Compare commits

..
254 Commits
Author SHA1 Message Date
semantic-release-bot 992e60980c chore(release): 1.19.6 [skip ci]
## [1.19.6](https://github.com/asepharyana/zesdex/compare/v1.19.5...v1.19.6) (2026-08-27)

### Performance Improvements

* **agent:** eksekusi tool read-only paralel seperti Claude Code ([74b1ad4](https://github.com/asepharyana/zesdex/commit/74b1ad43020a11ca27e60e3a24de0db5d1ab37b4))
2026-08-27 18:22:01 +00:00
asepharyana 74b1ad4302 perf(agent): eksekusi tool read-only paralel seperti Claude Code
Sebelumnya loop utama mengeksekusi semua tool call satu-per-satu
(sequential for loop). Seperti Claude Code, tool read-only yang
independen dalam satu pesan assistant (read/grep/glob/semantic_search
dsb.) kini dijalankan konkuren dengan bounded parallelism (max 8),
mengurangi latensi per turn secara signifikan untuk beban coding.

- feat(registry): tool_is_parallel_safe() — whitelist tool read-only
  yang aman dijalankan paralel; tool mutating/shell tetap sequential
- feat(executor): is_parallel_safe() delegasi ke registry; ToolExecutor
  trait Default=false (konservatif)
- fix(application): execute_tool_calls_in_parallel() — join_all +
  semaphore bounded 8, hasil dikumpulkan dalam URUTAN panggilan asli
  (kontrak OpenAI/Anthropic tool-result ordering)
- loop utama: batch paralel hanya jika SEMUA tool parallel-safe; jika
  ada satu tool mutating, jatuh balik ke jalur sequential aman
- test: +2 registry test, +2 application test (konkurensi & urutan,
  fallback batch mutating)
2026-08-28 01:17:26 +07:00
semantic-release-bot 9ad04cf819 chore(release): 1.19.5 [skip ci]
## [1.19.5](https://github.com/asepharyana/zesdex/compare/v1.19.4...v1.19.5) (2026-08-27)

### Bug Fixes

* **api:** model Opus default pakai claude-opus-5 (bukan -4-8) ([b28a5fe](https://github.com/asepharyana/zesdex/commit/b28a5fe384fd45255a6b249c7febd3b4ffc0fd2f))
* **api:** update zesdex packages to version 1.19.4 ([b46935c](https://github.com/asepharyana/zesdex/commit/b46935c606d4f68ea227c7db27e4c2aa9b4e373c))
2026-08-27 17:36:59 +00:00
asepharyana b46935c606 fix(api): update zesdex packages to version 1.19.4 2026-08-28 00:32:27 +07:00
asepharyana b28a5fe384 fix(api): model Opus default pakai claude-opus-5 (bukan -4-8)
Model terbaru di 9router adalah claude-opus-5. Update semua jalur
model default Opus:

- fix(app_config_repo): fallback default_model custom_model.unwrap_or
  -> claude-opus-5; model_roles list claude-opus-5
- fix(app_config): router provider default_model -> claude-opus-5
- fix(settings test): assertion claude-opus-5
- fix(data): ~/.local/share/zesdex/settings.json model -> claude-opus-5
2026-08-28 00:32:06 +07:00
semantic-release-bot b66898ea28 chore(release): 1.19.4 [skip ci]
## [1.19.4](https://github.com/asepharyana/zesdex/compare/v1.19.3...v1.19.4) (2026-08-27)

### Bug Fixes

* **api:** model claude selalu pakai Opus dari settings.json, bukan deepseek ([9aca45c](https://github.com/asepharyana/zesdex/commit/9aca45cb65d6913d14fecc10d70c180934f69d74))
2026-08-27 17:05:10 +00:00
asepharyana 9aca45cb65 fix(api): model claude selalu pakai Opus dari settings.json, bukan deepseek
TUI turn.rs & daemon handler.rs ambil model langsung dari
settings.model (tersimpan 'deepseek-v4-flash-free' di
~/.local/share/zesdex/settings.json) padahal provider sudah 'claude'.

- feat(domain): resolve_effective_model() — saat provider claude, model
  diambil dari app_config provider claude (default_model=claude-opus-4-8
  hasil deteksi ~/.claude/settings.json), menang atas settings.model basi.
  Provider non-claude tetap hormati settings.model user.
- fix(tui): turn.rs pakai resolve_effective_model (bukan settings.model)
- fix(daemon): handler.rs run_turn + compaction pakai resolve_effective_model
- fix(data): ~/.local/share/zesdex/settings.json model deepseek -> claude-opus-4-8
- test: 3 unit test resolve_effective_model
2026-08-28 00:00:32 +07:00
semantic-release-bot 4dccf0cee4 chore(release): 1.19.3 [skip ci]
## [1.19.3](https://github.com/asepharyana/zesdex/compare/v1.19.2...v1.19.3) (2026-08-27)

### Bug Fixes

* **api:** model Opus pakai URL + API custom dari ~/.claude/settings.json ([1f91b44](https://github.com/asepharyana/zesdex/commit/1f91b447080e7106201d77585edb7d38b74e34bb))
2026-08-27 16:49:19 +00:00
asepharyana 1f91b44708 fix(api): model Opus pakai URL + API custom dari ~/.claude/settings.json
Perbaiki provider claude agar selalu refresh dari settings.json dan
menjadi default (claude-opus-4-8) setiap startup:

- fix(app_config_repo): ganti or_insert -> insert untuk provider claude —
  base_url/key dari ~/.claude/settings.json selalu di-refresh, tidak
  tertutup snapshot lama app_config.json.
- fix(app_config_repo): hapus kondisi default_provider == default — saat
  settings.json terdeteksi, default_provider='claude' dan
  default_model='claude-opus-4-8' SELALU di-set (sebelumnya skip kalau
  user pernah ganti provider).
- fix(subagent/provider): resolve_subagent_provider fallback ke
  app_config.default_provider/default_model kalau settings.provider/model
  kosong — subagent ikut pakai Opus.
- test: 4 unit test (parse settings.json, refresh stale provider, custom
  model, env fallback). Verified live: settings.json terbaca (9router URL
  + key).
2026-08-27 23:45:30 +07:00
semantic-release-bot b25929824a chore(release): 1.19.2 [skip ci]
## [1.19.2](https://github.com/asepharyana/zesdex/compare/v1.19.1...v1.19.2) (2026-08-27)

### Performance Improvements

* **agent:** stabilkan async & parallel — satu runtime, bounded concurrency, isolasi error ([6a98d52](https://github.com/asepharyana/zesdex/commit/6a98d52d54a69f78710d852a69dda3ac0a4ead31))
2026-08-27 16:30:31 +00:00
asepharyana 3fd9a2b2db chore: sinkronkan Cargo.lock dengan versi 1.19.1 2026-08-27 23:26:37 +07:00
asepharyana 6a98d52d54 perf(agent): stabilkan async & parallel — satu runtime, bounded concurrency, isolasi error
Seperti Claude Code: satu runtime shared, concurrency dibatasi, error
subagent terisolasi (satu node gagal tidak menggagalkan cycle).

- feat(runtime): global tokio runtime via OnceLock — ganti 9+ titik
  Runtime::new() per tool call (spawn, parallel_delegate, workflow,
  explore, dir_cache, daemon handler). Hemat resource, hilangkan panic
  path Runtime::new().expect() di daemon compaction.
- fix(workflow): execute_cycle ganti try_join_all (fail-fast) →
  buffer_unordered(8) + isolasi error per node; node gagal di-log dan
  diganti [ERROR], hasil node lain tetap dipakai (Claude Code-style).
- fix(parallel_delegate): spawn subagent dibatasi per batch max_parallel
  (tidak unbounded threads).
- perf(subagent): run_agent adaptif max_tokens (800/1600/4096), temp 0.2,
  truncate tool output 12k, error-recovery note utk tool error berulang.
- test: runtime singleton + block_on (2 test).
2026-08-27 23:25:44 +07:00
semantic-release-bot 3847c0e6fd chore(release): 1.19.1 [skip ci]
## [1.19.1](https://github.com/asepharyana/zesdex/compare/v1.19.0...v1.19.1) (2026-08-27)

### Performance Improvements

* **agent:** rombak alur AI agent — adaptif, hemat token, self-healing ([eac0443](https://github.com/asepharyana/zesdex/commit/eac0443c4c3b8bfcbefd4bad9554168fb6525b94))
2026-08-27 16:10:48 +00:00
asepharyana 5023e5dfa1 chore: sinkronkan Cargo.lock dengan versi 1.19.0 2026-08-27 23:06:57 +07:00
asepharyana eac0443c4c perf(agent): rombak alur AI agent — adaptif, hemat token, self-healing
Ganti explore phase MANDATORY (3 subagent tiap turn, boros) dengan
tool explore_codebase yang DIPUTUSKAN agent sendiri (lazy, token-aware):
- hapus ExploreService trait + with_explore + Phase 0 dari turn loop
- ExploreServiceImpl kini jadi tool 'explore_codebase' (1 context-scout
  subagent, read-only, cap output 4k chars)
- system prompt: instruksi TOKEN BUDGET (jawab langsung utk query simple,
  panggil explore_codebase sekali utk task kompleks)

Loop utama kini adaptif & self-healing:
- max_tokens adaptif (800/1600/4096 by request length) — bukan selalu 4096
- temperature 0.2 saat tool-calling, 0.7 utk final answer
- ErrorTracker: deteksi tool error berulang → inject recovery note,
  stop setelah 8 error total (bukan 50 iterasi sia-sia)
- auto-compact history > 60k chars sebelum LLM call
- tool output di-truncate ke 12k chars sebelum masuk konteks

Tambah 8 unit test (truncation, adaptive tokens, error tracker).
2026-08-27 23:06:37 +07:00
asepharyana 14f3eae62a a 2026-08-27 23:06:37 +07:00
semantic-release-bot aec53651ed chore(release): 1.19.0 [skip ci]
# [1.19.0](https://github.com/asepharyana/zesdex/compare/v1.18.4...v1.19.0) (2026-08-27)

### Features

* hapus fitur LSP bawaan (language server protocol) ([93f3c2a](https://github.com/asepharyana/zesdex/commit/93f3c2a3572511b5a84f244980ad71bd1b455e70))
2026-08-27 15:49:38 +00:00
asepharyana 93f3c2a357 feat: hapus fitur LSP bawaan (language server protocol)
Hapus seluruh pipeline LSP (client, manager, provisioner, dan 7 tool
lsp_*) dari codebase:

- apps/infrastructure/src/lsp/ (client.rs, manager.rs, provisioner/*)
- apps/infrastructure/src/tools/lsp/ (connect, disconnect, diagnostics,
  hover, completion, definition, references)
- ToolCtx/ToolCtxBuilder: hapus field lsp_manager
- Daemon state: hapus lsp_manager, lsp_provision_msgs, shutdown_lsp
- Registry: hapus registrasi 7 tool lsp_*
- Settings: hapus lsp_auto_provision + lsp_languages
- Agent definitions: hapus lsp_* dari allowed tools coder/reviewer
- Cargo: hapus dependency lsp-types (workspace + infra)
- Update dokumentasi mod + arch_audit forbidden list

Verifikasi: cargo check/clippy/test semua hijau (54 test), tidak ada
referensi lsp_* tersisa di luar CHANGELOG.
2026-08-27 22:38:21 +07:00
semantic-release-bot 9ea3d361b1 chore(release): 1.18.4 [skip ci]
## [1.18.4](https://github.com/asepharyana/zesdex/compare/v1.18.3...v1.18.4) (2026-08-27)

### Performance Improvements

* **tui:** render streaming token secara inkremental + kurangi redraw sia-sia ([2717216](https://github.com/asepharyana/zesdex/commit/271721694beb62e9fa5ff932312b293aa1d56823))
2026-08-27 15:33:34 +00:00
asepharyana 271721694b perf(tui): render streaming token secara inkremental + kurangi redraw sia-sia
- fix(view): token streaming kini benar-benar tampil — sebelumnya cache
  display_lines tidak pernah di-rebuild saat pesan terakhir berubah
  (msg_count == cached_count), jadi teks AI streaming tidak pernah muncul
  sampai pesan baru/resize
- perf(view): streaming kini hanya re-render pesan TERAKHIR (splice di
  batas cached_last_start) → O(konten baru) per token, bukan O(seluruh
  history); guard cached_last_len mencegah re-render pada frame spinner
  tanpa token baru
- perf(run): skip chrono::Utc::now() + drain toasts saat tidak ada toast
- perf(misc): drain_expired_toasts tidak lagi clone seluruh daftar toast
- perf(view): render_toasts fast-path saat toasts kosong
2026-08-27 22:23:28 +07:00
semantic-release-bot 171597ca05 chore(release): 1.18.3 [skip ci]
## [1.18.3](https://github.com/asepharyana/zesdex/compare/v1.18.2...v1.18.3) (2026-08-27)

### Bug Fixes

* **api:** cegah race condition pada register users.json (TOCTOU) ([884b19c](https://github.com/asepharyana/zesdex/commit/884b19ccb5fbcaa6b29cb41dc978386cf7b1b3f9))
* **api:** perbaiki keamanan auth & WebSocket, tambah rate limiting ([6db00b2](https://github.com/asepharyana/zesdex/commit/6db00b22663839a6a975ae978058b894900c71de))
* **build:** perbaiki referensi paket zesdex-gateway dan sinkronisasi versi nix ([6d3f491](https://github.com/asepharyana/zesdex/commit/6d3f4918bfea06b106d4fe75adf58e6a29aca2a5))
* **build:** perbaiki referensi paket zesdex-gateway di Dockerfile & default.nix ([7f64423](https://github.com/asepharyana/zesdex/commit/7f644236158f66fcc106ec55e437ebf28ee1cca1))
2026-08-27 15:19:16 +00:00
asepharyana 7b0b53671f style: format seluruh workspace dengan cargo fmt
Menyeragamkan format kode sesuai rustfmt (126 file). Sebelumnya
lefthook pre-commit 'cargo fmt --check' akan gagal pada commit apa pun.
2026-08-27 22:10:28 +07:00
asepharyana 884b19ccb5 fix(api): cegah race condition pada register users.json (TOCTOU)
- Tambah users_lock (Mutex) di ApiState untuk serialisasi read-modify-write
  users.json pada endpoint register; lock hanya dipegang selama operasi
  file sinkron (tidak pernah lintas .await, menjaga future tetap Send)
- Hash password dihitung sebelum lock sehingga request concurrent tidak
  saling blokir selama hashing Argon2
2026-08-27 22:09:22 +07:00
asepharyana 6db00b2266 fix(api): perbaiki keamanan auth & WebSocket, tambah rate limiting
Security fixes hasil audit:
- fix(auth): refresh token kini memakai claim typ=refresh; access token
  tidak bisa dipakai sebagai refresh token (sebelumnya bisa — eskalasi
  masa berlaku 1 jam -> 7 hari)
- fix(api): layer JWT hanya melindungi route /sessions dan /chat;
  /auth/login, /auth/register, /auth/refresh, /health kini publik
  (sebelumnya semua route 401-lock, API tidak bisa dipakai sama sekali)
- fix(ws): endpoint /ws kini memverifikasi token ZESDEX_WS_TOKEN via
  query param jika env diset (mencegah pemakaian LLM proxy terbuka)
- feat(api): rate limiting login/register/refresh (20 request / 10 menit
  per client IP) memakai RateLimiter yang tadinya dead code
- test(jwt): tambah unit test token type access vs refresh + expired
2026-08-27 22:04:32 +07:00
asepharyana 7f64423615 fix(build): perbaiki referensi paket zesdex-gateway di Dockerfile & default.nix
- Dockerfile & default.nix: ganti zesdex-backend -> zesdex-gateway (binary zesdex)
- flake.nix & default.nix: versi 1.13.0 -> 1.18.2 mengikuti Cargo.toml
- chore(ci): drop cargo build --release dari check job, tambah cargo fmt --check
2026-08-27 21:52:25 +07:00
asepharyana 6d3f4918bf fix(build): perbaiki referensi paket zesdex-gateway dan sinkronisasi versi nix
- Dockerfile & default.nix: ganti zesdex-backend -> zesdex-gateway (binary zesdex)
- flake.nix & default.nix: versi 1.13.0 -> 1.18.2
- Cargo.lock: sinkronkan versi workspace member (1.18.0 -> 1.18.2)
- perf(search): kurangi alokasi per-query di semantic search (Vec<String> -> Vec<&str>)
- chore(ci): drop cargo build release dari check job, tambah fmt check
- chore: tambah .dockerignore, perbaiki trailing newline .gitignore
2026-08-27 21:50:35 +07:00
asepharyana 448eb5d462 delete: remove architecture, backend, data, dependencies, development, and frontend documentation files
add: create flake.lock for Nix package management
2026-08-27 21:30:42 +07:00
semantic-release-bot 924576d2ee chore(release): 1.18.2 [skip ci]
## [1.18.2](https://github.com/asepharyana/zesdex/compare/v1.18.1...v1.18.2) (2026-08-20)

### Bug Fixes

* **nix:** add perl to nativeBuildInputs for openssl-sys Configure ([033f964](https://github.com/asepharyana/zesdex/commit/033f964be0c695106eef74329524ad7b4b8dba14))
* **nix:** correct cargoBuildFlags package name zesdex-backend -> zesdex-gateway ([2de5b57](https://github.com/asepharyana/zesdex/commit/2de5b57133f6c7295d8a85e63cb86504ea2a7d3e))
2026-08-20 12:04:35 +00:00
mytheclipsebotreview 033f964be0 fix(nix): add perl to nativeBuildInputs for openssl-sys Configure
openssl-sys vendors an OpenSSL source that runs ./Configure via perl during
the build phase. The Nix sandbox had no perl on PATH, causing the gatekeeper
build of the zesdex binary to fail ('Command failed ... openssl-build ...
Configure'). Adding perl to nativeBuildInputs makes the vendored build
resolve. This unblocks the GHA-only deploy workflow.
2026-08-20 19:00:29 +07:00
mytheclipsebotreview 2de5b57133 fix(nix): correct cargoBuildFlags package name zesdex-backend -> zesdex-gateway
The gateway crate's package name is zesdex-gateway (not zesdex-backend);
the stale -p flag caused  to fail in CI with
'package ID specification zesdex-backend did not match any packages'.
This unblocks the GHA-only deploy workflow.
2026-08-20 18:44:21 +07:00
mytheclipsebotreview d1929f2fd4 ci: add nix build-and-deploy GitHub Actions workflow [skip ci]
Adds the canonical Nix CI/CD deploy workflow (install Nix, build .#default,
copy to VPS via SSH, update profile, systemctl restart) previously missing
from this repo. Enforces push-to-GitHub + GHA deploy only (no direct deploy).
2026-08-20 18:23:30 +07:00
semantic-release-bot 14aa1785f8 chore(release): 1.18.1 [skip ci]
## [1.18.1](https://github.com/asepharyana/zesdex/compare/v1.18.0...v1.18.1) (2026-08-01)

### Bug Fixes

* **nix:** restrict flake to x86_64-linux (nixpkgs 26.11 dropped darwin) ([0e0fd5d](https://github.com/asepharyana/zesdex/commit/0e0fd5df05e53a6fa17d481825f1a8c567214d0e))
2026-08-01 11:15:52 +00:00
asepharyana 0e0fd5df05 fix(nix): restrict flake to x86_64-linux (nixpkgs 26.11 dropped darwin) 2026-08-01 18:03:50 +07:00
asepharyana 07f547eea8 ci: publish flake to FlakeHub (rolling) 2026-08-01 17:58:44 +07:00
asepharyana f918d44c8d docs: clean up duplicate v1.18.0 changelog entries
CI / Check (push) Canceled after 0s
Release / Test (push) Canceled after 0s
Release / Semantic Release (push) Canceled after 0s
2026-07-22 16:17:18 +07:00
semantic-release-bot 0d06875bb7 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-22)

### Bug Fixes

* add .releaserc.json for semantic-release configuration ([047d718](https://github.com/asepharyana/zesdex/commit/047d7183d72adaa0dd1a18a7f92b22d67d5aa85f))
* **clippy:** replace type annotation with type alias + .insert() to avoid trivial_cast ([ffefa8c](https://github.com/asepharyana/zesdex/commit/ffefa8c07facbba83778f426ca4715569556b08a))
* **rust:** remove unused imports, variables, and dead code causing CI build failures ([eb8cc17](https://github.com/asepharyana/zesdex/commit/eb8cc1799359a5ef5b4a4ee3a4202b87e80bfe6c))
* **rust:** resolve all clippy warnings treated as errors in CI ([6b90c7e](https://github.com/asepharyana/zesdex/commit/6b90c7eb0d17d9281a377454e76dcc88a4232bc7))
* **tui:** resolve remaining clippy errors in workspace ([eed4025](https://github.com/asepharyana/zesdex/commit/eed4025918de65eb2f3fd98cd3350d62f3322132))

### Features

* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* Add SOLID principles and TDD reference documentation ([55677dd](https://github.com/asepharyana/zesdex/commit/55677dd67100813a5ed2b0bbf02257b57875ea07))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* **best_practice:** add code quality scanning and commit message validation ([8ecc588](https://github.com/asepharyana/zesdex/commit/8ecc588a3e125dc6a4b2e7eb4c12c6b344449c07))
* centralize default constants and refactor overlay enter handling in TUI ([d615090](https://github.com/asepharyana/zesdex/commit/d615090dcd34bdb93be22c1c7ce4ba674363c258))
* enhance context gathering in auto-review engine and agent runner ([dcc8c3e](https://github.com/asepharyana/zesdex/commit/dcc8c3ee42ef568843e04143048d799bc0882288))
* enhance explore phase with TUI workflow event handling ([b3a4d13](https://github.com/asepharyana/zesdex/commit/b3a4d131d13d94bd307720cb50c2d02dedf92873))
* implement Component trait for modular UI components and refactor TUI views to use it ([d59713d](https://github.com/asepharyana/zesdex/commit/d59713d3e3aa4325f9753bbddd068654e442f6ef))
* implement mandatory explore phase with parallel subagents ([f368f3a](https://github.com/asepharyana/zesdex/commit/f368f3a1c0d2df02eb50542a81bcff96d9cdc420))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* refactor auto-review engine to use spawn_subagent for improved thread handling ([094eb4b](https://github.com/asepharyana/zesdex/commit/094eb4b8baa5abd878dcf5b611cf615955bc79eb))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** introduce comprehensive state management for TUI interface ([8c58faf](https://github.com/asepharyana/zesdex/commit/8c58faf2920b7341dd50ace15044ff113cefb576))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-22 07:33:49 +00:00
Cyrene (Mem) ffefa8c07f fix(clippy): replace type annotation with type alias + .insert() to avoid trivial_cast
- Use type alias ExtDispatch for the HashMap type (fixes type_complexity)
- Use .insert() instead of HashMap::from([...]) to avoid fn ptr trivial casts
- Remove all as fn(...) casts to avoid clippy::trivial_casts
2026-07-22 14:29:50 +07:00
semantic-release-bot 883908ab55 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-22)

### Bug Fixes

* add .releaserc.json for semantic-release configuration ([047d718](https://github.com/asepharyana/zesdex/commit/047d7183d72adaa0dd1a18a7f92b22d67d5aa85f))
* **rust:** remove unused imports, variables, and dead code causing CI build failures ([eb8cc17](https://github.com/asepharyana/zesdex/commit/eb8cc1799359a5ef5b4a4ee3a4202b87e80bfe6c))
* **rust:** resolve all clippy warnings treated as errors in CI ([6b90c7e](https://github.com/asepharyana/zesdex/commit/6b90c7eb0d17d9281a377454e76dcc88a4232bc7))
* **tui:** resolve remaining clippy errors in workspace ([eed4025](https://github.com/asepharyana/zesdex/commit/eed4025918de65eb2f3fd98cd3350d62f3322132))

### Features

* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* Add SOLID principles and TDD reference documentation ([55677dd](https://github.com/asepharyana/zesdex/commit/55677dd67100813a5ed2b0bbf02257b57875ea07))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* **best_practice:** add code quality scanning and commit message validation ([8ecc588](https://github.com/asepharyana/zesdex/commit/8ecc588a3e125dc6a4b2e7eb4c12c6b344449c07))
* centralize default constants and refactor overlay enter handling in TUI ([d615090](https://github.com/asepharyana/zesdex/commit/d615090dcd34bdb93be22c1c7ce4ba674363c258))
* enhance context gathering in auto-review engine and agent runner ([dcc8c3e](https://github.com/asepharyana/zesdex/commit/dcc8c3ee42ef568843e04143048d799bc0882288))
* enhance explore phase with TUI workflow event handling ([b3a4d13](https://github.com/asepharyana/zesdex/commit/b3a4d131d13d94bd307720cb50c2d02dedf92873))
* implement Component trait for modular UI components and refactor TUI views to use it ([d59713d](https://github.com/asepharyana/zesdex/commit/d59713d3e3aa4325f9753bbddd068654e442f6ef))
* implement mandatory explore phase with parallel subagents ([f368f3a](https://github.com/asepharyana/zesdex/commit/f368f3a1c0d2df02eb50542a81bcff96d9cdc420))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* refactor auto-review engine to use spawn_subagent for improved thread handling ([094eb4b](https://github.com/asepharyana/zesdex/commit/094eb4b8baa5abd878dcf5b611cf615955bc79eb))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** introduce comprehensive state management for TUI interface ([8c58faf](https://github.com/asepharyana/zesdex/commit/8c58faf2920b7341dd50ace15044ff113cefb576))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-22 07:26:13 +00:00
Cyrene (Mem) eed4025918 fix(tui): resolve remaining clippy errors in workspace
- turn.rs: remove needless ref borrowing
- view/mod.rs: use unit struct directly instead of ::default() for
  ChatComponent, InputComponent, StatusBarComponent, SidebarComponent

These were uncovered after fixing the infrastructure crate errors.
2026-07-22 14:22:11 +07:00
Cyrene (Mem) 6b90c7eb0d fix(rust): resolve all clippy warnings treated as errors in CI
Fix 18 clippy errors across 7 files:
- lib.rs: change doc comment to regular comment (empty line after doc)
- arch_audit.rs: replace format!() with string literal, use is_none_or
- code_quality.rs: collapsible if, map_or → is_none_or
- commit.rs: collapsible match guard
- explore.rs: needless_range_loop → iterator enumerate
- skills.rs: map_or(false,...) → is_some_and
- semantic_search.rs: map_or → is_none_or, sort_by → sort_by_key,
  remove explicit type to avoid type_complexity

CI was failing with 'error: could not compile zesdex-infrastructure
due to 18 previous errors' at clippy step.
2026-07-22 14:16:56 +07:00
semantic-release-bot 958645ed7f chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-22)

### Bug Fixes

* add .releaserc.json for semantic-release configuration ([047d718](https://github.com/asepharyana/zesdex/commit/047d7183d72adaa0dd1a18a7f92b22d67d5aa85f))
* **rust:** remove unused imports, variables, and dead code causing CI build failures ([eb8cc17](https://github.com/asepharyana/zesdex/commit/eb8cc1799359a5ef5b4a4ee3a4202b87e80bfe6c))

### Features

* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* Add SOLID principles and TDD reference documentation ([55677dd](https://github.com/asepharyana/zesdex/commit/55677dd67100813a5ed2b0bbf02257b57875ea07))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* **best_practice:** add code quality scanning and commit message validation ([8ecc588](https://github.com/asepharyana/zesdex/commit/8ecc588a3e125dc6a4b2e7eb4c12c6b344449c07))
* centralize default constants and refactor overlay enter handling in TUI ([d615090](https://github.com/asepharyana/zesdex/commit/d615090dcd34bdb93be22c1c7ce4ba674363c258))
* enhance context gathering in auto-review engine and agent runner ([dcc8c3e](https://github.com/asepharyana/zesdex/commit/dcc8c3ee42ef568843e04143048d799bc0882288))
* enhance explore phase with TUI workflow event handling ([b3a4d13](https://github.com/asepharyana/zesdex/commit/b3a4d131d13d94bd307720cb50c2d02dedf92873))
* implement Component trait for modular UI components and refactor TUI views to use it ([d59713d](https://github.com/asepharyana/zesdex/commit/d59713d3e3aa4325f9753bbddd068654e442f6ef))
* implement mandatory explore phase with parallel subagents ([f368f3a](https://github.com/asepharyana/zesdex/commit/f368f3a1c0d2df02eb50542a81bcff96d9cdc420))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* refactor auto-review engine to use spawn_subagent for improved thread handling ([094eb4b](https://github.com/asepharyana/zesdex/commit/094eb4b8baa5abd878dcf5b611cf615955bc79eb))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** introduce comprehensive state management for TUI interface ([8c58faf](https://github.com/asepharyana/zesdex/commit/8c58faf2920b7341dd50ace15044ff113cefb576))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-22 07:01:54 +00:00
Cyrene (Mem) eb8cc17993 fix(rust): remove unused imports, variables, and dead code causing CI build failures
- Remove unused imports: AtomicBool, Future (provider.rs), debug (executor.rs)
- Remove unused import WorkflowScript (workflow.rs)
- Remove unused variables: tool_name, t_ctx, t_args (executor.rs)
- Remove dead variable class_indent (semantic_search.rs)

CI was failing with 'error: could not compile zesdex-infrastructure
due to 10 previous errors' caused by -D warnings treating unused
code as compilation errors.
2026-07-22 13:57:50 +07:00
asepharyana b3a4d131d1 feat: enhance explore phase with TUI workflow event handling 2026-07-21 07:47:35 +07:00
asepharyana f368f3a1c0 feat: implement mandatory explore phase with parallel subagents
- Added `ExploreService` trait and `ExploreServiceImpl` struct to handle the exploration of codebase context before agent turns.
- Implemented three parallel subagents: Code Structure, Symbol Index, and Semantic Context, each with specific directives.
- Integrated the explore phase into the agent turn process, ensuring that each turn starts with a consolidated context message.
- Enhanced `spawn_agent_turn` function to include explore service wiring and context preparation.
2026-07-21 07:41:28 +07:00
asepharyana 8ecc588a3e feat(best_practice): add code quality scanning and commit message validation
- Implemented a code quality scanner that checks for common clean-code violations in Rust source files, including missing documentation, usage of `.unwrap()` in production code, and commented-out code.
- Introduced a commit message validator that follows the Conventional Commits specification, ensuring proper formatting and providing suggestions for invalid messages.
- Created a unified BestPracticeEngine to encapsulate the functionalities of skills, architecture audits, code quality checks, and commit message validation.
- Added tests for both the code quality scanner and commit message validator to ensure reliability and correctness.
2026-07-21 07:21:22 +07:00
asepharyana 55677dd671 feat: Add SOLID principles and TDD reference documentation
- Created solid.md to document the SOLID principles for clean code practices.
- Created tdd.md to outline Test Driven Development principles and practices.
- Added kana-rust-backend-best-practice.md as a reference guide for building a Rust backend using Axum and SeaORM.
- Established push-flow-convention.md to enforce pre-commit and pre-push hooks with versioning rules.
- Introduced AGENTS.md to provide guidance on best practices and available commands for Kilo.
- Configured kilo.json to include new skills and agents for enhanced functionality.
- Added lefthook.yml for managing git hooks to ensure code quality and adherence to conventions.
2026-07-21 07:10:17 +07:00
asepharyana d615090dcd feat: centralize default constants and refactor overlay enter handling in TUI 2026-07-21 07:00:15 +07:00
asepharyana 8c58faf292 feat(tui): introduce comprehensive state management for TUI interface
- Add AppStateRest as the central state struct for managing TUI state.
- Implement InputState for handling user input, autocomplete, and history.
- Create MiscState to manage overlays, notifications, and editor state.
- Introduce ScrollState for viewport scrolling functionality.
- Develop TranscriptCache for efficient message rendering in the chat pane.
- Implement SimpleAgent and SimpleWorkflowEngine for agent lifecycle management.
- Add helper functions for managing effort levels and token counting.
- Organize state-related modules for better maintainability and clarity.
2026-07-21 06:42:53 +07:00
asepharyana 802346f909 Refactor subagent and workflow domain models; migrate access tiers and events to domain module
- Moved `AccessTier` and `SubagentEvent` enums to `zesdex_domain::subagent`.
- Consolidated workflow-related types into `zesdex_domain::workflow`.
- Updated references across the codebase to use the new domain models.
- Refactored tool execution logic to utilize a new `ToolExecutor` trait.
- Enhanced `AgentTurnService` to handle tool calls and events more effectively.
- Adjusted API handlers and state management to align with new domain structure.
2026-07-21 06:42:53 +07:00
semantic-release-bot 552bc5bc63 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Bug Fixes

* add .releaserc.json for semantic-release configuration ([047d718](https://github.com/asepharyana/zesdex/commit/047d7183d72adaa0dd1a18a7f92b22d67d5aa85f))

### Features

* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* enhance context gathering in auto-review engine and agent runner ([dcc8c3e](https://github.com/asepharyana/zesdex/commit/dcc8c3ee42ef568843e04143048d799bc0882288))
* implement Component trait for modular UI components and refactor TUI views to use it ([d59713d](https://github.com/asepharyana/zesdex/commit/d59713d3e3aa4325f9753bbddd068654e442f6ef))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* refactor auto-review engine to use spawn_subagent for improved thread handling ([094eb4b](https://github.com/asepharyana/zesdex/commit/094eb4b8baa5abd878dcf5b611cf615955bc79eb))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 23:11:52 +00:00
asepharyana d59713d3e3 feat: implement Component trait for modular UI components and refactor TUI views to use it 2026-07-21 06:08:00 +07:00
semantic-release-bot 6ab532018a chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Bug Fixes

* add .releaserc.json for semantic-release configuration ([047d718](https://github.com/asepharyana/zesdex/commit/047d7183d72adaa0dd1a18a7f92b22d67d5aa85f))

### Features

* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* enhance context gathering in auto-review engine and agent runner ([dcc8c3e](https://github.com/asepharyana/zesdex/commit/dcc8c3ee42ef568843e04143048d799bc0882288))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* refactor auto-review engine to use spawn_subagent for improved thread handling ([094eb4b](https://github.com/asepharyana/zesdex/commit/094eb4b8baa5abd878dcf5b611cf615955bc79eb))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 10:48:37 +00:00
asepharyana 047d7183d7 fix: add .releaserc.json for semantic-release configuration
- Configure branches, plugins, and release workflow for Rust project
- Fixes Release workflow failing with 'tag already exists'
2026-07-20 17:44:33 +07:00
semantic-release-bot 4d85e5144b chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* enhance context gathering in auto-review engine and agent runner ([dcc8c3e](https://github.com/asepharyana/zesdex/commit/dcc8c3ee42ef568843e04143048d799bc0882288))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* refactor auto-review engine to use spawn_subagent for improved thread handling ([094eb4b](https://github.com/asepharyana/zesdex/commit/094eb4b8baa5abd878dcf5b611cf615955bc79eb))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 10:36:16 +00:00
asepharyana dcc8c3ee42 feat: enhance context gathering in auto-review engine and agent runner 2026-07-20 17:32:31 +07:00
semantic-release-bot 289c58ef36 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* refactor auto-review engine to use spawn_subagent for improved thread handling ([094eb4b](https://github.com/asepharyana/zesdex/commit/094eb4b8baa5abd878dcf5b611cf615955bc79eb))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 10:29:23 +00:00
asepharyana 094eb4b8ba feat: refactor auto-review engine to use spawn_subagent for improved thread handling 2026-07-20 17:25:23 +07:00
asepharyana dd7825b481 refactor: streamline agent turn handling and background review process 2026-07-20 17:25:23 +07:00
semantic-release-bot 4c186b62d4 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 10:03:25 +00:00
asepharyana fef3c925cd feat: add semantic search tool for code symbol indexing and searching
- Implemented a new tool for semantic code search that indexes Rust code symbols (functions, structs, enums, traits, modules) and allows searching by name, concept, or meaning.
- Introduced a symbol index structure with methods for rebuilding the index and searching symbols.
- Added regex patterns for extracting various code symbols from Rust source files.
- Implemented scoring logic for search results based on exact matches, prefix matches, and context relevance.
- Created a web search tool that interacts with a SearXNG instance to fetch documentation and API information based on user queries.
- Added a diff preview overlay for rendering git diff output with color-coded additions and deletions in a TUI interface.
2026-07-20 16:59:27 +07:00
semantic-release-bot 785ae19757 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 09:42:13 +00:00
asepharyana 873f870e23 feat(agent): add AI summarization for conversation history compacting 2026-07-20 16:38:21 +07:00
semantic-release-bot 54927f692f chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 09:33:26 +00:00
asepharyana efcd191f96 feat(agent): implement agent execution engine and turn handling with background processing 2026-07-20 16:29:39 +07:00
semantic-release-bot 2e8a4f2443 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 09:20:09 +00:00
asepharyana 2f5f62ab09 feat(tui): add rich context information including active jobs, README snippet, and recent git history 2026-07-20 16:16:26 +07:00
asepharyana 919435eb84 feat(tui): integrate rich context builder into agent turn process 2026-07-20 16:16:26 +07:00
asepharyana bed9f8cff6 feat(tui): enhance system prompt with workspace structure information 2026-07-20 16:16:26 +07:00
asepharyana 6c7995f5f5 feat(llm): increase max retries for streaming requests from 3 to 10
refactor(shell): remove unused debug logging from tracing imports
2026-07-20 16:16:26 +07:00
asepharyana 7ea226509c feat(llm): improve UTF-8 handling in response processing to prevent infinite loops
feat(shell): enhance output capturing by using threads for stdout and stderr
feat(tui): update usage widget to display token counts and provider/model information
refactor(tui): simplify status bar rendering by removing unnecessary token calculations
2026-07-20 16:16:26 +07:00
semantic-release-bot 6bef4a3f82 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 08:57:39 +00:00
asepharyana 16494d4b1e Enhance logging and documentation across utility tools and TUI overlays
- Added tracing instrumentation and improved logging messages in the Pong, Todofinish, and Todowrite tools for better debugging and monitoring.
- Enhanced documentation comments for clarity on tool functionalities and workflows.
- Implemented tracing in WorkflowRun, NoteFinding, ReadFindings, and HiveMind tools to track execution phases and findings.
- Updated TUI overlays (e.g., Bash, Clear Confirm, Editor, Effort Level, Help, Key Input, Learning, Loading, MCP, Model Selector, Plan, Quit Confirm, Rewind, Settings, Todo, Usage) with debug logging to capture rendering details.
- Improved the status bar and workflow panel rendering with additional debug information.
- Added tracing to various utility functions to facilitate better performance monitoring and error tracking.
2026-07-20 15:53:43 +07:00
semantic-release-bot f84dfb8476 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
2026-07-20 08:25:10 +00:00
asepharyana 07b217cf4a feat(tui): enhance agent turn handling by grouping parameters and improving message management 2026-07-20 15:21:23 +07:00
asepharyana 9bfb95d795 feat(llm): improve tool call handling by dynamically resizing tool_calls and updating arguments 2026-07-20 14:58:39 +07:00
asepharyana 285dbb14cc feat(tui): add support for reasoning in chat messages and update transcript handling 2026-07-20 14:56:03 +07:00
asepharyana cac6626586 feat(tui): implement streaming support for LLM responses and update transcript handling 2026-07-20 14:51:16 +07:00
asepharyana 5a373d1031 feat(tui): update system message for clarity and conciseness in tool usage instructions 2026-07-20 14:47:55 +07:00
asepharyana fe2e916937 feat: add test_load and test_parse binaries for configuration loading and parsing 2026-07-20 14:47:55 +07:00
asepharyana 66ac4dbf02 feat: remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide 2026-07-20 14:47:55 +07:00
semantic-release-bot 44c3dd1239 chore(release): 1.18.0 [skip ci]
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-20)

### Features

* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
2026-07-20 06:56:23 +00:00
asepharyana 87abe8c335 feat(tui): optimize performance by caching display lines and token counts, and improve action handling 2026-07-20 13:52:20 +07:00
asepharyana 148ba4e07b feat(mcp): enhance MCP server registration with error handling and improve transport process management
refactor: update various tools for better error handling and path resolution
fix: improve markdown rendering and input display in TUI
2026-07-20 13:12:04 +07:00
semantic-release-bot 89ee213454 chore(release): 1.17.0 [skip ci]
# [1.17.0](https://github.com/asepharyana/zesdex/compare/v1.16.1...v1.17.0) (2026-07-20)

### Features

* **token:** add refresh token verification to TokenService ([a046519](https://github.com/asepharyana/zesdex/commit/a04651905f4afd562b516c839449a2c813ce6627))
2026-07-20 05:30:00 +00:00
asepharyana a04651905f feat(token): add refresh token verification to TokenService
feat(bootstrap): create temporary settings and config files to prevent data loss

refactor(edit_log): switch from Vec to VecDeque for efficient memory management

fix(gateway): ensure store directories are created before starting the API server

refactor(bgbash): implement a global singleton for BashControl

feat(auth): enhance session authentication middleware to use SessionRepository

fix(edit_log_repo): update to use VecDeque for in-memory edit log storage

fix(memory_repo): add newline escaping for frontmatter fields

fix(session_lock_repo): improve error handling for lock file operations

fix(bash_tools): prevent path traversal in job_id argument

refactor(delete): enforce empty directory deletion in file system tools

fix(edit): optimize string replacement to only replace the first occurrence

fix(git_cred): improve credential management with piped input to git commands

feat(git_operator): add safety filter to block destructive git operations

fix(shell): register background jobs in Bash control

feat(spawn): add access tier specification for pipeline stages

refactor(hive_mind): run directives concurrently for improved performance

fix(auth): update refresh token verification in the refresh handler

fix(chat): optimize LLM client usage based on model matching

fix(conversations): enhance message deletion to target specific indices

feat(api): add JWT authentication middleware for all API routes

fix(state): implement refresh token verification in JwtTokenService

fix(daemon): improve usage tracking with saturating addition

fix(tui): handle compacted messages in the TUI state management
2026-07-20 12:26:10 +07:00
semantic-release-bot 600ea041ef chore(release): 1.16.1 [skip ci]
## [1.16.1](https://github.com/asepharyana/zesdex/compare/v1.16.0...v1.16.1) (2026-07-20)
2026-07-20 05:06:27 +00:00
asepharyana 1ec2aa136a refactor: improve code readability and consistency across multiple files 2026-07-20 12:02:50 +07:00
semantic-release-bot 4ced6681c2 chore(release): 1.16.0 [skip ci]
# [1.16.0](https://github.com/asepharyana/zesdex/compare/v1.15.2...v1.16.0) (2026-07-20)

### Features

* **tui:** add usage overlay and sidebar for displaying usage statistics and tasks ([da2ed6d](https://github.com/asepharyana/zesdex/commit/da2ed6da25953b823354cc5deaa7b404b7b13cb0))
* **tui:** enhance agent turn with tool descriptions and sanitize arguments ([08e2f99](https://github.com/asepharyana/zesdex/commit/08e2f9998d3693e4cd57225491359c762d03f1d9))
* **tui:** implement agent turn engine for background processing and enhance input handling ([792695b](https://github.com/asepharyana/zesdex/commit/792695b65a393cfc54efe353480b7831e91544b5))
2026-07-20 04:33:19 +00:00
asepharyana 08e2f9998d feat(tui): enhance agent turn with tool descriptions and sanitize arguments 2026-07-20 11:29:33 +07:00
asepharyana 792695b65a feat(tui): implement agent turn engine for background processing and enhance input handling 2026-07-20 10:55:09 +07:00
asepharyana da2ed6da25 feat(tui): add usage overlay and sidebar for displaying usage statistics and tasks
feat(tui): implement status bar with connection and turn state indicators
feat(tui): create workflow panel for agent status and progress visualization
feat(web): introduce web frontend interface with static file serving
feat(ws): add WebSocket interface for real-time communication and session management
2026-07-20 09:04:57 +07:00
asepharyana bceba665c0 refactor: remove unused tracing imports across multiple files 2026-07-20 07:02:55 +07:00
asepharyana 714b4617dd Refactor CMS and IAM modules: restructure presentation and command layers
- Removed HTTP adapter module from CMS infrastructure.
- Updated CMS infrastructure module to exclude HTTP.
- Introduced presentation layer in CMS with DTOs and handlers for REST API.
- Added command types for CMS domain operations to encapsulate input data.
- Created typed error handling for CMS presentation layer.
- Implemented handlers for CMS REST API endpoints.
- Removed HTTP DTOs and handlers from IAM infrastructure.
- Introduced command types for IAM domain operations.
- Created presentation layer in IAM with DTOs and handlers for OAuth flow.
- Implemented typed error handling for IAM presentation layer.
2026-07-20 06:53:01 +07:00
asepharyana e9a8e93c83 Refactor session ID handling and improve error management
- Introduced `SessionId` newtype for validated session identifiers, ensuring safety against path traversal attacks.
- Updated session repository methods to accept `SessionId` instead of raw strings, enhancing type safety.
- Removed redundant error handling in repository methods by leveraging the new `Error` type from `zesdex_utils`.
- Simplified atomic JSON write operations by eliminating unnecessary error conversions.
- Enhanced integer casting with a new `CastOr` trait for safer narrowing conversions.
- Removed deprecated error handling code and consolidated error types across the codebase.
- Updated HTTP handlers to utilize the new session ID validation, improving overall robustness.
2026-07-20 06:39:30 +07:00
asepharyana ab1a54b72e Refactor error handling in IAM and CMS crates
- Introduced `RepositoryError` and `ServiceError` enums in both IAM and CMS domains for better error management.
- Updated domain traits and services to return specific error types instead of `anyhow::Result`.
- Enhanced session and OAuth repository implementations to handle errors more explicitly.
- Refactored session service methods to return `Result<T, ServiceError>` for improved error handling.
- Updated HTTP handlers to utilize the new error types.
- Modified password hashing functions to run in a blocking context using `tokio::task::spawn_blocking`.
- Added tests for new error handling mechanisms and async password functions.
2026-07-20 06:14:23 +07:00
asepharyana 5aaedbf787 docs: tambah doc comment, logging, dan inline comments di semua 255 file
Meliputi:
- File-level //! doc comment: tujuan file, alur kerja, komponen utama
- Function-level /// doc comment: apa, parameter, return, flow, edge cases
- Struct/enum/trait /// doc comment: peran, field docs
- Tracing logging (tracing::info!/debug!/trace!/warn!/error!) di setiap fungsi
- Inline comments untuk variable dan branching logic penting
- Seluruh 8 crates di workspace: zesdex-backend, zesdex-cms, zesdex-entities,
  zesdex-iam, zesdex-infra, zesdex-ipc, zesdex-middleware, zesdex-utils
- Build: 0 errors, 242/242 tests passed
2026-07-19 17:05:47 +07:00
semantic-release-bot 6680795ce7 chore(release): 1.15.2 [skip ci]
## [1.15.2](https://github.com/asepharyana/zesdex/compare/v1.15.1...v1.15.2) (2026-07-17)

### Bug Fixes

* correct jitter range to ±25% and fix abort.rs doc — review findings ([9b6e51d](https://github.com/asepharyana/zesdex/commit/9b6e51dc677cc4b798532f1e63335785f2f7bbbf))
2026-07-17 20:21:33 +00:00
asepharyana 9b6e51dc67 fix: correct jitter range to ±25% and fix abort.rs doc — review findings 2026-07-18 03:18:27 +07:00
asepharyana 40524f930f refactor: use mark_dirty() helper di input.rs, DRY 22 lokasi 2026-07-18 03:18:27 +07:00
asepharyana 086cb86f0d refactor: extract is_aborted helpers, DRY 16 call sites 2026-07-18 03:18:27 +07:00
asepharyana ff47bffe0c refactor: reuse is_auth_error from provider.rs, DRY backend retry logic 2026-07-18 03:18:27 +07:00
asepharyana 431c8d3b89 refactor: unify 3 backoff implementations into shared helper 2026-07-18 03:18:27 +07:00
asepharyanaandClaude Opus 4.8 e32501ee59 refactor: extract session_id extraction helper, DRY auth.rs
Extract duplicated session ID extraction + validation logic from
SessionAuthMiddleware::call() and require_session() into two shared
helper functions: extract_session_id and validate_and_build_identity.

Removes ~60 lines of duplicated code while preserving behavior:
- Both call sites now rely on the same extraction/validation path
- User-Agent default remains empty string (existing behavior unchanged)
- Error response format (401 with header/validation messages) unchanged

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 03:18:27 +07:00
asepharyanaandClaude Opus 4.8 7d8487cefb refactor: consolidate #![allow(clippy::cast_*)] to crate roots
Add the cast-allow block to zesdex-entities/src/lib.rs and
zesdex-utils/src/lib.rs (which lacked it), then remove from
65 sub-files across all 8 crates. Build and all 223 tests
continue to pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 03:18:27 +07:00
asepharyanaandClaude Opus 4.8 4cd38c9291 refactor: extract write_json_atomic helper, DRY 8 call sites
Move the crash-safe write-then-rename pattern into
zesdex-utils::write_json_atomic and apply it across:

- zesdex-cms: app_config_repo, conversation_repo, settings_repo
- zesdex-iam: oauth_repo, session_repo
- zesdex-entities: Conversation::save_conversation, Session::save

Excluded (non-JSON format):
- rewind_blob_repo (binary blob)
- memory_repo (markdown + frontmatter, not JSON)
- session_lock (PID string, not JSON)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 03:18:27 +07:00
asepharyanaandClaude Opus 4.8 9a6ab62562 refactor: DRY cleanup — extract shared helpers, remove duplication across tools, LSP, overlays, and runtime
Eliminate ~500 lines of duplicate code across 31 files by extracting
shared functions, helpers, and consolidating repeated patterns.

Highlights:
- Toast helpers (toast_info/success/warning/error) on AppStateRest
- push_event() helper for turn-event queue (19 callers consolidated)
- log_write_edit_tool() shared fn (turn.rs + engine.rs ~50 lines saved)
- resolve_api_key() shared fn (spawn.rs + provider.rs)
- LSP call_positional() helper on LspClient
- lsp_cursor_params() shared schema for 4 tool files
-overlay_block() helper for consistent overlay title/border styling
- cycle_selected_index(), path_not_found/a_directory() helpers
- mark_dirty(), save_settings() on AppStateRest
- Remove redundant Err(e) => Err(e) arms in LSP tools
- Consolidate generate_workspace_tree (turn.rs → workspace.rs)
- Simplify background-review wrapper args in auto/mod.rs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 03:18:27 +07:00
asepharyana b02754acd2 refactor: implement retry logic with exponential backoff and jitter for subagent and provider calls 2026-07-18 03:18:27 +07:00
semantic-release-bot b3c5b2a57b chore(release): 1.15.1 [skip ci]
## [1.15.1](https://github.com/asepharyana/zesdex/compare/v1.15.0...v1.15.1) (2026-07-17)
2026-07-17 03:32:34 +00:00
asepharyana 796bb09c5b refactor: enhance message shaping with progressive summarization and improved handling of dropped messages 2026-07-17 10:29:52 +07:00
asepharyana 5aad7e1eb1 refactor: streamline token counting and message shaping logic 2026-07-17 10:29:52 +07:00
semantic-release-bot 0dfde96f81 chore(release): 1.15.0 [skip ci]
# [1.15.0](https://github.com/asepharyana/zesdex/compare/v1.14.0...v1.15.0) (2026-07-17)

### Bug Fixes

* **cms:** perbaiki serde default hive_mind_node_timeout_ms & toleransi parse gagal di Settings ([6d41ffc](https://github.com/asepharyana/zesdex/commit/6d41ffc587f6f8de5bb4757c7eb8d69077831057))
* **cms:** satukan ChatMessage/Role Conversation dengan tipe kanonik zesdex-entities ([b272858](https://github.com/asepharyana/zesdex/commit/b272858edbe36af0b2eca119ff5b132de8dadce9))
* **iam:** redirect_uri dinamis + validasi CSRF state di OAuthServiceImpl ([be278f8](https://github.com/asepharyana/zesdex/commit/be278f8b1c2bc1295368e49c38622ef2bc3ed9ee))
* **iam:** set permission 0600 pada file token OAuth ([f2d97fb](https://github.com/asepharyana/zesdex/commit/f2d97fb17dcf4f52123da89532d7964ed8f8124c))
* **middleware:** jangan percaya header X-Forwarded-For/X-Real-IP secara default di rate limiter ([4dc4f80](https://github.com/asepharyana/zesdex/commit/4dc4f80fa344d894c2ce62f75d239847cd13001a))

### Features

* **cms:** implement RewindBlobRepository for managing binary blobs ([22dd6fd](https://github.com/asepharyana/zesdex/commit/22dd6fdda7d0c8eabfce296bbad53587204c69fa))
* **iam:** implementasikan FileSystemSessionLockRepository (sebelumnya belum ada implementasi) ([ff6a749](https://github.com/asepharyana/zesdex/commit/ff6a749c1149d890173922fbff76facef50a93b0))
* **iam:** port LoopbackServer OAuth callback listener dari zesdex-backend ([910aa5e](https://github.com/asepharyana/zesdex/commit/910aa5e071911f158609c4dd8985f776d8d9235f))
* **iam:** tambahkan CSPRNG (OsRng) untuk token state/PKCE ([5ede65f](https://github.com/asepharyana/zesdex/commit/5ede65f454b08303f588754a208dca0c37d3ce34))
2026-07-17 02:20:51 +00:00
asepharyana 9a67137954 refactor: massive codebase restructuring — naming, splitting, DRY
Crate renames:
  - zesdex-entities::seaorm → domain (misleading name, no SeaORM used)
  - zesdex-dto → merged into zesdex-entities (100% re-exports)
  - zesdex-libs → zesdex-infra (vague name)

Module renames:
  - app/harness → guard (misleading: safety gatekeeper, not test harness)
  - runtime/commands → action_dispatch (name clashed with controller/command)
  - resources → prompts (embedded prompt text, not general resources)
  - tool/seqthink → sequential_think (unreadable abbreviation)
  - msglog/query → insert (module only inserts, never queries)

Dead code removal:
  - app/mode/help.rs (orphaned — not declared in mod.rs)
  - app/mode/loading.rs (orphaned — not declared in mod.rs)

File splitting (71 new files, avg ~115 lines/file):
  - app/runtime/actions/: 1→8 files (was 2030 lines)
  - view/overlays/: 1→16 files (was 1167 lines)
  - tool/lsp/: 1→8 per-tool files (was 909 lines)
  - main.rs: 1→5 files (session, daemon, attach, event_loop)
  - workflow/engine + hive_mind: 2→10 files
  - subagent/engine + auto: 2→9 files
  - lsp/provisioner: 1→5 files
  - review/: 1→6 files
  - guard/: 1→2 files (extracted patterns)
  - state/misc: 1→3 files (input, scroll)
  - mcp/: 1→3 files (transport, adapter)
  - stream/json_repair extracted from turn.rs

DRY:
  - Pattern constants (STUB_PATTERNS etc) in guard/patterns shared with subagent
  - 3 near-identical background spawners → 1 generic + thin wrappers
  - Shared spawn_subagent_with_drain() extracted
  - Shared create_session() in main
  - write_osc52 deduplicated

Bug fixes:
  - archive_message(): sess.db → db (wrong variable name)
  - execute_one_tool(): wrong parameter name
  - check_credential_read() function was missing (restored from test expectations)
2026-07-17 09:08:41 +07:00
asepharyana 1f0ae9f551 Refactor and clean up code across multiple modules
- Simplified token type assignment in OAuth service.
- Removed unused session_lock module and re-exported Session from zesdex_entities.
- Cleaned up session entity by removing unnecessary comments and code.
- Consolidated session handling in HTTP handlers for better readability.
- Improved formatting and readability in OAuth repository tests.
- Enhanced session lock repository with clearer match statements.
- Streamlined session repository error handling.
- Refined RNG tests for better clarity.
- Adjusted module visibility and organization in lib.rs.
- Updated IPC client and connection code for better error handling and clarity.
- Improved frame handling in IPC for better readability.
- Organized module imports and added test utilities for IPC.
- Enhanced database connection error handling.
- Simplified JWT token creation error handling.
- Improved password verification error handling.
- Cleaned up state management code for better readability.
- Refactored middleware for session authentication and rate limiting.
- Simplified clipboard utility for better error handling.
- Enhanced logging initialization for better error reporting.
- Improved pagination utility with clearer method annotations.
- Cleaned up sanitization functions for filenames and paths.
- Enhanced slug generation functions for better clarity and usability.
2026-07-17 09:08:41 +07:00
asepharyana 22dd6fdda7 feat(cms): implement RewindBlobRepository for managing binary blobs 2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 b272858edb fix(cms): satukan ChatMessage/Role Conversation dengan tipe kanonik zesdex-entities
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 3f79b283e2 chore: hapus entitas settings/app_config/memory/edit_log lama di zesdex-entities yang sudah digantikan zesdex-cms
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 9618ef413b refactor(backend): alihkan EditLog ke zesdex-cms JsonlEditLogRepository
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 0ad3b0e539 refactor(backend): alihkan Memory ke zesdex-cms MarkdownMemoryRepository
Ganti semua pemanggilan Memory::read/write/remove/list di zesdex-backend
dengan MarkdownMemoryRepository dari zesdex-cms. Hapus re-export
model::memory yang sudah tidak dipakai.

Method mapping: read -> load, write -> save, remove -> delete, list -> list.
Import trait MemoryRepository untuk method resolution.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 dc9fd4dbd1 refactor(backend): alihkan AppConfig ke zesdex-cms JsonAppConfigRepository
Semua pemanggilan AppConfig::load() diganti dengan
JsonAppConfigRepository + AppConfigRepository trait.
Re-export model::app_config dihapus dari model/mod.rs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 8e6acc30d5 refactor(backend): alihkan Settings ke zesdex-cms JsonSettingsRepository
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 6d41ffc587 fix(cms): perbaiki serde default hive_mind_node_timeout_ms & toleransi parse gagal di Settings
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 f51a32569f chore: hapus implementasi OAuth/session lama yang sudah digantikan zesdex-iam
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 add6845edf refactor(backend): alihkan manajemen session ke zesdex-iam (SessionRepository/SessionLockRepository)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 4ab812d93b refactor(backend): alihkan run_oauth_flow ke zesdex-iam OAuthServiceImpl
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 ff6a749c11 feat(iam): implementasikan FileSystemSessionLockRepository (sebelumnya belum ada implementasi)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 f2d97fb17d fix(iam): set permission 0600 pada file token OAuth
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 be278f8b1c fix(iam): redirect_uri dinamis + validasi CSRF state di OAuthServiceImpl
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 910aa5e071 feat(iam): port LoopbackServer OAuth callback listener dari zesdex-backend
Duplikasi verbatim dari crates/zesdex-backend/src/service/oauth/loopback.rs
ke zesdex-iam untuk sentralisasi primitif OAuth.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyana 5ede65f454 feat(iam): tambahkan CSPRNG (OsRng) untuk token state/PKCE 2026-07-17 09:08:41 +07:00
asepharyanaandClaude Sonnet 5 4dc4f80fa3 fix(middleware): jangan percaya header X-Forwarded-For/X-Real-IP secara default di rate limiter
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 09:08:41 +07:00
asepharyana 3401d63063 docs(shell): perbaiki doc comment shell_filter yang menyesatkan soal credential-read 2026-07-17 09:08:41 +07:00
asepharyana be0a9582bb refactor: migrate monolithic crate to Cargo Workspace with Clean Architecture
Transform the single binary crate into a 9-crate workspace monorepo:

- Root Cargo.toml as [workspace] manager with resolver = "2"
- zesdex-entities: Domain entity types (session, settings, store, message, etc.)
- zesdex-utils: Pure utility functions (error, logger, pagination, slug, clipboard)
- zesdex-dto: Data Transfer Objects for LLM provider API communication
- zesdex-ipc: Unix-socket IPC layer (client/server/framing/protocol)
- zesdex-iam: Identity & Access Management (Clean Architecture: domain/application/infrastructure)
- zesdex-cms: Content Management (Clean Architecture: domain/application/infrastructure)
- zesdex-middleware: HTTP middleware (Auth, CORS, Rate Limiting)
- zesdex-libs: Composition root (AppContext, DB init, JWT, Argon2)
- zesdex-backend: Main binary entry point + seed/migrate binaries
- DevOps: Dockerfile, docker-compose, Nix (flake/shell/default), CI/CD updates
- Remove dead root src/ and src-misc/ directories

All crate re-exports maintain backward compatibility with original
crate::model::*, crate::dto::*, crate::ipc::* module paths.
Feature crates enforce strict layer separation: domain -> application
-> infrastructure with generic trait-based dependency injection.
2026-07-17 09:08:41 +07:00
semantic-release-bot 86cc412395 chore(release): 1.14.0 [skip ci]
# [1.14.0](https://github.com/asepharyana/zesdex/compare/v1.13.0...v1.14.0) (2026-07-16)

### Bug Fixes

* **context:** batasi squash_log ke tool bash saja ([7d99cd6](https://github.com/asepharyana/zesdex/commit/7d99cd66187b3fafb2ddeb19d8e8aa7db139df64))
* **context:** perbaiki fixture test shaping agar men-drop pesan lama ([8bb697a](https://github.com/asepharyana/zesdex/commit/8bb697a53fe89c9d00f709df33ccbd7944482f07))
* **plan:** perbaiki bug entropy gate dan fixture test squash.rs ([ceb8479](https://github.com/asepharyana/zesdex/commit/ceb84790bb741352b2b3416cda4bdbc6b42767c9))
* **plan:** perbaiki fixture test array-cutoff squash_json ([7ffdf44](https://github.com/asepharyana/zesdex/commit/7ffdf441355cda0972b849bc9b475d3de8f39843))
* **plan:** perbaiki fixture test shaping agar benar-benar men-drop pesan ([3a6e32d](https://github.com/asepharyana/zesdex/commit/3a6e32d8f3f0dd47d2c5ff63ab0c184b0ee4a6bc))
* **plan:** perkuat fixture test log agar benar-benar uji squash_log ([682007a](https://github.com/asepharyana/zesdex/commit/682007a2507f209c2378796442d4bc879516191a))

### Features

* **context:** tambah context::dedup untuk hasil tool yang berulang ([12a03fd](https://github.com/asepharyana/zesdex/commit/12a03fd3d1123c7a88289e44064537a71b9f574b))
* **context:** tambah context::shaping (port dari shortsend) ([e080d9f](https://github.com/asepharyana/zesdex/commit/e080d9fc6b7daf2ab37fb242d03a3f64e8629acc))
* **context:** tambah context::squash untuk kompresi hasil tool ([ea0b498](https://github.com/asepharyana/zesdex/commit/ea0b4988299894e4588d851ebc91704a9e73bc73))
* **context:** tambah context::tokens dengan tiktoken-rs ([c219b6e](https://github.com/asepharyana/zesdex/commit/c219b6ec58ddad4770e491a48bbe1b6e3d0c8884))
* **context:** tambah context::window::resolve ([059ca8e](https://github.com/asepharyana/zesdex/commit/059ca8ea246768dbec06ae5336433853e4276cec))
* **runtime:** kompres hasil tool lewat squash sebelum masuk context ([96084f7](https://github.com/asepharyana/zesdex/commit/96084f74621636a72c209388580d0ebbb335d198))
* **settings:** tambah mode ringkas opsional (concise_output) ([d6de973](https://github.com/asepharyana/zesdex/commit/d6de9735aba7745f5f57a8e7a5e625613c1a2569))
2026-07-16 01:01:45 +00:00
asepharyana 1afca97c1b refactor(subagent): remove unused step parameter from SubagentEvent 2026-07-16 07:58:34 +07:00
asepharyana a00aa9bec8 Refactor view modules for improved readability and consistency
- Updated markdown rendering logic to use more concise methods for obtaining vector lengths.
- Changed review status display to use the correct flag from settings.
- Cleaned up sidebar rendering code for better formatting and readability.
- Enhanced status bar rendering with improved string formatting and consistent style application.
- Refined workflow panel rendering, ensuring consistent style usage and improved readability.
- Added architecture overview and detailed documentation for backend, data, dependencies, and frontend structures.
2026-07-16 07:56:11 +07:00
asepharyanaandClaude Sonnet 5 7d99cd6618 fix(context): batasi squash_log ke tool bash saja
Ditemukan reviewer whole-branch final: looks_log_shaped murni berbasis
konten (>=3 baris berpola error/warn/fail), jadi hasil grep/search yang
match ke kode error-handling ikut lolos ambang itu -- padahal
squash_log punya cap keras 20 error + 10 warning tanpa budget byte,
diam-diam membuang match yang sah di luar cap itu. Sekarang hanya tool
bash (penghasil log sungguhan) yang boleh lewat squash_log; tool lain
yang kebetulan konten-nya mirip log jatuh ke squash_generic yang lebih
longgar (head/tail + budget byte). Tambah test regresi yang membedakan
kedua jalur lewat retensi baris terakhir.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:56:11 +07:00
asepharyana e075eb7acc style(context): bersihkan warning clippy pedantic di squash.rs dan dedup.rs
Perbaikan gaya murni (format! di-append ke String -> write!, syntax
perbandingan yang lebih jelas, backtick di doc comment) tanpa
mengubah perilaku -- semua test tetap hijau.
2026-07-16 07:56:11 +07:00
asepharyana d6de9735ab feat(settings): tambah mode ringkas opsional (concise_output)
Off by default, diaktifkan lewat settings.json (belum ada UI toggle —
sama seperti review_enabled/session_archive_enabled/lsp_auto_provision
yang juga cuma bisa diedit manual hari ini). Saat aktif, system prompt
diberi instruksi menulis ringkas, dengan pengecualian eksplisit untuk
konfirmasi operasi destruktif dan peringatan keamanan yang tetap harus
detail penuh.
2026-07-16 07:56:11 +07:00
asepharyana 85d16ebe97 refactor(status): pakai context::tokens dan context::window
Status bar sekarang memakai penghitungan token yang sama persis dengan
compaction (bukan heuristik /4 terpisah), dan selalu menampilkan angka
context window nyata alih-alih '?' saat model role tidak override
context_window secara eksplisit — konsisten dengan fallback yang
sudah dipakai compaction sendiri.
2026-07-16 07:56:11 +07:00
asepharyana 96084f7462 feat(runtime): kompres hasil tool lewat squash sebelum masuk context
Salinan yang dikirim ke UI (TurnEvent::ToolResult) tetap utuh; hanya
salinan yang masuk riwayat percakapan (dikirim ke LLM) yang dikompres,
supaya user tetap melihat output tool apa adanya.
2026-07-16 07:56:11 +07:00
asepharyanaandClaude Sonnet 5 82c024a854 docs(runtime): perbarui doc comment run_agent_turn yang basi
Masih menyebut shortsend padahal modul itu sudah dihapus dan diganti
context::dedup/context::shaping di commit sebelumnya.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:56:11 +07:00
asepharyana 78e402cf14 refactor(runtime): pindah ke context::, perbaiki asimetri /compact manual
Loop auto-compaction sekarang selalu menjalankan dedup tiap iterasi
lalu shaping lewat context::, menggantikan shortsend:: yang dihapus.

Action::Compact tadinya berjalan sinkron dan selalu client: None,
sehingga hasil compact manual tidak pernah diringkas LLM (beda dengan
compaction otomatis di tengah turn). Sekarang /compact jalan di
thread background seperti spawn_turn, sehingga bisa memanggil LLM
untuk meringkas riwayat yang dibuang — perilaku manual dan otomatis
jadi setara.

Ekstrak resolve_llm_client_config() dari spawn_turn supaya logika
resolusi api_key/model/base_url tidak dua kali.
2026-07-16 07:56:11 +07:00
asepharyanaandClaude Sonnet 5 3a6e32d8f3 fix(plan): perbaiki fixture test shaping agar benar-benar men-drop pesan
Ditemukan implementer Task 5: fixture pesan pendek (~8 token nyata
lewat tiktoken untuk 20 pesan = ~160 token) tidak pernah melebihi
target 700 token (70% dari max_wire_tokens=1000), jadi force=true pun
tidak pernah men-drop satu pesan pun -- test placeholder-summary dan
keeps-most-recent lulus secara vakum tanpa benar-benar menguji jalur
drop. Diverifikasi ulang dengan context::tokens::count_tokens nyata:
fixture baru (20 pesan ~49 token = ~980 token total) melebihi target
700 dengan nyaman.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:55:48 +07:00
asepharyana e080d9fc6b feat(context): tambah context::shaping (port dari shortsend)
Perilaku should_shape/shape_messages tidak berubah, hanya sumber
penghitungan token yang sekarang lewat context::tokens (tiktoken-rs)
menggantikan heuristik char/3 bawaannya sendiri.
2026-07-16 07:55:48 +07:00
asepharyana ea0b498829 feat(context): tambah context::squash untuk kompresi hasil tool
Kompresi per-jenis-konten (JSON: pertahankan struktur & value pendek/
entropi tinggi, buang value panjang bertele-tele; log: simpan baris
error/warning berskor tertinggi + konteks sekitarnya; generic: potong
importance-ranked) untuk hasil tool di atas 1.5KB. Tool read dikecualikan
total karena isinya harus tetap byte-exact untuk edit selanjutnya.
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 682007a250 fix(plan): perkuat fixture test log agar benar-benar uji squash_log
Ditemukan lewat trace manual (bukan implementer): fixture lama cuma
punya 1 baris berpola error, di bawah ambang looks_log_shaped (>=3),
jadi tanpa sadar selalu jatuh ke squash_generic -- test tetap lulus
tapi tidak pernah menguji logika scoring/windowing squash_log sama
sekali. Tambah baris error/warning lagi supaya jalur squash_log
benar-benar terpakai.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 7ffdf44135 fix(plan): perbaiki fixture test array-cutoff squash_json
Ditemukan implementer Task 4 (percobaan kedua, lagi-lagi BLOCKED
sebelum commit apapun): test sebelumnya memakai string sama yang
panjang+entropi-rendah di semua 4 elemen array, jadi elemen index
0-2 pun ikut ter-elide oleh aturan panjang/entropi normal -- tidak
benar-benar menguji efek posisi array. Ganti fixture pakai string
berbentuk UUID (tanpa spasi, entropi tinggi) yang lolos aturan normal
di posisi manapun, supaya index 3 yang di-force-elide walau
identifier-shaped benar-benar membuktikan aturan "past index 3
regardless of length/entropy".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 ceb84790bb fix(plan): perbaiki bug entropy gate dan fixture test squash.rs
Ditemukan implementer Task 4 sebelum commit apapun (BLOCKED, bukan
kode salah): entropi Shannon mentah per-karakter tidak membedakan
prosa dari identifier acak — prosa berulang skor ~3.89 bit/char,
lebih tinggi dari UUID (~3.39). Tambah syarat "tanpa spasi" sebelum
cek entropi (meniru pre-filter headroom sendiri), turunkan ambang ke
3.0 pada skala mentah. Fixture test array JSON juga diperbesar
(repeat 5 -> 8) karena sebelumnya tidak pernah melewati SQUASH_FLOOR_BYTES
yang diasumsikan test itu sendiri.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 12a03fd3d1 feat(context): tambah context::dedup untuk hasil tool yang berulang
Panggilan tool read-only (read, grep, glob, dst) dengan argumen persis
sama menyisakan satu salinan penuh saja di context; entri lama diganti
placeholder tapi tool-call-nya sendiri tetap terlihat di riwayat. Tool
bersifat mutasi (write/edit/bash/dll) tidak pernah disentuh.

Jadikan tool_scope::READ_TOOLS pub supaya jadi satu-satunya sumber
klasifikasi read-only, dipakai ulang bukan didaftar dua kali.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 059ca8ea24 feat(context): tambah context::window::resolve
Satukan tiga salinan logika resolusi context_window (Action::Compact,
spawn_turn, status bar) yang sempat melenceng satu sama lain.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
asepharyana c219b6ec58 feat(context): tambah context::tokens dengan tiktoken-rs
Ganti tiga heuristik char-count (/3 di shortsend, /4 di loop turn, /4
di status bar) yang saling tidak konsisten dengan satu BPE tokenizer
nyata. tiktoken-rs membundel vocab lewat include_str! saat build, jadi
tidak ada akses jaringan saat runtime.
2026-07-16 07:49:43 +07:00
asepharyana 8bb697a53f fix(context): perbaiki fixture test shaping agar men-drop pesan lama
Fixture pendek sebelumnya (~8 token nyata per pesan lewat tiktoken)
tidak pernah melebihi target 700 token, jadi shape_messages tidak
pernah men-drop satu pesan pun -- satu test gagal, satu test lain
lulus secara vakum. Pakai fixture lebih panjang (~49 token/pesan)
yang diverifikasi melebihi target dengan nyaman.
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 75e9cadcd5 docs(plans): tambah plan implementasi rombak context & compaction
9 task: tokens.rs (tiktoken-rs), window.rs, dedup.rs, squash.rs,
shaping.rs (port shortsend), gabungan cutover+fix /compact manual,
wiring squash, status bar, dan mode ringkas opsional. Setiap task
diverifikasi dengan cargo build/test nyata, bukan -D warnings (yang
sudah merah di main karena warning pre-existing di file lain).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 c4e1d7c2b2 docs(specs): hapus facade prepare(), panggil modul context langsung
Facade cuma dipakai generically oleh satu caller (Action::Compact);
auto-loop tetap butuh kontrol per-stage sendiri. Selaras dengan prinsip
"No DI" di CLAUDE.md. dedup::collapse juga diubah mengembalikan
(Vec<ChatMessage>, bool) supaya caller tahu ada perubahan tanpa perlu
ChatMessage: PartialEq.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 da39033e81 docs(specs): kecualikan tool read dari squash
Ditemukan saat menulis plan: kompresi JSON pada hasil read akan merusak
byte-exactness yang dibutuhkan untuk edit selanjutnya jika file yang
dibaca kebetulan berformat JSON (package.json, tsconfig.json, dst).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
asepharyanaandClaude Sonnet 5 f62ac3f688 docs(specs): tambah desain rombak context & compaction
Rencana pengganti shortsend.rs dengan modul context/ (dedup, squash,
shaping, tokens, window) plus mode ringkas opsional, disusun dari studi
teknik rtk-ai/rtk, headroomlabs-ai/headroom, dan JuliusBrussee/caveman
(ide saja, tanpa menyalin kode).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 07:49:43 +07:00
semantic-release-bot aaab953d8a chore(release): 1.13.0 [skip ci]
# [1.13.0](https://github.com/asepharyana/zesdex/compare/v1.12.0...v1.13.0) (2026-07-14)

### Bug Fixes

* correct test assertion in dim_false_plain_text_has_no_color ([8d77e45](https://github.com/asepharyana/zesdex/commit/8d77e4565c2e3ca49058022c71e8277bdd790312))
* Remove orphaned span_text helper function from markdown test module ([199028f](https://github.com/asepharyana/zesdex/commit/199028fa2eb6056dad2bdf0753554939c153a163))
* **state:** cegah panic saat select mention dengan cursor stale ([dcfc5b9](https://github.com/asepharyana/zesdex/commit/dcfc5b9ec0d35f4c66b1648ded00f4f1279e0413))
* **state:** jangan bangun mention index di mode attach ([e0d0860](https://github.com/asepharyana/zesdex/commit/e0d0860d7ba0ab6a4c9b9f1562f6a767a6424d99))

### Features

* Deteksi trigger [@mention](https://github.com/mention) dan Tab-cycle di input handler ([2eebedf](https://github.com/asepharyana/zesdex/commit/2eebedfea56c7d4827f94a2739dbb5fa006e3069))
* **ipc:** dukung Ctrl+Y clipboard copy di mode daemon/attach ([472162d](https://github.com/asepharyana/zesdex/commit/472162d135478666913a888a68867e635e50d14a))
* Judul dropdown autocomplete mengikuti jenisnya (Commands vs Files) ([7f2509e](https://github.com/asepharyana/zesdex/commit/7f2509ecd2688495545333debee0c81016b28641))
* **state:** Alirkan mention_index lewat ToolCtx dan AppStateRest, bangun index di background thread ([93be92a](https://github.com/asepharyana/zesdex/commit/93be92a5fb8644c9020478c49421585ade2d0fd1))
* Tambah Ctrl+Y untuk menyalin pesan assistant terakhir ([d93bdba](https://github.com/asepharyana/zesdex/commit/d93bdba59b7dd14b4a76dc91c6b7f70a3c0f721c))
* Tambah field pending_clipboard_copy di MiscState ([3b6abd9](https://github.com/asepharyana/zesdex/commit/3b6abd920ea92329ebcf888c3bb50470675c4152))
* Tambah helper truncate_diff untuk membatasi panjang diff ([5dd835f](https://github.com/asepharyana/zesdex/commit/5dd835ff244a138bb5f1a8dbfd7cf252c2671e5e))
* Tambah MentionIndex, AutocompleteKind, dan deteksi [@mention](https://github.com/mention) di InputState ([95cae8f](https://github.com/asepharyana/zesdex/commit/95cae8fd8a8ce737ba60c3ac8bea77f4c2e14b1a))
* Tambah write_osc52 dan salin ke clipboard di mode single-process ([71b1613](https://github.com/asepharyana/zesdex/commit/71b1613d8467cfcb2383b3fce153a25c7883ac3d))
* Tambahkan file baru ke mention_index saat tool write membuatnya ([930961b](https://github.com/asepharyana/zesdex/commit/930961bd85701ab8906b8d81095e46d3635a951d))
* Tampilkan unified diff pada hasil tool edit ([c3c0ef6](https://github.com/asepharyana/zesdex/commit/c3c0ef632a605d8bf32712049035e4fc814af9d5))
* Tampilkan unified diff saat tool write menimpa file yang sudah ada ([2bb8e6f](https://github.com/asepharyana/zesdex/commit/2bb8e6f2555eac01baf2311d41811afad4aa3041))
* **view:** Tambah parameter dim dan pewarnaan baris diff di markdown renderer ([683715c](https://github.com/asepharyana/zesdex/commit/683715cd7af77d87a2ae3834360bb6f7a4388bd0))
2026-07-14 23:39:22 +00:00
asepharyana e0d0860d7b fix(state): jangan bangun mention index di mode attach
AppStateRest::new() men-spawn thread ignore::Walk untuk mention_index
tanpa syarat, padahal mode --attach cuma dipakai untuk render lokal —
handle_key dan logika mention berjalan di sisi daemon lewat IPC, jadi
index di client attach tidak pernah dipakai. Ini bikin setiap
--attach melakukan full workspace walk (sampai 50.000 entry) sia-sia.

Pindahkan thread-spawn itu ke method terpisah
spawn_mention_index_build(), dipanggil eksplisit dari
run_single_process() dan run_daemon() setelah AppStateRest::new(),
tapi sengaja tidak dipanggil dari run_attach().
2026-07-15 06:32:57 +07:00
asepharyana dcfc5b9ec0 fix(state): cegah panic saat select mention dengan cursor stale
Cursor bisa berpindah (Left/Right) tanpa menutup dropdown mention,
sehingga mention_start jadi stale relatif ke cursor saat Enter
ditekan. select_autocomplete() lalu memanggil replace_range dengan
start > end dan panic (crash seluruh TUI, termasuk daemon). Tambah
guard: jika cursor < mention_start atau mention_start > buffer.len(),
tutup dropdown dan kembalikan false alih-alih menyambung range yang
tidak valid. Tambah regression test yang mereproduksi skenario ini.
2026-07-15 06:32:57 +07:00
asepharyana 472162d135 feat(ipc): dukung Ctrl+Y clipboard copy di mode daemon/attach
Tambah DaemonFrame::ClipboardCopy(String) supaya daemon bisa
mengirim teks pending_clipboard_copy ke attach client, yang
kemudian menulis sekuens OSC52 ke stdout-nya sendiri (bukan
stdout daemon yang tidak dimiliki terminal user).
2026-07-15 06:32:57 +07:00
asepharyana 71b1613d84 feat: Tambah write_osc52 dan salin ke clipboard di mode single-process 2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 d93bdba59b feat: Tambah Ctrl+Y untuk menyalin pesan assistant terakhir
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyana 3b6abd920e feat: Tambah field pending_clipboard_copy di MiscState 2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 7f2509ecd2 feat: Judul dropdown autocomplete mengikuti jenisnya (Commands vs Files)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 2eebedfea5 feat: Deteksi trigger @mention dan Tab-cycle di input handler
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 930961bd85 feat: Tambahkan file baru ke mention_index saat tool write membuatnya
Ketika write tool membuat file baru (bukan overwrite), path file
sekarang di-push ke mention_index untuk autocomplete @file mention.

- Capture file existence status sebelum write
- Push ke mention_index hanya untuk genuinely new files
- Add 2 tests: one untuk new file push, one untuk overwrite non-duplication

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyana 93be92a5fb feat(state): Alirkan mention_index lewat ToolCtx dan AppStateRest, bangun index di background thread
Menambahkan field mention_index: MentionIndex ke ToolCtx/ToolCtxBuilder dan
AppStateRest, mengikuti pola dir_cache yang sudah ada. AppStateRest::new()
sekarang men-spawn thread background yang men-walk setiap workspace root
via ignore::Walk, membangun daftar path file (dengan prefix [N] untuk root
selain yang pertama) dan mengisi mention_index — data ini yang akan dipakai
fitur autocomplete @file-mention.
2026-07-15 06:32:57 +07:00
asepharyana 95cae8fd8a feat: Tambah MentionIndex, AutocompleteKind, dan deteksi @mention di InputState
Menambahkan MentionIndex (indeks path file thread-safe untuk fitur
autocomplete @file-mention), enum AutocompleteKind untuk membedakan
dropdown slash-command dan file-mention, serta method baru pada
InputState: mention_query_at_cursor untuk deteksi token @mention di
posisi cursor, dan open_mention_autocomplete untuk fuzzy-match file
via nucleo-matcher. select_autocomplete kini kind-aware: menyisipkan
path file ke posisi mention alih-alih mengganti seluruh buffer.
2026-07-15 06:32:57 +07:00
asepharyana 5c413cf9a3 chore: Tambah dependency nucleo-matcher untuk fuzzy file matching 2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 c386030573 refactor: Pakai parameter dim render_markdown, hapus override style manual di chat
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 199028fa2e fix: Remove orphaned span_text helper function from markdown test module
The span_text function in src/view/markdown.rs's test module was no longer
called after the dim_false_plain_text_has_no_color test was fixed. With the
crate's dead_code = "deny" lint enabled, this unused function caused a compile
error. Removed it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 8d77e4565c fix: correct test assertion in dim_false_plain_text_has_no_color
The first assertion was checking span_text() which concatenates all spans
including trailing paragraph-end newlines, making the test guaranteed to fail.
Changed to check spans[0].content directly to verify the text span itself
contains 'hello world' with no color applied when dim=false.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyana 683715cd7a feat(view): Tambah parameter dim dan pewarnaan baris diff di markdown renderer
Tambahkan helper apply_dim dan diff_line_style, ubah signature
render_markdown untuk menerima flag dim, serta deteksi fence bahasa
diff sehingga baris +/-/@@ tetap berwarna meskipun pesan sedang
dirender dim (tampilan tool-output).
2026-07-15 06:32:57 +07:00
asepharyana 2bb8e6f255 feat: Tampilkan unified diff saat tool write menimpa file yang sudah ada 2026-07-15 06:32:57 +07:00
asepharyana c3c0ef632a feat: Tampilkan unified diff pada hasil tool edit 2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 5dd835ff24 feat: Tambah helper truncate_diff untuk membatasi panjang diff
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyanaandClaude Sonnet 5 0a24903eb0 chore: Tambah dependency similar untuk diff computation
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 06:32:57 +07:00
asepharyana de8e3703f2 docs: Perbaiki perintah cargo test --lib jadi cargo test (crate ini tanpa lib target) 2026-07-15 06:32:57 +07:00
asepharyana b7fc335bf5 docs: Tambah implementation plan untuk diff view, @mention, dan clipboard copy 2026-07-15 06:28:49 +07:00
asepharyana 821622e80d docs: Tambah spec desain clipboard copy via OSC52 2026-07-15 06:28:49 +07:00
asepharyana 8fbc51534d docs: Tambah spec desain fuzzy @file-mention autocomplete 2026-07-15 06:28:49 +07:00
asepharyana 3f284cbb9a docs: Tambah spec desain diff view untuk tool edit/write 2026-07-15 06:28:49 +07:00
semantic-release-bot 54484ed137 chore(release): 1.12.0 [skip ci]
# [1.12.0](https://github.com/asepharyana/zesdex/compare/v1.11.0...v1.12.0) (2026-07-14)

### Features

* Add mouse capture functionality to terminal and enhance markdown rendering with table support ([4428e8b](https://github.com/asepharyana/zesdex/commit/4428e8bc01c196415ac408a42f57305227a79760))
* Improve markdown rendering with enhanced line wrapping and indentation for code blocks ([b2e848d](https://github.com/asepharyana/zesdex/commit/b2e848d124e726c4d8b644d473e518398fab1dea))
2026-07-14 21:40:13 +00:00
asepharyana 9bf5236680 refactor: Remove obsolete documentation files and unused test for mouse functionality 2026-07-15 04:36:00 +07:00
asepharyana 4428e8bc01 feat: Add mouse capture functionality to terminal and enhance markdown rendering with table support 2026-07-15 04:36:00 +07:00
asepharyana b2e848d124 feat: Improve markdown rendering with enhanced line wrapping and indentation for code blocks 2026-07-15 04:36:00 +07:00
semantic-release-bot 3020a0431c chore(release): 1.11.0 [skip ci]
# [1.11.0](https://github.com/asepharyana/zesdex/compare/v1.10.0...v1.11.0) (2026-07-14)

### Features

* Enhance subagent tool output handling and clarify workflow directives ([6fbe1e2](https://github.com/asepharyana/zesdex/commit/6fbe1e2d1dc790ba2509803b3ab3a848d5b2a63b))
* Enhance token usage tracking and improve chat UI with emojis ([188e7cc](https://github.com/asepharyana/zesdex/commit/188e7cc9a9233140a5e4953e3f3ff66682914e42))
2026-07-14 20:43:21 +00:00
asepharyana 6fbe1e2d1d feat: Enhance subagent tool output handling and clarify workflow directives 2026-07-15 03:39:15 +07:00
asepharyana 9ba9a5048b refactor: Remove workflow-related commands and overlays from the application 2026-07-15 03:39:15 +07:00
asepharyana 188e7cc9a9 feat: Enhance token usage tracking and improve chat UI with emojis 2026-07-15 03:39:15 +07:00
semantic-release-bot 1a6a0c628e chore(release): 1.10.0 [skip ci]
# [1.10.0](https://github.com/asepharyana/zesdex/compare/v1.9.0...v1.10.0) (2026-07-14)

### Bug Fixes

* align format strings in sidebar Usage widget ([98615ca](https://github.com/asepharyana/zesdex/commit/98615ca5b9d896331a5a6d9af91035aca1f5e9d5))
* use {:>6}: for aligned colons in sidebar Usage widget ([f87ab13](https://github.com/asepharyana/zesdex/commit/f87ab133f1953633f66e21b9eaf7c4eb41291ccd))

### Features

* Implement lesson generation feature and update status display ([1c08b8e](https://github.com/asepharyana/zesdex/commit/1c08b8e4e9c3bb1318535a74c9812beb976df315))
2026-07-14 20:16:30 +00:00
asepharyana 1c08b8e4e9 feat: Implement lesson generation feature and update status display
- Added functionality to generate lessons based on code reviews, including prompts and instructions for the reviewer.
- Updated the `.gitignore` to exclude lesson documentation files.
- Removed the `/lesson` command from the help menu and command parsing.
- Enhanced the status bar to display a message when a lesson is being generated.
- Introduced a new `lesson_running` state to track lesson generation progress.
- Updated various components to handle the new lesson generation workflow, including subagent events and token usage tracking.
2026-07-15 03:11:55 +07:00
asepharyana f87ab133f1 fix: use {:>6}: for aligned colons in sidebar Usage widget
Colons are now at column 9 for all five lines (labels right-aligned
in 6-char field). Values start at column 10. Leading zeros retained
for minutes/seconds via {:02}.

   total: 0 tok
    main: 0 tok
   learn: 0 tok
   calls: 0
    time: 0h 06m 46s
2026-07-15 03:11:55 +07:00
asepharyana 98615ca5b9 fix: align format strings in sidebar Usage widget
All five lines now use consistent label-first '  {:<7} {}' pattern
with aligned colons (column 9) and values (column 10). Elapsed time
uses {:02} leading zeros for minutes/seconds.

Fixes malformed output where some lines used number-first order
('{} tok total') while others used label-first ('main: {} tok'),
causing visual misalignment in the ~28-char-wide sidebar column.
2026-07-15 03:11:55 +07:00
semantic-release-bot 5e6d6deeab chore(release): 1.9.0 [skip ci]
# [1.9.0](https://github.com/asepharyana/zesdex/compare/v1.8.0...v1.9.0) (2026-07-14)

### Bug Fixes

* **workflow:** import Color style for improved agent state rendering ([472c597](https://github.com/asepharyana/zesdex/commit/472c597c5e4ab12808a6bcd1899628bc7ab77186))

### Features

* **agent:** refine cognitive cycle plan with structured phases for exploration, planning, and execution ([c5253b2](https://github.com/asepharyana/zesdex/commit/c5253b2ca359d4dbed9445e04f1dec1a6bb37e8f))
* **subagent:** add progress event handling and formatting for subagent execution ([558908a](https://github.com/asepharyana/zesdex/commit/558908aef216e61a0a108083fbac5e02c31501dc))
* **subagent:** emit reasoning text as progress in StepCompleted events ([97aa75f](https://github.com/asepharyana/zesdex/commit/97aa75f2da37aee5fc7a0626fc396988f089fff2))
* **subagent:** include tool call arguments in ToolResult events and progress formatting ([a8adfcb](https://github.com/asepharyana/zesdex/commit/a8adfcbf6dc5411e977f22ac6b6ba023f563d7c9))
2026-07-14 19:29:20 +00:00
asepharyana c5253b2ca3 feat(agent): refine cognitive cycle plan with structured phases for exploration, planning, and execution 2026-07-15 02:25:15 +07:00
asepharyana a8adfcbf6d feat(subagent): include tool call arguments in ToolResult events and progress formatting 2026-07-15 02:25:15 +07:00
asepharyana 558908aef2 feat(subagent): add progress event handling and formatting for subagent execution 2026-07-15 02:25:15 +07:00
asepharyana 472c597c5e fix(workflow): import Color style for improved agent state rendering 2026-07-15 02:25:15 +07:00
asepharyana 97aa75f2da feat(subagent): emit reasoning text as progress in StepCompleted events 2026-07-15 02:25:15 +07:00
semantic-release-bot dfceb8acac chore(release): 1.8.0 [skip ci]
# [1.8.0](https://github.com/asepharyana/zesdex/compare/v1.7.0...v1.8.0) (2026-07-14)

### Features

* **tools:** require reason argument for delete and git_operator tools ([c6ab063](https://github.com/asepharyana/zesdex/commit/c6ab063c211fb858fd0e155883b9c47b345f0f8a))
2026-07-14 19:05:45 +00:00
asepharyana c6ab063c21 feat(tools): require reason argument for delete and git_operator tools 2026-07-15 02:01:24 +07:00
semantic-release-bot 2af8432ce4 chore(release): 1.7.0 [skip ci]
# [1.7.0](https://github.com/asepharyana/zesdex/compare/v1.6.0...v1.7.0) (2026-07-14)

### Bug Fixes

* **prompt:** perbarui system prompt dari CEO/company ke model hive-mind ([d392c4a](https://github.com/asepharyana/zesdex/commit/d392c4aa00154aae5a0f36db615f05adc385fdb5))
* **runtime:** add check for unconfigured provider to prevent misleading API errors ([181b512](https://github.com/asepharyana/zesdex/commit/181b5128ac1fba47627bf7b377358c782e3481b7))

### Features

* **install:** add installation script for building and symlinking the binary ([4eba9d0](https://github.com/asepharyana/zesdex/commit/4eba9d0a2fbe42b0383eaf872eaeace18cc59a92))
* **protocol:** add Paste request type for bracketed-paste events ([b92dab9](https://github.com/asepharyana/zesdex/commit/b92dab97e6efe1fd6f7c23b28310610c653a57b0))
* **provider:** enhance Claude provider configuration to support environment variable fallback ([4b16bc3](https://github.com/asepharyana/zesdex/commit/4b16bc31125018ad3d3e46706881596a226f5352))
* **runtime:** implement JSON repair function for truncated tool-call arguments ([e13f040](https://github.com/asepharyana/zesdex/commit/e13f04083313f3544bdb1a76b5ecd535ecf59e4f))
* **stream:** add method to detect incomplete tool calls and handle parsing errors ([732d603](https://github.com/asepharyana/zesdex/commit/732d6039dc23bc8ec323bc4f91be9a7131a61ef6))
2026-07-14 18:59:09 +00:00
asepharyana b92dab97e6 feat(protocol): add Paste request type for bracketed-paste events
feat(engine): summarize agent completion progress in UI notifications

feat(main): enable and disable bracketed paste support in terminal

fix(app_config): store API key from file as fallback for Claude provider

refactor(workflow): remove unnecessary card separator in workflow panel
2026-07-15 01:54:36 +07:00
asepharyana e13f040833 feat(runtime): implement JSON repair function for truncated tool-call arguments 2026-07-15 01:42:15 +07:00
asepharyana 4b16bc3112 feat(provider): enhance Claude provider configuration to support environment variable fallback 2026-07-15 01:06:36 +07:00
asepharyana 181b5128ac fix(runtime): add check for unconfigured provider to prevent misleading API errors 2026-07-15 00:59:32 +07:00
asepharyana 732d6039dc feat(stream): add method to detect incomplete tool calls and handle parsing errors 2026-07-15 00:49:50 +07:00
asepharyana 4eba9d0a2f feat(install): add installation script for building and symlinking the binary 2026-07-15 00:25:53 +07:00
asepharyana 7fccc16a54 refactor(engine, hive_mind): update terminology from 'agents' to 'drones' and enhance logging for clarity 2026-07-15 00:24:49 +07:00
asepharyana b5e3dfe4b1 refactor(hive_mind): enhance documentation for clarity and consistency in terminology 2026-07-15 00:22:59 +07:00
asepharyana 519be7559b refactor(prompts): update reviewer prompts to align with Hive's directive and contamination protocols 2026-07-15 00:20:41 +07:00
asepharyanaandClaude Sonnet 5 d392c4aa00 fix(prompt): perbarui system prompt dari CEO/company ke model hive-mind
src-misc/system-prompt.txt masih memakai framing lama "Zesdex Corp
CEO / 5 divisi" dan mereferensikan tool run_company_pipeline yang
sudah tidak ada, tertinggal saat commit 25f084f merombak arsitektur
ke hive-mind (CLAUDE.md, README.md, dan implementasi workflow_run
sudah diupdate saat itu, tapi file prompt utama ini terlewat).
Akibatnya AI membalas dengan persona CEO/company, bukan Core
Intelligence/hive-mind seperti didokumentasikan di README.md.

- system-prompt.txt: tulis ulang total ke model Core Intelligence /
  cognitive cycle plan / processing node / access tier, konsisten
  dengan CLAUDE.md dan tool hive_mind yang sebenarnya.
- system-tools.txt: tambah entri hive_mind dan read_findings yang
  sebelumnya tidak ada sama sekali di daftar tool.
- workflow.rs: perbaiki sisa teks "divisions/subagents" di deskripsi
  tool read_findings jadi "nodes/subagents".

Diverifikasi live: AI sekarang memperkenalkan diri sebagai "Core
Intelligence of Zesdex ... modeled as a hive-mind" alih-alih CEO.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:55:49 +07:00
semantic-release-bot 340ae2fde2 chore(release): 1.6.0 [skip ci]
# [1.6.0](https://github.com/asepharyana/zesdex/compare/v1.5.0...v1.6.0) (2026-07-14)

### Bug Fixes

* perbaiki 5 warning clippy pre-existing (base untuk TUI overhaul) ([6b58977](https://github.com/asepharyana/zesdex/commit/6b58977875f809f19cc2d7bb9b2a7dd057d0229e))
* **tui:** perbaiki isi overlay Todo dan Usage jadi tampilan detail nyata ([aaea300](https://github.com/asepharyana/zesdex/commit/aaea300699f7e76cdc689e225e7c4c3bc164e8d4))
* **tui:** perbaiki potensi terpotongnya baris token di widget Usage sidebar ([7fd55fa](https://github.com/asepharyana/zesdex/commit/7fd55fa86dfe8f9a4581f02fa9220cd5d1ba600c))
* **tui:** perbaiki rendering multi-baris pada pesan Tool ([2f1a4d8](https://github.com/asepharyana/zesdex/commit/2f1a4d85a1fdc9cbfb81912a3206c057ad9d1ed5))

### Features

* **tui:** ganti palet warna ke Tokyo Night ([7a9cb7b](https://github.com/asepharyana/zesdex/commit/7a9cb7bf342367c81fb4a1568675e46f132a8afc))
* **tui:** rombak rendering chat jadi format log rapat ([e34708a](https://github.com/asepharyana/zesdex/commit/e34708a3191bef63d191e76dee39a58a33e4ad5f))
* **tui:** tambah command /todo dan /usage untuk buka overlay ([aa2b6ac](https://github.com/asepharyana/zesdex/commit/aa2b6acb95f8518950b8b7d9c3c9e10968936162))
* **tui:** tambah dan pasang sidebar dashboard permanen ([31c01cd](https://github.com/asepharyana/zesdex/commit/31c01cdf1df6827c3a949820378c8b85ebcfdf87))
2026-07-14 16:45:55 +00:00
asepharyana 1010e44b22 Implement new feature for user authentication and improve error handling 2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 b355c9928e style(tui): hapus emoji dekoratif dari judul overlay
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 aaea300699 fix(tui): perbaiki isi overlay Todo dan Usage jadi tampilan detail nyata
Overlay Todo sebelumnya menampilkan jumlah pesan yang tidak relevan,
bukan isi task list. Overlay Usage sekarang pakai compute_usage_summary
yang sama dengan widget sidebar (DRY, angka konsisten).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 7fd55fa86d fix(tui): perbaiki potensi terpotongnya baris token di widget Usage sidebar
Baris pertama widget Usage sebelumnya bisa melebihi lebar kolom sidebar
(30 kolom) pada sesi dengan jumlah token besar, menyebabkan teks
terpotong diam-diam tanpa wrap. Sekarang dipecah jadi beberapa baris
pendek yang aman di lebar berapa pun yang realistis.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 31c01cdf1d feat(tui): tambah dan pasang sidebar dashboard permanen
Sidebar kanan permanen (Workflow/Tasks/Usage) menggantikan panel todo
ad-hoc yang lama. Widget baca state yang sudah ada, tidak ada perubahan
skema AppStateRest.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 aa2b6acb95 feat(tui): tambah command /todo dan /usage untuk buka overlay
Overlay Todo dan Usage sebelumnya tidak punya trigger sama sekali di
jalur interaksi normal (cuma bisa lewat restore snapshot sesi) --
sekarang mengikuti pola /workflow yang sudah ada.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 2f1a4d85a1 fix(tui): perbaiki rendering multi-baris pada pesan Tool
Konten Tool sebelumnya didorong sebagai satu Span tanpa split newline,
sehingga output tool multi-baris (stdout bash, hasil grep, diff)
tampil sebagai karakter \n literal alih-alih baris terpisah. Sekarang
mengikuti pola render_markdown + split_spans_into_lines yang sama
dengan role lain.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 e34708a319 feat(tui): rombak rendering chat jadi format log rapat
markdown.rs juga disesuaikan: indentasi paragraf/heading bawaannya
dilepas supaya tidak bentrok dengan indent PREFIX_WIDTH di chat.rs
(baris pertama vs baris wrap lanjutan jadi sejajar).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 6b58977875 fix: perbaiki 5 warning clippy pre-existing (base untuk TUI overhaul)
unnested_or_patterns, collapsible_if, items_after_statements, dan
case_sensitive_file_extension_comparisons di auto.rs, engine.rs, dan
actions/mod.rs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 7a9cb7bf34 feat(tui): ganti palet warna ke Tokyo Night
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
asepharyanaandClaude Sonnet 5 04e7ff9380 docs: tambah spec desain rombak TUI (Multi-Pane Dashboard, Tokyo Night)
Spec brainstorming untuk rombak total src/view + src/controller: layout
Multi-Pane Dashboard dengan sidebar Workflow/Tasks/Usage, palet Tokyo
Night, dan format chat inline rapat.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:41:53 +07:00
semantic-release-bot 7070c96460 chore(release): 1.5.0 [skip ci]
# [1.5.0](https://github.com/asepharyana/zesdex/compare/v1.4.0...v1.5.0) (2026-07-14)

### Bug Fixes

* **hive-mind:** ganti gerbang pipeline berbasis jumlah pesan dengan deteksi konvergensi sebelumnya ([5498088](https://github.com/asepharyana/zesdex/commit/5498088532314f8dbc005d5e8058c0170ca92320))
* **hive-mind:** gunakan flag SessionRuntime sebagai sinyal konvergensi otoritatif ([28e763a](https://github.com/asepharyana/zesdex/commit/28e763a695f56adfbecd4efb14edbde13bbd63dc))
* **hive-mind:** hapus penulisan docs/runs ganda dan sambungkan abort_flag ke tool hive_mind manual ([a125f5d](https://github.com/asepharyana/zesdex/commit/a125f5d4400b0c417ba4049e67480bd18479e90b))
* **hive-mind:** tambah timeout per-node dan jamin dokumentasi convergence tetap tertulis saat sintesis gagal ([b1c0265](https://github.com/asepharyana/zesdex/commit/b1c0265e8cdf9278664e64f77fbde4ec8c22fcfd))
* **subagent:** panic-proof overlap guards and update stale docs ([e023f2c](https://github.com/asepharyana/zesdex/commit/e023f2c5a8f036d89e925bb9ceec253343476a74))
* **subagent:** perbaiki filter is_production_code berbasis substring dan tambah pembatalan/anti-tumpang-tindih pada background review ([1039f67](https://github.com/asepharyana/zesdex/commit/1039f67c12749c6b2c93e3ab7037feded8ab01c6))
* **tui:** perbaiki roster workflow yang tidak pernah ter-reset karena substring "started" tidak pernah cocok ([fdd62f8](https://github.com/asepharyana/zesdex/commit/fdd62f830330b5b3e2b4f9fcc7274daf7f7842a5))

### Features

* **settings:** tambah hive_mind_node_timeout_ms dengan fallback serde default ([e2878a3](https://github.com/asepharyana/zesdex/commit/e2878a3d83f171aa181ac29ca689828e0cb1408f))
* **tool:** tambah abort_flag ke ToolCtx dan sambungkan dari session state ([79e2bfc](https://github.com/asepharyana/zesdex/commit/79e2bfcc9ca67424ca2b34a5652d3c2bb93291bf))
2026-07-14 03:59:10 +00:00
asepharyanaandClaude Sonnet 5 28e763a695 fix(hive-mind): gunakan flag SessionRuntime sebagai sinyal konvergensi otoritatif
Pesan sistem bertanda [Hive-Mind Consensus] hanya di-push ke variabel lokal
run_agent_turn dan diarsipkan ke SQLite, tidak pernah masuk ke
rt.messages lewat TurnEvent — sehingga hive_mind_already_ran selalu
memindai daftar pesan yang kosong dan gerbang "converge sekali per sesi"
tidak pernah aktif. Tambahkan SessionRuntime.hive_mind_converged yang
diset dari event TurnEvent::SystemNote { kind: "hive_mind_converged" }
setelah konvergensi selesai, disalurkan lewat TurnCtx, dan dijadikan
sinyal utama di run_agent_turn (pemindaian pesan lama tetap sebagai
fallback defensif).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 3e6f9a6a5f test(subagent): tambah pengujian invarian read⊆write⊆full pada tool_scope
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 e023f2c5a8 fix(subagent): panic-proof overlap guards and update stale docs
RunningGuard resets TEST_GEN_RUNNING/ARCH_REVIEW_RUNNING/SECURITY_REVIEW_RUNNING
via Drop so a subagent panic can no longer wedge that review kind disabled
for the rest of the process. Doc comments on run_subagent_with_retry and the
three spawn_background_* / spawn_all_background functions now describe the
abort_flag and overlap-guard behavior added in Task 7.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 1039f67c12 fix(subagent): perbaiki filter is_production_code berbasis substring dan tambah pembatalan/anti-tumpang-tindih pada background review
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 fdd62f8303 fix(tui): perbaiki roster workflow yang tidak pernah ter-reset karena substring "started" tidak pernah cocok
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 5498088532 fix(hive-mind): ganti gerbang pipeline berbasis jumlah pesan dengan deteksi konvergensi sebelumnya
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 a125f5d440 fix(hive-mind): hapus penulisan docs/runs ganda dan sambungkan abort_flag ke tool hive_mind manual
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 79e2bfcc9c feat(tool): tambah abort_flag ke ToolCtx dan sambungkan dari session state
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 b1c0265e8c fix(hive-mind): tambah timeout per-node dan jamin dokumentasi convergence tetap tertulis saat sintesis gagal
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 e2878a3d83 feat(settings): tambah hive_mind_node_timeout_ms dengan fallback serde default
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
asepharyanaandClaude Sonnet 5 6790fe481b docs: tambah rencana implementasi perbaikan hive-mind dan subagent
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:55:05 +07:00
semantic-release-bot d0c7fe4096 chore(release): 1.4.0 [skip ci]
# [1.4.0](https://github.com/asepharyana/zesdex/compare/v1.3.0...v1.4.0) (2026-07-14)

### Features

* **hive-mind:** implement multi-agent orchestration with cognitive cycles ([25f084f](https://github.com/asepharyana/zesdex/commit/25f084f9dbb5047c5c91aedcb582d35f4ff95395))
2026-07-14 01:16:53 +00:00
asepharyana 25f084f9db feat(hive-mind): implement multi-agent orchestration with cognitive cycles
- Introduced a new hive-mind architecture that allows the Core Intelligence to issue directives to anonymous processing nodes.
- Each node executes its directive and merges output into a collective state, visible to all nodes in real-time.
- Added support for dynamic cognitive cycles, enabling flexible task management.
- Implemented documentation generation for hive-mind runs, ensuring a durable record of decisions and actions.
- Refactored existing company pipeline tools to align with the new hive-mind structure, replacing division-specific prompts with a more generalized approach.
- Updated workflow rendering to accommodate hive-mind nodes and their system-assigned designations.
- Enhanced error handling and validation for cognitive cycle plans.
2026-07-14 08:12:43 +07:00
semantic-release-bot b1e0dcae14 chore(release): 1.3.0 [skip ci]
# [1.3.0](https://github.com/asepharyana/zesdex/compare/v1.2.0...v1.3.0) (2026-07-13)

### Features

* enhance edit logging in subagent execution and streamline edit tracking in run_agent_turn ([c60fadb](https://github.com/asepharyana/zesdex/commit/c60fadb88ae63788a5bbe3c3443e2ce826e5778f))
2026-07-13 07:51:20 +00:00
asepharyana c60fadb88a feat: enhance edit logging in subagent execution and streamline edit tracking in run_agent_turn 2026-07-13 14:47:03 +07:00
semantic-release-bot 4a297669b4 chore(release): 1.2.0 [skip ci]
# [1.2.0](https://github.com/asepharyana/zesdex/compare/v1.1.0...v1.2.0) (2026-07-13)

### Features

* enhance responsiveness by implementing abort checks in streaming API calls ([0d6f558](https://github.com/asepharyana/zesdex/commit/0d6f558b2bd0282a7a1695f7680ab1d1c6142579))
* refactor agent step limits and enhance workflow orchestration with new findings tool ([3b660e0](https://github.com/asepharyana/zesdex/commit/3b660e09a87f3e982db94f48d2282ddb63116341))
* remove pipeline command and refactor workflow execution to use custom specialists ([00e2913](https://github.com/asepharyana/zesdex/commit/00e29139c53c5fed4c13b0493297dd9da984460c))
* update overlay handling in apply_action and remove mouse capture from terminal execution ([2e351cc](https://github.com/asepharyana/zesdex/commit/2e351ccf6930ff4823f55b581308222229fe6684))
* update README and documentation for new tools and features ([1d50b94](https://github.com/asepharyana/zesdex/commit/1d50b94eec1ed82dfc40d43d41bd01aeb79edfe1))
2026-07-13 07:43:49 +00:00
asepharyana 2e351ccf69 feat: update overlay handling in apply_action and remove mouse capture from terminal execution 2026-07-13 14:39:39 +07:00
asepharyana 1d50b94eec feat: update README and documentation for new tools and features
- Updated README.md to reflect the addition of 3 new built-in tools, bringing the total to 37.
- Revised architecture documentation to indicate the increase in tool count.
- Enhanced backend documentation with updated line counts for various modules.
- Modified data documentation to change edit log format from JSON to JSONL.
- Updated dependencies documentation to reflect version upgrades for several crates.
- Improved prompts for auto-reviewer, division implementer, planner, tester, and quality reviewer to enforce stricter coding standards regarding linter bypasses.
- Refactored code in various modules to improve clarity and performance, including updates to error handling and tool execution logic.
- Added comprehensive tests for IPC frame serialization and deserialization.
2026-07-13 14:39:39 +07:00
asepharyana 00e29139c5 feat: remove pipeline command and refactor workflow execution to use custom specialists 2026-07-13 14:39:39 +07:00
asepharyana 3b660e09a8 feat: refactor agent step limits and enhance workflow orchestration with new findings tool 2026-07-13 14:39:39 +07:00
asepharyana 0d6f558b2b feat: enhance responsiveness by implementing abort checks in streaming API calls 2026-07-13 14:39:39 +07:00
semantic-release-bot 8388a83af0 chore(release): 1.1.0 [skip ci]
# [1.1.0](https://github.com/asepharyana/zesdex/compare/v1.0.4...v1.1.0) (2026-07-13)

### Features

* implement abort mechanism for workflows and subagents ([104b0da](https://github.com/asepharyana/zesdex/commit/104b0daf4cc51581de04f03d6b727cdb16f9b6c3))
2026-07-13 02:13:34 +00:00
asepharyana 104b0daf4c feat: implement abort mechanism for workflows and subagents 2026-07-13 09:09:23 +07:00
asepharyana 65647ce517 Update dependencies and refactor SHA256 hash encoding
- Updated `crossterm` from version 0.28 to 0.29.
- Upgraded `reqwest` from version 0.12 to 0.13 and added "form" feature.
- Bumped `serde_yaml_ng` from version 0.9 to 0.10.
- Increased `dirs` version from 5 to 6.
- Updated `rusqlite` from version 0.32 to 0.40.
- Upgraded `infer` from version 0.16 to 0.19.
- Bumped `sha2` from version 0.10 to 0.11.
- Updated `rmcp` from version 1.8 to 2.2.
- Refactored SHA256 hash encoding in `rewind.rs`, `mod.rs`, and `rest.rs` to use `hex::encode` instead of formatting with `{:x}` for better clarity and consistency.
2026-07-13 08:39:14 +07:00
semantic-release-bot 152b245f5e chore(release): 1.0.4 [skip ci]
## [1.0.4](https://github.com/asepharyana/zesdex/compare/v1.0.3...v1.0.4) (2026-07-13)

### Bug Fixes

* remove redundant ref in format! argument ([0155a04](https://github.com/asepharyana/zesdex/commit/0155a04ceeec7f7f234c08a7f56e9a4384691655))
2026-07-13 01:18:40 +00:00
asepharyana 0155a04cee fix: remove redundant ref in format! argument 2026-07-13 08:16:40 +07:00
semantic-release-bot ab07d094b4 chore(release): 1.0.3 [skip ci]
## [1.0.3](https://github.com/asepharyana/zesdex/compare/v1.0.2...v1.0.3) (2026-07-13)
2026-07-13 01:14:27 +00:00
asepharyana 29a9fae3f6 ci: add GitHub Actions workflows with semantic-release auto-versioning
chore: fix all 702 clippy warnings across codebase
- auto-fix 475 via cargo clippy --fix
- fix remaining 227 manually: uninlined_format_args, redundant_closure, match_same_arms,
  underscore_binding, format_push_string, items_after_statements, needless_pass_by_value,
  clone_on_copy, case_sensitive_extension, single_match/let-else, write_with_newline,
  and other clippy lints
2026-07-13 08:12:12 +07:00
432 changed files with 31361 additions and 20856 deletions
+26
View File
@@ -0,0 +1,26 @@
# Rust build artifacts
target/
# VCS
.git/
.gitignore
# Local/secret files
.env
.env.*
!.env.example
# Editor
.idea/
.vscode/
*.swp
# Nix
result
result-*
# Kilo metadata
.kilo/
# Docs lessons
docs/lesson/
+9 -4
View File
@@ -18,9 +18,14 @@ jobs:
- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: clippy
- name: Build
run: cargo build --release
- name: Format check
run: cargo fmt --all -- --check
- name: Test
run: cargo test
- name: Clippy workspace
run: cargo clippy --workspace --all-targets -- -D warnings
- name: Test workspace
run: cargo test --workspace
+61
View File
@@ -0,0 +1,61 @@
name: Build & Deploy (Nix)
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: deploy
cancel-in-progress: false
permissions:
contents: read
env:
VPS_HOST: ${{ secrets.VPS_HOST }}
VPS_USER: ${{ secrets.VPS_USER }}
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v22
with:
determinate: false
extra-conf: |
sandbox = false
accept-flake-config = true
- name: Cache Nix
uses: DeterminateSystems/magic-nix-cache-action@v14
- name: Build zesdex
id: build
run: |
nix build .#default --impure --option sandbox false --print-build-logs
STORE_PATH=$(readlink result)
echo "store-path=$STORE_PATH" >> "$GITHUB_OUTPUT"
echo "Build OK: $STORE_PATH"
- name: Setup SSH key
env:
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh
echo "$SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
sed -i 's/\r$//' ~/.ssh/id_ed25519
ssh-keygen -y -f ~/.ssh/id_ed25519 >/dev/null 2>&1 || { echo "SSH key invalid"; exit 1; }
ssh-keyscan -H "$VPS_HOST" >> ~/.ssh/known_hosts 2>/dev/null
- name: Deploy zesdex to VPS
run: |
STORE_PATH="${{ steps.build.outputs.store-path }}"
ssh "$VPS_USER@$VPS_HOST" "nix copy --to file:///nix/store $STORE_PATH && nix-env --install --force $STORE_PATH --profile /nix/var/nix/profiles/zesdex && systemctl restart zesdex"
@@ -0,0 +1,20 @@
name: Publish to FlakeHub
on:
push:
branches: [main, master]
workflow_dispatch:
jobs:
flakehub-publish:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v6
- uses: DeterminateSystems/determinate-nix-action@main
- uses: DeterminateSystems/flakehub-push@main
with:
visibility: public
rolling: true
+2 -2
View File
@@ -20,10 +20,10 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Build
run: cargo build --release
run: cargo build --release --workspace
- name: Test
run: cargo test
run: cargo test --workspace
release:
name: Semantic Release
+5 -1
View File
@@ -3,4 +3,8 @@ target/
.claude/settings.local.json
node_modules/
package.json
package-lock.json
package-lock.json
.superpowers/
docs/lesson/
.kilo/
.hermes/
+18
View File
@@ -0,0 +1,18 @@
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
["@semantic-release/exec", {
"prepareCmd": "sed -i 's/^version = \"[^\"]*\"/version = \"${nextRelease.version}\"/' Cargo.toml && cargo check"
}],
["@semantic-release/git", {
"assets": ["Cargo.toml", "CHANGELOG.md"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}],
["@semantic-release/github", {
"assets": []
}]
]
}
-20
View File
@@ -1,20 +0,0 @@
Codemap Update Report — 2026-07-12
====================================
Status: FIRST GENERATION (no previous codemaps to compare)
Files created:
- docs/CODEMAPS/architecture.md (new)
- docs/CODEMAPS/backend.md (new)
- docs/CODEMAPS/frontend.md (new)
- docs/CODEMAPS/data.md (new)
- docs/CODEMAPS/dependencies.md (new)
Source scanned:
- 124 Rust source files
- 30 directories
- 103 modules
- 10,402 lines total
No previous codemaps found — diff calculation skipped.
Freshness: all documents generated 2026-07-12.
+38
View File
@@ -0,0 +1,38 @@
# AGENTS.md
This file provides guidance to Kilo when working with code in the zesdex repository.
## Best Practice Conventions
Zesdex follows Kana Engineering Best Practices:
1. **Clean Architecture** — Strict domain/application/infrastructure/presentation layering.
- Domain has ZERO framework dependencies.
- Application depends only on domain.
- Infrastructure implements domain traits.
- DTOs cross layer boundaries, NOT entities.
2. **Clean Code** — Functions under ~40 lines, one level of abstraction per function, descriptive names, no flag arguments, no commented-out code.
3. **Documentation** — Every pub fn, struct, enum, and trait needs a doc comment (///) explaining what, flow, why, and return value.
4. **Commit Convention** — Conventional Commits in Bahasa Indonesia: `feat(scope):`, `fix(scope):`, `chore:`, `docs:`.
5. **Error Handling**`anyhow::Result` and `anyhow::bail!` throughout. Log with `tracing` (never stderr).
6. **Testing**`#[cfg(test)] mod tests` blocks inline in production files. Tests are F.I.R.S.T. (Fast, Independent, Repeatable, Self-validating, Timely).
7. **No Compiler Bypasses** — Never use `#[allow(...)]`, `#[expect(...)]`, or `#[allow(dead_code)]`. Fix the underlying code.
8. **Boy Scout Rule** — Leave every module cleaner than you found it.
## Available Agents
- `@rust-engineer` — Rust clean architecture specialist (subagent).
- `@code-reviewer` — Code review specialist (subagent).
## Available Commands
- `/check` — Run cargo check, clippy, and tests.
- `/audit` — Code quality audit against clean-architecture best practices.
- `/doc` — Generate or update doc comments.
+366
View File
@@ -1,3 +1,369 @@
## [1.19.6](https://github.com/asepharyana/zesdex/compare/v1.19.5...v1.19.6) (2026-08-27)
### Performance Improvements
* **agent:** eksekusi tool read-only paralel seperti Claude Code ([74b1ad4](https://github.com/asepharyana/zesdex/commit/74b1ad43020a11ca27e60e3a24de0db5d1ab37b4))
## [1.19.5](https://github.com/asepharyana/zesdex/compare/v1.19.4...v1.19.5) (2026-08-27)
### Bug Fixes
* **api:** model Opus default pakai claude-opus-5 (bukan -4-8) ([b28a5fe](https://github.com/asepharyana/zesdex/commit/b28a5fe384fd45255a6b249c7febd3b4ffc0fd2f))
* **api:** update zesdex packages to version 1.19.4 ([b46935c](https://github.com/asepharyana/zesdex/commit/b46935c606d4f68ea227c7db27e4c2aa9b4e373c))
## [1.19.4](https://github.com/asepharyana/zesdex/compare/v1.19.3...v1.19.4) (2026-08-27)
### Bug Fixes
* **api:** model claude selalu pakai Opus dari settings.json, bukan deepseek ([9aca45c](https://github.com/asepharyana/zesdex/commit/9aca45cb65d6913d14fecc10d70c180934f69d74))
## [1.19.3](https://github.com/asepharyana/zesdex/compare/v1.19.2...v1.19.3) (2026-08-27)
### Bug Fixes
* **api:** model Opus pakai URL + API custom dari ~/.claude/settings.json ([1f91b44](https://github.com/asepharyana/zesdex/commit/1f91b447080e7106201d77585edb7d38b74e34bb))
## [1.19.2](https://github.com/asepharyana/zesdex/compare/v1.19.1...v1.19.2) (2026-08-27)
### Performance Improvements
* **agent:** stabilkan async & parallel — satu runtime, bounded concurrency, isolasi error ([6a98d52](https://github.com/asepharyana/zesdex/commit/6a98d52d54a69f78710d852a69dda3ac0a4ead31))
## [1.19.1](https://github.com/asepharyana/zesdex/compare/v1.19.0...v1.19.1) (2026-08-27)
### Performance Improvements
* **agent:** rombak alur AI agent — adaptif, hemat token, self-healing ([eac0443](https://github.com/asepharyana/zesdex/commit/eac0443c4c3b8bfcbefd4bad9554168fb6525b94))
# [1.19.0](https://github.com/asepharyana/zesdex/compare/v1.18.4...v1.19.0) (2026-08-27)
### Features
* hapus fitur LSP bawaan (language server protocol) ([93f3c2a](https://github.com/asepharyana/zesdex/commit/93f3c2a3572511b5a84f244980ad71bd1b455e70))
## [1.18.4](https://github.com/asepharyana/zesdex/compare/v1.18.3...v1.18.4) (2026-08-27)
### Performance Improvements
* **tui:** render streaming token secara inkremental + kurangi redraw sia-sia ([2717216](https://github.com/asepharyana/zesdex/commit/271721694beb62e9fa5ff932312b293aa1d56823))
## [1.18.3](https://github.com/asepharyana/zesdex/compare/v1.18.2...v1.18.3) (2026-08-27)
### Bug Fixes
* **api:** cegah race condition pada register users.json (TOCTOU) ([884b19c](https://github.com/asepharyana/zesdex/commit/884b19ccb5fbcaa6b29cb41dc978386cf7b1b3f9))
* **api:** perbaiki keamanan auth & WebSocket, tambah rate limiting ([6db00b2](https://github.com/asepharyana/zesdex/commit/6db00b22663839a6a975ae978058b894900c71de))
* **build:** perbaiki referensi paket zesdex-gateway dan sinkronisasi versi nix ([6d3f491](https://github.com/asepharyana/zesdex/commit/6d3f4918bfea06b106d4fe75adf58e6a29aca2a5))
* **build:** perbaiki referensi paket zesdex-gateway di Dockerfile & default.nix ([7f64423](https://github.com/asepharyana/zesdex/commit/7f644236158f66fcc106ec55e437ebf28ee1cca1))
## [1.18.2](https://github.com/asepharyana/zesdex/compare/v1.18.1...v1.18.2) (2026-08-20)
### Bug Fixes
* **nix:** add perl to nativeBuildInputs for openssl-sys Configure ([033f964](https://github.com/asepharyana/zesdex/commit/033f964be0c695106eef74329524ad7b4b8dba14))
* **nix:** correct cargoBuildFlags package name zesdex-backend -> zesdex-gateway ([2de5b57](https://github.com/asepharyana/zesdex/commit/2de5b57133f6c7295d8a85e63cb86504ea2a7d3e))
## [1.18.1](https://github.com/asepharyana/zesdex/compare/v1.18.0...v1.18.1) (2026-08-01)
### Bug Fixes
* **nix:** restrict flake to x86_64-linux (nixpkgs 26.11 dropped darwin) ([0e0fd5d](https://github.com/asepharyana/zesdex/commit/0e0fd5df05e53a6fa17d481825f1a8c567214d0e))
# [1.18.0](https://github.com/asepharyana/zesdex/compare/v1.17.0...v1.18.0) (2026-07-22)
### Bug Fixes
* add .releaserc.json for semantic-release configuration ([047d718](https://github.com/asepharyana/zesdex/commit/047d7183d72adaa0dd1a18a7f92b22d67d5aa85f))
* **clippy:** replace type annotation with type alias + .insert() to avoid trivial_cast ([ffefa8c](https://github.com/asepharyana/zesdex/commit/ffefa8c07facbba83778f426ca4715569556b08a))
* **rust:** remove unused imports, variables, and dead code causing CI build failures ([eb8cc17](https://github.com/asepharyana/zesdex/commit/eb8cc1799359a5ef5b4a4ee3a4202b87e80bfe6c))
* **rust:** resolve all clippy warnings treated as errors in CI ([6b90c7e](https://github.com/asepharyana/zesdex/commit/6b90c7eb0d17d9281a377454e76dcc88a4232bc7))
* **tui:** resolve remaining clippy errors in workspace ([eed4025](https://github.com/asepharyana/zesdex/commit/eed4025918de65eb2f3fd98cd3350d62f3322132))
### Features
* add semantic search tool for code symbol indexing and searching ([fef3c92](https://github.com/asepharyana/zesdex/commit/fef3c925cd02e1d76e2d990cc6fa4e4cba64fab0))
* Add SOLID principles and TDD reference documentation ([55677dd](https://github.com/asepharyana/zesdex/commit/55677dd67100813a5ed2b0bbf02257b57875ea07))
* add test_load and test_parse binaries for configuration loading and parsing ([fe2e916](https://github.com/asepharyana/zesdex/commit/fe2e9169371bf7a3cc9391d8467d47fc2258ad1f))
* **agent:** add AI summarization for conversation history compacting ([873f870](https://github.com/asepharyana/zesdex/commit/873f870e233dd0d2c6f0cce935f83fb8ce373505))
* **agent:** implement agent execution engine and turn handling with background processing ([efcd191](https://github.com/asepharyana/zesdex/commit/efcd191f9698023944f9096a86c1efa47e412b6b))
* **best_practice:** add code quality scanning and commit message validation ([8ecc588](https://github.com/asepharyana/zesdex/commit/8ecc588a3e125dc6a4b2e7eb4c12c6b344449c07))
* centralize default constants and refactor overlay enter handling in TUI ([d615090](https://github.com/asepharyana/zesdex/commit/d615090dcd34bdb93be22c1c7ce4ba674363c258))
* enhance context gathering in auto-review engine and agent runner ([dcc8c3e](https://github.com/asepharyana/zesdex/commit/dcc8c3ee42ef568843e04143048d799bc0882288))
* enhance explore phase with TUI workflow event handling ([b3a4d13](https://github.com/asepharyana/zesdex/commit/b3a4d131d13d94bd307720cb50c2d02dedf92873))
* implement Component trait for modular UI components and refactor TUI views to use it ([d59713d](https://github.com/asepharyana/zesdex/commit/d59713d3e3aa4325f9753bbddd068654e442f6ef))
* implement mandatory explore phase with parallel subagents ([f368f3a](https://github.com/asepharyana/zesdex/commit/f368f3a1c0d2df02eb50542a81bcff96d9cdc420))
* **llm:** improve tool call handling by dynamically resizing tool_calls and updating arguments ([9bfb95d](https://github.com/asepharyana/zesdex/commit/9bfb95d795d6c7cc10cfcb907642bba7b8bb7f19))
* **llm:** improve UTF-8 handling in response processing to prevent infinite loops ([7ea2265](https://github.com/asepharyana/zesdex/commit/7ea226509c8e11ee1bab21d216e0413715988fb9))
* **llm:** increase max retries for streaming requests from 3 to 10 ([6c7995f](https://github.com/asepharyana/zesdex/commit/6c7995f5f5481c48ccd449e72d9563425fdcb837))
* **mcp:** enhance MCP server registration with error handling and improve transport process management ([148ba4e](https://github.com/asepharyana/zesdex/commit/148ba4e07b424736c6b4824c5786c0c7c9cbf0a1))
* refactor auto-review engine to use spawn_subagent for improved thread handling ([094eb4b](https://github.com/asepharyana/zesdex/commit/094eb4b8baa5abd878dcf5b611cf615955bc79eb))
* remove obsolete design documents for clipboard OSC52, diff view, file mention, context compaction, and add development guide ([66ac4db](https://github.com/asepharyana/zesdex/commit/66ac4dbf027820697f4303264666b5f63a0b31d4))
* **tui:** add rich context information including active jobs, README snippet, and recent git history ([2f5f62a](https://github.com/asepharyana/zesdex/commit/2f5f62ab097614d8b0c7a3e5c7bd364cd479e0aa))
* **tui:** add support for reasoning in chat messages and update transcript handling ([285dbb1](https://github.com/asepharyana/zesdex/commit/285dbb14cccb1c261134c1fcb6c30ef1ed02bb55))
* **tui:** enhance agent turn handling by grouping parameters and improving message management ([07b217c](https://github.com/asepharyana/zesdex/commit/07b217cf4a81b99c63101512932935246fcbc7ae))
* **tui:** enhance system prompt with workspace structure information ([bed9f8c](https://github.com/asepharyana/zesdex/commit/bed9f8cff60711c4db998c8f10f32f8e210ae410))
* **tui:** implement streaming support for LLM responses and update transcript handling ([cac6626](https://github.com/asepharyana/zesdex/commit/cac662658651ae092cffddfc88f39a775afef942))
* **tui:** integrate rich context builder into agent turn process ([919435e](https://github.com/asepharyana/zesdex/commit/919435eb84f9a41a0637052a5dc1234b410714f8))
* **tui:** introduce comprehensive state management for TUI interface ([8c58faf](https://github.com/asepharyana/zesdex/commit/8c58faf2920b7341dd50ace15044ff113cefb576))
* **tui:** optimize performance by caching display lines and token counts, and improve action handling ([87abe8c](https://github.com/asepharyana/zesdex/commit/87abe8c3358ac17196df93d19169901a856850d3))
* **tui:** update system message for clarity and conciseness in tool usage instructions ([5a373d1](https://github.com/asepharyana/zesdex/commit/5a373d1031b476970bd45804a65c7455be99e78d))
# [1.17.0](https://github.com/asepharyana/zesdex/compare/v1.16.1...v1.17.0) (2026-07-20)
### Features
* **token:** add refresh token verification to TokenService ([a046519](https://github.com/asepharyana/zesdex/commit/a04651905f4afd562b516c839449a2c813ce6627))
## [1.16.1](https://github.com/asepharyana/zesdex/compare/v1.16.0...v1.16.1) (2026-07-20)
# [1.16.0](https://github.com/asepharyana/zesdex/compare/v1.15.2...v1.16.0) (2026-07-20)
### Features
* **tui:** add usage overlay and sidebar for displaying usage statistics and tasks ([da2ed6d](https://github.com/asepharyana/zesdex/commit/da2ed6da25953b823354cc5deaa7b404b7b13cb0))
* **tui:** enhance agent turn with tool descriptions and sanitize arguments ([08e2f99](https://github.com/asepharyana/zesdex/commit/08e2f9998d3693e4cd57225491359c762d03f1d9))
* **tui:** implement agent turn engine for background processing and enhance input handling ([792695b](https://github.com/asepharyana/zesdex/commit/792695b65a393cfc54efe353480b7831e91544b5))
## [1.15.2](https://github.com/asepharyana/zesdex/compare/v1.15.1...v1.15.2) (2026-07-17)
### Bug Fixes
* correct jitter range to ±25% and fix abort.rs doc — review findings ([9b6e51d](https://github.com/asepharyana/zesdex/commit/9b6e51dc677cc4b798532f1e63335785f2f7bbbf))
## [1.15.1](https://github.com/asepharyana/zesdex/compare/v1.15.0...v1.15.1) (2026-07-17)
# [1.15.0](https://github.com/asepharyana/zesdex/compare/v1.14.0...v1.15.0) (2026-07-17)
### Bug Fixes
* **cms:** perbaiki serde default hive_mind_node_timeout_ms & toleransi parse gagal di Settings ([6d41ffc](https://github.com/asepharyana/zesdex/commit/6d41ffc587f6f8de5bb4757c7eb8d69077831057))
* **cms:** satukan ChatMessage/Role Conversation dengan tipe kanonik zesdex-entities ([b272858](https://github.com/asepharyana/zesdex/commit/b272858edbe36af0b2eca119ff5b132de8dadce9))
* **iam:** redirect_uri dinamis + validasi CSRF state di OAuthServiceImpl ([be278f8](https://github.com/asepharyana/zesdex/commit/be278f8b1c2bc1295368e49c38622ef2bc3ed9ee))
* **iam:** set permission 0600 pada file token OAuth ([f2d97fb](https://github.com/asepharyana/zesdex/commit/f2d97fb17dcf4f52123da89532d7964ed8f8124c))
* **middleware:** jangan percaya header X-Forwarded-For/X-Real-IP secara default di rate limiter ([4dc4f80](https://github.com/asepharyana/zesdex/commit/4dc4f80fa344d894c2ce62f75d239847cd13001a))
### Features
* **cms:** implement RewindBlobRepository for managing binary blobs ([22dd6fd](https://github.com/asepharyana/zesdex/commit/22dd6fdda7d0c8eabfce296bbad53587204c69fa))
* **iam:** implementasikan FileSystemSessionLockRepository (sebelumnya belum ada implementasi) ([ff6a749](https://github.com/asepharyana/zesdex/commit/ff6a749c1149d890173922fbff76facef50a93b0))
* **iam:** port LoopbackServer OAuth callback listener dari zesdex-backend ([910aa5e](https://github.com/asepharyana/zesdex/commit/910aa5e071911f158609c4dd8985f776d8d9235f))
* **iam:** tambahkan CSPRNG (OsRng) untuk token state/PKCE ([5ede65f](https://github.com/asepharyana/zesdex/commit/5ede65f454b08303f588754a208dca0c37d3ce34))
# [1.14.0](https://github.com/asepharyana/zesdex/compare/v1.13.0...v1.14.0) (2026-07-16)
### Bug Fixes
* **context:** batasi squash_log ke tool bash saja ([7d99cd6](https://github.com/asepharyana/zesdex/commit/7d99cd66187b3fafb2ddeb19d8e8aa7db139df64))
* **context:** perbaiki fixture test shaping agar men-drop pesan lama ([8bb697a](https://github.com/asepharyana/zesdex/commit/8bb697a53fe89c9d00f709df33ccbd7944482f07))
* **plan:** perbaiki bug entropy gate dan fixture test squash.rs ([ceb8479](https://github.com/asepharyana/zesdex/commit/ceb84790bb741352b2b3416cda4bdbc6b42767c9))
* **plan:** perbaiki fixture test array-cutoff squash_json ([7ffdf44](https://github.com/asepharyana/zesdex/commit/7ffdf441355cda0972b849bc9b475d3de8f39843))
* **plan:** perbaiki fixture test shaping agar benar-benar men-drop pesan ([3a6e32d](https://github.com/asepharyana/zesdex/commit/3a6e32d8f3f0dd47d2c5ff63ab0c184b0ee4a6bc))
* **plan:** perkuat fixture test log agar benar-benar uji squash_log ([682007a](https://github.com/asepharyana/zesdex/commit/682007a2507f209c2378796442d4bc879516191a))
### Features
* **context:** tambah context::dedup untuk hasil tool yang berulang ([12a03fd](https://github.com/asepharyana/zesdex/commit/12a03fd3d1123c7a88289e44064537a71b9f574b))
* **context:** tambah context::shaping (port dari shortsend) ([e080d9f](https://github.com/asepharyana/zesdex/commit/e080d9fc6b7daf2ab37fb242d03a3f64e8629acc))
* **context:** tambah context::squash untuk kompresi hasil tool ([ea0b498](https://github.com/asepharyana/zesdex/commit/ea0b4988299894e4588d851ebc91704a9e73bc73))
* **context:** tambah context::tokens dengan tiktoken-rs ([c219b6e](https://github.com/asepharyana/zesdex/commit/c219b6ec58ddad4770e491a48bbe1b6e3d0c8884))
* **context:** tambah context::window::resolve ([059ca8e](https://github.com/asepharyana/zesdex/commit/059ca8ea246768dbec06ae5336433853e4276cec))
* **runtime:** kompres hasil tool lewat squash sebelum masuk context ([96084f7](https://github.com/asepharyana/zesdex/commit/96084f74621636a72c209388580d0ebbb335d198))
* **settings:** tambah mode ringkas opsional (concise_output) ([d6de973](https://github.com/asepharyana/zesdex/commit/d6de9735aba7745f5f57a8e7a5e625613c1a2569))
# [1.13.0](https://github.com/asepharyana/zesdex/compare/v1.12.0...v1.13.0) (2026-07-14)
### Bug Fixes
* correct test assertion in dim_false_plain_text_has_no_color ([8d77e45](https://github.com/asepharyana/zesdex/commit/8d77e4565c2e3ca49058022c71e8277bdd790312))
* Remove orphaned span_text helper function from markdown test module ([199028f](https://github.com/asepharyana/zesdex/commit/199028fa2eb6056dad2bdf0753554939c153a163))
* **state:** cegah panic saat select mention dengan cursor stale ([dcfc5b9](https://github.com/asepharyana/zesdex/commit/dcfc5b9ec0d35f4c66b1648ded00f4f1279e0413))
* **state:** jangan bangun mention index di mode attach ([e0d0860](https://github.com/asepharyana/zesdex/commit/e0d0860d7ba0ab6a4c9b9f1562f6a767a6424d99))
### Features
* Deteksi trigger [@mention](https://github.com/mention) dan Tab-cycle di input handler ([2eebedf](https://github.com/asepharyana/zesdex/commit/2eebedfea56c7d4827f94a2739dbb5fa006e3069))
* **ipc:** dukung Ctrl+Y clipboard copy di mode daemon/attach ([472162d](https://github.com/asepharyana/zesdex/commit/472162d135478666913a888a68867e635e50d14a))
* Judul dropdown autocomplete mengikuti jenisnya (Commands vs Files) ([7f2509e](https://github.com/asepharyana/zesdex/commit/7f2509ecd2688495545333debee0c81016b28641))
* **state:** Alirkan mention_index lewat ToolCtx dan AppStateRest, bangun index di background thread ([93be92a](https://github.com/asepharyana/zesdex/commit/93be92a5fb8644c9020478c49421585ade2d0fd1))
* Tambah Ctrl+Y untuk menyalin pesan assistant terakhir ([d93bdba](https://github.com/asepharyana/zesdex/commit/d93bdba59b7dd14b4a76dc91c6b7f70a3c0f721c))
* Tambah field pending_clipboard_copy di MiscState ([3b6abd9](https://github.com/asepharyana/zesdex/commit/3b6abd920ea92329ebcf888c3bb50470675c4152))
* Tambah helper truncate_diff untuk membatasi panjang diff ([5dd835f](https://github.com/asepharyana/zesdex/commit/5dd835ff244a138bb5f1a8dbfd7cf252c2671e5e))
* Tambah MentionIndex, AutocompleteKind, dan deteksi [@mention](https://github.com/mention) di InputState ([95cae8f](https://github.com/asepharyana/zesdex/commit/95cae8fd8a8ce737ba60c3ac8bea77f4c2e14b1a))
* Tambah write_osc52 dan salin ke clipboard di mode single-process ([71b1613](https://github.com/asepharyana/zesdex/commit/71b1613d8467cfcb2383b3fce153a25c7883ac3d))
* Tambahkan file baru ke mention_index saat tool write membuatnya ([930961b](https://github.com/asepharyana/zesdex/commit/930961bd85701ab8906b8d81095e46d3635a951d))
* Tampilkan unified diff pada hasil tool edit ([c3c0ef6](https://github.com/asepharyana/zesdex/commit/c3c0ef632a605d8bf32712049035e4fc814af9d5))
* Tampilkan unified diff saat tool write menimpa file yang sudah ada ([2bb8e6f](https://github.com/asepharyana/zesdex/commit/2bb8e6f2555eac01baf2311d41811afad4aa3041))
* **view:** Tambah parameter dim dan pewarnaan baris diff di markdown renderer ([683715c](https://github.com/asepharyana/zesdex/commit/683715cd7af77d87a2ae3834360bb6f7a4388bd0))
# [1.12.0](https://github.com/asepharyana/zesdex/compare/v1.11.0...v1.12.0) (2026-07-14)
### Features
* Add mouse capture functionality to terminal and enhance markdown rendering with table support ([4428e8b](https://github.com/asepharyana/zesdex/commit/4428e8bc01c196415ac408a42f57305227a79760))
* Improve markdown rendering with enhanced line wrapping and indentation for code blocks ([b2e848d](https://github.com/asepharyana/zesdex/commit/b2e848d124e726c4d8b644d473e518398fab1dea))
# [1.11.0](https://github.com/asepharyana/zesdex/compare/v1.10.0...v1.11.0) (2026-07-14)
### Features
* Enhance subagent tool output handling and clarify workflow directives ([6fbe1e2](https://github.com/asepharyana/zesdex/commit/6fbe1e2d1dc790ba2509803b3ab3a848d5b2a63b))
* Enhance token usage tracking and improve chat UI with emojis ([188e7cc](https://github.com/asepharyana/zesdex/commit/188e7cc9a9233140a5e4953e3f3ff66682914e42))
# [1.10.0](https://github.com/asepharyana/zesdex/compare/v1.9.0...v1.10.0) (2026-07-14)
### Bug Fixes
* align format strings in sidebar Usage widget ([98615ca](https://github.com/asepharyana/zesdex/commit/98615ca5b9d896331a5a6d9af91035aca1f5e9d5))
* use {:>6}: for aligned colons in sidebar Usage widget ([f87ab13](https://github.com/asepharyana/zesdex/commit/f87ab133f1953633f66e21b9eaf7c4eb41291ccd))
### Features
* Implement lesson generation feature and update status display ([1c08b8e](https://github.com/asepharyana/zesdex/commit/1c08b8e4e9c3bb1318535a74c9812beb976df315))
# [1.9.0](https://github.com/asepharyana/zesdex/compare/v1.8.0...v1.9.0) (2026-07-14)
### Bug Fixes
* **workflow:** import Color style for improved agent state rendering ([472c597](https://github.com/asepharyana/zesdex/commit/472c597c5e4ab12808a6bcd1899628bc7ab77186))
### Features
* **agent:** refine cognitive cycle plan with structured phases for exploration, planning, and execution ([c5253b2](https://github.com/asepharyana/zesdex/commit/c5253b2ca359d4dbed9445e04f1dec1a6bb37e8f))
* **subagent:** add progress event handling and formatting for subagent execution ([558908a](https://github.com/asepharyana/zesdex/commit/558908aef216e61a0a108083fbac5e02c31501dc))
* **subagent:** emit reasoning text as progress in StepCompleted events ([97aa75f](https://github.com/asepharyana/zesdex/commit/97aa75f2da37aee5fc7a0626fc396988f089fff2))
* **subagent:** include tool call arguments in ToolResult events and progress formatting ([a8adfcb](https://github.com/asepharyana/zesdex/commit/a8adfcbf6dc5411e977f22ac6b6ba023f563d7c9))
# [1.8.0](https://github.com/asepharyana/zesdex/compare/v1.7.0...v1.8.0) (2026-07-14)
### Features
* **tools:** require reason argument for delete and git_operator tools ([c6ab063](https://github.com/asepharyana/zesdex/commit/c6ab063c211fb858fd0e155883b9c47b345f0f8a))
# [1.7.0](https://github.com/asepharyana/zesdex/compare/v1.6.0...v1.7.0) (2026-07-14)
### Bug Fixes
* **prompt:** perbarui system prompt dari CEO/company ke model hive-mind ([d392c4a](https://github.com/asepharyana/zesdex/commit/d392c4aa00154aae5a0f36db615f05adc385fdb5))
* **runtime:** add check for unconfigured provider to prevent misleading API errors ([181b512](https://github.com/asepharyana/zesdex/commit/181b5128ac1fba47627bf7b377358c782e3481b7))
### Features
* **install:** add installation script for building and symlinking the binary ([4eba9d0](https://github.com/asepharyana/zesdex/commit/4eba9d0a2fbe42b0383eaf872eaeace18cc59a92))
* **protocol:** add Paste request type for bracketed-paste events ([b92dab9](https://github.com/asepharyana/zesdex/commit/b92dab97e6efe1fd6f7c23b28310610c653a57b0))
* **provider:** enhance Claude provider configuration to support environment variable fallback ([4b16bc3](https://github.com/asepharyana/zesdex/commit/4b16bc31125018ad3d3e46706881596a226f5352))
* **runtime:** implement JSON repair function for truncated tool-call arguments ([e13f040](https://github.com/asepharyana/zesdex/commit/e13f04083313f3544bdb1a76b5ecd535ecf59e4f))
* **stream:** add method to detect incomplete tool calls and handle parsing errors ([732d603](https://github.com/asepharyana/zesdex/commit/732d6039dc23bc8ec323bc4f91be9a7131a61ef6))
# [1.6.0](https://github.com/asepharyana/zesdex/compare/v1.5.0...v1.6.0) (2026-07-14)
### Bug Fixes
* perbaiki 5 warning clippy pre-existing (base untuk TUI overhaul) ([6b58977](https://github.com/asepharyana/zesdex/commit/6b58977875f809f19cc2d7bb9b2a7dd057d0229e))
* **tui:** perbaiki isi overlay Todo dan Usage jadi tampilan detail nyata ([aaea300](https://github.com/asepharyana/zesdex/commit/aaea300699f7e76cdc689e225e7c4c3bc164e8d4))
* **tui:** perbaiki potensi terpotongnya baris token di widget Usage sidebar ([7fd55fa](https://github.com/asepharyana/zesdex/commit/7fd55fa86dfe8f9a4581f02fa9220cd5d1ba600c))
* **tui:** perbaiki rendering multi-baris pada pesan Tool ([2f1a4d8](https://github.com/asepharyana/zesdex/commit/2f1a4d85a1fdc9cbfb81912a3206c057ad9d1ed5))
### Features
* **tui:** ganti palet warna ke Tokyo Night ([7a9cb7b](https://github.com/asepharyana/zesdex/commit/7a9cb7bf342367c81fb4a1568675e46f132a8afc))
* **tui:** rombak rendering chat jadi format log rapat ([e34708a](https://github.com/asepharyana/zesdex/commit/e34708a3191bef63d191e76dee39a58a33e4ad5f))
* **tui:** tambah command /todo dan /usage untuk buka overlay ([aa2b6ac](https://github.com/asepharyana/zesdex/commit/aa2b6acb95f8518950b8b7d9c3c9e10968936162))
* **tui:** tambah dan pasang sidebar dashboard permanen ([31c01cd](https://github.com/asepharyana/zesdex/commit/31c01cdf1df6827c3a949820378c8b85ebcfdf87))
# [1.5.0](https://github.com/asepharyana/zesdex/compare/v1.4.0...v1.5.0) (2026-07-14)
### Bug Fixes
* **hive-mind:** ganti gerbang pipeline berbasis jumlah pesan dengan deteksi konvergensi sebelumnya ([5498088](https://github.com/asepharyana/zesdex/commit/5498088532314f8dbc005d5e8058c0170ca92320))
* **hive-mind:** gunakan flag SessionRuntime sebagai sinyal konvergensi otoritatif ([28e763a](https://github.com/asepharyana/zesdex/commit/28e763a695f56adfbecd4efb14edbde13bbd63dc))
* **hive-mind:** hapus penulisan docs/runs ganda dan sambungkan abort_flag ke tool hive_mind manual ([a125f5d](https://github.com/asepharyana/zesdex/commit/a125f5d4400b0c417ba4049e67480bd18479e90b))
* **hive-mind:** tambah timeout per-node dan jamin dokumentasi convergence tetap tertulis saat sintesis gagal ([b1c0265](https://github.com/asepharyana/zesdex/commit/b1c0265e8cdf9278664e64f77fbde4ec8c22fcfd))
* **subagent:** panic-proof overlap guards and update stale docs ([e023f2c](https://github.com/asepharyana/zesdex/commit/e023f2c5a8f036d89e925bb9ceec253343476a74))
* **subagent:** perbaiki filter is_production_code berbasis substring dan tambah pembatalan/anti-tumpang-tindih pada background review ([1039f67](https://github.com/asepharyana/zesdex/commit/1039f67c12749c6b2c93e3ab7037feded8ab01c6))
* **tui:** perbaiki roster workflow yang tidak pernah ter-reset karena substring "started" tidak pernah cocok ([fdd62f8](https://github.com/asepharyana/zesdex/commit/fdd62f830330b5b3e2b4f9fcc7274daf7f7842a5))
### Features
* **settings:** tambah hive_mind_node_timeout_ms dengan fallback serde default ([e2878a3](https://github.com/asepharyana/zesdex/commit/e2878a3d83f171aa181ac29ca689828e0cb1408f))
* **tool:** tambah abort_flag ke ToolCtx dan sambungkan dari session state ([79e2bfc](https://github.com/asepharyana/zesdex/commit/79e2bfcc9ca67424ca2b34a5652d3c2bb93291bf))
# [1.4.0](https://github.com/asepharyana/zesdex/compare/v1.3.0...v1.4.0) (2026-07-14)
### Features
* **hive-mind:** implement multi-agent orchestration with cognitive cycles ([25f084f](https://github.com/asepharyana/zesdex/commit/25f084f9dbb5047c5c91aedcb582d35f4ff95395))
# [1.3.0](https://github.com/asepharyana/zesdex/compare/v1.2.0...v1.3.0) (2026-07-13)
### Features
* enhance edit logging in subagent execution and streamline edit tracking in run_agent_turn ([c60fadb](https://github.com/asepharyana/zesdex/commit/c60fadb88ae63788a5bbe3c3443e2ce826e5778f))
# [1.2.0](https://github.com/asepharyana/zesdex/compare/v1.1.0...v1.2.0) (2026-07-13)
### Features
* enhance responsiveness by implementing abort checks in streaming API calls ([0d6f558](https://github.com/asepharyana/zesdex/commit/0d6f558b2bd0282a7a1695f7680ab1d1c6142579))
* refactor agent step limits and enhance workflow orchestration with new findings tool ([3b660e0](https://github.com/asepharyana/zesdex/commit/3b660e09a87f3e982db94f48d2282ddb63116341))
* remove pipeline command and refactor workflow execution to use custom specialists ([00e2913](https://github.com/asepharyana/zesdex/commit/00e29139c53c5fed4c13b0493297dd9da984460c))
* update overlay handling in apply_action and remove mouse capture from terminal execution ([2e351cc](https://github.com/asepharyana/zesdex/commit/2e351ccf6930ff4823f55b581308222229fe6684))
* update README and documentation for new tools and features ([1d50b94](https://github.com/asepharyana/zesdex/commit/1d50b94eec1ed82dfc40d43d41bd01aeb79edfe1))
# [1.1.0](https://github.com/asepharyana/zesdex/compare/v1.0.4...v1.1.0) (2026-07-13)
### Features
* implement abort mechanism for workflows and subagents ([104b0da](https://github.com/asepharyana/zesdex/commit/104b0daf4cc51581de04f03d6b727cdb16f9b6c3))
## [1.0.4](https://github.com/asepharyana/zesdex/compare/v1.0.3...v1.0.4) (2026-07-13)
### Bug Fixes
* remove redundant ref in format! argument ([0155a04](https://github.com/asepharyana/zesdex/commit/0155a04ceeec7f7f234c08a7f56e9a4384691655))
## [1.0.3](https://github.com/asepharyana/zesdex/compare/v1.0.2...v1.0.3) (2026-07-13)
## [1.0.2](https://github.com/asepharyana/zesdex/compare/v1.0.1...v1.0.2) (2026-07-12)
## [1.0.1](https://github.com/asepharyana/zesdex/compare/v1.0.0...v1.0.1) (2026-07-12)
-169
View File
@@ -1,169 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Test
```bash
# Build (debug)
cargo build
# Release build
cargo build --release
# Run all tests
cargo test
# Run a single test
cargo test test_name
# Lint
cargo clippy
# Lint with warnings-as-errors
cargo clippy -- -D warnings
```
Test modules are located inline in production files (not a separate `tests/` dir):
- `src/app/harness.rs` — guard/verdict parsing tests
- `src/app/runtime/stream/mod.rs` — SSE parser tests
- `src/model/memory.rs` — memory CRUD + slugify tests
- `src/model/editlog.rs` — edit log append/reload tests
- `src/tool/fs/helpers.rs` — tool argument extraction tests
Tests use `#[cfg(test)] mod tests` blocks. There are 37 unit tests total.
Tracing output goes to `~/.local/share/zesdex/zesdex.log`. Set `RUST_LOG=debug` for verbose logging.
## Architecture Overview
Zesdex is an autonomous AI coding agent with a TUI — an OpenAI/Anthropic-compatible LLM client wrapped in a tool-use harness with 28 built-in tools.
Detailed architecture documentation is in `docs/CODEMAPS/`:
| File | Covers |
|------|--------|
| [`docs/CODEMAPS/architecture.md`](docs/CODEMAPS/architecture.md) | System layout, process modes, data flow, key files |
| [`docs/CODEMAPS/backend.md`](docs/CODEMAPS/backend.md) | Provider, OAuth, IPC, workflow engine, MCP, review, bg bash |
| [`docs/CODEMAPS/frontend.md`](docs/CODEMAPS/frontend.md) | TUI render pipeline, 16 overlays, toasts, input handling |
| [`docs/CODEMAPS/data.md`](docs/CODEMAPS/data.md) | Persistence, SQLite msglog, memory files, settings/config |
| [`docs/CODEMAPS/dependencies.md`](docs/CODEMAPS/dependencies.md) | 23 Rust crates, 5 external services |
### Entry Points
`src/main.rs` — three modes:
- **Single-process** (default): TUI + agent loop in one process
- **Daemon** (`--daemon`): background Unix socket server, handles LLM calls
- **Attach** (`--attach <id>`): TUI-only client that connects to a daemon
### Core Flow
```
Controller (key input → Action) → Event Loop → LLM stream → Tool execution → State mutation → TUI render
│ │ │
│ src/controller/input.rs │ src/app/runtime/actions/ │ src/tool/
└── maps keys to Action enum │── dispatches Action::* └── 28 tool impls
│ matching on Action variant
│── applies state mutations
```
### Key Patterns
- **State mutation** — `AppStateRest` is mutable in-place from `actions/mod.rs` and `controller/input.rs`. No generic update function.
- **No DI** — modules call `Settings::load()`, `AppConfig::load()`, `all_tools()` directly.
- **Logging** — `tracing::warn!` to `~/.local/share/zesdex/zesdex.log` (not stderr, avoids TUI corruption).
- **Error handling** — `anyhow::Result` and `anyhow::bail!` throughout. No custom error types.
- **Static strings** — MCP tool descriptions use `Box::leak` + `OnceLock` cache.
- **Tools** — `trait Tool { fn name() -> &str, fn run() -> Result<String> }`, 28 impls, gated by `Harness`.
- **Shell safety** — `tool/shell_filter/` blocks credential leaks and destructive git commands.
### Company Pipeline (Division Architecture)
- **5 divisions** in `src/app/subagent/division.rs`: Strategy, Engineering, Quality, Security, Documentation.
- **Pipeline orchestrator** in `src/app/workflow/company.rs`: two modes:
- `run_company_pipeline()` — full 5-division pipeline
- `run_company_pipeline_quick()` — 3-division (Strategy → Engineering → Quality)
- **Auto-CEO trigger** in `run_agent_turn()` (`actions/mod.rs`): detects complex requests via `is_complex_request()` heuristics, auto-delegates to pipeline.
- **Override** via `/pipeline full|quick|skip` sets `MiscState::pipeline_override`, consumed on next turn.
- **Live division progress** in TUI panel (`view/workflow.rs`): shows division name + current tool via `AgentStatus::progress`.
- **Auto inline review** after each edit: `src/app/subagent/auto.rs``spawn_quick_review()` injects verdict back into LLM conversation.
- **Background subagents** (test-gen, arch-review, security-review) fire asynchronously at turn end via `TurnEvent::SystemNote`.
## Commit Convention
Gunakan **Conventional Commits** untuk semua commit. Format:
```
<type>(<scope>): <description>
```
**Type & efek ke versi:**
| Type | Bump | Kapan pakai |
|-------------|-------|------------------------------------------|
| `feat` | minor | Fitur baru |
| `fix` | patch | Perbaikan bug |
| `chore` | patch | Maintenance, update deps, dll |
| `docs` | patch | Perubahan dokumentasi/comment |
| `refactor` | patch | Refactor kode tanpa perubahan fungsional |
| `test` | patch | Nambah/ubah test |
| `style` | patch | Formatting, whitespace, lint |
| `perf` | patch | Optimasi performa |
| `ci` | patch | Perubahan CI/CD |
**Catatan:**
- **Semua type menghasilkan release** (patch minimal). Tidak ada commit yang "skip release".
- Tambahkan `BREAKING CHANGE:` di body commit untuk bump **major**.
- **Scope** opsional, tapi direkomendasikan (misal `feat(agent):`, `fix(ipc):`).
### Contoh
```
feat(tool): add batch file delete
chore: bump reqwest to 0.12
refactor(harness): flatten guard pipeline
fix(ipc): reconnect loop on socket timeout
docs: add architecture diagram to README
BREAKING CHANGE: IPC frame header changed from 4-byte to 8-byte length
```
## Code Documentation
Every function, struct, enum, trait, module, and significant code block must have a doc comment (`///` or `//!`) that explains:
- **What** the function/module does (purpose, not how)
- **Flow** — a brief ASCII or prose description of the code flow / data flow above each non-trivial function
- **Why** — non-obvious decisions, edge cases, invariants
- **Return** — what the caller gets back, especially for `Result` types
Examples:
```rust
/// Parse an SSE data chunk into one or more StreamEvents.
///
/// Flow: buffer → split on '\n' → flush on blank line → JSON parse → match event type
/// → return Token / ToolCallDelta / Usage / Done.
///
/// Edge case: chunk may split mid-line; remaining bytes stay in buffer
/// for the next feed() call.
fn feed(&mut self, chunk: &str) -> Vec<StreamEvent> { ... }
/// The single source-of-truth state struct for the entire application.
///
/// Mutated in-place from two locations: actions/mod.rs (apply_action)
/// and controller/input.rs (key event handlers). Read-only from
/// every other module.
struct AppStateRest { ... }
```
Rules:
- Every `pub fn` needs a doc comment
- Every `pub struct` / `pub enum` / `pub trait` needs a doc comment
- Non-trivial private functions (≥10 lines) need a doc comment
- Write the comment above the code it documents (not inline in the body)
- Update comments when code behavior changes — stale docs are worse than no docs
Generated
+1047 -276
View File
File diff suppressed because it is too large Load Diff
+72 -38
View File
@@ -1,11 +1,25 @@
[package]
name = "zesdex"
version = "1.0.2"
[workspace]
resolver = "2"
members = [
"apps/domain",
"apps/application",
"apps/infrastructure",
"apps/interfaces/tui",
"apps/interfaces/api",
"apps/interfaces/daemon",
"apps/interfaces/ws",
"apps/interfaces/grpc",
"apps/interfaces/web",
"apps/gateway",
"apps/bootstrap",
]
[workspace.package]
version = "1.19.6"
edition = "2021"
authors = ["asepharyana <superaseph@gmail.com>"]
# Treat all warnings as errors, set strict clippy levels
[lints.rust]
[workspace.lints.rust]
unused = "deny"
dead_code = "deny"
unreachable_code = "deny"
@@ -17,45 +31,65 @@ deprecated = "deny"
trivial_casts = "deny"
trivial_numeric_casts = "deny"
[lints.clippy]
[workspace.lints.clippy]
all = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -2 }
[dependencies]
ratatui = "0.30.2"
crossterm = "0.28"
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_yaml_ng = "0.10"
chrono = { version = "0.4", features = ["serde"] }
uuid = { version = "1", features = ["v4", "v5"] }
anyhow = "1"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "time", "net", "io-util", "signal"] }
reqwest = { version = "0.12", features = ["json", "stream", "blocking", "native-tls-vendored"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
reqwest = { version = "0.13", features = ["json", "stream", "blocking", "native-tls-vendored", "form"] }
ratatui = "0.30.2"
crossterm = "0.29"
rusqlite = { version = "0.40", features = ["bundled"] }
thiserror = "1"
base64 = "0.22"
sha2 = "0.11"
hex = "0.4"
libc = "0.2"
dirs = "6"
regex = "1"
globset = "0.4"
ignore = "0.4"
nucleo-matcher = "0.3"
futures-util = "0.3"
rmcp = { version = "2.2", default-features = false, features = ["client", "transport-child-process", "transport-streamable-http-client-reqwest", "macros"] }
tiktoken-rs = "0.12"
similar = "3"
syntect = { version = "5", default-features = false, features = ["default-fancy"] }
pulldown-cmark = { version = "0.13", default-features = false }
infer = "0.19"
webbrowser = "1"
url = "2"
percent-encoding = "2"
dom_smoothie = "0.18.0"
fast_html2md = "0.0.62"
scraper = "0.27.0"
url = "2"
percent-encoding = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_yaml_ng = "0.9"
anyhow = "1"
include_dir = "0.7"
uuid = { version = "1", features = ["v4", "v5"] }
dirs = "5"
futures-util = "0.3"
pulldown-cmark = { version = "0.13", default-features = false }
syntect = { version = "5", default-features = false, features = ["default-fancy"] }
rusqlite = { version = "0.32", features = ["bundled"] }
ignore = "0.4"
regex = "1"
globset = "0.4"
infer = "0.16"
base64 = "0.22"
sha2 = "0.10"
libc = "0.2"
rmcp = { version = "1.8", default-features = false, features = ["client", "transport-child-process", "transport-streamable-http-client-reqwest", "macros"] }
tracing = "0.1"
chrono = { version = "0.4", features = ["serde"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
webbrowser = "1"
lsp-types = "0.97"
axum = { version = "0.8", features = ["macros"] }
tower = "0.5"
tower-http = { version = "0.6", features = ["cors", "limit"] }
argon2 = "0.5"
jsonwebtoken = "9"
clap = { version = "4", features = ["derive"] }
rand_core = { version = "0.6", features = ["getrandom"] }
[[bin]]
name = "zesdex"
path = "src/main.rs"
# Clean-architecture workspace crate references
zesdex-domain = { path = "apps/domain" }
zesdex-application = { path = "apps/application" }
zesdex-infrastructure = { path = "apps/infrastructure" }
zesdex-tui = { path = "apps/interfaces/tui" }
zesdex-api = { path = "apps/interfaces/api" }
zesdex-daemon = { path = "apps/interfaces/daemon" }
zesdex-ws = { path = "apps/interfaces/ws" }
zesdex-grpc = { path = "apps/interfaces/grpc" }
zesdex-web = { path = "apps/interfaces/web" }
zesdex-gateway = { path = "apps/gateway" }
zesdex-bootstrap = { path = "apps/bootstrap" }
+30
View File
@@ -0,0 +1,30 @@
# syntax=docker/dockerfile:1
# Zesdex — Multi-stage Docker build
# ===================================
# Stage 1: Build with Rust toolchain
FROM rust:1.85-slim-bookworm AS builder
RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config libsqlite3-dev && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
# Build with release profile (treats warnings as errors via lints)
RUN cargo build --release -p zesdex-gateway --bin zesdex
# Stage 2: Minimal runtime image
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates libsqlite3-0 && \
rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/zesdex /usr/local/bin/zesdex
ENV ZESDEX_DATA_DIR=/data
VOLUME ["/data"]
ENTRYPOINT ["/usr/local/bin/zesdex"]
-379
View File
@@ -1,379 +0,0 @@
# Zesdex
> Autonomous AI coding agent in a terminal-based TUI.
Zesdex is a Rust-powered AI assistant that operates directly in your terminal via a rich TUI interface. It combines large language model intelligence with a comprehensive set of tools to explore, understand, and modify codebases autonomously — with built-in guardrails at every layer.
---
## Features
### Core
- **TUI Interface** — Full-screen terminal UI with chat panel, input bar, and status bar built with [ratatui](https://github.com/ratatui-org/ratatui) and [crossterm](https://github.com/crossterm-rs/crossterm).
- **Daemon Architecture** — Run as a background daemon with client attach/detach via Unix domain sockets. The daemon processes state; clients only render.
- **IPC Protocol** — Bidirectional state synchronization between daemon and client processes with diff-based updates.
- **Provider Agnostic** — Configurable AI model providers with dynamic model selection, per-role temperature/token limits, and API key management.
### Tool System (34 built-in tools)
| Category | Tools |
|----------|-------|
| **Filesystem** | `read`, `write`, `edit`, `delete` |
| **Search** | `grep` (recursive text), `glob` (file patterns) |
| **Shell** | `bash`, `bash_output`, `bash_kill` |
| **Git** | `git_operator`, `git_worktree`, `git_cred` |
| **Memory** | `remember`, `recall`, `forget` |
| **Planning** | `plan_enter`, `plan_ready`, `seqthink` |
| **Workflow** | `workflow_run`, `note_finding`, `company_pipeline` |
| **Utility** | `cd`, `dir_list`, `dir_cache_update`, `pong`, `todowrite`, `todofinish` |
| **LSP** | `lsp_connect`, `lsp_diagnostics`, `lsp_hover`, `lsp_completion`, `lsp_definition`, `lsp_references`, `lsp_disconnect` |
### Intelligence
- **Company Pipeline** — Autonomous agent orchestration modeled as a company with specialized divisions. The CEO (main agent) automatically delegates work to 5 divisions in sequence:
```
Strategy → Engineering → Quality → Security → Documentation
```
Each division has a dedicated role, toolset, and system prompt. Controlled via `/pipeline full|quick|skip`.
- **Workflow Engine** — Orchestrate complex multi-step tasks with parallel sub-agents, pipelines, and phased execution. Spawn independent workers that share findings in real-time.
- **Self-Learning** — Persistent memory system that stores lessons, references, and project knowledge across sessions. Memories include provenance tracking, lifecycle management, and scope isolation.
- **Self-Review** — Review subagents trigger automatically after each code edit (inline) and at turn completion (background). Three types: code quality, architecture, and security.
- **Self-Healing** — On build/test failures, spawns a sub-agent with the error context to autonomously fix issues before reporting them to the user.
- **MCP Support** — [Model Context Protocol](https://modelcontextprotocol.io/) integration for connecting to external AI tool servers.
- **Sequential Thinking** — Chain-of-thought reasoning tool for step-by-step problem decomposition.
- **Session Locking** — Prevents multiple processes from operating on the same session directory.
### Session Management
- Multiple concurrent sessions with history, rewind, and transcript persistence.
- Per-session edit logs with full change tracking.
- Session archival and summary generation.
---
## Architecture
```
src/
├── main.rs # Entry point: single-process, daemon, or attach mode
├── resources.rs # Embedded resources (help text, system prompts)
├── app/
│ ├── state/ # AppStateRest — immutable-rest state model
│ │ ├── rest.rs # Core state struct
│ │ ├── types.rs # Overlay, Toast, Origin enums
│ │ ├── snapshot.rs # State snapshots for IPC
│ │ ├── diff.rs # Diff-based state synchronization
│ │ ├── runtime.rs # Runtime state mutations
│ │ └── misc.rs # DirCache and miscellaneous state helpers
│ ├── runtime/ # Action dispatch and event loop
│ │ ├── actions/ # Action enum and apply_action reducer
│ │ ├── stream/ # LLM streaming and tool execution
│ │ │ └── tools/ # Tool harness integration
│ │ │ └── turn.rs # Turn orchestration
│ │ ├── event_loop/ # Main event loop and shortsend
│ │ ├── commands.rs # Slash command dispatch
│ │ └── shortsend.rs # Short-lived async send helper
│ ├── mode/ # UI modes and overlays (13 modes)
│ │ ├── bash.rs # Bash panel mode
│ │ ├── editor.rs # Multi-line editor mode
│ │ ├── effort.rs # Effort level selector
│ │ ├── help.rs # Help overlay
│ │ ├── key_input.rs # Raw key input mode
│ │ ├── loading.rs # Loading spinner overlay
│ │ ├── mcp.rs # MCP server management
│ │ ├── quit_confirm.rs # Quit confirmation dialog
│ │ ├── rewind.rs # Session rewind mode
│ │ ├── settings.rs # Settings panel
│ │ ├── todo.rs # Task list overlay
│ │ └── workflow.rs # Workflow visualization
│ ├── harness.rs # Tool harness for agent execution
│ ├── workflow/ # Workflow engine
│ │ ├── script.rs # Workflow script DSL
│ │ ├── engine.rs # Workflow executor
│ │ └── company.rs # Company pipeline orchestrator
│ ├── mcp/ # MCP client manager
│ │ └── manager.rs # MCP server lifecycle and tool exposure
│ ├── subagent/ # Sub-agent management
│ │ ├── spawn.rs # AgentDefinition and spawning
│ │ ├── engine.rs # Sub-agent event loop
│ │ ├── context.rs # Context construction for sub-agents
│ │ └── event.rs # Progress event types
│ ├── bgbash/ # Background bash job management
│ │ ├── job.rs # Background job handle
│ │ └── control.rs # Bash control (bg/fg/kill)
│ ├── lsp/ # LSP client management
│ │ ├── client.rs # LSP client connection wrapper
│ │ └── provisioner.rs # Auto-provisioning of LSP servers
│ └── review/ # Self-review quality system
├── controller/
│ ├── input.rs # Key event → Action mapping
│ └── command.rs # Slash command parser
├── dto/
│ ├── chat/ # Message, ToolCall, Role types
│ │ ├── message.rs # Chat message types
│ │ ├── tool.rs # Tool call/result types
│ │ └── mod.rs
│ └── provider/ # AI provider request/response/usage types
│ ├── request.rs # Provider request schema
│ ├── response.rs # Provider response schema
│ └── usage.rs # Token usage tracking
├── ipc/
│ ├── protocol.rs # ClientRequest, DaemonFrame, StatePayload
│ ├── server.rs # Unix socket server
│ ├── client.rs # Unix socket client
│ ├── conn.rs # Framed connection
│ ├── frame.rs # Length-prefixed frame encoding
│ ├── snapshot.rs # State snapshot serialization
│ └── diff.rs # Binary diff for state sync
├── model/
│ ├── store.rs # File-based storage (~/.config/zesdex/)
│ ├── session.rs # Session CRUD and listing
│ ├── settings.rs # User settings (provider, model, tokens)
│ ├── app_config.rs # Provider definitions and model roles
│ ├── memory.rs # Persistent memory with frontmatter
│ ├── editlog.rs # Edit history tracking
│ ├── msglog/ # Message log (SQLite-backed)
│ │ ├── schema.rs # SQLite schema
│ │ ├── query.rs # Query helpers
│ │ ├── blobs.rs # Large blob storage
│ │ └── summary.rs # Session summarization
│ ├── agent_def/ # Agent definitions (builtin, global, session)
│ │ ├── builtin.rs # Built-in agent profiles
│ │ ├── global.rs # Global agent config
│ │ └── session.rs # Per-session agent config
│ ├── conversation.rs # Conversation helpers
│ └── session_lock.rs # Flock-based session locking
├── service/
│ ├── provider.rs # AI provider abstraction
│ └── oauth/ # OAuth PKCE flow with loopback server
│ ├── loopback.rs # Local HTTP server for OAuth redirect
│ ├── manager.rs # OAuth token manager
│ ├── pkce.rs # PKCE code challenge/verifier
│ └── mod.rs
├── tool/ # 34 tool implementations
│ ├── fs/ # read, write, edit, delete
│ │ ├── read.rs
│ │ ├── write.rs
│ │ ├── edit.rs
│ │ ├── delete.rs
│ │ └── helpers.rs # Path resolution and validation
│ ├── search.rs # grep, glob
│ ├── shell.rs # bash
│ ├── bash_tools.rs # bash_output, bash_kill
│ ├── git_operator.rs # git operations
│ ├── git_worktree.rs # git worktree management
│ ├── git_cred.rs # git credential store/get/erase
│ ├── memory/ # remember, forget, recall
│ │ ├── remember.rs
│ │ ├── forget.rs
│ │ └── recall.rs
│ ├── plan.rs # plan_enter, plan_ready
│ ├── seqthink.rs # Sequential thinking
│ ├── workflow.rs # workflow_run, note_finding
│ ├── utility/ # cd, dir_list, dir_cache_update, pong, todowrite, todofinish
│ │ ├── cd.rs
│ │ ├── dir_list.rs
│ │ ├── dir_cache_update.rs
│ │ ├── pong.rs
│ │ ├── todowrite.rs
│ │ └── todofinish.rs
│ ├── lsp/ # LSP tools (connect, diagnostics, hover, etc.)
│ │ └── mod.rs
│ └── shell_filter/ # Shell output filtering (credentials, git)
│ ├── credentials.rs
│ ├── git.rs
│ └── mod.rs
└── view/ # TUI rendering
├── chat.rs # Chat transcript with markdown
├── markdown.rs # Markdown → ratatui spans
├── status.rs # Status bar
├── theme.rs # Color scheme
└── workflow.rs # Workflow visualization
```
---
## Usage
```bash
# Run in single-process mode (default)
zesdex
# Run as a background daemon
zesdex --daemon
# Attach to a running daemon session
zesdex --attach <session-id>
# Set log level
RUST_LOG=debug zesdex
```
### Key Bindings
| Binding | Action |
|---------|--------|
| `Ctrl+Q` | Quit |
| `Ctrl+H` | Help overlay |
| `Ctrl+P` | Settings overlay |
| `Ctrl+B` | Bash panel |
| `Ctrl+S` | Session hub |
| `Ctrl+T` | Task list |
| `Ctrl+W` | Workflow view |
| `Ctrl+K` | Key input mode |
| `Esc` | Cancel / back |
| `Tab` | Autocomplete |
| `↑/↓` | History / navigation |
| `Scroll` | Mouse scroll in chat |
### Slash Commands
| Command | Description |
|---------|-------------|
| `/help` | Show help |
| `/clear` | Clear transcript |
| `/model` | Select AI model provider |
| `/pipeline` | Show current pipeline mode |
| `/pipeline full` | Force full company pipeline (5 divisions) on next request |
| `/pipeline quick` | Force quick pipeline (3 divisions) on next request |
| `/pipeline skip` | Skip pipeline — handle next request directly |
| `/exit` | Exit application |
| `/settings` | Open settings |
| `Any text` | Sent to the AI assistant as a prompt |
---
## Configuration
All configuration lives in `~/.config/zesdex/` (or platform equivalent via the `dirs` crate).
| File | Purpose |
|------|---------|
| `settings.json` | Provider selection, model, temperature, max tokens, review settings, workflow concurrency |
| `app_config.json` | AI provider definitions (name, API base URL, auth type, default model) |
| `memory/` | Persistent lesson and reference storage (Markdown with YAML frontmatter) |
| `sessions/` | Per-session transcripts, edit logs, and activity data |
| `run/` | Unix domain sockets for daemon mode |
### Provider Configuration
Providers are defined in `app_config.json`:
```json
{
"providers": {
"my-provider": {
"api_base": "https://api.example.com/v1",
"api_key_env": "MY_API_KEY",
"default_model": "model-name"
}
},
"model_roles": {
"default": {
"provider": "my-provider",
"model": "model-name",
"max_tokens": 8192,
"temperature": 0.7
}
},
"default_provider": "my-provider",
"default_model": "model-name"
}
```
### Settings
Key settings in `settings.json`:
| Setting | Default | Description |
|---------|---------|-------------|
| `review_enabled` | `true` | Enable self-review after tool execution |
| `review_max_lessons_per_run` | `5` | Max lessons loaded per review cycle |
| `adaptive_review_max_skip` | `3` | Consecutive passes before skipping review |
| `verify_command` | `null` | Optional command to verify changes |
| `workflow_max_concurrency` | `5` | Max parallel sub-agents in workflows |
| `session_archive_enabled` | `true` | Auto-archive completed sessions |
---
## Installation
### Prerequisites
- **Rust** 2021 edition toolchain ([rustup](https://rustup.rs/))
### Build from Source
```bash
git clone <repository-url>
cd zesdex
cargo build --release
./target/release/zesdex
```
---
## Development
### Commit Convention
Project ini menggunakan **Conventional Commits** untuk otomatis menentukan versi rilis (melalui semantic-release).
Format:
```
<type>(<scope>): <description>
[optional body]
[optional footer]
```
**`<type>` — menentukan bump version:**
| Type | Bump | Keterangan |
|-------------|---------|-------------------------------------------|
| `feat` | minor | Fitur baru |
| `fix` | patch | Perbaikan bug |
| `chore` | patch | Tugas maintenance, refactor ringan |
| `docs` | patch | Perubahan dokumentasi |
| `refactor` | patch | Refactor kode (tanpa perubahan fungsional)|
| `test` | patch | Penambahan atau perbaikan test |
| `style` | patch | Perubahan formatting, whitespace, dll |
| `perf` | patch | Optimasi performa |
| `ci` | patch | Perubahan CI/CD |
**`BREAKING CHANGE`** pada body commit → **major** (apa pun typenya).
Contoh:
```
feat(agent): add workspace-aware file search
Implement context-aware search scoped to current workspace directory.
BREAKING CHANGE: search results now filter by workspace scope.
```
```
fix(ipc): handle partial frame on unix socket reconnect
```
```
chore: update rustls to 0.23
```
### Release Workflow
Push ke branch `main` akan memicu:
1. **CI** — `cargo build --release` + `cargo test`
2. **Semantic Release** — analisis commit → update `Cargo.toml` + `CHANGELOG.md` → git tag → GitHub Release dengan binary
---
## License
See [LICENSE](LICENSE) for details.
+22
View File
@@ -0,0 +1,22 @@
[package]
name = "zesdex-application"
version.workspace = true
edition.workspace = true
authors.workspace = true
# Application layer — port traits (interfaces), use cases, DTOs.
# Depends ONLY on domain. Application services orchestrate domain objects
# through port traits without knowing concrete implementations.
[dependencies]
zesdex-domain = { path = "../domain" }
serde.workspace = true
serde_json.workspace = true
chrono.workspace = true
uuid.workspace = true
anyhow.workspace = true
tracing.workspace = true
tokio.workspace = true
futures-util.workspace = true
base64.workspace = true
sha2.workspace = true
url.workspace = true
+35
View File
@@ -0,0 +1,35 @@
use anyhow::Result;
use std::future::Future;
use zesdex_domain::agent::AgentTurnParams;
/// Interface for dispatching tool calls to their concrete implementations.
pub trait ToolExecutor: Send + Sync {
/// Execute a tool call asynchronously.
fn execute(
&self,
tool_name: &str,
args: &serde_json::Value,
) -> impl Future<Output = Result<String>> + Send;
/// Whether a tool is *read-only* and therefore safe to run concurrently
/// with other read-only tools in the same assistant message.
///
/// Defaults to `false` (sequential) so a caller that does not know the
/// tool surface stays conservative. Concrete executors that know their
/// tools override this — e.g. return `true` for `read`/`grep`/`glob`.
fn is_parallel_safe(&self, tool_name: &str) -> bool {
let _ = tool_name;
false
}
}
/// Service for running agent turns asynchronously.
pub trait AgentTurnService: Send + Sync {
/// Run a full agent turn loop asynchronously.
fn run_turn(&self, params: AgentTurnParams) -> impl Future<Output = Result<()>> + Send;
}
pub mod turn_service;
pub use turn_service::{compact_messages_with_ai, AgentTurnServiceImpl};
+696
View File
@@ -0,0 +1,696 @@
use std::collections::VecDeque;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use tracing::{debug, info, warn};
use zesdex_domain::agent::{AgentTurnParams, TurnEvent};
use zesdex_domain::core::{ChatMessage, StreamEvent, ToolDef};
use zesdex_domain::main_agent_prompt;
use super::ToolExecutor;
use crate::ports::ProviderService;
/// Maximum tool-call iterations per agent turn before forcing termination.
const MAX_TURN_ITERATIONS: u32 = 50;
/// Maximum number of consecutive identical tool errors before the loop
/// injects a recovery note and forces a different approach.
const MAX_CONSECUTIVE_TOOL_ERRORS: usize = 3;
/// Total tool-call errors tolerated per turn before the loop is stopped.
const MAX_TOTAL_TOOL_ERRORS: usize = 8;
/// Ceiling for a single tool-result message inserted into context.
///
/// Tool outputs can be huge (read / semantic_search). Truncating keeps the
/// context window from exploding while preserving the important head.
const TOOL_OUTPUT_MAX_CHARS: usize = 12_000;
/// Total conversation characters that trigger auto-compaction before the
/// next LLM call.
const AUTO_COMPACT_CHARS: usize = 60_000;
// ---------------------------------------------------------------------------
// Helper: push a TurnEvent onto the shared queue.
// ---------------------------------------------------------------------------
fn push_event(queue: &Arc<Mutex<VecDeque<TurnEvent>>>, event: TurnEvent) {
if let Ok(mut q) = queue.lock() {
q.push_back(event);
}
}
// ---------------------------------------------------------------------------
// Helper: stream-event callback that forwards tokens to the turn-event queue
// and checks the abort flag on each emission.
// ---------------------------------------------------------------------------
fn make_stream_callback(
abort: &Arc<AtomicBool>,
turn_events: &Arc<Mutex<VecDeque<TurnEvent>>>,
) -> Box<dyn FnMut(&StreamEvent) -> bool + Send> {
let abort_clone = Arc::clone(abort);
let events_clone = Arc::clone(turn_events);
Box::new(move |event: &StreamEvent| -> bool {
if abort_clone.load(Ordering::SeqCst) {
return false;
}
match event {
StreamEvent::Token(s) => {
push_event(&events_clone, TurnEvent::StreamToken(s.clone()));
}
StreamEvent::Reasoning(s) => {
push_event(&events_clone, TurnEvent::StreamReasoning(s.clone()));
}
_ => {}
}
true
})
}
// ---------------------------------------------------------------------------
// Helper: truncate a long tool output before it enters the conversation
// context. Preserves the head and appends a clear truncation marker.
// ---------------------------------------------------------------------------
fn truncate_tool_output(output: String) -> String {
if output.len() <= TOOL_OUTPUT_MAX_CHARS {
return output;
}
let mut result: String = output.chars().take(TOOL_OUTPUT_MAX_CHARS).collect();
result.push_str(&format!(
"\n...[truncated {} chars]",
output.len() - TOOL_OUTPUT_MAX_CHARS
));
result
}
// ---------------------------------------------------------------------------
// Helper: adaptive generation parameters.
// ---------------------------------------------------------------------------
/// Pick a `max_tokens` budget for the turn's next LLM call based on the
/// length of the user's request. Short requests need far fewer tokens than
/// the current hardcoded 4096 — big savings on small tasks.
fn adaptive_max_tokens(request_len: usize) -> u32 {
if request_len <= 80 {
800
} else if request_len <= 400 {
1600
} else {
4096
}
}
/// Sum the character length of the conversation (user + assistant +
/// tool content) as a cheap proxy for context size.
fn conversation_chars(messages: &[ChatMessage]) -> usize {
messages
.iter()
.map(|m| m.content.as_deref().map(str::len).unwrap_or(0))
.sum()
}
/// Track repeated tool-call errors so the loop can recover instead of
/// burning iterations retrying the same failing tool.
#[derive(Default)]
struct ErrorTracker {
consecutive: usize,
total: usize,
last_tool: String,
last_error: String,
}
impl ErrorTracker {
fn record(&mut self, tool_name: &str, error: &str, messages: &mut Vec<ChatMessage>) {
if self.last_tool == tool_name {
self.consecutive += 1;
} else {
self.consecutive = 1;
}
self.last_tool = tool_name.to_string();
self.last_error = error.to_string();
self.total += 1;
// Inject a recovery note once the same tool keeps failing.
if self.consecutive >= MAX_CONSECUTIVE_TOOL_ERRORS
&& !messages.iter().any(|m| {
m.content
.as_deref()
.is_some_and(|c| c.contains("[System note]"))
})
{
messages.push(ChatMessage::system(
zesdex_domain::agent::prompt::error_recovery_note(tool_name, error),
));
}
}
fn should_stop(&self) -> bool {
self.consecutive >= MAX_CONSECUTIVE_TOOL_ERRORS * 2 || self.total >= MAX_TOTAL_TOOL_ERRORS
}
}
// ---------------------------------------------------------------------------
// Helper: execute a single tool call, push events, return the result string.
// ---------------------------------------------------------------------------
async fn execute_tool_call<T: ToolExecutor>(
tool_executor: &T,
turn_events: &Arc<Mutex<VecDeque<TurnEvent>>>,
tc: &zesdex_domain::core::ToolCall,
) -> String {
let name = &tc.function.name;
let args = zesdex_domain::core::tool_call::sanitize_tool_arguments(&tc.function.arguments);
debug!("executing tool: {name}");
let output = match tool_executor.execute(name, &args).await {
Ok(o) => o,
Err(e) => format!("Error: {e}"),
};
let is_error = output.starts_with("Error:");
let output = truncate_tool_output(output);
push_event(
turn_events,
TurnEvent::ToolResult {
tool_call_id: tc.id.clone(),
tool_name: name.clone(),
output: output.clone(),
is_error,
path: None,
},
);
output
}
// ---------------------------------------------------------------------------
// Helper: bounded-parallel execution of read-only tool calls.
// ---------------------------------------------------------------------------
/// Maximum number of read-only tool calls executed concurrently in a single
/// assistant batch. Models rarely emit more than a handful of reads per
/// message; this cap keeps resource usage bounded while still removing the
/// serial round-trip latency of many independent lookups.
const MAX_PARALLEL_TOOLS: usize = 8;
fn tool_executor_ref<T: ToolExecutor>(tool_executor: &T) -> &T {
tool_executor
}
/// Execute a batch of *read-only* tool calls concurrently (bounded by
/// [`MAX_PARALLEL_TOOLS`]) and return their outputs **in the original call
/// order**.
///
/// Order preservation matters: OpenAI/Anthropic tool-calling contracts expect
/// tool-result messages to appear in the same order as the `tool_calls`
/// emitted in the assistant message. Without it, the model sees shuffled
/// results and loses track of which result belongs to which call.
///
/// Each call still pushes its `TurnEvent::ToolResult` (so the TUI shows each
/// tool as it completes) but the returned `Vec` is ordered by the input index.
async fn execute_tool_calls_in_parallel<T: ToolExecutor>(
tool_executor: &T,
turn_events: &Arc<Mutex<VecDeque<TurnEvent>>>,
tool_calls: &[zesdex_domain::core::ToolCall],
) -> Vec<String> {
let semaphore = Arc::new(tokio::sync::Semaphore::new(MAX_PARALLEL_TOOLS));
let executor_ref = tool_executor_ref(tool_executor);
let futures = tool_calls.iter().map(|tc| {
let tc = tc.clone();
let events = turn_events.clone();
let sem = semaphore.clone();
async move {
// Acquire a permit to bound concurrency across the batch.
let _permit = sem.acquire_owned().await;
execute_tool_call(executor_ref, &events, &tc).await
}
});
futures_util::future::join_all(futures).await
}
// ---------------------------------------------------------------------------
// Helper: emit usage event from optional LLM response metadata.
// ---------------------------------------------------------------------------
fn emit_usage(turn_events: &Arc<Mutex<VecDeque<TurnEvent>>>, usage: Option<(u64, u64)>) {
if let Some((tokens_in, tokens_out)) = usage {
push_event(
turn_events,
TurnEvent::Usage {
tokens_in,
tokens_out,
},
);
}
}
// ---------------------------------------------------------------------------
// Service implementation
// ---------------------------------------------------------------------------
/// Service implementation for executing an agent turn asynchronously.
///
/// The turn loop is adaptive and token-aware:
/// - No mandatory explore phase — the *agent* decides when to call the
/// `explore_codebase` tool (see the main prompt), so simple queries skip
/// exploration entirely.
/// - `max_tokens` / `temperature` adapt to the request length and phase.
/// - Repeated tool errors trigger a system recovery note and eventually
/// stop the loop instead of burning iterations.
/// - Tool outputs are truncated before entering context.
/// - Oversized histories are auto-compacted before the next LLM call.
pub struct AgentTurnServiceImpl<P: ProviderService, T: ToolExecutor> {
provider: Arc<P>,
tool_executor: Arc<T>,
tool_defs: Vec<ToolDef>,
}
impl<P: ProviderService, T: ToolExecutor> AgentTurnServiceImpl<P, T> {
pub fn new(provider: Arc<P>, tool_executor: Arc<T>, tool_defs: Vec<ToolDef>) -> Self {
Self {
provider,
tool_executor,
tool_defs,
}
}
/// Execute a single LLM call with the current message list, handling
/// streaming events and error reporting.
async fn call_llm(
&self,
messages: &[ChatMessage],
abort: &Arc<AtomicBool>,
turn_events: &Arc<Mutex<VecDeque<TurnEvent>>>,
max_tokens: u32,
temperature: f32,
) -> Result<(ChatMessage, Option<(u64, u64)>), String> {
let on_event = make_stream_callback(abort, turn_events);
self.provider
.chat_stream(
messages,
Some(self.tool_defs.clone()),
Some(max_tokens),
Some(temperature),
on_event,
)
.await
.map_err(|e| format!("LLM error: {e}"))
}
/// Auto-compact the history in place if it exceeds the threshold.
///
/// Runs at most once per turn. Skips the synthetic system prompt that
/// this service inserts at index 0.
async fn auto_compact_if_needed(&self, messages: &mut Vec<ChatMessage>) {
if conversation_chars(messages) <= AUTO_COMPACT_CHARS {
return;
}
// Keep the system prompt (index 0) out of compaction.
let sys = messages[0].clone();
let mut rest: Vec<ChatMessage> = messages.drain(1..).collect();
let before = rest.len();
if let Err(e) = super::compact_messages_with_ai(&mut rest, self.provider.as_ref()).await {
warn!("auto-compact failed (non-fatal): {e}");
}
info!(
"auto-compacted history: {} messages -> {}",
before,
rest.len()
);
let mut rebuilt = Vec::with_capacity(rest.len() + 1);
rebuilt.push(sys);
rebuilt.extend(rest);
*messages = rebuilt;
}
}
impl<P: ProviderService, T: ToolExecutor> super::AgentTurnService for AgentTurnServiceImpl<P, T> {
async fn run_turn(&self, mut params: AgentTurnParams) -> anyhow::Result<()> {
info!(
"Starting async agent turn with {} messages (model: {})",
params.messages.len(),
params.model
);
// Insert system prompt at position 0 once and keep it there for the
// entire turn, avoiding per-iteration clones of the full message list.
params
.messages
.insert(0, ChatMessage::system(main_agent_prompt()));
let original_count = params.messages.len();
// Estimate request complexity from the last user message.
let request_len = params
.messages
.last()
.and_then(|m| m.content.as_deref())
.map(str::len)
.unwrap_or(0);
let mut errors = ErrorTracker::default();
// Track whether the previous call produced tool calls — used to
// lower temperature once the agent starts producing a final answer.
let mut saw_tool_calls = false;
for iteration in 0..MAX_TURN_ITERATIONS {
// ── Check abort flag ────────────────────────────────────────
if params.abort.load(Ordering::SeqCst) {
params.abort.store(false, Ordering::SeqCst);
push_event(
&params.turn_events,
TurnEvent::SystemNote {
kind: "info".into(),
message: "Turn aborted by user".into(),
},
);
break;
}
if errors.should_stop() {
push_event(
&params.turn_events,
TurnEvent::SystemNote {
kind: "warn".into(),
message: "Stopping: repeated tool errors without progress".into(),
},
);
break;
}
debug!("agent turn iteration {iteration}");
// ── Auto-compact oversized history before the LLM call ─────
self.auto_compact_if_needed(&mut params.messages).await;
// ── Adaptive generation parameters ─────────────────────────
let max_tokens = adaptive_max_tokens(request_len);
// Lower temperature while the agent is still choosing tools to
// keep tool selection deterministic; raise it for the final
// free-form answer.
let temperature = if saw_tool_calls { 0.2 } else { 0.7 };
// ── Stream start + call LLM ─────────────────────────────────
push_event(&params.turn_events, TurnEvent::StreamStart);
let result = self
.call_llm(
&params.messages,
&params.abort,
&params.turn_events,
max_tokens,
temperature,
)
.await;
match result {
Ok((assistant_msg, usage)) => {
let content = assistant_msg.content.clone().unwrap_or_default();
let tool_calls = assistant_msg.tool_calls.clone().unwrap_or_default();
push_event(
&params.turn_events,
TurnEvent::StreamDone(assistant_msg.clone()),
);
emit_usage(&params.turn_events, usage);
// ── No tool calls → assistant is done ──────────────
if tool_calls.is_empty() {
params.messages.push(ChatMessage::assistant(Some(content)));
break;
}
saw_tool_calls = true;
params.messages.push(assistant_msg);
// ── Execute each tool call ──────────────────────────
//
// If the whole batch is made of *read-only* tools
// (read/grep/glob/…), run it concurrently with bounded
// parallelism — a big latency win for coding turns that
// emit several independent lookups in one message. Any
// single mutating tool forces the whole batch back to the
// safe sequential path so writes never race.
//
// Results are always collected in the original call order
// to honour the tool-calling contract.
let parallel = tool_calls.len() > 1
&& tool_calls
.iter()
.all(|tc| self.tool_executor.is_parallel_safe(&tc.function.name));
let outputs: Vec<String> = if parallel {
execute_tool_calls_in_parallel(
self.tool_executor.as_ref(),
&params.turn_events,
&tool_calls,
)
.await
} else {
let mut sequential = Vec::with_capacity(tool_calls.len());
for tc in &tool_calls {
let out = execute_tool_call(
self.tool_executor.as_ref(),
&params.turn_events,
tc,
)
.await;
sequential.push(out);
}
sequential
};
for (tc, output) in tool_calls.iter().zip(outputs) {
if output.starts_with("Error:") {
errors.record(&tc.function.name, &output, &mut params.messages);
}
params
.messages
.push(ChatMessage::tool(tc.id.clone(), output));
}
}
Err(e) => {
warn!("{e}");
push_event(&params.turn_events, TurnEvent::Error(e));
break;
}
}
}
// Remove the synthetic sys_msg before shipping events to the TUI
// so the transcript shows only the actual user/assistant/tool exchange.
let compacted: Vec<ChatMessage> = params.messages.drain(original_count - 1..).collect();
push_event(&params.turn_events, TurnEvent::Compacted(compacted));
push_event(&params.turn_events, TurnEvent::Done);
params.in_flight.store(false, Ordering::SeqCst);
Ok(())
}
}
// ---------------------------------------------------------------------------
// Conversation compaction
// ---------------------------------------------------------------------------
/// Maximum number of recent messages to preserve during compaction.
const COMPACT_KEEP_TAIL: usize = 6;
/// Compacts conversation history using AI summarisation.
///
/// Flow: if the message count exceeds `KEEP_TAIL + 2`, the oldest messages
/// are drained and summarised by the LLM. The summary is inserted as a
/// system message at the head of the remaining history.
pub async fn compact_messages_with_ai<P: ProviderService>(
messages: &mut Vec<ChatMessage>,
provider: &P,
) -> anyhow::Result<()> {
if messages.len() <= COMPACT_KEEP_TAIL + 2 {
return Ok(()); // Not enough messages to compact
}
let split_idx = messages.len() - COMPACT_KEEP_TAIL;
let evicted: Vec<_> = messages.drain(..split_idx).collect();
let mut summary_prompt = vec![ChatMessage::system(zesdex_domain::compaction_prompt())];
summary_prompt.extend(evicted);
summary_prompt.push(ChatMessage::user(
"Please summarise our previous conversation above for context continuity.".to_string(),
));
match provider
.chat(&summary_prompt, None, Some(1024), Some(0.3))
.await
{
Ok((summary_msg, _)) => {
let summary_text = summary_msg
.content
.unwrap_or_else(|| "Previous context summarised.".to_string());
let summary_node = ChatMessage::system(format!(
"[AI Summary of Previous Conversation]\n{}",
summary_text.trim()
));
messages.insert(0, summary_node);
Ok(())
}
Err(e) => {
warn!("AI summarisation failed during compact, falling back to simple notice: {e}");
messages.insert(
0,
ChatMessage::system(
"[Earlier conversation messages compacted to save context window]".to_string(),
),
);
Ok(())
}
}
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn truncate_short_output_is_unchanged() {
let out = "short".to_string();
assert_eq!(truncate_tool_output(out.clone()), out);
}
#[test]
fn truncate_long_output_preserves_head_and_marks_cut() {
let long = "x".repeat(TOOL_OUTPUT_MAX_CHARS + 500);
let truncated = truncate_tool_output(long.clone());
assert!(truncated.len() < long.len());
assert!(truncated.contains("...[truncated"));
assert!(truncated.starts_with("xxx"));
}
#[test]
fn adaptive_max_tokens_scales_with_request_len() {
assert_eq!(adaptive_max_tokens(10), 800);
assert_eq!(adaptive_max_tokens(200), 1600);
assert_eq!(adaptive_max_tokens(5000), 4096);
}
#[test]
fn error_tracker_injects_recovery_note_after_repeats() {
let mut tracker = ErrorTracker::default();
let mut messages: Vec<ChatMessage> = Vec::new();
tracker.record("read", "Error: File not found", &mut messages);
tracker.record("read", "Error: File not found", &mut messages);
assert!(!tracker.should_stop());
// Third consecutive failure → recovery note injected.
tracker.record("read", "Error: File not found", &mut messages);
assert!(messages.iter().any(|m| m
.content
.as_deref()
.is_some_and(|c| c.contains("[System note]"))));
}
#[test]
fn error_tracker_stops_after_too_many_errors() {
let mut tracker = ErrorTracker::default();
let mut messages: Vec<ChatMessage> = Vec::new();
for i in 0..MAX_TOTAL_TOOL_ERRORS {
tracker.record("bash", &format!("Error: boom {i}"), &mut messages);
}
assert!(tracker.should_stop());
}
#[test]
fn conversation_chars_sums_content_only() {
let messages = vec![
ChatMessage::system("sys".to_string()),
ChatMessage::user("hello world".to_string()),
ChatMessage::tool("id".to_string(), "output".to_string()),
];
assert_eq!(conversation_chars(&messages), 3 + 11 + 6);
}
/// A fake executor that reports parallel-safety for read-only tools and
/// whose `execute` sleeps on the first call to prove the batch runs
/// concurrently (a sequential loop would pay the sleep per call).
struct FakeExecutor;
impl ToolExecutor for FakeExecutor {
async fn execute(&self, name: &str, _args: &serde_json::Value) -> anyhow::Result<String> {
if name == "read" {
// 30ms sleep on every read; a parallel batch of 3 would
// finish in ~30ms instead of ~90ms sequentially.
tokio::time::sleep(std::time::Duration::from_millis(30)).await;
}
Ok(format!("out:{name}"))
}
fn is_parallel_safe(&self, name: &str) -> bool {
matches!(name, "read" | "grep")
}
}
fn tc(name: &str, id: usize) -> zesdex_domain::core::ToolCall {
zesdex_domain::core::ToolCall {
id: format!("call_{id}"),
type_: "function".to_string(),
function: zesdex_domain::core::ToolFunction {
name: name.to_string(),
arguments: serde_json::Value::String(String::new()),
},
}
}
#[test]
fn parallel_batch_runs_concurrently_and_preserves_order() {
let executor = FakeExecutor;
let events = Arc::new(Mutex::new(VecDeque::new()));
let calls = vec![tc("read", 1), tc("grep", 2), tc("read", 3)];
// All three are parallel-safe.
assert!(calls
.iter()
.all(|c| executor.is_parallel_safe(&c.function.name)));
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_time()
.build()
.unwrap();
let started = std::time::Instant::now();
let outputs = rt.block_on(execute_tool_calls_in_parallel(&executor, &events, &calls));
let elapsed = started.elapsed();
// Results are in *original* call order (read, grep, read).
assert_eq!(
outputs,
vec![
"out:read".to_string(),
"out:grep".to_string(),
"out:read".to_string()
]
);
// Two reads sleep 30ms each; sequential would take ~60ms+ for the
// two reads, parallel keeps the whole batch under 60ms.
assert!(
elapsed < std::time::Duration::from_millis(60),
"batch took {elapsed:?}, expected parallel execution"
);
assert!(elapsed >= std::time::Duration::from_millis(25));
}
#[test]
fn mutating_batch_falls_back_to_sequential_path() {
// A batch containing a mutating tool is not eligible for the parallel
// path, so the main loop keeps results ordered and side-effects safe.
let executor = FakeExecutor;
let calls = [tc("read", 1), tc("edit", 2)];
assert!(!calls
.iter()
.all(|c| executor.is_parallel_safe(&c.function.name)));
}
}
+16
View File
@@ -0,0 +1,16 @@
//! Auth use-case implementations.
//!
//! Contains concrete service types that implement the domain's
//! authentication and session management traits by coordinating
//! injected repository and port dependencies.
//!
//! # Use Cases
//!
//! - [`oauth_service`] — `OAuthUseCase`: OAuth 2.0 authorization-code + PKCE flow
//! - [`session_service`] — `SessionServiceImpl`: session CRUD lifecycle
pub mod oauth_service;
pub mod session_service;
pub use oauth_service::{OAuthFlowStore, OAuthUseCase, TokenExchanger};
pub use session_service::SessionServiceImpl;
+237
View File
@@ -0,0 +1,237 @@
//! OAuth 2.0 authorization-code + PKCE flow use-case.
//!
//! `OAuthUseCase` orchestrates the standard PKCE-enhanced OAuth flow:
//!
//! 1. **`start_flow`** — generates a cryptographic PKCE code verifier,
//! derives its S256 challenge, creates a CSRF state token, persists
//! the verifier + state via `OAuthFlowStore`, and builds an
//! authorization URL with all required parameters.
//! 2. **`complete_flow`** — validates the returned `state` against the
//! stored value (CSRF check), reads the stored verifier, delegates
//! the token-code exchange to an injected `TokenExchanger`, and
//! persists the resulting `OAuthToken` via `OAuthRepository`.
//! 3. **`get_token`** — loads the stored OAuth token (if any).
//!
//! # Portability
//!
//! The service is generic over three injected dependencies:
//! - `R: OAuthRepository` — token persistence
//! - `S: OAuthFlowStore` — ephemeral flow state (verifier + CSRF state)
//! - `E: TokenExchanger` — the HTTP token-endpoint exchange
//!
//! This keeps all I/O and protocol-level concerns abstracted behind
//! port traits; the service itself contains only orchestration logic.
use std::path::PathBuf;
use tracing;
use zesdex_domain::auth::{OAuthConfig, OAuthRepository, OAuthToken, ServiceError};
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use base64::Engine as _;
use sha2::{Digest, Sha256};
// ---------------------------------------------------------------------------
// Port traits (defined here because they are specific to this use-case)
// ---------------------------------------------------------------------------
/// Persistence contract for ephemeral OAuth flow state.
///
/// Between `start_flow` and `complete_flow` the verifier and CSRF state
/// must survive across process boundaries (the user opens a browser, the
/// provider redirects back to a loopback listener on the next invocation).
///
/// Implementors store key-value pairs to disk or another durable medium
/// and clear them after a successful (or failed) flow completion.
pub trait OAuthFlowStore: Send + Sync {
/// Persist the PKCE code verifier and CSRF state token.
fn save_flow_state(&self, verifier: &str, state: &str) -> Result<(), ServiceError>;
/// Load the stored PKCE code verifier.
fn load_verifier(&self) -> Result<String, ServiceError>;
/// Load the stored CSRF state token.
fn load_state(&self) -> Result<String, ServiceError>;
/// Clear stored flow state (verifier + state).
fn clear(&self) -> Result<(), ServiceError>;
}
/// Abstraction for exchanging an authorization code for tokens.
///
/// Implementors handle the HTTP POST to the provider's token endpoint
/// with the appropriate form-encoded parameters, parse the JSON
/// response, and return the extracted `OAuthToken`.
pub trait TokenExchanger: Send + Sync {
/// Exchange an authorization code for an access token.
///
/// ## Parameters
/// - `token_url` — the provider's token endpoint URL
/// - `client_id` — OAuth client identifier
/// - `client_secret` — optional client secret
/// - `redirect_uri` — must match the URI used in `start_flow`
/// - `code` — the authorization code from the provider's redirect
/// - `code_verifier` — the PKCE verifier from `start_flow`
fn exchange_code(
&self,
token_url: &str,
client_id: &str,
client_secret: Option<&str>,
redirect_uri: &str,
code: &str,
code_verifier: &str,
) -> Result<OAuthToken, ServiceError>;
}
// ---------------------------------------------------------------------------
// PKCE helpers
// ---------------------------------------------------------------------------
/// Generate a PKCE code-verifier and its S256 code-challenge.
///
/// Uses 32 cryptographically random bytes, base64url-encoded (no padding)
/// for the verifier, then SHA-256 hashes the verifier and base64url-encodes
/// the digest for the challenge. This satisfies the PKCE `S256` method
/// which requires a minimum verifier length of 43 characters.
fn generate_pkce_pair() -> (String, String) {
// 32 random bytes → 43 base64url chars (well above the 43-char PKCE
// minimum).
let mut bytes = [0u8; 32];
bytes[..16].copy_from_slice(uuid::Uuid::new_v4().as_bytes());
bytes[16..].copy_from_slice(uuid::Uuid::new_v4().as_bytes());
let verifier = URL_SAFE_NO_PAD.encode(bytes);
let challenge = {
let mut hasher = Sha256::new();
hasher.update(verifier.as_bytes());
URL_SAFE_NO_PAD.encode(hasher.finalize())
};
(verifier, challenge)
}
/// Generate a random CSRF state token (UUID-based, 36 chars).
fn generate_state_token() -> String {
uuid::Uuid::new_v4().to_string()
}
// ---------------------------------------------------------------------------
// Service
// ---------------------------------------------------------------------------
/// Concrete OAuth flow use-case.
///
/// Generic over three dependencies:
/// - `R` — token persistence (`OAuthRepository`)
/// - `S` — flow-state persistence (`OAuthFlowStore`)
/// - `E` — token-endpoint HTTP exchange (`TokenExchanger`)
pub struct OAuthUseCase<R, S, E> {
/// Repository for persisting / loading OAuth tokens.
pub token_repo: R,
/// Store for ephemeral flow state (verifier + CSRF state).
pub flow_store: S,
/// Token-endpoint HTTP exchanger.
pub token_exchanger: E,
/// File path for the token JSON file.
pub token_path: PathBuf,
}
impl<R: OAuthRepository, S: OAuthFlowStore, E: TokenExchanger> OAuthUseCase<R, S, E> {
/// Create a new OAuth use-case.
pub fn new(token_repo: R, flow_store: S, token_exchanger: E, token_path: PathBuf) -> Self {
OAuthUseCase {
token_repo,
flow_store,
token_exchanger,
token_path,
}
}
}
impl<R: OAuthRepository, S: OAuthFlowStore, E: TokenExchanger> zesdex_domain::auth::OAuthService
for OAuthUseCase<R, S, E>
{
fn start_flow(
&self,
config: &OAuthConfig,
redirect_uri: &str,
) -> Result<(String, String), ServiceError> {
if config.auth_url.is_empty() {
return Err(ServiceError::InvalidConfig(
"OAuth auth_url is empty".to_string(),
));
}
let (verifier, challenge) = generate_pkce_pair();
let state = generate_state_token();
// Persist verifier + state so `complete_flow` can retrieve them.
self.flow_store.save_flow_state(&verifier, &state)?;
tracing::debug!(
auth_url = %config.auth_url,
redirect_uri = %redirect_uri,
state_len = state.len(),
"starting OAuth flow",
);
let mut url = url::Url::parse(&config.auth_url).map_err(|e| {
ServiceError::InvalidConfig(format!("invalid auth_url '{}': {e}", config.auth_url))
})?;
url.query_pairs_mut()
.append_pair("response_type", "code")
.append_pair("client_id", &config.client_id)
.append_pair("redirect_uri", redirect_uri)
.append_pair("scope", &config.scopes.join(" "))
.append_pair("state", &state)
.append_pair("code_challenge_method", "S256")
.append_pair("code_challenge", &challenge);
Ok((url.to_string(), state))
}
fn complete_flow(
&self,
config: &OAuthConfig,
redirect_uri: &str,
code: &str,
state: &str,
) -> Result<OAuthToken, ServiceError> {
// CSRF check: validate the returned state against the stored value.
let expected_state = self.flow_store.load_state()?;
if expected_state != state {
return Err(ServiceError::StateMismatch);
}
// Read the PKCE verifier that was saved in `start_flow`.
let verifier = self.flow_store.load_verifier()?;
tracing::debug!(
token_url = %config.token_url,
code_len = code.len(),
"completing OAuth flow — exchanging code for token",
);
// Delegate the HTTP token exchange to the injected exchanger.
let token = self.token_exchanger.exchange_code(
&config.token_url,
&config.client_id,
config.client_secret.as_deref(),
redirect_uri,
code,
&verifier,
)?;
// Persist the token and clean up flow state.
self.token_repo.save_token(&self.token_path, &token)?;
let _ = self.flow_store.clear();
Ok(token)
}
fn get_token(&self) -> Result<Option<OAuthToken>, ServiceError> {
self.token_repo
.load_token(&self.token_path)
.map_err(ServiceError::Repository)
}
}
@@ -0,0 +1,84 @@
//! Session management use-case.
//!
//! `SessionServiceImpl` implements [`SessionService`] from the domain
//! layer by delegating CRUD operations to injected repository traits.
//!
//! # Flow
//!
//! - **`create_session`** — generates a UUID v4 id, creates a `Session`
//! entity with the given title, persists via `SessionRepository`.
//! - **`list_all`** — delegates to `SessionRepository::list_sessions`.
//! - **`archive_session`** — loads session, sets `archived = true`,
//! persists the updated entity.
//!
//! # Generics
//!
//! - `R: SessionRepository` — session CRUD persistence
//! - `L: SessionLockRepository` — session lock acquire/release
use std::path::PathBuf;
use tracing;
use uuid::Uuid;
use zesdex_domain::auth::{
ServiceError, Session, SessionId, SessionLockRepository, SessionRepository,
};
/// Concrete session service backed by injected repository implementations.
pub struct SessionServiceImpl<R: SessionRepository, L: SessionLockRepository> {
/// Repository for session CRUD operations.
pub session_repo: R,
/// Repository for session lock acquire/release.
pub lock_repo: L,
/// Base data directory passed to repository methods.
pub base_dir: PathBuf,
}
impl<R: SessionRepository, L: SessionLockRepository> SessionServiceImpl<R, L> {
/// Create a new session service with the given repositories and base
/// data directory.
pub fn new(session_repo: R, lock_repo: L, base_dir: PathBuf) -> Self {
SessionServiceImpl {
session_repo,
lock_repo,
base_dir,
}
}
}
impl<R: SessionRepository, L: SessionLockRepository> zesdex_domain::auth::SessionService
for SessionServiceImpl<R, L>
{
fn create_session(&self, title: &str) -> Result<Session, ServiceError> {
let id = SessionId::new(&Uuid::new_v4().to_string()).map_err(ServiceError::Other)?;
let title_owned = if title.is_empty() {
"New Session".to_string()
} else {
title.to_string()
};
let session = Session::new(id.into_string(), title_owned);
tracing::debug!(session_id = %session.id, title = %session.title, "creating new session");
self.session_repo.save_session(&self.base_dir, &session)?;
Ok(session)
}
fn list_all(&self) -> Result<Vec<Session>, ServiceError> {
tracing::debug!("listing all sessions");
self.session_repo
.list_sessions(&self.base_dir)
.map_err(ServiceError::Repository)
}
fn archive_session(&self, id: SessionId) -> Result<(), ServiceError> {
tracing::debug!(session_id = %id, "archiving session");
let mut session = self.session_repo.load_session(&self.base_dir, &id)?;
session.archived = true;
let millis = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis();
session.updated_at = i64::try_from(millis).unwrap_or(i64::MAX);
self.session_repo.save_session(&self.base_dir, &session)?;
Ok(())
}
}
@@ -0,0 +1,68 @@
//! Conversation use-case implementation.
//!
//! `ConversationServiceImpl` implements [`ConversationService`] from the
//! domain layer. It is generic over `R: ConversationRepository`, delegating
//! all persistence to that adapter.
//!
//! # Flow
//!
//! Each method computes the session directory from the session ID, then
//! delegates the actual I/O to the injected `repo`. Error context is
//! added at this layer to identify which session caused the failure.
use std::path::PathBuf;
use tracing;
use zesdex_domain::cms::{Conversation, ConversationRepository, ServiceError};
use zesdex_domain::core::ChatMessage;
/// Service implementation for conversation CRUD operations.
///
/// Generic over `R: ConversationRepository` so the persistence layer
/// can be swapped without changing business logic.
pub struct ConversationServiceImpl<R> {
pub repo: R,
/// Base directory containing session subdirectories.
pub sessions_dir: PathBuf,
}
impl<R: ConversationRepository> ConversationServiceImpl<R> {
/// Create a new service with the given repository and sessions directory.
pub fn new(repo: R, sessions_dir: impl Into<PathBuf>) -> Self {
tracing::debug!("creating ConversationServiceImpl");
Self {
repo,
sessions_dir: sessions_dir.into(),
}
}
/// Compute the session directory for a given session id.
fn session_dir(&self, session_id: &str) -> PathBuf {
self.sessions_dir.join(session_id)
}
}
impl<R: ConversationRepository> zesdex_domain::cms::ConversationService
for ConversationServiceImpl<R>
{
fn load_conversation(&self, session_id: &str) -> Result<Conversation, ServiceError> {
tracing::debug!("loading conversation for session {session_id}");
let dir = self.session_dir(session_id);
self.repo.load(&dir).map_err(ServiceError::Repository)
}
fn save_conversation(&self, conv: &Conversation) -> Result<(), ServiceError> {
tracing::debug!("saving conversation for session {}", conv.session_id);
let dir = self.session_dir(&conv.session_id);
self.repo.save(&dir, conv)?;
Ok(())
}
fn add_message(&self, conv: &mut Conversation, msg: ChatMessage) -> Result<(), ServiceError> {
tracing::debug!("adding message to session {}", conv.session_id);
conv.push(msg);
let dir = self.session_dir(&conv.session_id);
self.repo.save(&dir, conv)?;
Ok(())
}
}
@@ -0,0 +1,59 @@
//! Memory use-case implementation.
//!
//! `MemoryServiceImpl` implements [`MemoryService`] from the domain
//! layer. It is generic over `R: MemoryRepository`, delegating all
//! persistence to that adapter.
//!
//! # Flow
//!
//! Each method delegates to the injected `repo` with the configured
//! `memory_dir`. Error context is added at this layer to identify which
//! memory operation failed.
use std::path::PathBuf;
use tracing;
use zesdex_domain::cms::{Memory, MemoryRepository, ServiceError};
/// Service implementation for memory CRUD operations.
///
/// Generic over `R: MemoryRepository` so the persistence layer can be
/// swapped without changing business logic.
pub struct MemoryServiceImpl<R> {
pub repo: R,
/// Base directory for memory storage files.
pub memory_dir: PathBuf,
}
impl<R: MemoryRepository> MemoryServiceImpl<R> {
/// Create a new service with the given repository and memory directory.
pub fn new(repo: R, memory_dir: impl Into<PathBuf>) -> Self {
tracing::debug!("creating MemoryServiceImpl");
Self {
repo,
memory_dir: memory_dir.into(),
}
}
}
impl<R: MemoryRepository> zesdex_domain::cms::MemoryService for MemoryServiceImpl<R> {
fn list_memories(&self) -> Result<Vec<String>, ServiceError> {
tracing::debug!("listing memories from {:?}", self.memory_dir);
self.repo
.list(&self.memory_dir)
.map_err(ServiceError::Repository)
}
fn save_memory(&self, memory: &Memory) -> Result<(), ServiceError> {
tracing::debug!("saving memory '{}'", memory.name);
self.repo.save(&self.memory_dir, memory)?;
Ok(())
}
fn delete_memory(&self, name: &str) -> Result<(), ServiceError> {
tracing::debug!("deleting memory '{name}'");
self.repo
.delete(&self.memory_dir, name)
.map_err(ServiceError::Repository)
}
}
+18
View File
@@ -0,0 +1,18 @@
//! CMS use-case implementations.
//!
//! Contains concrete service types that implement the domain's CMS
//! service traits by coordinating injected repository dependencies.
//!
//! # Use Cases
//!
//! - [`conversation_service`] — `ConversationServiceImpl`: conversation CRUD
//! - [`memory_service`] — `MemoryServiceImpl`: long-term memory management
//! - [`settings_service`] — `SettingsServiceImpl`: settings & app-config management
pub mod conversation_service;
pub mod memory_service;
pub mod settings_service;
pub use conversation_service::ConversationServiceImpl;
pub use memory_service::MemoryServiceImpl;
pub use settings_service::SettingsServiceImpl;
@@ -0,0 +1,67 @@
//! Settings and app-config use-case implementation.
//!
//! `SettingsServiceImpl` implements [`SettingsService`] from the domain
//! layer. It is generic over `S: SettingsRepository` and `C: AppConfigRepository`,
//! delegating persistence to those adapters.
//!
//! # Flow
//!
//! Each method delegates to the appropriate injected repository with the
//! configured `base_dir`. The `update_provider` method coordinates between
//! both repositories: load app config → mutate provider map → save app config.
use std::path::PathBuf;
use tracing;
use zesdex_domain::cms::{
AppConfig, AppConfigRepository, ProviderConfig, ServiceError, Settings, SettingsRepository,
};
/// Service implementation for settings and app-config operations.
///
/// Generic over `S: SettingsRepository` and `C: AppConfigRepository` so
/// the persistence layer can be swapped without changing business logic.
pub struct SettingsServiceImpl<S, C> {
pub settings_repo: S,
pub app_config_repo: C,
pub base_dir: PathBuf,
}
impl<S: SettingsRepository, C: AppConfigRepository> SettingsServiceImpl<S, C> {
/// Create a new service with the given repositories and base directory.
pub fn new(settings_repo: S, app_config_repo: C, base_dir: impl Into<PathBuf>) -> Self {
tracing::debug!("creating SettingsServiceImpl");
Self {
settings_repo,
app_config_repo,
base_dir: base_dir.into(),
}
}
}
impl<S: SettingsRepository, C: AppConfigRepository> zesdex_domain::cms::SettingsService
for SettingsServiceImpl<S, C>
{
fn load_settings(&self) -> Result<Settings, ServiceError> {
tracing::debug!("loading settings");
self.settings_repo
.load(&self.base_dir)
.map_err(ServiceError::Repository)
}
fn save_settings(&self, settings: &Settings) -> Result<(), ServiceError> {
tracing::debug!("saving settings");
self.settings_repo.save(&self.base_dir, settings)?;
Ok(())
}
fn update_provider(&self, name: &str, config: &ProviderConfig) -> Result<(), ServiceError> {
tracing::debug!("updating provider '{name}'");
let mut app_config: AppConfig = self.app_config_repo.load(&self.base_dir)?;
app_config
.providers
.insert(name.to_string(), config.clone());
self.app_config_repo.save(&self.base_dir, &app_config)?;
Ok(())
}
}
+56
View File
@@ -0,0 +1,56 @@
//! # Zesdex Application Layer
//!
//! Defines port traits (interfaces) and use-case implementations for the
//! Zesdex application. This crate depends **only** on the domain crate;
//! it has no knowledge of infrastructure or interface adapters.
//!
//! ## Architecture
//!
//! ```text
//! apps/application/src/
//! ├── lib.rs — crate root, re-exports
//! ├── ports/ — Port traits (interfaces to external services)
//! │ ├── provider.rs -- ProviderService (LLM chat completion)
//! │ ├── password.rs -- PasswordService (hash / verify)
//! │ ├── token.rs -- TokenService (JWT create / verify)
//! │ └── authentication.rs -- AuthService (combined auth)
//! ├── auth/ — Auth use-cases
//! │ ├── oauth_service.rs -- OAuth 2.0 PKCE flow
//! │ └── session_service.rs -- Session CRUD lifecycle
//! └── cms/ — CMS use-cases
//! ├── conversation_service.rs -- Conversation CRUD
//! ├── memory_service.rs -- Long-term memory management
//! └── settings_service.rs -- Settings & app-config management
//! ```
//!
//! ## Key Design Principle
//!
//! Application services are generic over their repository/port dependencies.
//! Concrete implementations are injected at the composition root, keeping
//! the use-case logic independent of any specific persistence or infrastructure
//! technology.
pub mod agent;
pub mod auth;
pub mod cms;
pub mod ports;
// Re-export port traits for ergonomic access.
pub use ports::*;
// Re-export auth use-cases.
pub use auth::{
oauth_service::{OAuthFlowStore, OAuthUseCase, TokenExchanger},
session_service::SessionServiceImpl,
};
// Re-export CMS use-cases.
pub use cms::{
conversation_service::ConversationServiceImpl, memory_service::MemoryServiceImpl,
settings_service::SettingsServiceImpl,
};
pub use agent::{
turn_service::{compact_messages_with_ai, AgentTurnServiceImpl},
AgentTurnService, ToolExecutor,
};
@@ -0,0 +1,32 @@
//! AuthService port — combined authentication operations.
//!
//! Defines a high-level authentication trait that composes password
//! verification and token generation into a single use-case boundary.
//! Implementations delegate to the injected `PasswordService` and
//! `TokenService` adapters.
use anyhow::Result;
use std::future::Future;
/// High-level authentication service combining password verification
/// and token issuance (login flow).
///
/// # Flow
///
/// 1. **`authenticate`** — verify a subject's password against a stored hash.
/// 2. **`issue_tokens`** — generate an access + refresh token pair for a subject.
///
/// Implementations are generic over `PasswordService` and `TokenService`
/// port traits.
pub trait AuthService: Send + Sync {
/// Authenticate a user by verifying a password against a stored hash.
///
/// Returns `true` if the password matches, `false` otherwise.
fn authenticate(&self, password: &str, hash: &str)
-> impl Future<Output = Result<bool>> + Send;
/// Issue a new access + refresh token pair for the given subject.
///
/// Returns `(access_token, refresh_token)`.
fn issue_tokens(&self, sub: &str) -> Result<(String, String)>;
}
+22
View File
@@ -0,0 +1,22 @@
//! Port traits — interfaces for external / infrastructure services.
//!
//! These traits define the boundaries between the application layer and
//! the outside world. Infrastructure adapters implement these traits;
//! the application layer depends only on the trait definitions.
//!
//! # Ports
//!
//! - [`provider`] — `ProviderService`: LLM chat completion (streaming + non-streaming)
//! - [`password`] — `PasswordService`: password hashing and verification
//! - [`token`] — `TokenService`: JWT access/refresh token generation and verification
//! - [`authentication`] — `AuthService`: combined authentication operations
pub mod authentication;
pub mod password;
pub mod provider;
pub mod token;
pub use authentication::AuthService;
pub use password::PasswordService;
pub use provider::ProviderService;
pub use token::TokenService;
+24
View File
@@ -0,0 +1,24 @@
//! PasswordService port — password hashing and verification abstraction.
//!
//! Defines the trait that password-hashing adapters (argon2, bcrypt, etc.)
//! implement. The application layer depends only on this trait, never on
//! a concrete hashing library.
use anyhow::Result;
use std::future::Future;
/// Abstraction for password hashing and verification.
///
/// Implementors handle the actual hashing algorithm (argon2, bcrypt, etc.)
/// and parameter selection. The trait is `Send + Sync` for use in async
/// service layers.
pub trait PasswordService: Send + Sync {
/// Hash a plaintext password and return the encoded hash string
/// (suitable for storage in a credential store).
fn hash(&self, password: &str) -> impl Future<Output = Result<String>> + Send;
/// Verify a plaintext password against a previously-hashed string.
///
/// Returns `true` if the password matches the hash, `false` otherwise.
fn verify(&self, password: &str, hash: &str) -> impl Future<Output = Result<bool>> + Send;
}
+56
View File
@@ -0,0 +1,56 @@
//! ProviderService port — LLM chat completion provider abstraction.
//!
//! Defines the trait that HTTP-based provider clients (OpenAI, Anthropic,
//! etc.) implement. Supports both non-streaming and SSE-streaming chat
//! completion requests.
//!
//! # Flow
//!
//! 1. Caller builds a message list and optional tool definitions.
//! 2. `chat` sends a non-streaming request and returns the full response.
//! 3. `chat_stream` sends a streaming request and invokes `on_event` for
//! each parsed `StreamEvent` as it arrives, then returns the assembled
//! message and usage.
use anyhow::Result;
use std::future::Future;
use zesdex_domain::core::{ChatMessage, StreamEvent, ToolDef};
/// Abstraction for an LLM provider chat-completion service.
///
/// Both methods accept a message list, optional tool definitions, and
/// generation parameters. Implementors handle authentication, HTTP
/// transport, retry logic, and response parsing internally.
///
/// # Send + Sync
///
/// This trait is `Send + Sync` so it can be shared across async tasks
/// and injected into service structs that require thread safety.
pub trait ProviderService: Send + Sync {
/// Send a non-streaming chat completion request.
///
/// Returns the assistant's `ChatMessage` and optional token usage
/// `(prompt_tokens, completion_tokens)`.
fn chat(
&self,
messages: &[ChatMessage],
tools: Option<Vec<ToolDef>>,
max_tokens: Option<u32>,
temperature: Option<f32>,
) -> impl Future<Output = Result<(ChatMessage, Option<(u64, u64)>)>> + Send;
/// Send a streaming chat completion request.
///
/// `on_event` is called for every parsed SSE event and returns `false`
/// to signal abort (caller cancellation). Returns the fully assembled
/// assistant message and optional usage once the stream completes.
fn chat_stream(
&self,
messages: &[ChatMessage],
tools: Option<Vec<ToolDef>>,
max_tokens: Option<u32>,
temperature: Option<f32>,
on_event: Box<dyn FnMut(&StreamEvent) -> bool + Send>,
) -> impl Future<Output = Result<(ChatMessage, Option<(u64, u64)>)>> + Send;
}
+32
View File
@@ -0,0 +1,32 @@
//! TokenService port — JWT access and refresh token abstraction.
//!
//! Defines the trait that JWT adapter implementations provide. Covers
//! token generation (pair of access + refresh tokens) and access token
//! verification (returns the subject claim).
use anyhow::Result;
/// Abstraction for JWT-based token generation and verification.
///
/// Implementors handle signing key management, token serialisation,
/// and expiry validation. The trait is `Send + Sync` for use across
/// thread boundaries.
pub trait TokenService: Send + Sync {
/// Generate an access + refresh token pair for the given subject
/// identifier.
///
/// Returns `(access_token, refresh_token)`.
fn generate_tokens(&self, sub: &str) -> Result<(String, String)>;
/// Verify an access token and return the embedded subject claim.
///
/// Returns `Err` if the token is expired, malformed, or has an
/// invalid signature.
fn verify_access_token(&self, token: &str) -> Result<String>;
/// Verify a refresh token and return the embedded subject claim.
///
/// Returns `Err` if the token is expired, malformed, or has an
/// invalid signature.
fn verify_refresh_token(&self, token: &str) -> Result<String>;
}
+25
View File
@@ -0,0 +1,25 @@
[package]
name = "zesdex-bootstrap"
version.workspace = true
edition.workspace = true
authors.workspace = true
# Bootstrap binary — seeds initial system data (permissions, roles,
# admin user) idempotently. Run once after first deployment.
[[bin]]
name = "bootstrap"
path = "src/main.rs"
[dependencies]
zesdex-domain = { path = "../domain" }
zesdex-application = { path = "../application" }
zesdex-infrastructure = { path = "../infrastructure" }
serde.workspace = true
serde_json.workspace = true
chrono.workspace = true
uuid.workspace = true
anyhow.workspace = true
tokio.workspace = true
tracing.workspace = true
dirs.workspace = true
+2
View File
@@ -0,0 +1,2 @@
//! Bootstrap library — shared utilities for the bootstrap binary.
//! The main entry point is in `main.rs`.
+44
View File
@@ -0,0 +1,44 @@
//! Bootstrap binary — seeds initial system data idempotently.
//!
//! Creates default permissions, roles, and admin user if they don't
//! already exist. Run once after first deployment.
//!
//! Usage: cargo run --bin bootstrap
fn main() -> anyhow::Result<()> {
println!("Zesdex Bootstrap — seeding initial data...");
let store = zesdex_domain::core::Store::new();
store.ensure_dirs()?;
// Seed default settings if not present
let settings_path = store.base_dir.join("settings.json");
if !settings_path.exists() {
let settings = zesdex_domain::cms::Settings::default();
let content = serde_json::to_string_pretty(&settings)?;
let tmp = store.base_dir.join("settings.json.tmp");
std::fs::write(&tmp, &content)?;
std::fs::File::open(&tmp)?.sync_all()?;
std::fs::rename(&tmp, &settings_path)?;
println!(" ✓ Default settings created");
} else {
println!(" · Settings already exist, skipping");
}
// Seed default app config if not present
let config_path = store.base_dir.join("app_config.json");
if !config_path.exists() {
let config = zesdex_domain::cms::AppConfig::default();
let content = serde_json::to_string_pretty(&config)?;
let tmp = store.base_dir.join("app_config.json.tmp");
std::fs::write(&tmp, &content)?;
std::fs::File::open(&tmp)?.sync_all()?;
std::fs::rename(&tmp, &config_path)?;
println!(" ✓ Default app_config created");
} else {
println!(" · App config already exists, skipping");
}
println!("Bootstrap complete.");
Ok(())
}
+20
View File
@@ -0,0 +1,20 @@
[package]
name = "zesdex-domain"
version.workspace = true
edition.workspace = true
authors.workspace = true
# Domain layer — PURE entities, value objects, repository/service traits.
# Zero framework dependencies. Only serde for serialization, chrono for
# timestamps, uuid for identity.
[dependencies]
serde.workspace = true
serde_json.workspace = true
chrono.workspace = true
uuid.workspace = true
base64.workspace = true
sha2.workspace = true
url.workspace = true
libc.workspace = true
anyhow.workspace = true
tracing.workspace = true
+34
View File
@@ -0,0 +1,34 @@
//! Shared default constants used across the application.
//!
//! Centralising these values eliminates the hardcoded-string duplication
//! that existed when every call site provided its own inline fallback.
//! Consumers should reference these constants rather than repeating
//! the string literals.
/// Default LLM provider API base URL.
pub const DEFAULT_API_BASE: &str = "https://opencode.ai/zen/v1";
/// Default LLM model identifier.
pub const DEFAULT_MODEL: &str = "deepseek-v4-flash-free";
/// Fallback JWT secret used only when `JWT_SECRET` env var is unset.
/// In production this MUST be configured via environment variable.
pub const FALLBACK_JWT_SECRET: &str = "dev-secret";
/// Default context window size (128k tokens).
pub const DEFAULT_CONTEXT_WINDOW: usize = 256_000;
/// Maximum tool-call iterations per agent turn.
pub const MAX_TOOL_ITERATIONS: u32 = 50;
/// Maximum subagent tool-call iterations.
pub const MAX_SUBAGENT_ITERATIONS: u32 = 25;
/// Default LLM request max tokens.
pub const DEFAULT_MAX_TOKENS: u32 = 4096;
/// Default temperature for the main agent.
pub const DEFAULT_TEMPERATURE: f64 = 0.7;
/// Default temperature for compaction / summary calls.
pub const DEFAULT_COMPACT_TEMPERATURE: f64 = 0.3;
+260
View File
@@ -0,0 +1,260 @@
//! Domain types for agent lifecycle: turn events, session runtime, progress
//! reporting, prompts, and the agent-turn parameter bundle.
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use crate::core::{ChatMessage, ToolCallResult, UsageStats};
pub mod defaults;
pub mod progress;
pub mod prompt;
/// Which kind of caller (main agent vs. subagent vs. reviewer) is
/// invoking a tool, used to scope permissions and tag log/output paths.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum Origin {
/// The main agent turn loop.
Main,
/// A spawned subagent (test-gen, arch-review, security-review, etc.).
SubAgent,
/// The auto-inline review step after an edit.
Reviewer,
}
impl Origin {
/// Short string tag for this origin, used in filenames and logs.
pub fn tag(self) -> String {
match self {
Origin::Main => "main",
Origin::SubAgent => "subagent",
Origin::Reviewer => "reviewer",
}
.to_string()
}
}
/// Severity/category of a toast notification, used to pick its color.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ToastKind {
Info,
Success,
Warning,
Error,
Lesson,
}
/// A transient status message shown in the TUI, auto-dismissed after `lifetime_ms`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Toast {
pub kind: ToastKind,
pub message: String,
pub created_at: i64,
pub lifetime_ms: u64,
}
impl Toast {
/// Create a toast with a default 5-second lifetime, stamped with now.
pub fn new(kind: ToastKind, message: String) -> Self {
Toast {
kind,
message,
created_at: chrono::Utc::now().timestamp_millis(),
lifetime_ms: 5000,
}
}
/// Whether this toast's lifetime has elapsed as of `now_ms`.
pub fn expired(&self, now_ms: i64) -> bool {
let lifetime = self.lifetime_ms as i64;
now_ms - self.created_at > lifetime
}
}
/// Agent status for workflow engine progress tracking.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum AgentStatus {
Pending,
Running,
Completed,
Failed(String),
Cancelled,
}
impl std::fmt::Display for AgentStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AgentStatus::Pending => write!(f, "pending"),
AgentStatus::Running => write!(f, "running"),
AgentStatus::Completed => write!(f, "completed"),
AgentStatus::Failed(msg) => write!(f, "failed: {msg}"),
AgentStatus::Cancelled => write!(f, "cancelled"),
}
}
}
/// Events emitted onto the turn-event queue while an agent turn runs,
/// consumed by the event loop to update state and drive re-renders.
#[derive(Debug, Clone)]
pub enum TurnEvent {
AssistantMessage(ChatMessage),
ToolResult {
tool_call_id: String,
tool_name: String,
output: String,
is_error: bool,
path: Option<String>,
},
SystemNote {
kind: String,
message: String,
},
StreamStart,
StreamToken(String),
StreamReasoning(String),
StreamDone(ChatMessage),
Usage {
tokens_in: u64,
tokens_out: u64,
},
ReviewUsage {
tokens_in: u64,
tokens_out: u64,
},
Compacted(Vec<ChatMessage>),
Error(String),
Done,
WorkflowAgentUpdate {
agent_id: String,
agent_name: String,
status: AgentStatus,
},
TodoUpdate(String),
PlanUpdate(String),
/// Structured progress report from a subagent or workflow node,
/// carrying the current tool name and optional step counters.
AgentProgress(crate::agent::progress::AgentProgress),
}
/// How a pending tool call should be executed when the turn resumes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ExecutionModel {
Inline,
Deferred,
AsyncTokio,
}
/// A tool call awaiting execution, along with which execution model
/// (inline, deferred, async) it should run under.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PendingTool {
pub tool_name: String,
pub args: serde_json::Value,
pub execution_model: ExecutionModel,
}
/// Reference to a background bash job tracked in session state.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BashJobRef {
pub id: String,
pub command: String,
pub started_at: i64,
pub running: bool,
}
/// Tracks counts of learned patterns by outcome and lifecycle stage.
#[derive(Debug, Clone, Default)]
pub struct LessonStats {
/// Total number of lessons tracked.
pub total: u32,
/// User-initiated lessons.
pub user: u32,
/// Feedback-driven lessons.
pub feedback: u32,
/// Project-scoped lessons.
pub project: u32,
/// Reference-scoped lessons.
pub reference: u32,
/// Currently active lessons.
pub active: u32,
/// Stale (outdated) lessons.
pub stale: u32,
/// Contradicted lessons.
pub contradicted: u32,
/// Human-authored lessons.
pub human: u32,
/// Verified lessons.
pub verified: u32,
/// Unverified lessons.
pub unverified: u32,
}
/// Per-session runtime state: message history, pending tool queue,
/// background bash jobs, lesson/review counters.
#[derive(Debug, Clone)]
pub struct SessionRuntime {
pub messages: Vec<ChatMessage>,
pub tool_call_results: Vec<ToolCallResult>,
pub pending_tool_queue: Vec<PendingTool>,
pub bash_jobs: Vec<BashJobRef>,
pub subagent_queue: usize,
pub edit_count: u32,
pub consecutive_empty_reviews: u32,
pub session_start: i64,
/// Aggregated lesson statistics.
pub lessons: LessonStats,
pub review_count: u32,
pub session_dir: PathBuf,
pub usage: UsageStats,
pub hive_mind_converged: bool,
}
impl SessionRuntime {
pub fn new(session_dir: PathBuf) -> Self {
SessionRuntime {
messages: Vec::new(),
tool_call_results: Vec::new(),
pending_tool_queue: Vec::new(),
bash_jobs: Vec::new(),
subagent_queue: 0,
edit_count: 0,
consecutive_empty_reviews: 0,
session_start: chrono::Utc::now().timestamp_millis(),
lessons: LessonStats::default(),
review_count: 0,
session_dir,
usage: UsageStats::default(),
hive_mind_converged: false,
}
}
pub fn push_message(&mut self, msg: ChatMessage) {
self.messages.push(msg);
}
}
/// Simple ASCII progress display for a long-running operation.
#[derive(Debug, Clone)]
pub struct ProgressState {
pub current: u64,
pub total: u64,
pub message: String,
pub start_time: i64,
}
use std::collections::VecDeque;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex};
/// Owned parameters required to spawn and execute an agent turn.
pub struct AgentTurnParams {
pub messages: Vec<ChatMessage>,
pub session_dir: PathBuf,
pub workspace_roots: Vec<PathBuf>,
pub turn_events: Arc<Mutex<VecDeque<TurnEvent>>>,
pub in_flight: Arc<AtomicBool>,
pub abort: Arc<AtomicBool>,
pub api_key: String,
pub model: String,
pub api_base: Option<String>,
}
+81
View File
@@ -0,0 +1,81 @@
//! Progress reporting types for long-running agent and subagent operations.
//!
//! These types are emitted onto the turn-event queue to drive the TUI's
//! spinner, progress bar, and agent-status sidebar. They are pure domain
//! types with no I/O or framework dependency.
use crate::agent::AgentStatus;
/// Describes progress within a single subagent or workflow-node execution.
///
/// Emitted as a `TurnEvent::AgentProgress` so the UI can show which tool
/// the subagent is currently invoking, or which step it has reached.
#[derive(Debug, Clone)]
pub struct AgentProgress {
/// Unique identifier for this agent (e.g. `"Node-0-1"`, `"auto-review"`).
pub agent_id: String,
/// Human-readable display name shown in the TUI sidebar.
pub agent_name: String,
/// Current lifecycle status.
pub status: AgentStatus,
/// Optional description of the current tool or step being executed.
/// Set to `None` when the agent is not actively executing a tool.
pub current_tool: Option<String>,
/// Optional progress range: (completed_steps, total_steps).
/// When `None`, the agent shows an indeterminate spinner.
pub steps: Option<(u32, u32)>,
}
impl AgentProgress {
/// Mark this agent as running with an optional tool name.
pub fn running(
agent_id: impl Into<String>,
agent_name: impl Into<String>,
current_tool: Option<String>,
) -> Self {
AgentProgress {
agent_id: agent_id.into(),
agent_name: agent_name.into(),
status: AgentStatus::Running,
current_tool,
steps: None,
}
}
/// Mark this agent as pending (queued but not yet started).
pub fn pending(agent_id: impl Into<String>, agent_name: impl Into<String>) -> Self {
AgentProgress {
agent_id: agent_id.into(),
agent_name: agent_name.into(),
status: AgentStatus::Pending,
current_tool: None,
steps: None,
}
}
/// Mark this agent as completed successfully.
pub fn completed(agent_id: impl Into<String>, agent_name: impl Into<String>) -> Self {
AgentProgress {
agent_id: agent_id.into(),
agent_name: agent_name.into(),
status: AgentStatus::Completed,
current_tool: None,
steps: None,
}
}
/// Mark this agent as failed with an error message.
pub fn failed(
agent_id: impl Into<String>,
agent_name: impl Into<String>,
error: String,
) -> Self {
AgentProgress {
agent_id: agent_id.into(),
agent_name: agent_name.into(),
status: AgentStatus::Failed(error),
current_tool: None,
steps: None,
}
}
}
+143
View File
@@ -0,0 +1,143 @@
//! System prompts and directive templates for agent and subagent turns.
//!
//! Centralising all prompt text here keeps the core turn logic free of
//! hardcoded prose, making prompts easier to maintain, review, and localise.
//!
//! # Flow
//! The application layer's `AgentTurnServiceImpl` calls `main_agent_prompt()`
//! to construct the system message at the start of each turn. Subagent and
//! review prompts are provided by their respective modules.
/// Build the main-agent system prompt.
///
/// The prompt establishes the agent's identity as Zesdex, an AI coding
/// assistant, and defines the priority hierarchy that governs tool selection:
///
/// 1. **Workflow first** — `workflow_run` / `hive_mind` for complex tasks
/// 2. **Planning & TODOs** — `plan_enter` / `todowrite` for structural work
/// 3. **Reasoning** — `seq_think` for deep analysis
/// 4. **Tool execution** — direct tools for simple actions
pub fn main_agent_prompt() -> String {
"\
You are Zesdex, an AI coding assistant. You have access to various tools \
via native function calling to help the user.
TOKEN BUDGET — BE EFFICIENT:
- For simple/factual questions, answer directly. Do NOT call tools.
- For complex or unfamiliar code tasks, call `explore_codebase` ONCE at the \
start to locate relevant code, then work from that context.
- Keep tool usage minimal: prefer `grep`/`glob`/`read` for targeted lookups; \
avoid re-reading files you already have in context.
- Keep responses concise; do not repeat tool output verbatim.
CRITICAL DIRECTIVES & PRIORITY HIERARCHY:
1. WORKFLOW FIRST: For any multi-step, complex, or non-trivial task, \
you MUST prioritise using `workflow_run` (to construct and execute a \
multi-phase YAML workflow) or `hive_mind` (to orchestrate parallel \
autonomous agents). Workflows are your primary strategy.
2. PLANNING & TODOs: Use `plan_enter` to establish high-level \
architectural plans and `todowrite` to maintain granular task checklists.
3. REASONING: Use `seq_think` for deep step-by-step analysis.
4. TOOL EXECUTION: Execute individual tools (file edits, terminal commands) \
within or guided by your workflows. If an error occurs, analyse and fix it.
Respond conversationally, concisely, and helpfully."
.to_string()
}
/// Build a subagent directive prompt.
///
/// The directive is embedded in a system message that also communicates the
/// current working directory and workspace root so the subagent can resolve
/// paths correctly.
pub fn subagent_directive(directive: &str, cwd: &str, ws_root: &str) -> String {
format!(
"\
You are a focused subagent.
Current directory (PWD): {cwd}
Workspace root: {ws_root}
Your directive:
{directive}
Complete the directive autonomously using the tools available to you. \
Return your final answer when done."
)
}
/// Build a conversation-compaction prompt.
///
/// The LLM is asked to produce a concise bulleted summary of the key
/// requests, decisions, tools executed, and files modified.
pub fn compaction_prompt() -> String {
"\
You are a helpful assistant summarising conversation history. \
Provide a concise summary of the key user requests, decisions, tools \
executed, and modified files. Format as a clear bulleted list."
.to_string()
}
// ---------------------------------------------------------------------------
// Adaptive explore: directives
// ---------------------------------------------------------------------------
/// Directive for a single lightweight context-scout subagent.
pub fn explore_scout_directive() -> String {
"\
You are a codebase context scout. \
Given the workspace root, quickly locate the code that is most relevant \
to the user's request: \
1. Run semantic_search once with the user's key terms. \
2. Read up to the 3 most relevant files (use grep for symbols if needed). \
3. Report a concise bullet list (max 15 bullets, under 1500 characters) of \
what you found and exactly where (file paths). \
Do NOT rebuild the index. Do NOT enumerate unrelated files. Be brief."
.to_string()
}
/// Build a system note injected after repeated tool errors to steer the
/// agent toward an alternative approach instead of retrying the same call.
pub fn error_recovery_note(tool_name: &str, last_error: &str) -> String {
format!(
"\
[System note] The tool `{tool_name}` failed repeatedly with: \"{last_error}\". \
Try an alternative approach (verify paths, correct arguments, use a \
different tool, or finish without this tool). Do NOT retry the same call."
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn main_prompt_is_non_empty() {
let prompt = main_agent_prompt();
assert!(!prompt.is_empty());
assert!(prompt.contains("Zesdex"));
assert!(prompt.contains("WORKFLOW FIRST"));
}
#[test]
fn subagent_directive_includes_directive_text() {
let prompt = subagent_directive("test directive", "/home", "/home/project");
assert!(prompt.contains("test directive"));
assert!(prompt.contains("/home"));
assert!(prompt.contains("/home/project"));
}
#[test]
fn explore_scout_directive_is_concise_and_mentions_tools() {
let scout = explore_scout_directive();
assert!(scout.contains("scout"));
assert!(scout.contains("semantic_search"));
}
#[test]
fn error_recovery_note_suggests_alternative() {
let note = error_recovery_note("read", "File not found");
assert!(note.contains("read"));
assert!(note.contains("alternative"));
}
}
+30
View File
@@ -0,0 +1,30 @@
//! Command types for IAM domain operations.
//!
//! Following the `NewXxx` / command pattern from clean architecture,
//! these types encapsulate the input data for create/update operations
//! on domain entities. They decouple presentation DTOs from the entity
//! mutation surface and provide a clear boundary for validation.
/// Command to create a new session.
///
/// Carries only the data needed to construct a session entity — the
/// service generates the UUID and timestamp internally.
#[derive(Debug, Clone)]
pub struct NewSession {
/// Human-readable session title.
pub title: String,
}
impl From<String> for NewSession {
fn from(title: String) -> Self {
Self { title }
}
}
impl From<&str> for NewSession {
fn from(title: &str) -> Self {
Self {
title: title.to_string(),
}
}
}
+62
View File
@@ -0,0 +1,62 @@
//! Domain error types for the IAM (auth) module.
//!
//! Typed error enums replace `anyhow::Result` in domain traits and
//! application services, enabling callers to match on specific error
//! variants (e.g. `NotFound` vs `Conflict`) rather than string-checking.
//!
//! # Components
//!
//! - [`RepositoryError`] — persistence-layer errors (not found, conflict, I/O)
//! - [`ServiceError`] — use-case / orchestration errors (config, state
//! mismatch, provider failures)
use std::fmt;
use crate::error::DomainError;
/// Shared repository error type for IAM persistence operations.
pub type RepositoryError = DomainError;
/// Errors from service / use-case operations in the IAM domain.
#[derive(Debug)]
pub enum ServiceError {
/// A repository operation failed.
Repository(DomainError),
/// The provided configuration is invalid.
InvalidConfig(String),
/// OAuth state mismatch — possible CSRF attack.
StateMismatch,
/// The OAuth provider returned an error.
OAuthProvider(String),
/// A generic error with a message.
Other(String),
}
impl From<DomainError> for ServiceError {
fn from(err: DomainError) -> Self {
ServiceError::Repository(err)
}
}
impl fmt::Display for ServiceError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ServiceError::Repository(err) => write!(f, "repository error: {err}"),
ServiceError::InvalidConfig(msg) => write!(f, "invalid configuration: {msg}"),
ServiceError::StateMismatch => {
write!(f, "OAuth state mismatch — possible CSRF attack")
}
ServiceError::OAuthProvider(msg) => write!(f, "OAuth provider error: {msg}"),
ServiceError::Other(msg) => write!(f, "{msg}"),
}
}
}
impl std::error::Error for ServiceError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ServiceError::Repository(err) => Some(err),
_ => None,
}
}
}
+12
View File
@@ -0,0 +1,12 @@
//! IAM Session re-export.
//!
//! Re-exports `Session` from the auth module for consistent IAM-boundary
//! imports. Consumers of the IAM module import `Session` from here rather
//! than from the core session module directly, keeping the dependency
//! internal and allowing the IAM crate to own its domain vocabulary.
pub use super::session::Session;
/// Alias for `Session` used in IAM contexts to distinguish from other
/// session types in the system.
pub type IamSession = Session;
+36
View File
@@ -0,0 +1,36 @@
//! Authentication domain entities, commands, errors, and repository/service traits.
//!
//! Combines the session types from `zesdex-entities` (auth sub-module) with the
//! IAM domain types (commands, OAuth, repository/service traits) from `zesdex-iam`.
//!
//! # Sub-modules
//!
//! - [`session`] — `Session` entity (session metadata)
//! - [`session_id`] — `SessionId` value object (validated newtype)
//! - [`session_lock`] — `SessionLock` RAII guard (PID-file lock)
//! - [`oauth`] — `OAuthToken`, `OAuthConfig` entities
//! - [`iam_session`] — Re-export of `Session` for IAM-boundary consistency
//! - [`commands`] — `NewSession` command type
//! - [`error`] — `RepositoryError`, `ServiceError` types
//! - [`repository`] — `SessionRepository`, `SessionLockRepository`, `OAuthRepository`
//! - [`service`] — `SessionService`, `OAuthService` traits
pub mod commands;
pub mod error;
pub mod iam_session;
pub mod oauth;
pub mod repository;
pub mod service;
pub mod session;
pub mod session_id;
pub mod session_lock;
pub use commands::NewSession;
pub use error::{RepositoryError, ServiceError};
pub use iam_session::IamSession;
pub use oauth::{OAuthConfig, OAuthToken};
pub use repository::{OAuthRepository, SessionLockRepository, SessionRepository};
pub use service::{OAuthService, SessionService};
pub use session::Session;
pub use session_id::SessionId;
pub use session_lock::SessionLock;
+53
View File
@@ -0,0 +1,53 @@
//! Pure OAuth entities — no HTTP or persistence logic.
//!
//! # Components
//!
//! - [`OAuthToken`] — access token with optional refresh token, epoch expiry
//! - [`OAuthConfig`] — provider configuration (auth URL, token URL, client id,
//! optional client secret, scopes)
use serde::{Deserialize, Serialize};
/// An OAuth 2.0 access token with optional refresh token and absolute
/// expiry time (epoch seconds).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OAuthToken {
/// The OAuth 2.0 access token string.
pub access_token: String,
/// Optional refresh token for long-lived access.
pub refresh_token: Option<String>,
/// Absolute expiry timestamp (epoch seconds since UNIX_EPOCH).
pub expires_at: u64,
/// Token type, e.g. `"Bearer"`.
pub token_type: String,
}
/// Static configuration for an OAuth provider.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OAuthConfig {
/// Authorization endpoint URL.
pub auth_url: String,
/// Token exchange endpoint URL.
pub token_url: String,
/// OAuth client identifier.
pub client_id: String,
/// Optional client secret (not all flows require it).
pub client_secret: Option<String>,
/// Space-separated list of requested scopes.
pub scopes: Vec<String>,
}
impl Default for OAuthConfig {
fn default() -> Self {
OAuthConfig {
auth_url: String::new(),
token_url: String::new(),
client_id: String::new(),
client_secret: None,
scopes: vec![
"openid".to_string(),
"profile".to_string(),
"email".to_string(),
],
}
}
}
+57
View File
@@ -0,0 +1,57 @@
//! Repository trait definitions (pure — no impls, no concrete persistence).
//!
//! Defines the repository contracts that infrastructure adapters implement.
//! Following clean architecture, domain code depends only on these traits,
//! not on concrete persistence libraries.
//!
//! # Traits
//!
//! - [`SessionRepository`] — CRUD for session metadata
//! - [`SessionLockRepository`] — acquire/release/liveness for session locks
//! - [`OAuthRepository`] — persist/load OAuth tokens
use std::path::Path;
use crate::auth::error::RepositoryError;
use crate::auth::oauth::OAuthToken;
use crate::auth::session::Session;
use crate::auth::session_id::SessionId;
/// Repository for loading, saving, listing, and deleting sessions.
pub trait SessionRepository {
/// List all loadable sessions under `<base_dir>/sessions/`.
fn list_sessions(&self, base_dir: &Path) -> Result<Vec<Session>, RepositoryError>;
/// Load a single session by id.
fn load_session(&self, base_dir: &Path, id: &SessionId) -> Result<Session, RepositoryError>;
/// Save a session's metadata to disk.
fn save_session(&self, base_dir: &Path, session: &Session) -> Result<(), RepositoryError>;
/// Delete a session directory and all its contents.
fn delete_session(&self, base_dir: &Path, id: &SessionId) -> Result<(), RepositoryError>;
}
/// Repository for per-session PID-file advisory locks.
pub trait SessionLockRepository {
/// Try to acquire the lock for a session directory.
/// Returns `true` if the lock was acquired, `false` if another live
/// process holds it.
fn try_lock(&self, session_dir: &Path) -> Result<bool, RepositoryError>;
/// Release the lock by removing the lock file.
fn unlock(&self, session_dir: &Path) -> Result<(), RepositoryError>;
/// Check whether a process with the given PID is alive.
fn is_alive(&self, pid: u32) -> bool;
}
/// Repository for persisting and loading OAuth tokens.
pub trait OAuthRepository {
/// Persist an OAuth token to a JSON file.
fn save_token(&self, path: &Path, token: &OAuthToken) -> Result<(), RepositoryError>;
/// Load an OAuth token from a JSON file, returning `None` if the file
/// does not exist.
fn load_token(&self, path: &Path) -> Result<Option<OAuthToken>, RepositoryError>;
}
+56
View File
@@ -0,0 +1,56 @@
//! Service trait definitions — use-case interfaces for session management
//! and OAuth flows.
//!
//! These traits define the boundary between the application orchestration
//! layer and the domain. Implementations live in the application layer.
//!
//! # Traits
//!
//! - [`SessionService`] — create, list, archive sessions
//! - [`OAuthService`] — start PKCE flow, complete code exchange, retrieve token
use crate::auth::error::ServiceError;
use crate::auth::oauth::{OAuthConfig, OAuthToken};
use crate::auth::session::Session;
use crate::auth::session_id::SessionId;
/// Session management use-case boundary.
pub trait SessionService {
/// Create a new session with a generated UUID and the given title.
fn create_session(&self, title: &str) -> Result<Session, ServiceError>;
/// List all available sessions.
fn list_all(&self) -> Result<Vec<Session>, ServiceError>;
/// Archive a session by id (sets `archived = true`).
fn archive_session(&self, id: SessionId) -> Result<(), ServiceError>;
}
/// OAuth flow use-case boundary.
pub trait OAuthService {
/// Start an OAuth authorization-code + PKCE flow for the given
/// `redirect_uri` (the caller is responsible for actually listening on
/// it — e.g. a bound `LoopbackServer`). Returns `(auth_url, state)`:
/// the URL to send the user to, and the CSRF state token that must be
/// passed back into `complete_flow` unchanged.
fn start_flow(
&self,
config: &OAuthConfig,
redirect_uri: &str,
) -> Result<(String, String), ServiceError>;
/// Complete the OAuth flow: validates `state` against the value
/// persisted during `start_flow` (bailing on mismatch — this is the
/// CSRF check), then exchanges `code` for a token using the same
/// `redirect_uri` passed to `start_flow`.
fn complete_flow(
&self,
config: &OAuthConfig,
redirect_uri: &str,
code: &str,
state: &str,
) -> Result<OAuthToken, ServiceError>;
/// Retrieve the currently stored OAuth token (if any).
fn get_token(&self) -> Result<Option<OAuthToken>, ServiceError>;
}
+71
View File
@@ -0,0 +1,71 @@
//! Session metadata: id, title, workspace roots, and message/token counts,
//! persisted as `session.json` per session directory.
//!
//! # Flow
//!
//! Created via [`Session::new`] → mutated in-memory → persisted via repository.
//!
//! # Components
//!
//! - `Session` struct — fields for all session metadata
//! - `new` — timestamped constructor
//! - `session_dir` / `conversation_path` — pure path computation
use chrono::Utc;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
/// Metadata for one conversation session (distinct from the message
/// history itself, which lives in `Conversation`/the msglog).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Session {
/// Unique session identifier (validated against path traversal in `load`).
pub id: String,
/// Epoch-millis timestamp of creation (`Utc::now().timestamp_millis()`).
pub created_at: i64,
/// Epoch-millis timestamp of last update.
pub updated_at: i64,
/// Human-readable title for the conversation.
pub title: String,
/// Model identifier string, e.g. `"anthropic/claude-opus-4-8"`.
pub model: String,
/// Workspace root directories associated with this session.
pub workspace_roots: Vec<PathBuf>,
/// Running count of messages in the conversation.
pub message_count: u32,
/// Running count of tokens consumed.
pub token_count: u32,
/// Soft-delete flag — archived sessions are hidden from the default list.
pub archived: bool,
/// Optional AI-generated conversation summary (used for compact context).
pub summary: Option<String>,
}
impl Session {
/// Create a new session with the given id/title, defaulting the
/// model, workspace root (current dir), and counters.
pub fn new(id: String, title: String) -> Self {
let now = Utc::now().timestamp_millis();
Session {
id,
created_at: now,
updated_at: now,
title,
model: "anthropic/claude-opus-4-8".to_string(),
workspace_roots: vec![std::env::current_dir().unwrap_or_default()],
message_count: 0,
token_count: 0,
archived: false,
summary: None,
}
}
/// Compute this session's directory under `<base_dir>/sessions/<id>`.
pub fn session_dir(&self, base_dir: &Path) -> PathBuf {
base_dir.join("sessions").join(&self.id)
}
/// Compute this session's `conversation.json` path.
pub fn conversation_path(&self, base_dir: &Path) -> PathBuf {
self.session_dir(base_dir).join("conversation.json")
}
}
+106
View File
@@ -0,0 +1,106 @@
//! Validated session identifier newtype.
//!
//! [`SessionId`] wraps a `String` that has been checked for path-traversal
//! characters. Construction via `SessionId::new(str)` validates the input
//! once; the guarantee is then enforced by the type system for all
//! downstream use.
//!
//! # Validation rules
//!
//! - Must not be empty
//! - Must only contain alphanumeric characters, hyphens, and underscores
use serde::{Deserialize, Serialize};
use std::fmt;
use std::path::Path;
use std::path::PathBuf;
/// A validated session identifier.
///
/// Guarantees the inner string is non-empty and contains no path-traversal
/// characters (`/`, `\\`, `..`) or other unsafe delimiters.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct SessionId(String);
impl SessionId {
/// Validate and construct a `SessionId`.
///
/// Returns `Err(msg)` if the input contains path separators, `..`, or
/// is empty.
pub fn new(id: &str) -> Result<Self, String> {
if id.is_empty() {
return Err("session id must not be empty".to_string());
}
if id.contains('/') || id.contains('\\') || id.contains("..") {
return Err(format!(
"session id '{id}' must not contain path separators"
));
}
Ok(SessionId(id.to_string()))
}
/// Return the underlying string.
pub fn as_str(&self) -> &str {
&self.0
}
/// Return the underlying owned string.
pub fn into_string(self) -> String {
self.0
}
/// Append this session id as a component of `base_dir`, yielding
/// `base_dir / self.0`.
///
/// Safe because the id has been validated to contain no path separators.
pub fn join_to(&self, base_dir: &Path) -> PathBuf {
base_dir.join(&self.0)
}
}
impl AsRef<str> for SessionId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for SessionId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl From<SessionId> for String {
fn from(sid: SessionId) -> Self {
sid.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_valid_uuids() {
assert!(SessionId::new("550e8400-e29b-41d4-a716-446655440000").is_ok());
assert!(SessionId::new("my-session_123").is_ok());
}
#[test]
fn test_rejects_path_traversal() {
assert!(SessionId::new("../etc/passwd").is_err());
assert!(SessionId::new("foo/../../bar").is_err());
assert!(SessionId::new("foo\\..\\bar").is_err());
}
#[test]
fn test_rejects_empty() {
assert!(SessionId::new("").is_err());
}
#[test]
fn test_into_string() {
let sid = SessionId::new("abc-123").unwrap();
assert_eq!(sid.into_string(), "abc-123");
}
}
+170
View File
@@ -0,0 +1,170 @@
//! PID-file based advisory lock preventing two processes from operating on
//! the same session directory concurrently.
//!
//! # Flow
//!
//! [`SessionLock::new`] creates a handle → [`SessionLock::try_lock`] attempts
//! atomic `O_CREAT|O_EXCL` creation. If the lock file already exists, the
//! owning PID is checked via liveness verification. Stale locks are
//! overwritten atomically (temp-file + rename + fsync). On [`Drop`],
//! the lock file is removed automatically.
//!
//! # Components
//!
//! - `SessionLock` — RAII guard wrapping a lock file path and PID
//! - `try_lock` — three-phase atomic acquire with stale-lock recovery
//! - `unlock` / `Drop` — explicit and implicit release
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
use tracing;
/// A PID-file lock (`<session_dir>/.lock`) tied to the current process,
/// auto-removed on drop.
#[derive(Debug)]
pub struct SessionLock {
/// Path to the `.lock` file inside the session directory.
pub(crate) path: PathBuf,
/// Process ID that holds (or will hold) this lock.
pub(crate) pid: u32,
}
impl SessionLock {
/// Construct a lock handle for a session directory (does not acquire
/// the lock yet — call `try_lock`).
pub fn new(session_dir: &Path) -> Self {
SessionLock {
path: session_dir.join(".lock"),
pid: std::process::id(),
}
}
/// Attempt to acquire the session lock using an atomic file creation.
///
/// Flow: try `O_CREAT | O_EXCL` via `create_new(true)` → if that
/// succeeds, the lock is ours — write our PID and return ok. If the
/// file already exists, read the PID inside it and check whether that
/// PID is still alive: if the process is still running, fail to acquire;
/// otherwise the lock is stale — overwrite it with our own PID and succeed.
///
/// Return: `Ok(true)` if acquired, `Ok(false)` if another live
/// process holds it, `Err` on I/O failure.
pub fn try_lock(&self) -> std::io::Result<bool> {
// Phase 1: try atomic create. If it succeeds, the lock is ours.
match fs::OpenOptions::new()
.create_new(true)
.write(true)
.open(&self.path)
{
Ok(mut file) => {
write!(file, "{}", self.pid)?;
file.sync_all()?;
tracing::debug!(path = %self.path.display(), pid = self.pid, "session lock acquired");
return Ok(true);
}
Err(ref e) if e.kind() == std::io::ErrorKind::AlreadyExists => {
tracing::debug!(path = %self.path.display(), "session lock already exists, checking staleness");
// Lock file exists — check if it's stale.
}
Err(e) => return Err(e),
}
// Phase 2: lock file exists — check liveness of the owning process.
let content = fs::read_to_string(&self.path).unwrap_or_default();
if let Ok(pid) = content.trim().parse::<u32>() {
if Self::is_alive(pid) {
tracing::warn!(stale = pid, path = %self.path.display(), "session lock held by live process");
return Ok(false);
}
tracing::debug!(stale = pid, "stale lock detected, overwriting");
}
// Phase 3: stale lock — overwrite it atomically (best-effort).
// Use a temp file + rename to avoid partial writes corrupting the lock.
let tmp = self.path.with_extension("lock.tmp");
{
let mut tmp_file = fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(&tmp)?;
write!(tmp_file, "{}", self.pid)?;
tmp_file.sync_all()?;
}
fs::rename(&tmp, &self.path)?;
// Sync the parent directory so the rename survives a crash.
if let Some(parent) = self.path.parent() {
let _ = fs::File::open(parent).and_then(|d| d.sync_all());
}
Ok(true)
}
/// Explicitly release the lock by removing the lock file.
pub fn unlock(&self) {
let _ = fs::remove_file(&self.path);
}
/// Check whether a process with the given PID is currently alive and
/// belongs to the same binary (mitigating PID-reuse races).
///
/// Strategy (Unix):
/// 1. Resolve `/proc/<pid>/exe` — if it doesn't match our own binary,
/// the PID either belongs to another process or is reused — return false.
/// 2. Send `kill(pid, 0)` to verify the process is still alive.
/// 3. Re-check `/proc/<pid>/exe` to close the TOCTOU window between
/// step 1 and step 2 (PID reuse after exe check, before kill).
///
/// On non-Unix platforms this always returns `true` (conservative).
fn is_alive(pid: u32) -> bool {
#[cfg(unix)]
{
// Resolve our own executable path once.
let self_exe = match std::fs::read_link("/proc/self/exe") {
Ok(exe) => exe,
Err(_) => return false,
};
let pid_signed: i32 = match pid.try_into() {
Ok(p) => p,
Err(_) => return false,
};
let proc_exe = std::path::PathBuf::from(format!("/proc/{pid}/exe"));
// Phase 1: read /proc/<pid>/exe and compare with self_exe.
let target = match std::fs::read_link(&proc_exe) {
Ok(t) => t,
Err(_) => return false,
};
if target != self_exe {
return false;
}
// Phase 2: verify the process is still alive.
// SAFETY: `libc::kill(pid, 0)` does not send a signal; it only checks
// whether the process exists and the caller has permission to signal it.
if unsafe { libc::kill(pid_signed, 0) != 0 } {
return false;
}
// Phase 3: re-check /proc/<pid>/exe to detect PID reuse between
// Phase 1 and Phase 2.
matches!(std::fs::read_link(&proc_exe), Ok(recheck) if recheck == self_exe)
}
#[cfg(not(unix))]
{
// Fallback: always assume alive (conservative).
let _ = pid;
true
}
}
}
impl Drop for SessionLock {
/// Release the lock automatically when the guard goes out of scope,
/// so an ungracefully-exited process doesn't leave a dangling lock.
fn drop(&mut self) {
let _ = fs::remove_file(&self.path);
}
}
+127
View File
@@ -0,0 +1,127 @@
//! Pure domain entity for application configuration.
//!
//! Defines `AppConfig`, `ProviderConfig`, and `ModelRole` — the data
//! structures that describe which LLM providers are registered, which
//! model roles exist, and which provider/model is the default.
//!
//! # Architecture
//! These are pure data structures with **no I/O logic**. Load/save
//! responsibilities live in `AppConfigRepository` (domain::repository).
//!
//! ## Data Flow
//! 1. `AppConfig` is deserialised from `app_config.json` at startup
//! 2. The HTTP handler layer calls `SettingsService::update_provider()`
//! to mutate the provider map
//! 3. The modified `AppConfig` is serialised back to `app_config.json`
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
/// Top-level application configuration.
///
/// Holds the registry of configured LLM providers, named model roles
/// (logical profiles mapping to a provider+model pair), and the default
/// provider/model selection.
///
/// ## Fields
/// - `providers` — map of provider name → connection details
/// - `model_roles` — map of role name → provider/model/temperature
/// - `default_provider` — the provider to use when none is specified
/// - `default_model` — the model to use when none is specified
/// - `default_context_window` — fallback context window size in tokens
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
pub providers: HashMap<String, ProviderConfig>,
pub model_roles: HashMap<String, ModelRole>,
pub default_provider: String,
pub default_model: String,
pub default_context_window: u32,
}
/// Connection details for a single LLM provider endpoint.
///
/// ## Fields
/// - `api_base` — base URL for the provider API
/// - `api_key_env` — optional environment variable name holding the API key
/// - `default_model` — optional default model name for this provider
/// - `default_api_key` — optional inline API key (less secure than env var)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProviderConfig {
pub api_base: String,
pub api_key_env: Option<String>,
pub default_model: Option<String>,
pub default_api_key: Option<String>,
}
/// A named model role mapping to a specific provider/model with parameters.
///
/// Roles allow the UI to present logical profiles (e.g. "fast", "reasoning")
/// that abstract over concrete provider+model strings.
///
/// ## Fields
/// - `provider` — which provider serves this role
/// - `model` — which model to use for this role
/// - `max_tokens` — optional maximum output token limit
/// - `context_window` — optional context window override
/// - `temperature` — optional generation temperature
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelRole {
pub provider: String,
pub model: String,
pub max_tokens: Option<u32>,
pub context_window: Option<u32>,
pub temperature: Option<f32>,
}
/// Returns the default AppConfig with built-in "zen" and "router" providers.
impl Default for AppConfig {
/// Construct an AppConfig with the default "zen" and "router" providers.
///
/// ## Defaults
/// - Zen provider: `deepseek-v4-flash-free` model
/// - Router provider: `claude-opus-5` model
/// - Default role: "default" → zen / deepseek-v4-flash-free, temp 0.7
/// - `default_context_window`: 256,000 tokens
fn default() -> Self {
let mut providers = HashMap::new();
providers.insert(
"zen".to_string(),
ProviderConfig {
api_base: "https://opencode.ai/zen/v1".to_string(),
api_key_env: Some("API_KEY".to_string()),
default_model: Some("deepseek-v4-flash-free".to_string()),
default_api_key: None,
},
);
providers.insert(
"router".to_string(),
ProviderConfig {
api_base: "https://9router.asepharyana.my.id/v1".to_string(),
api_key_env: Some("ROUTER_API_KEY".to_string()),
default_model: Some("claude-opus-5".to_string()),
default_api_key: None,
},
);
let mut model_roles = HashMap::new();
model_roles.insert(
"default".to_string(),
ModelRole {
provider: "zen".to_string(),
model: "deepseek-v4-flash-free".to_string(),
max_tokens: None,
context_window: None,
temperature: Some(0.7),
},
);
Self {
providers,
model_roles,
default_provider: "zen".to_string(),
default_model: "deepseek-v4-flash-free".to_string(),
default_context_window: 256_000,
}
}
}

Some files were not shown because too many files have changed in this diff Show More