@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
|
@@ -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 {
|
|
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
|
|
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(
|
|
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
|
|
100
|
-
|
|
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(
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 =
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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([
|
package/dist/runtime/waits.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export interface WaitSweepResult {
|
|
|
42
42
|
/** 运行已终态、被本次扫描取消的审批 / 输入请求。 */
|
|
43
43
|
cancelled: number;
|
|
44
44
|
/**
|
|
45
|
-
* Finished parent runs whose open `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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
|
package/dist/runtime/waits.js
CHANGED
|
@@ -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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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)) {
|
package/dist/skills/catalog.d.ts
CHANGED
|
@@ -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`。模型看到的目录与 `
|
|
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
|
-
* 是否给模型 `
|
|
106
|
+
* 是否给模型 `Skill`:日志里有过技能目录快照(Ruling M17),**即使最新一份是空的**。构建请求与执行工具调用
|
|
107
107
|
* 用同一判定。不因空快照收回这个工具:工具集合一变缓存前缀就失效;而且 agent 没有别的工具时会发出「没有工具
|
|
108
|
-
* 但历史里有 tool_use」的请求,Anthropic 会拒绝。空目录下调用
|
|
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
|
-
* 「读最新 → 推出下一份 → 追加」都在这把锁内,别的写快照的事务(运行开始、
|
|
127
|
+
* 「读最新 → 推出下一份 → 追加」都在这把锁内,别的写快照的事务(运行开始、SkillWrite、拒绝时的回退)插不进来。
|
|
128
128
|
*/
|
|
129
129
|
export declare function lockLatestCatalog(db: KernelSchemaDb, conversationId: string): Promise<SkillsSnapshot | undefined>;
|
|
130
130
|
/**
|
package/dist/skills/catalog.js
CHANGED
|
@@ -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`。模型看到的目录与 `
|
|
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
|
-
* 是否给模型 `
|
|
306
|
+
* 是否给模型 `Skill`:日志里有过技能目录快照(Ruling M17),**即使最新一份是空的**。构建请求与执行工具调用
|
|
307
307
|
* 用同一判定。不因空快照收回这个工具:工具集合一变缓存前缀就失效;而且 agent 没有别的工具时会发出「没有工具
|
|
308
|
-
* 但历史里有 tool_use」的请求,Anthropic 会拒绝。空目录下调用
|
|
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
|
-
* 「读最新 → 推出下一份 → 追加」都在这把锁内,别的写快照的事务(运行开始、
|
|
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`(工具 `
|
|
100
|
+
* - `write`(工具 `SkillWrite` 调用):私有 agent 直接生成新版本;共享 agent 生成一条待负责人批准的申请,
|
|
101
101
|
* 期间只有发起对话试用(`resolveEffectiveSkills` 按对话合并);两种情况都在同一事务里往发起对话追加一份
|
|
102
|
-
* 技能目录快照(Ruling M17:日志是唯一事实源),同一运行的下一步即可 `
|
|
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
|
|
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`(工具 `
|
|
61
|
+
* - `write`(工具 `SkillWrite` 调用):私有 agent 直接生成新版本;共享 agent 生成一条待负责人批准的申请,
|
|
61
62
|
* 期间只有发起对话试用(`resolveEffectiveSkills` 按对话合并);两种情况都在同一事务里往发起对话追加一份
|
|
62
|
-
* 技能目录快照(Ruling M17:日志是唯一事实源),同一运行的下一步即可 `
|
|
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:
|
|
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 `
|
|
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 `
|
|
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 = [
|
package/dist/skills/invoke.d.ts
CHANGED
|
@@ -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
|
-
* `
|
|
124
|
+
* `Bash` (batch 3 review m1).
|
|
125
125
|
*/
|
|
126
126
|
renderTask(a: {
|
|
127
127
|
orgId: string;
|
package/dist/skills/invoke.js
CHANGED
|
@@ -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
|
|
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,
|
|
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
|
-
* `
|
|
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,
|
|
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 ?
|
|
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
|
? {
|