@capybara-hq/kernel 0.1.0-rc.13 → 0.1.0-rc.15
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 +5 -13
- package/dist/catalog/admin-catalog.controller.d.ts +39 -5
- package/dist/catalog/admin-catalog.controller.js +75 -6
- package/dist/catalog/admin-catalog.schemas.d.ts +10 -0
- package/dist/catalog/admin-catalog.schemas.js +7 -0
- package/dist/catalog/appearance.schemas.d.ts +10 -0
- package/dist/catalog/appearance.schemas.js +20 -0
- package/dist/catalog/appearance.service.d.ts +105 -0
- package/dist/catalog/appearance.service.js +306 -0
- package/dist/catalog/catalog-content.d.ts +9 -1
- package/dist/catalog/catalog-content.js +2 -1
- package/dist/catalog/catalog-files.d.ts +3 -2
- package/dist/catalog/catalog-files.js +8 -5
- package/dist/catalog/catalog-import.module.js +3 -0
- package/dist/catalog/catalog-items.d.ts +11 -0
- package/dist/catalog/catalog-items.js +21 -0
- package/dist/catalog/catalog-scope.service.d.ts +7 -0
- package/dist/catalog/catalog-scope.service.js +55 -15
- package/dist/catalog/catalog.service.js +10 -2
- package/dist/catalog/cli.js +3 -0
- package/dist/catalog/component-scope.service.d.ts +14 -1
- package/dist/catalog/component-scope.service.js +12 -2
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/org-catalog.controller.d.ts +5 -4
- package/dist/catalog/org-catalog.controller.js +5 -4
- package/dist/catalog/org-catalog.schemas.d.ts +18 -2
- package/dist/catalog/org-catalog.schemas.js +16 -2
- package/dist/catalog/org-catalog.service.js +8 -2
- package/dist/catalog/org-extension.controller.d.ts +27 -7
- package/dist/catalog/org-extension.controller.js +48 -6
- package/dist/catalog/plugin-import.d.ts +28 -4
- package/dist/catalog/plugin-import.js +96 -20
- package/dist/catalog/plugin-package.d.ts +4 -2
- package/dist/catalog/plugin-package.js +66 -12
- package/dist/catalog/plugin-upgrade.d.ts +15 -1
- package/dist/catalog/plugin-upgrade.js +18 -5
- package/dist/channels/connections.controller.d.ts +1 -1
- package/dist/channels/connections.controller.js +1 -1
- package/dist/channels/connections.service.d.ts +22 -5
- package/dist/channels/connections.service.js +56 -10
- package/dist/channels/webhook.d.ts +21 -1
- package/dist/channels/webhook.js +39 -4
- package/dist/client/client-access.service.d.ts +101 -0
- package/dist/client/client-access.service.js +294 -0
- package/dist/client/client-builds.service.d.ts +109 -0
- package/dist/client/client-builds.service.js +229 -0
- package/dist/client/client-delivery.controller.d.ts +25 -0
- package/dist/client/client-delivery.controller.js +66 -0
- package/dist/client/client-files.d.ts +48 -0
- package/dist/client/client-files.js +136 -0
- package/dist/client/client-reports.cron.d.ts +13 -0
- package/dist/client/client-reports.cron.js +42 -0
- package/dist/client/client-reports.service.d.ts +30 -0
- package/dist/client/client-reports.service.js +102 -0
- package/dist/client/client.controller.d.ts +45 -0
- package/dist/client/client.controller.js +121 -0
- package/dist/client/client.module.d.ts +7 -0
- package/dist/client/client.module.js +26 -0
- package/dist/client/client.schemas.d.ts +55 -0
- package/dist/client/client.schemas.js +27 -0
- package/dist/ctx/create-ctx.d.ts +19 -4
- package/dist/ctx/create-ctx.js +51 -3
- package/dist/db/kernel-schema.d.ts +58 -2
- package/dist/errors.d.ts +33 -0
- package/dist/errors.js +33 -0
- package/dist/extensions/admin-ops.d.ts +4 -1
- package/dist/extensions/admin-ops.js +22 -1
- package/dist/extensions/admin-view.d.ts +8 -0
- package/dist/extensions/admin-view.js +78 -0
- package/dist/extensions/blobs.d.ts +14 -1
- package/dist/extensions/blobs.js +48 -5
- package/dist/extensions/guide-places.d.ts +66 -0
- package/dist/extensions/guide-places.js +152 -0
- package/dist/extensions/host.d.ts +6 -1
- package/dist/extensions/host.js +23 -12
- package/dist/extensions/instance.d.ts +5 -1
- package/dist/extensions/instance.js +8 -0
- package/dist/extensions/ledger.d.ts +1 -1
- package/dist/extensions/package.d.ts +4 -3
- package/dist/extensions/package.js +5 -1
- package/dist/extensions/permission-set.d.ts +35 -5
- package/dist/extensions/permission-set.js +36 -5
- package/dist/extensions/permission-view.d.ts +38 -7
- package/dist/extensions/permission-view.js +27 -8
- package/dist/extensions/plugin-guides.d.ts +207 -54
- package/dist/extensions/plugin-guides.js +436 -165
- package/dist/extensions/sources.d.ts +6 -0
- package/dist/extensions/sources.js +2 -0
- package/dist/extensions/state.module.js +9 -1
- package/dist/http/api.module.js +16 -0
- package/dist/identity/settings.d.ts +41 -26
- package/dist/identity/settings.js +87 -4
- package/dist/infra/lock/lock.service.d.ts +8 -0
- package/dist/infra/lock/lock.service.js +27 -0
- package/dist/infra/throttler/named-throttlers.d.ts +8 -1
- package/dist/infra/throttler/named-throttlers.js +30 -1
- package/dist/infra/throttler/throttler.guard.js +1 -1
- package/dist/kernel.module.js +3 -0
- package/dist/orgs/settings.service.d.ts +2 -26
- package/dist/overrides.d.ts +3 -1
- package/dist/overrides.js +2 -0
- package/dist/platform/exclusions.js +37 -6
- package/dist/platform/operation.js +4 -0
- package/dist/platform/ops/admin.ops.js +17 -2
- package/dist/platform/ops/catalog-admin.ops.d.ts +19 -1
- package/dist/platform/ops/catalog-admin.ops.js +85 -2
- package/dist/platform/ops/connectors.ops.js +2 -0
- package/dist/platform/ops/org-plugins.ops.d.ts +7 -1
- package/dist/platform/ops/org-plugins.ops.js +63 -4
- package/dist/platform/ops/org-settings.ops.js +2 -2
- package/dist/platform/ops/orgs.ops.js +1 -0
- package/dist/platform/ops/setup.ops.d.ts +24 -0
- package/dist/platform/ops/setup.ops.js +212 -0
- package/dist/platform/ops/ui.ops.js +1 -1
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +7 -0
- package/dist/platform/route-schemas.js +8 -0
- package/dist/roles/worker.module.js +4 -0
- package/dist/setup/kernel-checks.d.ts +91 -0
- package/dist/setup/kernel-checks.js +295 -0
- package/dist/setup/oauth-token-probe.d.ts +47 -0
- package/dist/setup/oauth-token-probe.js +108 -0
- package/dist/setup/redact-check.d.ts +18 -0
- package/dist/setup/redact-check.js +46 -0
- package/dist/setup/setup-check-registry.d.ts +86 -0
- package/dist/setup/setup-check-registry.js +75 -0
- package/dist/setup/setup-checks.controller.d.ts +28 -0
- package/dist/setup/setup-checks.controller.js +78 -0
- package/dist/setup/setup-checks.schemas.d.ts +38 -0
- package/dist/setup/setup-checks.schemas.js +43 -0
- package/dist/setup/setup-checks.service.d.ts +144 -0
- package/dist/setup/setup-checks.service.js +683 -0
- package/dist/setup/setup-guides.controller.d.ts +18 -0
- package/dist/setup/setup-guides.controller.js +48 -0
- package/dist/setup/setup-guides.schemas.d.ts +10 -0
- package/dist/setup/setup-guides.schemas.js +6 -0
- package/dist/setup/setup-guides.service.d.ts +126 -0
- package/dist/setup/setup-guides.service.js +315 -0
- package/dist/setup/setup.module.d.ts +8 -0
- package/dist/setup/setup.module.js +31 -0
- package/dist/themes/render-css.d.ts +2 -1
- package/dist/themes/render-css.js +5 -2
- package/dist/themes/theme-delivery.service.d.ts +4 -2
- package/dist/themes/theme-delivery.service.js +8 -3
- package/dist/themes/theme-state.d.ts +28 -7
- package/dist/themes/theme-state.js +24 -6
- package/dist/themes/themes-public.controller.d.ts +7 -2
- package/dist/themes/themes-public.controller.js +11 -5
- package/dist/themes/themes.service.js +2 -2
- package/dist/tools/connectors.controller.d.ts +28 -11
- package/dist/tools/connectors.controller.js +49 -14
- package/dist/tools/connectors.schemas.d.ts +4 -0
- package/dist/tools/connectors.schemas.js +4 -0
- package/dist/tools/connectors.service.d.ts +30 -2
- package/dist/tools/connectors.service.js +98 -3
- package/dist/tools/credentials.d.ts +20 -0
- package/dist/tools/credentials.js +90 -1
- package/dist/tools/oauth/tokens.d.ts +20 -0
- package/dist/tools/oauth/tokens.js +49 -24
- package/dist/tools/pipeline.d.ts +3 -2
- package/dist/ui/arrangement.d.ts +41 -50
- package/dist/ui/arrangement.js +88 -15
- package/dist/ui/registry.d.ts +13 -3
- package/dist/ui/registry.js +15 -4
- package/dist/ui/ui.schemas.d.ts +4 -0
- package/dist/ui/views.d.ts +36 -9
- package/dist/ui/views.js +58 -28
- package/package.json +3 -3
- package/src/migrations/0106_setup_guides_v2.sql +10 -0
- package/src/migrations/0107_extension_client_builds.sql +50 -0
|
@@ -95,6 +95,11 @@ export const PLATFORM_EXCLUSIONS = [
|
|
|
95
95
|
category: "transport",
|
|
96
96
|
reason: "Serves icon image bytes",
|
|
97
97
|
},
|
|
98
|
+
{
|
|
99
|
+
route: "GET /api/v1/admin/catalog/:itemId/guides/:guideId",
|
|
100
|
+
category: "internal",
|
|
101
|
+
reason: "The super admin's preview of a plugin's setup guide for the admin console, with no org and no target; agents assist with the org guides an org member sees",
|
|
102
|
+
},
|
|
98
103
|
{
|
|
99
104
|
route: "POST /api/v1/admin/catalog/items/:id/confirm",
|
|
100
105
|
category: "human-only",
|
|
@@ -128,11 +133,6 @@ export const PLATFORM_EXCLUSIONS = [
|
|
|
128
133
|
category: "transport",
|
|
129
134
|
reason: "Serves icon image bytes",
|
|
130
135
|
},
|
|
131
|
-
{
|
|
132
|
-
route: "GET /api/v1/orgs/:orgId/catalog/:itemId/guides/:guideId",
|
|
133
|
-
category: "internal",
|
|
134
|
-
reason: "A plugin's setup guide (an app manifest, URLs, steps) for the web's setup section; a person pastes it into the third-party platform's console, which an agent cannot reach",
|
|
135
|
-
},
|
|
136
136
|
{
|
|
137
137
|
route: "POST /api/v1/orgs/:orgId/catalog/:itemId/install",
|
|
138
138
|
category: "secret",
|
|
@@ -593,6 +593,11 @@ export const PLATFORM_EXCLUSIONS = [
|
|
|
593
593
|
category: "secret",
|
|
594
594
|
reason: "Edits connector endpoint config that can carry credentials",
|
|
595
595
|
},
|
|
596
|
+
{
|
|
597
|
+
route: "POST /api/v1/orgs/:orgId/connectors/:connectorId/guide-ack",
|
|
598
|
+
category: "human-only",
|
|
599
|
+
reason: "A person confirms they updated the app on the third-party platform after a connector template's setup guide changed; only that person knows it was done",
|
|
600
|
+
},
|
|
596
601
|
{
|
|
597
602
|
route: "POST /api/v1/orgs/:orgId/connectors/:connectorId/tools/:name/review",
|
|
598
603
|
category: "human-only",
|
|
@@ -709,9 +714,35 @@ export const PLATFORM_EXCLUSIONS = [
|
|
|
709
714
|
category: "transport",
|
|
710
715
|
reason: "Server-sent event stream of UI invalidations",
|
|
711
716
|
},
|
|
717
|
+
// client extensions (client extensions spec §9.2-§9.3)
|
|
718
|
+
{
|
|
719
|
+
route: "GET /api/v1/client/:plugin/:build/*",
|
|
720
|
+
category: "transport",
|
|
721
|
+
reason: "Serves a plugin's client code, stylesheets and assets to the browser that runs them",
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
route: "GET /api/v1/orgs/:orgId/ui/client",
|
|
725
|
+
category: "internal",
|
|
726
|
+
reason: "The web shell's list of client code to load (file URLs and integrity); nothing an agent acts on",
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
route: "GET /api/v1/admin/ui/client",
|
|
730
|
+
category: "internal",
|
|
731
|
+
reason: "The admin console's list of platform page client code to load; nothing an agent acts on",
|
|
732
|
+
},
|
|
733
|
+
{
|
|
734
|
+
route: "POST /api/v1/orgs/:orgId/ui/client/reports",
|
|
735
|
+
category: "transport",
|
|
736
|
+
reason: "Fire-and-forget crash report sent by the browser that ran the client code",
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
route: "POST /api/v1/admin/ui/client/reports",
|
|
740
|
+
category: "transport",
|
|
741
|
+
reason: "Fire-and-forget crash report sent by the admin console that ran the client code",
|
|
742
|
+
},
|
|
712
743
|
// themes (themes spec §8-§9)
|
|
713
744
|
{
|
|
714
|
-
route: "GET /api/v1/themes/:id/:version/theme.css",
|
|
745
|
+
route: "GET /api/v1/themes/:id/:version/:revision/theme.css",
|
|
715
746
|
category: "transport",
|
|
716
747
|
reason: "Serves a theme version's stylesheet to the browser; an agent reads themes.list",
|
|
717
748
|
},
|
|
@@ -87,6 +87,10 @@ export const PLATFORM_DOMAINS = [
|
|
|
87
87
|
id: "devices",
|
|
88
88
|
description: "Your own cloud devices (the workspaces your conversations run in): list, read, create, rename, delete, wipe the files.",
|
|
89
89
|
},
|
|
90
|
+
{
|
|
91
|
+
id: "setup",
|
|
92
|
+
description: "Plugin setup guides: list the guides you may help with, read one as Markdown, the state of its checks for a channel connection or a connector, and running one check. Entering secrets, connecting an account and confirming the app was updated stay with the person on the web; read the docs topic `setup` first.",
|
|
93
|
+
},
|
|
90
94
|
{
|
|
91
95
|
id: "themes",
|
|
92
96
|
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.",
|
|
@@ -41,6 +41,7 @@ const SettingsInput = DEPLOYMENT_SETTINGS_PATCH.pick({
|
|
|
41
41
|
orgMarketplaceBrowse: true,
|
|
42
42
|
uiTheme: true,
|
|
43
43
|
uiArrangement: true,
|
|
44
|
+
clientExtensions: true,
|
|
44
45
|
}).strict();
|
|
45
46
|
const ProviderId = ModelProviderParams.shape.provider.describe("The model provider (models.platform-list), e.g. the plugin name of its extension.");
|
|
46
47
|
/** `provider/model` of a purpose target, or null. */
|
|
@@ -122,7 +123,7 @@ let AdminOperations = class AdminOperations {
|
|
|
122
123
|
}),
|
|
123
124
|
defineOperation({
|
|
124
125
|
id: "admin.update-settings",
|
|
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.",
|
|
126
|
+
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 } } for a list slot, { <slot>: { use } } for a single slot: the platform default arrangement of UI slots, with contribution keys <extension>/<contribution>; hidden ones are not listed but still open by URL; use names the contribution that replaces the built-in, null for the built-in; null for a slot removes its entry), clientExtensions ({ enabled?, disabled? }: the kill switch of plugin client code; enabled false stops every plugin's interface code in every browser, disabled is the whole list of plugins whose interface code alone is stopped while their tools keep working; read the current list from admin.settings first). Per-org limits are orgs.set-limits.",
|
|
126
127
|
input: SettingsInput.refine((b) => Object.keys(b).length > 0, {
|
|
127
128
|
message: "at least one setting is required",
|
|
128
129
|
}),
|
|
@@ -149,7 +150,7 @@ let AdminOperations = class AdminOperations {
|
|
|
149
150
|
: { ok: false, code: "validation_failed", message: r.error.issues[0]?.message ?? "" };
|
|
150
151
|
},
|
|
151
152
|
summary: async (i) => {
|
|
152
|
-
const { uiTheme, uiArrangement, ...rest } = i;
|
|
153
|
+
const { uiTheme, uiArrangement, clientExtensions, ...rest } = i;
|
|
153
154
|
const parts = Object.entries(rest).map(([k, v]) => `${k}=${String(v)}`);
|
|
154
155
|
const zh = [...parts];
|
|
155
156
|
const en = [...parts];
|
|
@@ -164,6 +165,20 @@ let AdminOperations = class AdminOperations {
|
|
|
164
165
|
zh.push(`uiArrangement(${slots})`);
|
|
165
166
|
en.push(`uiArrangement (${slots})`);
|
|
166
167
|
}
|
|
168
|
+
if (clientExtensions !== undefined) {
|
|
169
|
+
const { enabled, disabled } = clientExtensions;
|
|
170
|
+
if (enabled !== undefined) {
|
|
171
|
+
zh.push(enabled ? "开启插件界面代码" : "停用全部插件界面代码");
|
|
172
|
+
en.push(enabled ? "plugin interface code on" : "all plugin interface code stopped");
|
|
173
|
+
}
|
|
174
|
+
if (disabled !== undefined) {
|
|
175
|
+
const list = disabled.length === 0 ? null : disabled.join(", ");
|
|
176
|
+
zh.push(list === null ? "不再单独停用任何插件的界面代码" : `停用界面代码的插件:${list}`);
|
|
177
|
+
en.push(list === null
|
|
178
|
+
? "no plugin's interface code stopped on its own"
|
|
179
|
+
: `interface code stopped for: ${list}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
167
182
|
return {
|
|
168
183
|
zh: `修改平台部署设置:${zh.join(",")}`,
|
|
169
184
|
en: `Change the deployment settings: ${en.join(", ")}`,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type OnModuleInit } from "@nestjs/common";
|
|
2
|
+
import { type AppearanceResult, AppearanceService } from "../../catalog/appearance.service.js";
|
|
2
3
|
import { CatalogService } from "../../catalog/catalog.service.js";
|
|
3
4
|
import { CatalogScopeService } from "../../catalog/catalog-scope.service.js";
|
|
4
5
|
import { PluginImport, type PluginReview } from "../../catalog/plugin-import.js";
|
|
5
6
|
import { KernelDb } from "../../infra/database/kernel-db.js";
|
|
7
|
+
import { ThemesService } from "../../themes/themes.service.js";
|
|
6
8
|
import { PlatformOperations } from "../registry.js";
|
|
7
9
|
/** `plugins.set-shown` on a plugin an org owns. */
|
|
8
10
|
export declare const ORG_OWNED = "An org owns this plugin and manages who sees it; the super admin changes that in the admin console, not here.";
|
|
@@ -41,6 +43,20 @@ export declare const reviewBrief: (r: PluginReview) => {
|
|
|
41
43
|
resolved: string | null;
|
|
42
44
|
}[];
|
|
43
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* The card of an "apply this plugin's appearance" operation (client extensions spec §6.5), from the
|
|
48
|
+
* route's dry run: the theme it sets (its name), the slots it replaces and how many were skipped.
|
|
49
|
+
*/
|
|
50
|
+
export declare function appearanceSummary(level: "platform" | "org", plugin: {
|
|
51
|
+
zh: string;
|
|
52
|
+
en: string;
|
|
53
|
+
}, r: AppearanceResult, theme: {
|
|
54
|
+
zh: string;
|
|
55
|
+
en: string;
|
|
56
|
+
} | null): {
|
|
57
|
+
zh: string;
|
|
58
|
+
en: string;
|
|
59
|
+
};
|
|
44
60
|
/**
|
|
45
61
|
* The super admin's platform catalog operations of the `Platform` tool (spec §14.2, §14.5 item
|
|
46
62
|
* 1): prepare an import from npm or git and read its review (a person confirms it on the web: the
|
|
@@ -55,7 +71,9 @@ export declare class CatalogAdminOperations implements OnModuleInit {
|
|
|
55
71
|
private readonly scope;
|
|
56
72
|
private readonly pluginImport;
|
|
57
73
|
private readonly kdb;
|
|
58
|
-
|
|
74
|
+
private readonly appearance;
|
|
75
|
+
private readonly themes;
|
|
76
|
+
constructor(registry: PlatformOperations, catalog: CatalogService, scope: CatalogScopeService, pluginImport: PluginImport, kdb: KernelDb, appearance: AppearanceService, themes: ThemesService);
|
|
59
77
|
/** The precheck refusal of another org's private plugin (the phase-1 rule), else null. */
|
|
60
78
|
private otherOrgs;
|
|
61
79
|
/** Whether an org owns the item (its owner org manages it, not the super admin's agent). */
|
|
@@ -11,11 +11,13 @@ import { ToolError } from "@capybara-hq/plugin-sdk";
|
|
|
11
11
|
import { Inject, Injectable } from "@nestjs/common";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
import { CatalogDisabledBody, CatalogGitImportBody, CatalogIdPathParams, CatalogNpmImportBody, CatalogScope, CatalogScopeBody, CatalogScopeOrgs, CatalogShownBody, CatalogStagingPathParams, } from "../../catalog/admin-catalog.schemas.js";
|
|
14
|
+
import { AppearanceService } from "../../catalog/appearance.service.js";
|
|
14
15
|
import { CatalogService } from "../../catalog/catalog.service.js";
|
|
15
16
|
import { CatalogScopeService } from "../../catalog/catalog-scope.service.js";
|
|
16
17
|
import { PluginImport } from "../../catalog/plugin-import.js";
|
|
17
18
|
import { ApiError } from "../../errors.js";
|
|
18
19
|
import { KernelDb } from "../../infra/database/kernel-db.js";
|
|
20
|
+
import { ThemesService } from "../../themes/themes.service.js";
|
|
19
21
|
import { defineOperation } from "../operation.js";
|
|
20
22
|
import { PlatformOperations } from "../registry.js";
|
|
21
23
|
import { precheckBy, viaAgent } from "./errors.js";
|
|
@@ -64,6 +66,37 @@ export const reviewBrief = (r) => ({
|
|
|
64
66
|
const conflictText = (cs) => cs
|
|
65
67
|
.map((c) => `skill "${c.name}" is already used in org ${c.orgName} (${c.plugins.length > 0 ? `${c.plugins.length} plugin(s)` : "its own skill"})`)
|
|
66
68
|
.join("; ");
|
|
69
|
+
/**
|
|
70
|
+
* The card of an "apply this plugin's appearance" operation (client extensions spec §6.5), from the
|
|
71
|
+
* route's dry run: the theme it sets (its name), the slots it replaces and how many were skipped.
|
|
72
|
+
*/
|
|
73
|
+
export function appearanceSummary(level, plugin, r, theme) {
|
|
74
|
+
const zh = [];
|
|
75
|
+
const en = [];
|
|
76
|
+
if (r.theme !== null && theme !== null) {
|
|
77
|
+
zh.push(`${level === "platform" ? "平台" : "本组织"}默认主题改为「${theme.zh}」`);
|
|
78
|
+
en.push(`${level === "platform" ? "platform" : "org"} default theme becomes "${theme.en}"`);
|
|
79
|
+
}
|
|
80
|
+
if (r.replacements.length > 0) {
|
|
81
|
+
const slots = r.replacements.map((x) => x.slot).join(", ");
|
|
82
|
+
zh.push(`替换 ${slots}`);
|
|
83
|
+
en.push(`replaces ${slots}`);
|
|
84
|
+
}
|
|
85
|
+
if (r.skipped.length > 0) {
|
|
86
|
+
zh.push(`跳过 ${r.skipped.length} 项`);
|
|
87
|
+
en.push(`${r.skipped.length} skipped`);
|
|
88
|
+
}
|
|
89
|
+
if (zh.length === 0) {
|
|
90
|
+
return {
|
|
91
|
+
zh: `插件「${plugin.zh}」的外观已经应用,没有改动`,
|
|
92
|
+
en: `The appearance of plugin "${plugin.en}" is applied already; nothing changes`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
zh: `应用插件「${plugin.zh}」的外观:${zh.join(";")}`,
|
|
97
|
+
en: `Apply the appearance of plugin "${plugin.en}": ${en.join("; ")}`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
67
100
|
/** A scope preview as the admin console shows it (orgs named); conflicting plugins counted. */
|
|
68
101
|
const previewBrief = (p) => ({
|
|
69
102
|
affected: p.affected,
|
|
@@ -93,12 +126,16 @@ let CatalogAdminOperations = class CatalogAdminOperations {
|
|
|
93
126
|
scope;
|
|
94
127
|
pluginImport;
|
|
95
128
|
kdb;
|
|
96
|
-
|
|
129
|
+
appearance;
|
|
130
|
+
themes;
|
|
131
|
+
constructor(registry, catalog, scope, pluginImport, kdb, appearance, themes) {
|
|
97
132
|
this.registry = registry;
|
|
98
133
|
this.catalog = catalog;
|
|
99
134
|
this.scope = scope;
|
|
100
135
|
this.pluginImport = pluginImport;
|
|
101
136
|
this.kdb = kdb;
|
|
137
|
+
this.appearance = appearance;
|
|
138
|
+
this.themes = themes;
|
|
102
139
|
}
|
|
103
140
|
/** The precheck refusal of another org's private plugin (the phase-1 rule), else null. */
|
|
104
141
|
async otherOrgs(itemId, orgId) {
|
|
@@ -585,6 +622,50 @@ let CatalogAdminOperations = class CatalogAdminOperations {
|
|
|
585
622
|
return { deleted: input.itemId };
|
|
586
623
|
},
|
|
587
624
|
}),
|
|
625
|
+
defineOperation({
|
|
626
|
+
id: "plugins.platform-apply-appearance",
|
|
627
|
+
description: "Apply a platform plugin's suggested appearance (super admin; the admin console's 应用此插件的外观): in one step, its theme becomes the platform default theme and each component it suggests replaces the built-in block of its slot (shell.brand, conversation.empty, conversation.composer.frame) in the platform arrangement; orgs that set their own keep theirs. The card shows exactly what changes; a theme that cannot be the platform default (scope not all, or off in an org) refuses the whole call, a component that is not available is skipped. Asked every time, never remembered.",
|
|
628
|
+
input: z.object({ itemId: ItemId }).strict(),
|
|
629
|
+
example: { itemId: "3f1c2a9e-5b7d-4e21-9c0a-1d2e3f4a5b6c" },
|
|
630
|
+
authz: { superAdmin: true },
|
|
631
|
+
mirrors: ["POST /api/v1/admin/catalog/items/:id/appearance"],
|
|
632
|
+
renames: { itemId: "id" },
|
|
633
|
+
// the route's dry run is this operation's card and precheck, never a confirmed call
|
|
634
|
+
omits: ["dryRun"],
|
|
635
|
+
confirm: "platform",
|
|
636
|
+
rememberable: false,
|
|
637
|
+
errors: [
|
|
638
|
+
{
|
|
639
|
+
code: "catalog.item_not_found",
|
|
640
|
+
next: "Check the plugin id with plugins.platform-list; only a plugin whose plugin.json has suggestedAppearance can be applied.",
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
code: "theme.not_available",
|
|
644
|
+
next: "The plugin's theme cannot be the platform default: give it scope all (plugins.component-scope-preview, then plugins.set-component-scope) and make sure no org switched it off, then apply again.",
|
|
645
|
+
},
|
|
646
|
+
],
|
|
647
|
+
precheck: async (i, ctx) => {
|
|
648
|
+
const other = await this.otherOrgs(i.itemId, ctx.orgId);
|
|
649
|
+
if (other !== null)
|
|
650
|
+
return other;
|
|
651
|
+
return precheckBy(() => this.appearance.apply({ platform: true }, i.itemId, { accountId: ctx.actorAccountId }, true));
|
|
652
|
+
},
|
|
653
|
+
summary: async (i, ctx) => {
|
|
654
|
+
const [n, r] = await Promise.all([
|
|
655
|
+
this.names(i.itemId),
|
|
656
|
+
this.appearance.apply({ platform: true }, i.itemId, { accountId: ctx.actorAccountId }, true),
|
|
657
|
+
]);
|
|
658
|
+
const theme = r.theme && localized(await this.themes.nameOf(r.theme.to), r.theme.to);
|
|
659
|
+
return appearanceSummary("platform", n, r, theme);
|
|
660
|
+
},
|
|
661
|
+
run: async (input, ctx) => {
|
|
662
|
+
await assertNotOtherOrgs(this.kdb.db, input.itemId, ctx.orgId);
|
|
663
|
+
return this.appearance.apply({ platform: true }, input.itemId, {
|
|
664
|
+
accountId: ctx.actorAccountId,
|
|
665
|
+
auditDetail: viaAgent("plugins.platform-apply-appearance", ctx),
|
|
666
|
+
}, false);
|
|
667
|
+
},
|
|
668
|
+
}),
|
|
588
669
|
]);
|
|
589
670
|
}
|
|
590
671
|
};
|
|
@@ -594,6 +675,8 @@ CatalogAdminOperations = __decorate([
|
|
|
594
675
|
__param(1, Inject(CatalogService)),
|
|
595
676
|
__param(2, Inject(CatalogScopeService)),
|
|
596
677
|
__param(3, Inject(PluginImport)),
|
|
597
|
-
__param(4, Inject(KernelDb))
|
|
678
|
+
__param(4, Inject(KernelDb)),
|
|
679
|
+
__param(5, Inject(AppearanceService)),
|
|
680
|
+
__param(6, Inject(ThemesService))
|
|
598
681
|
], CatalogAdminOperations);
|
|
599
682
|
export { CatalogAdminOperations };
|
|
@@ -120,6 +120,8 @@ let ConnectorsOperations = class ConnectorsOperations {
|
|
|
120
120
|
on: t.on,
|
|
121
121
|
switchable: t.switchable,
|
|
122
122
|
owner: t.owner,
|
|
123
|
+
// where the template's setup guide is (catalog item and guide id), null without one
|
|
124
|
+
guide: t.guide ?? null,
|
|
123
125
|
}));
|
|
124
126
|
return pageOf(templates, startOf(input.cursor), PAGE);
|
|
125
127
|
},
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type OnModuleInit } from "@nestjs/common";
|
|
2
|
+
import { AppearanceService } from "../../catalog/appearance.service.js";
|
|
2
3
|
import { CatalogScopeService } from "../../catalog/catalog-scope.service.js";
|
|
3
4
|
import { OrgCatalogService } from "../../catalog/org-catalog.service.js";
|
|
4
5
|
import { OrgPluginUploads } from "../../catalog/org-plugin-uploads.js";
|
|
5
6
|
import { OwnedItems } from "../../catalog/owned-items.js";
|
|
6
7
|
import { PluginInstaller } from "../../catalog/plugin-install.js";
|
|
7
8
|
import { KernelDb } from "../../infra/database/kernel-db.js";
|
|
9
|
+
import { ThemesService } from "../../themes/themes.service.js";
|
|
8
10
|
import { PlatformOperations } from "../registry.js";
|
|
9
11
|
/**
|
|
10
12
|
* The org's own plugin operations of the `Platform` tool (spec §14.2): the org's plugin installs
|
|
@@ -20,7 +22,11 @@ export declare class OrgPluginsOperations implements OnModuleInit {
|
|
|
20
22
|
private readonly owned;
|
|
21
23
|
private readonly scope;
|
|
22
24
|
private readonly kdb;
|
|
23
|
-
|
|
25
|
+
private readonly appearance;
|
|
26
|
+
private readonly themes;
|
|
27
|
+
constructor(registry: PlatformOperations, installer: PluginInstaller, orgCatalog: OrgCatalogService, uploads: OrgPluginUploads, owned: OwnedItems, scope: CatalogScopeService, kdb: KernelDb, appearance: AppearanceService, themes: ThemesService);
|
|
28
|
+
/** The display name of the live plugin of `extension`, or the name when it cannot be read. */
|
|
29
|
+
private pluginNames;
|
|
24
30
|
/** The org's own live plugin `id`, or null (another org's, a platform one, deleted, unknown). */
|
|
25
31
|
private ownedItem;
|
|
26
32
|
/** The precheck refusal of a plugin the org does not own. */
|
|
@@ -9,20 +9,23 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
9
9
|
};
|
|
10
10
|
import { Inject, Injectable } from "@nestjs/common";
|
|
11
11
|
import { z } from "zod";
|
|
12
|
+
import { AppearanceService } from "../../catalog/appearance.service.js";
|
|
12
13
|
import { CatalogScopeService } from "../../catalog/catalog-scope.service.js";
|
|
13
14
|
import { PluginInstallPathParams } from "../../catalog/org-catalog.schemas.js";
|
|
14
15
|
import { OrgCatalogService } from "../../catalog/org-catalog.service.js";
|
|
16
|
+
import { OrgExtensionParams } from "../../catalog/org-extension.schemas.js";
|
|
15
17
|
import { OrgPluginUploads } from "../../catalog/org-plugin-uploads.js";
|
|
16
18
|
import { OrgOwnedDeleteBody, OrgOwnedPluginParams, OrgOwnedShareableBody, OrgUploadStagingParams, } from "../../catalog/org-plugin-uploads.schemas.js";
|
|
17
19
|
import { OwnedItems } from "../../catalog/owned-items.js";
|
|
18
20
|
import { PluginInstaller } from "../../catalog/plugin-install.js";
|
|
19
21
|
import { KernelDb } from "../../infra/database/kernel-db.js";
|
|
22
|
+
import { ThemesService } from "../../themes/themes.service.js";
|
|
20
23
|
import { defineOperation } from "../operation.js";
|
|
21
24
|
import { PlatformOperations } from "../registry.js";
|
|
22
|
-
import { reviewBrief } from "./catalog-admin.ops.js";
|
|
25
|
+
import { appearanceSummary, reviewBrief } from "./catalog-admin.ops.js";
|
|
23
26
|
import { precheckBy, viaAgent } from "./errors.js";
|
|
24
27
|
import { Cursor, pageOf, startOf } from "./paging.js";
|
|
25
|
-
import { named } from "./summary.js";
|
|
28
|
+
import { localized, named, orElse } from "./summary.js";
|
|
26
29
|
const InstallId = PluginInstallPathParams.shape.installId.max(100);
|
|
27
30
|
/** An org-owned plugin's catalog item id (`:id` of the owned-plugins routes). */
|
|
28
31
|
const OwnedId = OrgOwnedPluginParams.shape.id;
|
|
@@ -51,7 +54,9 @@ let OrgPluginsOperations = class OrgPluginsOperations {
|
|
|
51
54
|
owned;
|
|
52
55
|
scope;
|
|
53
56
|
kdb;
|
|
54
|
-
|
|
57
|
+
appearance;
|
|
58
|
+
themes;
|
|
59
|
+
constructor(registry, installer, orgCatalog, uploads, owned, scope, kdb, appearance, themes) {
|
|
55
60
|
this.registry = registry;
|
|
56
61
|
this.installer = installer;
|
|
57
62
|
this.orgCatalog = orgCatalog;
|
|
@@ -59,6 +64,20 @@ let OrgPluginsOperations = class OrgPluginsOperations {
|
|
|
59
64
|
this.owned = owned;
|
|
60
65
|
this.scope = scope;
|
|
61
66
|
this.kdb = kdb;
|
|
67
|
+
this.appearance = appearance;
|
|
68
|
+
this.themes = themes;
|
|
69
|
+
}
|
|
70
|
+
/** The display name of the live plugin of `extension`, or the name when it cannot be read. */
|
|
71
|
+
pluginNames(extension) {
|
|
72
|
+
return orElse(async () => {
|
|
73
|
+
const row = await this.kdb.db
|
|
74
|
+
.selectFrom("catalog_items")
|
|
75
|
+
.select("display_name")
|
|
76
|
+
.where("name", "=", extension)
|
|
77
|
+
.where("deleted_at", "is", null)
|
|
78
|
+
.executeTakeFirst();
|
|
79
|
+
return localized(row?.display_name, extension);
|
|
80
|
+
}, { zh: named(extension), en: named(extension) });
|
|
62
81
|
}
|
|
63
82
|
/** The org's own live plugin `id`, or null (another org's, a platform one, deleted, unknown). */
|
|
64
83
|
async ownedItem(orgId, id) {
|
|
@@ -313,6 +332,44 @@ let OrgPluginsOperations = class OrgPluginsOperations {
|
|
|
313
332
|
return { withdrawn: input.itemId };
|
|
314
333
|
},
|
|
315
334
|
}),
|
|
335
|
+
defineOperation({
|
|
336
|
+
id: "plugins.apply-appearance",
|
|
337
|
+
description: "Apply a plugin's suggested appearance in this org (org admins; the 扩展 page's 应用此插件的外观), for a plugin whose extension is on here: in one step, its theme becomes the org's default theme (whether members may pick their own stays as it is) and each component it suggests replaces the built-in block of its slot (shell.brand, conversation.empty, conversation.composer.frame) in the org's arrangement. The card shows exactly what changes; a theme that is not on in the org refuses the whole call, a component that is not available is skipped. Asked every time, never remembered.",
|
|
338
|
+
input: z.object({ extension: OrgExtensionParams.shape.extension }).strict(),
|
|
339
|
+
example: { extension: "theme-cyberpunk" },
|
|
340
|
+
authz: { orgAction: "org.update" },
|
|
341
|
+
mirrors: ["POST /api/v1/orgs/:orgId/extensions/:extension/appearance"],
|
|
342
|
+
// the route's dry run is this operation's card and precheck, never a confirmed call
|
|
343
|
+
omits: ["dryRun"],
|
|
344
|
+
confirm: "org",
|
|
345
|
+
rememberable: false,
|
|
346
|
+
errors: [
|
|
347
|
+
{
|
|
348
|
+
code: "extension.not_found",
|
|
349
|
+
next: "Check the extension with extensions.list: it must be on in this org and its plugin must suggest an appearance.",
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
code: "theme.not_available",
|
|
353
|
+
next: {
|
|
354
|
+
orgAdmin: "The plugin's theme is not on in this org: switch it on in the org's appearance settings on the web, or ask the super admin to offer it to this org, then apply again.",
|
|
355
|
+
member: "Ask an org admin to switch the plugin's theme on in this org first.",
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
],
|
|
359
|
+
precheck: (i, ctx) => precheckBy(() => this.appearance.apply({ orgId: ctx.orgId }, i.extension, { accountId: ctx.actorAccountId }, true)),
|
|
360
|
+
summary: async (i, ctx) => {
|
|
361
|
+
const [n, r] = await Promise.all([
|
|
362
|
+
this.pluginNames(i.extension),
|
|
363
|
+
this.appearance.apply({ orgId: ctx.orgId }, i.extension, { accountId: ctx.actorAccountId }, true),
|
|
364
|
+
]);
|
|
365
|
+
const theme = r.theme && localized(await this.themes.nameIn(ctx.orgId, r.theme.to), r.theme.to);
|
|
366
|
+
return appearanceSummary("org", n, r, theme);
|
|
367
|
+
},
|
|
368
|
+
run: async (input, ctx) => this.appearance.apply({ orgId: ctx.orgId }, input.extension, {
|
|
369
|
+
accountId: ctx.actorAccountId,
|
|
370
|
+
auditDetail: viaAgent("plugins.apply-appearance", ctx),
|
|
371
|
+
}, false),
|
|
372
|
+
}),
|
|
316
373
|
]);
|
|
317
374
|
}
|
|
318
375
|
};
|
|
@@ -324,6 +381,8 @@ OrgPluginsOperations = __decorate([
|
|
|
324
381
|
__param(3, Inject(OrgPluginUploads)),
|
|
325
382
|
__param(4, Inject(OwnedItems)),
|
|
326
383
|
__param(5, Inject(CatalogScopeService)),
|
|
327
|
-
__param(6, Inject(KernelDb))
|
|
384
|
+
__param(6, Inject(KernelDb)),
|
|
385
|
+
__param(7, Inject(AppearanceService)),
|
|
386
|
+
__param(8, Inject(ThemesService))
|
|
328
387
|
], OrgPluginsOperations);
|
|
329
388
|
export { OrgPluginsOperations };
|
|
@@ -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), uiArrangement (per
|
|
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 list slot, the extension contributions the org hides and their order; per single slot, the contribution that replaces the built-in as use, null for the built-in; 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. uiArrangement: { <slot>: { hidden, order } } replaces that slot's entry, where hidden and
|
|
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 } } (a list slot) or { <slot>: { use } } (a single slot: shell.brand, conversation.empty, conversation.composer.frame) replaces that slot's entry, where hidden, order and use name contribution keys <extension>/<contribution> (hidden ones are not listed in the web UI but their pages still open by URL; use null is the built-in); 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,24 @@
|
|
|
1
|
+
import { type OnModuleInit } from "@nestjs/common";
|
|
2
|
+
import { KernelDb } from "../../infra/database/kernel-db.js";
|
|
3
|
+
import { SetupChecksService } from "../../setup/setup-checks.service.js";
|
|
4
|
+
import { SetupGuidesService } from "../../setup/setup-guides.service.js";
|
|
5
|
+
import { PlatformOperations } from "../registry.js";
|
|
6
|
+
/**
|
|
7
|
+
* Setup guide operations of the `Platform` tool (spec 2026-11-09-setup-guides-v2-design.md §12),
|
|
8
|
+
* the `setup` domain: the guides a person may see, one guide rendered as Markdown, the cached check
|
|
9
|
+
* states of a guide and running one check. All are reads (a check never writes anywhere; its cost
|
|
10
|
+
* is bounded by the cache, the cooldown and the org's concurrency cap) and use the routes'
|
|
11
|
+
* services, so a guide carries no secret (§6.3) and check results only the fixed, redacted fields.
|
|
12
|
+
* Entering a secret, OAuth consent and the guide ack stay with the person on the web (`human-only`
|
|
13
|
+
* and `secret` exclusions); no setup operation takes a value.
|
|
14
|
+
*/
|
|
15
|
+
export declare class SetupOperations implements OnModuleInit {
|
|
16
|
+
private readonly registry;
|
|
17
|
+
private readonly checks;
|
|
18
|
+
private readonly guides;
|
|
19
|
+
private readonly kdb;
|
|
20
|
+
constructor(registry: PlatformOperations, checks: SetupChecksService, guides: SetupGuidesService, kdb: KernelDb);
|
|
21
|
+
/** The actor as the routes see a caller: the org, their role there now and their account. */
|
|
22
|
+
private caller;
|
|
23
|
+
onModuleInit(): void;
|
|
24
|
+
}
|