@iislee/opencodex 2.11.0 → 2.31.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 (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Shared termination of surviving Windows scheduler launcher/wrapper processes.
3
+ *
4
+ * `schtasks /end` ends the task instance but often leaves wscript/cmd running the
5
+ * `:loop` batch, which brings the proxy back during a stop, a restart, or
6
+ * post-update reclaim. Both the service teardown path and the update job need
7
+ * that guarantee, and they used to carry a copy each.
8
+ *
9
+ * The copies drifted in both directions, which is why this module exists rather
10
+ * than a second careful implementation: the updater received the #1589 argv
11
+ * cleanup that service.ts missed, and service.ts received the canonical-path
12
+ * scoping the updater missed. One of those gaps could force-terminate a wrapper
13
+ * belonging to a DIFFERENT OpenCodex home.
14
+ *
15
+ * Matching is scoped to the CANONICAL paths of one installation, never a bare
16
+ * filename, and the path must appear as a COMPLETE command-line token
17
+ * (wscript.exe spawns the .vbs as an argument; cmd.exe /c runs the .cmd). A
18
+ * substring match is excluded: an unrelated process whose command line merely
19
+ * contains the filename, and a wrapper under another home whose path ends with
20
+ * the same name, must both survive.
21
+ */
22
+ import { spawnSync } from "node:child_process";
23
+
24
+ import { resolveTrustedWindowsPowerShellExe } from "./windows-elevation";
25
+
26
+ /** Quote for PowerShell: single-quote the value and double any embedded quote. */
27
+ function quoteForPowerShell(value: string): string {
28
+ return `'${value.replace(/'/g, "''")}'`;
29
+ }
30
+
31
+ /**
32
+ * The PowerShell that finds and stops the wrappers for exactly these paths.
33
+ * Exported for tests: the matching rule is the whole point of this module, and
34
+ * the spawn itself is best-effort and unobservable.
35
+ */
36
+ export function windowsWrapperKillScript(paths: readonly string[]): string {
37
+ return [
38
+ `$pats = @(${paths.map(quoteForPowerShell).join(", ")});`,
39
+ "Get-CimInstance Win32_Process | Where-Object {",
40
+ " if ($_.ProcessId -eq $PID) { return $false };",
41
+ " $c = $_.CommandLine; if (-not $c) { return $false };",
42
+ " foreach ($p in $pats) {",
43
+ " $i = $c.IndexOf($p, [System.StringComparison]::OrdinalIgnoreCase);",
44
+ " if ($i -lt 0) { continue };",
45
+ " $before = if ($i -gt 0) { $c.Substring($i - 1, 1) } else { ' ' };",
46
+ " $end = $i + $p.Length;",
47
+ " $after = if ($end -lt $c.Length) { $c.Substring($end, 1) } else { ' ' };",
48
+ " if ($before -match '[\\s\"'']' -and $after -match '[\\s\"'']') { return $true };",
49
+ " };",
50
+ " $false",
51
+ "} | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }",
52
+ ].join(" ");
53
+ }
54
+
55
+ /**
56
+ * Best-effort: never throws, never reports. A wrapper that survives is handled
57
+ * by the caller's own stop verification.
58
+ */
59
+ export function killWindowsSchedulerWrappers(paths: {
60
+ scriptPath: string;
61
+ launcherPath: string;
62
+ }): void {
63
+ if (process.platform !== "win32") return;
64
+ try {
65
+ spawnSync(resolveTrustedWindowsPowerShellExe(), [
66
+ // No `-WindowStyle Hidden` here: Bun 1.3.14 can fail that direct CLI pair
67
+ // before the command runs (#1589). `windowsHide` below is sufficient.
68
+ "-NoProfile", "-NoLogo", "-NonInteractive",
69
+ "-Command", windowsWrapperKillScript([paths.scriptPath, paths.launcherPath]),
70
+ ], { stdio: "ignore", timeout: 5000, windowsHide: true });
71
+ } catch { /* best-effort */ }
72
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Decode bounded text emitted by Windows system tools.
3
+ *
4
+ * [Decision Log]
5
+ * - Purpose: preserve non-ASCII paths when a Windows tool writes the active
6
+ * legacy code page instead of UTF-8.
7
+ * - Existing constraint: generated service assets may be UTF-16, while
8
+ * redirected `schtasks` output follows the Windows locale on affected hosts.
9
+ * - Alternatives considered: replacement-character heuristics and a new
10
+ * iconv dependency. The former can reinterpret valid text; the latter widens
11
+ * the install/security surface for two small, already-supported codecs.
12
+ * - Choice: recognize UTF-16 first, accept only strict UTF-8 next, then use the
13
+ * locale-appropriate WHATWG decoder (CP949 through `euc-kr`, or Windows-1252
14
+ * only for locales that actually use that family). Unknown/unsupported
15
+ * locales fail back to the old replacement-preserving UTF-8 result instead
16
+ * of guessing another code page or throwing in diagnostics.
17
+ * - Impact: decoding stays dependency-free and bounded, but this deliberately
18
+ * does not guess arbitrary OEM code pages that the runtime cannot identify.
19
+ */
20
+
21
+ function trimWindowsText(value: string): string {
22
+ return value.replace(/^\uFEFF/, "").trim();
23
+ }
24
+
25
+ function currentWindowsLocale(): string {
26
+ try {
27
+ return Intl.DateTimeFormat().resolvedOptions().locale;
28
+ } catch {
29
+ return "en-US";
30
+ }
31
+ }
32
+
33
+ function decodeStrict(buffer: Uint8Array, encoding: string): string | null {
34
+ try {
35
+ return trimWindowsText(new TextDecoder(encoding, { fatal: true }).decode(buffer));
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
40
+
41
+ function decodeUtf16Be(buffer: Uint8Array): string {
42
+ const payloadLength = buffer.length - 2;
43
+ const swapped = Buffer.alloc(payloadLength - (payloadLength % 2));
44
+ for (let i = 2; i + 1 < buffer.length; i += 2) {
45
+ swapped[i - 2] = buffer[i + 1]!;
46
+ swapped[i - 1] = buffer[i]!;
47
+ }
48
+ return trimWindowsText(swapped.toString("utf16le"));
49
+ }
50
+
51
+ /**
52
+ * CP949 is exposed by the Encoding Standard under the `euc-kr` label. Keep the
53
+ * Western fallback deliberately narrow: treating CP932, CP1250, or CP1251
54
+ * bytes as Windows-1252 can fabricate a different valid-looking filesystem
55
+ * path, which is worse than the previous replacement-character refusal.
56
+ */
57
+ function legacyEncodingForLocale(locale: string): "euc-kr" | "windows-1252" | null {
58
+ const language = locale.trim().split(/[-_]/, 1)[0]?.toLowerCase();
59
+ if (language === "ko") return "euc-kr";
60
+ if (language && WINDOWS_1252_LANGUAGES.has(language)) return "windows-1252";
61
+ return null;
62
+ }
63
+
64
+ const WINDOWS_1252_LANGUAGES = new Set([
65
+ "af", "br", "ca", "co", "cy", "da", "de", "en", "es", "eu", "fi", "fo", "fr",
66
+ "ga", "gd", "gl", "id", "is", "it", "lb", "ms", "nl", "no", "oc", "pt", "sq",
67
+ "sv", "sw",
68
+ ]);
69
+
70
+ export interface WindowsTextDecodeOptions {
71
+ /** Test seam and explicit locale override; production uses the active Intl locale. */
72
+ readonly locale?: string;
73
+ }
74
+
75
+ export function decodeWindowsTextBytes(
76
+ buffer: Uint8Array,
77
+ options: WindowsTextDecodeOptions = {},
78
+ ): string {
79
+ if (buffer.length === 0) return "";
80
+
81
+ const bomUtf16Le = buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe;
82
+ const bomUtf16Be = buffer.length >= 2 && buffer[0] === 0xfe && buffer[1] === 0xff;
83
+ const looksUtf16Le = buffer.length >= 4
84
+ && buffer[1] === 0x00
85
+ && buffer[3] === 0x00
86
+ && buffer[0] !== 0x00;
87
+
88
+ if (bomUtf16Le || looksUtf16Le) {
89
+ return trimWindowsText(Buffer.from(buffer).toString("utf16le"));
90
+ }
91
+ if (bomUtf16Be) return decodeUtf16Be(buffer);
92
+
93
+ const utf8 = decodeStrict(buffer, "utf-8");
94
+ if (utf8 !== null) return utf8;
95
+
96
+ const locale = options.locale ?? currentWindowsLocale();
97
+ const legacyEncoding = legacyEncodingForLocale(locale);
98
+ if (legacyEncoding !== null) {
99
+ const legacy = decodeStrict(buffer, legacyEncoding);
100
+ if (legacy !== null) return legacy;
101
+ }
102
+
103
+ // Preserve the previous fail-soft behavior when the runtime lacks a codec or
104
+ // the bytes are malformed even for the selected Windows code page.
105
+ return trimWindowsText(new TextDecoder("utf-8").decode(buffer));
106
+ }
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Resolve the effective Windows token to the locale-independent SID form that
3
+ * icacls accepts ("*S-1-..."). Environment values such as USERDOMAIN are not
4
+ * an authority for the current token: on workgroup machines USERDOMAIN may be
5
+ * the literal WORKGROUP even though the account belongs to the local computer.
6
+ *
7
+ * There is deliberately NO name-shaped fallback. A `DOMAIN\User` string has a
8
+ * valid shape, but shape is not evidence that the account is the current
9
+ * token's subject, and both environment variables are writable by whatever
10
+ * launched us. A wrong principal here is not cosmetic: `runIcacls` grants it
11
+ * Full Control and then removes inheritance, so a wrong grant either leaves a
12
+ * different account holding the secret or strands the file with no usable ACE.
13
+ * When the SID cannot be resolved, the caller declines to touch the ACL at all.
14
+ *
15
+ * Budget caveat: callers pass their REMAINING harden budget, which becomes the
16
+ * child process timeout. Trusted-executable resolution (a `GetSystemDirectoryW`
17
+ * FFI call) and spawn setup happen before that timeout starts, and the async
18
+ * timer only arms once `Bun.spawn` returns. Both are small in practice, but the
19
+ * lookup is not bounded by the deadline to the microsecond. Tightening that
20
+ * would mean passing an absolute deadline through the runner interface.
21
+ */
22
+
23
+ import { existsSync } from "node:fs";
24
+ import { win32 as windowsPath } from "node:path";
25
+
26
+ import {
27
+ resolveTrustedWindowsPowerShellExe,
28
+ WindowsSystemDirectoryFfiUnavailableError,
29
+ } from "./windows-elevation";
30
+
31
+ const SID_PATTERN = /^S-1-(?:\d+-)+\d+$/i;
32
+ const SID_EXPRESSION =
33
+ "[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value";
34
+ const DEFAULT_WINDOWS_ARM64_POWERSHELL = windowsPath.join(
35
+ "C:\\Windows\\System32",
36
+ "WindowsPowerShell",
37
+ "v1.0",
38
+ "powershell.exe",
39
+ );
40
+
41
+ type PrincipalExecutableResolution = Readonly<{
42
+ platform: NodeJS.Platform;
43
+ arch: string;
44
+ resolveTrusted: () => string;
45
+ pathExists: (path: string) => boolean;
46
+ }>;
47
+
48
+ /**
49
+ * Bun's Windows ARM64 build cannot currently execute the `bun:ffi` call used
50
+ * by the general System32 resolver. The ACL identity lookup has a narrower
51
+ * authority than the elevation helpers: it starts one non-elevated PowerShell
52
+ * command and accepts only a SID-shaped result. Keep its fallback equally
53
+ * narrow by using the fixed, OS-protected default installation path only.
54
+ *
55
+ * Environment and PATH lookup are deliberately absent. A Windows installation
56
+ * outside C:\\Windows keeps failing closed rather than executing a binary chosen
57
+ * by caller-controlled `SystemRoot`, `WINDIR`, or `PATH` values.
58
+ */
59
+ function resolveWindowsPrincipalPowerShellExecutable(
60
+ resolution: PrincipalExecutableResolution = {
61
+ platform: process.platform,
62
+ arch: process.arch,
63
+ resolveTrusted: resolveTrustedWindowsPowerShellExe,
64
+ pathExists: existsSync,
65
+ },
66
+ ): string {
67
+ try {
68
+ return resolution.resolveTrusted();
69
+ } catch (error) {
70
+ if (
71
+ !(error instanceof WindowsSystemDirectoryFfiUnavailableError) ||
72
+ resolution.platform !== "win32" ||
73
+ resolution.arch !== "arm64" ||
74
+ !resolution.pathExists(DEFAULT_WINDOWS_ARM64_POWERSHELL)
75
+ ) {
76
+ throw error;
77
+ }
78
+ return DEFAULT_WINDOWS_ARM64_POWERSHELL;
79
+ }
80
+ }
81
+
82
+ /** Test-only dependency-injected view of the Windows ARM64 executable boundary. */
83
+ export function resolveWindowsPrincipalPowerShellExecutableForTests(
84
+ resolution: PrincipalExecutableResolution,
85
+ ): string {
86
+ return resolveWindowsPrincipalPowerShellExecutable(resolution);
87
+ }
88
+
89
+ export interface WindowsPrincipalLookupResult {
90
+ success: boolean;
91
+ exitCode: number | null;
92
+ timedOut: boolean;
93
+ stdout: string;
94
+ }
95
+
96
+ export type WindowsPrincipalRunner = (
97
+ timeoutMs: number,
98
+ ) => WindowsPrincipalLookupResult;
99
+
100
+ export type AsyncWindowsPrincipalRunner = (
101
+ timeoutMs: number,
102
+ ) => Promise<WindowsPrincipalLookupResult>;
103
+
104
+ const POWERSHELL_ARGS = [
105
+ "-NoLogo",
106
+ "-NoProfile",
107
+ "-NonInteractive",
108
+ "-Command",
109
+ SID_EXPRESSION,
110
+ ] as const;
111
+
112
+ function windowsPrincipalPowerShellCommand(): string[] {
113
+ return [resolveWindowsPrincipalPowerShellExecutable(), ...POWERSHELL_ARGS];
114
+ }
115
+
116
+ /** Test-only readback of the exact trusted executable and static arguments. */
117
+ export function windowsPrincipalPowerShellCommandForTests(): string[] {
118
+ return windowsPrincipalPowerShellCommand();
119
+ }
120
+
121
+ function defaultWindowsPrincipalRunner(timeoutMs: number): WindowsPrincipalLookupResult {
122
+ const result = Bun.spawnSync(windowsPrincipalPowerShellCommand(), {
123
+ stdin: "ignore",
124
+ stdout: "pipe",
125
+ stderr: "ignore",
126
+ timeout: Math.max(1, timeoutMs),
127
+ windowsHide: true,
128
+ });
129
+ return {
130
+ success: result.success,
131
+ exitCode: result.exitCode,
132
+ timedOut: result.exitedDueToTimeout ?? false,
133
+ stdout: result.stdout ? result.stdout.toString() : "",
134
+ };
135
+ }
136
+
137
+ async function defaultAsyncWindowsPrincipalRunner(
138
+ timeoutMs: number,
139
+ ): Promise<WindowsPrincipalLookupResult> {
140
+ const proc = Bun.spawn(windowsPrincipalPowerShellCommand(), {
141
+ stdin: "ignore",
142
+ stdout: "pipe",
143
+ stderr: "ignore",
144
+ windowsHide: true,
145
+ });
146
+ let timedOut = false;
147
+ const timer = setTimeout(() => {
148
+ timedOut = true;
149
+ try { proc.kill(); } catch { /* already exited */ }
150
+ }, Math.max(1, timeoutMs));
151
+ let exitCode: number | null = null;
152
+ try {
153
+ exitCode = await proc.exited;
154
+ } finally {
155
+ clearTimeout(timer);
156
+ }
157
+ const stdout = proc.stdout
158
+ ? await new Response(proc.stdout).text().catch(() => "")
159
+ : "";
160
+ return {
161
+ success: !timedOut && exitCode === 0,
162
+ exitCode: timedOut ? null : exitCode,
163
+ timedOut,
164
+ stdout,
165
+ };
166
+ }
167
+
168
+ let principalRunner: WindowsPrincipalRunner = defaultWindowsPrincipalRunner;
169
+ let asyncPrincipalRunner: AsyncWindowsPrincipalRunner = defaultAsyncWindowsPrincipalRunner;
170
+ let cachedPrincipal: string | null = null;
171
+ let asyncLookupInFlight: Promise<string> | null = null;
172
+
173
+ /**
174
+ * POSIX CI drives the Windows ACL branch through `setPlatformForTests("win32")`,
175
+ * on hosts that have neither System32 nor PowerShell. Those runs need SOME
176
+ * principal, so this seam supplies a synthetic one.
177
+ *
178
+ * It lives here rather than in `windows-secret-acl.ts` for one reason that is
179
+ * not cosmetic: an explicitly injected runner must be able to beat it. When the
180
+ * synthetic value was chosen first, in the ACL module, a test could not inject a
181
+ * lookup FAILURE on POSIX at all — so the fail-closed and memo-isolation cases
182
+ * were guarded with `if (process.platform !== "win32") return;` and never ran
183
+ * outside Windows. Resolution order below is what makes those cases executable
184
+ * on every runner.
185
+ */
186
+ let syntheticPrincipalForTests: string | null = null;
187
+
188
+ /**
189
+ * Test seam: supply the principal used when no runner was injected and the host
190
+ * is not really Windows. Pass null to disable.
191
+ */
192
+ export function setSyntheticWindowsPrincipalForTests(principal: string | null): void {
193
+ syntheticPrincipalForTests = principal;
194
+ cachedPrincipal = null;
195
+ }
196
+
197
+ /** True when an explicit runner override is installed and must take precedence. */
198
+ function hasSyncRunnerOverride(): boolean {
199
+ return principalRunner !== defaultWindowsPrincipalRunner;
200
+ }
201
+
202
+ function hasAsyncRunnerOverride(): boolean {
203
+ return asyncPrincipalRunner !== defaultAsyncWindowsPrincipalRunner;
204
+ }
205
+
206
+ function identityError(reason: string): NodeJS.ErrnoException {
207
+ const error = new Error(`Windows effective-account SID lookup ${reason}`) as NodeJS.ErrnoException;
208
+ // Keep identity lookup failures distinct from icacls timeouts. In particular,
209
+ // they must not populate windows-secret-acl's destination timeout memo.
210
+ error.code = "EACLIDENTITY";
211
+ return error;
212
+ }
213
+
214
+ function principalFromResult(result: WindowsPrincipalLookupResult): string {
215
+ if (!result.success) {
216
+ throw identityError(result.timedOut
217
+ ? "timed out"
218
+ : `exited ${result.exitCode ?? "null"}`);
219
+ }
220
+ const sid = result.stdout.trim();
221
+ if (!SID_PATTERN.test(sid)) {
222
+ throw identityError(sid ? "returned an invalid SID" : "returned an empty SID");
223
+ }
224
+ return `*${sid.toUpperCase()}`;
225
+ }
226
+
227
+ /** Resolve and process-cache the effective token SID for synchronous ACL paths. */
228
+ export function resolveCurrentWindowsPrincipal(timeoutMs: number): string {
229
+ // Order matters: an explicitly injected runner outranks the synthetic value,
230
+ // so a test can inject a FAILURE on a POSIX host. See the seam comment above.
231
+ if (hasSyncRunnerOverride()) {
232
+ if (cachedPrincipal) return cachedPrincipal;
233
+ if (timeoutMs <= 0) throw identityError("had no remaining deadline");
234
+ let overridden: WindowsPrincipalLookupResult;
235
+ try {
236
+ overridden = principalRunner(timeoutMs);
237
+ } catch {
238
+ throw identityError("could not start");
239
+ }
240
+ const principal = principalFromResult(overridden);
241
+ cachedPrincipal = principal;
242
+ return principal;
243
+ }
244
+ if (cachedPrincipal) return cachedPrincipal;
245
+ if (syntheticPrincipalForTests) return syntheticPrincipalForTests;
246
+ if (timeoutMs <= 0) throw identityError("had no remaining deadline");
247
+ let result: WindowsPrincipalLookupResult;
248
+ try {
249
+ result = principalRunner(timeoutMs);
250
+ } catch {
251
+ throw identityError("could not start");
252
+ }
253
+ const principal = principalFromResult(result);
254
+ cachedPrincipal = principal;
255
+ return principal;
256
+ }
257
+
258
+ async function waitForExistingLookup(
259
+ lookup: Promise<string>,
260
+ timeoutMs: number,
261
+ ): Promise<string> {
262
+ if (timeoutMs <= 0) throw identityError("had no remaining deadline");
263
+ let timer: ReturnType<typeof setTimeout> | undefined;
264
+ try {
265
+ return await Promise.race([
266
+ lookup,
267
+ new Promise<never>((_, reject) => {
268
+ timer = setTimeout(
269
+ () => reject(identityError("timed out while awaiting the shared lookup")),
270
+ Math.max(1, timeoutMs),
271
+ );
272
+ }),
273
+ ]);
274
+ } finally {
275
+ if (timer) clearTimeout(timer);
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Async counterpart. Concurrent callers share one owned child lookup; a later
281
+ * caller may exhaust its own budget without cancelling the lookup owned by the
282
+ * first caller. The first caller owns that child and its process timeout; a
283
+ * later, longer budget deliberately does not extend an already-running child.
284
+ */
285
+ export async function resolveCurrentWindowsPrincipalAsync(timeoutMs: number): Promise<string> {
286
+ const overridden = hasAsyncRunnerOverride();
287
+ if (cachedPrincipal) return cachedPrincipal;
288
+ if (asyncLookupInFlight) return waitForExistingLookup(asyncLookupInFlight, timeoutMs);
289
+ // Same precedence rule as the sync path: an injected runner beats the synthetic.
290
+ if (!overridden && syntheticPrincipalForTests) return syntheticPrincipalForTests;
291
+ if (timeoutMs <= 0) throw identityError("had no remaining deadline");
292
+
293
+ const lookup = (async (): Promise<string> => {
294
+ let result: WindowsPrincipalLookupResult;
295
+ try {
296
+ result = await asyncPrincipalRunner(timeoutMs);
297
+ } catch {
298
+ throw identityError("could not start");
299
+ }
300
+ const principal = principalFromResult(result);
301
+ cachedPrincipal = principal;
302
+ return principal;
303
+ })();
304
+ asyncLookupInFlight = lookup;
305
+ try {
306
+ return await lookup;
307
+ } finally {
308
+ if (asyncLookupInFlight === lookup) asyncLookupInFlight = null;
309
+ }
310
+ }
311
+
312
+ /** Test seam: replace the sync resolver process and clear its successful cache. */
313
+ export function setWindowsPrincipalRunnerForTests(
314
+ runner: WindowsPrincipalRunner | null,
315
+ ): void {
316
+ if (asyncLookupInFlight) {
317
+ throw new Error("Cannot replace the Windows principal runner while a lookup is in flight.");
318
+ }
319
+ principalRunner = runner ?? defaultWindowsPrincipalRunner;
320
+ cachedPrincipal = null;
321
+ }
322
+
323
+ /** Test seam: replace the async resolver process and clear its successful cache. */
324
+ export function setAsyncWindowsPrincipalRunnerForTests(
325
+ runner: AsyncWindowsPrincipalRunner | null,
326
+ ): void {
327
+ if (asyncLookupInFlight) {
328
+ throw new Error("Cannot replace the Windows principal runner while a lookup is in flight.");
329
+ }
330
+ asyncPrincipalRunner = runner ?? defaultAsyncWindowsPrincipalRunner;
331
+ cachedPrincipal = null;
332
+ }
333
+
334
+ /** Test seam: clear only process-local principal state. */
335
+ export function resetWindowsPrincipalForTests(): void {
336
+ if (asyncLookupInFlight) {
337
+ throw new Error("Cannot reset the Windows principal while a lookup is in flight.");
338
+ }
339
+ cachedPrincipal = null;
340
+ syntheticPrincipalForTests = null;
341
+ }
package/src/lib/winsw.ts CHANGED
@@ -17,10 +17,11 @@ import { createHash } from "node:crypto";
17
17
  import { execFileSync } from "node:child_process";
18
18
  import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
19
19
  import { homedir } from "node:os";
20
- import { join, resolve } from "node:path";
20
+ import { join, resolve, win32 } from "node:path";
21
21
  import { expandUserPath, getConfigDir, loadConfig } from "../config";
22
22
  import { recordOwnedConfigPath } from "./config-ownership";
23
- import { durableBunPath } from "./bun-runtime";
23
+ import { BUN_RUNTIME_PATH_ENV, BUN_RUNTIME_SOURCE_ENV, durableBunRuntime } from "./bun-runtime";
24
+ import type { BunRuntimeSource } from "./bun-runtime";
24
25
  import { serviceApiTokenFilePath } from "./service-secrets";
25
26
 
26
27
  export const WINSW_VERSION = "2.12.0";
@@ -62,8 +63,15 @@ function currentCodexHomeAbsolute(): string {
62
63
  return raw ? resolve(expandUserPath(raw)) : join(homedir(), ".codex");
63
64
  }
64
65
 
66
+ function windowsServicePathAbsolute(raw: string): string {
67
+ const expanded = expandUserPath(raw);
68
+ return win32.isAbsolute(expanded) ? win32.normalize(expanded) : resolve(expanded);
69
+ }
70
+
65
71
  export interface WinswEntry {
66
72
  bun: string;
73
+ /** Provenance of `bun`, resolved together with it so the two can never disagree. */
74
+ bunRuntimeSource: BunRuntimeSource;
67
75
  cli: string;
68
76
  }
69
77
 
@@ -95,9 +103,12 @@ export function buildWinswXml(entry: WinswEntry, env: NodeJS.ProcessEnv = proces
95
103
  const aclTimeout = env.OPENCODEX_ACL_TIMEOUT_MS?.trim();
96
104
  const envLines = [
97
105
  ` <env name="OCX_SERVICE" value="1"/>`,
106
+ ` <env name="${BUN_RUNTIME_SOURCE_ENV}" value="${xmlEscape(entry.bunRuntimeSource)}"/>`,
107
+ ` <env name="${BUN_RUNTIME_PATH_ENV}" value="${xmlEscape(entry.bun)}"/>`,
98
108
  ` <env name="OCX_API_TOKEN_FILE" value="${xmlEscape(serviceApiTokenFilePath())}"/>`,
99
109
  ` <env name="PATH" value="${xmlEscape(env.PATH ?? "")}"/>`,
100
110
  env.CODEX_HOME?.trim() ? ` <env name="CODEX_HOME" value="${xmlEscape(currentCodexHomeAbsolute())}"/>` : null,
111
+ env.CODEX_SQLITE_HOME?.trim() ? ` <env name="CODEX_SQLITE_HOME" value="${xmlEscape(windowsServicePathAbsolute(env.CODEX_SQLITE_HOME.trim()))}"/>` : null,
101
112
  ` <env name="OPENCODEX_HOME" value="${xmlEscape(getConfigDir())}"/>`,
102
113
  aclTimeout ? ` <env name="OPENCODEX_ACL_TIMEOUT_MS" value="${xmlEscape(aclTimeout)}"/>` : null,
103
114
  ].filter((line): line is string => Boolean(line));
@@ -323,7 +334,23 @@ export async function installWinswService(entry: WinswEntry, deps: WinswInstallD
323
334
  }
324
335
 
325
336
  export function startWinswService(): void { runWinsw(["start"]); }
326
- export function stopWinswService(): void { try { runWinsw(["stopwait"]); } catch { /* not running */ } }
337
+
338
+ /**
339
+ * Stop the native service and prove it is no longer running. `stopwait` can fail both
340
+ * for the benign already-stopped case and for real access/timeout failures, so a bare
341
+ * catch cannot decide whether it is safe for lifecycle callers to continue. Re-read
342
+ * SCM state and only accept the two states that cannot still own the proxy listener.
343
+ */
344
+ export function stopWinswService(): void {
345
+ try { runWinsw(["stopwait"]); } catch { /* classify by verified state below */ }
346
+ const status = statusWinswRaw();
347
+ if (status === "stopped" || status === "nonexistent") return;
348
+ if (status === "unknown") {
349
+ throw new Error("Native service stop could not be verified.");
350
+ }
351
+ throw new Error("Native service is still running after stop.");
352
+ }
353
+
327
354
  export function uninstallWinswService(): void {
328
355
  if (!existsSync(winswExePath())) {
329
356
  // The binary is gone but the SCM registration can outlive it (quarantine, partial
@@ -363,7 +390,7 @@ export function winswStatusSummary(): string {
363
390
  if (status === "nonexistent") {
364
391
  // A stale SCM service can outlive a deleted exe; surface the repair path.
365
392
  return existsSync(winswXmlPath()) && !existsSync(winswExePath())
366
- ? "native assets present but WinSW binary missing — run 'ocx service install --native' to repair"
393
+ ? "native assets present but WinSW binary missing — run 'ocx service repair'"
367
394
  : "";
368
395
  }
369
396
  return `native (WinSW ${WINSW_VERSION}): ${status}`;
@@ -371,5 +398,6 @@ export function winswStatusSummary(): string {
371
398
 
372
399
  /** Default entry mirrors the Task Scheduler baking: durable Bun + cli.ts. */
373
400
  export function defaultWinswEntry(cliDir: string): WinswEntry {
374
- return { bun: durableBunPath(), cli: join(cliDir, "cli", "index.ts") };
401
+ const runtime = durableBunRuntime();
402
+ return { bun: runtime.path, bunRuntimeSource: runtime.source, cli: join(cliDir, "cli", "index.ts") };
375
403
  }
@@ -0,0 +1,74 @@
1
+ import { validateAntigravityImportCredential } from "../google-antigravity";
2
+ import { upsertCredentialByIdentity } from "../store";
3
+ import type { OAuthCredentials } from "../types";
4
+ import {
5
+ ACCOUNT_IMPORT_FORMAT,
6
+ ACCOUNT_IMPORT_MAX_EMAIL_LENGTH,
7
+ ACCOUNT_IMPORT_PROVIDER,
8
+ throwIfAccountImportAborted,
9
+ type AccountImportAdapter,
10
+ type CockpitAccountRecord,
11
+ type ValidatedAntigravityCredential,
12
+ } from "./types";
13
+
14
+ export interface AntigravityImportAdapterDeps {
15
+ validate(refreshToken: string, signal?: AbortSignal): Promise<ValidatedAntigravityCredential>;
16
+ upsert(credential: OAuthCredentials): Promise<"inserted" | "updated">;
17
+ }
18
+
19
+ function safeProviderEmail(value: unknown): string | null {
20
+ if (typeof value !== "string") return null;
21
+ const normalized = value.toLowerCase();
22
+ if (
23
+ normalized.length === 0
24
+ || normalized.length > ACCOUNT_IMPORT_MAX_EMAIL_LENGTH
25
+ || normalized !== normalized.trim()
26
+ || /[\x00-\x20\x7f]/.test(normalized)
27
+ ) return null;
28
+ return normalized;
29
+ }
30
+
31
+ export function createAntigravityAccountImportAdapter(
32
+ deps: AntigravityImportAdapterDeps = {
33
+ validate: validateAntigravityImportCredential,
34
+ upsert: credential => upsertCredentialByIdentity(ACCOUNT_IMPORT_PROVIDER, credential),
35
+ },
36
+ ): AccountImportAdapter {
37
+ return {
38
+ provider: ACCOUNT_IMPORT_PROVIDER,
39
+ format: ACCOUNT_IMPORT_FORMAT,
40
+ async importRecord(record: CockpitAccountRecord, signal?: AbortSignal) {
41
+ throwIfAccountImportAborted(signal);
42
+ let credential: ValidatedAntigravityCredential;
43
+ try {
44
+ credential = await deps.validate(record.refreshToken, signal);
45
+ } catch {
46
+ throwIfAccountImportAborted(signal);
47
+ return { status: "failed", code: "credential_rejected" };
48
+ }
49
+
50
+ throwIfAccountImportAborted(signal);
51
+
52
+ const providerEmail = safeProviderEmail(credential.email);
53
+ if (!providerEmail) return { status: "failed", code: "credential_rejected" };
54
+ if (providerEmail !== record.email) return { status: "failed", code: "identity_mismatch" };
55
+ if (typeof credential.projectId !== "string" || credential.projectId.length === 0) {
56
+ return { status: "failed", code: "missing_project" };
57
+ }
58
+
59
+ throwIfAccountImportAborted(signal);
60
+ try {
61
+ const disposition = await deps.upsert({
62
+ ...credential,
63
+ email: providerEmail,
64
+ source: "credential-file",
65
+ });
66
+ return disposition === "updated"
67
+ ? { status: "updated", code: "updated" }
68
+ : { status: "imported", code: "imported" };
69
+ } catch {
70
+ return { status: "failed", code: "persist_failed" };
71
+ }
72
+ },
73
+ };
74
+ }