@kiturone/kapibala 0.0.1
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/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/index.cjs +1940 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +636 -0
- package/dist/index.d.ts +636 -0
- package/dist/index.js +1872 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical Message & Event Types for Kapibala
|
|
3
|
+
*/
|
|
4
|
+
type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ThinkingBlock | RedactedThinkingBlock;
|
|
5
|
+
interface TextBlock {
|
|
6
|
+
type: 'text';
|
|
7
|
+
text: string;
|
|
8
|
+
}
|
|
9
|
+
interface ToolUseBlock {
|
|
10
|
+
type: 'tool_use';
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
input: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
interface ToolResultBlock {
|
|
16
|
+
type: 'tool_result';
|
|
17
|
+
toolUseId: string;
|
|
18
|
+
content: string;
|
|
19
|
+
isError?: boolean;
|
|
20
|
+
/** 单次工具调用总耗时,包含 tool hooks 与实际执行。 */
|
|
21
|
+
durationMs?: number;
|
|
22
|
+
}
|
|
23
|
+
interface ThinkingBlock {
|
|
24
|
+
type: 'thinking';
|
|
25
|
+
thinking: string;
|
|
26
|
+
signature?: string;
|
|
27
|
+
}
|
|
28
|
+
interface RedactedThinkingBlock {
|
|
29
|
+
type: 'redacted_thinking';
|
|
30
|
+
data: string;
|
|
31
|
+
}
|
|
32
|
+
interface Usage {
|
|
33
|
+
promptTokens: number;
|
|
34
|
+
completionTokens: number;
|
|
35
|
+
totalTokens: number;
|
|
36
|
+
}
|
|
37
|
+
type MessageRole = 'user' | 'assistant' | 'system' | 'tool';
|
|
38
|
+
interface CanonicalMessage {
|
|
39
|
+
role: MessageRole;
|
|
40
|
+
content: ContentBlock[];
|
|
41
|
+
timestamp?: number;
|
|
42
|
+
}
|
|
43
|
+
declare function isTextBlock(block: ContentBlock): block is TextBlock;
|
|
44
|
+
declare function isToolUseBlock(block: ContentBlock): block is ToolUseBlock;
|
|
45
|
+
declare function isToolResultBlock(block: ContentBlock): block is ToolResultBlock;
|
|
46
|
+
declare function isThinkingBlock(block: ContentBlock): block is ThinkingBlock;
|
|
47
|
+
interface TurnMetrics {
|
|
48
|
+
turn: number;
|
|
49
|
+
startTime: number;
|
|
50
|
+
endTime: number;
|
|
51
|
+
totalDurationMs: number;
|
|
52
|
+
ttftMs?: number;
|
|
53
|
+
modelDurationMs: number;
|
|
54
|
+
toolDurationMs: number;
|
|
55
|
+
promptTokens: number;
|
|
56
|
+
completionTokens: number;
|
|
57
|
+
totalTokens: number;
|
|
58
|
+
toolCallsCount: number;
|
|
59
|
+
}
|
|
60
|
+
interface RunMetrics {
|
|
61
|
+
startTime: number;
|
|
62
|
+
endTime: number;
|
|
63
|
+
totalDurationMs: number;
|
|
64
|
+
modelDurationMs: number;
|
|
65
|
+
toolDurationMs: number;
|
|
66
|
+
ttftMs?: number;
|
|
67
|
+
promptTokens: number;
|
|
68
|
+
completionTokens: number;
|
|
69
|
+
totalTokens: number;
|
|
70
|
+
turns: number;
|
|
71
|
+
toolCalls: number;
|
|
72
|
+
status: 'completed' | 'failed' | 'aborted';
|
|
73
|
+
/** 最近一次内部模型请求占用的上下文;不使用 run 累计 promptTokens。 */
|
|
74
|
+
contextUsage?: ContextUsage;
|
|
75
|
+
}
|
|
76
|
+
interface ContextUsage {
|
|
77
|
+
usedTokens?: number;
|
|
78
|
+
limitTokens: number;
|
|
79
|
+
percent?: number;
|
|
80
|
+
estimatedLimit: boolean;
|
|
81
|
+
}
|
|
82
|
+
type StepLogStage = 'model_request_start' | 'first_token' | 'model_stream_finish' | 'tool_execution_start' | 'tool_execution_finish' | 'turn_finish';
|
|
83
|
+
interface StepLogEntry {
|
|
84
|
+
timestamp: number;
|
|
85
|
+
turn: number;
|
|
86
|
+
stage: StepLogStage;
|
|
87
|
+
message: string;
|
|
88
|
+
durationMs?: number;
|
|
89
|
+
metadata?: Record<string, unknown>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* AgentSession 面向宿主输出的统一进程内事件契约。
|
|
93
|
+
*
|
|
94
|
+
* 事件只描述 Agent 语义,不携带终端颜色、组件状态或具体 UI 类型,因此 CLI、TUI、
|
|
95
|
+
* GUI 和 SDK 可以消费同一条事件流。跨进程或网络传输需要由宿主转换为独立的 wire DTO,
|
|
96
|
+
* 不应直接把本类型当作长期兼容的网络协议。
|
|
97
|
+
*/
|
|
98
|
+
type SessionEvent = {
|
|
99
|
+
type: 'turn_start';
|
|
100
|
+
turn: number;
|
|
101
|
+
} | {
|
|
102
|
+
type: 'step_log';
|
|
103
|
+
log: StepLogEntry;
|
|
104
|
+
} | {
|
|
105
|
+
type: 'text_delta';
|
|
106
|
+
text: string;
|
|
107
|
+
} | {
|
|
108
|
+
type: 'thinking_delta';
|
|
109
|
+
thinking: string;
|
|
110
|
+
} | {
|
|
111
|
+
type: 'tool_start';
|
|
112
|
+
id: string;
|
|
113
|
+
name: string;
|
|
114
|
+
input: Record<string, unknown>;
|
|
115
|
+
} | {
|
|
116
|
+
type: 'tool_finish';
|
|
117
|
+
id: string;
|
|
118
|
+
name: string;
|
|
119
|
+
result: string;
|
|
120
|
+
isError: boolean;
|
|
121
|
+
durationMs?: number;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 工具结果已完成 canonical 装配并写入历史。
|
|
125
|
+
* 消费方(SessionStore)据此落盘 —— 见设计文档 §4.4「tool:after 落一条 tool_result message」。
|
|
126
|
+
* 该事件在熔断/中断判定之前派发,保证任何终止路径下历史结构都合法(§4.3)。
|
|
127
|
+
*/
|
|
128
|
+
| {
|
|
129
|
+
type: 'tool_messages';
|
|
130
|
+
messages: CanonicalMessage[];
|
|
131
|
+
} | {
|
|
132
|
+
type: 'message_stop';
|
|
133
|
+
message: CanonicalMessage;
|
|
134
|
+
usage?: Usage;
|
|
135
|
+
ttftMs?: number;
|
|
136
|
+
durationMs?: number;
|
|
137
|
+
} | {
|
|
138
|
+
type: 'turn_finish';
|
|
139
|
+
turn: number;
|
|
140
|
+
usage?: Usage;
|
|
141
|
+
metrics: TurnMetrics;
|
|
142
|
+
} | {
|
|
143
|
+
type: 'run_finish';
|
|
144
|
+
metrics: RunMetrics;
|
|
145
|
+
} | {
|
|
146
|
+
type: 'error';
|
|
147
|
+
error: Error;
|
|
148
|
+
};
|
|
149
|
+
type ModelEvent = {
|
|
150
|
+
type: 'text_delta';
|
|
151
|
+
text: string;
|
|
152
|
+
} | {
|
|
153
|
+
type: 'thinking_delta';
|
|
154
|
+
thinking: string;
|
|
155
|
+
} | {
|
|
156
|
+
type: 'tool_call_start';
|
|
157
|
+
id: string;
|
|
158
|
+
name: string;
|
|
159
|
+
} | {
|
|
160
|
+
type: 'tool_call_delta';
|
|
161
|
+
id: string;
|
|
162
|
+
argumentChunk: string;
|
|
163
|
+
} | {
|
|
164
|
+
type: 'tool_call_finish';
|
|
165
|
+
id: string;
|
|
166
|
+
name: string;
|
|
167
|
+
input: Record<string, unknown>;
|
|
168
|
+
/** 参数 JSON 解析失败时置位,input 退化为 { _raw: '<原始字符串>' },便于上游诊断而非静默吞错 */
|
|
169
|
+
parseError?: boolean;
|
|
170
|
+
} | {
|
|
171
|
+
type: 'message_stop';
|
|
172
|
+
usage?: Usage;
|
|
173
|
+
ttftMs?: number;
|
|
174
|
+
durationMs?: number;
|
|
175
|
+
};
|
|
176
|
+
interface ToolDefinition {
|
|
177
|
+
name: string;
|
|
178
|
+
description: string;
|
|
179
|
+
parameters: Record<string, unknown>;
|
|
180
|
+
}
|
|
181
|
+
interface ModelRequest {
|
|
182
|
+
systemPrompt?: string;
|
|
183
|
+
messages: CanonicalMessage[];
|
|
184
|
+
tools?: ToolDefinition[];
|
|
185
|
+
signal?: AbortSignal;
|
|
186
|
+
temperature?: number;
|
|
187
|
+
maxTokens?: number;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Error Taxonomy for Kapibala Agent Harness
|
|
192
|
+
*/
|
|
193
|
+
declare class KapibalaError extends Error {
|
|
194
|
+
constructor(message: string);
|
|
195
|
+
}
|
|
196
|
+
declare class ModelError extends KapibalaError {
|
|
197
|
+
readonly status?: number;
|
|
198
|
+
readonly retryable: boolean;
|
|
199
|
+
constructor(message: string, options?: {
|
|
200
|
+
status?: number;
|
|
201
|
+
retryable?: boolean;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
declare class TransportError extends KapibalaError {
|
|
205
|
+
readonly retryable: boolean;
|
|
206
|
+
constructor(message: string, retryable?: boolean);
|
|
207
|
+
}
|
|
208
|
+
declare class ToolError extends KapibalaError {
|
|
209
|
+
constructor(message: string);
|
|
210
|
+
}
|
|
211
|
+
declare class ToolNotFound extends KapibalaError {
|
|
212
|
+
readonly toolName: string;
|
|
213
|
+
readonly availableTools: string[];
|
|
214
|
+
constructor(toolName: string, availableTools?: string[]);
|
|
215
|
+
}
|
|
216
|
+
declare class AbortError extends KapibalaError {
|
|
217
|
+
constructor(message?: string);
|
|
218
|
+
}
|
|
219
|
+
declare class FatalError extends KapibalaError {
|
|
220
|
+
constructor(message: string);
|
|
221
|
+
}
|
|
222
|
+
declare class SessionBusyError extends KapibalaError {
|
|
223
|
+
constructor(operation: string);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
interface SandboxConfig {
|
|
227
|
+
rootDir: string;
|
|
228
|
+
/**
|
|
229
|
+
* v0.0.1 恒为严格模式:任何解析后落在 rootDir 之外的物理路径一律拒绝,
|
|
230
|
+
* 不存在 fail-open 开关。该字段为 v0.0.2 权限引擎预留,当前不改变校验行为。
|
|
231
|
+
*/
|
|
232
|
+
allowSymlinks?: boolean;
|
|
233
|
+
}
|
|
234
|
+
declare class PathSandbox {
|
|
235
|
+
readonly rootDir: string;
|
|
236
|
+
readonly allowSymlinks: boolean;
|
|
237
|
+
private cachedRealRootDir?;
|
|
238
|
+
constructor(config: SandboxConfig);
|
|
239
|
+
/**
|
|
240
|
+
* rootDir 的物理路径。rootDir 自身可能是一个符号链接(如 macOS 的 /var → /private/var),
|
|
241
|
+
* 必须先归一化,否则物理路径与 rootDir 比较时会产生误判。
|
|
242
|
+
*/
|
|
243
|
+
private get realRootDir();
|
|
244
|
+
/**
|
|
245
|
+
* 检查并解析安全路径
|
|
246
|
+
* 1. 解析相对路径为相对于 rootDir 的绝对路径
|
|
247
|
+
* 2. 词法检查:`..` 归一化后必须仍在 rootDir 内
|
|
248
|
+
* 3. 物理检查:解析符号链接后的真实路径必须仍在 rootDir 内
|
|
249
|
+
*/
|
|
250
|
+
resolveSafePath(targetPath: string): string;
|
|
251
|
+
/**
|
|
252
|
+
* 把词法路径映射为物理路径。
|
|
253
|
+
*
|
|
254
|
+
* 关键点在于**向上回溯到最近一个真实存在的祖先**再取 realpath,然后把尚未存在的尾段拼回去:
|
|
255
|
+
* - 目标已存在 → 直接 realpath,符号链接立刻被展开;
|
|
256
|
+
* - 目标不存在(典型场景:write_file 新建文件) → 若只看目标本身,所有校验都会被跳过,
|
|
257
|
+
* 于是 `write_file('linkDir/new.txt')` 可以借道指向外部的 linkDir 越界写入。
|
|
258
|
+
* 回溯到 linkDir 取 realpath 即可识破这种穿透。
|
|
259
|
+
*/
|
|
260
|
+
private toPhysicalPath;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
type Capability = 'fs:read' | 'fs:write' | 'exec' | 'net:outbound' | 'env:read' | 'agent:spawn';
|
|
264
|
+
interface ToolMetadata {
|
|
265
|
+
source?: string;
|
|
266
|
+
dangerous?: boolean;
|
|
267
|
+
/** 所需能力的声明;v0.0.1 不据此授权,v0.0.2 的执行前权限决策才会消费。 */
|
|
268
|
+
permissions?: Capability[];
|
|
269
|
+
}
|
|
270
|
+
interface ToolContext {
|
|
271
|
+
rootDir: string;
|
|
272
|
+
signal?: AbortSignal;
|
|
273
|
+
logger?: (message: string) => void;
|
|
274
|
+
}
|
|
275
|
+
interface Tool<TInput = Record<string, unknown>, TOutput = unknown> {
|
|
276
|
+
readonly name: string;
|
|
277
|
+
readonly description: string;
|
|
278
|
+
readonly parameters: Record<string, unknown>;
|
|
279
|
+
readonly metadata?: ToolMetadata;
|
|
280
|
+
execute(input: TInput, ctx: ToolContext): Promise<TOutput>;
|
|
281
|
+
}
|
|
282
|
+
declare function defineTool<TInput = Record<string, unknown>, TOutput = unknown>(tool: Tool<TInput, TOutput>): Tool<TInput, TOutput>;
|
|
283
|
+
declare function toToolDefinition(tool: Tool): ToolDefinition;
|
|
284
|
+
|
|
285
|
+
type ConflictPolicy = 'error' | 'prefer-builtin' | 'prefer-last';
|
|
286
|
+
declare class ToolRegistry {
|
|
287
|
+
private readonly tools;
|
|
288
|
+
private readonly toolSources;
|
|
289
|
+
private readonly conflictPolicy;
|
|
290
|
+
constructor(options?: {
|
|
291
|
+
conflictPolicy?: ConflictPolicy;
|
|
292
|
+
});
|
|
293
|
+
register(tool: Tool, opts?: {
|
|
294
|
+
source?: string;
|
|
295
|
+
}): void;
|
|
296
|
+
registerSource(source: string, tools: Tool[]): void;
|
|
297
|
+
unregisterSource(source: string): void;
|
|
298
|
+
get(name: string): Tool | undefined;
|
|
299
|
+
resolve(name: string): Tool;
|
|
300
|
+
list(): Tool[];
|
|
301
|
+
definitions(): ToolDefinition[];
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
declare const readFileTool: Tool<{
|
|
305
|
+
path: string;
|
|
306
|
+
startLine?: number;
|
|
307
|
+
endLine?: number;
|
|
308
|
+
}, string>;
|
|
309
|
+
declare const writeFileTool: Tool<{
|
|
310
|
+
path: string;
|
|
311
|
+
content: string;
|
|
312
|
+
}, string>;
|
|
313
|
+
declare const editFileTool: Tool<{
|
|
314
|
+
path: string;
|
|
315
|
+
targetContent: string;
|
|
316
|
+
replacementContent: string;
|
|
317
|
+
}, string>;
|
|
318
|
+
declare const globTool: Tool<{
|
|
319
|
+
pattern: string;
|
|
320
|
+
subDirectory?: string;
|
|
321
|
+
}, string>;
|
|
322
|
+
declare const grepTool: Tool<{
|
|
323
|
+
pattern: string;
|
|
324
|
+
path?: string;
|
|
325
|
+
}, string>;
|
|
326
|
+
declare const builtinTools: (Tool<{
|
|
327
|
+
path: string;
|
|
328
|
+
startLine?: number;
|
|
329
|
+
endLine?: number;
|
|
330
|
+
}, string> | Tool<{
|
|
331
|
+
path: string;
|
|
332
|
+
content: string;
|
|
333
|
+
}, string> | Tool<{
|
|
334
|
+
path: string;
|
|
335
|
+
targetContent: string;
|
|
336
|
+
replacementContent: string;
|
|
337
|
+
}, string> | Tool<{
|
|
338
|
+
pattern: string;
|
|
339
|
+
subDirectory?: string;
|
|
340
|
+
}, string> | Tool<{
|
|
341
|
+
pattern: string;
|
|
342
|
+
path?: string;
|
|
343
|
+
}, string>)[];
|
|
344
|
+
|
|
345
|
+
type HookPoint = 'session:start' | 'session:end' | 'model:before' | 'model:after' | 'tool:before' | 'tool:after' | 'error';
|
|
346
|
+
interface HookContext {
|
|
347
|
+
readonly signal?: AbortSignal;
|
|
348
|
+
readonly logger?: (msg: string) => void;
|
|
349
|
+
}
|
|
350
|
+
type ToolDecision = {
|
|
351
|
+
action: 'continue';
|
|
352
|
+
} | {
|
|
353
|
+
action: 'skip';
|
|
354
|
+
result: string;
|
|
355
|
+
isError?: boolean;
|
|
356
|
+
} | {
|
|
357
|
+
action: 'modify';
|
|
358
|
+
input: Record<string, unknown>;
|
|
359
|
+
};
|
|
360
|
+
interface HookHandlers {
|
|
361
|
+
'session:start'?: (ctx: HookContext) => void | Promise<void>;
|
|
362
|
+
'session:end'?: (ctx: HookContext) => void | Promise<void>;
|
|
363
|
+
'model:before'?: (ctx: HookContext, req: ModelRequest) => ModelRequest | Promise<ModelRequest>;
|
|
364
|
+
'model:after'?: (ctx: HookContext, res: {
|
|
365
|
+
message: CanonicalMessage;
|
|
366
|
+
}) => void | Promise<void>;
|
|
367
|
+
'tool:before'?: (ctx: HookContext, call: {
|
|
368
|
+
id: string;
|
|
369
|
+
name: string;
|
|
370
|
+
input: Record<string, unknown>;
|
|
371
|
+
}) => ToolDecision | Promise<ToolDecision>;
|
|
372
|
+
'tool:after'?: (ctx: HookContext, call: {
|
|
373
|
+
id: string;
|
|
374
|
+
name: string;
|
|
375
|
+
input: Record<string, unknown>;
|
|
376
|
+
}, result: {
|
|
377
|
+
output: string;
|
|
378
|
+
isError: boolean;
|
|
379
|
+
}) => void | Promise<void>;
|
|
380
|
+
error?: (ctx: HookContext, err: Error) => void | Promise<void>;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
declare class HookRegistry {
|
|
384
|
+
private readonly hooks;
|
|
385
|
+
on<K extends HookPoint>(point: K, handler: NonNullable<HookHandlers[K]>): void;
|
|
386
|
+
get<K extends HookPoint>(point: K): Array<NonNullable<HookHandlers[K]>>;
|
|
387
|
+
emit<K extends 'session:start' | 'session:end' | 'model:after' | 'tool:after' | 'error'>(point: K, ctx: HookContext, ...args: any[]): Promise<void>;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
interface PluginContext {
|
|
391
|
+
readonly tools: ToolRegistry;
|
|
392
|
+
readonly hooks: HookRegistry;
|
|
393
|
+
readonly rootDir: string;
|
|
394
|
+
readonly logger?: (msg: string) => void;
|
|
395
|
+
}
|
|
396
|
+
interface AgentPlugin {
|
|
397
|
+
readonly name: string;
|
|
398
|
+
readonly version?: string;
|
|
399
|
+
setup(ctx: PluginContext): void | Promise<void>;
|
|
400
|
+
teardown?(): void | Promise<void>;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
interface ExecutorOptions {
|
|
404
|
+
tools: ToolRegistry;
|
|
405
|
+
hooks: HookRegistry;
|
|
406
|
+
rootDir: string;
|
|
407
|
+
signal?: AbortSignal;
|
|
408
|
+
logger?: (msg: string) => void;
|
|
409
|
+
/** 单次工具执行超时(毫秒)。异步挂起的工具超时后返回 isError 结果,避免永久卡死会话循环 */
|
|
410
|
+
toolTimeoutMs?: number;
|
|
411
|
+
}
|
|
412
|
+
declare class ToolExecutor {
|
|
413
|
+
private readonly tools;
|
|
414
|
+
private readonly hooks;
|
|
415
|
+
private readonly rootDir;
|
|
416
|
+
private readonly signal?;
|
|
417
|
+
private readonly logger?;
|
|
418
|
+
private readonly toolTimeoutMs;
|
|
419
|
+
constructor(options: ExecutorOptions);
|
|
420
|
+
runAll(calls: ToolUseBlock[]): Promise<ToolResultBlock[]>;
|
|
421
|
+
executeOne(call: ToolUseBlock): Promise<ToolResultBlock>;
|
|
422
|
+
/**
|
|
423
|
+
* 给工具执行加超时护栏:Promise.race 在超时后reject,循环拿到 isError 结果继续运转,
|
|
424
|
+
* 不会因某个异步工具(如未来接入的网络/exec 工具)挂起而永久卡死。
|
|
425
|
+
*
|
|
426
|
+
* 局限:同步 CPU 密集型实现会阻塞事件循环,timer 同样无法触发;
|
|
427
|
+
* 因此内置工具仍需避免执行用户可控的同步高复杂度计算。
|
|
428
|
+
*/
|
|
429
|
+
private withTimeout;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
type ModelRole = 'default' | 'planning' | 'execution' | 'summary' | 'fast';
|
|
433
|
+
type ContextWindowValue = number | `${number}${'K' | 'k' | 'M' | 'm'}`;
|
|
434
|
+
interface ResolvedContextWindow {
|
|
435
|
+
tokens: number;
|
|
436
|
+
/** true 表示模型未声明窗口,当前值来自 Kapibala 的默认估算。 */
|
|
437
|
+
estimated: boolean;
|
|
438
|
+
}
|
|
439
|
+
declare const DEFAULT_CONTEXT_WINDOW_TOKENS = 1000000;
|
|
440
|
+
/**
|
|
441
|
+
* 将模型上下文窗口统一解析为整数 Token 数。
|
|
442
|
+
*
|
|
443
|
+
* 配置允许直接填写整数,或使用十进制 K/M 简写;未填写时返回默认 1M,并标记为估算值。
|
|
444
|
+
*/
|
|
445
|
+
declare function resolveContextWindow(value?: ContextWindowValue): ResolvedContextWindow;
|
|
446
|
+
interface ModelProfile {
|
|
447
|
+
id: string;
|
|
448
|
+
name: string;
|
|
449
|
+
provider: 'openai-compatible';
|
|
450
|
+
baseURL: string;
|
|
451
|
+
apiKeyEnv: string;
|
|
452
|
+
apiKey?: string;
|
|
453
|
+
modelName: string;
|
|
454
|
+
contextWindow?: ContextWindowValue;
|
|
455
|
+
supportsThinking?: boolean;
|
|
456
|
+
}
|
|
457
|
+
interface ModelRouter {
|
|
458
|
+
resolve(role?: ModelRole): ModelProvider;
|
|
459
|
+
getProfile(role?: ModelRole): ModelProfile;
|
|
460
|
+
}
|
|
461
|
+
declare class SimpleModelRouter implements ModelRouter {
|
|
462
|
+
private readonly providers;
|
|
463
|
+
private readonly profiles;
|
|
464
|
+
private defaultRole;
|
|
465
|
+
constructor(defaultProfile: ModelProfile, defaultProvider: ModelProvider);
|
|
466
|
+
setRole(role: ModelRole, profile: ModelProfile, provider: ModelProvider): void;
|
|
467
|
+
resolve(role?: ModelRole): ModelProvider;
|
|
468
|
+
getProfile(role?: ModelRole): ModelProfile;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
interface ModelProvider {
|
|
472
|
+
readonly name: string;
|
|
473
|
+
create(req: ModelRequest): AsyncIterable<ModelEvent>;
|
|
474
|
+
/** 把一批工具结果装配成符合本协议的 canonical 消息序列 */
|
|
475
|
+
assembleToolResults(results: ToolResultBlock[]): CanonicalMessage[];
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
interface OpenAIProviderOptions {
|
|
479
|
+
baseURL: string;
|
|
480
|
+
apiKey: string;
|
|
481
|
+
modelName: string;
|
|
482
|
+
supportsThinking?: boolean;
|
|
483
|
+
/** 建立 HTTP 连接(收到响应头)的超时毫秒数;仅约束建连阶段,不限制流式读取总时长 */
|
|
484
|
+
connectTimeoutMs?: number;
|
|
485
|
+
}
|
|
486
|
+
declare class OpenAICompatibleProvider implements ModelProvider {
|
|
487
|
+
readonly name = "openai-compatible";
|
|
488
|
+
readonly baseURL: string;
|
|
489
|
+
readonly apiKey: string;
|
|
490
|
+
readonly modelName: string;
|
|
491
|
+
readonly supportsThinking: boolean;
|
|
492
|
+
readonly connectTimeoutMs: number;
|
|
493
|
+
constructor(options: OpenAIProviderOptions);
|
|
494
|
+
create(req: ModelRequest): AsyncIterable<ModelEvent>;
|
|
495
|
+
assembleToolResults(results: ToolResultBlock[]): CanonicalMessage[];
|
|
496
|
+
private translateMessagesToWire;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
declare class JSONLMessageStore implements MessageStore {
|
|
500
|
+
readonly filePath: string;
|
|
501
|
+
constructor(filePath: string);
|
|
502
|
+
append(message: CanonicalMessage): Promise<void>;
|
|
503
|
+
load(): Promise<CanonicalMessage[]>;
|
|
504
|
+
clear(): Promise<void>;
|
|
505
|
+
/**
|
|
506
|
+
* 历史自愈(设计文档 §4.4):逐条扫描 assistant 的 tool_use,
|
|
507
|
+
* 若其后的 tool 消息未完整覆盖这些 tool_use,就地补一条 is_error 的 tool_result。
|
|
508
|
+
*
|
|
509
|
+
* 之所以做**全历史扫描**而非只看末条:崩溃可能发生在任意一轮工具执行中途,
|
|
510
|
+
* 悬挂的 tool_use 未必位于历史末尾(例如中断后用户又继续提了问)。
|
|
511
|
+
* 只看末条会漏掉夹在中间的悬挂,下一次请求仍会因上下文非法而 400。
|
|
512
|
+
*/
|
|
513
|
+
private healDanglingToolCalls;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
interface MessageStore {
|
|
517
|
+
append(message: CanonicalMessage): Promise<void>;
|
|
518
|
+
load(): Promise<CanonicalMessage[]>;
|
|
519
|
+
clear(): Promise<void>;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
interface PromptAssemblerOptions {
|
|
523
|
+
tools?: ToolRegistry;
|
|
524
|
+
rootDir: string;
|
|
525
|
+
agentName?: string;
|
|
526
|
+
customInstructions?: string;
|
|
527
|
+
}
|
|
528
|
+
declare class PromptAssembler {
|
|
529
|
+
private readonly tools?;
|
|
530
|
+
private readonly rootDir;
|
|
531
|
+
private readonly agentName;
|
|
532
|
+
private readonly customInstructions?;
|
|
533
|
+
constructor(options: PromptAssemblerOptions);
|
|
534
|
+
assemble(): string;
|
|
535
|
+
private getL1Behavior;
|
|
536
|
+
private getL2Tools;
|
|
537
|
+
private getL3Environment;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
interface AgentLoopOptions {
|
|
541
|
+
provider: ModelProvider;
|
|
542
|
+
executor: ToolExecutor;
|
|
543
|
+
tools: ToolRegistry;
|
|
544
|
+
hooks: HookRegistry;
|
|
545
|
+
systemPrompt?: string;
|
|
546
|
+
maxSteps?: number;
|
|
547
|
+
maxConsecutiveErrors?: number;
|
|
548
|
+
signal?: AbortSignal;
|
|
549
|
+
}
|
|
550
|
+
declare class AgentLoop {
|
|
551
|
+
private readonly provider;
|
|
552
|
+
private readonly executor;
|
|
553
|
+
private readonly tools;
|
|
554
|
+
private readonly hooks;
|
|
555
|
+
private readonly systemPrompt?;
|
|
556
|
+
private readonly maxSteps;
|
|
557
|
+
private readonly maxConsecutiveErrors;
|
|
558
|
+
private readonly signal?;
|
|
559
|
+
constructor(options: AgentLoopOptions);
|
|
560
|
+
run(history: CanonicalMessage[]): AsyncIterable<SessionEvent>;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
interface SessionConfig {
|
|
564
|
+
defaultProfile: ModelProfile;
|
|
565
|
+
defaultProvider: ModelProvider;
|
|
566
|
+
store?: MessageStore;
|
|
567
|
+
rootDir?: string;
|
|
568
|
+
systemPrompt?: string;
|
|
569
|
+
maxSteps?: number;
|
|
570
|
+
logger?: (msg: string) => void;
|
|
571
|
+
}
|
|
572
|
+
interface SessionStats {
|
|
573
|
+
totalTurns: number;
|
|
574
|
+
totalTokens: Usage;
|
|
575
|
+
activeModel: string;
|
|
576
|
+
loadedToolsCount: number;
|
|
577
|
+
lastMetrics?: TurnMetrics;
|
|
578
|
+
lastRunMetrics?: RunMetrics;
|
|
579
|
+
contextUsage: ContextUsage;
|
|
580
|
+
}
|
|
581
|
+
declare class AgentSession {
|
|
582
|
+
readonly rootDir: string;
|
|
583
|
+
readonly tools: ToolRegistry;
|
|
584
|
+
readonly hooks: HookRegistry;
|
|
585
|
+
private readonly router;
|
|
586
|
+
private readonly store?;
|
|
587
|
+
private readonly customSystemPrompt?;
|
|
588
|
+
private readonly maxSteps;
|
|
589
|
+
private readonly logger?;
|
|
590
|
+
private history;
|
|
591
|
+
private totalTurns;
|
|
592
|
+
private usageStats;
|
|
593
|
+
private lastMetrics?;
|
|
594
|
+
private lastRunMetrics?;
|
|
595
|
+
private initialized;
|
|
596
|
+
private destroyed;
|
|
597
|
+
private activeRun;
|
|
598
|
+
private readonly plugins;
|
|
599
|
+
constructor(config: SessionConfig);
|
|
600
|
+
init(): Promise<void>;
|
|
601
|
+
use(plugin: AgentPlugin): Promise<void>;
|
|
602
|
+
switchModel(profile: ModelProfile, role?: ModelRole, provider?: ModelProvider): void;
|
|
603
|
+
getActiveProfile(role?: ModelRole): ModelProfile;
|
|
604
|
+
getHistory(): CanonicalMessage[];
|
|
605
|
+
getStats(): SessionStats;
|
|
606
|
+
getLastMetrics(): TurnMetrics | undefined;
|
|
607
|
+
getLastRunMetrics(): RunMetrics | undefined;
|
|
608
|
+
reset(): Promise<void>;
|
|
609
|
+
/**
|
|
610
|
+
* 执行一次用户输入,并以宿主无关的语义事件流返回全过程。
|
|
611
|
+
*
|
|
612
|
+
* Core 不负责终端或图形界面渲染;CLI、TUI、GUI 与其它宿主应消费同一组
|
|
613
|
+
* {@link SessionEvent},分别完成展示、交互和中止控制。
|
|
614
|
+
*
|
|
615
|
+
* @param userInput 用户本轮输入。
|
|
616
|
+
* @param options 可选的中止信号。
|
|
617
|
+
* @returns 文本、思考、工具、指标和错误等结构化事件的异步流。
|
|
618
|
+
* @throws {SessionBusyError} 当前会话已有正在执行的 run 时抛出。
|
|
619
|
+
*/
|
|
620
|
+
run(userInput: string, options?: {
|
|
621
|
+
signal?: AbortSignal;
|
|
622
|
+
}): AsyncIterable<SessionEvent>;
|
|
623
|
+
destroy(): Promise<void>;
|
|
624
|
+
private assertIdle;
|
|
625
|
+
/**
|
|
626
|
+
* 计算最近一次内部模型请求的上下文占用。
|
|
627
|
+
* run 累计 promptTokens 会重复计算每一步都重发的历史,不能用于窗口占用率。
|
|
628
|
+
*/
|
|
629
|
+
private createContextUsage;
|
|
630
|
+
private persistAssistant;
|
|
631
|
+
private persistToolMessages;
|
|
632
|
+
private closeInterruptedToolCalls;
|
|
633
|
+
private findClosedToolMessages;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export { AbortError, AgentLoop, type AgentLoopOptions, type AgentPlugin, AgentSession, type CanonicalMessage, type Capability, type ConflictPolicy, type ContentBlock, type ContextUsage, type ContextWindowValue, DEFAULT_CONTEXT_WINDOW_TOKENS, type ExecutorOptions, FatalError, type HookContext, type HookHandlers, type HookPoint, HookRegistry, JSONLMessageStore, KapibalaError, type MessageRole, type MessageStore, ModelError, type ModelEvent, type ModelProfile, type ModelProvider, type ModelRequest, type ModelRole, type ModelRouter, OpenAICompatibleProvider, type OpenAIProviderOptions, PathSandbox, type PluginContext, PromptAssembler, type PromptAssemblerOptions, type RedactedThinkingBlock, type ResolvedContextWindow, type RunMetrics, type SandboxConfig, SessionBusyError, type SessionConfig, type SessionEvent, type SessionStats, SimpleModelRouter, type StepLogEntry, type StepLogStage, type TextBlock, type ThinkingBlock, type Tool, type ToolContext, type ToolDecision, type ToolDefinition, ToolError, ToolExecutor, type ToolMetadata, ToolNotFound, ToolRegistry, type ToolResultBlock, type ToolUseBlock, TransportError, type TurnMetrics, type Usage, builtinTools, defineTool, editFileTool, globTool, grepTool, isTextBlock, isThinkingBlock, isToolResultBlock, isToolUseBlock, readFileTool, resolveContextWindow, toToolDefinition, writeFileTool };
|