@astralyn/pi 0.84.5 → 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.
Files changed (105) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/core/agent-session.d.ts.map +1 -1
  3. package/dist/core/agent-session.js +4 -0
  4. package/dist/core/agent-session.js.map +1 -1
  5. package/dist/core/extensions/index.d.ts +1 -1
  6. package/dist/core/extensions/index.d.ts.map +1 -1
  7. package/dist/core/extensions/index.js.map +1 -1
  8. package/dist/core/extensions/runner.d.ts +1 -0
  9. package/dist/core/extensions/runner.d.ts.map +1 -1
  10. package/dist/core/extensions/runner.js +6 -0
  11. package/dist/core/extensions/runner.js.map +1 -1
  12. package/dist/core/extensions/types.d.ts +11 -0
  13. package/dist/core/extensions/types.d.ts.map +1 -1
  14. package/dist/core/extensions/types.js.map +1 -1
  15. package/dist/core/tools/bash.d.ts +5 -0
  16. package/dist/core/tools/bash.d.ts.map +1 -1
  17. package/dist/core/tools/bash.js +1 -1
  18. package/dist/core/tools/bash.js.map +1 -1
  19. package/dist/extensions/background/index.d.ts +95 -20
  20. package/dist/extensions/background/index.d.ts.map +1 -1
  21. package/dist/extensions/background/index.js +470 -136
  22. package/dist/extensions/background/index.js.map +1 -1
  23. package/dist/extensions/background/manager.d.ts +14 -0
  24. package/dist/extensions/background/manager.d.ts.map +1 -1
  25. package/dist/extensions/background/manager.js +125 -24
  26. package/dist/extensions/background/manager.js.map +1 -1
  27. package/dist/extensions/background/registry.d.ts +82 -0
  28. package/dist/extensions/background/registry.d.ts.map +1 -1
  29. package/dist/extensions/background/registry.js +237 -6
  30. package/dist/extensions/background/registry.js.map +1 -1
  31. package/dist/extensions/background/render.d.ts +35 -11
  32. package/dist/extensions/background/render.d.ts.map +1 -1
  33. package/dist/extensions/background/render.js +172 -30
  34. package/dist/extensions/background/render.js.map +1 -1
  35. package/dist/extensions/subagent/activity.d.ts +3 -5
  36. package/dist/extensions/subagent/activity.d.ts.map +1 -1
  37. package/dist/extensions/subagent/activity.js +8 -89
  38. package/dist/extensions/subagent/activity.js.map +1 -1
  39. package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
  40. package/dist/extensions/subagent/agents-command.js +40 -94
  41. package/dist/extensions/subagent/agents-command.js.map +1 -1
  42. package/dist/extensions/subagent/agents.d.ts +2 -0
  43. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  44. package/dist/extensions/subagent/agents.js +7 -1
  45. package/dist/extensions/subagent/agents.js.map +1 -1
  46. package/dist/extensions/subagent/budget.d.ts +15 -0
  47. package/dist/extensions/subagent/budget.d.ts.map +1 -0
  48. package/dist/extensions/subagent/budget.js +96 -0
  49. package/dist/extensions/subagent/budget.js.map +1 -0
  50. package/dist/extensions/subagent/cancellation.d.ts +29 -0
  51. package/dist/extensions/subagent/cancellation.d.ts.map +1 -0
  52. package/dist/extensions/subagent/cancellation.js +73 -0
  53. package/dist/extensions/subagent/cancellation.js.map +1 -0
  54. package/dist/extensions/subagent/index.d.ts.map +1 -1
  55. package/dist/extensions/subagent/index.js +5 -22
  56. package/dist/extensions/subagent/index.js.map +1 -1
  57. package/dist/extensions/subagent/model-selection.d.ts +16 -0
  58. package/dist/extensions/subagent/model-selection.d.ts.map +1 -0
  59. package/dist/extensions/subagent/model-selection.js +51 -0
  60. package/dist/extensions/subagent/model-selection.js.map +1 -0
  61. package/dist/extensions/subagent/render.d.ts +6 -1
  62. package/dist/extensions/subagent/render.d.ts.map +1 -1
  63. package/dist/extensions/subagent/render.js +23 -12
  64. package/dist/extensions/subagent/render.js.map +1 -1
  65. package/dist/extensions/subagent/resolve.d.ts.map +1 -1
  66. package/dist/extensions/subagent/resolve.js +2 -21
  67. package/dist/extensions/subagent/resolve.js.map +1 -1
  68. package/dist/extensions/subagent/runner.d.ts +4 -5
  69. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  70. package/dist/extensions/subagent/runner.js +71 -264
  71. package/dist/extensions/subagent/runner.js.map +1 -1
  72. package/dist/extensions/subagent/sdk-runner.d.ts +13 -11
  73. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  74. package/dist/extensions/subagent/sdk-runner.js +167 -148
  75. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  76. package/dist/extensions/subagent/state.d.ts +89 -0
  77. package/dist/extensions/subagent/state.d.ts.map +1 -0
  78. package/dist/extensions/subagent/state.js +294 -0
  79. package/dist/extensions/subagent/state.js.map +1 -0
  80. package/dist/extensions/subagent/text.d.ts +4 -0
  81. package/dist/extensions/subagent/text.d.ts.map +1 -1
  82. package/dist/extensions/subagent/text.js +75 -0
  83. package/dist/extensions/subagent/text.js.map +1 -1
  84. package/dist/extensions/subagent/types.d.ts +3 -8
  85. package/dist/extensions/subagent/types.d.ts.map +1 -1
  86. package/dist/extensions/subagent/types.js.map +1 -1
  87. package/dist/extensions/subagent/ui/choices.d.ts +36 -0
  88. package/dist/extensions/subagent/ui/choices.d.ts.map +1 -0
  89. package/dist/extensions/subagent/ui/choices.js +54 -0
  90. package/dist/extensions/subagent/ui/choices.js.map +1 -0
  91. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
  92. package/dist/extensions/subagent/ui/model-list.js +10 -18
  93. package/dist/extensions/subagent/ui/model-list.js.map +1 -1
  94. package/dist/index.d.ts +1 -1
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js.map +1 -1
  97. package/docs/bundled/README.md +1 -1
  98. package/docs/bundled/extensions/background.md +55 -20
  99. package/docs/extensions.md +13 -0
  100. package/npm-shrinkwrap.json +2 -2
  101. package/package.json +1 -1
  102. package/dist/extensions/subagent/retry.d.ts +0 -17
  103. package/dist/extensions/subagent/retry.d.ts.map +0 -1
  104. package/dist/extensions/subagent/retry.js +0 -41
  105. package/dist/extensions/subagent/retry.js.map +0 -1
@@ -1,45 +1,14 @@
1
- import { clampThinkingLevel, getSupportedThinkingLevels } from "@earendil-works/pi-ai/compat";
2
1
  import { Container, Spacer, Text, TruncatedText, } from "@earendil-works/pi-tui";
3
2
  import { getAgentDir } from "../../config.js";
4
3
  import { DynamicBorder } from "../../modes/interactive/components/dynamic-border.js";
5
4
  import { keyLabel } from "../../modes/interactive/components/keybinding-hints.js";
6
- import { AGENT_PROFILES } from "./agents.js";
7
- import { THINKING_LEVELS } from "./constants.js";
5
+ import { AGENT_PROFILE_LABELS, AGENT_PROFILES } from "./agents.js";
8
6
  import { loadSubagentConfig, updateProfileOverride } from "./settings.js";
7
+ import { truncate } from "./text.js";
8
+ import { buildModelChoices, buildSettingsRows, buildThinkingChoices, compareModels, } from "./ui/choices.js";
9
9
  import { ProfileModelListComponent } from "./ui/model-list.js";
10
10
  const MODEL_REFRESH_TIMEOUT_MS = 15_000;
11
11
  const MAX_REFRESH_ERROR_LENGTH = 240;
12
- // Static display titles for the two built-in profiles; agents.ts owns the
13
- // model-facing copy.
14
- const PROFILE_LABELS = {
15
- explorer: "Explorer",
16
- general: "General",
17
- };
18
- function modelId(model) {
19
- return model ? `${model.provider}/${model.id}` : "none";
20
- }
21
- function findModel(models, value) {
22
- if (!value)
23
- return undefined;
24
- return models.find((model) => `${model.provider}/${model.id}` === value);
25
- }
26
- function boundText(value, limit) {
27
- const characters = [...value];
28
- return characters.length <= limit ? value : `${characters.slice(0, Math.max(0, limit - 1)).join("")}…`;
29
- }
30
- // Capability checks use the saved model when it is still in the catalog,
31
- // falling back to the parent session model otherwise.
32
- function effectiveModel(currentSessionModel, models, override) {
33
- if (override?.model) {
34
- const saved = findModel(models, override.model);
35
- if (saved)
36
- return saved;
37
- }
38
- return currentSessionModel;
39
- }
40
- function inheritedThinking(effective, currentThinking) {
41
- return effective ? clampThinkingLevel(effective, currentThinking) : currentThinking;
42
- }
43
12
  function refreshFailureMessage(providerIds) {
44
13
  if (providerIds.length === 1)
45
14
  return `Could not refresh ${providerIds[0]}; showing cached models.`;
@@ -73,28 +42,15 @@ class ProfileSettingsMenuComponent extends Container {
73
42
  this.theme = options.theme;
74
43
  this.keybindings = options.keybindings;
75
44
  this.onDone = options.onDone;
76
- const effective = effectiveModel(options.currentSessionModel, options.models, options.override);
77
- this.rows = [
78
- {
79
- action: "model",
80
- label: "Model",
81
- value: options.override?.model
82
- ? `override — ${options.override.model}${findModel(options.models, options.override.model) ? "" : " [unavailable]"}`
83
- : `inherit — ${modelId(options.currentSessionModel)}`,
84
- override: options.override?.model !== undefined,
85
- },
86
- {
87
- action: "thinking",
88
- label: "Thinking",
89
- value: options.override?.thinking
90
- ? `override — ${options.override.thinking}`
91
- : `inherit — ${inheritedThinking(effective, options.currentThinking)}`,
92
- override: options.override?.thinking !== undefined,
93
- },
94
- ];
45
+ this.rows = buildSettingsRows({
46
+ override: options.override,
47
+ models: options.models,
48
+ currentSessionModel: options.currentSessionModel,
49
+ currentThinking: options.currentThinking,
50
+ });
95
51
  this.addChild(new DynamicBorder());
96
52
  this.addChild(new Spacer(1));
97
- this.addChild(new Text(this.theme.fg("accent", this.theme.bold(PROFILE_LABELS[options.profile.name])), 1, 0));
53
+ this.addChild(new Text(this.theme.fg("accent", this.theme.bold(AGENT_PROFILE_LABELS[options.profile.name])), 1, 0));
98
54
  this.addChild(new Spacer(1));
99
55
  this.listContainer = new Container();
100
56
  this.addChild(this.listContainer);
@@ -158,7 +114,7 @@ class ModelPickerComponent extends Container {
158
114
  this.keybindings = options.keybindings;
159
115
  this.addChild(new DynamicBorder());
160
116
  this.addChild(new Spacer(1));
161
- this.addChild(new Text(this.theme.fg("accent", this.theme.bold(`Model — ${PROFILE_LABELS[options.profile.name]}`)), 1, 0));
117
+ this.addChild(new Text(this.theme.fg("accent", this.theme.bold(`Model — ${AGENT_PROFILE_LABELS[options.profile.name]}`)), 1, 0));
162
118
  this.addChild(new Spacer(1));
163
119
  this.modelList = new ProfileModelListComponent({
164
120
  theme: options.theme,
@@ -219,7 +175,7 @@ async function persistOverride(ctx, profile, patch, current) {
219
175
  await updateProfileOverride(profile.name, patch, getAgentDir());
220
176
  }
221
177
  catch (error) {
222
- ctx.ui.notify(`Could not save ${PROFILE_LABELS[profile.name]} settings: ${error instanceof Error ? error.message : String(error)}`, "error");
178
+ ctx.ui.notify(`Could not save ${AGENT_PROFILE_LABELS[profile.name]} settings: ${error instanceof Error ? error.message : String(error)}`, "error");
223
179
  }
224
180
  }
225
181
  async function refreshPickerModels(ctx, picker) {
@@ -245,7 +201,7 @@ async function refreshPickerModels(ctx, picker) {
245
201
  }
246
202
  const registryError = ctx.modelRegistry.getError();
247
203
  if (registryError) {
248
- picker.setRefreshStatus(boundText(registryError, MAX_REFRESH_ERROR_LENGTH), "error");
204
+ picker.setRefreshStatus(truncate(registryError, MAX_REFRESH_ERROR_LENGTH), "error");
249
205
  return;
250
206
  }
251
207
  picker.setRefreshStatus(undefined);
@@ -256,16 +212,18 @@ async function refreshPickerModels(ctx, picker) {
256
212
  const message = timedOut
257
213
  ? "Model refresh timed out; showing cached models."
258
214
  : `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`;
259
- picker.setRefreshStatus(boundText(message, MAX_REFRESH_ERROR_LENGTH), "error");
215
+ picker.setRefreshStatus(truncate(message, MAX_REFRESH_ERROR_LENGTH), "error");
260
216
  }
261
217
  finally {
262
218
  clearTimeout(timeout);
263
219
  }
264
220
  }
265
221
  async function selectProfile(ctx) {
266
- const labels = AGENT_PROFILES.map((profile) => PROFILE_LABELS[profile.name]);
222
+ const labels = AGENT_PROFILES.map((profile) => AGENT_PROFILE_LABELS[profile.name]);
267
223
  const label = await ctx.ui.select("Agents", labels);
268
- return label === undefined ? undefined : AGENT_PROFILES.find((profile) => PROFILE_LABELS[profile.name] === label);
224
+ return label === undefined
225
+ ? undefined
226
+ : AGENT_PROFILES.find((profile) => AGENT_PROFILE_LABELS[profile.name] === label);
269
227
  }
270
228
  async function showTuiSettingsMenu(ctx, profile, override, currentThinking) {
271
229
  return ctx.ui.custom((_tui, theme, keybindings, done) => new ProfileSettingsMenuComponent({
@@ -280,18 +238,16 @@ async function showTuiSettingsMenu(ctx, profile, override, currentThinking) {
280
238
  }));
281
239
  }
282
240
  async function showDialogSettingsMenu(ctx, profile, override, currentThinking) {
283
- const models = ctx.modelRegistry.getAvailable();
284
- const effective = effectiveModel(ctx.model, models, override);
285
- const modelValue = override?.model
286
- ? `override — ${override.model}${findModel(models, override.model) ? "" : " [unavailable]"}`
287
- : `inherit — ${modelId(ctx.model)}`;
288
- const thinkingValue = override?.thinking
289
- ? `override — ${override.thinking}`
290
- : `inherit — ${inheritedThinking(effective, currentThinking)}`;
291
241
  const options = new Map();
292
- options.set(`Model — ${modelValue}`, "model");
293
- options.set(`Thinking — ${thinkingValue}`, "thinking");
294
- const label = await ctx.ui.select(PROFILE_LABELS[profile.name], [...options.keys()]);
242
+ for (const row of buildSettingsRows({
243
+ override,
244
+ models: ctx.modelRegistry.getAvailable(),
245
+ currentSessionModel: ctx.model,
246
+ currentThinking,
247
+ })) {
248
+ options.set(`${row.label} — ${row.value}`, row.action);
249
+ }
250
+ const label = await ctx.ui.select(AGENT_PROFILE_LABELS[profile.name], [...options.keys()]);
295
251
  return label === undefined ? undefined : options.get(label);
296
252
  }
297
253
  async function showTuiModelPicker(ctx, profile, override) {
@@ -314,33 +270,23 @@ async function showTuiModelPicker(ctx, profile, override) {
314
270
  return chosen === undefined ? undefined : { modelId: chosen.modelId };
315
271
  }
316
272
  async function showDialogModelPicker(ctx, profile, override) {
317
- const models = ctx.modelRegistry.getAvailable().sort((left, right) => {
318
- const provider = left.provider.localeCompare(right.provider);
319
- return provider !== 0 ? provider : left.id.localeCompare(right.id);
273
+ const models = [...ctx.modelRegistry.getAvailable()].sort(compareModels);
274
+ const choices = buildModelChoices({
275
+ models,
276
+ currentSessionModel: ctx.model,
277
+ savedModelId: override?.model,
320
278
  });
321
- const choices = new Map();
322
- choices.set(`inherit (${modelId(ctx.model)})${override?.model ? "" : " ✓"}`, undefined);
323
- if (override?.model && !findModel(models, override.model)) {
324
- choices.set(`${override.model} [unavailable] ✓`, override.model);
325
- }
326
- for (const model of models) {
327
- const id = modelId(model);
328
- choices.set(`${id}${override?.model === id ? " ✓" : ""}`, id);
329
- }
330
- const label = await ctx.ui.select(`Model — ${PROFILE_LABELS[profile.name]}`, [...choices.keys()]);
279
+ const label = await ctx.ui.select(`Model — ${AGENT_PROFILE_LABELS[profile.name]}`, [...choices.keys()]);
331
280
  return label === undefined ? undefined : { modelId: choices.get(label) };
332
281
  }
333
282
  async function showThinkingPicker(ctx, profile, override, currentThinking) {
334
- const models = ctx.modelRegistry.getAvailable();
335
- const effective = effectiveModel(ctx.model, models, override);
336
- const levels = effective ? getSupportedThinkingLevels(effective) : [...THINKING_LEVELS];
337
- const inherited = inheritedThinking(effective, currentThinking);
338
- const choices = new Map();
339
- choices.set(`inherit (${inherited})${override?.thinking ? "" : " ✓"}`, undefined);
340
- for (const level of levels) {
341
- choices.set(`${level}${override?.thinking === level ? " ✓" : ""}`, level);
342
- }
343
- const label = await ctx.ui.select(`Thinking — ${PROFILE_LABELS[profile.name]}`, [...choices.keys()]);
283
+ const choices = buildThinkingChoices({
284
+ currentSessionModel: ctx.model,
285
+ models: ctx.modelRegistry.getAvailable(),
286
+ override,
287
+ currentThinking,
288
+ });
289
+ const label = await ctx.ui.select(`Thinking — ${AGENT_PROFILE_LABELS[profile.name]}`, [...choices.keys()]);
344
290
  return label === undefined ? undefined : { level: choices.get(label) };
345
291
  }
346
292
  async function runProfileSettings(ctx, profile, currentThinking) {
@@ -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 type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { clampThinkingLevel, getSupportedThinkingLevels } from \"@earendil-works/pi-ai/compat\";\nimport {\n\tContainer,\n\ttype Focusable,\n\ttype KeybindingsManager,\n\tSpacer,\n\tText,\n\tTruncatedText,\n\ttype TUI,\n} from \"@earendil-works/pi-tui\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/types.ts\";\nimport { DynamicBorder } from \"../../modes/interactive/components/dynamic-border.ts\";\nimport { keyLabel } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { AGENT_PROFILES } from \"./agents.ts\";\nimport { type SubagentAgentName, THINKING_LEVELS } from \"./constants.ts\";\nimport { loadSubagentConfig, updateProfileOverride } from \"./settings.ts\";\nimport type { AgentProfile, SubagentProfileOverride } from \"./types.ts\";\nimport { type ProfileModelChoice, ProfileModelListComponent } from \"./ui/model-list.ts\";\n\nconst MODEL_REFRESH_TIMEOUT_MS = 15_000;\nconst MAX_REFRESH_ERROR_LENGTH = 240;\n\n// Static display titles for the two built-in profiles; agents.ts owns the\n// model-facing copy.\nconst PROFILE_LABELS: Record<SubagentAgentName, string> = {\n\texplorer: \"Explorer\",\n\tgeneral: \"General\",\n};\n\ntype SettingsAction = \"model\" | \"thinking\";\n\nfunction modelId(model: Pick<Model<Api>, \"provider\" | \"id\"> | undefined): string {\n\treturn model ? `${model.provider}/${model.id}` : \"none\";\n}\n\nfunction findModel(models: readonly Model<Api>[], value: string | undefined): Model<Api> | undefined {\n\tif (!value) return undefined;\n\treturn models.find((model) => `${model.provider}/${model.id}` === value);\n}\n\nfunction boundText(value: string, limit: number): string {\n\tconst characters = [...value];\n\treturn characters.length <= limit ? value : `${characters.slice(0, Math.max(0, limit - 1)).join(\"\")}…`;\n}\n\n// Capability checks use the saved model when it is still in the catalog,\n// falling back to the parent session model otherwise.\nfunction effectiveModel(\n\tcurrentSessionModel: Model<Api> | undefined,\n\tmodels: readonly Model<Api>[],\n\toverride: SubagentProfileOverride | undefined,\n): Model<Api> | undefined {\n\tif (override?.model) {\n\t\tconst saved = findModel(models, override.model);\n\t\tif (saved) return saved;\n\t}\n\treturn currentSessionModel;\n}\n\nfunction inheritedThinking(effective: Model<Api> | undefined, currentThinking: ThinkingLevel): ThinkingLevel {\n\treturn effective ? (clampThinkingLevel(effective, currentThinking) as ThinkingLevel) : currentThinking;\n}\n\nfunction refreshFailureMessage(providerIds: readonly string[]): string {\n\tif (providerIds.length === 1) return `Could not refresh ${providerIds[0]}; showing cached models.`;\n\tconst visible = providerIds.slice(0, 3);\n\tconst omitted = providerIds.length - visible.length;\n\tconst suffix = omitted > 0 ? `, +${omitted} more` : \"\";\n\treturn `Could not refresh ${providerIds.length} model catalogs (${visible.join(\", \")}${suffix}); showing cached models.`;\n}\n\nfunction hint(\n\ttheme: Theme,\n\tkeybindings: KeybindingsManager,\n\tbinding: Parameters<KeybindingsManager[\"getKeys\"]>[0],\n\tdescription: string,\n): string {\n\tconst key = keyLabel(binding, { keybindings });\n\treturn key ? `${theme.fg(\"dim\", key)}${theme.fg(\"muted\", ` ${description}`)}` : \"\";\n}\n\nfunction navigationHint(theme: Theme, keybindings: KeybindingsManager): string {\n\tconst keys = [keyLabel(\"tui.select.up\", { keybindings }), keyLabel(\"tui.select.down\", { keybindings })]\n\t\t.filter(Boolean)\n\t\t.join(\"/\");\n\treturn keys ? `${theme.fg(\"dim\", keys)}${theme.fg(\"muted\", \" navigate\")}` : \"\";\n}\n\n/** Compact Model/Thinking settings menu for one profile; every confirm persists immediately. */\nclass ProfileSettingsMenuComponent extends Container implements Focusable {\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly rows: Array<{ action: SettingsAction; label: string; value: string; override: boolean }>;\n\tprivate readonly onDone: (action: SettingsAction | undefined) => void;\n\tprivate readonly listContainer: Container;\n\tprivate selectedIndex = 0;\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}\n\n\tconstructor(options: {\n\t\ttheme: Theme;\n\t\tkeybindings: KeybindingsManager;\n\t\tprofile: AgentProfile;\n\t\toverride: SubagentProfileOverride | undefined;\n\t\tmodels: readonly Model<Api>[];\n\t\tcurrentSessionModel: Model<Api> | undefined;\n\t\tcurrentThinking: ThinkingLevel;\n\t\tonDone: (action: SettingsAction | undefined) => void;\n\t}) {\n\t\tsuper();\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.onDone = options.onDone;\n\t\tconst effective = effectiveModel(options.currentSessionModel, options.models, options.override);\n\t\tthis.rows = [\n\t\t\t{\n\t\t\t\taction: \"model\",\n\t\t\t\tlabel: \"Model\",\n\t\t\t\tvalue: options.override?.model\n\t\t\t\t\t? `override — ${options.override.model}${findModel(options.models, options.override.model) ? \"\" : \" [unavailable]\"}`\n\t\t\t\t\t: `inherit — ${modelId(options.currentSessionModel)}`,\n\t\t\t\toverride: options.override?.model !== undefined,\n\t\t\t},\n\t\t\t{\n\t\t\t\taction: \"thinking\",\n\t\t\t\tlabel: \"Thinking\",\n\t\t\t\tvalue: options.override?.thinking\n\t\t\t\t\t? `override — ${options.override.thinking}`\n\t\t\t\t\t: `inherit — ${inheritedThinking(effective, options.currentThinking)}`,\n\t\t\t\toverride: options.override?.thinking !== undefined,\n\t\t\t},\n\t\t];\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(this.theme.fg(\"accent\", this.theme.bold(PROFILE_LABELS[options.profile.name])), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\t\tthis.addChild(new Spacer(1));\n\t\tconst hints = [\n\t\t\tnavigationHint(this.theme, options.keybindings),\n\t\t\thint(this.theme, options.keybindings, \"tui.select.confirm\", \"select\"),\n\t\t\thint(this.theme, options.keybindings, \"tui.select.cancel\", \"back\"),\n\t\t].filter(Boolean);\n\t\tthis.addChild(new Text(hints.join(this.theme.fg(\"muted\", \" • \")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\t\tfor (const [index, row] of this.rows.entries()) {\n\t\t\tconst selected = index === this.selectedIndex;\n\t\t\tconst prefix = selected ? this.theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst label = selected ? this.theme.fg(\"accent\", row.label) : this.theme.fg(\"text\", row.label);\n\t\t\tconst value = this.theme.fg(\"muted\", `— ${row.value}`);\n\t\t\tconst checkmark = row.override ? this.theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(`${prefix}${label} ${value}${checkmark}`, 1, 0));\n\t\t}\n\t}\n\n\tprivate moveSelection(offset: -1 | 1): void {\n\t\tthis.selectedIndex = (this.selectedIndex + offset + this.rows.length) % this.rows.length;\n\t\tthis.updateList();\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.moveSelection(-1);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.moveSelection(1);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.onDone(this.rows[this.selectedIndex]?.action);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onDone(undefined);\n\t\t}\n\t}\n}\n\n/** Standalone searchable model picker for one profile; confirm saves immediately. */\nclass ModelPickerComponent extends Container implements Focusable {\n\tprivate readonly tui: TUI;\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly modelList: ProfileModelListComponent;\n\tprivate readonly refreshAbortController = new AbortController();\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\tthis.modelList.focused = value;\n\t}\n\n\tconstructor(options: {\n\t\ttui: TUI;\n\t\ttheme: Theme;\n\t\tkeybindings: KeybindingsManager;\n\t\tprofile: AgentProfile;\n\t\tsavedModelId: string | undefined;\n\t\tmodels: readonly Model<Api>[];\n\t\tscopedModels: readonly { model: Model<Api> }[];\n\t\tcurrentSessionModel: Model<Api> | undefined;\n\t\tonDone: (choice: ProfileModelChoice | undefined) => 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.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(this.theme.fg(\"accent\", this.theme.bold(`Model — ${PROFILE_LABELS[options.profile.name]}`)), 1, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.modelList = new ProfileModelListComponent({\n\t\t\ttheme: options.theme,\n\t\t\tkeybindings: options.keybindings,\n\t\t\tmodels: options.models,\n\t\t\tscopedModels: options.scopedModels,\n\t\t\tcurrentSessionModel: options.currentSessionModel,\n\t\t\tsavedModelId: options.savedModelId,\n\t\t\tonDone: options.onDone,\n\t\t});\n\t\tthis.addChild(this.modelList);\n\t\tthis.addChild(new Spacer(1));\n\t\tconst hints = [\n\t\t\tnavigationHint(this.theme, options.keybindings),\n\t\t\toptions.scopedModels.length > 0 ? hint(this.theme, options.keybindings, \"tui.input.tab\", \"scope\") : \"\",\n\t\t\thint(this.theme, options.keybindings, \"tui.select.confirm\", \"select\"),\n\t\t\thint(this.theme, options.keybindings, \"tui.select.cancel\", \"back\"),\n\t\t].filter(Boolean);\n\t\tthis.addChild(new Text(hints.join(this.theme.fg(\"muted\", \" • \")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tget refreshSignal(): AbortSignal {\n\t\treturn this.refreshAbortController.signal;\n\t}\n\n\tcancelRefresh(): void {\n\t\tthis.refreshAbortController.abort();\n\t}\n\n\tget isClosed(): boolean {\n\t\treturn this.closed;\n\t}\n\n\tdispose(): void {\n\t\tthis.closed = true;\n\t\tthis.refreshAbortController.abort();\n\t}\n\n\tupdateModels(models: readonly Model<Api>[]): void {\n\t\tif (this.closed) return;\n\t\tthis.modelList.updateModels(models);\n\t\tthis.tui.requestRender();\n\t}\n\n\tsetRefreshStatus(message: string | undefined, tone: \"muted\" | \"success\" | \"error\" = \"muted\"): void {\n\t\tif (this.closed) return;\n\t\tthis.modelList.setStatus(message, tone);\n\t\tthis.tui.requestRender();\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.modelList.handleInput(data);\n\t}\n}\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\tcurrent: string | ThinkingLevel | undefined,\n): Promise<void> {\n\tconst next = \"model\" in patch ? patch.model : patch.thinking;\n\tif (next === current) return;\n\ttry {\n\t\tawait updateProfileOverride(profile.name, patch, getAgentDir());\n\t} catch (error) {\n\t\tctx.ui.notify(\n\t\t\t`Could not save ${PROFILE_LABELS[profile.name]} settings: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\"error\",\n\t\t);\n\t}\n}\n\nasync function refreshPickerModels(ctx: ExtensionCommandContext, picker: ModelPickerComponent): Promise<void> {\n\tlet timedOut = false;\n\tconst timeout = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tpicker.cancelRefresh();\n\t}, MODEL_REFRESH_TIMEOUT_MS);\n\ttimeout.unref?.();\n\ttry {\n\t\tconst result = await ctx.modelRegistry.refresh({ signal: picker.refreshSignal });\n\t\tif (picker.isClosed || (picker.refreshSignal.aborted && !timedOut)) return;\n\t\tpicker.updateModels(ctx.modelRegistry.getAvailable());\n\t\tif (result.aborted && timedOut) {\n\t\t\tpicker.setRefreshStatus(\"Model refresh timed out; showing cached models.\", \"error\");\n\t\t\treturn;\n\t\t}\n\t\tconst providerIds = [...result.errors.keys()];\n\t\tif (providerIds.length > 0) {\n\t\t\tpicker.setRefreshStatus(refreshFailureMessage(providerIds), \"error\");\n\t\t\treturn;\n\t\t}\n\t\tconst registryError = ctx.modelRegistry.getError();\n\t\tif (registryError) {\n\t\t\tpicker.setRefreshStatus(boundText(registryError, MAX_REFRESH_ERROR_LENGTH), \"error\");\n\t\t\treturn;\n\t\t}\n\t\tpicker.setRefreshStatus(undefined);\n\t} catch (error) {\n\t\tif (picker.isClosed || (picker.refreshSignal.aborted && !timedOut)) return;\n\t\tconst message = timedOut\n\t\t\t? \"Model refresh timed out; showing cached models.\"\n\t\t\t: `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`;\n\t\tpicker.setRefreshStatus(boundText(message, MAX_REFRESH_ERROR_LENGTH), \"error\");\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\nasync function selectProfile(ctx: ExtensionCommandContext): Promise<AgentProfile | undefined> {\n\tconst labels = AGENT_PROFILES.map((profile) => PROFILE_LABELS[profile.name]);\n\tconst label = await ctx.ui.select(\"Agents\", labels);\n\treturn label === undefined ? undefined : AGENT_PROFILES.find((profile) => PROFILE_LABELS[profile.name] === label);\n}\n\nasync function showTuiSettingsMenu(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n\tcurrentThinking: ThinkingLevel,\n): Promise<SettingsAction | undefined> {\n\treturn ctx.ui.custom<SettingsAction | undefined>(\n\t\t(_tui, theme, keybindings, done) =>\n\t\t\tnew ProfileSettingsMenuComponent({\n\t\t\t\ttheme,\n\t\t\t\tkeybindings,\n\t\t\t\tprofile,\n\t\t\t\toverride,\n\t\t\t\tmodels: ctx.modelRegistry.getAvailable(),\n\t\t\t\tcurrentSessionModel: ctx.model,\n\t\t\t\tcurrentThinking,\n\t\t\t\tonDone: done,\n\t\t\t}),\n\t);\n}\n\nasync function showDialogSettingsMenu(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n\tcurrentThinking: ThinkingLevel,\n): Promise<SettingsAction | undefined> {\n\tconst models = ctx.modelRegistry.getAvailable();\n\tconst effective = effectiveModel(ctx.model, models, override);\n\tconst modelValue = override?.model\n\t\t? `override — ${override.model}${findModel(models, override.model) ? \"\" : \" [unavailable]\"}`\n\t\t: `inherit — ${modelId(ctx.model)}`;\n\tconst thinkingValue = override?.thinking\n\t\t? `override — ${override.thinking}`\n\t\t: `inherit — ${inheritedThinking(effective, currentThinking)}`;\n\tconst options = new Map<string, SettingsAction>();\n\toptions.set(`Model — ${modelValue}`, \"model\");\n\toptions.set(`Thinking — ${thinkingValue}`, \"thinking\");\n\tconst label = await ctx.ui.select(PROFILE_LABELS[profile.name], [...options.keys()]);\n\treturn label === undefined ? undefined : options.get(label);\n}\n\nasync function showTuiModelPicker(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n): Promise<{ modelId: string | undefined } | undefined> {\n\tconst chosen = await ctx.ui.custom<ProfileModelChoice | undefined>((tui, theme, keybindings, done) => {\n\t\tconst picker = new ModelPickerComponent({\n\t\t\ttui,\n\t\t\ttheme,\n\t\t\tkeybindings,\n\t\t\tprofile,\n\t\t\tsavedModelId: override?.model,\n\t\t\tmodels: ctx.modelRegistry.getAvailable(),\n\t\t\tscopedModels: ctx.scopedModels,\n\t\t\tcurrentSessionModel: ctx.model,\n\t\t\tonDone: done,\n\t\t});\n\t\tpicker.setRefreshStatus(\"Refreshing model catalogs…\");\n\t\tvoid refreshPickerModels(ctx, picker);\n\t\treturn picker;\n\t});\n\treturn chosen === undefined ? undefined : { modelId: chosen.modelId };\n}\n\nasync function showDialogModelPicker(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n): Promise<{ modelId: string | undefined } | undefined> {\n\tconst models = ctx.modelRegistry.getAvailable().sort((left, right) => {\n\t\tconst provider = left.provider.localeCompare(right.provider);\n\t\treturn provider !== 0 ? provider : left.id.localeCompare(right.id);\n\t});\n\tconst choices = new Map<string, string | undefined>();\n\tchoices.set(`inherit (${modelId(ctx.model)})${override?.model ? \"\" : \" ✓\"}`, undefined);\n\tif (override?.model && !findModel(models, override.model)) {\n\t\tchoices.set(`${override.model} [unavailable] ✓`, override.model);\n\t}\n\tfor (const model of models) {\n\t\tconst id = modelId(model);\n\t\tchoices.set(`${id}${override?.model === id ? \" ✓\" : \"\"}`, id);\n\t}\n\tconst label = await ctx.ui.select(`Model — ${PROFILE_LABELS[profile.name]}`, [...choices.keys()]);\n\treturn label === undefined ? undefined : { modelId: choices.get(label) };\n}\n\nasync function showThinkingPicker(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n\tcurrentThinking: ThinkingLevel,\n): Promise<{ level: ThinkingLevel | undefined } | undefined> {\n\tconst models = ctx.modelRegistry.getAvailable();\n\tconst effective = effectiveModel(ctx.model, models, override);\n\tconst levels = effective ? (getSupportedThinkingLevels(effective) as ThinkingLevel[]) : [...THINKING_LEVELS];\n\tconst inherited = inheritedThinking(effective, currentThinking);\n\tconst choices = new Map<string, ThinkingLevel | undefined>();\n\tchoices.set(`inherit (${inherited})${override?.thinking ? \"\" : \" ✓\"}`, undefined);\n\tfor (const level of levels) {\n\t\tchoices.set(`${level}${override?.thinking === level ? \" ✓\" : \"\"}`, level);\n\t}\n\tconst label = await ctx.ui.select(`Thinking — ${PROFILE_LABELS[profile.name]}`, [...choices.keys()]);\n\treturn label === undefined ? undefined : { level: choices.get(label) };\n}\n\nasync function runProfileSettings(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\tcurrentThinking: ThinkingLevel,\n): Promise<void> {\n\tconst agentDir = getAgentDir();\n\tconst isTui = ctx.mode === \"tui\";\n\twhile (true) {\n\t\tconst config = await loadSubagentConfig(agentDir);\n\t\tconst override = config.profiles[profile.name];\n\t\tconst action = isTui\n\t\t\t? await showTuiSettingsMenu(ctx, profile, override, currentThinking)\n\t\t\t: await showDialogSettingsMenu(ctx, profile, override, currentThinking);\n\t\tif (!action) return;\n\t\tif (action === \"model\") {\n\t\t\tconst chosen = isTui\n\t\t\t\t? await showTuiModelPicker(ctx, profile, override)\n\t\t\t\t: await showDialogModelPicker(ctx, profile, override);\n\t\t\tif (!chosen) continue;\n\t\t\tawait persistOverride(ctx, profile, { model: chosen.modelId }, override?.model);\n\t\t} else {\n\t\t\tconst chosen = await showThinkingPicker(ctx, profile, override, currentThinking);\n\t\t\tif (!chosen) continue;\n\t\t\tawait persistOverride(ctx, profile, { thinking: chosen.level }, override?.thinking);\n\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\twhile (true) {\n\t\tconst profile = await selectProfile(ctx);\n\t\tif (!profile) return;\n\t\tawait runProfileSettings(ctx, profile, currentThinking);\n\t}\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 type { Api, Model } from \"@earendil-works/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\ttype KeybindingsManager,\n\tSpacer,\n\tText,\n\tTruncatedText,\n\ttype TUI,\n} from \"@earendil-works/pi-tui\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/types.ts\";\nimport { DynamicBorder } from \"../../modes/interactive/components/dynamic-border.ts\";\nimport { keyLabel } from \"../../modes/interactive/components/keybinding-hints.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 { truncate } from \"./text.ts\";\nimport type { AgentProfile, SubagentProfileOverride } from \"./types.ts\";\nimport {\n\tbuildModelChoices,\n\tbuildSettingsRows,\n\tbuildThinkingChoices,\n\tcompareModels,\n\ttype SettingsAction,\n\ttype SettingsRow,\n} from \"./ui/choices.ts\";\nimport { type ProfileModelChoice, ProfileModelListComponent } from \"./ui/model-list.ts\";\n\nconst MODEL_REFRESH_TIMEOUT_MS = 15_000;\nconst MAX_REFRESH_ERROR_LENGTH = 240;\n\nfunction refreshFailureMessage(providerIds: readonly string[]): string {\n\tif (providerIds.length === 1) return `Could not refresh ${providerIds[0]}; showing cached models.`;\n\tconst visible = providerIds.slice(0, 3);\n\tconst omitted = providerIds.length - visible.length;\n\tconst suffix = omitted > 0 ? `, +${omitted} more` : \"\";\n\treturn `Could not refresh ${providerIds.length} model catalogs (${visible.join(\", \")}${suffix}); showing cached models.`;\n}\n\nfunction hint(\n\ttheme: Theme,\n\tkeybindings: KeybindingsManager,\n\tbinding: Parameters<KeybindingsManager[\"getKeys\"]>[0],\n\tdescription: string,\n): string {\n\tconst key = keyLabel(binding, { keybindings });\n\treturn key ? `${theme.fg(\"dim\", key)}${theme.fg(\"muted\", ` ${description}`)}` : \"\";\n}\n\nfunction navigationHint(theme: Theme, keybindings: KeybindingsManager): string {\n\tconst keys = [keyLabel(\"tui.select.up\", { keybindings }), keyLabel(\"tui.select.down\", { keybindings })]\n\t\t.filter(Boolean)\n\t\t.join(\"/\");\n\treturn keys ? `${theme.fg(\"dim\", keys)}${theme.fg(\"muted\", \" navigate\")}` : \"\";\n}\n\n/** Compact Model/Thinking settings menu for one profile; every confirm persists immediately. */\nclass ProfileSettingsMenuComponent extends Container implements Focusable {\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly rows: readonly SettingsRow[];\n\tprivate readonly onDone: (action: SettingsAction | undefined) => void;\n\tprivate readonly listContainer: Container;\n\tprivate selectedIndex = 0;\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}\n\n\tconstructor(options: {\n\t\ttheme: Theme;\n\t\tkeybindings: KeybindingsManager;\n\t\tprofile: AgentProfile;\n\t\toverride: SubagentProfileOverride | undefined;\n\t\tmodels: readonly Model<Api>[];\n\t\tcurrentSessionModel: Model<Api> | undefined;\n\t\tcurrentThinking: ThinkingLevel;\n\t\tonDone: (action: SettingsAction | undefined) => void;\n\t}) {\n\t\tsuper();\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.onDone = options.onDone;\n\t\tthis.rows = buildSettingsRows({\n\t\t\toverride: options.override,\n\t\t\tmodels: options.models,\n\t\t\tcurrentSessionModel: options.currentSessionModel,\n\t\t\tcurrentThinking: options.currentThinking,\n\t\t}) satisfies SettingsRow[];\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(this.theme.fg(\"accent\", this.theme.bold(AGENT_PROFILE_LABELS[options.profile.name])), 1, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\t\tthis.addChild(new Spacer(1));\n\t\tconst hints = [\n\t\t\tnavigationHint(this.theme, options.keybindings),\n\t\t\thint(this.theme, options.keybindings, \"tui.select.confirm\", \"select\"),\n\t\t\thint(this.theme, options.keybindings, \"tui.select.cancel\", \"back\"),\n\t\t].filter(Boolean);\n\t\tthis.addChild(new Text(hints.join(this.theme.fg(\"muted\", \" • \")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\t\tfor (const [index, row] of this.rows.entries()) {\n\t\t\tconst selected = index === this.selectedIndex;\n\t\t\tconst prefix = selected ? this.theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst label = selected ? this.theme.fg(\"accent\", row.label) : this.theme.fg(\"text\", row.label);\n\t\t\tconst value = this.theme.fg(\"muted\", `— ${row.value}`);\n\t\t\tconst checkmark = row.override ? this.theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(`${prefix}${label} ${value}${checkmark}`, 1, 0));\n\t\t}\n\t}\n\n\tprivate moveSelection(offset: -1 | 1): void {\n\t\tthis.selectedIndex = (this.selectedIndex + offset + this.rows.length) % this.rows.length;\n\t\tthis.updateList();\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.moveSelection(-1);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.moveSelection(1);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.onDone(this.rows[this.selectedIndex]?.action);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onDone(undefined);\n\t\t}\n\t}\n}\n\n/** Standalone searchable model picker for one profile; confirm saves immediately. */\nclass ModelPickerComponent extends Container implements Focusable {\n\tprivate readonly tui: TUI;\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly modelList: ProfileModelListComponent;\n\tprivate readonly refreshAbortController = new AbortController();\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\tthis.modelList.focused = value;\n\t}\n\n\tconstructor(options: {\n\t\ttui: TUI;\n\t\ttheme: Theme;\n\t\tkeybindings: KeybindingsManager;\n\t\tprofile: AgentProfile;\n\t\tsavedModelId: string | undefined;\n\t\tmodels: readonly Model<Api>[];\n\t\tscopedModels: readonly { model: Model<Api> }[];\n\t\tcurrentSessionModel: Model<Api> | undefined;\n\t\tonDone: (choice: ProfileModelChoice | undefined) => 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.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(\n\t\t\t\tthis.theme.fg(\"accent\", this.theme.bold(`Model — ${AGENT_PROFILE_LABELS[options.profile.name]}`)),\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.modelList = new ProfileModelListComponent({\n\t\t\ttheme: options.theme,\n\t\t\tkeybindings: options.keybindings,\n\t\t\tmodels: options.models,\n\t\t\tscopedModels: options.scopedModels,\n\t\t\tcurrentSessionModel: options.currentSessionModel,\n\t\t\tsavedModelId: options.savedModelId,\n\t\t\tonDone: options.onDone,\n\t\t});\n\t\tthis.addChild(this.modelList);\n\t\tthis.addChild(new Spacer(1));\n\t\tconst hints = [\n\t\t\tnavigationHint(this.theme, options.keybindings),\n\t\t\toptions.scopedModels.length > 0 ? hint(this.theme, options.keybindings, \"tui.input.tab\", \"scope\") : \"\",\n\t\t\thint(this.theme, options.keybindings, \"tui.select.confirm\", \"select\"),\n\t\t\thint(this.theme, options.keybindings, \"tui.select.cancel\", \"back\"),\n\t\t].filter(Boolean);\n\t\tthis.addChild(new Text(hints.join(this.theme.fg(\"muted\", \" • \")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tget refreshSignal(): AbortSignal {\n\t\treturn this.refreshAbortController.signal;\n\t}\n\n\tcancelRefresh(): void {\n\t\tthis.refreshAbortController.abort();\n\t}\n\n\tget isClosed(): boolean {\n\t\treturn this.closed;\n\t}\n\n\tdispose(): void {\n\t\tthis.closed = true;\n\t\tthis.refreshAbortController.abort();\n\t}\n\n\tupdateModels(models: readonly Model<Api>[]): void {\n\t\tif (this.closed) return;\n\t\tthis.modelList.updateModels(models);\n\t\tthis.tui.requestRender();\n\t}\n\n\tsetRefreshStatus(message: string | undefined, tone: \"muted\" | \"success\" | \"error\" = \"muted\"): void {\n\t\tif (this.closed) return;\n\t\tthis.modelList.setStatus(message, tone);\n\t\tthis.tui.requestRender();\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.modelList.handleInput(data);\n\t}\n}\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\tcurrent: string | ThinkingLevel | undefined,\n): Promise<void> {\n\tconst next = \"model\" in patch ? patch.model : patch.thinking;\n\tif (next === current) return;\n\ttry {\n\t\tawait 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}\n}\n\nasync function refreshPickerModels(ctx: ExtensionCommandContext, picker: ModelPickerComponent): Promise<void> {\n\tlet timedOut = false;\n\tconst timeout = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tpicker.cancelRefresh();\n\t}, MODEL_REFRESH_TIMEOUT_MS);\n\ttimeout.unref?.();\n\ttry {\n\t\tconst result = await ctx.modelRegistry.refresh({ signal: picker.refreshSignal });\n\t\tif (picker.isClosed || (picker.refreshSignal.aborted && !timedOut)) return;\n\t\tpicker.updateModels(ctx.modelRegistry.getAvailable());\n\t\tif (result.aborted && timedOut) {\n\t\t\tpicker.setRefreshStatus(\"Model refresh timed out; showing cached models.\", \"error\");\n\t\t\treturn;\n\t\t}\n\t\tconst providerIds = [...result.errors.keys()];\n\t\tif (providerIds.length > 0) {\n\t\t\tpicker.setRefreshStatus(refreshFailureMessage(providerIds), \"error\");\n\t\t\treturn;\n\t\t}\n\t\tconst registryError = ctx.modelRegistry.getError();\n\t\tif (registryError) {\n\t\t\tpicker.setRefreshStatus(truncate(registryError, MAX_REFRESH_ERROR_LENGTH), \"error\");\n\t\t\treturn;\n\t\t}\n\t\tpicker.setRefreshStatus(undefined);\n\t} catch (error) {\n\t\tif (picker.isClosed || (picker.refreshSignal.aborted && !timedOut)) return;\n\t\tconst message = timedOut\n\t\t\t? \"Model refresh timed out; showing cached models.\"\n\t\t\t: `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`;\n\t\tpicker.setRefreshStatus(truncate(message, MAX_REFRESH_ERROR_LENGTH), \"error\");\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\nasync function selectProfile(ctx: ExtensionCommandContext): Promise<AgentProfile | undefined> {\n\tconst labels = AGENT_PROFILES.map((profile) => AGENT_PROFILE_LABELS[profile.name]);\n\tconst label = await ctx.ui.select(\"Agents\", labels);\n\treturn label === undefined\n\t\t? undefined\n\t\t: AGENT_PROFILES.find((profile) => AGENT_PROFILE_LABELS[profile.name] === label);\n}\n\nasync function showTuiSettingsMenu(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n\tcurrentThinking: ThinkingLevel,\n): Promise<SettingsAction | undefined> {\n\treturn ctx.ui.custom<SettingsAction | undefined>(\n\t\t(_tui, theme, keybindings, done) =>\n\t\t\tnew ProfileSettingsMenuComponent({\n\t\t\t\ttheme,\n\t\t\t\tkeybindings,\n\t\t\t\tprofile,\n\t\t\t\toverride,\n\t\t\t\tmodels: ctx.modelRegistry.getAvailable(),\n\t\t\t\tcurrentSessionModel: ctx.model,\n\t\t\t\tcurrentThinking,\n\t\t\t\tonDone: done,\n\t\t\t}),\n\t);\n}\n\nasync function showDialogSettingsMenu(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n\tcurrentThinking: ThinkingLevel,\n): Promise<SettingsAction | undefined> {\n\tconst options = new Map<string, SettingsAction>();\n\tfor (const row of buildSettingsRows({\n\t\toverride,\n\t\tmodels: ctx.modelRegistry.getAvailable(),\n\t\tcurrentSessionModel: ctx.model,\n\t\tcurrentThinking,\n\t})) {\n\t\toptions.set(`${row.label} — ${row.value}`, row.action);\n\t}\n\tconst label = await ctx.ui.select(AGENT_PROFILE_LABELS[profile.name], [...options.keys()]);\n\treturn label === undefined ? undefined : options.get(label);\n}\n\nasync function showTuiModelPicker(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n): Promise<{ modelId: string | undefined } | undefined> {\n\tconst chosen = await ctx.ui.custom<ProfileModelChoice | undefined>((tui, theme, keybindings, done) => {\n\t\tconst picker = new ModelPickerComponent({\n\t\t\ttui,\n\t\t\ttheme,\n\t\t\tkeybindings,\n\t\t\tprofile,\n\t\t\tsavedModelId: override?.model,\n\t\t\tmodels: ctx.modelRegistry.getAvailable(),\n\t\t\tscopedModels: ctx.scopedModels,\n\t\t\tcurrentSessionModel: ctx.model,\n\t\t\tonDone: done,\n\t\t});\n\t\tpicker.setRefreshStatus(\"Refreshing model catalogs…\");\n\t\tvoid refreshPickerModels(ctx, picker);\n\t\treturn picker;\n\t});\n\treturn chosen === undefined ? undefined : { modelId: chosen.modelId };\n}\n\nasync function showDialogModelPicker(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n): Promise<{ modelId: string | undefined } | undefined> {\n\tconst models = [...ctx.modelRegistry.getAvailable()].sort(compareModels);\n\tconst choices = buildModelChoices({\n\t\tmodels,\n\t\tcurrentSessionModel: ctx.model,\n\t\tsavedModelId: override?.model,\n\t});\n\tconst label = await ctx.ui.select(`Model — ${AGENT_PROFILE_LABELS[profile.name]}`, [...choices.keys()]);\n\treturn label === undefined ? undefined : { modelId: choices.get(label) };\n}\n\nasync function showThinkingPicker(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\toverride: SubagentProfileOverride | undefined,\n\tcurrentThinking: ThinkingLevel,\n): Promise<{ level: ThinkingLevel | undefined } | undefined> {\n\tconst choices = buildThinkingChoices({\n\t\tcurrentSessionModel: ctx.model,\n\t\tmodels: ctx.modelRegistry.getAvailable(),\n\t\toverride,\n\t\tcurrentThinking,\n\t});\n\tconst label = await ctx.ui.select(`Thinking — ${AGENT_PROFILE_LABELS[profile.name]}`, [...choices.keys()]);\n\treturn label === undefined ? undefined : { level: choices.get(label) };\n}\n\nasync function runProfileSettings(\n\tctx: ExtensionCommandContext,\n\tprofile: AgentProfile,\n\tcurrentThinking: ThinkingLevel,\n): Promise<void> {\n\tconst agentDir = getAgentDir();\n\tconst isTui = ctx.mode === \"tui\";\n\twhile (true) {\n\t\tconst config = await loadSubagentConfig(agentDir);\n\t\tconst override = config.profiles[profile.name];\n\t\tconst action = isTui\n\t\t\t? await showTuiSettingsMenu(ctx, profile, override, currentThinking)\n\t\t\t: await showDialogSettingsMenu(ctx, profile, override, currentThinking);\n\t\tif (!action) return;\n\t\tif (action === \"model\") {\n\t\t\tconst chosen = isTui\n\t\t\t\t? await showTuiModelPicker(ctx, profile, override)\n\t\t\t\t: await showDialogModelPicker(ctx, profile, override);\n\t\t\tif (!chosen) continue;\n\t\t\tawait persistOverride(ctx, profile, { model: chosen.modelId }, override?.model);\n\t\t} else {\n\t\t\tconst chosen = await showThinkingPicker(ctx, profile, override, currentThinking);\n\t\t\tif (!chosen) continue;\n\t\t\tawait persistOverride(ctx, profile, { thinking: chosen.level }, override?.thinking);\n\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\twhile (true) {\n\t\tconst profile = await selectProfile(ctx);\n\t\tif (!profile) return;\n\t\tawait runProfileSettings(ctx, profile, currentThinking);\n\t}\n}\n"]}
@@ -1,4 +1,6 @@
1
+ import { type SubagentAgentName } from "./constants.ts";
1
2
  import type { AgentProfile } from "./types.ts";
3
+ export declare const AGENT_PROFILE_LABELS: Record<SubagentAgentName, string>;
2
4
  export declare const AGENT_PROFILES: readonly AgentProfile[];
3
5
  export declare function subagentToolDescription(): string;
4
6
  //# sourceMappingURL=agents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EA6BjD,CAAC;AAIF,wBAAgB,uBAAuB,IAAI,MAAM,CAYhD"}
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,4 +1,10 @@
1
- import { DEFAULT_AGENT_TOOLS, EXPLORER_TOOLS, MAX_CONCURRENCY, MAX_TASKS } from "./constants.js";
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
+ };
2
8
  export const AGENT_PROFILES = [
3
9
  {
4
10
  name: "explorer",
@@ -1 +1 @@
1
- {"version":3,"file":"agents.js","sourceRoot":"","sources":["../../../src/extensions/subagent/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGjG,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 { DEFAULT_AGENT_TOOLS, EXPLORER_TOOLS, MAX_CONCURRENCY, MAX_TASKS } from \"./constants.ts\";\nimport type { AgentProfile } from \"./types.ts\";\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"]}
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"}