@kodax-ai/kodax 0.7.96 → 0.7.97-alpha.2
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 +86 -0
- package/README.md +85 -62
- package/README_CN.md +57 -67
- package/config-templates/config.example.jsonc +0 -14
- package/dist/chunks/{agent-7N427EVB.js → agent-J7SHFM5N.js} +1 -1
- package/dist/chunks/argument-completer-ZJQOWTIS.js +2 -0
- package/dist/chunks/{chunk-ABZDFK2X.js → chunk-2GV6MQ4T.js} +14 -14
- package/dist/chunks/{chunk-6QI3GOYG.js → chunk-3PS3YEDS.js} +1 -1
- package/dist/chunks/chunk-4VJMQDTH.js +417 -0
- package/dist/chunks/{chunk-NI7PBPUR.js → chunk-5DSUVP46.js} +1 -1
- package/dist/chunks/chunk-5P7RTSZT.js +21 -0
- package/dist/chunks/{chunk-XXNR6S4Q.js → chunk-6ZAQKFIM.js} +1 -1
- package/dist/chunks/chunk-7V2QBZ73.js +137 -0
- package/dist/chunks/{chunk-C7U542KM.js → chunk-F7DHZH6T.js} +1 -1
- package/dist/chunks/{chunk-7IMWOR34.js → chunk-HSRYDDPF.js} +1 -1
- package/dist/chunks/chunk-K3DQGSQU.js +372 -0
- package/dist/chunks/chunk-NO23K2CB.js +2 -0
- package/dist/chunks/{chunk-NKT3B3DR.js → chunk-OT5WHAX4.js} +1 -1
- package/dist/chunks/{chunk-YEAUDI6U.js → chunk-QGWHJIO4.js} +1 -1
- package/dist/chunks/chunk-QOFFAY5C.js +261 -0
- package/dist/chunks/{chunk-4PFZ7BEE.js → chunk-QVDTORL3.js} +11 -11
- package/dist/chunks/chunk-QZ4B4AWG.js +473 -0
- package/dist/chunks/chunk-RXDS6CNA.js +355 -0
- package/dist/chunks/{chunk-WV3DJVW4.js → chunk-VDGPJQL7.js} +135 -135
- package/dist/chunks/chunk-VEZ4WHPN.js +641 -0
- package/dist/chunks/chunk-ZPPAT25E.js +5 -0
- package/dist/chunks/chunk-ZQYWDI4O.js +1 -0
- package/dist/chunks/chunk-ZS2GUADU.js +498 -0
- package/dist/chunks/{chunk-GN2IY5YE.js → chunk-ZTYZYXGV.js} +1 -1
- package/dist/chunks/{chunk-EM4XJBTK.js → chunk-ZZQ4GDVU.js} +1 -1
- package/dist/chunks/{client-6WZZTTSV.js → client-MXOJ5XUN.js} +1 -1
- package/dist/chunks/{compaction-config-ZMEJU4U7.js → compaction-config-5VZSGKBQ.js} +1 -1
- package/dist/chunks/{construction-bootstrap-RX4DMHI7.js → construction-bootstrap-U2ZU2WAT.js} +1 -1
- package/dist/chunks/dist-CSLNWLOE.js +2 -0
- package/dist/chunks/dist-XXMJMJDU.js +2 -0
- package/dist/chunks/host-RUXYZFYN.js +2 -0
- package/dist/chunks/readline-helpers-JCVULR4C.js +2 -0
- package/dist/chunks/run-manager-DRIM5VNE.js +2 -0
- package/dist/chunks/utils-MQEBGKIX.js +2 -0
- package/dist/index.d.ts +63 -30
- package/dist/index.js +10 -6
- package/dist/kodax_bootstrap.js +1 -1
- package/dist/kodax_cli.js +1745 -1734
- package/dist/kodax_resume.js +32 -35
- package/dist/native/win32-x64/kodax-windows-sandbox.exe +0 -0
- package/dist/native/win32-x64/kodax-windows-text-transaction.node +0 -0
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/sandbox-network-broker.js +77 -77
- package/dist/sdk-a2a.d.ts +33 -18
- package/dist/sdk-a2a.js +8 -9
- package/dist/sdk-agent.d.ts +33 -26
- package/dist/sdk-agent.js +1 -1
- package/dist/sdk-client.d.ts +40 -0
- package/dist/sdk-client.js +2 -0
- package/dist/sdk-coding.d.ts +87 -499
- package/dist/sdk-coding.js +1 -1
- package/dist/sdk-experimental-memory.d.ts +3 -4
- package/dist/sdk-experimental-memory.js +1 -1
- package/dist/sdk-llm.d.ts +11 -9
- package/dist/sdk-llm.js +1 -1
- package/dist/sdk-mcp.d.ts +3 -3
- package/dist/sdk-mcp.js +1 -1
- package/dist/sdk-media.d.ts +3 -1
- package/dist/sdk-media.js +1 -1
- package/dist/sdk-repl.d.ts +317 -70
- package/dist/sdk-repl.js +2 -2
- package/dist/sdk-runtime.d.ts +580 -452
- package/dist/sdk-runtime.js +1 -1
- package/dist/sdk-sandbox.js +1 -1
- package/dist/sdk-session.d.ts +13 -9
- package/dist/sdk-session.js +1 -1
- package/dist/sdk-skills.js +1 -1
- package/dist/semantic-worker.js +57 -57
- package/dist/types-chunks/{base.d-Bt9lhwSV.d.ts → base.d-ZBOdjDUT.d.ts} +2 -1
- package/dist/types-chunks/{bash-prefix-extractor.d-DWFIMg0v.d.ts → bash-prefix-extractor.d-DvswAXKS.d.ts} +136 -66
- package/dist/types-chunks/{capability-learning.d-gRtO03f6.d.ts → capability-learning.d-B4pxKwP4.d.ts} +1 -1
- package/dist/types-chunks/{capability.d-Ch5Vos33.d.ts → capability.d-DOF3r0fJ.d.ts} +1 -1
- package/dist/types-chunks/{capsule.d-Dj1n6s0Y.d.ts → capsule.d-B4atvlxE.d.ts} +7 -19
- package/dist/types-chunks/client-contract-A1jdk6xz.d.ts +1993 -0
- package/dist/types-chunks/{controller.d-C0IM1Tud.d.ts → controller.d-BkUJ_3sl.d.ts} +1 -1
- package/dist/types-chunks/{controller.d-J2t1q8Ly.d.ts → controller.d-yyKajPTi.d.ts} +140 -1380
- package/dist/types-chunks/{cost-tracker.d-BWI4lFWn.d.ts → cost-tracker.d-BeaenODW.d.ts} +2 -47
- package/dist/types-chunks/{history-retrieval.d-CPN5PMBV.d.ts → history-retrieval.d-JdFfkeF3.d.ts} +2 -2
- package/dist/types-chunks/{manager.d-rtmywU9M.d.ts → manager.d-C_20XqCV.d.ts} +8 -1
- package/dist/types-chunks/manifest.d-Bw2i-zQi.d.ts +18 -0
- package/dist/types-chunks/provider-credential-context.d-BH2OaB1b.d.ts +47 -0
- package/dist/types-chunks/provider-request-observation.d-jL8T6wVO.d.ts +34 -0
- package/dist/types-chunks/{public-api.d-amBop8Nk.d.ts → public-api.d-Cq8ILMte.d.ts} +52 -13
- package/dist/types-chunks/{resolver.d-BrwLoWNr.d.ts → resolver.d-DLY01RHx.d.ts} +4 -2
- package/dist/types-chunks/{types.d-CSv0_cZC.d.ts → review-inbox.d-BeaLRNHx.d.ts} +251 -3
- package/dist/types-chunks/{shell-command-sets.d-oejwpP_7.d.ts → review-packet.d-D4bbTbq3.d.ts} +46 -3
- package/dist/types-chunks/{exec-policy.d-BPESl90L.d.ts → run-manager.d-C7Q71rin.d.ts} +385 -62
- package/dist/types-chunks/runtime-client-info-CxnlZlW5.d.ts +175 -0
- package/dist/types-chunks/{sdk-session-B6XjHNU1.d.ts → sdk-session-BDFjCpDn.d.ts} +12 -4
- package/dist/types-chunks/{side-query.d-DHWG1JZg.d.ts → side-query.d-DTrhVd_r.d.ts} +4 -3
- package/dist/types-chunks/trusted-repl-entry-vbUM8R6P.d.ts +445 -0
- package/dist/types-chunks/{types.d-CtO8mR1s.d.ts → types.d-BJTN-RZr.d.ts} +5 -5
- package/dist/types-chunks/{types.d-BrQMB-hy.d.ts → types.d-BjOq57-z.d.ts} +6 -0
- package/dist/types-chunks/types.d-o7t9dds4.d.ts +1484 -0
- package/dist/types-chunks/{utils.d-DcznBeQ3.d.ts → utils.d-CWiMhFfu.d.ts} +202 -36
- package/docs/CLIENT_CONTRACT.md +441 -0
- package/docs/SDK_MIGRATION.md +123 -0
- package/docs/SPACE_SDK_SEAMS.md +139 -0
- package/package.json +10 -5
- package/public_docs/README.md +12 -133
- package/public_docs/configuration/config-files.md +8 -14
- package/public_docs/sdk/embedder-guide.md +494 -420
- package/dist/chunks/argument-completer-FAIHW7HZ.js +0 -2
- package/dist/chunks/chunk-66XN5AFU.js +0 -417
- package/dist/chunks/chunk-7O2AIFNE.js +0 -373
- package/dist/chunks/chunk-DSXUXUZG.js +0 -5
- package/dist/chunks/chunk-GYO73UYQ.js +0 -275
- package/dist/chunks/chunk-HPCS3LZ5.js +0 -324
- package/dist/chunks/chunk-HZYRLIOC.js +0 -137
- package/dist/chunks/chunk-SC2ELSUS.js +0 -675
- package/dist/chunks/chunk-TEUD5VPJ.js +0 -471
- package/dist/chunks/chunk-TYZ2ZAYL.js +0 -487
- package/dist/chunks/dist-3UCCMCYR.js +0 -2
- package/dist/chunks/dist-F5IWZSAY.js +0 -2
- package/dist/chunks/host-W2JJ3V3Q.js +0 -2
- package/dist/chunks/run-manager-RBWU3EVE.js +0 -2
- package/dist/chunks/utils-DJ4ZFJGL.js +0 -2
- package/dist/runtime-worker.js +0 -5381
- package/dist/types-chunks/review-inbox.d-CTeUIKda.d.ts +0 -225
- package/dist/types-chunks/run-manager.d-hm1XgEou.d.ts +0 -94
- package/dist/types-chunks/trusted-repl-entry-D0w5M0UZ.d.ts +0 -323
- package/dist/types-chunks/types.d-B1l9pWyX.d.ts +0 -146
|
@@ -1,48 +1,129 @@
|
|
|
1
|
-
# KodaX SDK —
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
1
|
+
# KodaX SDK — Product Client and Host Integration
|
|
2
|
+
|
|
3
|
+
This page describes the current FEATURE_298/299 development tree, whose package
|
|
4
|
+
baseline is `0.7.97-alpha.1`. Some seam additions are newer than that baseline; this does not
|
|
5
|
+
claim that this contract is already published to npm. Check the installed
|
|
6
|
+
package exports and the connected Host's capabilities when migrating.
|
|
7
|
+
|
|
8
|
+
For applications sharing KodaX sessions, use `KodaXProductClient` from
|
|
9
|
+
`@kodax-ai/kodax/client`. The Host owns execution, configuration and persistence;
|
|
10
|
+
clients submit intent, answer interactions and render Host facts. The old
|
|
11
|
+
`KodaXClient` / `Client` classes and low-level Runtime facade are different
|
|
12
|
+
objects, not alternate names for this contract.
|
|
13
|
+
|
|
14
|
+
- [Product integration](#product-client-integration): connection and lifecycle.
|
|
15
|
+
- [Migration guide](../../docs/SDK_MIGRATION.md): old-to-new calls, ownership,
|
|
16
|
+
errors, history, cancellation and acceptance checklist (Chinese).
|
|
17
|
+
- [Complete Client contract](../../docs/CLIENT_CONTRACT.md): normative behavior
|
|
18
|
+
and method inventory; [types](../../packages/coding/src/client-contract.ts).
|
|
19
|
+
- [Removed surfaces](#migrating-to-v0797): breaking changes and replacements.
|
|
20
|
+
- [Space Host seams](../../docs/SPACE_SDK_SEAMS.md): trusted Main authorization,
|
|
21
|
+
canonical Fork/Retry/Rewind, Host configuration, attachments, statistics and lifecycle limits.
|
|
22
|
+
- Numbered sections below retain low-level library/Host guidance and historical
|
|
23
|
+
release context. They are not instructions for a product UI to create its own
|
|
24
|
+
execution owner or write the shared Host's files.
|
|
25
|
+
|
|
26
|
+
## Product Client integration
|
|
27
|
+
|
|
28
|
+
### Choose the connection entry
|
|
29
|
+
|
|
30
|
+
| Need | Entry | Ownership |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| Start or attach a local compatible Host | `ensureKodaXClient(options)` | Uses the shared launcher; updates only an eligible idle Host |
|
|
33
|
+
| Attach without starting or replacing a Host | `connectKodaXClient(options)` | Passive Node connection |
|
|
34
|
+
| Browser/UI contract types | `import type` from `/client` or `@kodax-ai/coding/client-contract` | No running Host or browser transport is provided by types |
|
|
35
|
+
| Trusted Host bootstrap, scoped credentials, Host Tools, explicit embedding | `/runtime` | Separate low-level authority; never a fallback after product connection failure |
|
|
36
|
+
| Independent Agent/LLM/coding library | `/agent`, `/llm`, `/coding` | Independently usable; not a shared-Session product client |
|
|
37
|
+
|
|
38
|
+
Both product constructors return `Promise<KodaXProductClient>`. The `/client`
|
|
39
|
+
subpath is ESM; CommonJS hosts use `await import('@kodax-ai/kodax/client')`.
|
|
40
|
+
It is not a root-entry re-export. `endpoint` is a local named pipe/Unix socket,
|
|
41
|
+
not an HTTP/WebSocket address. A browser application needs its own supported
|
|
42
|
+
bridge; do not import the Node connector into browser code.
|
|
43
|
+
|
|
44
|
+
`homeDir` is the base directory containing `.kodax`, not `.kodax` itself.
|
|
45
|
+
`connect` additionally accepts `endpoint` and `token`; `ensure` accepts
|
|
46
|
+
`daemonStartupTimeoutMs`. Both accept `profile` and `clientInfo`. Presentation
|
|
47
|
+
metadata such as `clientInfo.name` grants no authority. Configure provider
|
|
48
|
+
credentials at the Host, rather than passing API keys in input submissions.
|
|
49
|
+
|
|
50
|
+
### Observe, submit, and settle
|
|
51
|
+
|
|
52
|
+
The following helper uses an existing Client and Session. The application owns
|
|
53
|
+
connection/session selection and supplies renderers that replace the displayed
|
|
54
|
+
view and answer `view.interactions` through `client.interactions.respond`.
|
|
55
|
+
Without an interaction UI, a Run can legitimately wait for an answer. This
|
|
56
|
+
example neither auto-approves requests nor infers completion from rendering.
|
|
45
57
|
|
|
58
|
+
```ts
|
|
59
|
+
import type {
|
|
60
|
+
KodaXProductClient, ClientSessionView, ClientObservationStatus,
|
|
61
|
+
} from '@kodax-ai/kodax/client';
|
|
62
|
+
|
|
63
|
+
export async function submitImmediate(
|
|
64
|
+
client: KodaXProductClient,
|
|
65
|
+
sessionId: string,
|
|
66
|
+
inputId: string,
|
|
67
|
+
text: string,
|
|
68
|
+
render: (view: ClientSessionView) => void,
|
|
69
|
+
showConnection: (status: ClientObservationStatus) => void,
|
|
70
|
+
) {
|
|
71
|
+
const observation = await client.sessions.observe(sessionId, render, {
|
|
72
|
+
onStatus: showConnection,
|
|
73
|
+
});
|
|
74
|
+
try {
|
|
75
|
+
const accepted = await client.inputs.submit({
|
|
76
|
+
sessionId, inputId, text, delivery: 'immediate',
|
|
77
|
+
});
|
|
78
|
+
if (accepted.state !== 'submitted' || !accepted.runId) {
|
|
79
|
+
throw new Error(`Input ${inputId} is ${accepted.state}; inspect its receipt before continuing.`);
|
|
80
|
+
}
|
|
81
|
+
return await client.runs.await(accepted.runId);
|
|
82
|
+
} finally {
|
|
83
|
+
observation.close(); // Detaches this observer; does not stop the Run.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Keep `inputId`, original text and artifacts before calling this helper. After a
|
|
89
|
+
lost response query `inputs.read(sessionId, inputId)` on the same Host; never
|
|
90
|
+
silently create a new ID and resubmit. This helper handles only immediate
|
|
91
|
+
submission; queued, steer and redirect flows must follow their acceptance state.
|
|
92
|
+
|
|
93
|
+
Create/select sessions using `client.sessions.create({projectPath})` or
|
|
94
|
+
`list/read`. Use `client.sessions.updateSettings` for execution choices, then
|
|
95
|
+
submit input. On application disposal call `client.disconnect()`; use
|
|
96
|
+
`runs.stop` or `sessions.cancel` for explicit Stop, and `host.shutdown()` only
|
|
97
|
+
for an explicit request to close an idle Host. `phase: 'unknown'` from
|
|
98
|
+
`runs.await` is an uncertain outcome, not success, even on a healthy connection.
|
|
99
|
+
|
|
100
|
+
### Replace the consumption model
|
|
101
|
+
|
|
102
|
+
| Concern | Product surface | Consumer responsibility |
|
|
103
|
+
| --- | --- | --- |
|
|
104
|
+
| Current UI | `sessions.observe` | Replace each view; bounded items are not a complete transcript |
|
|
105
|
+
| Full display item | `sessions.readItem` | Keep the observed ID; validate paginated original text/input |
|
|
106
|
+
| History/search | `readHistory`, `readHistoryEntry`, `searchHistory` | Keep page revision and distinct history IDs; no cross-revision splicing |
|
|
107
|
+
| Settings and discovery | `sessions.*Settings`, `config.*`, `catalog.*` | Distinguish saved overrides/defaults from effective settings |
|
|
108
|
+
| User questions and permissions | `interactions.list/respond`, `view.interactions` | Reply to the exact request; use only Host-provided grant suggestions |
|
|
109
|
+
| Commands/Skills/review | `commands.*`, `inputs.submit`, `review.start` | Host prepares trusted execution; returned Run IDs are followed, not resubmitted |
|
|
110
|
+
| Command feedback | `sessions.appendNotice` | Durable client-only notices; report failures without re-running commands |
|
|
111
|
+
| MCP/Agents/Memory/Learning/Workflow | `mcp`, `registrations`, `agents`, `memory`, `learning`, `workflows` | Use domain operations; keep executable modules and local owners out of UI code |
|
|
112
|
+
|
|
113
|
+
Observation connection errors, pending interactions and Run terminal outcomes
|
|
114
|
+
are separate facts. Workflow/Learning subscription `ready` confirms registration,
|
|
115
|
+
not snapshot synchronization; rebuild a failed subscription and read its current
|
|
116
|
+
snapshot. Reconnect does not authorize replaying mutations. See the complete
|
|
117
|
+
Client contract for nullable reads, revision conflicts, lifecycle error handling,
|
|
118
|
+
and feature-specific Host compatibility checks.
|
|
119
|
+
|
|
120
|
+
## Low-level reference and release history
|
|
121
|
+
|
|
122
|
+
The sections below describe independent libraries, trusted Host capabilities and
|
|
123
|
+
past release decisions. Their examples are scoped to those layers. Product UI
|
|
124
|
+
migrations follow the entry and lifecycle above; retained low-level exports do
|
|
125
|
+
not mean every low-level capability has a Product Client equivalent. Historical
|
|
126
|
+
capability versions and removed APIs must be read with the migration table.
|
|
46
127
|
This guide documents the SDK surfaces a host integrator needs that
|
|
47
128
|
are NOT obvious from inspecting the type definitions alone:
|
|
48
129
|
|
|
@@ -62,7 +143,7 @@ are NOT obvious from inspecting the type definitions alone:
|
|
|
62
143
|
14. [Media input artifacts — `@kodax-ai/kodax/media`](#14-media-input-artifacts--kodax-aikodaxmedia-feature_239-v0756)
|
|
63
144
|
15. [Space v0.7.57 follow-up ledger](#15-space-v0757-follow-up-ledger)
|
|
64
145
|
16. [SDK agent-profile surface — `KodaXAgentProfile`](#16-sdk-agent-profile-surface--kodaxagentprofile-feature_247-v0758)
|
|
65
|
-
17. [Runtime SDK
|
|
146
|
+
17. [Runtime SDK and local daemon](#17-runtime-sdk-and-local-daemon-feature_253-feature_257)
|
|
66
147
|
18. [External-agent executor plane](#18-external-agent-executor-plane-feature_258-v0767)
|
|
67
148
|
19. [Session surface filtering and cursor pagination](#19-session-surface-filtering-and-cursor-pagination-feature_261-v0767)
|
|
68
149
|
20. [Cost-disciplined workflow routing and telemetry](#20-cost-disciplined-workflow-routing-and-telemetry-feature_259-v0767)
|
|
@@ -77,6 +158,7 @@ are NOT obvious from inspecting the type definitions alone:
|
|
|
77
158
|
29. [Evidence-gated background Skill learning](#29-evidence-gated-background-skill-learning-feature_263-v0778)
|
|
78
159
|
30. [Standalone sandbox SDK](#30-standalone-sandbox-sdk-v0778)
|
|
79
160
|
- [Learned Skill promotion reference](#learned-skill-promotion-reference-v0778)
|
|
161
|
+
- [Migrating to v0.7.97](#migrating-to-v0797)
|
|
80
162
|
|
|
81
163
|
§1–§3 (and the Phase-7/8 MCP-popout surface in §1) land in v0.7.42
|
|
82
164
|
under FEATURE_186 (see [ADR-032](../../docs/ADR.md#adr-032-sdk-embedder-surface-closure-feature_186-v0742)).
|
|
@@ -95,6 +177,9 @@ under FEATURE_186 (see [ADR-032](../../docs/ADR.md#adr-032-sdk-embedder-surface-
|
|
|
95
177
|
|
|
96
178
|
## 1. MCP server management — `McpManager` runtime API
|
|
97
179
|
|
|
180
|
+
> Independent MCP library reference. Product clients use `client.mcp` and
|
|
181
|
+
> `client.catalog`; they do not instantiate a manager or edit the Host's JSON.
|
|
182
|
+
|
|
98
183
|
### Why this exists
|
|
99
184
|
|
|
100
185
|
`@kodax-ai/kodax/mcp` re-exports `McpCapabilityProvider`, which is the
|
|
@@ -723,6 +808,9 @@ subpaths in a follow-up release.
|
|
|
723
808
|
|
|
724
809
|
## 6. Session persistence — wiring `runKodaX` to disk
|
|
725
810
|
|
|
811
|
+
> Independent in-process library ownership only. Product clients use
|
|
812
|
+
> `client.sessions` and never attach a `SessionStorage` to a shared Host.
|
|
813
|
+
|
|
726
814
|
### The trap
|
|
727
815
|
|
|
728
816
|
```ts
|
|
@@ -1028,14 +1116,13 @@ lineage tail, or concurrent durable write fails with
|
|
|
1028
1116
|
`SessionReadError.code === 'data_changed'`. Reload, obtain a fresh boundary,
|
|
1029
1117
|
and rebuild the tail before retrying.
|
|
1030
1118
|
|
|
1031
|
-
|
|
1119
|
+
Standalone Session owners follow the same rule: the prepared-tail persistence helper
|
|
1032
1120
|
falls back to `appendSessionDelta(id, data)` after `data_changed`, so the
|
|
1033
1121
|
authoritative full snapshot merges the newest UI/session state. Background
|
|
1034
1122
|
write failures are emitted as structured diagnostics; they are not swallowed
|
|
1035
1123
|
and a stale tail is never retried unchanged.
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
[transcript ownership](#unreleased-interrupted-run-recovery-and-transcript-ownership).
|
|
1124
|
+
Product Ink sessions use the Host Client API and never save a competing local
|
|
1125
|
+
transcript or lineage; see [transcript ownership](#unreleased-interrupted-run-recovery-and-transcript-ownership).
|
|
1039
1126
|
|
|
1040
1127
|
A non-null fulfilled append result is the reusable successor boundary. A
|
|
1041
1128
|
fulfilled `null` means the tail did commit exactly once, but the successor
|
|
@@ -1580,6 +1667,9 @@ and your Node / OS / SDK version.
|
|
|
1580
1667
|
|
|
1581
1668
|
## 10. Model capabilities — context window, reasoning, descriptors
|
|
1582
1669
|
|
|
1670
|
+
> Product consumers query `client.catalog` and effective Host settings. Direct
|
|
1671
|
+
> provider construction and credential access below belong to library/Host code.
|
|
1672
|
+
|
|
1583
1673
|
### Why this exists
|
|
1584
1674
|
|
|
1585
1675
|
A popout-style UI typically wants to list every provider/model KodaX
|
|
@@ -1828,6 +1918,9 @@ metadata, we can promote the snapshot to derive from it.
|
|
|
1828
1918
|
|
|
1829
1919
|
## 11. Workflow process events and lifecycle controls (FEATURE_229, v0.7.50)
|
|
1830
1920
|
|
|
1921
|
+
> Product consumers use `client.workflows` with declarative inputs. The lower
|
|
1922
|
+
> level runner/module interfaces below remain Host integration mechanisms.
|
|
1923
|
+
|
|
1831
1924
|
FEATURE_229 makes dynamic workflow progress a reusable SDK process surface
|
|
1832
1925
|
instead of terminal-only text. Hosts can observe and control workflows without
|
|
1833
1926
|
parsing `/workflow` output, replaying slash commands, or depending on Ink view
|
|
@@ -2559,9 +2652,9 @@ ambiguous call instead of risking cross-session delivery. Low-level child-Actor
|
|
|
2559
2652
|
producers may continue to pass an explicit `agentId`.
|
|
2560
2653
|
|
|
2561
2654
|
`enqueueWithArtifacts()` is an in-process queue helper for direct/inline runs.
|
|
2562
|
-
|
|
2655
|
+
Daemon clients must use `runtime.runs.submitInput(...)` (with
|
|
2563
2656
|
the same `sessionId` and `afterRunId`) because a process-local MessageQueue
|
|
2564
|
-
cannot cross
|
|
2657
|
+
cannot cross the transport boundary. Use `delivery:'after_turn'` to create
|
|
2565
2658
|
a continuation Run after the current Run ends, or `delivery:'interrupt'` to
|
|
2566
2659
|
inject into the current active Actor Run at its next safe Runner boundary.
|
|
2567
2660
|
|
|
@@ -2682,18 +2775,25 @@ runKodaX({
|
|
|
2682
2775
|
|
|
2683
2776
|
---
|
|
2684
2777
|
|
|
2685
|
-
## 17. Runtime SDK
|
|
2778
|
+
## 17. Runtime SDK and local daemon (FEATURE_253-FEATURE_257)
|
|
2686
2779
|
|
|
2687
2780
|
`@kodax-ai/kodax/runtime` is the stable host-facing runtime facade for
|
|
2688
2781
|
applications that want KodaX as a substrate instead of only as a terminal CLI.
|
|
2689
2782
|
It wraps the same coding/session engine used by the REPL and exposes it through
|
|
2690
|
-
one interface in
|
|
2783
|
+
one interface in two deployment shapes:
|
|
2691
2784
|
|
|
2692
2785
|
- **embedded / inline**: in-process runtime owned by the caller;
|
|
2693
|
-
- **embedded / worker**: private caller-owned runtime in a disposable V8 Worker;
|
|
2694
2786
|
- **daemon**: local-only runtime owner reached through a named pipe on Windows or
|
|
2695
2787
|
a Unix domain socket on Linux/macOS.
|
|
2696
2788
|
|
|
2789
|
+
The v0.7.96 Worker-hosted embedded runtime (`isolation: 'worker'`, the
|
|
2790
|
+
`dist/runtime-worker.js` sidecar, and the `requirements.hardDispose` gate) was
|
|
2791
|
+
removed in v0.7.97. Loading the configured A2A plane is owner wiring, not
|
|
2792
|
+
Runtime magic: call `createConfiguredA2ARuntimeIntegration({ configHome })`
|
|
2793
|
+
(exported from `@kodax-ai/kodax/a2a`) and pass its `runtimeOptions` as
|
|
2794
|
+
`externalAgents` — exactly what the CLI does for both its embedded sessions
|
|
2795
|
+
and the daemon Host it launches.
|
|
2796
|
+
|
|
2697
2797
|
The daemon is not a separate product engine. It hosts the embedded runtime behind
|
|
2698
2798
|
a process boundary, so REPL, Space, IDE adapters, ACP, and custom SDK clients can
|
|
2699
2799
|
share the same profile runtime without reimplementing sessions, permissions,
|
|
@@ -2701,13 +2801,16 @@ events, config, MCP, catalogs, artifacts, or diagnostics.
|
|
|
2701
2801
|
|
|
2702
2802
|
### Which shape to use
|
|
2703
2803
|
|
|
2804
|
+
Product UI and shared-Session automation should use `/client` as described at
|
|
2805
|
+
the top of this guide. This table also identifies explicit low-level ownership.
|
|
2806
|
+
|
|
2704
2807
|
| Host scenario | Recommended shape | Why |
|
|
2705
2808
|
|---|---|---|
|
|
2706
2809
|
| Unit tests, one-off scripts, short-lived SDK tools | `createKodaXRuntime()` | No daemon lifecycle; easiest cleanup. |
|
|
2707
2810
|
| A single app owns all KodaX state in one process | `createKodaXRuntime({ mode: 'embedded' })` | Direct in-process calls and no IPC. |
|
|
2708
|
-
|
|
|
2709
|
-
|
|
|
2710
|
-
|
|
|
2811
|
+
| REPL + Space + IDE product clients | `ensureKodaXClient({ profile, homeDir })` | Starts or reuses the Host and returns the Product contract. |
|
|
2812
|
+
| Product attach-only client | `connectKodaXClient({ profile, homeDir })` | Passive; fails if no compatible Host is ready. |
|
|
2813
|
+
| Trusted low-level daemon integration | `ensureKodaXRuntime` / `connectKodaXRuntime` | Runtime services rather than Product business methods. |
|
|
2711
2814
|
| Test/CI isolated daemon namespace | pass `homeDir` and `profile` | Keeps state/config/sessions out of the user's home daemon. |
|
|
2712
2815
|
|
|
2713
2816
|
### Public construction contract
|
|
@@ -2728,26 +2831,21 @@ The important creation options are:
|
|
|
2728
2831
|
| Option | Default | Contract |
|
|
2729
2832
|
|---|---|---|
|
|
2730
2833
|
| `mode` | `'embedded'` | Chooses private ownership or a shared daemon process. |
|
|
2731
|
-
| `isolation` | `'inline'` | Embedded-only. `'worker'` creates a private Runtime Worker; daemon rejects any explicit isolation because it is already process-isolated. |
|
|
2732
|
-
| `worker.resourceLimits` | unset | Optional V8 heap/stack limits; requires `isolation: 'worker'`. |
|
|
2733
|
-
| `worker.shutdownTimeoutMs` | `2000` | Grace before the parent terminates the Runtime Worker. |
|
|
2734
|
-
| `worker.configuredA2A` | `false` | Explicitly lets the Worker owner load and reconcile `<homeDir>/.kodax/integrations/a2a.json`; installs the full list/describe/spawn/task plane inside the Worker. |
|
|
2735
|
-
| `requirements.hardDispose` | `false` | Rejects inline and daemon forms; prevents an accidental weaker ownership form. |
|
|
2736
2834
|
| `homeDir` | unset | When omitted, use the exact resolved `KODAX_HOME`. When set, this is the base directory that owns `.kodax`, with the same meaning as CLI `daemon --home`; daemon state/config live under `<homeDir>/.kodax`. |
|
|
2737
2835
|
| `profile` | `'default'` | Daemon uniqueness and runtime configuration namespace. |
|
|
2738
2836
|
| `sessionsDir` | `<homeDir>/.kodax/sessions` | Explicit session storage override. |
|
|
2739
2837
|
| `daemonStartupTimeoutMs` | `60000` | Total cold-start/concurrent-owner wait budget. |
|
|
2740
2838
|
| `daemonConnectTimeoutMs` | `2000` | Per-socket connection timeout. |
|
|
2741
2839
|
| `autoStartDaemon` | conditional | For `createKodaXRuntime({mode:'daemon'})`, true only when no explicit endpoint/transport is supplied. |
|
|
2742
|
-
| `execPolicy` | unset | Trusted host-owned administrator rules and canonical trusted-project roots.
|
|
2840
|
+
| `execPolicy` | unset | Trusted host-owned administrator rules and canonical trusted-project roots. The inline owner receives it directly; daemon mode accepts it only while auto-starting a new owner. |
|
|
2743
2841
|
| `autoReview` | unset | Trusted host-owned administrator/model guidance for Auto review. It follows the same owner-only transport contract as `execPolicy`. |
|
|
2744
2842
|
| `externalAgents` | unset | Host-installed executor factories, dispatch policy, optional credential/artifact policies, and default dispatch context. Inline owner only; see §18. |
|
|
2745
2843
|
| `requirements.externalAgents` | `false` | Reject a Runtime/daemon connection that does not advertise an installed external-agent plane. |
|
|
2746
2844
|
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2845
|
+
The former `isolation`, `worker.*`, and `requirements.hardDispose` options were
|
|
2846
|
+
removed with the Worker facade in v0.7.97; supplying them is now a plain unknown-
|
|
2847
|
+
option error. Options are never silently ignored to select a weaker ownership
|
|
2848
|
+
form.
|
|
2751
2849
|
|
|
2752
2850
|
### Basic embedded usage
|
|
2753
2851
|
|
|
@@ -2811,10 +2909,11 @@ try {
|
|
|
2811
2909
|
}
|
|
2812
2910
|
```
|
|
2813
2911
|
|
|
2814
|
-
|
|
2912
|
+
This is a low-level Runtime example, not the default product integration.
|
|
2913
|
+
`createKodaXRuntime({ mode: 'daemon' })` is a retained convenience API: when
|
|
2815
2914
|
no explicit `daemonEndpoint` or `daemonTransport` is supplied it starts or reuses
|
|
2816
|
-
the local profile daemon. `connectKodaXRuntime()` is
|
|
2817
|
-
`autoStart: true`
|
|
2915
|
+
the local profile daemon. `connectKodaXRuntime()` is passive and rejects
|
|
2916
|
+
`autoStart: true`; use `ensureKodaXRuntime()` for low-level startup/update.
|
|
2818
2917
|
|
|
2819
2918
|
Trusted `execPolicy` and `autoReview` options are owner bootstrap inputs, not
|
|
2820
2919
|
client connection settings. For a new daemon, KodaX transfers them through a
|
|
@@ -2861,11 +2960,11 @@ verified shutdown and is not silently upgraded in place. Stop it explicitly and
|
|
|
2861
2960
|
relaunch it before requiring the capability. The CLI's `kodax daemon stop
|
|
2862
2961
|
--json` follows the same daemon-plus-supervisor boundary.
|
|
2863
2962
|
|
|
2864
|
-
The daemon-owned slice does not
|
|
2865
|
-
Issue 256; that owner-lease work remains open after
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
descendant cannot be proven gone.
|
|
2963
|
+
The daemon-owned slice does not carry the former Runtime Worker's
|
|
2964
|
+
child-lifetime gap (Issue 256); that owner-lease work remains open after
|
|
2965
|
+
v0.7.87 only for constructed-handler workers, without a replacement target
|
|
2966
|
+
assigned by this release. Executor cleanup still uses identity-checked
|
|
2967
|
+
evidence and fails closed when a descendant cannot be proven gone.
|
|
2869
2968
|
|
|
2870
2969
|
### Actor settlement recovery (v0.7.84)
|
|
2871
2970
|
|
|
@@ -2886,12 +2985,16 @@ duplicate outcome. A no-op quiesce does not rewrite the Session.
|
|
|
2886
2985
|
|
|
2887
2986
|
### v0.7.85 Runtime and Memory release boundaries
|
|
2888
2987
|
|
|
2889
|
-
The v0.7.85 SDK
|
|
2890
|
-
|
|
2891
|
-
`
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2988
|
+
The v0.7.85 SDK originally added Session-scoped durable Runtime Event Journals;
|
|
2989
|
+
v0.7.97 removes that surface. Events are now a live in-process stream only:
|
|
2990
|
+
each envelope is `{ id, seq, time, sessionId, runId, turnId?, type, payload }`,
|
|
2991
|
+
where `seq` is a per-Session in-process ordering hint. It starts at `1`, resets
|
|
2992
|
+
when a Session is deleted and recreated, and is not comparable across restarts
|
|
2993
|
+
or Sessions. There is no durable `event.replay` RPC, no
|
|
2994
|
+
`{ sessionId, journalEpoch, seq }` cursor, and no `sessionEventJournal:1`
|
|
2995
|
+
capability; remote consumption reuses `session.observe` notifications, and the
|
|
2996
|
+
SDK `runtime.events.subscribe()` facade delivers the same live stream. A2A
|
|
2997
|
+
binds one Runtime Session to each Task.
|
|
2895
2998
|
|
|
2896
2999
|
Memory management is conversation-first for explicit remember, correction,
|
|
2897
3000
|
forget, recall, and exceptional-decision requests. Safe explicit mutations are
|
|
@@ -2899,8 +3002,8 @@ host-governed and immediate; ambiguous or inferred changes remain reviewable.
|
|
|
2899
3002
|
F289/F290 bound review draining and lesson/verdict admission, and the
|
|
2900
3003
|
experimental Memory SDK exposes the additive management facade only when the
|
|
2901
3004
|
supplied controller supports it. Terminal Runs with authoritative status and
|
|
2902
|
-
no queued interrupt input are restored at startup without replaying
|
|
2903
|
-
|
|
3005
|
+
no queued interrupt input are restored at startup without replaying event
|
|
3006
|
+
history. The semantic repo-intelligence Worker retires after its idle
|
|
2904
3007
|
warm-cache window, while later cache misses start a fresh Worker.
|
|
2905
3008
|
|
|
2906
3009
|
### v0.7.86 Runtime ownership and sandbox lifecycle boundaries
|
|
@@ -3016,59 +3119,6 @@ materialization point to `{ type: 'object', properties, required? }`; only
|
|
|
3016
3119
|
string names remain in `required`. This keeps the schema shown to the model and
|
|
3017
3120
|
the provider wire contract aligned across daemon and embedded hosts.
|
|
3018
3121
|
|
|
3019
|
-
### Worker-hosted embedded usage
|
|
3020
|
-
|
|
3021
|
-
```ts
|
|
3022
|
-
import { createKodaXRuntime } from '@kodax-ai/kodax/runtime';
|
|
3023
|
-
|
|
3024
|
-
const runtime = await createKodaXRuntime({
|
|
3025
|
-
mode: 'embedded',
|
|
3026
|
-
isolation: 'worker',
|
|
3027
|
-
worker: {
|
|
3028
|
-
resourceLimits: { maxOldGenerationSizeMb: 1024 },
|
|
3029
|
-
shutdownTimeoutMs: 2000,
|
|
3030
|
-
configuredA2A: true,
|
|
3031
|
-
},
|
|
3032
|
-
requirements: { externalAgents: true },
|
|
3033
|
-
});
|
|
3034
|
-
|
|
3035
|
-
try {
|
|
3036
|
-
console.log(runtime.identity.isolation); // 'worker'
|
|
3037
|
-
console.log(runtime.identity.workerThreadId); // Node Worker thread id
|
|
3038
|
-
// runtime.sessions/runs/events/... are identical to inline and daemon.
|
|
3039
|
-
} finally {
|
|
3040
|
-
await runtime.close();
|
|
3041
|
-
}
|
|
3042
|
-
```
|
|
3043
|
-
|
|
3044
|
-
`mode` describes ownership and sharing; `isolation` describes where a private
|
|
3045
|
-
embedded owner executes. Inline is the lowest-latency default. Worker is useful
|
|
3046
|
-
for Electron/Space-style hosts that need private state and deterministic V8
|
|
3047
|
-
disposal. Daemon is for durable multi-client sharing and already uses an OS
|
|
3048
|
-
process, so daemon + worker is rejected.
|
|
3049
|
-
|
|
3050
|
-
Worker `resourceLimits` bound parts of the V8 heap only. They do not cover every
|
|
3051
|
-
kind of native/external memory and do not make Node code safe to treat as
|
|
3052
|
-
untrusted. Worker isolation is a fault boundary, not a security sandbox.
|
|
3053
|
-
|
|
3054
|
-
Configured A2A is loaded by the Worker owner, not serialized from a parent
|
|
3055
|
-
factory closure. `worker.configuredA2A` is therefore an explicit opt-in. When
|
|
3056
|
-
enabled, the Worker reconciles the same user document as the CLI/daemon path,
|
|
3057
|
-
advertises `externalAgents`, and backs `listDispatchable`, `describe`,
|
|
3058
|
-
`preflight`, and external Actor dispatch with one real executor plane.
|
|
3059
|
-
|
|
3060
|
-
Callers that cannot accept a silent fallback can require the capability:
|
|
3061
|
-
|
|
3062
|
-
```ts
|
|
3063
|
-
await createKodaXRuntime({
|
|
3064
|
-
mode: 'embedded',
|
|
3065
|
-
isolation: 'worker',
|
|
3066
|
-
requirements: { hardDispose: true },
|
|
3067
|
-
});
|
|
3068
|
-
```
|
|
3069
|
-
|
|
3070
|
-
Daemon hosts advertise `hardDispose: false`; Worker hosts advertise true.
|
|
3071
|
-
|
|
3072
3122
|
### Close, abort, and ownership semantics
|
|
3073
3123
|
|
|
3074
3124
|
The same method name deliberately has deployment-specific ownership effects:
|
|
@@ -3076,17 +3126,24 @@ The same method name deliberately has deployment-specific ownership effects:
|
|
|
3076
3126
|
| Form | `runtime.close()` | Run abort | After owner crash/termination |
|
|
3077
3127
|
|---|---|---|---|
|
|
3078
3128
|
| embedded / inline | Cancels owned runs and permissions and closes private runtime state. It cannot recover a host event loop blocked by arbitrary inline code. | `runs.abort(runId)` settles the Runtime handle and forwards cancellation to coding. | The embedding process owns recovery. |
|
|
3079
|
-
| embedded / Worker | Requests shutdown, waits up to `shutdownTimeoutMs`, then always terminates the Worker. | Same Runtime abort API; closing the Runtime is the hard-disposal escalation for the whole isolate. | Pending transport requests reject; create a new Runtime explicitly. |
|
|
3080
3129
|
| daemon client | Detaches only this client transport. Other REPL/Space/SDK clients and runs remain owned by the daemon. | Aborts only the addressed run. | The client connection rejects; reconnect explicitly after the daemon is healthy. |
|
|
3081
3130
|
|
|
3082
3131
|
`close()` is idempotent. It is not a shared-daemon stop command. Use
|
|
3083
3132
|
`kodax daemon stop`, `kodax daemon restart`, or an authenticated low-level
|
|
3084
3133
|
`runtime.shutdown` request for administrative shutdown. KodaX does not
|
|
3085
|
-
automatically retry or replay an in-flight run after a
|
|
3134
|
+
automatically retry or replay an in-flight run after a daemon owner dies,
|
|
3086
3135
|
because provider and tool side effects may already have happened.
|
|
3087
3136
|
|
|
3088
|
-
`runtime.shutdown`
|
|
3089
|
-
|
|
3137
|
+
`runtime.shutdown` performs a real idle shutdown: it takes the draining fence,
|
|
3138
|
+
rechecks preflight, and stops the daemon only when no active or queued run,
|
|
3139
|
+
Workflow, Agent turn, pending permission/user input, other logical client, or
|
|
3140
|
+
in-flight mutation exists; otherwise it fails with a structured `conflict`
|
|
3141
|
+
error and the daemon keeps running. Shutdown never changes the owner mode
|
|
3142
|
+
implicitly — a daemon-to-inline ownership change goes only through an explicit
|
|
3143
|
+
`setKodaXRuntimeOwnerMode()` call, or owner-lock release followed by
|
|
3144
|
+
`acquireKodaXInlineOwner()`; the former `stopForInline()` rollback and the
|
|
3145
|
+
crash-resumable exit-settlement transaction were removed in v0.7.97. Host-close
|
|
3146
|
+
logging and owner-lock release are still intermediate
|
|
3090
3147
|
progress boundaries. A successful `kodax daemon stop` / `restart` additionally
|
|
3091
3148
|
waits for the original daemon PID to disappear and verifies a shutdown-success
|
|
3092
3149
|
outcome bound to that exact Runtime ID and PID. Before that process exits, the
|
|
@@ -3179,7 +3236,6 @@ kodax daemon status --profile default --json
|
|
|
3179
3236
|
kodax daemon logs --profile default --lines 100
|
|
3180
3237
|
kodax daemon stop --profile default --json
|
|
3181
3238
|
kodax daemon restart --profile default
|
|
3182
|
-
kodax --runtime-mode daemon
|
|
3183
3239
|
```
|
|
3184
3240
|
|
|
3185
3241
|
Inside the REPL, `/status runtime` reports embedded/daemon mode, profile,
|
|
@@ -3187,14 +3243,14 @@ runtime id, endpoint/health when applicable, and active/queued counters.
|
|
|
3187
3243
|
|
|
3188
3244
|
### Runtime services
|
|
3189
3245
|
|
|
3190
|
-
Every `KodaXRuntime` exposes the same service set in inline
|
|
3246
|
+
Every `KodaXRuntime` exposes the same service set in inline and daemon mode:
|
|
3191
3247
|
|
|
3192
3248
|
| Service | Purpose |
|
|
3193
3249
|
|---|---|
|
|
3194
|
-
| `identity` | Runtime id, mode, isolation, profile, started time, package version
|
|
3250
|
+
| `identity` | Runtime id, mode, isolation (`inline` for embedded, `process` for daemon), profile, started time, package version. |
|
|
3195
3251
|
| `sessions` | Create/load/list/fork/transcript/settings/notice/rewind/compact/archive/delete. |
|
|
3196
3252
|
| `runs` | Start/await/get/list/abort runs; update provider/model/reasoning for supported phases. |
|
|
3197
|
-
| `events` | Subscribe to live
|
|
3253
|
+
| `events` | Subscribe to the live in-process event stream (one `seq` ordering hint per Session). |
|
|
3198
3254
|
| `permissions` | Request/list/respond to tool permissions across clients. |
|
|
3199
3255
|
| `workflows` | Observe workflow process snapshots/events and lifecycle controls. |
|
|
3200
3256
|
| `config` | Read/patch/reload daemon or embedded profile config. |
|
|
@@ -3202,7 +3258,6 @@ Every `KodaXRuntime` exposes the same service set in inline, Worker, and daemon
|
|
|
3202
3258
|
| `mcp` | MCP server CRUD, validation, reload, and tool catalog listing. |
|
|
3203
3259
|
| `artifacts` | Create/get/delete runtime artifact references for file/image/video inputs. |
|
|
3204
3260
|
| `status` | Runtime snapshot with sessions, runs, permissions, workflows, and daemon counters. |
|
|
3205
|
-
| `diagnostics` | Latest context-budget and tool-exposure decisions for GUI/debug surfaces. |
|
|
3206
3261
|
| `admin.agentRegistrations` | List/upsert, atomically set `enabled` while preserving the full registration, or remove redacted external-agent registrations. Owner/revision-conditional mutation prevents a stale manager from changing a same-ID replacement. With no plane, list is empty and mutations fail clearly. |
|
|
3207
3262
|
| `agents` | Check `enabled`, list/describe policy-filtered dispatchable agents, and preflight a selected route. |
|
|
3208
3263
|
| `agentTasks` | Start/list/get/wait/continue/cancel/reconcile durable external-agent tasks and read their ordered event stream. |
|
|
@@ -3439,50 +3494,53 @@ bundles.
|
|
|
3439
3494
|
- Preserve an unknown-code/default UI path at transport boundaries so a newer
|
|
3440
3495
|
Runtime cannot turn a diagnostic extension into a failed host UI.
|
|
3441
3496
|
|
|
3442
|
-
### Session-scoped event
|
|
3497
|
+
### Session-scoped live event ordering
|
|
3443
3498
|
|
|
3444
3499
|
Runtime event order is defined inside one Session, not across the Runtime.
|
|
3445
|
-
|
|
3500
|
+
Since v0.7.97 the event surface is a live in-process stream; the durable
|
|
3501
|
+
journal, `events.replay()`, and the `{ sessionId, journalEpoch, seq }` cursor
|
|
3502
|
+
were removed. Every event envelope is:
|
|
3446
3503
|
|
|
3447
3504
|
```ts
|
|
3448
|
-
type
|
|
3505
|
+
type RuntimeEventEnvelope = {
|
|
3506
|
+
id: string;
|
|
3507
|
+
seq: number; // per-Session in-process ordering hint; starts at 1
|
|
3508
|
+
time: string;
|
|
3449
3509
|
sessionId: string;
|
|
3450
|
-
|
|
3451
|
-
|
|
3510
|
+
runId: string;
|
|
3511
|
+
turnId?: string;
|
|
3512
|
+
type: RuntimeEventType;
|
|
3513
|
+
payload: unknown;
|
|
3452
3514
|
};
|
|
3453
3515
|
```
|
|
3454
3516
|
|
|
3455
|
-
|
|
3517
|
+
`seq` is an ordering hint, not a durable cursor. It starts at `1` within one
|
|
3518
|
+
Session, resets when that Session is deleted and recreated, and is not
|
|
3519
|
+
comparable across restarts or between Sessions — do not persist it as a
|
|
3520
|
+
resume point. Consumption is subscription-shaped and always scoped:
|
|
3456
3521
|
|
|
3457
3522
|
```ts
|
|
3458
|
-
const
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3523
|
+
const sub = runtime.events.subscribe(
|
|
3524
|
+
{ sessionId: session.id }, // runId optionally narrows to one Run
|
|
3525
|
+
(event) => renderLiveEvent(event),
|
|
3526
|
+
);
|
|
3527
|
+
await sub.ready; // daemon handshake; absent for local subscriptions
|
|
3528
|
+
sub.close();
|
|
3464
3529
|
```
|
|
3465
3530
|
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
`seq: 1
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
journal known to that Run are forced to resync when the index is valid. A
|
|
3480
|
-
missing or corrupt index cannot prove that an old trimmed journal is unrelated,
|
|
3481
|
-
so that ambiguous migration case also requires a fresh snapshot.
|
|
3482
|
-
|
|
3483
|
-
### Run options across Worker/daemon boundaries
|
|
3484
|
-
|
|
3485
|
-
`runs.start({ options })` is a DTO boundary in Worker and daemon forms. Do not
|
|
3531
|
+
Remote event consumption reuses `session.observe` notifications: an
|
|
3532
|
+
observation snapshot carries a `seq` high-water, every event with
|
|
3533
|
+
`seq <= snapshot.seq` is already reflected in the snapshot, and live listener
|
|
3534
|
+
events for that observation have strictly greater `seq`. Separate Sessions may
|
|
3535
|
+
both contain `seq: 1`; that is intentional. Supplying both `sessionId` and
|
|
3536
|
+
`runId` validates their ownership before the subscription is installed.
|
|
3537
|
+
Deleting and recreating a Session invalidates outstanding observations with
|
|
3538
|
+
reason `runtime_changed`; acquire a fresh observation instead of reusing a
|
|
3539
|
+
stale projection or sequence number.
|
|
3540
|
+
|
|
3541
|
+
### Run options across the daemon boundary
|
|
3542
|
+
|
|
3543
|
+
`runs.start({ options })` is a DTO boundary in daemon form. Do not
|
|
3486
3544
|
pass process-local objects such as `extensionRuntime`, callbacks, `AbortSignal`,
|
|
3487
3545
|
LSP services, class instances, or cyclic structures. KodaX rejects them before
|
|
3488
3546
|
transport instead of silently dropping fields.
|
|
@@ -3509,9 +3567,9 @@ For daemon mode, extension and MCP ownership follows daemon configuration.
|
|
|
3509
3567
|
Configure extensions in the daemon profile and call
|
|
3510
3568
|
`runtime.catalog.reloadExtensions()` or the matching config service. A CLI
|
|
3511
3569
|
`--extension <path>` is intentionally rejected in daemon mode because that
|
|
3512
|
-
process-local object cannot become part of a durable shared owner.
|
|
3513
|
-
|
|
3514
|
-
|
|
3570
|
+
process-local object cannot become part of a durable shared owner. Use
|
|
3571
|
+
owner-readable config/module descriptors or inline mode for host-created
|
|
3572
|
+
extension objects.
|
|
3515
3573
|
|
|
3516
3574
|
### Permissions across clients
|
|
3517
3575
|
|
|
@@ -3565,7 +3623,7 @@ argument, `{ signal }`; abort the visible prompt when it fires.
|
|
|
3565
3623
|
`createKodaXRuntime({ userInputTimeoutMs })` and daemon auto-start use an
|
|
3566
3624
|
independent AskUser deadline (300,000 ms by default). The value must be a
|
|
3567
3625
|
positive integer no greater than 2,147,483,647 and is validated before
|
|
3568
|
-
embedded
|
|
3626
|
+
embedded or daemon startup. The same bound applies to
|
|
3569
3627
|
`permissionTimeoutMs`, except that its existing value `0` disables the
|
|
3570
3628
|
permission timer. On expiry, the Runtime accepts only a model-supplied default that is
|
|
3571
3629
|
valid for the rendered options and selection bounds; otherwise it dismisses
|
|
@@ -3638,25 +3696,22 @@ engine:
|
|
|
3638
3696
|
bridge discovery resident;
|
|
3639
3697
|
- tool-search/describe/call-style bridge semantics keep tools reachable;
|
|
3640
3698
|
- repo-intelligence schemas remain discoverable under pressure;
|
|
3641
|
-
- context-aware tool result budgets and compaction pressure
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
snapshots contain counts, and cache diagnostics contain hashes plus
|
|
3658
|
-
Provider-reported usage; they do not contain raw prompt or sensitive tool
|
|
3659
|
-
input/output.
|
|
3699
|
+
- context-aware tool result budgets and compaction pressure surface as bounded
|
|
3700
|
+
diagnostic events.
|
|
3701
|
+
|
|
3702
|
+
The v0.7.96 pull-style diagnostics RPCs (`context.budget.get`,
|
|
3703
|
+
`tool.exposure.preview`, `provider.cache.diagnostics.get` and the
|
|
3704
|
+
`runtime.diagnostics.latestContextBudget()` / `latestToolExposure()` /
|
|
3705
|
+
`latestProviderCacheDiagnostic()` facade) were removed in v0.7.97. The
|
|
3706
|
+
`capabilities.contextDiagnostics: true` client capability now only gates
|
|
3707
|
+
delivery of diagnostic event notifications (`context.budget.snapshot`,
|
|
3708
|
+
`tool.exposure.planned`, `provider.cache.diagnostics`, and
|
|
3709
|
+
`context.compaction.skipped`) on the live event stream; consume them through
|
|
3710
|
+
`runtime.events.subscribe(...)` or a `session.observe` snapshot. Diagnostic
|
|
3711
|
+
payloads carry `contextId` and, for children, `parentContextId`. These
|
|
3712
|
+
diagnostics are designed for status panels and debugging: budget snapshots
|
|
3713
|
+
contain counts, and cache diagnostics contain hashes plus Provider-reported
|
|
3714
|
+
usage; they do not contain raw prompt or sensitive tool input/output.
|
|
3660
3715
|
|
|
3661
3716
|
### Protocol schema and versioning
|
|
3662
3717
|
|
|
@@ -3678,7 +3733,9 @@ fields requires a protocol version bump.
|
|
|
3678
3733
|
### v0.7.69 Runtime verification record
|
|
3679
3734
|
|
|
3680
3735
|
This subsection is the historical verification record for the original shared
|
|
3681
|
-
Runtime delivery.
|
|
3736
|
+
Runtime delivery. The Worker-isolation gates it records validated the Worker
|
|
3737
|
+
facade that v0.7.97 later removed; the current deployment shapes are inline
|
|
3738
|
+
embedded and daemon only. Current 0.7.80 release gates and evidence live in
|
|
3682
3739
|
[`docs/release.md`](https://github.com/icetomoyo/KodaX/blob/main/docs/release.md#v0780-release-preparation).
|
|
3683
3740
|
|
|
3684
3741
|
The v0.7.69 release validation covers the runtime migration, the Worker
|
|
@@ -3693,8 +3750,8 @@ daemon delivery:
|
|
|
3693
3750
|
entries on Node 20 and Node 22;
|
|
3694
3751
|
- runtime/daemon/SDK/ACP/REPL integration tests, including process-distinct SDK
|
|
3695
3752
|
auto-start and multi-client sessions/permissions;
|
|
3696
|
-
- Worker Runtime identity, service parity, hard close,
|
|
3697
|
-
and contradictory-option rejection;
|
|
3753
|
+
- the (since-removed) Worker Runtime's identity, service parity, hard close,
|
|
3754
|
+
capability requirements, and contradictory-option rejection;
|
|
3698
3755
|
- constructed-handler reverse tool RPC, abort bridging, CPU-loop termination,
|
|
3699
3756
|
respawn, and revoke/dispose queue drainage;
|
|
3700
3757
|
- context/tool-exposure eval gate;
|
|
@@ -3716,10 +3773,12 @@ daemon delivery:
|
|
|
3716
3773
|
Tool reverse bridges, owner fencing, restart outcomes, and process-distinct
|
|
3717
3774
|
client/daemon smokes with credential-canary scans;
|
|
3718
3775
|
- a fresh `0.7.69` tarball consumer importing all 11 public subpaths, creating a
|
|
3719
|
-
|
|
3720
|
-
|
|
3776
|
+
session through the embedded Worker form (removed in v0.7.97), running the
|
|
3777
|
+
packaged CLI, and checking packaged DTS and sidecars; plus a Windows x64
|
|
3778
|
+
binary/version/sidecar smoke;
|
|
3721
3779
|
- external fresh npm consumer installation of the `0.7.67` tarball, proving
|
|
3722
|
-
Worker isolation
|
|
3780
|
+
the embedded Worker isolation contract (removed in v0.7.97) and a distinct
|
|
3781
|
+
daemon PID through the published subpath;
|
|
3723
3782
|
- Ubuntu Node 22 Unix-domain-socket daemon gate, including two clients sharing
|
|
3724
3783
|
one runtime and cross-client permission resolution.
|
|
3725
3784
|
|
|
@@ -3749,15 +3808,15 @@ runtime a specific A2A, MCP, or HTTP client. The public contracts live in
|
|
|
3749
3808
|
|
|
3750
3809
|
### Ownership rule
|
|
3751
3810
|
|
|
3752
|
-
An `AgentExecutorFactory` contains functions, so it cannot cross a
|
|
3753
|
-
|
|
3811
|
+
An `AgentExecutorFactory` contains functions, so it cannot cross a daemon DTO
|
|
3812
|
+
boundary. Install factories where the Runtime owner executes:
|
|
3754
3813
|
|
|
3755
3814
|
| Desired owner | Supported construction |
|
|
3756
3815
|
|---|---|
|
|
3757
|
-
| Private in-process owner | `createKodaXRuntime({ mode: 'embedded',
|
|
3816
|
+
| Private in-process owner | `createKodaXRuntime({ mode: 'embedded', externalAgents })` |
|
|
3758
3817
|
| New locally hosted daemon owner | `createKodaXRuntime({ mode: 'daemon', profile: '<unique>', externalAgents })` |
|
|
3759
3818
|
| Existing daemon | Configure its owner, then attach with `connectKodaXRuntime({ requirements: { externalAgents: true } })`; a client cannot inject factories. |
|
|
3760
|
-
|
|
|
3819
|
+
| Built-in configured A2A plane | Wire it in the owner: `createConfiguredA2ARuntimeIntegration({ configHome })` → pass `runtimeOptions` as `externalAgents` (the KodaX CLI does this for its embedded sessions and the daemon Host it launches; an SDK-created runtime never reads `integrations/a2a.json` on its own). The former `worker: { configuredA2A: true }` opt-in was removed with the Worker facade in v0.7.97. |
|
|
3761
3820
|
|
|
3762
3821
|
When `mode: 'daemon'` and `externalAgents` are supplied, the caller must win a
|
|
3763
3822
|
new in-process daemon lease. KodaX rejects an already-running profile instead of
|
|
@@ -3778,7 +3837,6 @@ import { createKodaXRuntime } from '@kodax-ai/kodax/runtime';
|
|
|
3778
3837
|
|
|
3779
3838
|
const runtime = await createKodaXRuntime({
|
|
3780
3839
|
mode: 'embedded',
|
|
3781
|
-
isolation: 'inline',
|
|
3782
3840
|
externalAgents: {
|
|
3783
3841
|
factories: [createReferenceAgentExecutorFactory({
|
|
3784
3842
|
executorId: 'example-http',
|
|
@@ -4204,7 +4262,7 @@ await runKodaX(
|
|
|
4204
4262
|
);
|
|
4205
4263
|
```
|
|
4206
4264
|
|
|
4207
|
-
`memoryRecallRunner` is a process-local function binding.
|
|
4265
|
+
`memoryRecallRunner` is a process-local function binding. Daemon DTO
|
|
4208
4266
|
options reject it instead of silently dropping it; configure the binding
|
|
4209
4267
|
inside the Runtime owner or keep this run inline. The selector can return only
|
|
4210
4268
|
exact IDs from the closed offered set and is capped at three calls per memory
|
|
@@ -4297,7 +4355,6 @@ const discovered = await discoverA2ARegistration({
|
|
|
4297
4355
|
|
|
4298
4356
|
const runtime = await createKodaXRuntime({
|
|
4299
4357
|
mode: 'embedded',
|
|
4300
|
-
isolation: 'inline',
|
|
4301
4358
|
externalAgents: {
|
|
4302
4359
|
factories: [createA2AAgentExecutorFactory(client)],
|
|
4303
4360
|
credentialBroker: {
|
|
@@ -4561,7 +4618,7 @@ import {
|
|
|
4561
4618
|
} from '@kodax-ai/kodax/a2a';
|
|
4562
4619
|
import { createKodaXRuntime } from '@kodax-ai/kodax/runtime';
|
|
4563
4620
|
|
|
4564
|
-
const runtime = await createKodaXRuntime({ mode: 'embedded'
|
|
4621
|
+
const runtime = await createKodaXRuntime({ mode: 'embedded' });
|
|
4565
4622
|
const server = createKodaXA2AServer({
|
|
4566
4623
|
runtime,
|
|
4567
4624
|
dataDir: '/var/lib/kodax/a2a',
|
|
@@ -4648,6 +4705,10 @@ The normative baseline is A2A repository commit
|
|
|
4648
4705
|
|
|
4649
4706
|
## 23. Shared Coder daemon for Space and IDE hosts (FEATURE_269, v0.7.69)
|
|
4650
4707
|
|
|
4708
|
+
> Trusted Electron Main/Host integration reference, including capabilities not
|
|
4709
|
+
> exposed by Product Client. UI business operations use `/client`; do not port
|
|
4710
|
+
> this entire Runtime facade into the renderer. See the migration guide above.
|
|
4711
|
+
|
|
4651
4712
|
FEATURE_269 makes one local daemon the source of truth for a Coder profile.
|
|
4652
4713
|
CLI, Space, IDE, and SDK clients can observe and control the same sessions and
|
|
4653
4714
|
runs. The transport remains local to the current OS user; it is not a remote
|
|
@@ -4664,7 +4725,8 @@ data root.
|
|
|
4664
4725
|
Space should own the daemon SDK client in Electron Main. Persist a random,
|
|
4665
4726
|
stable `instanceId` and a separate 32+ character `instanceSecret` per Space
|
|
4666
4727
|
installation. Store the secret in the OS keychain; never accept either value
|
|
4667
|
-
from renderer or model output. `connectKodaXRuntime()` is
|
|
4728
|
+
from renderer or model output. `connectKodaXRuntime()` is passive;
|
|
4729
|
+
use `ensureKodaXRuntime()` for low-level startup/update.
|
|
4668
4730
|
An explicit inline rollback policy blocks auto-start until the owner policy is
|
|
4669
4731
|
explicitly changed back to daemon.
|
|
4670
4732
|
|
|
@@ -4683,7 +4745,7 @@ and cannot resume the old bridge's leases. Restore the exact existing identity
|
|
|
4683
4745
|
from verified recovery material, or explicitly treat it as a new identity.
|
|
4684
4746
|
|
|
4685
4747
|
For Electron, `homeDir` is still the CLI-style base directory, not
|
|
4686
|
-
`process.env.KODAX_HOME`. Packaged/asar applications may use `
|
|
4748
|
+
`process.env.KODAX_HOME`. Packaged/asar applications may use `ensureKodaXRuntime()`
|
|
4687
4749
|
directly; the SDK launches only the daemon child in Electron's Node execution
|
|
4688
4750
|
mode and does not mutate the application's environment or start a second GUI
|
|
4689
4751
|
instance. `ELECTRON_RUN_AS_NODE` exists only at the child exec boundary and is
|
|
@@ -4694,7 +4756,7 @@ Packaged auto-start requires Electron's `RunAsNode` fuse, which Electron enables
|
|
|
4694
4756
|
by default. If an embedder deliberately disables that fuse, the packaged
|
|
4695
4757
|
executable cannot serve as a detached Node host: start the daemon with an
|
|
4696
4758
|
ordinary Node/CLI process and use attach-only mode instead. A packaged
|
|
4697
|
-
|
|
4759
|
+
startup timeout includes this fuse requirement in its diagnostic; the
|
|
4698
4760
|
SDK does not relaunch the GUI or silently fall back to an inline Runtime.
|
|
4699
4761
|
|
|
4700
4762
|
### Packaged Electron native artifact layout
|
|
@@ -4730,11 +4792,10 @@ evidence schema while a new build is prepared. A new process with a new embedded
|
|
|
4730
4792
|
hash publishes its own immutable generation atomically.
|
|
4731
4793
|
|
|
4732
4794
|
```ts
|
|
4733
|
-
import {
|
|
4795
|
+
import { ensureKodaXRuntime } from '@kodax-ai/kodax/runtime';
|
|
4734
4796
|
|
|
4735
|
-
const runtime = await
|
|
4797
|
+
const runtime = await ensureKodaXRuntime({
|
|
4736
4798
|
profile: 'coder',
|
|
4737
|
-
autoStart: true,
|
|
4738
4799
|
// Opt in only when this product remains the visible owner of the daemon.
|
|
4739
4800
|
// If the product crashes, the daemon stops after its final client is gone
|
|
4740
4801
|
// and governed work becomes idle.
|
|
@@ -4750,10 +4811,8 @@ const runtime = await connectKodaXRuntime({
|
|
|
4750
4811
|
capabilities: {
|
|
4751
4812
|
richEvents: true,
|
|
4752
4813
|
permissionPrompts: true,
|
|
4753
|
-
operationDeduplication: true,
|
|
4754
4814
|
},
|
|
4755
4815
|
requirements: {
|
|
4756
|
-
operationDeduplication: 1,
|
|
4757
4816
|
sessionObservation: 1,
|
|
4758
4817
|
afterTurnInput: 1,
|
|
4759
4818
|
interruptInput: 1,
|
|
@@ -4790,7 +4849,7 @@ Coder. Products that depend on same-Run delivery should require
|
|
|
4790
4849
|
silently substitute `delivery:'after_turn'` unless that is the user's intent.
|
|
4791
4850
|
|
|
4792
4851
|
The SDK requires `runtimeAutoModeGuardrail:6` and
|
|
4793
|
-
`sharedSessionSettings:2` automatically for ordinary
|
|
4852
|
+
`sharedSessionSettings:2` automatically for ordinary launcher startup.
|
|
4794
4853
|
The capability gate prevents an alpha.6 client from attaching to an alpha.3
|
|
4795
4854
|
daemon that advertises the older permission-before-sandbox contract. Supplying
|
|
4796
4855
|
`daemonOrphanExitMs` additionally requires the
|
|
@@ -4833,11 +4892,11 @@ Require it before auto-start so an idle daemon that still exposes the legacy
|
|
|
4833
4892
|
ordinary-history projection is replaced; a busy or otherwise unsafe owner
|
|
4834
4893
|
produces the normal capability-upgrade error.
|
|
4835
4894
|
|
|
4836
|
-
`KODAX_RUNTIME_SDK_CAPABILITIES.sandboxRuntime` is `11` in v0.7.
|
|
4895
|
+
`KODAX_RUNTIME_SDK_CAPABILITIES.sandboxRuntime` is `11` in v0.7.97
|
|
4837
4896
|
and `crashOutcomeModel` remains `2`. Windows auto-start requires
|
|
4838
4897
|
`sandboxRuntime:11`, so an idle v10-or-older daemon is replaced. Concurrent
|
|
4839
4898
|
authenticated upgrade clients converge on one fenced replacement, including
|
|
4840
|
-
the exact
|
|
4899
|
+
the exact revision-CAS attach window; a busy daemon or one with
|
|
4841
4900
|
untrusted clients remains untouched and returns structured restart guidance. Version 6 means that
|
|
4842
4901
|
trusted text transactions are host-owned and the native shell runner has no
|
|
4843
4902
|
command-lifetime filesystem-effect lease; a v5 daemon cannot be reused for
|
|
@@ -4852,121 +4911,64 @@ must instead be stopped/upgraded. `reclaimStaleKodaXFileLock` remains an
|
|
|
4852
4911
|
explicit stale-lock helper for APIs that still use file locks, not a general
|
|
4853
4912
|
lock-deletion primitive.
|
|
4854
4913
|
|
|
4855
|
-
###
|
|
4856
|
-
|
|
4857
|
-
Hosts that own a complete Runtime exit can use the SDK transaction instead of
|
|
4858
|
-
duplicating stop, process-tree, Job, ACL, and owner-policy recovery logic:
|
|
4859
|
-
|
|
4860
|
-
```ts
|
|
4861
|
-
import { settleKodaXRuntimeExit } from '@kodax-ai/kodax/runtime';
|
|
4862
|
-
|
|
4863
|
-
const outcome = await settleKodaXRuntimeExit({
|
|
4864
|
-
configHome: coderConfigHome,
|
|
4865
|
-
profile: 'coder',
|
|
4866
|
-
runtime, // optional; omit only when resuming a prepared ticket after relaunch
|
|
4867
|
-
});
|
|
4868
|
-
|
|
4869
|
-
if (outcome.status === 'blocked') {
|
|
4870
|
-
// Keep the host open, relaunch the product, restart the OS, or request
|
|
4871
|
-
// explicit manual recovery according to outcome.nextAction.
|
|
4872
|
-
reportRuntimeExitBlock(outcome.reason, outcome.nextAction);
|
|
4873
|
-
} else {
|
|
4874
|
-
reportRuntimeExit(outcome.status, outcome.repairs);
|
|
4875
|
-
}
|
|
4876
|
-
```
|
|
4877
|
-
|
|
4878
|
-
`runtimeExitSettlement:2` is a local SDK capability and does not add a daemon
|
|
4879
|
-
handshake requirement. The SDK writes an exact owner/process-start and platform
|
|
4880
|
-
boot identity before cooperative stop, then returns `clean` only after the
|
|
4881
|
-
durable shutdown outcome and required exits are verified. `recovered` may repair
|
|
4882
|
-
only identity-scoped Windows process/Job/ACL residue, or exact POSIX owner/state
|
|
4883
|
-
residue after a boot-identity change. Same-boot POSIX uncertainty, active work,
|
|
4884
|
-
PID reuse, foreign markers, corrupt tickets, and replacement owners return
|
|
4885
|
-
`blocked`; the SDK never exposes a bare-PID kill, raw marker deletion, or forced
|
|
4886
|
-
ACL-recovery primitive. Version 2 removes the final same-boot Windows manual
|
|
4887
|
-
cleanup hole: stale, uncontained recovery tickets are retried through the
|
|
4888
|
-
sandbox account's own runner and clear only after an exact SID-idle proof. The
|
|
4889
|
-
transaction has a fixed bounded deadline and does not accept caller-supplied
|
|
4890
|
-
short timeouts.
|
|
4891
|
-
|
|
4892
|
-
After a verified Windows boot change, settlement may also recover shared ACL
|
|
4893
|
-
state when a machine-lock recheck proves that every primary and legacy marker
|
|
4894
|
-
has a canonical non-current boot identity. The recovered scope, repair fact,
|
|
4895
|
-
and recovery boot identity are durably recorded before a second lock-scoped
|
|
4896
|
-
recheck removes markers. If Windows restarts again before clear, native
|
|
4897
|
-
recovery repeats against the new boot before the recorded identity advances.
|
|
4898
|
-
Same-boot or unverifiable markers remain `blocked`. A durable Windows
|
|
4899
|
-
`failed` shutdown outcome ends the 170-second orderly wait and enters exact
|
|
4900
|
-
recovery immediately. Anthropic/OpenAI `APIUserAbortError` objects are
|
|
4901
|
-
classified by isolated SDK class identity when the request signal is already
|
|
4902
|
-
aborted, so managed Stop stays interrupted before credential redaction.
|
|
4903
|
-
|
|
4904
|
-
When the host is about to close, pass the connected Runtime so the SDK can
|
|
4905
|
-
record the exact owner and management revision. After a crash, call the same
|
|
4906
|
-
function with only `configHome` and `profile` to resume a still-exact prepared
|
|
4907
|
-
ticket. Do not delete `exit-settlement.json`, clear ACL markers, or start a
|
|
4908
|
-
replacement owner while a settlement is `prepared` or `stop_accepted`.
|
|
4914
|
+
### Windows lifecycle diagnostics
|
|
4909
4915
|
|
|
4910
4916
|
Windows lifecycle diagnostics use the existing process-local
|
|
4911
4917
|
`setKodaXDiagnosticSink` export from `@kodax-ai/kodax/agent`. Install the sink
|
|
4912
|
-
before connecting or
|
|
4918
|
+
before connecting or ensuring Runtime ownership, and call its returned cleanup
|
|
4913
4919
|
function when the host closes. The daemon already writes its own diagnostics
|
|
4914
4920
|
to `daemon.log`; a client-process sink does not subscribe to daemon-process
|
|
4915
4921
|
events.
|
|
4916
4922
|
|
|
4917
4923
|
`source: 'runtime:windows'` identifies boot identity, Job membership, process
|
|
4918
|
-
snapshot, process-start identity
|
|
4924
|
+
snapshot, and process-start identity stages. Probe
|
|
4919
4925
|
details report availability, whether a cached result was used, and (for an
|
|
4920
4926
|
executed probe) elapsed time, timeout, exit code, and a bounded OS error code.
|
|
4921
|
-
|
|
4922
|
-
owner identities. `source: 'runtime.daemon.capabilities'` with
|
|
4927
|
+
`source: 'runtime.daemon.capabilities'` with
|
|
4923
4928
|
`stage: 'capability-check'` records the original required capability and version
|
|
4924
|
-
before a subsequent upgrade
|
|
4929
|
+
before a subsequent upgrade failure can obscure it.
|
|
4925
4930
|
|
|
4926
4931
|
These records omit commands, environment variables, stdout, stderr, credentials,
|
|
4927
4932
|
and identity values. They do not add probes or retries, change existing failure
|
|
4928
|
-
caching, relax Job/identity checks, or alter
|
|
4933
|
+
caching, relax Job/identity checks, or alter shutdown results. A missing
|
|
4929
4934
|
capability diagnostic is evidence for troubleshooting, not permission to bypass
|
|
4930
4935
|
the required capability. Diagnostic sink exceptions remain isolated from the
|
|
4931
4936
|
Runtime operation.
|
|
4932
4937
|
|
|
4933
4938
|
### Unreleased: interrupted Run recovery and transcript ownership
|
|
4934
4939
|
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
the
|
|
4966
|
-
|
|
4967
|
-
host's existing transcript intact. Embedders must not build a second
|
|
4968
|
-
conversation writer from streaming callbacks; use the Runtime Session APIs
|
|
4969
|
-
and presentation overlays instead.
|
|
4940
|
+
The current development tree integrates the rc.14 fixes under FEATURE_298 /
|
|
4941
|
+
v0.7.97. Product applications use [/client](#product-client-integration), and
|
|
4942
|
+
the Host is the only Session writer. Ink/classic consumers render Host facts
|
|
4943
|
+
and submit intents; they do not save a competing transcript or lineage.
|
|
4944
|
+
|
|
4945
|
+
Runtime-owned managed Runs save generated messages and tool results at Runner
|
|
4946
|
+
commit boundaries. An interrupted Run can contribute a bounded recovery note
|
|
4947
|
+
to the next SA or AMA model request. Its sources are canonical Session/active
|
|
4948
|
+
lineage, Run status, and successfully saved display checkpoints. The Host
|
|
4949
|
+
flushes the existing writer before reading; it does not replay durable events
|
|
4950
|
+
or infer success from telemetry. Failed checkpoint reads/writes remain errors.
|
|
4951
|
+
|
|
4952
|
+
Evidence uses accepted input and turn identities, explicit sourceRunId /
|
|
4953
|
+
sourceTurnId, assistant outputId, and the assistantOutputId owning a tool call.
|
|
4954
|
+
A proposed tool is not an executed effect. Execution without a recorded result
|
|
4955
|
+
has an unknown outcome, including a displayed cancelled tool whose result was
|
|
4956
|
+
never saved. Already committed output is excluded by identity, so two equal
|
|
4957
|
+
replies with different outputIds remain distinct. Thinking, child output, and
|
|
4958
|
+
ordinary notices never enter the recovery record.
|
|
4959
|
+
|
|
4960
|
+
The record covers at most three Runs and 6,000 characters, giving operations
|
|
4961
|
+
priority over quoted, unconfirmed reply excerpts. It is transient model context,
|
|
4962
|
+
never a user instruction or canonical Session message. No automatic tool redo
|
|
4963
|
+
or recovery of uncheckpointed tokens is promised. Tool-only invocations make
|
|
4964
|
+
no model call and need no recovery note. Standalone callers can supply the
|
|
4965
|
+
internal KodaXInterruptedRunEvidence / Operation / Reply handoff types through
|
|
4966
|
+
context.interruptedRunEvidence; that option is not a persistence protocol.
|
|
4967
|
+
|
|
4968
|
+
Uncertain Shell cleanup retains deferred process ownership while allowing the
|
|
4969
|
+
next Run and Host close to proceed. ClientRunStatus and ClientRunOutcome expose
|
|
4970
|
+
the Host terminal.effectOutcome and Stop facts. A completed execution with
|
|
4971
|
+
unknown effects does not prove cleanup or confirm Stop.
|
|
4970
4972
|
|
|
4971
4973
|
### Historical v0.7.92 filesystem-effect coordinator and managed terminal authority
|
|
4972
4974
|
|
|
@@ -5001,16 +5003,13 @@ message-derived transcript plus optional display overlays. Do not treat
|
|
|
5001
5003
|
Presentation-only synthetic completion events remain host-owned when that
|
|
5002
5004
|
cache is non-empty.
|
|
5003
5005
|
|
|
5004
|
-
Observation boundaries such as `events.subscribe()
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
required first sample plus the most recent sample; discarded intermediate
|
|
5012
|
-
snapshots are not lifecycle events, and surviving samples retain their latest
|
|
5013
|
-
emission order.
|
|
5006
|
+
Observation boundaries such as `events.subscribe()` and Session status
|
|
5007
|
+
projection deliver the live in-process stream; since v0.7.97 removed the
|
|
5008
|
+
durable event journal, there is no replay boundary, durable append, or
|
|
5009
|
+
stale-waterline failure mode on this path. Latest-only progress coalescing
|
|
5010
|
+
preserves its required first sample plus the most recent sample; discarded
|
|
5011
|
+
intermediate snapshots are not lifecycle events, and surviving samples retain
|
|
5012
|
+
their latest emission order.
|
|
5014
5013
|
|
|
5015
5014
|
When a healthy profile daemon is too old, the SDK first reads capabilities from
|
|
5016
5015
|
the authenticated health probe, before attaching the embedder's stable client
|
|
@@ -5018,11 +5017,12 @@ identity or restoring its reverse bridge. The incompatible daemon is contacted
|
|
|
5018
5017
|
with an ephemeral upgrade identity. The SDK requires `daemonManagement:1`,
|
|
5019
5018
|
takes a revision/owner-policy fenced preflight, and replaces it only when no
|
|
5020
5019
|
active or queued run, Workflow, Agent turn, pending permission/user input, or
|
|
5021
|
-
other logical client exists. Replacement
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5020
|
+
other logical client exists. Replacement performs a fenced idle shutdown: it
|
|
5021
|
+
verifies the captured owner/process-start identity, sends `runtime.shutdown`,
|
|
5022
|
+
waits for the complete process exit, and then starts the packaged Runtime.
|
|
5023
|
+
v0.7.97 removed the crash-resumable exit-settlement ticket this path
|
|
5024
|
+
previously reused; there is no prepared-ticket state to preserve across a
|
|
5025
|
+
crash mid-upgrade.
|
|
5026
5026
|
A busy or still-older daemon is never stopped: the connection rejects with
|
|
5027
5027
|
`RuntimeDaemonCapabilityUpgradeError`, whose `recoverable` and
|
|
5028
5028
|
`restartRequired` fields are `true` and whose optional `preflight` explains the
|
|
@@ -5041,8 +5041,8 @@ The packaged daemon authenticates one local OS-user/profile trust domain with
|
|
|
5041
5041
|
a random token stored beside daemon state and a user-only local endpoint. It
|
|
5042
5042
|
does not issue a different daemon token to each application in v0.7.69. The
|
|
5043
5043
|
returned scope set is chosen by the host (the packaged host grants the public
|
|
5044
|
-
local-user set). `clientInfo.instanceId` is stable attribution
|
|
5045
|
-
|
|
5044
|
+
local-user set). `clientInfo.instanceId` is stable attribution: the daemon
|
|
5045
|
+
derives its authenticated connection principal from it. `instanceSecret` proves that a new authenticated
|
|
5046
5046
|
connection is the same stable client when it resumes that client's credential
|
|
5047
5047
|
or Host Tool leases; only its hash participates in daemon-owned bridge state.
|
|
5048
5048
|
Keep all three values in Electron Main. Mutually distrusting processes running
|
|
@@ -5119,9 +5119,9 @@ including its stable KodaX code, stage, bounded display message, and optional
|
|
|
5119
5119
|
sanitized upstream metadata.
|
|
5120
5120
|
Sandbox and managed-child termination failures are observed and retained as
|
|
5121
5121
|
diagnostics rather than escaping as process-global unhandled rejections.
|
|
5122
|
-
If terminal status persistence fails
|
|
5123
|
-
|
|
5124
|
-
|
|
5122
|
+
If terminal status persistence fails, Runtime still publishes `run.updated`
|
|
5123
|
+
with `phase:'unknown'` on the live event stream. If live delivery fails too,
|
|
5124
|
+
active `sessions.observe()` handles resolve
|
|
5125
5125
|
`invalidated` with `reason:'delivery_failed'`; consumers must discard their
|
|
5126
5126
|
local projection and acquire a fresh observation instead of retaining a stale
|
|
5127
5127
|
running/terminal state.
|
|
@@ -5231,10 +5231,10 @@ runtime.connection?.subscribe((state) => {
|
|
|
5231
5231
|
});
|
|
5232
5232
|
```
|
|
5233
5233
|
|
|
5234
|
-
The SDK reports the current `connectionId`, `runtimeEpoch`,
|
|
5235
|
-
|
|
5234
|
+
The SDK reports the current `connectionId`, `runtimeEpoch`,
|
|
5235
|
+
disconnect reason, and whether a new connection may be
|
|
5236
5236
|
attempted. It does not transparently replay requests or subscriptions. Space
|
|
5237
|
-
creates a replacement Runtime client, checks its new
|
|
5237
|
+
creates a replacement Runtime client, checks its new epoch, resumes eligible
|
|
5238
5238
|
leases, and observes the session again.
|
|
5239
5239
|
|
|
5240
5240
|
`RuntimeDaemonDisconnectCode` reports only transport-observable facts:
|
|
@@ -5291,54 +5291,50 @@ restart changes `runtimeId`. The observation's `invalidated` promise reports
|
|
|
5291
5291
|
`transport_disconnected`; after it resolves, no state derived from that
|
|
5292
5292
|
observation remains authoritative. Restart recovery interrupts only a Run
|
|
5293
5293
|
whose owner is definitely gone; uncertain external execution is `unknown`.
|
|
5294
|
-
Timeout or cancellation removes the daemon request immediately.
|
|
5295
|
-
|
|
5296
|
-
the
|
|
5294
|
+
Timeout or cancellation removes the daemon request immediately. A result that
|
|
5295
|
+
arrives after its reader abandoned the request is dropped — the transport
|
|
5296
|
+
sends a hygiene `request.cancel` so the Host frees the in-flight record and
|
|
5297
|
+
any subscription it created, but no late delivery reaches the caller.
|
|
5297
5298
|
|
|
5298
5299
|
### Durable mutations, stable ordering, and settings CAS
|
|
5299
5300
|
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
control
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5301
|
+
Public control mutations no longer take an operation envelope. v0.7.97 removed
|
|
5302
|
+
the generic `operation: { operationId }` input, auto-generated operation IDs,
|
|
5303
|
+
the control journal, and the `runtime.operations.get` receipt query; mutation
|
|
5304
|
+
identity now comes from each mutation's own domain fields — the explicit
|
|
5305
|
+
`sessionId` on create, the returned `runId` on start, and the settings
|
|
5306
|
+
revision on CAS updates. Credential and Host Tool
|
|
5307
|
+
register/revoke/supply/complete requests are reverse-bridge
|
|
5308
|
+
control frames and persist no secrets or results. They still enter the daemon
|
|
5309
|
+
management draining fence: once an atomic stop begins, they fail with typed
|
|
5310
|
+
`conflict` and cannot change reverse-bridge state. Reconnection semantics are
|
|
5311
|
+
explicit: after a lost response, re-read authoritative state and reconcile in
|
|
5312
|
+
your product code; the SDK never transparently retries or replays a mutation.
|
|
5310
5313
|
|
|
5311
5314
|
```ts
|
|
5312
5315
|
const session = await runtime.sessions.create({
|
|
5313
5316
|
sessionId: stableSpaceSessionId,
|
|
5314
5317
|
title: 'Shared session',
|
|
5315
5318
|
surface: 'space-desktop',
|
|
5316
|
-
operation: { operationId: loadOrCreatePendingOperationId('space-session-draft-7') },
|
|
5317
5319
|
});
|
|
5318
5320
|
|
|
5319
|
-
const operationId = loadOrCreatePendingOperationId('space-run-draft-42');
|
|
5320
5321
|
const handle = await runtime.runs.start({
|
|
5321
5322
|
sessionId: session.id,
|
|
5322
5323
|
input: { type: 'text', text: prompt },
|
|
5323
5324
|
options: { provider: 'anthropic' },
|
|
5324
|
-
operation: { operationId },
|
|
5325
5325
|
});
|
|
5326
5326
|
|
|
5327
5327
|
const current = await runtime.sessions.getSettingsVersioned(session.id);
|
|
5328
5328
|
const updated = await runtime.sessions.updateSettingsVersioned(
|
|
5329
5329
|
session.id,
|
|
5330
5330
|
{ model: 'claude-sonnet-4-5' },
|
|
5331
|
-
{
|
|
5332
|
-
operationId: loadOrCreatePendingOperationId('space-settings-draft-9'),
|
|
5333
|
-
expectedRevision: current.revision,
|
|
5334
|
-
},
|
|
5331
|
+
{ expectedRevision: current.revision },
|
|
5335
5332
|
);
|
|
5336
5333
|
```
|
|
5337
5334
|
|
|
5338
|
-
|
|
5335
|
+
Re-creating with the same explicit `sessionId` cannot overwrite
|
|
5339
5336
|
an existing session. Same-session starts and after-turn inputs receive a durable `sessionOrder`.
|
|
5340
|
-
|
|
5341
|
-
create another run. Settings use compare-and-swap; a stale revision returns a
|
|
5337
|
+
Settings use compare-and-swap; a stale revision returns a
|
|
5342
5338
|
structured conflict and must be reloaded, never silently overwritten. The
|
|
5343
5339
|
shared settings keys are `provider`, `model`, `effort`, `thinking`,
|
|
5344
5340
|
`reasoningMode`, `permissionMode`, `executionCwd`, `agentMode`, and
|
|
@@ -5351,7 +5347,6 @@ const queued = await runtime.runs.submitInput({
|
|
|
5351
5347
|
afterRunId: handle.runId,
|
|
5352
5348
|
delivery: 'after_turn',
|
|
5353
5349
|
input: { type: 'text', text: 'Also update the tests.' },
|
|
5354
|
-
operation: { operationId: loadOrCreatePendingOperationId('space-input-17') },
|
|
5355
5350
|
});
|
|
5356
5351
|
|
|
5357
5352
|
if (!queued.accepted) {
|
|
@@ -5365,7 +5360,8 @@ This does not create a Run. Each accepted input appears as `queued` in the
|
|
|
5365
5360
|
owning Run's `interruptInputs`. At the next safe boundary, all accumulated
|
|
5366
5361
|
interrupts are drained FIFO, remain separate user messages in one next LLM
|
|
5367
5362
|
request, and produce one `run.input.delivered` event whose `inputs` array is the
|
|
5368
|
-
complete ordered batch.
|
|
5363
|
+
complete ordered batch. An accepted interrupt returns the `inputId` of the
|
|
5364
|
+
admitted item, which you keep for later reconciliation.
|
|
5369
5365
|
The accepted result's `runId` is the existing owning Run (equal to
|
|
5370
5366
|
`afterRunId`), not a newly created continuation.
|
|
5371
5367
|
|
|
@@ -5381,8 +5377,8 @@ and Runtime restart preserve a newly recorded reference.
|
|
|
5381
5377
|
Since v0.7.82, submission resolves the admitted authoritative Run before it
|
|
5382
5378
|
reads mutable canonical Session history. Active interrupt and after-turn
|
|
5383
5379
|
requests therefore do not surface a transient `data_changed` response caused by
|
|
5384
|
-
predecessor persistence. `after_turn` still waits for predecessor settlement
|
|
5385
|
-
and
|
|
5380
|
+
predecessor persistence. `after_turn` still waits for predecessor settlement;
|
|
5381
|
+
admission and queue placement are owned by the receiving Run.
|
|
5386
5382
|
|
|
5387
5383
|
Interrupt admission closes when the Runner publishes its final completion or
|
|
5388
5384
|
terminal error signal, or when the Run's supplied `abortSignal` aborts, even if
|
|
@@ -5405,7 +5401,6 @@ const interrupted = await runtime.runs.submitInput({
|
|
|
5405
5401
|
afterRunId: handle.runId,
|
|
5406
5402
|
delivery: 'interrupt',
|
|
5407
5403
|
input: { type: 'text', text: 'Also preserve the public API.' },
|
|
5408
|
-
operation: { operationId: loadOrCreatePendingOperationId('space-input-18') },
|
|
5409
5404
|
});
|
|
5410
5405
|
```
|
|
5411
5406
|
|
|
@@ -5417,8 +5412,9 @@ Run status exposes acceptance/start/queue times, authenticated origin,
|
|
|
5417
5412
|
`terminal.code = 'blocked'`; surface `terminal.message` when present instead of
|
|
5418
5413
|
replacing it with a generic run failure. Respect `effectOutcome`; `unknown` must
|
|
5419
5414
|
never be presented as success or automatically retried. After a lost response,
|
|
5420
|
-
|
|
5421
|
-
|
|
5415
|
+
there is no operation receipt to query: re-read authoritative state with
|
|
5416
|
+
`runs.get(runId)` / `sessions.status(sessionId)` and reconcile explicitly.
|
|
5417
|
+
Permission grants remain daemon-owned and
|
|
5422
5418
|
revisioned.
|
|
5423
5419
|
|
|
5424
5420
|
Runtime startup restores all indexed active Runs and at most 200 recent
|
|
@@ -5494,7 +5490,7 @@ permission context contracts: Auto approvals bind to one exact text call
|
|
|
5494
5490
|
without granting a directory, and direct plus managed provider requests carry
|
|
5495
5491
|
the live permission mode refreshed on retries.
|
|
5496
5492
|
`sharedSessionSettings` v2 advertises the four canonical profiles and the
|
|
5497
|
-
input-only `auto-in-project` alias. Embedded
|
|
5493
|
+
input-only `auto-in-project` alias. Embedded and daemon hosts expose
|
|
5498
5494
|
the same contract; restart or upgrade an older daemon instead of falling back
|
|
5499
5495
|
to client-side routing.
|
|
5500
5496
|
|
|
@@ -5529,11 +5525,10 @@ const run = await runtime.runs.start({
|
|
|
5529
5525
|
mode: 'scoped',
|
|
5530
5526
|
providers: ['anthropic', 'openai'],
|
|
5531
5527
|
},
|
|
5532
|
-
operation: { operationId: loadOrCreatePendingOperationId('space-run-88') },
|
|
5533
5528
|
});
|
|
5534
5529
|
```
|
|
5535
5530
|
|
|
5536
|
-
The allowlist is a ceiling:
|
|
5531
|
+
The allowlist is a ceiling: a run binding can narrow it but cannot add a
|
|
5537
5532
|
Provider. The daemon asks only when an actual primary, fallback, classifier,
|
|
5538
5533
|
sidecar, compaction, Workflow, or utility wire call needs that Provider.
|
|
5539
5534
|
An unauthorized Provider fails before the host callback. The secret crosses
|
|
@@ -5615,7 +5610,6 @@ await runtime.runs.start({
|
|
|
5615
5610
|
sessionId,
|
|
5616
5611
|
input: { type: 'text', text: 'Create the report artifact.' },
|
|
5617
5612
|
hostTools: { leaseId: hostLease.id },
|
|
5618
|
-
operation: { operationId: loadOrCreatePendingOperationId('space-artifact-run') },
|
|
5619
5613
|
});
|
|
5620
5614
|
```
|
|
5621
5615
|
|
|
@@ -5688,16 +5682,18 @@ rollout unless the product cannot operate without it.
|
|
|
5688
5682
|
|
|
5689
5683
|
Preflight is useful for UI, but it is not a stop authorization token. Use
|
|
5690
5684
|
`runtime.daemon.inspect()` to obtain one consistent management revision,
|
|
5691
|
-
verified owner fence, owner-policy revision, and preflight projection
|
|
5692
|
-
`runtime.
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5685
|
+
verified owner fence, owner-policy revision, and preflight projection, then
|
|
5686
|
+
send the authenticated `runtime.shutdown` request: management rechecks
|
|
5687
|
+
preflight under the draining fence and commits the stop only when the daemon is
|
|
5688
|
+
idle, otherwise it fails with a structured `conflict` and the daemon keeps
|
|
5689
|
+
running. The management revision also advances when the preflight projection changes,
|
|
5690
|
+
so a Workflow or AgentTask lifecycle transition between inspect and stop
|
|
5691
|
+
invalidates the stale attempt. Capability details
|
|
5696
5692
|
`daemonManagement.backgroundWorkPreflight` and
|
|
5697
5693
|
`daemonManagement.reverseBridgeDrainingFence` identify this complete contract.
|
|
5698
|
-
`runtime.operations.get()` reconciles durable mutations,
|
|
5699
5694
|
`hostTools.getInvocation()` reconciles Host Tool metadata, and
|
|
5700
|
-
`permissions.listGrants()` returns the daemon-owned persistent grant set
|
|
5695
|
+
`permissions.listGrants()` returns the daemon-owned persistent grant set;
|
|
5696
|
+
durable mutations are reconciled by re-reading their authoritative state.
|
|
5701
5697
|
|
|
5702
5698
|
Terminal notification read/unread state is intentionally client-owned in
|
|
5703
5699
|
v0.7.69 (`durableRecoveryQueries.terminalAcknowledgement === false`): Space
|
|
@@ -5709,45 +5705,47 @@ truth.
|
|
|
5709
5705
|
|
|
5710
5706
|
Daemon and inline Coder use one profile fence. Do not compose
|
|
5711
5707
|
`status.preflight()` with a low-level unconditional stop: another client or run
|
|
5712
|
-
can appear between those calls.
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5708
|
+
can appear between those calls. v0.7.97 removed the combined rollback
|
|
5709
|
+
transaction (`runtime.daemon.stopForInline()`); stopping the daemon and
|
|
5710
|
+
changing the owner mode are now two explicit steps, and the owner mode never
|
|
5711
|
+
changes implicitly. First stop the daemon through the fenced idle shutdown —
|
|
5712
|
+
management rechecks preflight under the draining fence and returns a
|
|
5713
|
+
structured `conflict` instead of stopping a busy daemon — then flip the owner
|
|
5714
|
+
policy while no owner lock exists:
|
|
5717
5715
|
|
|
5718
5716
|
```ts
|
|
5719
5717
|
import {
|
|
5720
5718
|
acquireKodaXInlineOwner,
|
|
5721
5719
|
enableKodaXDaemonOwner,
|
|
5722
5720
|
getKodaXRuntimeOwnerState,
|
|
5721
|
+
setKodaXRuntimeOwnerMode,
|
|
5723
5722
|
} from '@kodax-ai/kodax/runtime';
|
|
5724
5723
|
|
|
5725
5724
|
const management = await runtime.daemon.inspect();
|
|
5726
5725
|
if (!management.preflight.canStop) {
|
|
5727
|
-
|
|
5726
|
+
showStopBlockers(management.preflight.blockers);
|
|
5728
5727
|
return;
|
|
5729
5728
|
}
|
|
5730
5729
|
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
expectedRevision: management.revision,
|
|
5734
|
-
expectedOwnerPolicyRevision: management.ownerPolicy.revision,
|
|
5735
|
-
operation: { operationId: loadOrCreatePendingOperationId('coder-inline-rollback') },
|
|
5736
|
-
});
|
|
5730
|
+
// Fenced idle stop; active work returns structured `conflict`.
|
|
5731
|
+
const stop = await runtime.daemon.shutdown();
|
|
5737
5732
|
|
|
5738
|
-
// `accepted` means
|
|
5739
|
-
//
|
|
5733
|
+
// `accepted` means the stop was taken. Wait through the public owner-state
|
|
5734
|
+
// query; never infer release from a PID.
|
|
5740
5735
|
const shutdownDeadline = Date.now() + 30_000;
|
|
5741
|
-
while (getKodaXRuntimeOwnerState({ homeDir: kodaxHome, profile: 'coder' }).owner
|
|
5742
|
-
=== rollback.runtimeId) {
|
|
5736
|
+
while (getKodaXRuntimeOwnerState({ homeDir: kodaxHome, profile: 'coder' }).owner) {
|
|
5743
5737
|
if (Date.now() >= shutdownDeadline) throw new Error('Timed out waiting for daemon owner release.');
|
|
5744
5738
|
await delay(25);
|
|
5745
5739
|
}
|
|
5746
|
-
const releasedOwner = getKodaXRuntimeOwnerState({ homeDir: kodaxHome, profile: 'coder' });
|
|
5747
|
-
if (releasedOwner.ownerStatus !== 'unowned') {
|
|
5748
|
-
throw new Error('Coder profile acquired a different owner during rollback.');
|
|
5749
|
-
}
|
|
5750
5740
|
await runtime.close(); // Detach only; it does not perform a second stop.
|
|
5741
|
+
|
|
5742
|
+
// Explicit daemon→inline owner-mode change; rejected while an owner lock exists.
|
|
5743
|
+
setKodaXRuntimeOwnerMode({
|
|
5744
|
+
mode: 'inline',
|
|
5745
|
+
expectedRevision: management.ownerPolicy.revision,
|
|
5746
|
+
homeDir: kodaxHome,
|
|
5747
|
+
profile: 'coder',
|
|
5748
|
+
});
|
|
5751
5749
|
const inlineOwner = acquireKodaXInlineOwner({ homeDir: kodaxHome, profile: 'coder' });
|
|
5752
5750
|
|
|
5753
5751
|
// Later, after the inline owner has released its fence:
|
|
@@ -5759,25 +5757,30 @@ const daemonPolicy = enableKodaXDaemonOwner({ homeDir: kodaxHome, profile: 'code
|
|
|
5759
5757
|
Any management revision change, another logical client, active or queued run,
|
|
5760
5758
|
running/paused Workflow, non-terminal/unknown AgentTask, pending
|
|
5761
5759
|
AskUser/permission, or in-flight mutation returns structured `conflict`; the
|
|
5762
|
-
daemon remains running and
|
|
5763
|
-
credential and Host Tool state changes without
|
|
5760
|
+
daemon remains running and the owner mode remains unchanged. Draining also rejects
|
|
5761
|
+
credential and Host Tool state changes without persisting their secrets or
|
|
5764
5762
|
results. The inline policy is sticky: later CLI auto-start is rejected until
|
|
5763
|
+
`setKodaXRuntimeOwnerMode({ mode: 'daemon', ... })` or
|
|
5765
5764
|
`enableKodaXDaemonOwner()` changes it back to `daemon`. `runtime.close()` still
|
|
5766
5765
|
only detaches. Stale-owner handling validates the owned lock/state and never
|
|
5767
5766
|
kills a process merely because a PID was reused.
|
|
5768
5767
|
|
|
5769
5768
|
Keep all trusted objects in Electron Main: daemon token/endpoint, stable client
|
|
5770
|
-
identity,
|
|
5769
|
+
identity, owner policy, keychain broker, Host Tool handlers, and
|
|
5771
5770
|
permission-grant administration. Renderer IPC should expose product-specific
|
|
5772
5771
|
commands and sanitized projections only. Never pass daemon credentials,
|
|
5773
|
-
leases,
|
|
5772
|
+
leases, or trusted session/run context to renderer or model
|
|
5774
5773
|
tool arguments.
|
|
5775
5774
|
|
|
5776
5775
|
---
|
|
5777
5776
|
|
|
5778
5777
|
## 24. Runtime-owned permission routing and plan bridges (v0.7.96)
|
|
5779
5778
|
|
|
5780
|
-
The
|
|
5779
|
+
> The product equivalent is `view.interactions` plus `interactions.respond`.
|
|
5780
|
+
> The Runtime helpers below are for trusted Host adapters, not client-created
|
|
5781
|
+
> permission requests or alternate authorization owners.
|
|
5782
|
+
|
|
5783
|
+
The Runtime owns permission routing in inline and daemon deployments.
|
|
5781
5784
|
Clients select one of four profiles and must not add a second preflight gate:
|
|
5782
5785
|
|
|
5783
5786
|
```ts
|
|
@@ -5950,6 +5953,10 @@ for the current permission contract.
|
|
|
5950
5953
|
|
|
5951
5954
|
## 25. Always-on context compaction and bounded transcript recovery (v0.7.74)
|
|
5952
5955
|
|
|
5956
|
+
> Product clients use `sessions.compact`, `observe`, `readItem`, `readHistory`,
|
|
5957
|
+
> `readHistoryEntry` and `searchHistory`. Low-level transcript/event examples
|
|
5958
|
+
> below do not imply an additional Product event replay surface.
|
|
5959
|
+
|
|
5953
5960
|
Automatic large compaction is always enabled. `enabled` remains accepted for
|
|
5954
5961
|
v0.7.x source compatibility, but `false` is normalized to `true`.
|
|
5955
5962
|
`triggerPercent` defaults to `75` and is clamped to `15..90`. The optional
|
|
@@ -5985,16 +5992,16 @@ await runtime.sessions.compact({
|
|
|
5985
5992
|
mode: 'scoped',
|
|
5986
5993
|
providers: ['anthropic'],
|
|
5987
5994
|
},
|
|
5988
|
-
operation: {
|
|
5989
|
-
operationId: loadOrCreatePendingOperationId(`compact:${session.id}`),
|
|
5990
|
-
},
|
|
5991
5995
|
});
|
|
5992
5996
|
```
|
|
5993
5997
|
|
|
5994
5998
|
Manual compact uses the same credential-aware summary implementation as
|
|
5995
|
-
automatic compact.
|
|
5996
|
-
|
|
5997
|
-
|
|
5999
|
+
automatic compact. There is no client-supplied operation envelope: the daemon
|
|
6000
|
+
itself mints the short-lived compaction identity for the scoped credential
|
|
6001
|
+
target (a `compact_<uuid>` maintenance id bound to the stable
|
|
6002
|
+
`session.compact` operation, not a fabricated Run ID) and validates lease,
|
|
6003
|
+
Provider, and Session before the summary call. After a lost response, re-read
|
|
6004
|
+
the Session's compaction state instead of retrying blindly.
|
|
5998
6005
|
|
|
5999
6006
|
Setting `compactionTriggerTokens: 0` removes the absolute Session override.
|
|
6000
6007
|
Percentage updates are normalized to `15..90`; negative/fractional absolute
|
|
@@ -6199,7 +6206,7 @@ only prevents high-frequency progress from becoming a model control signal.
|
|
|
6199
6206
|
## 27. Windows GUI background subprocess visibility (v0.7.75)
|
|
6200
6207
|
|
|
6201
6208
|
KodaX SDK hosts do not need to add process-wide console suppression around the
|
|
6202
|
-
Runtime.
|
|
6209
|
+
Runtime. Since the v0.7.75 release candidate, Runtime-reachable
|
|
6203
6210
|
non-interactive/background child processes request `windowsHide: true` at their
|
|
6204
6211
|
own spawn boundary. The covered paths include:
|
|
6205
6212
|
|
|
@@ -6214,8 +6221,10 @@ commands, and PTY sessions remain interactive. POSIX-only `ps`, `tmux`, and
|
|
|
6214
6221
|
sandbox branches are reviewed bundle-audit exceptions rather than Windows
|
|
6215
6222
|
visibility paths.
|
|
6216
6223
|
|
|
6217
|
-
|
|
6218
|
-
|
|
6224
|
+
The bundled runtime entry points ship with the `dist/semantic-worker.js` and
|
|
6225
|
+
`dist/constructed-handler-worker.js` sidecars (the former
|
|
6226
|
+
`dist/runtime-worker.js` sidecar and its build-time child-process audit were
|
|
6227
|
+
removed with the Worker facade in v0.7.97). The packaged Electron daemon smoke then
|
|
6219
6228
|
runs 20 ordinary queries with a Win32 probe and checks that the expected Git
|
|
6220
6229
|
children never own a visible console window. These checks validate the SDK
|
|
6221
6230
|
boundary, but they do not replace product-level validation in the packaged host.
|
|
@@ -6309,6 +6318,9 @@ for cross-project, cache, cancellation, credential, and Windows argv checks.
|
|
|
6309
6318
|
|
|
6310
6319
|
## 29. Evidence-gated background Skill learning (FEATURE_263, v0.7.78)
|
|
6311
6320
|
|
|
6321
|
+
> Product clients consume the Host-owned `client.learning` service. Bootstrap
|
|
6322
|
+
> options below configure the trusted owner, not a separate UI learning engine.
|
|
6323
|
+
|
|
6312
6324
|
F263 completes the existing Learning Center rather than introducing a second
|
|
6313
6325
|
queue or client-owned Skill store. Episode review runs after durable foreground
|
|
6314
6326
|
completion and stays off the active Run's latency path. A correction, failure,
|
|
@@ -6389,7 +6401,7 @@ bindings without mutating an in-flight prompt.
|
|
|
6389
6401
|
Learning Center notification state is client-specific, but capability
|
|
6390
6402
|
lifecycle and project canary state are owner-global. Renderer code should
|
|
6391
6403
|
receive sanitized records/events through host IPC; it should not receive
|
|
6392
|
-
daemon credentials or mutate files directly. Inline
|
|
6404
|
+
daemon credentials or mutate files directly. Inline and daemon
|
|
6393
6405
|
facades expose the same learning methods. A host missing `skillLearningLoop:1`
|
|
6394
6406
|
may still support the older Ready/manual Learning Center surface, but must not
|
|
6395
6407
|
claim the complete F263 project-canary contract.
|
|
@@ -6811,7 +6823,7 @@ try {
|
|
|
6811
6823
|
when multiple projects expose the same display name or slug. `'user'` is the
|
|
6812
6824
|
only supported scope. Daemon clients need the server-issued
|
|
6813
6825
|
`learning:control` scope; advertising a client capability does not grant it.
|
|
6814
|
-
Inline
|
|
6826
|
+
Inline and daemon facades carry the same v2 learned-record shape and
|
|
6815
6827
|
promotion method.
|
|
6816
6828
|
|
|
6817
6829
|
The Runtime verifies the source is a regular non-symlink file inside the exact
|
|
@@ -6838,6 +6850,68 @@ unsupported options fail before the Runtime mutation.
|
|
|
6838
6850
|
|
|
6839
6851
|
---
|
|
6840
6852
|
|
|
6853
|
+
## Migrating to v0.7.97
|
|
6854
|
+
|
|
6855
|
+
For the complete product-facing mapping, use the [SDK migration guide](../../docs/SDK_MIGRATION.md).
|
|
6856
|
+
The table below covers removals in this development tree; it does not claim a
|
|
6857
|
+
published `v0.7.97` package. Retained Runtime APIs are not automatically Product APIs.
|
|
6858
|
+
|
|
6859
|
+
v0.7.97 is a breaking SDK release for embedders. It removes the durable event
|
|
6860
|
+
journal/replay surface, the generic operation envelope/receipts, the
|
|
6861
|
+
crash-resumable exit-settlement protocol, and the Worker-hosted embedded
|
|
6862
|
+
runtime. If you upgrade a host past v0.7.96, map every removed surface to its
|
|
6863
|
+
replacement:
|
|
6864
|
+
|
|
6865
|
+
| Removed in v0.7.97 | Replacement |
|
|
6866
|
+
|---|---|
|
|
6867
|
+
| Operation envelope (`operation: { operationId }` on public control mutations), auto-generated operation IDs, `runtime.operations.get` receipts, and the `operationDeduplication` capability/requirement | Mutation identity comes from each mutation's own domain fields (explicit `sessionId` on create, returned `runId`, `expectedRevision` CAS on settings). After a lost response, re-read authoritative state (`runs.get`, `sessions.status`) and reconcile explicitly; there is no transparent retry or receipt query. |
|
|
6868
|
+
| `settleKodaXRuntimeExit()` SDK export, `daemon.rollbackToInline`, client `stopForInline`, and the `runtimeExitSettlement:2` capability | `runtime.shutdown` / `runtime.daemon.shutdown()` is a real idle shutdown (busy → structured `conflict`). Daemon→inline ownership changes are explicit: `setKodaXRuntimeOwnerMode({ mode, expectedRevision })`, or owner-lock release plus `acquireKodaXInlineOwner()`. The owner mode never changes implicitly. |
|
|
6869
|
+
| `event.subscribe`/`event.replay` RPCs, the `{ sessionId, journalEpoch, seq }` cursor, `journalEpoch` fields, and the `sessionEventJournal:1` capability | Events are a live in-process stream (`{ id, seq, time, sessionId, runId, turnId?, type, payload }`). Remote consumption reuses `session.observe` notifications; observation snapshots carry a `seq` high-water, live listener events are strictly greater, and `seq` never persists across restarts. Deleting/recreating a Session invalidates observations with `runtime_changed`. |
|
|
6870
|
+
| Diagnostics RPCs `context.budget.get`, `tool.exposure.preview`, `provider.cache.diagnostics.get` (and the `runtime.diagnostics.latest*` facade) | Removed. `capabilities.contextDiagnostics: true` only gates diagnostic event notifications (`context.budget.snapshot`, `tool.exposure.planned`, `provider.cache.diagnostics`, `context.compaction.skipped`) on the live stream. |
|
|
6871
|
+
| `isolation: 'worker'`, `worker: { configuredA2A: true }` (and `worker.*` options), `requirements.hardDispose`, and the `dist/runtime-worker.js` sidecar | Deleted. Use inline embedded or daemon mode. For the configured A2A plane, wire `createConfiguredA2ARuntimeIntegration({ configHome })` in the owner and pass its `runtimeOptions` as `externalAgents` — the Runtime itself never reads `integrations/a2a.json`. |
|
|
6872
|
+
| Late-result redelivery after an abandoned read | Removed. `request.cancel`/`request.ack` remain daemon transport-control frames only; an abandoned read gets no late delivery. |
|
|
6873
|
+
| The product mode surfaces: the CLI `--runtime-mode` flag, the `KODAX_RUNTIME_MODE` environment variable, and the `runtimeMode` key in `~/.kodax/config.json` | Removed in the fixed-Host release. The `kodax` CLI always starts-or-attaches the daemon owner; SDK callers keep the `mode: 'embedded' | 'daemon'` option on `createKodaXRuntime` (embedded stays a low-level path, never a product fallback). |
|
|
6874
|
+
| `setThinking` REPL callback | Removed. Use `setReasoningMode` (the shared settings key is `reasoningMode`). |
|
|
6875
|
+
| `getKodaXRuntimeOwnerPolicy` export | Removed. `getKodaXRuntimeOwnerState()` remains and reports policy, owner status, and the current owner in one call. |
|
|
6876
|
+
|
|
6877
|
+
Product UIs connect through `connectKodaXClient` from `@kodax-ai/kodax/client`.
|
|
6878
|
+
The Host owns execution and saved history; `sessions.observe` delivers the
|
|
6879
|
+
current display; `readItem` expands display references, while `readHistory`,
|
|
6880
|
+
`readHistoryEntry` and `searchHistory` provide canonical history and its own
|
|
6881
|
+
readable references. A display preview is not the full
|
|
6882
|
+
message. The Runtime-to-product adapter is internal and is not an SDK export.
|
|
6883
|
+
|
|
6884
|
+
Keep an input's original text, artifacts and `inputId` until its outcome is
|
|
6885
|
+
known. After a lost response, query that same Host with `inputs.read`; only a
|
|
6886
|
+
confirmed withdrawal returns a queued input to the editor. A replacement Host
|
|
6887
|
+
does not inherit the old Host's input identities.
|
|
6888
|
+
|
|
6889
|
+
Product rewind requires the head the user reviewed, so another client's newer
|
|
6890
|
+
work cannot be silently discarded:
|
|
6891
|
+
|
|
6892
|
+
```ts
|
|
6893
|
+
const lineage = await client.sessions.readLineage(sessionId);
|
|
6894
|
+
await client.sessions.rewindSession(sessionId, {
|
|
6895
|
+
selector: targetEntryId,
|
|
6896
|
+
expectedHead: lineage?.activeEntryId ?? null,
|
|
6897
|
+
});
|
|
6898
|
+
```
|
|
6899
|
+
|
|
6900
|
+
On `conflict`, reload the lineage and let the user review the new state before
|
|
6901
|
+
trying again. Rewind changes the conversation branch; it does not undo files.
|
|
6902
|
+
Bound REPL Memory commands use the same daemon owner, and Workflow/Skill
|
|
6903
|
+
execution uses real Runs with the Session's effective settings and tool policy.
|
|
6904
|
+
|
|
6905
|
+
Two compatibilities are unchanged and worth restating: the constructed-handler
|
|
6906
|
+
worker (repo-intelligence and managed-task workers in `@kodax-ai/coding`) is a
|
|
6907
|
+
separate, kept surface, and the `mode: 'embedded' | 'daemon'` option on
|
|
6908
|
+
`createKodaXRuntime` still selects the ownership form. Host-minted compact
|
|
6909
|
+
identity (`compact_<uuid>`, minted by the daemon for the scoped credential
|
|
6910
|
+
target of manual compaction) still exists — it is Host-internal, not a client
|
|
6911
|
+
envelope.
|
|
6912
|
+
|
|
6913
|
+
---
|
|
6914
|
+
|
|
6841
6915
|
## Managed extension execution and Session Stop (FEATURE_299, v0.7.96)
|
|
6842
6916
|
|
|
6843
6917
|
A Stop button uses one owner-side operation:
|