@intentic/sandbox-contract 1.232.0 → 1.234.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 (538) hide show
  1. package/README.md +11 -5
  2. package/dist/agent-catalog.d.ts +4 -2
  3. package/dist/agent-catalog.d.ts.map +1 -1
  4. package/dist/agent-catalog.js +20 -14
  5. package/dist/agent-catalog.js.map +1 -1
  6. package/dist/chores/chores.d.ts +1 -1
  7. package/dist/chores/chores.d.ts.map +1 -1
  8. package/dist/chores/chores.js +36 -1
  9. package/dist/chores/chores.js.map +1 -1
  10. package/dist/chores/probes.d.ts +1 -1
  11. package/dist/chores/probes.d.ts.map +1 -1
  12. package/dist/chores/probes.js +70 -0
  13. package/dist/chores/probes.js.map +1 -1
  14. package/dist/chores/stack.d.ts.map +1 -1
  15. package/dist/chores/stack.js +2 -1
  16. package/dist/chores/stack.js.map +1 -1
  17. package/dist/chores/verdict.d.ts +1 -1
  18. package/dist/chores/verdict.d.ts.map +1 -1
  19. package/dist/command-classes.d.ts +17 -0
  20. package/dist/command-classes.d.ts.map +1 -0
  21. package/dist/command-classes.js +189 -0
  22. package/dist/command-classes.js.map +1 -0
  23. package/dist/contracts/activity.contract.js +1 -1
  24. package/dist/contracts/activity.contract.js.map +1 -1
  25. package/dist/contracts/agent.contract.d.ts +40 -2
  26. package/dist/contracts/agent.contract.d.ts.map +1 -1
  27. package/dist/contracts/agent.contract.js +4 -1
  28. package/dist/contracts/agent.contract.js.map +1 -1
  29. package/dist/contracts/agents.contract.d.ts +24 -0
  30. package/dist/contracts/agents.contract.d.ts.map +1 -1
  31. package/dist/contracts/agents.contract.js +5 -1
  32. package/dist/contracts/agents.contract.js.map +1 -1
  33. package/dist/contracts/automations.contract.d.ts +30 -0
  34. package/dist/contracts/automations.contract.d.ts.map +1 -1
  35. package/dist/contracts/automations.contract.js +2 -1
  36. package/dist/contracts/automations.contract.js.map +1 -1
  37. package/dist/contracts/capabilities.contract.d.ts +63 -0
  38. package/dist/contracts/capabilities.contract.d.ts.map +1 -1
  39. package/dist/contracts/capabilities.contract.js +3 -1
  40. package/dist/contracts/capabilities.contract.js.map +1 -1
  41. package/dist/contracts/chores.contract.d.ts +17 -0
  42. package/dist/contracts/chores.contract.d.ts.map +1 -1
  43. package/dist/contracts/chores.contract.js +2 -1
  44. package/dist/contracts/chores.contract.js.map +1 -1
  45. package/dist/contracts/ci.contract.js +2 -1
  46. package/dist/contracts/ci.contract.js.map +1 -1
  47. package/dist/contracts/claude.contract.js +2 -1
  48. package/dist/contracts/claude.contract.js.map +1 -1
  49. package/dist/contracts/cursor.contract.js +2 -1
  50. package/dist/contracts/cursor.contract.js.map +1 -1
  51. package/dist/contracts/drafts.contract.d.ts.map +1 -1
  52. package/dist/contracts/drafts.contract.js +2 -1
  53. package/dist/contracts/drafts.contract.js.map +1 -1
  54. package/dist/contracts/endpoints.contract.d.ts.map +1 -1
  55. package/dist/contracts/endpoints.contract.js +2 -1
  56. package/dist/contracts/endpoints.contract.js.map +1 -1
  57. package/dist/contracts/exit.contract.d.ts.map +1 -1
  58. package/dist/contracts/exit.contract.js +2 -1
  59. package/dist/contracts/exit.contract.js.map +1 -1
  60. package/dist/contracts/extensions.contract.d.ts +44 -0
  61. package/dist/contracts/extensions.contract.d.ts.map +1 -1
  62. package/dist/contracts/extensions.contract.js +4 -1
  63. package/dist/contracts/extensions.contract.js.map +1 -1
  64. package/dist/contracts/git.contract.d.ts.map +1 -1
  65. package/dist/contracts/git.contract.js +4 -1
  66. package/dist/contracts/git.contract.js.map +1 -1
  67. package/dist/contracts/grok.contract.d.ts.map +1 -1
  68. package/dist/contracts/grok.contract.js +2 -1
  69. package/dist/contracts/grok.contract.js.map +1 -1
  70. package/dist/contracts/history.contract.d.ts.map +1 -1
  71. package/dist/contracts/history.contract.js +2 -1
  72. package/dist/contracts/history.contract.js.map +1 -1
  73. package/dist/contracts/host.contract.d.ts +7 -0
  74. package/dist/contracts/host.contract.d.ts.map +1 -1
  75. package/dist/contracts/host.contract.js +4 -1
  76. package/dist/contracts/host.contract.js.map +1 -1
  77. package/dist/contracts/intentic.contract.d.ts.map +1 -1
  78. package/dist/contracts/intentic.contract.js +2 -1
  79. package/dist/contracts/intentic.contract.js.map +1 -1
  80. package/dist/contracts/inventory.contract.js +1 -1
  81. package/dist/contracts/inventory.contract.js.map +1 -1
  82. package/dist/contracts/issues.contract.d.ts +89 -0
  83. package/dist/contracts/issues.contract.d.ts.map +1 -0
  84. package/dist/contracts/issues.contract.js +50 -0
  85. package/dist/contracts/issues.contract.js.map +1 -0
  86. package/dist/contracts/logs.contract.d.ts.map +1 -1
  87. package/dist/contracts/logs.contract.js +1 -1
  88. package/dist/contracts/logs.contract.js.map +1 -1
  89. package/dist/contracts/loops.contract.js +2 -1
  90. package/dist/contracts/loops.contract.js.map +1 -1
  91. package/dist/contracts/panels.contract.d.ts.map +1 -1
  92. package/dist/contracts/panels.contract.js +2 -1
  93. package/dist/contracts/panels.contract.js.map +1 -1
  94. package/dist/contracts/personas.contract.js +2 -1
  95. package/dist/contracts/personas.contract.js.map +1 -1
  96. package/dist/contracts/ports.contract.d.ts.map +1 -1
  97. package/dist/contracts/ports.contract.js +2 -1
  98. package/dist/contracts/ports.contract.js.map +1 -1
  99. package/dist/contracts/prepush.contract.d.ts.map +1 -1
  100. package/dist/contracts/prepush.contract.js +2 -1
  101. package/dist/contracts/prepush.contract.js.map +1 -1
  102. package/dist/contracts/providers.contract.d.ts.map +1 -1
  103. package/dist/contracts/providers.contract.js +2 -1
  104. package/dist/contracts/providers.contract.js.map +1 -1
  105. package/dist/contracts/public.contract.d.ts.map +1 -1
  106. package/dist/contracts/public.contract.js +2 -1
  107. package/dist/contracts/public.contract.js.map +1 -1
  108. package/dist/contracts/push.contract.d.ts.map +1 -1
  109. package/dist/contracts/push.contract.js +2 -1
  110. package/dist/contracts/push.contract.js.map +1 -1
  111. package/dist/contracts/runner.contract.d.ts +127 -84
  112. package/dist/contracts/runner.contract.d.ts.map +1 -1
  113. package/dist/contracts/runner.contract.js +10 -2
  114. package/dist/contracts/runner.contract.js.map +1 -1
  115. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  116. package/dist/contracts/secrets.contract.js +2 -1
  117. package/dist/contracts/secrets.contract.js.map +1 -1
  118. package/dist/contracts/sessions.contract.js +1 -1
  119. package/dist/contracts/sessions.contract.js.map +1 -1
  120. package/dist/contracts/settings.contract.d.ts +32 -0
  121. package/dist/contracts/settings.contract.d.ts.map +1 -1
  122. package/dist/contracts/settings.contract.js +3 -1
  123. package/dist/contracts/settings.contract.js.map +1 -1
  124. package/dist/contracts/share.contract.d.ts.map +1 -1
  125. package/dist/contracts/share.contract.js +2 -1
  126. package/dist/contracts/share.contract.js.map +1 -1
  127. package/dist/contracts/skills.contract.d.ts.map +1 -1
  128. package/dist/contracts/skills.contract.js +2 -1
  129. package/dist/contracts/skills.contract.js.map +1 -1
  130. package/dist/contracts/system.contract.d.ts +31 -16
  131. package/dist/contracts/system.contract.d.ts.map +1 -1
  132. package/dist/contracts/system.contract.js +6 -1
  133. package/dist/contracts/system.contract.js.map +1 -1
  134. package/dist/contracts/translator.contract.d.ts.map +1 -1
  135. package/dist/contracts/translator.contract.js +4 -1
  136. package/dist/contracts/translator.contract.js.map +1 -1
  137. package/dist/contracts/usage.contract.js +1 -1
  138. package/dist/contracts/usage.contract.js.map +1 -1
  139. package/dist/contracts/vpn.contract.d.ts.map +1 -1
  140. package/dist/contracts/vpn.contract.js +2 -1
  141. package/dist/contracts/vpn.contract.js.map +1 -1
  142. package/dist/contracts/webext.contract.d.ts +45 -0
  143. package/dist/contracts/webext.contract.d.ts.map +1 -0
  144. package/dist/contracts/webext.contract.js +12 -0
  145. package/dist/contracts/webext.contract.js.map +1 -0
  146. package/dist/contracts/workflows.contract.js +2 -1
  147. package/dist/contracts/workflows.contract.js.map +1 -1
  148. package/dist/contracts/workspace.contract.d.ts +2 -2
  149. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  150. package/dist/contracts/workspace.contract.js +7 -1
  151. package/dist/contracts/workspace.contract.js.map +1 -1
  152. package/dist/credential-material.d.ts +2 -0
  153. package/dist/credential-material.d.ts.map +1 -0
  154. package/dist/credential-material.js +36 -0
  155. package/dist/credential-material.js.map +1 -0
  156. package/dist/definition-action.d.ts +7 -0
  157. package/dist/definition-action.d.ts.map +1 -0
  158. package/dist/definition-action.js +3 -0
  159. package/dist/definition-action.js.map +1 -0
  160. package/dist/definition.d.ts +132 -21
  161. package/dist/definition.d.ts.map +1 -1
  162. package/dist/definition.js +29 -7
  163. package/dist/definition.js.map +1 -1
  164. package/dist/events.d.ts +101 -0
  165. package/dist/events.d.ts.map +1 -1
  166. package/dist/events.js +25 -1
  167. package/dist/events.js.map +1 -1
  168. package/dist/fast-tier.d.ts +1 -1
  169. package/dist/fast-tier.d.ts.map +1 -1
  170. package/dist/history-state.d.ts.map +1 -1
  171. package/dist/history-state.js +2 -0
  172. package/dist/history-state.js.map +1 -1
  173. package/dist/hostnames.d.ts +2 -0
  174. package/dist/hostnames.d.ts.map +1 -1
  175. package/dist/hostnames.js +3 -1
  176. package/dist/hostnames.js.map +1 -1
  177. package/dist/index.d.ts +411 -7
  178. package/dist/index.d.ts.map +1 -1
  179. package/dist/index.js +56 -1
  180. package/dist/index.js.map +1 -1
  181. package/dist/listener-protocol.js +1 -1
  182. package/dist/listener-protocol.js.map +1 -1
  183. package/dist/quick-model.d.ts +1 -1
  184. package/dist/quick-model.d.ts.map +1 -1
  185. package/dist/runner-protocol.d.ts +18 -0
  186. package/dist/runner-protocol.d.ts.map +1 -1
  187. package/dist/runner-protocol.js +8 -4
  188. package/dist/runner-protocol.js.map +1 -1
  189. package/dist/runtime-state.d.ts +9 -0
  190. package/dist/runtime-state.d.ts.map +1 -1
  191. package/dist/runtime-state.js +3 -0
  192. package/dist/runtime-state.js.map +1 -1
  193. package/dist/schemas/activity.d.ts +112 -0
  194. package/dist/schemas/activity.d.ts.map +1 -0
  195. package/dist/schemas/activity.js +70 -0
  196. package/dist/schemas/activity.js.map +1 -0
  197. package/dist/schemas/agent.d.ts +195 -0
  198. package/dist/schemas/agent.d.ts.map +1 -0
  199. package/dist/schemas/agent.js +171 -0
  200. package/dist/schemas/agent.js.map +1 -0
  201. package/dist/schemas/agents.d.ts +690 -0
  202. package/dist/schemas/agents.d.ts.map +1 -0
  203. package/dist/schemas/agents.js +314 -0
  204. package/dist/schemas/agents.js.map +1 -0
  205. package/dist/schemas/automations.d.ts +781 -0
  206. package/dist/schemas/automations.d.ts.map +1 -0
  207. package/dist/schemas/automations.js +223 -0
  208. package/dist/schemas/automations.js.map +1 -0
  209. package/dist/schemas/capabilities.d.ts +753 -0
  210. package/dist/schemas/capabilities.d.ts.map +1 -0
  211. package/dist/schemas/capabilities.js +269 -0
  212. package/dist/schemas/capabilities.js.map +1 -0
  213. package/dist/schemas/ci.d.ts +179 -0
  214. package/dist/schemas/ci.d.ts.map +1 -0
  215. package/dist/schemas/ci.js +99 -0
  216. package/dist/schemas/ci.js.map +1 -0
  217. package/dist/schemas/claude-gate.d.ts +13 -0
  218. package/dist/schemas/claude-gate.d.ts.map +1 -0
  219. package/dist/schemas/claude-gate.js +8 -0
  220. package/dist/schemas/claude-gate.js.map +1 -0
  221. package/dist/schemas/codebase-health.d.ts +56 -0
  222. package/dist/schemas/codebase-health.d.ts.map +1 -0
  223. package/dist/schemas/codebase-health.js +43 -0
  224. package/dist/schemas/codebase-health.js.map +1 -0
  225. package/dist/schemas/computers.d.ts +386 -0
  226. package/dist/schemas/computers.d.ts.map +1 -0
  227. package/dist/schemas/computers.js +107 -0
  228. package/dist/schemas/computers.js.map +1 -0
  229. package/dist/schemas/drafts.d.ts +84 -0
  230. package/dist/schemas/drafts.d.ts.map +1 -0
  231. package/dist/schemas/drafts.js +44 -0
  232. package/dist/schemas/drafts.js.map +1 -0
  233. package/dist/schemas/environment.d.ts +349 -0
  234. package/dist/schemas/environment.d.ts.map +1 -0
  235. package/dist/schemas/environment.js +111 -0
  236. package/dist/schemas/environment.js.map +1 -0
  237. package/dist/schemas/exit.d.ts +151 -0
  238. package/dist/schemas/exit.d.ts.map +1 -0
  239. package/dist/schemas/exit.js +115 -0
  240. package/dist/schemas/exit.js.map +1 -0
  241. package/dist/schemas/extension-updates.d.ts +1016 -0
  242. package/dist/schemas/extension-updates.d.ts.map +1 -0
  243. package/dist/schemas/extension-updates.js +199 -0
  244. package/dist/schemas/extension-updates.js.map +1 -0
  245. package/dist/schemas/fast-mode.d.ts +8 -0
  246. package/dist/schemas/fast-mode.d.ts.map +1 -0
  247. package/dist/schemas/fast-mode.js +3 -0
  248. package/dist/schemas/fast-mode.js.map +1 -0
  249. package/dist/schemas/git-history.d.ts +238 -0
  250. package/dist/schemas/git-history.d.ts.map +1 -0
  251. package/dist/schemas/git-history.js +152 -0
  252. package/dist/schemas/git-history.js.map +1 -0
  253. package/dist/schemas/git.d.ts +471 -0
  254. package/dist/schemas/git.d.ts.map +1 -0
  255. package/dist/schemas/git.js +204 -0
  256. package/dist/schemas/git.js.map +1 -0
  257. package/dist/schemas/history.d.ts +100 -0
  258. package/dist/schemas/history.d.ts.map +1 -0
  259. package/dist/schemas/history.js +54 -0
  260. package/dist/schemas/history.js.map +1 -0
  261. package/dist/schemas/hosts.d.ts +41 -0
  262. package/dist/schemas/hosts.d.ts.map +1 -0
  263. package/dist/schemas/hosts.js +18 -0
  264. package/dist/schemas/hosts.js.map +1 -0
  265. package/dist/schemas/intentic.d.ts +5 -0
  266. package/dist/schemas/intentic.d.ts.map +1 -0
  267. package/dist/schemas/intentic.js +3 -0
  268. package/dist/schemas/intentic.js.map +1 -0
  269. package/dist/schemas/internal.d.ts +8 -0
  270. package/dist/schemas/internal.d.ts.map +1 -0
  271. package/dist/schemas/internal.js +12 -0
  272. package/dist/schemas/internal.js.map +1 -0
  273. package/dist/schemas/inventory.d.ts +171 -0
  274. package/dist/schemas/inventory.d.ts.map +1 -0
  275. package/dist/schemas/inventory.js +51 -0
  276. package/dist/schemas/inventory.js.map +1 -0
  277. package/dist/schemas/issues.d.ts +324 -0
  278. package/dist/schemas/issues.d.ts.map +1 -0
  279. package/dist/schemas/issues.js +107 -0
  280. package/dist/schemas/issues.js.map +1 -0
  281. package/dist/schemas/logs.d.ts +67 -0
  282. package/dist/schemas/logs.d.ts.map +1 -0
  283. package/dist/schemas/logs.js +54 -0
  284. package/dist/schemas/logs.js.map +1 -0
  285. package/dist/schemas/loops.d.ts +415 -0
  286. package/dist/schemas/loops.d.ts.map +1 -0
  287. package/dist/schemas/loops.js +188 -0
  288. package/dist/schemas/loops.js.map +1 -0
  289. package/dist/schemas/maintenance.d.ts +618 -0
  290. package/dist/schemas/maintenance.d.ts.map +1 -0
  291. package/dist/schemas/maintenance.js +222 -0
  292. package/dist/schemas/maintenance.js.map +1 -0
  293. package/dist/schemas/marketplace.d.ts +64 -0
  294. package/dist/schemas/marketplace.d.ts.map +1 -0
  295. package/dist/schemas/marketplace.js +17 -0
  296. package/dist/schemas/marketplace.js.map +1 -0
  297. package/dist/schemas/panels.d.ts +61 -0
  298. package/dist/schemas/panels.d.ts.map +1 -0
  299. package/dist/schemas/panels.js +51 -0
  300. package/dist/schemas/panels.js.map +1 -0
  301. package/dist/schemas/personas.d.ts +122 -0
  302. package/dist/schemas/personas.d.ts.map +1 -0
  303. package/dist/schemas/personas.js +102 -0
  304. package/dist/schemas/personas.js.map +1 -0
  305. package/dist/schemas/plan-limits.d.ts +172 -0
  306. package/dist/schemas/plan-limits.d.ts.map +1 -0
  307. package/dist/schemas/plan-limits.js +126 -0
  308. package/dist/schemas/plan-limits.js.map +1 -0
  309. package/dist/schemas/ports.d.ts +71 -0
  310. package/dist/schemas/ports.d.ts.map +1 -0
  311. package/dist/schemas/ports.js +42 -0
  312. package/dist/schemas/ports.js.map +1 -0
  313. package/dist/schemas/provider-oauth.d.ts +128 -0
  314. package/dist/schemas/provider-oauth.d.ts.map +1 -0
  315. package/dist/schemas/provider-oauth.js +91 -0
  316. package/dist/schemas/provider-oauth.js.map +1 -0
  317. package/dist/schemas/provider-subscriptions.d.ts +9 -0
  318. package/dist/schemas/provider-subscriptions.d.ts.map +1 -0
  319. package/dist/schemas/provider-subscriptions.js +3 -0
  320. package/dist/schemas/provider-subscriptions.js.map +1 -0
  321. package/dist/schemas/public.d.ts +32 -0
  322. package/dist/schemas/public.d.ts.map +1 -0
  323. package/dist/schemas/public.js +29 -0
  324. package/dist/schemas/public.js.map +1 -0
  325. package/dist/schemas/push.d.ts +55 -0
  326. package/dist/schemas/push.d.ts.map +1 -0
  327. package/dist/schemas/push.js +60 -0
  328. package/dist/schemas/push.js.map +1 -0
  329. package/dist/schemas/secrets.d.ts +86 -0
  330. package/dist/schemas/secrets.d.ts.map +1 -0
  331. package/dist/schemas/secrets.js +51 -0
  332. package/dist/schemas/secrets.js.map +1 -0
  333. package/dist/schemas/sessions.d.ts +32 -0
  334. package/dist/schemas/sessions.d.ts.map +1 -0
  335. package/dist/schemas/sessions.js +11 -0
  336. package/dist/schemas/sessions.js.map +1 -0
  337. package/dist/schemas/settings.d.ts +554 -0
  338. package/dist/schemas/settings.d.ts.map +1 -0
  339. package/dist/schemas/settings.js +263 -0
  340. package/dist/schemas/settings.js.map +1 -0
  341. package/dist/schemas/share.d.ts +49 -0
  342. package/dist/schemas/share.d.ts.map +1 -0
  343. package/dist/schemas/share.js +26 -0
  344. package/dist/schemas/share.js.map +1 -0
  345. package/dist/schemas/shared.d.ts +22 -0
  346. package/dist/schemas/shared.d.ts.map +1 -0
  347. package/dist/schemas/shared.js +16 -0
  348. package/dist/schemas/shared.js.map +1 -0
  349. package/dist/schemas/system.d.ts +86 -0
  350. package/dist/schemas/system.d.ts.map +1 -0
  351. package/dist/schemas/system.js +64 -0
  352. package/dist/schemas/system.js.map +1 -0
  353. package/dist/schemas/terminal.d.ts +230 -0
  354. package/dist/schemas/terminal.d.ts.map +1 -0
  355. package/dist/schemas/terminal.js +133 -0
  356. package/dist/schemas/terminal.js.map +1 -0
  357. package/dist/schemas/usage.d.ts +113 -0
  358. package/dist/schemas/usage.d.ts.map +1 -0
  359. package/dist/schemas/usage.js +91 -0
  360. package/dist/schemas/usage.js.map +1 -0
  361. package/dist/schemas/vpn.d.ts +229 -0
  362. package/dist/schemas/vpn.d.ts.map +1 -0
  363. package/dist/schemas/vpn.js +115 -0
  364. package/dist/schemas/vpn.js.map +1 -0
  365. package/dist/schemas/webext.d.ts +122 -0
  366. package/dist/schemas/webext.d.ts.map +1 -0
  367. package/dist/schemas/webext.js +45 -0
  368. package/dist/schemas/webext.js.map +1 -0
  369. package/dist/schemas/workflows.d.ts +881 -0
  370. package/dist/schemas/workflows.d.ts.map +1 -0
  371. package/dist/schemas/workflows.js +164 -0
  372. package/dist/schemas/workflows.js.map +1 -0
  373. package/dist/schemas/workspace-repos.d.ts +143 -0
  374. package/dist/schemas/workspace-repos.d.ts.map +1 -0
  375. package/dist/schemas/workspace-repos.js +87 -0
  376. package/dist/schemas/workspace-repos.js.map +1 -0
  377. package/dist/schemas/workspace-search.d.ts +170 -0
  378. package/dist/schemas/workspace-search.d.ts.map +1 -0
  379. package/dist/schemas/workspace-search.js +85 -0
  380. package/dist/schemas/workspace-search.js.map +1 -0
  381. package/dist/schemas/workspace-setup.d.ts +48 -0
  382. package/dist/schemas/workspace-setup.d.ts.map +1 -0
  383. package/dist/schemas/workspace-setup.js +26 -0
  384. package/dist/schemas/workspace-setup.js.map +1 -0
  385. package/dist/schemas/workspace-tree.d.ts +120 -0
  386. package/dist/schemas/workspace-tree.d.ts.map +1 -0
  387. package/dist/schemas/workspace-tree.js +111 -0
  388. package/dist/schemas/workspace-tree.js.map +1 -0
  389. package/dist/webext-links.d.ts +14 -0
  390. package/dist/webext-links.d.ts.map +1 -0
  391. package/dist/webext-links.js +25 -0
  392. package/dist/webext-links.js.map +1 -0
  393. package/dist/webext-protocol.d.ts +8 -0
  394. package/dist/webext-protocol.d.ts.map +1 -0
  395. package/dist/webext-protocol.js +7 -0
  396. package/dist/webext-protocol.js.map +1 -0
  397. package/dist/workflow-faults.d.ts +1 -1
  398. package/dist/workflow-faults.d.ts.map +1 -1
  399. package/dist/workspace-state.d.ts +12 -8
  400. package/dist/workspace-state.d.ts.map +1 -1
  401. package/dist/workspace-state.js +15 -10
  402. package/dist/workspace-state.js.map +1 -1
  403. package/package.json +19 -8
  404. package/src/agent-catalog.test.ts +56 -55
  405. package/src/agent-catalog.ts +33 -33
  406. package/src/capability-ledger.test.ts +11 -2
  407. package/src/chores/chores.test.ts +1 -1
  408. package/src/chores/chores.ts +67 -2
  409. package/src/chores/probes.test.ts +65 -0
  410. package/src/chores/probes.ts +133 -1
  411. package/src/chores/stack.test.ts +19 -0
  412. package/src/chores/stack.ts +19 -3
  413. package/src/chores/verdict.test.ts +40 -20
  414. package/src/chores/verdict.ts +1 -1
  415. package/src/command-classes.test.ts +445 -0
  416. package/src/command-classes.ts +468 -0
  417. package/src/contracts/activity.contract.ts +1 -1
  418. package/src/contracts/agent.contract.ts +4 -13
  419. package/src/contracts/agents.contract.ts +6 -6
  420. package/src/contracts/automations.contract.ts +2 -2
  421. package/src/contracts/capabilities.contract.ts +3 -4
  422. package/src/contracts/chores.contract.ts +2 -1
  423. package/src/contracts/ci.contract.ts +2 -2
  424. package/src/contracts/claude.contract.ts +2 -2
  425. package/src/contracts/cursor.contract.ts +2 -2
  426. package/src/contracts/drafts.contract.ts +2 -1
  427. package/src/contracts/endpoints.contract.ts +2 -1
  428. package/src/contracts/exit.contract.ts +2 -1
  429. package/src/contracts/extensions.contract.ts +8 -7
  430. package/src/contracts/git.contract.ts +19 -18
  431. package/src/contracts/grok.contract.ts +2 -1
  432. package/src/contracts/history.contract.ts +2 -1
  433. package/src/contracts/host.contract.ts +4 -1
  434. package/src/contracts/intentic.contract.ts +2 -1
  435. package/src/contracts/inventory.contract.ts +1 -1
  436. package/src/contracts/issues.contract.ts +60 -0
  437. package/src/contracts/logs.contract.ts +7 -1
  438. package/src/contracts/loops.contract.ts +2 -2
  439. package/src/contracts/panels.contract.ts +2 -1
  440. package/src/contracts/personas.contract.ts +3 -3
  441. package/src/contracts/ports.contract.ts +3 -2
  442. package/src/contracts/prepush.contract.ts +2 -1
  443. package/src/contracts/providers.contract.ts +2 -1
  444. package/src/contracts/public.contract.ts +3 -2
  445. package/src/contracts/push.contract.ts +2 -1
  446. package/src/contracts/runner.contract.ts +18 -2
  447. package/src/contracts/secrets.contract.ts +2 -1
  448. package/src/contracts/sessions.contract.ts +1 -1
  449. package/src/contracts/settings.contract.ts +3 -9
  450. package/src/contracts/share.contract.ts +3 -2
  451. package/src/contracts/skills.contract.ts +2 -1
  452. package/src/contracts/system.contract.ts +6 -9
  453. package/src/contracts/translator.contract.ts +4 -1
  454. package/src/contracts/usage.contract.ts +1 -1
  455. package/src/contracts/vpn.contract.ts +2 -8
  456. package/src/contracts/webext.contract.ts +37 -0
  457. package/src/contracts/workflows.contract.ts +2 -2
  458. package/src/contracts/workspace.contract.ts +10 -12
  459. package/src/conversation-ids.test.ts +1 -1
  460. package/src/credential-material.test.ts +120 -0
  461. package/src/credential-material.ts +100 -0
  462. package/src/definition-action.ts +8 -0
  463. package/src/definition.ts +74 -10
  464. package/src/events.ts +84 -22
  465. package/src/fast-tier.ts +1 -1
  466. package/src/history-state.ts +17 -0
  467. package/src/host-protocol.ts +1 -1
  468. package/src/hostnames.test.ts +2 -2
  469. package/src/hostnames.ts +18 -2
  470. package/src/index.ts +65 -1
  471. package/src/listener-protocol.ts +1 -1
  472. package/src/quick-model.ts +1 -1
  473. package/src/routes.test.ts +4 -2
  474. package/src/runner-protocol.ts +35 -5
  475. package/src/runtime-state.ts +16 -0
  476. package/src/schemas/activity.ts +123 -0
  477. package/src/schemas/agent.ts +422 -0
  478. package/src/schemas/agents.ts +802 -0
  479. package/src/schemas/automations.ts +522 -0
  480. package/src/schemas/capabilities.ts +729 -0
  481. package/src/schemas/ci.ts +235 -0
  482. package/src/schemas/claude-gate.ts +13 -0
  483. package/src/schemas/codebase-health.ts +64 -0
  484. package/src/schemas/computers.ts +287 -0
  485. package/src/schemas/drafts.ts +108 -0
  486. package/src/schemas/environment.ts +276 -0
  487. package/src/schemas/exit.ts +222 -0
  488. package/src/schemas/extension-updates.ts +324 -0
  489. package/src/schemas/fast-mode.ts +8 -0
  490. package/src/schemas/git-history.ts +265 -0
  491. package/src/schemas/git.ts +430 -0
  492. package/src/schemas/history.ts +112 -0
  493. package/src/schemas/hosts.ts +37 -0
  494. package/src/schemas/intentic.ts +2 -0
  495. package/src/schemas/internal.ts +17 -0
  496. package/src/schemas/inventory.ts +68 -0
  497. package/src/schemas/issues.ts +279 -0
  498. package/src/schemas/logs.ts +96 -0
  499. package/src/schemas/loops.ts +401 -0
  500. package/src/schemas/maintenance.ts +471 -0
  501. package/src/schemas/marketplace.ts +23 -0
  502. package/src/schemas/panels.ts +99 -0
  503. package/src/schemas/personas.ts +281 -0
  504. package/src/schemas/plan-limits.ts +255 -0
  505. package/src/schemas/ports.ts +84 -0
  506. package/src/schemas/provider-oauth.ts +191 -0
  507. package/src/schemas/provider-subscriptions.ts +11 -0
  508. package/src/schemas/public.ts +52 -0
  509. package/src/schemas/push.ts +112 -0
  510. package/src/schemas/secrets.ts +68 -0
  511. package/src/schemas/sessions.ts +16 -0
  512. package/src/schemas/settings.ts +964 -0
  513. package/src/schemas/share.ts +71 -0
  514. package/src/schemas/shared.ts +32 -0
  515. package/src/schemas/system.ts +156 -0
  516. package/src/schemas/terminal.ts +288 -0
  517. package/src/schemas/usage.ts +303 -0
  518. package/src/{schemas.test.ts → schemas/version-seam.test.ts} +4 -2
  519. package/src/schemas/vpn.ts +215 -0
  520. package/src/schemas/webext.ts +108 -0
  521. package/src/schemas/workflows.ts +413 -0
  522. package/src/schemas/workspace-repos.ts +123 -0
  523. package/src/schemas/workspace-search.ts +141 -0
  524. package/src/schemas/workspace-setup.ts +43 -0
  525. package/src/schemas/workspace-tree.ts +234 -0
  526. package/src/title.test.ts +1 -1
  527. package/src/tunnel-ids.test.ts +3 -1
  528. package/src/webext-links.ts +90 -0
  529. package/src/webext-protocol.ts +27 -0
  530. package/src/workflow-faults.test.ts +1 -1
  531. package/src/workflow-faults.ts +1 -1
  532. package/src/workspace-state.test.ts +6 -4
  533. package/src/workspace-state.ts +35 -50
  534. package/dist/schemas.d.ts +0 -9909
  535. package/dist/schemas.d.ts.map +0 -1
  536. package/dist/schemas.js +0 -4288
  537. package/dist/schemas.js.map +0 -1
  538. package/src/schemas.ts +0 -10090
@@ -0,0 +1,802 @@
1
+ // agents: the conversation fleet
2
+ import { z } from "zod";
3
+ import { AgentHarnessSchema, AgentOriginSchema, AgentProviderSchema, ForkedFromSchema } from "./agent.js";
4
+ import { LoopStateSchema } from "./loops.js";
5
+ // A "fleet agent" is any conversation with a registry entry, keyed by its conversationId. Isolated ones own a
6
+ // git worktree (branch agent/<id> in every workspace repo); workspace conversations have no branch. The fleet
7
+ // surface shows both through the same status/activity/cost lifecycle.
8
+
9
+ // idle/running/awaiting are the turn lifecycle (awaiting = paused on a plan approval or question); ready /
10
+ // landed / conflict are outcomes of the land flow, `ready` is a clean completion whose delta stayed on the
11
+ // agent's branch because auto-land is off (the user lands it deliberately, from the review panel or the card);
12
+ // error is a terminal turn failure surfaced on the card.
13
+ //
14
+ // `interrupted` is the turn that never got to report ANY of those: the daemon died under it (a container
15
+ // rebuild, a crash, an OOM kill), taking the provider process and the whole runtime half of the fleet, status,
16
+ // attention flags, the park a question raised, with it. It exists because the alternative is worse than
17
+ // unlabelled: without it such a turn rehydrates as `idle`, which is the resting status of a turn that finished
18
+ // CLEANLY, so the board files a killed agent under Finished and the question it was holding disappears with the
19
+ // process that asked it. See agents-store.ts, this is the status a live turn leaves on disk.
20
+ //
21
+ /* `stopping` and `stopped` are the two halves of a user's Stop, and they exist because a hard-cancel is NOT
22
+ * instant: /agent/stop aborts the provider and then waits for the turn's generator to unwind (worktree and
23
+ * registry cleanup), which is seconds of real time. For that whole window the runtime half still said
24
+ * `running`, so every surface kept its spinner turning on a turn the user had already killed, and then the
25
+ * card jumped to a settled state out of nowhere. `stopping` is what the daemon knows the instant the abort
26
+ * lands, published immediately so the press has a visible result; `stopped` is where the turn comes to rest.
27
+ *
28
+ * `dismissing` IS THAT SAME WINDOW FOR THE OTHER ENDING A PERSON CHOOSES, waving away the question the turn was
29
+ * parked on, and it is a status of its own for one reason: the two endings come to rest in different places.
30
+ * A Stop leaves half-written work somebody has to pick up, so its card settles in Attention; a dismissal is
31
+ * "I am done with this", so its card settles in Finished. Published as one value, the unwind could not say
32
+ * which, so every surface had to park the card where it already was and move it once the turn had ACTUALLY
33
+ * finished, seconds later, and the daemon papered over the dismissal half by suppressing the broadcast that
34
+ * would have filed it under Active in the meantime — a bet on nothing else broadcasting inside that window,
35
+ * which a second agent's frame lost routinely. Said apart, the destination is known at the press: each card
36
+ * moves once, immediately, to the lane it is going to end up in, and no surface has to guess or suppress.
37
+ *
38
+ * `stopped` is deliberately its own value rather than `interrupted` or `error`. Not `error`, which is what a
39
+ * stopped turn used to report (every provider adapter surfaces the abort's unwind as an error frame), a card
40
+ * accusing the user's own deliberate press of being a failure. Not `interrupted` either: that one means the
41
+ * daemon died under the turn, and a boot pass may re-run it, which is precisely what must never happen to a
42
+ * turn a person chose to end. */
43
+ /* `resuming` is the same argument as `stopping`, made about the other end of a turn's life: the turn was killed
44
+ * by something the daemon is ALREADY undoing (a rotated credential being re-minted, a provider outage being
45
+ * waited out, turn-resume.ts), so it has stopped without having ended. The gap is real time, a few seconds for
46
+ * a re-mint, minutes for an outage's backoff, and for that whole window the turn reported the resting `idle`,
47
+ * which the board reads as finished. So a 401 that nobody caused and nobody has to fix filed the card under
48
+ * Finished and then pulled it back into Active a moment later, which is the fleet contradicting itself in front
49
+ * of the user about work that never stopped being in progress.
50
+ *
51
+ * Never persisted (see PersistedAgentStatusSchema): what is coming back is remembered in the daemon's memory
52
+ * alone, and a daemon that dies mid-wait takes the resume with it, so the card falls back to the ending its
53
+ * killed turn actually wrote and reads as finished, which by then is true. Nothing is left to bring it back. */
54
+ export const AgentStatusSchema = z.enum([
55
+ "idle",
56
+ "running",
57
+ "awaiting",
58
+ "stopping",
59
+ "dismissing",
60
+ "stopped",
61
+ "resuming",
62
+ "ready",
63
+ "landed",
64
+ "conflict",
65
+ "error",
66
+ "interrupted",
67
+ ]);
68
+ export type AgentStatus = z.infer<typeof AgentStatusSchema>;
69
+ // The card's live activity snippet: the last tool the agent used (with its target) and the in-progress todo.
70
+ export const AgentActivitySchema = z.object({
71
+ tool: z.string().optional().describe("The last tool it reached for."),
72
+ target: z.string().optional().describe("What it reached for that tool with: a file, a command, a URL."),
73
+ todo: z.string().optional().describe("The item on its own list that it is working through."),
74
+ });
75
+ export type AgentActivity = z.infer<typeof AgentActivitySchema>;
76
+ // Which "needs you" flags are raised, the fleet badge aggregates these across all agents.
77
+ export const AgentAttentionSchema = z.object({
78
+ plan: z.boolean().describe("It has proposed a plan and is waiting for a yes."),
79
+ question: z.boolean().describe("It has asked you something."),
80
+ permission: z.boolean().describe("It wants to use a tool it needs permission for."),
81
+ // A priced service run parked on the owner's click (platform/service-offer.ts), the one card where
82
+ // waiting costs the agent its whole call, so the lane says "spend approval" rather than a generic pause.
83
+ service: z
84
+ .boolean()
85
+ .describe("It wants to spend money on a paid service and is waiting for approval. The one pause where waiting costs it the whole call."),
86
+ // A missing capability parked on the owner's setup (capabilities/capability-offer.ts), the agent is
87
+ // waiting for something to be connected, so the lane can say "setup needed" rather than a generic pause.
88
+ capability: z.boolean().describe("It needs something connected that is not connected yet."),
89
+ conflict: z.boolean().describe("Its work cannot be merged without somebody resolving a clash."),
90
+ });
91
+ export type AgentAttention = z.infer<typeof AgentAttentionSchema>;
92
+ /* WHAT A LANDING IS CALLED, the commit message drafted from the landed diff (agents/landed-subject.ts), and
93
+ * the whole of it: a subject, and the two trailer sentences a repo that keeps a changelog gets.
94
+ *
95
+ * ONE SHAPE, TWO CARRIERS, and that is the reason it is a schema of its own rather than three fields written
96
+ * out twice. The same sentence reaches the Changes panel down two roads, the fleet roster, which is live and
97
+ * drops archived agents, and the review, which is a rescan and outlives the card (OriginAgent), so the panel
98
+ * takes whichever answers first and must not care which one did. Two hand-kept copies of these three fields
99
+ * would be two things to keep in step, and the one that drifted would be the one nobody was looking at.
100
+ *
101
+ * THE PARTS STAY APART. A subject is one bounded line everywhere it is stored and shown; the notes are
102
+ * sentences for the people who read a release. Flattening them into one string would produce a run-on subject
103
+ * in the commit box and a truncated note in the changelog, so they are joined only at the moment of the fill,
104
+ * where they become a commit message with its trailers and nowhere before it. */
105
+ export const LandedMessageSchema = z.object({
106
+ /* WHAT THIS AGENT'S LANDED WORK DID, as a commit subject, written from the landed diff when the work
107
+ * arrived, which is why it can say what a title cannot.
108
+ *
109
+ * A title names the ASK, and it is written once, from the opening prompt, a second into the first turn. A
110
+ * conversation that opens "audit the review panel" and then spends four turns fixing what the audit found
111
+ * still answers to "Review panel · audit", a good name for the session and a wrong subject for the
112
+ * commit. This is read off the code instead, so it describes the change the user is about to record. */
113
+ subject: z
114
+ .string()
115
+ .describe(
116
+ "One line saying what the merged work did, read off the code rather than off the opening request. A conversation that asks for an audit and then spends four turns fixing what it found needs a subject about the fixes.",
117
+ ),
118
+ /* THE SAME LANDING, SAID TO A USER, the `Release-Note:` sentence the chip files in under the subject, for
119
+ * a repo that keeps a changelog (SandboxSettings.changelogRepos).
120
+ *
121
+ * Usually absent, and that is the design: most landings change nothing a user would notice, and the model
122
+ * is told to omit the note for those rather than to invent one. */
123
+ note: z
124
+ .string()
125
+ .optional()
126
+ .describe(
127
+ "The same change said to somebody who uses the product, for a repository that keeps a changelog. Usually absent, because most changes are not ones a user would notice.",
128
+ ),
129
+ /* WHAT THE SAME LANDING TAKES AWAY, the `Breaking-Note:` sentence, filed as its own trailer so the
130
+ * release harvest can put it under "Breaking changes" and the update card can warn with it before the
131
+ * update rather than after. Nearly always absent: the model is told a breaking note is for removals only,
132
+ * and to omit it when in doubt, except when the landing shrinks a wire-contract lock, where the sentence
133
+ * is REQUIRED and mechanically guaranteed (the daemon's git/contract-shrink.ts) rather than judged. */
134
+ breaking: z
135
+ .string()
136
+ .optional()
137
+ .describe("What this change takes away, for anything already relying on it. Nearly always absent: it is for removals, not for additions."),
138
+ });
139
+ export type LandedMessage = z.infer<typeof LandedMessageSchema>;
140
+ /* ONE MODEL'S TURN IN THE DRAFTING WALK, asked, and what became of the ask. The quick-model chain tries the
141
+ * connected models in order (agent/quick-model.ts), and each rung ends one of four ways:
142
+ * asking , in flight right now; `ms` absent because it is still being spent.
143
+ * answered, it wrote the sentence, in `ms`.
144
+ * refused , it failed or declined, in `ms`, with its own words in `reason`.
145
+ * skipped , not asked at all: it refused within the last few minutes and the walk stepped over it, with the
146
+ * reason it gave back then. Skipping is the memo working, and it reads as such.
147
+ * The steps arrive in the order they were spent, so the list IS the timeline. */
148
+ export const LandedMessageStepSchema = z.object({
149
+ provider: z.string().min(1).describe("Which provider was asked."),
150
+ model: z.string().min(1).describe("Which of its models."),
151
+ status: z
152
+ .enum(["asking", "answered", "refused", "skipped"])
153
+ .describe("How this one went. Skipped means it was not asked at all, because it refused a few minutes ago and the walk stepped over it."),
154
+ // When this rung started being asked, ms since epoch, what an in-flight step's ticking "12s…" is measured
155
+ // from, client-side, without a frame per second. Absent for `skipped`, which cost no time at all.
156
+ at: z.number().optional().describe("When it started being asked, in milliseconds. Absent for one that was skipped, which cost no time."),
157
+ ms: z.number().optional().describe("How long it took. Absent while it is still being asked."),
158
+ reason: z.string().optional().describe("Why it refused, in its own words."),
159
+ });
160
+ export type LandedMessageStep = z.infer<typeof LandedMessageStepSchema>;
161
+ /* THE FULL ACCOUNT OF ONE LANDING'S COMMIT MESSAGE BEING DRAFTED, everything a user waiting at the commit box
162
+ * is owed: that the draft started, which models have been asked, how each one went, and how it ended.
163
+ *
164
+ * `outcome` is absent while the draft is RUNNING, which is what "a sentence is on its way" now means, the
165
+ * boolean flag this replaces could say only that, and nothing else this schema carries. Ended, it is:
166
+ * written, the sentence is on the card (`landedMessage`) and in the box; the steps say who wrote it.
167
+ * failed , nothing usable came back. The steps carry each model's own words; `reason` is the one-line
168
+ * account for the surfaces with a single line to spend (an answer that was itself a refusal
169
+ * sentence, or the whole chain spent).
170
+ * An empty `steps` with no outcome is the moment before the first model is asked, the diff is being read. */
171
+ export const LandedMessageDraftSchema = z.object({
172
+ startedAt: z.number().describe("When the drafting began, in milliseconds."),
173
+ steps: z
174
+ .array(LandedMessageStepSchema)
175
+ .describe(
176
+ "Each model that was asked, in the order they were spent, so the list is the timeline. Empty with no outcome means the diff is still being read.",
177
+ ),
178
+ outcome: z.enum(["written", "failed"]).optional().describe("How it ended. Absent means it is still going."),
179
+ reason: z
180
+ .string()
181
+ .optional()
182
+ .describe("The one-line account of a failure, for a screen with one line to spend. The steps carry each model's own words."),
183
+ finishedAt: z.number().optional().describe("When it ended, in milliseconds."),
184
+ });
185
+ export type LandedMessageDraft = z.infer<typeof LandedMessageDraftSchema>;
186
+ export const AgentSummarySchema = z.object({
187
+ // The conversationId.
188
+ id: z.string().describe("The conversation id, which is how every other call addresses it."),
189
+ sessionId: z.string().optional().describe("The provider session behind the last turn. It is retired whenever the model or account changes."),
190
+ // First prompt, sanitized to one bounded line.
191
+ title: z.string().optional().describe("What to call it: the first prompt cut to one line, unless somebody renamed it."),
192
+ status: AgentStatusSchema.describe(
193
+ "What it is doing. Stopping and stopped are the two halves of somebody pressing stop, because a cancel is not instant; dismissing is the same window for a question waved away, which ends the turn too but owes the user nothing; resuming means the sandbox is already putting right whatever killed the turn.",
194
+ ),
195
+ /* WHY THE LAST TURN FAILED, the sentence it died on, carried beside the `error` status because that word
196
+ * on its own is not an answer. A session refused on its first request (an organization with Claude Code
197
+ * switched off, a spent allowance, a model the endpoint has never heard of) reached every surface as a grey
198
+ * "error" and a link into the transcript, so the one place the reason existed was the dead conversation
199
+ * itself, which is exactly where an unattended run, started from a fan-out nobody is watching, is least
200
+ * likely to be read. Absent unless the last turn ended in failure, and cleared the moment it runs again. */
201
+ failure: z
202
+ .string()
203
+ .optional()
204
+ .describe(
205
+ "Why the last turn failed, in the words it died on. Absent unless it did, and cleared the moment it runs again. Carried here because the word error on its own is not an answer, least of all for a run nobody was watching.",
206
+ ),
207
+ provider: AgentProviderSchema.describe("Which model provider it runs on."),
208
+ harness: AgentHarnessSchema.describe("Which agentic loop it runs on."),
209
+ // Which machine its turns execute on: a paired runner's id, absent for this sandbox (runners/). Latched
210
+ // with the conversation, so a card can say where the work is happening without asking anything.
211
+ runner: z.string().optional().describe("The runner this conversation runs on. Absent means this sandbox."),
212
+ // What the agent's last turn ran with, the model, its reasoning effort, whether extended thinking was on,
213
+ // and whether fast speed was asked for. Recorded per agent because they are facts about THIS conversation: a
214
+ // client opening it seeds its composer from them, rather than from whatever that browser last picked in some
215
+ // other tab. Absent for an agent whose turns predate the record (model has always been kept; the rest are
216
+ // newer). `fast` is what was REQUESTED, not what was served, the served answer belongs to a turn and rides
217
+ // its `fast_mode` frame, while this is the composer's memory of the user's own choice.
218
+ model: z
219
+ .string()
220
+ .optional()
221
+ .describe(
222
+ "What its last turn ran with. Kept per conversation so opening it restores the choices made in it, rather than whatever some other tab last picked.",
223
+ ),
224
+ effort: z.string().optional().describe("How hard that turn was told to think."),
225
+ thinking: z.boolean().optional().describe("Whether that turn showed its reasoning."),
226
+ fast: z.boolean().optional().describe("Whether that turn asked for higher speed. What was asked for, not what was served."),
227
+ /* WHAT THE COMPLEXITY JUDGE MADE OF THE LAST TURN HERE, mirrored from the persisted entry (agents-store.ts
228
+ * `tier`) so a client opening the conversation tomorrow can seed its composer preview with the one judge
229
+ * input a draft cannot contain (prompt-complexity.ts `afterHardTurn`). The JUDGEMENT, never what ran, for
230
+ * the reason the store states: what ran is a fact about configuration, the next turn is asking about the
231
+ * difficulty of the work. Absent ⇒ nothing judged yet. */
232
+ tier: z
233
+ .enum(["fast", "standard"])
234
+ .optional()
235
+ .describe("How hard its last turn looked to the complexity judge. What the next turn's preview needs, not what actually ran."),
236
+ // The conversation's standing "keep every turn on my pick" choice, the composer's memory of it, the same
237
+ // shape as `fast` above: what was asked for, restored into the composer on open, sent back on every turn.
238
+ tierHold: z
239
+ .boolean()
240
+ .optional()
241
+ .describe("Whether this conversation is pinned to the picked model, so a turn that looks simple is never moved to a cheaper one."),
242
+ account: z.string().optional().describe("Which connected account paid for it."),
243
+ // The worktree branch (agent/<id>); absent for a non-isolated (main-tree) conversation.
244
+ branch: z.string().optional().describe("The branch its private copy works on. Absent for a conversation that works directly in the shared tree."),
245
+ // This agent's own answer to "land automatically at turn completion?", an explicit per-agent override of
246
+ // the sandbox-wide `autoLand` setting. ABSENT ⇒ inherit, which is the common case and the one that keeps
247
+ // the global toggle meaningful: an agent that never expressed an opinion follows the sandbox wherever it
248
+ // is pointed next. Written by `agents.autoLand`; the UI shows the EFFECTIVE value (this ?? the setting).
249
+ autoLand: z
250
+ .boolean()
251
+ .optional()
252
+ .describe(
253
+ "This conversation's own answer to whether its work merges automatically. Absent means it follows the sandbox-wide setting, which is the common case.",
254
+ ),
255
+ /* This agent's own answer to "re-run my turn when the model provider was what failed?", the same
256
+ * two-level shape as `autoLand` above, and here for a sharper reason than symmetry.
257
+ *
258
+ * The press that writes this is offered INSIDE one conversation, at the moment that conversation's turn
259
+ * died, and what a person means by it is "finish THIS piece of work". It used to write the sandbox-wide
260
+ * setting, so one impatient click at 2 a.m. quietly armed every agent on the board, a scope
261
+ * nothing on screen had asked about. So the chat's offer writes this, the settings toggle writes the
262
+ * default, and the two stay honestly different things.
263
+ *
264
+ * ABSENT ⇒ inherit the sandbox setting, which is what keeps that default meaningful: a conversation that
265
+ * never expressed an opinion follows the sandbox wherever it is pointed next. Written by
266
+ * `agents.resumeAfterOutage`; every surface shows the EFFECTIVE value (this ?? the setting). */
267
+ resumeAfterOutage: z.boolean().optional(),
268
+ // A collaborator asked for this agent's work to be landed (agents.requestLand), collaborators may drive
269
+ // agents but not merge into the main tree, so the ask rides the summary where every maintainer's board
270
+ // sees it. Cleared by the land or discard that answers it. Absent ⇒ nobody is waiting.
271
+ landRequested: z
272
+ .object({
273
+ email: z.string().describe("Who asked."),
274
+ name: z.string().optional().describe("Their display name."),
275
+ at: z.number().describe("When they asked, in milliseconds."),
276
+ })
277
+ .optional()
278
+ .describe(
279
+ "A collaborator has asked a maintainer to merge this work. Cleared by whichever merge or discard answers it. Absent means nobody is waiting.",
280
+ ),
281
+ // Present when the conversation was opened by an outside message rather than by the user (see
282
+ // AgentOriginSchema), the card's provenance line. Absent ⇒ the user started it.
283
+ origin: AgentOriginSchema.optional().describe(
284
+ "Where the conversation came from when nobody typed it: a chat mention, a visitor's message, a webhook. Absent means a person started it.",
285
+ ),
286
+ /* Where this conversation was cut from, when it was cut from another. Recorded once, from the fork's very
287
+ * first turn, and never cleared, it is the relationship, not a pending state.
288
+ *
289
+ * It rides the SUMMARY rather than living in the client's tabs because a fork and its source are two chats
290
+ * that are obviously related and, without this, had no way to say how: the link has to survive closing
291
+ * either tab and reopening it from history, and it has to be readable from the OTHER side, the source's
292
+ * own transcript marks its cut points by looking for the conversations that name it. */
293
+ forkedFrom: ForkedFromSchema.optional().describe(
294
+ "The conversation this one was cut from. Recorded once and never cleared: it is the relationship, not a pending state.",
295
+ ),
296
+ // The ROOT repo's short base sha, the checkout moment's display identity. Per-repo bases stay
297
+ // daemon-internal (agents.diff already reports against them).
298
+ base: z.string().optional().describe("The commit its private copy started from, shortened."),
299
+ costUsd: z.number().optional().describe("What it has cost so far, in dollars. A helper agent's spend is its own and is not folded in here."),
300
+ inputTokens: z.number().optional().describe("Tokens sent."),
301
+ outputTokens: z.number().optional().describe("Tokens received."),
302
+ contextTokens: z.number().optional().describe("How much of the window the conversation currently fills."),
303
+ contextWindow: z.number().optional().describe("How large that window is."),
304
+ activity: AgentActivitySchema.optional().describe("What it is doing at this moment."),
305
+ /* THE WHOLE STORY OF THIS LANDING'S COMMIT MESSAGE BEING WRITTEN, present from the moment the land starts
306
+ * the draft, updated on every transition, and kept after it ends until the next land replaces it.
307
+ *
308
+ * This used to be one boolean ("a model is writing"), and a boolean is exactly one fact short of every
309
+ * question the wait raises: WHICH model, for how long, what refused and in what words, what finally
310
+ * answered. All of that was known in the daemon and thrown away at the door, a first-pinned model that
311
+ * burned 58 seconds refusing on every landing had to be caught by watching CLI processes by hand, because
312
+ * nothing on any screen could have shown it.
313
+ *
314
+ * Runtime only: nothing about it is persisted, so a daemon restart forgets it. That is correct rather than
315
+ * lossy, a restart also killed the draft it would have been describing. */
316
+ landedMessageDraft: LandedMessageDraftSchema.optional().describe(
317
+ "The whole story of this merge's commit message being written: which models were asked, how long each took, what refused and in what words. Forgotten on restart, which is right, because a restart also killed the drafting it describes.",
318
+ ),
319
+ /* AND THE SENTENCE ITSELF, once the flag above clears, what this agent's landed work is called, for the
320
+ * Changes panel's "From" chip to file into the commit box.
321
+ *
322
+ * IT RIDES THE ROSTER because the roster is the channel that is already live for it. The review carries the
323
+ * same fact (OriginAgent.subject) and has to, for an archived agent whose lines are still in the tree, but
324
+ * the review is a workspace-wide rescan, coalesced daemon-side and refetched only when something asks, and
325
+ * this sentence arrives ALONE, seconds after the work it describes, with nothing else moving. Every link in
326
+ * that chain has to hold for a message that exists to become a message the user can see, and when one of
327
+ * them doesn't, the box stays empty with nothing to say why, while the flag above, which travels on THIS
328
+ * frame, has already told them a sentence was coming.
329
+ *
330
+ * So the fact goes where the promise went. Same push, same instant: the frame that ends `landedMessageDraft`
331
+ * is the frame that carries the answer, which is also what makes "your commit message is ready" honest.
332
+ *
333
+ * Absent for every agent that has not landed, and for a landing nothing could be written about. Replaced
334
+ * wholesale by the next land, the claim grows and so does the sentence about it. */
335
+ landedMessage: LandedMessageSchema.optional().describe(
336
+ "What this conversation's merged work is called, once the drafting above has finished. It arrives on the same push that ends the draft, so the promise and the answer travel together.",
337
+ ),
338
+ // Present while a turn runs: its start, ms since epoch.
339
+ startedAt: z.number().optional().describe("When the running turn started, in milliseconds. Absent when none is running."),
340
+ updatedAt: z.number().describe("When it last did something, in milliseconds. Reading it does not count."),
341
+ // When the agent was last OPENED, ms since epoch, the unread badge's reference point (`updatedAt >
342
+ // seenAt` ⇒ the agent has done something you haven't looked at). Absent ⇒ never opened. Daemon-side on
343
+ // purpose: read state is a fact about the WORK, not about one browser profile, so clearing site data or
344
+ // picking up the phone must not resurrect every badge.
345
+ seenAt: z
346
+ .number()
347
+ .optional()
348
+ .describe(
349
+ "When somebody last opened it, in milliseconds. Newer activity than this is what makes it unread. Kept by the sandbox rather than by a browser, so clearing site data or picking up a phone does not resurrect every badge.",
350
+ ),
351
+ attention: AgentAttentionSchema.describe("Which kinds of waiting-for-you it is doing."),
352
+ // Completed turns and lifetime tool calls, the card's msgs/tools counters.
353
+ turns: z.number().optional().describe("Turns it has finished."),
354
+ toolUses: z.number().optional().describe("Tools it has used, over its whole life."),
355
+ /* The agents THIS agent started (SubagentSessionSchema), live and lifetime. Absent ⇒ it has never delegated,
356
+ * which is most agents, so the card's chip appears on content rather than reading "0" down the board.
357
+ *
358
+ * THE TWO HALVES COME FROM DIFFERENT PLACES, and have to: `running` is read off the live subagent registry,
359
+ * which sweeps a child five minutes after it reports and remembers nothing across a restart, while `total`
360
+ * is counted onto the agent's own entry as each child is born. Deriving both from the live registry is what
361
+ * used to take the count off a card while the agent that earned it was still on the board.
362
+ *
363
+ * It earns a place on a card because a fleet card is the answer to "what is this agent up to", and an agent
364
+ * running five children looked exactly like an agent running none: the work was real, the spend was real, and
365
+ * the board said nothing. The tokens are NOT folded into the parent's cost, a child's spend is its own, and
366
+ * the Subagents area is where it is attributed. */
367
+ subagents: z
368
+ .object({
369
+ running: z.number().describe("Helpers working right now."),
370
+ total: z.number().describe("Helpers it has started over its whole life."),
371
+ })
372
+ .optional()
373
+ .describe(
374
+ "Helper agents this one delegated to. Absent means it never has, which is most conversations. Their spend is their own and is not folded into this conversation's cost.",
375
+ ),
376
+ // The agent's cumulative output (base → branch tip across every repo), refreshed on each land,
377
+ // the card's "12 files · +412 −96" readout. Independent of what has landed.
378
+ diff: z
379
+ .object({
380
+ files: z.number().describe("Files touched."),
381
+ insertions: z.number().describe("Lines added."),
382
+ deletions: z.number().describe("Lines removed."),
383
+ })
384
+ .optional()
385
+ .describe("Everything it has written, measured from where it started. Independent of how much has been merged."),
386
+ /* HOW MUCH OF WHAT THIS AGENT LANDED IS STILL IN YOUR WORKING TREE, present only when some of it ISN'T.
387
+ *
388
+ * A land applies its delta to the main tree as uncommitted changes, so the user can discard it there like
389
+ * any other change, and every other reading on this card is measured between commits and cannot see that
390
+ * happen (landed-presence.ts). Left unsaid, the card goes on wearing a landed chip and the session menu
391
+ * goes on saying "Already in your workspace" over a tree that no longer holds it, and the next land
392
+ * carries only the NEW delta, dropping turn 2 onto a tree missing turn 1.
393
+ *
394
+ * `present` counts the landed paths still there: dirty, or committed into history, a commit is the
395
+ * strongest form of still-there, which is why this cannot be folded into the Changes panel's own
396
+ * attribution, where a commit is what ENDS the agent's claim (origins.ts).
397
+ *
398
+ * Absent is the steady state and the quiet one: an agent that never landed and an agent whose work is
399
+ * exactly where it left it both say nothing. Its PRESENCE is the signal, which is what keeps the board
400
+ * from spending a line per card on the ordinary case. */
401
+ landedPresence: z
402
+ .object({
403
+ landed: z.number().describe("Paths this conversation merged in."),
404
+ present: z.number().describe("How many of them are still there, either pending or committed."),
405
+ })
406
+ .optional()
407
+ .describe(
408
+ "Present only when some of what it merged has since been thrown away. Absent is the steady state: its presence is the signal, so an ordinary card spends no line on it.",
409
+ ),
410
+ /* The loop driving this conversation, when one is (or was), "iteration 3/12, until the suite is green".
411
+ *
412
+ * PROJECTED onto the card rather than fetched beside it, and that is the whole reason a loop needed no
413
+ * surface of its own: a looping agent is an agent, so the board's status, spend, unread badge and Stop
414
+ * button already describe it, and one extra line is the difference between a card that says `running` for
415
+ * forty minutes and one that says what it is running towards. A second query joined client-side would have
416
+ * paid for the same line with a poll that can disagree with the roster.
417
+ *
418
+ * Absent ⇒ an ordinary conversation, which is nearly all of them. */
419
+ loop: z
420
+ .object({
421
+ state: LoopStateSchema.describe("How the loop is going."),
422
+ iteration: z.number().int().min(0).describe("Which round it is on."),
423
+ maxIterations: z.number().int().min(1).describe("How many rounds it will attempt before giving up."),
424
+ goal: z.string().describe("What it is looping towards."),
425
+ })
426
+ .optional()
427
+ .describe("The loop driving this conversation, if one is. Absent for an ordinary conversation, which is nearly all of them."),
428
+ /* The workflow run this conversation is a step of, "Ship the feature · step 3 of 4 · Review the change".
429
+ *
430
+ * Projected for the same reason the loop above is, and it answers a question only the board can be asked. A
431
+ * run of four `fresh` steps IS four conversations, so it arrives on the board as four unrelated cards that
432
+ * started a few minutes apart, the work reads as four people who happen to be busy rather than as one job
433
+ * with a shape. Naming the run on each card is what makes them one block, and `runId` is what lets the board
434
+ * order them together and link every one of them at the run's own graph.
435
+ *
436
+ * POSITION IS A FACT ABOUT THE STEP, not a running total: `index`/`total` are its place in the workflow's own
437
+ * step order, so a card is published once when its step starts and never has to be rewritten because a
438
+ * sibling advanced. How the run as a whole is going is the run page's job, and how THIS step is going is
439
+ * already the card's status and the loop line above.
440
+ *
441
+ * `step` moves within one conversation when steps are chained with `continue`, they share it, which is the
442
+ * point of chaining, so this says which one is on it NOW.
443
+ *
444
+ * Absent ⇒ an ordinary conversation. */
445
+ workflow: z
446
+ .object({
447
+ runId: z.string().describe("The run this belongs to, which is how a board groups its steps together."),
448
+ name: z.string().describe("The workflow's name."),
449
+ step: z.string().describe("Which step this conversation is on now. It moves when steps are chained."),
450
+ index: z.number().int().min(1).describe("This step's place in the workflow, counting from one."),
451
+ total: z.number().int().min(1).describe("How many steps the workflow has."),
452
+ })
453
+ .optional()
454
+ .describe(
455
+ "The workflow run this conversation is a step of. Without it, a four-step run reads as four unrelated conversations that happen to have started together.",
456
+ ),
457
+ /* THE OUTSIDE CONDITIONS THIS CONVERSATION IS PARKED ON, the armed condition watches (the daemon's
458
+ * agent/watchers.ts), projected onto the card for the same reason the loop and the workflow above are.
459
+ *
460
+ * IT IS THE ONE PROMISE THE BOARD USED TO KEEP SILENTLY. An agent that arms a watch ends its turn: nothing
461
+ * is running, nothing is owed to the user, so every surface filed it under finished and drew the resting
462
+ * `idle`. Then, some hours later, the daemon's check exits 0 and that same conversation starts working
463
+ * again, on its own, in front of somebody who had been told it was done. The wake is the feature; the card
464
+ * saying nothing about it beforehand is what made it read as the sandbox acting unasked.
465
+ *
466
+ * It also has a bill attached, which no other projection here does. An armed watch keeps a hosted machine
467
+ * awake (system/idle-stop.ts counts them, deliberately: stopping the box is how a watch silently never
468
+ * fires), so an invisible watch is invisible compute. A user looking at a board of finished agents,
469
+ * wondering why the machine will not go quiet, could not have found the answer anywhere.
470
+ *
471
+ * WHAT IS ON THE WIRE IS WHAT A CARD CAN ACT ON, and nothing else. The note (the agent's own line on what
472
+ * it is waiting for), the cadence, and the deadline, which is what turns "waiting" into a countdown with an
473
+ * end. Deliberately NOT the check command: it is shell text the reader cannot run, judge or fix from a
474
+ * board, and it is the one field that could carry a secret reference into a surface that is read over
475
+ * shoulders. Deliberately NOT the check COUNT either, which would move every interval and buy a whole
476
+ * roster broadcast to advance a number nobody is reading.
477
+ *
478
+ * Absent ⇒ nothing armed, which is nearly every conversation. Empty is never sent: the daemon clears the
479
+ * projection instead, so the field's PRESENCE is the signal. */
480
+ watches: z
481
+ .array(
482
+ z.object({
483
+ id: z.string().describe("The daemon's handle for this watch, the same one the agent was given when it armed it."),
484
+ note: z.string().describe("The agent's own line on what it is waiting for."),
485
+ intervalSeconds: z.number().int().min(1).describe("How often the check runs."),
486
+ deadlineAt: z.number().describe("When it gives up and wakes the conversation anyway, in milliseconds. Every watch has one."),
487
+ }),
488
+ )
489
+ .optional()
490
+ .describe(
491
+ "Outside conditions this conversation is parked on, each of which will wake it. Absent means none, which is nearly every conversation: an armed watch is why a finished-looking agent starts working by itself, and why a hosted machine will not go idle.",
492
+ ),
493
+ // When the agent was ARCHIVED (ms epoch), off the board, but nothing lost: its checkout was retired
494
+ // (worktree removed) while the agent/<id> branch, the transcript, and every counter stayed. Absent ⇒ live
495
+ // on the board. Archived agents are excluded from the roster the fleet renders; `agents.archived` lists
496
+ // them, `agents.unarchive` brings one back, and the next turn re-attaches its worktree from the branch.
497
+ archivedAt: z
498
+ .number()
499
+ .optional()
500
+ .describe(
501
+ "When it was put away, in milliseconds. Nothing was lost: its branch, its record and every counter stayed, and bringing it back gives it a fresh working copy. Absent means it is live on the board.",
502
+ ),
503
+ });
504
+ export type AgentSummary = z.infer<typeof AgentSummarySchema>;
505
+ // One armed condition watch as a card carries it (AgentSummarySchema.watches). Named off the summary rather
506
+ // than declared beside it, so the shape the daemon publishes and the shape the wire promises cannot drift.
507
+ export type AgentWatch = NonNullable<AgentSummary["watches"]>[number];
508
+ // AgentsListSchema lives further down, after AutomationApprovalSchema, the fleet list carries the held wakes,
509
+ // and zod declaration order forces the ride-along to be declared first.
510
+ export const AgentIdSchema = z.object({ id: z.string().min(1).describe("Which conversation.") });
511
+ // archive's input: the agents to take off the board. Absent `ids` ⇒ every finished agent that is archivable
512
+ // right now (the lane header's "Clear"); unarchive always names its ids (a restore, or a bulk archive's undo).
513
+ export const AgentArchiveSchema = z.object({
514
+ ids: z
515
+ .array(z.string().min(1))
516
+ .max(500)
517
+ .optional()
518
+ .describe("Which conversations to put away. Leave it out for every finished one that can be archived right now."),
519
+ });
520
+ export const AgentIdsSchema = z.object({ ids: z.array(z.string().min(1)).min(1).max(500).describe("Which conversations.") });
521
+ // What actually MOVED, and deliberately NOT the roster afterwards. Two archives in flight at once each finish
522
+ // holding a full-roster snapshot from a different instant, so a client that swapped one in wholesale would let
523
+ // the slower response resurrect what the faster one just filed away, a delta composes where a snapshot races.
524
+ // Whole summaries rather than ids because the receiving side has to SHOW them (the archive list, and the agent
525
+ // detail page addressed by id); the ids "Undo" needs come off them for free.
526
+ // The agents an archive/unarchive actually moved, plus the registry revision that applied the move, the
527
+ // browser holds its optimistic add/remove of exactly these ids until it sees a roster at or past `rev`.
528
+ export const AgentsMovedSchema = z.object({
529
+ moved: z
530
+ .array(AgentSummarySchema)
531
+ .describe(
532
+ "What actually moved, whole, rather than the fleet afterwards. Two archives finishing at once would each carry a snapshot from a different instant, and swapping one in wholesale would let the slower answer resurrect what the faster one just filed away.",
533
+ ),
534
+ rev: z
535
+ .number()
536
+ .describe(
537
+ "The version of the fleet that includes this move, so a caller can hold its own optimistic change until it sees a list at least that new.",
538
+ ),
539
+ });
540
+ export type AgentsMoved = z.infer<typeof AgentsMovedSchema>;
541
+ /* AN ARCHIVE ALSO REPORTS WHAT IT COULD NOT DO, which is the half that used to go missing. Releasing a working
542
+ * copy is git work, and it can fail for reasons no press can fix: the repository behind a checkout was deleted
543
+ * from the workspace, a checkout is locked. Those agents stay on the board, so the answer carries them and the
544
+ * sentence each failed with, otherwise the only true thing the caller could say about an archive that moved
545
+ * nothing was "there was nothing to archive": to a user looking straight at the card it refused. */
546
+ export const AgentsArchivedSchema = AgentsMovedSchema.extend({
547
+ failed: z
548
+ .array(
549
+ z.object({
550
+ id: z.string().describe("Which conversation stayed on the board."),
551
+ reason: z.string().describe("Why its working copy could not be released, in the words the failure came with."),
552
+ }),
553
+ )
554
+ .describe("The conversations this press could not put away, each with the reason, so the board can say it instead of reporting silence."),
555
+ });
556
+ export type AgentsArchived = z.infer<typeof AgentsArchivedSchema>;
557
+ // What a purge actually deleted. Ids, not summaries: these agents no longer exist anywhere, there is nothing
558
+ // left to show and nothing to put back, so the only thing the caller can do with the answer is drop those rows
559
+ // and count them. No revision either: archived agents are already off the broadcast roster (see `list`), so a
560
+ // purge changes nothing the board's pending-move machinery has to hold a card against.
561
+ export const AgentsRemovedSchema = z.object({
562
+ removed: z
563
+ .array(z.string())
564
+ .describe(
565
+ "Which conversations were deleted, as ids. Ids rather than whole cards, because these no longer exist anywhere: there is nothing left to show and nothing to put back.",
566
+ ),
567
+ });
568
+ export type AgentsRemoved = z.infer<typeof AgentsRemovedSchema>;
569
+ /* Search the fleet by what was SAID in it, the board's filter (and the popped-out rail's).
570
+ *
571
+ * Both sides of the conversation, and nothing else: the user's own prompts and the agent's chat bubbles. What
572
+ * an agent ANSWERED is half of what a chat is remembered by, the name it found, the file it named, the number
573
+ * it reported, and a filter that could not reach it sent people back to opening chats one at a time.
574
+ *
575
+ * What stays out is everything that is not speech: extended thinking, tool calls and their output, and the
576
+ * daemon's own protocol (preambles, attachment notes). That is the line the old user-only rule was really
577
+ * drawing, tool output alone names nearly every identifier in the workspace, so matching it returns most of
578
+ * the board and the filter stops filtering. Prose is a fraction of a transcript and reads like a sentence
579
+ * someone wrote, which is why it can be searched when a diff dump cannot.
580
+ *
581
+ * The card TITLE is the first prompt (sanitized), so a title match and a prompt match are one rule, not two.
582
+ *
583
+ * Two chars minimum: below that every agent matches and the scan is pure cost.
584
+ *
585
+ * `caseSensitive` is the field's Aa switch, the same name and the same default as the workspace search's, so
586
+ * one word means one thing across the daemon's search routes. Off is case-INSENSITIVE rather than smart case:
587
+ * a filter that quietly changed rule when a capital was typed would make the switch beside it a lie.
588
+ */
589
+ export const AgentSearchQuerySchema = z.object({
590
+ query: z
591
+ .string()
592
+ .trim()
593
+ .min(2)
594
+ .describe(
595
+ "What to look for. Searched against what was said, both sides of the conversation, and nothing else: not the thinking, not the tool output, which between them name nearly every identifier in the workspace and would return most of the board.",
596
+ ),
597
+ caseSensitive: z.stringbool().optional().describe("Whether capitals matter."),
598
+ });
599
+ /* WHY a row survived the filter: the matched line, windowed around the hit, and which side of the conversation
600
+ * said it. A result that matches for a reason the reader cannot see is worse than no filter at all.
601
+ *
602
+ * `speaker` rides WITH the text rather than beside it because the two are never separately true, every line is
603
+ * someone's, and because the words alone stopped being self-identifying the moment agent prose became
604
+ * matchable: "landAgent lives in laneDrop.ts" under a card reads as something the user typed until the row
605
+ * says otherwise.
606
+ */
607
+ export const SpeakerSchema = z.enum(["user", "agent"]);
608
+ export type Speaker = z.infer<typeof SpeakerSchema>;
609
+ export const MatchSnippetSchema = z.object({
610
+ text: z.string().describe("The matching line, with a little either side of it."),
611
+ speaker: SpeakerSchema.describe(
612
+ "Who said it. Carried with the words rather than beside them, because a line of the agent's prose under a card reads as something you typed until the row says otherwise.",
613
+ ),
614
+ });
615
+ export type MatchSnippet = z.infer<typeof MatchSnippetSchema>;
616
+ // One matching agent, and the evidence for it. `snippet` is absent when the match is the TITLE, which the card
617
+ // already shows, repeating it underneath is noise where evidence was wanted.
618
+ export const AgentMatchSchema = z.object({
619
+ id: z.string().describe("Which conversation matched."),
620
+ snippet: MatchSnippetSchema.optional().describe(
621
+ "Why, in its own words. Absent when the title was the match, which the card already shows: repeating it underneath is noise where evidence was wanted.",
622
+ ),
623
+ });
624
+ export type AgentMatch = z.infer<typeof AgentMatchSchema>;
625
+ // `scanned` is how many agents the daemon actually read prompts for, so the board can say when a query saw
626
+ // less than the whole fleet rather than implying it saw all of it.
627
+ export const AgentSearchResultSchema = z.object({
628
+ matches: z.array(AgentMatchSchema).describe("What matched, from the live fleet and the archive together."),
629
+ scanned: z
630
+ .number()
631
+ .describe(
632
+ "How many conversations were actually read, so a screen can say when a search saw less than everything rather than implying it saw all of it.",
633
+ ),
634
+ indexing: z
635
+ .boolean()
636
+ .describe(
637
+ "Whether what was said is still being read in the background. True means this answer can still grow, so a screen must say it is incomplete rather than presenting it as the whole list.",
638
+ ),
639
+ });
640
+ export type AgentSearchResult = z.infer<typeof AgentSearchResultSchema>;
641
+ // rename's input: the user-chosen display title (bounded like sanitizeTitle's cap).
642
+ export const AgentRenameSchema = z.object({
643
+ id: z.string().min(1).describe("Which conversation."),
644
+ title: z.string().trim().min(1).max(80).describe("What to call it from now on."),
645
+ });
646
+ /* place's input: words the user writes INTO the transcript wearing the agent's voice (see agentsContract.place).
647
+ * Bounded well above anything a person types by hand and just above the handoff's per-message render cap
648
+ * (runtime-history's MESSAGE_CHAR_CAP), a placed line longer than that would reach the agent truncated, which
649
+ * silently breaks "it thinks these are its own words". Better to refuse at the door with a reason. */
650
+ export const AgentPlaceSchema = z.object({
651
+ id: z.string().min(1).describe("Which conversation."),
652
+ text: z
653
+ .string()
654
+ .trim()
655
+ .min(1)
656
+ .max(8_000)
657
+ .describe(
658
+ "The words to put in the agent's mouth. Bounded just above what the next turn can carry whole, because a line too long to be handed over intact would reach the agent truncated and quietly break the very thing this is for.",
659
+ ),
660
+ });
661
+ // autoLand's input: this agent's own land-at-completion posture. `null` CLEARS the override back to "inherit
662
+ // the sandbox setting", the browser sends it whenever the user toggles back to what the global already says,
663
+ // so agents don't accumulate frozen overrides that quietly stop following the global toggle.
664
+ export const AgentAutoLandSchema = z.object({
665
+ id: z.string().min(1).describe("Which conversation."),
666
+ autoLand: z
667
+ .boolean()
668
+ .nullable()
669
+ .describe(
670
+ "Whether its work merges automatically when a turn finishes. Null clears the override and goes back to following the sandbox-wide setting, so a conversation does not sit holding a frozen copy of a default it has quietly stopped following.",
671
+ ),
672
+ });
673
+ // resumeAfterOutage's input: this ONE conversation's answer to a provider outage. `null` clears the override
674
+ // back to "inherit the sandbox setting", sent whenever the user toggles back to what the global already says,
675
+ // on the same reasoning as autoLand's null: an agent holding a frozen copy of a default has quietly stopped
676
+ // following it, and nothing on screen would say so.
677
+ export const AgentResumeAfterOutageSchema = z.object({
678
+ id: z.string().min(1).describe("Which conversation."),
679
+ resumeAfterOutage: z
680
+ .boolean()
681
+ .nullable()
682
+ .describe("Whether it retries by itself when the model provider was what failed. Null clears the override back to the sandbox-wide setting."),
683
+ });
684
+ export const AgentFileDiffQuerySchema = z.object({
685
+ id: z.string().min(1).describe("Which conversation."),
686
+ repo: z.string().min(1).describe("Which repository."),
687
+ path: z.string().min(1).describe("Which file, relative to that repository."),
688
+ });
689
+ /* WHY a path would not land. The distinction is the whole difference between an actionable report and a dead
690
+ * end, because the three have nothing in common but their symptom:
691
+ * `workspace`, you have uncommitted edits on that path. Yours is the copy at risk; commit or stash it.
692
+ * `diverged` , the main tree's COMMITTED content moved under the agent since it branched. Nothing of
693
+ * yours is at risk; the agent's delta is simply written against an older file.
694
+ * `binary` , git cannot three-way merge the file at all, so no automatic resolution exists.
695
+ * The old report named only the first, which is the rarest of the three. */
696
+ export const LandConflictReasonSchema = z.enum(["workspace", "diverged", "binary"]);
697
+ export type LandConflictReason = z.infer<typeof LandConflictReasonSchema>;
698
+ export const LandConflictPathSchema = z.object({
699
+ path: z.string().describe("Which file."),
700
+ reason: LandConflictReasonSchema.describe(
701
+ "Why it would not merge, and the three have nothing in common but the symptom. Your own uncommitted edits on that path, where yours is the copy at risk. The shared tree having moved under the conversation since it started, where nothing of yours is at risk. Or a file git cannot merge at all, where no automatic answer exists.",
702
+ ),
703
+ });
704
+ /* land's outcome, per repo of the composition. `paths` is the set that genuinely failed to apply. NOT the
705
+ * whole delta, which is what the first version reported whenever it could not pin the cause down, turning
706
+ * four real conflicts into a wall of fourteen. `clean` counts what would land regardless, so the UI can say
707
+ * how much is being held back by how little, and offer to take it. An empty `paths` with `clean: 0` is the
708
+ * repo-unavailable case: the main checkout is gone, and no path-level account exists. */
709
+ export const LandConflictSchema = z.object({
710
+ repo: z.string().describe("Which repository."),
711
+ paths: z
712
+ .array(LandConflictPathSchema)
713
+ .describe(
714
+ "The files that genuinely would not apply. Not the whole change: reporting everything whenever the cause could not be pinned down turned four real conflicts into a wall of fourteen.",
715
+ ),
716
+ clean: z
717
+ .number()
718
+ .describe(
719
+ "How many files would apply regardless, so a screen can say how much is being held back by how little and offer to take it. Zero alongside an empty list means the repository could not be reached at all.",
720
+ ),
721
+ // The branch the user's checkout is on, the thing the agent has to rebase onto. Carried because only the
722
+ // daemon can see it: an isolated turn's worktree is mounted over the agent's whole view, so the resolution
723
+ // errand could otherwise only tell it to go and read the name off `git worktree list`. Absent on a detached
724
+ // HEAD or a vanished checkout, where there is no name to give.
725
+ mainBranch: z
726
+ .string()
727
+ .optional()
728
+ .describe(
729
+ "The branch your own checkout is on, which is what the conversation has to rebase onto. Carried because only the sandbox can see it. Absent where there is no name to give.",
730
+ ),
731
+ });
732
+ export type LandConflict = z.infer<typeof LandConflictSchema>;
733
+ // land's outcome; landed only when every repo with changes applied cleanly. Conflicted repos keep their
734
+ // worktree state, nothing is lost, and "Land now" stays available. `resolving` is populated only by a
735
+ // `merge` land: the paths written into the workspace carrying conflict markers, which the user finishes by
736
+ // hand in their own editor exactly as they would any merge.
737
+ export const LandResultSchema = z.object({
738
+ landed: z.boolean().describe("Whether anything was applied."),
739
+ conflicts: z.array(LandConflictSchema).optional().describe("What stopped it, per repository."),
740
+ resolving: z
741
+ .array(
742
+ z.object({
743
+ repo: z.string().describe("Which repository."),
744
+ paths: z.array(z.string()).describe("Which files now hold conflict markers to sort out by hand."),
745
+ }),
746
+ )
747
+ .optional()
748
+ .describe("Files left half-merged, when you asked for the mode that lands what it can and leaves the rest marked up."),
749
+ // A `measure` outcome with an outstanding delta: nothing was applied and nothing failed, the work is
750
+ // waiting on the branch for a deliberate Land. `landed: false` alone can't say that (it means refusal).
751
+ held: z
752
+ .boolean()
753
+ .optional()
754
+ .describe(
755
+ "Nothing was applied and nothing failed: there is work waiting on the branch for a deliberate merge. Not merged on its own cannot say that, because on its own it means refused.",
756
+ ),
757
+ });
758
+ export type LandResult = z.infer<typeof LandResultSchema>;
759
+ /* land's input. `check` is the safe default and the historical behaviour: the delta is applied only if ALL of
760
+ * it applies, so a refusal leaves the workspace byte-identical. `merge` is the escape hatch the conflict
761
+ * report offers, a three-way apply that lands every clean path and leaves the rest with conflict markers to
762
+ * resolve in place. It is opt-in because it WRITES on failure, which is the one thing `check` promises not
763
+ * to do. `measure` is the auto-land-off mode: everything a land does EXCEPT touching the main tree, the
764
+ * provenance commit onto agent/<id>, the cumulative diffstat, and the bookkeeping for work that reached the
765
+ * main line by another road, so a held agent's card stays as current as a landed one's while its delta waits
766
+ * on the branch for a deliberate Land. */
767
+ export const LandModeSchema = z.enum(["check", "merge", "measure"]);
768
+ export type LandMode = z.infer<typeof LandModeSchema>;
769
+ /* WHICH RUNG OF AN AGENT'S HISTORY A READING, or a land. STARTS AT.
770
+ *
771
+ * outstanding, only what has not landed yet, measured from the last landed tip. The default, and what a
772
+ * land carries: a second land applies only what the agent has done since the first.
773
+ * cumulative , the agent's WHOLE output, from where its branch left the main line. What the review lists
774
+ * (landed work stays inspectable), and what "Land again" applies.
775
+ *
776
+ * A CUMULATIVE LAND IS NOT A DOUBLE APPLICATION. It is the way back when a land's work was discarded from the
777
+ * workspace: the outstanding span is empty then, every sha says the work landed, because it did, so only a
778
+ * reading from the base can still see the part that is missing. Paths the tree already holds drop out of it
779
+ * per file, by the same reverse probe that keeps work which reached main by another road out of a conflict
780
+ * report (land.ts, classifyDelta), so what actually applies is exactly what is gone. */
781
+ export const AgentSpanSchema = z.enum(["cumulative", "outstanding"]);
782
+ export type AgentSpan = z.infer<typeof AgentSpanSchema>;
783
+ /* LAND WHILE THE AGENT IS STILL WRITING, the user's deliberate override of the turn guard, and the only
784
+ * input here that is about WHEN a land may run rather than what it carries.
785
+ *
786
+ * A land snapshots the agent's checkout, so mid-turn it can catch work half-done: one leg of a rename, three
787
+ * files of a five-file change. The guard exists for that, and it stays the default. What makes the override
788
+ * defensible rather than reckless is that neither half of the damage is permanent, a land arrives as
789
+ * UNCOMMITTED changes the user reviews before committing, and the rest of the turn lands on top of it at
790
+ * completion like any other incremental land. So a premature land is a mess the user can see and one the next
791
+ * land repairs, which is a thing to warn about; it is not a thing to forbid.
792
+ *
793
+ * It does NOT cover a turn PARKED on a question or a permission card, nothing is being written there, so that
794
+ * land needs no override and takes none (agents.routes.ts). This flag means "yes, mid-write, I know". */
795
+ export const AgentLandSchema = z.object({
796
+ id: z.string().min(1).describe("Which conversation's work to merge."),
797
+ mode: LandModeSchema.optional().describe(
798
+ "How to apply it. The default applies all of it or none, so a refusal leaves the workspace exactly as it was. The other lands every clean file and leaves the rest with conflict markers to resolve by hand.",
799
+ ),
800
+ span: AgentSpanSchema.optional().describe("How much of the work to take. Leave it out for everything not yet merged."),
801
+ force: z.boolean().optional().describe("Go ahead despite a check that would otherwise refuse."),
802
+ });