Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# EditorConfig: https://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.rs]
indent_size = 4

[Makefile]
indent_style = tab
29 changes: 29 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: Bug Report
about: Report a bug or unexpected behavior
title: "fix: "
labels: bug
assignees: ""
---

## Describe the bug
A clear and concise description of the bug.

## To Reproduce
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '...'
3. See error

## Expected behavior
What you expected to happen.

## Screenshots
If applicable, add screenshots to help explain.

## Environment
- OS: [e.g. Windows 11, macOS 14, Ubuntu 24.04]
- enowX-Coder version: [e.g. latest main]

## Additional context
Add any other context about the problem here.
22 changes: 22 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: Feature Request
about: Suggest an idea or enhancement
title: "feat: "
labels: enhancement
assignees: ""
---

## Is your feature request related to a problem?
A clear and concise description of what the problem is.

## Describe the solution you'd like
What you want to happen.

## Describe alternatives you've considered
Other solutions or features you've considered.

## Use case
Who would benefit from this feature? How?

## Additional context
Add any other context, mockups, or screenshots here.
23 changes: 23 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Description
<!-- Describe what this PR does and why it's needed -->

## Type of Change
- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature
- [ ] Breaking change (fix or feature that would cause existing functionality to not work)
- [ ] Documentation update
- [ ] Refactor (no behavior change)

## How Has This Been Tested?
<!-- Describe the tests that you ran to verify your changes -->

- [ ] `cargo clippy -- -D warnings` passes (Rust)
- [ ] `bunx tsc --noEmit` passes (TypeScript)
- [ ] Manual testing steps below

## Checklist
- [ ] My code follows the project's style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] I have added tests that prove my fix is effective or that my feature works
57 changes: 57 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
frontend:
name: Frontend (TypeScript)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Type check
run: bunx tsc --noEmit

- name: Lint
run: bun lint 2>/dev/null || echo "No lint script"

- name: Build
run: bun run build

backend:
name: Backend (Rust)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install system deps
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Cache cargo registry
uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri

- name: Clippy (deny warnings)
run: cd src-tauri && cargo clippy -- -D warnings

- name: Tests
run: cd src-tauri && cargo test

- name: Build check
run: cd src-tauri && cargo check
82 changes: 82 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Contributing to enowX-Coder

Thank you for your interest in contributing! enowX-Coder is a Tauri-based AI code editor built with Rust + React + TypeScript.

## 🏗️ Architecture

- **Backend**: `src-tauri/` — Rust (Tauri v2)
- **Frontend**: `src/` — React + TypeScript
- **Database**: SQLite via `sqlx`
- **AI**: Streaming chat via OpenAI/Anthropic compatible providers

## 🚀 Getting Started

```bash
# Clone the repository
git clone https://github.com/kevinnft/enowX-Coder.git
cd enowX-Coder

# Install frontend dependencies
bun install

# Run in development mode
cargo tauri dev
```

## 📝 Commit Convention

We use [Conventional Commits](https://www.conventionalcommits.org/):

```
<type>(<scope>): <description>
```

| Type | Description |
|---|---|
| `feat` | New feature |
| `fix` | Bug fix |
| `refactor` | Code restructure, no behavior change |
| `chore` | Maintenance, tooling |
| `docs` | Documentation |
| `build` | Dependencies, build config |
| `test` | Adding/fixing tests |
| `perf` | Performance improvement |

Examples:
```
feat(chat): add model selector dropdown
fix(editor): resolve tab sync issue on file switch
refactor(agents): simplify prompt construction
docs: add setup guide for Linux
```

## 🌿 Git Workflow

- **Trunk-based development**: branch from `main`, short-lived branches only
- Delete branches after merge
- Never force push to `main`
- Use `git add -p` (interactive staging), never blind `git add .`

## 📋 Code Standards

### Rust
- Use `AppError` enum with `thiserror` — never `unwrap()` in production paths
- Commands are thin wrappers — all business logic in `services/`
- All Tauri commands must be `async`
- Use `#[serde(rename_all = "camelCase")]` on structs sent to frontend

### TypeScript / React
- Strict TypeScript — no `as any`, no `@ts-ignore`
- Follow existing component patterns

## 🧪 Pull Requests

Before submitting a PR:
1. Make sure `cargo clippy -- -D warnings` passes
2. Make sure `bunx tsc --noEmit` passes
3. Squash your commits into logical units
4. Write a clear description of what changes and why

## 🤝 Code of Conduct

We follow Contributor Covenant. Be respectful, constructive, and inclusive.
29 changes: 29 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Security Policy

## Supported Versions

| Version | Supported |
|---|---|
| Latest release | ✅ |

## Reporting a Vulnerability

We take security seriously. If you discover a security vulnerability, please:

1. **Do NOT open a public issue**
2. Email: `kevinnft@users.noreply.github.com`
3. Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (optional)

We will respond within 48 hours and work with you to resolve the issue.

## Security Practices

- API keys and provider credentials are stored locally only (`~/.local/share/enowx-coder/`)
- No telemetry or data collection
- SQLite database is local-only
- Provider API calls use HTTPS only
- All Rust code uses safe error handling (no `unwrap()` in production paths)
5 changes: 5 additions & 0 deletions src-tauri/clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
disallowed-methods = [
{ path = "std::option::Option::unwrap", reason = "use expect() with a message or handle the None case" },
{ path = "std::result::Result::unwrap", reason = "use expect() with a message or handle the Err case" },
{ path = "std::result::Result::expect", reason = "use proper error handling with AppError" },
]
5 changes: 5 additions & 0 deletions src-tauri/rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
edition = "2021"
max_width = 100
newline_style = "Unix"
use_field_init_shorthand = true
reorder_imports = true
29 changes: 29 additions & 0 deletions src-tauri/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,32 @@ impl From<tauri::Error> for AppError {
Self::Tauri(value.to_string())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_not_found_error() {
let err = AppError::NotFound("resource".to_string());
assert_eq!(err.to_string(), "Not found: resource");
}

#[test]
fn test_validation_error() {
let err = AppError::Validation("invalid input".to_string());
assert_eq!(err.to_string(), "Validation error: invalid input");
}

#[test]
fn test_cancelled_error() {
let err = AppError::Cancelled;
assert_eq!(err.to_string(), "Cancelled");
}

#[test]
fn test_error_to_string() {
let err: String = AppError::NotFound("test").into();
assert_eq!(err, "Not found: test");
}
}
20 changes: 20 additions & 0 deletions src-tauri/src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,23 @@ pub use provider::{fixed_base_url, Provider};
pub use provider_model::ProviderModelConfig;
pub use session::Session;
pub use tool_call::ToolCall;


#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_project_serialization() {
let p = Project {
id: 1,
name: "test-project".to_string(),
path: "/home/test/project".to_string(),
session_count: 0,
last_opened_at: "2025-01-01T00:00:00Z".to_string(),
created_at: "2025-01-01T00:00:00Z".to_string(),
};
let json = serde_json::to_string(&p).unwrap();
assert!(json.contains("test-project"));
}
}
Loading