klyro 0.1.63 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/anthropic-adapter.js +6 -1
- package/dist/agent/capabilities.d.ts +122 -0
- package/dist/agent/capabilities.js +150 -0
- package/dist/agent/orchestrator.d.ts +131 -0
- package/dist/agent/orchestrator.js +269 -0
- package/dist/agent/provider-adapter.d.ts +9 -0
- package/dist/agent/provider-adapter.js +24 -1
- package/dist/agent/registry.d.ts +1 -0
- package/dist/agent/registry.js +1 -0
- package/dist/agent/retry.d.ts +12 -1
- package/dist/agent/retry.js +19 -1
- package/dist/agent/runtime.d.ts +20 -0
- package/dist/agent/runtime.js +9 -1
- package/dist/agent/scoped-registry.d.ts +22 -0
- package/dist/agent/scoped-registry.js +42 -0
- package/dist/agent/task-manager.d.ts +115 -0
- package/dist/agent/task-manager.js +250 -0
- package/dist/agent/worker-spawner.d.ts +17 -12
- package/dist/agent/worker-spawner.js +26 -20
- package/dist/cli/dotenv.d.ts +3 -0
- package/dist/cli/dotenv.js +57 -0
- package/dist/cli/repl.js +41 -2
- package/dist/cli/run.d.ts +3 -0
- package/dist/cli/run.js +118 -7
- package/dist/context/klyro-md.d.ts +6 -0
- package/dist/context/klyro-md.js +21 -15
- package/dist/context/trust.d.ts +42 -0
- package/dist/context/trust.js +111 -0
- package/dist/events/catalog.d.ts +71 -0
- package/dist/index.js +4 -0
- package/dist/mcp/client.d.ts +53 -0
- package/dist/mcp/client.js +225 -0
- package/dist/mcp/config.d.ts +30 -0
- package/dist/mcp/config.js +82 -0
- package/dist/mcp/policy.d.ts +13 -0
- package/dist/mcp/policy.js +12 -0
- package/dist/mcp/registry.d.ts +50 -0
- package/dist/mcp/registry.js +172 -0
- package/dist/mcp/schema.d.ts +11 -0
- package/dist/mcp/schema.js +46 -0
- package/dist/policy/engine.js +3 -2
- package/dist/tools/agent/spawn-agent.d.ts +9 -0
- package/dist/tools/agent/spawn-agent.js +50 -0
- package/dist/tools/agent/task-get.d.ts +8 -0
- package/dist/tools/agent/task-get.js +40 -0
- package/dist/tools/agent/task-list.d.ts +4 -0
- package/dist/tools/agent/task-list.js +41 -0
- package/dist/tools/plan/todo-write.d.ts +1 -1
- package/dist/tools/registry.js +6 -0
- package/dist/tools/types.d.ts +12 -0
- package/package.json +1 -1
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* Auth can be a Bearer token (for proxies) — the adapter accepts either.
|
|
17
17
|
*/
|
|
18
18
|
import { assertSafeBaseURL } from '../chat.js';
|
|
19
|
+
import { parseRetryAfterMs } from './provider-adapter.js';
|
|
19
20
|
const DEFAULT_VERSION = '2023-06-01';
|
|
20
21
|
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
21
22
|
export class AnthropicApiError extends Error {
|
|
@@ -97,11 +98,15 @@ async function* streamAnthropic(req, opts) {
|
|
|
97
98
|
clearTimeout(timer);
|
|
98
99
|
if (!resp.ok || !resp.body) {
|
|
99
100
|
const text = await resp.text().catch(() => '<unreadable>');
|
|
101
|
+
const retryable = resp.status >= 500 || resp.status === 429;
|
|
102
|
+
const retryAfterMs = retryable ? parseRetryAfterMs(resp.headers?.get('retry-after')) : undefined;
|
|
100
103
|
yield {
|
|
101
104
|
kind: 'error',
|
|
102
105
|
code: `http_${resp.status}`,
|
|
103
106
|
message: `Anthropic API returned ${resp.status}: ${text.slice(0, 500)}`,
|
|
104
|
-
retryable
|
|
107
|
+
retryable,
|
|
108
|
+
status: String(resp.status),
|
|
109
|
+
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
105
110
|
};
|
|
106
111
|
return;
|
|
107
112
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent capability enforcement (P0.2 from r-6-10.fix.md).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the **effective tool set** for a (child) agent by intersecting:
|
|
5
|
+
*
|
|
6
|
+
* 1. the parent's effective tools — a child can never receive more tools than its parent
|
|
7
|
+
* 2. the agent definition's `allowedTools` (if specified)
|
|
8
|
+
* 3. the runtime policy's allowed tools (e.g. `--allow-write` flags)
|
|
9
|
+
*
|
|
10
|
+
* Then applies safety modifiers:
|
|
11
|
+
*
|
|
12
|
+
* - `readonly: true` strips every tool classified as write or mutation.
|
|
13
|
+
* - `canSpawn: false` (default for children) removes any spawn_agent-like tools.
|
|
14
|
+
* - A deny-list always wins, regardless of what the agent declares.
|
|
15
|
+
*
|
|
16
|
+
* This is a pure function — no I/O, no side effects. It exists so the runtime
|
|
17
|
+
* can decide which tools to expose to the model BEFORE the model picks one.
|
|
18
|
+
*
|
|
19
|
+
* Wiring lives in src/agent/runtime.ts (see the tool-filter hook).
|
|
20
|
+
*/
|
|
21
|
+
export interface AgentCapabilities {
|
|
22
|
+
/** Tools the agent definition explicitly allows. `undefined` means "no allow-list". */
|
|
23
|
+
allowedTools?: string[];
|
|
24
|
+
/** If true, write/mutation tools are stripped. */
|
|
25
|
+
readonly?: boolean;
|
|
26
|
+
/** If false (or unset), tools that can spawn new agents are stripped. */
|
|
27
|
+
canSpawn?: boolean;
|
|
28
|
+
/** Model override — if the provider cannot satisfy it, callers must error rather than fall back. */
|
|
29
|
+
model?: string;
|
|
30
|
+
/** Recursion depth cap. Beyond this, spawn attempts are blocked. */
|
|
31
|
+
maxDepth?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface ResolveToolsInput {
|
|
34
|
+
/** Tools the parent is allowed to use (or `null` for the root agent = all registered tools). */
|
|
35
|
+
parentTools: ReadonlySet<string> | null;
|
|
36
|
+
/** The agent's declared capability profile. */
|
|
37
|
+
agent: AgentCapabilities;
|
|
38
|
+
/** Tools currently allowed by runtime policy (e.g. user-permission flags). */
|
|
39
|
+
policyAllowed: ReadonlySet<string>;
|
|
40
|
+
/** All tools known to the registry (used when parentTools is null). */
|
|
41
|
+
registryTools: ReadonlySet<string>;
|
|
42
|
+
/** Tools that mutate state — stripped under `readonly`. */
|
|
43
|
+
writeTools: ReadonlySet<string>;
|
|
44
|
+
/** Tools that spawn other agents — stripped when `canSpawn` is false. */
|
|
45
|
+
spawnTools: ReadonlySet<string>;
|
|
46
|
+
/** Tools that are NEVER allowed, even if explicitly requested. */
|
|
47
|
+
denied: ReadonlySet<string>;
|
|
48
|
+
/** If true, spawn tools are kept even when agent.canSpawn is false/unset. */
|
|
49
|
+
canSpawnOverride?: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface ResolveToolsResult {
|
|
52
|
+
/** Tools the child agent is permitted to call. */
|
|
53
|
+
allowed: string[];
|
|
54
|
+
/** Tools that were denied (debugging/observability). */
|
|
55
|
+
dropped: {
|
|
56
|
+
tool: string;
|
|
57
|
+
reason: 'denied' | 'readonly' | 'no-spawn' | 'not-in-parent' | 'not-in-policy' | 'unknown';
|
|
58
|
+
}[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the effective tool set for an agent.
|
|
62
|
+
*
|
|
63
|
+
* Order of operations:
|
|
64
|
+
* 1. Start from `parentTools ?? registryTools`.
|
|
65
|
+
* 2. Intersect with `policyAllowed`.
|
|
66
|
+
* 3. If `allowedTools` is set, intersect again.
|
|
67
|
+
* 4. Strip `writeTools` if `readonly`.
|
|
68
|
+
* 5. Strip `spawnTools` if `!canSpawn`.
|
|
69
|
+
* 6. Remove `denied` last (always wins).
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveAgentTools(input: ResolveToolsInput): ResolveToolsResult;
|
|
72
|
+
/**
|
|
73
|
+
* Reason a tool was dropped from the resolved capability set. Mirrors
|
|
74
|
+
* `ResolveToolsResult.dropped[].reason`.
|
|
75
|
+
*/
|
|
76
|
+
export type DropReason = 'denied' | 'readonly' | 'no-spawn' | 'not-in-parent' | 'not-in-policy' | 'unknown';
|
|
77
|
+
/**
|
|
78
|
+
* Fully-resolved capability profile for a child agent — tool set plus
|
|
79
|
+
* non-tool knobs (model override, recursion cap). Computed once at spawn
|
|
80
|
+
* time and threaded through the runtime as `parentContext`.
|
|
81
|
+
*/
|
|
82
|
+
export interface ResolvedCapabilities {
|
|
83
|
+
/** Sorted tool names the child is allowed to invoke. */
|
|
84
|
+
allowed: ReadonlySet<string>;
|
|
85
|
+
/** Per-tool drop reasons — surfaced in ChildSummary for parent visibility. */
|
|
86
|
+
dropped: {
|
|
87
|
+
tool: string;
|
|
88
|
+
reason: DropReason;
|
|
89
|
+
}[];
|
|
90
|
+
/** Model override to send to the provider (or undefined to inherit parent). */
|
|
91
|
+
model?: string;
|
|
92
|
+
/** Effective recursion depth cap. Caller MUST reject spawn when depth + 1 > maxDepth. */
|
|
93
|
+
maxDepth: number;
|
|
94
|
+
readonly: boolean;
|
|
95
|
+
canSpawn: boolean;
|
|
96
|
+
}
|
|
97
|
+
/** Extra knobs consumed by `resolveCapabilities` on top of `ResolveToolsInput`. */
|
|
98
|
+
export interface ResolveCapabilitiesExtra {
|
|
99
|
+
/** Caller-provided maxDepth (e.g. from CLI `--max-depth` or a parent's maxDepth). Required. */
|
|
100
|
+
maxDepth: number;
|
|
101
|
+
/** If true, the resolved `allowed` set may include tools that themselves spawn agents. */
|
|
102
|
+
canSpawnOverride?: boolean;
|
|
103
|
+
}
|
|
104
|
+
/** Combined input for the one-shot resolver used by the orchestrator. */
|
|
105
|
+
export interface ResolveCapabilitiesInput extends ResolveToolsInput, ResolveCapabilitiesExtra {
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* One-shot capability resolver: tool intersection + per-agent model/maxDepth.
|
|
109
|
+
*
|
|
110
|
+
* `maxDepth` precedence (most specific wins):
|
|
111
|
+
* 1. `agent.maxDepth` (if set on the definition)
|
|
112
|
+
* 2. `extra.maxDepth` (parent / CLI cap)
|
|
113
|
+
* `model` is propagated only when the agent declares one; we do not silently
|
|
114
|
+
* override a parent's chosen model.
|
|
115
|
+
*/
|
|
116
|
+
export declare function resolveCapabilities(input: ResolveCapabilitiesInput): ResolvedCapabilities;
|
|
117
|
+
/** Sensible defaults for "what counts as a write tool" if a caller doesn't override. */
|
|
118
|
+
export declare const DEFAULT_WRITE_TOOLS: ReadonlySet<string>;
|
|
119
|
+
/** Default spawn tools — removed from children by default. */
|
|
120
|
+
export declare const DEFAULT_SPAWN_TOOLS: ReadonlySet<string>;
|
|
121
|
+
/** Default deny-list — these are NEVER allowed, even if explicitly requested. */
|
|
122
|
+
export declare const DEFAULT_DENIED_TOOLS: ReadonlySet<string>;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent capability enforcement (P0.2 from r-6-10.fix.md).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the **effective tool set** for a (child) agent by intersecting:
|
|
5
|
+
*
|
|
6
|
+
* 1. the parent's effective tools — a child can never receive more tools than its parent
|
|
7
|
+
* 2. the agent definition's `allowedTools` (if specified)
|
|
8
|
+
* 3. the runtime policy's allowed tools (e.g. `--allow-write` flags)
|
|
9
|
+
*
|
|
10
|
+
* Then applies safety modifiers:
|
|
11
|
+
*
|
|
12
|
+
* - `readonly: true` strips every tool classified as write or mutation.
|
|
13
|
+
* - `canSpawn: false` (default for children) removes any spawn_agent-like tools.
|
|
14
|
+
* - A deny-list always wins, regardless of what the agent declares.
|
|
15
|
+
*
|
|
16
|
+
* This is a pure function — no I/O, no side effects. It exists so the runtime
|
|
17
|
+
* can decide which tools to expose to the model BEFORE the model picks one.
|
|
18
|
+
*
|
|
19
|
+
* Wiring lives in src/agent/runtime.ts (see the tool-filter hook).
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the effective tool set for an agent.
|
|
23
|
+
*
|
|
24
|
+
* Order of operations:
|
|
25
|
+
* 1. Start from `parentTools ?? registryTools`.
|
|
26
|
+
* 2. Intersect with `policyAllowed`.
|
|
27
|
+
* 3. If `allowedTools` is set, intersect again.
|
|
28
|
+
* 4. Strip `writeTools` if `readonly`.
|
|
29
|
+
* 5. Strip `spawnTools` if `!canSpawn`.
|
|
30
|
+
* 6. Remove `denied` last (always wins).
|
|
31
|
+
*/
|
|
32
|
+
export function resolveAgentTools(input) {
|
|
33
|
+
const { parentTools, agent, policyAllowed, registryTools, writeTools, spawnTools, denied, } = input;
|
|
34
|
+
const allowed = new Set();
|
|
35
|
+
const dropped = [];
|
|
36
|
+
// 1. Baseline: parent's tools, or all registered tools for the root agent.
|
|
37
|
+
// Record narrowing for observability: registry tools outside the parent's
|
|
38
|
+
// set are reported as 'not-in-parent' drops (child can never exceed parent).
|
|
39
|
+
const baseline = parentTools ?? registryTools;
|
|
40
|
+
if (parentTools !== null) {
|
|
41
|
+
for (const name of registryTools) {
|
|
42
|
+
if (!parentTools.has(name)) {
|
|
43
|
+
dropped.push({ tool: name, reason: 'not-in-parent' });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
for (const name of baseline) {
|
|
48
|
+
if (!registryTools.has(name)) {
|
|
49
|
+
dropped.push({ tool: name, reason: 'unknown' });
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!policyAllowed.has(name)) {
|
|
53
|
+
dropped.push({ tool: name, reason: 'not-in-policy' });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
allowed.add(name);
|
|
57
|
+
}
|
|
58
|
+
// 3. Apply the agent's allow-list (if any). Anything not in the list is dropped.
|
|
59
|
+
if (agent.allowedTools) {
|
|
60
|
+
const explicit = new Set(agent.allowedTools);
|
|
61
|
+
for (const name of [...allowed]) {
|
|
62
|
+
if (!explicit.has(name)) {
|
|
63
|
+
allowed.delete(name);
|
|
64
|
+
dropped.push({ tool: name, reason: 'not-in-parent' });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Tools requested in allowedTools but not in the baseline cannot be granted.
|
|
68
|
+
for (const name of agent.allowedTools) {
|
|
69
|
+
if (!allowed.has(name) && registryTools.has(name) && policyAllowed.has(name)) {
|
|
70
|
+
dropped.push({ tool: name, reason: 'not-in-parent' });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// 4. readonly → strip write tools.
|
|
75
|
+
if (agent.readonly) {
|
|
76
|
+
for (const name of [...allowed]) {
|
|
77
|
+
if (writeTools.has(name)) {
|
|
78
|
+
allowed.delete(name);
|
|
79
|
+
dropped.push({ tool: name, reason: 'readonly' });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// 5. canSpawn=false → strip spawn tools. Default: root agent (parentTools
|
|
84
|
+
// === null) may spawn; children strip unless explicitly enabled. An explicit
|
|
85
|
+
// canSpawnOverride=true (via resolveCapabilities) also keeps them.
|
|
86
|
+
const canSpawnEffective = input.canSpawnOverride ?? input.agent.canSpawn ?? (input.parentTools === null);
|
|
87
|
+
if (!canSpawnEffective) {
|
|
88
|
+
for (const name of [...allowed]) {
|
|
89
|
+
if (spawnTools.has(name)) {
|
|
90
|
+
allowed.delete(name);
|
|
91
|
+
dropped.push({ tool: name, reason: 'no-spawn' });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// 6. Deny-list always wins.
|
|
96
|
+
for (const name of [...allowed]) {
|
|
97
|
+
if (denied.has(name)) {
|
|
98
|
+
allowed.delete(name);
|
|
99
|
+
dropped.push({ tool: name, reason: 'denied' });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
allowed: [...allowed].sort(),
|
|
104
|
+
dropped: dropped.sort((a, b) => a.tool.localeCompare(b.tool)),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* One-shot capability resolver: tool intersection + per-agent model/maxDepth.
|
|
109
|
+
*
|
|
110
|
+
* `maxDepth` precedence (most specific wins):
|
|
111
|
+
* 1. `agent.maxDepth` (if set on the definition)
|
|
112
|
+
* 2. `extra.maxDepth` (parent / CLI cap)
|
|
113
|
+
* `model` is propagated only when the agent declares one; we do not silently
|
|
114
|
+
* override a parent's chosen model.
|
|
115
|
+
*/
|
|
116
|
+
export function resolveCapabilities(input) {
|
|
117
|
+
const resolved = resolveAgentTools(input);
|
|
118
|
+
const allowed = new Set(resolved.allowed);
|
|
119
|
+
const model = input.agent.model;
|
|
120
|
+
const maxDepth = input.agent.maxDepth ?? input.maxDepth;
|
|
121
|
+
const canSpawn = input.canSpawnOverride ?? input.agent.canSpawn ?? false;
|
|
122
|
+
return {
|
|
123
|
+
allowed,
|
|
124
|
+
dropped: resolved.dropped,
|
|
125
|
+
...(model !== undefined ? { model } : {}),
|
|
126
|
+
maxDepth,
|
|
127
|
+
readonly: input.agent.readonly ?? false,
|
|
128
|
+
canSpawn,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** Sensible defaults for "what counts as a write tool" if a caller doesn't override. */
|
|
132
|
+
export const DEFAULT_WRITE_TOOLS = new Set([
|
|
133
|
+
'write_file',
|
|
134
|
+
'edit_file',
|
|
135
|
+
'multi_edit',
|
|
136
|
+
'apply_patch',
|
|
137
|
+
'shell_exec',
|
|
138
|
+
'memory_write',
|
|
139
|
+
'background_shell',
|
|
140
|
+
'todo_write',
|
|
141
|
+
]);
|
|
142
|
+
/** Default spawn tools — removed from children by default. */
|
|
143
|
+
export const DEFAULT_SPAWN_TOOLS = new Set([
|
|
144
|
+
'spawn_agent',
|
|
145
|
+
'subtask',
|
|
146
|
+
]);
|
|
147
|
+
/** Default deny-list — these are NEVER allowed, even if explicitly requested. */
|
|
148
|
+
export const DEFAULT_DENIED_TOOLS = new Set([
|
|
149
|
+
// Add dangerous tools here. Empty by default — extend as policy matures.
|
|
150
|
+
]);
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentOrchestrator — spawns child agents and turns them into tasks.
|
|
3
|
+
*
|
|
4
|
+
* The lowest-level way to run Klyro is `run(options, deps)` (one agent,
|
|
5
|
+
* one loop). Orchestration layers on top of that: a parent agent calls
|
|
6
|
+
* `spawn_agent`, which resolves the target `AgentDefinition`, computes its
|
|
7
|
+
* effective capabilities (via `resolveCapabilities`), creates a
|
|
8
|
+
* `TaskRecord`, and runs a *scoped* child loop. The child runs in-process
|
|
9
|
+
* with a `ScopedRegistry` (narrowed tool set), an optional model override,
|
|
10
|
+
* a depth cap, and an AbortController wired to the parent's signal.
|
|
11
|
+
*
|
|
12
|
+
* The compact result is a `ChildSummary` — a `ToolResult` the parent model
|
|
13
|
+
* can act on — never the full child transcript.
|
|
14
|
+
*/
|
|
15
|
+
import type { RuntimeDeps } from './runtime.js';
|
|
16
|
+
import type { ToolResult } from '../tools/types.js';
|
|
17
|
+
import { TaskManager, type TaskStatus, type TaskSummary } from './task-manager.js';
|
|
18
|
+
import { WorkerSpawner } from './worker-spawner.js';
|
|
19
|
+
import { type DropReason } from './capabilities.js';
|
|
20
|
+
/** An agent a model can delegate to via `spawn_agent`. */
|
|
21
|
+
export interface AgentDefinition {
|
|
22
|
+
id: string;
|
|
23
|
+
description: string;
|
|
24
|
+
/** Explicit allow-list. Undefined means "inherit every tool the parent has". */
|
|
25
|
+
allowedTools?: string[];
|
|
26
|
+
readonly?: boolean;
|
|
27
|
+
/** Children cannot spawn further agents unless explicitly enabled. */
|
|
28
|
+
canSpawn?: boolean;
|
|
29
|
+
/** Per-agent model override. Must be honoured (or surfaced as an error). */
|
|
30
|
+
model?: string;
|
|
31
|
+
maxDepth?: number;
|
|
32
|
+
maxSteps?: number;
|
|
33
|
+
maxCost?: number;
|
|
34
|
+
maxTimeMs?: number;
|
|
35
|
+
}
|
|
36
|
+
/** Default agents a model can delegate to. */
|
|
37
|
+
export declare const BUILTIN_AGENTS: readonly AgentDefinition[];
|
|
38
|
+
/** Compact summary returned to the parent — the child's transcript stays separate. */
|
|
39
|
+
export interface ChildSummary {
|
|
40
|
+
taskId: string;
|
|
41
|
+
agentName: string;
|
|
42
|
+
status: TaskStatus;
|
|
43
|
+
durationMs: number;
|
|
44
|
+
finalText?: string;
|
|
45
|
+
changedFiles: string[];
|
|
46
|
+
usage?: {
|
|
47
|
+
input: number;
|
|
48
|
+
output: number;
|
|
49
|
+
estimated?: boolean;
|
|
50
|
+
};
|
|
51
|
+
error?: {
|
|
52
|
+
code: string;
|
|
53
|
+
message: string;
|
|
54
|
+
};
|
|
55
|
+
/** Tool drops from capability resolution, surfaced for parent visibility. */
|
|
56
|
+
droppedTools?: {
|
|
57
|
+
tool: string;
|
|
58
|
+
reason: DropReason;
|
|
59
|
+
}[];
|
|
60
|
+
}
|
|
61
|
+
/** Capability context the bridge passes when the parent calls spawn_agent. */
|
|
62
|
+
export interface ParentContextRef {
|
|
63
|
+
taskId?: string;
|
|
64
|
+
parentTaskId?: string;
|
|
65
|
+
sessionId: string;
|
|
66
|
+
cwd: string;
|
|
67
|
+
depth: number;
|
|
68
|
+
maxDepth: number;
|
|
69
|
+
allowedTools: ReadonlySet<string> | null;
|
|
70
|
+
model?: string;
|
|
71
|
+
}
|
|
72
|
+
/** Interface exposed to the runtime/tools for a child spawn request. */
|
|
73
|
+
export interface AgentSpawnBridge {
|
|
74
|
+
parent: ParentContextRef;
|
|
75
|
+
spawnAgent(input: {
|
|
76
|
+
agent: string;
|
|
77
|
+
task: string;
|
|
78
|
+
cwd?: string;
|
|
79
|
+
model?: string;
|
|
80
|
+
timeoutMs?: number;
|
|
81
|
+
}): Promise<ToolResult<ChildSummary>>;
|
|
82
|
+
listAgents(): AgentDefinition[];
|
|
83
|
+
getAgent(id: string): AgentDefinition | undefined;
|
|
84
|
+
listTasks(filter?: {
|
|
85
|
+
parentTaskId?: string;
|
|
86
|
+
status?: TaskStatus;
|
|
87
|
+
}): TaskSummary[];
|
|
88
|
+
getTask(id: string): TaskSummary & {
|
|
89
|
+
error?: {
|
|
90
|
+
code: string;
|
|
91
|
+
message: string;
|
|
92
|
+
};
|
|
93
|
+
} | undefined;
|
|
94
|
+
}
|
|
95
|
+
/** Constructor options for the orchestrator — the parent runtime's deps. */
|
|
96
|
+
export interface OrchestratorOpts {
|
|
97
|
+
sessionId: string;
|
|
98
|
+
deps: RuntimeDeps;
|
|
99
|
+
taskManager?: TaskManager;
|
|
100
|
+
workerSpawner?: WorkerSpawner;
|
|
101
|
+
}
|
|
102
|
+
export declare class AgentOrchestrator {
|
|
103
|
+
readonly sessionId: string;
|
|
104
|
+
readonly deps: RuntimeDeps;
|
|
105
|
+
readonly taskManager: TaskManager;
|
|
106
|
+
readonly workerSpawner: WorkerSpawner;
|
|
107
|
+
constructor(opts: OrchestratorOpts);
|
|
108
|
+
listAgents(): AgentDefinition[];
|
|
109
|
+
getAgent(id: string): AgentDefinition | undefined;
|
|
110
|
+
/** Build the bridge the parent's runtime hands to tools. */
|
|
111
|
+
bridgeFor(parent: ParentContextRef): AgentSpawnBridge;
|
|
112
|
+
/** Compute a child's effective capabilities from the parent's own. */
|
|
113
|
+
private resolveChild;
|
|
114
|
+
/**
|
|
115
|
+
* Spawn a child agent for a given capability context, await its run, and
|
|
116
|
+
* return a compact summary. Blocks until the child settles (P0 scope;
|
|
117
|
+
* async task_wait arrives in a later slice).
|
|
118
|
+
*/
|
|
119
|
+
spawnAgent(input: {
|
|
120
|
+
agent: string;
|
|
121
|
+
task: string;
|
|
122
|
+
cwd?: string;
|
|
123
|
+
model?: string;
|
|
124
|
+
timeoutMs?: number;
|
|
125
|
+
}, parent: ParentContextRef): Promise<ToolResult<ChildSummary>>;
|
|
126
|
+
private toChildSummary;
|
|
127
|
+
}
|
|
128
|
+
/** Module-scoped holder the orchestrator sets so children inherit the parent's signal. */
|
|
129
|
+
export declare const parentAbortSignalRef: {
|
|
130
|
+
current: AbortSignal | null;
|
|
131
|
+
};
|