openhorse 0.2.19 → 0.2.21
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/coordinator.d.ts.map +1 -1
- package/dist/agents/fork.d.ts.map +1 -1
- package/dist/agents/fork.js +0 -1
- package/dist/agents/fork.js.map +1 -1
- package/dist/agents/worker-pool.d.ts.map +1 -1
- package/dist/agents/worker-pool.js +3 -1
- package/dist/agents/worker-pool.js.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +13 -28
- package/dist/commands/index.js.map +1 -1
- package/dist/core/checkpoint.d.ts.map +1 -1
- package/dist/core/checkpoint.js +3 -0
- package/dist/core/checkpoint.js.map +1 -1
- package/dist/framework/prompt.d.ts.map +1 -1
- package/dist/framework/prompt.js +16 -0
- package/dist/framework/prompt.js.map +1 -1
- package/dist/framework/query.d.ts.map +1 -1
- package/dist/framework/query.js +0 -7
- package/dist/framework/query.js.map +1 -1
- package/dist/harness/context-harness.d.ts.map +1 -1
- package/dist/harness/context-harness.js +6 -1
- package/dist/harness/context-harness.js.map +1 -1
- package/dist/harness/ledger.d.ts +1 -0
- package/dist/harness/ledger.d.ts.map +1 -1
- package/dist/harness/ledger.js +8 -0
- package/dist/harness/ledger.js.map +1 -1
- package/dist/harness/safety.d.ts +2 -0
- package/dist/harness/safety.d.ts.map +1 -1
- package/dist/harness/safety.js +27 -3
- package/dist/harness/safety.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +1 -1
- package/dist/init.js.map +1 -1
- package/dist/ink-ui/components/Markdown.d.ts +1 -1
- package/dist/ink-ui/components/Markdown.d.ts.map +1 -1
- package/dist/ink-ui/components/Markdown.js +1 -1
- package/dist/ink-ui/components/Markdown.js.map +1 -1
- package/dist/ink-ui/runtime/grapheme.d.ts +9 -8
- package/dist/ink-ui/runtime/grapheme.d.ts.map +1 -1
- package/dist/ink-ui/runtime/grapheme.js +14 -60
- package/dist/ink-ui/runtime/grapheme.js.map +1 -1
- package/dist/ink-ui/runtime/input-buffer.d.ts +9 -31
- package/dist/ink-ui/runtime/input-buffer.d.ts.map +1 -1
- package/dist/ink-ui/runtime/input-buffer.js +15 -162
- package/dist/ink-ui/runtime/input-buffer.js.map +1 -1
- package/dist/ink-ui/runtime/native-cursor.js +0 -25
- package/dist/ink-ui/runtime/native-cursor.js.map +1 -1
- package/dist/ink-ui/runtime/prompt-layout.d.ts +9 -29
- package/dist/ink-ui/runtime/prompt-layout.d.ts.map +1 -1
- package/dist/ink-ui/runtime/prompt-layout.js +18 -166
- package/dist/ink-ui/runtime/prompt-layout.js.map +1 -1
- package/dist/ink-ui/runtime/transcript-state.d.ts.map +1 -1
- package/dist/ink-ui/runtime/transcript-state.js +2 -0
- package/dist/ink-ui/runtime/transcript-state.js.map +1 -1
- package/dist/ink-ui/screens/ReplScreen.d.ts.map +1 -1
- package/dist/ink-ui/screens/ReplScreen.js +11 -0
- package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
- package/dist/memory/entrypoint.js +1 -1
- package/dist/memory/entrypoint.js.map +1 -1
- package/dist/memory/storage.js +1 -1
- package/dist/memory/storage.js.map +1 -1
- package/dist/memory/store.d.ts +1 -0
- package/dist/memory/store.d.ts.map +1 -1
- package/dist/memory/store.js +9 -0
- package/dist/memory/store.js.map +1 -1
- package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
- package/dist/runtime/agent-runtime-controller.js +15 -0
- package/dist/runtime/agent-runtime-controller.js.map +1 -1
- package/dist/runtime/agent-runtime-protocol.d.ts +4 -1
- package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
- package/dist/runtime/agent-runtime-protocol.js +6 -0
- package/dist/runtime/agent-runtime-protocol.js.map +1 -1
- package/dist/runtime/chat-controller.d.ts +27 -0
- package/dist/runtime/chat-controller.d.ts.map +1 -1
- package/dist/runtime/chat-controller.js +148 -5
- package/dist/runtime/chat-controller.js.map +1 -1
- package/dist/runtime/composer/buffer.d.ts +43 -0
- package/dist/runtime/composer/buffer.d.ts.map +1 -0
- package/dist/runtime/composer/buffer.js +176 -0
- package/dist/runtime/composer/buffer.js.map +1 -0
- package/dist/runtime/composer/grapheme.d.ts +19 -0
- package/dist/runtime/composer/grapheme.d.ts.map +1 -0
- package/dist/runtime/composer/grapheme.js +73 -0
- package/dist/runtime/composer/grapheme.js.map +1 -0
- package/dist/runtime/composer/history.d.ts +39 -0
- package/dist/runtime/composer/history.d.ts.map +1 -0
- package/dist/runtime/composer/history.js +91 -0
- package/dist/runtime/composer/history.js.map +1 -0
- package/dist/runtime/composer/layout.d.ts +40 -0
- package/dist/runtime/composer/layout.d.ts.map +1 -0
- package/dist/runtime/composer/layout.js +174 -0
- package/dist/runtime/composer/layout.js.map +1 -0
- package/dist/runtime/rich-text/ansi-parser.d.ts +31 -0
- package/dist/runtime/rich-text/ansi-parser.d.ts.map +1 -0
- package/dist/runtime/rich-text/ansi-parser.js +272 -0
- package/dist/runtime/rich-text/ansi-parser.js.map +1 -0
- package/dist/runtime/rich-text/layout.d.ts +21 -0
- package/dist/runtime/rich-text/layout.d.ts.map +1 -0
- package/dist/runtime/rich-text/layout.js +327 -0
- package/dist/runtime/rich-text/layout.js.map +1 -0
- package/dist/runtime/rich-text/markdown-parser.d.ts +17 -0
- package/dist/runtime/rich-text/markdown-parser.d.ts.map +1 -0
- package/dist/runtime/rich-text/markdown-parser.js +211 -0
- package/dist/runtime/rich-text/markdown-parser.js.map +1 -0
- package/dist/runtime/rich-text/sanitizer.d.ts +18 -0
- package/dist/runtime/rich-text/sanitizer.d.ts.map +1 -0
- package/dist/runtime/rich-text/sanitizer.js +32 -0
- package/dist/runtime/rich-text/sanitizer.js.map +1 -0
- package/dist/runtime/rich-text/types.d.ts +59 -0
- package/dist/runtime/rich-text/types.d.ts.map +1 -0
- package/dist/runtime/rich-text/types.js +17 -0
- package/dist/runtime/rich-text/types.js.map +1 -0
- package/dist/runtime/subagents/budget.d.ts +118 -0
- package/dist/runtime/subagents/budget.d.ts.map +1 -0
- package/dist/runtime/subagents/budget.js +173 -0
- package/dist/runtime/subagents/budget.js.map +1 -0
- package/dist/runtime/subagents/child-executor-guard.d.ts +60 -0
- package/dist/runtime/subagents/child-executor-guard.d.ts.map +1 -0
- package/dist/runtime/subagents/child-executor-guard.js +219 -0
- package/dist/runtime/subagents/child-executor-guard.js.map +1 -0
- package/dist/runtime/subagents/context-builder.d.ts +34 -0
- package/dist/runtime/subagents/context-builder.d.ts.map +1 -0
- package/dist/runtime/subagents/context-builder.js +99 -0
- package/dist/runtime/subagents/context-builder.js.map +1 -0
- package/dist/runtime/subagents/index.d.ts +21 -0
- package/dist/runtime/subagents/index.d.ts.map +1 -0
- package/dist/runtime/subagents/index.js +62 -0
- package/dist/runtime/subagents/index.js.map +1 -0
- package/dist/runtime/subagents/policy.d.ts +68 -0
- package/dist/runtime/subagents/policy.d.ts.map +1 -0
- package/dist/runtime/subagents/policy.js +230 -0
- package/dist/runtime/subagents/policy.js.map +1 -0
- package/dist/runtime/subagents/presets.d.ts +44 -0
- package/dist/runtime/subagents/presets.d.ts.map +1 -0
- package/dist/runtime/subagents/presets.js +148 -0
- package/dist/runtime/subagents/presets.js.map +1 -0
- package/dist/runtime/subagents/production.d.ts +44 -0
- package/dist/runtime/subagents/production.d.ts.map +1 -0
- package/dist/runtime/subagents/production.js +118 -0
- package/dist/runtime/subagents/production.js.map +1 -0
- package/dist/runtime/subagents/provider-gate.d.ts +99 -0
- package/dist/runtime/subagents/provider-gate.d.ts.map +1 -0
- package/dist/runtime/subagents/provider-gate.js +186 -0
- package/dist/runtime/subagents/provider-gate.js.map +1 -0
- package/dist/runtime/subagents/result-parser.d.ts +40 -0
- package/dist/runtime/subagents/result-parser.d.ts.map +1 -0
- package/dist/runtime/subagents/result-parser.js +226 -0
- package/dist/runtime/subagents/result-parser.js.map +1 -0
- package/dist/runtime/subagents/runner.d.ts +53 -0
- package/dist/runtime/subagents/runner.d.ts.map +1 -0
- package/dist/runtime/subagents/runner.js +172 -0
- package/dist/runtime/subagents/runner.js.map +1 -0
- package/dist/runtime/subagents/runtime-integration.d.ts +73 -0
- package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -0
- package/dist/runtime/subagents/runtime-integration.js +148 -0
- package/dist/runtime/subagents/runtime-integration.js.map +1 -0
- package/dist/runtime/subagents/supervisor.d.ts +79 -0
- package/dist/runtime/subagents/supervisor.d.ts.map +1 -0
- package/dist/runtime/subagents/supervisor.js +301 -0
- package/dist/runtime/subagents/supervisor.js.map +1 -0
- package/dist/runtime/subagents/tool.d.ts +38 -0
- package/dist/runtime/subagents/tool.d.ts.map +1 -0
- package/dist/runtime/subagents/tool.js +171 -0
- package/dist/runtime/subagents/tool.js.map +1 -0
- package/dist/runtime/subagents/types.d.ts +150 -0
- package/dist/runtime/subagents/types.d.ts.map +1 -0
- package/dist/runtime/subagents/types.js +52 -0
- package/dist/runtime/subagents/types.js.map +1 -0
- package/dist/runtime/ui-events.d.ts +5 -0
- package/dist/runtime/ui-events.d.ts.map +1 -1
- package/dist/runtime/ui-events.js.map +1 -1
- package/dist/runtime/ui-view-model.d.ts +35 -1
- package/dist/runtime/ui-view-model.d.ts.map +1 -1
- package/dist/runtime/ui-view-model.js +32 -1
- package/dist/runtime/ui-view-model.js.map +1 -1
- package/dist/sdk/query.d.ts.map +1 -1
- package/dist/sdk/query.js +0 -1
- package/dist/sdk/query.js.map +1 -1
- package/dist/services/auto-fix/autoFixHook.d.ts.map +1 -1
- package/dist/services/auto-fix/autoFixHook.js +3 -2
- package/dist/services/auto-fix/autoFixHook.js.map +1 -1
- package/dist/services/auto-fix/autoFixRunner.d.ts +2 -2
- package/dist/services/auto-fix/autoFixRunner.d.ts.map +1 -1
- package/dist/services/auto-fix/autoFixRunner.js +2 -2
- package/dist/services/auto-fix/autoFixRunner.js.map +1 -1
- package/dist/services/compact/auto-compact.js +3 -3
- package/dist/services/compact/auto-compact.js.map +1 -1
- package/dist/services/compact/summary-generator.d.ts.map +1 -1
- package/dist/services/compact/summary-generator.js +0 -1
- package/dist/services/compact/summary-generator.js.map +1 -1
- package/dist/services/concurrent-sessions.d.ts.map +1 -1
- package/dist/services/concurrent-sessions.js +3 -0
- package/dist/services/concurrent-sessions.js.map +1 -1
- package/dist/services/config.d.ts +11 -4
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +45 -4
- package/dist/services/config.js.map +1 -1
- package/dist/services/doctor.d.ts.map +1 -1
- package/dist/services/doctor.js +1 -1
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/global-config.d.ts +23 -1
- package/dist/services/global-config.d.ts.map +1 -1
- package/dist/services/global-config.js +3 -0
- package/dist/services/global-config.js.map +1 -1
- package/dist/services/llm.d.ts.map +1 -1
- package/dist/services/llm.js +9 -1
- package/dist/services/llm.js.map +1 -1
- package/dist/services/mcp/transports.d.ts +2 -0
- package/dist/services/mcp/transports.d.ts.map +1 -1
- package/dist/services/mcp/transports.js +23 -2
- package/dist/services/mcp/transports.js.map +1 -1
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js.map +1 -1
- package/dist/services/model-context.d.ts.map +1 -1
- package/dist/services/model-context.js +7 -1
- package/dist/services/model-context.js.map +1 -1
- package/dist/services/session-memory/sessionMemory.js +1 -1
- package/dist/services/session-memory/sessionMemory.js.map +1 -1
- package/dist/services/session-storage.d.ts +1 -1
- package/dist/services/session-storage.d.ts.map +1 -1
- package/dist/services/session-storage.js +38 -4
- package/dist/services/session-storage.js.map +1 -1
- package/dist/services/task-manager.d.ts +2 -0
- package/dist/services/task-manager.d.ts.map +1 -1
- package/dist/services/task-manager.js +13 -0
- package/dist/services/task-manager.js.map +1 -1
- package/dist/services/usage-state.d.ts.map +1 -1
- package/dist/services/usage-state.js +3 -0
- package/dist/services/usage-state.js.map +1 -1
- package/dist/skills/loader.d.ts +1 -1
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +1 -1
- package/dist/skills/loader.js.map +1 -1
- package/dist/skills/registry.d.ts +1 -1
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +1 -1
- package/dist/skills/registry.js.map +1 -1
- package/dist/terminal-ui/launch.d.ts +18 -3
- package/dist/terminal-ui/launch.d.ts.map +1 -1
- package/dist/terminal-ui/launch.js +21 -4
- package/dist/terminal-ui/launch.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/lsp.js.map +1 -1
- package/dist/tools/web.js +3 -3
- package/dist/tools/web.js.map +1 -1
- package/dist/tui-core/frame.d.ts +13 -1
- package/dist/tui-core/frame.d.ts.map +1 -1
- package/dist/tui-core/frame.js +61 -8
- package/dist/tui-core/frame.js.map +1 -1
- package/dist/tui-core/style.d.ts +87 -0
- package/dist/tui-core/style.d.ts.map +1 -0
- package/dist/tui-core/style.js +248 -0
- package/dist/tui-core/style.js.map +1 -0
- package/dist/tui-core/terminal-writer.d.ts.map +1 -1
- package/dist/tui-core/terminal-writer.js +16 -3
- package/dist/tui-core/terminal-writer.js.map +1 -1
- package/dist/tui-ui/inline-surface.d.ts +134 -0
- package/dist/tui-ui/inline-surface.d.ts.map +1 -0
- package/dist/tui-ui/inline-surface.js +364 -0
- package/dist/tui-ui/inline-surface.js.map +1 -0
- package/dist/tui-ui/launch.d.ts.map +1 -1
- package/dist/tui-ui/launch.js +249 -64
- package/dist/tui-ui/launch.js.map +1 -1
- package/dist/tui-ui/layout.js +15 -2
- package/dist/tui-ui/layout.js.map +1 -1
- package/dist/tui-ui/render-scheduler.d.ts +37 -0
- package/dist/tui-ui/render-scheduler.d.ts.map +1 -0
- package/dist/tui-ui/render-scheduler.js +118 -0
- package/dist/tui-ui/render-scheduler.js.map +1 -0
- package/dist/tui-ui/runner.d.ts +12 -0
- package/dist/tui-ui/runner.d.ts.map +1 -1
- package/dist/tui-ui/runner.js +34 -2
- package/dist/tui-ui/runner.js.map +1 -1
- package/dist/tui-ui/state.d.ts +33 -3
- package/dist/tui-ui/state.d.ts.map +1 -1
- package/dist/tui-ui/state.js +138 -25
- package/dist/tui-ui/state.js.map +1 -1
- package/dist/tui-ui/transcript-cache.d.ts +33 -0
- package/dist/tui-ui/transcript-cache.d.ts.map +1 -0
- package/dist/tui-ui/transcript-cache.js +67 -0
- package/dist/tui-ui/transcript-cache.js.map +1 -0
- package/dist/ui/box.d.ts.map +1 -1
- package/dist/ui/box.js +0 -11
- package/dist/ui/box.js.map +1 -1
- package/dist/ui/command-panel.d.ts.map +1 -1
- package/dist/ui/command-panel.js +1 -3
- package/dist/ui/command-panel.js.map +1 -1
- package/dist/ui/file-completion.js +1 -1
- package/dist/ui/file-completion.js.map +1 -1
- package/dist/ui/markdown.d.ts.map +1 -1
- package/dist/ui/markdown.js +1 -2
- package/dist/ui/markdown.js.map +1 -1
- package/dist/ui/multiline-input.d.ts.map +1 -1
- package/dist/ui/multiline-input.js +1 -2
- package/dist/ui/multiline-input.js.map +1 -1
- package/dist/ui/progress.d.ts.map +1 -1
- package/dist/ui/progress.js +0 -3
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/status-bar.d.ts.map +1 -1
- package/dist/ui/status-bar.js +0 -1
- package/dist/ui/status-bar.js.map +1 -1
- package/dist/ui/stream-markdown.d.ts +3 -0
- package/dist/ui/stream-markdown.d.ts.map +1 -1
- package/dist/ui/stream-markdown.js +0 -6
- package/dist/ui/stream-markdown.js.map +1 -1
- package/dist/ui/tool-preview.d.ts.map +1 -1
- package/dist/ui/tool-preview.js +0 -1
- package/dist/ui/tool-preview.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli-dbg.js +0 -717
- package/dist/cli-debug.d.ts +0 -7
- package/dist/cli-debug.d.ts.map +0 -1
- package/dist/cli-debug.js +0 -717
- package/dist/cli-debug.js.map +0 -1
- package/dist/cli-debug2.d.ts +0 -7
- package/dist/cli-debug2.d.ts.map +0 -1
- package/dist/cli-debug2.js +0 -717
- package/dist/cli-debug2.js.map +0 -1
- package/dist/cli-debug3.d.ts +0 -7
- package/dist/cli-debug3.d.ts.map +0 -1
- package/dist/cli-debug3.js +0 -719
- package/dist/cli-debug3.js.map +0 -1
- package/dist/cli-ink.d.ts +0 -8
- package/dist/cli-ink.d.ts.map +0 -1
- package/dist/cli-ink.js +0 -32
- package/dist/cli-ink.js.map +0 -1
- package/dist/cli-patch.js +0 -716
- package/dist/cli-test.js +0 -726
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Subagent budget ledger: reserve before launch, reconcile after completion.
|
|
4
|
+
*
|
|
5
|
+
* The root turn owns an aggregate budget (model requests, tool calls,
|
|
6
|
+
* model-visible bytes, wall-clock time). Children draw against it. To avoid
|
|
7
|
+
* over-spending, the Supervisor reserves a per-task allowance up front and
|
|
8
|
+
* releases the difference once the real usage is known.
|
|
9
|
+
*
|
|
10
|
+
* This ledger is the single source of truth for child aggregate usage; the
|
|
11
|
+
* root loop reads it to fold child cost into `/cost` and loop stats.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.SubagentBudgetLedger = exports.TurnTaskState = void 0;
|
|
15
|
+
exports.budgetLimitsFromConfig = budgetLimitsFromConfig;
|
|
16
|
+
const types_1 = require("./types");
|
|
17
|
+
/**
|
|
18
|
+
* R6: turn-level mutable state shared across all `subtask` calls within one
|
|
19
|
+
* root turn. Lives on the SubagentTurnBundle so multiple `subtask` tool calls
|
|
20
|
+
* in the same turn see a consistent counter - the per-batch reset that
|
|
21
|
+
* previously let a turn exceed `maxTasksPerTurn` is gone.
|
|
22
|
+
*/
|
|
23
|
+
class TurnTaskState {
|
|
24
|
+
constructor() {
|
|
25
|
+
this.started = 0;
|
|
26
|
+
}
|
|
27
|
+
/** Increment by `n` and return the new total. Called atomically by the
|
|
28
|
+
* supervisor after policy allows a batch. */
|
|
29
|
+
addStarted(n) {
|
|
30
|
+
this.started += n;
|
|
31
|
+
return this.started;
|
|
32
|
+
}
|
|
33
|
+
/** Total tasks started in this root turn (across all `subtask` calls). */
|
|
34
|
+
tasksStarted() {
|
|
35
|
+
return this.started;
|
|
36
|
+
}
|
|
37
|
+
reset() {
|
|
38
|
+
this.started = 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.TurnTaskState = TurnTaskState;
|
|
42
|
+
/**
|
|
43
|
+
* Aggregate budget ledger for one root turn. Not thread-safe by itself;
|
|
44
|
+
* the Supervisor serializes mutations.
|
|
45
|
+
*
|
|
46
|
+
* R6: observed usage is recorded faithfully (never clamped to hide overage).
|
|
47
|
+
* The enforced allowance and observed usage are modeled separately, so `/cost`
|
|
48
|
+
* and telemetry reflect the truth while the runtime still stops children that
|
|
49
|
+
* exceed their allowance.
|
|
50
|
+
*/
|
|
51
|
+
class SubagentBudgetLedger {
|
|
52
|
+
constructor(limits) {
|
|
53
|
+
this.reserved = new Map();
|
|
54
|
+
this.reconciled = [];
|
|
55
|
+
this.violations = [];
|
|
56
|
+
this.limits = limits;
|
|
57
|
+
}
|
|
58
|
+
/** Reserve model-request slots for a task. Returns false if unavailable. */
|
|
59
|
+
reserve(taskId, requestedRequests) {
|
|
60
|
+
if (this.reserved.has(taskId))
|
|
61
|
+
return null;
|
|
62
|
+
const want = Math.max(1, Math.min(requestedRequests, this.limits.maxModelRequestsPerTask));
|
|
63
|
+
if (want > this.availableModelRequests())
|
|
64
|
+
return null;
|
|
65
|
+
this.reserved.set(taskId, want);
|
|
66
|
+
return { taskId, modelRequests: want };
|
|
67
|
+
}
|
|
68
|
+
/** Release a reservation without consuming (e.g. task rejected after reserve). */
|
|
69
|
+
release(taskId) {
|
|
70
|
+
this.reserved.delete(taskId);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Reconcile actual usage for a task. Releases its reservation and debits
|
|
74
|
+
* the REAL usage (never clamped). Records a violation if observed usage
|
|
75
|
+
* exceeded an enforced per-task or aggregate ceiling. Returns true if the
|
|
76
|
+
* aggregate turn limit is still respected.
|
|
77
|
+
*
|
|
78
|
+
* R6: observed usage is stored as-is so `/cost` and telemetry are truthful.
|
|
79
|
+
*/
|
|
80
|
+
reconcile(taskId, actual) {
|
|
81
|
+
this.reserved.delete(taskId);
|
|
82
|
+
// Record observed usage faithfully - do NOT clamp to hide overage.
|
|
83
|
+
this.reconciled.push({ ...actual });
|
|
84
|
+
// Record violations: observed exceeded an enforced ceiling.
|
|
85
|
+
if (actual.modelRequests > this.limits.maxModelRequestsPerTask) {
|
|
86
|
+
this.violations.push({
|
|
87
|
+
taskId,
|
|
88
|
+
limit: 'maxModelRequestsPerTask',
|
|
89
|
+
observed: actual.modelRequests,
|
|
90
|
+
enforced: this.limits.maxModelRequestsPerTask,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (actual.toolCalls > this.limits.maxToolCallsPerTask) {
|
|
94
|
+
this.violations.push({
|
|
95
|
+
taskId,
|
|
96
|
+
limit: 'maxToolCallsPerTask',
|
|
97
|
+
observed: actual.toolCalls,
|
|
98
|
+
enforced: this.limits.maxToolCallsPerTask,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (actual.durationMs > this.limits.timeoutMs) {
|
|
102
|
+
this.violations.push({
|
|
103
|
+
taskId,
|
|
104
|
+
limit: 'timeoutMs',
|
|
105
|
+
observed: actual.durationMs,
|
|
106
|
+
enforced: this.limits.timeoutMs,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return this.aggregateUsedModelRequests() <= this.limits.maxModelRequestsPerTurn;
|
|
110
|
+
}
|
|
111
|
+
availableModelRequests() {
|
|
112
|
+
return Math.max(0, this.limits.maxModelRequestsPerTurn - this.aggregateReservedOrUsed());
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Whether `count` new tasks can each reserve at least one model request.
|
|
116
|
+
* NOTE: this checks the minimum (1 request per task), not the full
|
|
117
|
+
* per-task cap. The supervisor's reserve loop (supervisor.ts:158-179)
|
|
118
|
+
* handles per-task reserve amounts individually.
|
|
119
|
+
*/
|
|
120
|
+
canReserveBatch(count) {
|
|
121
|
+
return this.availableModelRequests() >= count;
|
|
122
|
+
}
|
|
123
|
+
snapshot() {
|
|
124
|
+
const used = (0, types_1.sumSubtaskUsage)(this.reconciled);
|
|
125
|
+
const reservedModelRequests = (0, types_1.sumSubtaskUsage)(Array.from(this.reserved.entries()).map(([, n]) => ({ ...types_1.EMPTY_SUBTASK_USAGE, modelRequests: n }))).modelRequests;
|
|
126
|
+
const availableModelRequests = this.availableModelRequests();
|
|
127
|
+
return {
|
|
128
|
+
reservedModelRequests,
|
|
129
|
+
used,
|
|
130
|
+
availableModelRequests,
|
|
131
|
+
exhausted: this.aggregateUsedModelRequests() > this.limits.maxModelRequestsPerTurn,
|
|
132
|
+
violations: [...this.violations],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** Reconciled aggregate usage across all completed children. */
|
|
136
|
+
aggregateUsage() {
|
|
137
|
+
return (0, types_1.sumSubtaskUsage)(this.reconciled);
|
|
138
|
+
}
|
|
139
|
+
/** Number of tasks that have been reconciled (completed/failed/cancelled). */
|
|
140
|
+
reconciledTaskCount() {
|
|
141
|
+
return this.reconciled.length;
|
|
142
|
+
}
|
|
143
|
+
/** Recorded overage violations (observed exceeded enforced ceiling). */
|
|
144
|
+
violationsList() {
|
|
145
|
+
return [...this.violations];
|
|
146
|
+
}
|
|
147
|
+
/** True if no reservations are outstanding and no usage has been recorded. */
|
|
148
|
+
isClean() {
|
|
149
|
+
return this.reserved.size === 0 && this.reconciled.length === 0;
|
|
150
|
+
}
|
|
151
|
+
aggregateReservedOrUsed() {
|
|
152
|
+
let total = 0;
|
|
153
|
+
for (const n of this.reserved.values())
|
|
154
|
+
total += n;
|
|
155
|
+
for (const u of this.reconciled)
|
|
156
|
+
total += u.modelRequests;
|
|
157
|
+
return total;
|
|
158
|
+
}
|
|
159
|
+
aggregateUsedModelRequests() {
|
|
160
|
+
return this.reconciled.reduce((acc, u) => acc + u.modelRequests, 0);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.SubagentBudgetLedger = SubagentBudgetLedger;
|
|
164
|
+
/** Build limits from a SubagentConfig. */
|
|
165
|
+
function budgetLimitsFromConfig(config) {
|
|
166
|
+
return {
|
|
167
|
+
maxModelRequestsPerTurn: config.maxModelRequestsPerTurn,
|
|
168
|
+
maxModelRequestsPerTask: config.maxModelRequestsPerTask,
|
|
169
|
+
maxToolCallsPerTask: config.maxToolCallsPerTask,
|
|
170
|
+
timeoutMs: config.timeoutMs,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../../src/runtime/subagents/budget.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChildToolExecutorGuard: enforces project-root and packet-scope isolation.
|
|
3
|
+
*
|
|
4
|
+
* R3 (v0.2.20): the policy only canonicalizes scope.paths into the child
|
|
5
|
+
* prompt, but the actual tool arguments (read_file path, glob base, grep
|
|
6
|
+
* path, batch_read nested args) were not validated. A child could read
|
|
7
|
+
* absolute paths, `../` escapes, outside-scope files, or symlink targets
|
|
8
|
+
* pointing outside the project.
|
|
9
|
+
*
|
|
10
|
+
* This guard wraps the child tool executor and performs a realpath-based
|
|
11
|
+
* containment check on every path-bearing argument before delegating to
|
|
12
|
+
* the real executor.
|
|
13
|
+
*
|
|
14
|
+
* Two containment boundaries:
|
|
15
|
+
* 1. Canonical project root (always enforced).
|
|
16
|
+
* 2. Packet scope paths (enforced when the packet specifies a non-empty
|
|
17
|
+
* scope). The path must be inside the root AND inside at least one
|
|
18
|
+
* scope realpath.
|
|
19
|
+
*/
|
|
20
|
+
export interface GuardOptions {
|
|
21
|
+
/** Canonical project root (first containment boundary). */
|
|
22
|
+
rootCwd: string;
|
|
23
|
+
/** Canonical scope paths (second, stricter boundary). Empty = root only. */
|
|
24
|
+
scopePaths?: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
export interface GuardRejection {
|
|
27
|
+
ok: false;
|
|
28
|
+
tool: string;
|
|
29
|
+
reason: string;
|
|
30
|
+
path?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface GuardApproval {
|
|
33
|
+
ok: true;
|
|
34
|
+
}
|
|
35
|
+
export type GuardVerdict = GuardApproval | GuardRejection;
|
|
36
|
+
/**
|
|
37
|
+
* Evaluate whether a tool call is allowed under the guard's boundaries.
|
|
38
|
+
* Pure (modulo realpath reads) so it can be tested in isolation.
|
|
39
|
+
*/
|
|
40
|
+
export declare function evaluateToolCall(tool: string, args: Record<string, unknown>, options: GuardOptions): GuardVerdict;
|
|
41
|
+
/**
|
|
42
|
+
* A mutable scope holder: the supervisor sets the current packet's scope
|
|
43
|
+
* before running it, so the turn-level guard can enforce per-packet scope
|
|
44
|
+
* containment without rebuilding the executor per packet.
|
|
45
|
+
*/
|
|
46
|
+
export declare class ScopeHolder {
|
|
47
|
+
private current;
|
|
48
|
+
setScope(paths: readonly string[]): void;
|
|
49
|
+
clear(): void;
|
|
50
|
+
getScope(): readonly string[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Wrap a child tool executor with containment enforcement. The returned
|
|
54
|
+
* executor delegates to `inner` only when all path-bearing args are inside
|
|
55
|
+
* the project root (and inside the packet scope, if the scope holder is set).
|
|
56
|
+
*/
|
|
57
|
+
export declare function createChildToolExecutorGuard(inner: (name: string, args: Record<string, unknown>, abortSignal?: AbortSignal) => Promise<string>, options: GuardOptions & {
|
|
58
|
+
scopeHolder?: ScopeHolder;
|
|
59
|
+
}): (name: string, args: Record<string, unknown>, abortSignal?: AbortSignal) => Promise<string>;
|
|
60
|
+
//# sourceMappingURL=child-executor-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-executor-guard.d.ts","sourceRoot":"","sources":["../../../src/runtime/subagents/child-executor-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAiBH,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,KAAK,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,IAAI,CAAC;CACV;AAED,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,cAAc,CAAC;AA+I1D;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,YAAY,GACpB,YAAY,CAkBd;AAED;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAyB;IAExC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAIxC,KAAK,IAAI,IAAI;IAIb,QAAQ,IAAI,SAAS,MAAM,EAAE;CAG9B;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,CACL,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,WAAW,CAAC,EAAE,WAAW,KACtB,OAAO,CAAC,MAAM,CAAC,EACpB,OAAO,EAAE,YAAY,GAAG;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GACpD,CACD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,WAAW,CAAC,EAAE,WAAW,KACtB,OAAO,CAAC,MAAM,CAAC,CAgBnB"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ChildToolExecutorGuard: enforces project-root and packet-scope isolation.
|
|
4
|
+
*
|
|
5
|
+
* R3 (v0.2.20): the policy only canonicalizes scope.paths into the child
|
|
6
|
+
* prompt, but the actual tool arguments (read_file path, glob base, grep
|
|
7
|
+
* path, batch_read nested args) were not validated. A child could read
|
|
8
|
+
* absolute paths, `../` escapes, outside-scope files, or symlink targets
|
|
9
|
+
* pointing outside the project.
|
|
10
|
+
*
|
|
11
|
+
* This guard wraps the child tool executor and performs a realpath-based
|
|
12
|
+
* containment check on every path-bearing argument before delegating to
|
|
13
|
+
* the real executor.
|
|
14
|
+
*
|
|
15
|
+
* Two containment boundaries:
|
|
16
|
+
* 1. Canonical project root (always enforced).
|
|
17
|
+
* 2. Packet scope paths (enforced when the packet specifies a non-empty
|
|
18
|
+
* scope). The path must be inside the root AND inside at least one
|
|
19
|
+
* scope realpath.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.ScopeHolder = void 0;
|
|
23
|
+
exports.evaluateToolCall = evaluateToolCall;
|
|
24
|
+
exports.createChildToolExecutorGuard = createChildToolExecutorGuard;
|
|
25
|
+
const path_1 = require("path");
|
|
26
|
+
const fs_1 = require("fs");
|
|
27
|
+
/** Tools whose arguments carry a single primary path under key `path`. */
|
|
28
|
+
const PATH_TOOLS = new Set(['read_file', 'list_files']);
|
|
29
|
+
/** Tools whose arguments carry a base/glob root under `path`. */
|
|
30
|
+
const BASE_PATH_TOOLS = new Set(['glob']);
|
|
31
|
+
/** Tools whose arguments carry a search base under `path`. */
|
|
32
|
+
const SEARCH_PATH_TOOLS = new Set(['grep']);
|
|
33
|
+
/** batch_read nests step args; each step has { tool, args }. */
|
|
34
|
+
const BATCH_TOOL = 'batch_read';
|
|
35
|
+
/**
|
|
36
|
+
* Return the realpath of the nearest existing ancestor of `p`.
|
|
37
|
+
*
|
|
38
|
+
* This handles not-yet-created paths (the target doesn't exist, but its
|
|
39
|
+
* parent dir does) and symlinked parent directories: we walk up until we
|
|
40
|
+
* find a path that exists, then resolve its realpath. Symlink escapes in
|
|
41
|
+
* an existing ancestor are caught because realpath resolves them.
|
|
42
|
+
*/
|
|
43
|
+
function nearestExistingAncestorRealpath(p) {
|
|
44
|
+
let current = p;
|
|
45
|
+
for (let i = 0; i < 64; i++) {
|
|
46
|
+
if ((0, fs_1.existsSync)(current)) {
|
|
47
|
+
try {
|
|
48
|
+
return (0, fs_1.realpathSync)(current);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
// Distinguish ENOENT (path disappeared between existsSync and realpathSync)
|
|
52
|
+
// from permission/I/O errors. ENOENT: continue walking up. Others: fail.
|
|
53
|
+
const code = err?.code;
|
|
54
|
+
if (code === 'ENOENT') {
|
|
55
|
+
// Path vanished between existsSync and realpathSync (TOCTOU).
|
|
56
|
+
// Continue walking up to find an existing ancestor.
|
|
57
|
+
const parent = (0, path_1.resolve)(current, '..');
|
|
58
|
+
if (parent === current)
|
|
59
|
+
return undefined;
|
|
60
|
+
current = parent;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
// EACCES, EIO, etc: cannot resolve realpath — treat as unresolvable.
|
|
64
|
+
// Returning undefined signals to the caller that containment cannot be
|
|
65
|
+
// verified, and the path should be rejected.
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const parent = (0, path_1.resolve)(current, '..');
|
|
70
|
+
if (parent === current)
|
|
71
|
+
return undefined; // filesystem root, no existing ancestor
|
|
72
|
+
current = parent;
|
|
73
|
+
}
|
|
74
|
+
return undefined; // loop exhausted, no existing ancestor found
|
|
75
|
+
}
|
|
76
|
+
/** True if `candidate` is `ancestor` or inside it (both realpaths). */
|
|
77
|
+
function isInsideOrEqual(candidate, ancestor) {
|
|
78
|
+
if (candidate === ancestor)
|
|
79
|
+
return true;
|
|
80
|
+
const rel = (0, path_1.relative)(ancestor, candidate);
|
|
81
|
+
return rel !== '' && !rel.startsWith('..') && !(0, path_1.isAbsolute)(rel);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check that a path stays inside root (and inside a scope if scopes given).
|
|
85
|
+
*
|
|
86
|
+
* Strategy: resolve the path against root, then take the realpath of its
|
|
87
|
+
* nearest existing ancestor. If that ancestor is outside root, the path
|
|
88
|
+
* escapes (via `..`, absolute outside root, or symlinked parent). If scopes
|
|
89
|
+
* are specified, the ancestor must also be inside a scope OR the path must
|
|
90
|
+
* descend into a scope from the root (ancestor is root itself, remaining
|
|
91
|
+
* suffix enters a scope).
|
|
92
|
+
*/
|
|
93
|
+
function checkContainment(rawPath, rootReal, scopeReals) {
|
|
94
|
+
if (typeof rawPath !== 'string' || rawPath.trim() === '') {
|
|
95
|
+
return { contained: false, reason: 'empty path' };
|
|
96
|
+
}
|
|
97
|
+
const resolved = (0, path_1.resolve)(rootReal, rawPath);
|
|
98
|
+
const ancestorReal = nearestExistingAncestorRealpath(resolved);
|
|
99
|
+
// If no existing ancestor could be resolved (e.g. EACCES on realpathSync),
|
|
100
|
+
// containment cannot be verified — reject the path.
|
|
101
|
+
if (ancestorReal === undefined) {
|
|
102
|
+
return { contained: false, reason: `cannot verify path containment: ${rawPath}` };
|
|
103
|
+
}
|
|
104
|
+
// Boundary 1: must be inside root.
|
|
105
|
+
if (!isInsideOrEqual(ancestorReal, rootReal)) {
|
|
106
|
+
return { contained: false, reason: `path escapes project root: ${rawPath}` };
|
|
107
|
+
}
|
|
108
|
+
// Boundary 2: if scopes specified, the target must be inside a scope.
|
|
109
|
+
if (scopeReals.length > 0) {
|
|
110
|
+
// If the ancestor is already inside a scope, ok.
|
|
111
|
+
const ancestorInScope = scopeReals.some(s => isInsideOrEqual(ancestorReal, s));
|
|
112
|
+
if (!ancestorInScope) {
|
|
113
|
+
// Ancestor is root (or above scope) but target may descend into a
|
|
114
|
+
// scope. Re-resolve the full target's nearest-existing-ancestor
|
|
115
|
+
// against each scope: the resolved path relative to root must, when
|
|
116
|
+
// joined, fall inside a scope realpath.
|
|
117
|
+
const targetInScope = scopeReals.some(s => {
|
|
118
|
+
// Compute where the target would resolve to relative to root, then
|
|
119
|
+
// check containment against the scope realpath.
|
|
120
|
+
const targetResolved = (0, path_1.resolve)(rootReal, rawPath);
|
|
121
|
+
const targetAncestor = nearestExistingAncestorRealpath(targetResolved);
|
|
122
|
+
return targetAncestor !== undefined && isInsideOrEqual(targetAncestor, s);
|
|
123
|
+
});
|
|
124
|
+
if (!targetInScope) {
|
|
125
|
+
return { contained: false, reason: `path outside packet scope: ${rawPath}` };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return { contained: true };
|
|
130
|
+
}
|
|
131
|
+
/** Extract path-bearing arguments from a tool call. */
|
|
132
|
+
function extractPathArgs(tool, args) {
|
|
133
|
+
const paths = [];
|
|
134
|
+
if (PATH_TOOLS.has(tool) ||
|
|
135
|
+
BASE_PATH_TOOLS.has(tool) ||
|
|
136
|
+
SEARCH_PATH_TOOLS.has(tool)) {
|
|
137
|
+
const p = args.path;
|
|
138
|
+
if (typeof p === 'string') {
|
|
139
|
+
paths.push(p);
|
|
140
|
+
}
|
|
141
|
+
// glob/grep with no path default to cwd (inside root) - no check needed.
|
|
142
|
+
}
|
|
143
|
+
if (tool === BATCH_TOOL) {
|
|
144
|
+
const steps = args.steps;
|
|
145
|
+
if (Array.isArray(steps)) {
|
|
146
|
+
for (const step of steps) {
|
|
147
|
+
if (step && typeof step === 'object' && typeof step.tool === 'string') {
|
|
148
|
+
const stepArgs = step.args && typeof step.args === 'object'
|
|
149
|
+
? step.args
|
|
150
|
+
: {};
|
|
151
|
+
paths.push(...extractPathArgs(step.tool, stepArgs));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return paths;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Evaluate whether a tool call is allowed under the guard's boundaries.
|
|
160
|
+
* Pure (modulo realpath reads) so it can be tested in isolation.
|
|
161
|
+
*/
|
|
162
|
+
function evaluateToolCall(tool, args, options) {
|
|
163
|
+
const rootReal = nearestExistingAncestorRealpath(options.rootCwd);
|
|
164
|
+
if (rootReal === undefined) {
|
|
165
|
+
return { ok: false, tool, reason: 'cannot resolve project root realpath' };
|
|
166
|
+
}
|
|
167
|
+
const scopeReals = (options.scopePaths ?? []).map(p => nearestExistingAncestorRealpath((0, path_1.resolve)(rootReal, p))).filter((s) => s !== undefined);
|
|
168
|
+
const pathArgs = extractPathArgs(tool, args);
|
|
169
|
+
for (const path of pathArgs) {
|
|
170
|
+
const verdict = checkContainment(path, rootReal, scopeReals);
|
|
171
|
+
if (!verdict.contained) {
|
|
172
|
+
return { ok: false, tool, reason: verdict.reason ?? 'path rejected', path };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return { ok: true };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* A mutable scope holder: the supervisor sets the current packet's scope
|
|
179
|
+
* before running it, so the turn-level guard can enforce per-packet scope
|
|
180
|
+
* containment without rebuilding the executor per packet.
|
|
181
|
+
*/
|
|
182
|
+
class ScopeHolder {
|
|
183
|
+
constructor() {
|
|
184
|
+
this.current = [];
|
|
185
|
+
}
|
|
186
|
+
setScope(paths) {
|
|
187
|
+
this.current = paths;
|
|
188
|
+
}
|
|
189
|
+
clear() {
|
|
190
|
+
this.current = [];
|
|
191
|
+
}
|
|
192
|
+
getScope() {
|
|
193
|
+
return this.current;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.ScopeHolder = ScopeHolder;
|
|
197
|
+
/**
|
|
198
|
+
* Wrap a child tool executor with containment enforcement. The returned
|
|
199
|
+
* executor delegates to `inner` only when all path-bearing args are inside
|
|
200
|
+
* the project root (and inside the packet scope, if the scope holder is set).
|
|
201
|
+
*/
|
|
202
|
+
function createChildToolExecutorGuard(inner, options) {
|
|
203
|
+
return async (name, args, abortSignal) => {
|
|
204
|
+
const scopePaths = options.scopeHolder?.getScope() ?? options.scopePaths ?? [];
|
|
205
|
+
const verdict = evaluateToolCall(name, args, {
|
|
206
|
+
rootCwd: options.rootCwd,
|
|
207
|
+
scopePaths,
|
|
208
|
+
});
|
|
209
|
+
if (!verdict.ok) {
|
|
210
|
+
return JSON.stringify({
|
|
211
|
+
success: false,
|
|
212
|
+
output: '',
|
|
213
|
+
error: `Subagent scope guard rejected ${verdict.tool}: ${verdict.reason}`,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return inner(name, args, abortSignal);
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=child-executor-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-executor-guard.js","sourceRoot":"","sources":["../../../src/runtime/subagents/child-executor-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubagentContextBuilder: assembles the independent child message context.
|
|
3
|
+
*
|
|
4
|
+
* A child does NOT inherit the parent's full transcript. It receives a role
|
|
5
|
+
* system prompt, a read-only summary of the root objective, and the specific
|
|
6
|
+
* task packet with canonical scope. Optional capsule/evidence are injected only
|
|
7
|
+
* when available, kept compact to avoid polluting the child context.
|
|
8
|
+
*/
|
|
9
|
+
import type { Message } from '../../services/llm';
|
|
10
|
+
import type { ContextCapsule } from '../../harness/types';
|
|
11
|
+
import type { SubtaskPacket } from './types';
|
|
12
|
+
export interface ChildContextInputs {
|
|
13
|
+
/** Canonical project root the child operates in. */
|
|
14
|
+
cwd: string;
|
|
15
|
+
/** The task packet (objective, scope, expectedOutput, hints). */
|
|
16
|
+
packet: SubtaskPacket;
|
|
17
|
+
/** Canonical scope paths already validated by policy. */
|
|
18
|
+
canonicalScopePaths?: string[];
|
|
19
|
+
/** Read-only summary of the root objective; never the full parent transcript. */
|
|
20
|
+
rootObjectiveSummary?: string;
|
|
21
|
+
/** Parent harness capsule, compacted to its salient fields. */
|
|
22
|
+
capsule?: ContextCapsule;
|
|
23
|
+
/** Model/provider info shown to the child so it understands its limits. */
|
|
24
|
+
modelLabel?: string;
|
|
25
|
+
/** Active project instructions / skill guidance (read-only). */
|
|
26
|
+
projectInstructions?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build the child message list. The first message is always the role system
|
|
30
|
+
* prompt; a single user message frames the task. The child loop appends its
|
|
31
|
+
* own assistant/tool messages on top of this.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildChildMessages(inputs: ChildContextInputs): Message[];
|
|
34
|
+
//# sourceMappingURL=context-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../../src/runtime/subagents/context-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,MAAM,EAAE,aAAa,CAAC;IACtB,yDAAyD;IACzD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,EAAE,CAwDxE"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SubagentContextBuilder: assembles the independent child message context.
|
|
4
|
+
*
|
|
5
|
+
* A child does NOT inherit the parent's full transcript. It receives a role
|
|
6
|
+
* system prompt, a read-only summary of the root objective, and the specific
|
|
7
|
+
* task packet with canonical scope. Optional capsule/evidence are injected only
|
|
8
|
+
* when available, kept compact to avoid polluting the child context.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.buildChildMessages = buildChildMessages;
|
|
12
|
+
const presets_1 = require("./presets");
|
|
13
|
+
/**
|
|
14
|
+
* Build the child message list. The first message is always the role system
|
|
15
|
+
* prompt; a single user message frames the task. The child loop appends its
|
|
16
|
+
* own assistant/tool messages on top of this.
|
|
17
|
+
*/
|
|
18
|
+
function buildChildMessages(inputs) {
|
|
19
|
+
const { packet, cwd } = inputs;
|
|
20
|
+
const systemPrompt = assembleSystemPrompt(inputs);
|
|
21
|
+
const userPrompt = assembleUserPrompt(inputs);
|
|
22
|
+
return [
|
|
23
|
+
{ role: 'system', content: systemPrompt },
|
|
24
|
+
{ role: 'user', content: userPrompt },
|
|
25
|
+
];
|
|
26
|
+
function assembleSystemPrompt(i) {
|
|
27
|
+
const rolePrompt = (0, presets_1.systemPromptForRole)(packet.role);
|
|
28
|
+
const lines = [rolePrompt, ''];
|
|
29
|
+
lines.push(`# Operating context`);
|
|
30
|
+
lines.push(`- Project root: ${cwd}`);
|
|
31
|
+
if (i.modelLabel)
|
|
32
|
+
lines.push(`- Model: ${i.modelLabel}`);
|
|
33
|
+
lines.push('- You are a child agent at delegation depth 1. You may NOT create further subagents.');
|
|
34
|
+
lines.push('- You may NOT edit, write, delete, commit, push, publish, install, or run shell commands.');
|
|
35
|
+
if (i.rootObjectiveSummary) {
|
|
36
|
+
lines.push('');
|
|
37
|
+
lines.push(`# Root objective (read-only summary)`);
|
|
38
|
+
lines.push(truncate(i.rootObjectiveSummary, 800));
|
|
39
|
+
}
|
|
40
|
+
if (i.projectInstructions) {
|
|
41
|
+
lines.push('');
|
|
42
|
+
lines.push(`# Project instructions (read-only)`);
|
|
43
|
+
lines.push(truncate(i.projectInstructions, 1200));
|
|
44
|
+
}
|
|
45
|
+
if (i.capsule) {
|
|
46
|
+
lines.push('');
|
|
47
|
+
lines.push(`# Parent context capsule (read-only)`);
|
|
48
|
+
lines.push(compactCapsule(i.capsule));
|
|
49
|
+
}
|
|
50
|
+
return lines.join('\n');
|
|
51
|
+
}
|
|
52
|
+
function assembleUserPrompt(i) {
|
|
53
|
+
const lines = [];
|
|
54
|
+
lines.push(`## Task`);
|
|
55
|
+
lines.push(`role: ${packet.role}`);
|
|
56
|
+
lines.push(`objective: ${packet.objective}`);
|
|
57
|
+
if (packet.reason)
|
|
58
|
+
lines.push(`reason: ${packet.reason}`);
|
|
59
|
+
if (i.canonicalScopePaths && i.canonicalScopePaths.length > 0) {
|
|
60
|
+
lines.push(`scope: ${i.canonicalScopePaths.join(', ')}`);
|
|
61
|
+
}
|
|
62
|
+
if (packet.contextHints && packet.contextHints.length > 0) {
|
|
63
|
+
lines.push(`hints:`);
|
|
64
|
+
for (const hint of packet.contextHints)
|
|
65
|
+
lines.push(` - ${hint}`);
|
|
66
|
+
}
|
|
67
|
+
if (packet.expectedOutput) {
|
|
68
|
+
lines.push(`expected output: ${packet.expectedOutput}`);
|
|
69
|
+
}
|
|
70
|
+
lines.push('');
|
|
71
|
+
lines.push('Investigate now using only the read-only tools available to you, then emit the JSON result object as specified in your system prompt.');
|
|
72
|
+
return lines.join('\n');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function compactCapsule(capsule) {
|
|
76
|
+
const lines = [];
|
|
77
|
+
if (capsule.contract?.objective)
|
|
78
|
+
lines.push(`- contract objective: ${truncate(capsule.contract.objective, 200)}`);
|
|
79
|
+
if (capsule.completed.length > 0)
|
|
80
|
+
lines.push(`- completed: ${truncate(capsule.completed.join('; '), 300)}`);
|
|
81
|
+
if (capsule.openTodos.length > 0)
|
|
82
|
+
lines.push(`- open todos: ${truncate(capsule.openTodos.join('; '), 300)}`);
|
|
83
|
+
if (capsule.changedFiles.length > 0)
|
|
84
|
+
lines.push(`- changed files: ${truncate(capsule.changedFiles.join(', '), 300)}`);
|
|
85
|
+
if (capsule.keyFacts.length > 0) {
|
|
86
|
+
lines.push(`- key facts:`);
|
|
87
|
+
for (const fact of capsule.keyFacts.slice(0, 5))
|
|
88
|
+
lines.push(` - ${truncate(fact.content, 160)}`);
|
|
89
|
+
}
|
|
90
|
+
if (capsule.nextAction)
|
|
91
|
+
lines.push(`- next action: ${truncate(capsule.nextAction, 200)}`);
|
|
92
|
+
return lines.length > 0 ? lines.join('\n') : '(no capsule fields)';
|
|
93
|
+
}
|
|
94
|
+
function truncate(text, max) {
|
|
95
|
+
if (text.length <= max)
|
|
96
|
+
return text;
|
|
97
|
+
return `${text.slice(0, max - 1)}…`;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=context-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../../../src/runtime/subagents/context-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent runtime public surface.
|
|
3
|
+
*
|
|
4
|
+
* v0.2.20 exposes a read-only subagent runtime. The root Agent may request
|
|
5
|
+
* 1-3 independent investigation packets; a Supervisor runs them as isolated
|
|
6
|
+
* child agents under a unified budget, permission boundary and trace.
|
|
7
|
+
*/
|
|
8
|
+
export * from './types';
|
|
9
|
+
export * from './presets';
|
|
10
|
+
export { evaluateSubtaskPolicy, canonicalizeScopePaths, hasExplicitDelegationIntent, clampSubagentConfig, type PolicyContext, type PolicyVerdict, type PolicyRejectReason, } from './policy';
|
|
11
|
+
export { SubagentBudgetLedger, TurnTaskState, budgetLimitsFromConfig, type SubagentBudgetLimits, type ReservedBudget, type BudgetSnapshot, type BudgetViolation, } from './budget';
|
|
12
|
+
export { buildChildMessages, type ChildContextInputs } from './context-builder';
|
|
13
|
+
export { parseSubtaskResult, extractJsonObject, type ParsedSubtaskPayload } from './result-parser';
|
|
14
|
+
export { createChildToolExecutorGuard, evaluateToolCall, ScopeHolder, type GuardOptions, type GuardVerdict, } from './child-executor-guard';
|
|
15
|
+
export { runSubtask, type SubagentRunnerDeps, type ChildToolSet, type ExecuteChildQuery, type RunSubtaskOutcome, } from './runner';
|
|
16
|
+
export { SubagentProviderGate, type ProviderGateOptions, } from './provider-gate';
|
|
17
|
+
export { runSubtaskBatch, type SubagentSupervisorDeps, type RunBatchOutcome, } from './supervisor';
|
|
18
|
+
export { createSubtaskTool, coerceSubtaskRequest, summarizeBatchForModel, } from './tool';
|
|
19
|
+
export { createProductionExecuteQuery, createChildLlmConfig, type SubagentLlmFactoryDeps, } from './production';
|
|
20
|
+
export { createSubagentToolForTurn, createSubagentBundleForTurn, deriveRootLlmConfig, type SubagentTurnInputs, type SubagentTurnBundle, } from './runtime-integration';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/subagents/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,2BAA2B,EAC3B,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACnG,OAAO,EACL,4BAA4B,EAC5B,gBAAgB,EAChB,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,UAAU,EACV,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,oBAAoB,EACpB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,uBAAuB,CAAC"}
|