@kodax-ai/kodax 0.7.58 → 0.7.60
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.
- package/CHANGELOG.md +61 -0
- package/README.md +11 -4
- package/README_CN.md +10 -4
- package/dist/chunks/{agent-YJNC2755.js → agent-L5FC3YOY.js} +1 -1
- package/dist/chunks/argument-completer-BQDAYT7W.js +2 -0
- package/dist/chunks/chunk-2RLIKZOZ.js +18 -0
- package/dist/chunks/chunk-4K5BDO7S.js +721 -0
- package/dist/chunks/{chunk-XXEIFNBE.js → chunk-5TRQBMPR.js} +1 -1
- package/dist/chunks/{chunk-QHWXPJEG.js → chunk-6DWXUZMO.js} +166 -167
- package/dist/chunks/{chunk-CV6JHPEO.js → chunk-6OZ5KWG3.js} +1 -1
- package/dist/chunks/chunk-IJN6ZJVI.js +310 -0
- package/dist/chunks/chunk-QFCF3GNT.js +326 -0
- package/dist/chunks/{chunk-HS2K74I4.js → chunk-S4GVQO3W.js} +13 -13
- package/dist/chunks/{chunk-6AU6EPO6.js → chunk-SGNM3UP6.js} +1 -1
- package/dist/chunks/chunk-U6BNMGSK.js +17 -0
- package/dist/chunks/{chunk-526OILYL.js → chunk-UA744TZM.js} +1 -1
- package/dist/chunks/{chunk-NKHXRN7G.js → chunk-XULI4U7I.js} +119 -117
- package/dist/chunks/chunk-ZL5CEANW.js +7 -0
- package/dist/chunks/chunk-ZPD7IUKW.js +322 -0
- package/dist/chunks/compaction-config-E4LN3M53.js +2 -0
- package/dist/chunks/{construction-bootstrap-CIXFH5SE.js → construction-bootstrap-GIFDM4L5.js} +1 -1
- package/dist/chunks/dist-73L4OYPD.js +2 -0
- package/dist/chunks/dist-7PXDYX2R.js +2 -0
- package/dist/chunks/host-FLG7FJZT.js +2 -0
- package/dist/chunks/{paste-Y4DVUWSM.js → paste-FDYM7SZX.js} +1 -1
- package/dist/chunks/run-manager-IU5COC6X.js +2 -0
- package/dist/chunks/{utils-FLVVQHM7.js → utils-NP42DKL3.js} +1 -1
- package/dist/index.d.ts +13 -12
- package/dist/index.js +2 -2
- package/dist/kodax_cli.js +1063 -1020
- package/dist/provider-capabilities.json +971 -986
- package/dist/sdk-agent.d.ts +27 -15
- package/dist/sdk-agent.js +1 -1
- package/dist/sdk-coding.d.ts +84 -17
- package/dist/sdk-coding.js +1 -1
- package/dist/sdk-llm.d.ts +6 -6
- package/dist/sdk-llm.js +1 -1
- package/dist/sdk-mcp.js +1 -1
- package/dist/sdk-media.d.ts +1 -1
- package/dist/sdk-media.js +1 -1
- package/dist/sdk-repl.d.ts +13 -11
- package/dist/sdk-repl.js +2 -2
- package/dist/sdk-session.d.ts +7 -6
- package/dist/sdk-session.js +1 -1
- package/dist/sdk-skills.d.ts +4 -231
- package/dist/sdk-skills.js +1 -1
- package/dist/types-chunks/{base.d-BA9Doaj_.d.ts → base.d-DalIRhbb.d.ts} +1 -1
- package/dist/types-chunks/{bash-prefix-extractor.d-D3cddmyV.d.ts → bash-prefix-extractor.d-Ds1THKeH.d.ts} +88 -27
- package/dist/types-chunks/{capability-learning.d-DRV80ISB.d.ts → capability-learning.d-BQB0M70w.d.ts} +1 -1
- package/dist/types-chunks/{guardrail.d-iK7FwMdW.d.ts → guardrail.d-CdqJwwN7.d.ts} +3 -3
- package/dist/types-chunks/{process.d-DHow2y2G.d.ts → process.d-C93UMgPK.d.ts} +39 -6
- package/dist/types-chunks/{resolver.d-DDOfVYDr.d.ts → resolver.d-CGkfRULj.d.ts} +58 -4
- package/dist/types-chunks/{run-manager.d-ByDcJc5g.d.ts → run-manager.d-DLK3ed-T.d.ts} +5 -5
- package/dist/types-chunks/{sdk-session-21Tt3N_x.d.ts → sdk-session-CtwN7iBO.d.ts} +56 -8
- package/dist/types-chunks/{storage.d-BsZrBPYu.d.ts → storage.d-DlZS0g8w.d.ts} +2 -2
- package/dist/types-chunks/{types.d-Ci5YPFEh.d.ts → types.d-Bp4Lm1jv.d.ts} +37 -3
- package/dist/types-chunks/{types.d-D4ZA8LJV.d.ts → types.d-CSZAMmU-.d.ts} +4 -1
- package/dist/types-chunks/types.d-vJExiRje.d.ts +232 -0
- package/dist/types-chunks/{utils.d-BURxOxFd.d.ts → utils.d-Boz9k2HB.d.ts} +6 -5
- package/package.json +1 -1
- package/dist/chunks/argument-completer-QGBNXTYJ.js +0 -2
- package/dist/chunks/chunk-73Z7BK5H.js +0 -15
- package/dist/chunks/chunk-7QB55SYG.js +0 -326
- package/dist/chunks/chunk-CQ6EQG7E.js +0 -322
- package/dist/chunks/chunk-OBPB5BQ6.js +0 -310
- package/dist/chunks/chunk-P4VF3JEP.js +0 -7
- package/dist/chunks/chunk-PIQWODWN.js +0 -18
- package/dist/chunks/chunk-ZZDC75H4.js +0 -681
- package/dist/chunks/compaction-config-OPMRZSAK.js +0 -2
- package/dist/chunks/dist-JSE7NICF.js +0 -2
- package/dist/chunks/dist-SDNQOW52.js +0 -2
- package/dist/chunks/host-H7FQMMRC.js +0 -2
- package/dist/chunks/run-manager-4H5HWMVW.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,67 @@ All notable changes to this project will be documented in this file.
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.7.60] - 2026-07-04
|
|
10
|
+
|
|
11
|
+
> Scope note: an F250 refactor + Space SDK rollup. **FEATURE_250** brings the deferred-tool
|
|
12
|
+
> progressive-disclosure mechanism — previously SA-path-only — to the AMA/AMAW **managed** tool
|
|
13
|
+
> path, so cache-cold managed turns carry one-line search hints instead of full descriptions for
|
|
14
|
+
> the repo-intelligence + web/code/goal tools. Tool `input_schema` is unchanged, so every deferred
|
|
15
|
+
> tool stays directly callable; the full description is fetched on demand via `tool_search`.
|
|
16
|
+
> Transparent (no user-facing behavior change) and prompt-additive only (a two-line
|
|
17
|
+
> `code_search`/`semantic_lookup` teaching block). The release also lands **CAP-099 (Space SDK):
|
|
18
|
+
> live turn attribution + structured transcript** — streamed activity events carry session/turn
|
|
19
|
+
> identity, explicit turn-boundary events share one per-session sequence, and client-only
|
|
20
|
+
> transcript notices are persisted without ever entering the model context. All additive and
|
|
21
|
+
> profile/host-gated; the default path stays unchanged when a host does not read the new metadata.
|
|
22
|
+
> No public runtime type is removed.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **`code_search` / `semantic_lookup` teaching in the Worker REPO INTELLIGENCE prompt (FEATURE_250).** A two-line, eval-justified teaching block: the floor-tier alias under-adopted the hint-only tools on ambiguous tasks (75%), and the teaching recovered adoption to 100% while being strictly non-negative on every other alias.
|
|
27
|
+
- **CAP-099 live turn attribution — session/turn identity on streamed events (Space SDK).** A shared live-turn scope (`createLiveTurnScope` / `withLiveTurnAttribution`, `event-emitter.ts`) stamps `KodaXActivityEventMeta` (`sessionId` / `seq` / `turnId` / `deliveryId` / `timestamp`) onto every streamed activity callback, and explicit turn-boundary events (`emitTurnStarted` / `emitTurnCompleted` / `emitTurnFailed`) share one monotonic per-session sequence — so an SDK host can route streamed assistant events to the owning turn's UI bubble by turn ownership instead of fragile ordering-by-observation. Threaded through messaging (queue/drain), orchestration (idle-yield), run-substrate, runner-driven, run-workflow, and dispatch-child-tasks; a host that ignores the metadata sees unchanged behavior. New `cap-099-live-turn-attribution` contract test; existing `cap-005/006/007/041/046/054/086` event-contract tests updated for the added meta parameter.
|
|
28
|
+
- **Client-only transcript notices + structured transcript entries (CAP-099, Space SDK).** The persisted transcript gains structured entry types (`message` / `compaction` / `branch_summary` / `client_notice` / `task_result`) with `source` + `turnId`. A `client_notice` is persisted as a lineage entry, NOT a model message: `loadSession()` (active model context) omits it while `loadFullTranscript()` returns it with `type: 'client_notice'`, `source: 'client'`, and `payload.entersModelContext === false` — so a host can render client-side scrollback notices without polluting the model's context. SDK embedder guide updated (`docs/SDK_EMBEDDER_GUIDE.md`).
|
|
29
|
+
- **Transcript clone provenance for SDK hosts (CAP-099, Space SDK).** Lineage entries now carry optional `logicalId` / `sourceEntryId`, and `loadFullTranscript().transcriptEntries[]` always exposes a stable `logicalId` (falling back to `entryId` for old sessions). Forked/cloned entries keep the source `logicalId` and point `sourceEntryId` at the root physical source entry, so hosts can fold cloned history precisely without guessing from role/content/timestamp or `[compacted]` placeholders. `loadFullTranscript()` remains raw append-order scrollback; it does not silently merge branches or hide compaction notices.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **Progressive disclosure on the AMA/AMAW managed tool path (FEATURE_250).** `buildAgentToolsFromRegistry` (`agent-chain.ts`) now hint-swaps the 13 non-mcp deferred tools — repo-intel (`repo_overview`, `changed_scope`, `module_context`, `symbol_context`, `process_context`, `impact_estimate`), web/code (`web_search`, `web_fetch`, `code_search`, `semantic_lookup`), and goal (`get_goal`, `create_goal`, `update_goal`) — to their `DEFERRED_TOOL_HINTS` one-liner. The swap is a one-time build-time change (the managed `Agent.tools` is a static array), so the tools[] prefix is cache-stable turn-to-turn. `mcp_*` (5) stay resident (remote-mutation risk + not covered by the reachability eval; conservative hold gated on a future MCP-runtime eval); `run_workflow` is untouched (host-conditional per FEATURE_246/249). Two eval panels (5-alias coding-plan) confirm no reachability harm: DEFER_SAFE 5/5, 0% read/grep fallback, and V_teach 100% adoption on ambiguous tasks. KodaX's hint-swap keeps the tool in `tools[]` with `input_schema` intact — safer than the reference agents (Claude Code / Codex) which remove deferred tools from the wire and therefore gate deferral off for weak models.
|
|
34
|
+
- **Inline workflow preflight hardening (FEATURE_246).** The inline `run_workflow` restricted-smoke preflight now rejects two more classes of weak-model authoring bug before a workflow starts: (1) an unawaited `wf.runAgent` / `wf.synthesize` result that leaks into a property read, JSON serialization, or assignment — a Proxy trap throws `wf.<method> result must be awaited before …` instead of silently coercing a pending command; and (2) a `manifest.readOnly=true` workflow that spawns a write-capable child (`readOnly:false`) — it now throws at preflight instead of running. This is the deterministic-structural groundwork for the planned FEATURE_252 workflow-quality lints (v0.7.61).
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- **`tool_search` result protected from microcompaction pruning (FEATURE_250).** `tool_search` is added to `PRUNE_PROTECTED_TOOLS` (`compaction.ts`). On the managed path a deferred tool's full description lives only in the `tool_search` result message (the static `Agent.tools` array cannot make a description resident mid-session), so the unconditional 20-turn prune would otherwise silently stub the only teaching surface for any non-prompt-taught deferral.
|
|
39
|
+
- **Headless SDK resume recovers `<task-completed>` results + per-message timestamps (Space SDK).** Two resume/persistence fixes for headless SDK embedders; the KodaX TUI is byte-unchanged. (1) `dispatch_child_task` / `run_workflow` `<task-completed>` result banners are spliced into the transcript as synthetic user messages that the reconstruction helper drops, so a headless host with no `uiHistory` lost them on resume — they are now tagged `_source: 'task-completed'` (only when a task-notification actually drained) and restored as a distinct `task_completed` event seed at their transcript position; when `uiHistory` is present the derived seed is discarded, so the CLI does not double-render. (2) `KodaXMessage` carried no time, so `createSessionLineage` stamped a whole managed task's messages with one accounting-millisecond and per-message "N ago" footers collapsed — an additive `KodaXMessage.timestamp?` is now stamped at each message-finalization site and preferred by `createSessionLineage`. The dedup fingerprint ignores timestamp (resume dedup unaffected); old sessions fall back to accounting-time.
|
|
40
|
+
- **Goal-state tool results protected from microcompaction pruning.** `get_goal` / `create_goal` / `update_goal` are added to `PRUNE_PROTECTED_TOOLS` (`compaction.ts`) alongside `tool_search`. The canonical goal state persists as session-lineage entries, but these tool results are the model-visible status snapshots and lifecycle-transition receipts (short, low-frequency, control-plane-like), so microcompaction's 20-turn prune no longer stubs the model's view of `/goal` state. (v0.7.60 review follow-up.)
|
|
41
|
+
|
|
42
|
+
## [0.7.59] - 2026-07-03
|
|
43
|
+
|
|
44
|
+
> Scope note: a rollup release on top of v0.7.58. **FEATURE_248** and **FEATURE_249** extend
|
|
45
|
+
> workflow *activation*: the AMAW Worker now carries a mode-level standing directive that
|
|
46
|
+
> defaults substantive work to orchestrating cross-checking agents, and AMA can activate
|
|
47
|
+
> `run_workflow` from an explicit natural-language request. The release also lands the Space SDK
|
|
48
|
+
> R1-R6 capability hardening, an ark-coding lineup refresh, and several workflow-runtime + SDK
|
|
49
|
+
> parity fixes. All prompt-only / additive; no public runtime type is removed.
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- **AMA natural-language workflow activation (FEATURE_249).** `buildWorkflowToolHost` is widened so AMA — not only AMAW — hosts the `run_workflow` tool. AMA activates it on an explicit natural-language request (the tool is available and LLM-native, with no standing directive); AMAW additionally self-activates on complexity via the FEATURE_248 directive. SA is unchanged (fails the gate + `SA_SOLO_EXCLUDE_TOOLS`). The F248 directive stays strictly AMAW-only through an independent `amawOrchestrationAvailable` gate that is structurally separate from the tool host.
|
|
54
|
+
- **Host-facing Worker workflow-authoring entrypoint + resume replay telemetry (Space SDK R1/R2).** A non-coding SDK host can drive the scout-then-author Worker authoring path directly, and same-session resume now emits replay telemetry (an `agent_replayed` event) so a host can observe cache hits when a run resumes.
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- **AMAW mode-level `ORCHESTRATION DEFAULT` standing directive (FEATURE_248, prompt-only).** The Worker system prompt gains an AMAW-gated standing directive (mirroring the reference "ultracode" mechanism): substantive work — a multi-file investigation, a design/architecture decision, anything costly to get wrong — defaults to orchestrating multiple cross-checking agents rather than working it alone end to end, while trivial and conversational turns stay solo. A **PLAN-TIME COMMITMENT** flow-fix front-loads the orchestrate-vs-solo call to turn 0 and makes plan items the agents/stages to dispatch. Leak-closed via a new optional `ManagedRolePromptContext.amawOrchestrationAvailable` field, so AMA and SA prompts stay byte-identical. Narrowed-SHIP: acceptance is task-inception activation; mid-task re-architecture is a documented non-goal, and absolute activation is model-ceiling-limited on current coding-plan aliases.
|
|
59
|
+
- **Space SDK capability hardening (R1-R6).** Per an adversarial review of the six Space SDK capabilities: model-level overrides are honored on the default model and a `resolveWireEffort` helper is added; LLM-triggered skill dynamic-context is routed through the host policy (R4); a rejected `reasoning_effort` self-heals across turns (R5); plus the host-facing authoring entrypoint and resume-replay telemetry (R1/R2) noted above.
|
|
60
|
+
- **ark-coding lineup refreshed to Ark's official model catalog.**
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
|
|
64
|
+
- **Workflow `tokenBudget` of `0` / `null` / negative now means unbounded** instead of being clamped to a 1-token budget — expressing "no limit" as `0` from one of a host's launch paths previously wedged the whole run. `maxAgents` / `maxConcurrency` keep their count floor of 1.
|
|
65
|
+
- **The built-in parallel-investigation workflow reads structured child findings instead of the timing-fragile `finalText`.** A child's smart digest is delivered asynchronously (after its terminal event), so a synthesis step could receive empty findings ("总评:(无) / 发现:无"); it now reads the structured result.
|
|
66
|
+
- **Authored + generated workflows read `result.structured`, not the top-level result or `finalText` (KodaX-Space).** Both authoring surfaces — the `run_workflow` tool description and the blind generator prompt — are taught to read a child's validated object off `result.structured` (a review workflow that declared an `outputSchema` but read fields off the top-level result produced an empty report). The sandbox source policy also now preserves `${...}` interpolation inside template literals so a `${process.cwd()}` no longer evades the forbidden-pattern scan and crashes at runtime, bans computed `globalThis[...]` access, and `wf.log` tolerates a bare string.
|
|
67
|
+
- **The Sidecar Verifier's feedback renders under its own identity, not `[Evaluator]`.** Three UI seams surfaced the legacy `evaluator` role name as a phantom `[Evaluator]` agent (status-line label-lag on a revise, the persisted transcript, and the restored synthetic sidecar message on `kodax -c`); all three now attribute to the `⚡ Sidecar Verifier` identity.
|
|
68
|
+
- **`getCustomProviderModelDescriptors` honors a `models[]` override on the default model.** The custom-provider descriptor-listing SDK surface returned a bare `{id}` descriptor for a custom provider's default model even when it had a `models[]` entry (context window / max output / reasoning profile), disagreeing with `getCustomModelCapabilities`; both SDK surfaces now agree (R3 regression test added).
|
|
69
|
+
|
|
9
70
|
## [0.7.58] - 2026-07-02
|
|
10
71
|
|
|
11
72
|
> Scope note: a feature + hardening release. **FEATURE_246** delivers Claude-Code-harness
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square"></a>
|
|
18
18
|
<a href="https://github.com/icetomoyo/KodaX/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/icetomoyo/KodaX?style=flat-square&logo=github&color=f1c40f"></a>
|
|
19
19
|
<a href="https://github.com/icetomoyo/KodaX/actions"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/icetomoyo/KodaX/release.yml?style=flat-square&label=release"></a>
|
|
20
|
-
<img alt="providers" src="https://img.shields.io/badge/LLMs-
|
|
20
|
+
<img alt="providers" src="https://img.shields.io/badge/LLMs-15_aliases_+_custom-2ecc71?style=flat-square">
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
<p align="center">
|
|
@@ -396,7 +396,7 @@ KodaX has two layers that consumers should understand separately:
|
|
|
396
396
|
| `packages/agent` | `@kodax-ai/kodax/mcp` | **Narrow subset** | MCP only — `McpCapabilityProvider` / `createMcpTransport` / `searchMcpCatalog` / ... (11 exports = pre-v0.7.43 `@kodax-ai/mcp` complete API) | MCP server hosts |
|
|
397
397
|
| `packages/coding` | `@kodax-ai/kodax/coding` | Full package | Coding agent + 50+ tools + repo-intelligence (342 exports) | Build a Claude Code-shape product |
|
|
398
398
|
| `packages/repl` | `@kodax-ai/kodax/repl` | Full package | Ink TUI + permission modes + commands (193 exports) | Terminal-UI consumers |
|
|
399
|
-
| `packages/repl` | `@kodax-ai/kodax/session` | **Narrow subset** | Session management only — `listSessions` / `forkSession` / `watchSessions` / ...
|
|
399
|
+
| `packages/repl` | `@kodax-ai/kodax/session` | **Narrow subset** | Session management only — `listSessions` / `loadFullTranscript` / `appendClientNotice` / `forkSession` / `watchSessions` / ... | IDE plugins and desktop hosts reading session history |
|
|
400
400
|
|
|
401
401
|
**Rule of thumb**: if you need Runner / Agent / fan-out, import from `/agent`. If you only need skills or mcp APIs, import from `/skills` or `/mcp` to get a smaller bundle. The narrow subsets are subsets of the full packages — they do **not** expose extra symbols.
|
|
402
402
|
|
|
@@ -404,7 +404,13 @@ KodaX has two layers that consumers should understand separately:
|
|
|
404
404
|
|
|
405
405
|
**Workflow Process Surface (FEATURE_229, v0.7.50)**: workflow progress is now a reusable Agent-layer process contract rather than private REPL text. SDK hosts can subscribe to `WorkflowProcessEvent`/poll `WorkflowProcessSnapshot`, use `createWorkflowRunManager` and `createWorkflowLifecycleController` for stop/pause/resume/result/artifact/delete/prune/identity/preflight controls, and receive ANSI-free provenance fields (`source`, `sourceRunId`, `sourceWorkflowName`, `savedWorkflowName`, `revisionOf`) plus `resultSummary`. `/coding` owns the coding workflow backend and run graph, `/repl` renders the same snapshots, and the terminal UI is not the hidden source of truth. `KodaXEvents` callbacks also take an optional metadata arg (`KodaXToolEventMeta` / `KodaXActivityEventMeta` / `KodaXWorkflowEventMeta`) so a host can attribute every child-agent tool/thinking/progress event to its workflow run and child id without a second event protocol, and generated/saved workflow scripts pass `validateRestrictedWorkflowSource` (compile + source-policy check) plus a generator repair/smoke loop before they run. See [docs/ADR.md ADR-040](docs/ADR.md) for the layering rationale.
|
|
406
406
|
|
|
407
|
-
**Host Reads Persisted History (FEATURE_230 + FEATURE_234, v0.7.51)**:
|
|
407
|
+
**Host Reads Persisted History (FEATURE_230 + FEATURE_234, v0.7.51)**: additive closures for hosts that read persisted state. **Durable tool transcript replay** — a resumed session now replays the tool cards the assistant used instead of degrading to text-only. `messages` / `lineage` stay canonical; `SessionData.uiHistory` becomes a bounded, sanitized, terminal-only replay cache. The SDK transcript contract is explicit: `loadSession()` = active model context, `loadFullTranscript()` = append-order host scrollback with typed entries (`message` / `compaction` / `branch_summary` / `client_notice` / `task_result`) plus clone provenance (`logicalId` / `sourceEntryId`), `uiHistory` = optional replay cache, and tool cards can always be reconstructed from canonical messages. Hosts can persist local slash output with `appendClientNotice()` without entering model context, and workflow/child completions expose structured `taskResults[]` instead of requiring `<task-completed>` parsing. **Workflow run host attribution** — `WorkflowProcessTrackerOptions` / `WorkflowProcessSnapshot` gain a host-owned opaque `hostMetadata?: Record<string, string>` that the SDK stores, persists to `run.json`, and echoes back (including after a restart) without interpreting it, so a host can map a run to the session/surface that launched it with zero side table. Unstamped/legacy runs honestly echo `hostMetadata === undefined`. See [docs/features/v0.7.51.md](docs/features/v0.7.51.md).
|
|
408
|
+
|
|
409
|
+
**Inline Workflow Authoring (FEATURE_246, v0.7.58)**: in AMA/AMAW the Worker can now author and run a workflow inline via a model-callable `run_workflow` tool — it scouts the codebase with its own tools first, then bakes concrete findings into each child prompt, and runs the script through the **unchanged** sandbox + static-validation + postcondition-verification pipeline. This replaces the context-blind `sideQuery` generator as the primary interactive path (the generator survives only as a fallback for the explicit `/workflow create` command and non-interactive / CI hosts that have no investigating Worker). It adds structured child output (`outputSchema`), the no-barrier `wf.pipeline` staged primitive, same-session resume (`resumeFromRunId`), nested `wf.workflow(...)`, and a `/workflow create` redirect to Worker-authored scouting; `run_workflow` is async / idle-yield so the turn is not blocked. The neutral run-lifecycle manager (`createWorkflowRunManager` / `getDefaultWorkflowRunManager`) now lives in `@kodax-ai/kodax/agent` for non-coding SDK hosts. See [docs/features/v0.7.58.md](docs/features/v0.7.58.md) and [docs/ADR.md](docs/ADR.md) ADR-044/046/047/048/049.
|
|
410
|
+
|
|
411
|
+
**Workflow Activation Tiers (FEATURE_248 + FEATURE_249, v0.7.59)**: the three agent modes now have a coherent workflow posture. **AMAW** carries a mode-level `ORCHESTRATION DEFAULT` standing directive (mirroring the reference "ultracode" posture): substantive work — a multi-file investigation, a design decision, anything costly to get wrong — defaults to orchestrating multiple cross-checking agents, with a PLAN-TIME COMMITMENT flow-fix that front-loads the orchestrate-vs-solo call to turn 0. **AMA** hosts the same `run_workflow` tool but with no standing directive — it activates a workflow when you ask for orchestration in natural language, never on complexity alone. **SA** stays solo. The directive is leak-closed via `amawOrchestrationAvailable`, so AMA and SA prompts stay byte-identical. See [docs/features/v0.7.59.md](docs/features/v0.7.59.md).
|
|
412
|
+
|
|
413
|
+
**Progressive Disclosure on the Managed Tool Path (FEATURE_250, v0.7.60)**: the deferred-tool progressive-disclosure mechanism — previously SA-path-only — now applies to the AMA/AMAW **managed** path too. Cache-cold managed turns carry one-line search hints instead of full descriptions for the 13 non-mcp deferred tools (repo-intelligence + web/code + goal); each tool's `input_schema` is unchanged, so it stays directly callable and the full description is fetched on demand via `tool_search`. `mcp_*` stay resident and `run_workflow` is untouched. Transparent to users; validated by two 5-alias eval panels (DEFER_SAFE 5/5, 0% read/grep fallback). See [docs/features/v0.7.60.md](docs/features/v0.7.60.md).
|
|
408
414
|
|
|
409
415
|
---
|
|
410
416
|
|
|
@@ -984,7 +990,7 @@ await runInkInteractiveMode({ provider: 'zhipu-coding', effort: 'auto' });
|
|
|
984
990
|
| minimax-coding | `MINIMAX_CODING_API_KEY` | Native | MiniMax-M2.7 (`MiniMax-M3` Frontier Coding, native multimodal + 1M ctx, plus `MiniMax-M2.7-highspeed` via `/model`) |
|
|
985
991
|
| mimo | `MIMO_API_KEY` | Native | mimo-v2.5-pro (Xiaomi MiMo pay-per-token, Anthropic-compat) |
|
|
986
992
|
| mimo-coding | `MIMO_CODING_API_KEY` | Native | mimo-v2.5-pro (Xiaomi Token Plan, Anthropic-compat) |
|
|
987
|
-
| ark-coding | `ARK_CODING_API_KEY` | Native | glm-5.
|
|
993
|
+
| ark-coding | `ARK_CODING_API_KEY` | Native | glm-5.2 (Volcengine Ark Coding Plan — GLM-5.2 (alias: `glm-latest`) · Kimi K2.7 Code / K2.6 · MiniMax M3 / M2.7 · DeepSeek V4 Pro / V4 Flash · Doubao Seed 2.0 Code / Pro / Lite · Doubao Seed Code) |
|
|
988
994
|
| deepseek | `DEEPSEEK_API_KEY` | Native | deepseek-v4-flash (`deepseek-v4-pro` via `/model`) |
|
|
989
995
|
| gemini-cli | `GEMINI_API_KEY` | Prompt-only / CLI bridge | (via gemini CLI) |
|
|
990
996
|
| codex-cli | `OPENAI_API_KEY` | Prompt-only / CLI bridge | (via codex CLI) |
|
|
@@ -1073,6 +1079,7 @@ KodaX ships 50+ built-in tools, grouped below. They are registered as a single f
|
|
|
1073
1079
|
| `task_stop` | Request graceful exit of a specific child. Current tool finishes atomically, then the child sees a `<coordinator-stop-request>` and emits a final summary. Coordinator-only. (FEATURE_120, v0.7.39) |
|
|
1074
1080
|
| `ask_user_question` | Single/multi-select or free-text prompt back to the user |
|
|
1075
1081
|
| `exit_plan_mode` | Present a finalized plan for approval (REPL only) |
|
|
1082
|
+
| `run_workflow` | Author and run a workflow script inline. Hosted in AMAW (self-activates on complexity via the ORCHESTRATION DEFAULT directive) and AMA (activates on an explicit natural-language request); not in SA. Scouts the codebase first, then bakes findings into child prompts; structured output via `outputSchema`, same-session `resumeFromRunId`, nested `wf.workflow(...)`. Async / idle-yield. (FEATURE_246 v0.7.58; FEATURE_248/249 v0.7.59) |
|
|
1076
1083
|
| `emit_managed_protocol` | Internal managed-task protocol side-channel for role payloads (verdict). V2 Worker single-loop + Sidecar Verifier is the default since v0.7.42 (FEATURE_184); V1 chain retired in v0.7.43 (FEATURE_193). |
|
|
1077
1084
|
|
|
1078
1085
|
---
|
package/README_CN.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square"></a>
|
|
18
18
|
<a href="https://github.com/icetomoyo/KodaX/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/icetomoyo/KodaX?style=flat-square&logo=github&color=f1c40f"></a>
|
|
19
19
|
<a href="https://github.com/icetomoyo/KodaX/actions"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/icetomoyo/KodaX/release.yml?style=flat-square&label=release"></a>
|
|
20
|
-
<img alt="providers" src="https://img.shields.io/badge/LLMs-
|
|
20
|
+
<img alt="providers" src="https://img.shields.io/badge/LLMs-15_aliases_+_custom-2ecc71?style=flat-square">
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
<p align="center">
|
|
@@ -390,7 +390,7 @@ dist/binary/linux-x64/
|
|
|
390
390
|
| minimax-coding | `MINIMAX_CODING_API_KEY` | Native | MiniMax-M2.7(可 `/model` 切换 `MiniMax-M3` Frontier Coding,原生多模态 + 1M ctx;以及 `MiniMax-M2.7-highspeed`) |
|
|
391
391
|
| mimo | `MIMO_API_KEY` | Native | mimo-v2.5-pro(小米 MiMo 按量计费,Anthropic 协议) |
|
|
392
392
|
| mimo-coding | `MIMO_CODING_API_KEY` | Native | mimo-v2.5-pro(小米 MiMo Token Plan,Anthropic 协议) |
|
|
393
|
-
| ark-coding | `ARK_CODING_API_KEY` | Native | glm-5.
|
|
393
|
+
| ark-coding | `ARK_CODING_API_KEY` | Native | glm-5.2(火山方舟 Coding Plan — GLM-5.2(别名 `glm-latest`) · Kimi K2.7 Code / K2.6 · MiniMax M3 / M2.7 · DeepSeek V4 Pro / V4 Flash · Doubao Seed 2.0 Code / Pro / Lite · Doubao Seed Code) |
|
|
394
394
|
| deepseek | `DEEPSEEK_API_KEY` | Native | deepseek-v4-flash(可 `/model` 切换 `deepseek-v4-pro`) |
|
|
395
395
|
| gemini-cli | `GEMINI_API_KEY` | Prompt-only / CLI bridge | (通过 gemini CLI) |
|
|
396
396
|
| codex-cli | `OPENAI_API_KEY` | Prompt-only / CLI bridge | (通过 codex CLI) |
|
|
@@ -500,13 +500,19 @@ KodaX 有两层结构,SDK 用户需要分开理解:
|
|
|
500
500
|
| `packages/agent` | `@kodax-ai/kodax/mcp` | **窄子集** | 仅 MCP —— `McpCapabilityProvider` / `createMcpTransport` / `searchMcpCatalog` 等 (11 exports = v0.7.43 之前 `@kodax-ai/mcp` 完整 API) | MCP server 宿主 |
|
|
501
501
|
| `packages/coding` | `@kodax-ai/kodax/coding` | 完整包 | Coding agent + 50+ 工具 + repo-intelligence (342 exports) | 构建 Claude Code 形态产品 |
|
|
502
502
|
| `packages/repl` | `@kodax-ai/kodax/repl` | 完整包 | Ink TUI + 权限模式 + 命令系统 (193 exports) | 终端 UI 消费者 |
|
|
503
|
-
| `packages/repl` | `@kodax-ai/kodax/session` | **窄子集** | 仅会话管理 —— `listSessions` / `forkSession` / `watchSessions` 等
|
|
503
|
+
| `packages/repl` | `@kodax-ai/kodax/session` | **窄子集** | 仅会话管理 —— `listSessions` / `loadFullTranscript` / `appendClientNotice` / `forkSession` / `watchSessions` 等 | 读取 session 历史的 IDE 插件和桌面宿主 |
|
|
504
504
|
|
|
505
505
|
**经验法则**:需要 Runner / Agent / fan-out 时从 `/agent` 引入;只需要 skills 或 mcp API 时从 `/skills` 或 `/mcp` 引入,bundle 更小。窄子集是完整包的真子集 —— **不会**有额外符号。
|
|
506
506
|
|
|
507
507
|
**Workflow process surface(FEATURE_229,v0.7.50)**:动态工作流不再只是 REPL 私有文本,而是 Agent 层可复用的 process/event/snapshot 契约。SDK 宿主可以订阅 `WorkflowProcessEvent`、轮询 `WorkflowProcessSnapshot`,并通过 `createWorkflowRunManager` / `createWorkflowLifecycleController` 做 stop/pause/resume、读取 final result/artifact、删除/清理 terminal runs、管理 workflow identity/preflight。`/coding` 负责 coding workflow backend 与 run graph,`/repl` 只是消费同一份 snapshot 渲染 UI;SDK 不需要解析 slash-command 输出或 Ink view-model。`KodaXEvents` 回调新增可选 meta 尾参(`KodaXToolEventMeta` / `KodaXActivityEventMeta` / `KodaXWorkflowEventMeta`),宿主据此把每个子 Agent 的 tool/thinking/progress 事件归因到对应 workflow run 与 child id,无需第二套事件协议;生成/保存的工作流脚本在运行前过 `validateRestrictedWorkflowSource`(编译 + 源策略检查)与 generator 的 repair/smoke 循环。分层取舍见 [docs/ADR.md ADR-040](docs/ADR.md)。
|
|
508
508
|
|
|
509
|
-
**宿主读持久化历史(FEATURE_230 + FEATURE_234,v0.7.51
|
|
509
|
+
**宿主读持久化历史(FEATURE_230 + FEATURE_234,v0.7.51)**:面向「宿主读持久化状态」的 additive 闭环。**持久化工具记录回放**——resume 的会话现在会回放助手用过的工具卡片,而不是退化成纯文本。`messages` / `lineage` 仍是 canonical;`SessionData.uiHistory` 成为有界、脱敏、仅 terminal 状态的回放缓存。SDK transcript 契约明确化:`loadSession()` = 活动 model context,`loadFullTranscript()` = 带结构化条目的追加序 host scrollback(`message` / `compaction` / `branch_summary` / `client_notice` / `task_result`)并带 clone provenance(`logicalId` / `sourceEntryId`),`uiHistory` = 可选回放缓存,工具卡片始终可从 canonical messages 重建。宿主可用 `appendClientNotice()` 持久化本地 slash 输出且不进入模型上下文;workflow/child 完成结果通过结构化 `taskResults[]` 暴露,不再要求解析 `<task-completed>` 文本。**Workflow run 宿主归属**——`WorkflowProcessTrackerOptions` / `WorkflowProcessSnapshot` 新增 host-owned 不透明 `hostMetadata?: Record<string, string>`,SDK 存储、持久化进 `run.json`、回读回显(含进程重启后)但不解释其含义,让宿主零侧表把 run 归回发起它的 session/surface。未 stamp 的旧 run 诚实回显 `hostMetadata === undefined`。详见 [docs/features/v0.7.51.md](docs/features/v0.7.51.md)。
|
|
510
|
+
|
|
511
|
+
**Inline workflow authoring(FEATURE_246,v0.7.58)**:AMA/AMAW 下 Worker 现在可通过 model-callable 的 `run_workflow` 工具在会话内直接编写并运行工作流——先用自己的工具 scout 代码库,再把具体发现烤进每个 child prompt,然后走**不变的** sandbox + 静态校验 + postcondition 验证流水线。它取代 context-blind 的 `sideQuery` generator 成为主交互路径(generator 仅作为显式 `/workflow create` 命令与无 investigating Worker 的 non-interactive/CI 主机的 fallback 保留);新增结构化 child 输出(`outputSchema`)、无 barrier 的 `wf.pipeline` 分阶段原语、同会话 resume(`resumeFromRunId`)、嵌套 `wf.workflow(...)`,`/workflow create` 重定向到 Worker 的 scout-then-author;`run_workflow` 为 async / idle-yield,不阻塞当前轮。中立的 run-lifecycle manager(`createWorkflowRunManager`)已移入 `@kodax-ai/kodax/agent` 供非 coding SDK 宿主使用。详见 [docs/features/v0.7.58.md](docs/features/v0.7.58.md) 与 [docs/ADR.md](docs/ADR.md) ADR-044/046/047/048/049。
|
|
512
|
+
|
|
513
|
+
**工作流激活分层(FEATURE_248 + FEATURE_249,v0.7.59)**:三种 agent 模式现在有一致的工作流姿态。**AMAW** 携带 mode-level 的 `ORCHESTRATION DEFAULT` 常驻指令(对齐参考实现的 "ultracode" 姿态):实质性工作——多文件调查、设计决策、任何做错代价高的任务——默认编排多个交叉验证的 agent,并有 PLAN-TIME COMMITMENT 流程修正把 orchestrate-vs-solo 决策前置到第 0 轮。**AMA** 同样 host `run_workflow` 工具但没有常驻指令——当你用自然语言请求编排时才激活,绝不因复杂度独自触发。**SA** 保持单独作业。该指令通过 `amawOrchestrationAvailable` 关闭泄漏,因此 AMA 与 SA 的 prompt 保持逐字节一致。详见 [docs/features/v0.7.59.md](docs/features/v0.7.59.md)。
|
|
514
|
+
|
|
515
|
+
**managed 工具路径的渐进披露(FEATURE_250,v0.7.60)**:deferred-tool 渐进披露机制——此前仅 SA path 拥有——现在也应用于 AMA/AMAW 的 **managed** path。缓存冷启的 managed 轮次对 13 个 non-mcp 延迟工具(repo-intelligence + web/code + goal)携带一行 search hint 而非完整描述;每个工具的 `input_schema` 不变,因此仍可直接调用,完整描述按需通过 `tool_search` 拉取。`mcp_*` 保持常驻,`run_workflow` 不动。对用户透明;由两个 5-alias eval panel 验证(DEFER_SAFE 5/5,0% read/grep 回退)。详见 [docs/features/v0.7.60.md](docs/features/v0.7.60.md)。
|
|
510
516
|
|
|
511
517
|
```
|
|
512
518
|
KodaX/ # 4 workspace packages(FEATURE_194 v0.7.43)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @kodax-ai/kodax — bundled distribution. See docs/ADR.md ADR-022 + ADR-024.
|
|
2
|
-
import{I as c,J as d,K as e,L as f,Z as g,_ as h,ia as i,oa as j}from"./chunk-
|
|
2
|
+
import{I as c,J as d,K as e,L as f,Z as g,_ as h,ia as i,oa as j}from"./chunk-ZPD7IUKW.js";import"./chunk-D6QVXQNI.js";import"./chunk-UA744TZM.js";import"./chunk-QFCF3GNT.js";import"./chunk-S4GVQO3W.js";import{mb as a,nb as b}from"./chunk-4K5BDO7S.js";import"./chunk-ZL5CEANW.js";import"./chunk-V4WSBIXB.js";export{d as bucketProviderPayloadSize,g as buildAutoRepoIntelligenceContext,e as checkPromiseSignal,b as cleanupIncompleteToolCalls,h as describeTransientProviderRetry,f as emitResilienceDebug,c as estimateProviderPayloadBytes,j as runKodaX,i as saveSessionSnapshot,a as validateAndFixToolHistory};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @kodax-ai/kodax — bundled distribution. See docs/ADR.md ADR-022 + ADR-024.
|
|
2
|
+
import{Aa as b,za as a}from"./chunk-6DWXUZMO.js";import"./chunk-SGNM3UP6.js";import"./chunk-5TRQBMPR.js";import"./chunk-XULI4U7I.js";import"./chunk-U6BNMGSK.js";import"./chunk-2RLIKZOZ.js";import"./chunk-ZPD7IUKW.js";import"./chunk-D6QVXQNI.js";import"./chunk-UA744TZM.js";import"./chunk-QFCF3GNT.js";import"./chunk-S4GVQO3W.js";import"./chunk-4K5BDO7S.js";import"./chunk-ZL5CEANW.js";import"./chunk-V4WSBIXB.js";export{a as ArgumentCompleter,b as createArgumentCompleter};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// @kodax-ai/kodax — bundled distribution. See docs/ADR.md ADR-022 + ADR-024.
|
|
2
|
+
import{Ab as Te,Bb as X,Cb as Ee,Db as Ae,Fa as We,Jc as Pe,Kc as Oe}from"./chunk-QFCF3GNT.js";import{N as ge}from"./chunk-S4GVQO3W.js";import{Va as G,Zd as ve,_d as Se,ae as F,ce as z,db as ye,ie as J,je as W,ke as H,le as xe,se as Me,te as Re,ue as be}from"./chunk-4K5BDO7S.js";import{B as ke}from"./chunk-ZL5CEANW.js";import{a}from"./chunk-V4WSBIXB.js";import{basename as bn,dirname as Wn}from"node:path";import{execFile as yt}from"node:child_process";import j from"node:path";import{promisify as vt}from"node:util";var St=vt(yt),xt=1e4,De=2,Fe=new Set(["write","edit","multi_edit","insert_after_anchor"]),Mt=/^\s*(?:let me|i will|i'll|i am going to)\b[\s\S]{0,120}\b(?:start|create|implement|write|build|plan)\b|^\s*(?:我将|让我|接下来)[\s\S]{0,80}(?:开始|创建|编写|实现|制定)/i;function Rt(e){if(e?.timeoutMs!==void 0){if(!Number.isFinite(e.timeoutMs)||e.timeoutMs<=0)throw new Error("workflow wait timeoutMs must be a positive number");return Math.floor(e.timeoutMs)}}a(Rt,"normalizeWaitTimeoutMs");function Y(e){return e?.requiresMutation===!0||(e?.requiredChangedPaths?.length??0)>0}a(Y,"hasVerificationWork");function T(e){return e.replace(/\\/g,"/").replace(/^\.\//,"").trim()}a(T,"normalizeWorkspacePath");function bt(e,t){let n=t.gitRoot?j.resolve(t.gitRoot):void 0,o=j.isAbsolute(e)&&n?j.relative(n,j.resolve(e)):e;return T(o)}a(bt,"normalizeRequiredPath");function Wt(e){let t=(e.readOnly??!1)===!1?{enforcement:"warn",requiresMutation:!0,rejectPreparatoryFinalText:!0}:void 0;if(e.verification!==void 0){let n={...t??{},...e.verification,enforcement:e.verification.enforcement??"hard"},o=e.verification.requiredChangedPaths;return{verification:{...n,...o!==void 0&&o.length>0&&n.requiresMutation===void 0?{requiresMutation:!0}:{}}}}return{verification:t}}a(Wt,"resolveVerificationForInput");function Tt(e,t){if(t===!0&&e.readOnly===!1)throw new Error(`workflow manifest readOnly=true cannot spawn write-capable child "${e.name}"; set the workflow manifest readOnly=false or use child readOnly:true`);let n=e.readOnly??t??!1;return e.readOnly===n?e:{...e,readOnly:n}}a(Tt,"resolveSpawnAgentInput");function _e(e){let t=e.trim();return t.length>0&&Mt.test(t)}a(_e,"isPreparatoryOnlyText");function Et(e,t){let n=e.trim(),o=t?.trim();return o&&(n.length===0||_e(n))?o:e}a(Et,"selectWorkflowFinalText");async function B(e,t){return(await St("git",[...e],{cwd:t,timeout:xt,windowsHide:!0,maxBuffer:4194304})).stdout.toString()}a(B,"runGit");async function At(e){let t=e.gitRoot??e.executionCwd??process.cwd(),n=(await B(["rev-parse","--show-toplevel"],t)).trim(),o=await Promise.all([B(["diff","--name-only","--"],n),B(["diff","--cached","--name-only","--"],n),B(["ls-files","--others","--exclude-standard"],n)]);return[...new Set(o.flatMap(i=>i.split(/\r?\n/)).map(T).filter(i=>i.length>0))]}a(At,"listGitChangedFiles");async function Z(e,t){try{return{paths:(await t(e)).map(T).filter(o=>o.length>0)}}catch(n){return{paths:[],error:n instanceof Error?n.message:String(n)}}}a(Z,"captureChangedPaths");function Pt(){return{toolNameById:new Map,toolPathById:new Map,succeededToolCalls:[],succeededPaths:[]}}a(Pt,"createMutationRecorder");function Ot(e){if(e)for(let t of["path","file_path","target_path"]){let n=e[t];if(typeof n=="string"&&n.trim().length>0)return T(n)}}a(Ot,"readMutationPath");function Ft(e,t){return{...e??{},onToolUseStart:a((n,o)=>{if(Fe.has(n.name)){t.toolNameById.set(n.id,n.name);let i=Ot(n.input);i!==void 0&&t.toolPathById.set(n.id,i)}e?.onToolUseStart?.(n,o)},"onToolUseStart"),onToolResult:a((n,o)=>{let i=t.toolNameById.get(n.id)??n.name;if(Fe.has(i)&&!n.content.trimStart().startsWith("[Tool Error]")){t.succeededToolCalls.push(i);let r=t.toolPathById.get(n.id);r!==void 0&&t.succeededPaths.push(r)}e?.onToolResult?.(n,o)},"onToolResult")}}a(Ft,"wrapEventsForMutationRecording");function Q(e){return[...new Set(e.filter(t=>t.trim().length>0))]}a(Q,"uniqueItems");function Ie(e){let t=e.verification;if(!t)return;let n=[],o=new Set(e.before.paths.map(T)),i=Q(e.after.paths.map(T)),r=i.filter(m=>!o.has(m)),s=Q(e.mutationRecorder.succeededToolCalls),c=e.acceptToolMutationEvidence?s:[],p=e.acceptToolMutationEvidence?Q(e.mutationRecorder.succeededPaths.map(T)):[],l=r.length>0||c.length>0,h=t.enforcement??"hard",v=(t.requiredChangedPaths??[]).map(m=>bt(m,e.ctx));t.requiresMutation===!0&&(e.before.error!==void 0||e.after.error!==void 0?n.push(`workspace mutation verification could not read changed files: ${e.after.error??e.before.error}`):l||n.push(e.acceptToolMutationEvidence||s.length===0?"expected file mutations, but no new workspace changes or successful write tools were observed":"write tools ran in an isolated worktree, but no main workspace changes were present after cleanup")),e.term.limitReached===!0&&!l&&n.push("workflow child reached its iteration limit before satisfying the task");for(let m of v)!i.includes(m)&&!p.includes(m)&&n.push(`required changed path was not present in workspace changes: ${m}`);let k=t.minFinalTextChars;return k!==void 0&&!l&&e.term.finalText.trim().length<k&&n.push(`finalText was shorter than the required ${k} characters`),t.rejectPreparatoryFinalText===!0&&!l&&_e(e.term.finalText)&&n.push("finalText looks preparatory instead of terminal"),{ok:n.length===0,enforcement:h,reasons:n,changedPaths:i,mutationToolCalls:s,mutationEvidence:l}}a(Ie,"evaluateVerification");function ee(e,t){if(t.ok)return e;let o=[t.enforcement==="warn"?"[Workflow task completed without verification]":"[Workflow task verification failed]",...t.reasons.map(i=>`- ${i}`)].join(`
|
|
3
|
+
`);return e.trim().length>0?`${e}
|
|
4
|
+
|
|
5
|
+
${o}`:o}a(ee,"appendVerificationFailure");function Ce(){return{ok:!1,enforcement:"warn",reasons:["workflow child reached its iteration limit before satisfying the task"],mutationEvidence:!1}}a(Ce,"limitReachedWarningVerification");function It(e){return e.entry.bundle.readOnly!==!0&&e.entry.repairAttempts<De&&e.term.status==="completed"&&e.verification!==void 0&&e.verification.ok!==!0&&e.verification.enforcement!=="warn"}a(It,"shouldRepairVerificationFailure");function Ct(e){let t=e.verification.reasons.map(o=>`- ${o}`).join(`
|
|
6
|
+
`),n=(e.verification.changedPaths??[]).length>0?`
|
|
7
|
+
Workspace changes already present before this repair attempt:
|
|
8
|
+
${e.verification.changedPaths?.map(o=>`- ${o}`).join(`
|
|
9
|
+
`)??""}`:"";return[e.originalPrompt,"","[Workflow verification repair]",`Repair attempt ${e.attempt}/${De}.`,"The previous attempt did not satisfy the workflow postconditions.","Do not stop at analysis, planning, or a promise to begin. Complete the required file writes in the real workspace now.","Use the available file editing tools when a file change is required, then report the exact files changed.","","Verification failures:",t,n,"","Previous terminal response:",e.previousFinalText.trim()||"(empty)"].join(`
|
|
10
|
+
`)}a(Ct,"buildVerificationRepairPrompt");async function $e(e,t,n,o,i=n){if(n===void 0)return e;let r;try{return await Promise.race([e,new Promise((s,c)=>{r=setTimeout(()=>{o.childAbortControllers?.get(t)?.abort(),c(new Error(`workflow task ${t} timed out after ${i??n}ms`))},n)})])}finally{r&&clearTimeout(r)}}a($e,"waitForChildPromise");function Ne(e,t,n){return t.outputSchema!==void 0&&We(t.outputSchema),Oe(t.name,t.evidenceRefs,n),{id:e,fanoutClass:"evidence-scan",objective:t.prompt,readOnly:t.readOnly??!1,evidenceRefs:t.evidenceRefs?[...t.evidenceRefs]:[],constraints:[],...t.modelHint?{modelHint:t.modelHint}:{},...t.isolation?{isolation:t.isolation}:{},...t.subagentType?{specialistName:t.subagentType}:{},...t.outputSchema!==void 0?{outputSchema:t.outputSchema}:{},...t.effort?{effort:t.effort}:{}}}a(Ne,"buildBundle");function te(e,t){if(e.cancelledChildren.includes(t))return{status:"stopped",snapStatus:"aborted",finalText:""};let n=e.results[0],o=Et(n?.summary??"",n?.digest);return n?.status==="completed"?{status:"completed",snapStatus:"completed",finalText:o,...n.digest?{digest:n.digest}:{},...n.digestFailed?{digestFailed:!0}:{},...n.digestPending?{digestPending:!0}:{},...n.limitReached?{limitReached:!0}:{},...n.provider?{provider:n.provider}:{},...n.model?{model:n.model}:{},...n.structured!==void 0?{structured:n.structured}:{}}:{status:"failed",snapStatus:"failed",finalText:o,...n?.limitReached?{limitReached:!0}:{},...n?.provider?{provider:n.provider}:{},...n?.model?{model:n.model}:{}}}a(te,"deriveTerminal");function qe(e){let{ctx:t,childOptions:n}=e,o=e.runChild??Pe,i=e.queue??ke(),r=e.listChangedFiles??At,s=e.now??(()=>Date.now()),c=0,p=e.generateId??(()=>`wf-child-${c+=1}`),l=new Map,h=new Set,v=new Map,k=a(()=>e.onTaskSummary!==void 0||h.size>0,"hasTaskSummaryObservers"),m=a((d,g)=>{try{e.onTaskSummary?.(d,g)}catch{}for(let f of h)try{f(d,g)}catch{}},"notifyTaskSummary");return{spawn:a(async d=>{let g=Tt(d,e.defaultChildReadOnly),f=p(),S=Ne(f,g,new Set(l.keys())),O=Wt(g).verification,R=Pt(),D=g.isolation!=="worktree",u=Y(O)?Z(t,r):Promise.resolve({paths:[]}),w=t.childProgressSnapshots,x=a(async A=>{let he=new AbortController;t.childAbortControllers?.set(f,he),w&&Te(w,{childId:f,startedAt:s(),maxIterations:n.maxIterationsPerChild,parentRole:n.parentRole,readOnly:A.readOnly,specialistName:A.specialistName});let kt={...n,parentOptions:{...n.parentOptions,events:Ft(n.parentOptions.events,R)},maxParallel:1,workflowChild:!0,...e.runId!==void 0?{workflowCorrelation:{workflowRunId:e.runId,childAgentId:f,itemId:`agent:${f}`}}:{},childActivityName:g.name,workflowDigestMode:k()?"async":"blocking",...k()?{onWorkflowChildDigest:a(y=>{m(y.childId,{...y.digest?{summary:y.digest}:{},summaryKind:y.digest?"digest":"digest-failed",...y.totalTokensUsed>0?{usage:{totalTokens:y.totalTokensUsed}}:{}})},"onWorkflowChildDigest")}:{},abortSignal:he.signal,snapshotUpdater:w?y=>Ee(w,f,y):void 0},q;try{return await u,q=await o([A],t,kt),q}finally{if(t.childAbortControllers?.delete(f),w){let y=q?te(q,f):{snapStatus:"failed",finalText:""};X(w,f,{status:y.snapStatus,finalText:y.finalText,endedAt:s()})}}},"runBundle"),_=x(S);return l.set(f,{name:g.name,input:g,bundle:S,promise:_,runBundle:x,verification:O,changedPathBaseline:u,mutationRecorder:R,acceptToolMutationEvidence:D,repairAttempts:0}),G(v,f,_),{taskId:f,name:g.name}},"spawn"),wait:a(async(d,g)=>{let f=l.get(d);if(!f)throw new Error(`unknown workflow task: ${d}`);let S=Rt(g),pe=Date.now(),O=a(async x=>{if(S===void 0)return $e(x,d,void 0,t);let _=Date.now()-pe,A=S-_;if(A<=0)throw t.childAbortControllers?.get(d)?.abort(),new Error(`workflow task ${d} timed out after ${S}ms`);return $e(x,d,Math.max(1,Math.floor(A)),t,S)},"waitForAttempt"),R=await O(f.promise),D=R.totalTokensUsed,u=te(R,d),w=f.verification?Ie({verification:f.verification,term:u,before:await f.changedPathBaseline,after:Y(f.verification)?await Z(t,r):{paths:[]},mutationRecorder:f.mutationRecorder,ctx:t,acceptToolMutationEvidence:f.acceptToolMutationEvidence}):void 0;for(u.limitReached===!0&&w===void 0&&u.status==="completed"&&(w=Ce(),u={...u,status:"completed_unverified",snapStatus:"completed",finalText:ee(u.finalText,w)});It({entry:f,term:u,verification:w});){f.repairAttempts+=1;let x=Ne(d,{...f.input,prompt:Ct({originalPrompt:f.input.prompt,previousFinalText:u.finalText,verification:w,attempt:f.repairAttempts})});f.promise=f.runBundle(x),G(v,d,f.promise),R=await O(f.promise),D+=R.totalTokensUsed,u=te(R,d),w=f.verification?Ie({verification:f.verification,term:u,before:await f.changedPathBaseline,after:Y(f.verification)?await Z(t,r):{paths:[]},mutationRecorder:f.mutationRecorder,ctx:t,acceptToolMutationEvidence:f.acceptToolMutationEvidence}):void 0,u.limitReached===!0&&w===void 0&&u.status==="completed"&&(w=Ce(),u={...u,status:"completed_unverified",snapStatus:"completed",finalText:ee(u.finalText,w)})}if(w!==void 0&&!w.ok&&u.status==="completed"){let x=w.enforcement==="warn";u={...u,status:x?"completed_unverified":"failed",snapStatus:x?"completed":"failed",finalText:ee(u.finalText,w)}}return X(t.childProgressSnapshots,d,{status:u.snapStatus,finalText:u.finalText,endedAt:s()}),{taskId:d,name:f.name,status:u.status,finalText:u.finalText,...u.digest?{digest:u.digest}:{},...u.digestFailed?{digestFailed:!0}:{},...u.digestPending?{digestPending:!0}:{},...w!==void 0?{verification:w}:{},...u.limitReached?{limitReached:!0}:{},...u.provider?{provider:u.provider}:{},...u.model?{model:u.model}:{},...u.structured!==void 0?{structured:u.structured}:{},usage:{totalTokens:D}}},"wait"),output:a(async d=>{if(!l.has(d))throw new Error(`unknown workflow task: ${d}`);let g=l.get(d)?.name??d,f=t.childProgressSnapshots?.get(d);if(!f)return{taskId:d,name:g,status:"running"};let S=f.status==="aborted"?"stopped":f.status;return f.finalText!==void 0?{taskId:d,name:g,status:S,lastText:f.finalText}:{taskId:d,name:g,status:S}},"output"),send:a(async(d,g)=>{if(!l.has(d))throw new Error(`unknown workflow task: ${d}`);ye({to:d,priority:"user",mode:"prompt",content:g,registry:v,queue:i})},"send"),stop:a(async d=>{if(!l.has(d))throw new Error(`unknown workflow task: ${d}`);t.childAbortControllers?.get(d)?.abort()},"stop"),subscribeTaskSummaryUpdates:a(d=>(h.add(d),()=>{h.delete(d)}),"subscribeTaskSummaryUpdates")}}a(qe,"createCodingWorkflowBackend");import{homedir as sn}from"node:os";import{join as Ze}from"node:path";var $t=["structure, entry points, and control flow","edge cases, error handling, and failure modes","tests, validation, and existing coverage"],Nt="Deduplicate overlapping findings, keep concrete evidence (file:line), rank by relevance to the question, and explicitly note gaps left by any failed investigation.",Dt={type:"object",additionalProperties:!1,required:["finding"],properties:{finding:{type:"string",description:"Your concrete findings for this focus, with file:line evidence. If nothing relevant was found, a brief note saying so."}}};function _t(e){if(e!==null&&typeof e=="object"&&"finding"in e){let t=e.finding;if(typeof t=="string"&&t.trim().length>0)return t}}a(_t,"readStructuredFinding");function qt(e){let t=_t(e.structured);if(t)return t;let n=e.finalText?.trim();return n&&n.length>0?e.finalText:"[no finding text was returned \u2014 the investigator may have ended on a tool call without a closing summary]"}a(qt,"pickFindingText");function jt(e,t){return["Investigate the following question (READ-ONLY \u2014 do not modify any files):",e,"",`Focus your investigation on: ${t}`,"","Report concrete findings backed by evidence (cite file:line). If you find nothing relevant for this focus, say so briefly."].join(`
|
|
11
|
+
`)}a(jt,"buildInvestigatorPrompt");function Bt(e){let t=Math.max(1,(e.maxAgents??8)-1);return(e.targets&&e.targets.length>0?e.targets:$t).slice(0,t).map((o,i)=>({name:`investigate-${i+1}`,prompt:jt(e.question,o)}))}a(Bt,"resolveAngles");async function Lt(e,t){try{let n=await e.runAgent({name:t.name,prompt:t.prompt,readOnly:!0,outputSchema:Dt});return n===null?{angle:t.name,status:"failed",text:"[investigation failed] agent did not complete"}:{angle:t.name,status:n.status==="completed"?"completed":"failed",text:qt(n)}}catch(n){let o=n instanceof Error?n.message:String(n);return{angle:t.name,status:"failed",text:`[investigation failed] ${o}`}}}a(Lt,"investigate");async function Ut(e,t){let n=Bt(t),o=(await e.phase("investigate",()=>e.parallel(n.map(s=>()=>Lt(e,s)),t.maxConcurrency!==void 0?{concurrency:t.maxConcurrency}:void 0))).filter(s=>s!==null),i=o.some(s=>s.status!=="completed");return{synthesis:(await e.phase("synthesize",()=>e.synthesize({inputs:o.map(s=>`### ${s.angle} (${s.status})
|
|
12
|
+
${s.text}`),rubric:t.rubric??Nt}))).text,findings:o,degraded:i}}a(Ut,"runParallelInvestigation");var je={meta:{name:"parallel-investigation",description:"Fan out read-only investigators over a question (split by target areas), then synthesize ranked, evidence-keeping findings.",maxAgents:8,maxConcurrency:4,readOnly:!0,phases:["investigate","synthesize"]},run:Ut};function Vt(e){return{meta:e.meta,run:a((t,n)=>e.run(t,n),"run")}}a(Vt,"erase");var Be=[Vt(je)];function Le(e){return Be.find(t=>t.meta.name===e)}a(Le,"getBuiltinWorkflow");function Qn(){return Be.map(e=>e.meta)}a(Qn,"listBuiltinWorkflows");import{mkdir as ze,readdir as Kt,readFile as I,rename as Gt,unlink as oe,writeFile as ae}from"node:fs/promises";import{basename as zt,dirname as re,join as E}from"node:path";import{pathToFileURL as Jt}from"node:url";var Je=[".workflow.json",".ts",".mjs",".js"],C="0.7.49";function He(){return"0.7.60"}a(He,"currentKodaxWorkflowVersion");function Ht(e){return e.endsWith(".workflow.json")?"capability-generated":"trusted-local"}a(Ht,"executionForPath");function Xt(e){let t=Je.find(n=>e.endsWith(n));return t?e.slice(0,-t.length):void 0}a(Xt,"stripWorkflowSuffix");function ie(e){let t=e.trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^[.-]+|[.-]+$/g,"").slice(0,80);if(!t||t==="."||t==="..")throw new Error("workflow name must contain at least one safe filename character");return t}a(ie,"safeWorkflowName");function se(e){return typeof e=="object"&&e!==null}a(se,"isRecord");function Ue(e,t){let n=e[t];if(typeof n!="string"||n.length===0)throw new Error(`workflow run.json missing ${t}`);return n}a(Ue,"readRequiredString");async function Ve(e,t){if(!e)return[];let n;try{n=await Kt(e)}catch{return[]}let o=new Map;for(let i of Je)for(let r of n){if(!r.endsWith(i))continue;let s=Xt(r);if(!s||s.length===0||o.has(s))continue;let c=E(e,r);o.set(s,{name:s,path:c,source:t,execution:Ht(c)})}return[...o.values()]}a(Ve,"scanDir");async function $(e){let t=await Ve(e.personal,"personal"),n=await Ve(e.project,"project"),o=new Map;for(let i of t)o.set(i.name,i);for(let i of n)o.set(i.name,i);return[...o.values()].sort((i,r)=>i.name.localeCompare(r.name))}a($,"discoverSavedWorkflows");function Yt(e){return typeof e=="object"&&e!==null&&"meta"in e&&"run"in e&&typeof e.run=="function"}a(Yt,"isWorkflowModule");function Zt(e){let t=e.default;if(Yt(t))return t;let n=typeof t=="function"?t:e.run,o=e.workflow??e.meta;if(typeof n=="function"&&typeof o=="object"&&o!==null&&"name"in o)return{meta:o,run:n};throw new Error("invalid workflow module: expected a `{ meta, run }` default export, or `export const workflow = {...}` + a default run function")}a(Zt,"normalizeWorkflowModule");function Qt(e){let t=JSON.parse(e);if(!se(t))throw new Error("generated workflow file must be an object");if(t.format!==void 0&&t.format!=="kodax.workflow")throw new Error(`unsupported workflow capsule format: ${String(t.format)}`);if(t.format==="kodax.workflow"){let i=J(t);return{manifest:i.manifest,source:i.source,capsule:i,legacy:!1}}let n=t.source;if(typeof n!="string"||n.trim().length===0)throw new Error("generated workflow file source must be a non-empty string");let o=F(t.manifest);return{manifest:o,source:n,capsule:W({minKodaxVersion:C,manifest:o,source:n}),legacy:!0}}a(Qt,"parseGeneratedWorkflowFile");async function ce(e){let t=Qt(await I(e,"utf8"));return t.capsule??W({minKodaxVersion:C,manifest:t.manifest,source:t.source})}a(ce,"loadSavedWorkflowCapsule");async function Xe(e){if(e.endsWith(".workflow.json"))return H(await ce(e));let t=await import(Jt(e).href);return Zt(t)}a(Xe,"loadSavedWorkflow");function fe(e){if(e.mayUseWorktree===!0)return{environment:["git-repo","worktree-capable"]}}a(fe,"deriveRequirements");function L(e,t){z(t,{filename:`${e.name}.workflow.js`,requireAsyncRun:!0})}a(L,"assertGeneratedCapsuleSource");async function en(e){let t=ie(e.name),n=F(e.manifest);L(n,e.source);let o=e.requires??fe(n),i=W({minKodaxVersion:e.minKodaxVersion??C,manifest:n,source:e.source,...e.intent!==void 0?{intent:e.intent}:{},...e.inputs!==void 0?{inputs:e.inputs}:{},...o!==void 0?{requires:o}:{},...e.provenance!==void 0?{provenance:e.provenance}:{}});await ze(e.dir,{recursive:!0});let r=E(e.dir,`${t}.workflow.json`);return await ae(r,`${JSON.stringify(i,null,2)}
|
|
13
|
+
`,"utf8"),{name:t,path:r,source:"project",execution:"capability-generated"}}a(en,"saveGeneratedWorkflow");async function Ke(e,t){await ae(e,`${JSON.stringify(t,null,2)}
|
|
14
|
+
`,"utf8")}a(Ke,"writeCapsuleFile");async function tn(e){try{return await I(e,"utf8"),!0}catch{return!1}}a(tn,"fileExists");async function ir(e){let t=(await $(e.dirs)).filter(c=>c.name===e.name).filter(c=>e.source===void 0||c.source===e.source);if(t.length===0)throw new Error(`saved workflow not found: ${e.name}`);if(t.length>1)throw new Error(`ambiguous saved workflow name: ${e.name}`);let n=t[0];if(!n.path.endsWith(".workflow.json"))throw new Error("only generated workflow capsules can be renamed");let o=ie(e.newName),i=E(re(n.path),`${o}.workflow.json`);if(i!==n.path&&await tn(i))throw new Error(`saved workflow already exists: ${o}`);let r=await ce(n.path);L(r.manifest,r.source);let s=W({minKodaxVersion:r.minKodaxVersion,manifest:{...r.manifest,name:o},source:r.source,...r.intent!==void 0?{intent:r.intent}:{},...r.inputs!==void 0?{inputs:r.inputs}:{},...r.requires!==void 0?{requires:r.requires}:{},...r.provenance!==void 0?{provenance:r.provenance}:{}});return await ae(i,`${JSON.stringify(s,null,2)}
|
|
15
|
+
`,"utf8"),i!==n.path&&await oe(n.path),{name:o,path:i,source:n.source,execution:"capability-generated"}}a(ir,"renameSavedWorkflow");async function sr(e){let t=(await $(e.dirs)).filter(o=>o.name===e.name).filter(o=>e.source===void 0||o.source===e.source);if(t.length===0)throw new Error(`saved workflow not found: ${e.name}`);if(t.length>1)throw new Error(`ambiguous saved workflow name: ${e.name}`);let n=t[0];if(!n.path.endsWith(".workflow.json"))throw new Error("only generated workflow capsules can be deleted");return await oe(n.path),n}a(sr,"deleteSavedWorkflow");async function cr(e){let t=ie(e.name),n=(await $(e.dirs)).filter(m=>m.name===t).filter(m=>e.savedSource===void 0||m.source===e.savedSource);if(n.length===0)throw new Error(`saved workflow not found: ${t}`);if(n.length>1)throw new Error(`ambiguous saved workflow name: ${t}`);let o=n[0];if(!o.path.endsWith(".workflow.json"))throw new Error("only generated workflow capsules can be replaced");let i=F({...e.manifest,name:t});L(i,e.source);let r=e.requires??fe(i),s=W({minKodaxVersion:e.minKodaxVersion??C,manifest:i,source:e.source,...e.intent!==void 0?{intent:e.intent}:{},...e.inputs!==void 0?{inputs:e.inputs}:{},...r!==void 0?{requires:r}:{},...e.provenance!==void 0?{provenance:e.provenance}:{}}),c=await ce(o.path),p=new Date().toISOString().replace(/[:.]/g,"-"),l=E(re(o.path),".revisions",t),h=`${p}-${process.hrtime.bigint().toString(36)}`,v=E(l,`${t}-${h}.workflow.json`),k=E(re(o.path),`.${t}.${process.pid}.${Date.now().toString(36)}.tmp`);await ze(l,{recursive:!0}),await Ke(v,c);try{await Ke(k,s),await Gt(k,o.path)}catch(m){try{await oe(k)}catch{}throw m}return{name:t,path:o.path,source:o.source,execution:"capability-generated",previousPath:v}}a(cr,"replaceSavedWorkflow");function nn(e){if(!se(e))return;let t=e.request;if(typeof t=="string"&&t.trim().length>0)return t;let n=e.question;if(typeof n=="string"&&n.trim().length>0)return n}a(nn,"readOptionalOriginalRequest");function Ye(e){return rn(e)}a(Ye,"buildCapsuleFromRun");async function rn(e){let t=JSON.parse(await I(E(e.runDir,"run.json"),"utf8"));if(!se(t))throw new Error("workflow run.json must be an object");let n=Ue(t,"scriptSnapshotPath"),o=Ue(t,"manifestSnapshotPath"),i=await I(n,"utf8"),r=F(JSON.parse(await I(o,"utf8")));L(r,i);let s=typeof t.runId=="string"&&t.runId.length>0?t.runId:zt(e.runDir),c=nn(t.args),p=fe(r),l=xe(r,c!==void 0?{originalRequest:c}:{}),h={description:"Provide new workflow args matching the generated request shape.",..."args"in t?{examples:[t.args]}:{}};return W({minKodaxVersion:C,manifest:r,source:i,intent:l,inputs:h,...p!==void 0?{requires:p}:{},provenance:{fromRunId:s,createdAt:new Date().toISOString(),kodaxVersion:He()}})}a(rn,"readCapsuleFromRun");async function fr(e){let t=await Ye(e);return{capsule:t,module:H(t)}}a(fr,"loadGeneratedWorkflowFromRun");async function dr(e){let t=await Ye(e);return en({dir:e.targetDir,name:e.name,manifest:t.manifest,source:t.source,...t.intent!==void 0?{intent:t.intent}:{},...t.inputs!==void 0?{inputs:t.inputs}:{},...t.requires!==void 0?{requires:t.requires}:{},...t.provenance!==void 0?{provenance:t.provenance}:{},minKodaxVersion:t.minKodaxVersion})}a(dr,"saveGeneratedWorkflowFromRun");function b(e,t,n,o){e.push({severity:t,requirement:n,message:o})}a(b,"addRequirementIssue");function Ge(e){let t=/^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(e.trim());if(t)return[Number(t[1]),Number(t[2]),Number(t[3])]}a(Ge,"parseSemver");function on(e,t){for(let n=0;n<3;n+=1){let o=e[n]-t[n];if(o!==0)return o}return 0}a(on,"compareSemver");function an(e,t,n){let o=Ge(t),i=Ge(n);if(!o){b(e,"error","kodax:min-version",`workflow minKodaxVersion is not valid semver: ${t}`);return}if(!i){b(e,"warning","kodax:min-version",`cannot verify workflow minKodaxVersion ${t}; current version is unknown`);return}on(i,o)<0&&b(e,"error","kodax:min-version",`workflow requires KodaX >= ${t}, current version is ${n}`)}a(an,"addMinVersionIssue");function ne(e,t,n,o){if(!n)return;if(!o){for(let r of n)b(e,"warning",`${t}:${r}`,`workflow requires ${t}:${r}, but no ${t} inventory was provided`);return}let i=new Set(o);for(let r of n)i.has(r)||b(e,"error",`${t}:${r}`,`missing required workflow ${t}: ${r}`)}a(ne,"addMissingItems");function ur(e,t={}){let n=J(e),o=[],i=n.requires;an(o,n.minKodaxVersion,t.kodaxVersion??He()),i?.environment?.includes("git-repo")&&t.isGitRepo===!1&&b(o,"error","environment:git-repo","workflow requires a git repository"),i?.environment?.includes("worktree-capable")&&t.worktreeCapable===!1&&b(o,"error","environment:worktree-capable","workflow may request git worktree isolation");try{z(n.source,{filename:`${n.manifest.name}.workflow.js`,requireAsyncRun:!0})}catch(r){let s=r instanceof Error?r.message:String(r);b(o,"error","workflow:source",s)}return ne(o,"tools",i?.tools,t.availableTools),ne(o,"mcp",i?.mcp,t.availableMcp),ne(o,"skills",i?.skills,t.availableSkills),{ok:!o.some(r=>r.severity==="error"),issues:o}}a(ur,"preflightWorkflowCapsule");function cn(e){return{project:Ze(e,".kodax","workflows"),personal:Ze(sn(),".kodax","workflows")}}a(cn,"defaultSavedWorkflowDirs");async function fn(e,t){let o=(await $(t)).find(i=>i.name===e);if(o)return Xe(o.path)}a(fn,"resolveSavedByName");function Qe(e){let t=cn(e);return async n=>Le(n)??await fn(n,t)}a(Qe,"createNestedWorkflowResolver");import{existsSync as dn,mkdirSync as un,readFileSync as ln,writeFileSync as et}from"node:fs";import{join as N}from"node:path";var tt="results";function nt(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}a(nt,"safeKey");function rt(e,t){let n=N(e,t);if(dn(n))try{return JSON.parse(ln(n,"utf8"))}catch{return}}a(rt,"readResult");function ot(e,t={}){let n=N(e,tt);un(n,{recursive:!0});let o=t.readFrom?N(t.readFrom,tt):void 0;return{get:a(i=>{let r=`${nt(i)}.json`,s=rt(n,r);if(s!==void 0)return s;if(o===void 0)return;let c=rt(o,r);if(c!==void 0){try{et(N(n,r),JSON.stringify(c),"utf8")}catch{}return c}},"get"),set:a((i,r)=>{try{et(N(n,`${nt(i)}.json`),JSON.stringify(r),"utf8")}catch{}},"set")}}a(ot,"createFsResultCache");import{mkdirSync as mn,appendFileSync as wn,writeFileSync as U}from"node:fs";import{join as P}from"node:path";function pn(e){let t=e.replace(/[^a-zA-Z0-9._-]/g,"_").slice(0,120);return t.length>0?t:"artifact"}a(pn,"safeWorkflowArtifactName");function at(e,t={}){let n=t.now??(()=>Date.now()),o=P(e,"artifacts");mn(o,{recursive:!0});let i=P(e,"events.jsonl");return{runDir:e,onEvent:a(r=>{wn(i,`${JSON.stringify({...r,ts:n()})}
|
|
16
|
+
`,"utf8")},"onEvent"),writeArtifact:a((r,s)=>{let c=P(o,`${pn(r)}.json`);return U(c,JSON.stringify(s,null,2),"utf8"),{name:r,path:c}},"writeArtifact"),writeScriptSnapshot:a(r=>{let s=P(e,"script.js");if(U(s,r.source,"utf8"),!r.manifest)return{scriptPath:s};let c=P(e,"manifest.json");return U(c,`${JSON.stringify(r.manifest,null,2)}
|
|
17
|
+
`,"utf8"),{scriptPath:s,manifestPath:c}},"writeScriptSnapshot"),writeRunJson:a(r=>{let s=ve(r.processMetadata?.hostMetadata),c={runId:r.state.runId,workflow:r.meta.name,status:r.state.status,totalSpawned:r.state.totalSpawned,artifacts:r.state.artifacts.map(p=>p.name),eventCount:r.state.events.length,startedAt:r.startedAt,endedAt:r.endedAt,args:r.args,...r.resultSummary!==void 0?{resultSummary:r.resultSummary}:{},...r.processMetadata?.displayName!==void 0?{displayName:r.processMetadata.displayName}:{},...r.processMetadata?.goal!==void 0?{goal:r.processMetadata.goal}:{},...r.processMetadata?.source!==void 0?{source:r.processMetadata.source}:{},...r.processMetadata?.savedWorkflowName!==void 0?{savedWorkflowName:r.processMetadata.savedWorkflowName}:{},...r.processMetadata?.sourceRunId!==void 0?{sourceRunId:r.processMetadata.sourceRunId}:{},...r.processMetadata?.sourceWorkflowName!==void 0?{sourceWorkflowName:r.processMetadata.sourceWorkflowName}:{},...r.processMetadata?.revisionOf!==void 0?{revisionOf:r.processMetadata.revisionOf}:{},...r.processMetadata?.resumedFromRunId!==void 0?{resumedFromRunId:r.processMetadata.resumedFromRunId}:{},...s!==void 0?{hostMetadata:s}:{},...r.scriptSnapshot?{scriptSnapshotPath:r.scriptSnapshot.scriptPath,...r.scriptSnapshot.manifestPath?{manifestSnapshotPath:r.scriptSnapshot.manifestPath}:{}}:{}};U(P(e,"run.json"),`${JSON.stringify(c,null,2)}
|
|
18
|
+
`,"utf8")},"writeRunJson")}}a(at,"createRunGraphWriter");import{execFile as hn}from"node:child_process";import{promisify as gn}from"node:util";import{statSync as kn}from"node:fs";import{join as yn}from"node:path";var vn=gn(hn);function ue(e){return yn(e,"worktrees")}a(ue,"workflowWorktreeBaseDir");var Sn=360*60*1e3;function st(e,t){return vn("git",[...e],{cwd:t}).then(n=>n.stdout)}a(st,"defaultRunGit");function xn(e){return kn(e).mtimeMs}a(xn,"defaultMtimeMs");function Mn(e){let t=[],n,o,i=a(()=>{n&&t.push(o?{path:n,branch:o}:{path:n}),n=void 0,o=void 0},"flush");for(let r of e.split(/\r?\n/))r.startsWith("worktree ")?(i(),n=r.slice(9).trim()):r.startsWith("branch ")&&(o=r.slice(7).trim().replace(/^refs\/heads\//,""));return i(),t}a(Mn,"parseWorktreeList");function it(e){return e.replace(/\\/g,"/").replace(/\/+$/,"")}a(it,"normalize");function ct(e,t){let n=it(e),o=it(t);return n===o||n.startsWith(`${o}/`)}a(ct,"isUnder");async function Rn(e,t,n){try{let i=(await t(["status","--porcelain"],e.path)).split(/\r?\n/).filter(c=>c.trim().length>0).length,r=await t(["rev-list","--count","HEAD","--not","--remotes"],e.path),s=Number.parseInt(r.trim(),10)||0;return i>0||s>0}catch(o){return n.push(`retain ${e.path}: cannot verify worktree cleanliness: ${o instanceof Error?o.message:String(o)}`),!0}}a(Rn,"worktreeHasChanges");async function ft(e,t,n,o,i){if(await Rn(e,n,i)){i.push(`retain ${e.path}: worktree has unmerged changes`);return}try{await n(["worktree","remove",e.path,"--force"],t),o.push(e.path)}catch(r){i.push(`remove ${e.path}: ${r instanceof Error?r.message:String(r)}`);return}if(e.branch)try{await n(["branch","-D",e.branch],t)}catch{}}a(ft,"removeWorktree");async function dt(e,t,n){try{let o=await t(["worktree","list","--porcelain"],e);return Mn(o)}catch(o){n.push(`list worktrees: ${o instanceof Error?o.message:String(o)}`);return}}a(dt,"listWorktrees");async function de(e,t,n){try{await t(["worktree","prune"],e)}catch(o){n.push(`prune: ${o instanceof Error?o.message:String(o)}`)}}a(de,"prune");async function ut(e,t={}){let n=[],o=[];if(!e.gitRoot)return{removed:o,warnings:n};let i=t.runGit??st,r=await dt(e.gitRoot,i,n);if(!r)return{removed:o,warnings:n};for(let s of r)ct(s.path,e.baseDir)&&await ft(s,e.gitRoot,i,o,n);return o.length>0&&await de(e.gitRoot,i,n),{removed:o,warnings:n}}a(ut,"sweepWorkflowRunWorktrees");async function lt(e,t={}){let n=[],o=[];if(!e.gitRoot)return{removed:o,warnings:n};let i=t.runGit??st,r=t.mtimeMs??xn,s=t.now??(()=>Date.now()),c=e.maxAgeMs??Sn;await de(e.gitRoot,i,n);let p=await dt(e.gitRoot,i,n);if(!p)return{removed:o,warnings:n};for(let l of p){if(!ct(l.path,e.workflowRunsRoot))continue;let h;try{h=s()-r(l.path)}catch{continue}h>=c&&await ft(l,e.gitRoot,i,o,n)}return o.length>0&&await de(e.gitRoot,i,n),{removed:o,warnings:n}}a(lt,"pruneStaleWorkflowWorktrees");var Tn=200,mt={maxAgents:64,tokenBudget:2e5};function En(e,t){let n=e.meta,o=V(n,t);return{name:n.name,description:n.description,phases:n.phases??[],...n.plannedAgents!==void 0?{plannedAgents:n.plannedAgents}:{},maxAgents:o.maxAgents??null,maxConcurrency:o.maxConcurrency??null,tokenBudget:o.tokenBudget??null,writesFiles:n.readOnly!==!0}}a(En,"buildApprovalSummary");function le(e,t){if(e!==void 0)return!Number.isInteger(e)||e<=0?1:Math.min(e,t)}a(le,"clampLimit");function An(e,t,n){let o=le(e,n),i=le(t,n);return o===void 0?i:i===void 0?o:Math.min(o,i)}a(An,"clampEffectiveLimit");function wt(e,t){if(!(e==null||!Number.isFinite(e)||e<=0))return Math.min(Math.floor(e),t)}a(wt,"clampTokenBudget");function Pn(e,t,n){let o=wt(e,n),i=wt(t,n);return o===void 0?i:i===void 0?o:Math.min(o,i)}a(Pn,"clampEffectiveTokenBudget");function V(e,t){let n=An(e.maxAgents,t?.maxAgents,mt.maxAgents),o=ge(),i=[e.maxConcurrency,t?.maxConcurrency].map(c=>le(c,o)).filter(c=>c!==void 0),r=i.length===0?o:Math.min(o,...i),s=Pn(e.tokenBudget,t?.tokenBudget,mt.tokenBudget);return{...n!==void 0?{maxAgents:n}:{},...r!==void 0?{maxConcurrency:r}:{},...s!==void 0?{tokenBudget:s}:{}}}a(V,"clampWorkflowLimits");function pt(e){if(typeof e=="string"&&e.trim().length>0)return e;if(typeof e!="object"||e===null)return;let t=e,n=t.synthesis;if(typeof n=="string"&&n.trim().length>0)return n;if(typeof n=="object"&&n!==null){let o=n.text;if(typeof o=="string"&&o.trim().length>0)return o}for(let o of["summary","report","text","result"]){let i=t[o];if(typeof i=="string"&&i.trim().length>0)return i}}a(pt,"workflowResultSummary");async function me(e){let t=V(e.module.meta,e.hostPolicy),n=En(e.module,e.hostPolicy);if(e.approval&&!await e.approval(n))return{kind:"denied",summary:n};let o=e.now??(()=>Date.now()),i=e.ctx?.executionCwd??e.ctx?.gitRoot;await lt({workflowRunsRoot:Wn(e.runDir),gitRoot:i},{now:o,...e.worktreeSweepDeps});let r=at(e.runDir,{now:o}),s=e.resumeFromRunDir!==void 0?bn(e.resumeFromRunDir):void 0,c=e.onWorkflowProcessEvent?Se({runId:e.runId,workflowName:e.module.meta.name,displayName:e.processMetadata?.displayName??e.module.meta.name,...e.processMetadata?.goal!==void 0?{goal:e.processMetadata.goal}:{},...e.processMetadata?.source!==void 0?{source:e.processMetadata.source}:{},...e.processMetadata?.savedWorkflowName!==void 0?{savedWorkflowName:e.processMetadata.savedWorkflowName}:{},...e.processMetadata?.sourceRunId!==void 0?{sourceRunId:e.processMetadata.sourceRunId}:{},...e.processMetadata?.sourceWorkflowName!==void 0?{sourceWorkflowName:e.processMetadata.sourceWorkflowName}:{},...e.processMetadata?.revisionOf!==void 0?{revisionOf:e.processMetadata.revisionOf}:{},...s!==void 0?{resumedFromRunId:s}:{},...e.processMetadata?.hostMetadata!==void 0?{hostMetadata:{...e.processMetadata.hostMetadata}}:{},...e.module.meta.phases!==void 0?{phases:e.module.meta.phases}:{},...t.maxAgents!==void 0?{maxAgents:t.maxAgents}:{},...e.module.meta.plannedAgents!==void 0?{plannedAgents:e.module.meta.plannedAgents}:{},...t.tokenBudget!==void 0?{tokenBudget:t.tokenBudget}:{},now:a(()=>new Date(o()).toISOString(),"now")}):void 0,p=e.scriptSnapshot?r.writeScriptSnapshot(e.scriptSnapshot):void 0,l=e.backend??On(e),v={...e.beforeSpawn?Fn(l,e.beforeSpawn):l,writeArtifact:a(async(M,we)=>r.writeArtifact(M,we),"writeArtifact")},k=o(),m;try{m=await Me({runId:e.runId,args:e.args,backend:v,limits:t,...e.signal?{signal:e.signal}:{},summarizeResult:pt,resolveWorkflowModule:Qe(i??process.cwd()),resultCache:ot(e.runDir,e.resumeFromRunDir?{readFrom:e.resumeFromRunDir}:{}),onEvent:a(M=>{r.onEvent(M),c&&e.onWorkflowProcessEvent?.(c.applyEvent(M)),e.onEvent?.(M)},"onEvent")},M=>e.module.run(M,e.args))}finally{await ut({baseDir:ue(e.runDir),gitRoot:i},{now:o,...e.worktreeSweepDeps})}let K=m.ok?pt(m.result):void 0;return r.writeRunJson({meta:e.module.meta,args:e.args,state:m.state,startedAt:k,endedAt:o(),...p?{scriptSnapshot:p}:{},...K!==void 0?{resultSummary:K}:{},...e.processMetadata!==void 0||s!==void 0?{processMetadata:{...e.processMetadata,...s!==void 0?{resumedFromRunId:s}:{}}}:{}}),m.ok?{kind:"completed",result:m.result,state:m.state}:{kind:"failed",error:m.error,state:m.state}}a(me,"runWorkflowModule");function On(e){if(!e.ctx||!e.childOptions)throw new Error("runWorkflowModule requires either a backend or ctx + childOptions");return qe({ctx:e.ctx,childOptions:e.childOptions,runId:e.runId,defaultChildReadOnly:e.module.meta.readOnly===!0})}a(On,"buildBackend");function Fn(e,t){return{...e,spawn:a(async n=>(await t(),e.spawn(n)),"spawn")}}a(Fn,"withBeforeSpawn");function In(e,t,n){let o=e?.onWorkflowAgentDigest;o&&(n.type==="agent_completed"||n.type==="agent_unverified"||n.type==="agent_failed"||n.type==="agent_summary_updated")&&o({runId:t,event:n})}a(In,"emitWorkflowAgentDigest");async function ht(e){let t={...Ae({options:e.options,runtime:e.options.extensionRuntime,managedProtocolPayloadRef:{current:void 0}}),workflowWorktreeBaseDir:ue(e.runDir)},n={maxIterationsPerChild:Tn,parentRole:"worker",parentHarness:"tool-dispatch",parentOptions:{provider:e.options.provider,model:e.options.modelOverride??e.options.model,effort:e.options.effort,reasoningMode:e.options.reasoningMode,repoIntelligenceMode:e.options.context?.repoIntelligenceMode,repoIntelligenceTrace:e.options.context?.repoIntelligenceTrace,extensionRuntime:e.options.extensionRuntime,events:e.options.events},...e.options.guardrails?{guardrails:e.options.guardrails}:{},...t.planModeBlockCheck?{planModeBlockCheck:t.planModeBlockCheck}:{}},o=e.onWorkflowProcessEvent||e.options.events?.onWorkflowProcessEvent?r=>{e.onWorkflowProcessEvent?.(r),e.options.events?.onWorkflowProcessEvent?.(r)}:void 0,i=e.onEvent||e.options.events?.onWorkflowAgentDigest?r=>{e.onEvent?.(r),In(e.options.events,e.runId,r)}:void 0;return me({module:e.module,args:e.args,runId:e.runId,runDir:e.runDir,ctx:t,childOptions:n,...e.approval?{approval:e.approval}:{},...e.signal?{signal:e.signal}:{},...i?{onEvent:i}:{},...o?{onWorkflowProcessEvent:o}:{},...e.options.workflowHostPolicy?{hostPolicy:e.options.workflowHostPolicy}:{},...e.now?{now:e.now}:{},...e.scriptSnapshot?{scriptSnapshot:e.scriptSnapshot}:{},...e.resumeFromRunDir?{resumeFromRunDir:e.resumeFromRunDir}:{},...e.processMetadata?{processMetadata:e.processMetadata}:{},...e.beforeSpawn?{beforeSpawn:e.beforeSpawn}:{}})}a(ht,"runWorkflowFromOptions");function Cn(e){if(typeof e=="string"&&e.trim().length>0)return e;if(typeof e!="object"||e===null)return;let t=e,n=t.synthesis;if(typeof n=="string"&&n.trim().length>0)return n;if(typeof n=="object"&&n!==null){let o=n.text;if(typeof o=="string"&&o.trim().length>0)return o}for(let o of["summary","report","text","result"]){let i=t[o];if(typeof i=="string"&&i.trim().length>0)return i}}a(Cn,"resultText");function $n(e){if(e.kind==="completed"){let t=Cn(e.result);return t!==void 0?{status:"completed",resultText:t}:{status:"completed"}}return e.kind==="denied"?{status:"denied"}:{status:"failed",error:e.error}}a($n,"classifyOutcome");function Nn(e,t){return{kind:"failed",error:t instanceof Error?t:new Error(String(t)),state:{runId:e,status:"failed",totalSpawned:0,events:[],artifacts:[]}}}a(Nn,"failedOutcome");var Dn=1e3;function _n(e={},t=Re(e)){let n=new Map,o=a(r=>r?{...r,runDir:n.get(r.runId)??""}:void 0,"withRunDir"),i=a((r,s)=>{if(n.set(r.runId,r.runDir),n.size>Dn){let l=new Set(t.list().map(h=>h.runId));for(let h of n.keys())h!==r.runId&&!l.has(h)&&n.delete(h)}let c=V(r.meta,r.hostPolicy),p=t.start({runId:r.runId,workflow:r.meta.name,...r.meta.phases!==void 0?{phases:r.meta.phases}:{},...c.maxAgents!==void 0?{maxAgents:c.maxAgents}:{},...r.meta.plannedAgents!==void 0?{plannedAgents:r.meta.plannedAgents}:{},...c.tokenBudget!==void 0?{tokenBudget:c.tokenBudget}:{},...r.processMetadata!==void 0?{processMetadata:r.processMetadata}:{},...r.signal?{signal:r.signal}:{},runFn:s,classify:$n,onError:a(l=>Nn(r.runId,l),"onError")});return{runId:p.runId,done:p.done,getSnapshot:a(()=>o(p.getSnapshot()),"getSnapshot"),getProcessSnapshot:a(()=>p.getProcessSnapshot(),"getProcessSnapshot")}},"startManaged");return{start:a(r=>i({runId:r.runId,runDir:r.runDir,meta:r.module.meta,hostPolicy:r.hostPolicy,processMetadata:r.processMetadata,signal:r.signal},s=>me({...r,signal:s.signal,beforeSpawn:s.beforeSpawn,onEvent:a(c=>{s.onEvent(c),r.onEvent?.(c)},"onEvent")})),"start"),startFromOptions:a(r=>i({runId:r.runId,runDir:r.runDir,meta:r.module.meta,hostPolicy:r.options.workflowHostPolicy,processMetadata:r.processMetadata,signal:r.signal},s=>ht({...r,signal:s.signal,beforeSpawn:s.beforeSpawn,onEvent:a(c=>{s.onEvent(c),r.onEvent?.(c)},"onEvent")})),"startFromOptions"),list:a(()=>t.list().map(r=>({...r,runDir:n.get(r.runId)??""})),"list"),get:a(r=>o(t.get(r)),"get"),subscribeWorkflowProcess:a(r=>t.subscribeWorkflowProcess(r),"subscribeWorkflowProcess"),getWorkflowProcessSnapshot:a(r=>t.getWorkflowProcessSnapshot(r),"getWorkflowProcessSnapshot"),listWorkflowProcessSnapshots:a(r=>t.listWorkflowProcessSnapshots(r),"listWorkflowProcessSnapshots"),pause:a(r=>t.pause(r),"pause"),resume:a(r=>t.resume(r),"resume"),stop:a((r,s)=>t.stop(r,s),"stop")}}a(_n,"createWorkflowRunManager");var gt;function Jr(){return gt??=_n({},be()),gt}a(Jr,"getDefaultWorkflowRunManager");export{qe as a,je as b,Be as c,Le as d,Qn as e,$ as f,Zt as g,ce as h,Xe as i,en as j,ir as k,sr as l,cr as m,fr as n,dr as o,ur as p,pn as q,at as r,mt as s,En as t,V as u,me as v,In as w,ht as x,_n as y,Jr as z};
|