@xopcai/xopc 0.0.224 → 0.0.225
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/demo-memory/src/index.js +10 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store--GBciH10.js → activity-store-CtTYnku4.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-K7V4XXt7.js → agent-avatar-dicebear-dizuqu_4.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-BsxTpXyq.js → agents-DeEEFZJ4.js} +1 -1
- package/dist/gateway/static/root/assets/{api-HoIz_ija.js → api-CLRMz2BT.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-xQCmkAHh.js → app-management-settings-panel-Cnk-DtQh.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-BRoeA4kU.js → appearance-settings-wP0rogVI.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-BXgpBA8w.js → apps-page-Db5YNHVM.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-CteCVsBP.js → archive-plugin-Cpzsm-DM.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-D7xNA2jB.js → attachment-load-Bd2OOoEK.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BD1vK7r5.js → automations-page-DNqhguyk.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-wrgf-z7D.js → automations-workspace-CNT05YTb.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-C3DaJa0W.js → binary-plugins-Dcma5HdI.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-lTkcHTve.js → block-editor-D-B8ThwK.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-zhzNkeVG.js → browser-settings-page-UbDj3LIq.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-1UZ0vnIy.js → browser-workflow-inputs-BAPZIXrs.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-BHuJOF4M.js → browser-workflows-page-DHtaSKEh.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-DuCmg2Ej.js → capabilities-settings-panel-CiO152QS.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-api-yNqTIuyd.js → capability-presets-api-zsZQ7im3.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-DjiP3mQQ.js → capability-presets-settings-panel-Bc_hRwfL.js} +1 -1
- package/dist/gateway/static/root/assets/{channel-recipient-api-krezGsKc.js → channel-recipient-api-Cp8iaaXp.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-B4AtvQHk.js → channels-settings-CFW7zBoT.js} +1 -1
- package/dist/gateway/static/root/assets/channels-status-swr-5rNVq7iI.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-BRrL2iHA.js → chat-terminal-dock-Dr6Rq2ln.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-DLBr5nre.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-Bl-2DzBQ.js → cron-expression-BiXrpzmo.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-CxTl6Wlz.js → date-picker-BPuRtwKt.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-DSl0mOPa.js → dependency-picker-BNC_W7wI.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-DTeCmCdb.js → desktop-pet-DzOpt5nI.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BNebxg0V.js → desktop-pet-settings-BW0brCvH.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-Dn9XpmXY.js → directory-picker-path-field-Baml0uTS.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-D-J-eOTb.js → extension-debug-page-CBXyKmfS.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CpST24nU.js → extension-page-BBhcr_SZ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-4nQXFnFq.js → extension-settings-page-4rwWpN9_.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-BHWHduDi.js → gateway-config-api-Dg-BlBe4.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-yUxMMVjK.js → gateway-config-swr-Du0MvK9s.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-BimMKmkM.js → gateway-settings-BOuYZOYe.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-9mrsL84j.js → gateway-startup-retry-JbjcHCaN.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-MUJ3mEC9.js → heartbeat-settings-Dq4YAlSx.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-DSM6aPHF.js → home-page-BIXkO0Ck.js} +1 -1
- package/dist/gateway/static/root/assets/{image-generation-api-CgFAGDi8.js → image-generation-api-G2tfPvKP.js} +1 -1
- package/dist/gateway/static/root/assets/{index-B3zYJBhK.js → index-Csccu8sa.js} +11 -11
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-6Ar5rfX4.js → keyboard-shortcuts-settings-L1Vtxgp9.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-tzM0wTL8.js → local-app-workbench-page-D-eacBcO.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-B5n-x544.js → local-apps-page--thlkBLS.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-CPylQjH9.js → locale-store-DqJz-cOR.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-CgoQlera.js → logs-page-BRCglHvd.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-CXBLyU-0.js → management-settings-p55fR4XO.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-CtmQemJi.js → markdown-split-DwMcRlBR.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-CUsob4Pz.js → markdown-view-CTB9u15e.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Dsd-IEOW.js → media-plugins-O6H3GZn7.js} +1 -1
- package/dist/gateway/static/root/assets/{messages-B82nsi9k.js → messages-CeydamsI.js} +3 -3
- package/dist/gateway/static/root/assets/{notes-api-CfKZYrBC.js → notes-api-CrjQbmk1.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-BKbOTE2n.js → notes-page-miO9ig9C.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-workbench-BScELo01.js → notes-workbench-_13lmvmF.js} +2 -2
- package/dist/gateway/static/root/assets/{product-open-page-DqB9bsDB.js → product-open-page-BOu07nXf.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-DUoyty8X.js → project-detail-page-BStRkOQr.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-PeXUdGdO.js → projects-page-CY03RxVr.js} +1 -1
- package/dist/gateway/static/root/assets/{registry-api-B_5D8epF.js → registry-api-Bf_HDLUJ.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-sHho-uXP.js → remote-access-hub-B19llkld.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DBTH_t0O.js → runtime-tools-settings-panel-DthuRqUH.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CqMKAwV0.js → schema-form-8W8PhXxa.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-DyvNgaP9.js → sessions-page-BDA2qbTd.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BONIDX4v.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-dPriuuYq.js → settings-form-section-CrsKGYiG.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-B-Mbm8Va.js → settings-loading-skeleton-WJtI0AAq.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-Dyj3w-Ml.js → settings-page-PCjwRF47.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-C4FxY5J3.js → setup-status-panel-D65CwlNC.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-emEdx7YL.js → share-preview-page-BGtvLLeZ.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-BQBVq-sN.js → shares-settings-CdzVKrBl.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CsRWid5h.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-BNtYnrRT.js → skills-page-C_npyryI.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-DjnbNFs5.js → skills-page.utils-C46Sd78k.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-DDStf-jZ.js → system-settings-panel-DomTLwki.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-ZVwr8KbS.js → task-detail-page-B6YFX7kK.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-BN-32Fz5.js → theme-store-Ce7wq__X.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-C2mKZ-ua.js → use-autosave-Do9mCRcY.js} +1 -1
- package/dist/gateway/static/root/assets/{user-context-page-CHjIinCW.js → user-context-page-CiCQA40E.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-D7OHeQby.js → voice-api-key-field-Bc5p-0tX.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CIiXie7F.js → work-discovery-overlay-BieqsmT1.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-9_dAGW3_.js → workflow-run-setup-panel-DVj8iYvm.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-DXpYJxao.js → workflows-page-AG04TTuH.js} +1 -1
- package/dist/gateway/static/root/index.html +10 -10
- package/dist/package.js +1 -1
- package/dist/src/agent/embedded/run-turn.js +2 -0
- package/dist/src/agent/mcp/bundle-mcp-config.d.ts +9 -1
- package/dist/src/agent/mcp/bundle-mcp-config.js +11 -15
- package/dist/src/agent/mcp/embedded-mcp.d.ts +1 -1
- package/dist/src/agent/mcp/index.d.ts +1 -0
- package/dist/src/agent/mcp/index.js +7 -1
- package/dist/src/agent/mcp/mcp-http.d.ts +4 -0
- package/dist/src/agent/mcp/mcp-http.js +25 -1
- package/dist/src/agent/mcp/mcp-transport-config.d.ts +4 -0
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -0
- package/dist/src/agent/mcp/mcp-transport.d.ts +7 -1
- package/dist/src/agent/mcp/mcp-transport.js +38 -11
- package/dist/src/agent/mcp/oauth/index.d.ts +6 -0
- package/dist/src/agent/mcp/oauth/index.js +6 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-errors.d.ts +5 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-errors.js +14 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-manager.d.ts +25 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-manager.js +219 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-provider.d.ts +33 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-provider.js +103 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-session.d.ts +29 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-session.js +169 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-store.d.ts +9 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +79 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-types.d.ts +22 -0
- package/dist/src/agent/mcp/oauth/mcp-oauth-types.js +1 -0
- package/dist/src/agent/memory/builtin-provider.js +23 -4
- package/dist/src/agent/memory/compaction-promotion.d.ts +18 -0
- package/dist/src/agent/memory/compaction-promotion.js +211 -0
- package/dist/src/agent/memory/context/types.d.ts +5 -0
- package/dist/src/agent/memory/manager.d.ts +3 -0
- package/dist/src/agent/memory/manager.js +12 -2
- package/dist/src/agent/memory/trusted-recall.d.ts +7 -0
- package/dist/src/agent/memory/trusted-recall.js +53 -0
- package/dist/src/agent/memory/turn-provenance.d.ts +14 -0
- package/dist/src/agent/memory/turn-provenance.js +60 -0
- package/dist/src/agent/memory/types.d.ts +18 -3
- package/dist/src/agent/memory/user-context-coordinator.js +57 -6
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +2 -0
- package/dist/src/agent/tools/memory-tool.js +5 -1
- package/dist/src/capabilities/store-connector.js +99 -10
- 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-marketplace.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/config/config-mutation.d.ts +14 -0
- package/dist/src/config/config-mutation.js +33 -0
- package/dist/src/config/index.js +3 -3
- package/dist/src/config/paths.d.ts +2 -0
- package/dist/src/config/paths.js +5 -1
- package/dist/src/config/schema.d.ts +17 -0
- package/dist/src/config/schema.js +26 -2
- package/dist/src/connectors/auth-provider-registry.d.ts +1 -1
- package/dist/src/connectors/auth-provider-registry.js +23 -2
- package/dist/src/connectors/install.js +3 -3
- package/dist/src/connectors/instances.d.ts +2 -1
- package/dist/src/connectors/instances.js +15 -5
- package/dist/src/connectors/materialize.d.ts +1 -0
- package/dist/src/connectors/materialize.js +9 -1
- package/dist/src/connectors/runtime-adapter-registry.js +1 -0
- package/dist/src/connectors/types.d.ts +4 -1
- package/dist/src/extensions/connector-dependencies.d.ts +10 -0
- package/dist/src/extensions/connector-dependencies.js +65 -0
- package/dist/src/extensions/install.js +27 -0
- package/dist/src/extensions/normalize-manifest.js +1 -0
- package/dist/src/extensions/sdk/index.js +1 -1
- package/dist/src/extensions/types/manifest.d.ts +2 -0
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/routes/capabilities.js +8 -8
- package/dist/src/gateway/hono/routes/connectors.js +87 -55
- package/dist/src/gateway/hono/routes/mcp.js +77 -5
- package/dist/src/gateway/hono/routes/voice.js +1 -1
- package/dist/src/gateway/service.js +8 -8
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/knowledge/connected-knowledge-pipeline.js +26 -4
- package/dist/src/session/store.js +27 -0
- package/dist/src/storage/sqlite/memory-records-repository.d.ts +9 -1
- package/dist/src/storage/sqlite/memory-records-repository.js +40 -6
- package/dist/src/storage/sqlite/migrations/134_memory_provenance.sql +18 -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/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/user-context/planner.js +8 -3
- package/package.json +2 -2
- package/dist/gateway/static/root/assets/channels-status-swr-DMxB7slL.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-fmda2NEP.js +0 -2
- package/dist/gateway/static/root/assets/settings-advanced-gate-CnYf1R7z.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BFoEpQ4I.js +0 -1
- package/dist/src/extensions/bundle-mcp.d.ts +0 -18
- package/dist/src/extensions/bundle-mcp.js +0 -69
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { McpAuthorizationRequiredError } from "./mcp-oauth-errors.js";
|
|
2
|
+
import { McpOAuthStore } from "./mcp-oauth-store.js";
|
|
3
|
+
//#region src/agent/mcp/oauth/mcp-oauth-provider.ts
|
|
4
|
+
var XopcMcpOAuthClientProvider = class {
|
|
5
|
+
store;
|
|
6
|
+
codeVerifierValue;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
this.store = options.store ?? new McpOAuthStore();
|
|
10
|
+
}
|
|
11
|
+
get redirectUrl() {
|
|
12
|
+
return this.options.interaction?.redirectUrl ?? new URL("http://127.0.0.1/oauth/callback");
|
|
13
|
+
}
|
|
14
|
+
get clientMetadata() {
|
|
15
|
+
return {
|
|
16
|
+
client_name: "XOPC",
|
|
17
|
+
client_uri: "https://xopc.ai",
|
|
18
|
+
redirect_uris: [this.redirectUrl.toString()],
|
|
19
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
20
|
+
response_types: ["code"],
|
|
21
|
+
token_endpoint_auth_method: "none"
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
state() {
|
|
25
|
+
return this.options.interaction?.state;
|
|
26
|
+
}
|
|
27
|
+
async clientInformation() {
|
|
28
|
+
if (this.options.clientId) return { client_id: this.options.clientId };
|
|
29
|
+
return (await this.store.load(this.options.serverUrl))?.clientInformation;
|
|
30
|
+
}
|
|
31
|
+
async saveClientInformation(clientInformation) {
|
|
32
|
+
await this.store.update(this.options.serverUrl, (current) => ({
|
|
33
|
+
...current,
|
|
34
|
+
version: 1,
|
|
35
|
+
serverUrl: this.options.serverUrl.toString(),
|
|
36
|
+
clientInformation,
|
|
37
|
+
updatedAt: current?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
async tokens() {
|
|
41
|
+
return (await this.store.load(this.options.serverUrl))?.tokens;
|
|
42
|
+
}
|
|
43
|
+
async saveTokens(tokens) {
|
|
44
|
+
await this.store.update(this.options.serverUrl, (current) => ({
|
|
45
|
+
...current,
|
|
46
|
+
version: 1,
|
|
47
|
+
serverUrl: this.options.serverUrl.toString(),
|
|
48
|
+
tokens,
|
|
49
|
+
tokensSavedAt: Date.now(),
|
|
50
|
+
updatedAt: current?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
async redirectToAuthorization(authorizationUrl) {
|
|
54
|
+
if (!this.options.interaction) throw new McpAuthorizationRequiredError();
|
|
55
|
+
await this.options.interaction.onRedirect(authorizationUrl);
|
|
56
|
+
}
|
|
57
|
+
saveCodeVerifier(codeVerifier) {
|
|
58
|
+
this.codeVerifierValue = codeVerifier;
|
|
59
|
+
}
|
|
60
|
+
codeVerifier() {
|
|
61
|
+
if (!this.codeVerifierValue) throw new Error("MCP OAuth code verifier is unavailable");
|
|
62
|
+
return this.codeVerifierValue;
|
|
63
|
+
}
|
|
64
|
+
async saveDiscoveryState(discoveryState) {
|
|
65
|
+
await this.store.update(this.options.serverUrl, (current) => {
|
|
66
|
+
const authorizationServerChanged = Boolean(current?.discoveryState?.authorizationServerUrl && current.discoveryState.authorizationServerUrl !== discoveryState.authorizationServerUrl);
|
|
67
|
+
return {
|
|
68
|
+
...current,
|
|
69
|
+
version: 1,
|
|
70
|
+
serverUrl: this.options.serverUrl.toString(),
|
|
71
|
+
discoveryState,
|
|
72
|
+
clientInformation: authorizationServerChanged ? void 0 : current?.clientInformation,
|
|
73
|
+
tokens: authorizationServerChanged ? void 0 : current?.tokens,
|
|
74
|
+
tokensSavedAt: authorizationServerChanged ? void 0 : current?.tokensSavedAt,
|
|
75
|
+
updatedAt: current?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async discoveryState() {
|
|
80
|
+
return (await this.store.load(this.options.serverUrl))?.discoveryState;
|
|
81
|
+
}
|
|
82
|
+
async invalidateCredentials(scope) {
|
|
83
|
+
if (scope === "verifier") {
|
|
84
|
+
this.codeVerifierValue = void 0;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
await this.store.update(this.options.serverUrl, (current) => {
|
|
88
|
+
if (!current) return void 0;
|
|
89
|
+
if (scope === "all") return void 0;
|
|
90
|
+
return {
|
|
91
|
+
...current,
|
|
92
|
+
...scope === "client" ? { clientInformation: void 0 } : {},
|
|
93
|
+
...scope === "tokens" ? {
|
|
94
|
+
tokens: void 0,
|
|
95
|
+
tokensSavedAt: void 0
|
|
96
|
+
} : {},
|
|
97
|
+
...scope === "discovery" ? { discoveryState: void 0 } : {}
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
//#endregion
|
|
103
|
+
export { XopcMcpOAuthClientProvider };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { McpOAuthSessionSnapshot } from './mcp-oauth-types.js';
|
|
2
|
+
export declare class McpOAuthSession {
|
|
3
|
+
readonly serverId: string;
|
|
4
|
+
readonly serverUrl: URL;
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly state: string;
|
|
7
|
+
readonly createdAt: number;
|
|
8
|
+
readonly expiresAt: number;
|
|
9
|
+
private statusValue;
|
|
10
|
+
private authorizationUrlValue?;
|
|
11
|
+
private errorValue?;
|
|
12
|
+
private callbackServer?;
|
|
13
|
+
private redirectUrlValue?;
|
|
14
|
+
private settleCode?;
|
|
15
|
+
private callbackConsumed;
|
|
16
|
+
private readonly codePromise;
|
|
17
|
+
private timeout?;
|
|
18
|
+
constructor(serverId: string, serverUrl: URL, ttlMs?: number);
|
|
19
|
+
get redirectUrl(): URL;
|
|
20
|
+
start(): Promise<void>;
|
|
21
|
+
setAuthorizationUrl(url: URL): void;
|
|
22
|
+
waitForCode(): Promise<string>;
|
|
23
|
+
complete(): void;
|
|
24
|
+
fail(error: unknown): void;
|
|
25
|
+
cancel(): void;
|
|
26
|
+
snapshot(): McpOAuthSessionSnapshot;
|
|
27
|
+
close(): Promise<void>;
|
|
28
|
+
private closeServer;
|
|
29
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { randomBytes, randomUUID } from "node:crypto";
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
//#region src/agent/mcp/oauth/mcp-oauth-session.ts
|
|
4
|
+
const CALLBACK_PATH = "/oauth/callback";
|
|
5
|
+
const DEFAULT_SESSION_TTL_MS = 600 * 1e3;
|
|
6
|
+
function callbackPage(title, message) {
|
|
7
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>${title}</title></head><body><h1>${title}</h1><p>${message}</p></body></html>`;
|
|
8
|
+
}
|
|
9
|
+
var McpOAuthSession = class {
|
|
10
|
+
id = `mcp_oauth_${randomUUID()}`;
|
|
11
|
+
state = randomBytes(24).toString("base64url");
|
|
12
|
+
createdAt = Date.now();
|
|
13
|
+
expiresAt;
|
|
14
|
+
statusValue = "starting";
|
|
15
|
+
authorizationUrlValue;
|
|
16
|
+
errorValue;
|
|
17
|
+
callbackServer;
|
|
18
|
+
redirectUrlValue;
|
|
19
|
+
settleCode;
|
|
20
|
+
callbackConsumed = false;
|
|
21
|
+
codePromise;
|
|
22
|
+
timeout;
|
|
23
|
+
constructor(serverId, serverUrl, ttlMs = DEFAULT_SESSION_TTL_MS) {
|
|
24
|
+
this.serverId = serverId;
|
|
25
|
+
this.serverUrl = serverUrl;
|
|
26
|
+
this.expiresAt = this.createdAt + ttlMs;
|
|
27
|
+
this.codePromise = new Promise((resolve) => {
|
|
28
|
+
this.settleCode = resolve;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
get redirectUrl() {
|
|
32
|
+
if (!this.redirectUrlValue) throw new Error("MCP OAuth callback server has not started");
|
|
33
|
+
return this.redirectUrlValue;
|
|
34
|
+
}
|
|
35
|
+
async start() {
|
|
36
|
+
if (this.callbackServer) return;
|
|
37
|
+
const server = createServer((request, response) => {
|
|
38
|
+
response.setHeader("content-type", "text/html; charset=utf-8");
|
|
39
|
+
response.setHeader("cache-control", "no-store");
|
|
40
|
+
response.setHeader("referrer-policy", "no-referrer");
|
|
41
|
+
response.setHeader("x-content-type-options", "nosniff");
|
|
42
|
+
try {
|
|
43
|
+
const callback = new URL(request.url ?? "", "http://127.0.0.1");
|
|
44
|
+
if (callback.pathname !== CALLBACK_PATH) {
|
|
45
|
+
response.statusCode = 404;
|
|
46
|
+
response.end(callbackPage("Not found", "This is not an XOPC OAuth callback."));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (callback.searchParams.get("state") !== this.state) {
|
|
50
|
+
response.statusCode = 400;
|
|
51
|
+
response.end(callbackPage("Authorization failed", "MCP OAuth state mismatch"));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (this.callbackConsumed) {
|
|
55
|
+
response.statusCode = 409;
|
|
56
|
+
response.end(callbackPage("Authorization already handled", "Return to XOPC to continue."));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const oauthError = callback.searchParams.get("error");
|
|
60
|
+
const code = callback.searchParams.get("code");
|
|
61
|
+
if (oauthError || !code) {
|
|
62
|
+
const error = /* @__PURE__ */ new Error(oauthError === "access_denied" ? "Authorization was denied" : "Authorization code is missing");
|
|
63
|
+
response.statusCode = 400;
|
|
64
|
+
response.end(callbackPage("Authorization failed", error.message));
|
|
65
|
+
this.fail(error);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.callbackConsumed = true;
|
|
69
|
+
this.statusValue = "exchanging_code";
|
|
70
|
+
response.statusCode = 200;
|
|
71
|
+
response.end(callbackPage("Authorization complete", "Return to XOPC to finish connecting the MCP server."));
|
|
72
|
+
this.settleCode?.({ code });
|
|
73
|
+
this.settleCode = void 0;
|
|
74
|
+
} catch {
|
|
75
|
+
const error = /* @__PURE__ */ new Error("MCP OAuth callback could not be processed");
|
|
76
|
+
response.statusCode = 500;
|
|
77
|
+
response.end(callbackPage("Authorization failed", error.message));
|
|
78
|
+
this.fail(error);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
this.callbackServer = server;
|
|
82
|
+
try {
|
|
83
|
+
this.redirectUrlValue = await new Promise((resolve, reject) => {
|
|
84
|
+
server.once("error", reject);
|
|
85
|
+
server.listen(0, "127.0.0.1", () => {
|
|
86
|
+
server.removeListener("error", reject);
|
|
87
|
+
const address = server.address();
|
|
88
|
+
if (!address || typeof address === "string") {
|
|
89
|
+
reject(/* @__PURE__ */ new Error("MCP OAuth callback server did not expose a TCP port"));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
resolve(new URL(`http://127.0.0.1:${address.port}${CALLBACK_PATH}`));
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
} catch (error) {
|
|
96
|
+
this.callbackServer = void 0;
|
|
97
|
+
server.close();
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
this.timeout = setTimeout(() => {
|
|
101
|
+
this.statusValue = "expired";
|
|
102
|
+
this.errorValue = "MCP OAuth session expired";
|
|
103
|
+
this.settleCode?.({ error: new Error(this.errorValue) });
|
|
104
|
+
this.settleCode = void 0;
|
|
105
|
+
this.closeServer();
|
|
106
|
+
}, Math.max(1, this.expiresAt - Date.now()));
|
|
107
|
+
this.timeout.unref?.();
|
|
108
|
+
}
|
|
109
|
+
setAuthorizationUrl(url) {
|
|
110
|
+
this.authorizationUrlValue = url.toString();
|
|
111
|
+
this.statusValue = "waiting_browser";
|
|
112
|
+
}
|
|
113
|
+
async waitForCode() {
|
|
114
|
+
const result = await this.codePromise;
|
|
115
|
+
if (result.error) throw result.error;
|
|
116
|
+
if (!result.code) throw new Error("MCP OAuth authorization code is unavailable");
|
|
117
|
+
return result.code;
|
|
118
|
+
}
|
|
119
|
+
complete() {
|
|
120
|
+
this.statusValue = "connected";
|
|
121
|
+
this.errorValue = void 0;
|
|
122
|
+
this.closeServer();
|
|
123
|
+
}
|
|
124
|
+
fail(error) {
|
|
125
|
+
this.statusValue = "failed";
|
|
126
|
+
this.errorValue = error instanceof Error ? error.message : String(error);
|
|
127
|
+
this.settleCode?.({ error: error instanceof Error ? error : new Error(String(error)) });
|
|
128
|
+
this.settleCode = void 0;
|
|
129
|
+
this.closeServer();
|
|
130
|
+
}
|
|
131
|
+
cancel() {
|
|
132
|
+
if ([
|
|
133
|
+
"connected",
|
|
134
|
+
"failed",
|
|
135
|
+
"expired",
|
|
136
|
+
"cancelled"
|
|
137
|
+
].includes(this.statusValue)) return;
|
|
138
|
+
this.statusValue = "cancelled";
|
|
139
|
+
this.settleCode?.({ error: /* @__PURE__ */ new Error("MCP OAuth session cancelled") });
|
|
140
|
+
this.settleCode = void 0;
|
|
141
|
+
this.closeServer();
|
|
142
|
+
}
|
|
143
|
+
snapshot() {
|
|
144
|
+
return {
|
|
145
|
+
id: this.id,
|
|
146
|
+
serverId: this.serverId,
|
|
147
|
+
serverUrl: this.serverUrl.toString(),
|
|
148
|
+
status: this.statusValue,
|
|
149
|
+
authorizationUrl: this.authorizationUrlValue,
|
|
150
|
+
error: this.errorValue,
|
|
151
|
+
createdAt: this.createdAt,
|
|
152
|
+
expiresAt: this.expiresAt
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async close() {
|
|
156
|
+
this.cancel();
|
|
157
|
+
await this.closeServer();
|
|
158
|
+
}
|
|
159
|
+
async closeServer() {
|
|
160
|
+
if (this.timeout) clearTimeout(this.timeout);
|
|
161
|
+
this.timeout = void 0;
|
|
162
|
+
const server = this.callbackServer;
|
|
163
|
+
this.callbackServer = void 0;
|
|
164
|
+
if (!server) return;
|
|
165
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
//#endregion
|
|
169
|
+
export { McpOAuthSession };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { McpOAuthRecord } from './mcp-oauth-types.js';
|
|
2
|
+
export declare function canonicalMcpServerUrl(input: string | URL): string;
|
|
3
|
+
export declare function mcpOAuthServerKey(input: string | URL): string;
|
|
4
|
+
export declare class McpOAuthStore {
|
|
5
|
+
pathFor(serverUrl: string | URL): string;
|
|
6
|
+
load(serverUrlInput: string | URL): Promise<McpOAuthRecord | undefined>;
|
|
7
|
+
update(serverUrlInput: string | URL, update: (current: McpOAuthRecord | undefined) => McpOAuthRecord | undefined): Promise<McpOAuthRecord | undefined>;
|
|
8
|
+
delete(serverUrl: string | URL): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { init_paths, resolveMcpOAuthPath } from "../../../config/paths.js";
|
|
2
|
+
import { init_write_file_atomic, writeTextAtomic } from "../../../infra/write-file-atomic.js";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { readFile, rm } from "node:fs/promises";
|
|
5
|
+
//#region src/agent/mcp/oauth/mcp-oauth-store.ts
|
|
6
|
+
init_paths();
|
|
7
|
+
init_write_file_atomic();
|
|
8
|
+
const writeTails = /* @__PURE__ */ new Map();
|
|
9
|
+
function canonicalMcpServerUrl(input) {
|
|
10
|
+
const url = input instanceof URL ? new URL(input) : new URL(input);
|
|
11
|
+
url.hash = "";
|
|
12
|
+
return url.toString();
|
|
13
|
+
}
|
|
14
|
+
function mcpOAuthServerKey(input) {
|
|
15
|
+
return createHash("sha256").update(canonicalMcpServerUrl(input)).digest("hex");
|
|
16
|
+
}
|
|
17
|
+
function isStoredRecord(value, serverUrl) {
|
|
18
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
19
|
+
const record = value;
|
|
20
|
+
if (record.version !== 1 || record.serverUrl !== serverUrl || typeof record.updatedAt !== "string") return false;
|
|
21
|
+
if (record.tokens !== void 0) {
|
|
22
|
+
const tokens = record.tokens;
|
|
23
|
+
if (typeof tokens.access_token !== "string" || typeof tokens.token_type !== "string") return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
async function serializeWrite(key, operation) {
|
|
28
|
+
const previous = writeTails.get(key) ?? Promise.resolve();
|
|
29
|
+
let release;
|
|
30
|
+
const gate = new Promise((resolve) => {
|
|
31
|
+
release = resolve;
|
|
32
|
+
});
|
|
33
|
+
const tail = previous.catch(() => void 0).then(() => gate);
|
|
34
|
+
writeTails.set(key, tail);
|
|
35
|
+
await previous.catch(() => void 0);
|
|
36
|
+
try {
|
|
37
|
+
return await operation();
|
|
38
|
+
} finally {
|
|
39
|
+
release();
|
|
40
|
+
if (writeTails.get(key) === tail) writeTails.delete(key);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
var McpOAuthStore = class {
|
|
44
|
+
pathFor(serverUrl) {
|
|
45
|
+
return resolveMcpOAuthPath(mcpOAuthServerKey(serverUrl));
|
|
46
|
+
}
|
|
47
|
+
async load(serverUrlInput) {
|
|
48
|
+
const serverUrl = canonicalMcpServerUrl(serverUrlInput);
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(await readFile(this.pathFor(serverUrl), "utf8"));
|
|
51
|
+
return isStoredRecord(parsed, serverUrl) ? parsed : void 0;
|
|
52
|
+
} catch {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async update(serverUrlInput, update) {
|
|
57
|
+
const serverUrl = canonicalMcpServerUrl(serverUrlInput);
|
|
58
|
+
return serializeWrite(mcpOAuthServerKey(serverUrl), async () => {
|
|
59
|
+
const next = update(await this.load(serverUrl));
|
|
60
|
+
if (!next) {
|
|
61
|
+
await rm(this.pathFor(serverUrl), { force: true });
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const normalized = {
|
|
65
|
+
...next,
|
|
66
|
+
version: 1,
|
|
67
|
+
serverUrl,
|
|
68
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
69
|
+
};
|
|
70
|
+
await writeTextAtomic(this.pathFor(serverUrl), JSON.stringify(normalized, null, 2));
|
|
71
|
+
return normalized;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async delete(serverUrl) {
|
|
75
|
+
await this.update(serverUrl, () => void 0);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
//#endregion
|
|
79
|
+
export { McpOAuthStore, canonicalMcpServerUrl, mcpOAuthServerKey };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { OAuthDiscoveryState } from '@modelcontextprotocol/sdk/client/auth.js';
|
|
2
|
+
import type { OAuthClientInformationMixed, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
3
|
+
export type McpOAuthRecord = {
|
|
4
|
+
version: 1;
|
|
5
|
+
serverUrl: string;
|
|
6
|
+
clientInformation?: OAuthClientInformationMixed;
|
|
7
|
+
discoveryState?: OAuthDiscoveryState;
|
|
8
|
+
tokens?: OAuthTokens;
|
|
9
|
+
tokensSavedAt?: number;
|
|
10
|
+
updatedAt: string;
|
|
11
|
+
};
|
|
12
|
+
export type McpOAuthSessionStatus = 'starting' | 'waiting_browser' | 'exchanging_code' | 'connected' | 'failed' | 'expired' | 'cancelled';
|
|
13
|
+
export type McpOAuthSessionSnapshot = {
|
|
14
|
+
id: string;
|
|
15
|
+
serverId: string;
|
|
16
|
+
serverUrl: string;
|
|
17
|
+
status: McpOAuthSessionStatus;
|
|
18
|
+
authorizationUrl?: string;
|
|
19
|
+
error?: string;
|
|
20
|
+
createdAt: number;
|
|
21
|
+
expiresAt: number;
|
|
22
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { init_agent_session_key, normalizeAgentId } from "../../routing/agent-session-key.js";
|
|
2
2
|
import { appendMemorySignal, deleteMemoryRecord, getMemoryRecord, listMemoryRecords, searchMemoryRecords, upsertMemoryRecord } from "../../storage/sqlite/memory-records-repository.js";
|
|
3
3
|
import "../../storage/sqlite/index.js";
|
|
4
|
+
import { resolveMemorySessionKind } from "./turn-provenance.js";
|
|
4
5
|
//#region src/agent/memory/builtin-provider.ts
|
|
5
6
|
init_agent_session_key();
|
|
6
7
|
/**
|
|
@@ -44,7 +45,8 @@ var BuiltinMemoryProvider = class {
|
|
|
44
45
|
unscopedWorkspaceOnly: request.scope?.workspaceId == null,
|
|
45
46
|
kinds: request.kinds,
|
|
46
47
|
maxResults: request.maxResults,
|
|
47
|
-
minScore: request.minScore
|
|
48
|
+
minScore: request.minScore,
|
|
49
|
+
trustedOnly: request.trustedOnly
|
|
48
50
|
};
|
|
49
51
|
const [active, shadow] = [searchMemoryRecords(options), searchMemoryRecords({
|
|
50
52
|
...options,
|
|
@@ -90,10 +92,13 @@ var BuiltinMemoryProvider = class {
|
|
|
90
92
|
});
|
|
91
93
|
}
|
|
92
94
|
async write(request) {
|
|
95
|
+
const sourceAgentId = normalizeAgentId(request.sourceAgentId ?? "main");
|
|
96
|
+
const sourceSessionId = request.provenance?.sourceSessionId ?? request.scope?.sessionKey;
|
|
97
|
+
const originClass = request.confirmed ? "owner" : request.provenance?.originClass ?? "agent";
|
|
93
98
|
const record = upsertMemoryRecord({
|
|
94
99
|
providerId: this.id,
|
|
95
100
|
kind: request.kind,
|
|
96
|
-
sourceAgentId
|
|
101
|
+
sourceAgentId,
|
|
97
102
|
workspaceId: request.scope?.workspaceId,
|
|
98
103
|
sessionKey: request.scope?.sessionKey,
|
|
99
104
|
projectId: request.scope?.projectId,
|
|
@@ -117,7 +122,14 @@ var BuiltinMemoryProvider = class {
|
|
|
117
122
|
reviewAfter: request.reviewAfter,
|
|
118
123
|
expiresAt: request.expiresAt,
|
|
119
124
|
supersedesRecordId: request.supersedesRecordId,
|
|
120
|
-
conflictGroupId: request.conflictGroupId
|
|
125
|
+
conflictGroupId: request.conflictGroupId,
|
|
126
|
+
originClass,
|
|
127
|
+
sessionKind: request.provenance?.sessionKind ?? (sourceSessionId ? resolveMemorySessionKind(sourceSessionId) : "unknown"),
|
|
128
|
+
observedAt: request.provenance?.observedAt,
|
|
129
|
+
sourceSessionId,
|
|
130
|
+
sourceTurnId: request.provenance?.sourceTurnId,
|
|
131
|
+
supersedesKey: request.provenance?.supersedesKey,
|
|
132
|
+
derivedFromRecalledContext: request.confirmed ? false : request.provenance?.derivedFromRecalledContext
|
|
121
133
|
});
|
|
122
134
|
return {
|
|
123
135
|
success: true,
|
|
@@ -164,7 +176,14 @@ var BuiltinMemoryProvider = class {
|
|
|
164
176
|
reviewAfter: existing.reviewAfter,
|
|
165
177
|
expiresAt: existing.expiresAt,
|
|
166
178
|
supersedesRecordId: existing.supersedesRecordId,
|
|
167
|
-
conflictGroupId: existing.conflictGroupId
|
|
179
|
+
conflictGroupId: existing.conflictGroupId,
|
|
180
|
+
originClass: existing.provenance.originClass,
|
|
181
|
+
sessionKind: existing.provenance.sessionKind,
|
|
182
|
+
observedAt: existing.provenance.observedAt,
|
|
183
|
+
sourceSessionId: existing.provenance.sourceSessionId,
|
|
184
|
+
sourceTurnId: existing.provenance.sourceTurnId,
|
|
185
|
+
supersedesKey: existing.provenance.supersedesKey,
|
|
186
|
+
derivedFromRecalledContext: existing.provenance.derivedFromRecalledContext
|
|
168
187
|
})
|
|
169
188
|
};
|
|
170
189
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CompactionAudit, CompactionHandover } from '../../session/compaction-types.js';
|
|
2
|
+
import type { TranscriptSourceEntry } from '../../storage/sqlite/transcript-repository.js';
|
|
3
|
+
export interface PromoteCompactionLedgerInput {
|
|
4
|
+
sessionKey: string;
|
|
5
|
+
sessionId: string;
|
|
6
|
+
sourceAgentId: string;
|
|
7
|
+
workspaceId: string;
|
|
8
|
+
projectId?: string;
|
|
9
|
+
handover: CompactionHandover;
|
|
10
|
+
audit: CompactionAudit;
|
|
11
|
+
sourceEntries: readonly TranscriptSourceEntry[];
|
|
12
|
+
}
|
|
13
|
+
export interface PromoteCompactionLedgerResult {
|
|
14
|
+
episodicRecordIds: string[];
|
|
15
|
+
durableRecordIds: string[];
|
|
16
|
+
rejectedRecordIds: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare function promoteCompactionLedger(input: PromoteCompactionLedgerInput): PromoteCompactionLedgerResult;
|