@yachiyo-5i/xlyra-agent 0.2.0
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 +661 -0
- package/README.md +306 -0
- package/dist/chunk-QH6SEOO6.js +3590 -0
- package/dist/chunk-QH6SEOO6.js.map +1 -0
- package/dist/cli.cjs +3833 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +287 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +3703 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1171 -0
- package/dist/index.d.ts +1171 -0
- package/dist/index.js +145 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1171 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Hono } from 'hono';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 内部规范模型 —— 协议无关的对话数据表达。
|
|
6
|
+
*
|
|
7
|
+
* 分层定位:llm/protocols/ 下的两个适配器(OpenAI Responses / Anthropic
|
|
8
|
+
* Messages)负责把各自 wire 格式翻译成这里的模型;agent 层(runner/压缩/
|
|
9
|
+
* 工具)永远只面对本文件定义的结构,不感知任何协议细节。
|
|
10
|
+
*
|
|
11
|
+
* 设计要点:
|
|
12
|
+
* - ToolCall 始终保留 raw_arguments 原文(字符串),parse 发生在使用方——
|
|
13
|
+
* 流式分片期间参数是不完整 JSON,只有归并完成后才可能解析成功;
|
|
14
|
+
* - ChatMessage 带 thinking / thinking_signature:Anthropic 多轮工具往返
|
|
15
|
+
* 要求带签名的 thinking block 原样回喂(评审定案透传),无签名的旧消息
|
|
16
|
+
* 回喂时整块省略(API 允许);
|
|
17
|
+
* - tool 角色的 is_error:Anthropic tool_result block 需要显式标注失败。
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
declare const toolCallSchema: z.ZodObject<{
|
|
21
|
+
id: z.ZodString;
|
|
22
|
+
name: z.ZodString;
|
|
23
|
+
raw_arguments: z.ZodString;
|
|
24
|
+
}, z.core.$strip>;
|
|
25
|
+
type ToolCall = z.infer<typeof toolCallSchema>;
|
|
26
|
+
declare const chatMessageSchema: z.ZodObject<{
|
|
27
|
+
role: z.ZodEnum<{
|
|
28
|
+
system: "system";
|
|
29
|
+
user: "user";
|
|
30
|
+
assistant: "assistant";
|
|
31
|
+
tool: "tool";
|
|
32
|
+
}>;
|
|
33
|
+
content: z.ZodDefault<z.ZodString>;
|
|
34
|
+
tool_calls: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
35
|
+
id: z.ZodString;
|
|
36
|
+
name: z.ZodString;
|
|
37
|
+
raw_arguments: z.ZodString;
|
|
38
|
+
}, z.core.$strip>>>;
|
|
39
|
+
tool_call_id: z.ZodOptional<z.ZodString>;
|
|
40
|
+
name: z.ZodOptional<z.ZodString>;
|
|
41
|
+
is_error: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
thinking: z.ZodOptional<z.ZodString>;
|
|
43
|
+
thinking_signature: z.ZodOptional<z.ZodString>;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
type ChatMessage = z.infer<typeof chatMessageSchema>;
|
|
46
|
+
/** 消息正文文本(当前为纯文本管线,直接返回 content;保留函数形态便于将来多模态扩展) */
|
|
47
|
+
declare function messageText(message: ChatMessage): string;
|
|
48
|
+
declare const tokenUsageSchema: z.ZodObject<{
|
|
49
|
+
prompt_tokens: z.ZodDefault<z.ZodNumber>;
|
|
50
|
+
completion_tokens: z.ZodDefault<z.ZodNumber>;
|
|
51
|
+
total_tokens: z.ZodDefault<z.ZodNumber>;
|
|
52
|
+
cache_read_tokens: z.ZodDefault<z.ZodNumber>;
|
|
53
|
+
}, z.core.$strip>;
|
|
54
|
+
type TokenUsage = z.infer<typeof tokenUsageSchema>;
|
|
55
|
+
declare function emptyUsage(): TokenUsage;
|
|
56
|
+
declare function addUsage(total: TokenUsage, step: TokenUsage): TokenUsage;
|
|
57
|
+
declare const modelSettingsSchema: z.ZodObject<{
|
|
58
|
+
temperature: z.ZodOptional<z.ZodNumber>;
|
|
59
|
+
max_tokens: z.ZodOptional<z.ZodNumber>;
|
|
60
|
+
reasoning_effort: z.ZodOptional<z.ZodEnum<{
|
|
61
|
+
low: "low";
|
|
62
|
+
medium: "medium";
|
|
63
|
+
high: "high";
|
|
64
|
+
}>>;
|
|
65
|
+
}, z.core.$strip>;
|
|
66
|
+
type ModelSettings = z.infer<typeof modelSettingsSchema>;
|
|
67
|
+
/** 暴露给模型的工具声明(parameters 为 JSON Schema object) */
|
|
68
|
+
interface ToolDefinition {
|
|
69
|
+
name: string;
|
|
70
|
+
description: string;
|
|
71
|
+
parameters: Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
/** 一次模型调用的定稿响应(done 事件的载荷) */
|
|
74
|
+
interface ChatResponse {
|
|
75
|
+
content: string;
|
|
76
|
+
thinking: string | null;
|
|
77
|
+
thinking_signature: string | null;
|
|
78
|
+
tool_calls: ToolCall[];
|
|
79
|
+
usage: TokenUsage;
|
|
80
|
+
finish_reason: string | null;
|
|
81
|
+
model: string;
|
|
82
|
+
provider: string;
|
|
83
|
+
}
|
|
84
|
+
/** 定稿响应 → 入对话历史的 assistant 消息(思考链与签名随消息保存,供历史回喂) */
|
|
85
|
+
declare function responseToMessage(response: ChatResponse): ChatMessage;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 协议接口 —— llm 层对上游(agent 层)的唯一契约。
|
|
89
|
+
*
|
|
90
|
+
* 契约约束(两个适配器都必须满足):
|
|
91
|
+
* 1. 错误以 error 事件收尾,不抛异常(网络错误、HTTP 非 2xx、流中断同约定);
|
|
92
|
+
* 2. 每条流恰好一个终态(done 或 error),永不静默结束;
|
|
93
|
+
* 3. toolcall_start 在工具名称确定的第一刻发出;toolcall_end 时
|
|
94
|
+
* raw_arguments 为累积全量;
|
|
95
|
+
* 4. done 携带完整 ChatResponse(content/thinking/tool_calls/usage/...)。
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
interface ChatRequest {
|
|
99
|
+
/** 端点内的模型 id(路由解析后的值,不含端点前缀) */
|
|
100
|
+
model: string;
|
|
101
|
+
messages: ChatMessage[];
|
|
102
|
+
tools?: ToolDefinition[];
|
|
103
|
+
settings: ModelSettings;
|
|
104
|
+
/** 外部取消信号:触发后适配器尽快终止流并静默结束(终态事件由编排层负责) */
|
|
105
|
+
signal?: AbortSignal;
|
|
106
|
+
}
|
|
107
|
+
type StreamEvent = {
|
|
108
|
+
type: "thinking_delta";
|
|
109
|
+
delta: string;
|
|
110
|
+
} | {
|
|
111
|
+
type: "text_delta";
|
|
112
|
+
delta: string;
|
|
113
|
+
}
|
|
114
|
+
/** 名称已确定,参数开始生成(tool_call 仅含 id/name) */
|
|
115
|
+
| {
|
|
116
|
+
type: "toolcall_start";
|
|
117
|
+
tool_call: ToolCall;
|
|
118
|
+
}
|
|
119
|
+
/** 参数 JSON 逐片增量 */
|
|
120
|
+
| {
|
|
121
|
+
type: "toolcall_delta";
|
|
122
|
+
tool_call: ToolCall;
|
|
123
|
+
delta: string;
|
|
124
|
+
}
|
|
125
|
+
/** 参数已完整(raw_arguments 为全量) */
|
|
126
|
+
| {
|
|
127
|
+
type: "toolcall_end";
|
|
128
|
+
tool_call: ToolCall;
|
|
129
|
+
} | {
|
|
130
|
+
type: "done";
|
|
131
|
+
response: ChatResponse;
|
|
132
|
+
} | {
|
|
133
|
+
type: "error";
|
|
134
|
+
error: string;
|
|
135
|
+
};
|
|
136
|
+
interface LlmProtocol {
|
|
137
|
+
/** 协议标识:"openai-responses" | "anthropic-messages" */
|
|
138
|
+
readonly name: string;
|
|
139
|
+
chatStream(req: ChatRequest): AsyncIterable<StreamEvent>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* LLM 层错误:路由解析失败(没配端点/模型不存在)等**调用前**错误抛出;
|
|
144
|
+
* 调用中的流错误一律走 StreamEvent error 事件,不抛异常。
|
|
145
|
+
*/
|
|
146
|
+
declare class LlmError extends Error {
|
|
147
|
+
constructor(message: string);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
interface EndpointConfig {
|
|
151
|
+
name: string;
|
|
152
|
+
protocol: "openai-responses" | "anthropic-messages";
|
|
153
|
+
base_url: string;
|
|
154
|
+
api_key: string;
|
|
155
|
+
/** 可用模型表:key 为模型 id;context_window 可选 */
|
|
156
|
+
models?: Record<string, {
|
|
157
|
+
context_window?: number;
|
|
158
|
+
}>;
|
|
159
|
+
default_model?: string;
|
|
160
|
+
}
|
|
161
|
+
interface ResolvedModel {
|
|
162
|
+
endpoint: EndpointConfig;
|
|
163
|
+
protocol: LlmProtocol;
|
|
164
|
+
/** 端点内的模型 id(已剥离端点前缀) */
|
|
165
|
+
modelId: string;
|
|
166
|
+
contextWindow: number | undefined;
|
|
167
|
+
}
|
|
168
|
+
declare function builtinContextWindow(modelId: string): number | undefined;
|
|
169
|
+
declare class EndpointResolver {
|
|
170
|
+
private readonly endpoints;
|
|
171
|
+
private readonly protocols;
|
|
172
|
+
constructor(endpoints: EndpointConfig[]);
|
|
173
|
+
resolve(model: string): ResolvedModel;
|
|
174
|
+
private protocolFor;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 极简 SSE 解析器 —— 两套协议适配器共用。
|
|
179
|
+
*
|
|
180
|
+
* 覆盖 SSE 规范的常用子集:`event:` / 多行 `data:` 拼接 / `: comment`
|
|
181
|
+
* 心跳行 / \r\n 与 \n 换行 / OpenAI 的 `data: [DONE]` 哨兵。
|
|
182
|
+
* 不依赖任何第三方库;输入是 fetch 响应的 body 流。
|
|
183
|
+
*/
|
|
184
|
+
interface SseEvent {
|
|
185
|
+
/** event 字段值;缺省为空串(OpenAI 系协议通常不写 event,靠 data 里的 type) */
|
|
186
|
+
event: string;
|
|
187
|
+
/** 多行 data 已按规范以 \n 拼接 */
|
|
188
|
+
data: string;
|
|
189
|
+
}
|
|
190
|
+
declare function parseSse(body: ReadableStream<Uint8Array>): AsyncGenerator<SseEvent>;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 流式 tool_call 归并器 —— 两个协议适配器共用。
|
|
194
|
+
*
|
|
195
|
+
* 两套协议的参数都是逐片增量(Responses 的 function_call_arguments.delta /
|
|
196
|
+
* Anthropic 的 input_json_delta),适配器以各自的归并键(item_id / block
|
|
197
|
+
* index)调用本类累积,end 时得到 raw_arguments 全量。
|
|
198
|
+
*
|
|
199
|
+
* 刻意不在增量阶段做 partial parse(避免 O(n²) 重复解析);end 时的
|
|
200
|
+
* JSON.parse 失败也不报错——raw_arguments 保留原文,由 runner 的参数
|
|
201
|
+
* 校验阶段统一报错回喂模型。
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
declare class ToolCallBuffer {
|
|
205
|
+
private readonly buffers;
|
|
206
|
+
/** 名称确定的第一刻登记;返回仅含 id/name 的 ToolCall(供 toolcall_start 事件) */
|
|
207
|
+
start(key: string, id: string, name: string): ToolCall;
|
|
208
|
+
/** 追加参数分片;返回当前快照(供 toolcall_delta 事件携带归属信息) */
|
|
209
|
+
append(key: string, delta: string): ToolCall | null;
|
|
210
|
+
/** 结束归并;fullRaw 提供时以全量为准(Responses 的 .done 事件自带全量串) */
|
|
211
|
+
finish(key: string, fullRaw?: string): ToolCall | null;
|
|
212
|
+
/** 流异常终止时丢弃全部未完成归并 */
|
|
213
|
+
clear(): void;
|
|
214
|
+
get pendingCount(): number;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* 工具参数校验 —— 调用前对 raw_arguments 做 JSON Schema 校验。
|
|
219
|
+
*
|
|
220
|
+
* 覆盖我们工具声明用到的 JSON Schema 子集(object / properties / required /
|
|
221
|
+
* string / number / integer / boolean / array / enum / default),不引 ajv:
|
|
222
|
+
* 我们的 schema 全部来自自家工具的 Zod 定义,结构可控。将来支持外部工具
|
|
223
|
+
* 声明时,可在此替换为完整 JSON Schema 校验器,接口不变。
|
|
224
|
+
*
|
|
225
|
+
* 校验失败返回中文错误文本(喂回模型自行修正),不抛异常。
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
interface ValidatedArgs {
|
|
229
|
+
args: Record<string, unknown> | null;
|
|
230
|
+
error: string | null;
|
|
231
|
+
}
|
|
232
|
+
declare function validateToolCall(definitions: ToolDefinition[], call: ToolCall): ValidatedArgs;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* OpenAI Responses API 适配器。
|
|
236
|
+
*
|
|
237
|
+
* 按官方文档实现(https://platform.openai.com/docs/api-reference/responses-streaming):
|
|
238
|
+
* - 请求:POST {base_url}/responses,system → instructions,历史 → input items
|
|
239
|
+
* (message / function_call / function_call_output),stream: true;
|
|
240
|
+
* - 流式:tool_call 以 output_item.added(function_call) 确定 id/name,
|
|
241
|
+
* function_call_arguments.delta 逐片累积、.done 给全量;
|
|
242
|
+
* response.completed / failed / incomplete 为终态。
|
|
243
|
+
*
|
|
244
|
+
* 终态怪癖处理(继承 MovieClaw 兼容层经验):
|
|
245
|
+
* - response.incomplete:已累积出完整 tool_calls 时按 done 处理(让循环继续),
|
|
246
|
+
* 否则报 error;
|
|
247
|
+
* - 流中途断开(无终态事件)→ error,不静默。
|
|
248
|
+
*/
|
|
249
|
+
|
|
250
|
+
interface ResponsesEndpointOptions {
|
|
251
|
+
baseUrl: string;
|
|
252
|
+
apiKey: string;
|
|
253
|
+
/** 展示与日志用的端点名 */
|
|
254
|
+
providerName?: string;
|
|
255
|
+
/** 测试注入用;默认全局 fetch */
|
|
256
|
+
fetchImpl?: typeof fetch;
|
|
257
|
+
}
|
|
258
|
+
declare class OpenAIResponsesProtocol implements LlmProtocol {
|
|
259
|
+
readonly name = "openai-responses";
|
|
260
|
+
private readonly baseUrl;
|
|
261
|
+
private readonly apiKey;
|
|
262
|
+
private readonly provider;
|
|
263
|
+
private readonly fetchImpl;
|
|
264
|
+
constructor(opts: ResponsesEndpointOptions);
|
|
265
|
+
chatStream(req: ChatRequest): AsyncIterable<StreamEvent>;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Anthropic Messages API 适配器。
|
|
270
|
+
*
|
|
271
|
+
* 按官方文档实现(https://docs.claude.com/en/api/messages-streaming):
|
|
272
|
+
* - 请求:POST {base_url}/v1/messages,system 是顶层字段;assistant 的
|
|
273
|
+
* tool_calls → tool_use content blocks;tool 结果并入 user 消息的
|
|
274
|
+
* tool_result blocks;max_tokens 必填;
|
|
275
|
+
* - 流式:content_block 状态机按 block index 归并;input_json_delta
|
|
276
|
+
* 累积到 content_block_stop 才 parse(避免每片 partial parse 的 O(n²));
|
|
277
|
+
* signature_delta 必须采集——评审定案 thinking 签名透传进历史,
|
|
278
|
+
* 多轮工具往返要求带签名的 thinking block 原样回喂。
|
|
279
|
+
*
|
|
280
|
+
* 实现纪律(来自公开 issue 的已知坑):
|
|
281
|
+
* - delta 类型与当前 block 类型不符 → 按流损坏处理,error 事件收尾,不猜;
|
|
282
|
+
* - tool_result 必须与此前 assistant 的 tool_use 严格配对(runner 保证),
|
|
283
|
+
* 否则 API 400。
|
|
284
|
+
*/
|
|
285
|
+
|
|
286
|
+
interface MessagesEndpointOptions {
|
|
287
|
+
baseUrl: string;
|
|
288
|
+
apiKey: string;
|
|
289
|
+
providerName?: string;
|
|
290
|
+
/** anthropic-version 头;默认官方当前版本 */
|
|
291
|
+
apiVersion?: string;
|
|
292
|
+
/** 测试注入用;默认全局 fetch */
|
|
293
|
+
fetchImpl?: typeof fetch;
|
|
294
|
+
}
|
|
295
|
+
declare class AnthropicMessagesProtocol implements LlmProtocol {
|
|
296
|
+
readonly name = "anthropic-messages";
|
|
297
|
+
private readonly baseUrl;
|
|
298
|
+
private readonly apiKey;
|
|
299
|
+
private readonly provider;
|
|
300
|
+
private readonly apiVersion;
|
|
301
|
+
private readonly fetchImpl;
|
|
302
|
+
constructor(opts: MessagesEndpointOptions);
|
|
303
|
+
chatStream(req: ChatRequest): AsyncIterable<StreamEvent>;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Agent 执行过程的事件协议 —— 前后端之间的「执行进度语言」。
|
|
308
|
+
*
|
|
309
|
+
* 设计原则(移植自 MovieClaw,对齐 pi 的 agent 事件思路):
|
|
310
|
+
* 1. 事件类型面向「渲染语义」而非模型协议:调用方拿到事件就知道往哪个区域
|
|
311
|
+
* 画什么,不需要理解底层 LLM 流的细节;
|
|
312
|
+
* 2. 增量事件(*_delta)负责打字机效果,结束事件(agent_done)带完整结果,
|
|
313
|
+
* 断线重连/中途加入也能靠终态恢复;
|
|
314
|
+
* 3. 工具调用三段式:名称确定即发 tool_call_start,参数逐片发 tool_call_delta,
|
|
315
|
+
* 参数完整后发 tool_call——调用方从名称确定的一刻起就能展示进度。
|
|
316
|
+
*
|
|
317
|
+
* 事件序列(每一步 = 一次模型调用):
|
|
318
|
+
* agent_start → [ (thinking_delta|text_delta)*
|
|
319
|
+
* → (tool_call_start → tool_call_delta* → tool_call)*
|
|
320
|
+
* → tool_result* ]×N
|
|
321
|
+
* → agent_done | agent_error | agent_cancelled
|
|
322
|
+
* (任意安全点可插 context_compacted)
|
|
323
|
+
*/
|
|
324
|
+
|
|
325
|
+
declare const agentStartParamsSchema: z.ZodObject<{
|
|
326
|
+
input: z.ZodString;
|
|
327
|
+
include_input: z.ZodDefault<z.ZodBoolean>;
|
|
328
|
+
history: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
329
|
+
role: z.ZodEnum<{
|
|
330
|
+
system: "system";
|
|
331
|
+
user: "user";
|
|
332
|
+
assistant: "assistant";
|
|
333
|
+
tool: "tool";
|
|
334
|
+
}>;
|
|
335
|
+
content: z.ZodDefault<z.ZodString>;
|
|
336
|
+
tool_calls: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
337
|
+
id: z.ZodString;
|
|
338
|
+
name: z.ZodString;
|
|
339
|
+
raw_arguments: z.ZodString;
|
|
340
|
+
}, z.core.$strip>>>;
|
|
341
|
+
tool_call_id: z.ZodOptional<z.ZodString>;
|
|
342
|
+
name: z.ZodOptional<z.ZodString>;
|
|
343
|
+
is_error: z.ZodOptional<z.ZodBoolean>;
|
|
344
|
+
thinking: z.ZodOptional<z.ZodString>;
|
|
345
|
+
thinking_signature: z.ZodOptional<z.ZodString>;
|
|
346
|
+
}, z.core.$strip>>>;
|
|
347
|
+
model: z.ZodDefault<z.ZodString>;
|
|
348
|
+
system_prompt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
349
|
+
settings: z.ZodDefault<z.ZodObject<{
|
|
350
|
+
temperature: z.ZodOptional<z.ZodNumber>;
|
|
351
|
+
max_tokens: z.ZodOptional<z.ZodNumber>;
|
|
352
|
+
reasoning_effort: z.ZodOptional<z.ZodEnum<{
|
|
353
|
+
low: "low";
|
|
354
|
+
medium: "medium";
|
|
355
|
+
high: "high";
|
|
356
|
+
}>>;
|
|
357
|
+
}, z.core.$strip>>;
|
|
358
|
+
}, z.core.$strip>;
|
|
359
|
+
type AgentStartParams = z.input<typeof agentStartParamsSchema>;
|
|
360
|
+
declare const agentToolResultSchema: z.ZodObject<{
|
|
361
|
+
tool_call_id: z.ZodString;
|
|
362
|
+
name: z.ZodString;
|
|
363
|
+
output: z.ZodString;
|
|
364
|
+
is_error: z.ZodDefault<z.ZodBoolean>;
|
|
365
|
+
elapsed_ms: z.ZodDefault<z.ZodNumber>;
|
|
366
|
+
}, z.core.$strip>;
|
|
367
|
+
type AgentToolResult = z.infer<typeof agentToolResultSchema>;
|
|
368
|
+
declare const agentCompactionSchema: z.ZodObject<{
|
|
369
|
+
summary: z.ZodString;
|
|
370
|
+
tokens_before: z.ZodNumber;
|
|
371
|
+
tokens_after: z.ZodNumber;
|
|
372
|
+
}, z.core.$strip>;
|
|
373
|
+
type AgentCompaction = z.infer<typeof agentCompactionSchema>;
|
|
374
|
+
/** 提权请求(escalation_request 事件载荷):工具访问越界路径时发起,
|
|
375
|
+
* 前端展示并等待用户确认;确认后服务端登记授权并重发消息续跑 */
|
|
376
|
+
declare const agentEscalationSchema: z.ZodObject<{
|
|
377
|
+
escalation_id: z.ZodString;
|
|
378
|
+
requested_path: z.ZodString;
|
|
379
|
+
resolved_path: z.ZodString;
|
|
380
|
+
tool_name: z.ZodString;
|
|
381
|
+
resource_type: z.ZodDefault<z.ZodEnum<{
|
|
382
|
+
path: "path";
|
|
383
|
+
command: "command";
|
|
384
|
+
}>>;
|
|
385
|
+
requested_command: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
386
|
+
workdir: z.ZodString;
|
|
387
|
+
}, z.core.$strip>;
|
|
388
|
+
type AgentEscalation = z.infer<typeof agentEscalationSchema>;
|
|
389
|
+
declare const agentDoneSchema: z.ZodObject<{
|
|
390
|
+
text: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
391
|
+
thinking: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
392
|
+
finish_reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
393
|
+
usage: z.ZodDefault<z.ZodObject<{
|
|
394
|
+
prompt_tokens: z.ZodDefault<z.ZodNumber>;
|
|
395
|
+
completion_tokens: z.ZodDefault<z.ZodNumber>;
|
|
396
|
+
total_tokens: z.ZodDefault<z.ZodNumber>;
|
|
397
|
+
cache_read_tokens: z.ZodDefault<z.ZodNumber>;
|
|
398
|
+
}, z.core.$strip>>;
|
|
399
|
+
steps: z.ZodDefault<z.ZodNumber>;
|
|
400
|
+
model: z.ZodDefault<z.ZodString>;
|
|
401
|
+
provider: z.ZodDefault<z.ZodString>;
|
|
402
|
+
elapsed_ms: z.ZodDefault<z.ZodNumber>;
|
|
403
|
+
}, z.core.$strip>;
|
|
404
|
+
type AgentDone = z.infer<typeof agentDoneSchema>;
|
|
405
|
+
/** Agent 事件:type 决定哪些字段有值;作为 SSE 载荷时 type 同时用作 SSE 的 event 名 */
|
|
406
|
+
declare const agentEventSchema: z.ZodObject<{
|
|
407
|
+
type: z.ZodEnum<{
|
|
408
|
+
thinking_delta: "thinking_delta";
|
|
409
|
+
text_delta: "text_delta";
|
|
410
|
+
tool_result: "tool_result";
|
|
411
|
+
tool_call: "tool_call";
|
|
412
|
+
agent_start: "agent_start";
|
|
413
|
+
tool_call_start: "tool_call_start";
|
|
414
|
+
tool_call_delta: "tool_call_delta";
|
|
415
|
+
context_compacted: "context_compacted";
|
|
416
|
+
escalation_request: "escalation_request";
|
|
417
|
+
agent_done: "agent_done";
|
|
418
|
+
agent_error: "agent_error";
|
|
419
|
+
agent_cancelled: "agent_cancelled";
|
|
420
|
+
}>;
|
|
421
|
+
run_id: z.ZodString;
|
|
422
|
+
delta: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
423
|
+
tool_call: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
424
|
+
id: z.ZodString;
|
|
425
|
+
name: z.ZodString;
|
|
426
|
+
raw_arguments: z.ZodString;
|
|
427
|
+
}, z.core.$strip>>>;
|
|
428
|
+
tool_call_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
429
|
+
tool_result: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
430
|
+
tool_call_id: z.ZodString;
|
|
431
|
+
name: z.ZodString;
|
|
432
|
+
output: z.ZodString;
|
|
433
|
+
is_error: z.ZodDefault<z.ZodBoolean>;
|
|
434
|
+
elapsed_ms: z.ZodDefault<z.ZodNumber>;
|
|
435
|
+
}, z.core.$strip>>>;
|
|
436
|
+
compaction: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
437
|
+
summary: z.ZodString;
|
|
438
|
+
tokens_before: z.ZodNumber;
|
|
439
|
+
tokens_after: z.ZodNumber;
|
|
440
|
+
}, z.core.$strip>>>;
|
|
441
|
+
escalation: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
442
|
+
escalation_id: z.ZodString;
|
|
443
|
+
requested_path: z.ZodString;
|
|
444
|
+
resolved_path: z.ZodString;
|
|
445
|
+
tool_name: z.ZodString;
|
|
446
|
+
resource_type: z.ZodDefault<z.ZodEnum<{
|
|
447
|
+
path: "path";
|
|
448
|
+
command: "command";
|
|
449
|
+
}>>;
|
|
450
|
+
requested_command: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
451
|
+
workdir: z.ZodString;
|
|
452
|
+
}, z.core.$strip>>>;
|
|
453
|
+
provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
454
|
+
model: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
455
|
+
result: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
456
|
+
text: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
457
|
+
thinking: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
458
|
+
finish_reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
459
|
+
usage: z.ZodDefault<z.ZodObject<{
|
|
460
|
+
prompt_tokens: z.ZodDefault<z.ZodNumber>;
|
|
461
|
+
completion_tokens: z.ZodDefault<z.ZodNumber>;
|
|
462
|
+
total_tokens: z.ZodDefault<z.ZodNumber>;
|
|
463
|
+
cache_read_tokens: z.ZodDefault<z.ZodNumber>;
|
|
464
|
+
}, z.core.$strip>>;
|
|
465
|
+
steps: z.ZodDefault<z.ZodNumber>;
|
|
466
|
+
model: z.ZodDefault<z.ZodString>;
|
|
467
|
+
provider: z.ZodDefault<z.ZodString>;
|
|
468
|
+
elapsed_ms: z.ZodDefault<z.ZodNumber>;
|
|
469
|
+
}, z.core.$strip>>>;
|
|
470
|
+
error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
471
|
+
}, z.core.$strip>;
|
|
472
|
+
type AgentEvent = z.infer<typeof agentEventSchema>;
|
|
473
|
+
type AgentEventType = AgentEvent["type"];
|
|
474
|
+
declare const TERMINAL_EVENT_TYPES: ReadonlySet<AgentEventType>;
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* 上下文压缩 —— codex 本地压缩策略的移植(经 MovieClaw 验证的取舍)。
|
|
478
|
+
*
|
|
479
|
+
* 核心思路:
|
|
480
|
+
* 1. 触发以服务端上报的 usage 为准:每步响应带回真实 prompt_tokens,无需引入
|
|
481
|
+
* tokenizer;仅在没有服务端数据的场合(续聊冷启动、尚未发送的工具结果)用
|
|
482
|
+
* 「UTF-8 字节数 ≈ 4 字节/token」的启发式补估;
|
|
483
|
+
* 2. 压缩就是一次普通模型调用:把交接摘要指令作为 user 消息追加到全量历史
|
|
484
|
+
* 末尾,不带任何工具定义——模型只能输出文本,天然保证这一轮只写摘要;
|
|
485
|
+
* 3. 重建历史「宽进严出」:生成摘要时模型看得到全部现场;压缩落地后只保留
|
|
486
|
+
* 「预算内最近的用户原话 + 摘要」,工具轨迹全部丢弃——用户原话永不经过
|
|
487
|
+
* 有损摘要,防多次压缩后忘记原始意图;
|
|
488
|
+
* 4. 失败一律降级:压缩失败只记日志、返回 null,绝不中断正在进行的运行。
|
|
489
|
+
*/
|
|
490
|
+
|
|
491
|
+
/** 自动压缩水位线:上下文占用 ≥ 窗口的 90% 时触发(codex 同款比例) */
|
|
492
|
+
declare const COMPACT_TRIGGER_RATIO = 0.9;
|
|
493
|
+
/** 重建历史时保留近期用户消息的 token 预算(codex 同款 20k) */
|
|
494
|
+
declare const RETAINED_USER_TOKEN_BUDGET = 20000;
|
|
495
|
+
/** 无 tokenizer 时的估算系数:约 4 字节(UTF-8)≈ 1 token。对中文同样适用——
|
|
496
|
+
* 一个汉字 3 字节 ≈ 0.75 token,与主流 tokenizer 的量级一致,偏保守即可 */
|
|
497
|
+
declare const APPROX_BYTES_PER_TOKEN = 4;
|
|
498
|
+
interface CompactionResult {
|
|
499
|
+
/** 交接摘要文本 */
|
|
500
|
+
summary: string;
|
|
501
|
+
/** 重建后的历史(不含 system,system 每次运行重拼) */
|
|
502
|
+
replacement_history: ChatMessage[];
|
|
503
|
+
/** 压缩前后的估算 token 数(bytes/4 启发式,展示与观测用,非精确值) */
|
|
504
|
+
tokens_before: number;
|
|
505
|
+
tokens_after: number;
|
|
506
|
+
}
|
|
507
|
+
declare function estimateTokens(target: ChatMessage[] | ChatMessage | string): number;
|
|
508
|
+
/** 是否达到自动压缩水位线;模型未声明窗口时永不自动压缩(调用方负责日志) */
|
|
509
|
+
declare function shouldCompact(contextTokens: number, contextWindow: number | undefined): boolean;
|
|
510
|
+
/** 识别历史里由压缩产生的摘要消息(user 角色 + 固定前缀) */
|
|
511
|
+
declare function isSummaryMessage(message: ChatMessage): boolean;
|
|
512
|
+
/** 按 codex 策略重建历史:预算内逆序保留的用户原话 + 摘要收尾。
|
|
513
|
+
* - 只保留真实 user 消息(排除 system / 旧压缩摘要),从最新往旧装入预算,
|
|
514
|
+
* 装不下的最旧一条中部截断;
|
|
515
|
+
* - assistant / tool / 思考内容全部丢弃,信息由摘要承载;
|
|
516
|
+
* - 摘要带固定前缀、作为最后一条 user 消息。 */
|
|
517
|
+
declare function buildReplacementHistory(messages: ChatMessage[], summary: string): ChatMessage[];
|
|
518
|
+
/**
|
|
519
|
+
* 执行一次压缩:全量历史 + 摘要指令 → 模型写交接摘要 → 重建历史。
|
|
520
|
+
*
|
|
521
|
+
* messages 是完整现场(含 system 与全部工具往返);返回的
|
|
522
|
+
* replacement_history 不含 system。任何失败(流错误、异常、空摘要)都
|
|
523
|
+
* 返回 null,由调用方决定降级方式——本函数绝不抛异常。
|
|
524
|
+
*/
|
|
525
|
+
declare function compact(protocol: LlmProtocol, model: string, messages: ChatMessage[], settings: ModelSettings): Promise<CompactionResult | null>;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Agent 系统提示词。
|
|
529
|
+
*
|
|
530
|
+
* 设计原则(移植自 MovieClaw,对齐 Claude Code 的提示词架构):
|
|
531
|
+
* - 正文只写通用行为准则(运行方式 / 并行调用 / 工作循环 / 回复风格),
|
|
532
|
+
* 不含任何领域词汇——领域语义由各工具的 description 和运行时环境段承载;
|
|
533
|
+
* - 环境事实(日期等)随时会变,由 buildSystemPrompt 在每次运行时拼接,
|
|
534
|
+
* 绝不写死在正文里。
|
|
535
|
+
*/
|
|
536
|
+
/** 压缩摘要消息的固定前缀——重建历史时靠它识别「这条 user 消息是压缩摘要」,
|
|
537
|
+
* 再次压缩时旧摘要不会被当成用户原话保留(codex SUMMARY_PREFIX 同款机制) */
|
|
538
|
+
declare const SUMMARY_PREFIX = "\u3010\u4E0A\u4E0B\u6587\u538B\u7F29\u6458\u8981\u3011\u6B64\u524D\u7684\u5BF9\u8BDD\u5DF2\u88AB\u538B\u7F29\uFF0C\u4EE5\u4E0B\u662F\u4EA4\u63A5\u6458\u8981\uFF1A";
|
|
539
|
+
/** 交接摘要指令(codex SUMMARIZATION_PROMPT 的中文对齐版)。作为一条普通
|
|
540
|
+
* user 消息追加到全量历史末尾发起压缩请求,不是系统提示词。 */
|
|
541
|
+
declare const COMPACT_PROMPT = "\u4F60\u6B63\u5728\u6267\u884C\u4E00\u6B21\u4E0A\u4E0B\u6587\u538B\u7F29\u3002\u8BF7\u4E3A\u5C06\u8981\u63A5\u624B\u8FD9\u6BB5\u5BF9\u8BDD\u7684\u53E6\u4E00\u4E2A LLM \u5199\u4E00\u4EFD\u4EA4\u63A5\u6458\u8981\u3002\n\n\u6458\u8981\u5FC5\u987B\u5305\u542B\uFF1A\n- \u4EFB\u52A1\u76EE\u6807\u4E0E\u5F53\u524D\u8FDB\u5EA6\u3001\u5DF2\u505A\u51FA\u7684\u5173\u952E\u51B3\u5B9A\n- \u7528\u6237\u63D0\u51FA\u7684\u7EA6\u675F\u3001\u504F\u597D\u548C\u91CD\u8981\u80CC\u666F\n- \u5C1A\u672A\u5B8C\u6210\u7684\u4E8B\u9879\uFF08\u660E\u786E\u7684\u4E0B\u4E00\u6B65\uFF09\n- \u7EE7\u7EED\u5DE5\u4F5C\u5FC5\u987B\u4FDD\u7559\u7684\u5173\u952E\u6570\u636E\uFF08\u8DEF\u5F84\u3001ID\u3001\u7F16\u53F7\u3001\u67E5\u8BE2\u7ED3\u679C\u8981\u70B9\u7B49\uFF09\n\n\u4FDD\u6301\u7B80\u6D01\u3001\u7ED3\u6784\u5316\uFF0C\u4EE5\u5E2E\u52A9\u4E0B\u4E00\u4E2A LLM \u65E0\u7F1D\u63A5\u7EED\u5DE5\u4F5C\u4E3A\u552F\u4E00\u76EE\u6807\u3002\u53EA\u8F93\u51FA\u6458\u8981\u6B63\u6587\u3002\n";
|
|
542
|
+
interface SystemPromptOptions {
|
|
543
|
+
/** 助理名称,默认 "xlyra 助理" */
|
|
544
|
+
agentName?: string;
|
|
545
|
+
/** 一句话人设(拼在首段),默认空 */
|
|
546
|
+
persona?: string;
|
|
547
|
+
/** 运行时环境段(每行一个事实,拼在「# 环境」下) */
|
|
548
|
+
extraEnvironment?: string;
|
|
549
|
+
/** 当前会话实际暴露给模型的工具;由 Runner 动态注入,避免静态提示漂移。 */
|
|
550
|
+
availableTools?: Array<Pick<ToolDefinition, "name" | "description">>;
|
|
551
|
+
}
|
|
552
|
+
declare function buildAvailableToolsPrompt(availableTools: Array<Pick<ToolDefinition, "name" | "description">>): string;
|
|
553
|
+
declare function buildSystemPrompt(opts?: SystemPromptOptions): string;
|
|
554
|
+
|
|
555
|
+
/** 文件格式版本;结构变化时 +1,读取端按版本做迁移
|
|
556
|
+
* v3:新增 type="escalation" 的提权请求行(读端向后兼容 v1/v2) */
|
|
557
|
+
declare const SESSION_FORMAT_VERSION = 3;
|
|
558
|
+
/** 会话标题 / 最后提示预览的截断长度 */
|
|
559
|
+
declare const PREVIEW_MAX_CHARS = 80;
|
|
560
|
+
/** 默认数据根目录(~/.xlyra-agent),sessions 与 index.json 均在其下 */
|
|
561
|
+
declare function defaultDataDir(): string;
|
|
562
|
+
declare function defaultSessionsDir(): string;
|
|
563
|
+
declare const sessionHeaderSchema: z.ZodObject<{
|
|
564
|
+
type: z.ZodDefault<z.ZodLiteral<"session">>;
|
|
565
|
+
version: z.ZodDefault<z.ZodNumber>;
|
|
566
|
+
session_id: z.ZodString;
|
|
567
|
+
created_at: z.ZodString;
|
|
568
|
+
}, z.core.$strip>;
|
|
569
|
+
type SessionHeader = z.infer<typeof sessionHeaderSchema>;
|
|
570
|
+
declare const sessionMessageEntrySchema: z.ZodObject<{
|
|
571
|
+
type: z.ZodDefault<z.ZodLiteral<"message">>;
|
|
572
|
+
uuid: z.ZodString;
|
|
573
|
+
parent_uuid: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
574
|
+
timestamp: z.ZodString;
|
|
575
|
+
message: z.ZodObject<{
|
|
576
|
+
role: z.ZodEnum<{
|
|
577
|
+
system: "system";
|
|
578
|
+
user: "user";
|
|
579
|
+
assistant: "assistant";
|
|
580
|
+
tool: "tool";
|
|
581
|
+
}>;
|
|
582
|
+
content: z.ZodDefault<z.ZodString>;
|
|
583
|
+
tool_calls: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
584
|
+
id: z.ZodString;
|
|
585
|
+
name: z.ZodString;
|
|
586
|
+
raw_arguments: z.ZodString;
|
|
587
|
+
}, z.core.$strip>>>;
|
|
588
|
+
tool_call_id: z.ZodOptional<z.ZodString>;
|
|
589
|
+
name: z.ZodOptional<z.ZodString>;
|
|
590
|
+
is_error: z.ZodOptional<z.ZodBoolean>;
|
|
591
|
+
thinking: z.ZodOptional<z.ZodString>;
|
|
592
|
+
thinking_signature: z.ZodOptional<z.ZodString>;
|
|
593
|
+
}, z.core.$strip>;
|
|
594
|
+
model: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
595
|
+
usage: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
596
|
+
prompt_tokens: z.ZodDefault<z.ZodNumber>;
|
|
597
|
+
completion_tokens: z.ZodDefault<z.ZodNumber>;
|
|
598
|
+
total_tokens: z.ZodDefault<z.ZodNumber>;
|
|
599
|
+
cache_read_tokens: z.ZodDefault<z.ZodNumber>;
|
|
600
|
+
}, z.core.$strip>>>;
|
|
601
|
+
finish_reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
602
|
+
}, z.core.$strip>;
|
|
603
|
+
type SessionMessageEntry = z.infer<typeof sessionMessageEntrySchema>;
|
|
604
|
+
declare const sessionCompactionEntrySchema: z.ZodObject<{
|
|
605
|
+
type: z.ZodDefault<z.ZodLiteral<"compaction">>;
|
|
606
|
+
uuid: z.ZodString;
|
|
607
|
+
parent_uuid: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
608
|
+
timestamp: z.ZodString;
|
|
609
|
+
summary: z.ZodString;
|
|
610
|
+
replacement_history: z.ZodArray<z.ZodObject<{
|
|
611
|
+
role: z.ZodEnum<{
|
|
612
|
+
system: "system";
|
|
613
|
+
user: "user";
|
|
614
|
+
assistant: "assistant";
|
|
615
|
+
tool: "tool";
|
|
616
|
+
}>;
|
|
617
|
+
content: z.ZodDefault<z.ZodString>;
|
|
618
|
+
tool_calls: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
619
|
+
id: z.ZodString;
|
|
620
|
+
name: z.ZodString;
|
|
621
|
+
raw_arguments: z.ZodString;
|
|
622
|
+
}, z.core.$strip>>>;
|
|
623
|
+
tool_call_id: z.ZodOptional<z.ZodString>;
|
|
624
|
+
name: z.ZodOptional<z.ZodString>;
|
|
625
|
+
is_error: z.ZodOptional<z.ZodBoolean>;
|
|
626
|
+
thinking: z.ZodOptional<z.ZodString>;
|
|
627
|
+
thinking_signature: z.ZodOptional<z.ZodString>;
|
|
628
|
+
}, z.core.$strip>>;
|
|
629
|
+
tokens_before: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
630
|
+
tokens_after: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
631
|
+
}, z.core.$strip>;
|
|
632
|
+
type SessionCompactionEntry = z.infer<typeof sessionCompactionEntrySchema>;
|
|
633
|
+
/** 提权请求行:越界访问的协商记录(回放时前端据此渲染确认卡片)。
|
|
634
|
+
* granted=null 待确认;true 已授权;false 已拒绝 */
|
|
635
|
+
declare const sessionEscalationEntrySchema: z.ZodObject<{
|
|
636
|
+
type: z.ZodDefault<z.ZodLiteral<"escalation">>;
|
|
637
|
+
uuid: z.ZodString;
|
|
638
|
+
parent_uuid: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
639
|
+
timestamp: z.ZodString;
|
|
640
|
+
requested_path: z.ZodString;
|
|
641
|
+
resolved_path: z.ZodString;
|
|
642
|
+
tool_name: z.ZodString;
|
|
643
|
+
resource_type: z.ZodDefault<z.ZodEnum<{
|
|
644
|
+
path: "path";
|
|
645
|
+
command: "command";
|
|
646
|
+
}>>;
|
|
647
|
+
requested_command: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
648
|
+
granted: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodBoolean>>>;
|
|
649
|
+
}, z.core.$strip>;
|
|
650
|
+
type SessionEscalationEntry = z.infer<typeof sessionEscalationEntrySchema>;
|
|
651
|
+
type SessionEntry = SessionMessageEntry | SessionCompactionEntry | SessionEscalationEntry;
|
|
652
|
+
interface SessionSummary {
|
|
653
|
+
session_id: string;
|
|
654
|
+
created_at: string;
|
|
655
|
+
entry_count: number;
|
|
656
|
+
leaf_uuid: string | null;
|
|
657
|
+
/** 首条 user 消息的截断文本;作为无自定义标题时的会话标题 */
|
|
658
|
+
title: string | null;
|
|
659
|
+
/** 最后一条 user 消息的截断文本 */
|
|
660
|
+
last_prompt: string | null;
|
|
661
|
+
last_timestamp: string;
|
|
662
|
+
}
|
|
663
|
+
declare function isMessageEntry(e: SessionEntry): e is SessionMessageEntry;
|
|
664
|
+
declare function isCompactionEntry(e: SessionEntry): e is SessionCompactionEntry;
|
|
665
|
+
declare function isEscalationEntry(e: SessionEntry): e is SessionEscalationEntry;
|
|
666
|
+
declare class AgentSessionStore {
|
|
667
|
+
private readonly root;
|
|
668
|
+
/** session_id → 最后一条 entry 的 uuid(避免每次 append 都重读文件) */
|
|
669
|
+
private readonly leafCache;
|
|
670
|
+
constructor(root?: string);
|
|
671
|
+
get rootDir(): string;
|
|
672
|
+
pathOf(sessionId: string): string;
|
|
673
|
+
exists(sessionId: string): boolean;
|
|
674
|
+
/** 新建会话文件并写入头行,返回头信息 */
|
|
675
|
+
create(sessionId?: string): SessionHeader;
|
|
676
|
+
/** 追加一条定稿消息,自动接到当前链尾,返回写入的 entry */
|
|
677
|
+
append(sessionId: string, message: ChatMessage, meta?: {
|
|
678
|
+
model?: string;
|
|
679
|
+
usage?: z.infer<typeof tokenUsageSchema>;
|
|
680
|
+
finish_reason?: string;
|
|
681
|
+
}): SessionMessageEntry;
|
|
682
|
+
/** 追加一条压缩行,与 append 同款接到当前链尾(parent 链线性穿过压缩行) */
|
|
683
|
+
appendCompaction(sessionId: string, result: CompactionResult): SessionCompactionEntry;
|
|
684
|
+
/** 追加一条提权请求行(granted=null 待确认) */
|
|
685
|
+
appendEscalation(sessionId: string, info: {
|
|
686
|
+
escalation_id: string;
|
|
687
|
+
requested_path: string;
|
|
688
|
+
resolved_path: string;
|
|
689
|
+
tool_name: string;
|
|
690
|
+
resource_type?: "path" | "command";
|
|
691
|
+
requested_command?: string[];
|
|
692
|
+
}): SessionEscalationEntry;
|
|
693
|
+
/** 标记提权请求的确认结果(granted=true 授权 / false 拒绝)。
|
|
694
|
+
* 这是 append-only 原则的第二个例外(另一个是 discardFromUserMessage):
|
|
695
|
+
* 提权行的 granted 字段需要就地更新,否则确认状态无法在回放时保留。
|
|
696
|
+
* 实现上仍是整文件原子重写(tmp + rename),与 discard 同款安全保证。 */
|
|
697
|
+
resolveEscalation(sessionId: string, escalationId: string, granted: boolean): boolean;
|
|
698
|
+
/**
|
|
699
|
+
* 中断收尾:给没有结果的 tool_call 补写错误回执,返回补写条数。
|
|
700
|
+
*
|
|
701
|
+
* 保证文件里 assistant 的 tool_calls 与 tool 消息任何时刻都配对完整,
|
|
702
|
+
* resume 直接回喂 API 不需要修复逻辑(在写入侧一次做对)。
|
|
703
|
+
* 只检查最后一条压缩行之后的消息:更早的往返已被压缩挡在上下文之外,
|
|
704
|
+
* 给死上下文补回执毫无意义。
|
|
705
|
+
*/
|
|
706
|
+
sealPendingToolCalls(sessionId: string): number;
|
|
707
|
+
/**
|
|
708
|
+
* 删除指定 user message 及其之后的全部 entry,返回删除条数。
|
|
709
|
+
*
|
|
710
|
+
* 这是本模块唯一改写历史行的方法,与「append-only」约定相悖,属于刻意的
|
|
711
|
+
* 例外:用户要的就是「这些记录不该再存在」。整文件重写,写临时文件后
|
|
712
|
+
* rename 原子换入:中途崩溃要么旧文件完好、要么新文件完整。
|
|
713
|
+
* 只允许从 user message 切:从 assistant/tool 中间切会留下没有回执的
|
|
714
|
+
* tool_call,重建出的上下文喂回模型直接 400。
|
|
715
|
+
*/
|
|
716
|
+
discardFromUserMessage(sessionId: string, messageId: string): number;
|
|
717
|
+
/** 删除会话文件(幂等) */
|
|
718
|
+
delete(sessionId: string): void;
|
|
719
|
+
/** 读取整个会话(头 + 全部 entry,含压缩行),坏行静默跳过 */
|
|
720
|
+
read(sessionId: string): {
|
|
721
|
+
header: SessionHeader;
|
|
722
|
+
entries: SessionEntry[];
|
|
723
|
+
badLines: number;
|
|
724
|
+
};
|
|
725
|
+
/**
|
|
726
|
+
* 把会话重建成模型上下文消息列表(resume 喂回模型用)。
|
|
727
|
+
* 有压缩行时,从最后一条压缩行的替换历史起步、只追加其后的增量消息;
|
|
728
|
+
* system 提示词不入库(随代码版本演进),由 runner 每次运行时重新拼装。
|
|
729
|
+
*/
|
|
730
|
+
buildHistory(sessionId: string): ChatMessage[];
|
|
731
|
+
/**
|
|
732
|
+
* 重建提权中断前的上下文:保留原始 user 输入,但丢弃被中断的
|
|
733
|
+
* assistant/tool 往返,授权后由 runner 从原输入继续推理。
|
|
734
|
+
*/
|
|
735
|
+
buildHistoryBeforeEscalation(sessionId: string, escalationId: string): ChatMessage[];
|
|
736
|
+
/** 扫描单个会话文件生成索引摘要 */
|
|
737
|
+
summarize(sessionId: string): SessionSummary;
|
|
738
|
+
/** 遍历目录下全部会话文件生成摘要(索引整体重建用;单文件损坏只跳过) */
|
|
739
|
+
scanAll(): SessionSummary[];
|
|
740
|
+
private currentLeaf;
|
|
741
|
+
private appendLine;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* 工具挂点:声明 + 执行器的绑定。
|
|
746
|
+
*
|
|
747
|
+
* 工具的「声明」(definition,暴露给模型)与「执行」(handler,真正干活)
|
|
748
|
+
* 在此绑成一个单元——改行为时提示词与实现不会漂移。handler 约定:
|
|
749
|
+
* - 入参是已通过 JSON Schema 校验的参数 dict;
|
|
750
|
+
* - 返回喂回模型的文本(紧凑、模型可读即可);
|
|
751
|
+
* - 业务失败 throw new Error(中文说明):runner 会把异常转成失败结果
|
|
752
|
+
* 回喂模型,不中断 loop。
|
|
753
|
+
*/
|
|
754
|
+
|
|
755
|
+
interface ToolAnnotations {
|
|
756
|
+
/** 不修改文件、进程或外部状态。 */
|
|
757
|
+
readOnly: boolean;
|
|
758
|
+
/** 可与同一模型响应中的其他只读工具并发执行。 */
|
|
759
|
+
parallelSafe: boolean;
|
|
760
|
+
}
|
|
761
|
+
interface ToolContext {
|
|
762
|
+
/** 当前 Agent 运行的取消信号;长任务必须主动监听。 */
|
|
763
|
+
signal?: AbortSignal;
|
|
764
|
+
/** 当前运行编号,供进程会话与诊断日志关联。 */
|
|
765
|
+
runId?: string;
|
|
766
|
+
}
|
|
767
|
+
interface ToolHandlerResult {
|
|
768
|
+
/** 回喂模型的紧凑文本。 */
|
|
769
|
+
content: string;
|
|
770
|
+
/** 工具可显式返回业务失败,而不必抛异常。 */
|
|
771
|
+
isError?: boolean;
|
|
772
|
+
/** 仅供宿主扩展使用;当前消息协议不会把它回喂模型。 */
|
|
773
|
+
metadata?: Record<string, unknown>;
|
|
774
|
+
}
|
|
775
|
+
interface AgentTool {
|
|
776
|
+
definition: ToolDefinition;
|
|
777
|
+
/** 省略时按“有副作用、不可并行”的保守策略处理。 */
|
|
778
|
+
annotations?: ToolAnnotations;
|
|
779
|
+
/** 字符串返回值继续兼容已有自定义工具。 */
|
|
780
|
+
handler: (args: Record<string, unknown>, context?: ToolContext) => Promise<string | ToolHandlerResult>;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
interface AgentRunnerOptions {
|
|
784
|
+
/** 直接使用单个协议实例(库形态的典型用法) */
|
|
785
|
+
protocol?: LlmProtocol;
|
|
786
|
+
/** 或经端点路由按 params.model 解析(服务层用法);两者必传其一 */
|
|
787
|
+
resolver?: EndpointResolver;
|
|
788
|
+
tools?: AgentTool[];
|
|
789
|
+
maxSteps?: number;
|
|
790
|
+
/** 定稿消息回调(会话持久化挂点):中间步 assistant(含 tool_calls)、
|
|
791
|
+
* 每条 tool 结果、终答 assistant 各调用一次;流式 delta 不经过这里 */
|
|
792
|
+
onMessage?: (message: ChatMessage, response: ChatResponse | null) => Promise<void>;
|
|
793
|
+
/** 压缩定稿回调(转录落盘挂点):每次上下文压缩成功后调用一次 */
|
|
794
|
+
onCompaction?: (result: CompactionResult) => Promise<void>;
|
|
795
|
+
/** 提权请求回调(转录落盘挂点):回放时前端据此渲染确认卡片 */
|
|
796
|
+
onEscalation?: (info: {
|
|
797
|
+
escalation_id: string;
|
|
798
|
+
requested_path: string;
|
|
799
|
+
resolved_path: string;
|
|
800
|
+
tool_name: string;
|
|
801
|
+
resource_type: "path" | "command";
|
|
802
|
+
requested_command?: string[];
|
|
803
|
+
}) => Promise<void>;
|
|
804
|
+
/** 日志输出(默认 console);测试可注入静默 logger */
|
|
805
|
+
logger?: Pick<Console, "info" | "warn" | "error">;
|
|
806
|
+
/** 提权事件里展示的工作区根(用户判断边界用);服务装配层从工具配置传入 */
|
|
807
|
+
workdirHint?: string;
|
|
808
|
+
}
|
|
809
|
+
interface AgentRunOptions {
|
|
810
|
+
runId?: string;
|
|
811
|
+
signal?: AbortSignal;
|
|
812
|
+
}
|
|
813
|
+
declare class AgentRunner {
|
|
814
|
+
private readonly protocol?;
|
|
815
|
+
private readonly resolver?;
|
|
816
|
+
private readonly tools;
|
|
817
|
+
private readonly toolsByName;
|
|
818
|
+
private readonly maxSteps;
|
|
819
|
+
private readonly onMessage?;
|
|
820
|
+
private readonly onCompaction?;
|
|
821
|
+
private readonly onEscalation?;
|
|
822
|
+
private readonly logger;
|
|
823
|
+
/** 提权事件里展示的工作区根(用户判断边界用);由构造方从工具配置传入 */
|
|
824
|
+
private readonly workdirHint;
|
|
825
|
+
constructor(opts: AgentRunnerOptions);
|
|
826
|
+
start(params: AgentStartParams, runOpts?: AgentRunOptions): AsyncGenerator<AgentEvent>;
|
|
827
|
+
/** 达到水位线时压缩上下文并原地替换 messages,返回压缩事件。
|
|
828
|
+
* 任何失败都降级为「本次不压缩」:记日志后照常返回 null,运行继续。 */
|
|
829
|
+
private maybeCompact;
|
|
830
|
+
private notifyCompaction;
|
|
831
|
+
private notifyEscalation;
|
|
832
|
+
private notify;
|
|
833
|
+
/** 执行单个工具调用:校验 → 执行;任何失败都转为回喂文本,不抛异常 */
|
|
834
|
+
private executeTool;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* 会话级路径授权登记表(进程内)。
|
|
839
|
+
* key = sessionId,value = 已授权的路径前缀集合(realpath 后的绝对路径)。
|
|
840
|
+
*/
|
|
841
|
+
declare class EscalationGrants {
|
|
842
|
+
private readonly grants;
|
|
843
|
+
grant(sessionId: string, resolvedPath: string): void;
|
|
844
|
+
grantCapability(sessionId: string, capability: string): void;
|
|
845
|
+
/** 已授权路径或其子路径视为已放开 */
|
|
846
|
+
isGranted(sessionId: string, resolvedPath: string): boolean;
|
|
847
|
+
isCapabilityGranted(sessionId: string, capability: string): boolean;
|
|
848
|
+
/** 会话删除时清掉授权(授权随会话生命周期) */
|
|
849
|
+
drop(sessionId: string): void;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* 工具工厂共享的沙箱参数形态(避免每个工具文件重复定义)。
|
|
854
|
+
*/
|
|
855
|
+
|
|
856
|
+
interface SandboxOptions {
|
|
857
|
+
allowOutsideWorkdir?: boolean;
|
|
858
|
+
/** 命令工具是否已由宿主预授权;否则首次调用走提权协商。 */
|
|
859
|
+
commandExecutionEnabled?: boolean;
|
|
860
|
+
grants?: EscalationGrants;
|
|
861
|
+
sessionId?: string;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
declare function makeListTool(workdir: string, sandbox?: SandboxOptions): AgentTool;
|
|
865
|
+
|
|
866
|
+
declare function makeReadTool(workdir: string, sandbox?: SandboxOptions): AgentTool;
|
|
867
|
+
|
|
868
|
+
declare function makeCreateTool(workdir: string, sandbox?: SandboxOptions): AgentTool;
|
|
869
|
+
|
|
870
|
+
declare function makeApplyPatchTool(workdir: string, sandbox?: SandboxOptions): AgentTool;
|
|
871
|
+
|
|
872
|
+
declare function makeEditTool(workdir: string, sandbox?: SandboxOptions): AgentTool;
|
|
873
|
+
|
|
874
|
+
declare function makeSearchTool(workdir: string, sandbox?: SandboxOptions): AgentTool;
|
|
875
|
+
|
|
876
|
+
interface SpawnProcessOptions {
|
|
877
|
+
command: string[];
|
|
878
|
+
cwd: string;
|
|
879
|
+
timeoutMs: number;
|
|
880
|
+
signal?: AbortSignal;
|
|
881
|
+
}
|
|
882
|
+
interface ProcessPollResult {
|
|
883
|
+
sessionId: string;
|
|
884
|
+
output: string;
|
|
885
|
+
running: boolean;
|
|
886
|
+
exitCode: number | null;
|
|
887
|
+
exitSignal: NodeJS.Signals | null;
|
|
888
|
+
error: string | null;
|
|
889
|
+
}
|
|
890
|
+
declare class ProcessManager {
|
|
891
|
+
private readonly sessions;
|
|
892
|
+
start(options: SpawnProcessOptions): string;
|
|
893
|
+
poll(sessionId: string, yieldTimeMs: number, maxOutputBytes: number): Promise<ProcessPollResult>;
|
|
894
|
+
write(sessionId: string, chars: string): void;
|
|
895
|
+
private require;
|
|
896
|
+
private terminate;
|
|
897
|
+
private finish;
|
|
898
|
+
private prune;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
declare function makeExecCommandTool(workdir: string, manager: ProcessManager, sandbox?: SandboxOptions): AgentTool;
|
|
902
|
+
declare function formatProcessResult(result: ProcessPollResult): {
|
|
903
|
+
content: string;
|
|
904
|
+
isError: boolean;
|
|
905
|
+
};
|
|
906
|
+
|
|
907
|
+
declare function makeWriteStdinTool(manager: ProcessManager, sandbox?: SandboxOptions): AgentTool;
|
|
908
|
+
|
|
909
|
+
declare function makeWriteTool(workdir: string, sandbox?: SandboxOptions): AgentTool;
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* 解析目标路径并做沙箱校验;返回可直接用于 fs 操作的绝对路径。
|
|
913
|
+
* 目标不存在时(create 场景):取最深的已存在祖先做 realpath,再拼回剩余段。
|
|
914
|
+
*/
|
|
915
|
+
declare function resolveSandboxed(workdir: string, raw: string, opts?: {
|
|
916
|
+
allowOutsideWorkdir?: boolean;
|
|
917
|
+
/** 会话级授权清单(提供 sessionId 时生效) */
|
|
918
|
+
grants?: EscalationGrants;
|
|
919
|
+
sessionId?: string;
|
|
920
|
+
}): string;
|
|
921
|
+
|
|
922
|
+
interface BuiltinToolsOptions {
|
|
923
|
+
/** 工作目录:相对路径解析基准 + 沙箱边界 */
|
|
924
|
+
workdir: string;
|
|
925
|
+
/** 显式放开沙箱(默认 false:全部路径限制在 workdir 内) */
|
|
926
|
+
allowOutsideWorkdir?: boolean;
|
|
927
|
+
/** 会话级路径授权清单(与 sessionId 一起提供时生效) */
|
|
928
|
+
grants?: EscalationGrants;
|
|
929
|
+
/** 当前会话 id(授权清单的查询键) */
|
|
930
|
+
sessionId?: string;
|
|
931
|
+
/** 预授权本机命令执行;关闭时工具仍会声明,但首次调用触发提权协商。 */
|
|
932
|
+
enableCommandExecution?: boolean;
|
|
933
|
+
}
|
|
934
|
+
declare function builtinTools(opts: BuiltinToolsOptions): AgentTool[];
|
|
935
|
+
|
|
936
|
+
declare const appConfigSchema: z.ZodObject<{
|
|
937
|
+
endpoints: z.ZodArray<z.ZodObject<{
|
|
938
|
+
name: z.ZodString;
|
|
939
|
+
protocol: z.ZodEnum<{
|
|
940
|
+
"anthropic-messages": "anthropic-messages";
|
|
941
|
+
"openai-responses": "openai-responses";
|
|
942
|
+
}>;
|
|
943
|
+
base_url: z.ZodString;
|
|
944
|
+
api_key: z.ZodString;
|
|
945
|
+
models: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
946
|
+
context_window: z.ZodOptional<z.ZodNumber>;
|
|
947
|
+
}, z.core.$strip>>>;
|
|
948
|
+
default_model: z.ZodOptional<z.ZodString>;
|
|
949
|
+
}, z.core.$strip>>;
|
|
950
|
+
server: z.ZodOptional<z.ZodObject<{
|
|
951
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
952
|
+
token: z.ZodOptional<z.ZodString>;
|
|
953
|
+
}, z.core.$strip>>;
|
|
954
|
+
agent: z.ZodOptional<z.ZodObject<{
|
|
955
|
+
workdir: z.ZodOptional<z.ZodString>;
|
|
956
|
+
agent_name: z.ZodOptional<z.ZodString>;
|
|
957
|
+
persona: z.ZodOptional<z.ZodString>;
|
|
958
|
+
enable_command_execution: z.ZodOptional<z.ZodBoolean>;
|
|
959
|
+
}, z.core.$strip>>;
|
|
960
|
+
}, z.core.$strip>;
|
|
961
|
+
type AppConfig = z.infer<typeof appConfigSchema>;
|
|
962
|
+
type ServerConfig = NonNullable<AppConfig["server"]>;
|
|
963
|
+
type AgentServiceConfig = NonNullable<AppConfig["agent"]>;
|
|
964
|
+
declare function defaultConfigPath(): string;
|
|
965
|
+
/** 加载并校验配置;文件不存在/结构非法时抛出明确中文错误 */
|
|
966
|
+
declare function loadConfig(configPath?: string): AppConfig;
|
|
967
|
+
/** 保存配置(tmp + rename 原子写入);config 须已通过 schema 校验 */
|
|
968
|
+
declare function saveConfig(config: AppConfig, configPath?: string): void;
|
|
969
|
+
/** 配置是否存在(config init 判重 / 首次运行引导用) */
|
|
970
|
+
declare function configExists(configPath?: string): boolean;
|
|
971
|
+
/** 新增或更新端点(按 name 匹配,同名覆盖);返回写入后的完整配置 */
|
|
972
|
+
declare function upsertEndpoint(endpoint: EndpointConfig, configPath?: string): AppConfig;
|
|
973
|
+
/** 按 name 删除端点;不存在时返回 false。不允许删除最后一条(配置必须非空) */
|
|
974
|
+
declare function removeEndpoint(name: string, configPath?: string): boolean;
|
|
975
|
+
|
|
976
|
+
interface RunningState {
|
|
977
|
+
run_id: string;
|
|
978
|
+
/** 最近一次心跳的 epoch 毫秒 */
|
|
979
|
+
last_heartbeat: number;
|
|
980
|
+
}
|
|
981
|
+
interface SessionMeta {
|
|
982
|
+
session_id: string;
|
|
983
|
+
created_at: string;
|
|
984
|
+
title: string | null;
|
|
985
|
+
last_prompt: string | null;
|
|
986
|
+
entry_count: number;
|
|
987
|
+
leaf_uuid: string | null;
|
|
988
|
+
last_active: string;
|
|
989
|
+
running: RunningState | null;
|
|
990
|
+
}
|
|
991
|
+
declare class SessionIndex {
|
|
992
|
+
private readonly file;
|
|
993
|
+
private readonly metas;
|
|
994
|
+
constructor(indexFile: string);
|
|
995
|
+
/** 启动时加载;文件不存在/损坏则从空开始(rebuild 会补齐) */
|
|
996
|
+
private load;
|
|
997
|
+
/** 从事实源整体重建(启动自愈):扫描结果单向覆盖索引 */
|
|
998
|
+
rebuild(summaries: SessionSummary[]): void;
|
|
999
|
+
create(sessionId: string): void;
|
|
1000
|
+
get(sessionId: string): SessionMeta | undefined;
|
|
1001
|
+
/** 每次追加 entry 后刷新链尾/计数/预览;title 仅在传入时更新(首条消息) */
|
|
1002
|
+
touchAfterAppend(sessionId: string, update: {
|
|
1003
|
+
leaf_uuid: string;
|
|
1004
|
+
entry_count: number;
|
|
1005
|
+
last_prompt?: string;
|
|
1006
|
+
title?: string;
|
|
1007
|
+
}): void;
|
|
1008
|
+
rename(sessionId: string, title: string): boolean;
|
|
1009
|
+
markRunning(sessionId: string, runId: string): void;
|
|
1010
|
+
heartbeat(sessionId: string): void;
|
|
1011
|
+
finishRun(sessionId: string): void;
|
|
1012
|
+
/** 是否有正在进行的消息处理:运行标记存在且心跳未超时 */
|
|
1013
|
+
isRunning(sessionId: string): boolean;
|
|
1014
|
+
/** 按最后活跃时间倒序分页 */
|
|
1015
|
+
list(limit: number, offset: number): SessionMeta[];
|
|
1016
|
+
remove(sessionId: string): void;
|
|
1017
|
+
private persist;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* 会话记录器:把一次 Agent 运行的定稿消息接进 JSONL 存储与会话索引。
|
|
1022
|
+
*
|
|
1023
|
+
* 一次运行一个实例,由路由层创建并挂到两个钩子上:
|
|
1024
|
+
* - AgentRunner(onMessage / onCompaction)——定稿消息与压缩行落盘并刷新
|
|
1025
|
+
* 索引(先文件后索引,见 sessions.ts 的写入顺序约定);
|
|
1026
|
+
* - RunRegistry.start(onTerminal)——运行终态时收尾:停心跳、给未配对的
|
|
1027
|
+
* tool_call 补错误回执、清空运行标记(列表立即显示已结束)。
|
|
1028
|
+
*
|
|
1029
|
+
* 心跳独立于消息追加:长工具执行期间可能几十秒没有新消息,心跳任务保证
|
|
1030
|
+
* last_heartbeat 持续刷新,调用方才能正确区分「还在跑」和「已崩溃」。
|
|
1031
|
+
* 进程硬崩时心跳自然停止,超时窗过后状态自愈为已结束——这正是不持久化
|
|
1032
|
+
* 静态 status 字段的原因。
|
|
1033
|
+
*/
|
|
1034
|
+
|
|
1035
|
+
declare class AgentRunRecorder {
|
|
1036
|
+
private readonly store;
|
|
1037
|
+
private readonly index;
|
|
1038
|
+
private readonly sessionId;
|
|
1039
|
+
/** 运行开始时会话已有的 entry 数;之后每次落盘递增,避免反复重读文件 */
|
|
1040
|
+
private entryCount;
|
|
1041
|
+
private heartbeatTimer;
|
|
1042
|
+
/** begin 与 onTerminal 分别由路由层和后台任务并发调用:用同一根 Promise
|
|
1043
|
+
* 链串行化,防「极速结束的运行被误标为永远运行中」的竞态 */
|
|
1044
|
+
private lifecycle;
|
|
1045
|
+
private terminated;
|
|
1046
|
+
constructor(store: AgentSessionStore, index: SessionIndex, sessionId: string, entryCount: number);
|
|
1047
|
+
/** 运行启动:标记 running 并开启心跳。运行已先一步终态时跳过。 */
|
|
1048
|
+
begin(runId: string): Promise<void>;
|
|
1049
|
+
/** 落盘 user message,刷新标题(仅首条)与最后提示预览,返回 message id */
|
|
1050
|
+
recordUserMessage(text: string): Promise<string>;
|
|
1051
|
+
/** runner 定稿消息回调:assistant 带响应元数据,tool 结果不带 */
|
|
1052
|
+
onMessage: (message: ChatMessage, response: ChatResponse | null) => Promise<void>;
|
|
1053
|
+
/** runner 压缩定稿回调:压缩行落盘并刷新索引(与 onMessage 同一节奏) */
|
|
1054
|
+
onCompaction: (result: CompactionResult) => Promise<void>;
|
|
1055
|
+
/** runner 提权请求回调:提权行落盘并刷新索引(回放时前端渲染确认卡片) */
|
|
1056
|
+
onEscalation: (info: {
|
|
1057
|
+
escalation_id: string;
|
|
1058
|
+
requested_path: string;
|
|
1059
|
+
resolved_path: string;
|
|
1060
|
+
tool_name: string;
|
|
1061
|
+
resource_type?: "path" | "command";
|
|
1062
|
+
requested_command?: string[];
|
|
1063
|
+
}) => Promise<void>;
|
|
1064
|
+
/** 运行终态收尾(done / error / cancelled 统一路径) */
|
|
1065
|
+
onTerminal: (_event: AgentEvent) => Promise<void>;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
interface StoredAgentEvent {
|
|
1069
|
+
/** 运行内递增序号;直接用作 SSE 的 id */
|
|
1070
|
+
sequence: number;
|
|
1071
|
+
event: AgentEvent;
|
|
1072
|
+
}
|
|
1073
|
+
interface Run {
|
|
1074
|
+
runId: string;
|
|
1075
|
+
sessionId: string;
|
|
1076
|
+
events: StoredAgentEvent[];
|
|
1077
|
+
terminal: boolean;
|
|
1078
|
+
completedAt: number | null;
|
|
1079
|
+
controller: AbortController;
|
|
1080
|
+
/** 等待新事件的唤醒回调(一次性,触发后移除) */
|
|
1081
|
+
waiters: Set<() => void>;
|
|
1082
|
+
/** 终态钩子:运行进入终态后调用一次(停心跳、补配对、清运行标记) */
|
|
1083
|
+
onTerminal: ((event: AgentEvent) => Promise<void>) | null;
|
|
1084
|
+
}
|
|
1085
|
+
declare class RunRegistry {
|
|
1086
|
+
private readonly retentionMs;
|
|
1087
|
+
private readonly runs;
|
|
1088
|
+
private readonly latestBySession;
|
|
1089
|
+
private closing;
|
|
1090
|
+
constructor(opts?: {
|
|
1091
|
+
retentionMs?: number;
|
|
1092
|
+
});
|
|
1093
|
+
/** 分配运行编号并把 runner 放入后台执行,立即返回编号 */
|
|
1094
|
+
start(runner: AgentRunner, params: AgentStartParams, opts: {
|
|
1095
|
+
sessionId: string;
|
|
1096
|
+
onTerminal?: (event: AgentEvent) => Promise<void>;
|
|
1097
|
+
}): string;
|
|
1098
|
+
/** 按公开会话编号读取当前(或最近一轮)事件 */
|
|
1099
|
+
getSessionEvents(sessionId: string, afterSequence: number, timeoutSeconds: number): Promise<{
|
|
1100
|
+
events: StoredAgentEvent[];
|
|
1101
|
+
terminal: boolean;
|
|
1102
|
+
}>;
|
|
1103
|
+
/**
|
|
1104
|
+
* 返回游标后的事件;暂无事件时等待通知,超时返回空列表供 SSE 发心跳。
|
|
1105
|
+
* 调用方应先发送本批事件,再在 terminal=true 且批次已追平时关闭连接。
|
|
1106
|
+
*/
|
|
1107
|
+
getEvents(runId: string, afterSequence: number, timeoutSeconds: number): Promise<{
|
|
1108
|
+
events: StoredAgentEvent[];
|
|
1109
|
+
terminal: boolean;
|
|
1110
|
+
}>;
|
|
1111
|
+
/**
|
|
1112
|
+
* 幂等取消一次运行:**先落可回放的 agent_cancelled 终态事件,再 abort**。
|
|
1113
|
+
* 顺序很重要:运行刚创建、事件循环尚未开始消费时,直接 abort 会让 runner
|
|
1114
|
+
* 一次都不执行,订阅者会永久等待——先落终态事件保证任何情况下订阅者
|
|
1115
|
+
* 都能看到收尾。
|
|
1116
|
+
*/
|
|
1117
|
+
cancel(runId: string): Promise<void>;
|
|
1118
|
+
cancelSession(sessionId: string): Promise<void>;
|
|
1119
|
+
/** 应用关闭时取消全部活动运行 */
|
|
1120
|
+
close(): Promise<void>;
|
|
1121
|
+
/** 消费 runner 事件并写入日志,兜住所有退出路径补齐终态 */
|
|
1122
|
+
private execute;
|
|
1123
|
+
/** 原子追加事件并广播唤醒;终态之后的迟到事件直接忽略 */
|
|
1124
|
+
private publish;
|
|
1125
|
+
getRun(runId: string): Run;
|
|
1126
|
+
private sessionRun;
|
|
1127
|
+
/** 惰性清理超过保留期的终态运行;活动运行永不在这里删除 */
|
|
1128
|
+
private pruneExpired;
|
|
1129
|
+
}
|
|
1130
|
+
/** 路由层可直接转成统一错误响应的异常 */
|
|
1131
|
+
declare class HttpError extends Error {
|
|
1132
|
+
readonly status: number;
|
|
1133
|
+
constructor(status: number, message: string);
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
interface RoutesContext {
|
|
1137
|
+
resolver: EndpointResolver;
|
|
1138
|
+
store: AgentSessionStore;
|
|
1139
|
+
index: SessionIndex;
|
|
1140
|
+
registry: RunRegistry;
|
|
1141
|
+
/** 会话级路径授权登记表(提权协商的确认落点) */
|
|
1142
|
+
grants: EscalationGrants;
|
|
1143
|
+
/** 工具工厂:按会话构建工具集(授权清单需要 sessionId 才能生效) */
|
|
1144
|
+
makeTools: (sessionId: string) => AgentTool[];
|
|
1145
|
+
/** 提权事件展示的工作区根 */
|
|
1146
|
+
workdir: string;
|
|
1147
|
+
agentName?: string;
|
|
1148
|
+
persona?: string;
|
|
1149
|
+
/** 可选静态 Bearer token;配置后全部端点要求鉴权 */
|
|
1150
|
+
token?: string;
|
|
1151
|
+
}
|
|
1152
|
+
declare function createAgentRoutes(ctx: RoutesContext): Hono;
|
|
1153
|
+
|
|
1154
|
+
interface AgentServer {
|
|
1155
|
+
app: Hono;
|
|
1156
|
+
registry: RunRegistry;
|
|
1157
|
+
store: AgentSessionStore;
|
|
1158
|
+
index: SessionIndex;
|
|
1159
|
+
}
|
|
1160
|
+
/** 以代码方式装配服务(嵌入用法) */
|
|
1161
|
+
declare function createAgentServer(config: AppConfig, opts?: {
|
|
1162
|
+
configPath?: string;
|
|
1163
|
+
dataDir?: string;
|
|
1164
|
+
}): AgentServer;
|
|
1165
|
+
/** 以配置文件启动 HTTP 服务(CLI serve 命令) */
|
|
1166
|
+
declare function serveFromConfig(opts: {
|
|
1167
|
+
configPath?: string;
|
|
1168
|
+
port?: number;
|
|
1169
|
+
}): void;
|
|
1170
|
+
|
|
1171
|
+
export { APPROX_BYTES_PER_TOKEN, type AgentCompaction, type AgentDone, type AgentEscalation, type AgentEvent, type AgentEventType, type AgentRunOptions, AgentRunRecorder, AgentRunner, type AgentRunnerOptions, type AgentServiceConfig, AgentSessionStore, type AgentStartParams, type AgentTool, type AgentToolResult, AnthropicMessagesProtocol, type AppConfig, type BuiltinToolsOptions, COMPACT_PROMPT, COMPACT_TRIGGER_RATIO, type ChatMessage, type ChatRequest, type ChatResponse, type CompactionResult, type EndpointConfig, EndpointResolver, HttpError, LlmError, type LlmProtocol, type MessagesEndpointOptions, type ModelSettings, OpenAIResponsesProtocol, PREVIEW_MAX_CHARS, ProcessManager, RETAINED_USER_TOKEN_BUDGET, type ResolvedModel, type ResponsesEndpointOptions, RunRegistry, SESSION_FORMAT_VERSION, SUMMARY_PREFIX, type SandboxOptions, type ServerConfig, type SessionCompactionEntry, type SessionEntry, type SessionEscalationEntry, type SessionHeader, SessionIndex, type SessionMessageEntry, type SessionSummary, type SseEvent, type StoredAgentEvent, type StreamEvent, type SystemPromptOptions, TERMINAL_EVENT_TYPES, type TokenUsage, type ToolAnnotations, type ToolCall, ToolCallBuffer, type ToolContext, type ToolDefinition, type ToolHandlerResult, type ValidatedArgs, addUsage, agentCompactionSchema, agentDoneSchema, agentEscalationSchema, agentEventSchema, agentStartParamsSchema, agentToolResultSchema, buildAvailableToolsPrompt, buildReplacementHistory, buildSystemPrompt, builtinContextWindow, builtinTools, chatMessageSchema, compact, configExists, createAgentRoutes, createAgentServer, defaultConfigPath, defaultDataDir, defaultSessionsDir, emptyUsage, estimateTokens, formatProcessResult, isCompactionEntry, isEscalationEntry, isMessageEntry, isSummaryMessage, loadConfig, makeApplyPatchTool, makeCreateTool, makeEditTool, makeExecCommandTool, makeListTool, makeReadTool, makeSearchTool, makeWriteStdinTool, makeWriteTool, messageText, modelSettingsSchema, parseSse, removeEndpoint, resolveSandboxed, responseToMessage, saveConfig, serveFromConfig, shouldCompact, tokenUsageSchema, toolCallSchema, upsertEndpoint, validateToolCall };
|