@capybara-hq/kernel 0.1.0-rc.12 → 0.1.0-rc.14

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 (267) hide show
  1. package/dist/admin/admin.schemas.d.ts +13 -0
  2. package/dist/agents/agent-lookup.d.ts +5 -0
  3. package/dist/agents/agent-lookup.js +15 -0
  4. package/dist/background/background.module.js +2 -2
  5. package/dist/background/launch-lock.d.ts +1 -1
  6. package/dist/background/launch-lock.js +1 -1
  7. package/dist/background/poll.job.d.ts +2 -2
  8. package/dist/background/poll.job.js +10 -10
  9. package/dist/background/stop.d.ts +1 -1
  10. package/dist/background/stop.js +3 -3
  11. package/dist/background/store.d.ts +5 -5
  12. package/dist/background/store.js +5 -5
  13. package/dist/background/tasks.service.d.ts +6 -6
  14. package/dist/background/tasks.service.js +13 -13
  15. package/dist/catalog/admin-catalog.controller.d.ts +13 -2
  16. package/dist/catalog/admin-catalog.controller.js +24 -3
  17. package/dist/catalog/admin-catalog.schemas.d.ts +10 -0
  18. package/dist/catalog/admin-catalog.schemas.js +7 -0
  19. package/dist/catalog/catalog-content.d.ts +9 -1
  20. package/dist/catalog/catalog-content.js +2 -1
  21. package/dist/catalog/catalog-files.d.ts +3 -2
  22. package/dist/catalog/catalog-files.js +8 -5
  23. package/dist/catalog/component-scope.service.d.ts +14 -1
  24. package/dist/catalog/component-scope.service.js +12 -2
  25. package/dist/catalog/marketplaces.service.d.ts +1 -1
  26. package/dist/catalog/org-catalog.controller.d.ts +5 -4
  27. package/dist/catalog/org-catalog.controller.js +5 -4
  28. package/dist/catalog/org-catalog.schemas.d.ts +18 -2
  29. package/dist/catalog/org-catalog.schemas.js +16 -2
  30. package/dist/catalog/org-catalog.service.js +8 -2
  31. package/dist/catalog/plugin-import.js +1 -1
  32. package/dist/catalog/plugin-package.js +37 -9
  33. package/dist/catalog/plugin-upgrade.d.ts +15 -1
  34. package/dist/catalog/plugin-upgrade.js +18 -5
  35. package/dist/channels/channels.module.js +2 -2
  36. package/dist/channels/connections.controller.d.ts +1 -1
  37. package/dist/channels/connections.controller.js +1 -1
  38. package/dist/channels/connections.service.d.ts +22 -5
  39. package/dist/channels/connections.service.js +56 -10
  40. package/dist/channels/inbound.d.ts +8 -8
  41. package/dist/channels/inbound.js +31 -31
  42. package/dist/channels/phrases.d.ts +27 -27
  43. package/dist/channels/phrases.js +27 -27
  44. package/dist/channels/webhook.d.ts +21 -1
  45. package/dist/channels/webhook.js +39 -4
  46. package/dist/config/docs.js +1 -1
  47. package/dist/config/schema.d.ts +2 -2
  48. package/dist/config/schema.js +21 -21
  49. package/dist/conversations/conversations.controller.d.ts +11 -11
  50. package/dist/conversations/conversations.controller.js +15 -15
  51. package/dist/conversations/conversations.module.d.ts +1 -1
  52. package/dist/conversations/conversations.module.js +7 -7
  53. package/dist/conversations/conversations.schemas.js +1 -1
  54. package/dist/conversations/conversations.service.d.ts +14 -14
  55. package/dist/conversations/conversations.service.js +19 -19
  56. package/dist/conversations/{environment-status.d.ts → device-status.d.ts} +9 -9
  57. package/dist/conversations/{environment-status.js → device-status.js} +18 -18
  58. package/dist/conversations/event-log.d.ts +1 -1
  59. package/dist/conversations/event-log.js +1 -1
  60. package/dist/conversations/events.d.ts +1 -1
  61. package/dist/conversations/events.js +2 -2
  62. package/dist/ctx/create-ctx.d.ts +26 -3
  63. package/dist/ctx/create-ctx.js +134 -26
  64. package/dist/db/kernel-schema.d.ts +37 -25
  65. package/dist/{environments → devices}/access.d.ts +19 -19
  66. package/dist/{environments → devices}/access.js +28 -28
  67. package/dist/devices/conversation-devices.d.ts +75 -0
  68. package/dist/{environments/conversation-environments.js → devices/conversation-devices.js} +71 -72
  69. package/dist/devices/devices.controller.d.ts +36 -0
  70. package/dist/{environments/environments.controller.js → devices/devices.controller.js} +37 -37
  71. package/dist/devices/devices.module.d.ts +5 -13
  72. package/dist/devices/devices.module.js +16 -29
  73. package/dist/devices/devices.schemas.d.ts +3 -0
  74. package/dist/devices/devices.schemas.js +14 -0
  75. package/dist/{environments/environments.service.d.ts → devices/devices.service.d.ts} +70 -70
  76. package/dist/{environments/environments.service.js → devices/devices.service.js} +122 -122
  77. package/dist/devices/dto.d.ts +13 -54
  78. package/dist/devices/dto.js +7 -39
  79. package/dist/devices/label.d.ts +11 -0
  80. package/dist/{environments → devices}/label.js +7 -7
  81. package/dist/{environments → devices}/legacy-cleanup.job.d.ts +3 -3
  82. package/dist/{environments → devices}/legacy-cleanup.job.js +3 -3
  83. package/dist/errors.d.ts +29 -25
  84. package/dist/errors.js +29 -25
  85. package/dist/evals/recorded-tools.d.ts +2 -2
  86. package/dist/evals/recorded-tools.js +6 -6
  87. package/dist/extensions/admin-ops.js +1 -0
  88. package/dist/extensions/admin-view.js +2 -0
  89. package/dist/extensions/effective-config.d.ts +6 -0
  90. package/dist/extensions/effective-config.js +18 -7
  91. package/dist/extensions/guide-places.d.ts +66 -0
  92. package/dist/extensions/guide-places.js +152 -0
  93. package/dist/extensions/host.d.ts +13 -2
  94. package/dist/extensions/host.js +27 -6
  95. package/dist/extensions/instance.d.ts +17 -2
  96. package/dist/extensions/instance.js +21 -0
  97. package/dist/extensions/ledger.d.ts +1 -1
  98. package/dist/extensions/permission-set.d.ts +16 -2
  99. package/dist/extensions/permission-set.js +17 -3
  100. package/dist/extensions/permission-view.d.ts +10 -1
  101. package/dist/extensions/plugin-guides.d.ts +207 -54
  102. package/dist/extensions/plugin-guides.js +436 -165
  103. package/dist/files/previewers.d.ts +1 -1
  104. package/dist/files/previewers.js +1 -1
  105. package/dist/http/api.module.js +16 -6
  106. package/dist/http/gateway-routes.d.ts +1 -1
  107. package/dist/http/gateway-routes.js +1 -1
  108. package/dist/identity/settings.d.ts +32 -0
  109. package/dist/identity/settings.js +26 -2
  110. package/dist/infra/config/kernel-config.service.js +4 -4
  111. package/dist/infra/lock/lock.service.d.ts +8 -0
  112. package/dist/infra/lock/lock.service.js +27 -0
  113. package/dist/infra/throttler/named-throttlers.d.ts +4 -1
  114. package/dist/infra/throttler/named-throttlers.js +16 -1
  115. package/dist/infra/throttler/throttler.guard.js +1 -1
  116. package/dist/kernel.module.js +3 -3
  117. package/dist/{devices → local-devices}/device-auth.controller.d.ts +6 -6
  118. package/dist/{devices → local-devices}/device-auth.controller.js +5 -5
  119. package/dist/{devices → local-devices}/device-auth.d.ts +20 -20
  120. package/dist/{devices → local-devices}/device-auth.js +51 -53
  121. package/dist/local-devices/device-auth.module.d.ts +7 -0
  122. package/dist/{devices → local-devices}/device-auth.module.js +5 -5
  123. package/dist/{devices → local-devices}/device-routes.d.ts +3 -3
  124. package/dist/{devices → local-devices}/device-routes.js +2 -2
  125. package/dist/local-devices/dto.d.ts +66 -0
  126. package/dist/local-devices/dto.js +44 -0
  127. package/dist/{devices → local-devices}/keys.d.ts +11 -11
  128. package/dist/{devices → local-devices}/keys.js +11 -11
  129. package/dist/{devices/device-gateway.d.ts → local-devices/local-device-gateway.d.ts} +14 -14
  130. package/dist/{devices/device-gateway.js → local-devices/local-device-gateway.js} +44 -44
  131. package/dist/{devices/device-provider.d.ts → local-devices/local-device-provider.d.ts} +15 -15
  132. package/dist/{devices/device-provider.js → local-devices/local-device-provider.js} +23 -23
  133. package/dist/local-devices/local-devices.module.d.ts +16 -0
  134. package/dist/local-devices/local-devices.module.js +44 -0
  135. package/dist/{devices → local-devices}/machines.d.ts +26 -26
  136. package/dist/{devices → local-devices}/machines.js +71 -71
  137. package/dist/{devices → local-devices}/relay.d.ts +15 -15
  138. package/dist/{devices → local-devices}/relay.js +55 -55
  139. package/dist/{devices → local-devices}/targets.d.ts +8 -8
  140. package/dist/{devices → local-devices}/targets.js +14 -14
  141. package/dist/orgs/offboarding.d.ts +6 -6
  142. package/dist/orgs/offboarding.js +12 -12
  143. package/dist/orgs/settings.service.d.ts +28 -0
  144. package/dist/orgs/settings.service.js +20 -1
  145. package/dist/overrides.d.ts +3 -1
  146. package/dist/overrides.js +2 -0
  147. package/dist/platform/exclusions.js +48 -8
  148. package/dist/platform/operation.js +10 -2
  149. package/dist/platform/ops/admin.ops.js +8 -2
  150. package/dist/platform/ops/connectors.ops.js +2 -0
  151. package/dist/platform/ops/conversations.ops.d.ts +3 -3
  152. package/dist/platform/ops/conversations.ops.js +9 -9
  153. package/dist/platform/ops/devices.ops.d.ts +26 -0
  154. package/dist/platform/ops/devices.ops.js +311 -0
  155. package/dist/platform/ops/org-settings.ops.js +2 -2
  156. package/dist/platform/ops/orgs.ops.js +1 -0
  157. package/dist/platform/ops/setup.ops.d.ts +24 -0
  158. package/dist/platform/ops/setup.ops.js +212 -0
  159. package/dist/platform/ops/ui.ops.d.ts +8 -0
  160. package/dist/platform/ops/ui.ops.js +41 -0
  161. package/dist/platform/platform-ops.module.d.ts +4 -2
  162. package/dist/platform/platform-ops.module.js +13 -5
  163. package/dist/platform/route-schemas.js +11 -3
  164. package/dist/roles/gateway-role.d.ts +3 -3
  165. package/dist/roles/gateway-role.js +4 -4
  166. package/dist/roles/gateway.module.d.ts +1 -1
  167. package/dist/roles/gateway.module.js +5 -5
  168. package/dist/roles/worker.module.js +1 -1
  169. package/dist/runtime/context/build.d.ts +1 -1
  170. package/dist/runtime/context/build.js +6 -6
  171. package/dist/runtime/context/compaction.js +1 -1
  172. package/dist/runtime/context/{environment-paths.d.ts → device-paths.d.ts} +11 -11
  173. package/dist/runtime/context/{environment-paths.js → device-paths.js} +13 -13
  174. package/dist/runtime/maintenance.d.ts +1 -1
  175. package/dist/sandbox/jobs.d.ts +13 -13
  176. package/dist/sandbox/jobs.js +20 -20
  177. package/dist/sandbox/leases.d.ts +9 -9
  178. package/dist/sandbox/leases.js +14 -14
  179. package/dist/sandbox/providers.d.ts +8 -8
  180. package/dist/sandbox/providers.js +8 -8
  181. package/dist/sandbox/sandbox.module.d.ts +1 -1
  182. package/dist/sandbox/sandbox.module.js +1 -1
  183. package/dist/sandbox/sandbox.service.d.ts +76 -76
  184. package/dist/sandbox/sandbox.service.js +230 -230
  185. package/dist/setup/kernel-checks.d.ts +91 -0
  186. package/dist/setup/kernel-checks.js +295 -0
  187. package/dist/setup/oauth-token-probe.d.ts +47 -0
  188. package/dist/setup/oauth-token-probe.js +108 -0
  189. package/dist/setup/redact-check.d.ts +18 -0
  190. package/dist/setup/redact-check.js +46 -0
  191. package/dist/setup/setup-check-registry.d.ts +86 -0
  192. package/dist/setup/setup-check-registry.js +75 -0
  193. package/dist/setup/setup-checks.controller.d.ts +28 -0
  194. package/dist/setup/setup-checks.controller.js +78 -0
  195. package/dist/setup/setup-checks.schemas.d.ts +38 -0
  196. package/dist/setup/setup-checks.schemas.js +43 -0
  197. package/dist/setup/setup-checks.service.d.ts +144 -0
  198. package/dist/setup/setup-checks.service.js +683 -0
  199. package/dist/setup/setup-guides.controller.d.ts +18 -0
  200. package/dist/setup/setup-guides.controller.js +48 -0
  201. package/dist/setup/setup-guides.schemas.d.ts +10 -0
  202. package/dist/setup/setup-guides.schemas.js +6 -0
  203. package/dist/setup/setup-guides.service.d.ts +126 -0
  204. package/dist/setup/setup-guides.service.js +315 -0
  205. package/dist/setup/setup.module.d.ts +8 -0
  206. package/dist/setup/setup.module.js +31 -0
  207. package/dist/tools/builtins/builtin-tools.d.ts +2 -2
  208. package/dist/tools/builtins/builtin-tools.js +5 -5
  209. package/dist/tools/builtins/platform.js +1 -1
  210. package/dist/tools/builtins/sandbox/bash.js +6 -6
  211. package/dist/tools/builtins/sandbox/common.d.ts +25 -25
  212. package/dist/tools/builtins/sandbox/common.js +51 -51
  213. package/dist/tools/builtins/sandbox/edit.js +2 -2
  214. package/dist/tools/builtins/sandbox/index.d.ts +1 -1
  215. package/dist/tools/builtins/sandbox/index.js +1 -1
  216. package/dist/tools/builtins/sandbox/task-output.d.ts +6 -6
  217. package/dist/tools/builtins/sandbox/task-output.js +10 -10
  218. package/dist/tools/builtins/sandbox/task-stop.js +2 -2
  219. package/dist/tools/builtins/sandbox/write.js +2 -2
  220. package/dist/tools/builtins/skill-load.d.ts +1 -1
  221. package/dist/tools/builtins/skill-load.js +2 -2
  222. package/dist/tools/connectors.controller.d.ts +28 -11
  223. package/dist/tools/connectors.controller.js +49 -14
  224. package/dist/tools/connectors.schemas.d.ts +4 -0
  225. package/dist/tools/connectors.schemas.js +4 -0
  226. package/dist/tools/connectors.service.d.ts +30 -2
  227. package/dist/tools/connectors.service.js +98 -3
  228. package/dist/tools/credentials.d.ts +20 -0
  229. package/dist/tools/credentials.js +90 -1
  230. package/dist/tools/oauth/tokens.d.ts +20 -0
  231. package/dist/tools/oauth/tokens.js +49 -24
  232. package/dist/tools/pipeline.js +4 -3
  233. package/dist/tools/registry.d.ts +2 -2
  234. package/dist/tools/tools.module.js +3 -3
  235. package/dist/ui/admin-ui.controller.d.ts +56 -0
  236. package/dist/ui/admin-ui.controller.js +192 -0
  237. package/dist/ui/arrangement.d.ts +74 -0
  238. package/dist/ui/arrangement.js +98 -0
  239. package/dist/ui/embed-token.d.ts +2 -2
  240. package/dist/ui/embed-token.js +30 -5
  241. package/dist/ui/registry.d.ts +29 -14
  242. package/dist/ui/registry.js +31 -10
  243. package/dist/ui/slots.controller.d.ts +11 -0
  244. package/dist/ui/slots.controller.js +25 -0
  245. package/dist/ui/ui-stream.d.ts +20 -3
  246. package/dist/ui/ui-stream.js +25 -7
  247. package/dist/ui/ui.schemas.d.ts +66 -0
  248. package/dist/ui/ui.schemas.js +65 -0
  249. package/dist/ui/views.controller.d.ts +35 -49
  250. package/dist/ui/views.controller.js +48 -70
  251. package/dist/ui/views.d.ts +84 -18
  252. package/dist/ui/views.js +201 -38
  253. package/package.json +3 -3
  254. package/src/migrations/0105_devices_rename.sql +136 -0
  255. package/src/migrations/0106_setup_guides_v2.sql +10 -0
  256. package/dist/devices/device-auth.module.d.ts +0 -7
  257. package/dist/environments/conversation-environments.d.ts +0 -75
  258. package/dist/environments/dto.d.ts +0 -25
  259. package/dist/environments/dto.js +0 -12
  260. package/dist/environments/environments.controller.d.ts +0 -36
  261. package/dist/environments/environments.module.d.ts +0 -8
  262. package/dist/environments/environments.module.js +0 -31
  263. package/dist/environments/environments.schemas.d.ts +0 -3
  264. package/dist/environments/environments.schemas.js +0 -14
  265. package/dist/environments/label.d.ts +0 -11
  266. package/dist/platform/ops/environments.ops.d.ts +0 -26
  267. package/dist/platform/ops/environments.ops.js +0 -311
@@ -142,15 +142,15 @@ async function runInBackground(deps, ctx, input) {
142
142
  const requested = input.timeout;
143
143
  const seconds = Math.max(1, Math.ceil(Math.min(requested ?? maxMs, maxMs) / 1000));
144
144
  const root = sandboxConversationOf(ctx);
145
- // the environment the task will run in (the root conversation's, bound for good)
146
- let environmentId;
145
+ // the device the task will run in (the root conversation's, bound for good)
146
+ let deviceId;
147
147
  try {
148
- environmentId = await deps.environments.forTool(ctx.orgId, root);
148
+ deviceId = await deps.devices.forTool(ctx.orgId, root);
149
149
  }
150
150
  catch (e) {
151
151
  throw mapSandboxError(e, deps.log);
152
152
  }
153
- if (!(await sandbox.availableFor(environmentId)))
153
+ if (!(await sandbox.availableFor(deviceId)))
154
154
  throw noSandboxError();
155
155
  const maxTasks = cfg.sandbox.background.maxTasks;
156
156
  const id = newTaskId();
@@ -161,7 +161,7 @@ async function runInBackground(deps, ctx, input) {
161
161
  orgId: ctx.orgId,
162
162
  conversationId: ctx.conversationId,
163
163
  sandboxConversationId: root,
164
- environmentId,
164
+ deviceId,
165
165
  runId: ctx.runId,
166
166
  callId: ctx.callId,
167
167
  // the run's trigger account (the pipeline passes `runs.trigger_account_id` as `accountId`)
@@ -238,7 +238,7 @@ async function runInBackground(deps, ctx, input) {
238
238
  const sid = out;
239
239
  try {
240
240
  // under the shared lease: no rebuild can come between the launch and this read
241
- const instance = await currentInstance(environmentId);
241
+ const instance = await currentInstance(deviceId);
242
242
  if (instance === null)
243
243
  throw new Error("the sandbox instance could not be read");
244
244
  const marked = await background.markStarted(id, {
@@ -5,7 +5,7 @@ import type { BackgroundTaskStore } from "../../../background/store.js";
5
5
  import type { KernelConfig } from "../../../config/schema.js";
6
6
  import type { AttachmentsService } from "../../../conversations/attachments.service.js";
7
7
  import type { EventLog } from "../../../conversations/event-log.js";
8
- import { type ConversationEnvironments } from "../../../environments/conversation-environments.js";
8
+ import { type ConversationDevices } from "../../../devices/conversation-devices.js";
9
9
  import type { KernelConfigService } from "../../../infra/config/kernel-config.service.js";
10
10
  import { type HeldProvider, type SandboxService } from "../../../sandbox/sandbox.service.js";
11
11
  import type { StorageService } from "../../../storage/storage.service.js";
@@ -19,11 +19,11 @@ export interface SandboxToolDeps {
19
19
  */
20
20
  sandbox: Pick<SandboxService, "cloudAvailable" | "availableFor" | "withSandbox"> & Partial<Pick<SandboxService, "pathLease" | "currentInstance" | "ifRunning">>;
21
21
  /**
22
- * The environment a call enters: the root conversation's, checked for its owner every call.
22
+ * The device a call enters: the root conversation's, checked for its owner every call.
23
23
  * `usableNow` (absent in test stubs: only the cloud provider counts) tells a listing whether a
24
- * conversation's environment can run without a cloud provider (ruling R8).
24
+ * conversation's device can run without a cloud provider (ruling R8).
25
25
  */
26
- environments: Pick<ConversationEnvironments, "forTool"> & Partial<Pick<ConversationEnvironments, "usableNow">>;
26
+ devices: Pick<ConversationDevices, "forTool"> & Partial<Pick<ConversationDevices, "usableNow">>;
27
27
  /** Background `Bash` tasks; absent in test stubs, where `run_in_background` is refused. */
28
28
  background?: Pick<BackgroundTaskStore, "reserve" | "markStarted" | "failLaunch" | "finishStoppedLaunch" | "releaseStop" | "get" | "advanceOffset">;
29
29
  /**
@@ -38,7 +38,7 @@ export interface SandboxToolDeps {
38
38
  storage: Pick<StorageService, "kernel" | "deployment" | "available">;
39
39
  /**
40
40
  * `publishChanged`: `Deliver` announces `changed: files` (UI refresh B). `latestOfType` reads the
41
- * conversation's latest `environment_paths` (absent in test stubs, which record none).
41
+ * conversation's latest `device_paths` (absent in test stubs, which record none).
42
42
  */
43
43
  eventLog: Pick<EventLog, "append" | "latestFileState"> & Partial<Pick<EventLog, "publishChanged" | "latestOfType">>;
44
44
  config: Pick<KernelConfigService, "get">;
@@ -51,22 +51,22 @@ export interface SandboxToolDeps {
51
51
  * every provider call).
52
52
  */
53
53
  export interface SandboxSession {
54
- /** The environment the call runs in (path leases are taken on it). */
55
- environmentId: string;
54
+ /** The device the call runs in (path leases are taken on it). */
55
+ deviceId: string;
56
56
  h: SandboxHandle;
57
57
  /** The instance's roots: every path the call builds or checks is under one of them. */
58
58
  roots: SandboxRoots;
59
59
  p: HeldProvider;
60
60
  signal: AbortSignal;
61
61
  }
62
- /** This conversation's first use of its environment (in the instance's workspace). */
62
+ /** This conversation's first use of its device (in the instance's workspace). */
63
63
  export declare const sandboxStartedNotice: (roots: SandboxRoots) => string;
64
64
  /** {@link sandboxStartedNotice} of an instance with the default roots. */
65
65
  export declare const SANDBOX_STARTED_NOTICE: string;
66
- /** A new instance came up on the environment's kept files. */
67
- export declare const SANDBOX_RESTARTED_NOTICE = "The environment's instance was restarted; files are kept, running processes are gone and temporary files may be gone.";
66
+ /** A new instance came up on the device's kept files. */
67
+ export declare const SANDBOX_RESTARTED_NOTICE = "The device's instance was restarted; files are kept, running processes are gone and temporary files may be gone.";
68
68
  /**
69
- * The environment's files were reset (on request, or after they were lost) since this conversation
69
+ * The device's files were reset (on request, or after they were lost) since this conversation
70
70
  * last used it.
71
71
  */
72
72
  export declare const sandboxFilesResetNotice: (roots: SandboxRoots) => string;
@@ -83,13 +83,13 @@ export declare function noSandboxError(): ToolError;
83
83
  export declare const SANDBOX_UNREACHABLE_TEXT = "The sandbox provider can't be reached (the connection failed), so this call did nothing in the sandbox; retrying won't help until a super admin checks the sandbox extension's configuration (Admin console \u2192 Extensions). Continue without the sandbox, or ask the person to have a super admin check it.";
84
84
  /** A provider connection that broke during the call: the provider may have acted before it broke. */
85
85
  export declare const SANDBOX_CONNECTION_DROPPED_TEXT = "The connection to the sandbox provider broke during this call, so it may or may not have taken effect; check the sandbox state before retrying. If it fails again, continue without the sandbox and ask the person to have a super admin check the sandbox extension's configuration (Admin console \u2192 Extensions).";
86
- /** The directory of attachments in the environment (each conversation has a subdirectory). */
86
+ /** The directory of attachments in the device (each conversation has a subdirectory). */
87
87
  export declare const attachmentsRoot: (roots: SandboxRoots) => string;
88
88
  /** {@link attachmentsRoot} of an instance with the default roots. */
89
89
  export declare const ATTACHMENTS_ROOT: string;
90
90
  /**
91
91
  * One conversation's attachment directory: the first 12 hex digits of the root conversation's
92
- * UUID, so conversations sharing an environment do not overwrite each other's files.
92
+ * UUID, so conversations sharing a device do not overwrite each other's files.
93
93
  */
94
94
  export declare const attachmentsDir: (roots: SandboxRoots, rootConversationId: string) => string;
95
95
  /** The conversation's marker of synced attachments: `{ <attachment id>: <file name> }`. */
@@ -144,7 +144,7 @@ export declare function clip(s: string, max: number): string;
144
144
  export declare function withNotices(notices: readonly string[], text: string): string;
145
145
  /**
146
146
  * The root-independent checks of a path (`validateSandboxPathShape`: non-empty, absolute, no
147
- * control characters, no empty or `..` segments), run before the call enters its environment, so
147
+ * control characters, no empty or `..` segments), run before the call enters its device, so
148
148
  * a malformed path never creates or resumes an instance; root membership is checked inside
149
149
  * ({@link checkPath}).
150
150
  */
@@ -176,41 +176,41 @@ export declare function assignAttachmentNames(items: readonly {
176
176
  */
177
177
  export declare function mapSandboxError(e: unknown, log: Pick<Logger, "warn"> | undefined): unknown;
178
178
  /**
179
- * Runs `fn` in the environment of the call's conversation (a sub-agent: its root's): resolves and
180
- * checks the environment for the conversation's owner (binding an unbound conversation to the
179
+ * Runs `fn` in the device of the call's conversation (a sub-agent: its root's): resolves and
180
+ * checks the device for the conversation's owner (binding an unbound conversation to the
181
181
  * owner's default first), then `SandboxService.withSandbox` (the instance created, resumed or
182
182
  * rebuilt on the kept files as needed, every `exec` carrying the call's actor). Attachments are
183
183
  * synced first. Returns the value and the notices to put before the result (first use, a new
184
184
  * instance, newly copied attachments). When `withSandbox` rebuilds a gone instance and calls
185
185
  * `fn` again, the notices are the last call's. The instance's roots are recorded for the model
186
- * on the conversation's first call and whenever they change ({@link recordEnvironmentPaths}).
186
+ * on the conversation's first call and whenever they change ({@link recordDevicePaths}).
187
187
  */
188
188
  export declare function inSandbox<T>(deps: SandboxToolDeps, ctx: BuiltinCallContext, fn: (s: SandboxSession) => Promise<T>): Promise<{
189
189
  value: T;
190
190
  notices: string[];
191
191
  }>;
192
- /** The conversation whose environment a call uses (the root conversation's for a sub-agent). */
192
+ /** The conversation whose device a call uses (the root conversation's for a sub-agent). */
193
193
  export declare const sandboxConversationOf: (ctx: BuiltinCallContext) => string;
194
194
  /**
195
- * Runs `fn` under the per-path lease of `path` in the session's environment (spec §10.4: the
195
+ * Runs `fn` under the per-path lease of `path` in the session's device (spec §10.4: the
196
196
  * kernel's own read-modify-write of one file never loses another holder's update, from any
197
- * conversation sharing the environment). `fn` gets `signal` combined with the path lease's: pass
197
+ * conversation sharing the device). `fn` gets `signal` combined with the path lease's: pass
198
198
  * it to every provider call, so a lost path lease stops the write. Without `pathLease` (test
199
199
  * stubs) it just runs `fn` with `signal`.
200
200
  */
201
- export declare function withPathLease<T>(deps: Pick<SandboxToolDeps, "sandbox">, s: Pick<SandboxSession, "environmentId">, path: string, signal: AbortSignal, fn: (signal: AbortSignal) => Promise<T>): Promise<T>;
201
+ export declare function withPathLease<T>(deps: Pick<SandboxToolDeps, "sandbox">, s: Pick<SandboxSession, "deviceId">, path: string, signal: AbortSignal, fn: (signal: AbortSignal) => Promise<T>): Promise<T>;
202
202
  /**
203
203
  * Whether a sandbox tool call of the conversation tree rooted at `conversationId` can run: a
204
- * cloud provider is loaded, or (ruling R8) the conversation's environment runs on a registered
205
- * kernel provider (`@device`). Without a conversation only the cloud provider counts.
204
+ * cloud provider is loaded, or (ruling R8) the conversation's device runs on a registered
205
+ * kernel provider (`@local`). Without a conversation only the cloud provider counts.
206
206
  */
207
- export declare function sandboxUsable(deps: Pick<SandboxToolDeps, "sandbox" | "environments">, orgId: string, conversationId: string | undefined): Promise<boolean>;
207
+ export declare function sandboxUsable(deps: Pick<SandboxToolDeps, "sandbox" | "devices">, orgId: string, conversationId: string | undefined): Promise<boolean>;
208
208
  /**
209
209
  * The reason the registry reports the sandbox tools unavailable with, or null when they can run
210
210
  * ({@link sandboxUsable}; the listing passes the root conversation of the run). An eval replay
211
211
  * lists them as available (`replay`: its calls are never executed). `memo` (one per listing)
212
212
  * makes every sandbox tool of a listing share one answer.
213
213
  */
214
- export declare const unavailableWhenNoSandbox: (deps: Pick<SandboxToolDeps, "sandbox" | "environments">) => (ctx: ToolListingScope) => Promise<string | null>;
214
+ export declare const unavailableWhenNoSandbox: (deps: Pick<SandboxToolDeps, "sandbox" | "devices">) => (ctx: ToolListingScope) => Promise<string | null>;
215
215
  /** 读出的字节是否像二进制(开头 8 KB 里有 NUL)。 */
216
216
  export declare function looksBinary(data: Uint8Array): boolean;
@@ -1,25 +1,25 @@
1
1
  import { DEFAULT_SANDBOX_ROOTS, DeviceProtocolError, isFileSystemGoneError, isSandboxGoneError, ToolError, validateSandboxPath, validateSandboxPathShape, } from "@capybara-hq/plugin-sdk";
2
- import { ANONYMOUS_NO_ENVIRONMENT, } from "../../../environments/conversation-environments.js";
2
+ import { ANONYMOUS_NO_DEVICE, } from "../../../devices/conversation-devices.js";
3
3
  import { ApiError } from "../../../errors.js";
4
- import { environmentPathsChange } from "../../../runtime/context/environment-paths.js";
4
+ import { devicePathsChange } from "../../../runtime/context/device-paths.js";
5
5
  import { SandboxPathBusyError } from "../../../sandbox/leases.js";
6
6
  import { SandboxLockLostError, } from "../../../sandbox/sandbox.service.js";
7
7
  import { SandboxProviderUnreachableError } from "../../../sandbox/unreachable.js";
8
8
  // ---- 模型可见文案(英文) ----
9
- /** This conversation's first use of its environment (in the instance's workspace). */
10
- export const sandboxStartedNotice = (roots) => `Environment started (first use in this conversation); the working directory is ${roots.workspace}, shared with the environment's other conversations.`;
9
+ /** This conversation's first use of its device (in the instance's workspace). */
10
+ export const sandboxStartedNotice = (roots) => `Device started (first use in this conversation); the working directory is ${roots.workspace}, shared with the device's other conversations.`;
11
11
  /** {@link sandboxStartedNotice} of an instance with the default roots. */
12
12
  export const SANDBOX_STARTED_NOTICE = sandboxStartedNotice(DEFAULT_SANDBOX_ROOTS);
13
- /** A new instance came up on the environment's kept files. */
14
- export const SANDBOX_RESTARTED_NOTICE = "The environment's instance was restarted; files are kept, running processes are gone and temporary files may be gone.";
13
+ /** A new instance came up on the device's kept files. */
14
+ export const SANDBOX_RESTARTED_NOTICE = "The device's instance was restarted; files are kept, running processes are gone and temporary files may be gone.";
15
15
  /**
16
- * The environment's files were reset (on request, or after they were lost) since this conversation
16
+ * The device's files were reset (on request, or after they were lost) since this conversation
17
17
  * last used it.
18
18
  */
19
- export const sandboxFilesResetNotice = (roots) => `The environment's files were reset; earlier files in ${roots.workspace} and running processes are gone and temporary files may be gone, so recreate anything you still need.`;
19
+ export const sandboxFilesResetNotice = (roots) => `The device's files were reset; earlier files in ${roots.workspace} and running processes are gone and temporary files may be gone, so recreate anything you still need.`;
20
20
  /** {@link sandboxFilesResetNotice} of an instance with the default roots. */
21
21
  export const SANDBOX_FILES_RESET_NOTICE = sandboxFilesResetNotice(DEFAULT_SANDBOX_ROOTS);
22
- const BUSY_TEXT = "The environment is busy: all its command slots are taken by commands of this or another conversation sharing it; wait for one to finish and retry.";
22
+ const BUSY_TEXT = "The device is busy: all its command slots are taken by commands of this or another conversation sharing it; wait for one to finish and retry.";
23
23
  const NO_SANDBOX_TEXT = "No sandbox is configured in this deployment; ask an administrator to install a sandbox plugin, or do the task without the sandbox.";
24
24
  /** 没有沙箱提供方时「工具不可用」的原因(进提醒,内核在后面补句号):与调用时的错误同一句话。 */
25
25
  export const SANDBOX_UNAVAILABLE_REASON = NO_SANDBOX_TEXT.slice(0, -1);
@@ -27,12 +27,12 @@ export const SANDBOX_UNAVAILABLE_REASON = NO_SANDBOX_TEXT.slice(0, -1);
27
27
  export function noSandboxError() {
28
28
  return new ToolError(NO_SANDBOX_TEXT);
29
29
  }
30
- const PATH_BUSY_TEXT = "Another sub-agent or another conversation in this environment is writing this file; wait a moment and retry.";
30
+ const PATH_BUSY_TEXT = "Another sub-agent or another conversation on this device is writing this file; wait a moment and retry.";
31
31
  const ANONYMOUS_TEXT = "The sandbox is not available to anonymous IM senders; do the task without the sandbox, or ask the person to link their account and start a new conversation.";
32
- const ENV_NOT_FOUND_TEXT = "This conversation's environment was deleted or its owner can no longer use it; ask the user to start a new conversation in another environment.";
33
- const ENV_FORBIDDEN_TEXT = "This conversation's owner may no longer use its environment; ask the user to start a new conversation in an environment they can use.";
34
- const ENV_UNAVAILABLE_TEXT = "This conversation's environment is kept by a sandbox provider that is not active in this deployment; ask the user to start a new conversation in another environment, or an administrator to re-enable that provider.";
35
- const ENV_FILES_LOST_TEXT = "This environment's files are gone. Ask the user to reset its files on the environments page, then retry.";
32
+ const ENV_NOT_FOUND_TEXT = "This conversation's device was deleted or its owner can no longer use it; ask the user to start a new conversation on another device.";
33
+ const ENV_FORBIDDEN_TEXT = "This conversation's owner may no longer use its device; ask the user to start a new conversation on a device they can use.";
34
+ const ENV_UNAVAILABLE_TEXT = "This conversation's device is kept by a sandbox provider that is not active in this deployment; ask the user to start a new conversation on another device, or an administrator to re-enable that provider.";
35
+ const ENV_FILES_LOST_TEXT = "This device's files are gone. Ask the user to reset its files on the devices page, then retry.";
36
36
  /**
37
37
  * A provider call that never connected (refused, unknown host, unreachable network): the request
38
38
  * did not reach the provider, so the call did nothing in the sandbox.
@@ -40,20 +40,20 @@ const ENV_FILES_LOST_TEXT = "This environment's files are gone. Ask the user to
40
40
  export const SANDBOX_UNREACHABLE_TEXT = "The sandbox provider can't be reached (the connection failed), so this call did nothing in the sandbox; retrying won't help until a super admin checks the sandbox extension's configuration (Admin console → Extensions). Continue without the sandbox, or ask the person to have a super admin check it.";
41
41
  /** A provider connection that broke during the call: the provider may have acted before it broke. */
42
42
  export const SANDBOX_CONNECTION_DROPPED_TEXT = "The connection to the sandbox provider broke during this call, so it may or may not have taken effect; check the sandbox state before retrying. If it fails again, continue without the sandbox and ask the person to have a super admin check the sandbox extension's configuration (Admin console → Extensions).";
43
- const DEVICE_FILES_LOST_TEXT = "This environment's directory is gone from its connected machine. Ask the person to run capybara-device logout, then capybara-device login into this environment, on that machine, then retry.";
44
- const FILES_GONE_TEXT = "This environment's files are gone. Ask the user to reset its files on the environments page (for a connected machine: to run capybara-device logout, then capybara-device login, on it), then retry.";
45
- const DEVICE_OFFLINE_TEXT = "The connected machine is offline. Ask the person to start capybara-device on it.";
46
- const DEVICE_OUTDATED_TEXT = "The connected machine runs an outdated capybara-device. Ask the person to update it on that machine and start it again.";
47
- const DEVICE_REVOKED_TEXT = "The connected machine of this environment was disconnected. Ask the person to run capybara-device logout, then capybara-device login on it, or to start a new conversation in another environment.";
48
- const deviceProtocolText = (detail) => `The connected machine sent an answer the platform cannot read (${detail}). Ask the person to update capybara-device on that machine, then retry.`;
43
+ const DEVICE_FILES_LOST_TEXT = "This device's directory is gone from the device's machine. Ask the person to run capybara-device logout, then capybara-device login into this device, on that machine, then retry.";
44
+ const FILES_GONE_TEXT = "This device's files are gone. Ask the user to reset its files on the devices page (for a local device: to run capybara-device logout, then capybara-device login, on it), then retry.";
45
+ const DEVICE_OFFLINE_TEXT = "The device's machine is offline. Ask the person to start capybara-device on it, or to start a new conversation on another device.";
46
+ const DEVICE_OUTDATED_TEXT = "The device's machine runs an outdated capybara-device. Ask the person to update it on that machine and start it again.";
47
+ const DEVICE_REVOKED_TEXT = "The device's machine was disconnected. Ask the person to run capybara-device logout, then capybara-device login on it, or to start a new conversation on another device.";
48
+ const deviceProtocolText = (detail) => `The device's machine sent an answer the platform cannot read (${detail}). Ask the person to update capybara-device on that machine, then retry.`;
49
49
  const LOCK_LOST_TEXT = "The sandbox operation was interrupted because the sandbox lock was lost; check the sandbox state and retry.";
50
- /** The directory of attachments in the environment (each conversation has a subdirectory). */
50
+ /** The directory of attachments in the device (each conversation has a subdirectory). */
51
51
  export const attachmentsRoot = (roots) => `${roots.workspace}/attachments`;
52
52
  /** {@link attachmentsRoot} of an instance with the default roots. */
53
53
  export const ATTACHMENTS_ROOT = attachmentsRoot(DEFAULT_SANDBOX_ROOTS);
54
54
  /**
55
55
  * One conversation's attachment directory: the first 12 hex digits of the root conversation's
56
- * UUID, so conversations sharing an environment do not overwrite each other's files.
56
+ * UUID, so conversations sharing a device do not overwrite each other's files.
57
57
  */
58
58
  export const attachmentsDir = (roots, rootConversationId) => `${attachmentsRoot(roots)}/${rootConversationId.replaceAll("-", "").slice(0, 12)}`;
59
59
  /** The conversation's marker of synced attachments: `{ <attachment id>: <file name> }`. */
@@ -122,7 +122,7 @@ export function withNotices(notices, text) {
122
122
  }
123
123
  /**
124
124
  * The root-independent checks of a path (`validateSandboxPathShape`: non-empty, absolute, no
125
- * control characters, no empty or `..` segments), run before the call enters its environment, so
125
+ * control characters, no empty or `..` segments), run before the call enters its device, so
126
126
  * a malformed path never creates or resumes an instance; root membership is checked inside
127
127
  * ({@link checkPath}).
128
128
  */
@@ -320,28 +320,28 @@ export function mapSandboxError(e, log) {
320
320
  return new ToolError(BUSY_TEXT);
321
321
  if (e.code === "sandbox.unavailable") {
322
322
  const reason = e.details?.[0]?.reason;
323
- if (reason === ANONYMOUS_NO_ENVIRONMENT)
323
+ if (reason === ANONYMOUS_NO_DEVICE)
324
324
  return new ToolError(ANONYMOUS_TEXT);
325
325
  return new ToolError(NO_SANDBOX_TEXT);
326
326
  }
327
327
  const detail = e.details?.[0];
328
- if (e.code === "environment.not_found")
328
+ if (e.code === "device.not_found")
329
329
  return new ToolError(ENV_NOT_FOUND_TEXT);
330
- if (e.code === "environment.forbidden" && detail?.reason === "machine_revoked") {
330
+ if (e.code === "device.forbidden" && detail?.reason === "machine_revoked") {
331
331
  return new ToolError(DEVICE_REVOKED_TEXT);
332
332
  }
333
- if (e.code === "environment.forbidden")
333
+ if (e.code === "device.forbidden")
334
334
  return new ToolError(ENV_FORBIDDEN_TEXT);
335
- if (e.code === "environment.unavailable")
335
+ if (e.code === "device.unavailable")
336
336
  return new ToolError(ENV_UNAVAILABLE_TEXT);
337
- if (e.code === "environment.files_lost" && detail?.source === "device") {
337
+ if (e.code === "device.files_lost" && detail?.source === "local") {
338
338
  return new ToolError(DEVICE_FILES_LOST_TEXT);
339
339
  }
340
- if (e.code === "environment.files_lost")
340
+ if (e.code === "device.files_lost")
341
341
  return new ToolError(ENV_FILES_LOST_TEXT);
342
- if (e.code === "environment.offline")
342
+ if (e.code === "device.offline")
343
343
  return new ToolError(DEVICE_OFFLINE_TEXT);
344
- if (e.code === "environment.program_outdated")
344
+ if (e.code === "device.program_outdated")
345
345
  return new ToolError(DEVICE_OUTDATED_TEXT);
346
346
  }
347
347
  // an operation outside withSandbox's own mapping (it records lost files itself)
@@ -356,27 +356,27 @@ export function mapSandboxError(e, log) {
356
356
  return e;
357
357
  }
358
358
  /**
359
- * Runs `fn` in the environment of the call's conversation (a sub-agent: its root's): resolves and
360
- * checks the environment for the conversation's owner (binding an unbound conversation to the
359
+ * Runs `fn` in the device of the call's conversation (a sub-agent: its root's): resolves and
360
+ * checks the device for the conversation's owner (binding an unbound conversation to the
361
361
  * owner's default first), then `SandboxService.withSandbox` (the instance created, resumed or
362
362
  * rebuilt on the kept files as needed, every `exec` carrying the call's actor). Attachments are
363
363
  * synced first. Returns the value and the notices to put before the result (first use, a new
364
364
  * instance, newly copied attachments). When `withSandbox` rebuilds a gone instance and calls
365
365
  * `fn` again, the notices are the last call's. The instance's roots are recorded for the model
366
- * on the conversation's first call and whenever they change ({@link recordEnvironmentPaths}).
366
+ * on the conversation's first call and whenever they change ({@link recordDevicePaths}).
367
367
  */
368
368
  export async function inSandbox(deps, ctx, fn) {
369
369
  try {
370
- const environmentId = await deps.environments.forTool(ctx.orgId, sandboxConversationOf(ctx));
370
+ const deviceId = await deps.devices.forTool(ctx.orgId, sandboxConversationOf(ctx));
371
371
  return await deps.sandbox.withSandbox({
372
372
  orgId: ctx.orgId,
373
- environmentId,
373
+ deviceId,
374
374
  // a sub-agent is told when another holder rebuilt the shared instance (final review m5)
375
375
  holderConversationId: ctx.conversationId,
376
376
  actor: { accountId: ctx.accountId, conversationId: ctx.conversationId },
377
377
  }, async (h, p, info, signal) => {
378
- const s = { environmentId, h, roots: info.roots, p, signal };
379
- await recordEnvironmentPaths(deps, ctx, info.roots);
378
+ const s = { deviceId, h, roots: info.roots, p, signal };
379
+ await recordDevicePaths(deps, ctx, info.roots);
380
380
  const notices = [];
381
381
  if (info.filesReset)
382
382
  notices.push(sandboxFilesResetNotice(info.roots));
@@ -398,32 +398,32 @@ export async function inSandbox(deps, ctx, fn) {
398
398
  }
399
399
  /**
400
400
  * Environments spec §13.1, ruling R22: the calling conversation's log (the log its model reads; a
401
- * sub-agent's own too) gets an `environment_paths` event on its first sandbox call, the default
401
+ * sub-agent's own too) gets an `device_paths` event on its first sandbox call, the default
402
402
  * roots included, and again whenever the held instance's roots differ from the latest recorded
403
403
  * ones; always before the call's result. One indexed read per call (migration 0094); parallel
404
404
  * calls that saw the same latest event write one event (its idempotency key).
405
405
  */
406
- async function recordEnvironmentPaths(deps, ctx, roots) {
406
+ async function recordDevicePaths(deps, ctx, roots) {
407
407
  if (!deps.eventLog.latestOfType)
408
408
  return;
409
- const latest = await deps.eventLog.latestOfType(ctx.conversationId, "environment_paths");
410
- const change = environmentPathsChange(latest, roots, ctx.runId);
409
+ const latest = await deps.eventLog.latestOfType(ctx.conversationId, "device_paths");
410
+ const change = devicePathsChange(latest, roots, ctx.runId);
411
411
  if (change)
412
412
  await deps.eventLog.append(ctx.conversationId, [change]);
413
413
  }
414
- /** The conversation whose environment a call uses (the root conversation's for a sub-agent). */
414
+ /** The conversation whose device a call uses (the root conversation's for a sub-agent). */
415
415
  export const sandboxConversationOf = (ctx) => ctx.sandboxConversationId ?? ctx.conversationId;
416
416
  /**
417
- * Runs `fn` under the per-path lease of `path` in the session's environment (spec §10.4: the
417
+ * Runs `fn` under the per-path lease of `path` in the session's device (spec §10.4: the
418
418
  * kernel's own read-modify-write of one file never loses another holder's update, from any
419
- * conversation sharing the environment). `fn` gets `signal` combined with the path lease's: pass
419
+ * conversation sharing the device). `fn` gets `signal` combined with the path lease's: pass
420
420
  * it to every provider call, so a lost path lease stops the write. Without `pathLease` (test
421
421
  * stubs) it just runs `fn` with `signal`.
422
422
  */
423
423
  export async function withPathLease(deps, s, path, signal, fn) {
424
424
  if (!deps.sandbox.pathLease)
425
425
  return fn(signal);
426
- const lease = await deps.sandbox.pathLease(s.environmentId, path, signal);
426
+ const lease = await deps.sandbox.pathLease(s.deviceId, path, signal);
427
427
  try {
428
428
  return await fn(AbortSignal.any([signal, lease.signal]));
429
429
  }
@@ -433,15 +433,15 @@ export async function withPathLease(deps, s, path, signal, fn) {
433
433
  }
434
434
  /**
435
435
  * Whether a sandbox tool call of the conversation tree rooted at `conversationId` can run: a
436
- * cloud provider is loaded, or (ruling R8) the conversation's environment runs on a registered
437
- * kernel provider (`@device`). Without a conversation only the cloud provider counts.
436
+ * cloud provider is loaded, or (ruling R8) the conversation's device runs on a registered
437
+ * kernel provider (`@local`). Without a conversation only the cloud provider counts.
438
438
  */
439
439
  export async function sandboxUsable(deps, orgId, conversationId) {
440
440
  if (deps.sandbox.cloudAvailable)
441
441
  return true;
442
- if (conversationId === undefined || !deps.environments.usableNow)
442
+ if (conversationId === undefined || !deps.devices.usableNow)
443
443
  return false;
444
- return deps.environments.usableNow(orgId, conversationId);
444
+ return deps.devices.usableNow(orgId, conversationId);
445
445
  }
446
446
  /**
447
447
  * The reason the registry reports the sandbox tools unavailable with, or null when they can run
@@ -57,10 +57,10 @@ export function sandboxEditTool(deps) {
57
57
  throw new ToolError(SAME_TEXT);
58
58
  checkPathShape(input.file_path, "file_path");
59
59
  let path = "";
60
- const { value: edit, notices } = await inSandbox(deps, ctx, ({ environmentId, h, roots, p, signal }) => {
60
+ const { value: edit, notices } = await inSandbox(deps, ctx, ({ deviceId, h, roots, p, signal }) => {
61
61
  path = checkWritable(input.file_path, roots);
62
62
  // read, replace, write: one holder at a time per file
63
- return withPathLease(deps, { environmentId }, path, signal, async (signal) => {
63
+ return withPathLease(deps, { deviceId }, path, signal, async (signal) => {
64
64
  const st = await p.stat(h, path, signal);
65
65
  if (st === null)
66
66
  throw new ToolError(notFound(path));
@@ -6,7 +6,7 @@ export { assignAttachmentNames, RUN_DEADLINE_MARGIN_MS, runTimeLeftMs, SANDBOX_R
6
6
  export { compileGlob, GlobPatternError, MAX_GLOB_STARS } from "./glob-match.js";
7
7
  /**
8
8
  * The sandbox builtins (M5 T8): Bash / Read / Write / Edit / Glob / Grep / Deliver, all run in the
9
- * conversation's environment (`SandboxService.withSandbox`) after syncing attachments to
9
+ * conversation's device (`SandboxService.withSandbox`) after syncing attachments to
10
10
  * `<workspace>/attachments` (the instance's roots, environments spec §13.1); unavailable without
11
11
  * a provider for it. Allowed by default; with the org setting `sandboxToolPolicy` set to ask,
12
12
  * every one but Read / Glob / Grep needs approval (see policy.ts).
@@ -13,7 +13,7 @@ export { assignAttachmentNames, RUN_DEADLINE_MARGIN_MS, runTimeLeftMs, SANDBOX_R
13
13
  export { compileGlob, GlobPatternError, MAX_GLOB_STARS } from "./glob-match.js";
14
14
  /**
15
15
  * The sandbox builtins (M5 T8): Bash / Read / Write / Edit / Glob / Grep / Deliver, all run in the
16
- * conversation's environment (`SandboxService.withSandbox`) after syncing attachments to
16
+ * conversation's device (`SandboxService.withSandbox`) after syncing attachments to
17
17
  * `<workspace>/attachments` (the instance's roots, environments spec §13.1); unavailable without
18
18
  * a provider for it. Allowed by default; with the org setting `sandboxToolPolicy` set to ask,
19
19
  * every one but Read / Glob / Grep needs approval (see policy.ts).
@@ -14,12 +14,12 @@ export interface TaskEnv {
14
14
  store: NonNullable<SandboxToolDeps["background"]>;
15
15
  tasks: NonNullable<SandboxToolDeps["tasks"]>;
16
16
  ifRunning: SandboxService["ifRunning"];
17
- environments: SandboxToolDeps["environments"];
17
+ devices: SandboxToolDeps["devices"];
18
18
  log: SandboxToolDeps["log"];
19
19
  }
20
20
  /**
21
21
  * The task tools' dependencies; throws the tool's error when they are missing, or when the
22
- * conversation's environment cannot run (no cloud provider, and not a registered `@device` one:
22
+ * conversation's device cannot run (no cloud provider, and not a registered `@local` one:
23
23
  * ruling R8).
24
24
  */
25
25
  export declare function taskEnv(deps: SandboxToolDeps, ctx: BuiltinCallContext): Promise<TaskEnv>;
@@ -29,14 +29,14 @@ export declare function taskEnv(deps: SandboxToolDeps, ctx: BuiltinCallContext):
29
29
  */
30
30
  export declare function ownedTask(env: TaskEnv, ctx: BuiltinCallContext, id: string): Promise<BackgroundTaskRow>;
31
31
  /**
32
- * The per-call access re-check of every sandbox tool (`inSandbox`): the conversation's environment
32
+ * The per-call access re-check of every sandbox tool (`inSandbox`): the conversation's device
33
33
  * may still be used by its owner. The task tools read a task's own instance without `inSandbox`,
34
34
  * so they check here first; errors become the tools' errors.
35
35
  */
36
- export declare function recheckEnvironment(env: TaskEnv, ctx: BuiltinCallContext): Promise<void>;
36
+ export declare function recheckDevice(env: TaskEnv, ctx: BuiltinCallContext): Promise<void>;
37
37
  /**
38
- * `ifRunning` on the task's own environment instance (its execs act for the task's trigger in its
39
- * conversation); sandbox errors become the tools' errors. A task from before environments has no
38
+ * `ifRunning` on the task's own device instance (its execs act for the task's trigger in its
39
+ * conversation); sandbox errors become the tools' errors. A task from before devices has no
40
40
  * instance (`not_running`).
41
41
  */
42
42
  export declare function onTaskInstance<T>(env: TaskEnv, task: BackgroundTaskRow, fn: (p: HeldProvider, h: SandboxHandle, signal: AbortSignal) => Promise<T>, signal: AbortSignal): Promise<IfRunningResult<T>>;
@@ -51,7 +51,7 @@ const SPEC = {
51
51
  };
52
52
  /**
53
53
  * The task tools' dependencies; throws the tool's error when they are missing, or when the
54
- * conversation's environment cannot run (no cloud provider, and not a registered `@device` one:
54
+ * conversation's device cannot run (no cloud provider, and not a registered `@local` one:
55
55
  * ruling R8).
56
56
  */
57
57
  export async function taskEnv(deps, ctx) {
@@ -65,7 +65,7 @@ export async function taskEnv(deps, ctx) {
65
65
  store: background,
66
66
  tasks,
67
67
  ifRunning: deps.sandbox.ifRunning.bind(deps.sandbox),
68
- environments: deps.environments,
68
+ devices: deps.devices,
69
69
  log: deps.log,
70
70
  };
71
71
  }
@@ -83,28 +83,28 @@ export async function ownedTask(env, ctx, id) {
83
83
  return task;
84
84
  }
85
85
  /**
86
- * The per-call access re-check of every sandbox tool (`inSandbox`): the conversation's environment
86
+ * The per-call access re-check of every sandbox tool (`inSandbox`): the conversation's device
87
87
  * may still be used by its owner. The task tools read a task's own instance without `inSandbox`,
88
88
  * so they check here first; errors become the tools' errors.
89
89
  */
90
- export async function recheckEnvironment(env, ctx) {
90
+ export async function recheckDevice(env, ctx) {
91
91
  try {
92
- await env.environments.forTool(ctx.orgId, sandboxConversationOf(ctx));
92
+ await env.devices.forTool(ctx.orgId, sandboxConversationOf(ctx));
93
93
  }
94
94
  catch (e) {
95
95
  throw mapSandboxError(e, env.log);
96
96
  }
97
97
  }
98
98
  /**
99
- * `ifRunning` on the task's own environment instance (its execs act for the task's trigger in its
100
- * conversation); sandbox errors become the tools' errors. A task from before environments has no
99
+ * `ifRunning` on the task's own device instance (its execs act for the task's trigger in its
100
+ * conversation); sandbox errors become the tools' errors. A task from before devices has no
101
101
  * instance (`not_running`).
102
102
  */
103
103
  export async function onTaskInstance(env, task, fn, signal) {
104
- if (task.environmentId === null)
104
+ if (task.deviceId === null)
105
105
  return { kind: "not_running", status: "gone" };
106
106
  try {
107
- return await env.ifRunning(task.environmentId, { createdAt: task.sandboxCreatedAt }, (p, h, sig) => fn(actingAs(p, taskActor(task)), h, sig), signal);
107
+ return await env.ifRunning(task.deviceId, { createdAt: task.sandboxCreatedAt }, (p, h, sig) => fn(actingAs(p, taskActor(task)), h, sig), signal);
108
108
  }
109
109
  catch (e) {
110
110
  throw mapSandboxError(e, env.log);
@@ -269,7 +269,7 @@ export function taskOutputTool(deps) {
269
269
  const { task_id, block = true, timeout } = input;
270
270
  const env = await taskEnv(deps, ctx);
271
271
  let task = await ownedTask(env, ctx, task_id);
272
- await recheckEnvironment(env, ctx);
272
+ await recheckDevice(env, ctx);
273
273
  if (block && task.status === "running") {
274
274
  const wait = Math.max(0, Math.min(timeout ?? TASK_OUTPUT_DEFAULT_TIMEOUT_MS, TASK_OUTPUT_MAX_TIMEOUT_MS, runTimeLeftMs(ctx.runDeadline)));
275
275
  const until = Date.now() + wait;
@@ -1,7 +1,7 @@
1
1
  import { rootsOf, ToolError } from "@capybara-hq/plugin-sdk";
2
2
  import { decodeTail, tailCommand } from "../../../background/session.js";
3
3
  import { clip, display, mapSandboxError, sandboxBaseTimeoutMs, unavailableWhenNoSandbox, } from "./common.js";
4
- import { onTaskInstance, ownedTask, recheckEnvironment, statusLine, taskEnv, } from "./task-output.js";
4
+ import { onTaskInstance, ownedTask, recheckDevice, statusLine, taskEnv, } from "./task-output.js";
5
5
  /** The time limit of reading a stopped task's last lines. */
6
6
  const TAIL_EXEC_TIMEOUT_MS = 10_000;
7
7
  const SPEC = {
@@ -84,7 +84,7 @@ export function taskStopTool(deps) {
84
84
  const { task_id } = input;
85
85
  const env = await taskEnv(deps, ctx);
86
86
  const task = await ownedTask(env, ctx, task_id);
87
- await recheckEnvironment(env, ctx);
87
+ await recheckDevice(env, ctx);
88
88
  if (task.status !== "running") {
89
89
  return ended(env, task, "had already finished", ctx.signal);
90
90
  }
@@ -46,10 +46,10 @@ export function sandboxWriteTool(deps) {
46
46
  const data = new TextEncoder().encode(input.content);
47
47
  checkPathShape(input.file_path, "file_path");
48
48
  let path = "";
49
- const { value, notices } = await inSandbox(deps, ctx, ({ environmentId, h, roots, p, signal }) => {
49
+ const { value, notices } = await inSandbox(deps, ctx, ({ deviceId, h, roots, p, signal }) => {
50
50
  path = checkWritable(input.file_path, roots);
51
51
  // stat, read the previous content, write: one holder at a time per file
52
- return withPathLease(deps, { environmentId }, path, signal, async (signal) => {
52
+ return withPathLease(deps, { deviceId }, path, signal, async (signal) => {
53
53
  const st = await p.stat(h, path, signal);
54
54
  if (st?.isDir)
55
55
  throw new ToolError(isDirectory(path));
@@ -8,7 +8,7 @@ import { type SandboxToolDeps } from "./sandbox/common.js";
8
8
  * Builtin tool `Skill` (M5 T14, ruling M17): resolves the name against the latest skills catalog
9
9
  * snapshot in the log to an id and version, and returns that version's SKILL.md body and file list
10
10
  * (the result names the version). A skill with other files is copied whole into the conversation's
11
- * environment at `<skills root>/<name>@<digest>/` (the instance's skills root, `/skills` by default; the provider writes as root, commands read only; the
11
+ * device at `<skills root>/<name>@<digest>/` (the instance's skills root, `/skills` by default; the provider writes as root, commands read only; the
12
12
  * digest is {@link skillDigest} of the version's file manifest, so versions of one skill coexist in
13
13
  * the shared file system). Without a sandbox provider only the body is given, with a note that
14
14
  * scripts are unavailable.
@@ -14,7 +14,7 @@ import { clip, display, inSandbox, sandboxBaseTimeoutMs, sandboxConversationOf,
14
14
  * Builtin tool `Skill` (M5 T14, ruling M17): resolves the name against the latest skills catalog
15
15
  * snapshot in the log to an id and version, and returns that version's SKILL.md body and file list
16
16
  * (the result names the version). A skill with other files is copied whole into the conversation's
17
- * environment at `<skills root>/<name>@<digest>/` (the instance's skills root, `/skills` by default; the provider writes as root, commands read only; the
17
+ * device at `<skills root>/<name>@<digest>/` (the instance's skills root, `/skills` by default; the provider writes as root, commands read only; the
18
18
  * digest is {@link skillDigest} of the version's file manifest, so versions of one skill coexist in
19
19
  * the shared file system). Without a sandbox provider only the body is given, with a note that
20
20
  * scripts are unavailable.
@@ -49,7 +49,7 @@ const SPEC = {
49
49
  description: "Load a skill from the skills list: returns the skill's instructions " +
50
50
  "(its SKILL.md) and the list of its files. Call it before starting a task that matches a " +
51
51
  "skill's description, then follow the returned instructions. If the skill has scripts or other " +
52
- "files, they are copied read-only to <name>@<version-id>/ in the skills directory of this environment; run scripts " +
52
+ "files, they are copied read-only to <name>@<version-id>/ in the skills directory of this device; run scripts " +
53
53
  "there with an interpreter (sh, python3, node). Call it again when the skills list changes. Pass args when the task gives the skill arguments (they replace " +
54
54
  "$ARGUMENTS and $1, $2… in the instructions). Do not use it for skills that are not in the list.",
55
55
  inputSchema: {