@astralyn/pi 0.84.14 → 0.84.16
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 +23 -0
- package/dist/cli.js +2435 -18
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +12 -6
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/types.d.ts +4 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/tools/bash.d.ts +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +4 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/find.d.ts +2 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +18 -15
- package/dist/core/tools/find.js.map +1 -1
- package/dist/extensions/background/actions.d.ts.map +1 -1
- package/dist/extensions/background/actions.js +3 -2
- package/dist/extensions/background/actions.js.map +1 -1
- package/dist/extensions/background/index.d.ts +5 -4
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +9 -5
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/background/manager.d.ts.map +1 -1
- package/dist/extensions/background/manager.js +8 -9
- package/dist/extensions/background/manager.js.map +1 -1
- package/dist/extensions/background/registry.d.ts +4 -1
- package/dist/extensions/background/registry.d.ts.map +1 -1
- package/dist/extensions/background/registry.js +30 -17
- package/dist/extensions/background/registry.js.map +1 -1
- package/dist/extensions/background/task-view.d.ts +6 -0
- package/dist/extensions/background/task-view.d.ts.map +1 -1
- package/dist/extensions/background/task-view.js +11 -6
- package/dist/extensions/background/task-view.js.map +1 -1
- package/dist/extensions/deepwiki/client.d.ts.map +1 -1
- package/dist/extensions/deepwiki/client.js +3 -0
- package/dist/extensions/deepwiki/client.js.map +1 -1
- package/dist/extensions/deepwiki/execute.d.ts +2 -1
- package/dist/extensions/deepwiki/execute.d.ts.map +1 -1
- package/dist/extensions/deepwiki/execute.js +17 -2
- package/dist/extensions/deepwiki/execute.js.map +1 -1
- package/dist/extensions/deepwiki/http.d.ts +1 -0
- package/dist/extensions/deepwiki/http.d.ts.map +1 -1
- package/dist/extensions/deepwiki/http.js +16 -2
- package/dist/extensions/deepwiki/http.js.map +1 -1
- package/dist/extensions/deepwiki/schema.d.ts +1 -1
- package/dist/extensions/deepwiki/schema.d.ts.map +1 -1
- package/dist/extensions/deepwiki/schema.js +8 -2
- package/dist/extensions/deepwiki/schema.js.map +1 -1
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +80 -9
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/index.d.ts.map +1 -1
- package/dist/extensions/question/index.js +8 -0
- package/dist/extensions/question/index.js.map +1 -1
- package/dist/extensions/question/schema.d.ts +2 -2
- package/dist/extensions/question/schema.d.ts.map +1 -1
- package/dist/extensions/question/schema.js +41 -11
- package/dist/extensions/question/schema.js.map +1 -1
- package/dist/extensions/question/types.d.ts +1 -1
- package/dist/extensions/question/types.d.ts.map +1 -1
- package/dist/extensions/question/types.js.map +1 -1
- package/dist/extensions/router/probe.d.ts.map +1 -1
- package/dist/extensions/router/probe.js +10 -29
- package/dist/extensions/router/probe.js.map +1 -1
- package/dist/extensions/router/register.d.ts.map +1 -1
- package/dist/extensions/router/register.js +16 -6
- package/dist/extensions/router/register.js.map +1 -1
- package/dist/extensions/router/store.d.ts.map +1 -1
- package/dist/extensions/router/store.js +108 -51
- package/dist/extensions/router/store.js.map +1 -1
- package/dist/extensions/router/ui.d.ts +6 -0
- package/dist/extensions/router/ui.d.ts.map +1 -1
- package/dist/extensions/router/ui.js +14 -6
- package/dist/extensions/router/ui.js.map +1 -1
- package/dist/extensions/statusline/index.d.ts.map +1 -1
- package/dist/extensions/statusline/index.js +40 -43
- package/dist/extensions/statusline/index.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts +7 -1
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +69 -6
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents-command.js +1 -1
- package/dist/extensions/subagent/agents-command.js.map +1 -1
- package/dist/extensions/subagent/agents.d.ts.map +1 -1
- package/dist/extensions/subagent/agents.js +0 -3
- package/dist/extensions/subagent/agents.js.map +1 -1
- package/dist/extensions/subagent/budget.d.ts.map +1 -1
- package/dist/extensions/subagent/budget.js +29 -2
- package/dist/extensions/subagent/budget.js.map +1 -1
- package/dist/extensions/subagent/cancellation.d.ts +4 -4
- package/dist/extensions/subagent/cancellation.d.ts.map +1 -1
- package/dist/extensions/subagent/cancellation.js +31 -13
- package/dist/extensions/subagent/cancellation.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts +1 -0
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +1 -0
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +1 -0
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts +8 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +155 -178
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +1 -0
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +53 -44
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +0 -3
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/settings.d.ts +1 -1
- package/dist/extensions/subagent/settings.d.ts.map +1 -1
- package/dist/extensions/subagent/settings.js +74 -25
- package/dist/extensions/subagent/settings.js.map +1 -1
- package/dist/extensions/subagent/state.d.ts +1 -0
- package/dist/extensions/subagent/state.d.ts.map +1 -1
- package/dist/extensions/subagent/state.js +46 -16
- package/dist/extensions/subagent/state.js.map +1 -1
- package/dist/extensions/subagent/types.d.ts +0 -7
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/subagent/ui/agents-dialog.js +1 -1
- package/dist/extensions/subagent/ui/agents-dialog.js.map +1 -1
- package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
- package/dist/extensions/subagent/ui/model-list.js +3 -4
- package/dist/extensions/subagent/ui/model-list.js.map +1 -1
- package/dist/extensions/subagent/ui/model-picker.d.ts.map +1 -1
- package/dist/extensions/subagent/ui/model-picker.js +2 -1
- package/dist/extensions/subagent/ui/model-picker.js.map +1 -1
- package/dist/extensions/web-search/format.d.ts.map +1 -1
- package/dist/extensions/web-search/format.js +36 -15
- package/dist/extensions/web-search/format.js.map +1 -1
- package/dist/extensions/web-search/index.d.ts.map +1 -1
- package/dist/extensions/web-search/index.js +11 -8
- package/dist/extensions/web-search/index.js.map +1 -1
- package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -1
- package/dist/extensions/web-search/providers/deepseek.js +36 -5
- package/dist/extensions/web-search/providers/deepseek.js.map +1 -1
- package/dist/extensions/web-search/providers/http.d.ts +2 -7
- package/dist/extensions/web-search/providers/http.d.ts.map +1 -1
- package/dist/extensions/web-search/providers/http.js +12 -57
- package/dist/extensions/web-search/providers/http.js.map +1 -1
- package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -1
- package/dist/extensions/web-search/providers/minimax.js +18 -6
- package/dist/extensions/web-search/providers/minimax.js.map +1 -1
- package/dist/extensions/web-search/render.d.ts.map +1 -1
- package/dist/extensions/web-search/render.js +16 -5
- package/dist/extensions/web-search/render.js.map +1 -1
- package/dist/extensions/web-search/results.d.ts +10 -3
- package/dist/extensions/web-search/results.d.ts.map +1 -1
- package/dist/extensions/web-search/results.js +25 -7
- package/dist/extensions/web-search/results.js.map +1 -1
- package/dist/image-resize-worker.js +2 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +7 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-group.js +10 -0
- package/dist/modes/interactive/components/tool-group.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +3 -40
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +0 -4
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +16 -23
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/rpc-entry.js +2435 -10
- package/dist/utils/http-response.d.ts +10 -0
- package/dist/utils/http-response.d.ts.map +1 -0
- package/dist/utils/http-response.js +68 -0
- package/dist/utils/http-response.js.map +1 -0
- package/docs/bundled/extensions/background.md +4 -3
- package/docs/bundled/extensions/deepwiki.md +7 -5
- package/docs/bundled/extensions/question.md +6 -4
- package/docs/bundled/extensions/router.md +1 -1
- package/docs/bundled/extensions/statusline.md +1 -0
- package/docs/bundled/extensions/subagent.md +29 -39
- package/docs/bundled/extensions/web-search.md +3 -3
- package/docs/development.md +8 -3
- package/docs/extensions.md +2 -2
- package/npm-shrinkwrap.json +110 -109
- package/package.json +4 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
2
2
|
import type { Usage } from "@earendil-works/pi-ai";
|
|
3
|
-
import type { SubagentUsage } from "./types.ts";
|
|
3
|
+
import type { SubagentUsage, ToolActivity } from "./types.ts";
|
|
4
4
|
/** The usage fields that are summed when aggregating. */
|
|
5
5
|
export declare const USAGE_SUM_FIELDS: readonly ["input", "output", "cacheRead", "cacheWrite", "totalTokens"];
|
|
6
6
|
export declare function emptyUsage(): SubagentUsage;
|
|
@@ -9,7 +9,13 @@ export declare function mergeUsage(target: SubagentUsage, source: SubagentUsage)
|
|
|
9
9
|
export declare function toNestedUsage(usage: SubagentUsage): Usage;
|
|
10
10
|
export declare function assistantText(message: AgentMessage | undefined): string;
|
|
11
11
|
export declare function finalAssistantText(messages: readonly AgentMessage[]): string;
|
|
12
|
+
/** Synthetic lifecycle entries stay persisted but do not count as worker tool calls. */
|
|
13
|
+
export declare function isSyntheticActivity(activity: Pick<ToolActivity, "toolName">): boolean;
|
|
14
|
+
/** Activity rows shown in the expanded worker UI. */
|
|
15
|
+
export declare function isDisplayableActivity(activity: Pick<ToolActivity, "toolName">): boolean;
|
|
12
16
|
export declare function activitySummary(toolName: string, args: unknown): string;
|
|
17
|
+
/** Convert one persisted activity summary into the compact call-shaped UI label. */
|
|
18
|
+
export declare function activityCallText(activity: Pick<ToolActivity, "toolName" | "summary">): string;
|
|
13
19
|
export declare function formatTokens(value: number): string;
|
|
14
20
|
/**
|
|
15
21
|
* Activity summary for the synthetic auto-compaction entry. The before/after
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,wEAAyE,CAAC;AAEvG,wBAAgB,UAAU,IAAI,aAAa,CAW1C;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI,CAO9E;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAQ7E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,KAAK,CAezD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,CAMvE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAM5E;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,OAAO,CAErF;AAED,qDAAqD;AACrD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,OAAO,CAEvF;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAevE;AAgBD,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC,GAAG,MAAM,CAqC7F;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG3G;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAoBrD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TASK_OUTPUT_LIMIT } from "./constants.js";
|
|
2
|
-
import { boundText } from "./text.js";
|
|
1
|
+
import { COMPACTION_ACTIVITY_ID, TASK_OUTPUT_LIMIT } from "./constants.js";
|
|
2
|
+
import { boundText, plainLine } from "./text.js";
|
|
3
3
|
/** The usage fields that are summed when aggregating. */
|
|
4
4
|
export const USAGE_SUM_FIELDS = ["input", "output", "cacheRead", "cacheWrite", "totalTokens"];
|
|
5
5
|
export function emptyUsage() {
|
|
@@ -67,21 +67,84 @@ export function finalAssistantText(messages) {
|
|
|
67
67
|
}
|
|
68
68
|
return "";
|
|
69
69
|
}
|
|
70
|
+
/** Synthetic lifecycle entries stay persisted but do not count as worker tool calls. */
|
|
71
|
+
export function isSyntheticActivity(activity) {
|
|
72
|
+
return activity.toolName === COMPACTION_ACTIVITY_ID;
|
|
73
|
+
}
|
|
74
|
+
/** Activity rows shown in the expanded worker UI. */
|
|
75
|
+
export function isDisplayableActivity(activity) {
|
|
76
|
+
return !isSyntheticActivity(activity);
|
|
77
|
+
}
|
|
70
78
|
export function activitySummary(toolName, args) {
|
|
71
79
|
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
72
80
|
return toolName;
|
|
73
81
|
const input = args;
|
|
74
82
|
const path = typeof input.path === "string" ? input.path : typeof input.file_path === "string" ? input.file_path : undefined;
|
|
83
|
+
const pattern = typeof input.pattern === "string" ? input.pattern : undefined;
|
|
75
84
|
if (toolName === "bash" && typeof input.command === "string")
|
|
76
85
|
return `Run ${boundText(input.command.replace(/\s+/gu, " "), 160)}`;
|
|
86
|
+
if (toolName === "find" && pattern !== undefined) {
|
|
87
|
+
const displayPattern = pattern.trim() || '""';
|
|
88
|
+
return `Find ${boundText(displayPattern, 120)}`;
|
|
89
|
+
}
|
|
77
90
|
if (path)
|
|
78
91
|
return `${toolName} ${boundText(path, 180)}`;
|
|
79
|
-
if (toolName === "grep" &&
|
|
80
|
-
return `Search ${boundText(
|
|
81
|
-
if (toolName === "find" && typeof input.pattern === "string")
|
|
82
|
-
return `Find ${boundText(input.pattern, 120)}`;
|
|
92
|
+
if (toolName === "grep" && pattern)
|
|
93
|
+
return `Search ${boundText(pattern, 120)}`;
|
|
83
94
|
return toolName;
|
|
84
95
|
}
|
|
96
|
+
const OUTPUT_TRUNCATION_NOTICE_PATTERN = /\s*\[Output truncated(?:: \d+ bytes omitted)?\.\]\s*$/u;
|
|
97
|
+
function displayActivityLine(text) {
|
|
98
|
+
return plainLine(text).replace(OUTPUT_TRUNCATION_NOTICE_PATTERN, "...").trim();
|
|
99
|
+
}
|
|
100
|
+
function stripActivityPrefix(summary, prefixes) {
|
|
101
|
+
for (const prefix of prefixes) {
|
|
102
|
+
if (summary === prefix)
|
|
103
|
+
return "";
|
|
104
|
+
if (summary.startsWith(`${prefix} `))
|
|
105
|
+
return summary.slice(prefix.length + 1).trim();
|
|
106
|
+
}
|
|
107
|
+
return summary;
|
|
108
|
+
}
|
|
109
|
+
/** Convert one persisted activity summary into the compact call-shaped UI label. */
|
|
110
|
+
export function activityCallText(activity) {
|
|
111
|
+
const summary = displayActivityLine(activity.summary);
|
|
112
|
+
let label;
|
|
113
|
+
let detail;
|
|
114
|
+
switch (activity.toolName) {
|
|
115
|
+
case "bash":
|
|
116
|
+
label = "Run";
|
|
117
|
+
detail = stripActivityPrefix(summary, ["Run", "bash"]);
|
|
118
|
+
break;
|
|
119
|
+
case "read":
|
|
120
|
+
label = "Read";
|
|
121
|
+
detail = stripActivityPrefix(summary, ["Read", "read"]);
|
|
122
|
+
break;
|
|
123
|
+
case "grep":
|
|
124
|
+
label = "Grep";
|
|
125
|
+
detail = stripActivityPrefix(summary, ["Grep", "grep", "Search"]);
|
|
126
|
+
break;
|
|
127
|
+
case "find":
|
|
128
|
+
label = "Find";
|
|
129
|
+
detail = stripActivityPrefix(summary, ["Find", "find"]);
|
|
130
|
+
break;
|
|
131
|
+
case "ls":
|
|
132
|
+
label = "List";
|
|
133
|
+
detail = stripActivityPrefix(summary, ["List", "ls"]) || ".";
|
|
134
|
+
break;
|
|
135
|
+
case "edit":
|
|
136
|
+
label = "Edit";
|
|
137
|
+
detail = stripActivityPrefix(summary, ["Edit", "edit"]);
|
|
138
|
+
break;
|
|
139
|
+
case "write":
|
|
140
|
+
label = "Write";
|
|
141
|
+
detail = stripActivityPrefix(summary, ["Write", "write"]);
|
|
142
|
+
break;
|
|
143
|
+
default:
|
|
144
|
+
return summary || activity.toolName;
|
|
145
|
+
}
|
|
146
|
+
return detail ? `${label}(${detail})` : label;
|
|
147
|
+
}
|
|
85
148
|
export function formatTokens(value) {
|
|
86
149
|
if (value < 1_000)
|
|
87
150
|
return String(value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../../../src/extensions/subagent/activity.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,CAAU,CAAC;AAEvG,MAAM,UAAU,UAAU;IACzB,OAAO;QACN,KAAK,EAAE,CAAC;QACR,QAAQ,EAAE,CAAC;QACX,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,CAAC;QACb,WAAW,EAAE,CAAC;QACd,IAAI,EAAE,CAAC;KACP,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAqB,EAAE,KAAwB;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,KAAK,MAAM,KAAK,IAAI,gBAAgB;QAAE,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,CAAC;IACtC,wEAAwE;IACxE,0DAA0D;IAC1D,IAAI,KAAK,CAAC,WAAW;QAAE,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC,WAAW,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAqB,EAAE,MAAqB;IACtE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;IAC7B,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,gBAAgB;QAAE,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IACrE,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC;IAC3B,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IAClF,CAAC;AACF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAoB;IACjD,OAAO;QACN,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI,EAAE;YACL,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,CAAC;YACb,KAAK,EAAE,KAAK,CAAC,IAAI;SACjB;KACD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAiC;IAC9D,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,EAAE,CAAC;IACxD,OAAO,OAAO,CAAC,OAAO;SACpB,MAAM,CAAC,CAAC,IAAI,EAA0C,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;SAC9E,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SACxB,IAAI,CAAC,EAAE,CAAC,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAiC;IACnE,KAAK,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3D,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,IAAI,IAAI;YAAE,OAAO,SAAS,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAa;IAC9D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9E,MAAM,KAAK,GAAG,IAA+B,CAAC;IAC9C,MAAM,IAAI,GACT,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACjH,IAAI,QAAQ,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QAC3D,OAAO,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IACrE,IAAI,IAAI;QAAE,OAAO,GAAG,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;IACvD,IAAI,QAAQ,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,UAAU,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;IAC/G,IAAI,QAAQ,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,QAAQ,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;IAC7G,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa;IACzC,IAAI,KAAK,GAAG,KAAK;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,KAAK,GAAG,SAAS;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACpF,OAAO,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAgC,EAAE,WAA+B;IAClG,IAAI,YAAY,IAAI,WAAW;QAAE,OAAO,aAAa,YAAY,CAAC,YAAY,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC;IACjH,OAAO,iBAAiB,CAAC;AAC1B,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,eAAe,CAAC,KAAa;IAC5C,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAe;IAC5C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACrD,MAAM,OAAO,GAAI,MAAgC,CAAC,OAAO,CAAC;IAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,SAAS,CACf,OAAO;SACL,MAAM,CAAC,CAAC,IAAI,EAA0C,EAAE;QACxD,OAAO,OAAO,CACb,IAAI;YACH,OAAO,IAAI,KAAK,QAAQ;YACvB,IAA2B,CAAC,IAAI,KAAK,MAAM;YAC5C,OAAQ,IAA2B,CAAC,IAAI,KAAK,QAAQ,CACtD,CAAC;IACH,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SACxB,IAAI,CAAC,IAAI,CAAC;SACV,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,IAAI,EAAE,EACR,GAAG,CACH,CAAC;AACH,CAAC","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai\";\nimport { TASK_OUTPUT_LIMIT } from \"./constants.ts\";\nimport { boundText } from \"./text.ts\";\nimport type { SubagentUsage } from \"./types.ts\";\n\n/** The usage fields that are summed when aggregating. */\nexport const USAGE_SUM_FIELDS = [\"input\", \"output\", \"cacheRead\", \"cacheWrite\", \"totalTokens\"] as const;\n\nexport function emptyUsage(): SubagentUsage {\n\treturn {\n\t\tturns: 0,\n\t\ttoolUses: 0,\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tcost: 0,\n\t};\n}\n\nexport function addUsage(target: SubagentUsage, usage: Usage | undefined): void {\n\tif (!usage) return;\n\tfor (const field of USAGE_SUM_FIELDS) target[field] += usage[field] ?? 0;\n\ttarget.cost += usage.cost?.total ?? 0;\n\t// Watermark, not a sum: the latest request's total is the context size,\n\t// and it can shrink again after the worker auto-compacts.\n\tif (usage.totalTokens) target.contextTokens = usage.totalTokens;\n}\n\nexport function mergeUsage(target: SubagentUsage, source: SubagentUsage): void {\n\ttarget.turns += source.turns;\n\ttarget.toolUses += source.toolUses;\n\tfor (const field of USAGE_SUM_FIELDS) target[field] += source[field];\n\ttarget.cost += source.cost;\n\tif (source.contextTokens) {\n\t\ttarget.contextTokens = Math.max(target.contextTokens ?? 0, source.contextTokens);\n\t}\n}\n\nexport function toNestedUsage(usage: SubagentUsage): Usage {\n\treturn {\n\t\tinput: usage.input,\n\t\toutput: usage.output,\n\t\tcacheRead: usage.cacheRead,\n\t\tcacheWrite: usage.cacheWrite,\n\t\ttotalTokens: usage.totalTokens,\n\t\tcost: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotal: usage.cost,\n\t\t},\n\t};\n}\n\nexport function assistantText(message: AgentMessage | undefined): string {\n\tif (!message || message.role !== \"assistant\") return \"\";\n\treturn message.content\n\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\");\n}\n\nexport function finalAssistantText(messages: readonly AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst text = assistantText(messages[index]);\n\t\tif (text) return boundText(text, TASK_OUTPUT_LIMIT);\n\t}\n\treturn \"\";\n}\n\nexport function activitySummary(toolName: string, args: unknown): string {\n\tif (!args || typeof args !== \"object\" || Array.isArray(args)) return toolName;\n\tconst input = args as Record<string, unknown>;\n\tconst path =\n\t\ttypeof input.path === \"string\" ? input.path : typeof input.file_path === \"string\" ? input.file_path : undefined;\n\tif (toolName === \"bash\" && typeof input.command === \"string\")\n\t\treturn `Run ${boundText(input.command.replace(/\\s+/gu, \" \"), 160)}`;\n\tif (path) return `${toolName} ${boundText(path, 180)}`;\n\tif (toolName === \"grep\" && typeof input.pattern === \"string\") return `Search ${boundText(input.pattern, 120)}`;\n\tif (toolName === \"find\" && typeof input.pattern === \"string\") return `Find ${boundText(input.pattern, 120)}`;\n\treturn toolName;\n}\n\nexport function formatTokens(value: number): string {\n\tif (value < 1_000) return String(value);\n\tif (value < 1_000_000) return `${(value / 1_000).toFixed(value < 10_000 ? 1 : 0)}k`;\n\treturn `${(value / 1_000_000).toFixed(1)}M`;\n}\n\n/**\n * Activity summary for the synthetic auto-compaction entry. The before/after\n * pair is only known once a compaction succeeds; a failed or aborted one keeps\n * the neutral label and carries its reason in the entry's resultSummary.\n */\nexport function compactionSummary(tokensBefore: number | undefined, tokensAfter: number | undefined): string {\n\tif (tokensBefore && tokensAfter) return `Compacted ${formatTokens(tokensBefore)} → ${formatTokens(tokensAfter)}`;\n\treturn \"Compact context\";\n}\n\n/** Failure reason for the compaction activity; bounded like {@link resultSummary}. */\nexport function compactionError(error: string): string {\n\treturn boundText(error.replace(/\\s+/gu, \" \").trim(), 240);\n}\n\n/**\n * Extracts a short text summary from a tool result's content array.\n * Accepts `unknown` because SDK event payloads carry loosely-typed result\n * objects; the function defensively narrows to the text-content shape.\n */\nexport function resultSummary(result: unknown): string {\n\tif (!result || typeof result !== \"object\") return \"\";\n\tconst content = (result as { content?: unknown }).content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn boundText(\n\t\tcontent\n\t\t\t.filter((part): part is { type: \"text\"; text: string } => {\n\t\t\t\treturn Boolean(\n\t\t\t\t\tpart &&\n\t\t\t\t\t\ttypeof part === \"object\" &&\n\t\t\t\t\t\t(part as { type?: unknown }).type === \"text\" &&\n\t\t\t\t\t\ttypeof (part as { text?: unknown }).text === \"string\",\n\t\t\t\t);\n\t\t\t})\n\t\t\t.map((part) => part.text)\n\t\t\t.join(\"\\n\")\n\t\t\t.replace(/\\s+/gu, \" \")\n\t\t\t.trim(),\n\t\t240,\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../../../src/extensions/subagent/activity.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai\";\nimport { COMPACTION_ACTIVITY_ID, TASK_OUTPUT_LIMIT } from \"./constants.ts\";\nimport { boundText, plainLine } from \"./text.ts\";\nimport type { SubagentUsage, ToolActivity } from \"./types.ts\";\n\n/** The usage fields that are summed when aggregating. */\nexport const USAGE_SUM_FIELDS = [\"input\", \"output\", \"cacheRead\", \"cacheWrite\", \"totalTokens\"] as const;\n\nexport function emptyUsage(): SubagentUsage {\n\treturn {\n\t\tturns: 0,\n\t\ttoolUses: 0,\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tcost: 0,\n\t};\n}\n\nexport function addUsage(target: SubagentUsage, usage: Usage | undefined): void {\n\tif (!usage) return;\n\tfor (const field of USAGE_SUM_FIELDS) target[field] += usage[field] ?? 0;\n\ttarget.cost += usage.cost?.total ?? 0;\n\t// Watermark, not a sum: the latest request's total is the context size,\n\t// and it can shrink again after the worker auto-compacts.\n\tif (usage.totalTokens) target.contextTokens = usage.totalTokens;\n}\n\nexport function mergeUsage(target: SubagentUsage, source: SubagentUsage): void {\n\ttarget.turns += source.turns;\n\ttarget.toolUses += source.toolUses;\n\tfor (const field of USAGE_SUM_FIELDS) target[field] += source[field];\n\ttarget.cost += source.cost;\n\tif (source.contextTokens) {\n\t\ttarget.contextTokens = Math.max(target.contextTokens ?? 0, source.contextTokens);\n\t}\n}\n\nexport function toNestedUsage(usage: SubagentUsage): Usage {\n\treturn {\n\t\tinput: usage.input,\n\t\toutput: usage.output,\n\t\tcacheRead: usage.cacheRead,\n\t\tcacheWrite: usage.cacheWrite,\n\t\ttotalTokens: usage.totalTokens,\n\t\tcost: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotal: usage.cost,\n\t\t},\n\t};\n}\n\nexport function assistantText(message: AgentMessage | undefined): string {\n\tif (!message || message.role !== \"assistant\") return \"\";\n\treturn message.content\n\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\");\n}\n\nexport function finalAssistantText(messages: readonly AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst text = assistantText(messages[index]);\n\t\tif (text) return boundText(text, TASK_OUTPUT_LIMIT);\n\t}\n\treturn \"\";\n}\n\n/** Synthetic lifecycle entries stay persisted but do not count as worker tool calls. */\nexport function isSyntheticActivity(activity: Pick<ToolActivity, \"toolName\">): boolean {\n\treturn activity.toolName === COMPACTION_ACTIVITY_ID;\n}\n\n/** Activity rows shown in the expanded worker UI. */\nexport function isDisplayableActivity(activity: Pick<ToolActivity, \"toolName\">): boolean {\n\treturn !isSyntheticActivity(activity);\n}\n\nexport function activitySummary(toolName: string, args: unknown): string {\n\tif (!args || typeof args !== \"object\" || Array.isArray(args)) return toolName;\n\tconst input = args as Record<string, unknown>;\n\tconst path =\n\t\ttypeof input.path === \"string\" ? input.path : typeof input.file_path === \"string\" ? input.file_path : undefined;\n\tconst pattern = typeof input.pattern === \"string\" ? input.pattern : undefined;\n\tif (toolName === \"bash\" && typeof input.command === \"string\")\n\t\treturn `Run ${boundText(input.command.replace(/\\s+/gu, \" \"), 160)}`;\n\tif (toolName === \"find\" && pattern !== undefined) {\n\t\tconst displayPattern = pattern.trim() || '\"\"';\n\t\treturn `Find ${boundText(displayPattern, 120)}`;\n\t}\n\tif (path) return `${toolName} ${boundText(path, 180)}`;\n\tif (toolName === \"grep\" && pattern) return `Search ${boundText(pattern, 120)}`;\n\treturn toolName;\n}\n\nconst OUTPUT_TRUNCATION_NOTICE_PATTERN = /\\s*\\[Output truncated(?:: \\d+ bytes omitted)?\\.\\]\\s*$/u;\n\nfunction displayActivityLine(text: string): string {\n\treturn plainLine(text).replace(OUTPUT_TRUNCATION_NOTICE_PATTERN, \"...\").trim();\n}\n\nfunction stripActivityPrefix(summary: string, prefixes: readonly string[]): string {\n\tfor (const prefix of prefixes) {\n\t\tif (summary === prefix) return \"\";\n\t\tif (summary.startsWith(`${prefix} `)) return summary.slice(prefix.length + 1).trim();\n\t}\n\treturn summary;\n}\n\n/** Convert one persisted activity summary into the compact call-shaped UI label. */\nexport function activityCallText(activity: Pick<ToolActivity, \"toolName\" | \"summary\">): string {\n\tconst summary = displayActivityLine(activity.summary);\n\tlet label: string;\n\tlet detail: string;\n\tswitch (activity.toolName) {\n\t\tcase \"bash\":\n\t\t\tlabel = \"Run\";\n\t\t\tdetail = stripActivityPrefix(summary, [\"Run\", \"bash\"]);\n\t\t\tbreak;\n\t\tcase \"read\":\n\t\t\tlabel = \"Read\";\n\t\t\tdetail = stripActivityPrefix(summary, [\"Read\", \"read\"]);\n\t\t\tbreak;\n\t\tcase \"grep\":\n\t\t\tlabel = \"Grep\";\n\t\t\tdetail = stripActivityPrefix(summary, [\"Grep\", \"grep\", \"Search\"]);\n\t\t\tbreak;\n\t\tcase \"find\":\n\t\t\tlabel = \"Find\";\n\t\t\tdetail = stripActivityPrefix(summary, [\"Find\", \"find\"]);\n\t\t\tbreak;\n\t\tcase \"ls\":\n\t\t\tlabel = \"List\";\n\t\t\tdetail = stripActivityPrefix(summary, [\"List\", \"ls\"]) || \".\";\n\t\t\tbreak;\n\t\tcase \"edit\":\n\t\t\tlabel = \"Edit\";\n\t\t\tdetail = stripActivityPrefix(summary, [\"Edit\", \"edit\"]);\n\t\t\tbreak;\n\t\tcase \"write\":\n\t\t\tlabel = \"Write\";\n\t\t\tdetail = stripActivityPrefix(summary, [\"Write\", \"write\"]);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn summary || activity.toolName;\n\t}\n\treturn detail ? `${label}(${detail})` : label;\n}\n\nexport function formatTokens(value: number): string {\n\tif (value < 1_000) return String(value);\n\tif (value < 1_000_000) return `${(value / 1_000).toFixed(value < 10_000 ? 1 : 0)}k`;\n\treturn `${(value / 1_000_000).toFixed(1)}M`;\n}\n\n/**\n * Activity summary for the synthetic auto-compaction entry. The before/after\n * pair is only known once a compaction succeeds; a failed or aborted one keeps\n * the neutral label and carries its reason in the entry's resultSummary.\n */\nexport function compactionSummary(tokensBefore: number | undefined, tokensAfter: number | undefined): string {\n\tif (tokensBefore && tokensAfter) return `Compacted ${formatTokens(tokensBefore)} → ${formatTokens(tokensAfter)}`;\n\treturn \"Compact context\";\n}\n\n/** Failure reason for the compaction activity; bounded like {@link resultSummary}. */\nexport function compactionError(error: string): string {\n\treturn boundText(error.replace(/\\s+/gu, \" \").trim(), 240);\n}\n\n/**\n * Extracts a short text summary from a tool result's content array.\n * Accepts `unknown` because SDK event payloads carry loosely-typed result\n * objects; the function defensively narrows to the text-content shape.\n */\nexport function resultSummary(result: unknown): string {\n\tif (!result || typeof result !== \"object\") return \"\";\n\tconst content = (result as { content?: unknown }).content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn boundText(\n\t\tcontent\n\t\t\t.filter((part): part is { type: \"text\"; text: string } => {\n\t\t\t\treturn Boolean(\n\t\t\t\t\tpart &&\n\t\t\t\t\t\ttypeof part === \"object\" &&\n\t\t\t\t\t\t(part as { type?: unknown }).type === \"text\" &&\n\t\t\t\t\t\ttypeof (part as { text?: unknown }).text === \"string\",\n\t\t\t\t);\n\t\t\t})\n\t\t\t.map((part) => part.text)\n\t\t\t.join(\"\\n\")\n\t\t\t.replace(/\\s+/gu, \" \")\n\t\t\t.trim(),\n\t\t240,\n\t);\n}\n"]}
|
|
@@ -206,7 +206,7 @@ class AgentsMenuComponent extends Container {
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
async function showTuiAgentsCommand(ctx, currentThinking) {
|
|
209
|
-
const config = await loadSubagentConfig(getAgentDir());
|
|
209
|
+
const config = await loadSubagentConfig(getAgentDir(), (message) => ctx.ui.notify(message, "warning"));
|
|
210
210
|
await ctx.ui.custom((tui, theme, keybindings, done) => new AgentsMenuComponent({
|
|
211
211
|
tui,
|
|
212
212
|
theme,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-command.js","sourceRoot":"","sources":["../../../src/extensions/subagent/agents-command.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tisFocusable,\n\ttype KeybindingsManager,\n\ttype TUI,\n} from \"@earendil-works/pi-tui\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/types.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { AGENT_PROFILE_LABELS, AGENT_PROFILES } from \"./agents.ts\";\nimport { loadSubagentConfig, updateProfileOverride } from \"./settings.ts\";\nimport type { AgentProfile, SubagentConfigFile, SubagentProfileOverride } from \"./types.ts\";\nimport { showDialogAgentsCommand } from \"./ui/agents-dialog.ts\";\nimport { ChoiceMenuComponent } from \"./ui/choice-menu.ts\";\nimport { buildThinkingChoices, type SettingsAction } from \"./ui/choices.ts\";\nimport { ModelPickerComponent, refreshPickerModels } from \"./ui/model-picker.ts\";\nimport { ProfileSettingsMenuComponent } from \"./ui/profile-settings-menu.ts\";\n\n/** Persist a single override atomically; the UI only reflects the value on success. */\nasync function persistOverride(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\tpatch: Partial<SubagentProfileOverride>,\n): Promise<SubagentConfigFile | undefined> {\n\ttry {\n\t\treturn await updateProfileOverride(profile.name, patch, getAgentDir());\n\t} catch (error) {\n\t\tctx.ui.notify(\n\t\t\t`Could not save ${AGENT_PROFILE_LABELS[profile.name]} settings: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\"error\",\n\t\t);\n\t\treturn undefined;\n\t}\n}\n\ntype AgentsMenuRoute =\n\t| { kind: \"profiles\" }\n\t| { kind: \"settings\"; profile: AgentProfile; selectedAction: SettingsAction }\n\t| { kind: \"model\"; profile: AgentProfile }\n\t| { kind: \"thinking\"; profile: AgentProfile };\n\n/** One mounted /agents TUI whose child pages switch without restoring the editor between them. */\nclass AgentsMenuComponent extends Container implements Focusable {\n\tprivate readonly tui: TUI;\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly ctx: ExtensionCommandContext;\n\tprivate readonly currentThinking: ThinkingLevel;\n\tprivate readonly onDone: () => void;\n\tprivate config: SubagentConfigFile;\n\tprivate activeScreen: (Component & { dispose?(): void }) | undefined;\n\tprivate route: AgentsMenuRoute = { kind: \"profiles\" };\n\tprivate selectedProfile: AgentProfile | undefined;\n\tprivate selectedSettingsAction: SettingsAction = \"model\";\n\tprivate saving = false;\n\tprivate closed = false;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tif (this.activeScreen && isFocusable(this.activeScreen)) this.activeScreen.focused = value;\n\t}\n\n\tconstructor(options: {\n\t\ttui: TUI;\n\t\ttheme: Theme;\n\t\tkeybindings: KeybindingsManager;\n\t\tctx: ExtensionCommandContext;\n\t\tcurrentThinking: ThinkingLevel;\n\t\tconfig: SubagentConfigFile;\n\t\tonDone: () => void;\n\t}) {\n\t\tsuper();\n\t\tthis.tui = options.tui;\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.ctx = options.ctx;\n\t\tthis.currentThinking = options.currentThinking;\n\t\tthis.config = options.config;\n\t\tthis.onDone = options.onDone;\n\t\tthis.showProfiles();\n\t}\n\n\tprivate disposeActiveScreen(): void {\n\t\tconst screen = this.activeScreen;\n\t\tthis.activeScreen = undefined;\n\t\tif (!screen) return;\n\t\tconst disposable = screen as Component & { dispose?(): void };\n\t\tif (isFocusable(screen)) screen.focused = false;\n\t\tdisposable.dispose?.();\n\t}\n\n\tprivate setActiveScreen(screen: Component & { dispose?(): void }): void {\n\t\tthis.disposeActiveScreen();\n\t\tthis.clear();\n\t\tthis.activeScreen = screen;\n\t\tthis.addChild(screen);\n\t\tif (isFocusable(screen)) screen.focused = this._focused;\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate showProfiles(): void {\n\t\tthis.route = { kind: \"profiles\" };\n\t\tconst choices = AGENT_PROFILES.map((profile) => ({\n\t\t\tlabel: AGENT_PROFILE_LABELS[profile.name],\n\t\t\tvalue: profile,\n\t\t}));\n\t\tconst initialIndex = choices.findIndex((choice) => choice.value.name === this.selectedProfile?.name);\n\t\tthis.setActiveScreen(\n\t\t\tnew ChoiceMenuComponent({\n\t\t\t\ttheme: this.theme,\n\t\t\t\tkeybindings: this.keybindings,\n\t\t\t\ttitle: \"Agents\",\n\t\t\t\tchoices,\n\t\t\t\tinitialIndex,\n\t\t\t\tcancelDescription: \"close\",\n\t\t\t\tonDone: (choice) => {\n\t\t\t\t\tif (!choice) {\n\t\t\t\t\t\tthis.onDone();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.selectedProfile = choice.value;\n\t\t\t\t\tthis.selectedSettingsAction = \"model\";\n\t\t\t\t\tthis.showSettings(choice.value);\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate showSettings(profile: AgentProfile, selectedAction = this.selectedSettingsAction): void {\n\t\tthis.selectedProfile = profile;\n\t\tthis.selectedSettingsAction = selectedAction;\n\t\tthis.route = { kind: \"settings\", profile, selectedAction };\n\t\tthis.setActiveScreen(\n\t\t\tnew ProfileSettingsMenuComponent({\n\t\t\t\ttheme: this.theme,\n\t\t\t\tkeybindings: this.keybindings,\n\t\t\t\tprofile,\n\t\t\t\toverride: this.config.profiles[profile.name],\n\t\t\t\tmodels: this.ctx.modelRegistry.getAvailable(),\n\t\t\t\tcurrentSessionModel: this.ctx.model,\n\t\t\t\tcurrentThinking: this.currentThinking,\n\t\t\t\tselectedAction,\n\t\t\t\tstatus: this.saving ? \"Saving…\" : undefined,\n\t\t\t\tonDone: (action) => {\n\t\t\t\t\tif (!action) {\n\t\t\t\t\t\tthis.showProfiles();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.selectedSettingsAction = action;\n\t\t\t\t\tif (action === \"model\") this.showModelPicker(profile);\n\t\t\t\t\telse this.showThinkingPicker(profile);\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate showModelPicker(profile: AgentProfile): void {\n\t\tthis.route = { kind: \"model\", profile };\n\t\tconst override = this.config.profiles[profile.name];\n\t\tconst picker = new ModelPickerComponent({\n\t\t\ttui: this.tui,\n\t\t\ttheme: this.theme,\n\t\t\tkeybindings: this.keybindings,\n\t\t\tprofile,\n\t\t\tsavedModelId: override?.model,\n\t\t\tmodels: this.ctx.modelRegistry.getAvailable(),\n\t\t\tscopedModels: this.ctx.scopedModels,\n\t\t\tcurrentSessionModel: this.ctx.model,\n\t\t\tonDone: (choice) => {\n\t\t\t\tif (!choice) {\n\t\t\t\t\tthis.showSettings(profile, \"model\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.saveOverride(profile, { model: choice.modelId }, \"model\");\n\t\t\t},\n\t\t});\n\t\tpicker.setRefreshStatus(\"Refreshing model catalogs…\");\n\t\tthis.setActiveScreen(picker);\n\t\tvoid refreshPickerModels(this.ctx, picker);\n\t}\n\n\tprivate showThinkingPicker(profile: AgentProfile): void {\n\t\tthis.route = { kind: \"thinking\", profile };\n\t\tconst override = this.config.profiles[profile.name];\n\t\tconst choices = [\n\t\t\t...buildThinkingChoices({\n\t\t\t\tcurrentSessionModel: this.ctx.model,\n\t\t\t\tmodels: this.ctx.modelRegistry.getAvailable(),\n\t\t\t\toverride,\n\t\t\t\tcurrentThinking: this.currentThinking,\n\t\t\t}).entries(),\n\t\t].map(([label, level]) => ({ label, value: level }));\n\t\tconst initialIndex = choices.findIndex((choice) => choice.label.endsWith(\" ✓\"));\n\t\tthis.setActiveScreen(\n\t\t\tnew ChoiceMenuComponent({\n\t\t\t\ttheme: this.theme,\n\t\t\t\tkeybindings: this.keybindings,\n\t\t\t\ttitle: `Thinking — ${AGENT_PROFILE_LABELS[profile.name]}`,\n\t\t\t\tchoices,\n\t\t\t\tinitialIndex,\n\t\t\t\tcancelDescription: \"back\",\n\t\t\t\tonDone: (choice) => {\n\t\t\t\t\tif (!choice) {\n\t\t\t\t\t\tthis.showSettings(profile, \"thinking\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.saveOverride(profile, { thinking: choice.value }, \"thinking\");\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate saveOverride(\n\t\tprofile: AgentProfile,\n\t\tpatch: Partial<SubagentProfileOverride>,\n\t\treturnAction: SettingsAction,\n\t): void {\n\t\tif (this.saving) return;\n\t\tthis.saving = true;\n\t\tthis.showSettings(profile, returnAction);\n\t\tvoid persistOverride(this.ctx, profile, patch)\n\t\t\t.then(\n\t\t\t\t(config) => this.completeSave(profile, config),\n\t\t\t\t() => this.completeSave(profile, undefined),\n\t\t\t)\n\t\t\t.catch(() => {\n\t\t\t\t// A reload can stale the command context while the queued file write finishes.\n\t\t\t});\n\t}\n\n\tprivate completeSave(profile: AgentProfile, config: SubagentConfigFile | undefined): void {\n\t\tif (this.closed) return;\n\t\tthis.saving = false;\n\t\tif (config) this.config = config;\n\t\tif (this.route.kind === \"settings\" && this.route.profile.name === profile.name) {\n\t\t\tthis.showSettings(profile, this.route.selectedAction);\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this.saving) {\n\t\t\tthis.activeScreen?.handleInput?.(data);\n\t\t\treturn;\n\t\t}\n\t\tif (!this.keybindings.matches(data, \"tui.select.cancel\")) return;\n\t\tif (this.route.kind === \"settings\") this.showProfiles();\n\t\telse if (this.route.kind === \"profiles\") this.onDone();\n\t}\n\n\tdispose(): void {\n\t\tthis.closed = true;\n\t\tthis.disposeActiveScreen();\n\t\tthis.clear();\n\t}\n}\n\nasync function showTuiAgentsCommand(ctx: ExtensionCommandContext, currentThinking: ThinkingLevel): Promise<void> {\n\tconst config = await loadSubagentConfig(getAgentDir());\n\tawait ctx.ui.custom<void>(\n\t\t(tui, theme, keybindings, done) =>\n\t\t\tnew AgentsMenuComponent({\n\t\t\t\ttui,\n\t\t\t\ttheme,\n\t\t\t\tkeybindings,\n\t\t\t\tctx,\n\t\t\t\tcurrentThinking,\n\t\t\t\tconfig,\n\t\t\t\tonDone: () => done(),\n\t\t\t}),\n\t);\n}\n\nexport async function showAgentsCommand(ctx: ExtensionCommandContext, currentThinking: ThinkingLevel): Promise<void> {\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(\"/agents requires an interactive UI.\", \"warning\");\n\t\treturn;\n\t}\n\tif (ctx.mode === \"tui\") await showTuiAgentsCommand(ctx, currentThinking);\n\telse await showDialogAgentsCommand(ctx, currentThinking);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agents-command.js","sourceRoot":"","sources":["../../../src/extensions/subagent/agents-command.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tisFocusable,\n\ttype KeybindingsManager,\n\ttype TUI,\n} from \"@earendil-works/pi-tui\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/types.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { AGENT_PROFILE_LABELS, AGENT_PROFILES } from \"./agents.ts\";\nimport { loadSubagentConfig, updateProfileOverride } from \"./settings.ts\";\nimport type { AgentProfile, SubagentConfigFile, SubagentProfileOverride } from \"./types.ts\";\nimport { showDialogAgentsCommand } from \"./ui/agents-dialog.ts\";\nimport { ChoiceMenuComponent } from \"./ui/choice-menu.ts\";\nimport { buildThinkingChoices, type SettingsAction } from \"./ui/choices.ts\";\nimport { ModelPickerComponent, refreshPickerModels } from \"./ui/model-picker.ts\";\nimport { ProfileSettingsMenuComponent } from \"./ui/profile-settings-menu.ts\";\n\n/** Persist a single override atomically; the UI only reflects the value on success. */\nasync function persistOverride(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\tpatch: Partial<SubagentProfileOverride>,\n): Promise<SubagentConfigFile | undefined> {\n\ttry {\n\t\treturn await updateProfileOverride(profile.name, patch, getAgentDir());\n\t} catch (error) {\n\t\tctx.ui.notify(\n\t\t\t`Could not save ${AGENT_PROFILE_LABELS[profile.name]} settings: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\"error\",\n\t\t);\n\t\treturn undefined;\n\t}\n}\n\ntype AgentsMenuRoute =\n\t| { kind: \"profiles\" }\n\t| { kind: \"settings\"; profile: AgentProfile; selectedAction: SettingsAction }\n\t| { kind: \"model\"; profile: AgentProfile }\n\t| { kind: \"thinking\"; profile: AgentProfile };\n\n/** One mounted /agents TUI whose child pages switch without restoring the editor between them. */\nclass AgentsMenuComponent extends Container implements Focusable {\n\tprivate readonly tui: TUI;\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly ctx: ExtensionCommandContext;\n\tprivate readonly currentThinking: ThinkingLevel;\n\tprivate readonly onDone: () => void;\n\tprivate config: SubagentConfigFile;\n\tprivate activeScreen: (Component & { dispose?(): void }) | undefined;\n\tprivate route: AgentsMenuRoute = { kind: \"profiles\" };\n\tprivate selectedProfile: AgentProfile | undefined;\n\tprivate selectedSettingsAction: SettingsAction = \"model\";\n\tprivate saving = false;\n\tprivate closed = false;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tif (this.activeScreen && isFocusable(this.activeScreen)) this.activeScreen.focused = value;\n\t}\n\n\tconstructor(options: {\n\t\ttui: TUI;\n\t\ttheme: Theme;\n\t\tkeybindings: KeybindingsManager;\n\t\tctx: ExtensionCommandContext;\n\t\tcurrentThinking: ThinkingLevel;\n\t\tconfig: SubagentConfigFile;\n\t\tonDone: () => void;\n\t}) {\n\t\tsuper();\n\t\tthis.tui = options.tui;\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.ctx = options.ctx;\n\t\tthis.currentThinking = options.currentThinking;\n\t\tthis.config = options.config;\n\t\tthis.onDone = options.onDone;\n\t\tthis.showProfiles();\n\t}\n\n\tprivate disposeActiveScreen(): void {\n\t\tconst screen = this.activeScreen;\n\t\tthis.activeScreen = undefined;\n\t\tif (!screen) return;\n\t\tconst disposable = screen as Component & { dispose?(): void };\n\t\tif (isFocusable(screen)) screen.focused = false;\n\t\tdisposable.dispose?.();\n\t}\n\n\tprivate setActiveScreen(screen: Component & { dispose?(): void }): void {\n\t\tthis.disposeActiveScreen();\n\t\tthis.clear();\n\t\tthis.activeScreen = screen;\n\t\tthis.addChild(screen);\n\t\tif (isFocusable(screen)) screen.focused = this._focused;\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate showProfiles(): void {\n\t\tthis.route = { kind: \"profiles\" };\n\t\tconst choices = AGENT_PROFILES.map((profile) => ({\n\t\t\tlabel: AGENT_PROFILE_LABELS[profile.name],\n\t\t\tvalue: profile,\n\t\t}));\n\t\tconst initialIndex = choices.findIndex((choice) => choice.value.name === this.selectedProfile?.name);\n\t\tthis.setActiveScreen(\n\t\t\tnew ChoiceMenuComponent({\n\t\t\t\ttheme: this.theme,\n\t\t\t\tkeybindings: this.keybindings,\n\t\t\t\ttitle: \"Agents\",\n\t\t\t\tchoices,\n\t\t\t\tinitialIndex,\n\t\t\t\tcancelDescription: \"close\",\n\t\t\t\tonDone: (choice) => {\n\t\t\t\t\tif (!choice) {\n\t\t\t\t\t\tthis.onDone();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.selectedProfile = choice.value;\n\t\t\t\t\tthis.selectedSettingsAction = \"model\";\n\t\t\t\t\tthis.showSettings(choice.value);\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate showSettings(profile: AgentProfile, selectedAction = this.selectedSettingsAction): void {\n\t\tthis.selectedProfile = profile;\n\t\tthis.selectedSettingsAction = selectedAction;\n\t\tthis.route = { kind: \"settings\", profile, selectedAction };\n\t\tthis.setActiveScreen(\n\t\t\tnew ProfileSettingsMenuComponent({\n\t\t\t\ttheme: this.theme,\n\t\t\t\tkeybindings: this.keybindings,\n\t\t\t\tprofile,\n\t\t\t\toverride: this.config.profiles[profile.name],\n\t\t\t\tmodels: this.ctx.modelRegistry.getAvailable(),\n\t\t\t\tcurrentSessionModel: this.ctx.model,\n\t\t\t\tcurrentThinking: this.currentThinking,\n\t\t\t\tselectedAction,\n\t\t\t\tstatus: this.saving ? \"Saving…\" : undefined,\n\t\t\t\tonDone: (action) => {\n\t\t\t\t\tif (!action) {\n\t\t\t\t\t\tthis.showProfiles();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.selectedSettingsAction = action;\n\t\t\t\t\tif (action === \"model\") this.showModelPicker(profile);\n\t\t\t\t\telse this.showThinkingPicker(profile);\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate showModelPicker(profile: AgentProfile): void {\n\t\tthis.route = { kind: \"model\", profile };\n\t\tconst override = this.config.profiles[profile.name];\n\t\tconst picker = new ModelPickerComponent({\n\t\t\ttui: this.tui,\n\t\t\ttheme: this.theme,\n\t\t\tkeybindings: this.keybindings,\n\t\t\tprofile,\n\t\t\tsavedModelId: override?.model,\n\t\t\tmodels: this.ctx.modelRegistry.getAvailable(),\n\t\t\tscopedModels: this.ctx.scopedModels,\n\t\t\tcurrentSessionModel: this.ctx.model,\n\t\t\tonDone: (choice) => {\n\t\t\t\tif (!choice) {\n\t\t\t\t\tthis.showSettings(profile, \"model\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.saveOverride(profile, { model: choice.modelId }, \"model\");\n\t\t\t},\n\t\t});\n\t\tpicker.setRefreshStatus(\"Refreshing model catalogs…\");\n\t\tthis.setActiveScreen(picker);\n\t\tvoid refreshPickerModels(this.ctx, picker);\n\t}\n\n\tprivate showThinkingPicker(profile: AgentProfile): void {\n\t\tthis.route = { kind: \"thinking\", profile };\n\t\tconst override = this.config.profiles[profile.name];\n\t\tconst choices = [\n\t\t\t...buildThinkingChoices({\n\t\t\t\tcurrentSessionModel: this.ctx.model,\n\t\t\t\tmodels: this.ctx.modelRegistry.getAvailable(),\n\t\t\t\toverride,\n\t\t\t\tcurrentThinking: this.currentThinking,\n\t\t\t}).entries(),\n\t\t].map(([label, level]) => ({ label, value: level }));\n\t\tconst initialIndex = choices.findIndex((choice) => choice.label.endsWith(\" ✓\"));\n\t\tthis.setActiveScreen(\n\t\t\tnew ChoiceMenuComponent({\n\t\t\t\ttheme: this.theme,\n\t\t\t\tkeybindings: this.keybindings,\n\t\t\t\ttitle: `Thinking — ${AGENT_PROFILE_LABELS[profile.name]}`,\n\t\t\t\tchoices,\n\t\t\t\tinitialIndex,\n\t\t\t\tcancelDescription: \"back\",\n\t\t\t\tonDone: (choice) => {\n\t\t\t\t\tif (!choice) {\n\t\t\t\t\t\tthis.showSettings(profile, \"thinking\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.saveOverride(profile, { thinking: choice.value }, \"thinking\");\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate saveOverride(\n\t\tprofile: AgentProfile,\n\t\tpatch: Partial<SubagentProfileOverride>,\n\t\treturnAction: SettingsAction,\n\t): void {\n\t\tif (this.saving) return;\n\t\tthis.saving = true;\n\t\tthis.showSettings(profile, returnAction);\n\t\tvoid persistOverride(this.ctx, profile, patch)\n\t\t\t.then(\n\t\t\t\t(config) => this.completeSave(profile, config),\n\t\t\t\t() => this.completeSave(profile, undefined),\n\t\t\t)\n\t\t\t.catch(() => {\n\t\t\t\t// A reload can stale the command context while the queued file write finishes.\n\t\t\t});\n\t}\n\n\tprivate completeSave(profile: AgentProfile, config: SubagentConfigFile | undefined): void {\n\t\tif (this.closed) return;\n\t\tthis.saving = false;\n\t\tif (config) this.config = config;\n\t\tif (this.route.kind === \"settings\" && this.route.profile.name === profile.name) {\n\t\t\tthis.showSettings(profile, this.route.selectedAction);\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this.saving) {\n\t\t\tthis.activeScreen?.handleInput?.(data);\n\t\t\treturn;\n\t\t}\n\t\tif (!this.keybindings.matches(data, \"tui.select.cancel\")) return;\n\t\tif (this.route.kind === \"settings\") this.showProfiles();\n\t\telse if (this.route.kind === \"profiles\") this.onDone();\n\t}\n\n\tdispose(): void {\n\t\tthis.closed = true;\n\t\tthis.disposeActiveScreen();\n\t\tthis.clear();\n\t}\n}\n\nasync function showTuiAgentsCommand(ctx: ExtensionCommandContext, currentThinking: ThinkingLevel): Promise<void> {\n\tconst config = await loadSubagentConfig(getAgentDir(), (message) => ctx.ui.notify(message, \"warning\"));\n\tawait ctx.ui.custom<void>(\n\t\t(tui, theme, keybindings, done) =>\n\t\t\tnew AgentsMenuComponent({\n\t\t\t\ttui,\n\t\t\t\ttheme,\n\t\t\t\tkeybindings,\n\t\t\t\tctx,\n\t\t\t\tcurrentThinking,\n\t\t\t\tconfig,\n\t\t\t\tonDone: () => done(),\n\t\t\t}),\n\t);\n}\n\nexport async function showAgentsCommand(ctx: ExtensionCommandContext, currentThinking: ThinkingLevel): Promise<void> {\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(\"/agents requires an interactive UI.\", \"warning\");\n\t\treturn;\n\t}\n\tif (ctx.mode === \"tui\") await showTuiAgentsCommand(ctx, currentThinking);\n\telse await showDialogAgentsCommand(ctx, currentThinking);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxG,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,
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxG,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,EAwBjD,CAAC;AAQF,wBAAgB,uBAAuB,IAAI,MAAM,CAYhD"}
|
|
@@ -8,7 +8,6 @@ export const AGENT_PROFILE_LABELS = {
|
|
|
8
8
|
export const AGENT_PROFILES = [
|
|
9
9
|
{
|
|
10
10
|
name: "explorer",
|
|
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',
|
|
12
11
|
tools: [...EXPLORER_TOOLS],
|
|
13
12
|
systemPrompt: [
|
|
14
13
|
"You are a fast read-only exploration agent; return findings as quickly as possible.",
|
|
@@ -19,11 +18,9 @@ export const AGENT_PROFILES = [
|
|
|
19
18
|
"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.",
|
|
20
19
|
"Return concise findings with precise paths, symbols, relationships, and unresolved uncertainties.",
|
|
21
20
|
].join("\n"),
|
|
22
|
-
omitContextFiles: true,
|
|
23
21
|
},
|
|
24
22
|
{
|
|
25
23
|
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
24
|
tools: [...DEFAULT_AGENT_TOOLS],
|
|
28
25
|
systemPrompt: [
|
|
29
26
|
"Work independently on the delegated task from start to finish.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,SAAS,EAA0B,MAAM,gBAAgB,CAAC;AAGxG,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,
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,SAAS,EAA0B,MAAM,gBAAgB,CAAC;AAGxG,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,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;KACZ;IACD;QACC,IAAI,EAAE,SAAS;QACf,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,gFAAgF;AAChF,gFAAgF;AAChF,iFAAiF;AACjF,kBAAkB;AAClB,MAAM,UAAU,uBAAuB;IACtC,OAAO;QACN,iMAAiM;QACjM,EAAE;QACF,aAAa,SAAS,uHAAuH;QAC7I,EAAE;QACF,iBAAiB;QACjB,gOAAgO;QAChO,0HAA0H;QAC1H,EAAE;QACF,6GAA6G;KAC7G,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC","sourcesContent":["import { DEFAULT_AGENT_TOOLS, EXPLORER_TOOLS, MAX_TASKS, type SubagentAgentName } 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\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},\n\t{\n\t\tname: \"general\",\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.\n// Concurrency and result ordering live on the tasks parameter; when-to-delegate\n// routing lives in promptGuidelines. The self-contained-briefing rule is stated\n// here as well as on the prompt parameter because it is the failure mode workers\n// hit most often.\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; 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\"Never delegate with vague instructions: state what must be investigated or changed and the expected output.\",\n\t].join(\"\\n\");\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/budget.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/budget.ts"],"names":[],"mappings":"AAUA,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;AAuDD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,eAAe,CAkB9E;AAqBD,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAM9D"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDisplayableActivity } from "./activity.js";
|
|
2
|
+
import { DETAILS_ACTIVITY_LIMIT, DETAILS_OUTPUT_LIMIT, DISPLAY_ACTIVITY_LIMIT, RETRY_ERROR_TEXT_LIMIT, TASK_OUTPUT_LIMIT, TOTAL_OUTPUT_LIMIT, } from "./constants.js";
|
|
2
3
|
import { boundText } from "./text.js";
|
|
3
4
|
const EMPTY_OUTPUT = "(Subagent completed but returned no output.)";
|
|
4
5
|
// Pass-2 (adversarial) accounting: the bounded non-report payload is
|
|
@@ -26,6 +27,32 @@ export function planBudgets(taskCount) {
|
|
|
26
27
|
function detailsSize(details) {
|
|
27
28
|
return Buffer.byteLength(JSON.stringify(details), "utf8");
|
|
28
29
|
}
|
|
30
|
+
// Keep the normal newest-activity tail while guaranteeing that synthetic
|
|
31
|
+
// compaction entries cannot evict the three real tool calls the expanded UI
|
|
32
|
+
// promises to show. The count and byte caps remain unchanged.
|
|
33
|
+
function selectDetailsActivities(activities) {
|
|
34
|
+
if (activities.length <= DETAILS_ACTIVITY_LIMIT)
|
|
35
|
+
return activities;
|
|
36
|
+
const required = new Set();
|
|
37
|
+
for (let index = activities.length - 1; index >= 0 && required.size < DISPLAY_ACTIVITY_LIMIT; index--) {
|
|
38
|
+
const activity = activities[index];
|
|
39
|
+
if (activity && isDisplayableActivity(activity))
|
|
40
|
+
required.add(index);
|
|
41
|
+
}
|
|
42
|
+
const selected = new Set();
|
|
43
|
+
for (let index = activities.length - DETAILS_ACTIVITY_LIMIT; index < activities.length; index++)
|
|
44
|
+
selected.add(index);
|
|
45
|
+
for (const index of required)
|
|
46
|
+
selected.add(index);
|
|
47
|
+
const ordered = [...selected].sort((left, right) => left - right);
|
|
48
|
+
while (ordered.length > DETAILS_ACTIVITY_LIMIT) {
|
|
49
|
+
const removable = ordered.findIndex((index) => !required.has(index));
|
|
50
|
+
if (removable === -1)
|
|
51
|
+
break;
|
|
52
|
+
ordered.splice(removable, 1);
|
|
53
|
+
}
|
|
54
|
+
return ordered.map((index) => activities[index]);
|
|
55
|
+
}
|
|
29
56
|
function boundRuns(details, reportLimit) {
|
|
30
57
|
return {
|
|
31
58
|
...details,
|
|
@@ -34,7 +61,7 @@ function boundRuns(details, reportLimit) {
|
|
|
34
61
|
cwd: boundText(run.cwd, 1_024),
|
|
35
62
|
currentActivity: run.currentActivity ? boundText(run.currentActivity, 512) : undefined,
|
|
36
63
|
retry: run.retry ? { ...run.retry, error: boundText(run.retry.error, RETRY_ERROR_TEXT_LIMIT) } : undefined,
|
|
37
|
-
activities: run.activities
|
|
64
|
+
activities: selectDetailsActivities(run.activities).map((activity) => ({
|
|
38
65
|
...activity,
|
|
39
66
|
summary: boundText(activity.summary, 256),
|
|
40
67
|
resultSummary: activity.resultSummary ? boundText(activity.resultSummary, 256) : undefined,
|
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../../src/extensions/subagent/budget.ts"],"names":[],"mappings":"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","sourcesContent":["import { isDisplayableActivity } from \"./activity.ts\";\nimport {\n\tDETAILS_ACTIVITY_LIMIT,\n\tDETAILS_OUTPUT_LIMIT,\n\tDISPLAY_ACTIVITY_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\n// Keep the normal newest-activity tail while guaranteeing that synthetic\n// compaction entries cannot evict the three real tool calls the expanded UI\n// promises to show. The count and byte caps remain unchanged.\nfunction selectDetailsActivities(activities: SubagentRunDetails[\"activities\"]): SubagentRunDetails[\"activities\"] {\n\tif (activities.length <= DETAILS_ACTIVITY_LIMIT) return activities;\n\n\tconst required = new Set<number>();\n\tfor (let index = activities.length - 1; index >= 0 && required.size < DISPLAY_ACTIVITY_LIMIT; index--) {\n\t\tconst activity = activities[index];\n\t\tif (activity && isDisplayableActivity(activity)) required.add(index);\n\t}\n\n\tconst selected = new Set<number>();\n\tfor (let index = activities.length - DETAILS_ACTIVITY_LIMIT; index < activities.length; index++) selected.add(index);\n\tfor (const index of required) selected.add(index);\n\n\tconst ordered = [...selected].sort((left, right) => left - right);\n\twhile (ordered.length > DETAILS_ACTIVITY_LIMIT) {\n\t\tconst removable = ordered.findIndex((index) => !required.has(index));\n\t\tif (removable === -1) break;\n\t\tordered.splice(removable, 1);\n\t}\n\treturn ordered.map((index) => activities[index]!);\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: selectDetailsActivities(run.activities).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"]}
|
|
@@ -11,16 +11,16 @@ export interface RunCancellation {
|
|
|
11
11
|
/** Fires when the parent signal aborts or abort() is called. */
|
|
12
12
|
readonly signal: AbortSignal;
|
|
13
13
|
readonly aborted: boolean;
|
|
14
|
-
/** Idempotent: marks the scope aborted and awaits the
|
|
14
|
+
/** Idempotent: marks the scope aborted and awaits the current handler. */
|
|
15
15
|
abort(): Promise<void>;
|
|
16
16
|
/**
|
|
17
17
|
* Single-slot abort handler; a later call replaces the earlier one.
|
|
18
|
-
* Registering after an abort invokes
|
|
19
|
-
*
|
|
18
|
+
* Registering after an abort invokes that handler immediately and once by
|
|
19
|
+
* function identity. The returned unregister function is idempotent.
|
|
20
20
|
*/
|
|
21
21
|
onAbort(handler: () => Promise<void>): () => void;
|
|
22
22
|
throwIfAborted(): void;
|
|
23
|
-
/** Drops the parent-signal listener and the handler; idempotent. */
|
|
23
|
+
/** Drops the parent-signal listener and the current handler; idempotent. */
|
|
24
24
|
dispose(): void;
|
|
25
25
|
}
|
|
26
26
|
export declare function createRunCancellation(parent: AbortSignal | undefined): RunCancellation;
|
|
@@ -1 +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,
|
|
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,0EAA0E;IAC1E,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,4EAA4E;IAC5E,OAAO,IAAI,IAAI,CAAC;CAChB;AAOD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,eAAe,CA4DtF;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhF"}
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
-
const NO_OP_HANDLER = () => Promise.resolve();
|
|
2
1
|
export function createRunCancellation(parent) {
|
|
3
2
|
const controller = new AbortController();
|
|
4
|
-
|
|
5
|
-
let
|
|
3
|
+
const executions = new Map();
|
|
4
|
+
let current;
|
|
5
|
+
let registrationId = 0;
|
|
6
6
|
let disposed = false;
|
|
7
|
+
const executeHandler = (handler) => {
|
|
8
|
+
if (disposed || !handler)
|
|
9
|
+
return Promise.resolve();
|
|
10
|
+
const existing = executions.get(handler);
|
|
11
|
+
if (existing)
|
|
12
|
+
return existing;
|
|
13
|
+
const execution = Promise.resolve()
|
|
14
|
+
.then(handler)
|
|
15
|
+
.catch(() => undefined);
|
|
16
|
+
executions.set(handler, execution);
|
|
17
|
+
return execution;
|
|
18
|
+
};
|
|
7
19
|
const trigger = () => {
|
|
8
20
|
if (disposed)
|
|
9
21
|
return Promise.resolve();
|
|
10
22
|
if (!controller.signal.aborted)
|
|
11
23
|
controller.abort();
|
|
12
|
-
|
|
13
|
-
.then(handler)
|
|
14
|
-
.catch(() => undefined);
|
|
15
|
-
return inFlight;
|
|
24
|
+
return executeHandler(current?.handler);
|
|
16
25
|
};
|
|
17
26
|
const parentListener = () => {
|
|
18
27
|
void trigger();
|
|
@@ -29,13 +38,20 @@ export function createRunCancellation(parent) {
|
|
|
29
38
|
return controller.signal.aborted;
|
|
30
39
|
},
|
|
31
40
|
abort: trigger,
|
|
32
|
-
onAbort(
|
|
33
|
-
|
|
41
|
+
onAbort(handler) {
|
|
42
|
+
if (disposed)
|
|
43
|
+
return () => { };
|
|
44
|
+
const registration = { id: ++registrationId, handler };
|
|
45
|
+
current = registration;
|
|
34
46
|
if (controller.signal.aborted)
|
|
35
|
-
void
|
|
47
|
+
void executeHandler(handler);
|
|
48
|
+
let unregistered = false;
|
|
36
49
|
return () => {
|
|
37
|
-
if (
|
|
38
|
-
|
|
50
|
+
if (unregistered)
|
|
51
|
+
return;
|
|
52
|
+
unregistered = true;
|
|
53
|
+
if (current?.id === registration.id)
|
|
54
|
+
current = undefined;
|
|
39
55
|
};
|
|
40
56
|
},
|
|
41
57
|
throwIfAborted() {
|
|
@@ -43,8 +59,10 @@ export function createRunCancellation(parent) {
|
|
|
43
59
|
throw new Error("Subagent run was aborted.");
|
|
44
60
|
},
|
|
45
61
|
dispose() {
|
|
62
|
+
if (disposed)
|
|
63
|
+
return;
|
|
46
64
|
disposed = true;
|
|
47
|
-
|
|
65
|
+
current = undefined;
|
|
48
66
|
parent?.removeEventListener("abort", parentListener);
|
|
49
67
|
},
|
|
50
68
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cancellation.js","sourceRoot":"","sources":["../../../src/extensions/subagent/cancellation.ts"],"names":[],"mappings":"
|
|
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 current 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 that handler immediately and once by\n\t * function identity. The returned unregister function is idempotent.\n\t */\n\tonAbort(handler: () => Promise<void>): () => void;\n\tthrowIfAborted(): void;\n\t/** Drops the parent-signal listener and the current handler; idempotent. */\n\tdispose(): void;\n}\n\ninterface HandlerRegistration {\n\tid: number;\n\thandler: () => Promise<void>;\n}\n\nexport function createRunCancellation(parent: AbortSignal | undefined): RunCancellation {\n\tconst controller = new AbortController();\n\tconst executions = new Map<() => Promise<void>, Promise<void>>();\n\tlet current: HandlerRegistration | undefined;\n\tlet registrationId = 0;\n\tlet disposed = false;\n\n\tconst executeHandler = (handler: (() => Promise<void>) | undefined): Promise<void> => {\n\t\tif (disposed || !handler) return Promise.resolve();\n\t\tconst existing = executions.get(handler);\n\t\tif (existing) return existing;\n\t\tconst execution = Promise.resolve()\n\t\t\t.then(handler)\n\t\t\t.catch(() => undefined);\n\t\texecutions.set(handler, execution);\n\t\treturn execution;\n\t};\n\n\tconst trigger = (): Promise<void> => {\n\t\tif (disposed) return Promise.resolve();\n\t\tif (!controller.signal.aborted) controller.abort();\n\t\treturn executeHandler(current?.handler);\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(handler: () => Promise<void>): () => void {\n\t\t\tif (disposed) return () => {};\n\t\t\tconst registration: HandlerRegistration = { id: ++registrationId, handler };\n\t\t\tcurrent = registration;\n\t\t\tif (controller.signal.aborted) void executeHandler(handler);\n\t\t\tlet unregistered = false;\n\t\t\treturn () => {\n\t\t\t\tif (unregistered) return;\n\t\t\t\tunregistered = true;\n\t\t\t\tif (current?.id === registration.id) current = undefined;\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\tif (disposed) return;\n\t\t\tdisposed = true;\n\t\t\tcurrent = undefined;\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"]}
|
|
@@ -14,6 +14,7 @@ export declare const EXPLORER_TOOLS: readonly ["read", "grep", "find", "ls", "ba
|
|
|
14
14
|
export declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
15
15
|
export declare const ACTIVITY_LIMIT = 80;
|
|
16
16
|
export declare const ACTIVITY_TEXT_LIMIT: number;
|
|
17
|
+
export declare const DISPLAY_ACTIVITY_LIMIT = 3;
|
|
17
18
|
export declare const COMPACTION_ACTIVITY_ID = "compaction";
|
|
18
19
|
export declare const TASK_OUTPUT_LIMIT: number;
|
|
19
20
|
export declare const TOTAL_OUTPUT_LIMIT: number;
|