@capybara-hq/kernel 0.1.0-rc.12 → 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.
- package/dist/admin/admin.schemas.d.ts +13 -0
- package/dist/agents/agent-lookup.d.ts +5 -0
- package/dist/agents/agent-lookup.js +15 -0
- package/dist/background/background.module.js +2 -2
- package/dist/background/launch-lock.d.ts +1 -1
- package/dist/background/launch-lock.js +1 -1
- package/dist/background/poll.job.d.ts +2 -2
- package/dist/background/poll.job.js +10 -10
- package/dist/background/stop.d.ts +1 -1
- package/dist/background/stop.js +3 -3
- package/dist/background/store.d.ts +5 -5
- package/dist/background/store.js +5 -5
- package/dist/background/tasks.service.d.ts +6 -6
- package/dist/background/tasks.service.js +13 -13
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/channels/channels.module.js +2 -2
- package/dist/channels/inbound.d.ts +8 -8
- package/dist/channels/inbound.js +31 -31
- package/dist/channels/phrases.d.ts +27 -27
- package/dist/channels/phrases.js +27 -27
- package/dist/config/docs.js +1 -1
- package/dist/config/schema.d.ts +2 -2
- package/dist/config/schema.js +21 -21
- package/dist/conversations/conversations.controller.d.ts +11 -11
- package/dist/conversations/conversations.controller.js +15 -15
- package/dist/conversations/conversations.module.d.ts +1 -1
- package/dist/conversations/conversations.module.js +7 -7
- package/dist/conversations/conversations.schemas.js +1 -1
- package/dist/conversations/conversations.service.d.ts +14 -14
- package/dist/conversations/conversations.service.js +19 -19
- package/dist/conversations/{environment-status.d.ts → device-status.d.ts} +9 -9
- package/dist/conversations/{environment-status.js → device-status.js} +18 -18
- package/dist/conversations/event-log.d.ts +1 -1
- package/dist/conversations/event-log.js +1 -1
- package/dist/conversations/events.d.ts +1 -1
- package/dist/conversations/events.js +2 -2
- package/dist/ctx/create-ctx.d.ts +10 -1
- package/dist/ctx/create-ctx.js +86 -25
- package/dist/db/kernel-schema.d.ts +26 -23
- package/dist/{environments → devices}/access.d.ts +19 -19
- package/dist/{environments → devices}/access.js +28 -28
- package/dist/devices/conversation-devices.d.ts +75 -0
- package/dist/{environments/conversation-environments.js → devices/conversation-devices.js} +71 -72
- package/dist/devices/devices.controller.d.ts +36 -0
- package/dist/{environments/environments.controller.js → devices/devices.controller.js} +37 -37
- package/dist/devices/devices.module.d.ts +5 -13
- package/dist/devices/devices.module.js +16 -29
- package/dist/devices/devices.schemas.d.ts +3 -0
- package/dist/devices/devices.schemas.js +14 -0
- package/dist/{environments/environments.service.d.ts → devices/devices.service.d.ts} +70 -70
- package/dist/{environments/environments.service.js → devices/devices.service.js} +122 -122
- package/dist/devices/dto.d.ts +13 -54
- package/dist/devices/dto.js +7 -39
- package/dist/devices/label.d.ts +11 -0
- package/dist/{environments → devices}/label.js +7 -7
- package/dist/{environments → devices}/legacy-cleanup.job.d.ts +3 -3
- package/dist/{environments → devices}/legacy-cleanup.job.js +3 -3
- package/dist/errors.d.ts +25 -25
- package/dist/errors.js +25 -25
- package/dist/evals/recorded-tools.d.ts +2 -2
- package/dist/evals/recorded-tools.js +6 -6
- package/dist/extensions/admin-ops.js +1 -0
- package/dist/extensions/admin-view.js +2 -0
- package/dist/extensions/effective-config.d.ts +6 -0
- package/dist/extensions/effective-config.js +18 -7
- package/dist/extensions/host.d.ts +13 -2
- package/dist/extensions/host.js +24 -3
- package/dist/extensions/instance.d.ts +12 -1
- package/dist/extensions/instance.js +13 -0
- package/dist/extensions/permission-view.d.ts +10 -1
- package/dist/files/previewers.d.ts +1 -1
- package/dist/files/previewers.js +1 -1
- package/dist/http/api.module.js +10 -6
- package/dist/http/gateway-routes.d.ts +1 -1
- package/dist/http/gateway-routes.js +1 -1
- package/dist/identity/settings.d.ts +32 -0
- package/dist/identity/settings.js +26 -2
- package/dist/infra/config/kernel-config.service.js +4 -4
- package/dist/kernel.module.js +3 -3
- package/dist/{devices → local-devices}/device-auth.controller.d.ts +6 -6
- package/dist/{devices → local-devices}/device-auth.controller.js +5 -5
- package/dist/{devices → local-devices}/device-auth.d.ts +20 -20
- package/dist/{devices → local-devices}/device-auth.js +51 -53
- package/dist/local-devices/device-auth.module.d.ts +7 -0
- package/dist/{devices → local-devices}/device-auth.module.js +5 -5
- package/dist/{devices → local-devices}/device-routes.d.ts +3 -3
- package/dist/{devices → local-devices}/device-routes.js +2 -2
- package/dist/local-devices/dto.d.ts +66 -0
- package/dist/local-devices/dto.js +44 -0
- package/dist/{devices → local-devices}/keys.d.ts +11 -11
- package/dist/{devices → local-devices}/keys.js +11 -11
- package/dist/{devices/device-gateway.d.ts → local-devices/local-device-gateway.d.ts} +14 -14
- package/dist/{devices/device-gateway.js → local-devices/local-device-gateway.js} +44 -44
- package/dist/{devices/device-provider.d.ts → local-devices/local-device-provider.d.ts} +15 -15
- package/dist/{devices/device-provider.js → local-devices/local-device-provider.js} +23 -23
- package/dist/local-devices/local-devices.module.d.ts +16 -0
- package/dist/local-devices/local-devices.module.js +44 -0
- package/dist/{devices → local-devices}/machines.d.ts +26 -26
- package/dist/{devices → local-devices}/machines.js +71 -71
- package/dist/{devices → local-devices}/relay.d.ts +15 -15
- package/dist/{devices → local-devices}/relay.js +55 -55
- package/dist/{devices → local-devices}/targets.d.ts +8 -8
- package/dist/{devices → local-devices}/targets.js +14 -14
- package/dist/orgs/offboarding.d.ts +6 -6
- package/dist/orgs/offboarding.js +12 -12
- package/dist/orgs/settings.service.d.ts +28 -0
- package/dist/orgs/settings.service.js +20 -1
- package/dist/platform/exclusions.js +38 -3
- package/dist/platform/operation.js +6 -2
- package/dist/platform/ops/admin.ops.js +8 -2
- package/dist/platform/ops/conversations.ops.d.ts +3 -3
- package/dist/platform/ops/conversations.ops.js +9 -9
- package/dist/platform/ops/devices.ops.d.ts +26 -0
- package/dist/platform/ops/devices.ops.js +311 -0
- package/dist/platform/ops/org-settings.ops.js +2 -2
- package/dist/platform/ops/orgs.ops.js +1 -0
- package/dist/platform/ops/ui.ops.d.ts +8 -0
- package/dist/platform/ops/ui.ops.js +41 -0
- package/dist/platform/platform-ops.module.d.ts +3 -2
- package/dist/platform/platform-ops.module.js +8 -5
- package/dist/platform/route-schemas.js +6 -3
- package/dist/roles/gateway-role.d.ts +3 -3
- package/dist/roles/gateway-role.js +4 -4
- package/dist/roles/gateway.module.d.ts +1 -1
- package/dist/roles/gateway.module.js +5 -5
- package/dist/roles/worker.module.js +1 -1
- package/dist/runtime/context/build.d.ts +1 -1
- package/dist/runtime/context/build.js +6 -6
- package/dist/runtime/context/compaction.js +1 -1
- package/dist/runtime/context/{environment-paths.d.ts → device-paths.d.ts} +11 -11
- package/dist/runtime/context/{environment-paths.js → device-paths.js} +13 -13
- package/dist/runtime/maintenance.d.ts +1 -1
- package/dist/sandbox/jobs.d.ts +13 -13
- package/dist/sandbox/jobs.js +20 -20
- package/dist/sandbox/leases.d.ts +9 -9
- package/dist/sandbox/leases.js +14 -14
- package/dist/sandbox/providers.d.ts +8 -8
- package/dist/sandbox/providers.js +8 -8
- package/dist/sandbox/sandbox.module.d.ts +1 -1
- package/dist/sandbox/sandbox.module.js +1 -1
- package/dist/sandbox/sandbox.service.d.ts +76 -76
- package/dist/sandbox/sandbox.service.js +230 -230
- package/dist/tools/builtins/builtin-tools.d.ts +2 -2
- package/dist/tools/builtins/builtin-tools.js +5 -5
- package/dist/tools/builtins/platform.js +1 -1
- package/dist/tools/builtins/sandbox/bash.js +6 -6
- package/dist/tools/builtins/sandbox/common.d.ts +25 -25
- package/dist/tools/builtins/sandbox/common.js +51 -51
- package/dist/tools/builtins/sandbox/edit.js +2 -2
- package/dist/tools/builtins/sandbox/index.d.ts +1 -1
- package/dist/tools/builtins/sandbox/index.js +1 -1
- package/dist/tools/builtins/sandbox/task-output.d.ts +6 -6
- package/dist/tools/builtins/sandbox/task-output.js +10 -10
- package/dist/tools/builtins/sandbox/task-stop.js +2 -2
- package/dist/tools/builtins/sandbox/write.js +2 -2
- package/dist/tools/builtins/skill-load.d.ts +1 -1
- package/dist/tools/builtins/skill-load.js +2 -2
- package/dist/tools/pipeline.js +4 -3
- package/dist/tools/registry.d.ts +2 -2
- package/dist/tools/tools.module.js +3 -3
- package/dist/ui/admin-ui.controller.d.ts +56 -0
- package/dist/ui/admin-ui.controller.js +192 -0
- package/dist/ui/arrangement.d.ts +74 -0
- package/dist/ui/arrangement.js +98 -0
- package/dist/ui/embed-token.d.ts +2 -2
- package/dist/ui/embed-token.js +30 -5
- package/dist/ui/registry.d.ts +29 -14
- package/dist/ui/registry.js +31 -10
- package/dist/ui/slots.controller.d.ts +11 -0
- package/dist/ui/slots.controller.js +25 -0
- package/dist/ui/ui-stream.d.ts +20 -3
- package/dist/ui/ui-stream.js +25 -7
- package/dist/ui/ui.schemas.d.ts +66 -0
- package/dist/ui/ui.schemas.js +65 -0
- package/dist/ui/views.controller.d.ts +35 -49
- package/dist/ui/views.controller.js +48 -70
- package/dist/ui/views.d.ts +84 -18
- package/dist/ui/views.js +201 -38
- package/package.json +3 -3
- package/src/migrations/0105_devices_rename.sql +136 -0
- package/dist/devices/device-auth.module.d.ts +0 -7
- package/dist/environments/conversation-environments.d.ts +0 -75
- package/dist/environments/dto.d.ts +0 -25
- package/dist/environments/dto.js +0 -12
- package/dist/environments/environments.controller.d.ts +0 -36
- package/dist/environments/environments.module.d.ts +0 -8
- package/dist/environments/environments.module.js +0 -31
- package/dist/environments/environments.schemas.d.ts +0 -3
- package/dist/environments/environments.schemas.js +0 -14
- package/dist/environments/label.d.ts +0 -11
- package/dist/platform/ops/environments.ops.d.ts +0 -26
- 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
|
-
//
|
|
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/
|
|
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
|
|
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",
|
|
@@ -654,6 +654,11 @@ export const PLATFORM_EXCLUSIONS = [
|
|
|
654
654
|
category: "internal",
|
|
655
655
|
reason: "Navigation entries of the web shell (panels, pages, embeds); nothing an agent acts on",
|
|
656
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
|
+
},
|
|
657
662
|
{
|
|
658
663
|
route: "GET /api/v1/orgs/:orgId/ui/views/:plugin/:id",
|
|
659
664
|
category: "transport",
|
|
@@ -674,6 +679,36 @@ export const PLATFORM_EXCLUSIONS = [
|
|
|
674
679
|
category: "transport",
|
|
675
680
|
reason: "Server-sent event stream of UI invalidations",
|
|
676
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
|
+
},
|
|
677
712
|
// themes (themes spec §8-§9)
|
|
678
713
|
{
|
|
679
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: "
|
|
88
|
-
description: "Your own cloud
|
|
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(", ")}`,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type OnModuleInit } from "@nestjs/common";
|
|
2
2
|
import { ConversationsService } from "../../conversations/conversations.service.js";
|
|
3
|
-
import {
|
|
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
|
|
17
|
+
private readonly device;
|
|
18
18
|
private readonly kdb;
|
|
19
|
-
constructor(registry: PlatformOperations, conversations: ConversationsService, files: ConversationFiles,
|
|
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 {
|
|
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
|
-
|
|
44
|
+
device;
|
|
45
45
|
kdb;
|
|
46
|
-
constructor(registry, conversations, files,
|
|
46
|
+
constructor(registry, conversations, files, device, kdb) {
|
|
47
47
|
this.registry = registry;
|
|
48
48
|
this.conversations = conversations;
|
|
49
49
|
this.files = files;
|
|
50
|
-
this.
|
|
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.
|
|
352
|
-
description: "Read the
|
|
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/
|
|
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
|
-
|
|
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(
|
|
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 };
|
|
@@ -39,7 +39,7 @@ let OrgSettingsOperations = class OrgSettingsOperations {
|
|
|
39
39
|
this.registry.register([
|
|
40
40
|
defineOperation({
|
|
41
41
|
id: "org-settings.get",
|
|
42
|
-
description: "Read this org's settings: toolSearch, locale, sandboxToolPolicy, platformTool (on, read-only or off), sandboxEgress and wakeOnBackgroundTask (absent means it follows the deployment), theme (the org's default theme id, null or absent following the platform, and personal: allowed or locked), the deployment's sandbox egress default and the sandbox cpu / memory limits in effect.",
|
|
42
|
+
description: "Read this org's settings: toolSearch, locale, sandboxToolPolicy, platformTool (on, read-only or off), sandboxEgress and wakeOnBackgroundTask (absent means it follows the deployment), theme (the org's default theme id, null or absent following the platform, and personal: allowed or locked), uiArrangement (per UI slot, the extension contributions the org hides and their order; a slot not listed follows the platform), the deployment's sandbox egress default and the sandbox cpu / memory limits in effect.",
|
|
43
43
|
input: z.object({}).strict(),
|
|
44
44
|
example: {},
|
|
45
45
|
authz: { orgAction: "org.read" },
|
|
@@ -53,7 +53,7 @@ let OrgSettingsOperations = class OrgSettingsOperations {
|
|
|
53
53
|
}),
|
|
54
54
|
defineOperation({
|
|
55
55
|
id: "org-settings.update",
|
|
56
|
-
description: "Change this org's settings (org admins). Give only the settings to change; null clears sandboxEgress or wakeOnBackgroundTask so they follow the deployment again. theme: { id, personal } sets the org's default theme (a theme id from themes.list, or null to follow the platform) and whether members may pick their own (allowed) or not (locked); null clears it. Setting platformTool to off or read-only takes effect from the next call and cuts this Platform tool off in the org, so say so before asking; an org admin switches it back on in the web settings.",
|
|
56
|
+
description: "Change this org's settings (org admins). Give only the settings to change; null clears sandboxEgress or wakeOnBackgroundTask so they follow the deployment again. theme: { id, personal } sets the org's default theme (a theme id from themes.list, or null to follow the platform) and whether members may pick their own (allowed) or not (locked); null clears it. uiArrangement: { <slot>: { hidden, order } } replaces that slot's entry, where hidden and order list contribution keys <extension>/<contribution> (hidden ones are not listed in the web UI but their pages still open by URL); null for a slot makes it follow the platform again; platform.page is refused. Setting platformTool to off or read-only takes effect from the next call and cuts this Platform tool off in the org, so say so before asking; an org admin switches it back on in the web settings.",
|
|
57
57
|
input: OrgSettingsPatchSchema.refine((i) => Object.values(i).some((v) => v !== undefined), {
|
|
58
58
|
message: "give at least one setting",
|
|
59
59
|
}),
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type OnModuleInit } from "@nestjs/common";
|
|
2
|
+
import { PlatformOperations } from "../registry.js";
|
|
3
|
+
/** UI operations of the `Platform` tool (UI slots spec §3): the slot catalog. */
|
|
4
|
+
export declare class UiOperations implements OnModuleInit {
|
|
5
|
+
private readonly registry;
|
|
6
|
+
constructor(registry: PlatformOperations);
|
|
7
|
+
onModuleInit(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
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 { UI_SLOTS } from "@capybara-hq/plugin-sdk";
|
|
11
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { defineOperation } from "../operation.js";
|
|
14
|
+
import { PlatformOperations } from "../registry.js";
|
|
15
|
+
/** UI operations of the `Platform` tool (UI slots spec §3): the slot catalog. */
|
|
16
|
+
let UiOperations = class UiOperations {
|
|
17
|
+
registry;
|
|
18
|
+
constructor(registry) {
|
|
19
|
+
this.registry = registry;
|
|
20
|
+
}
|
|
21
|
+
onModuleInit() {
|
|
22
|
+
this.registry.register([
|
|
23
|
+
defineOperation({
|
|
24
|
+
id: "ui.slots",
|
|
25
|
+
description: "List the UI slots an extension can contribute to (id, version, where it is, scope and args, accepted kinds view / embed, minimum role, anchors). Use a slot id as a ui contribution's `slot` in a plugin manifest.",
|
|
26
|
+
input: z.object({}).strict(),
|
|
27
|
+
example: {},
|
|
28
|
+
// any signed-in person may call the route; every run's actor is a member of this org
|
|
29
|
+
authz: { orgAction: "agents.use" },
|
|
30
|
+
mirrors: ["GET /api/v1/ui/slots"],
|
|
31
|
+
confirm: "read",
|
|
32
|
+
run: async () => ({ slots: UI_SLOTS }),
|
|
33
|
+
}),
|
|
34
|
+
]);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
UiOperations = __decorate([
|
|
38
|
+
Injectable(),
|
|
39
|
+
__param(0, Inject(PlatformOperations))
|
|
40
|
+
], UiOperations);
|
|
41
|
+
export { UiOperations };
|