@xopcai/xopc 0.0.395 → 0.0.397
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/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BRtkz-ZU.js → agent-avatar-dicebear-CIEGrioy.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-Dqg2NOn-.js → agent-defaults-settings-panel-CzKNVkRn.js} +1 -1
- package/dist/gateway/static/root/assets/agent-plugin-dialog-mpA9rwYd.js +1 -0
- package/dist/gateway/static/root/assets/{agents-0zgLsfVA.js → agents-7VMa7Rzo.js} +3 -3
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BZS8FvoL.js → app-management-settings-panel-DIJ0ii-n.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-RxXMAxiB.js → appearance-settings-BGnyHS-p.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-CvqDUvof.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-DEnHq3OR.js → archive-plugin-CR8FcRAa.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BwkugzB8.js → automations-page-BLInZo7N.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-K8aDhoYt.js → automations-workspace-DvTSHLt3.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-NWeXhh1k.js → binary-plugins-DW9pu205.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-D_bKN3BN.js → block-editor-ClgTc5v8.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automation-inputs-vtPkXfJ8.js → browser-automation-inputs-Bn7kDuUB.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-DBPbwOG8.js → browser-automations-page-CJGBhDnv.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-VBZDYoXD.js → browser-settings-page-tsi5W-cJ.js} +1 -1
- package/dist/gateway/static/root/assets/capabilities-page-CfbGk8q_.js +2 -0
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-C_OMsW_8.js → capabilities-settings-panel-BkO7QEyA.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-header-actions-CMJXWq8a.js → capability-header-actions-9ZG71-BO.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-C_TVCc1N.js → channels-D0CwJktG.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-9YRAokOl.js → chat-terminal-dock-x1W2_hwc.js} +1 -1
- package/dist/gateway/static/root/assets/{computer-settings-page-BPYAZ4ks.js → computer-settings-page-D_b_bFVz.js} +1 -1
- package/dist/gateway/static/root/assets/{connector-service-page-B81cEAEX.js → connector-service-page-Kf8kaNm_.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-C0NvAP2V.js → connectors-page-DlpfL2Rc.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BvKP4P3n.js → date-picker-d5kiPUG0.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-TvrNaf8y.js → dependency-picker-BcH76tQC.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-De-_QNSD.js → desktop-pet-B-925tPX.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-CRSRTIwT.js → desktop-pet-settings-3XJ4qR65.js} +1 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-12m5Z9-8.js +1 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-DOPXwYNR.js → directory-picker-path-field-B-qZCjGR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DzXvpUwj.js → extension-debug-page-BlQu1u6X.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-C0S1zNeP.js → extension-page-CXxM1M62.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-C3Z7bFjy.js → extension-settings-page-AF5nvsPP.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-Btc2wTQe.js → gateway-settings-ABXvW_yL.js} +1 -1
- package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-BFYBbh1P.js → highlighted-body-KQOG7T2V-Czdbbi0H.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-C5sLR47Q.js → home-page-LXGxGwVl.js} +1 -1
- package/dist/gateway/static/root/assets/{image-generation-api-Vqcyqnzb.js → image-generation-api-DPFPJ2ps.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-BJGHrzhX.js → imports-page-Bwyotfbt.js} +1 -1
- package/dist/gateway/static/root/assets/index-BKHxJaGD.css +1 -0
- package/dist/gateway/static/root/assets/{index-BNRLzxpH.js → index-Dsp_gNdl.js} +116 -116
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BQkQoPmm.js → keyboard-shortcuts-settings-C20gl-l7.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-DbxLz9Ms.js → local-app-workbench-page-o0M_OSjC.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-CaatwSrK.js → local-apps-page-DoWJCmOq.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-3Wo4Lmts.js → logs-page-BFTL93RX.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-BHlbM8IM.js → management-settings-C52cuMg1.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Cq1uLrd8.js → media-plugins-DLrTRF0a.js} +1 -1
- package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-CPYJsRUJ.js +1 -0
- package/dist/gateway/static/root/assets/{note-detail-panel-MjKND8HC.js → note-detail-panel-CNN41byS.js} +3 -3
- package/dist/gateway/static/root/assets/{notes-page-Cv040hVD.js → notes-page-BsfBp_8z.js} +1 -1
- package/dist/gateway/static/root/assets/{page-context-capture-button-Cp71nTq2.js → page-context-capture-button-YTVWZ02-.js} +1 -1
- package/dist/gateway/static/root/assets/{personal-page-CyEUWV2n.js → personal-page-N4KoCZYG.js} +1 -1
- package/dist/gateway/static/root/assets/plugin-details-page-DcrrzQI-.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-gzCecXc4.js → preview-open-alternatives-DzA__S54.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-CWFT7VuQ.js → product-open-page-DvlMKj0T.js} +1 -1
- package/dist/gateway/static/root/assets/{product-preview-content-Dh111Kca.js → product-preview-content-qdFyo4NG.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-CyhyZiTi.js → project-detail-page-y67s_fA8.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-QUdyJino.js → projects-page-D5iYgi0O.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-Cd8P0Dxs.js → remote-access-hub-DeFF7Re-.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-bTjVfYm5.js → runtime-tools-settings-panel-BCHLh-KQ.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-BGOzfVyj.js → schema-form-CJvaVHkx.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-BGMemJF6.js → sessions-page-DZ93_D5M.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-F1WX7vxq.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-Bqm1IKvR.js → settings-form-section-B3eODxNv.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-CniJVL-o.js → settings-page-Dg86uCnr.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-JPs4-QRw.js → setup-status-panel-ruFzAArp.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-BnDGFgBR.js → share-preview-page-DCy1f25V.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-Cgp5BuLt.js → shares-settings-DeIVZvpJ.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-api-CFdrz6tl.js → skill-api-RisyPAMA.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-reload-api-Cy5jVfms.js → skill-reload-api-Dwkm1Fof.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-CxaA3P5E.js → skills-page-UiTLsrFc.js} +1 -1
- package/dist/gateway/static/root/assets/{style-C_MAnir7.js → style-CwMX73G7.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-BjnIlilP.js → system-settings-panel-Cma37Pfm.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-Bg79rPnF.js → task-detail-page-BKOF_kxS.js} +1 -1
- package/dist/gateway/static/root/assets/{tracing-settings-page-BCI0tUbe.js → tracing-settings-page-DC-kLysq.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-0knnta9z.js → tunnel-api-BgdhbR1L.js} +1 -1
- package/dist/gateway/static/root/assets/{usage-page-D5aT1eie.js → usage-page-BSlFg3Xj.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-Ds_mbAfe.js → use-autosave-iKvZ1pvC.js} +1 -1
- package/dist/gateway/static/root/assets/{user-model-page-D7L0-pDt.js → user-model-page-D4GB8QsM.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-CPoGdarN.js → voice-api-key-field-CESbtuwM.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CWNguy2Z.js → work-discovery-overlay-dtPpmYyh.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BcDMFfkT.js → workflow-run-setup-panel-DmFn3E_B.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-BwZB-s4N.js → workflows-page-DEtaRuxH.js} +1 -1
- package/dist/gateway/static/root/assets/{xopc-cloud-account-card-DlKr98VO.js → xopc-cloud-account-card-DTZnabfg.js} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/embedded/codemode-extension.d.ts +1 -0
- package/dist/src/agent/embedded/codemode-extension.js +6 -1
- package/dist/src/agent/embedded/run-for-session.js +1 -1
- package/dist/src/agent/embedded/run-turn.js +34 -2
- package/dist/src/agent/embedded/session-runner.js +1 -1
- package/dist/src/agent/mcp/config.d.ts +2 -0
- package/dist/src/agent/mcp/config.js +2 -2
- package/dist/src/agent/mcp/connection-setup.js +13 -1
- package/dist/src/agent/mcp/effective-server.d.ts +3 -0
- package/dist/src/agent/mcp/effective-server.js +27 -0
- package/dist/src/agent/mcp/native-mcp.d.ts +1 -1
- package/dist/src/agent/mcp/native-mcp.js +13 -4
- package/dist/src/agent/mcp/tool-catalog.js +2 -1
- package/dist/src/agent/skills/index.d.ts +1 -0
- package/dist/src/agent/skills/index.js +6 -2
- package/dist/src/agent/skills/skill-manager.d.ts +1 -0
- package/dist/src/agent/skills/skill-manager.js +6 -1
- package/dist/src/agent/skills/skill-sources.d.ts +1 -0
- package/dist/src/agent/skills/skill-sources.js +4 -3
- package/dist/src/agent/skills/types.d.ts +1 -0
- package/dist/src/agent/workspace-runtime/registry.js +6 -2
- package/dist/src/browser/native-messaging-host.js +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +2 -2
- package/dist/src/channels/index.js +1 -1
- package/dist/src/channels/manager.js +1 -1
- package/dist/src/cli/commands/channels.js +1 -1
- package/dist/src/cli/commands/connectors.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/extension-agent-plugin.js +92 -7
- package/dist/src/cli/commands/extension-marketplace.js +2 -2
- package/dist/src/cli/commands/extension.js +1 -1
- package/dist/src/cli/commands/mcp.js +6 -4
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard/model.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/extensions/agent-plugins/auth.d.ts +7 -1
- package/dist/src/extensions/agent-plugins/auth.js +53 -12
- package/dist/src/extensions/agent-plugins/branding.d.ts +6 -0
- package/dist/src/extensions/agent-plugins/branding.js +44 -0
- package/dist/src/extensions/agent-plugins/cli-authorization.d.ts +22 -0
- package/dist/src/extensions/agent-plugins/cli-authorization.js +198 -0
- package/dist/src/extensions/agent-plugins/connection-reuse.d.ts +10 -0
- package/dist/src/extensions/agent-plugins/connection-reuse.js +23 -0
- package/dist/src/extensions/agent-plugins/credentials.js +24 -1
- package/dist/src/extensions/agent-plugins/formats.d.ts +27 -0
- package/dist/src/extensions/agent-plugins/formats.js +208 -0
- package/dist/src/extensions/agent-plugins/inventory.d.ts +142 -2
- package/dist/src/extensions/agent-plugins/inventory.js +39 -5
- package/dist/src/extensions/agent-plugins/mcp-adapter.d.ts +2 -1
- package/dist/src/extensions/agent-plugins/mcp-adapter.js +42 -8
- package/dist/src/extensions/agent-plugins/mcp-format.d.ts +2 -0
- package/dist/src/extensions/agent-plugins/mcp-format.js +82 -0
- package/dist/src/extensions/agent-plugins/resources.d.ts +14 -0
- package/dist/src/extensions/agent-plugins/resources.js +112 -0
- package/dist/src/extensions/agent-plugins/setup-contract.d.ts +54 -0
- package/dist/src/extensions/agent-plugins/setup-contract.js +58 -0
- package/dist/src/extensions/agent-plugins/setup.d.ts +119 -0
- package/dist/src/extensions/agent-plugins/setup.js +491 -0
- package/dist/src/extensions/agent-plugins/source-catalog.d.ts +21 -0
- package/dist/src/extensions/agent-plugins/source-catalog.js +175 -0
- package/dist/src/extensions/agent-plugins/sources.d.ts +1 -1
- package/dist/src/extensions/agent-plugins/sources.js +12 -3
- package/dist/src/extensions/agent-plugins/store.d.ts +33 -2
- package/dist/src/extensions/agent-plugins/store.js +175 -25
- package/dist/src/extensions/agent-plugins/user-config.d.ts +5 -0
- package/dist/src/extensions/agent-plugins/user-config.js +49 -0
- package/dist/src/extensions/agent-plugins/validation.d.ts +26 -1
- package/dist/src/extensions/agent-plugins/validation.js +142 -27
- package/dist/src/extensions/sdk/index.js +1 -1
- package/dist/src/gateway/hono/app.js +1 -1
- package/dist/src/gateway/hono/routes/agent-plugins.js +120 -9
- package/dist/src/gateway/hono/routes/browser-install.js +1 -1
- package/dist/src/gateway/hono/routes/composer-history.js +22 -4
- package/dist/src/gateway/hono/routes/mcp.js +6 -4
- package/dist/src/gateway/hono/routes/provider-setup.js +7 -0
- package/dist/src/gateway/service.js +11 -9
- package/dist/src/gateway/session-context-summary.js +1 -1
- package/dist/src/gateway/xopc-cloud-capability-setup.d.ts +4 -0
- package/dist/src/gateway/xopc-cloud-capability-setup.js +90 -26
- package/dist/src/home-intelligence/host.js +2 -2
- package/dist/src/providers/setup/engine.js +12 -10
- package/dist/src/providers/setup/voice.js +24 -6
- package/dist/src/storage/sqlite/composer-input-history-repository.d.ts +4 -3
- package/dist/src/storage/sqlite/composer-input-history-repository.js +10 -8
- package/dist/src/storage/sqlite/device-pairing-approval.js +1 -1
- package/dist/src/storage/sqlite/migrations/257_session_composer_history.sql +11 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +2 -2
- package/dist/src/tui/backends/embedded-backend.js +4 -4
- package/dist/src/tui/backends/gateway-realtime-backend.d.ts +2 -2
- package/dist/src/tui/backends/gateway-realtime-backend.js +7 -4
- package/dist/src/tui/composer-history.d.ts +14 -0
- package/dist/src/tui/composer-history.js +85 -0
- package/dist/src/tui/tui-backend.d.ts +4 -3
- package/dist/src/tui/tui.js +19 -46
- package/package.json +12 -4
- package/dist/gateway/static/root/assets/agent-plugin-dialog-CKK95Jmr.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-mGU9WLjP.js +0 -1
- package/dist/gateway/static/root/assets/capabilities-page-CQsGp9Sx.js +0 -2
- package/dist/gateway/static/root/assets/device-pairing-wizard-DnyJ8Bja.js +0 -1
- package/dist/gateway/static/root/assets/index-zIgp-ZTu.css +0 -1
- package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-XhlIBp5t.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BiySFw1N.js +0 -1
|
@@ -14,4 +14,4 @@ export interface AgentPluginSourceProvenance {
|
|
|
14
14
|
export declare function isAgentPluginArchive(buffer: Buffer): boolean;
|
|
15
15
|
export declare function withAgentPluginArchive<T>(buffer: Buffer, fn: (local: string) => T): T;
|
|
16
16
|
/** Resolve remote artifacts only for explicit inspect/install requests, never during discovery. */
|
|
17
|
-
export declare function withAgentPluginSource<T>(source: string, config: Config | undefined, fn: (local: string, provenance?: AgentPluginSourceProvenance) => T): Promise<T>;
|
|
17
|
+
export declare function withAgentPluginSource<T>(source: string, config: Config | undefined, fn: (local: string, provenance?: AgentPluginSourceProvenance, resolvedCommit?: string, importManifest?: Record<string, unknown>) => T, depth?: number): Promise<T>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { createPluginSourceFetch } from "./source-http-fetch.js";
|
|
2
|
+
import { PLUGIN_MANIFEST_PATHS } from "./formats.js";
|
|
3
|
+
import { PluginSourceRedirect, isGitPluginSource, withCatalogSource } from "./source-catalog.js";
|
|
2
4
|
import { tmpdir } from "node:os";
|
|
3
5
|
import { join } from "node:path";
|
|
4
6
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -14,11 +16,11 @@ function isAgentPluginArchive(buffer) {
|
|
|
14
16
|
return Boolean(JSON.parse(entry.getData().toString("utf8"))?.xopc?.extension);
|
|
15
17
|
};
|
|
16
18
|
if (paths.includes("xopc.extension.json")) return false;
|
|
17
|
-
if (paths.includes(
|
|
19
|
+
if (PLUGIN_MANIFEST_PATHS.some((path) => paths.includes(path))) return !nativeMetadata("package.json");
|
|
18
20
|
const first = new Set(paths.map((path) => path.split("/")[0]));
|
|
19
21
|
if (first.size !== 1) return false;
|
|
20
22
|
const root = [...first][0];
|
|
21
|
-
return paths.includes(`${root}
|
|
23
|
+
return PLUGIN_MANIFEST_PATHS.some((path) => paths.includes(`${root}/${path}`)) && !paths.includes(`${root}/xopc.extension.json`) && !nativeMetadata(`${root}/package.json`);
|
|
22
24
|
}
|
|
23
25
|
function withAgentPluginArchive(buffer, fn) {
|
|
24
26
|
const dir = mkdtempSync(join(tmpdir(), "xopc-plugin-download-"));
|
|
@@ -34,7 +36,14 @@ function withAgentPluginArchive(buffer, fn) {
|
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
/** Resolve remote artifacts only for explicit inspect/install requests, never during discovery. */
|
|
37
|
-
async function withAgentPluginSource(source, config, fn) {
|
|
39
|
+
async function withAgentPluginSource(source, config, fn, depth = 0) {
|
|
40
|
+
if (depth > 4) throw new Error("Marketplace source nesting exceeds limits");
|
|
41
|
+
if (isGitPluginSource(source) || !source.startsWith("https://") && !source.startsWith("store:") && (!source.toLowerCase().endsWith(".zip") || source.includes("#"))) try {
|
|
42
|
+
return await withCatalogSource(source, (local, metadata) => fn(local, void 0, metadata.commit, metadata.importManifest));
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error instanceof PluginSourceRedirect) return withAgentPluginSource(error.source, config, fn, depth + 1);
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
38
47
|
if (!source.startsWith("https://") && !source.startsWith("store:")) return fn(source);
|
|
39
48
|
let buffer;
|
|
40
49
|
let provenance;
|
|
@@ -31,6 +31,14 @@ declare const receiptSchema: z.ZodObject<{
|
|
|
31
31
|
"local-exec": "local-exec";
|
|
32
32
|
}>>;
|
|
33
33
|
}, z.core.$strict>>;
|
|
34
|
+
adapterVersion: z.ZodOptional<z.ZodString>;
|
|
35
|
+
credentialScope: z.ZodOptional<z.ZodLiteral<"revision">>;
|
|
36
|
+
workspacePaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
37
|
+
resourceHashes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
38
|
+
oauthServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
39
|
+
importManifest: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
40
|
+
resolvedCommit: z.ZodOptional<z.ZodString>;
|
|
41
|
+
declaredName: z.ZodOptional<z.ZodString>;
|
|
34
42
|
previous: z.ZodOptional<z.ZodObject<{
|
|
35
43
|
id: z.ZodString;
|
|
36
44
|
revision: z.ZodString;
|
|
@@ -61,6 +69,14 @@ declare const receiptSchema: z.ZodObject<{
|
|
|
61
69
|
"local-exec": "local-exec";
|
|
62
70
|
}>>;
|
|
63
71
|
}, z.core.$strict>>;
|
|
72
|
+
adapterVersion: z.ZodOptional<z.ZodString>;
|
|
73
|
+
credentialScope: z.ZodOptional<z.ZodLiteral<"revision">>;
|
|
74
|
+
workspacePaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
75
|
+
resourceHashes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
76
|
+
oauthServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
77
|
+
importManifest: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
78
|
+
resolvedCommit: z.ZodOptional<z.ZodString>;
|
|
79
|
+
declaredName: z.ZodOptional<z.ZodString>;
|
|
64
80
|
}, z.core.$strip>>;
|
|
65
81
|
}, z.core.$strip>;
|
|
66
82
|
export type PluginReceipt = z.infer<typeof receiptSchema>;
|
|
@@ -71,6 +87,7 @@ export interface InstalledAgentPlugin extends PluginInspection {
|
|
|
71
87
|
readiness: 'ready' | 'setup_required' | 'degraded' | 'blocked';
|
|
72
88
|
}
|
|
73
89
|
export interface PluginInstallPlan extends PluginInspection {
|
|
90
|
+
installId: string;
|
|
74
91
|
integrity: string;
|
|
75
92
|
reviewHash: string;
|
|
76
93
|
addedCapabilities: string[];
|
|
@@ -88,9 +105,11 @@ export declare class AgentPluginStore {
|
|
|
88
105
|
private write;
|
|
89
106
|
private mutate;
|
|
90
107
|
get(id: string): InstalledAgentPlugin | undefined;
|
|
108
|
+
private fromReceipt;
|
|
91
109
|
list(): InstalledAgentPlugin[];
|
|
92
|
-
active(): InstalledAgentPlugin[];
|
|
93
|
-
|
|
110
|
+
active(_agentId?: string, workspaceDir?: string): InstalledAgentPlugin[];
|
|
111
|
+
private setupReady;
|
|
112
|
+
inspect(source: string, sourceLabel?: string, importManifest?: Record<string, unknown>): PluginInstallPlan;
|
|
94
113
|
private plan;
|
|
95
114
|
install(source: string, options?: {
|
|
96
115
|
reviewHash?: string;
|
|
@@ -98,8 +117,20 @@ export declare class AgentPluginStore {
|
|
|
98
117
|
expectedId?: string;
|
|
99
118
|
sourceLabel?: string;
|
|
100
119
|
provenance?: AgentPluginSourceProvenance;
|
|
120
|
+
stage?: boolean;
|
|
121
|
+
resolvedCommit?: string;
|
|
122
|
+
importManifest?: Record<string, unknown>;
|
|
101
123
|
}): InstalledAgentPlugin;
|
|
124
|
+
history(id: string): InstalledAgentPlugin[];
|
|
125
|
+
/** Publish synchronous resource changes while the package lifecycle lock is held. */
|
|
126
|
+
withRevision<T>(id: string, revision: string, fn: () => T): T;
|
|
127
|
+
private pendingPath;
|
|
128
|
+
pendingReceipt(id: string): PluginReceipt | undefined;
|
|
129
|
+
pending(id: string): InstalledAgentPlugin | undefined;
|
|
130
|
+
commitPending(id: string): void;
|
|
131
|
+
discardPending(id: string): void;
|
|
102
132
|
setEnabled(id: string, enabled: boolean): InstalledAgentPlugin;
|
|
133
|
+
setWorkspaceScope(id: string, workspacePaths?: string[] | null): InstalledAgentPlugin;
|
|
103
134
|
rollback(id: string): InstalledAgentPlugin;
|
|
104
135
|
remove(id: string, removeData?: boolean): void;
|
|
105
136
|
private withSource;
|
|
@@ -3,10 +3,13 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
3
3
|
import { init_logger } from "../../utils/logger.js";
|
|
4
4
|
import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
|
|
5
5
|
import { computeExtensionDirectoryIntegrity } from "../lockfile.js";
|
|
6
|
+
import { prunePluginResourceCache } from "./resources.js";
|
|
7
|
+
import { PLUGIN_MANIFEST_PATHS } from "./formats.js";
|
|
6
8
|
import { containedPath, inspectAgentPlugin, pluginName } from "./validation.js";
|
|
9
|
+
import { pluginSourceKey } from "./source-catalog.js";
|
|
7
10
|
import { tmpdir } from "node:os";
|
|
8
11
|
import { dirname, join, resolve } from "node:path";
|
|
9
|
-
import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
10
13
|
import { createHash, randomUUID } from "node:crypto";
|
|
11
14
|
import { z } from "zod";
|
|
12
15
|
import AdmZip from "adm-zip";
|
|
@@ -39,7 +42,15 @@ const receiptFields = z.object({
|
|
|
39
42
|
enabled: z.boolean(),
|
|
40
43
|
integrity: z.string(),
|
|
41
44
|
capabilities: z.array(z.string()),
|
|
42
|
-
provenance: provenanceSchema.optional()
|
|
45
|
+
provenance: provenanceSchema.optional(),
|
|
46
|
+
adapterVersion: z.string().min(1).max(64).optional(),
|
|
47
|
+
credentialScope: z.literal("revision").optional(),
|
|
48
|
+
workspacePaths: z.array(z.string()).max(100).optional(),
|
|
49
|
+
resourceHashes: z.array(z.string()).optional(),
|
|
50
|
+
oauthServers: z.record(z.string(), z.string()).optional(),
|
|
51
|
+
importManifest: z.record(z.string(), z.unknown()).optional(),
|
|
52
|
+
resolvedCommit: z.string().regex(/^[a-f0-9]{40,64}$/).optional(),
|
|
53
|
+
declaredName: pluginName.optional()
|
|
43
54
|
});
|
|
44
55
|
const receiptSchema = receiptFields.extend({ previous: receiptFields.optional() });
|
|
45
56
|
const log = createLogger("AgentPlugins");
|
|
@@ -54,7 +65,8 @@ var AgentPluginStore = class {
|
|
|
54
65
|
if (!existsSync(this.receiptsDir())) return "";
|
|
55
66
|
return readdirSync(this.receiptsDir()).filter((name) => name.endsWith(".json")).sort().map((name) => {
|
|
56
67
|
try {
|
|
57
|
-
|
|
68
|
+
const setupPath = join(this.stateDir, "plugin-setup", name);
|
|
69
|
+
return createHash("sha256").update(readFileSync(join(this.receiptsDir(), name))).update(existsSync(setupPath) ? readFileSync(setupPath) : "").digest("hex");
|
|
58
70
|
} catch {
|
|
59
71
|
return "";
|
|
60
72
|
}
|
|
@@ -93,17 +105,29 @@ var AgentPluginStore = class {
|
|
|
93
105
|
}
|
|
94
106
|
get(id) {
|
|
95
107
|
const receipt = this.receipt(id);
|
|
96
|
-
|
|
108
|
+
return receipt ? this.fromReceipt(receipt) : void 0;
|
|
109
|
+
}
|
|
110
|
+
fromReceipt(receipt) {
|
|
111
|
+
const id = receipt.id;
|
|
97
112
|
const rootDir = this.revisionDir(id, receipt.revision);
|
|
98
113
|
try {
|
|
99
114
|
validatePackageTree(rootDir);
|
|
100
|
-
const inspection = inspectAgentPlugin(rootDir, this.dataDir(id));
|
|
115
|
+
const inspection = inspectAgentPlugin(rootDir, this.dataDir(id), receipt.importManifest);
|
|
101
116
|
const valid = computeExtensionDirectoryIntegrity(rootDir) === receipt.integrity;
|
|
102
117
|
if (!valid) inspection.diagnostics.push({
|
|
103
118
|
component: "package",
|
|
104
119
|
message: "Installed files differ from the reviewed package"
|
|
105
120
|
});
|
|
106
|
-
const
|
|
121
|
+
const previouslyReviewed = new Set(receipt.capabilities);
|
|
122
|
+
const adapterChanged = receipt.adapterVersion !== void 0 && receipt.adapterVersion !== inspection.layout?.adapterVersion;
|
|
123
|
+
const capabilityChanged = inspection.capabilities.some((capability) => !previouslyReviewed.has(capability) && !(receipt.adapterVersion === void 0 && previouslyReviewed.has(capability.replace(/:\{\}:\{\}$/, ""))));
|
|
124
|
+
if (adapterChanged || capabilityChanged) inspection.diagnostics.push({
|
|
125
|
+
component: "review",
|
|
126
|
+
message: "Adapter interpretation changed capabilities. Inspect and review this package again."
|
|
127
|
+
});
|
|
128
|
+
const setupPath = join(this.stateDir, "plugin-setup", `${id}.json`);
|
|
129
|
+
const setup = existsSync(setupPath) ? JSON.parse(readFileSync(setupPath, "utf8")) : void 0;
|
|
130
|
+
const readiness = !valid || adapterChanged || capabilityChanged || inspection.layout?.compatibility.some((item) => item.component === "hooks" || item.component === "authorizations" && item.support === "invalid") ? "blocked" : setup?.packageRevision === receipt.revision && setup.state !== "completed" && !setup.installed ? "setup_required" : inspection.diagnostics.length || setup?.packageRevision === receipt.revision && (setup.partial || setup.installed && (setup.missingConfig?.length || setup.connections?.some((value) => value.state !== "connected") || setup.authorizations?.some((value) => value.state !== "connected"))) ? "degraded" : "ready";
|
|
107
131
|
return {
|
|
108
132
|
...inspection,
|
|
109
133
|
id,
|
|
@@ -149,23 +173,43 @@ var AgentPluginStore = class {
|
|
|
149
173
|
}
|
|
150
174
|
});
|
|
151
175
|
}
|
|
152
|
-
active() {
|
|
176
|
+
active(_agentId, workspaceDir) {
|
|
153
177
|
if (["1", "true"].includes(process.env.XOPC_SKIP_EXTENSIONS ?? "")) return [];
|
|
154
|
-
return this.list().filter((p) => p.receipt.enabled && p.readiness !== "blocked");
|
|
178
|
+
return this.list().filter((p) => p.receipt.enabled && p.readiness !== "blocked" && (p.receipt.workspacePaths === void 0 || workspaceDir !== void 0 && p.receipt.workspacePaths.includes(existsSync(workspaceDir) ? realpathSync(workspaceDir) : resolve(workspaceDir))) && this.setupReady(p));
|
|
179
|
+
}
|
|
180
|
+
setupReady(plugin) {
|
|
181
|
+
const path = join(this.stateDir, "plugin-setup", `${plugin.id}.json`);
|
|
182
|
+
if (!existsSync(path)) return true;
|
|
183
|
+
try {
|
|
184
|
+
const job = JSON.parse(readFileSync(path, "utf8"));
|
|
185
|
+
return job.packageRevision !== plugin.receipt.revision || job.state === "completed" || job.installed === true;
|
|
186
|
+
} catch {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
155
189
|
}
|
|
156
|
-
inspect(source) {
|
|
157
|
-
return this.withSource(source, (root) => this.plan(root));
|
|
190
|
+
inspect(source, sourceLabel = source, importManifest) {
|
|
191
|
+
return this.withSource(source, (root) => this.plan(root, sourceLabel, importManifest));
|
|
158
192
|
}
|
|
159
|
-
plan(root) {
|
|
193
|
+
plan(root, sourceLabel, importManifest) {
|
|
160
194
|
validatePackageTree(root);
|
|
161
|
-
const initial = inspectAgentPlugin(root);
|
|
162
|
-
const
|
|
195
|
+
const initial = inspectAgentPlugin(root, void 0, importManifest);
|
|
196
|
+
const existing = this.list().find((p) => p.receipt.source === sourceLabel && p.manifest.name === initial.manifest.name);
|
|
197
|
+
const scoped = initial.layout?.dialect !== "portable" || /^(?:git\+|github:|https:\/\/github\.com\/)/.test(sourceLabel) || sourceLabel.includes("#plugin=");
|
|
198
|
+
const installId = existing?.id ?? (scoped ? `${initial.manifest.name.slice(0, 48).replace(/[.-]+$/, "")}-${pluginSourceKey(sourceLabel)}` : initial.manifest.name);
|
|
199
|
+
const inspection = inspectAgentPlugin(root, this.dataDir(installId), importManifest);
|
|
163
200
|
const integrity = computeExtensionDirectoryIntegrity(root);
|
|
164
|
-
const current = this.receipt(
|
|
201
|
+
const current = this.receipt(installId);
|
|
165
202
|
const addedCapabilities = inspection.capabilities.filter((c) => !current?.capabilities.includes(c));
|
|
166
|
-
const reviewHash = createHash("sha256").update(JSON.stringify([
|
|
203
|
+
const reviewHash = createHash("sha256").update(JSON.stringify([
|
|
204
|
+
"plugin-adapter-v1",
|
|
205
|
+
integrity,
|
|
206
|
+
inspection.capabilities,
|
|
207
|
+
installId,
|
|
208
|
+
importManifest
|
|
209
|
+
])).digest("hex");
|
|
167
210
|
return {
|
|
168
211
|
...inspection,
|
|
212
|
+
installId,
|
|
169
213
|
integrity,
|
|
170
214
|
reviewHash,
|
|
171
215
|
addedCapabilities,
|
|
@@ -174,12 +218,15 @@ var AgentPluginStore = class {
|
|
|
174
218
|
}
|
|
175
219
|
install(source, options = {}) {
|
|
176
220
|
return this.mutate(() => this.withSource(source, (root) => {
|
|
177
|
-
const plan = this.plan(root);
|
|
178
|
-
const id = plan.
|
|
179
|
-
|
|
221
|
+
const plan = this.plan(root, options.sourceLabel ?? source, options.importManifest);
|
|
222
|
+
const id = options.expectedId ?? plan.installId;
|
|
223
|
+
const expected = this.receipt(id);
|
|
224
|
+
if (expected && (expected.declaredName ?? expected.id) !== plan.manifest.name) throw new Error("Update package identity does not match installed plugin");
|
|
225
|
+
if (options.expectedId && !expected) throw new Error("Update package identity does not match installed plugin");
|
|
180
226
|
const current = this.receipt(id);
|
|
181
227
|
if (current && !options.replace) throw new Error("Plugin already installed; use update");
|
|
182
|
-
|
|
228
|
+
const changedExecutable = current && current.integrity !== plan.integrity && (plan.capabilities.some((capability) => capability.startsWith("runtime.")) || current.capabilities.some((capability) => capability.startsWith("runtime.")));
|
|
229
|
+
if ((!current || plan.addedCapabilities.length > 0 || changedExecutable) && options.reviewHash !== plan.reviewHash) throw new Error("Package capability review is required");
|
|
183
230
|
if (options.reviewHash && options.reviewHash !== plan.reviewHash) throw new Error("Package changed after review; inspect again");
|
|
184
231
|
validatePackageTree(root);
|
|
185
232
|
const revision = randomUUID();
|
|
@@ -192,35 +239,119 @@ var AgentPluginStore = class {
|
|
|
192
239
|
verbatimSymlinks: true
|
|
193
240
|
});
|
|
194
241
|
validatePackageTree(target);
|
|
195
|
-
const installed = inspectAgentPlugin(target, this.dataDir(id));
|
|
242
|
+
const installed = inspectAgentPlugin(target, this.dataDir(id), options.importManifest);
|
|
196
243
|
const integrity = computeExtensionDirectoryIntegrity(target);
|
|
197
244
|
if (integrity !== plan.integrity) throw new Error("Package changed during installation");
|
|
198
245
|
const label = options.sourceLabel ?? source;
|
|
199
|
-
|
|
246
|
+
const receipt = {
|
|
200
247
|
id,
|
|
201
248
|
revision,
|
|
202
|
-
source: /^(https:\/\/|store:)/.test(label) ? label : resolve(label),
|
|
249
|
+
source: /^(https:\/\/|store:|git\+|github:)/.test(label) ? label : resolve(label),
|
|
203
250
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
251
|
+
declaredName: installed.manifest.name,
|
|
252
|
+
adapterVersion: installed.layout?.adapterVersion,
|
|
253
|
+
credentialScope: "revision",
|
|
254
|
+
oauthServers: Object.fromEntries(Object.entries(installed.servers).filter(([, server]) => server.type !== "stdio").map(([name, server]) => [name, server.type !== "stdio" ? server.url : ""])),
|
|
255
|
+
importManifest: options.importManifest,
|
|
256
|
+
resolvedCommit: options.resolvedCommit,
|
|
257
|
+
workspacePaths: current?.workspacePaths,
|
|
258
|
+
resourceHashes: plan.resources?.map((resource) => resource.sha256),
|
|
204
259
|
enabled: current?.enabled ?? false,
|
|
205
260
|
integrity,
|
|
206
261
|
capabilities: installed.capabilities,
|
|
207
262
|
...options.provenance ? { provenance: provenanceSchema.parse(options.provenance) } : {},
|
|
208
263
|
previous: current ? receiptFields.parse(current) : void 0
|
|
209
|
-
}
|
|
264
|
+
};
|
|
265
|
+
writeTextAtomicSync(join(this.stateDir, "plugin-revisions", id, `${revision}.json`), JSON.stringify(receiptFields.parse(receipt)));
|
|
266
|
+
if (options.stage && current) writeTextAtomicSync(this.pendingPath(id), JSON.stringify(receipt));
|
|
267
|
+
else this.write(receipt);
|
|
210
268
|
} catch (error) {
|
|
211
269
|
rmSync(target, {
|
|
212
270
|
recursive: true,
|
|
213
271
|
force: true
|
|
214
272
|
});
|
|
273
|
+
rmSync(join(this.stateDir, "plugin-revisions", id, `${revision}.json`), { force: true });
|
|
215
274
|
throw error;
|
|
216
275
|
}
|
|
217
|
-
return this.get(id);
|
|
276
|
+
return options.stage && current ? this.pending(id) : this.get(id);
|
|
218
277
|
}));
|
|
219
278
|
}
|
|
279
|
+
history(id) {
|
|
280
|
+
const current = this.receipt(id), pending = this.pending(id);
|
|
281
|
+
const receipts = /* @__PURE__ */ new Map();
|
|
282
|
+
for (const receipt of [
|
|
283
|
+
current,
|
|
284
|
+
current?.previous,
|
|
285
|
+
pending?.receipt
|
|
286
|
+
]) if (receipt) receipts.set(receipt.revision, receipt);
|
|
287
|
+
const directory = join(this.stateDir, "plugin-revisions", pluginName.parse(id));
|
|
288
|
+
if (existsSync(directory)) for (const name of readdirSync(directory)) {
|
|
289
|
+
if (!name.endsWith(".json")) continue;
|
|
290
|
+
const receipt = receiptFields.parse(JSON.parse(readFileSync(join(directory, name), "utf8")));
|
|
291
|
+
if (receipt.id !== id) throw new Error("Plugin history identity mismatch");
|
|
292
|
+
receipts.set(receipt.revision, receipt);
|
|
293
|
+
}
|
|
294
|
+
return [...receipts.values()].map((receipt) => this.fromReceipt(receipt));
|
|
295
|
+
}
|
|
296
|
+
/** Publish synchronous resource changes while the package lifecycle lock is held. */
|
|
297
|
+
withRevision(id, revision, fn) {
|
|
298
|
+
return this.mutate(() => {
|
|
299
|
+
if (this.receipt(id)?.revision !== revision && this.pending(id)?.receipt.revision !== revision) throw new Error("Plugin revision changed or was removed");
|
|
300
|
+
return fn();
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
pendingPath(id) {
|
|
304
|
+
return join(this.stateDir, "plugin-pending", `${pluginName.parse(id)}.json`);
|
|
305
|
+
}
|
|
306
|
+
pendingReceipt(id) {
|
|
307
|
+
const path = this.pendingPath(id);
|
|
308
|
+
if (!existsSync(path)) return void 0;
|
|
309
|
+
const receipt = receiptSchema.parse(JSON.parse(readFileSync(path, "utf8")));
|
|
310
|
+
if (receipt.id !== id) throw new Error("Staged plugin identity mismatch");
|
|
311
|
+
return receipt;
|
|
312
|
+
}
|
|
313
|
+
pending(id) {
|
|
314
|
+
const receipt = this.pendingReceipt(id);
|
|
315
|
+
return receipt ? this.fromReceipt(receipt) : void 0;
|
|
316
|
+
}
|
|
317
|
+
commitPending(id) {
|
|
318
|
+
this.mutate(() => {
|
|
319
|
+
const pending = this.pending(id);
|
|
320
|
+
if (!pending) return;
|
|
321
|
+
if (pending.readiness === "blocked" || pending.receipt.previous?.revision !== this.receipt(id)?.revision) throw new Error("Staged update changed; inspect again");
|
|
322
|
+
this.write(pending.receipt);
|
|
323
|
+
rmSync(this.pendingPath(id), { force: true });
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
discardPending(id) {
|
|
327
|
+
this.mutate(() => {
|
|
328
|
+
const pending = this.pending(id);
|
|
329
|
+
if (!pending) return;
|
|
330
|
+
rmSync(this.pendingPath(id), { force: true });
|
|
331
|
+
rmSync(pending.rootDir, {
|
|
332
|
+
recursive: true,
|
|
333
|
+
force: true
|
|
334
|
+
});
|
|
335
|
+
try {
|
|
336
|
+
const data = this.dataDir(id);
|
|
337
|
+
rmSync(containedPath(data, join(data, "resources", pending.receipt.revision)), {
|
|
338
|
+
recursive: true,
|
|
339
|
+
force: true
|
|
340
|
+
});
|
|
341
|
+
} catch (err) {
|
|
342
|
+
log.warn({
|
|
343
|
+
err,
|
|
344
|
+
pluginId: id
|
|
345
|
+
}, "Could not clean staged plugin resources");
|
|
346
|
+
}
|
|
347
|
+
prunePluginResourceCache(this);
|
|
348
|
+
});
|
|
349
|
+
}
|
|
220
350
|
setEnabled(id, enabled) {
|
|
221
351
|
return this.mutate(() => {
|
|
222
352
|
const plugin = this.get(id);
|
|
223
353
|
if (!plugin) throw new Error("Plugin not installed");
|
|
354
|
+
if (enabled && plugin.layout?.compatibility.some((item) => item.component === "hooks")) throw new Error("This plugin requires unsupported lifecycle hooks and cannot be enabled by this compatibility version");
|
|
224
355
|
if (enabled && plugin.readiness === "blocked") throw new Error("Repair the plugin before enabling it");
|
|
225
356
|
this.write({
|
|
226
357
|
...plugin.receipt,
|
|
@@ -229,6 +360,17 @@ var AgentPluginStore = class {
|
|
|
229
360
|
return this.get(id);
|
|
230
361
|
});
|
|
231
362
|
}
|
|
363
|
+
setWorkspaceScope(id, workspacePaths) {
|
|
364
|
+
return this.mutate(() => {
|
|
365
|
+
const plugin = this.get(id);
|
|
366
|
+
if (!plugin) throw new Error("Plugin not installed");
|
|
367
|
+
this.write({
|
|
368
|
+
...plugin.receipt,
|
|
369
|
+
workspacePaths: workspacePaths === void 0 ? plugin.receipt.workspacePaths : workspacePaths === null ? void 0 : [...new Set(workspacePaths.map((path) => existsSync(path) ? realpathSync(path) : resolve(path)))]
|
|
370
|
+
});
|
|
371
|
+
return this.get(id);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
232
374
|
rollback(id) {
|
|
233
375
|
return this.mutate(() => {
|
|
234
376
|
const receipt = this.receipt(id);
|
|
@@ -238,6 +380,7 @@ var AgentPluginStore = class {
|
|
|
238
380
|
this.write({
|
|
239
381
|
...previous,
|
|
240
382
|
enabled: receipt.enabled,
|
|
383
|
+
workspacePaths: receipt.workspacePaths,
|
|
241
384
|
previous: receiptFields.parse(receipt)
|
|
242
385
|
});
|
|
243
386
|
return this.get(id);
|
|
@@ -251,14 +394,21 @@ var AgentPluginStore = class {
|
|
|
251
394
|
recursive: true,
|
|
252
395
|
force: true
|
|
253
396
|
});
|
|
397
|
+
rmSync(join(this.stateDir, "plugin-revisions", id), {
|
|
398
|
+
recursive: true,
|
|
399
|
+
force: true
|
|
400
|
+
});
|
|
254
401
|
rmSync(join(this.stateDir, "plugin-health", id), {
|
|
255
402
|
recursive: true,
|
|
256
403
|
force: true
|
|
257
404
|
});
|
|
405
|
+
rmSync(this.pendingPath(id), { force: true });
|
|
406
|
+
rmSync(join(this.stateDir, "plugin-setup", `${id}.json`), { force: true });
|
|
258
407
|
if (removeData) rmSync(this.dataDir(id), {
|
|
259
408
|
recursive: true,
|
|
260
409
|
force: true
|
|
261
410
|
});
|
|
411
|
+
prunePluginResourceCache(this);
|
|
262
412
|
});
|
|
263
413
|
}
|
|
264
414
|
withSource(source, fn) {
|
|
@@ -292,7 +442,7 @@ var AgentPluginStore = class {
|
|
|
292
442
|
}
|
|
293
443
|
}
|
|
294
444
|
const children = readdirSync(temp);
|
|
295
|
-
return fn(existsSync(join(temp,
|
|
445
|
+
return fn(PLUGIN_MANIFEST_PATHS.some((path) => existsSync(join(temp, path))) ? temp : children.length === 1 ? join(temp, children[0]) : temp);
|
|
296
446
|
} finally {
|
|
297
447
|
rmSync(temp, {
|
|
298
448
|
recursive: true,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AgentPluginStore, InstalledAgentPlugin } from './store.js';
|
|
2
|
+
export declare function readPluginUserConfig(store: AgentPluginStore, id: string, revision: string): Record<string, unknown>;
|
|
3
|
+
export declare function savePluginUserConfig(store: AgentPluginStore, plugin: InstalledAgentPlugin, input: Record<string, unknown>): Promise<void>;
|
|
4
|
+
export declare function pluginConfigMissing(store: AgentPluginStore, plugin: InstalledAgentPlugin): string[];
|
|
5
|
+
export declare function expandUserConfig(value: string, values: Record<string, unknown>): unknown;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
|
|
2
|
+
import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
|
|
3
|
+
import { pluginAuthorizations } from "./setup-contract.js";
|
|
4
|
+
import { pluginName } from "./validation.js";
|
|
5
|
+
import { pluginCredentialProviderPrefix } from "./auth.js";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
//#region src/extensions/agent-plugins/user-config.ts
|
|
10
|
+
init_credentials();
|
|
11
|
+
init_write_file_atomic();
|
|
12
|
+
function readPluginUserConfig(store, id, revision) {
|
|
13
|
+
const path = join(store.stateDir, "plugin-config", `${pluginName.parse(id)}-${revision}.json`);
|
|
14
|
+
return existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : {};
|
|
15
|
+
}
|
|
16
|
+
async function savePluginUserConfig(store, plugin, input) {
|
|
17
|
+
const fields = plugin.layout?.userConfig ?? {};
|
|
18
|
+
const values = readPluginUserConfig(store, plugin.id, plugin.receipt.revision);
|
|
19
|
+
for (const [key, value] of Object.entries(input)) {
|
|
20
|
+
const field = fields[key];
|
|
21
|
+
if (!field || typeof value !== field.type || typeof value === "string" && (value.length > 16384 || value.includes("\0"))) throw new Error(`Invalid configuration: ${key}`);
|
|
22
|
+
if (field.sensitive) {
|
|
23
|
+
const provider = `${pluginCredentialProviderPrefix(plugin.id)}config-${createHash("sha256").update(`${plugin.receipt.revision}:${key}`).digest("hex")}`;
|
|
24
|
+
await new CredentialResolver({ stateDir: store.stateDir }).saveApiKey(provider, String(value));
|
|
25
|
+
values[key] = { xopcSecretRef: {
|
|
26
|
+
provider,
|
|
27
|
+
fieldKey: key,
|
|
28
|
+
prefix: ""
|
|
29
|
+
} };
|
|
30
|
+
} else values[key] = value;
|
|
31
|
+
}
|
|
32
|
+
writeTextAtomicSync(join(store.stateDir, "plugin-config", `${plugin.id}-${plugin.receipt.revision}.json`), JSON.stringify(values));
|
|
33
|
+
}
|
|
34
|
+
function pluginConfigMissing(store, plugin) {
|
|
35
|
+
const saved = readPluginUserConfig(store, plugin.id, plugin.receipt.revision);
|
|
36
|
+
const accountFields = new Set(pluginAuthorizations(plugin.manifest).flatMap((value) => value.methods.flatMap((method) => method.type === "form" || method.type === "cli" ? method.fields : [])));
|
|
37
|
+
return Object.entries(plugin.layout?.userConfig ?? {}).filter(([key, field]) => !accountFields.has(key) && field.required && (saved[key] === void 0 || saved[key] === "") && field.default === void 0).map(([key]) => key);
|
|
38
|
+
}
|
|
39
|
+
function expandUserConfig(value, values) {
|
|
40
|
+
const exact = value.match(/^\$\{user_config\.([A-Za-z_][A-Za-z0-9_]*)\}$/);
|
|
41
|
+
if (exact && typeof values[exact[1]] === "object") return values[exact[1]];
|
|
42
|
+
return value.replace(/\$\{user_config\.([A-Za-z_][A-Za-z0-9_]*)\}/g, (_all, key) => {
|
|
43
|
+
if (values[key] === void 0) throw new Error(`Configure ${key} before starting tools`);
|
|
44
|
+
if (typeof values[key] === "object") throw new Error("Sensitive configuration must occupy an entire environment/header value");
|
|
45
|
+
return String(values[key]);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { expandUserConfig, pluginConfigMissing, readPluginUserConfig, savePluginUserConfig };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { pluginResources } from './resources.js';
|
|
2
|
+
import { type PluginLayout } from './formats.js';
|
|
1
3
|
import { z } from 'zod';
|
|
2
4
|
export declare const PLUGIN_SCHEMA = "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json";
|
|
3
5
|
export declare const MCP_SCHEMA = "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json";
|
|
@@ -28,6 +30,27 @@ declare const serverSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
28
30
|
type: z.ZodLiteral<"streamable-http">;
|
|
29
31
|
url: z.ZodString;
|
|
30
32
|
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
33
|
+
oauth: z.ZodOptional<z.ZodObject<{
|
|
34
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
35
|
+
clientId: z.ZodOptional<z.ZodString>;
|
|
36
|
+
callbackPort: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
callbackUrl: z.ZodOptional<z.ZodString>;
|
|
38
|
+
clientName: z.ZodOptional<z.ZodString>;
|
|
39
|
+
clientRegistration: z.ZodOptional<z.ZodEnum<{
|
|
40
|
+
dcr: "dcr";
|
|
41
|
+
cimd: "cimd";
|
|
42
|
+
}>>;
|
|
43
|
+
authServerMetadataUrl: z.ZodOptional<z.ZodString>;
|
|
44
|
+
}, z.core.$strict>>;
|
|
45
|
+
connectionAuth: z.ZodOptional<z.ZodObject<{
|
|
46
|
+
mode: z.ZodEnum<{
|
|
47
|
+
none: "none";
|
|
48
|
+
oauth: "oauth";
|
|
49
|
+
"api-key": "api-key";
|
|
50
|
+
}>;
|
|
51
|
+
headerName: z.ZodOptional<z.ZodString>;
|
|
52
|
+
prefix: z.ZodOptional<z.ZodString>;
|
|
53
|
+
}, z.core.$strict>>;
|
|
31
54
|
}, z.core.$strict>], "type">;
|
|
32
55
|
export type PluginManifest = z.infer<typeof manifestSchema>;
|
|
33
56
|
export type PluginServer = z.infer<typeof serverSchema>;
|
|
@@ -36,6 +59,8 @@ export interface PluginDiagnostic {
|
|
|
36
59
|
message: string;
|
|
37
60
|
}
|
|
38
61
|
export interface PluginInspection {
|
|
62
|
+
resources?: ReturnType<typeof pluginResources>;
|
|
63
|
+
layout?: PluginLayout;
|
|
39
64
|
manifest: PluginManifest;
|
|
40
65
|
rootDir: string;
|
|
41
66
|
skills: Array<{
|
|
@@ -50,6 +75,6 @@ export declare function containedPath(root: string, path: string): string;
|
|
|
50
75
|
export declare function expandPluginVariables(value: string, root: string, data: string): string;
|
|
51
76
|
export declare function resolvePluginCwd(cwd: string | undefined, root: string, data: string): string;
|
|
52
77
|
export declare function validatePluginServer(raw: unknown, root: string, data: string): PluginServer;
|
|
53
|
-
export declare function inspectAgentPlugin(rootDir: string, dataDir?: string): PluginInspection;
|
|
78
|
+
export declare function inspectAgentPlugin(rootDir: string, dataDir?: string, importManifest?: Record<string, unknown>): PluginInspection;
|
|
54
79
|
export declare function pluginServerId(pluginId: string, serverName: string): string;
|
|
55
80
|
export {};
|