gsd-pi 2.10.12 → 2.12.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 (504) hide show
  1. package/dist/bundled-extension-paths.d.ts +2 -0
  2. package/dist/bundled-extension-paths.js +10 -0
  3. package/dist/loader.js +45 -28
  4. package/dist/onboarding.js +100 -0
  5. package/dist/resource-loader.js +12 -3
  6. package/dist/resources/GSD-WORKFLOW.md +661 -0
  7. package/dist/resources/agents/researcher.md +29 -0
  8. package/dist/resources/agents/scout.md +56 -0
  9. package/dist/resources/agents/worker.md +31 -0
  10. package/dist/resources/extensions/ask-user-questions.ts +289 -0
  11. package/dist/resources/extensions/async-jobs/async-bash-tool.ts +211 -0
  12. package/dist/resources/extensions/async-jobs/await-tool.ts +101 -0
  13. package/dist/resources/extensions/async-jobs/cancel-job-tool.ts +34 -0
  14. package/dist/resources/extensions/async-jobs/index.ts +133 -0
  15. package/dist/resources/extensions/async-jobs/job-manager.ts +211 -0
  16. package/dist/resources/extensions/bg-shell/index.ts +3179 -0
  17. package/dist/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
  18. package/dist/resources/extensions/browser-tools/capture.ts +165 -0
  19. package/dist/resources/extensions/browser-tools/core.d.ts +205 -0
  20. package/dist/resources/extensions/browser-tools/core.js +1057 -0
  21. package/dist/resources/extensions/browser-tools/evaluate-helpers.ts +184 -0
  22. package/dist/resources/extensions/browser-tools/index.ts +51 -0
  23. package/dist/resources/extensions/browser-tools/lifecycle.ts +270 -0
  24. package/dist/resources/extensions/browser-tools/package.json +24 -0
  25. package/dist/resources/extensions/browser-tools/refs.ts +264 -0
  26. package/dist/resources/extensions/browser-tools/settle.ts +197 -0
  27. package/dist/resources/extensions/browser-tools/state.ts +408 -0
  28. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +652 -0
  29. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +614 -0
  30. package/dist/resources/extensions/browser-tools/tools/assertions.ts +342 -0
  31. package/dist/resources/extensions/browser-tools/tools/forms.ts +801 -0
  32. package/dist/resources/extensions/browser-tools/tools/inspection.ts +492 -0
  33. package/dist/resources/extensions/browser-tools/tools/intent.ts +614 -0
  34. package/dist/resources/extensions/browser-tools/tools/interaction.ts +865 -0
  35. package/dist/resources/extensions/browser-tools/tools/navigation.ts +232 -0
  36. package/dist/resources/extensions/browser-tools/tools/pages.ts +303 -0
  37. package/dist/resources/extensions/browser-tools/tools/refs.ts +541 -0
  38. package/dist/resources/extensions/browser-tools/tools/screenshot.ts +83 -0
  39. package/dist/resources/extensions/browser-tools/tools/session.ts +400 -0
  40. package/dist/resources/extensions/browser-tools/tools/wait.ts +247 -0
  41. package/dist/resources/extensions/browser-tools/utils.ts +660 -0
  42. package/dist/resources/extensions/context7/index.ts +428 -0
  43. package/dist/resources/extensions/context7/package.json +11 -0
  44. package/dist/resources/extensions/get-secrets-from-user.ts +625 -0
  45. package/dist/resources/extensions/google-search/index.ts +336 -0
  46. package/dist/resources/extensions/google-search/package.json +9 -0
  47. package/dist/resources/extensions/gsd/activity-log.ts +116 -0
  48. package/dist/resources/extensions/gsd/auto.ts +3732 -0
  49. package/dist/resources/extensions/gsd/commands.ts +544 -0
  50. package/dist/resources/extensions/gsd/crash-recovery.ts +105 -0
  51. package/dist/resources/extensions/gsd/dashboard-overlay.ts +564 -0
  52. package/dist/resources/extensions/gsd/dispatch-guard.ts +78 -0
  53. package/dist/resources/extensions/gsd/docs/preferences-reference.md +278 -0
  54. package/dist/resources/extensions/gsd/doctor.ts +766 -0
  55. package/dist/resources/extensions/gsd/exit-command.ts +18 -0
  56. package/dist/resources/extensions/gsd/files.ts +857 -0
  57. package/dist/resources/extensions/gsd/git-service.ts +904 -0
  58. package/dist/resources/extensions/gsd/gitignore.ts +200 -0
  59. package/dist/resources/extensions/gsd/guided-flow.ts +1054 -0
  60. package/dist/resources/extensions/gsd/index.ts +735 -0
  61. package/dist/resources/extensions/gsd/metrics.ts +374 -0
  62. package/dist/resources/extensions/gsd/migrate/command.ts +218 -0
  63. package/dist/resources/extensions/gsd/migrate/index.ts +42 -0
  64. package/dist/resources/extensions/gsd/migrate/parser.ts +323 -0
  65. package/dist/resources/extensions/gsd/migrate/parsers.ts +624 -0
  66. package/dist/resources/extensions/gsd/migrate/preview.ts +48 -0
  67. package/dist/resources/extensions/gsd/migrate/transformer.ts +346 -0
  68. package/dist/resources/extensions/gsd/migrate/types.ts +370 -0
  69. package/dist/resources/extensions/gsd/migrate/validator.ts +55 -0
  70. package/dist/resources/extensions/gsd/migrate/writer.ts +539 -0
  71. package/dist/resources/extensions/gsd/native-git-bridge.ts +181 -0
  72. package/dist/resources/extensions/gsd/native-parser-bridge.ts +135 -0
  73. package/dist/resources/extensions/gsd/observability-validator.ts +408 -0
  74. package/dist/resources/extensions/gsd/package.json +11 -0
  75. package/dist/resources/extensions/gsd/paths.ts +339 -0
  76. package/dist/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  77. package/dist/resources/extensions/gsd/preferences.ts +988 -0
  78. package/dist/resources/extensions/gsd/prompt-loader.ts +92 -0
  79. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +25 -0
  80. package/dist/resources/extensions/gsd/prompts/complete-slice.md +27 -0
  81. package/dist/resources/extensions/gsd/prompts/discuss.md +237 -0
  82. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +29 -0
  83. package/dist/resources/extensions/gsd/prompts/execute-task.md +63 -0
  84. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -0
  85. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -0
  86. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +61 -0
  87. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +3 -0
  88. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +29 -0
  89. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -0
  90. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +13 -0
  91. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -0
  92. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +78 -0
  93. package/dist/resources/extensions/gsd/prompts/plan-slice.md +55 -0
  94. package/dist/resources/extensions/gsd/prompts/queue.md +100 -0
  95. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +48 -0
  96. package/dist/resources/extensions/gsd/prompts/replan-slice.md +39 -0
  97. package/dist/resources/extensions/gsd/prompts/research-milestone.md +37 -0
  98. package/dist/resources/extensions/gsd/prompts/research-slice.md +28 -0
  99. package/dist/resources/extensions/gsd/prompts/review-migration.md +66 -0
  100. package/dist/resources/extensions/gsd/prompts/run-uat.md +109 -0
  101. package/dist/resources/extensions/gsd/prompts/system.md +190 -0
  102. package/dist/resources/extensions/gsd/prompts/worktree-merge.md +123 -0
  103. package/dist/resources/extensions/gsd/roadmap-slices.ts +50 -0
  104. package/dist/resources/extensions/gsd/session-forensics.ts +500 -0
  105. package/dist/resources/extensions/gsd/skill-discovery.ts +137 -0
  106. package/dist/resources/extensions/gsd/state.ts +569 -0
  107. package/dist/resources/extensions/gsd/templates/context.md +76 -0
  108. package/dist/resources/extensions/gsd/templates/decisions.md +8 -0
  109. package/dist/resources/extensions/gsd/templates/milestone-summary.md +73 -0
  110. package/dist/resources/extensions/gsd/templates/plan.md +131 -0
  111. package/dist/resources/extensions/gsd/templates/preferences.md +23 -0
  112. package/dist/resources/extensions/gsd/templates/project.md +31 -0
  113. package/dist/resources/extensions/gsd/templates/reassessment.md +28 -0
  114. package/dist/resources/extensions/gsd/templates/requirements.md +81 -0
  115. package/dist/resources/extensions/gsd/templates/research.md +46 -0
  116. package/dist/resources/extensions/gsd/templates/roadmap.md +118 -0
  117. package/dist/resources/extensions/gsd/templates/secrets-manifest.md +22 -0
  118. package/dist/resources/extensions/gsd/templates/slice-context.md +58 -0
  119. package/dist/resources/extensions/gsd/templates/slice-summary.md +99 -0
  120. package/dist/resources/extensions/gsd/templates/state.md +19 -0
  121. package/dist/resources/extensions/gsd/templates/task-plan.md +52 -0
  122. package/dist/resources/extensions/gsd/templates/task-summary.md +57 -0
  123. package/dist/resources/extensions/gsd/templates/uat.md +54 -0
  124. package/dist/resources/extensions/gsd/tests/activity-log-prune.test.ts +297 -0
  125. package/dist/resources/extensions/gsd/tests/activity-log-save.test.ts +127 -0
  126. package/dist/resources/extensions/gsd/tests/auto-draft-pause.test.ts +109 -0
  127. package/dist/resources/extensions/gsd/tests/auto-preflight.test.ts +45 -0
  128. package/dist/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +196 -0
  129. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
  130. package/dist/resources/extensions/gsd/tests/collect-from-manifest.test.ts +469 -0
  131. package/dist/resources/extensions/gsd/tests/complete-milestone.test.ts +200 -0
  132. package/dist/resources/extensions/gsd/tests/cost-projection.test.ts +134 -0
  133. package/dist/resources/extensions/gsd/tests/derive-state-deps.test.ts +312 -0
  134. package/dist/resources/extensions/gsd/tests/derive-state-draft.test.ts +299 -0
  135. package/dist/resources/extensions/gsd/tests/derive-state.test.ts +660 -0
  136. package/dist/resources/extensions/gsd/tests/discuss-prompt.test.ts +27 -0
  137. package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +91 -0
  138. package/dist/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +170 -0
  139. package/dist/resources/extensions/gsd/tests/doctor.test.ts +594 -0
  140. package/dist/resources/extensions/gsd/tests/draft-promotion.test.ts +169 -0
  141. package/dist/resources/extensions/gsd/tests/exit-command.test.ts +50 -0
  142. package/dist/resources/extensions/gsd/tests/git-service.test.ts +1788 -0
  143. package/dist/resources/extensions/gsd/tests/idle-recovery.test.ts +577 -0
  144. package/dist/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +580 -0
  145. package/dist/resources/extensions/gsd/tests/manifest-status.test.ts +283 -0
  146. package/dist/resources/extensions/gsd/tests/metrics-io.test.ts +176 -0
  147. package/dist/resources/extensions/gsd/tests/metrics.test.ts +188 -0
  148. package/dist/resources/extensions/gsd/tests/migrate-command.test.ts +369 -0
  149. package/dist/resources/extensions/gsd/tests/migrate-parser.test.ts +757 -0
  150. package/dist/resources/extensions/gsd/tests/migrate-transformer.test.ts +635 -0
  151. package/dist/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +414 -0
  152. package/dist/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +297 -0
  153. package/dist/resources/extensions/gsd/tests/migrate-writer.test.ts +398 -0
  154. package/dist/resources/extensions/gsd/tests/must-have-parser.test.ts +291 -0
  155. package/dist/resources/extensions/gsd/tests/network-error-fallback.test.ts +54 -0
  156. package/dist/resources/extensions/gsd/tests/next-milestone-id.test.ts +66 -0
  157. package/dist/resources/extensions/gsd/tests/orphaned-branch.test.ts +353 -0
  158. package/dist/resources/extensions/gsd/tests/parsers.test.ts +1664 -0
  159. package/dist/resources/extensions/gsd/tests/plan-milestone.test.ts +133 -0
  160. package/dist/resources/extensions/gsd/tests/plan-quality-validator.test.ts +363 -0
  161. package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  162. package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  163. package/dist/resources/extensions/gsd/tests/queue-draft-detection.test.ts +126 -0
  164. package/dist/resources/extensions/gsd/tests/reassess-prompt.test.ts +142 -0
  165. package/dist/resources/extensions/gsd/tests/regex-hardening.test.ts +281 -0
  166. package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +155 -0
  167. package/dist/resources/extensions/gsd/tests/remote-status.test.ts +99 -0
  168. package/dist/resources/extensions/gsd/tests/replan-slice.test.ts +493 -0
  169. package/dist/resources/extensions/gsd/tests/requirements.test.ts +106 -0
  170. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +35 -0
  171. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +11 -0
  172. package/dist/resources/extensions/gsd/tests/roadmap-slices.test.ts +41 -0
  173. package/dist/resources/extensions/gsd/tests/run-uat.test.ts +316 -0
  174. package/dist/resources/extensions/gsd/tests/secure-env-collect.test.ts +185 -0
  175. package/dist/resources/extensions/gsd/tests/smart-entry-draft.test.ts +123 -0
  176. package/dist/resources/extensions/gsd/tests/test-helpers.ts +61 -0
  177. package/dist/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +219 -0
  178. package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +234 -0
  179. package/dist/resources/extensions/gsd/tests/workspace-index.test.ts +75 -0
  180. package/dist/resources/extensions/gsd/tests/worktree-integration.test.ts +234 -0
  181. package/dist/resources/extensions/gsd/tests/worktree-manager.test.ts +141 -0
  182. package/dist/resources/extensions/gsd/tests/worktree.test.ts +597 -0
  183. package/dist/resources/extensions/gsd/tests/write-gate.test.ts +122 -0
  184. package/dist/resources/extensions/gsd/types.ts +296 -0
  185. package/dist/resources/extensions/gsd/unit-runtime.ts +184 -0
  186. package/dist/resources/extensions/gsd/workspace-index.ts +189 -0
  187. package/dist/resources/extensions/gsd/worktree-command.ts +845 -0
  188. package/dist/resources/extensions/gsd/worktree-manager.ts +459 -0
  189. package/dist/resources/extensions/gsd/{worktree.js → worktree.ts} +92 -61
  190. package/dist/resources/extensions/mac-tools/index.ts +852 -0
  191. package/dist/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
  192. package/dist/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
  193. package/dist/resources/extensions/mcporter/index.ts +429 -0
  194. package/dist/resources/extensions/remote-questions/config.ts +81 -0
  195. package/dist/resources/extensions/remote-questions/discord-adapter.ts +128 -0
  196. package/dist/resources/extensions/remote-questions/format.ts +163 -0
  197. package/dist/resources/extensions/remote-questions/manager.ts +192 -0
  198. package/dist/resources/extensions/remote-questions/remote-command.ts +361 -0
  199. package/dist/resources/extensions/remote-questions/slack-adapter.ts +92 -0
  200. package/dist/resources/extensions/remote-questions/status.ts +31 -0
  201. package/dist/resources/extensions/remote-questions/store.ts +77 -0
  202. package/dist/resources/extensions/remote-questions/types.ts +75 -0
  203. package/dist/resources/extensions/search-the-web/cache.ts +78 -0
  204. package/dist/resources/extensions/search-the-web/command-search-provider.ts +99 -0
  205. package/dist/resources/extensions/search-the-web/format.ts +258 -0
  206. package/dist/resources/extensions/search-the-web/http.ts +238 -0
  207. package/dist/resources/extensions/search-the-web/index.ts +65 -0
  208. package/dist/resources/extensions/search-the-web/native-search.ts +165 -0
  209. package/dist/resources/extensions/search-the-web/provider.ts +136 -0
  210. package/dist/resources/extensions/search-the-web/tavily.ts +116 -0
  211. package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +581 -0
  212. package/dist/resources/extensions/search-the-web/tool-llm-context.ts +620 -0
  213. package/dist/resources/extensions/search-the-web/tool-search.ts +635 -0
  214. package/dist/resources/extensions/search-the-web/url-utils.ts +91 -0
  215. package/dist/resources/extensions/shared/bundled-extension-paths.ts +11 -0
  216. package/dist/resources/extensions/shared/confirm-ui.ts +126 -0
  217. package/dist/resources/extensions/shared/interview-ui.ts +613 -0
  218. package/dist/resources/extensions/shared/next-action-ui.ts +197 -0
  219. package/dist/resources/extensions/shared/progress-widget.ts +282 -0
  220. package/dist/resources/extensions/shared/terminal.ts +23 -0
  221. package/dist/resources/extensions/shared/thinking-widget.ts +107 -0
  222. package/dist/resources/extensions/shared/ui.ts +400 -0
  223. package/dist/resources/extensions/shared/wizard-ui.ts +551 -0
  224. package/dist/resources/extensions/slash-commands/audit.ts +88 -0
  225. package/dist/resources/extensions/slash-commands/clear.ts +10 -0
  226. package/dist/resources/extensions/slash-commands/create-extension.ts +297 -0
  227. package/dist/resources/extensions/slash-commands/create-slash-command.ts +234 -0
  228. package/dist/resources/extensions/slash-commands/index.ts +12 -0
  229. package/dist/resources/extensions/subagent/agents.ts +126 -0
  230. package/dist/resources/extensions/subagent/index.ts +1072 -0
  231. package/dist/resources/extensions/subagent/isolation.ts +498 -0
  232. package/dist/resources/extensions/ttsr/index.ts +163 -0
  233. package/dist/resources/extensions/ttsr/rule-loader.ts +121 -0
  234. package/dist/resources/extensions/ttsr/ttsr-interrupt.md +6 -0
  235. package/dist/resources/extensions/ttsr/ttsr-manager.ts +430 -0
  236. package/dist/resources/extensions/universal-config/discovery.ts +78 -0
  237. package/dist/resources/extensions/universal-config/format.ts +160 -0
  238. package/dist/resources/extensions/universal-config/index.ts +118 -0
  239. package/dist/resources/extensions/universal-config/package.json +11 -0
  240. package/dist/resources/extensions/universal-config/scanners.ts +579 -0
  241. package/dist/resources/extensions/universal-config/tests/discovery.test.ts +111 -0
  242. package/dist/resources/extensions/universal-config/tests/format.test.ts +111 -0
  243. package/dist/resources/extensions/universal-config/tests/scanners.test.ts +438 -0
  244. package/dist/resources/extensions/universal-config/tools.ts +60 -0
  245. package/dist/resources/extensions/universal-config/types.ts +116 -0
  246. package/dist/resources/extensions/voice/index.ts +271 -0
  247. package/dist/resources/extensions/voice/speech-recognizer.py +504 -0
  248. package/dist/resources/extensions/voice/speech-recognizer.swift +154 -0
  249. package/dist/resources/skills/debug-like-expert/SKILL.md +231 -0
  250. package/dist/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
  251. package/dist/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
  252. package/dist/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
  253. package/dist/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
  254. package/dist/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
  255. package/dist/resources/skills/frontend-design/SKILL.md +45 -0
  256. package/dist/resources/skills/github-workflows/SKILL.md +92 -0
  257. package/dist/resources/skills/github-workflows/references/gh/SKILL.md +255 -0
  258. package/dist/resources/skills/github-workflows/references/gh/references/issue-stories.md +204 -0
  259. package/dist/resources/skills/github-workflows/references/gh/references/labels.md +170 -0
  260. package/dist/resources/skills/github-workflows/references/gh/references/milestones.md +158 -0
  261. package/dist/resources/skills/github-workflows/references/gh/references/projects-v2.md +177 -0
  262. package/dist/resources/skills/github-workflows/references/gh/scripts/experiment_cleanup.py +191 -0
  263. package/dist/resources/skills/github-workflows/references/gh/scripts/github_project_setup.py +799 -0
  264. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  265. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
  266. package/dist/resources/skills/swiftui/SKILL.md +208 -0
  267. package/dist/resources/skills/swiftui/references/animations.md +921 -0
  268. package/dist/resources/skills/swiftui/references/architecture.md +1561 -0
  269. package/dist/resources/skills/swiftui/references/layout-system.md +1186 -0
  270. package/dist/resources/skills/swiftui/references/navigation.md +1492 -0
  271. package/dist/resources/skills/swiftui/references/networking-async.md +214 -0
  272. package/dist/resources/skills/swiftui/references/performance.md +1706 -0
  273. package/dist/resources/skills/swiftui/references/platform-integration.md +204 -0
  274. package/dist/resources/skills/swiftui/references/state-management.md +1443 -0
  275. package/dist/resources/skills/swiftui/references/swiftdata.md +297 -0
  276. package/dist/resources/skills/swiftui/references/testing-debugging.md +247 -0
  277. package/dist/resources/skills/swiftui/references/uikit-appkit-interop.md +218 -0
  278. package/dist/resources/skills/swiftui/workflows/add-feature.md +191 -0
  279. package/dist/resources/skills/swiftui/workflows/build-new-app.md +311 -0
  280. package/dist/resources/skills/swiftui/workflows/debug-swiftui.md +192 -0
  281. package/dist/resources/skills/swiftui/workflows/optimize-performance.md +197 -0
  282. package/dist/resources/skills/swiftui/workflows/ship-app.md +203 -0
  283. package/dist/resources/skills/swiftui/workflows/write-tests.md +235 -0
  284. package/dist/wizard.js +1 -0
  285. package/package.json +8 -6
  286. package/packages/native/dist/fd/index.d.ts +1 -0
  287. package/packages/native/dist/fd/index.js +1 -0
  288. package/packages/native/dist/grep/index.d.ts +2 -1
  289. package/packages/native/dist/grep/index.js +1 -0
  290. package/packages/native/src/__tests__/fd.test.mjs +35 -0
  291. package/packages/native/src/__tests__/grep.test.mjs +26 -9
  292. package/packages/native/src/fd/index.ts +1 -0
  293. package/packages/native/src/grep/index.ts +3 -2
  294. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  295. package/packages/pi-agent-core/dist/agent-loop.js +169 -55
  296. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  297. package/packages/pi-agent-core/dist/agent.d.ts +13 -1
  298. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  299. package/packages/pi-agent-core/dist/agent.js +16 -0
  300. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  301. package/packages/pi-agent-core/dist/types.d.ts +91 -1
  302. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  303. package/packages/pi-agent-core/dist/types.js.map +1 -1
  304. package/packages/pi-agent-core/src/agent-loop.ts +273 -63
  305. package/packages/pi-agent-core/src/agent.ts +24 -0
  306. package/packages/pi-agent-core/src/types.ts +98 -0
  307. package/packages/pi-ai/dist/env-api-keys.js +2 -0
  308. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  309. package/packages/pi-ai/dist/models.generated.d.ts +314 -0
  310. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  311. package/packages/pi-ai/dist/models.generated.js +236 -0
  312. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  313. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  314. package/packages/pi-ai/dist/providers/google-gemini-cli.js +6 -0
  315. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  316. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  317. package/packages/pi-ai/dist/providers/openai-completions.js +2 -0
  318. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  319. package/packages/pi-ai/dist/types.d.ts +1 -1
  320. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  321. package/packages/pi-ai/dist/types.js.map +1 -1
  322. package/packages/pi-ai/src/env-api-keys.ts +2 -0
  323. package/packages/pi-ai/src/models.generated.ts +236 -0
  324. package/packages/pi-ai/src/providers/google-gemini-cli.ts +8 -0
  325. package/packages/pi-ai/src/providers/openai-completions.ts +3 -0
  326. package/packages/pi-ai/src/types.ts +2 -1
  327. package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  328. package/packages/pi-coding-agent/dist/cli/args.js +1 -0
  329. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  330. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +26 -0
  331. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/agent-session.js +137 -22
  333. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +20 -0
  335. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  336. package/packages/pi-coding-agent/dist/core/auth-storage.js +43 -0
  337. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts +51 -0
  339. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +119 -0
  341. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -0
  342. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.d.ts +2 -0
  343. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +183 -0
  345. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
  347. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/index.js +1 -0
  349. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  351. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  352. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +12 -1
  354. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/session-manager.js +37 -1
  356. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  357. package/packages/pi-coding-agent/dist/core/session-manager.test.d.ts +2 -0
  358. package/packages/pi-coding-agent/dist/core/session-manager.test.d.ts.map +1 -0
  359. package/packages/pi-coding-agent/dist/core/session-manager.test.js +61 -0
  360. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -0
  361. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
  362. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  363. package/packages/pi-coding-agent/dist/core/settings-manager.js +47 -0
  364. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  365. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  366. package/packages/pi-coding-agent/dist/core/tools/find.js +1 -0
  367. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  368. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +6 -15
  370. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +18 -1
  372. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +46 -4
  374. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  375. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  376. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +25 -2
  377. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  378. package/packages/pi-coding-agent/src/cli/args.ts +1 -0
  379. package/packages/pi-coding-agent/src/core/agent-session.ts +167 -22
  380. package/packages/pi-coding-agent/src/core/auth-storage.ts +45 -0
  381. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +229 -0
  382. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +165 -0
  383. package/packages/pi-coding-agent/src/core/index.ts +1 -0
  384. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  385. package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -0
  386. package/packages/pi-coding-agent/src/core/session-manager.ts +51 -1
  387. package/packages/pi-coding-agent/src/core/settings-manager.ts +66 -0
  388. package/packages/pi-coding-agent/src/core/tools/find.ts +1 -0
  389. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +6 -16
  390. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +49 -4
  391. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -2
  392. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  393. package/packages/pi-tui/dist/autocomplete.js +3 -4
  394. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  395. package/packages/pi-tui/dist/components/editor.d.ts +7 -0
  396. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  397. package/packages/pi-tui/dist/components/editor.js +57 -50
  398. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  399. package/packages/pi-tui/src/autocomplete.ts +3 -5
  400. package/packages/pi-tui/src/components/editor.ts +70 -49
  401. package/pkg/dist/core/export-html/ansi-to-html.d.ts +22 -0
  402. package/pkg/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  403. package/pkg/dist/core/export-html/ansi-to-html.js +249 -0
  404. package/pkg/dist/core/export-html/ansi-to-html.js.map +1 -0
  405. package/pkg/dist/core/export-html/index.d.ts +37 -0
  406. package/pkg/dist/core/export-html/index.d.ts.map +1 -0
  407. package/pkg/dist/core/export-html/index.js +223 -0
  408. package/pkg/dist/core/export-html/index.js.map +1 -0
  409. package/pkg/dist/core/export-html/template.css +971 -0
  410. package/pkg/dist/core/export-html/template.html +54 -0
  411. package/pkg/dist/core/export-html/template.js +1583 -0
  412. package/pkg/dist/core/export-html/tool-renderer.d.ts +38 -0
  413. package/pkg/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  414. package/pkg/dist/core/export-html/tool-renderer.js +70 -0
  415. package/pkg/dist/core/export-html/tool-renderer.js.map +1 -0
  416. package/pkg/dist/core/export-html/vendor/highlight.min.js +1213 -0
  417. package/pkg/dist/core/export-html/vendor/marked.min.js +6 -0
  418. package/scripts/postinstall.js +30 -17
  419. package/src/resources/extensions/bg-shell/index.ts +51 -7
  420. package/src/resources/extensions/gsd/activity-log.ts +61 -14
  421. package/src/resources/extensions/gsd/auto.ts +288 -19
  422. package/src/resources/extensions/gsd/commands.ts +9 -3
  423. package/src/resources/extensions/gsd/dashboard-overlay.ts +55 -12
  424. package/src/resources/extensions/gsd/docs/preferences-reference.md +25 -0
  425. package/src/resources/extensions/gsd/doctor.ts +60 -3
  426. package/src/resources/extensions/gsd/files.ts +45 -1
  427. package/src/resources/extensions/gsd/git-service.ts +46 -41
  428. package/src/resources/extensions/gsd/guided-flow.ts +81 -9
  429. package/src/resources/extensions/gsd/index.ts +62 -1
  430. package/src/resources/extensions/gsd/native-git-bridge.ts +181 -0
  431. package/src/resources/extensions/gsd/paths.ts +35 -4
  432. package/src/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  433. package/src/resources/extensions/gsd/preferences.ts +232 -1
  434. package/src/resources/extensions/gsd/prompt-loader.ts +45 -3
  435. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  436. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -3
  437. package/src/resources/extensions/gsd/prompts/discuss.md +10 -8
  438. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  439. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -1
  440. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -1
  441. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  442. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +3 -1
  443. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +4 -2
  444. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -1
  445. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +3 -1
  446. package/src/resources/extensions/gsd/prompts/plan-milestone.md +9 -12
  447. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -3
  448. package/src/resources/extensions/gsd/prompts/queue.md +3 -1
  449. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  450. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  451. package/src/resources/extensions/gsd/state.ts +130 -18
  452. package/src/resources/extensions/gsd/templates/context.md +1 -1
  453. package/src/resources/extensions/gsd/templates/state.md +3 -3
  454. package/src/resources/extensions/gsd/tests/activity-log-save.test.ts +127 -0
  455. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +5 -1
  456. package/src/resources/extensions/gsd/tests/doctor.test.ts +115 -1
  457. package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +6 -2
  458. package/src/resources/extensions/gsd/tests/git-service.test.ts +35 -35
  459. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +8 -8
  460. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +4 -1
  461. package/src/resources/extensions/gsd/tests/network-error-fallback.test.ts +54 -0
  462. package/src/resources/extensions/gsd/tests/orphaned-branch.test.ts +5 -5
  463. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  464. package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  465. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +12 -0
  466. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +6 -0
  467. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +4 -4
  468. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +4 -4
  469. package/src/resources/extensions/gsd/tests/worktree.test.ts +19 -19
  470. package/src/resources/extensions/gsd/types.ts +109 -0
  471. package/src/resources/extensions/gsd/worktree-manager.ts +72 -13
  472. package/src/resources/extensions/gsd/worktree.ts +5 -4
  473. package/src/resources/extensions/search-the-web/command-search-provider.ts +8 -4
  474. package/src/resources/extensions/search-the-web/native-search.ts +32 -23
  475. package/src/resources/extensions/search-the-web/provider.ts +19 -2
  476. package/src/resources/extensions/search-the-web/tool-fetch-page.ts +62 -0
  477. package/src/resources/extensions/search-the-web/tool-llm-context.ts +62 -3
  478. package/src/resources/extensions/search-the-web/tool-search.ts +62 -3
  479. package/src/resources/extensions/shared/bundled-extension-paths.ts +11 -0
  480. package/src/resources/extensions/subagent/index.ts +2 -1
  481. package/src/resources/skills/github-workflows/SKILL.md +5 -0
  482. package/dist/resources/extensions/gsd/git-service.d.ts +0 -225
  483. package/dist/resources/extensions/gsd/git-service.js +0 -756
  484. package/dist/resources/extensions/gsd/preferences.d.ts +0 -122
  485. package/dist/resources/extensions/gsd/preferences.js +0 -616
  486. package/dist/resources/extensions/gsd/worktree.d.ts +0 -106
  487. package/dist/resources/extensions/remote-questions/config.d.ts +0 -14
  488. package/dist/resources/extensions/remote-questions/config.js +0 -68
  489. package/dist/resources/extensions/remote-questions/discord-adapter.d.ts +0 -17
  490. package/dist/resources/extensions/remote-questions/discord-adapter.js +0 -118
  491. package/dist/resources/extensions/remote-questions/format.d.ts +0 -38
  492. package/dist/resources/extensions/remote-questions/format.js +0 -119
  493. package/dist/resources/extensions/remote-questions/manager.d.ts +0 -23
  494. package/dist/resources/extensions/remote-questions/manager.js +0 -161
  495. package/dist/resources/extensions/remote-questions/remote-command.d.ts +0 -6
  496. package/dist/resources/extensions/remote-questions/remote-command.js +0 -358
  497. package/dist/resources/extensions/remote-questions/slack-adapter.d.ts +0 -15
  498. package/dist/resources/extensions/remote-questions/slack-adapter.js +0 -82
  499. package/dist/resources/extensions/remote-questions/status.d.ts +0 -9
  500. package/dist/resources/extensions/remote-questions/status.js +0 -25
  501. package/dist/resources/extensions/remote-questions/store.d.ts +0 -11
  502. package/dist/resources/extensions/remote-questions/store.js +0 -66
  503. package/dist/resources/extensions/remote-questions/types.d.ts +0 -68
  504. package/dist/resources/extensions/remote-questions/types.js +0 -4
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: scout
3
+ description: Fast codebase recon that returns compressed context for handoff to other agents
4
+ tools: read, grep, find, ls, bash
5
+ ---
6
+
7
+ You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything.
8
+
9
+ Your output will be passed to an agent who has NOT seen the files you explored.
10
+
11
+ Thoroughness (infer from task, default medium):
12
+
13
+ - Quick: Targeted lookups, key files only
14
+ - Medium: Follow imports, read critical sections
15
+ - Thorough: Trace all dependencies, check tests/types
16
+
17
+ Strategy:
18
+
19
+ 1. grep/find to locate relevant code
20
+ 2. Read key sections (not entire files)
21
+ 3. Identify types, interfaces, key functions
22
+ 4. Note dependencies between files
23
+
24
+ Output format:
25
+
26
+ ## Files Retrieved
27
+
28
+ List with exact line ranges:
29
+
30
+ 1. `path/to/file.ts` (lines 10-50) - Description of what's here
31
+ 2. `path/to/other.ts` (lines 100-150) - Description
32
+ 3. ...
33
+
34
+ ## Key Code
35
+
36
+ Critical types, interfaces, or functions:
37
+
38
+ ```typescript
39
+ interface Example {
40
+ // actual code from the files
41
+ }
42
+ ```
43
+
44
+ ```typescript
45
+ function keyFunction() {
46
+ // actual implementation
47
+ }
48
+ ```
49
+
50
+ ## Architecture
51
+
52
+ Brief explanation of how the pieces connect.
53
+
54
+ ## Start Here
55
+
56
+ Which file to look at first and why.
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: worker
3
+ description: General-purpose subagent with full capabilities, isolated context
4
+ ---
5
+
6
+ You are a worker agent with full capabilities. You operate in an isolated context window to handle delegated tasks without polluting the main conversation.
7
+
8
+ Work autonomously to complete the assigned task. Use all available tools as needed, with one important restriction:
9
+
10
+ - Do **not** spawn subagents or act as an orchestrator unless the parent task explicitly instructs you to do so.
11
+ - If the task looks like GSD orchestration, planning, scouting, parallel dispatch, or review routing, stop and report that the caller should use the appropriate specialist agent instead (for example: `gsd-worker`, `gsd-scout`, `gsd-reviewer`, or the top-level orchestrator).
12
+ - In particular, do **not** call `gsd_scout`, `subagent`, `launch_parallel_view`, or `gsd_execute_parallel` on your own initiative.
13
+
14
+ Output format when finished:
15
+
16
+ ## Completed
17
+
18
+ What was done.
19
+
20
+ ## Files Changed
21
+
22
+ - `path/to/file.ts` - what changed
23
+
24
+ ## Notes (if any)
25
+
26
+ Anything the main agent should know.
27
+
28
+ If handing off to another agent (e.g. reviewer), include:
29
+
30
+ - Exact file paths changed
31
+ - Key functions/types touched (short list)
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Request User Input — LLM tool for asking the user questions
3
+ *
4
+ * Thin wrapper around the shared interview-ui. The LLM presents 1-3
5
+ * questions with 2-3 options each. Each question can be single-select (default)
6
+ * or multi-select (allowMultiple: true). A free-form "None of the above" option
7
+ * is added automatically to single-select questions.
8
+ *
9
+ * Based on: https://github.com/openai/codex (codex-rs/core/src/tools/handlers/ask_user_questions.rs)
10
+ */
11
+
12
+ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
13
+ import { Text } from "@gsd/pi-tui";
14
+ import { Type } from "@sinclair/typebox";
15
+ import {
16
+ showInterviewRound,
17
+ type Question,
18
+ type QuestionOption,
19
+ type RoundResult,
20
+ } from "./shared/interview-ui.js";
21
+
22
+ // ─── Types ────────────────────────────────────────────────────────────────────
23
+
24
+ interface LocalResultDetails {
25
+ remote?: false;
26
+ questions: Question[];
27
+ response: RoundResult | null;
28
+ cancelled: boolean;
29
+ }
30
+
31
+ interface RemoteResultDetails {
32
+ remote: true;
33
+ channel: string;
34
+ timed_out: boolean;
35
+ promptId?: string;
36
+ threadUrl?: string;
37
+ status?: string;
38
+ questions?: Question[];
39
+ response?: import("./remote-questions/types.js").RemoteAnswer;
40
+ error?: boolean;
41
+ }
42
+
43
+ type AskUserQuestionsDetails = LocalResultDetails | RemoteResultDetails;
44
+
45
+ // ─── Schema ───────────────────────────────────────────────────────────────────
46
+
47
+ const OptionSchema = Type.Object({
48
+ label: Type.String({ description: "User-facing label (1-5 words)" }),
49
+ description: Type.String({ description: "One short sentence explaining impact/tradeoff if selected" }),
50
+ });
51
+
52
+ const QuestionSchema = Type.Object({
53
+ id: Type.String({ description: "Stable identifier for mapping answers (snake_case)" }),
54
+ header: Type.String({ description: "Short header label shown in the UI (12 or fewer chars)" }),
55
+ question: Type.String({ description: "Single-sentence prompt shown to the user" }),
56
+ options: Type.Array(OptionSchema, {
57
+ description:
58
+ 'Provide 2-3 mutually exclusive choices for single-select, or any number for multi-select. Put the recommended option first and suffix its label with "(Recommended)". Do not include an "Other" option for single-select; the client adds a free-form "None of the above" option automatically.',
59
+ }),
60
+ allowMultiple: Type.Optional(
61
+ Type.Boolean({
62
+ description:
63
+ "If true, the user can select multiple options using SPACE to toggle and ENTER to confirm. No 'None of the above' option is added. Default: false.",
64
+ }),
65
+ ),
66
+ });
67
+
68
+ const AskUserQuestionsParams = Type.Object({
69
+ questions: Type.Array(QuestionSchema, {
70
+ description: "Questions to show the user. Prefer 1 and do not exceed 3.",
71
+ }),
72
+ });
73
+
74
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
75
+
76
+ const OTHER_OPTION_LABEL = "None of the above";
77
+
78
+ function errorResult(
79
+ message: string,
80
+ questions: Question[] = [],
81
+ ): { content: { type: "text"; text: string }[]; details: AskUserQuestionsDetails } {
82
+ return {
83
+ content: [{ type: "text", text: message }],
84
+ details: { questions, response: null, cancelled: true },
85
+ };
86
+ }
87
+
88
+ /** Convert the shared RoundResult into the JSON the LLM expects. */
89
+ function formatForLLM(result: RoundResult): string {
90
+ const answers: Record<string, { answers: string[] }> = {};
91
+ for (const [id, answer] of Object.entries(result.answers)) {
92
+ const list: string[] = [];
93
+ if (Array.isArray(answer.selected)) {
94
+ list.push(...answer.selected);
95
+ } else {
96
+ list.push(answer.selected);
97
+ }
98
+ if (answer.notes) {
99
+ list.push(`user_note: ${answer.notes}`);
100
+ }
101
+ answers[id] = { answers: list };
102
+ }
103
+ return JSON.stringify({ answers });
104
+ }
105
+
106
+ // ─── Extension ────────────────────────────────────────────────────────────────
107
+
108
+ export default function AskUserQuestions(pi: ExtensionAPI) {
109
+ pi.registerTool({
110
+ name: "ask_user_questions",
111
+ label: "Request User Input",
112
+ description:
113
+ "Request user input for one to three short questions and wait for the response. Single-select questions have 2-3 mutually exclusive options with a free-form 'None of the above' added automatically. Multi-select questions (allowMultiple: true) let the user toggle multiple options with SPACE and confirm with ENTER.",
114
+ promptGuidelines: [
115
+ "Use ask_user_questions when you need the user to choose between concrete alternatives before proceeding.",
116
+ "Keep questions to 1 when possible; never exceed 3.",
117
+ "For single-select: each question must have 2-3 options. Put the recommended option first with '(Recommended)' suffix. Do not include an 'Other' or 'None of the above' option - the client adds one automatically.",
118
+ "For multi-select: set allowMultiple: true. The user can pick any number of options. No 'None of the above' is added.",
119
+ ],
120
+ parameters: AskUserQuestionsParams,
121
+
122
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
123
+ // Validation
124
+ if (params.questions.length === 0 || params.questions.length > 3) {
125
+ return errorResult("Error: questions must contain 1-3 items", params.questions);
126
+ }
127
+
128
+ for (const q of params.questions) {
129
+ if (!q.options || q.options.length === 0) {
130
+ return errorResult(
131
+ `Error: ask_user_questions requires non-empty options for every question (question "${q.id}" has none)`,
132
+ params.questions,
133
+ );
134
+ }
135
+ }
136
+
137
+ if (!ctx.hasUI) {
138
+ const { tryRemoteQuestions } = await import("./remote-questions/manager.js");
139
+ const remoteResult = await tryRemoteQuestions(params.questions, signal);
140
+ if (remoteResult) return { ...remoteResult, details: remoteResult.details as unknown };
141
+ return errorResult("Error: UI not available (non-interactive mode)", params.questions);
142
+ }
143
+
144
+ // Delegate to shared interview UI
145
+ const result = await showInterviewRound(params.questions, {}, ctx as any);
146
+
147
+ // RPC mode fallback: custom() returns undefined, so showInterviewRound
148
+ // may return undefined. Fall back to sequential ctx.ui.select() calls.
149
+ if (!result) {
150
+ const answers: Record<string, { answers: string[] }> = {};
151
+ for (const q of params.questions) {
152
+ const options = q.options.map((o) => o.label);
153
+ if (!q.allowMultiple) {
154
+ options.push(OTHER_OPTION_LABEL);
155
+ }
156
+ const selected = await ctx.ui.select(
157
+ `${q.header}: ${q.question}`,
158
+ options,
159
+ { signal, ...(q.allowMultiple ? { allowMultiple: true } : {}) },
160
+ );
161
+ if (selected === undefined) {
162
+ return errorResult("ask_user_questions was cancelled", params.questions);
163
+ }
164
+ answers[q.id] = {
165
+ answers: Array.isArray(selected) ? selected : [selected],
166
+ };
167
+ }
168
+ const roundResult: RoundResult = {
169
+ endInterview: false,
170
+ answers: Object.fromEntries(
171
+ Object.entries(answers).map(([id, a]) => [
172
+ id,
173
+ { selected: a.answers.length === 1 ? a.answers[0] : a.answers, notes: "" },
174
+ ]),
175
+ ),
176
+ };
177
+ return {
178
+ content: [{ type: "text" as const, text: JSON.stringify({ answers }) }],
179
+ details: {
180
+ questions: params.questions,
181
+ response: roundResult,
182
+ cancelled: false,
183
+ } satisfies LocalResultDetails,
184
+ };
185
+ }
186
+
187
+ // Check if cancelled (empty answers = user exited)
188
+ const hasAnswers = Object.keys(result.answers).length > 0;
189
+ if (!hasAnswers) {
190
+ return {
191
+ content: [{ type: "text", text: "ask_user_questions was cancelled before receiving a response" }],
192
+ details: { questions: params.questions, response: null, cancelled: true } satisfies LocalResultDetails,
193
+ };
194
+ }
195
+
196
+ return {
197
+ content: [{ type: "text", text: formatForLLM(result) }],
198
+ details: { questions: params.questions, response: result, cancelled: false } satisfies LocalResultDetails,
199
+ };
200
+ },
201
+
202
+ // ─── Rendering ────────────────────────────────────────────────────────
203
+
204
+ renderCall(args, theme) {
205
+ const qs = (args.questions as Question[]) || [];
206
+ let text = theme.fg("toolTitle", theme.bold("ask_user_questions "));
207
+ text += theme.fg("muted", `${qs.length} question${qs.length !== 1 ? "s" : ""}`);
208
+ if (qs.length > 0) {
209
+ const headers = qs.map((q) => q.header).join(", ");
210
+ text += theme.fg("dim", ` (${headers})`);
211
+ }
212
+ for (const q of qs) {
213
+ const multiSel = !!q.allowMultiple;
214
+ text += `\n ${theme.fg("text", q.question)}`;
215
+ const optLabels = multiSel
216
+ ? (q.options || []).map((o: QuestionOption) => o.label)
217
+ : [...(q.options || []).map((o: QuestionOption) => o.label), OTHER_OPTION_LABEL];
218
+ const prefix = multiSel ? "☐" : "";
219
+ const numbered = optLabels.map((l, i) => `${prefix}${i + 1}. ${l}`).join(", ");
220
+ text += `\n ${theme.fg("dim", numbered)}`;
221
+ }
222
+ return new Text(text, 0, 0);
223
+ },
224
+
225
+ renderResult(result, _options, theme) {
226
+ const details = result.details as AskUserQuestionsDetails | undefined;
227
+ if (!details) {
228
+ const text = result.content[0];
229
+ return new Text(text?.type === "text" ? text.text : "", 0, 0);
230
+ }
231
+
232
+ // Remote channel result (discriminated on details.remote === true)
233
+ if (details.remote) {
234
+ if (details.timed_out) {
235
+ return new Text(
236
+ `${theme.fg("warning", `${details.channel} — timed out`)}${details.threadUrl ? theme.fg("dim", ` ${details.threadUrl}`) : ""}`,
237
+ 0,
238
+ 0,
239
+ );
240
+ }
241
+
242
+ const questions = (details.questions ?? []) as Question[];
243
+ const lines: string[] = [];
244
+ lines.push(theme.fg("dim", details.channel));
245
+ if (details.response) {
246
+ for (const q of questions) {
247
+ const answer = details.response.answers[q.id];
248
+ if (!answer) {
249
+ lines.push(`${theme.fg("accent", q.header)}: ${theme.fg("dim", "(no answer)")}`);
250
+ continue;
251
+ }
252
+ const answerText = answer.answers.length > 0 ? answer.answers.join(", ") : "(custom)";
253
+ let line = `${theme.fg("success", "✓ ")}${theme.fg("accent", q.header)}: ${answerText}`;
254
+ if (answer.user_note) {
255
+ line += ` ${theme.fg("muted", `[note: ${answer.user_note}]`)}`;
256
+ }
257
+ lines.push(line);
258
+ }
259
+ }
260
+ return new Text(lines.join("\n"), 0, 0);
261
+ }
262
+
263
+ if (details.cancelled || !details.response) {
264
+ return new Text(theme.fg("warning", "Cancelled"), 0, 0);
265
+ }
266
+
267
+ const lines: string[] = [];
268
+ for (const q of details.questions) {
269
+ const answer = (details.response as RoundResult).answers[q.id];
270
+ if (!answer) {
271
+ lines.push(`${theme.fg("accent", q.header)}: ${theme.fg("dim", "(no answer)")}`);
272
+ continue;
273
+ }
274
+ const selected = answer.selected;
275
+ const notes = answer.notes;
276
+ const multiSel = !!q.allowMultiple;
277
+ const answerText = multiSel && Array.isArray(selected)
278
+ ? selected.join(", ")
279
+ : (Array.isArray(selected) ? selected[0] : selected) ?? "(no answer)";
280
+ let line = `${theme.fg("success", "✓ ")}${theme.fg("accent", q.header)}: ${answerText}`;
281
+ if (notes) {
282
+ line += ` ${theme.fg("muted", `[note: ${notes}]`)}`;
283
+ }
284
+ lines.push(line);
285
+ }
286
+ return new Text(lines.join("\n"), 0, 0);
287
+ },
288
+ });
289
+ }
@@ -0,0 +1,211 @@
1
+ /**
2
+ * async_bash tool — run a bash command in the background.
3
+ *
4
+ * Registers the command with the AsyncJobManager and returns a job ID
5
+ * immediately. The LLM can continue working and check results later
6
+ * with await_job.
7
+ */
8
+
9
+ import type { ToolDefinition } from "@gsd/pi-coding-agent";
10
+ import {
11
+ getShellConfig,
12
+ sanitizeCommand,
13
+ DEFAULT_MAX_BYTES,
14
+ DEFAULT_MAX_LINES,
15
+ } from "@gsd/pi-coding-agent";
16
+ import { Type } from "@sinclair/typebox";
17
+ import { spawn } from "node:child_process";
18
+ import { createWriteStream } from "node:fs";
19
+ import { tmpdir } from "node:os";
20
+ import { join } from "node:path";
21
+ import { randomBytes } from "node:crypto";
22
+ import type { AsyncJobManager } from "./job-manager.js";
23
+
24
+ const schema = Type.Object({
25
+ command: Type.String({ description: "Bash command to execute in the background" }),
26
+ timeout: Type.Optional(
27
+ Type.Number({ description: "Timeout in seconds (optional)" }),
28
+ ),
29
+ label: Type.Optional(
30
+ Type.String({ description: "Short label for the job (shown in /jobs). Defaults to a truncated version of the command." }),
31
+ ),
32
+ });
33
+
34
+ function getTempFilePath(): string {
35
+ const id = randomBytes(8).toString("hex");
36
+ return join(tmpdir(), `pi-async-bash-${id}.log`);
37
+ }
38
+
39
+ /**
40
+ * Kill a process and its children. Uses process group kill on Unix.
41
+ */
42
+ function killTree(pid: number): void {
43
+ try {
44
+ // Kill the process group (negative PID)
45
+ process.kill(-pid, "SIGTERM");
46
+ } catch {
47
+ try {
48
+ process.kill(pid, "SIGTERM");
49
+ } catch {
50
+ // Already exited
51
+ }
52
+ }
53
+ }
54
+
55
+ export function createAsyncBashTool(
56
+ getManager: () => AsyncJobManager,
57
+ getCwd: () => string,
58
+ ): ToolDefinition<typeof schema> {
59
+ return {
60
+ name: "async_bash",
61
+ label: "Background Bash",
62
+ description:
63
+ `Run a bash command in the background. Returns a job ID immediately so you can continue working. ` +
64
+ `Use await_job to get results or cancel_job to stop. Ideal for long-running builds, tests, or installs. ` +
65
+ `Output is truncated to the last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB.`,
66
+ promptSnippet: "Run a bash command in the background, returning a job ID immediately.",
67
+ promptGuidelines: [
68
+ "Use async_bash for commands that take more than a few seconds (builds, tests, installs, large git operations).",
69
+ "After starting async jobs, continue with other work and use await_job when you need the results.",
70
+ "Use cancel_job to stop a running background job.",
71
+ "Check /jobs to see all running and recent background jobs.",
72
+ ],
73
+ parameters: schema,
74
+ async execute(_toolCallId, params) {
75
+ const manager = getManager();
76
+ const cwd = getCwd();
77
+ const { command, timeout, label } = params;
78
+ const shortCmd = label ?? (command.length > 60 ? command.slice(0, 57) + "..." : command);
79
+
80
+ const jobId = manager.register("bash", shortCmd, (signal) => {
81
+ return executeBashInBackground(command, cwd, signal, timeout);
82
+ });
83
+
84
+ return {
85
+ content: [{
86
+ type: "text",
87
+ text: [
88
+ `Background job started: **${jobId}**`,
89
+ `Command: \`${shortCmd}\``,
90
+ "",
91
+ "Use `await_job` to get results when ready, or `cancel_job` to stop.",
92
+ ].join("\n"),
93
+ }],
94
+ };
95
+ },
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Execute a bash command, collecting output. Returns the text result.
101
+ */
102
+ function executeBashInBackground(
103
+ command: string,
104
+ cwd: string,
105
+ signal: AbortSignal,
106
+ timeout?: number,
107
+ ): Promise<string> {
108
+ return new Promise<string>((resolve, reject) => {
109
+ const { shell, args } = getShellConfig();
110
+ const resolvedCommand = sanitizeCommand(command);
111
+
112
+ const child = spawn(shell, [...args, resolvedCommand], {
113
+ cwd,
114
+ detached: true,
115
+ env: { ...process.env },
116
+ stdio: ["ignore", "pipe", "pipe"],
117
+ });
118
+
119
+ let timedOut = false;
120
+ let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
121
+
122
+ if (timeout !== undefined && timeout > 0) {
123
+ timeoutHandle = setTimeout(() => {
124
+ timedOut = true;
125
+ if (child.pid) killTree(child.pid);
126
+ }, timeout * 1000);
127
+ }
128
+
129
+ const chunks: Buffer[] = [];
130
+ let totalBytes = 0;
131
+ let spillFilePath: string | undefined;
132
+ let spillStream: ReturnType<typeof createWriteStream> | undefined;
133
+ const MAX_BUFFER = DEFAULT_MAX_BYTES * 2;
134
+
135
+ const onData = (data: Buffer) => {
136
+ totalBytes += data.length;
137
+
138
+ if (totalBytes > DEFAULT_MAX_BYTES && !spillFilePath) {
139
+ spillFilePath = getTempFilePath();
140
+ spillStream = createWriteStream(spillFilePath);
141
+ for (const chunk of chunks) spillStream.write(chunk);
142
+ }
143
+ if (spillStream) spillStream.write(data);
144
+
145
+ chunks.push(data);
146
+ let chunksBytes = chunks.reduce((s, c) => s + c.length, 0);
147
+ while (chunksBytes > MAX_BUFFER && chunks.length > 1) {
148
+ const removed = chunks.shift()!;
149
+ chunksBytes -= removed.length;
150
+ }
151
+ };
152
+
153
+ if (child.stdout) child.stdout.on("data", onData);
154
+ if (child.stderr) child.stderr.on("data", onData);
155
+
156
+ const onAbort = () => {
157
+ if (child.pid) killTree(child.pid);
158
+ };
159
+
160
+ if (signal.aborted) {
161
+ onAbort();
162
+ } else {
163
+ signal.addEventListener("abort", onAbort, { once: true });
164
+ }
165
+
166
+ child.on("error", (err) => {
167
+ if (timeoutHandle) clearTimeout(timeoutHandle);
168
+ signal.removeEventListener("abort", onAbort);
169
+ reject(err);
170
+ });
171
+
172
+ child.on("close", (code) => {
173
+ if (timeoutHandle) clearTimeout(timeoutHandle);
174
+ signal.removeEventListener("abort", onAbort);
175
+ if (spillStream) spillStream.end();
176
+
177
+ if (signal.aborted) {
178
+ const output = Buffer.concat(chunks).toString("utf-8");
179
+ resolve(output ? `${output}\n\nCommand aborted` : "Command aborted");
180
+ return;
181
+ }
182
+
183
+ if (timedOut) {
184
+ const output = Buffer.concat(chunks).toString("utf-8");
185
+ resolve(output ? `${output}\n\nCommand timed out after ${timeout} seconds` : `Command timed out after ${timeout} seconds`);
186
+ return;
187
+ }
188
+
189
+ const fullOutput = Buffer.concat(chunks).toString("utf-8");
190
+
191
+ const lines = fullOutput.split("\n");
192
+ let text: string;
193
+ if (lines.length > DEFAULT_MAX_LINES) {
194
+ text = lines.slice(-DEFAULT_MAX_LINES).join("\n");
195
+ if (spillFilePath) {
196
+ text += `\n\n[Showing last ${DEFAULT_MAX_LINES} of ${lines.length} lines. Full output: ${spillFilePath}]`;
197
+ } else {
198
+ text += `\n\n[Showing last ${DEFAULT_MAX_LINES} of ${lines.length} lines]`;
199
+ }
200
+ } else {
201
+ text = fullOutput || "(no output)";
202
+ }
203
+
204
+ if (code !== 0 && code !== null) {
205
+ text += `\n\nCommand exited with code ${code}`;
206
+ }
207
+
208
+ resolve(text);
209
+ });
210
+ });
211
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * await_job tool — wait for one or more background jobs to complete.
3
+ *
4
+ * If specific job IDs are provided, waits for those jobs.
5
+ * If omitted, waits for any running job to complete.
6
+ */
7
+
8
+ import type { ToolDefinition } from "@gsd/pi-coding-agent";
9
+ import { Type } from "@sinclair/typebox";
10
+ import type { AsyncJobManager, Job } from "./job-manager.js";
11
+
12
+ const schema = Type.Object({
13
+ jobs: Type.Optional(
14
+ Type.Array(Type.String(), {
15
+ description: "Job IDs to wait for. Omit to wait for any running job.",
16
+ }),
17
+ ),
18
+ });
19
+
20
+ export function createAwaitTool(getManager: () => AsyncJobManager): ToolDefinition<typeof schema> {
21
+ return {
22
+ name: "await_job",
23
+ label: "Await Background Job",
24
+ description:
25
+ "Wait for background jobs to complete. Provide specific job IDs or omit to wait for the next job that finishes. Returns results of completed jobs.",
26
+ parameters: schema,
27
+ async execute(_toolCallId, params) {
28
+ const manager = getManager();
29
+ const { jobs: jobIds } = params;
30
+
31
+ let watched: Job[];
32
+ if (jobIds && jobIds.length > 0) {
33
+ watched = [];
34
+ const notFound: string[] = [];
35
+ for (const id of jobIds) {
36
+ const job = manager.getJob(id);
37
+ if (job) {
38
+ watched.push(job);
39
+ } else {
40
+ notFound.push(id);
41
+ }
42
+ }
43
+ if (notFound.length > 0 && watched.length === 0) {
44
+ return {
45
+ content: [{ type: "text", text: `No jobs found: ${notFound.join(", ")}` }],
46
+ };
47
+ }
48
+ } else {
49
+ watched = manager.getRunningJobs();
50
+ if (watched.length === 0) {
51
+ return {
52
+ content: [{ type: "text", text: "No running background jobs." }],
53
+ };
54
+ }
55
+ }
56
+
57
+ // If all watched jobs are already done, return immediately
58
+ const running = watched.filter((j) => j.status === "running");
59
+ if (running.length === 0) {
60
+ const result = formatResults(watched);
61
+ manager.acknowledgeDeliveries(watched.map((j) => j.id));
62
+ return { content: [{ type: "text", text: result }] };
63
+ }
64
+
65
+ // Wait for at least one to complete
66
+ await Promise.race(running.map((j) => j.promise));
67
+
68
+ // Collect all completed results (more may have finished while waiting)
69
+ const completed = watched.filter((j) => j.status !== "running");
70
+ manager.acknowledgeDeliveries(completed.map((j) => j.id));
71
+
72
+ const stillRunning = watched.filter((j) => j.status === "running");
73
+ let result = formatResults(completed);
74
+ if (stillRunning.length > 0) {
75
+ result += `\n\n**Still running:** ${stillRunning.map((j) => `${j.id} (${j.label})`).join(", ")}`;
76
+ }
77
+
78
+ return { content: [{ type: "text", text: result }] };
79
+ },
80
+ };
81
+ }
82
+
83
+ function formatResults(jobs: Job[]): string {
84
+ if (jobs.length === 0) return "No completed jobs.";
85
+
86
+ const parts: string[] = [];
87
+ for (const job of jobs) {
88
+ const elapsed = ((Date.now() - job.startTime) / 1000).toFixed(1);
89
+ const header = `### ${job.id} — ${job.label} (${job.status}, ${elapsed}s)`;
90
+
91
+ if (job.status === "completed") {
92
+ parts.push(`${header}\n\n${job.resultText ?? "(no output)"}`);
93
+ } else if (job.status === "failed") {
94
+ parts.push(`${header}\n\nError: ${job.errorText ?? "unknown error"}`);
95
+ } else if (job.status === "cancelled") {
96
+ parts.push(`${header}\n\nCancelled.`);
97
+ }
98
+ }
99
+
100
+ return parts.join("\n\n---\n\n");
101
+ }