@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.
Files changed (133) hide show
  1. package/dist/agents/agent-lookup.js +10 -2
  2. package/dist/agents/agents.service.js +19 -6
  3. package/dist/agents/definition.d.ts +31 -8
  4. package/dist/agents/definition.js +193 -17
  5. package/dist/agents/templates.js +19 -4
  6. package/dist/catalog/catalog-content.js +4 -1
  7. package/dist/catalog/claude/agents.js +13 -10
  8. package/dist/catalog/marketplaces.service.d.ts +1 -1
  9. package/dist/channels/cards.d.ts +8 -2
  10. package/dist/channels/cards.js +16 -8
  11. package/dist/config/schema.js +2 -2
  12. package/dist/conversations/artifacts.d.ts +1 -1
  13. package/dist/conversations/artifacts.js +1 -1
  14. package/dist/conversations/event-log.d.ts +11 -0
  15. package/dist/conversations/event-log.js +19 -0
  16. package/dist/conversations/events.d.ts +23 -3
  17. package/dist/conversations/events.js +26 -14
  18. package/dist/db/kernel-schema.d.ts +2 -2
  19. package/dist/evals/recorded-tools.d.ts +27 -1
  20. package/dist/evals/recorded-tools.js +85 -10
  21. package/dist/evals/run-replay.d.ts +5 -0
  22. package/dist/evals/run-replay.js +19 -5
  23. package/dist/evals/trajectory.d.ts +2 -2
  24. package/dist/identity/settings.js +1 -1
  25. package/dist/lifecycle/kernel-lifecycle.js +5 -0
  26. package/dist/orgs/settings.service.d.ts +2 -2
  27. package/dist/orgs/settings.service.js +2 -2
  28. package/dist/runtime/context/build.d.ts +6 -6
  29. package/dist/runtime/context/build.js +18 -8
  30. package/dist/runtime/context/claude-tools.d.ts +2 -1
  31. package/dist/runtime/context/claude-tools.js +9 -10
  32. package/dist/runtime/context/legacy-text.d.ts +22 -0
  33. package/dist/runtime/context/legacy-text.js +37 -0
  34. package/dist/runtime/context/skills.d.ts +29 -11
  35. package/dist/runtime/context/skills.js +37 -30
  36. package/dist/runtime/loop.d.ts +1 -1
  37. package/dist/runtime/model-call.js +1 -1
  38. package/dist/runtime/run-finish.d.ts +1 -1
  39. package/dist/runtime/run-queue.d.ts +3 -3
  40. package/dist/runtime/run-queue.js +2 -2
  41. package/dist/runtime/run-worker.d.ts +2 -2
  42. package/dist/runtime/run-worker.js +4 -4
  43. package/dist/runtime/subagents/definition.d.ts +1 -6
  44. package/dist/runtime/subagents/definition.js +11 -12
  45. package/dist/runtime/subagents/dispatch.d.ts +2 -2
  46. package/dist/runtime/subagents/dispatch.js +2 -2
  47. package/dist/runtime/subagents/org-agents.js +2 -1
  48. package/dist/runtime/subagents/roster.d.ts +1 -1
  49. package/dist/runtime/subagents/roster.js +1 -1
  50. package/dist/runtime/subagents/skill-fork.d.ts +2 -2
  51. package/dist/runtime/subagents/skill-fork.js +2 -2
  52. package/dist/runtime/subagents/subagents.service.d.ts +3 -3
  53. package/dist/runtime/subagents/subagents.service.js +3 -3
  54. package/dist/runtime/waits.d.ts +5 -5
  55. package/dist/runtime/waits.js +5 -5
  56. package/dist/skills/catalog.d.ts +4 -4
  57. package/dist/skills/catalog.js +4 -4
  58. package/dist/skills/changes.service.d.ts +2 -2
  59. package/dist/skills/changes.service.js +5 -4
  60. package/dist/skills/invocation-keys.d.ts +1 -1
  61. package/dist/skills/invocation-keys.js +1 -1
  62. package/dist/skills/invoke.d.ts +1 -1
  63. package/dist/skills/invoke.js +5 -4
  64. package/dist/tools/approvals.service.d.ts +6 -0
  65. package/dist/tools/approvals.service.js +19 -1
  66. package/dist/tools/builtin-names.d.ts +73 -0
  67. package/dist/tools/builtin-names.js +116 -0
  68. package/dist/tools/builtins/agent.d.ts +7 -7
  69. package/dist/tools/builtins/agent.js +7 -11
  70. package/dist/tools/builtins/ask-user.d.ts +1 -1
  71. package/dist/tools/builtins/ask-user.js +2 -2
  72. package/dist/tools/builtins/builtin-tools.d.ts +2 -2
  73. package/dist/tools/builtins/builtin-tools.js +2 -2
  74. package/dist/tools/builtins/read-tool-output.d.ts +1 -1
  75. package/dist/tools/builtins/read-tool-output.js +2 -2
  76. package/dist/tools/builtins/sandbox/bash.d.ts +5 -5
  77. package/dist/tools/builtins/sandbox/bash.js +31 -28
  78. package/dist/tools/builtins/sandbox/common.d.ts +3 -3
  79. package/dist/tools/builtins/sandbox/common.js +2 -2
  80. package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
  81. package/dist/tools/builtins/sandbox/deliver.js +11 -11
  82. package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
  83. package/dist/tools/builtins/sandbox/edit.js +41 -30
  84. package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
  85. package/dist/tools/builtins/sandbox/file-state.js +34 -0
  86. package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
  87. package/dist/tools/builtins/sandbox/glob-match.js +1 -1
  88. package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
  89. package/dist/tools/builtins/sandbox/glob.js +4 -4
  90. package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
  91. package/dist/tools/builtins/sandbox/grep.js +147 -30
  92. package/dist/tools/builtins/sandbox/index.d.ts +1 -1
  93. package/dist/tools/builtins/sandbox/index.js +1 -1
  94. package/dist/tools/builtins/sandbox/read.d.ts +2 -2
  95. package/dist/tools/builtins/sandbox/read.js +21 -14
  96. package/dist/tools/builtins/sandbox/write.d.ts +1 -1
  97. package/dist/tools/builtins/sandbox/write.js +37 -33
  98. package/dist/tools/builtins/skill-load.d.ts +3 -3
  99. package/dist/tools/builtins/skill-load.js +32 -16
  100. package/dist/tools/builtins/skill-write.d.ts +4 -4
  101. package/dist/tools/builtins/skill-write.js +10 -10
  102. package/dist/tools/builtins/tool-search.d.ts +13 -9
  103. package/dist/tools/builtins/tool-search.js +25 -14
  104. package/dist/tools/connectors.service.js +4 -4
  105. package/dist/tools/display-names.d.ts +9 -0
  106. package/dist/tools/display-names.js +24 -0
  107. package/dist/tools/drift.js +5 -5
  108. package/dist/tools/elicitation.js +1 -1
  109. package/dist/tools/info.d.ts +20 -4
  110. package/dist/tools/info.js +55 -32
  111. package/dist/tools/legacy-data.d.ts +34 -0
  112. package/dist/tools/legacy-data.js +76 -0
  113. package/dist/tools/legacy-keys.d.ts +51 -0
  114. package/dist/tools/legacy-keys.js +115 -0
  115. package/dist/tools/naming.d.ts +1 -5
  116. package/dist/tools/naming.js +1 -7
  117. package/dist/tools/outputs.js +1 -1
  118. package/dist/tools/pipeline.d.ts +13 -7
  119. package/dist/tools/pipeline.js +97 -39
  120. package/dist/tools/policy.d.ts +1 -14
  121. package/dist/tools/policy.js +13 -19
  122. package/dist/tools/questions.controller.d.ts +1 -1
  123. package/dist/tools/questions.controller.js +1 -1
  124. package/dist/tools/questions.service.d.ts +1 -1
  125. package/dist/tools/registry.d.ts +16 -21
  126. package/dist/tools/registry.js +29 -37
  127. package/dist/tools/resources.d.ts +1 -1
  128. package/dist/tools/resources.js +1 -1
  129. package/dist/tools/tools.module.js +1 -1
  130. package/package.json +2 -2
  131. package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
  132. package/dist/tools/builtins/sandbox/names.d.ts +0 -7
  133. package/dist/tools/builtins/sandbox/names.js +0 -20
@@ -1,13 +1,9 @@
1
- import { SKILL_ENTRY_FILE, sanitizeParams, } from "@capybara-hq/plugin-sdk";
1
+ import { connectorToolKey, extensionToolKey, parseToolKey, SKILL_ENTRY_FILE, sanitizeParams, } from "@capybara-hq/plugin-sdk";
2
2
  import { loadTemplates } from "../../agents/templates.js";
3
3
  import { ApiError } from "../../errors.js";
4
4
  import { PINNED_SKILLS_LIMITS } from "../../skills/catalog.js";
5
- import { toolKey } from "../../tools/naming.js";
6
- /**
7
- * Tools a sub-agent never gets (spec §5.3, §5.5): `agent` (depth 1), `ask_user` (the person does not
8
- * see the child), `sandbox_deliver` (delivering files is the parent's job) and `skill_write`.
9
- */
10
- export const CHILD_REMOVED_TOOLS = ["agent", "ask_user", "sandbox_deliver", "skill_write"];
5
+ import { CHILD_REMOVED_TOOLS } from "../../tools/builtin-names.js";
6
+ export { CHILD_REMOVED_TOOLS } from "../../tools/builtin-names.js";
11
7
  /**
12
8
  * The roster entry's template is gone (an inline template edited away, a plugin template
13
9
  * uninstalled) between resolving the roster and reading it. The dispatch refuses the call as an
@@ -72,7 +68,7 @@ async function loadConnectors(db, orgId, refs) {
72
68
  /**
73
69
  * Narrows tool refs by resolved key (spec §5.3): keeps a key when `allow` (if given) lists it and
74
70
  * neither `deny` nor {@link CHILD_REMOVED_TOOLS} does. A connector ref with `tools: "all"` stays
75
- * live only when nothing can narrow it (no allowlist and no deny key under `<slug>__`), so a tool
71
+ * live only when nothing can narrow it (no allowlist and no deny key under `mcp__<slug>__`), so a tool
76
72
  * the connector gains later never slips past the template; otherwise it becomes the kept names, or
77
73
  * is dropped. A connector that no longer exists keeps its ref only without an allowlist.
78
74
  */
@@ -86,7 +82,7 @@ function narrowTools(refs, connectors, allow, deny) {
86
82
  out.push(ref);
87
83
  }
88
84
  else if (ref.kind === "plugin") {
89
- if (keep(toolKey(ref.plugin, ref.name)))
85
+ if (keep(extensionToolKey(ref.plugin, ref.name)))
90
86
  out.push(ref);
91
87
  }
92
88
  else {
@@ -96,13 +92,16 @@ function narrowTools(refs, connectors, allow, deny) {
96
92
  out.push(ref);
97
93
  continue;
98
94
  }
99
- const prefix = toolKey(c.slug, "");
100
- if (ref.tools === "all" && allow === null && ![...deny].some((k) => k.startsWith(prefix))) {
95
+ const ownsKey = (k) => {
96
+ const parsed = parseToolKey(k);
97
+ return parsed?.kind === "connector" && parsed.slug === c.slug;
98
+ };
99
+ if (ref.tools === "all" && allow === null && ![...deny].some(ownsKey)) {
101
100
  out.push(ref);
102
101
  continue;
103
102
  }
104
103
  const names = ref.tools === "all" ? c.tools : ref.tools;
105
- const kept = names.filter((name) => keep(toolKey(c.slug, name)));
104
+ const kept = names.filter((name) => keep(connectorToolKey(c.slug, name)));
106
105
  if (kept.length > 0)
107
106
  out.push({ ...ref, tools: kept });
108
107
  }
@@ -48,7 +48,7 @@ export type DispatchOutcome = {
48
48
  };
49
49
  /**
50
50
  * A dispatch for a person's fork invocation (phase D spec §6.2, `advanceSkillForks`), not for a
51
- * model's `agent` call: `general-purpose` is always available (the `agent` tool and
51
+ * model's `Agent` call: `general-purpose` is always available (the `Agent` tool and
52
52
  * `subagents.general` do not gate it), an unknown type falls back to it with a warning, and the
53
53
  * child records the invoked skill.
54
54
  */
@@ -83,7 +83,7 @@ export interface DispatchPlan {
83
83
  tierFallback: boolean;
84
84
  }
85
85
  /**
86
- * Dispatches the sub-agent of one `agent` call (spec §7.1), after the pipeline's validation,
86
+ * Dispatches the sub-agent of one `Agent` call (spec §7.1), after the pipeline's validation,
87
87
  * policy, approval and `tool.preExecute` stages. A new sub-agent: resolves its type and effective
88
88
  * definition, then in one transaction (holding the parent run's row lock, so the dispatches of one
89
89
  * run serialize) inserts the child conversation, appends `subagent_started` and the task message,
@@ -20,7 +20,7 @@ const GENERAL_ENTRY = {
20
20
  /** Idempotency key of the parent's `subagent_dispatched` event. */
21
21
  export const dispatchedIdemKey = (runId, callId) => `subagent_dispatched:${runId}:${callId}`;
22
22
  /**
23
- * Dispatches the sub-agent of one `agent` call (spec §7.1), after the pipeline's validation,
23
+ * Dispatches the sub-agent of one `Agent` call (spec §7.1), after the pipeline's validation,
24
24
  * policy, approval and `tool.preExecute` stages. A new sub-agent: resolves its type and effective
25
25
  * definition, then in one transaction (holding the parent run's row lock, so the dispatches of one
26
26
  * run serialize) inserts the child conversation, appends `subagent_started` and the task message,
@@ -274,7 +274,7 @@ async function orgAgentGates(db, a, agentId, agentType, resumed) {
274
274
  }
275
275
  const taskMessage = (ctx, callId, prompt, narrowed,
276
276
  /**
277
- * A fork invocation's record: the child's log then holds the invocation, so its `skill_load`
277
+ * A fork invocation's record: the child's log then holds the invocation, so its `Skill`
278
278
  * is offered and resolves the invoked version (phase D).
279
279
  */
280
280
  skill) => ({
@@ -1,6 +1,7 @@
1
1
  import { isAgentVisibleTo } from "../../agents/agent-lookup.js";
2
2
  import { normalizeStoredDefinition } from "../../agents/definition.js";
3
3
  import { audit } from "../../identity/audit.js";
4
+ import { normalizeStoredDefinitionIn } from "../../tools/legacy-data.js";
4
5
  /**
5
6
  * Checks the gates for dispatching `agentId` from a parent whose current definition is
6
7
  * `parentDefinition` (read live by the caller: R5, removing an allowlist entry stops new
@@ -23,7 +24,7 @@ export async function checkOrgAgent(db, a) {
23
24
  if (!(a.parentDefinition.subagents?.agents ?? []).some((x) => x.agentId === a.agentId)) {
24
25
  return { ok: false, gate: "allowlist" };
25
26
  }
26
- const definition = normalizeStoredDefinition(row.definition);
27
+ const definition = await normalizeStoredDefinitionIn(db, a.orgId, row.definition);
27
28
  if (definition.subagents?.dispatchable !== true)
28
29
  return { ok: false, gate: "dispatchable" };
29
30
  if (!(await isAgentVisibleTo(db, a.agentId, a.triggerAccountId))) {
@@ -45,7 +45,7 @@ export declare const isGeneralAlias: (agent: string) => boolean;
45
45
  * `general-purpose` for no `agent` and Claude's built-in types; else a roster type (a bare name
46
46
  * prefers the skill's own plugin's template `<plugin>:<name>`, then {@link findType}). An `agent`
47
47
  * that does not resolve falls back to `general-purpose` and is returned as `unknown`. `inRoster`:
48
- * the type is one the parent's `agent` tool offers (`general-purpose` is not when
48
+ * the type is one the parent's `Agent` tool offers (`general-purpose` is not when
49
49
  * `subagents.general === false`, which does not block a person's fork invocation).
50
50
  */
51
51
  export declare function resolveSkillForkType(db: KernelSchemaDb, orgId: string, parent: Pick<AgentDefinition, "subagents">, agent: string | undefined, plugin: string | undefined): Promise<{
@@ -90,7 +90,7 @@ export const isGeneralAlias = (agent) => GENERAL_ALIASES.has(agent);
90
90
  * `general-purpose` for no `agent` and Claude's built-in types; else a roster type (a bare name
91
91
  * prefers the skill's own plugin's template `<plugin>:<name>`, then {@link findType}). An `agent`
92
92
  * that does not resolve falls back to `general-purpose` and is returned as `unknown`. `inRoster`:
93
- * the type is one the parent's `agent` tool offers (`general-purpose` is not when
93
+ * the type is one the parent's `Agent` tool offers (`general-purpose` is not when
94
94
  * `subagents.general === false`, which does not block a person's fork invocation).
95
95
  */
96
96
  export async function resolveSkillForkType(db, orgId, parent, agent, plugin) {
@@ -8,7 +8,7 @@ import { type DispatchDeps } from "./dispatch.js";
8
8
  /**
9
9
  * Forked skills (phase D spec §6): a person's invocation of a `context: fork` skill starts its own
10
10
  * run (the run boundary, {@link forkBoundary}), whose `prepare` node dispatches the sub-agent
11
- * through phase C's `dispatchSubagent` before any model call and waits on it like an `agent` call
11
+ * through phase C's `dispatchSubagent` before any model call and waits on it like an `Agent` call
12
12
  * (`subagents` wait `sa-<runId>-0`). When the child has ended, `prepare` appends the model-visible
13
13
  * `skill_fork_result` and the parent's model answers. Every terminal path of the run (and the wait
14
14
  * sweep) pairs a fork invocation without a report ({@link pairStoppedForks}), so the log never holds
@@ -110,7 +110,7 @@ export declare const recordedSkillForks: (eventLog: Pick<EventLog, "append" | "f
110
110
  * In the transaction of a run's terminal path (or the wait sweep): the run's fork invocation
111
111
  * (its trigger message, by the run boundary) without a report gets one now: the ended child's
112
112
  * result (and the parent's missing `subagent_finished`), {@link AGENT_STOPPED_WITH_RUN_TEXT} for a
113
- * child still active (the caller stops it after its commit, as for `agent` calls), or
113
+ * child still active (the caller stops it after its commit, as for `Agent` calls), or
114
114
  * {@link FORK_NOT_STARTED_TEXT} when nothing was dispatched. Returns the call ids written
115
115
  * (`skill-<seq>`) and the highest seq; the caller notifies after its commit.
116
116
  */
@@ -7,7 +7,7 @@ import { dispatchSubagent } from "./dispatch.js";
7
7
  /**
8
8
  * Forked skills (phase D spec §6): a person's invocation of a `context: fork` skill starts its own
9
9
  * run (the run boundary, {@link forkBoundary}), whose `prepare` node dispatches the sub-agent
10
- * through phase C's `dispatchSubagent` before any model call and waits on it like an `agent` call
10
+ * through phase C's `dispatchSubagent` before any model call and waits on it like an `Agent` call
11
11
  * (`subagents` wait `sa-<runId>-0`). When the child has ended, `prepare` appends the model-visible
12
12
  * `skill_fork_result` and the parent's model answers. Every terminal path of the run (and the wait
13
13
  * sweep) pairs a fork invocation without a report ({@link pairStoppedForks}), so the log never holds
@@ -190,7 +190,7 @@ export const recordedSkillForks = (eventLog, recorded) => ({
190
190
  * In the transaction of a run's terminal path (or the wait sweep): the run's fork invocation
191
191
  * (its trigger message, by the run boundary) without a report gets one now: the ended child's
192
192
  * result (and the parent's missing `subagent_finished`), {@link AGENT_STOPPED_WITH_RUN_TEXT} for a
193
- * child still active (the caller stops it after its commit, as for `agent` calls), or
193
+ * child still active (the caller stops it after its commit, as for `Agent` calls), or
194
194
  * {@link FORK_NOT_STARTED_TEXT} when nothing was dispatched. Returns the call ids written
195
195
  * (`skill-<seq>`) and the highest seq; the caller notifies after its commit.
196
196
  */
@@ -12,7 +12,7 @@ import { type ChildWriter, type DispatchArgs, type DispatchCommit, type Dispatch
12
12
  import { type SubagentStep } from "./progress.js";
13
13
  import { type SkillForkDeps, type SkillForks } from "./skill-fork.js";
14
14
  /**
15
- * Sub-agents (phase C, spec §7) and forked skills (phase D): the `agent` tool's dispatch (the
15
+ * Sub-agents (phase C, spec §7) and forked skills (phase D): the `Agent` tool's dispatch (the
16
16
  * tool pipeline calls {@link dispatch}), a run's fork invocation ({@link skillForks}, the loop's
17
17
  * `prepare`) and a child step's progress on the parent's stream ({@link progress}). Child runs go
18
18
  * to the sub-agent run queue through {@link RunJobs}. The child lifecycle after dispatch (a
@@ -28,13 +28,13 @@ export declare class SubagentsService {
28
28
  /** The live fork handler of the loop (`LoopDeps.skillForks`). */
29
29
  readonly skillForks: SkillForks;
30
30
  constructor(kdb: KernelDb, eventLog: EventLog, purposes: ModelPurposesService, registry: ProviderRegistry, config: KernelConfigService, jobs: RunJobs, invoker: SkillInvoker, bus: ExtensionContext["bus"], log: KernelLogger, txHost: TransactionHost);
31
- /** Dispatches the sub-agent of one `agent` call (`dispatchSubagent`). */
31
+ /** Dispatches the sub-agent of one `Agent` call (`dispatchSubagent`). */
32
32
  dispatch(a: DispatchArgs): Promise<DispatchOutcome>;
33
33
  /** The dispatch's writes in a transaction of their own (see `commitDispatchIn`). */
34
34
  commitDispatch(a: DispatchArgs, plan: DispatchPlan, child: ChildWriter): Promise<DispatchCommit | null>;
35
35
  /** A sub-agent's finished step on its parent's stream (sub-agents spec §14.2). Never throws. */
36
36
  progress(s: SubagentStep): Promise<void>;
37
37
  }
38
- /** Sub-agent dispatch (the tools domain's `agent` tool and the run loop use it). */
38
+ /** Sub-agent dispatch (the tools domain's `Agent` tool and the run loop use it). */
39
39
  export declare class SubagentsModule {
40
40
  }
@@ -24,7 +24,7 @@ import { commitDispatchIn, dispatchSubagent, } from "./dispatch.js";
24
24
  import { publishSubagentProgress } from "./progress.js";
25
25
  import { liveSkillForks } from "./skill-fork.js";
26
26
  /**
27
- * Sub-agents (phase C, spec §7) and forked skills (phase D): the `agent` tool's dispatch (the
27
+ * Sub-agents (phase C, spec §7) and forked skills (phase D): the `Agent` tool's dispatch (the
28
28
  * tool pipeline calls {@link dispatch}), a run's fork invocation ({@link skillForks}, the loop's
29
29
  * `prepare`) and a child step's progress on the parent's stream ({@link progress}). Child runs go
30
30
  * to the sub-agent run queue through {@link RunJobs}. The child lifecycle after dispatch (a
@@ -58,7 +58,7 @@ let SubagentsService = class SubagentsService {
58
58
  };
59
59
  this.skillForks = liveSkillForks(this.deps);
60
60
  }
61
- /** Dispatches the sub-agent of one `agent` call (`dispatchSubagent`). */
61
+ /** Dispatches the sub-agent of one `Agent` call (`dispatchSubagent`). */
62
62
  dispatch(a) {
63
63
  return dispatchSubagent(this.deps, a);
64
64
  }
@@ -88,7 +88,7 @@ SubagentsService = __decorate([
88
88
  __param(9, Inject(TransactionHost))
89
89
  ], SubagentsService);
90
90
  export { SubagentsService };
91
- /** Sub-agent dispatch (the tools domain's `agent` tool and the run loop use it). */
91
+ /** Sub-agent dispatch (the tools domain's `Agent` tool and the run loop use it). */
92
92
  let SubagentsModule = class SubagentsModule {
93
93
  };
94
94
  SubagentsModule = __decorate([
@@ -42,7 +42,7 @@ export interface WaitSweepResult {
42
42
  /** 运行已终态、被本次扫描取消的审批 / 输入请求。 */
43
43
  cancelled: number;
44
44
  /**
45
- * Finished parent runs whose open `agent` calls had no `tool_result`, repaired (final review
45
+ * Finished parent runs whose open `Agent` calls had no `tool_result`, repaired (final review
46
46
  * I3: the next run would send an unpaired tool call, which providers refuse).
47
47
  */
48
48
  repaired: number;
@@ -75,7 +75,7 @@ export declare class Waits implements OnApplicationShutdown {
75
75
  private readonly questions;
76
76
  private readonly runQueue;
77
77
  /**
78
- * Writes, in the caller's transaction, the results of a stopped run's open `agent` calls;
78
+ * Writes, in the caller's transaction, the results of a stopped run's open `Agent` calls;
79
79
  * `fire` runs their observe hooks after the commit.
80
80
  */
81
81
  private readonly pipeline;
@@ -96,7 +96,7 @@ export declare class Waits implements OnApplicationShutdown {
96
96
  private readonly unsubscribe;
97
97
  constructor(kdb: KernelDb, eventLog: EventLog, approvals: Pick<ApprovalsService, "expire" | "cancelPendingIn">, questions: Pick<QuestionsService, "expire" | "cancelPendingIn">, runQueue: Pick<RunQueue, "enqueue" | "repairOrphan" | "abortIfOrphaned">,
98
98
  /**
99
- * Writes, in the caller's transaction, the results of a stopped run's open `agent` calls;
99
+ * Writes, in the caller's transaction, the results of a stopped run's open `Agent` calls;
100
100
  * `fire` runs their observe hooks after the commit.
101
101
  */
102
102
  pipeline: Pick<ToolPipeline, "stopOpenAgentCalls">, finisher: Pick<RunFinish, "finishIn">,
@@ -163,7 +163,7 @@ export declare class Waits implements OnApplicationShutdown {
163
163
  * 运行已不是 waiting(例如刚被续跑)→ 返回 false,由调用方走常规中止。
164
164
  */
165
165
  abortWaiting(conversationId: string, runId: string, byAccountId: string | null, detail?: RunAbortDetail): Promise<boolean>;
166
- /** {@link abortWaiting}'s transaction; the open `agent` calls it wrote go back through `st`. */
166
+ /** {@link abortWaiting}'s transaction; the open `Agent` calls it wrote go back through `st`. */
167
167
  private abortWaitingIn;
168
168
  /** 扫描 3:运行已终态(如暂停途中失败)仍 pending 的审批 / 输入请求 → 取消(写决定 / 回答事件)。 */
169
169
  private sweepFinishedRuns;
@@ -193,7 +193,7 @@ export declare class Waits implements OnApplicationShutdown {
193
193
  */
194
194
  private sweepSubagentOrphans;
195
195
  /**
196
- * Finished parent runs (past the grace period, within the last day) with an `agent` call that has
196
+ * Finished parent runs (past the grace period, within the last day) with an `Agent` call that has
197
197
  * no `tool_result` (final review I3): a terminal path that skipped `stopOpenAgentCalls`, such as
198
198
  * an old replica's abort, would otherwise leave an unpaired tool call that every later request of
199
199
  * the conversation sends and providers refuse. Each is repaired under the conversation row lock
@@ -75,7 +75,7 @@ let Waits = class Waits {
75
75
  unsubscribe;
76
76
  constructor(kdb, eventLog, approvals, questions, runQueue,
77
77
  /**
78
- * Writes, in the caller's transaction, the results of a stopped run's open `agent` calls;
78
+ * Writes, in the caller's transaction, the results of a stopped run's open `Agent` calls;
79
79
  * `fire` runs their observe hooks after the commit.
80
80
  */
81
81
  pipeline, finisher,
@@ -337,7 +337,7 @@ let Waits = class Waits {
337
337
  await this.stopChildren(runId, null).catch((err) => this.log.error("cannot stop the sub-agents of a run", { runId, err }));
338
338
  return true;
339
339
  }
340
- /** {@link abortWaiting}'s transaction; the open `agent` calls it wrote go back through `st`. */
340
+ /** {@link abortWaiting}'s transaction; the open `Agent` calls it wrote go back through `st`. */
341
341
  async abortWaitingIn(conversationId, runId, byAccountId, detail, st) {
342
342
  const t = this.db;
343
343
  await t
@@ -385,7 +385,7 @@ let Waits = class Waits {
385
385
  if (typeof spec.step === "number")
386
386
  steps.add(spec.step);
387
387
  }
388
- // a parent waiting on sub-agents (spec §12): its open `agent` calls get their results
388
+ // a parent waiting on sub-agents (spec §12): its open `Agent` calls get their results
389
389
  const agents = await this.pipeline.stopOpenAgentCalls(runId);
390
390
  for (const step of agents.steps)
391
391
  steps.add(step);
@@ -626,7 +626,7 @@ let Waits = class Waits {
626
626
  return out;
627
627
  }
628
628
  /**
629
- * Finished parent runs (past the grace period, within the last day) with an `agent` call that has
629
+ * Finished parent runs (past the grace period, within the last day) with an `Agent` call that has
630
630
  * no `tool_result` (final review I3): a terminal path that skipped `stopOpenAgentCalls`, such as
631
631
  * an old replica's abort, would otherwise leave an unpaired tool call that every later request of
632
632
  * the conversation sends and providers refuse. Each is repaired under the conversation row lock
@@ -887,7 +887,7 @@ let Waits = class Waits {
887
887
  * 等待中的调用给取消说明,其余(排在等待调用之后、尚未执行的)给「未执行」说明。
888
888
  */
889
889
  async stoppedResults(t, conversationId, runId, steps, cancelled,
890
- /** Calls whose result the caller writes itself (open `agent` calls). */
890
+ /** Calls whose result the caller writes itself (open `Agent` calls). */
891
891
  skip = new Set()) {
892
892
  const out = [];
893
893
  for (const step of steps.sort((a, b) => a - b)) {
@@ -11,7 +11,7 @@ import { type CatalogSkill, type PinnedSkill, type SkillsSnapshot } from "../run
11
11
  import { type PrefixedStorage, StorageService } from "../storage/storage.service.js";
12
12
  /**
13
13
  * 技能目录快照(M5 T14,Ruling M17):运行开始时解析「此刻对这个对话生效的技能」,与日志里最新一份快照不同才写
14
- * `skills_catalog`。模型看到的目录与 `skill_load` 的名字解析只来自日志,不读实时的库。
14
+ * `skills_catalog`。模型看到的目录与 `Skill` 的名字解析只来自日志,不读实时的库。
15
15
  */
16
16
  /**
17
17
  * Pinned skill limits (spec §9.1): at most `count` pinned skills per agent, whose current SKILL.md
@@ -103,9 +103,9 @@ export declare function loadPinnedBodies(storage: PrefixedStorage, orgId: string
103
103
  export declare function fitPinned(pinned: readonly PinnedSkill[], log: Pick<Logger, "warn"> | undefined, input: Partial<Pick<EffectiveSkillsInput, "orgId" | "agentId" | "conversationId">>): PinnedSkill[];
104
104
  /** `skills_catalog` 的幂等键:每次运行最多写一份。 */
105
105
  /**
106
- * 是否给模型 `skill_load`:日志里有过技能目录快照(Ruling M17),**即使最新一份是空的**。构建请求与执行工具调用
106
+ * 是否给模型 `Skill`:日志里有过技能目录快照(Ruling M17),**即使最新一份是空的**。构建请求与执行工具调用
107
107
  * 用同一判定。不因空快照收回这个工具:工具集合一变缓存前缀就失效;而且 agent 没有别的工具时会发出「没有工具
108
- * 但历史里有 tool_use」的请求,Anthropic 会拒绝。空目录下调用 skill_load 由 `NO_SKILLS_TEXT` 给出可执行的说明。
108
+ * 但历史里有 tool_use」的请求,Anthropic 会拒绝。空目录下调用 Skill 由 `NO_SKILLS_TEXT` 给出可执行的说明。
109
109
  */
110
110
  export declare function skillLoadOffered(latest: Extract<ConversationEvent, {
111
111
  type: "skills_catalog";
@@ -124,7 +124,7 @@ export declare const skillsCatalogIdemKey: (runId: string) => string;
124
124
  /**
125
125
  * 在调用方事务里锁会话行(与 `EventLog.append` 同一把锁)并读最新一份技能目录快照(没有为 undefined)。
126
126
  * `db` is the caller's transaction handle (`KernelDb.db` inside `@Transactional`).
127
- * 「读最新 → 推出下一份 → 追加」都在这把锁内,别的写快照的事务(运行开始、skill_write、拒绝时的回退)插不进来。
127
+ * 「读最新 → 推出下一份 → 追加」都在这把锁内,别的写快照的事务(运行开始、SkillWrite、拒绝时的回退)插不进来。
128
128
  */
129
129
  export declare function lockLatestCatalog(db: KernelSchemaDb, conversationId: string): Promise<SkillsSnapshot | undefined>;
130
130
  /**
@@ -23,7 +23,7 @@ import { sameSnapshot, } from "../runtime/context/skills.js";
23
23
  import { StorageService } from "../storage/storage.service.js";
24
24
  /**
25
25
  * 技能目录快照(M5 T14,Ruling M17):运行开始时解析「此刻对这个对话生效的技能」,与日志里最新一份快照不同才写
26
- * `skills_catalog`。模型看到的目录与 `skill_load` 的名字解析只来自日志,不读实时的库。
26
+ * `skills_catalog`。模型看到的目录与 `Skill` 的名字解析只来自日志,不读实时的库。
27
27
  */
28
28
  /**
29
29
  * Pinned skill limits (spec §9.1): at most `count` pinned skills per agent, whose current SKILL.md
@@ -303,9 +303,9 @@ export function fitPinned(pinned, log, input) {
303
303
  }
304
304
  /** `skills_catalog` 的幂等键:每次运行最多写一份。 */
305
305
  /**
306
- * 是否给模型 `skill_load`:日志里有过技能目录快照(Ruling M17),**即使最新一份是空的**。构建请求与执行工具调用
306
+ * 是否给模型 `Skill`:日志里有过技能目录快照(Ruling M17),**即使最新一份是空的**。构建请求与执行工具调用
307
307
  * 用同一判定。不因空快照收回这个工具:工具集合一变缓存前缀就失效;而且 agent 没有别的工具时会发出「没有工具
308
- * 但历史里有 tool_use」的请求,Anthropic 会拒绝。空目录下调用 skill_load 由 `NO_SKILLS_TEXT` 给出可执行的说明。
308
+ * 但历史里有 tool_use」的请求,Anthropic 会拒绝。空目录下调用 Skill 由 `NO_SKILLS_TEXT` 给出可执行的说明。
309
309
  */
310
310
  export function skillLoadOffered(latest,
311
311
  /**
@@ -336,7 +336,7 @@ export const skillsCatalogIdemKey = (runId) => `skills_catalog:${runId}`;
336
336
  /**
337
337
  * 在调用方事务里锁会话行(与 `EventLog.append` 同一把锁)并读最新一份技能目录快照(没有为 undefined)。
338
338
  * `db` is the caller's transaction handle (`KernelDb.db` inside `@Transactional`).
339
- * 「读最新 → 推出下一份 → 追加」都在这把锁内,别的写快照的事务(运行开始、skill_write、拒绝时的回退)插不进来。
339
+ * 「读最新 → 推出下一份 → 追加」都在这把锁内,别的写快照的事务(运行开始、SkillWrite、拒绝时的回退)插不进来。
340
340
  */
341
341
  export async function lockLatestCatalog(db, conversationId) {
342
342
  await db
@@ -97,9 +97,9 @@ export interface CancelledDrafts {
97
97
  }
98
98
  /**
99
99
  * agent 自写技能与共享 agent 的技能变更审批(M5 T15,R4):
100
- * - `write`(工具 `skill_write` 调用):私有 agent 直接生成新版本;共享 agent 生成一条待负责人批准的申请,
100
+ * - `write`(工具 `SkillWrite` 调用):私有 agent 直接生成新版本;共享 agent 生成一条待负责人批准的申请,
101
101
  * 期间只有发起对话试用(`resolveEffectiveSkills` 按对话合并);两种情况都在同一事务里往发起对话追加一份
102
- * 技能目录快照(Ruling M17:日志是唯一事实源),同一运行的下一步即可 `skill_load`;
102
+ * 技能目录快照(Ruling M17:日志是唯一事实源),同一运行的下一步即可 `Skill`;
103
103
  * - `decide`(HTTP,只有该 agent 当前的负责人):批准 → 版本对所有对话生效(各对话下一次运行开始时写新快照);
104
104
  * 拒绝 → 删除草稿对象,发起对话下一次运行开始时目录回到当前版本;
105
105
  * - 同一 agent 的同名技能最多一条待处理申请:同一对话再写取代旧的(旧的 cancelled、草稿删除、技能 id 不变),
@@ -22,6 +22,7 @@ import { Transactional } from "../infra/database/transactional.decorator.js";
22
22
  import { KERNEL_LOGGER } from "../infra/tokens.js";
23
23
  import { sameSnapshot, } from "../runtime/context/skills.js";
24
24
  import { StorageService } from "../storage/storage.service.js";
25
+ import { BUILTIN } from "../tools/builtin-names.js";
25
26
  import { fitPinned, invocationOf, lockLatestCatalog } from "./catalog.js";
26
27
  /**
27
28
  * 每个 agent 自己的技能(`scope = agent`)上限,含待批准的新技能。远低于目录快照的上限(`SKILLS_CATALOG_MAX`),
@@ -42,7 +43,7 @@ const AGENT_GONE_TEXT = "This agent no longer exists, so the skill cannot be sav
42
43
  const iso = (v) => new Date(v).toISOString();
43
44
  const byName = (a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
44
45
  const notFound = () => new ApiError("skill_change.not_found", "Skill change not found");
45
- /** The body of the SKILL.md a skill_write just stored (as run start would read it); null if unparsable. */
46
+ /** The body of the SKILL.md a SkillWrite just stored (as run start would read it); null if unparsable. */
46
47
  function writtenBody(pkg) {
47
48
  const md = pkg.files.find((f) => f.path === SKILL_ENTRY_FILE);
48
49
  if (!md)
@@ -57,9 +58,9 @@ function writtenBody(pkg) {
57
58
  }
58
59
  /**
59
60
  * agent 自写技能与共享 agent 的技能变更审批(M5 T15,R4):
60
- * - `write`(工具 `skill_write` 调用):私有 agent 直接生成新版本;共享 agent 生成一条待负责人批准的申请,
61
+ * - `write`(工具 `SkillWrite` 调用):私有 agent 直接生成新版本;共享 agent 生成一条待负责人批准的申请,
61
62
  * 期间只有发起对话试用(`resolveEffectiveSkills` 按对话合并);两种情况都在同一事务里往发起对话追加一份
62
- * 技能目录快照(Ruling M17:日志是唯一事实源),同一运行的下一步即可 `skill_load`;
63
+ * 技能目录快照(Ruling M17:日志是唯一事实源),同一运行的下一步即可 `Skill`;
63
64
  * - `decide`(HTTP,只有该 agent 当前的负责人):批准 → 版本对所有对话生效(各对话下一次运行开始时写新快照);
64
65
  * 拒绝 → 删除草稿对象,发起对话下一次运行开始时目录回到当前版本;
65
66
  * - 同一 agent 的同名技能最多一条待处理申请:同一对话再写取代旧的(旧的 cancelled、草稿删除、技能 id 不变),
@@ -245,7 +246,7 @@ let SkillChangesService = class SkillChangesService {
245
246
  files: pkg.manifest.files.length,
246
247
  agentId: ctx.agentId,
247
248
  conversationId: ctx.conversationId,
248
- via: "skill_write",
249
+ via: BUILTIN.SkillWrite,
249
250
  },
250
251
  });
251
252
  outcome = { kind: "version", skillId, version, created: !existing };
@@ -2,7 +2,7 @@
2
2
  * The SKILL.md invocation keys (package ecosystem phase D) and their lenient reading: readers of
3
3
  * stored files (catalog install and upgrade) and the Claude Code translation drop a key the strict
4
4
  * `parseSkillMd` checks would refuse, with the reason, instead of refusing the skill or storing an
5
- * invocation nobody can use. Uploads, native imports and `skill_write` stay strict.
5
+ * invocation nobody can use. Uploads, native imports and `SkillWrite` stay strict.
6
6
  */
7
7
  /** The frontmatter keys that make up a skill's invocation metadata. */
8
8
  export declare const INVOCATION_KEYS: readonly ["disable-model-invocation", "user-invocable", "context", "agent", "argument-hint", "arguments"];
@@ -3,7 +3,7 @@ import { parseSkillMd } from "@capybara-hq/plugin-sdk";
3
3
  * The SKILL.md invocation keys (package ecosystem phase D) and their lenient reading: readers of
4
4
  * stored files (catalog install and upgrade) and the Claude Code translation drop a key the strict
5
5
  * `parseSkillMd` checks would refuse, with the reason, instead of refusing the skill or storing an
6
- * invocation nobody can use. Uploads, native imports and `skill_write` stay strict.
6
+ * invocation nobody can use. Uploads, native imports and `SkillWrite` stay strict.
7
7
  */
8
8
  /** The frontmatter keys that make up a skill's invocation metadata. */
9
9
  export const INVOCATION_KEYS = [
@@ -121,7 +121,7 @@ export declare class SkillInvoker {
121
121
  * `storage.unavailable` (`skill_unreadable`) when the version is gone or its SKILL.md cannot be
122
122
  * read, plain `storage.unavailable` when storage is down. `task` renders the text for the
123
123
  * sub-agent's effective definition: the shell-injection line only when the sub-agent has
124
- * `sandbox_bash` (batch 3 review m1).
124
+ * `Bash` (batch 3 review m1).
125
125
  */
126
126
  renderTask(a: {
127
127
  orgId: string;
@@ -15,6 +15,7 @@ import { KernelDb } from "../infra/database/kernel-db.js";
15
15
  import { KERNEL_LOGGER } from "../infra/tokens.js";
16
16
  import { isGeneralAlias, resolveSkillForkType } from "../runtime/subagents/roster.js";
17
17
  import { StorageService } from "../storage/storage.service.js";
18
+ import { BUILTIN } from "../tools/builtin-names.js";
18
19
  import { findSkillVersion, readSkillFile, SkillIntegrityError, } from "../tools/builtins/skill-load.js";
19
20
  import { invocationOf, resolveSkills } from "./catalog.js";
20
21
  /** A leading `/<name>` or `/<plugin>:<name>`, then whitespace or the end (spec §3.2). */
@@ -142,10 +143,10 @@ let SkillInvoker = class SkillInvoker {
142
143
  const body = await this.readBody(a.orgId, found);
143
144
  const others = found.manifest.files.some((f) => f.path !== SKILL_ENTRY_FILE);
144
145
  const lines = {
145
- // the invocation itself makes the conversation's next run offer skill_load (skillLoadOffered)
146
+ // the invocation itself makes the conversation's next run offer Skill (skillLoadOffered)
146
147
  ...(others && { files: "load" }),
147
148
  ...(hasShellInjection(body) &&
148
- hasBuiltin(a.agent, "sandbox_bash") && { shellHint: true }),
149
+ hasBuiltin(a.agent, BUILTIN.Bash) && { shellHint: true }),
149
150
  };
150
151
  const input = {
151
152
  name: a.name,
@@ -192,7 +193,7 @@ let SkillInvoker = class SkillInvoker {
192
193
  * `storage.unavailable` (`skill_unreadable`) when the version is gone or its SKILL.md cannot be
193
194
  * read, plain `storage.unavailable` when storage is down. `task` renders the text for the
194
195
  * sub-agent's effective definition: the shell-injection line only when the sub-agent has
195
- * `sandbox_bash` (batch 3 review m1).
196
+ * `Bash` (batch 3 review m1).
196
197
  */
197
198
  async renderTask(a) {
198
199
  const { skill } = a;
@@ -225,7 +226,7 @@ let SkillInvoker = class SkillInvoker {
225
226
  lines: {
226
227
  ...(others && { files: "load" }),
227
228
  ...(hasShellInjection(body) &&
228
- hasBuiltin(child, "sandbox_bash") && { shellHint: true }),
229
+ hasBuiltin(child, BUILTIN.Bash) && { shellHint: true }),
229
230
  },
230
231
  lead: false,
231
232
  });
@@ -1,3 +1,4 @@
1
+ import { type LocalizedName } from "@capybara-hq/plugin-sdk";
1
2
  import { EventLog } from "../conversations/event-log.js";
2
3
  import { KernelConfigService } from "../infra/config/kernel-config.service.js";
3
4
  import { KernelDb } from "../infra/database/kernel-db.js";
@@ -43,6 +44,11 @@ export interface ApprovalView extends ApprovalRecord {
43
44
  name: string;
44
45
  slug: string;
45
46
  } | null;
47
+ /** An extension tool's plugin (`plugin__<plugin>__<tool>`) and its display name (display only). */
48
+ extension: {
49
+ name: string;
50
+ displayName: LocalizedName;
51
+ } | null;
46
52
  agent: {
47
53
  id: string;
48
54
  name: string;
@@ -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 { randomUUID } from "node:crypto";
11
+ import { connectorToolKey, parseToolKey } from "@capybara-hq/plugin-sdk";
11
12
  import { Inject, Injectable } from "@nestjs/common";
12
13
  import { sql } from "kysely";
13
14
  import { EventLog } from "../conversations/event-log.js";
@@ -19,6 +20,7 @@ import { TransactionHost } from "../infra/database/transaction-host.js";
19
20
  import { Transactional } from "../infra/database/transactional.decorator.js";
20
21
  import { KernelEvents } from "../infra/events/kernel-events.js";
21
22
  import { ORG_ROLES, roleAtLeast } from "../orgs/roles.js";
23
+ import { pluginDisplayNames } from "./display-names.js";
22
24
  export { APPROVAL_DENY_REASON_MAX_CHARS } from "../conversations/events.js";
23
25
  /** `list` 一次最多返回的审批数(收件箱据此判断这个来源是否取满)。 */
24
26
  export const APPROVALS_LIST_MAX = 100;
@@ -579,12 +581,22 @@ let ApprovalsService = class ApprovalsService {
579
581
  .where("id", "in", connectorIds)
580
582
  .execute();
581
583
  const connectorById = new Map(apps.map((a) => [a.id, a]));
584
+ const pluginOf = (r) => {
585
+ if (r.connectorId !== null)
586
+ return null;
587
+ const p = parseToolKey(r.toolKey);
588
+ return p?.kind === "extension" ? p.plugin : null;
589
+ };
590
+ const displayNames = await pluginDisplayNames(db.db, recs.flatMap((r) => {
591
+ const p = pluginOf(r);
592
+ return p === null ? [] : [p];
593
+ }));
582
594
  return recs.flatMap((r) => {
583
595
  const c = ctx.get(r.runId);
584
596
  if (!c)
585
597
  return [];
586
598
  const app = r.connectorId === null ? undefined : connectorById.get(r.connectorId);
587
- const prefix = app ? `${app.slug}__` : undefined;
599
+ const prefix = app ? connectorToolKey(app.slug, "") : undefined;
588
600
  return [
589
601
  {
590
602
  ...r,
@@ -592,6 +604,12 @@ let ApprovalsService = class ApprovalsService {
592
604
  ? r.toolKey.slice(prefix.length)
593
605
  : r.toolKey,
594
606
  connector: app ? { id: app.id, name: app.name, slug: app.slug } : null,
607
+ extension: (() => {
608
+ const p = pluginOf(r);
609
+ return p === null
610
+ ? null
611
+ : { name: p, displayName: displayNames.get(p) ?? { zh: p, en: p } };
612
+ })(),
595
613
  agent: { id: c.agent_id, name: names.get(c.agent_id) ?? "" },
596
614
  ...(c.parent_conversation_id !== null
597
615
  ? {