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,165 @@
1
+ // GSD Provider Fallback Resolver
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ /**
5
+ * FallbackResolver - Cross-provider fallback when rate/quota limits are hit.
6
+ *
7
+ * When a provider's credentials are all exhausted, this resolver finds the next
8
+ * available provider+model from a user-configured fallback chain. It also handles
9
+ * restoration: checking if a higher-priority provider has recovered before each request.
10
+ */
11
+
12
+ import type { Api, Model } from "@gsd/pi-ai";
13
+ import type { AuthStorage, UsageLimitErrorType } from "./auth-storage.js";
14
+ import type { ModelRegistry } from "./model-registry.js";
15
+ import type { FallbackChainEntry, SettingsManager } from "./settings-manager.js";
16
+
17
+ export interface FallbackResult {
18
+ model: Model<Api>;
19
+ chainName: string;
20
+ reason: string;
21
+ }
22
+
23
+ export class FallbackResolver {
24
+ constructor(
25
+ private settingsManager: SettingsManager,
26
+ private authStorage: AuthStorage,
27
+ private modelRegistry: ModelRegistry,
28
+ ) {}
29
+
30
+ /**
31
+ * Find the next available fallback for a model that just failed.
32
+ * Searches all chains for entries matching the current model's provider+id,
33
+ * then returns the next available entry with lower priority (higher number).
34
+ *
35
+ * @returns FallbackResult if a fallback is available, null otherwise
36
+ */
37
+ async findFallback(
38
+ currentModel: Model<Api>,
39
+ errorType: UsageLimitErrorType,
40
+ ): Promise<FallbackResult | null> {
41
+ const { enabled, chains } = this.settingsManager.getFallbackSettings();
42
+ if (!enabled) return null;
43
+
44
+ // Mark the current provider as exhausted at the provider level
45
+ this.authStorage.markProviderExhausted(currentModel.provider, errorType);
46
+
47
+ // Search all chains for one containing the current model
48
+ for (const [chainName, entries] of Object.entries(chains)) {
49
+ const currentIndex = entries.findIndex(
50
+ (e) => e.provider === currentModel.provider && e.model === currentModel.id,
51
+ );
52
+
53
+ if (currentIndex === -1) continue;
54
+
55
+ // Try entries after the current one (already sorted by priority)
56
+ const result = await this._findAvailableInChain(chainName, entries, currentIndex + 1);
57
+ if (result) return result;
58
+
59
+ // Wrap around: try entries before the current one
60
+ const wrapResult = await this._findAvailableInChain(chainName, entries, 0, currentIndex);
61
+ if (wrapResult) return wrapResult;
62
+ }
63
+
64
+ return null;
65
+ }
66
+
67
+ /**
68
+ * Check if a higher-priority provider in the chain has recovered.
69
+ * Called before each LLM request to restore the best available provider.
70
+ *
71
+ * @returns FallbackResult if a better provider is available, null if current is best
72
+ */
73
+ async checkForRestoration(currentModel: Model<Api>): Promise<FallbackResult | null> {
74
+ const { enabled, chains } = this.settingsManager.getFallbackSettings();
75
+ if (!enabled) return null;
76
+
77
+ for (const [chainName, entries] of Object.entries(chains)) {
78
+ const currentIndex = entries.findIndex(
79
+ (e) => e.provider === currentModel.provider && e.model === currentModel.id,
80
+ );
81
+
82
+ if (currentIndex === -1) continue;
83
+
84
+ // Only check entries with higher priority (lower index = higher priority)
85
+ if (currentIndex === 0) continue; // Already at highest priority
86
+
87
+ const result = await this._findAvailableInChain(chainName, entries, 0, currentIndex);
88
+ if (result) {
89
+ return {
90
+ ...result,
91
+ reason: `${result.model.provider}/${result.model.id} recovered, restoring from fallback`,
92
+ };
93
+ }
94
+ }
95
+
96
+ return null;
97
+ }
98
+
99
+ /**
100
+ * Get the best available model from a named chain.
101
+ * Useful for initial model selection.
102
+ */
103
+ async getBestAvailable(chainName: string): Promise<FallbackResult | null> {
104
+ const { enabled, chains } = this.settingsManager.getFallbackSettings();
105
+ if (!enabled) return null;
106
+
107
+ const entries = chains[chainName];
108
+ if (!entries || entries.length === 0) return null;
109
+
110
+ return this._findAvailableInChain(chainName, entries, 0);
111
+ }
112
+
113
+ /**
114
+ * Find the chain(s) a model belongs to.
115
+ */
116
+ findChainsForModel(provider: string, modelId: string): string[] {
117
+ const { chains } = this.settingsManager.getFallbackSettings();
118
+ const result: string[] = [];
119
+
120
+ for (const [chainName, entries] of Object.entries(chains)) {
121
+ if (entries.some((e) => e.provider === provider && e.model === modelId)) {
122
+ result.push(chainName);
123
+ }
124
+ }
125
+
126
+ return result;
127
+ }
128
+
129
+ /**
130
+ * Search a chain for the first available entry starting from startIndex.
131
+ */
132
+ private async _findAvailableInChain(
133
+ chainName: string,
134
+ entries: FallbackChainEntry[],
135
+ startIndex: number,
136
+ endIndex?: number,
137
+ ): Promise<FallbackResult | null> {
138
+ const end = endIndex ?? entries.length;
139
+
140
+ for (let i = startIndex; i < end; i++) {
141
+ const entry = entries[i];
142
+
143
+ // Check provider-level backoff
144
+ if (!this.authStorage.isProviderAvailable(entry.provider)) {
145
+ continue;
146
+ }
147
+
148
+ // Check if model exists in registry
149
+ const model = this.modelRegistry.find(entry.provider, entry.model);
150
+ if (!model) continue;
151
+
152
+ // Check if API key is available
153
+ const hasAuth = this.authStorage.hasAuth(entry.provider);
154
+ if (!hasAuth) continue;
155
+
156
+ return {
157
+ model,
158
+ chainName,
159
+ reason: `falling back to ${entry.provider}/${entry.model}`,
160
+ };
161
+ }
162
+
163
+ return null;
164
+ }
165
+ }
@@ -12,6 +12,7 @@ export {
12
12
  type SessionStats,
13
13
  } from "./agent-session.js";
14
14
  export { type BashExecutorOptions, type BashResult, executeBash, executeBashWithOperations } from "./bash-executor.js";
15
+ export { FallbackResolver, type FallbackResult } from "./fallback-resolver.js";
15
16
  export type { CompactionResult } from "./compaction/index.js";
16
17
  export { createEventBus, type EventBus, type EventBusController } from "./event-bus.js";
17
18
 
@@ -36,6 +36,7 @@ export const defaultModelPerProvider: Record<KnownProvider, string> = {
36
36
  "opencode-go": "kimi-k2.5",
37
37
  "kimi-coding": "kimi-k2-thinking",
38
38
  "alibaba-coding-plan": "qwen3.5-plus",
39
+ "ollama-cloud": "qwen3:32b",
39
40
  };
40
41
 
41
42
  export interface ScopedModel {
@@ -0,0 +1,65 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { mkdtempSync, rmSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+
7
+ import { SessionManager } from "./session-manager.js";
8
+
9
+ function makeAssistantMessage(input: number, output: number, cacheRead = 0, cacheWrite = 0, cost = 0) {
10
+ return {
11
+ role: "assistant",
12
+ content: [{ type: "text", text: "ok" }],
13
+ usage: {
14
+ input,
15
+ output,
16
+ cacheRead,
17
+ cacheWrite,
18
+ total: input + output + cacheRead + cacheWrite,
19
+ cost: { total: cost },
20
+ },
21
+ } as any;
22
+ }
23
+
24
+ describe("SessionManager usage totals", () => {
25
+ it("tracks assistant usage incrementally without rescanning entries", () => {
26
+ const dir = mkdtempSync(join(tmpdir(), "gsd-session-manager-test-"));
27
+ try {
28
+ const manager = SessionManager.create(dir, dir);
29
+
30
+ manager.appendMessage({ role: "user", content: [{ type: "text", text: "hello" }] } as any);
31
+ manager.appendMessage(makeAssistantMessage(10, 5, 3, 2, 0.25));
32
+ manager.appendMessage(makeAssistantMessage(7, 4, 1, 0, 0.1));
33
+
34
+ assert.deepEqual(manager.getUsageTotals(), {
35
+ input: 17,
36
+ output: 9,
37
+ cacheRead: 4,
38
+ cacheWrite: 2,
39
+ cost: 0.35,
40
+ });
41
+ } finally {
42
+ rmSync(dir, { recursive: true, force: true });
43
+ }
44
+ });
45
+
46
+ it("resets totals when starting a new session", () => {
47
+ const dir = mkdtempSync(join(tmpdir(), "gsd-session-manager-test-"));
48
+ try {
49
+ const manager = SessionManager.create(dir, dir);
50
+ manager.appendMessage(makeAssistantMessage(5, 5, 0, 0, 0.05));
51
+ assert.equal(manager.getUsageTotals().input, 5);
52
+
53
+ manager.newSession();
54
+ assert.deepEqual(manager.getUsageTotals(), {
55
+ input: 0,
56
+ output: 0,
57
+ cacheRead: 0,
58
+ cacheWrite: 0,
59
+ cost: 0,
60
+ });
61
+ } finally {
62
+ rmSync(dir, { recursive: true, force: true });
63
+ }
64
+ });
65
+ });
@@ -182,6 +182,14 @@ export interface SessionInfo {
182
182
  allMessagesText: string;
183
183
  }
184
184
 
185
+ export interface SessionUsageTotals {
186
+ input: number;
187
+ output: number;
188
+ cacheRead: number;
189
+ cacheWrite: number;
190
+ cost: number;
191
+ }
192
+
185
193
  export type ReadonlySessionManager = Pick<
186
194
  SessionManager,
187
195
  | "getCwd"
@@ -195,10 +203,21 @@ export type ReadonlySessionManager = Pick<
195
203
  | "getBranch"
196
204
  | "getHeader"
197
205
  | "getEntries"
206
+ | "getUsageTotals"
198
207
  | "getTree"
199
208
  | "getSessionName"
200
209
  >;
201
210
 
211
+ function createEmptyUsageTotals(): SessionUsageTotals {
212
+ return {
213
+ input: 0,
214
+ output: 0,
215
+ cacheRead: 0,
216
+ cacheWrite: 0,
217
+ cost: 0,
218
+ };
219
+ }
220
+
202
221
  /** Generate a unique short ID (8 hex chars, collision-checked) */
203
222
  function generateId(byId: { has(id: string): boolean }): string {
204
223
  for (let i = 0; i < 100; i++) {
@@ -779,10 +798,12 @@ export class SessionManager {
779
798
  private persist: boolean;
780
799
  private flushed: boolean = false;
781
800
  private fileEntries: FileEntry[] = [];
801
+ private sessionEntries: SessionEntry[] = [];
782
802
  private byId: Map<string, SessionEntry> = new Map();
783
803
  private blobStore: BlobStore;
784
804
  private labelsById: Map<string, string> = new Map();
785
805
  private leafId: string | null = null;
806
+ private usageTotals: SessionUsageTotals = createEmptyUsageTotals();
786
807
 
787
808
  private constructor(cwd: string, sessionDir: string, sessionFile: string | undefined, persist: boolean) {
788
809
  this.cwd = cwd;
@@ -846,9 +867,11 @@ export class SessionManager {
846
867
  parentSession: options?.parentSession,
847
868
  };
848
869
  this.fileEntries = [header];
870
+ this.sessionEntries = [];
849
871
  this.byId.clear();
850
872
  this.labelsById.clear();
851
873
  this.leafId = null;
874
+ this.usageTotals = createEmptyUsageTotals();
852
875
  this.flushed = false;
853
876
 
854
877
  if (this.persist) {
@@ -859,13 +882,17 @@ export class SessionManager {
859
882
  }
860
883
 
861
884
  private _buildIndex(): void {
885
+ this.sessionEntries = [];
862
886
  this.byId.clear();
863
887
  this.labelsById.clear();
864
888
  this.leafId = null;
889
+ this.usageTotals = createEmptyUsageTotals();
865
890
  for (const entry of this.fileEntries) {
866
891
  if (entry.type === "session") continue;
892
+ this.sessionEntries.push(entry);
867
893
  this.byId.set(entry.id, entry);
868
894
  this.leafId = entry.id;
895
+ this._accumulateUsage(entry);
869
896
  if (entry.type === "label") {
870
897
  if (entry.label) {
871
898
  this.labelsById.set(entry.targetId, entry.label);
@@ -926,11 +953,30 @@ export class SessionManager {
926
953
 
927
954
  private _appendEntry(entry: SessionEntry): void {
928
955
  this.fileEntries.push(entry);
956
+ this.sessionEntries.push(entry);
929
957
  this.byId.set(entry.id, entry);
930
958
  this.leafId = entry.id;
959
+ this._accumulateUsage(entry);
931
960
  this._persist(entry);
932
961
  }
933
962
 
963
+ private _accumulateUsage(entry: SessionEntry): void {
964
+ if (entry.type !== "message" || entry.message.role !== "assistant") {
965
+ return;
966
+ }
967
+
968
+ const usage = entry.message.usage;
969
+ if (!usage) {
970
+ return;
971
+ }
972
+
973
+ this.usageTotals.input += usage.input;
974
+ this.usageTotals.output += usage.output;
975
+ this.usageTotals.cacheRead += usage.cacheRead;
976
+ this.usageTotals.cacheWrite += usage.cacheWrite;
977
+ this.usageTotals.cost += usage.cost.total;
978
+ }
979
+
934
980
  /** Append a message as child of current leaf, then advance leaf. Returns entry id.
935
981
  * Does not allow writing CompactionSummaryMessage and BranchSummaryMessage directly.
936
982
  * Reason: we want these to be top-level entries in the session, not message session entries,
@@ -1167,7 +1213,11 @@ export class SessionManager {
1167
1213
  * change the leaf pointer. Entries cannot be modified or deleted.
1168
1214
  */
1169
1215
  getEntries(): SessionEntry[] {
1170
- return this.fileEntries.filter((e): e is SessionEntry => e.type !== "session");
1216
+ return [...this.sessionEntries];
1217
+ }
1218
+
1219
+ getUsageTotals(): SessionUsageTotals {
1220
+ return { ...this.usageTotals };
1171
1221
  }
1172
1222
 
1173
1223
  /**
@@ -68,6 +68,17 @@ export interface TaskIsolationSettings {
68
68
  merge?: "patch" | "branch"; // default: "patch"
69
69
  }
70
70
 
71
+ export interface FallbackChainEntry {
72
+ provider: string;
73
+ model: string;
74
+ priority: number;
75
+ }
76
+
77
+ export interface FallbackSettings {
78
+ enabled?: boolean; // default: false
79
+ chains?: Record<string, FallbackChainEntry[]>; // keyed by chain name
80
+ }
81
+
71
82
  export type TransportSetting = Transport;
72
83
 
73
84
  /**
@@ -122,6 +133,7 @@ export interface Settings {
122
133
  async?: AsyncSettings;
123
134
  bashInterceptor?: BashInterceptorSettings;
124
135
  taskIsolation?: TaskIsolationSettings;
136
+ fallback?: FallbackSettings;
125
137
  }
126
138
 
127
139
  /** Deep merge settings: project/overrides take precedence, nested objects merge recursively */
@@ -1010,4 +1022,58 @@ export class SettingsManager {
1010
1022
  getTaskIsolationMerge(): "patch" | "branch" {
1011
1023
  return this.settings.taskIsolation?.merge ?? "patch";
1012
1024
  }
1025
+
1026
+ getFallbackEnabled(): boolean {
1027
+ return this.settings.fallback?.enabled ?? false;
1028
+ }
1029
+
1030
+ setFallbackEnabled(enabled: boolean): void {
1031
+ if (!this.globalSettings.fallback) {
1032
+ this.globalSettings.fallback = {};
1033
+ }
1034
+ this.globalSettings.fallback.enabled = enabled;
1035
+ this.markModified("fallback", "enabled");
1036
+ this.save();
1037
+ }
1038
+
1039
+ getFallbackChains(): Record<string, FallbackChainEntry[]> {
1040
+ return this.settings.fallback?.chains ?? {};
1041
+ }
1042
+
1043
+ getFallbackChain(name: string): FallbackChainEntry[] | undefined {
1044
+ return this.settings.fallback?.chains?.[name];
1045
+ }
1046
+
1047
+ setFallbackChain(name: string, entries: FallbackChainEntry[]): void {
1048
+ if (!this.globalSettings.fallback) {
1049
+ this.globalSettings.fallback = {};
1050
+ }
1051
+ if (!this.globalSettings.fallback.chains) {
1052
+ this.globalSettings.fallback.chains = {};
1053
+ }
1054
+ // Sort by priority
1055
+ this.globalSettings.fallback.chains[name] = [...entries].sort((a, b) => a.priority - b.priority);
1056
+ this.markModified("fallback");
1057
+ this.save();
1058
+ }
1059
+
1060
+ removeFallbackChain(name: string): boolean {
1061
+ if (!this.globalSettings.fallback?.chains?.[name]) {
1062
+ return false;
1063
+ }
1064
+ delete this.globalSettings.fallback.chains[name];
1065
+ if (Object.keys(this.globalSettings.fallback.chains).length === 0) {
1066
+ delete this.globalSettings.fallback.chains;
1067
+ }
1068
+ this.markModified("fallback");
1069
+ this.save();
1070
+ return true;
1071
+ }
1072
+
1073
+ getFallbackSettings(): { enabled: boolean; chains: Record<string, FallbackChainEntry[]> } {
1074
+ return {
1075
+ enabled: this.getFallbackEnabled(),
1076
+ chains: this.getFallbackChains(),
1077
+ };
1078
+ }
1013
1079
  }
@@ -140,6 +140,7 @@ export function createFindTool(cwd: string, options?: FindToolOptions): AgentToo
140
140
  path: searchPath,
141
141
  hidden: true,
142
142
  gitignore: true,
143
+ cache: true,
143
144
  maxResults: effectiveLimit,
144
145
  });
145
146
 
@@ -61,22 +61,12 @@ export class FooterComponent implements Component {
61
61
  render(width: number): string[] {
62
62
  const state = this.session.state;
63
63
 
64
- // Calculate cumulative usage from ALL session entries (not just post-compaction messages)
65
- let totalInput = 0;
66
- let totalOutput = 0;
67
- let totalCacheRead = 0;
68
- let totalCacheWrite = 0;
69
- let totalCost = 0;
70
-
71
- for (const entry of this.session.sessionManager.getEntries()) {
72
- if (entry.type === "message" && entry.message.role === "assistant") {
73
- totalInput += entry.message.usage.input;
74
- totalOutput += entry.message.usage.output;
75
- totalCacheRead += entry.message.usage.cacheRead;
76
- totalCacheWrite += entry.message.usage.cacheWrite;
77
- totalCost += entry.message.usage.cost.total;
78
- }
79
- }
64
+ const usageTotals = this.session.sessionManager.getUsageTotals();
65
+ const totalInput = usageTotals.input;
66
+ const totalOutput = usageTotals.output;
67
+ const totalCacheRead = usageTotals.cacheRead;
68
+ const totalCacheWrite = usageTotals.cacheWrite;
69
+ const totalCost = usageTotals.cost;
80
70
 
81
71
  // Calculate context usage from session (handles compaction correctly).
82
72
  // After compaction, tokens are unknown until the next LLM response.
@@ -1,3 +1,5 @@
1
+ // GSD Login Dialog Component — OAuth login flow UI
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
1
3
  import { getOAuthProviders } from "@gsd/pi-ai/oauth";
2
4
  import { Container, type Focusable, getEditorKeybindings, Input, Spacer, Text, type TUI } from "@gsd/pi-tui";
3
5
  import { exec } from "child_process";
@@ -6,7 +8,12 @@ import { DynamicBorder } from "./dynamic-border.js";
6
8
  import { keyHint } from "./keybinding-hints.js";
7
9
 
8
10
  /**
9
- * Login dialog component - replaces editor during OAuth login flow
11
+ * Login dialog component - replaces editor during OAuth login flow.
12
+ *
13
+ * Guards against stuck UI by:
14
+ * - Rejecting any outstanding promise before creating a new one
15
+ * - Listening on the internal AbortSignal so external cancellation cleans up
16
+ * - Exposing a public dispose() method so the caller can force-cleanup
10
17
  */
11
18
  export class LoginDialogComponent extends Container implements Focusable {
12
19
  private contentContainer: Container;
@@ -15,6 +22,7 @@ export class LoginDialogComponent extends Container implements Focusable {
15
22
  private abortController = new AbortController();
16
23
  private inputResolver?: (value: string) => void;
17
24
  private inputRejecter?: (error: Error) => void;
25
+ private disposed = false;
18
26
 
19
27
  // Focusable implementation - propagate to input for IME cursor positioning
20
28
  private _focused = false;
@@ -62,22 +70,51 @@ export class LoginDialogComponent extends Container implements Focusable {
62
70
 
63
71
  // Bottom border
64
72
  this.addChild(new DynamicBorder());
73
+
74
+ // Wire abort signal so external cancellation rejects pending promises
75
+ this.abortController.signal.addEventListener("abort", () => {
76
+ this.rejectPending("Login cancelled");
77
+ });
65
78
  }
66
79
 
67
80
  get signal(): AbortSignal {
68
81
  return this.abortController.signal;
69
82
  }
70
83
 
71
- private cancel(): void {
72
- this.abortController.abort();
84
+ /**
85
+ * Reject any outstanding input promise without triggering a full cancel.
86
+ * Safe to call multiple times.
87
+ */
88
+ private rejectPending(reason: string): void {
73
89
  if (this.inputRejecter) {
74
- this.inputRejecter(new Error("Login cancelled"));
90
+ const rejecter = this.inputRejecter;
75
91
  this.inputResolver = undefined;
76
92
  this.inputRejecter = undefined;
93
+ rejecter(new Error(reason));
77
94
  }
95
+ }
96
+
97
+ private cancel(): void {
98
+ if (this.disposed) return;
99
+ this.abortController.abort();
100
+ // rejectPending is also called by the abort listener, but guard with
101
+ // disposed flag and nulling to avoid double-reject
102
+ this.rejectPending("Login cancelled");
78
103
  this.onComplete(false, "Login cancelled");
79
104
  }
80
105
 
106
+ /**
107
+ * Force-dispose the dialog, rejecting any pending promises.
108
+ * Called by the parent when restoring the editor, as a safety net
109
+ * to ensure no promises are left dangling.
110
+ */
111
+ dispose(): void {
112
+ if (this.disposed) return;
113
+ this.disposed = true;
114
+ this.abortController.abort();
115
+ this.rejectPending("Login dialog disposed");
116
+ }
117
+
81
118
  /**
82
119
  * Called by onAuth callback - show URL and optional instructions
83
120
  */
@@ -106,6 +143,9 @@ export class LoginDialogComponent extends Container implements Focusable {
106
143
  * Show input for manual code/URL entry (for callback server providers)
107
144
  */
108
145
  showManualInput(prompt: string): Promise<string> {
146
+ // Reject any previous pending promise before creating a new one
147
+ this.rejectPending("Superseded by new input prompt");
148
+
109
149
  this.contentContainer.addChild(new Spacer(1));
110
150
  this.contentContainer.addChild(new Text(theme.fg("dim", prompt), 1, 0));
111
151
  this.contentContainer.addChild(this.input);
@@ -123,6 +163,9 @@ export class LoginDialogComponent extends Container implements Focusable {
123
163
  * Note: Does NOT clear content, appends to existing (preserves URL from showAuth)
124
164
  */
125
165
  showPrompt(message: string, placeholder?: string): Promise<string> {
166
+ // Reject any previous pending promise before creating a new one
167
+ this.rejectPending("Superseded by new input prompt");
168
+
126
169
  this.contentContainer.addChild(new Spacer(1));
127
170
  this.contentContainer.addChild(new Text(theme.fg("text", message), 1, 0));
128
171
  if (placeholder) {
@@ -161,6 +204,8 @@ export class LoginDialogComponent extends Container implements Focusable {
161
204
  }
162
205
 
163
206
  handleInput(data: string): void {
207
+ if (this.disposed) return;
208
+
164
209
  const kb = getEditorKeybindings();
165
210
 
166
211
  if (kb.matches(data, "selectCancel")) {
@@ -2382,6 +2382,24 @@ export class InteractiveMode {
2382
2382
  this.ui.requestRender();
2383
2383
  break;
2384
2384
  }
2385
+
2386
+ case "fallback_provider_switch": {
2387
+ this.showStatus(`Switched from ${event.from} → ${event.to} (${event.reason})`);
2388
+ this.ui.requestRender();
2389
+ break;
2390
+ }
2391
+
2392
+ case "fallback_provider_restored": {
2393
+ this.showStatus(`Restored to ${event.provider}`);
2394
+ this.ui.requestRender();
2395
+ break;
2396
+ }
2397
+
2398
+ case "fallback_chain_exhausted": {
2399
+ this.showError(event.reason);
2400
+ this.ui.requestRender();
2401
+ break;
2402
+ }
2385
2403
  }
2386
2404
  }
2387
2405
 
@@ -3805,8 +3823,10 @@ export class InteractiveMode {
3805
3823
  manualCodeReject = reject;
3806
3824
  });
3807
3825
 
3808
- // Restore editor helper
3826
+ // Restore editor helper — also disposes the dialog to reject any
3827
+ // dangling promises and prevent the UI from getting stuck.
3809
3828
  const restoreEditor = () => {
3829
+ dialog.dispose();
3810
3830
  this.editorContainer.clear();
3811
3831
  this.editorContainer.addChild(this.editor);
3812
3832
  this.ui.setFocus(this.editor);
@@ -3881,8 +3901,14 @@ export class InteractiveMode {
3881
3901
  this.showStatus(`Logged in to ${providerName}. Credentials saved to ${getAuthPath()}`);
3882
3902
  } catch (error: unknown) {
3883
3903
  restoreEditor();
3904
+ // Also reject the manual code promise if it's still pending
3905
+ if (manualCodeReject) {
3906
+ manualCodeReject(new Error("Login cancelled"));
3907
+ manualCodeReject = undefined;
3908
+ manualCodeResolve = undefined;
3909
+ }
3884
3910
  const errorMsg = error instanceof Error ? error.message : String(error);
3885
- if (errorMsg !== "Login cancelled") {
3911
+ if (errorMsg !== "Login cancelled" && !errorMsg.includes("Superseded") && !errorMsg.includes("disposed")) {
3886
3912
  this.showError(`Failed to login to ${providerName}: ${errorMsg}`);
3887
3913
  }
3888
3914
  }
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"AAsFA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IAGpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QACF,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC;IAIT,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QACF,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;CACF;AAGD,qBAAa,4BAA6B,YAAW,oBAAoB;IACxE,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAS;gBAGxB,QAAQ,GAAE,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAAO,EAClD,QAAQ,GAAE,MAAsB;IAMjC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA+FvD,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAkF7D,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,uBAAuB;IA6B/B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,kBAAkB;IAmI1B,OAAO,CAAC,uBAAuB;IA+C/B,uBAAuB,CACtB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAyBvD,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;CAW5F"}
1
+ {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"AAuFA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IAGpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QACF,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC;IAIT,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QACF,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;CACF;AAGD,qBAAa,4BAA6B,YAAW,oBAAoB;IACxE,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAS;gBAGxB,QAAQ,GAAE,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAAO,EAClD,QAAQ,GAAE,MAAsB;IAMjC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA+FvD,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAkF7D,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,uBAAuB;IA6B/B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,kBAAkB;IAmI1B,OAAO,CAAC,uBAAuB;IA4C/B,uBAAuB,CACtB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAyBvD,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;CAW5F"}