@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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LocalizedName, ThemeScheme } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { ApiError } from "../errors.js";
|
|
3
|
+
import { PluginGuides } from "../extensions/plugin-guides.js";
|
|
3
4
|
import { SuperAdminLock } from "../identity/super-admin.js";
|
|
4
5
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
5
6
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
@@ -172,6 +173,14 @@ export interface OrgOfferedComponentView extends OrgComponentView {
|
|
|
172
173
|
* name as its owner (本组织 for the viewing org's own, the owner's name for another org's).
|
|
173
174
|
*/
|
|
174
175
|
owner: Owner;
|
|
176
|
+
/**
|
|
177
|
+
* Connector templates only: the template's setup guide in its plugin's latest version (`GET
|
|
178
|
+
* …/catalog/:itemId/guides/:guideId`), null without one (spec 2026-11-09-setup-guides-v2 §9.3).
|
|
179
|
+
*/
|
|
180
|
+
guide?: {
|
|
181
|
+
itemId: string;
|
|
182
|
+
guideId: string;
|
|
183
|
+
} | null;
|
|
175
184
|
}
|
|
176
185
|
/** The result of an org switch: the component, or (switching off without `confirm`) the preview. */
|
|
177
186
|
export type ComponentSwitchResult = {
|
|
@@ -231,11 +240,15 @@ export declare class ComponentScopeService {
|
|
|
231
240
|
/** Promote on share (ruling P3-3): an org row shown or associated becomes a platform row. */
|
|
232
241
|
private readonly promotion;
|
|
233
242
|
readonly txHost: TransactionHost;
|
|
243
|
+
/** The connector templates' setup guides (the org list's `guide`). */
|
|
244
|
+
private readonly guides;
|
|
234
245
|
constructor(kdb: KernelDb, adminLock: SuperAdminLock,
|
|
235
246
|
/** The org row lock (orgs/org-lock.ts): joins the caller's transaction. */
|
|
236
247
|
orgLock: OrgLock,
|
|
237
248
|
/** Promote on share (ruling P3-3): an org row shown or associated becomes a platform row. */
|
|
238
|
-
promotion: ComponentPromotion, txHost: TransactionHost
|
|
249
|
+
promotion: ComponentPromotion, txHost: TransactionHost,
|
|
250
|
+
/** The connector templates' setup guides (the org list's `guide`). */
|
|
251
|
+
guides: Pick<PluginGuides, "templateGuides">);
|
|
239
252
|
private get db();
|
|
240
253
|
/**
|
|
241
254
|
* What the admin routes act on (ruling P3-23): the platform component `id`, an org row the org
|
|
@@ -12,6 +12,7 @@ import { Inject, Injectable } from "@nestjs/common";
|
|
|
12
12
|
import { sql } from "kysely";
|
|
13
13
|
import { templateTypeClashes, templateTypeOf } from "../agents/templates.js";
|
|
14
14
|
import { ApiError } from "../errors.js";
|
|
15
|
+
import { PluginGuides } from "../extensions/plugin-guides.js";
|
|
15
16
|
import { audit } from "../identity/audit.js";
|
|
16
17
|
import { SuperAdminLock } from "../identity/super-admin.js";
|
|
17
18
|
import { notifyItemShared } from "../inbox/org-notices.js";
|
|
@@ -124,16 +125,20 @@ let ComponentScopeService = class ComponentScopeService {
|
|
|
124
125
|
orgLock;
|
|
125
126
|
promotion;
|
|
126
127
|
txHost;
|
|
128
|
+
guides;
|
|
127
129
|
constructor(kdb, adminLock,
|
|
128
130
|
/** The org row lock (orgs/org-lock.ts): joins the caller's transaction. */
|
|
129
131
|
orgLock,
|
|
130
132
|
/** Promote on share (ruling P3-3): an org row shown or associated becomes a platform row. */
|
|
131
|
-
promotion, txHost
|
|
133
|
+
promotion, txHost,
|
|
134
|
+
/** The connector templates' setup guides (the org list's `guide`). */
|
|
135
|
+
guides) {
|
|
132
136
|
this.kdb = kdb;
|
|
133
137
|
this.adminLock = adminLock;
|
|
134
138
|
this.orgLock = orgLock;
|
|
135
139
|
this.promotion = promotion;
|
|
136
140
|
this.txHost = txHost;
|
|
141
|
+
this.guides = guides;
|
|
137
142
|
}
|
|
138
143
|
get db() {
|
|
139
144
|
return this.kdb.db;
|
|
@@ -245,6 +250,9 @@ let ComponentScopeService = class ComponentScopeService {
|
|
|
245
250
|
const st = await loadScopeState(this.db, kind, comps);
|
|
246
251
|
const linked = await this.linkedCopies(orgId, kind);
|
|
247
252
|
const owners = await ownersOf(this.db, comps.flatMap((c) => (c.ownerOrgId === null ? [] : [c.ownerOrgId])));
|
|
253
|
+
const guides = kind === "connector_template"
|
|
254
|
+
? await this.guides.templateGuides(comps.flatMap((c) => c.itemId === null ? [] : [{ itemId: c.itemId, templateId: c.name }]))
|
|
255
|
+
: undefined;
|
|
248
256
|
const rows = [];
|
|
249
257
|
for (const c of comps) {
|
|
250
258
|
const p = pluginFactsOf(st, c.itemId, orgId);
|
|
@@ -273,6 +281,7 @@ let ComponentScopeService = class ComponentScopeService {
|
|
|
273
281
|
platformDefault: !locked && (c.scopeMode === "follow" ? p?.scope === "all" : c.scope === "all"),
|
|
274
282
|
linkedIds: linked.get(c.id) ?? [],
|
|
275
283
|
owner: ownerOf(c.ownerOrgId, owners),
|
|
284
|
+
...(guides !== undefined && { guide: guides.get(`${c.itemId}/${c.name}`) ?? null }),
|
|
276
285
|
});
|
|
277
286
|
}
|
|
278
287
|
rows.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
@@ -1067,7 +1076,8 @@ ComponentScopeService = __decorate([
|
|
|
1067
1076
|
__param(1, Inject(SuperAdminLock)),
|
|
1068
1077
|
__param(2, Inject(OrgLock)),
|
|
1069
1078
|
__param(3, Inject(ComponentPromotion)),
|
|
1070
|
-
__param(4, Inject(TransactionHost))
|
|
1079
|
+
__param(4, Inject(TransactionHost)),
|
|
1080
|
+
__param(5, Inject(PluginGuides))
|
|
1071
1081
|
], ComponentScopeService);
|
|
1072
1082
|
export { ComponentScopeService };
|
|
1073
1083
|
/** Whether `c` is the platform default theme `uiTheme` (locked on in every org, themes spec §7). */
|
|
@@ -188,7 +188,7 @@ export declare function headsToResolve(entries: readonly MarketplaceEntry[], imp
|
|
|
188
188
|
/** The host versions (an entry's `minKernel` is judged against them). */
|
|
189
189
|
export declare const HOST_VERSIONS: {
|
|
190
190
|
readonly kernel: string;
|
|
191
|
-
readonly sdk: "0.1.0-rc.
|
|
191
|
+
readonly sdk: "0.1.0-rc.11";
|
|
192
192
|
};
|
|
193
193
|
/** Whether this deployment satisfies the entry's `minKernel`. */
|
|
194
194
|
export declare const entryCompatible: (e: Pick<MarketplaceEntry, "minKernel">) => boolean;
|
|
@@ -98,10 +98,11 @@ export declare class OrgCatalogController {
|
|
|
98
98
|
*/
|
|
99
99
|
icon(org: OrgContext, itemId: string, reply: FastifyReply): Promise<void>;
|
|
100
100
|
/**
|
|
101
|
-
* A setup guide of the item, rendered for this org (spec 2026-11-
|
|
102
|
-
* §
|
|
103
|
-
*
|
|
104
|
-
*
|
|
101
|
+
* A setup guide of the item, rendered for this org (spec 2026-11-09-setup-guides-v2-design.md
|
|
102
|
+
* §7.2): the document's blocks with the place's variables filled in, its modes, audiences and
|
|
103
|
+
* checks, the unresolved variables with their reasons, the drift hash and the target. The item
|
|
104
|
+
* must be one the org's catalog shows; the place and audience's action (`channels.manage`,
|
|
105
|
+
* `connectors.manage`, `connectors.use`) is checked by the service.
|
|
105
106
|
*/
|
|
106
107
|
guide(org: OrgContext, itemId: string, guideId: string, q: z.infer<typeof CatalogGuideQuery>): Promise<{
|
|
107
108
|
guide: RenderedSetupGuide;
|
|
@@ -129,10 +129,11 @@ let OrgCatalogController = class OrgCatalogController {
|
|
|
129
129
|
await sendCatalogIcon(reply, icon);
|
|
130
130
|
}
|
|
131
131
|
/**
|
|
132
|
-
* A setup guide of the item, rendered for this org (spec 2026-11-
|
|
133
|
-
* §
|
|
134
|
-
*
|
|
135
|
-
*
|
|
132
|
+
* A setup guide of the item, rendered for this org (spec 2026-11-09-setup-guides-v2-design.md
|
|
133
|
+
* §7.2): the document's blocks with the place's variables filled in, its modes, audiences and
|
|
134
|
+
* checks, the unresolved variables with their reasons, the drift hash and the target. The item
|
|
135
|
+
* must be one the org's catalog shows; the place and audience's action (`channels.manage`,
|
|
136
|
+
* `connectors.manage`, `connectors.use`) is checked by the service.
|
|
136
137
|
*/
|
|
137
138
|
async guide(org, itemId, guideId, q) {
|
|
138
139
|
return { guide: await this.guides.render(org, itemId, guideId, q) };
|
|
@@ -63,6 +63,11 @@ export declare const OrgPluginSwitchBody: z.ZodObject<{
|
|
|
63
63
|
export declare const CatalogItemPathParams: z.ZodObject<{
|
|
64
64
|
itemId: z.ZodString;
|
|
65
65
|
}, z.core.$strip>;
|
|
66
|
+
/** `:itemId` / `:guideId` of the guide route (`@Param`). */
|
|
67
|
+
export declare const CatalogGuidePathParams: z.ZodObject<{
|
|
68
|
+
itemId: z.ZodString;
|
|
69
|
+
guideId: z.ZodString;
|
|
70
|
+
}, z.core.$strip>;
|
|
66
71
|
/** `:installId` as the uninstall route takes it (`@Param`). */
|
|
67
72
|
export declare const PluginInstallPathParams: z.ZodObject<{
|
|
68
73
|
installId: z.ZodString;
|
|
@@ -77,12 +82,23 @@ export declare const CatalogRequestsListQuery: z.ZodObject<{
|
|
|
77
82
|
}>>;
|
|
78
83
|
}, z.core.$strip>;
|
|
79
84
|
/**
|
|
80
|
-
* `GET catalog/:itemId/guides/:guideId
|
|
81
|
-
*
|
|
85
|
+
* `GET catalog/:itemId/guides/:guideId` (spec 2026-11-09-setup-guides-v2-design.md §7.2): the mode
|
|
86
|
+
* and audience to render (the place's, checked by the service), the document language, and the
|
|
87
|
+
* target: a channel connection or the name typed so far on 新建渠道 (`channel-connection`), a
|
|
88
|
+
* connector made from the template (`connector-template`).
|
|
82
89
|
*/
|
|
83
90
|
export declare const CatalogGuideQuery: z.ZodObject<{
|
|
84
91
|
mode: z.ZodOptional<z.ZodString>;
|
|
92
|
+
audience: z.ZodOptional<z.ZodEnum<{
|
|
93
|
+
admin: "admin";
|
|
94
|
+
member: "member";
|
|
95
|
+
}>>;
|
|
96
|
+
locale: z.ZodOptional<z.ZodEnum<{
|
|
97
|
+
en: "en";
|
|
98
|
+
zh: "zh";
|
|
99
|
+
}>>;
|
|
85
100
|
connectionId: z.ZodOptional<z.ZodString>;
|
|
86
101
|
name: z.ZodOptional<z.ZodString>;
|
|
102
|
+
connectorId: z.ZodOptional<z.ZodString>;
|
|
87
103
|
}, z.core.$strict>;
|
|
88
104
|
export declare const ORG_CATALOG_ROUTES: readonly RouteSchemas[];
|
|
@@ -53,6 +53,10 @@ export const OrgPluginSwitchBody = z
|
|
|
53
53
|
.strict();
|
|
54
54
|
/** `:itemId` as the routes take it (`@Param`). */
|
|
55
55
|
export const CatalogItemPathParams = z.object({ itemId: z.string().min(1) });
|
|
56
|
+
/** `:itemId` / `:guideId` of the guide route (`@Param`). */
|
|
57
|
+
export const CatalogGuidePathParams = CatalogItemPathParams.extend({
|
|
58
|
+
guideId: z.string().min(1).max(64),
|
|
59
|
+
});
|
|
56
60
|
/** `:installId` as the uninstall route takes it (`@Param`). */
|
|
57
61
|
export const PluginInstallPathParams = z.object({ installId: z.string().min(1) });
|
|
58
62
|
/** The super admin's request list filter. */
|
|
@@ -60,19 +64,29 @@ export const CatalogRequestsListQuery = z.object({
|
|
|
60
64
|
status: z.enum(["pending", "approved", "rejected", "cancelled"]).optional(),
|
|
61
65
|
});
|
|
62
66
|
/**
|
|
63
|
-
* `GET catalog/:itemId/guides/:guideId
|
|
64
|
-
*
|
|
67
|
+
* `GET catalog/:itemId/guides/:guideId` (spec 2026-11-09-setup-guides-v2-design.md §7.2): the mode
|
|
68
|
+
* and audience to render (the place's, checked by the service), the document language, and the
|
|
69
|
+
* target: a channel connection or the name typed so far on 新建渠道 (`channel-connection`), a
|
|
70
|
+
* connector made from the template (`connector-template`).
|
|
65
71
|
*/
|
|
66
72
|
export const CatalogGuideQuery = z
|
|
67
73
|
.object({
|
|
68
74
|
mode: z.string().min(1).max(64).optional(),
|
|
75
|
+
audience: z.enum(["admin", "member"]).optional(),
|
|
76
|
+
locale: z.enum(["en", "zh"]).optional(),
|
|
69
77
|
connectionId: z.string().min(1).max(100).optional(),
|
|
70
78
|
name: z.string().max(100).optional(),
|
|
79
|
+
connectorId: z.string().min(1).max(100).optional(),
|
|
71
80
|
})
|
|
72
81
|
.strict();
|
|
73
82
|
export const ORG_CATALOG_ROUTES = [
|
|
74
83
|
{ route: "GET /api/v1/orgs/:orgId/catalog" },
|
|
75
84
|
{ route: "GET /api/v1/orgs/:orgId/catalog/:itemId", params: CatalogItemPathParams },
|
|
85
|
+
{
|
|
86
|
+
route: "GET /api/v1/orgs/:orgId/catalog/:itemId/guides/:guideId",
|
|
87
|
+
params: CatalogGuidePathParams,
|
|
88
|
+
query: CatalogGuideQuery,
|
|
89
|
+
},
|
|
76
90
|
{
|
|
77
91
|
route: "POST /api/v1/orgs/:orgId/catalog/:itemId/requests",
|
|
78
92
|
params: CatalogItemPathParams,
|
|
@@ -9,6 +9,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
9
9
|
};
|
|
10
10
|
import { Inject, Injectable } from "@nestjs/common";
|
|
11
11
|
import { ApiError } from "../errors.js";
|
|
12
|
+
import { templateGuideOf } from "../extensions/plugin-guides.js";
|
|
12
13
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
13
14
|
import { ExtensionAvailability } from "../extensions/unavailable.js";
|
|
14
15
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
@@ -272,6 +273,11 @@ let OrgCatalogService = class OrgCatalogService {
|
|
|
272
273
|
throw itemNotFound();
|
|
273
274
|
const m = v.manifest;
|
|
274
275
|
const templates = await readCatalogTemplates(this.storage, v);
|
|
276
|
+
// where each template's page finds its setup guide (spec 2026-11-09-setup-guides-v2 §9.3)
|
|
277
|
+
const guideOf = (templateId) => {
|
|
278
|
+
const g = templateGuideOf(m, templateId);
|
|
279
|
+
return g ? { itemId, guideId: g.id } : null;
|
|
280
|
+
};
|
|
275
281
|
// Providers the install would switch on first (a refusal is the install's to report)
|
|
276
282
|
const implied = await this.pluginInstaller
|
|
277
283
|
.impliedProviders(orgId, m, templates, m.dependencies ?? [])
|
|
@@ -284,7 +290,7 @@ let OrgCatalogService = class OrgCatalogService {
|
|
|
284
290
|
item,
|
|
285
291
|
hasIcon: m.icon !== undefined,
|
|
286
292
|
extension: m.extension ? m.name : null,
|
|
287
|
-
templates: templates.map((t) => orgTemplateView(t.id, t.file)),
|
|
293
|
+
templates: templates.map((t) => orgTemplateView(t.id, t.file, guideOf(t.id))),
|
|
288
294
|
dependencies: [
|
|
289
295
|
...(m.dependencies ?? []).map((d) => ({ name: d.name, range: d.version })),
|
|
290
296
|
...implied.map((d) => ({ name: d.name, range: d.range, implied: true })),
|
|
@@ -292,7 +298,7 @@ let OrgCatalogService = class OrgCatalogService {
|
|
|
292
298
|
skills: (m.skills ?? []).map((s) => packagePath(s.path)),
|
|
293
299
|
agents: (m.agents ?? []).map((a) => packagePath(a.path)),
|
|
294
300
|
missingTemplates: item.installed !== null && item.state === "needs_config"
|
|
295
|
-
? ((await this.pluginInstaller.missingConnectors(orgId, itemId))?.templates ?? []).map((t) => orgTemplateView(t.id, t.file))
|
|
301
|
+
? ((await this.pluginInstaller.missingConnectors(orgId, itemId))?.templates ?? []).map((t) => orgTemplateView(t.id, t.file, guideOf(t.id)))
|
|
296
302
|
: [],
|
|
297
303
|
};
|
|
298
304
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { LocalizedName } from "@capybara-hq/plugin-sdk";
|
|
1
|
+
import type { LocalizedName, SuggestedAppearance } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { type ClientBuildSummary, ClientBuilds } from "../client/client-builds.service.js";
|
|
3
4
|
import { ExtensionDisplayNames } from "../extensions/display-name.js";
|
|
4
5
|
import { OrgExtensionConfigs, type OrgExtensionView } from "../extensions/org-config.js";
|
|
5
6
|
import { OrgOverrides, type OrgOverrideView } from "../extensions/org-overrides.js";
|
|
@@ -7,6 +8,8 @@ import { PluginIcons } from "../extensions/plugin-icons.js";
|
|
|
7
8
|
import { type Principal } from "../identity/principal.js";
|
|
8
9
|
import { type OrgContext } from "../orgs/org.guard.js";
|
|
9
10
|
import { type OrgToolSwitch, OrgToolSwitches, type OrgToolSwitchResult } from "../tools/org-tool-switches.js";
|
|
11
|
+
import { AppearanceApplyBody } from "./appearance.schemas.js";
|
|
12
|
+
import { type AppearanceResult, AppearanceService } from "./appearance.service.js";
|
|
10
13
|
import { OrgExtensionParams as ExtensionParams, OrgExtensionToolParams as ToolParams, OrgToolSwitchPut as ToolSwitchPut } from "./org-extension.schemas.js";
|
|
11
14
|
import { OrgExtensionSwitch } from "./org-extension-switch.js";
|
|
12
15
|
import type { UninstallPreview } from "./plugin-install.js";
|
|
@@ -31,20 +34,26 @@ declare const OverridesTake: z.ZodObject<{
|
|
|
31
34
|
/**
|
|
32
35
|
* One extension of the org list: the org view plus the plugin's display name, the URL of its
|
|
33
36
|
* plugin's icon on the org's catalog route (null without one or when the org may not see the
|
|
34
|
-
* plugin's item)
|
|
35
|
-
* only, also for members)
|
|
37
|
+
* plugin's item), the extension points it provides (`channel@1`, `web-search@1`, … the names
|
|
38
|
+
* only, also for members), the plugin's suggested appearance (null without one; the page offers
|
|
39
|
+
* 应用此插件的外观 to org admins when set, client extensions spec §6.5) and the client build of the
|
|
40
|
+
* running package (files with sizes, total, client API version; null without one: the permission
|
|
41
|
+
* review's 客户端代码 group, spec §5.4).
|
|
36
42
|
*/
|
|
37
43
|
export type OrgExtensionItem = OrgExtensionView & {
|
|
38
44
|
displayName: LocalizedName | null;
|
|
39
45
|
icon: string | null;
|
|
40
46
|
provides: string[];
|
|
47
|
+
suggestedAppearance: SuggestedAppearance | null;
|
|
48
|
+
client: ClientBuildSummary | null;
|
|
41
49
|
};
|
|
42
50
|
/**
|
|
43
51
|
* What a member sees of an extension: its state and the points it provides (names only, what the
|
|
44
|
-
* 扩展 page sorts by), never the org config, the secrets' state, the config schema
|
|
45
|
-
* permission list
|
|
52
|
+
* 扩展 page sorts by), never the org config, the secrets' state, the config schema, the
|
|
53
|
+
* permission list, the suggested appearance (members cannot apply it) or the client build (part of
|
|
54
|
+
* the permission review).
|
|
46
55
|
*/
|
|
47
|
-
export type OrgExtensionMemberItem = Omit<OrgExtensionItem, "config" | "secrets" | "orgConfigSchema" | "permissions">;
|
|
56
|
+
export type OrgExtensionMemberItem = Omit<OrgExtensionItem, "config" | "secrets" | "orgConfigSchema" | "permissions" | "suggestedAppearance" | "client">;
|
|
48
57
|
/**
|
|
49
58
|
* Org-level extension enablement and config (`/api/v1/orgs/:orgId/extensions`); responses echo only
|
|
50
59
|
* non-secret config and whether each secret is set.
|
|
@@ -54,7 +63,9 @@ export declare class OrgExtensionConfigsController {
|
|
|
54
63
|
private readonly displayNames;
|
|
55
64
|
private readonly extSwitch;
|
|
56
65
|
private readonly icons;
|
|
57
|
-
|
|
66
|
+
private readonly appearance;
|
|
67
|
+
private readonly clientBuilds;
|
|
68
|
+
constructor(configs: OrgExtensionConfigs, displayNames: ExtensionDisplayNames, extSwitch: OrgExtensionSwitch, icons: PluginIcons, appearance: AppearanceService, clientBuilds: ClientBuilds);
|
|
58
69
|
/**
|
|
59
70
|
* The org's extensions (also the channel plugin options: those providing `channel@1`). Members
|
|
60
71
|
* get the projection {@link OrgExtensionMemberItem}; admins the full view.
|
|
@@ -72,6 +83,15 @@ export declare class OrgExtensionConfigsController {
|
|
|
72
83
|
preview: UninstallPreview;
|
|
73
84
|
confirm: string;
|
|
74
85
|
}>;
|
|
86
|
+
/**
|
|
87
|
+
* 应用此插件的外观 (client extensions spec §6.5), for a plugin whose extension is on in the org:
|
|
88
|
+
* sets the plugin's suggested theme as the org's default theme (keeping `personal`) and each
|
|
89
|
+
* suggested replacement as the org arrangement's `use` of its slot, in one transaction.
|
|
90
|
+
* `dryRun: true` answers the same changes and writes nothing. A theme not on in the org -> 400
|
|
91
|
+
* `theme.not_available` (nothing written); a replacement not available in the org is skipped.
|
|
92
|
+
* An extension not on in the org, or a plugin without a suggestion -> 404 `extension.not_found`.
|
|
93
|
+
*/
|
|
94
|
+
applyAppearance(principal: Principal, org: OrgContext, { extension }: z.infer<typeof ExtensionParams>, body: z.infer<typeof AppearanceApplyBody>): Promise<AppearanceResult>;
|
|
75
95
|
}
|
|
76
96
|
/**
|
|
77
97
|
* The org's two-level deployment config of an extension (spec A §5.3 to §5.6): following or a copy,
|
|
@@ -9,6 +9,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
9
9
|
};
|
|
10
10
|
import { Controller, Delete, Get, HttpCode, Inject, Param, Post, Put } from "@nestjs/common";
|
|
11
11
|
import { z } from "zod";
|
|
12
|
+
import { ClientBuilds } from "../client/client-builds.service.js";
|
|
12
13
|
import { ExtensionDisplayNames } from "../extensions/display-name.js";
|
|
13
14
|
import { OrgExtensionConfigs, providesOf, } from "../extensions/org-config.js";
|
|
14
15
|
import { OrgOverrides } from "../extensions/org-overrides.js";
|
|
@@ -19,6 +20,8 @@ import { ZBody, ZParam } from "../infra/validation/zod-params.js";
|
|
|
19
20
|
import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
|
|
20
21
|
import { roleAtLeast } from "../orgs/roles.js";
|
|
21
22
|
import { OrgToolSwitches, } from "../tools/org-tool-switches.js";
|
|
23
|
+
import { AppearanceApplyBody } from "./appearance.schemas.js";
|
|
24
|
+
import { AppearanceService } from "./appearance.service.js";
|
|
22
25
|
import { OrgExtensionParams as ExtensionParams, OrgExtensionToolParams as ToolParams, OrgToolSwitchPut as ToolSwitchPut, } from "./org-extension.schemas.js";
|
|
23
26
|
import { OrgExtensionSwitch } from "./org-extension-switch.js";
|
|
24
27
|
const PutBody = z
|
|
@@ -65,6 +68,8 @@ class OrgExtensionParamsDto extends createZodDto(ExtensionParams, "OrgExtensionP
|
|
|
65
68
|
}
|
|
66
69
|
class OrgExtensionToolParamsDto extends createZodDto(ToolParams, "OrgExtensionToolParams") {
|
|
67
70
|
}
|
|
71
|
+
class OrgAppearanceApplyBody extends createZodDto(AppearanceApplyBody, "OrgAppearanceApplyBody") {
|
|
72
|
+
}
|
|
68
73
|
class OrgOverridesPutBody extends createZodDto(OverridesPut, "OrgOverridesPutBody") {
|
|
69
74
|
}
|
|
70
75
|
class OrgOverridesTakeBody extends createZodDto(OverridesTake, "OrgOverridesTakeBody") {
|
|
@@ -78,11 +83,15 @@ let OrgExtensionConfigsController = class OrgExtensionConfigsController {
|
|
|
78
83
|
displayNames;
|
|
79
84
|
extSwitch;
|
|
80
85
|
icons;
|
|
81
|
-
|
|
86
|
+
appearance;
|
|
87
|
+
clientBuilds;
|
|
88
|
+
constructor(configs, displayNames, extSwitch, icons, appearance, clientBuilds) {
|
|
82
89
|
this.configs = configs;
|
|
83
90
|
this.displayNames = displayNames;
|
|
84
91
|
this.extSwitch = extSwitch;
|
|
85
92
|
this.icons = icons;
|
|
93
|
+
this.appearance = appearance;
|
|
94
|
+
this.clientBuilds = clientBuilds;
|
|
86
95
|
}
|
|
87
96
|
/**
|
|
88
97
|
* The org's extensions (also the channel plugin options: those providing `channel@1`). Members
|
|
@@ -91,20 +100,25 @@ let OrgExtensionConfigsController = class OrgExtensionConfigsController {
|
|
|
91
100
|
async list(org) {
|
|
92
101
|
const views = await this.configs.list(org.orgId);
|
|
93
102
|
const plugins = views.map((v) => v.plugin);
|
|
94
|
-
const
|
|
103
|
+
const admin = roleAtLeast(org.role, "admin");
|
|
104
|
+
const [names, icons, suggestions, clients] = await Promise.all([
|
|
95
105
|
this.displayNames.many(plugins),
|
|
96
106
|
this.icons.many(plugins, orgIconScope(org)),
|
|
107
|
+
admin ? this.appearance.suggestions(plugins) : new Map(),
|
|
108
|
+
admin ? this.clientBuilds.installedSummaries(plugins) : new Map(),
|
|
97
109
|
]);
|
|
98
110
|
const items = views.map((v) => ({
|
|
99
111
|
...v,
|
|
100
112
|
displayName: names.get(v.plugin) ?? null,
|
|
101
113
|
icon: icons.get(v.plugin) ?? null,
|
|
102
114
|
provides: providesOf(v),
|
|
115
|
+
suggestedAppearance: suggestions.get(v.plugin) ?? null,
|
|
116
|
+
client: clients.get(v.plugin) ?? null,
|
|
103
117
|
}));
|
|
104
|
-
if (
|
|
118
|
+
if (admin)
|
|
105
119
|
return { extensions: items };
|
|
106
120
|
return {
|
|
107
|
-
extensions: items.map(({ config: _c, secrets: _s, orgConfigSchema: _o, permissions: _p, ...rest }) => rest),
|
|
121
|
+
extensions: items.map(({ config: _c, secrets: _s, orgConfigSchema: _o, permissions: _p, suggestedAppearance: _a, client: _cl, ...rest }) => rest),
|
|
108
122
|
};
|
|
109
123
|
}
|
|
110
124
|
/**
|
|
@@ -116,9 +130,11 @@ let OrgExtensionConfigsController = class OrgExtensionConfigsController {
|
|
|
116
130
|
const r = await this.extSwitch.put(org.orgId, p.account.id, extension, body, patTokenId(p));
|
|
117
131
|
if (r.kind === "preview")
|
|
118
132
|
return { preview: r.preview, confirm: r.confirm };
|
|
119
|
-
const [displayName, icons] = await Promise.all([
|
|
133
|
+
const [displayName, icons, suggestions, clients] = await Promise.all([
|
|
120
134
|
this.displayNames.get(r.view.plugin),
|
|
121
135
|
this.icons.many([r.view.plugin], orgIconScope(org)),
|
|
136
|
+
this.appearance.suggestions([r.view.plugin]),
|
|
137
|
+
this.clientBuilds.installedSummaries([r.view.plugin]),
|
|
122
138
|
]);
|
|
123
139
|
return {
|
|
124
140
|
extension: {
|
|
@@ -126,9 +142,24 @@ let OrgExtensionConfigsController = class OrgExtensionConfigsController {
|
|
|
126
142
|
displayName,
|
|
127
143
|
icon: icons.get(r.view.plugin) ?? null,
|
|
128
144
|
provides: providesOf(r.view),
|
|
145
|
+
suggestedAppearance: suggestions.get(r.view.plugin) ?? null,
|
|
146
|
+
client: clients.get(r.view.plugin) ?? null,
|
|
129
147
|
},
|
|
130
148
|
};
|
|
131
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* 应用此插件的外观 (client extensions spec §6.5), for a plugin whose extension is on in the org:
|
|
152
|
+
* sets the plugin's suggested theme as the org's default theme (keeping `personal`) and each
|
|
153
|
+
* suggested replacement as the org arrangement's `use` of its slot, in one transaction.
|
|
154
|
+
* `dryRun: true` answers the same changes and writes nothing. A theme not on in the org -> 400
|
|
155
|
+
* `theme.not_available` (nothing written); a replacement not available in the org is skipped.
|
|
156
|
+
* An extension not on in the org, or a plugin without a suggestion -> 404 `extension.not_found`.
|
|
157
|
+
*/
|
|
158
|
+
applyAppearance(principal, org, { extension }, body) {
|
|
159
|
+
const p = requireUser(principal);
|
|
160
|
+
const tokenId = patTokenId(p);
|
|
161
|
+
return this.appearance.apply({ orgId: org.orgId }, extension, { accountId: p.account.id, ...(tokenId !== undefined && { tokenId }) }, body.dryRun === true);
|
|
162
|
+
}
|
|
132
163
|
};
|
|
133
164
|
__decorate([
|
|
134
165
|
Get(),
|
|
@@ -143,12 +174,23 @@ __decorate([
|
|
|
143
174
|
__param(2, Param("extension")),
|
|
144
175
|
__param(3, ZBody(OrgExtensionPutBody))
|
|
145
176
|
], OrgExtensionConfigsController.prototype, "put", null);
|
|
177
|
+
__decorate([
|
|
178
|
+
Post(":extension/appearance"),
|
|
179
|
+
HttpCode(200),
|
|
180
|
+
OrgAction("org.update"),
|
|
181
|
+
__param(0, CurrentPrincipal()),
|
|
182
|
+
__param(1, CurrentOrg()),
|
|
183
|
+
__param(2, ZParam(OrgExtensionParamsDto)),
|
|
184
|
+
__param(3, ZBody(OrgAppearanceApplyBody))
|
|
185
|
+
], OrgExtensionConfigsController.prototype, "applyAppearance", null);
|
|
146
186
|
OrgExtensionConfigsController = __decorate([
|
|
147
187
|
Controller("api/v1/orgs/:orgId/extensions"),
|
|
148
188
|
__param(0, Inject(OrgExtensionConfigs)),
|
|
149
189
|
__param(1, Inject(ExtensionDisplayNames)),
|
|
150
190
|
__param(2, Inject(OrgExtensionSwitch)),
|
|
151
|
-
__param(3, Inject(PluginIcons))
|
|
191
|
+
__param(3, Inject(PluginIcons)),
|
|
192
|
+
__param(4, Inject(AppearanceService)),
|
|
193
|
+
__param(5, Inject(ClientBuilds))
|
|
152
194
|
], OrgExtensionConfigsController);
|
|
153
195
|
export { OrgExtensionConfigsController };
|
|
154
196
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type AgentTemplate, type AgentTemplateTier, type LocalizedName, type PluginManifest, type ThemeScheme } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import type { Queue } from "bullmq";
|
|
3
|
+
import { ClientBuilds } from "../client/client-builds.service.js";
|
|
3
4
|
import { ApiError } from "../errors.js";
|
|
4
5
|
import { ExtensionAdminOps } from "../extensions/admin-ops.js";
|
|
5
6
|
import { ExtensionAdmin } from "../extensions/admin-view.js";
|
|
@@ -103,6 +104,24 @@ export interface PluginReviewExtension {
|
|
|
103
104
|
reviewHash: string;
|
|
104
105
|
/** Sensitive permissions or migration warnings. */
|
|
105
106
|
sensitive: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* The extension's client code (client extensions spec §5.4, §9.1), for the 客户端代码 group of
|
|
109
|
+
* the review: every file of `extension.client` by its manifest key with its size, checked
|
|
110
|
+
* against its integrity when the import was prepared. Absent without client code.
|
|
111
|
+
*/
|
|
112
|
+
client?: PluginReviewClient;
|
|
113
|
+
}
|
|
114
|
+
/** The client code of an extension in a review. */
|
|
115
|
+
export interface PluginReviewClient {
|
|
116
|
+
/** Entry, styles and assets in that order; `path` is the manifest key (`./dist/client/...`). */
|
|
117
|
+
files: {
|
|
118
|
+
path: string;
|
|
119
|
+
size: number;
|
|
120
|
+
}[];
|
|
121
|
+
/** Total bytes. */
|
|
122
|
+
totalBytes: number;
|
|
123
|
+
/** The client API version the bundle was built against. */
|
|
124
|
+
apiVersion: number;
|
|
106
125
|
}
|
|
107
126
|
/** One connector template in a review. */
|
|
108
127
|
export interface PluginReviewTemplate {
|
|
@@ -350,9 +369,10 @@ export interface StagedTarget {
|
|
|
350
369
|
}
|
|
351
370
|
/**
|
|
352
371
|
* The API error of a plugin package that cannot be read in a catalog path: the pre-0.1.0 format ->
|
|
353
|
-
* `catalog.legacy_format`;
|
|
354
|
-
*
|
|
355
|
-
* anything else -> `catalog.invalid_manifest` (issues as
|
|
372
|
+
* `catalog.legacy_format`; undeclared client code -> `client.undeclared`; a failing theme (themes
|
|
373
|
+
* spec §5) -> `theme.invalid` (details `[{ theme, errors }]`) or `theme.unreadable` (details
|
|
374
|
+
* `[{ theme, issues }]`, the failing pairs); anything else -> `catalog.invalid_manifest` (issues as
|
|
375
|
+
* details).
|
|
356
376
|
*/
|
|
357
377
|
export declare function catalogPackageError(e: PluginPackageError | ExtensionPackageError): ApiError;
|
|
358
378
|
export declare class PluginImport {
|
|
@@ -378,6 +398,8 @@ export declare class PluginImport {
|
|
|
378
398
|
private readonly platform;
|
|
379
399
|
/** A failed platform sync enqueues a run of the migration job here (it heals the item). */
|
|
380
400
|
private readonly maintenance;
|
|
401
|
+
/** The client build of a dropped org upload's package is deleted with it. */
|
|
402
|
+
private readonly clientBuilds;
|
|
381
403
|
/** Where plugin files go (the kernel's object storage; the CLI's own, see {@link useCliStorage}). */
|
|
382
404
|
private files;
|
|
383
405
|
/**
|
|
@@ -398,7 +420,9 @@ export declare class PluginImport {
|
|
|
398
420
|
/** The platform rows of a new item's components, written after the confirm's commit. */
|
|
399
421
|
platform: PlatformComponents,
|
|
400
422
|
/** A failed platform sync enqueues a run of the migration job here (it heals the item). */
|
|
401
|
-
maintenance: Pick<Queue, "add"
|
|
423
|
+
maintenance: Pick<Queue, "add">,
|
|
424
|
+
/** The client build of a dropped org upload's package is deleted with it. */
|
|
425
|
+
clientBuilds: ClientBuilds);
|
|
402
426
|
/** The kernel-schema handle of the current context (the transaction, else the pool). */
|
|
403
427
|
private get db();
|
|
404
428
|
/**
|