@capybara-hq/kernel 0.1.0-rc.11 → 0.1.0-rc.13

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 (220) 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/agents/agents.schemas.d.ts +3 -0
  5. package/dist/agents/agents.service.js +11 -1
  6. package/dist/agents/definition.d.ts +1 -0
  7. package/dist/agents/definition.js +7 -3
  8. package/dist/agents/org-templates.js +4 -0
  9. package/dist/agents/pending-connectors.service.js +1 -1
  10. package/dist/background/background.module.js +2 -2
  11. package/dist/background/launch-lock.d.ts +1 -1
  12. package/dist/background/launch-lock.js +1 -1
  13. package/dist/background/poll.job.d.ts +2 -2
  14. package/dist/background/poll.job.js +10 -10
  15. package/dist/background/stop.d.ts +1 -1
  16. package/dist/background/stop.js +3 -3
  17. package/dist/background/store.d.ts +5 -5
  18. package/dist/background/store.js +5 -5
  19. package/dist/background/tasks.service.d.ts +6 -6
  20. package/dist/background/tasks.service.js +13 -13
  21. package/dist/catalog/component-scope.controller.d.ts +18 -6
  22. package/dist/catalog/component-scope.controller.js +36 -13
  23. package/dist/catalog/component-scope.service.d.ts +11 -0
  24. package/dist/catalog/component-scope.service.js +4 -0
  25. package/dist/catalog/component-state.d.ts +8 -0
  26. package/dist/catalog/component-state.js +19 -11
  27. package/dist/catalog/marketplaces.service.d.ts +1 -1
  28. package/dist/catalog/plugin-import.js +4 -1
  29. package/dist/channels/channels.module.js +2 -2
  30. package/dist/channels/inbound.d.ts +8 -8
  31. package/dist/channels/inbound.js +31 -31
  32. package/dist/channels/phrases.d.ts +27 -27
  33. package/dist/channels/phrases.js +27 -27
  34. package/dist/config/docs.js +1 -1
  35. package/dist/config/schema.d.ts +2 -2
  36. package/dist/config/schema.js +21 -21
  37. package/dist/conversations/conversations.controller.d.ts +11 -11
  38. package/dist/conversations/conversations.controller.js +15 -15
  39. package/dist/conversations/conversations.module.d.ts +1 -1
  40. package/dist/conversations/conversations.module.js +7 -7
  41. package/dist/conversations/conversations.schemas.js +1 -1
  42. package/dist/conversations/conversations.service.d.ts +23 -14
  43. package/dist/conversations/conversations.service.js +28 -21
  44. package/dist/conversations/{environment-status.d.ts → device-status.d.ts} +9 -9
  45. package/dist/conversations/{environment-status.js → device-status.js} +18 -18
  46. package/dist/conversations/event-log.d.ts +1 -1
  47. package/dist/conversations/event-log.js +1 -1
  48. package/dist/conversations/events.d.ts +2 -1
  49. package/dist/conversations/events.js +2 -2
  50. package/dist/ctx/create-ctx.d.ts +10 -1
  51. package/dist/ctx/create-ctx.js +86 -25
  52. package/dist/db/kernel-schema.d.ts +39 -23
  53. package/dist/{environments → devices}/access.d.ts +19 -19
  54. package/dist/{environments → devices}/access.js +28 -28
  55. package/dist/devices/conversation-devices.d.ts +75 -0
  56. package/dist/{environments/conversation-environments.js → devices/conversation-devices.js} +71 -72
  57. package/dist/devices/devices.controller.d.ts +36 -0
  58. package/dist/{environments/environments.controller.js → devices/devices.controller.js} +37 -37
  59. package/dist/devices/devices.module.d.ts +5 -13
  60. package/dist/devices/devices.module.js +16 -29
  61. package/dist/devices/devices.schemas.d.ts +3 -0
  62. package/dist/devices/devices.schemas.js +14 -0
  63. package/dist/{environments/environments.service.d.ts → devices/devices.service.d.ts} +70 -70
  64. package/dist/{environments/environments.service.js → devices/devices.service.js} +122 -122
  65. package/dist/devices/dto.d.ts +13 -54
  66. package/dist/devices/dto.js +7 -39
  67. package/dist/devices/label.d.ts +11 -0
  68. package/dist/{environments → devices}/label.js +7 -7
  69. package/dist/{environments → devices}/legacy-cleanup.job.d.ts +3 -3
  70. package/dist/{environments → devices}/legacy-cleanup.job.js +3 -3
  71. package/dist/errors.d.ts +27 -25
  72. package/dist/errors.js +27 -25
  73. package/dist/evals/recorded-tools.d.ts +2 -2
  74. package/dist/evals/recorded-tools.js +6 -6
  75. package/dist/extensions/admin-ops.js +1 -0
  76. package/dist/extensions/admin-view.js +2 -0
  77. package/dist/extensions/effective-config.d.ts +6 -0
  78. package/dist/extensions/effective-config.js +18 -7
  79. package/dist/extensions/host.d.ts +13 -2
  80. package/dist/extensions/host.js +24 -3
  81. package/dist/extensions/instance.d.ts +12 -1
  82. package/dist/extensions/instance.js +13 -0
  83. package/dist/extensions/permission-view.d.ts +10 -1
  84. package/dist/files/previewers.d.ts +1 -1
  85. package/dist/files/previewers.js +1 -1
  86. package/dist/http/api.module.js +10 -6
  87. package/dist/http/gateway-routes.d.ts +1 -1
  88. package/dist/http/gateway-routes.js +1 -1
  89. package/dist/identity/settings.d.ts +32 -0
  90. package/dist/identity/settings.js +26 -2
  91. package/dist/infra/config/kernel-config.service.js +4 -4
  92. package/dist/kernel.module.js +3 -3
  93. package/dist/{devices → local-devices}/device-auth.controller.d.ts +6 -6
  94. package/dist/{devices → local-devices}/device-auth.controller.js +5 -5
  95. package/dist/{devices → local-devices}/device-auth.d.ts +20 -20
  96. package/dist/{devices → local-devices}/device-auth.js +51 -53
  97. package/dist/local-devices/device-auth.module.d.ts +7 -0
  98. package/dist/{devices → local-devices}/device-auth.module.js +5 -5
  99. package/dist/{devices → local-devices}/device-routes.d.ts +3 -3
  100. package/dist/{devices → local-devices}/device-routes.js +2 -2
  101. package/dist/local-devices/dto.d.ts +66 -0
  102. package/dist/local-devices/dto.js +44 -0
  103. package/dist/{devices → local-devices}/keys.d.ts +11 -11
  104. package/dist/{devices → local-devices}/keys.js +11 -11
  105. package/dist/{devices/device-gateway.d.ts → local-devices/local-device-gateway.d.ts} +14 -14
  106. package/dist/{devices/device-gateway.js → local-devices/local-device-gateway.js} +44 -44
  107. package/dist/{devices/device-provider.d.ts → local-devices/local-device-provider.d.ts} +15 -15
  108. package/dist/{devices/device-provider.js → local-devices/local-device-provider.js} +23 -23
  109. package/dist/local-devices/local-devices.module.d.ts +16 -0
  110. package/dist/local-devices/local-devices.module.js +44 -0
  111. package/dist/{devices → local-devices}/machines.d.ts +26 -26
  112. package/dist/{devices → local-devices}/machines.js +71 -71
  113. package/dist/{devices → local-devices}/relay.d.ts +15 -15
  114. package/dist/{devices → local-devices}/relay.js +55 -55
  115. package/dist/{devices → local-devices}/targets.d.ts +8 -8
  116. package/dist/{devices → local-devices}/targets.js +14 -14
  117. package/dist/orgs/offboarding.d.ts +6 -6
  118. package/dist/orgs/offboarding.js +12 -12
  119. package/dist/orgs/settings.service.d.ts +28 -0
  120. package/dist/orgs/settings.service.js +20 -1
  121. package/dist/platform/exclusions.js +48 -3
  122. package/dist/platform/operation.js +6 -2
  123. package/dist/platform/ops/admin.ops.js +8 -2
  124. package/dist/platform/ops/agents.ops.js +19 -6
  125. package/dist/platform/ops/conversations.ops.d.ts +3 -3
  126. package/dist/platform/ops/conversations.ops.js +9 -9
  127. package/dist/platform/ops/devices.ops.d.ts +26 -0
  128. package/dist/platform/ops/devices.ops.js +311 -0
  129. package/dist/platform/ops/org-settings.ops.js +2 -2
  130. package/dist/platform/ops/orgs.ops.js +1 -0
  131. package/dist/platform/ops/ui.ops.d.ts +8 -0
  132. package/dist/platform/ops/ui.ops.js +41 -0
  133. package/dist/platform/platform-ops.module.d.ts +3 -2
  134. package/dist/platform/platform-ops.module.js +8 -5
  135. package/dist/platform/route-schemas.js +6 -3
  136. package/dist/roles/gateway-role.d.ts +3 -3
  137. package/dist/roles/gateway-role.js +4 -4
  138. package/dist/roles/gateway.module.d.ts +1 -1
  139. package/dist/roles/gateway.module.js +5 -5
  140. package/dist/roles/worker.module.js +1 -1
  141. package/dist/runtime/context/build.d.ts +1 -1
  142. package/dist/runtime/context/build.js +6 -6
  143. package/dist/runtime/context/compaction.js +1 -1
  144. package/dist/runtime/context/{environment-paths.d.ts → device-paths.d.ts} +11 -11
  145. package/dist/runtime/context/{environment-paths.js → device-paths.js} +13 -13
  146. package/dist/runtime/maintenance.d.ts +1 -1
  147. package/dist/runtime/subagents/definition.d.ts +3 -2
  148. package/dist/runtime/subagents/definition.js +2 -1
  149. package/dist/sandbox/jobs.d.ts +13 -13
  150. package/dist/sandbox/jobs.js +20 -20
  151. package/dist/sandbox/leases.d.ts +9 -9
  152. package/dist/sandbox/leases.js +14 -14
  153. package/dist/sandbox/providers.d.ts +8 -8
  154. package/dist/sandbox/providers.js +8 -8
  155. package/dist/sandbox/sandbox.module.d.ts +1 -1
  156. package/dist/sandbox/sandbox.module.js +1 -1
  157. package/dist/sandbox/sandbox.service.d.ts +76 -76
  158. package/dist/sandbox/sandbox.service.js +230 -230
  159. package/dist/tools/builtins/builtin-tools.d.ts +2 -2
  160. package/dist/tools/builtins/builtin-tools.js +5 -5
  161. package/dist/tools/builtins/platform.js +1 -1
  162. package/dist/tools/builtins/sandbox/bash.js +6 -6
  163. package/dist/tools/builtins/sandbox/common.d.ts +25 -25
  164. package/dist/tools/builtins/sandbox/common.js +51 -51
  165. package/dist/tools/builtins/sandbox/edit.js +2 -2
  166. package/dist/tools/builtins/sandbox/index.d.ts +1 -1
  167. package/dist/tools/builtins/sandbox/index.js +1 -1
  168. package/dist/tools/builtins/sandbox/task-output.d.ts +6 -6
  169. package/dist/tools/builtins/sandbox/task-output.js +10 -10
  170. package/dist/tools/builtins/sandbox/task-stop.js +2 -2
  171. package/dist/tools/builtins/sandbox/write.js +2 -2
  172. package/dist/tools/builtins/skill-load.d.ts +1 -1
  173. package/dist/tools/builtins/skill-load.js +2 -2
  174. package/dist/tools/connector-account-policies.d.ts +51 -0
  175. package/dist/tools/connector-account-policies.js +165 -0
  176. package/dist/tools/connectors.controller.d.ts +35 -4
  177. package/dist/tools/connectors.controller.js +66 -7
  178. package/dist/tools/connectors.schemas.d.ts +11 -0
  179. package/dist/tools/connectors.schemas.js +11 -0
  180. package/dist/tools/connectors.service.d.ts +2 -0
  181. package/dist/tools/connectors.service.js +1 -0
  182. package/dist/tools/pipeline.d.ts +1 -1
  183. package/dist/tools/pipeline.js +4 -3
  184. package/dist/tools/policy.d.ts +23 -1
  185. package/dist/tools/policy.js +99 -24
  186. package/dist/tools/registry.d.ts +2 -2
  187. package/dist/tools/tools.module.js +6 -3
  188. package/dist/ui/admin-ui.controller.d.ts +56 -0
  189. package/dist/ui/admin-ui.controller.js +192 -0
  190. package/dist/ui/arrangement.d.ts +74 -0
  191. package/dist/ui/arrangement.js +98 -0
  192. package/dist/ui/embed-token.d.ts +2 -2
  193. package/dist/ui/embed-token.js +30 -5
  194. package/dist/ui/registry.d.ts +29 -14
  195. package/dist/ui/registry.js +31 -10
  196. package/dist/ui/slots.controller.d.ts +11 -0
  197. package/dist/ui/slots.controller.js +25 -0
  198. package/dist/ui/ui-stream.d.ts +20 -3
  199. package/dist/ui/ui-stream.js +25 -7
  200. package/dist/ui/ui.schemas.d.ts +66 -0
  201. package/dist/ui/ui.schemas.js +65 -0
  202. package/dist/ui/views.controller.d.ts +35 -49
  203. package/dist/ui/views.controller.js +48 -70
  204. package/dist/ui/views.d.ts +84 -18
  205. package/dist/ui/views.js +201 -38
  206. package/package.json +3 -3
  207. package/src/migrations/0104_connector_tool_account_policies.sql +16 -0
  208. package/src/migrations/0105_devices_rename.sql +136 -0
  209. package/dist/devices/device-auth.module.d.ts +0 -7
  210. package/dist/environments/conversation-environments.d.ts +0 -75
  211. package/dist/environments/dto.d.ts +0 -25
  212. package/dist/environments/dto.js +0 -12
  213. package/dist/environments/environments.controller.d.ts +0 -36
  214. package/dist/environments/environments.module.d.ts +0 -8
  215. package/dist/environments/environments.module.js +0 -31
  216. package/dist/environments/environments.schemas.d.ts +0 -3
  217. package/dist/environments/environments.schemas.js +0 -14
  218. package/dist/environments/label.d.ts +0 -11
  219. package/dist/platform/ops/environments.ops.d.ts +0 -26
  220. package/dist/platform/ops/environments.ops.js +0 -311
@@ -267,14 +267,14 @@ export const PLATFORM_EXCLUSIONS = [
267
267
  category: "transport",
268
268
  reason: "Serves sandbox file bytes",
269
269
  },
270
- // environments (personal cloud environments, environments design phase 1)
270
+ // devices (personal cloud devices, environments design phase 1)
271
271
  // connected machines (environments design phase 2): device sign-in by the program and on the
272
272
  // confirmation page, and disconnecting a machine. The machine's WebSocket (`GET /device/connect`)
273
273
  // is a raw gateway-role route, not a Nest controller, so it is not listed (like the webhook)
274
274
  {
275
- route: "DELETE /api/v1/orgs/:orgId/environments/:id/machine",
275
+ route: "DELETE /api/v1/orgs/:orgId/devices/:id/machine",
276
276
  category: "human-only",
277
- reason: "Disconnects a person's own machine (revokes its credential); a trust decision taken on the environment's page",
277
+ reason: "Disconnects a person's own machine (revokes its credential); a trust decision taken on the device's page",
278
278
  },
279
279
  {
280
280
  route: "POST /api/v1/device/authorize",
@@ -608,6 +608,16 @@ export const PLATFORM_EXCLUSIONS = [
608
608
  category: "secret",
609
609
  reason: "Writes the caller's connector credentials",
610
610
  },
611
+ {
612
+ route: "GET /api/v1/orgs/:orgId/connectors/:connectorId/tool-policies/me",
613
+ category: "internal",
614
+ reason: "Display list of the connector card's 权限 sheet; connectors.get gives an agent the tools and their org defaults",
615
+ },
616
+ {
617
+ route: "PUT /api/v1/orgs/:orgId/connectors/:connectorId/tool-policies/me",
618
+ category: "human-only",
619
+ reason: "A member's own tool policies decide what agents may call with their connection without asking; an agent must never loosen them for itself",
620
+ },
611
621
  {
612
622
  route: "DELETE /api/v1/orgs/:orgId/connectors/:connectorId/credentials/me",
613
623
  category: "secret",
@@ -644,6 +654,11 @@ export const PLATFORM_EXCLUSIONS = [
644
654
  category: "internal",
645
655
  reason: "Navigation entries of the web shell (panels, pages, embeds); nothing an agent acts on",
646
656
  },
657
+ {
658
+ route: "GET /api/v1/orgs/:orgId/ui/arrangement",
659
+ category: "internal",
660
+ reason: "Listing for the 界面位置 page; the arrangement is read and written through org-settings / admin settings",
661
+ },
647
662
  {
648
663
  route: "GET /api/v1/orgs/:orgId/ui/views/:plugin/:id",
649
664
  category: "transport",
@@ -664,6 +679,36 @@ export const PLATFORM_EXCLUSIONS = [
664
679
  category: "transport",
665
680
  reason: "Server-sent event stream of UI invalidations",
666
681
  },
682
+ {
683
+ route: "GET /api/v1/admin/ui/contributions",
684
+ category: "internal",
685
+ reason: "Navigation entries of the admin console (platform pages)",
686
+ },
687
+ {
688
+ route: "GET /api/v1/admin/ui/arrangement",
689
+ category: "internal",
690
+ reason: "Listing for the 界面位置 page; the arrangement is read and written through org-settings / admin settings",
691
+ },
692
+ {
693
+ route: "GET /api/v1/admin/ui/views/:plugin/:id",
694
+ category: "transport",
695
+ reason: "Renders an extension UI view for the web app",
696
+ },
697
+ {
698
+ route: "POST /api/v1/admin/ui/actions/:plugin/:id",
699
+ category: "transport",
700
+ reason: "Runs an extension UI action from the web app",
701
+ },
702
+ {
703
+ route: "POST /api/v1/admin/ui/embeds/:plugin/:id/token",
704
+ category: "transport",
705
+ reason: "Issues an embed token for an iframe",
706
+ },
707
+ {
708
+ route: "GET /api/v1/admin/ui/stream",
709
+ category: "transport",
710
+ reason: "Server-sent event stream of UI invalidations",
711
+ },
667
712
  // themes (themes spec §8-§9)
668
713
  {
669
714
  route: "GET /api/v1/themes/:id/:version/theme.css",
@@ -84,11 +84,15 @@ export const PLATFORM_DOMAINS = [
84
84
  description: "The org's settings (tool search, language, sandbox policy, the Platform tool switch, the default theme): read and change.",
85
85
  },
86
86
  {
87
- id: "environments",
88
- description: "Your own cloud environments (the workspaces your conversations run in): list, read, create, rename, delete, wipe the files.",
87
+ id: "devices",
88
+ description: "Your own cloud devices (the workspaces your conversations run in): list, read, create, rename, delete, wipe the files.",
89
89
  },
90
90
  {
91
91
  id: "themes",
92
92
  description: "The themes on in this org, the one in effect for you and the org's theme setting: list. Themes are set through your preferences, the org settings and the deployment settings.",
93
93
  },
94
+ {
95
+ id: "ui",
96
+ description: "The UI slots an extension can contribute to (the catalog): list. A slot id is a ui contribution's `slot` in a plugin manifest.",
97
+ },
94
98
  ];
@@ -40,6 +40,7 @@ const SettingsInput = DEPLOYMENT_SETTINGS_PATCH.pick({
40
40
  customSkills: true,
41
41
  orgMarketplaceBrowse: true,
42
42
  uiTheme: true,
43
+ uiArrangement: true,
43
44
  }).strict();
44
45
  const ProviderId = ModelProviderParams.shape.provider.describe("The model provider (models.platform-list), e.g. the plugin name of its extension.");
45
46
  /** `provider/model` of a purpose target, or null. */
@@ -121,7 +122,7 @@ let AdminOperations = class AdminOperations {
121
122
  }),
122
123
  defineOperation({
123
124
  id: "admin.update-settings",
124
- description: "Change deployment settings (super admin); give only the keys to change: orgCreation (anyone or super_admin), priceCurrency (ISO 4217 code), customConnectors / customSkills (allow or deny: whether orgs may create their own instead of installing from the catalog), orgMarketplaceBrowse (true or false), uiTheme ({ id }: the platform default theme, a platform theme whose scope is all, or null for the built-in theme; it is what every org falls back to and what the sign-in pages show). Per-org limits are orgs.set-limits.",
125
+ description: "Change deployment settings (super admin); give only the keys to change: orgCreation (anyone or super_admin), priceCurrency (ISO 4217 code), customConnectors / customSkills (allow or deny: whether orgs may create their own instead of installing from the catalog), orgMarketplaceBrowse (true or false), uiTheme ({ id }: the platform default theme, a platform theme whose scope is all, or null for the built-in theme; it is what every org falls back to and what the sign-in pages show), uiArrangement ({ <slot>: { hidden, order } }: the platform default arrangement of UI slots, with contribution keys <extension>/<contribution>; hidden ones are not listed but still open by URL; null for a slot removes its entry). Per-org limits are orgs.set-limits.",
125
126
  input: SettingsInput.refine((b) => Object.keys(b).length > 0, {
126
127
  message: "at least one setting is required",
127
128
  }),
@@ -148,7 +149,7 @@ let AdminOperations = class AdminOperations {
148
149
  : { ok: false, code: "validation_failed", message: r.error.issues[0]?.message ?? "" };
149
150
  },
150
151
  summary: async (i) => {
151
- const { uiTheme, ...rest } = i;
152
+ const { uiTheme, uiArrangement, ...rest } = i;
152
153
  const parts = Object.entries(rest).map(([k, v]) => `${k}=${String(v)}`);
153
154
  const zh = [...parts];
154
155
  const en = [...parts];
@@ -158,6 +159,11 @@ let AdminOperations = class AdminOperations {
158
159
  zh.push(`uiTheme=${uiTheme.id === null ? "内置主题" : (name?.zh ?? uiTheme.id)}`);
159
160
  en.push(`uiTheme=${uiTheme.id === null ? "built-in theme" : (name?.en ?? uiTheme.id)}`);
160
161
  }
162
+ if (uiArrangement !== undefined) {
163
+ const slots = Object.keys(uiArrangement).join(", ");
164
+ zh.push(`uiArrangement(${slots})`);
165
+ en.push(`uiArrangement (${slots})`);
166
+ }
161
167
  return {
162
168
  zh: `修改平台部署设置:${zh.join(",")}`,
163
169
  en: `Change the deployment settings: ${en.join(", ")}`,
@@ -40,6 +40,15 @@ const RouteSkills = Def.skills.unwrap();
40
40
  const Skills = RouteSkills.pick({ pinned: true })
41
41
  .extend({ orgSkills: RouteSkills.shape.orgSkills.unwrap() })
42
42
  .strict();
43
+ /**
44
+ * Whether `next` sets an `allow` that `current` does not have (decision 2026-11-09: `allow` on a
45
+ * connector tool lets an agent call it without asking). Such a change is confirmed every time and
46
+ * never remembered, so an agent can never loosen its own policies on a grant the person remembered
47
+ * for ordinary edits.
48
+ */
49
+ function addsAllow(next, current) {
50
+ return Object.entries(next ?? {}).some(([k, v]) => v === "allow" && current?.[k] !== "allow");
51
+ }
43
52
  /** The definition fields an agent can set through the tool; the rest keep the web's defaults. */
44
53
  const Fields = {
45
54
  name: Def.name,
@@ -156,8 +165,10 @@ let AgentsOperations = class AgentsOperations {
156
165
  * `agents.update`'s class (spec §13): `personal` (may be remembered) only on a private agent the
157
166
  * actor owns; any other agent the actor may edit is shared, so each change is confirmed.
158
167
  */
159
- async updateClass(agentId, ctx) {
168
+ async updateClass(agentId, toolPolicies, ctx) {
160
169
  const a = await this.agents.get(ctx.orgId, agentId, ctx.actorAccountId);
170
+ if (addsAllow(toolPolicies, a.definition.toolPolicies))
171
+ return "org";
161
172
  return a.visibility === "private" && a.ownerAccountId === ctx.actorAccountId
162
173
  ? "personal"
163
174
  : "org";
@@ -221,6 +232,8 @@ let AgentsOperations = class AgentsOperations {
221
232
  omits: ["memberIds", "profile"],
222
233
  loosens: { visibility: "optional: the operation creates private agents only" },
223
234
  confirm: "personal",
235
+ // an `allow` loosens: never on a remembered grant
236
+ confirmFor: async (i) => addsAllow(i.definition.toolPolicies, undefined) ? "org" : "personal",
224
237
  summary: (i) => ({
225
238
  zh: `新建私有智能体「${i.definition.name}」`,
226
239
  en: `Create private agent "${i.definition.name}"`,
@@ -246,7 +259,7 @@ let AgentsOperations = class AgentsOperations {
246
259
  }),
247
260
  defineOperation({
248
261
  id: "agents.update",
249
- description: 'Change an agent you may edit: your own, private or shared, and as an org admin any agent of the org. Send the version you read from agents.get and only the fields to change; the others keep their value. The description (one short paragraph, "" removes it) is saved with the definition; the avatar and quick actions are changed with agents.update-profile. disabledTools replaces the whole list of turned-off tools (send [] to turn every tool on). A version that is no longer current is refused, so read the agent again first. The visibility cannot be changed here (that is done on the agents page of the web app). A change to your own private agent may be remembered by the person; a change to a shared agent is confirmed every time.',
262
+ description: 'Change an agent you may edit: your own, private or shared, and as an org admin any agent of the org. Send the version you read from agents.get and only the fields to change; the others keep their value. The description (one short paragraph, "" removes it) is saved with the definition; the avatar and quick actions are changed with agents.update-profile. disabledTools replaces the whole list of turned-off tools (send [] to turn every tool on). A version that is no longer current is refused, so read the agent again first. The visibility cannot be changed here (that is done on the agents page of the web app). A change to your own private agent may be remembered by the person; a change to a shared agent, or one that sets a tool policy to allow, is confirmed every time.',
250
263
  input: z
251
264
  .object({
252
265
  agentId: AgentId,
@@ -289,7 +302,7 @@ let AgentsOperations = class AgentsOperations {
289
302
  next: "The agent changed since you read it: read it again with agents.get, then send its current version.",
290
303
  },
291
304
  ],
292
- confirmFor: (i, ctx) => this.updateClass(i.agentId, ctx),
305
+ confirmFor: (i, ctx) => this.updateClass(i.agentId, i.toolPolicies, ctx),
293
306
  summary: async (i, ctx) => {
294
307
  const a = await this.agents.get(ctx.orgId, i.agentId, ctx.actorAccountId);
295
308
  const name = named(a.definition.name);
@@ -353,7 +366,7 @@ let AgentsOperations = class AgentsOperations {
353
366
  // needs no declaration: an input that accepts less than the route passes the parity test.
354
367
  omits: ["expectedUpdatedAt"],
355
368
  confirm: "personal",
356
- confirmFor: (i, ctx) => this.updateClass(i.agentId, ctx),
369
+ confirmFor: (i, ctx) => this.updateClass(i.agentId, undefined, ctx),
357
370
  errors: [
358
371
  {
359
372
  code: "agent.not_found",
@@ -493,7 +506,7 @@ let AgentsOperations = class AgentsOperations {
493
506
  confirm: "personal",
494
507
  // destructive: asked every time and never remembered, a shared agent as an org write
495
508
  rememberable: false,
496
- confirmFor: (i, ctx) => this.updateClass(i.agentId, ctx),
509
+ confirmFor: (i, ctx) => this.updateClass(i.agentId, undefined, ctx),
497
510
  errors: [
498
511
  {
499
512
  code: "agent.not_found",
@@ -578,7 +591,7 @@ let AgentsOperations = class AgentsOperations {
578
591
  authz: { orgAction: "agents.create" },
579
592
  mirrors: ["POST /api/v1/orgs/:orgId/agents/:agentId/pending-connectors/:key/bind"],
580
593
  confirm: "personal",
581
- confirmFor: (i, ctx) => this.updateClass(i.agentId, ctx),
594
+ confirmFor: (i, ctx) => this.updateClass(i.agentId, undefined, ctx),
582
595
  errors: [
583
596
  {
584
597
  code: "agent.pending_connector_not_found",
@@ -1,6 +1,6 @@
1
1
  import { type OnModuleInit } from "@nestjs/common";
2
2
  import { ConversationsService } from "../../conversations/conversations.service.js";
3
- import { ConversationEnvironmentStatus } from "../../conversations/environment-status.js";
3
+ import { ConversationDeviceStatus } from "../../conversations/device-status.js";
4
4
  import { ConversationFiles } from "../../conversations/files.js";
5
5
  import { KernelDb } from "../../infra/database/kernel-db.js";
6
6
  import { PlatformOperations } from "../registry.js";
@@ -14,9 +14,9 @@ export declare class ConversationsOperations implements OnModuleInit {
14
14
  private readonly registry;
15
15
  private readonly conversations;
16
16
  private readonly files;
17
- private readonly environment;
17
+ private readonly device;
18
18
  private readonly kdb;
19
- constructor(registry: PlatformOperations, conversations: ConversationsService, files: ConversationFiles, environment: ConversationEnvironmentStatus, kdb: KernelDb);
19
+ constructor(registry: PlatformOperations, conversations: ConversationsService, files: ConversationFiles, device: ConversationDeviceStatus, kdb: KernelDb);
20
20
  /**
21
21
  * Whether `id` is the conversation this run belongs to: its ROOT (the Platform tool also runs in
22
22
  * sub-agents, whose own id is not the person's conversation). Stopping or deleting it would end
@@ -11,7 +11,7 @@ import { Inject, Injectable } from "@nestjs/common";
11
11
  import { z } from "zod";
12
12
  import { EventsQuery, FilesQuery, IdParams, ListQuery, PatchBody, SubagentsQuery, } from "../../conversations/conversations.schemas.js";
13
13
  import { ConversationsService, } from "../../conversations/conversations.service.js";
14
- import { ConversationEnvironmentStatus } from "../../conversations/environment-status.js";
14
+ import { ConversationDeviceStatus } from "../../conversations/device-status.js";
15
15
  import { ConversationFiles } from "../../conversations/files.js";
16
16
  import { KernelDb } from "../../infra/database/kernel-db.js";
17
17
  import { rootConversationOf } from "../../runtime/subagents/child.js";
@@ -41,13 +41,13 @@ let ConversationsOperations = class ConversationsOperations {
41
41
  registry;
42
42
  conversations;
43
43
  files;
44
- environment;
44
+ device;
45
45
  kdb;
46
- constructor(registry, conversations, files, environment, kdb) {
46
+ constructor(registry, conversations, files, device, kdb) {
47
47
  this.registry = registry;
48
48
  this.conversations = conversations;
49
49
  this.files = files;
50
- this.environment = environment;
50
+ this.device = device;
51
51
  this.kdb = kdb;
52
52
  }
53
53
  /**
@@ -348,12 +348,12 @@ let ConversationsOperations = class ConversationsOperations {
348
348
  },
349
349
  }),
350
350
  defineOperation({
351
- id: "conversations.environment",
352
- description: "Read the environment one of your conversations works in and whether its instance is running or suspended; environment is null while the conversation has none. Takes the id from conversations.list.",
351
+ id: "conversations.device",
352
+ description: "Read the device one of your conversations works in and whether its instance is running or suspended; device is null while the conversation has none. Takes the id from conversations.list.",
353
353
  input: Id,
354
354
  example: { conversationId: "3f2b8a40-6c1d-4e0b-9a77-5d1e2c8b9f10" },
355
355
  authz: { orgAction: "agents.use" },
356
- mirrors: ["GET /api/v1/orgs/:orgId/conversations/:id/environment"],
356
+ mirrors: ["GET /api/v1/orgs/:orgId/conversations/:id/device"],
357
357
  renames: { conversationId: "id" },
358
358
  errors: [
359
359
  {
@@ -363,7 +363,7 @@ let ConversationsOperations = class ConversationsOperations {
363
363
  ],
364
364
  confirm: "read",
365
365
  run: async (input, ctx) => ({
366
- environment: await this.environment.get(ctx.orgId, input.conversationId, ctx.actorAccountId),
366
+ device: await this.device.get(ctx.orgId, input.conversationId, ctx.actorAccountId),
367
367
  }),
368
368
  }),
369
369
  defineOperation({
@@ -464,7 +464,7 @@ ConversationsOperations = __decorate([
464
464
  __param(0, Inject(PlatformOperations)),
465
465
  __param(1, Inject(ConversationsService)),
466
466
  __param(2, Inject(ConversationFiles)),
467
- __param(3, Inject(ConversationEnvironmentStatus)),
467
+ __param(3, Inject(ConversationDeviceStatus)),
468
468
  __param(4, Inject(KernelDb))
469
469
  ], ConversationsOperations);
470
470
  export { ConversationsOperations };
@@ -0,0 +1,26 @@
1
+ import { type OnModuleInit } from "@nestjs/common";
2
+ import { DevicesService } from "../../devices/devices.service.js";
3
+ import { KernelDb } from "../../infra/database/kernel-db.js";
4
+ import { PlatformOperations } from "../registry.js";
5
+ /**
6
+ * Device operations of the `Platform` tool (environments design, phase 1): a person's own
7
+ * cloud devices. Phase 1 has personal devices only, visible to their owner alone, so
8
+ * these are `personal` writes. A cloud device carries no credentials or device connection;
9
+ * deleting one and wiping its files are `personal` writes that are never remembered.
10
+ */
11
+ export declare class DevicesOperations implements OnModuleInit {
12
+ private readonly registry;
13
+ private readonly devices;
14
+ private readonly kdb;
15
+ constructor(registry: PlatformOperations, devices: DevicesService, kdb: KernelDb);
16
+ /**
17
+ * Whether `id` is the device the run works in: the one its root conversation is bound to
18
+ * (sub-agents use the root's). Deleting or wiping it would pull the sandbox from under the run.
19
+ */
20
+ private isRunsDevice;
21
+ /** The precheck of a destructive write: never the run's own device, then the service's. */
22
+ private precheckDestructive;
23
+ /** The device's name for a card; its id when it cannot be read. */
24
+ private label;
25
+ onModuleInit(): void;
26
+ }
@@ -0,0 +1,311 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import { Inject, Injectable } from "@nestjs/common";
11
+ import { z } from "zod";
12
+ import { DevicesService } from "../../devices/devices.service.js";
13
+ import { DeviceNameBody, DeviceParams } from "../../devices/dto.js";
14
+ import { deviceLabel } from "../../devices/label.js";
15
+ import { KernelDb } from "../../infra/database/kernel-db.js";
16
+ import { rootConversationOf } from "../../runtime/subagents/child.js";
17
+ import { defineOperation } from "../operation.js";
18
+ import { PlatformOperations } from "../registry.js";
19
+ import { precheckBy, viaAgent } from "./errors.js";
20
+ import { named, orElse } from "./summary.js";
21
+ const DeviceId = z.object({ deviceId: DeviceParams.shape.id }).strict();
22
+ const Name = z.object({ name: DeviceNameBody.shape.name }).strict();
23
+ /**
24
+ * Model-facing names are English: the default is "Personal", a default demoted by a provider
25
+ * switch "Personal (Docker sandbox)" (the web shows 「个人设备」 / 「个人设备(Docker 沙箱)」).
26
+ */
27
+ const labelOf = (e) => deviceLabel(e, "en");
28
+ /** A row's state: why it cannot be used now, else whether its instance runs. */
29
+ function stateOf(e) {
30
+ if (!e.available) {
31
+ return {
32
+ state: "unavailable",
33
+ reason: "Its sandbox provider is no longer the deployment's current one.",
34
+ next: "Ask an org admin; use another device meanwhile.",
35
+ };
36
+ }
37
+ if (e.filesLost && e.source === "local") {
38
+ return {
39
+ state: "files_lost",
40
+ reason: "Its directory is gone from the connected machine.",
41
+ next: "Ask the person to run capybara-device logout, then capybara-device login into this device, on that machine.",
42
+ };
43
+ }
44
+ if (e.filesLost) {
45
+ return {
46
+ state: "files_lost",
47
+ reason: "Its file system is gone at the provider.",
48
+ next: "Wipe its files with devices.reset-files to use it again.",
49
+ };
50
+ }
51
+ return { state: e.instance?.status ?? "ready" };
52
+ }
53
+ const row = (e) => ({
54
+ id: e.id,
55
+ name: labelOf(e),
56
+ ...stateOf(e),
57
+ isDefault: e.isDefault,
58
+ source: e.source,
59
+ provider: e.provider,
60
+ online: e.online,
61
+ machine: e.machine && {
62
+ name: e.machine.name,
63
+ os: e.machine.os,
64
+ lastSeenAt: e.machine.lastSeenAt,
65
+ },
66
+ lastUsedAt: e.instance?.lastUsedAt ?? null,
67
+ });
68
+ /**
69
+ * Device operations of the `Platform` tool (environments design, phase 1): a person's own
70
+ * cloud devices. Phase 1 has personal devices only, visible to their owner alone, so
71
+ * these are `personal` writes. A cloud device carries no credentials or device connection;
72
+ * deleting one and wiping its files are `personal` writes that are never remembered.
73
+ */
74
+ let DevicesOperations = class DevicesOperations {
75
+ registry;
76
+ devices;
77
+ kdb;
78
+ constructor(registry, devices, kdb) {
79
+ this.registry = registry;
80
+ this.devices = devices;
81
+ this.kdb = kdb;
82
+ }
83
+ /**
84
+ * Whether `id` is the device the run works in: the one its root conversation is bound to
85
+ * (sub-agents use the root's). Deleting or wiping it would pull the sandbox from under the run.
86
+ */
87
+ async isRunsDevice(id, ctx) {
88
+ const root = await rootConversationOf(this.kdb.db, ctx.conversationId);
89
+ const row = await this.kdb.db
90
+ .selectFrom("conversations")
91
+ .select("device_id")
92
+ .where("id", "=", root)
93
+ .where("org_id", "=", ctx.orgId)
94
+ .executeTakeFirst();
95
+ return row?.device_id === id;
96
+ }
97
+ /** The precheck of a destructive write: never the run's own device, then the service's. */
98
+ async precheckDestructive(id, ctx, verb, read) {
99
+ if (await this.isRunsDevice(id, ctx)) {
100
+ return {
101
+ ok: false,
102
+ code: "device.current",
103
+ message: `The device you are running in cannot be ${verb} from here.`,
104
+ };
105
+ }
106
+ return precheckBy(read);
107
+ }
108
+ /** The device's name for a card; its id when it cannot be read. */
109
+ label(ctx, id) {
110
+ return orElse(async () => named(labelOf(await this.devices.get(ctx.orgId, ctx.actorAccountId, id))), id);
111
+ }
112
+ onModuleInit() {
113
+ this.registry.register([
114
+ defineOperation({
115
+ id: "devices.list",
116
+ description: "List your own devices in this org: one compact row each (name, state, whether it is the default, source: cloud or local, provider, whether a local one is online and its machine, last use), plus the default and last used ids and whether new cloud devices can be made. The default device is shown as Personal; a former default left behind by a sandbox provider switch is shown as Personal (<provider>) and becomes the default again when that provider is back.",
117
+ input: z.object({}).strict(),
118
+ example: {},
119
+ authz: { orgAction: "agents.use" },
120
+ mirrors: ["GET /api/v1/orgs/:orgId/devices"],
121
+ confirm: "read",
122
+ run: async (_input, ctx) => {
123
+ const l = await this.devices.list(ctx.orgId, ctx.actorAccountId);
124
+ return {
125
+ items: l.items.map(row),
126
+ defaultId: l.defaultId,
127
+ lastUsedId: l.lastUsedId,
128
+ cloudAvailable: l.cloudAvailable,
129
+ };
130
+ },
131
+ }),
132
+ defineOperation({
133
+ id: "devices.get",
134
+ description: "Read one of your devices with its source (cloud or local), provider, state, instance, the machine of a local one and whether it is online, limits and creation time. Takes the id from devices.list.",
135
+ input: DeviceId,
136
+ example: { deviceId: "4e8a0c1d-6b2f-4a37-8d19-3c5e7f9a1b20" },
137
+ authz: { orgAction: "agents.use" },
138
+ mirrors: ["GET /api/v1/orgs/:orgId/devices/:id"],
139
+ renames: { deviceId: "id" },
140
+ confirm: "read",
141
+ errors: [
142
+ {
143
+ code: "device.not_found",
144
+ next: "Check the id with devices.list: you only see your own devices.",
145
+ },
146
+ ],
147
+ run: async (input, ctx) => {
148
+ const e = await this.devices.get(ctx.orgId, ctx.actorAccountId, input.deviceId);
149
+ return { device: { ...e, name: labelOf(e), ...stateOf(e) } };
150
+ },
151
+ }),
152
+ defineOperation({
153
+ id: "devices.create",
154
+ description: "Create a personal cloud device with a name (1-64 characters, unique among yours, case-insensitive). It is ready at once; its instance and files are made on first use. It needs a sandbox provider and is limited per person.",
155
+ input: Name,
156
+ example: { name: "Data analysis" },
157
+ authz: { orgAction: "agents.use" },
158
+ mirrors: ["POST /api/v1/orgs/:orgId/devices"],
159
+ confirm: "personal",
160
+ errors: [
161
+ {
162
+ code: "device.name_taken",
163
+ next: "You have a device with this name: pick another name, or read yours with devices.list.",
164
+ },
165
+ {
166
+ code: "device.limit_reached",
167
+ next: "You are at the limit: delete a device you no longer need with devices.delete, or use an existing one.",
168
+ },
169
+ {
170
+ code: "device.current",
171
+ next: "This conversation works in it: ask the person to wipe it on the web, or wipe a different one.",
172
+ },
173
+ {
174
+ code: "device.unavailable",
175
+ next: {
176
+ superAdmin: "No sandbox provider is current: set one up in the admin console under extensions, then call again.",
177
+ orgAdmin: "No sandbox provider is set up; ask the super admin.",
178
+ member: "No sandbox provider is set up in this deployment; ask an org admin.",
179
+ },
180
+ },
181
+ ],
182
+ precheck: (i, ctx) => precheckBy(() => this.devices.checkCreate(ctx.orgId, ctx.actorAccountId, i.name)),
183
+ summary: (i) => ({
184
+ zh: `新建个人云端设备「${named(i.name)}」`,
185
+ en: `Create personal cloud device "${named(i.name)}"`,
186
+ }),
187
+ run: async (input, ctx) => {
188
+ const e = await this.devices.create(ctx.orgId, ctx.actorAccountId, { name: input.name }, undefined, viaAgent("devices.create", ctx));
189
+ return { device: row(e) };
190
+ },
191
+ }),
192
+ defineOperation({
193
+ id: "devices.delete",
194
+ description: "Delete one of your devices, the default one included: its instance and ALL its files are destroyed after the response and cannot be recovered. Conversations bound to it keep pointing at it and their sandbox tools then fail. The person confirms every delete; it is never remembered. The device this conversation works in cannot be deleted. Takes the id from devices.list.",
195
+ input: DeviceId,
196
+ example: { deviceId: "4e8a0c1d-6b2f-4a37-8d19-3c5e7f9a1b20" },
197
+ authz: { orgAction: "agents.use" },
198
+ mirrors: ["DELETE /api/v1/orgs/:orgId/devices/:id"],
199
+ renames: { deviceId: "id" },
200
+ confirm: "personal",
201
+ // destructive: asked every time and never remembered
202
+ rememberable: false,
203
+ errors: [
204
+ {
205
+ code: "device.not_found",
206
+ next: "Check the id with devices.list: you only see your own devices.",
207
+ },
208
+ {
209
+ code: "device.current",
210
+ next: "This conversation works in it: ask the person to delete it on the web, or delete a different one.",
211
+ },
212
+ ],
213
+ precheck: (i, ctx) => this.precheckDestructive(i.deviceId, ctx, "deleted", () => this.devices.get(ctx.orgId, ctx.actorAccountId, i.deviceId)),
214
+ summary: async (i, ctx) => {
215
+ const n = await this.label(ctx, i.deviceId);
216
+ const c = await orElse(() => this.devices.boundConversations(ctx.orgId, ctx.actorAccountId, i.deviceId), 0);
217
+ return {
218
+ zh: `删除设备「${n}」:其中所有文件将被销毁且无法恢复;使用它的 ${c} 个对话将失去沙箱(沙箱工具会失败)`,
219
+ en: `Delete device "${n}": all its files are destroyed and cannot be recovered; the ${c} conversations using it lose their sandbox (their sandbox tools fail)`,
220
+ };
221
+ },
222
+ run: async (input, ctx) => {
223
+ await this.devices.remove(ctx.orgId, ctx.actorAccountId, input.deviceId, undefined, viaAgent("devices.delete", ctx));
224
+ return { id: input.deviceId, deleted: true };
225
+ },
226
+ }),
227
+ defineOperation({
228
+ id: "devices.reset-files",
229
+ description: "Wipe one of your devices' files so it starts empty: ALL its files are destroyed (after running commands finish) and cannot be recovered; the next use creates a fresh workspace. Use it when a device reports its files are lost (not for a connected machine's device: its files are on the machine). The person confirms every reset; it is never remembered. The device this conversation works in cannot be wiped. Takes the id from devices.list.",
230
+ input: DeviceId,
231
+ example: { deviceId: "4e8a0c1d-6b2f-4a37-8d19-3c5e7f9a1b20" },
232
+ authz: { orgAction: "agents.use" },
233
+ mirrors: ["POST /api/v1/orgs/:orgId/devices/:id/files/reset"],
234
+ renames: { deviceId: "id" },
235
+ confirm: "personal",
236
+ rememberable: false,
237
+ errors: [
238
+ {
239
+ code: "device.not_found",
240
+ next: "Check the id with devices.list: you only see your own devices.",
241
+ },
242
+ {
243
+ code: "device.current",
244
+ next: "This conversation works in it: ask the person to wipe it on the web, or wipe a different one.",
245
+ },
246
+ {
247
+ code: "device.files_on_device",
248
+ next: "Its files are on its connected machine: ask the person to run capybara-device logout, then capybara-device login into this device, on that machine.",
249
+ },
250
+ {
251
+ code: "device.unavailable",
252
+ next: {
253
+ orgAdmin: "Its sandbox provider is no longer the current one: use another device, or ask the super admin about the provider.",
254
+ member: "Its sandbox provider is no longer the current one: use another device, or ask an org admin.",
255
+ },
256
+ },
257
+ ],
258
+ precheck: (i, ctx) => this.precheckDestructive(i.deviceId, ctx, "wiped", () => this.devices.checkReset(ctx.orgId, ctx.actorAccountId, i.deviceId)),
259
+ summary: async (i, ctx) => {
260
+ const n = await this.label(ctx, i.deviceId);
261
+ return {
262
+ zh: `清空设备「${n}」的文件:所有文件将被销毁且无法恢复`,
263
+ en: `Wipe the files of device "${n}": all files are destroyed and cannot be recovered`,
264
+ };
265
+ },
266
+ run: async (input, ctx) => {
267
+ await this.devices.resetFiles(ctx.orgId, ctx.actorAccountId, input.deviceId, undefined, viaAgent("devices.reset-files", ctx));
268
+ return { id: input.deviceId, reset: true };
269
+ },
270
+ }),
271
+ defineOperation({
272
+ id: "devices.rename",
273
+ description: "Rename one of your devices, the default one included (it then has a name). The new name is 1-64 characters and unique among yours, case-insensitive. Takes the id from devices.list.",
274
+ input: DeviceId.extend({ name: DeviceNameBody.shape.name }).strict(),
275
+ example: { deviceId: "4e8a0c1d-6b2f-4a37-8d19-3c5e7f9a1b20", name: "Reports" },
276
+ authz: { orgAction: "agents.use" },
277
+ mirrors: ["PATCH /api/v1/orgs/:orgId/devices/:id"],
278
+ renames: { deviceId: "id" },
279
+ confirm: "personal",
280
+ errors: [
281
+ {
282
+ code: "device.not_found",
283
+ next: "Check the id with devices.list: you only see your own devices.",
284
+ },
285
+ {
286
+ code: "device.name_taken",
287
+ next: "You have a device with this name: pick another name.",
288
+ },
289
+ ],
290
+ precheck: (i, ctx) => precheckBy(() => this.devices.checkRename(ctx.orgId, ctx.actorAccountId, i.deviceId, i.name)),
291
+ summary: async (i, ctx) => {
292
+ const from = await orElse(async () => named(labelOf(await this.devices.get(ctx.orgId, ctx.actorAccountId, i.deviceId))), i.deviceId);
293
+ return {
294
+ zh: `将设备「${from}」重命名为「${named(i.name)}」`,
295
+ en: `Rename device "${from}" to "${named(i.name)}"`,
296
+ };
297
+ },
298
+ run: async (input, ctx) => ({
299
+ device: row(await this.devices.rename(ctx.orgId, ctx.actorAccountId, input.deviceId, input.name, undefined, viaAgent("devices.rename", ctx))),
300
+ }),
301
+ }),
302
+ ]);
303
+ }
304
+ };
305
+ DevicesOperations = __decorate([
306
+ Injectable(),
307
+ __param(0, Inject(PlatformOperations)),
308
+ __param(1, Inject(DevicesService)),
309
+ __param(2, Inject(KernelDb))
310
+ ], DevicesOperations);
311
+ export { DevicesOperations };