@kodax-ai/kodax 0.7.39 → 0.7.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/README.md +58 -0
- package/README_CN.md +31 -0
- package/dist/chunks/{chunk-SF7WD7E5.js → chunk-5TFLMGER.js} +1 -1
- package/dist/chunks/{chunk-HUAU4KB3.js → chunk-6OB4AJOM.js} +1 -1
- package/dist/chunks/chunk-6QO6HWGU.js +30 -0
- package/dist/chunks/{chunk-SONW6AC7.js → chunk-EQ5DGS2W.js} +1 -1
- package/dist/chunks/chunk-EVIDQWMF.js +5 -0
- package/dist/chunks/chunk-HYWVRTFA.js +1233 -0
- package/dist/chunks/chunk-SX2IS5JP.js +16 -0
- package/dist/chunks/chunk-V4WSBIXB.js +2 -0
- package/dist/chunks/chunk-ZPJPNLBK.js +462 -0
- package/dist/chunks/compaction-config-LT5PEXPT.js +2 -0
- package/dist/chunks/{construction-bootstrap-XSE7ZABG.js → construction-bootstrap-HBCWJFHC.js} +1 -1
- package/dist/chunks/{devtools-MOFU7YQF.js → devtools-EYGFOXEU.js} +1 -1
- package/dist/chunks/{dist-WKW4CBG6.js → dist-M57GIWR4.js} +1 -1
- package/dist/chunks/dist-V3BS2NKB.js +2 -0
- package/dist/chunks/paste-5DSTHQGK.js +2 -0
- package/dist/chunks/{utils-3HW4KOGE.js → utils-FAFUQJ2A.js} +1 -1
- package/dist/index.d.ts +232 -7
- package/dist/index.js +2 -2
- package/dist/kodax_cli.js +945 -923
- package/dist/sdk-agent.d.ts +1459 -10
- package/dist/sdk-agent.js +1 -1
- package/dist/sdk-coding.d.ts +4543 -14
- package/dist/sdk-coding.js +1 -1
- package/dist/sdk-llm.d.ts +209 -10
- package/dist/sdk-llm.js +1 -1
- package/dist/sdk-repl.d.ts +2694 -13
- package/dist/sdk-repl.js +1 -1
- package/dist/sdk-skills.d.ts +487 -11
- package/dist/sdk-skills.js +1 -1
- package/dist/types-chunks/bash-prefix-extractor.d-B2iliwdi.d.ts +2432 -0
- package/dist/types-chunks/capability.d-BxNgd1-c.d.ts +368 -0
- package/dist/types-chunks/cost-tracker.d-C4dMlQuV.d.ts +342 -0
- package/dist/types-chunks/history-cleanup.d-q1vAvCss.d.ts +1266 -0
- package/dist/types-chunks/instance-discovery.d-DZhp77vb.d.ts +1217 -0
- package/dist/types-chunks/resolver.d-BwD6TKz7.d.ts +262 -0
- package/dist/types-chunks/storage.d-Bv9T99Qu.d.ts +584 -0
- package/dist/types-chunks/types.d-C5mHR87z.d.ts +119 -0
- package/package.json +8 -2
- package/dist/acp_events.d.ts +0 -109
- package/dist/acp_logger.d.ts +0 -20
- package/dist/acp_server.d.ts +0 -92
- package/dist/chunks/chunk-4E76FLZ3.js +0 -2
- package/dist/chunks/chunk-7LQ2NCHF.js +0 -1221
- package/dist/chunks/chunk-N2VZ2MJF.js +0 -11
- package/dist/chunks/chunk-WEEQZYZS.js +0 -460
- package/dist/chunks/chunk-XI75LZIO.js +0 -30
- package/dist/chunks/compaction-config-YL4SWWII.js +0 -2
- package/dist/chunks/dist-AMUYI7R5.js +0 -2
- package/dist/cli_commands.d.ts +0 -17
- package/dist/cli_option_helpers.d.ts +0 -49
- package/dist/cli_option_helpers.test.d.ts +0 -1
- package/dist/constructed_cli.d.ts +0 -82
- package/dist/constructed_cli.test.d.ts +0 -1
- package/dist/kodax_cli.d.ts +0 -7
- package/dist/self_modify_cli.d.ts +0 -81
- package/dist/self_modify_cli.test.d.ts +0 -9
- package/dist/skill_cli.d.ts +0 -15
- package/dist/skill_cli.test.d.ts +0 -1
|
@@ -0,0 +1,1266 @@
|
|
|
1
|
+
import { o as KodaXMessage } from './capability.d-BxNgd1-c.js';
|
|
2
|
+
import { a as AgentMessage, a7 as SpanData, a6 as Span, a8 as SpanError, A as Agent, _ as RunnerLlmReturn, G as Guardrail, a1 as RunnerToolObserver } from './instance-discovery.d-DZhp77vb.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @kodax-ai/agent Constants
|
|
6
|
+
*
|
|
7
|
+
* 通用 Agent 常量配置
|
|
8
|
+
*/
|
|
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
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @kodax-ai/agent Tokenizer
|
|
22
|
+
*
|
|
23
|
+
* Token 估算 - 使用 tiktoken 进行精确计算
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 估算消息的 token 数量
|
|
28
|
+
*
|
|
29
|
+
* 精确计算包括:
|
|
30
|
+
* - 消息结构开销(每条约 4 tokens)
|
|
31
|
+
* - 角色标识
|
|
32
|
+
* - 内容文本
|
|
33
|
+
* - 工具调用和结果
|
|
34
|
+
*/
|
|
35
|
+
declare function estimateTokens(messages: KodaXMessage[]): number;
|
|
36
|
+
/**
|
|
37
|
+
* 计算单个文本的 token 数量(便捷函数)
|
|
38
|
+
*/
|
|
39
|
+
declare function countTokens(text: string): number;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Layer A Primitive: Session / SessionEntry / MessageEntry / SessionExtension
|
|
43
|
+
*
|
|
44
|
+
* FEATURE_081 (v0.7.23): Base Session shape. The thick
|
|
45
|
+
* `KodaXSessionLineage` lives in `@kodax-ai/session-lineage` and is re-expressed
|
|
46
|
+
* as a `LineageExtension` over this base.
|
|
47
|
+
*
|
|
48
|
+
* History: extracted to `@kodax-ai/core` in FEATURE_082 (v0.7.24); merged back
|
|
49
|
+
* into `@kodax-ai/agent` in v0.7.35.1 FEATURE_142. `@kodax-ai/coding` retains a
|
|
50
|
+
* barrel re-export for batteries-included consumers.
|
|
51
|
+
*
|
|
52
|
+
* Status: @experimental — API shape may be refined during v0.7.x.
|
|
53
|
+
*
|
|
54
|
+
* Design intent:
|
|
55
|
+
* - Base Session is a minimal, linearly-appendable log of typed entries.
|
|
56
|
+
* - Extensions (lineage, artifacts, labels, compaction) layer on top by
|
|
57
|
+
* claiming additional `entry.type` values and contributing operators /
|
|
58
|
+
* reducers that read the entry stream.
|
|
59
|
+
* - coding preset composes LineageExtension + CompactionExtension +
|
|
60
|
+
* ArtifactExtension to reproduce today's `KodaXSessionLineage` behavior.
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A single immutable entry in a Session log. `type` is the dispatch key used
|
|
65
|
+
* by extensions to claim ownership of an entry kind.
|
|
66
|
+
*/
|
|
67
|
+
interface SessionEntry {
|
|
68
|
+
readonly id: string;
|
|
69
|
+
readonly ts: number;
|
|
70
|
+
readonly type: string;
|
|
71
|
+
readonly payload: unknown;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Canonical message entry type. All Layer A consumers can rely on
|
|
75
|
+
* `type: 'message'` entries existing; extensions add more types.
|
|
76
|
+
*/
|
|
77
|
+
interface MessageEntry extends SessionEntry {
|
|
78
|
+
readonly type: 'message';
|
|
79
|
+
readonly payload: {
|
|
80
|
+
readonly role: AgentMessage['role'];
|
|
81
|
+
readonly content: AgentMessage['content'];
|
|
82
|
+
readonly synthetic?: boolean;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Options for forking a session.
|
|
87
|
+
*
|
|
88
|
+
* v0.7.23 exposes only `name` (label for the new fork); structural options
|
|
89
|
+
* (branch-at-entry, shallow copy, etc.) are reserved for later versions.
|
|
90
|
+
*/
|
|
91
|
+
interface SessionForkOptions {
|
|
92
|
+
readonly name?: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Minimal Session interface.
|
|
96
|
+
*
|
|
97
|
+
* Implementations must guarantee:
|
|
98
|
+
* - `append()` is atomic: either the entry is visible on next `entries()`
|
|
99
|
+
* iteration or it throws.
|
|
100
|
+
* - `entries()` yields entries in append order.
|
|
101
|
+
* - `metadata` is a readonly snapshot; mutations are made via extensions.
|
|
102
|
+
* - `fork()` returns a new Session with a snapshot of current entries; the
|
|
103
|
+
* two sessions diverge thereafter.
|
|
104
|
+
*/
|
|
105
|
+
interface Session {
|
|
106
|
+
readonly id: string;
|
|
107
|
+
append(entry: SessionEntry): Promise<void>;
|
|
108
|
+
entries(): AsyncIterable<SessionEntry>;
|
|
109
|
+
fork(opts?: SessionForkOptions): Promise<Session>;
|
|
110
|
+
readonly metadata: ReadonlyMap<string, unknown>;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Extension contract for teaching a Session new entry types + operators +
|
|
114
|
+
* reducers.
|
|
115
|
+
*
|
|
116
|
+
* - `entryTypes`: which `entry.type` values this extension owns. Two
|
|
117
|
+
* extensions composed into one Session must not claim overlapping types.
|
|
118
|
+
* - `operators`: high-level imperative verbs exposed to callers (e.g.
|
|
119
|
+
* `branch`, `rewind`, `attachArtifact`).
|
|
120
|
+
* - `reducers`: pure projections over the entry stream (e.g. "build lineage
|
|
121
|
+
* tree").
|
|
122
|
+
*
|
|
123
|
+
* The exact dispatch mechanics (`ExtendedSession<T>` typing, operator
|
|
124
|
+
* registration) land with the coding preset integration; v0.7.23 pins the
|
|
125
|
+
* shape only.
|
|
126
|
+
*/
|
|
127
|
+
interface SessionExtension {
|
|
128
|
+
readonly name: string;
|
|
129
|
+
readonly entryTypes: readonly string[];
|
|
130
|
+
readonly operators?: Readonly<Record<string, (session: Session, ...args: readonly unknown[]) => Promise<unknown>>>;
|
|
131
|
+
readonly reducers?: Readonly<Record<string, (entries: readonly SessionEntry[]) => unknown>>;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Options for `createInMemorySession`.
|
|
135
|
+
*/
|
|
136
|
+
interface InMemorySessionOptions {
|
|
137
|
+
readonly id?: string;
|
|
138
|
+
readonly metadata?: ReadonlyMap<string, unknown>;
|
|
139
|
+
readonly initialEntries?: readonly SessionEntry[];
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* In-memory Session suitable for tests, examples, and embedded SDK use. Not
|
|
143
|
+
* durable across process restarts — persistence is provided by coding-specific
|
|
144
|
+
* adapters in `@kodax-ai/session-lineage` and `@kodax-ai/agent`.
|
|
145
|
+
*/
|
|
146
|
+
declare function createInMemorySession(opts?: InMemorySessionOptions): Session;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Layer A Primitive: CompactionPolicy + DefaultSummaryCompaction
|
|
150
|
+
*
|
|
151
|
+
* FEATURE_081 (v0.7.23): Pluggable compaction for generic agent loops.
|
|
152
|
+
*
|
|
153
|
+
* Two layers:
|
|
154
|
+
* - Layer A (here): `CompactionPolicy` interface + `DefaultSummaryCompaction`
|
|
155
|
+
* — a minimal "token threshold → LLM summary of old messages" policy that
|
|
156
|
+
* any external Agent can pick up with zero KodaX runtime dependency.
|
|
157
|
+
* - Layer B (`@kodax-ai/session-lineage/src/lineage.ts`): `LineageCompaction`
|
|
158
|
+
* wraps the full FEATURE_072 lineage-native compaction for the coding
|
|
159
|
+
* preset.
|
|
160
|
+
*
|
|
161
|
+
* The `compaction` entry shape written by `DefaultSummaryCompaction` is the
|
|
162
|
+
* same type used by `LineageExtension`, so the two layers interoperate on
|
|
163
|
+
* the same Session log.
|
|
164
|
+
*
|
|
165
|
+
* History: extracted to `@kodax-ai/core` in FEATURE_082 (v0.7.24); merged back
|
|
166
|
+
* into `@kodax-ai/agent` in v0.7.35.1 FEATURE_142.
|
|
167
|
+
*/
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Runtime context for a compaction pass. Abstracts the LLM/tokenizer
|
|
171
|
+
* dependencies so policies stay independent of any specific provider.
|
|
172
|
+
*/
|
|
173
|
+
interface CompactionContext {
|
|
174
|
+
readonly tokensUsed: number;
|
|
175
|
+
readonly budget: number;
|
|
176
|
+
/**
|
|
177
|
+
* Summarizer implementation. Callers inject a function that maps a list of
|
|
178
|
+
* messages to a short summary string. In coding-preset mode this is wired
|
|
179
|
+
* to `runKodaX` internally; for external consumers it can call any LLM.
|
|
180
|
+
*/
|
|
181
|
+
readonly summarize: (messages: readonly AgentMessage[]) => Promise<string>;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Payload written to the `compaction` entry appended by `compact()`.
|
|
185
|
+
*/
|
|
186
|
+
interface CompactionEntryPayload {
|
|
187
|
+
readonly summary: string;
|
|
188
|
+
readonly replacedMessageEntryIds: readonly string[];
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Typed compaction entry. `type` is `'compaction'`; extensions (LineageExtension)
|
|
192
|
+
* may claim this same type.
|
|
193
|
+
*/
|
|
194
|
+
interface CompactionEntry extends SessionEntry {
|
|
195
|
+
readonly type: 'compaction';
|
|
196
|
+
readonly payload: CompactionEntryPayload;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Outcome of a single CompactionPolicy.compact() pass. Renamed from
|
|
200
|
+
* `CompactionResult` to `PolicyCompactionResult` in v0.7.35.1 FEATURE_142
|
|
201
|
+
* because the Layer A primitive collided with @kodax-ai/agent's pre-existing
|
|
202
|
+
* `CompactionResult` (compaction/types.ts) used by the coding orchestration
|
|
203
|
+
* post-compact pipeline. The two types model different things:
|
|
204
|
+
* - `PolicyCompactionResult` (here): "summary + replaced entry ids", the
|
|
205
|
+
* payload of one CompactionPolicy step.
|
|
206
|
+
* - `CompactionResult` (compaction/types.ts): the rich result of the
|
|
207
|
+
* coding-side multi-pass compaction (artifactLedger / memorySeed /
|
|
208
|
+
* tokensBefore / tokensAfter / etc).
|
|
209
|
+
*/
|
|
210
|
+
interface PolicyCompactionResult {
|
|
211
|
+
readonly summary: string;
|
|
212
|
+
readonly replacedMessageEntryIds: readonly string[];
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Pluggable compaction policy. Any multi-turn Agent loop can check
|
|
216
|
+
* `shouldCompact()` at round boundaries and call `compact()` when it returns
|
|
217
|
+
* true.
|
|
218
|
+
*/
|
|
219
|
+
interface CompactionPolicy {
|
|
220
|
+
readonly name: string;
|
|
221
|
+
shouldCompact(session: Session, tokensUsed: number, budget: number): boolean;
|
|
222
|
+
compact(session: Session, ctx: CompactionContext): Promise<PolicyCompactionResult>;
|
|
223
|
+
/** Optional: rehydrate compacted content when a restore hint is available. */
|
|
224
|
+
restore?(session: Session, hint: unknown): Promise<void>;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Configuration for `DefaultSummaryCompaction`.
|
|
228
|
+
*/
|
|
229
|
+
interface DefaultSummaryCompactionOptions {
|
|
230
|
+
/**
|
|
231
|
+
* Fraction of `budget` at which compaction triggers. Default 0.8 (i.e.
|
|
232
|
+
* 80% of the token budget). Must be in (0, 1].
|
|
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
|
+
*/
|
|
243
|
+
readonly now?: () => number;
|
|
244
|
+
/**
|
|
245
|
+
* Optional random-string override. Useful for deterministic tests.
|
|
246
|
+
*/
|
|
247
|
+
readonly randomSuffix?: () => string;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Minimal "token threshold + LLM summary" compaction policy. Works on any
|
|
251
|
+
* Session that stores `message` entries.
|
|
252
|
+
*
|
|
253
|
+
* Behavior:
|
|
254
|
+
* - `shouldCompact` returns true when `tokensUsed >= budget *
|
|
255
|
+
* thresholdRatio`.
|
|
256
|
+
* - `compact` reads all `message` entries, keeps the last `keepRecent`
|
|
257
|
+
* untouched, summarizes the rest via `ctx.summarize`, and appends a
|
|
258
|
+
* single `compaction` entry to the session.
|
|
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;
|
|
267
|
+
private readonly now;
|
|
268
|
+
private readonly randomSuffix;
|
|
269
|
+
constructor(opts?: DefaultSummaryCompactionOptions);
|
|
270
|
+
shouldCompact(_session: Session, tokensUsed: number, budget: number): boolean;
|
|
271
|
+
compact(session: Session, ctx: CompactionContext): Promise<PolicyCompactionResult>;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Trace — the root container for a single user-visible workflow.
|
|
276
|
+
*
|
|
277
|
+
* FEATURE_083 (v0.7.24): a Trace wraps a root span and all its descendants.
|
|
278
|
+
* The Runner.run(agent, ...) entry creates a trace per run by default;
|
|
279
|
+
* consumers can nest runs under an existing trace via `Runner.run(agent, input, { trace })`.
|
|
280
|
+
*/
|
|
281
|
+
|
|
282
|
+
interface Trace {
|
|
283
|
+
readonly id: string;
|
|
284
|
+
readonly startedAt: number;
|
|
285
|
+
readonly rootSpan: Span;
|
|
286
|
+
readonly metadata: ReadonlyMap<string, unknown>;
|
|
287
|
+
end(): void;
|
|
288
|
+
readonly endedAt?: number;
|
|
289
|
+
readonly error?: SpanError;
|
|
290
|
+
}
|
|
291
|
+
interface TraceOptions {
|
|
292
|
+
readonly id?: string;
|
|
293
|
+
readonly name?: string;
|
|
294
|
+
readonly rootSpanData?: SpanData;
|
|
295
|
+
readonly metadata?: ReadonlyMap<string, unknown>;
|
|
296
|
+
readonly now?: () => number;
|
|
297
|
+
readonly nextSpanId?: () => string;
|
|
298
|
+
readonly nextTraceId?: () => string;
|
|
299
|
+
readonly onSpanStart?: (span: Span) => void;
|
|
300
|
+
readonly onSpanEnd?: (span: Span) => void;
|
|
301
|
+
readonly onTraceEnd?: (trace: Trace) => void;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Tracer — convenience façade that creates Traces wired to the registered
|
|
306
|
+
* processors and default id generators.
|
|
307
|
+
*
|
|
308
|
+
* FEATURE_083 (v0.7.24): callers typically use the default tracer:
|
|
309
|
+
*
|
|
310
|
+
* const trace = defaultTracer.startTrace({ name: 'coding-run' });
|
|
311
|
+
* const child = trace.rootSpan.addChild('generation', { kind: 'generation', ... });
|
|
312
|
+
* // ... do work ...
|
|
313
|
+
* child.end();
|
|
314
|
+
* trace.end();
|
|
315
|
+
*
|
|
316
|
+
* Advanced callers can inject a custom clock / id generator for
|
|
317
|
+
* deterministic tests.
|
|
318
|
+
*/
|
|
319
|
+
|
|
320
|
+
interface StartTraceOptions {
|
|
321
|
+
readonly id?: string;
|
|
322
|
+
readonly name?: string;
|
|
323
|
+
readonly rootSpanData?: TraceOptions['rootSpanData'];
|
|
324
|
+
readonly metadata?: ReadonlyMap<string, unknown>;
|
|
325
|
+
}
|
|
326
|
+
interface TracerOptions {
|
|
327
|
+
readonly now?: () => number;
|
|
328
|
+
readonly nextSpanId?: () => string;
|
|
329
|
+
readonly nextTraceId?: () => string;
|
|
330
|
+
}
|
|
331
|
+
declare class Tracer {
|
|
332
|
+
private readonly options;
|
|
333
|
+
constructor(options?: TracerOptions);
|
|
334
|
+
startTrace(opts?: StartTraceOptions): Trace;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Layer A Primitive: Quality Invariant + Admission Contract types.
|
|
339
|
+
*
|
|
340
|
+
* FEATURE_101 (v0.7.31) — types-only module. Runner.admit() runtime lives
|
|
341
|
+
* in `./runner.ts`; the seven (+1 external) invariant implementations live
|
|
342
|
+
* in `@kodax-ai/coding/src/agent-runtime/invariants/`.
|
|
343
|
+
*
|
|
344
|
+
* Why types-only here: the admission contract is a Layer A primitive that
|
|
345
|
+
* @kodax-ai/coding consumes — putting it in @kodax-ai/core keeps SDK consumers
|
|
346
|
+
* from pulling in coding-specific imports just to reference admission
|
|
347
|
+
* types. The actual invariant implementations need access to mutation
|
|
348
|
+
* trackers, budget controllers, and ToolGuardrail capability tiers — all
|
|
349
|
+
* of which live in @kodax-ai/coding — so they belong there.
|
|
350
|
+
*
|
|
351
|
+
* Status: @experimental. v0.7.31 ships these types alongside the FEATURE_089
|
|
352
|
+
* agent-generation consumer; once dispatch eval baseline (FEATURE_101
|
|
353
|
+
* Phase 3) stabilizes the schema we promote to ADR-021.
|
|
354
|
+
*
|
|
355
|
+
* See:
|
|
356
|
+
* - docs/features/v0.7.31.md#feature_101-constructed-agent-admission-contract
|
|
357
|
+
* - docs/features/v0.7.31.md#feature_106-ama-harness-selection-calibration
|
|
358
|
+
* (FEATURE_106 registers the 8th invariant 'harnessSelectionTiming' —
|
|
359
|
+
* external to admission v1 closed set but uses the same runtime)
|
|
360
|
+
*/
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Untrusted Agent declaration submitted by an LLM-driven generator
|
|
364
|
+
* (FEATURE_089) or any other consumer that wants the manifest verified
|
|
365
|
+
* by the admission contract before activation.
|
|
366
|
+
*
|
|
367
|
+
* Structurally `Agent` plus three manifest-only optional fields the LLM
|
|
368
|
+
* may declare to express intent (per FEATURE_101 §Manifest schema):
|
|
369
|
+
*
|
|
370
|
+
* - `requestedToolCapabilities`: "I plan to use bash:test, not bash:network"
|
|
371
|
+
* Admission intersects with the resolved capability set from `tools`.
|
|
372
|
+
* - `maxBudget`: "Cap my total turn budget at N" — admission clamps to
|
|
373
|
+
* `system_cap.maxBudget`; runtime further clamps to parent.remaining.
|
|
374
|
+
* - `declaredInvariants`: extra invariants the LLM voluntarily binds.
|
|
375
|
+
* The required set (resolved from role / toolScope / harnessTier) is
|
|
376
|
+
* ALWAYS a floor — declaredInvariants can only ADD.
|
|
377
|
+
*
|
|
378
|
+
* `Runner.admit(manifest)` reads as "this manifest has not been admitted
|
|
379
|
+
* yet" while `Runner.run(agent, ...)` reads as "this Agent is trusted
|
|
380
|
+
* to execute".
|
|
381
|
+
*/
|
|
382
|
+
type AgentManifest = Agent & {
|
|
383
|
+
readonly requestedToolCapabilities?: readonly ToolPermission[];
|
|
384
|
+
readonly maxBudget?: number;
|
|
385
|
+
/**
|
|
386
|
+
* Tool-loop iteration ceiling the manifest commits to. Admission
|
|
387
|
+
* clamps to `system_cap.maxIterations` via `clampMaxIterations` patch;
|
|
388
|
+
* Runner.run reads the post-clamp value through `getAdmittedAgentBindings`
|
|
389
|
+
* and takes min-wins against `RunOptions.maxToolLoopIterations`. Symmetric
|
|
390
|
+
* with `maxBudget` — both are activation caps, both flow through the
|
|
391
|
+
* patch reducer, both consulted at runtime via the WeakMap binding.
|
|
392
|
+
*/
|
|
393
|
+
readonly maxIterations?: number;
|
|
394
|
+
readonly declaredInvariants?: readonly InvariantId[];
|
|
395
|
+
};
|
|
396
|
+
/**
|
|
397
|
+
* Coarse-grained capability classes that group concrete tools by their
|
|
398
|
+
* observable side effects. Replaces the v0.7.30 `ToolName[]` allow-list
|
|
399
|
+
* with semantic categories so admission can reason about "this manifest
|
|
400
|
+
* wants bash:network capability" without enumerating every concrete tool.
|
|
401
|
+
*
|
|
402
|
+
* Aligned with FEATURE_092 (Auto Mode Classifier, v0.7.33) and FEATURE_094
|
|
403
|
+
* (anti-escape, v0.7.36) which both classify tools along these axes.
|
|
404
|
+
*/
|
|
405
|
+
type ToolCapability = 'read' | 'edit' | 'bash:test' | 'bash:read-only' | 'bash:mutating' | 'bash:network' | 'subagent';
|
|
406
|
+
/**
|
|
407
|
+
* Per-tool capability declaration. Used in `AgentManifest.requestedToolCapabilities`
|
|
408
|
+
* (an optional field manifests can declare to express intent — admission
|
|
409
|
+
* intersects with the resolved capability set).
|
|
410
|
+
*/
|
|
411
|
+
interface ToolPermission {
|
|
412
|
+
readonly tool: string;
|
|
413
|
+
readonly capabilities: readonly ToolCapability[];
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Quality invariant identifier.
|
|
417
|
+
*
|
|
418
|
+
* **Admission contract v1 closed set (7 ids)** — FEATURE_101 itself enforces
|
|
419
|
+
* exactly these on every untrusted manifest:
|
|
420
|
+
*
|
|
421
|
+
* - 'finalOwner' Manifest must designate a final owner role
|
|
422
|
+
* - 'handoffLegality' Handoff graph (manifest + activated agents) is acyclic
|
|
423
|
+
* - 'budgetCeiling' manifest.maxBudget ≤ system_cap; runtime clamp to parent
|
|
424
|
+
* - 'toolPermission' Resolved capabilities ⊆ system_cap; runtime clamp to parent
|
|
425
|
+
* - 'evidenceTrail' Mutations must leave evidence; terminal verifies completeness
|
|
426
|
+
* - 'boundedRevise' maxIterations ≤ system; runtime tracks revise count
|
|
427
|
+
* - 'independentReview' Verifier role bound; verifier can't read generator reasoning
|
|
428
|
+
*
|
|
429
|
+
* **External consumers (open-ended) — registered to invariant runtime but
|
|
430
|
+
* NOT in admission v1 closed set**:
|
|
431
|
+
*
|
|
432
|
+
* - 'harnessSelectionTiming' FEATURE_106 (v0.7.31) — multi-file mutations
|
|
433
|
+
* must be preceded by an emitted harness verdict
|
|
434
|
+
*
|
|
435
|
+
* The runtime is open: future features may register additional invariants.
|
|
436
|
+
* The closed-set guarantee (7) applies to admission v1 only — see
|
|
437
|
+
* docs/features/v0.7.31.md FEATURE_101 §第一版 Invariant 清单 注脚.
|
|
438
|
+
*/
|
|
439
|
+
type InvariantId = 'finalOwner' | 'handoffLegality' | 'budgetCeiling' | 'toolPermission' | 'evidenceTrail' | 'boundedRevise' | 'independentReview' | 'harnessSelectionTiming' | 'planBeforeMutate';
|
|
440
|
+
/**
|
|
441
|
+
* Patch the admission layer applies when an invariant returns severity='clamp'.
|
|
442
|
+
* Pure data — Runner applies it via a single deterministic reducer (see
|
|
443
|
+
* `applyManifestPatch` in `./admission-patch.ts`).
|
|
444
|
+
*
|
|
445
|
+
* Empty / undefined fields mean "no change". Multiple patches compose by
|
|
446
|
+
* union (removeTools concatenates, clamp* picks min, addInvariants unions).
|
|
447
|
+
*/
|
|
448
|
+
interface ManifestPatch {
|
|
449
|
+
readonly removeTools?: readonly string[];
|
|
450
|
+
readonly clampMaxBudget?: number;
|
|
451
|
+
readonly clampMaxIterations?: number;
|
|
452
|
+
readonly addInvariants?: readonly InvariantId[];
|
|
453
|
+
readonly notes?: readonly string[];
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Three-severity result returned by every invariant hook (admit / observe /
|
|
457
|
+
* assertTerminal):
|
|
458
|
+
*
|
|
459
|
+
* - `ok: true` No violation. Runner continues.
|
|
460
|
+
* - `severity: 'reject'` Hard violation. Admission fails (admit-time)
|
|
461
|
+
* or runtime escalates (observe/terminal-time).
|
|
462
|
+
* - `severity: 'clamp'` Manifest is over-broad. Admission applies the
|
|
463
|
+
* attached `patch` and admits with a warning.
|
|
464
|
+
* clamp severity ONLY makes sense at admit-time;
|
|
465
|
+
* observe/terminal hooks should use 'warn' or
|
|
466
|
+
* 'reject'.
|
|
467
|
+
* - `severity: 'warn'` Log-only signal. Runner records to trace +
|
|
468
|
+
* dispatch-eval metric, no action taken.
|
|
469
|
+
*
|
|
470
|
+
* The discriminated union pattern lets TypeScript narrow `patch` to only
|
|
471
|
+
* be present on clamp results — callers can't forget to check.
|
|
472
|
+
*/
|
|
473
|
+
type InvariantResult = {
|
|
474
|
+
readonly ok: true;
|
|
475
|
+
} | {
|
|
476
|
+
readonly ok: false;
|
|
477
|
+
readonly severity: 'reject';
|
|
478
|
+
readonly reason: string;
|
|
479
|
+
} | {
|
|
480
|
+
readonly ok: false;
|
|
481
|
+
readonly severity: 'clamp';
|
|
482
|
+
readonly reason: string;
|
|
483
|
+
readonly patch: ManifestPatch;
|
|
484
|
+
} | {
|
|
485
|
+
readonly ok: false;
|
|
486
|
+
readonly severity: 'warn';
|
|
487
|
+
readonly reason: string;
|
|
488
|
+
};
|
|
489
|
+
/**
|
|
490
|
+
* System-wide caps the admission layer enforces against. The Runner
|
|
491
|
+
* resolves these from configuration once at startup (or per-call when
|
|
492
|
+
* the SDK consumer overrides via Runner.admit options).
|
|
493
|
+
*
|
|
494
|
+
* `maxBudget` / `maxIterations` are activation caps — runtime clamps to
|
|
495
|
+
* parent.remaining via the budget controller (separate concern).
|
|
496
|
+
* `allowedToolCapabilities` is the union of capabilities the system
|
|
497
|
+
* permits ANY constructed agent to request (intersected with
|
|
498
|
+
* manifest.requestedToolCapabilities at admission time).
|
|
499
|
+
*/
|
|
500
|
+
interface SystemCap {
|
|
501
|
+
readonly maxBudget: number;
|
|
502
|
+
readonly maxIterations: number;
|
|
503
|
+
readonly allowedToolCapabilities: readonly ToolCapability[];
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Context passed to invariant.admit() hooks at admission time.
|
|
507
|
+
*
|
|
508
|
+
* `activatedAgents` is the global set of already-admitted constructed
|
|
509
|
+
* agents — used by `handoffLegality` for transitive cycle detection
|
|
510
|
+
* (handoffs reference these by name).
|
|
511
|
+
*
|
|
512
|
+
* `stagedAgents` is the set of manifests that have been staged in the
|
|
513
|
+
* current generation batch but are not yet activated. FEATURE_101
|
|
514
|
+
* v0.7.31.1 patch: `handoffLegality` consults both maps so a same-batch
|
|
515
|
+
* cycle (A→B + B→A staged together, neither yet activated) is rejected
|
|
516
|
+
* at admission time instead of slipping through. The map is
|
|
517
|
+
* intentionally separate from `activatedAgents` so invariants that
|
|
518
|
+
* only care about already-running agents (future work) can still
|
|
519
|
+
* distinguish.
|
|
520
|
+
*
|
|
521
|
+
* Frozen at admission entry; invariants must not mutate.
|
|
522
|
+
*/
|
|
523
|
+
interface AdmissionCtx {
|
|
524
|
+
readonly manifest: AgentManifest;
|
|
525
|
+
readonly activatedAgents: ReadonlyMap<string, Agent>;
|
|
526
|
+
readonly stagedAgents: ReadonlyMap<string, Agent>;
|
|
527
|
+
readonly systemCap: SystemCap;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Runtime event fed to invariant.observe() during agent execution.
|
|
531
|
+
* Discriminated by `kind` so each invariant only narrows on what it
|
|
532
|
+
* cares about (e.g. `harnessSelectionTiming` only inspects
|
|
533
|
+
* `mutation_recorded` events).
|
|
534
|
+
*/
|
|
535
|
+
type RunnerEvent = {
|
|
536
|
+
readonly kind: 'tool_call';
|
|
537
|
+
readonly toolName: string;
|
|
538
|
+
readonly capability?: ToolCapability;
|
|
539
|
+
} | {
|
|
540
|
+
readonly kind: 'mutation_recorded';
|
|
541
|
+
readonly file: string;
|
|
542
|
+
readonly fileCount: number;
|
|
543
|
+
} | {
|
|
544
|
+
readonly kind: 'handoff_taken';
|
|
545
|
+
readonly target: string;
|
|
546
|
+
} | {
|
|
547
|
+
readonly kind: 'revise_count';
|
|
548
|
+
readonly harness: string;
|
|
549
|
+
readonly count: number;
|
|
550
|
+
} | {
|
|
551
|
+
readonly kind: 'evidence_added';
|
|
552
|
+
readonly artifactPath: string;
|
|
553
|
+
};
|
|
554
|
+
/**
|
|
555
|
+
* Read-only view of the per-run mutation tracker. Invariant observe hooks
|
|
556
|
+
* may inspect but never mutate. (The full @kodax-ai/coding mutation tracker
|
|
557
|
+
* has additional fields like per-file line deltas — those are the coding
|
|
558
|
+
* package's concern, not the Layer A primitive.)
|
|
559
|
+
*/
|
|
560
|
+
interface ReadonlyMutationTracker {
|
|
561
|
+
readonly files: ReadonlySet<string>;
|
|
562
|
+
readonly totalOps: number;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Recorder slice exposed to observe hooks for cross-event correlation.
|
|
566
|
+
* Kept minimal — invariants that need richer state should manage their
|
|
567
|
+
* own per-instance counters and use the recorder only for shared
|
|
568
|
+
* "did Scout commit a harness verdict yet?" signal.
|
|
569
|
+
*/
|
|
570
|
+
interface ReadonlyRecorder {
|
|
571
|
+
readonly scout?: {
|
|
572
|
+
readonly payload?: {
|
|
573
|
+
readonly scout?: {
|
|
574
|
+
readonly confirmedHarness?: string;
|
|
575
|
+
};
|
|
576
|
+
};
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
interface ObserveCtx {
|
|
580
|
+
readonly manifest: AgentManifest;
|
|
581
|
+
readonly mutationTracker: ReadonlyMutationTracker;
|
|
582
|
+
readonly recorder: ReadonlyRecorder;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Terminal-time deliverable inspected by invariant.assertTerminal hooks.
|
|
586
|
+
*
|
|
587
|
+
* `verdict` is set when an Evaluator role emitted a verdict; undefined
|
|
588
|
+
* for H0 runs that bypass evaluation. `evidenceArtifacts` enumerates the
|
|
589
|
+
* artifact files produced during the run (per-mutation evidence,
|
|
590
|
+
* verification reports, etc.).
|
|
591
|
+
*/
|
|
592
|
+
interface Deliverable {
|
|
593
|
+
readonly evidenceArtifacts: readonly string[];
|
|
594
|
+
readonly verdict?: 'accept' | 'revise' | 'blocked';
|
|
595
|
+
readonly mutationCount: number;
|
|
596
|
+
}
|
|
597
|
+
interface TerminalCtx {
|
|
598
|
+
readonly manifest: AgentManifest;
|
|
599
|
+
readonly deliverable: Deliverable;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Quality Invariant declaration. An invariant declares which of the three
|
|
603
|
+
* hook points it implements (admit / observe / assertTerminal) — at least
|
|
604
|
+
* one of the three must be present.
|
|
605
|
+
*
|
|
606
|
+
* Invariants are registered to the runtime via `registerInvariant()` (in
|
|
607
|
+
* `./admission.ts` once Runner.admit lands). The runtime maintains a
|
|
608
|
+
* static registry indexed by `InvariantId`; `Runner.admit` resolves the
|
|
609
|
+
* required set per (role, toolScope, harnessTier) tuple and applies all
|
|
610
|
+
* relevant admit hooks.
|
|
611
|
+
*
|
|
612
|
+
* Invariants must be pure functions of their inputs. Side effects
|
|
613
|
+
* (writing trace, sending events) happen in the Runner shell, not inside
|
|
614
|
+
* the invariant body.
|
|
615
|
+
*/
|
|
616
|
+
interface QualityInvariant {
|
|
617
|
+
readonly id: InvariantId;
|
|
618
|
+
readonly description: string;
|
|
619
|
+
admit?(manifest: AgentManifest, ctx: AdmissionCtx): InvariantResult;
|
|
620
|
+
observe?(event: RunnerEvent, ctx: ObserveCtx): InvariantResult;
|
|
621
|
+
assertTerminal?(deliverable: Deliverable, ctx: TerminalCtx): InvariantResult;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Opaque handle produced by `Runner.admit()` on success. Required input
|
|
625
|
+
* to `ConstructionRuntime.activate()` — prevents activate from being
|
|
626
|
+
* called on a manifest that hasn't gone through admission.
|
|
627
|
+
*
|
|
628
|
+
* `appliedPatches` records every clamp the admission applied; consumers
|
|
629
|
+
* can inspect to surface "what was modified vs the manifest you submitted".
|
|
630
|
+
* `invariantBindings` lists the invariants registered against this
|
|
631
|
+
* admitted agent (effective set = required ∪ declared).
|
|
632
|
+
*/
|
|
633
|
+
interface AdmittedHandle {
|
|
634
|
+
readonly manifest: AgentManifest;
|
|
635
|
+
readonly admittedAt: string;
|
|
636
|
+
readonly appliedPatches: readonly ManifestPatch[];
|
|
637
|
+
readonly invariantBindings: readonly InvariantId[];
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Admission verdict — discriminated union so TypeScript can narrow
|
|
641
|
+
* `handle` (only present on success) vs `reason` (only on failure).
|
|
642
|
+
*
|
|
643
|
+
* `retryable` on failure indicates whether the generator should be asked
|
|
644
|
+
* to fix and retry (schema invalid / DAG cycle) vs hard reject (system
|
|
645
|
+
* cap violated past clamp tolerance).
|
|
646
|
+
*/
|
|
647
|
+
type AdmissionVerdict = {
|
|
648
|
+
readonly ok: true;
|
|
649
|
+
readonly handle: AdmittedHandle;
|
|
650
|
+
readonly clampNotes: readonly string[];
|
|
651
|
+
} | {
|
|
652
|
+
readonly ok: false;
|
|
653
|
+
readonly reason: string;
|
|
654
|
+
readonly retryable: boolean;
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* FEATURE_101 admission audit — the 5-step process `Runner.admit` runs
|
|
659
|
+
* against an untrusted manifest.
|
|
660
|
+
*
|
|
661
|
+
* Pure orchestration of the building blocks declared elsewhere in
|
|
662
|
+
* @kodax-ai/core:
|
|
663
|
+
*
|
|
664
|
+
* 1. **Schema validation** — manifest has well-formed name, instructions,
|
|
665
|
+
* tools, declaredInvariants, requestedToolCapabilities. Fail-fast on
|
|
666
|
+
* shape errors (no clamps).
|
|
667
|
+
* 2. **Resolve effective invariants** — required (system policy) ∪
|
|
668
|
+
* declared (manifest voluntary). Required is computed from
|
|
669
|
+
* role / toolScope / harnessTier; declared can only ADD.
|
|
670
|
+
* 3. **Run admit hooks** — for each effective invariant that has an
|
|
671
|
+
* admit hook registered, call it with the (manifest, ctx) tuple.
|
|
672
|
+
* Collect reject / clamp / warn results.
|
|
673
|
+
* 4. **Compose patches** — clamp-severity results carry patches; we
|
|
674
|
+
* compose them with `composePatches` (min-wins for clamps, union
|
|
675
|
+
* for collections).
|
|
676
|
+
* 5. **Apply patches** — `applyManifestPatch` produces the final
|
|
677
|
+
* admitted manifest. Reject results short-circuit before this step.
|
|
678
|
+
*
|
|
679
|
+
* Returns an `AdmissionVerdict` discriminated union — `ok: true` carries
|
|
680
|
+
* the `AdmittedHandle` plus `clampNotes`; `ok: false` carries `reason`
|
|
681
|
+
* and the `retryable` flag.
|
|
682
|
+
*
|
|
683
|
+
* Pure function (no I/O, no logging). The Runner shell is responsible
|
|
684
|
+
* for tracing / observability around this call.
|
|
685
|
+
*/
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Default system cap — high ceilings so admission only clamps when
|
|
689
|
+
* deployments have explicitly declared tighter limits. The numbers
|
|
690
|
+
* mirror the legacy `runManagedTask` budget defaults so this is a
|
|
691
|
+
* compatibility-preserving baseline, not a policy tightening.
|
|
692
|
+
*/
|
|
693
|
+
declare const DEFAULT_SYSTEM_CAP: SystemCap;
|
|
694
|
+
/**
|
|
695
|
+
* Options accepted by `runAdmissionAudit` (and surfaced by `Runner.admit`).
|
|
696
|
+
* All fields are optional — the audit substitutes safe defaults so the
|
|
697
|
+
* SDK call surface stays a single positional argument: the manifest.
|
|
698
|
+
*/
|
|
699
|
+
interface AdmissionAuditOptions {
|
|
700
|
+
readonly systemCap?: SystemCap;
|
|
701
|
+
readonly activatedAgents?: ReadonlyMap<string, Agent>;
|
|
702
|
+
/**
|
|
703
|
+
* FEATURE_101 v0.7.31.1 — same-batch staged agents. Manifests that
|
|
704
|
+
* have been staged but not yet activated still need to participate
|
|
705
|
+
* in `handoffLegality` cycle detection: a generator that writes A
|
|
706
|
+
* (handoff to B) and B (handoff to A) in the same batch sees neither
|
|
707
|
+
* activated when admission runs on each individually. With
|
|
708
|
+
* `stagedAgents` populated, the second admission detects the back
|
|
709
|
+
* edge to the first and rejects.
|
|
710
|
+
*
|
|
711
|
+
* Sourced from `ConstructionRuntime` which builds a Map of
|
|
712
|
+
* staged-status manifests at the call site.
|
|
713
|
+
*/
|
|
714
|
+
readonly stagedAgents?: ReadonlyMap<string, Agent>;
|
|
715
|
+
/**
|
|
716
|
+
* Agent role identifier — opaque string from the agent layer's perspective.
|
|
717
|
+
* Concrete agent presets (e.g. coding's AMA harness with 'scout' / 'planner' /
|
|
718
|
+
* 'generator' / 'evaluator' / 'direct') brand this themselves; the admission
|
|
719
|
+
* framework only plumbs it through to `resolveRequiredInvariants`.
|
|
720
|
+
* v0.7.35.1 FEATURE_142: widened from coding-AMA literal union per ADR-021
|
|
721
|
+
* (agent layer must not enumerate coding-specific role names).
|
|
722
|
+
*/
|
|
723
|
+
readonly role?: string;
|
|
724
|
+
readonly toolScope?: readonly string[];
|
|
725
|
+
/**
|
|
726
|
+
* Harness tier identifier — opaque string. Concrete agent presets brand it
|
|
727
|
+
* (e.g. coding's 'H0_DIRECT' / 'H1_EXECUTE_EVAL' / 'H2_PLAN_EXECUTE_EVAL').
|
|
728
|
+
* v0.7.35.1 FEATURE_142: widened from coding-AMA literal union per ADR-021.
|
|
729
|
+
*/
|
|
730
|
+
readonly harnessTier?: string;
|
|
731
|
+
/**
|
|
732
|
+
* ISO timestamp recorded on the AdmittedHandle. Defaults to
|
|
733
|
+
* `new Date().toISOString()` — overridable so tests can pin a value.
|
|
734
|
+
*/
|
|
735
|
+
readonly nowIso?: string;
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Scan an instructions string for known prompt-injection patterns.
|
|
739
|
+
* Returns the first matching pattern id or undefined when clean.
|
|
740
|
+
*/
|
|
741
|
+
declare function detectInstructionsInjection(text: string): string | undefined;
|
|
742
|
+
/**
|
|
743
|
+
* Run the admission audit against an untrusted manifest. Returns an
|
|
744
|
+
* `AdmissionVerdict` — never throws (errors are encoded in the verdict).
|
|
745
|
+
*
|
|
746
|
+
* Pure function: same inputs always return equivalent outputs (modulo
|
|
747
|
+
* the `nowIso` timestamp, which can be pinned via options).
|
|
748
|
+
*/
|
|
749
|
+
declare function runAdmissionAudit(manifest: AgentManifest, options?: AdmissionAuditOptions): AdmissionVerdict;
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* FEATURE_101 (v0.7.31.1) — admission session: runtime dispatch of
|
|
753
|
+
* `observe` and `assertTerminal` invariant hooks.
|
|
754
|
+
*
|
|
755
|
+
* The v0.7.31 release shipped only the `admit` hook wired into
|
|
756
|
+
* `Runner.admit`. The three-segment hook model (admit / observe /
|
|
757
|
+
* assertTerminal) declared in FEATURE_101 §三段 hook 模型 had its
|
|
758
|
+
* other two thirds defined as types but never invoked at runtime —
|
|
759
|
+
* meaning every invariant that depended on observe / terminal
|
|
760
|
+
* (`evidenceTrail`, `independentReview`, `boundedRevise`,
|
|
761
|
+
* `harnessSelectionTiming`) was effectively dormant after admission.
|
|
762
|
+
*
|
|
763
|
+
* This module fills that gap with two pieces:
|
|
764
|
+
*
|
|
765
|
+
* 1. A WeakMap-backed binding registry (`setAdmittedAgentBindings` /
|
|
766
|
+
* `getAdmittedAgentBindings`) so `Runner.run` can recover the
|
|
767
|
+
* InvariantId set associated with an admitted agent without a
|
|
768
|
+
* compile-time dependency from `agent.ts` onto `admission.ts`
|
|
769
|
+
* (which would re-introduce the import cycle the original split
|
|
770
|
+
* avoided).
|
|
771
|
+
* 2. `InvariantSession`: a per-run event router. The Runner creates
|
|
772
|
+
* one when an agent has bindings, and threads `record*` calls
|
|
773
|
+
* through it during the run. The session dispatches observe to
|
|
774
|
+
* bound invariants and accumulates violations; assertTerminal
|
|
775
|
+
* runs once at end.
|
|
776
|
+
*
|
|
777
|
+
* Pure runtime — no I/O. The session does not log or trace; the Runner
|
|
778
|
+
* shell decides what to do with returned violation results
|
|
779
|
+
* (typically: trace span for `warn`, throw for `reject`, accumulate
|
|
780
|
+
* patches for `clamp` though clamp is admit-time only).
|
|
781
|
+
*/
|
|
782
|
+
|
|
783
|
+
/**
|
|
784
|
+
* Associate an admitted manifest's invariant bindings with the runtime
|
|
785
|
+
* Agent the consumer uses. Set by `ConstructionRuntime.activate` after
|
|
786
|
+
* `Runner.admit` succeeds; SDK consumers calling `Runner.run` directly
|
|
787
|
+
* on hand-authored Agents leave this unset and skip runtime invariant
|
|
788
|
+
* dispatch entirely.
|
|
789
|
+
*/
|
|
790
|
+
declare function setAdmittedAgentBindings(agent: Agent, manifest: AgentManifest, bindings: readonly InvariantId[]): void;
|
|
791
|
+
/**
|
|
792
|
+
* Look up bindings for an agent. Returns undefined when the agent was
|
|
793
|
+
* never admitted (trusted SDK / preset path).
|
|
794
|
+
*/
|
|
795
|
+
declare function getAdmittedAgentBindings(agent: Agent): {
|
|
796
|
+
readonly bindings: readonly InvariantId[];
|
|
797
|
+
readonly manifest: AgentManifest;
|
|
798
|
+
} | undefined;
|
|
799
|
+
/**
|
|
800
|
+
* Test-only — clears the registry. Production code should never call
|
|
801
|
+
* this; the WeakMap entries are reclaimed naturally when agents fall
|
|
802
|
+
* out of scope.
|
|
803
|
+
*/
|
|
804
|
+
declare function _resetAdmittedAgentBindings(agent: Agent): void;
|
|
805
|
+
/**
|
|
806
|
+
* Severity surface returned by `recordX` calls. A `reject` from
|
|
807
|
+
* observe means the run must abort; the Runner shell raises an error.
|
|
808
|
+
* A `warn` is informational — the Runner records it but continues.
|
|
809
|
+
* `ok` is the no-op success case.
|
|
810
|
+
*/
|
|
811
|
+
interface SessionDispatchResult {
|
|
812
|
+
readonly results: readonly {
|
|
813
|
+
readonly id: InvariantId;
|
|
814
|
+
readonly result: InvariantResult;
|
|
815
|
+
}[];
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Per-run state machine + event router. Constructed once at the start
|
|
819
|
+
* of a run (inside `Runner.run`) when the start agent has bindings.
|
|
820
|
+
* The Runner threads tool / handoff / mutation events through the
|
|
821
|
+
* `record*` API; the session fans them out to bound invariants.
|
|
822
|
+
*
|
|
823
|
+
* Threading rules (so the data stays valid):
|
|
824
|
+
* - `recordX` calls return synchronously; observe hooks are pure
|
|
825
|
+
* functions of the immutable event payload + read-only context.
|
|
826
|
+
* - `assertTerminal` must be called exactly once at run end. The
|
|
827
|
+
* Runner is responsible for honoring this.
|
|
828
|
+
* - The session is single-run; spawning a sub-run (handoff /
|
|
829
|
+
* dispatch_child_task) creates a fresh session for the target.
|
|
830
|
+
*
|
|
831
|
+
* The session is never exposed across module boundaries — it lives in
|
|
832
|
+
* the Runner closure and dies when the run ends. WeakMap is overkill
|
|
833
|
+
* for state that is by-construction scoped; plain fields suffice.
|
|
834
|
+
*/
|
|
835
|
+
declare class InvariantSession {
|
|
836
|
+
private readonly bindings;
|
|
837
|
+
private readonly manifest;
|
|
838
|
+
private readonly mutations;
|
|
839
|
+
private readonly recorder;
|
|
840
|
+
private verdict;
|
|
841
|
+
private readonly evidenceArtifacts;
|
|
842
|
+
private readonly violations;
|
|
843
|
+
private terminalRan;
|
|
844
|
+
constructor(bindings: readonly InvariantId[], manifest: AgentManifest);
|
|
845
|
+
recordToolCall(toolName: string, capability?: ToolCapability): SessionDispatchResult;
|
|
846
|
+
recordHandoff(target: string): SessionDispatchResult;
|
|
847
|
+
/**
|
|
848
|
+
* Record a file mutation. `fileCount` is the cumulative distinct-file
|
|
849
|
+
* total (mirrors `harnessSelectionTiming` ObserveCtx contract). The
|
|
850
|
+
* session computes it from its internal MutableMutationTracker so
|
|
851
|
+
* callers don't need to track it.
|
|
852
|
+
*/
|
|
853
|
+
recordMutation(file: string): SessionDispatchResult;
|
|
854
|
+
recordEvidence(artifactPath: string): SessionDispatchResult;
|
|
855
|
+
recordRevise(harness: string, count: number): SessionDispatchResult;
|
|
856
|
+
/**
|
|
857
|
+
* Record the Scout's confirmed-harness signal — drives
|
|
858
|
+
* `harnessSelectionTiming.observe`'s "did Scout commit a harness
|
|
859
|
+
* verdict yet?" check. Coding-side surface invokes this after the
|
|
860
|
+
* scout role emits its verdict.
|
|
861
|
+
*/
|
|
862
|
+
setConfirmedHarness(harness: string): void;
|
|
863
|
+
setVerdict(verdict: 'accept' | 'revise' | 'blocked'): void;
|
|
864
|
+
/** @internal Test inspection + Runner trace surface. */
|
|
865
|
+
getViolations(): readonly {
|
|
866
|
+
readonly id: InvariantId;
|
|
867
|
+
readonly result: InvariantResult;
|
|
868
|
+
}[];
|
|
869
|
+
getMutationCount(): number;
|
|
870
|
+
getEvidenceArtifacts(): readonly string[];
|
|
871
|
+
/**
|
|
872
|
+
* Run all bound invariants' `assertTerminal` hooks. Caller must
|
|
873
|
+
* invoke exactly once; subsequent calls are no-ops (returns the
|
|
874
|
+
* accumulated violations from the first call). Returns the
|
|
875
|
+
* union of violations gathered during observe + this terminal pass.
|
|
876
|
+
*/
|
|
877
|
+
assertTerminal(): SessionDispatchResult;
|
|
878
|
+
private dispatchObserve;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Construct a session for an agent if it has admission bindings, or
|
|
882
|
+
* return undefined for trusted (un-admitted) agents — the Runner
|
|
883
|
+
* checks the return value and skips invariant dispatch entirely when
|
|
884
|
+
* undefined, keeping the trusted-path zero-overhead.
|
|
885
|
+
*/
|
|
886
|
+
declare function createInvariantSessionForAgent(agent: Agent): InvariantSession | undefined;
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* Layer A Primitive: Runner
|
|
890
|
+
*
|
|
891
|
+
* FEATURE_080 (v0.7.23): minimal execution entry for an `Agent`.
|
|
892
|
+
*
|
|
893
|
+
* Two dispatch paths:
|
|
894
|
+
* 1. **Preset dispatch** (the "default coding agent" registers via
|
|
895
|
+
* `registerPresetDispatcher`): delegates to the existing `runKodaX`
|
|
896
|
+
* implementation so SA users see zero behavior change. This is the
|
|
897
|
+
* "Option Y" dog-food wiring negotiated during FEATURE_080+081 design.
|
|
898
|
+
* 2. **Generic dispatch**: for user-defined agents. Performs a single
|
|
899
|
+
* system+user → assistant turn using an injected LLM callback. No tool
|
|
900
|
+
* loop, no extensions, no managed-task harness — those arrive with
|
|
901
|
+
* FEATURE_084 (v0.7.26).
|
|
902
|
+
*
|
|
903
|
+
* Status: @experimental. History: extracted to `@kodax-ai/core` in FEATURE_082
|
|
904
|
+
* (v0.7.24); merged back into `@kodax-ai/agent` in v0.7.35.1 FEATURE_142.
|
|
905
|
+
* `@kodax-ai/coding` retains a barrel re-export for batteries-included consumers.
|
|
906
|
+
*/
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Options accepted by `Runner.run` and `Runner.runStream`.
|
|
910
|
+
*/
|
|
911
|
+
interface RunOptions {
|
|
912
|
+
/**
|
|
913
|
+
* Opaque payload forwarded to the preset dispatcher when one matches.
|
|
914
|
+
* For the built-in coding preset this carries `KodaXOptions`.
|
|
915
|
+
*/
|
|
916
|
+
readonly presetOptions?: unknown;
|
|
917
|
+
/**
|
|
918
|
+
* LLM callback used by the generic dispatch path. Receives the assembled
|
|
919
|
+
* message transcript and the current Agent.
|
|
920
|
+
*
|
|
921
|
+
* Return a plain `string` to preserve the v0.7.23 single-turn behaviour
|
|
922
|
+
* (no tool loop). Return a `RunnerLlmResult` with `toolCalls` to opt into
|
|
923
|
+
* the FEATURE_084 tool loop — the Runner will execute each call against
|
|
924
|
+
* the agent's `RunnableTool`s, append tool_use + tool_result blocks to
|
|
925
|
+
* the transcript, and invoke this callback again until no tool calls are
|
|
926
|
+
* returned (or `MAX_TOOL_LOOP_ITERATIONS` is reached).
|
|
927
|
+
*/
|
|
928
|
+
readonly llm?: (messages: readonly AgentMessage[], agent: Agent) => Promise<RunnerLlmReturn>;
|
|
929
|
+
/**
|
|
930
|
+
* Optional Session to persist the generic-path transcript into. When
|
|
931
|
+
* supplied, each generated message is appended as a `message` entry.
|
|
932
|
+
*/
|
|
933
|
+
readonly session?: Session;
|
|
934
|
+
/**
|
|
935
|
+
* Abort signal forwarded to preset dispatchers that honor it.
|
|
936
|
+
*/
|
|
937
|
+
readonly abortSignal?: AbortSignal;
|
|
938
|
+
/**
|
|
939
|
+
* FEATURE_083 (v0.7.24): tracer used to record AgentSpan / GenerationSpan /
|
|
940
|
+
* ToolCallSpan / HandoffSpan for this run. Defaults to `defaultTracer` when
|
|
941
|
+
* omitted. Pass `null` to disable tracing for this call.
|
|
942
|
+
*/
|
|
943
|
+
readonly tracer?: Tracer | null;
|
|
944
|
+
/**
|
|
945
|
+
* When supplied, the run attaches its AgentSpan as a child of this trace's
|
|
946
|
+
* root span instead of starting a new trace. Useful when an outer Agent
|
|
947
|
+
* is orchestrating sub-runs and wants one trace per user request.
|
|
948
|
+
*/
|
|
949
|
+
readonly trace?: Trace;
|
|
950
|
+
/**
|
|
951
|
+
* FEATURE_085 (v0.7.26): run-scoped guardrails. Merged with
|
|
952
|
+
* `agent.guardrails` — declaration order is agent-first, then opts.
|
|
953
|
+
* Input / output / tool-before / tool-after hooks all dispatch from
|
|
954
|
+
* this union. See `@kodax-ai/agent/primitives/guardrail.ts` for shape.
|
|
955
|
+
*/
|
|
956
|
+
readonly guardrails?: readonly Guardrail[];
|
|
957
|
+
/**
|
|
958
|
+
* Per-run override for the tool-loop iteration cap. When omitted, the
|
|
959
|
+
* loop uses `MAX_TOOL_LOOP_ITERATIONS` (20) — a safe ceiling for
|
|
960
|
+
* stand-alone agent runs. Managed-task orchestration (multi-role
|
|
961
|
+
* handoff chain: Scout → Planner → Generator → Evaluator) needs a much
|
|
962
|
+
* higher cap because the iteration counter is shared across every
|
|
963
|
+
* role in the chain. Legacy `runManagedTask` gave each role its own
|
|
964
|
+
* `DEFAULT_MANAGED_WORK_BUDGET` (200) — the Runner-driven path passes
|
|
965
|
+
* that value here so long investigations don't trip the safety valve
|
|
966
|
+
* after ~20 tool calls.
|
|
967
|
+
*/
|
|
968
|
+
readonly maxToolLoopIterations?: number;
|
|
969
|
+
/**
|
|
970
|
+
* v0.7.26 parity: observer callbacks fired around every tool
|
|
971
|
+
* invocation. Legacy `runManagedTask` emitted `events.onToolResult`
|
|
972
|
+
* at three sites per invocation so the REPL worker ledger could
|
|
973
|
+
* render live tool-call progress — without this plumbing, the
|
|
974
|
+
* Runner-driven path's UI shows only the final output. Preset
|
|
975
|
+
* dispatchers can attach this observer to surface `onToolCall` /
|
|
976
|
+
* `onToolResult` through the usual `KodaXEvents` bus.
|
|
977
|
+
*/
|
|
978
|
+
readonly toolObserver?: RunnerToolObserver;
|
|
979
|
+
/**
|
|
980
|
+
* v0.7.26 parity: compaction hook. Called AFTER each iteration's
|
|
981
|
+
* tool_result has been appended to the transcript (or after the
|
|
982
|
+
* assistant message when there are no tool calls), before the next
|
|
983
|
+
* LLM turn. Return the replacement transcript to trigger compaction;
|
|
984
|
+
* return the same array (or undefined) to skip. Legacy agent.ts ran
|
|
985
|
+
* `intelligentCompact` on the same boundary, so Runner-driven parity
|
|
986
|
+
* requires this hook point. The Runner owns the transcript mutably,
|
|
987
|
+
* so this is the only point consumers can insert a compacted view.
|
|
988
|
+
*/
|
|
989
|
+
readonly compactionHook?: (transcript: readonly AgentMessage[]) => Promise<readonly AgentMessage[] | undefined>;
|
|
990
|
+
/**
|
|
991
|
+
* FEATURE_101 (v0.7.31.1): callback fired once when the Runner has
|
|
992
|
+
* resolved invariant bindings on the start agent and created an
|
|
993
|
+
* `InvariantSession` for the run. Coding-side consumers (mutation
|
|
994
|
+
* tracker, verdict recorder, evidence trail) bind to the session
|
|
995
|
+
* here so per-tool event recording and verdict propagation flow
|
|
996
|
+
* into observe / assertTerminal hooks.
|
|
997
|
+
*
|
|
998
|
+
* Trusted (un-admitted) agents skip session creation entirely —
|
|
999
|
+
* this callback is never fired for them. The "auto-created
|
|
1000
|
+
* session" path keeps SDK consumers from having to instantiate
|
|
1001
|
+
* sessions themselves while still letting them observe.
|
|
1002
|
+
*/
|
|
1003
|
+
readonly onInvariantSessionStarted?: (session: InvariantSession) => void;
|
|
1004
|
+
/**
|
|
1005
|
+
* FEATURE_101 (v0.7.31.1): pluggable tool capability classifier.
|
|
1006
|
+
* Runner calls this on every tool invocation (after Guardrail
|
|
1007
|
+
* before-hooks but before the actual execution); when present, the
|
|
1008
|
+
* returned `ToolCapability` is attached to the `tool_call` event
|
|
1009
|
+
* dispatched to `invariant.observe` hooks. Without a classifier
|
|
1010
|
+
* the event omits the capability field — invariants that key on
|
|
1011
|
+
* capability gracefully fall back to "unknown capability" semantics.
|
|
1012
|
+
*
|
|
1013
|
+
* The coding package wires `resolveToolCapability` from
|
|
1014
|
+
* `agent-runtime/invariants/tool-permission.ts` here.
|
|
1015
|
+
*/
|
|
1016
|
+
readonly capabilityClassifier?: (toolName: string) => ToolCapability | undefined;
|
|
1017
|
+
/**
|
|
1018
|
+
* FEATURE_101 (v0.7.31.1): runtime tool capability re-clamp.
|
|
1019
|
+
*
|
|
1020
|
+
* Admission's `toolPermission` invariant clamps an admitted manifest's
|
|
1021
|
+
* tools to `system_cap.allowedToolCapabilities` at activation time.
|
|
1022
|
+
* That covers "agent declared a tool the system never allows", but
|
|
1023
|
+
* NOT the runtime case where a parent run is itself capped lower
|
|
1024
|
+
* than system_cap and dispatches a sub-agent. The design's two-stage
|
|
1025
|
+
* clamp model wants the parent's narrower set to apply to every
|
|
1026
|
+
* tool call inside the sub-run.
|
|
1027
|
+
*
|
|
1028
|
+
* When this option is set AND the start agent has admission bindings,
|
|
1029
|
+
* Runner.run filters every tool invocation through `capabilityClassifier`
|
|
1030
|
+
* and rejects calls whose capability tier is not in the parent set.
|
|
1031
|
+
* Rejection materializes as an error tool_result so the LLM can
|
|
1032
|
+
* observe the clamp and recover. Trusted (un-admitted) agents are
|
|
1033
|
+
* NOT clamped — the parent passes them as-is by design (admission
|
|
1034
|
+
* trust = runtime trust).
|
|
1035
|
+
*/
|
|
1036
|
+
readonly parentToolCapabilities?: readonly ToolCapability[];
|
|
1037
|
+
/**
|
|
1038
|
+
* FEATURE_164 (v0.7.41) — mid-turn message injection hook.
|
|
1039
|
+
*
|
|
1040
|
+
* Called AFTER tool execution + compaction + handoff handling have
|
|
1041
|
+
* completed for the current iteration, but BEFORE the next iteration's
|
|
1042
|
+
* `runGenerationTurn` starts. The hook returns an array of additional
|
|
1043
|
+
* messages (typically user-role prompts the caller wants to splice in)
|
|
1044
|
+
* which the Runner pushes to the transcript and Session before the
|
|
1045
|
+
* next LLM call.
|
|
1046
|
+
*
|
|
1047
|
+
* Designed to support claudecode-style "chat-while-waiting": when the
|
|
1048
|
+
* user types a new query while the agent is mid-task, the caller's
|
|
1049
|
+
* hook can drain the input queue and inject it as a user message at
|
|
1050
|
+
* the tool-result boundary — Worker continues its loop, the LLM
|
|
1051
|
+
* sees the new user message in its next call, and no empty turn is
|
|
1052
|
+
* emitted. Replaces the legacy "return `{text: '', toolCalls: []}`"
|
|
1053
|
+
* pattern that polluted the transcript with an empty assistant turn.
|
|
1054
|
+
*
|
|
1055
|
+
* The hook fires only when the current iteration ran tool calls (the
|
|
1056
|
+
* terminal-no-tool branch returns before reaching here). Empty return
|
|
1057
|
+
* value is the no-op fast path. Returning a transcript-replacement
|
|
1058
|
+
* is intentionally NOT supported — callers wanting that semantic
|
|
1059
|
+
* should use `compactionHook` instead.
|
|
1060
|
+
*/
|
|
1061
|
+
readonly beforeNextTurn?: (ctx: {
|
|
1062
|
+
readonly agent: Agent;
|
|
1063
|
+
readonly transcript: readonly AgentMessage[];
|
|
1064
|
+
readonly iteration: number;
|
|
1065
|
+
}) => Promise<readonly AgentMessage[]>;
|
|
1066
|
+
/**
|
|
1067
|
+
* FEATURE_166 (v0.7.41 follow-up) — agent-switch hook.
|
|
1068
|
+
*
|
|
1069
|
+
* Fires AFTER `currentAgent` has been swapped to the handoff target
|
|
1070
|
+
* (`handoffSignal.to`) AND after the transcript inputFilter +
|
|
1071
|
+
* system-message replacement have run, but BEFORE the next
|
|
1072
|
+
* iteration's `runGenerationTurn`. Lets callers react to a role
|
|
1073
|
+
* transition between
|
|
1074
|
+
* turns — most notably the coding observer, which uses this signal to
|
|
1075
|
+
* flip the REPL's `activeWorkerTitle` ahead of the new agent's first
|
|
1076
|
+
* streaming output (without this hook, the label only flips when the
|
|
1077
|
+
* new agent's first slot-tool succeeds, so the label LAGS through
|
|
1078
|
+
* Evaluator's thinking / pre-verdict text and any verification
|
|
1079
|
+
* tool calls; production session 20260515_185354 trace confirms).
|
|
1080
|
+
*
|
|
1081
|
+
* Awaitable so callers can perform async side effects (e.g. flushing
|
|
1082
|
+
* a status emit through an event bus). Errors propagate verbatim —
|
|
1083
|
+
* the hook is caller-controlled, matching `beforeNextTurn` semantics.
|
|
1084
|
+
*
|
|
1085
|
+
* Fires at most once per iteration (only the first matching handoff
|
|
1086
|
+
* in a tool-result batch transitions ownership; see line ~782).
|
|
1087
|
+
*/
|
|
1088
|
+
readonly onAgentSwitched?: (ctx: {
|
|
1089
|
+
readonly from: Agent;
|
|
1090
|
+
readonly to: Agent;
|
|
1091
|
+
readonly iteration: number;
|
|
1092
|
+
}) => void | Promise<void>;
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Result returned by `Runner.run`.
|
|
1096
|
+
*/
|
|
1097
|
+
interface RunResult<TData = unknown> {
|
|
1098
|
+
readonly output: string;
|
|
1099
|
+
readonly messages: readonly AgentMessage[];
|
|
1100
|
+
readonly sessionId?: string;
|
|
1101
|
+
readonly data?: TData;
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Stream events emitted by `Runner.runStream`. The event surface is
|
|
1105
|
+
* intentionally small in v0.7.23; FEATURE_084 expands it to mirror the
|
|
1106
|
+
* task-engine's event set.
|
|
1107
|
+
*/
|
|
1108
|
+
type RunEvent<TData = unknown> = {
|
|
1109
|
+
readonly kind: 'message';
|
|
1110
|
+
readonly message: AgentMessage;
|
|
1111
|
+
} | {
|
|
1112
|
+
readonly kind: 'complete';
|
|
1113
|
+
readonly result: RunResult<TData>;
|
|
1114
|
+
} | {
|
|
1115
|
+
readonly kind: 'error';
|
|
1116
|
+
readonly error: Error;
|
|
1117
|
+
};
|
|
1118
|
+
/**
|
|
1119
|
+
* Tracing context handed to preset dispatchers so they can attach richer
|
|
1120
|
+
* spans (e.g. GenerationSpan, ToolCallSpan) under the Runner's AgentSpan.
|
|
1121
|
+
*
|
|
1122
|
+
* FEATURE_083 (v0.7.24): added in Slice 8 to let the coding preset emit
|
|
1123
|
+
* the AgentSpan lifecycle under the same trace as the Runner entry point.
|
|
1124
|
+
*/
|
|
1125
|
+
interface PresetTracingContext {
|
|
1126
|
+
readonly tracer: Tracer;
|
|
1127
|
+
readonly trace: Trace;
|
|
1128
|
+
readonly agentSpan: Span;
|
|
1129
|
+
}
|
|
1130
|
+
/**
|
|
1131
|
+
* Preset dispatcher signature. Registered via `registerPresetDispatcher` and
|
|
1132
|
+
* keyed on `Agent.name`. The optional fourth argument carries tracing
|
|
1133
|
+
* context created by the Runner; dispatchers may emit child spans under
|
|
1134
|
+
* `tracingContext.agentSpan`.
|
|
1135
|
+
*/
|
|
1136
|
+
type PresetDispatcher = (agent: Agent, input: string | readonly AgentMessage[], opts: RunOptions | undefined, tracingContext?: PresetTracingContext) => Promise<RunResult>;
|
|
1137
|
+
/**
|
|
1138
|
+
* Register a preset dispatcher for a given Agent name. The coding package
|
|
1139
|
+
* registers the `runKodaX` dispatcher for the default coding agent on
|
|
1140
|
+
* import of `createDefaultCodingAgent`.
|
|
1141
|
+
*
|
|
1142
|
+
* Returns an unregister function.
|
|
1143
|
+
*/
|
|
1144
|
+
declare function registerPresetDispatcher(agentName: string, dispatcher: PresetDispatcher): () => void;
|
|
1145
|
+
/** @internal Testing helper. Do not rely on this from application code. */
|
|
1146
|
+
declare function _resetPresetDispatchers(): void;
|
|
1147
|
+
/**
|
|
1148
|
+
* Wrap a role-spec string in the trusted/untrusted boundary admission
|
|
1149
|
+
* applies to admitted (constructed) agents. Exported so the FEATURE_104
|
|
1150
|
+
* benchmark dataset (`benchmark/datasets/admission-wrap-baseline/`) can
|
|
1151
|
+
* use the production wrap text verbatim — preventing drift between the
|
|
1152
|
+
* Q6 non-degradation eval and the actual Runner behavior.
|
|
1153
|
+
*
|
|
1154
|
+
* `agent` selects the path: agents with admission bindings get the
|
|
1155
|
+
* full wrap; trusted agents pass through unchanged. Callers wanting the
|
|
1156
|
+
* wrap unconditionally (e.g. for test harnessing) should pass an agent
|
|
1157
|
+
* whose bindings are populated via `setAdmittedAgentBindings`.
|
|
1158
|
+
*/
|
|
1159
|
+
declare function buildSystemPrompt(agent: Agent, instructions: string): string;
|
|
1160
|
+
/**
|
|
1161
|
+
* Minimal execution entry for an `Agent`.
|
|
1162
|
+
*/
|
|
1163
|
+
declare class Runner {
|
|
1164
|
+
/**
|
|
1165
|
+
* Run an agent to completion. Resolves with the final output plus the
|
|
1166
|
+
* full transcript.
|
|
1167
|
+
*
|
|
1168
|
+
* FEATURE_083 (v0.7.24): emits an AgentSpan around every run and a
|
|
1169
|
+
* GenerationSpan around the underlying LLM call in the generic path.
|
|
1170
|
+
* Preset dispatchers receive a `PresetTracingContext` so they can attach
|
|
1171
|
+
* richer spans under the AgentSpan. Pass `opts.tracer = null` to skip
|
|
1172
|
+
* tracing entirely for performance-sensitive calls.
|
|
1173
|
+
*/
|
|
1174
|
+
static run<TData = unknown>(agent: Agent, input: string | readonly AgentMessage[], opts?: RunOptions): Promise<RunResult<TData>>;
|
|
1175
|
+
/**
|
|
1176
|
+
* FEATURE_101 (v0.7.31): admit an untrusted `AgentManifest` against the
|
|
1177
|
+
* admission contract. Returns an `AdmissionVerdict` — `{ ok: true,
|
|
1178
|
+
* handle, clampNotes }` on admission, `{ ok: false, reason, retryable }`
|
|
1179
|
+
* on schema/invariant rejection.
|
|
1180
|
+
*
|
|
1181
|
+
* `Runner.admit` is the single gate between an LLM-emitted manifest and
|
|
1182
|
+
* an executable Agent. The caller MUST receive an admitted handle
|
|
1183
|
+
* before invoking `Runner.run` on any LLM-constructed agent (FEATURE_089
|
|
1184
|
+
* agent-generation enforces this via the activate handle plumbing in
|
|
1185
|
+
* v0.7.31; SDK consumers calling `Runner.run` on hand-authored Agents
|
|
1186
|
+
* are trusted by definition and skip admission).
|
|
1187
|
+
*
|
|
1188
|
+
* Pure delegation to `runAdmissionAudit` — invariants are resolved from
|
|
1189
|
+
* the shared module-scope registry (registered via
|
|
1190
|
+
* `registerCoreInvariants()` and the @kodax-ai/coding capability-coupled
|
|
1191
|
+
* invariants). The runtime stays sync (no I/O); `async` is reserved
|
|
1192
|
+
* for future versions that may need to consult external policy stores.
|
|
1193
|
+
*
|
|
1194
|
+
* @experimental
|
|
1195
|
+
*/
|
|
1196
|
+
static admit(manifest: AgentManifest, options?: AdmissionAuditOptions): Promise<AdmissionVerdict>;
|
|
1197
|
+
/**
|
|
1198
|
+
* Streaming variant. v0.7.23 emits a single `complete` event after
|
|
1199
|
+
* delegating to `run`; richer intermediate events land with FEATURE_084.
|
|
1200
|
+
*/
|
|
1201
|
+
static runStream<TData = unknown>(agent: Agent, input: string | readonly AgentMessage[], opts?: RunOptions): AsyncIterable<RunEvent<TData>>;
|
|
1202
|
+
}
|
|
1203
|
+
/** @internal Exposed so preset dispatchers can extract the assistant text from a KodaXResult. */
|
|
1204
|
+
declare function extractAssistantTextFromMessage(message: AgentMessage): string;
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* History cleanup middleware — CAP-002
|
|
1208
|
+
*
|
|
1209
|
+
* Capability inventory: docs/features/v0.7.29-capability-inventory.md#cap-002
|
|
1210
|
+
*
|
|
1211
|
+
* Two pure functions that maintain the assistant↔user `tool_use`/`tool_result`
|
|
1212
|
+
* pairing invariant the provider expects. Both functions take a message array
|
|
1213
|
+
* and return a new array (immutable — never mutate the input).
|
|
1214
|
+
*
|
|
1215
|
+
* - `cleanupIncompleteToolCalls`: when a stream is interrupted mid-flight,
|
|
1216
|
+
* the last assistant message may carry orphan `tool_use` blocks with no
|
|
1217
|
+
* matching `tool_result`. The next provider call would 400 with
|
|
1218
|
+
* "tool_call_id not found". This function strips those orphans before
|
|
1219
|
+
* the next request.
|
|
1220
|
+
*
|
|
1221
|
+
* - `validateAndFixToolHistory`: deeper pass that walks the full message
|
|
1222
|
+
* history and fixes mis-pairings on both sides — orphan `tool_use` in
|
|
1223
|
+
* assistant messages, orphan `tool_result` in user messages, and ensures
|
|
1224
|
+
* no message becomes empty after stripping (Kimi specifically rejects
|
|
1225
|
+
* empty assistant messages with 400, so we inject a `'...'` placeholder
|
|
1226
|
+
* when stripping would empty an assistant message).
|
|
1227
|
+
*
|
|
1228
|
+
* Migration history: extracted from `agent.ts` (originally lines 517–758)
|
|
1229
|
+
* during FEATURE_100 P2. Both `agent.ts` and `task-engine/runner-driven.ts`
|
|
1230
|
+
* already consume these via the package re-export (`@kodax-ai/coding`).
|
|
1231
|
+
*
|
|
1232
|
+
* Type guards are inlined here rather than imported from agent.ts because
|
|
1233
|
+
* the migration's whole point is to remove dependencies on agent.ts. If
|
|
1234
|
+
* additional agent-runtime modules need the same guards in the future,
|
|
1235
|
+
* extract them to `agent-runtime/content-blocks.ts`.
|
|
1236
|
+
*/
|
|
1237
|
+
|
|
1238
|
+
/**
|
|
1239
|
+
* Walk the message history and remove mis-paired `tool_use` / `tool_result`
|
|
1240
|
+
* blocks. Preserves message order and structure; never mutates input.
|
|
1241
|
+
*
|
|
1242
|
+
* Rules enforced:
|
|
1243
|
+
* - assistant `tool_use` with no matching `tool_result` in the next user
|
|
1244
|
+
* message → removed
|
|
1245
|
+
* - assistant `tool_use` with empty / missing id → removed
|
|
1246
|
+
* - user `tool_result` with no matching assistant `tool_use` in the previous
|
|
1247
|
+
* message → removed
|
|
1248
|
+
* - user `tool_result` with empty / missing tool_use_id → removed
|
|
1249
|
+
* - assistant message that becomes content-empty after stripping → inject
|
|
1250
|
+
* a `'...'` placeholder text block (preserves message-alternation invariant
|
|
1251
|
+
* downstream providers like Kimi require)
|
|
1252
|
+
*/
|
|
1253
|
+
declare function validateAndFixToolHistory(messages: KodaXMessage[]): KodaXMessage[];
|
|
1254
|
+
/**
|
|
1255
|
+
* Strip orphan `tool_use` blocks from the LAST assistant message only.
|
|
1256
|
+
*
|
|
1257
|
+
* Used as a quick pre-stream guard when a previous turn was interrupted
|
|
1258
|
+
* (Issue 072): the last assistant message has unanswered tool_use blocks,
|
|
1259
|
+
* and the next provider request would 400 with "tool_call_id not found".
|
|
1260
|
+
*
|
|
1261
|
+
* Cheaper than `validateAndFixToolHistory` because it only touches the tail.
|
|
1262
|
+
*/
|
|
1263
|
+
declare function cleanupIncompleteToolCalls(messages: KodaXMessage[]): KodaXMessage[];
|
|
1264
|
+
|
|
1265
|
+
export { cleanupIncompleteToolCalls as $, DEFAULT_SYSTEM_CAP as D, Runner as G, KODAX_API_MIN_INTERVAL as K, PROMISE_PATTERN as P, _resetPresetDispatchers as Y, buildSystemPrompt as Z, _resetAdmittedAgentBindings as _, countTokens as a0, createInMemorySession as a1, createInvariantSessionForAgent as a2, detectInstructionsInjection as a3, estimateTokens as a4, extractAssistantTextFromMessage as a5, getAdmittedAgentBindings as a6, registerPresetDispatcher as a7, runAdmissionAudit as a8, setAdmittedAgentBindings as a9, validateAndFixToolHistory as aa, DefaultSummaryCompaction as h, InvariantSession as m, KODAX_DEFAULT_TIMEOUT as n, KODAX_HARD_TIMEOUT as o, KODAX_MAX_INCOMPLETE_RETRIES as p, KODAX_MAX_MAXTOKENS_RETRIES as q, KODAX_MAX_RETRIES as r, KODAX_MAX_TOKENS as s, KODAX_RETRY_BASE_DELAY as t, KODAX_STAGGER_DELAY as u };
|
|
1266
|
+
export type { AdmissionAuditOptions as A, RunEvent as B, CompactionContext as C, RunOptions as E, RunResult as F, RunnerEvent as H, InMemorySessionOptions as I, SessionDispatchResult as J, SessionEntry as L, ManifestPatch as M, SessionExtension as N, ObserveCtx as O, QualityInvariant as Q, ReadonlyMutationTracker as R, Session as S, SessionForkOptions as T, SystemCap as U, TerminalCtx as V, ToolCapability as W, ToolPermission as X, AdmissionCtx as a, AdmissionVerdict as b, AdmittedHandle as c, AgentManifest as d, CompactionEntry as e, CompactionEntryPayload as f, CompactionPolicy as g, DefaultSummaryCompactionOptions as i, Deliverable as j, InvariantId as k, InvariantResult as l, MessageEntry as v, PolicyCompactionResult as w, PresetDispatcher as x, PresetTracingContext as y, ReadonlyRecorder as z };
|