@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
package/dist/tools/registry.d.ts
CHANGED
|
@@ -7,13 +7,8 @@ import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
|
7
7
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
8
8
|
import type { OrgRole } from "../orgs/roles.js";
|
|
9
9
|
import { BuiltinTools } from "./builtins/builtin-tools.js";
|
|
10
|
+
export { BUILTIN_TOOL_NAMES } from "./builtin-names.js";
|
|
10
11
|
export { canonicalJson } from "./canonical-json.js";
|
|
11
|
-
/**
|
|
12
|
-
* 内核内置工具的名字(Task 10 / Task 19 实现;M5 T8 加沙箱工具)。保存 agent 时内置工具引用按这份清单校验,
|
|
13
|
-
* 不依赖当前是否已注册,避免实现落地顺序影响已保存的定义;运行时未注册的照常报不可用。
|
|
14
|
-
* `skill_write`(M5 T15)由 agent 定义显式引用才可用(负责人决定 agent 能否改自己的技能)。
|
|
15
|
-
*/
|
|
16
|
-
export declare const BUILTIN_TOOL_NAMES: readonly ["ask_user", "read_tool_output", "tool_search", "skill_load", "skill_write", "sandbox_bash", "sandbox_read", "sandbox_write", "sandbox_edit", "sandbox_glob", "sandbox_grep", "sandbox_deliver", "agent"];
|
|
17
12
|
/** 保存 agent 时引用校验的问题(`path` 为 `tools.<i>`)。 */
|
|
18
13
|
export interface ToolRefIssue {
|
|
19
14
|
path: string;
|
|
@@ -21,7 +16,7 @@ export interface ToolRefIssue {
|
|
|
21
16
|
}
|
|
22
17
|
/**
|
|
23
18
|
* 内置工具处理函数的上下文:在 SDK 的 `ToolCallContext` 之上,管线额外传入本步解析出的工具
|
|
24
|
-
* (`
|
|
19
|
+
* (`ToolSearch` 据此搜索)。插件处理函数收到的仍是 `ToolCallContext`。
|
|
25
20
|
*/
|
|
26
21
|
export interface BuiltinCallContext extends ToolCallContext {
|
|
27
22
|
tools?: readonly ResolvedTool[];
|
|
@@ -39,7 +34,7 @@ export interface BuiltinCallContext extends ToolCallContext {
|
|
|
39
34
|
sandboxConversationId?: string;
|
|
40
35
|
}
|
|
41
36
|
/**
|
|
42
|
-
* 内置工具的结果:`ToolResult` 之外可带 `loadedTools`(`
|
|
37
|
+
* 内置工具的结果:`ToolResult` 之外可带 `loadedTools`(`ToolSearch` 加载的工具 key,
|
|
43
38
|
* 管线写进 `tool_result.loadedTools`)。
|
|
44
39
|
*/
|
|
45
40
|
export type BuiltinResult = (ToolResult & {
|
|
@@ -52,7 +47,7 @@ export type BuiltinResult = (ToolResult & {
|
|
|
52
47
|
}) | InputRequired;
|
|
53
48
|
/** 内置工具的处理函数(插件的 `ToolHandler` 可直接赋给它)。 */
|
|
54
49
|
export type BuiltinHandler = (input: unknown, ctx: BuiltinCallContext) => Promise<BuiltinResult>;
|
|
55
|
-
/** 内核内置工具(`
|
|
50
|
+
/** 内核内置工具(`AskUserQuestion` 等,Task 10 实现具体工具);key 就是 `spec.name`。 */
|
|
56
51
|
export interface BuiltinTool {
|
|
57
52
|
spec: ToolSpec;
|
|
58
53
|
defaultPolicy: "allow" | "ask";
|
|
@@ -116,7 +111,7 @@ export interface ResolvedTool {
|
|
|
116
111
|
*/
|
|
117
112
|
requiredRole?: OrgRole;
|
|
118
113
|
}
|
|
119
|
-
/** 不可用的引用:`ref` 尽量写成模型认识的工具 key(`
|
|
114
|
+
/** 不可用的引用:`ref` 尽量写成模型认识的工具 key(`mcp__docs__search`、`mcp__docs__*`),否则 `app:<id>`。 */
|
|
120
115
|
export interface UnavailableTool {
|
|
121
116
|
ref: string;
|
|
122
117
|
reason: string;
|
|
@@ -148,7 +143,7 @@ export interface AgentTools {
|
|
|
148
143
|
*/
|
|
149
144
|
hidden?: UnavailableTool[];
|
|
150
145
|
/**
|
|
151
|
-
* 本步是否启用 `
|
|
146
|
+
* 本步是否启用 `ToolSearch`(spec 5.5):启用时 `tools` 末尾含 `ToolSearch`,构建请求时只放内置工具
|
|
152
147
|
* 与已加载工具的完整定义,其余进目录。缺省视为未启用。
|
|
153
148
|
*/
|
|
154
149
|
toolSearch?: boolean;
|
|
@@ -178,7 +173,7 @@ export declare class ToolRegistry {
|
|
|
178
173
|
private readonly extensions;
|
|
179
174
|
private readonly builtinTools;
|
|
180
175
|
/**
|
|
181
|
-
* `tools.searchThreshold*` and the sub-agent limits. Absent (some tests): `
|
|
176
|
+
* `tools.searchThreshold*` and the sub-agent limits. Absent (some tests): `ToolSearch` is never
|
|
182
177
|
* offered and the sub-agent limits are the schema defaults.
|
|
183
178
|
*/
|
|
184
179
|
private readonly config?;
|
|
@@ -188,11 +183,11 @@ export declare class ToolRegistry {
|
|
|
188
183
|
/** The installed connectors (`connector@1`, from the extension registry). */
|
|
189
184
|
extensions: Pick<ExtensionRegistry, "list">, builtinTools: Pick<BuiltinTools, "list">,
|
|
190
185
|
/**
|
|
191
|
-
* `tools.searchThreshold*` and the sub-agent limits. Absent (some tests): `
|
|
186
|
+
* `tools.searchThreshold*` and the sub-agent limits. Absent (some tests): `ToolSearch` is never
|
|
192
187
|
* offered and the sub-agent limits are the schema defaults.
|
|
193
188
|
*/
|
|
194
189
|
config?: Pick<KernelConfigService, "get"> | undefined);
|
|
195
|
-
/** The kernel's builtin tools (`
|
|
190
|
+
/** The kernel's builtin tools (`ToolSearch` is added by {@link forAgent}, not by definitions). */
|
|
196
191
|
private get builtins();
|
|
197
192
|
/** `host.list("connector")` 中 `kind` 匹配的第一个实现;未安装返回 undefined。 */
|
|
198
193
|
findConnector(kind: string): Connector | undefined;
|
|
@@ -228,23 +223,23 @@ export declare class ToolRegistry {
|
|
|
228
223
|
issues: ToolRefIssue[];
|
|
229
224
|
}>;
|
|
230
225
|
/**
|
|
231
|
-
* 解析 agent 引用的工具(见类注释),再判定是否启用 `
|
|
226
|
+
* 解析 agent 引用的工具(见类注释),再判定是否启用 `ToolSearch`:组织设置 `toolSearch === "on"`,且
|
|
232
227
|
* 可用工具数 > `tools.searchThresholdTools` 或其定义的估算 token > `tools.searchThresholdTokens`。
|
|
233
|
-
* 启用时把内置 `
|
|
234
|
-
* `skillLoad`:对话日志里有技能目录快照(`skills_catalog`,Ruling M17)→ 加入内置 `
|
|
235
|
-
* 定义里显式引用的 `
|
|
228
|
+
* 启用时把内置 `ToolSearch` 追加到末尾。定义里显式引用的 `ToolSearch` 忽略(由这里按设置管理)。
|
|
229
|
+
* `skillLoad`:对话日志里有技能目录快照(`skills_catalog`,Ruling M17)→ 加入内置 `Skill`(始终完整加载);
|
|
230
|
+
* 定义里显式引用的 `Skill` 同样忽略。
|
|
236
231
|
*/
|
|
237
232
|
forAgent(orgId: string, def: {
|
|
238
233
|
tools: readonly AgentToolRef[];
|
|
239
234
|
skillLoad?: boolean;
|
|
240
|
-
/** The definition's sub-agent roster source: the `
|
|
235
|
+
/** The definition's sub-agent roster source: the `Agent` tool's description lists it. */
|
|
241
236
|
subagents?: AgentDefinition["subagents"];
|
|
242
237
|
}): Promise<AgentTools>;
|
|
243
|
-
/** 是否启用 `
|
|
238
|
+
/** 是否启用 `ToolSearch`(见 {@link forAgent});先比阈值,超过才读组织设置。 */
|
|
244
239
|
private searchActive;
|
|
245
240
|
private resolve;
|
|
246
241
|
/**
|
|
247
|
-
* `subagents.maxConcurrentPerRun` with the organization's override, for the `
|
|
242
|
+
* `subagents.maxConcurrentPerRun` with the organization's override, for the `Agent` tool's
|
|
248
243
|
* description (§4.3). A change of the limit changes the tool's spec hash; replays read the
|
|
249
244
|
* definition logged by hash, so no drift reason is involved. Without config (some tests): the
|
|
250
245
|
* schema default.
|
package/dist/tools/registry.js
CHANGED
|
@@ -8,6 +8,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
|
+
import { connectorToolKey, extensionToolKey } from "@capybara-hq/plugin-sdk";
|
|
11
12
|
import { Inject, Injectable } from "@nestjs/common";
|
|
12
13
|
import { ExtensionHost } from "../extensions/host.js";
|
|
13
14
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
@@ -17,27 +18,14 @@ import { readOrgSettings } from "../orgs/settings.service.js";
|
|
|
17
18
|
import { estimateTokens } from "../runtime/context/tokens.js";
|
|
18
19
|
import { SUBAGENT_LIMIT_DEFAULTS, subagentLimits } from "../runtime/subagents/limits.js";
|
|
19
20
|
import { resolveRoster } from "../runtime/subagents/roster.js";
|
|
20
|
-
import { AGENT_TOOL,
|
|
21
|
+
import { AGENT_TOOL, BUILTIN_TOOL_NAMES, SKILL_LOAD, TOOL_SEARCH } from "./builtin-names.js";
|
|
22
|
+
import { agentToolSpec } from "./builtins/agent.js";
|
|
21
23
|
import { BuiltinTools } from "./builtins/builtin-tools.js";
|
|
22
|
-
import { SANDBOX_TOOL_NAMES } from "./builtins/sandbox/names.js";
|
|
23
24
|
import { canonicalJson } from "./canonical-json.js";
|
|
24
|
-
import {
|
|
25
|
+
import { legacyKeySaveText } from "./legacy-keys.js";
|
|
26
|
+
import { toolKeyIssue } from "./naming.js";
|
|
27
|
+
export { BUILTIN_TOOL_NAMES } from "./builtin-names.js";
|
|
25
28
|
export { canonicalJson } from "./canonical-json.js";
|
|
26
|
-
/**
|
|
27
|
-
* 内核内置工具的名字(Task 10 / Task 19 实现;M5 T8 加沙箱工具)。保存 agent 时内置工具引用按这份清单校验,
|
|
28
|
-
* 不依赖当前是否已注册,避免实现落地顺序影响已保存的定义;运行时未注册的照常报不可用。
|
|
29
|
-
* `skill_write`(M5 T15)由 agent 定义显式引用才可用(负责人决定 agent 能否改自己的技能)。
|
|
30
|
-
*/
|
|
31
|
-
export const BUILTIN_TOOL_NAMES = [
|
|
32
|
-
"ask_user",
|
|
33
|
-
"read_tool_output",
|
|
34
|
-
"tool_search",
|
|
35
|
-
"skill_load",
|
|
36
|
-
"skill_write",
|
|
37
|
-
...SANDBOX_TOOL_NAMES,
|
|
38
|
-
// phase C: dispatches sub-agents; its description is built per agent from the roster
|
|
39
|
-
"agent",
|
|
40
|
-
];
|
|
41
29
|
/** The first 16 hex digits of sha256(canonicalJson(v)): a fingerprint independent of key order. */
|
|
42
30
|
export function contentHash(v) {
|
|
43
31
|
return createHash("sha256").update(canonicalJson(v)).digest("hex").slice(0, 16);
|
|
@@ -68,10 +56,8 @@ export function specHash(spec) {
|
|
|
68
56
|
export function policyFromAnnotations(a) {
|
|
69
57
|
return a?.readOnlyHint === true ? "allow" : "ask";
|
|
70
58
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/** 内置 `skill_load` 的名字(对话日志里有技能目录快照时由注册表自动加入,不进 agent 定义)。 */
|
|
74
|
-
const SKILL_LOAD = "skill_load";
|
|
59
|
+
// `ToolSearch` is added by the registry by org setting and threshold, `Skill` when the log has a
|
|
60
|
+
// skills catalog snapshot; neither comes from agent definitions (`./builtin-names.ts`).
|
|
75
61
|
/** 工具定义(模型可见三项)的估算 token 数(与请求估算同一口径)。 */
|
|
76
62
|
function estimateToolTokens(tools) {
|
|
77
63
|
return estimateTokens([], [], tools.map((t) => ({
|
|
@@ -114,7 +100,7 @@ let ToolRegistry = class ToolRegistry {
|
|
|
114
100
|
/** The installed connectors (`connector@1`, from the extension registry). */
|
|
115
101
|
extensions, builtinTools,
|
|
116
102
|
/**
|
|
117
|
-
* `tools.searchThreshold*` and the sub-agent limits. Absent (some tests): `
|
|
103
|
+
* `tools.searchThreshold*` and the sub-agent limits. Absent (some tests): `ToolSearch` is never
|
|
118
104
|
* offered and the sub-agent limits are the schema defaults.
|
|
119
105
|
*/
|
|
120
106
|
config) {
|
|
@@ -124,7 +110,7 @@ let ToolRegistry = class ToolRegistry {
|
|
|
124
110
|
this.builtinTools = builtinTools;
|
|
125
111
|
this.config = config;
|
|
126
112
|
}
|
|
127
|
-
/** The kernel's builtin tools (`
|
|
113
|
+
/** The kernel's builtin tools (`ToolSearch` is added by {@link forAgent}, not by definitions). */
|
|
128
114
|
get builtins() {
|
|
129
115
|
return this.builtinTools.list();
|
|
130
116
|
}
|
|
@@ -205,13 +191,19 @@ let ToolRegistry = class ToolRegistry {
|
|
|
205
191
|
const path = `tools.${i}`;
|
|
206
192
|
if (ref.kind === "builtin") {
|
|
207
193
|
if (!BUILTIN_TOOL_NAMES.includes(ref.name)) {
|
|
208
|
-
|
|
194
|
+
const renamed = legacyKeySaveText(ref.name);
|
|
195
|
+
issues.push({
|
|
196
|
+
path,
|
|
197
|
+
message: renamed === null
|
|
198
|
+
? `Built-in tool "${ref.name}" does not exist`
|
|
199
|
+
: `Built-in tool ${renamed}`,
|
|
200
|
+
});
|
|
209
201
|
return;
|
|
210
202
|
}
|
|
211
203
|
claim(path, ref.name, `builtin:${ref.name}`);
|
|
212
204
|
}
|
|
213
205
|
else if (ref.kind === "plugin") {
|
|
214
|
-
const key =
|
|
206
|
+
const key = extensionToolKey(ref.plugin, ref.name);
|
|
215
207
|
if (!pluginTools.some((x) => x.plugin === ref.plugin && x.spec.name === ref.name)) {
|
|
216
208
|
issues.push({ path, message: `Plugin tool "${key}" does not exist` });
|
|
217
209
|
return;
|
|
@@ -238,18 +230,18 @@ let ToolRegistry = class ToolRegistry {
|
|
|
238
230
|
});
|
|
239
231
|
continue;
|
|
240
232
|
}
|
|
241
|
-
claim(path,
|
|
233
|
+
claim(path, connectorToolKey(app.slug, name), `connector:${app.id}:${name}`);
|
|
242
234
|
}
|
|
243
235
|
}
|
|
244
236
|
});
|
|
245
237
|
return { keys: new Set(owner.keys()), issues };
|
|
246
238
|
}
|
|
247
239
|
/**
|
|
248
|
-
* 解析 agent 引用的工具(见类注释),再判定是否启用 `
|
|
240
|
+
* 解析 agent 引用的工具(见类注释),再判定是否启用 `ToolSearch`:组织设置 `toolSearch === "on"`,且
|
|
249
241
|
* 可用工具数 > `tools.searchThresholdTools` 或其定义的估算 token > `tools.searchThresholdTokens`。
|
|
250
|
-
* 启用时把内置 `
|
|
251
|
-
* `skillLoad`:对话日志里有技能目录快照(`skills_catalog`,Ruling M17)→ 加入内置 `
|
|
252
|
-
* 定义里显式引用的 `
|
|
242
|
+
* 启用时把内置 `ToolSearch` 追加到末尾。定义里显式引用的 `ToolSearch` 忽略(由这里按设置管理)。
|
|
243
|
+
* `skillLoad`:对话日志里有技能目录快照(`skills_catalog`,Ruling M17)→ 加入内置 `Skill`(始终完整加载);
|
|
244
|
+
* 定义里显式引用的 `Skill` 同样忽略。
|
|
253
245
|
*/
|
|
254
246
|
async forAgent(orgId, def) {
|
|
255
247
|
const { tools, unavailable, hidden } = await this.resolve(orgId, def);
|
|
@@ -277,7 +269,7 @@ let ToolRegistry = class ToolRegistry {
|
|
|
277
269
|
}
|
|
278
270
|
return { tools, unavailable, hidden, toolSearch };
|
|
279
271
|
}
|
|
280
|
-
/** 是否启用 `
|
|
272
|
+
/** 是否启用 `ToolSearch`(见 {@link forAgent});先比阈值,超过才读组织设置。 */
|
|
281
273
|
async searchActive(orgId, tools) {
|
|
282
274
|
const cfg = this.config?.get().tools;
|
|
283
275
|
if (!cfg || !this.builtins.some((b) => b.spec.name === TOOL_SEARCH))
|
|
@@ -329,7 +321,7 @@ let ToolRegistry = class ToolRegistry {
|
|
|
329
321
|
unavailable.push({ ref: ref.name, reason: why });
|
|
330
322
|
continue;
|
|
331
323
|
}
|
|
332
|
-
// `
|
|
324
|
+
// `Agent`: the description lists this definition's roster (sub-agents spec §4.3); with an
|
|
333
325
|
// empty roster there is nothing to dispatch, so the tool is not offered at all
|
|
334
326
|
let spec = b.spec;
|
|
335
327
|
if (b.spec.name === AGENT_TOOL) {
|
|
@@ -349,7 +341,7 @@ let ToolRegistry = class ToolRegistry {
|
|
|
349
341
|
});
|
|
350
342
|
}
|
|
351
343
|
else if (ref.kind === "plugin") {
|
|
352
|
-
const key =
|
|
344
|
+
const key = extensionToolKey(ref.plugin, ref.name);
|
|
353
345
|
const t = pluginTools.find((x) => x.plugin === ref.plugin && x.spec.name === ref.name);
|
|
354
346
|
if (!t) {
|
|
355
347
|
unavailable.push({ ref: key, reason: "Plugin tool does not exist" });
|
|
@@ -381,7 +373,7 @@ let ToolRegistry = class ToolRegistry {
|
|
|
381
373
|
unavailable.push({ ref: `app:${ref.connectorId}`, reason: "App does not exist" });
|
|
382
374
|
continue;
|
|
383
375
|
}
|
|
384
|
-
const all =
|
|
376
|
+
const all = connectorToolKey(app.slug, "*");
|
|
385
377
|
if (app.deleted) {
|
|
386
378
|
unavailable.push({ ref: all, reason: `App ${app.slug} was deleted` });
|
|
387
379
|
continue;
|
|
@@ -403,7 +395,7 @@ let ToolRegistry = class ToolRegistry {
|
|
|
403
395
|
// 「all」里未启用的工具不算 agent 点名要的,不进 unavailable(不提醒),只记进 hidden 备查
|
|
404
396
|
const notEnabled = ref.tools === "all" ? hidden : unavailable;
|
|
405
397
|
for (const t of wanted) {
|
|
406
|
-
const key =
|
|
398
|
+
const key = connectorToolKey(app.slug, t.name);
|
|
407
399
|
// 远端已不再提供(漂移检测置停用并标记,见 drift.ts):与「没有这一行」同一个事实
|
|
408
400
|
if ("missing" in t || t.gone) {
|
|
409
401
|
notEnabled.push({ ref: key, reason: `Tool no longer exists in app ${app.slug}` });
|
|
@@ -440,7 +432,7 @@ let ToolRegistry = class ToolRegistry {
|
|
|
440
432
|
return { tools, unavailable, hidden };
|
|
441
433
|
}
|
|
442
434
|
/**
|
|
443
|
-
* `subagents.maxConcurrentPerRun` with the organization's override, for the `
|
|
435
|
+
* `subagents.maxConcurrentPerRun` with the organization's override, for the `Agent` tool's
|
|
444
436
|
* description (§4.3). A change of the limit changes the tool's spec hash; replays read the
|
|
445
437
|
* definition logged by hash, so no drift reason is involved. Without config (some tests): the
|
|
446
438
|
* schema default.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ConnectorSession, type ToolResult, type ToolSpec } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
/**
|
|
3
|
-
* 连接器 resources 的两个内核工具(brief
|
|
3
|
+
* 连接器 resources 的两个内核工具(brief:`mcp__<slug>__list_resources`、`mcp__<slug>__read_resource {uri}`)。
|
|
4
4
|
*
|
|
5
5
|
* 设计:安装 / 刷新连接器时,连接器会话带 `listResources` 方法即视为支持 resources(不额外调用,免得多一次外连
|
|
6
6
|
* 和多一种失败),内核把这两个工具作为 `source = 'resources'` 的行写进 `connector_tools`(迁移 0013)。这样它们和
|
package/dist/tools/resources.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ToolError, } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
/**
|
|
3
|
-
* 连接器 resources 的两个内核工具(brief
|
|
3
|
+
* 连接器 resources 的两个内核工具(brief:`mcp__<slug>__list_resources`、`mcp__<slug>__read_resource {uri}`)。
|
|
4
4
|
*
|
|
5
5
|
* 设计:安装 / 刷新连接器时,连接器会话带 `listResources` 方法即视为支持 resources(不额外调用,免得多一次外连
|
|
6
6
|
* 和多一种失败),内核把这两个工具作为 `source = 'resources'` 的行写进 `connector_tools`(迁移 0013)。这样它们和
|
|
@@ -48,7 +48,7 @@ ToolsModule = __decorate([
|
|
|
48
48
|
StorageModule,
|
|
49
49
|
SkillsModule,
|
|
50
50
|
OrgLockModule,
|
|
51
|
-
// the `
|
|
51
|
+
// the `Agent` tool's dispatch
|
|
52
52
|
SubagentsModule,
|
|
53
53
|
// the builtin sandbox and skill tools run in the conversation's sandbox
|
|
54
54
|
SandboxModule,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capybara-hq/kernel",
|
|
3
|
-
"version": "0.1.0-rc.
|
|
3
|
+
"version": "0.1.0-rc.3",
|
|
4
4
|
"description": "Capybara kernel: config, database, plugin host and HTTP API of the Capybara agent platform",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"yaml": "^2.9.1",
|
|
65
65
|
"yauzl": "3.4.0",
|
|
66
66
|
"zod": "^4.6.7",
|
|
67
|
-
"@capybara-hq/plugin-sdk": "^0.1.0-rc.
|
|
67
|
+
"@capybara-hq/plugin-sdk": "^0.1.0-rc.1"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@langchain/langgraph-checkpoint-validation": "^1.2.0",
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
-- Tool naming (spec docs/superpowers/specs/2026-10-29-tool-naming-claude-code-design.md §8.2):
|
|
2
|
+
-- the release candidates' tool keys in mutable state become the current keys. Builtins by the
|
|
3
|
+
-- frozen map of packages/kernel/src/tools/legacy-keys.ts (LEGACY_BUILTINS); an rc `<x>__<tool>`
|
|
4
|
+
-- key becomes `mcp__<x>__<tool>` when `x` is a connector of the row's org (or the row records its
|
|
5
|
+
-- connector) and `plugin__<x>__<tool>` when `x` is an extension of the deployment
|
|
6
|
+
-- (extension_installs, or extension_name_owners for config-declared ones); when both or neither,
|
|
7
|
+
-- the row stays and the kernel's startup notice `tools.legacy_key_unmapped` counts it.
|
|
8
|
+
-- Keys in the current format never match. A grant whose new key already exists for the same
|
|
9
|
+
-- owner is left as it is (the primary key). Decided approvals and answered questions are
|
|
10
|
+
-- history and stay. Logs and recordings are never rewritten (§8). Idempotent: a second run
|
|
11
|
+
-- matches nothing it could change.
|
|
12
|
+
|
|
13
|
+
-- capybara:allow-destructive rewrites rc tool keys in place (the old keys no longer name a tool; the kernel reads only the new ones)
|
|
14
|
+
UPDATE tool_grants g
|
|
15
|
+
SET tool_key = m.new_key
|
|
16
|
+
FROM (VALUES
|
|
17
|
+
('sandbox_bash', 'Bash'), ('sandbox_read', 'Read'), ('sandbox_write', 'Write'),
|
|
18
|
+
('sandbox_edit', 'Edit'), ('sandbox_glob', 'Glob'), ('sandbox_grep', 'Grep'),
|
|
19
|
+
('sandbox_deliver', 'Deliver'), ('skill_load', 'Skill'), ('skill_write', 'SkillWrite'),
|
|
20
|
+
('ask_user', 'AskUserQuestion'), ('read_tool_output', 'ReadToolOutput'),
|
|
21
|
+
('tool_search', 'ToolSearch'), ('agent', 'Agent')
|
|
22
|
+
) AS m(old_key, new_key)
|
|
23
|
+
WHERE g.tool_key = m.old_key
|
|
24
|
+
AND NOT EXISTS (
|
|
25
|
+
SELECT 1 FROM tool_grants x
|
|
26
|
+
WHERE x.org_id = g.org_id AND x.account_id = g.account_id AND x.agent_id = g.agent_id
|
|
27
|
+
AND x.tool_key = m.new_key
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
-- capybara:allow-destructive rewrites rc tool keys in place (the old keys no longer name a tool; the kernel reads only the new ones)
|
|
31
|
+
UPDATE tool_grants g
|
|
32
|
+
SET tool_key = CASE
|
|
33
|
+
WHEN g.connector_id IS NOT NULL OR (
|
|
34
|
+
EXISTS (SELECT 1 FROM connectors c
|
|
35
|
+
WHERE c.org_id = g.org_id AND c.deleted_at IS NULL
|
|
36
|
+
AND c.slug = split_part(g.tool_key, '__', 1))
|
|
37
|
+
AND split_part(g.tool_key, '__', 1) NOT IN (
|
|
38
|
+
SELECT name FROM extension_installs UNION SELECT name FROM extension_name_owners)
|
|
39
|
+
) THEN 'mcp__' || g.tool_key
|
|
40
|
+
ELSE 'plugin__' || g.tool_key
|
|
41
|
+
END
|
|
42
|
+
WHERE g.tool_key ~ '^[a-z0-9][a-z0-9_-]*__.' AND g.tool_key !~ '^(mcp|plugin)__'
|
|
43
|
+
AND (
|
|
44
|
+
g.connector_id IS NOT NULL
|
|
45
|
+
OR (
|
|
46
|
+
EXISTS (SELECT 1 FROM connectors c
|
|
47
|
+
WHERE c.org_id = g.org_id AND c.deleted_at IS NULL
|
|
48
|
+
AND c.slug = split_part(g.tool_key, '__', 1))
|
|
49
|
+
) <> (
|
|
50
|
+
split_part(g.tool_key, '__', 1) IN (
|
|
51
|
+
SELECT name FROM extension_installs UNION SELECT name FROM extension_name_owners)
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
AND NOT EXISTS (
|
|
55
|
+
SELECT 1 FROM tool_grants x
|
|
56
|
+
WHERE x.org_id = g.org_id AND x.account_id = g.account_id AND x.agent_id = g.agent_id
|
|
57
|
+
AND x.tool_key IN ('mcp__' || g.tool_key, 'plugin__' || g.tool_key)
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
-- capybara:allow-destructive rewrites rc tool keys in place (the old keys no longer name a tool; the kernel reads only the new ones)
|
|
61
|
+
UPDATE conversation_tool_grants g
|
|
62
|
+
SET tool_key = m.new_key
|
|
63
|
+
FROM (VALUES
|
|
64
|
+
('sandbox_bash', 'Bash'), ('sandbox_read', 'Read'), ('sandbox_write', 'Write'),
|
|
65
|
+
('sandbox_edit', 'Edit'), ('sandbox_glob', 'Glob'), ('sandbox_grep', 'Grep'),
|
|
66
|
+
('sandbox_deliver', 'Deliver'), ('skill_load', 'Skill'), ('skill_write', 'SkillWrite'),
|
|
67
|
+
('ask_user', 'AskUserQuestion'), ('read_tool_output', 'ReadToolOutput'),
|
|
68
|
+
('tool_search', 'ToolSearch'), ('agent', 'Agent')
|
|
69
|
+
) AS m(old_key, new_key)
|
|
70
|
+
WHERE g.tool_key = m.old_key
|
|
71
|
+
AND NOT EXISTS (
|
|
72
|
+
SELECT 1 FROM conversation_tool_grants x
|
|
73
|
+
WHERE x.conversation_id = g.conversation_id AND x.tool_key = m.new_key
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
-- capybara:allow-destructive rewrites rc tool keys in place (the old keys no longer name a tool; the kernel reads only the new ones)
|
|
77
|
+
UPDATE conversation_tool_grants g
|
|
78
|
+
SET tool_key = CASE
|
|
79
|
+
WHEN g.connector_id IS NOT NULL OR (
|
|
80
|
+
EXISTS (SELECT 1 FROM connectors c
|
|
81
|
+
WHERE c.org_id = v.org_id AND c.deleted_at IS NULL
|
|
82
|
+
AND c.slug = split_part(g.tool_key, '__', 1))
|
|
83
|
+
AND split_part(g.tool_key, '__', 1) NOT IN (
|
|
84
|
+
SELECT name FROM extension_installs UNION SELECT name FROM extension_name_owners)
|
|
85
|
+
) THEN 'mcp__' || g.tool_key
|
|
86
|
+
ELSE 'plugin__' || g.tool_key
|
|
87
|
+
END
|
|
88
|
+
FROM conversations v
|
|
89
|
+
WHERE v.id = g.conversation_id
|
|
90
|
+
AND g.tool_key ~ '^[a-z0-9][a-z0-9_-]*__.' AND g.tool_key !~ '^(mcp|plugin)__'
|
|
91
|
+
AND (
|
|
92
|
+
g.connector_id IS NOT NULL
|
|
93
|
+
OR (
|
|
94
|
+
EXISTS (SELECT 1 FROM connectors c
|
|
95
|
+
WHERE c.org_id = v.org_id AND c.deleted_at IS NULL
|
|
96
|
+
AND c.slug = split_part(g.tool_key, '__', 1))
|
|
97
|
+
) <> (
|
|
98
|
+
split_part(g.tool_key, '__', 1) IN (
|
|
99
|
+
SELECT name FROM extension_installs UNION SELECT name FROM extension_name_owners)
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
AND NOT EXISTS (
|
|
103
|
+
SELECT 1 FROM conversation_tool_grants x
|
|
104
|
+
WHERE x.conversation_id = g.conversation_id
|
|
105
|
+
AND x.tool_key IN ('mcp__' || g.tool_key, 'plugin__' || g.tool_key)
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
-- capybara:allow-destructive rewrites rc tool keys of pending approvals in place (resumed by run and call id, never by key)
|
|
109
|
+
UPDATE approvals a
|
|
110
|
+
SET tool_key = m.new_key
|
|
111
|
+
FROM (VALUES
|
|
112
|
+
('sandbox_bash', 'Bash'), ('sandbox_read', 'Read'), ('sandbox_write', 'Write'),
|
|
113
|
+
('sandbox_edit', 'Edit'), ('sandbox_glob', 'Glob'), ('sandbox_grep', 'Grep'),
|
|
114
|
+
('sandbox_deliver', 'Deliver'), ('skill_load', 'Skill'), ('skill_write', 'SkillWrite'),
|
|
115
|
+
('ask_user', 'AskUserQuestion'), ('read_tool_output', 'ReadToolOutput'),
|
|
116
|
+
('tool_search', 'ToolSearch'), ('agent', 'Agent')
|
|
117
|
+
) AS m(old_key, new_key)
|
|
118
|
+
WHERE a.status = 'pending' AND a.tool_key = m.old_key;
|
|
119
|
+
|
|
120
|
+
-- capybara:allow-destructive rewrites rc tool keys of pending approvals in place (resumed by run and call id, never by key)
|
|
121
|
+
UPDATE approvals a
|
|
122
|
+
SET tool_key = CASE
|
|
123
|
+
WHEN a.connector_id IS NOT NULL OR (
|
|
124
|
+
EXISTS (SELECT 1 FROM connectors c
|
|
125
|
+
WHERE c.org_id = a.org_id AND c.deleted_at IS NULL
|
|
126
|
+
AND c.slug = split_part(a.tool_key, '__', 1))
|
|
127
|
+
AND split_part(a.tool_key, '__', 1) NOT IN (
|
|
128
|
+
SELECT name FROM extension_installs UNION SELECT name FROM extension_name_owners)
|
|
129
|
+
) THEN 'mcp__' || a.tool_key
|
|
130
|
+
ELSE 'plugin__' || a.tool_key
|
|
131
|
+
END
|
|
132
|
+
WHERE a.status = 'pending'
|
|
133
|
+
AND a.tool_key ~ '^[a-z0-9][a-z0-9_-]*__.' AND a.tool_key !~ '^(mcp|plugin)__'
|
|
134
|
+
AND (
|
|
135
|
+
a.connector_id IS NOT NULL
|
|
136
|
+
OR (
|
|
137
|
+
EXISTS (SELECT 1 FROM connectors c
|
|
138
|
+
WHERE c.org_id = a.org_id AND c.deleted_at IS NULL
|
|
139
|
+
AND c.slug = split_part(a.tool_key, '__', 1))
|
|
140
|
+
) <> (
|
|
141
|
+
split_part(a.tool_key, '__', 1) IN (
|
|
142
|
+
SELECT name FROM extension_installs UNION SELECT name FROM extension_name_owners)
|
|
143
|
+
)
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
-- capybara:allow-destructive rewrites rc tool keys of pending questions in place (resumed by run and call id, never by key)
|
|
147
|
+
UPDATE questions q
|
|
148
|
+
SET spec = jsonb_set(q.spec, '{toolKey}', to_jsonb(m.new_key))
|
|
149
|
+
FROM (VALUES
|
|
150
|
+
('sandbox_bash', 'Bash'), ('sandbox_read', 'Read'), ('sandbox_write', 'Write'),
|
|
151
|
+
('sandbox_edit', 'Edit'), ('sandbox_glob', 'Glob'), ('sandbox_grep', 'Grep'),
|
|
152
|
+
('sandbox_deliver', 'Deliver'), ('skill_load', 'Skill'), ('skill_write', 'SkillWrite'),
|
|
153
|
+
('ask_user', 'AskUserQuestion'), ('read_tool_output', 'ReadToolOutput'),
|
|
154
|
+
('tool_search', 'ToolSearch'), ('agent', 'Agent')
|
|
155
|
+
) AS m(old_key, new_key)
|
|
156
|
+
WHERE q.status = 'pending' AND q.spec->>'toolKey' = m.old_key;
|
|
157
|
+
|
|
158
|
+
-- capybara:allow-destructive rewrites rc tool keys of pending questions in place (resumed by run and call id, never by key)
|
|
159
|
+
UPDATE questions q
|
|
160
|
+
SET spec = jsonb_set(
|
|
161
|
+
q.spec,
|
|
162
|
+
'{toolKey}',
|
|
163
|
+
to_jsonb(CASE
|
|
164
|
+
WHEN EXISTS (SELECT 1 FROM connectors c
|
|
165
|
+
WHERE c.org_id = q.org_id AND c.deleted_at IS NULL
|
|
166
|
+
AND c.slug = split_part(q.spec->>'toolKey', '__', 1))
|
|
167
|
+
THEN 'mcp__' || (q.spec->>'toolKey')
|
|
168
|
+
ELSE 'plugin__' || (q.spec->>'toolKey')
|
|
169
|
+
END)
|
|
170
|
+
)
|
|
171
|
+
WHERE q.status = 'pending'
|
|
172
|
+
AND q.spec->>'toolKey' ~ '^[a-z0-9][a-z0-9_-]*__.' AND q.spec->>'toolKey' !~ '^(mcp|plugin)__'
|
|
173
|
+
AND (
|
|
174
|
+
EXISTS (SELECT 1 FROM connectors c
|
|
175
|
+
WHERE c.org_id = q.org_id AND c.deleted_at IS NULL
|
|
176
|
+
AND c.slug = split_part(q.spec->>'toolKey', '__', 1))
|
|
177
|
+
) <> (
|
|
178
|
+
split_part(q.spec->>'toolKey', '__', 1) IN (
|
|
179
|
+
SELECT name FROM extension_installs UNION SELECT name FROM extension_name_owners)
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
-- What the startup notice counts (rows the statements above could not map), each over a partial
|
|
183
|
+
-- index holding only such rows, so the count at every start reads nearly empty indexes. The
|
|
184
|
+
-- predicate is the one of countLegacyToolKeys (packages/kernel/src/tools/legacy-data.ts).
|
|
185
|
+
CREATE INDEX IF NOT EXISTS tool_grants_legacy_key_idx ON tool_grants (org_id)
|
|
186
|
+
WHERE (tool_key = ANY (ARRAY['sandbox_bash', 'sandbox_read', 'sandbox_write', 'sandbox_edit',
|
|
187
|
+
'sandbox_glob', 'sandbox_grep', 'sandbox_deliver', 'skill_load', 'skill_write', 'ask_user',
|
|
188
|
+
'read_tool_output', 'tool_search', 'agent']::text[])
|
|
189
|
+
OR (tool_key ~ '^[a-z0-9][a-z0-9_-]*__.' AND tool_key !~ '^(mcp|plugin)__'));
|
|
190
|
+
CREATE INDEX IF NOT EXISTS conversation_tool_grants_legacy_key_idx
|
|
191
|
+
ON conversation_tool_grants (conversation_id)
|
|
192
|
+
WHERE (tool_key = ANY (ARRAY['sandbox_bash', 'sandbox_read', 'sandbox_write', 'sandbox_edit',
|
|
193
|
+
'sandbox_glob', 'sandbox_grep', 'sandbox_deliver', 'skill_load', 'skill_write', 'ask_user',
|
|
194
|
+
'read_tool_output', 'tool_search', 'agent']::text[])
|
|
195
|
+
OR (tool_key ~ '^[a-z0-9][a-z0-9_-]*__.' AND tool_key !~ '^(mcp|plugin)__'));
|
|
196
|
+
CREATE INDEX IF NOT EXISTS approvals_legacy_key_idx ON approvals (org_id)
|
|
197
|
+
WHERE status = 'pending'
|
|
198
|
+
AND (tool_key = ANY (ARRAY['sandbox_bash', 'sandbox_read', 'sandbox_write', 'sandbox_edit',
|
|
199
|
+
'sandbox_glob', 'sandbox_grep', 'sandbox_deliver', 'skill_load', 'skill_write', 'ask_user',
|
|
200
|
+
'read_tool_output', 'tool_search', 'agent']::text[])
|
|
201
|
+
OR (tool_key ~ '^[a-z0-9][a-z0-9_-]*__.' AND tool_key !~ '^(mcp|plugin)__'));
|
|
202
|
+
CREATE INDEX IF NOT EXISTS questions_legacy_key_idx ON questions (org_id)
|
|
203
|
+
WHERE status = 'pending'
|
|
204
|
+
AND ((spec->>'toolKey') = ANY (ARRAY['sandbox_bash', 'sandbox_read', 'sandbox_write',
|
|
205
|
+
'sandbox_edit', 'sandbox_glob', 'sandbox_grep', 'sandbox_deliver', 'skill_load', 'skill_write',
|
|
206
|
+
'ask_user', 'read_tool_output', 'tool_search', 'agent']::text[])
|
|
207
|
+
OR ((spec->>'toolKey') ~ '^[a-z0-9][a-z0-9_-]*__.' AND (spec->>'toolKey') !~ '^(mcp|plugin)__'));
|
|
208
|
+
|
|
209
|
+
-- Read before Write / Edit (spec §4.5): EventLog.latestFileState reads the latest tool_result of
|
|
210
|
+
-- a conversation whose view names a file, on every Write and Edit. Without this index it scans
|
|
211
|
+
-- the conversation's events backwards through the primary key, filtering each payload (EXPLAIN
|
|
212
|
+
-- on a 20 000-event conversation: every row removed by the filter for a path never read); with
|
|
213
|
+
-- it, one index probe. Partial: only tool_result rows. Built without CONCURRENTLY (a migration
|
|
214
|
+
-- runs in one transaction), which locks conversation_events against writes while it builds: this
|
|
215
|
+
-- assumes release-candidate-sized event tables, as the event indexes of 0025 and 0040 did. A
|
|
216
|
+
-- deployment with a large table builds it CONCURRENTLY by hand before upgrading; IF NOT EXISTS
|
|
217
|
+
-- then skips it here.
|
|
218
|
+
CREATE INDEX IF NOT EXISTS conversation_events_file_state_idx
|
|
219
|
+
ON conversation_events (conversation_id, ((payload->'view'->'file'->>'path')), seq DESC)
|
|
220
|
+
WHERE type = 'tool_result';
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 沙箱内置工具的名字(M5 T8,Ruling M12:工具 key 只能含字母数字、`_`、`-`,所以是 `sandbox_<动作>`)。
|
|
3
|
-
* 单独成文件:注册表与策略判定只需要名字,不引入工具实现。
|
|
4
|
-
*/
|
|
5
|
-
export declare const SANDBOX_TOOL_NAMES: readonly ["sandbox_bash", "sandbox_read", "sandbox_write", "sandbox_edit", "sandbox_glob", "sandbox_grep", "sandbox_deliver"];
|
|
6
|
-
/** 组织设置 `sandboxToolPolicy` 为 `ask` 时需要审批的沙箱工具(只读的 read / glob / grep 除外)。 */
|
|
7
|
-
export declare const SANDBOX_ASK_TOOL_NAMES: ReadonlySet<string>;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 沙箱内置工具的名字(M5 T8,Ruling M12:工具 key 只能含字母数字、`_`、`-`,所以是 `sandbox_<动作>`)。
|
|
3
|
-
* 单独成文件:注册表与策略判定只需要名字,不引入工具实现。
|
|
4
|
-
*/
|
|
5
|
-
export const SANDBOX_TOOL_NAMES = [
|
|
6
|
-
"sandbox_bash",
|
|
7
|
-
"sandbox_read",
|
|
8
|
-
"sandbox_write",
|
|
9
|
-
"sandbox_edit",
|
|
10
|
-
"sandbox_glob",
|
|
11
|
-
"sandbox_grep",
|
|
12
|
-
"sandbox_deliver",
|
|
13
|
-
];
|
|
14
|
-
/** 组织设置 `sandboxToolPolicy` 为 `ask` 时需要审批的沙箱工具(只读的 read / glob / grep 除外)。 */
|
|
15
|
-
export const SANDBOX_ASK_TOOL_NAMES = new Set([
|
|
16
|
-
"sandbox_bash",
|
|
17
|
-
"sandbox_write",
|
|
18
|
-
"sandbox_edit",
|
|
19
|
-
"sandbox_deliver",
|
|
20
|
-
]);
|