@intentic/sandbox-contract 1.311.0 → 1.313.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 (444) hide show
  1. package/README.md +32 -4
  2. package/dist/chores/chores.js +6 -6
  3. package/dist/chores/chores.js.map +1 -1
  4. package/dist/chores/index.d.ts +0 -1
  5. package/dist/chores/index.d.ts.map +1 -1
  6. package/dist/chores/index.js +0 -1
  7. package/dist/chores/index.js.map +1 -1
  8. package/dist/chores/prompt.d.ts.map +1 -1
  9. package/dist/chores/prompt.js +3 -2
  10. package/dist/chores/prompt.js.map +1 -1
  11. package/dist/contracts/accounts.contract.d.ts +69 -0
  12. package/dist/contracts/accounts.contract.d.ts.map +1 -1
  13. package/dist/contracts/agent.contract.d.ts +436 -0
  14. package/dist/contracts/agent.contract.d.ts.map +1 -1
  15. package/dist/contracts/agent.contract.js +11 -1
  16. package/dist/contracts/agent.contract.js.map +1 -1
  17. package/dist/contracts/agents.contract.d.ts +718 -90
  18. package/dist/contracts/agents.contract.d.ts.map +1 -1
  19. package/dist/contracts/agents.contract.js +30 -2
  20. package/dist/contracts/agents.contract.js.map +1 -1
  21. package/dist/contracts/capabilities.contract.js +1 -1
  22. package/dist/contracts/capabilities.contract.js.map +1 -1
  23. package/dist/contracts/device.contract.d.ts +20 -4
  24. package/dist/contracts/device.contract.d.ts.map +1 -1
  25. package/dist/contracts/device.contract.js +1 -1
  26. package/dist/contracts/device.contract.js.map +1 -1
  27. package/dist/contracts/extensions.contract.d.ts +13 -0
  28. package/dist/contracts/extensions.contract.d.ts.map +1 -1
  29. package/dist/contracts/git.contract.d.ts +2 -0
  30. package/dist/contracts/git.contract.d.ts.map +1 -1
  31. package/dist/contracts/offload.contract.d.ts +107 -0
  32. package/dist/contracts/offload.contract.d.ts.map +1 -0
  33. package/dist/contracts/offload.contract.js +53 -0
  34. package/dist/contracts/offload.contract.js.map +1 -0
  35. package/dist/contracts/personas.contract.d.ts +2 -0
  36. package/dist/contracts/personas.contract.d.ts.map +1 -1
  37. package/dist/contracts/ports.contract.d.ts +5 -0
  38. package/dist/contracts/ports.contract.d.ts.map +1 -1
  39. package/dist/contracts/runner.contract.d.ts +204 -0
  40. package/dist/contracts/runner.contract.d.ts.map +1 -1
  41. package/dist/contracts/runner.contract.js +3 -1
  42. package/dist/contracts/runner.contract.js.map +1 -1
  43. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  44. package/dist/contracts/secrets.contract.js +1 -0
  45. package/dist/contracts/secrets.contract.js.map +1 -1
  46. package/dist/contracts/sessions.contract.d.ts +59 -0
  47. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  48. package/dist/contracts/settings.contract.d.ts +20 -8
  49. package/dist/contracts/settings.contract.d.ts.map +1 -1
  50. package/dist/contracts/settings.contract.js +2 -2
  51. package/dist/contracts/settings.contract.js.map +1 -1
  52. package/dist/contracts/system.contract.d.ts +230 -15
  53. package/dist/contracts/system.contract.d.ts.map +1 -1
  54. package/dist/contracts/translator.contract.d.ts +88 -0
  55. package/dist/contracts/translator.contract.d.ts.map +1 -1
  56. package/dist/contracts/workspace.contract.d.ts +217 -0
  57. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  58. package/dist/contracts/workspace.contract.js +40 -3
  59. package/dist/contracts/workspace.contract.js.map +1 -1
  60. package/dist/documents/conversions.d.ts +81 -0
  61. package/dist/documents/conversions.d.ts.map +1 -0
  62. package/dist/documents/conversions.js +213 -0
  63. package/dist/documents/conversions.js.map +1 -0
  64. package/dist/documents/index.d.ts +4 -0
  65. package/dist/documents/index.d.ts.map +1 -0
  66. package/dist/documents/index.js +4 -0
  67. package/dist/documents/index.js.map +1 -0
  68. package/dist/documents/passthrough.d.ts +13 -0
  69. package/dist/documents/passthrough.d.ts.map +1 -0
  70. package/dist/documents/passthrough.js +101 -0
  71. package/dist/documents/passthrough.js.map +1 -0
  72. package/dist/documents/read.d.ts +24 -0
  73. package/dist/documents/read.d.ts.map +1 -0
  74. package/dist/documents/read.js +81 -0
  75. package/dist/documents/read.js.map +1 -0
  76. package/dist/events/agent-events.d.ts +235 -0
  77. package/dist/events/agent-events.d.ts.map +1 -1
  78. package/dist/events/agent-events.js +3 -0
  79. package/dist/events/agent-events.js.map +1 -1
  80. package/dist/events/child-run.d.ts +9 -0
  81. package/dist/events/child-run.d.ts.map +1 -0
  82. package/dist/events/child-run.js +41 -0
  83. package/dist/events/child-run.js.map +1 -0
  84. package/dist/events/errands.d.ts +5 -0
  85. package/dist/events/errands.d.ts.map +1 -0
  86. package/dist/events/errands.js +19 -0
  87. package/dist/events/errands.js.map +1 -0
  88. package/dist/events/land-breakage.d.ts +3 -0
  89. package/dist/events/land-breakage.d.ts.map +1 -1
  90. package/dist/events/land-breakage.js +3 -0
  91. package/dist/events/land-breakage.js.map +1 -1
  92. package/dist/events/land-conflict.d.ts +3 -0
  93. package/dist/events/land-conflict.d.ts.map +1 -0
  94. package/dist/events/land-conflict.js +4 -0
  95. package/dist/events/land-conflict.js.map +1 -0
  96. package/dist/events/requests.d.ts +152 -0
  97. package/dist/events/requests.d.ts.map +1 -1
  98. package/dist/events/requests.js +26 -1
  99. package/dist/events/requests.js.map +1 -1
  100. package/dist/events/system-events.d.ts +74 -12
  101. package/dist/events/system-events.d.ts.map +1 -1
  102. package/dist/events/system-events.js +3 -1
  103. package/dist/events/system-events.js.map +1 -1
  104. package/dist/events/transcript.d.ts +387 -0
  105. package/dist/events/transcript.d.ts.map +1 -1
  106. package/dist/events/transcript.js +3 -0
  107. package/dist/events/transcript.js.map +1 -1
  108. package/dist/events/verify-nudge.d.ts.map +1 -1
  109. package/dist/events/verify-nudge.js.map +1 -1
  110. package/dist/front/browser-wire.d.ts +6 -0
  111. package/dist/front/browser-wire.d.ts.map +1 -0
  112. package/dist/front/browser-wire.js +4 -0
  113. package/dist/front/browser-wire.js.map +1 -0
  114. package/dist/front/front-wire.d.ts +6 -0
  115. package/dist/front/front-wire.d.ts.map +1 -0
  116. package/dist/front/front-wire.js +5 -0
  117. package/dist/front/front-wire.js.map +1 -0
  118. package/dist/front/generated/browser-wire.d.ts +19 -0
  119. package/dist/front/generated/browser-wire.d.ts.map +1 -0
  120. package/dist/front/generated/browser-wire.js +2 -0
  121. package/dist/front/generated/browser-wire.js.map +1 -0
  122. package/dist/front/generated/wire.d.ts +70 -1
  123. package/dist/front/generated/wire.d.ts.map +1 -1
  124. package/dist/ids/conversation-ids.d.ts +3 -0
  125. package/dist/ids/conversation-ids.d.ts.map +1 -1
  126. package/dist/ids/conversation-ids.js +4 -2
  127. package/dist/ids/conversation-ids.js.map +1 -1
  128. package/dist/ids/session-names.d.ts +3 -0
  129. package/dist/ids/session-names.d.ts.map +1 -1
  130. package/dist/ids/session-names.js +3 -0
  131. package/dist/ids/session-names.js.map +1 -1
  132. package/dist/index.d.ts +2052 -190
  133. package/dist/index.d.ts.map +1 -1
  134. package/dist/index.js +15 -1
  135. package/dist/index.js.map +1 -1
  136. package/dist/models/agent-catalog.d.ts.map +1 -1
  137. package/dist/models/agent-catalog.js +4 -6
  138. package/dist/models/agent-catalog.js.map +1 -1
  139. package/dist/models/agent-runtimes.d.ts +2 -1
  140. package/dist/models/agent-runtimes.d.ts.map +1 -1
  141. package/dist/models/agent-runtimes.js +7 -1
  142. package/dist/models/agent-runtimes.js.map +1 -1
  143. package/dist/models/plan-pools.d.ts +22 -1
  144. package/dist/models/plan-pools.d.ts.map +1 -1
  145. package/dist/models/plan-pools.js +86 -0
  146. package/dist/models/plan-pools.js.map +1 -1
  147. package/dist/policy/request-status.d.ts +1 -1
  148. package/dist/policy/request-status.d.ts.map +1 -1
  149. package/dist/policy/request-status.js +4 -11
  150. package/dist/policy/request-status.js.map +1 -1
  151. package/dist/policy/reserved-servers.d.ts.map +1 -1
  152. package/dist/policy/reserved-servers.js +2 -1
  153. package/dist/policy/reserved-servers.js.map +1 -1
  154. package/dist/policy/turned-away.d.ts.map +1 -1
  155. package/dist/policy/turned-away.js +1 -0
  156. package/dist/policy/turned-away.js.map +1 -1
  157. package/dist/protocol/container-requirements.d.ts +0 -1
  158. package/dist/protocol/container-requirements.d.ts.map +1 -1
  159. package/dist/protocol/container-requirements.js +1 -2
  160. package/dist/protocol/container-requirements.js.map +1 -1
  161. package/dist/protocol/edge-verdict.d.ts +2 -1
  162. package/dist/protocol/edge-verdict.d.ts.map +1 -1
  163. package/dist/protocol/edge-verdict.js +1 -1
  164. package/dist/protocol/edge-verdict.js.map +1 -1
  165. package/dist/protocol/ingress-contract.d.ts +1 -12
  166. package/dist/protocol/ingress-contract.d.ts.map +1 -1
  167. package/dist/protocol/ingress-contract.js +1 -1
  168. package/dist/protocol/ingress-contract.js.map +1 -1
  169. package/dist/protocol/raw-routes.d.ts +36 -26
  170. package/dist/protocol/raw-routes.d.ts.map +1 -1
  171. package/dist/protocol/raw-routes.js +17 -23
  172. package/dist/protocol/raw-routes.js.map +1 -1
  173. package/dist/protocol/route-meta.d.ts +22 -0
  174. package/dist/protocol/route-meta.d.ts.map +1 -1
  175. package/dist/protocol/route-meta.js +16 -0
  176. package/dist/protocol/route-meta.js.map +1 -1
  177. package/dist/protocol/runner-protocol.d.ts +34 -0
  178. package/dist/protocol/runner-protocol.d.ts.map +1 -1
  179. package/dist/protocol/runner-protocol.js +33 -0
  180. package/dist/protocol/runner-protocol.js.map +1 -1
  181. package/dist/protocol/tunnel-bulk.d.ts +2 -0
  182. package/dist/protocol/tunnel-bulk.d.ts.map +1 -0
  183. package/dist/protocol/tunnel-bulk.js +3 -0
  184. package/dist/protocol/tunnel-bulk.js.map +1 -0
  185. package/dist/protocol/x402.d.ts +17 -0
  186. package/dist/protocol/x402.d.ts.map +1 -0
  187. package/dist/protocol/x402.js +37 -0
  188. package/dist/protocol/x402.js.map +1 -0
  189. package/dist/schemas/activity.d.ts.map +1 -1
  190. package/dist/schemas/activity.js.map +1 -1
  191. package/dist/schemas/agent.d.ts +25 -0
  192. package/dist/schemas/agent.d.ts.map +1 -1
  193. package/dist/schemas/agent.js +14 -2
  194. package/dist/schemas/agent.js.map +1 -1
  195. package/dist/schemas/agents.d.ts +90 -18
  196. package/dist/schemas/agents.d.ts.map +1 -1
  197. package/dist/schemas/agents.js +49 -5
  198. package/dist/schemas/agents.js.map +1 -1
  199. package/dist/schemas/automations.d.ts +23 -6
  200. package/dist/schemas/automations.d.ts.map +1 -1
  201. package/dist/schemas/automations.js.map +1 -1
  202. package/dist/schemas/devices.d.ts +134 -7
  203. package/dist/schemas/devices.d.ts.map +1 -1
  204. package/dist/schemas/devices.js +43 -18
  205. package/dist/schemas/devices.js.map +1 -1
  206. package/dist/schemas/extension-updates.d.ts +26 -0
  207. package/dist/schemas/extension-updates.d.ts.map +1 -1
  208. package/dist/schemas/extension-updates.js +4 -0
  209. package/dist/schemas/extension-updates.js.map +1 -1
  210. package/dist/schemas/git/git.d.ts +19 -0
  211. package/dist/schemas/git/git.d.ts.map +1 -1
  212. package/dist/schemas/git/git.js +1 -0
  213. package/dist/schemas/git/git.js.map +1 -1
  214. package/dist/schemas/hosts.d.ts +35 -3
  215. package/dist/schemas/hosts.d.ts.map +1 -1
  216. package/dist/schemas/hosts.js +22 -6
  217. package/dist/schemas/hosts.js.map +1 -1
  218. package/dist/schemas/keep-warm.d.ts +2 -12
  219. package/dist/schemas/keep-warm.d.ts.map +1 -1
  220. package/dist/schemas/keep-warm.js +8 -10
  221. package/dist/schemas/keep-warm.js.map +1 -1
  222. package/dist/schemas/metrics.d.ts +29 -0
  223. package/dist/schemas/metrics.d.ts.map +1 -1
  224. package/dist/schemas/metrics.js +19 -3
  225. package/dist/schemas/metrics.js.map +1 -1
  226. package/dist/schemas/offload.d.ts +62 -0
  227. package/dist/schemas/offload.d.ts.map +1 -0
  228. package/dist/schemas/offload.js +23 -0
  229. package/dist/schemas/offload.js.map +1 -0
  230. package/dist/schemas/personas.d.ts +3 -0
  231. package/dist/schemas/personas.d.ts.map +1 -1
  232. package/dist/schemas/personas.js +12 -3
  233. package/dist/schemas/personas.js.map +1 -1
  234. package/dist/schemas/ports.d.ts +10 -0
  235. package/dist/schemas/ports.d.ts.map +1 -1
  236. package/dist/schemas/ports.js +8 -0
  237. package/dist/schemas/ports.js.map +1 -1
  238. package/dist/schemas/providers/plan-limits.d.ts +169 -0
  239. package/dist/schemas/providers/plan-limits.d.ts.map +1 -1
  240. package/dist/schemas/providers/plan-limits.js +54 -1
  241. package/dist/schemas/providers/plan-limits.js.map +1 -1
  242. package/dist/schemas/providers/provider-oauth.d.ts +69 -0
  243. package/dist/schemas/providers/provider-oauth.d.ts.map +1 -1
  244. package/dist/schemas/providers/provider-oauth.js +6 -1
  245. package/dist/schemas/providers/provider-oauth.js.map +1 -1
  246. package/dist/schemas/settings-history.d.ts +55 -0
  247. package/dist/schemas/settings-history.d.ts.map +1 -0
  248. package/dist/schemas/settings-history.js +73 -0
  249. package/dist/schemas/settings-history.js.map +1 -0
  250. package/dist/schemas/settings.d.ts +188 -4
  251. package/dist/schemas/settings.d.ts.map +1 -1
  252. package/dist/schemas/settings.js +41 -26
  253. package/dist/schemas/settings.js.map +1 -1
  254. package/dist/schemas/speaker.d.ts +36 -0
  255. package/dist/schemas/speaker.d.ts.map +1 -0
  256. package/dist/schemas/speaker.js +62 -0
  257. package/dist/schemas/speaker.js.map +1 -0
  258. package/dist/schemas/state-plan.d.ts +46 -0
  259. package/dist/schemas/state-plan.d.ts.map +1 -0
  260. package/dist/schemas/state-plan.js +31 -0
  261. package/dist/schemas/state-plan.js.map +1 -0
  262. package/dist/schemas/system.d.ts +64 -0
  263. package/dist/schemas/system.d.ts.map +1 -1
  264. package/dist/schemas/system.js +12 -1
  265. package/dist/schemas/system.js.map +1 -1
  266. package/dist/schemas/workspace/mainline.d.ts +513 -0
  267. package/dist/schemas/workspace/mainline.d.ts.map +1 -0
  268. package/dist/schemas/workspace/mainline.js +182 -0
  269. package/dist/schemas/workspace/mainline.js.map +1 -0
  270. package/dist/schemas/workspace/workspace-tree.d.ts +23 -0
  271. package/dist/schemas/workspace/workspace-tree.d.ts.map +1 -1
  272. package/dist/schemas/workspace/workspace-tree.js +34 -0
  273. package/dist/schemas/workspace/workspace-tree.js.map +1 -1
  274. package/dist/state/contract-lock.d.ts +1 -0
  275. package/dist/state/contract-lock.d.ts.map +1 -1
  276. package/dist/state/contract-lock.js +47 -1
  277. package/dist/state/contract-lock.js.map +1 -1
  278. package/dist/state/definition.d.ts +44 -20
  279. package/dist/state/definition.d.ts.map +1 -1
  280. package/dist/state/definition.js.map +1 -1
  281. package/dist/state/fix-stance.d.ts +1 -1
  282. package/dist/state/fix-stance.d.ts.map +1 -1
  283. package/dist/state/fix-stance.js +2 -1
  284. package/dist/state/fix-stance.js.map +1 -1
  285. package/dist/state/history-state.d.ts.map +1 -1
  286. package/dist/state/history-state.js +7 -0
  287. package/dist/state/history-state.js.map +1 -1
  288. package/dist/state/landed-commit.d.ts +1 -0
  289. package/dist/state/landed-commit.d.ts.map +1 -1
  290. package/dist/state/landed-commit.js +2 -0
  291. package/dist/state/landed-commit.js.map +1 -1
  292. package/dist/state/red-streak.d.ts +7 -0
  293. package/dist/state/red-streak.d.ts.map +1 -0
  294. package/dist/state/red-streak.js +11 -0
  295. package/dist/state/red-streak.js.map +1 -0
  296. package/dist/state/runtime-state.d.ts +3 -0
  297. package/dist/state/runtime-state.d.ts.map +1 -1
  298. package/dist/state/runtime-state.js +1 -0
  299. package/dist/state/runtime-state.js.map +1 -1
  300. package/dist/state/workspace-state.d.ts +23 -1
  301. package/dist/state/workspace-state.d.ts.map +1 -1
  302. package/dist/state/workspace-state.js +33 -3
  303. package/dist/state/workspace-state.js.map +1 -1
  304. package/dist/text/shell-regions.d.ts +1 -0
  305. package/dist/text/shell-regions.d.ts.map +1 -1
  306. package/dist/text/shell-regions.js +1 -1
  307. package/dist/text/shell-regions.js.map +1 -1
  308. package/dist/text/transcript-fold.d.ts +1 -0
  309. package/dist/text/transcript-fold.d.ts.map +1 -1
  310. package/dist/text/transcript-fold.js +24 -8
  311. package/dist/text/transcript-fold.js.map +1 -1
  312. package/package.json +42 -42
  313. package/src/chores/chores.ts +6 -6
  314. package/src/chores/index.ts +0 -1
  315. package/src/chores/prompt.ts +3 -2
  316. package/src/contracts/agent.contract.ts +14 -0
  317. package/src/contracts/agents.contract.ts +36 -1
  318. package/src/contracts/capabilities.contract.ts +2 -2
  319. package/src/contracts/device.contract.ts +5 -3
  320. package/src/contracts/offload.contract.ts +60 -0
  321. package/src/contracts/runner.contract.ts +7 -1
  322. package/src/contracts/secrets.contract.ts +2 -0
  323. package/src/contracts/settings.contract.ts +2 -1
  324. package/src/contracts/workspace.contract.ts +54 -2
  325. package/src/documents/conversions.ts +402 -0
  326. package/src/documents/index.ts +7 -0
  327. package/src/documents/passthrough.ts +139 -0
  328. package/src/documents/read.ts +114 -0
  329. package/src/events/agent-events.ts +5 -0
  330. package/src/events/child-run.test.ts +81 -0
  331. package/src/events/child-run.ts +73 -0
  332. package/src/events/errands.test.ts +22 -0
  333. package/src/events/errands.ts +27 -0
  334. package/src/events/land-breakage.ts +12 -0
  335. package/src/events/land-conflict.ts +12 -0
  336. package/src/events/requests.ts +40 -1
  337. package/src/events/system-events.ts +9 -3
  338. package/src/events/transcript.ts +8 -0
  339. package/src/events/verify-nudge.ts +4 -3
  340. package/src/front/browser-wire.ts +20 -0
  341. package/src/front/front-wire.ts +15 -0
  342. package/src/front/generated/browser-wire.json +138 -0
  343. package/src/front/generated/browser-wire.ts +16 -0
  344. package/src/front/generated/front-wire.json +793 -0
  345. package/src/front/generated/tunnel.json +38 -0
  346. package/src/front/generated/wire.ts +37 -9
  347. package/src/front/wire-manifests.test.ts +61 -0
  348. package/src/ids/conversation-ids.ts +13 -5
  349. package/src/ids/session-names.ts +7 -0
  350. package/src/index.ts +15 -2
  351. package/src/models/agent-catalog.test.ts +6 -4
  352. package/src/models/agent-catalog.ts +4 -6
  353. package/src/models/agent-runtimes.ts +22 -7
  354. package/src/models/capability-ledger.test.ts +2 -0
  355. package/src/models/plan-pools.test.ts +121 -2
  356. package/src/models/plan-pools.ts +152 -2
  357. package/src/policy/request-status.ts +4 -12
  358. package/src/policy/reserved-servers.test.ts +6 -0
  359. package/src/policy/reserved-servers.ts +13 -10
  360. package/src/policy/turned-away.ts +3 -0
  361. package/src/protocol/container-requirements.test.ts +2 -3
  362. package/src/protocol/container-requirements.ts +1 -7
  363. package/src/protocol/edge-verdict.ts +13 -11
  364. package/src/protocol/ingress-contract.fixture.json +90 -0
  365. package/src/protocol/ingress-contract.test.ts +18 -26
  366. package/src/protocol/ingress-contract.ts +10 -25
  367. package/src/protocol/raw-routes.ts +22 -26
  368. package/src/protocol/route-meta.ts +39 -0
  369. package/src/protocol/runner-protocol.ts +53 -0
  370. package/src/protocol/tunnel-bulk.test.ts +37 -0
  371. package/src/protocol/tunnel-bulk.ts +7 -0
  372. package/src/protocol/x402.test.ts +29 -0
  373. package/src/protocol/x402.ts +61 -0
  374. package/src/schemas/activity.ts +3 -1
  375. package/src/schemas/agent.ts +28 -3
  376. package/src/schemas/agents.ts +83 -8
  377. package/src/schemas/automations.ts +4 -2
  378. package/src/schemas/devices.ts +106 -39
  379. package/src/schemas/extension-updates.ts +6 -0
  380. package/src/schemas/git/git.ts +5 -0
  381. package/src/schemas/hosts.ts +64 -13
  382. package/src/schemas/ic-shape-args.test.ts +64 -0
  383. package/src/schemas/keep-warm.test.ts +6 -13
  384. package/src/schemas/keep-warm.ts +15 -20
  385. package/src/schemas/metrics.ts +28 -3
  386. package/src/schemas/offload.ts +44 -0
  387. package/src/schemas/personas.ts +18 -3
  388. package/src/schemas/ports.ts +10 -0
  389. package/src/schemas/providers/plan-limits.ts +84 -1
  390. package/src/schemas/providers/provider-oauth.ts +10 -1
  391. package/src/schemas/settings-history.ts +108 -0
  392. package/src/schemas/settings.test.ts +54 -1
  393. package/src/schemas/settings.ts +88 -49
  394. package/src/schemas/speaker.ts +89 -0
  395. package/src/schemas/state-plan.test.ts +69 -0
  396. package/src/schemas/state-plan.ts +47 -0
  397. package/src/schemas/system.ts +24 -3
  398. package/src/schemas/workspace/mainline.test.ts +28 -0
  399. package/src/schemas/workspace/mainline.ts +268 -0
  400. package/src/schemas/workspace/workspace-tree.ts +47 -0
  401. package/src/state/contract-lock.test.ts +65 -4
  402. package/src/state/contract-lock.ts +70 -2
  403. package/src/state/definition.ts +3 -2
  404. package/src/state/fix-stance.test.ts +8 -0
  405. package/src/state/fix-stance.ts +3 -3
  406. package/src/state/history-state.ts +19 -0
  407. package/src/state/landed-commit.test.ts +12 -1
  408. package/src/state/landed-commit.ts +5 -0
  409. package/src/state/red-streak.test.ts +28 -0
  410. package/src/state/red-streak.ts +28 -0
  411. package/src/state/runtime-state.ts +4 -0
  412. package/src/state/workspace-state.test.ts +7 -1
  413. package/src/state/workspace-state.ts +45 -3
  414. package/src/text/shell-regions.test.ts +38 -0
  415. package/src/text/shell-regions.ts +3 -3
  416. package/src/text/transcript-fold.test.ts +46 -0
  417. package/src/text/transcript-fold.ts +31 -9
  418. package/dist/chores/fix-deps.d.ts +0 -10
  419. package/dist/chores/fix-deps.d.ts.map +0 -1
  420. package/dist/chores/fix-deps.js +0 -18
  421. package/dist/chores/fix-deps.js.map +0 -1
  422. package/dist/protocol/ingress-protocol.d.ts +0 -30
  423. package/dist/protocol/ingress-protocol.d.ts.map +0 -1
  424. package/dist/protocol/ingress-protocol.js +0 -300
  425. package/dist/protocol/ingress-protocol.js.map +0 -1
  426. package/dist/protocol/terminal-protocol.d.ts +0 -18
  427. package/dist/protocol/terminal-protocol.d.ts.map +0 -1
  428. package/dist/protocol/terminal-protocol.js +0 -2
  429. package/dist/protocol/terminal-protocol.js.map +0 -1
  430. package/dist/protocol/tunnel-heartbeat.d.ts +0 -19
  431. package/dist/protocol/tunnel-heartbeat.d.ts.map +0 -1
  432. package/dist/protocol/tunnel-heartbeat.js +0 -41
  433. package/dist/protocol/tunnel-heartbeat.js.map +0 -1
  434. package/dist/protocol/upgrade-relay.d.ts +0 -4
  435. package/dist/protocol/upgrade-relay.d.ts.map +0 -1
  436. package/dist/protocol/upgrade-relay.js +0 -25
  437. package/dist/protocol/upgrade-relay.js.map +0 -1
  438. package/src/chores/fix-deps.ts +0 -22
  439. package/src/protocol/ingress-protocol.test.ts +0 -579
  440. package/src/protocol/ingress-protocol.ts +0 -469
  441. package/src/protocol/terminal-protocol.ts +0 -13
  442. package/src/protocol/tunnel-heartbeat.test.ts +0 -75
  443. package/src/protocol/tunnel-heartbeat.ts +0 -67
  444. package/src/protocol/upgrade-relay.ts +0 -28
@@ -0,0 +1,38 @@
1
+ {
2
+ "close": {
3
+ "away": 1001,
4
+ "displaced": 4001,
5
+ "refused": 4003
6
+ },
7
+ "headers": {
8
+ "bulk": "x-intentic-bulk",
9
+ "grant": "x-intentic-grant",
10
+ "lane": "x-intentic-lane",
11
+ "transports": "x-intentic-transports"
12
+ },
13
+ "lanes": [
14
+ "interactive",
15
+ "bulk"
16
+ ],
17
+ "liveness": {
18
+ "deadAfterMs": 45000,
19
+ "pingEveryMs": 15000
20
+ },
21
+ "mux": "yamux",
22
+ "path": "/tunnel/v2",
23
+ "quic": {
24
+ "alpn": "intentic-tunnel/1",
25
+ "hello": {
26
+ "gone": 2,
27
+ "held": 0,
28
+ "refused": 1
29
+ },
30
+ "yieldAfterBytes": 1048576
31
+ },
32
+ "transports": [
33
+ "quic",
34
+ "h3",
35
+ "webtransport"
36
+ ],
37
+ "upgrade": "websocket"
38
+ }
@@ -1,6 +1,10 @@
1
1
  // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2
2
 
3
- export type Answer = { "answer": "preview", route: PreviewRoute, };
3
+ export type Answer = { "answer": "preview", route: PreviewRoute, } | { "answer": "terminal", plan: TerminalPlan,
4
+ /**
5
+ * The member whose ticket opened it, lowercased; absent when the daemon runs without auth.
6
+ */
7
+ member?: string, };
4
8
 
5
9
  /**
6
10
  * A PEM certificate chain and its PEM private key.
@@ -12,7 +16,9 @@ export type Endpoint = { host: string, port: number, };
12
16
  /**
13
17
  * Everything Node sends the front.
14
18
  */
15
- export type FromNode = { "kind": "hello", build: string, pid: number, } | { "kind": "listen", config: ListenConfig, } | { "kind": "certificate", certificate?: Certificate, } | { "kind": "tunnel", tunnel?: TunnelConfig, } | { "kind": "answer", id: number, answer: Answer, } | { "kind": "refused", id: number, message: string, };
19
+ export type FromNode = { "kind": "hello", build: string, pid: number, } | { "kind": "listen", config: ListenConfig, } | { "kind": "certificate", certificate?: Certificate, } | { "kind": "tunnel", tunnel?: TunnelConfig, } | { "kind": "ask", id: number, question: FrontQuestion, } | { "kind": "answer", id: number, answer: Answer, } | { "kind": "refused", id: number, message: string, } | { "kind": "revoke", member?: string, } | { "kind": "watch", checkout: WatchedCheckout, } | { "kind": "unwatch", dir: string, };
20
+
21
+ export type FrontAnswer = { "answer": "sync", generations: Array<number | null>, };
16
22
 
17
23
  /**
18
24
  * Request headers only the front sets on what it forwards to Node; it strips them from everything arriving outside.
@@ -20,6 +26,11 @@ export type FromNode = { "kind": "hello", build: string, pid: number, } | { "kin
20
26
  */
21
27
  export type FrontHeader = "x-intentic-preview" | "x-intentic-preview-unreachable";
22
28
 
29
+ /**
30
+ * A question Node asks the front.
31
+ */
32
+ export type FrontQuestion = { "question": "sync", dirs: Array<string>, };
33
+
23
34
  /**
24
35
  * Every port the front binds, as Node's config names them; an absent one is not bound.
25
36
  */
@@ -38,26 +49,37 @@ frameAncestors: Array<string>,
38
49
  previewProbePath: string, };
39
50
 
40
51
  /**
41
- * Where a preview host's requests go, as Node resolved it.
52
+ * An answer Node renders whole when asked, for the front to write as it stands: a refusal page, or the probe's report.
42
53
  */
43
- export type PreviewRoute = { "to": "upstream", upstream: Upstream, } | { "to": "node" };
54
+ export type Page = { status: number, headers: { [key in string]: string }, body: string, };
44
55
 
45
56
  /**
46
- * A question the front asks Node; the answer carries the same id.
57
+ * What becomes of a preview host's request, decided by Node once, when asked.
47
58
  */
48
- export type Question = { "question": "preview", host: string, };
59
+ export type PreviewRoute = { "to": "upstream", upstream: Upstream, } | { "to": "page", page: Page, } | { "to": "outbox" };
60
+
61
+ /**
62
+ * A question the front asks Node.
63
+ */
64
+ export type Question = { "question": "preview", host: string, probe: boolean, } | { "question": "terminal", query: string, };
49
65
 
50
66
  export type Scheme = "http" | "https";
51
67
 
68
+ /**
69
+ * What a terminal socket opens onto, as Node decided from its ticket, session name and working directory.
70
+ */
71
+ export type TerminalPlan = { "plan": "session", name: string, createIn?: string, } | { "plan": "tail", path: string, } | { "plan": "exit", code: number, reason: string, } | { "plan": "refused", code: number, reason: string, };
72
+
52
73
  /**
53
74
  * Everything the front sends Node.
54
75
  */
55
- export type ToNode = { "kind": "ask", id: number, question: Question, } | { "kind": "tunnel", connected: boolean, };
76
+ export type ToNode = { "kind": "ask", id: number, question: Question, } | { "kind": "answer", id: number, answer: FrontAnswer, } | { "kind": "refused", id: number, message: string, } | { "kind": "tunnel", connected: boolean, };
56
77
 
57
78
  /**
58
- * The ingress tunnel's door and the reachability grant it presents there.
79
+ * The ingress tunnel's door, the reachability grant it presents there, and the daemon's transfer routes it announces
80
+ * (`METHOD /path` each, as the daemon names them), which the edge sends down the bulk socket.
59
81
  */
60
- export type TunnelConfig = { url: string, grant: string, };
82
+ export type TunnelConfig = { url: string, grant: string, bulk: Array<string>, };
61
83
 
62
84
  /**
63
85
  * A local upstream a preview host relays to.
@@ -71,3 +93,9 @@ localhost: boolean,
71
93
  * Framed by the editor: `frame-ancestors` is set and `x-frame-options` dropped.
72
94
  */
73
95
  frameable: boolean, };
96
+
97
+ /**
98
+ * A checkout whose changes the front counts: its working tree, the git dir holding its index and HEAD, and the common
99
+ * dir holding refs and excludes (the git dir itself for a repository's main checkout).
100
+ */
101
+ export type WatchedCheckout = { dir: string, gitDir: string, commonDir: string, };
@@ -0,0 +1,61 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { EDGE_VERDICT_HEADER, edgeVerdictOf } from "../protocol/edge-verdict.js";
3
+ import { INGRESS_GRANT_HEADER, INGRESS_TUNNEL_PATH } from "../protocol/ingress-contract.js";
4
+ import { EDGE_TRANSPORTS, TERMINAL_PATH, WEBTRANSPORT_PATH } from "./browser-wire.js";
5
+ import { ASK_PATIENCE_MS, FRAME_LENGTH_BYTES, FRONT_SOCKET_ENV, NODE_SOCKET_ENV } from "./front-wire.js";
6
+
7
+ // The manifests `cargo test` writes from the Rust crates that define this wire: every value TypeScript restates is read
8
+ // back against them, so the two languages cannot drift and contract.lock.json pins what both agree on.
9
+ const manifest = (name: string): Record<string, unknown> =>
10
+ JSON.parse(readFileSync(new URL(`./generated/${name}.json`, import.meta.url), "utf8")) as Record<string, unknown>;
11
+
12
+ const tunnel = manifest("tunnel") as {
13
+ path: string;
14
+ headers: { grant: string; transports: string };
15
+ transports: string[];
16
+ };
17
+ // SAFETY: front-wire's own test writes this manifest with exactly these keys, and the lock pins them.
18
+ const socket = manifest("front-wire") as {
19
+ env: { frontSocket: string; nodeSocket: string };
20
+ askPatienceMs: number;
21
+ frame: { lengthBytes: number };
22
+ };
23
+ const browser = manifest("browser-wire") as {
24
+ edge: { verdictHeader: string; verdicts: { oneOf: { const: string }[] } };
25
+ terminal: { path: string; upgrade: string };
26
+ webTransport: { path: string };
27
+ };
28
+
29
+ describe("the wire outside oRPC, as the Rust crates define it", () => {
30
+ it("names the tunnel door and its headers as the tunnel crate does", () => {
31
+ expect({ path: INGRESS_TUNNEL_PATH, grant: INGRESS_GRANT_HEADER }).toEqual({
32
+ path: tunnel.path,
33
+ grant: tunnel.headers.grant,
34
+ });
35
+ });
36
+
37
+ it("names the control socket's env vars, its patience and its framing as front-wire does", () => {
38
+ expect({ front: FRONT_SOCKET_ENV, node: NODE_SOCKET_ENV, patience: ASK_PATIENCE_MS, length: FRAME_LENGTH_BYTES }).toEqual({
39
+ front: socket.env.frontSocket,
40
+ node: socket.env.nodeSocket,
41
+ patience: socket.askPatienceMs,
42
+ length: socket.frame.lengthBytes,
43
+ });
44
+ });
45
+
46
+ it("declares exactly the transports an edge may", () => {
47
+ expect<readonly string[]>(EDGE_TRANSPORTS).toEqual(tunnel.transports);
48
+ });
49
+
50
+ it("reads the edge's verdicts and the browser's paths as browser-wire writes them", () => {
51
+ const verdicts = browser.edge.verdicts.oneOf.map((verdict) => verdict.const);
52
+ expect(verdicts).toEqual(["no-tunnel", "unknown-sandbox", "dropped"]);
53
+ expect<readonly (string | undefined)[]>(verdicts.map((verdict) => edgeVerdictOf(verdict))).toEqual(verdicts);
54
+ expect({ header: EDGE_VERDICT_HEADER, terminal: TERMINAL_PATH, session: WEBTRANSPORT_PATH, upgrade: "websocket" }).toEqual({
55
+ header: browser.edge.verdictHeader,
56
+ terminal: browser.terminal.path,
57
+ session: browser.webTransport.path,
58
+ upgrade: browser.terminal.upgrade,
59
+ });
60
+ });
61
+ });
@@ -160,15 +160,16 @@ const repoSlug = (repo: string): string =>
160
160
  .replace(/^-+|-+$/g, "") || "repo";
161
161
  export const ciFixConversationId = (repo: string, runId: number): string => `${CI_FIX_PREFIX}${repoSlug(repo)}-${runId}`;
162
162
 
163
- // Keyed by which gates failed (fixSignature), not a run id (a push has none); the same gates red again is the same
164
- // failure. Hashed rather than spelled into the branch name; the fix agent's first message names the gates.
163
+ // Keyed by when the project's push red began (pushFixBase, `red:<since>`), not a run id (a push has none): a refused push
164
+ // is owed by that red too (push-checks-store.ts). Hashed rather than spelled into the branch name; the fix agent's first
165
+ // message names what it is for.
165
166
  export const PUSH_FIX_PREFIX = "push-fix-";
166
167
 
167
168
  // FNV-1a, not a cryptographic hash: nothing here is secret, the only requirement is the same failure yields the same
168
- // seven characters in every browser and in node.
169
+ // seven characters in every browser and in node. The one spelling: a push finding's id (push-checks-store.ts) is this too.
169
170
  const FNV_OFFSET = 0x811c_9dc5;
170
171
  const FNV_PRIME = 0x0100_0193;
171
- const digest = (text: string): string => {
172
+ export const fnvDigest = (text: string): string => {
172
173
  let hash = FNV_OFFSET;
173
174
  for (let index = 0; index < text.length; index += 1) {
174
175
  hash = Math.imul(hash ^ text.charCodeAt(index), FNV_PRIME);
@@ -176,7 +177,14 @@ const digest = (text: string): string => {
176
177
  return (hash >>> 0).toString(36).padStart(7, "0");
177
178
  };
178
179
 
179
- export const pushFixConversationId = (scope: string, signature: string): string => `${PUSH_FIX_PREFIX}${repoSlug(scope)}-${digest(signature)}`;
180
+ export const pushFixConversationId = (scope: string, signature: string): string => `${PUSH_FIX_PREFIX}${repoSlug(scope)}-${fnvDigest(signature)}`;
181
+
182
+ // A red main-line check that no conversation still holding the work could take: keyed by the project and the moment its
183
+ // red streak began, so every attempt at one streak shares a base and a later streak in the same project starts over.
184
+ // Seconds in base36 keep it short; the workspace root is spelled `workspace`, since its project folder is empty.
185
+ export const LAND_FIX_PREFIX = "land-fix-";
186
+ export const landFixConversationId = (project: string, redSince: number): string =>
187
+ `${LAND_FIX_PREFIX}${repoSlug(project === "" ? "workspace" : project)}-${Math.floor(redSince / 1000).toString(36)}`;
180
188
 
181
189
  // ONE FAILURE, MANY ATTEMPTS, ONE LIVE ANSWER. The derived id above names the FAILURE; an attempt at it is a
182
190
  // conversation of its own, so starting over (another model, a clean worktree) never rewrites a record some other window
@@ -6,6 +6,8 @@ export const WEB_SESSION_PREFIX = "web-";
6
6
  export const AGENT_SESSION_PREFIX = "agent-";
7
7
  export const JOB_SESSION_PREFIX = "job-";
8
8
  export const BROWSER_SESSION_PREFIX = "browser-";
9
+ // A panel's session, one per managed process; the browser string-builds these names too, so never rename it.
10
+ export const PANEL_SESSION_PREFIX = "panel-";
9
11
 
10
12
  // Eight characters of the SDK session UUID, sanitized to the name-guard charset; groups a turn's work, including its
11
13
  // subagents', under one name. Undefined when it sanitizes to empty.
@@ -21,6 +23,11 @@ export const agentSessionName = (sessionId: string): string | undefined => {
21
23
  return suffix === undefined ? undefined : `${AGENT_SESSION_PREFIX}${suffix}`;
22
24
  };
23
25
 
26
+ // The session a panel keyed `key` runs in, and back; undefined for a name that isn't a panel session at all.
27
+ export const panelSession = (key: string): string => `${PANEL_SESSION_PREFIX}${key}`;
28
+ export const panelKeyOf = (session: string | undefined): string | undefined =>
29
+ session?.startsWith(PANEL_SESSION_PREFIX) === true ? session.slice(PANEL_SESSION_PREFIX.length) : undefined;
30
+
24
31
  // The browser session one SDK session drives. Shares the suffix with agentSessionName on purpose: a conversation's
25
32
  // shell and its browser read as the pair they are.
26
33
  export const browserSessionName = (sessionId: string): string | undefined => {
package/src/index.ts CHANGED
@@ -40,6 +40,7 @@ import { skillsContract } from "./contracts/skills.contract.js";
40
40
  import { systemContract } from "./contracts/system.contract.js";
41
41
  import { translatorContract } from "./contracts/translator.contract.js";
42
42
  import { usageContract } from "./contracts/usage.contract.js";
43
+ import { offloadContract } from "./contracts/offload.contract.js";
43
44
  import { vpnContract } from "./contracts/vpn.contract.js";
44
45
  import { workflowsContract } from "./contracts/workflows.contract.js";
45
46
  import { workspaceContract } from "./contracts/workspace.contract.js";
@@ -100,6 +101,7 @@ export { systemContract } from "./contracts/system.contract.js";
100
101
  export { translatorContract } from "./contracts/translator.contract.js";
101
102
  export { type PlanLimitsHeld, type PlanLimitsRefreshed, PlanLimitsRefreshedSchema, usageContract } from "./contracts/usage.contract.js";
102
103
  export { netdiskContract } from "./contracts/netdisk.contract.js";
104
+ export { offloadContract } from "./contracts/offload.contract.js";
103
105
  export { vpnContract } from "./contracts/vpn.contract.js";
104
106
  export { workflowsContract } from "./contracts/workflows.contract.js";
105
107
  export { workspaceContract } from "./contracts/workspace.contract.js";
@@ -110,15 +112,19 @@ export * from "./events/resume.js";
110
112
  export * from "./events/system-events.js";
111
113
  export * from "./events/transcript.js";
112
114
  export * from "./events/land-breakage.js";
115
+ export * from "./events/land-conflict.js";
113
116
  export * from "./events/verify-nudge.js";
117
+ export * from "./events/errands.js";
114
118
  export * from "./events/watch-wake.js";
115
119
  export * from "./policy/request-status.js";
120
+ export * from "./events/child-run.js";
116
121
  export * from "./policy/turned-away.js";
117
122
  export * from "./text/mentions.js";
118
123
  export * from "./protocol/sse.js";
119
124
  export * from "./protocol/routes.js";
120
- export type { ControlReach, RouteMeta } from "./protocol/route-meta.js";
125
+ export { type ControlReach, defaultFloor, type RouteAccess, type RouteMeta, routeAccess } from "./protocol/route-meta.js";
121
126
  export { RAW_ROUTE_LIST, RAW_ROUTES, type RawRouteKey, rawRoutePath } from "./protocol/raw-routes.js";
127
+ export { tunnelBulkRoutes } from "./protocol/tunnel-bulk.js";
122
128
  export type { SandboxCallInput, SandboxGroup, SandboxHandlerInput, SandboxHandlerOutput, SandboxProcedure } from "./protocol/procedure-types.js";
123
129
  export * from "./policy/control-scopes.js";
124
130
  // The container's directory layout, re-exported since extensions can't import @intentic/constants directly.
@@ -130,6 +136,7 @@ export * from "./state/history-state.js";
130
136
  export * from "./state/fix-stance.js";
131
137
  export * from "./state/landed-commit.js";
132
138
  export * from "./state/fix-attempt-plan.js";
139
+ export * from "./state/red-streak.js";
133
140
  // Provider vocabulary bottom-up: agent-runtimes, provider-specs, agent-catalog; three modules since the dependency
134
141
  // points one way.
135
142
  export * from "./models/agent-runtimes.js";
@@ -170,6 +177,7 @@ export * from "./schemas/areas.js";
170
177
  export * from "./policy/fence-paths.js";
171
178
  export * from "./policy/persona-home.js";
172
179
  export * from "./schemas/agents.js";
180
+ export * from "./schemas/speaker.js";
173
181
  export * from "./schemas/approvals.js";
174
182
  export * from "./schemas/automations.js";
175
183
  export * from "./schemas/capabilities.js";
@@ -210,29 +218,33 @@ export * from "./schemas/secrets.js";
210
218
  export * from "./schemas/netdisk.js";
211
219
  export * from "./schemas/sessions.js";
212
220
  export * from "./schemas/settings.js";
221
+ export * from "./schemas/settings-history.js";
213
222
  export * from "./schemas/share.js";
214
223
  export * from "./schemas/shared.js";
215
224
  export * from "./schemas/system-prompt.js";
216
225
  export * from "./schemas/system.js";
226
+ export * from "./schemas/state-plan.js";
217
227
  export * from "./schemas/terminal.js";
218
228
  export * from "./schemas/turn-break.js";
219
229
  export * from "./schemas/keep-warm.js";
220
230
  export * from "./schemas/providers/usage.js";
221
231
  export * from "./schemas/vpn.js";
232
+ export * from "./schemas/offload.js";
222
233
  export * from "./schemas/webext.js";
223
234
  export * from "./schemas/workflows.js";
224
235
  export * from "./schemas/workspace/workspace-repos.js";
225
236
  export * from "./schemas/workspace/workspace-search.js";
237
+ export * from "./schemas/workspace/mainline.js";
226
238
  export * from "./schemas/workspace/workspace-setup.js";
227
239
  export * from "./schemas/workspace/workspace-tree.js";
228
240
  export * from "./state/arrival.js";
229
241
  export * from "./state/definition.js";
230
242
  export * from "./policy/search-globs.js";
231
243
  export * from "./state/starter.js";
232
- export * from "./protocol/terminal-protocol.js";
233
244
  export * from "./text/title.js";
234
245
  export * from "./state/versions.js";
235
246
  export * from "./text/model-answer.js";
247
+ export * from "./text/shell-regions.js";
236
248
  export * from "./text/whisper.js";
237
249
  export * from "./text/workflow-faults.js";
238
250
  export * from "./text/emoji.js";
@@ -278,6 +290,7 @@ export const sandboxContract = {
278
290
  translator: translatorContract,
279
291
  usage: usageContract,
280
292
  vpn: vpnContract,
293
+ offload: offloadContract,
281
294
  exit: exitContract,
282
295
  netdisk: netdiskContract,
283
296
  workflows: workflowsContract,
@@ -31,7 +31,7 @@ describe("every provider/harness pair declares what it can do", () => {
31
31
 
32
32
  expect(["claude-code", "codex", "cursor", "opencode", "opencode-gemini", "acp", "pi"]).toContain(capabilities.runtime);
33
33
  expect(["modes", "plan"]).toContain(capabilities.permissions);
34
- expect(["full", "tools", "browser", "http", "none"]).toContain(capabilities.mcp);
34
+ expect(["full", "tools", "http", "none"]).toContain(capabilities.mcp);
35
35
  expect(capabilities.execution).toContain("shell");
36
36
  for (const backend of capabilities.execution) {
37
37
  expect(["shell", "js"]).toContain(backend);
@@ -135,8 +135,8 @@ test("the ceiling has nothing to disclose; a floor names what it lacks", () => {
135
135
  expect(acpCaps.terminals).toBe(true);
136
136
 
137
137
  const codexCaps = capabilitiesOf("codex", "native");
138
- expect(codexCaps.mcp).toBe("browser");
139
- expect(limitationsOf(codexCaps).some((line) => line.includes("browser"))).toBe(true);
138
+ expect(codexCaps.mcp).toBe("http");
139
+ expect(limitationsOf(codexCaps)).toContain("MCP servers only, none of the daemon's own tools, no plugins");
140
140
  expect(limitationsOf(codexCaps).length).toBeLessThan(limitationsOf({ ...grokCaps, mcp: "none" }).length + 5);
141
141
  });
142
142
 
@@ -154,13 +154,15 @@ test("every axis a record can lack has words for it", () => {
154
154
  commands: false,
155
155
  terminals: false,
156
156
  recovery: false,
157
+ warm: false,
157
158
  instructions: "none",
158
159
  skillDiscovery: "prompt",
159
160
  rulebook: "none",
160
161
  secrets: "none",
161
162
  };
162
163
 
163
- // Thirteen disclosable axes, thirteen sentences; `fastMode` is the exception, disclosed via fastAllowed.
164
+ // Thirteen disclosable axes, thirteen sentences; `fastMode` is disclosed via fastAllowed, and `warm` (keep-warm, off by
165
+ // default) is no limit on the turn itself.
164
166
  expect(limitationsOf(nothing)).toHaveLength(13);
165
167
  expect(limitationsOf(nothing).join(" ")).not.toContain("fast");
166
168
  });
@@ -116,12 +116,10 @@ export const limitationsOf = (capabilities: AgentCapabilities): string[] => [
116
116
  ...(capabilities.mcp === "none"
117
117
  ? ["no MCP tools or plugins"]
118
118
  : capabilities.mcp === "http"
119
- ? ["MCP tools only, no plugins or browser"]
120
- : capabilities.mcp === "browser"
121
- ? ["browser tools only, no other MCP"]
122
- : capabilities.mcp === "tools"
123
- ? ["no plugins"]
124
- : []),
119
+ ? ["MCP servers only, none of the daemon's own tools, no plugins"]
120
+ : capabilities.mcp === "tools"
121
+ ? ["no plugins"]
122
+ : []),
125
123
  ...(capabilities.execution.includes("js") ? [] : ["no code runs, shell only"]),
126
124
  ...(capabilities.effort ? [] : ["no effort control"]),
127
125
  ...(capabilities.commands ? [] : ["no slash commands"]),
@@ -15,8 +15,13 @@ export interface AgentCapabilities {
15
15
  readonly permissions: "modes" | "plan";
16
16
  // Can stop mid-turn and ask the user a multiple-choice question (`question` frames).
17
17
  readonly questions: boolean;
18
- // Which tools reach the agent, full down to none; never rounded up or down from what a runtime has.
19
- readonly mcp: "full" | "tools" | "browser" | "http" | "none";
18
+ // Which tools reach the agent, full down to none; never rounded up or down from what a runtime has. Every runtime
19
+ // but `none` takes the turn's whole remote list (TurnTools.remote: the daemon's MCP door's mounts, browsers
20
+ // included, and the mcp-kind cards), so no granted server reaches one runtime and misses another:
21
+ // full - that list, the daemon's own in-process servers (ui, secrets, watch, …), and plugin checkouts.
22
+ // tools - that list, and the daemon's own tools through the runtime's host callbacks; no plugins.
23
+ // http - that list alone, as http MCP servers.
24
+ readonly mcp: "full" | "tools" | "http" | "none";
20
25
  // Which ways of executing the daemon stands behind here; distinct from `mcp`, which names tools, not execution.
21
26
  readonly execution: readonly ExecutionBackend[];
22
27
  // Reasoning-effort selection is forwarded to the model.
@@ -31,6 +36,9 @@ export interface AgentCapabilities {
31
36
  readonly terminals: boolean;
32
37
  // Fails with the coded frames auto-resume keys off, so a turn the provider killed is re-run once it's back.
33
38
  readonly recovery: boolean;
39
+ // Can hold an idle conversation's prompt cache warm: its provider replays the last turn's prefix as one forked,
40
+ // unsaved request with every tool refused (keep-warm). Only where the provider module also implements `warm`.
41
+ readonly warm: boolean;
34
42
  // How much of the owner's instructions this runtime takes: replace the base, append to it, or no seam at all.
35
43
  readonly instructions: "replace" | "append" | "none";
36
44
  // How the runtime discovers loaded skills: scans its own filesystem, or the daemon names them in the opener.
@@ -61,6 +69,7 @@ export const CLAUDE_CODE: AgentCapabilities = {
61
69
  commands: true,
62
70
  terminals: true,
63
71
  recovery: true,
72
+ warm: true,
64
73
  instructions: "replace",
65
74
  skillDiscovery: "native",
66
75
  // The only runtime with its own pre-execution hook, so the only one where a hold can park instead of refusing.
@@ -68,14 +77,15 @@ export const CLAUDE_CODE: AgentCapabilities = {
68
77
  secrets: "masked",
69
78
  };
70
79
 
71
- // Codex app-server: item-level events, process-backed MCP, and four seams (steer, a question request, the skills list,
72
- // the shared mount namespace). Daemon-side servers, plugins, server approvals stay unwired.
80
+ // Codex app-server: item-level events, the turn's remote MCP servers over http, and four seams (steer, a question
81
+ // request, the skills list, the shared mount namespace). The daemon's in-process servers, plugins and server approvals
82
+ // stay unwired.
73
83
  export const CODEX: AgentCapabilities = {
74
84
  runtime: "codex",
75
85
  steering: true,
76
86
  permissions: "plan",
77
87
  questions: true,
78
- mcp: "browser",
88
+ mcp: "http",
79
89
  execution: ["shell"],
80
90
  effort: true,
81
91
  fastMode: false,
@@ -83,6 +93,7 @@ export const CODEX: AgentCapabilities = {
83
93
  commands: true,
84
94
  terminals: false,
85
95
  recovery: false,
96
+ warm: false,
86
97
  // Both ride the per-thread config: one replaces Codex's base prompt, the other adds a developer message.
87
98
  instructions: "replace",
88
99
  skillDiscovery: "native",
@@ -106,6 +117,7 @@ export const OPENCODE: AgentCapabilities = {
106
117
  commands: false,
107
118
  terminals: false,
108
119
  recovery: false,
120
+ warm: false,
109
121
  // `system` on the prompt body, per message; adds to OpenCode's own prompt, with no seam to replace it.
110
122
  instructions: "append",
111
123
  skillDiscovery: "prompt",
@@ -122,7 +134,7 @@ export const OPENCODE_GEMINI: AgentCapabilities = {
122
134
  };
123
135
 
124
136
  // Any agent speaking the Agent Client Protocol: a documented floor, not the native ceiling. Publishes commands and
125
- // terminals, takes http MCP tools when offered, but owns its own model, effort and permission posture.
137
+ // terminals, takes the turn's remote MCP servers when it advertises http MCP, but owns its own model, effort and permission posture.
126
138
  export const ACP: AgentCapabilities = {
127
139
  runtime: "acp",
128
140
  steering: false,
@@ -136,6 +148,7 @@ export const ACP: AgentCapabilities = {
136
148
  commands: true,
137
149
  terminals: true,
138
150
  recovery: false,
151
+ warm: false,
139
152
  // ACP's calls carry no system field: the agent owns its instructions, the persona note rides the message.
140
153
  instructions: "none",
141
154
  skillDiscovery: "prompt",
@@ -159,6 +172,7 @@ export const PI: AgentCapabilities = {
159
172
  commands: true,
160
173
  terminals: false,
161
174
  recovery: false,
175
+ warm: false,
162
176
  // Pi's RPC sets no standing instructions; like ACP, it hears the persona note through the user message.
163
177
  instructions: "none",
164
178
  skillDiscovery: "prompt",
@@ -177,7 +191,7 @@ export const CURSOR: AgentCapabilities = {
177
191
  permissions: "plan",
178
192
  // True since the daemon supplies its own ask tool; Cursor's own can fabricate an answer, so it's disallowed.
179
193
  questions: true,
180
- // stdio + http/sse MCP servers plus host callbacks; everything but a Claude Code plugin checkout.
194
+ // The turn's remote MCP servers plus host callbacks; everything but a Claude Code plugin checkout.
181
195
  mcp: "tools",
182
196
  // The JS backend rides Cursor's custom-tool seam rather than an MCP server, and consults the rulebook in its
183
197
  // handler, since the hook file only covers the shell.
@@ -193,6 +207,7 @@ export const CURSOR: AgentCapabilities = {
193
207
  terminals: false,
194
208
  // The SDK throws typed errors instead of dissolving a refusal into prose, so the adapter files coded frames.
195
209
  recovery: true,
210
+ warm: false,
196
211
  // append, reached differently: `beforeSubmitPrompt`'s reply folds the daemon's text onto Cursor's base. The SDK can
197
212
  // replace that base outright, but only for an entitled account, so the seam every turn can reach is this one.
198
213
  instructions: "append",
@@ -32,6 +32,8 @@ const LEDGER: Record<keyof AgentCapabilities, Backing> = {
32
32
  // - refuse-only: a hold refuses instead of parking
33
33
  // - other values: park on a card
34
34
  rulebook: "enforced",
35
+ // agent/run/turn/cache-keepwarm.ts files nothing to keep warm for a turn whose runtime lacks it.
36
+ warm: "enforced",
35
37
 
36
38
  // Descriptive: true of the runtime but nothing consults these; wiring one up moves it to enforced.
37
39
  questions: "descriptive",