@astralyn/pi 0.84.6 → 0.84.8

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 (86) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/core/compaction/compaction.d.ts +2 -0
  3. package/dist/core/compaction/compaction.d.ts.map +1 -1
  4. package/dist/core/compaction/compaction.js +7 -7
  5. package/dist/core/compaction/compaction.js.map +1 -1
  6. package/dist/extensions/background/index.d.ts.map +1 -1
  7. package/dist/extensions/background/index.js +48 -72
  8. package/dist/extensions/background/index.js.map +1 -1
  9. package/dist/extensions/background/manager.d.ts.map +1 -1
  10. package/dist/extensions/background/manager.js +5 -3
  11. package/dist/extensions/background/manager.js.map +1 -1
  12. package/dist/extensions/background/registry.d.ts +11 -13
  13. package/dist/extensions/background/registry.d.ts.map +1 -1
  14. package/dist/extensions/background/registry.js +71 -80
  15. package/dist/extensions/background/registry.js.map +1 -1
  16. package/dist/extensions/background/render.d.ts.map +1 -1
  17. package/dist/extensions/background/render.js +17 -4
  18. package/dist/extensions/background/render.js.map +1 -1
  19. package/dist/extensions/deepwiki/constants.d.ts +2 -2
  20. package/dist/extensions/deepwiki/constants.d.ts.map +1 -1
  21. package/dist/extensions/deepwiki/constants.js +5 -5
  22. package/dist/extensions/deepwiki/constants.js.map +1 -1
  23. package/dist/extensions/deepwiki/schema.js +1 -1
  24. package/dist/extensions/deepwiki/schema.js.map +1 -1
  25. package/dist/extensions/question/constants.d.ts +2 -2
  26. package/dist/extensions/question/constants.d.ts.map +1 -1
  27. package/dist/extensions/question/constants.js +5 -2
  28. package/dist/extensions/question/constants.js.map +1 -1
  29. package/dist/extensions/router/dialog-host.d.ts +60 -0
  30. package/dist/extensions/router/dialog-host.d.ts.map +1 -0
  31. package/dist/extensions/router/dialog-host.js +196 -0
  32. package/dist/extensions/router/dialog-host.js.map +1 -0
  33. package/dist/extensions/router/probe.d.ts.map +1 -1
  34. package/dist/extensions/router/probe.js +2 -0
  35. package/dist/extensions/router/probe.js.map +1 -1
  36. package/dist/extensions/router/ui.d.ts.map +1 -1
  37. package/dist/extensions/router/ui.js +117 -67
  38. package/dist/extensions/router/ui.js.map +1 -1
  39. package/dist/extensions/subagent/activity.d.ts +9 -0
  40. package/dist/extensions/subagent/activity.d.ts.map +1 -1
  41. package/dist/extensions/subagent/activity.js +21 -0
  42. package/dist/extensions/subagent/activity.js.map +1 -1
  43. package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
  44. package/dist/extensions/subagent/agents-command.js +355 -71
  45. package/dist/extensions/subagent/agents-command.js.map +1 -1
  46. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  47. package/dist/extensions/subagent/agents.js +7 -3
  48. package/dist/extensions/subagent/agents.js.map +1 -1
  49. package/dist/extensions/subagent/constants.d.ts +1 -0
  50. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  51. package/dist/extensions/subagent/constants.js +4 -0
  52. package/dist/extensions/subagent/constants.js.map +1 -1
  53. package/dist/extensions/subagent/index.js +2 -2
  54. package/dist/extensions/subagent/index.js.map +1 -1
  55. package/dist/extensions/subagent/render.d.ts.map +1 -1
  56. package/dist/extensions/subagent/render.js +1 -7
  57. package/dist/extensions/subagent/render.js.map +1 -1
  58. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  59. package/dist/extensions/subagent/sdk-runner.js +19 -0
  60. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  61. package/dist/extensions/subagent/settings.d.ts.map +1 -1
  62. package/dist/extensions/subagent/settings.js +11 -4
  63. package/dist/extensions/subagent/settings.js.map +1 -1
  64. package/dist/extensions/subagent/state.d.ts +9 -0
  65. package/dist/extensions/subagent/state.d.ts.map +1 -1
  66. package/dist/extensions/subagent/state.js +33 -2
  67. package/dist/extensions/subagent/state.js.map +1 -1
  68. package/dist/extensions/subagent/ui/model-list.d.ts +1 -0
  69. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
  70. package/dist/extensions/subagent/ui/model-list.js +5 -0
  71. package/dist/extensions/subagent/ui/model-list.js.map +1 -1
  72. package/dist/extensions/todo/constants.d.ts +1 -1
  73. package/dist/extensions/todo/constants.d.ts.map +1 -1
  74. package/dist/extensions/todo/constants.js +10 -27
  75. package/dist/extensions/todo/constants.js.map +1 -1
  76. package/dist/extensions/todo/state.d.ts.map +1 -1
  77. package/dist/extensions/todo/state.js +27 -16
  78. package/dist/extensions/todo/state.js.map +1 -1
  79. package/dist/extensions/todo/view.d.ts.map +1 -1
  80. package/dist/extensions/todo/view.js +16 -5
  81. package/dist/extensions/todo/view.js.map +1 -1
  82. package/docs/bundled/extensions/background.md +3 -3
  83. package/docs/bundled/extensions/todo.md +2 -2
  84. package/docs/compaction.md +2 -0
  85. package/npm-shrinkwrap.json +2 -2
  86. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { Container, Spacer, Text, TruncatedText, } from "@earendil-works/pi-tui";
1
+ import { Container, isFocusable, Spacer, Text, TruncatedText, } from "@earendil-works/pi-tui";
2
2
  import { getAgentDir } from "../../config.js";
3
3
  import { DynamicBorder } from "../../modes/interactive/components/dynamic-border.js";
4
4
  import { keyLabel } from "../../modes/interactive/components/keybinding-hints.js";
@@ -27,6 +27,85 @@ function navigationHint(theme, keybindings) {
27
27
  .join("/");
28
28
  return keys ? `${theme.fg("dim", keys)}${theme.fg("muted", " navigate")}` : "";
29
29
  }
30
+ /** Small Pi-native list page used inside the single /agents custom UI lifecycle. */
31
+ class ChoiceMenuComponent 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._focused = false;
41
+ this.theme = options.theme;
42
+ this.keybindings = options.keybindings;
43
+ this.choices = options.choices;
44
+ this.onDone = options.onDone;
45
+ this.title = options.title;
46
+ this.cancelDescription = options.cancelDescription;
47
+ this.selectedIndex = Math.min(Math.max(options.initialIndex ?? 0, 0), Math.max(0, options.choices.length - 1));
48
+ this.addChild(new DynamicBorder());
49
+ this.addChild(new Spacer(1));
50
+ this.titleText = new Text("", 1, 0);
51
+ this.addChild(this.titleText);
52
+ this.addChild(new Spacer(1));
53
+ this.listContainer = new Container();
54
+ this.addChild(this.listContainer);
55
+ this.addChild(new Spacer(1));
56
+ this.hintText = new Text("", 1, 0);
57
+ this.addChild(this.hintText);
58
+ this.addChild(new Spacer(1));
59
+ this.addChild(new DynamicBorder());
60
+ this.updateStaticText();
61
+ this.updateList();
62
+ }
63
+ updateStaticText() {
64
+ this.titleText.setText(this.theme.fg("accent", this.theme.bold(this.title)));
65
+ const hints = [
66
+ navigationHint(this.theme, this.keybindings),
67
+ hint(this.theme, this.keybindings, "tui.select.confirm", "select"),
68
+ hint(this.theme, this.keybindings, "tui.select.cancel", this.cancelDescription),
69
+ ].filter(Boolean);
70
+ this.hintText.setText(hints.join(this.theme.fg("muted", " • ")));
71
+ }
72
+ updateList() {
73
+ this.listContainer.clear();
74
+ for (const [index, choice] of this.choices.entries()) {
75
+ const selected = index === this.selectedIndex;
76
+ const prefix = selected ? this.theme.fg("accent", "→ ") : " ";
77
+ const label = this.theme.fg(selected ? "accent" : "text", choice.label);
78
+ this.listContainer.addChild(new TruncatedText(`${prefix}${label}`, 1, 0));
79
+ }
80
+ }
81
+ moveSelection(offset) {
82
+ if (this.choices.length === 0)
83
+ return;
84
+ this.selectedIndex = (this.selectedIndex + offset + this.choices.length) % this.choices.length;
85
+ this.updateList();
86
+ }
87
+ invalidate() {
88
+ this.updateStaticText();
89
+ this.updateList();
90
+ super.invalidate();
91
+ }
92
+ handleInput(data) {
93
+ if (this.keybindings.matches(data, "tui.select.up")) {
94
+ this.moveSelection(-1);
95
+ }
96
+ else if (this.keybindings.matches(data, "tui.select.down")) {
97
+ this.moveSelection(1);
98
+ }
99
+ else if (this.keybindings.matches(data, "tui.select.confirm")) {
100
+ const choice = this.choices[this.selectedIndex];
101
+ if (choice)
102
+ this.onDone(choice);
103
+ }
104
+ else if (this.keybindings.matches(data, "tui.select.cancel")) {
105
+ this.onDone(undefined);
106
+ }
107
+ }
108
+ }
30
109
  /** Compact Model/Thinking settings menu for one profile; every confirm persists immediately. */
31
110
  class ProfileSettingsMenuComponent extends Container {
32
111
  get focused() {
@@ -42,29 +121,48 @@ class ProfileSettingsMenuComponent extends Container {
42
121
  this.theme = options.theme;
43
122
  this.keybindings = options.keybindings;
44
123
  this.onDone = options.onDone;
124
+ this.title = AGENT_PROFILE_LABELS[options.profile.name];
125
+ this.status = options.status;
45
126
  this.rows = buildSettingsRows({
46
127
  override: options.override,
47
128
  models: options.models,
48
129
  currentSessionModel: options.currentSessionModel,
49
130
  currentThinking: options.currentThinking,
50
131
  });
132
+ this.selectedIndex = Math.max(0, this.rows.findIndex((row) => row.action === options.selectedAction));
51
133
  this.addChild(new DynamicBorder());
52
134
  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));
135
+ this.titleText = new Text("", 1, 0);
136
+ this.addChild(this.titleText);
54
137
  this.addChild(new Spacer(1));
55
138
  this.listContainer = new Container();
56
139
  this.addChild(this.listContainer);
57
140
  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));
141
+ if (this.status) {
142
+ this.statusText = new Text("", 1, 0);
143
+ this.addChild(this.statusText);
144
+ this.addChild(new Spacer(1));
145
+ }
146
+ else {
147
+ this.statusText = undefined;
148
+ }
149
+ this.hintText = new Text("", 1, 0);
150
+ this.addChild(this.hintText);
64
151
  this.addChild(new Spacer(1));
65
152
  this.addChild(new DynamicBorder());
153
+ this.updateStaticText();
66
154
  this.updateList();
67
155
  }
156
+ updateStaticText() {
157
+ this.titleText.setText(this.theme.fg("accent", this.theme.bold(this.title)));
158
+ this.statusText?.setText(this.theme.fg("muted", this.status ?? ""));
159
+ const hints = [
160
+ navigationHint(this.theme, this.keybindings),
161
+ hint(this.theme, this.keybindings, "tui.select.confirm", "select"),
162
+ hint(this.theme, this.keybindings, "tui.select.cancel", "back"),
163
+ ].filter(Boolean);
164
+ this.hintText.setText(hints.join(this.theme.fg("muted", " • ")));
165
+ }
68
166
  updateList() {
69
167
  this.listContainer.clear();
70
168
  for (const [index, row] of this.rows.entries()) {
@@ -80,6 +178,11 @@ class ProfileSettingsMenuComponent extends Container {
80
178
  this.selectedIndex = (this.selectedIndex + offset + this.rows.length) % this.rows.length;
81
179
  this.updateList();
82
180
  }
181
+ invalidate() {
182
+ this.updateStaticText();
183
+ this.updateList();
184
+ super.invalidate();
185
+ }
83
186
  handleInput(data) {
84
187
  if (this.keybindings.matches(data, "tui.select.up")) {
85
188
  this.moveSelection(-1);
@@ -95,7 +198,7 @@ class ProfileSettingsMenuComponent extends Container {
95
198
  }
96
199
  }
97
200
  }
98
- /** Standalone searchable model picker for one profile; confirm saves immediately. */
201
+ /** Searchable model page for one profile; confirm saves immediately. */
99
202
  class ModelPickerComponent extends Container {
100
203
  get focused() {
101
204
  return this._focused;
@@ -112,9 +215,12 @@ class ModelPickerComponent extends Container {
112
215
  this.tui = options.tui;
113
216
  this.theme = options.theme;
114
217
  this.keybindings = options.keybindings;
218
+ this.title = `Model — ${AGENT_PROFILE_LABELS[options.profile.name]}`;
219
+ this.hasScopedModels = options.scopedModels.length > 0;
115
220
  this.addChild(new DynamicBorder());
116
221
  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));
222
+ this.titleText = new Text("", 1, 0);
223
+ this.addChild(this.titleText);
118
224
  this.addChild(new Spacer(1));
119
225
  this.modelList = new ProfileModelListComponent({
120
226
  theme: options.theme,
@@ -127,15 +233,21 @@ class ModelPickerComponent extends Container {
127
233
  });
128
234
  this.addChild(this.modelList);
129
235
  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));
236
+ this.hintText = new Text("", 1, 0);
237
+ this.addChild(this.hintText);
137
238
  this.addChild(new Spacer(1));
138
239
  this.addChild(new DynamicBorder());
240
+ this.updateStaticText();
241
+ }
242
+ updateStaticText() {
243
+ this.titleText.setText(this.theme.fg("accent", this.theme.bold(this.title)));
244
+ const hints = [
245
+ navigationHint(this.theme, this.keybindings),
246
+ this.hasScopedModels ? hint(this.theme, this.keybindings, "tui.input.tab", "scope") : "",
247
+ hint(this.theme, this.keybindings, "tui.select.confirm", "select"),
248
+ hint(this.theme, this.keybindings, "tui.select.cancel", "back"),
249
+ ].filter(Boolean);
250
+ this.hintText.setText(hints.join(this.theme.fg("muted", " • ")));
139
251
  }
140
252
  get refreshSignal() {
141
253
  return this.refreshAbortController.signal;
@@ -162,20 +274,22 @@ class ModelPickerComponent extends Container {
162
274
  this.modelList.setStatus(message, tone);
163
275
  this.tui.requestRender();
164
276
  }
277
+ invalidate() {
278
+ this.updateStaticText();
279
+ super.invalidate();
280
+ }
165
281
  handleInput(data) {
166
282
  this.modelList.handleInput(data);
167
283
  }
168
284
  }
169
285
  /** 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)
173
- return;
286
+ async function persistOverride(ctx, profile, patch) {
174
287
  try {
175
- await updateProfileOverride(profile.name, patch, getAgentDir());
288
+ return await updateProfileOverride(profile.name, patch, getAgentDir());
176
289
  }
177
290
  catch (error) {
178
291
  ctx.ui.notify(`Could not save ${AGENT_PROFILE_LABELS[profile.name]} settings: ${error instanceof Error ? error.message : String(error)}`, "error");
292
+ return undefined;
179
293
  }
180
294
  }
181
295
  async function refreshPickerModels(ctx, picker) {
@@ -218,6 +332,194 @@ async function refreshPickerModels(ctx, picker) {
218
332
  clearTimeout(timeout);
219
333
  }
220
334
  }
335
+ /** One mounted /agents TUI whose child pages switch without restoring the editor between them. */
336
+ class AgentsMenuComponent extends Container {
337
+ get focused() {
338
+ return this._focused;
339
+ }
340
+ set focused(value) {
341
+ this._focused = value;
342
+ if (this.activeScreen && isFocusable(this.activeScreen))
343
+ this.activeScreen.focused = value;
344
+ }
345
+ constructor(options) {
346
+ super();
347
+ this.route = { kind: "profiles" };
348
+ this.selectedSettingsAction = "model";
349
+ this.saving = false;
350
+ this.closed = false;
351
+ this._focused = false;
352
+ this.tui = options.tui;
353
+ this.theme = options.theme;
354
+ this.keybindings = options.keybindings;
355
+ this.ctx = options.ctx;
356
+ this.currentThinking = options.currentThinking;
357
+ this.config = options.config;
358
+ this.onDone = options.onDone;
359
+ this.showProfiles();
360
+ }
361
+ disposeActiveScreen() {
362
+ const screen = this.activeScreen;
363
+ this.activeScreen = undefined;
364
+ if (!screen)
365
+ return;
366
+ const disposable = screen;
367
+ if (isFocusable(screen))
368
+ screen.focused = false;
369
+ disposable.dispose?.();
370
+ }
371
+ setActiveScreen(screen) {
372
+ this.disposeActiveScreen();
373
+ this.clear();
374
+ this.activeScreen = screen;
375
+ this.addChild(screen);
376
+ if (isFocusable(screen))
377
+ screen.focused = this._focused;
378
+ this.tui.requestRender();
379
+ }
380
+ showProfiles() {
381
+ this.route = { kind: "profiles" };
382
+ const choices = AGENT_PROFILES.map((profile) => ({
383
+ label: AGENT_PROFILE_LABELS[profile.name],
384
+ value: profile,
385
+ }));
386
+ const initialIndex = choices.findIndex((choice) => choice.value.name === this.selectedProfile?.name);
387
+ this.setActiveScreen(new ChoiceMenuComponent({
388
+ theme: this.theme,
389
+ keybindings: this.keybindings,
390
+ title: "Agents",
391
+ choices,
392
+ initialIndex,
393
+ cancelDescription: "close",
394
+ onDone: (choice) => {
395
+ if (!choice) {
396
+ this.onDone();
397
+ return;
398
+ }
399
+ this.selectedProfile = choice.value;
400
+ this.selectedSettingsAction = "model";
401
+ this.showSettings(choice.value);
402
+ },
403
+ }));
404
+ }
405
+ showSettings(profile, selectedAction = this.selectedSettingsAction) {
406
+ this.selectedProfile = profile;
407
+ this.selectedSettingsAction = selectedAction;
408
+ this.route = { kind: "settings", profile, selectedAction };
409
+ this.setActiveScreen(new ProfileSettingsMenuComponent({
410
+ theme: this.theme,
411
+ keybindings: this.keybindings,
412
+ profile,
413
+ override: this.config.profiles[profile.name],
414
+ models: this.ctx.modelRegistry.getAvailable(),
415
+ currentSessionModel: this.ctx.model,
416
+ currentThinking: this.currentThinking,
417
+ selectedAction,
418
+ status: this.saving ? "Saving…" : undefined,
419
+ onDone: (action) => {
420
+ if (!action) {
421
+ this.showProfiles();
422
+ return;
423
+ }
424
+ this.selectedSettingsAction = action;
425
+ if (action === "model")
426
+ this.showModelPicker(profile);
427
+ else
428
+ this.showThinkingPicker(profile);
429
+ },
430
+ }));
431
+ }
432
+ showModelPicker(profile) {
433
+ this.route = { kind: "model", profile };
434
+ const override = this.config.profiles[profile.name];
435
+ const picker = new ModelPickerComponent({
436
+ tui: this.tui,
437
+ theme: this.theme,
438
+ keybindings: this.keybindings,
439
+ profile,
440
+ savedModelId: override?.model,
441
+ models: this.ctx.modelRegistry.getAvailable(),
442
+ scopedModels: this.ctx.scopedModels,
443
+ currentSessionModel: this.ctx.model,
444
+ onDone: (choice) => {
445
+ if (!choice) {
446
+ this.showSettings(profile, "model");
447
+ return;
448
+ }
449
+ this.saveOverride(profile, { model: choice.modelId }, "model");
450
+ },
451
+ });
452
+ picker.setRefreshStatus("Refreshing model catalogs…");
453
+ this.setActiveScreen(picker);
454
+ void refreshPickerModels(this.ctx, picker);
455
+ }
456
+ showThinkingPicker(profile) {
457
+ this.route = { kind: "thinking", profile };
458
+ const override = this.config.profiles[profile.name];
459
+ const choices = [
460
+ ...buildThinkingChoices({
461
+ currentSessionModel: this.ctx.model,
462
+ models: this.ctx.modelRegistry.getAvailable(),
463
+ override,
464
+ currentThinking: this.currentThinking,
465
+ }).entries(),
466
+ ].map(([label, level]) => ({ label, value: level }));
467
+ const initialIndex = choices.findIndex((choice) => choice.label.endsWith(" ✓"));
468
+ this.setActiveScreen(new ChoiceMenuComponent({
469
+ theme: this.theme,
470
+ keybindings: this.keybindings,
471
+ title: `Thinking — ${AGENT_PROFILE_LABELS[profile.name]}`,
472
+ choices,
473
+ initialIndex,
474
+ cancelDescription: "back",
475
+ onDone: (choice) => {
476
+ if (!choice) {
477
+ this.showSettings(profile, "thinking");
478
+ return;
479
+ }
480
+ this.saveOverride(profile, { thinking: choice.value }, "thinking");
481
+ },
482
+ }));
483
+ }
484
+ saveOverride(profile, patch, returnAction) {
485
+ if (this.saving)
486
+ return;
487
+ this.saving = true;
488
+ this.showSettings(profile, returnAction);
489
+ void persistOverride(this.ctx, profile, patch)
490
+ .then((config) => this.completeSave(profile, config), () => this.completeSave(profile, undefined))
491
+ .catch(() => {
492
+ // A reload can stale the command context while the queued file write finishes.
493
+ });
494
+ }
495
+ completeSave(profile, config) {
496
+ if (this.closed)
497
+ return;
498
+ this.saving = false;
499
+ if (config)
500
+ this.config = config;
501
+ if (this.route.kind === "settings" && this.route.profile.name === profile.name) {
502
+ this.showSettings(profile, this.route.selectedAction);
503
+ }
504
+ }
505
+ handleInput(data) {
506
+ if (!this.saving) {
507
+ this.activeScreen?.handleInput?.(data);
508
+ return;
509
+ }
510
+ if (!this.keybindings.matches(data, "tui.select.cancel"))
511
+ return;
512
+ if (this.route.kind === "settings")
513
+ this.showProfiles();
514
+ else if (this.route.kind === "profiles")
515
+ this.onDone();
516
+ }
517
+ dispose() {
518
+ this.closed = true;
519
+ this.disposeActiveScreen();
520
+ this.clear();
521
+ }
522
+ }
221
523
  async function selectProfile(ctx) {
222
524
  const labels = AGENT_PROFILES.map((profile) => AGENT_PROFILE_LABELS[profile.name]);
223
525
  const label = await ctx.ui.select("Agents", labels);
@@ -225,18 +527,6 @@ async function selectProfile(ctx) {
225
527
  ? undefined
226
528
  : AGENT_PROFILES.find((profile) => AGENT_PROFILE_LABELS[profile.name] === label);
227
529
  }
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,
238
- }));
239
- }
240
530
  async function showDialogSettingsMenu(ctx, profile, override, currentThinking) {
241
531
  const options = new Map();
242
532
  for (const row of buildSettingsRows({
@@ -250,25 +540,6 @@ async function showDialogSettingsMenu(ctx, profile, override, currentThinking) {
250
540
  const label = await ctx.ui.select(AGENT_PROFILE_LABELS[profile.name], [...options.keys()]);
251
541
  return label === undefined ? undefined : options.get(label);
252
542
  }
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
543
  async function showDialogModelPicker(ctx, profile, override) {
273
544
  const models = [...ctx.modelRegistry.getAvailable()].sort(compareModels);
274
545
  const choices = buildModelChoices({
@@ -279,7 +550,7 @@ async function showDialogModelPicker(ctx, profile, override) {
279
550
  const label = await ctx.ui.select(`Model — ${AGENT_PROFILE_LABELS[profile.name]}`, [...choices.keys()]);
280
551
  return label === undefined ? undefined : { modelId: choices.get(label) };
281
552
  }
282
- async function showThinkingPicker(ctx, profile, override, currentThinking) {
553
+ async function showDialogThinkingPicker(ctx, profile, override, currentThinking) {
283
554
  const choices = buildThinkingChoices({
284
555
  currentSessionModel: ctx.model,
285
556
  models: ctx.modelRegistry.getAvailable(),
@@ -289,43 +560,56 @@ async function showThinkingPicker(ctx, profile, override, currentThinking) {
289
560
  const label = await ctx.ui.select(`Thinking — ${AGENT_PROFILE_LABELS[profile.name]}`, [...choices.keys()]);
290
561
  return label === undefined ? undefined : { level: choices.get(label) };
291
562
  }
292
- async function runProfileSettings(ctx, profile, currentThinking) {
563
+ async function runDialogProfileSettings(ctx, profile, currentThinking) {
293
564
  const agentDir = getAgentDir();
294
- const isTui = ctx.mode === "tui";
295
565
  while (true) {
296
566
  const config = await loadSubagentConfig(agentDir);
297
567
  const override = config.profiles[profile.name];
298
- const action = isTui
299
- ? await showTuiSettingsMenu(ctx, profile, override, currentThinking)
300
- : await showDialogSettingsMenu(ctx, profile, override, currentThinking);
568
+ const action = await showDialogSettingsMenu(ctx, profile, override, currentThinking);
301
569
  if (!action)
302
570
  return;
303
571
  if (action === "model") {
304
- const chosen = isTui
305
- ? await showTuiModelPicker(ctx, profile, override)
306
- : await showDialogModelPicker(ctx, profile, override);
572
+ const chosen = await showDialogModelPicker(ctx, profile, override);
307
573
  if (!chosen)
308
574
  continue;
309
- await persistOverride(ctx, profile, { model: chosen.modelId }, override?.model);
575
+ await persistOverride(ctx, profile, { model: chosen.modelId });
310
576
  }
311
577
  else {
312
- const chosen = await showThinkingPicker(ctx, profile, override, currentThinking);
578
+ const chosen = await showDialogThinkingPicker(ctx, profile, override, currentThinking);
313
579
  if (!chosen)
314
580
  continue;
315
- await persistOverride(ctx, profile, { thinking: chosen.level }, override?.thinking);
581
+ await persistOverride(ctx, profile, { thinking: chosen.level });
316
582
  }
317
583
  }
318
584
  }
319
- export async function showAgentsCommand(ctx, currentThinking) {
320
- if (!ctx.hasUI) {
321
- ctx.ui.notify("/agents requires an interactive UI.", "warning");
322
- return;
323
- }
585
+ async function showTuiAgentsCommand(ctx, currentThinking) {
586
+ const config = await loadSubagentConfig(getAgentDir());
587
+ await ctx.ui.custom((tui, theme, keybindings, done) => new AgentsMenuComponent({
588
+ tui,
589
+ theme,
590
+ keybindings,
591
+ ctx,
592
+ currentThinking,
593
+ config,
594
+ onDone: () => done(),
595
+ }));
596
+ }
597
+ async function showDialogAgentsCommand(ctx, currentThinking) {
324
598
  while (true) {
325
599
  const profile = await selectProfile(ctx);
326
600
  if (!profile)
327
601
  return;
328
- await runProfileSettings(ctx, profile, currentThinking);
602
+ await runDialogProfileSettings(ctx, profile, currentThinking);
603
+ }
604
+ }
605
+ export async function showAgentsCommand(ctx, currentThinking) {
606
+ if (!ctx.hasUI) {
607
+ ctx.ui.notify("/agents requires an interactive UI.", "warning");
608
+ return;
329
609
  }
610
+ if (ctx.mode === "tui")
611
+ await showTuiAgentsCommand(ctx, currentThinking);
612
+ else
613
+ await showDialogAgentsCommand(ctx, currentThinking);
330
614
  }
331
615
  //# sourceMappingURL=agents-command.js.map