@intentic/sandbox-contract 1.344.0 → 1.346.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 (418) hide show
  1. package/README.md +27 -9
  2. package/dist/contracts/accounts.contract.d.ts +24 -80
  3. package/dist/contracts/accounts.contract.d.ts.map +1 -1
  4. package/dist/contracts/agent.contract.d.ts +247 -8
  5. package/dist/contracts/agent.contract.d.ts.map +1 -1
  6. package/dist/contracts/agent.contract.js +13 -2
  7. package/dist/contracts/agent.contract.js.map +1 -1
  8. package/dist/contracts/agents.contract.d.ts +1570 -33
  9. package/dist/contracts/agents.contract.d.ts.map +1 -1
  10. package/dist/contracts/agents.contract.js +47 -4
  11. package/dist/contracts/agents.contract.js.map +1 -1
  12. package/dist/contracts/device.contract.d.ts +244 -1
  13. package/dist/contracts/device.contract.d.ts.map +1 -1
  14. package/dist/contracts/device.contract.js +5 -1
  15. package/dist/contracts/device.contract.js.map +1 -1
  16. package/dist/contracts/endpoints.contract.d.ts +2 -1
  17. package/dist/contracts/endpoints.contract.d.ts.map +1 -1
  18. package/dist/contracts/endpoints.contract.js +1 -0
  19. package/dist/contracts/endpoints.contract.js.map +1 -1
  20. package/dist/contracts/providers.contract.d.ts +0 -1
  21. package/dist/contracts/providers.contract.d.ts.map +1 -1
  22. package/dist/contracts/push.contract.d.ts +11 -0
  23. package/dist/contracts/push.contract.d.ts.map +1 -1
  24. package/dist/contracts/push.contract.js +10 -1
  25. package/dist/contracts/push.contract.js.map +1 -1
  26. package/dist/contracts/runner.contract.d.ts +149 -123
  27. package/dist/contracts/runner.contract.d.ts.map +1 -1
  28. package/dist/contracts/secrets.contract.d.ts +169 -0
  29. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  30. package/dist/contracts/secrets.contract.js +35 -0
  31. package/dist/contracts/secrets.contract.js.map +1 -1
  32. package/dist/contracts/sessions.contract.d.ts +2 -0
  33. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  34. package/dist/contracts/settings.contract.d.ts +37 -0
  35. package/dist/contracts/settings.contract.d.ts.map +1 -1
  36. package/dist/contracts/system.contract.d.ts +235 -31
  37. package/dist/contracts/system.contract.d.ts.map +1 -1
  38. package/dist/contracts/translator.contract.d.ts +24 -80
  39. package/dist/contracts/translator.contract.d.ts.map +1 -1
  40. package/dist/contracts/workspace.contract.d.ts +11 -0
  41. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  42. package/dist/contracts/workspace.contract.js +11 -1
  43. package/dist/contracts/workspace.contract.js.map +1 -1
  44. package/dist/events/agent-events.d.ts +60 -0
  45. package/dist/events/agent-events.d.ts.map +1 -1
  46. package/dist/events/agent-events.js +44 -38
  47. package/dist/events/agent-events.js.map +1 -1
  48. package/dist/events/agent-transcript.d.ts +727 -0
  49. package/dist/events/agent-transcript.d.ts.map +1 -0
  50. package/dist/events/agent-transcript.js +34 -0
  51. package/dist/events/agent-transcript.js.map +1 -0
  52. package/dist/events/agent-words.d.ts +5 -0
  53. package/dist/events/agent-words.d.ts.map +1 -1
  54. package/dist/events/agent-words.js +9 -0
  55. package/dist/events/agent-words.js.map +1 -1
  56. package/dist/events/failure-rows.d.ts +14 -0
  57. package/dist/events/failure-rows.d.ts.map +1 -0
  58. package/dist/events/failure-rows.js +109 -0
  59. package/dist/events/failure-rows.js.map +1 -0
  60. package/dist/events/requests.d.ts +143 -0
  61. package/dist/events/requests.d.ts.map +1 -1
  62. package/dist/events/requests.js +35 -1
  63. package/dist/events/requests.js.map +1 -1
  64. package/dist/events/sandbox-notice.d.ts +23 -0
  65. package/dist/events/sandbox-notice.d.ts.map +1 -1
  66. package/dist/events/sandbox-notice.js +2 -0
  67. package/dist/events/sandbox-notice.js.map +1 -1
  68. package/dist/events/system-events.d.ts +156 -0
  69. package/dist/events/system-events.d.ts.map +1 -1
  70. package/dist/events/system-events.js +7 -1
  71. package/dist/events/system-events.js.map +1 -1
  72. package/dist/events/transcript.d.ts +20 -720
  73. package/dist/events/transcript.d.ts.map +1 -1
  74. package/dist/events/transcript.js +17 -19
  75. package/dist/events/transcript.js.map +1 -1
  76. package/dist/ids/conversation-ids.d.ts +2 -0
  77. package/dist/ids/conversation-ids.d.ts.map +1 -1
  78. package/dist/ids/conversation-ids.js +2 -0
  79. package/dist/ids/conversation-ids.js.map +1 -1
  80. package/dist/ids/row-ids.d.ts +3 -0
  81. package/dist/ids/row-ids.d.ts.map +1 -0
  82. package/dist/ids/row-ids.js +11 -0
  83. package/dist/ids/row-ids.js.map +1 -0
  84. package/dist/index.d.ts +2296 -199
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/models/agent-lanes.d.ts.map +1 -1
  87. package/dist/models/agent-lanes.js +6 -7
  88. package/dist/models/agent-lanes.js.map +1 -1
  89. package/dist/models/agent-standing.d.ts +6 -19
  90. package/dist/models/agent-standing.d.ts.map +1 -1
  91. package/dist/models/agent-standing.js +14 -38
  92. package/dist/models/agent-standing.js.map +1 -1
  93. package/dist/models/model-pins.d.ts +3 -0
  94. package/dist/models/model-pins.d.ts.map +1 -1
  95. package/dist/models/model-pins.js +2 -0
  96. package/dist/models/model-pins.js.map +1 -1
  97. package/dist/models/plan-pools.d.ts +26 -4
  98. package/dist/models/plan-pools.d.ts.map +1 -1
  99. package/dist/models/plan-pools.js +159 -40
  100. package/dist/models/plan-pools.js.map +1 -1
  101. package/dist/netd/generated/wire.d.ts +5 -0
  102. package/dist/netd/generated/wire.d.ts.map +1 -1
  103. package/dist/policy/command-classes.d.ts +1 -1
  104. package/dist/policy/command-classes.d.ts.map +1 -1
  105. package/dist/policy/command-classes.js +2 -2
  106. package/dist/policy/command-classes.js.map +1 -1
  107. package/dist/policy/keyring-origins.d.ts +27 -0
  108. package/dist/policy/keyring-origins.d.ts.map +1 -0
  109. package/dist/policy/keyring-origins.js +213 -0
  110. package/dist/policy/keyring-origins.js.map +1 -0
  111. package/dist/policy/keyring-seal.d.ts +9 -0
  112. package/dist/policy/keyring-seal.d.ts.map +1 -1
  113. package/dist/policy/keyring-seal.js +18 -6
  114. package/dist/policy/keyring-seal.js.map +1 -1
  115. package/dist/policy/safety-policy.d.ts +1 -1
  116. package/dist/policy/safety-policy.d.ts.map +1 -1
  117. package/dist/policy/safety-policy.js +1 -1
  118. package/dist/policy/safety-policy.js.map +1 -1
  119. package/dist/policy/turned-away.d.ts +1 -0
  120. package/dist/policy/turned-away.d.ts.map +1 -1
  121. package/dist/policy/turned-away.js +10 -0
  122. package/dist/policy/turned-away.js.map +1 -1
  123. package/dist/protocol/doors/host-protocol.d.ts +1 -0
  124. package/dist/protocol/doors/host-protocol.d.ts.map +1 -1
  125. package/dist/protocol/doors/host-protocol.js +1 -0
  126. package/dist/protocol/doors/host-protocol.js.map +1 -1
  127. package/dist/protocol/doors/runner-protocol.d.ts +1 -0
  128. package/dist/protocol/doors/runner-protocol.d.ts.map +1 -1
  129. package/dist/protocol/doors/runner-protocol.js +1 -0
  130. package/dist/protocol/doors/runner-protocol.js.map +1 -1
  131. package/dist/protocol/doors/webext-links.d.ts +1 -0
  132. package/dist/protocol/doors/webext-links.d.ts.map +1 -1
  133. package/dist/protocol/doors/webext-links.js +1 -0
  134. package/dist/protocol/doors/webext-links.js.map +1 -1
  135. package/dist/protocol/peer-dial.d.ts +2 -0
  136. package/dist/protocol/peer-dial.d.ts.map +1 -1
  137. package/dist/protocol/peer-dial.js +62 -29
  138. package/dist/protocol/peer-dial.js.map +1 -1
  139. package/dist/protocol/raw/raw-json-routes.d.ts +179 -1
  140. package/dist/protocol/raw/raw-json-routes.d.ts.map +1 -1
  141. package/dist/protocol/raw/raw-json-routes.js +5 -0
  142. package/dist/protocol/raw/raw-json-routes.js.map +1 -1
  143. package/dist/protocol/raw/raw-routes.d.ts +35 -0
  144. package/dist/protocol/raw/raw-routes.d.ts.map +1 -1
  145. package/dist/protocol/raw/raw-routes.js +9 -0
  146. package/dist/protocol/raw/raw-routes.js.map +1 -1
  147. package/dist/schemas/agent-next.d.ts +21 -0
  148. package/dist/schemas/agent-next.d.ts.map +1 -0
  149. package/dist/schemas/agent-next.js +21 -0
  150. package/dist/schemas/agent-next.js.map +1 -0
  151. package/dist/schemas/agent-place.d.ts +10 -0
  152. package/dist/schemas/agent-place.d.ts.map +1 -0
  153. package/dist/schemas/agent-place.js +15 -0
  154. package/dist/schemas/agent-place.js.map +1 -0
  155. package/dist/schemas/agent-search.d.ts +45 -0
  156. package/dist/schemas/agent-search.d.ts.map +1 -0
  157. package/dist/schemas/agent-search.js +28 -0
  158. package/dist/schemas/agent-search.js.map +1 -0
  159. package/dist/schemas/agent.d.ts +120 -78
  160. package/dist/schemas/agent.d.ts.map +1 -1
  161. package/dist/schemas/agent.js +40 -49
  162. package/dist/schemas/agent.js.map +1 -1
  163. package/dist/schemas/agents-list.d.ts +54 -0
  164. package/dist/schemas/agents-list.d.ts.map +1 -1
  165. package/dist/schemas/agents.d.ts +165 -59
  166. package/dist/schemas/agents.d.ts.map +1 -1
  167. package/dist/schemas/agents.js +25 -50
  168. package/dist/schemas/agents.js.map +1 -1
  169. package/dist/schemas/attach.d.ts +8 -0
  170. package/dist/schemas/attach.d.ts.map +1 -0
  171. package/dist/schemas/attach.js +14 -0
  172. package/dist/schemas/attach.js.map +1 -0
  173. package/dist/schemas/command-admission.d.ts +71 -0
  174. package/dist/schemas/command-admission.d.ts.map +1 -0
  175. package/dist/schemas/command-admission.js +27 -0
  176. package/dist/schemas/command-admission.js.map +1 -0
  177. package/dist/schemas/compose-overlay.d.ts +9 -0
  178. package/dist/schemas/compose-overlay.d.ts.map +1 -0
  179. package/dist/schemas/compose-overlay.js +11 -0
  180. package/dist/schemas/compose-overlay.js.map +1 -0
  181. package/dist/schemas/composer-drafts.d.ts +169 -0
  182. package/dist/schemas/composer-drafts.d.ts.map +1 -0
  183. package/dist/schemas/composer-drafts.js +60 -0
  184. package/dist/schemas/composer-drafts.js.map +1 -0
  185. package/dist/schemas/conversation-links.d.ts +44 -0
  186. package/dist/schemas/conversation-links.d.ts.map +1 -0
  187. package/dist/schemas/conversation-links.js +35 -0
  188. package/dist/schemas/conversation-links.js.map +1 -0
  189. package/dist/schemas/data-protection.d.ts +1 -1
  190. package/dist/schemas/data-protection.d.ts.map +1 -1
  191. package/dist/schemas/device-commands.d.ts +63 -0
  192. package/dist/schemas/device-commands.d.ts.map +1 -0
  193. package/dist/schemas/device-commands.js +42 -0
  194. package/dist/schemas/device-commands.js.map +1 -0
  195. package/dist/schemas/device-folder.d.ts +11 -0
  196. package/dist/schemas/device-folder.d.ts.map +1 -1
  197. package/dist/schemas/device-folder.js +1 -0
  198. package/dist/schemas/device-folder.js.map +1 -1
  199. package/dist/schemas/devices.d.ts +18 -68
  200. package/dist/schemas/devices.d.ts.map +1 -1
  201. package/dist/schemas/devices.js +8 -45
  202. package/dist/schemas/devices.js.map +1 -1
  203. package/dist/schemas/environment.d.ts.map +1 -1
  204. package/dist/schemas/environment.js.map +1 -1
  205. package/dist/schemas/hosts.d.ts +29 -0
  206. package/dist/schemas/hosts.d.ts.map +1 -1
  207. package/dist/schemas/hosts.js +23 -0
  208. package/dist/schemas/hosts.js.map +1 -1
  209. package/dist/schemas/keyring-native.d.ts +137 -0
  210. package/dist/schemas/keyring-native.d.ts.map +1 -0
  211. package/dist/schemas/keyring-native.js +69 -0
  212. package/dist/schemas/keyring-native.js.map +1 -0
  213. package/dist/schemas/keyring.d.ts +413 -0
  214. package/dist/schemas/keyring.d.ts.map +1 -1
  215. package/dist/schemas/keyring.js +139 -4
  216. package/dist/schemas/keyring.js.map +1 -1
  217. package/dist/schemas/phone-passwords.d.ts +186 -0
  218. package/dist/schemas/phone-passwords.d.ts.map +1 -0
  219. package/dist/schemas/phone-passwords.js +25 -0
  220. package/dist/schemas/phone-passwords.js.map +1 -0
  221. package/dist/schemas/privacy-egress.d.ts +41 -0
  222. package/dist/schemas/privacy-egress.d.ts.map +1 -0
  223. package/dist/schemas/privacy-egress.js +30 -0
  224. package/dist/schemas/privacy-egress.js.map +1 -0
  225. package/dist/schemas/privacy.d.ts +1 -0
  226. package/dist/schemas/privacy.d.ts.map +1 -1
  227. package/dist/schemas/privacy.js +1 -0
  228. package/dist/schemas/privacy.js.map +1 -1
  229. package/dist/schemas/providers/plan-limits.d.ts +76 -130
  230. package/dist/schemas/providers/plan-limits.d.ts.map +1 -1
  231. package/dist/schemas/providers/plan-limits.js +36 -23
  232. package/dist/schemas/providers/plan-limits.js.map +1 -1
  233. package/dist/schemas/providers/provider-oauth.d.ts +24 -82
  234. package/dist/schemas/providers/provider-oauth.d.ts.map +1 -1
  235. package/dist/schemas/providers/provider-oauth.js +1 -6
  236. package/dist/schemas/providers/provider-oauth.js.map +1 -1
  237. package/dist/schemas/providers/refusals.d.ts +64 -0
  238. package/dist/schemas/providers/refusals.d.ts.map +1 -0
  239. package/dist/schemas/providers/refusals.js +33 -0
  240. package/dist/schemas/providers/refusals.js.map +1 -0
  241. package/dist/schemas/providers/usage.d.ts +1 -0
  242. package/dist/schemas/providers/usage.d.ts.map +1 -1
  243. package/dist/schemas/providers/usage.js +1 -0
  244. package/dist/schemas/providers/usage.js.map +1 -1
  245. package/dist/schemas/push.d.ts +13 -0
  246. package/dist/schemas/push.d.ts.map +1 -1
  247. package/dist/schemas/push.js +11 -1
  248. package/dist/schemas/push.js.map +1 -1
  249. package/dist/schemas/sandbox-passwords.d.ts +288 -0
  250. package/dist/schemas/sandbox-passwords.d.ts.map +1 -0
  251. package/dist/schemas/sandbox-passwords.js +66 -0
  252. package/dist/schemas/sandbox-passwords.js.map +1 -0
  253. package/dist/schemas/secrets.d.ts +2 -0
  254. package/dist/schemas/secrets.d.ts.map +1 -1
  255. package/dist/schemas/secrets.js +4 -0
  256. package/dist/schemas/secrets.js.map +1 -1
  257. package/dist/schemas/sessions.js +1 -1
  258. package/dist/schemas/sessions.js.map +1 -1
  259. package/dist/schemas/settings-savings.d.ts +709 -0
  260. package/dist/schemas/settings-savings.d.ts.map +1 -0
  261. package/dist/schemas/settings-savings.js +53 -0
  262. package/dist/schemas/settings-savings.js.map +1 -0
  263. package/dist/schemas/settings.d.ts +7 -671
  264. package/dist/schemas/settings.d.ts.map +1 -1
  265. package/dist/schemas/settings.js +5 -50
  266. package/dist/schemas/settings.js.map +1 -1
  267. package/dist/schemas/system.d.ts +16 -0
  268. package/dist/schemas/system.d.ts.map +1 -1
  269. package/dist/schemas/system.js +11 -0
  270. package/dist/schemas/system.js.map +1 -1
  271. package/dist/schemas/terminal.d.ts +5 -0
  272. package/dist/schemas/terminal.d.ts.map +1 -1
  273. package/dist/schemas/terminal.js +4 -0
  274. package/dist/schemas/terminal.js.map +1 -1
  275. package/dist/schemas/work-assurance.d.ts +24 -0
  276. package/dist/schemas/work-assurance.d.ts.map +1 -0
  277. package/dist/schemas/work-assurance.js +23 -0
  278. package/dist/schemas/work-assurance.js.map +1 -0
  279. package/dist/schemas/workspace/workspace-tree.d.ts +23 -0
  280. package/dist/schemas/workspace/workspace-tree.d.ts.map +1 -1
  281. package/dist/schemas/workspace/workspace-tree.js +20 -0
  282. package/dist/schemas/workspace/workspace-tree.js.map +1 -1
  283. package/dist/state/auth-state.d.ts +4 -0
  284. package/dist/state/auth-state.d.ts.map +1 -0
  285. package/dist/state/auth-state.js +37 -0
  286. package/dist/state/auth-state.js.map +1 -0
  287. package/dist/state/definition.d.ts +12 -0
  288. package/dist/state/definition.d.ts.map +1 -1
  289. package/dist/state/runtime-state.d.ts +3 -0
  290. package/dist/state/runtime-state.d.ts.map +1 -1
  291. package/dist/state/runtime-state.js +1 -0
  292. package/dist/state/runtime-state.js.map +1 -1
  293. package/dist/state/sandbox-build.d.ts +20 -0
  294. package/dist/state/sandbox-build.d.ts.map +1 -0
  295. package/dist/state/sandbox-build.js +43 -0
  296. package/dist/state/sandbox-build.js.map +1 -0
  297. package/dist/state/ways-back.d.ts +4 -0
  298. package/dist/state/ways-back.d.ts.map +1 -0
  299. package/dist/state/ways-back.js +8 -0
  300. package/dist/state/ways-back.js.map +1 -0
  301. package/dist/text/land-rows.d.ts +14 -0
  302. package/dist/text/land-rows.d.ts.map +1 -0
  303. package/dist/text/land-rows.js +86 -0
  304. package/dist/text/land-rows.js.map +1 -0
  305. package/dist/text/transcript-fold.d.ts +4 -2
  306. package/dist/text/transcript-fold.d.ts.map +1 -1
  307. package/dist/text/transcript-fold.js +21 -187
  308. package/dist/text/transcript-fold.js.map +1 -1
  309. package/dist/webext/index.d.ts +1 -0
  310. package/dist/webext/index.d.ts.map +1 -1
  311. package/dist/webext/index.js +1 -0
  312. package/dist/webext/index.js.map +1 -1
  313. package/package.json +7 -6
  314. package/src/contracts/agent.contract.ts +13 -1
  315. package/src/contracts/agents.contract.ts +53 -28
  316. package/src/contracts/device.contract.ts +16 -0
  317. package/src/contracts/endpoints.contract.ts +3 -0
  318. package/src/contracts/push.contract.ts +23 -1
  319. package/src/contracts/secrets.contract.ts +39 -0
  320. package/src/contracts/workspace.contract.ts +16 -0
  321. package/src/events/agent-events.ts +99 -79
  322. package/src/events/agent-transcript.ts +48 -0
  323. package/src/events/agent-words.ts +13 -0
  324. package/src/events/failure-rows.ts +148 -0
  325. package/src/events/requests.ts +41 -3
  326. package/src/events/sandbox-notice.ts +14 -2
  327. package/src/events/system-events.ts +14 -4
  328. package/src/events/transcript.ts +30 -28
  329. package/src/ids/conversation-ids.ts +7 -0
  330. package/src/ids/project-dir.test.ts +2 -2
  331. package/src/ids/project-dir.ts +4 -4
  332. package/src/ids/row-ids.ts +20 -0
  333. package/src/models/agent-lanes.ts +16 -24
  334. package/src/models/agent-runtimes.ts +2 -2
  335. package/src/models/agent-standing.ts +38 -95
  336. package/src/models/model-pins.test.ts +31 -1
  337. package/src/models/model-pins.ts +17 -0
  338. package/src/models/plan-pools.test.ts +274 -31
  339. package/src/models/plan-pools.ts +294 -79
  340. package/src/netd/generated/netd-wire.json +25 -0
  341. package/src/netd/generated/wire.ts +1 -1
  342. package/src/policy/command-classes.ts +2 -2
  343. package/src/policy/keyring-origins.test.ts +132 -0
  344. package/src/policy/keyring-origins.ts +287 -0
  345. package/src/policy/keyring-seal.test.ts +37 -2
  346. package/src/policy/keyring-seal.ts +33 -7
  347. package/src/policy/safety-policy.ts +1 -1
  348. package/src/policy/tests/safety-policy.test.ts +1 -1
  349. package/src/policy/turned-away.ts +15 -0
  350. package/src/protocol/doors/host-protocol.ts +3 -0
  351. package/src/protocol/doors/runner-protocol.ts +4 -1
  352. package/src/protocol/doors/webext-links.ts +3 -0
  353. package/src/protocol/peer-dial.test.ts +90 -4
  354. package/src/protocol/peer-dial.ts +83 -39
  355. package/src/protocol/raw/raw-json-routes.ts +13 -0
  356. package/src/protocol/raw/raw-routes.ts +13 -1
  357. package/src/schemas/agent-next.ts +34 -0
  358. package/src/schemas/agent-place.ts +22 -0
  359. package/src/schemas/agent-search.ts +51 -0
  360. package/src/schemas/agent.ts +63 -90
  361. package/src/schemas/agents.ts +55 -99
  362. package/src/schemas/attach.ts +23 -0
  363. package/src/schemas/command-admission.ts +57 -0
  364. package/src/schemas/compose-overlay.test.ts +35 -0
  365. package/src/schemas/compose-overlay.ts +19 -0
  366. package/src/schemas/composer-drafts.ts +86 -0
  367. package/src/schemas/conversation-links.ts +62 -0
  368. package/src/schemas/data-protection.ts +1 -1
  369. package/src/schemas/device-commands.ts +89 -0
  370. package/src/schemas/device-folder.ts +9 -0
  371. package/src/schemas/devices.ts +28 -110
  372. package/src/schemas/environment.ts +8 -9
  373. package/src/schemas/hosts.ts +60 -0
  374. package/src/schemas/keyring-native.test.ts +13 -0
  375. package/src/schemas/keyring-native.ts +101 -0
  376. package/src/schemas/keyring.ts +202 -4
  377. package/src/schemas/machine-presence.test.ts +33 -0
  378. package/src/schemas/phone-passwords.ts +51 -0
  379. package/src/schemas/privacy-egress.test.ts +83 -0
  380. package/src/schemas/privacy-egress.ts +86 -0
  381. package/src/schemas/privacy.ts +4 -0
  382. package/src/schemas/project-delivery.ts +1 -1
  383. package/src/schemas/providers/plan-limits.test.ts +16 -0
  384. package/src/schemas/providers/plan-limits.ts +55 -49
  385. package/src/schemas/providers/provider-oauth.ts +1 -13
  386. package/src/schemas/providers/refusals.ts +62 -0
  387. package/src/schemas/providers/usage.ts +2 -0
  388. package/src/schemas/push.ts +19 -3
  389. package/src/schemas/sandbox-passwords.ts +88 -0
  390. package/src/schemas/secrets.ts +4 -0
  391. package/src/schemas/sessions.ts +1 -1
  392. package/src/schemas/settings-savings.ts +125 -0
  393. package/src/schemas/settings.ts +10 -116
  394. package/src/schemas/system.ts +15 -0
  395. package/src/schemas/terminal.ts +8 -0
  396. package/src/schemas/work-assurance.ts +36 -0
  397. package/src/schemas/workspace/workspace-tree.ts +32 -0
  398. package/src/state/auth-state.ts +89 -0
  399. package/src/state/runtime-state.ts +10 -4
  400. package/src/state/sandbox-build.test.ts +95 -0
  401. package/src/state/sandbox-build.ts +96 -0
  402. package/src/state/ways-back.test.ts +36 -0
  403. package/src/state/ways-back.ts +19 -0
  404. package/src/state/workspace-state.ts +1 -1
  405. package/src/text/land-rows.ts +111 -0
  406. package/src/text/transcript-fold.test.ts +105 -9
  407. package/src/text/transcript-fold.ts +30 -232
  408. package/src/webext/index.ts +2 -0
  409. package/dist/events/undelivered.d.ts +0 -6
  410. package/dist/events/undelivered.d.ts.map +0 -1
  411. package/dist/events/undelivered.js +0 -9
  412. package/dist/events/undelivered.js.map +0 -1
  413. package/dist/state/history-state.d.ts +0 -3
  414. package/dist/state/history-state.d.ts.map +0 -1
  415. package/dist/state/history-state.js +0 -137
  416. package/dist/state/history-state.js.map +0 -1
  417. package/src/events/undelivered.ts +0 -15
  418. package/src/state/history-state.ts +0 -270
@@ -47,16 +47,22 @@ class FakeSocket implements SocketLike {
47
47
  // This door's silence deadline, named so the assertions can read it off the same number the loop is given.
48
48
  const SILENCE_MS = 30_000;
49
49
 
50
- // A ladder that answers with a fixed delay and records what it was told, so the test can read the held time.
50
+ // A ladder that answers with a fixed delay and records what it was told, so the test can read the held time, and how
51
+ // often it was put back on its floor.
51
52
  const ladder = (delay = 1_000) => {
52
53
  const held: number[] = [];
53
- return {
54
+ const rungs = {
54
55
  held,
56
+ resets: 0,
55
57
  next: (heldMs: number) => {
56
58
  held.push(heldMs);
57
59
  return delay;
58
60
  },
61
+ reset: () => {
62
+ rungs.resets += 1;
63
+ },
59
64
  };
65
+ return rungs;
60
66
  };
61
67
 
62
68
  const dialling = (delay?: number) => {
@@ -64,6 +70,7 @@ const dialling = (delay?: number) => {
64
70
  const attached: FakeSocket[] = [];
65
71
  const said: string[] = [];
66
72
  const revoked = jest.fn();
73
+ const backoff = ladder(delay);
67
74
  const link = dialPeer<FakeSocket>({
68
75
  open: async () => {
69
76
  const socket = new FakeSocket();
@@ -72,12 +79,12 @@ const dialling = (delay?: number) => {
72
79
  },
73
80
  hello: () => ({ type: "hello", token: "iht_test", version: "1.0.0" }),
74
81
  attach: (socket) => void attached.push(socket),
75
- backoff: ladder(delay),
82
+ backoff,
76
83
  silenceMs: SILENCE_MS,
77
84
  log: (message) => void said.push(message),
78
85
  revoked,
79
86
  });
80
- return { link, sockets, attached, said, revoked };
87
+ return { link, sockets, attached, said, revoked, backoff };
81
88
  };
82
89
 
83
90
  test("the handler is attached before the hello goes out, and the hello is the first frame", async () => {
@@ -305,6 +312,85 @@ test("a link nobody has answered in a long time rests between tries, and is neve
305
312
  }
306
313
  });
307
314
 
315
+ /* A FAR END SOMEBODY KNOWS IS BACK (a sandbox the machine agent just woke) is dialled at once, whatever the ladder had
316
+ left to wait, and a dial that still finds it booting is back on the ladder's first rung, not on the long rest. */
317
+ test("retryNow ends the long rest and dials at once, and the outage behind it no longer counts", async () => {
318
+ jest.useFakeTimers();
319
+ try {
320
+ const RUNG_MS = 30_000;
321
+ const { link, sockets, said, backoff } = dialling(RUNG_MS);
322
+ for (let attempt = 1; attempt <= LONG_OUTAGE_ATTEMPTS; attempt += 1) {
323
+ // one drop per attempt is serial by definition
324
+ await waitFor(() => expect(sockets).toHaveLength(attempt));
325
+ sockets.at(-1)?.drops(1006);
326
+ if (attempt < LONG_OUTAGE_ATTEMPTS) {
327
+ // ditto
328
+ await advanceTimersByTimeAsync(RUNG_MS);
329
+ }
330
+ }
331
+ // Resting now: the long outage's quarter hour on top of the rung.
332
+ expect(link.outage()).toEqual({ failures: LONG_OUTAGE_ATTEMPTS, since: expect.any(Number) });
333
+ await advanceTimersByTimeAsync(RUNG_MS);
334
+ expect(sockets).toHaveLength(LONG_OUTAGE_ATTEMPTS);
335
+
336
+ link.retryNow();
337
+ await waitFor(() => expect(sockets).toHaveLength(LONG_OUTAGE_ATTEMPTS + 1));
338
+ expect(backoff.resets).toBe(1);
339
+ expect(link.outage()).toBeUndefined();
340
+ expect(link.state()).toBe("connecting");
341
+
342
+ // Still booting: the first failure of a new outage, said out loud, waits one rung and no rest.
343
+ sockets.at(-1)?.drops(PEER_TRY_AGAIN);
344
+ expect(said.at(-1)).toBe("the sandbox is not ready to admit this connection yet; reconnecting in 30s");
345
+ expect(link.outage()).toEqual({ failures: 1, since: expect.any(Number) });
346
+ await advanceTimersByTimeAsync(RUNG_MS);
347
+ await waitFor(() => expect(sockets).toHaveLength(LONG_OUTAGE_ATTEMPTS + 2));
348
+
349
+ // Nothing of the cut wait is left to fire (the one dial it owed has been made): the open socket's watchdog is
350
+ // the one timer armed.
351
+ sockets.at(-1)?.opens();
352
+ expect(link.state()).toBe("open");
353
+ expect(jest.getTimerCount()).toBe(1);
354
+
355
+ link.stop();
356
+ await link.done;
357
+ } finally {
358
+ jest.useRealTimers();
359
+ }
360
+ });
361
+
362
+ test("retryNow dials nothing beside an open link or a dial in flight, and nothing once the link is stopped", async () => {
363
+ jest.useFakeTimers();
364
+ try {
365
+ const { link, sockets, backoff } = dialling(60_000);
366
+ await waitFor(() => expect(sockets).toHaveLength(1));
367
+ // In flight: no second dial beside it, though its ladder is reset so a failure of it retries on the floor.
368
+ link.retryNow();
369
+ await advanceTimersByTimeAsync(0);
370
+ expect(sockets).toHaveLength(1);
371
+ expect(backoff.resets).toBe(1);
372
+
373
+ sockets[0]?.opens();
374
+ link.retryNow();
375
+ await advanceTimersByTimeAsync(0);
376
+ expect(sockets).toHaveLength(1);
377
+ expect(backoff.resets).toBe(1);
378
+ expect(link.state()).toBe("open");
379
+
380
+ sockets[0]?.drops(1006);
381
+ link.stop();
382
+ await link.done;
383
+ link.retryNow();
384
+ await advanceTimersByTimeAsync(120_000);
385
+ expect(sockets).toHaveLength(1);
386
+ expect(backoff.resets).toBe(1);
387
+ expect(jest.getTimerCount()).toBe(0);
388
+ expect(link.state()).toBe("closed");
389
+ } finally {
390
+ jest.useRealTimers();
391
+ }
392
+ });
393
+
308
394
  // A stop that lands while the address is still being decided has nothing to close and must open nothing after
309
395
  // the fact: a socket dialled by a loop that has already reported itself done would be a connection nobody stops.
310
396
  test("a stop during resolution opens nothing, and a socket a slow resolver still hands over is closed", async () => {
@@ -58,8 +58,9 @@ export interface PeerDialSpec<S extends SocketLike> {
58
58
  readonly hello: () => Promise<Record<string, unknown>> | Record<string, unknown>;
59
59
  // Hand the open socket to the oRPC handler serving the door's contract.
60
60
  readonly attach: (socket: S) => void;
61
- // The retry ladder: how long to wait after a drop, given how long the socket had held.
62
- readonly backoff: { readonly next: (heldMs: number) => number };
61
+ // The retry ladder: how long to wait after a drop, given how long the socket had held; `reset` puts it back on its
62
+ // floor (`retryNow`).
63
+ readonly backoff: { readonly next: (heldMs: number) => number; readonly reset: () => void };
63
64
  /* How long this socket may hear nothing before the link is presumed dead: `peerLinkSilenceMs` of the heartbeat the door's own hub pings on. */
64
65
  readonly silenceMs: number;
65
66
  readonly log: (message: string) => void;
@@ -86,8 +87,71 @@ export interface PeerLink {
86
87
  readonly stop: (reason?: string) => void;
87
88
  readonly state: () => PeerLinkState;
88
89
  readonly outage: () => PeerOutage | undefined;
90
+ /* SOMEBODY KNOWS THE FAR END IS BACK, so the link need not wait to find out (2026-10-19). A machine agent that has
91
+ just woken a sleeping sandbox knows it is starting, but the link to it had spent the sleep on the ladder: past
92
+ LONG_OUTAGE_ATTEMPTS each try rests a quarter of an hour, and on rog a sandbox woken at 16:48 had its link back at
93
+ 17:12, 24 minutes with no device tools. This ends a wait on the ladder (the long rest included) and dials now,
94
+ and puts the outage behind it as an answer would (`failures`, the quiet rule, its `since`, the ladder's rung), so
95
+ a dial that finds the sandbox still booting retries on the fast floor. A dial in flight is left to finish and
96
+ only its ladder is reset, so a failure of it retries fast too; an open or stopped link is untouched. */
97
+ readonly retryNow: () => void;
89
98
  }
90
99
 
100
+ /* ONE OUTAGE'S BOOKKEEPING: the attempts that have failed since the link was last open, when the first of them was, and
101
+ what each may say (the quiet rule above). An answer clears it, and so does `retryNow`. */
102
+ const failureRun = (log: (message: string) => void) => {
103
+ let failures = 0;
104
+ // When the loop last complained out loud, and when the CURRENT outage began.
105
+ let quietSince = 0;
106
+ let since: number | undefined;
107
+ return {
108
+ count: (): number => failures,
109
+ // One more failed attempt; answers how many that makes.
110
+ fail: (): number => {
111
+ failures += 1;
112
+ since ??= Date.now();
113
+ return failures;
114
+ },
115
+ /* What ONE failed attempt is allowed to say. */
116
+ complain: (said: string, delay: number): void => {
117
+ const every = `retrying every ${Math.round(delay / 1000)}s`;
118
+ if (failures <= LOUD_ATTEMPTS) {
119
+ log(`${said}; reconnecting in ${Math.round(delay / 1000)}s`);
120
+ return;
121
+ }
122
+ if (failures === LOUD_ATTEMPTS + 1) {
123
+ quietSince = Date.now();
124
+ log(`${said}; still nothing after ${failures} attempts — ${every}, and saying so at most every ${Math.round(QUIET_LOG_MS / 60_000)} minutes from here`);
125
+ return;
126
+ }
127
+ if (Date.now() - quietSince >= QUIET_LOG_MS) {
128
+ quietSince = Date.now();
129
+ log(`${said}; ${failures} failed attempts, ${every}`);
130
+ }
131
+ },
132
+ clear: (): void => {
133
+ failures = 0;
134
+ quietSince = 0;
135
+ since = undefined;
136
+ },
137
+ reading: (): PeerOutage | undefined => (since === undefined ? undefined : { failures, since }),
138
+ };
139
+ };
140
+
141
+ /* THE WAIT ON THE LADDER hangs off the loop's stop, so a link stopped during it is done at once and never dials again,
142
+ and off a controller of its own, which `retryNow` aborts to dial at once. Cutting a wait already over does nothing. */
143
+ const ladderWaits = (stopping: AbortSignal) => {
144
+ let resting: AbortController | undefined;
145
+ return {
146
+ wait: (delay: number, dial: () => Promise<void>): void => {
147
+ const rest = new AbortController();
148
+ resting = rest;
149
+ void sleep(delay, { signal: anySignal(stopping, rest.signal) }).then(() => (stopping.aborted ? undefined : dial()));
150
+ },
151
+ cut: (): void => resting?.abort(),
152
+ };
153
+ };
154
+
91
155
  export const dialPeer = <S extends SocketLike>(spec: PeerDialSpec<S>): PeerLink => {
92
156
  // The loop's whole life: every way it ends (a stop, a revocation, a pairing gone) aborts this, and everything the
93
157
  // loop arms hangs off it, so nothing it left behind can dial, wait or fire once it is over. A stopped link that
@@ -96,32 +160,8 @@ export const dialPeer = <S extends SocketLike>(spec: PeerDialSpec<S>): PeerLink
96
160
  const done = new Promise<void>((resolve) => void whenAborted(stopping.signal, () => resolve()));
97
161
  let socket: S | undefined;
98
162
  let openedAt: number | undefined;
99
- // Consecutive attempts that have failed since this link was last open, and when the loop last complained out
100
- // loud: between them they are the whole of the quiet rule above.
101
- let failures = 0;
102
- let quietSince = 0;
103
- // When the CURRENT outage began, as opposed to when this link was last complained about.
104
- let failingSince: number | undefined;
105
-
106
- /* What ONE failed attempt is allowed to say. */
107
- const complain = (said: string, delay: number): void => {
108
- const every = `retrying every ${Math.round(delay / 1000)}s`;
109
- if (failures <= LOUD_ATTEMPTS) {
110
- spec.log(`${said}; reconnecting in ${Math.round(delay / 1000)}s`);
111
- return;
112
- }
113
- if (failures === LOUD_ATTEMPTS + 1) {
114
- quietSince = Date.now();
115
- spec.log(
116
- `${said}; still nothing after ${failures} attempts — ${every}, and saying so at most every ${Math.round(QUIET_LOG_MS / 60_000)} minutes from here`,
117
- );
118
- return;
119
- }
120
- if (Date.now() - quietSince >= QUIET_LOG_MS) {
121
- quietSince = Date.now();
122
- spec.log(`${said}; ${failures} failed attempts, ${every}`);
123
- }
124
- };
163
+ const outage = failureRun(spec.log);
164
+ const ladder = ladderWaits(stopping.signal);
125
165
 
126
166
  const open = async (): Promise<void> => {
127
167
  const attempt = await spec.open(stopping.signal);
@@ -155,14 +195,11 @@ export const dialPeer = <S extends SocketLike>(spec: PeerDialSpec<S>): PeerLink
155
195
  }
156
196
  const rung = spec.backoff.next(openedAt === undefined ? 0 : Date.now() - openedAt);
157
197
  openedAt = undefined;
158
- failures += 1;
159
- failingSince ??= Date.now();
160
198
  // The rest is added to the ladder's draw rather than replacing it: a flat fifteen minutes would bring back in
161
199
  // lockstep every link that entered the long outage together.
162
- const delay = failures >= LONG_OUTAGE_ATTEMPTS ? LONG_OUTAGE_MS + rung : rung;
163
- complain(said, delay);
164
- // The wait hangs off the stop: a link stopped during it is done at once and never dials again.
165
- void sleep(delay, { signal: stopping.signal }).then(() => (stopping.signal.aborted ? undefined : open()));
200
+ const delay = outage.fail() >= LONG_OUTAGE_ATTEMPTS ? LONG_OUTAGE_MS + rung : rung;
201
+ outage.complain(said, delay);
202
+ ladder.wait(delay, open);
166
203
  };
167
204
 
168
205
  const arm = (): void => {
@@ -189,9 +226,7 @@ export const dialPeer = <S extends SocketLike>(spec: PeerDialSpec<S>): PeerLink
189
226
  openedAt = Date.now();
190
227
  // A link that is up owes nothing to the failures behind it: the next outage is news again, and the
191
228
  // "connected to …" line this open is about to log is what reports the recovery.
192
- failures = 0;
193
- quietSince = 0;
194
- failingSince = undefined;
229
+ outage.clear();
195
230
  arm();
196
231
  spec.attach(ws);
197
232
  const send = (hello: Record<string, unknown>): void => {
@@ -230,7 +265,7 @@ export const dialPeer = <S extends SocketLike>(spec: PeerDialSpec<S>): PeerLink
230
265
 
231
266
  /* Socket errors record a cause; the close event owns retry scheduling. */
232
267
  ws.addEventListener("error", () => {
233
- if (failures < LOUD_ATTEMPTS) {
268
+ if (outage.count() < LOUD_ATTEMPTS) {
234
269
  spec.log("connection error");
235
270
  }
236
271
  });
@@ -251,6 +286,15 @@ export const dialPeer = <S extends SocketLike>(spec: PeerDialSpec<S>): PeerLink
251
286
  // ladder) and a finished one is closed: read off the loop itself, not a flag kept beside it that a redial
252
287
  // firing after the stop could set back.
253
288
  state: () => (socket?.readyState === OPEN ? "open" : stopping.signal.aborted ? "closed" : "connecting"),
254
- outage: () => (failingSince === undefined ? undefined : { failures, since: failingSince }),
289
+ outage: outage.reading,
290
+ retryNow: () => {
291
+ if (stopping.signal.aborted || socket?.readyState === OPEN) {
292
+ return;
293
+ }
294
+ outage.clear();
295
+ spec.backoff.reset();
296
+ // Waiting on the ladder: the wait ends now and its dial follows. A dial in flight has no wait to end.
297
+ ladder.cut();
298
+ },
255
299
  };
256
300
  };
@@ -17,6 +17,15 @@ import { HostsListSchema } from "../../schemas/hosts.js";
17
17
  import { VoicesViewSchema } from "../../schemas/voice.js";
18
18
  import { MemberEmailSchema, MemberGrantSchema, MemberSelfSchema, MembersListSchema, MembersRosterSchema } from "../../schemas/members.js";
19
19
  import { PhonesListSchema, PhoneWakeRegistrationSchema } from "../../schemas/phone.js";
20
+ import {
21
+ PhoneKeyringsResultSchema,
22
+ PhonePasswordsCaptureResultSchema,
23
+ PhonePasswordsCaptureSchema,
24
+ PhonePasswordsFillResultSchema,
25
+ PhonePasswordsFillSchema,
26
+ PhonePasswordsPairResultSchema,
27
+ PhonePasswordsPairSchema,
28
+ } from "../../schemas/phone-passwords.js";
20
29
  import { OkSchema } from "../../schemas/shared.js";
21
30
  import { EnrollCodeAnswerSchema, EnrollCodeRequestSchema, PeerPairingAnswerSchema, SyncPairAnswerSchema, SyncPairRequestSchema } from "../../schemas/short-codes.js";
22
31
  import { SpeechStatusSchema, SpeechTranscriptSchema, SpeechWakeClaimSchema, SpeechWakeGrantSchema } from "../../schemas/speech.js";
@@ -133,6 +142,10 @@ export const RAW_JSON_ROUTES = {
133
142
  "POST /system/phones/pair": { output: PeerPairingAnswerSchema },
134
143
  "DELETE /system/phones/{id}": { output: OkSchema },
135
144
  "POST /system/phones/{id}/wake": { input: PhoneWakeRegistrationSchema, output: OkSchema },
145
+ "GET /system/phones/passwords/keyrings": { output: PhoneKeyringsResultSchema },
146
+ "POST /system/phones/passwords/pair": { input: PhonePasswordsPairSchema, output: PhonePasswordsPairResultSchema },
147
+ "POST /system/phones/passwords/capture": { input: PhonePasswordsCaptureSchema, output: PhonePasswordsCaptureResultSchema },
148
+ "POST /system/phones/passwords/fill": { input: PhonePasswordsFillSchema, output: PhonePasswordsFillResultSchema },
136
149
  "GET /system/runners": { output: RunnersListSchema },
137
150
  "DELETE /system/runners/{id}": { output: OkSchema },
138
151
  "POST /system/runners/{id}/definition/sync": { output: RunnerDefinitionAppliedSchema },
@@ -13,6 +13,8 @@ export const RAW_ROUTES = {
13
13
  // A person opening this sandbox's own address in a browser: sent to the app's /open on it, the address being what
14
14
  // they may still hold when the platform has lost the rest. Anything else gets the same 401 as before it existed.
15
15
  "GET /": { auth: "door", beforeBoot: true },
16
+ // The tab icon a browser asks for on that address: the lotus in the sandbox green, the same bytes for everyone.
17
+ "GET /favicon.ico": { auth: "door", beforeBoot: true },
16
18
  "GET /diff/raw": { lane: "bulk" },
17
19
  // Arming the dictation model is a read any tier makes; dictating is writing a message, the collaborator's grant.
18
20
  "GET /speech/status": { guest: true },
@@ -144,14 +146,17 @@ export const RAW_ROUTES = {
144
146
  "POST /children/answer": { agent: true, control: "never" },
145
147
  "POST /children/cancel": { agent: true, control: "never" },
146
148
  "POST /children/merge": { agent: true, control: "never" },
149
+ "POST /children/settle": { agent: true, control: "never" },
147
150
  // Handing a task to another of the owner's sandboxes over a link card (`agents delegate`), and which links this
148
151
  // conversation's turn may hand work to (`agents links`); held to the cards the turn was granted, like the tool.
149
152
  "POST /children/delegate": { agent: true, control: "never" },
150
153
  "GET /children/links": { agent: true, control: "never" },
151
154
  "GET /children": { agent: true, control: "never" },
152
- // The fleet reads, and the one write: words in front of another conversation, which a person can do by typing.
155
+ // The fleet reads, and its two writes: words in front of another conversation, which a person can do by typing, and
156
+ // the Continue a person can press on one a spent allowance or a stop held (`agents resume`).
153
157
  "GET /fleet": { agent: true },
154
158
  "POST /fleet/message": { agent: true },
159
+ "POST /fleet/resume": { agent: true },
155
160
  "GET /fleet/{handle}": { agent: true },
156
161
  // The `devices push` CLI: a program the agent built, carried to one of the owner's computers in chunks; held to the
157
162
  // devices the calling conversation's turn mounts, and refused by the machine itself unless "Run programs" is on.
@@ -192,6 +197,7 @@ export const RAW_ROUTES = {
192
197
  "DELETE /system/hosts/{id}": { control: "never" },
193
198
  // A peer's socket reconnects on its own backoff, so it answers before boot.
194
199
  "GET /system/hosts/connect": { auth: "door", beforeBoot: true, control: "never" },
200
+ "POST /system/hosts/keyring-changed": { auth: "door", control: "never" },
195
201
  "POST /system/webext/pair": { control: "never" },
196
202
  "POST /system/webext/enroll": { auth: "door", control: "never" },
197
203
  "GET /system/webext": { control: "never" },
@@ -204,6 +210,11 @@ export const RAW_ROUTES = {
204
210
  "GET /system/phones/connect": { auth: "door", beforeBoot: true, control: "never" },
205
211
  // The editor hands over the push-relay channel it registered for a phone, so the sandbox can wake it.
206
212
  "POST /system/phones/{id}/wake": { control: "never" },
213
+ // The phone as Android's autofill service (schemas/phone-passwords.ts): each checks the phone's enrollment token itself.
214
+ "GET /system/phones/passwords/keyrings": { auth: "door", control: "never" },
215
+ "POST /system/phones/passwords/pair": { auth: "door", control: "never" },
216
+ "POST /system/phones/passwords/capture": { auth: "door", control: "never" },
217
+ "POST /system/phones/passwords/fill": { auth: "door", control: "never" },
207
218
  "POST /system/runners/pair": { control: "never" },
208
219
  "POST /system/runners/enroll": { auth: "door", control: "never" },
209
220
  "GET /system/runners": { control: "never" },
@@ -219,6 +230,7 @@ export const RAW_ROUTES = {
219
230
  // A secret the browser types for the agent (`type_secret` aimed at it): one value for one ticket the daemon minted
220
231
  // for this browser and one host, handed back on the browser's own request rather than over the tool socket.
221
232
  "POST /system/webext/secret": { auth: "door", control: "never" },
233
+ "POST /system/webext/grants-changed": { auth: "door", control: "never" },
222
234
  // This sandbox's keyring keys (schemas/keyring.ts), public halves only: a keyring fetches them here over TLS, from the
223
235
  // sandbox's own address, before it shares anything with it, rather than take them from whoever relays the share.
224
236
  "GET /keyring/keys": { auth: "door", control: "never" },
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+
3
+ // WHAT MOVES A CONVERSATION NEXT WITH NOBODY PRESSING ANYTHING: the one answer every surface reads (AgentSummary.next).
4
+ // Five mechanisms can carry a conversation on by themselves: a spent allowance's held turn re-run at its reopen or moved
5
+ // to another account, a message held for memory sent once memory frees, and messages a person booked for a time or for
6
+ // after another conversation lands. Each used to publish its own raw state on the card (a booking flag copied onto the
7
+ // stored ending and re-synced every beat, the queue's own shadow, a failure code plus an answer the editor looked up in
8
+ // Settings), and each surface rebuilt "does it go by itself" from its own subset: the lane from two of them, the card's
9
+ // corner from three, the chat's bar from one more. They disagreed (a memory hold "sends when room" in the corner and
10
+ // waited in Attention; a booked resend read as Attention after a restart; a booked message cancelled with an archive
11
+ // that never counted it). The daemon now derives this one value from what the conversation holds, every time the card
12
+ // is read (conversation-next.ts), and nothing else on the card says whether or when it goes by itself.
13
+ export const AgentNextSchema = z.discriminatedUnion("kind", [
14
+ z.object({
15
+ kind: z.literal("rerun"),
16
+ at: z.number().describe("When the held turn goes again, in milliseconds: its allowance's reopen, or the next pass for a move. Already past means any moment now."),
17
+ onto: z.string().optional().describe("The account the owner's answer to the limit is moving it to. Absent when it goes again where it was refused."),
18
+ }),
19
+ z.object({ kind: z.literal("room") }).describe("A message, or a turn the sandbox kept, held because memory ran short: it goes once memory has stayed free a while."),
20
+ z.object({
21
+ kind: z.literal("send"),
22
+ at: z.number().describe("When the soonest booked message goes, in milliseconds."),
23
+ count: z.number().int().min(1).describe("How many messages are booked to go by themselves."),
24
+ }),
25
+ z.object({
26
+ kind: z.literal("land"),
27
+ after: z.string().describe("The conversation whose landed work the first booked message waits for."),
28
+ count: z.number().int().min(1).describe("How many messages are booked to go by themselves."),
29
+ }),
30
+ ]);
31
+ export type AgentNext = z.infer<typeof AgentNextSchema>;
32
+
33
+ /** Whether a conversation carries on by itself, with nobody pressing anything: the one reading of `next`. */
34
+ export const goesBySelf = (agent: { readonly next?: AgentNext | undefined }): boolean => agent.next !== undefined;
@@ -0,0 +1,22 @@
1
+ import { z } from "zod";
2
+
3
+ // Words put in an agent's mouth (`agents.place`): what is asked, and what the record answers.
4
+
5
+ // Bounded just above the handoff's per-message render cap, so a line too long to carry whole doesn't reach the agent
6
+ // truncated.
7
+ export const AgentPlaceSchema = z.object({
8
+ id: z.string().min(1).describe("Which conversation."),
9
+ text: z
10
+ .string()
11
+ .trim()
12
+ .min(1)
13
+ .max(8_000)
14
+ .describe(
15
+ "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.",
16
+ ),
17
+ });
18
+ // The placed line's own id, so the window that placed it holds the same row its next read of the record brings.
19
+ export const AgentPlacedSchema = z.object({
20
+ ok: z.literal(true).describe("Always true: the line is on the record."),
21
+ rowId: z.string().optional().describe("The `rowId` the line was recorded under. Absent from a sandbox older than row ids."),
22
+ });
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+
3
+ // The board's search over what conversations said: the query, and what came back with its evidence.
4
+
5
+ // Searches only speech, both sides of the conversation, never thinking, tool output or protocol text, which would
6
+ // otherwise match nearly the whole board. Two-char minimum; `caseSensitive` off means case-insensitive, matching
7
+ // workspace search's own switch.
8
+ export const AgentSearchQuerySchema = z.object({
9
+ query: z
10
+ .string()
11
+ .trim()
12
+ .min(2)
13
+ .describe(
14
+ "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.",
15
+ ),
16
+ caseSensitive: z.stringbool().optional().describe("Whether capitals matter."),
17
+ });
18
+ // Why a row survived the filter: the matched line, windowed, and who said it. `speaker` rides with the text since agent
19
+ // prose alone can read as something the user typed.
20
+ export const SpeakerSchema = z.enum(["user", "agent"]);
21
+ export type Speaker = z.infer<typeof SpeakerSchema>;
22
+ export const MatchSnippetSchema = z.object({
23
+ text: z.string().describe("The matching line, with a little either side of it."),
24
+ speaker: SpeakerSchema.describe(
25
+ "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.",
26
+ ),
27
+ });
28
+ export type MatchSnippet = z.infer<typeof MatchSnippetSchema>;
29
+ // One matching agent and its evidence; `snippet` is absent for a title match, which the card already shows.
30
+ export const AgentMatchSchema = z.object({
31
+ id: z.string().describe("Which conversation matched."),
32
+ snippet: MatchSnippetSchema.optional().describe(
33
+ "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.",
34
+ ),
35
+ });
36
+ export type AgentMatch = z.infer<typeof AgentMatchSchema>;
37
+ // How many agents were actually read, so the board can say a search saw less than the whole fleet.
38
+ export const AgentSearchResultSchema = z.object({
39
+ matches: z.array(AgentMatchSchema).describe("What matched, from the live fleet and the archive together."),
40
+ scanned: z
41
+ .number()
42
+ .describe(
43
+ "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.",
44
+ ),
45
+ indexing: z
46
+ .boolean()
47
+ .describe(
48
+ "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.",
49
+ ),
50
+ });
51
+ export type AgentSearchResult = z.infer<typeof AgentSearchResultSchema>;