gsd-pi 2.38.0-dev.eeb3520 → 2.39.0-dev.38f11d1

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 (335) hide show
  1. package/README.md +15 -11
  2. package/dist/app-paths.js +1 -1
  3. package/dist/cli.js +9 -0
  4. package/dist/extension-discovery.d.ts +5 -3
  5. package/dist/extension-discovery.js +14 -9
  6. package/dist/extension-registry.js +2 -2
  7. package/dist/remote-questions-config.js +2 -2
  8. package/dist/resource-loader.js +34 -1
  9. package/dist/resources/extensions/async-jobs/index.js +10 -0
  10. package/dist/resources/extensions/browser-tools/index.js +3 -1
  11. package/dist/resources/extensions/browser-tools/package.json +3 -1
  12. package/dist/resources/extensions/browser-tools/tools/verify.js +97 -0
  13. package/dist/resources/extensions/cmux/index.js +55 -1
  14. package/dist/resources/extensions/context7/package.json +1 -1
  15. package/dist/resources/extensions/env-utils.js +29 -0
  16. package/dist/resources/extensions/get-secrets-from-user.js +5 -24
  17. package/dist/resources/extensions/github-sync/cli.js +284 -0
  18. package/dist/resources/extensions/github-sync/index.js +73 -0
  19. package/dist/resources/extensions/github-sync/mapping.js +67 -0
  20. package/dist/resources/extensions/github-sync/sync.js +424 -0
  21. package/dist/resources/extensions/github-sync/templates.js +118 -0
  22. package/dist/resources/extensions/github-sync/types.js +7 -0
  23. package/dist/resources/extensions/google-search/package.json +3 -1
  24. package/dist/resources/extensions/gsd/auto/session.js +6 -23
  25. package/dist/resources/extensions/gsd/auto-dashboard.js +7 -0
  26. package/dist/resources/extensions/gsd/auto-dispatch.js +8 -9
  27. package/dist/resources/extensions/gsd/auto-loop.js +923 -787
  28. package/dist/resources/extensions/gsd/auto-post-unit.js +107 -70
  29. package/dist/resources/extensions/gsd/auto-prompts.js +205 -51
  30. package/dist/resources/extensions/gsd/auto-start.js +19 -3
  31. package/dist/resources/extensions/gsd/auto-worktree-sync.js +13 -5
  32. package/dist/resources/extensions/gsd/auto-worktree.js +3 -3
  33. package/dist/resources/extensions/gsd/auto.js +147 -98
  34. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +126 -0
  35. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +233 -0
  36. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +59 -0
  37. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +38 -0
  38. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +156 -0
  39. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +46 -0
  40. package/dist/resources/extensions/gsd/bootstrap/system-context.js +300 -0
  41. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +38 -0
  42. package/dist/resources/extensions/gsd/captures.js +9 -1
  43. package/dist/resources/extensions/gsd/commands/catalog.js +278 -0
  44. package/dist/resources/extensions/gsd/commands/context.js +84 -0
  45. package/dist/resources/extensions/gsd/commands/dispatcher.js +21 -0
  46. package/dist/resources/extensions/gsd/commands/handlers/auto.js +72 -0
  47. package/dist/resources/extensions/gsd/commands/handlers/core.js +246 -0
  48. package/dist/resources/extensions/gsd/commands/handlers/ops.js +166 -0
  49. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +94 -0
  50. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +102 -0
  51. package/dist/resources/extensions/gsd/commands/index.js +11 -0
  52. package/dist/resources/extensions/gsd/commands-extensions.js +3 -2
  53. package/dist/resources/extensions/gsd/commands-handlers.js +17 -4
  54. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  55. package/dist/resources/extensions/gsd/commands.js +8 -1169
  56. package/dist/resources/extensions/gsd/context-budget.js +2 -10
  57. package/dist/resources/extensions/gsd/dashboard-overlay.js +9 -0
  58. package/dist/resources/extensions/gsd/detection.js +1 -2
  59. package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -2
  60. package/dist/resources/extensions/gsd/doctor-checks.js +82 -0
  61. package/dist/resources/extensions/gsd/doctor-environment.js +78 -0
  62. package/dist/resources/extensions/gsd/doctor-format.js +15 -0
  63. package/dist/resources/extensions/gsd/doctor-proactive.js +80 -10
  64. package/dist/resources/extensions/gsd/doctor-providers.js +30 -11
  65. package/dist/resources/extensions/gsd/doctor.js +234 -12
  66. package/dist/resources/extensions/gsd/exit-command.js +2 -1
  67. package/dist/resources/extensions/gsd/export-html.js +46 -0
  68. package/dist/resources/extensions/gsd/export.js +1 -1
  69. package/dist/resources/extensions/gsd/files.js +48 -9
  70. package/dist/resources/extensions/gsd/forensics.js +1 -1
  71. package/dist/resources/extensions/gsd/git-service.js +30 -12
  72. package/dist/resources/extensions/gsd/gitignore.js +16 -3
  73. package/dist/resources/extensions/gsd/guided-flow.js +149 -38
  74. package/dist/resources/extensions/gsd/health-widget-core.js +32 -70
  75. package/dist/resources/extensions/gsd/health-widget.js +4 -87
  76. package/dist/resources/extensions/gsd/index.js +4 -1111
  77. package/dist/resources/extensions/gsd/migrate/parsers.js +1 -1
  78. package/dist/resources/extensions/gsd/migrate-external.js +18 -1
  79. package/dist/resources/extensions/gsd/native-git-bridge.js +37 -0
  80. package/dist/resources/extensions/gsd/package.json +1 -1
  81. package/dist/resources/extensions/gsd/paths.js +3 -0
  82. package/dist/resources/extensions/gsd/preferences-models.js +0 -12
  83. package/dist/resources/extensions/gsd/preferences-types.js +1 -1
  84. package/dist/resources/extensions/gsd/preferences-validation.js +59 -11
  85. package/dist/resources/extensions/gsd/preferences.js +22 -11
  86. package/dist/resources/extensions/gsd/progress-score.js +20 -1
  87. package/dist/resources/extensions/gsd/prompt-loader.js +6 -2
  88. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  89. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  90. package/dist/resources/extensions/gsd/prompts/discuss.md +11 -14
  91. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -3
  92. package/dist/resources/extensions/gsd/prompts/forensics.md +121 -46
  93. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  94. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
  95. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
  96. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  97. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  98. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  99. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  100. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  101. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  102. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  103. package/dist/resources/extensions/gsd/prompts/queue.md +4 -8
  104. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
  105. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  106. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  107. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  108. package/dist/resources/extensions/gsd/prompts/run-uat.md +28 -11
  109. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -2
  110. package/dist/resources/extensions/gsd/repo-identity.js +21 -4
  111. package/dist/resources/extensions/gsd/resource-version.js +2 -1
  112. package/dist/resources/extensions/gsd/roadmap-mutations.js +24 -0
  113. package/dist/resources/extensions/gsd/state.js +42 -23
  114. package/dist/resources/extensions/gsd/templates/runtime.md +21 -0
  115. package/dist/resources/extensions/gsd/templates/task-plan.md +3 -0
  116. package/dist/resources/extensions/gsd/visualizer-data.js +27 -2
  117. package/dist/resources/extensions/gsd/visualizer-views.js +52 -0
  118. package/dist/resources/extensions/gsd/worktree.js +35 -16
  119. package/dist/resources/extensions/mcp-client/index.js +14 -1
  120. package/dist/resources/extensions/remote-questions/status.js +4 -1
  121. package/dist/resources/extensions/remote-questions/store.js +4 -1
  122. package/dist/resources/extensions/search-the-web/provider.js +2 -1
  123. package/dist/resources/extensions/shared/frontmatter.js +1 -1
  124. package/dist/resources/extensions/subagent/index.js +12 -3
  125. package/dist/resources/extensions/subagent/isolation.js +2 -1
  126. package/dist/resources/extensions/ttsr/rule-loader.js +2 -1
  127. package/dist/resources/extensions/universal-config/package.json +1 -1
  128. package/dist/welcome-screen.d.ts +12 -0
  129. package/dist/welcome-screen.js +53 -0
  130. package/package.json +1 -1
  131. package/packages/pi-ai/dist/utils/oauth/anthropic.js +2 -2
  132. package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +1 -1
  133. package/packages/pi-ai/src/utils/oauth/anthropic.ts +2 -2
  134. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  135. package/packages/pi-coding-agent/dist/core/extensions/loader.js +205 -7
  136. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  137. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  138. package/packages/pi-coding-agent/dist/core/package-manager.js +8 -4
  139. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  140. package/packages/pi-coding-agent/dist/core/skills.d.ts +1 -0
  141. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  142. package/packages/pi-coding-agent/dist/core/skills.js +6 -1
  143. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  144. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  145. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  146. package/packages/pi-coding-agent/dist/index.js +1 -1
  147. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  148. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts +17 -0
  149. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -0
  150. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +244 -0
  151. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -0
  152. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.d.ts +3 -0
  153. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.d.ts.map +1 -0
  154. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js +58 -0
  155. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -0
  156. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +12 -0
  157. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -0
  158. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +54 -0
  159. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -0
  160. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts +6 -0
  161. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -0
  162. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +63 -0
  163. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -0
  164. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +38 -0
  165. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -0
  166. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js +2 -0
  167. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -0
  168. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  169. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -453
  170. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  171. package/packages/pi-coding-agent/package.json +1 -1
  172. package/packages/pi-coding-agent/src/core/extensions/loader.ts +223 -7
  173. package/packages/pi-coding-agent/src/core/package-manager.ts +8 -4
  174. package/packages/pi-coding-agent/src/core/skills.ts +9 -1
  175. package/packages/pi-coding-agent/src/index.ts +1 -0
  176. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +302 -0
  177. package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +59 -0
  178. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +68 -0
  179. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +71 -0
  180. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +37 -0
  181. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +16 -506
  182. package/pkg/package.json +1 -1
  183. package/src/resources/extensions/async-jobs/index.ts +11 -0
  184. package/src/resources/extensions/browser-tools/index.ts +3 -0
  185. package/src/resources/extensions/browser-tools/tools/verify.ts +117 -0
  186. package/src/resources/extensions/cmux/index.ts +57 -1
  187. package/src/resources/extensions/env-utils.ts +31 -0
  188. package/src/resources/extensions/get-secrets-from-user.ts +5 -24
  189. package/src/resources/extensions/github-sync/cli.ts +364 -0
  190. package/src/resources/extensions/github-sync/index.ts +93 -0
  191. package/src/resources/extensions/github-sync/mapping.ts +81 -0
  192. package/src/resources/extensions/github-sync/sync.ts +556 -0
  193. package/src/resources/extensions/github-sync/templates.ts +183 -0
  194. package/src/resources/extensions/github-sync/tests/cli.test.ts +20 -0
  195. package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +39 -0
  196. package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
  197. package/src/resources/extensions/github-sync/tests/templates.test.ts +110 -0
  198. package/src/resources/extensions/github-sync/types.ts +47 -0
  199. package/src/resources/extensions/gsd/auto/session.ts +7 -25
  200. package/src/resources/extensions/gsd/auto-dashboard.ts +10 -0
  201. package/src/resources/extensions/gsd/auto-dispatch.ts +7 -9
  202. package/src/resources/extensions/gsd/auto-loop.ts +1285 -1138
  203. package/src/resources/extensions/gsd/auto-post-unit.ts +90 -46
  204. package/src/resources/extensions/gsd/auto-prompts.ts +250 -53
  205. package/src/resources/extensions/gsd/auto-start.ts +24 -3
  206. package/src/resources/extensions/gsd/auto-worktree-sync.ts +15 -4
  207. package/src/resources/extensions/gsd/auto-worktree.ts +3 -3
  208. package/src/resources/extensions/gsd/auto.ts +143 -102
  209. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +142 -0
  210. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +238 -0
  211. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +90 -0
  212. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +46 -0
  213. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +167 -0
  214. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +55 -0
  215. package/src/resources/extensions/gsd/bootstrap/system-context.ts +340 -0
  216. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +51 -0
  217. package/src/resources/extensions/gsd/captures.ts +10 -1
  218. package/src/resources/extensions/gsd/commands/catalog.ts +301 -0
  219. package/src/resources/extensions/gsd/commands/context.ts +101 -0
  220. package/src/resources/extensions/gsd/commands/dispatcher.ts +32 -0
  221. package/src/resources/extensions/gsd/commands/handlers/auto.ts +74 -0
  222. package/src/resources/extensions/gsd/commands/handlers/core.ts +274 -0
  223. package/src/resources/extensions/gsd/commands/handlers/ops.ts +169 -0
  224. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +118 -0
  225. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +109 -0
  226. package/src/resources/extensions/gsd/commands/index.ts +14 -0
  227. package/src/resources/extensions/gsd/commands-extensions.ts +4 -2
  228. package/src/resources/extensions/gsd/commands-handlers.ts +18 -3
  229. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  230. package/src/resources/extensions/gsd/commands.ts +10 -1307
  231. package/src/resources/extensions/gsd/context-budget.ts +2 -12
  232. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -0
  233. package/src/resources/extensions/gsd/detection.ts +2 -2
  234. package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -2
  235. package/src/resources/extensions/gsd/doctor-checks.ts +75 -0
  236. package/src/resources/extensions/gsd/doctor-environment.ts +82 -1
  237. package/src/resources/extensions/gsd/doctor-format.ts +20 -0
  238. package/src/resources/extensions/gsd/doctor-proactive.ts +106 -10
  239. package/src/resources/extensions/gsd/doctor-providers.ts +30 -9
  240. package/src/resources/extensions/gsd/doctor-types.ts +16 -1
  241. package/src/resources/extensions/gsd/doctor.ts +243 -14
  242. package/src/resources/extensions/gsd/exit-command.ts +2 -2
  243. package/src/resources/extensions/gsd/export-html.ts +51 -0
  244. package/src/resources/extensions/gsd/export.ts +1 -1
  245. package/src/resources/extensions/gsd/files.ts +51 -11
  246. package/src/resources/extensions/gsd/forensics.ts +1 -1
  247. package/src/resources/extensions/gsd/git-service.ts +44 -10
  248. package/src/resources/extensions/gsd/gitignore.ts +17 -3
  249. package/src/resources/extensions/gsd/guided-flow.ts +177 -44
  250. package/src/resources/extensions/gsd/health-widget-core.ts +28 -80
  251. package/src/resources/extensions/gsd/health-widget.ts +4 -89
  252. package/src/resources/extensions/gsd/index.ts +12 -1307
  253. package/src/resources/extensions/gsd/migrate/parsers.ts +1 -1
  254. package/src/resources/extensions/gsd/migrate-external.ts +18 -1
  255. package/src/resources/extensions/gsd/native-git-bridge.ts +37 -0
  256. package/src/resources/extensions/gsd/paths.ts +4 -0
  257. package/src/resources/extensions/gsd/preferences-models.ts +0 -12
  258. package/src/resources/extensions/gsd/preferences-types.ts +4 -4
  259. package/src/resources/extensions/gsd/preferences-validation.ts +51 -11
  260. package/src/resources/extensions/gsd/preferences.ts +25 -11
  261. package/src/resources/extensions/gsd/progress-score.ts +23 -0
  262. package/src/resources/extensions/gsd/prompt-loader.ts +7 -2
  263. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  264. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  265. package/src/resources/extensions/gsd/prompts/discuss.md +11 -14
  266. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -3
  267. package/src/resources/extensions/gsd/prompts/forensics.md +121 -46
  268. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  269. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
  270. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
  271. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  272. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  273. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  274. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  275. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  276. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  277. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  278. package/src/resources/extensions/gsd/prompts/queue.md +4 -8
  279. package/src/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
  280. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  281. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  282. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  283. package/src/resources/extensions/gsd/prompts/run-uat.md +28 -11
  284. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -2
  285. package/src/resources/extensions/gsd/repo-identity.ts +23 -4
  286. package/src/resources/extensions/gsd/resource-version.ts +3 -1
  287. package/src/resources/extensions/gsd/roadmap-mutations.ts +29 -0
  288. package/src/resources/extensions/gsd/state.ts +39 -21
  289. package/src/resources/extensions/gsd/templates/runtime.md +21 -0
  290. package/src/resources/extensions/gsd/templates/task-plan.md +3 -0
  291. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +21 -18
  292. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +135 -77
  293. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +4 -3
  294. package/src/resources/extensions/gsd/tests/cmux.test.ts +93 -0
  295. package/src/resources/extensions/gsd/tests/derive-state.test.ts +43 -0
  296. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +266 -0
  297. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +3 -3
  298. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +86 -3
  299. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +50 -0
  300. package/src/resources/extensions/gsd/tests/health-widget.test.ts +16 -54
  301. package/src/resources/extensions/gsd/tests/parsers.test.ts +131 -14
  302. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +209 -0
  303. package/src/resources/extensions/gsd/tests/preferences.test.ts +2 -7
  304. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +59 -0
  305. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -16
  306. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +21 -1
  307. package/src/resources/extensions/gsd/tests/run-uat.test.ts +16 -4
  308. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +140 -0
  309. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +10 -10
  310. package/src/resources/extensions/gsd/tests/worktree.test.ts +47 -0
  311. package/src/resources/extensions/gsd/types.ts +18 -1
  312. package/src/resources/extensions/gsd/verification-evidence.ts +16 -0
  313. package/src/resources/extensions/gsd/visualizer-data.ts +52 -2
  314. package/src/resources/extensions/gsd/visualizer-views.ts +58 -0
  315. package/src/resources/extensions/gsd/worktree.ts +35 -15
  316. package/src/resources/extensions/mcp-client/index.ts +17 -1
  317. package/src/resources/extensions/remote-questions/status.ts +5 -1
  318. package/src/resources/extensions/remote-questions/store.ts +5 -1
  319. package/src/resources/extensions/search-the-web/provider.ts +2 -1
  320. package/src/resources/extensions/shared/frontmatter.ts +1 -1
  321. package/src/resources/extensions/subagent/index.ts +12 -3
  322. package/src/resources/extensions/subagent/isolation.ts +3 -1
  323. package/src/resources/extensions/ttsr/rule-loader.ts +3 -1
  324. package/dist/resources/extensions/gsd/prompt-compressor.js +0 -393
  325. package/dist/resources/extensions/gsd/semantic-chunker.js +0 -254
  326. package/dist/resources/extensions/gsd/summary-distiller.js +0 -212
  327. package/src/resources/extensions/gsd/prompt-compressor.ts +0 -508
  328. package/src/resources/extensions/gsd/semantic-chunker.ts +0 -336
  329. package/src/resources/extensions/gsd/summary-distiller.ts +0 -258
  330. package/src/resources/extensions/gsd/tests/context-compression.test.ts +0 -193
  331. package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +0 -529
  332. package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +0 -426
  333. package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +0 -323
  334. package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +0 -1272
  335. package/src/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +0 -164
@@ -45,8 +45,12 @@ import { ToolExecutionComponent } from "./components/tool-execution.js";
45
45
  import { TreeSelectorComponent } from "./components/tree-selector.js";
46
46
  import { UserMessageComponent } from "./components/user-message.js";
47
47
  import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
48
- import { dispatchSlashCommand, getAppKeyDisplay } from "./slash-command-handlers.js";
49
- import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, initTheme, onThemeChange, setRegisteredThemes, setTheme, setThemeInstance, Theme, theme, } from "./theme/theme.js";
48
+ import { getAppKeyDisplay } from "./slash-command-handlers.js";
49
+ import { handleAgentEvent } from "./controllers/chat-controller.js";
50
+ import { createExtensionUIContext as buildExtensionUIContext } from "./controllers/extension-ui-controller.js";
51
+ import { setupEditorSubmitHandler as setupEditorSubmitHandlerController } from "./controllers/input-controller.js";
52
+ import { findExactModelMatch as findExactModelMatchController, getModelCandidates as getModelCandidatesController, handleModelCommand as handleModelCommandController, updateAvailableProviderCount as updateAvailableProviderCountController, } from "./controllers/model-controller.js";
53
+ import { getAvailableThemes, getEditorTheme, getMarkdownTheme, initTheme, onThemeChange, setRegisteredThemes, setTheme, theme, } from "./theme/theme.js";
50
54
  function isExpandable(obj) {
51
55
  return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
52
56
  }
@@ -1168,60 +1172,7 @@ export class InteractiveMode {
1168
1172
  * Create the ExtensionUIContext for extensions.
1169
1173
  */
1170
1174
  createExtensionUIContext() {
1171
- return {
1172
- select: (title, options, opts) => this.showExtensionSelector(title, options, opts),
1173
- confirm: (title, message, opts) => this.showExtensionConfirm(title, message, opts),
1174
- input: (title, placeholder, opts) => this.showExtensionInput(title, placeholder, opts),
1175
- notify: (message, type) => this.showExtensionNotify(message, type),
1176
- onTerminalInput: (handler) => this.addExtensionTerminalInputListener(handler),
1177
- setStatus: (key, text) => this.setExtensionStatus(key, text),
1178
- setWorkingMessage: (message) => {
1179
- if (this.loadingAnimation) {
1180
- if (message) {
1181
- this.loadingAnimation.setMessage(message);
1182
- }
1183
- else {
1184
- this.loadingAnimation.setMessage(`${this.defaultWorkingMessage} (${appKey(this.keybindings, "interrupt")} to interrupt)`);
1185
- }
1186
- }
1187
- else {
1188
- // Queue message for when loadingAnimation is created (handles agent_start race)
1189
- this.pendingWorkingMessage = message;
1190
- }
1191
- },
1192
- setWidget: (key, content, options) => this.setExtensionWidget(key, content, options),
1193
- setFooter: (factory) => this.setExtensionFooter(factory),
1194
- setHeader: (factory) => this.setExtensionHeader(factory),
1195
- setTitle: (title) => this.ui.terminal.setTitle(title),
1196
- custom: (factory, options) => this.showExtensionCustom(factory, options),
1197
- pasteToEditor: (text) => this.editor.handleInput(`\x1b[200~${text}\x1b[201~`),
1198
- setEditorText: (text) => this.editor.setText(text),
1199
- getEditorText: () => this.editor.getText(),
1200
- editor: (title, prefill) => this.showExtensionEditor(title, prefill),
1201
- setEditorComponent: (factory) => this.setCustomEditorComponent(factory),
1202
- get theme() {
1203
- return theme;
1204
- },
1205
- getAllThemes: () => getAvailableThemesWithPaths(),
1206
- getTheme: (name) => getThemeByName(name),
1207
- setTheme: (themeOrName) => {
1208
- if (themeOrName instanceof Theme) {
1209
- setThemeInstance(themeOrName);
1210
- this.ui.requestRender();
1211
- return { success: true };
1212
- }
1213
- const result = setTheme(themeOrName, true);
1214
- if (result.success) {
1215
- if (this.settingsManager.getTheme() !== themeOrName) {
1216
- this.settingsManager.setTheme(themeOrName);
1217
- }
1218
- this.ui.requestRender();
1219
- }
1220
- return result;
1221
- },
1222
- getToolsExpanded: () => this.toolOutputExpanded,
1223
- setToolsExpanded: (expanded) => this.setToolsExpanded(expanded),
1224
- };
1175
+ return buildExtensionUIContext(this);
1225
1176
  }
1226
1177
  /**
1227
1178
  * Show a selector for extensions.
@@ -1628,65 +1579,7 @@ export class InteractiveMode {
1628
1579
  };
1629
1580
  }
1630
1581
  setupEditorSubmitHandler() {
1631
- this.defaultEditor.onSubmit = async (text) => {
1632
- text = text.trim();
1633
- if (!text)
1634
- return;
1635
- // Handle slash commands
1636
- if (text.startsWith("/")) {
1637
- const handled = await dispatchSlashCommand(text, this.getSlashCommandContext());
1638
- if (handled) {
1639
- this.editor.setText("");
1640
- return;
1641
- }
1642
- }
1643
- // Handle bash command (! for normal, !! for excluded from context)
1644
- if (text.startsWith("!")) {
1645
- const isExcluded = text.startsWith("!!");
1646
- const command = isExcluded ? text.slice(2).trim() : text.slice(1).trim();
1647
- if (command) {
1648
- if (this.session.isBashRunning) {
1649
- this.showWarning("A bash command is already running. Press Esc to cancel it first.");
1650
- this.editor.setText(text);
1651
- return;
1652
- }
1653
- this.editor.addToHistory?.(text);
1654
- await this.handleBashCommand(command, isExcluded);
1655
- this.isBashMode = false;
1656
- this.updateEditorBorderColor();
1657
- return;
1658
- }
1659
- }
1660
- // Queue input during compaction (extension commands execute immediately)
1661
- if (this.session.isCompacting) {
1662
- if (this.isExtensionCommand(text)) {
1663
- this.editor.addToHistory?.(text);
1664
- this.editor.setText("");
1665
- await this.session.prompt(text);
1666
- }
1667
- else {
1668
- this.queueCompactionMessage(text, "steer");
1669
- }
1670
- return;
1671
- }
1672
- // If streaming, use prompt() with steer behavior
1673
- // This handles extension commands (execute immediately), prompt template expansion, and queueing
1674
- if (this.session.isStreaming) {
1675
- this.editor.addToHistory?.(text);
1676
- this.editor.setText("");
1677
- await this.session.prompt(text, { streamingBehavior: "steer" });
1678
- this.updatePendingMessagesDisplay();
1679
- this.ui.requestRender();
1680
- return;
1681
- }
1682
- // Normal message submission
1683
- // First, move any pending bash components to chat
1684
- this.flushPendingBashComponents();
1685
- if (this.onInputCallback) {
1686
- this.onInputCallback(text);
1687
- }
1688
- this.editor.addToHistory?.(text);
1689
- };
1582
+ setupEditorSubmitHandlerController(this);
1690
1583
  }
1691
1584
  subscribeToAgent() {
1692
1585
  this.unsubscribe = this.session.subscribe(async (event) => {
@@ -1694,290 +1587,7 @@ export class InteractiveMode {
1694
1587
  });
1695
1588
  }
1696
1589
  async handleEvent(event) {
1697
- if (!this.isInitialized) {
1698
- await this.init();
1699
- }
1700
- this.footer.invalidate();
1701
- switch (event.type) {
1702
- case "agent_start":
1703
- // Restore main escape handler if retry handler is still active
1704
- // (retry success event fires later, but we need main handler now)
1705
- if (this.retryEscapeHandler) {
1706
- this.defaultEditor.onEscape = this.retryEscapeHandler;
1707
- this.retryEscapeHandler = undefined;
1708
- }
1709
- if (this.retryLoader) {
1710
- this.retryLoader.stop();
1711
- this.retryLoader = undefined;
1712
- }
1713
- if (this.loadingAnimation) {
1714
- this.loadingAnimation.stop();
1715
- }
1716
- this.statusContainer.clear();
1717
- this.loadingAnimation = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), this.defaultWorkingMessage);
1718
- this.statusContainer.addChild(this.loadingAnimation);
1719
- // Apply any pending working message queued before loader existed
1720
- if (this.pendingWorkingMessage !== undefined) {
1721
- if (this.pendingWorkingMessage) {
1722
- this.loadingAnimation.setMessage(this.pendingWorkingMessage);
1723
- }
1724
- this.pendingWorkingMessage = undefined;
1725
- }
1726
- this.ui.requestRender();
1727
- break;
1728
- case "message_start":
1729
- if (event.message.role === "custom") {
1730
- this.addMessageToChat(event.message);
1731
- this.ui.requestRender();
1732
- }
1733
- else if (event.message.role === "user") {
1734
- this.addMessageToChat(event.message);
1735
- this.updatePendingMessagesDisplay();
1736
- this.ui.requestRender();
1737
- }
1738
- else if (event.message.role === "assistant") {
1739
- this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings());
1740
- this.streamingMessage = event.message;
1741
- this.chatContainer.addChild(this.streamingComponent);
1742
- this.streamingComponent.updateContent(this.streamingMessage);
1743
- this.ui.requestRender();
1744
- }
1745
- break;
1746
- case "message_update":
1747
- if (this.streamingComponent && event.message.role === "assistant") {
1748
- this.streamingMessage = event.message;
1749
- this.streamingComponent.updateContent(this.streamingMessage);
1750
- for (const content of this.streamingMessage.content) {
1751
- if (content.type === "toolCall") {
1752
- if (!this.pendingTools.has(content.id)) {
1753
- const component = new ToolExecutionComponent(content.name, content.arguments, {
1754
- showImages: this.settingsManager.getShowImages(),
1755
- }, this.getRegisteredToolDefinition(content.name), this.ui);
1756
- component.setExpanded(this.toolOutputExpanded);
1757
- this.chatContainer.addChild(component);
1758
- this.pendingTools.set(content.id, component);
1759
- }
1760
- else {
1761
- const component = this.pendingTools.get(content.id);
1762
- if (component) {
1763
- component.updateArgs(content.arguments);
1764
- }
1765
- }
1766
- }
1767
- else if (content.type === "serverToolUse") {
1768
- // Server-side tool (e.g., native web search) — show as pending tool execution
1769
- if (!this.pendingTools.has(content.id)) {
1770
- const component = new ToolExecutionComponent(content.name, content.input ?? {}, {
1771
- showImages: this.settingsManager.getShowImages(),
1772
- }, undefined, this.ui);
1773
- component.setExpanded(this.toolOutputExpanded);
1774
- this.chatContainer.addChild(component);
1775
- this.pendingTools.set(content.id, component);
1776
- }
1777
- }
1778
- else if (content.type === "webSearchResult") {
1779
- // Server-side tool result — resolve the pending server tool execution
1780
- const component = this.pendingTools.get(content.toolUseId);
1781
- if (component) {
1782
- const searchContent = content.content;
1783
- const isError = searchContent && typeof searchContent === "object" && "type" in searchContent && searchContent.type === "web_search_tool_result_error";
1784
- const resultText = this.formatWebSearchResult(searchContent);
1785
- component.updateResult({
1786
- content: [{ type: "text", text: resultText }],
1787
- isError: !!isError,
1788
- });
1789
- this.pendingTools.delete(content.toolUseId);
1790
- }
1791
- }
1792
- }
1793
- this.ui.requestRender();
1794
- }
1795
- break;
1796
- case "message_end":
1797
- if (event.message.role === "user")
1798
- break;
1799
- if (this.streamingComponent && event.message.role === "assistant") {
1800
- this.streamingMessage = event.message;
1801
- let errorMessage;
1802
- if (this.streamingMessage.stopReason === "aborted") {
1803
- const retryAttempt = this.session.retryAttempt;
1804
- errorMessage =
1805
- retryAttempt > 0
1806
- ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}`
1807
- : "Operation aborted";
1808
- this.streamingMessage.errorMessage = errorMessage;
1809
- }
1810
- this.streamingComponent.updateContent(this.streamingMessage);
1811
- if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
1812
- if (!errorMessage) {
1813
- errorMessage = this.streamingMessage.errorMessage || "Error";
1814
- }
1815
- for (const [, component] of this.pendingTools.entries()) {
1816
- component.updateResult({
1817
- content: [{ type: "text", text: errorMessage }],
1818
- isError: true,
1819
- });
1820
- }
1821
- this.pendingTools.clear();
1822
- }
1823
- else {
1824
- // Args are now complete - trigger diff computation for edit tools
1825
- for (const [, component] of this.pendingTools.entries()) {
1826
- component.setArgsComplete();
1827
- }
1828
- }
1829
- this.streamingComponent = undefined;
1830
- this.streamingMessage = undefined;
1831
- this.footer.invalidate();
1832
- }
1833
- this.ui.requestRender();
1834
- break;
1835
- case "tool_execution_start": {
1836
- if (!this.pendingTools.has(event.toolCallId)) {
1837
- const component = new ToolExecutionComponent(event.toolName, event.args, {
1838
- showImages: this.settingsManager.getShowImages(),
1839
- }, this.getRegisteredToolDefinition(event.toolName), this.ui);
1840
- component.setExpanded(this.toolOutputExpanded);
1841
- this.chatContainer.addChild(component);
1842
- this.pendingTools.set(event.toolCallId, component);
1843
- this.ui.requestRender();
1844
- }
1845
- break;
1846
- }
1847
- case "tool_execution_update": {
1848
- const component = this.pendingTools.get(event.toolCallId);
1849
- if (component) {
1850
- component.updateResult({ ...event.partialResult, isError: false }, true);
1851
- this.ui.requestRender();
1852
- }
1853
- break;
1854
- }
1855
- case "tool_execution_end": {
1856
- const component = this.pendingTools.get(event.toolCallId);
1857
- if (component) {
1858
- component.updateResult({ ...event.result, isError: event.isError });
1859
- this.pendingTools.delete(event.toolCallId);
1860
- this.ui.requestRender();
1861
- }
1862
- break;
1863
- }
1864
- case "agent_end":
1865
- if (this.loadingAnimation) {
1866
- this.loadingAnimation.stop();
1867
- this.loadingAnimation = undefined;
1868
- this.statusContainer.clear();
1869
- }
1870
- if (this.streamingComponent) {
1871
- this.chatContainer.removeChild(this.streamingComponent);
1872
- this.streamingComponent = undefined;
1873
- this.streamingMessage = undefined;
1874
- }
1875
- this.pendingTools.clear();
1876
- await this.checkShutdownRequested();
1877
- this.ui.requestRender();
1878
- break;
1879
- case "auto_compaction_start": {
1880
- // Keep editor active; submissions are queued during compaction.
1881
- // Set up escape to abort auto-compaction
1882
- this.autoCompactionEscapeHandler = this.defaultEditor.onEscape;
1883
- this.defaultEditor.onEscape = () => {
1884
- this.session.abortCompaction();
1885
- };
1886
- // Show compacting indicator with reason
1887
- this.statusContainer.clear();
1888
- const reasonText = event.reason === "overflow" ? "Context overflow detected, " : "";
1889
- this.autoCompactionLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), `${reasonText}Auto-compacting... (${appKey(this.keybindings, "interrupt")} to cancel)`);
1890
- this.statusContainer.addChild(this.autoCompactionLoader);
1891
- this.ui.requestRender();
1892
- break;
1893
- }
1894
- case "auto_compaction_end": {
1895
- // Restore escape handler
1896
- if (this.autoCompactionEscapeHandler) {
1897
- this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
1898
- this.autoCompactionEscapeHandler = undefined;
1899
- }
1900
- // Stop loader
1901
- if (this.autoCompactionLoader) {
1902
- this.autoCompactionLoader.stop();
1903
- this.autoCompactionLoader = undefined;
1904
- this.statusContainer.clear();
1905
- }
1906
- // Handle result
1907
- if (event.aborted) {
1908
- this.showStatus("Auto-compaction cancelled");
1909
- }
1910
- else if (event.result) {
1911
- // Rebuild chat to show compacted state
1912
- this.chatContainer.clear();
1913
- this.rebuildChatFromMessages();
1914
- // Add compaction component at bottom so user sees it without scrolling
1915
- this.addMessageToChat({
1916
- role: "compactionSummary",
1917
- tokensBefore: event.result.tokensBefore,
1918
- summary: event.result.summary,
1919
- timestamp: Date.now(),
1920
- });
1921
- this.footer.invalidate();
1922
- }
1923
- else if (event.errorMessage) {
1924
- // Compaction failed (e.g., quota exceeded, API error)
1925
- this.chatContainer.addChild(new Spacer(1));
1926
- this.chatContainer.addChild(new Text(theme.fg("error", event.errorMessage), 1, 0));
1927
- }
1928
- void this.flushCompactionQueue({ willRetry: event.willRetry });
1929
- this.ui.requestRender();
1930
- break;
1931
- }
1932
- case "auto_retry_start": {
1933
- // Set up escape to abort retry
1934
- this.retryEscapeHandler = this.defaultEditor.onEscape;
1935
- this.defaultEditor.onEscape = () => {
1936
- this.session.abortRetry();
1937
- };
1938
- // Show retry indicator
1939
- this.statusContainer.clear();
1940
- const delaySeconds = Math.round(event.delayMs / 1000);
1941
- this.retryLoader = new Loader(this.ui, (spinner) => theme.fg("warning", spinner), (text) => theme.fg("muted", text), `Retrying (${event.attempt}/${event.maxAttempts}) in ${delaySeconds}s... (${appKey(this.keybindings, "interrupt")} to cancel)`);
1942
- this.statusContainer.addChild(this.retryLoader);
1943
- this.ui.requestRender();
1944
- break;
1945
- }
1946
- case "auto_retry_end": {
1947
- // Restore escape handler
1948
- if (this.retryEscapeHandler) {
1949
- this.defaultEditor.onEscape = this.retryEscapeHandler;
1950
- this.retryEscapeHandler = undefined;
1951
- }
1952
- // Stop loader
1953
- if (this.retryLoader) {
1954
- this.retryLoader.stop();
1955
- this.retryLoader = undefined;
1956
- this.statusContainer.clear();
1957
- }
1958
- // Show error only on final failure (success shows normal response)
1959
- if (!event.success) {
1960
- this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
1961
- }
1962
- this.ui.requestRender();
1963
- break;
1964
- }
1965
- case "fallback_provider_switch": {
1966
- this.showStatus(`Switched from ${event.from} → ${event.to} (${event.reason})`);
1967
- this.ui.requestRender();
1968
- break;
1969
- }
1970
- case "fallback_provider_restored": {
1971
- this.showStatus(`Restored to ${event.provider}`);
1972
- this.ui.requestRender();
1973
- break;
1974
- }
1975
- case "fallback_chain_exhausted": {
1976
- this.showError(event.reason);
1977
- this.ui.requestRender();
1978
- break;
1979
- }
1980
- }
1590
+ await handleAgentEvent(this, event);
1981
1591
  }
1982
1592
  /** Extract text content from a user message */
1983
1593
  getUserMessageText(message) {
@@ -2750,67 +2360,17 @@ export class InteractiveMode {
2750
2360
  });
2751
2361
  }
2752
2362
  async handleModelCommand(searchTerm) {
2753
- if (!searchTerm) {
2754
- this.showModelSelector();
2755
- return;
2756
- }
2757
- const model = await this.findExactModelMatch(searchTerm);
2758
- if (model) {
2759
- try {
2760
- await this.session.setModel(model);
2761
- this.footer.invalidate();
2762
- this.updateEditorBorderColor();
2763
- this.showStatus(`Model: ${model.id}`);
2764
- this.checkDaxnutsEasterEgg(model);
2765
- }
2766
- catch (error) {
2767
- this.showError(error instanceof Error ? error.message : String(error));
2768
- }
2769
- return;
2770
- }
2771
- this.showModelSelector(searchTerm);
2363
+ await handleModelCommandController(this, searchTerm);
2772
2364
  }
2773
2365
  async findExactModelMatch(searchTerm) {
2774
- const term = searchTerm.trim();
2775
- if (!term)
2776
- return undefined;
2777
- let targetProvider;
2778
- let targetModelId = "";
2779
- if (term.includes("/")) {
2780
- const parts = term.split("/", 2);
2781
- targetProvider = parts[0]?.trim().toLowerCase();
2782
- targetModelId = parts[1]?.trim().toLowerCase() ?? "";
2783
- }
2784
- else {
2785
- targetModelId = term.toLowerCase();
2786
- }
2787
- if (!targetModelId)
2788
- return undefined;
2789
- const models = await this.getModelCandidates();
2790
- const exactMatches = models.filter((item) => {
2791
- const idMatch = item.id.toLowerCase() === targetModelId;
2792
- const providerMatch = !targetProvider || item.provider.toLowerCase() === targetProvider;
2793
- return idMatch && providerMatch;
2794
- });
2795
- return exactMatches.length === 1 ? exactMatches[0] : undefined;
2366
+ return findExactModelMatchController(this, searchTerm);
2796
2367
  }
2797
2368
  async getModelCandidates() {
2798
- if (this.session.scopedModels.length > 0) {
2799
- return this.session.scopedModels.map((scoped) => scoped.model);
2800
- }
2801
- this.session.modelRegistry.refresh();
2802
- try {
2803
- return await this.session.modelRegistry.getAvailable();
2804
- }
2805
- catch {
2806
- return [];
2807
- }
2369
+ return getModelCandidatesController(this);
2808
2370
  }
2809
2371
  /** Update the footer's available provider count from current model candidates */
2810
2372
  async updateAvailableProviderCount() {
2811
- const models = await this.getModelCandidates();
2812
- const uniqueProviders = new Set(models.map((m) => m.provider));
2813
- this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size);
2373
+ await updateAvailableProviderCountController(this);
2814
2374
  }
2815
2375
  showModelSelector(initialSearchInput) {
2816
2376
  this.showSelector((done) => {