gsd-pi 2.76.0 → 2.77.0-dev.1d17f366c

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 (932) hide show
  1. package/README.md +32 -30
  2. package/dist/claude-cli-check.js +32 -3
  3. package/dist/cli-web-branch.d.ts +1 -0
  4. package/dist/cli-web-branch.js +3 -0
  5. package/dist/cli.js +38 -2
  6. package/dist/extension-discovery.d.ts +6 -0
  7. package/dist/extension-discovery.js +37 -0
  8. package/dist/extension-registry.d.ts +3 -0
  9. package/dist/extension-sort.d.ts +18 -0
  10. package/dist/extension-sort.js +114 -0
  11. package/dist/extension-validator.d.ts +47 -0
  12. package/dist/extension-validator.js +127 -0
  13. package/dist/loader.js +35 -7
  14. package/dist/mcp-server.d.ts +7 -0
  15. package/dist/mcp-server.js +35 -1
  16. package/dist/onboarding.js +45 -0
  17. package/dist/provider-migrations.d.ts +18 -0
  18. package/dist/provider-migrations.js +14 -0
  19. package/dist/resource-loader.d.ts +1 -1
  20. package/dist/resource-loader.js +2 -8
  21. package/dist/resources/agents/researcher.md +1 -1
  22. package/dist/resources/extensions/claude-code-cli/readiness.js +31 -8
  23. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +144 -63
  24. package/dist/resources/extensions/cmux/index.js +20 -0
  25. package/dist/resources/extensions/github-sync/templates.js +103 -0
  26. package/dist/resources/extensions/google-search/extension-manifest.json +5 -4
  27. package/dist/resources/extensions/google-search/index.js +3 -375
  28. package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
  29. package/dist/resources/extensions/gsd/auto/loop.js +90 -2
  30. package/dist/resources/extensions/gsd/auto/phases.js +145 -28
  31. package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
  32. package/dist/resources/extensions/gsd/auto/run-unit.js +48 -4
  33. package/dist/resources/extensions/gsd/auto/session.js +22 -1
  34. package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
  35. package/dist/resources/extensions/gsd/auto-dispatch.js +115 -17
  36. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  37. package/dist/resources/extensions/gsd/auto-model-selection.js +53 -16
  38. package/dist/resources/extensions/gsd/auto-post-unit.js +90 -2
  39. package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
  40. package/dist/resources/extensions/gsd/auto-recovery.js +46 -1
  41. package/dist/resources/extensions/gsd/auto-start.js +84 -60
  42. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
  43. package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
  44. package/dist/resources/extensions/gsd/auto-verification.js +33 -0
  45. package/dist/resources/extensions/gsd/auto-worktree.js +109 -61
  46. package/dist/resources/extensions/gsd/auto.js +107 -38
  47. package/dist/resources/extensions/gsd/blocked-models.js +68 -0
  48. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -1
  49. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
  50. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
  51. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +3 -0
  52. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +4 -2
  53. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +23 -0
  54. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +52 -6
  55. package/dist/resources/extensions/gsd/bootstrap/system-context.js +95 -29
  56. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
  57. package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
  58. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
  59. package/dist/resources/extensions/gsd/commands-cmux.js +9 -6
  60. package/dist/resources/extensions/gsd/commands-extensions.js +634 -43
  61. package/dist/resources/extensions/gsd/commands-extract-learnings.js +54 -89
  62. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
  63. package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
  64. package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
  65. package/dist/resources/extensions/gsd/db-writer.js +88 -16
  66. package/dist/resources/extensions/gsd/dispatch-guard.js +29 -3
  67. package/dist/resources/extensions/gsd/doctor-git-checks.js +23 -29
  68. package/dist/resources/extensions/gsd/doctor-providers.js +51 -5
  69. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +1 -0
  70. package/dist/resources/extensions/gsd/error-classifier.js +31 -3
  71. package/dist/resources/extensions/gsd/exec-history.js +120 -0
  72. package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
  73. package/dist/resources/extensions/gsd/file-lock.js +49 -9
  74. package/dist/resources/extensions/gsd/git-service.js +1 -0
  75. package/dist/resources/extensions/gsd/gitignore.js +2 -0
  76. package/dist/resources/extensions/gsd/gsd-db.js +168 -23
  77. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
  78. package/dist/resources/extensions/gsd/guided-flow.js +212 -9
  79. package/dist/resources/extensions/gsd/health-widget.js +4 -1
  80. package/dist/resources/extensions/gsd/hook-emitter.js +108 -0
  81. package/dist/resources/extensions/gsd/init-wizard.js +15 -1
  82. package/dist/resources/extensions/gsd/journal.js +17 -2
  83. package/dist/resources/extensions/gsd/key-manager.js +28 -0
  84. package/dist/resources/extensions/gsd/memory-backfill.js +126 -0
  85. package/dist/resources/extensions/gsd/memory-store.js +19 -0
  86. package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
  87. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  88. package/dist/resources/extensions/gsd/model-router.js +36 -3
  89. package/dist/resources/extensions/gsd/notifications.js +30 -16
  90. package/dist/resources/extensions/gsd/pre-execution-checks.js +44 -9
  91. package/dist/resources/extensions/gsd/preferences-types.js +9 -0
  92. package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
  93. package/dist/resources/extensions/gsd/preferences.js +17 -17
  94. package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
  95. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  96. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  97. package/dist/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
  98. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  99. package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
  100. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  101. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
  102. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  103. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  104. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -0
  105. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  106. package/dist/resources/extensions/gsd/reports.js +5 -4
  107. package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
  108. package/dist/resources/extensions/gsd/safety/file-change-validator.js +13 -5
  109. package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
  110. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  111. package/dist/resources/extensions/gsd/state.js +68 -29
  112. package/dist/resources/extensions/gsd/token-counter.js +22 -5
  113. package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
  114. package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
  115. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
  116. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
  117. package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
  118. package/dist/resources/extensions/gsd/tools/memory-tools.js +26 -1
  119. package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
  120. package/dist/resources/extensions/gsd/uok/audit.js +18 -2
  121. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  122. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  123. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  124. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  125. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  126. package/dist/resources/extensions/gsd/uok/plan-v2.js +30 -7
  127. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  128. package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
  129. package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
  130. package/dist/resources/extensions/gsd/workflow-templates/spike.md +6 -0
  131. package/dist/resources/extensions/gsd/worktree-manager.js +1 -0
  132. package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
  133. package/dist/resources/extensions/mcp-client/auth.js +10 -1
  134. package/dist/resources/extensions/mcp-client/index.js +118 -9
  135. package/dist/resources/extensions/search-the-web/command-search-provider.js +5 -4
  136. package/dist/resources/extensions/search-the-web/native-search.js +45 -13
  137. package/dist/resources/extensions/shared/cmux-events.js +12 -0
  138. package/dist/resources/extensions/shared/rtk-session-stats.js +1 -2
  139. package/dist/resources/skills/api-design/SKILL.md +190 -0
  140. package/dist/resources/skills/create-mcp-server/SKILL.md +121 -0
  141. package/dist/resources/skills/create-skill/SKILL.md +2 -2
  142. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  143. package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  144. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  145. package/dist/resources/skills/decompose-into-slices/SKILL.md +139 -0
  146. package/dist/resources/skills/dependency-upgrade/SKILL.md +158 -0
  147. package/dist/resources/skills/design-an-interface/SKILL.md +102 -0
  148. package/dist/resources/skills/forensics/SKILL.md +153 -0
  149. package/dist/resources/skills/grill-me/SKILL.md +93 -0
  150. package/dist/resources/skills/handoff/SKILL.md +121 -0
  151. package/dist/resources/skills/observability/SKILL.md +174 -0
  152. package/dist/resources/skills/security-review/SKILL.md +181 -0
  153. package/dist/resources/skills/spike-wrap-up/SKILL.md +138 -0
  154. package/dist/resources/skills/tdd/SKILL.md +112 -0
  155. package/dist/resources/skills/verify-before-complete/SKILL.md +98 -0
  156. package/dist/resources/skills/write-docs/SKILL.md +82 -0
  157. package/dist/resources/skills/write-milestone-brief/SKILL.md +135 -0
  158. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  159. package/dist/web/standalone/.next/BUILD_ID +1 -1
  160. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  161. package/dist/web/standalone/.next/build-manifest.json +4 -4
  162. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  163. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  164. package/dist/web/standalone/.next/required-server-files.json +4 -4
  165. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  166. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  168. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  169. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  170. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  171. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  172. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  173. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  174. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  176. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  178. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  179. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  180. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  181. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  182. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  183. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  184. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  185. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  195. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  201. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  204. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  209. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  211. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  214. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  217. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  220. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  223. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  224. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  226. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  227. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  228. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  229. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  230. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  231. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  232. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  233. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  234. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  235. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  236. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  237. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  238. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  239. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  240. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  241. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  242. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  243. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  244. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  245. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  246. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  247. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  248. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  249. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  250. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  251. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  252. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  253. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  254. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  255. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  256. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  257. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  258. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  259. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  260. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  261. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  262. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  263. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  264. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  265. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  266. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  267. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  268. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  269. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  270. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  271. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  272. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  273. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  274. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  275. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  276. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  277. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  278. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  279. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  280. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  281. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  282. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  283. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  284. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  285. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  286. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  287. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  288. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  289. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  290. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  291. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  292. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  293. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  294. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  295. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  296. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  297. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  298. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  299. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  300. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  301. package/dist/web/standalone/.next/server/app/index.html +1 -1
  302. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  303. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  304. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  305. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  306. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  307. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  308. package/dist/web/standalone/.next/server/app/page.js +2 -2
  309. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  310. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  311. package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
  312. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  313. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  314. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  315. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  316. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  317. package/dist/web/standalone/.next/server/middleware.js +2 -2
  318. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  319. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  320. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  321. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  322. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  323. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  324. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  325. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  326. package/dist/web/standalone/.next/static/chunks/app/page-5b113fd32bc2a1c3.js +1 -0
  327. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  328. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  329. package/dist/web/standalone/.next/static/chunks/{webpack-5fc74f13a25fa1bb.js → webpack-2e68521d7c82f7c2.js} +1 -1
  330. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  331. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  332. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  333. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  334. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  335. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  336. package/dist/web/standalone/server.js +1 -1
  337. package/dist/welcome-screen.js +6 -1
  338. package/dist/wizard.js +2 -0
  339. package/package.json +16 -14
  340. package/packages/daemon/package.json +2 -2
  341. package/packages/mcp-server/README.md +3 -3
  342. package/packages/mcp-server/dist/env-writer.d.ts +1 -0
  343. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
  344. package/packages/mcp-server/dist/env-writer.js +74 -6
  345. package/packages/mcp-server/dist/env-writer.js.map +1 -1
  346. package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
  347. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
  348. package/packages/mcp-server/dist/remote-questions.js +732 -0
  349. package/packages/mcp-server/dist/remote-questions.js.map +1 -0
  350. package/packages/mcp-server/dist/server.d.ts +7 -0
  351. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  352. package/packages/mcp-server/dist/server.js +95 -10
  353. package/packages/mcp-server/dist/server.js.map +1 -1
  354. package/packages/mcp-server/dist/session-manager.d.ts +14 -0
  355. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  356. package/packages/mcp-server/dist/session-manager.js +49 -1
  357. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  358. package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
  359. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  360. package/packages/mcp-server/dist/workflow-tools.js +178 -31
  361. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  362. package/packages/mcp-server/package.json +9 -3
  363. package/packages/mcp-server/src/env-writer.test.ts +79 -1
  364. package/packages/mcp-server/src/env-writer.ts +76 -6
  365. package/packages/mcp-server/src/mcp-server.test.ts +67 -0
  366. package/packages/mcp-server/src/readers/readers.test.ts +5 -1
  367. package/packages/mcp-server/src/remote-questions.test.ts +294 -0
  368. package/packages/mcp-server/src/remote-questions.ts +916 -0
  369. package/packages/mcp-server/src/server.ts +118 -16
  370. package/packages/mcp-server/src/session-manager.ts +43 -1
  371. package/packages/mcp-server/src/workflow-tools.test.ts +190 -1
  372. package/packages/mcp-server/src/workflow-tools.ts +234 -49
  373. package/packages/mcp-server/tsconfig.test.json +19 -0
  374. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  375. package/packages/native/package.json +6 -1
  376. package/packages/native/src/__tests__/clipboard.test.mjs +69 -23
  377. package/packages/native/tsconfig.tsbuildinfo +1 -1
  378. package/packages/pi-agent-core/dist/agent-loop.js +12 -0
  379. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  380. package/packages/pi-agent-core/dist/types.d.ts +30 -0
  381. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  382. package/packages/pi-agent-core/dist/types.js.map +1 -1
  383. package/packages/pi-agent-core/package.json +6 -1
  384. package/packages/pi-agent-core/src/agent-loop.test.ts +220 -15
  385. package/packages/pi-agent-core/src/agent-loop.ts +14 -0
  386. package/packages/pi-agent-core/src/types.ts +34 -0
  387. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  388. package/packages/pi-ai/dist/models/custom.d.ts +38 -0
  389. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
  390. package/packages/pi-ai/dist/models/custom.js +41 -0
  391. package/packages/pi-ai/dist/models/custom.js.map +1 -1
  392. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
  393. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  394. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts +2 -0
  395. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts.map +1 -0
  396. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +13 -0
  397. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -0
  398. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  399. package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
  400. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  401. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  402. package/packages/pi-ai/dist/providers/anthropic.js +13 -4
  403. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  404. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
  405. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
  406. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
  407. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
  408. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  409. package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
  410. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  411. package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
  412. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  413. package/packages/pi-ai/dist/providers/simple-options.js +16 -1
  414. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  415. package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
  416. package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
  417. package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
  418. package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
  419. package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
  420. package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
  421. package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
  422. package/packages/pi-ai/dist/providers/think-tag-parser.test.js.map +1 -0
  423. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  424. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +12 -2
  425. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  426. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +164 -14
  427. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
  428. package/packages/pi-ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
  429. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js +15 -3
  430. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js.map +1 -1
  431. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts +2 -0
  432. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts.map +1 -0
  433. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +67 -0
  434. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -0
  435. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
  436. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js +16 -3
  437. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
  438. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts +2 -0
  439. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts.map +1 -0
  440. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +67 -0
  441. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -0
  442. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +2 -0
  443. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +1 -0
  444. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +289 -0
  445. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +1 -0
  446. package/packages/pi-ai/package.json +6 -1
  447. package/packages/pi-ai/src/models/custom.ts +42 -0
  448. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
  449. package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -0
  450. package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
  451. package/packages/pi-ai/src/providers/anthropic.ts +15 -4
  452. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
  453. package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
  454. package/packages/pi-ai/src/providers/simple-options.ts +17 -1
  455. package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
  456. package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
  457. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +200 -23
  458. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +12 -2
  459. package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +84 -0
  460. package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +15 -5
  461. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +84 -0
  462. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +16 -5
  463. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +363 -0
  464. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  465. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
  466. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  467. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
  468. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  469. package/packages/pi-coding-agent/dist/core/agent-session.js +32 -2
  470. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  471. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +25 -0
  472. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  473. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +105 -6
  474. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  475. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +230 -28
  476. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
  477. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +30 -2
  478. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  479. package/packages/pi-coding-agent/dist/core/compaction/utils.js +113 -12
  480. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  481. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
  482. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  483. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +29 -18
  484. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  485. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
  486. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
  487. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
  488. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
  489. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +56 -1
  490. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -1
  491. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +8 -15
  492. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  493. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts +25 -0
  494. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts.map +1 -0
  495. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js +109 -0
  496. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js.map +1 -0
  497. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts +67 -0
  498. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts.map +1 -0
  499. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js +167 -0
  500. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js.map +1 -0
  501. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  502. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  503. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  504. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +3 -2
  505. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  506. package/packages/pi-coding-agent/dist/core/extensions/loader.js +28 -8
  507. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  508. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +35 -2
  509. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  510. package/packages/pi-coding-agent/dist/core/extensions/runner.js +233 -0
  511. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  512. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +212 -2
  513. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  514. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  515. package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts +53 -0
  516. package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts.map +1 -0
  517. package/packages/pi-coding-agent/dist/core/hooks-runner.js +337 -0
  518. package/packages/pi-coding-agent/dist/core/hooks-runner.js.map +1 -0
  519. package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts +2 -0
  520. package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts.map +1 -0
  521. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +234 -0
  522. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -0
  523. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
  524. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  525. package/packages/pi-coding-agent/dist/core/index.js +1 -0
  526. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  527. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +11 -0
  528. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  529. package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
  530. package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
  531. package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
  532. package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
  533. package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
  534. package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
  535. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts +2 -0
  536. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts.map +1 -0
  537. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js +40 -0
  538. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js.map +1 -0
  539. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -2
  540. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  541. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
  542. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
  543. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
  544. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
  545. package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
  546. package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
  547. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -0
  548. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  549. package/packages/pi-coding-agent/dist/core/model-registry.js +90 -10
  550. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  551. package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
  552. package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
  553. package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
  554. package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
  555. package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
  556. package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
  557. package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
  558. package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
  559. package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -1
  560. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  561. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
  562. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  563. package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
  564. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  565. package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
  566. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  567. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  568. package/packages/pi-coding-agent/dist/core/session-manager.js +10 -6
  569. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  570. package/packages/pi-coding-agent/dist/core/session-manager.test.js +45 -1
  571. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  572. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +55 -0
  573. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  574. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  575. package/packages/pi-coding-agent/dist/core/system-prompt.js +3 -3
  576. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  577. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js +2 -1
  578. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -1
  579. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  580. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  581. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  582. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
  583. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
  584. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
  585. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  586. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
  587. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  588. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  589. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  590. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  591. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
  592. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  593. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
  594. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  595. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  596. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
  597. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  598. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
  599. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  600. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
  601. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  602. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -0
  603. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  604. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  605. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
  606. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  607. package/packages/pi-coding-agent/package.json +6 -1
  608. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
  609. package/packages/pi-coding-agent/src/core/agent-session.ts +38 -2
  610. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +368 -28
  611. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +122 -6
  612. package/packages/pi-coding-agent/src/core/compaction/utils.ts +111 -13
  613. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  614. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +32 -18
  615. package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +68 -1
  616. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +9 -18
  617. package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
  618. package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
  619. package/packages/pi-coding-agent/src/core/extensions/index.ts +16 -0
  620. package/packages/pi-coding-agent/src/core/extensions/loader.ts +29 -11
  621. package/packages/pi-coding-agent/src/core/extensions/runner.ts +351 -0
  622. package/packages/pi-coding-agent/src/core/extensions/types.ts +266 -0
  623. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +269 -0
  624. package/packages/pi-coding-agent/src/core/hooks-runner.ts +460 -0
  625. package/packages/pi-coding-agent/src/core/index.ts +10 -0
  626. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +13 -0
  627. package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
  628. package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
  629. package/packages/pi-coding-agent/src/core/model-registry-auth-header.test.ts +44 -0
  630. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -2
  631. package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
  632. package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
  633. package/packages/pi-coding-agent/src/core/model-registry.ts +102 -10
  634. package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
  635. package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
  636. package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -1
  637. package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
  638. package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
  639. package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -1
  640. package/packages/pi-coding-agent/src/core/session-manager.ts +10 -6
  641. package/packages/pi-coding-agent/src/core/settings-manager.ts +57 -0
  642. package/packages/pi-coding-agent/src/core/system-prompt.ts +3 -3
  643. package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +2 -1
  644. package/packages/pi-coding-agent/src/index.ts +16 -0
  645. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
  646. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
  647. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
  648. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
  649. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
  650. package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
  651. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +14 -0
  652. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
  653. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  654. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +12 -5
  655. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  656. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +21 -0
  657. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  658. package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
  659. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  660. package/packages/pi-tui/dist/stdin-buffer.js +20 -0
  661. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  662. package/packages/pi-tui/package.json +6 -1
  663. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -5
  664. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +27 -0
  665. package/packages/pi-tui/src/stdin-buffer.ts +26 -0
  666. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  667. package/packages/rpc-client/package.json +6 -1
  668. package/pkg/package.json +1 -1
  669. package/scripts/install.js +512 -0
  670. package/scripts/lib/workspace-manifest.cjs +86 -0
  671. package/scripts/link-workspace-packages.cjs +5 -16
  672. package/scripts/postinstall.js +9 -178
  673. package/src/resources/agents/researcher.md +1 -1
  674. package/src/resources/extensions/claude-code-cli/readiness.ts +32 -8
  675. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +158 -67
  676. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +251 -14
  677. package/src/resources/extensions/cmux/index.ts +35 -10
  678. package/src/resources/extensions/github-sync/templates.ts +151 -0
  679. package/src/resources/extensions/github-sync/tests/templates.test.ts +59 -0
  680. package/src/resources/extensions/google-search/extension-manifest.json +5 -4
  681. package/src/resources/extensions/google-search/index.ts +9 -470
  682. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  683. package/src/resources/extensions/gsd/auto/loop-deps.ts +15 -1
  684. package/src/resources/extensions/gsd/auto/loop.ts +104 -2
  685. package/src/resources/extensions/gsd/auto/phases.ts +176 -27
  686. package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
  687. package/src/resources/extensions/gsd/auto/run-unit.ts +56 -4
  688. package/src/resources/extensions/gsd/auto/session.ts +35 -2
  689. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  690. package/src/resources/extensions/gsd/auto/types.ts +1 -1
  691. package/src/resources/extensions/gsd/auto-dispatch.ts +117 -16
  692. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  693. package/src/resources/extensions/gsd/auto-model-selection.ts +71 -15
  694. package/src/resources/extensions/gsd/auto-post-unit.ts +92 -3
  695. package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
  696. package/src/resources/extensions/gsd/auto-recovery.ts +40 -1
  697. package/src/resources/extensions/gsd/auto-start.ts +88 -74
  698. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
  699. package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
  700. package/src/resources/extensions/gsd/auto-verification.ts +33 -0
  701. package/src/resources/extensions/gsd/auto-worktree.ts +122 -68
  702. package/src/resources/extensions/gsd/auto.ts +115 -42
  703. package/src/resources/extensions/gsd/blocked-models.ts +98 -0
  704. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +131 -1
  705. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
  706. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
  707. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +5 -0
  708. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -2
  709. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +26 -0
  710. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +54 -6
  711. package/src/resources/extensions/gsd/bootstrap/system-context.ts +102 -35
  712. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
  713. package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
  714. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
  715. package/src/resources/extensions/gsd/commands-cmux.ts +10 -6
  716. package/src/resources/extensions/gsd/commands-extensions.ts +747 -41
  717. package/src/resources/extensions/gsd/commands-extract-learnings.ts +55 -90
  718. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
  719. package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
  720. package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
  721. package/src/resources/extensions/gsd/db-writer.ts +88 -17
  722. package/src/resources/extensions/gsd/dispatch-guard.ts +26 -2
  723. package/src/resources/extensions/gsd/doctor-git-checks.ts +23 -27
  724. package/src/resources/extensions/gsd/doctor-providers.ts +59 -6
  725. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +2 -0
  726. package/src/resources/extensions/gsd/error-classifier.ts +36 -3
  727. package/src/resources/extensions/gsd/exec-history.ts +153 -0
  728. package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
  729. package/src/resources/extensions/gsd/file-lock.ts +84 -11
  730. package/src/resources/extensions/gsd/git-service.ts +1 -0
  731. package/src/resources/extensions/gsd/gitignore.ts +2 -1
  732. package/src/resources/extensions/gsd/gsd-db.ts +186 -23
  733. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
  734. package/src/resources/extensions/gsd/guided-flow.ts +259 -10
  735. package/src/resources/extensions/gsd/health-widget.ts +3 -1
  736. package/src/resources/extensions/gsd/hook-emitter.ts +188 -0
  737. package/src/resources/extensions/gsd/init-wizard.ts +15 -1
  738. package/src/resources/extensions/gsd/journal.ts +29 -3
  739. package/src/resources/extensions/gsd/key-manager.ts +28 -0
  740. package/src/resources/extensions/gsd/memory-backfill.ts +140 -0
  741. package/src/resources/extensions/gsd/memory-store.ts +26 -0
  742. package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
  743. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  744. package/src/resources/extensions/gsd/model-router.ts +42 -1
  745. package/src/resources/extensions/gsd/notifications.ts +27 -15
  746. package/src/resources/extensions/gsd/pre-execution-checks.ts +46 -10
  747. package/src/resources/extensions/gsd/preferences-types.ts +46 -0
  748. package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
  749. package/src/resources/extensions/gsd/preferences.ts +17 -17
  750. package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
  751. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  752. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  753. package/src/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
  754. package/src/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  755. package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
  756. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  757. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
  758. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  759. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  760. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -0
  761. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  762. package/src/resources/extensions/gsd/reports.ts +5 -4
  763. package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
  764. package/src/resources/extensions/gsd/safety/file-change-validator.ts +17 -4
  765. package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
  766. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  767. package/src/resources/extensions/gsd/state.ts +80 -34
  768. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +238 -4
  769. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  770. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +95 -1
  771. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
  772. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +122 -0
  773. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
  774. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +63 -0
  775. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
  776. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
  777. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
  778. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +98 -0
  779. package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +54 -0
  780. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
  781. package/src/resources/extensions/gsd/tests/cmux.test.ts +5 -9
  782. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +68 -66
  783. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
  784. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +15 -0
  785. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
  786. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  787. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  788. package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
  789. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +161 -0
  790. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  791. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +42 -0
  792. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +8 -4
  793. package/src/resources/extensions/gsd/tests/derive-state.test.ts +1 -2
  794. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +14 -9
  795. package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
  796. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  797. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  798. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +148 -3
  799. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
  800. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +306 -1
  801. package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
  802. package/src/resources/extensions/gsd/tests/exec-history.test.ts +237 -0
  803. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
  804. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  805. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +58 -0
  806. package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
  807. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +40 -9
  808. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +62 -0
  809. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +131 -0
  810. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +447 -1
  811. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  812. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
  813. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
  814. package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +11 -0
  815. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +78 -0
  816. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +4 -2
  817. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
  818. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
  819. package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +11 -0
  820. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +1 -1
  821. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
  822. package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
  823. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +101 -0
  824. package/src/resources/extensions/gsd/tests/key-manager.test.ts +9 -0
  825. package/src/resources/extensions/gsd/tests/load-memory-block.test.ts +36 -0
  826. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +76 -0
  827. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  828. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
  829. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  830. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +3 -3
  831. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  832. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +4 -2
  833. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +5 -0
  834. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
  835. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +150 -0
  836. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
  837. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
  838. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
  839. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +356 -0
  840. package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
  841. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
  842. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
  843. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +142 -29
  844. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +181 -0
  845. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
  846. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
  847. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  848. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
  849. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
  850. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  851. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
  852. package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
  853. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
  854. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
  855. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  856. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
  857. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +24 -0
  858. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  859. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
  860. package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
  861. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
  862. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
  863. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
  864. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  865. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  866. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  867. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  868. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +42 -2
  869. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  870. package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
  871. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +147 -8
  872. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +25 -2
  873. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
  874. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
  875. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
  876. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
  877. package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
  878. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
  879. package/src/resources/extensions/gsd/token-counter.ts +22 -5
  880. package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
  881. package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
  882. package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
  883. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
  884. package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
  885. package/src/resources/extensions/gsd/tools/memory-tools.ts +31 -1
  886. package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
  887. package/src/resources/extensions/gsd/uok/audit.ts +20 -2
  888. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  889. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  890. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  891. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  892. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  893. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  894. package/src/resources/extensions/gsd/uok/plan-v2.ts +39 -8
  895. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  896. package/src/resources/extensions/gsd/workflow-logger.ts +25 -3
  897. package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
  898. package/src/resources/extensions/gsd/workflow-templates/spike.md +6 -0
  899. package/src/resources/extensions/gsd/worktree-manager.ts +1 -0
  900. package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
  901. package/src/resources/extensions/mcp-client/auth.ts +12 -1
  902. package/src/resources/extensions/mcp-client/index.ts +129 -10
  903. package/src/resources/extensions/search-the-web/command-search-provider.ts +5 -4
  904. package/src/resources/extensions/search-the-web/native-search.ts +48 -12
  905. package/src/resources/extensions/shared/cmux-events.ts +59 -0
  906. package/src/resources/extensions/shared/rtk-session-stats.ts +1 -2
  907. package/src/resources/skills/api-design/SKILL.md +190 -0
  908. package/src/resources/skills/create-mcp-server/SKILL.md +121 -0
  909. package/src/resources/skills/create-skill/SKILL.md +2 -2
  910. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  911. package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  912. package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  913. package/src/resources/skills/decompose-into-slices/SKILL.md +139 -0
  914. package/src/resources/skills/dependency-upgrade/SKILL.md +158 -0
  915. package/src/resources/skills/design-an-interface/SKILL.md +102 -0
  916. package/src/resources/skills/forensics/SKILL.md +153 -0
  917. package/src/resources/skills/grill-me/SKILL.md +93 -0
  918. package/src/resources/skills/handoff/SKILL.md +121 -0
  919. package/src/resources/skills/observability/SKILL.md +174 -0
  920. package/src/resources/skills/security-review/SKILL.md +181 -0
  921. package/src/resources/skills/spike-wrap-up/SKILL.md +138 -0
  922. package/src/resources/skills/tdd/SKILL.md +112 -0
  923. package/src/resources/skills/verify-before-complete/SKILL.md +98 -0
  924. package/src/resources/skills/write-docs/SKILL.md +82 -0
  925. package/src/resources/skills/write-milestone-brief/SKILL.md +135 -0
  926. package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
  927. package/dist/web/standalone/.next/static/chunks/2826.e59e8578e2e28639.js +0 -9
  928. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +0 -1
  929. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  930. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  931. /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → vidAVJkURvTJ0_V2-64ro}/_buildManifest.js +0 -0
  932. /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → vidAVJkURvTJ0_V2-64ro}/_ssgManifest.js +0 -0
@@ -0,0 +1,916 @@
1
+ /**
2
+ * Remote Questions — self-contained MCP-server adapter
3
+ *
4
+ * Mirrors the routing logic from src/resources/extensions/ask-user-questions.ts
5
+ * but without any dependency on @gsd/pi-coding-agent or the main src/ tree.
6
+ * All channel adapters (Discord, Slack, Telegram), config resolution, HTTP
7
+ * calls, and polling are inlined here so packages/mcp-server remains a
8
+ * standalone package.
9
+ *
10
+ * Entry points consumed by server.ts:
11
+ * isRemoteConfigured() — cheap synchronous config check
12
+ * tryRemoteQuestions(...) — dispatch + poll + return result
13
+ */
14
+
15
+ import { readFileSync } from 'node:fs';
16
+ import { homedir } from 'node:os';
17
+ import { join } from 'node:path';
18
+ import { randomUUID } from 'node:crypto';
19
+
20
+ // ---------------------------------------------------------------------------
21
+ // Types
22
+ // ---------------------------------------------------------------------------
23
+
24
+ type RemoteChannel = 'slack' | 'discord' | 'telegram';
25
+
26
+ interface QuestionOption {
27
+ label: string;
28
+ description: string;
29
+ }
30
+
31
+ export interface RemoteQuestion {
32
+ id: string;
33
+ header: string;
34
+ question: string;
35
+ options: QuestionOption[];
36
+ allowMultiple?: boolean;
37
+ }
38
+
39
+ interface RemotePrompt {
40
+ id: string;
41
+ channel: RemoteChannel;
42
+ createdAt: number;
43
+ timeoutAt: number;
44
+ pollIntervalMs: number;
45
+ questions: RemoteQuestion[];
46
+ context: { source: string };
47
+ }
48
+
49
+ interface RemotePromptRef {
50
+ id: string;
51
+ channel: RemoteChannel;
52
+ messageId: string;
53
+ channelId: string;
54
+ threadTs?: string;
55
+ threadUrl?: string;
56
+ }
57
+
58
+ interface RemoteAnswer {
59
+ answers: Record<string, { answers: string[]; user_note?: string }>;
60
+ }
61
+
62
+ export interface RemoteToolResult {
63
+ content: Array<{ type: 'text'; text: string }>;
64
+ details?: Record<string, unknown>;
65
+ }
66
+
67
+ interface ResolvedConfig {
68
+ channel: RemoteChannel;
69
+ channelId: string;
70
+ timeoutMs: number;
71
+ pollIntervalMs: number;
72
+ token: string;
73
+ }
74
+
75
+ // ---------------------------------------------------------------------------
76
+ // Constants
77
+ // ---------------------------------------------------------------------------
78
+
79
+ const PER_REQUEST_TIMEOUT_MS = 15_000;
80
+ const DISCORD_API = 'https://discord.com/api/v10';
81
+ const SLACK_API = 'https://slack.com/api';
82
+ const TELEGRAM_API = 'https://api.telegram.org';
83
+
84
+ const DISCORD_NUMBER_EMOJIS = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣'];
85
+ const SLACK_NUMBER_REACTION_NAMES = ['one', 'two', 'three', 'four', 'five'];
86
+
87
+ const DEFAULT_TIMEOUT_MINUTES = 5;
88
+ const DEFAULT_POLL_INTERVAL_SECONDS = 5;
89
+ const MIN_TIMEOUT_MINUTES = 1;
90
+ const MAX_TIMEOUT_MINUTES = 30;
91
+ const MIN_POLL_INTERVAL_SECONDS = 2;
92
+ const MAX_POLL_INTERVAL_SECONDS = 30;
93
+
94
+ const CHANNEL_ID_PATTERNS: Record<RemoteChannel, RegExp> = {
95
+ slack: /^[A-Z0-9]{9,12}$/,
96
+ discord: /^\d{17,20}$/,
97
+ telegram: /^-?\d{5,20}$/,
98
+ };
99
+
100
+ const ENV_KEYS: Record<RemoteChannel, string> = {
101
+ slack: 'SLACK_BOT_TOKEN',
102
+ discord: 'DISCORD_BOT_TOKEN',
103
+ telegram: 'TELEGRAM_BOT_TOKEN',
104
+ };
105
+
106
+ // ---------------------------------------------------------------------------
107
+ // Config resolution — reads ~/.gsd/PREFERENCES.md YAML frontmatter
108
+ // ---------------------------------------------------------------------------
109
+
110
+ function clampNumber(value: unknown, fallback: number, min: number, max: number): number {
111
+ const n = typeof value === 'number' ? value : Number(value);
112
+ if (!Number.isFinite(n)) return fallback;
113
+ return Math.max(min, Math.min(max, n));
114
+ }
115
+
116
+ /**
117
+ * Minimal YAML frontmatter reader. Handles:
118
+ * ---
119
+ * key: value
120
+ * nested_key:
121
+ * child: value
122
+ * ---
123
+ * Sufficient for the flat remote_questions config block.
124
+ */
125
+ function parseSimpleFrontmatter(content: string): Record<string, unknown> {
126
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/m);
127
+ if (!match) return {};
128
+
129
+ const yaml = match[1];
130
+ const result: Record<string, unknown> = {};
131
+ let currentSection: string | null = null;
132
+ const sectionData: Record<string, Record<string, unknown>> = {};
133
+
134
+ for (const rawLine of yaml.split('\n')) {
135
+ const line = rawLine.replace(/\r$/, '');
136
+ if (!line.trim() || line.trim().startsWith('#')) continue;
137
+
138
+ // Top-level key (no indent)
139
+ const topMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_]*):\s*(.*)$/);
140
+ if (topMatch) {
141
+ currentSection = topMatch[1];
142
+ const val = topMatch[2].trim();
143
+ if (val) {
144
+ result[currentSection] = parseSimpleScalar(val);
145
+ currentSection = null; // scalar, no children
146
+ } else {
147
+ sectionData[currentSection] = {};
148
+ result[currentSection] = sectionData[currentSection];
149
+ }
150
+ continue;
151
+ }
152
+
153
+ // Indented child key
154
+ const childMatch = line.match(/^\s+([a-zA-Z_][a-zA-Z0-9_]*):\s*(.*)$/);
155
+ if (childMatch && currentSection && sectionData[currentSection]) {
156
+ const childKey = childMatch[1];
157
+ const childVal = childMatch[2].trim();
158
+ sectionData[currentSection][childKey] = parseSimpleScalar(childVal);
159
+ }
160
+ }
161
+
162
+ return result;
163
+ }
164
+
165
+ function parseSimpleScalar(raw: string): string | number | boolean | null {
166
+ const s = raw.replace(/^["']|["']$/g, '').trim();
167
+ if (s === 'true') return true;
168
+ if (s === 'false') return false;
169
+ if (s === 'null' || s === '~') return null;
170
+ const n = Number(s);
171
+ if (s !== '' && !Number.isNaN(n)) return n;
172
+ return s;
173
+ }
174
+
175
+ function loadPreferencesFromFile(path: string): Record<string, unknown> | null {
176
+ try {
177
+ const content = readFileSync(path, 'utf-8');
178
+ return parseSimpleFrontmatter(content);
179
+ } catch {
180
+ return null;
181
+ }
182
+ }
183
+
184
+ function resolveRemoteConfig(): ResolvedConfig | null {
185
+ const gsdHome = process.env['GSD_HOME'] ?? join(homedir(), '.gsd');
186
+ const globalPath = join(gsdHome, 'PREFERENCES.md');
187
+
188
+ const prefs = loadPreferencesFromFile(globalPath);
189
+ if (!prefs) return null;
190
+
191
+ const rq = prefs['remote_questions'] as Record<string, unknown> | undefined;
192
+ if (!rq || !rq['channel'] || !rq['channel_id']) return null;
193
+
194
+ const channel = String(rq['channel']) as RemoteChannel;
195
+ if (channel !== 'slack' && channel !== 'discord' && channel !== 'telegram') return null;
196
+
197
+ const channelId = String(rq['channel_id']);
198
+ if (!CHANNEL_ID_PATTERNS[channel].test(channelId)) return null;
199
+
200
+ const token = process.env[ENV_KEYS[channel]];
201
+ if (!token) return null;
202
+
203
+ const timeoutMs = clampNumber(rq['timeout_minutes'], DEFAULT_TIMEOUT_MINUTES, MIN_TIMEOUT_MINUTES, MAX_TIMEOUT_MINUTES) * 60 * 1000;
204
+ const pollIntervalMs = clampNumber(rq['poll_interval_seconds'], DEFAULT_POLL_INTERVAL_SECONDS, MIN_POLL_INTERVAL_SECONDS, MAX_POLL_INTERVAL_SECONDS) * 1000;
205
+
206
+ return { channel, channelId, timeoutMs, pollIntervalMs, token };
207
+ }
208
+
209
+ /**
210
+ * Cheap synchronous check — does not make any HTTP requests.
211
+ */
212
+ export function isRemoteConfigured(): boolean {
213
+ return resolveRemoteConfig() !== null;
214
+ }
215
+
216
+ // ---------------------------------------------------------------------------
217
+ // HTTP helper
218
+ // ---------------------------------------------------------------------------
219
+
220
+ async function apiRequest(
221
+ url: string,
222
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE',
223
+ body: unknown,
224
+ authScheme: 'Bearer' | 'Bot',
225
+ authToken: string,
226
+ errorLabel: string,
227
+ ): Promise<unknown> {
228
+ const headers: Record<string, string> = {
229
+ Authorization: `${authScheme} ${authToken}`,
230
+ };
231
+
232
+ const init: RequestInit = {
233
+ method,
234
+ headers,
235
+ signal: AbortSignal.timeout(PER_REQUEST_TIMEOUT_MS),
236
+ };
237
+
238
+ if (body !== undefined) {
239
+ headers['Content-Type'] = 'application/json';
240
+ init.body = JSON.stringify(body);
241
+ }
242
+
243
+ const response = await fetch(url, init);
244
+
245
+ if (response.status === 204) return {};
246
+
247
+ if (!response.ok) {
248
+ const text = await response.text().catch(() => '');
249
+ const safeText = text.length > 200 ? text.slice(0, 200) + '\u2026' : text;
250
+ throw new Error(`${errorLabel} HTTP ${response.status}: ${safeText}`);
251
+ }
252
+
253
+ return response.json();
254
+ }
255
+
256
+ // ---------------------------------------------------------------------------
257
+ // Payload formatting
258
+ // ---------------------------------------------------------------------------
259
+
260
+ function formatForDiscord(prompt: RemotePrompt): { embeds: unknown[]; reactionEmojis: string[] } {
261
+ const reactionEmojis: string[] = [];
262
+ const embeds = prompt.questions.map((q, questionIndex) => {
263
+ const supportsReactions = prompt.questions.length === 1;
264
+ const optionLines = q.options.map((opt, i) => {
265
+ const emoji = DISCORD_NUMBER_EMOJIS[i] ?? `${i + 1}.`;
266
+ if (supportsReactions && DISCORD_NUMBER_EMOJIS[i]) reactionEmojis.push(DISCORD_NUMBER_EMOJIS[i]);
267
+ return `${emoji} **${opt.label}** — ${opt.description}`;
268
+ });
269
+
270
+ const footerParts: string[] = [];
271
+ if (supportsReactions) {
272
+ footerParts.push(q.allowMultiple
273
+ ? 'Reply with comma-separated choices (`1,3`) or react with matching numbers'
274
+ : 'Reply with a number or react with the matching number');
275
+ } else {
276
+ footerParts.push(`Question ${questionIndex + 1}/${prompt.questions.length} — reply with one line per question or use semicolons`);
277
+ }
278
+ footerParts.push(`Source: ${prompt.context.source}`);
279
+
280
+ return {
281
+ title: q.header,
282
+ description: q.question,
283
+ color: 0x7c3aed,
284
+ fields: [{ name: 'Options', value: optionLines.join('\n') }],
285
+ footer: { text: footerParts.join(' · ') },
286
+ };
287
+ });
288
+
289
+ return { embeds, reactionEmojis };
290
+ }
291
+
292
+ function formatForSlack(prompt: RemotePrompt): unknown[] {
293
+ const blocks: unknown[] = [
294
+ { type: 'header', text: { type: 'plain_text', text: 'GSD needs your input' } },
295
+ ];
296
+
297
+ if (prompt.questions.length > 1) {
298
+ blocks.push({
299
+ type: 'context',
300
+ elements: [{ type: 'mrkdwn', text: 'Reply once in thread using one line per question or semicolons (`1; 2; custom note`).' }],
301
+ });
302
+ }
303
+
304
+ for (const q of prompt.questions) {
305
+ const supportsReactions = prompt.questions.length === 1;
306
+ blocks.push({ type: 'section', text: { type: 'mrkdwn', text: `*${q.header}*\n${q.question}` } });
307
+ blocks.push({
308
+ type: 'section',
309
+ text: { type: 'mrkdwn', text: q.options.map((opt, i) => `${i + 1}. *${opt.label}* — ${opt.description}`).join('\n') },
310
+ });
311
+ blocks.push({
312
+ type: 'context',
313
+ elements: [{
314
+ type: 'mrkdwn',
315
+ text: prompt.questions.length > 1
316
+ ? (q.allowMultiple ? 'For this question, use comma-separated numbers (`1,3`) or free text.' : 'For this question, use one number (`1`) or free text.')
317
+ : (q.allowMultiple
318
+ ? (supportsReactions ? 'Reply in thread with comma-separated numbers (`1,3`) or react with matching number emoji.' : 'Reply in thread with comma-separated numbers (`1,3`) or free text.')
319
+ : (supportsReactions ? 'Reply in thread with a number (`1`) or react with the matching number emoji.' : 'Reply in thread with a number (`1`) or free text.')),
320
+ }],
321
+ });
322
+ blocks.push({ type: 'divider' });
323
+ }
324
+
325
+ return blocks;
326
+ }
327
+
328
+ function formatForTelegram(prompt: RemotePrompt): { text: string; parse_mode: 'HTML'; reply_markup?: unknown } {
329
+ const escape = (s: string) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
330
+ const lines: string[] = ['<b>GSD needs your input</b>', ''];
331
+
332
+ for (let qi = 0; qi < prompt.questions.length; qi++) {
333
+ const q = prompt.questions[qi];
334
+ lines.push(`<b>${escape(q.header)}</b>`);
335
+ lines.push(escape(q.question));
336
+ lines.push('');
337
+ for (let i = 0; i < q.options.length; i++) {
338
+ lines.push(`${i + 1}. <b>${escape(q.options[i].label)}</b> — ${escape(q.options[i].description)}`);
339
+ }
340
+ lines.push('');
341
+ if (prompt.questions.length === 1) {
342
+ lines.push(q.allowMultiple ? 'Reply with comma-separated numbers (1,3) or free text.' : 'Reply with a number or tap a button below.');
343
+ } else {
344
+ lines.push(`Question ${qi + 1}/${prompt.questions.length} — reply with one line per question or use semicolons.`);
345
+ }
346
+ if (qi < prompt.questions.length - 1) lines.push('');
347
+ }
348
+
349
+ const result: { text: string; parse_mode: 'HTML'; reply_markup?: unknown } = {
350
+ text: lines.join('\n'),
351
+ parse_mode: 'HTML',
352
+ };
353
+
354
+ if (prompt.questions.length === 1 && prompt.questions[0].options.length <= 5) {
355
+ result.reply_markup = {
356
+ inline_keyboard: prompt.questions[0].options.map((opt, i) => [{
357
+ text: `${i + 1}. ${opt.label}`,
358
+ callback_data: `${prompt.id}:${i}`,
359
+ }]),
360
+ };
361
+ }
362
+
363
+ return result;
364
+ }
365
+
366
+ // ---------------------------------------------------------------------------
367
+ // Response parsing
368
+ // ---------------------------------------------------------------------------
369
+
370
+ function parseAnswerForQuestion(text: string, q: RemoteQuestion): { answers: string[]; user_note?: string } {
371
+ if (!text) return { answers: [], user_note: 'No response provided' };
372
+
373
+ if (/^[\d,\s]+$/.test(text)) {
374
+ const nums = text
375
+ .split(',')
376
+ .map((s) => parseInt(s.trim(), 10))
377
+ .filter((n) => !Number.isNaN(n) && n >= 1 && n <= q.options.length);
378
+ if (nums.length > 0) {
379
+ const selected = nums.map((n) => q.options[n - 1].label);
380
+ return { answers: q.allowMultiple ? selected : [selected[0]] };
381
+ }
382
+ }
383
+
384
+ const single = parseInt(text, 10);
385
+ if (!Number.isNaN(single) && single >= 1 && single <= q.options.length) {
386
+ return { answers: [q.options[single - 1].label] };
387
+ }
388
+
389
+ const truncated = text.length > 500 ? text.slice(0, 500) + '\u2026' : text;
390
+ return { answers: [], user_note: truncated };
391
+ }
392
+
393
+ function parseTextReply(text: string, questions: RemoteQuestion[]): RemoteAnswer {
394
+ const answers: RemoteAnswer['answers'] = {};
395
+ const trimmed = text.trim();
396
+
397
+ if (questions.length === 1) {
398
+ answers[questions[0].id] = parseAnswerForQuestion(trimmed, questions[0]);
399
+ return { answers };
400
+ }
401
+
402
+ const parts = trimmed.includes(';')
403
+ ? trimmed.split(';').map((s) => s.trim()).filter(Boolean)
404
+ : trimmed.split('\n').map((s) => s.trim()).filter(Boolean);
405
+
406
+ for (let i = 0; i < questions.length; i++) {
407
+ answers[questions[i].id] = parseAnswerForQuestion(parts[i] ?? '', questions[i]);
408
+ }
409
+
410
+ return { answers };
411
+ }
412
+
413
+ function parseDiscordReactions(
414
+ reactions: Array<{ emoji: string; count: number }>,
415
+ questions: RemoteQuestion[],
416
+ ): RemoteAnswer {
417
+ const answers: RemoteAnswer['answers'] = {};
418
+ if (questions.length !== 1) {
419
+ for (const q of questions) {
420
+ answers[q.id] = { answers: [], user_note: 'Discord reactions are only supported for single-question prompts' };
421
+ }
422
+ return { answers };
423
+ }
424
+
425
+ const q = questions[0];
426
+ const picked = reactions
427
+ .filter((r) => DISCORD_NUMBER_EMOJIS.includes(r.emoji) && r.count > 0)
428
+ .map((r) => q.options[DISCORD_NUMBER_EMOJIS.indexOf(r.emoji)]?.label)
429
+ .filter((l): l is string => Boolean(l));
430
+
431
+ answers[q.id] = picked.length > 0
432
+ ? { answers: q.allowMultiple ? picked : [picked[0]] }
433
+ : { answers: [], user_note: 'No clear response via reactions' };
434
+
435
+ return { answers };
436
+ }
437
+
438
+ function parseSlackReactions(reactionNames: string[], questions: RemoteQuestion[]): RemoteAnswer {
439
+ const answers: RemoteAnswer['answers'] = {};
440
+ if (questions.length !== 1) {
441
+ for (const q of questions) {
442
+ answers[q.id] = { answers: [], user_note: 'Slack reactions are only supported for single-question prompts' };
443
+ }
444
+ return { answers };
445
+ }
446
+
447
+ const q = questions[0];
448
+ const picked = reactionNames
449
+ .filter((name) => SLACK_NUMBER_REACTION_NAMES.includes(name))
450
+ .map((name) => q.options[SLACK_NUMBER_REACTION_NAMES.indexOf(name)]?.label)
451
+ .filter((l): l is string => Boolean(l));
452
+
453
+ answers[q.id] = picked.length > 0
454
+ ? { answers: q.allowMultiple ? picked : [picked[0]] }
455
+ : { answers: [], user_note: 'No clear response via reactions' };
456
+
457
+ return { answers };
458
+ }
459
+
460
+ function parseTelegramCallbackData(callbackData: string, questions: RemoteQuestion[], promptId: string): RemoteAnswer | null {
461
+ const pattern = new RegExp(`^${promptId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}:(\\d+)$`);
462
+ const match = callbackData.match(pattern);
463
+ if (match && questions.length === 1) {
464
+ const idx = parseInt(match[1], 10);
465
+ const q = questions[0];
466
+ if (idx >= 0 && idx < q.options.length) {
467
+ return { answers: { [q.id]: { answers: [q.options[idx].label] } } };
468
+ }
469
+ }
470
+ return null;
471
+ }
472
+
473
+ // ---------------------------------------------------------------------------
474
+ // Channel adapters
475
+ // ---------------------------------------------------------------------------
476
+
477
+ interface DispatchResult {
478
+ ref: RemotePromptRef;
479
+ }
480
+
481
+ // --- Discord ---
482
+
483
+ async function discordValidate(token: string, channelId: string): Promise<{ botUserId: string; guildId: string | null }> {
484
+ const meRes = await apiRequest(`${DISCORD_API}/users/@me`, 'GET', undefined, 'Bot', token, 'Discord API') as Record<string, unknown>;
485
+ if (!meRes['id']) throw new Error('Discord auth failed: invalid token');
486
+ const botUserId = String(meRes['id']);
487
+
488
+ let guildId: string | null = null;
489
+ try {
490
+ const chanRes = await apiRequest(`${DISCORD_API}/channels/${channelId}`, 'GET', undefined, 'Bot', token, 'Discord API') as Record<string, unknown>;
491
+ if (chanRes['guild_id']) guildId = String(chanRes['guild_id']);
492
+ } catch { /* non-fatal */ }
493
+
494
+ return { botUserId, guildId };
495
+ }
496
+
497
+ async function discordSend(prompt: RemotePrompt, token: string, channelId: string, guildId: string | null): Promise<DispatchResult> {
498
+ const { embeds, reactionEmojis } = formatForDiscord(prompt);
499
+ const res = await apiRequest(
500
+ `${DISCORD_API}/channels/${channelId}/messages`,
501
+ 'POST',
502
+ { content: '**GSD needs your input** — reply to this message with your answer', embeds },
503
+ 'Bot', token, 'Discord API',
504
+ ) as Record<string, unknown>;
505
+
506
+ if (!res['id']) throw new Error(`Discord send failed: ${JSON.stringify(res)}`);
507
+ const messageId = String(res['id']);
508
+
509
+ if (prompt.questions.length === 1) {
510
+ for (const emoji of reactionEmojis) {
511
+ try {
512
+ await apiRequest(`${DISCORD_API}/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/@me`, 'PUT', undefined, 'Bot', token, 'Discord API');
513
+ } catch { /* best-effort */ }
514
+ }
515
+ }
516
+
517
+ const threadUrl = guildId ? `https://discord.com/channels/${guildId}/${channelId}/${messageId}` : undefined;
518
+ return { ref: { id: prompt.id, channel: 'discord', messageId, channelId, threadUrl } };
519
+ }
520
+
521
+ async function discordPoll(prompt: RemotePrompt, ref: RemotePromptRef, token: string, botUserId: string): Promise<RemoteAnswer | null> {
522
+ // Try reactions first for single-question prompts
523
+ if (prompt.questions.length === 1) {
524
+ const reactions: Array<{ emoji: string; count: number }> = [];
525
+ for (const emoji of DISCORD_NUMBER_EMOJIS) {
526
+ try {
527
+ const users = await apiRequest(
528
+ `${DISCORD_API}/channels/${ref.channelId}/messages/${ref.messageId}/reactions/${encodeURIComponent(emoji)}`,
529
+ 'GET', undefined, 'Bot', token, 'Discord API',
530
+ ) as unknown[];
531
+ if (Array.isArray(users)) {
532
+ const humanUsers = users.filter((u) => (u as Record<string, unknown>)['id'] !== botUserId);
533
+ if (humanUsers.length > 0) reactions.push({ emoji, count: humanUsers.length });
534
+ }
535
+ } catch (err) {
536
+ const msg = String((err as Error).message ?? '');
537
+ if (msg.includes('HTTP 404')) continue;
538
+ if (msg.includes('HTTP 401') || msg.includes('HTTP 403')) throw err;
539
+ }
540
+ }
541
+ if (reactions.length > 0) return parseDiscordReactions(reactions, prompt.questions);
542
+ }
543
+
544
+ // Try text replies
545
+ const messages = await apiRequest(
546
+ `${DISCORD_API}/channels/${ref.channelId}/messages?after=${ref.messageId}&limit=10`,
547
+ 'GET', undefined, 'Bot', token, 'Discord API',
548
+ ) as unknown[];
549
+
550
+ if (!Array.isArray(messages)) return null;
551
+
552
+ const replies = messages.filter((m) => {
553
+ const msg = m as Record<string, unknown>;
554
+ const author = msg['author'] as Record<string, unknown> | undefined;
555
+ const msgRef = msg['message_reference'] as Record<string, unknown> | undefined;
556
+ return author?.['id'] && author['id'] !== botUserId && msgRef?.['message_id'] === ref.messageId && msg['content'];
557
+ });
558
+
559
+ if (replies.length === 0) return null;
560
+ const first = replies[0] as Record<string, unknown>;
561
+ return parseTextReply(String(first['content']), prompt.questions);
562
+ }
563
+
564
+ async function discordAcknowledge(ref: RemotePromptRef, token: string): Promise<void> {
565
+ try {
566
+ await apiRequest(
567
+ `${DISCORD_API}/channels/${ref.channelId}/messages/${ref.messageId}/reactions/${encodeURIComponent('✅')}/@me`,
568
+ 'PUT', undefined, 'Bot', token, 'Discord API',
569
+ );
570
+ } catch { /* best-effort */ }
571
+ }
572
+
573
+ // --- Slack ---
574
+
575
+ async function slackValidate(token: string): Promise<string> {
576
+ const res = await apiRequest(`${SLACK_API}/auth.test`, 'GET', undefined, 'Bearer', token, 'Slack API') as Record<string, unknown>;
577
+ if (!res['ok']) throw new Error(`Slack auth failed: ${res['error'] ?? 'invalid token'}`);
578
+ return String(res['user_id'] ?? '');
579
+ }
580
+
581
+ async function slackSend(prompt: RemotePrompt, token: string, channelId: string): Promise<DispatchResult> {
582
+ const res = await apiRequest(
583
+ `${SLACK_API}/chat.postMessage`,
584
+ 'POST',
585
+ { channel: channelId, text: 'GSD needs your input', blocks: formatForSlack(prompt) },
586
+ 'Bearer', token, 'Slack API',
587
+ ) as Record<string, unknown>;
588
+
589
+ if (!res['ok']) throw new Error(`Slack postMessage failed: ${res['error'] ?? 'unknown'}`);
590
+
591
+ const ts = String(res['ts']);
592
+ const channel = String(res['channel']);
593
+
594
+ if (prompt.questions.length === 1) {
595
+ const reactionNames = SLACK_NUMBER_REACTION_NAMES.slice(0, prompt.questions[0].options.length);
596
+ for (const name of reactionNames) {
597
+ try {
598
+ await apiRequest(`${SLACK_API}/reactions.add`, 'POST', { channel, timestamp: ts, name }, 'Bearer', token, 'Slack API');
599
+ } catch { /* best-effort */ }
600
+ }
601
+ }
602
+
603
+ return {
604
+ ref: {
605
+ id: prompt.id,
606
+ channel: 'slack',
607
+ messageId: ts,
608
+ threadTs: ts,
609
+ channelId: channel,
610
+ threadUrl: `https://slack.com/archives/${channel}/p${ts.replace('.', '')}`,
611
+ },
612
+ };
613
+ }
614
+
615
+ async function slackPoll(prompt: RemotePrompt, ref: RemotePromptRef, token: string, botUserId: string): Promise<RemoteAnswer | null> {
616
+ // Check reactions for single-question prompts
617
+ if (prompt.questions.length === 1) {
618
+ const qs = new URLSearchParams({ channel: ref.channelId, timestamp: ref.messageId, full: 'true' }).toString();
619
+ const res = await apiRequest(`${SLACK_API}/reactions.get?${qs}`, 'GET', undefined, 'Bearer', token, 'Slack API') as Record<string, unknown>;
620
+
621
+ if (res['ok']) {
622
+ const message = (res['message'] ?? {}) as { reactions?: Array<{ name?: string; count?: number; users?: string[] }> };
623
+ const reactions = Array.isArray(message.reactions) ? message.reactions : [];
624
+ const picked = reactions
625
+ .filter((r) => r.name && SLACK_NUMBER_REACTION_NAMES.includes(r.name))
626
+ .filter((r) => {
627
+ const count = Number(r.count ?? 0);
628
+ const users = Array.isArray(r.users) ? r.users.map(String) : [];
629
+ const botIncluded = botUserId ? users.includes(botUserId) : false;
630
+ return count > (botIncluded ? 1 : 0);
631
+ })
632
+ .map((r) => String(r.name));
633
+
634
+ if (picked.length > 0) return parseSlackReactions(picked, prompt.questions);
635
+ }
636
+ }
637
+
638
+ // Check thread replies
639
+ const qs = new URLSearchParams({ channel: ref.channelId, ts: ref.threadTs!, limit: '20' }).toString();
640
+ const res = await apiRequest(`${SLACK_API}/conversations.replies?${qs}`, 'GET', undefined, 'Bearer', token, 'Slack API') as Record<string, unknown>;
641
+
642
+ if (!res['ok']) return null;
643
+
644
+ const messages = (res['messages'] ?? []) as Array<{ user?: string; text?: string; ts: string }>;
645
+ const userReplies = messages.filter((m) => m.ts !== ref.threadTs && m.user && m.user !== botUserId && m.text);
646
+ if (userReplies.length === 0) return null;
647
+
648
+ return parseTextReply(String(userReplies[0].text), prompt.questions);
649
+ }
650
+
651
+ async function slackAcknowledge(ref: RemotePromptRef, token: string): Promise<void> {
652
+ try {
653
+ await apiRequest(
654
+ `${SLACK_API}/reactions.add`,
655
+ 'POST',
656
+ { channel: ref.channelId, timestamp: ref.messageId, name: 'white_check_mark' },
657
+ 'Bearer', token, 'Slack API',
658
+ );
659
+ } catch { /* best-effort */ }
660
+ }
661
+
662
+ // --- Telegram ---
663
+
664
+ async function telegramValidate(token: string): Promise<number> {
665
+ const res = await apiRequest(`${TELEGRAM_API}/bot${token}/getMe`, 'GET', undefined, 'Bearer', token, 'Telegram API') as Record<string, unknown>;
666
+ const result = res['result'] as Record<string, unknown> | undefined;
667
+ if (!res['ok'] || !result?.['id']) throw new Error('Telegram auth failed: invalid bot token');
668
+ return result['id'] as number;
669
+ }
670
+
671
+ async function telegramSend(prompt: RemotePrompt, token: string, chatId: string): Promise<DispatchResult> {
672
+ const payload = formatForTelegram(prompt);
673
+ const params: Record<string, unknown> = { chat_id: chatId, text: payload.text, parse_mode: payload.parse_mode };
674
+ if (payload.reply_markup) params['reply_markup'] = payload.reply_markup;
675
+
676
+ const res = await apiRequest(`${TELEGRAM_API}/bot${token}/sendMessage`, 'POST', params, 'Bearer', token, 'Telegram API') as Record<string, unknown>;
677
+ const result = res['result'] as Record<string, unknown> | undefined;
678
+ if (!res['ok'] || !result?.['message_id']) throw new Error(`Telegram sendMessage failed: ${JSON.stringify(res)}`);
679
+
680
+ const messageId = String(result['message_id']);
681
+ // Build public URL only for public channels (negative IDs are private groups)
682
+ const isPublic = !chatId.startsWith('-');
683
+ const messageUrl = isPublic ? `https://t.me/${chatId.replace('@', '')}/${messageId}` : undefined;
684
+
685
+ return { ref: { id: prompt.id, channel: 'telegram', messageId, channelId: chatId, threadUrl: messageUrl } };
686
+ }
687
+
688
+ async function telegramPoll(
689
+ prompt: RemotePrompt,
690
+ ref: RemotePromptRef,
691
+ token: string,
692
+ botUserId: number,
693
+ lastUpdateId: { value: number },
694
+ ): Promise<RemoteAnswer | null> {
695
+ const params: Record<string, unknown> = {
696
+ offset: lastUpdateId.value + 1,
697
+ timeout: 0,
698
+ allowed_updates: ['message', 'callback_query'],
699
+ };
700
+
701
+ const res = await apiRequest(`${TELEGRAM_API}/bot${token}/getUpdates`, 'POST', params, 'Bearer', token, 'Telegram API') as Record<string, unknown>;
702
+ if (!res['ok'] || !Array.isArray(res['result'])) return null;
703
+
704
+ for (const update of res['result'] as Record<string, unknown>[]) {
705
+ if ((update['update_id'] as number) > lastUpdateId.value) {
706
+ lastUpdateId.value = update['update_id'] as number;
707
+ }
708
+
709
+ // Callback query (inline keyboard button press)
710
+ if (update['callback_query']) {
711
+ const cq = update['callback_query'] as Record<string, unknown>;
712
+ const msg = cq['message'] as Record<string, unknown> | undefined;
713
+ const from = cq['from'] as Record<string, unknown> | undefined;
714
+ if (msg && String((msg['chat'] as Record<string, unknown>)?.['id']) === ref.channelId &&
715
+ String(msg['message_id']) === ref.messageId && from?.['id'] !== botUserId) {
716
+ // Dismiss loading spinner
717
+ try {
718
+ await apiRequest(`${TELEGRAM_API}/bot${token}/answerCallbackQuery`, 'POST', { callback_query_id: cq['id'] }, 'Bearer', token, 'Telegram API');
719
+ } catch { /* best-effort */ }
720
+ const callbackData = cq['data'] ? String(cq['data']) : null;
721
+ if (callbackData) {
722
+ const parsed = parseTelegramCallbackData(callbackData, prompt.questions, prompt.id);
723
+ if (parsed) return parsed;
724
+ }
725
+ }
726
+ }
727
+
728
+ // Text message reply
729
+ if (update['message']) {
730
+ const msg = update['message'] as Record<string, unknown>;
731
+ const from = msg['from'] as Record<string, unknown> | undefined;
732
+ if (String((msg['chat'] as Record<string, unknown>)?.['id']) === ref.channelId &&
733
+ from?.['id'] !== botUserId && msg['text']) {
734
+ return parseTextReply(String(msg['text']), prompt.questions);
735
+ }
736
+ }
737
+ }
738
+
739
+ return null;
740
+ }
741
+
742
+ // ---------------------------------------------------------------------------
743
+ // Polling loop
744
+ // ---------------------------------------------------------------------------
745
+
746
+ function sleep(ms: number, signal?: AbortSignal): Promise<void> {
747
+ return new Promise((resolve) => {
748
+ if (signal?.aborted) return resolve();
749
+ const timer = setTimeout(() => {
750
+ signal?.removeEventListener('abort', onAbort);
751
+ resolve();
752
+ }, ms);
753
+ const onAbort = () => { clearTimeout(timer); resolve(); };
754
+ signal?.addEventListener('abort', onAbort, { once: true });
755
+ });
756
+ }
757
+
758
+ interface ChannelState {
759
+ botUserId: string | number;
760
+ guildId?: string | null; // Discord only
761
+ lastUpdateId?: { value: number }; // Telegram only
762
+ }
763
+
764
+ async function pollUntilDone(
765
+ config: ResolvedConfig,
766
+ prompt: RemotePrompt,
767
+ ref: RemotePromptRef,
768
+ state: ChannelState,
769
+ signal?: AbortSignal,
770
+ ): Promise<RemoteAnswer | null> {
771
+ while (Date.now() < prompt.timeoutAt && !signal?.aborted) {
772
+ try {
773
+ let answer: RemoteAnswer | null = null;
774
+
775
+ if (config.channel === 'discord') {
776
+ answer = await discordPoll(prompt, ref, config.token, String(state.botUserId));
777
+ } else if (config.channel === 'slack') {
778
+ answer = await slackPoll(prompt, ref, config.token, String(state.botUserId));
779
+ } else {
780
+ answer = await telegramPoll(prompt, ref, config.token, state.botUserId as number, state.lastUpdateId!);
781
+ }
782
+
783
+ if (answer) return answer;
784
+ } catch {
785
+ // Non-fatal poll error — wait and retry
786
+ }
787
+
788
+ await sleep(prompt.pollIntervalMs, signal);
789
+ }
790
+
791
+ return null;
792
+ }
793
+
794
+ // ---------------------------------------------------------------------------
795
+ // Public entry point
796
+ // ---------------------------------------------------------------------------
797
+
798
+ function buildPrompt(questions: RemoteQuestion[], config: ResolvedConfig): RemotePrompt {
799
+ const createdAt = Date.now();
800
+ return {
801
+ id: randomUUID(),
802
+ channel: config.channel,
803
+ createdAt,
804
+ timeoutAt: createdAt + config.timeoutMs,
805
+ pollIntervalMs: config.pollIntervalMs,
806
+ context: { source: 'ask_user_questions' },
807
+ questions: questions.map((q) => ({
808
+ id: q.id,
809
+ header: q.header,
810
+ question: q.question,
811
+ options: q.options,
812
+ allowMultiple: q.allowMultiple ?? false,
813
+ })),
814
+ };
815
+ }
816
+
817
+ function formatForTool(answer: RemoteAnswer): Record<string, { answers: string[] }> {
818
+ const out: Record<string, { answers: string[] }> = {};
819
+ for (const [id, data] of Object.entries(answer.answers)) {
820
+ const list = [...data.answers];
821
+ if (data.user_note) list.push(`user_note: ${data.user_note}`);
822
+ out[id] = { answers: list };
823
+ }
824
+ return out;
825
+ }
826
+
827
+ /**
828
+ * Dispatch questions to the configured remote channel and wait for a response.
829
+ *
830
+ * Returns null when no remote channel is configured.
831
+ * Returns a tool result shaped like { content, details } on success or
832
+ * timeout — callers should check details.timed_out before trusting the result.
833
+ */
834
+ export async function tryRemoteQuestions(
835
+ questions: RemoteQuestion[],
836
+ signal?: AbortSignal,
837
+ ): Promise<RemoteToolResult | null> {
838
+ const config = resolveRemoteConfig();
839
+ if (!config) return null;
840
+
841
+ const prompt = buildPrompt(questions, config);
842
+
843
+ // Validate auth and send the prompt
844
+ let ref: RemotePromptRef;
845
+ let state: ChannelState;
846
+
847
+ try {
848
+ if (config.channel === 'discord') {
849
+ const { botUserId, guildId } = await discordValidate(config.token, config.channelId);
850
+ state = { botUserId, guildId };
851
+ const dispatch = await discordSend(prompt, config.token, config.channelId, guildId);
852
+ ref = dispatch.ref;
853
+ } else if (config.channel === 'slack') {
854
+ const botUserId = await slackValidate(config.token);
855
+ state = { botUserId };
856
+ const dispatch = await slackSend(prompt, config.token, config.channelId);
857
+ ref = dispatch.ref;
858
+ } else {
859
+ const botUserId = await telegramValidate(config.token);
860
+ state = { botUserId, lastUpdateId: { value: 0 } };
861
+ const dispatch = await telegramSend(prompt, config.token, config.channelId);
862
+ ref = dispatch.ref;
863
+ }
864
+ } catch (err) {
865
+ return {
866
+ content: [{ type: 'text', text: `Remote questions failed (${config.channel}): ${(err as Error).message}` }],
867
+ details: { remote: true, channel: config.channel, error: true, status: 'failed' },
868
+ };
869
+ }
870
+
871
+ const answer = await pollUntilDone(config, prompt, ref, state, signal);
872
+
873
+ if (!answer) {
874
+ const timedOut = !signal?.aborted;
875
+ return {
876
+ content: [{
877
+ type: 'text',
878
+ text: JSON.stringify({
879
+ timed_out: timedOut,
880
+ channel: config.channel,
881
+ prompt_id: prompt.id,
882
+ timeout_minutes: config.timeoutMs / 60000,
883
+ thread_url: ref.threadUrl ?? null,
884
+ message: `User did not respond within ${config.timeoutMs / 60000} minutes.`,
885
+ }),
886
+ }],
887
+ details: {
888
+ remote: true,
889
+ channel: config.channel,
890
+ timed_out: timedOut,
891
+ promptId: prompt.id,
892
+ threadUrl: ref.threadUrl ?? null,
893
+ status: signal?.aborted ? 'cancelled' : 'timed_out',
894
+ },
895
+ };
896
+ }
897
+
898
+ // Best-effort acknowledgement
899
+ try {
900
+ if (config.channel === 'discord') await discordAcknowledge(ref, config.token);
901
+ else if (config.channel === 'slack') await slackAcknowledge(ref, config.token);
902
+ } catch { /* best-effort */ }
903
+
904
+ return {
905
+ content: [{ type: 'text', text: JSON.stringify({ answers: formatForTool(answer) }) }],
906
+ details: {
907
+ remote: true,
908
+ channel: config.channel,
909
+ timed_out: false,
910
+ promptId: prompt.id,
911
+ threadUrl: ref.threadUrl ?? null,
912
+ questions,
913
+ status: 'answered',
914
+ },
915
+ };
916
+ }