@kodax-ai/kodax 0.7.40 → 0.7.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/chunks/{chunk-NDNILSTR.js → chunk-5TFLMGER.js} +1 -1
  3. package/dist/chunks/{chunk-FAVPT4P7.js → chunk-6OB4AJOM.js} +1 -1
  4. package/dist/chunks/chunk-HYWVRTFA.js +1233 -0
  5. package/dist/chunks/chunk-SX2IS5JP.js +16 -0
  6. package/dist/chunks/chunk-ZPJPNLBK.js +462 -0
  7. package/dist/chunks/{compaction-config-A7XZ6H5Y.js → compaction-config-LT5PEXPT.js} +1 -1
  8. package/dist/chunks/{construction-bootstrap-OFPUZTXQ.js → construction-bootstrap-HBCWJFHC.js} +1 -1
  9. package/dist/chunks/dist-V3BS2NKB.js +2 -0
  10. package/dist/chunks/{utils-DFMYJUTE.js → utils-FAFUQJ2A.js} +1 -1
  11. package/dist/index.d.ts +232 -7
  12. package/dist/index.js +2 -2
  13. package/dist/kodax_cli.js +922 -912
  14. package/dist/sdk-agent.d.ts +1459 -10
  15. package/dist/sdk-agent.js +1 -1
  16. package/dist/sdk-coding.d.ts +4543 -14
  17. package/dist/sdk-coding.js +1 -1
  18. package/dist/sdk-llm.d.ts +209 -10
  19. package/dist/sdk-repl.d.ts +2694 -13
  20. package/dist/sdk-repl.js +1 -1
  21. package/dist/sdk-skills.d.ts +487 -11
  22. package/dist/types-chunks/bash-prefix-extractor.d-B2iliwdi.d.ts +2432 -0
  23. package/dist/types-chunks/capability.d-BxNgd1-c.d.ts +368 -0
  24. package/dist/types-chunks/cost-tracker.d-C4dMlQuV.d.ts +342 -0
  25. package/dist/types-chunks/history-cleanup.d-q1vAvCss.d.ts +1266 -0
  26. package/dist/types-chunks/instance-discovery.d-DZhp77vb.d.ts +1217 -0
  27. package/dist/types-chunks/resolver.d-BwD6TKz7.d.ts +262 -0
  28. package/dist/types-chunks/storage.d-Bv9T99Qu.d.ts +584 -0
  29. package/dist/types-chunks/types.d-C5mHR87z.d.ts +119 -0
  30. package/package.json +8 -3
  31. package/dist/acp_events.d.ts +0 -109
  32. package/dist/acp_logger.d.ts +0 -20
  33. package/dist/acp_server.d.ts +0 -92
  34. package/dist/chunks/chunk-CLS57NPX.js +0 -460
  35. package/dist/chunks/chunk-QZEDWITG.js +0 -1226
  36. package/dist/chunks/chunk-Z5EBDA6R.js +0 -15
  37. package/dist/chunks/dist-OTUF22DA.js +0 -2
  38. package/dist/cli_commands.d.ts +0 -17
  39. package/dist/cli_option_helpers.d.ts +0 -49
  40. package/dist/cli_option_helpers.test.d.ts +0 -1
  41. package/dist/constructed_cli.d.ts +0 -82
  42. package/dist/constructed_cli.test.d.ts +0 -1
  43. package/dist/kodax_cli.d.ts +0 -7
  44. package/dist/self_modify_cli.d.ts +0 -81
  45. package/dist/self_modify_cli.test.d.ts +0 -9
  46. package/dist/skill_cli.d.ts +0 -15
  47. package/dist/skill_cli.test.d.ts +0 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,63 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  > Full history for versions prior to v0.7.0: [CHANGELOG_ARCHIVE.md](docs/CHANGELOG_ARCHIVE.md)
6
6
 
7
+ ## [0.7.41] - 2026-05-19
8
+
9
+ ### Theme
10
+
11
+ **KodaX Team Mode + AMA Reliability + Source-Tree Modularization + REPL Render & TTFB Perf** — The release lands a third-axis differentiator (multi-instance auto coordination) alongside three AMA-path reliability fixes (mid-turn inject, pending-children handoff gate, post-handoff label flip, terminal-verdict fallback), the Todo V2 per-task CRUD migration with extension hooks, and the largest source-tree refactor since v0.7.25 (`runner-driven.ts` 6406 → 1897 lines, -70.4%, byte-identical). FEATURE_125 KodaX Team Mode is the headline: zero-cognitive-load multi-session awareness (no `/team create`, no `team_id`) — each KodaX instance writes per-pid state to `<configHome>/instances/<pid>/`, every LLM round injects a sibling-snapshot block into all 5 managed roles' system prompts (Scout / Planner / Generator / Evaluator / Worker), and a runtime content-hash safety net catches the only genuine data-race surface (concurrent overwrite of a file another session already read). The LLM-First design contrasts with claude code Team Mode's mode-based 4-stage workflow and no-conflict-resolution semantics. FEATURE_167 closes a structural `signal:'COMPLETE'` false-positive on V2 Evaluator turns (3-layer probe-gated defense: B0 parser SKIP / B1 retry cap / B2 synthesized verdict accept). FEATURE_165 + 166 land together as a Worker→Evaluator handoff hardening pair — runtime gate blocks `emit_handoff` while child registry is non-empty (covers V1+V2 shared `handoffEmit` path), and the REPL surface flips role labels immediately on `agentSwitched` (was lagged a turn). FEATURE_170 migrates the todo subsystem from monolithic init/replace to per-task add/patch/remove with extension events + hooks + new `todo_create` tool; Layer 2 LLM-judge eval (Layer A + Layer B 3.2% disagreement → DATA VALID) clears gate (a)+(b) MET, (c) saturation-artifact noted. FEATURE_171 extracts 12 submodules from `runner-driven.ts` across R1–R4 — zero behavior change, 4 reviewer APPROVE rounds, 4314/4314 tests pass each commit, ADR-026 + HLD §3.5.1 documented.
12
+
13
+ ### Added
14
+
15
+ - **FEATURE_125 — KodaX Team Mode (Multi-Instance Auto Coordination)**. 11 commits S1–S7 + W1–W4 (`acef3c5e` → `9225ad31` → S7 `e2916675` + `e6bc5d7b` audit) + release-prep wiring `0cfc8bc4`. KodaX 自创的多 session 自动协调机制:用户**零认知负担**(无 `/team create`、无 `team_id` 概念),KodaX 自动感知本机其他 KodaX session 状态,把状态注入 LLM system prompt 让 LLM 自决避让/协作/调度;runtime 仅在 race condition 物理边界(content hash mismatch)兜底,不强制 lock、不强制等待。这是与 claude code Team Mode(mode-based 4-stage workflow + 完全无 conflict resolution)的核心差异化。**5 layers**: (S1) per-instance state writer at `<configHome>/instances/<pid>/{state.json,meta.json,heartbeat}` with atomic writes + 1s heartbeat + register/refresh/shutdown lifecycle; (S2) sibling-instance discovery + stale detection + reap with `PersistedSessionState v1` version guard + per-instance failure isolation; (S3) pure system-prompt formatter for the `=== Other active KodaX sessions ===` block (LLM-First wording, truncation, no behavior dictation); (S4) `KodaXToolExecutionContext.contentHashCache?` sha256-based stale-write detection with `recordRead` / `checkStale` / `recordWrite` per-task lifetime; (S5) tool-time soft-warning formatter for exact-path overlap match (no blocking, just an informational banner). **Wiring** (W1–W4): Read tool records sha256 on every successful read up to 5 MB (size cap so huge files don't pay the hash cost); Edit / Write / MultiEdit pre-mutation `checkStale` block + post-mutation `recordWrite` + sibling-overlap warning banner via `ctx.siblingSnapshot`; REPL bootstrap helper `bootstrapTeamMode()` with process-level singleton + `/exit` + SIGTERM lifecycle hooks (mirror wiring landed for both `runInteractiveMode` legacy path AND `runInkInteractiveMode` Ink REPL path — the latter was the release-blocker fix in commit `0cfc8bc4`); runner-driven adapter does per-LLM-round sibling discovery, injects `teamModeSection` into all 5 managed roles' system prompts (Scout / Planner / Generator / Evaluator / Worker) via a mutable `siblingSnapshot` ref + `Object.defineProperty` getter so tool ctx always reads the freshest snapshot. **S7 Layer 2 panel + audit**: `tests/feature-125-team-mode-awareness.eval.ts` + `benchmark/datasets/feature-125-team-mode-awareness/cases.ts`; 5 aliases × 2 cases × 5 runs = 50 LLM calls; **SHIP** per pre-registered matrix after audit-corrected regex extension (`buildToolNamePatterns` expanded from 4 to 9 syntax variants to capture kimi `read:0>{...}` and zhipu `<tool_name>read</tool_name>` forms). Layer A + Layer B audit-corrected primary verdict: case 1 84% / case 2 60% overall (4/5 aliases ≥60% — kimi case 2 narrate-without-tool documented as `feedback_model_structural_floor_not_prompt_tunable`; not addressable via prompt iteration). Design doc: [docs/features/v0.7.41.md#feature_125-kodax-team-mode--multi-instance-auto-coordination](docs/features/v0.7.41.md#feature_125-kodax-team-mode--multi-instance-auto-coordination). Test guide: `docs/test-guides/FEATURE_125_v0.7.41_TEST_GUIDE.md`.
16
+ - **FEATURE_165 — Worker `emit_handoff` pending-children gate**. Commit `0ebeb15f`. Runtime gate at `runner-driven.ts:2402` blocks `emit_handoff` when the child registry is non-empty (covers both V1 and V2's shared `handoffEmit` path). 9 unit tests + 1 integration test pin the gate semantics across both paths. **Prompt addition PARTIAL/dropped**: Layer 2 probe (250 calls × 5 aliases) showed negative-case D/E already 100% on the baseline (`Δ=0pp`), so the pre-registered SHIP condition (2) failed mathematically; the runtime gate is the production-load-bearing change. Probe also confirmed zhipu intent-vs-action floor reproduces in canned-history sessions (structural, not context-length-driven). Design doc: [docs/features/v0.7.41.md#feature_165--worker-emit_handoff-pending-children-gatev0741-hotfix](docs/features/v0.7.41.md#feature_165--worker-emit_handoff-pending-children-gatev0741-hotfix).
17
+ - **FEATURE_166 — Post-handoff role label flip**. Commit `0ebeb15f`. New `onAgentSwitched` hook on agent-runtime + `ObserverBridge.agentSwitched(role)` on coding-side. Fixes the V2 Worker→Evaluator handoff label-lag (`[Worker]` would persist on the next Evaluator turn until the assistant produced output). Production session `20260515_185354` gave a directly reproducible verdict trace. 7 unit tests + 1 pre-existing test corrected. Same session also surfaced FEATURE_167 (Evaluator text-only termination leaves `recorder.verdict === undefined`, V2 runner-driven never wired the `parseManagedTaskVerdictDirectiveFromJson` fallback — landed in FEATURE_167 below). Design doc: [docs/features/v0.7.41.md#feature_166--post-handoff-role-label-flipshipped](docs/features/v0.7.41.md#feature_166--post-handoff-role-label-flipshipped).
18
+ - **FEATURE_167 — Evaluator terminal-verdict fallback (B0 parser + B1 retry + B2 synthesized accept)**. Commit `d537c784` 2026-05-15. Three-layer probe-gated defense closes the structural `signal:'COMPLETE'` false-positive on V2 Evaluator turns where the model exits text-only without calling `emit_verdict` and `recorder.verdict` therefore stays `undefined`. **Layer B0** — parser SKIP path (regex+JSON parse on the assistant's terminal text looking for `{"signal":"COMPLETE","grade":...}` directives); **Layer B1** — retry gate with per-alias cap (default 2, zhipu cap 1 to avoid amplifying the intent-vs-action floor — see `project_zhipu_send_message_floor` memory); **Layer B2** — synthesized verdict accept (fabricates a `{signal:'NEEDS_REVISION', grade:'C', summary:'…inferred from terminal text…'}` envelope so the V2 task engine can complete instead of hanging on the missing verdict). Reviewer-suggested change "include `revise` in the gate" was rejected — correct invariant is `recorder.verdict` object identity comparison (NOT status comparison), otherwise a stale `revise` from a prior turn would falsely satisfy the gate. 29 tests (16 retry-config + 9 predicate + 4 integration); audit panel 0/75 disagreement → DATA VALID. Design doc: [docs/features/v0.7.41.md#feature_167--evaluator-terminal-verdict-兜底shipped](docs/features/v0.7.41.md#feature_167--evaluator-terminal-verdict-兜底shipped).
19
+ - **FEATURE_170 — Todo V2 Migration (per-task CRUD + extension hooks + `todo_create` tool)**. C1–C6 across 8 commits (`e45ddaa8` → `20e02103`). Replaces v0.7.x's monolithic init/replace todo-store API with per-task `add` / `patch` / `remove` operations + monotonic counter + metadata + extension events (`todo:added` / `todo:patched` / `todo:removed` / `todo:before-complete`) + before-complete hook for downstream consumers. New `todo_create` tool added to the registry + role wiring + throttle reset. Worker / legacy / throttle prompts updated to teach the per-item API (C5) with activeForm parity fix (C5 follow-up). **Layer 2 LLM-judge eval (Layer A + Layer B)**: 250-call panel + Layer A 5-sub-agent self-judge + Layer B 3-judge majority (750 calls), Layer B 3.2% disagreement → DATA VALID; gate (a)+(b) MET; gate (c) FAIL as a **pre-registered SHIP gate saturation artifact** (C2 baseline 96% / C3 100% — mathematically unable to add +20pp from a near-saturated baseline). C1 +32pp / mmx 0→100% are direct prompt-cause evidence — SHIP, keep the prompt rewrite. Lessons captured in two new memory entries: `feedback_pre_registered_gate_saturation` (pilot for baseline ceiling before deferring on Δ ≥+N pp) and `feedback_simplifying_prompt_can_regress` (Prefer over X when Y comparative clauses are load-bearing). Design doc: [docs/features/v0.7.41.md#feature_170--todo-v2-migration-per-task-crud--extension-hookssshipped-2026-05-16](docs/features/v0.7.41.md#feature_170--todo-v2-migration-per-task-crud--extension-hookssshipped-2026-05-16).
20
+ - **FEATURE_164 — Mid-turn user-input injection** (shipped as part of commit `0ebeb15f`, the FEATURE_164+165+166 triple). Closes the gap where a user prompt typed during an active LLM round was queued but only delivered as a synthetic `[user]` banner on the next idle-yield wake — semantically incorrect for the user's intent ("inject as if I'd typed it mid-turn"). Now the runner-driven adapter checks the `MessageQueue` snapshot before each LLM call and prepends any queued real-user messages as proper non-synthetic user-bubble messages within the same round.
21
+
22
+ ### Fixed
23
+
24
+ - **FEATURE_125 W3 — Ink REPL Team Mode bootstrap wiring** (release-blocker fix). Commit `0cfc8bc4`. Discovered during v0.7.41 release prep audit: FEATURE_125 W3 (commit `1a073ecc`) wired `bootstrapTeamMode` into the legacy `runInteractiveMode` path but never into `runInkInteractiveMode`, so the Ink REPL (the default REPL path on all platforms since v0.7.25) ran with Team Mode dormant — `<configHome>/instances/<pid>/` was never created, no heartbeat thread started, sibling discovery returned empty, and the system-prompt `teamModeSection` was a no-op for every Ink-launched session. Mirror-wires the bootstrap + `process.on('exit')` + `process.on('SIGTERM')` + clean-exit cleanup into `runInkInteractiveMode` at the same insertion point (after `gitRoot` resolution, before render). 37 lines net.
25
+ - **Issue 132 — h2-boundary `session.jsonl` ENOENT race**. Commit `bf3006fb`. Eager-read in `agent-task-runner` resolves the timing window where benchmark h2-boundary cases would call `tail -f session.jsonl` before the file existed on disk; pre-reads on task start instead of awaiting the first append.
26
+ - **FEATURE_166 stale-test correction** (1 pre-existing test): `agent-runtime.test.ts` had been asserting the buggy label-lag behavior as-correct — corrected to pin the fixed semantics so future regressions surface immediately.
27
+ - **FEATURE_171 build break + decl emit** (covered transitively by the R1–R4 chain test-pass discipline): every refactor commit ran `tsc -b tsconfig.build.json` + 4314 tests green; no stage shipped a partial transform.
28
+ - **Bundle SDK `.d.ts` so consumer `tsc` resolves types** (commit `af623000`). Footgun caught at the SDK consumer surface: tarball shipped `dist/index.js` + subpath bundles but no matching `.d.ts`, so `import { runKodaX } from '@kodax-ai/kodax'` worked at runtime while consumer `tsc` reported missing types. Build pipeline now layers `tsc --emitDeclarationOnly` on top of the esbuild bundle so every published subpath ships real types.
29
+ - **`KODAX_RENDER_TRACE` default path uses `os.tmpdir()` not `homedir()`** (commit `54a59caa`). Phase A.0 review follow-up — `homedir()` pollutes the user's home with per-pid trace files; `os.tmpdir()` is the conventional location for ephemeral diagnostic output and gets cleaned up by the OS.
30
+
31
+ ### Performance
32
+
33
+ - **FEATURE_172 — REPL Render Path Optimization (Phase 1 + Phase A.0/A.1)**. Triggered by user SSH long-session (`kodax -c` with 200+ history items) reporting "every 2-3s a frame refresh" during streaming. Two-phase work, with a mid-feature scope correction.
34
+ - **Phase 1 (data layer)** — 5 commits `19c6aff3` → `26d47084`. Split `transcript-layout.ts` into pure static/dynamic helpers (`buildTranscriptStaticPortion` / `buildTranscriptDynamicPortion` / `composeTranscriptRenderModel`); split `promptMainScreenRenderModel` + `transcriptMainScreenRenderModel` `useMemo` into static + dynamic with a static-cache-key invariant (streaming-state changes no longer invalidate the static portion); added `React.memo` `areTranscriptRowPropsEqual` comparator on `TranscriptRowRenderer`. **Data-layer bench** (`baseline-26d47084.json`, 800 items): streaming-tick p95 94.18ms → 0.52ms (-99.4%).
35
+ - **Phase 1 scope correction (2026-05-19)** — Phase 1 ship review with 3 parallel Explore-agent traces + claudecode end-to-end pipeline comparison revealed the data-layer bench (`benchmark/perf/repl-render-perf.bench.ts`) only measured `buildTranscriptRenderModel` inner function (~3-5% of total per-frame cost). The real ~80% lives in `tui/substrate/ink/` rendering substrate: `renderNodeToOutput` full-tree recursion (~55%), `setCellAt` `cells.slice()` O(N²) (~12%), `Output.getGrid()` rebuild (~12%), `diffEach` full-screen walk (~10%), `markDirty` propagation gap (~5%). **Lesson** captured to feedback memory: bench must measure end-to-end wall-time, not isolated inner functions; static analysis of a hot loop can miss the actual cost center.
36
+ - **Phase A.0 — `KODAX_RENDER_TRACE` env-gated per-frame trace + end-to-end bench scaffold** (commits `5ca91970` + `54a59caa` + `dae85141` + `99e7f2af`). Env-gated trace writes one `frame=N renderTime=X bytes_per_frame=Y writes=Z` line per render to `<tmpdir>/kodax-render-trace-<pid>.log`; bench scaffold parametrizes viewport at the user's real SSH dimensions (148×43) and measures the full engine `onRender` pipeline with a mock stdout so `setCellAt` / `outputToScreen` / `diff` costs are real.
37
+ - **Phase A.1 — `ScreenBuilder` eliminates `setCellAt` O(N²) `cells.slice()`** (commit `25bf0f52`). New mutable builder pattern at `output-to-screen.ts:211`: original `setCellAt(screen, ...)` did `screen.cells.slice()` (full width×height ref copy) + `{...screen, cells}` per non-empty cell — on a 148×43 viewport with ~500 non-empty cells/frame that's ~3.18M element-copies + 500 fresh arrays + 500 fresh Screen objects per frame. `createScreenBuilder(width, height)` exposes O(1) `setCellAt` writes + one-shot `build()` that returns a frozen Screen; only the `outputToScreen` hot loop migrated, public `setCellAt(Screen, ...)` API preserved for tests + future immutable callers. **End-to-end bench delta** (148×43, `mainscreen-windowed-800` scenario): renderer p95 14.804ms → 3.095ms (-79%, 4.78× speedup). 193 substrate-ink tests + 7 new ScreenBuilder unit tests (byte-equal vs `setCellAt`, OOB rejection, post-build-write rejection, 10k-write soft budget) + last-write-wins test `1105a181` close the review loop. 1426/1427 full repl PASS.
38
+ - **Phase A.2-E deferred pending user SSH trace measurement after A.1 ship.** ADR-028 documents the full claudecode port plan (Phase B nodeCache + markDirty / Phase C screen.damage bounding box / Phase D Output.charCache + StylePool / Phase E FRAME_INTERVAL + viewport culling). Layer 0 G1 (transcript render goldens, `925a4d77`) + G2 (perf bench + baseline, `4641ebb9`) + G4 (hit-test + selection 22 edge tests, `4fb590f3`) shipped as Phase 0 planning artifacts; ADR-027 + ADR-028 + `docs/test-guides/FEATURE_172_v0.7.41_REGRESSION_GUIDE.md` document the full pipeline.
39
+ - **First-round TTFB compression — drop `refresh:true` tax + parallel pre-LLM + REPL-mount prewarm** (commit `e8b336ed`). Triggered by user observation: review-type prompts on a medium repo paid ~24s pre-LLM wall-time (after parallel/memoize work) before any LLM token streamed. Compressed via L1+L2 to ~10-15s (LLM-TTFB-bound). 5 stacked changes:
40
+ - **L1 — `middleware/repo-intelligence.ts` first-round NEVER forces `refresh:true`**. 4 sites of `refresh: isNewSession` → `refresh: false`. The 30s `PREMIUM_REFRESH_TIMEOUT_MS` budget was paid on every new session, but the daemon's own background polling keeps its on-disk state fresh; the 4s budget path returns daemon's already-cached state immediately. Single biggest savings (~10-15s).
41
+ - **L2 — REPL-mount prewarm** (new `prewarmRepoIntelligenceCaches` helper exported from `@kodax-ai/coding` + Ink-REPL `useEffect`). Fires `getRepoRoutingSignals` + `getRepoPreturnBundle` with refresh:false at REPL mount, fire-and-forget. Cache-coherent with L1 (both refresh:false) so user-path either coalesces onto in-flight prewarm Promise (~2s) or hits warmed P3+ cache (~0ms). Default-on; opt-out via `KODAX_PREWARM_REPO_INTELLIGENCE=0`.
42
+ - **P1.a — middleware parallel fan-out**. Two-phase `Promise.all`: Phase 1 races OSS overview (git+fs) with premium preturn (daemon); Phase 2 races module + impact direct-call fallbacks ONLY for slots not already filled by preturn. Behavioral pins preserved (preturn gating + `.catch(() => null)` error isolation + emit order: preturn → module → impact).
43
+ - **P1.b — run-substrate parallel**. `hydrateSession` (MCP state restore) and `getRepoRoutingSignals` collapsed to one wall-time slot via `Promise.all`; hydration error propagation unchanged, routing has independent `.catch(() => null)`.
44
+ - **P2 / P3 / P3+ — multi-tier cache stack**. P2 in-flight Promise sharing in `tryPremiumPreturn` (1.5s TTL, cacheKey DELIBERATELY includes `refresh` so explicit `refresh:true` callers — `/repointel warm`, eval harness — get their own daemon work). P3/P3+ session-scoped caches (60s TTL on routing signals + preturn bundle, cacheKey OMITS refresh so prewarm + first-round share one entry under the "data within 60s is fresh by definition" semantics). `normalizeCachePath` helper makes cacheKey robust to Windows drive-letter case + relative-vs-absolute caller variations + Promise rejection paths.
45
+ - **Default repo-intelligence mode preserved as `'auto'`**. Briefly experimented with flipping default to `'oss'` for users without repointel; cost analysis showed `'auto'` fallback path is ~10ms localhost TCP RST + 2s `PREMIUM_FAILURE_TTL_MS` cache → 0ms within TTL + ~5-10ms per >2s gap (negligible vs LLM TTFB). Auto-detection of installed repointel is the right default per README:182.
46
+ - **Inline spinner-row stats tail — elapsed + tokens (claudecode parity)** (commit `58682cbf`). REPL spinner row gains an inline `Xs · Y tokens` running tail (matches claudecode's status indicator). Frontline of a sequence of claudecode-parity surface improvements; documented in ADR-027 Phase 0.
47
+
48
+ ### Internal / architecture
49
+
50
+ - **FEATURE_171 — `runner-driven.ts` modular split**. R1 `2fef1c31` (4 leaf modules + `types.ts`) → R2 `f0be2d4e` (4 mid-coupling modules) → R3 `bfb2b818` (agent-chain + llm-adapter) → R4 `62dc1c58` (payload-builder + checkpoint-flow). 12 submodule extraction; **6406 → 1897 lines (-70.4%)**; **zero behavior change**; **4 reviewer APPROVE rounds**; **4314/4314 tests pass each commit**. ADR-026 + HLD.md §3.5.1 documented in R5 (`4d108af9`). The refactor preserves the closure pattern around `baseCtx` / `siblingSnapshot` / `contextTokenSnapshotRef` — what was a 6400-line monolith is now a stack of named factories each under 800 lines. Module map: `types.ts`, `agent-chain.ts`, `payload-builder.ts`, `checkpoint-flow.ts`, `llm-adapter.ts`, `compaction-bridge.ts`, `manager-input-builder.ts`, `result-projection.ts`, `tool-ctx-builder.ts`, `child-task-orchestration.ts`, `recorder-bridge.ts`, plus the residual `runner-driven.ts` entry. Side benefit: faster IDE hover-pop on the public surface; the public export shape is unchanged so all consumers are byte-equivalent.
51
+ - **`bootstrapTeamMode` + `TeamModeHandle` exports added to `@kodax-ai/agent`** so the Ink REPL can import them without depending on legacy-CLI internals. The handle exposes `shutdown()` and is opaque otherwise (per the layer-independence guarantee — REPL has no business poking at the per-instance writer's internals).
52
+ - **`KodaXToolExecutionContext.contentHashCache?`** field added with `recordRead` / `checkStale` / `recordWrite` API surface. Per-task lifetime (created at task start, destroyed at completion). Wired into Read / Edit / Write / MultiEdit tool implementations so the FEATURE_125 race-detection works without per-tool plumbing.
53
+ - **`KodaXToolExecutionContext.siblingSnapshot?`** field added (as a mutable ref) with `Object.defineProperty` getter on the tool ctx so each tool invocation reads the freshest snapshot from the runner-driven adapter's per-round refresh. Avoids stale-snapshot reads when the LLM stream spans multiple seconds.
54
+ - **`buildToolNamePatterns` extended from 4 to 9 syntax variants** in the benchmark harness regex tooling (`benchmark/datasets/feature-125-team-mode-awareness/cases.ts` + downstream). Captures kimi `read:0>{...}`, zhipu `<tool_name>read</tool_name>` and 3 other non-canonical syntaxes; lesson saved as `feedback_regex_audit_per_new_eval`.
55
+ - **`JudgeContext.toolCalls?`** plumbed through `benchmark/harness/judges.ts` + both call sites in `benchmark/harness/harness.ts`. Optional `judge(output, context?)` arg lets binding-only providers (zhipu/glm51, mmx/m27, etc. — they emit `text=""` and put the tool call in the structured `tool_calls` field) be judged on what the harness actually captured, not on the empty raw text. Existing text-only judges ignore the arg and continue to work unchanged. Per `feedback_audit_must_see_binding` + `feedback_audit_binding_priority_in_prompt`: also requires the audit judge prompt to label the binding as "ABSOLUTE GROUND TRUTH" + a `CRITICAL RULE` system prompt section, or judges over-anchor on the empty raw text.
56
+ - **2 prompt-eval datasets** added under `benchmark/datasets/`: `feature-125-team-mode-awareness/` (S7 Layer 2 panel: peer-active-file-acknowledge-read-first + peer-recently-modified-reread) and `tool-schema-slim/` (Layer 2 eval of v2_slim ~half + v3_aggressive ~quarter description variants for `ask_user_question` + `todo_create` — see "Tool schema slim eval" below).
57
+ - **Tool schema slim eval (DEFER both v2 + v3)**. Commit `d68141ea`. Designed + ran the largest two-Scout-tool slim attempt: `ask_user_question` (2760 B / ~690 tok) + `todo_create` (2384 B / ~596 tok) — combined ~785–990 tokens potentially saved. 4-alias panel × 9 cases × 5 runs + panel-internal majority audit (initial 85–97% disagreement on AUQ_6 / 18–30% on TC_1 fixed by switching to v2 `CRITICAL RULE` prompt → 0% disagreement, data validated). Both variants **DEFER**: v2 gate (a) violations AUQ_1 zhipu −20pp + TC_1 zhipu/ds/kimi −20 to −40pp; v3 gate (a) violations AUQ_1 zhipu/ds −20 to −40pp + TC_1 zhipu/ds −40pp. Reason: `"For X use Y, NOT Z"` comparative clauses in schema descriptions are load-bearing disambiguation priors — slimming caused zhipu/ds to mis-classify simple cases. Pattern matches existing `feedback_simplifying_prompt_can_regress` + `feedback_model_structural_floor_not_prompt_tunable`. Future schema-slim work: don't touch "use X for ... NOT for ..." clauses; safe to slim version prefixes + return-value descriptions + "use sparingly" style instructions + property description secondary detail. Net cost ~$23 within ~$27 budget.
58
+
59
+ ### Test coverage delta
60
+
61
+ - New: 17 (S1) + 20 (S2) + 20 (S3) + 15 (S4) + 15 (S5) + 7 (S6 integration) + 4 (W1) + 14 (W2) + 10 (W3) + 9 (W4) = 131 FEATURE_125 tests; 9 (FEATURE_165) + 7 (FEATURE_166) + 29 (FEATURE_167) + ~30 (FEATURE_170 C1–C6 follow-ups) = ~75 reliability tests; 50 (FEATURE_171 R4 tool wiring contract) + 0 net new for R1–R3 (all R-series ran the full pre-existing 4314 each round); ~95 FEATURE_172 Phase 1 (65 transcript-layout helpers + 8 golden snapshot + 22 hit-test/selection edge) + 17 React.memo comparator + 7 ScreenBuilder + 1 last-write-wins + 1 KODAX_RENDER_TRACE = ~120 FEATURE_172 tests; 4 cache-coalesce regression tests for the TTFB stack (P2 in-flight, P3 cross-call, P3+ multi-round, refresh:true-within-TTL).
62
+ - Total green at HEAD: **5,081 tests pass + 23 todo + 1 skipped across 8 workspaces** (agent 477 / coding 2712 / llm 276 / mcp 28 / repl 1419 / repo-intel & skills 136 / repointel-protocol & session-lineage 18 / tracing 15). `tsc -p packages/coding/tsconfig.json --noEmit` + `tsc -p packages/repl/tsconfig.json --noEmit` both clean.
63
+
7
64
  ## [0.7.40] - 2026-05-13
8
65
 
9
66
  ### Theme
@@ -1,2 +1,2 @@
1
1
  // @kodax-ai/kodax — bundled distribution. See docs/ADR.md ADR-022 + ADR-024.
2
- import{ic as A,kc as M}from"./chunk-QZEDWITG.js";import{ia as O}from"./chunk-Z5EBDA6R.js";import{$ as m,S as w,T as S,U as x,V as I,W as L,X as h,_ as k,ca as b,ja as R}from"./chunk-6QO6HWGU.js";import{a as i}from"./chunk-V4WSBIXB.js";import a from"fs";import c from"path";import{exec as F,spawnSync as G}from"child_process";import{promisify as V}from"util";import{fileURLToPath as q}from"url";var E="en";function U(){return(process.env.LC_ALL||process.env.LC_MESSAGES||process.env.LANG||"").toLowerCase().startsWith("zh")?"zh":"en"}i(U,"detectSystemLocale");function N(e){if(!e||e==="auto"){E=U();return}E=e.toLowerCase().replace(/[-_].*/,"")==="zh"?"zh":"en"}i(N,"setLocale");var T={en:{"dialog.confirm":"[Confirm]","dialog.select":"[Select]","dialog.input":"[Input]","confirm.instruction.basic":"Press (y) yes, (n) no","confirm.instruction.always":"Press (y) yes, (a) always yes for this tool, (n) no","confirm.instruction.protected":"Press (y) to confirm, (n) to cancel (protected path)","confirm.result.approved":"Approved","confirm.result.approved_always":"Approved (always)","confirm.result.denied":"Denied","tool.bash.title":"Execute bash command?","tool.shell.title":"Execute shell command?","tool.write.title":"Write to file?","tool.edit.title":"Edit file?","tool.generic.title":"Execute {tool}?","field.reason":"Reason","field.intent":"Intent","field.target":"Target","field.scope":"Scope","field.risk":"Risk","field.summary":"Summary","intent.read":"Read project files","intent.delete":"Delete files","intent.deps":"Modify dependencies or environment","intent.modify":"Modify files","intent.execute":"Execute command","intent.write_file":"Write file","intent.edit_file":"Edit file","intent.use_tool":"Use {tool}","risk.destructive":"Destructive change","risk.deps":"May change dependencies or local tools","risk.modify":"May modify files","risk.unknown":"Command effects depend on its arguments","risk.network":"May access network","scope.outside":"Outside project","scope.protected":"Protected path","waiting.confirm":"Waiting: approval required","waiting.select":"Waiting: choose an option","waiting.input":"Waiting: answer the prompt","placeholder.confirm":"Respond to the approval prompt above...","placeholder.select":"Choose an option above...","placeholder.input":"Answer the prompt above...","placeholder.busy":"Agent is busy...","placeholder.queue":"Queue a follow-up for the next round...","placeholder.idle":"Type a message...","select.choice":"Choice:","select.type_number":"(type a number)","select.more":"{count} more choices...","select.more_above":"\u2191 {count} more above","select.more_below":"\u2193 {count} more below","select.confirm_hint":"Press Enter to confirm, Esc to cancel","select.navigate_hint":"Use \u2191\u2193 to navigate, Enter to confirm, Esc to cancel","select.multiselect_hint":"Use \u2191\u2193 to navigate, Space to toggle, Enter to confirm, Esc to cancel","select.multiselect_empty":"Select at least one option with Space before confirming.","select.back_prev":"\u2190 Back to previous question","input.default":"Default:","input.value":"Value:","input.type_response":"(type your response)","managed.completed":"Task completed","managed.completed.blocked":"Task blocked","managed.completed.continuation":"Task needs continuation",cancelled:"[Cancelled] Operation cancelled by user"},zh:{"dialog.confirm":"[\u786E\u8BA4]","dialog.select":"[\u9009\u62E9]","dialog.input":"[\u8F93\u5165]","confirm.instruction.basic":"\u6309 (y) \u786E\u8BA4, (n) \u62D2\u7EDD","confirm.instruction.always":"\u6309 (y) \u786E\u8BA4, (a) \u59CB\u7EC8\u5141\u8BB8\u6B64\u5DE5\u5177, (n) \u62D2\u7EDD","confirm.instruction.protected":"\u6309 (y) \u786E\u8BA4, (n) \u53D6\u6D88 (\u53D7\u4FDD\u62A4\u8DEF\u5F84)","confirm.result.approved":"\u5DF2\u6279\u51C6","confirm.result.approved_always":"\u5DF2\u6279\u51C6 (\u59CB\u7EC8\u5141\u8BB8)","confirm.result.denied":"\u5DF2\u62D2\u7EDD","tool.bash.title":"\u6267\u884C bash \u547D\u4EE4\uFF1F","tool.shell.title":"\u6267\u884C shell \u547D\u4EE4\uFF1F","tool.write.title":"\u5199\u5165\u6587\u4EF6\uFF1F","tool.edit.title":"\u7F16\u8F91\u6587\u4EF6\uFF1F","tool.generic.title":"\u6267\u884C {tool}\uFF1F","field.reason":"\u539F\u56E0","field.intent":"\u610F\u56FE","field.target":"\u76EE\u6807","field.scope":"\u8303\u56F4","field.risk":"\u98CE\u9669","field.summary":"\u6458\u8981","intent.read":"\u8BFB\u53D6\u9879\u76EE\u6587\u4EF6","intent.delete":"\u5220\u9664\u6587\u4EF6","intent.deps":"\u4FEE\u6539\u4F9D\u8D56\u6216\u73AF\u5883","intent.modify":"\u4FEE\u6539\u6587\u4EF6","intent.execute":"\u6267\u884C\u547D\u4EE4","intent.write_file":"\u5199\u5165\u6587\u4EF6","intent.edit_file":"\u7F16\u8F91\u6587\u4EF6","intent.use_tool":"\u4F7F\u7528 {tool}","risk.destructive":"\u7834\u574F\u6027\u53D8\u66F4","risk.deps":"\u53EF\u80FD\u4FEE\u6539\u4F9D\u8D56\u6216\u672C\u5730\u5DE5\u5177","risk.modify":"\u53EF\u80FD\u4FEE\u6539\u6587\u4EF6","risk.unknown":"\u547D\u4EE4\u6548\u679C\u53D6\u51B3\u4E8E\u53C2\u6570","risk.network":"\u53EF\u80FD\u8BBF\u95EE\u7F51\u7EDC","scope.outside":"\u9879\u76EE\u5916\u90E8","scope.protected":"\u53D7\u4FDD\u62A4\u8DEF\u5F84","waiting.confirm":"\u7B49\u5F85\u4E2D\uFF1A\u9700\u8981\u5BA1\u6279","waiting.select":"\u7B49\u5F85\u4E2D\uFF1A\u8BF7\u9009\u62E9","waiting.input":"\u7B49\u5F85\u4E2D\uFF1A\u8BF7\u56DE\u7B54","placeholder.confirm":"\u8BF7\u56DE\u5E94\u4E0A\u65B9\u7684\u5BA1\u6279\u63D0\u793A...","placeholder.select":"\u8BF7\u5728\u4E0A\u65B9\u9009\u62E9\u4E00\u4E2A\u9009\u9879...","placeholder.input":"\u8BF7\u56DE\u7B54\u4E0A\u65B9\u7684\u63D0\u793A...","placeholder.busy":"\u4EE3\u7406\u6B63\u5728\u5DE5\u4F5C\u4E2D...","placeholder.queue":"\u6392\u961F\u7B49\u5F85\u4E0B\u4E00\u8F6E\u8DDF\u8FDB...","placeholder.idle":"\u8F93\u5165\u6D88\u606F...","select.choice":"\u9009\u9879\uFF1A","select.type_number":"(\u8F93\u5165\u7F16\u53F7)","select.more":"\u8FD8\u6709 {count} \u4E2A\u9009\u9879...","select.more_above":"\u2191 \u4E0A\u65B9\u8FD8\u6709 {count} \u4E2A","select.more_below":"\u2193 \u4E0B\u65B9\u8FD8\u6709 {count} \u4E2A","select.confirm_hint":"\u6309 Enter \u786E\u8BA4\uFF0CEsc \u53D6\u6D88","select.navigate_hint":"\u4F7F\u7528 \u2191\u2193 \u5BFC\u822A\uFF0CEnter \u786E\u8BA4\uFF0CEsc \u53D6\u6D88","select.multiselect_hint":"\u4F7F\u7528 \u2191\u2193 \u5BFC\u822A\uFF0C\u7A7A\u683C \u5207\u6362\u9009\u4E2D\uFF0CEnter \u786E\u8BA4\uFF0CEsc \u53D6\u6D88","select.multiselect_empty":"\u8BF7\u5148\u4F7F\u7528\u7A7A\u683C\u9009\u62E9\u81F3\u5C11\u4E00\u4E2A\u9009\u9879\u3002","select.back_prev":"\u2190 \u8FD4\u56DE\u4E0A\u4E00\u9898","input.default":"\u9ED8\u8BA4\u503C\uFF1A","input.value":"\u503C\uFF1A","input.type_response":"(\u8F93\u5165\u4F60\u7684\u56DE\u7B54)","managed.completed":"\u4EFB\u52A1\u5B8C\u6210","managed.completed.blocked":"\u4EFB\u52A1\u53D7\u963B","managed.completed.continuation":"\u4EFB\u52A1\u9700\u8981\u7EE7\u7EED",cancelled:"[\u5DF2\u53D6\u6D88] \u64CD\u4F5C\u5DF2\u88AB\u7528\u6237\u53D6\u6D88"}};function pe(e,t){let o=T[E][e]??T.en[e]??e;if(t)for(let[r,l]of Object.entries(t))o=o.replace(`{${r}}`,String(l));return o}i(pe,"t");var W=V(F),X=O(),Ce=c.join(X,"sessions"),d=c.join(X,"config.json"),we=60,s=null,_=!1,J="dumb";function Q(e){let t=c.basename(e).toLowerCase(),n="__KODAX_SHELL_ENV_START__",o=`printf '%s\\0' '${n}'; env -0`;return t==="fish"?{args:["-i","-c",o],sentinel:n}:{args:t==="bash"||t==="zsh"?["-ic",o]:["-lc",o],sentinel:n}}i(Q,"buildShellEnvCommand");function Y(e,t){let n=`${t}\0`,o=e.lastIndexOf(n);if(o===-1)return{};let r=e.slice(o+n.length),l={};for(let u of r.split("\0")){if(!u)continue;let p=u.indexOf("=");p<=0||(l[u.slice(0,p)]=u.slice(p+1))}return l}i(Y,"parseNullDelimitedShellEnv");function Z(e={}){let t=e.env??process.env;if((e.platform??process.platform)==="win32"||t.KODAX_DISABLE_SHELL_ENV_HYDRATION==="1")return!1;let o=e.shell??t.SHELL;if(!o||!c.isAbsolute(o))return!1;let{args:r,sentinel:l}=Q(o),u=e.run??G,p={...t,TERM:J},f=u(o,r,{encoding:"utf8",env:p,maxBuffer:1024*1024,timeout:5e3,windowsHide:!0,detached:!0,stdio:["ignore","pipe","pipe"]});if(f.status!==0||!f.stdout)return!1;let H=typeof f.stdout=="string"?f.stdout:f.stdout.toString("utf8"),j=Y(H,l),C=!1;for(let[v,z]of Object.entries(j))v!=="TERM"&&t[v]===void 0&&(t[v]=z,C=!0);return C}i(Z,"hydrateProcessEnvFromShell");function ee(){if(!_){_=!0;try{Z()}catch{}}}i(ee,"ensureShellEnvironmentHydrated");function Se(){_=!1}i(Se,"resetShellEnvironmentHydrationForTesting");function te(e){k(e.customProviders??[])}i(te,"registerConfiguredCustomProviders");function $(e){if(!Array.isArray(e))return;let t=e.filter(n=>typeof n=="string").map(n=>n.trim()).filter(n=>n.length>0);return t.length>0?t:[]}i($,"normalizeConfiguredExtensions");function ne(e){if(e.permissionMode!=="default")return e;let t={...e,permissionMode:"accept-edits"};try{a.mkdirSync(c.dirname(d),{recursive:!0}),a.writeFileSync(d,JSON.stringify(t,null,2))}catch{}return t}i(ne,"migrateLegacyPermissionModeInConfig");function oe(){if(s)return s;let e="0.7.40";if(e)return s=e,s;let t=c.join(c.dirname(q(import.meta.url)),"../../package.json");if(a.existsSync(t))try{return s=JSON.parse(a.readFileSync(t,"utf-8")).version??"0.0.0",s??"0.0.0"}catch{}return s="0.0.0",s}i(oe,"getVersion");var xe=oe();function Ie(e){return S(e)}i(Ie,"getProviderModel");function P(e,t){let n=new Set(e.map(r=>r.toLowerCase())),o=[...e];for(let r of t)n.has(r.toLowerCase())||o.push(r);return o}i(P,"mergeModels");function ie(e,t){t||(t=y().providerModels);let n=t?.[e];if(n&&n.length>0){try{let o=h(e);if(o.length>0)return P(n,o)}catch{}try{let o=m(e);if(o)return P(n,o.getAvailableModels())}catch{}return n}try{let o=h(e);if(o.length>0)return o}catch{}try{let o=m(e);if(o)return o.getAvailableModels()}catch{}return[]}i(ie,"getProviderAvailableModels");function re(e,t){let n=x(e,t);if(n!=="unknown")return n;try{let o=m(e);if(o)return o.getReasoningCapability(t)}catch{}return"unknown"}i(re,"getProviderReasoningCapability");function se(e){let t=I(e);if(t)return t;try{return b().find(o=>o.name===e)?.capabilityProfile??null}catch{return null}}i(se,"getProviderCapabilityProfile");function B(e,t){let n=se(e),o=re(e,t);if(n)return{capabilityProfile:n,reasoningCapability:o};try{let r=R(e);return{capabilityProfile:r.getCapabilityProfile(),reasoningCapability:r.getReasoningCapability(t)}}catch{return null}}i(B,"getProviderCapabilityMetadata");function Le(e,t){let n=B(e,t);return n?A({providerName:e,model:t,capabilityProfile:n.capabilityProfile,reasoningCapability:n.reasoningCapability==="unknown"?void 0:n.reasoningCapability}):null}i(Le,"getProviderCapabilitySnapshot");function ae(e,t,n,o){let r=B(e,t);return r?M({providerName:e,model:t,capabilityProfile:r.capabilityProfile,reasoningCapability:r.reasoningCapability==="unknown"?void 0:r.reasoningCapability,reasoningMode:n,hints:o}):null}i(ae,"getProviderPolicyDecision");function ke(e){let t=e.transport==="cli-bridge"?"CLI bridge":"Native API",n=e.conversationSemantics==="last-user-message"?"forwards only the latest user message":"preserves full conversation history",o=e.mcpSupport==="native"?"MCP available":"MCP unavailable";return`${t}; ${n}; ${o}`}i(ke,"describeProviderCapabilitySummary");function Re(e){switch(e){case"native-budget":return"B";case"native-effort":return"E";case"native-toggle":return"T";default:return"-"}}i(Re,"formatReasoningCapabilityShort");function ce(e){switch(e){case"native-budget":return"budget";case"native-effort":return"effort";case"native-toggle":return"toggle";default:return"none"}}i(ce,"describeReasoningCapabilityControl");function Oe(e,t){if(e==="off")return"Reasoning disabled";switch(t){case"native-budget":return"Uses native thinking budget control";case"native-effort":return"Uses native reasoning effort control";case"native-toggle":return"Uses provider-native thinking toggle only";case"none":return"Runs without native reasoning parameters";case"prompt-only":return"Uses prompt overlays only; no native reasoning parameter";default:return"Runs without native reasoning parameters"}}i(Oe,"describeReasoningExecution");function Ae(e){let t=[];e||(e=y().providerModels);for(let n of L())t.push({name:n.name,model:n.model,models:ie(n.name,e),configured:n.capabilityProfile.transport==="cli-bridge"?!0:n.configured,reasoningCapability:n.reasoningCapability,capabilityProfile:n.capabilityProfile});try{let n=b().map(o=>({...o,models:(()=>{let r=e?.[o.name];return r&&r.length>0?P(r,o.models):o.models})()}));t.push(...n)}catch{}return t}i(Ae,"getProviderList");function Me(e){if(w(e))return!0;try{return m(e)?.isConfigured()??!1}catch{return!1}}i(Me,"isProviderConfigured");function y(){try{if(a.existsSync(d)){let e=JSON.parse(a.readFileSync(d,"utf-8")),t=e.reasoningCeiling??e.reasoningMode;return ne({...e,reasoningMode:t,extensions:$(e.extensions)})}}catch{}return{}}i(y,"loadConfig");function le(e){e.streamIdleTimeoutMs&&!process.env.KODAX_STREAM_IDLE_TIMEOUT_MS&&(process.env.KODAX_STREAM_IDLE_TIMEOUT_MS=String(e.streamIdleTimeoutMs))}i(le,"applyResilienceRuntimeEnv");function ue(e){e.repoIntelligenceMode&&!process.env.KODAX_REPO_INTELLIGENCE_MODE&&(process.env.KODAX_REPO_INTELLIGENCE_MODE=e.repoIntelligenceMode),e.repointelEndpoint&&!process.env.KODAX_REPOINTEL_ENDPOINT&&(process.env.KODAX_REPOINTEL_ENDPOINT=e.repointelEndpoint),e.repointelBin&&!process.env.KODAX_REPOINTEL_BIN&&(process.env.KODAX_REPOINTEL_BIN=e.repointelBin),e.repoIntelligenceTrace===!0&&!process.env.KODAX_REPO_INTELLIGENCE_TRACE&&(process.env.KODAX_REPO_INTELLIGENCE_TRACE="1")}i(ue,"applyRepoIntelligenceRuntimeEnv");function Te(){ee();let e=y();return le(e),ue(e),te(e),N(e.locale),e}i(Te,"prepareRuntimeConfig");function Ne(e){let n={...y(),...e},o=$(n.extensions);o!==void 0&&(n.extensions=o);for(let r of Object.keys(e))e[r]===void 0&&delete n[r];a.mkdirSync(c.dirname(d),{recursive:!0}),a.writeFileSync(d,JSON.stringify(n,null,2))}i(Ne,"saveConfig");async function De(){try{let{stdout:e}=await W("git rev-parse --show-toplevel");return e.trim()}catch{return null}}i(De,"getGitRoot");function de(e){switch(e){case"builtin":return"Built-in";case"runtime":return"Runtime extension";case"custom":return"Custom config";default:return"Unknown"}}i(de,"formatProviderSourceKind");function Ke(e){let t=e.transport==="cli-bridge"?"CLI bridge":"Native API",n=e.conversationSemantics==="last-user-message"?"latest-user-message only":"full conversation history";return[`Source: ${de(e.sourceKind)}`,`Transport: ${t}`,`Conversation semantics: ${n}`,`Context fidelity: ${e.contextFidelity}`,`Tool calling: ${e.toolCallingFidelity}`,`Session behavior: ${e.sessionSupport}`,`Long-running support: ${e.longRunningSupport}`,`Evidence-heavy flows: ${e.evidenceSupport}`,`Multimodal support: ${e.multimodalSupport}`,`MCP support: ${e.mcpSupport}`,`Reasoning control: ${ce(e.reasoningCapability)}`]}i(Ke,"formatProviderCapabilityDetailLines");function Xe(e,t,n){return[{label:"General coding",hints:{}},{label:"Evidence-heavy review",hints:{evidenceHeavy:!0}},{label:"Long-running task",hints:{longRunning:!0}}].map(r=>({label:r.label,decision:ae(e,t,n,r.hints)})).filter(r=>r.decision!==null)}i(Xe,"getProviderCommonPolicyScenarios");var D=.5,K=0,g={locked:!1,queue:[]};async function $e(e){for(;g.locked;)await new Promise(t=>g.queue.push(t));g.locked=!0;try{let t=(Date.now()-K)/1e3;t<D&&await new Promise(o=>setTimeout(o,(D-t)*1e3));let n=await e();return K=Date.now(),n}finally{g.locked=!1;let t=g.queue.shift();t&&t()}}i($e,"rateLimitedCall");export{pe as a,X as b,Ce as c,d,we as e,Z as f,Se as g,te as h,oe as i,xe as j,Ie as k,ie as l,re as m,se as n,Le as o,ae as p,ke as q,Re as r,ce as s,Oe as t,Ae as u,Me as v,y as w,Te as x,Ne as y,De as z,de as A,Ke as B,Xe as C,$e as D};
2
+ import{pc as A,rc as M}from"./chunk-HYWVRTFA.js";import{ia as O}from"./chunk-SX2IS5JP.js";import{$ as m,S as w,T as S,U as x,V as I,W as L,X as h,_ as k,ca as b,ja as R}from"./chunk-6QO6HWGU.js";import{a as i}from"./chunk-V4WSBIXB.js";import a from"fs";import c from"path";import{exec as F,spawnSync as G}from"child_process";import{promisify as V}from"util";import{fileURLToPath as q}from"url";var E="en";function U(){return(process.env.LC_ALL||process.env.LC_MESSAGES||process.env.LANG||"").toLowerCase().startsWith("zh")?"zh":"en"}i(U,"detectSystemLocale");function N(e){if(!e||e==="auto"){E=U();return}E=e.toLowerCase().replace(/[-_].*/,"")==="zh"?"zh":"en"}i(N,"setLocale");var T={en:{"dialog.confirm":"[Confirm]","dialog.select":"[Select]","dialog.input":"[Input]","confirm.instruction.basic":"Press (y) yes, (n) no","confirm.instruction.always":"Press (y) yes, (a) always yes for this tool, (n) no","confirm.instruction.protected":"Press (y) to confirm, (n) to cancel (protected path)","confirm.result.approved":"Approved","confirm.result.approved_always":"Approved (always)","confirm.result.denied":"Denied","tool.bash.title":"Execute bash command?","tool.shell.title":"Execute shell command?","tool.write.title":"Write to file?","tool.edit.title":"Edit file?","tool.generic.title":"Execute {tool}?","field.reason":"Reason","field.intent":"Intent","field.target":"Target","field.scope":"Scope","field.risk":"Risk","field.summary":"Summary","intent.read":"Read project files","intent.delete":"Delete files","intent.deps":"Modify dependencies or environment","intent.modify":"Modify files","intent.execute":"Execute command","intent.write_file":"Write file","intent.edit_file":"Edit file","intent.use_tool":"Use {tool}","risk.destructive":"Destructive change","risk.deps":"May change dependencies or local tools","risk.modify":"May modify files","risk.unknown":"Command effects depend on its arguments","risk.network":"May access network","scope.outside":"Outside project","scope.protected":"Protected path","waiting.confirm":"Waiting: approval required","waiting.select":"Waiting: choose an option","waiting.input":"Waiting: answer the prompt","placeholder.confirm":"Respond to the approval prompt above...","placeholder.select":"Choose an option above...","placeholder.input":"Answer the prompt above...","placeholder.busy":"Agent is busy...","placeholder.queue":"Queue a follow-up for the next round...","placeholder.idle":"Type a message...","select.choice":"Choice:","select.type_number":"(type a number)","select.more":"{count} more choices...","select.more_above":"\u2191 {count} more above","select.more_below":"\u2193 {count} more below","select.confirm_hint":"Press Enter to confirm, Esc to cancel","select.navigate_hint":"Use \u2191\u2193 to navigate, Enter to confirm, Esc to cancel","select.multiselect_hint":"Use \u2191\u2193 to navigate, Space to toggle, Enter to confirm, Esc to cancel","select.multiselect_empty":"Select at least one option with Space before confirming.","select.back_prev":"\u2190 Back to previous question","input.default":"Default:","input.value":"Value:","input.type_response":"(type your response)","managed.completed":"Task completed","managed.completed.blocked":"Task blocked","managed.completed.continuation":"Task needs continuation",cancelled:"[Cancelled] Operation cancelled by user"},zh:{"dialog.confirm":"[\u786E\u8BA4]","dialog.select":"[\u9009\u62E9]","dialog.input":"[\u8F93\u5165]","confirm.instruction.basic":"\u6309 (y) \u786E\u8BA4, (n) \u62D2\u7EDD","confirm.instruction.always":"\u6309 (y) \u786E\u8BA4, (a) \u59CB\u7EC8\u5141\u8BB8\u6B64\u5DE5\u5177, (n) \u62D2\u7EDD","confirm.instruction.protected":"\u6309 (y) \u786E\u8BA4, (n) \u53D6\u6D88 (\u53D7\u4FDD\u62A4\u8DEF\u5F84)","confirm.result.approved":"\u5DF2\u6279\u51C6","confirm.result.approved_always":"\u5DF2\u6279\u51C6 (\u59CB\u7EC8\u5141\u8BB8)","confirm.result.denied":"\u5DF2\u62D2\u7EDD","tool.bash.title":"\u6267\u884C bash \u547D\u4EE4\uFF1F","tool.shell.title":"\u6267\u884C shell \u547D\u4EE4\uFF1F","tool.write.title":"\u5199\u5165\u6587\u4EF6\uFF1F","tool.edit.title":"\u7F16\u8F91\u6587\u4EF6\uFF1F","tool.generic.title":"\u6267\u884C {tool}\uFF1F","field.reason":"\u539F\u56E0","field.intent":"\u610F\u56FE","field.target":"\u76EE\u6807","field.scope":"\u8303\u56F4","field.risk":"\u98CE\u9669","field.summary":"\u6458\u8981","intent.read":"\u8BFB\u53D6\u9879\u76EE\u6587\u4EF6","intent.delete":"\u5220\u9664\u6587\u4EF6","intent.deps":"\u4FEE\u6539\u4F9D\u8D56\u6216\u73AF\u5883","intent.modify":"\u4FEE\u6539\u6587\u4EF6","intent.execute":"\u6267\u884C\u547D\u4EE4","intent.write_file":"\u5199\u5165\u6587\u4EF6","intent.edit_file":"\u7F16\u8F91\u6587\u4EF6","intent.use_tool":"\u4F7F\u7528 {tool}","risk.destructive":"\u7834\u574F\u6027\u53D8\u66F4","risk.deps":"\u53EF\u80FD\u4FEE\u6539\u4F9D\u8D56\u6216\u672C\u5730\u5DE5\u5177","risk.modify":"\u53EF\u80FD\u4FEE\u6539\u6587\u4EF6","risk.unknown":"\u547D\u4EE4\u6548\u679C\u53D6\u51B3\u4E8E\u53C2\u6570","risk.network":"\u53EF\u80FD\u8BBF\u95EE\u7F51\u7EDC","scope.outside":"\u9879\u76EE\u5916\u90E8","scope.protected":"\u53D7\u4FDD\u62A4\u8DEF\u5F84","waiting.confirm":"\u7B49\u5F85\u4E2D\uFF1A\u9700\u8981\u5BA1\u6279","waiting.select":"\u7B49\u5F85\u4E2D\uFF1A\u8BF7\u9009\u62E9","waiting.input":"\u7B49\u5F85\u4E2D\uFF1A\u8BF7\u56DE\u7B54","placeholder.confirm":"\u8BF7\u56DE\u5E94\u4E0A\u65B9\u7684\u5BA1\u6279\u63D0\u793A...","placeholder.select":"\u8BF7\u5728\u4E0A\u65B9\u9009\u62E9\u4E00\u4E2A\u9009\u9879...","placeholder.input":"\u8BF7\u56DE\u7B54\u4E0A\u65B9\u7684\u63D0\u793A...","placeholder.busy":"\u4EE3\u7406\u6B63\u5728\u5DE5\u4F5C\u4E2D...","placeholder.queue":"\u6392\u961F\u7B49\u5F85\u4E0B\u4E00\u8F6E\u8DDF\u8FDB...","placeholder.idle":"\u8F93\u5165\u6D88\u606F...","select.choice":"\u9009\u9879\uFF1A","select.type_number":"(\u8F93\u5165\u7F16\u53F7)","select.more":"\u8FD8\u6709 {count} \u4E2A\u9009\u9879...","select.more_above":"\u2191 \u4E0A\u65B9\u8FD8\u6709 {count} \u4E2A","select.more_below":"\u2193 \u4E0B\u65B9\u8FD8\u6709 {count} \u4E2A","select.confirm_hint":"\u6309 Enter \u786E\u8BA4\uFF0CEsc \u53D6\u6D88","select.navigate_hint":"\u4F7F\u7528 \u2191\u2193 \u5BFC\u822A\uFF0CEnter \u786E\u8BA4\uFF0CEsc \u53D6\u6D88","select.multiselect_hint":"\u4F7F\u7528 \u2191\u2193 \u5BFC\u822A\uFF0C\u7A7A\u683C \u5207\u6362\u9009\u4E2D\uFF0CEnter \u786E\u8BA4\uFF0CEsc \u53D6\u6D88","select.multiselect_empty":"\u8BF7\u5148\u4F7F\u7528\u7A7A\u683C\u9009\u62E9\u81F3\u5C11\u4E00\u4E2A\u9009\u9879\u3002","select.back_prev":"\u2190 \u8FD4\u56DE\u4E0A\u4E00\u9898","input.default":"\u9ED8\u8BA4\u503C\uFF1A","input.value":"\u503C\uFF1A","input.type_response":"(\u8F93\u5165\u4F60\u7684\u56DE\u7B54)","managed.completed":"\u4EFB\u52A1\u5B8C\u6210","managed.completed.blocked":"\u4EFB\u52A1\u53D7\u963B","managed.completed.continuation":"\u4EFB\u52A1\u9700\u8981\u7EE7\u7EED",cancelled:"[\u5DF2\u53D6\u6D88] \u64CD\u4F5C\u5DF2\u88AB\u7528\u6237\u53D6\u6D88"}};function pe(e,t){let o=T[E][e]??T.en[e]??e;if(t)for(let[r,l]of Object.entries(t))o=o.replace(`{${r}}`,String(l));return o}i(pe,"t");var W=V(F),X=O(),Ce=c.join(X,"sessions"),d=c.join(X,"config.json"),we=60,s=null,_=!1,J="dumb";function Q(e){let t=c.basename(e).toLowerCase(),n="__KODAX_SHELL_ENV_START__",o=`printf '%s\\0' '${n}'; env -0`;return t==="fish"?{args:["-i","-c",o],sentinel:n}:{args:t==="bash"||t==="zsh"?["-ic",o]:["-lc",o],sentinel:n}}i(Q,"buildShellEnvCommand");function Y(e,t){let n=`${t}\0`,o=e.lastIndexOf(n);if(o===-1)return{};let r=e.slice(o+n.length),l={};for(let u of r.split("\0")){if(!u)continue;let p=u.indexOf("=");p<=0||(l[u.slice(0,p)]=u.slice(p+1))}return l}i(Y,"parseNullDelimitedShellEnv");function Z(e={}){let t=e.env??process.env;if((e.platform??process.platform)==="win32"||t.KODAX_DISABLE_SHELL_ENV_HYDRATION==="1")return!1;let o=e.shell??t.SHELL;if(!o||!c.isAbsolute(o))return!1;let{args:r,sentinel:l}=Q(o),u=e.run??G,p={...t,TERM:J},f=u(o,r,{encoding:"utf8",env:p,maxBuffer:1024*1024,timeout:5e3,windowsHide:!0,detached:!0,stdio:["ignore","pipe","pipe"]});if(f.status!==0||!f.stdout)return!1;let H=typeof f.stdout=="string"?f.stdout:f.stdout.toString("utf8"),j=Y(H,l),C=!1;for(let[v,z]of Object.entries(j))v!=="TERM"&&t[v]===void 0&&(t[v]=z,C=!0);return C}i(Z,"hydrateProcessEnvFromShell");function ee(){if(!_){_=!0;try{Z()}catch{}}}i(ee,"ensureShellEnvironmentHydrated");function Se(){_=!1}i(Se,"resetShellEnvironmentHydrationForTesting");function te(e){k(e.customProviders??[])}i(te,"registerConfiguredCustomProviders");function $(e){if(!Array.isArray(e))return;let t=e.filter(n=>typeof n=="string").map(n=>n.trim()).filter(n=>n.length>0);return t.length>0?t:[]}i($,"normalizeConfiguredExtensions");function ne(e){if(e.permissionMode!=="default")return e;let t={...e,permissionMode:"accept-edits"};try{a.mkdirSync(c.dirname(d),{recursive:!0}),a.writeFileSync(d,JSON.stringify(t,null,2))}catch{}return t}i(ne,"migrateLegacyPermissionModeInConfig");function oe(){if(s)return s;let e="0.7.41";if(e)return s=e,s;let t=c.join(c.dirname(q(import.meta.url)),"../../package.json");if(a.existsSync(t))try{return s=JSON.parse(a.readFileSync(t,"utf-8")).version??"0.0.0",s??"0.0.0"}catch{}return s="0.0.0",s}i(oe,"getVersion");var xe=oe();function Ie(e){return S(e)}i(Ie,"getProviderModel");function P(e,t){let n=new Set(e.map(r=>r.toLowerCase())),o=[...e];for(let r of t)n.has(r.toLowerCase())||o.push(r);return o}i(P,"mergeModels");function ie(e,t){t||(t=y().providerModels);let n=t?.[e];if(n&&n.length>0){try{let o=h(e);if(o.length>0)return P(n,o)}catch{}try{let o=m(e);if(o)return P(n,o.getAvailableModels())}catch{}return n}try{let o=h(e);if(o.length>0)return o}catch{}try{let o=m(e);if(o)return o.getAvailableModels()}catch{}return[]}i(ie,"getProviderAvailableModels");function re(e,t){let n=x(e,t);if(n!=="unknown")return n;try{let o=m(e);if(o)return o.getReasoningCapability(t)}catch{}return"unknown"}i(re,"getProviderReasoningCapability");function se(e){let t=I(e);if(t)return t;try{return b().find(o=>o.name===e)?.capabilityProfile??null}catch{return null}}i(se,"getProviderCapabilityProfile");function B(e,t){let n=se(e),o=re(e,t);if(n)return{capabilityProfile:n,reasoningCapability:o};try{let r=R(e);return{capabilityProfile:r.getCapabilityProfile(),reasoningCapability:r.getReasoningCapability(t)}}catch{return null}}i(B,"getProviderCapabilityMetadata");function Le(e,t){let n=B(e,t);return n?A({providerName:e,model:t,capabilityProfile:n.capabilityProfile,reasoningCapability:n.reasoningCapability==="unknown"?void 0:n.reasoningCapability}):null}i(Le,"getProviderCapabilitySnapshot");function ae(e,t,n,o){let r=B(e,t);return r?M({providerName:e,model:t,capabilityProfile:r.capabilityProfile,reasoningCapability:r.reasoningCapability==="unknown"?void 0:r.reasoningCapability,reasoningMode:n,hints:o}):null}i(ae,"getProviderPolicyDecision");function ke(e){let t=e.transport==="cli-bridge"?"CLI bridge":"Native API",n=e.conversationSemantics==="last-user-message"?"forwards only the latest user message":"preserves full conversation history",o=e.mcpSupport==="native"?"MCP available":"MCP unavailable";return`${t}; ${n}; ${o}`}i(ke,"describeProviderCapabilitySummary");function Re(e){switch(e){case"native-budget":return"B";case"native-effort":return"E";case"native-toggle":return"T";default:return"-"}}i(Re,"formatReasoningCapabilityShort");function ce(e){switch(e){case"native-budget":return"budget";case"native-effort":return"effort";case"native-toggle":return"toggle";default:return"none"}}i(ce,"describeReasoningCapabilityControl");function Oe(e,t){if(e==="off")return"Reasoning disabled";switch(t){case"native-budget":return"Uses native thinking budget control";case"native-effort":return"Uses native reasoning effort control";case"native-toggle":return"Uses provider-native thinking toggle only";case"none":return"Runs without native reasoning parameters";case"prompt-only":return"Uses prompt overlays only; no native reasoning parameter";default:return"Runs without native reasoning parameters"}}i(Oe,"describeReasoningExecution");function Ae(e){let t=[];e||(e=y().providerModels);for(let n of L())t.push({name:n.name,model:n.model,models:ie(n.name,e),configured:n.capabilityProfile.transport==="cli-bridge"?!0:n.configured,reasoningCapability:n.reasoningCapability,capabilityProfile:n.capabilityProfile});try{let n=b().map(o=>({...o,models:(()=>{let r=e?.[o.name];return r&&r.length>0?P(r,o.models):o.models})()}));t.push(...n)}catch{}return t}i(Ae,"getProviderList");function Me(e){if(w(e))return!0;try{return m(e)?.isConfigured()??!1}catch{return!1}}i(Me,"isProviderConfigured");function y(){try{if(a.existsSync(d)){let e=JSON.parse(a.readFileSync(d,"utf-8")),t=e.reasoningCeiling??e.reasoningMode;return ne({...e,reasoningMode:t,extensions:$(e.extensions)})}}catch{}return{}}i(y,"loadConfig");function le(e){e.streamIdleTimeoutMs&&!process.env.KODAX_STREAM_IDLE_TIMEOUT_MS&&(process.env.KODAX_STREAM_IDLE_TIMEOUT_MS=String(e.streamIdleTimeoutMs))}i(le,"applyResilienceRuntimeEnv");function ue(e){e.repoIntelligenceMode&&!process.env.KODAX_REPO_INTELLIGENCE_MODE&&(process.env.KODAX_REPO_INTELLIGENCE_MODE=e.repoIntelligenceMode),e.repointelEndpoint&&!process.env.KODAX_REPOINTEL_ENDPOINT&&(process.env.KODAX_REPOINTEL_ENDPOINT=e.repointelEndpoint),e.repointelBin&&!process.env.KODAX_REPOINTEL_BIN&&(process.env.KODAX_REPOINTEL_BIN=e.repointelBin),e.repoIntelligenceTrace===!0&&!process.env.KODAX_REPO_INTELLIGENCE_TRACE&&(process.env.KODAX_REPO_INTELLIGENCE_TRACE="1")}i(ue,"applyRepoIntelligenceRuntimeEnv");function Te(){ee();let e=y();return le(e),ue(e),te(e),N(e.locale),e}i(Te,"prepareRuntimeConfig");function Ne(e){let n={...y(),...e},o=$(n.extensions);o!==void 0&&(n.extensions=o);for(let r of Object.keys(e))e[r]===void 0&&delete n[r];a.mkdirSync(c.dirname(d),{recursive:!0}),a.writeFileSync(d,JSON.stringify(n,null,2))}i(Ne,"saveConfig");async function De(){try{let{stdout:e}=await W("git rev-parse --show-toplevel");return e.trim()}catch{return null}}i(De,"getGitRoot");function de(e){switch(e){case"builtin":return"Built-in";case"runtime":return"Runtime extension";case"custom":return"Custom config";default:return"Unknown"}}i(de,"formatProviderSourceKind");function Ke(e){let t=e.transport==="cli-bridge"?"CLI bridge":"Native API",n=e.conversationSemantics==="last-user-message"?"latest-user-message only":"full conversation history";return[`Source: ${de(e.sourceKind)}`,`Transport: ${t}`,`Conversation semantics: ${n}`,`Context fidelity: ${e.contextFidelity}`,`Tool calling: ${e.toolCallingFidelity}`,`Session behavior: ${e.sessionSupport}`,`Long-running support: ${e.longRunningSupport}`,`Evidence-heavy flows: ${e.evidenceSupport}`,`Multimodal support: ${e.multimodalSupport}`,`MCP support: ${e.mcpSupport}`,`Reasoning control: ${ce(e.reasoningCapability)}`]}i(Ke,"formatProviderCapabilityDetailLines");function Xe(e,t,n){return[{label:"General coding",hints:{}},{label:"Evidence-heavy review",hints:{evidenceHeavy:!0}},{label:"Long-running task",hints:{longRunning:!0}}].map(r=>({label:r.label,decision:ae(e,t,n,r.hints)})).filter(r=>r.decision!==null)}i(Xe,"getProviderCommonPolicyScenarios");var D=.5,K=0,g={locked:!1,queue:[]};async function $e(e){for(;g.locked;)await new Promise(t=>g.queue.push(t));g.locked=!0;try{let t=(Date.now()-K)/1e3;t<D&&await new Promise(o=>setTimeout(o,(D-t)*1e3));let n=await e();return K=Date.now(),n}finally{g.locked=!1;let t=g.queue.shift();t&&t()}}i($e,"rateLimitedCall");export{pe as a,X as b,Ce as c,d,we as e,Z as f,Se as g,te as h,oe as i,xe as j,Ie as k,ie as l,re as m,se as n,Le as o,ae as p,ke as q,Re as r,ce as s,Oe as t,Ae as u,Me as v,y as w,Te as x,Ne as y,De as z,de as A,Ke as B,Xe as C,$e as D};
@@ -1,2 +1,2 @@
1
1
  // @kodax-ai/kodax — bundled distribution. See docs/ADR.md ADR-022 + ADR-024.
2
- import{ja as e}from"./chunk-Z5EBDA6R.js";import{a as n}from"./chunk-V4WSBIXB.js";import{readFile as i}from"fs/promises";var c={enabled:!0,triggerPercent:75};async function g(o){let t=e("config.json");try{let r=await a(t);if(r?.compaction)return{...c,...r.compaction}}catch{}return c}n(g,"loadCompactionConfig");async function a(o){try{let t=await i(o,"utf-8");return JSON.parse(t)}catch{return null}}n(a,"readConfigFile");export{g as a};
2
+ import{ja as e}from"./chunk-SX2IS5JP.js";import{a as n}from"./chunk-V4WSBIXB.js";import{readFile as i}from"fs/promises";var c={enabled:!0,triggerPercent:75};async function g(o){let t=e("config.json");try{let r=await a(t);if(r?.compaction)return{...c,...r.compaction}}catch{}return c}n(g,"loadCompactionConfig");async function a(o){try{let t=await i(o,"utf-8");return JSON.parse(t)}catch{return null}}n(a,"readConfigFile");export{g as a};