@intentic/sandbox-contract 1.247.0 → 1.249.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 (883) hide show
  1. package/README.md +18 -15
  2. package/dist/chores/chores.d.ts.map +1 -1
  3. package/dist/chores/chores.js.map +1 -1
  4. package/dist/chores/digest.d.ts.map +1 -1
  5. package/dist/chores/digest.js.map +1 -1
  6. package/dist/chores/extension-update.d.ts.map +1 -1
  7. package/dist/chores/extension-update.js.map +1 -1
  8. package/dist/chores/fix-deps.d.ts.map +1 -1
  9. package/dist/chores/fix-deps.js.map +1 -1
  10. package/dist/chores/index.d.ts +2 -2
  11. package/dist/chores/index.d.ts.map +1 -1
  12. package/dist/chores/index.js +1 -1
  13. package/dist/chores/index.js.map +1 -1
  14. package/dist/chores/probes.d.ts.map +1 -1
  15. package/dist/chores/probes.js.map +1 -1
  16. package/dist/chores/prompt.d.ts.map +1 -1
  17. package/dist/chores/prompt.js.map +1 -1
  18. package/dist/chores/stack.d.ts.map +1 -1
  19. package/dist/chores/stack.js.map +1 -1
  20. package/dist/chores/verdict.d.ts +7 -1
  21. package/dist/chores/verdict.d.ts.map +1 -1
  22. package/dist/chores/verdict.js +8 -0
  23. package/dist/chores/verdict.js.map +1 -1
  24. package/dist/contracts/accounts.contract.d.ts.map +1 -1
  25. package/dist/contracts/accounts.contract.js.map +1 -1
  26. package/dist/contracts/activity.contract.d.ts +1 -0
  27. package/dist/contracts/activity.contract.d.ts.map +1 -1
  28. package/dist/contracts/agent.contract.d.ts +13 -205
  29. package/dist/contracts/agent.contract.d.ts.map +1 -1
  30. package/dist/contracts/agent.contract.js +2 -1
  31. package/dist/contracts/agent.contract.js.map +1 -1
  32. package/dist/contracts/agents.contract.d.ts +228 -54
  33. package/dist/contracts/agents.contract.d.ts.map +1 -1
  34. package/dist/contracts/agents.contract.js +11 -2
  35. package/dist/contracts/agents.contract.js.map +1 -1
  36. package/dist/contracts/automations.contract.d.ts +35 -17
  37. package/dist/contracts/automations.contract.d.ts.map +1 -1
  38. package/dist/contracts/automations.contract.js +10 -1
  39. package/dist/contracts/automations.contract.js.map +1 -1
  40. package/dist/contracts/capabilities.contract.d.ts +0 -12
  41. package/dist/contracts/capabilities.contract.d.ts.map +1 -1
  42. package/dist/contracts/capabilities.contract.js +1 -1
  43. package/dist/contracts/capabilities.contract.js.map +1 -1
  44. package/dist/contracts/chores.contract.d.ts.map +1 -1
  45. package/dist/contracts/chores.contract.js.map +1 -1
  46. package/dist/contracts/ci.contract.d.ts +9 -0
  47. package/dist/contracts/ci.contract.d.ts.map +1 -1
  48. package/dist/contracts/endpoints.contract.d.ts.map +1 -1
  49. package/dist/contracts/endpoints.contract.js.map +1 -1
  50. package/dist/contracts/exit.contract.d.ts.map +1 -1
  51. package/dist/contracts/exit.contract.js +1 -1
  52. package/dist/contracts/exit.contract.js.map +1 -1
  53. package/dist/contracts/extensions.contract.d.ts.map +1 -1
  54. package/dist/contracts/extensions.contract.js.map +1 -1
  55. package/dist/contracts/git.contract.d.ts +45 -6
  56. package/dist/contracts/git.contract.d.ts.map +1 -1
  57. package/dist/contracts/git.contract.js +9 -9
  58. package/dist/contracts/git.contract.js.map +1 -1
  59. package/dist/contracts/host.contract.d.ts +2 -0
  60. package/dist/contracts/host.contract.d.ts.map +1 -1
  61. package/dist/contracts/host.contract.js.map +1 -1
  62. package/dist/contracts/intentic.contract.js +1 -1
  63. package/dist/contracts/intentic.contract.js.map +1 -1
  64. package/dist/contracts/logs.contract.d.ts.map +1 -1
  65. package/dist/contracts/logs.contract.js.map +1 -1
  66. package/dist/contracts/loops.contract.d.ts.map +1 -1
  67. package/dist/contracts/loops.contract.js.map +1 -1
  68. package/dist/contracts/personas.contract.d.ts +39 -4
  69. package/dist/contracts/personas.contract.d.ts.map +1 -1
  70. package/dist/contracts/personas.contract.js +10 -1
  71. package/dist/contracts/personas.contract.js.map +1 -1
  72. package/dist/contracts/providers.contract.d.ts.map +1 -1
  73. package/dist/contracts/providers.contract.js.map +1 -1
  74. package/dist/contracts/runner.contract.d.ts +6 -80
  75. package/dist/contracts/runner.contract.d.ts.map +1 -1
  76. package/dist/contracts/runner.contract.js +2 -2
  77. package/dist/contracts/runner.contract.js.map +1 -1
  78. package/dist/contracts/safety.contract.d.ts.map +1 -1
  79. package/dist/contracts/safety.contract.js +1 -1
  80. package/dist/contracts/safety.contract.js.map +1 -1
  81. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  82. package/dist/contracts/secrets.contract.js.map +1 -1
  83. package/dist/contracts/sessions.contract.d.ts +2 -41
  84. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  85. package/dist/contracts/sessions.contract.js +1 -1
  86. package/dist/contracts/sessions.contract.js.map +1 -1
  87. package/dist/contracts/settings.contract.d.ts +10 -10
  88. package/dist/contracts/settings.contract.d.ts.map +1 -1
  89. package/dist/contracts/settings.contract.js.map +1 -1
  90. package/dist/contracts/share.contract.d.ts.map +1 -1
  91. package/dist/contracts/share.contract.js.map +1 -1
  92. package/dist/contracts/skills.contract.d.ts.map +1 -1
  93. package/dist/contracts/skills.contract.js.map +1 -1
  94. package/dist/contracts/system.contract.d.ts +49 -73
  95. package/dist/contracts/system.contract.d.ts.map +1 -1
  96. package/dist/contracts/system.contract.js +12 -2
  97. package/dist/contracts/system.contract.js.map +1 -1
  98. package/dist/contracts/usage.contract.d.ts.map +1 -1
  99. package/dist/contracts/usage.contract.js.map +1 -1
  100. package/dist/contracts/vpn.contract.d.ts.map +1 -1
  101. package/dist/contracts/vpn.contract.js +1 -1
  102. package/dist/contracts/vpn.contract.js.map +1 -1
  103. package/dist/contracts/webext.contract.d.ts.map +1 -1
  104. package/dist/contracts/webext.contract.js.map +1 -1
  105. package/dist/contracts/workflows.contract.d.ts +7 -6
  106. package/dist/contracts/workflows.contract.d.ts.map +1 -1
  107. package/dist/contracts/workflows.contract.js +12 -3
  108. package/dist/contracts/workflows.contract.js.map +1 -1
  109. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  110. package/dist/contracts/workspace.contract.js.map +1 -1
  111. package/dist/events/agent-events.d.ts +1237 -0
  112. package/dist/events/agent-events.d.ts.map +1 -0
  113. package/dist/events/agent-events.js +226 -0
  114. package/dist/events/agent-events.js.map +1 -0
  115. package/dist/events/cards.d.ts +404 -0
  116. package/dist/events/cards.d.ts.map +1 -0
  117. package/dist/events/cards.js +179 -0
  118. package/dist/events/cards.js.map +1 -0
  119. package/dist/events/resume.d.ts +23 -0
  120. package/dist/events/resume.d.ts.map +1 -0
  121. package/dist/events/resume.js +31 -0
  122. package/dist/events/resume.js.map +1 -0
  123. package/dist/events/system-events.d.ts +615 -0
  124. package/dist/events/system-events.d.ts.map +1 -0
  125. package/dist/events/system-events.js +64 -0
  126. package/dist/events/system-events.js.map +1 -0
  127. package/dist/events/transcript.d.ts +1755 -0
  128. package/dist/events/transcript.d.ts.map +1 -0
  129. package/dist/events/transcript.js +205 -0
  130. package/dist/events/transcript.js.map +1 -0
  131. package/dist/ids/conversation-ids.d.ts +8 -0
  132. package/dist/ids/conversation-ids.d.ts.map +1 -0
  133. package/dist/{conversation-ids.js → ids/conversation-ids.js} +13 -0
  134. package/dist/ids/conversation-ids.js.map +1 -0
  135. package/dist/ids/hostnames.d.ts.map +1 -0
  136. package/dist/ids/hostnames.js.map +1 -0
  137. package/dist/ids/session-names.d.ts.map +1 -0
  138. package/dist/ids/session-names.js.map +1 -0
  139. package/dist/ids/share-paths.d.ts.map +1 -0
  140. package/dist/ids/share-paths.js.map +1 -0
  141. package/dist/{tunnel-ids.d.ts → ids/tunnel-ids.d.ts} +1 -0
  142. package/dist/ids/tunnel-ids.d.ts.map +1 -0
  143. package/dist/{tunnel-ids.js → ids/tunnel-ids.js} +1 -0
  144. package/dist/ids/tunnel-ids.js.map +1 -0
  145. package/dist/index.d.ts +464 -447
  146. package/dist/index.d.ts.map +1 -1
  147. package/dist/index.js +54 -47
  148. package/dist/index.js.map +1 -1
  149. package/dist/{agent-catalog.d.ts → models/agent-catalog.d.ts} +2 -2
  150. package/dist/models/agent-catalog.d.ts.map +1 -0
  151. package/dist/models/agent-catalog.js.map +1 -0
  152. package/dist/models/agent-runtimes.d.ts.map +1 -0
  153. package/dist/models/agent-runtimes.js.map +1 -0
  154. package/dist/{fast-tier.d.ts → models/fast-tier.d.ts} +1 -1
  155. package/dist/models/fast-tier.d.ts.map +1 -0
  156. package/dist/models/fast-tier.js.map +1 -0
  157. package/dist/models/model-order.d.ts.map +1 -0
  158. package/dist/models/model-order.js.map +1 -0
  159. package/dist/{model-pins.d.ts → models/model-pins.d.ts} +2 -4
  160. package/dist/models/model-pins.d.ts.map +1 -0
  161. package/dist/models/model-pins.js +22 -0
  162. package/dist/models/model-pins.js.map +1 -0
  163. package/dist/{model-roles.d.ts → models/model-roles.d.ts} +25 -30
  164. package/dist/models/model-roles.d.ts.map +1 -0
  165. package/dist/{model-roles.js → models/model-roles.js} +30 -27
  166. package/dist/models/model-roles.js.map +1 -0
  167. package/dist/{plan-pools.d.ts → models/plan-pools.d.ts} +1 -1
  168. package/dist/models/plan-pools.d.ts.map +1 -0
  169. package/dist/models/plan-pools.js.map +1 -0
  170. package/dist/models/prompt-complexity.d.ts.map +1 -0
  171. package/dist/models/prompt-complexity.js.map +1 -0
  172. package/dist/models/provider-specs.d.ts.map +1 -0
  173. package/dist/models/provider-specs.js.map +1 -0
  174. package/dist/policy/approvals-execution.d.ts.map +1 -0
  175. package/dist/policy/approvals-execution.js.map +1 -0
  176. package/dist/{batch-runs.d.ts → policy/batch-runs.d.ts} +5 -1
  177. package/dist/policy/batch-runs.d.ts.map +1 -0
  178. package/dist/{batch-runs.js → policy/batch-runs.js} +10 -7
  179. package/dist/policy/batch-runs.js.map +1 -0
  180. package/dist/policy/capability-env.d.ts.map +1 -0
  181. package/dist/policy/capability-env.js.map +1 -0
  182. package/dist/policy/capability-secrets.d.ts.map +1 -0
  183. package/dist/policy/capability-secrets.js.map +1 -0
  184. package/dist/{card-status.d.ts → policy/card-status.d.ts} +2 -2
  185. package/dist/policy/card-status.d.ts.map +1 -0
  186. package/dist/{card-status.js → policy/card-status.js} +1 -5
  187. package/dist/policy/card-status.js.map +1 -0
  188. package/dist/{command-classes.d.ts → policy/command-classes.d.ts} +6 -2
  189. package/dist/policy/command-classes.d.ts.map +1 -0
  190. package/dist/{command-classes.js → policy/command-classes.js} +48 -11
  191. package/dist/policy/command-classes.js.map +1 -0
  192. package/dist/{command-run.d.ts → policy/command-run.d.ts} +1 -1
  193. package/dist/policy/command-run.d.ts.map +1 -0
  194. package/dist/policy/command-run.js.map +1 -0
  195. package/dist/policy/control-scopes.d.ts +16 -0
  196. package/dist/policy/control-scopes.d.ts.map +1 -0
  197. package/dist/policy/control-scopes.js +26 -0
  198. package/dist/policy/control-scopes.js.map +1 -0
  199. package/dist/policy/credential-material.d.ts.map +1 -0
  200. package/dist/policy/credential-material.js.map +1 -0
  201. package/dist/policy/needs-action.d.ts.map +1 -0
  202. package/dist/policy/needs-action.js.map +1 -0
  203. package/dist/policy/output-fields.d.ts.map +1 -0
  204. package/dist/policy/output-fields.js.map +1 -0
  205. package/dist/policy/overlay-lint.d.ts.map +1 -0
  206. package/dist/policy/overlay-lint.js.map +1 -0
  207. package/dist/policy/owner-ticket.d.ts.map +1 -0
  208. package/dist/{owner-ticket.js → policy/owner-ticket.js} +1 -1
  209. package/dist/policy/owner-ticket.js.map +1 -0
  210. package/dist/{safety-policy.d.ts → policy/safety-policy.d.ts} +6 -5
  211. package/dist/policy/safety-policy.d.ts.map +1 -0
  212. package/dist/{safety-policy.js → policy/safety-policy.js} +12 -12
  213. package/dist/policy/safety-policy.js.map +1 -0
  214. package/dist/policy/search-globs.d.ts.map +1 -0
  215. package/dist/policy/search-globs.js.map +1 -0
  216. package/dist/protocol/container-requirements.d.ts +20 -0
  217. package/dist/protocol/container-requirements.d.ts.map +1 -0
  218. package/dist/protocol/container-requirements.js +23 -0
  219. package/dist/protocol/container-requirements.js.map +1 -0
  220. package/dist/{host-protocol.d.ts → protocol/host-protocol.d.ts} +1 -0
  221. package/dist/protocol/host-protocol.d.ts.map +1 -0
  222. package/dist/{host-protocol.js → protocol/host-protocol.js} +1 -0
  223. package/dist/protocol/host-protocol.js.map +1 -0
  224. package/dist/protocol/ingress-contract.d.ts.map +1 -0
  225. package/dist/{ingress-contract.js → protocol/ingress-contract.js} +1 -1
  226. package/dist/protocol/ingress-contract.js.map +1 -0
  227. package/dist/protocol/ingress-protocol.d.ts.map +1 -0
  228. package/dist/protocol/ingress-protocol.js.map +1 -0
  229. package/dist/protocol/listener-protocol.d.ts.map +1 -0
  230. package/dist/{listener-protocol.js → protocol/listener-protocol.js} +1 -1
  231. package/dist/protocol/listener-protocol.js.map +1 -0
  232. package/dist/{peer-dial.d.ts → protocol/peer-dial.d.ts} +4 -1
  233. package/dist/protocol/peer-dial.d.ts.map +1 -0
  234. package/dist/{peer-dial.js → protocol/peer-dial.js} +51 -10
  235. package/dist/protocol/peer-dial.js.map +1 -0
  236. package/dist/protocol/peer-mcp-server.d.ts.map +1 -0
  237. package/dist/protocol/peer-mcp-server.js.map +1 -0
  238. package/dist/protocol/request-id.d.ts.map +1 -0
  239. package/dist/protocol/request-id.js.map +1 -0
  240. package/dist/protocol/routes.d.ts.map +1 -0
  241. package/dist/protocol/routes.js.map +1 -0
  242. package/dist/{runner-protocol.d.ts → protocol/runner-protocol.d.ts} +1 -0
  243. package/dist/protocol/runner-protocol.d.ts.map +1 -0
  244. package/dist/{runner-protocol.js → protocol/runner-protocol.js} +2 -1
  245. package/dist/protocol/runner-protocol.js.map +1 -0
  246. package/dist/protocol/sse.d.ts.map +1 -0
  247. package/dist/protocol/sse.js.map +1 -0
  248. package/dist/{terminal-protocol.d.ts → protocol/terminal-protocol.d.ts} +1 -3
  249. package/dist/protocol/terminal-protocol.d.ts.map +1 -0
  250. package/dist/protocol/terminal-protocol.js.map +1 -0
  251. package/dist/protocol/webext-links.d.ts.map +1 -0
  252. package/dist/protocol/webext-links.js.map +1 -0
  253. package/dist/{webext-protocol.d.ts → protocol/webext-protocol.d.ts} +1 -0
  254. package/dist/protocol/webext-protocol.d.ts.map +1 -0
  255. package/dist/{webext-protocol.js → protocol/webext-protocol.js} +1 -0
  256. package/dist/protocol/webext-protocol.js.map +1 -0
  257. package/dist/schemas/activity.d.ts +2 -0
  258. package/dist/schemas/activity.d.ts.map +1 -1
  259. package/dist/schemas/activity.js +4 -0
  260. package/dist/schemas/activity.js.map +1 -1
  261. package/dist/schemas/agent.d.ts +17 -4
  262. package/dist/schemas/agent.d.ts.map +1 -1
  263. package/dist/schemas/agent.js +21 -4
  264. package/dist/schemas/agent.js.map +1 -1
  265. package/dist/schemas/agents.d.ts +17 -4
  266. package/dist/schemas/agents.d.ts.map +1 -1
  267. package/dist/schemas/agents.js +15 -4
  268. package/dist/schemas/agents.js.map +1 -1
  269. package/dist/schemas/approvals.d.ts.map +1 -1
  270. package/dist/schemas/approvals.js.map +1 -1
  271. package/dist/schemas/automations.d.ts +54 -28
  272. package/dist/schemas/automations.d.ts.map +1 -1
  273. package/dist/schemas/automations.js +26 -8
  274. package/dist/schemas/automations.js.map +1 -1
  275. package/dist/schemas/capabilities.d.ts +0 -8
  276. package/dist/schemas/capabilities.d.ts.map +1 -1
  277. package/dist/schemas/capabilities.js +0 -4
  278. package/dist/schemas/capabilities.js.map +1 -1
  279. package/dist/schemas/ci.d.ts +10 -0
  280. package/dist/schemas/ci.d.ts.map +1 -1
  281. package/dist/schemas/ci.js +9 -1
  282. package/dist/schemas/ci.js.map +1 -1
  283. package/dist/schemas/codebase-health.d.ts.map +1 -1
  284. package/dist/schemas/codebase-health.js.map +1 -1
  285. package/dist/schemas/devices.d.ts +90 -0
  286. package/dist/schemas/devices.d.ts.map +1 -1
  287. package/dist/schemas/devices.js +10 -1
  288. package/dist/schemas/devices.js.map +1 -1
  289. package/dist/schemas/engines.d.ts.map +1 -1
  290. package/dist/schemas/engines.js.map +1 -1
  291. package/dist/schemas/environment.d.ts.map +1 -1
  292. package/dist/schemas/environment.js.map +1 -1
  293. package/dist/schemas/exit.d.ts.map +1 -1
  294. package/dist/schemas/exit.js.map +1 -1
  295. package/dist/schemas/extension-updates.d.ts.map +1 -1
  296. package/dist/schemas/extension-updates.js.map +1 -1
  297. package/dist/schemas/git-history.d.ts.map +1 -1
  298. package/dist/schemas/git-history.js.map +1 -1
  299. package/dist/schemas/git.d.ts +80 -16
  300. package/dist/schemas/git.d.ts.map +1 -1
  301. package/dist/schemas/git.js +37 -25
  302. package/dist/schemas/git.js.map +1 -1
  303. package/dist/schemas/history.d.ts.map +1 -1
  304. package/dist/schemas/history.js.map +1 -1
  305. package/dist/schemas/hosts.d.ts.map +1 -1
  306. package/dist/schemas/hosts.js.map +1 -1
  307. package/dist/schemas/inventory.d.ts.map +1 -1
  308. package/dist/schemas/inventory.js.map +1 -1
  309. package/dist/schemas/issues.d.ts +0 -1
  310. package/dist/schemas/issues.d.ts.map +1 -1
  311. package/dist/schemas/issues.js +0 -1
  312. package/dist/schemas/issues.js.map +1 -1
  313. package/dist/schemas/logs.d.ts.map +1 -1
  314. package/dist/schemas/logs.js.map +1 -1
  315. package/dist/schemas/loops.d.ts.map +1 -1
  316. package/dist/schemas/loops.js +1 -1
  317. package/dist/schemas/loops.js.map +1 -1
  318. package/dist/schemas/maintenance.d.ts.map +1 -1
  319. package/dist/schemas/maintenance.js.map +1 -1
  320. package/dist/schemas/marketplace.d.ts +0 -4
  321. package/dist/schemas/marketplace.d.ts.map +1 -1
  322. package/dist/schemas/panels.d.ts.map +1 -1
  323. package/dist/schemas/panels.js.map +1 -1
  324. package/dist/schemas/personas.d.ts +49 -4
  325. package/dist/schemas/personas.d.ts.map +1 -1
  326. package/dist/schemas/personas.js +32 -5
  327. package/dist/schemas/personas.js.map +1 -1
  328. package/dist/schemas/plan-limits.d.ts +2 -4
  329. package/dist/schemas/plan-limits.d.ts.map +1 -1
  330. package/dist/schemas/plan-limits.js +5 -8
  331. package/dist/schemas/plan-limits.js.map +1 -1
  332. package/dist/schemas/ports.d.ts.map +1 -1
  333. package/dist/schemas/ports.js.map +1 -1
  334. package/dist/schemas/provider-oauth.d.ts.map +1 -1
  335. package/dist/schemas/provider-oauth.js.map +1 -1
  336. package/dist/schemas/provider-subscriptions.d.ts +1 -1
  337. package/dist/schemas/provider-subscriptions.d.ts.map +1 -1
  338. package/dist/schemas/provider-subscriptions.js +1 -1
  339. package/dist/schemas/provider-subscriptions.js.map +1 -1
  340. package/dist/schemas/public.d.ts.map +1 -1
  341. package/dist/schemas/public.js.map +1 -1
  342. package/dist/schemas/push.d.ts.map +1 -1
  343. package/dist/schemas/push.js.map +1 -1
  344. package/dist/schemas/secrets.d.ts.map +1 -1
  345. package/dist/schemas/secrets.js.map +1 -1
  346. package/dist/schemas/settings.d.ts +7 -5
  347. package/dist/schemas/settings.d.ts.map +1 -1
  348. package/dist/schemas/settings.js +18 -8
  349. package/dist/schemas/settings.js.map +1 -1
  350. package/dist/schemas/share.d.ts.map +1 -1
  351. package/dist/schemas/share.js.map +1 -1
  352. package/dist/schemas/shared.d.ts +4 -0
  353. package/dist/schemas/shared.d.ts.map +1 -1
  354. package/dist/schemas/shared.js +3 -0
  355. package/dist/schemas/shared.js.map +1 -1
  356. package/dist/schemas/system.d.ts +6 -0
  357. package/dist/schemas/system.d.ts.map +1 -1
  358. package/dist/schemas/system.js +10 -0
  359. package/dist/schemas/system.js.map +1 -1
  360. package/dist/schemas/terminal.d.ts.map +1 -1
  361. package/dist/schemas/terminal.js.map +1 -1
  362. package/dist/schemas/usage.d.ts.map +1 -1
  363. package/dist/schemas/usage.js.map +1 -1
  364. package/dist/schemas/vpn.d.ts.map +1 -1
  365. package/dist/schemas/vpn.js.map +1 -1
  366. package/dist/schemas/webext.d.ts.map +1 -1
  367. package/dist/schemas/webext.js.map +1 -1
  368. package/dist/schemas/workflows.d.ts +66 -9
  369. package/dist/schemas/workflows.d.ts.map +1 -1
  370. package/dist/schemas/workflows.js +6 -5
  371. package/dist/schemas/workflows.js.map +1 -1
  372. package/dist/schemas/workspace-repos.d.ts.map +1 -1
  373. package/dist/schemas/workspace-repos.js.map +1 -1
  374. package/dist/schemas/workspace-search.d.ts.map +1 -1
  375. package/dist/schemas/workspace-search.js.map +1 -1
  376. package/dist/schemas/workspace-setup.d.ts.map +1 -1
  377. package/dist/schemas/workspace-setup.js.map +1 -1
  378. package/dist/schemas/workspace-tree.d.ts.map +1 -1
  379. package/dist/schemas/workspace-tree.js.map +1 -1
  380. package/dist/state/arrival.d.ts.map +1 -0
  381. package/dist/{arrival.js → state/arrival.js} +1 -1
  382. package/dist/state/arrival.js.map +1 -0
  383. package/dist/state/contract-lock.d.ts.map +1 -0
  384. package/dist/{contract-lock.js → state/contract-lock.js} +1 -1
  385. package/dist/state/contract-lock.js.map +1 -0
  386. package/dist/{definition.d.ts → state/definition.d.ts} +21 -17
  387. package/dist/state/definition.d.ts.map +1 -0
  388. package/dist/{definition.js → state/definition.js} +4 -4
  389. package/dist/state/definition.js.map +1 -0
  390. package/dist/state/history-state.d.ts.map +1 -0
  391. package/dist/{history-state.js → state/history-state.js} +1 -0
  392. package/dist/state/history-state.js.map +1 -0
  393. package/dist/state/runtime-state.d.ts.map +1 -0
  394. package/dist/state/runtime-state.js.map +1 -0
  395. package/dist/state/starter.d.ts.map +1 -0
  396. package/dist/state/starter.js.map +1 -0
  397. package/dist/state/state-portability.d.ts.map +1 -0
  398. package/dist/state/state-portability.js.map +1 -0
  399. package/dist/state/versions.d.ts.map +1 -0
  400. package/dist/state/versions.js.map +1 -0
  401. package/dist/{workspace-state.d.ts → state/workspace-state.d.ts} +8 -5
  402. package/dist/state/workspace-state.d.ts.map +1 -0
  403. package/dist/{workspace-state.js → state/workspace-state.js} +25 -1
  404. package/dist/state/workspace-state.js.map +1 -0
  405. package/dist/{documents.d.ts → text/documents.d.ts} +1 -1
  406. package/dist/text/documents.d.ts.map +1 -0
  407. package/dist/{documents.js → text/documents.js} +1 -1
  408. package/dist/text/documents.js.map +1 -0
  409. package/dist/text/embed.d.ts.map +1 -0
  410. package/dist/text/embed.js.map +1 -0
  411. package/dist/text/mentions.d.ts.map +1 -0
  412. package/dist/text/mentions.js.map +1 -0
  413. package/dist/text/model-answer.d.ts +3 -0
  414. package/dist/text/model-answer.d.ts.map +1 -0
  415. package/dist/text/model-answer.js +3 -0
  416. package/dist/text/model-answer.js.map +1 -0
  417. package/dist/text/path-refs.d.ts.map +1 -0
  418. package/dist/text/path-refs.js.map +1 -0
  419. package/dist/{shell-regions.d.ts → text/shell-regions.d.ts} +1 -1
  420. package/dist/text/shell-regions.d.ts.map +1 -0
  421. package/dist/text/shell-regions.js.map +1 -0
  422. package/dist/text/title.d.ts.map +1 -0
  423. package/dist/text/title.js.map +1 -0
  424. package/dist/{transcript-fold.d.ts → text/transcript-fold.d.ts} +2 -1
  425. package/dist/text/transcript-fold.d.ts.map +1 -0
  426. package/dist/{transcript-fold.js → text/transcript-fold.js} +2 -16
  427. package/dist/text/transcript-fold.js.map +1 -0
  428. package/dist/text/whisper.d.ts +3 -0
  429. package/dist/text/whisper.d.ts.map +1 -0
  430. package/dist/text/whisper.js +11 -0
  431. package/dist/text/whisper.js.map +1 -0
  432. package/dist/{workflow-faults.d.ts → text/workflow-faults.d.ts} +1 -1
  433. package/dist/text/workflow-faults.d.ts.map +1 -0
  434. package/dist/{workflow-faults.js → text/workflow-faults.js} +1 -1
  435. package/dist/text/workflow-faults.js.map +1 -0
  436. package/package.json +70 -70
  437. package/src/chores/chores.test.ts +4 -10
  438. package/src/chores/chores.ts +148 -392
  439. package/src/chores/digest.ts +8 -28
  440. package/src/chores/extension-update.ts +3 -8
  441. package/src/chores/fix-deps.ts +4 -18
  442. package/src/chores/index.ts +2 -2
  443. package/src/chores/probes.test.ts +7 -43
  444. package/src/chores/probes.ts +62 -167
  445. package/src/chores/prompt.ts +10 -34
  446. package/src/chores/stack.test.ts +6 -45
  447. package/src/chores/stack.ts +27 -118
  448. package/src/chores/verdict.test.ts +101 -80
  449. package/src/chores/verdict.ts +54 -99
  450. package/src/contracts/accounts.contract.ts +4 -19
  451. package/src/contracts/agent.contract.ts +7 -22
  452. package/src/contracts/agents.contract.ts +25 -71
  453. package/src/contracts/automations.contract.ts +14 -30
  454. package/src/contracts/capabilities.contract.ts +8 -35
  455. package/src/contracts/chores.contract.ts +4 -15
  456. package/src/contracts/endpoints.contract.ts +5 -22
  457. package/src/contracts/exit.contract.ts +7 -30
  458. package/src/contracts/extensions.contract.ts +8 -30
  459. package/src/contracts/git.contract.ts +25 -49
  460. package/src/contracts/host.contract.ts +9 -44
  461. package/src/contracts/intentic.contract.ts +1 -1
  462. package/src/contracts/logs.contract.ts +3 -13
  463. package/src/contracts/loops.contract.ts +9 -40
  464. package/src/contracts/personas.contract.ts +22 -30
  465. package/src/contracts/providers.contract.ts +4 -17
  466. package/src/contracts/runner.contract.ts +12 -39
  467. package/src/contracts/safety.contract.ts +5 -14
  468. package/src/contracts/secrets.contract.ts +4 -22
  469. package/src/contracts/sessions.contract.ts +1 -1
  470. package/src/contracts/settings.contract.ts +4 -10
  471. package/src/contracts/share.contract.ts +3 -9
  472. package/src/contracts/skills.contract.ts +4 -15
  473. package/src/contracts/system.contract.ts +26 -52
  474. package/src/contracts/usage.contract.ts +7 -21
  475. package/src/contracts/vpn.contract.ts +9 -16
  476. package/src/contracts/webext.contract.ts +9 -25
  477. package/src/contracts/workflows.contract.ts +34 -58
  478. package/src/contracts/workspace.contract.ts +19 -50
  479. package/src/events/agent-events.ts +345 -0
  480. package/src/events/cards.ts +286 -0
  481. package/src/{events.test.ts → events/resume.test.ts} +4 -19
  482. package/src/events/resume.ts +60 -0
  483. package/src/events/system-events.ts +139 -0
  484. package/src/events/transcript.ts +320 -0
  485. package/src/{conversation-ids.test.ts → ids/conversation-ids.test.ts} +25 -13
  486. package/src/ids/conversation-ids.ts +178 -0
  487. package/src/ids/hostnames.ts +129 -0
  488. package/src/ids/session-names.ts +29 -0
  489. package/src/ids/share-paths.ts +43 -0
  490. package/src/{tunnel-ids.test.ts → ids/tunnel-ids.test.ts} +1 -14
  491. package/src/ids/tunnel-ids.ts +29 -0
  492. package/src/index.ts +71 -88
  493. package/src/{agent-catalog.test.ts → models/agent-catalog.test.ts} +19 -93
  494. package/src/models/agent-catalog.ts +174 -0
  495. package/src/models/agent-runtimes.ts +201 -0
  496. package/src/models/capability-ledger.test.ts +84 -0
  497. package/src/{fast-tier.test.ts → models/fast-tier.test.ts} +7 -18
  498. package/src/models/fast-tier.ts +36 -0
  499. package/src/{model-order.test.ts → models/model-order.test.ts} +19 -40
  500. package/src/models/model-order.ts +163 -0
  501. package/src/models/model-pins.test.ts +87 -0
  502. package/src/models/model-pins.ts +57 -0
  503. package/src/models/model-roles.test.ts +38 -0
  504. package/src/models/model-roles.ts +180 -0
  505. package/src/{plan-pools.test.ts → models/plan-pools.test.ts} +6 -11
  506. package/src/models/plan-pools.ts +65 -0
  507. package/src/{prompt-complexity.test.ts → models/prompt-complexity.test.ts} +8 -60
  508. package/src/models/prompt-complexity.ts +215 -0
  509. package/src/{provider-specs.test.ts → models/provider-specs.test.ts} +18 -47
  510. package/src/models/provider-specs.ts +272 -0
  511. package/src/policy/approvals-execution.ts +58 -0
  512. package/src/{batch-runs.test.ts → policy/batch-runs.test.ts} +4 -20
  513. package/src/policy/batch-runs.ts +137 -0
  514. package/src/policy/capability-secrets.ts +5 -0
  515. package/src/{card-status.ts → policy/card-status.ts} +11 -26
  516. package/src/{command-classes.test.ts → policy/command-classes.test.ts} +11 -118
  517. package/src/policy/command-classes.ts +395 -0
  518. package/src/policy/command-run.ts +65 -0
  519. package/src/policy/control-scopes.ts +38 -0
  520. package/src/{credential-material.test.ts → policy/credential-material.test.ts} +4 -26
  521. package/src/policy/credential-material.ts +91 -0
  522. package/src/policy/needs-action.ts +5 -0
  523. package/src/policy/output-fields.ts +86 -0
  524. package/src/policy/overlay-lint.ts +100 -0
  525. package/src/{owner-ticket.test.ts → policy/owner-ticket.test.ts} +1 -1
  526. package/src/{owner-ticket.ts → policy/owner-ticket.ts} +9 -31
  527. package/src/policy/safety-policy.test.ts +84 -0
  528. package/src/policy/safety-policy.ts +142 -0
  529. package/src/policy/search-globs.ts +60 -0
  530. package/src/protocol/container-requirements.test.ts +72 -0
  531. package/src/protocol/container-requirements.ts +58 -0
  532. package/src/protocol/host-protocol.ts +29 -0
  533. package/src/protocol/ingress-contract.ts +103 -0
  534. package/src/{ingress-protocol.test.ts → protocol/ingress-protocol.test.ts} +25 -90
  535. package/src/protocol/ingress-protocol.ts +441 -0
  536. package/src/protocol/listener-protocol.ts +75 -0
  537. package/src/{peer-dial.test.ts → protocol/peer-dial.test.ts} +52 -1
  538. package/src/protocol/peer-dial.ts +207 -0
  539. package/src/{peer-mcp-server.ts → protocol/peer-mcp-server.ts} +16 -41
  540. package/src/protocol/request-id.ts +5 -0
  541. package/src/{routes.test.ts → protocol/routes.test.ts} +14 -22
  542. package/src/protocol/routes.ts +159 -0
  543. package/src/protocol/runner-protocol.ts +197 -0
  544. package/src/protocol/terminal-protocol.ts +13 -0
  545. package/src/protocol/webext-links.ts +50 -0
  546. package/src/protocol/webext-protocol.ts +24 -0
  547. package/src/schemas/activity.ts +22 -30
  548. package/src/schemas/agent.ts +130 -238
  549. package/src/schemas/agents.ts +165 -483
  550. package/src/schemas/approvals.ts +23 -71
  551. package/src/schemas/automations.ts +145 -249
  552. package/src/schemas/capabilities.ts +127 -414
  553. package/src/schemas/ci.ts +56 -108
  554. package/src/schemas/codebase-health.ts +7 -11
  555. package/src/schemas/devices.ts +98 -321
  556. package/src/schemas/engines.ts +16 -44
  557. package/src/schemas/environment.ts +41 -91
  558. package/src/schemas/exit.ts +24 -81
  559. package/src/schemas/extension-updates.ts +42 -87
  560. package/src/schemas/git-history.ts +30 -84
  561. package/src/schemas/git.ts +141 -256
  562. package/src/schemas/history.ts +14 -40
  563. package/src/schemas/hosts.ts +9 -15
  564. package/src/schemas/inventory.ts +8 -10
  565. package/src/schemas/issues.ts +66 -134
  566. package/src/schemas/logs.ts +15 -34
  567. package/src/schemas/loops.ts +46 -163
  568. package/src/schemas/maintenance.ts +47 -172
  569. package/src/schemas/panels.ts +20 -45
  570. package/src/schemas/personas.ts +85 -168
  571. package/src/schemas/plan-limits.ts +58 -197
  572. package/src/schemas/ports.ts +14 -32
  573. package/src/schemas/provider-oauth.ts +23 -76
  574. package/src/schemas/provider-subscriptions.ts +4 -13
  575. package/src/schemas/public.ts +4 -15
  576. package/src/schemas/push.ts +8 -36
  577. package/src/schemas/secrets.ts +20 -64
  578. package/src/schemas/settings.ts +177 -597
  579. package/src/schemas/share.ts +14 -32
  580. package/src/schemas/shared.ts +14 -13
  581. package/src/schemas/system.ts +46 -78
  582. package/src/schemas/terminal.ts +41 -120
  583. package/src/schemas/usage.ts +44 -233
  584. package/src/schemas/version-seam.test.ts +9 -26
  585. package/src/schemas/vpn.ts +27 -64
  586. package/src/schemas/webext.ts +22 -53
  587. package/src/schemas/workflows.ts +57 -183
  588. package/src/schemas/workspace-repos.ts +12 -24
  589. package/src/schemas/workspace-search.ts +17 -35
  590. package/src/schemas/workspace-setup.ts +4 -11
  591. package/src/schemas/workspace-tree.ts +32 -91
  592. package/src/state/arrival.ts +109 -0
  593. package/src/state/contract-lock.test.ts +17 -0
  594. package/src/state/contract-lock.ts +49 -0
  595. package/src/state/definition.ts +143 -0
  596. package/src/state/history-state.ts +103 -0
  597. package/src/{runtime-state.test.ts → state/runtime-state.test.ts} +3 -10
  598. package/src/state/runtime-state.ts +62 -0
  599. package/src/state/starter.ts +5 -0
  600. package/src/state/state-portability.ts +27 -0
  601. package/src/state/versions.ts +26 -0
  602. package/src/{workspace-state.test.ts → state/workspace-state.test.ts} +65 -173
  603. package/src/state/workspace-state.ts +669 -0
  604. package/src/{documents.test.ts → text/documents.test.ts} +1 -1
  605. package/src/text/documents.ts +42 -0
  606. package/src/text/embed.ts +132 -0
  607. package/src/text/mentions.ts +21 -0
  608. package/src/text/model-answer.ts +9 -0
  609. package/src/text/path-refs.ts +39 -0
  610. package/src/text/shell-regions.ts +224 -0
  611. package/src/{title.test.ts → text/title.test.ts} +13 -32
  612. package/src/text/title.ts +202 -0
  613. package/src/{transcript-fold.test.ts → text/transcript-fold.test.ts} +5 -83
  614. package/src/{transcript-fold.ts → text/transcript-fold.ts} +65 -170
  615. package/src/text/whisper.test.ts +19 -0
  616. package/src/text/whisper.ts +17 -0
  617. package/src/{workflow-faults.test.ts → text/workflow-faults.test.ts} +6 -24
  618. package/src/{workflow-faults.ts → text/workflow-faults.ts} +20 -60
  619. package/dist/agent-catalog.d.ts.map +0 -1
  620. package/dist/agent-catalog.js.map +0 -1
  621. package/dist/agent-runtimes.d.ts.map +0 -1
  622. package/dist/agent-runtimes.js.map +0 -1
  623. package/dist/approvals-execution.d.ts.map +0 -1
  624. package/dist/approvals-execution.js.map +0 -1
  625. package/dist/arrival.d.ts.map +0 -1
  626. package/dist/arrival.js.map +0 -1
  627. package/dist/batch-runs.d.ts.map +0 -1
  628. package/dist/batch-runs.js.map +0 -1
  629. package/dist/capability-env.d.ts.map +0 -1
  630. package/dist/capability-env.js.map +0 -1
  631. package/dist/capability-secrets.d.ts.map +0 -1
  632. package/dist/capability-secrets.js.map +0 -1
  633. package/dist/card-status.d.ts.map +0 -1
  634. package/dist/card-status.js.map +0 -1
  635. package/dist/command-classes.d.ts.map +0 -1
  636. package/dist/command-classes.js.map +0 -1
  637. package/dist/command-run.d.ts.map +0 -1
  638. package/dist/command-run.js.map +0 -1
  639. package/dist/contract-lock.d.ts.map +0 -1
  640. package/dist/contract-lock.js.map +0 -1
  641. package/dist/conversation-ids.d.ts +0 -4
  642. package/dist/conversation-ids.d.ts.map +0 -1
  643. package/dist/conversation-ids.js.map +0 -1
  644. package/dist/credential-material.d.ts.map +0 -1
  645. package/dist/credential-material.js.map +0 -1
  646. package/dist/definition.d.ts.map +0 -1
  647. package/dist/definition.js.map +0 -1
  648. package/dist/documents.d.ts.map +0 -1
  649. package/dist/documents.js.map +0 -1
  650. package/dist/embed.d.ts.map +0 -1
  651. package/dist/embed.js.map +0 -1
  652. package/dist/events.d.ts +0 -4336
  653. package/dist/events.d.ts.map +0 -1
  654. package/dist/events.js +0 -725
  655. package/dist/events.js.map +0 -1
  656. package/dist/fast-tier.d.ts.map +0 -1
  657. package/dist/fast-tier.js.map +0 -1
  658. package/dist/history-state.d.ts.map +0 -1
  659. package/dist/history-state.js.map +0 -1
  660. package/dist/host-protocol.d.ts.map +0 -1
  661. package/dist/host-protocol.js.map +0 -1
  662. package/dist/hostnames.d.ts.map +0 -1
  663. package/dist/hostnames.js.map +0 -1
  664. package/dist/ingress-contract.d.ts.map +0 -1
  665. package/dist/ingress-contract.js.map +0 -1
  666. package/dist/ingress-protocol.d.ts.map +0 -1
  667. package/dist/ingress-protocol.js.map +0 -1
  668. package/dist/listener-protocol.d.ts.map +0 -1
  669. package/dist/listener-protocol.js.map +0 -1
  670. package/dist/mentions.d.ts.map +0 -1
  671. package/dist/mentions.js.map +0 -1
  672. package/dist/model-order.d.ts.map +0 -1
  673. package/dist/model-order.js.map +0 -1
  674. package/dist/model-pins.d.ts.map +0 -1
  675. package/dist/model-pins.js +0 -45
  676. package/dist/model-pins.js.map +0 -1
  677. package/dist/model-roles.d.ts.map +0 -1
  678. package/dist/model-roles.js.map +0 -1
  679. package/dist/needs-action.d.ts.map +0 -1
  680. package/dist/needs-action.js.map +0 -1
  681. package/dist/output-fields.d.ts.map +0 -1
  682. package/dist/output-fields.js.map +0 -1
  683. package/dist/overlay-lint.d.ts.map +0 -1
  684. package/dist/overlay-lint.js.map +0 -1
  685. package/dist/owner-ticket.d.ts.map +0 -1
  686. package/dist/owner-ticket.js.map +0 -1
  687. package/dist/path-refs.d.ts.map +0 -1
  688. package/dist/path-refs.js.map +0 -1
  689. package/dist/peer-dial.d.ts.map +0 -1
  690. package/dist/peer-dial.js.map +0 -1
  691. package/dist/peer-mcp-server.d.ts.map +0 -1
  692. package/dist/peer-mcp-server.js.map +0 -1
  693. package/dist/plan-pools.d.ts.map +0 -1
  694. package/dist/plan-pools.js.map +0 -1
  695. package/dist/prompt-complexity.d.ts.map +0 -1
  696. package/dist/prompt-complexity.js.map +0 -1
  697. package/dist/provider-specs.d.ts.map +0 -1
  698. package/dist/provider-specs.js.map +0 -1
  699. package/dist/request-id.d.ts.map +0 -1
  700. package/dist/request-id.js.map +0 -1
  701. package/dist/routes.d.ts.map +0 -1
  702. package/dist/routes.js.map +0 -1
  703. package/dist/runner-protocol.d.ts.map +0 -1
  704. package/dist/runner-protocol.js.map +0 -1
  705. package/dist/runtime-state.d.ts.map +0 -1
  706. package/dist/runtime-state.js.map +0 -1
  707. package/dist/safety-policy.d.ts.map +0 -1
  708. package/dist/safety-policy.js.map +0 -1
  709. package/dist/schemas/context.d.ts +0 -30
  710. package/dist/schemas/context.d.ts.map +0 -1
  711. package/dist/schemas/context.js +0 -34
  712. package/dist/schemas/context.js.map +0 -1
  713. package/dist/search-globs.d.ts.map +0 -1
  714. package/dist/search-globs.js.map +0 -1
  715. package/dist/session-names.d.ts.map +0 -1
  716. package/dist/session-names.js.map +0 -1
  717. package/dist/share-paths.d.ts.map +0 -1
  718. package/dist/share-paths.js.map +0 -1
  719. package/dist/shell-regions.d.ts.map +0 -1
  720. package/dist/shell-regions.js.map +0 -1
  721. package/dist/sse.d.ts.map +0 -1
  722. package/dist/sse.js.map +0 -1
  723. package/dist/starter.d.ts.map +0 -1
  724. package/dist/starter.js.map +0 -1
  725. package/dist/state-portability.d.ts.map +0 -1
  726. package/dist/state-portability.js.map +0 -1
  727. package/dist/terminal-protocol.d.ts.map +0 -1
  728. package/dist/terminal-protocol.js.map +0 -1
  729. package/dist/title.d.ts.map +0 -1
  730. package/dist/title.js.map +0 -1
  731. package/dist/transcript-fold.d.ts.map +0 -1
  732. package/dist/transcript-fold.js.map +0 -1
  733. package/dist/tunnel-ids.d.ts.map +0 -1
  734. package/dist/tunnel-ids.js.map +0 -1
  735. package/dist/versions.d.ts.map +0 -1
  736. package/dist/versions.js.map +0 -1
  737. package/dist/webext-links.d.ts.map +0 -1
  738. package/dist/webext-links.js.map +0 -1
  739. package/dist/webext-protocol.d.ts.map +0 -1
  740. package/dist/webext-protocol.js.map +0 -1
  741. package/dist/workflow-faults.d.ts.map +0 -1
  742. package/dist/workflow-faults.js.map +0 -1
  743. package/dist/workspace-state.d.ts.map +0 -1
  744. package/dist/workspace-state.js.map +0 -1
  745. package/src/agent-catalog.ts +0 -316
  746. package/src/agent-runtimes.ts +0 -419
  747. package/src/approvals-execution.ts +0 -96
  748. package/src/arrival.ts +0 -160
  749. package/src/batch-runs.ts +0 -188
  750. package/src/capability-ledger.test.ts +0 -140
  751. package/src/capability-secrets.ts +0 -20
  752. package/src/command-classes.ts +0 -617
  753. package/src/command-run.ts +0 -78
  754. package/src/contract-lock.test.ts +0 -23
  755. package/src/contract-lock.ts +0 -66
  756. package/src/conversation-ids.ts +0 -207
  757. package/src/credential-material.ts +0 -181
  758. package/src/definition.ts +0 -207
  759. package/src/documents.ts +0 -67
  760. package/src/embed.ts +0 -164
  761. package/src/events.ts +0 -1870
  762. package/src/fast-tier.ts +0 -72
  763. package/src/history-state.ts +0 -174
  764. package/src/host-protocol.ts +0 -36
  765. package/src/hostnames.ts +0 -180
  766. package/src/ingress-contract.ts +0 -157
  767. package/src/ingress-protocol.ts +0 -625
  768. package/src/listener-protocol.ts +0 -96
  769. package/src/mentions.ts +0 -25
  770. package/src/model-order.ts +0 -262
  771. package/src/model-pins.test.ts +0 -202
  772. package/src/model-pins.ts +0 -183
  773. package/src/model-roles.ts +0 -224
  774. package/src/needs-action.ts +0 -14
  775. package/src/output-fields.ts +0 -111
  776. package/src/overlay-lint.ts +0 -116
  777. package/src/path-refs.ts +0 -59
  778. package/src/peer-dial.ts +0 -163
  779. package/src/plan-pools.ts +0 -92
  780. package/src/prompt-complexity.ts +0 -334
  781. package/src/provider-specs.ts +0 -432
  782. package/src/request-id.ts +0 -41
  783. package/src/routes.ts +0 -219
  784. package/src/runner-protocol.ts +0 -239
  785. package/src/runtime-state.ts +0 -140
  786. package/src/safety-policy.test.ts +0 -88
  787. package/src/safety-policy.ts +0 -258
  788. package/src/schemas/context.ts +0 -87
  789. package/src/search-globs.ts +0 -76
  790. package/src/session-names.ts +0 -44
  791. package/src/share-paths.ts +0 -68
  792. package/src/shell-regions.ts +0 -289
  793. package/src/starter.ts +0 -13
  794. package/src/state-portability.ts +0 -56
  795. package/src/terminal-protocol.ts +0 -16
  796. package/src/title.ts +0 -267
  797. package/src/tunnel-ids.ts +0 -57
  798. package/src/versions.ts +0 -48
  799. package/src/webext-links.ts +0 -90
  800. package/src/webext-protocol.ts +0 -27
  801. package/src/workspace-state.ts +0 -1096
  802. /package/dist/{hostnames.d.ts → ids/hostnames.d.ts} +0 -0
  803. /package/dist/{hostnames.js → ids/hostnames.js} +0 -0
  804. /package/dist/{session-names.d.ts → ids/session-names.d.ts} +0 -0
  805. /package/dist/{session-names.js → ids/session-names.js} +0 -0
  806. /package/dist/{share-paths.d.ts → ids/share-paths.d.ts} +0 -0
  807. /package/dist/{share-paths.js → ids/share-paths.js} +0 -0
  808. /package/dist/{agent-catalog.js → models/agent-catalog.js} +0 -0
  809. /package/dist/{agent-runtimes.d.ts → models/agent-runtimes.d.ts} +0 -0
  810. /package/dist/{agent-runtimes.js → models/agent-runtimes.js} +0 -0
  811. /package/dist/{fast-tier.js → models/fast-tier.js} +0 -0
  812. /package/dist/{model-order.d.ts → models/model-order.d.ts} +0 -0
  813. /package/dist/{model-order.js → models/model-order.js} +0 -0
  814. /package/dist/{plan-pools.js → models/plan-pools.js} +0 -0
  815. /package/dist/{prompt-complexity.d.ts → models/prompt-complexity.d.ts} +0 -0
  816. /package/dist/{prompt-complexity.js → models/prompt-complexity.js} +0 -0
  817. /package/dist/{provider-specs.d.ts → models/provider-specs.d.ts} +0 -0
  818. /package/dist/{provider-specs.js → models/provider-specs.js} +0 -0
  819. /package/dist/{approvals-execution.d.ts → policy/approvals-execution.d.ts} +0 -0
  820. /package/dist/{approvals-execution.js → policy/approvals-execution.js} +0 -0
  821. /package/dist/{capability-env.d.ts → policy/capability-env.d.ts} +0 -0
  822. /package/dist/{capability-env.js → policy/capability-env.js} +0 -0
  823. /package/dist/{capability-secrets.d.ts → policy/capability-secrets.d.ts} +0 -0
  824. /package/dist/{capability-secrets.js → policy/capability-secrets.js} +0 -0
  825. /package/dist/{command-run.js → policy/command-run.js} +0 -0
  826. /package/dist/{credential-material.d.ts → policy/credential-material.d.ts} +0 -0
  827. /package/dist/{credential-material.js → policy/credential-material.js} +0 -0
  828. /package/dist/{needs-action.d.ts → policy/needs-action.d.ts} +0 -0
  829. /package/dist/{needs-action.js → policy/needs-action.js} +0 -0
  830. /package/dist/{output-fields.d.ts → policy/output-fields.d.ts} +0 -0
  831. /package/dist/{output-fields.js → policy/output-fields.js} +0 -0
  832. /package/dist/{overlay-lint.d.ts → policy/overlay-lint.d.ts} +0 -0
  833. /package/dist/{overlay-lint.js → policy/overlay-lint.js} +0 -0
  834. /package/dist/{owner-ticket.d.ts → policy/owner-ticket.d.ts} +0 -0
  835. /package/dist/{search-globs.d.ts → policy/search-globs.d.ts} +0 -0
  836. /package/dist/{search-globs.js → policy/search-globs.js} +0 -0
  837. /package/dist/{ingress-contract.d.ts → protocol/ingress-contract.d.ts} +0 -0
  838. /package/dist/{ingress-protocol.d.ts → protocol/ingress-protocol.d.ts} +0 -0
  839. /package/dist/{ingress-protocol.js → protocol/ingress-protocol.js} +0 -0
  840. /package/dist/{listener-protocol.d.ts → protocol/listener-protocol.d.ts} +0 -0
  841. /package/dist/{peer-mcp-server.d.ts → protocol/peer-mcp-server.d.ts} +0 -0
  842. /package/dist/{peer-mcp-server.js → protocol/peer-mcp-server.js} +0 -0
  843. /package/dist/{request-id.d.ts → protocol/request-id.d.ts} +0 -0
  844. /package/dist/{request-id.js → protocol/request-id.js} +0 -0
  845. /package/dist/{routes.d.ts → protocol/routes.d.ts} +0 -0
  846. /package/dist/{routes.js → protocol/routes.js} +0 -0
  847. /package/dist/{sse.d.ts → protocol/sse.d.ts} +0 -0
  848. /package/dist/{sse.js → protocol/sse.js} +0 -0
  849. /package/dist/{terminal-protocol.js → protocol/terminal-protocol.js} +0 -0
  850. /package/dist/{webext-links.d.ts → protocol/webext-links.d.ts} +0 -0
  851. /package/dist/{webext-links.js → protocol/webext-links.js} +0 -0
  852. /package/dist/{arrival.d.ts → state/arrival.d.ts} +0 -0
  853. /package/dist/{contract-lock.d.ts → state/contract-lock.d.ts} +0 -0
  854. /package/dist/{history-state.d.ts → state/history-state.d.ts} +0 -0
  855. /package/dist/{runtime-state.d.ts → state/runtime-state.d.ts} +0 -0
  856. /package/dist/{runtime-state.js → state/runtime-state.js} +0 -0
  857. /package/dist/{starter.d.ts → state/starter.d.ts} +0 -0
  858. /package/dist/{starter.js → state/starter.js} +0 -0
  859. /package/dist/{state-portability.d.ts → state/state-portability.d.ts} +0 -0
  860. /package/dist/{state-portability.js → state/state-portability.js} +0 -0
  861. /package/dist/{versions.d.ts → state/versions.d.ts} +0 -0
  862. /package/dist/{versions.js → state/versions.js} +0 -0
  863. /package/dist/{embed.d.ts → text/embed.d.ts} +0 -0
  864. /package/dist/{embed.js → text/embed.js} +0 -0
  865. /package/dist/{mentions.d.ts → text/mentions.d.ts} +0 -0
  866. /package/dist/{mentions.js → text/mentions.js} +0 -0
  867. /package/dist/{path-refs.d.ts → text/path-refs.d.ts} +0 -0
  868. /package/dist/{path-refs.js → text/path-refs.js} +0 -0
  869. /package/dist/{shell-regions.js → text/shell-regions.js} +0 -0
  870. /package/dist/{title.d.ts → text/title.d.ts} +0 -0
  871. /package/dist/{title.js → text/title.js} +0 -0
  872. /package/src/{hostnames.test.ts → ids/hostnames.test.ts} +0 -0
  873. /package/src/{share-paths.test.ts → ids/share-paths.test.ts} +0 -0
  874. /package/src/{capability-env.ts → policy/capability-env.ts} +0 -0
  875. /package/src/{overlay-lint.test.ts → policy/overlay-lint.test.ts} +0 -0
  876. /package/src/{search-globs.test.ts → policy/search-globs.test.ts} +0 -0
  877. /package/src/{ingress-contract.test.ts → protocol/ingress-contract.test.ts} +0 -0
  878. /package/src/{peer-mcp-server.test.ts → protocol/peer-mcp-server.test.ts} +0 -0
  879. /package/src/{sse.ts → protocol/sse.ts} +0 -0
  880. /package/src/{versions.test.ts → state/versions.test.ts} +0 -0
  881. /package/src/{embed.test.ts → text/embed.test.ts} +0 -0
  882. /package/src/{mentions.test.ts → text/mentions.test.ts} +0 -0
  883. /package/src/{path-refs.test.ts → text/path-refs.test.ts} +0 -0
@@ -0,0 +1,441 @@
1
+ import { Agent, request as h1Request, type IncomingMessage, type OutgoingHttpHeaders, type ServerResponse } from "node:http";
2
+ import {
3
+ type ClientHttp2Session,
4
+ connect as h2Connect,
5
+ constants,
6
+ createServer as createH2Server,
7
+ type IncomingHttpHeaders,
8
+ type ServerHttp2Stream,
9
+ } from "node:http2";
10
+ import { type AddressInfo, createServer as createNetServer, connect as netConnect, type Socket } from "node:net";
11
+ import { Duplex } from "node:stream";
12
+
13
+ // Both ends of the ingress tunnel's h2 session, over any node Duplex, in one file: a wire format with two owners
14
+ // drifts. h2 gives multiplexing and backpressure for free; routing is per h2 stream, since one edge connection can
15
+ // interleave several sandboxes' hosts.
16
+
17
+ // Header hygiene
18
+
19
+ // Headers that must not cross a hop: h2 throws on these, and `host` is replaced by :authority.
20
+ const HOP_BY_HOP = new Set([
21
+ "connection",
22
+ "host",
23
+ "http2-settings",
24
+ "keep-alive",
25
+ "proxy-authenticate",
26
+ "proxy-authorization",
27
+ "proxy-connection",
28
+ "te",
29
+ "trailer",
30
+ "transfer-encoding",
31
+ "upgrade",
32
+ ]);
33
+
34
+ // Headers that survive a hop: pseudo-headers and HOP_BY_HOP removed, values unchanged, including array values for a
35
+ // repeated field like `set-cookie`.
36
+ const endToEnd = (headers: IncomingHttpHeaders): OutgoingHttpHeaders => {
37
+ const kept: OutgoingHttpHeaders = {};
38
+ for (const [name, value] of Object.entries(headers)) {
39
+ if (value !== undefined && !name.startsWith(":") && !HOP_BY_HOP.has(name)) {
40
+ kept[name] = value;
41
+ }
42
+ }
43
+ return kept;
44
+ };
45
+
46
+ // The upgrade envelope
47
+
48
+ // A websocket upgrade rides a CONNECT stream, where the headers an upgrade needs (Connection, Upgrade,
49
+ // Sec-WebSocket-Key) are exactly the ones h2 forbids. The whole h1 request head travels prefixed under `x-ingress-*`
50
+ // and is rebuilt verbatim on the far side, so no header is individually allowlisted.
51
+ const UPGRADE_METHOD_HEADER = "x-ingress-method";
52
+ const UPGRADE_PATH_HEADER = "x-ingress-path";
53
+ const UPGRADE_HEADER_PREFIX = "x-ingress-h-";
54
+
55
+ const upgradeEnvelope = (request: IncomingMessage, authority: string): OutgoingHttpHeaders => {
56
+ const envelope: OutgoingHttpHeaders = {
57
+ [constants.HTTP2_HEADER_METHOD]: constants.HTTP2_METHOD_CONNECT,
58
+ [constants.HTTP2_HEADER_AUTHORITY]: authority,
59
+ [UPGRADE_METHOD_HEADER]: request.method ?? "GET",
60
+ [UPGRADE_PATH_HEADER]: request.url ?? "/",
61
+ };
62
+ for (const [name, value] of Object.entries(request.headers)) {
63
+ if (value !== undefined) {
64
+ envelope[`${UPGRADE_HEADER_PREFIX}${name}`] = value;
65
+ }
66
+ }
67
+ return envelope;
68
+ };
69
+
70
+ // Rebuilds the h1 head an envelope carried; anything without the `x-ingress-h-` prefix is dropped as not part of the
71
+ // original request.
72
+ const upgradeHead = (headers: IncomingHttpHeaders): { method: string; path: string; headers: OutgoingHttpHeaders } => {
73
+ const rebuilt: OutgoingHttpHeaders = {};
74
+ for (const [name, value] of Object.entries(headers)) {
75
+ if (value !== undefined && name.startsWith(UPGRADE_HEADER_PREFIX)) {
76
+ rebuilt[name.slice(UPGRADE_HEADER_PREFIX.length)] = value;
77
+ }
78
+ }
79
+ return {
80
+ method: single(headers[UPGRADE_METHOD_HEADER]) ?? "GET",
81
+ path: single(headers[UPGRADE_PATH_HEADER]) ?? "/",
82
+ headers: rebuilt,
83
+ };
84
+ };
85
+
86
+ // First value of a header that should never repeat; a repeated one is taken as its first value.
87
+ const single = (value: string | string[] | undefined): string | undefined => (Array.isArray(value) ? value[0] : value);
88
+
89
+ // Serializes a response head verbatim from `rawHeaders` (order and spelling preserved) since it is written raw onto the
90
+ // browser's socket; latin1, since header values are opaque octets, not utf-8 text.
91
+ const serializeHead = (response: IncomingMessage, drop: ReadonlySet<string>, add: readonly string[]): Buffer => {
92
+ const lines = [`HTTP/${response.httpVersion} ${String(response.statusCode)} ${response.statusMessage ?? ""}`];
93
+ for (let index = 0; index + 1 < response.rawHeaders.length; index += 2) {
94
+ const name = response.rawHeaders[index] as string;
95
+ if (!drop.has(name.toLowerCase())) {
96
+ lines.push(`${name}: ${response.rawHeaders[index + 1] as string}`);
97
+ }
98
+ }
99
+ return Buffer.from(`${[...lines, ...add].join("\r\n")}\r\n\r\n`, "latin1");
100
+ };
101
+
102
+ // A non-101 answer on a CONNECT stream needs re-framing: `transfer-encoding` is dropped since the body is already
103
+ // de-chunked, and `connection: close` delimits it instead.
104
+ const DECLINED_UPGRADE_DROP = new Set(["connection", "keep-alive", "transfer-encoding"]);
105
+ const DECLINED_UPGRADE_ADD = ["connection: close"];
106
+ const NOTHING_DROPPED: ReadonlySet<string> = new Set();
107
+
108
+ // Session tuning
109
+
110
+ // Session memory budget shared by every stream on the tunnel; exhausting it kills the whole session, not one request.
111
+ const MAX_SESSION_MEMORY_MB = 128;
112
+
113
+ // Per-stream receive window, larger than h2's 64KB default since this session crosses the internet.
114
+ const INITIAL_WINDOW_SIZE = 1024 * 1024;
115
+
116
+ // Concurrent stream ceiling per sandbox, raised since streams here can stay open for a session's whole life.
117
+ const PEER_MAX_CONCURRENT_STREAMS = 256;
118
+
119
+ // Fixed loopback address; no stream over this tunnel can be pointed anywhere but this container's own listener.
120
+ const LOOPBACK = "127.0.0.1";
121
+
122
+ // The splice
123
+
124
+ // Pipes both directions; `pipe` carries end-of-stream each way on its own. A failure on either side destroys both,
125
+ // since `destroy` is idempotent and the two handlers won't loop.
126
+ const splice = (left: Duplex, right: Duplex): void => {
127
+ left.pipe(right);
128
+ right.pipe(left);
129
+ const fail = (): void => {
130
+ left.destroy();
131
+ right.destroy();
132
+ };
133
+ left.on("error", fail);
134
+ right.on("error", fail);
135
+ // A side that closes without finishing its writes (a reset, a dropped socket) takes the other side down too;
136
+ // `writableFinished` distinguishes that from a graceful FIN already forwarded by the pipe.
137
+ left.on("close", () => {
138
+ if (!right.writableFinished) {
139
+ right.destroy();
140
+ }
141
+ });
142
+ right.on("close", () => {
143
+ if (!left.writableFinished) {
144
+ left.destroy();
145
+ }
146
+ });
147
+ };
148
+
149
+ // The loopback bridge
150
+
151
+ // Bridges the caller's Duplex onto a real net.Socket: node's Duplex-over-h2 wrapper allows one write in flight, so a
152
+ // same-turn second write throws ERR_INTERNAL_ASSERTION and kills the process. The accepted socket is checked against
153
+ // the one just dialed.
154
+ const loopbackBridge = async (): Promise<{ session: Socket; tunnel: Socket }> => {
155
+ const listener = createNetServer();
156
+ try {
157
+ await new Promise<void>((resolve, reject) => {
158
+ listener.once("error", reject);
159
+ listener.listen(0, LOOPBACK, resolve);
160
+ });
161
+ const accepted = new Promise<Socket>((resolve, reject) => {
162
+ listener.once("connection", resolve);
163
+ listener.once("error", reject);
164
+ });
165
+ const tunnel = netConnect((listener.address() as AddressInfo).port, LOOPBACK);
166
+ await new Promise<void>((resolve, reject) => {
167
+ tunnel.once("connect", resolve);
168
+ tunnel.once("error", reject);
169
+ });
170
+ const session = await accepted;
171
+ if (session.remotePort !== tunnel.localPort) {
172
+ session.destroy();
173
+ tunnel.destroy();
174
+ throw new Error("the loopback bridge accepted a connection that was not its own");
175
+ }
176
+ // Disables Nagle: both ends are local, and frames here are already sized by h2.
177
+ session.setNoDelay(true);
178
+ tunnel.setNoDelay(true);
179
+ return { session, tunnel };
180
+ } finally {
181
+ listener.close();
182
+ }
183
+ };
184
+
185
+ // The ingress half: an h2 client over the tunnel
186
+
187
+ export interface IngressSession {
188
+ // Forwards one edge request down the tunnel. Resolves once the response is fully written; rejects on failure, and
189
+ // the caller reads `response.headersSent` to tell an untouched response (write your own 502) from one truncated
190
+ // mid-body.
191
+ readonly forwardRequest: (request: IncomingMessage, response: ServerResponse) => Promise<void>;
192
+ // Same for an upgrade, given the hijacked socket and any bytes already read past the request head. Nothing is
193
+ // written to `socket` until the far end accepts, so a rejection leaves it untouched for the caller to answer.
194
+ readonly forwardUpgrade: (request: IncomingMessage, socket: Duplex, head: Buffer) => Promise<void>;
195
+ // Ends the session and its bridge, which ends the caller's duplex and closes the WebSocket.
196
+ readonly close: () => void;
197
+ }
198
+
199
+ // Opens the ingress side of a tunnel; async since the bridge itself is. The connect URL is a placeholder — this session
200
+ // has no host of its own, every request supplies the authority it's routed by.
201
+ export const openIngressSession = async (duplex: Duplex): Promise<IngressSession> => {
202
+ const bridge = await loopbackBridge();
203
+ splice(bridge.tunnel, duplex);
204
+ const session: ClientHttp2Session = h2Connect("http://tunnel.invalid", {
205
+ createConnection: () => bridge.session,
206
+ maxSessionMemory: MAX_SESSION_MEMORY_MB,
207
+ peerMaxConcurrentStreams: PEER_MAX_CONCURRENT_STREAMS,
208
+ settings: { initialWindowSize: INITIAL_WINDOW_SIZE },
209
+ });
210
+ // Without a handler here, a dead or hostile peer raises an uncaught exception and takes every other sandbox's
211
+ // tunnel down with it. Destroying the duplex closes the WebSocket, which the reconnect loop waits on.
212
+ session.on("error", () => duplex.destroy());
213
+ session.on("close", () => duplex.destroy());
214
+
215
+ // Authority to route the stream by. The ingress already refuses any Host that doesn't own a sandbox, so a request
216
+ // with no Host here is a caller bug, not a routing decision.
217
+ const authorityOf = (request: IncomingMessage): string => {
218
+ const host = request.headers.host;
219
+ if (host === undefined || host === "") {
220
+ throw new Error("an ingress request is routed by its Host header, and this one has none");
221
+ }
222
+ return host;
223
+ };
224
+
225
+ const forwardRequest = (request: IncomingMessage, response: ServerResponse): Promise<void> =>
226
+ new Promise<void>((resolve, reject) => {
227
+ const authority = authorityOf(request);
228
+ // `endStream: false` for every method, not only ones that may carry a body: the request is piped
229
+ // regardless, and an already-ended GET closes the stream with an empty frame.
230
+ const stream = session.request(
231
+ {
232
+ [constants.HTTP2_HEADER_METHOD]: request.method ?? "GET",
233
+ [constants.HTTP2_HEADER_PATH]: request.url ?? "/",
234
+ [constants.HTTP2_HEADER_AUTHORITY]: authority,
235
+ // The edge is HTTPS-only, so this is what the browser used; nothing here routes on it.
236
+ [constants.HTTP2_HEADER_SCHEME]: "https",
237
+ ...endToEnd(request.headers),
238
+ },
239
+ { endStream: false },
240
+ );
241
+ request.pipe(stream);
242
+
243
+ // The browser giving up must reach the daemon: without this, a closed tab leaves the h2 stream, the
244
+ // daemon's own request, and any long-lived generator (SSE) running for nobody. RST_STREAM(CANCEL) unwinds
245
+ // all three.
246
+ response.on("close", () => {
247
+ if (!response.writableFinished) {
248
+ stream.close(constants.NGHTTP2_CANCEL);
249
+ }
250
+ });
251
+
252
+ stream.on("response", (headers) => {
253
+ if (response.destroyed) {
254
+ stream.close(constants.NGHTTP2_CANCEL);
255
+ return;
256
+ }
257
+ response.writeHead(Number(headers[constants.HTTP2_HEADER_STATUS] ?? 502), endToEnd(headers));
258
+ stream.pipe(response);
259
+ });
260
+ stream.on("error", reject);
261
+ // The response resolves on `finish`, once node has flushed it to the browser, not merely when the h2 stream
262
+ // closes.
263
+ response.on("finish", resolve);
264
+ stream.on("close", () => {
265
+ if (!response.writableEnded) {
266
+ reject(new Error("the tunnel closed the stream before the response was complete"));
267
+ }
268
+ });
269
+ });
270
+
271
+ const forwardUpgrade = (request: IncomingMessage, socket: Duplex, head: Buffer): Promise<void> =>
272
+ new Promise<void>((resolve, reject) => {
273
+ const stream = session.request(upgradeEnvelope(request, authorityOf(request)), { endStream: false });
274
+ stream.on("error", reject);
275
+ stream.once("response", (headers) => {
276
+ const status = Number(headers[constants.HTTP2_HEADER_STATUS]);
277
+ if (status !== constants.HTTP_STATUS_OK) {
278
+ // The far end refused the upgrade; nothing has reached the browser yet, so the caller still owns
279
+ // the socket.
280
+ stream.close(constants.NGHTTP2_CANCEL);
281
+ reject(new Error(`the tunnel refused an upgrade with :status ${String(status)}`));
282
+ return;
283
+ }
284
+ // Bytes the client already sent past its request head; dropped, the handshake completes and then hangs
285
+ // on a frame nobody has.
286
+ if (head.length > 0) {
287
+ stream.write(head);
288
+ }
289
+ splice(stream, socket);
290
+ resolve();
291
+ });
292
+ });
293
+
294
+ return {
295
+ forwardRequest,
296
+ forwardUpgrade,
297
+ // Graceful GOAWAY first, then the bridge's far half, which the session itself knows nothing about.
298
+ close: () => {
299
+ session.close(() => bridge.tunnel.destroy());
300
+ bridge.tunnel.end();
301
+ },
302
+ };
303
+ };
304
+
305
+ // The daemon half: an h2 server over the tunnel, onto the loopback listener
306
+
307
+ export interface ServeIngressSessionOptions {
308
+ // The daemon's own listener; every stream lands there as a plain HTTP/1.1 request or upgrade.
309
+ readonly targetPort: number;
310
+ }
311
+
312
+ export interface IngressSessionServer {
313
+ // Sends GOAWAY over the bridge, which ends the caller's duplex once it's done writing the shutdown frame. The
314
+ // WebSocket itself belongs to whoever dialed it.
315
+ readonly close: () => void;
316
+ }
317
+
318
+ // One h2 server per session, bound to nothing; it exists only to be handed a connection. The h1 hop to the loopback
319
+ // listener runs over a keep-alive agent, so steady traffic reuses sockets; the upgrade path does not.
320
+ export const serveIngressSession = async (duplex: Duplex, options: ServeIngressSessionOptions): Promise<IngressSessionServer> => {
321
+ const bridge = await loopbackBridge();
322
+ splice(bridge.tunnel, duplex);
323
+ const agent = new Agent({ keepAlive: true, maxSockets: PEER_MAX_CONCURRENT_STREAMS });
324
+ const server = createH2Server({
325
+ maxSessionMemory: MAX_SESSION_MEMORY_MB,
326
+ settings: { initialWindowSize: INITIAL_WINDOW_SIZE },
327
+ });
328
+
329
+ // A failed session is news for the reconnect loop, not an uncaught exception that takes the whole daemon down.
330
+ // Destroying the duplex closes the WebSocket the loop waits on; `clientError` should never fire but isn't worth
331
+ // crashing over either.
332
+ server.on("sessionError", () => duplex.destroy());
333
+ server.on("clientError", () => duplex.destroy());
334
+ server.on("error", () => duplex.destroy());
335
+
336
+ const forwardToLoopback = (stream: ServerHttp2Stream, headers: IncomingHttpHeaders): void => {
337
+ const local = h1Request({
338
+ host: LOOPBACK,
339
+ port: options.targetPort,
340
+ method: single(headers[constants.HTTP2_HEADER_METHOD]) ?? "GET",
341
+ path: single(headers[constants.HTTP2_HEADER_PATH]) ?? "/",
342
+ // The Host the request was made to, restored where an h1 server reads it; this alone tells a preview, a
343
+ // port and the daemon apart.
344
+ headers: { host: single(headers[constants.HTTP2_HEADER_AUTHORITY]) ?? "", ...endToEnd(headers) },
345
+ agent,
346
+ });
347
+ stream.pipe(local);
348
+ local.on("response", (response) => {
349
+ stream.respond({ [constants.HTTP2_HEADER_STATUS]: response.statusCode ?? 502, ...endToEnd(response.headers) });
350
+ response.pipe(stream);
351
+ });
352
+ // The listener isn't answering; closed with an error code rather than a 502 of our own, since the ingress owns
353
+ // what an unreachable sandbox looks like.
354
+ local.on("error", () => stream.close(constants.NGHTTP2_INTERNAL_ERROR));
355
+ stream.on("error", () => local.destroy());
356
+ // The edge cancelled (RST_STREAM); stop generating a response nobody reads. `aborted` is the only event that
357
+ // means this — on a reset, node fires `aborted` before `finish` and `close`, so a
358
+ // `writableEnded`/`writableFinished` guard there would miss it.
359
+ stream.on("aborted", () => local.destroy());
360
+ };
361
+
362
+ const spliceUpgrade = (stream: ServerHttp2Stream, headers: IncomingHttpHeaders): void => {
363
+ const head = upgradeHead(headers);
364
+ // `agent: false`: an upgraded connection stops being HTTP once accepted and can never return to the keep-alive
365
+ // pool the request path above uses.
366
+ const local = h1Request({ host: LOOPBACK, port: options.targetPort, method: head.method, path: head.path, headers: head.headers, agent: false });
367
+ local.on("upgrade", (response, socket, first) => {
368
+ stream.respond({ [constants.HTTP2_HEADER_STATUS]: constants.HTTP_STATUS_OK });
369
+ // Response head written verbatim (see serializeHead), then any bytes already sent past it, then the pipe.
370
+ stream.write(serializeHead(response, NOTHING_DROPPED, []));
371
+ if (first.length > 0) {
372
+ stream.write(first);
373
+ }
374
+ splice(stream, socket);
375
+ });
376
+ // The local server declined to upgrade; its answer goes to the browser with framing that matches the already
377
+ // de-chunked body.
378
+ local.on("response", (response) => {
379
+ stream.respond({ [constants.HTTP2_HEADER_STATUS]: constants.HTTP_STATUS_OK });
380
+ stream.write(serializeHead(response, DECLINED_UPGRADE_DROP, DECLINED_UPGRADE_ADD));
381
+ response.pipe(stream);
382
+ });
383
+ local.on("error", () => stream.close(constants.NGHTTP2_CONNECT_ERROR));
384
+ // An upgrade request carries no body; the client is waiting on the handshake before it says anything else.
385
+ local.end();
386
+ };
387
+
388
+ server.on("stream", (stream, headers) => {
389
+ if (headers[constants.HTTP2_HEADER_METHOD] === constants.HTTP2_METHOD_CONNECT) {
390
+ spliceUpgrade(stream, headers);
391
+ return;
392
+ }
393
+ forwardToLoopback(stream, headers);
394
+ });
395
+
396
+ // Creates a server-side session without a listener: the server never binds, it is simply handed a connection.
397
+ server.emit("connection", bridge.session);
398
+
399
+ return {
400
+ close: () => {
401
+ agent.destroy();
402
+ server.close();
403
+ bridge.tunnel.end();
404
+ },
405
+ };
406
+ };
407
+
408
+ // Reimplements `ws`'s createWebSocketStream, which Bun does not support, so both runtimes get the same Duplex.
409
+ // Preserves byte safety: the write callback fires only once the socket has taken the frame, and a closed socket ends
410
+ // the readable side with `push(null)`.
411
+ export interface TunnelWebSocket {
412
+ readonly send: (data: Buffer, options: { binary: boolean }, callback: (error?: Error) => void) => void;
413
+ readonly close: () => void;
414
+ readonly on: {
415
+ (event: `message`, listener: (data: unknown) => void): unknown;
416
+ (event: `close`, listener: () => void): unknown;
417
+ (event: `error`, listener: (error: Error) => void): unknown;
418
+ };
419
+ }
420
+
421
+ export const webSocketDuplex = (socket: TunnelWebSocket): Duplex => {
422
+ const duplex = new Duplex({
423
+ read: () => {},
424
+ write: (chunk: Buffer, _encoding, callback) => {
425
+ socket.send(chunk, { binary: true }, (error) => callback(error ?? null));
426
+ },
427
+ // Half-closing a WebSocket isn't possible; ending the writable side closes the socket outright.
428
+ final: (callback) => {
429
+ socket.close();
430
+ callback();
431
+ },
432
+ });
433
+ // `message` carries a Buffer for binary frames; a stray text frame arrives as a string and is coerced rather than
434
+ // dropped.
435
+ socket.on(`message`, (data: unknown) => {
436
+ duplex.push(Buffer.isBuffer(data) ? data : Buffer.from(data as string));
437
+ });
438
+ socket.on(`close`, () => duplex.push(null));
439
+ socket.on(`error`, (error: Error) => duplex.destroy(error));
440
+ return duplex;
441
+ };
@@ -0,0 +1,75 @@
1
+ import { z } from "zod";
2
+ import { ActivityStatusSchema } from "../schemas/activity.js";
3
+
4
+ // Wire between the daemon and an extension's realtime-listener gateway (ext-discord, ext-slack, ext-telegram,
5
+ // ext-whatsapp, ext-imap): the four /listeners/:provider routes (state, dispatch, failure, status). Shared here so both
6
+ // ends compile against one declaration.
7
+
8
+ // One normalized inbound event: the JSON body a realtime source POSTs to /listeners/<provider>/dispatch. A zod schema
9
+ // since it's parsed from untrusted gateway input; `provider` and `type` are open strings, not a core enum.
10
+ export const ListenerMessageSchema = z.object({
11
+ provider: z.string().min(1),
12
+ type: z.string().min(1),
13
+ id: z.string(),
14
+ channelId: z.string(),
15
+ author: z.object({ id: z.string(), name: z.string() }),
16
+ content: z.string(),
17
+ // Discord only: the message @mentions or replies to one of our bots; voice events never set it.
18
+ mentioned: z.boolean().optional(),
19
+ // CI pipeline event: the ref it ran on. Top-level, not in `extra`, since the dispatcher matches triggers on it.
20
+ branch: z.string().optional(),
21
+ // Prior channel messages fetched when tagged; top-level so it reaches the model but skips the activity feed.
22
+ history: z
23
+ .array(
24
+ z.object({
25
+ author: z.object({ id: z.string(), name: z.string() }),
26
+ content: z.string(),
27
+ timestamp: z.string(),
28
+ self: z.boolean().optional(),
29
+ }),
30
+ )
31
+ .optional(),
32
+ timestamp: z.string(),
33
+ // Provider-specific fields:
34
+ // - discord message: guildId, attachments
35
+ // - voice_utterance: path
36
+ // - voice_transcript: path, participants, durationSeconds
37
+ extra: z.record(z.string(), z.unknown()).optional(),
38
+ });
39
+ export type ListenerMessage = z.infer<typeof ListenerMessageSchema>;
40
+
41
+ // One ndjson frame of a /listeners/<provider>/dispatch?stream=1 response: a text delta, a failure sentence, or a
42
+ // terminal marker. A type, not a schema, since only the daemon produces these.
43
+ export interface ListenerDispatchFrame {
44
+ readonly automationId: string;
45
+ readonly delta?: string;
46
+ // The turn's failure, forwarded verbatim since a gateway delivers it into the owner's own channel.
47
+ readonly failed?: string;
48
+ readonly end?: boolean;
49
+ }
50
+
51
+ // Where a device-linking ceremony stands (whatsapp), reported per status tick; every state here means not yet paired.
52
+ // `since` stamps the current code's age, since WhatsApp reissues a fresh one on each reopen.
53
+ export const ListenerPairingSchema = z.object({
54
+ // waiting: socket up, no code yet (or the last one died with its socket)
55
+ // code: `code` is live, type it on the phone
56
+ // failed: `detail` says what WhatsApp refused
57
+ state: z.enum(["waiting", "code", "failed"]),
58
+ code: z.string().optional(),
59
+ detail: z.string().optional(),
60
+ since: z.number().optional(),
61
+ });
62
+ export type ListenerPairing = z.infer<typeof ListenerPairingSchema>;
63
+
64
+ // Push-based status: a gateway POSTs its connection/voice snapshot to /listeners/<provider>/status, since the daemon
65
+ // holds no provider connection to probe itself. Extends ActivityStatus with whisper's voice-pending flag and each
66
+ // unpaired capability's pairing ceremony by id.
67
+ export const ListenerStatusSchema = ActivityStatusSchema.extend({
68
+ whisperReady: z.boolean().optional(),
69
+ pairing: z.record(z.string(), ListenerPairingSchema).optional(),
70
+ });
71
+ export type ListenerStatus = z.infer<typeof ListenerStatusSchema>;
72
+
73
+ // A connection's place in the reconcile lifecycle: `idle` is up but intentionally holding nothing (no enabled
74
+ // automation), `pairing` is up but waiting on an uncompleted credential ceremony; the rest are the connect loop.
75
+ export type ListenerGatewayPhase = "idle" | "ready" | "pairing" | "connecting" | "disconnected";
@@ -11,7 +11,7 @@ class FakeSocket implements SocketLike {
11
11
  closed: { readonly code: number | undefined; readonly reason: string | undefined } | undefined;
12
12
  private readonly listeners = new Map<string, Set<(event: { readonly code?: number }) => void>>();
13
13
 
14
- addEventListener(type: "open" | "close" | "error", listener: (event: { readonly code?: number }) => void): void {
14
+ addEventListener(type: "open" | "close" | "error" | "message", listener: (event: { readonly code?: number }) => void): void {
15
15
  const set = this.listeners.get(type) ?? new Set();
16
16
  set.add(listener);
17
17
  this.listeners.set(type, set);
@@ -31,6 +31,10 @@ class FakeSocket implements SocketLike {
31
31
  this.readyState = 3;
32
32
  this.emit("close", code);
33
33
  }
34
+ // A frame from the sandbox: the heartbeat, or any call. Only that one arrived matters to the loop.
35
+ says(): void {
36
+ this.emit("message");
37
+ }
34
38
  private emit(type: string, code?: number): void {
35
39
  for (const listener of this.listeners.get(type) ?? []) {
36
40
  listener(code === undefined ? {} : { code });
@@ -38,6 +42,9 @@ class FakeSocket implements SocketLike {
38
42
  }
39
43
  }
40
44
 
45
+ // This door's silence deadline, named so the assertions can read it off the same number the loop is given.
46
+ const SILENCE_MS = 30_000;
47
+
41
48
  // A ladder that answers with a fixed delay and records what it was told, so the test can read the held time.
42
49
  const ladder = (delay = 1_000) => {
43
50
  const held: number[] = [];
@@ -64,6 +71,7 @@ const dialling = () => {
64
71
  hello: () => ({ type: "hello", token: "iht_test", version: "1.0.0" }),
65
72
  attach: (socket) => void attached.push(socket),
66
73
  backoff: ladder(),
74
+ silenceMs: SILENCE_MS,
67
75
  log: (message) => void said.push(message),
68
76
  revoked,
69
77
  });
@@ -105,6 +113,46 @@ test("a drop redials on the ladder, telling it how long the socket held", async
105
113
  }
106
114
  });
107
115
 
116
+ /* THE DROP NOBODY REPORTS, which is the one that used to last for days: a far end that is gone while the socket
117
+ * stays open — a sandbox container recreated behind a port relay that outlived it, a NAT that forgot the flow, a
118
+ * laptop's wifi suspended mid-session. Note what this test never calls: `drops`. Nothing closes, nothing errors,
119
+ * and the loop has to reach the conclusion on its own or hold a dead link forever. */
120
+ test("a socket that goes silent is abandoned and redialled, though no close ever arrives", async () => {
121
+ vi.useFakeTimers();
122
+ try {
123
+ const { link, sockets, said } = dialling();
124
+ await vi.waitFor(() => expect(sockets).toHaveLength(1));
125
+ sockets[0]?.opens();
126
+
127
+ // A frame inside every window holds the link: this is the sandbox's heartbeat, three beats of it.
128
+ for (let beat = 0; beat < 3; beat += 1) {
129
+ await vi.advanceTimersByTimeAsync(SILENCE_MS - 1_000);
130
+ sockets[0]?.says();
131
+ }
132
+ expect(link.state()).toBe("open");
133
+ expect(sockets).toHaveLength(1);
134
+
135
+ // Then the beats stop, and nothing else happens: no close, no error.
136
+ await vi.advanceTimersByTimeAsync(SILENCE_MS);
137
+ expect(said.at(-1)).toBe(`nothing heard for ${SILENCE_MS / 1_000}s; reconnecting in 1s`);
138
+ expect(sockets[0]?.closed).toEqual({ code: 1000, reason: "no heartbeat" });
139
+ expect(link.state()).toBe("connecting");
140
+
141
+ await vi.advanceTimersByTimeAsync(1_000);
142
+ await vi.waitFor(() => expect(sockets).toHaveLength(2));
143
+
144
+ // The close an abandoned socket may still emit minutes later must not put a second loop on the link.
145
+ sockets[0]?.drops(1006);
146
+ await vi.advanceTimersByTimeAsync(10_000);
147
+ expect(sockets).toHaveLength(2);
148
+
149
+ link.stop();
150
+ await link.done;
151
+ } finally {
152
+ vi.useRealTimers();
153
+ }
154
+ });
155
+
108
156
  test("a refused enrollment (1008) is never retried and is reported once", async () => {
109
157
  vi.useFakeTimers();
110
158
  try {
@@ -142,6 +190,7 @@ test("a stop during resolution opens nothing, and a socket a slow resolver still
142
190
  hello: () => ({}),
143
191
  attach: () => undefined,
144
192
  backoff: ladder(),
193
+ silenceMs: SILENCE_MS,
145
194
  log: () => undefined,
146
195
  revoked: () => undefined,
147
196
  });
@@ -166,6 +215,7 @@ test("a stop during resolution opens nothing, and a socket a slow resolver still
166
215
  hello: () => ({}),
167
216
  attach: () => undefined,
168
217
  backoff: ladder(),
218
+ silenceMs: SILENCE_MS,
169
219
  log: () => undefined,
170
220
  revoked: () => undefined,
171
221
  });
@@ -191,6 +241,7 @@ test("a pairing that is gone by the next attempt ends the loop rather than diall
191
241
  hello: () => ({}),
192
242
  attach: () => undefined,
193
243
  backoff: ladder(0),
244
+ silenceMs: SILENCE_MS,
194
245
  log: () => undefined,
195
246
  revoked: () => undefined,
196
247
  });