toolroll 0.5.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 (626) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1113 -0
  3. package/THIRD_PARTY_NOTICES.md +449 -0
  4. package/dist/accent-colors.d.ts +48 -0
  5. package/dist/accent-colors.js +122 -0
  6. package/dist/action-ledger.d.ts +26 -0
  7. package/dist/action-ledger.js +75 -0
  8. package/dist/agent-fence.d.ts +42 -0
  9. package/dist/agent-fence.js +183 -0
  10. package/dist/agentconfig.d.ts +216 -0
  11. package/dist/agentconfig.js +454 -0
  12. package/dist/api-tokens.d.ts +16 -0
  13. package/dist/api-tokens.js +27 -0
  14. package/dist/approval-policy.d.ts +69 -0
  15. package/dist/approval-policy.js +137 -0
  16. package/dist/approval-rules-ui.d.ts +25 -0
  17. package/dist/approval-rules-ui.js +39 -0
  18. package/dist/assignment-adapters.d.ts +180 -0
  19. package/dist/assignment-adapters.js +239 -0
  20. package/dist/assignment-brief.d.ts +71 -0
  21. package/dist/assignment-brief.js +129 -0
  22. package/dist/assignment-delivery.d.ts +56 -0
  23. package/dist/assignment-delivery.js +160 -0
  24. package/dist/assignment-presentation.d.ts +26 -0
  25. package/dist/assignment-presentation.js +80 -0
  26. package/dist/assignment-status.d.ts +62 -0
  27. package/dist/assignment-status.js +152 -0
  28. package/dist/assignment-ui.d.ts +71 -0
  29. package/dist/assignment-ui.js +103 -0
  30. package/dist/assignment.d.ts +222 -0
  31. package/dist/assignment.js +399 -0
  32. package/dist/attest.d.ts +56 -0
  33. package/dist/attest.js +153 -0
  34. package/dist/backend.d.ts +97 -0
  35. package/dist/backend.js +166 -0
  36. package/dist/backup-ui.d.ts +22 -0
  37. package/dist/backup-ui.js +59 -0
  38. package/dist/backup.d.ts +84 -0
  39. package/dist/backup.js +421 -0
  40. package/dist/beads.d.ts +34 -0
  41. package/dist/beads.js +135 -0
  42. package/dist/bin.d.ts +2 -0
  43. package/dist/bin.js +22 -0
  44. package/dist/board.d.ts +150 -0
  45. package/dist/board.js +210 -0
  46. package/dist/boot-identity.d.ts +63 -0
  47. package/dist/boot-identity.js +99 -0
  48. package/dist/browser/THIRD_PARTY_NOTICES.txt +2295 -0
  49. package/dist/browser/workspace.css +4 -0
  50. package/dist/browser/workspace.js +225 -0
  51. package/dist/browser-crew.d.ts +11 -0
  52. package/dist/browser-crew.js +50 -0
  53. package/dist/browser-shell.d.ts +8 -0
  54. package/dist/browser-shell.js +60 -0
  55. package/dist/browser-workspace.d.ts +780 -0
  56. package/dist/browser-workspace.js +47 -0
  57. package/dist/budget-alerts.d.ts +19 -0
  58. package/dist/budget-alerts.js +46 -0
  59. package/dist/builder.d.ts +370 -0
  60. package/dist/builder.js +3262 -0
  61. package/dist/capscan.d.ts +35 -0
  62. package/dist/capscan.js +113 -0
  63. package/dist/chat-acceptance.d.ts +71 -0
  64. package/dist/chat-acceptance.js +120 -0
  65. package/dist/chat-actions.d.ts +265 -0
  66. package/dist/chat-actions.js +1273 -0
  67. package/dist/chat-channel.d.ts +109 -0
  68. package/dist/chat-channel.js +652 -0
  69. package/dist/chat-continuity.d.ts +32 -0
  70. package/dist/chat-continuity.js +317 -0
  71. package/dist/chat-controls.d.ts +113 -0
  72. package/dist/chat-controls.js +53 -0
  73. package/dist/chat-delivery-state.d.ts +159 -0
  74. package/dist/chat-delivery-state.js +309 -0
  75. package/dist/chat-delivery.d.ts +38 -0
  76. package/dist/chat-delivery.js +693 -0
  77. package/dist/chat-display.d.ts +1 -0
  78. package/dist/chat-display.js +18 -0
  79. package/dist/chat-evidence.d.ts +123 -0
  80. package/dist/chat-evidence.js +207 -0
  81. package/dist/chat-flow.d.ts +44 -0
  82. package/dist/chat-flow.js +215 -0
  83. package/dist/chat-inbox.d.ts +57 -0
  84. package/dist/chat-inbox.js +123 -0
  85. package/dist/chat-polish.d.ts +16 -0
  86. package/dist/chat-polish.js +135 -0
  87. package/dist/chat-review.d.ts +46 -0
  88. package/dist/chat-review.js +98 -0
  89. package/dist/chat-rooms.d.ts +123 -0
  90. package/dist/chat-rooms.js +216 -0
  91. package/dist/chat-task-actions.d.ts +44 -0
  92. package/dist/chat-task-actions.js +79 -0
  93. package/dist/check-progress.d.ts +51 -0
  94. package/dist/check-progress.js +290 -0
  95. package/dist/child-database.d.ts +12 -0
  96. package/dist/child-database.js +30 -0
  97. package/dist/claim.d.ts +688 -0
  98. package/dist/claim.js +1740 -0
  99. package/dist/cli.d.ts +137 -0
  100. package/dist/cli.js +1461 -0
  101. package/dist/codex-limits.d.ts +15 -0
  102. package/dist/codex-limits.js +145 -0
  103. package/dist/coding-context.d.ts +55 -0
  104. package/dist/coding-context.js +92 -0
  105. package/dist/coding-handoff.d.ts +57 -0
  106. package/dist/coding-handoff.js +277 -0
  107. package/dist/coding-provider.d.ts +72 -0
  108. package/dist/coding-provider.js +424 -0
  109. package/dist/coding-shipping-ui.d.ts +4 -0
  110. package/dist/coding-shipping-ui.js +12 -0
  111. package/dist/coding-types.d.ts +62 -0
  112. package/dist/coding-types.js +1 -0
  113. package/dist/coding-ui.d.ts +17 -0
  114. package/dist/coding-ui.js +364 -0
  115. package/dist/coding-update.d.ts +15 -0
  116. package/dist/coding-update.js +149 -0
  117. package/dist/coding-workspace.d.ts +124 -0
  118. package/dist/coding-workspace.js +768 -0
  119. package/dist/container-state.d.ts +5 -0
  120. package/dist/container-state.js +62 -0
  121. package/dist/containment.d.ts +197 -0
  122. package/dist/containment.js +559 -0
  123. package/dist/contest.d.ts +318 -0
  124. package/dist/contest.js +753 -0
  125. package/dist/control-setup.d.ts +35 -0
  126. package/dist/control-setup.js +40 -0
  127. package/dist/control-ui.d.ts +29 -0
  128. package/dist/control-ui.js +53 -0
  129. package/dist/controller-service.d.ts +1 -0
  130. package/dist/controller-service.js +19 -0
  131. package/dist/controller-supervisor.d.ts +30 -0
  132. package/dist/controller-supervisor.js +104 -0
  133. package/dist/converse.d.ts +304 -0
  134. package/dist/converse.js +849 -0
  135. package/dist/coordinator-proposals.d.ts +29 -0
  136. package/dist/coordinator-proposals.js +137 -0
  137. package/dist/coordinator.d.ts +186 -0
  138. package/dist/coordinator.js +447 -0
  139. package/dist/credentials-ui.d.ts +25 -0
  140. package/dist/credentials-ui.js +48 -0
  141. package/dist/daemon.d.ts +209 -0
  142. package/dist/daemon.js +604 -0
  143. package/dist/decision.d.ts +120 -0
  144. package/dist/decision.js +388 -0
  145. package/dist/demo.d.ts +55 -0
  146. package/dist/demo.js +992 -0
  147. package/dist/desktop-access.d.ts +28 -0
  148. package/dist/desktop-access.js +88 -0
  149. package/dist/desktop-bundle.d.ts +16 -0
  150. package/dist/desktop-bundle.js +74 -0
  151. package/dist/desktop-host.d.ts +54 -0
  152. package/dist/desktop-host.js +508 -0
  153. package/dist/desktop-update-gate.d.ts +12 -0
  154. package/dist/desktop-update-gate.js +91 -0
  155. package/dist/desktop-update-recovery.d.ts +14 -0
  156. package/dist/desktop-update-recovery.js +243 -0
  157. package/dist/desktop-update.d.ts +110 -0
  158. package/dist/desktop-update.js +740 -0
  159. package/dist/discord-api.d.ts +20 -0
  160. package/dist/discord-api.js +138 -0
  161. package/dist/discord-chat.d.ts +16 -0
  162. package/dist/discord-chat.js +381 -0
  163. package/dist/discord-settings.d.ts +7 -0
  164. package/dist/discord-settings.js +75 -0
  165. package/dist/discord.d.ts +10 -0
  166. package/dist/discord.js +169 -0
  167. package/dist/discover.d.ts +75 -0
  168. package/dist/discover.js +150 -0
  169. package/dist/dispatch.d.ts +100 -0
  170. package/dist/dispatch.js +311 -0
  171. package/dist/dispose.d.ts +161 -0
  172. package/dist/dispose.js +803 -0
  173. package/dist/email-settings.d.ts +34 -0
  174. package/dist/email-settings.js +50 -0
  175. package/dist/envelope.d.ts +47 -0
  176. package/dist/envelope.js +105 -0
  177. package/dist/evidence-pack.d.ts +185 -0
  178. package/dist/evidence-pack.js +258 -0
  179. package/dist/evidence.d.ts +345 -0
  180. package/dist/evidence.js +782 -0
  181. package/dist/exec.d.ts +285 -0
  182. package/dist/exec.js +1841 -0
  183. package/dist/exhaustion.d.ts +85 -0
  184. package/dist/exhaustion.js +141 -0
  185. package/dist/export-ui.d.ts +4 -0
  186. package/dist/export-ui.js +17 -0
  187. package/dist/export.d.ts +48 -0
  188. package/dist/export.js +305 -0
  189. package/dist/flow-actions.d.ts +77 -0
  190. package/dist/flow-actions.js +203 -0
  191. package/dist/flow-code.d.ts +50 -0
  192. package/dist/flow-code.js +159 -0
  193. package/dist/flow-draft.d.ts +38 -0
  194. package/dist/flow-draft.js +80 -0
  195. package/dist/flow-engine.d.ts +66 -0
  196. package/dist/flow-engine.js +416 -0
  197. package/dist/flow-insights.d.ts +95 -0
  198. package/dist/flow-insights.js +149 -0
  199. package/dist/flow-live.d.ts +24 -0
  200. package/dist/flow-live.js +150 -0
  201. package/dist/flow-people.d.ts +24 -0
  202. package/dist/flow-people.js +91 -0
  203. package/dist/flow-replies.d.ts +48 -0
  204. package/dist/flow-replies.js +113 -0
  205. package/dist/flow-scripts.d.ts +38 -0
  206. package/dist/flow-scripts.js +73 -0
  207. package/dist/flow-secrets.d.ts +13 -0
  208. package/dist/flow-secrets.js +45 -0
  209. package/dist/flow-sort.d.ts +82 -0
  210. package/dist/flow-sort.js +153 -0
  211. package/dist/flow-steps.d.ts +40 -0
  212. package/dist/flow-steps.js +408 -0
  213. package/dist/flow-triggers.d.ts +244 -0
  214. package/dist/flow-triggers.js +959 -0
  215. package/dist/flows-ui.d.ts +20 -0
  216. package/dist/flows-ui.js +175 -0
  217. package/dist/flows.d.ts +229 -0
  218. package/dist/flows.js +968 -0
  219. package/dist/fonts.d.ts +19 -0
  220. package/dist/fonts.js +19 -0
  221. package/dist/gaps.d.ts +35 -0
  222. package/dist/gaps.js +101 -0
  223. package/dist/gate-failure.d.ts +40 -0
  224. package/dist/gate-failure.js +66 -0
  225. package/dist/git.d.ts +54 -0
  226. package/dist/git.js +94 -0
  227. package/dist/google-mail.d.ts +58 -0
  228. package/dist/google-mail.js +151 -0
  229. package/dist/grant.d.ts +136 -0
  230. package/dist/grant.js +238 -0
  231. package/dist/graph.d.ts +164 -0
  232. package/dist/graph.js +383 -0
  233. package/dist/guides.d.ts +22 -0
  234. package/dist/guides.js +363 -0
  235. package/dist/held.d.ts +150 -0
  236. package/dist/held.js +799 -0
  237. package/dist/invoke.d.ts +112 -0
  238. package/dist/invoke.js +780 -0
  239. package/dist/issues.d.ts +41 -0
  240. package/dist/issues.js +131 -0
  241. package/dist/job-object-helper.ps1 +252 -0
  242. package/dist/jsonl-discriminants.d.ts +11 -0
  243. package/dist/jsonl-discriminants.js +93 -0
  244. package/dist/keys.d.ts +104 -0
  245. package/dist/keys.js +229 -0
  246. package/dist/kits-ui.d.ts +17 -0
  247. package/dist/kits-ui.js +46 -0
  248. package/dist/kits.d.ts +86 -0
  249. package/dist/kits.js +215 -0
  250. package/dist/knowledge-cli.d.ts +101 -0
  251. package/dist/knowledge-cli.js +92 -0
  252. package/dist/knowledge-ui.d.ts +24 -0
  253. package/dist/knowledge-ui.js +40 -0
  254. package/dist/lead-context.d.ts +8 -0
  255. package/dist/lead-context.js +56 -0
  256. package/dist/lead-follow.d.ts +22 -0
  257. package/dist/lead-follow.js +167 -0
  258. package/dist/lead-status.d.ts +75 -0
  259. package/dist/lead-status.js +285 -0
  260. package/dist/ledger-chain.d.ts +46 -0
  261. package/dist/ledger-chain.js +187 -0
  262. package/dist/ledger-csv.d.ts +4 -0
  263. package/dist/ledger-csv.js +11 -0
  264. package/dist/ledger-view.d.ts +24 -0
  265. package/dist/ledger-view.js +58 -0
  266. package/dist/limits-ui.d.ts +26 -0
  267. package/dist/limits-ui.js +67 -0
  268. package/dist/link.d.ts +72 -0
  269. package/dist/link.js +217 -0
  270. package/dist/live.d.ts +96 -0
  271. package/dist/live.js +366 -0
  272. package/dist/liveness.d.ts +30 -0
  273. package/dist/liveness.js +42 -0
  274. package/dist/log.d.ts +7 -0
  275. package/dist/log.js +25 -0
  276. package/dist/mailbox.d.ts +57 -0
  277. package/dist/mailbox.js +150 -0
  278. package/dist/maintenance.d.ts +11 -0
  279. package/dist/maintenance.js +35 -0
  280. package/dist/mate-cli.d.ts +52 -0
  281. package/dist/mate-cli.js +345 -0
  282. package/dist/mate-contract.d.ts +10 -0
  283. package/dist/mate-contract.js +30 -0
  284. package/dist/mate-doors.d.ts +69 -0
  285. package/dist/mate-doors.js +548 -0
  286. package/dist/mate-progress.d.ts +29 -0
  287. package/dist/mate-progress.js +121 -0
  288. package/dist/mate-tools.d.ts +94 -0
  289. package/dist/mate-tools.js +1878 -0
  290. package/dist/mate.d.ts +92 -0
  291. package/dist/mate.js +435 -0
  292. package/dist/mcp-connect.d.ts +103 -0
  293. package/dist/mcp-connect.js +252 -0
  294. package/dist/mcp.d.ts +27 -0
  295. package/dist/mcp.js +651 -0
  296. package/dist/memory-cli.d.ts +466 -0
  297. package/dist/memory-cli.js +111 -0
  298. package/dist/memory-pass.d.ts +160 -0
  299. package/dist/memory-pass.js +409 -0
  300. package/dist/metrics.d.ts +3 -0
  301. package/dist/metrics.js +56 -0
  302. package/dist/mobile-viewport.d.ts +3 -0
  303. package/dist/mobile-viewport.js +37 -0
  304. package/dist/model-catalog.d.ts +118 -0
  305. package/dist/model-catalog.js +376 -0
  306. package/dist/models-cli.d.ts +102 -0
  307. package/dist/models-cli.js +66 -0
  308. package/dist/models-ui.d.ts +34 -0
  309. package/dist/models-ui.js +68 -0
  310. package/dist/modes.d.ts +80 -0
  311. package/dist/modes.js +182 -0
  312. package/dist/monitoring-settings.d.ts +44 -0
  313. package/dist/monitoring-settings.js +173 -0
  314. package/dist/monitoring-ui.d.ts +20 -0
  315. package/dist/monitoring-ui.js +51 -0
  316. package/dist/monitoring.d.ts +34 -0
  317. package/dist/monitoring.js +221 -0
  318. package/dist/names.d.ts +67 -0
  319. package/dist/names.js +102 -0
  320. package/dist/observations.d.ts +40 -0
  321. package/dist/observations.js +211 -0
  322. package/dist/oidc.d.ts +71 -0
  323. package/dist/oidc.js +182 -0
  324. package/dist/onboard.d.ts +108 -0
  325. package/dist/onboard.js +325 -0
  326. package/dist/openrouter-models.d.ts +30 -0
  327. package/dist/openrouter-models.js +120 -0
  328. package/dist/operate.d.ts +118 -0
  329. package/dist/operate.js +11321 -0
  330. package/dist/peek-cli.d.ts +97 -0
  331. package/dist/peek-cli.js +215 -0
  332. package/dist/peek.d.ts +134 -0
  333. package/dist/peek.js +578 -0
  334. package/dist/phase-routing.d.ts +307 -0
  335. package/dist/phase-routing.js +658 -0
  336. package/dist/plan-auto.d.ts +14 -0
  337. package/dist/plan-auto.js +92 -0
  338. package/dist/plan.d.ts +186 -0
  339. package/dist/plan.js +401 -0
  340. package/dist/planner-source.d.ts +251 -0
  341. package/dist/planner-source.js +460 -0
  342. package/dist/planner.d.ts +75 -0
  343. package/dist/planner.js +992 -0
  344. package/dist/policy-ui.d.ts +20 -0
  345. package/dist/policy-ui.js +41 -0
  346. package/dist/policy.d.ts +111 -0
  347. package/dist/policy.js +231 -0
  348. package/dist/prepared-evidence.d.ts +16 -0
  349. package/dist/prepared-evidence.js +96 -0
  350. package/dist/pricing.d.ts +45 -0
  351. package/dist/pricing.js +77 -0
  352. package/dist/principal.d.ts +42 -0
  353. package/dist/principal.js +82 -0
  354. package/dist/probe.d.ts +46 -0
  355. package/dist/probe.js +79 -0
  356. package/dist/process-custody.d.ts +17 -0
  357. package/dist/process-custody.js +91 -0
  358. package/dist/process-liveness.d.ts +10 -0
  359. package/dist/process-liveness.js +81 -0
  360. package/dist/process-recovery-anchor.d.ts +75 -0
  361. package/dist/process-recovery-anchor.js +188 -0
  362. package/dist/process-recovery-coalition.d.ts +25 -0
  363. package/dist/process-recovery-coalition.js +105 -0
  364. package/dist/process-recovery-eligibility.d.ts +178 -0
  365. package/dist/process-recovery-eligibility.js +170 -0
  366. package/dist/process-recovery-native.d.ts +172 -0
  367. package/dist/process-recovery-native.js +592 -0
  368. package/dist/process-recovery-provenance.d.ts +163 -0
  369. package/dist/process-recovery-provenance.js +292 -0
  370. package/dist/process-recovery-services.d.ts +56 -0
  371. package/dist/process-recovery-services.js +191 -0
  372. package/dist/process-recovery-settlement.d.ts +32 -0
  373. package/dist/process-recovery-settlement.js +132 -0
  374. package/dist/process-recovery.d.ts +41 -0
  375. package/dist/process-recovery.js +91 -0
  376. package/dist/process-tree.d.ts +41 -0
  377. package/dist/process-tree.js +264 -0
  378. package/dist/project-access.d.ts +14 -0
  379. package/dist/project-access.js +34 -0
  380. package/dist/project-cli.d.ts +18 -0
  381. package/dist/project-cli.js +104 -0
  382. package/dist/project-delete-ui.d.ts +22 -0
  383. package/dist/project-delete-ui.js +48 -0
  384. package/dist/project-delete.d.ts +55 -0
  385. package/dist/project-delete.js +413 -0
  386. package/dist/project-knowledge.d.ts +111 -0
  387. package/dist/project-knowledge.js +241 -0
  388. package/dist/project-learning.d.ts +100 -0
  389. package/dist/project-learning.js +438 -0
  390. package/dist/project-memory.d.ts +81 -0
  391. package/dist/project-memory.js +264 -0
  392. package/dist/project-skills.d.ts +152 -0
  393. package/dist/project-skills.js +660 -0
  394. package/dist/project-tools.d.ts +219 -0
  395. package/dist/project-tools.js +796 -0
  396. package/dist/project.d.ts +61 -0
  397. package/dist/project.js +125 -0
  398. package/dist/prompt.d.ts +22 -0
  399. package/dist/prompt.js +72 -0
  400. package/dist/proof.d.ts +513 -0
  401. package/dist/proof.js +1140 -0
  402. package/dist/proposal.d.ts +82 -0
  403. package/dist/proposal.js +210 -0
  404. package/dist/provider-connection.d.ts +22 -0
  405. package/dist/provider-connection.js +98 -0
  406. package/dist/provider-limits.d.ts +35 -0
  407. package/dist/provider-limits.js +95 -0
  408. package/dist/provider.d.ts +279 -0
  409. package/dist/provider.js +935 -0
  410. package/dist/publish.d.ts +107 -0
  411. package/dist/publish.js +650 -0
  412. package/dist/pulls.d.ts +118 -0
  413. package/dist/pulls.js +240 -0
  414. package/dist/push.d.ts +95 -0
  415. package/dist/push.js +353 -0
  416. package/dist/quality.d.ts +8 -0
  417. package/dist/quality.js +6 -0
  418. package/dist/recipe-ui.d.ts +18 -0
  419. package/dist/recipe-ui.js +152 -0
  420. package/dist/recipes.d.ts +81 -0
  421. package/dist/recipes.js +332 -0
  422. package/dist/remote.d.ts +67 -0
  423. package/dist/remote.js +122 -0
  424. package/dist/render.d.ts +64 -0
  425. package/dist/render.js +587 -0
  426. package/dist/report-summary.d.ts +13 -0
  427. package/dist/report-summary.js +15 -0
  428. package/dist/repos.d.ts +65 -0
  429. package/dist/repos.js +277 -0
  430. package/dist/repository-context-ui.d.ts +2 -0
  431. package/dist/repository-context-ui.js +10 -0
  432. package/dist/repository-context.d.ts +67 -0
  433. package/dist/repository-context.js +376 -0
  434. package/dist/restart-certification.d.ts +134 -0
  435. package/dist/restart-certification.js +226 -0
  436. package/dist/result-actions.d.ts +28 -0
  437. package/dist/result-actions.js +270 -0
  438. package/dist/result-completion.d.ts +18 -0
  439. package/dist/result-completion.js +66 -0
  440. package/dist/result-review.d.ts +213 -0
  441. package/dist/result-review.js +430 -0
  442. package/dist/retention-ui.d.ts +12 -0
  443. package/dist/retention-ui.js +39 -0
  444. package/dist/retention.d.ts +72 -0
  445. package/dist/retention.js +288 -0
  446. package/dist/review-context.d.ts +243 -0
  447. package/dist/review-context.js +1043 -0
  448. package/dist/review-evidence.d.ts +33 -0
  449. package/dist/review-evidence.js +56 -0
  450. package/dist/reviewer.d.ts +97 -0
  451. package/dist/reviewer.js +202 -0
  452. package/dist/routine.d.ts +228 -0
  453. package/dist/routine.js +764 -0
  454. package/dist/runner.d.ts +266 -0
  455. package/dist/runner.js +399 -0
  456. package/dist/scan.d.ts +32 -0
  457. package/dist/scan.js +92 -0
  458. package/dist/scope.d.ts +695 -0
  459. package/dist/scope.js +1176 -0
  460. package/dist/scout-report.d.ts +42 -0
  461. package/dist/scout-report.js +108 -0
  462. package/dist/scout.d.ts +69 -0
  463. package/dist/scout.js +351 -0
  464. package/dist/serve.d.ts +313 -0
  465. package/dist/serve.js +21776 -0
  466. package/dist/session-brief.d.ts +8 -0
  467. package/dist/session-brief.js +24 -0
  468. package/dist/session-cli.d.ts +13 -0
  469. package/dist/session-cli.js +284 -0
  470. package/dist/session-contract.d.ts +183 -0
  471. package/dist/session-contract.js +122 -0
  472. package/dist/session-http.d.ts +19 -0
  473. package/dist/session-http.js +154 -0
  474. package/dist/session-server.d.ts +12 -0
  475. package/dist/session-server.js +37 -0
  476. package/dist/session-service.d.ts +22 -0
  477. package/dist/session-service.js +157 -0
  478. package/dist/setup-guide.d.ts +39 -0
  479. package/dist/setup-guide.js +93 -0
  480. package/dist/sign-in-guard.d.ts +45 -0
  481. package/dist/sign-in-guard.js +74 -0
  482. package/dist/skills-ui.d.ts +11 -0
  483. package/dist/skills-ui.js +58 -0
  484. package/dist/skills.d.ts +97 -0
  485. package/dist/skills.js +276 -0
  486. package/dist/slack-api.d.ts +55 -0
  487. package/dist/slack-api.js +229 -0
  488. package/dist/slack-chat.d.ts +28 -0
  489. package/dist/slack-chat.js +413 -0
  490. package/dist/slack-settings.d.ts +7 -0
  491. package/dist/slack-settings.js +75 -0
  492. package/dist/slack-state.d.ts +13 -0
  493. package/dist/slack-state.js +9 -0
  494. package/dist/slack.d.ts +13 -0
  495. package/dist/slack.js +167 -0
  496. package/dist/spend-ui.d.ts +28 -0
  497. package/dist/spend-ui.js +95 -0
  498. package/dist/spend.d.ts +142 -0
  499. package/dist/spend.js +313 -0
  500. package/dist/sqlite-runtime.d.ts +3 -0
  501. package/dist/sqlite-runtime.js +6 -0
  502. package/dist/sso-settings.d.ts +33 -0
  503. package/dist/sso-settings.js +103 -0
  504. package/dist/sso-ui.d.ts +22 -0
  505. package/dist/sso-ui.js +39 -0
  506. package/dist/storage.d.ts +15 -0
  507. package/dist/storage.js +84 -0
  508. package/dist/store.d.ts +7754 -0
  509. package/dist/store.js +23279 -0
  510. package/dist/structured-output.d.ts +58 -0
  511. package/dist/structured-output.js +103 -0
  512. package/dist/style-asset.d.ts +7 -0
  513. package/dist/style-asset.js +41 -0
  514. package/dist/subscription-chat.d.ts +46 -0
  515. package/dist/subscription-chat.js +275 -0
  516. package/dist/summary.d.ts +33 -0
  517. package/dist/summary.js +71 -0
  518. package/dist/supervisor.mjs +297 -0
  519. package/dist/surface.d.ts +63 -0
  520. package/dist/surface.js +352 -0
  521. package/dist/sync.d.ts +94 -0
  522. package/dist/sync.js +279 -0
  523. package/dist/task-composer.d.ts +13 -0
  524. package/dist/task-composer.js +52 -0
  525. package/dist/task-control.d.ts +165 -0
  526. package/dist/task-control.js +214 -0
  527. package/dist/task-outcome-cli.d.ts +10 -0
  528. package/dist/task-outcome-cli.js +92 -0
  529. package/dist/task-text.d.ts +30 -0
  530. package/dist/task-text.js +41 -0
  531. package/dist/team-cli.d.ts +15 -0
  532. package/dist/team-cli.js +618 -0
  533. package/dist/team-contract.d.ts +92 -0
  534. package/dist/team-contract.js +1 -0
  535. package/dist/team-http.d.ts +17 -0
  536. package/dist/team-http.js +144 -0
  537. package/dist/team-leads.d.ts +81 -0
  538. package/dist/team-leads.js +565 -0
  539. package/dist/team-runtime.d.ts +27 -0
  540. package/dist/team-runtime.js +264 -0
  541. package/dist/team-ui.d.ts +3 -0
  542. package/dist/team-ui.js +9 -0
  543. package/dist/team-updates.d.ts +8 -0
  544. package/dist/team-updates.js +57 -0
  545. package/dist/teammate-admin.d.ts +53 -0
  546. package/dist/teammate-admin.js +111 -0
  547. package/dist/teammate-desk.d.ts +60 -0
  548. package/dist/teammate-desk.js +154 -0
  549. package/dist/teammate-memory.d.ts +64 -0
  550. package/dist/teammate-memory.js +196 -0
  551. package/dist/teammate-question.d.ts +59 -0
  552. package/dist/teammate-question.js +175 -0
  553. package/dist/teammate-tools.d.ts +108 -0
  554. package/dist/teammate-tools.js +271 -0
  555. package/dist/teammate-week.d.ts +68 -0
  556. package/dist/teammate-week.js +132 -0
  557. package/dist/teammate-work.d.ts +76 -0
  558. package/dist/teammate-work.js +280 -0
  559. package/dist/teammates-ui.d.ts +20 -0
  560. package/dist/teammates-ui.js +166 -0
  561. package/dist/teammates.d.ts +180 -0
  562. package/dist/teammates.js +253 -0
  563. package/dist/teams-api.d.ts +33 -0
  564. package/dist/teams-api.js +204 -0
  565. package/dist/teams-chat.d.ts +26 -0
  566. package/dist/teams-chat.js +215 -0
  567. package/dist/teams-settings.d.ts +12 -0
  568. package/dist/teams-settings.js +57 -0
  569. package/dist/teams.d.ts +21 -0
  570. package/dist/teams.js +124 -0
  571. package/dist/telegram-flow.d.ts +49 -0
  572. package/dist/telegram-flow.js +110 -0
  573. package/dist/telegram-mate.d.ts +137 -0
  574. package/dist/telegram-mate.js +707 -0
  575. package/dist/telegram-progress.d.ts +14 -0
  576. package/dist/telegram-progress.js +129 -0
  577. package/dist/telegram-settings.d.ts +9 -0
  578. package/dist/telegram-settings.js +36 -0
  579. package/dist/telegram-status.d.ts +75 -0
  580. package/dist/telegram-status.js +265 -0
  581. package/dist/telegram-team.d.ts +85 -0
  582. package/dist/telegram-team.js +359 -0
  583. package/dist/telegram.d.ts +230 -0
  584. package/dist/telegram.js +1931 -0
  585. package/dist/templates.d.ts +65 -0
  586. package/dist/templates.js +118 -0
  587. package/dist/tool-launcher.d.ts +1 -0
  588. package/dist/tool-launcher.js +101 -0
  589. package/dist/tools-ui.d.ts +30 -0
  590. package/dist/tools-ui.js +40 -0
  591. package/dist/transitions-recipes.d.ts +1 -0
  592. package/dist/transitions-recipes.js +203 -0
  593. package/dist/tree-proof.d.ts +34 -0
  594. package/dist/tree-proof.js +58 -0
  595. package/dist/verification-evidence.d.ts +44 -0
  596. package/dist/verification-evidence.js +238 -0
  597. package/dist/version.d.ts +2 -0
  598. package/dist/version.js +10 -0
  599. package/dist/webhooks.d.ts +91 -0
  600. package/dist/webhooks.js +283 -0
  601. package/dist/work-index.d.ts +68 -0
  602. package/dist/work-index.js +384 -0
  603. package/dist/work-summary.d.ts +57 -0
  604. package/dist/work-summary.js +116 -0
  605. package/dist/workspace-motion.d.ts +4 -0
  606. package/dist/workspace-motion.js +133 -0
  607. package/dist/workspace-revision.d.ts +19 -0
  608. package/dist/workspace-revision.js +92 -0
  609. package/dist/workspace-ui.d.ts +204 -0
  610. package/dist/workspace-ui.js +411 -0
  611. package/dist/worktree-notices.d.ts +13 -0
  612. package/dist/worktree-notices.js +17 -0
  613. package/dist/worktree.d.ts +249 -0
  614. package/dist/worktree.js +720 -0
  615. package/package.json +122 -0
  616. package/scripts/canary-assertions.mjs +42 -0
  617. package/scripts/crash-canary.mjs +253 -0
  618. package/scripts/fixtures/crash-process.mjs +74 -0
  619. package/scripts/fixtures/pilot-scenarios.mjs +85 -0
  620. package/scripts/fixtures/restart-service.mjs +27 -0
  621. package/scripts/launchd-certification.mjs +143 -0
  622. package/scripts/pilot.mjs +121 -0
  623. package/scripts/proof-preflight.mjs +140 -0
  624. package/scripts/provider-canary.mjs +379 -0
  625. package/scripts/recovery-canary.mjs +135 -0
  626. package/scripts/restart-certification.mjs +98 -0
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Repo onboarding (four Codex rounds, findings 1–39): clone a GitHub
3
+ * repository into a configured projects root, as a ceremony.
4
+ *
5
+ * The boundaries, in one place: the clone is the ONLY network write and
6
+ * acts as the serve process's ambient GitHub credential; the target is
7
+ * confined to an explicitly configured --project-root; publication is
8
+ * CLAIM-FIRST (an exclusive mkdir of the final directory — a lost race
9
+ * fails before a byte is written); nothing is ever deleted that this
10
+ * request did not create; submodules and LFS smudge fetches are off; and
11
+ * a fresh clone enters with ZERO authority — no tasks, no scopes, no
12
+ * grants, exactly like an `up`-enrolled repository.
13
+ *
14
+ * POSIX only: tree death is proven by polling the process group to
15
+ * ESRCH. Windows cannot prove descendants died after the leader exited
16
+ * (finding 32), so onboarding refuses there instead of guessing.
17
+ */
18
+ export declare function parseGithubRepo(raw: string): {
19
+ ok: true;
20
+ owner: string;
21
+ name: string;
22
+ } | {
23
+ ok: false;
24
+ problem: string;
25
+ };
26
+ export type GhTreeResult = {
27
+ code: number;
28
+ stdout: string;
29
+ stderr: string;
30
+ timedOut: boolean;
31
+ notFound: boolean;
32
+ /** The whole process tree is PROVEN dead (finding 21) — cleanup and
33
+ * verification both gate on this; on doubt nothing is touched. */
34
+ treeGone: boolean;
35
+ };
36
+ /**
37
+ * Run gh with its own detached group and prove tree death on EVERY
38
+ * outcome. Deliberately NOT exec.ts's processGroup path: liveProviders is
39
+ * provider-owned (finding 12), and this contract — poll the group to
40
+ * ESRCH before anyone may clean up — is onboarding's own.
41
+ */
42
+ export declare function runGhTree(args: readonly string[], options: {
43
+ cwd?: string;
44
+ timeoutMs: number;
45
+ }): Promise<GhTreeResult>;
46
+ /** Capped, control-stripped stderr for refusal text — never unbounded. */
47
+ export declare function ghWords(stderr: string): string;
48
+ export type RepoPreview = {
49
+ nameWithOwner: string;
50
+ visibility: string;
51
+ /** GitHub reports KiB (finding 18); null = unknown = treated LARGE. */
52
+ diskUsageKib: number | null;
53
+ description: string;
54
+ };
55
+ export declare const LARGE_REPO_KIB = 1048576;
56
+ export declare function isLargeRepo(preview: RepoPreview): boolean;
57
+ export type PreviewOutcome = {
58
+ ok: true;
59
+ preview: RepoPreview;
60
+ } | {
61
+ ok: false;
62
+ reason: "gh-missing" | "gh-auth" | "gh-timeout" | "gh-said-no" | "malformed";
63
+ message: string;
64
+ };
65
+ /** `gh repo view` — nothing is written on ANY preview outcome. */
66
+ export declare function previewGithubRepo(owner: string, name: string): Promise<PreviewOutcome>;
67
+ export type RepoListing = {
68
+ nameWithOwner: string;
69
+ isPrivate: boolean;
70
+ /** ISO stamp of the last push, "" when GitHub omitted it. */
71
+ updatedAt: string;
72
+ description: string;
73
+ };
74
+ export type ListOutcome = {
75
+ ok: true;
76
+ repos: RepoListing[];
77
+ } | {
78
+ ok: false;
79
+ reason: "gh-missing" | "gh-auth" | "gh-timeout" | "gh-said-no" | "malformed";
80
+ message: string;
81
+ };
82
+ /**
83
+ * `gh repo list` — the signed-in account's repositories, read-only, so the
84
+ * projects screen can OFFER them instead of making the operator type
85
+ * owner/name from memory. Same discipline as the preview: gh's answer is
86
+ * DATA — every identity is re-parsed through the strict parser and rows
87
+ * that fail it are dropped, never rendered. Nothing is written on any
88
+ * outcome.
89
+ */
90
+ export declare function listGithubRepos(limit?: number): Promise<ListOutcome>;
91
+ export type CloneOutcome = {
92
+ ok: true;
93
+ target: string;
94
+ } | {
95
+ ok: false;
96
+ reason: "exists" | "gh-missing" | "gh-auth" | "gh-timeout" | "clone-failed" | "verify-failed" | "residual";
97
+ message: string;
98
+ };
99
+ /**
100
+ * The claim-first clone (findings 6/11/23): mkdir the FINAL target
101
+ * exclusively — EEXIST loses the race with NOTHING written — then clone
102
+ * into it. Cleanup removes the target only because THIS call created it,
103
+ * and only after the tree is proven dead; on doubt the residual is named.
104
+ */
105
+ export declare function cloneGithubRepo(nameWithOwner: string, root: string, gitVerify: (cwd: string) => Promise<{
106
+ code: number;
107
+ stdout: string;
108
+ }>): Promise<CloneOutcome>;
@@ -0,0 +1,325 @@
1
+ /**
2
+ * Repo onboarding (four Codex rounds, findings 1–39): clone a GitHub
3
+ * repository into a configured projects root, as a ceremony.
4
+ *
5
+ * The boundaries, in one place: the clone is the ONLY network write and
6
+ * acts as the serve process's ambient GitHub credential; the target is
7
+ * confined to an explicitly configured --project-root; publication is
8
+ * CLAIM-FIRST (an exclusive mkdir of the final directory — a lost race
9
+ * fails before a byte is written); nothing is ever deleted that this
10
+ * request did not create; submodules and LFS smudge fetches are off; and
11
+ * a fresh clone enters with ZERO authority — no tasks, no scopes, no
12
+ * grants, exactly like an `up`-enrolled repository.
13
+ *
14
+ * POSIX only: tree death is proven by polling the process group to
15
+ * ESRCH. Windows cannot prove descendants died after the leader exited
16
+ * (finding 32), so onboarding refuses there instead of guessing.
17
+ */
18
+ import { mkdirSync, openSync, closeSync, writeSync, rmSync, constants as fsConstants } from "node:fs";
19
+ import { basename, dirname, join } from "node:path";
20
+ import { spawn } from "node:child_process";
21
+ /** Strict, onboarding-only (finding 5/18): exactly owner/name, bounded
22
+ * ASCII, alnum-leading, no leading dash or dot, `.`/`..` refused. The two
23
+ * looser GITHUB_REPO_SHAPE call sites gate other, already-reviewed
24
+ * authority and are deliberately untouched. */
25
+ const COMPONENT = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
26
+ export function parseGithubRepo(raw) {
27
+ let text = raw.trim();
28
+ if (text.length === 0 || text.length > 512)
29
+ return { ok: false, problem: "name a repository as owner/name or a github.com link" };
30
+ if (text.startsWith("https://") || text.startsWith("http://")) {
31
+ let url;
32
+ try {
33
+ url = new URL(text);
34
+ }
35
+ catch {
36
+ return { ok: false, problem: "that link is not a URL" };
37
+ }
38
+ if (url.protocol !== "https:" || url.hostname !== "github.com" || url.port !== "" || url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "") {
39
+ return { ok: false, problem: "only plain https://github.com/owner/name links are accepted" };
40
+ }
41
+ const segments = url.pathname.split("/").filter(one => one !== "");
42
+ if (segments.length !== 2)
43
+ return { ok: false, problem: "a repository link has exactly two path segments: owner/name" };
44
+ text = `${segments[0]}/${segments[1]?.replace(/\.git$/, "")}`;
45
+ }
46
+ const parts = text.split("/");
47
+ if (parts.length !== 2)
48
+ return { ok: false, problem: "name a repository as owner/name" };
49
+ const [owner = "", name = ""] = parts;
50
+ for (const part of [owner, name]) {
51
+ if (!COMPONENT.test(part) || part === "." || part === ".." || part.startsWith("-") || part.startsWith(".")) {
52
+ return { ok: false, problem: "owner and name are letters, digits, dots, dashes, and underscores — nothing else" };
53
+ }
54
+ }
55
+ return { ok: true, owner, name };
56
+ }
57
+ const GH_ENV = {
58
+ GH_PROMPT_DISABLED: "1",
59
+ GH_NO_UPDATE_NOTIFIER: "1",
60
+ GIT_LFS_SKIP_SMUDGE: "1",
61
+ GIT_TERMINAL_PROMPT: "0",
62
+ };
63
+ /**
64
+ * Run gh with its own detached group and prove tree death on EVERY
65
+ * outcome. Deliberately NOT exec.ts's processGroup path: liveProviders is
66
+ * provider-owned (finding 12), and this contract — poll the group to
67
+ * ESRCH before anyone may clean up — is onboarding's own.
68
+ */
69
+ export function runGhTree(args, options) {
70
+ return new Promise(resolve => {
71
+ if (process.platform === "win32") {
72
+ resolve({ code: 1, stdout: "", stderr: "onboarding is not supported on Windows yet", timedOut: false, notFound: true, treeGone: true });
73
+ return;
74
+ }
75
+ let child;
76
+ try {
77
+ child = spawn("gh", [...args], {
78
+ cwd: options.cwd,
79
+ shell: false,
80
+ windowsHide: true,
81
+ detached: true,
82
+ stdio: ["ignore", "pipe", "pipe"],
83
+ env: { ...process.env, ...GH_ENV },
84
+ });
85
+ }
86
+ catch (error) {
87
+ resolve({ code: 1, stdout: "", stderr: String(error), timedOut: false, notFound: false, treeGone: true });
88
+ return;
89
+ }
90
+ const pid = child.pid;
91
+ let stdout = "";
92
+ let stderr = "";
93
+ let timedOut = false;
94
+ let notFound = false;
95
+ const timer = setTimeout(() => {
96
+ timedOut = true;
97
+ if (pid !== undefined) {
98
+ try {
99
+ process.kill(-pid, "SIGKILL");
100
+ }
101
+ catch {
102
+ // group already gone
103
+ }
104
+ }
105
+ }, options.timeoutMs);
106
+ child.stdout?.setEncoding("utf8");
107
+ child.stdout?.on("data", (chunk) => {
108
+ if (stdout.length < 256 * 1024)
109
+ stdout += chunk;
110
+ });
111
+ child.stderr?.setEncoding("utf8");
112
+ child.stderr?.on("data", (chunk) => {
113
+ if (stderr.length < 64 * 1024)
114
+ stderr += chunk;
115
+ });
116
+ child.on("error", error => {
117
+ notFound = error.code === "ENOENT";
118
+ if (stderr === "")
119
+ stderr = String(error);
120
+ });
121
+ child.on("close", code => {
122
+ clearTimeout(timer);
123
+ // Tree death, proven by the group answering ESRCH — on every path.
124
+ const settle = (treeGone) => resolve({ code: notFound ? 127 : timedOut ? 124 : (code ?? 1), stdout, stderr, timedOut, notFound, treeGone });
125
+ if (pid === undefined) {
126
+ settle(true);
127
+ return;
128
+ }
129
+ const deadline = Date.now() + 5_000;
130
+ const poll = () => {
131
+ try {
132
+ process.kill(-pid, 0);
133
+ }
134
+ catch {
135
+ settle(true); // ESRCH: nobody left in the group
136
+ return;
137
+ }
138
+ if (Date.now() > deadline) {
139
+ settle(false);
140
+ return;
141
+ }
142
+ setTimeout(poll, 100);
143
+ };
144
+ poll();
145
+ });
146
+ });
147
+ }
148
+ /** Capped, control-stripped stderr for refusal text — never unbounded. */
149
+ export function ghWords(stderr) {
150
+ const line = stderr.split("\n").find(one => one.trim() !== "") ?? "";
151
+ return line.replace(/[\x00-\x1f\x7f]/g, " ").slice(0, 200).trim();
152
+ }
153
+ export const LARGE_REPO_KIB = 1_048_576; // 1 GiB in KiB
154
+ export function isLargeRepo(preview) {
155
+ return preview.diskUsageKib === null || preview.diskUsageKib >= LARGE_REPO_KIB;
156
+ }
157
+ /** `gh repo view` — nothing is written on ANY preview outcome. */
158
+ export async function previewGithubRepo(owner, name) {
159
+ const answer = await runGhTree(["repo", "view", `github.com/${owner}/${name}`, "--json", "nameWithOwner,visibility,diskUsage,description"], { timeoutMs: 30_000 });
160
+ if (answer.notFound)
161
+ return { ok: false, reason: "gh-missing", message: "the GitHub CLI is not installed on this machine — install gh where serve runs" };
162
+ if (answer.timedOut)
163
+ return { ok: false, reason: "gh-timeout", message: "GitHub did not answer in time — nothing was written" };
164
+ if (answer.code === 4)
165
+ return { ok: false, reason: "gh-auth", message: "gh is not signed in — run `gh auth login --hostname github.com` where serve runs" };
166
+ if (answer.code !== 0)
167
+ return { ok: false, reason: "gh-said-no", message: `GitHub said no — ${ghWords(answer.stderr) || "the repository may not exist, or this account cannot see it"}; nothing was written` };
168
+ let parsed;
169
+ try {
170
+ parsed = JSON.parse(answer.stdout);
171
+ }
172
+ catch {
173
+ return { ok: false, reason: "malformed", message: "GitHub's answer was not the JSON gh promises — nothing was written" };
174
+ }
175
+ const nameWithOwner = parsed["nameWithOwner"];
176
+ // The returned identity is RE-PARSED through the strict parser before
177
+ // anything derives from it (finding 18) — gh's answer is data too.
178
+ if (typeof nameWithOwner !== "string" || !parseGithubRepo(nameWithOwner).ok) {
179
+ return { ok: false, reason: "malformed", message: "GitHub named a repository shape this console refuses — nothing was written" };
180
+ }
181
+ const disk = parsed["diskUsage"];
182
+ const description = typeof parsed["description"] === "string" ? parsed["description"] : "";
183
+ return {
184
+ ok: true,
185
+ preview: {
186
+ nameWithOwner,
187
+ visibility: typeof parsed["visibility"] === "string" ? parsed["visibility"].toLowerCase() : "unknown",
188
+ diskUsageKib: typeof disk === "number" && disk >= 0 ? disk : null,
189
+ description: description.replace(/[\x00-\x1f\x7f]/g, " ").slice(0, 200),
190
+ },
191
+ };
192
+ }
193
+ /**
194
+ * `gh repo list` — the signed-in account's repositories, read-only, so the
195
+ * projects screen can OFFER them instead of making the operator type
196
+ * owner/name from memory. Same discipline as the preview: gh's answer is
197
+ * DATA — every identity is re-parsed through the strict parser and rows
198
+ * that fail it are dropped, never rendered. Nothing is written on any
199
+ * outcome.
200
+ */
201
+ export async function listGithubRepos(limit = 100) {
202
+ const answer = await runGhTree(["repo", "list", "--json", "nameWithOwner,isPrivate,updatedAt,description", "--limit", String(Math.max(1, Math.min(200, limit)))], { timeoutMs: 30_000 });
203
+ if (answer.notFound)
204
+ return { ok: false, reason: "gh-missing", message: "the GitHub CLI is not installed on this machine — install gh where serve runs" };
205
+ if (answer.timedOut)
206
+ return { ok: false, reason: "gh-timeout", message: "GitHub did not answer in time" };
207
+ if (answer.code === 4)
208
+ return { ok: false, reason: "gh-auth", message: "gh is not signed in — run `gh auth login --hostname github.com` where serve runs" };
209
+ if (answer.code !== 0)
210
+ return { ok: false, reason: "gh-said-no", message: `GitHub said no — ${ghWords(answer.stderr) || "the account's repositories could not be listed"}` };
211
+ let parsed;
212
+ try {
213
+ parsed = JSON.parse(answer.stdout);
214
+ }
215
+ catch {
216
+ return { ok: false, reason: "malformed", message: "GitHub's answer was not the JSON gh promises" };
217
+ }
218
+ if (!Array.isArray(parsed))
219
+ return { ok: false, reason: "malformed", message: "GitHub's answer was not the JSON gh promises" };
220
+ const repos = [];
221
+ for (const raw of parsed) {
222
+ if (raw === null || typeof raw !== "object")
223
+ continue;
224
+ const row = raw;
225
+ const nameWithOwner = row["nameWithOwner"];
226
+ if (typeof nameWithOwner !== "string" || !parseGithubRepo(nameWithOwner).ok)
227
+ continue;
228
+ const description = typeof row["description"] === "string" ? row["description"] : "";
229
+ repos.push({
230
+ nameWithOwner,
231
+ isPrivate: row["isPrivate"] === true,
232
+ // The stamp is DATA too (ghlist review, finding 3): only an
233
+ // ISO-shaped value survives; anything else renders as nothing.
234
+ updatedAt: typeof row["updatedAt"] === "string" && /^\d{4}-\d{2}-\d{2}T[0-9:.]+Z?$/.test(row["updatedAt"])
235
+ ? row["updatedAt"]
236
+ : "",
237
+ description: description.replace(/[\x00-\x1f\x7f]/g, " ").slice(0, 120),
238
+ });
239
+ }
240
+ return { ok: true, repos };
241
+ }
242
+ /**
243
+ * The claim-first clone (findings 6/11/23): mkdir the FINAL target
244
+ * exclusively — EEXIST loses the race with NOTHING written — then clone
245
+ * into it. Cleanup removes the target only because THIS call created it,
246
+ * and only after the tree is proven dead; on doubt the residual is named.
247
+ */
248
+ export async function cloneGithubRepo(nameWithOwner, root, gitVerify) {
249
+ const shape = parseGithubRepo(nameWithOwner);
250
+ if (!shape.ok)
251
+ return { ok: false, reason: "clone-failed", message: shape.problem };
252
+ const target = join(root, shape.name);
253
+ if (dirname(target) !== root || basename(target) !== shape.name) {
254
+ return { ok: false, reason: "clone-failed", message: "the target escaped its root — refused" };
255
+ }
256
+ try {
257
+ mkdirSync(target); // the CLAIM — exclusive by mkdir semantics
258
+ }
259
+ catch {
260
+ return {
261
+ ok: false,
262
+ reason: "exists",
263
+ message: `nothing was written by this request — a directory already exists at ${target}; if it is empty and nobody is cloning, it is an abandoned claim: inspect and remove it by hand`,
264
+ };
265
+ }
266
+ // The ownership marker (finding 11): written and removed before gh runs;
267
+ // its lifecycle is within this invocation only.
268
+ const marker = join(target, ".so-claim");
269
+ try {
270
+ const fd = openSync(marker, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL, 0o600);
271
+ writeSync(fd, "claimed by standing-orders onboarding\n");
272
+ closeSync(fd);
273
+ rmSync(marker);
274
+ }
275
+ catch {
276
+ // The claim stands; a marker hiccup is not worth a wedged directory.
277
+ }
278
+ const answer = await runGhTree(["repo", "clone", `github.com/${nameWithOwner}`, target, "--", "--no-tags", "--no-recurse-submodules"], { timeoutMs: 10 * 60_000 });
279
+ const cleanOwn = () => {
280
+ if (!answer.treeGone)
281
+ return false; // doubt: touch nothing (finding 21)
282
+ try {
283
+ rmSync(target, { recursive: true, force: true });
284
+ return true;
285
+ }
286
+ catch {
287
+ return false;
288
+ }
289
+ };
290
+ if (answer.notFound) {
291
+ cleanOwn();
292
+ return { ok: false, reason: "gh-missing", message: "the GitHub CLI is not installed on this machine — the claimed directory was removed" };
293
+ }
294
+ if (answer.code === 4) {
295
+ const removed = cleanOwn();
296
+ return { ok: false, reason: "gh-auth", message: `gh is not signed in — run \`gh auth login --hostname github.com\` where serve runs; ${removed ? "the claimed directory was removed" : `a residual remains at ${target}`}` };
297
+ }
298
+ if (answer.timedOut || answer.code !== 0) {
299
+ const removed = cleanOwn();
300
+ const said = answer.timedOut ? "the clone ran past ten minutes and was stopped" : `the clone failed — ${ghWords(answer.stderr) || "git said no"}`;
301
+ return {
302
+ ok: false,
303
+ reason: answer.timedOut ? "gh-timeout" : "clone-failed",
304
+ message: `${said}; ${removed ? "this request's partial copy was removed" : `a residual remains at ${target} — remove it by hand`}`,
305
+ };
306
+ }
307
+ if (!answer.treeGone) {
308
+ return { ok: false, reason: "residual", message: `the clone finished but its helpers could not be proven gone — inspect ${target} before using it` };
309
+ }
310
+ // Verify what landed IS the repository we asked for, where we asked.
311
+ const top = await gitVerify(target);
312
+ if (top.code !== 0 || top.stdout.trim() !== target) {
313
+ const removed = (() => {
314
+ try {
315
+ rmSync(target, { recursive: true, force: true });
316
+ return true;
317
+ }
318
+ catch {
319
+ return false;
320
+ }
321
+ })();
322
+ return { ok: false, reason: "verify-failed", message: `what landed did not verify as a repository at ${target}; ${removed ? "it was removed" : "a residual remains — remove it by hand"}` };
323
+ }
324
+ return { ok: true, target };
325
+ }
@@ -0,0 +1,30 @@
1
+ export type OpenRouterModel = {
2
+ id: string;
3
+ name: string;
4
+ context: number | null;
5
+ tools: boolean;
6
+ input: number | null;
7
+ output: number | null;
8
+ cachedInput: number | null;
9
+ extraCharges: boolean;
10
+ conditionalPricing: boolean;
11
+ /** Unix seconds when OpenRouter listed it — the closest thing to a release date. */
12
+ created: number | null;
13
+ };
14
+ export type OpenRouterModels = {
15
+ ok: true;
16
+ models: OpenRouterModel[];
17
+ source: "public" | "account";
18
+ checkedAt: string;
19
+ } | {
20
+ ok: false;
21
+ problem: string;
22
+ };
23
+ export declare function parseOpenRouterModels(data: unknown): OpenRouterModel[] | null;
24
+ export declare function fetchOpenRouterModels(key: string | null, fetcher?: typeof fetch): Promise<OpenRouterModels>;
25
+ /** One bounded cache per console. A changed/removed key cannot reuse another account's list. */
26
+ export declare function openRouterModelsCache(fetcher?: typeof fetch): (key: string | null, refresh?: boolean) => Promise<OpenRouterModels>;
27
+ export declare function modelDollars(amount: number | null): string;
28
+ export declare function openRouterPicker(catalog: OpenRouterModels, selected: string | null, refreshUrl: string): string;
29
+ /** Only filters already-rendered options; credentials never enter this script. */
30
+ export declare function openRouterPickerScript(): string;
@@ -0,0 +1,120 @@
1
+ /** Live discovery for the UI. Prices are USD, separate from rounded budget pins. */
2
+ import { createHash } from "node:crypto";
3
+ import { readCappedBody } from "./converse.js";
4
+ import { validModelId } from "./provider.js";
5
+ const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
6
+ function price(value, units = 1_000_000) {
7
+ if ((typeof value !== "string" || !/^\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(value)) && typeof value !== "number")
8
+ return null;
9
+ const amount = Number(value) * units;
10
+ return Number.isFinite(amount) && amount >= 0 ? amount : null;
11
+ }
12
+ export function parseOpenRouterModels(data) {
13
+ if (!Array.isArray(data) || data.length > 5_000)
14
+ return null;
15
+ const models = new Map();
16
+ for (const value of data) {
17
+ const row = record(value), pricing = record(row.pricing), architecture = record(row.architecture);
18
+ if (typeof row.id !== "string" || !validModelId(row.id) || row.id.length > 128)
19
+ continue;
20
+ if (Array.isArray(architecture.output_modalities) && !architecture.output_modalities.includes("text"))
21
+ continue;
22
+ models.set(row.id, {
23
+ id: row.id, name: typeof row.name === "string" ? row.name.slice(0, 150) : row.id,
24
+ context: typeof row.context_length === "number" && Number.isSafeInteger(row.context_length) && row.context_length > 0 ? row.context_length : null,
25
+ tools: Array.isArray(row.supported_parameters) && row.supported_parameters.includes("tools"),
26
+ input: price(pricing.prompt), output: price(pricing.completion), cachedInput: price(pricing.input_cache_read),
27
+ extraCharges: ["request", "image", "web_search", "internal_reasoning", "input_cache_write"].some(key => (price(pricing[key], 1) ?? 0) > 0),
28
+ conditionalPricing: Array.isArray(pricing.overrides) && pricing.overrides.length > 0,
29
+ created: typeof row.created === "number" && Number.isSafeInteger(row.created) && row.created > 0 ? row.created : null,
30
+ });
31
+ }
32
+ return [...models.values()].sort((a, b) => a.name.localeCompare(b.name));
33
+ }
34
+ export async function fetchOpenRouterModels(key, fetcher = fetch) {
35
+ try {
36
+ const response = await fetcher(`https://openrouter.ai/api/v1/models${key === null ? "" : "/user"}`, {
37
+ headers: key === null ? { accept: "application/json" } : { accept: "application/json", authorization: `Bearer ${key}` },
38
+ redirect: "error", signal: AbortSignal.timeout(8_000),
39
+ });
40
+ if (!response.ok) {
41
+ await response.body?.cancel();
42
+ return { ok: false, problem: response.status === 401 || response.status === 403
43
+ ? "OpenRouter rejected this key. Update your connection and try again."
44
+ : "OpenRouter’s model list is unavailable. Try again shortly." };
45
+ }
46
+ const body = await readCappedBody(response, 8_388_608);
47
+ if (body === null)
48
+ return { ok: false, problem: "OpenRouter’s model list was too large to load. Try again shortly." };
49
+ const models = parseOpenRouterModels(record(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(body))).data);
50
+ if (models === null)
51
+ return { ok: false, problem: "OpenRouter returned an unreadable model list. Try again shortly." };
52
+ return { ok: true, models, source: key === null ? "public" : "account", checkedAt: new Date().toISOString() };
53
+ }
54
+ catch {
55
+ return { ok: false, problem: "Couldn’t load models from OpenRouter. Check your connection and try again." };
56
+ }
57
+ }
58
+ /** One bounded cache per console. A changed/removed key cannot reuse another account's list. */
59
+ export function openRouterModelsCache(fetcher = fetch) {
60
+ let cache = null;
61
+ let pending = null;
62
+ return async (key, refresh = false) => {
63
+ const fingerprint = createHash("sha256").update(key ?? "public").digest("hex");
64
+ if (!refresh && cache?.fingerprint === fingerprint && cache.expires > Date.now())
65
+ return cache.result;
66
+ if (pending?.fingerprint === fingerprint)
67
+ return pending.result;
68
+ const result = fetchOpenRouterModels(key, fetcher);
69
+ pending = { fingerprint, result };
70
+ const value = await result;
71
+ // An older request finishing late must not overwrite a newer key's cache.
72
+ if (pending?.result === result) {
73
+ cache = { fingerprint, expires: Date.now() + (value.ok ? 600_000 : 30_000), result: value };
74
+ pending = null;
75
+ }
76
+ return value;
77
+ };
78
+ }
79
+ const escape = (s) => s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
80
+ export function modelDollars(amount) {
81
+ if (amount === null)
82
+ return "Not reported";
83
+ if (amount === 0)
84
+ return "$0";
85
+ if (amount < 0.00000001)
86
+ return "<$0.00000001";
87
+ return "$" + amount.toLocaleString("en-US", { maximumFractionDigits: 8 });
88
+ }
89
+ function details(model) {
90
+ return `Input ${modelDollars(model.input)} · Output ${modelDollars(model.output)}${model.cachedInput === null ? "" : ` · Cached input ${modelDollars(model.cachedInput)}`} per 1M tokens. ` +
91
+ (model.context === null ? "" : `${model.context.toLocaleString("en-US")} token context. `) +
92
+ (model.tools ? "Tool calling supported. " : "Tool calling not listed. ") +
93
+ (model.conditionalPricing ? "Rates change with context length or other conditions. " : "") +
94
+ (model.extraCharges ? "Additional usage charges may apply. " : "") + "Actual charges depend on routing and usage.";
95
+ }
96
+ export function openRouterPicker(catalog, selected, refreshUrl) {
97
+ const rows = catalog.ok ? catalog.models : [];
98
+ const current = rows.find(row => row.id === selected);
99
+ const manual = selected && !current ? `<option selected value="${escape(selected)}" data-detail="This saved model is not in the loaded catalog. Availability and pricing are unverified.">${escape(selected)} · Saved choice</option>` : "";
100
+ return `<div data-openrouter-picker><p class="meta">${catalog.ok
101
+ ? `${rows.length} text models · ${catalog.source === "account" ? "Filtered for your OpenRouter account" : "Public catalog · Connect a key to check your account"} · Updated ${escape(catalog.checkedAt.slice(11, 16))} UTC`
102
+ : escape(catalog.problem)} <a href="${escape(refreshUrl)}">Refresh models</a></p>` +
103
+ `<label data-model-search hidden>Search models<input type="search" placeholder="Search by name or provider" autocomplete="off"></label>` +
104
+ `<label>Model<select name="model" aria-describedby="openrouter-price"><option value="__custom__"${selected === null ? " selected" : ""}>Choose a model</option>${manual}${rows.map(row => `<option value="${escape(row.id)}" data-detail="${escape(details(row))}"${row.id === selected ? " selected" : ""}>${escape(row.name)} · ${modelDollars(row.input)} in / ${modelDollars(row.output)} out per 1M</option>`).join("")}</select></label>` +
105
+ `<p id="openrouter-price" class="meta" aria-live="polite">${current ? escape(details(current)) : selected ? "This saved model is not in the loaded catalog. Availability and pricing are unverified." : "Choose a model to see its token prices and context size."}</p>` +
106
+ `<p data-model-count class="meta" aria-live="polite"></p><p class="meta"><a href="https://openrouter.ai/models" target="_blank" rel="noreferrer">Compare models on OpenRouter ↗</a> · Prices in USD; catalog browsing uses no model tokens.</p></div>`;
107
+ }
108
+ /** Only filters already-rendered options; credentials never enter this script. */
109
+ export function openRouterPickerScript() {
110
+ return `(function(){document.querySelectorAll('[data-openrouter-picker]').forEach(function(root){
111
+ var search=root.querySelector('input[type=search]'),select=root.querySelector('select'),price=root.querySelector('#openrouter-price'),count=root.querySelector('[data-model-count]');
112
+ if(!search||!select)return;root.querySelector('[data-model-search]').hidden=false;
113
+ var options=Array.from(select.options),chosen=select.value;
114
+ function filter(){var q=search.value.trim().toLowerCase(),matches=options.filter(function(o){return o.value!=='__custom__'&&(o.textContent+' '+o.value).toLowerCase().includes(q)});
115
+ select.replaceChildren();options.forEach(function(o){if(o.value==='__custom__'||o.value===chosen||matches.includes(o))select.appendChild(o)});select.value=chosen;
116
+ count.textContent=q?matches.length+' matches'+(chosen!=='__custom__'&&!matches.some(function(o){return o.value===chosen})?' · your selection is kept':''):'';
117
+ }
118
+ select.addEventListener('change',function(){chosen=select.value;price.textContent=select.selectedOptions[0].dataset.detail||'Choose a model to see its token prices and context size.';filter()});search.addEventListener('input',filter);
119
+ })})();`;
120
+ }