@intentic/sandbox-contract 1.231.0 → 1.233.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 (500) hide show
  1. package/README.md +13 -2
  2. package/dist/agent-catalog.d.ts +2 -1
  3. package/dist/agent-catalog.d.ts.map +1 -1
  4. package/dist/agent-catalog.js +1 -1
  5. package/dist/agent-catalog.js.map +1 -1
  6. package/dist/chores/chores.d.ts +1 -1
  7. package/dist/chores/chores.d.ts.map +1 -1
  8. package/dist/chores/probes.d.ts +1 -1
  9. package/dist/chores/probes.d.ts.map +1 -1
  10. package/dist/chores/stack.d.ts.map +1 -1
  11. package/dist/chores/stack.js +2 -1
  12. package/dist/chores/stack.js.map +1 -1
  13. package/dist/chores/verdict.d.ts +1 -1
  14. package/dist/chores/verdict.d.ts.map +1 -1
  15. package/dist/command-classes.d.ts +14 -0
  16. package/dist/command-classes.d.ts.map +1 -0
  17. package/dist/command-classes.js +168 -0
  18. package/dist/command-classes.js.map +1 -0
  19. package/dist/contracts/activity.contract.js +1 -1
  20. package/dist/contracts/activity.contract.js.map +1 -1
  21. package/dist/contracts/agent.contract.d.ts +51 -2
  22. package/dist/contracts/agent.contract.d.ts.map +1 -1
  23. package/dist/contracts/agent.contract.js +13 -1
  24. package/dist/contracts/agent.contract.js.map +1 -1
  25. package/dist/contracts/agents.contract.d.ts +24 -0
  26. package/dist/contracts/agents.contract.d.ts.map +1 -1
  27. package/dist/contracts/agents.contract.js +5 -1
  28. package/dist/contracts/agents.contract.js.map +1 -1
  29. package/dist/contracts/automations.contract.js +2 -1
  30. package/dist/contracts/automations.contract.js.map +1 -1
  31. package/dist/contracts/capabilities.contract.d.ts +63 -0
  32. package/dist/contracts/capabilities.contract.d.ts.map +1 -1
  33. package/dist/contracts/capabilities.contract.js +3 -1
  34. package/dist/contracts/capabilities.contract.js.map +1 -1
  35. package/dist/contracts/chores.contract.d.ts.map +1 -1
  36. package/dist/contracts/chores.contract.js +2 -1
  37. package/dist/contracts/chores.contract.js.map +1 -1
  38. package/dist/contracts/ci.contract.js +2 -1
  39. package/dist/contracts/ci.contract.js.map +1 -1
  40. package/dist/contracts/claude.contract.js +2 -1
  41. package/dist/contracts/claude.contract.js.map +1 -1
  42. package/dist/contracts/cursor.contract.js +2 -1
  43. package/dist/contracts/cursor.contract.js.map +1 -1
  44. package/dist/contracts/drafts.contract.d.ts.map +1 -1
  45. package/dist/contracts/drafts.contract.js +2 -1
  46. package/dist/contracts/drafts.contract.js.map +1 -1
  47. package/dist/contracts/endpoints.contract.d.ts.map +1 -1
  48. package/dist/contracts/endpoints.contract.js +2 -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 +2 -1
  52. package/dist/contracts/exit.contract.js.map +1 -1
  53. package/dist/contracts/extensions.contract.d.ts +42 -0
  54. package/dist/contracts/extensions.contract.d.ts.map +1 -1
  55. package/dist/contracts/extensions.contract.js +4 -1
  56. package/dist/contracts/extensions.contract.js.map +1 -1
  57. package/dist/contracts/git.contract.d.ts.map +1 -1
  58. package/dist/contracts/git.contract.js +4 -1
  59. package/dist/contracts/git.contract.js.map +1 -1
  60. package/dist/contracts/grok.contract.d.ts.map +1 -1
  61. package/dist/contracts/grok.contract.js +2 -1
  62. package/dist/contracts/grok.contract.js.map +1 -1
  63. package/dist/contracts/history.contract.d.ts.map +1 -1
  64. package/dist/contracts/history.contract.js +2 -1
  65. package/dist/contracts/history.contract.js.map +1 -1
  66. package/dist/contracts/host.contract.d.ts +11 -0
  67. package/dist/contracts/host.contract.d.ts.map +1 -1
  68. package/dist/contracts/host.contract.js +4 -1
  69. package/dist/contracts/host.contract.js.map +1 -1
  70. package/dist/contracts/intentic.contract.d.ts.map +1 -1
  71. package/dist/contracts/intentic.contract.js +2 -1
  72. package/dist/contracts/intentic.contract.js.map +1 -1
  73. package/dist/contracts/inventory.contract.js +1 -1
  74. package/dist/contracts/inventory.contract.js.map +1 -1
  75. package/dist/contracts/logs.contract.d.ts.map +1 -1
  76. package/dist/contracts/logs.contract.js +1 -1
  77. package/dist/contracts/logs.contract.js.map +1 -1
  78. package/dist/contracts/loops.contract.js +2 -1
  79. package/dist/contracts/loops.contract.js.map +1 -1
  80. package/dist/contracts/panels.contract.d.ts.map +1 -1
  81. package/dist/contracts/panels.contract.js +2 -1
  82. package/dist/contracts/panels.contract.js.map +1 -1
  83. package/dist/contracts/personas.contract.js +2 -1
  84. package/dist/contracts/personas.contract.js.map +1 -1
  85. package/dist/contracts/ports.contract.d.ts.map +1 -1
  86. package/dist/contracts/ports.contract.js +2 -1
  87. package/dist/contracts/ports.contract.js.map +1 -1
  88. package/dist/contracts/prepush.contract.d.ts.map +1 -1
  89. package/dist/contracts/prepush.contract.js +2 -1
  90. package/dist/contracts/prepush.contract.js.map +1 -1
  91. package/dist/contracts/providers.contract.d.ts.map +1 -1
  92. package/dist/contracts/providers.contract.js +2 -1
  93. package/dist/contracts/providers.contract.js.map +1 -1
  94. package/dist/contracts/public.contract.d.ts.map +1 -1
  95. package/dist/contracts/public.contract.js +2 -1
  96. package/dist/contracts/public.contract.js.map +1 -1
  97. package/dist/contracts/push.contract.d.ts.map +1 -1
  98. package/dist/contracts/push.contract.js +2 -1
  99. package/dist/contracts/push.contract.js.map +1 -1
  100. package/dist/contracts/runner.contract.d.ts +151 -43
  101. package/dist/contracts/runner.contract.d.ts.map +1 -1
  102. package/dist/contracts/runner.contract.js +14 -1
  103. package/dist/contracts/runner.contract.js.map +1 -1
  104. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  105. package/dist/contracts/secrets.contract.js +2 -1
  106. package/dist/contracts/secrets.contract.js.map +1 -1
  107. package/dist/contracts/sessions.contract.js +1 -1
  108. package/dist/contracts/sessions.contract.js.map +1 -1
  109. package/dist/contracts/settings.contract.d.ts +20 -0
  110. package/dist/contracts/settings.contract.d.ts.map +1 -1
  111. package/dist/contracts/settings.contract.js +3 -1
  112. package/dist/contracts/settings.contract.js.map +1 -1
  113. package/dist/contracts/share.contract.d.ts.map +1 -1
  114. package/dist/contracts/share.contract.js +2 -1
  115. package/dist/contracts/share.contract.js.map +1 -1
  116. package/dist/contracts/skills.contract.d.ts.map +1 -1
  117. package/dist/contracts/skills.contract.js +2 -1
  118. package/dist/contracts/skills.contract.js.map +1 -1
  119. package/dist/contracts/system.contract.d.ts +35 -16
  120. package/dist/contracts/system.contract.d.ts.map +1 -1
  121. package/dist/contracts/system.contract.js +6 -1
  122. package/dist/contracts/system.contract.js.map +1 -1
  123. package/dist/contracts/translator.contract.d.ts.map +1 -1
  124. package/dist/contracts/translator.contract.js +4 -1
  125. package/dist/contracts/translator.contract.js.map +1 -1
  126. package/dist/contracts/usage.contract.js +1 -1
  127. package/dist/contracts/usage.contract.js.map +1 -1
  128. package/dist/contracts/vpn.contract.d.ts.map +1 -1
  129. package/dist/contracts/vpn.contract.js +2 -1
  130. package/dist/contracts/vpn.contract.js.map +1 -1
  131. package/dist/contracts/webext.contract.d.ts +45 -0
  132. package/dist/contracts/webext.contract.d.ts.map +1 -0
  133. package/dist/contracts/webext.contract.js +12 -0
  134. package/dist/contracts/webext.contract.js.map +1 -0
  135. package/dist/contracts/workflows.contract.js +2 -1
  136. package/dist/contracts/workflows.contract.js.map +1 -1
  137. package/dist/contracts/workspace.contract.d.ts +2 -2
  138. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  139. package/dist/contracts/workspace.contract.js +7 -1
  140. package/dist/contracts/workspace.contract.js.map +1 -1
  141. package/dist/definition-action.d.ts +7 -0
  142. package/dist/definition-action.d.ts.map +1 -0
  143. package/dist/definition-action.js +3 -0
  144. package/dist/definition-action.js.map +1 -0
  145. package/dist/definition.d.ts +1064 -0
  146. package/dist/definition.d.ts.map +1 -0
  147. package/dist/definition.js +93 -0
  148. package/dist/definition.js.map +1 -0
  149. package/dist/events.d.ts +109 -0
  150. package/dist/events.d.ts.map +1 -1
  151. package/dist/events.js +30 -1
  152. package/dist/events.js.map +1 -1
  153. package/dist/fast-tier.d.ts +1 -1
  154. package/dist/fast-tier.d.ts.map +1 -1
  155. package/dist/history-state.d.ts.map +1 -1
  156. package/dist/history-state.js +1 -0
  157. package/dist/history-state.js.map +1 -1
  158. package/dist/index.d.ts +371 -103
  159. package/dist/index.d.ts.map +1 -1
  160. package/dist/index.js +52 -1
  161. package/dist/index.js.map +1 -1
  162. package/dist/listener-protocol.js +1 -1
  163. package/dist/listener-protocol.js.map +1 -1
  164. package/dist/quick-model.d.ts +1 -1
  165. package/dist/quick-model.d.ts.map +1 -1
  166. package/dist/runner-protocol.d.ts +18 -0
  167. package/dist/runner-protocol.d.ts.map +1 -1
  168. package/dist/runner-protocol.js +8 -4
  169. package/dist/runner-protocol.js.map +1 -1
  170. package/dist/schemas/activity.d.ts +112 -0
  171. package/dist/schemas/activity.d.ts.map +1 -0
  172. package/dist/schemas/activity.js +70 -0
  173. package/dist/schemas/activity.js.map +1 -0
  174. package/dist/schemas/agent.d.ts +189 -0
  175. package/dist/schemas/agent.d.ts.map +1 -0
  176. package/dist/schemas/agent.js +170 -0
  177. package/dist/schemas/agent.js.map +1 -0
  178. package/dist/schemas/agents.d.ts +690 -0
  179. package/dist/schemas/agents.d.ts.map +1 -0
  180. package/dist/schemas/agents.js +314 -0
  181. package/dist/schemas/agents.js.map +1 -0
  182. package/dist/schemas/automations.d.ts +736 -0
  183. package/dist/schemas/automations.d.ts.map +1 -0
  184. package/dist/schemas/automations.js +218 -0
  185. package/dist/schemas/automations.js.map +1 -0
  186. package/dist/schemas/capabilities.d.ts +753 -0
  187. package/dist/schemas/capabilities.d.ts.map +1 -0
  188. package/dist/schemas/capabilities.js +269 -0
  189. package/dist/schemas/capabilities.js.map +1 -0
  190. package/dist/schemas/ci.d.ts +179 -0
  191. package/dist/schemas/ci.d.ts.map +1 -0
  192. package/dist/schemas/ci.js +99 -0
  193. package/dist/schemas/ci.js.map +1 -0
  194. package/dist/schemas/claude-gate.d.ts +13 -0
  195. package/dist/schemas/claude-gate.d.ts.map +1 -0
  196. package/dist/schemas/claude-gate.js +8 -0
  197. package/dist/schemas/claude-gate.js.map +1 -0
  198. package/dist/schemas/codebase-health.d.ts +56 -0
  199. package/dist/schemas/codebase-health.d.ts.map +1 -0
  200. package/dist/schemas/codebase-health.js +43 -0
  201. package/dist/schemas/codebase-health.js.map +1 -0
  202. package/dist/schemas/computers.d.ts +386 -0
  203. package/dist/schemas/computers.d.ts.map +1 -0
  204. package/dist/schemas/computers.js +107 -0
  205. package/dist/schemas/computers.js.map +1 -0
  206. package/dist/schemas/drafts.d.ts +84 -0
  207. package/dist/schemas/drafts.d.ts.map +1 -0
  208. package/dist/schemas/drafts.js +44 -0
  209. package/dist/schemas/drafts.js.map +1 -0
  210. package/dist/schemas/environment.d.ts +349 -0
  211. package/dist/schemas/environment.d.ts.map +1 -0
  212. package/dist/schemas/environment.js +111 -0
  213. package/dist/schemas/environment.js.map +1 -0
  214. package/dist/schemas/exit.d.ts +151 -0
  215. package/dist/schemas/exit.d.ts.map +1 -0
  216. package/dist/schemas/exit.js +115 -0
  217. package/dist/schemas/exit.js.map +1 -0
  218. package/dist/schemas/extension-updates.d.ts +1014 -0
  219. package/dist/schemas/extension-updates.d.ts.map +1 -0
  220. package/dist/schemas/extension-updates.js +197 -0
  221. package/dist/schemas/extension-updates.js.map +1 -0
  222. package/dist/schemas/fast-mode.d.ts +8 -0
  223. package/dist/schemas/fast-mode.d.ts.map +1 -0
  224. package/dist/schemas/fast-mode.js +3 -0
  225. package/dist/schemas/fast-mode.js.map +1 -0
  226. package/dist/schemas/git-history.d.ts +238 -0
  227. package/dist/schemas/git-history.d.ts.map +1 -0
  228. package/dist/schemas/git-history.js +152 -0
  229. package/dist/schemas/git-history.js.map +1 -0
  230. package/dist/schemas/git.d.ts +471 -0
  231. package/dist/schemas/git.d.ts.map +1 -0
  232. package/dist/schemas/git.js +204 -0
  233. package/dist/schemas/git.js.map +1 -0
  234. package/dist/schemas/history.d.ts +100 -0
  235. package/dist/schemas/history.d.ts.map +1 -0
  236. package/dist/schemas/history.js +54 -0
  237. package/dist/schemas/history.js.map +1 -0
  238. package/dist/schemas/hosts.d.ts +41 -0
  239. package/dist/schemas/hosts.d.ts.map +1 -0
  240. package/dist/schemas/hosts.js +18 -0
  241. package/dist/schemas/hosts.js.map +1 -0
  242. package/dist/schemas/intentic.d.ts +5 -0
  243. package/dist/schemas/intentic.d.ts.map +1 -0
  244. package/dist/schemas/intentic.js +3 -0
  245. package/dist/schemas/intentic.js.map +1 -0
  246. package/dist/schemas/internal.d.ts +8 -0
  247. package/dist/schemas/internal.d.ts.map +1 -0
  248. package/dist/schemas/internal.js +12 -0
  249. package/dist/schemas/internal.js.map +1 -0
  250. package/dist/schemas/inventory.d.ts +171 -0
  251. package/dist/schemas/inventory.d.ts.map +1 -0
  252. package/dist/schemas/inventory.js +51 -0
  253. package/dist/schemas/inventory.js.map +1 -0
  254. package/dist/schemas/logs.d.ts +67 -0
  255. package/dist/schemas/logs.d.ts.map +1 -0
  256. package/dist/schemas/logs.js +54 -0
  257. package/dist/schemas/logs.js.map +1 -0
  258. package/dist/schemas/loops.d.ts +415 -0
  259. package/dist/schemas/loops.d.ts.map +1 -0
  260. package/dist/schemas/loops.js +188 -0
  261. package/dist/schemas/loops.js.map +1 -0
  262. package/dist/schemas/maintenance.d.ts +557 -0
  263. package/dist/schemas/maintenance.d.ts.map +1 -0
  264. package/dist/schemas/maintenance.js +201 -0
  265. package/dist/schemas/maintenance.js.map +1 -0
  266. package/dist/schemas/marketplace.d.ts +64 -0
  267. package/dist/schemas/marketplace.d.ts.map +1 -0
  268. package/dist/schemas/marketplace.js +17 -0
  269. package/dist/schemas/marketplace.js.map +1 -0
  270. package/dist/schemas/panels.d.ts +61 -0
  271. package/dist/schemas/panels.d.ts.map +1 -0
  272. package/dist/schemas/panels.js +51 -0
  273. package/dist/schemas/panels.js.map +1 -0
  274. package/dist/schemas/personas.d.ts +122 -0
  275. package/dist/schemas/personas.d.ts.map +1 -0
  276. package/dist/schemas/personas.js +102 -0
  277. package/dist/schemas/personas.js.map +1 -0
  278. package/dist/schemas/plan-limits.d.ts +172 -0
  279. package/dist/schemas/plan-limits.d.ts.map +1 -0
  280. package/dist/schemas/plan-limits.js +126 -0
  281. package/dist/schemas/plan-limits.js.map +1 -0
  282. package/dist/schemas/ports.d.ts +71 -0
  283. package/dist/schemas/ports.d.ts.map +1 -0
  284. package/dist/schemas/ports.js +42 -0
  285. package/dist/schemas/ports.js.map +1 -0
  286. package/dist/schemas/provider-oauth.d.ts +128 -0
  287. package/dist/schemas/provider-oauth.d.ts.map +1 -0
  288. package/dist/schemas/provider-oauth.js +91 -0
  289. package/dist/schemas/provider-oauth.js.map +1 -0
  290. package/dist/schemas/provider-subscriptions.d.ts +9 -0
  291. package/dist/schemas/provider-subscriptions.d.ts.map +1 -0
  292. package/dist/schemas/provider-subscriptions.js +3 -0
  293. package/dist/schemas/provider-subscriptions.js.map +1 -0
  294. package/dist/schemas/public.d.ts +32 -0
  295. package/dist/schemas/public.d.ts.map +1 -0
  296. package/dist/schemas/public.js +29 -0
  297. package/dist/schemas/public.js.map +1 -0
  298. package/dist/schemas/push.d.ts +55 -0
  299. package/dist/schemas/push.d.ts.map +1 -0
  300. package/dist/schemas/push.js +60 -0
  301. package/dist/schemas/push.js.map +1 -0
  302. package/dist/schemas/secrets.d.ts +86 -0
  303. package/dist/schemas/secrets.d.ts.map +1 -0
  304. package/dist/schemas/secrets.js +51 -0
  305. package/dist/schemas/secrets.js.map +1 -0
  306. package/dist/schemas/sessions.d.ts +32 -0
  307. package/dist/schemas/sessions.d.ts.map +1 -0
  308. package/dist/schemas/sessions.js +11 -0
  309. package/dist/schemas/sessions.js.map +1 -0
  310. package/dist/schemas/settings.d.ts +548 -0
  311. package/dist/schemas/settings.d.ts.map +1 -0
  312. package/dist/schemas/settings.js +259 -0
  313. package/dist/schemas/settings.js.map +1 -0
  314. package/dist/schemas/share.d.ts +49 -0
  315. package/dist/schemas/share.d.ts.map +1 -0
  316. package/dist/schemas/share.js +26 -0
  317. package/dist/schemas/share.js.map +1 -0
  318. package/dist/schemas/shared.d.ts +22 -0
  319. package/dist/schemas/shared.d.ts.map +1 -0
  320. package/dist/schemas/shared.js +16 -0
  321. package/dist/schemas/shared.js.map +1 -0
  322. package/dist/schemas/system.d.ts +86 -0
  323. package/dist/schemas/system.d.ts.map +1 -0
  324. package/dist/schemas/system.js +64 -0
  325. package/dist/schemas/system.js.map +1 -0
  326. package/dist/schemas/terminal.d.ts +230 -0
  327. package/dist/schemas/terminal.d.ts.map +1 -0
  328. package/dist/schemas/terminal.js +133 -0
  329. package/dist/schemas/terminal.js.map +1 -0
  330. package/dist/schemas/usage.d.ts +113 -0
  331. package/dist/schemas/usage.d.ts.map +1 -0
  332. package/dist/schemas/usage.js +91 -0
  333. package/dist/schemas/usage.js.map +1 -0
  334. package/dist/schemas/vpn.d.ts +229 -0
  335. package/dist/schemas/vpn.d.ts.map +1 -0
  336. package/dist/schemas/vpn.js +115 -0
  337. package/dist/schemas/vpn.js.map +1 -0
  338. package/dist/schemas/webext.d.ts +98 -0
  339. package/dist/schemas/webext.d.ts.map +1 -0
  340. package/dist/schemas/webext.js +36 -0
  341. package/dist/schemas/webext.js.map +1 -0
  342. package/dist/schemas/workflows.d.ts +881 -0
  343. package/dist/schemas/workflows.d.ts.map +1 -0
  344. package/dist/schemas/workflows.js +164 -0
  345. package/dist/schemas/workflows.js.map +1 -0
  346. package/dist/schemas/workspace-repos.d.ts +143 -0
  347. package/dist/schemas/workspace-repos.d.ts.map +1 -0
  348. package/dist/schemas/workspace-repos.js +87 -0
  349. package/dist/schemas/workspace-repos.js.map +1 -0
  350. package/dist/schemas/workspace-search.d.ts +170 -0
  351. package/dist/schemas/workspace-search.d.ts.map +1 -0
  352. package/dist/schemas/workspace-search.js +85 -0
  353. package/dist/schemas/workspace-search.js.map +1 -0
  354. package/dist/schemas/workspace-setup.d.ts +48 -0
  355. package/dist/schemas/workspace-setup.d.ts.map +1 -0
  356. package/dist/schemas/workspace-setup.js +26 -0
  357. package/dist/schemas/workspace-setup.js.map +1 -0
  358. package/dist/schemas/workspace-tree.d.ts +120 -0
  359. package/dist/schemas/workspace-tree.d.ts.map +1 -0
  360. package/dist/schemas/workspace-tree.js +111 -0
  361. package/dist/schemas/workspace-tree.js.map +1 -0
  362. package/dist/webext-links.d.ts +13 -0
  363. package/dist/webext-links.d.ts.map +1 -0
  364. package/dist/webext-links.js +24 -0
  365. package/dist/webext-links.js.map +1 -0
  366. package/dist/webext-protocol.d.ts +8 -0
  367. package/dist/webext-protocol.d.ts.map +1 -0
  368. package/dist/webext-protocol.js +7 -0
  369. package/dist/webext-protocol.js.map +1 -0
  370. package/dist/workflow-faults.d.ts +1 -1
  371. package/dist/workflow-faults.d.ts.map +1 -1
  372. package/dist/workspace-state.d.ts +11 -2
  373. package/dist/workspace-state.d.ts.map +1 -1
  374. package/dist/workspace-state.js +4 -2
  375. package/dist/workspace-state.js.map +1 -1
  376. package/package.json +17 -6
  377. package/src/agent-catalog.test.ts +1 -1
  378. package/src/agent-catalog.ts +4 -11
  379. package/src/chores/chores.ts +1 -1
  380. package/src/chores/probes.ts +1 -1
  381. package/src/chores/stack.test.ts +19 -0
  382. package/src/chores/stack.ts +19 -3
  383. package/src/chores/verdict.test.ts +11 -1
  384. package/src/chores/verdict.ts +1 -1
  385. package/src/command-classes.test.ts +378 -0
  386. package/src/command-classes.ts +378 -0
  387. package/src/contracts/activity.contract.ts +1 -1
  388. package/src/contracts/agent.contract.ts +22 -12
  389. package/src/contracts/agents.contract.ts +6 -6
  390. package/src/contracts/automations.contract.ts +2 -2
  391. package/src/contracts/capabilities.contract.ts +3 -4
  392. package/src/contracts/chores.contract.ts +2 -1
  393. package/src/contracts/ci.contract.ts +2 -2
  394. package/src/contracts/claude.contract.ts +2 -2
  395. package/src/contracts/cursor.contract.ts +2 -2
  396. package/src/contracts/drafts.contract.ts +2 -1
  397. package/src/contracts/endpoints.contract.ts +2 -1
  398. package/src/contracts/exit.contract.ts +2 -1
  399. package/src/contracts/extensions.contract.ts +5 -5
  400. package/src/contracts/git.contract.ts +19 -18
  401. package/src/contracts/grok.contract.ts +2 -1
  402. package/src/contracts/history.contract.ts +2 -1
  403. package/src/contracts/host.contract.ts +4 -1
  404. package/src/contracts/intentic.contract.ts +2 -1
  405. package/src/contracts/inventory.contract.ts +1 -1
  406. package/src/contracts/logs.contract.ts +7 -1
  407. package/src/contracts/loops.contract.ts +2 -2
  408. package/src/contracts/panels.contract.ts +2 -1
  409. package/src/contracts/personas.contract.ts +3 -3
  410. package/src/contracts/ports.contract.ts +3 -2
  411. package/src/contracts/prepush.contract.ts +2 -1
  412. package/src/contracts/providers.contract.ts +2 -1
  413. package/src/contracts/public.contract.ts +3 -2
  414. package/src/contracts/push.contract.ts +2 -1
  415. package/src/contracts/runner.contract.ts +33 -1
  416. package/src/contracts/secrets.contract.ts +2 -1
  417. package/src/contracts/sessions.contract.ts +1 -1
  418. package/src/contracts/settings.contract.ts +3 -9
  419. package/src/contracts/share.contract.ts +3 -2
  420. package/src/contracts/skills.contract.ts +2 -1
  421. package/src/contracts/system.contract.ts +6 -9
  422. package/src/contracts/translator.contract.ts +4 -1
  423. package/src/contracts/usage.contract.ts +1 -1
  424. package/src/contracts/vpn.contract.ts +2 -8
  425. package/src/contracts/webext.contract.ts +37 -0
  426. package/src/contracts/workflows.contract.ts +2 -2
  427. package/src/contracts/workspace.contract.ts +10 -12
  428. package/src/conversation-ids.test.ts +1 -1
  429. package/src/definition-action.ts +8 -0
  430. package/src/definition.ts +235 -0
  431. package/src/events.ts +128 -22
  432. package/src/fast-tier.ts +1 -1
  433. package/src/history-state.ts +5 -0
  434. package/src/host-protocol.ts +1 -1
  435. package/src/hostnames.test.ts +2 -2
  436. package/src/index.ts +61 -1
  437. package/src/listener-protocol.ts +1 -1
  438. package/src/quick-model.ts +1 -1
  439. package/src/runner-protocol.ts +35 -5
  440. package/src/schemas/activity.ts +123 -0
  441. package/src/schemas/agent.ts +409 -0
  442. package/src/schemas/agents.ts +802 -0
  443. package/src/schemas/automations.ts +510 -0
  444. package/src/schemas/capabilities.ts +729 -0
  445. package/src/schemas/ci.ts +235 -0
  446. package/src/schemas/claude-gate.ts +13 -0
  447. package/src/schemas/codebase-health.ts +64 -0
  448. package/src/schemas/computers.ts +287 -0
  449. package/src/schemas/drafts.ts +108 -0
  450. package/src/schemas/environment.ts +276 -0
  451. package/src/schemas/exit.ts +222 -0
  452. package/src/schemas/extension-updates.ts +322 -0
  453. package/src/schemas/fast-mode.ts +8 -0
  454. package/src/schemas/git-history.ts +265 -0
  455. package/src/schemas/git.ts +430 -0
  456. package/src/schemas/history.ts +112 -0
  457. package/src/schemas/hosts.ts +37 -0
  458. package/src/schemas/intentic.ts +2 -0
  459. package/src/schemas/internal.ts +17 -0
  460. package/src/schemas/inventory.ts +68 -0
  461. package/src/schemas/logs.ts +96 -0
  462. package/src/schemas/loops.ts +401 -0
  463. package/src/schemas/maintenance.ts +421 -0
  464. package/src/schemas/marketplace.ts +23 -0
  465. package/src/schemas/panels.ts +99 -0
  466. package/src/schemas/personas.ts +281 -0
  467. package/src/schemas/plan-limits.ts +255 -0
  468. package/src/schemas/ports.ts +84 -0
  469. package/src/schemas/provider-oauth.ts +191 -0
  470. package/src/schemas/provider-subscriptions.ts +11 -0
  471. package/src/schemas/public.ts +52 -0
  472. package/src/schemas/push.ts +112 -0
  473. package/src/schemas/secrets.ts +68 -0
  474. package/src/schemas/sessions.ts +16 -0
  475. package/src/schemas/settings.ts +932 -0
  476. package/src/schemas/share.ts +71 -0
  477. package/src/schemas/shared.ts +32 -0
  478. package/src/schemas/system.ts +156 -0
  479. package/src/schemas/terminal.ts +286 -0
  480. package/src/schemas/usage.ts +303 -0
  481. package/src/{schemas.test.ts → schemas/version-seam.test.ts} +4 -2
  482. package/src/schemas/vpn.ts +215 -0
  483. package/src/schemas/webext.ts +79 -0
  484. package/src/schemas/workflows.ts +413 -0
  485. package/src/schemas/workspace-repos.ts +123 -0
  486. package/src/schemas/workspace-search.ts +141 -0
  487. package/src/schemas/workspace-setup.ts +43 -0
  488. package/src/schemas/workspace-tree.ts +234 -0
  489. package/src/title.test.ts +1 -1
  490. package/src/webext-links.ts +80 -0
  491. package/src/webext-protocol.ts +27 -0
  492. package/src/workflow-faults.test.ts +1 -1
  493. package/src/workflow-faults.ts +1 -1
  494. package/src/workspace-state.test.ts +7 -3
  495. package/src/workspace-state.ts +27 -13
  496. package/dist/schemas.d.ts +0 -9800
  497. package/dist/schemas.d.ts.map +0 -1
  498. package/dist/schemas.js +0 -4252
  499. package/dist/schemas.js.map +0 -1
  500. package/src/schemas.ts +0 -9999
@@ -0,0 +1,108 @@
1
+ // drafts: agent-proposed posts awaiting owner approval (.intentic/config/drafts/<id>.json)
2
+ import { z } from "zod";
3
+ import { entryId } from "./internal.js";
4
+ // One JSON file per draft. The AGENT creates drafts with its normal file tools, it can't call daemon routes,
5
+ // the same split as the environment proposal, while the daemon edits/deletes them on the owner's behalf, so
6
+ // the two writers never share a file. The id IS the filename (entryId charset ⇒ path-safe); the body never
7
+ // carries it. Posting is the agent's job too (there is no typed publish path): a "publish approved drafts"
8
+ // automation wakes the agent for due drafts, which posts via the platform skills and flips the status.
9
+
10
+ export const DraftStatusSchema = z.enum(["proposed", "approved", "posting", "posted", "failed"]);
11
+ export type DraftStatus = z.infer<typeof DraftStatusSchema>;
12
+ // The on-disk file body. proposed (agent) → approved (owner) → posting (publisher, set BEFORE acting so a dead
13
+ // turn can't double-post) → posted | failed. Reject = delete the file; retry = re-approve a failed draft.
14
+ export const DraftSchema = z.object({
15
+ // Which skill posts it: "x" | "reddit" | "youtube" | "discord" | …, a bare string so new platforms need
16
+ // no contract change; an unknown platform simply fails at posting time.
17
+ platform: z
18
+ .string()
19
+ .min(1)
20
+ .describe("Where it should go. A plain name, so a new site needs no change here; an unknown one simply fails when it tries to post."),
21
+ /* WHOSE NAME THIS GOES OUT UNDER, a PersonaSchema id, handed to the publish turn as AgentTurnSchema.actsAs.
22
+ * Required in practice for every platform outside DIRECT_PUBLISH_PLATFORMS, and the reason is the whole
23
+ * shape of turnPersona: publishing through a browser needs a logged-in account, and an UNATTENDED turn that
24
+ * names no persona is denied every account there is. Without this field the publisher could only wake such a
25
+ * turn, one structurally unable to reach the login the post needs, which read from inside the turn as "this
26
+ * account is not connected" and cost two approved posts before anyone traced it back here.
27
+ *
28
+ * A PERSONA RATHER THAN AN ACCOUNT ID, because that is the vocabulary the rest of the system already speaks:
29
+ * `actsAs` is the only pin turnPersona honours, and a card carries the workspace scope the turn also needs to
30
+ * write this file's own status back. Naming the account directly would invent a second way to say the same
31
+ * thing, and the two would disagree the first time a card's accounts changed.
32
+ *
33
+ * The daemon never guesses it. One site can be connected several times over, five Reddit logins here, and
34
+ * picking for the owner means picking wrong in public, with no undo. A draft that needs a turn and names
35
+ * nobody is failed with that sentence instead of sent. */
36
+ actsAs: entryId
37
+ .optional()
38
+ .describe(
39
+ "Whose name it goes out under. Needed for anywhere that requires being logged in, because an unwatched turn naming nobody is allowed no account at all. Never guessed: one site can be connected five times over, and picking for you means picking wrong in public with no undo.",
40
+ ),
41
+ content: z.string().min(1).describe("The post itself."),
42
+ // Reddit posts / YouTube uploads need one.
43
+ title: z.string().optional().describe("A title, where the site wants one."),
44
+ /* Where on the platform: subreddit / Discord channel id / community. OR the URL of the thing this draft
45
+ * replies to. A URL target means the draft is a reply, and on reddit the difference between a thread's
46
+ * address and one comment's permalink is the difference between talking to the room and answering the
47
+ * person: the publisher opens exactly this and replies where it lands. */
48
+ target: z
49
+ .string()
50
+ .optional()
51
+ .describe(
52
+ "Where on the site: a community, a channel. Or the address of the thing this replies to, in which case it is a reply, and on some sites the difference between a thread's address and one comment's is the difference between talking to the room and answering the person.",
53
+ ),
54
+ // Workspace-relative attachment paths, e.g. ".intentic/config/drafts/media/chart.png".
55
+ media: z.array(z.string()).optional().describe("Anything to attach, as workspace paths."),
56
+ // Suggested post time (epoch ms, the at/nextRun convention). Optional, the agent may propose without a
57
+ // date and the owner sets one at approval; an approved draft with no date posts as soon as it's picked up.
58
+ scheduledAt: z
59
+ .number()
60
+ .optional()
61
+ .describe(
62
+ "When it should go out, in milliseconds. An agent may propose without one and you set it when approving; an approved draft with no time goes as soon as it is picked up.",
63
+ ),
64
+ // Agent-written files only need platform + content; status defaults, the rest are optional, so a
65
+ // well-formed proposal never lands in `invalid` just for omitting bookkeeping fields.
66
+ status: DraftStatusSchema.default("proposed").describe(
67
+ "Where it is: proposed by the agent, approved by you, being sent, sent, or failed. Rejecting is deleting it; retrying is approving a failed one again.",
68
+ ),
69
+ createdAt: z.number().optional().describe("When it was written, in milliseconds."),
70
+ // When sending STARTED, stamped with status "posting". The publisher needs it to tell a send that is under
71
+ // way from one whose run died mid-flight, and those two are indistinguishable from the due time, a post
72
+ // scheduled for last week is not a post that has been sending since last week.
73
+ postingAt: z
74
+ .number()
75
+ .optional()
76
+ .describe(
77
+ "When sending started, in milliseconds. Needed to tell a send that is under way from one whose run died mid-flight, which the scheduled time cannot: a post due last week is not a post that has been sending since last week.",
78
+ ),
79
+ postedAt: z.number().optional().describe("When it went out, in milliseconds."),
80
+ // Where it landed, when the platform hands back an address for it. The one thing a posted row can offer
81
+ // that reading the draft cannot: the post itself, to go and look at.
82
+ postedUrl: z
83
+ .string()
84
+ .optional()
85
+ .describe(
86
+ "Where it landed, when the site hands back an address. The one thing a sent draft can offer that reading it cannot: the post itself, to go and look at.",
87
+ ),
88
+ // Why posting failed; set with status "failed". Written for the owner to read in the queue, so it is a
89
+ // sentence rather than a code.
90
+ error: z.string().optional().describe("Why it failed, written as a sentence for a person to read rather than as a code."),
91
+ });
92
+ export type Draft = z.infer<typeof DraftSchema>;
93
+ // The list row / upsert input: the file body plus its filename id.
94
+ export const DraftSummarySchema = DraftSchema.extend({ id: entryId.describe("The draft's id.") });
95
+ export type DraftSummary = z.infer<typeof DraftSummarySchema>;
96
+ // `invalid` = filenames that failed to parse. Agent-written files are a trust boundary, without this a typo'd
97
+ // draft would silently never post.
98
+ export const DraftsListSchema = z.object({
99
+ drafts: z.array(DraftSummarySchema).describe("The queue."),
100
+ invalid: z
101
+ .array(z.string())
102
+ .describe(
103
+ "Drafts that could not be read at all. Listed rather than skipped, because an agent writes these files directly and a malformed one would otherwise never post and never say why.",
104
+ ),
105
+ });
106
+ export type DraftsList = z.infer<typeof DraftsListSchema>;
107
+ // entryId, not a bare string: the id becomes a filename under .intentic/config/drafts/.
108
+ export const DraftIdParamSchema = z.object({ id: entryId.describe("Which draft.") });
@@ -0,0 +1,276 @@
1
+ // environment: the overlay Dockerfile extending the sandbox image
2
+ import { z } from "zod";
3
+ // The approved file is DAEMON-COMPOSED: pinned FROM + capability fragments + the owner-approved custom section.
4
+ // The agent drafts one file per thing it needs (.intentic/config/environment.d/<tool>.Dockerfile, custom-section
5
+ // content only, no FROM) with its normal file tools, and the daemon folds those into the single proposal file
6
+ // (.intentic/config/environment.Dockerfile) the owner reads. The owner approves it in the browser, which stores it as
7
+ // the custom file and recomposes the approved artifact whose sha256 the rebuild executor pins. Both composed
8
+ // files are written only when the composition CHANGES, see writeComposed, and the read loop it exists to end.
9
+ // Status is derived, never stored:
10
+ // applied = sha256(approved) === appliedHash; pending rebuild = approved present but hashes differ; proposed =
11
+ // proposal present with a hash different from custom's.
12
+
13
+ const environmentFileSchema = z.object({ content: z.string(), hash: z.string() });
14
+ /* ---- environment DRIFT: what the live container has that the image did not put there ----
15
+ *
16
+ * Anything installed outside /work dies with the container, and transcript mining showed the same tools being
17
+ * reinstalled session after session (cargo-xwin six times, a Windows rustup target eight) before anyone thought
18
+ * to bake them. Drift is the daemon OBSERVING that gap rather than trusting the model to report it: apt installs
19
+ * read from dpkg's own log, everything else from system paths newer than the container itself. Two channels
20
+ * because they are disjoint by construction — dpkg unpacks files with their archive mtimes, so an mtime sweep
21
+ * cannot see apt, and nothing apt does lands under the swept prefixes' hand-installed corners. */
22
+ export const EnvironmentDriftSchema = z.object({
23
+ // When this container was created (PID 1's start). A snapshot whose bornAt is not the running container's
24
+ // describes a container that no longer exists, and every reader must treat it as no drift at all.
25
+ bornAt: z.number(),
26
+ // When the probe ran.
27
+ at: z.number(),
28
+ // Debian packages installed since the container was born, from /var/log/dpkg.log.
29
+ apt: z.array(z.string()),
30
+ // System paths (outside /work) newer than the container, collapsed so a browser download is one entry.
31
+ paths: z.array(z.string()),
32
+ });
33
+ export type EnvironmentDrift = z.infer<typeof EnvironmentDriftSchema>;
34
+ // How a runtime install was made, which decides whether the daemon can draft a Dockerfile step for it
35
+ // mechanically (apt/cargo/npm/rustup-target) or only surface it for a person to route (pip belongs in a venv or
36
+ // a Debian package, "other" is a curl|sh whose replay could embed anything).
37
+ export const RuntimeInstallKindSchema = z.enum(["apt", "pip", "cargo", "npm", "rustup-target", "playwright", "gem", "pipx", "go", "other"]);
38
+ export type RuntimeInstallKind = z.infer<typeof RuntimeInstallKindSchema>;
39
+ /* One tool's runtime-install history across sessions: the ledger entry behind the recurrence signal. Sessions
40
+ * are the unit of recurrence — a session that retries an install five times needed it once — and the entry
41
+ * survives container recreates (the file lives under /work), which is exactly what makes "installed again in a
42
+ * fresh container" observable at all. */
43
+ export const RuntimeInstallSchema = z.object({
44
+ tool: z.string(),
45
+ kind: RuntimeInstallKindSchema,
46
+ // Distinct conversation ids that installed it, capped; length is the recurrence count that gates drafting.
47
+ sessions: z.array(z.string()),
48
+ // The most recent install commands, capped, secrets already masked to references by the harness.
49
+ commands: z.array(z.string()),
50
+ firstAt: z.number(),
51
+ lastAt: z.number(),
52
+ count: z.number(),
53
+ // The owner rejected an auto-drafted step for this tool: never propose it again until this is cleared.
54
+ declinedAt: z.number().optional(),
55
+ });
56
+ export type RuntimeInstall = z.infer<typeof RuntimeInstallSchema>;
57
+ export const RuntimeInstallsFileSchema = z.object({
58
+ installs: z.array(RuntimeInstallSchema),
59
+ // The last drift snapshot, persisted so a daemon restart does not blank the card until the next sweep.
60
+ drift: EnvironmentDriftSchema.optional(),
61
+ });
62
+ export type RuntimeInstallsFile = z.infer<typeof RuntimeInstallsFileSchema>;
63
+ // A ledger entry as the Environment card shows it: recurrence joined with whether the install is present in the
64
+ // LIVE container (drift-corroborated), already drafted for approval, or previously declined.
65
+ export const EnvironmentRecurringSchema = z.object({
66
+ tool: z.string(),
67
+ kind: RuntimeInstallKindSchema,
68
+ sessions: z.number(),
69
+ lastAt: z.number(),
70
+ live: z.boolean(),
71
+ drafted: z.boolean().optional(),
72
+ declined: z.boolean().optional(),
73
+ });
74
+ export type EnvironmentRecurring = z.infer<typeof EnvironmentRecurringSchema>;
75
+ export const EnvironmentSchema = z.object({
76
+ proposal: environmentFileSchema.optional(),
77
+ // The owner-approved agent-written custom section (.intentic/config/environment.custom.Dockerfile).
78
+ custom: environmentFileSchema.optional(),
79
+ approved: environmentFileSchema.optional(),
80
+ // sha256 of the overlay the running container was built from (SANDBOX_ENVIRONMENT_HASH); absent = stock image.
81
+ appliedHash: z.string().optional(),
82
+ // config.sandbox.name, the UI derives the rebuild one-liner's slug from it.
83
+ container: z.string().optional(),
84
+ // What the live container has that the image did not put there; absent until the first sweep of this container.
85
+ drift: EnvironmentDriftSchema.optional(),
86
+ // Runtime installs worth the owner's attention: recurring across sessions, or present-and-doomed right now.
87
+ recurring: z.array(EnvironmentRecurringSchema).optional(),
88
+ });
89
+ export type Environment = z.infer<typeof EnvironmentSchema>;
90
+ export const EnvironmentApproveSchema = z.object({ hash: z.string().min(1) });
91
+ /* ---- environment CONTENTS: what the sandbox has, as opposed to how it was built ----
92
+ *
93
+ * The overlay above answers "what was added on top, and do you approve it?". Nobody opens the Environment tab
94
+ * asking that, they ask "can this sandbox compile my Rust app / transcode a video / drive a browser?", and a
95
+ * build recipe is a bad answer to it: it is install plumbing, it names packages rather than abilities, and it is
96
+ * only the DELTA, so an inventory read off it alone would claim a sandbox has ffmpeg and no Node.
97
+ *
98
+ * So this is a second read of the same sandbox, and its authority is different in a way that matters: NAMES,
99
+ * GROUPING and RATIONALE come from the recipe (which is where the agent wrote them), while PRESENCE and VERSION
100
+ * come from asking the environment itself. That split is what makes it honest. A version is never parsed out of
101
+ * an install line, half the entries pin nothing, and a pinned number is a lie the moment something is approved
102
+ * but not yet rebuilt, so an item whose tools cannot be probed carries no version at all rather than a guess.
103
+ * And presence is OBSERVED, which is what makes per-item state exact without diffing anything: an item the
104
+ * recipe contains and the probe cannot find is precisely one that arrives with the next rebuild.
105
+ */
106
+
107
+ const environmentToolSchema = z.object({
108
+ // The binary as it is invoked (`rustc`, `ffmpeg`), because that is what somebody types next.
109
+ name: z.string(),
110
+ // What the binary itself reports, absent when it is not installed (yet) or answers no version flag.
111
+ version: z.string().optional(),
112
+ });
113
+ export const EnvironmentItemSchema = z.object({
114
+ id: z.string(),
115
+ // The block's own name, how the thing is referred to, not the packages it happens to install.
116
+ name: z.string(),
117
+ /* WHY IT IS HERE, which is also whether the reader may remove it: `custom` is what an agent asked for and the
118
+ * owner approved for this workspace, `capability` is the cost of a capability they turned on, `base` comes
119
+ * with every sandbox and is nobody's decision. */
120
+ origin: z.enum(["custom", "capability", "base"]),
121
+ // Which capability/extension/pack pulled it in, the answer to "why do I have this?" for an origin the
122
+ // reader did not choose item by item.
123
+ originLabel: z.string().optional(),
124
+ // Observed, not inferred: `active` means the probe found it, `after-rebuild` that the recipe has it and the
125
+ // container does not, `awaiting-approval` that it is in a proposal nobody has approved yet.
126
+ state: z.enum(["active", "after-rebuild", "awaiting-approval"]),
127
+ // Every binary this one block puts on PATH, with the version each reports. Usually one; a toolchain is several.
128
+ tools: z.array(environmentToolSchema),
129
+ // How many further packages the block installs that are not commands anyone runs (libraries, headers). A
130
+ // count rather than a list: eleven rows of `libssl-dev` is noise, "+11 packages" is the same fact.
131
+ extras: z.number().optional(),
132
+ // One standalone line, from the block's opening comment, the part everyone reads.
133
+ purpose: z.string().optional(),
134
+ /* That comment in full, as prose, absent when the line above already is the whole of it. NOT the remainder
135
+ * after the line: `purpose` is a summary of this (a parenthetical dropped, an over-long sentence cut back to
136
+ * its claim), so the two overlap by design and it is the reader's view that picks one. Long, the rationale
137
+ * for a toolchain runs to paragraphs, so it lives behind a disclosure rather than on the row. */
138
+ detail: z.string().optional(),
139
+ // The block's own instruction lines, for the reader who wants to see exactly what runs.
140
+ commands: z.string().optional(),
141
+ });
142
+ export type EnvironmentItem = z.infer<typeof EnvironmentItemSchema>;
143
+ export const EnvironmentContentsSchema = z.object({ items: z.array(EnvironmentItemSchema) });
144
+ export type EnvironmentContents = z.infer<typeof EnvironmentContentsSchema>;
145
+ /* ---- portability: exporting a sandbox's environment and restoring it into a fresh one ----
146
+ *
147
+ * A sandbox is four stores, not one: `/work` (the workspace and the daemon's manifests), `/history` (every
148
+ * repo's real git dir, the fleet registry, the ledgers), the CONTAINER (the built overlay image plus the env
149
+ * the run contract replays) and the AI-provider credential root. A bundle carries the first two, declared entry
150
+ * by entry in WORKSPACE_STATE_FILES / HISTORY_STATE_FILES. It cannot carry the other two, and the honest
151
+ * consequence is that an import ends in a REPORT rather than a claim of equivalence, the container has no
152
+ * docker socket, so only the host can rebuild the image the overlay describes.
153
+ *
154
+ * The bundle's manifest (BundleManifestSchema) lives in definition.ts beside the sandbox DEFINITION it embeds:
155
+ * a bundle is definition + state, and keeping the two schemas together is what keeps the two export doors from
156
+ * drifting into different answers about what an environment is. */
157
+
158
+ // What a restore actually did. `needsAction` is the part that matters: the environment rebuild command, the
159
+ // credentials to re-enter, the logins to redo, each one a thing the target cannot do for itself.
160
+ export const ImportReportSchema = z.object({
161
+ restored: z.object({ workspaceFiles: z.number(), historyFiles: z.number(), repos: z.array(z.string()), bytes: z.number() }),
162
+ // Entries the bundle carried that this daemon refused to write (an identity file, an escaping path), empty
163
+ // for any bundle a matching exporter produced, and a tamper signal when it is not.
164
+ refused: z.array(z.string()),
165
+ needsAction: z.array(z.object({ subject: z.string(), detail: z.string() })),
166
+ });
167
+ export type ImportReport = z.infer<typeof ImportReportSchema>;
168
+ /* ---- migrations: importing a FOREIGN assistant's setup (Hermes, OpenClaw) ----
169
+ *
170
+ * A different crossing than a bundle restore, and deliberately a different surface: a bundle is our own format,
171
+ * re-derived entry by entry against the state manifests, while a migration reads a directory some OTHER
172
+ * program laid out (`~/.hermes`) and TRANSLATES it into native things, skills, automations, capabilities,
173
+ * merged memory. Nothing foreign is executed or copied verbatim into daemon state; every item lands through the
174
+ * same write paths the settings/skills/automations/capabilities surfaces use, which is what keeps an imported
175
+ * setup editable and deletable in the ordinary UI the day after (docs/assistant-import-design.md).
176
+ *
177
+ * The flow is PREVIEW-FIRST, mirroring what these tools' own `migrate` commands taught their users to expect:
178
+ * `plan` parses the uploaded archive into an itemized checklist and holds the upload in memory under a token;
179
+ * `apply` names the ticked item ids and the token. The plan is RE-DERIVED from the held archive at apply, the
180
+ * wire plan is a rendering for the owner, never the input the write trusts (restore.ts's rule, kept). */
181
+ export const MigrationSourceSchema = z.enum(["hermes", "openclaw"]);
182
+ export type MigrationSource = z.infer<typeof MigrationSourceSchema>;
183
+ // What an item becomes here, not what it was there, the apply loop dispatches on this, and the checklist
184
+ // groups by it so the owner reads "3 skills, 2 automations" rather than a foreign directory listing.
185
+ export const MigrationTargetSchema = z.enum(["memory", "skill", "automation", "capability", "secret", "file"]);
186
+ export type MigrationTarget = z.infer<typeof MigrationTargetSchema>;
187
+ export const MigrationItemSchema = z.object({
188
+ // Deterministic (derived from the source artifact, e.g. `skill:weather`), so the ids the owner ticked name
189
+ // the same items when the plan is re-derived at apply.
190
+ id: z.string(),
191
+ target: MigrationTargetSchema,
192
+ // The checklist line, plain words: "Skill, weather", "Nightly digest (9:00 every day)".
193
+ label: z.string(),
194
+ detail: z.string().optional(),
195
+ /* The default tick. False marks the items the owner should read before taking, a server URL that points at
196
+ * localhost on the OLD machine, an .env key that looks like tuning rather than a credential. They still
197
+ * import fine when ticked; the flag is the adapter's judgment, not a gate. */
198
+ recommended: z.boolean(),
199
+ // Names of the secrets this item would store (never values, values stay in the held archive until apply,
200
+ // and only move when the apply says includeSecrets). Empty for items that carry none.
201
+ secrets: z.array(z.string()),
202
+ });
203
+ export type MigrationItem = z.infer<typeof MigrationItemSchema>;
204
+ export const MigrationNeedsActionSchema = z.object({ subject: z.string(), detail: z.string() });
205
+ export const MigrationPlanSchema = z.object({
206
+ source: MigrationSourceSchema,
207
+ // Names the held upload for the apply call. Minted per plan; a new upload replaces the held one.
208
+ token: z.string(),
209
+ items: z.array(MigrationItemSchema),
210
+ // What the adapter saw and will not move, sessions, logs, pairing state, listed rather than silent.
211
+ refused: z.array(z.string()),
212
+ // What is already known not to move mechanically (channels to reconnect, a model to pick), the same
213
+ // honesty ImportReportSchema carries, surfaced at PREVIEW time so the owner ticks with open eyes.
214
+ needsAction: z.array(MigrationNeedsActionSchema),
215
+ });
216
+ export type MigrationPlan = z.infer<typeof MigrationPlanSchema>;
217
+ /* One of the owner's own computers, as an import SOURCE, the answer to "where is my setup" that needs no
218
+ * packing at all. Read on the card's first render for every enrolled machine, so the offer appears before the
219
+ * owner has read a single instruction.
220
+ *
221
+ * `found` absent means "connected, and nothing to import here", which is a real answer worth rendering
222
+ * quietly, not an error: the machine may simply be a different one from the machine the assistant runs on. */
223
+ export const MigrationHostSchema = z.object({
224
+ id: z.string(),
225
+ online: z.boolean(),
226
+ found: MigrationSourceSchema.optional(),
227
+ // Why this machine cannot be read right now, when it cannot, offline, or its own refusal, in its words.
228
+ detail: z.string().optional(),
229
+ });
230
+ export const MigrationHostsSchema = z.object({ hosts: z.array(MigrationHostSchema) });
231
+ export type MigrationHost = z.infer<typeof MigrationHostSchema>;
232
+ // Read the setup off a connected computer instead of an upload. Answers with a plan, exactly as the upload
233
+ // route does, everything after this point is identical whichever door the setup came through.
234
+ export const MigrationScanSchema = z.object({ host: z.string().min(1) });
235
+ export const MigrationApplySchema = z.object({
236
+ token: z.string(),
237
+ // The ticked item ids. Ids the re-derived plan does not contain are ignored rather than erroring, the
238
+ // archive is the truth, and a stale checklist must not block the items that still exist.
239
+ items: z.array(z.string()),
240
+ // The owner's explicit consent to move credential VALUES (mirrors the bundle export's `?secrets=`, and the
241
+ // `--include-secrets` these tools' own migrate commands require). Off: secret items are skipped and
242
+ // capability configs land without their keys.
243
+ includeSecrets: z.boolean(),
244
+ });
245
+ export type MigrationApply = z.infer<typeof MigrationApplySchema>;
246
+ export const MigrationReportSchema = z.object({
247
+ applied: z.array(z.object({ id: z.string(), target: MigrationTargetSchema, label: z.string() })),
248
+ // Items that were ticked and did not land, each with the reason, a full disk, an env store that needs
249
+ // DevOps active. Distinct from `refused`, which is the class of things never attempted.
250
+ failed: z.array(z.object({ id: z.string(), label: z.string(), error: z.string() })),
251
+ refused: z.array(z.string()),
252
+ needsAction: z.array(MigrationNeedsActionSchema),
253
+ });
254
+ export type MigrationReport = z.infer<typeof MigrationReportSchema>;
255
+ /* One export sitting in the daemon's export directory, the ARTIFACT a bundle is, rather than the request that
256
+ * produced it. Packing takes minutes over a real workspace, so tying it to a response made it a property of one
257
+ * browser tab: a refresh abandoned the work and left nothing to come back to. It is a file now, and every field
258
+ * below is read off that file rather than remembered anywhere.
259
+ *
260
+ * `status` is derived from the extension (.part / .tar.gz / .failed) and `bytes` is the file's own size, which
261
+ * is what makes a live pack's progress free to report. */
262
+ export const BundleExportSchema = z.object({
263
+ // The finished bundle's filename, which is the id in every route, and, once downloaded, the name the owner
264
+ // sees on disk. Carries its own timestamp and a `-with-secrets` marker so it stays self-describing there.
265
+ name: z.string(),
266
+ status: z.enum(["packing", "ready", "failed"]),
267
+ // Bytes written so far while packing; the finished size once ready.
268
+ bytes: z.number(),
269
+ // mtime: when packing ended for a finished bundle, when it last made progress for a live one.
270
+ createdAt: z.number(),
271
+ secrets: z.boolean(),
272
+ // Why it stopped, for a failed one. Read from the .failed marker's own contents.
273
+ error: z.string().optional(),
274
+ });
275
+ export type BundleExport = z.infer<typeof BundleExportSchema>;
276
+ export const BundleExportsSchema = z.object({ exports: z.array(BundleExportSchema) });
@@ -0,0 +1,222 @@
1
+ // Geo exits: somewhere the agent's traffic can LEAVE from, so a page fetches as if read elsewhere. Its own
2
+ // capability kind rather than a fourth `vpn` provider — an exit routes NOTHING into the main table.
3
+ import { z } from "zod";
4
+ import { autoStart } from "./internal.js";
5
+ /* A GEO EXIT: somewhere the agent's traffic can LEAVE from, so a page fetches as if read in Berlin or Osaka.
6
+ * Its own kind rather than a fourth `vpn` provider, and the distinction is the whole reason this works:
7
+ *
8
+ * a `vpn` REACHES a private network , one stored gateway, dialled, pushing its routes into the main table.
9
+ * an `exit` LEAVES from somewhere else, a POOL with a catalog, switched at runtime, routing NOTHING into
10
+ * the main table.
11
+ *
12
+ * That last clause is load-bearing. An exit is a full tunnel by definition, and a full tunnel on the main
13
+ * table swallows the sandbox's own uplink, the model endpoint and the tunnel that makes this sandbox
14
+ * reachable, which reads to a user as the agent breaking mid-turn (see IpsecVpnConfigSchema.routedNetworks
15
+ * for the same trap on the vpn kind). So an exit never touches the default route. It publishes a local SOCKS
16
+ * proxy and callers opt in: a browser account naming it, `curl --proxy`, and nothing else. The side benefit
17
+ * is trust, a volunteer relay carries only what was pointed at it, never the agent's own working traffic.
18
+ *
19
+ * Three providers, chosen because each is reachable with no paid account:
20
+ * tor , the Tor network. ~52 exit countries, no account, no credentials, no privileges: it is a SOCKS
21
+ * proxy already. Country is a torrc line, a new IP is a control-port signal. The free default.
22
+ * vpngate , the University of Tsukuba's volunteer relay pool. No account; its public CSV IS the catalog,
23
+ * so servers auto-fill. Overwhelmingly Japan/Korea in practice, which is the half of the map Tor
24
+ * covers worst, so the two complement rather than duplicate.
25
+ * wireguard, bring your own .conf files, one per country, from a provider's dashboard (Proton VPN's free
26
+ * tier, Mullvad, anything). The catalog is built by parsing what was pasted.
27
+ * Starting, switching country and rotating are LIVE operations (see exit.contract.ts), never config, so an
28
+ * exit's real state is read off the machine. `country` is the resting preference and `autoStart` the only
29
+ * other persisted intent. */
30
+ export const ExitProviderSchema = z.enum(["tor", "vpngate", "wireguard"]);
31
+ export type ExitProvider = z.infer<typeof ExitProviderSchema>;
32
+ // An ISO 3166-1 alpha-2 code, normalised up so "de", "DE" and "De" are one country rather than three. The
33
+ // catalogs, the CLI and the manifest all speak this one spelling.
34
+ export const CountryCodeSchema = z
35
+ .string()
36
+ .regex(/^[A-Za-z]{2}$/, "A country is its two-letter code, like DE, US or JP.")
37
+ .transform((value) => value.toUpperCase());
38
+ export const TorExitConfigSchema = z.object({
39
+ provider: z.literal("tor"),
40
+ // Where to come out, when nothing has asked for somewhere else. Absent ⇒ let Tor choose, which is both
41
+ // faster and kinder to the network.
42
+ country: CountryCodeSchema.optional(),
43
+ autoStart,
44
+ });
45
+ export const VpngateExitConfigSchema = z.object({
46
+ provider: z.literal("vpngate"),
47
+ country: CountryCodeSchema.optional(),
48
+ autoStart,
49
+ });
50
+ export const WireguardExitConfigSchema = z.object({
51
+ /* One or more WireGuard .conf files in one field, pasted back to back. One field rather than one
52
+ * capability per country because they are one POOL: the whole point is switching between them under a
53
+ * proxy port that never moves, and a user with five Proton free countries should not add five capabilities
54
+ * to get five countries out of one account.
55
+ *
56
+ * Country per conf comes from an optional `# country: DE` line, else from the provider's own naming
57
+ * convention in the Endpoint host (Proton's `de-free-01.protonvpn.net`, Mullvad's `de-ber-wg-001`), else
58
+ * from a lookup through the tunnel once it is up. Whole thing is the secret: each conf holds a private key. */
59
+ provider: z.literal("wireguard"),
60
+ config: z.string().min(1),
61
+ country: CountryCodeSchema.optional(),
62
+ autoStart,
63
+ });
64
+ export const ExitConfigSchema = z.discriminatedUnion("provider", [TorExitConfigSchema, VpngateExitConfigSchema, WireguardExitConfigSchema]);
65
+ export type TorExitConfig = z.infer<typeof TorExitConfigSchema>;
66
+ export type VpngateExitConfig = z.infer<typeof VpngateExitConfigSchema>;
67
+ export type WireguardExitConfig = z.infer<typeof WireguardExitConfigSchema>;
68
+ export type ExitConfig = z.infer<typeof ExitConfigSchema>;
69
+ // The manifest says which exits EXIST; this says which are up, where they come out, and what the world sees.
70
+ // Read off the machine and off the wire, never remembered: an exit the agent stopped from a shell and one the
71
+ // UI stopped read identically, and a daemon restart observes the truth rather than a stale guess.
72
+
73
+ export const ExitStateSchema = z.enum([
74
+ // Carrying traffic: the proxy is listening and the last check came out where it was asked to.
75
+ "up",
76
+ // Coming up, or moving to another country. The proxy port may already be open and not yet where you want.
77
+ "starting",
78
+ // Configured and idle. The resting state, and the default one: exits are not held open for nothing.
79
+ "down",
80
+ // The client isn't installed yet (tor, openvpn): the capability's image fragment needs an owner rebuild.
81
+ "unavailable",
82
+ // The last start or switch failed; `detail` carries the reason.
83
+ "failed",
84
+ ]);
85
+ export type ExitState = z.infer<typeof ExitStateSchema>;
86
+ /* WHAT THE WORLD SEES, fetched THROUGH the exit's own proxy. This is the load-bearing type of the whole
87
+ * feature: "switch to Germany" is worth nothing as a report that a tunnel came up, and worth everything as a
88
+ * report that the egress address is now German. Every start, use and rotate ends by producing one of these,
89
+ * and a switch that cannot produce one fails instead of quietly leaving traffic where it was. */
90
+ export const ExitObservationSchema = z.object({
91
+ ip: z.string().describe("The address the world sees, looked up through the exit's own proxy rather than assumed."),
92
+ // Absent when the lookup answered with an address but no country: a switch is judged on the country when
93
+ // one is known, and on the address having CHANGED when it is not.
94
+ country: z
95
+ .string()
96
+ .optional()
97
+ .describe(
98
+ "Which country that address is in. Absent when the lookup gave an address and no country, in which case a switch is judged on the address having changed instead.",
99
+ ),
100
+ countryName: z.string().optional().describe("That country's name, spelled out."),
101
+ });
102
+ export type ExitObservation = z.infer<typeof ExitObservationSchema>;
103
+ /* One country an exit can come out of, as the picker and `exit countries` render it. `servers` and `share`
104
+ * are what stop a country list being a lie: Tor lists 52 countries and a third of them are one underpowered
105
+ * relay, so the ranking has to carry how much is actually there, not just that the flag exists. */
106
+ export const ExitPointSchema = z.object({
107
+ country: z.string().describe("The country's code."),
108
+ countryName: z.string().describe("Its name, spelled out."),
109
+ // How many relays/servers this provider has there right now.
110
+ servers: z.number().describe("How many servers this provider has there."),
111
+ // This country's share of the provider's total exit capacity, 0..1. Used to sort and to grey out the
112
+ // countries that technically exist and practically do not.
113
+ share: z
114
+ .number()
115
+ .optional()
116
+ .describe(
117
+ "How much of the provider's actual capacity is there, from zero to one. This is what a list should be sorted by: a third of the countries on offer are one overloaded machine behind a flag, and a count of servers would rank them first.",
118
+ ),
119
+ });
120
+ export type ExitPoint = z.infer<typeof ExitPointSchema>;
121
+ export const ExitCountriesSchema = z.object({
122
+ countries: z.array(ExitPointSchema).describe("Where this exit can put you, best-supplied first."),
123
+ // Whether this list came off the provider live or out of the baked fallback (no network, or the provider
124
+ // is down). The picker says so rather than presenting a stale list as current.
125
+ live: z
126
+ .boolean()
127
+ .describe("Whether the provider answered, or this came from a built-in list. Said out loud rather than presenting an old list as current."),
128
+ });
129
+ export const ExitLinkSchema = z.object({
130
+ id: z.string().describe("Which exit."),
131
+ provider: ExitProviderSchema.describe("What it runs on."),
132
+ state: ExitStateSchema.describe(
133
+ "Whether it is carrying traffic, coming up, resting, failed, or not installable yet because its client needs a rebuild to arrive.",
134
+ ),
135
+ // The SOCKS endpoint callers point at. Fixed per exit and stable across country switches, which is what
136
+ // lets a long task change country halfway without reconfiguring anything downstream.
137
+ proxy: z
138
+ .string()
139
+ .describe(
140
+ "Where to point traffic that should go through it. Fixed per exit and unchanged by a country switch, which is what lets a long job move country halfway through without reconfiguring anything.",
141
+ ),
142
+ // The country ASKED for (manifest preference, or the last `use`). Absent = provider's choice.
143
+ country: z.string().optional().describe("Where it was asked to come out. Absent means the provider chose."),
144
+ // The country actually OBSERVED at the last check, and the address behind it. These two disagreeing is
145
+ // the single most useful fault signal this feature has, so they are separate fields, never merged.
146
+ observedCountry: z
147
+ .string()
148
+ .optional()
149
+ .describe(
150
+ "Where it actually comes out, as last checked. Kept separate from what was asked for, because those two disagreeing is the most useful fault signal this whole feature has.",
151
+ ),
152
+ ip: z.string().optional().describe("The address behind that observation."),
153
+ // Epoch ms of the observation above, so a stale reading can be rendered as stale.
154
+ checkedAt: z.number().optional().describe("When that was checked, in milliseconds, so an old reading can be shown as old."),
155
+ // The tunnel interface, for the providers that have one (vpngate, wireguard). Tor has none by design.
156
+ interface: z.string().optional().describe("The network interface, for the kinds that have one."),
157
+ since: z.number().optional().describe("When it came up, in milliseconds."),
158
+ autoStart: z.boolean().describe("Whether it starts itself when the sandbox does."),
159
+ detail: z.string().optional().describe("Why it failed, or a note about a healthy one."),
160
+ });
161
+ export type ExitLink = z.infer<typeof ExitLinkSchema>;
162
+ export const ExitListSchema = z.object({
163
+ links: z.array(ExitLinkSchema).describe("Every configured exit, with where it was asked to come out and where it actually does."),
164
+ });
165
+ /* WHERE EACH FREE PROVIDER CAN ACTUALLY COME OUT, as measured, and the reason it lives in the contract rather
166
+ * than in the daemon: two consumers need the same answer and must not drift. The daemon uses it as the
167
+ * FALLBACK catalog when a provider's own list cannot be fetched; the add form uses it to fill the country
168
+ * picker, so a user chooses from a list instead of guessing a code and finding out later that nothing serves
169
+ * it. A second copy of these numbers would let the picker offer a country the driver cannot dial.
170
+ *
171
+ * `share` is the country's slice of the provider's exit capacity, and it is the number that matters. A third
172
+ * of Tor's fifty-two countries are one overloaded relay behind a flag; ranking by relay COUNT alone would put
173
+ * the United States first on 1,171 slow relays when the Netherlands carries three times the traffic on half as
174
+ * many. Both surfaces sort on this so the top of the list is the part that works.
175
+ *
176
+ * Measured 2026-08-21 from onionoo.torproject.org and vpngate.net's public CSV. Stale by construction, which
177
+ * is exactly why the daemon prefers a live fetch and labels this one as not-live when it falls back to it. */
178
+ export const TOR_EXIT_COUNTRIES: readonly ExitPoint[] = [
179
+ { country: "NL", countryName: "Netherlands", servers: 607, share: 0.304 },
180
+ { country: "DE", countryName: "Germany", servers: 415, share: 0.242 },
181
+ { country: "SE", countryName: "Sweden", servers: 344, share: 0.14 },
182
+ { country: "US", countryName: "United States", servers: 1171, share: 0.097 },
183
+ { country: "AT", countryName: "Austria", servers: 123, share: 0.054 },
184
+ { country: "LU", countryName: "Luxembourg", servers: 92, share: 0.033 },
185
+ { country: "FR", countryName: "France", servers: 63, share: 0.032 },
186
+ { country: "NO", countryName: "Norway", servers: 54, share: 0.026 },
187
+ { country: "RO", countryName: "Romania", servers: 71, share: 0.011 },
188
+ { country: "DK", countryName: "Denmark", servers: 15, share: 0.007 },
189
+ { country: "HU", countryName: "Hungary", servers: 20, share: 0.006 },
190
+ { country: "IT", countryName: "Italy", servers: 15, share: 0.006 },
191
+ { country: "UA", countryName: "Ukraine", servers: 23, share: 0.006 },
192
+ { country: "CH", countryName: "Switzerland", servers: 23, share: 0.006 },
193
+ { country: "IS", countryName: "Iceland", servers: 23, share: 0.003 },
194
+ { country: "PL", countryName: "Poland", servers: 8, share: 0.002 },
195
+ { country: "BG", countryName: "Bulgaria", servers: 17, share: 0.002 },
196
+ { country: "GB", countryName: "United Kingdom", servers: 8, share: 0.002 },
197
+ { country: "FI", countryName: "Finland", servers: 13, share: 0.002 },
198
+ ];
199
+ // VPN Gate, and its shape is the honest headline: 87% of its pool is Japan and Korea. That is not a defect to
200
+ // hide behind a long country list, it is the reason to have it, Tor's Asian exit capacity is close to nothing,
201
+ // so the two providers cover each other rather than overlapping.
202
+ export const VPNGATE_EXIT_COUNTRIES: readonly ExitPoint[] = [
203
+ { country: "JP", countryName: "Japan", servers: 46, share: 0.48 },
204
+ { country: "KR", countryName: "Korea, South", servers: 37, share: 0.39 },
205
+ { country: "VN", countryName: "Vietnam", servers: 3, share: 0.03 },
206
+ { country: "TH", countryName: "Thailand", servers: 2, share: 0.02 },
207
+ { country: "RU", countryName: "Russia", servers: 2, share: 0.02 },
208
+ { country: "RO", countryName: "Romania", servers: 1, share: 0.01 },
209
+ { country: "MX", countryName: "Mexico", servers: 1, share: 0.01 },
210
+ { country: "IN", countryName: "India", servers: 1, share: 0.01 },
211
+ { country: "CN", countryName: "China", servers: 1, share: 0.01 },
212
+ { country: "BY", countryName: "Belarus", servers: 1, share: 0.01 },
213
+ ];
214
+ export const ExitIdParamSchema = z.object({ id: z.string().describe("Which exit.") });
215
+ // POST /exit/{id}/use body. An absent country means "let the provider choose", the same thing an absent
216
+ // `country` in the manifest means, so clearing a country is expressible rather than only setting one.
217
+ export const ExitUseInputSchema = z.object({
218
+ id: z.string().describe("Which exit."),
219
+ country: CountryCodeSchema.optional().describe(
220
+ "Where to come out. Leaving it out means letting the provider choose, so clearing a country is something you can actually say rather than only setting one.",
221
+ ),
222
+ });