@kodax-ai/kodax 0.7.42 → 0.7.44
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 +65 -6
- package/README.md +87 -56
- package/README_CN.md +46 -25
- package/dist/chunks/chunk-35BDEEC5.js +2 -0
- package/dist/chunks/chunk-4YPL2UVZ.js +848 -0
- package/dist/chunks/chunk-DI2G3YWL.js +31 -0
- package/dist/chunks/chunk-HHQ7YTGM.js +425 -0
- package/dist/chunks/chunk-QHILHQBB.js +519 -0
- package/dist/chunks/{chunk-IYJ5EPRV.js → chunk-RUDYNAK7.js} +1 -1
- package/dist/chunks/compaction-config-NAPRF7XR.js +2 -0
- package/dist/chunks/{construction-bootstrap-J2WOCYEK.js → construction-bootstrap-PHTGBRNU.js} +4 -4
- package/dist/chunks/dist-CCYBJJZY.js +2 -0
- package/dist/chunks/dist-RHIHZAYX.js +2 -0
- package/dist/chunks/utils-TV3UYCHQ.js +2 -0
- package/dist/index.d.ts +11 -11
- package/dist/index.js +2 -2
- package/dist/kodax_cli.js +1159 -1102
- package/dist/provider-capabilities.json +167 -0
- package/dist/sdk-agent.d.ts +905 -48
- package/dist/sdk-agent.js +1 -1
- package/dist/sdk-coding.d.ts +995 -755
- package/dist/sdk-coding.js +1 -1
- package/dist/sdk-llm.d.ts +5 -3
- package/dist/sdk-llm.js +1 -1
- package/dist/sdk-mcp.d.ts +1 -1
- package/dist/sdk-mcp.js +1 -1
- package/dist/sdk-repl.d.ts +10 -9
- package/dist/sdk-repl.js +1 -1
- package/dist/sdk-session.d.ts +23 -11
- package/dist/sdk-session.js +1 -1
- package/dist/sdk-skills.js +1 -1
- package/dist/types-chunks/{cost-tracker.d-B6vMoLLF.d.ts → base.d-FUJahC0i.d.ts} +2 -110
- package/dist/types-chunks/{bash-prefix-extractor.d-CkhaqKkg.d.ts → bash-prefix-extractor.d-DdoSeghD.d.ts} +442 -131
- package/dist/types-chunks/cost-tracker.d-wRtyEW9d.d.ts +110 -0
- package/dist/types-chunks/file-tracker.d-DOfaoCbJ.d.ts +633 -0
- package/dist/types-chunks/manager.d-87belpiS.d.ts +370 -0
- package/dist/types-chunks/{resolver.d-DX9au4NJ.d.ts → resolver.d-B7ZnVuuf.d.ts} +157 -10
- package/dist/types-chunks/{session-storage.d-Cci897iM.d.ts → storage.d-DFD9ln5c.d.ts} +49 -2
- package/dist/types-chunks/{history-cleanup.d-DznrzEiU.d.ts → types.d-DM8zEJgF.d.ts} +1084 -282
- package/dist/types-chunks/{types.d-mM8vqvhT.d.ts → types.d-HBbWT-iA.d.ts} +41 -3
- package/dist/types-chunks/{storage.d-Bc5DoAwp.d.ts → utils.d-C5fzCE9W.d.ts} +25 -47
- package/package.json +7 -6
- package/dist/chunks/chunk-3RKBXWZS.js +0 -2
- package/dist/chunks/chunk-7JLYVWAF.js +0 -1033
- package/dist/chunks/chunk-CD3R5YBH.js +0 -16
- package/dist/chunks/chunk-DKXUY5F2.js +0 -209
- package/dist/chunks/chunk-HMYEQJGT.js +0 -31
- package/dist/chunks/chunk-KUX5LRPP.js +0 -2
- package/dist/chunks/chunk-OWSKU55I.js +0 -13
- package/dist/chunks/chunk-ZZ4KRK2B.js +0 -465
- package/dist/chunks/compaction-config-FIFFP4FT.js +0 -2
- package/dist/chunks/dist-2ZHWDXMQ.js +0 -2
- package/dist/chunks/dist-W4CJWLIH.js +0 -2
- package/dist/chunks/utils-A5MWDTWZ.js +0 -2
- package/dist/types-chunks/instance-discovery.d-BsKnIwpg.d.ts +0 -990
- package/dist/types-chunks/transport.d-DuyjG30t.d.ts +0 -180
|
@@ -1,48 +1,179 @@
|
|
|
1
|
-
import { m as KodaXMessage } from './types.d-B1uGoVTE.js';
|
|
2
|
-
import { a as
|
|
1
|
+
import { X as KodaXToolDefinition, m as KodaXMessage, D as KodaXReasoningMode, Z as KodaXToolResultContentItem, T as KodaXThinkingBlock, G as KodaXRedactedThinkingBlock } from './types.d-B1uGoVTE.js';
|
|
2
|
+
import { a as KodaXCompactMemorySeed, k as KodaXSessionArtifactLedgerEntry } from './types.d-HBbWT-iA.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Layer A Primitive: Agent / Handoff / Guardrail / AgentReasoningProfile
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* FEATURE_080 (v0.7.23): Agent-as-data types. Declarative dataclass shape.
|
|
8
|
+
* The runtime counterpart is `Runner` in `./runner.ts`.
|
|
9
|
+
*
|
|
10
|
+
* History: extracted to `@kodax-ai/core` in FEATURE_082 (v0.7.24); merged back
|
|
11
|
+
* into `@kodax-ai/agent` in v0.7.35.1 FEATURE_142 (single-consumer rule —
|
|
12
|
+
* @kodax-ai/core had only @kodax-ai/coding as consumer). `@kodax-ai/coding` retains
|
|
13
|
+
* a barrel re-export for batteries-included consumers.
|
|
14
|
+
*
|
|
15
|
+
* Status: @experimental — API shape may be refined during v0.7.x. Used by
|
|
16
|
+
* the task-engine rewrite in FEATURE_084 (v0.7.26).
|
|
17
|
+
*
|
|
18
|
+
* Guardrail and AgentReasoningProfile are declared here but their runtime
|
|
19
|
+
* behavior is deferred:
|
|
20
|
+
* - Guardrail runtime → FEATURE_085 (v0.7.26)
|
|
21
|
+
* - AgentReasoningProfile behavior → FEATURE_078 (v0.7.29)
|
|
8
22
|
*/
|
|
9
|
-
declare const KODAX_MAX_TOKENS = 32768;
|
|
10
|
-
declare const KODAX_DEFAULT_TIMEOUT = 60;
|
|
11
|
-
declare const KODAX_HARD_TIMEOUT = 300;
|
|
12
|
-
declare const KODAX_MAX_RETRIES = 3;
|
|
13
|
-
declare const KODAX_RETRY_BASE_DELAY = 2;
|
|
14
|
-
declare const KODAX_MAX_INCOMPLETE_RETRIES = 2;
|
|
15
|
-
declare const KODAX_MAX_MAXTOKENS_RETRIES = 3;
|
|
16
|
-
declare const KODAX_STAGGER_DELAY = 1;
|
|
17
|
-
declare const KODAX_API_MIN_INTERVAL = 0.5;
|
|
18
|
-
declare const PROMISE_PATTERN: RegExp;
|
|
19
23
|
|
|
20
24
|
/**
|
|
21
|
-
*
|
|
25
|
+
* Reasoning depth / mode selector. Alias for `KodaXReasoningMode` to keep the
|
|
26
|
+
* Layer A surface independent of the `KodaX*` brand; unified during the prefix
|
|
27
|
+
* cleanup in FEATURE_086 (v0.7.27).
|
|
28
|
+
*/
|
|
29
|
+
type ReasoningDepth = KodaXReasoningMode;
|
|
30
|
+
/**
|
|
31
|
+
* Tool binding accepted by an `Agent`. Layer A treats tools as opaque
|
|
32
|
+
* definitions; the executor lives in `@kodax-ai/coding` and is wired up by the
|
|
33
|
+
* Runner when it dispatches through `runKodaX`.
|
|
34
|
+
*/
|
|
35
|
+
type AgentTool = KodaXToolDefinition;
|
|
36
|
+
/**
|
|
37
|
+
* Transport-level message reused from the AI layer. Kept as an alias so
|
|
38
|
+
* consumers of the Layer A primitives do not need to import from `@kodax-ai/llm`
|
|
39
|
+
* directly.
|
|
40
|
+
*/
|
|
41
|
+
type AgentMessage = KodaXMessage;
|
|
42
|
+
/**
|
|
43
|
+
* Declarative reasoning profile attached to an Agent.
|
|
22
44
|
*
|
|
23
|
-
*
|
|
45
|
+
* In v0.7.23 this is a placeholder shape — only the `default` depth is read
|
|
46
|
+
* when the Runner dispatches to `runKodaX`. Escalation on revise/replan and
|
|
47
|
+
* max clamping are implemented in FEATURE_078 (v0.7.29).
|
|
24
48
|
*/
|
|
25
|
-
|
|
49
|
+
interface AgentReasoningProfile {
|
|
50
|
+
readonly default: ReasoningDepth;
|
|
51
|
+
readonly max?: ReasoningDepth;
|
|
52
|
+
readonly escalateOnRevise?: boolean;
|
|
53
|
+
}
|
|
26
54
|
/**
|
|
27
|
-
*
|
|
55
|
+
* Declarative middleware reference attached to an Agent.
|
|
56
|
+
*
|
|
57
|
+
* FEATURE_100 (v0.7.29) introduces this field so the coding preset
|
|
58
|
+
* can declare the four substrate middlewares (auto-reroute,
|
|
59
|
+
* mutation-reflection, pre-answer-judge, post-tool-judge) on the
|
|
60
|
+
* Agent declaration itself. Today these middlewares fire inside
|
|
61
|
+
* the substrate body; the declaration field serves as the
|
|
62
|
+
* machine-readable contract that the substrate honours, and lets
|
|
63
|
+
* SDK consumers introspect / override middleware policy without
|
|
64
|
+
* touching `runKodaX` internals.
|
|
28
65
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
66
|
+
* `enabled` is the only knob today; future versions add config
|
|
67
|
+
* payload as additional fields (kept declarative — no fn callbacks).
|
|
68
|
+
*/
|
|
69
|
+
interface AgentMiddlewareDeclaration {
|
|
70
|
+
readonly name: string;
|
|
71
|
+
readonly enabled: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Guardrail placeholder. Layer A declares the slot; the actual
|
|
75
|
+
* input/output/tool-call gating runtime lives in FEATURE_085 (v0.7.26).
|
|
76
|
+
*
|
|
77
|
+
* A guardrail targets one of three hook points:
|
|
78
|
+
* - `input`: inspect / veto prompts before they enter the agent loop.
|
|
79
|
+
* - `output`: inspect / rewrite assistant messages before they leave.
|
|
80
|
+
* - `tool`: inspect / veto tool invocations during the loop.
|
|
81
|
+
*/
|
|
82
|
+
interface Guardrail {
|
|
83
|
+
readonly kind: 'input' | 'output' | 'tool';
|
|
84
|
+
readonly name: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Handoff between Agents.
|
|
88
|
+
*
|
|
89
|
+
* - `continuation`: ownership of the conversation transfers to `target` and
|
|
90
|
+
* the caller exits. Mirrors the Scout → Generator upgrade path.
|
|
91
|
+
* - `as-tool`: `target` is invoked like a tool from within the caller loop;
|
|
92
|
+
* only the generated input is passed, and control returns on completion.
|
|
93
|
+
* Mirrors FEATURE_067 `dispatch_child_task`.
|
|
94
|
+
*
|
|
95
|
+
* `inputFilter` is applied to the visible history before the target runs;
|
|
96
|
+
* default is no filtering.
|
|
97
|
+
*/
|
|
98
|
+
interface Handoff<TTo = unknown> {
|
|
99
|
+
readonly target: Agent<TTo>;
|
|
100
|
+
readonly kind: 'continuation' | 'as-tool';
|
|
101
|
+
readonly description?: string;
|
|
102
|
+
readonly inputFilter?: (history: readonly AgentMessage[]) => readonly AgentMessage[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Agent-as-data. A declarative specification of "who is running, with which
|
|
106
|
+
* instructions, tools, handoffs, and reasoning profile."
|
|
107
|
+
*
|
|
108
|
+
* Runtime note: in v0.7.23 the only Agent that is fully executed is the
|
|
109
|
+
* built-in coding preset (`createDefaultCodingAgent()`), which dispatches
|
|
110
|
+
* through `runKodaX`. Custom Agents defined by SDK consumers run through a
|
|
111
|
+
* generic Runner loop with limited capabilities (LLM call + Agent-declared
|
|
112
|
+
* tools only — no extensions, no managed-task harness). The full runtime
|
|
113
|
+
* arrives with FEATURE_084 (v0.7.26).
|
|
114
|
+
*/
|
|
115
|
+
interface Agent<TContext = unknown> {
|
|
116
|
+
readonly name: string;
|
|
117
|
+
readonly instructions: string | ((ctx: TContext) => string);
|
|
118
|
+
readonly tools?: readonly AgentTool[];
|
|
119
|
+
readonly handoffs?: readonly Handoff[];
|
|
120
|
+
readonly reasoning?: AgentReasoningProfile;
|
|
121
|
+
readonly guardrails?: readonly Guardrail[];
|
|
122
|
+
/**
|
|
123
|
+
* FEATURE_191 — one-sentence human-readable summary surfaced to
|
|
124
|
+
* other agents that may dispatch this one (e.g., via the
|
|
125
|
+
* `dispatch_child_task(subagent_type=<name>)` Worker SP block). The
|
|
126
|
+
* field propagates from `AgentContent.description` when the agent is
|
|
127
|
+
* built via the construction substrate; built-in / SDK-created
|
|
128
|
+
* agents may set it directly. Optional for backward compatibility
|
|
129
|
+
* with the FEATURE_089 minimal-agent shape and pre-FEATURE_191
|
|
130
|
+
* built-ins.
|
|
131
|
+
*/
|
|
132
|
+
readonly description?: string;
|
|
133
|
+
/** Reserved for structured-output agents; not consumed in v0.7.23. */
|
|
134
|
+
readonly outputSchema?: unknown;
|
|
135
|
+
readonly model?: string;
|
|
136
|
+
readonly provider?: string;
|
|
137
|
+
/**
|
|
138
|
+
* FEATURE_100 (v0.7.29) substrate executor: when set, `Runner.run`
|
|
139
|
+
* delegates execution to this function instead of consulting the
|
|
140
|
+
* preset-dispatcher registry or running the generic LLM loop. The
|
|
141
|
+
* coding preset attaches `runKodaX`'s full execution pipeline here so
|
|
142
|
+
* the SDK surface `Runner.run(createDefaultCodingAgent(), prompt, opts)`
|
|
143
|
+
* directly drives substrate without a `registerPresetDispatcher`
|
|
144
|
+
* indirection (the v0.7.23 "Option Y" facade).
|
|
145
|
+
*
|
|
146
|
+
* Type is intentionally `unknown` to avoid a `core/agent.ts` ↔
|
|
147
|
+
* `core/runner.ts` module cycle. `Runner.run` casts to the
|
|
148
|
+
* `PresetDispatcher` shape declared in `runner.ts` at the call site.
|
|
149
|
+
*/
|
|
150
|
+
readonly substrateExecutor?: unknown;
|
|
151
|
+
/**
|
|
152
|
+
* FEATURE_100 (v0.7.29) declarative middleware list. The coding
|
|
153
|
+
* preset declares the four substrate middlewares it ships with
|
|
154
|
+
* (auto-reroute, mutation-reflection, pre-answer-judge,
|
|
155
|
+
* post-tool-judge). Substrate consults this list on entry and
|
|
156
|
+
* skips the corresponding step when `enabled === false`. SDK
|
|
157
|
+
* consumers can introspect or override declared middleware
|
|
158
|
+
* without touching the substrate body.
|
|
159
|
+
*/
|
|
160
|
+
readonly middleware?: readonly AgentMiddlewareDeclaration[];
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Ergonomic factory. Equivalent to a plain object literal but freezes the
|
|
164
|
+
* shape so tests cannot mutate a shared Agent by accident.
|
|
34
165
|
*/
|
|
35
|
-
declare function
|
|
166
|
+
declare function createAgent<TContext = unknown>(spec: Agent<TContext>): Agent<TContext>;
|
|
36
167
|
/**
|
|
37
|
-
*
|
|
168
|
+
* Ergonomic factory for Handoff.
|
|
38
169
|
*/
|
|
39
|
-
declare function
|
|
170
|
+
declare function createHandoff<TTo = unknown>(spec: Handoff<TTo>): Handoff<TTo>;
|
|
40
171
|
|
|
41
172
|
/**
|
|
42
173
|
* Layer A Primitive: Session / SessionEntry / MessageEntry / SessionExtension
|
|
43
174
|
*
|
|
44
175
|
* FEATURE_081 (v0.7.23): Base Session shape. The thick
|
|
45
|
-
* `KodaXSessionLineage` lives in
|
|
176
|
+
* `KodaXSessionLineage` lives in `../session-lineage/index.js` and is re-expressed
|
|
46
177
|
* as a `LineageExtension` over this base.
|
|
47
178
|
*
|
|
48
179
|
* History: extracted to `@kodax-ai/core` in FEATURE_082 (v0.7.24); merged back
|
|
@@ -141,134 +272,205 @@ interface InMemorySessionOptions {
|
|
|
141
272
|
/**
|
|
142
273
|
* In-memory Session suitable for tests, examples, and embedded SDK use. Not
|
|
143
274
|
* durable across process restarts — persistence is provided by coding-specific
|
|
144
|
-
* adapters in
|
|
275
|
+
* adapters in `../session-lineage/index.js` and `@kodax-ai/agent`.
|
|
145
276
|
*/
|
|
146
277
|
declare function createInMemorySession(opts?: InMemorySessionOptions): Session;
|
|
147
278
|
|
|
148
279
|
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* -
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*/
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
280
|
+
* SpanData variants — payload shapes carried by each `Span`.
|
|
281
|
+
*
|
|
282
|
+
* FEATURE_083 (v0.7.24): the Agent-era tracing model uses a discriminated
|
|
283
|
+
* union so consumers (OpenTelemetry adapter, Langfuse adapter, KodaX
|
|
284
|
+
* built-in file processor) can render each span kind with type safety.
|
|
285
|
+
*
|
|
286
|
+
* Variants mirror the semantic events KodaX emits today:
|
|
287
|
+
* - AgentSpanData : one `Runner.run(agent, ...)` round
|
|
288
|
+
* - GenerationSpanData: one provider LLM call
|
|
289
|
+
* - ToolCallSpanData : one tool invocation (including MCP tool)
|
|
290
|
+
* - HandoffSpanData : continuation or as-tool handoff between agents
|
|
291
|
+
* - CompactionSpanData: one compaction pass (token-threshold or lineage)
|
|
292
|
+
* - GuardrailSpanData : one guardrail check at input/output/tool
|
|
293
|
+
* - EvidenceSpanData : repo-intelligence / evidence acquisition
|
|
294
|
+
* - FanoutSpanData : parallel fanout bracket (winner-cancel capable)
|
|
295
|
+
*
|
|
296
|
+
* API surface is `@experimental` until v0.8.0 — shape may be refined as
|
|
297
|
+
* FEATURE_084 (v0.7.26) starts emitting these.
|
|
298
|
+
*/
|
|
299
|
+
interface AgentSpanData {
|
|
300
|
+
readonly kind: 'agent';
|
|
301
|
+
readonly agentName: string;
|
|
302
|
+
readonly model?: string;
|
|
303
|
+
readonly provider?: string;
|
|
304
|
+
readonly tools?: readonly string[];
|
|
305
|
+
readonly handoffs?: readonly string[];
|
|
306
|
+
readonly outputMessages?: number;
|
|
307
|
+
readonly error?: string;
|
|
308
|
+
}
|
|
309
|
+
interface GenerationSpanData {
|
|
310
|
+
readonly kind: 'generation';
|
|
311
|
+
readonly agentName: string;
|
|
312
|
+
readonly provider: string;
|
|
313
|
+
readonly model: string;
|
|
314
|
+
readonly inputMessages?: number;
|
|
315
|
+
readonly outputTokens?: number;
|
|
316
|
+
readonly inputTokens?: number;
|
|
317
|
+
readonly reasoningTokens?: number;
|
|
318
|
+
readonly cachedTokens?: number;
|
|
319
|
+
readonly usage?: {
|
|
320
|
+
readonly inputTokens?: number;
|
|
321
|
+
readonly outputTokens?: number;
|
|
322
|
+
readonly totalTokens?: number;
|
|
323
|
+
readonly reasoningTokens?: number;
|
|
324
|
+
readonly cachedTokens?: number;
|
|
325
|
+
readonly costUsd?: number;
|
|
326
|
+
};
|
|
327
|
+
readonly finishReason?: string;
|
|
328
|
+
readonly error?: string;
|
|
329
|
+
}
|
|
330
|
+
interface ToolCallSpanData {
|
|
331
|
+
readonly kind: 'tool_call';
|
|
332
|
+
readonly toolName: string;
|
|
333
|
+
readonly providerId?: string;
|
|
334
|
+
readonly capabilityId?: string;
|
|
335
|
+
readonly inputPreview?: string;
|
|
336
|
+
readonly outputPreview?: string;
|
|
337
|
+
readonly status: 'ok' | 'error';
|
|
338
|
+
readonly error?: string;
|
|
339
|
+
}
|
|
340
|
+
interface HandoffSpanData {
|
|
341
|
+
readonly kind: 'handoff';
|
|
342
|
+
readonly fromAgent: string;
|
|
343
|
+
readonly toAgent: string;
|
|
344
|
+
readonly handoffKind: 'continuation' | 'as-tool';
|
|
345
|
+
readonly description?: string;
|
|
346
|
+
}
|
|
347
|
+
interface CompactionSpanData {
|
|
348
|
+
readonly kind: 'compaction';
|
|
349
|
+
readonly policyName: string;
|
|
174
350
|
readonly tokensUsed: number;
|
|
175
351
|
readonly budget: number;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
readonly
|
|
352
|
+
readonly replacedMessageCount: number;
|
|
353
|
+
readonly summaryLength: number;
|
|
354
|
+
readonly error?: string;
|
|
355
|
+
}
|
|
356
|
+
interface GuardrailSpanData {
|
|
357
|
+
readonly kind: 'guardrail';
|
|
358
|
+
readonly guardrailName: string;
|
|
359
|
+
readonly hookPoint: 'input' | 'output' | 'tool';
|
|
360
|
+
readonly decision: 'pass' | 'veto' | 'rewrite' | 'error';
|
|
361
|
+
readonly reason?: string;
|
|
362
|
+
readonly error?: string;
|
|
363
|
+
}
|
|
364
|
+
interface EvidenceSpanData {
|
|
365
|
+
readonly kind: 'evidence';
|
|
366
|
+
readonly source: string;
|
|
367
|
+
readonly queryPreview?: string;
|
|
368
|
+
readonly resultCount?: number;
|
|
369
|
+
readonly cacheHit?: boolean;
|
|
370
|
+
readonly error?: string;
|
|
371
|
+
}
|
|
372
|
+
interface FanoutSpanData {
|
|
373
|
+
readonly kind: 'fanout';
|
|
374
|
+
readonly agentName: string;
|
|
375
|
+
readonly childCount: number;
|
|
376
|
+
readonly winnerChildId?: string;
|
|
377
|
+
readonly cancelledChildIds?: readonly string[];
|
|
182
378
|
}
|
|
183
379
|
/**
|
|
184
|
-
*
|
|
380
|
+
* FEATURE_184 (v0.7.45) — Stop hook observability.
|
|
381
|
+
*
|
|
382
|
+
* Emitted when the Runner's `RunOptions.stopHook` is invoked or fails.
|
|
383
|
+
* `outcome` records what the hook returned (or `'error'` for thrown
|
|
384
|
+
* exceptions — fail-open path), `reanimateCount` is the running count
|
|
385
|
+
* after this invocation. `reason` carries the abort/reanimate text
|
|
386
|
+
* when relevant, truncated by consumers as needed.
|
|
185
387
|
*/
|
|
186
|
-
interface
|
|
187
|
-
readonly
|
|
188
|
-
readonly
|
|
388
|
+
interface StopHookSpanData {
|
|
389
|
+
readonly kind: 'stop-hook';
|
|
390
|
+
readonly outcome: 'accept' | 'reanimate' | 'abort' | 'budget-exhausted' | 'error';
|
|
391
|
+
readonly reanimateCount: number;
|
|
392
|
+
readonly reanimateBudget: number;
|
|
393
|
+
readonly reason?: string;
|
|
394
|
+
readonly error?: string;
|
|
189
395
|
}
|
|
190
396
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
397
|
+
* Discriminated union of all span payload shapes. Additional variants may
|
|
398
|
+
* be added in future features — consumers should check `kind` before
|
|
399
|
+
* reading specific fields.
|
|
193
400
|
*/
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
readonly payload: CompactionEntryPayload;
|
|
197
|
-
}
|
|
401
|
+
type SpanData = AgentSpanData | GenerationSpanData | ToolCallSpanData | HandoffSpanData | CompactionSpanData | GuardrailSpanData | EvidenceSpanData | FanoutSpanData | StopHookSpanData;
|
|
402
|
+
|
|
198
403
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
404
|
+
* Span — a single timed unit of work inside a Trace.
|
|
405
|
+
*
|
|
406
|
+
* FEATURE_083 (v0.7.24): minimal Span implementation modeled after the
|
|
407
|
+
* openai-agents-python Trace/Span pattern.
|
|
408
|
+
*
|
|
409
|
+
* Design constraints:
|
|
410
|
+
* - Span creation must be cheap (no await, no serialisation). Processors
|
|
411
|
+
* do their own batching / flushing.
|
|
412
|
+
* - `addChild()` is synchronous and immediately visible in the Trace tree.
|
|
413
|
+
* - `end()` is idempotent; calling it twice is a no-op.
|
|
414
|
+
* - `error` is an optional field that sets a flag on the span without
|
|
415
|
+
* throwing. The consumer decides how to surface errors.
|
|
209
416
|
*/
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
readonly
|
|
417
|
+
|
|
418
|
+
interface SpanError {
|
|
419
|
+
readonly message: string;
|
|
420
|
+
readonly stack?: string;
|
|
421
|
+
readonly data?: unknown;
|
|
213
422
|
}
|
|
214
423
|
/**
|
|
215
|
-
*
|
|
216
|
-
* `shouldCompact()` at round boundaries and call `compact()` when it returns
|
|
217
|
-
* true.
|
|
424
|
+
* Public Span interface. Concrete implementation is `SpanImpl`.
|
|
218
425
|
*/
|
|
219
|
-
interface
|
|
426
|
+
interface Span {
|
|
427
|
+
readonly id: string;
|
|
428
|
+
readonly traceId: string;
|
|
429
|
+
readonly parentId?: string;
|
|
220
430
|
readonly name: string;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
431
|
+
readonly data: SpanData;
|
|
432
|
+
readonly startedAt: number;
|
|
433
|
+
readonly endedAt?: number;
|
|
434
|
+
readonly error?: SpanError;
|
|
435
|
+
readonly children: readonly Span[];
|
|
436
|
+
addChild(name: string, data: SpanData): Span;
|
|
437
|
+
setError(err: SpanError | Error): void;
|
|
438
|
+
end(): void;
|
|
225
439
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
*/
|
|
234
|
-
readonly thresholdRatio?: number;
|
|
235
|
-
/**
|
|
236
|
-
* Number of most-recent message entries to preserve verbatim. Default 10.
|
|
237
|
-
* Must be non-negative.
|
|
238
|
-
*/
|
|
239
|
-
readonly keepRecent?: number;
|
|
240
|
-
/**
|
|
241
|
-
* Optional clock override (ms epoch). Useful for deterministic tests.
|
|
242
|
-
*/
|
|
440
|
+
interface SpanImplOptions {
|
|
441
|
+
readonly id: string;
|
|
442
|
+
readonly traceId: string;
|
|
443
|
+
readonly parentId?: string;
|
|
444
|
+
readonly name: string;
|
|
445
|
+
readonly data: SpanData;
|
|
446
|
+
readonly startedAt?: number;
|
|
243
447
|
readonly now?: () => number;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
readonly randomSuffix?: () => string;
|
|
448
|
+
readonly nextSpanId?: () => string;
|
|
449
|
+
readonly onChildCreated?: (span: Span) => void;
|
|
450
|
+
readonly onSpanEnd?: (span: Span) => void;
|
|
248
451
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
*
|
|
260
|
-
* Caller is responsible for invoking `shouldCompact` and for interpreting the
|
|
261
|
-
* appended entry when building the next turn's prompt.
|
|
262
|
-
*/
|
|
263
|
-
declare class DefaultSummaryCompaction implements CompactionPolicy {
|
|
264
|
-
readonly name = "default-summary";
|
|
265
|
-
private readonly thresholdRatio;
|
|
266
|
-
private readonly keepRecent;
|
|
452
|
+
declare class SpanImpl implements Span {
|
|
453
|
+
readonly id: string;
|
|
454
|
+
readonly traceId: string;
|
|
455
|
+
readonly parentId?: string;
|
|
456
|
+
readonly name: string;
|
|
457
|
+
readonly data: SpanData;
|
|
458
|
+
readonly startedAt: number;
|
|
459
|
+
private _endedAt?;
|
|
460
|
+
private _error?;
|
|
461
|
+
private readonly _children;
|
|
267
462
|
private readonly now;
|
|
268
|
-
private readonly
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
463
|
+
private readonly nextSpanId;
|
|
464
|
+
private readonly onChildCreated?;
|
|
465
|
+
private readonly onSpanEnd?;
|
|
466
|
+
private _ended;
|
|
467
|
+
constructor(opts: SpanImplOptions);
|
|
468
|
+
get endedAt(): number | undefined;
|
|
469
|
+
get error(): SpanError | undefined;
|
|
470
|
+
get children(): readonly Span[];
|
|
471
|
+
addChild(name: string, data: SpanData): Span;
|
|
472
|
+
setError(err: SpanError | Error): void;
|
|
473
|
+
end(): void;
|
|
272
474
|
}
|
|
273
475
|
|
|
274
476
|
/**
|
|
@@ -300,6 +502,12 @@ interface TraceOptions {
|
|
|
300
502
|
readonly onSpanEnd?: (span: Span) => void;
|
|
301
503
|
readonly onTraceEnd?: (trace: Trace) => void;
|
|
302
504
|
}
|
|
505
|
+
/**
|
|
506
|
+
* In-memory Trace implementation. External consumers can replace this with
|
|
507
|
+
* an adapter (OpenTelemetry Trace, Langfuse trace) by registering their own
|
|
508
|
+
* `TracingProcessor`.
|
|
509
|
+
*/
|
|
510
|
+
declare function createTrace(opts?: TraceOptions): Trace;
|
|
303
511
|
|
|
304
512
|
/**
|
|
305
513
|
* Tracer — convenience façade that creates Traces wired to the registered
|
|
@@ -333,6 +541,8 @@ declare class Tracer {
|
|
|
333
541
|
constructor(options?: TracerOptions);
|
|
334
542
|
startTrace(opts?: StartTraceOptions): Trace;
|
|
335
543
|
}
|
|
544
|
+
/** Default tracer shared by the KodaX runtime. External callers can create their own. */
|
|
545
|
+
declare const defaultTracer: Tracer;
|
|
336
546
|
|
|
337
547
|
/**
|
|
338
548
|
* Layer A Primitive: Quality Invariant + Admission Contract types.
|
|
@@ -885,6 +1095,155 @@ declare class InvariantSession {
|
|
|
885
1095
|
*/
|
|
886
1096
|
declare function createInvariantSessionForAgent(agent: Agent): InvariantSession | undefined;
|
|
887
1097
|
|
|
1098
|
+
/**
|
|
1099
|
+
* Runner Tool Loop — FEATURE_084 Shard 1 (v0.7.26).
|
|
1100
|
+
*
|
|
1101
|
+
* Extends the Layer A Runner generic-dispatch path with tool-call support.
|
|
1102
|
+
* Before Shard 1 the Runner could only do a single `system+user → assistant`
|
|
1103
|
+
* turn. Now the injected LLM callback may return a structured result that
|
|
1104
|
+
* declares tool calls; the Runner executes them, appends tool_use +
|
|
1105
|
+
* tool_result content blocks, and loops until the LLM stops emitting tool
|
|
1106
|
+
* calls (or MAX_TOOL_LOOP_ITERATIONS is reached).
|
|
1107
|
+
*
|
|
1108
|
+
* This Shard only lands the capability. No built-in Agent consumes it yet —
|
|
1109
|
+
* the coding preset (SA path) continues to dispatch through
|
|
1110
|
+
* `registerPresetDispatcher` unchanged.
|
|
1111
|
+
*
|
|
1112
|
+
* @experimental Shape may be refined during the v0.7.26 shard rollout.
|
|
1113
|
+
*/
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
* Hard ceiling on tool-loop iterations. A single run may invoke at most this
|
|
1117
|
+
* many LLM turns (counting the initial turn); if the model keeps returning
|
|
1118
|
+
* tool calls past this limit we abort to prevent runaway behaviour.
|
|
1119
|
+
*/
|
|
1120
|
+
declare const MAX_TOOL_LOOP_ITERATIONS = 20;
|
|
1121
|
+
/**
|
|
1122
|
+
* One tool invocation requested by the LLM.
|
|
1123
|
+
*/
|
|
1124
|
+
interface RunnerToolCall {
|
|
1125
|
+
readonly id: string;
|
|
1126
|
+
readonly name: string;
|
|
1127
|
+
readonly input: Record<string, unknown>;
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Structured LLM result. Returning this instead of a plain string lets the
|
|
1131
|
+
* Runner drive a tool loop. If `toolCalls` is empty or omitted the loop
|
|
1132
|
+
* terminates and `text` becomes the final output.
|
|
1133
|
+
*/
|
|
1134
|
+
interface RunnerLlmResult {
|
|
1135
|
+
readonly text: string;
|
|
1136
|
+
readonly toolCalls?: readonly RunnerToolCall[];
|
|
1137
|
+
readonly stopReason?: string;
|
|
1138
|
+
/**
|
|
1139
|
+
* v0.7.26 parity: extended-thinking blocks from the provider stream.
|
|
1140
|
+
* Must be preserved on the assistant message so (a) session resume can
|
|
1141
|
+
* re-render them and (b) Anthropic's extended-thinking API contract is
|
|
1142
|
+
* honoured — provider rejects the next turn with a 400 when a tool_use
|
|
1143
|
+
* turn's `thinking` block is missing from prior assistant history.
|
|
1144
|
+
*/
|
|
1145
|
+
readonly thinkingBlocks?: readonly (KodaXThinkingBlock | KodaXRedactedThinkingBlock)[];
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* LLM callback return type. `string` preserves the v0.7.23 single-turn
|
|
1149
|
+
* behaviour; `RunnerLlmResult` opts into the tool loop.
|
|
1150
|
+
*/
|
|
1151
|
+
type RunnerLlmReturn = string | RunnerLlmResult;
|
|
1152
|
+
/**
|
|
1153
|
+
* Observer callbacks fired around every tool invocation. Preset
|
|
1154
|
+
* dispatchers (e.g. the coding Runner-driven path) pass these through
|
|
1155
|
+
* `RunOptions.toolObserver` so REPL / CLI consumers see live
|
|
1156
|
+
* `onToolCall` / `onToolResult` events, matching the legacy task-engine
|
|
1157
|
+
* event surface (v0.7.22 agent.ts fired `events.onToolResult` at three
|
|
1158
|
+
* sites per invocation).
|
|
1159
|
+
*/
|
|
1160
|
+
interface RunnerToolObserver {
|
|
1161
|
+
/**
|
|
1162
|
+
* Permission / policy gate fired BEFORE each tool invocation. Return
|
|
1163
|
+
* `true` (or `undefined`) to allow, `false` to block with a generic
|
|
1164
|
+
* message, or a `string` to block with that message as the tool result.
|
|
1165
|
+
* Used to hook plan-mode / accept-edits / extension `tool:before`
|
|
1166
|
+
* policies onto the Runner-driven path (v0.7.22 parity — legacy
|
|
1167
|
+
* `events.beforeToolExecute` surface).
|
|
1168
|
+
*/
|
|
1169
|
+
readonly beforeTool?: (call: RunnerToolCall) => Promise<boolean | string | undefined>;
|
|
1170
|
+
readonly onToolCall?: (call: RunnerToolCall) => void;
|
|
1171
|
+
readonly onToolResult?: (call: RunnerToolCall, result: RunnerToolResult) => void;
|
|
1172
|
+
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Context passed to a RunnableTool's `execute` function.
|
|
1175
|
+
*/
|
|
1176
|
+
interface RunnerToolContext {
|
|
1177
|
+
readonly agent: Agent;
|
|
1178
|
+
readonly abortSignal?: AbortSignal;
|
|
1179
|
+
/** The agent's Span, so tool implementations can nest custom spans if needed. */
|
|
1180
|
+
readonly agentSpan?: Span | null;
|
|
1181
|
+
/**
|
|
1182
|
+
* Current tool_use call id. Passed through so tool wrappers can correlate
|
|
1183
|
+
* progress events (`onToolProgress`) and other per-call side-effects with
|
|
1184
|
+
* the REPL's tool-block in the transcript. Populated by `executeRunnerToolCall`.
|
|
1185
|
+
*/
|
|
1186
|
+
readonly toolCallId?: string;
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* Value returned by `RunnableTool.execute`. The `content` is what the LLM
|
|
1190
|
+
* sees in the next turn as `tool_result`:
|
|
1191
|
+
*
|
|
1192
|
+
* - `string` — plain text (the default for most tools).
|
|
1193
|
+
* - `readonly KodaXToolResultContentItem[]` — an array of typed items
|
|
1194
|
+
* (text + image), used by multimodal tools like `read` on an image
|
|
1195
|
+
* path. Provider serializers lower each item to the wire format
|
|
1196
|
+
* (Anthropic accepts inline; OpenAI-compat downgrades image to text
|
|
1197
|
+
* placeholder).
|
|
1198
|
+
*/
|
|
1199
|
+
interface RunnerToolResult {
|
|
1200
|
+
readonly content: string | readonly KodaXToolResultContentItem[];
|
|
1201
|
+
readonly isError?: boolean;
|
|
1202
|
+
readonly metadata?: Record<string, unknown>;
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* A tool bundled with its executor. Extends `AgentTool` (the wire-format
|
|
1206
|
+
* `KodaXToolDefinition`) so it can be passed through to the provider
|
|
1207
|
+
* unchanged while also carrying a function the Runner can invoke.
|
|
1208
|
+
*/
|
|
1209
|
+
interface RunnableTool extends AgentTool {
|
|
1210
|
+
readonly execute: (input: Record<string, unknown>, ctx: RunnerToolContext) => Promise<RunnerToolResult>;
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Narrowing helper — distinguishes a `RunnableTool` from a plain
|
|
1214
|
+
* `AgentTool`. An agent may declare both: the Runner only executes the
|
|
1215
|
+
* tools that carry an `execute` function.
|
|
1216
|
+
*/
|
|
1217
|
+
declare function isRunnableTool(tool: AgentTool): tool is RunnableTool;
|
|
1218
|
+
/**
|
|
1219
|
+
* Narrowing helper for the LLM callback return shape.
|
|
1220
|
+
*/
|
|
1221
|
+
declare function isRunnerLlmResult(value: unknown): value is RunnerLlmResult;
|
|
1222
|
+
/**
|
|
1223
|
+
* Execute one tool call against the agent's declared tools. Emits a
|
|
1224
|
+
* ToolCallSpan under `ctx.agentSpan` when tracing is active. Returns a
|
|
1225
|
+
* `RunnerToolResult` — tool errors do not throw, they are surfaced with
|
|
1226
|
+
* `isError: true` so the LLM can see them in the next turn and react.
|
|
1227
|
+
*/
|
|
1228
|
+
declare function executeRunnerToolCall(call: RunnerToolCall, agent: Agent, ctx: RunnerToolContext): Promise<RunnerToolResult>;
|
|
1229
|
+
/**
|
|
1230
|
+
* Build the assistant message that captures one LLM turn. Preserves
|
|
1231
|
+
* thinking blocks (extended-thinking contract), text blocks, and tool_use
|
|
1232
|
+
* blocks in the order Anthropic's wire format expects: thinking → text →
|
|
1233
|
+
* tool_use. This mirrors v0.7.22 `agent.ts:2230`
|
|
1234
|
+
* (`[...thinkingBlocks, ...textBlocks, ...visibleToolBlocks]`) which the
|
|
1235
|
+
* Runner-driven path must preserve — without it Anthropic returns 400 on
|
|
1236
|
+
* the next turn when extended thinking is active, and session resume
|
|
1237
|
+
* loses the reasoning trace.
|
|
1238
|
+
*/
|
|
1239
|
+
declare function buildAssistantMessageFromLlmResult(result: RunnerLlmResult): AgentMessage;
|
|
1240
|
+
/**
|
|
1241
|
+
* Build the user message that carries tool_result blocks back to the LLM.
|
|
1242
|
+
* Provider serializers (Anthropic, OpenAI) both accept tool_result on the
|
|
1243
|
+
* user turn.
|
|
1244
|
+
*/
|
|
1245
|
+
declare function buildToolResultMessage(calls: readonly RunnerToolCall[], results: readonly RunnerToolResult[]): AgentMessage;
|
|
1246
|
+
|
|
888
1247
|
/**
|
|
889
1248
|
* Layer A Primitive: Runner
|
|
890
1249
|
*
|
|
@@ -1307,169 +1666,612 @@ declare class Runner {
|
|
|
1307
1666
|
declare function extractAssistantTextFromMessage(message: AgentMessage): string;
|
|
1308
1667
|
|
|
1309
1668
|
/**
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
*
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1324
|
-
*
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1327
|
-
*
|
|
1328
|
-
*
|
|
1329
|
-
*
|
|
1330
|
-
*
|
|
1331
|
-
*
|
|
1332
|
-
*
|
|
1333
|
-
*
|
|
1334
|
-
*
|
|
1335
|
-
*
|
|
1336
|
-
|
|
1337
|
-
* `path.join(os.homedir(), '.kodax')` calls — so the migration
|
|
1338
|
-
* from hardcoded sites to this helper is byte-equivalent for the
|
|
1339
|
-
* existing user base.
|
|
1340
|
-
*
|
|
1341
|
-
* Why a process-level singleton (and not per-call DI):
|
|
1342
|
-
* the ~30 fs callsites are buried in library helpers (construction /
|
|
1343
|
-
* mcp catalog / oauth tokens / paste-cache etc.). Threading a
|
|
1344
|
-
* `configHome` parameter through every helper would change ~50
|
|
1345
|
-
* function signatures, and every caller would have to remember to
|
|
1346
|
-
* thread it — a single forgotten thread silently falls back to
|
|
1347
|
-
* default. Singleton matches the `process.env.NODE_ENV` pattern: a
|
|
1348
|
-
* process really has a single config home (no legitimate use case
|
|
1349
|
-
* for a process to interleave reads/writes against `~/.kodax/` AND
|
|
1350
|
-
* `~/.opsagent/` simultaneously).
|
|
1351
|
-
*
|
|
1352
|
-
* NOT migrated:
|
|
1353
|
-
* - `@kodax-ai/llm/src/reasoning-overrides.ts:49` keeps its inline
|
|
1354
|
-
* `process.env.KODAX_HOME ?? path.join(os.homedir(), '.kodax')`
|
|
1355
|
-
* fallback because moving it to this helper would create an
|
|
1356
|
-
* `@kodax-ai/llm → @kodax-ai/agent` dependency cycle (agent already
|
|
1357
|
-
* imports ai). The two implementations have identical observable
|
|
1358
|
-
* behavior at the env / default tiers; the programmatic override
|
|
1359
|
-
* tier doesn't apply to ai-layer code.
|
|
1360
|
-
* - **Project-relative** `.kodax/` paths (e.g. `path.join(projectRoot,
|
|
1361
|
-
* '.kodax', 'AGENTS.md')`) are NOT migrated — those name a
|
|
1362
|
-
* different concept (per-project config) and use a different root.
|
|
1363
|
-
* - **CWD-relative** subpath constants like `path.join('.kodax',
|
|
1364
|
-
* 'constructed', '_audit.jsonl')` (joined with a project root by
|
|
1365
|
-
* the caller) are likewise project-scoped and stay as-is.
|
|
1366
|
-
*/
|
|
1367
|
-
/**
|
|
1368
|
-
* Set the agent config home programmatically. Highest priority in
|
|
1369
|
-
* {@link getAgentConfigHome}'s 3-tier chain.
|
|
1370
|
-
*
|
|
1371
|
-
* Substrate consumers (e.g. an agent built on top of `@kodax-ai/agent`)
|
|
1372
|
-
* should call this once at process boot, before any subsystem reads
|
|
1373
|
-
* the path. Pass `undefined` to reset (used in tests).
|
|
1374
|
-
*/
|
|
1375
|
-
declare function setAgentConfigHome(path: string | undefined): void;
|
|
1376
|
-
/**
|
|
1377
|
-
* Resolve the agent runtime config home directory.
|
|
1378
|
-
*
|
|
1379
|
-
* Priority (high → low):
|
|
1380
|
-
* 1. Programmatic override via {@link setAgentConfigHome}
|
|
1381
|
-
* 2. `KODAX_HOME` env var
|
|
1382
|
-
* 3. `~/.kodax` (hardcoded default)
|
|
1383
|
-
*/
|
|
1384
|
-
declare function getAgentConfigHome(): string;
|
|
1385
|
-
/**
|
|
1386
|
-
* Resolve a sub-path under the agent config home.
|
|
1387
|
-
*
|
|
1388
|
-
* Equivalent to `path.join(getAgentConfigHome(), ...segments)` but
|
|
1389
|
-
* shorter at every callsite (which is the entire point of the helper —
|
|
1390
|
-
* 30 callsites of `path.join(os.homedir(), '.kodax', x, y)` collapse to
|
|
1391
|
-
* 30 callsites of `getAgentConfigPath(x, y)`).
|
|
1392
|
-
*/
|
|
1393
|
-
declare function getAgentConfigPath(...segments: string[]): string;
|
|
1394
|
-
/**
|
|
1395
|
-
* v0.7.42 — Namespaced data directory for third-party apps embedding the
|
|
1396
|
-
* KodaX SDK (e.g. `KodaX Space` desktop client, IDE extensions).
|
|
1397
|
-
*
|
|
1398
|
-
* Returns `${getAgentConfigHome()}/apps/<appId>/` and creates the directory
|
|
1399
|
-
* if missing. Provides a coordination point so multiple SDK consumers can
|
|
1400
|
-
* share `~/.kodax/` without colliding on path conventions.
|
|
1401
|
-
*
|
|
1402
|
-
* Constraints:
|
|
1403
|
-
* - `appId` must match `^[a-z][a-z0-9-]{1,31}$` (lowercase kebab, 2–32 chars,
|
|
1404
|
-
* no dots, no slashes, no underscores) — keeps the directory name safe
|
|
1405
|
-
* across all filesystems and prevents `../` traversal.
|
|
1406
|
-
* - Reserved prefixes (`kodax`, `kodax-*`) are rejected to leave room
|
|
1407
|
-
* for first-party feature directories that may collide later.
|
|
1408
|
-
*
|
|
1409
|
-
* The convention is intentionally light — no central registry, no manifest.
|
|
1410
|
-
* Apps owning their data dir means SDK upgrades cannot trample on third-party
|
|
1411
|
-
* state. Apps are responsible for migration/cleanup within their own subtree.
|
|
1412
|
-
*/
|
|
1413
|
-
declare function getAppDataDir(appId: string): string;
|
|
1669
|
+
* Guardrail Runtime — FEATURE_085 (v0.7.26).
|
|
1670
|
+
*
|
|
1671
|
+
* Three-tier runtime for Agent guardrails:
|
|
1672
|
+
*
|
|
1673
|
+
* - `InputGuardrail`: runs once before the first LLM turn, inspects the
|
|
1674
|
+
* full input transcript, may allow / rewrite / block / escalate.
|
|
1675
|
+
* - `OutputGuardrail`: runs once before returning, inspects the final
|
|
1676
|
+
* assistant message, may allow / rewrite / block / escalate.
|
|
1677
|
+
* - `ToolGuardrail`: runs before and/or after each tool invocation,
|
|
1678
|
+
* inspects the call / result, may allow / rewrite / block / escalate.
|
|
1679
|
+
*
|
|
1680
|
+
* The four verdict actions:
|
|
1681
|
+
*
|
|
1682
|
+
* - `allow`: continue with the current value.
|
|
1683
|
+
* - `rewrite`: replace the current value with `payload`.
|
|
1684
|
+
* - `block`: throw `GuardrailBlockedError` (for input/output) or surface
|
|
1685
|
+
* an error tool_result (for tool-before); the LLM / caller sees a
|
|
1686
|
+
* rejection and must adapt.
|
|
1687
|
+
* - `escalate`: throw `GuardrailEscalateError`; the SDK consumer catches
|
|
1688
|
+
* and decides whether to prompt the user, retry under different
|
|
1689
|
+
* constraints, etc.
|
|
1690
|
+
*
|
|
1691
|
+
* Every guardrail invocation emits a `GuardrailSpan` under the agent's
|
|
1692
|
+
* span when tracing is active.
|
|
1693
|
+
*
|
|
1694
|
+
* @experimental API shape may adjust during v0.7.x rollout.
|
|
1695
|
+
*/
|
|
1414
1696
|
|
|
1415
1697
|
/**
|
|
1416
|
-
*
|
|
1698
|
+
* Shared execution context passed to every guardrail.
|
|
1417
1699
|
*
|
|
1418
|
-
*
|
|
1700
|
+
* `messages` is the live conversation transcript at the moment this
|
|
1701
|
+
* guardrail fires. For tool-side guardrails this is the transcript at
|
|
1702
|
+
* call-site time — it does NOT yet include the assistant turn that
|
|
1703
|
+
* emitted the current tool_use, since that turn is appended only after
|
|
1704
|
+
* the full tool batch settles. Optional so existing guardrails that
|
|
1705
|
+
* don't read context still type-check; populated by the Runner for all
|
|
1706
|
+
* production hook points.
|
|
1419
1707
|
*
|
|
1420
|
-
*
|
|
1421
|
-
*
|
|
1422
|
-
*
|
|
1708
|
+
* Added in FEATURE_092 (v0.7.33) so the auto-mode classifier guardrail
|
|
1709
|
+
* can extract intent context (user prompt + prior tool_use / tool_result
|
|
1710
|
+
* blocks) without reaching into Runner internals.
|
|
1711
|
+
*/
|
|
1712
|
+
interface GuardrailContext {
|
|
1713
|
+
readonly agent: Agent;
|
|
1714
|
+
readonly abortSignal?: AbortSignal;
|
|
1715
|
+
readonly messages?: readonly AgentMessage[];
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* Outcome of a single guardrail check. `payload` shape depends on the hook
|
|
1719
|
+
* point — see the specific guardrail interface for the expected type.
|
|
1720
|
+
*/
|
|
1721
|
+
type GuardrailVerdict = {
|
|
1722
|
+
readonly action: 'allow';
|
|
1723
|
+
} | {
|
|
1724
|
+
readonly action: 'rewrite';
|
|
1725
|
+
readonly payload: unknown;
|
|
1726
|
+
readonly reason?: string;
|
|
1727
|
+
} | {
|
|
1728
|
+
readonly action: 'block';
|
|
1729
|
+
readonly reason: string;
|
|
1730
|
+
} | {
|
|
1731
|
+
readonly action: 'escalate';
|
|
1732
|
+
readonly reason: string;
|
|
1733
|
+
};
|
|
1734
|
+
/**
|
|
1735
|
+
* Input-side guardrail. Expected `rewrite` payload shape:
|
|
1736
|
+
* `readonly AgentMessage[]` — the replacement transcript.
|
|
1737
|
+
*/
|
|
1738
|
+
interface InputGuardrail extends Guardrail {
|
|
1739
|
+
readonly kind: 'input';
|
|
1740
|
+
check(input: readonly AgentMessage[], ctx: GuardrailContext): Promise<GuardrailVerdict>;
|
|
1741
|
+
}
|
|
1742
|
+
/**
|
|
1743
|
+
* Output-side guardrail. Expected `rewrite` payload shape:
|
|
1744
|
+
* `AgentMessage` — the replacement final assistant message.
|
|
1745
|
+
*/
|
|
1746
|
+
interface OutputGuardrail extends Guardrail {
|
|
1747
|
+
readonly kind: 'output';
|
|
1748
|
+
check(output: AgentMessage, ctx: GuardrailContext): Promise<GuardrailVerdict>;
|
|
1749
|
+
}
|
|
1750
|
+
/**
|
|
1751
|
+
* Tool-side guardrail. `beforeTool` rewrite payload shape: `RunnerToolCall`
|
|
1752
|
+
* (replacement call). `afterTool` rewrite payload shape: `RunnerToolResult`
|
|
1753
|
+
* (replacement result). Either hook is optional.
|
|
1754
|
+
*/
|
|
1755
|
+
interface ToolGuardrail extends Guardrail {
|
|
1756
|
+
readonly kind: 'tool';
|
|
1757
|
+
beforeTool?(call: RunnerToolCall, ctx: GuardrailContext): Promise<GuardrailVerdict>;
|
|
1758
|
+
afterTool?(call: RunnerToolCall, result: RunnerToolResult, ctx: GuardrailContext): Promise<GuardrailVerdict>;
|
|
1759
|
+
}
|
|
1760
|
+
/**
|
|
1761
|
+
* Thrown when any guardrail returns `{ action: 'block' }`. The Runner
|
|
1762
|
+
* propagates this up to the caller — the run is aborted at that point.
|
|
1763
|
+
*/
|
|
1764
|
+
declare class GuardrailBlockedError extends Error {
|
|
1765
|
+
readonly guardrailName: string;
|
|
1766
|
+
readonly hookPoint: 'input' | 'output' | 'tool';
|
|
1767
|
+
constructor(guardrailName: string, hookPoint: 'input' | 'output' | 'tool', reason: string);
|
|
1768
|
+
}
|
|
1769
|
+
/**
|
|
1770
|
+
* Thrown when any guardrail returns `{ action: 'escalate' }`. Callers can
|
|
1771
|
+
* catch and prompt the user or apply a stricter policy before retrying.
|
|
1772
|
+
*/
|
|
1773
|
+
declare class GuardrailEscalateError extends Error {
|
|
1774
|
+
readonly guardrailName: string;
|
|
1775
|
+
readonly hookPoint: 'input' | 'output' | 'tool';
|
|
1776
|
+
constructor(guardrailName: string, hookPoint: 'input' | 'output' | 'tool', reason: string);
|
|
1777
|
+
}
|
|
1778
|
+
/** Filter a guardrail list by hook-point. */
|
|
1779
|
+
declare function collectGuardrails(guardrails: readonly Guardrail[] | undefined): {
|
|
1780
|
+
input: readonly InputGuardrail[];
|
|
1781
|
+
output: readonly OutputGuardrail[];
|
|
1782
|
+
tool: readonly ToolGuardrail[];
|
|
1783
|
+
};
|
|
1784
|
+
/**
|
|
1785
|
+
* Run all input guardrails in declaration order. Returns the (possibly
|
|
1786
|
+
* rewritten) transcript. Throws on block / escalate.
|
|
1787
|
+
*/
|
|
1788
|
+
declare function runInputGuardrails(transcript: readonly AgentMessage[], guardrails: readonly InputGuardrail[], ctx: GuardrailContext, agentSpan: Span | null): Promise<readonly AgentMessage[]>;
|
|
1789
|
+
/**
|
|
1790
|
+
* Run all output guardrails in declaration order. Returns the (possibly
|
|
1791
|
+
* rewritten) final assistant message. Throws on block / escalate.
|
|
1792
|
+
*/
|
|
1793
|
+
declare function runOutputGuardrails(output: AgentMessage, guardrails: readonly OutputGuardrail[], ctx: GuardrailContext, agentSpan: Span | null): Promise<AgentMessage>;
|
|
1794
|
+
/**
|
|
1795
|
+
* Outcome of the before-tool guardrail stage.
|
|
1796
|
+
* - `{ kind: 'allow', call }`: continue to executeRunnerToolCall with `call`
|
|
1797
|
+
* - `{ kind: 'block', result }`: skip execution; return `result` as the
|
|
1798
|
+
* tool_result to the LLM (so it sees the rejection and can adapt)
|
|
1799
|
+
*/
|
|
1800
|
+
type ToolBeforeOutcome = {
|
|
1801
|
+
readonly kind: 'allow';
|
|
1802
|
+
readonly call: RunnerToolCall;
|
|
1803
|
+
} | {
|
|
1804
|
+
readonly kind: 'block';
|
|
1805
|
+
readonly result: RunnerToolResult;
|
|
1806
|
+
};
|
|
1807
|
+
/**
|
|
1808
|
+
* Run before-tool guardrails in declaration order. Rewrite replaces the
|
|
1809
|
+
* tool call. Block surfaces an error tool_result to the LLM instead of
|
|
1810
|
+
* throwing — the LLM sees the rejection and adapts. Escalate still throws.
|
|
1811
|
+
*/
|
|
1812
|
+
declare function runToolBeforeGuardrails(call: RunnerToolCall, guardrails: readonly ToolGuardrail[], ctx: GuardrailContext, agentSpan: Span | null): Promise<ToolBeforeOutcome>;
|
|
1813
|
+
/**
|
|
1814
|
+
* Run after-tool guardrails in declaration order. Rewrite replaces the
|
|
1815
|
+
* result content. Block replaces with an error result. Escalate throws.
|
|
1816
|
+
*/
|
|
1817
|
+
declare function runToolAfterGuardrails(call: RunnerToolCall, result: RunnerToolResult, guardrails: readonly ToolGuardrail[], ctx: GuardrailContext, agentSpan: Span | null): Promise<RunnerToolResult>;
|
|
1818
|
+
|
|
1819
|
+
/**
|
|
1820
|
+
* Child task registry primitive — generic fan-out tracking.
|
|
1821
|
+
*
|
|
1822
|
+
* FEATURE_120 v0.7.39 Step 0 (package-attribution migration, ADR-021).
|
|
1823
|
+
* Lifted from `@kodax-ai/coding`'s `KodaXToolExecutionContext.childTaskRegistry`
|
|
1824
|
+
* field + inline cleanup chain in `tools/dispatch-child-tasks.ts`. The
|
|
1825
|
+
* coding side now consumes this primitive specialized to its
|
|
1826
|
+
* `KodaXChildExecutionResult` type; any other agent-flavor downstream
|
|
1827
|
+
* can specialize on its own child-result type without re-implementing
|
|
1828
|
+
* the cleanup contract.
|
|
1829
|
+
*
|
|
1830
|
+
* The shape is intentionally minimal: a Map plus a `register` helper
|
|
1831
|
+
* that bundles the v0.7.38 FEATURE_155 Bug A hotfix (`c1bdaf4e`)
|
|
1832
|
+
* cleanup chain into a single call site. The helper exists because
|
|
1833
|
+
* the cleanup is **not optional** — without it, every settled promise
|
|
1834
|
+
* stays in the registry forever, gets re-wrapped by the next
|
|
1835
|
+
* idle-yield `waitForWakeEvent` call, and fires spurious
|
|
1836
|
+
* `child-completed` wakes (production symptom: Evaluator gets
|
|
1837
|
+
* bombarded by duplicate `<task-completed>` notifications, consuming
|
|
1838
|
+
* an LLM turn each up to `IDLE_YIELD_MAX_ITERATIONS=64`).
|
|
1839
|
+
*/
|
|
1840
|
+
/**
|
|
1841
|
+
* Map of `task_id` → in-flight child-execution promise. Generic over
|
|
1842
|
+
* the child-result type so the agent layer doesn't depend on any
|
|
1843
|
+
* specific agent flavor's result shape.
|
|
1844
|
+
*
|
|
1845
|
+
* Mutation contract:
|
|
1846
|
+
* - Owned by the runner's per-turn execution context. The dispatch
|
|
1847
|
+
* tool writes via `registerChildTask`; the idle-yield outer loop
|
|
1848
|
+
* reads via `Map.prototype.entries()` / `.size`.
|
|
1849
|
+
* - **Never delete entries manually** — call `registerChildTask`
|
|
1850
|
+
* and the cleanup chain it installs will run on settle.
|
|
1851
|
+
*/
|
|
1852
|
+
type ChildTaskRegistry<T> = Map<string, Promise<T>>;
|
|
1853
|
+
/**
|
|
1854
|
+
* Register an in-flight child-execution promise in the registry and
|
|
1855
|
+
* install the cleanup chain that removes the entry once the promise
|
|
1856
|
+
* settles (success or failure).
|
|
1857
|
+
*
|
|
1858
|
+
* The cleanup chain is two stages:
|
|
1859
|
+
* 1. `.finally(() => registry.delete(childId))` — runs on settle
|
|
1860
|
+
* regardless of outcome, removing the entry before the next
|
|
1861
|
+
* idle-yield outer-loop iteration observes the registry.
|
|
1862
|
+
* 2. `.catch(() => {})` — swallows the rejection on the cleanup
|
|
1863
|
+
* chain so a child that crashes before any consumer awaits it
|
|
1864
|
+
* doesn't surface as `unhandledRejection` on Node. Must come
|
|
1865
|
+
* AFTER `.finally` because `.finally` returns a NEW promise
|
|
1866
|
+
* that rejects with the same reason.
|
|
1867
|
+
*
|
|
1868
|
+
* The original `promise` argument is **not** returned — the helper's
|
|
1869
|
+
* value-add is the cleanup side-effect, not promise transformation.
|
|
1870
|
+
* Callers that need to await the result read from `registry.get(id)`
|
|
1871
|
+
* or hold their own reference.
|
|
1872
|
+
*
|
|
1873
|
+
* @throws Error when `childId` already exists in the registry. Caller
|
|
1874
|
+
* should report this to the LLM as a tool-error (duplicate task_id);
|
|
1875
|
+
* the helper does NOT swallow the conflict because that would
|
|
1876
|
+
* silently overwrite an in-flight child's tracking entry.
|
|
1877
|
+
*/
|
|
1878
|
+
declare function registerChildTask<T>(registry: ChildTaskRegistry<T>, childId: string, promise: Promise<T>): void;
|
|
1879
|
+
|
|
1880
|
+
/**
|
|
1881
|
+
* Generic per-task abort primitive — `requestTaskStop`.
|
|
1882
|
+
*
|
|
1883
|
+
* FEATURE_120 v0.7.39 Phase 3a (ADR-021). Coordinator-style agents need
|
|
1884
|
+
* to request that a specific in-flight child task exit gracefully. The
|
|
1885
|
+
* @kodax-ai/agent layer owns the abort-controller registry shape and
|
|
1886
|
+
* the abort-dispatch decision; agent-flavor wrappers (e.g. the coding
|
|
1887
|
+
* `task_stop` tool, Phase 3b) layer in domain framing such as the
|
|
1888
|
+
* `<coordinator-stop-request>` message tag.
|
|
1889
|
+
*
|
|
1890
|
+
* What this primitive owns:
|
|
1891
|
+
* - A `TaskAbortRegistry` type alias = `Map<string, AbortController>`.
|
|
1892
|
+
* The map is owned + mutated by the caller; the primitive only
|
|
1893
|
+
* reads it. Callers use `registry.set(id, controller)` /
|
|
1894
|
+
* `registry.delete(id)` directly — the standard `Map` mutators
|
|
1895
|
+
* are simple enough that wrapping them adds no value.
|
|
1896
|
+
* - `requestTaskStop({taskId, registry, reason?})` — looks up the
|
|
1897
|
+
* controller, decides whether to abort, calls `controller.abort`,
|
|
1898
|
+
* returns a structured outcome.
|
|
1899
|
+
*
|
|
1900
|
+
* Abort semantics (matches the existing FEATURE_115 soft-pause
|
|
1901
|
+
* principle): aborting fires the signal but does NOT interrupt any
|
|
1902
|
+
* synchronous tool that's already executing. The child's next abort
|
|
1903
|
+
* check (`signal.throwIfAborted()` or an `signal.aborted` poll)
|
|
1904
|
+
* surfaces the abort. This matches Node's AbortController contract.
|
|
1905
|
+
*
|
|
1906
|
+
* What this primitive does NOT do (deliberate):
|
|
1907
|
+
* - Enqueue a coordinator-stop-request message — that's a
|
|
1908
|
+
* coding-flavor convenience and uses the existing
|
|
1909
|
+
* `routeMessage` primitive at the tool layer.
|
|
1910
|
+
* - Track abort lifecycle / auto-cleanup the registry — the
|
|
1911
|
+
* controller's lifetime is tied to its owning task's Promise;
|
|
1912
|
+
* the caller removes the registry entry when the task settles
|
|
1913
|
+
* (typically in a `.finally` chain alongside the child-task
|
|
1914
|
+
* registry cleanup).
|
|
1915
|
+
* - Time-out enforcement / retry — orthogonal concerns owned at
|
|
1916
|
+
* higher layers if needed.
|
|
1917
|
+
*/
|
|
1918
|
+
/**
|
|
1919
|
+
* Registry mapping task ids to their owning AbortController.
|
|
1920
|
+
* Lifetime: created per parent-run, populated at child dispatch,
|
|
1921
|
+
* cleared when the child Promise settles.
|
|
1922
|
+
*/
|
|
1923
|
+
type TaskAbortRegistry = Map<string, AbortController>;
|
|
1924
|
+
interface RequestTaskStopOptions {
|
|
1925
|
+
/** Target task id. Must exist as a key in `registry`. */
|
|
1926
|
+
readonly taskId: string;
|
|
1927
|
+
/** Registry of in-flight task abort controllers. */
|
|
1928
|
+
readonly registry: ReadonlyMap<string, AbortController>;
|
|
1929
|
+
/**
|
|
1930
|
+
* Optional cause forwarded to `AbortController.abort(reason)`.
|
|
1931
|
+
* - Error → passed through verbatim (preserves stack / custom
|
|
1932
|
+
* subclasses).
|
|
1933
|
+
* - string → wrapped in `new Error(reason)`.
|
|
1934
|
+
* - undefined → a default Error mentioning the taskId is
|
|
1935
|
+
* fabricated so the child receives a non-empty signal.reason.
|
|
1936
|
+
*/
|
|
1937
|
+
readonly reason?: string | Error;
|
|
1938
|
+
}
|
|
1939
|
+
type RequestTaskStopResult = {
|
|
1940
|
+
readonly ok: true;
|
|
1941
|
+
readonly taskId: string;
|
|
1942
|
+
} | {
|
|
1943
|
+
readonly ok: false;
|
|
1944
|
+
readonly reason: 'unknown-target';
|
|
1945
|
+
readonly taskId: string;
|
|
1946
|
+
} | {
|
|
1947
|
+
readonly ok: false;
|
|
1948
|
+
readonly reason: 'already-aborted';
|
|
1949
|
+
readonly taskId: string;
|
|
1950
|
+
};
|
|
1951
|
+
/**
|
|
1952
|
+
* Look up `taskId` in `registry`. If found and not yet aborted, abort
|
|
1953
|
+
* the controller with the supplied reason. Returns a discriminated
|
|
1954
|
+
* outcome so callers can render success / error UX without string
|
|
1955
|
+
* matching.
|
|
1423
1956
|
*
|
|
1424
|
-
*
|
|
1425
|
-
*
|
|
1426
|
-
*
|
|
1427
|
-
*
|
|
1428
|
-
* the next request.
|
|
1957
|
+
* `already-aborted` is reported separately from success because the
|
|
1958
|
+
* first-abort `signal.reason` is preserved verbatim — debugging
|
|
1959
|
+
* chains depend on the original cause not being overwritten by
|
|
1960
|
+
* subsequent stop requests.
|
|
1429
1961
|
*
|
|
1430
|
-
*
|
|
1431
|
-
*
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1962
|
+
* Synchronous: `AbortController.abort` is synchronous; no async work
|
|
1963
|
+
* is performed by this primitive.
|
|
1964
|
+
*/
|
|
1965
|
+
declare function requestTaskStop(opts: RequestTaskStopOptions): RequestTaskStopResult;
|
|
1966
|
+
|
|
1967
|
+
/**
|
|
1968
|
+
* FEATURE_125 (v0.7.41) — Team Mode Layer 1: per-instance state broadcast.
|
|
1969
|
+
*
|
|
1970
|
+
* Each running KodaX session registers a directory under
|
|
1971
|
+
* `<agentConfigHome>/instances/<pid>/` containing three files:
|
|
1972
|
+
*
|
|
1973
|
+
* meta.json — written once at registration; cwd / startedAt /
|
|
1974
|
+
* optional git branch + remote. Static for the session.
|
|
1975
|
+
* state.json — re-written whenever the session's `currentIntent`,
|
|
1976
|
+
* `agentPhase`, or active/recently-modified file set
|
|
1977
|
+
* changes. Read by sibling sessions for context.
|
|
1978
|
+
* heartbeat — empty file whose mtime is touched on every refresh.
|
|
1979
|
+
* Sibling sessions use the mtime to declare an instance
|
|
1980
|
+
* stale (default 30s of no heartbeat → cleanup).
|
|
1981
|
+
*
|
|
1982
|
+
* Atomic write strategy:
|
|
1983
|
+
* - state.json is written via `<path>.tmp` + `rename()`. On POSIX the
|
|
1984
|
+
* rename is atomic; on Windows it is atomic when source + target sit
|
|
1985
|
+
* on the same filesystem (always true for `<agentConfigHome>/...`).
|
|
1986
|
+
* - heartbeat is touched via `utimesSync()`. Cheap, no rename needed.
|
|
1987
|
+
*
|
|
1988
|
+
* Lifecycle:
|
|
1989
|
+
* - `createStateWriter` writes meta.json + state.json + heartbeat once,
|
|
1990
|
+
* then starts an interval timer (default 1000ms) that refreshes
|
|
1991
|
+
* state.json and touches heartbeat.
|
|
1992
|
+
* - `update(patch)` shallow-merges the patch into the in-memory state
|
|
1993
|
+
* and flushes immediately so peer sessions see the change at the
|
|
1994
|
+
* next tool boundary, not at the next heartbeat tick.
|
|
1995
|
+
* - `shutdown()` clears the timer, removes the instance directory,
|
|
1996
|
+
* and resolves. Idempotent — safe to call multiple times.
|
|
1997
|
+
*
|
|
1998
|
+
* Crash recovery:
|
|
1999
|
+
* - If a process is killed mid-run, the directory is left on disk.
|
|
2000
|
+
* The next session's discovery scan (S2, `instance-discovery.ts`)
|
|
2001
|
+
* detects the stale heartbeat and removes the directory.
|
|
2002
|
+
*
|
|
2003
|
+
* DI-clean: every fs / clock dependency is injectable for hermetic tests.
|
|
2004
|
+
*/
|
|
2005
|
+
/**
|
|
2006
|
+
* Live session state surfaced to sibling KodaX sessions. Mirrors the
|
|
2007
|
+
* shape documented in `docs/features/v0.7.41.md#feature_125-step-1`.
|
|
2008
|
+
*/
|
|
2009
|
+
interface SessionStateSnapshot {
|
|
2010
|
+
readonly agentPhase: 'idle' | 'awaiting_llm' | 'running_tool';
|
|
2011
|
+
/** Single-line description of what the agent is currently doing. */
|
|
2012
|
+
readonly currentIntent?: string;
|
|
2013
|
+
/** Files the session is actively editing right now. */
|
|
2014
|
+
readonly activeFiles?: readonly string[];
|
|
2015
|
+
/** Files modified in the recent past (sibling sessions read this to detect "their content may be stale"). */
|
|
2016
|
+
readonly recentlyModifiedFiles?: readonly RecentlyModifiedFile[];
|
|
2017
|
+
/**
|
|
2018
|
+
* FEATURE_170 (v0.7.41) — optional one-line summary of the active
|
|
2019
|
+
* todo list. Lets sibling sessions display "they're currently
|
|
2020
|
+
* working on: <X>" without owning the todo store.
|
|
2021
|
+
*/
|
|
2022
|
+
readonly currentTodoSummary?: CurrentTodoSummary;
|
|
2023
|
+
/**
|
|
2024
|
+
* v0.7.43 (FEATURE_173 Part B follow-up) — REPL session id
|
|
2025
|
+
* (e.g. `YYYYMMDD_HHMMSS`). Lets `listRunningSessions()` correlate
|
|
2026
|
+
* a sibling instance with its `.jsonl` file. Mutable: starts
|
|
2027
|
+
* undefined during bootstrap, set after `createInteractiveContext`,
|
|
2028
|
+
* re-published on `/new`. Older writers omit this; readers MUST
|
|
2029
|
+
* treat as optional.
|
|
2030
|
+
*/
|
|
2031
|
+
readonly sessionId?: string;
|
|
2032
|
+
}
|
|
2033
|
+
interface RecentlyModifiedFile {
|
|
2034
|
+
readonly path: string;
|
|
2035
|
+
readonly modifiedAt: number;
|
|
2036
|
+
}
|
|
2037
|
+
interface CurrentTodoSummary {
|
|
2038
|
+
readonly inProgress?: string;
|
|
2039
|
+
readonly pendingCount: number;
|
|
2040
|
+
readonly completedCount: number;
|
|
2041
|
+
}
|
|
2042
|
+
interface SessionMeta {
|
|
2043
|
+
readonly cwd: string;
|
|
2044
|
+
readonly startedAt: number;
|
|
2045
|
+
readonly gitBranch?: string;
|
|
2046
|
+
readonly gitRemote?: string;
|
|
2047
|
+
}
|
|
2048
|
+
/**
|
|
2049
|
+
* Stored shape of `state.json` on disk — additive over SessionStateSnapshot.
|
|
1436
2050
|
*
|
|
1437
|
-
*
|
|
1438
|
-
*
|
|
1439
|
-
*
|
|
2051
|
+
* Reader contract (S2 `instance-discovery.ts`): parse the JSON, verify
|
|
2052
|
+
* `version === '1'` before reading any other field. On an unknown
|
|
2053
|
+
* version, log + skip the instance — this lets a newer writer coexist
|
|
2054
|
+
* with an older reader during an in-place upgrade.
|
|
1440
2055
|
*
|
|
1441
|
-
*
|
|
1442
|
-
*
|
|
1443
|
-
*
|
|
1444
|
-
*
|
|
2056
|
+
* Fields are camelCase + a nested `meta` object (cwd / startedAt /
|
|
2057
|
+
* gitBranch / gitRemote). Do NOT assume the snake_case / flat shape
|
|
2058
|
+
* shown in early design-doc drafts — the typed interface here is the
|
|
2059
|
+
* ground truth; the doc has been updated to match.
|
|
2060
|
+
*/
|
|
2061
|
+
interface PersistedSessionState extends SessionStateSnapshot {
|
|
2062
|
+
readonly version: '1';
|
|
2063
|
+
readonly pid: number;
|
|
2064
|
+
readonly updatedAt: number;
|
|
2065
|
+
readonly meta: SessionMeta;
|
|
2066
|
+
}
|
|
2067
|
+
/** Minimal injectable fs surface — lets tests drive the writer without disk I/O. */
|
|
2068
|
+
interface StateWriterFs {
|
|
2069
|
+
mkdirSync(dirPath: string, options: {
|
|
2070
|
+
recursive: true;
|
|
2071
|
+
}): void;
|
|
2072
|
+
writeFileSync(filePath: string, data: string): void;
|
|
2073
|
+
/** Atomic write helper: writes to `${filePath}.tmp` then renames. */
|
|
2074
|
+
atomicWriteSync(filePath: string, data: string): void;
|
|
2075
|
+
utimesSync(filePath: string, atime: number, mtime: number): void;
|
|
2076
|
+
rmSync(dirPath: string, options: {
|
|
2077
|
+
recursive: true;
|
|
2078
|
+
force: true;
|
|
2079
|
+
}): void;
|
|
2080
|
+
existsSync(targetPath: string): boolean;
|
|
2081
|
+
}
|
|
2082
|
+
interface StateWriterOptions {
|
|
2083
|
+
/** Defaults to `process.pid`. Tests / multi-instance fixtures override. */
|
|
2084
|
+
readonly pid?: number;
|
|
2085
|
+
readonly meta: SessionMeta;
|
|
2086
|
+
readonly initialState: SessionStateSnapshot;
|
|
2087
|
+
/** Defaults to 1000ms. Tests pass a faster tick. */
|
|
2088
|
+
readonly heartbeatIntervalMs?: number;
|
|
2089
|
+
/** Defaults to `Date.now`. Tests inject a controllable clock. */
|
|
2090
|
+
readonly clock?: () => number;
|
|
2091
|
+
/** Defaults to {@link REAL_FS}. Tests inject an in-memory fs. */
|
|
2092
|
+
readonly fs?: StateWriterFs;
|
|
2093
|
+
/**
|
|
2094
|
+
* Root directory under which `<pid>/` is created. Defaults to
|
|
2095
|
+
* `getAgentConfigPath('instances')`. Tests can point at a temp dir.
|
|
2096
|
+
*/
|
|
2097
|
+
readonly instancesRoot?: string;
|
|
2098
|
+
}
|
|
2099
|
+
interface StateWriter {
|
|
2100
|
+
readonly pid: number;
|
|
2101
|
+
readonly instanceDir: string;
|
|
2102
|
+
/** Apply a partial update to the in-memory state and flush to disk. */
|
|
2103
|
+
update(patch: Partial<SessionStateSnapshot>): void;
|
|
2104
|
+
/** Touch the heartbeat and re-write state.json without changing state. */
|
|
2105
|
+
refresh(): void;
|
|
2106
|
+
/** Stop the interval, remove the instance directory, resolve when done. */
|
|
2107
|
+
shutdown(): Promise<void>;
|
|
2108
|
+
/** Read-only snapshot of the current state. Useful for tests. */
|
|
2109
|
+
getState(): SessionStateSnapshot;
|
|
2110
|
+
}
|
|
2111
|
+
/**
|
|
2112
|
+
* Construct a writer, register the instance directory, and start the
|
|
2113
|
+
* heartbeat interval. Returns synchronously so the caller can rely on
|
|
2114
|
+
* `instanceDir` being live the moment the function returns.
|
|
1445
2115
|
*/
|
|
2116
|
+
declare function createStateWriter(options: StateWriterOptions): StateWriter;
|
|
1446
2117
|
|
|
1447
2118
|
/**
|
|
1448
|
-
*
|
|
1449
|
-
* blocks. Preserves message order and structure; never mutates input.
|
|
2119
|
+
* FEATURE_125 (v0.7.41) — Team Mode Layer 2a: sibling instance discovery.
|
|
1450
2120
|
*
|
|
1451
|
-
*
|
|
1452
|
-
*
|
|
1453
|
-
*
|
|
1454
|
-
*
|
|
1455
|
-
*
|
|
1456
|
-
*
|
|
1457
|
-
*
|
|
1458
|
-
*
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
2121
|
+
* Scans `<agentConfigHome>/instances/`, filters out the caller's own
|
|
2122
|
+
* pid, drops any directory whose `heartbeat` file is stale (>30s of no
|
|
2123
|
+
* touch), parses `state.json`, validates `version === '1'`, and returns
|
|
2124
|
+
* a typed list of live sibling instances. Stale directories are
|
|
2125
|
+
* optionally reaped (`reapStale: true`) — the next session entering
|
|
2126
|
+
* Team Mode does the cleanup so crashed processes don't accumulate
|
|
2127
|
+
* forever.
|
|
2128
|
+
*
|
|
2129
|
+
* Per-instance failures (corrupt JSON, vanished file mid-read, permission
|
|
2130
|
+
* error) are isolated: the bad directory is logged + skipped, the rest
|
|
2131
|
+
* of the scan completes. Discovery NEVER throws to its caller — a
|
|
2132
|
+
* Team-Mode-disabled return is `[]`, not an exception. This keeps the
|
|
2133
|
+
* worker LLM call path resilient to one peer session's bad state.
|
|
2134
|
+
*
|
|
2135
|
+
* DI-clean: every fs / clock / logger dependency is injectable so
|
|
2136
|
+
* hermetic tests can simulate stale / corrupt / mid-scan-deletion
|
|
2137
|
+
* scenarios without real disk.
|
|
1461
2138
|
*/
|
|
1462
|
-
|
|
2139
|
+
|
|
2140
|
+
/** A sibling KodaX session that passed stale + version-guard checks. */
|
|
2141
|
+
interface DiscoveredInstance {
|
|
2142
|
+
readonly pid: number;
|
|
2143
|
+
readonly state: PersistedSessionState;
|
|
2144
|
+
/** Heartbeat mtime in ms (epoch). Useful for ordering "freshest first". */
|
|
2145
|
+
readonly heartbeatMtimeMs: number;
|
|
2146
|
+
}
|
|
2147
|
+
/** Minimal injectable fs surface used by `discoverInstances`. */
|
|
2148
|
+
interface InstanceDiscoveryFs {
|
|
2149
|
+
existsSync(targetPath: string): boolean;
|
|
2150
|
+
readdirSync(dirPath: string): string[];
|
|
2151
|
+
/** Returns the mtime of the path in ms, or `null` if missing / unreadable. */
|
|
2152
|
+
statMtimeMs(filePath: string): number | null;
|
|
2153
|
+
readFileSync(filePath: string, encoding: 'utf8'): string;
|
|
2154
|
+
rmSync(dirPath: string, options: {
|
|
2155
|
+
recursive: true;
|
|
2156
|
+
force: true;
|
|
2157
|
+
}): void;
|
|
2158
|
+
}
|
|
2159
|
+
interface DiscoveryOptions {
|
|
2160
|
+
/**
|
|
2161
|
+
* pid to exclude from the result. Defaults to `process.pid` — the
|
|
2162
|
+
* caller's own state.json should not appear in its own sibling list.
|
|
2163
|
+
*/
|
|
2164
|
+
readonly excludePid?: number;
|
|
2165
|
+
/**
|
|
2166
|
+
* Heartbeat mtime older than `now - staleThresholdMs` → directory is
|
|
2167
|
+
* stale. Default 30_000 (matches v0.7.41 spec).
|
|
2168
|
+
*/
|
|
2169
|
+
readonly staleThresholdMs?: number;
|
|
2170
|
+
/**
|
|
2171
|
+
* When true, stale directories are removed during the scan (best-
|
|
2172
|
+
* effort `rmSync(force:true)`; failure is swallowed). When false,
|
|
2173
|
+
* stale directories are skipped but left on disk. Defaults to false
|
|
2174
|
+
* — wire from the session-startup path with `true` so crashed-process
|
|
2175
|
+
* dirs don't accumulate.
|
|
2176
|
+
*/
|
|
2177
|
+
readonly reapStale?: boolean;
|
|
2178
|
+
readonly clock?: () => number;
|
|
2179
|
+
readonly fs?: InstanceDiscoveryFs;
|
|
2180
|
+
readonly instancesRoot?: string;
|
|
2181
|
+
/** Per-instance failure log; defaults to a no-op. Pass `console.warn` in dev. */
|
|
2182
|
+
readonly logger?: (message: string) => void;
|
|
2183
|
+
}
|
|
1463
2184
|
/**
|
|
1464
|
-
*
|
|
2185
|
+
* Synchronous discovery scan. Returns a freshness-sorted array
|
|
2186
|
+
* (newest heartbeat first) so callers that want only the N most-recent
|
|
2187
|
+
* siblings can slice without re-sorting.
|
|
1465
2188
|
*
|
|
1466
|
-
*
|
|
1467
|
-
*
|
|
1468
|
-
*
|
|
1469
|
-
|
|
1470
|
-
|
|
2189
|
+
* Never throws. A missing `<instancesRoot>` directory means the user
|
|
2190
|
+
* is the first session ever on this machine → `[]`. A scan failure on
|
|
2191
|
+
* one entry is logged + skipped, not propagated.
|
|
2192
|
+
*/
|
|
2193
|
+
declare function discoverInstances(options?: DiscoveryOptions): DiscoveredInstance[];
|
|
2194
|
+
|
|
2195
|
+
/**
|
|
2196
|
+
* ../../index.js Compaction Types
|
|
1471
2197
|
*/
|
|
1472
|
-
declare function cleanupIncompleteToolCalls(messages: KodaXMessage[]): KodaXMessage[];
|
|
1473
2198
|
|
|
1474
|
-
|
|
1475
|
-
|
|
2199
|
+
interface CompactionConfig {
|
|
2200
|
+
/** Whether automatic compaction is enabled. */
|
|
2201
|
+
enabled: boolean;
|
|
2202
|
+
/** Trigger compaction when context usage exceeds this percentage of the window. */
|
|
2203
|
+
triggerPercent: number;
|
|
2204
|
+
/**
|
|
2205
|
+
* @deprecated V2 compaction no longer uses this option.
|
|
2206
|
+
*
|
|
2207
|
+
* The system now combines protected recent context, lightweight pruning, and
|
|
2208
|
+
* rolling summaries automatically.
|
|
2209
|
+
*/
|
|
2210
|
+
keepRecentPercent?: number;
|
|
2211
|
+
/** Percentage of the most recent context that is never compacted or pruned. Defaults to 20. */
|
|
2212
|
+
protectionPercent?: number;
|
|
2213
|
+
/**
|
|
2214
|
+
* Percentage of the context window used as the chunk size for each rolling
|
|
2215
|
+
* summary pass. Defaults to 10.
|
|
2216
|
+
*/
|
|
2217
|
+
rollingSummaryPercent?: number;
|
|
2218
|
+
/** Prune oversized tool results when they exceed roughly this many tokens. Defaults to 500. */
|
|
2219
|
+
pruningThresholdTokens?: number;
|
|
2220
|
+
/**
|
|
2221
|
+
* Gap ratio for prune fast-return. After pruning, if remaining tokens still exceed
|
|
2222
|
+
* triggerTokens * pruningGapRatio, the system continues to the summarization path
|
|
2223
|
+
* instead of returning early. Defaults to 0.8.
|
|
2224
|
+
*/
|
|
2225
|
+
pruningGapRatio?: number;
|
|
2226
|
+
/** Optional override for the provider context window. */
|
|
2227
|
+
contextWindow?: number;
|
|
2228
|
+
}
|
|
2229
|
+
interface CompactionDetails {
|
|
2230
|
+
readFiles: string[];
|
|
2231
|
+
modifiedFiles: string[];
|
|
2232
|
+
}
|
|
2233
|
+
interface CompactionAnchor {
|
|
2234
|
+
summary: string;
|
|
2235
|
+
tokensBefore: number;
|
|
2236
|
+
tokensAfter: number;
|
|
2237
|
+
entriesRemoved: number;
|
|
2238
|
+
reason: string;
|
|
2239
|
+
artifactLedgerId?: string;
|
|
2240
|
+
details?: CompactionDetails;
|
|
2241
|
+
memorySeed?: KodaXCompactMemorySeed;
|
|
2242
|
+
}
|
|
2243
|
+
interface CompactionUpdate {
|
|
2244
|
+
anchor?: CompactionAnchor;
|
|
2245
|
+
artifactLedger?: KodaXSessionArtifactLedgerEntry[];
|
|
2246
|
+
memorySeed?: KodaXCompactMemorySeed;
|
|
2247
|
+
/**
|
|
2248
|
+
* FEATURE_072: ledger-summary + file-content messages produced by
|
|
2249
|
+
* `buildPostCompactAttachments` + `buildFileContentMessages`. Agent.ts
|
|
2250
|
+
* passes these separately from the kept-tail messages so REPL-side
|
|
2251
|
+
* `applySessionCompaction` can store them natively on the CompactionEntry
|
|
2252
|
+
* rather than inlining them as loose `[Post-compact: ...]` system messages
|
|
2253
|
+
* in lineage. Agent.ts keeps inlining them into its local flat `messages`
|
|
2254
|
+
* via `injectPostCompactAttachments` (P4 belt-and-suspenders); the lineage
|
|
2255
|
+
* is the persistence source of truth.
|
|
2256
|
+
*/
|
|
2257
|
+
postCompactAttachments?: readonly KodaXMessage[];
|
|
2258
|
+
}
|
|
2259
|
+
interface CompactionResult {
|
|
2260
|
+
compacted: boolean;
|
|
2261
|
+
messages: KodaXMessage[];
|
|
2262
|
+
summary?: string;
|
|
2263
|
+
tokensBefore: number;
|
|
2264
|
+
tokensAfter: number;
|
|
2265
|
+
entriesRemoved: number;
|
|
2266
|
+
details?: CompactionDetails;
|
|
2267
|
+
artifactLedger?: KodaXSessionArtifactLedgerEntry[];
|
|
2268
|
+
anchor?: CompactionAnchor;
|
|
2269
|
+
memorySeed?: KodaXCompactMemorySeed;
|
|
2270
|
+
}
|
|
2271
|
+
interface FileOperations {
|
|
2272
|
+
readFiles: string[];
|
|
2273
|
+
modifiedFiles: string[];
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
export { DEFAULT_SYSTEM_CAP as D, InvariantSession as O, MAX_TOOL_LOOP_ITERATIONS as P, getAdmittedAgentBindings as a$, Runner as a6, Tracer as aI, _resetAdmittedAgentBindings as aK, _resetPresetDispatchers as aL, buildAssistantMessageFromLlmResult as aM, buildSystemPrompt as aN, buildToolResultMessage as aO, collectGuardrails as aP, createAgent as aQ, createHandoff as aR, createInMemorySession as aS, createInvariantSessionForAgent as aT, createStateWriter as aU, createTrace as aV, defaultTracer as aW, detectInstructionsInjection as aX, discoverInstances as aY, executeRunnerToolCall as aZ, extractAssistantTextFromMessage as a_, SpanImpl as ao, isRunnableTool as b0, isRunnerLlmResult as b1, registerChildTask as b2, registerPresetDispatcher as b3, requestTaskStop as b4, runAdmissionAudit as b5, runInputGuardrails as b6, runOutputGuardrails as b7, runToolAfterGuardrails as b8, runToolBeforeGuardrails as b9, setAdmittedAgentBindings as ba, GuardrailBlockedError as w, GuardrailEscalateError as y };
|
|
2277
|
+
export type { RecentlyModifiedFile as $, AdmissionAuditOptions as A, GuardrailVerdict as B, ChildTaskRegistry as C, EvidenceSpanData as E, FanoutSpanData as F, GenerationSpanData as G, Handoff as H, HandoffSpanData as I, InMemorySessionOptions as J, InputGuardrail as K, InstanceDiscoveryFs as L, InvariantId as M, InvariantResult as N, ManifestPatch as Q, MessageEntry as R, ObserveCtx as S, OutputGuardrail as T, PersistedSessionState as U, PresetDispatcher as V, PresetTracingContext as W, QualityInvariant as X, ReadonlyMutationTracker as Y, ReadonlyRecorder as Z, ReasoningDepth as _, AdmissionCtx as a, RequestTaskStopOptions as a0, RequestTaskStopResult as a1, RunEvent as a2, RunOptions as a3, RunResult as a4, RunnableTool as a5, RunnerEvent as a7, RunnerLlmResult as a8, RunnerLlmReturn as a9, TerminalCtx as aA, ToolBeforeOutcome as aB, ToolCallSpanData as aC, ToolCapability as aD, ToolGuardrail as aE, ToolPermission as aF, Trace as aG, TraceOptions as aH, TracerOptions as aJ, RunnerToolCall as aa, RunnerToolContext as ab, RunnerToolObserver as ac, RunnerToolResult as ad, Session as ae, SessionDispatchResult as af, SessionEntry as ag, SessionExtension as ah, SessionForkOptions as ai, SessionMeta as aj, SessionStateSnapshot as ak, Span as al, SpanData as am, SpanError as an, SpanImplOptions as ap, StartTraceOptions as aq, StateWriter as ar, StateWriterFs as as, StateWriterOptions as at, StopHookContext as au, StopHookFn as av, StopHookResult as aw, StopHookSpanData as ax, SystemCap as ay, TaskAbortRegistry as az, AdmissionVerdict as b, AdmittedHandle as c, Agent as d, AgentManifest as e, AgentMessage as f, AgentMiddlewareDeclaration as g, AgentReasoningProfile as h, AgentSpanData as i, AgentTool as j, CompactionAnchor as k, CompactionConfig as l, CompactionDetails as m, CompactionResult as n, CompactionSpanData as o, CompactionUpdate as p, CurrentTodoSummary as q, Deliverable as r, DiscoveredInstance as s, DiscoveryOptions as t, FileOperations as u, Guardrail as v, GuardrailContext as x, GuardrailSpanData as z };
|