@capybara-hq/kernel 0.1.0-rc.26 → 0.1.0-rc.27
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/catalog/catalog-content.d.ts +6 -1
- package/dist/catalog/catalog-content.js +2 -1
- package/dist/catalog/org-catalog.service.js +5 -2
- package/dist/catalog/plugin-install.d.ts +5 -0
- package/dist/catalog/plugin-install.js +37 -1
- package/dist/tools/connectors.service.js +0 -4
- package/package.json +1 -1
|
@@ -77,6 +77,11 @@ export interface OrgCatalogTemplate {
|
|
|
77
77
|
* install wizard does not ask for it (an org admin sets it up when switching it on).
|
|
78
78
|
*/
|
|
79
79
|
defaultOff: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* The template is on in this org right now (a default-off one an admin switched on): the install
|
|
82
|
+
* asks for its input too, since the install is what creates its connector.
|
|
83
|
+
*/
|
|
84
|
+
on: boolean;
|
|
80
85
|
/**
|
|
81
86
|
* The template's setup guide in the item's latest version (`GET …/catalog/:itemId/guides/
|
|
82
87
|
* :guideId`), null without one (spec 2026-11-09-setup-guides-v2-design.md §9.3).
|
|
@@ -118,7 +123,7 @@ export interface OrgCatalogDetail {
|
|
|
118
123
|
* A connector template as an org sees it (the install wizard and the upgrade preview's inputs):
|
|
119
124
|
* presets and editable paths, no credentials.
|
|
120
125
|
*/
|
|
121
|
-
export declare function orgTemplateView(id: string, file: ConnectorTemplateFile, guide?: OrgCatalogTemplate["guide"]): OrgCatalogTemplate;
|
|
126
|
+
export declare function orgTemplateView(id: string, file: ConnectorTemplateFile, guide?: OrgCatalogTemplate["guide"], on?: boolean): OrgCatalogTemplate;
|
|
122
127
|
/** An item's icon (the latest version's plugin icon). */
|
|
123
128
|
export interface CatalogIcon {
|
|
124
129
|
data: Uint8Array;
|
|
@@ -16,7 +16,7 @@ import { satisfiesRange } from "./versions.js";
|
|
|
16
16
|
* A connector template as an org sees it (the install wizard and the upgrade preview's inputs):
|
|
17
17
|
* presets and editable paths, no credentials.
|
|
18
18
|
*/
|
|
19
|
-
export function orgTemplateView(id, file, guide = null) {
|
|
19
|
+
export function orgTemplateView(id, file, guide = null, on = true) {
|
|
20
20
|
const t = file.template;
|
|
21
21
|
return {
|
|
22
22
|
id,
|
|
@@ -30,6 +30,7 @@ export function orgTemplateView(id, file, guide = null) {
|
|
|
30
30
|
ownership: t.ownership ??
|
|
31
31
|
(typeof t.auth.ownership === "string" ? t.auth.ownership : null),
|
|
32
32
|
defaultOff: file.defaultEnabled === false,
|
|
33
|
+
on,
|
|
33
34
|
guide,
|
|
34
35
|
};
|
|
35
36
|
}
|
|
@@ -273,6 +273,9 @@ let OrgCatalogService = class OrgCatalogService {
|
|
|
273
273
|
throw itemNotFound();
|
|
274
274
|
const m = v.manifest;
|
|
275
275
|
const templates = await readCatalogTemplates(this.storage, v);
|
|
276
|
+
// Which templates are on in this org now: the install asks for the input of those, a
|
|
277
|
+
// default-off one an admin switched on included
|
|
278
|
+
const on = await connectorTemplatesOn(this.db, orgId, itemId, templates.map((t) => t.id));
|
|
276
279
|
// where each template's page finds its setup guide (spec 2026-11-09-setup-guides-v2 §9.3)
|
|
277
280
|
const guideOf = (templateId) => {
|
|
278
281
|
const g = templateGuideOf(m, templateId);
|
|
@@ -290,7 +293,7 @@ let OrgCatalogService = class OrgCatalogService {
|
|
|
290
293
|
item,
|
|
291
294
|
hasIcon: m.icon !== undefined,
|
|
292
295
|
extension: m.extension ? m.name : null,
|
|
293
|
-
templates: templates.map((t) => orgTemplateView(t.id, t.file, guideOf(t.id))),
|
|
296
|
+
templates: templates.map((t) => orgTemplateView(t.id, t.file, guideOf(t.id), on.has(t.id))),
|
|
294
297
|
dependencies: [
|
|
295
298
|
...(m.dependencies ?? []).map((d) => ({ name: d.name, range: d.version })),
|
|
296
299
|
...implied.map((d) => ({ name: d.name, range: d.range, implied: true })),
|
|
@@ -298,7 +301,7 @@ let OrgCatalogService = class OrgCatalogService {
|
|
|
298
301
|
skills: (m.skills ?? []).map((s) => packagePath(s.path)),
|
|
299
302
|
agents: (m.agents ?? []).map((a) => packagePath(a.path)),
|
|
300
303
|
missingTemplates: item.installed !== null && item.state === "needs_config"
|
|
301
|
-
? ((await this.pluginInstaller.missingConnectors(orgId, itemId))?.templates ?? []).map((t) => orgTemplateView(t.id, t.file, guideOf(t.id)))
|
|
304
|
+
? ((await this.pluginInstaller.missingConnectors(orgId, itemId))?.templates ?? []).map((t) => orgTemplateView(t.id, t.file, guideOf(t.id), true))
|
|
302
305
|
: [],
|
|
303
306
|
};
|
|
304
307
|
}
|
|
@@ -540,6 +540,11 @@ export declare class PluginInstaller {
|
|
|
540
540
|
file: ConnectorTemplateFile;
|
|
541
541
|
}[];
|
|
542
542
|
} | undefined>;
|
|
543
|
+
/**
|
|
544
|
+
* The org's live connector made from one of the plugin's connector templates, if any: an
|
|
545
|
+
* uninstall keeps a connector its agents use, and the plugin's next switch-on reuses it.
|
|
546
|
+
*/
|
|
547
|
+
private liveTemplateConnector;
|
|
543
548
|
/**
|
|
544
549
|
* Creates the connectors an installed plugin is missing (ruling P2-10, `POST …/catalog/:itemId/
|
|
545
550
|
* connectors`): `input.connectors` names some of {@link missingConnectors}' templates with the
|
|
@@ -484,6 +484,10 @@ let PluginInstaller = class PluginInstaller {
|
|
|
484
484
|
// The kernel installs only what needs no org input (the scope sync's `needs_config` rule)
|
|
485
485
|
if (actor === null)
|
|
486
486
|
throw systemNeedsInput(manifest.name);
|
|
487
|
+
// An earlier switch-off kept this template's connector: the install takes it back, so its
|
|
488
|
+
// input is not asked for here (the connector keeps its endpoint and credentials)
|
|
489
|
+
if ((await this.liveTemplateConnector(orgId, itemId, ct.id)) !== undefined)
|
|
490
|
+
continue;
|
|
487
491
|
connectors.set(ct.id, this.planConnector(actor, { itemId, version, name: manifest.name }, ct, input, at, approvedBy));
|
|
488
492
|
}
|
|
489
493
|
}
|
|
@@ -743,9 +747,24 @@ let PluginInstaller = class PluginInstaller {
|
|
|
743
747
|
}
|
|
744
748
|
step = "connectors";
|
|
745
749
|
for (const ct of plan.templates) {
|
|
750
|
+
// An earlier switch-off kept this template's connector (its agents use it): the plugin
|
|
751
|
+
// takes it back instead of creating a second one, whose default slug the first holds
|
|
752
|
+
const existing = await this.liveTemplateConnector(orgId, itemId, ct.id);
|
|
753
|
+
if (existing !== undefined) {
|
|
754
|
+
await record({
|
|
755
|
+
kind: "connector",
|
|
756
|
+
ref: existing,
|
|
757
|
+
created: false,
|
|
758
|
+
skillVersion: null,
|
|
759
|
+
templateId: ct.id,
|
|
760
|
+
});
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
746
763
|
const ci = plan.connectors.get(ct.id);
|
|
764
|
+
// No input was needed (a live connector was taken back above, or the template was skipped
|
|
765
|
+
// at plan time): nothing to create
|
|
747
766
|
if (!ci)
|
|
748
|
-
|
|
767
|
+
continue;
|
|
749
768
|
if (actor === null)
|
|
750
769
|
throw systemNeedsInput(manifest.name);
|
|
751
770
|
const r = await this.connectors.create(orgId, actor, ci, opts.actorTokenId);
|
|
@@ -1657,6 +1676,23 @@ let PluginInstaller = class PluginInstaller {
|
|
|
1657
1676
|
templates: all.filter((t) => on.has(t.id) && !made.has(t.id)),
|
|
1658
1677
|
};
|
|
1659
1678
|
}
|
|
1679
|
+
/**
|
|
1680
|
+
* The org's live connector made from one of the plugin's connector templates, if any: an
|
|
1681
|
+
* uninstall keeps a connector its agents use, and the plugin's next switch-on reuses it.
|
|
1682
|
+
*/
|
|
1683
|
+
async liveTemplateConnector(orgId, itemId, templateId) {
|
|
1684
|
+
const row = await this.db
|
|
1685
|
+
.selectFrom("connectors as c")
|
|
1686
|
+
.innerJoin("platform_connector_templates as p", "p.id", "c.platform_template_id")
|
|
1687
|
+
.select("c.id")
|
|
1688
|
+
.where("c.org_id", "=", orgId)
|
|
1689
|
+
.where("c.deleted_at", "is", null)
|
|
1690
|
+
.where("p.catalog_item_id", "=", itemId)
|
|
1691
|
+
.where("p.template_id", "=", templateId)
|
|
1692
|
+
.orderBy("c.created_at")
|
|
1693
|
+
.executeTakeFirst();
|
|
1694
|
+
return row?.id;
|
|
1695
|
+
}
|
|
1660
1696
|
/**
|
|
1661
1697
|
* Creates the connectors an installed plugin is missing (ruling P2-10, `POST …/catalog/:itemId/
|
|
1662
1698
|
* connectors`): `input.connectors` names some of {@link missingConnectors}' templates with the
|
|
@@ -287,10 +287,6 @@ let ConnectorsService = class ConnectorsService {
|
|
|
287
287
|
checkCreateInput(actorAccountId, input) {
|
|
288
288
|
const slug = this.resolveSlug(input);
|
|
289
289
|
const endpoint = this.parseEndpoint(input.connector, input.endpoint);
|
|
290
|
-
// a defaulted slug skips plugin names itself (`freeName`)
|
|
291
|
-
if (!input.slugDefault && this.extensions.manifests().some((m) => m.name === slug)) {
|
|
292
|
-
throw fail("slug", `Slug "${slug}" is the name of an installed plugin; choose another`);
|
|
293
|
-
}
|
|
294
290
|
const auth = input.auth;
|
|
295
291
|
const credential = input.credential ?? undefined;
|
|
296
292
|
if (!isOAuth(auth)) {
|
package/package.json
CHANGED