@astralyn/pi 0.84.4 → 0.84.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/cli/args.d.ts +1 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +11 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/auth-command.d.ts.map +1 -1
  7. package/dist/cli/auth-command.js +5 -4
  8. package/dist/cli/auth-command.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +6 -1
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +11 -6
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/experimental.d.ts +4 -0
  14. package/dist/core/experimental.d.ts.map +1 -1
  15. package/dist/core/experimental.js +4 -0
  16. package/dist/core/experimental.js.map +1 -1
  17. package/dist/core/extensions/index.d.ts +1 -1
  18. package/dist/core/extensions/index.d.ts.map +1 -1
  19. package/dist/core/extensions/index.js.map +1 -1
  20. package/dist/core/extensions/runner.d.ts +1 -0
  21. package/dist/core/extensions/runner.d.ts.map +1 -1
  22. package/dist/core/extensions/runner.js +10 -0
  23. package/dist/core/extensions/runner.js.map +1 -1
  24. package/dist/core/extensions/types.d.ts +19 -1
  25. package/dist/core/extensions/types.d.ts.map +1 -1
  26. package/dist/core/extensions/types.js.map +1 -1
  27. package/dist/core/keybindings.d.ts +29 -0
  28. package/dist/core/keybindings.d.ts.map +1 -1
  29. package/dist/core/keybindings.js +4 -0
  30. package/dist/core/keybindings.js.map +1 -1
  31. package/dist/core/model-config.d.ts +5 -0
  32. package/dist/core/model-config.d.ts.map +1 -1
  33. package/dist/core/model-config.js +1 -0
  34. package/dist/core/model-config.js.map +1 -1
  35. package/dist/core/model-registry.d.ts +2 -0
  36. package/dist/core/model-registry.d.ts.map +1 -1
  37. package/dist/core/model-registry.js +4 -0
  38. package/dist/core/model-registry.js.map +1 -1
  39. package/dist/core/project-trust.js +2 -2
  40. package/dist/core/project-trust.js.map +1 -1
  41. package/dist/core/sdk.d.ts +5 -3
  42. package/dist/core/sdk.d.ts.map +1 -1
  43. package/dist/core/sdk.js +2 -1
  44. package/dist/core/sdk.js.map +1 -1
  45. package/dist/core/session-manager.js +2 -2
  46. package/dist/core/session-manager.js.map +1 -1
  47. package/dist/core/settings-manager.d.ts +6 -0
  48. package/dist/core/settings-manager.d.ts.map +1 -1
  49. package/dist/core/settings-manager.js +12 -0
  50. package/dist/core/settings-manager.js.map +1 -1
  51. package/dist/core/system-prompt.js +1 -1
  52. package/dist/core/system-prompt.js.map +1 -1
  53. package/dist/core/tools/bash.d.ts +7 -1
  54. package/dist/core/tools/bash.d.ts.map +1 -1
  55. package/dist/core/tools/bash.js +4 -2
  56. package/dist/core/tools/bash.js.map +1 -1
  57. package/dist/core/tools/edit.d.ts.map +1 -1
  58. package/dist/core/tools/edit.js +2 -0
  59. package/dist/core/tools/edit.js.map +1 -1
  60. package/dist/core/tools/find.js +1 -1
  61. package/dist/core/tools/find.js.map +1 -1
  62. package/dist/core/tools/grep.js +1 -1
  63. package/dist/core/tools/grep.js.map +1 -1
  64. package/dist/core/tools/read.d.ts.map +1 -1
  65. package/dist/core/tools/read.js +2 -0
  66. package/dist/core/tools/read.js.map +1 -1
  67. package/dist/core/tools/write.d.ts.map +1 -1
  68. package/dist/core/tools/write.js +2 -0
  69. package/dist/core/tools/write.js.map +1 -1
  70. package/dist/extensions/background/index.d.ts +149 -0
  71. package/dist/extensions/background/index.d.ts.map +1 -0
  72. package/dist/extensions/background/index.js +666 -0
  73. package/dist/extensions/background/index.js.map +1 -0
  74. package/dist/extensions/background/manager.d.ts +95 -0
  75. package/dist/extensions/background/manager.d.ts.map +1 -0
  76. package/dist/extensions/background/manager.js +421 -0
  77. package/dist/extensions/background/manager.js.map +1 -0
  78. package/dist/extensions/background/registry.d.ts +220 -0
  79. package/dist/extensions/background/registry.d.ts.map +1 -0
  80. package/dist/extensions/background/registry.js +589 -0
  81. package/dist/extensions/background/registry.js.map +1 -0
  82. package/dist/extensions/background/render.d.ts +50 -0
  83. package/dist/extensions/background/render.d.ts.map +1 -0
  84. package/dist/extensions/background/render.js +260 -0
  85. package/dist/extensions/background/render.js.map +1 -0
  86. package/dist/extensions/index.d.ts.map +1 -1
  87. package/dist/extensions/index.js +2 -0
  88. package/dist/extensions/index.js.map +1 -1
  89. package/dist/extensions/subagent/activity.d.ts +3 -6
  90. package/dist/extensions/subagent/activity.d.ts.map +1 -1
  91. package/dist/extensions/subagent/activity.js +9 -93
  92. package/dist/extensions/subagent/activity.js.map +1 -1
  93. package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
  94. package/dist/extensions/subagent/agents-command.js +270 -169
  95. package/dist/extensions/subagent/agents-command.js.map +1 -1
  96. package/dist/extensions/subagent/agents.d.ts +5 -6
  97. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  98. package/dist/extensions/subagent/agents.js +28 -192
  99. package/dist/extensions/subagent/agents.js.map +1 -1
  100. package/dist/extensions/subagent/budget.d.ts +15 -0
  101. package/dist/extensions/subagent/budget.d.ts.map +1 -0
  102. package/dist/extensions/subagent/budget.js +96 -0
  103. package/dist/extensions/subagent/budget.js.map +1 -0
  104. package/dist/extensions/subagent/cancellation.d.ts +29 -0
  105. package/dist/extensions/subagent/cancellation.d.ts.map +1 -0
  106. package/dist/extensions/subagent/cancellation.js +73 -0
  107. package/dist/extensions/subagent/cancellation.js.map +1 -0
  108. package/dist/extensions/subagent/constants.d.ts +4 -5
  109. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  110. package/dist/extensions/subagent/constants.js +11 -7
  111. package/dist/extensions/subagent/constants.js.map +1 -1
  112. package/dist/extensions/subagent/index.d.ts +0 -3
  113. package/dist/extensions/subagent/index.d.ts.map +1 -1
  114. package/dist/extensions/subagent/index.js +59 -208
  115. package/dist/extensions/subagent/index.js.map +1 -1
  116. package/dist/extensions/subagent/model-selection.d.ts +16 -0
  117. package/dist/extensions/subagent/model-selection.d.ts.map +1 -0
  118. package/dist/extensions/subagent/model-selection.js +51 -0
  119. package/dist/extensions/subagent/model-selection.js.map +1 -0
  120. package/dist/extensions/subagent/render.d.ts +7 -2
  121. package/dist/extensions/subagent/render.d.ts.map +1 -1
  122. package/dist/extensions/subagent/render.js +219 -576
  123. package/dist/extensions/subagent/render.js.map +1 -1
  124. package/dist/extensions/subagent/resolve.d.ts +2 -2
  125. package/dist/extensions/subagent/resolve.d.ts.map +1 -1
  126. package/dist/extensions/subagent/resolve.js +24 -35
  127. package/dist/extensions/subagent/resolve.js.map +1 -1
  128. package/dist/extensions/subagent/runner.d.ts +4 -6
  129. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  130. package/dist/extensions/subagent/runner.js +101 -316
  131. package/dist/extensions/subagent/runner.js.map +1 -1
  132. package/dist/extensions/subagent/schema.d.ts +4 -10
  133. package/dist/extensions/subagent/schema.d.ts.map +1 -1
  134. package/dist/extensions/subagent/schema.js +8 -13
  135. package/dist/extensions/subagent/schema.js.map +1 -1
  136. package/dist/extensions/subagent/sdk-runner.d.ts +13 -11
  137. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  138. package/dist/extensions/subagent/sdk-runner.js +169 -161
  139. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  140. package/dist/extensions/subagent/settings.d.ts +2 -2
  141. package/dist/extensions/subagent/settings.d.ts.map +1 -1
  142. package/dist/extensions/subagent/settings.js +27 -14
  143. package/dist/extensions/subagent/settings.js.map +1 -1
  144. package/dist/extensions/subagent/state.d.ts +89 -0
  145. package/dist/extensions/subagent/state.d.ts.map +1 -0
  146. package/dist/extensions/subagent/state.js +294 -0
  147. package/dist/extensions/subagent/state.js.map +1 -0
  148. package/dist/extensions/subagent/text.d.ts +7 -0
  149. package/dist/extensions/subagent/text.d.ts.map +1 -0
  150. package/dist/extensions/subagent/text.js +91 -0
  151. package/dist/extensions/subagent/text.js.map +1 -0
  152. package/dist/extensions/subagent/types.d.ts +16 -43
  153. package/dist/extensions/subagent/types.d.ts.map +1 -1
  154. package/dist/extensions/subagent/types.js.map +1 -1
  155. package/dist/extensions/subagent/ui/choices.d.ts +36 -0
  156. package/dist/extensions/subagent/ui/choices.d.ts.map +1 -0
  157. package/dist/extensions/subagent/ui/choices.js +54 -0
  158. package/dist/extensions/subagent/ui/choices.js.map +1 -0
  159. package/dist/extensions/subagent/ui/model-list.d.ts +4 -3
  160. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
  161. package/dist/extensions/subagent/ui/model-list.js +20 -22
  162. package/dist/extensions/subagent/ui/model-list.js.map +1 -1
  163. package/dist/index.d.ts +2 -2
  164. package/dist/index.d.ts.map +1 -1
  165. package/dist/index.js.map +1 -1
  166. package/dist/main.d.ts.map +1 -1
  167. package/dist/main.js +5 -1
  168. package/dist/main.js.map +1 -1
  169. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/model-selector.js +2 -1
  171. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  172. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  173. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/settings-selector.js +10 -0
  175. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  176. package/dist/modes/interactive/interactive-mode.d.ts +8 -2
  177. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  178. package/dist/modes/interactive/interactive-mode.js +77 -25
  179. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  180. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  181. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  182. package/dist/modes/interactive/model-catalog-refresh.js +36 -0
  183. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  184. package/dist/modes/interactive/theme/dark.json +2 -0
  185. package/dist/modes/interactive/theme/light.json +2 -0
  186. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  187. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  188. package/dist/modes/interactive/theme/theme-controller.js +23 -10
  189. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  190. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  191. package/dist/modes/interactive/theme/theme.d.ts +5 -3
  192. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  193. package/dist/modes/interactive/theme/theme.js +12 -2
  194. package/dist/modes/interactive/theme/theme.js.map +1 -1
  195. package/dist/modes/json-event.d.ts +4 -1
  196. package/dist/modes/json-event.d.ts.map +1 -1
  197. package/dist/modes/json-event.js +5 -2
  198. package/dist/modes/json-event.js.map +1 -1
  199. package/dist/package-manager-cli.js +1 -1
  200. package/dist/package-manager-cli.js.map +1 -1
  201. package/dist/server/create-harness.d.ts.map +1 -1
  202. package/dist/server/create-harness.js +2 -0
  203. package/dist/server/create-harness.js.map +1 -1
  204. package/dist/utils/tools-manager.d.ts +10 -1
  205. package/dist/utils/tools-manager.d.ts.map +1 -1
  206. package/dist/utils/tools-manager.js +14 -19
  207. package/dist/utils/tools-manager.js.map +1 -1
  208. package/docs/bundled/README.md +1 -0
  209. package/docs/bundled/extensions/background.md +99 -0
  210. package/docs/bundled/extensions/subagent.md +83 -71
  211. package/docs/compaction.md +6 -6
  212. package/docs/custom-provider.md +1 -1
  213. package/docs/docs.json +4 -0
  214. package/docs/environment-variables.md +8 -2
  215. package/docs/extensions.md +19 -2
  216. package/docs/json.md +6 -4
  217. package/docs/keybindings.md +9 -2
  218. package/docs/rpc.md +15 -4
  219. package/docs/sdk.md +9 -0
  220. package/docs/settings.md +31 -0
  221. package/docs/terminal-setup.md +23 -2
  222. package/docs/themes.md +24 -3
  223. package/docs/tui.md +2 -2
  224. package/docs/usage.md +4 -3
  225. package/examples/README.md +1 -1
  226. package/examples/extensions/README.md +0 -1
  227. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  228. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  229. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  230. package/examples/extensions/gondolin/package-lock.json +2 -2
  231. package/examples/extensions/gondolin/package.json +1 -1
  232. package/examples/extensions/sandbox/package-lock.json +2 -2
  233. package/examples/extensions/sandbox/package.json +1 -1
  234. package/examples/extensions/with-deps/package-lock.json +2 -2
  235. package/examples/extensions/with-deps/package.json +1 -1
  236. package/npm-shrinkwrap.json +170 -221
  237. package/package.json +6 -6
  238. package/dist/extensions/subagent/display-name.d.ts +0 -6
  239. package/dist/extensions/subagent/display-name.d.ts.map +0 -1
  240. package/dist/extensions/subagent/display-name.js +0 -13
  241. package/dist/extensions/subagent/display-name.js.map +0 -1
  242. package/dist/extensions/subagent/retry.d.ts +0 -17
  243. package/dist/extensions/subagent/retry.d.ts.map +0 -1
  244. package/dist/extensions/subagent/retry.js +0 -41
  245. package/dist/extensions/subagent/retry.js.map +0 -1
  246. package/dist/extensions/subagent/ui/profile-editor.d.ts +0 -54
  247. package/dist/extensions/subagent/ui/profile-editor.d.ts.map +0 -1
  248. package/dist/extensions/subagent/ui/profile-editor.js +0 -154
  249. package/dist/extensions/subagent/ui/profile-editor.js.map +0 -1
  250. package/dist/extensions/subagent/ui/profile-picker.d.ts +0 -32
  251. package/dist/extensions/subagent/ui/profile-picker.d.ts.map +0 -1
  252. package/dist/extensions/subagent/ui/profile-picker.js +0 -149
  253. package/dist/extensions/subagent/ui/profile-picker.js.map +0 -1
  254. package/examples/extensions/subagent/README.md +0 -175
  255. package/examples/extensions/subagent/agents/planner.md +0 -37
  256. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  257. package/examples/extensions/subagent/agents/scout.md +0 -50
  258. package/examples/extensions/subagent/agents/worker.md +0 -24
  259. package/examples/extensions/subagent/agents.ts +0 -126
  260. package/examples/extensions/subagent/index.ts +0 -1009
  261. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  262. package/examples/extensions/subagent/prompts/implement.md +0 -10
  263. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
@@ -1,220 +1,319 @@
1
- import { clampThinkingLevel, getSupportedThinkingLevels } from "@earendil-works/pi-ai/compat";
1
+ import { Container, Spacer, Text, TruncatedText, } from "@earendil-works/pi-tui";
2
2
  import { getAgentDir } from "../../config.js";
3
- import { discoverAgents } from "./agents.js";
4
- import { THINKING_LEVELS } from "./constants.js";
5
- import { displayAgentName } from "./display-name.js";
3
+ import { DynamicBorder } from "../../modes/interactive/components/dynamic-border.js";
4
+ import { keyLabel } from "../../modes/interactive/components/keybinding-hints.js";
5
+ import { AGENT_PROFILE_LABELS, AGENT_PROFILES } from "./agents.js";
6
6
  import { loadSubagentConfig, updateProfileOverride } from "./settings.js";
7
- import { ProfileEditorComponent } from "./ui/profile-editor.js";
8
- import { ProfilePickerComponent } from "./ui/profile-picker.js";
7
+ import { truncate } from "./text.js";
8
+ import { buildModelChoices, buildSettingsRows, buildThinkingChoices, compareModels, } from "./ui/choices.js";
9
+ import { ProfileModelListComponent } from "./ui/model-list.js";
9
10
  const MODEL_REFRESH_TIMEOUT_MS = 15_000;
10
- const MAX_DIAGNOSTICS = 20;
11
- const MAX_DIAGNOSTIC_LENGTH = 240;
12
11
  const MAX_REFRESH_ERROR_LENGTH = 240;
13
- function compareAgentNames(left, right) {
14
- if (left.name < right.name)
15
- return -1;
16
- if (left.name > right.name)
17
- return 1;
18
- return 0;
19
- }
20
- function modelId(model) {
21
- return model ? `${model.provider}/${model.id}` : "none";
12
+ function refreshFailureMessage(providerIds) {
13
+ if (providerIds.length === 1)
14
+ return `Could not refresh ${providerIds[0]}; showing cached models.`;
15
+ const visible = providerIds.slice(0, 3);
16
+ const omitted = providerIds.length - visible.length;
17
+ const suffix = omitted > 0 ? `, +${omitted} more` : "";
18
+ return `Could not refresh ${providerIds.length} model catalogs (${visible.join(", ")}${suffix}); showing cached models.`;
22
19
  }
23
- function findModel(models, value) {
24
- if (!value)
25
- return undefined;
26
- return models.find((model) => `${model.provider}/${model.id}` === value);
20
+ function hint(theme, keybindings, binding, description) {
21
+ const key = keyLabel(binding, { keybindings });
22
+ return key ? `${theme.fg("dim", key)}${theme.fg("muted", ` ${description}`)}` : "";
27
23
  }
28
- function boundText(value, limit) {
29
- const characters = [...value];
30
- return characters.length <= limit ? value : `${characters.slice(0, Math.max(0, limit - 1)).join("")}…`;
24
+ function navigationHint(theme, keybindings) {
25
+ const keys = [keyLabel("tui.select.up", { keybindings }), keyLabel("tui.select.down", { keybindings })]
26
+ .filter(Boolean)
27
+ .join("/");
28
+ return keys ? `${theme.fg("dim", keys)}${theme.fg("muted", " navigate")}` : "";
31
29
  }
32
- function formatDiagnostics(diagnostics) {
33
- const visible = diagnostics
34
- .slice(0, MAX_DIAGNOSTICS)
35
- .map((diagnostic) => boundText(`${diagnostic.path}: ${diagnostic.message}`, MAX_DIAGNOSTIC_LENGTH));
36
- if (diagnostics.length > visible.length) {
37
- visible.push(`… ${diagnostics.length - visible.length} more issue${diagnostics.length - visible.length === 1 ? "" : "s"}`);
38
- }
39
- return visible.join("\n");
30
+ /** Compact Model/Thinking settings menu for one profile; every confirm persists immediately. */
31
+ class ProfileSettingsMenuComponent extends Container {
32
+ get focused() {
33
+ return this._focused;
34
+ }
35
+ set focused(value) {
36
+ this._focused = value;
37
+ }
38
+ constructor(options) {
39
+ super();
40
+ this.selectedIndex = 0;
41
+ this._focused = false;
42
+ this.theme = options.theme;
43
+ this.keybindings = options.keybindings;
44
+ this.onDone = options.onDone;
45
+ this.rows = buildSettingsRows({
46
+ override: options.override,
47
+ models: options.models,
48
+ currentSessionModel: options.currentSessionModel,
49
+ currentThinking: options.currentThinking,
50
+ });
51
+ this.addChild(new DynamicBorder());
52
+ this.addChild(new Spacer(1));
53
+ this.addChild(new Text(this.theme.fg("accent", this.theme.bold(AGENT_PROFILE_LABELS[options.profile.name])), 1, 0));
54
+ this.addChild(new Spacer(1));
55
+ this.listContainer = new Container();
56
+ this.addChild(this.listContainer);
57
+ this.addChild(new Spacer(1));
58
+ const hints = [
59
+ navigationHint(this.theme, options.keybindings),
60
+ hint(this.theme, options.keybindings, "tui.select.confirm", "select"),
61
+ hint(this.theme, options.keybindings, "tui.select.cancel", "back"),
62
+ ].filter(Boolean);
63
+ this.addChild(new Text(hints.join(this.theme.fg("muted", " • ")), 1, 0));
64
+ this.addChild(new Spacer(1));
65
+ this.addChild(new DynamicBorder());
66
+ this.updateList();
67
+ }
68
+ updateList() {
69
+ this.listContainer.clear();
70
+ for (const [index, row] of this.rows.entries()) {
71
+ const selected = index === this.selectedIndex;
72
+ const prefix = selected ? this.theme.fg("accent", "→ ") : " ";
73
+ const label = selected ? this.theme.fg("accent", row.label) : this.theme.fg("text", row.label);
74
+ const value = this.theme.fg("muted", `— ${row.value}`);
75
+ const checkmark = row.override ? this.theme.fg("success", " ✓") : "";
76
+ this.listContainer.addChild(new TruncatedText(`${prefix}${label} ${value}${checkmark}`, 1, 0));
77
+ }
78
+ }
79
+ moveSelection(offset) {
80
+ this.selectedIndex = (this.selectedIndex + offset + this.rows.length) % this.rows.length;
81
+ this.updateList();
82
+ }
83
+ handleInput(data) {
84
+ if (this.keybindings.matches(data, "tui.select.up")) {
85
+ this.moveSelection(-1);
86
+ }
87
+ else if (this.keybindings.matches(data, "tui.select.down")) {
88
+ this.moveSelection(1);
89
+ }
90
+ else if (this.keybindings.matches(data, "tui.select.confirm")) {
91
+ this.onDone(this.rows[this.selectedIndex]?.action);
92
+ }
93
+ else if (this.keybindings.matches(data, "tui.select.cancel")) {
94
+ this.onDone(undefined);
95
+ }
96
+ }
40
97
  }
41
- function overridesEqual(override, result) {
42
- return override?.model === result.model && override?.thinking === result.thinking;
98
+ /** Standalone searchable model picker for one profile; confirm saves immediately. */
99
+ class ModelPickerComponent extends Container {
100
+ get focused() {
101
+ return this._focused;
102
+ }
103
+ set focused(value) {
104
+ this._focused = value;
105
+ this.modelList.focused = value;
106
+ }
107
+ constructor(options) {
108
+ super();
109
+ this.refreshAbortController = new AbortController();
110
+ this.closed = false;
111
+ this._focused = false;
112
+ this.tui = options.tui;
113
+ this.theme = options.theme;
114
+ this.keybindings = options.keybindings;
115
+ this.addChild(new DynamicBorder());
116
+ this.addChild(new Spacer(1));
117
+ this.addChild(new Text(this.theme.fg("accent", this.theme.bold(`Model — ${AGENT_PROFILE_LABELS[options.profile.name]}`)), 1, 0));
118
+ this.addChild(new Spacer(1));
119
+ this.modelList = new ProfileModelListComponent({
120
+ theme: options.theme,
121
+ keybindings: options.keybindings,
122
+ models: options.models,
123
+ scopedModels: options.scopedModels,
124
+ currentSessionModel: options.currentSessionModel,
125
+ savedModelId: options.savedModelId,
126
+ onDone: options.onDone,
127
+ });
128
+ this.addChild(this.modelList);
129
+ this.addChild(new Spacer(1));
130
+ const hints = [
131
+ navigationHint(this.theme, options.keybindings),
132
+ options.scopedModels.length > 0 ? hint(this.theme, options.keybindings, "tui.input.tab", "scope") : "",
133
+ hint(this.theme, options.keybindings, "tui.select.confirm", "select"),
134
+ hint(this.theme, options.keybindings, "tui.select.cancel", "back"),
135
+ ].filter(Boolean);
136
+ this.addChild(new Text(hints.join(this.theme.fg("muted", " • ")), 1, 0));
137
+ this.addChild(new Spacer(1));
138
+ this.addChild(new DynamicBorder());
139
+ }
140
+ get refreshSignal() {
141
+ return this.refreshAbortController.signal;
142
+ }
143
+ cancelRefresh() {
144
+ this.refreshAbortController.abort();
145
+ }
146
+ get isClosed() {
147
+ return this.closed;
148
+ }
149
+ dispose() {
150
+ this.closed = true;
151
+ this.refreshAbortController.abort();
152
+ }
153
+ updateModels(models) {
154
+ if (this.closed)
155
+ return;
156
+ this.modelList.updateModels(models);
157
+ this.tui.requestRender();
158
+ }
159
+ setRefreshStatus(message, tone = "muted") {
160
+ if (this.closed)
161
+ return;
162
+ this.modelList.setStatus(message, tone);
163
+ this.tui.requestRender();
164
+ }
165
+ handleInput(data) {
166
+ this.modelList.handleInput(data);
167
+ }
43
168
  }
44
- async function saveProfileResult(ctx, profileName, override, result) {
45
- if (overridesEqual(override, result))
169
+ /** Persist a single override atomically; the UI only reflects the value on success. */
170
+ async function persistOverride(ctx, profile, patch, current) {
171
+ const next = "model" in patch ? patch.model : patch.thinking;
172
+ if (next === current)
46
173
  return;
47
174
  try {
48
- await updateProfileOverride(profileName, { model: result.model, thinking: result.thinking }, getAgentDir());
175
+ await updateProfileOverride(profile.name, patch, getAgentDir());
49
176
  }
50
177
  catch (error) {
51
- ctx.ui.notify(`Could not save ${displayAgentName(profileName)} 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");
52
179
  }
53
180
  }
54
- function refreshFailureMessage(providerIds) {
55
- if (providerIds.length === 1)
56
- return `Could not refresh ${providerIds[0]}; showing cached models.`;
57
- const visible = providerIds.slice(0, 3);
58
- const omitted = providerIds.length - visible.length;
59
- const suffix = omitted > 0 ? `, +${omitted} more` : "";
60
- return `Could not refresh ${providerIds.length} model catalogs (${visible.join(", ")}${suffix}); showing cached models.`;
61
- }
62
- async function refreshEditorModels(ctx, editor) {
181
+ async function refreshPickerModels(ctx, picker) {
63
182
  let timedOut = false;
64
183
  const timeout = setTimeout(() => {
65
184
  timedOut = true;
66
- editor.cancelRefresh();
185
+ picker.cancelRefresh();
67
186
  }, MODEL_REFRESH_TIMEOUT_MS);
68
187
  timeout.unref?.();
69
188
  try {
70
- const result = await ctx.modelRegistry.refresh({ signal: editor.refreshSignal });
71
- if (editor.refreshSignal.aborted && !timedOut)
189
+ const result = await ctx.modelRegistry.refresh({ signal: picker.refreshSignal });
190
+ if (picker.isClosed || (picker.refreshSignal.aborted && !timedOut))
72
191
  return;
73
- editor.updateModels(ctx.modelRegistry.getAvailable());
192
+ picker.updateModels(ctx.modelRegistry.getAvailable());
74
193
  if (result.aborted && timedOut) {
75
- editor.setRefreshStatus("Model refresh timed out; showing cached models.", "error");
194
+ picker.setRefreshStatus("Model refresh timed out; showing cached models.", "error");
76
195
  return;
77
196
  }
78
197
  const providerIds = [...result.errors.keys()];
79
198
  if (providerIds.length > 0) {
80
- editor.setRefreshStatus(refreshFailureMessage(providerIds), "error");
199
+ picker.setRefreshStatus(refreshFailureMessage(providerIds), "error");
81
200
  return;
82
201
  }
83
202
  const registryError = ctx.modelRegistry.getError();
84
203
  if (registryError) {
85
- editor.setRefreshStatus(boundText(registryError, MAX_REFRESH_ERROR_LENGTH), "error");
204
+ picker.setRefreshStatus(truncate(registryError, MAX_REFRESH_ERROR_LENGTH), "error");
86
205
  return;
87
206
  }
88
- editor.setRefreshStatus("Model catalogs refreshed.", "success");
207
+ picker.setRefreshStatus(undefined);
89
208
  }
90
209
  catch (error) {
91
- if (editor.refreshSignal.aborted && !timedOut)
210
+ if (picker.isClosed || (picker.refreshSignal.aborted && !timedOut))
92
211
  return;
93
212
  const message = timedOut
94
213
  ? "Model refresh timed out; showing cached models."
95
214
  : `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`;
96
- editor.setRefreshStatus(boundText(message, MAX_REFRESH_ERROR_LENGTH), "error");
215
+ picker.setRefreshStatus(truncate(message, MAX_REFRESH_ERROR_LENGTH), "error");
97
216
  }
98
217
  finally {
99
218
  clearTimeout(timeout);
100
219
  }
101
220
  }
102
- async function showTuiAgentsCommand(ctx, currentThinking) {
103
- const agentDir = getAgentDir();
104
- let selectedProfileName;
105
- while (true) {
106
- const discovery = discoverAgents(ctx.cwd, { projectTrusted: ctx.isProjectTrusted(), agentDir });
107
- const picked = await ctx.ui.custom((_tui, theme, keybindings, done) => new ProfilePickerComponent(theme, keybindings, discovery.agents, discovery.diagnostics, done, selectedProfileName));
108
- if (!picked)
109
- return;
110
- if (picked.kind === "diagnostics") {
111
- ctx.ui.notify(formatDiagnostics(discovery.diagnostics), "warning");
112
- continue;
113
- }
114
- selectedProfileName = picked.name;
115
- const agent = discovery.agents.find((candidate) => candidate.name === picked.name);
116
- if (!agent)
117
- continue;
118
- const config = await loadSubagentConfig(agentDir);
119
- const override = config.profiles[agent.name];
120
- const edited = await ctx.ui.custom((tui, theme, keybindings, done) => {
121
- const editor = new ProfileEditorComponent({
122
- tui,
123
- theme,
124
- keybindings,
125
- agent,
126
- override,
127
- models: ctx.modelRegistry.getAvailable(),
128
- scopedModels: ctx.scopedModels,
129
- currentSessionModel: ctx.model,
130
- currentThinking,
131
- onDone: done,
132
- });
133
- editor.setRefreshStatus("Refreshing model catalogs…");
134
- void refreshEditorModels(ctx, editor);
135
- return editor;
136
- });
137
- if (!edited)
138
- continue;
139
- await saveProfileResult(ctx, agent.name, override, edited);
140
- }
221
+ async function selectProfile(ctx) {
222
+ const labels = AGENT_PROFILES.map((profile) => AGENT_PROFILE_LABELS[profile.name]);
223
+ const label = await ctx.ui.select("Agents", labels);
224
+ return label === undefined
225
+ ? undefined
226
+ : AGENT_PROFILES.find((profile) => AGENT_PROFILE_LABELS[profile.name] === label);
141
227
  }
142
- function uniqueProfileLabels(agents) {
143
- const sorted = [...agents].sort(compareAgentNames);
144
- const counts = new Map();
145
- for (const agent of sorted) {
146
- const display = displayAgentName(agent.name);
147
- counts.set(display, (counts.get(display) ?? 0) + 1);
148
- }
149
- return new Map(sorted.map((agent) => {
150
- const display = displayAgentName(agent.name);
151
- return [counts.get(display) === 1 ? display : `${display} (${agent.name})`, agent];
228
+ async function showTuiSettingsMenu(ctx, profile, override, currentThinking) {
229
+ return ctx.ui.custom((_tui, theme, keybindings, done) => new ProfileSettingsMenuComponent({
230
+ theme,
231
+ keybindings,
232
+ profile,
233
+ override,
234
+ models: ctx.modelRegistry.getAvailable(),
235
+ currentSessionModel: ctx.model,
236
+ currentThinking,
237
+ onDone: done,
152
238
  }));
153
239
  }
154
- async function showDialogAgentsCommand(ctx, currentThinking) {
240
+ async function showDialogSettingsMenu(ctx, profile, override, currentThinking) {
241
+ const options = new Map();
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()]);
251
+ return label === undefined ? undefined : options.get(label);
252
+ }
253
+ async function showTuiModelPicker(ctx, profile, override) {
254
+ const chosen = await ctx.ui.custom((tui, theme, keybindings, done) => {
255
+ const picker = new ModelPickerComponent({
256
+ tui,
257
+ theme,
258
+ keybindings,
259
+ profile,
260
+ savedModelId: override?.model,
261
+ models: ctx.modelRegistry.getAvailable(),
262
+ scopedModels: ctx.scopedModels,
263
+ currentSessionModel: ctx.model,
264
+ onDone: done,
265
+ });
266
+ picker.setRefreshStatus("Refreshing model catalogs…");
267
+ void refreshPickerModels(ctx, picker);
268
+ return picker;
269
+ });
270
+ return chosen === undefined ? undefined : { modelId: chosen.modelId };
271
+ }
272
+ async function showDialogModelPicker(ctx, profile, override) {
273
+ const models = [...ctx.modelRegistry.getAvailable()].sort(compareModels);
274
+ const choices = buildModelChoices({
275
+ models,
276
+ currentSessionModel: ctx.model,
277
+ savedModelId: override?.model,
278
+ });
279
+ const label = await ctx.ui.select(`Model — ${AGENT_PROFILE_LABELS[profile.name]}`, [...choices.keys()]);
280
+ return label === undefined ? undefined : { modelId: choices.get(label) };
281
+ }
282
+ async function showThinkingPicker(ctx, profile, override, currentThinking) {
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()]);
290
+ return label === undefined ? undefined : { level: choices.get(label) };
291
+ }
292
+ async function runProfileSettings(ctx, profile, currentThinking) {
155
293
  const agentDir = getAgentDir();
294
+ const isTui = ctx.mode === "tui";
156
295
  while (true) {
157
- const discovery = discoverAgents(ctx.cwd, { projectTrusted: ctx.isProjectTrusted(), agentDir });
158
- const labels = uniqueProfileLabels(discovery.agents);
159
- const diagnosticsLabel = discovery.diagnostics.length
160
- ? `View ${discovery.diagnostics.length} agent file issue${discovery.diagnostics.length === 1 ? "" : "s"}`
161
- : undefined;
162
- const selectedLabel = await ctx.ui.select("Agents", [
163
- ...labels.keys(),
164
- ...(diagnosticsLabel ? [diagnosticsLabel] : []),
165
- ]);
166
- if (!selectedLabel)
167
- return;
168
- if (selectedLabel === diagnosticsLabel) {
169
- ctx.ui.notify(formatDiagnostics(discovery.diagnostics), "warning");
170
- continue;
171
- }
172
- const agent = labels.get(selectedLabel);
173
- if (!agent)
174
- continue;
175
296
  const config = await loadSubagentConfig(agentDir);
176
- const override = config.profiles[agent.name];
177
- const models = ctx.modelRegistry.getAvailable().sort((left, right) => {
178
- const provider = left.provider.localeCompare(right.provider);
179
- return provider !== 0 ? provider : left.id.localeCompare(right.id);
180
- });
181
- const modelChoices = new Map();
182
- const inheritModelLabel = `inherit (${modelId(ctx.model)})${override?.model ? "" : " ✓"}`;
183
- modelChoices.set(inheritModelLabel, undefined);
184
- if (override?.model && !findModel(models, override.model)) {
185
- modelChoices.set(`${override.model} [unavailable] ✓`, override.model);
186
- }
187
- for (const model of models) {
188
- const id = modelId(model);
189
- modelChoices.set(`${id}${override?.model === id ? " ✓" : ""}`, id);
297
+ const override = config.profiles[profile.name];
298
+ const action = isTui
299
+ ? await showTuiSettingsMenu(ctx, profile, override, currentThinking)
300
+ : await showDialogSettingsMenu(ctx, profile, override, currentThinking);
301
+ if (!action)
302
+ return;
303
+ if (action === "model") {
304
+ const chosen = isTui
305
+ ? await showTuiModelPicker(ctx, profile, override)
306
+ : await showDialogModelPicker(ctx, profile, override);
307
+ if (!chosen)
308
+ continue;
309
+ await persistOverride(ctx, profile, { model: chosen.modelId }, override?.model);
190
310
  }
191
- const selectedModelLabel = await ctx.ui.select(`Model for ${displayAgentName(agent.name)}`, [
192
- ...modelChoices.keys(),
193
- ]);
194
- if (!selectedModelLabel)
195
- continue;
196
- const selectedModelId = modelChoices.get(selectedModelLabel);
197
- const effectiveModel = selectedModelId ? findModel(models, selectedModelId) : ctx.model;
198
- const levels = effectiveModel
199
- ? getSupportedThinkingLevels(effectiveModel)
200
- : [...THINKING_LEVELS];
201
- const inheritedThinking = effectiveModel
202
- ? clampThinkingLevel(effectiveModel, currentThinking)
203
- : currentThinking;
204
- const thinkingChoices = new Map();
205
- thinkingChoices.set(`inherit (${inheritedThinking})${override?.thinking ? "" : " ✓"}`, undefined);
206
- for (const level of levels) {
207
- thinkingChoices.set(`${level}${override?.thinking === level ? " ✓" : ""}`, level);
311
+ else {
312
+ const chosen = await showThinkingPicker(ctx, profile, override, currentThinking);
313
+ if (!chosen)
314
+ continue;
315
+ await persistOverride(ctx, profile, { thinking: chosen.level }, override?.thinking);
208
316
  }
209
- const selectedThinkingLabel = await ctx.ui.select(`Thinking for ${displayAgentName(agent.name)}`, [
210
- ...thinkingChoices.keys(),
211
- ]);
212
- if (!selectedThinkingLabel)
213
- continue;
214
- await saveProfileResult(ctx, agent.name, override, {
215
- model: selectedModelId,
216
- thinking: thinkingChoices.get(selectedThinkingLabel),
217
- });
218
317
  }
219
318
  }
220
319
  export async function showAgentsCommand(ctx, currentThinking) {
@@ -222,9 +321,11 @@ export async function showAgentsCommand(ctx, currentThinking) {
222
321
  ctx.ui.notify("/agents requires an interactive UI.", "warning");
223
322
  return;
224
323
  }
225
- if (ctx.mode === "tui")
226
- await showTuiAgentsCommand(ctx, currentThinking);
227
- else
228
- await showDialogAgentsCommand(ctx, currentThinking);
324
+ while (true) {
325
+ const profile = await selectProfile(ctx);
326
+ if (!profile)
327
+ return;
328
+ await runProfileSettings(ctx, profile, currentThinking);
329
+ }
229
330
  }
230
331
  //# sourceMappingURL=agents-command.js.map
@@ -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 { getAgentDir } from \"../../config.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/types.ts\";\nimport { discoverAgents } from \"./agents.ts\";\nimport { THINKING_LEVELS } from \"./constants.ts\";\nimport { displayAgentName } from \"./display-name.ts\";\nimport { loadSubagentConfig, updateProfileOverride } from \"./settings.ts\";\nimport type { AgentDefinition, AgentDiagnostic, SubagentProfileOverride } from \"./types.ts\";\nimport { ProfileEditorComponent, type ProfileEditorResult } from \"./ui/profile-editor.ts\";\nimport { ProfilePickerComponent, type ProfilePickerResult } from \"./ui/profile-picker.ts\";\n\nconst MODEL_REFRESH_TIMEOUT_MS = 15_000;\nconst MAX_DIAGNOSTICS = 20;\nconst MAX_DIAGNOSTIC_LENGTH = 240;\nconst MAX_REFRESH_ERROR_LENGTH = 240;\n\nfunction compareAgentNames(left: AgentDefinition, right: AgentDefinition): number {\n\tif (left.name < right.name) return -1;\n\tif (left.name > right.name) return 1;\n\treturn 0;\n}\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\nfunction formatDiagnostics(diagnostics: readonly AgentDiagnostic[]): string {\n\tconst visible = diagnostics\n\t\t.slice(0, MAX_DIAGNOSTICS)\n\t\t.map((diagnostic) => boundText(`${diagnostic.path}: ${diagnostic.message}`, MAX_DIAGNOSTIC_LENGTH));\n\tif (diagnostics.length > visible.length) {\n\t\tvisible.push(\n\t\t\t`… ${diagnostics.length - visible.length} more issue${diagnostics.length - visible.length === 1 ? \"\" : \"s\"}`,\n\t\t);\n\t}\n\treturn visible.join(\"\\n\");\n}\n\nfunction overridesEqual(override: SubagentProfileOverride | undefined, result: ProfileEditorResult): boolean {\n\treturn override?.model === result.model && override?.thinking === result.thinking;\n}\n\nasync function saveProfileResult(\n\tctx: ExtensionCommandContext,\n\tprofileName: string,\n\toverride: SubagentProfileOverride | undefined,\n\tresult: ProfileEditorResult,\n): Promise<void> {\n\tif (overridesEqual(override, result)) return;\n\ttry {\n\t\tawait updateProfileOverride(profileName, { model: result.model, thinking: result.thinking }, getAgentDir());\n\t} catch (error) {\n\t\tctx.ui.notify(\n\t\t\t`Could not save ${displayAgentName(profileName)} settings: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\"error\",\n\t\t);\n\t}\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\nasync function refreshEditorModels(ctx: ExtensionCommandContext, editor: ProfileEditorComponent): Promise<void> {\n\tlet timedOut = false;\n\tconst timeout = setTimeout(() => {\n\t\ttimedOut = true;\n\t\teditor.cancelRefresh();\n\t}, MODEL_REFRESH_TIMEOUT_MS);\n\ttimeout.unref?.();\n\ttry {\n\t\tconst result = await ctx.modelRegistry.refresh({ signal: editor.refreshSignal });\n\t\tif (editor.refreshSignal.aborted && !timedOut) return;\n\t\teditor.updateModels(ctx.modelRegistry.getAvailable());\n\t\tif (result.aborted && timedOut) {\n\t\t\teditor.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\teditor.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\teditor.setRefreshStatus(boundText(registryError, MAX_REFRESH_ERROR_LENGTH), \"error\");\n\t\t\treturn;\n\t\t}\n\t\teditor.setRefreshStatus(\"Model catalogs refreshed.\", \"success\");\n\t} catch (error) {\n\t\tif (editor.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\teditor.setRefreshStatus(boundText(message, MAX_REFRESH_ERROR_LENGTH), \"error\");\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\nasync function showTuiAgentsCommand(ctx: ExtensionCommandContext, currentThinking: ThinkingLevel): Promise<void> {\n\tconst agentDir = getAgentDir();\n\tlet selectedProfileName: string | undefined;\n\twhile (true) {\n\t\tconst discovery = discoverAgents(ctx.cwd, { projectTrusted: ctx.isProjectTrusted(), agentDir });\n\t\tconst picked = await ctx.ui.custom<ProfilePickerResult>(\n\t\t\t(_tui, theme, keybindings, done) =>\n\t\t\t\tnew ProfilePickerComponent(\n\t\t\t\t\ttheme,\n\t\t\t\t\tkeybindings,\n\t\t\t\t\tdiscovery.agents,\n\t\t\t\t\tdiscovery.diagnostics,\n\t\t\t\t\tdone,\n\t\t\t\t\tselectedProfileName,\n\t\t\t\t),\n\t\t);\n\t\tif (!picked) return;\n\t\tif (picked.kind === \"diagnostics\") {\n\t\t\tctx.ui.notify(formatDiagnostics(discovery.diagnostics), \"warning\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tselectedProfileName = picked.name;\n\t\tconst agent = discovery.agents.find((candidate) => candidate.name === picked.name);\n\t\tif (!agent) continue;\n\t\tconst config = await loadSubagentConfig(agentDir);\n\t\tconst override = config.profiles[agent.name];\n\t\tconst edited = await ctx.ui.custom<ProfileEditorResult | undefined>((tui, theme, keybindings, done) => {\n\t\t\tconst editor = new ProfileEditorComponent({\n\t\t\t\ttui,\n\t\t\t\ttheme,\n\t\t\t\tkeybindings,\n\t\t\t\tagent,\n\t\t\t\toverride,\n\t\t\t\tmodels: ctx.modelRegistry.getAvailable(),\n\t\t\t\tscopedModels: ctx.scopedModels,\n\t\t\t\tcurrentSessionModel: ctx.model,\n\t\t\t\tcurrentThinking,\n\t\t\t\tonDone: done,\n\t\t\t});\n\t\t\teditor.setRefreshStatus(\"Refreshing model catalogs…\");\n\t\t\tvoid refreshEditorModels(ctx, editor);\n\t\t\treturn editor;\n\t\t});\n\t\tif (!edited) continue;\n\t\tawait saveProfileResult(ctx, agent.name, override, edited);\n\t}\n}\n\nfunction uniqueProfileLabels(agents: readonly AgentDefinition[]): Map<string, AgentDefinition> {\n\tconst sorted = [...agents].sort(compareAgentNames);\n\tconst counts = new Map<string, number>();\n\tfor (const agent of sorted) {\n\t\tconst display = displayAgentName(agent.name);\n\t\tcounts.set(display, (counts.get(display) ?? 0) + 1);\n\t}\n\treturn new Map(\n\t\tsorted.map((agent) => {\n\t\t\tconst display = displayAgentName(agent.name);\n\t\t\treturn [counts.get(display) === 1 ? display : `${display} (${agent.name})`, agent];\n\t\t}),\n\t);\n}\n\nasync function showDialogAgentsCommand(ctx: ExtensionCommandContext, currentThinking: ThinkingLevel): Promise<void> {\n\tconst agentDir = getAgentDir();\n\twhile (true) {\n\t\tconst discovery = discoverAgents(ctx.cwd, { projectTrusted: ctx.isProjectTrusted(), agentDir });\n\t\tconst labels = uniqueProfileLabels(discovery.agents);\n\t\tconst diagnosticsLabel = discovery.diagnostics.length\n\t\t\t? `View ${discovery.diagnostics.length} agent file issue${discovery.diagnostics.length === 1 ? \"\" : \"s\"}`\n\t\t\t: undefined;\n\t\tconst selectedLabel = await ctx.ui.select(\"Agents\", [\n\t\t\t...labels.keys(),\n\t\t\t...(diagnosticsLabel ? [diagnosticsLabel] : []),\n\t\t]);\n\t\tif (!selectedLabel) return;\n\t\tif (selectedLabel === diagnosticsLabel) {\n\t\t\tctx.ui.notify(formatDiagnostics(discovery.diagnostics), \"warning\");\n\t\t\tcontinue;\n\t\t}\n\t\tconst agent = labels.get(selectedLabel);\n\t\tif (!agent) continue;\n\n\t\tconst config = await loadSubagentConfig(agentDir);\n\t\tconst override = config.profiles[agent.name];\n\t\tconst models = ctx.modelRegistry.getAvailable().sort((left, right) => {\n\t\t\tconst provider = left.provider.localeCompare(right.provider);\n\t\t\treturn provider !== 0 ? provider : left.id.localeCompare(right.id);\n\t\t});\n\t\tconst modelChoices = new Map<string, string | undefined>();\n\t\tconst inheritModelLabel = `inherit (${modelId(ctx.model)})${override?.model ? \"\" : \" ✓\"}`;\n\t\tmodelChoices.set(inheritModelLabel, undefined);\n\t\tif (override?.model && !findModel(models, override.model)) {\n\t\t\tmodelChoices.set(`${override.model} [unavailable] ✓`, override.model);\n\t\t}\n\t\tfor (const model of models) {\n\t\t\tconst id = modelId(model);\n\t\t\tmodelChoices.set(`${id}${override?.model === id ? \" ✓\" : \"\"}`, id);\n\t\t}\n\t\tconst selectedModelLabel = await ctx.ui.select(`Model for ${displayAgentName(agent.name)}`, [\n\t\t\t...modelChoices.keys(),\n\t\t]);\n\t\tif (!selectedModelLabel) continue;\n\t\tconst selectedModelId = modelChoices.get(selectedModelLabel);\n\t\tconst effectiveModel = selectedModelId ? findModel(models, selectedModelId) : ctx.model;\n\t\tconst levels = effectiveModel\n\t\t\t? (getSupportedThinkingLevels(effectiveModel) as ThinkingLevel[])\n\t\t\t: [...THINKING_LEVELS];\n\t\tconst inheritedThinking = effectiveModel\n\t\t\t? (clampThinkingLevel(effectiveModel, currentThinking) as ThinkingLevel)\n\t\t\t: currentThinking;\n\t\tconst thinkingChoices = new Map<string, ThinkingLevel | undefined>();\n\t\tthinkingChoices.set(`inherit (${inheritedThinking})${override?.thinking ? \"\" : \" ✓\"}`, undefined);\n\t\tfor (const level of levels) {\n\t\t\tthinkingChoices.set(`${level}${override?.thinking === level ? \" ✓\" : \"\"}`, level);\n\t\t}\n\t\tconst selectedThinkingLabel = await ctx.ui.select(`Thinking for ${displayAgentName(agent.name)}`, [\n\t\t\t...thinkingChoices.keys(),\n\t\t]);\n\t\tif (!selectedThinkingLabel) continue;\n\t\tawait saveProfileResult(ctx, agent.name, override, {\n\t\t\tmodel: selectedModelId,\n\t\t\tthinking: thinkingChoices.get(selectedThinkingLabel),\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\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 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,7 +1,6 @@
1
- import type { AgentDiscoveryResult } from "./types.ts";
2
- export declare function discoverAgents(cwd: string, options: {
3
- projectTrusted: boolean;
4
- agentDir?: string;
5
- }): AgentDiscoveryResult;
6
- export declare function subagentToolDescription(discovery: AgentDiscoveryResult): string;
1
+ import { type SubagentAgentName } from "./constants.ts";
2
+ import type { AgentProfile } from "./types.ts";
3
+ export declare const AGENT_PROFILE_LABELS: Record<SubagentAgentName, string>;
4
+ export declare const AGENT_PROFILES: readonly AgentProfile[];
5
+ export declare function subagentToolDescription(): string;
7
6
  //# sourceMappingURL=agents.d.ts.map