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,625 @@
1
+ /**
2
+ * get-secrets-from-user — paged secure env var collection + apply
3
+ *
4
+ * Collects secrets one-per-page via masked TUI input, then writes them
5
+ * to .env (local), Vercel, or Convex. No ctx.callTool, no external deps.
6
+ * Uses Node fs/promises for file I/O and pi.exec() for CLI sinks.
7
+ */
8
+
9
+ import { readFile, writeFile } from "node:fs/promises";
10
+ import { existsSync, statSync } from "node:fs";
11
+ import { resolve } from "node:path";
12
+
13
+ import type { ExtensionAPI, Theme } from "@gsd/pi-coding-agent";
14
+ import { CURSOR_MARKER, Editor, type EditorTheme, Key, matchesKey, Text, truncateToWidth, wrapTextWithAnsi } from "@gsd/pi-tui";
15
+ import { Type } from "@sinclair/typebox";
16
+ import { makeUI, type ProgressStatus } from "./shared/ui.js";
17
+ import { parseSecretsManifest, formatSecretsManifest } from "./gsd/files.js";
18
+ import { resolveMilestoneFile } from "./gsd/paths.js";
19
+ import type { SecretsManifestEntry } from "./gsd/types.js";
20
+
21
+ // ─── Types ────────────────────────────────────────────────────────────────────
22
+
23
+ interface CollectedSecret {
24
+ key: string;
25
+ value: string | null; // null = skipped
26
+ }
27
+
28
+ interface ToolResultDetails {
29
+ destination: string;
30
+ environment?: string;
31
+ applied: string[];
32
+ skipped: string[];
33
+ existingSkipped?: string[];
34
+ detectedDestination?: string;
35
+ }
36
+
37
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
38
+
39
+ function maskPreview(value: string): string {
40
+ if (!value) return "";
41
+ if (value.length <= 8) return "*".repeat(value.length);
42
+ return `${value.slice(0, 4)}${"*".repeat(Math.max(4, value.length - 8))}${value.slice(-4)}`;
43
+ }
44
+
45
+ /**
46
+ * Replace editor visible text with masked characters while preserving ANSI cursor/sequencer codes.
47
+ */
48
+ function maskEditorLine(line: string): string {
49
+ // Keep border / metadata lines readable.
50
+ if (line.startsWith("─")) {
51
+ return line;
52
+ }
53
+
54
+ let output = "";
55
+ let i = 0;
56
+ while (i < line.length) {
57
+ if (line.startsWith(CURSOR_MARKER, i)) {
58
+ output += CURSOR_MARKER;
59
+ i += CURSOR_MARKER.length;
60
+ continue;
61
+ }
62
+
63
+ const ansiMatch = /^\x1b\[[0-9;]*m/.exec(line.slice(i));
64
+ if (ansiMatch) {
65
+ output += ansiMatch[0];
66
+ i += ansiMatch[0].length;
67
+ continue;
68
+ }
69
+
70
+ const ch = line[i] as string;
71
+ output += ch === " " ? " " : "*";
72
+ i += 1;
73
+ }
74
+
75
+ return output;
76
+ }
77
+
78
+ function shellEscapeSingle(value: string): string {
79
+ return `'${value.replace(/'/g, `'\\''`)}'`;
80
+ }
81
+
82
+ async function writeEnvKey(filePath: string, key: string, value: string): Promise<void> {
83
+ let content = "";
84
+ try {
85
+ content = await readFile(filePath, "utf8");
86
+ } catch {
87
+ content = "";
88
+ }
89
+ const escaped = value.replace(/\\/g, "\\\\").replace(/\n/g, "\\n").replace(/\r/g, "");
90
+ const line = `${key}=${escaped}`;
91
+ const regex = new RegExp(`^${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*=.*$`, "m");
92
+ if (regex.test(content)) {
93
+ content = content.replace(regex, line);
94
+ } else {
95
+ if (content.length > 0 && !content.endsWith("\n")) content += "\n";
96
+ content += `${line}\n`;
97
+ }
98
+ await writeFile(filePath, content, "utf8");
99
+ }
100
+
101
+ // ─── Exported utilities ───────────────────────────────────────────────────────
102
+
103
+ /**
104
+ * Check which keys already exist in the .env file or process.env.
105
+ * Returns the subset of `keys` that are already set.
106
+ * Handles ENOENT gracefully (still checks process.env).
107
+ * Empty-string values count as existing.
108
+ */
109
+ export async function checkExistingEnvKeys(keys: string[], envFilePath: string): Promise<string[]> {
110
+ let fileContent = "";
111
+ try {
112
+ fileContent = await readFile(envFilePath, "utf8");
113
+ } catch {
114
+ // ENOENT or other read error — proceed with empty content
115
+ }
116
+
117
+ const existing: string[] = [];
118
+ for (const key of keys) {
119
+ const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
120
+ const regex = new RegExp(`^${escaped}\\s*=`, "m");
121
+ if (regex.test(fileContent) || key in process.env) {
122
+ existing.push(key);
123
+ }
124
+ }
125
+ return existing;
126
+ }
127
+
128
+ /**
129
+ * Detect the write destination based on project files in basePath.
130
+ * Priority: vercel.json → convex/ dir → fallback "dotenv".
131
+ */
132
+ export function detectDestination(basePath: string): "dotenv" | "vercel" | "convex" {
133
+ if (existsSync(resolve(basePath, "vercel.json"))) {
134
+ return "vercel";
135
+ }
136
+ const convexPath = resolve(basePath, "convex");
137
+ try {
138
+ if (existsSync(convexPath) && statSync(convexPath).isDirectory()) {
139
+ return "convex";
140
+ }
141
+ } catch {
142
+ // stat error — treat as not found
143
+ }
144
+ return "dotenv";
145
+ }
146
+
147
+ // ─── Paged secure input UI ────────────────────────────────────────────────────
148
+
149
+ /**
150
+ * Show a single-key masked input page via ctx.ui.custom().
151
+ * Returns the entered value, or null if skipped/cancelled.
152
+ */
153
+ async function collectOneSecret(
154
+ ctx: { ui: any; hasUI: boolean },
155
+ pageIndex: number,
156
+ totalPages: number,
157
+ keyName: string,
158
+ hint: string | undefined,
159
+ guidance?: string[],
160
+ ): Promise<string | null> {
161
+ if (!ctx.hasUI) return null;
162
+
163
+ return ctx.ui.custom((tui: any, theme: any, _kb: any, done: (r: string | null) => void) => {
164
+ let value = "";
165
+ let cachedLines: string[] | undefined;
166
+
167
+ const editorTheme: EditorTheme = {
168
+ borderColor: (s: string) => theme.fg("accent", s),
169
+ selectList: {
170
+ selectedPrefix: (t: string) => theme.fg("accent", t),
171
+ selectedText: (t: string) => theme.fg("accent", t),
172
+ description: (t: string) => theme.fg("muted", t),
173
+ scrollInfo: (t: string) => theme.fg("dim", t),
174
+ noMatch: (t: string) => theme.fg("warning", t),
175
+ },
176
+ };
177
+ const editor = new Editor(tui, editorTheme, { paddingX: 1 });
178
+
179
+ function refresh() {
180
+ cachedLines = undefined;
181
+ tui.requestRender();
182
+ }
183
+
184
+ function handleInput(data: string) {
185
+ if (matchesKey(data, Key.enter)) {
186
+ value = editor.getText().trim();
187
+ done(value.length > 0 ? value : null);
188
+ return;
189
+ }
190
+ if (matchesKey(data, Key.escape)) {
191
+ done(null);
192
+ return;
193
+ }
194
+ // ctrl+s = skip this key
195
+ if (data === "\x13") {
196
+ done(null);
197
+ return;
198
+ }
199
+ editor.handleInput(data);
200
+ refresh();
201
+ }
202
+
203
+ function render(width: number): string[] {
204
+ if (cachedLines) return cachedLines;
205
+ const lines: string[] = [];
206
+ const add = (s: string) => lines.push(truncateToWidth(s, width));
207
+
208
+ add(theme.fg("accent", "─".repeat(width)));
209
+ add(theme.fg("dim", ` Page ${pageIndex + 1}/${totalPages} · Secure Env Setup`));
210
+ lines.push("");
211
+
212
+ // Key name as big header
213
+ add(theme.fg("accent", theme.bold(` ${keyName}`)));
214
+ if (hint) {
215
+ add(theme.fg("muted", ` ${hint}`));
216
+ }
217
+
218
+ // Guidance steps (numbered, dim, wrapped for long URLs)
219
+ if (guidance && guidance.length > 0) {
220
+ lines.push("");
221
+ for (let g = 0; g < guidance.length; g++) {
222
+ const prefix = ` ${g + 1}. `;
223
+ const step = guidance[g] as string;
224
+ const wrappedLines = wrapTextWithAnsi(step, width - 4);
225
+ for (let w = 0; w < wrappedLines.length; w++) {
226
+ const indent = w === 0 ? prefix : " ".repeat(prefix.length);
227
+ lines.push(theme.fg("dim", `${indent}${wrappedLines[w]}`));
228
+ }
229
+ }
230
+ }
231
+
232
+ lines.push("");
233
+
234
+ // Masked preview
235
+ const raw = editor.getText();
236
+ const preview = raw.length > 0 ? maskPreview(raw) : theme.fg("dim", "(empty — press enter to skip)");
237
+ add(theme.fg("text", ` Preview: ${preview}`));
238
+ lines.push("");
239
+
240
+ // Editor
241
+ add(theme.fg("muted", " Enter value:"));
242
+ for (const line of editor.render(width - 2)) {
243
+ add(theme.fg("text", maskEditorLine(line)));
244
+ }
245
+
246
+ lines.push("");
247
+ add(theme.fg("dim", ` enter to confirm | ctrl+s or esc to skip | esc cancels`));
248
+ add(theme.fg("accent", "─".repeat(width)));
249
+
250
+ cachedLines = lines;
251
+ return lines;
252
+ }
253
+
254
+ return {
255
+ render,
256
+ invalidate: () => { cachedLines = undefined; },
257
+ handleInput,
258
+ };
259
+ });
260
+ }
261
+
262
+ /**
263
+ * Exported wrapper around collectOneSecret for testing.
264
+ * Exposes the same interface with guidance parameter for test verification.
265
+ */
266
+ export const collectOneSecretWithGuidance = collectOneSecret;
267
+
268
+ // ─── Summary Screen ───────────────────────────────────────────────────────────
269
+
270
+ /**
271
+ * Read-only summary screen showing all manifest entries with status indicators.
272
+ * Follows the confirm-ui.ts pattern: render → any key → done.
273
+ *
274
+ * Status mapping:
275
+ * - collected → done
276
+ * - pending → pending
277
+ * - skipped → skipped
278
+ * - existing keys (in existingKeys) → done with "already set" annotation
279
+ */
280
+ export async function showSecretsSummary(
281
+ ctx: { ui: any; hasUI: boolean },
282
+ entries: SecretsManifestEntry[],
283
+ existingKeys: string[],
284
+ ): Promise<void> {
285
+ if (!ctx.hasUI) return;
286
+
287
+ const existingSet = new Set(existingKeys);
288
+
289
+ await ctx.ui.custom((tui: any, theme: Theme, _kb: any, done: (r: null) => void) => {
290
+ let cachedLines: string[] | undefined;
291
+
292
+ function handleInput(_data: string) {
293
+ // Any key dismisses — pass null to satisfy the typed done() callback
294
+ done(null);
295
+ }
296
+
297
+ function render(width: number): string[] {
298
+ if (cachedLines) return cachedLines;
299
+
300
+ const ui = makeUI(theme, width);
301
+ const lines: string[] = [];
302
+ const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
303
+
304
+ push(ui.bar());
305
+ push(ui.blank());
306
+ push(ui.header(" Secrets Summary"));
307
+ push(ui.blank());
308
+
309
+ for (const entry of entries) {
310
+ let status: ProgressStatus;
311
+ let detail: string | undefined;
312
+
313
+ if (existingSet.has(entry.key)) {
314
+ status = "done";
315
+ detail = "already set";
316
+ } else if (entry.status === "collected") {
317
+ status = "done";
318
+ } else if (entry.status === "skipped") {
319
+ status = "skipped";
320
+ } else {
321
+ status = "pending";
322
+ }
323
+
324
+ push(ui.progressItem(entry.key, status, { detail }));
325
+ }
326
+
327
+ push(ui.blank());
328
+ push(ui.hints(["any key to continue"]));
329
+ push(ui.bar());
330
+
331
+ cachedLines = lines;
332
+ return lines;
333
+ }
334
+
335
+ return {
336
+ render,
337
+ invalidate: () => { cachedLines = undefined; },
338
+ handleInput,
339
+ };
340
+ });
341
+ }
342
+
343
+ // ─── Destination Write Helper ─────────────────────────────────────────────────
344
+
345
+ /**
346
+ * Apply collected secrets to the target destination.
347
+ * Dotenv writes are handled directly; vercel/convex require pi.exec.
348
+ */
349
+ async function applySecrets(
350
+ provided: Array<{ key: string; value: string }>,
351
+ destination: "dotenv" | "vercel" | "convex",
352
+ opts: {
353
+ envFilePath: string;
354
+ environment?: string;
355
+ exec?: (cmd: string, args: string[]) => Promise<{ code: number; stderr: string }>;
356
+ },
357
+ ): Promise<{ applied: string[]; errors: string[] }> {
358
+ const applied: string[] = [];
359
+ const errors: string[] = [];
360
+
361
+ if (destination === "dotenv") {
362
+ for (const { key, value } of provided) {
363
+ try {
364
+ await writeEnvKey(opts.envFilePath, key, value);
365
+ applied.push(key);
366
+ } catch (err: any) {
367
+ errors.push(`${key}: ${err.message}`);
368
+ }
369
+ }
370
+ }
371
+
372
+ if (destination === "vercel" && opts.exec) {
373
+ const env = opts.environment ?? "development";
374
+ for (const { key, value } of provided) {
375
+ try {
376
+ const result = await opts.exec("sh", [
377
+ "-c",
378
+ `printf %s ${shellEscapeSingle(value)} | vercel env add ${key} ${env}`,
379
+ ]);
380
+ if (result.code !== 0) {
381
+ errors.push(`${key}: ${result.stderr.slice(0, 200)}`);
382
+ } else {
383
+ applied.push(key);
384
+ }
385
+ } catch (err: any) {
386
+ errors.push(`${key}: ${err.message}`);
387
+ }
388
+ }
389
+ }
390
+
391
+ if (destination === "convex" && opts.exec) {
392
+ for (const { key, value } of provided) {
393
+ try {
394
+ const result = await opts.exec("sh", [
395
+ "-c",
396
+ `npx convex env set ${key} ${shellEscapeSingle(value)}`,
397
+ ]);
398
+ if (result.code !== 0) {
399
+ errors.push(`${key}: ${result.stderr.slice(0, 200)}`);
400
+ } else {
401
+ applied.push(key);
402
+ }
403
+ } catch (err: any) {
404
+ errors.push(`${key}: ${err.message}`);
405
+ }
406
+ }
407
+ }
408
+
409
+ return { applied, errors };
410
+ }
411
+
412
+ // ─── Manifest Orchestrator ────────────────────────────────────────────────────
413
+
414
+ /**
415
+ * Full orchestrator: reads manifest, checks env, shows summary, collects
416
+ * only pending keys (with guidance + hint), updates manifest statuses,
417
+ * writes back, and applies collected values to the destination.
418
+ *
419
+ * Returns a structured result matching the tool result shape.
420
+ */
421
+ export async function collectSecretsFromManifest(
422
+ base: string,
423
+ milestoneId: string,
424
+ ctx: { ui: any; hasUI: boolean; cwd: string },
425
+ ): Promise<{ applied: string[]; skipped: string[]; existingSkipped: string[] }> {
426
+ // (a) Resolve manifest path
427
+ const manifestPath = resolveMilestoneFile(base, milestoneId, "SECRETS");
428
+ if (!manifestPath) {
429
+ throw new Error(`Secrets manifest not found for milestone ${milestoneId} in ${base}`);
430
+ }
431
+
432
+ // (b) Read and parse manifest
433
+ const content = await readFile(manifestPath, "utf8");
434
+ const manifest = parseSecretsManifest(content);
435
+
436
+ // (c) Check existing keys
437
+ const envPath = resolve(base, ".env");
438
+ const allKeys = manifest.entries.map((e) => e.key);
439
+ const existingKeys = await checkExistingEnvKeys(allKeys, envPath);
440
+ const existingSet = new Set(existingKeys);
441
+
442
+ // (d) Build categorization
443
+ const existingSkipped: string[] = [];
444
+ const alreadySkipped: string[] = [];
445
+ const pendingEntries: SecretsManifestEntry[] = [];
446
+
447
+ for (const entry of manifest.entries) {
448
+ if (existingSet.has(entry.key)) {
449
+ existingSkipped.push(entry.key);
450
+ } else if (entry.status === "skipped") {
451
+ alreadySkipped.push(entry.key);
452
+ } else if (entry.status === "pending") {
453
+ pendingEntries.push(entry);
454
+ }
455
+ // collected entries that are not in env are left as-is
456
+ }
457
+
458
+ // (e) Show summary screen
459
+ await showSecretsSummary(ctx, manifest.entries, existingKeys);
460
+
461
+ // (f) Detect destination
462
+ const destination = detectDestination(ctx.cwd);
463
+
464
+ // (g) Collect only pending keys that are not already existing
465
+ const collected: CollectedSecret[] = [];
466
+ for (let i = 0; i < pendingEntries.length; i++) {
467
+ const entry = pendingEntries[i] as SecretsManifestEntry;
468
+ const value = await collectOneSecret(
469
+ ctx,
470
+ i,
471
+ pendingEntries.length,
472
+ entry.key,
473
+ entry.formatHint || undefined,
474
+ entry.guidance.length > 0 ? entry.guidance : undefined,
475
+ );
476
+ collected.push({ key: entry.key, value });
477
+ }
478
+
479
+ // (h) Update manifest entry statuses
480
+ for (const { key, value } of collected) {
481
+ const entry = manifest.entries.find((e) => e.key === key);
482
+ if (entry) {
483
+ entry.status = value !== null ? "collected" : "skipped";
484
+ }
485
+ }
486
+
487
+ // (i) Write manifest back to disk
488
+ await writeFile(manifestPath, formatSecretsManifest(manifest), "utf8");
489
+
490
+ // (j) Apply collected values to destination
491
+ const provided = collected.filter((c) => c.value !== null) as Array<{ key: string; value: string }>;
492
+ const { applied } = await applySecrets(provided, destination, {
493
+ envFilePath: resolve(ctx.cwd, ".env"),
494
+ });
495
+
496
+ const skipped = [
497
+ ...alreadySkipped,
498
+ ...collected.filter((c) => c.value === null).map((c) => c.key),
499
+ ];
500
+
501
+ return { applied, skipped, existingSkipped };
502
+ }
503
+
504
+ // ─── Extension ────────────────────────────────────────────────────────────────
505
+
506
+ export default function secureEnv(pi: ExtensionAPI) {
507
+ pi.registerTool({
508
+ name: "secure_env_collect",
509
+ label: "Secure Env Collect",
510
+ description:
511
+ "Collect one or more env vars through a paged masked-input UI, then write them to .env, Vercel, or Convex. " +
512
+ "Values are shown masked to the user (e.g. sk-ir***dgdh) and never echoed in tool output.",
513
+ promptSnippet: "Collect and apply env vars securely without asking user to edit files manually.",
514
+ promptGuidelines: [
515
+ "NEVER ask the user to manually edit .env files, copy-paste into a terminal, or open a dashboard to set env vars. Always use secure_env_collect instead.",
516
+ "When a command fails due to a missing env var (e.g. 'OPENAI_API_KEY is not set', 'Missing required environment variable', 'Invalid API key', 'authentication required'), immediately call secure_env_collect with the missing keys before retrying.",
517
+ "When starting a new project or running setup steps that require secrets (API keys, tokens, database URLs), proactively call secure_env_collect before the first command that needs them.",
518
+ "Detect the right destination: use 'dotenv' for local dev, 'vercel' when deploying to Vercel, 'convex' when using Convex backend.",
519
+ "After secure_env_collect completes, re-run the originally blocked command to verify the fix worked.",
520
+ "Never echo, log, or repeat secret values in your responses. Only report key names and applied/skipped status.",
521
+ ],
522
+ parameters: Type.Object({
523
+ destination: Type.Optional(Type.Union([
524
+ Type.Literal("dotenv"),
525
+ Type.Literal("vercel"),
526
+ Type.Literal("convex"),
527
+ ], { description: "Where to write the collected secrets" })),
528
+ keys: Type.Array(
529
+ Type.Object({
530
+ key: Type.String({ description: "Env var name, e.g. OPENAI_API_KEY" }),
531
+ hint: Type.Optional(Type.String({ description: "Format hint shown to user, e.g. 'starts with sk-'" })),
532
+ required: Type.Optional(Type.Boolean()),
533
+ guidance: Type.Optional(Type.Array(Type.String(), { description: "Step-by-step guidance for finding this key" })),
534
+ }),
535
+ { minItems: 1 },
536
+ ),
537
+ envFilePath: Type.Optional(Type.String({ description: "Path to .env file (dotenv only). Defaults to .env in cwd." })),
538
+ environment: Type.Optional(
539
+ Type.Union([
540
+ Type.Literal("development"),
541
+ Type.Literal("preview"),
542
+ Type.Literal("production"),
543
+ ], { description: "Target environment (vercel only)" }),
544
+ ),
545
+ }),
546
+
547
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
548
+ if (!ctx.hasUI) {
549
+ return {
550
+ content: [{ type: "text", text: "Error: UI not available (interactive mode required for secure env collection)." }],
551
+ isError: true,
552
+ details: undefined as unknown,
553
+ };
554
+ }
555
+
556
+ // Auto-detect destination when not provided
557
+ const destinationAutoDetected = params.destination == null;
558
+ const destination = params.destination ?? detectDestination(ctx.cwd);
559
+
560
+ const collected: CollectedSecret[] = [];
561
+
562
+ // Collect one key per page
563
+ for (let i = 0; i < params.keys.length; i++) {
564
+ const item = params.keys[i];
565
+ const value = await collectOneSecret(ctx, i, params.keys.length, item.key, item.hint, item.guidance);
566
+ collected.push({ key: item.key, value });
567
+ }
568
+
569
+ const provided = collected.filter((c) => c.value !== null) as Array<{ key: string; value: string }>;
570
+ const skipped = collected.filter((c) => c.value === null).map((c) => c.key);
571
+
572
+ // Apply to destination via shared helper
573
+ const { applied, errors } = await applySecrets(provided, destination, {
574
+ envFilePath: resolve(ctx.cwd, params.envFilePath ?? ".env"),
575
+ environment: params.environment,
576
+ exec: (cmd, args) => pi.exec(cmd, args),
577
+ });
578
+
579
+ const details: ToolResultDetails = {
580
+ destination,
581
+ environment: params.environment,
582
+ applied,
583
+ skipped,
584
+ ...(destinationAutoDetected ? { detectedDestination: destination } : {}),
585
+ };
586
+
587
+ const lines = [
588
+ `destination: ${destination}${destinationAutoDetected ? " (auto-detected)" : ""}${params.environment ? ` (${params.environment})` : ""}`,
589
+ ...applied.map((k) => `✓ ${k}: applied`),
590
+ ...skipped.map((k) => `• ${k}: skipped`),
591
+ ...errors.map((e) => `✗ ${e}`),
592
+ ];
593
+
594
+ return {
595
+ content: [{ type: "text", text: lines.join("\n") }],
596
+ details,
597
+ isError: errors.length > 0 && applied.length === 0,
598
+ };
599
+ },
600
+
601
+ renderCall(args, theme) {
602
+ const count = Array.isArray(args.keys) ? args.keys.length : 0;
603
+ return new Text(
604
+ theme.fg("toolTitle", theme.bold("secure_env_collect ")) +
605
+ theme.fg("muted", `→ ${args.destination ?? "auto"}`) +
606
+ theme.fg("dim", ` ${count} key${count !== 1 ? "s" : ""}`),
607
+ 0, 0,
608
+ );
609
+ },
610
+
611
+ renderResult(result, _options, theme) {
612
+ const details = result.details as ToolResultDetails | undefined;
613
+ if (!details) {
614
+ const t = result.content[0];
615
+ return new Text(t?.type === "text" ? t.text : "", 0, 0);
616
+ }
617
+ const lines = [
618
+ `${theme.fg("success", "✓")} ${details.destination}${details.environment ? ` (${details.environment})` : ""}`,
619
+ ...details.applied.map((k) => ` ${theme.fg("success", "✓")} ${k}: applied`),
620
+ ...details.skipped.map((k) => ` ${theme.fg("warning", "•")} ${k}: skipped`),
621
+ ];
622
+ return new Text(lines.join("\n"), 0, 0);
623
+ },
624
+ });
625
+ }