@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
|
@@ -2,6 +2,7 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { isManagedConnectorServer } from "../../connectors/materialize.js";
|
|
4
4
|
import { prepareNativeMcpConfig } from "./native-mcp.js";
|
|
5
|
+
import { resolveMcpSetupConfig } from "./effective-server.js";
|
|
5
6
|
import { classifyMcpConnectionError } from "./connection-errors.js";
|
|
6
7
|
import { McpAuthenticationRequiredError, discoverMcpTools, signInNativeMcp } from "./tool-catalog.js";
|
|
7
8
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -83,6 +84,7 @@ async function advertisesOAuth(config, workspace, serverId, signal) {
|
|
|
83
84
|
return Boolean(legacy && legacy.issuer === url.origin && typeof legacy.authorization_endpoint === "string" && typeof legacy.token_endpoint === "string");
|
|
84
85
|
}
|
|
85
86
|
async function probeMcpConnection(config, workspace, serverId, options) {
|
|
87
|
+
config = resolveMcpSetupConfig(config, serverId);
|
|
86
88
|
try {
|
|
87
89
|
return {
|
|
88
90
|
state: "connected",
|
|
@@ -116,6 +118,7 @@ async function probeMcpConnection(config, workspace, serverId, options) {
|
|
|
116
118
|
}
|
|
117
119
|
const attempts = /* @__PURE__ */ new Map();
|
|
118
120
|
function fingerprint(config, serverId) {
|
|
121
|
+
config = resolveMcpSetupConfig(config, serverId);
|
|
119
122
|
const server = config.mcp?.servers?.[serverId];
|
|
120
123
|
return createHash("sha256").update(JSON.stringify(server ? {
|
|
121
124
|
...server,
|
|
@@ -138,6 +141,7 @@ function cancel(attempt) {
|
|
|
138
141
|
}
|
|
139
142
|
/** A UI bridge to native pi's login command; no host-owned OAuth client or token store. */
|
|
140
143
|
function startMcpAuthorization(config, workspace, serverId, owner, options) {
|
|
144
|
+
config = resolveMcpSetupConfig(config, serverId);
|
|
141
145
|
const server = config.mcp?.servers?.[serverId];
|
|
142
146
|
if (!server?.url || server.enabled === false || isManagedConnectorServer(server) && server.xopcConnector.enabled === false) throw new Error("An enabled HTTP MCP server is required.");
|
|
143
147
|
httpUrl(server.url);
|
|
@@ -227,7 +231,15 @@ function submitMcpRedirect(id, owner, redirectUrl, config) {
|
|
|
227
231
|
if (!expected) return false;
|
|
228
232
|
const target = new URL(expected);
|
|
229
233
|
const actual = httpUrl(redirectUrl);
|
|
230
|
-
if (actual.origin !== target.origin || actual.pathname !== target.pathname || actual.searchParams.get("state") !== authorization.searchParams.get("state")
|
|
234
|
+
if (actual.origin !== target.origin || actual.pathname !== target.pathname || actual.searchParams.get("state") !== authorization.searchParams.get("state")) return false;
|
|
235
|
+
if (actual.searchParams.has("error")) {
|
|
236
|
+
cancel(attempt);
|
|
237
|
+
attempt.result.state = "error";
|
|
238
|
+
attempt.result.error = "Sign-in was declined or could not be completed. Try again.";
|
|
239
|
+
delete attempt.result.authorizationUrl;
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
if (!actual.searchParams.get("code")) return false;
|
|
231
243
|
attempt.redirect(actual.href);
|
|
232
244
|
attempt.redirect = void 0;
|
|
233
245
|
return true;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AgentPluginStore } from "../../extensions/agent-plugins/store.js";
|
|
2
|
+
import { materializePluginServers } from "../../extensions/agent-plugins/mcp-adapter.js";
|
|
3
|
+
//#region src/agent/mcp/effective-server.ts
|
|
4
|
+
/** Resolve a single explicit setup target without enabling it for any agent. */
|
|
5
|
+
function resolveMcpSetupConfig(config, serverId) {
|
|
6
|
+
if (Object.hasOwn(config.mcp?.servers ?? {}, serverId)) return config;
|
|
7
|
+
const store = new AgentPluginStore();
|
|
8
|
+
for (const installed of store.list()) {
|
|
9
|
+
const plugin = store.pending(installed.id) ?? installed;
|
|
10
|
+
if (plugin.readiness === "blocked") continue;
|
|
11
|
+
const servers = materializePluginServers(plugin, store, [], true);
|
|
12
|
+
if (!Object.hasOwn(servers, serverId)) continue;
|
|
13
|
+
return {
|
|
14
|
+
...config,
|
|
15
|
+
mcp: {
|
|
16
|
+
...config.mcp,
|
|
17
|
+
servers: {
|
|
18
|
+
...config.mcp?.servers,
|
|
19
|
+
[serverId]: servers[serverId]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return config;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { resolveMcpSetupConfig };
|
|
@@ -8,4 +8,4 @@ export type NativeMcpConfig = LoadedMcpConfig & {
|
|
|
8
8
|
credentialAliases?: Record<string, string>;
|
|
9
9
|
};
|
|
10
10
|
/** Only projects host configuration and secret references; all MCP execution belongs to pi. */
|
|
11
|
-
export declare function prepareNativeMcpConfig(config: Config, workspaceDir: string): Promise<NativeMcpConfig>;
|
|
11
|
+
export declare function prepareNativeMcpConfig(config: Config, workspaceDir: string, agentId?: string): Promise<NativeMcpConfig>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { init_paths_state, resolveStateDir } from "../../config/paths-state.js";
|
|
2
2
|
import { McpServerSchema, init_schema } from "../../config/schema.js";
|
|
3
3
|
import { resolveConnectorSecretReferences } from "../../connectors/secret-store.js";
|
|
4
|
+
import { validPluginOAuthReference } from "../../extensions/agent-plugins/connection-reuse.js";
|
|
4
5
|
import { createNativeMcpCredentials, routeNativeMcpCredentials } from "./credential-store.js";
|
|
5
6
|
import { loadMergedMcpConfig } from "./config.js";
|
|
6
7
|
import { join } from "node:path";
|
|
@@ -20,17 +21,19 @@ function getNativePiAgentDir() {
|
|
|
20
21
|
return directory;
|
|
21
22
|
}
|
|
22
23
|
/** Only projects host configuration and secret references; all MCP execution belongs to pi. */
|
|
23
|
-
async function prepareNativeMcpConfig(config, workspaceDir) {
|
|
24
|
+
async function prepareNativeMcpConfig(config, workspaceDir, agentId) {
|
|
24
25
|
getNativePiAgentDir();
|
|
25
26
|
const merged = loadMergedMcpConfig({
|
|
26
27
|
cfg: config,
|
|
27
|
-
workspaceDir
|
|
28
|
+
workspaceDir,
|
|
29
|
+
agentId
|
|
28
30
|
});
|
|
29
31
|
const result = {
|
|
30
32
|
servers: [],
|
|
31
33
|
errors: merged.diagnostics.map((item) => item.message)
|
|
32
34
|
};
|
|
33
35
|
const names = /* @__PURE__ */ new Set();
|
|
36
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
34
37
|
for (const [name, raw] of Object.entries(merged.config.mcpServers)) {
|
|
35
38
|
const normalized = name.replace(/-/g, "_");
|
|
36
39
|
if (!/^[a-zA-Z0-9_-]+$/.test(name) || names.has(normalized)) {
|
|
@@ -38,6 +41,12 @@ async function prepareNativeMcpConfig(config, workspaceDir) {
|
|
|
38
41
|
continue;
|
|
39
42
|
}
|
|
40
43
|
names.add(normalized);
|
|
44
|
+
const reference = raw.xopcPluginOAuthReference;
|
|
45
|
+
if (reference && !validPluginOAuthReference(reference, config, raw)) {
|
|
46
|
+
result.errors.push(`Shared MCP connection changed: ${name}. Reconnect this plugin.`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (typeof raw.xopcOAuthCredentialId === "string") aliases.set(name, raw.xopcOAuthCredentialId);
|
|
41
50
|
const parsed = McpServerSchema.safeParse(raw);
|
|
42
51
|
if (!parsed.success) {
|
|
43
52
|
result.errors.push(`Invalid MCP server ${name}: ${parsed.error.message}`);
|
|
@@ -61,14 +70,14 @@ async function prepareNativeMcpConfig(config, workspaceDir) {
|
|
|
61
70
|
"description"
|
|
62
71
|
].filter((key) => value[key] !== void 0).map((key) => [key, value[key]]));
|
|
63
72
|
if (projected.type === "streamable-http") projected.type = "http";
|
|
73
|
+
const plugin = raw.xopcPlugin;
|
|
64
74
|
result.servers.push({
|
|
65
75
|
name,
|
|
66
76
|
config: projected,
|
|
67
|
-
source: "xopc.json",
|
|
77
|
+
source: plugin?.revision ? `plugin:${plugin.id}@${plugin.revision}` : "xopc.json",
|
|
68
78
|
scope: "extension"
|
|
69
79
|
});
|
|
70
80
|
}
|
|
71
|
-
const aliases = new Map(Object.entries(config.mcp?.servers ?? {}).filter(([, value]) => typeof value.xopcOAuthCredentialId === "string").map(([name, value]) => [name, value.xopcOAuthCredentialId]));
|
|
72
81
|
if (aliases.size) {
|
|
73
82
|
result.credentials = routeNativeMcpCredentials(await createNativeMcpCredentials(), aliases);
|
|
74
83
|
result.credentialAliases = Object.fromEntries(aliases);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createEmbeddedModelRuntime } from "../embedded/model-runtime.js";
|
|
2
2
|
import { getNativePiAgentDir, prepareNativeMcpConfig } from "./native-mcp.js";
|
|
3
|
+
import { resolveMcpSetupConfig } from "./effective-server.js";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { InMemoryCredentialStore, InMemoryModelsStore } from "@earendil-works/pi-ai";
|
|
5
6
|
import { DefaultResourceLoader, ModelRuntime, SessionManager, SettingsManager, createAgentSession, createMcpExtension, createToolSearchExtension } from "@earendil-works/pi-coding-agent";
|
|
@@ -16,7 +17,7 @@ async function signInNativeMcp(config, workspaceDir, serverId, interaction, opti
|
|
|
16
17
|
async function runNativeMcpSession(config, workspaceDir, serverId, interaction, options) {
|
|
17
18
|
const signal = interaction?.signal ?? options?.signal;
|
|
18
19
|
signal?.throwIfAborted();
|
|
19
|
-
const loaded = await prepareNativeMcpConfig(config, workspaceDir);
|
|
20
|
+
const loaded = await prepareNativeMcpConfig(resolveMcpSetupConfig(config, serverId), workspaceDir);
|
|
20
21
|
signal?.throwIfAborted();
|
|
21
22
|
const entry = loaded.servers.find((server) => server.name === serverId);
|
|
22
23
|
if (!entry) throw new Error(`MCP server "${serverId}" is not configured or has invalid configuration.`);
|
|
@@ -40,6 +40,7 @@ export interface SkillLoader {
|
|
|
40
40
|
getEnabledSkills: (config?: Record<string, SkillConfig>) => Skill[];
|
|
41
41
|
}
|
|
42
42
|
export interface SkillLoaderOptions {
|
|
43
|
+
agentId?: string;
|
|
43
44
|
/** Re-evaluated on every load so trust changes take effect without recreating the runtime. */
|
|
44
45
|
isWorkspaceTrusted?: (workspaceDir: string) => boolean;
|
|
45
46
|
}
|
|
@@ -135,7 +135,10 @@ function discoverAndMergeSkills(sources, maxSkillFileBytes, limits = {}, initial
|
|
|
135
135
|
skills: source.skillFiles.slice(0, limits.maxSkillsLoadedPerSource).flatMap((path) => {
|
|
136
136
|
const result = loadSkillFromFile(path, source, source.rootDir, maxSkillFileBytes);
|
|
137
137
|
if (result.diagnostic) diagnostics.push(result.diagnostic);
|
|
138
|
-
return result.skill ? [
|
|
138
|
+
return result.skill ? [{
|
|
139
|
+
...result.skill,
|
|
140
|
+
name: source.skillAliases?.[path] ?? result.skill.name
|
|
141
|
+
}] : [];
|
|
139
142
|
}),
|
|
140
143
|
diagnostics: []
|
|
141
144
|
} : discoverSkills(source, maxSkillFileBytes, limits.maxSkillsLoadedPerSource, limits.maxCandidatesPerRoot);
|
|
@@ -320,7 +323,8 @@ function createSkillLoader(options = {}) {
|
|
|
320
323
|
return loadSkills({
|
|
321
324
|
workspaceDir,
|
|
322
325
|
builtinDir,
|
|
323
|
-
workspaceTrust
|
|
326
|
+
workspaceTrust,
|
|
327
|
+
agentId: options.agentId
|
|
324
328
|
});
|
|
325
329
|
}
|
|
326
330
|
return {
|
|
@@ -35,7 +35,10 @@ var SkillManager = class {
|
|
|
35
35
|
constructor(workspace, bundledSkillsDir, options = {}) {
|
|
36
36
|
this.workspace = workspace;
|
|
37
37
|
this.bundledSkillsDir = bundledSkillsDir || resolveBundledSkillsDir();
|
|
38
|
-
this.skillLoader = createSkillLoader({
|
|
38
|
+
this.skillLoader = createSkillLoader({
|
|
39
|
+
agentId: options.agentId,
|
|
40
|
+
isWorkspaceTrusted: options.isWorkspaceTrusted
|
|
41
|
+
});
|
|
39
42
|
this.initialize();
|
|
40
43
|
}
|
|
41
44
|
/**
|
|
@@ -216,12 +219,14 @@ var SkillManager = class {
|
|
|
216
219
|
* Find a skill by name
|
|
217
220
|
*/
|
|
218
221
|
findSkill(name) {
|
|
222
|
+
this.refreshPlugins();
|
|
219
223
|
return this.skills.find((s) => s.name === name);
|
|
220
224
|
}
|
|
221
225
|
/**
|
|
222
226
|
* Check if a skill exists
|
|
223
227
|
*/
|
|
224
228
|
hasSkill(name) {
|
|
229
|
+
this.refreshPlugins();
|
|
225
230
|
return this.skills.some((s) => s.name === name);
|
|
226
231
|
}
|
|
227
232
|
/**
|
|
@@ -48,15 +48,16 @@ function resolveSkillSources(options, skillsConfig) {
|
|
|
48
48
|
const extraDirs = [...configuredExtraDirs, ...optionExtraDirs];
|
|
49
49
|
const sources = [];
|
|
50
50
|
const diagnostics = [];
|
|
51
|
-
for (const plugin of new AgentPluginStore().active()) {
|
|
51
|
+
for (const plugin of new AgentPluginStore().active(options.agentId, options.workspaceDir)) {
|
|
52
52
|
sources.push({
|
|
53
53
|
id: `plugin:${plugin.id}`,
|
|
54
|
-
rootDir:
|
|
54
|
+
rootDir: plugin.rootDir,
|
|
55
55
|
priority: 150,
|
|
56
56
|
scope: "global",
|
|
57
57
|
managed: false,
|
|
58
58
|
writable: false,
|
|
59
|
-
skillFiles: plugin.skills.map((skill) => skill.filePath)
|
|
59
|
+
skillFiles: plugin.skills.map((skill) => skill.filePath),
|
|
60
|
+
skillAliases: plugin.layout?.dialect !== "portable" ? Object.fromEntries(plugin.skills.map((skill) => [skill.filePath, `${plugin.id}.${skill.name}`])) : void 0
|
|
60
61
|
});
|
|
61
62
|
diagnostics.push(...plugin.diagnostics.map((diagnostic) => ({
|
|
62
63
|
type: "warning",
|
|
@@ -111,6 +111,7 @@ export interface SkillSourceDescriptor {
|
|
|
111
111
|
writable: boolean;
|
|
112
112
|
/** Validated portable plugin files; bypass recursive discovery. */
|
|
113
113
|
skillFiles?: string[];
|
|
114
|
+
skillAliases?: Record<string, string>;
|
|
114
115
|
}
|
|
115
116
|
export type SkillOrigin = SkillSourceDescriptor;
|
|
116
117
|
export interface SkillsLimitsConfig {
|
|
@@ -23,11 +23,15 @@ var WorkspaceRuntimeRegistry = class {
|
|
|
23
23
|
/** Lazily construct and cache an agent-scoped runtime for a workspace. */
|
|
24
24
|
getOrCreate(resolvedPath, requestedAgentId) {
|
|
25
25
|
const cfg = this.getConfig();
|
|
26
|
-
const
|
|
26
|
+
const agentId = normalizeAgentId(requestedAgentId?.trim() || resolveAgentIdForWorkspacePath(resolvedPath));
|
|
27
|
+
const runtimeKey = `${agentId}\u0000${resolvedPath}`;
|
|
27
28
|
const existing = this.runtimes.get(runtimeKey);
|
|
28
29
|
if (existing) return existing;
|
|
29
30
|
const { memoryManager } = this.userContextRuntimes.getOrCreate(cfg);
|
|
30
|
-
const skillManager = new SkillManager(resolvedPath, this.bundledSkillsDir, {
|
|
31
|
+
const skillManager = new SkillManager(resolvedPath, this.bundledSkillsDir, {
|
|
32
|
+
agentId,
|
|
33
|
+
isWorkspaceTrusted: () => this.isWorkspaceTrusted?.(resolvedPath) === true
|
|
34
|
+
});
|
|
31
35
|
const rt = {
|
|
32
36
|
skillManager,
|
|
33
37
|
systemPromptBuilder: new SystemPromptBuilder({
|
|
@@ -4,8 +4,8 @@ import { init_src } from "../../packages/gateway-contract/src/index.js";
|
|
|
4
4
|
import { getGatewayIdentityPublicKeyRaw, getOrCreateGatewayIdentity, init_gateway_identity_repository } from "../storage/sqlite/gateway-identity-repository.js";
|
|
5
5
|
import { createDevicePairingSetup, init_device_pairing_repository } from "../storage/sqlite/device-pairing-repository.js";
|
|
6
6
|
import { loadConfig } from "../config/loader.js";
|
|
7
|
-
import { browserEnrollmentPublicKeyThumbprint } from "./enrollment.js";
|
|
8
7
|
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "./extension-identity.js";
|
|
8
|
+
import { browserEnrollmentPublicKeyThumbprint } from "./enrollment.js";
|
|
9
9
|
import os from "node:os";
|
|
10
10
|
//#region src/browser/native-messaging-host.ts
|
|
11
11
|
init_src();
|
|
@@ -4,10 +4,10 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
4
4
|
import { init_logger } from "../../utils/logger.js";
|
|
5
5
|
import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
|
|
6
6
|
import { init_paths, resolveBinDir, resolveConfigPath } from "../../config/paths.js";
|
|
7
|
-
import {
|
|
7
|
+
import { resolvePackageRoot } from "../../infra/update-check.js";
|
|
8
8
|
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "../extension-identity.js";
|
|
9
|
+
import { assertCacheDir } from "../cache-dir-policy.js";
|
|
9
10
|
import "../native-messaging-host.js";
|
|
10
|
-
import { resolvePackageRoot } from "../../infra/update-check.js";
|
|
11
11
|
import { dirname, join } from "node:path";
|
|
12
12
|
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
@@ -7,8 +7,8 @@ import { compileAllowlist, evaluateAccess, hasBotMention, removeBotMention, reso
|
|
|
7
7
|
import { renderMarkdownWithMarkers } from "../markdown/render.js";
|
|
8
8
|
import { convertMarkdownTables } from "../markdown/tables.js";
|
|
9
9
|
import { buildCodeSpanIndex, createInlineCodeState } from "../markdown/code-spans.js";
|
|
10
|
+
import { ChannelManager, createChannelManager } from "./manager.js";
|
|
10
11
|
import "./format.js";
|
|
11
12
|
import { MessagePipeline, createEnvelopeTimestampHandler, createFilterCommandsHandler, createFilterEmptyHandler, createFilterSelfHandler, createPipeline, standardPreflightHandlers, standardProcessHandlers } from "./pipeline.js";
|
|
12
|
-
import { ChannelManager, createChannelManager } from "./manager.js";
|
|
13
13
|
import { collectSetupWizardChannels } from "./setup-wizard-discovery.js";
|
|
14
14
|
export { ChannelManager, MessagePipeline, buildCodeSpanIndex, chunkMarkdownIR, chunkText, collectSetupWizardChannels, compileAllowlist, convertMarkdownTables, createChannelManager, createEnvelopeTimestampHandler, createFilterCommandsHandler, createFilterEmptyHandler, createFilterSelfHandler, createInlineCodeState, createPipeline, evaluateAccess, findFenceSpanAt, getChannelPlugin, getChannelRegistryVersion, hasBotMention, isSafeFenceBreak, listChannelPlugins, markdownToIR, markdownToIRWithMeta, parseFenceSpans, parseFrontmatterBlock, removeBotMention, renderMarkdownWithMarkers, resolveAllowlistMatch, resolveAllowlistMatchSimple, resolveDmPolicy, resolveGroupPolicy, standardPreflightHandlers, standardProcessHandlers, syncChannelPluginsFromManager };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
3
|
import { ChannelHealthMonitor } from "./health-monitor.js";
|
|
4
|
-
import { ChannelHeartbeatScheduler } from "./heartbeat-scheduler.js";
|
|
5
4
|
import { ChannelPluginRegistry } from "./plugin-registry.js";
|
|
5
|
+
import { ChannelHeartbeatScheduler } from "./heartbeat-scheduler.js";
|
|
6
6
|
import { ChannelOutboundSender } from "./outbound-sender.js";
|
|
7
7
|
import { ChannelLifecycleSupervisor } from "./lifecycle-supervisor.js";
|
|
8
8
|
//#region src/channels/manager.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { buildChannelCatalogForConfig } from "../../channels/catalog/channel-catalog-service.js";
|
|
2
2
|
import { loadConfig, saveConfig } from "../../config/loader.js";
|
|
3
|
+
import { formatExamples, register } from "../registry.js";
|
|
3
4
|
import { listChannelPairingState } from "../../channels/pairing/pairing-service.js";
|
|
4
5
|
import { approveChannelPairingFromCli } from "../../channels/pairing/approve-cli.js";
|
|
5
|
-
import { formatExamples, register } from "../registry.js";
|
|
6
6
|
import { colors } from "../utils/colors.js";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
//#region src/cli/commands/channels.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../capabilities/store-connector.js";
|
|
2
2
|
import { loadConfig, saveConfig } from "../../config/loader.js";
|
|
3
3
|
import { register } from "../registry.js";
|
|
4
|
-
import { confirm } from "@inquirer/prompts";
|
|
5
4
|
import { Command } from "commander";
|
|
5
|
+
import { confirm } from "@inquirer/prompts";
|
|
6
6
|
//#region src/cli/commands/connectors.ts
|
|
7
7
|
function parsePairs(values, option) {
|
|
8
8
|
const output = {};
|
|
@@ -53,7 +53,7 @@ async function checkDatabaseSchema(ctx) {
|
|
|
53
53
|
id: "database-schema",
|
|
54
54
|
label: "Database schema",
|
|
55
55
|
status: "pass",
|
|
56
|
-
message: `SQLite schema v${status.dbVersion} (current release
|
|
56
|
+
message: `SQLite schema v${status.dbVersion} (current release v257).`,
|
|
57
57
|
hints: []
|
|
58
58
|
};
|
|
59
59
|
}
|
|
@@ -1,24 +1,35 @@
|
|
|
1
|
+
import { getWorkspacePath } from "../../config/workspace-path-helpers.js";
|
|
2
|
+
import { pluginAuthorizations } from "../../extensions/agent-plugins/setup-contract.js";
|
|
3
|
+
import { PLUGIN_MANIFEST_PATHS } from "../../extensions/agent-plugins/formats.js";
|
|
4
|
+
import { pluginServerId } from "../../extensions/agent-plugins/validation.js";
|
|
5
|
+
import { isGitPluginSource } from "../../extensions/agent-plugins/source-catalog.js";
|
|
1
6
|
import { AgentPluginStore } from "../../extensions/agent-plugins/store.js";
|
|
2
7
|
import { loadConfig } from "../../config/loader.js";
|
|
3
8
|
import { getContextWithOpts } from "../context.js";
|
|
4
9
|
import { isAgentPluginArchive, withAgentPluginSource } from "../../extensions/agent-plugins/sources.js";
|
|
10
|
+
import { PluginSetupService } from "../../extensions/agent-plugins/setup.js";
|
|
5
11
|
import { removePluginCredentials } from "../../extensions/agent-plugins/credentials.js";
|
|
6
12
|
import { join, resolve } from "node:path";
|
|
7
13
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
14
|
+
import { readFile } from "node:fs/promises";
|
|
8
15
|
import { confirm } from "@inquirer/prompts";
|
|
9
16
|
//#region src/cli/commands/extension-agent-plugin.ts
|
|
10
17
|
function isAgentPluginSource(source) {
|
|
11
|
-
if (source.startsWith("https://")) return true;
|
|
18
|
+
if (source.startsWith("https://") || isGitPluginSource(source) || source.includes("#plugin=")) return true;
|
|
12
19
|
const path = resolve(source);
|
|
13
20
|
if (existsSync(join(path, "package.json"))) {
|
|
14
21
|
if (JSON.parse(readFileSync(join(path, "package.json"), "utf8"))?.xopc?.extension) return false;
|
|
15
22
|
}
|
|
16
|
-
return existsSync(path) && (statSync(path).isFile() && /\.zip$/i.test(path) && statSync(path).size <= 50 * 1024 * 1024 && isAgentPluginArchive(readFileSync(path)) ||
|
|
23
|
+
return existsSync(path) && (statSync(path).isFile() && /\.zip$/i.test(path) && statSync(path).size <= 50 * 1024 * 1024 && isAgentPluginArchive(readFileSync(path)) || [
|
|
24
|
+
...PLUGIN_MANIFEST_PATHS,
|
|
25
|
+
".agents/plugins/marketplace.json",
|
|
26
|
+
".claude-plugin/marketplace.json"
|
|
27
|
+
].some((file) => existsSync(join(path, file))) && !existsSync(join(path, "xopc.extension.json")));
|
|
17
28
|
}
|
|
18
29
|
async function installAgentPluginFromCli(source, options) {
|
|
19
30
|
const store = new AgentPluginStore();
|
|
20
31
|
const cfg = loadConfig(getContextWithOpts().configPath);
|
|
21
|
-
const plan = await withAgentPluginSource(source, cfg, (local) => store.inspect(local));
|
|
32
|
+
const plan = await withAgentPluginSource(source, cfg, (local, _p, _commit, importManifest) => store.inspect(local, source, importManifest));
|
|
22
33
|
console.log(JSON.stringify({
|
|
23
34
|
format: "agent-plugin",
|
|
24
35
|
name: plan.manifest.name,
|
|
@@ -34,22 +45,96 @@ async function installAgentPluginFromCli(source, options) {
|
|
|
34
45
|
default: false
|
|
35
46
|
})) return;
|
|
36
47
|
}
|
|
37
|
-
const plugin = await withAgentPluginSource(source, cfg, (local, provenance) => store.install(local, {
|
|
48
|
+
const plugin = await withAgentPluginSource(source, cfg, (local, provenance, resolvedCommit, importManifest) => store.install(local, {
|
|
38
49
|
reviewHash: plan.reviewHash,
|
|
39
50
|
replace: options.force,
|
|
51
|
+
stage: options.force,
|
|
40
52
|
expectedId: options.expectedId,
|
|
41
|
-
sourceLabel: source
|
|
42
|
-
provenance
|
|
53
|
+
sourceLabel: source,
|
|
54
|
+
provenance,
|
|
55
|
+
resolvedCommit,
|
|
56
|
+
importManifest
|
|
43
57
|
}));
|
|
58
|
+
if (plugin.readiness !== "blocked") new PluginSetupService(store).create(plugin.id, "gateway-owner");
|
|
44
59
|
console.log(`Installed plugin:${plugin.id} (${plugin.receipt.enabled ? "enabled" : "disabled"}).`);
|
|
60
|
+
if (plugin.readiness !== "blocked") console.log(`Continue with: xopc extensions setup plugin:${plugin.id} --prepare`);
|
|
45
61
|
return plugin;
|
|
46
62
|
}
|
|
47
63
|
function addAgentPluginLifecycleCommands(command) {
|
|
64
|
+
command.command("setup").argument("<id>", "plugin:<id>").option("--prepare", "Prepare resources and check tools").option("--authorize <server>", "Authorize a plugin account or show native MCP sign-in instructions").option("--method <id>", "Choose one of the account authorization methods").option("--skip-auth", "Finish installation and authorize later in plugin details").option("--complete", "Finish setup and enable globally for all agents").option("--workspace <paths...>", "Restrict the plugin to these workspace paths").option("--config-file <path>", "Read typed user configuration from a JSON file").option("--allow-partial", "Enable available components after reviewing compatibility limits").option("--cancel", "Cancel preparation").action(async (raw, options) => {
|
|
65
|
+
const store = new AgentPluginStore(), setup = new PluginSetupService(store), id = raw.replace(/^plugin:/, "");
|
|
66
|
+
const cfg = loadConfig(getContextWithOpts().configPath), workspace = getWorkspacePath(cfg) || process.cwd(), owner = "gateway-owner";
|
|
67
|
+
let job = setup.create(id, owner);
|
|
68
|
+
const declaration = pluginAuthorizations((store.pending(id) ?? store.get(id)).manifest).find((value) => value.id === options.authorize);
|
|
69
|
+
const method = declaration?.methods.find((value) => value.id === (options.method ?? declaration.methods[0]?.id));
|
|
70
|
+
if (options.configFile) job = await setup.act(id, owner, {
|
|
71
|
+
action: "configure",
|
|
72
|
+
expectedRevision: job.revision,
|
|
73
|
+
values: JSON.parse(await readFile(options.configFile, "utf8")),
|
|
74
|
+
...method?.type === "form" ? {
|
|
75
|
+
authorization: declaration.id,
|
|
76
|
+
method: method.id
|
|
77
|
+
} : {}
|
|
78
|
+
}, cfg, workspace);
|
|
79
|
+
if (options.prepare || declaration) job = await setup.act(id, owner, {
|
|
80
|
+
action: "prepare",
|
|
81
|
+
expectedRevision: job.revision
|
|
82
|
+
}, cfg, workspace);
|
|
83
|
+
if (options.authorize) if (declaration) {
|
|
84
|
+
if (!method) throw new Error("Unknown authorization method");
|
|
85
|
+
if (method.type !== "form") {
|
|
86
|
+
job = await setup.act(id, owner, {
|
|
87
|
+
action: "authorize",
|
|
88
|
+
expectedRevision: job.revision,
|
|
89
|
+
server: declaration.id,
|
|
90
|
+
method: method.id
|
|
91
|
+
}, cfg, workspace);
|
|
92
|
+
let lastUrl = "";
|
|
93
|
+
for (;;) {
|
|
94
|
+
const attempt = await setup.authorization(id, owner, declaration.id, cfg);
|
|
95
|
+
if (!attempt) throw new Error("Sign-in is unavailable. Retry authorization.");
|
|
96
|
+
const url = "challenge" in attempt ? attempt.challenge?.url : "authorizationUrl" in attempt ? attempt.authorizationUrl : void 0;
|
|
97
|
+
if (url && url !== lastUrl) {
|
|
98
|
+
console.log(`Complete sign-in: ${url}`);
|
|
99
|
+
lastUrl = url;
|
|
100
|
+
}
|
|
101
|
+
if (attempt.state === "connected") break;
|
|
102
|
+
if (["cancelled", "error"].includes(attempt.state)) throw new Error("Sign-in did not complete. Retry authorization.");
|
|
103
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
104
|
+
}
|
|
105
|
+
job = await setup.act(id, owner, {
|
|
106
|
+
action: "prepare",
|
|
107
|
+
expectedRevision: job.revision
|
|
108
|
+
}, cfg, workspace);
|
|
109
|
+
} else if (!options.configFile) throw new Error("Provide credential fields with --config-file");
|
|
110
|
+
} else {
|
|
111
|
+
if (!job.connections.some((c) => c.name === options.authorize)) throw new Error("Unknown plugin MCP server");
|
|
112
|
+
console.log(`Sign in with: xopc mcp login ${pluginServerId(id, options.authorize)}`);
|
|
113
|
+
}
|
|
114
|
+
if (options.complete) job = await setup.act(id, owner, {
|
|
115
|
+
action: "complete",
|
|
116
|
+
expectedRevision: job.revision,
|
|
117
|
+
workspacePaths: options.workspace,
|
|
118
|
+
allowPartial: options.allowPartial === true
|
|
119
|
+
}, cfg, workspace);
|
|
120
|
+
if (options.skipAuth) job = await setup.act(id, owner, {
|
|
121
|
+
action: "defer",
|
|
122
|
+
expectedRevision: job.revision
|
|
123
|
+
}, cfg, workspace);
|
|
124
|
+
if (options.cancel) job = await setup.act(id, owner, {
|
|
125
|
+
action: "cancel",
|
|
126
|
+
expectedRevision: job.revision
|
|
127
|
+
}, cfg, workspace);
|
|
128
|
+
console.log(JSON.stringify(job, null, 2));
|
|
129
|
+
});
|
|
48
130
|
command.command("rollback").argument("<id>", "plugin:<name>").action((raw) => {
|
|
49
131
|
console.log(JSON.stringify(new AgentPluginStore().rollback(raw.replace(/^plugin:/, "")), null, 2));
|
|
50
132
|
});
|
|
51
133
|
for (const action of ["enable", "disable"]) command.command(action).argument("<id>", "plugin:<name>").action((raw) => {
|
|
52
|
-
const
|
|
134
|
+
const store = new AgentPluginStore(), id = raw.replace(/^plugin:/, "");
|
|
135
|
+
const job = new PluginSetupService(store).get(id, "gateway-owner");
|
|
136
|
+
if (action === "enable" && job && job.state !== "completed") throw new Error("Finish plugin setup before enabling");
|
|
137
|
+
const plugin = store.setEnabled(id, action === "enable");
|
|
53
138
|
console.log(`${plugin.id}: ${action}d`);
|
|
54
139
|
});
|
|
55
140
|
command.command("remove").argument("<id>", "plugin:<name>").option("--remove-data", "Also remove persistent plugin data").option("--remove-credentials", "Also delete local credentials").action(async (raw, options) => {
|
|
@@ -16,8 +16,8 @@ import { existsSync, readFileSync, statSync } from "node:fs";
|
|
|
16
16
|
import { execSync } from "node:child_process";
|
|
17
17
|
import { createHash } from "node:crypto";
|
|
18
18
|
import semver from "semver";
|
|
19
|
-
import { confirm } from "@inquirer/prompts";
|
|
20
19
|
import { Command } from "commander";
|
|
20
|
+
import { confirm } from "@inquirer/prompts";
|
|
21
21
|
//#region src/cli/commands/extension-marketplace.ts
|
|
22
22
|
init_paths();
|
|
23
23
|
const MANIFEST = "xopc.extension.json";
|
|
@@ -224,7 +224,7 @@ async function installExtensionFromStoreWithLock(params) {
|
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
function createExtensionInstallCommand() {
|
|
227
|
-
return new Command("install").description("Install a native extension or portable Agent Plugin
|
|
227
|
+
return new Command("install").description("Install a native extension or Codex, Claude or portable Agent Plugin").argument("<target>", "store:<id>, npm:<package>, Git / marketplace source, directory or plugin ZIP").option("-f, --force", "Replace an existing store or local extension with the same manifest id", false).option("-y, --yes", "Skip interactive install confirmation", false).action(async (target, opts) => {
|
|
228
228
|
if (isAgentPluginSource(target)) {
|
|
229
229
|
await installAgentPluginFromCli(target, opts);
|
|
230
230
|
return;
|
|
@@ -78,7 +78,7 @@ function createExtensionInspectCommand() {
|
|
|
78
78
|
try {
|
|
79
79
|
if (extensionId.startsWith("plugin:") || extensionId.startsWith("store:") || isAgentPluginSource(extensionId)) {
|
|
80
80
|
const store = new AgentPluginStore();
|
|
81
|
-
const result = extensionId.startsWith("plugin:") ? store.get(extensionId.slice(7)) : await withAgentPluginSource(extensionId, loadConfig(getContextWithOpts().configPath), (source) => store.inspect(source));
|
|
81
|
+
const result = extensionId.startsWith("plugin:") ? store.get(extensionId.slice(7)) : await withAgentPluginSource(extensionId, loadConfig(getContextWithOpts().configPath), (source, _p, _commit, importManifest) => store.inspect(source, extensionId, importManifest));
|
|
82
82
|
if (!result) throw new Error("Plugin not installed");
|
|
83
83
|
console.log(JSON.stringify(result, null, 2));
|
|
84
84
|
return;
|
|
@@ -3,6 +3,7 @@ import { loadConfig } from "../../config/loader.js";
|
|
|
3
3
|
import { register } from "../registry.js";
|
|
4
4
|
import { createGatewayHttpClientFromConfig } from "../../mcp/gateway-http-client.js";
|
|
5
5
|
import { createCapabilityMcpServer } from "../../mcp/capability-server.js";
|
|
6
|
+
import { resolveMcpSetupConfig } from "../../agent/mcp/effective-server.js";
|
|
6
7
|
import { join } from "node:path";
|
|
7
8
|
import { chmodSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
9
|
import { main } from "@earendil-works/pi-coding-agent";
|
|
@@ -18,24 +19,25 @@ function createMcpCommand(ctx) {
|
|
|
18
19
|
]) {
|
|
19
20
|
const native = command.command(action).description(`Use pi's native MCP ${action}`);
|
|
20
21
|
if (action !== "list") native.argument("<server>", "Configured MCP server ID");
|
|
21
|
-
if (action === "list") native.option("--json", "Print pi MCP diagnostics as JSON");
|
|
22
|
+
if (action === "list") native.option("--json", "Print pi MCP diagnostics as JSON").option("--agent <id>", "Include plugins bound to this agent");
|
|
22
23
|
if (action === "login") native.option("--timeout <seconds>", "Browser sign-in timeout in seconds");
|
|
23
24
|
native.action(async (serverOrOptions, loginOptions) => {
|
|
24
25
|
const server = typeof serverOrOptions === "string" ? serverOrOptions : void 0;
|
|
25
26
|
const options = typeof serverOrOptions === "string" ? loginOptions : serverOrOptions;
|
|
26
|
-
const
|
|
27
|
+
const config = loadConfig(ctx.configPath);
|
|
28
|
+
const mcp = await prepareNativeMcpConfig(server ? resolveMcpSetupConfig(config, server) : config, ctx.workspacePath || process.cwd(), options?.agent);
|
|
27
29
|
if (mcp.errors.length) throw new Error(mcp.errors.join("\n"));
|
|
28
30
|
const path = join(getNativePiAgentDir(), "mcp.json");
|
|
29
31
|
if (existsSync(path) && JSON.parse(readFileSync(path, "utf8")).xopcGenerated !== true) throw new Error("The pi directory contains a user-managed mcp.json. Use a dedicated PI_CODING_AGENT_DIR for xopc.");
|
|
30
32
|
if (existsSync(path)) chmodSync(path, 384);
|
|
31
33
|
writeFileSync(path, JSON.stringify({
|
|
32
34
|
xopcGenerated: true,
|
|
33
|
-
mcpServers: Object.fromEntries(mcp.servers.map((entry) => [entry.name, entry.config]))
|
|
35
|
+
mcpServers: Object.fromEntries(mcp.servers.filter((entry) => !server || entry.name === server).map((entry) => [mcp.credentialAliases?.[entry.name] ?? entry.name, entry.config]))
|
|
34
36
|
}), { mode: 384 });
|
|
35
37
|
await main([
|
|
36
38
|
"mcp",
|
|
37
39
|
action,
|
|
38
|
-
...server ? [server] : [],
|
|
40
|
+
...server ? [mcp.credentialAliases?.[server] ?? server] : [],
|
|
39
41
|
...action === "list" && options?.json ? ["--json"] : [],
|
|
40
42
|
...action === "login" && loginOptions?.timeout ? ["--timeout", loginOptions.timeout] : []
|
|
41
43
|
]);
|
|
@@ -16,8 +16,8 @@ import { prepareUpdateGlobalDefaults } from "../../gateway/global-defaults-admin
|
|
|
16
16
|
import { disconnectProvider } from "../../providers/provider-disconnect.js";
|
|
17
17
|
import { colors } from "../utils/colors.js";
|
|
18
18
|
import { runCliOAuthLogin } from "../utils/oauth-login.js";
|
|
19
|
-
import { input } from "@inquirer/prompts";
|
|
20
19
|
import { Command } from "commander";
|
|
20
|
+
import { input } from "@inquirer/prompts";
|
|
21
21
|
//#region src/cli/commands/models.ts
|
|
22
22
|
init_credentials();
|
|
23
23
|
init_schema();
|
|
@@ -11,8 +11,8 @@ import { initWorkspace } from "../utils/init-workspace.js";
|
|
|
11
11
|
import { setupModel } from "./onboard/model.js";
|
|
12
12
|
import { getChannelConfigurators } from "./onboard/channels/registry.js";
|
|
13
13
|
import { setupChannels } from "./onboard/channels/index.js";
|
|
14
|
-
import { select } from "@inquirer/prompts";
|
|
15
14
|
import { Command } from "commander";
|
|
15
|
+
import { select } from "@inquirer/prompts";
|
|
16
16
|
//#region src/cli/commands/onboard.ts
|
|
17
17
|
init_repository();
|
|
18
18
|
init_schema();
|