@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
@@ -0,0 +1,86 @@
1
+ import { z } from "zod";
2
+ import { type PrivacyShieldPolicy, trustedInConversation } from "./privacy.js";
3
+
4
+ // THE ONE DECISION about bytes bound for a model provider: pass them as they are, watch them, mask them, or refuse them.
5
+ // Every place they leave by asks it (the gateway, a hooked runtime's channels, a sealed helper prompt, a turn's
6
+ // admission, a runner's placement, a credential that would go around the gateway), and so does the editor before a
7
+ // send, so the warning above the composer is this verdict and never a guess of its own. Before 2026-10-20 the formula
8
+ // was written out at each of those places, and they drifted: helpers refused where turns ran, a child kept here where
9
+ // its parent could go, a strip that warned on opening a composer and stayed silent about a runner.
10
+
11
+ // How bytes reach the provider. Through a seam the shield reads every byte at: the gateway a runtime is pointed at, the
12
+ // hooks a runtime hands each channel's text to before its model reads it, a sealed prompt (a helper's whole request, in
13
+ // hand before any runtime has it). Or past every seam: a runtime with neither (an ACP agent, Pi), a runner calling its
14
+ // provider from its own machine, a key the provider is called with directly (Codex on the container's OpenAI key), a
15
+ // shared server started before the shield was on.
16
+ export type PrivacySeam = "gateway" | "hooks" | "sealed";
17
+ export const PrivacyBypassSchema = z.enum(["runtime", "runner", "own-key", "shared-server"]);
18
+ export type PrivacyBypass = z.infer<typeof PrivacyBypassSchema>;
19
+ export type PrivacyRoute = PrivacySeam | PrivacyBypass;
20
+
21
+ const SEAMS: ReadonlySet<PrivacyRoute> = new Set<PrivacySeam>(["gateway", "hooks", "sealed"]);
22
+ const isSeam = (route: PrivacyRoute): route is PrivacySeam => SEAMS.has(route);
23
+
24
+ // The route of a turn on a runtime, from its `privacy` capability (agent-runtimes.ts), placed on `runner` or here.
25
+ export const turnRoute = (privacy: "gateway" | "hooks" | "none", runner?: string): PrivacyRoute =>
26
+ runner !== undefined ? "runner" : privacy === "none" ? "runtime" : privacy;
27
+
28
+ export interface PrivacyEgress {
29
+ readonly provider: string;
30
+ // A model this machine serves: nothing it reads leaves.
31
+ readonly local: boolean;
32
+ // A conversation's own grant counts there; a request outside any conversation has none.
33
+ readonly conversationId?: string | undefined;
34
+ readonly route: PrivacyRoute;
35
+ }
36
+
37
+ // Why bytes pass as they are: the shield is off, the model is on this machine, the owner trusts the provider everywhere
38
+ // or let it read this conversation, or the shield only watches and cannot see this route at all.
39
+ export type PassReason = "off" | "local" | "trusted" | "granted" | "unwatched";
40
+
41
+ export type ShieldVerdict =
42
+ | { readonly kind: "pass"; readonly because: PassReason }
43
+ | { readonly kind: "watch" }
44
+ | { readonly kind: "mask" }
45
+ | { readonly kind: "refuse"; readonly route: PrivacyBypass };
46
+
47
+ const pass = (because: PassReason): ShieldVerdict => ({ kind: "pass", because });
48
+
49
+ export const shieldVerdict = (policy: Pick<PrivacyShieldPolicy, "mode" | "trusted" | "conversations">, egress: PrivacyEgress): ShieldVerdict => {
50
+ if (policy.mode === "off") {
51
+ return pass("off");
52
+ }
53
+ if (egress.local) {
54
+ return pass("local");
55
+ }
56
+ if (policy.trusted.includes(egress.provider)) {
57
+ return pass("trusted");
58
+ }
59
+ if (trustedInConversation(policy, egress.provider, egress.conversationId)) {
60
+ return pass("granted");
61
+ }
62
+ if (!isSeam(egress.route)) {
63
+ return policy.mode === "on" ? { kind: "refuse", route: egress.route } : pass("unwatched");
64
+ }
65
+ return policy.mode === "on" ? { kind: "mask" } : { kind: "watch" };
66
+ };
67
+
68
+ // Whether the owner let the provider read what it is sent as it is (here, everywhere, or in this conversation): what
69
+ // the log calls trusted.
70
+ export const ownerTrusted = (verdict: ShieldVerdict): boolean =>
71
+ verdict.kind === "pass" && (verdict.because === "local" || verdict.because === "trusted" || verdict.because === "granted");
72
+
73
+ // The failure codes a turn the shield turned away ends with: refused by its verdict (`privacy-unshielded`), or for what
74
+ // it found where it could not mask (`privacy-instructions`). The way through both is the same grant.
75
+ const REFUSAL_CODES = ["privacy-unshielded", "privacy-instructions"] as const;
76
+ export type PrivacyRefusalCode = (typeof REFUSAL_CODES)[number];
77
+ const REFUSAL_CODE_SET: ReadonlySet<string> = new Set(REFUSAL_CODES);
78
+ export const isPrivacyRefusal = (code: string | undefined): code is PrivacyRefusalCode => code !== undefined && REFUSAL_CODE_SET.has(code);
79
+
80
+ // A refusal as the shield both words and types it: the sentence a turn ends with, and the route its verdict refused,
81
+ // which rides the turn's error frame (`privacyRoute`) so a reader acts on the route rather than on the sentence. Absent
82
+ // for a policy that could not be read, which refuses whatever the route.
83
+ export interface PrivacyRefusal {
84
+ readonly sentence: string;
85
+ readonly route?: PrivacyBypass;
86
+ }
@@ -42,6 +42,10 @@ export type PrivacyNames = z.infer<typeof PrivacyNamesSchema>;
42
42
 
43
43
  export const PRIVACY_TRUSTED_MAX = 200;
44
44
  export const PRIVACY_ALLOW_MAX = 1000;
45
+
46
+ // How a never-masked value (policy `allow`) is compared with what the shield finds, by the detectors and by the editor
47
+ // that keeps the list: case, Unicode composition and runs of whitespace do not tell two values apart.
48
+ export const allowKey = (value: string): string => value.normalize("NFC").toLowerCase().replace(/\s+/g, " ").trim();
45
49
  export const PRIVACY_CONVERSATIONS_MAX = 200;
46
50
 
47
51
  // The owner's own additions to what the shield finds. The policy travels whole on every write, so each is kept to what a
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
 
3
- // LANDED WORK DELIVERED TO THE OWNER'S FOLDER. A folder attached to this computer's own sandbox is copied one way into
3
+ // LANDED WORK DELIVERED TO THE OWNER'S FOLDER. A folder with a sandbox made for it is copied one way into
4
4
  // `/work/<name>`; when a conversation's work lands there, the daemon hands the same change to the machine agent that
5
5
  // holds the folder, which applies it file by file under a restore point and never over an edit of the owner's own.
6
6
  // The daemon asks (`deliverProject` on the device contract), the machine decides and writes; nothing an agent runs can
@@ -0,0 +1,16 @@
1
+ import { sandboxAnswerSchema } from "../../index.js";
2
+ import { ProviderRefusalsSchema } from "./plan-limits.js";
3
+
4
+ // 2026-10-21: /agent/refusals went from one refusal per provider to a list per provider, and the editor parses every
5
+ // answer with its own build's schema. Against a released daemon (1.249.0 to 1.345.0) the parse failed, the read was kept
6
+ // as nothing, and every spent account and model read as ready.
7
+ test("reads a released daemon's one refusal per provider as a list of one, and today's lists as they are", () => {
8
+ const spent = { at: 1_760_000_000_000, kind: "limit", message: "Claude AI usage limit reached", account: "acct-1", resetsAt: 1_760_010_000 };
9
+ const schema = sandboxAnswerSchema(["agent", "refusals"]);
10
+ const older = schema?.safeParse({ refusals: { claude: spent } });
11
+ expect(older?.success).toBe(true);
12
+ expect(older?.data).toEqual({ refusals: { claude: [spent] } });
13
+ const today = { refusals: { claude: [spent, { at: 1_760_000_000_001, kind: "auth", message: "OAuth token revoked", account: "acct-2" }], codex: [] } };
14
+ expect(schema?.safeParse(today).data).toEqual(today);
15
+ expect(ProviderRefusalsSchema.safeParse({ refusals: { claude: "spent" } }).success).toBe(false);
16
+ });
@@ -36,6 +36,12 @@ export const UsageWindowSchema = z.object({
36
36
  .describe(
37
37
  "When the window this pool was last read in closed, in epoch seconds, while nothing has read the pool since. Its `utilization` is then 0, the floor every new window starts from, not a measurement, and `resetsAt` is absent because the next reset is unknown.",
38
38
  ),
39
+ missingSince: z
40
+ .number()
41
+ .optional()
42
+ .describe(
43
+ "When the provider stopped reporting this pool, in epoch seconds: a later reading of the account named every other pool but not this one. Its figure is the last one read, still a valid floor until its window closes, and the pool is dropped once it has.",
44
+ ),
39
45
  });
40
46
  export type UsageWindow = z.infer<typeof UsageWindowSchema>;
41
47
  // A failed re-read, whatever the cause: a 429 park, a 403 asking for verification, a 5xx, a timeout. Recorded as the fact
@@ -50,6 +56,12 @@ export const UsageUnreadSchema = z.object({
50
56
  ),
51
57
  });
52
58
  export type UsageUnread = z.infer<typeof UsageUnreadSchema>;
59
+ // A turn answered against a reading that said its model could not run: the provider's own word that the reading is wrong.
60
+ export const UsageContradictionSchema = z.object({
61
+ at: z.number().describe("When the turn was answered, in milliseconds."),
62
+ model: z.string().describe("The model the answered turn ran on."),
63
+ });
64
+ export type UsageContradiction = z.infer<typeof UsageContradictionSchema>;
53
65
  // Every window kept, not just the binding one, since which pool binds changes between turns. Utilization only climbs
54
66
  // within a window, so a stale reading is still a valid floor. `measuredAt` is epoch ms — windows are seconds.
55
67
  export const AccountUsageSchema = z.object({
@@ -58,15 +70,25 @@ export const AccountUsageSchema = z.object({
58
70
  unread: UsageUnreadSchema.optional().describe(
59
71
  "Present while re-reading this account keeps failing: these windows are the last reading that succeeded, and `measuredAt` will not move until a read succeeds again.",
60
72
  ),
73
+ uncovered: z
74
+ .array(z.string())
75
+ .optional()
76
+ .describe(
77
+ "Models this account serves that no pool in this reading gates, by id: the provider published no allowance for them, so their room is unknown, never assumed spent. Absent when every model is covered or the account's models are not known.",
78
+ ),
79
+ contradicted: UsageContradictionSchema.optional()
80
+ .describe(
81
+ "A turn on `model` was answered after this reading said every pool it spends was empty, so the reading is wrong about that model: those pools read as at the line, not spent, until a new reading replaces this one.",
82
+ ),
61
83
  });
62
84
  export type AccountUsage = z.infer<typeof AccountUsageSchema>;
63
85
  // Who has to act for a blocked account, which is the only thing a surface chooses its instruction by: the reason is the
64
86
  // words for a person, never a key.
65
87
  export const AccountFixSchema = z.enum(["reconnect", "admin", "verify", "wait"]);
66
88
  export type AccountFix = z.infer<typeof AccountFixSchema>;
67
- // Whether an account can serve a turn, decided once by the daemon (models/plan-pools.ts `serviceState`) from every fact
68
- // it holds about it: a revoked sign-in, a lost seat, a translator bench, a refusal still standing, and its plan limits.
69
- // Every picker (an unnamed turn, a limit move, a keep-warm refresh) and every surface reads this one verdict.
89
+ // Whether an account can serve a turn, judged by one rule (models/plan-pools.ts `serviceStates`) from every fact on file
90
+ // about it: a revoked sign-in, a lost seat, a translator bench, every refusal still standing, and its plan limits. The
91
+ // daemon and the editor run that rule on the same facts; nothing publishes or keeps a judged copy.
70
92
  export const AccountStateSchema = z.discriminatedUnion("kind", [
71
93
  z.object({
72
94
  kind: z.literal("ready"),
@@ -82,6 +104,10 @@ export const AccountStateSchema = z.discriminatedUnion("kind", [
82
104
  .number()
83
105
  .optional()
84
106
  .describe("When every full pool has reopened, in epoch seconds, where the plan publishes it. Absent means unknown, never now."),
107
+ pool: z
108
+ .string()
109
+ .optional()
110
+ .describe("The pool holding it shut, by the plan's own name for it, where the plan meters it apart from other models. Absent for an undivided allowance."),
85
111
  }),
86
112
  z.object({
87
113
  kind: z.literal("blocked"),
@@ -123,49 +149,7 @@ export const LimitResetClaimSchema = z.object({
123
149
  detail: z.string().optional().describe("What went wrong, in words, for the two outcomes that are this sandbox's fault rather than the plan's."),
124
150
  });
125
151
  export type LimitResetClaim = z.infer<typeof LimitResetClaimSchema>;
126
- // Observed and exact, unlike a polled usage snapshot that can be stale; keyed by provider, not account, since a routed
127
- // turn doesn't know which served it. `kind` is read off what the provider said, not the frame code.
128
- export const ProviderRefusalSchema = z.object({
129
- // Read side by side with `AccountUsage.measuredAt` (also ms).
130
- at: z.number().describe("When it refused, in milliseconds."),
131
- // Only a turn that actually runs settles an entitlement refusal — nothing else can.
132
- kind: z
133
- .enum(["limit", "auth", "entitlement"])
134
- .describe(
135
- "Three different noes, kept apart because what fixes each is different. A spent allowance is answered by waiting; a refused credential by signing in again; and an entitlement refusal, where somebody has switched this off for your seat, by neither of those. That last one authenticates fine and reports healthy limits the whole time it refuses everything.",
136
- ),
137
- message: z.string().describe("The provider's own words, verbatim. The only part that says which limit or which credential."),
138
- // Known for native turns only; a routed turn doesn't say which account served it.
139
- account: z.string().optional().describe("Which account was serving, where that is known."),
140
- // Lets a `limit` refusal be read against the pool that model spends (`UsageWindow.gates`), not the account's
141
- // fullest pool.
142
- model: z.string().optional().describe("Which model the refused turn was on, where that is known."),
143
- // The provider's own "try again at …", which a polled reading cannot contradict: a usage endpoint can keep showing
144
- // room while the plan refuses every turn.
145
- resetsAt: z
146
- .number()
147
- .optional()
148
- .describe(
149
- "When the provider said to try again, in epoch seconds, for a spent allowance where it named one. Until then the refusal stands whatever a reading says; after it, it is over.",
150
- ),
151
- // Codex's "To get more access now, send a request to your admin": a team's credit, which no usage endpoint reads,
152
- // so a weekly pool at 57% says nothing about it (2026-10-17).
153
- unmetered: z
154
- .literal(true)
155
- .optional()
156
- .describe(
157
- "Set on a spent allowance no usage reading measures, such as a credit an organisation's admin grants. No reading answers it: it stands until the provider's own reset, or until a turn is answered.",
158
- ),
159
- });
160
- export type ProviderRefusal = z.infer<typeof ProviderRefusalSchema>;
161
- export const ProviderRefusalsSchema = z.object({
162
- refusals: z
163
- .record(z.string(), ProviderRefusalSchema)
164
- .describe(
165
- "The most recent refusal per provider. Read alongside an account's usage: that says how full it was when last checked, this says whether it has since started saying no.",
166
- ),
167
- });
168
- export type ProviderRefusals = z.infer<typeof ProviderRefusalsSchema>;
152
+ export { type ProviderRefusal, ProviderRefusalSchema, type ProviderRefusals, ProviderRefusalsSchema } from "./refusals.js";
169
153
  // `name` is CLIProxyAPI's auth-file name, the stable key a disconnect addresses; `label` is the reported sign-in
170
154
  // identity (email, else the file name).
171
155
  export const TranslatorAccountSchema = z.object({
@@ -190,9 +174,6 @@ export const TranslatorAccountSchema = z.object({
190
174
  verify: z.string().optional(),
191
175
  })
192
176
  .optional(),
193
- state: AccountStateSchema.optional().describe(
194
- "Whether it can serve a turn now, judged from everything above plus the provider's last refusal. Absent from a daemon older than this field.",
195
- ),
196
177
  });
197
178
  export type TranslatorAccount = z.infer<typeof TranslatorAccountSchema>;
198
179
  // A list per provider, not a flag: CLIProxyAPI holds several auth files per provider and balances across them. Built
@@ -408,6 +389,8 @@ export const ResumeRoutingSchema = z.object({
408
389
  ),
409
390
  // A client whose catalog hasn't loaded has nothing to send; the turn's own model is the better fallback.
410
391
  model: z.string().optional().describe("Which model. Leave it out to keep the one the refused turn named."),
392
+ // A tier named for one model may mean nothing on another, so a move onto a ladder rung carries that rung's own.
393
+ effort: z.string().optional().describe("How hard the model should think on the re-run. Leave it out to keep the refused turn's."),
411
394
  // A session is a file the daemon keeps; a credential is an env var. That's what lets a same-provider account switch
412
395
  // resume the existing session instead of opening a fresh one.
413
396
  carry: z
@@ -458,6 +441,19 @@ export const QueueResumeSchema = z.object({
458
441
  ),
459
442
  });
460
443
  export type QueueResume = z.infer<typeof QueueResumeSchema>;
444
+ // Points a person's waiting messages at another provider, model or account without letting them go: what a pick in the
445
+ // model picker does to the words already waiting, which would otherwise go by themselves on the pick they were sent under.
446
+ export const QueueRerouteSchema = z.object({
447
+ conversationId: z.string().min(1).describe("Whose queue."),
448
+ routing: ResumeRoutingSchema.describe(
449
+ "Who serves the turn each message starts from now on. A model or effort left out keeps each message's own; an account left out goes on the conversation's own when it goes.",
450
+ ),
451
+ ids: z
452
+ .array(z.string().min(1))
453
+ .optional()
454
+ .describe("Which waiting messages to move. Leave it out to move every person's waiting message, held or booked; each keeps its own booking."),
455
+ });
456
+ export type QueueReroute = z.infer<typeof QueueRerouteSchema>;
461
457
  // Re-times what a conversation's queue holds: the same messages (or only those `ids` names), booked for another instant
462
458
  // or for after another conversation's work lands. One of the two, never both, since a booking waits on exactly one thing.
463
459
  export const QueueScheduleSchema = z
@@ -472,6 +468,12 @@ export const QueueScheduleSchema = z
472
468
  sendAfter: ConversationIdSchema.optional().describe(
473
469
  "Send what waits once that conversation has finished and all of its work has landed in the workspace, instead. Sent now when it has nothing running and nothing left to land.",
474
470
  ),
471
+ sendAtReopen: z
472
+ .literal(true)
473
+ .optional()
474
+ .describe(
475
+ "Says `sendAt` is the reopen of the allowance what waits would be refused by, not a time you chose; the queue records it as `reopenOf`. Only with `sendAt`.",
476
+ ),
475
477
  ids: z
476
478
  .array(z.string().min(1))
477
479
  .optional()
@@ -497,6 +499,10 @@ export const QueueContinueSchema = z
497
499
  .optional()
498
500
  .describe("Carry on at this instant (epoch milliseconds). At most a month ahead; an instant already past carries on now."),
499
501
  sendAfter: ConversationIdSchema.optional().describe("Carry on once that conversation has finished and all of its work has landed, instead."),
502
+ sendAtReopen: z
503
+ .literal(true)
504
+ .optional()
505
+ .describe("Says `sendAt` is the reopen of a spent allowance, not a time you chose; the queue records it as `reopenOf`. Only with `sendAt`."),
500
506
  routing: ResumeRoutingSchema.optional().describe(
501
507
  "Who serves the turn it starts. Leave it out to carry on where the conversation runs when it goes.",
502
508
  ),
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { AccountStateSchema, AccountUsageSchema } from "./plan-limits.js";
2
+ import { AccountUsageSchema } from "./plan-limits.js";
3
3
  import { SignInCatcherSchema } from "../loopback-catch.js";
4
4
  import { KeyedProviderSchema } from "./provider-subscriptions.js";
5
5
  // Claude uses PKCE paste-back (start → exchange); Codex uses OpenAI's device-code flow (start → poll). A sandbox can
@@ -38,9 +38,6 @@ export const OauthAccountSchema = z.object({
38
38
  usage: AccountUsageSchema.optional().describe(
39
39
  "How full its plan limits were when last measured, so a picker can show what is left before committing work to it. Absent until a reading exists, which reads as unknown rather than as nothing left.",
40
40
  ),
41
- state: AccountStateSchema.optional().describe(
42
- "Whether it can serve a turn now, judged once from the sign-in, the seat, the provider's last refusal and the plan limits: the verdict every picker in the sandbox uses. Read this rather than the fields it was judged from. Absent from a daemon older than this field.",
43
- ),
44
41
  });
45
42
  export type OauthAccount = z.infer<typeof OauthAccountSchema>;
46
43
  export const OauthAccountListSchema = z.object({
@@ -191,15 +188,6 @@ export const ModelSchema = z.object({
191
188
  helperOnly: HelperOnlySchema.optional().describe(
192
189
  "Set where this model may write commit messages, titles and other one-shot jobs but never run a chat turn, and why: its server says it cannot call tools, or it is the small local model kept for quick jobs. Absent means nothing has said it cannot.",
193
190
  ),
194
- // Epoch seconds. A fact about the MODEL, not about any one account: a routed provider balances across credentials,
195
- // so a model every one of them is benched on is unrunnable however much headroom their rings show. Absent is the
196
- // ordinary case and means runnable, never "unknown".
197
- availableAt: z
198
- .number()
199
- .optional()
200
- .describe(
201
- "When this model can be asked again, where every credential that serves it is currently refused. Absent means it can be asked now. A model here is still worth showing, unlike one the plan does not cover at all: the wait is the whole answer.",
202
- ),
203
191
  });
204
192
  export type Model = z.infer<typeof ModelSchema>;
205
193
  export const ModelsSchema = z.object({
@@ -0,0 +1,62 @@
1
+ import { z } from "zod";
2
+
3
+ // WHAT A PROVIDER SAID WHEN IT REFUSED A TURN, and the ledger of them the sandbox answers with. Kept out of plan-limits.ts,
4
+ // which re-exports both, so the plan and turn schemas there stay within one file's reach.
5
+
6
+ // Observed and exact, unlike a polled usage snapshot that can be stale; keyed by provider, not account, since a routed
7
+ // turn doesn't know which served it. `kind` is read off what the provider said, not the frame code.
8
+ export const ProviderRefusalSchema = z.object({
9
+ // Read side by side with `AccountUsage.measuredAt` (also ms).
10
+ at: z.number().describe("When it refused, in milliseconds."),
11
+ // Only a turn that actually runs settles an entitlement refusal — nothing else can.
12
+ kind: z
13
+ .enum(["limit", "auth", "entitlement"])
14
+ .describe(
15
+ "Three different noes, kept apart because what fixes each is different. A spent allowance is answered by waiting; a refused credential by signing in again; and an entitlement refusal, where somebody has switched this off for your seat, by neither of those. That last one authenticates fine and reports healthy limits the whole time it refuses everything.",
16
+ ),
17
+ message: z.string().describe("The provider's own words, verbatim. The only part that says which limit or which credential."),
18
+ // Known for native turns only; a routed turn doesn't say which account served it.
19
+ account: z.string().optional().describe("Which account was serving, where that is known."),
20
+ // Lets a `limit` refusal be read against the pool that model spends (`UsageWindow.gates`), not the account's
21
+ // fullest pool.
22
+ model: z.string().optional().describe("Which model the refused turn was on, where that is known."),
23
+ // The provider's own "try again at …", which a polled reading cannot contradict: a usage endpoint can keep showing
24
+ // room while the plan refuses every turn.
25
+ resetsAt: z
26
+ .number()
27
+ .optional()
28
+ .describe(
29
+ "When the provider said to try again, in epoch seconds, for a spent allowance where it named one. Until then the refusal stands whatever a reading says; after it, it is over.",
30
+ ),
31
+ // Stamped by the daemon's ledger as it files a spent allowance naming no instant (plan-pools.ts refusedPoolReset).
32
+ poolResetsAt: z.number().optional().describe("Epoch seconds the refused pool reopens, for a spent allowance naming no time: it ends then."),
33
+ // Cursor's "ask your admin to increase your limit": a team's spend limit, which no usage endpoint reads. Not Codex's
34
+ // "send a request to your admin", which names a window its reading measures (failure-sentences.ts ADMIN_GRANTED).
35
+ unmetered: z
36
+ .literal(true)
37
+ .optional()
38
+ .describe(
39
+ "Set on a spent allowance no usage reading measures, such as a credit an organisation's admin grants. No reading answers it: it stands until the provider's own reset, or until a turn is answered.",
40
+ ),
41
+ byHand: z
42
+ .literal(true)
43
+ .optional()
44
+ .describe(
45
+ "Set by a person rather than by a refused turn, for a plan nothing can read: believed for a day, or until unmarked or a turn on it is answered.",
46
+ ),
47
+ });
48
+ export type ProviderRefusal = z.infer<typeof ProviderRefusalSchema>;
49
+ // A released daemon (1.345.0 and earlier) answers one refusal per provider, its last: read as a list of one, as the
50
+ // /events frame's `refusal` is (refusalsOf). What this build sends, and its output shape, is still the list.
51
+ const RefusalsOnFileSchema = z.codec(z.union([z.array(ProviderRefusalSchema), ProviderRefusalSchema]), z.array(ProviderRefusalSchema), {
52
+ decode: (filed) => (Array.isArray(filed) ? filed : [filed]),
53
+ encode: (list) => list,
54
+ });
55
+ export const ProviderRefusalsSchema = z.object({
56
+ refusals: z
57
+ .record(z.string(), RefusalsOnFileSchema)
58
+ .describe(
59
+ "Every refusal on file per provider, each the latest of its kind for the account and model it names: what every verdict on that provider's accounts is judged against. Read alongside an account's usage: that says how full it was when last checked, these say whether it has since started saying no.",
60
+ ),
61
+ });
62
+ export type ProviderRefusals = z.infer<typeof ProviderRefusalsSchema>;
@@ -74,6 +74,8 @@ export const UsageTurnSchema = z.object({
74
74
  iqSearchCohort: z.string().optional(),
75
75
  // Every tool call that searched, including CLI searches like `iq q`; absent means unmeasured, not zero.
76
76
  searchCalls: z.number().optional(),
77
+ // Of searchCalls, the ones that ran iq: the search teaching's uptake. Absent on rows written before 2026-10-19.
78
+ iqSearches: z.number().optional(),
77
79
  // Search calls before the first file touch; absent as searchCalls; a turn touching nothing counts them all.
78
80
  openingSearches: z.number().optional(),
79
81
  // Directory listings (ls, tree, LS tool) before the turn's first file touch, same window as openingSearches.
@@ -3,8 +3,9 @@ import { z } from "zod";
3
3
  // The daemon is the only tier that knows what the agent is doing, so it is the sender. A registration is per-device, in
4
4
  // two kinds:
5
5
  // webpush: a browser (including the Android TWA); the daemon sends to its push service directly, end-to-end encrypted.
6
- // relay: a native app (iOS); its OS push service only accepts sends from the vendor, so the daemon posts through a
7
- // relay, which can read the payload.
6
+ // relay: a native app (the iPhone app, the Android editor app, the Intentic Device app); its OS push service only accepts
7
+ // sends from the vendor, so the daemon posts through a relay, which can read the payload. Only Apple is handed the words:
8
+ // an Android app gets a data-only message and fetches them from the daemon itself.
8
9
 
9
10
  // Exact shape `web-push` consumes, from `PushManager.subscribe()`; posted back verbatim.
10
11
  export const WebPushChannelSchema = z.object({
@@ -26,7 +27,12 @@ export const RelayChannelSchema = z.object({
26
27
  ),
27
28
  url: z.url().describe("Where to post a send. Recorded rather than assumed, so the sandbox need not know any platform by name."),
28
29
  deviceId: z.string().min(1).describe("The device's id, which also identifies this registration everywhere else in this group."),
29
- secret: z.string().min(1).describe("Proof that this sandbox may notify this device. The relay never learns which sandbox is calling."),
30
+ secret: z
31
+ .string()
32
+ .min(1)
33
+ .describe(
34
+ "Proof that this sandbox may notify this device. A send names no sandbox; the relay knows which sandbox a device belongs to only when the editor app registered it for that one sandbox, so the app can be told which sandbox to ask.",
35
+ ),
30
36
  });
31
37
  export type RelayChannel = z.infer<typeof RelayChannelSchema>;
32
38
  export const PushChannelSchema = z.discriminatedUnion("kind", [WebPushChannelSchema, RelayChannelSchema]);
@@ -61,6 +67,16 @@ export const PushNotificationSchema = z.object({
61
67
  ),
62
68
  });
63
69
  export type PushNotification = z.infer<typeof PushNotificationSchema>;
70
+ export const PushSentQuerySchema = z.object({
71
+ tag: z.string().min(1).describe("The tag the push carried, which is all a native app's push says about what it was."),
72
+ });
73
+ // What a native app's data-only push leaves out, read back over the app's own session so the words never pass through
74
+ // the push service or the relay.
75
+ export const PushSentNotificationSchema = PushNotificationSchema.extend({
76
+ tag: z.string().min(1).describe("The tag it was sent under, the one asked for."),
77
+ sentAt: z.string().describe("When the sandbox sent it (ISO)."),
78
+ });
79
+ export type PushSentNotification = z.infer<typeof PushSentNotificationSchema>;
64
80
  export const PushConfigSchema = z.object({
65
81
  publicKey: z.string().describe("The key a browser needs in order to subscribe. Native apps ignore it."),
66
82
  subscribed: z
@@ -0,0 +1,88 @@
1
+ import { z } from "zod";
2
+ import { KeyringOriginSchema, KeyringRememberSchema, KeyringShareModeSchema } from "./keyring.js";
3
+
4
+ // THE SANDBOX'S SIDE OF PASSWORDS (2026-10-19): an agent asking for a credential by where it is to be used (`secrets
5
+ // want`, `type_secret` aimed at a page or a window), and the hosted Passwords view's three reads. The vault and its
6
+ // management stay on the owner's computers; what a sandbox learns of an entry is the pointer its keyring shared here.
7
+
8
+ /** `secrets want`: a credential by the place it is for, asked of the owner's keyrings. */
9
+ export const SecretWantSchema = z
10
+ .object({
11
+ origin: KeyringOriginSchema.describe("Where it is to be used: a site, a program on the owner's computer, an ssh target, a git host."),
12
+ username: z.string().max(256).optional().describe("The account wanted, when the agent knows it."),
13
+ why: z.string().min(1).max(300).describe("What it is for, in words for the person's prompt."),
14
+ // Filled by the CLI itself, from the running turn, so the prompt names the conversation that asked.
15
+ conversationId: z.string().max(200).optional(),
16
+ })
17
+ .strict();
18
+ export type SecretWant = z.infer<typeof SecretWantSchema>;
19
+
20
+ export const SecretWantResultSchema = z.discriminatedUnion("state", [
21
+ z.object({
22
+ state: z.literal("allowed"),
23
+ name: z.string().describe("The name a secret reference uses from now on."),
24
+ machine: z.string().describe("The computer whose keyring shares it."),
25
+ message: z.string(),
26
+ }),
27
+ z.object({ state: z.literal("pending"), id: z.string(), machine: z.string(), message: z.string().describe("Where the owner's answer is awaited.") }),
28
+ z.object({ state: z.literal("denied"), message: z.string() }),
29
+ z.object({ state: z.literal("unknown"), message: z.string().describe("No keyring had it and nobody typed it once, or none could be asked.") }),
30
+ ]);
31
+ export type SecretWantResult = z.infer<typeof SecretWantResultSchema>;
32
+
33
+ /** One need this sandbox raised, as its record and the hosted view's Requests keep it. */
34
+ export const SandboxNeedSchema = z.object({
35
+ id: z.string(),
36
+ origin: KeyringOriginSchema,
37
+ username: z.string().optional(),
38
+ detail: z.string(),
39
+ conversation: z.string().optional(),
40
+ machine: z.string().optional().describe("The computer it was answered on, or waits on."),
41
+ state: z.enum(["pending", "allowed", "denied", "unknown"]),
42
+ name: z.string().optional().describe("The entry it was answered with, once allowed."),
43
+ at: z.number().int(),
44
+ });
45
+ export type SandboxNeed = z.infer<typeof SandboxNeedSchema>;
46
+ export const SandboxNeedsSchema = z.object({ needs: z.array(SandboxNeedSchema) });
47
+
48
+ /** One of the owner's computers as the hosted Passwords view shows its keyring. */
49
+ export const SandboxPasswordsKeyringSchema = z.object({
50
+ machine: z.string(),
51
+ online: z.boolean(),
52
+ setUp: z.boolean().describe("Answering, set up, and trusted by this sandbox: it can be asked."),
53
+ locked: z.boolean().optional(),
54
+ remember: KeyringRememberSchema.optional(),
55
+ });
56
+ export type SandboxPasswordsKeyring = z.infer<typeof SandboxPasswordsKeyringSchema>;
57
+
58
+ /** One password this sandbox may use: a pointer one of the owner's keyrings shares here. Never a value. */
59
+ export const SandboxPasswordSchema = z.object({
60
+ name: z.string(),
61
+ title: z.string(),
62
+ kind: z.enum(["password", "text"]),
63
+ origins: z.array(KeyringOriginSchema).describe("Where it works, from the entry's rules."),
64
+ anyField: z.boolean(),
65
+ machine: z.string().describe("The computer whose keyring keeps it."),
66
+ mode: KeyringShareModeSchema.describe("How this sandbox may use it."),
67
+ online: z.boolean(),
68
+ updatedAt: z.number(),
69
+ lastUsedAt: z.number().optional().describe("This sandbox's last use of it, from its own use ledger."),
70
+ });
71
+ export type SandboxPassword = z.infer<typeof SandboxPasswordSchema>;
72
+
73
+ export const SandboxPasswordsSchema = z.object({
74
+ sandbox: z.string().describe("This sandbox's own address, as the keyrings name it."),
75
+ items: z.array(SandboxPasswordSchema),
76
+ keyrings: z.array(SandboxPasswordsKeyringSchema),
77
+ });
78
+ export type SandboxPasswords = z.infer<typeof SandboxPasswordsSchema>;
79
+
80
+ /** One use of a keyring-held password by this sandbox, from its use ledger. */
81
+ export const SandboxPasswordUseSchema = z.object({
82
+ at: z.number(),
83
+ name: z.string(),
84
+ lane: z.string(),
85
+ detail: z.string().optional(),
86
+ approvedBy: z.string().optional(),
87
+ });
88
+ export const SandboxPasswordsActivitySchema = z.object({ lines: z.array(SandboxPasswordUseSchema) });
@@ -257,6 +257,10 @@ export const SandboxKeyringSchema = z.object({
257
257
  machine: z.string().describe("The computer, by its device card."),
258
258
  online: z.boolean().describe("Whether it answers now."),
259
259
  locked: z.boolean().optional().describe("Whether its keyring is locked, as last heard. Absent while offline."),
260
+ setUp: z
261
+ .boolean()
262
+ .optional()
263
+ .describe("Whether its keyring answers with a vault this sandbox trusts, so a value can be kept there. Absent while offline, and from a daemon older than 2026-10-19."),
260
264
  version: z.string().optional().describe("The keyring's release, as last heard."),
261
265
  pendingInbox: z.number().int().nonnegative().optional().describe("Values sent to be kept there that wait for its next unlock."),
262
266
  shared: z.number().int().nonnegative().describe("How many of its entries are shared with this sandbox."),
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { MatchSnippetSchema } from "./agents.js";
2
+ import { MatchSnippetSchema } from "./agent-search.js";
3
3
  export const SessionIdParamSchema = z.object({ id: z.string().describe("Which past conversation.") });
4
4
  export const SessionSummarySchema = z.object({
5
5
  id: z.string().describe("Its id."),