@pellux/goodvibes-agent 0.1.0

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 (398) hide show
  1. package/.goodvibes/GOODVIBES.md +35 -0
  2. package/.goodvibes/agents/reviewer.md +48 -0
  3. package/.goodvibes/skills/add-provider/SKILL.md +199 -0
  4. package/CHANGELOG.md +25 -0
  5. package/README.md +74 -0
  6. package/bin/goodvibes-agent.ts +2 -0
  7. package/docs/README.md +23 -0
  8. package/docs/deployment-and-services.md +57 -0
  9. package/docs/getting-started.md +53 -0
  10. package/docs/release-and-publishing.md +46 -0
  11. package/package.json +134 -0
  12. package/scripts/check-bun.sh +20 -0
  13. package/src/audio/player.ts +156 -0
  14. package/src/audio/spoken-turn-controller.ts +203 -0
  15. package/src/audio/spoken-turn-model-routing.ts +117 -0
  16. package/src/audio/spoken-turn-wiring.ts +44 -0
  17. package/src/audio/text-chunker.ts +110 -0
  18. package/src/cli/bundle-command.ts +227 -0
  19. package/src/cli/completion.ts +90 -0
  20. package/src/cli/config-overrides.ts +159 -0
  21. package/src/cli/endpoints.ts +63 -0
  22. package/src/cli/entrypoint.ts +172 -0
  23. package/src/cli/help.ts +299 -0
  24. package/src/cli/index.ts +11 -0
  25. package/src/cli/management-commands.ts +426 -0
  26. package/src/cli/management.ts +744 -0
  27. package/src/cli/network-posture.ts +46 -0
  28. package/src/cli/package-verification.ts +123 -0
  29. package/src/cli/parser.ts +369 -0
  30. package/src/cli/provider-auth-routes.ts +22 -0
  31. package/src/cli/provider-classification.ts +107 -0
  32. package/src/cli/redaction.ts +105 -0
  33. package/src/cli/service-command.ts +26 -0
  34. package/src/cli/service-posture.ts +482 -0
  35. package/src/cli/status.ts +383 -0
  36. package/src/cli/surface-command.ts +247 -0
  37. package/src/cli/tui-startup.ts +32 -0
  38. package/src/cli/types.ts +69 -0
  39. package/src/cli-flags.ts +21 -0
  40. package/src/config/goodvibes-home-audit.ts +465 -0
  41. package/src/config/index.ts +57 -0
  42. package/src/config/provider-model.ts +23 -0
  43. package/src/config/secret-config.ts +119 -0
  44. package/src/config/secrets.ts +71 -0
  45. package/src/config/surface.ts +1 -0
  46. package/src/core/composer-state.ts +61 -0
  47. package/src/core/conversation-rendering.ts +359 -0
  48. package/src/core/conversation.ts +551 -0
  49. package/src/core/history.ts +45 -0
  50. package/src/core/orchestrator.ts +7 -0
  51. package/src/core/system-message-router.ts +171 -0
  52. package/src/daemon/cli.ts +55 -0
  53. package/src/daemon/safe-serve.ts +61 -0
  54. package/src/input/agent-workspace.ts +428 -0
  55. package/src/input/autocomplete.ts +96 -0
  56. package/src/input/bookmark-modal.ts +115 -0
  57. package/src/input/command-args-hint.ts +36 -0
  58. package/src/input/command-registry.ts +329 -0
  59. package/src/input/commands/agent-externalized-tui.ts +73 -0
  60. package/src/input/commands/agent-workspace-runtime.ts +17 -0
  61. package/src/input/commands/branch-runtime.ts +72 -0
  62. package/src/input/commands/cloudflare-runtime.ts +370 -0
  63. package/src/input/commands/config.ts +18 -0
  64. package/src/input/commands/control-room-runtime.ts +255 -0
  65. package/src/input/commands/conversation-runtime.ts +207 -0
  66. package/src/input/commands/discovery-runtime.ts +52 -0
  67. package/src/input/commands/eval.ts +204 -0
  68. package/src/input/commands/experience-runtime.ts +278 -0
  69. package/src/input/commands/guidance-runtime.ts +106 -0
  70. package/src/input/commands/health-runtime.ts +434 -0
  71. package/src/input/commands/hooks-runtime.ts +148 -0
  72. package/src/input/commands/incident-runtime.ts +95 -0
  73. package/src/input/commands/integration-runtime.ts +394 -0
  74. package/src/input/commands/intelligence-runtime.ts +223 -0
  75. package/src/input/commands/knowledge.ts +531 -0
  76. package/src/input/commands/local-auth-runtime.ts +105 -0
  77. package/src/input/commands/local-provider-runtime.ts +170 -0
  78. package/src/input/commands/local-runtime.ts +392 -0
  79. package/src/input/commands/local-setup-review.ts +199 -0
  80. package/src/input/commands/local-setup-transfer.ts +135 -0
  81. package/src/input/commands/local-setup.ts +282 -0
  82. package/src/input/commands/managed-runtime.ts +209 -0
  83. package/src/input/commands/marketplace-runtime.ts +290 -0
  84. package/src/input/commands/mcp-runtime.ts +432 -0
  85. package/src/input/commands/memory-product-runtime.ts +111 -0
  86. package/src/input/commands/memory.ts +151 -0
  87. package/src/input/commands/notify-runtime.ts +83 -0
  88. package/src/input/commands/onboarding-runtime.ts +14 -0
  89. package/src/input/commands/operator-panel-runtime.ts +146 -0
  90. package/src/input/commands/operator-runtime.ts +392 -0
  91. package/src/input/commands/planning-runtime.ts +205 -0
  92. package/src/input/commands/platform-access-runtime.ts +422 -0
  93. package/src/input/commands/platform-services-runtime.ts +246 -0
  94. package/src/input/commands/policy-dispatch.ts +339 -0
  95. package/src/input/commands/policy.ts +17 -0
  96. package/src/input/commands/product-runtime.ts +351 -0
  97. package/src/input/commands/profile-sync-runtime.ts +99 -0
  98. package/src/input/commands/provider-accounts-runtime.ts +113 -0
  99. package/src/input/commands/provider.ts +363 -0
  100. package/src/input/commands/qrcode-runtime.ts +20 -0
  101. package/src/input/commands/quit-shared.ts +162 -0
  102. package/src/input/commands/recall-bundle.ts +132 -0
  103. package/src/input/commands/recall-capture.ts +152 -0
  104. package/src/input/commands/recall-query.ts +229 -0
  105. package/src/input/commands/recall-review.ts +98 -0
  106. package/src/input/commands/recall-shared.ts +22 -0
  107. package/src/input/commands/remote-runtime-pool.ts +106 -0
  108. package/src/input/commands/remote-runtime-setup.ts +199 -0
  109. package/src/input/commands/remote-runtime.ts +431 -0
  110. package/src/input/commands/replay-runtime.ts +18 -0
  111. package/src/input/commands/runtime-services.ts +291 -0
  112. package/src/input/commands/schedule-runtime.ts +91 -0
  113. package/src/input/commands/services-runtime.ts +209 -0
  114. package/src/input/commands/session-content.ts +408 -0
  115. package/src/input/commands/session-workflow.ts +464 -0
  116. package/src/input/commands/session.ts +375 -0
  117. package/src/input/commands/settings-sync-runtime.ts +174 -0
  118. package/src/input/commands/share-runtime.ts +119 -0
  119. package/src/input/commands/shell-core.ts +307 -0
  120. package/src/input/commands/skills-runtime.ts +221 -0
  121. package/src/input/commands/subscription-runtime.ts +434 -0
  122. package/src/input/commands/tasks-runtime.ts +230 -0
  123. package/src/input/commands/teamwork-runtime.ts +339 -0
  124. package/src/input/commands/teleport-runtime.ts +57 -0
  125. package/src/input/commands/tts-runtime.ts +29 -0
  126. package/src/input/commands/work-plan-runtime.ts +169 -0
  127. package/src/input/commands.ts +131 -0
  128. package/src/input/feed-context-factory.ts +254 -0
  129. package/src/input/file-picker.ts +192 -0
  130. package/src/input/handler-command-route.ts +180 -0
  131. package/src/input/handler-content-actions.ts +497 -0
  132. package/src/input/handler-feed-routes.ts +648 -0
  133. package/src/input/handler-feed.ts +452 -0
  134. package/src/input/handler-interactions.ts +281 -0
  135. package/src/input/handler-modal-routes.ts +418 -0
  136. package/src/input/handler-modal-stack.ts +263 -0
  137. package/src/input/handler-modal-token-routes.ts +329 -0
  138. package/src/input/handler-onboarding-cloudflare.ts +391 -0
  139. package/src/input/handler-onboarding.ts +620 -0
  140. package/src/input/handler-picker-routes.ts +472 -0
  141. package/src/input/handler-prompt-buffer.ts +320 -0
  142. package/src/input/handler-shortcuts.ts +213 -0
  143. package/src/input/handler-ui-state.ts +372 -0
  144. package/src/input/handler.ts +729 -0
  145. package/src/input/input-history.ts +297 -0
  146. package/src/input/keybindings.ts +292 -0
  147. package/src/input/mcp-workspace.ts +554 -0
  148. package/src/input/model-picker-provider-filter.ts +28 -0
  149. package/src/input/model-picker-types.ts +137 -0
  150. package/src/input/model-picker.ts +797 -0
  151. package/src/input/onboarding/handler-onboarding-routes.ts +125 -0
  152. package/src/input/onboarding/onboarding-runtime-status.ts +87 -0
  153. package/src/input/onboarding/onboarding-wizard-apply.ts +277 -0
  154. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +494 -0
  155. package/src/input/onboarding/onboarding-wizard-cloudflare.ts +204 -0
  156. package/src/input/onboarding/onboarding-wizard-constants.ts +158 -0
  157. package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +130 -0
  158. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +762 -0
  159. package/src/input/onboarding/onboarding-wizard-helpers.ts +167 -0
  160. package/src/input/onboarding/onboarding-wizard-rules.ts +256 -0
  161. package/src/input/onboarding/onboarding-wizard-state.ts +365 -0
  162. package/src/input/onboarding/onboarding-wizard-steps.ts +798 -0
  163. package/src/input/onboarding/onboarding-wizard-types.ts +195 -0
  164. package/src/input/onboarding/onboarding-wizard.ts +711 -0
  165. package/src/input/panel-integration-actions.ts +78 -0
  166. package/src/input/profile-picker-modal.ts +222 -0
  167. package/src/input/search.ts +100 -0
  168. package/src/input/selection-modal.ts +163 -0
  169. package/src/input/selection.ts +135 -0
  170. package/src/input/session-picker-modal.ts +136 -0
  171. package/src/input/settings-modal-behavior.ts +37 -0
  172. package/src/input/settings-modal-secrets.ts +41 -0
  173. package/src/input/settings-modal-subscriptions.ts +95 -0
  174. package/src/input/settings-modal-types.ts +91 -0
  175. package/src/input/settings-modal.ts +793 -0
  176. package/src/input/submission-intent.ts +17 -0
  177. package/src/input/submission-router.ts +59 -0
  178. package/src/input/tts-settings-actions.ts +100 -0
  179. package/src/main.ts +792 -0
  180. package/src/mcp/runtime-reload.ts +81 -0
  181. package/src/panels/agent-inspector-panel.ts +521 -0
  182. package/src/panels/agent-inspector-shared.ts +94 -0
  183. package/src/panels/agent-logs-panel.ts +559 -0
  184. package/src/panels/agent-logs-shared.ts +129 -0
  185. package/src/panels/approval-panel.ts +150 -0
  186. package/src/panels/automation-control-panel.ts +212 -0
  187. package/src/panels/base-panel.ts +254 -0
  188. package/src/panels/builtin/agent.ts +117 -0
  189. package/src/panels/builtin/development.ts +31 -0
  190. package/src/panels/builtin/knowledge.ts +26 -0
  191. package/src/panels/builtin/operations.ts +349 -0
  192. package/src/panels/builtin/session.ts +129 -0
  193. package/src/panels/builtin/shared.ts +274 -0
  194. package/src/panels/builtin-panels.ts +23 -0
  195. package/src/panels/cockpit-panel.ts +183 -0
  196. package/src/panels/communication-panel.ts +153 -0
  197. package/src/panels/confirm-state.ts +61 -0
  198. package/src/panels/context-visualizer-panel.ts +204 -0
  199. package/src/panels/control-plane-panel.ts +211 -0
  200. package/src/panels/cost-tracker-panel.ts +444 -0
  201. package/src/panels/debug-panel.ts +432 -0
  202. package/src/panels/diff-panel.ts +520 -0
  203. package/src/panels/docs-panel.ts +283 -0
  204. package/src/panels/eval-panel.ts +399 -0
  205. package/src/panels/file-explorer-panel.ts +584 -0
  206. package/src/panels/file-preview-panel.ts +434 -0
  207. package/src/panels/forensics-panel.ts +364 -0
  208. package/src/panels/git-panel.ts +638 -0
  209. package/src/panels/hooks-panel.ts +239 -0
  210. package/src/panels/incident-review-panel.ts +197 -0
  211. package/src/panels/index.ts +46 -0
  212. package/src/panels/intelligence-panel.ts +176 -0
  213. package/src/panels/knowledge-panel.ts +345 -0
  214. package/src/panels/local-auth-panel.ts +130 -0
  215. package/src/panels/marketplace-panel.ts +212 -0
  216. package/src/panels/memory-panel.ts +225 -0
  217. package/src/panels/ops-control-panel.ts +150 -0
  218. package/src/panels/ops-strategy-panel.ts +235 -0
  219. package/src/panels/orchestration-panel.ts +273 -0
  220. package/src/panels/panel-list-panel.ts +509 -0
  221. package/src/panels/panel-manager.ts +570 -0
  222. package/src/panels/panel-picker.ts +106 -0
  223. package/src/panels/plan-dashboard-panel.ts +274 -0
  224. package/src/panels/plugins-panel.ts +178 -0
  225. package/src/panels/policy-panel.ts +308 -0
  226. package/src/panels/polish.ts +717 -0
  227. package/src/panels/project-planning-panel.ts +711 -0
  228. package/src/panels/provider-account-snapshot.ts +259 -0
  229. package/src/panels/provider-accounts-panel.ts +218 -0
  230. package/src/panels/provider-health-domains.ts +215 -0
  231. package/src/panels/provider-health-panel.ts +727 -0
  232. package/src/panels/provider-health-tracker.ts +115 -0
  233. package/src/panels/provider-stats-panel.ts +366 -0
  234. package/src/panels/qr-panel.ts +182 -0
  235. package/src/panels/remote-panel.ts +449 -0
  236. package/src/panels/routes-panel.ts +178 -0
  237. package/src/panels/sandbox-panel.ts +283 -0
  238. package/src/panels/schedule-panel.ts +329 -0
  239. package/src/panels/scrollable-list-panel.ts +491 -0
  240. package/src/panels/search-focus.ts +32 -0
  241. package/src/panels/security-panel.ts +295 -0
  242. package/src/panels/services-panel.ts +231 -0
  243. package/src/panels/session-browser-panel.ts +400 -0
  244. package/src/panels/session-maintenance.ts +125 -0
  245. package/src/panels/settings-sync-panel.ts +120 -0
  246. package/src/panels/skills-panel.ts +431 -0
  247. package/src/panels/subscription-panel.ts +263 -0
  248. package/src/panels/symbol-outline-panel.ts +486 -0
  249. package/src/panels/system-messages-panel.ts +230 -0
  250. package/src/panels/tasks-panel.ts +399 -0
  251. package/src/panels/thinking-panel.ts +304 -0
  252. package/src/panels/token-budget-panel.ts +475 -0
  253. package/src/panels/tool-inspector-panel.ts +429 -0
  254. package/src/panels/types.ts +54 -0
  255. package/src/panels/watchers-panel.ts +193 -0
  256. package/src/panels/work-plan-panel.ts +175 -0
  257. package/src/panels/worktree-panel.ts +182 -0
  258. package/src/panels/wrfc-panel.ts +609 -0
  259. package/src/permissions/prompt.ts +165 -0
  260. package/src/planning/project-planning-coordinator.ts +543 -0
  261. package/src/plugins/loader.ts +15 -0
  262. package/src/renderer/agent-detail-modal.ts +331 -0
  263. package/src/renderer/agent-workspace.ts +238 -0
  264. package/src/renderer/ansi-sanitize.ts +76 -0
  265. package/src/renderer/autocomplete-overlay.ts +154 -0
  266. package/src/renderer/block-actions.ts +76 -0
  267. package/src/renderer/bookmark-modal.ts +101 -0
  268. package/src/renderer/bottom-bar.ts +58 -0
  269. package/src/renderer/buffer.ts +113 -0
  270. package/src/renderer/code-block.ts +373 -0
  271. package/src/renderer/compositor.ts +283 -0
  272. package/src/renderer/context-inspector.ts +219 -0
  273. package/src/renderer/conversation-layout.ts +67 -0
  274. package/src/renderer/conversation-overlays.ts +140 -0
  275. package/src/renderer/conversation-surface.ts +260 -0
  276. package/src/renderer/diff-view.ts +132 -0
  277. package/src/renderer/diff.ts +130 -0
  278. package/src/renderer/file-picker-overlay.ts +101 -0
  279. package/src/renderer/file-tree.ts +153 -0
  280. package/src/renderer/fullscreen-primitives.ts +130 -0
  281. package/src/renderer/fullscreen-workspace.ts +199 -0
  282. package/src/renderer/git-status.ts +89 -0
  283. package/src/renderer/help-overlay.ts +267 -0
  284. package/src/renderer/history-search-overlay.ts +73 -0
  285. package/src/renderer/layout-engine.ts +97 -0
  286. package/src/renderer/layout.ts +32 -0
  287. package/src/renderer/live-tail-modal.ts +156 -0
  288. package/src/renderer/markdown.ts +635 -0
  289. package/src/renderer/mcp-workspace.ts +237 -0
  290. package/src/renderer/modal-factory.ts +467 -0
  291. package/src/renderer/modal-utils.ts +24 -0
  292. package/src/renderer/model-picker-overlay.ts +473 -0
  293. package/src/renderer/model-workspace.ts +488 -0
  294. package/src/renderer/onboarding/onboarding-wizard.ts +615 -0
  295. package/src/renderer/overlay-box.ts +146 -0
  296. package/src/renderer/overlay-viewport.ts +104 -0
  297. package/src/renderer/panel-composite.ts +158 -0
  298. package/src/renderer/panel-picker-overlay.ts +202 -0
  299. package/src/renderer/panel-tab-bar.ts +69 -0
  300. package/src/renderer/panel-workspace-bar.ts +42 -0
  301. package/src/renderer/process-indicator.ts +96 -0
  302. package/src/renderer/process-modal.ts +656 -0
  303. package/src/renderer/process-summary.ts +67 -0
  304. package/src/renderer/profile-picker-modal.ts +129 -0
  305. package/src/renderer/progress.ts +98 -0
  306. package/src/renderer/qr-renderer.ts +120 -0
  307. package/src/renderer/search-overlay.ts +54 -0
  308. package/src/renderer/selection-modal-overlay.ts +214 -0
  309. package/src/renderer/semantic-diff.ts +369 -0
  310. package/src/renderer/session-picker-modal.ts +127 -0
  311. package/src/renderer/settings-modal-helpers.ts +193 -0
  312. package/src/renderer/settings-modal.ts +537 -0
  313. package/src/renderer/shell-surface.ts +88 -0
  314. package/src/renderer/status-glyphs.ts +21 -0
  315. package/src/renderer/status-token.ts +67 -0
  316. package/src/renderer/surface-layout.ts +101 -0
  317. package/src/renderer/syntax-highlighter.ts +542 -0
  318. package/src/renderer/system-message.ts +83 -0
  319. package/src/renderer/tab-strip.ts +108 -0
  320. package/src/renderer/text-layout.ts +31 -0
  321. package/src/renderer/thinking.ts +17 -0
  322. package/src/renderer/tool-call.ts +234 -0
  323. package/src/renderer/ui-factory.ts +524 -0
  324. package/src/renderer/ui-primitives.ts +96 -0
  325. package/src/runtime/bootstrap-command-context.ts +278 -0
  326. package/src/runtime/bootstrap-command-parts.ts +386 -0
  327. package/src/runtime/bootstrap-core.ts +540 -0
  328. package/src/runtime/bootstrap-hook-bridge.ts +112 -0
  329. package/src/runtime/bootstrap-shell.ts +283 -0
  330. package/src/runtime/bootstrap.ts +575 -0
  331. package/src/runtime/cloudflare-control-plane.ts +349 -0
  332. package/src/runtime/context.ts +142 -0
  333. package/src/runtime/diagnostics/panels/index.ts +24 -0
  334. package/src/runtime/diagnostics/panels/ops.ts +156 -0
  335. package/src/runtime/diagnostics/panels/panel-resources.ts +118 -0
  336. package/src/runtime/diagnostics/panels/policy.ts +177 -0
  337. package/src/runtime/index.ts +662 -0
  338. package/src/runtime/onboarding/apply.ts +642 -0
  339. package/src/runtime/onboarding/derivation.ts +534 -0
  340. package/src/runtime/onboarding/index.ts +7 -0
  341. package/src/runtime/onboarding/markers.ts +148 -0
  342. package/src/runtime/onboarding/snapshot.ts +406 -0
  343. package/src/runtime/onboarding/state.ts +141 -0
  344. package/src/runtime/onboarding/types.ts +404 -0
  345. package/src/runtime/onboarding/verify.ts +171 -0
  346. package/src/runtime/operator-token-cleanup.ts +27 -0
  347. package/src/runtime/perf/panel-contracts.ts +32 -0
  348. package/src/runtime/perf/panel-health-monitor.ts +18 -0
  349. package/src/runtime/sandbox-public-gaps.ts +358 -0
  350. package/src/runtime/services.ts +670 -0
  351. package/src/runtime/store/domains/domain-read-matrix.ts +15 -0
  352. package/src/runtime/store/domains/index.ts +222 -0
  353. package/src/runtime/store/domains/panels.ts +117 -0
  354. package/src/runtime/store/domains/ui-perf.ts +103 -0
  355. package/src/runtime/store/index.ts +305 -0
  356. package/src/runtime/store/selectors/index.ts +359 -0
  357. package/src/runtime/store/state.ts +145 -0
  358. package/src/runtime/surface-feature-flags.ts +65 -0
  359. package/src/runtime/terminal-output-guard.ts +228 -0
  360. package/src/runtime/ui/index.ts +39 -0
  361. package/src/runtime/ui/model-picker/data-provider.ts +182 -0
  362. package/src/runtime/ui/model-picker/health-enrichment.ts +228 -0
  363. package/src/runtime/ui/model-picker/index.ts +59 -0
  364. package/src/runtime/ui/model-picker/types.ts +149 -0
  365. package/src/runtime/ui/provider-health/data-provider.ts +244 -0
  366. package/src/runtime/ui/provider-health/fallback-visualizer.ts +71 -0
  367. package/src/runtime/ui/provider-health/index.ts +46 -0
  368. package/src/runtime/ui/provider-health/types.ts +146 -0
  369. package/src/runtime/ui-events.ts +1 -0
  370. package/src/runtime/ui-read-model-helpers.ts +1 -0
  371. package/src/runtime/ui-read-models-observability-maintenance.ts +1 -0
  372. package/src/runtime/ui-read-models-observability-options.ts +1 -0
  373. package/src/runtime/ui-read-models-observability-remote.ts +1 -0
  374. package/src/runtime/ui-read-models-observability-security.ts +1 -0
  375. package/src/runtime/ui-read-models-observability-system.ts +1 -0
  376. package/src/runtime/ui-read-models-observability.ts +1 -0
  377. package/src/runtime/ui-read-models.ts +61 -0
  378. package/src/runtime/ui-service-queries.ts +1 -0
  379. package/src/runtime/ui-services.ts +190 -0
  380. package/src/scripts/process-messages.ts +42 -0
  381. package/src/shell/blocking-input.ts +98 -0
  382. package/src/shell/service-settings-sync.ts +273 -0
  383. package/src/shell/ui-openers.ts +352 -0
  384. package/src/tools/index.ts +1 -0
  385. package/src/tools/wrfc-agent-guard.ts +49 -0
  386. package/src/types/grid.ts +48 -0
  387. package/src/types/sql-js.d.ts +15 -0
  388. package/src/utils/clipboard.ts +22 -0
  389. package/src/utils/splash-lines.ts +46 -0
  390. package/src/utils/terminal-width.ts +185 -0
  391. package/src/verification/live-verifier.ts +430 -0
  392. package/src/verification/verification-ledger.ts +242 -0
  393. package/src/version.ts +17 -0
  394. package/src/widget/index.ts +2 -0
  395. package/src/widget/types.ts +9 -0
  396. package/src/widget/widget.ts +8 -0
  397. package/src/work-plans/work-plan-store.ts +374 -0
  398. package/tsconfig.json +18 -0
@@ -0,0 +1,131 @@
1
+ import type { CommandRegistry } from './command-registry.ts';
2
+ import { policyCommand } from './commands/policy.ts';
3
+ import { providerCommand } from './commands/provider.ts';
4
+ import { evalCommand } from './commands/eval.ts';
5
+ import { sessionCommand } from './commands/session.ts';
6
+ import { recallCommand } from './commands/memory.ts';
7
+ import { knowledgeCommand } from './commands/knowledge.ts';
8
+ import { registerShellCoreCommands } from './commands/shell-core.ts';
9
+ import { registerConfigCommand } from './commands/config.ts';
10
+ import { registerSessionWorkflowCommands } from './commands/session-workflow.ts';
11
+ import { registerDiscoveryRuntimeCommands } from './commands/discovery-runtime.ts';
12
+ import { registerPlanningRuntimeCommands } from './commands/planning-runtime.ts';
13
+ import { registerScheduleRuntimeCommands } from './commands/schedule-runtime.ts';
14
+ import { registerBranchRuntimeCommands } from './commands/branch-runtime.ts';
15
+ import { registerOperatorRuntimeCommands } from './commands/operator-runtime.ts';
16
+ import { registerIntegrationRuntimeCommands } from './commands/integration-runtime.ts';
17
+ import { registerNotifyRuntimeCommands } from './commands/notify-runtime.ts';
18
+ import { registerReplayRuntimeCommands } from './commands/replay-runtime.ts';
19
+ import { registerShareRuntimeCommands } from './commands/share-runtime.ts';
20
+ import { registerLocalSetupCommands } from './commands/local-setup.ts';
21
+ import { registerProductRuntimeCommands } from './commands/product-runtime.ts';
22
+ import { registerProfileSyncRuntimeCommands } from './commands/profile-sync-runtime.ts';
23
+ import { registerManagedRuntimeCommands } from './commands/managed-runtime.ts';
24
+ import { registerPlatformAccessRuntimeCommands } from './commands/platform-access-runtime.ts';
25
+ import { registerPlatformServicesRuntimeCommands } from './commands/platform-services-runtime.ts';
26
+ import { registerTeamworkRuntimeCommands } from './commands/teamwork-runtime.ts';
27
+ import { registerMarketplaceRuntimeCommands } from './commands/marketplace-runtime.ts';
28
+ import { registerGuidanceRuntimeCommands } from './commands/guidance-runtime.ts';
29
+ import { registerRemoteRuntimeCommands } from './commands/remote-runtime.ts';
30
+ import { registerTeleportRuntimeCommands } from './commands/teleport-runtime.ts';
31
+ import { registerSubscriptionRuntimeCommands } from './commands/subscription-runtime.ts';
32
+ import { registerHooksRuntimeCommands } from './commands/hooks-runtime.ts';
33
+ import { registerControlRoomRuntimeCommands } from './commands/control-room-runtime.ts';
34
+ import { registerMcpRuntimeCommands } from './commands/mcp-runtime.ts';
35
+ import { registerSessionContentCommands } from './commands/session-content.ts';
36
+ import { registerLocalRuntimeCommands } from './commands/local-runtime.ts';
37
+ import { registerExperienceRuntimeCommands } from './commands/experience-runtime.ts';
38
+ import { registerIncidentRuntimeCommands } from './commands/incident-runtime.ts';
39
+ import { registerMemoryProductRuntimeCommands } from './commands/memory-product-runtime.ts';
40
+ import { registerSkillsRuntimeCommands } from './commands/skills-runtime.ts';
41
+ import { registerServicesRuntimeCommands } from './commands/services-runtime.ts';
42
+ import { registerTasksRuntimeCommands } from './commands/tasks-runtime.ts';
43
+ import { registerLocalProviderRuntimeCommands } from './commands/local-provider-runtime.ts';
44
+ import { registerHealthRuntimeCommands } from './commands/health-runtime.ts';
45
+ import { registerSettingsSyncRuntimeCommands } from './commands/settings-sync-runtime.ts';
46
+ import { registerProviderAccountsRuntimeCommands } from './commands/provider-accounts-runtime.ts';
47
+ import { registerLocalAuthRuntimeCommands } from './commands/local-auth-runtime.ts';
48
+ import { registerIntelligenceRuntimeCommands } from './commands/intelligence-runtime.ts';
49
+ import { registerConversationRuntimeCommands } from './commands/conversation-runtime.ts';
50
+ import { registerQrcodeRuntimeCommands } from './commands/qrcode-runtime.ts';
51
+ import { registerOnboardingRuntimeCommands } from './commands/onboarding-runtime.ts';
52
+ import { registerTtsRuntimeCommands } from './commands/tts-runtime.ts';
53
+ import { registerCloudflareRuntimeCommands } from './commands/cloudflare-runtime.ts';
54
+ import { registerWorkPlanRuntimeCommands } from './commands/work-plan-runtime.ts';
55
+ import { registerAgentWorkspaceRuntimeCommands } from './commands/agent-workspace-runtime.ts';
56
+ import { registerAgentExternalizedTuiCommands } from './commands/agent-externalized-tui.ts';
57
+
58
+ /**
59
+ * registerBuiltinCommands - Register all built-in slash commands into the registry.
60
+ * Call once during application startup.
61
+ */
62
+ export function registerBuiltinCommands(registry: CommandRegistry): void {
63
+ registerShellCoreCommands(registry);
64
+ registerAgentWorkspaceRuntimeCommands(registry);
65
+ registerConfigCommand(registry);
66
+ registerOperatorRuntimeCommands(registry);
67
+ registerIntegrationRuntimeCommands(registry);
68
+ registerAgentExternalizedTuiCommands(registry);
69
+ registerNotifyRuntimeCommands(registry);
70
+ registerReplayRuntimeCommands(registry);
71
+ registerShareRuntimeCommands(registry);
72
+ registerLocalSetupCommands(registry);
73
+ registerProductRuntimeCommands(registry);
74
+ registerProfileSyncRuntimeCommands(registry);
75
+ registerManagedRuntimeCommands(registry);
76
+ registerPlatformAccessRuntimeCommands(registry);
77
+ registerPlatformServicesRuntimeCommands(registry);
78
+ registerTeamworkRuntimeCommands(registry);
79
+ registerMarketplaceRuntimeCommands(registry);
80
+ registerGuidanceRuntimeCommands(registry);
81
+ registerRemoteRuntimeCommands(registry);
82
+ registerTeleportRuntimeCommands(registry);
83
+ registerSubscriptionRuntimeCommands(registry);
84
+ registerHooksRuntimeCommands(registry);
85
+ registerControlRoomRuntimeCommands(registry);
86
+ registerMcpRuntimeCommands(registry);
87
+ registerIncidentRuntimeCommands(registry);
88
+ registerMemoryProductRuntimeCommands(registry);
89
+ registerSkillsRuntimeCommands(registry);
90
+ registerExperienceRuntimeCommands(registry);
91
+ registerServicesRuntimeCommands(registry);
92
+ registerTasksRuntimeCommands(registry);
93
+ registerLocalProviderRuntimeCommands(registry);
94
+ registerHealthRuntimeCommands(registry);
95
+ registerSettingsSyncRuntimeCommands(registry);
96
+ registerProviderAccountsRuntimeCommands(registry);
97
+ registerLocalAuthRuntimeCommands(registry);
98
+ registerIntelligenceRuntimeCommands(registry);
99
+ registerConversationRuntimeCommands(registry);
100
+ registerQrcodeRuntimeCommands(registry);
101
+ registerOnboardingRuntimeCommands(registry);
102
+ registerTtsRuntimeCommands(registry);
103
+ registerCloudflareRuntimeCommands(registry);
104
+ registerWorkPlanRuntimeCommands(registry);
105
+ registerLocalRuntimeCommands(registry);
106
+ registerSessionWorkflowCommands(registry);
107
+ registerDiscoveryRuntimeCommands(registry);
108
+ registerPlanningRuntimeCommands(registry);
109
+ registerScheduleRuntimeCommands(registry);
110
+ registerBranchRuntimeCommands(registry);
111
+ registerSessionContentCommands(registry);
112
+
113
+ // ── /policy ───────────────────────────────────────────────────────────────
114
+ registry.register(policyCommand);
115
+
116
+ // ── /provider ─────────────────────────────────────────────────────────────
117
+ registry.register(providerCommand);
118
+
119
+ // ── /eval ─────────────────────────────────────────────────────────────────
120
+ registry.register(evalCommand);
121
+
122
+ // ── /session ─────────────────────────────────────────────────────────────
123
+ registry.register(sessionCommand);
124
+
125
+ // ── /recall ──────────────────────────────────────────────────────────────
126
+ registry.register(recallCommand);
127
+
128
+ // ── /knowledge ───────────────────────────────────────────────────────────
129
+ registry.register(knowledgeCommand);
130
+
131
+ }
@@ -0,0 +1,254 @@
1
+ /**
2
+ * feed-context-factory.ts — Construction and mutable-field sync for InputFeedContext.
3
+ *
4
+ * Extracted from handler.ts (Wave 4α review, 0.18.23) to keep handler.ts under the
5
+ * 800-line architecture cap.
6
+ *
7
+ * Two exported functions:
8
+ * - `buildInitialFeedContext` — assembles the long-lived InputFeedContext from
9
+ * pre-built field groups. Called once at InputHandler construction time.
10
+ * - `syncFeedContextMutableFields` — copies mutable scalar fields into the
11
+ * already-allocated context before each feed() dispatch.
12
+ */
13
+ import type { InputFeedContext } from './handler-feed.ts';
14
+ import type { SelectionManager } from './selection.ts';
15
+ import type { InfiniteBuffer } from '../core/history.ts';
16
+ import type { CommandRegistry, CommandContext } from './command-registry.ts';
17
+ import type { AutocompleteEngine } from './autocomplete.ts';
18
+ import type { FilePickerModal } from './file-picker.ts';
19
+ import type { ModelPickerModal } from './model-picker.ts';
20
+ import type { SelectionModal } from './selection-modal.ts';
21
+ import type { SelectionResult } from './selection-modal.ts';
22
+ import type { SearchManager } from './search.ts';
23
+ import type { InputHistory, HistorySearch } from './input-history.ts';
24
+ import type { ConversationManager } from '../core/conversation';
25
+ import type { ProcessModal } from '../renderer/process-modal.ts';
26
+ import type { LiveTailModal } from '../renderer/live-tail-modal.ts';
27
+ import type { BlockActionsMenu } from '../renderer/block-actions.ts';
28
+ import type { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
29
+ import type { ContextInspectorModal } from '../renderer/context-inspector.ts';
30
+ import type { BookmarkModal } from './bookmark-modal.ts';
31
+ import type { SettingsModal } from './settings-modal.ts';
32
+ import type { McpWorkspace } from './mcp-workspace.ts';
33
+ import type { AgentWorkspace } from './agent-workspace.ts';
34
+ import type { SessionPickerModal } from './session-picker-modal.ts';
35
+ import type { ProfilePickerModal } from './profile-picker-modal.ts';
36
+ import type { OnboardingWizardController } from './onboarding/onboarding-wizard.ts';
37
+ import type { WrappedPromptInfo } from './handler-prompt-buffer.ts';
38
+ import type { Panel } from '../panels/types.ts';
39
+ import type { PanelManager } from '../panels/panel-manager.ts';
40
+ import type { KeybindingsManager } from './keybindings.ts';
41
+ import type { ModelPickerTarget } from './model-picker.ts';
42
+ import type { PanelMouseLayout } from './handler-feed-routes.ts';
43
+
44
+ /**
45
+ * Initial mutable scalar values for InputFeedContext.
46
+ *
47
+ * **Mutable fields** (synced per-feed via syncFeedContextMutableFields or inside
48
+ * action closures that call syncFeedContextMutableFields):
49
+ * - `prompt`, `cursorPos` — current text buffer state
50
+ * - `commandMode`, `panelFocused`, `indicatorFocused` — focus-mode flags
51
+ * - `helpOverlayActive`, `helpScrollOffset` — help overlay state
52
+ * - `shortcutsOverlayActive`, `shortcutsScrollOffset` — shortcuts overlay state
53
+ * - `nextPasteId`, `nextImageId` — monotonically increasing ID counters
54
+ * - `mouseDownRow`, `mouseDownCol` — drag-tracking coordinates
55
+ * - `contentWidth` — reflow width, updated by setContentWidth()
56
+ * - `selectionCallback` — current selection modal callback (nullable)
57
+ */
58
+ export interface FeedContextMutableInit {
59
+ prompt: string;
60
+ cursorPos: number;
61
+ inputScrollTop: number;
62
+ commandMode: boolean;
63
+ panelFocused: boolean;
64
+ indicatorFocused: boolean;
65
+ helpOverlayActive: boolean;
66
+ helpScrollOffset: number;
67
+ shortcutsOverlayActive: boolean;
68
+ shortcutsScrollOffset: number;
69
+ nextPasteId: number;
70
+ nextImageId: number;
71
+ mouseDownRow: number;
72
+ mouseDownCol: number;
73
+ contentWidth: number;
74
+ panelMouseLayout: PanelMouseLayout | null;
75
+ selectionCallback: ((result: SelectionResult | null) => void) | null;
76
+ }
77
+
78
+ /**
79
+ * Stable (readonly) service references for InputFeedContext.
80
+ *
81
+ * **Stable references** (set once at construction, never reallocated):
82
+ * - `pasteRegistry`, `imageRegistry` — owned Maps, never replaced
83
+ * - `selectionModal`, `bookmarkModal`, `settingsModal`, `sessionPickerModal`,
84
+ * `profilePickerModal` — modal objects constructed once
85
+ * - `filePicker`, `modelPicker`, `processModal`, `liveTailModal`,
86
+ * `agentDetailModal`, `contextInspectorModal`, `blockActionsMenu`,
87
+ * `searchManager`, `historySearch`, `onboardingWizard` — service objects constructed once
88
+ * - `panelManager`, `keybindingsManager` — from uiServices, stable
89
+ * - `modalStack` — reference to the handler's shared array
90
+ * - `getHistory`, `getViewportHeight`, `getScrollTop`, `scroll`, `exitApp` — callbacks
91
+ * - `commandRegistry`, `commandContext`, `autocomplete`, `inputHistory`,
92
+ * `conversationManager` — wired after construction; synced at feed() entry only
93
+ * (not per-action) since no in-feed action changes them
94
+ *
95
+ * **Rationale:** per-feed mutation on a single object avoids per-keystroke GC pressure
96
+ * from ~80-field object allocation. Stable references are service handles that never
97
+ * need to change after construction.
98
+ */
99
+ export interface FeedContextStableRefs {
100
+ selection: SelectionManager;
101
+ pasteRegistry: Map<string, string>;
102
+ imageRegistry: Map<string, { data: string; mediaType: string }>;
103
+ projectRoot: string;
104
+ selectionModal: SelectionModal;
105
+ bookmarkModal: BookmarkModal;
106
+ settingsModal: SettingsModal;
107
+ mcpWorkspace: McpWorkspace;
108
+ agentWorkspace: AgentWorkspace;
109
+ sessionPickerModal: SessionPickerModal;
110
+ profilePickerModal: ProfilePickerModal;
111
+ historySearch: HistorySearch;
112
+ commandRegistry: CommandRegistry | null;
113
+ commandContext: CommandContext | undefined;
114
+ autocomplete: AutocompleteEngine | null;
115
+ filePicker: FilePickerModal;
116
+ modelPicker: ModelPickerModal;
117
+ onboardingWizard: OnboardingWizardController;
118
+ processModal: ProcessModal;
119
+ liveTailModal: LiveTailModal;
120
+ agentDetailModal: AgentDetailModal;
121
+ contextInspectorModal: ContextInspectorModal;
122
+ blockActionsMenu: BlockActionsMenu;
123
+ searchManager: SearchManager;
124
+ modalStack: string[];
125
+ inputHistory: InputHistory | null;
126
+ conversationManager: ConversationManager | null;
127
+ panelManager: PanelManager;
128
+ keybindingsManager: KeybindingsManager;
129
+ getHistory: () => InfiniteBuffer;
130
+ getViewportHeight: () => number;
131
+ getScrollTop: () => number;
132
+ scroll: (delta: number) => void;
133
+ exitApp: () => void;
134
+ }
135
+
136
+ /** Bound method closures for InputFeedContext. Built in handler.ts where private members are accessible. */
137
+ export interface FeedContextClosures {
138
+ modalOpened: (name: string) => void;
139
+ handleEscape: () => void;
140
+ handleCopy: () => void;
141
+ handleCtrlC: () => void;
142
+ handleBlockCopy: () => void;
143
+ handleBookmark: () => void;
144
+ handleBlockSave: () => void;
145
+ handleDiffApply: () => boolean;
146
+ handleUndo: () => void;
147
+ handleRedo: () => void;
148
+ handlePaste: () => void;
149
+ saveUndoState: () => void;
150
+ ensureInputCursorVisible: (contentWidth?: number) => void;
151
+ registerPaste: (content: string) => string;
152
+ executeBlockAction: (id: string) => void;
153
+ cyclePanelTab: (direction: 'next' | 'prev') => void;
154
+ onPanelInputConsumed: (activePanel: Panel | null, key: string) => void;
155
+ getWrappedPromptInfo: (contentWidth: number) => WrappedPromptInfo;
156
+ moveCursorVertical: (direction: -1 | 1) => boolean;
157
+ handlePathCompletion: () => boolean;
158
+ handleBlockToggle: () => void;
159
+ findMarkerAtPos: (pos: number) => { start: number; end: number } | null;
160
+ cleanupMarkerRegistry: (text: string) => void;
161
+ expandPrompt: (text: string) => string | import('@pellux/goodvibes-sdk/platform/providers').ContentPart[];
162
+ openModelPickerWithTarget: (target: ModelPickerTarget, source?: 'settings' | 'onboarding') => boolean;
163
+ openProviderModelPickerWithTarget: (target: ModelPickerTarget, source?: 'settings' | 'onboarding') => boolean;
164
+ onModelPickerCommit: () => boolean;
165
+ onOnboardingAction: (action: import('./onboarding/onboarding-wizard.ts').OnboardingWizardAction) => void;
166
+ }
167
+
168
+ /**
169
+ * buildInitialFeedContext — Allocate the single InputFeedContext that lives for the
170
+ * lifetime of the InputHandler.
171
+ *
172
+ * Accepts pre-built field groups from handler.ts where private access is available.
173
+ * The resulting context object is mutated in place on every feed() call via
174
+ * syncFeedContextMutableFields — no re-allocation occurs per keystroke.
175
+ *
176
+ * @param mutable Initial mutable scalar values (synced per-feed).
177
+ * @param stable Stable service references (set once, never replaced).
178
+ * @param closures Pre-built bound method closures (built in handler.ts).
179
+ */
180
+ export function buildInitialFeedContext(
181
+ mutable: FeedContextMutableInit,
182
+ stable: FeedContextStableRefs,
183
+ closures: FeedContextClosures,
184
+ ): InputFeedContext {
185
+ const noop = (): void => {};
186
+ return {
187
+ // --- mutable scalars ---
188
+ ...mutable,
189
+ // --- requestRender: placeholder, swapped per-feed to buffered version ---
190
+ requestRender: noop,
191
+ // --- stable refs ---
192
+ ...stable,
193
+ // --- closures ---
194
+ ...closures,
195
+ };
196
+ }
197
+
198
+ /**
199
+ * syncFeedContextMutableFields — Copy mutable scalar fields into the reused
200
+ * InputFeedContext object.
201
+ *
202
+ * **Fields synced (updated on every call):**
203
+ * - `prompt` — current prompt text buffer
204
+ * - `cursorPos` — caret position within prompt
205
+ * - `commandMode` — whether command-mode prefix is active
206
+ * - `panelFocused` — whether the active panel owns keyboard focus
207
+ * - `indicatorFocused` — whether the status indicator owns focus
208
+ * - `helpOverlayActive` / `helpScrollOffset` — help overlay visibility and scroll
209
+ * - `shortcutsOverlayActive` / `shortcutsScrollOffset` — shortcuts overlay state
210
+ * - `selectionCallback` — the current in-flight selection modal callback
211
+ * - `nextPasteId` / `nextImageId` — monotonically increasing allocation counters
212
+ * - `mouseDownRow` / `mouseDownCol` — drag-start coordinates
213
+ *
214
+ * **Fields intentionally excluded (synced only at feed() entry, not here):**
215
+ * - `contentWidth` — semi-stable; only changes on terminal resize via setContentWidth().
216
+ * Synced at feed() entry because it is only relevant for layout, not action-reaction
217
+ * sequences within a single feed.
218
+ * - `commandRegistry`, `commandContext` — wired after construction via
219
+ * setCommandRegistry(); synced at feed() entry since no in-feed action changes them.
220
+ * - `autocomplete` — wired after construction; synced at feed() entry.
221
+ * - `inputHistory`, `conversationManager` — late-wired service handles; stable within
222
+ * a feed. Synced at feed() entry only.
223
+ * - `requestRender` — swapped to a buffered version at feed() entry and restored in
224
+ * the finally block; not managed by this function.
225
+ *
226
+ * Called from within action closures (`handleEscape`, `handleCtrlC`, `handleUndo`,
227
+ * `handleRedo`, `handlePaste`) that mutate handler state mid-feed, so subsequent
228
+ * route handlers see updated values without re-reading handler fields.
229
+ *
230
+ * @param fields Current mutable field values from the handler.
231
+ * @param ctx The InputFeedContext to update in place.
232
+ */
233
+ export function syncFeedContextMutableFields(
234
+ fields: FeedContextMutableInit,
235
+ ctx: InputFeedContext,
236
+ ): void {
237
+ ctx.prompt = fields.prompt;
238
+ ctx.cursorPos = fields.cursorPos;
239
+ ctx.inputScrollTop = fields.inputScrollTop;
240
+ ctx.commandMode = fields.commandMode;
241
+ ctx.panelFocused = fields.panelFocused;
242
+ ctx.indicatorFocused = fields.indicatorFocused;
243
+ ctx.helpOverlayActive = fields.helpOverlayActive;
244
+ ctx.helpScrollOffset = fields.helpScrollOffset;
245
+ ctx.shortcutsOverlayActive = fields.shortcutsOverlayActive;
246
+ ctx.shortcutsScrollOffset = fields.shortcutsScrollOffset;
247
+ ctx.selectionCallback = fields.selectionCallback;
248
+ ctx.nextPasteId = fields.nextPasteId;
249
+ ctx.nextImageId = fields.nextImageId;
250
+ ctx.mouseDownRow = fields.mouseDownRow;
251
+ ctx.mouseDownCol = fields.mouseDownCol;
252
+ ctx.contentWidth = fields.contentWidth;
253
+ ctx.panelMouseLayout = fields.panelMouseLayout;
254
+ }
@@ -0,0 +1,192 @@
1
+ import { readdir } from 'node:fs/promises';
2
+ import { join, relative } from 'node:path';
3
+ import type { ShellPathService } from '@/runtime/index.ts';
4
+
5
+ /**
6
+ * FilePickerModal - Fuzzy file finder triggered by @ in the input area.
7
+ * Walks the project directory, fuzzy-matches against the query,
8
+ * and lets the user select a file to insert its path.
9
+ */
10
+ export class FilePickerModal {
11
+ constructor(private readonly shellPaths: Pick<ShellPathService, 'workingDirectory'>) {}
12
+
13
+ public active = false;
14
+ public query = '';
15
+ public searchFocused = true;
16
+ public results: string[] = [];
17
+ public selectedIndex = 0;
18
+ /** Position in the prompt where @ was typed — used to replace @query with the selected path */
19
+ public insertPos = 0;
20
+ /** When true, selected file inserts as !@path (inject mode) instead of @path */
21
+ public injectMode = false;
22
+
23
+ public allFiles: string[] = [];
24
+ private filesCached = false;
25
+
26
+
27
+ private onUpdate: (() => void) | null = null;
28
+
29
+ /** Set a callback to trigger re-render when file list loads. */
30
+ setOnUpdate(fn: () => void): void {
31
+ this.onUpdate = fn;
32
+ }
33
+
34
+ /** Activate the file picker at the given prompt position. */
35
+ open(insertPos: number, injectMode = false): void {
36
+ this.active = true;
37
+ this.query = '';
38
+ this.searchFocused = true;
39
+ this.selectedIndex = 0;
40
+ this.insertPos = insertPos;
41
+ this.injectMode = injectMode;
42
+
43
+ if (this.filesCached) {
44
+ this.updateResults();
45
+ } else {
46
+ // Show "Loading..." immediately, load files in background
47
+ this.results = [];
48
+ this.loadFiles().then(() => {
49
+ if (this.active) {
50
+ this.updateResults();
51
+ this.onUpdate?.();
52
+ }
53
+ });
54
+ }
55
+ }
56
+
57
+ /** Close the file picker without selecting. */
58
+ close(): void {
59
+ this.active = false;
60
+ this.query = '';
61
+ this.searchFocused = true;
62
+ this.results = [];
63
+ this.selectedIndex = 0;
64
+ this.injectMode = false;
65
+ }
66
+
67
+ /** Update the search query and re-filter results. */
68
+ setQuery(q: string): void {
69
+ this.query = q;
70
+ this.selectedIndex = 0;
71
+ this.updateResults();
72
+ }
73
+
74
+ canFocusSearch(): boolean {
75
+ return true;
76
+ }
77
+
78
+ focusSearch(): void {
79
+ this.searchFocused = true;
80
+ }
81
+
82
+ blurSearch(): void {
83
+ this.searchFocused = false;
84
+ }
85
+
86
+ /** Move selection up. */
87
+ moveUp(): void {
88
+ if (this.selectedIndex > 0) this.selectedIndex--;
89
+ }
90
+
91
+ /** Move selection down. */
92
+ moveDown(): void {
93
+ if (this.selectedIndex < this.results.length - 1) this.selectedIndex++;
94
+ }
95
+
96
+ /** Get the currently selected file path, or null if none. */
97
+ getSelected(): string | null {
98
+ if (this.results.length === 0) return null;
99
+ return this.results[this.selectedIndex] ?? null;
100
+ }
101
+
102
+ /** Fuzzy match: does the query match the candidate? */
103
+ private fuzzyMatch(query: string, candidate: string): { match: boolean; score: number } {
104
+ if (query.length === 0) return { match: true, score: 0 };
105
+ const lowerQuery = query.toLowerCase();
106
+ const lowerCandidate = candidate.toLowerCase();
107
+
108
+ // Substring match (highest priority)
109
+ const subIdx = lowerCandidate.indexOf(lowerQuery);
110
+ if (subIdx !== -1) {
111
+ // Bonus for matching at start of filename (after last /)
112
+ const lastSlash = lowerCandidate.lastIndexOf('/');
113
+ const filenameStart = lastSlash + 1;
114
+ const isFilenameMatch = subIdx >= filenameStart;
115
+ return { match: true, score: isFilenameMatch ? 100 - subIdx : 50 - subIdx };
116
+ }
117
+
118
+ // Character-by-character fuzzy match
119
+ let qi = 0;
120
+ let score = 0;
121
+ for (let ci = 0; ci < lowerCandidate.length && qi < lowerQuery.length; ci++) {
122
+ if (lowerCandidate[ci] === lowerQuery[qi]) {
123
+ qi++;
124
+ score += 1;
125
+ }
126
+ }
127
+ if (qi === lowerQuery.length) {
128
+ return { match: true, score };
129
+ }
130
+ return { match: false, score: 0 };
131
+ }
132
+
133
+ private updateResults(): void {
134
+ if (this.query.length === 0) {
135
+ this.results = this.allFiles;
136
+ return;
137
+ }
138
+
139
+ const scored = this.allFiles
140
+ .map(f => ({ file: f, ...this.fuzzyMatch(this.query, f) }))
141
+ .filter(r => r.match)
142
+ .sort((a, b) => b.score - a.score)
143
+ ;
144
+
145
+ this.results = scored.map(r => r.file);
146
+ if (this.selectedIndex >= this.results.length) {
147
+ this.selectedIndex = Math.max(0, this.results.length - 1);
148
+ }
149
+ }
150
+
151
+ private async loadFiles(): Promise<void> {
152
+ const root = this.shellPaths.workingDirectory;
153
+ const files: string[] = [];
154
+ await this.walkDir(root, files, 0);
155
+ this.allFiles = files.sort();
156
+ this.filesCached = true;
157
+ }
158
+
159
+ private async walkDir(dir: string, files: string[], depth: number): Promise<void> {
160
+ if (depth > 8) return; // Limit depth
161
+ if (files.length > 5000) return; // Limit total files
162
+
163
+ let entries: import('node:fs').Dirent[];
164
+ try {
165
+ entries = (await readdir(dir, { withFileTypes: true })) as unknown as import('node:fs').Dirent[];
166
+ } catch {
167
+ return;
168
+ }
169
+
170
+ for (const entry of entries) {
171
+ // Skip hidden dirs, node_modules, dist, .git
172
+ if (entry.name.startsWith('.')) continue;
173
+ if (entry.name === 'node_modules' || entry.name === 'dist') continue;
174
+
175
+ const fullPath = join(dir, entry.name);
176
+ const relPath = relative(this.shellPaths.workingDirectory, fullPath);
177
+
178
+ if (entry.isDirectory()) {
179
+ files.push(relPath + '/');
180
+ await this.walkDir(fullPath, files, depth + 1);
181
+ } else if (entry.isFile()) {
182
+ files.push(relPath);
183
+ }
184
+ }
185
+ }
186
+
187
+ /** Invalidate the file cache (e.g., after file operations). */
188
+ invalidateCache(): void {
189
+ this.filesCached = false;
190
+ this.allFiles = [];
191
+ }
192
+ }