@capybara-hq/kernel 0.1.0-rc.2 → 0.1.0-rc.3
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/dist/agents/agent-lookup.js +10 -2
- package/dist/agents/agents.service.js +19 -6
- package/dist/agents/definition.d.ts +31 -8
- package/dist/agents/definition.js +193 -17
- package/dist/agents/templates.js +19 -4
- package/dist/catalog/catalog-content.js +4 -1
- package/dist/catalog/claude/agents.js +13 -10
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/channels/cards.d.ts +8 -2
- package/dist/channels/cards.js +16 -8
- package/dist/config/schema.js +2 -2
- package/dist/conversations/artifacts.d.ts +1 -1
- package/dist/conversations/artifacts.js +1 -1
- package/dist/conversations/event-log.d.ts +11 -0
- package/dist/conversations/event-log.js +19 -0
- package/dist/conversations/events.d.ts +23 -3
- package/dist/conversations/events.js +26 -14
- package/dist/db/kernel-schema.d.ts +2 -2
- package/dist/evals/recorded-tools.d.ts +27 -1
- package/dist/evals/recorded-tools.js +85 -10
- package/dist/evals/run-replay.d.ts +5 -0
- package/dist/evals/run-replay.js +19 -5
- package/dist/evals/trajectory.d.ts +2 -2
- package/dist/identity/settings.js +1 -1
- package/dist/lifecycle/kernel-lifecycle.js +5 -0
- package/dist/orgs/settings.service.d.ts +2 -2
- package/dist/orgs/settings.service.js +2 -2
- package/dist/runtime/context/build.d.ts +6 -6
- package/dist/runtime/context/build.js +18 -8
- package/dist/runtime/context/claude-tools.d.ts +2 -1
- package/dist/runtime/context/claude-tools.js +9 -10
- package/dist/runtime/context/legacy-text.d.ts +22 -0
- package/dist/runtime/context/legacy-text.js +37 -0
- package/dist/runtime/context/skills.d.ts +29 -11
- package/dist/runtime/context/skills.js +37 -30
- package/dist/runtime/loop.d.ts +1 -1
- package/dist/runtime/model-call.js +1 -1
- package/dist/runtime/run-finish.d.ts +1 -1
- package/dist/runtime/run-queue.d.ts +3 -3
- package/dist/runtime/run-queue.js +2 -2
- package/dist/runtime/run-worker.d.ts +2 -2
- package/dist/runtime/run-worker.js +4 -4
- package/dist/runtime/subagents/definition.d.ts +1 -6
- package/dist/runtime/subagents/definition.js +11 -12
- package/dist/runtime/subagents/dispatch.d.ts +2 -2
- package/dist/runtime/subagents/dispatch.js +2 -2
- package/dist/runtime/subagents/org-agents.js +2 -1
- package/dist/runtime/subagents/roster.d.ts +1 -1
- package/dist/runtime/subagents/roster.js +1 -1
- package/dist/runtime/subagents/skill-fork.d.ts +2 -2
- package/dist/runtime/subagents/skill-fork.js +2 -2
- package/dist/runtime/subagents/subagents.service.d.ts +3 -3
- package/dist/runtime/subagents/subagents.service.js +3 -3
- package/dist/runtime/waits.d.ts +5 -5
- package/dist/runtime/waits.js +5 -5
- package/dist/skills/catalog.d.ts +4 -4
- package/dist/skills/catalog.js +4 -4
- package/dist/skills/changes.service.d.ts +2 -2
- package/dist/skills/changes.service.js +5 -4
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/invoke.d.ts +1 -1
- package/dist/skills/invoke.js +5 -4
- package/dist/tools/approvals.service.d.ts +6 -0
- package/dist/tools/approvals.service.js +19 -1
- package/dist/tools/builtin-names.d.ts +73 -0
- package/dist/tools/builtin-names.js +116 -0
- package/dist/tools/builtins/agent.d.ts +7 -7
- package/dist/tools/builtins/agent.js +7 -11
- package/dist/tools/builtins/ask-user.d.ts +1 -1
- package/dist/tools/builtins/ask-user.js +2 -2
- package/dist/tools/builtins/builtin-tools.d.ts +2 -2
- package/dist/tools/builtins/builtin-tools.js +2 -2
- package/dist/tools/builtins/read-tool-output.d.ts +1 -1
- package/dist/tools/builtins/read-tool-output.js +2 -2
- package/dist/tools/builtins/sandbox/bash.d.ts +5 -5
- package/dist/tools/builtins/sandbox/bash.js +31 -28
- package/dist/tools/builtins/sandbox/common.d.ts +3 -3
- package/dist/tools/builtins/sandbox/common.js +2 -2
- package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
- package/dist/tools/builtins/sandbox/deliver.js +11 -11
- package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
- package/dist/tools/builtins/sandbox/edit.js +41 -30
- package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
- package/dist/tools/builtins/sandbox/file-state.js +34 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob-match.js +1 -1
- package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob.js +4 -4
- package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
- package/dist/tools/builtins/sandbox/grep.js +147 -30
- package/dist/tools/builtins/sandbox/index.d.ts +1 -1
- package/dist/tools/builtins/sandbox/index.js +1 -1
- package/dist/tools/builtins/sandbox/read.d.ts +2 -2
- package/dist/tools/builtins/sandbox/read.js +21 -14
- package/dist/tools/builtins/sandbox/write.d.ts +1 -1
- package/dist/tools/builtins/sandbox/write.js +37 -33
- package/dist/tools/builtins/skill-load.d.ts +3 -3
- package/dist/tools/builtins/skill-load.js +32 -16
- package/dist/tools/builtins/skill-write.d.ts +4 -4
- package/dist/tools/builtins/skill-write.js +10 -10
- package/dist/tools/builtins/tool-search.d.ts +13 -9
- package/dist/tools/builtins/tool-search.js +25 -14
- package/dist/tools/connectors.service.js +4 -4
- package/dist/tools/display-names.d.ts +9 -0
- package/dist/tools/display-names.js +24 -0
- package/dist/tools/drift.js +5 -5
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/info.d.ts +20 -4
- package/dist/tools/info.js +55 -32
- package/dist/tools/legacy-data.d.ts +34 -0
- package/dist/tools/legacy-data.js +76 -0
- package/dist/tools/legacy-keys.d.ts +51 -0
- package/dist/tools/legacy-keys.js +115 -0
- package/dist/tools/naming.d.ts +1 -5
- package/dist/tools/naming.js +1 -7
- package/dist/tools/outputs.js +1 -1
- package/dist/tools/pipeline.d.ts +13 -7
- package/dist/tools/pipeline.js +97 -39
- package/dist/tools/policy.d.ts +1 -14
- package/dist/tools/policy.js +13 -19
- package/dist/tools/questions.controller.d.ts +1 -1
- package/dist/tools/questions.controller.js +1 -1
- package/dist/tools/questions.service.d.ts +1 -1
- package/dist/tools/registry.d.ts +16 -21
- package/dist/tools/registry.js +29 -37
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/tools.module.js +1 -1
- package/package.json +2 -2
- package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
- package/dist/tools/builtins/sandbox/names.d.ts +0 -7
- package/dist/tools/builtins/sandbox/names.js +0 -20
|
@@ -191,6 +191,25 @@ let EventLog = class EventLog {
|
|
|
191
191
|
.executeTakeFirst();
|
|
192
192
|
return r && toEvent(r);
|
|
193
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* The file state (`tool_result.view.file`) the latest `Read` / `Write` / `Edit` result of this
|
|
196
|
+
* conversation recorded for `path` (a normalized sandbox path); null when none did. One index
|
|
197
|
+
* probe per call: the partial index `conversation_events_file_state_idx` of migration 0063
|
|
198
|
+
* (conversation_id, view.file.path, seq DESC; tool_result rows only) answers it, also for a path
|
|
199
|
+
* never read (the query's predicate must keep matching that index's expression).
|
|
200
|
+
*/
|
|
201
|
+
async latestFileState(conversationId, path) {
|
|
202
|
+
const r = await this.db
|
|
203
|
+
.selectFrom("conversation_events")
|
|
204
|
+
.select(sql `payload->'view'->'file'`.as("file"))
|
|
205
|
+
.where("conversation_id", "=", conversationId)
|
|
206
|
+
.where("type", "=", "tool_result")
|
|
207
|
+
.where(sql `payload->'view'->'file'->>'path' = ${path}`)
|
|
208
|
+
.orderBy("seq", "desc")
|
|
209
|
+
.limit(1)
|
|
210
|
+
.executeTakeFirst();
|
|
211
|
+
return r ? { size: r.file.size, sha256: r.file.sha256 } : null;
|
|
212
|
+
}
|
|
194
213
|
validate(e) {
|
|
195
214
|
const r = ConversationEventSchema.safeParse({ type: e.type, payload: e.payload });
|
|
196
215
|
if (!r.success) {
|
|
@@ -86,10 +86,10 @@ export type LogContentBlock = Exclude<ContentBlock, MediaBlock> | (MediaBlock ex
|
|
|
86
86
|
} : never : never);
|
|
87
87
|
/**
|
|
88
88
|
* Structured view of a builtin tool's result (UI refresh B, spec §5.5 / §5.9): display only, like
|
|
89
|
-
* `display`. `command`: `
|
|
89
|
+
* `display`. `command`: `Bash` (the model's `description`, the exit code, null when the
|
|
90
90
|
* command was stopped, and whether it timed out; the web shows "Failed" for a non-zero exit even
|
|
91
|
-
* though `isError` stays false); `edit`: `
|
|
92
|
-
* `read`: `
|
|
91
|
+
* though `isError` stays false); `edit`: `Edit` / `Write` (a capped line diff);
|
|
92
|
+
* `read`: `Read` (the line range shown).
|
|
93
93
|
*/
|
|
94
94
|
export declare const ToolViewSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
95
95
|
kind: z.ZodLiteral<"command">;
|
|
@@ -103,6 +103,11 @@ export declare const ToolViewSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
103
103
|
added: z.ZodNumber;
|
|
104
104
|
removed: z.ZodNumber;
|
|
105
105
|
truncated: z.ZodBoolean;
|
|
106
|
+
file: z.ZodOptional<z.ZodObject<{
|
|
107
|
+
path: z.ZodString;
|
|
108
|
+
size: z.ZodNumber;
|
|
109
|
+
sha256: z.ZodString;
|
|
110
|
+
}, z.core.$strip>>;
|
|
106
111
|
hunks: z.ZodArray<z.ZodObject<{
|
|
107
112
|
oldStart: z.ZodNumber;
|
|
108
113
|
newStart: z.ZodNumber;
|
|
@@ -120,6 +125,11 @@ export declare const ToolViewSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
120
125
|
path: z.ZodString;
|
|
121
126
|
fromLine: z.ZodOptional<z.ZodNumber>;
|
|
122
127
|
toLine: z.ZodOptional<z.ZodNumber>;
|
|
128
|
+
file: z.ZodOptional<z.ZodObject<{
|
|
129
|
+
path: z.ZodString;
|
|
130
|
+
size: z.ZodNumber;
|
|
131
|
+
sha256: z.ZodString;
|
|
132
|
+
}, z.core.$strip>>;
|
|
123
133
|
}, z.core.$strip>], "kind">;
|
|
124
134
|
export type ToolView = z.infer<typeof ToolViewSchema>;
|
|
125
135
|
/**
|
|
@@ -441,6 +451,11 @@ export declare const ConversationEventSchema: z.ZodDiscriminatedUnion<[z.ZodObje
|
|
|
441
451
|
added: z.ZodNumber;
|
|
442
452
|
removed: z.ZodNumber;
|
|
443
453
|
truncated: z.ZodBoolean;
|
|
454
|
+
file: z.ZodOptional<z.ZodObject<{
|
|
455
|
+
path: z.ZodString;
|
|
456
|
+
size: z.ZodNumber;
|
|
457
|
+
sha256: z.ZodString;
|
|
458
|
+
}, z.core.$strip>>;
|
|
444
459
|
hunks: z.ZodArray<z.ZodObject<{
|
|
445
460
|
oldStart: z.ZodNumber;
|
|
446
461
|
newStart: z.ZodNumber;
|
|
@@ -458,6 +473,11 @@ export declare const ConversationEventSchema: z.ZodDiscriminatedUnion<[z.ZodObje
|
|
|
458
473
|
path: z.ZodString;
|
|
459
474
|
fromLine: z.ZodOptional<z.ZodNumber>;
|
|
460
475
|
toLine: z.ZodOptional<z.ZodNumber>;
|
|
476
|
+
file: z.ZodOptional<z.ZodObject<{
|
|
477
|
+
path: z.ZodString;
|
|
478
|
+
size: z.ZodNumber;
|
|
479
|
+
sha256: z.ZodString;
|
|
480
|
+
}, z.core.$strip>>;
|
|
461
481
|
}, z.core.$strip>], "kind">>;
|
|
462
482
|
card: z.ZodOptional<z.ZodObject<{
|
|
463
483
|
plugin: z.ZodString;
|
|
@@ -75,12 +75,22 @@ const STOP_REASONS = ["end_turn", "tool_use", "max_tokens", "refusal", "other"];
|
|
|
75
75
|
const EFFORT_ENUM = ["low", "medium", "high", "xhigh", "max"];
|
|
76
76
|
const seqNo = z.number().int().nonnegative();
|
|
77
77
|
const count = z.number().int().nonnegative();
|
|
78
|
+
/**
|
|
79
|
+
* The state of a file a `Read` / `Write` / `Edit` saw or left (display only, but the kernel reads it
|
|
80
|
+
* back from the log to decide read-before-write): the full normalized path, the file's full size and
|
|
81
|
+
* the sha256 of the bytes handled (the first bytes only for a file over `Read`'s byte limit).
|
|
82
|
+
*/
|
|
83
|
+
const FileStateViewSchema = z.object({
|
|
84
|
+
path: z.string().max(4096),
|
|
85
|
+
size: count,
|
|
86
|
+
sha256: z.string().regex(/^[0-9a-f]{64}$/),
|
|
87
|
+
});
|
|
78
88
|
/**
|
|
79
89
|
* Structured view of a builtin tool's result (UI refresh B, spec §5.5 / §5.9): display only, like
|
|
80
|
-
* `display`. `command`: `
|
|
90
|
+
* `display`. `command`: `Bash` (the model's `description`, the exit code, null when the
|
|
81
91
|
* command was stopped, and whether it timed out; the web shows "Failed" for a non-zero exit even
|
|
82
|
-
* though `isError` stays false); `edit`: `
|
|
83
|
-
* `read`: `
|
|
92
|
+
* though `isError` stays false); `edit`: `Edit` / `Write` (a capped line diff);
|
|
93
|
+
* `read`: `Read` (the line range shown).
|
|
84
94
|
*/
|
|
85
95
|
export const ToolViewSchema = z.discriminatedUnion("kind", [
|
|
86
96
|
z.object({
|
|
@@ -96,6 +106,7 @@ export const ToolViewSchema = z.discriminatedUnion("kind", [
|
|
|
96
106
|
added: count,
|
|
97
107
|
removed: count,
|
|
98
108
|
truncated: z.boolean(),
|
|
109
|
+
file: FileStateViewSchema.optional(),
|
|
99
110
|
hunks: z
|
|
100
111
|
.array(z.object({
|
|
101
112
|
oldStart: count,
|
|
@@ -114,6 +125,7 @@ export const ToolViewSchema = z.discriminatedUnion("kind", [
|
|
|
114
125
|
path: z.string().max(TOOL_VIEW_PATH_MAX_CHARS),
|
|
115
126
|
fromLine: count.optional(),
|
|
116
127
|
toLine: count.optional(),
|
|
128
|
+
file: FileStateViewSchema.optional(),
|
|
117
129
|
}),
|
|
118
130
|
]);
|
|
119
131
|
const ModelUsageShape = {
|
|
@@ -260,13 +272,13 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
260
272
|
*/
|
|
261
273
|
absorbedUpToSeq: seqNo.optional(),
|
|
262
274
|
/**
|
|
263
|
-
* 本次请求带给模型的工具(按发送顺序:未启用
|
|
275
|
+
* 本次请求带给模型的工具(按发送顺序:未启用 ToolSearch 时按 key 排序;启用时为内置工具按 key 排序,
|
|
264
276
|
* 其后是已加载工具按首次加载顺序)及其定义指纹(`ResolvedTool.specHash`)。
|
|
265
277
|
* 模型不支持工具时为空数组。较早的事件可能没有。
|
|
266
278
|
*/
|
|
267
279
|
tools: z.array(z.object({ key: z.string(), specHash: z.string() })).optional(),
|
|
268
280
|
/**
|
|
269
|
-
* 启用
|
|
281
|
+
* 启用 ToolSearch 时 system 第二块目录里的工具(按 key 排序)及定义指纹;定义同样存在
|
|
270
282
|
* `capybara.tool_specs`,目录文本可由它们还原。未启用时不写。
|
|
271
283
|
*/
|
|
272
284
|
catalog: z.array(z.object({ key: z.string(), specHash: z.string() })).optional(),
|
|
@@ -339,7 +351,7 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
339
351
|
outputId: z.string().optional(),
|
|
340
352
|
contentTypes: z.array(z.string()).optional(),
|
|
341
353
|
/**
|
|
342
|
-
* `
|
|
354
|
+
* `ToolSearch` 本次加载的工具 key(没有匹配时不写)。已加载集合 = 会话中全部 tool_result 的
|
|
343
355
|
* `loadedTools` 并集(含已被摘要覆盖的部分),构建请求时由日志还原,不放进程内存。
|
|
344
356
|
*/
|
|
345
357
|
loadedTools: z.array(z.string()).optional(),
|
|
@@ -395,7 +407,7 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
395
407
|
reason: z.string().max(APPROVAL_DENY_REASON_MAX_CHARS).optional(),
|
|
396
408
|
})),
|
|
397
409
|
/**
|
|
398
|
-
* 工具调用需要用户输入(`
|
|
410
|
+
* 工具调用需要用户输入(`AskUserQuestion`、插件工具的 `input_required`、MCP elicitation):输入请求已建,
|
|
399
411
|
* run 暂停等待回答。界面据此显示表单卡片(不进模型请求)。
|
|
400
412
|
*/
|
|
401
413
|
ev("question_asked", z.object({
|
|
@@ -423,7 +435,7 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
423
435
|
reason: z.enum(["provider_rejected"]),
|
|
424
436
|
})),
|
|
425
437
|
/**
|
|
426
|
-
* agent 经 `
|
|
438
|
+
* agent 经 `Deliver` 把沙箱里的文件交付给用户(M5 T8,C3):字节在对象存储
|
|
427
439
|
* `kernel/<orgId>/<objectKey>`(`objectKey` = `artifacts/<conversationId>/<artifactId>`,相对内核前缀),
|
|
428
440
|
* 这里只有元数据。网页从日志重建产物列表;不进模型请求(模型看到的是同一调用的 tool_result 确认)。
|
|
429
441
|
*/
|
|
@@ -439,7 +451,7 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
439
451
|
/**
|
|
440
452
|
* 本对话此刻生效的技能(M5 T14,Ruling M17):运行开始时内核解析生效的技能集合(agent 版本选中的组织技能 +
|
|
441
453
|
* agent 自己的技能,未删除,取 current_version),与日志里上一份快照不同才写。模型看到的技能目录只来自这里:
|
|
442
|
-
* 第一份(在任何 `model_call` 之前)进 system 缓存段,之后的在所在位置渲染为英文变更提醒;`
|
|
454
|
+
* 第一份(在任何 `model_call` 之前)进 system 缓存段,之后的在所在位置渲染为英文变更提醒;`Skill` 按最新一份
|
|
443
455
|
* 把名字解析为 id 与版本。按 name 排序。
|
|
444
456
|
*/
|
|
445
457
|
ev("skills_catalog", z.object({
|
|
@@ -451,12 +463,12 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
451
463
|
version: z.number().int().positive(),
|
|
452
464
|
/**
|
|
453
465
|
* 内容来源(对象前缀,T15):已生成的版本为 `skill_versions.object_prefix`,试用中的草稿为申请的
|
|
454
|
-
* `object_prefix`。同号的草稿与正式版本靠它区分;`
|
|
466
|
+
* `object_prefix`。同号的草稿与正式版本靠它区分;`Skill` 只按它解析。
|
|
455
467
|
*/
|
|
456
468
|
source: z.string().min(1).max(512),
|
|
457
469
|
/**
|
|
458
470
|
* The catalog item (plugin) name the skill came from (phase B); absent for the org's
|
|
459
|
-
* own and the agent's skills, and in snapshots written before phase B. `
|
|
471
|
+
* own and the agent's skills, and in snapshots written before phase B. `Skill`
|
|
460
472
|
* resolves `<plugin>:<name>` with it; it is not model-visible otherwise.
|
|
461
473
|
*/
|
|
462
474
|
plugin: z.string().min(1).max(64).optional(),
|
|
@@ -465,7 +477,7 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
465
477
|
/**
|
|
466
478
|
* Pinned skills (phase B, spec §9.1) in the agent's order: each a skill of `skills` (same
|
|
467
479
|
* id, version and source) with its SKILL.md body as read at run start or written by
|
|
468
|
-
*
|
|
480
|
+
* SkillWrite. Absent means none (every snapshot before phase B).
|
|
469
481
|
*/
|
|
470
482
|
pinned: z
|
|
471
483
|
.array(z.object({
|
|
@@ -534,7 +546,7 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
534
546
|
warnings: z.array(z.string()).optional(),
|
|
535
547
|
})),
|
|
536
548
|
/**
|
|
537
|
-
* Parent log (phase C, spec §14.1): the `
|
|
549
|
+
* Parent log (phase C, spec §14.1): the `Agent` call `callId` started (or resumed) the sub-agent
|
|
538
550
|
* `subagentId` (its child conversation id) with run `childRunId`. Not model-visible: the model
|
|
539
551
|
* sees the call's tool_call / tool_result pair.
|
|
540
552
|
*/
|
|
@@ -550,7 +562,7 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
550
562
|
tierFallback: z.boolean().optional(),
|
|
551
563
|
/**
|
|
552
564
|
* Phase D: the seq of the person's fork invocation this dispatch runs (`callId` is
|
|
553
|
-
* `skill-<seq>`, step 0, no tool call); absent for an `
|
|
565
|
+
* `skill-<seq>`, step 0, no tool call); absent for an `Agent` call.
|
|
554
566
|
*/
|
|
555
567
|
invokedSeq: seqNo.optional(),
|
|
556
568
|
})),
|
|
@@ -269,7 +269,7 @@ export interface RunsTable {
|
|
|
269
269
|
/** 0054: when this run's `subagents` wait expires (set while it waits on sub-agents). */
|
|
270
270
|
wait_expires_at: TsNullable;
|
|
271
271
|
}
|
|
272
|
-
/** 0053: one row per sub-agent dispatch (an `
|
|
272
|
+
/** 0053: one row per sub-agent dispatch (an `Agent` call of a parent run). */
|
|
273
273
|
export interface SubagentDispatchesTable {
|
|
274
274
|
parent_run_id: string;
|
|
275
275
|
parent_call_id: string;
|
|
@@ -400,7 +400,7 @@ export interface ApprovalsTable {
|
|
|
400
400
|
/** 0056: the reason given with a denial (null without one). */
|
|
401
401
|
deny_reason: Generated<string | null>;
|
|
402
402
|
}
|
|
403
|
-
/** 0010_tools.sql:
|
|
403
|
+
/** 0010_tools.sql:AskUserQuestion 提问。 */
|
|
404
404
|
export interface QuestionsTable {
|
|
405
405
|
id: string;
|
|
406
406
|
org_id: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { EventLog } from "../conversations/event-log.js";
|
|
2
|
+
import { type LegacyScope } from "../tools/legacy-keys.js";
|
|
2
3
|
import { type ToolPipeline, type ToolStepContext } from "../tools/pipeline.js";
|
|
3
4
|
import type { CaseSnapshot } from "./snapshot.js";
|
|
4
5
|
/**
|
|
@@ -15,12 +16,34 @@ export interface RecordedCall {
|
|
|
15
16
|
inputKey: string;
|
|
16
17
|
content: string;
|
|
17
18
|
isError: boolean;
|
|
18
|
-
/** 原结果里的 `
|
|
19
|
+
/** 原结果里的 `ToolSearch` 已加载工具(照抄:之后请求的已加载集合由日志还原)。 */
|
|
19
20
|
loadedTools?: string[];
|
|
20
21
|
contentTypes?: string[];
|
|
21
22
|
/** 原 `tool_call_started` 的定义指纹(没有开始事件的调用为空串)。 */
|
|
22
23
|
specHash: string;
|
|
24
|
+
/** The recorded call used release-candidate names; `toolKey` and `inputKey` are already the current ones. */
|
|
25
|
+
legacy?: true;
|
|
23
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The connectors and extensions an rc `<x>__<tool>` key can name, from positive evidence in the
|
|
29
|
+
* snapshot only (a head with no evidence, or evidence of both kinds, stays unmapped, so its
|
|
30
|
+
* recorded calls are unmatched, which is a safe miss):
|
|
31
|
+
* - a connector: the tool definition the key was recorded with (`toolSpecs`, found by the specHash of
|
|
32
|
+
* its `tool_call_started` or its `model_call` tools / catalog entry) has `connectorData`;
|
|
33
|
+
* - an extension: that definition exists without `connectorData` and its name is the key's tool
|
|
34
|
+
* part, or an agent definition names exactly that tool as a `{ kind: "plugin", plugin: x, name }` ref.
|
|
35
|
+
*/
|
|
36
|
+
export declare function legacyScopeOf(s: CaseSnapshot): LegacyScope;
|
|
37
|
+
/**
|
|
38
|
+
* A recorded call in the current names: an rc builtin or `<x>__<tool>` key becomes its current
|
|
39
|
+
* key with the input's parameters renamed. Only the recorded side is ever normalized; a call
|
|
40
|
+
* already in current names (or one that cannot be mapped) is returned as is.
|
|
41
|
+
*/
|
|
42
|
+
export declare function currentCall(name: string, input: unknown, scope: LegacyScope): {
|
|
43
|
+
name: string;
|
|
44
|
+
input: unknown;
|
|
45
|
+
legacy: boolean;
|
|
46
|
+
};
|
|
24
47
|
/** 规范化 JSON:对象键递归按码点排序,数组保持顺序;`undefined` 按 JSON 规则省略。 */
|
|
25
48
|
export declare function canonicalJson(v: unknown): string;
|
|
26
49
|
/** The matching key of a call: the canonical JSON of its input without the ignored fields. */
|
|
@@ -43,7 +66,10 @@ export declare class RecordedToolPipeline implements Pick<ToolPipeline, "runStep
|
|
|
43
66
|
private readonly d;
|
|
44
67
|
private readonly used;
|
|
45
68
|
private misses;
|
|
69
|
+
private legacyHits;
|
|
46
70
|
constructor(d: RecordedToolPipelineDeps);
|
|
71
|
+
/** Calls so far matched with a recording made under release-candidate tool names. */
|
|
72
|
+
legacyMatches(): number;
|
|
47
73
|
/** 至今没有匹配到记录的调用数。 */
|
|
48
74
|
unmatched(): number;
|
|
49
75
|
runStep(ctx: ToolStepContext): Promise<{
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { assistantIdemKey } from "../runtime/model-call.js";
|
|
2
|
+
import { MATCH_IGNORED_FIELDS } from "../tools/builtin-names.js";
|
|
3
|
+
import { isLegacyPrefixedKey, legacyToolInput, legacyToolKey, } from "../tools/legacy-keys.js";
|
|
2
4
|
import { RUN_STOPPED_TEXT } from "../tools/pipeline.js";
|
|
3
5
|
/**
|
|
4
6
|
* 整轮回放的工具管线(C6 / Review Focus 3):只回放原运行记录的工具结果,**从不执行任何工具**——
|
|
@@ -7,6 +9,77 @@ import { RUN_STOPPED_TEXT } from "../tools/pipeline.js";
|
|
|
7
9
|
*/
|
|
8
10
|
/** 没有匹配记录时模型看到的工具结果(模型可见,英文)。 */
|
|
9
11
|
export const REPLAY_NO_RECORDING = "[replay] No recorded result matches this tool call (same tool and arguments); the tool was not executed during replay.";
|
|
12
|
+
/**
|
|
13
|
+
* The connectors and extensions an rc `<x>__<tool>` key can name, from positive evidence in the
|
|
14
|
+
* snapshot only (a head with no evidence, or evidence of both kinds, stays unmapped, so its
|
|
15
|
+
* recorded calls are unmatched, which is a safe miss):
|
|
16
|
+
* - a connector: the tool definition the key was recorded with (`toolSpecs`, found by the specHash of
|
|
17
|
+
* its `tool_call_started` or its `model_call` tools / catalog entry) has `connectorData`;
|
|
18
|
+
* - an extension: that definition exists without `connectorData` and its name is the key's tool
|
|
19
|
+
* part, or an agent definition names exactly that tool as a `{ kind: "plugin", plugin: x, name }` ref.
|
|
20
|
+
*/
|
|
21
|
+
export function legacyScopeOf(s) {
|
|
22
|
+
const hashes = new Map();
|
|
23
|
+
const note = (key, hash) => {
|
|
24
|
+
if (!isLegacyPrefixedKey(key))
|
|
25
|
+
return;
|
|
26
|
+
const set = hashes.get(key) ?? new Set();
|
|
27
|
+
if (hash !== undefined && hash !== "")
|
|
28
|
+
set.add(hash);
|
|
29
|
+
hashes.set(key, set);
|
|
30
|
+
};
|
|
31
|
+
for (const e of s.events) {
|
|
32
|
+
if (e.type === "tool_call_started") {
|
|
33
|
+
const p = e.payload;
|
|
34
|
+
note(p.toolKey, p.specHash);
|
|
35
|
+
}
|
|
36
|
+
else if (e.type === "model_call") {
|
|
37
|
+
const r = e.payload.request;
|
|
38
|
+
for (const t of [...(r?.tools ?? []), ...(r?.catalog ?? [])])
|
|
39
|
+
note(t.key, t.specHash);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const extensionNames = new Set();
|
|
43
|
+
const connectorSlugs = new Set();
|
|
44
|
+
const planted = new Set();
|
|
45
|
+
for (const def of Object.values(s.definitions)) {
|
|
46
|
+
for (const t of def.tools)
|
|
47
|
+
if (t.kind === "plugin")
|
|
48
|
+
planted.add(`${t.plugin}__${t.name}`);
|
|
49
|
+
}
|
|
50
|
+
for (const [key, set] of hashes) {
|
|
51
|
+
const i = key.indexOf("__");
|
|
52
|
+
const head = key.slice(0, i);
|
|
53
|
+
const tool = key.slice(i + 2);
|
|
54
|
+
for (const h of set) {
|
|
55
|
+
const spec = s.toolSpecs[h];
|
|
56
|
+
if (spec === undefined)
|
|
57
|
+
continue;
|
|
58
|
+
if (spec.connectorData !== undefined) {
|
|
59
|
+
connectorSlugs.add(head);
|
|
60
|
+
}
|
|
61
|
+
else if (spec.name === tool) {
|
|
62
|
+
extensionNames.add(head);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
for (const key of planted) {
|
|
67
|
+
if (hashes.has(key))
|
|
68
|
+
extensionNames.add(key.slice(0, key.indexOf("__")));
|
|
69
|
+
}
|
|
70
|
+
return { connectorSlugs, extensionNames };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A recorded call in the current names: an rc builtin or `<x>__<tool>` key becomes its current
|
|
74
|
+
* key with the input's parameters renamed. Only the recorded side is ever normalized; a call
|
|
75
|
+
* already in current names (or one that cannot be mapped) is returned as is.
|
|
76
|
+
*/
|
|
77
|
+
export function currentCall(name, input, scope) {
|
|
78
|
+
const key = legacyToolKey(name, scope);
|
|
79
|
+
if (key === null)
|
|
80
|
+
return { name, input, legacy: false };
|
|
81
|
+
return { name: key, input: legacyToolInput(name, input), legacy: true };
|
|
82
|
+
}
|
|
10
83
|
/** 规范化 JSON:对象键递归按码点排序,数组保持顺序;`undefined` 按 JSON 规则省略。 */
|
|
11
84
|
export function canonicalJson(v) {
|
|
12
85
|
const norm = (x) => {
|
|
@@ -23,14 +96,6 @@ export function canonicalJson(v) {
|
|
|
23
96
|
};
|
|
24
97
|
return JSON.stringify(norm(v) ?? null);
|
|
25
98
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Input fields left out when matching, per tool: display-only arguments the model writes that do not
|
|
28
|
-
* change what the tool does. `sandbox_bash`'s `description` became required in UI refresh B, so a
|
|
29
|
-
* recording without it and a replayed call with one (or a different wording) still match.
|
|
30
|
-
*/
|
|
31
|
-
const MATCH_IGNORED_FIELDS = {
|
|
32
|
-
sandbox_bash: ["description"],
|
|
33
|
-
};
|
|
34
99
|
/** The matching key of a call: the canonical JSON of its input without the ignored fields. */
|
|
35
100
|
export function matchKey(toolKey, input) {
|
|
36
101
|
const ignored = MATCH_IGNORED_FIELDS[toolKey];
|
|
@@ -64,6 +129,7 @@ export function recordedCalls(s) {
|
|
|
64
129
|
started.set(p.callId, p.specHash);
|
|
65
130
|
}
|
|
66
131
|
}
|
|
132
|
+
const scope = legacyScopeOf(s);
|
|
67
133
|
const out = [];
|
|
68
134
|
for (const e of own) {
|
|
69
135
|
if (e.type !== "assistant_message")
|
|
@@ -76,9 +142,11 @@ export function recordedCalls(s) {
|
|
|
76
142
|
const r = results.get(call.id);
|
|
77
143
|
if (!r)
|
|
78
144
|
continue;
|
|
145
|
+
const cur = currentCall(call.name, call.input, scope);
|
|
79
146
|
out.push({
|
|
80
|
-
toolKey:
|
|
81
|
-
inputKey: matchKey(
|
|
147
|
+
toolKey: cur.name,
|
|
148
|
+
inputKey: matchKey(cur.name, cur.input),
|
|
149
|
+
...(cur.legacy && { legacy: true }),
|
|
82
150
|
content: r.content,
|
|
83
151
|
isError: r.isError,
|
|
84
152
|
...(r.loadedTools !== undefined && { loadedTools: r.loadedTools }),
|
|
@@ -98,9 +166,14 @@ export class RecordedToolPipeline {
|
|
|
98
166
|
d;
|
|
99
167
|
used = new Set();
|
|
100
168
|
misses = 0;
|
|
169
|
+
legacyHits = 0;
|
|
101
170
|
constructor(d) {
|
|
102
171
|
this.d = d;
|
|
103
172
|
}
|
|
173
|
+
/** Calls so far matched with a recording made under release-candidate tool names. */
|
|
174
|
+
legacyMatches() {
|
|
175
|
+
return this.legacyHits;
|
|
176
|
+
}
|
|
104
177
|
/** 至今没有匹配到记录的调用数。 */
|
|
105
178
|
unmatched() {
|
|
106
179
|
return this.misses;
|
|
@@ -162,6 +235,8 @@ export class RecordedToolPipeline {
|
|
|
162
235
|
if (i < 0)
|
|
163
236
|
return undefined;
|
|
164
237
|
this.used.add(i);
|
|
238
|
+
if (this.d.recordings[i]?.legacy === true)
|
|
239
|
+
this.legacyHits++;
|
|
165
240
|
return this.d.recordings[i];
|
|
166
241
|
}
|
|
167
242
|
}
|
|
@@ -37,6 +37,11 @@ export interface RunReplayResult {
|
|
|
37
37
|
usage: ModelUsage;
|
|
38
38
|
steps: number;
|
|
39
39
|
unmatched: number;
|
|
40
|
+
/**
|
|
41
|
+
* Set when a call was matched with a recording made under the release-candidate tool names
|
|
42
|
+
* (`sandbox_edit` for `Edit`, `docs__search` for `mcp__docs__search`, old parameter names).
|
|
43
|
+
*/
|
|
44
|
+
legacyKeyMatch?: true;
|
|
40
45
|
}
|
|
41
46
|
/** 原运行(基线)的同形摘要。 */
|
|
42
47
|
export type RunBaseline = Omit<RunReplayResult, "conversationId" | "outcome" | "unmatched">;
|
package/dist/evals/run-replay.js
CHANGED
|
@@ -22,7 +22,7 @@ import { RunError } from "../runtime/model-call.js";
|
|
|
22
22
|
import { recordedSkillForks } from "../runtime/subagents/skill-fork.js";
|
|
23
23
|
import { skillsCatalogIdemKey } from "../skills/catalog.js";
|
|
24
24
|
import { ACTIVE_EVAL_STATUSES, addUsage, consumeTokens, TOO_MANY_ERRORS, usageTokens, } from "./budget.js";
|
|
25
|
-
import { RecordedToolPipeline, recordedCalls } from "./recorded-tools.js";
|
|
25
|
+
import { currentCall, legacyScopeOf, RecordedToolPipeline, recordedCalls, } from "./recorded-tools.js";
|
|
26
26
|
/** 写种子时发现已失去认领或运行已不在执行:本次执行停下,不留评测对话。 */
|
|
27
27
|
export class ReplayClaimLost extends Error {
|
|
28
28
|
constructor() {
|
|
@@ -177,7 +177,7 @@ const ZERO = {
|
|
|
177
177
|
cacheWriteTokens: 0,
|
|
178
178
|
};
|
|
179
179
|
/** 一次运行的工具调用序列、最后的回复、停止原因、用量与步数(基线与候选同一算法)。 */
|
|
180
|
-
function summarize(events, runId) {
|
|
180
|
+
function summarize(events, runId, scope) {
|
|
181
181
|
const toolCalls = [];
|
|
182
182
|
let usage = ZERO;
|
|
183
183
|
let last = null;
|
|
@@ -189,8 +189,14 @@ function summarize(events, runId) {
|
|
|
189
189
|
const p = e.payload;
|
|
190
190
|
steps.add(p.step);
|
|
191
191
|
for (const b of p.content) {
|
|
192
|
-
if (b.type
|
|
192
|
+
if (b.type !== "tool_call")
|
|
193
|
+
continue;
|
|
194
|
+
if (scope === undefined)
|
|
193
195
|
toolCalls.push({ name: b.name, input: b.input });
|
|
196
|
+
else {
|
|
197
|
+
const { name, input } = currentCall(b.name, b.input, scope);
|
|
198
|
+
toolCalls.push({ name, input });
|
|
199
|
+
}
|
|
194
200
|
}
|
|
195
201
|
last = { content: p.content, stopReason: p.stopReason };
|
|
196
202
|
}
|
|
@@ -214,7 +220,9 @@ function summarize(events, runId) {
|
|
|
214
220
|
}
|
|
215
221
|
/** 原运行(快照)的摘要,作为整轮回放的基线。 */
|
|
216
222
|
export function runBaseline(s) {
|
|
217
|
-
|
|
223
|
+
// an rc recording is read in the current tool names, so the diff against a candidate only
|
|
224
|
+
// shows real differences
|
|
225
|
+
return summarize(s.events, s.runId, legacyScopeOf(s));
|
|
218
226
|
}
|
|
219
227
|
/**
|
|
220
228
|
* 删掉一个评测对话(崩溃重跑前清掉上一次的残留):先删它各次运行的 checkpoint,再删对话(事件、运行随之级联删除)。
|
|
@@ -558,5 +566,11 @@ export async function replayRun(d, s, candidate, evalRunId, signal) {
|
|
|
558
566
|
});
|
|
559
567
|
await Promise.allSettled([...charges]);
|
|
560
568
|
const summary = summarize(await readAll(eventLog, conversationId), runId);
|
|
561
|
-
return {
|
|
569
|
+
return {
|
|
570
|
+
conversationId,
|
|
571
|
+
outcome: outcome.kind,
|
|
572
|
+
...summary,
|
|
573
|
+
unmatched: pipeline.unmatched(),
|
|
574
|
+
...(pipeline.legacyMatches() > 0 && { legacyKeyMatch: true }),
|
|
575
|
+
};
|
|
562
576
|
}
|
|
@@ -54,7 +54,7 @@ export interface TrajectoryToolCall {
|
|
|
54
54
|
byAccountId: string | null;
|
|
55
55
|
decidedAt: string | null;
|
|
56
56
|
} | null;
|
|
57
|
-
/** 最近一次输入请求(`
|
|
57
|
+
/** 最近一次输入请求(`AskUserQuestion`、插件 `input_required`、MCP elicitation)。 */
|
|
58
58
|
question: {
|
|
59
59
|
questionId: string;
|
|
60
60
|
askedAt: string;
|
|
@@ -64,7 +64,7 @@ export interface TrajectoryToolCall {
|
|
|
64
64
|
/** A `tool.preExecute` policy hook denied the call (it never started). */
|
|
65
65
|
hookDenied?: TrajectoryHookDenial;
|
|
66
66
|
/**
|
|
67
|
-
* An `
|
|
67
|
+
* An `Agent` call that dispatched (or resumed) a sub-agent (phase C, spec §15.4): the child
|
|
68
68
|
* conversation (`subagentId`, whose trajectory the viewer links to), the run it started and that
|
|
69
69
|
* run's end (`running` until its `subagent_finished`).
|
|
70
70
|
*/
|
|
@@ -68,7 +68,7 @@ export const DEPLOYMENT_SETTINGS = z.object({
|
|
|
68
68
|
/** 组织能否自建连接器(不经企业目录)。 */
|
|
69
69
|
customConnectors: CustomPolicy.default("allow"),
|
|
70
70
|
/**
|
|
71
|
-
* 组织能否自建技能(不经企业目录):deny 时组织管理员不能上传技能包。agent 自写技能(`
|
|
71
|
+
* 组织能否自建技能(不经企业目录):deny 时组织管理员不能上传技能包。agent 自写技能(`SkillWrite`,私有 agent 的
|
|
72
72
|
* agent 级技能与共享 agent 经负责人审批的变更)不受此开关约束——那是 agent 定义的一部分,由 R3 / R4 把关。
|
|
73
73
|
*/
|
|
74
74
|
customSkills: CustomPolicy.default("allow"),
|
|
@@ -36,6 +36,7 @@ import { GatewayRole } from "../roles/gateway-role.js";
|
|
|
36
36
|
import { WorkerRole } from "../roles/worker-role.js";
|
|
37
37
|
import { UsageReporter } from "../runtime/usage-report.js";
|
|
38
38
|
import { sandboxConfigWarnings } from "../sandbox/sandbox.service.js";
|
|
39
|
+
import { warnLegacyToolKeys } from "../tools/legacy-data.js";
|
|
39
40
|
import { KERNEL_APP_OPTIONS } from "./tokens.js";
|
|
40
41
|
/**
|
|
41
42
|
* The stop phase budgets. Each phase waits `min(its budget, what is left of the total)`, where the
|
|
@@ -193,6 +194,10 @@ let KernelLifecycle = class KernelLifecycle {
|
|
|
193
194
|
// In flight for the stop: aborted when the shutdown begins, which then waits for its session to end
|
|
194
195
|
await this.shutdown.trackInFlight(migrate(config.db.url, { schema: KERNEL_SCHEMA, dir: KERNEL_MIGRATIONS_DIR }, { connectTimeoutMs: config.db.connectTimeoutMs, signal: this.shutdown.signal }));
|
|
195
196
|
this.checkpoint();
|
|
197
|
+
// Rows still holding a release-candidate tool key that migration 0063 could not map: one
|
|
198
|
+
// read-only count, a WARN when there are any (tool naming spec §8.2); never blocks the start
|
|
199
|
+
await warnLegacyToolKeys(this.kdb.db, this.log).catch((e) => this.log.warn("tools.legacy_key_count_failed", { error: errMsg(e) }));
|
|
200
|
+
this.checkpoint();
|
|
196
201
|
// official 清单来源按配置同步(幂等;每个副本启动时都做)
|
|
197
202
|
await this.marketplaces.syncOfficialFromConfig();
|
|
198
203
|
// The bootstrap plugins (spec §7), once per manifest across replicas (the Redis lock
|
|
@@ -8,10 +8,10 @@ import { OrgLock } from "./org-lock.js";
|
|
|
8
8
|
/**
|
|
9
9
|
* 组织设置(`capybara.orgs.settings` jsonb)。读取宽松:缺失或非法的字段按默认值,未知键保留不动
|
|
10
10
|
* (更新时与存量合并),新版本加字段不需要迁移。
|
|
11
|
-
* - `toolSearch`:工具超过阈值时是否改用目录 + `
|
|
11
|
+
* - `toolSearch`:工具超过阈值时是否改用目录 + `ToolSearch`(D11,默认 on)。
|
|
12
12
|
* - `locale`:组织默认语言(`zh` / `en`,默认 en),机器人在 IM 里说的固定话术按它选择。
|
|
13
13
|
* - `sandboxToolPolicy`:沙箱工具的默认策略(M5 T8,默认 allow)。为 `ask` 时除只读的
|
|
14
|
-
* `
|
|
14
|
+
* `Read` / `Glob` / `Grep` 外都需要审批(执行时实时读取)。
|
|
15
15
|
* - `sandboxEgress`:组织的沙箱出站(Ruling M19 / D6),缺省跟随部署的 `sandbox.limits.egress` + `allowHosts`。
|
|
16
16
|
* 见 {@link effectiveSandboxEgress}。存量值非法时按 `none` 读(宁可断网,不悄悄放宽到部署默认)。
|
|
17
17
|
*/
|
|
@@ -21,10 +21,10 @@ import { OrgLock } from "./org-lock.js";
|
|
|
21
21
|
/**
|
|
22
22
|
* 组织设置(`capybara.orgs.settings` jsonb)。读取宽松:缺失或非法的字段按默认值,未知键保留不动
|
|
23
23
|
* (更新时与存量合并),新版本加字段不需要迁移。
|
|
24
|
-
* - `toolSearch`:工具超过阈值时是否改用目录 + `
|
|
24
|
+
* - `toolSearch`:工具超过阈值时是否改用目录 + `ToolSearch`(D11,默认 on)。
|
|
25
25
|
* - `locale`:组织默认语言(`zh` / `en`,默认 en),机器人在 IM 里说的固定话术按它选择。
|
|
26
26
|
* - `sandboxToolPolicy`:沙箱工具的默认策略(M5 T8,默认 allow)。为 `ask` 时除只读的
|
|
27
|
-
* `
|
|
27
|
+
* `Read` / `Glob` / `Grep` 外都需要审批(执行时实时读取)。
|
|
28
28
|
* - `sandboxEgress`:组织的沙箱出站(Ruling M19 / D6),缺省跟随部署的 `sandbox.limits.egress` + `allowHosts`。
|
|
29
29
|
* 见 {@link effectiveSandboxEgress}。存量值非法时按 `none` 读(宁可断网,不悄悄放宽到部署默认)。
|
|
30
30
|
*/
|
|
@@ -25,13 +25,13 @@ export interface ModelCallMeta {
|
|
|
25
25
|
params: Record<string, ParamValue>;
|
|
26
26
|
/**
|
|
27
27
|
* 请求带的工具(按发送顺序)及定义指纹;定义本身按指纹存在 `capybara.tool_specs`。
|
|
28
|
-
* 未启用
|
|
28
|
+
* 未启用 ToolSearch 时按 key 排序;启用时见 {@link BuildModelRequestInput.toolSearch}。
|
|
29
29
|
*/
|
|
30
30
|
tools: {
|
|
31
31
|
key: string;
|
|
32
32
|
specHash: string;
|
|
33
33
|
}[];
|
|
34
|
-
/** 启用
|
|
34
|
+
/** 启用 ToolSearch 时 system 第二块目录里的工具(按 key 排序)及定义指纹;未启用没有该字段。 */
|
|
35
35
|
catalog?: {
|
|
36
36
|
key: string;
|
|
37
37
|
specHash: string;
|
|
@@ -75,8 +75,8 @@ export interface BuildModelRequestInput {
|
|
|
75
75
|
*/
|
|
76
76
|
tools?: RequestTool[];
|
|
77
77
|
/**
|
|
78
|
-
* 启用
|
|
79
|
-
* - `tools` 只放内置工具(含 `
|
|
78
|
+
* 启用 ToolSearch(spec 5.5,由 `ToolRegistry.forAgent` 判定)。启用且有工具时:
|
|
79
|
+
* - `tools` 只放内置工具(含 `ToolSearch`,按 key 排序)与**已加载**工具的完整定义;
|
|
80
80
|
* 已加载 = 日志中全部 `tool_result.loadedTools` 的并集(含摘要之前的;不在本步可用工具中的忽略),
|
|
81
81
|
* 按首次加载顺序追加在内置工具之后——新加载只在末尾追加,已发送的工具顺序不变;
|
|
82
82
|
* - 其余工具(不论是否已加载)以目录形式放进 system 第二个块(按 key 排序,打缓存断点),
|
|
@@ -224,7 +224,7 @@ export declare function summaryText(summary: string): string;
|
|
|
224
224
|
* 由会话事件日志 + agent 定义构建模型请求(纯函数,不做 I/O)。
|
|
225
225
|
* - system:`BEHAVIOR_RULES + "\n\n" + agent.instructions` 一个块,打缓存断点(a sub-agent's log:
|
|
226
226
|
* `BEHAVIOR_RULES`, its preamble and its instructions, all from its `subagent_started`);日志里第一份 `skills_catalog`
|
|
227
|
-
* 快照在任何 `model_call` 之前时,技能目录接在这个块末尾(Ruling M17,见 ./skills.ts);启用
|
|
227
|
+
* 快照在任何 `model_call` 之前时,技能目录接在这个块末尾(Ruling M17,见 ./skills.ts);启用 ToolSearch 时
|
|
228
228
|
* 第二个块是工具目录(见 {@link BuildModelRequestInput.toolSearch});
|
|
229
229
|
* - 之后的 `skills_catalog` 在所在位置渲染为 system 变更提醒;被压缩摘要覆盖的,若摘要时生效的目录与 system 里的
|
|
230
230
|
* 不同,紧随摘要补一条完整的当前目录;
|
|
@@ -245,7 +245,7 @@ export declare function buildModelRequest(input: BuildModelRequestInput): {
|
|
|
245
245
|
mediaTokens: number;
|
|
246
246
|
};
|
|
247
247
|
/**
|
|
248
|
-
* 日志里 `
|
|
248
|
+
* 日志里 `ToolSearch` 加载过的工具 key(全部 `tool_result.loadedTools` 的并集,按首次出现顺序)。
|
|
249
249
|
* 不看压缩摘要的边界:加载过的工具在摘要之后仍保持加载(模型可能凭摘要继续使用它们,且已发送的工具列表只追加)。
|
|
250
250
|
*/
|
|
251
251
|
export declare function loadedToolKeys(events: readonly ConversationEvent[]): string[];
|