@wjarka/cezarion 0.10.0-pr30.54

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 (478) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +838 -0
  3. package/dist/agent-config/account-identity.d.ts +44 -0
  4. package/dist/agent-config/account-identity.js +128 -0
  5. package/dist/agent-config/account-identity.js.map +1 -0
  6. package/dist/agent-config/catalog.d.ts +72 -0
  7. package/dist/agent-config/catalog.js +223 -0
  8. package/dist/agent-config/catalog.js.map +1 -0
  9. package/dist/agent-config/files.d.ts +46 -0
  10. package/dist/agent-config/files.js +119 -0
  11. package/dist/agent-config/files.js.map +1 -0
  12. package/dist/agent-config/model-settings/claude.d.ts +2 -0
  13. package/dist/agent-config/model-settings/claude.js +11 -0
  14. package/dist/agent-config/model-settings/claude.js.map +1 -0
  15. package/dist/agent-config/model-settings/codex.d.ts +2 -0
  16. package/dist/agent-config/model-settings/codex.js +16 -0
  17. package/dist/agent-config/model-settings/codex.js.map +1 -0
  18. package/dist/agent-config/model-settings/opencode.d.ts +2 -0
  19. package/dist/agent-config/model-settings/opencode.js +8 -0
  20. package/dist/agent-config/model-settings/opencode.js.map +1 -0
  21. package/dist/agent-config/model-settings/pi.d.ts +12 -0
  22. package/dist/agent-config/model-settings/pi.js +18 -0
  23. package/dist/agent-config/model-settings/pi.js.map +1 -0
  24. package/dist/agent-config/model-settings/shared.d.ts +9 -0
  25. package/dist/agent-config/model-settings/shared.js +93 -0
  26. package/dist/agent-config/model-settings/shared.js.map +1 -0
  27. package/dist/agent-config/model-settings/types.d.ts +9 -0
  28. package/dist/agent-config/model-settings/types.js +2 -0
  29. package/dist/agent-config/model-settings/types.js.map +1 -0
  30. package/dist/agent-config/models.d.ts +9 -0
  31. package/dist/agent-config/models.js +32 -0
  32. package/dist/agent-config/models.js.map +1 -0
  33. package/dist/agent-config/seed.d.ts +7 -0
  34. package/dist/agent-config/seed.js +90 -0
  35. package/dist/agent-config/seed.js.map +1 -0
  36. package/dist/agent-config/service.d.ts +44 -0
  37. package/dist/agent-config/service.js +71 -0
  38. package/dist/agent-config/service.js.map +1 -0
  39. package/dist/agent-config/validate.d.ts +21 -0
  40. package/dist/agent-config/validate.js +76 -0
  41. package/dist/agent-config/validate.js.map +1 -0
  42. package/dist/automations/coordinator.d.ts +26 -0
  43. package/dist/automations/coordinator.js +66 -0
  44. package/dist/automations/coordinator.js.map +1 -0
  45. package/dist/automations/github-poller.d.ts +74 -0
  46. package/dist/automations/github-poller.js +234 -0
  47. package/dist/automations/github-poller.js.map +1 -0
  48. package/dist/automations/scheduler.d.ts +42 -0
  49. package/dist/automations/scheduler.js +192 -0
  50. package/dist/automations/scheduler.js.map +1 -0
  51. package/dist/automations/store.d.ts +65 -0
  52. package/dist/automations/store.js +298 -0
  53. package/dist/automations/store.js.map +1 -0
  54. package/dist/automations/task-template.d.ts +18 -0
  55. package/dist/automations/task-template.js +95 -0
  56. package/dist/automations/task-template.js.map +1 -0
  57. package/dist/automations/types.d.ts +255 -0
  58. package/dist/automations/types.js +159 -0
  59. package/dist/automations/types.js.map +1 -0
  60. package/dist/config.d.ts +77 -0
  61. package/dist/config.js +242 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/contract/agent-config.d.ts +153 -0
  64. package/dist/contract/agent-profiles.d.ts +347 -0
  65. package/dist/contract/automations.d.ts +935 -0
  66. package/dist/contract/events.d.ts +104 -0
  67. package/dist/contract/github.d.ts +556 -0
  68. package/dist/contract/health.d.ts +102 -0
  69. package/dist/contract/index.d.ts +16 -0
  70. package/dist/contract/index.js +1895 -0
  71. package/dist/contract/projects.d.ts +210 -0
  72. package/dist/contract/repo.d.ts +234 -0
  73. package/dist/contract/runs.d.ts +1473 -0
  74. package/dist/contract/skills.d.ts +232 -0
  75. package/dist/contract/workflows.d.ts +218 -0
  76. package/dist/contract/workspace.d.ts +579 -0
  77. package/dist/core/agent-env.d.ts +31 -0
  78. package/dist/core/agent-env.js +371 -0
  79. package/dist/core/agent-env.js.map +1 -0
  80. package/dist/core/agent-model-policy.d.ts +10 -0
  81. package/dist/core/agent-model-policy.js +36 -0
  82. package/dist/core/agent-model-policy.js.map +1 -0
  83. package/dist/core/agent-profiles.d.ts +62 -0
  84. package/dist/core/agent-profiles.js +90 -0
  85. package/dist/core/agent-profiles.js.map +1 -0
  86. package/dist/core/agent-runner.d.ts +211 -0
  87. package/dist/core/agent-runner.js +68 -0
  88. package/dist/core/agent-runner.js.map +1 -0
  89. package/dist/core/ask.d.ts +105 -0
  90. package/dist/core/ask.js +187 -0
  91. package/dist/core/ask.js.map +1 -0
  92. package/dist/core/backend-detect.d.ts +16 -0
  93. package/dist/core/backend-detect.js +155 -0
  94. package/dist/core/backend-detect.js.map +1 -0
  95. package/dist/core/claude-cli-runner.d.ts +59 -0
  96. package/dist/core/claude-cli-runner.js +483 -0
  97. package/dist/core/claude-cli-runner.js.map +1 -0
  98. package/dist/core/claude-ui-mapper.d.ts +80 -0
  99. package/dist/core/claude-ui-mapper.js +598 -0
  100. package/dist/core/claude-ui-mapper.js.map +1 -0
  101. package/dist/core/codex-app-server-runner.d.ts +41 -0
  102. package/dist/core/codex-app-server-runner.js +584 -0
  103. package/dist/core/codex-app-server-runner.js.map +1 -0
  104. package/dist/core/codex-app-server-transport.d.ts +35 -0
  105. package/dist/core/codex-app-server-transport.js +150 -0
  106. package/dist/core/codex-app-server-transport.js.map +1 -0
  107. package/dist/core/codex-model-catalog.d.ts +10 -0
  108. package/dist/core/codex-model-catalog.js +110 -0
  109. package/dist/core/codex-model-catalog.js.map +1 -0
  110. package/dist/core/codex-ui-mapper.d.ts +112 -0
  111. package/dist/core/codex-ui-mapper.js +766 -0
  112. package/dist/core/codex-ui-mapper.js.map +1 -0
  113. package/dist/core/model-identity.d.ts +125 -0
  114. package/dist/core/model-identity.js +132 -0
  115. package/dist/core/model-identity.js.map +1 -0
  116. package/dist/core/model-presets.d.ts +21 -0
  117. package/dist/core/model-presets.js +81 -0
  118. package/dist/core/model-presets.js.map +1 -0
  119. package/dist/core/ndjson.d.ts +6 -0
  120. package/dist/core/ndjson.js +23 -0
  121. package/dist/core/ndjson.js.map +1 -0
  122. package/dist/core/opencode-model-catalog.d.ts +32 -0
  123. package/dist/core/opencode-model-catalog.js +153 -0
  124. package/dist/core/opencode-model-catalog.js.map +1 -0
  125. package/dist/core/opencode-server-runner.d.ts +32 -0
  126. package/dist/core/opencode-server-runner.js +882 -0
  127. package/dist/core/opencode-server-runner.js.map +1 -0
  128. package/dist/core/opencode-ui-mapper.d.ts +137 -0
  129. package/dist/core/opencode-ui-mapper.js +800 -0
  130. package/dist/core/opencode-ui-mapper.js.map +1 -0
  131. package/dist/core/pi-model-catalog.d.ts +31 -0
  132. package/dist/core/pi-model-catalog.js +152 -0
  133. package/dist/core/pi-model-catalog.js.map +1 -0
  134. package/dist/core/pi-runner.d.ts +24 -0
  135. package/dist/core/pi-runner.js +403 -0
  136. package/dist/core/pi-runner.js.map +1 -0
  137. package/dist/core/pi-ui-mapper.d.ts +36 -0
  138. package/dist/core/pi-ui-mapper.js +304 -0
  139. package/dist/core/pi-ui-mapper.js.map +1 -0
  140. package/dist/core/process-usage.d.ts +66 -0
  141. package/dist/core/process-usage.js +193 -0
  142. package/dist/core/process-usage.js.map +1 -0
  143. package/dist/core/provider-auth.d.ts +154 -0
  144. package/dist/core/provider-auth.js +509 -0
  145. package/dist/core/provider-auth.js.map +1 -0
  146. package/dist/core/provider-availability.d.ts +3 -0
  147. package/dist/core/provider-availability.js +14 -0
  148. package/dist/core/provider-availability.js.map +1 -0
  149. package/dist/core/runner-factory.d.ts +8 -0
  150. package/dist/core/runner-factory.js +25 -0
  151. package/dist/core/runner-factory.js.map +1 -0
  152. package/dist/core/runner-model-catalog.d.ts +29 -0
  153. package/dist/core/runner-model-catalog.js +78 -0
  154. package/dist/core/runner-model-catalog.js.map +1 -0
  155. package/dist/core/secret-redaction.d.ts +37 -0
  156. package/dist/core/secret-redaction.js +115 -0
  157. package/dist/core/secret-redaction.js.map +1 -0
  158. package/dist/core/shell-env.d.ts +28 -0
  159. package/dist/core/shell-env.js +56 -0
  160. package/dist/core/shell-env.js.map +1 -0
  161. package/dist/core/tool-display.d.ts +31 -0
  162. package/dist/core/tool-display.js +179 -0
  163. package/dist/core/tool-display.js.map +1 -0
  164. package/dist/core/ui-events.d.ts +335 -0
  165. package/dist/core/ui-events.js +25 -0
  166. package/dist/core/ui-events.js.map +1 -0
  167. package/dist/core/usage-limit.d.ts +42 -0
  168. package/dist/core/usage-limit.js +209 -0
  169. package/dist/core/usage-limit.js.map +1 -0
  170. package/dist/core/usage.d.ts +11 -0
  171. package/dist/core/usage.js +15 -0
  172. package/dist/core/usage.js.map +1 -0
  173. package/dist/core/v1-text-coalescer.d.ts +36 -0
  174. package/dist/core/v1-text-coalescer.js +72 -0
  175. package/dist/core/v1-text-coalescer.js.map +1 -0
  176. package/dist/git-diff-base.d.ts +85 -0
  177. package/dist/git-diff-base.js +180 -0
  178. package/dist/git-diff-base.js.map +1 -0
  179. package/dist/git-refs.d.ts +11 -0
  180. package/dist/git-refs.js +14 -0
  181. package/dist/git-refs.js.map +1 -0
  182. package/dist/git-worktree.d.ts +161 -0
  183. package/dist/git-worktree.js +508 -0
  184. package/dist/git-worktree.js.map +1 -0
  185. package/dist/handoff.d.ts +62 -0
  186. package/dist/handoff.js +154 -0
  187. package/dist/handoff.js.map +1 -0
  188. package/dist/index.d.ts +2 -0
  189. package/dist/index.js +680 -0
  190. package/dist/index.js.map +1 -0
  191. package/dist/install-as-command.d.ts +40 -0
  192. package/dist/install-as-command.js +52 -0
  193. package/dist/install-as-command.js.map +1 -0
  194. package/dist/pack-check.d.ts +17 -0
  195. package/dist/pack-check.js +27 -0
  196. package/dist/pack-check.js.map +1 -0
  197. package/dist/paths.d.ts +140 -0
  198. package/dist/paths.js +192 -0
  199. package/dist/paths.js.map +1 -0
  200. package/dist/planner.d.ts +27 -0
  201. package/dist/planner.js +268 -0
  202. package/dist/planner.js.map +1 -0
  203. package/dist/release/manifests.d.ts +81 -0
  204. package/dist/release/manifests.js +74 -0
  205. package/dist/release/manifests.js.map +1 -0
  206. package/dist/release/snapshot.d.ts +67 -0
  207. package/dist/release/snapshot.js +97 -0
  208. package/dist/release/snapshot.js.map +1 -0
  209. package/dist/release/stable.d.ts +38 -0
  210. package/dist/release/stable.js +55 -0
  211. package/dist/release/stable.js.map +1 -0
  212. package/dist/runs/agent-tmpdir.d.ts +41 -0
  213. package/dist/runs/agent-tmpdir.js +183 -0
  214. package/dist/runs/agent-tmpdir.js.map +1 -0
  215. package/dist/runs/auto-name.d.ts +75 -0
  216. package/dist/runs/auto-name.js +179 -0
  217. package/dist/runs/auto-name.js.map +1 -0
  218. package/dist/runs/event-history.d.ts +50 -0
  219. package/dist/runs/event-history.js +613 -0
  220. package/dist/runs/event-history.js.map +1 -0
  221. package/dist/runs/retention.d.ts +60 -0
  222. package/dist/runs/retention.js +86 -0
  223. package/dist/runs/retention.js.map +1 -0
  224. package/dist/runs/review-gate.d.ts +18 -0
  225. package/dist/runs/review-gate.js +21 -0
  226. package/dist/runs/review-gate.js.map +1 -0
  227. package/dist/runs/run-index.d.ts +19 -0
  228. package/dist/runs/run-index.js +43 -0
  229. package/dist/runs/run-index.js.map +1 -0
  230. package/dist/runs/store.d.ts +446 -0
  231. package/dist/runs/store.js +1118 -0
  232. package/dist/runs/store.js.map +1 -0
  233. package/dist/runs/task-markers.d.ts +28 -0
  234. package/dist/runs/task-markers.js +74 -0
  235. package/dist/runs/task-markers.js.map +1 -0
  236. package/dist/runs/task-refs.d.ts +25 -0
  237. package/dist/runs/task-refs.js +74 -0
  238. package/dist/runs/task-refs.js.map +1 -0
  239. package/dist/runs/ui-event-sink.d.ts +81 -0
  240. package/dist/runs/ui-event-sink.js +210 -0
  241. package/dist/runs/ui-event-sink.js.map +1 -0
  242. package/dist/server/app-type.d.ts +21 -0
  243. package/dist/server/app-type.js +2 -0
  244. package/dist/server/app-type.js.map +1 -0
  245. package/dist/server/capabilities.d.ts +70 -0
  246. package/dist/server/capabilities.js +152 -0
  247. package/dist/server/capabilities.js.map +1 -0
  248. package/dist/server/checkout.d.ts +128 -0
  249. package/dist/server/checkout.js +296 -0
  250. package/dist/server/checkout.js.map +1 -0
  251. package/dist/server/forge/github.d.ts +513 -0
  252. package/dist/server/forge/github.js +2364 -0
  253. package/dist/server/forge/github.js.map +1 -0
  254. package/dist/server/forge/index.d.ts +40 -0
  255. package/dist/server/forge/index.js +72 -0
  256. package/dist/server/forge/index.js.map +1 -0
  257. package/dist/server/forge/types.d.ts +242 -0
  258. package/dist/server/forge/types.js +2 -0
  259. package/dist/server/forge/types.js.map +1 -0
  260. package/dist/server/fs-browse.d.ts +105 -0
  261. package/dist/server/fs-browse.js +182 -0
  262. package/dist/server/fs-browse.js.map +1 -0
  263. package/dist/server/git-changes.d.ts +213 -0
  264. package/dist/server/git-changes.js +555 -0
  265. package/dist/server/git-changes.js.map +1 -0
  266. package/dist/server/git.d.ts +28 -0
  267. package/dist/server/git.js +112 -0
  268. package/dist/server/git.js.map +1 -0
  269. package/dist/server/github.d.ts +9 -0
  270. package/dist/server/github.js +8 -0
  271. package/dist/server/github.js.map +1 -0
  272. package/dist/server/launch-key.d.ts +7 -0
  273. package/dist/server/launch-key.js +33 -0
  274. package/dist/server/launch-key.js.map +1 -0
  275. package/dist/server/open-in-app.d.ts +66 -0
  276. package/dist/server/open-in-app.js +211 -0
  277. package/dist/server/open-in-app.js.map +1 -0
  278. package/dist/server/open-in-terminal.d.ts +70 -0
  279. package/dist/server/open-in-terminal.js +179 -0
  280. package/dist/server/open-in-terminal.js.map +1 -0
  281. package/dist/server/pr.d.ts +7 -0
  282. package/dist/server/pr.js +7 -0
  283. package/dist/server/pr.js.map +1 -0
  284. package/dist/server/project-context.d.ts +120 -0
  285. package/dist/server/project-context.js +182 -0
  286. package/dist/server/project-context.js.map +1 -0
  287. package/dist/server/provider-action-gate.d.ts +8 -0
  288. package/dist/server/provider-action-gate.js +56 -0
  289. package/dist/server/provider-action-gate.js.map +1 -0
  290. package/dist/server/provider-auth-runtime.d.ts +21 -0
  291. package/dist/server/provider-auth-runtime.js +66 -0
  292. package/dist/server/provider-auth-runtime.js.map +1 -0
  293. package/dist/server/server.d.ts +13138 -0
  294. package/dist/server/server.js +5263 -0
  295. package/dist/server/server.js.map +1 -0
  296. package/dist/server/static-ui.d.ts +49 -0
  297. package/dist/server/static-ui.js +92 -0
  298. package/dist/server/static-ui.js.map +1 -0
  299. package/dist/server/validators.d.ts +97 -0
  300. package/dist/server/validators.js +86 -0
  301. package/dist/server/validators.js.map +1 -0
  302. package/dist/server/ws.d.ts +85 -0
  303. package/dist/server/ws.js +218 -0
  304. package/dist/server/ws.js.map +1 -0
  305. package/dist/server/wsl.d.ts +25 -0
  306. package/dist/server/wsl.js +92 -0
  307. package/dist/server/wsl.js.map +1 -0
  308. package/dist/server-install/engine.d.ts +50 -0
  309. package/dist/server-install/engine.js +324 -0
  310. package/dist/server-install/engine.js.map +1 -0
  311. package/dist/server-install/platforms/macosx-ngrok.d.ts +6 -0
  312. package/dist/server-install/platforms/macosx-ngrok.js +345 -0
  313. package/dist/server-install/platforms/macosx-ngrok.js.map +1 -0
  314. package/dist/server-install/platforms/ubuntu-vps.d.ts +78 -0
  315. package/dist/server-install/platforms/ubuntu-vps.js +1016 -0
  316. package/dist/server-install/platforms/ubuntu-vps.js.map +1 -0
  317. package/dist/server-install/state.d.ts +52 -0
  318. package/dist/server-install/state.js +182 -0
  319. package/dist/server-install/state.js.map +1 -0
  320. package/dist/server-install/steps.d.ts +109 -0
  321. package/dist/server-install/steps.js +334 -0
  322. package/dist/server-install/steps.js.map +1 -0
  323. package/dist/server-install/strategies.d.ts +4 -0
  324. package/dist/server-install/strategies.js +20 -0
  325. package/dist/server-install/strategies.js.map +1 -0
  326. package/dist/server-install/types.d.ts +287 -0
  327. package/dist/server-install/types.js +121 -0
  328. package/dist/server-install/types.js.map +1 -0
  329. package/dist/server-install/ui.d.ts +42 -0
  330. package/dist/server-install/ui.js +130 -0
  331. package/dist/server-install/ui.js.map +1 -0
  332. package/dist/skills-banner.d.ts +22 -0
  333. package/dist/skills-banner.js +41 -0
  334. package/dist/skills-banner.js.map +1 -0
  335. package/dist/skills-remote.d.ts +84 -0
  336. package/dist/skills-remote.js +468 -0
  337. package/dist/skills-remote.js.map +1 -0
  338. package/dist/skills-update.d.ts +88 -0
  339. package/dist/skills-update.js +392 -0
  340. package/dist/skills-update.js.map +1 -0
  341. package/dist/skills.d.ts +82 -0
  342. package/dist/skills.js +251 -0
  343. package/dist/skills.js.map +1 -0
  344. package/dist/todos.d.ts +48 -0
  345. package/dist/todos.js +201 -0
  346. package/dist/todos.js.map +1 -0
  347. package/dist/ui-state.d.ts +26 -0
  348. package/dist/ui-state.js +38 -0
  349. package/dist/ui-state.js.map +1 -0
  350. package/dist/update-check.d.ts +12 -0
  351. package/dist/update-check.js +41 -0
  352. package/dist/update-check.js.map +1 -0
  353. package/dist/workflows/load.d.ts +15 -0
  354. package/dist/workflows/load.js +56 -0
  355. package/dist/workflows/load.js.map +1 -0
  356. package/dist/workflows/run.d.ts +758 -0
  357. package/dist/workflows/run.js +3389 -0
  358. package/dist/workflows/run.js.map +1 -0
  359. package/dist/workflows/types.d.ts +153 -0
  360. package/dist/workflows/types.js +212 -0
  361. package/dist/workflows/types.js.map +1 -0
  362. package/dist/workspace/agent-accounts.d.ts +153 -0
  363. package/dist/workspace/agent-accounts.js +304 -0
  364. package/dist/workspace/agent-accounts.js.map +1 -0
  365. package/dist/workspace/agent-profiles.d.ts +78 -0
  366. package/dist/workspace/agent-profiles.js +115 -0
  367. package/dist/workspace/agent-profiles.js.map +1 -0
  368. package/dist/workspace/config.d.ts +169 -0
  369. package/dist/workspace/config.js +379 -0
  370. package/dist/workspace/config.js.map +1 -0
  371. package/dist/workspace/migrations.d.ts +45 -0
  372. package/dist/workspace/migrations.js +147 -0
  373. package/dist/workspace/migrations.js.map +1 -0
  374. package/dist/workspace/projects-cli.d.ts +25 -0
  375. package/dist/workspace/projects-cli.js +172 -0
  376. package/dist/workspace/projects-cli.js.map +1 -0
  377. package/dist/workspace/projects.d.ts +109 -0
  378. package/dist/workspace/projects.js +250 -0
  379. package/dist/workspace/projects.js.map +1 -0
  380. package/dist/workspace/semaphore.d.ts +179 -0
  381. package/dist/workspace/semaphore.js +195 -0
  382. package/dist/workspace/semaphore.js.map +1 -0
  383. package/dist/workspace/ui-state.d.ts +34 -0
  384. package/dist/workspace/ui-state.js +53 -0
  385. package/dist/workspace/ui-state.js.map +1 -0
  386. package/package.json +70 -0
  387. package/scripts/check-pack.mjs +46 -0
  388. package/scripts/inline-contract.mjs +112 -0
  389. package/scripts/install-as-command.mjs +120 -0
  390. package/scripts/mock-claude.mjs +520 -0
  391. package/scripts/mock-pi-rpc.mjs +83 -0
  392. package/scripts/sync-readme.mjs +20 -0
  393. package/scripts/test-process-usage.mjs +47 -0
  394. package/web/dist/assets/alert-dialog-B4Ofsgv7.js +1 -0
  395. package/web/dist/assets/arrow-down-Dy8dup7j.js +1 -0
  396. package/web/dist/assets/arrow-left-BJaucbhn.js +1 -0
  397. package/web/dist/assets/bundle-mjs-BT31bpU6.js +1 -0
  398. package/web/dist/assets/centered-state-duPW0phQ.js +43 -0
  399. package/web/dist/assets/chevron-right-Be4A5TCS.js +1 -0
  400. package/web/dist/assets/chunk-BO2N2NFS-DE6qKn3r.js +131 -0
  401. package/web/dist/assets/collapsible-DdcNBdSk.js +1 -0
  402. package/web/dist/assets/commit-list-CgvN9vec.js +1 -0
  403. package/web/dist/assets/compare-variants-CQA2nd65.js +1 -0
  404. package/web/dist/assets/core-BCsw8oQw.js +12 -0
  405. package/web/dist/assets/css-BsVw1vtW.js +1 -0
  406. package/web/dist/assets/diff-B6Agp5Hl.js +3 -0
  407. package/web/dist/assets/diff-stat-BoXuGkgq.js +1 -0
  408. package/web/dist/assets/diff-view-CD8XI-fj.js +6 -0
  409. package/web/dist/assets/diff-woXpYk--.js +1 -0
  410. package/web/dist/assets/dropdown-menu-B3SYw-k5.js +1 -0
  411. package/web/dist/assets/editable-title-B-hjp5wl.js +1 -0
  412. package/web/dist/assets/ellipsis-vertical-BYwzw0xl.js +1 -0
  413. package/web/dist/assets/engine-javascript-FQvzRocB.js +141 -0
  414. package/web/dist/assets/file-BRj5eISx.js +1 -0
  415. package/web/dist/assets/folder-z4oT5981.js +1 -0
  416. package/web/dist/assets/git-toolbar-owSEkYld.js +1 -0
  417. package/web/dist/assets/github-Bz2VgRX3.js +1 -0
  418. package/web/dist/assets/go-rLFTqkRN.js +1 -0
  419. package/web/dist/assets/highlighted-body-OFNGDK62-BL-MfFgl.js +1 -0
  420. package/web/dist/assets/highlighter-CdHqIwFr.js +3 -0
  421. package/web/dist/assets/html-BY76lXLH.js +1 -0
  422. package/web/dist/assets/image-preview-h3WFluuy.js +1 -0
  423. package/web/dist/assets/index-BbcQNT92.css +2 -0
  424. package/web/dist/assets/index-EtQQQ6Kj.js +7 -0
  425. package/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  426. package/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  427. package/web/dist/assets/javascript-BgS3c2Ky.js +1 -0
  428. package/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  429. package/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  430. package/web/dist/assets/json-qhed-kSA.js +1 -0
  431. package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
  432. package/web/dist/assets/jsx-Bz0zcwM4.js +1 -0
  433. package/web/dist/assets/lib-BQXq3kEf.js +1 -0
  434. package/web/dist/assets/lib-BxQXEXDF.js +1 -0
  435. package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
  436. package/web/dist/assets/markdown-DqBKYPiB.js +2 -0
  437. package/web/dist/assets/mermaid-GHXKKRXX-C4jxqUUb.js +1 -0
  438. package/web/dist/assets/new-task-form-BdJKRBJX.js +1 -0
  439. package/web/dist/assets/pill-BQfmfpYp.js +1 -0
  440. package/web/dist/assets/project-router-DxgFZY1l.js +1 -0
  441. package/web/dist/assets/prompt-templates-B6m16gq-.js +15 -0
  442. package/web/dist/assets/python-gzcpVVnB.js +1 -0
  443. package/web/dist/assets/react-runtime-CCIEwYL0.js +9 -0
  444. package/web/dist/assets/refresh-cw-mhSpxf2a.js +1 -0
  445. package/web/dist/assets/repo-git-CUNRxR3_.js +1 -0
  446. package/web/dist/assets/rolldown-runtime-QTnfLwEv.js +1 -0
  447. package/web/dist/assets/run-diff-DsmmDVfx.js +3 -0
  448. package/web/dist/assets/run-header-BkhrseLJ.js +1 -0
  449. package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
  450. package/web/dist/assets/search-x-BqDMB2g8.js +1 -0
  451. package/web/dist/assets/shellscript-CLZ0U2zV.js +1 -0
  452. package/web/dist/assets/skill-empty-hint-BWEvTggc.js +1 -0
  453. package/web/dist/assets/skills-9oR_oHse.js +1 -0
  454. package/web/dist/assets/skills-DwIxnnWO.js +1 -0
  455. package/web/dist/assets/sparkles-DIoTQpyx.js +1 -0
  456. package/web/dist/assets/sql-BsFa4tDR.js +1 -0
  457. package/web/dist/assets/square-terminal-Cc7CuQxc.js +1 -0
  458. package/web/dist/assets/tab-link-D1fQgpmO.js +1 -0
  459. package/web/dist/assets/task-changes-BKeLlDpK.js +1 -0
  460. package/web/dist/assets/task-commits-gcEFZIa5.js +1 -0
  461. package/web/dist/assets/task-files-BGAqoXTW.js +2 -0
  462. package/web/dist/assets/task-thread-DT8aUYTS.js +9 -0
  463. package/web/dist/assets/textarea-BOVbfy5C.js +1 -0
  464. package/web/dist/assets/thread-loading-CypW73KD.js +1 -0
  465. package/web/dist/assets/toml-CcmNWLt0.js +1 -0
  466. package/web/dist/assets/trash-2-CJq6LHWn.js +1 -0
  467. package/web/dist/assets/triangle-alert-CjDFvU27.js +1 -0
  468. package/web/dist/assets/tsx-udAQXfEw.js +1 -0
  469. package/web/dist/assets/typescript-bsJCZSQ-.js +1 -0
  470. package/web/dist/assets/upload-CPDZlJeK.js +1 -0
  471. package/web/dist/assets/use-desktop-5JsLmi0a.js +1 -0
  472. package/web/dist/assets/use-submit-shortcut-CHVFevty.js +1 -0
  473. package/web/dist/assets/utils-DiO6zyJd.js +64 -0
  474. package/web/dist/assets/workflows-rQDFzWRt.js +11 -0
  475. package/web/dist/assets/yaml-rwi0_p6S.js +1 -0
  476. package/web/dist/assets/zoomable-image-COWqb11v.js +1 -0
  477. package/web/dist/index.html +80 -0
  478. package/web/dist/open-mercato.svg +11 -0
@@ -0,0 +1,154 @@
1
+ export declare const PROVIDER_IDS: readonly ['claude', 'codex', 'opencode', 'pi'];
2
+ export type ProviderId = (typeof PROVIDER_IDS)[number];
3
+ export type ProviderConnectionState = 'connected' | 'disconnected' | 'not-installed' | 'unknown';
4
+ export interface ProviderStatus {
5
+ provider: ProviderId;
6
+ status: ProviderConnectionState;
7
+ enabled?: boolean;
8
+ hint?: string;
9
+ authFailureId?: string;
10
+ /** Which agent account this row describes (spec 2026-07-29-agent-profiles). Absent on the rows
11
+ * `status()` builds — that route answers for the discovered default only, and stays exactly
12
+ * as wide as it has always been. Stamped in by `profileStatus()`. */
13
+ profileId?: string;
14
+ }
15
+ export interface ProviderStatusResponse {
16
+ providers: ProviderStatus[];
17
+ }
18
+ export interface ProviderCommandResult {
19
+ stdout: string;
20
+ stderr: string;
21
+ exitCode: number | null;
22
+ errorCode?: string;
23
+ timedOut?: boolean;
24
+ }
25
+ export type RunProviderCommand = (executable: string, args: readonly string[], timeoutMs: number,
26
+ /** Extra environment for the probe — how an agent profile's config dir reaches the CLI (spec
27
+ * 2026-07-29-agent-profiles). Optional so every existing caller and the test kit keep their
28
+ * three-argument signature; absent means the default profile, which needs nothing. */
29
+ env?: Record<string, string>) => Promise<ProviderCommandResult>;
30
+ /**
31
+ * The explicit environment lock delegates model and credential configuration
32
+ * to each native coding agent. In that mode Cezar must not second-guess the
33
+ * agent's own credentials through the provider checks introduced by #652.
34
+ *
35
+ * Config-file model locks intentionally do not disable the checks: this bypass
36
+ * is an operator-level process policy and only the exact documented `1` opts in.
37
+ */
38
+ export declare function providerAuthChecksDisabled(env?: NodeJS.ProcessEnv): boolean;
39
+ export declare function isRuntimeProviderAuthFailure(message: string): boolean;
40
+ /** One authoritative runtime authentication incident. The identifier is opaque
41
+ * and stable until the user explicitly acknowledges that exact incident. */
42
+ export interface RuntimeAuthFailureReport {
43
+ status: ProviderStatus & {
44
+ status: 'disconnected';
45
+ authFailureId: string;
46
+ };
47
+ /** True only for the global latch edge, so callers can fan out one coarse
48
+ * status update while every affected task still records its own callout. */
49
+ transitioned: boolean;
50
+ }
51
+ export declare class ProviderAuthService {
52
+ private readonly runCommand;
53
+ private readonly now;
54
+ private readonly platform;
55
+ private readonly createAuthFailureId;
56
+ private readonly runtimeFailures;
57
+ private nextRuntimeFailureGeneration;
58
+ private nextProbeGeneration;
59
+ private completed?;
60
+ private inFlight?;
61
+ /** Per-account probe results, keyed by `profileCacheKey` (spec 2026-07-29-agent-profiles).
62
+ * Separate from `completed` because a second Claude login is a different answer to the same
63
+ * question, and sharing one slot would let whichever probe ran last speak for both. */
64
+ private readonly completedProfiles;
65
+ private readonly inFlightProfiles;
66
+ constructor(options?: {
67
+ runCommand?: RunProviderCommand;
68
+ now?: () => number;
69
+ platform?: NodeJS.Platform;
70
+ createAuthFailureId?: () => string;
71
+ });
72
+ /**
73
+ * Every provider's authentication state — STALE-WHILE-REVALIDATE, the same policy the health
74
+ * snapshot uses.
75
+ *
76
+ * Once anything is known, a reader gets it immediately and an expired cache is refreshed BEHIND
77
+ * the answer instead of in front of it. Awaiting the refresh is what made `GET
78
+ * /providers/status` cost ~0.8s here (and ~3s on a slower box) every time the window lapsed:
79
+ * the endpoint is read by the cockpit on a poll, so "occasionally slow" means "slow in the UI,
80
+ * unpredictably". Only a genuinely cold cache waits, and after the boot warm there isn't one.
81
+ *
82
+ * `refresh: true` still blocks — it is what "Check again", `POST /providers/connect` and the
83
+ * action gate's verify-before-refuse use, and they are asking precisely because they need an
84
+ * answer that is true NOW.
85
+ */
86
+ status(options?: {
87
+ refresh?: boolean;
88
+ }): Promise<ProviderStatusResponse>;
89
+ reportRuntimeAuthFailure(provider: ProviderId): RuntimeAuthFailureReport | null;
90
+ /** Clear only the incident the caller actually observed. A stale retry must
91
+ * never erase a rejection that arrived after the user began recovery. */
92
+ clearRuntimeAuthFailure(provider: ProviderId, authFailureId: string): boolean;
93
+ /**
94
+ * The command that logs `provider` in, as a copyable one-liner.
95
+ *
96
+ * `configDir` points the login at a specific agent account (spec 2026-07-29-agent-profiles) —
97
+ * without it, "Connect" on a second Claude account would sign the user into the FIRST one and
98
+ * report success. Returns `null` when the dir cannot be embedded safely on this platform, and
99
+ * the caller must then refuse rather than fall back to the bare command: a login aimed at the
100
+ * wrong account is the failure this whole path exists to prevent.
101
+ */
102
+ loginCommand(provider: ProviderId, configDir?: string | null): string | null;
103
+ installHint(provider: ProviderId): string;
104
+ private withRuntimeFailures;
105
+ private startFreshProbe;
106
+ /**
107
+ * One NON-default agent account's authentication state (spec 2026-07-29-agent-profiles).
108
+ *
109
+ * Deliberately a separate entry point from `status()`, which keeps answering exactly one row
110
+ * per provider — the discovered default — so `GET /api/v1/providers/status` is byte-identical
111
+ * for anyone with no extra accounts. Per-account rows are carried by the agent-profiles route.
112
+ *
113
+ * Cached on the same asymmetric lifetime as `status()` (`cacheTtlFor`: minutes for a connected
114
+ * answer, a minute for anything else), keyed by `(provider, profileId)` so two Claude accounts never read
115
+ * each other's answer. The runtime-auth latch is deliberately NOT applied: it is a coarse
116
+ * per-provider signal and stamping it onto every account of that provider would mark an
117
+ * untouched account as broken.
118
+ */
119
+ profileStatus(provider: ProviderId, profile: {
120
+ id: string;
121
+ configDir: string | null;
122
+ }): Promise<ProviderStatus>;
123
+ /**
124
+ * Drop a cached per-account answer — used when an account's dir changes under us.
125
+ *
126
+ * TARGETED by default, because this cache is warmed at boot and is meant to survive: clearing
127
+ * every account because ONE was repointed would throw away knowledge that is still true and make
128
+ * the other accounts re-probe. Called with no argument it clears everything, which is what a
129
+ * shutdown or a whole-store reload wants.
130
+ */
131
+ forgetProfileStatus(provider?: ProviderId, profileId?: string): void;
132
+ /**
133
+ * The cached answer for one account, or `undefined` when nothing is known yet — WITHOUT
134
+ * spawning anything.
135
+ *
136
+ * Every probe shells out to an agent CLI, which costs hundreds of milliseconds per provider and
137
+ * per account. A route whose real job is "what exists" must not pay that: `GET /api/v1/health`
138
+ * already established this posture (it serves whatever the cache holds and never pays a `gh`
139
+ * shell-out), and this is the same rule for auth.
140
+ *
141
+ * The peeks deliberately ignore the TTLs below — they answer with the last thing known, however
142
+ * old. The short window exists to stop a stale NEGATIVE from blocking a run, and a peek blocks
143
+ * nothing: it fills in a dot on a settings page that offers Connect and a re-check right beside
144
+ * it. Applying the window here instead made the whole cache expire in five seconds on any machine
145
+ * where a single provider is logged out — which is most of them, since few people are signed into
146
+ * all three — and put the shell-out straight back on the page load this exists to protect.
147
+ * Callers that need a guaranteed-fresh answer call {@link status} or pass `refresh`.
148
+ */
149
+ peekProfileStatus(provider: ProviderId, profileId: string): ProviderStatus | undefined;
150
+ /** The cached default-profile rows, or `undefined` when the probe has never completed. Same
151
+ * no-spawn contract as {@link peekProfileStatus}. */
152
+ peekStatus(): ProviderStatusResponse | undefined;
153
+ private probe;
154
+ }
@@ -0,0 +1,509 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { AGENT_MODELS_LOCKED_ENV } from './agent-model-policy.js';
4
+ import { profileEnv } from './agent-profiles.js';
5
+ import { withEnvPrefix } from './shell-env.js';
6
+ export const PROVIDER_IDS = ['claude', 'codex', 'opencode', 'pi'];
7
+ /**
8
+ * The explicit environment lock delegates model and credential configuration
9
+ * to each native coding agent. In that mode Cezar must not second-guess the
10
+ * agent's own credentials through the provider checks introduced by #652.
11
+ *
12
+ * Config-file model locks intentionally do not disable the checks: this bypass
13
+ * is an operator-level process policy and only the exact documented `1` opts in.
14
+ */
15
+ export function providerAuthChecksDisabled(env = process.env) {
16
+ return env[AGENT_MODELS_LOCKED_ENV] === '1';
17
+ }
18
+ const COMMAND_TIMEOUT_MS = 10_000;
19
+ /**
20
+ * How long a probe result stands before it is re-checked — deliberately ASYMMETRIC.
21
+ *
22
+ * Which login an agent is signed into is operating knowledge: it matters for every run, and it
23
+ * changes only when someone runs `claude auth login`. Re-probing it every few seconds cost a CLI
24
+ * shell-out per provider and per account on every page load, for an answer that had almost
25
+ * certainly not changed. So a CONNECTED answer is kept for minutes.
26
+ *
27
+ * A NOT-CONNECTED answer is re-checked sooner, for ONE reason: display self-healing. If you log in
28
+ * from a terminal, cezar cannot see it happen, so a card that says "disconnected" must eventually
29
+ * find out on its own. The window is a minute rather than seconds because reading is now
30
+ * stale-while-revalidate (see `status`): every expiry costs a background probe, and a cockpit
31
+ * polling this endpoint would turn a five-second window into a spawn every five seconds, forever,
32
+ * on any machine where one provider is logged out — which is most of them.
33
+ *
34
+ * What this window is NOT is a correctness mechanism for starting runs. `provider-action-gate.ts`
35
+ * refuses to start a run against a provider it believes disconnected, and it re-verifies before it
36
+ * refuses (`providerActionError` in `server.ts`) rather than trusting an aging negative. That
37
+ * inversion is what makes a long window safe here: the only reader that must not be wrong pays for
38
+ * its own certainty, on the rare path where it is about to say no.
39
+ *
40
+ * A stale CONNECTED answer needs no window at all: the run starts, and a credential that really has
41
+ * gone bad surfaces as a runtime auth failure, which is latched and overrides this cache on the spot
42
+ * (`withRuntimeFailures`).
43
+ *
44
+ * Anything cezar CAN observe invalidates explicitly instead of waiting for either window: opening a
45
+ * login (`POST /providers/connect`), repointing or removing an account (`forgetProfileStatus`), and
46
+ * a runtime rejection.
47
+ */
48
+ const CONNECTED_TTL_MS = 10 * 60_000;
49
+ const UNSETTLED_TTL_MS = 60_000;
50
+ /** The lifetime for a set of rows: minutes only when EVERY row is connected. A mixed answer takes
51
+ * the short window, because the not-connected row in it is the one that might self-heal.
52
+ *
53
+ * KNOWN COARSENESS: the window applies to the whole three-provider response, so one logged-out
54
+ * provider drags the two connected ones into re-probing with it. That is wasted work rather than a
55
+ * wrong answer, and it is now paid in the background; fixing it properly means per-provider
56
+ * timestamps and merging partial probe results. */
57
+ function cacheTtlFor(rows) {
58
+ return rows.every((row) => row.status === 'connected') ? CONNECTED_TTL_MS : UNSETTLED_TTL_MS;
59
+ }
60
+ const UNKNOWN_HINT = 'Authentication could not be verified. Try again.';
61
+ const TIMEOUT_HINT = 'Authentication check timed out. Try again.';
62
+ const RUNTIME_AUTH_HINT = 'Authentication was rejected during a run. Reconnect, then try again.';
63
+ const ANSI_SEQUENCE = /\u001B\[[0-?]*[ -/]*[@-~]/g;
64
+ const RUNTIME_AUTH_FAILURE_PATTERNS = [
65
+ /\b(?:failed to authenticate|authentication failed|unauthenticated|unauthorized)\b/i,
66
+ /\bproviderautherror\b/i,
67
+ /\b(?:oauth|access|refresh)?\s*token\b.{0,80}\b(?:revoked|expired|invalid)\b/i,
68
+ /\b(?:revoked|expired|invalid)\b.{0,80}\b(?:oauth|access|refresh)?\s*token\b/i,
69
+ /\b(?:oauth|token|credential|unauthorized|unauthenticated)\b.{0,80}\b401\b/i,
70
+ /\b401\b.{0,80}\b(?:oauth|token|credential|unauthorized|unauthenticated)\b/i,
71
+ ];
72
+ const RUNTIME_API_KEY_FAILURE_PATTERNS = [
73
+ // Vendor-shaped errors can carry a process prefix before the actual
74
+ // authentication error, so anchor on that explicit error label.
75
+ /\b(?:api|authentication|auth)\s*error\b\s*[:=-]\s*(?:(?:http\s+)?401\b[\s:=-]*)?(?:(?:revoked|expired|invalid)\s+(?:api[-\s]?key|x-api-key)|(?:api[-\s]?key|x-api-key)\s*(?:(?:is|was|has been)\s+|[:=-]\s*)?(?:revoked|expired|invalid))\b/i,
76
+ // Otherwise require the credential rejection to be the complete line,
77
+ // optionally introduced by a generic error label or 401 status. This keeps
78
+ // implementation notes such as "coverage for invalid API key handling"
79
+ // from looking like live authentication failures.
80
+ /(?:^|\r?\n)\s*(?:error\s*[:=-]\s*)?(?:(?:http\s+)?401\b[\s:=-]*)?(?:(?:revoked|expired|invalid)\s+(?:api[-\s]?key|x-api-key)|(?:api[-\s]?key|x-api-key)\s+(?:(?:is|was|has been)\s+)?(?:revoked|expired|invalid))\s*(?:[.!]|$)/im,
81
+ ];
82
+ export function isRuntimeProviderAuthFailure(message) {
83
+ return [...RUNTIME_AUTH_FAILURE_PATTERNS, ...RUNTIME_API_KEY_FAILURE_PATTERNS]
84
+ .some((pattern) => pattern.test(message));
85
+ }
86
+ function normalizedOutput(stdout) {
87
+ return stdout.replace(ANSI_SEQUENCE, '').trim().toLowerCase();
88
+ }
89
+ function normalizedLines(...outputs) {
90
+ return outputs.flatMap((output) => normalizedOutput(output).split(/\r?\n/))
91
+ .map((line) => line.trim())
92
+ .filter(Boolean);
93
+ }
94
+ function parseClaudeStatus(result) {
95
+ try {
96
+ const value = JSON.parse(result.stdout);
97
+ if (value.loggedIn === true && result.exitCode === 0)
98
+ return 'connected';
99
+ if (value.loggedIn === false && result.exitCode === 1)
100
+ return 'disconnected';
101
+ return null;
102
+ }
103
+ catch {
104
+ return null;
105
+ }
106
+ }
107
+ function parseCodexStatus(result) {
108
+ const answers = normalizedLines(result.stdout, result.stderr)
109
+ .map((line) => {
110
+ if (line === 'logged in using chatgpt'
111
+ || line === 'logged in using an api key'
112
+ || line === 'logged in using agent identity'
113
+ || line === 'logged in using access token'
114
+ || line === 'logged in using personal access token'
115
+ || line === 'logged in using amazon bedrock api key'
116
+ || /^logged in using an api key - (?:\*{3}|\S{8}\*{3}\S{5})$/.test(line)) {
117
+ return 'connected';
118
+ }
119
+ if (line === 'not logged in' || line === 'run codex login to authenticate') {
120
+ return 'disconnected';
121
+ }
122
+ return null;
123
+ })
124
+ .filter((answer) => answer !== null);
125
+ if (answers.length !== 1)
126
+ return null;
127
+ if (answers[0] === 'connected' && result.exitCode === 0)
128
+ return 'connected';
129
+ if (answers[0] === 'disconnected' && result.exitCode === 1)
130
+ return 'disconnected';
131
+ return null;
132
+ }
133
+ function parseOpenCodeStatus(result) {
134
+ if (result.exitCode !== 0)
135
+ return null;
136
+ const lines = normalizedLines(result.stdout);
137
+ const storedSummaries = lines
138
+ .map((line) => line.match(/^[^a-z0-9]*(\d+)\s+credentials?$/)?.[1])
139
+ .filter((count) => count !== undefined);
140
+ if (storedSummaries.length !== 1)
141
+ return null;
142
+ const storedCount = Number(storedSummaries[0]);
143
+ if (!Number.isSafeInteger(storedCount))
144
+ return null;
145
+ const environmentSummaries = lines
146
+ .map((line) => line.match(/^[^a-z0-9]*(\d+)\s+environment\s+variables?$/)?.[1])
147
+ .filter((count) => count !== undefined);
148
+ const hasEnvironmentBlock = lines.some((line) => /^[^a-z0-9]*environment$/.test(line));
149
+ if (environmentSummaries.length > 1)
150
+ return null;
151
+ if (hasEnvironmentBlock !== (environmentSummaries.length === 1))
152
+ return null;
153
+ const environmentCount = environmentSummaries.length === 1
154
+ ? Number(environmentSummaries[0])
155
+ : 0;
156
+ if (!Number.isSafeInteger(environmentCount))
157
+ return null;
158
+ return storedCount > 0 || environmentCount > 0 ? 'connected' : 'disconnected';
159
+ }
160
+ function parsePiStatus(result) {
161
+ if (result.exitCode !== 0)
162
+ return null;
163
+ const lines = normalizedLines(result.stdout);
164
+ if (lines.some((line) => /^provider\s+model\s+context\s+max-out\s+thinking\s+images$/.test(line))) {
165
+ return 'connected';
166
+ }
167
+ if (lines.some((line) => line.includes('no models available'))
168
+ && lines.some((line) => line.includes('/login'))) {
169
+ return 'disconnected';
170
+ }
171
+ return null;
172
+ }
173
+ const DESCRIPTORS = [
174
+ {
175
+ id: 'claude',
176
+ executable: () => process.env.CEZ_CLAUDE_BIN ?? 'claude',
177
+ statusArgs: ['auth', 'status', '--json'],
178
+ loginArgs: ['auth', 'login'],
179
+ installHint: 'Install Claude Code, then run `claude auth login`.',
180
+ parse: parseClaudeStatus,
181
+ },
182
+ {
183
+ id: 'codex',
184
+ executable: () => process.env.CEZ_CODEX_BIN ?? 'codex',
185
+ statusArgs: ['login', 'status'],
186
+ loginArgs: ['login'],
187
+ installHint: 'Install the Codex CLI, then run `codex login`.',
188
+ parse: parseCodexStatus,
189
+ },
190
+ {
191
+ id: 'opencode',
192
+ executable: () => process.env.CEZ_OPENCODE_BIN ?? 'opencode',
193
+ statusArgs: ['auth', 'list'],
194
+ loginArgs: ['auth', 'login'],
195
+ installHint: 'Install OpenCode, then run `opencode auth login`.',
196
+ parse: parseOpenCodeStatus,
197
+ },
198
+ {
199
+ id: 'pi',
200
+ executable: () => process.env.CEZ_PI_BIN ?? 'pi',
201
+ statusArgs: ['--list-models'],
202
+ loginArgs: ['/login'],
203
+ installHint: 'Install pi, then run `pi /login`.',
204
+ parse: parsePiStatus,
205
+ },
206
+ ];
207
+ function defaultRunProviderCommand(executable, args, timeoutMs, env) {
208
+ return new Promise((resolve) => {
209
+ execFile(executable, args, {
210
+ timeout: timeoutMs,
211
+ windowsHide: true,
212
+ maxBuffer: 256 * 1024,
213
+ // Inherit, then override: an auth probe is a short read-only CLI call, not a spawned
214
+ // agent, so it does not go through `buildChildEnv`'s allowlist — the CLI still needs the
215
+ // host's PATH and HOME to run at all. `env` is only ever a profile's config-dir variable.
216
+ ...(env && Object.keys(env).length > 0 ? { env: { ...process.env, ...env } } : {}),
217
+ }, (error, stdout, stderr) => {
218
+ const commandError = error;
219
+ const code = commandError?.code;
220
+ resolve({
221
+ stdout: String(stdout),
222
+ stderr: String(stderr),
223
+ exitCode: typeof code === 'number' ? code : error ? null : 0,
224
+ errorCode: typeof code === 'string' ? code : undefined,
225
+ timedOut: commandError?.code === 'ETIMEDOUT'
226
+ || (commandError?.killed === true && commandError.signal === 'SIGTERM'),
227
+ });
228
+ });
229
+ });
230
+ }
231
+ function quoteExecutable(executable, platform) {
232
+ if (platform === 'win32') {
233
+ return `"${executable.replace(/[%&!"]/g, '^$&')}"`;
234
+ }
235
+ return `'${executable.replaceAll("'", "'\\''")}'`;
236
+ }
237
+ /** The per-account cache key. ONE definition: a probe that wrote under a different spelling than
238
+ * a peek reads would silently make every peek a miss, and every page load pay for a CLI spawn. */
239
+ function profileCacheKey(provider, profileId) {
240
+ return `${provider}\u0000${profileId}`;
241
+ }
242
+ function descriptorFor(provider) {
243
+ const descriptor = DESCRIPTORS.find(({ id }) => id === provider);
244
+ if (!descriptor)
245
+ throw new Error(`Unknown provider: ${provider}`);
246
+ return descriptor;
247
+ }
248
+ export class ProviderAuthService {
249
+ runCommand;
250
+ now;
251
+ platform;
252
+ createAuthFailureId;
253
+ runtimeFailures = new Map();
254
+ nextRuntimeFailureGeneration = 0;
255
+ nextProbeGeneration = 0;
256
+ completed;
257
+ inFlight;
258
+ /** Per-account probe results, keyed by `profileCacheKey` (spec 2026-07-29-agent-profiles).
259
+ * Separate from `completed` because a second Claude login is a different answer to the same
260
+ * question, and sharing one slot would let whichever probe ran last speak for both. */
261
+ completedProfiles = new Map();
262
+ inFlightProfiles = new Map();
263
+ constructor(options) {
264
+ this.runCommand = options?.runCommand ?? defaultRunProviderCommand;
265
+ this.now = options?.now ?? Date.now;
266
+ this.platform = options?.platform ?? process.platform;
267
+ this.createAuthFailureId = options?.createAuthFailureId ?? randomUUID;
268
+ }
269
+ /**
270
+ * Every provider's authentication state — STALE-WHILE-REVALIDATE, the same policy the health
271
+ * snapshot uses.
272
+ *
273
+ * Once anything is known, a reader gets it immediately and an expired cache is refreshed BEHIND
274
+ * the answer instead of in front of it. Awaiting the refresh is what made `GET
275
+ * /providers/status` cost ~0.8s here (and ~3s on a slower box) every time the window lapsed:
276
+ * the endpoint is read by the cockpit on a poll, so "occasionally slow" means "slow in the UI,
277
+ * unpredictably". Only a genuinely cold cache waits, and after the boot warm there isn't one.
278
+ *
279
+ * `refresh: true` still blocks — it is what "Check again", `POST /providers/connect` and the
280
+ * action gate's verify-before-refuse use, and they are asking precisely because they need an
281
+ * answer that is true NOW.
282
+ */
283
+ status(options) {
284
+ if (process.env.CEZ_DRY_RUN === '1' || providerAuthChecksDisabled()) {
285
+ return Promise.resolve({
286
+ providers: PROVIDER_IDS.map((provider) => ({ provider, status: 'connected' })),
287
+ });
288
+ }
289
+ if (options?.refresh) {
290
+ // Joining a probe already running satisfies "true now" and preserves the in-flight identity
291
+ // contract (one shared promise for concurrent callers).
292
+ return this.inFlight ? this.inFlight.visible : this.startFreshProbe().visible;
293
+ }
294
+ if (this.completed) {
295
+ // Checked BEFORE `inFlight` on purpose: a reader arriving during a background revalidation
296
+ // must be served from cache, not attached to the probe it was meant to avoid.
297
+ if (this.now() - this.completed.timestamp >= cacheTtlFor(this.completed.response.providers)) {
298
+ if (!this.inFlight)
299
+ void this.startFreshProbe().raw.catch(() => { });
300
+ }
301
+ return Promise.resolve(this.withRuntimeFailures(this.completed.response));
302
+ }
303
+ if (this.inFlight)
304
+ return this.inFlight.visible;
305
+ return this.startFreshProbe().visible;
306
+ }
307
+ reportRuntimeAuthFailure(provider) {
308
+ if (process.env.CEZ_DRY_RUN === '1' || providerAuthChecksDisabled())
309
+ return null;
310
+ const current = this.runtimeFailures.get(provider);
311
+ const failure = {
312
+ generation: ++this.nextRuntimeFailureGeneration,
313
+ authFailureId: current?.authFailureId ?? this.createAuthFailureId(),
314
+ };
315
+ this.runtimeFailures.set(provider, failure);
316
+ return {
317
+ status: {
318
+ provider,
319
+ status: 'disconnected',
320
+ hint: RUNTIME_AUTH_HINT,
321
+ authFailureId: failure.authFailureId,
322
+ },
323
+ transitioned: current === undefined,
324
+ };
325
+ }
326
+ /** Clear only the incident the caller actually observed. A stale retry must
327
+ * never erase a rejection that arrived after the user began recovery. */
328
+ clearRuntimeAuthFailure(provider, authFailureId) {
329
+ const current = this.runtimeFailures.get(provider);
330
+ if (!current || current.authFailureId !== authFailureId)
331
+ return false;
332
+ this.runtimeFailures.delete(provider);
333
+ return true;
334
+ }
335
+ /**
336
+ * The command that logs `provider` in, as a copyable one-liner.
337
+ *
338
+ * `configDir` points the login at a specific agent account (spec 2026-07-29-agent-profiles) —
339
+ * without it, "Connect" on a second Claude account would sign the user into the FIRST one and
340
+ * report success. Returns `null` when the dir cannot be embedded safely on this platform, and
341
+ * the caller must then refuse rather than fall back to the bare command: a login aimed at the
342
+ * wrong account is the failure this whole path exists to prevent.
343
+ */
344
+ loginCommand(provider, configDir) {
345
+ const descriptor = descriptorFor(provider);
346
+ const command = [quoteExecutable(descriptor.executable(), this.platform), ...descriptor.loginArgs].join(' ');
347
+ const env = configDir ? profileEnv(provider, configDir) : {};
348
+ return withEnvPrefix(command, env, this.platform);
349
+ }
350
+ installHint(provider) {
351
+ return descriptorFor(provider).installHint;
352
+ }
353
+ withRuntimeFailures(response) {
354
+ if (this.runtimeFailures.size === 0)
355
+ return response;
356
+ return {
357
+ providers: response.providers.map((row) => {
358
+ const failure = this.runtimeFailures.get(row.provider);
359
+ return failure
360
+ ? {
361
+ provider: row.provider,
362
+ status: 'disconnected',
363
+ hint: RUNTIME_AUTH_HINT,
364
+ authFailureId: failure.authFailureId,
365
+ }
366
+ : row;
367
+ }),
368
+ };
369
+ }
370
+ startFreshProbe() {
371
+ const generation = ++this.nextProbeGeneration;
372
+ const raw = Promise.all(DESCRIPTORS.map((descriptor) => this.probe(descriptor)))
373
+ .then((providers) => {
374
+ const response = { providers };
375
+ if (!this.completed || generation >= this.completed.generation) {
376
+ this.completed = { response, timestamp: this.now(), generation };
377
+ }
378
+ return response;
379
+ });
380
+ // One derived visible promise per raw probe preserves the historical
381
+ // in-flight identity contract while still consulting the current latch
382
+ // only after the async vendor commands resolve.
383
+ const probe = {
384
+ raw,
385
+ visible: raw.then((response) => this.withRuntimeFailures(response)),
386
+ };
387
+ this.inFlight = probe;
388
+ void raw.finally(() => {
389
+ if (this.inFlight === probe)
390
+ this.inFlight = undefined;
391
+ });
392
+ return probe;
393
+ }
394
+ /**
395
+ * One NON-default agent account's authentication state (spec 2026-07-29-agent-profiles).
396
+ *
397
+ * Deliberately a separate entry point from `status()`, which keeps answering exactly one row
398
+ * per provider — the discovered default — so `GET /api/v1/providers/status` is byte-identical
399
+ * for anyone with no extra accounts. Per-account rows are carried by the agent-profiles route.
400
+ *
401
+ * Cached on the same asymmetric lifetime as `status()` (`cacheTtlFor`: minutes for a connected
402
+ * answer, a minute for anything else), keyed by `(provider, profileId)` so two Claude accounts never read
403
+ * each other's answer. The runtime-auth latch is deliberately NOT applied: it is a coarse
404
+ * per-provider signal and stamping it onto every account of that provider would mark an
405
+ * untouched account as broken.
406
+ */
407
+ async profileStatus(provider, profile) {
408
+ if (process.env.CEZ_DRY_RUN === '1') {
409
+ return { provider, status: 'connected', profileId: profile.id };
410
+ }
411
+ const key = profileCacheKey(provider, profile.id);
412
+ const cached = this.completedProfiles.get(key);
413
+ if (cached && this.now() - cached.timestamp < cacheTtlFor([cached.status]))
414
+ return cached.status;
415
+ const pending = this.inFlightProfiles.get(key);
416
+ if (pending)
417
+ return pending;
418
+ const probe = this.probe(descriptorFor(provider), profile.configDir)
419
+ .then((status) => {
420
+ const stamped = { ...status, profileId: profile.id };
421
+ this.completedProfiles.set(key, { status: stamped, timestamp: this.now() });
422
+ return stamped;
423
+ })
424
+ .finally(() => {
425
+ if (this.inFlightProfiles.get(key) === probe)
426
+ this.inFlightProfiles.delete(key);
427
+ });
428
+ this.inFlightProfiles.set(key, probe);
429
+ return probe;
430
+ }
431
+ /**
432
+ * Drop a cached per-account answer — used when an account's dir changes under us.
433
+ *
434
+ * TARGETED by default, because this cache is warmed at boot and is meant to survive: clearing
435
+ * every account because ONE was repointed would throw away knowledge that is still true and make
436
+ * the other accounts re-probe. Called with no argument it clears everything, which is what a
437
+ * shutdown or a whole-store reload wants.
438
+ */
439
+ forgetProfileStatus(provider, profileId) {
440
+ if (provider === undefined || profileId === undefined) {
441
+ this.completedProfiles.clear();
442
+ return;
443
+ }
444
+ this.completedProfiles.delete(profileCacheKey(provider, profileId));
445
+ }
446
+ /**
447
+ * The cached answer for one account, or `undefined` when nothing is known yet — WITHOUT
448
+ * spawning anything.
449
+ *
450
+ * Every probe shells out to an agent CLI, which costs hundreds of milliseconds per provider and
451
+ * per account. A route whose real job is "what exists" must not pay that: `GET /api/v1/health`
452
+ * already established this posture (it serves whatever the cache holds and never pays a `gh`
453
+ * shell-out), and this is the same rule for auth.
454
+ *
455
+ * The peeks deliberately ignore the TTLs below — they answer with the last thing known, however
456
+ * old. The short window exists to stop a stale NEGATIVE from blocking a run, and a peek blocks
457
+ * nothing: it fills in a dot on a settings page that offers Connect and a re-check right beside
458
+ * it. Applying the window here instead made the whole cache expire in five seconds on any machine
459
+ * where a single provider is logged out — which is most of them, since few people are signed into
460
+ * all three — and put the shell-out straight back on the page load this exists to protect.
461
+ * Callers that need a guaranteed-fresh answer call {@link status} or pass `refresh`.
462
+ */
463
+ peekProfileStatus(provider, profileId) {
464
+ if (process.env.CEZ_DRY_RUN === '1') {
465
+ return { provider, status: 'connected', profileId };
466
+ }
467
+ return this.completedProfiles.get(profileCacheKey(provider, profileId))?.status;
468
+ }
469
+ /** The cached default-profile rows, or `undefined` when the probe has never completed. Same
470
+ * no-spawn contract as {@link peekProfileStatus}. */
471
+ peekStatus() {
472
+ if (process.env.CEZ_DRY_RUN === '1') {
473
+ return { providers: PROVIDER_IDS.map((provider) => ({ provider, status: 'connected' })) };
474
+ }
475
+ if (!this.completed)
476
+ return undefined;
477
+ return this.withRuntimeFailures(this.completed.response);
478
+ }
479
+ async probe(descriptor, configDir) {
480
+ let result;
481
+ // The default profile is probed with the SAME three-argument call it always was — no
482
+ // trailing `undefined`. `runCommand` is an injected seam, and handing every existing
483
+ // implementation an extra argument it never asked for would be a change in the zero-config
484
+ // path for no gain.
485
+ const env = configDir ? profileEnv(descriptor.id, configDir) : undefined;
486
+ try {
487
+ result = await (env === undefined
488
+ ? this.runCommand(descriptor.executable(), descriptor.statusArgs, COMMAND_TIMEOUT_MS)
489
+ : this.runCommand(descriptor.executable(), descriptor.statusArgs, COMMAND_TIMEOUT_MS, env));
490
+ }
491
+ catch {
492
+ return { provider: descriptor.id, status: 'unknown', hint: UNKNOWN_HINT };
493
+ }
494
+ if (result.errorCode === 'ENOENT') {
495
+ return { provider: descriptor.id, status: 'not-installed', hint: descriptor.installHint };
496
+ }
497
+ if (result.timedOut) {
498
+ return { provider: descriptor.id, status: 'unknown', hint: TIMEOUT_HINT };
499
+ }
500
+ if (result.errorCode) {
501
+ return { provider: descriptor.id, status: 'unknown', hint: UNKNOWN_HINT };
502
+ }
503
+ const status = descriptor.parse(result);
504
+ if (status !== null)
505
+ return { provider: descriptor.id, status };
506
+ return { provider: descriptor.id, status: 'unknown', hint: UNKNOWN_HINT };
507
+ }
508
+ }
509
+ //# sourceMappingURL=provider-auth.js.map