@astralyn/pi 0.84.2 → 0.84.4

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 (151) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/cli/args.js +1 -1
  3. package/dist/cli/args.js.map +1 -1
  4. package/dist/cli/config-selector.d.ts.map +1 -1
  5. package/dist/cli/config-selector.js +2 -3
  6. package/dist/cli/config-selector.js.map +1 -1
  7. package/dist/cli/project-trust.d.ts.map +1 -1
  8. package/dist/cli/project-trust.js +1 -4
  9. package/dist/cli/project-trust.js.map +1 -1
  10. package/dist/cli/startup-ui.d.ts.map +1 -1
  11. package/dist/cli/startup-ui.js +3 -5
  12. package/dist/cli/startup-ui.js.map +1 -1
  13. package/dist/config.d.ts +5 -0
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +8 -1
  16. package/dist/config.js.map +1 -1
  17. package/dist/core/agent-session.d.ts +1 -25
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +29 -408
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/compaction-controller.d.ts +89 -0
  22. package/dist/core/compaction-controller.d.ts.map +1 -0
  23. package/dist/core/compaction-controller.js +428 -0
  24. package/dist/core/compaction-controller.js.map +1 -0
  25. package/dist/core/extensions/index.d.ts +1 -1
  26. package/dist/core/extensions/index.d.ts.map +1 -1
  27. package/dist/core/extensions/index.js.map +1 -1
  28. package/dist/core/extensions/loader.js +3 -3
  29. package/dist/core/extensions/loader.js.map +1 -1
  30. package/dist/core/extensions/types.d.ts +2 -27
  31. package/dist/core/extensions/types.d.ts.map +1 -1
  32. package/dist/core/extensions/types.js.map +1 -1
  33. package/dist/core/provider-attribution.js +2 -2
  34. package/dist/core/provider-attribution.js.map +1 -1
  35. package/dist/core/settings-manager.js +1 -1
  36. package/dist/core/settings-manager.js.map +1 -1
  37. package/dist/core/telemetry.d.ts +1 -1
  38. package/dist/core/telemetry.d.ts.map +1 -1
  39. package/dist/core/telemetry.js +1 -1
  40. package/dist/core/telemetry.js.map +1 -1
  41. package/dist/extensions/deepwiki/index.d.ts.map +1 -1
  42. package/dist/extensions/deepwiki/index.js +23 -1
  43. package/dist/extensions/deepwiki/index.js.map +1 -1
  44. package/dist/extensions/deepwiki/render.d.ts +1 -1
  45. package/dist/extensions/deepwiki/render.d.ts.map +1 -1
  46. package/dist/extensions/deepwiki/render.js +4 -2
  47. package/dist/extensions/deepwiki/render.js.map +1 -1
  48. package/dist/extensions/question/index.d.ts.map +1 -1
  49. package/dist/extensions/question/index.js +0 -1
  50. package/dist/extensions/question/index.js.map +1 -1
  51. package/dist/extensions/subagent/agents-command.d.ts +4 -0
  52. package/dist/extensions/subagent/agents-command.d.ts.map +1 -0
  53. package/dist/extensions/subagent/agents-command.js +230 -0
  54. package/dist/extensions/subagent/agents-command.js.map +1 -0
  55. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  56. package/dist/extensions/subagent/agents.js +2 -0
  57. package/dist/extensions/subagent/agents.js.map +1 -1
  58. package/dist/extensions/subagent/display-name.d.ts +6 -0
  59. package/dist/extensions/subagent/display-name.d.ts.map +1 -0
  60. package/dist/extensions/subagent/display-name.js +13 -0
  61. package/dist/extensions/subagent/display-name.js.map +1 -0
  62. package/dist/extensions/subagent/index.d.ts.map +1 -1
  63. package/dist/extensions/subagent/index.js +19 -126
  64. package/dist/extensions/subagent/index.js.map +1 -1
  65. package/dist/extensions/subagent/render.d.ts.map +1 -1
  66. package/dist/extensions/subagent/render.js +1 -10
  67. package/dist/extensions/subagent/render.js.map +1 -1
  68. package/dist/extensions/subagent/settings.d.ts +0 -1
  69. package/dist/extensions/subagent/settings.d.ts.map +1 -1
  70. package/dist/extensions/subagent/settings.js +3 -7
  71. package/dist/extensions/subagent/settings.js.map +1 -1
  72. package/dist/extensions/subagent/types.d.ts +2 -0
  73. package/dist/extensions/subagent/types.d.ts.map +1 -1
  74. package/dist/extensions/subagent/types.js.map +1 -1
  75. package/dist/extensions/subagent/ui/model-list.d.ts +67 -0
  76. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -0
  77. package/dist/extensions/subagent/ui/model-list.js +242 -0
  78. package/dist/extensions/subagent/ui/model-list.js.map +1 -0
  79. package/dist/extensions/subagent/ui/profile-editor.d.ts +54 -0
  80. package/dist/extensions/subagent/ui/profile-editor.d.ts.map +1 -0
  81. package/dist/extensions/subagent/ui/profile-editor.js +154 -0
  82. package/dist/extensions/subagent/ui/profile-editor.js.map +1 -0
  83. package/dist/extensions/subagent/ui/profile-picker.d.ts +32 -0
  84. package/dist/extensions/subagent/ui/profile-picker.d.ts.map +1 -0
  85. package/dist/extensions/subagent/ui/profile-picker.js +149 -0
  86. package/dist/extensions/subagent/ui/profile-picker.js.map +1 -0
  87. package/dist/extensions/todo/constants.d.ts +6 -17
  88. package/dist/extensions/todo/constants.d.ts.map +1 -1
  89. package/dist/extensions/todo/constants.js +20 -31
  90. package/dist/extensions/todo/constants.js.map +1 -1
  91. package/dist/extensions/todo/index.d.ts.map +1 -1
  92. package/dist/extensions/todo/index.js +36 -57
  93. package/dist/extensions/todo/index.js.map +1 -1
  94. package/dist/extensions/todo/schema.d.ts +20 -59
  95. package/dist/extensions/todo/schema.d.ts.map +1 -1
  96. package/dist/extensions/todo/schema.js +23 -69
  97. package/dist/extensions/todo/schema.js.map +1 -1
  98. package/dist/extensions/todo/state.d.ts +23 -65
  99. package/dist/extensions/todo/state.d.ts.map +1 -1
  100. package/dist/extensions/todo/state.js +238 -1262
  101. package/dist/extensions/todo/state.js.map +1 -1
  102. package/dist/extensions/todo/view.d.ts +19 -10
  103. package/dist/extensions/todo/view.d.ts.map +1 -1
  104. package/dist/extensions/todo/view.js +411 -463
  105. package/dist/extensions/todo/view.js.map +1 -1
  106. package/dist/extensions/todo/widget.d.ts +15 -0
  107. package/dist/extensions/todo/widget.d.ts.map +1 -0
  108. package/dist/extensions/todo/widget.js +50 -0
  109. package/dist/extensions/todo/widget.js.map +1 -0
  110. package/dist/modes/interactive/components/extension-selector.d.ts +1 -4
  111. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  112. package/dist/modes/interactive/components/extension-selector.js +6 -12
  113. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  114. package/dist/modes/interactive/components/settings-selector.js +1 -1
  115. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  116. package/dist/modes/interactive/components/tool-chrome.d.ts +28 -0
  117. package/dist/modes/interactive/components/tool-chrome.d.ts.map +1 -0
  118. package/dist/modes/interactive/components/tool-chrome.js +81 -0
  119. package/dist/modes/interactive/components/tool-chrome.js.map +1 -0
  120. package/dist/modes/interactive/components/tool-execution.d.ts +0 -3
  121. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  122. package/dist/modes/interactive/components/tool-execution.js +11 -108
  123. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  124. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  125. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  126. package/dist/modes/interactive/interactive-mode.js +35 -52
  127. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  128. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  129. package/dist/modes/rpc/rpc-mode.js +1 -8
  130. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  131. package/docs/bundled/README.md +1 -1
  132. package/docs/bundled/extensions/subagent.md +20 -5
  133. package/docs/bundled/extensions/todo.md +84 -24
  134. package/docs/bundled/tool-presentation.md +3 -3
  135. package/docs/extensions.md +6 -23
  136. package/docs/settings.md +1 -1
  137. package/docs/usage.md +1 -1
  138. package/npm-shrinkwrap.json +2 -2
  139. package/package.json +1 -1
  140. package/dist/extensions/subagent/picker.d.ts +0 -31
  141. package/dist/extensions/subagent/picker.d.ts.map +0 -1
  142. package/dist/extensions/subagent/picker.js +0 -109
  143. package/dist/extensions/subagent/picker.js.map +0 -1
  144. package/dist/extensions/todo/overlay.d.ts +0 -24
  145. package/dist/extensions/todo/overlay.d.ts.map +0 -1
  146. package/dist/extensions/todo/overlay.js +0 -135
  147. package/dist/extensions/todo/overlay.js.map +0 -1
  148. package/dist/utils/coalescing-terminal.d.ts +0 -132
  149. package/dist/utils/coalescing-terminal.d.ts.map +0 -1
  150. package/dist/utils/coalescing-terminal.js +0 -292
  151. package/dist/utils/coalescing-terminal.js.map +0 -1
@@ -0,0 +1,242 @@
1
+ import { Container, fuzzyFilter, Input, Spacer, Text, TruncatedText, } from "@earendil-works/pi-tui";
2
+ const MAX_VISIBLE_MODELS = 10;
3
+ function fullModelId(model) {
4
+ return `${model.provider}/${model.id}`;
5
+ }
6
+ function parseModelId(value) {
7
+ const separator = value.indexOf("/");
8
+ return separator > 0
9
+ ? { provider: value.slice(0, separator), id: value.slice(separator + 1) }
10
+ : { provider: "", id: value };
11
+ }
12
+ function compareModels(left, right) {
13
+ const provider = left.provider.localeCompare(right.provider);
14
+ return provider !== 0 ? provider : left.id.localeCompare(right.id);
15
+ }
16
+ function modelSearchText(item) {
17
+ if (item.modelId === undefined) {
18
+ const inherited = item.model ? ` ${fullModelId(item.model)} ${item.model.name}` : "";
19
+ return `inherit${inherited}`;
20
+ }
21
+ const name = item.name ? ` ${item.name}` : "";
22
+ return `${item.provider} ${item.provider}/${item.id} ${item.provider} ${item.id}${name}`;
23
+ }
24
+ /** Non-closing /model-style search list embedded by the profile editor. */
25
+ export class ProfileModelListComponent extends Container {
26
+ get focused() {
27
+ return this._focused;
28
+ }
29
+ set focused(value) {
30
+ this._focused = value;
31
+ this.searchInput.focused = value;
32
+ }
33
+ constructor(options) {
34
+ super();
35
+ this.allChoices = [];
36
+ this.scopedChoices = [];
37
+ this.activeChoices = [];
38
+ this.filteredChoices = [];
39
+ this.selectedIndex = 0;
40
+ this.statusTone = "muted";
41
+ this._focused = false;
42
+ this.theme = options.theme;
43
+ this.keybindings = options.keybindings;
44
+ this.models = [...options.models];
45
+ this.currentSessionModel = options.currentSessionModel;
46
+ this.savedModelId = options.savedModelId;
47
+ this.scopedModelKeys = new Set(options.scopedModels.map(({ model }) => fullModelId(model)));
48
+ this.scope = this.scopedModelKeys.size > 0 ? "scoped" : "all";
49
+ this.onSelectionChange = options.onSelectionChange;
50
+ this.scopeContainer = new Container();
51
+ this.addChild(this.scopeContainer);
52
+ this.searchInput = new Input();
53
+ this.addChild(this.searchInput);
54
+ this.addChild(new Spacer(1));
55
+ this.listContainer = new Container();
56
+ this.addChild(this.listContainer);
57
+ this.rebuildChoices(this.savedModelId ?? "");
58
+ }
59
+ makeInheritChoice() {
60
+ return {
61
+ key: "",
62
+ modelId: undefined,
63
+ model: this.currentSessionModel,
64
+ unavailable: false,
65
+ provider: this.currentSessionModel?.provider ?? "",
66
+ id: "inherit",
67
+ name: this.currentSessionModel?.name,
68
+ };
69
+ }
70
+ makeModelChoice(model) {
71
+ return {
72
+ key: fullModelId(model),
73
+ modelId: fullModelId(model),
74
+ model,
75
+ unavailable: false,
76
+ provider: model.provider,
77
+ id: model.id,
78
+ name: model.name,
79
+ };
80
+ }
81
+ makeUnavailableChoice(modelId) {
82
+ const parsed = parseModelId(modelId);
83
+ return {
84
+ key: modelId,
85
+ modelId,
86
+ model: undefined,
87
+ unavailable: true,
88
+ provider: parsed.provider,
89
+ id: parsed.id,
90
+ name: undefined,
91
+ };
92
+ }
93
+ buildChoices(models) {
94
+ const sorted = [...models].sort(compareModels);
95
+ const availableById = new Map(this.models.map((model) => [fullModelId(model), model]));
96
+ const choices = [this.makeInheritChoice()];
97
+ if (this.savedModelId) {
98
+ const saved = availableById.get(this.savedModelId);
99
+ choices.push(saved ? this.makeModelChoice(saved) : this.makeUnavailableChoice(this.savedModelId));
100
+ }
101
+ for (const model of sorted) {
102
+ if (fullModelId(model) !== this.savedModelId)
103
+ choices.push(this.makeModelChoice(model));
104
+ }
105
+ return choices;
106
+ }
107
+ rebuildChoices(preferredKey) {
108
+ const currentKey = preferredKey ?? this.filteredChoices[this.selectedIndex]?.key ?? this.savedModelId ?? "";
109
+ this.allChoices = this.buildChoices(this.models);
110
+ const scopedModels = this.models.filter((model) => this.scopedModelKeys.has(fullModelId(model)));
111
+ this.scopedChoices = this.buildChoices(scopedModels);
112
+ this.activeChoices = this.scope === "scoped" ? this.scopedChoices : this.allChoices;
113
+ this.applyFilter(this.searchInput.getValue(), currentKey, false);
114
+ this.updateScopeView();
115
+ }
116
+ applyFilter(query, preferredKey, resetSelection = true) {
117
+ this.filteredChoices = query ? fuzzyFilter(this.activeChoices, query, modelSearchText) : this.activeChoices;
118
+ if (preferredKey !== undefined) {
119
+ const preferredIndex = this.filteredChoices.findIndex((choice) => choice.key === preferredKey);
120
+ this.selectedIndex = preferredIndex >= 0 ? preferredIndex : 0;
121
+ }
122
+ else if (query && resetSelection) {
123
+ this.selectedIndex = 0;
124
+ }
125
+ else {
126
+ this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredChoices.length - 1));
127
+ }
128
+ this.updateList();
129
+ this.onSelectionChange(this.getSelectedChoice());
130
+ }
131
+ updateScopeView() {
132
+ this.scopeContainer.clear();
133
+ if (this.scopedModelKeys.size === 0) {
134
+ this.scopeContainer.addChild(new Text(this.theme.fg("warning", "Only showing models from configured providers. Use /login to add providers."), 0, 0));
135
+ this.scopeContainer.addChild(new Spacer(1));
136
+ return;
137
+ }
138
+ const all = this.scope === "all" ? this.theme.fg("accent", "all") : this.theme.fg("muted", "all");
139
+ const scoped = this.scope === "scoped" ? this.theme.fg("accent", "scoped") : this.theme.fg("muted", "scoped");
140
+ this.scopeContainer.addChild(new Text(`${this.theme.fg("muted", "Scope: ")}${all}${this.theme.fg("muted", " | ")}${scoped}`, 0, 0));
141
+ this.scopeContainer.addChild(new Spacer(1));
142
+ }
143
+ choiceLabel(choice) {
144
+ if (choice.modelId === undefined) {
145
+ const inherited = choice.model ? fullModelId(choice.model) : "none";
146
+ return `inherit ${this.theme.fg("muted", `(${inherited})`)}`;
147
+ }
148
+ if (choice.unavailable) {
149
+ const badge = choice.provider ? `${choice.provider} · unavailable` : "unavailable";
150
+ return `${choice.id} ${this.theme.fg("warning", `[${badge}]`)}`;
151
+ }
152
+ return `${choice.id} ${this.theme.fg("muted", `[${choice.provider}]`)}`;
153
+ }
154
+ updateList() {
155
+ this.listContainer.clear();
156
+ const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(MAX_VISIBLE_MODELS / 2), this.filteredChoices.length - MAX_VISIBLE_MODELS));
157
+ const endIndex = Math.min(startIndex + MAX_VISIBLE_MODELS, this.filteredChoices.length);
158
+ for (let index = startIndex; index < endIndex; index++) {
159
+ const choice = this.filteredChoices[index];
160
+ if (!choice)
161
+ continue;
162
+ const selected = index === this.selectedIndex;
163
+ const saved = choice.modelId === this.savedModelId;
164
+ const prefix = selected ? this.theme.fg("accent", "→ ") : " ";
165
+ const label = this.choiceLabel(choice);
166
+ const styledLabel = selected ? this.theme.fg("accent", label) : label;
167
+ const checkmark = saved ? this.theme.fg("success", " ✓") : "";
168
+ this.listContainer.addChild(new TruncatedText(`${prefix}${styledLabel}${checkmark}`, 0, 0));
169
+ }
170
+ if (startIndex > 0 || endIndex < this.filteredChoices.length) {
171
+ this.listContainer.addChild(new TruncatedText(this.theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredChoices.length})`), 0, 0));
172
+ }
173
+ if (this.filteredChoices.length === 0) {
174
+ this.listContainer.addChild(new Text(this.theme.fg("muted", " No matching models"), 0, 0));
175
+ }
176
+ else {
177
+ const selected = this.filteredChoices[this.selectedIndex];
178
+ if (selected?.model?.name) {
179
+ this.listContainer.addChild(new Spacer(1));
180
+ this.listContainer.addChild(new Text(this.theme.fg("muted", ` Model Name: ${selected.model.name}`), 0, 0));
181
+ }
182
+ }
183
+ if (this.statusMessage) {
184
+ this.listContainer.addChild(new Spacer(1));
185
+ this.listContainer.addChild(new Text(this.theme.fg(this.statusTone, ` ${this.statusMessage}`), 0, 0));
186
+ }
187
+ }
188
+ moveSelection(offset) {
189
+ if (this.filteredChoices.length === 0)
190
+ return;
191
+ this.selectedIndex = (this.selectedIndex + offset + this.filteredChoices.length) % this.filteredChoices.length;
192
+ this.updateList();
193
+ this.onSelectionChange(this.getSelectedChoice());
194
+ }
195
+ toggleScope() {
196
+ if (this.scopedModelKeys.size === 0)
197
+ return;
198
+ const currentKey = this.filteredChoices[this.selectedIndex]?.key;
199
+ this.scope = this.scope === "all" ? "scoped" : "all";
200
+ this.activeChoices = this.scope === "scoped" ? this.scopedChoices : this.allChoices;
201
+ this.applyFilter(this.searchInput.getValue(), currentKey, false);
202
+ this.updateScopeView();
203
+ }
204
+ getSelectedChoice() {
205
+ const selected = this.filteredChoices[this.selectedIndex];
206
+ if (!selected)
207
+ return undefined;
208
+ return { modelId: selected.modelId, model: selected.model, unavailable: selected.unavailable };
209
+ }
210
+ getScope() {
211
+ return this.scope;
212
+ }
213
+ getSearchValue() {
214
+ return this.searchInput.getValue();
215
+ }
216
+ updateModels(models) {
217
+ const selectedKey = this.filteredChoices[this.selectedIndex]?.key;
218
+ this.models = [...models];
219
+ this.rebuildChoices(selectedKey);
220
+ }
221
+ setStatus(message, tone = "muted") {
222
+ this.statusMessage = message;
223
+ this.statusTone = tone;
224
+ this.updateList();
225
+ }
226
+ handleInput(data) {
227
+ if (this.keybindings.matches(data, "tui.input.tab")) {
228
+ this.toggleScope();
229
+ }
230
+ else if (this.keybindings.matches(data, "tui.select.up")) {
231
+ this.moveSelection(-1);
232
+ }
233
+ else if (this.keybindings.matches(data, "tui.select.down")) {
234
+ this.moveSelection(1);
235
+ }
236
+ else {
237
+ this.searchInput.handleInput(data);
238
+ this.applyFilter(this.searchInput.getValue());
239
+ }
240
+ }
241
+ }
242
+ //# sourceMappingURL=model-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-list.js","sourceRoot":"","sources":["../../../../src/extensions/subagent/ui/model-list.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Model } from \"@earendil-works/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tInput,\n\ttype KeybindingsManager,\n\tSpacer,\n\tText,\n\tTruncatedText,\n} from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\n\nconst MAX_VISIBLE_MODELS = 10;\n\ntype ModelScope = \"all\" | \"scoped\";\ntype StatusTone = \"muted\" | \"success\" | \"error\";\n\nexport interface ProfileModelChoice {\n\t/** Undefined represents inheriting the current session model. */\n\tmodelId: string | undefined;\n\t/** Effective model for capability checks; unavailable saved overrides have none. */\n\tmodel: Model<Api> | undefined;\n\tunavailable: boolean;\n}\n\nexport interface ProfileModelListOptions {\n\ttheme: Theme;\n\tkeybindings: KeybindingsManager;\n\tmodels: readonly Model<Api>[];\n\tscopedModels: readonly { model: Model<Api> }[];\n\tcurrentSessionModel: Model<Api> | undefined;\n\tsavedModelId: string | undefined;\n\tonSelectionChange: (choice: ProfileModelChoice | undefined) => void;\n}\n\ninterface ModelChoiceItem extends ProfileModelChoice {\n\tkey: string;\n\tprovider: string;\n\tid: string;\n\tname: string | undefined;\n}\n\nfunction fullModelId(model: Pick<Model<Api>, \"provider\" | \"id\">): string {\n\treturn `${model.provider}/${model.id}`;\n}\n\nfunction parseModelId(value: string): { provider: string; id: string } {\n\tconst separator = value.indexOf(\"/\");\n\treturn separator > 0\n\t\t? { provider: value.slice(0, separator), id: value.slice(separator + 1) }\n\t\t: { provider: \"\", id: value };\n}\n\nfunction compareModels(left: Model<Api>, right: Model<Api>): number {\n\tconst provider = left.provider.localeCompare(right.provider);\n\treturn provider !== 0 ? provider : left.id.localeCompare(right.id);\n}\n\nfunction modelSearchText(item: ModelChoiceItem): string {\n\tif (item.modelId === undefined) {\n\t\tconst inherited = item.model ? ` ${fullModelId(item.model)} ${item.model.name}` : \"\";\n\t\treturn `inherit${inherited}`;\n\t}\n\tconst name = item.name ? ` ${item.name}` : \"\";\n\treturn `${item.provider} ${item.provider}/${item.id} ${item.provider} ${item.id}${name}`;\n}\n\n/** Non-closing /model-style search list embedded by the profile editor. */\nexport class ProfileModelListComponent extends Container implements Focusable {\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly currentSessionModel: Model<Api> | undefined;\n\tprivate readonly savedModelId: string | undefined;\n\tprivate readonly scopedModelKeys: Set<string>;\n\tprivate readonly onSelectionChange: (choice: ProfileModelChoice | undefined) => void;\n\tprivate readonly searchInput: Input;\n\tprivate readonly scopeContainer: Container;\n\tprivate readonly listContainer: Container;\n\tprivate models: Model<Api>[];\n\tprivate allChoices: ModelChoiceItem[] = [];\n\tprivate scopedChoices: ModelChoiceItem[] = [];\n\tprivate activeChoices: ModelChoiceItem[] = [];\n\tprivate filteredChoices: ModelChoiceItem[] = [];\n\tprivate selectedIndex = 0;\n\tprivate scope: ModelScope;\n\tprivate statusMessage: string | undefined;\n\tprivate statusTone: StatusTone = \"muted\";\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.searchInput.focused = value;\n\t}\n\n\tconstructor(options: ProfileModelListOptions) {\n\t\tsuper();\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.models = [...options.models];\n\t\tthis.currentSessionModel = options.currentSessionModel;\n\t\tthis.savedModelId = options.savedModelId;\n\t\tthis.scopedModelKeys = new Set(options.scopedModels.map(({ model }) => fullModelId(model)));\n\t\tthis.scope = this.scopedModelKeys.size > 0 ? \"scoped\" : \"all\";\n\t\tthis.onSelectionChange = options.onSelectionChange;\n\n\t\tthis.scopeContainer = new Container();\n\t\tthis.addChild(this.scopeContainer);\n\t\tthis.searchInput = new Input();\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.rebuildChoices(this.savedModelId ?? \"\");\n\t}\n\n\tprivate makeInheritChoice(): ModelChoiceItem {\n\t\treturn {\n\t\t\tkey: \"\",\n\t\t\tmodelId: undefined,\n\t\t\tmodel: this.currentSessionModel,\n\t\t\tunavailable: false,\n\t\t\tprovider: this.currentSessionModel?.provider ?? \"\",\n\t\t\tid: \"inherit\",\n\t\t\tname: this.currentSessionModel?.name,\n\t\t};\n\t}\n\n\tprivate makeModelChoice(model: Model<Api>): ModelChoiceItem {\n\t\treturn {\n\t\t\tkey: fullModelId(model),\n\t\t\tmodelId: fullModelId(model),\n\t\t\tmodel,\n\t\t\tunavailable: false,\n\t\t\tprovider: model.provider,\n\t\t\tid: model.id,\n\t\t\tname: model.name,\n\t\t};\n\t}\n\n\tprivate makeUnavailableChoice(modelId: string): ModelChoiceItem {\n\t\tconst parsed = parseModelId(modelId);\n\t\treturn {\n\t\t\tkey: modelId,\n\t\t\tmodelId,\n\t\t\tmodel: undefined,\n\t\t\tunavailable: true,\n\t\t\tprovider: parsed.provider,\n\t\t\tid: parsed.id,\n\t\t\tname: undefined,\n\t\t};\n\t}\n\n\tprivate buildChoices(models: readonly Model<Api>[]): ModelChoiceItem[] {\n\t\tconst sorted = [...models].sort(compareModels);\n\t\tconst availableById = new Map(this.models.map((model) => [fullModelId(model), model]));\n\t\tconst choices: ModelChoiceItem[] = [this.makeInheritChoice()];\n\t\tif (this.savedModelId) {\n\t\t\tconst saved = availableById.get(this.savedModelId);\n\t\t\tchoices.push(saved ? this.makeModelChoice(saved) : this.makeUnavailableChoice(this.savedModelId));\n\t\t}\n\t\tfor (const model of sorted) {\n\t\t\tif (fullModelId(model) !== this.savedModelId) choices.push(this.makeModelChoice(model));\n\t\t}\n\t\treturn choices;\n\t}\n\n\tprivate rebuildChoices(preferredKey?: string): void {\n\t\tconst currentKey = preferredKey ?? this.filteredChoices[this.selectedIndex]?.key ?? this.savedModelId ?? \"\";\n\t\tthis.allChoices = this.buildChoices(this.models);\n\t\tconst scopedModels = this.models.filter((model) => this.scopedModelKeys.has(fullModelId(model)));\n\t\tthis.scopedChoices = this.buildChoices(scopedModels);\n\t\tthis.activeChoices = this.scope === \"scoped\" ? this.scopedChoices : this.allChoices;\n\t\tthis.applyFilter(this.searchInput.getValue(), currentKey, false);\n\t\tthis.updateScopeView();\n\t}\n\n\tprivate applyFilter(query: string, preferredKey?: string, resetSelection = true): void {\n\t\tthis.filteredChoices = query ? fuzzyFilter(this.activeChoices, query, modelSearchText) : this.activeChoices;\n\t\tif (preferredKey !== undefined) {\n\t\t\tconst preferredIndex = this.filteredChoices.findIndex((choice) => choice.key === preferredKey);\n\t\t\tthis.selectedIndex = preferredIndex >= 0 ? preferredIndex : 0;\n\t\t} else if (query && resetSelection) {\n\t\t\tthis.selectedIndex = 0;\n\t\t} else {\n\t\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredChoices.length - 1));\n\t\t}\n\t\tthis.updateList();\n\t\tthis.onSelectionChange(this.getSelectedChoice());\n\t}\n\n\tprivate updateScopeView(): void {\n\t\tthis.scopeContainer.clear();\n\t\tif (this.scopedModelKeys.size === 0) {\n\t\t\tthis.scopeContainer.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\tthis.theme.fg(\"warning\", \"Only showing models from configured providers. Use /login to add providers.\"),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t\tthis.scopeContainer.addChild(new Spacer(1));\n\t\t\treturn;\n\t\t}\n\t\tconst all = this.scope === \"all\" ? this.theme.fg(\"accent\", \"all\") : this.theme.fg(\"muted\", \"all\");\n\t\tconst scoped = this.scope === \"scoped\" ? this.theme.fg(\"accent\", \"scoped\") : this.theme.fg(\"muted\", \"scoped\");\n\t\tthis.scopeContainer.addChild(\n\t\t\tnew Text(`${this.theme.fg(\"muted\", \"Scope: \")}${all}${this.theme.fg(\"muted\", \" | \")}${scoped}`, 0, 0),\n\t\t);\n\t\tthis.scopeContainer.addChild(new Spacer(1));\n\t}\n\n\tprivate choiceLabel(choice: ModelChoiceItem): string {\n\t\tif (choice.modelId === undefined) {\n\t\t\tconst inherited = choice.model ? fullModelId(choice.model) : \"none\";\n\t\t\treturn `inherit ${this.theme.fg(\"muted\", `(${inherited})`)}`;\n\t\t}\n\t\tif (choice.unavailable) {\n\t\t\tconst badge = choice.provider ? `${choice.provider} · unavailable` : \"unavailable\";\n\t\t\treturn `${choice.id} ${this.theme.fg(\"warning\", `[${badge}]`)}`;\n\t\t}\n\t\treturn `${choice.id} ${this.theme.fg(\"muted\", `[${choice.provider}]`)}`;\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tthis.selectedIndex - Math.floor(MAX_VISIBLE_MODELS / 2),\n\t\t\t\tthis.filteredChoices.length - MAX_VISIBLE_MODELS,\n\t\t\t),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + MAX_VISIBLE_MODELS, this.filteredChoices.length);\n\t\tfor (let index = startIndex; index < endIndex; index++) {\n\t\t\tconst choice = this.filteredChoices[index];\n\t\t\tif (!choice) continue;\n\t\t\tconst selected = index === this.selectedIndex;\n\t\t\tconst saved = choice.modelId === this.savedModelId;\n\t\t\tconst prefix = selected ? this.theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst label = this.choiceLabel(choice);\n\t\t\tconst styledLabel = selected ? this.theme.fg(\"accent\", label) : label;\n\t\t\tconst checkmark = saved ? this.theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(`${prefix}${styledLabel}${checkmark}`, 0, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredChoices.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew TruncatedText(\n\t\t\t\t\tthis.theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredChoices.length})`),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (this.filteredChoices.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t} else {\n\t\t\tconst selected = this.filteredChoices[this.selectedIndex];\n\t\t\tif (selected?.model?.name) {\n\t\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", ` Model Name: ${selected.model.name}`), 0, 0));\n\t\t\t}\n\t\t}\n\t\tif (this.statusMessage) {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(this.statusTone, ` ${this.statusMessage}`), 0, 0));\n\t\t}\n\t}\n\n\tprivate moveSelection(offset: -1 | 1): void {\n\t\tif (this.filteredChoices.length === 0) return;\n\t\tthis.selectedIndex = (this.selectedIndex + offset + this.filteredChoices.length) % this.filteredChoices.length;\n\t\tthis.updateList();\n\t\tthis.onSelectionChange(this.getSelectedChoice());\n\t}\n\n\tprivate toggleScope(): void {\n\t\tif (this.scopedModelKeys.size === 0) return;\n\t\tconst currentKey = this.filteredChoices[this.selectedIndex]?.key;\n\t\tthis.scope = this.scope === \"all\" ? \"scoped\" : \"all\";\n\t\tthis.activeChoices = this.scope === \"scoped\" ? this.scopedChoices : this.allChoices;\n\t\tthis.applyFilter(this.searchInput.getValue(), currentKey, false);\n\t\tthis.updateScopeView();\n\t}\n\n\tgetSelectedChoice(): ProfileModelChoice | undefined {\n\t\tconst selected = this.filteredChoices[this.selectedIndex];\n\t\tif (!selected) return undefined;\n\t\treturn { modelId: selected.modelId, model: selected.model, unavailable: selected.unavailable };\n\t}\n\n\tgetScope(): ModelScope {\n\t\treturn this.scope;\n\t}\n\n\tgetSearchValue(): string {\n\t\treturn this.searchInput.getValue();\n\t}\n\n\tupdateModels(models: readonly Model<Api>[]): void {\n\t\tconst selectedKey = this.filteredChoices[this.selectedIndex]?.key;\n\t\tthis.models = [...models];\n\t\tthis.rebuildChoices(selectedKey);\n\t}\n\n\tsetStatus(message: string | undefined, tone: StatusTone = \"muted\"): void {\n\t\tthis.statusMessage = message;\n\t\tthis.statusTone = tone;\n\t\tthis.updateList();\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.input.tab\")) {\n\t\t\tthis.toggleScope();\n\t\t} else if (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 {\n\t\t\tthis.searchInput.handleInput(data);\n\t\t\tthis.applyFilter(this.searchInput.getValue());\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,54 @@
1
+ import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
2
+ import type { Api, Model } from "@earendil-works/pi-ai";
3
+ import { Container, type Focusable, type KeybindingsManager, type TUI } from "@earendil-works/pi-tui";
4
+ import type { Theme } from "../../../modes/interactive/theme/theme.ts";
5
+ import type { AgentDefinition, SubagentProfileOverride } from "../types.ts";
6
+ export interface ProfileEditorResult {
7
+ model: string | undefined;
8
+ thinking: ThinkingLevel | undefined;
9
+ }
10
+ export interface ProfileEditorOptions {
11
+ tui: TUI;
12
+ theme: Theme;
13
+ keybindings: KeybindingsManager;
14
+ agent: AgentDefinition;
15
+ override: SubagentProfileOverride | undefined;
16
+ models: readonly Model<Api>[];
17
+ scopedModels: readonly {
18
+ model: Model<Api>;
19
+ }[];
20
+ currentSessionModel: Model<Api> | undefined;
21
+ currentThinking: ThinkingLevel;
22
+ onDone: (result: ProfileEditorResult | undefined) => void;
23
+ }
24
+ /** Unified model and thinking editor for one Subagent profile. */
25
+ export declare class ProfileEditorComponent extends Container implements Focusable {
26
+ private readonly tui;
27
+ private readonly theme;
28
+ private readonly keybindings;
29
+ private readonly currentThinking;
30
+ private readonly onDone;
31
+ private readonly thinkingContainer;
32
+ private readonly modelList;
33
+ private readonly refreshAbortController;
34
+ private candidateModel;
35
+ private candidateThinking;
36
+ private availableThinking;
37
+ private closed;
38
+ private _focused;
39
+ get focused(): boolean;
40
+ set focused(value: boolean);
41
+ constructor(options: ProfileEditorOptions);
42
+ private handleModelSelection;
43
+ private inheritedThinking;
44
+ private updateThinkingView;
45
+ private cycleThinking;
46
+ private confirm;
47
+ get refreshSignal(): AbortSignal;
48
+ cancelRefresh(): void;
49
+ updateModels(models: readonly Model<Api>[]): void;
50
+ setRefreshStatus(message: string | undefined, tone?: "muted" | "success" | "error"): void;
51
+ handleInput(data: string): void;
52
+ dispose(): void;
53
+ }
54
+ //# sourceMappingURL=profile-editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-editor.d.ts","sourceRoot":"","sources":["../../../../src/extensions/subagent/ui/profile-editor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,kBAAkB,EAAgB,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAGpH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AAGvE,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAG5E,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACpC,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,kBAAkB,CAAC;IAChC,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,uBAAuB,GAAG,SAAS,CAAC;IAC9C,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9B,YAAY,EAAE,SAAS;QAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;KAAE,EAAE,CAAC;IAC/C,mBAAmB,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC5C,eAAe,EAAE,aAAa,CAAC;IAC/B,MAAM,EAAE,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,KAAK,IAAI,CAAC;CAC1D;AAYD,kEAAkE;AAClE,qBAAa,sBAAuB,SAAQ,SAAU,YAAW,SAAS;IACzE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoD;IAC3E,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAY;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;IACtD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAChE,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;IAEzB,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;gBAEW,OAAO,EAAE,oBAAoB;IAkDzC,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,OAAO;IASf,IAAI,aAAa,IAAI,WAAW,CAE/B;IAED,aAAa,IAAI,IAAI;IAIrB,YAAY,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI;IAMjD,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,GAAE,OAAO,GAAG,SAAS,GAAG,OAAiB,GAAG,IAAI;IAMlG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAc/B,OAAO,IAAI,IAAI;CAKf"}
@@ -0,0 +1,154 @@
1
+ import { clampThinkingLevel, getSupportedThinkingLevels } from "@earendil-works/pi-ai/compat";
2
+ import { Container, Spacer, Text } from "@earendil-works/pi-tui";
3
+ import { DynamicBorder } from "../../../modes/interactive/components/dynamic-border.js";
4
+ import { keyLabel } from "../../../modes/interactive/components/keybinding-hints.js";
5
+ import { THINKING_LEVELS } from "../constants.js";
6
+ import { displayAgentDescription, displayAgentName } from "../display-name.js";
7
+ import { ProfileModelListComponent } from "./model-list.js";
8
+ function hint(theme, keybindings, binding, description) {
9
+ const key = keyLabel(binding, { keybindings });
10
+ return key ? `${theme.fg("dim", key)}${theme.fg("muted", ` ${description}`)}` : "";
11
+ }
12
+ /** Unified model and thinking editor for one Subagent profile. */
13
+ export class ProfileEditorComponent extends Container {
14
+ get focused() {
15
+ return this._focused;
16
+ }
17
+ set focused(value) {
18
+ this._focused = value;
19
+ this.modelList.focused = value;
20
+ }
21
+ constructor(options) {
22
+ super();
23
+ this.refreshAbortController = new AbortController();
24
+ this.availableThinking = [];
25
+ this.closed = false;
26
+ this._focused = false;
27
+ this.tui = options.tui;
28
+ this.theme = options.theme;
29
+ this.keybindings = options.keybindings;
30
+ this.currentThinking = options.currentThinking;
31
+ this.onDone = options.onDone;
32
+ this.candidateThinking = options.override?.thinking;
33
+ this.addChild(new DynamicBorder());
34
+ this.addChild(new Spacer(1));
35
+ this.addChild(new Text(this.theme.fg("accent", this.theme.bold(displayAgentName(options.agent.name))), 1, 0));
36
+ this.addChild(new Text(this.theme.fg("muted", displayAgentDescription(options.agent)), 1, 0));
37
+ this.addChild(new Spacer(1));
38
+ this.thinkingContainer = new Container();
39
+ this.addChild(this.thinkingContainer);
40
+ this.addChild(new Spacer(1));
41
+ this.addChild(new Text(this.theme.fg("text", this.theme.bold("Model")), 1, 0));
42
+ this.modelList = new ProfileModelListComponent({
43
+ theme: options.theme,
44
+ keybindings: options.keybindings,
45
+ models: options.models,
46
+ scopedModels: options.scopedModels,
47
+ currentSessionModel: options.currentSessionModel,
48
+ savedModelId: options.override?.model,
49
+ onSelectionChange: (choice) => this.handleModelSelection(choice),
50
+ });
51
+ this.addChild(this.modelList);
52
+ this.addChild(new Spacer(1));
53
+ const navigationKeys = [
54
+ keyLabel("tui.select.up", { keybindings: options.keybindings }),
55
+ keyLabel("tui.select.down", { keybindings: options.keybindings }),
56
+ ]
57
+ .filter(Boolean)
58
+ .join("/");
59
+ const hints = [
60
+ navigationKeys ? `${this.theme.fg("dim", navigationKeys)}${this.theme.fg("muted", " navigate")}` : "",
61
+ options.scopedModels.length > 0 ? hint(this.theme, options.keybindings, "tui.input.tab", "scope") : "",
62
+ hint(this.theme, options.keybindings, "app.thinking.cycle", "thinking"),
63
+ hint(this.theme, options.keybindings, "tui.select.confirm", "apply"),
64
+ hint(this.theme, options.keybindings, "tui.select.cancel", "back"),
65
+ ].filter(Boolean);
66
+ this.addChild(new Text(hints.join(this.theme.fg("muted", " • ")), 1, 0));
67
+ this.addChild(new Spacer(1));
68
+ this.addChild(new DynamicBorder());
69
+ }
70
+ handleModelSelection(choice) {
71
+ this.candidateModel = choice;
72
+ const model = choice?.model;
73
+ this.availableThinking = model ? getSupportedThinkingLevels(model) : [...THINKING_LEVELS];
74
+ if (this.candidateThinking !== undefined && model && !this.availableThinking.includes(this.candidateThinking)) {
75
+ this.candidateThinking = clampThinkingLevel(model, this.candidateThinking);
76
+ }
77
+ this.updateThinkingView();
78
+ }
79
+ inheritedThinking() {
80
+ return this.candidateModel?.model
81
+ ? clampThinkingLevel(this.candidateModel.model, this.currentThinking)
82
+ : this.currentThinking;
83
+ }
84
+ updateThinkingView() {
85
+ this.thinkingContainer.clear();
86
+ const choices = [undefined, ...this.availableThinking];
87
+ const rendered = choices.map((choice) => {
88
+ const label = choice === undefined ? `inherit (${this.inheritedThinking()})` : choice;
89
+ const selected = choice === this.candidateThinking;
90
+ return selected
91
+ ? `${this.theme.fg("accent", label)}${this.theme.fg("success", " ✓")}`
92
+ : this.theme.fg("muted", label);
93
+ });
94
+ this.thinkingContainer.addChild(new Text(`${this.theme.fg("text", this.theme.bold("Thinking"))} ${rendered.join(this.theme.fg("muted", " · "))}`, 1, 0));
95
+ }
96
+ cycleThinking() {
97
+ if (!this.candidateModel)
98
+ return;
99
+ const choices = [undefined, ...this.availableThinking];
100
+ const currentIndex = choices.indexOf(this.candidateThinking);
101
+ this.candidateThinking = choices[(currentIndex + 1 + choices.length) % choices.length];
102
+ this.updateThinkingView();
103
+ }
104
+ confirm() {
105
+ if (!this.candidateModel)
106
+ return;
107
+ this.dispose();
108
+ this.onDone({
109
+ model: this.candidateModel.modelId,
110
+ thinking: this.candidateThinking,
111
+ });
112
+ }
113
+ get refreshSignal() {
114
+ return this.refreshAbortController.signal;
115
+ }
116
+ cancelRefresh() {
117
+ this.refreshAbortController.abort();
118
+ }
119
+ updateModels(models) {
120
+ if (this.closed)
121
+ return;
122
+ this.modelList.updateModels(models);
123
+ this.tui.requestRender();
124
+ }
125
+ setRefreshStatus(message, tone = "muted") {
126
+ if (this.closed)
127
+ return;
128
+ this.modelList.setStatus(message, tone);
129
+ this.tui.requestRender();
130
+ }
131
+ handleInput(data) {
132
+ if (this.keybindings.matches(data, "app.thinking.cycle")) {
133
+ this.cycleThinking();
134
+ }
135
+ else if (this.keybindings.matches(data, "tui.select.confirm")) {
136
+ this.confirm();
137
+ }
138
+ else if (this.keybindings.matches(data, "tui.select.cancel")) {
139
+ this.dispose();
140
+ this.onDone(undefined);
141
+ }
142
+ else {
143
+ this.modelList.handleInput(data);
144
+ }
145
+ this.tui.requestRender();
146
+ }
147
+ dispose() {
148
+ if (this.closed)
149
+ return;
150
+ this.closed = true;
151
+ this.refreshAbortController.abort();
152
+ }
153
+ }
154
+ //# sourceMappingURL=profile-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-editor.js","sourceRoot":"","sources":["../../../../src/extensions/subagent/ui/profile-editor.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 { Container, type Focusable, type KeybindingsManager, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\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 { THINKING_LEVELS } from \"../constants.ts\";\nimport { displayAgentDescription, displayAgentName } from \"../display-name.ts\";\nimport type { AgentDefinition, SubagentProfileOverride } from \"../types.ts\";\nimport { type ProfileModelChoice, ProfileModelListComponent } from \"./model-list.ts\";\n\nexport interface ProfileEditorResult {\n\tmodel: string | undefined;\n\tthinking: ThinkingLevel | undefined;\n}\n\nexport interface ProfileEditorOptions {\n\ttui: TUI;\n\ttheme: Theme;\n\tkeybindings: KeybindingsManager;\n\tagent: AgentDefinition;\n\toverride: SubagentProfileOverride | undefined;\n\tmodels: readonly Model<Api>[];\n\tscopedModels: readonly { model: Model<Api> }[];\n\tcurrentSessionModel: Model<Api> | undefined;\n\tcurrentThinking: ThinkingLevel;\n\tonDone: (result: ProfileEditorResult | undefined) => void;\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\n/** Unified model and thinking editor for one Subagent profile. */\nexport class ProfileEditorComponent extends Container implements Focusable {\n\tprivate readonly tui: TUI;\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly currentThinking: ThinkingLevel;\n\tprivate readonly onDone: (result: ProfileEditorResult | undefined) => void;\n\tprivate readonly thinkingContainer: Container;\n\tprivate readonly modelList: ProfileModelListComponent;\n\tprivate readonly refreshAbortController = new AbortController();\n\tprivate candidateModel: ProfileModelChoice | undefined;\n\tprivate candidateThinking: ThinkingLevel | undefined;\n\tprivate availableThinking: ThinkingLevel[] = [];\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: ProfileEditorOptions) {\n\t\tsuper();\n\t\tthis.tui = options.tui;\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.currentThinking = options.currentThinking;\n\t\tthis.onDone = options.onDone;\n\t\tthis.candidateThinking = options.override?.thinking;\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(this.theme.fg(\"accent\", this.theme.bold(displayAgentName(options.agent.name))), 1, 0));\n\t\tthis.addChild(new Text(this.theme.fg(\"muted\", displayAgentDescription(options.agent)), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.thinkingContainer = new Container();\n\t\tthis.addChild(this.thinkingContainer);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(this.theme.fg(\"text\", this.theme.bold(\"Model\")), 1, 0));\n\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.override?.model,\n\t\t\tonSelectionChange: (choice) => this.handleModelSelection(choice),\n\t\t});\n\t\tthis.addChild(this.modelList);\n\t\tthis.addChild(new Spacer(1));\n\n\t\tconst navigationKeys = [\n\t\t\tkeyLabel(\"tui.select.up\", { keybindings: options.keybindings }),\n\t\t\tkeyLabel(\"tui.select.down\", { keybindings: options.keybindings }),\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\"/\");\n\t\tconst hints = [\n\t\t\tnavigationKeys ? `${this.theme.fg(\"dim\", navigationKeys)}${this.theme.fg(\"muted\", \" navigate\")}` : \"\",\n\t\t\toptions.scopedModels.length > 0 ? hint(this.theme, options.keybindings, \"tui.input.tab\", \"scope\") : \"\",\n\t\t\thint(this.theme, options.keybindings, \"app.thinking.cycle\", \"thinking\"),\n\t\t\thint(this.theme, options.keybindings, \"tui.select.confirm\", \"apply\"),\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\tprivate handleModelSelection(choice: ProfileModelChoice | undefined): void {\n\t\tthis.candidateModel = choice;\n\t\tconst model = choice?.model;\n\t\tthis.availableThinking = model ? (getSupportedThinkingLevels(model) as ThinkingLevel[]) : [...THINKING_LEVELS];\n\t\tif (this.candidateThinking !== undefined && model && !this.availableThinking.includes(this.candidateThinking)) {\n\t\t\tthis.candidateThinking = clampThinkingLevel(model, this.candidateThinking) as ThinkingLevel;\n\t\t}\n\t\tthis.updateThinkingView();\n\t}\n\n\tprivate inheritedThinking(): ThinkingLevel {\n\t\treturn this.candidateModel?.model\n\t\t\t? (clampThinkingLevel(this.candidateModel.model, this.currentThinking) as ThinkingLevel)\n\t\t\t: this.currentThinking;\n\t}\n\n\tprivate updateThinkingView(): void {\n\t\tthis.thinkingContainer.clear();\n\t\tconst choices: Array<ThinkingLevel | undefined> = [undefined, ...this.availableThinking];\n\t\tconst rendered = choices.map((choice) => {\n\t\t\tconst label = choice === undefined ? `inherit (${this.inheritedThinking()})` : choice;\n\t\t\tconst selected = choice === this.candidateThinking;\n\t\t\treturn selected\n\t\t\t\t? `${this.theme.fg(\"accent\", label)}${this.theme.fg(\"success\", \" ✓\")}`\n\t\t\t\t: this.theme.fg(\"muted\", label);\n\t\t});\n\t\tthis.thinkingContainer.addChild(\n\t\t\tnew Text(\n\t\t\t\t`${this.theme.fg(\"text\", this.theme.bold(\"Thinking\"))} ${rendered.join(this.theme.fg(\"muted\", \" · \"))}`,\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate cycleThinking(): void {\n\t\tif (!this.candidateModel) return;\n\t\tconst choices: Array<ThinkingLevel | undefined> = [undefined, ...this.availableThinking];\n\t\tconst currentIndex = choices.indexOf(this.candidateThinking);\n\t\tthis.candidateThinking = choices[(currentIndex + 1 + choices.length) % choices.length];\n\t\tthis.updateThinkingView();\n\t}\n\n\tprivate confirm(): void {\n\t\tif (!this.candidateModel) return;\n\t\tthis.dispose();\n\t\tthis.onDone({\n\t\t\tmodel: this.candidateModel.modelId,\n\t\t\tthinking: this.candidateThinking,\n\t\t});\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\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\tif (this.keybindings.matches(data, \"app.thinking.cycle\")) {\n\t\t\tthis.cycleThinking();\n\t\t} else if (this.keybindings.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.confirm();\n\t\t} else if (this.keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.dispose();\n\t\t\tthis.onDone(undefined);\n\t\t} else {\n\t\t\tthis.modelList.handleInput(data);\n\t\t}\n\t\tthis.tui.requestRender();\n\t}\n\n\tdispose(): void {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\t\tthis.refreshAbortController.abort();\n\t}\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { Container, type Focusable, type KeybindingsManager } from "@earendil-works/pi-tui";
2
+ import type { Theme } from "../../../modes/interactive/theme/theme.ts";
3
+ import type { AgentDefinition, AgentDiagnostic } from "../types.ts";
4
+ export type ProfilePickerResult = {
5
+ kind: "profile";
6
+ name: string;
7
+ } | {
8
+ kind: "diagnostics";
9
+ } | undefined;
10
+ /** Searchable, alphabetized profile selector used by /agents. */
11
+ export declare class ProfilePickerComponent extends Container implements Focusable {
12
+ private readonly theme;
13
+ private readonly keybindings;
14
+ private readonly profiles;
15
+ private readonly diagnostics;
16
+ private readonly onDone;
17
+ private readonly searchInput;
18
+ private readonly listContainer;
19
+ private readonly detailContainer;
20
+ private filteredItems;
21
+ private selectedIndex;
22
+ private _focused;
23
+ get focused(): boolean;
24
+ set focused(value: boolean);
25
+ constructor(theme: Theme, keybindings: KeybindingsManager, profiles: readonly AgentDefinition[], diagnostics: readonly AgentDiagnostic[], onDone: (result: ProfilePickerResult) => void, initialProfileName?: string);
26
+ private applyFilter;
27
+ private updateView;
28
+ private moveSelection;
29
+ private confirm;
30
+ handleInput(data: string): void;
31
+ }
32
+ //# sourceMappingURL=profile-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-picker.d.ts","sourceRoot":"","sources":["../../../../src/extensions/subagent/ui/profile-picker.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,SAAS,EACT,KAAK,SAAS,EAEd,KAAK,kBAAkB,EAIvB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AAEvE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgBpE,MAAM,MAAM,mBAAmB,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GAAG,SAAS,CAAC;AAkB1G,iEAAiE;AACjE,qBAAa,sBAAuB,SAAQ,SAAU,YAAW,SAAS;IACzE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAY;IAC1C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAY;IAC5C,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAS;IAEzB,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;gBAGA,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,kBAAkB,EAC/B,QAAQ,EAAE,SAAS,eAAe,EAAE,EACpC,WAAW,EAAE,SAAS,eAAe,EAAE,EACvC,MAAM,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,EAC7C,kBAAkB,CAAC,EAAE,MAAM;IA8C5B,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,UAAU;IA0DlB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,OAAO;IAQf,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAc/B"}