@intentic/sandbox-contract 1.307.0 → 1.308.2

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 (260) hide show
  1. package/README.md +12 -0
  2. package/dist/contracts/accounts.contract.d.ts +6 -6
  3. package/dist/contracts/accounts.contract.js +7 -7
  4. package/dist/contracts/accounts.contract.js.map +1 -1
  5. package/dist/contracts/activity.contract.d.ts +2 -2
  6. package/dist/contracts/activity.contract.js +3 -3
  7. package/dist/contracts/activity.contract.js.map +1 -1
  8. package/dist/contracts/agent.contract.d.ts +10 -10
  9. package/dist/contracts/agent.contract.d.ts.map +1 -1
  10. package/dist/contracts/agent.contract.js +21 -11
  11. package/dist/contracts/agent.contract.js.map +1 -1
  12. package/dist/contracts/agents.contract.d.ts +41 -27
  13. package/dist/contracts/agents.contract.d.ts.map +1 -1
  14. package/dist/contracts/agents.contract.js +44 -28
  15. package/dist/contracts/agents.contract.js.map +1 -1
  16. package/dist/contracts/approvals.contract.d.ts +3 -3
  17. package/dist/contracts/approvals.contract.js +4 -4
  18. package/dist/contracts/approvals.contract.js.map +1 -1
  19. package/dist/contracts/areas.contract.d.ts +3 -3
  20. package/dist/contracts/areas.contract.d.ts.map +1 -1
  21. package/dist/contracts/areas.contract.js +5 -4
  22. package/dist/contracts/areas.contract.js.map +1 -1
  23. package/dist/contracts/automations.contract.d.ts +11 -11
  24. package/dist/contracts/automations.contract.js +12 -12
  25. package/dist/contracts/automations.contract.js.map +1 -1
  26. package/dist/contracts/capabilities.contract.d.ts +13 -13
  27. package/dist/contracts/capabilities.contract.d.ts.map +1 -1
  28. package/dist/contracts/capabilities.contract.js +18 -14
  29. package/dist/contracts/capabilities.contract.js.map +1 -1
  30. package/dist/contracts/chores.contract.d.ts +3 -3
  31. package/dist/contracts/chores.contract.js +4 -4
  32. package/dist/contracts/chores.contract.js.map +1 -1
  33. package/dist/contracts/ci.contract.d.ts +5 -5
  34. package/dist/contracts/ci.contract.js +6 -6
  35. package/dist/contracts/ci.contract.js.map +1 -1
  36. package/dist/contracts/diff.contract.d.ts +1 -1
  37. package/dist/contracts/diff.contract.js +2 -2
  38. package/dist/contracts/diff.contract.js.map +1 -1
  39. package/dist/contracts/endpoints.contract.d.ts +4 -4
  40. package/dist/contracts/endpoints.contract.js +5 -5
  41. package/dist/contracts/endpoints.contract.js.map +1 -1
  42. package/dist/contracts/exit.contract.d.ts +7 -7
  43. package/dist/contracts/exit.contract.d.ts.map +1 -1
  44. package/dist/contracts/exit.contract.js +9 -8
  45. package/dist/contracts/exit.contract.js.map +1 -1
  46. package/dist/contracts/extensions.contract.d.ts +17 -17
  47. package/dist/contracts/extensions.contract.js +18 -18
  48. package/dist/contracts/extensions.contract.js.map +1 -1
  49. package/dist/contracts/git.contract.d.ts +47 -45
  50. package/dist/contracts/git.contract.d.ts.map +1 -1
  51. package/dist/contracts/git.contract.js +46 -46
  52. package/dist/contracts/git.contract.js.map +1 -1
  53. package/dist/contracts/history.contract.d.ts +4 -4
  54. package/dist/contracts/history.contract.js +5 -5
  55. package/dist/contracts/history.contract.js.map +1 -1
  56. package/dist/contracts/intentic.contract.d.ts +3 -3
  57. package/dist/contracts/intentic.contract.d.ts.map +1 -1
  58. package/dist/contracts/intentic.contract.js +5 -4
  59. package/dist/contracts/intentic.contract.js.map +1 -1
  60. package/dist/contracts/inventory.contract.d.ts +3 -3
  61. package/dist/contracts/inventory.contract.js +4 -4
  62. package/dist/contracts/inventory.contract.js.map +1 -1
  63. package/dist/contracts/issues.contract.d.ts +5 -5
  64. package/dist/contracts/issues.contract.js +6 -6
  65. package/dist/contracts/issues.contract.js.map +1 -1
  66. package/dist/contracts/logs.contract.d.ts +3 -3
  67. package/dist/contracts/logs.contract.d.ts.map +1 -1
  68. package/dist/contracts/logs.contract.js +6 -4
  69. package/dist/contracts/logs.contract.js.map +1 -1
  70. package/dist/contracts/loops.contract.d.ts +6 -6
  71. package/dist/contracts/loops.contract.js +7 -7
  72. package/dist/contracts/loops.contract.js.map +1 -1
  73. package/dist/contracts/netdisk.contract.d.ts +3 -3
  74. package/dist/contracts/netdisk.contract.d.ts.map +1 -1
  75. package/dist/contracts/netdisk.contract.js +5 -4
  76. package/dist/contracts/netdisk.contract.js.map +1 -1
  77. package/dist/contracts/panels.contract.d.ts +3 -3
  78. package/dist/contracts/panels.contract.js +4 -4
  79. package/dist/contracts/panels.contract.js.map +1 -1
  80. package/dist/contracts/personas.contract.d.ts +8 -8
  81. package/dist/contracts/personas.contract.d.ts.map +1 -1
  82. package/dist/contracts/personas.contract.js +10 -9
  83. package/dist/contracts/personas.contract.js.map +1 -1
  84. package/dist/contracts/ports.contract.d.ts +3 -3
  85. package/dist/contracts/ports.contract.d.ts.map +1 -1
  86. package/dist/contracts/ports.contract.js +5 -4
  87. package/dist/contracts/ports.contract.js.map +1 -1
  88. package/dist/contracts/prepush.contract.d.ts +3 -3
  89. package/dist/contracts/prepush.contract.js +4 -4
  90. package/dist/contracts/prepush.contract.js.map +1 -1
  91. package/dist/contracts/providers.contract.d.ts +2 -2
  92. package/dist/contracts/providers.contract.d.ts.map +1 -1
  93. package/dist/contracts/providers.contract.js +5 -3
  94. package/dist/contracts/providers.contract.js.map +1 -1
  95. package/dist/contracts/public.contract.d.ts +3 -3
  96. package/dist/contracts/public.contract.js +4 -4
  97. package/dist/contracts/public.contract.js.map +1 -1
  98. package/dist/contracts/push.contract.d.ts +4 -4
  99. package/dist/contracts/push.contract.d.ts.map +1 -1
  100. package/dist/contracts/push.contract.js +9 -5
  101. package/dist/contracts/push.contract.js.map +1 -1
  102. package/dist/contracts/safety.contract.d.ts +3 -3
  103. package/dist/contracts/safety.contract.js +4 -4
  104. package/dist/contracts/safety.contract.js.map +1 -1
  105. package/dist/contracts/secrets.contract.d.ts +9 -9
  106. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  107. package/dist/contracts/secrets.contract.js +13 -10
  108. package/dist/contracts/secrets.contract.js.map +1 -1
  109. package/dist/contracts/sessions.contract.d.ts +2 -2
  110. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  111. package/dist/contracts/sessions.contract.js +5 -3
  112. package/dist/contracts/sessions.contract.js.map +1 -1
  113. package/dist/contracts/settings.contract.d.ts +11 -9
  114. package/dist/contracts/settings.contract.d.ts.map +1 -1
  115. package/dist/contracts/settings.contract.js +11 -10
  116. package/dist/contracts/settings.contract.js.map +1 -1
  117. package/dist/contracts/share.contract.d.ts +4 -4
  118. package/dist/contracts/share.contract.js +5 -5
  119. package/dist/contracts/share.contract.js.map +1 -1
  120. package/dist/contracts/skills.contract.d.ts +5 -5
  121. package/dist/contracts/skills.contract.js +6 -6
  122. package/dist/contracts/skills.contract.js.map +1 -1
  123. package/dist/contracts/system.contract.d.ts +22 -19
  124. package/dist/contracts/system.contract.d.ts.map +1 -1
  125. package/dist/contracts/system.contract.js +27 -20
  126. package/dist/contracts/system.contract.js.map +1 -1
  127. package/dist/contracts/translator.contract.d.ts +5 -5
  128. package/dist/contracts/translator.contract.js +6 -6
  129. package/dist/contracts/translator.contract.js.map +1 -1
  130. package/dist/contracts/usage.contract.d.ts +4 -4
  131. package/dist/contracts/usage.contract.js +5 -5
  132. package/dist/contracts/usage.contract.js.map +1 -1
  133. package/dist/contracts/vpn.contract.d.ts +4 -4
  134. package/dist/contracts/vpn.contract.d.ts.map +1 -1
  135. package/dist/contracts/vpn.contract.js +6 -5
  136. package/dist/contracts/vpn.contract.js.map +1 -1
  137. package/dist/contracts/workflows.contract.d.ts +9 -9
  138. package/dist/contracts/workflows.contract.js +10 -10
  139. package/dist/contracts/workflows.contract.js.map +1 -1
  140. package/dist/contracts/workspace.contract.d.ts +30 -30
  141. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  142. package/dist/contracts/workspace.contract.js +46 -31
  143. package/dist/contracts/workspace.contract.js.map +1 -1
  144. package/dist/events/land-breakage.d.ts +4 -0
  145. package/dist/events/land-breakage.d.ts.map +1 -0
  146. package/dist/events/land-breakage.js +4 -0
  147. package/dist/events/land-breakage.js.map +1 -0
  148. package/dist/events/system-events.d.ts +2 -0
  149. package/dist/events/system-events.d.ts.map +1 -1
  150. package/dist/index.d.ts +9379 -9350
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.js +13 -1
  153. package/dist/index.js.map +1 -1
  154. package/dist/protocol/procedure-types.d.ts +10 -0
  155. package/dist/protocol/procedure-types.d.ts.map +1 -0
  156. package/dist/protocol/procedure-types.js +2 -0
  157. package/dist/protocol/procedure-types.js.map +1 -0
  158. package/dist/protocol/raw-routes.d.ts +417 -0
  159. package/dist/protocol/raw-routes.d.ts.map +1 -0
  160. package/dist/protocol/raw-routes.js +140 -0
  161. package/dist/protocol/raw-routes.js.map +1 -0
  162. package/dist/protocol/route-meta.d.ts +18 -0
  163. package/dist/protocol/route-meta.d.ts.map +1 -0
  164. package/dist/protocol/route-meta.js +3 -0
  165. package/dist/protocol/route-meta.js.map +1 -0
  166. package/dist/protocol/routes.d.ts +3 -0
  167. package/dist/protocol/routes.d.ts.map +1 -1
  168. package/dist/protocol/routes.js +47 -14
  169. package/dist/protocol/routes.js.map +1 -1
  170. package/dist/schemas/agent.d.ts +33 -0
  171. package/dist/schemas/agent.d.ts.map +1 -1
  172. package/dist/schemas/agent.js +22 -3
  173. package/dist/schemas/agent.js.map +1 -1
  174. package/dist/schemas/agents.d.ts +4 -0
  175. package/dist/schemas/agents.d.ts.map +1 -1
  176. package/dist/schemas/agents.js +4 -0
  177. package/dist/schemas/agents.js.map +1 -1
  178. package/dist/schemas/automations.d.ts +1 -0
  179. package/dist/schemas/automations.d.ts.map +1 -1
  180. package/dist/schemas/devices.d.ts.map +1 -1
  181. package/dist/schemas/devices.js +2 -2
  182. package/dist/schemas/devices.js.map +1 -1
  183. package/dist/schemas/git/git.d.ts +3 -0
  184. package/dist/schemas/git/git.d.ts.map +1 -1
  185. package/dist/schemas/hosts.d.ts +1 -0
  186. package/dist/schemas/hosts.d.ts.map +1 -1
  187. package/dist/schemas/hosts.js +1 -0
  188. package/dist/schemas/hosts.js.map +1 -1
  189. package/dist/schemas/settings.d.ts +1 -0
  190. package/dist/schemas/settings.d.ts.map +1 -1
  191. package/dist/schemas/settings.js +4 -0
  192. package/dist/schemas/settings.js.map +1 -1
  193. package/dist/state/definition.d.ts +4 -0
  194. package/dist/state/definition.d.ts.map +1 -1
  195. package/dist/state/history-state.d.ts.map +1 -1
  196. package/dist/state/history-state.js +2 -12
  197. package/dist/state/history-state.js.map +1 -1
  198. package/dist/state/landed-commit.d.ts +4 -0
  199. package/dist/state/landed-commit.d.ts.map +1 -0
  200. package/dist/state/landed-commit.js +12 -0
  201. package/dist/state/landed-commit.js.map +1 -0
  202. package/package.json +5 -5
  203. package/src/contracts/accounts.contract.ts +7 -7
  204. package/src/contracts/activity.contract.ts +3 -3
  205. package/src/contracts/agent.contract.ts +25 -11
  206. package/src/contracts/agents.contract.ts +48 -30
  207. package/src/contracts/approvals.contract.ts +4 -4
  208. package/src/contracts/areas.contract.ts +5 -4
  209. package/src/contracts/automations.contract.ts +12 -12
  210. package/src/contracts/capabilities.contract.ts +23 -14
  211. package/src/contracts/chores.contract.ts +4 -4
  212. package/src/contracts/ci.contract.ts +6 -6
  213. package/src/contracts/diff.contract.ts +2 -2
  214. package/src/contracts/endpoints.contract.ts +5 -5
  215. package/src/contracts/exit.contract.ts +11 -8
  216. package/src/contracts/extensions.contract.ts +18 -18
  217. package/src/contracts/git.contract.ts +46 -46
  218. package/src/contracts/history.contract.ts +5 -5
  219. package/src/contracts/intentic.contract.ts +5 -4
  220. package/src/contracts/inventory.contract.ts +4 -4
  221. package/src/contracts/issues.contract.ts +6 -6
  222. package/src/contracts/logs.contract.ts +8 -4
  223. package/src/contracts/loops.contract.ts +7 -7
  224. package/src/contracts/netdisk.contract.ts +7 -4
  225. package/src/contracts/panels.contract.ts +4 -4
  226. package/src/contracts/personas.contract.ts +10 -9
  227. package/src/contracts/ports.contract.ts +6 -4
  228. package/src/contracts/prepush.contract.ts +4 -4
  229. package/src/contracts/providers.contract.ts +5 -3
  230. package/src/contracts/public.contract.ts +4 -4
  231. package/src/contracts/push.contract.ts +12 -5
  232. package/src/contracts/safety.contract.ts +4 -4
  233. package/src/contracts/secrets.contract.ts +16 -10
  234. package/src/contracts/sessions.contract.ts +6 -3
  235. package/src/contracts/settings.contract.ts +11 -10
  236. package/src/contracts/share.contract.ts +5 -5
  237. package/src/contracts/skills.contract.ts +6 -6
  238. package/src/contracts/system.contract.ts +32 -20
  239. package/src/contracts/translator.contract.ts +6 -6
  240. package/src/contracts/usage.contract.ts +5 -5
  241. package/src/contracts/vpn.contract.ts +8 -5
  242. package/src/contracts/workflows.contract.ts +10 -10
  243. package/src/contracts/workspace.contract.ts +49 -31
  244. package/src/events/land-breakage.ts +11 -0
  245. package/src/index.ts +23 -1
  246. package/src/models/capability-ledger.test.ts +1 -1
  247. package/src/protocol/procedure-types.ts +24 -0
  248. package/src/protocol/raw-routes.ts +191 -0
  249. package/src/protocol/route-meta.ts +39 -0
  250. package/src/protocol/routes.test.ts +65 -2
  251. package/src/protocol/routes.ts +88 -27
  252. package/src/schemas/agent.test.ts +66 -0
  253. package/src/schemas/agent.ts +184 -154
  254. package/src/schemas/agents.ts +6 -0
  255. package/src/schemas/devices.ts +2 -2
  256. package/src/schemas/hosts.ts +4 -0
  257. package/src/schemas/settings.ts +9 -0
  258. package/src/state/history-state.ts +14 -29
  259. package/src/state/landed-commit.test.ts +18 -0
  260. package/src/state/landed-commit.ts +17 -0
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { SkillBodySchema, SkillDraftSchema, SkillIdSchema, SkillRemoveSchema, SkillsListSchema, SkillSwitchSchema } from "../schemas/settings.js";
3
3
  import { OkSchema } from "../schemas/shared.js";
4
4
 
@@ -8,7 +8,7 @@ import { OkSchema } from "../schemas/shared.js";
8
8
  // together with the text. `read` takes the id in the query, since an id can name an owner and won't fit a path
9
9
  // template.
10
10
  export const skillsContract = {
11
- list: oc
11
+ list: procedure
12
12
  .route({
13
13
  method: "GET",
14
14
  path: "/skills",
@@ -17,7 +17,7 @@ export const skillsContract = {
17
17
  "Every skill available here and whether it is switched on, joined from all the places they come from: the owner's own, the settings, plugins a connection installed, folders inside extensions, and persona kits.",
18
18
  })
19
19
  .output(SkillsListSchema),
20
- read: oc
20
+ read: procedure
21
21
  .route({
22
22
  method: "GET",
23
23
  path: "/skills/read",
@@ -29,7 +29,7 @@ export const skillsContract = {
29
29
  .output(SkillBodySchema),
30
30
  // Upsert by name; renaming saves under a new name and deletes the old. A new skill starts on; rewriting keeps its
31
31
  // switch as it was.
32
- save: oc
32
+ save: procedure
33
33
  .route({
34
34
  method: "POST",
35
35
  path: "/skills",
@@ -39,7 +39,7 @@ export const skillsContract = {
39
39
  })
40
40
  .input(SkillDraftSchema)
41
41
  .output(OkSchema),
42
- switch: oc
42
+ switch: procedure
43
43
  .route({
44
44
  method: "POST",
45
45
  path: "/skills/switch",
@@ -49,7 +49,7 @@ export const skillsContract = {
49
49
  })
50
50
  .input(SkillSwitchSchema)
51
51
  .output(OkSchema),
52
- remove: oc
52
+ remove: procedure
53
53
  .route({
54
54
  method: "POST",
55
55
  path: "/skills/remove",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { streamOf } from "../protocol/routes.js";
3
3
  import { z } from "zod";
4
4
  import { SessionTranscriptSchema } from "../events/transcript.js";
@@ -27,11 +27,14 @@ import {
27
27
  } from "../schemas/terminal.js";
28
28
  import { UsageSummarySchema } from "../schemas/providers/usage.js";
29
29
 
30
+ // The box itself (terminals, devices, sessions, spend), which no control token reaches whatever the floor.
31
+ const systemRoute = procedure.meta({ control: "never" });
32
+
30
33
  // Sandbox status/identity, the long-lived liveness stream, and the connect-token-relayed host tunnel. `events`
31
34
  // interleaves heartbeats, workspaceChanged batches and presence snapshots until the request aborts. `clientId` is this
32
35
  // tab's presence key; omitting it means never joining the roster.
33
36
  export const systemContract = {
34
- info: oc
37
+ info: procedure
35
38
  .route({
36
39
  method: "GET",
37
40
  path: "/info",
@@ -39,9 +42,10 @@ export const systemContract = {
39
42
  description:
40
43
  "The sandbox's own identity and state: which workspace it holds, which image it runs, what it is called, and the list of calls it actually implements. Start here, because a browser is routinely newer than the sandbox it is talking to and this is how it finds out what is there.",
41
44
  })
45
+ .meta({ guest: true })
42
46
  .output(InfoSchema),
43
47
  // Own route, not a field on /info: it goes stale on a manifest changing on disk, not on identity changing.
44
- manifestProblems: oc
48
+ manifestProblems: systemRoute
45
49
  .route({
46
50
  method: "GET",
47
51
  path: "/system/manifest-problems",
@@ -51,7 +55,7 @@ export const systemContract = {
51
55
  })
52
56
  .output(ManifestProblemsSchema),
53
57
  // Removes or renames only a key, never a value; writes queue through the owning store, not racing a live save.
54
- repairManifest: oc
58
+ repairManifest: systemRoute
55
59
  .route({
56
60
  method: "POST",
57
61
  path: "/system/manifest-problems/repair",
@@ -62,7 +66,7 @@ export const systemContract = {
62
66
  .input(ManifestRepairSchema)
63
67
  .output(OkSchema),
64
68
  // Trades a verified bearer or unexpired session for a fresh daemon session; calling it again renews it.
65
- session: oc
69
+ session: systemRoute
66
70
  .route({
67
71
  method: "POST",
68
72
  path: "/system/session",
@@ -70,8 +74,10 @@ export const systemContract = {
70
74
  description:
71
75
  "Exchanges a verified sign-in, or a session that has not expired yet, for a fresh session the daemon minted. That session is the credential every other call carries, and calling this again with a live one renews it.",
72
76
  })
77
+ // Staying signed in and on the roster is identity, not power, and needs nothing the boot chain builds.
78
+ .meta({ beforeBoot: true, floor: "viewer", guest: true })
73
79
  .output(DaemonSessionSchema),
74
- events: oc
80
+ events: procedure
75
81
  .route({
76
82
  method: "GET",
77
83
  path: "/events",
@@ -79,10 +85,11 @@ export const systemContract = {
79
85
  description:
80
86
  "A stream held open for as long as you want it, carrying heartbeats so a caller notices the sandbox dying at once, batches of file changes so a tree or an editor can refresh itself, and the roster of who else is looking. Give it an id for this connection to appear in that roster; leave it out and you watch without being seen.",
81
87
  })
88
+ .meta({ beforeBoot: true, stream: true, guest: true })
82
89
  .input(z.object({ clientId: z.string().optional() }))
83
90
  .output(streamOf(SystemEventSchema)),
84
91
  // A tab's activity self-report (view/session/file/idle), fanned back out to every member on /events.
85
- presence: oc
92
+ presence: systemRoute
86
93
  .route({
87
94
  method: "POST",
88
95
  path: "/system/presence",
@@ -90,19 +97,22 @@ export const systemContract = {
90
97
  description:
91
98
  "Reports which view, conversation or file this connection is on, or that it has gone idle. The daemon fans it back out on the event stream so everyone else's roster updates.",
92
99
  })
100
+ .meta({ beforeBoot: true, floor: "viewer", guest: true })
93
101
  .input(PresenceReportSchema)
94
102
  .output(OkSchema),
95
103
  // Per-account token/cost totals, aggregated from the activity log's turn.completed events.
96
- usage: oc
104
+ usage: systemRoute
97
105
  .route({
98
106
  method: "GET",
99
107
  path: "/system/usage",
100
108
  summary: "What has been spent",
101
109
  description: "Token and cost totals per account, added up from the record of every finished turn.",
102
110
  })
111
+ // Spend is the operator's reading, not the audience's.
112
+ .meta({ floor: "maintainer" })
103
113
  .output(UsageSummarySchema),
104
114
  // Measured per request and never in the background: a sandbox nobody is asking pays nothing for this route.
105
- metrics: oc
115
+ metrics: systemRoute
106
116
  .route({
107
117
  method: "GET",
108
118
  path: "/system/metrics",
@@ -112,7 +122,7 @@ export const systemContract = {
112
122
  })
113
123
  .output(SandboxMetricsSchema),
114
124
  // Control plane only; live I/O is /system/terminal WebSocket, exempt from the Bearer auth these routes take.
115
- terminals: oc
125
+ terminals: systemRoute
116
126
  .route({
117
127
  method: "GET",
118
128
  path: "/system/terminals",
@@ -120,8 +130,10 @@ export const systemContract = {
120
130
  description:
121
131
  "The terminal sessions this sandbox is holding, which is what a terminal panel rebuilds its tabs from after a reload. The live typing and output run over a separate socket; this is the list.",
122
132
  })
133
+ // Lists tmux and the supervisor, neither built by the boot chain, for a surface on screen meanwhile.
134
+ .meta({ beforeBoot: true })
123
135
  .output(TerminalsListSchema),
124
- killTerminal: oc
136
+ killTerminal: systemRoute
125
137
  .route({
126
138
  method: "DELETE",
127
139
  path: "/system/terminals/{name}",
@@ -131,7 +143,7 @@ export const systemContract = {
131
143
  .input(TerminalNameParamSchema)
132
144
  .output(OkSchema),
133
145
  // Scrollback as selectable text; the live view is a tmux alternate screen, with nothing in the page to select.
134
- terminalScrollback: oc
146
+ terminalScrollback: systemRoute
135
147
  .route({
136
148
  method: "GET",
137
149
  path: "/system/terminals/{name}/scrollback",
@@ -142,7 +154,7 @@ export const systemContract = {
142
154
  .input(TerminalScrollbackQuerySchema)
143
155
  .output(TerminalScrollbackSchema),
144
156
  // Control plane like `terminals`; frames stream separately. `closeBrowser` fails the next call as crashed.
145
- browsers: oc
157
+ browsers: systemRoute
146
158
  .route({
147
159
  method: "GET",
148
160
  path: "/system/browsers",
@@ -151,7 +163,7 @@ export const systemContract = {
151
163
  "Every browser a conversation currently has running and the pages inside each one. The picture of what they are showing comes over a separate socket; this is the roster.",
152
164
  })
153
165
  .output(BrowsersListSchema),
154
- closeBrowser: oc
166
+ closeBrowser: systemRoute
155
167
  .route({
156
168
  method: "DELETE",
157
169
  path: "/system/browsers/{name}",
@@ -162,7 +174,7 @@ export const systemContract = {
162
174
  .input(BrowserNameParamSchema)
163
175
  .output(OkSchema),
164
176
  // SDK subagents and delegated runs alike; watched via transcript, not a socket, live then from stored history.
165
- subagents: oc
177
+ subagents: systemRoute
166
178
  .route({
167
179
  method: "GET",
168
180
  path: "/system/subagents",
@@ -171,7 +183,7 @@ export const systemContract = {
171
183
  "Every subagent and child agent this sandbox's conversations have delegated work to, whichever tool started it, with what each one is doing.",
172
184
  })
173
185
  .output(SubagentsListSchema),
174
- subagentTranscript: oc
186
+ subagentTranscript: systemRoute
175
187
  .route({
176
188
  method: "GET",
177
189
  path: "/system/subagents/{id}/transcript",
@@ -184,7 +196,7 @@ export const systemContract = {
184
196
  // On the contract, not a hand-written route beside it: this payload is what every "do it out there" button is
185
197
  // gated on, so its shape has to be fingerprinted like any other, or a daemon older than the app disagrees about
186
198
  // it silently and the buttons just stop being drawn.
187
- devices: oc
199
+ devices: systemRoute
188
200
  .route({
189
201
  method: "GET",
190
202
  path: "/system/devices",
@@ -194,7 +206,7 @@ export const systemContract = {
194
206
  })
195
207
  .output(DevicesListSchema),
196
208
  // One stream for every op; the daemon adds no judgment, a refusal is the machine's own `error` line.
197
- manageDeviceSandbox: oc
209
+ manageDeviceSandbox: systemRoute
198
210
  .route({
199
211
  method: "POST",
200
212
  path: "/system/devices/{id}/sandboxes/{slug}",
@@ -205,7 +217,7 @@ export const systemContract = {
205
217
  .input(DeviceSandboxFlowInputSchema)
206
218
  .output(streamOf(DeviceFlowLineSchema)),
207
219
  // Closed set of actions; the daemon builds the command line, not the caller. One sentence is the whole answer.
208
- runDeviceCommand: oc
220
+ runDeviceCommand: systemRoute
209
221
  .route({
210
222
  method: "POST",
211
223
  path: "/system/devices/{id}/commands/{command}",
@@ -216,7 +228,7 @@ export const systemContract = {
216
228
  .input(DeviceCommandInputSchema)
217
229
  .output(DeviceCommandResultSchema),
218
230
  // The stream usually ends without a frame; a bare stop means success, the device's version confirms it later.
219
- runDeviceAgentFlow: oc
231
+ runDeviceAgentFlow: systemRoute
220
232
  .route({
221
233
  method: "POST",
222
234
  path: "/system/devices/{id}/agent/{op}",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { z } from "zod";
3
3
  import { TranslatorAccountsSchema } from "../schemas/providers/plan-limits.js";
4
4
  import { TranslatorCompleteSchema, TranslatorStartSchema, TranslatorStatusSchema } from "../schemas/providers/provider-oauth.js";
@@ -15,7 +15,7 @@ import { OkSchema } from "../schemas/shared.js";
15
15
  // URL this sandbox can't receive, so `complete` hands the landing URL to the translator. `connect.flow` tells the
16
16
  // card which mechanic it received without inferring it from whether an optional device code happened to exist.
17
17
  export const translatorContract = {
18
- accounts: oc
18
+ accounts: procedure
19
19
  .route({
20
20
  method: "GET",
21
21
  path: "/translator/accounts",
@@ -24,7 +24,7 @@ export const translatorContract = {
24
24
  "What is signed in per provider. Each provider can hold several accounts at once, and the translator spreads work across them.",
25
25
  })
26
26
  .output(TranslatorAccountsSchema),
27
- connect: oc
27
+ connect: procedure
28
28
  .route({
29
29
  method: "POST",
30
30
  path: "/translator/{provider}/connect",
@@ -34,7 +34,7 @@ export const translatorContract = {
34
34
  })
35
35
  .input(z.object({ provider: KeyedProviderSchema }))
36
36
  .output(TranslatorStartSchema),
37
- status: oc
37
+ status: procedure
38
38
  .route({
39
39
  method: "GET",
40
40
  path: "/translator/{provider}/connect",
@@ -44,7 +44,7 @@ export const translatorContract = {
44
44
  })
45
45
  .input(z.object({ provider: KeyedProviderSchema, state: z.string().min(1) }))
46
46
  .output(TranslatorStatusSchema),
47
- complete: oc
47
+ complete: procedure
48
48
  .route({
49
49
  method: "POST",
50
50
  path: "/translator/{provider}/complete",
@@ -54,7 +54,7 @@ export const translatorContract = {
54
54
  })
55
55
  .input(TranslatorCompleteSchema)
56
56
  .output(OkSchema),
57
- disconnect: oc
57
+ disconnect: procedure
58
58
  .route({
59
59
  method: "POST",
60
60
  path: "/translator/{provider}/disconnect",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { z } from "zod";
3
3
  import { LimitResetClaimSchema, LimitResetStatusSchema } from "../schemas/providers/plan-limits.js";
4
4
  import { DayWindowQuerySchema, UsageRollupSchema } from "../schemas/providers/usage.js";
@@ -28,7 +28,7 @@ export type PlanLimitsHeld = PlanLimitsRefreshed["held"][number];
28
28
  // Durable spend ledger, read-only over the wire; rows are appended daemon-side at turn end.
29
29
  // `rollup` groups by day, provider, account and model, so every cost panel re-projects from this one answer.
30
30
  export const usageContract = {
31
- rollup: oc
31
+ rollup: procedure
32
32
  .route({
33
33
  method: "GET",
34
34
  path: "/usage/rollup",
@@ -39,7 +39,7 @@ export const usageContract = {
39
39
  .input(DayWindowQuerySchema)
40
40
  .output(UsageRollupSchema),
41
41
  // Re-measures every account's plan limits on request; readings also arrive via /events and account lists otherwise.
42
- refreshPlanLimits: oc
42
+ refreshPlanLimits: procedure
43
43
  .route({
44
44
  method: "POST",
45
45
  path: "/usage/plan-limits/refresh",
@@ -52,7 +52,7 @@ export const usageContract = {
52
52
  // Asked, not polled: the provider only evaluates this when told the account is at the wall, and the answer isn't
53
53
  // cached.
54
54
  // Answers `available: false` rather than failing when the account has no such mechanism.
55
- limitReset: oc
55
+ limitReset: procedure
56
56
  .route({
57
57
  method: "GET",
58
58
  path: "/usage/limit-reset/{account}",
@@ -62,7 +62,7 @@ export const usageContract = {
62
62
  })
63
63
  .input(z.object({ account: z.string().min(1).describe("Which account.") }))
64
64
  .output(LimitResetStatusSchema),
65
- claimLimitReset: oc
65
+ claimLimitReset: procedure
66
66
  .route({
67
67
  method: "POST",
68
68
  path: "/usage/limit-reset/{account}/claim",
@@ -1,16 +1,19 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { streamOf } from "../protocol/routes.js";
3
3
  import { IntenticLineSchema } from "../events/system-events.js";
4
4
  import { OkSchema } from "../schemas/shared.js";
5
5
  import { ForticlientImportInputSchema, ForticlientImportSchema, VpnConnectInputSchema, VpnIdParamSchema, VpnListSchema } from "../schemas/vpn.js";
6
6
 
7
+ // The agent's `vpn` CLI dials and drops these on the agent token; a control token never reaches them.
8
+ const vpnRoute = procedure.meta({ agent: true, control: "never" });
9
+
7
10
  // A VPN is added as a `vpn` capability; connecting and dropping it happen through the routes here, called by both the
8
11
  // operator UI and the agent's `vpn` CLI.
9
12
  // Every route reads tunnel state from the OS, not daemon memory, so a shell-dropped tunnel and a UI-dropped one are the
10
13
  // same event across a restart.
11
14
  export const vpnContract = {
12
15
  // Every configured VPN with its live link state; feeds the VPN card, rail indicator, and `vpn list`.
13
- list: oc
16
+ list: vpnRoute
14
17
  .route({
15
18
  method: "GET",
16
19
  path: "/vpn",
@@ -20,7 +23,7 @@ export const vpnContract = {
20
23
  })
21
24
  .output(VpnListSchema),
22
25
  // Dials a stored VPN, streaming auth and routing progress; idempotent, an already-up tunnel is just reported.
23
- connect: oc
26
+ connect: vpnRoute
24
27
  .route({
25
28
  method: "POST",
26
29
  path: "/vpn/{id}/connect",
@@ -31,7 +34,7 @@ export const vpnContract = {
31
34
  .input(VpnConnectInputSchema)
32
35
  .output(streamOf(IntenticLineSchema)),
33
36
  // Drops a tunnel; tolerates one already down, since the contract is "not up," not "it was up."
34
- disconnect: oc
37
+ disconnect: vpnRoute
35
38
  .route({
36
39
  method: "POST",
37
40
  path: "/vpn/{id}/disconnect",
@@ -41,7 +44,7 @@ export const vpnContract = {
41
44
  .input(VpnIdParamSchema)
42
45
  .output(OkSchema),
43
46
  // Parses an exported FortiClient config into addable connections a user can pick instead of retyping.
44
- importForticlient: oc
47
+ importForticlient: vpnRoute
45
48
  .route({
46
49
  method: "POST",
47
50
  path: "/vpn/import-forticlient",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { DoorTokenSchema, OkSchema } from "../schemas/shared.js";
3
3
  import {
4
4
  WorkflowIdParamSchema,
@@ -17,7 +17,7 @@ import {
17
17
  // `run` acks with the run as recorded and executes detached, the same contract every turn-starting route here keeps.
18
18
  export const workflowsContract = {
19
19
  // Every saved workflow with its run history, newest first; a never-run workflow isn't an error case.
20
- list: oc
20
+ list: procedure
21
21
  .route({
22
22
  method: "GET",
23
23
  path: "/workflows",
@@ -29,7 +29,7 @@ export const workflowsContract = {
29
29
  // Create or replace, with the operation explicit so an id collision can't turn a create into an overwrite.
30
30
  // Refuses a graph that can't run (a cycle, an unmet `needs`, a step with no completion signal), in the same words
31
31
  // the design-time validator (workflowFaults) uses.
32
- save: oc
32
+ save: procedure
33
33
  .route({
34
34
  method: "POST",
35
35
  path: "/workflows",
@@ -40,7 +40,7 @@ export const workflowsContract = {
40
40
  .input(WorkflowSaveSchema)
41
41
  .output(WorkflowSavedSchema),
42
42
  // Mints a new gate credential; every pipeline holding the old URL stops working the moment this answers.
43
- rotateGateToken: oc
43
+ rotateGateToken: procedure
44
44
  .route({
45
45
  method: "POST",
46
46
  path: "/workflows/{id}/gate/rotate",
@@ -51,7 +51,7 @@ export const workflowsContract = {
51
51
  .input(WorkflowIdParamSchema)
52
52
  .output(DoorTokenSchema),
53
53
  // Deleting a workflow doesn't stop or erase an in-flight run: a run snapshots its definition at start.
54
- remove: oc
54
+ remove: procedure
55
55
  .route({
56
56
  method: "DELETE",
57
57
  path: "/workflows/{id}",
@@ -64,7 +64,7 @@ export const workflowsContract = {
64
64
  // Starts a run, optionally with a request appended to every step's own prompt; each step is recorded `pending` up
65
65
  // front so the graph is complete from the first frame.
66
66
  // Multiple runs of one workflow can be in flight at once; each derives its own conversation ids, so none collide.
67
- run: oc
67
+ run: procedure
68
68
  .route({
69
69
  method: "POST",
70
70
  path: "/workflows/{id}/run",
@@ -75,7 +75,7 @@ export const workflowsContract = {
75
75
  .input(WorkflowRunStartSchema)
76
76
  .output(WorkflowRunSchema),
77
77
  // Every run across every workflow, newest first; the only place a deleted workflow's runs are still reachable.
78
- runs: oc
78
+ runs: procedure
79
79
  .route({
80
80
  method: "GET",
81
81
  path: "/workflows/runs",
@@ -87,7 +87,7 @@ export const workflowsContract = {
87
87
  // Cuts off in-flight steps where they stand, aborting their turns like /agent/stop; not the graceful
88
88
  // finish-the-iteration stop a loop performs, since a step is a whole agent turn.
89
89
  // Always ends the run, including one left `running` by a daemon that was replaced mid-flight.
90
- stopRun: oc
90
+ stopRun: procedure
91
91
  .route({
92
92
  method: "POST",
93
93
  path: "/workflows/runs/{runId}/stop",
@@ -100,7 +100,7 @@ export const workflowsContract = {
100
100
  // Ends a run's board presence, the run's half of `agents.archive`: nothing is lost, checkouts are reclaimed, and
101
101
  // `unarchiveRun` reverses it. Refused while the run is going.
102
102
  // Archives every step that ran along with it, since a step has no card of its own; the run's row stands for it.
103
- archiveRun: oc
103
+ archiveRun: procedure
104
104
  .route({
105
105
  method: "POST",
106
106
  path: "/workflows/runs/{runId}/archive",
@@ -111,7 +111,7 @@ export const workflowsContract = {
111
111
  .input(WorkflowRunIdParamSchema)
112
112
  .output(OkSchema),
113
113
  // Inverse of archiveRun: puts an archived run and its sessions back on the board.
114
- unarchiveRun: oc
114
+ unarchiveRun: procedure
115
115
  .route({
116
116
  method: "POST",
117
117
  path: "/workflows/runs/{runId}/unarchive",