gsd-pi 2.10.12 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (504) hide show
  1. package/dist/bundled-extension-paths.d.ts +2 -0
  2. package/dist/bundled-extension-paths.js +10 -0
  3. package/dist/loader.js +45 -28
  4. package/dist/onboarding.js +100 -0
  5. package/dist/resource-loader.js +12 -3
  6. package/dist/resources/GSD-WORKFLOW.md +661 -0
  7. package/dist/resources/agents/researcher.md +29 -0
  8. package/dist/resources/agents/scout.md +56 -0
  9. package/dist/resources/agents/worker.md +31 -0
  10. package/dist/resources/extensions/ask-user-questions.ts +289 -0
  11. package/dist/resources/extensions/async-jobs/async-bash-tool.ts +211 -0
  12. package/dist/resources/extensions/async-jobs/await-tool.ts +101 -0
  13. package/dist/resources/extensions/async-jobs/cancel-job-tool.ts +34 -0
  14. package/dist/resources/extensions/async-jobs/index.ts +133 -0
  15. package/dist/resources/extensions/async-jobs/job-manager.ts +211 -0
  16. package/dist/resources/extensions/bg-shell/index.ts +3179 -0
  17. package/dist/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
  18. package/dist/resources/extensions/browser-tools/capture.ts +165 -0
  19. package/dist/resources/extensions/browser-tools/core.d.ts +205 -0
  20. package/dist/resources/extensions/browser-tools/core.js +1057 -0
  21. package/dist/resources/extensions/browser-tools/evaluate-helpers.ts +184 -0
  22. package/dist/resources/extensions/browser-tools/index.ts +51 -0
  23. package/dist/resources/extensions/browser-tools/lifecycle.ts +270 -0
  24. package/dist/resources/extensions/browser-tools/package.json +24 -0
  25. package/dist/resources/extensions/browser-tools/refs.ts +264 -0
  26. package/dist/resources/extensions/browser-tools/settle.ts +197 -0
  27. package/dist/resources/extensions/browser-tools/state.ts +408 -0
  28. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +652 -0
  29. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +614 -0
  30. package/dist/resources/extensions/browser-tools/tools/assertions.ts +342 -0
  31. package/dist/resources/extensions/browser-tools/tools/forms.ts +801 -0
  32. package/dist/resources/extensions/browser-tools/tools/inspection.ts +492 -0
  33. package/dist/resources/extensions/browser-tools/tools/intent.ts +614 -0
  34. package/dist/resources/extensions/browser-tools/tools/interaction.ts +865 -0
  35. package/dist/resources/extensions/browser-tools/tools/navigation.ts +232 -0
  36. package/dist/resources/extensions/browser-tools/tools/pages.ts +303 -0
  37. package/dist/resources/extensions/browser-tools/tools/refs.ts +541 -0
  38. package/dist/resources/extensions/browser-tools/tools/screenshot.ts +83 -0
  39. package/dist/resources/extensions/browser-tools/tools/session.ts +400 -0
  40. package/dist/resources/extensions/browser-tools/tools/wait.ts +247 -0
  41. package/dist/resources/extensions/browser-tools/utils.ts +660 -0
  42. package/dist/resources/extensions/context7/index.ts +428 -0
  43. package/dist/resources/extensions/context7/package.json +11 -0
  44. package/dist/resources/extensions/get-secrets-from-user.ts +625 -0
  45. package/dist/resources/extensions/google-search/index.ts +336 -0
  46. package/dist/resources/extensions/google-search/package.json +9 -0
  47. package/dist/resources/extensions/gsd/activity-log.ts +116 -0
  48. package/dist/resources/extensions/gsd/auto.ts +3732 -0
  49. package/dist/resources/extensions/gsd/commands.ts +544 -0
  50. package/dist/resources/extensions/gsd/crash-recovery.ts +105 -0
  51. package/dist/resources/extensions/gsd/dashboard-overlay.ts +564 -0
  52. package/dist/resources/extensions/gsd/dispatch-guard.ts +78 -0
  53. package/dist/resources/extensions/gsd/docs/preferences-reference.md +278 -0
  54. package/dist/resources/extensions/gsd/doctor.ts +766 -0
  55. package/dist/resources/extensions/gsd/exit-command.ts +18 -0
  56. package/dist/resources/extensions/gsd/files.ts +857 -0
  57. package/dist/resources/extensions/gsd/git-service.ts +904 -0
  58. package/dist/resources/extensions/gsd/gitignore.ts +200 -0
  59. package/dist/resources/extensions/gsd/guided-flow.ts +1054 -0
  60. package/dist/resources/extensions/gsd/index.ts +735 -0
  61. package/dist/resources/extensions/gsd/metrics.ts +374 -0
  62. package/dist/resources/extensions/gsd/migrate/command.ts +218 -0
  63. package/dist/resources/extensions/gsd/migrate/index.ts +42 -0
  64. package/dist/resources/extensions/gsd/migrate/parser.ts +323 -0
  65. package/dist/resources/extensions/gsd/migrate/parsers.ts +624 -0
  66. package/dist/resources/extensions/gsd/migrate/preview.ts +48 -0
  67. package/dist/resources/extensions/gsd/migrate/transformer.ts +346 -0
  68. package/dist/resources/extensions/gsd/migrate/types.ts +370 -0
  69. package/dist/resources/extensions/gsd/migrate/validator.ts +55 -0
  70. package/dist/resources/extensions/gsd/migrate/writer.ts +539 -0
  71. package/dist/resources/extensions/gsd/native-git-bridge.ts +181 -0
  72. package/dist/resources/extensions/gsd/native-parser-bridge.ts +135 -0
  73. package/dist/resources/extensions/gsd/observability-validator.ts +408 -0
  74. package/dist/resources/extensions/gsd/package.json +11 -0
  75. package/dist/resources/extensions/gsd/paths.ts +339 -0
  76. package/dist/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  77. package/dist/resources/extensions/gsd/preferences.ts +988 -0
  78. package/dist/resources/extensions/gsd/prompt-loader.ts +92 -0
  79. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +25 -0
  80. package/dist/resources/extensions/gsd/prompts/complete-slice.md +27 -0
  81. package/dist/resources/extensions/gsd/prompts/discuss.md +237 -0
  82. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +29 -0
  83. package/dist/resources/extensions/gsd/prompts/execute-task.md +63 -0
  84. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -0
  85. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -0
  86. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +61 -0
  87. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +3 -0
  88. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +29 -0
  89. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -0
  90. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +13 -0
  91. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -0
  92. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +78 -0
  93. package/dist/resources/extensions/gsd/prompts/plan-slice.md +55 -0
  94. package/dist/resources/extensions/gsd/prompts/queue.md +100 -0
  95. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +48 -0
  96. package/dist/resources/extensions/gsd/prompts/replan-slice.md +39 -0
  97. package/dist/resources/extensions/gsd/prompts/research-milestone.md +37 -0
  98. package/dist/resources/extensions/gsd/prompts/research-slice.md +28 -0
  99. package/dist/resources/extensions/gsd/prompts/review-migration.md +66 -0
  100. package/dist/resources/extensions/gsd/prompts/run-uat.md +109 -0
  101. package/dist/resources/extensions/gsd/prompts/system.md +190 -0
  102. package/dist/resources/extensions/gsd/prompts/worktree-merge.md +123 -0
  103. package/dist/resources/extensions/gsd/roadmap-slices.ts +50 -0
  104. package/dist/resources/extensions/gsd/session-forensics.ts +500 -0
  105. package/dist/resources/extensions/gsd/skill-discovery.ts +137 -0
  106. package/dist/resources/extensions/gsd/state.ts +569 -0
  107. package/dist/resources/extensions/gsd/templates/context.md +76 -0
  108. package/dist/resources/extensions/gsd/templates/decisions.md +8 -0
  109. package/dist/resources/extensions/gsd/templates/milestone-summary.md +73 -0
  110. package/dist/resources/extensions/gsd/templates/plan.md +131 -0
  111. package/dist/resources/extensions/gsd/templates/preferences.md +23 -0
  112. package/dist/resources/extensions/gsd/templates/project.md +31 -0
  113. package/dist/resources/extensions/gsd/templates/reassessment.md +28 -0
  114. package/dist/resources/extensions/gsd/templates/requirements.md +81 -0
  115. package/dist/resources/extensions/gsd/templates/research.md +46 -0
  116. package/dist/resources/extensions/gsd/templates/roadmap.md +118 -0
  117. package/dist/resources/extensions/gsd/templates/secrets-manifest.md +22 -0
  118. package/dist/resources/extensions/gsd/templates/slice-context.md +58 -0
  119. package/dist/resources/extensions/gsd/templates/slice-summary.md +99 -0
  120. package/dist/resources/extensions/gsd/templates/state.md +19 -0
  121. package/dist/resources/extensions/gsd/templates/task-plan.md +52 -0
  122. package/dist/resources/extensions/gsd/templates/task-summary.md +57 -0
  123. package/dist/resources/extensions/gsd/templates/uat.md +54 -0
  124. package/dist/resources/extensions/gsd/tests/activity-log-prune.test.ts +297 -0
  125. package/dist/resources/extensions/gsd/tests/activity-log-save.test.ts +127 -0
  126. package/dist/resources/extensions/gsd/tests/auto-draft-pause.test.ts +109 -0
  127. package/dist/resources/extensions/gsd/tests/auto-preflight.test.ts +45 -0
  128. package/dist/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +196 -0
  129. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
  130. package/dist/resources/extensions/gsd/tests/collect-from-manifest.test.ts +469 -0
  131. package/dist/resources/extensions/gsd/tests/complete-milestone.test.ts +200 -0
  132. package/dist/resources/extensions/gsd/tests/cost-projection.test.ts +134 -0
  133. package/dist/resources/extensions/gsd/tests/derive-state-deps.test.ts +312 -0
  134. package/dist/resources/extensions/gsd/tests/derive-state-draft.test.ts +299 -0
  135. package/dist/resources/extensions/gsd/tests/derive-state.test.ts +660 -0
  136. package/dist/resources/extensions/gsd/tests/discuss-prompt.test.ts +27 -0
  137. package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +91 -0
  138. package/dist/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +170 -0
  139. package/dist/resources/extensions/gsd/tests/doctor.test.ts +594 -0
  140. package/dist/resources/extensions/gsd/tests/draft-promotion.test.ts +169 -0
  141. package/dist/resources/extensions/gsd/tests/exit-command.test.ts +50 -0
  142. package/dist/resources/extensions/gsd/tests/git-service.test.ts +1788 -0
  143. package/dist/resources/extensions/gsd/tests/idle-recovery.test.ts +577 -0
  144. package/dist/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +580 -0
  145. package/dist/resources/extensions/gsd/tests/manifest-status.test.ts +283 -0
  146. package/dist/resources/extensions/gsd/tests/metrics-io.test.ts +176 -0
  147. package/dist/resources/extensions/gsd/tests/metrics.test.ts +188 -0
  148. package/dist/resources/extensions/gsd/tests/migrate-command.test.ts +369 -0
  149. package/dist/resources/extensions/gsd/tests/migrate-parser.test.ts +757 -0
  150. package/dist/resources/extensions/gsd/tests/migrate-transformer.test.ts +635 -0
  151. package/dist/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +414 -0
  152. package/dist/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +297 -0
  153. package/dist/resources/extensions/gsd/tests/migrate-writer.test.ts +398 -0
  154. package/dist/resources/extensions/gsd/tests/must-have-parser.test.ts +291 -0
  155. package/dist/resources/extensions/gsd/tests/network-error-fallback.test.ts +54 -0
  156. package/dist/resources/extensions/gsd/tests/next-milestone-id.test.ts +66 -0
  157. package/dist/resources/extensions/gsd/tests/orphaned-branch.test.ts +353 -0
  158. package/dist/resources/extensions/gsd/tests/parsers.test.ts +1664 -0
  159. package/dist/resources/extensions/gsd/tests/plan-milestone.test.ts +133 -0
  160. package/dist/resources/extensions/gsd/tests/plan-quality-validator.test.ts +363 -0
  161. package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  162. package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  163. package/dist/resources/extensions/gsd/tests/queue-draft-detection.test.ts +126 -0
  164. package/dist/resources/extensions/gsd/tests/reassess-prompt.test.ts +142 -0
  165. package/dist/resources/extensions/gsd/tests/regex-hardening.test.ts +281 -0
  166. package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +155 -0
  167. package/dist/resources/extensions/gsd/tests/remote-status.test.ts +99 -0
  168. package/dist/resources/extensions/gsd/tests/replan-slice.test.ts +493 -0
  169. package/dist/resources/extensions/gsd/tests/requirements.test.ts +106 -0
  170. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +35 -0
  171. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +11 -0
  172. package/dist/resources/extensions/gsd/tests/roadmap-slices.test.ts +41 -0
  173. package/dist/resources/extensions/gsd/tests/run-uat.test.ts +316 -0
  174. package/dist/resources/extensions/gsd/tests/secure-env-collect.test.ts +185 -0
  175. package/dist/resources/extensions/gsd/tests/smart-entry-draft.test.ts +123 -0
  176. package/dist/resources/extensions/gsd/tests/test-helpers.ts +61 -0
  177. package/dist/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +219 -0
  178. package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +234 -0
  179. package/dist/resources/extensions/gsd/tests/workspace-index.test.ts +75 -0
  180. package/dist/resources/extensions/gsd/tests/worktree-integration.test.ts +234 -0
  181. package/dist/resources/extensions/gsd/tests/worktree-manager.test.ts +141 -0
  182. package/dist/resources/extensions/gsd/tests/worktree.test.ts +597 -0
  183. package/dist/resources/extensions/gsd/tests/write-gate.test.ts +122 -0
  184. package/dist/resources/extensions/gsd/types.ts +296 -0
  185. package/dist/resources/extensions/gsd/unit-runtime.ts +184 -0
  186. package/dist/resources/extensions/gsd/workspace-index.ts +189 -0
  187. package/dist/resources/extensions/gsd/worktree-command.ts +845 -0
  188. package/dist/resources/extensions/gsd/worktree-manager.ts +459 -0
  189. package/dist/resources/extensions/gsd/{worktree.js → worktree.ts} +92 -61
  190. package/dist/resources/extensions/mac-tools/index.ts +852 -0
  191. package/dist/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
  192. package/dist/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
  193. package/dist/resources/extensions/mcporter/index.ts +429 -0
  194. package/dist/resources/extensions/remote-questions/config.ts +81 -0
  195. package/dist/resources/extensions/remote-questions/discord-adapter.ts +128 -0
  196. package/dist/resources/extensions/remote-questions/format.ts +163 -0
  197. package/dist/resources/extensions/remote-questions/manager.ts +192 -0
  198. package/dist/resources/extensions/remote-questions/remote-command.ts +361 -0
  199. package/dist/resources/extensions/remote-questions/slack-adapter.ts +92 -0
  200. package/dist/resources/extensions/remote-questions/status.ts +31 -0
  201. package/dist/resources/extensions/remote-questions/store.ts +77 -0
  202. package/dist/resources/extensions/remote-questions/types.ts +75 -0
  203. package/dist/resources/extensions/search-the-web/cache.ts +78 -0
  204. package/dist/resources/extensions/search-the-web/command-search-provider.ts +99 -0
  205. package/dist/resources/extensions/search-the-web/format.ts +258 -0
  206. package/dist/resources/extensions/search-the-web/http.ts +238 -0
  207. package/dist/resources/extensions/search-the-web/index.ts +65 -0
  208. package/dist/resources/extensions/search-the-web/native-search.ts +165 -0
  209. package/dist/resources/extensions/search-the-web/provider.ts +136 -0
  210. package/dist/resources/extensions/search-the-web/tavily.ts +116 -0
  211. package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +581 -0
  212. package/dist/resources/extensions/search-the-web/tool-llm-context.ts +620 -0
  213. package/dist/resources/extensions/search-the-web/tool-search.ts +635 -0
  214. package/dist/resources/extensions/search-the-web/url-utils.ts +91 -0
  215. package/dist/resources/extensions/shared/bundled-extension-paths.ts +11 -0
  216. package/dist/resources/extensions/shared/confirm-ui.ts +126 -0
  217. package/dist/resources/extensions/shared/interview-ui.ts +613 -0
  218. package/dist/resources/extensions/shared/next-action-ui.ts +197 -0
  219. package/dist/resources/extensions/shared/progress-widget.ts +282 -0
  220. package/dist/resources/extensions/shared/terminal.ts +23 -0
  221. package/dist/resources/extensions/shared/thinking-widget.ts +107 -0
  222. package/dist/resources/extensions/shared/ui.ts +400 -0
  223. package/dist/resources/extensions/shared/wizard-ui.ts +551 -0
  224. package/dist/resources/extensions/slash-commands/audit.ts +88 -0
  225. package/dist/resources/extensions/slash-commands/clear.ts +10 -0
  226. package/dist/resources/extensions/slash-commands/create-extension.ts +297 -0
  227. package/dist/resources/extensions/slash-commands/create-slash-command.ts +234 -0
  228. package/dist/resources/extensions/slash-commands/index.ts +12 -0
  229. package/dist/resources/extensions/subagent/agents.ts +126 -0
  230. package/dist/resources/extensions/subagent/index.ts +1072 -0
  231. package/dist/resources/extensions/subagent/isolation.ts +498 -0
  232. package/dist/resources/extensions/ttsr/index.ts +163 -0
  233. package/dist/resources/extensions/ttsr/rule-loader.ts +121 -0
  234. package/dist/resources/extensions/ttsr/ttsr-interrupt.md +6 -0
  235. package/dist/resources/extensions/ttsr/ttsr-manager.ts +430 -0
  236. package/dist/resources/extensions/universal-config/discovery.ts +78 -0
  237. package/dist/resources/extensions/universal-config/format.ts +160 -0
  238. package/dist/resources/extensions/universal-config/index.ts +118 -0
  239. package/dist/resources/extensions/universal-config/package.json +11 -0
  240. package/dist/resources/extensions/universal-config/scanners.ts +579 -0
  241. package/dist/resources/extensions/universal-config/tests/discovery.test.ts +111 -0
  242. package/dist/resources/extensions/universal-config/tests/format.test.ts +111 -0
  243. package/dist/resources/extensions/universal-config/tests/scanners.test.ts +438 -0
  244. package/dist/resources/extensions/universal-config/tools.ts +60 -0
  245. package/dist/resources/extensions/universal-config/types.ts +116 -0
  246. package/dist/resources/extensions/voice/index.ts +271 -0
  247. package/dist/resources/extensions/voice/speech-recognizer.py +504 -0
  248. package/dist/resources/extensions/voice/speech-recognizer.swift +154 -0
  249. package/dist/resources/skills/debug-like-expert/SKILL.md +231 -0
  250. package/dist/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
  251. package/dist/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
  252. package/dist/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
  253. package/dist/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
  254. package/dist/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
  255. package/dist/resources/skills/frontend-design/SKILL.md +45 -0
  256. package/dist/resources/skills/github-workflows/SKILL.md +92 -0
  257. package/dist/resources/skills/github-workflows/references/gh/SKILL.md +255 -0
  258. package/dist/resources/skills/github-workflows/references/gh/references/issue-stories.md +204 -0
  259. package/dist/resources/skills/github-workflows/references/gh/references/labels.md +170 -0
  260. package/dist/resources/skills/github-workflows/references/gh/references/milestones.md +158 -0
  261. package/dist/resources/skills/github-workflows/references/gh/references/projects-v2.md +177 -0
  262. package/dist/resources/skills/github-workflows/references/gh/scripts/experiment_cleanup.py +191 -0
  263. package/dist/resources/skills/github-workflows/references/gh/scripts/github_project_setup.py +799 -0
  264. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  265. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
  266. package/dist/resources/skills/swiftui/SKILL.md +208 -0
  267. package/dist/resources/skills/swiftui/references/animations.md +921 -0
  268. package/dist/resources/skills/swiftui/references/architecture.md +1561 -0
  269. package/dist/resources/skills/swiftui/references/layout-system.md +1186 -0
  270. package/dist/resources/skills/swiftui/references/navigation.md +1492 -0
  271. package/dist/resources/skills/swiftui/references/networking-async.md +214 -0
  272. package/dist/resources/skills/swiftui/references/performance.md +1706 -0
  273. package/dist/resources/skills/swiftui/references/platform-integration.md +204 -0
  274. package/dist/resources/skills/swiftui/references/state-management.md +1443 -0
  275. package/dist/resources/skills/swiftui/references/swiftdata.md +297 -0
  276. package/dist/resources/skills/swiftui/references/testing-debugging.md +247 -0
  277. package/dist/resources/skills/swiftui/references/uikit-appkit-interop.md +218 -0
  278. package/dist/resources/skills/swiftui/workflows/add-feature.md +191 -0
  279. package/dist/resources/skills/swiftui/workflows/build-new-app.md +311 -0
  280. package/dist/resources/skills/swiftui/workflows/debug-swiftui.md +192 -0
  281. package/dist/resources/skills/swiftui/workflows/optimize-performance.md +197 -0
  282. package/dist/resources/skills/swiftui/workflows/ship-app.md +203 -0
  283. package/dist/resources/skills/swiftui/workflows/write-tests.md +235 -0
  284. package/dist/wizard.js +1 -0
  285. package/package.json +8 -6
  286. package/packages/native/dist/fd/index.d.ts +1 -0
  287. package/packages/native/dist/fd/index.js +1 -0
  288. package/packages/native/dist/grep/index.d.ts +2 -1
  289. package/packages/native/dist/grep/index.js +1 -0
  290. package/packages/native/src/__tests__/fd.test.mjs +35 -0
  291. package/packages/native/src/__tests__/grep.test.mjs +26 -9
  292. package/packages/native/src/fd/index.ts +1 -0
  293. package/packages/native/src/grep/index.ts +3 -2
  294. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  295. package/packages/pi-agent-core/dist/agent-loop.js +169 -55
  296. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  297. package/packages/pi-agent-core/dist/agent.d.ts +13 -1
  298. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  299. package/packages/pi-agent-core/dist/agent.js +16 -0
  300. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  301. package/packages/pi-agent-core/dist/types.d.ts +91 -1
  302. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  303. package/packages/pi-agent-core/dist/types.js.map +1 -1
  304. package/packages/pi-agent-core/src/agent-loop.ts +273 -63
  305. package/packages/pi-agent-core/src/agent.ts +24 -0
  306. package/packages/pi-agent-core/src/types.ts +98 -0
  307. package/packages/pi-ai/dist/env-api-keys.js +2 -0
  308. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  309. package/packages/pi-ai/dist/models.generated.d.ts +314 -0
  310. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  311. package/packages/pi-ai/dist/models.generated.js +236 -0
  312. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  313. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  314. package/packages/pi-ai/dist/providers/google-gemini-cli.js +6 -0
  315. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  316. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  317. package/packages/pi-ai/dist/providers/openai-completions.js +2 -0
  318. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  319. package/packages/pi-ai/dist/types.d.ts +1 -1
  320. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  321. package/packages/pi-ai/dist/types.js.map +1 -1
  322. package/packages/pi-ai/src/env-api-keys.ts +2 -0
  323. package/packages/pi-ai/src/models.generated.ts +236 -0
  324. package/packages/pi-ai/src/providers/google-gemini-cli.ts +8 -0
  325. package/packages/pi-ai/src/providers/openai-completions.ts +3 -0
  326. package/packages/pi-ai/src/types.ts +2 -1
  327. package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  328. package/packages/pi-coding-agent/dist/cli/args.js +1 -0
  329. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  330. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +26 -0
  331. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/agent-session.js +137 -22
  333. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +20 -0
  335. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  336. package/packages/pi-coding-agent/dist/core/auth-storage.js +43 -0
  337. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts +51 -0
  339. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +119 -0
  341. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -0
  342. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.d.ts +2 -0
  343. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +183 -0
  345. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
  347. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/index.js +1 -0
  349. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  351. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  352. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +12 -1
  354. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/session-manager.js +37 -1
  356. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  357. package/packages/pi-coding-agent/dist/core/session-manager.test.d.ts +2 -0
  358. package/packages/pi-coding-agent/dist/core/session-manager.test.d.ts.map +1 -0
  359. package/packages/pi-coding-agent/dist/core/session-manager.test.js +61 -0
  360. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -0
  361. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
  362. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  363. package/packages/pi-coding-agent/dist/core/settings-manager.js +47 -0
  364. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  365. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  366. package/packages/pi-coding-agent/dist/core/tools/find.js +1 -0
  367. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  368. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +6 -15
  370. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +18 -1
  372. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +46 -4
  374. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  375. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  376. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +25 -2
  377. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  378. package/packages/pi-coding-agent/src/cli/args.ts +1 -0
  379. package/packages/pi-coding-agent/src/core/agent-session.ts +167 -22
  380. package/packages/pi-coding-agent/src/core/auth-storage.ts +45 -0
  381. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +229 -0
  382. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +165 -0
  383. package/packages/pi-coding-agent/src/core/index.ts +1 -0
  384. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  385. package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -0
  386. package/packages/pi-coding-agent/src/core/session-manager.ts +51 -1
  387. package/packages/pi-coding-agent/src/core/settings-manager.ts +66 -0
  388. package/packages/pi-coding-agent/src/core/tools/find.ts +1 -0
  389. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +6 -16
  390. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +49 -4
  391. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -2
  392. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  393. package/packages/pi-tui/dist/autocomplete.js +3 -4
  394. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  395. package/packages/pi-tui/dist/components/editor.d.ts +7 -0
  396. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  397. package/packages/pi-tui/dist/components/editor.js +57 -50
  398. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  399. package/packages/pi-tui/src/autocomplete.ts +3 -5
  400. package/packages/pi-tui/src/components/editor.ts +70 -49
  401. package/pkg/dist/core/export-html/ansi-to-html.d.ts +22 -0
  402. package/pkg/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  403. package/pkg/dist/core/export-html/ansi-to-html.js +249 -0
  404. package/pkg/dist/core/export-html/ansi-to-html.js.map +1 -0
  405. package/pkg/dist/core/export-html/index.d.ts +37 -0
  406. package/pkg/dist/core/export-html/index.d.ts.map +1 -0
  407. package/pkg/dist/core/export-html/index.js +223 -0
  408. package/pkg/dist/core/export-html/index.js.map +1 -0
  409. package/pkg/dist/core/export-html/template.css +971 -0
  410. package/pkg/dist/core/export-html/template.html +54 -0
  411. package/pkg/dist/core/export-html/template.js +1583 -0
  412. package/pkg/dist/core/export-html/tool-renderer.d.ts +38 -0
  413. package/pkg/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  414. package/pkg/dist/core/export-html/tool-renderer.js +70 -0
  415. package/pkg/dist/core/export-html/tool-renderer.js.map +1 -0
  416. package/pkg/dist/core/export-html/vendor/highlight.min.js +1213 -0
  417. package/pkg/dist/core/export-html/vendor/marked.min.js +6 -0
  418. package/scripts/postinstall.js +30 -17
  419. package/src/resources/extensions/bg-shell/index.ts +51 -7
  420. package/src/resources/extensions/gsd/activity-log.ts +61 -14
  421. package/src/resources/extensions/gsd/auto.ts +288 -19
  422. package/src/resources/extensions/gsd/commands.ts +9 -3
  423. package/src/resources/extensions/gsd/dashboard-overlay.ts +55 -12
  424. package/src/resources/extensions/gsd/docs/preferences-reference.md +25 -0
  425. package/src/resources/extensions/gsd/doctor.ts +60 -3
  426. package/src/resources/extensions/gsd/files.ts +45 -1
  427. package/src/resources/extensions/gsd/git-service.ts +46 -41
  428. package/src/resources/extensions/gsd/guided-flow.ts +81 -9
  429. package/src/resources/extensions/gsd/index.ts +62 -1
  430. package/src/resources/extensions/gsd/native-git-bridge.ts +181 -0
  431. package/src/resources/extensions/gsd/paths.ts +35 -4
  432. package/src/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  433. package/src/resources/extensions/gsd/preferences.ts +232 -1
  434. package/src/resources/extensions/gsd/prompt-loader.ts +45 -3
  435. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  436. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -3
  437. package/src/resources/extensions/gsd/prompts/discuss.md +10 -8
  438. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  439. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -1
  440. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -1
  441. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  442. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +3 -1
  443. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +4 -2
  444. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -1
  445. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +3 -1
  446. package/src/resources/extensions/gsd/prompts/plan-milestone.md +9 -12
  447. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -3
  448. package/src/resources/extensions/gsd/prompts/queue.md +3 -1
  449. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  450. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  451. package/src/resources/extensions/gsd/state.ts +130 -18
  452. package/src/resources/extensions/gsd/templates/context.md +1 -1
  453. package/src/resources/extensions/gsd/templates/state.md +3 -3
  454. package/src/resources/extensions/gsd/tests/activity-log-save.test.ts +127 -0
  455. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +5 -1
  456. package/src/resources/extensions/gsd/tests/doctor.test.ts +115 -1
  457. package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +6 -2
  458. package/src/resources/extensions/gsd/tests/git-service.test.ts +35 -35
  459. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +8 -8
  460. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +4 -1
  461. package/src/resources/extensions/gsd/tests/network-error-fallback.test.ts +54 -0
  462. package/src/resources/extensions/gsd/tests/orphaned-branch.test.ts +5 -5
  463. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  464. package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  465. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +12 -0
  466. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +6 -0
  467. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +4 -4
  468. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +4 -4
  469. package/src/resources/extensions/gsd/tests/worktree.test.ts +19 -19
  470. package/src/resources/extensions/gsd/types.ts +109 -0
  471. package/src/resources/extensions/gsd/worktree-manager.ts +72 -13
  472. package/src/resources/extensions/gsd/worktree.ts +5 -4
  473. package/src/resources/extensions/search-the-web/command-search-provider.ts +8 -4
  474. package/src/resources/extensions/search-the-web/native-search.ts +32 -23
  475. package/src/resources/extensions/search-the-web/provider.ts +19 -2
  476. package/src/resources/extensions/search-the-web/tool-fetch-page.ts +62 -0
  477. package/src/resources/extensions/search-the-web/tool-llm-context.ts +62 -3
  478. package/src/resources/extensions/search-the-web/tool-search.ts +62 -3
  479. package/src/resources/extensions/shared/bundled-extension-paths.ts +11 -0
  480. package/src/resources/extensions/subagent/index.ts +2 -1
  481. package/src/resources/skills/github-workflows/SKILL.md +5 -0
  482. package/dist/resources/extensions/gsd/git-service.d.ts +0 -225
  483. package/dist/resources/extensions/gsd/git-service.js +0 -756
  484. package/dist/resources/extensions/gsd/preferences.d.ts +0 -122
  485. package/dist/resources/extensions/gsd/preferences.js +0 -616
  486. package/dist/resources/extensions/gsd/worktree.d.ts +0 -106
  487. package/dist/resources/extensions/remote-questions/config.d.ts +0 -14
  488. package/dist/resources/extensions/remote-questions/config.js +0 -68
  489. package/dist/resources/extensions/remote-questions/discord-adapter.d.ts +0 -17
  490. package/dist/resources/extensions/remote-questions/discord-adapter.js +0 -118
  491. package/dist/resources/extensions/remote-questions/format.d.ts +0 -38
  492. package/dist/resources/extensions/remote-questions/format.js +0 -119
  493. package/dist/resources/extensions/remote-questions/manager.d.ts +0 -23
  494. package/dist/resources/extensions/remote-questions/manager.js +0 -161
  495. package/dist/resources/extensions/remote-questions/remote-command.d.ts +0 -6
  496. package/dist/resources/extensions/remote-questions/remote-command.js +0 -358
  497. package/dist/resources/extensions/remote-questions/slack-adapter.d.ts +0 -15
  498. package/dist/resources/extensions/remote-questions/slack-adapter.js +0 -82
  499. package/dist/resources/extensions/remote-questions/status.d.ts +0 -9
  500. package/dist/resources/extensions/remote-questions/status.js +0 -25
  501. package/dist/resources/extensions/remote-questions/store.d.ts +0 -11
  502. package/dist/resources/extensions/remote-questions/store.js +0 -66
  503. package/dist/resources/extensions/remote-questions/types.d.ts +0 -68
  504. package/dist/resources/extensions/remote-questions/types.js +0 -4
@@ -0,0 +1,264 @@
1
+ /**
2
+ * browser-tools — ref snapshot and resolution
3
+ *
4
+ * Builds deterministic element snapshots and resolves ref targets.
5
+ * Uses window.__pi.* utilities injected via addInitScript (from
6
+ * evaluate-helpers.ts) instead of redeclaring functions inline.
7
+ *
8
+ * Functions kept inline (not shared/duplicated):
9
+ * - matchesMode, computeNearestHeading, computeFormOwnership
10
+ */
11
+
12
+ import type { Frame, Page } from "playwright";
13
+ import type { RefNode } from "./state.js";
14
+ import { getSnapshotModeConfig } from "./core.js";
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // buildRefSnapshot
18
+ // ---------------------------------------------------------------------------
19
+
20
+ export async function buildRefSnapshot(
21
+ target: Page | Frame,
22
+ options: { selector?: string; interactiveOnly: boolean; limit: number; mode?: string },
23
+ ): Promise<Array<Omit<RefNode, "ref">>> {
24
+ // Resolve mode config in Node context and serialize it as plain data for the evaluate callback
25
+ const modeConfig = options.mode ? getSnapshotModeConfig(options.mode) : null;
26
+ return await target.evaluate(({ selector, interactiveOnly, limit, modeConfig: mc }) => {
27
+ const root = selector ? document.querySelector(selector) : document.body;
28
+ if (!root) {
29
+ throw new Error(`Selector scope not found: ${selector}`);
30
+ }
31
+
32
+ // Use injected window.__pi utilities
33
+ const pi = (window as any).__pi;
34
+ const simpleHash = pi.simpleHash;
35
+ const isVisible = pi.isVisible;
36
+ const isEnabled = pi.isEnabled;
37
+ const inferRole = pi.inferRole;
38
+ const accessibleName = pi.accessibleName;
39
+ const isInteractiveEl = pi.isInteractiveEl;
40
+ const cssPath = pi.cssPath;
41
+ const domPath = pi.domPath;
42
+ const selectorHints = pi.selectorHints;
43
+
44
+ // Mode-based element matching — used when a snapshot mode config is provided
45
+ const matchesMode = (el: Element, cfg: { tags: string[]; roles: string[]; selectors: string[]; ariaAttributes: string[] }): boolean => {
46
+ const tag = el.tagName.toLowerCase();
47
+ if (cfg.tags.length > 0 && cfg.tags.includes(tag)) return true;
48
+ const role = inferRole(el);
49
+ if (cfg.roles.length > 0 && cfg.roles.includes(role)) return true;
50
+ for (const sel of cfg.selectors) {
51
+ try { if (el.matches(sel)) return true; } catch { /* invalid selector, skip */ }
52
+ }
53
+ for (const attr of cfg.ariaAttributes) {
54
+ if (el.hasAttribute(attr)) return true;
55
+ }
56
+ return false;
57
+ };
58
+
59
+ let elements = Array.from(root.querySelectorAll("*"));
60
+
61
+ if (mc) {
62
+ // Mode takes precedence over interactiveOnly
63
+ if (mc.visibleOnly) {
64
+ // visible_only mode: include all elements that are visible
65
+ elements = elements.filter((el) => isVisible(el));
66
+ } else if (mc.useInteractiveFilter) {
67
+ // interactive mode: reuse existing isInteractiveEl
68
+ elements = elements.filter((el) => isInteractiveEl(el));
69
+ } else if (mc.containerExpand) {
70
+ // Container-expanding modes (dialog, errors): match containers, then include
71
+ // all interactive children of those containers, plus the containers themselves
72
+ const containers: Element[] = [];
73
+ const directMatches: Element[] = [];
74
+ for (const el of elements) {
75
+ if (matchesMode(el, mc)) {
76
+ // Check if this is a container element (has children)
77
+ const childEls = el.querySelectorAll("*");
78
+ if (childEls.length > 0) {
79
+ containers.push(el);
80
+ } else {
81
+ directMatches.push(el);
82
+ }
83
+ }
84
+ }
85
+ // Collect container elements + all interactive children inside containers
86
+ const result = new Set<Element>(directMatches);
87
+ for (const container of containers) {
88
+ result.add(container);
89
+ const children = Array.from(container.querySelectorAll("*"));
90
+ for (const child of children) {
91
+ if (isInteractiveEl(child)) result.add(child);
92
+ }
93
+ }
94
+ elements = Array.from(result);
95
+ } else {
96
+ // Standard mode filtering by tag/role/selector/ariaAttribute
97
+ elements = elements.filter((el) => matchesMode(el, mc));
98
+ }
99
+ } else if (!interactiveOnly) {
100
+ if (root instanceof Element) elements.unshift(root);
101
+ } else {
102
+ elements = elements.filter((el) => isInteractiveEl(el));
103
+ }
104
+
105
+ const seen = new Set<Element>();
106
+ const unique = elements.filter((el) => {
107
+ if (seen.has(el)) return false;
108
+ seen.add(el);
109
+ return true;
110
+ });
111
+
112
+ // Fingerprint helpers — computed for each element in the snapshot
113
+ const computeNearestHeading = (el: Element): string => {
114
+ const headingTags = new Set(["H1", "H2", "H3", "H4", "H5", "H6"]);
115
+ // Walk up ancestors looking for heading or preceding-sibling heading
116
+ let current: Element | null = el;
117
+ while (current && current !== document.body) {
118
+ // Check preceding siblings of current
119
+ let sib: Element | null = current.previousElementSibling;
120
+ while (sib) {
121
+ if (headingTags.has(sib.tagName) || sib.getAttribute("role") === "heading") {
122
+ return (sib.textContent || "").trim().replace(/\s+/g, " ").slice(0, 80);
123
+ }
124
+ sib = sib.previousElementSibling;
125
+ }
126
+ // Check if the parent itself is a heading (unlikely but possible)
127
+ const parent: Element | null = current.parentElement;
128
+ if (parent && (headingTags.has(parent.tagName) || parent.getAttribute("role") === "heading")) {
129
+ return (parent.textContent || "").trim().replace(/\s+/g, " ").slice(0, 80);
130
+ }
131
+ current = parent;
132
+ }
133
+ return "";
134
+ };
135
+
136
+ const computeFormOwnership = (el: Element): string => {
137
+ // Check form attribute (explicit form association)
138
+ const formAttr = el.getAttribute("form");
139
+ if (formAttr) return formAttr;
140
+ // Walk up ancestors looking for <form>
141
+ let current: Element | null = el.parentElement;
142
+ while (current && current !== document.body) {
143
+ if (current.tagName === "FORM") {
144
+ return (current as HTMLFormElement).id || (current as HTMLFormElement).name || "form";
145
+ }
146
+ current = current.parentElement;
147
+ }
148
+ return "";
149
+ };
150
+
151
+ return unique.slice(0, limit).map((el) => {
152
+ const tag = el.tagName.toLowerCase();
153
+ const role = inferRole(el);
154
+ const textContent = (el.textContent || "").trim().replace(/\s+/g, " ").slice(0, 200);
155
+ const childTags = Array.from(el.children).map((c) => c.tagName.toLowerCase());
156
+
157
+ return {
158
+ tag,
159
+ role,
160
+ name: accessibleName(el),
161
+ selectorHints: selectorHints(el),
162
+ isVisible: isVisible(el),
163
+ isEnabled: isEnabled(el),
164
+ xpathOrPath: cssPath(el),
165
+ href: el.getAttribute("href") || undefined,
166
+ type: el.getAttribute("type") || undefined,
167
+ path: domPath(el),
168
+ contentHash: simpleHash(textContent),
169
+ structuralSignature: simpleHash(`${tag}|${role}|${childTags.join(",")}`),
170
+ nearestHeading: computeNearestHeading(el),
171
+ formOwnership: computeFormOwnership(el),
172
+ };
173
+ });
174
+ }, { ...options, modeConfig });
175
+ }
176
+
177
+ // ---------------------------------------------------------------------------
178
+ // resolveRefTarget
179
+ // ---------------------------------------------------------------------------
180
+
181
+ export async function resolveRefTarget(
182
+ target: Page | Frame,
183
+ node: RefNode,
184
+ ): Promise<{ ok: true; selector: string } | { ok: false; reason: string }> {
185
+ return await target.evaluate((refNode) => {
186
+ // Use injected window.__pi utilities
187
+ const pi = (window as any).__pi;
188
+ const cssPath = pi.cssPath;
189
+ const simpleHash = pi.simpleHash;
190
+
191
+ const byPath = (): Element | null => {
192
+ let current: Element | null = document.documentElement;
193
+ for (const idx of refNode.path || []) {
194
+ if (!current || idx < 0 || idx >= current.children.length) return null;
195
+ current = current.children[idx] as Element;
196
+ }
197
+ return current;
198
+ };
199
+
200
+ const nodeName = (el: Element): string => {
201
+ return (
202
+ el.getAttribute("aria-label")?.trim() ||
203
+ (el as HTMLInputElement).value?.trim() ||
204
+ el.getAttribute("placeholder")?.trim() ||
205
+ (el.textContent || "").trim().replace(/\s+/g, " ").slice(0, 80)
206
+ );
207
+ };
208
+
209
+ // Tier 1: path-based resolution
210
+ const pathEl = byPath();
211
+ if (pathEl && pathEl.tagName.toLowerCase() === refNode.tag) {
212
+ return { ok: true as const, selector: cssPath(pathEl) };
213
+ }
214
+
215
+ // Tier 2: selector hints
216
+ for (const hint of refNode.selectorHints || []) {
217
+ try {
218
+ const el = document.querySelector(hint);
219
+ if (!el) continue;
220
+ if (el.tagName.toLowerCase() !== refNode.tag) continue;
221
+ return { ok: true as const, selector: cssPath(el) };
222
+ } catch {
223
+ // ignore malformed selector hint
224
+ }
225
+ }
226
+
227
+ // Tier 3: role + name match
228
+ const candidates = Array.from(document.querySelectorAll(refNode.tag));
229
+ const matchTarget = candidates.find((el) => {
230
+ const role = el.getAttribute("role") || "";
231
+ const name = nodeName(el);
232
+ const roleMatch = !refNode.role || role === refNode.role;
233
+ const nameMatch = !!refNode.name && name.toLowerCase() === refNode.name.toLowerCase();
234
+ return roleMatch && nameMatch;
235
+ });
236
+ if (matchTarget) {
237
+ return { ok: true as const, selector: cssPath(matchTarget) };
238
+ }
239
+
240
+ // Tier 4: structural signature + content hash fingerprint matching
241
+ if (refNode.contentHash && refNode.structuralSignature) {
242
+ const fpMatches: Element[] = [];
243
+ for (const candidate of candidates) {
244
+ const tag = candidate.tagName.toLowerCase();
245
+ const role = candidate.getAttribute("role") || "";
246
+ const textContent = (candidate.textContent || "").trim().replace(/\s+/g, " ").slice(0, 200);
247
+ const childTags = Array.from(candidate.children).map((c) => c.tagName.toLowerCase());
248
+ const candidateContentHash = simpleHash(textContent);
249
+ const candidateStructSig = simpleHash(`${tag}|${role}|${childTags.join(",")}`);
250
+ if (candidateContentHash === refNode.contentHash && candidateStructSig === refNode.structuralSignature) {
251
+ fpMatches.push(candidate);
252
+ }
253
+ }
254
+ if (fpMatches.length === 1) {
255
+ return { ok: true as const, selector: cssPath(fpMatches[0]) };
256
+ }
257
+ if (fpMatches.length > 1) {
258
+ return { ok: false as const, reason: "multiple fingerprint matches — ambiguous" };
259
+ }
260
+ }
261
+
262
+ return { ok: false as const, reason: "element not found in current DOM" };
263
+ }, node);
264
+ }
@@ -0,0 +1,197 @@
1
+ /**
2
+ * browser-tools — DOM settle logic
3
+ *
4
+ * Adaptive settling after browser actions. Polls for DOM quiet (mutation
5
+ * counter stable, no pending critical requests, optional focus stability)
6
+ * before returning control.
7
+ */
8
+
9
+ import type { Frame, Page } from "playwright";
10
+ import type { AdaptiveSettleDetails, AdaptiveSettleOptions } from "./state.js";
11
+ import { getPendingCriticalRequests } from "./utils.js";
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // Mutation counter (installed in-page via evaluate)
15
+ // ---------------------------------------------------------------------------
16
+
17
+ export async function ensureMutationCounter(p: Page): Promise<void> {
18
+ await p.evaluate(() => {
19
+ const key = "__piMutationCounter" as const;
20
+ const installedKey = "__piMutationCounterInstalled" as const;
21
+ const w = window as unknown as Record<string, unknown>;
22
+ if (typeof w[key] !== "number") w[key] = 0;
23
+ if (w[installedKey]) return;
24
+ const observer = new MutationObserver(() => {
25
+ const current = typeof w[key] === "number" ? (w[key] as number) : 0;
26
+ w[key] = current + 1;
27
+ });
28
+ observer.observe(document.documentElement || document.body, {
29
+ subtree: true,
30
+ childList: true,
31
+ attributes: true,
32
+ characterData: true,
33
+ });
34
+ w[installedKey] = true;
35
+ });
36
+ }
37
+
38
+ export async function readMutationCounter(p: Page): Promise<number> {
39
+ try {
40
+ return await p.evaluate(() => {
41
+ const w = window as unknown as Record<string, unknown>;
42
+ const value = w.__piMutationCounter;
43
+ return typeof value === "number" ? value : 0;
44
+ });
45
+ } catch {
46
+ return 0;
47
+ }
48
+ }
49
+
50
+ // ---------------------------------------------------------------------------
51
+ // Focus descriptor (for focus-stability checks)
52
+ // ---------------------------------------------------------------------------
53
+
54
+ export async function readFocusedDescriptor(target: Page | Frame): Promise<string> {
55
+ try {
56
+ return await target.evaluate(() => {
57
+ const el = document.activeElement as HTMLElement | null;
58
+ if (!el || el === document.body || el === document.documentElement) return "";
59
+ const id = el.id ? `#${el.id}` : "";
60
+ const role = el.getAttribute("role") || "";
61
+ const name = (el.getAttribute("aria-label") || el.getAttribute("name") || "").trim();
62
+ return `${el.tagName.toLowerCase()}${id}|${role}|${name}`;
63
+ });
64
+ } catch {
65
+ return "";
66
+ }
67
+ }
68
+
69
+ // ---------------------------------------------------------------------------
70
+ // Combined settle-state reader (mutation counter + focus in one evaluate)
71
+ // ---------------------------------------------------------------------------
72
+
73
+ /**
74
+ * Reads the mutation counter and optionally the focused element descriptor
75
+ * in a single `evaluate()` call, saving one round-trip per poll iteration.
76
+ */
77
+ async function readSettleState(
78
+ target: Page | Frame,
79
+ checkFocus: boolean,
80
+ ): Promise<{ mutationCount: number; focusDescriptor: string }> {
81
+ try {
82
+ return await target.evaluate((wantFocus: boolean) => {
83
+ const w = window as unknown as Record<string, unknown>;
84
+ const mutationCount = typeof w.__piMutationCounter === "number" ? (w.__piMutationCounter as number) : 0;
85
+ if (!wantFocus) return { mutationCount, focusDescriptor: "" };
86
+ const el = document.activeElement as HTMLElement | null;
87
+ if (!el || el === document.body || el === document.documentElement) {
88
+ return { mutationCount, focusDescriptor: "" };
89
+ }
90
+ const id = el.id ? `#${el.id}` : "";
91
+ const role = el.getAttribute("role") || "";
92
+ const name = (el.getAttribute("aria-label") || el.getAttribute("name") || "").trim();
93
+ return { mutationCount, focusDescriptor: `${el.tagName.toLowerCase()}${id}|${role}|${name}` };
94
+ }, checkFocus);
95
+ } catch {
96
+ return { mutationCount: 0, focusDescriptor: "" };
97
+ }
98
+ }
99
+
100
+ // ---------------------------------------------------------------------------
101
+ // Adaptive settle
102
+ // ---------------------------------------------------------------------------
103
+
104
+ /** Threshold (ms) after which zero mutations triggers a shortened quiet window. */
105
+ const ZERO_MUTATION_THRESHOLD_MS = 60;
106
+ /** Shortened quiet window when no mutations have been observed. */
107
+ const ZERO_MUTATION_QUIET_MS = 30;
108
+
109
+ export async function settleAfterActionAdaptive(
110
+ p: Page,
111
+ opts: AdaptiveSettleOptions = {},
112
+ ): Promise<AdaptiveSettleDetails> {
113
+ const timeoutMs = Math.max(150, opts.timeoutMs ?? 500);
114
+ const pollMs = Math.min(100, Math.max(20, opts.pollMs ?? 40));
115
+ const baseQuietWindowMs = Math.max(60, opts.quietWindowMs ?? 100);
116
+ const checkFocus = opts.checkFocusStability ?? false;
117
+
118
+ const startedAt = Date.now();
119
+ let polls = 0;
120
+ let sawUrlChange = false;
121
+ let lastActivityAt = startedAt;
122
+ let previousUrl = p.url();
123
+ let totalMutationsSeen = 0;
124
+ let activeQuietWindowMs = baseQuietWindowMs;
125
+
126
+ // Install mutation counter + read initial state in one evaluate sequence.
127
+ // ensureMutationCounter must run first (installs the observer), then we
128
+ // read the baseline via the combined reader.
129
+ await ensureMutationCounter(p).catch(() => {});
130
+ const initial = await readSettleState(p, checkFocus);
131
+ let previousMutationCount = initial.mutationCount;
132
+ let previousFocus = initial.focusDescriptor;
133
+
134
+ while (Date.now() - startedAt < timeoutMs) {
135
+ await new Promise((resolve) => setTimeout(resolve, pollMs));
136
+ polls += 1;
137
+ const now = Date.now();
138
+
139
+ const currentUrl = p.url();
140
+ if (currentUrl !== previousUrl) {
141
+ sawUrlChange = true;
142
+ previousUrl = currentUrl;
143
+ lastActivityAt = now;
144
+ }
145
+
146
+ // Single combined evaluate for mutation count + focus descriptor.
147
+ const state = await readSettleState(p, checkFocus);
148
+
149
+ if (state.mutationCount > previousMutationCount) {
150
+ totalMutationsSeen += state.mutationCount - previousMutationCount;
151
+ previousMutationCount = state.mutationCount;
152
+ lastActivityAt = now;
153
+ }
154
+
155
+ if (checkFocus && state.focusDescriptor !== previousFocus) {
156
+ previousFocus = state.focusDescriptor;
157
+ lastActivityAt = now;
158
+ }
159
+
160
+ const pendingCritical = getPendingCriticalRequests(p);
161
+ if (pendingCritical > 0) {
162
+ lastActivityAt = now;
163
+ continue;
164
+ }
165
+
166
+ // Zero-mutation short-circuit: after ZERO_MUTATION_THRESHOLD_MS with
167
+ // no mutations observed at all, reduce the quiet window to settle faster.
168
+ if (
169
+ totalMutationsSeen === 0 &&
170
+ now - startedAt >= ZERO_MUTATION_THRESHOLD_MS &&
171
+ activeQuietWindowMs !== ZERO_MUTATION_QUIET_MS
172
+ ) {
173
+ activeQuietWindowMs = ZERO_MUTATION_QUIET_MS;
174
+ }
175
+
176
+ if (now - lastActivityAt >= activeQuietWindowMs) {
177
+ const usedShortcut = activeQuietWindowMs === ZERO_MUTATION_QUIET_MS && totalMutationsSeen === 0;
178
+ return {
179
+ settleMode: "adaptive",
180
+ settleMs: now - startedAt,
181
+ settleReason: usedShortcut
182
+ ? "zero_mutation_shortcut"
183
+ : sawUrlChange
184
+ ? "url_changed_then_quiet"
185
+ : "dom_quiet",
186
+ settlePolls: polls,
187
+ };
188
+ }
189
+ }
190
+
191
+ return {
192
+ settleMode: "adaptive",
193
+ settleMs: Date.now() - startedAt,
194
+ settleReason: "timeout_fallback",
195
+ settlePolls: polls,
196
+ };
197
+ }