@astralyn/pi 0.84.4 → 0.84.6
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/CHANGELOG.md +57 -0
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-command.d.ts.map +1 -1
- package/dist/cli/auth-command.js +5 -4
- package/dist/cli/auth-command.js.map +1 -1
- package/dist/core/agent-session.d.ts +6 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +11 -6
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/experimental.d.ts +4 -0
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +4 -0
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +10 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +19 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +29 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +4 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +5 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +1 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +2 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +4 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/project-trust.js +2 -2
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/sdk.d.ts +5 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +2 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.js +2 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +12 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +7 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +4 -2
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +2 -0
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -0
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -0
- package/dist/core/tools/write.js.map +1 -1
- package/dist/extensions/background/index.d.ts +149 -0
- package/dist/extensions/background/index.d.ts.map +1 -0
- package/dist/extensions/background/index.js +666 -0
- package/dist/extensions/background/index.js.map +1 -0
- package/dist/extensions/background/manager.d.ts +95 -0
- package/dist/extensions/background/manager.d.ts.map +1 -0
- package/dist/extensions/background/manager.js +421 -0
- package/dist/extensions/background/manager.js.map +1 -0
- package/dist/extensions/background/registry.d.ts +220 -0
- package/dist/extensions/background/registry.d.ts.map +1 -0
- package/dist/extensions/background/registry.js +589 -0
- package/dist/extensions/background/registry.js.map +1 -0
- package/dist/extensions/background/render.d.ts +50 -0
- package/dist/extensions/background/render.d.ts.map +1 -0
- package/dist/extensions/background/render.js +260 -0
- package/dist/extensions/background/render.js.map +1 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +2 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts +3 -6
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +9 -93
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
- package/dist/extensions/subagent/agents-command.js +270 -169
- package/dist/extensions/subagent/agents-command.js.map +1 -1
- package/dist/extensions/subagent/agents.d.ts +5 -6
- package/dist/extensions/subagent/agents.d.ts.map +1 -1
- package/dist/extensions/subagent/agents.js +28 -192
- package/dist/extensions/subagent/agents.js.map +1 -1
- package/dist/extensions/subagent/budget.d.ts +15 -0
- package/dist/extensions/subagent/budget.d.ts.map +1 -0
- package/dist/extensions/subagent/budget.js +96 -0
- package/dist/extensions/subagent/budget.js.map +1 -0
- package/dist/extensions/subagent/cancellation.d.ts +29 -0
- package/dist/extensions/subagent/cancellation.d.ts.map +1 -0
- package/dist/extensions/subagent/cancellation.js +73 -0
- package/dist/extensions/subagent/cancellation.js.map +1 -0
- package/dist/extensions/subagent/constants.d.ts +4 -5
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +11 -7
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts +0 -3
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +59 -208
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/model-selection.d.ts +16 -0
- package/dist/extensions/subagent/model-selection.d.ts.map +1 -0
- package/dist/extensions/subagent/model-selection.js +51 -0
- package/dist/extensions/subagent/model-selection.js.map +1 -0
- package/dist/extensions/subagent/render.d.ts +7 -2
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +219 -576
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts +2 -2
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +24 -35
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +4 -6
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +101 -316
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/schema.d.ts +4 -10
- package/dist/extensions/subagent/schema.d.ts.map +1 -1
- package/dist/extensions/subagent/schema.js +8 -13
- package/dist/extensions/subagent/schema.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts +13 -11
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +169 -161
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/settings.d.ts +2 -2
- package/dist/extensions/subagent/settings.d.ts.map +1 -1
- package/dist/extensions/subagent/settings.js +27 -14
- package/dist/extensions/subagent/settings.js.map +1 -1
- package/dist/extensions/subagent/state.d.ts +89 -0
- package/dist/extensions/subagent/state.d.ts.map +1 -0
- package/dist/extensions/subagent/state.js +294 -0
- package/dist/extensions/subagent/state.js.map +1 -0
- package/dist/extensions/subagent/text.d.ts +7 -0
- package/dist/extensions/subagent/text.d.ts.map +1 -0
- package/dist/extensions/subagent/text.js +91 -0
- package/dist/extensions/subagent/text.js.map +1 -0
- package/dist/extensions/subagent/types.d.ts +16 -43
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/subagent/ui/choices.d.ts +36 -0
- package/dist/extensions/subagent/ui/choices.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/choices.js +54 -0
- package/dist/extensions/subagent/ui/choices.js.map +1 -0
- package/dist/extensions/subagent/ui/model-list.d.ts +4 -3
- package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
- package/dist/extensions/subagent/ui/model-list.js +20 -22
- package/dist/extensions/subagent/ui/model-list.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +5 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +2 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +8 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +77 -25
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.js +36 -0
- package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
- package/dist/modes/interactive/theme/dark.json +2 -0
- package/dist/modes/interactive/theme/light.json +2 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +23 -10
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +9 -1
- package/dist/modes/interactive/theme/theme.d.ts +5 -3
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +12 -2
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +4 -1
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +5 -2
- package/dist/modes/json-event.js.map +1 -1
- package/dist/package-manager-cli.js +1 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/server/create-harness.d.ts.map +1 -1
- package/dist/server/create-harness.js +2 -0
- package/dist/server/create-harness.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +10 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +14 -19
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/bundled/README.md +1 -0
- package/docs/bundled/extensions/background.md +99 -0
- package/docs/bundled/extensions/subagent.md +83 -71
- package/docs/compaction.md +6 -6
- package/docs/custom-provider.md +1 -1
- package/docs/docs.json +4 -0
- package/docs/environment-variables.md +8 -2
- package/docs/extensions.md +19 -2
- package/docs/json.md +6 -4
- package/docs/keybindings.md +9 -2
- package/docs/rpc.md +15 -4
- package/docs/sdk.md +9 -0
- package/docs/settings.md +31 -0
- package/docs/terminal-setup.md +23 -2
- package/docs/themes.md +24 -3
- package/docs/tui.md +2 -2
- package/docs/usage.md +4 -3
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +170 -221
- package/package.json +6 -6
- package/dist/extensions/subagent/display-name.d.ts +0 -6
- package/dist/extensions/subagent/display-name.d.ts.map +0 -1
- package/dist/extensions/subagent/display-name.js +0 -13
- package/dist/extensions/subagent/display-name.js.map +0 -1
- package/dist/extensions/subagent/retry.d.ts +0 -17
- package/dist/extensions/subagent/retry.d.ts.map +0 -1
- package/dist/extensions/subagent/retry.js +0 -41
- package/dist/extensions/subagent/retry.js.map +0 -1
- package/dist/extensions/subagent/ui/profile-editor.d.ts +0 -54
- package/dist/extensions/subagent/ui/profile-editor.d.ts.map +0 -1
- package/dist/extensions/subagent/ui/profile-editor.js +0 -154
- package/dist/extensions/subagent/ui/profile-editor.js.map +0 -1
- package/dist/extensions/subagent/ui/profile-picker.d.ts +0 -32
- package/dist/extensions/subagent/ui/profile-picker.d.ts.map +0 -1
- package/dist/extensions/subagent/ui/profile-picker.js +0 -149
- package/dist/extensions/subagent/ui/profile-picker.js.map +0 -1
- package/examples/extensions/subagent/README.md +0 -175
- package/examples/extensions/subagent/agents/planner.md +0 -37
- package/examples/extensions/subagent/agents/reviewer.md +0 -35
- package/examples/extensions/subagent/agents/scout.md +0 -50
- package/examples/extensions/subagent/agents/worker.md +0 -24
- package/examples/extensions/subagent/agents.ts +0 -126
- package/examples/extensions/subagent/index.ts +0 -1009
- package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/examples/extensions/subagent/prompts/implement.md +0 -10
- package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAKN,KAAK,iBAAiB,EACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAGlE,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EA6BjD,CAAC;AAIF,wBAAgB,uBAAuB,IAAI,MAAM,CAYhD"}
|
|
@@ -1,33 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const TOOL_DESCRIPTION_AGENT_LIST_LIMIT = 8_000;
|
|
10
|
-
const TOOL_DESCRIPTION_AGENT_SUMMARY_LIMIT = 480;
|
|
11
|
-
const BUILTIN_AGENTS = [
|
|
12
|
-
{
|
|
13
|
-
name: "general",
|
|
14
|
-
description: "Implementation agent for bounded coding tasks: edits, fixes, refactors, and verification in a scoped area. Use when the task changes files; use explorer for read-only questions",
|
|
15
|
-
uiDescription: "Implementation agent for bounded coding tasks: edits, fixes, refactors, and verification in a scoped area.",
|
|
16
|
-
tools: [...DEFAULT_AGENT_TOOLS],
|
|
17
|
-
systemPrompt: [
|
|
18
|
-
"Work independently on the delegated task from start to finish.",
|
|
19
|
-
"Inspect relevant repository instructions before changing files.",
|
|
20
|
-
"Prefer editing existing files; never create documentation files unless the task explicitly asks for them.",
|
|
21
|
-
"Keep changes focused, run appropriate verification, and report exact paths, checks, blockers, and remaining risks.",
|
|
22
|
-
].join("\n"),
|
|
23
|
-
source: "builtin",
|
|
24
|
-
filePath: "<builtin:general>",
|
|
25
|
-
backend: "sdk",
|
|
26
|
-
},
|
|
1
|
+
import { DEFAULT_AGENT_TOOLS, EXPLORER_TOOLS, MAX_CONCURRENCY, MAX_TASKS, } from "./constants.js";
|
|
2
|
+
// Static display titles for the two built-in profiles; this file owns the
|
|
3
|
+
// model-facing copy, and renderers/commands share these labels.
|
|
4
|
+
export const AGENT_PROFILE_LABELS = {
|
|
5
|
+
explorer: "Explorer",
|
|
6
|
+
general: "General",
|
|
7
|
+
};
|
|
8
|
+
export const AGENT_PROFILES = [
|
|
27
9
|
{
|
|
28
10
|
name: "explorer",
|
|
29
11
|
description: 'Fast read-only agent for finding files, searching code, and answering codebase questions. Can inspect git history (log, blame, diff) via read-only bash. State thoroughness in the prompt: "quick" for a targeted lookup, "medium" for checking likely related locations, or "very thorough" for exhaustive sweeps across locations and naming conventions',
|
|
30
|
-
uiDescription: "Fast read-only agent for finding files, searching code, and answering codebase questions.",
|
|
31
12
|
tools: [...EXPLORER_TOOLS],
|
|
32
13
|
systemPrompt: [
|
|
33
14
|
"You are a fast read-only exploration agent; return findings as quickly as possible.",
|
|
@@ -38,178 +19,33 @@ const BUILTIN_AGENTS = [
|
|
|
38
19
|
"Match the depth the caller requested: quick targets the direct question, medium checks likely related locations, and very thorough sweeps multiple locations and naming conventions.",
|
|
39
20
|
"Return concise findings with precise paths, symbols, relationships, and unresolved uncertainties.",
|
|
40
21
|
].join("\n"),
|
|
41
|
-
source: "builtin",
|
|
42
|
-
filePath: "<builtin:explorer>",
|
|
43
|
-
backend: "sdk",
|
|
44
22
|
omitContextFiles: true,
|
|
45
23
|
},
|
|
24
|
+
{
|
|
25
|
+
name: "general",
|
|
26
|
+
description: "Implementation agent for bounded coding tasks: edits, fixes, refactors, and verification in a scoped area. Use when the task changes files; use explorer for read-only questions",
|
|
27
|
+
tools: [...DEFAULT_AGENT_TOOLS],
|
|
28
|
+
systemPrompt: [
|
|
29
|
+
"Work independently on the delegated task from start to finish.",
|
|
30
|
+
"Inspect relevant repository instructions before changing files.",
|
|
31
|
+
"Prefer editing existing files; never create documentation files unless the task explicitly asks for them.",
|
|
32
|
+
"Keep changes focused, run appropriate verification, and report exact paths, checks, blockers, and remaining risks.",
|
|
33
|
+
].join("\n"),
|
|
34
|
+
},
|
|
46
35
|
];
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function findNearestProjectAgentsDir(cwd) {
|
|
56
|
-
let current = cwd;
|
|
57
|
-
while (true) {
|
|
58
|
-
const candidate = join(current, CONFIG_DIR_NAME, "agents");
|
|
59
|
-
if (isDirectory(candidate))
|
|
60
|
-
return candidate;
|
|
61
|
-
const parent = dirname(current);
|
|
62
|
-
if (parent === current)
|
|
63
|
-
return undefined;
|
|
64
|
-
current = parent;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
function parseTools(raw, filePath) {
|
|
68
|
-
if (!raw?.trim())
|
|
69
|
-
return [...DEFAULT_AGENT_TOOLS];
|
|
70
|
-
const tools = [
|
|
71
|
-
...new Set(raw
|
|
72
|
-
.split(",")
|
|
73
|
-
.map((tool) => tool.trim())
|
|
74
|
-
.filter(Boolean)),
|
|
75
|
-
];
|
|
76
|
-
const unsupported = tools.filter((tool) => !BUILTIN_TOOL_SET.has(tool));
|
|
77
|
-
if (unsupported.length > 0) {
|
|
78
|
-
throw new Error(`Unsupported tool(s) ${unsupported.join(", ")} in ${filePath}.`);
|
|
79
|
-
}
|
|
80
|
-
return tools;
|
|
81
|
-
}
|
|
82
|
-
// Frontmatter model/thinking keys are intentionally ignored: agent files
|
|
83
|
-
// travel across machines (project repos), so a pinned model rarely exists
|
|
84
|
-
// in the reader's environment. Model and thinking come from /agents
|
|
85
|
-
// overrides or default to the parent session.
|
|
86
|
-
function parseAgentFile(filePath, source) {
|
|
87
|
-
const content = readFileSync(filePath, "utf8");
|
|
88
|
-
const { frontmatter, body } = parseFrontmatter(content);
|
|
89
|
-
const name = frontmatter.name?.trim() ?? "";
|
|
90
|
-
const description = frontmatter.description?.trim() ?? "";
|
|
91
|
-
if (!name)
|
|
92
|
-
throw new Error("Missing required frontmatter field: name.");
|
|
93
|
-
if (!AGENT_NAME_PATTERN.test(name)) {
|
|
94
|
-
throw new Error(`Agent name "${name}" must use lowercase letters, digits, hyphens, or underscores.`);
|
|
95
|
-
}
|
|
96
|
-
if (!description)
|
|
97
|
-
throw new Error("Missing required frontmatter field: description.");
|
|
98
|
-
if (!body.trim())
|
|
99
|
-
throw new Error("Agent prompt body must not be empty.");
|
|
100
|
-
const backend = frontmatter.backend?.trim();
|
|
101
|
-
if (backend && backend !== "sdk")
|
|
102
|
-
throw new Error(`Backend "${backend}" is not implemented; use "sdk".`);
|
|
103
|
-
return {
|
|
104
|
-
name,
|
|
105
|
-
description,
|
|
106
|
-
tools: parseTools(frontmatter.tools, filePath),
|
|
107
|
-
systemPrompt: body.trim(),
|
|
108
|
-
source,
|
|
109
|
-
filePath,
|
|
110
|
-
backend: "sdk",
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
function loadAgentDirectory(dir, source) {
|
|
114
|
-
if (!existsSync(dir))
|
|
115
|
-
return { agents: [], diagnostics: [] };
|
|
116
|
-
let entries;
|
|
117
|
-
try {
|
|
118
|
-
entries = readdirSync(dir, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
return {
|
|
122
|
-
agents: [],
|
|
123
|
-
diagnostics: [{ path: dir, source, message: error instanceof Error ? error.message : String(error) }],
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
const agents = [];
|
|
127
|
-
const diagnostics = [];
|
|
128
|
-
for (const entry of entries) {
|
|
129
|
-
if (!entry.name.endsWith(".md") || (!entry.isFile() && !entry.isSymbolicLink()))
|
|
130
|
-
continue;
|
|
131
|
-
const filePath = join(dir, entry.name);
|
|
132
|
-
try {
|
|
133
|
-
agents.push(parseAgentFile(filePath, source));
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
diagnostics.push({
|
|
137
|
-
path: filePath,
|
|
138
|
-
source,
|
|
139
|
-
message: error instanceof Error ? error.message : String(error),
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return { agents, diagnostics };
|
|
144
|
-
}
|
|
145
|
-
export function discoverAgents(cwd, options) {
|
|
146
|
-
const userDir = join(options.agentDir ?? getAgentDir(), "agents");
|
|
147
|
-
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
148
|
-
const user = loadAgentDirectory(userDir, "user");
|
|
149
|
-
const project = options.projectTrusted && projectAgentsDir
|
|
150
|
-
? loadAgentDirectory(projectAgentsDir, "project")
|
|
151
|
-
: { agents: [], diagnostics: [] };
|
|
152
|
-
const agents = new Map(BUILTIN_AGENTS.map((agent) => [agent.name, { ...agent, tools: [...agent.tools] }]));
|
|
153
|
-
for (const agent of user.agents)
|
|
154
|
-
agents.set(agent.name, agent);
|
|
155
|
-
for (const agent of project.agents)
|
|
156
|
-
agents.set(agent.name, agent);
|
|
157
|
-
return {
|
|
158
|
-
agents: [...agents.values()],
|
|
159
|
-
diagnostics: [...user.diagnostics, ...project.diagnostics],
|
|
160
|
-
projectAgentsDir,
|
|
161
|
-
projectAgentsTrusted: options.projectTrusted,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
export function subagentToolDescription(discovery) {
|
|
165
|
-
const agentLines = [];
|
|
166
|
-
let agentListLength = 0;
|
|
167
|
-
for (const [index, agent] of discovery.agents.entries()) {
|
|
168
|
-
const normalizedDescription = agent.description.replace(/\s+/gu, " ").trim();
|
|
169
|
-
const description = Buffer.byteLength(normalizedDescription, "utf8") <= TOOL_DESCRIPTION_AGENT_SUMMARY_LIMIT
|
|
170
|
-
? normalizedDescription
|
|
171
|
-
: `${utf8Prefix(normalizedDescription, TOOL_DESCRIPTION_AGENT_SUMMARY_LIMIT - Buffer.byteLength("…", "utf8"))}…`;
|
|
172
|
-
const defaultLabel = agent.name === "general" ? " (default)" : "";
|
|
173
|
-
const tools = agent.tools.length > 0 ? agent.tools.join(", ") : "none";
|
|
174
|
-
const line = `- ${agent.name}${defaultLabel}: ${description} (Tools: ${tools})`;
|
|
175
|
-
const lineLength = Buffer.byteLength(line, "utf8") + 1;
|
|
176
|
-
if (agentListLength + lineLength > TOOL_DESCRIPTION_AGENT_LIST_LIMIT) {
|
|
177
|
-
let omitted = discovery.agents.length - index;
|
|
178
|
-
let notice = `- ${omitted} additional profile${omitted === 1 ? "" : "s"} omitted from this bounded description; /agents lists every profile.`;
|
|
179
|
-
while (agentLines.length > 0 &&
|
|
180
|
-
agentListLength + Buffer.byteLength(notice, "utf8") + 1 > TOOL_DESCRIPTION_AGENT_LIST_LIMIT) {
|
|
181
|
-
const removed = agentLines.pop();
|
|
182
|
-
if (!removed)
|
|
183
|
-
break;
|
|
184
|
-
agentListLength -= Buffer.byteLength(removed, "utf8") + 1;
|
|
185
|
-
omitted++;
|
|
186
|
-
notice = `- ${omitted} additional profile${omitted === 1 ? "" : "s"} omitted from this bounded description; /agents lists every profile.`;
|
|
187
|
-
}
|
|
188
|
-
agentLines.push(notice);
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
agentLines.push(line);
|
|
192
|
-
agentListLength += lineLength;
|
|
193
|
-
}
|
|
36
|
+
// Static model-facing guidance: there are exactly two profiles and one
|
|
37
|
+
// tasks-array parameter shape, so the description never depends on discovery.
|
|
38
|
+
export function subagentToolDescription() {
|
|
194
39
|
return [
|
|
195
|
-
|
|
196
|
-
"",
|
|
197
|
-
"Available agent profiles:",
|
|
198
|
-
...agentLines,
|
|
40
|
+
"Delegate bounded work to isolated one-shot subagents. Workers cannot see the parent conversation: each task needs a complete self-contained briefing, and you receive only their final reports.",
|
|
199
41
|
"",
|
|
200
|
-
|
|
201
|
-
"- Read a known file directly with read, or search for a known symbol directly with grep.",
|
|
202
|
-
"- Prefer direct tools when a directed lookup answers the question; delegate when the investigation will clearly take more than ~3 searches or would flood your context with intermediate output.",
|
|
203
|
-
"- Do not delegate a trivial task when the coordination overhead exceeds the work.",
|
|
42
|
+
`Provide 1-${MAX_TASKS} independent tasks. Multiple tasks run concurrently: at most ${MAX_CONCURRENCY} active at once, excess tasks queue, and results preserve input order. For sequential work, call this tool again with the previous result folded into the next briefing.`,
|
|
204
43
|
"",
|
|
205
|
-
"
|
|
206
|
-
"-
|
|
207
|
-
"-
|
|
208
|
-
"- Lookups: hand over the exact command or file. Investigations: hand over the question — prescribed steps become dead weight when the premise is wrong.",
|
|
209
|
-
'- If you need a short answer, say so (e.g. "report in under 200 words"). Workers cannot see the parent conversation or ask the end user questions.',
|
|
210
|
-
'- Example briefing (explorer): "Quick: which commit introduced the retry loop in src/net/client.ts? Use git log/blame; report the hash and a one-line summary."',
|
|
44
|
+
"Agent profiles:",
|
|
45
|
+
"- explorer (default): read-only investigation — finding files, searching code, and answering codebase questions; bash is restricted to read-only inspection (git log/diff/blame, ls, cat, and similar). Never use for changes.",
|
|
46
|
+
"- general: implementation — edits, fixes, refactors, and verification in a scoped area; use when the task changes files.",
|
|
211
47
|
"",
|
|
212
|
-
"
|
|
48
|
+
"Do not delegate a trivial task you can answer with one or two direct tool calls, and never delegate understanding with vague instructions: state what must be investigated or changed and the expected output.",
|
|
213
49
|
].join("\n");
|
|
214
50
|
}
|
|
215
51
|
//# sourceMappingURL=agents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Dirent, existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../../config.ts\";\nimport { parseFrontmatter } from \"../../utils/frontmatter.ts\";\nimport { utf8Prefix } from \"./activity.ts\";\nimport { BUILTIN_TOOL_NAMES, DEFAULT_AGENT_TOOLS, EXPLORER_TOOLS, MAX_CONCURRENCY, MAX_TASKS } from \"./constants.ts\";\nimport type { AgentDefinition, AgentDiagnostic, AgentDiscoveryResult, AgentSource } from \"./types.ts\";\n\nconst AGENT_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]{0,79}$/u;\nconst BUILTIN_TOOL_SET = new Set<string>(BUILTIN_TOOL_NAMES);\nconst TOOL_DESCRIPTION_AGENT_LIST_LIMIT = 8_000;\nconst TOOL_DESCRIPTION_AGENT_SUMMARY_LIMIT = 480;\n\nconst BUILTIN_AGENTS: AgentDefinition[] = [\n\t{\n\t\tname: \"general\",\n\t\tdescription:\n\t\t\t\"Implementation agent for bounded coding tasks: edits, fixes, refactors, and verification in a scoped area. Use when the task changes files; use explorer for read-only questions\",\n\t\tuiDescription:\n\t\t\t\"Implementation agent for bounded coding tasks: edits, fixes, refactors, and verification in a scoped area.\",\n\t\ttools: [...DEFAULT_AGENT_TOOLS],\n\t\tsystemPrompt: [\n\t\t\t\"Work independently on the delegated task from start to finish.\",\n\t\t\t\"Inspect relevant repository instructions before changing files.\",\n\t\t\t\"Prefer editing existing files; never create documentation files unless the task explicitly asks for them.\",\n\t\t\t\"Keep changes focused, run appropriate verification, and report exact paths, checks, blockers, and remaining risks.\",\n\t\t].join(\"\\n\"),\n\t\tsource: \"builtin\",\n\t\tfilePath: \"<builtin:general>\",\n\t\tbackend: \"sdk\",\n\t},\n\t{\n\t\tname: \"explorer\",\n\t\tdescription:\n\t\t\t'Fast read-only agent for finding files, searching code, and answering codebase questions. Can inspect git history (log, blame, diff) via read-only bash. State thoroughness in the prompt: \"quick\" for a targeted lookup, \"medium\" for checking likely related locations, or \"very thorough\" for exhaustive sweeps across locations and naming conventions',\n\t\tuiDescription: \"Fast read-only agent for finding files, searching code, and answering codebase questions.\",\n\t\ttools: [...EXPLORER_TOOLS],\n\t\tsystemPrompt: [\n\t\t\t\"You are a fast read-only exploration agent; return findings as quickly as possible.\",\n\t\t\t\"Explore the delegated question without modifying files.\",\n\t\t\t\"Use read and search tools to gather exact evidence, batching independent searches and reads instead of running them one at a time.\",\n\t\t\t\"bash is for read-only inspection only: git log/diff/blame/show/status, ls, wc, head, tail, cat, and similar.\",\n\t\t\t\"Never run anything that modifies state: no file creation or deletion, no redirect (>, >>) or heredoc writes, no temp files, no git commands that write (add, commit, checkout, restore, stash, clean), no installs, no network access.\",\n\t\t\t\"Match the depth the caller requested: quick targets the direct question, medium checks likely related locations, and very thorough sweeps multiple locations and naming conventions.\",\n\t\t\t\"Return concise findings with precise paths, symbols, relationships, and unresolved uncertainties.\",\n\t\t].join(\"\\n\"),\n\t\tsource: \"builtin\",\n\t\tfilePath: \"<builtin:explorer>\",\n\t\tbackend: \"sdk\",\n\t\tomitContextFiles: true,\n\t},\n];\n\nfunction isDirectory(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction findNearestProjectAgentsDir(cwd: string): string | undefined {\n\tlet current = cwd;\n\twhile (true) {\n\t\tconst candidate = join(current, CONFIG_DIR_NAME, \"agents\");\n\t\tif (isDirectory(candidate)) return candidate;\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) return undefined;\n\t\tcurrent = parent;\n\t}\n}\n\nfunction parseTools(raw: string | undefined, filePath: string): string[] {\n\tif (!raw?.trim()) return [...DEFAULT_AGENT_TOOLS];\n\tconst tools = [\n\t\t...new Set(\n\t\t\traw\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((tool) => tool.trim())\n\t\t\t\t.filter(Boolean),\n\t\t),\n\t];\n\tconst unsupported = tools.filter((tool) => !BUILTIN_TOOL_SET.has(tool));\n\tif (unsupported.length > 0) {\n\t\tthrow new Error(`Unsupported tool(s) ${unsupported.join(\", \")} in ${filePath}.`);\n\t}\n\treturn tools;\n}\n\n// Frontmatter model/thinking keys are intentionally ignored: agent files\n// travel across machines (project repos), so a pinned model rarely exists\n// in the reader's environment. Model and thinking come from /agents\n// overrides or default to the parent session.\nfunction parseAgentFile(filePath: string, source: Exclude<AgentSource, \"builtin\">): AgentDefinition {\n\tconst content = readFileSync(filePath, \"utf8\");\n\tconst { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);\n\tconst name = frontmatter.name?.trim() ?? \"\";\n\tconst description = frontmatter.description?.trim() ?? \"\";\n\tif (!name) throw new Error(\"Missing required frontmatter field: name.\");\n\tif (!AGENT_NAME_PATTERN.test(name)) {\n\t\tthrow new Error(`Agent name \"${name}\" must use lowercase letters, digits, hyphens, or underscores.`);\n\t}\n\tif (!description) throw new Error(\"Missing required frontmatter field: description.\");\n\tif (!body.trim()) throw new Error(\"Agent prompt body must not be empty.\");\n\tconst backend = frontmatter.backend?.trim();\n\tif (backend && backend !== \"sdk\") throw new Error(`Backend \"${backend}\" is not implemented; use \"sdk\".`);\n\treturn {\n\t\tname,\n\t\tdescription,\n\t\ttools: parseTools(frontmatter.tools, filePath),\n\t\tsystemPrompt: body.trim(),\n\t\tsource,\n\t\tfilePath,\n\t\tbackend: \"sdk\",\n\t};\n}\n\nfunction loadAgentDirectory(\n\tdir: string,\n\tsource: Exclude<AgentSource, \"builtin\">,\n): { agents: AgentDefinition[]; diagnostics: AgentDiagnostic[] } {\n\tif (!existsSync(dir)) return { agents: [], diagnostics: [] };\n\tlet entries: Dirent[];\n\ttry {\n\t\tentries = readdirSync(dir, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));\n\t} catch (error) {\n\t\treturn {\n\t\t\tagents: [],\n\t\t\tdiagnostics: [{ path: dir, source, message: error instanceof Error ? error.message : String(error) }],\n\t\t};\n\t}\n\tconst agents: AgentDefinition[] = [];\n\tconst diagnostics: AgentDiagnostic[] = [];\n\tfor (const entry of entries) {\n\t\tif (!entry.name.endsWith(\".md\") || (!entry.isFile() && !entry.isSymbolicLink())) continue;\n\t\tconst filePath = join(dir, entry.name);\n\t\ttry {\n\t\t\tagents.push(parseAgentFile(filePath, source));\n\t\t} catch (error) {\n\t\t\tdiagnostics.push({\n\t\t\t\tpath: filePath,\n\t\t\t\tsource,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t});\n\t\t}\n\t}\n\treturn { agents, diagnostics };\n}\n\nexport function discoverAgents(\n\tcwd: string,\n\toptions: { projectTrusted: boolean; agentDir?: string },\n): AgentDiscoveryResult {\n\tconst userDir = join(options.agentDir ?? getAgentDir(), \"agents\");\n\tconst projectAgentsDir = findNearestProjectAgentsDir(cwd);\n\tconst user = loadAgentDirectory(userDir, \"user\");\n\tconst project =\n\t\toptions.projectTrusted && projectAgentsDir\n\t\t\t? loadAgentDirectory(projectAgentsDir, \"project\")\n\t\t\t: { agents: [], diagnostics: [] };\n\tconst agents = new Map(BUILTIN_AGENTS.map((agent) => [agent.name, { ...agent, tools: [...agent.tools] }]));\n\tfor (const agent of user.agents) agents.set(agent.name, agent);\n\tfor (const agent of project.agents) agents.set(agent.name, agent);\n\treturn {\n\t\tagents: [...agents.values()],\n\t\tdiagnostics: [...user.diagnostics, ...project.diagnostics],\n\t\tprojectAgentsDir,\n\t\tprojectAgentsTrusted: options.projectTrusted,\n\t};\n}\n\nexport function subagentToolDescription(discovery: AgentDiscoveryResult): string {\n\tconst agentLines: string[] = [];\n\tlet agentListLength = 0;\n\tfor (const [index, agent] of discovery.agents.entries()) {\n\t\tconst normalizedDescription = agent.description.replace(/\\s+/gu, \" \").trim();\n\t\tconst description =\n\t\t\tBuffer.byteLength(normalizedDescription, \"utf8\") <= TOOL_DESCRIPTION_AGENT_SUMMARY_LIMIT\n\t\t\t\t? normalizedDescription\n\t\t\t\t: `${utf8Prefix(normalizedDescription, TOOL_DESCRIPTION_AGENT_SUMMARY_LIMIT - Buffer.byteLength(\"…\", \"utf8\"))}…`;\n\t\tconst defaultLabel = agent.name === \"general\" ? \" (default)\" : \"\";\n\t\tconst tools = agent.tools.length > 0 ? agent.tools.join(\", \") : \"none\";\n\t\tconst line = `- ${agent.name}${defaultLabel}: ${description} (Tools: ${tools})`;\n\t\tconst lineLength = Buffer.byteLength(line, \"utf8\") + 1;\n\t\tif (agentListLength + lineLength > TOOL_DESCRIPTION_AGENT_LIST_LIMIT) {\n\t\t\tlet omitted = discovery.agents.length - index;\n\t\t\tlet notice = `- ${omitted} additional profile${omitted === 1 ? \"\" : \"s\"} omitted from this bounded description; /agents lists every profile.`;\n\t\t\twhile (\n\t\t\t\tagentLines.length > 0 &&\n\t\t\t\tagentListLength + Buffer.byteLength(notice, \"utf8\") + 1 > TOOL_DESCRIPTION_AGENT_LIST_LIMIT\n\t\t\t) {\n\t\t\t\tconst removed = agentLines.pop();\n\t\t\t\tif (!removed) break;\n\t\t\t\tagentListLength -= Buffer.byteLength(removed, \"utf8\") + 1;\n\t\t\t\tomitted++;\n\t\t\t\tnotice = `- ${omitted} additional profile${omitted === 1 ? \"\" : \"s\"} omitted from this bounded description; /agents lists every profile.`;\n\t\t\t}\n\t\t\tagentLines.push(notice);\n\t\t\tbreak;\n\t\t}\n\t\tagentLines.push(line);\n\t\tagentListLength += lineLength;\n\t}\n\n\treturn [\n\t\t`Delegate bounded work to isolated one-shot subagents. Delegation keeps intermediate tool output (file dumps, search results) out of your context: you receive only the final report. Choose exactly one mode: prompt for one task, or tasks for independent parallel work (up to ${MAX_TASKS} per call; ${MAX_CONCURRENCY} run concurrently, the rest queue). For sequential work, call this tool again with the previous result folded into the next briefing.`,\n\t\t\"\",\n\t\t\"Available agent profiles:\",\n\t\t...agentLines,\n\t\t\"\",\n\t\t\"When not to delegate:\",\n\t\t\"- Read a known file directly with read, or search for a known symbol directly with grep.\",\n\t\t\"- Prefer direct tools when a directed lookup answers the question; delegate when the investigation will clearly take more than ~3 searches or would flood your context with intermediate output.\",\n\t\t\"- Do not delegate a trivial task when the coordination overhead exceeds the work.\",\n\t\t\"\",\n\t\t\"Writing the briefing:\",\n\t\t\"- Brief the worker like a capable colleague entering the project now: include the objective, relevant context, exact paths or symbols already known, constraints, and expected output.\",\n\t\t\"- Never delegate understanding with vague instructions such as 'fix this based on your findings'; state what must be investigated or changed and whether the worker should research, implement, or review.\",\n\t\t\"- Lookups: hand over the exact command or file. Investigations: hand over the question — prescribed steps become dead weight when the premise is wrong.\",\n\t\t'- If you need a short answer, say so (e.g. \"report in under 200 words\"). Workers cannot see the parent conversation or ask the end user questions.',\n\t\t'- Example briefing (explorer): \"Quick: which commit introduced the retry loop in src/net/client.ts? Use git log/blame; report the hash and a one-line summary.\"',\n\t\t\"\",\n\t\t\"The subagent's report is not shown to the user. Interpret it and relay the important findings, changes, verification, and unresolved risks in your own reply.\",\n\t].join(\"\\n\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,SAAS,GAET,MAAM,gBAAgB,CAAC;AAGxB,0EAA0E;AAC1E,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAsC;IACtE,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;CAClB,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAA4B;IACtD;QACC,IAAI,EAAE,UAAU;QAChB,WAAW,EACV,4VAA4V;QAC7V,KAAK,EAAE,CAAC,GAAG,cAAc,CAAC;QAC1B,YAAY,EAAE;YACb,qFAAqF;YACrF,yDAAyD;YACzD,oIAAoI;YACpI,8GAA8G;YAC9G,wOAAwO;YACxO,sLAAsL;YACtL,mGAAmG;SACnG,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,gBAAgB,EAAE,IAAI;KACtB;IACD;QACC,IAAI,EAAE,SAAS;QACf,WAAW,EACV,kLAAkL;QACnL,KAAK,EAAE,CAAC,GAAG,mBAAmB,CAAC;QAC/B,YAAY,EAAE;YACb,gEAAgE;YAChE,iEAAiE;YACjE,2GAA2G;YAC3G,oHAAoH;SACpH,CAAC,IAAI,CAAC,IAAI,CAAC;KACZ;CACD,CAAC;AAEF,uEAAuE;AACvE,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB;IACtC,OAAO;QACN,iMAAiM;QACjM,EAAE;QACF,aAAa,SAAS,gEAAgE,eAAe,0KAA0K;QAC/Q,EAAE;QACF,iBAAiB;QACjB,gOAAgO;QAChO,0HAA0H;QAC1H,EAAE;QACF,gNAAgN;KAChN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC","sourcesContent":["import {\n\tDEFAULT_AGENT_TOOLS,\n\tEXPLORER_TOOLS,\n\tMAX_CONCURRENCY,\n\tMAX_TASKS,\n\ttype SubagentAgentName,\n} from \"./constants.ts\";\nimport type { AgentProfile } from \"./types.ts\";\n\n// Static display titles for the two built-in profiles; this file owns the\n// model-facing copy, and renderers/commands share these labels.\nexport const AGENT_PROFILE_LABELS: Record<SubagentAgentName, string> = {\n\texplorer: \"Explorer\",\n\tgeneral: \"General\",\n};\n\nexport const AGENT_PROFILES: readonly AgentProfile[] = [\n\t{\n\t\tname: \"explorer\",\n\t\tdescription:\n\t\t\t'Fast read-only agent for finding files, searching code, and answering codebase questions. Can inspect git history (log, blame, diff) via read-only bash. State thoroughness in the prompt: \"quick\" for a targeted lookup, \"medium\" for checking likely related locations, or \"very thorough\" for exhaustive sweeps across locations and naming conventions',\n\t\ttools: [...EXPLORER_TOOLS],\n\t\tsystemPrompt: [\n\t\t\t\"You are a fast read-only exploration agent; return findings as quickly as possible.\",\n\t\t\t\"Explore the delegated question without modifying files.\",\n\t\t\t\"Use read and search tools to gather exact evidence, batching independent searches and reads instead of running them one at a time.\",\n\t\t\t\"bash is for read-only inspection only: git log/diff/blame/show/status, ls, wc, head, tail, cat, and similar.\",\n\t\t\t\"Never run anything that modifies state: no file creation or deletion, no redirect (>, >>) or heredoc writes, no temp files, no git commands that write (add, commit, checkout, restore, stash, clean), no installs, no network access.\",\n\t\t\t\"Match the depth the caller requested: quick targets the direct question, medium checks likely related locations, and very thorough sweeps multiple locations and naming conventions.\",\n\t\t\t\"Return concise findings with precise paths, symbols, relationships, and unresolved uncertainties.\",\n\t\t].join(\"\\n\"),\n\t\tomitContextFiles: true,\n\t},\n\t{\n\t\tname: \"general\",\n\t\tdescription:\n\t\t\t\"Implementation agent for bounded coding tasks: edits, fixes, refactors, and verification in a scoped area. Use when the task changes files; use explorer for read-only questions\",\n\t\ttools: [...DEFAULT_AGENT_TOOLS],\n\t\tsystemPrompt: [\n\t\t\t\"Work independently on the delegated task from start to finish.\",\n\t\t\t\"Inspect relevant repository instructions before changing files.\",\n\t\t\t\"Prefer editing existing files; never create documentation files unless the task explicitly asks for them.\",\n\t\t\t\"Keep changes focused, run appropriate verification, and report exact paths, checks, blockers, and remaining risks.\",\n\t\t].join(\"\\n\"),\n\t},\n];\n\n// Static model-facing guidance: there are exactly two profiles and one\n// tasks-array parameter shape, so the description never depends on discovery.\nexport function subagentToolDescription(): string {\n\treturn [\n\t\t\"Delegate bounded work to isolated one-shot subagents. Workers cannot see the parent conversation: each task needs a complete self-contained briefing, and you receive only their final reports.\",\n\t\t\"\",\n\t\t`Provide 1-${MAX_TASKS} independent tasks. Multiple tasks run concurrently: at most ${MAX_CONCURRENCY} active at once, excess tasks queue, and results preserve input order. For sequential work, call this tool again with the previous result folded into the next briefing.`,\n\t\t\"\",\n\t\t\"Agent profiles:\",\n\t\t\"- explorer (default): read-only investigation — finding files, searching code, and answering codebase questions; bash is restricted to read-only inspection (git log/diff/blame, ls, cat, and similar). Never use for changes.\",\n\t\t\"- general: implementation — edits, fixes, refactors, and verification in a scoped area; use when the task changes files.\",\n\t\t\"\",\n\t\t\"Do not delegate a trivial task you can answer with one or two direct tool calls, and never delegate understanding with vague instructions: state what must be investigated or changed and the expected output.\",\n\t].join(\"\\n\");\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SubagentDetails } from "./types.ts";
|
|
2
|
+
export interface BudgetPlan {
|
|
3
|
+
/** Per-run share of the persisted details budget. */
|
|
4
|
+
perRunDetails: number;
|
|
5
|
+
/** Report cap inside the persisted details for a single run. */
|
|
6
|
+
perRunDetailsReport: number;
|
|
7
|
+
/** Model-facing report budget per numbered task section. */
|
|
8
|
+
perTaskReport: number;
|
|
9
|
+
/** Model-facing total report budget across every section. */
|
|
10
|
+
totalReport: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function planBudgets(taskCount: number): BudgetPlan;
|
|
13
|
+
export declare function boundSubagentDetails(details: SubagentDetails): SubagentDetails;
|
|
14
|
+
export declare function resultContent(details: SubagentDetails): string;
|
|
15
|
+
//# sourceMappingURL=budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/budget.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAC;AAYtE,MAAM,WAAW,UAAU;IAC1B,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,aAAa,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAczD;AA8BD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,eAAe,CAkB9E;AAqBD,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAM9D"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { DETAILS_ACTIVITY_LIMIT, DETAILS_OUTPUT_LIMIT, RETRY_ERROR_TEXT_LIMIT, TASK_OUTPUT_LIMIT, TOTAL_OUTPUT_LIMIT, } from "./constants.js";
|
|
2
|
+
import { boundText } from "./text.js";
|
|
3
|
+
const EMPTY_OUTPUT = "(Subagent completed but returned no output.)";
|
|
4
|
+
// Pass-2 (adversarial) accounting: the bounded non-report payload is
|
|
5
|
+
// measured exactly (JSON escaping included), the residual is split across
|
|
6
|
+
// runs, and a worst-case JSON-escape factor of 6x (\\uXXXX control escapes)
|
|
7
|
+
// keeps the final serialization under the limit by construction — no shrink
|
|
8
|
+
// loop, at most three serializations.
|
|
9
|
+
const BATCH_RESERVE_BYTES = 1 * 1024;
|
|
10
|
+
const JSON_ESCAPE_FACTOR = 6;
|
|
11
|
+
export function planBudgets(taskCount) {
|
|
12
|
+
const count = Math.max(1, taskCount);
|
|
13
|
+
const perRunDetails = Math.max(1_024, Math.floor((DETAILS_OUTPUT_LIMIT - 8 * 1024) / count));
|
|
14
|
+
// Fair per-task report budget: the total cap is split evenly after
|
|
15
|
+
// reserving room for the numbered section headings and separators, capped
|
|
16
|
+
// per task.
|
|
17
|
+
const headingReserve = Math.min(256 * count, Math.floor(TOTAL_OUTPUT_LIMIT / 4));
|
|
18
|
+
const fairShare = Math.floor((TOTAL_OUTPUT_LIMIT - headingReserve) / count);
|
|
19
|
+
return {
|
|
20
|
+
perRunDetails,
|
|
21
|
+
perRunDetailsReport: Math.min(TASK_OUTPUT_LIMIT, Math.max(1_024, perRunDetails - 7 * 1024)),
|
|
22
|
+
perTaskReport: Math.min(TASK_OUTPUT_LIMIT, Math.max(2_048, fairShare)),
|
|
23
|
+
totalReport: TOTAL_OUTPUT_LIMIT,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function detailsSize(details) {
|
|
27
|
+
return Buffer.byteLength(JSON.stringify(details), "utf8");
|
|
28
|
+
}
|
|
29
|
+
function boundRuns(details, reportLimit) {
|
|
30
|
+
return {
|
|
31
|
+
...details,
|
|
32
|
+
runs: details.runs.map((run) => ({
|
|
33
|
+
...run,
|
|
34
|
+
cwd: boundText(run.cwd, 1_024),
|
|
35
|
+
currentActivity: run.currentActivity ? boundText(run.currentActivity, 512) : undefined,
|
|
36
|
+
retry: run.retry ? { ...run.retry, error: boundText(run.retry.error, RETRY_ERROR_TEXT_LIMIT) } : undefined,
|
|
37
|
+
activities: run.activities.slice(-DETAILS_ACTIVITY_LIMIT).map((activity) => ({
|
|
38
|
+
...activity,
|
|
39
|
+
summary: boundText(activity.summary, 256),
|
|
40
|
+
resultSummary: activity.resultSummary ? boundText(activity.resultSummary, 256) : undefined,
|
|
41
|
+
})),
|
|
42
|
+
report: boundText(run.report, reportLimit),
|
|
43
|
+
error: run.error ? boundText(run.error, 1_024) : undefined,
|
|
44
|
+
})),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Bounds the persisted details payload. Pass 1 uses the same optimistic
|
|
48
|
+
// per-run budget as the historical shrink loop's starting point, which every
|
|
49
|
+
// realistic batch satisfies without shrinking reports. Only adversarial
|
|
50
|
+
// payloads (e.g. every field at its cap in a full 8-run batch) fall through
|
|
51
|
+
// to pass 2, which caps reports to the measured residual share.
|
|
52
|
+
export function boundSubagentDetails(details) {
|
|
53
|
+
const plan = planBudgets(details.runs.length);
|
|
54
|
+
const optimistic = boundRuns(details, plan.perRunDetailsReport);
|
|
55
|
+
if (detailsSize(optimistic) <= DETAILS_OUTPUT_LIMIT)
|
|
56
|
+
return optimistic;
|
|
57
|
+
const count = Math.max(1, details.runs.length);
|
|
58
|
+
const nonReportBytes = detailsSize(boundRuns(details, 0));
|
|
59
|
+
const residual = DETAILS_OUTPUT_LIMIT - nonReportBytes - BATCH_RESERVE_BYTES;
|
|
60
|
+
// Factor 2 covers realistic escaping (quotes, backslashes, newlines); the
|
|
61
|
+
// measured result still wins when it fits.
|
|
62
|
+
const likely = Math.min(plan.perRunDetailsReport, Math.max(0, Math.floor(residual / count / 2)));
|
|
63
|
+
const likelyBounded = boundRuns(details, likely);
|
|
64
|
+
if (detailsSize(likelyBounded) <= DETAILS_OUTPUT_LIMIT)
|
|
65
|
+
return likelyBounded;
|
|
66
|
+
// Worst-case \\uXXXX control escapes: under the limit by construction.
|
|
67
|
+
const reportLimit = Math.min(plan.perRunDetailsReport, Math.max(0, Math.floor(residual / count / JSON_ESCAPE_FACTOR)));
|
|
68
|
+
return boundRuns(details, reportLimit);
|
|
69
|
+
}
|
|
70
|
+
function reportSectionTitle(run, index) {
|
|
71
|
+
return `### ${index + 1}. ${run.description} (${run.agent}) — ${run.status}`;
|
|
72
|
+
}
|
|
73
|
+
function reportSectionBody(run) {
|
|
74
|
+
if (run.status === "completed")
|
|
75
|
+
return run.report || EMPTY_OUTPUT;
|
|
76
|
+
if (run.status === "failed" || run.status === "aborted") {
|
|
77
|
+
const verdict = run.status === "aborted" ? "Subagent aborted" : "Subagent failed";
|
|
78
|
+
const cause = run.error ? `: ${run.error}` : ".";
|
|
79
|
+
const partial = run.report ? `\n\nPartial report:\n${run.report}` : "";
|
|
80
|
+
return `${verdict}${cause}${partial}`;
|
|
81
|
+
}
|
|
82
|
+
if (run.status === "queued")
|
|
83
|
+
return "Task was queued and never started.";
|
|
84
|
+
return "Task was still running when the batch settled.";
|
|
85
|
+
}
|
|
86
|
+
// Always ordered numbered sections, even for a single task, so the parent
|
|
87
|
+
// can reference results by number. Total cap with a fair per-task budget;
|
|
88
|
+
// empty, failed, aborted, and partial reports are labeled explicitly.
|
|
89
|
+
export function resultContent(details) {
|
|
90
|
+
const perTaskBudget = planBudgets(details.runs.length).perTaskReport;
|
|
91
|
+
const sections = details.runs.map((run, index) => {
|
|
92
|
+
return `${reportSectionTitle(run, index)}\n\n${boundText(reportSectionBody(run), perTaskBudget)}`;
|
|
93
|
+
});
|
|
94
|
+
return boundText(sections.join("\n\n---\n\n"), TOTAL_OUTPUT_LIMIT);
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../../src/extensions/subagent/budget.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tDETAILS_ACTIVITY_LIMIT,\n\tDETAILS_OUTPUT_LIMIT,\n\tRETRY_ERROR_TEXT_LIMIT,\n\tTASK_OUTPUT_LIMIT,\n\tTOTAL_OUTPUT_LIMIT,\n} from \"./constants.ts\";\nimport { boundText } from \"./text.ts\";\nimport type { SubagentDetails, SubagentRunDetails } from \"./types.ts\";\n\nconst EMPTY_OUTPUT = \"(Subagent completed but returned no output.)\";\n\n// Pass-2 (adversarial) accounting: the bounded non-report payload is\n// measured exactly (JSON escaping included), the residual is split across\n// runs, and a worst-case JSON-escape factor of 6x (\\\\uXXXX control escapes)\n// keeps the final serialization under the limit by construction — no shrink\n// loop, at most three serializations.\nconst BATCH_RESERVE_BYTES = 1 * 1024;\nconst JSON_ESCAPE_FACTOR = 6;\n\nexport interface BudgetPlan {\n\t/** Per-run share of the persisted details budget. */\n\tperRunDetails: number;\n\t/** Report cap inside the persisted details for a single run. */\n\tperRunDetailsReport: number;\n\t/** Model-facing report budget per numbered task section. */\n\tperTaskReport: number;\n\t/** Model-facing total report budget across every section. */\n\ttotalReport: number;\n}\n\nexport function planBudgets(taskCount: number): BudgetPlan {\n\tconst count = Math.max(1, taskCount);\n\tconst perRunDetails = Math.max(1_024, Math.floor((DETAILS_OUTPUT_LIMIT - 8 * 1024) / count));\n\t// Fair per-task report budget: the total cap is split evenly after\n\t// reserving room for the numbered section headings and separators, capped\n\t// per task.\n\tconst headingReserve = Math.min(256 * count, Math.floor(TOTAL_OUTPUT_LIMIT / 4));\n\tconst fairShare = Math.floor((TOTAL_OUTPUT_LIMIT - headingReserve) / count);\n\treturn {\n\t\tperRunDetails,\n\t\tperRunDetailsReport: Math.min(TASK_OUTPUT_LIMIT, Math.max(1_024, perRunDetails - 7 * 1024)),\n\t\tperTaskReport: Math.min(TASK_OUTPUT_LIMIT, Math.max(2_048, fairShare)),\n\t\ttotalReport: TOTAL_OUTPUT_LIMIT,\n\t};\n}\n\nfunction detailsSize(details: SubagentDetails): number {\n\treturn Buffer.byteLength(JSON.stringify(details), \"utf8\");\n}\n\nfunction boundRuns(details: SubagentDetails, reportLimit: number): SubagentDetails {\n\treturn {\n\t\t...details,\n\t\truns: details.runs.map((run) => ({\n\t\t\t...run,\n\t\t\tcwd: boundText(run.cwd, 1_024),\n\t\t\tcurrentActivity: run.currentActivity ? boundText(run.currentActivity, 512) : undefined,\n\t\t\tretry: run.retry ? { ...run.retry, error: boundText(run.retry.error, RETRY_ERROR_TEXT_LIMIT) } : undefined,\n\t\t\tactivities: run.activities.slice(-DETAILS_ACTIVITY_LIMIT).map((activity) => ({\n\t\t\t\t...activity,\n\t\t\t\tsummary: boundText(activity.summary, 256),\n\t\t\t\tresultSummary: activity.resultSummary ? boundText(activity.resultSummary, 256) : undefined,\n\t\t\t})),\n\t\t\treport: boundText(run.report, reportLimit),\n\t\t\terror: run.error ? boundText(run.error, 1_024) : undefined,\n\t\t})),\n\t};\n}\n\n// Bounds the persisted details payload. Pass 1 uses the same optimistic\n// per-run budget as the historical shrink loop's starting point, which every\n// realistic batch satisfies without shrinking reports. Only adversarial\n// payloads (e.g. every field at its cap in a full 8-run batch) fall through\n// to pass 2, which caps reports to the measured residual share.\nexport function boundSubagentDetails(details: SubagentDetails): SubagentDetails {\n\tconst plan = planBudgets(details.runs.length);\n\tconst optimistic = boundRuns(details, plan.perRunDetailsReport);\n\tif (detailsSize(optimistic) <= DETAILS_OUTPUT_LIMIT) return optimistic;\n\tconst count = Math.max(1, details.runs.length);\n\tconst nonReportBytes = detailsSize(boundRuns(details, 0));\n\tconst residual = DETAILS_OUTPUT_LIMIT - nonReportBytes - BATCH_RESERVE_BYTES;\n\t// Factor 2 covers realistic escaping (quotes, backslashes, newlines); the\n\t// measured result still wins when it fits.\n\tconst likely = Math.min(plan.perRunDetailsReport, Math.max(0, Math.floor(residual / count / 2)));\n\tconst likelyBounded = boundRuns(details, likely);\n\tif (detailsSize(likelyBounded) <= DETAILS_OUTPUT_LIMIT) return likelyBounded;\n\t// Worst-case \\\\uXXXX control escapes: under the limit by construction.\n\tconst reportLimit = Math.min(\n\t\tplan.perRunDetailsReport,\n\t\tMath.max(0, Math.floor(residual / count / JSON_ESCAPE_FACTOR)),\n\t);\n\treturn boundRuns(details, reportLimit);\n}\n\nfunction reportSectionTitle(run: SubagentRunDetails, index: number): string {\n\treturn `### ${index + 1}. ${run.description} (${run.agent}) — ${run.status}`;\n}\n\nfunction reportSectionBody(run: SubagentRunDetails): string {\n\tif (run.status === \"completed\") return run.report || EMPTY_OUTPUT;\n\tif (run.status === \"failed\" || run.status === \"aborted\") {\n\t\tconst verdict = run.status === \"aborted\" ? \"Subagent aborted\" : \"Subagent failed\";\n\t\tconst cause = run.error ? `: ${run.error}` : \".\";\n\t\tconst partial = run.report ? `\\n\\nPartial report:\\n${run.report}` : \"\";\n\t\treturn `${verdict}${cause}${partial}`;\n\t}\n\tif (run.status === \"queued\") return \"Task was queued and never started.\";\n\treturn \"Task was still running when the batch settled.\";\n}\n\n// Always ordered numbered sections, even for a single task, so the parent\n// can reference results by number. Total cap with a fair per-task budget;\n// empty, failed, aborted, and partial reports are labeled explicitly.\nexport function resultContent(details: SubagentDetails): string {\n\tconst perTaskBudget = planBudgets(details.runs.length).perTaskReport;\n\tconst sections = details.runs.map((run, index) => {\n\t\treturn `${reportSectionTitle(run, index)}\\n\\n${boundText(reportSectionBody(run), perTaskBudget)}`;\n\t});\n\treturn boundText(sections.join(\"\\n\\n---\\n\\n\"), TOTAL_OUTPUT_LIMIT);\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run cancellation scope.
|
|
3
|
+
*
|
|
4
|
+
* One scope owns a single subagent run for its whole life: queued at the
|
|
5
|
+
* gate, task-retry backoff, worker initialization, and the worker session
|
|
6
|
+
* itself. The derived signal fires on either the parent turn signal or an
|
|
7
|
+
* explicit abort (session shutdown); a single optional handler (the worker
|
|
8
|
+
* session's abort) rides along so aborting also stops the live session.
|
|
9
|
+
*/
|
|
10
|
+
export interface RunCancellation {
|
|
11
|
+
/** Fires when the parent signal aborts or abort() is called. */
|
|
12
|
+
readonly signal: AbortSignal;
|
|
13
|
+
readonly aborted: boolean;
|
|
14
|
+
/** Idempotent: marks the scope aborted and awaits the registered handler. */
|
|
15
|
+
abort(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Single-slot abort handler; a later call replaces the earlier one.
|
|
18
|
+
* Registering after an abort invokes the handler immediately. Returns an
|
|
19
|
+
* unregister function that restores a no-op (the scope stays abortable).
|
|
20
|
+
*/
|
|
21
|
+
onAbort(handler: () => Promise<void>): () => void;
|
|
22
|
+
throwIfAborted(): void;
|
|
23
|
+
/** Drops the parent-signal listener and the handler; idempotent. */
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}
|
|
26
|
+
export declare function createRunCancellation(parent: AbortSignal | undefined): RunCancellation;
|
|
27
|
+
/** Sleeps until the deadline or the scope aborts; rejects on abort. */
|
|
28
|
+
export declare function abortableSleep(ms: number, scope: RunCancellation): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=cancellation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancellation.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/cancellation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,6EAA6E;IAC7E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC;IAClD,cAAc,IAAI,IAAI,CAAC;IACvB,oEAAoE;IACpE,OAAO,IAAI,IAAI,CAAC;CAChB;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,eAAe,CA6CtF;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const NO_OP_HANDLER = () => Promise.resolve();
|
|
2
|
+
export function createRunCancellation(parent) {
|
|
3
|
+
const controller = new AbortController();
|
|
4
|
+
let handler = NO_OP_HANDLER;
|
|
5
|
+
let inFlight;
|
|
6
|
+
let disposed = false;
|
|
7
|
+
const trigger = () => {
|
|
8
|
+
if (disposed)
|
|
9
|
+
return Promise.resolve();
|
|
10
|
+
if (!controller.signal.aborted)
|
|
11
|
+
controller.abort();
|
|
12
|
+
inFlight ??= Promise.resolve()
|
|
13
|
+
.then(handler)
|
|
14
|
+
.catch(() => undefined);
|
|
15
|
+
return inFlight;
|
|
16
|
+
};
|
|
17
|
+
const parentListener = () => {
|
|
18
|
+
void trigger();
|
|
19
|
+
};
|
|
20
|
+
if (parent) {
|
|
21
|
+
if (parent.aborted)
|
|
22
|
+
void trigger();
|
|
23
|
+
else
|
|
24
|
+
parent.addEventListener("abort", parentListener, { once: true });
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
signal: controller.signal,
|
|
28
|
+
get aborted() {
|
|
29
|
+
return controller.signal.aborted;
|
|
30
|
+
},
|
|
31
|
+
abort: trigger,
|
|
32
|
+
onAbort(next) {
|
|
33
|
+
handler = next;
|
|
34
|
+
if (controller.signal.aborted)
|
|
35
|
+
void trigger();
|
|
36
|
+
return () => {
|
|
37
|
+
if (handler === next)
|
|
38
|
+
handler = NO_OP_HANDLER;
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
throwIfAborted() {
|
|
42
|
+
if (controller.signal.aborted)
|
|
43
|
+
throw new Error("Subagent run was aborted.");
|
|
44
|
+
},
|
|
45
|
+
dispose() {
|
|
46
|
+
disposed = true;
|
|
47
|
+
handler = NO_OP_HANDLER;
|
|
48
|
+
parent?.removeEventListener("abort", parentListener);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Sleeps until the deadline or the scope aborts; rejects on abort. */
|
|
53
|
+
export function abortableSleep(ms, scope) {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
if (scope.signal.aborted) {
|
|
56
|
+
reject(new Error("Aborted"));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let timer;
|
|
60
|
+
const onAbort = () => {
|
|
61
|
+
if (timer)
|
|
62
|
+
clearTimeout(timer);
|
|
63
|
+
scope.signal.removeEventListener("abort", onAbort);
|
|
64
|
+
reject(new Error("Aborted"));
|
|
65
|
+
};
|
|
66
|
+
timer = setTimeout(() => {
|
|
67
|
+
scope.signal.removeEventListener("abort", onAbort);
|
|
68
|
+
resolve();
|
|
69
|
+
}, ms);
|
|
70
|
+
scope.signal.addEventListener("abort", onAbort, { once: true });
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=cancellation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancellation.js","sourceRoot":"","sources":["../../../src/extensions/subagent/cancellation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Per-run cancellation scope.\n *\n * One scope owns a single subagent run for its whole life: queued at the\n * gate, task-retry backoff, worker initialization, and the worker session\n * itself. The derived signal fires on either the parent turn signal or an\n * explicit abort (session shutdown); a single optional handler (the worker\n * session's abort) rides along so aborting also stops the live session.\n */\nexport interface RunCancellation {\n\t/** Fires when the parent signal aborts or abort() is called. */\n\treadonly signal: AbortSignal;\n\treadonly aborted: boolean;\n\t/** Idempotent: marks the scope aborted and awaits the registered handler. */\n\tabort(): Promise<void>;\n\t/**\n\t * Single-slot abort handler; a later call replaces the earlier one.\n\t * Registering after an abort invokes the handler immediately. Returns an\n\t * unregister function that restores a no-op (the scope stays abortable).\n\t */\n\tonAbort(handler: () => Promise<void>): () => void;\n\tthrowIfAborted(): void;\n\t/** Drops the parent-signal listener and the handler; idempotent. */\n\tdispose(): void;\n}\n\nconst NO_OP_HANDLER = (): Promise<void> => Promise.resolve();\n\nexport function createRunCancellation(parent: AbortSignal | undefined): RunCancellation {\n\tconst controller = new AbortController();\n\tlet handler: () => Promise<void> = NO_OP_HANDLER;\n\tlet inFlight: Promise<void> | undefined;\n\tlet disposed = false;\n\n\tconst trigger = (): Promise<void> => {\n\t\tif (disposed) return Promise.resolve();\n\t\tif (!controller.signal.aborted) controller.abort();\n\t\tinFlight ??= Promise.resolve()\n\t\t\t.then(handler)\n\t\t\t.catch(() => undefined);\n\t\treturn inFlight;\n\t};\n\n\tconst parentListener = (): void => {\n\t\tvoid trigger();\n\t};\n\tif (parent) {\n\t\tif (parent.aborted) void trigger();\n\t\telse parent.addEventListener(\"abort\", parentListener, { once: true });\n\t}\n\n\treturn {\n\t\tsignal: controller.signal,\n\t\tget aborted(): boolean {\n\t\t\treturn controller.signal.aborted;\n\t\t},\n\t\tabort: trigger,\n\t\tonAbort(next: () => Promise<void>): () => void {\n\t\t\thandler = next;\n\t\t\tif (controller.signal.aborted) void trigger();\n\t\t\treturn () => {\n\t\t\t\tif (handler === next) handler = NO_OP_HANDLER;\n\t\t\t};\n\t\t},\n\t\tthrowIfAborted(): void {\n\t\t\tif (controller.signal.aborted) throw new Error(\"Subagent run was aborted.\");\n\t\t},\n\t\tdispose(): void {\n\t\t\tdisposed = true;\n\t\t\thandler = NO_OP_HANDLER;\n\t\t\tparent?.removeEventListener(\"abort\", parentListener);\n\t\t},\n\t};\n}\n\n/** Sleeps until the deadline or the scope aborts; rejects on abort. */\nexport function abortableSleep(ms: number, scope: RunCancellation): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (scope.signal.aborted) {\n\t\t\treject(new Error(\"Aborted\"));\n\t\t\treturn;\n\t\t}\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst onAbort = (): void => {\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\tscope.signal.removeEventListener(\"abort\", onAbort);\n\t\t\treject(new Error(\"Aborted\"));\n\t\t};\n\t\ttimer = setTimeout(() => {\n\t\t\tscope.signal.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tscope.signal.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n"]}
|
|
@@ -7,16 +7,15 @@ export declare const MAX_TASKS = 8;
|
|
|
7
7
|
export declare const MAX_CONCURRENCY = 5;
|
|
8
8
|
export declare const TASK_RETRY_LIMIT = 2;
|
|
9
9
|
export declare const TASK_RETRY_BASE_DELAY_MS = 1000;
|
|
10
|
-
export declare const
|
|
10
|
+
export declare const SUBAGENT_AGENT_NAMES: readonly ["explorer", "general"];
|
|
11
|
+
export type SubagentAgentName = (typeof SUBAGENT_AGENT_NAMES)[number];
|
|
11
12
|
export declare const DEFAULT_AGENT_TOOLS: readonly ["read", "bash", "edit", "write"];
|
|
12
13
|
export declare const EXPLORER_TOOLS: readonly ["read", "grep", "find", "ls", "bash"];
|
|
13
14
|
export declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
14
|
-
export declare const LIVE_TEXT_LIMIT: number;
|
|
15
15
|
export declare const ACTIVITY_LIMIT = 80;
|
|
16
16
|
export declare const ACTIVITY_TEXT_LIMIT: number;
|
|
17
|
-
export declare const
|
|
18
|
-
export declare const
|
|
19
|
-
export declare const PARALLEL_OUTPUT_LIMIT: number;
|
|
17
|
+
export declare const TASK_OUTPUT_LIMIT: number;
|
|
18
|
+
export declare const TOTAL_OUTPUT_LIMIT: number;
|
|
20
19
|
export declare const ERROR_TEXT_LIMIT: number;
|
|
21
20
|
export declare const RETRY_ERROR_TEXT_LIMIT = 160;
|
|
22
21
|
export declare const DETAILS_OUTPUT_LIMIT: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAC7C,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,eAAe,IAAI,CAAC;AAKjC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,wBAAwB,OAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAC7C,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,eAAe,IAAI,CAAC;AAKjC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAI9C,eAAO,MAAM,oBAAoB,kCAAmC,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAGtE,eAAO,MAAM,mBAAmB,4CAA6C,CAAC;AAI9E,eAAO,MAAM,cAAc,iDAAkD,CAAC;AAE9E,eAAO,MAAM,eAAe,sEAQiB,CAAC;AAE9C,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAG7C,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAE3C,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAC5C,eAAO,MAAM,gBAAgB,QAAW,CAAC;AACzC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,oBAAoB,QAAa,CAAC;AAG/C,eAAO,MAAM,sBAAsB,KAAK,CAAC"}
|