@astralyn/pi 0.84.4 → 0.84.5

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 (234) hide show
  1. package/CHANGELOG.md +30 -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 +7 -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/runner.d.ts.map +1 -1
  18. package/dist/core/extensions/runner.js +4 -0
  19. package/dist/core/extensions/runner.js.map +1 -1
  20. package/dist/core/extensions/types.d.ts +8 -1
  21. package/dist/core/extensions/types.d.ts.map +1 -1
  22. package/dist/core/extensions/types.js.map +1 -1
  23. package/dist/core/keybindings.d.ts +29 -0
  24. package/dist/core/keybindings.d.ts.map +1 -1
  25. package/dist/core/keybindings.js +4 -0
  26. package/dist/core/keybindings.js.map +1 -1
  27. package/dist/core/model-config.d.ts +5 -0
  28. package/dist/core/model-config.d.ts.map +1 -1
  29. package/dist/core/model-config.js +1 -0
  30. package/dist/core/model-config.js.map +1 -1
  31. package/dist/core/model-registry.d.ts +2 -0
  32. package/dist/core/model-registry.d.ts.map +1 -1
  33. package/dist/core/model-registry.js +4 -0
  34. package/dist/core/model-registry.js.map +1 -1
  35. package/dist/core/project-trust.js +2 -2
  36. package/dist/core/project-trust.js.map +1 -1
  37. package/dist/core/sdk.d.ts +5 -3
  38. package/dist/core/sdk.d.ts.map +1 -1
  39. package/dist/core/sdk.js +2 -1
  40. package/dist/core/sdk.js.map +1 -1
  41. package/dist/core/session-manager.js +2 -2
  42. package/dist/core/session-manager.js.map +1 -1
  43. package/dist/core/settings-manager.d.ts +6 -0
  44. package/dist/core/settings-manager.d.ts.map +1 -1
  45. package/dist/core/settings-manager.js +12 -0
  46. package/dist/core/settings-manager.js.map +1 -1
  47. package/dist/core/system-prompt.js +1 -1
  48. package/dist/core/system-prompt.js.map +1 -1
  49. package/dist/core/tools/bash.d.ts +2 -1
  50. package/dist/core/tools/bash.d.ts.map +1 -1
  51. package/dist/core/tools/bash.js +3 -1
  52. package/dist/core/tools/bash.js.map +1 -1
  53. package/dist/core/tools/edit.d.ts.map +1 -1
  54. package/dist/core/tools/edit.js +2 -0
  55. package/dist/core/tools/edit.js.map +1 -1
  56. package/dist/core/tools/find.js +1 -1
  57. package/dist/core/tools/find.js.map +1 -1
  58. package/dist/core/tools/grep.js +1 -1
  59. package/dist/core/tools/grep.js.map +1 -1
  60. package/dist/core/tools/read.d.ts.map +1 -1
  61. package/dist/core/tools/read.js +2 -0
  62. package/dist/core/tools/read.js.map +1 -1
  63. package/dist/core/tools/write.d.ts.map +1 -1
  64. package/dist/core/tools/write.js +2 -0
  65. package/dist/core/tools/write.js.map +1 -1
  66. package/dist/extensions/background/index.d.ts +74 -0
  67. package/dist/extensions/background/index.d.ts.map +1 -0
  68. package/dist/extensions/background/index.js +332 -0
  69. package/dist/extensions/background/index.js.map +1 -0
  70. package/dist/extensions/background/manager.d.ts +81 -0
  71. package/dist/extensions/background/manager.d.ts.map +1 -0
  72. package/dist/extensions/background/manager.js +320 -0
  73. package/dist/extensions/background/manager.js.map +1 -0
  74. package/dist/extensions/background/registry.d.ts +138 -0
  75. package/dist/extensions/background/registry.d.ts.map +1 -0
  76. package/dist/extensions/background/registry.js +358 -0
  77. package/dist/extensions/background/registry.js.map +1 -0
  78. package/dist/extensions/background/render.d.ts +26 -0
  79. package/dist/extensions/background/render.d.ts.map +1 -0
  80. package/dist/extensions/background/render.js +118 -0
  81. package/dist/extensions/background/render.js.map +1 -0
  82. package/dist/extensions/index.d.ts.map +1 -1
  83. package/dist/extensions/index.js +2 -0
  84. package/dist/extensions/index.js.map +1 -1
  85. package/dist/extensions/subagent/activity.d.ts +0 -1
  86. package/dist/extensions/subagent/activity.d.ts.map +1 -1
  87. package/dist/extensions/subagent/activity.js +2 -5
  88. package/dist/extensions/subagent/activity.js.map +1 -1
  89. package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
  90. package/dist/extensions/subagent/agents-command.js +308 -153
  91. package/dist/extensions/subagent/agents-command.js.map +1 -1
  92. package/dist/extensions/subagent/agents.d.ts +3 -6
  93. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  94. package/dist/extensions/subagent/agents.js +22 -192
  95. package/dist/extensions/subagent/agents.js.map +1 -1
  96. package/dist/extensions/subagent/constants.d.ts +4 -5
  97. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  98. package/dist/extensions/subagent/constants.js +11 -7
  99. package/dist/extensions/subagent/constants.js.map +1 -1
  100. package/dist/extensions/subagent/index.d.ts +0 -3
  101. package/dist/extensions/subagent/index.d.ts.map +1 -1
  102. package/dist/extensions/subagent/index.js +56 -188
  103. package/dist/extensions/subagent/index.js.map +1 -1
  104. package/dist/extensions/subagent/render.d.ts +1 -1
  105. package/dist/extensions/subagent/render.d.ts.map +1 -1
  106. package/dist/extensions/subagent/render.js +208 -576
  107. package/dist/extensions/subagent/render.js.map +1 -1
  108. package/dist/extensions/subagent/resolve.d.ts +2 -2
  109. package/dist/extensions/subagent/resolve.d.ts.map +1 -1
  110. package/dist/extensions/subagent/resolve.js +23 -15
  111. package/dist/extensions/subagent/resolve.js.map +1 -1
  112. package/dist/extensions/subagent/runner.d.ts +1 -2
  113. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  114. package/dist/extensions/subagent/runner.js +109 -131
  115. package/dist/extensions/subagent/runner.js.map +1 -1
  116. package/dist/extensions/subagent/schema.d.ts +4 -10
  117. package/dist/extensions/subagent/schema.d.ts.map +1 -1
  118. package/dist/extensions/subagent/schema.js +8 -13
  119. package/dist/extensions/subagent/schema.js.map +1 -1
  120. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  121. package/dist/extensions/subagent/sdk-runner.js +9 -20
  122. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  123. package/dist/extensions/subagent/settings.d.ts +2 -2
  124. package/dist/extensions/subagent/settings.d.ts.map +1 -1
  125. package/dist/extensions/subagent/settings.js +27 -14
  126. package/dist/extensions/subagent/settings.js.map +1 -1
  127. package/dist/extensions/subagent/text.d.ts +3 -0
  128. package/dist/extensions/subagent/text.d.ts.map +1 -0
  129. package/dist/extensions/subagent/text.js +16 -0
  130. package/dist/extensions/subagent/text.js.map +1 -0
  131. package/dist/extensions/subagent/types.d.ts +13 -35
  132. package/dist/extensions/subagent/types.d.ts.map +1 -1
  133. package/dist/extensions/subagent/types.js.map +1 -1
  134. package/dist/extensions/subagent/ui/model-list.d.ts +4 -3
  135. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
  136. package/dist/extensions/subagent/ui/model-list.js +10 -4
  137. package/dist/extensions/subagent/ui/model-list.js.map +1 -1
  138. package/dist/index.d.ts +1 -1
  139. package/dist/index.d.ts.map +1 -1
  140. package/dist/index.js.map +1 -1
  141. package/dist/main.d.ts.map +1 -1
  142. package/dist/main.js +5 -1
  143. package/dist/main.js.map +1 -1
  144. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  145. package/dist/modes/interactive/components/model-selector.js +2 -1
  146. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  147. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  148. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  149. package/dist/modes/interactive/components/settings-selector.js +10 -0
  150. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  151. package/dist/modes/interactive/interactive-mode.d.ts +8 -2
  152. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  153. package/dist/modes/interactive/interactive-mode.js +77 -25
  154. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  155. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  156. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  157. package/dist/modes/interactive/model-catalog-refresh.js +36 -0
  158. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  159. package/dist/modes/interactive/theme/dark.json +2 -0
  160. package/dist/modes/interactive/theme/light.json +2 -0
  161. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  162. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  163. package/dist/modes/interactive/theme/theme-controller.js +23 -10
  164. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  165. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  166. package/dist/modes/interactive/theme/theme.d.ts +5 -3
  167. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  168. package/dist/modes/interactive/theme/theme.js +12 -2
  169. package/dist/modes/interactive/theme/theme.js.map +1 -1
  170. package/dist/modes/json-event.d.ts +4 -1
  171. package/dist/modes/json-event.d.ts.map +1 -1
  172. package/dist/modes/json-event.js +5 -2
  173. package/dist/modes/json-event.js.map +1 -1
  174. package/dist/package-manager-cli.js +1 -1
  175. package/dist/package-manager-cli.js.map +1 -1
  176. package/dist/server/create-harness.d.ts.map +1 -1
  177. package/dist/server/create-harness.js +2 -0
  178. package/dist/server/create-harness.js.map +1 -1
  179. package/dist/utils/tools-manager.d.ts +10 -1
  180. package/dist/utils/tools-manager.d.ts.map +1 -1
  181. package/dist/utils/tools-manager.js +14 -19
  182. package/dist/utils/tools-manager.js.map +1 -1
  183. package/docs/bundled/README.md +1 -0
  184. package/docs/bundled/extensions/background.md +64 -0
  185. package/docs/bundled/extensions/subagent.md +83 -71
  186. package/docs/compaction.md +6 -6
  187. package/docs/custom-provider.md +1 -1
  188. package/docs/docs.json +4 -0
  189. package/docs/environment-variables.md +8 -2
  190. package/docs/extensions.md +6 -2
  191. package/docs/json.md +6 -4
  192. package/docs/keybindings.md +9 -2
  193. package/docs/rpc.md +15 -4
  194. package/docs/sdk.md +9 -0
  195. package/docs/settings.md +31 -0
  196. package/docs/terminal-setup.md +23 -2
  197. package/docs/themes.md +24 -3
  198. package/docs/tui.md +2 -2
  199. package/docs/usage.md +4 -3
  200. package/examples/README.md +1 -1
  201. package/examples/extensions/README.md +0 -1
  202. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  203. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  204. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  205. package/examples/extensions/gondolin/package-lock.json +2 -2
  206. package/examples/extensions/gondolin/package.json +1 -1
  207. package/examples/extensions/sandbox/package-lock.json +2 -2
  208. package/examples/extensions/sandbox/package.json +1 -1
  209. package/examples/extensions/with-deps/package-lock.json +2 -2
  210. package/examples/extensions/with-deps/package.json +1 -1
  211. package/npm-shrinkwrap.json +170 -221
  212. package/package.json +6 -6
  213. package/dist/extensions/subagent/display-name.d.ts +0 -6
  214. package/dist/extensions/subagent/display-name.d.ts.map +0 -1
  215. package/dist/extensions/subagent/display-name.js +0 -13
  216. package/dist/extensions/subagent/display-name.js.map +0 -1
  217. package/dist/extensions/subagent/ui/profile-editor.d.ts +0 -54
  218. package/dist/extensions/subagent/ui/profile-editor.d.ts.map +0 -1
  219. package/dist/extensions/subagent/ui/profile-editor.js +0 -154
  220. package/dist/extensions/subagent/ui/profile-editor.js.map +0 -1
  221. package/dist/extensions/subagent/ui/profile-picker.d.ts +0 -32
  222. package/dist/extensions/subagent/ui/profile-picker.d.ts.map +0 -1
  223. package/dist/extensions/subagent/ui/profile-picker.js +0 -149
  224. package/dist/extensions/subagent/ui/profile-picker.js.map +0 -1
  225. package/examples/extensions/subagent/README.md +0 -175
  226. package/examples/extensions/subagent/agents/planner.md +0 -37
  227. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  228. package/examples/extensions/subagent/agents/scout.md +0 -50
  229. package/examples/extensions/subagent/agents/worker.md +0 -24
  230. package/examples/extensions/subagent/agents.ts +0 -126
  231. package/examples/extensions/subagent/index.ts +0 -1009
  232. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  233. package/examples/extensions/subagent/prompts/implement.md +0 -10
  234. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astralyn/pi",
3
- "version": "0.84.4",
3
+ "version": "0.84.5",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -52,11 +52,11 @@
52
52
  "prepublishOnly": "npm run clean && npm run build"
53
53
  },
54
54
  "dependencies": {
55
- "@earendil-works/pi-agent-core": "0.84.1",
56
- "@earendil-works/pi-ai": "0.84.1",
57
- "@earendil-works/pi-client": "0.84.1",
58
- "@earendil-works/pi-protocol": "0.84.1",
59
- "@earendil-works/pi-tui": "0.84.1",
55
+ "@earendil-works/pi-agent-core": "0.84.2",
56
+ "@earendil-works/pi-ai": "0.84.2",
57
+ "@earendil-works/pi-client": "0.84.2",
58
+ "@earendil-works/pi-protocol": "0.84.2",
59
+ "@earendil-works/pi-tui": "0.84.2",
60
60
  "@silvia-odwyer/photon-node": "0.3.4",
61
61
  "chalk": "5.6.2",
62
62
  "cross-spawn": "7.0.6",
@@ -1,6 +0,0 @@
1
- import type { AgentDefinition } from "./types.ts";
2
- /** Convert a lowercase profile identifier into its display-only title. */
3
- export declare function displayAgentName(name: string): string;
4
- /** Keep model-facing usage guidance separate from concise built-in UI copy. */
5
- export declare function displayAgentDescription(agent: AgentDefinition): string;
6
- //# sourceMappingURL=display-name.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"display-name.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/display-name.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrD;AAED,+EAA+E;AAC/E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAEtE"}
@@ -1,13 +0,0 @@
1
- /** Convert a lowercase profile identifier into its display-only title. */
2
- export function displayAgentName(name) {
3
- return name
4
- .split(/[-_]/u)
5
- .filter(Boolean)
6
- .map((word) => `${word[0]?.toUpperCase() ?? ""}${word.slice(1)}`)
7
- .join(" ");
8
- }
9
- /** Keep model-facing usage guidance separate from concise built-in UI copy. */
10
- export function displayAgentDescription(agent) {
11
- return agent.uiDescription ?? agent.description;
12
- }
13
- //# sourceMappingURL=display-name.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"display-name.js","sourceRoot":"","sources":["../../../src/extensions/subagent/display-name.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC5C,OAAO,IAAI;SACT,KAAK,CAAC,OAAO,CAAC;SACd,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;SAChE,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,uBAAuB,CAAC,KAAsB;IAC7D,OAAO,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,WAAW,CAAC;AACjD,CAAC","sourcesContent":["import type { AgentDefinition } from \"./types.ts\";\n\n/** Convert a lowercase profile identifier into its display-only title. */\nexport function displayAgentName(name: string): string {\n\treturn name\n\t\t.split(/[-_]/u)\n\t\t.filter(Boolean)\n\t\t.map((word) => `${word[0]?.toUpperCase() ?? \"\"}${word.slice(1)}`)\n\t\t.join(\" \");\n}\n\n/** Keep model-facing usage guidance separate from concise built-in UI copy. */\nexport function displayAgentDescription(agent: AgentDefinition): string {\n\treturn agent.uiDescription ?? agent.description;\n}\n"]}
@@ -1,54 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,154 +0,0 @@
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
@@ -1 +0,0 @@
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"]}
@@ -1,32 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,149 +0,0 @@
1
- import { Container, Input, Spacer, Text, TruncatedText, } from "@earendil-works/pi-tui";
2
- import { DynamicBorder } from "../../../modes/interactive/components/dynamic-border.js";
3
- import { keyLabel } from "../../../modes/interactive/components/keybinding-hints.js";
4
- import { displayAgentDescription, displayAgentName } from "../display-name.js";
5
- const MAX_VISIBLE_PROFILES = 10;
6
- function compareProfileNames(left, right) {
7
- if (left.name < right.name)
8
- return -1;
9
- if (left.name > right.name)
10
- return 1;
11
- return 0;
12
- }
13
- function hint(theme, keybindings, binding, description) {
14
- const key = keyLabel(binding, { keybindings });
15
- return key ? `${theme.fg("dim", key)}${theme.fg("muted", ` ${description}`)}` : "";
16
- }
17
- /** Searchable, alphabetized profile selector used by /agents. */
18
- export class ProfilePickerComponent extends Container {
19
- get focused() {
20
- return this._focused;
21
- }
22
- set focused(value) {
23
- this._focused = value;
24
- this.searchInput.focused = value;
25
- }
26
- constructor(theme, keybindings, profiles, diagnostics, onDone, initialProfileName) {
27
- super();
28
- this.filteredItems = [];
29
- this.selectedIndex = 0;
30
- this._focused = false;
31
- this.theme = theme;
32
- this.keybindings = keybindings;
33
- this.profiles = [...profiles].sort(compareProfileNames);
34
- this.diagnostics = diagnostics;
35
- this.onDone = onDone;
36
- this.addChild(new DynamicBorder());
37
- this.addChild(new Spacer(1));
38
- this.addChild(new Text(theme.fg("accent", theme.bold("Agents")), 1, 0));
39
- this.addChild(new Spacer(1));
40
- this.searchInput = new Input();
41
- this.addChild(this.searchInput);
42
- this.addChild(new Spacer(1));
43
- this.listContainer = new Container();
44
- this.addChild(this.listContainer);
45
- this.detailContainer = new Container();
46
- this.addChild(this.detailContainer);
47
- this.addChild(new Spacer(1));
48
- const navigationKeys = [keyLabel("tui.select.up", { keybindings }), keyLabel("tui.select.down", { keybindings })]
49
- .filter(Boolean)
50
- .join("/");
51
- const hints = [
52
- navigationKeys ? `${theme.fg("dim", navigationKeys)}${theme.fg("muted", " navigate")}` : "",
53
- hint(theme, keybindings, "tui.select.confirm", "configure"),
54
- hint(theme, keybindings, "tui.select.cancel", "close"),
55
- ].filter(Boolean);
56
- this.addChild(new Text(hints.join(theme.fg("muted", " • ")), 1, 0));
57
- this.addChild(new Spacer(1));
58
- this.addChild(new DynamicBorder());
59
- this.applyFilter("");
60
- if (initialProfileName) {
61
- const initialIndex = this.filteredItems.findIndex((item) => item.kind === "profile" && item.agent.name === initialProfileName);
62
- if (initialIndex >= 0)
63
- this.selectedIndex = initialIndex;
64
- }
65
- this.updateView();
66
- }
67
- applyFilter(query) {
68
- const normalizedQuery = query.trim().toLowerCase();
69
- const profiles = normalizedQuery
70
- ? this.profiles.filter((agent) => `${agent.name} ${displayAgentName(agent.name)} ${displayAgentDescription(agent)}`
71
- .toLowerCase()
72
- .includes(normalizedQuery))
73
- : this.profiles;
74
- this.filteredItems = profiles.map((agent) => ({ kind: "profile", agent }));
75
- if (!normalizedQuery && this.diagnostics.length > 0) {
76
- this.filteredItems.push({ kind: "diagnostics", count: this.diagnostics.length });
77
- }
78
- this.selectedIndex = normalizedQuery
79
- ? 0
80
- : Math.min(this.selectedIndex, Math.max(0, this.filteredItems.length - 1));
81
- this.updateView();
82
- }
83
- updateView() {
84
- this.listContainer.clear();
85
- this.detailContainer.clear();
86
- const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(MAX_VISIBLE_PROFILES / 2), this.filteredItems.length - MAX_VISIBLE_PROFILES));
87
- const endIndex = Math.min(startIndex + MAX_VISIBLE_PROFILES, this.filteredItems.length);
88
- for (let index = startIndex; index < endIndex; index++) {
89
- const item = this.filteredItems[index];
90
- if (!item)
91
- continue;
92
- const selected = index === this.selectedIndex;
93
- const label = item.kind === "profile"
94
- ? displayAgentName(item.agent.name)
95
- : `View ${item.count} agent file issue${item.count === 1 ? "" : "s"}`;
96
- const prefix = selected ? this.theme.fg("accent", "→ ") : " ";
97
- const text = selected ? this.theme.fg("accent", label) : this.theme.fg("text", label);
98
- this.listContainer.addChild(new TruncatedText(`${prefix}${text}`, 1, 0));
99
- }
100
- if (startIndex > 0 || endIndex < this.filteredItems.length) {
101
- this.listContainer.addChild(new TruncatedText(this.theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredItems.length})`), 1, 0));
102
- }
103
- if (this.filteredItems.length === 0) {
104
- this.listContainer.addChild(new Text(this.theme.fg("muted", " No matching profiles"), 1, 0));
105
- return;
106
- }
107
- const selected = this.filteredItems[this.selectedIndex];
108
- if (!selected)
109
- return;
110
- this.detailContainer.addChild(new Spacer(1));
111
- if (selected.kind === "profile") {
112
- this.detailContainer.addChild(new Text(this.theme.fg("muted", displayAgentDescription(selected.agent)), 1, 0));
113
- }
114
- else {
115
- this.detailContainer.addChild(new Text(this.theme.fg("warning", `${selected.count} profile file${selected.count === 1 ? "" : "s"} could not be loaded.`), 1, 0));
116
- }
117
- }
118
- moveSelection(offset) {
119
- if (this.filteredItems.length === 0)
120
- return;
121
- this.selectedIndex = (this.selectedIndex + offset + this.filteredItems.length) % this.filteredItems.length;
122
- this.updateView();
123
- }
124
- confirm() {
125
- const selected = this.filteredItems[this.selectedIndex];
126
- if (!selected)
127
- return;
128
- this.onDone(selected.kind === "profile" ? { kind: "profile", name: selected.agent.name } : { kind: "diagnostics" });
129
- }
130
- handleInput(data) {
131
- if (this.keybindings.matches(data, "tui.select.up")) {
132
- this.moveSelection(-1);
133
- }
134
- else if (this.keybindings.matches(data, "tui.select.down")) {
135
- this.moveSelection(1);
136
- }
137
- else if (this.keybindings.matches(data, "tui.select.confirm")) {
138
- this.confirm();
139
- }
140
- else if (this.keybindings.matches(data, "tui.select.cancel")) {
141
- this.onDone(undefined);
142
- }
143
- else {
144
- this.searchInput.handleInput(data);
145
- this.applyFilter(this.searchInput.getValue());
146
- }
147
- }
148
- }
149
- //# sourceMappingURL=profile-picker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"profile-picker.js","sourceRoot":"","sources":["../../../../src/extensions/subagent/ui/profile-picker.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tContainer,\n\ttype Focusable,\n\tInput,\n\ttype KeybindingsManager,\n\tSpacer,\n\tText,\n\tTruncatedText,\n} 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 { displayAgentDescription, displayAgentName } from \"../display-name.ts\";\nimport type { AgentDefinition, AgentDiagnostic } from \"../types.ts\";\n\nconst MAX_VISIBLE_PROFILES = 10;\n\ninterface ProfileItem {\n\tkind: \"profile\";\n\tagent: AgentDefinition;\n}\n\ninterface DiagnosticItem {\n\tkind: \"diagnostics\";\n\tcount: number;\n}\n\ntype PickerItem = ProfileItem | DiagnosticItem;\n\nexport type ProfilePickerResult = { kind: \"profile\"; name: string } | { kind: \"diagnostics\" } | undefined;\n\nfunction compareProfileNames(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 hint(\n\ttheme: Theme,\n\tkeybindings: KeybindingsManager,\n\tbinding: \"tui.select.up\" | \"tui.select.down\" | \"tui.select.confirm\" | \"tui.select.cancel\",\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/** Searchable, alphabetized profile selector used by /agents. */\nexport class ProfilePickerComponent extends Container implements Focusable {\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly profiles: AgentDefinition[];\n\tprivate readonly diagnostics: readonly AgentDiagnostic[];\n\tprivate readonly onDone: (result: ProfilePickerResult) => void;\n\tprivate readonly searchInput: Input;\n\tprivate readonly listContainer: Container;\n\tprivate readonly detailContainer: Container;\n\tprivate filteredItems: PickerItem[] = [];\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\tthis.searchInput.focused = value;\n\t}\n\n\tconstructor(\n\t\ttheme: Theme,\n\t\tkeybindings: KeybindingsManager,\n\t\tprofiles: readonly AgentDefinition[],\n\t\tdiagnostics: readonly AgentDiagnostic[],\n\t\tonDone: (result: ProfilePickerResult) => void,\n\t\tinitialProfileName?: string,\n\t) {\n\t\tsuper();\n\t\tthis.theme = theme;\n\t\tthis.keybindings = keybindings;\n\t\tthis.profiles = [...profiles].sort(compareProfileNames);\n\t\tthis.diagnostics = diagnostics;\n\t\tthis.onDone = onDone;\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"accent\", theme.bold(\"Agents\")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.searchInput = new Input();\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\t\tthis.detailContainer = new Container();\n\t\tthis.addChild(this.detailContainer);\n\t\tthis.addChild(new Spacer(1));\n\n\t\tconst navigationKeys = [keyLabel(\"tui.select.up\", { keybindings }), keyLabel(\"tui.select.down\", { keybindings })]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\"/\");\n\t\tconst hints = [\n\t\t\tnavigationKeys ? `${theme.fg(\"dim\", navigationKeys)}${theme.fg(\"muted\", \" navigate\")}` : \"\",\n\t\t\thint(theme, keybindings, \"tui.select.confirm\", \"configure\"),\n\t\t\thint(theme, keybindings, \"tui.select.cancel\", \"close\"),\n\t\t].filter(Boolean);\n\t\tthis.addChild(new Text(hints.join(theme.fg(\"muted\", \" • \")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\tthis.applyFilter(\"\");\n\t\tif (initialProfileName) {\n\t\t\tconst initialIndex = this.filteredItems.findIndex(\n\t\t\t\t(item) => item.kind === \"profile\" && item.agent.name === initialProfileName,\n\t\t\t);\n\t\t\tif (initialIndex >= 0) this.selectedIndex = initialIndex;\n\t\t}\n\t\tthis.updateView();\n\t}\n\n\tprivate applyFilter(query: string): void {\n\t\tconst normalizedQuery = query.trim().toLowerCase();\n\t\tconst profiles = normalizedQuery\n\t\t\t? this.profiles.filter((agent) =>\n\t\t\t\t\t`${agent.name} ${displayAgentName(agent.name)} ${displayAgentDescription(agent)}`\n\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t.includes(normalizedQuery),\n\t\t\t\t)\n\t\t\t: this.profiles;\n\t\tthis.filteredItems = profiles.map((agent): ProfileItem => ({ kind: \"profile\", agent }));\n\t\tif (!normalizedQuery && this.diagnostics.length > 0) {\n\t\t\tthis.filteredItems.push({ kind: \"diagnostics\", count: this.diagnostics.length });\n\t\t}\n\t\tthis.selectedIndex = normalizedQuery\n\t\t\t? 0\n\t\t\t: Math.min(this.selectedIndex, Math.max(0, this.filteredItems.length - 1));\n\t\tthis.updateView();\n\t}\n\n\tprivate updateView(): void {\n\t\tthis.listContainer.clear();\n\t\tthis.detailContainer.clear();\n\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_PROFILES / 2),\n\t\t\t\tthis.filteredItems.length - MAX_VISIBLE_PROFILES,\n\t\t\t),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + MAX_VISIBLE_PROFILES, this.filteredItems.length);\n\t\tfor (let index = startIndex; index < endIndex; index++) {\n\t\t\tconst item = this.filteredItems[index];\n\t\t\tif (!item) continue;\n\t\t\tconst selected = index === this.selectedIndex;\n\t\t\tconst label =\n\t\t\t\titem.kind === \"profile\"\n\t\t\t\t\t? displayAgentName(item.agent.name)\n\t\t\t\t\t: `View ${item.count} agent file issue${item.count === 1 ? \"\" : \"s\"}`;\n\t\t\tconst prefix = selected ? this.theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst text = selected ? this.theme.fg(\"accent\", label) : this.theme.fg(\"text\", label);\n\t\t\tthis.listContainer.addChild(new TruncatedText(`${prefix}${text}`, 1, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredItems.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.filteredItems.length})`),\n\t\t\t\t\t1,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (this.filteredItems.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", \" No matching profiles\"), 1, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tconst selected = this.filteredItems[this.selectedIndex];\n\t\tif (!selected) return;\n\t\tthis.detailContainer.addChild(new Spacer(1));\n\t\tif (selected.kind === \"profile\") {\n\t\t\tthis.detailContainer.addChild(new Text(this.theme.fg(\"muted\", displayAgentDescription(selected.agent)), 1, 0));\n\t\t} else {\n\t\t\tthis.detailContainer.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\tthis.theme.fg(\n\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t\t`${selected.count} profile file${selected.count === 1 ? \"\" : \"s\"} could not be loaded.`,\n\t\t\t\t\t),\n\t\t\t\t\t1,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate moveSelection(offset: -1 | 1): void {\n\t\tif (this.filteredItems.length === 0) return;\n\t\tthis.selectedIndex = (this.selectedIndex + offset + this.filteredItems.length) % this.filteredItems.length;\n\t\tthis.updateView();\n\t}\n\n\tprivate confirm(): void {\n\t\tconst selected = this.filteredItems[this.selectedIndex];\n\t\tif (!selected) return;\n\t\tthis.onDone(\n\t\t\tselected.kind === \"profile\" ? { kind: \"profile\", name: selected.agent.name } : { kind: \"diagnostics\" },\n\t\t);\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.confirm();\n\t\t} else if (this.keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onDone(undefined);\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"]}