@gajae-code/coding-agent 0.17.1 → 0.17.4

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 (375) hide show
  1. package/CHANGELOG.md +266 -0
  2. package/dist/types/async/job-manager.d.ts +7 -6
  3. package/dist/types/cli/daemon-cli.d.ts +3 -1
  4. package/dist/types/cli/github-release.d.ts +17 -0
  5. package/dist/types/cli/public-command-entry.d.ts +56 -0
  6. package/dist/types/cli/public-command-errors.d.ts +126 -0
  7. package/dist/types/cli/public-command-evidence.d.ts +99 -0
  8. package/dist/types/cli/public-command-help.d.ts +65 -0
  9. package/dist/types/cli/public-command-registry.d.ts +69 -0
  10. package/dist/types/cli/session-picker.d.ts +1 -1
  11. package/dist/types/cli/setup-cli.d.ts +1 -0
  12. package/dist/types/cli/skills-cli.d.ts +5 -0
  13. package/dist/types/cli.d.ts +3 -0
  14. package/dist/types/commands/daemon.d.ts +4 -50
  15. package/dist/types/commands/sdk.d.ts +20 -37
  16. package/dist/types/commands/setup.d.ts +3 -0
  17. package/dist/types/commands/skills.d.ts +9 -0
  18. package/dist/types/config/autorouting-tier-map.d.ts +24 -0
  19. package/dist/types/config/file-lock.d.ts +10 -1
  20. package/dist/types/config/model-profile-activation.d.ts +63 -4
  21. package/dist/types/config/model-registry.d.ts +20 -2
  22. package/dist/types/config/settings-schema.d.ts +11 -0
  23. package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
  24. package/dist/types/coordinator-mcp/server.d.ts +3 -0
  25. package/dist/types/daemon/operator-contract.d.ts +5 -1
  26. package/dist/types/eval/js/worker-protocol.d.ts +2 -0
  27. package/dist/types/extensibility/extensions/types.d.ts +12 -0
  28. package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
  29. package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
  30. package/dist/types/extensibility/shared-events.d.ts +3 -1
  31. package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
  32. package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
  33. package/dist/types/internal-urls/index.d.ts +1 -0
  34. package/dist/types/internal-urls/parse.d.ts +9 -1
  35. package/dist/types/main.d.ts +22 -0
  36. package/dist/types/modes/acp/acp-agent.d.ts +94 -1
  37. package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
  38. package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
  39. package/dist/types/modes/components/session-selector.d.ts +5 -2
  40. package/dist/types/modes/components/thinking-selector.d.ts +2 -1
  41. package/dist/types/modes/components/user-message-selector.d.ts +5 -2
  42. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  43. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  44. package/dist/types/modes/interactive-mode.d.ts +1 -1
  45. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
  46. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
  47. package/dist/types/modes/types.d.ts +2 -2
  48. package/dist/types/runtime/process-lifecycle.d.ts +2 -0
  49. package/dist/types/runtime-mcp/manager.d.ts +56 -0
  50. package/dist/types/runtime-mcp/pool.d.ts +17 -0
  51. package/dist/types/runtime-mcp/redaction.d.ts +20 -0
  52. package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
  53. package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
  54. package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
  55. package/dist/types/sdk/acp/adapter.d.ts +27 -0
  56. package/dist/types/sdk/acp/final-text.d.ts +8 -0
  57. package/dist/types/sdk/broker/broker.d.ts +13 -2
  58. package/dist/types/sdk/broker/ensure.d.ts +46 -1
  59. package/dist/types/sdk/broker/identity.d.ts +3 -1
  60. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
  61. package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
  62. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  63. package/dist/types/sdk/broker/session-index.d.ts +22 -3
  64. package/dist/types/sdk/broker/spawn-authority.d.ts +4 -0
  65. package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
  66. package/dist/types/sdk/bus/index.d.ts +19 -0
  67. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
  68. package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
  69. package/dist/types/sdk/cli/master-cli.d.ts +6 -10
  70. package/dist/types/sdk/cli/rows.d.ts +19 -1
  71. package/dist/types/sdk/cli/session-cli.d.ts +22 -5
  72. package/dist/types/sdk/client/client.d.ts +2 -0
  73. package/dist/types/sdk/guides/cli.d.ts +3 -4
  74. package/dist/types/sdk/guides/verify.d.ts +2 -0
  75. package/dist/types/sdk/host/host.d.ts +9 -0
  76. package/dist/types/sdk/host/session-runtime.d.ts +31 -0
  77. package/dist/types/sdk/host/types.d.ts +10 -0
  78. package/dist/types/sdk/index.d.ts +1 -0
  79. package/dist/types/sdk/prompt-deadline-flush.d.ts +83 -0
  80. package/dist/types/sdk/prompt-deadline-manager.d.ts +38 -1
  81. package/dist/types/sdk/prompt-failure.d.ts +30 -1
  82. package/dist/types/sdk/prompt-status.d.ts +8 -0
  83. package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
  84. package/dist/types/sdk/router/replay-retention-gap-cache.d.ts +13 -0
  85. package/dist/types/sdk/router/session-router.d.ts +2 -0
  86. package/dist/types/sdk/startup-capability.d.ts +2 -0
  87. package/dist/types/sdk/transport/relay.d.ts +1 -0
  88. package/dist/types/sdk/transport/serve-cli.d.ts +73 -2
  89. package/dist/types/sdk/transport/stdio.d.ts +5 -1
  90. package/dist/types/session/agent-session.d.ts +168 -21
  91. package/dist/types/session/fallback-chain-controller.d.ts +6 -6
  92. package/dist/types/session/fold-coordinator.d.ts +17 -3
  93. package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
  94. package/dist/types/session/session-manager.d.ts +64 -1
  95. package/dist/types/session/session-work-lease.d.ts +14 -0
  96. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
  97. package/dist/types/setup/provider-onboarding.d.ts +81 -1
  98. package/dist/types/thinking.d.ts +3 -1
  99. package/dist/types/tools/bash.d.ts +37 -11
  100. package/dist/types/tools/job.d.ts +1 -1
  101. package/dist/types/tools/steer-fold.d.ts +31 -0
  102. package/dist/types/utils/git.d.ts +28 -2
  103. package/dist/types/utils/mupdf-embedded.d.ts +2 -0
  104. package/dist/types/utils/mupdf-wasm-embedded.d.ts +2 -0
  105. package/dist/types/utils/mupdf.d.ts +4 -0
  106. package/dist/types/utils/session-title-generation.d.ts +6 -0
  107. package/dist/types/utils/title-generator.d.ts +11 -2
  108. package/dist/types/web/scrapers/types.d.ts +3 -0
  109. package/package.json +18 -10
  110. package/scripts/build-binary.ts +9 -3
  111. package/scripts/compile-args.ts +0 -9
  112. package/scripts/embed-mupdf.ts +52 -0
  113. package/scripts/generate-sdk-operation-inventory.ts +31 -1
  114. package/scripts/vendor-markit.ts +196 -0
  115. package/src/async/job-manager.ts +60 -9
  116. package/src/cli/daemon-cli.ts +53 -18
  117. package/src/cli/github-release.ts +87 -5
  118. package/src/cli/mcp-cli.ts +38 -4
  119. package/src/cli/public-command-entry.ts +450 -0
  120. package/src/cli/public-command-errors.ts +581 -0
  121. package/src/cli/public-command-evidence.ts +717 -0
  122. package/src/cli/public-command-help.ts +360 -0
  123. package/src/cli/public-command-registry.ts +535 -0
  124. package/src/cli/session-picker.ts +2 -1
  125. package/src/cli/setup-cli.ts +9 -1
  126. package/src/cli/skills-cli.ts +46 -2
  127. package/src/cli.ts +61 -1
  128. package/src/commands/daemon.ts +65 -69
  129. package/src/commands/sdk.ts +232 -100
  130. package/src/commands/setup.ts +2 -0
  131. package/src/commands/skills.ts +11 -0
  132. package/src/config/autorouting-tier-map.ts +16 -0
  133. package/src/config/file-lock.ts +199 -68
  134. package/src/config/model-profile-activation.ts +406 -53
  135. package/src/config/model-registry.ts +204 -25
  136. package/src/config/settings-schema.ts +26 -2
  137. package/src/coordinator-mcp/policy.ts +10 -5
  138. package/src/coordinator-mcp/question-gate-codec.ts +17 -0
  139. package/src/coordinator-mcp/question-state.ts +175 -8
  140. package/src/coordinator-mcp/server.ts +528 -87
  141. package/src/coordinator-mcp/session-reaper.ts +6 -4
  142. package/src/crash/record-loader.ts +6 -2
  143. package/src/daemon/operator-contract.ts +26 -12
  144. package/src/debug/report-bundle.ts +114 -24
  145. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  146. package/src/eval/js/context-manager.ts +8 -8
  147. package/src/eval/js/worker-core.ts +9 -4
  148. package/src/eval/js/worker-protocol.ts +2 -0
  149. package/src/extensibility/extensions/runner.ts +52 -4
  150. package/src/extensibility/extensions/types.ts +10 -0
  151. package/src/extensibility/gjc-plugins/registry.ts +196 -37
  152. package/src/extensibility/runtime-skill-discovery.ts +61 -3
  153. package/src/extensibility/shared-events.ts +3 -1
  154. package/src/gjc-runtime/managed-owner-admission.ts +67 -50
  155. package/src/gjc-runtime/session-state-lock.ts +165 -24
  156. package/src/gjc-runtime/ultragoal-succession.ts +31 -3
  157. package/src/internal-urls/docs-index.generated.ts +21 -19
  158. package/src/internal-urls/embedded-protocol.ts +83 -0
  159. package/src/internal-urls/index.ts +1 -0
  160. package/src/internal-urls/parse.ts +21 -1
  161. package/src/internal-urls/router.ts +4 -2
  162. package/src/main.ts +123 -55
  163. package/src/modes/acp/acp-agent.ts +593 -47
  164. package/src/modes/acp/acp-event-mapper.ts +9 -0
  165. package/src/modes/acp/startup-provenance.ts +59 -0
  166. package/src/modes/components/custom-provider-wizard.ts +308 -7
  167. package/src/modes/components/model-selector.ts +31 -15
  168. package/src/modes/components/oauth-selector.ts +9 -0
  169. package/src/modes/components/session-selector.ts +47 -4
  170. package/src/modes/components/status-line/segments.ts +6 -1
  171. package/src/modes/components/thinking-selector.ts +7 -3
  172. package/src/modes/components/user-message-selector.ts +57 -15
  173. package/src/modes/controllers/command-controller.ts +58 -32
  174. package/src/modes/controllers/extension-ui-controller.ts +33 -7
  175. package/src/modes/controllers/input-controller.ts +4 -0
  176. package/src/modes/controllers/selector-controller.ts +177 -18
  177. package/src/modes/interactive-mode.ts +21 -7
  178. package/src/modes/runtime-init.ts +1 -0
  179. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
  180. package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
  181. package/src/modes/types.ts +2 -2
  182. package/src/prompts/agent-fragments/browser-aside.md +1 -0
  183. package/src/prompts/system/title-system.md +1 -1
  184. package/src/prompts/tools/bash.md +1 -1
  185. package/src/prompts/tools/job.md +1 -1
  186. package/src/prompts/tools/read.md +2 -0
  187. package/src/runtime/network-prewarm-service.test.ts +36 -1
  188. package/src/runtime/network-prewarm-service.ts +28 -3
  189. package/src/runtime/process-lifecycle.ts +22 -11
  190. package/src/runtime-mcp/config.ts +16 -1
  191. package/src/runtime-mcp/manager.ts +689 -55
  192. package/src/runtime-mcp/pool.test.ts +31 -0
  193. package/src/runtime-mcp/pool.ts +304 -28
  194. package/src/runtime-mcp/redaction.ts +42 -0
  195. package/src/runtime-mcp/startup-policy.ts +7 -0
  196. package/src/runtime-mcp/tool-bridge.ts +71 -0
  197. package/src/runtime-mcp/transports/http.ts +108 -25
  198. package/src/sdk/acp/adapter.ts +90 -9
  199. package/src/sdk/acp/final-text.ts +19 -2
  200. package/src/sdk/broker/broker.ts +378 -52
  201. package/src/sdk/broker/ensure.ts +97 -19
  202. package/src/sdk/broker/identity.ts +9 -1
  203. package/src/sdk/broker/lifecycle-ledger.ts +95 -31
  204. package/src/sdk/broker/lifecycle.ts +690 -141
  205. package/src/sdk/broker/runtime.ts +1 -1
  206. package/src/sdk/broker/session-index.ts +97 -4
  207. package/src/sdk/broker/spawn-authority.ts +35 -7
  208. package/src/sdk/broker/stderr-drainer.ts +59 -0
  209. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  210. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  211. package/src/sdk/bus/index.ts +721 -84
  212. package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
  213. package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
  214. package/src/sdk/bus/telegram-daemon.ts +10 -3
  215. package/src/sdk/cli/master-cli.ts +47 -36
  216. package/src/sdk/cli/rows.ts +30 -7
  217. package/src/sdk/cli/session-cli.ts +687 -184
  218. package/src/sdk/client/client.ts +18 -0
  219. package/src/sdk/guides/catalog.ts +2 -2
  220. package/src/sdk/guides/cli.ts +20 -62
  221. package/src/sdk/guides/verify.ts +14 -0
  222. package/src/sdk/host/host.ts +49 -5
  223. package/src/sdk/host/session-runtime.test.ts +636 -9
  224. package/src/sdk/host/session-runtime.ts +499 -118
  225. package/src/sdk/host/types.ts +12 -1
  226. package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
  227. package/src/sdk/host/websocket-transport.ts +40 -6
  228. package/src/sdk/index.ts +11 -0
  229. package/src/sdk/prompt-deadline-flush.ts +334 -0
  230. package/src/sdk/prompt-deadline-manager.ts +136 -4
  231. package/src/sdk/prompt-failure.ts +43 -1
  232. package/src/sdk/prompt-status.ts +8 -0
  233. package/src/sdk/prompt-tool-boundary.ts +121 -0
  234. package/src/sdk/protocol/operation-inventory.generated.json +106 -0
  235. package/src/sdk/router/replay-retention-gap-cache.ts +27 -0
  236. package/src/sdk/router/session-router.ts +31 -4
  237. package/src/sdk/session.ts +194 -16
  238. package/src/sdk/startup-capability.ts +1 -1
  239. package/src/sdk/transport/relay.ts +71 -6
  240. package/src/sdk/transport/serve-cli.ts +494 -49
  241. package/src/sdk/transport/socket.ts +12 -11
  242. package/src/sdk/transport/stdio.ts +7 -3
  243. package/src/session/agent-session.ts +2437 -400
  244. package/src/session/fallback-chain-controller.ts +6 -7
  245. package/src/session/fold-coordinator.ts +24 -5
  246. package/src/session/internal/managed-session-scope.ts +58 -18
  247. package/src/session/internal/managed-session-storage.ts +304 -11
  248. package/src/session/session-manager.ts +382 -44
  249. package/src/session/session-work-lease.ts +34 -0
  250. package/src/session-import/codex.ts +12 -3
  251. package/src/setup/model-onboarding-guidance.ts +1 -1
  252. package/src/setup/provider-onboarding.ts +397 -24
  253. package/src/slash-commands/builtin-registry.ts +258 -14
  254. package/src/task/index.ts +14 -2
  255. package/src/thinking.ts +21 -2
  256. package/src/tools/bash.ts +98 -78
  257. package/src/tools/fetch.ts +119 -20
  258. package/src/tools/job.ts +151 -25
  259. package/src/tools/output-meta.ts +15 -2
  260. package/src/tools/path-utils.ts +27 -3
  261. package/src/tools/read.ts +3 -3
  262. package/src/tools/steer-fold.ts +107 -0
  263. package/src/tools/tool-catalog.generated.ts +29 -2
  264. package/src/tools/tool-errors.ts +4 -0
  265. package/src/utils/git.ts +53 -3
  266. package/src/utils/markit.ts +55 -41
  267. package/src/utils/mupdf-assets.d.ts +4 -0
  268. package/src/utils/mupdf-embedded.ts +4 -0
  269. package/src/utils/mupdf-wasm-embedded.ts +3 -0
  270. package/src/utils/mupdf-wasm.ts +24 -2
  271. package/src/utils/mupdf.ts +129 -0
  272. package/src/utils/session-title-generation.ts +29 -0
  273. package/src/utils/title-generator.ts +46 -2
  274. package/src/web/scrapers/types.ts +24 -3
  275. package/vendor/markit-ai/LICENSE +21 -0
  276. package/vendor/markit-ai/MANIFEST.json +412 -0
  277. package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
  278. package/vendor/markit-ai/dist/commands/config.js +139 -0
  279. package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
  280. package/vendor/markit-ai/dist/commands/convert.js +113 -0
  281. package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
  282. package/vendor/markit-ai/dist/commands/formats.js +92 -0
  283. package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
  284. package/vendor/markit-ai/dist/commands/init.js +29 -0
  285. package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
  286. package/vendor/markit-ai/dist/commands/onboard.js +61 -0
  287. package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
  288. package/vendor/markit-ai/dist/commands/plugin.js +58 -0
  289. package/vendor/markit-ai/dist/config.d.ts +26 -0
  290. package/vendor/markit-ai/dist/config.js +42 -0
  291. package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
  292. package/vendor/markit-ai/dist/converters/audio.js +104 -0
  293. package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
  294. package/vendor/markit-ai/dist/converters/csv.js +83 -0
  295. package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
  296. package/vendor/markit-ai/dist/converters/docx.js +57 -0
  297. package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
  298. package/vendor/markit-ai/dist/converters/epub.js +128 -0
  299. package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
  300. package/vendor/markit-ai/dist/converters/github.js +148 -0
  301. package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
  302. package/vendor/markit-ai/dist/converters/html.js +30 -0
  303. package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
  304. package/vendor/markit-ai/dist/converters/image.js +124 -0
  305. package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
  306. package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
  307. package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
  308. package/vendor/markit-ai/dist/converters/iwork.js +391 -0
  309. package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
  310. package/vendor/markit-ai/dist/converters/json.js +21 -0
  311. package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
  312. package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
  313. package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
  314. package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
  315. package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
  316. package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
  317. package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
  318. package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
  319. package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
  320. package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
  321. package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
  322. package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
  323. package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
  324. package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
  325. package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
  326. package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
  327. package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
  328. package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
  329. package/vendor/markit-ai/dist/converters/pptx.js +289 -0
  330. package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
  331. package/vendor/markit-ai/dist/converters/rss.js +138 -0
  332. package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
  333. package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
  334. package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
  335. package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
  336. package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
  337. package/vendor/markit-ai/dist/converters/xml.js +18 -0
  338. package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
  339. package/vendor/markit-ai/dist/converters/yaml.js +17 -0
  340. package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
  341. package/vendor/markit-ai/dist/converters/zip.js +57 -0
  342. package/vendor/markit-ai/dist/index.d.ts +30 -0
  343. package/vendor/markit-ai/dist/index.js +26 -0
  344. package/vendor/markit-ai/dist/main.d.ts +2 -0
  345. package/vendor/markit-ai/dist/main.js +191 -0
  346. package/vendor/markit-ai/dist/markit.d.ts +45 -0
  347. package/vendor/markit-ai/dist/markit.js +267 -0
  348. package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
  349. package/vendor/markit-ai/dist/plugins/api.js +42 -0
  350. package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
  351. package/vendor/markit-ai/dist/plugins/index.js +3 -0
  352. package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
  353. package/vendor/markit-ai/dist/plugins/installer.js +176 -0
  354. package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
  355. package/vendor/markit-ai/dist/plugins/loader.js +61 -0
  356. package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
  357. package/vendor/markit-ai/dist/plugins/types.js +1 -0
  358. package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
  359. package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
  360. package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
  361. package/vendor/markit-ai/dist/providers/index.js +56 -0
  362. package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
  363. package/vendor/markit-ai/dist/providers/openai.js +76 -0
  364. package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
  365. package/vendor/markit-ai/dist/providers/types.js +1 -0
  366. package/vendor/markit-ai/dist/types.d.ts +36 -0
  367. package/vendor/markit-ai/dist/types.js +1 -0
  368. package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
  369. package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
  370. package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
  371. package/vendor/markit-ai/dist/utils/output.js +31 -0
  372. package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
  373. package/vendor/markit-ai/dist/utils/turndown.js +70 -0
  374. package/vendor/markit-ai/package.json +74 -0
  375. package/vendor/markit-ai.patch +49 -0
@@ -239,6 +239,7 @@ export function mapAgentSessionEventToAcpSessionUpdates(
239
239
  content: todo.content,
240
240
  priority: "medium" as const,
241
241
  status: mapTodoStatus(todo.status),
242
+ _meta: { gjcTodoStatus: todo.status },
242
243
  }));
243
244
  return [toSessionNotification(sessionId, { sessionUpdate: "plan", entries })];
244
245
  }
@@ -502,6 +503,13 @@ function toSessionNotification(sessionId: string, update: SessionUpdate): Sessio
502
503
  return { sessionId, update };
503
504
  }
504
505
 
506
+ /**
507
+ * ACP's `PlanEntryStatus` has only three members, so an `abandoned` todo has to be projected as
508
+ * one of them and `completed` is the one that stops a client's plan UI from showing a dropped task
509
+ * as outstanding work. That projection is lossy, so every plan entry also carries the internal
510
+ * status as `_meta.gjcTodoStatus` for readers that need the truth rather than the rendering
511
+ * (issue #5669).
512
+ */
505
513
  const todoStatusMap: Record<TodoStatus, "pending" | "in_progress" | "completed"> = {
506
514
  pending: "pending",
507
515
  in_progress: "in_progress",
@@ -529,6 +537,7 @@ function mapTodoWriteResultToPlanUpdate(
529
537
  content: todo.content,
530
538
  priority: "medium" as const,
531
539
  status: mapTodoStatus(todo.status),
540
+ _meta: { gjcTodoStatus: todo.status },
532
541
  })),
533
542
  };
534
543
  }
@@ -0,0 +1,59 @@
1
+ import { AcpSdkAdapterError } from "../../sdk/acp";
2
+
3
+ type JsonObject = Record<string, unknown>;
4
+
5
+ export type PrimaryControlSurface = "cli" | "sdk";
6
+
7
+ /**
8
+ * Startup-control provenance is the authority record ACP needs before it may take
9
+ * permission, provider, and lifecycle ownership of a session. Hosts serving that
10
+ * record report capabilities carrying `promptTerminalOutcomeVersion`
11
+ * and `primaryControlSurface`; a host that predates the record reports neither, and a
12
+ * host that cannot answer at all reports nothing. Those are three different operator
13
+ * problems, so they get three different messages instead of one "restart the session".
14
+ */
15
+ export function resolveStartupProvenance(input: {
16
+ sessionId: string;
17
+ capabilities: JsonObject | undefined;
18
+ queryFailure: unknown;
19
+ }): PrimaryControlSurface {
20
+ const { sessionId, capabilities, queryFailure } = input;
21
+ if (!capabilities)
22
+ throw new AcpSdkAdapterError(
23
+ "unavailable",
24
+ `ACP session ${sessionId} did not answer runtime.capabilities, so its startup control provenance is unknown${describeFailure(queryFailure)}.`,
25
+ );
26
+ const surface =
27
+ capabilities.primaryControlSurface === "sdk"
28
+ ? "sdk"
29
+ : capabilities.primaryControlSurface === "cli"
30
+ ? "cli"
31
+ : undefined;
32
+ if (capabilities.promptTerminalOutcomeVersion !== 1 || surface === undefined)
33
+ throw new AcpSdkAdapterError(
34
+ "unavailable",
35
+ `ACP session ${sessionId} is served by a live GJC host that predates startup control provenance. Upgrading the client does not upgrade that already-running host: stop it, then reopen the session so the current build resumes it from its stored record.`,
36
+ );
37
+ return surface;
38
+ }
39
+
40
+ function describeFailure(failure: unknown): string {
41
+ if (failure === undefined) return "";
42
+ let code: unknown;
43
+ try {
44
+ if ((typeof failure !== "object" || failure === null) && typeof failure !== "function") return " (query failed)";
45
+ code = (failure as { code?: unknown }).code;
46
+ } catch {
47
+ return " (query failed)";
48
+ }
49
+ switch (code) {
50
+ case "connection_closed":
51
+ return " (connection closed)";
52
+ case "timeout":
53
+ return " (query timed out)";
54
+ case "uncertain_after_send":
55
+ return " (query outcome uncertain)";
56
+ default:
57
+ return " (query failed)";
58
+ }
59
+ }
@@ -1,3 +1,4 @@
1
+ import * as crypto from "node:crypto";
1
2
  import { Container, Input, matchesKey, SecretInput, Spacer, Text, TruncatedText } from "@gajae-code/tui";
2
3
  import type { ProviderCompatibility, ProviderSetupInput } from "../../setup/provider-onboarding";
3
4
  import { theme } from "../theme/theme";
@@ -12,6 +13,7 @@ type WizardStep =
12
13
  | "base-url"
13
14
  | "credential-source"
14
15
  | "credential"
16
+ | "discover"
15
17
  | "models"
16
18
  | "confirm"
17
19
  | "force-confirm";
@@ -22,11 +24,33 @@ interface WizardState {
22
24
  baseUrl: string;
23
25
  credentialSource: CustomProviderCredentialSource;
24
26
  credential: string;
27
+ discoverModels: boolean;
28
+ discoveredModels: string[];
29
+ /** Inputs that produced discoveredModels; empty when results are stale/unprobed. */
30
+ discoveredForBaseUrl: string;
31
+ /** SHA-256 of the credential that produced the results — never the secret itself. */
32
+ discoveredForCredentialHash: string;
33
+ discoveredForCredentialSource: CustomProviderCredentialSource;
34
+ discoveryError: string | null;
25
35
  models: string;
26
36
  }
27
37
 
28
38
  export type CustomProviderWizardSubmit = ProviderSetupInput;
29
39
 
40
+ export interface CustomProviderWizardDiscoveryDeps {
41
+ discoverModels?: (input: {
42
+ baseUrl: string;
43
+ apiKeyEnv?: string;
44
+ apiKey?: string;
45
+ signal?: AbortSignal;
46
+ }) => Promise<{ models: string[] }>;
47
+ }
48
+
49
+ /** Non-secret fingerprint binding probe results to the credential that produced them. */
50
+ function fingerprintCredential(credential: string): string {
51
+ return `sha256:${crypto.createHash("sha256").update(credential, "utf8").digest("hex")}`;
52
+ }
53
+
30
54
  export class CustomProviderWizardComponent extends Container {
31
55
  #contentContainer: Container;
32
56
  #input: Input | SecretInput | null = null;
@@ -39,22 +63,37 @@ export class CustomProviderWizardComponent extends Container {
39
63
  baseUrl: "",
40
64
  credentialSource: "env",
41
65
  credential: "",
66
+ discoverModels: false,
67
+ discoveredModels: [],
68
+ discoveredForBaseUrl: "",
69
+ discoveredForCredentialHash: "",
70
+ discoveredForCredentialSource: "env",
71
+ discoveryError: null,
42
72
  models: "",
43
73
  };
44
74
  #submitInFlight = false;
75
+ #discoveryInFlight = false;
76
+ #discoveryGeneration = 0;
77
+ #submitGeneration = 0;
78
+ #discoveryAbort: AbortController | null = null;
79
+ #submitAbort: AbortController | null = null;
80
+ #dismissed = false;
45
81
  #onSubmit: (input: CustomProviderWizardSubmit) => void;
46
82
  #onCancel: () => void;
47
83
  #onRender: () => void;
84
+ #discoveryDeps: CustomProviderWizardDiscoveryDeps = {};
48
85
 
49
86
  constructor(
50
87
  onSubmit: (input: CustomProviderWizardSubmit) => void,
51
88
  onCancel: () => void,
52
89
  onRender: () => void = () => {},
90
+ discoveryDeps: CustomProviderWizardDiscoveryDeps = {},
53
91
  ) {
54
92
  super();
55
93
  this.#onSubmit = onSubmit;
56
94
  this.#onCancel = onCancel;
57
95
  this.#onRender = onRender;
96
+ this.#discoveryDeps = discoveryDeps;
58
97
 
59
98
  this.addChild(new DynamicBorder());
60
99
  this.addChild(new Spacer(1));
@@ -83,6 +122,8 @@ export class CustomProviderWizardComponent extends Container {
83
122
  handleInput(keyData: string): void {
84
123
  if (matchesAppInterrupt(keyData)) {
85
124
  if (this.#step === "compatibility") {
125
+ this.#dismissed = true;
126
+ this.#cancelDiscovery();
86
127
  this.#clearLiteralCredential();
87
128
  this.#onCancel();
88
129
  return;
@@ -155,6 +196,9 @@ export class CustomProviderWizardComponent extends Container {
155
196
  this.#renderSecretInputStep();
156
197
  }
157
198
  break;
199
+ case "discover":
200
+ this.#renderDiscoverStep();
201
+ break;
158
202
  case "models":
159
203
  this.#renderInputStep(
160
204
  "Step 6: Model id(s)",
@@ -204,6 +248,49 @@ export class CustomProviderWizardComponent extends Container {
204
248
  this.#addHelp("[Enter to continue, Esc to go back]");
205
249
  }
206
250
 
251
+ #renderDiscoverStep(): void {
252
+ this.#contentContainer.addChild(new Text(theme.fg("accent", "Step 6: Model discovery")));
253
+ this.#contentContainer.addChild(new Spacer(1));
254
+ if (this.#state.compatibility !== "openai") {
255
+ this.#contentContainer.addChild(
256
+ new Text("Model discovery needs an OpenAI-compatible endpoint. Continue with manual model ids.", 0, 0),
257
+ );
258
+ this.#contentContainer.addChild(new Spacer(1));
259
+ this.#addOption(0, "Enter model ids manually");
260
+ this.#addHelp("[Enter to continue, Esc to go back]");
261
+ return;
262
+ }
263
+ if (this.#discoveryInFlight) {
264
+ this.#contentContainer.addChild(new Text("Discovering models from the provider /v1/models endpoint…", 0, 0));
265
+ this.#contentContainer.addChild(new Spacer(1));
266
+ this.#addHelp("The API key is sent only to your configured base URL.");
267
+ return;
268
+ }
269
+ if (this.#state.discoveryError) {
270
+ this.#contentContainer.addChild(
271
+ new Text(theme.fg("warning", `Discovery failed: ${this.#state.discoveryError}`), 0, 0),
272
+ );
273
+ this.#contentContainer.addChild(new Spacer(1));
274
+ }
275
+ if (this.#state.discoveredModels.length > 0) {
276
+ const preview = this.#state.discoveredModels.slice(0, 10).join(", ");
277
+ const extra =
278
+ this.#state.discoveredModels.length > 10 ? ` (+${this.#state.discoveredModels.length - 10} more)` : "";
279
+ this.#contentContainer.addChild(
280
+ new Text(`Discovered ${this.#state.discoveredModels.length} model(s): ${preview}${extra}`, 0, 0),
281
+ );
282
+ this.#contentContainer.addChild(new Spacer(1));
283
+ } else if (!this.#state.discoveryError) {
284
+ this.#contentContainer.addChild(
285
+ new Text("Probe the provider /v1/models endpoint, or enter model ids manually.", 0, 0),
286
+ );
287
+ this.#contentContainer.addChild(new Spacer(1));
288
+ }
289
+ this.#addOption(0, this.#state.discoveredModels.length > 0 ? "Use discovered models" : "Discover models now");
290
+ this.#addOption(1, "Enter model ids manually");
291
+ this.#addHelp("[↑↓ to navigate, Enter to select, Esc to go back]");
292
+ }
293
+
207
294
  #renderSecretInputStep(): void {
208
295
  this.#contentContainer.addChild(new Text(theme.fg("accent", "Step 5: Credential")));
209
296
  this.#contentContainer.addChild(new Spacer(1));
@@ -214,9 +301,7 @@ export class CustomProviderWizardComponent extends Container {
214
301
  const credential = secret.consume().trim();
215
302
  if (!credential) return;
216
303
  this.#state.credential = credential;
217
- this.#step = "models";
218
- this.#renderStep();
219
- this.#onRender();
304
+ this.#enterDiscovery();
220
305
  };
221
306
  this.#input = input;
222
307
  this.#contentContainer.addChild(input);
@@ -267,16 +352,25 @@ export class CustomProviderWizardComponent extends Container {
267
352
  if (!value) return;
268
353
  if (this.#step === "provider-id") {
269
354
  this.#state.providerId = value;
355
+ // A provider-ID revision invalidates pending submits exactly
356
+ // like URL/credential revisions do.
357
+ this.#clearStaleDiscovery();
270
358
  this.#step = "base-url";
271
359
  } else if (this.#step === "base-url") {
272
360
  this.#state.baseUrl = value;
361
+ this.#clearStaleDiscovery();
273
362
  this.#step = "credential-source";
274
363
  this.#selectedIndex = 0;
275
364
  } else if (this.#step === "credential") {
276
365
  this.#state.credential = value;
277
- this.#step = "models";
366
+ this.#enterDiscovery();
367
+ return;
278
368
  } else if (this.#step === "models") {
279
369
  this.#state.models = value;
370
+ // Manual entry supersedes any accepted discovery (clearStale
371
+ // also resets discoverModels): submitting both would silently
372
+ // persist live discovery the manual screen never disclosed.
373
+ this.#clearStaleDiscovery();
280
374
  this.#step = "confirm";
281
375
  this.#selectedIndex = 0;
282
376
  this.#lastSubmitError = null;
@@ -285,6 +379,18 @@ export class CustomProviderWizardComponent extends Container {
285
379
  this.#onRender();
286
380
  }
287
381
 
382
+ #enterDiscovery(): void {
383
+ this.#clearStaleDiscovery();
384
+ this.#step = "discover";
385
+ this.#selectedIndex = 0;
386
+ if (this.#state.compatibility === "openai" && this.#discoveryDeps.discoverModels) {
387
+ this.#runDiscovery();
388
+ } else {
389
+ this.#renderStep();
390
+ this.#onRender();
391
+ }
392
+ }
393
+
288
394
  #selectCurrentOption(): void {
289
395
  if (this.#step === "compatibility") {
290
396
  this.#state.compatibility = this.#selectedIndex === 0 ? "openai" : "anthropic";
@@ -293,37 +399,189 @@ export class CustomProviderWizardComponent extends Container {
293
399
  this.#state.credentialSource = this.#selectedIndex === 0 ? "env" : "literal";
294
400
  this.#state.credential = "";
295
401
  this.#step = "credential";
402
+ } else if (this.#step === "discover") {
403
+ if (this.#state.compatibility !== "openai") {
404
+ this.#step = "models";
405
+ } else if (this.#selectedIndex === 0) {
406
+ if (this.#state.discoveredModels.length > 0 && this.#discoveryResultsAreFresh()) {
407
+ this.#state.discoverModels = true;
408
+ this.#state.models = "";
409
+ this.#step = "confirm";
410
+ this.#selectedIndex = 0;
411
+ this.#lastSubmitError = null;
412
+ } else {
413
+ this.#runDiscovery();
414
+ return;
415
+ }
416
+ } else {
417
+ this.#state.discoverModels = false;
418
+ this.#cancelDiscovery();
419
+ this.#step = "models";
420
+ }
296
421
  } else if (this.#step === "confirm" || this.#step === "force-confirm") {
297
422
  if (this.#selectedIndex === 0) {
298
423
  this.#submit();
299
424
  return;
300
425
  }
301
- this.#step = "models";
426
+ this.#goBack();
427
+ return;
302
428
  }
303
429
  this.#renderStep();
304
430
  this.#onRender();
305
431
  }
306
432
 
433
+ #clearStaleDiscovery(): void {
434
+ this.#discoveryGeneration += 1;
435
+ this.#submitGeneration += 1;
436
+ this.#discoveryAbort?.abort();
437
+ this.#discoveryAbort = null;
438
+ // A revision also invalidates an in-flight submit: without this,
439
+ // a submit-time probe started before the edit could still persist
440
+ // the old URL/key and close the wizard as successful.
441
+ this.#submitAbort?.abort();
442
+ this.#submitAbort = null;
443
+ this.#discoveryInFlight = false;
444
+ this.#state.discoveredModels = [];
445
+ this.#state.discoveredForBaseUrl = "";
446
+ this.#state.discoveredForCredentialHash = "";
447
+ this.#state.discoverModels = false;
448
+ this.#state.discoveryError = null;
449
+ }
450
+
451
+ #discoveryResultsAreFresh(): boolean {
452
+ return (
453
+ this.#state.discoveredForBaseUrl !== "" &&
454
+ this.#state.discoveredForBaseUrl === this.#state.baseUrl.trim() &&
455
+ this.#state.discoveredForCredentialHash !== "" &&
456
+ this.#state.discoveredForCredentialHash === fingerprintCredential(this.#state.credential.trim()) &&
457
+ this.#state.discoveredForCredentialSource === this.#state.credentialSource
458
+ );
459
+ }
460
+
461
+ #runDiscovery(): void {
462
+ const discover = this.#discoveryDeps.discoverModels;
463
+ if (!discover || this.#discoveryInFlight) return;
464
+ this.#discoveryAbort?.abort();
465
+ const controller = new AbortController();
466
+ this.#discoveryAbort = controller;
467
+ this.#discoveryInFlight = true;
468
+ this.#discoveryGeneration += 1;
469
+ const generation = this.#discoveryGeneration;
470
+ this.#state.discoveryError = null;
471
+ this.#renderStep();
472
+ this.#onRender();
473
+ // Immutable fingerprint of the inputs being probed: completions are
474
+ // accepted only when both the generation and the live inputs still
475
+ // match, so an edit made while the request was in flight cannot
476
+ // inherit a catalog fetched for different inputs.
477
+ const credential = this.#state.credential.trim();
478
+ const fingerprint = {
479
+ baseUrl: this.#state.baseUrl.trim(),
480
+ credential,
481
+ credentialSource: this.#state.credentialSource,
482
+ };
483
+ const request = {
484
+ baseUrl: fingerprint.baseUrl,
485
+ apiKeyEnv: fingerprint.credentialSource === "env" ? fingerprint.credential : undefined,
486
+ apiKey: fingerprint.credentialSource === "literal" ? fingerprint.credential : undefined,
487
+ signal: controller.signal,
488
+ };
489
+ void Promise.resolve()
490
+ .then(() => discover(request))
491
+ .then(
492
+ result => {
493
+ if (!this.#isCurrentDiscoveryGeneration(generation)) return;
494
+ this.#discoveryInFlight = false;
495
+ if (!this.#discoveryFingerprintMatches(fingerprint)) {
496
+ if (this.#step === "discover") {
497
+ this.#renderStep();
498
+ this.#onRender();
499
+ }
500
+ return;
501
+ }
502
+ const models = [...new Set(result.models.map(model => model.trim()).filter(Boolean))].sort((a, b) =>
503
+ a.localeCompare(b),
504
+ );
505
+ this.#state.discoveredModels = models;
506
+ this.#state.discoveredForBaseUrl = fingerprint.baseUrl;
507
+ this.#state.discoveredForCredentialHash = fingerprintCredential(fingerprint.credential);
508
+ this.#state.discoveredForCredentialSource = fingerprint.credentialSource;
509
+ this.#state.discoveryError = models.length === 0 ? "The endpoint returned no models." : null;
510
+ this.#selectedIndex = 0;
511
+ if (this.#step === "discover") {
512
+ this.#renderStep();
513
+ this.#onRender();
514
+ }
515
+ },
516
+ error => {
517
+ if (!this.#isCurrentDiscoveryGeneration(generation)) return;
518
+ this.#discoveryInFlight = false;
519
+ if (!this.#discoveryFingerprintMatches(fingerprint)) {
520
+ if (this.#step === "discover") {
521
+ this.#renderStep();
522
+ this.#onRender();
523
+ }
524
+ return;
525
+ }
526
+ this.#state.discoveredModels = [];
527
+ this.#state.discoveredForBaseUrl = "";
528
+ this.#state.discoveredForCredentialHash = "";
529
+ this.#state.discoveryError = error instanceof Error ? error.message : String(error);
530
+ this.#selectedIndex = 1;
531
+ if (this.#step === "discover") {
532
+ this.#renderStep();
533
+ this.#onRender();
534
+ }
535
+ },
536
+ );
537
+ }
538
+
539
+ #isCurrentDiscoveryGeneration(generation: number): boolean {
540
+ return generation === this.#discoveryGeneration;
541
+ }
542
+
543
+ #discoveryFingerprintMatches(fingerprint: {
544
+ baseUrl: string;
545
+ credential: string;
546
+ credentialSource: CustomProviderCredentialSource;
547
+ }): boolean {
548
+ return (
549
+ fingerprint.baseUrl === this.#state.baseUrl.trim() &&
550
+ fingerprint.credential === this.#state.credential.trim() &&
551
+ fingerprint.credentialSource === this.#state.credentialSource
552
+ );
553
+ }
554
+
307
555
  #submit(): void {
308
556
  if (this.#submitInFlight) return;
309
557
  this.#submitInFlight = true;
558
+ // Own the submit-time pre-write probe lifecycle: Esc-cancel during a
559
+ // stalled submit aborts the probe via #cancelDiscovery so the
560
+ // provider cannot be written after dismissal.
561
+ this.#submitAbort?.abort();
562
+ this.#submitAbort = new AbortController();
563
+ this.#submitGeneration += 1;
310
564
  let submission: unknown;
311
565
  try {
312
566
  submission = this.#onSubmit(this.#buildInput(this.#step === "force-confirm"));
313
567
  } catch (error) {
314
568
  this.#submitInFlight = false;
569
+ this.#endSubmitDiscovery();
315
570
  throw error;
316
571
  }
317
572
  if (!(submission instanceof Promise)) {
318
573
  this.#submitInFlight = false;
574
+ this.#endSubmitDiscovery();
319
575
  return;
320
576
  }
321
577
  void submission.then(
322
578
  () => {
323
579
  this.#submitInFlight = false;
580
+ this.#endSubmitDiscovery();
324
581
  },
325
582
  () => {
326
583
  this.#submitInFlight = false;
584
+ this.#endSubmitDiscovery();
327
585
  },
328
586
  );
329
587
  }
@@ -339,6 +597,8 @@ export class CustomProviderWizardComponent extends Container {
339
597
  .split(",")
340
598
  .map(model => model.trim())
341
599
  .filter(Boolean),
600
+ discover: this.#state.compatibility === "openai" ? this.#state.discoverModels : false,
601
+ discoverySignal: this.#submitAbort?.signal,
342
602
  force,
343
603
  };
344
604
 
@@ -346,9 +606,44 @@ export class CustomProviderWizardComponent extends Container {
346
606
  }
347
607
 
348
608
  complete(): void {
609
+ this.#cancelDiscovery();
349
610
  this.#clearLiteralCredential();
350
611
  }
351
612
 
613
+ /**
614
+ * Abort any in-flight probe and invalidate its generation so a late
615
+ * completion cannot render into (or retain credentials from) a
616
+ * dismissed wizard. Used by both submit and cancel paths.
617
+ */
618
+ #cancelDiscovery(): void {
619
+ this.#discoveryGeneration += 1;
620
+ this.#submitGeneration += 1;
621
+ this.#discoveryAbort?.abort();
622
+ this.#discoveryAbort = null;
623
+ this.#submitAbort?.abort();
624
+ this.#submitAbort = null;
625
+ this.#discoveryInFlight = false;
626
+ }
627
+
628
+ /** Clear the settled submit controller without aborting (submit finished). */
629
+ #endSubmitDiscovery(): void {
630
+ this.#submitAbort = null;
631
+ }
632
+
633
+ /** Generation token for the latest submit attempt. */
634
+ currentSubmitGeneration(): number {
635
+ return this.#submitGeneration;
636
+ }
637
+
638
+ /**
639
+ * Whether a submit attempt is still current: same generation and not
640
+ * dismissed. Revision or cancel invalidates pending completions so a
641
+ * stale refresh cannot report success or rerender over new inputs.
642
+ */
643
+ isSubmitCurrent(generation: number): boolean {
644
+ return generation === this.#submitGeneration && !this.#dismissed;
645
+ }
646
+
352
647
  #clearLiteralCredential(): void {
353
648
  if (this.#state.credentialSource === "literal") this.#state.credential = "";
354
649
  }
@@ -358,7 +653,8 @@ export class CustomProviderWizardComponent extends Container {
358
653
  this.#step === "confirm" ||
359
654
  this.#step === "force-confirm" ||
360
655
  this.#step === "compatibility" ||
361
- this.#step === "credential-source"
656
+ this.#step === "credential-source" ||
657
+ this.#step === "discover"
362
658
  ? 1
363
659
  : 0;
364
660
  this.#selectedIndex = (this.#selectedIndex + delta + maxIndex + 1) % (maxIndex + 1);
@@ -367,11 +663,16 @@ export class CustomProviderWizardComponent extends Container {
367
663
  }
368
664
 
369
665
  #goBack(): void {
666
+ if (this.#step === "discover" || this.#step === "confirm" || this.#step === "force-confirm") {
667
+ // Revision starts on entry to the editor, not when its new value is saved.
668
+ this.#cancelDiscovery();
669
+ }
370
670
  if (this.#step === "provider-id") this.#step = "compatibility";
371
671
  else if (this.#step === "base-url") this.#step = "provider-id";
372
672
  else if (this.#step === "credential-source") this.#step = "base-url";
373
673
  else if (this.#step === "credential") this.#step = "credential-source";
374
- else if (this.#step === "models") this.#step = "credential";
674
+ else if (this.#step === "discover") this.#step = "credential";
675
+ else if (this.#step === "models") this.#step = "discover";
375
676
  else if (this.#step === "confirm" || this.#step === "force-confirm") this.#step = "models";
376
677
  this.#selectedIndex = 0;
377
678
  this.#renderStep();