@xopcai/xopc 0.0.222 → 0.0.224
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/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-NItGQmvR.js → activity-store--GBciH10.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DsR_2U9-.js → agent-avatar-dicebear-K7V4XXt7.js} +1 -1
- package/dist/gateway/static/root/assets/agents-BsxTpXyq.js +68 -0
- package/dist/gateway/static/root/assets/{api-53ZXsuyr.js → api-HoIz_ija.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BCzVX09V.js → app-management-settings-panel-xQCmkAHh.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DgSpwqQI.js → appearance-settings-BRoeA4kU.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BXgpBA8w.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-D8o8CP9Y.js → archive-plugin-CteCVsBP.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-BQHcAR6J.js → attachment-load-D7xNA2jB.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-CswK3HFb.js → automations-page-BD1vK7r5.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-wrgf-z7D.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-BlpyTJ1b.js → binary-plugins-C3DaJa0W.js} +1 -1
- package/dist/gateway/static/root/assets/block-editor-lTkcHTve.js +184 -0
- package/dist/gateway/static/root/assets/browser-settings-page-zhzNkeVG.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-Bi6RSSpD.js → browser-workflow-inputs-1UZ0vnIy.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-CZNOOQY4.js → browser-workflows-page-BHuJOF4M.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-DuCmg2Ej.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-pC2fno7r.js → capability-presets-api-yNqTIuyd.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DjiP3mQQ.js +3 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-B5Szgu_z.js → channel-recipient-api-krezGsKc.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-B4AtvQHk.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-DMxB7slL.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-2fpzufzt.js → chat-terminal-dock-BRrL2iHA.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-fmda2NEP.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-VePLfPUR.js → cron-expression-Bl-2DzBQ.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-CJegmPTJ.js → date-picker-CxTl6Wlz.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-B2o9unBk.js → dependency-picker-DSl0mOPa.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-BH4Np-ay.js → desktop-pet-DTeCmCdb.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-Duu3ctxD.js → desktop-pet-settings-BNebxg0V.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-BBCUZOg2.js → directory-picker-path-field-Dn9XpmXY.js} +1 -1
- package/dist/gateway/static/root/assets/dist-DaxPZj9e.js +1 -0
- package/dist/gateway/static/root/assets/{dist-DY4Af0fY.js → dist-J_ySZvz0.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DS_o3F97.js → extension-debug-page-D-J-eOTb.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BTLBZdCq.js → extension-page-CpST24nU.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-KTGrYbgk.js → extension-settings-page-4nQXFnFq.js} +1 -1
- package/dist/gateway/static/root/assets/floating-ui.dom-B7uQOZZW.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-api-D3YJVfzY.js → gateway-config-api-BHWHduDi.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-BzTbnu4O.js → gateway-config-swr-yUxMMVjK.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-B8--s3yC.js → gateway-settings-BimMKmkM.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-B2zpkNvi.js → gateway-startup-retry-9mrsL84j.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-MUJ3mEC9.js +1 -0
- package/dist/gateway/static/root/assets/home-page-DSM6aPHF.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-BXRjz-iY.js → image-generation-api-CgFAGDi8.js} +1 -1
- package/dist/gateway/static/root/assets/index-B3zYJBhK.js +74 -0
- package/dist/gateway/static/root/assets/index-D3_xSYKd.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-D-Ib-suu.js → keyboard-shortcuts-settings-6Ar5rfX4.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-tzM0wTL8.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-Bsy1lvAc.js → local-apps-page-B5n-x544.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-iKjqemWG.js → locale-store-CPylQjH9.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-CgoQlera.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-D-akydG4.js → management-settings-CXBLyU-0.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-DHH4Cu2i.js → markdown-split-CtmQemJi.js} +1 -1
- package/dist/gateway/static/root/assets/markdown-view-CUsob4Pz.js +69 -0
- package/dist/gateway/static/root/assets/{media-plugins-BwHtUXkj.js → media-plugins-Dsd-IEOW.js} +1 -1
- package/dist/gateway/static/root/assets/messages-B82nsi9k.js +3 -0
- package/dist/gateway/static/root/assets/notes-api-CfKZYrBC.js +1 -0
- package/dist/gateway/static/root/assets/{notes-page-BxM1p6hz.js → notes-page-BKbOTE2n.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-BScELo01.js +4 -0
- package/dist/gateway/static/root/assets/oauth-authorization-window-Cdolr2wE.js +1 -0
- package/dist/gateway/static/root/assets/{popover-select-BzdnTy3h.js → popover-select-CccGri5Y.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-DrfWH1ir.js → product-open-page-DqB9bsDB.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-DUoyty8X.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-PeXUdGdO.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-Cx3JxXSL.js → registry-api-B_5D8epF.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-sHho-uXP.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DF7syQRd.js → runtime-tools-settings-panel-DBTH_t0O.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-BQ_qRIsM.js → schema-form-CqMKAwV0.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DyvNgaP9.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CnYf1R7z.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-BBHGOQHU.js → settings-form-section-dPriuuYq.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-CiwjP2-b.js → settings-loading-skeleton-B-Mbm8Va.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-Rl9waapk.js → settings-page-Dyj3w-Ml.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-C4FxY5J3.js +1 -0
- package/dist/gateway/static/root/assets/share-preview-page-emEdx7YL.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-BQBVq-sN.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BFoEpQ4I.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-YbtR_zEU.js → skills-page-BNtYnrRT.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-DTmx2Zza.js → skills-page.utils-DjnbNFs5.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-BZDJcKdS.js → system-settings-panel-DDStf-jZ.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-ZVwr8KbS.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-BOD2D0dJ.js → theme-store-BN-32Fz5.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-Be9aR9qA.js → use-autosave-C2mKZ-ua.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-CHjIinCW.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-IMc3Ua6C.js → voice-api-key-field-D7OHeQby.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-TC-xQenr.js → work-discovery-overlay-CIiXie7F.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-B2auxcRv.js → workflow-run-setup-panel-9_dAGW3_.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-DXpYJxao.js +5 -0
- package/dist/gateway/static/root/index.html +15 -14
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-instance-gateway.d.ts +3 -0
- package/dist/src/agent/agent-manager.d.ts +3 -0
- package/dist/src/agent/agent-manager.js +30 -24
- package/dist/src/agent/embedded/index.d.ts +1 -1
- package/dist/src/agent/embedded/index.js +2 -2
- package/dist/src/agent/embedded/run-for-session.js +101 -62
- package/dist/src/agent/embedded/run-turn.js +56 -28
- package/dist/src/agent/embedded/runs.d.ts +16 -29
- package/dist/src/agent/embedded/runs.js +44 -65
- package/dist/src/agent/embedded/types.d.ts +4 -0
- package/dist/src/agent/orchestration/agent-run-supervisor.d.ts +28 -0
- package/dist/src/agent/orchestration/agent-run-supervisor.js +49 -0
- package/dist/src/agent/orchestration/agent-turn-policy.d.ts +18 -0
- package/dist/src/agent/orchestration/agent-turn-policy.js +36 -0
- package/dist/src/agent/orchestration/llm-turn-retry.d.ts +5 -0
- package/dist/src/agent/orchestration/llm-turn-retry.js +34 -4
- package/dist/src/agent/orchestration/run-agent-turn-with-timeout.d.ts +10 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +25 -4
- package/dist/src/agent/service/async-queue.d.ts +16 -3
- package/dist/src/agent/service/async-queue.js +29 -11
- package/dist/src/agent/service/process-direct-streaming.js +27 -4
- package/dist/src/agent/service.js +1 -0
- package/dist/src/agent/tools/exec-command.d.ts +2 -0
- package/dist/src/agent/tools/exec-command.js +70 -7
- package/dist/src/auth/oauth/index.js +3 -3
- package/dist/src/auth/oauth/registry.d.ts +2 -0
- package/dist/src/auth/oauth/registry.js +20 -12
- package/dist/src/auth/oauth/xopc-cloud.d.ts +1 -0
- package/dist/src/auth/oauth/xopc-cloud.js +32 -16
- package/dist/src/cli/commands/channels.js +1 -1
- package/dist/src/cli/commands/connectors.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/commands/tunnel.js +4 -5
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/schema.d.ts +18 -0
- package/dist/src/config/schema.js +19 -1
- package/dist/src/extensions/sdk/index.js +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/hono/app.js +2 -1
- package/dist/src/gateway/hono/oauth-async.d.ts +1 -0
- package/dist/src/gateway/hono/oauth-async.js +11 -4
- package/dist/src/gateway/hono/routes/config.js +10 -0
- package/dist/src/gateway/hono/routes/host-fs.js +40 -1
- package/dist/src/gateway/hono/routes/media.js +33 -1
- package/dist/src/gateway/hono/routes/notes.js +162 -7
- package/dist/src/gateway/hono/routes/shares.js +141 -6
- package/dist/src/gateway/hono/routes/tunnel.js +47 -10
- package/dist/src/gateway/hono/routes/voice.d.ts +2 -6
- package/dist/src/gateway/hono/routes/voice.js +20 -4
- package/dist/src/gateway/hono/routes/workflows.js +2 -2
- package/dist/src/gateway/run-loop.js +3 -0
- package/dist/src/gateway/server.d.ts +3 -0
- package/dist/src/gateway/server.js +30 -5
- package/dist/src/gateway/service.js +4 -4
- package/dist/src/notes/service.d.ts +6 -2
- package/dist/src/notes/service.js +36 -4
- package/dist/src/providers/index.js +2 -2
- package/dist/src/share/note-share-service.d.ts +67 -0
- package/dist/src/share/note-share-service.js +283 -0
- package/dist/src/share/share-config.js +32 -3
- package/dist/src/share/share-landing.d.ts +5 -1
- package/dist/src/share/share-landing.js +28 -1
- package/dist/src/share/share-store.d.ts +34 -5
- package/dist/src/share/share-store.js +125 -19
- package/dist/src/share/share-thumbnail.js +4 -2
- package/dist/src/share/share-types.d.ts +52 -14
- package/dist/src/share/share-types.js +9 -0
- package/dist/src/share/share-zip.d.ts +2 -2
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/tunnel/env.d.ts +12 -6
- package/dist/src/tunnel/env.js +34 -26
- package/dist/src/tunnel/gateway-lifecycle.js +2 -13
- package/dist/src/tunnel/index.d.ts +1 -1
- package/dist/src/tunnel/index.js +2 -2
- package/dist/src/tunnel/tunnel-audit.d.ts +1 -1
- package/dist/src/tunnel/tunnel-config.d.ts +1 -1
- package/dist/src/tunnel/tunnel-config.js +9 -4
- package/dist/src/tunnel/tunnel-service.d.ts +1 -1
- package/dist/src/tunnel/tunnel-service.js +3 -0
- package/dist/src/tunnel/well-known.d.ts +1 -1
- package/dist/src/tunnel/well-known.js +1 -1
- package/dist/src/tunnel/xopc-cloud-registration.d.ts +9 -0
- package/dist/src/tunnel/xopc-cloud-registration.js +42 -0
- package/dist/src/voice/stt/transcribe-core.js +17 -1
- package/dist/src/voice/stt/types.d.ts +1 -1
- package/package.json +2 -2
- package/dist/gateway/static/root/assets/agents-DijFbC4G.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-BFAmf9hq.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-B8us5JBf.js +0 -6
- package/dist/gateway/static/root/assets/block-editor-C3mwGsms.js +0 -184
- package/dist/gateway/static/root/assets/browser-settings-page-BeBd17-3.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-Bv0z3KRq.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-BczD-pWE.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-2KQYq6xl.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-ByRbxC6z.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-PB1boaNy.js +0 -2
- package/dist/gateway/static/root/assets/dist-C230izr8.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-5YQ5BUwp.js +0 -1
- package/dist/gateway/static/root/assets/home-page-DfIVWJl3.js +0 -1
- package/dist/gateway/static/root/assets/index-BXGC3VFm.css +0 -2
- package/dist/gateway/static/root/assets/index-jqDCfet4.js +0 -74
- package/dist/gateway/static/root/assets/local-app-workbench-page-CAb0odzu.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-CFxKbDZl.js +0 -2
- package/dist/gateway/static/root/assets/markdown-view-DYkxMtJA.js +0 -69
- package/dist/gateway/static/root/assets/messages-kx5W39dO.js +0 -3
- package/dist/gateway/static/root/assets/notes-api-DJizatxh.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-BGjEC89c.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-Dj9kEQwg.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CBRy5Ezz.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DSwz9RBh.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-WtattyVX.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CNAz_q1F.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CNo4Ajhn.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-B7PI3yZ6.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-DpOH0zWB.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BOf4xCat.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-DrMX5Yhj.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-ewIK2ddC.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-Bdn82kFQ.js +0 -5
|
@@ -9,11 +9,12 @@ import { init_kimi_coding, kimiCodingOAuthProvider } from "./kimi-coding.js";
|
|
|
9
9
|
import { init_minimax_cn, minimaxCnOAuthProvider } from "./minimax-cn.js";
|
|
10
10
|
import { init_minimax, minimaxOAuthProvider } from "./minimax.js";
|
|
11
11
|
import { init_openai_codex, openaiCodexOAuthProvider } from "./openai-codex.js";
|
|
12
|
-
import { init_xopc_cloud, xopcCloudOAuthProvider } from "./xopc-cloud.js";
|
|
12
|
+
import { init_xopc_cloud, xopcCloudOAuthProvider, xopcTunnelOAuthProvider } from "./xopc-cloud.js";
|
|
13
13
|
//#region src/auth/oauth/registry.ts
|
|
14
|
-
function definition(provider, displayName = provider.name) {
|
|
14
|
+
function definition(provider, purpose, displayName = provider.name) {
|
|
15
15
|
return {
|
|
16
16
|
displayName,
|
|
17
|
+
purpose,
|
|
17
18
|
provider,
|
|
18
19
|
profileId: `${provider.id}:default`,
|
|
19
20
|
urlPrompt: "🌐 Please open this URL in your browser:\n"
|
|
@@ -28,6 +29,9 @@ function getOAuthProviderInterfaces() {
|
|
|
28
29
|
function getOAuthProviderIds() {
|
|
29
30
|
return Object.keys(OAUTH_PROVIDER_DEFINITIONS);
|
|
30
31
|
}
|
|
32
|
+
function getModelOAuthProviderIds() {
|
|
33
|
+
return Object.entries(OAUTH_PROVIDER_DEFINITIONS).filter(([, definition]) => definition.purpose === "models").map(([id]) => id);
|
|
34
|
+
}
|
|
31
35
|
function isOAuthOnlyProvider(provider) {
|
|
32
36
|
return OAUTH_PROVIDER_DEFINITIONS[provider]?.oauthOnly === true;
|
|
33
37
|
}
|
|
@@ -44,22 +48,26 @@ var init_registry = __esmMin((() => {
|
|
|
44
48
|
init_xopc_cloud();
|
|
45
49
|
OAUTH_PROVIDER_DEFINITIONS = {
|
|
46
50
|
"xopc-cloud": {
|
|
47
|
-
...definition(xopcCloudOAuthProvider),
|
|
51
|
+
...definition(xopcCloudOAuthProvider, "models"),
|
|
52
|
+
oauthOnly: true
|
|
53
|
+
},
|
|
54
|
+
"xopc-tunnel": {
|
|
55
|
+
...definition(xopcTunnelOAuthProvider, "tunnel"),
|
|
48
56
|
oauthOnly: true
|
|
49
57
|
},
|
|
50
|
-
anthropic: definition(anthropicOAuthProvider, "Anthropic (Claude)"),
|
|
51
|
-
minimax: definition(minimaxOAuthProvider, "MiniMax (幂维智能)"),
|
|
58
|
+
anthropic: definition(anthropicOAuthProvider, "models", "Anthropic (Claude)"),
|
|
59
|
+
minimax: definition(minimaxOAuthProvider, "models", "MiniMax (幂维智能)"),
|
|
52
60
|
"minimax-cn": {
|
|
53
|
-
...definition(minimaxCnOAuthProvider, "MiniMax CN"),
|
|
61
|
+
...definition(minimaxCnOAuthProvider, "models", "MiniMax CN"),
|
|
54
62
|
urlPrompt: "🌐 请在浏览器中打开以下 URL:\n"
|
|
55
63
|
},
|
|
56
|
-
"kimi-coding": definition(kimiCodingOAuthProvider, "Kimi For Coding (月之暗面)"),
|
|
57
|
-
"github-copilot": definition(githubCopilotOAuthProvider),
|
|
58
|
-
"google-gemini-cli": definition(geminiCliOAuthProvider),
|
|
59
|
-
"google-antigravity": definition(antigravityOAuthProvider),
|
|
60
|
-
"openai-codex": definition(openaiCodexOAuthProvider)
|
|
64
|
+
"kimi-coding": definition(kimiCodingOAuthProvider, "models", "Kimi For Coding (月之暗面)"),
|
|
65
|
+
"github-copilot": definition(githubCopilotOAuthProvider, "models"),
|
|
66
|
+
"google-gemini-cli": definition(geminiCliOAuthProvider, "models"),
|
|
67
|
+
"google-antigravity": definition(antigravityOAuthProvider, "models"),
|
|
68
|
+
"openai-codex": definition(openaiCodexOAuthProvider, "models")
|
|
61
69
|
};
|
|
62
70
|
}));
|
|
63
71
|
//#endregion
|
|
64
72
|
init_registry();
|
|
65
|
-
export { OAUTH_PROVIDER_DEFINITIONS, getOAuthProviderDefinition, getOAuthProviderIds, getOAuthProviderInterfaces, init_registry, isOAuthOnlyProvider };
|
|
73
|
+
export { OAUTH_PROVIDER_DEFINITIONS, getModelOAuthProviderIds, getOAuthProviderDefinition, getOAuthProviderIds, getOAuthProviderInterfaces, init_registry, isOAuthOnlyProvider };
|
|
@@ -213,7 +213,7 @@ function callbackHtml(title, message, tone, returnToAppUrl) {
|
|
|
213
213
|
</body>
|
|
214
214
|
</html>`;
|
|
215
215
|
}
|
|
216
|
-
async function loginWithBrowser(callbacks) {
|
|
216
|
+
async function loginWithBrowser(callbacks, scope) {
|
|
217
217
|
if (callbacks.signal?.aborted) throw callbacks.signal.reason instanceof Error ? callbacks.signal.reason : /* @__PURE__ */ new Error("XOPC OAuth login cancelled");
|
|
218
218
|
const { verifier, challenge } = await generatePKCE();
|
|
219
219
|
const state = randomBytes(24).toString("base64url");
|
|
@@ -274,7 +274,7 @@ async function loginWithBrowser(callbacks) {
|
|
|
274
274
|
response_type: "code",
|
|
275
275
|
client_id: CLIENT_ID,
|
|
276
276
|
redirect_uri: redirectUri,
|
|
277
|
-
scope
|
|
277
|
+
scope,
|
|
278
278
|
code_challenge: challenge,
|
|
279
279
|
code_challenge_method: "S256",
|
|
280
280
|
state,
|
|
@@ -309,7 +309,7 @@ async function loginWithBrowser(callbacks) {
|
|
|
309
309
|
server.close();
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
|
-
async function loginWithDeviceCode(callbacks) {
|
|
312
|
+
async function loginWithDeviceCode(callbacks, scope) {
|
|
313
313
|
const response = await fetch(`${consoleUrl()}/oauth/device_authorization`, {
|
|
314
314
|
method: "POST",
|
|
315
315
|
headers: {
|
|
@@ -318,7 +318,7 @@ async function loginWithDeviceCode(callbacks) {
|
|
|
318
318
|
},
|
|
319
319
|
body: new URLSearchParams({
|
|
320
320
|
client_id: CLIENT_ID,
|
|
321
|
-
scope
|
|
321
|
+
scope,
|
|
322
322
|
device_name: hostname() || "XOPC client",
|
|
323
323
|
client_type: "cli"
|
|
324
324
|
}),
|
|
@@ -353,9 +353,9 @@ async function loginWithDeviceCode(callbacks) {
|
|
|
353
353
|
}
|
|
354
354
|
throw new Error("XOPC OAuth authorization expired");
|
|
355
355
|
}
|
|
356
|
-
async function login(callbacks) {
|
|
356
|
+
async function login(callbacks, options) {
|
|
357
357
|
return await callbacks.onSelect({
|
|
358
|
-
message:
|
|
358
|
+
message: `Choose how to authorize ${options.serviceName}`,
|
|
359
359
|
options: [{
|
|
360
360
|
id: "browser",
|
|
361
361
|
label: "Browser (recommended for this device)"
|
|
@@ -363,7 +363,7 @@ async function login(callbacks) {
|
|
|
363
363
|
id: "device_code",
|
|
364
364
|
label: "Device code (remote or headless)"
|
|
365
365
|
}]
|
|
366
|
-
}) === "device_code" ? loginWithDeviceCode(callbacks) : loginWithBrowser(callbacks);
|
|
366
|
+
}) === "device_code" ? loginWithDeviceCode(callbacks, options.scope) : loginWithBrowser(callbacks, options.scope);
|
|
367
367
|
}
|
|
368
368
|
async function refreshToken(current, signal) {
|
|
369
369
|
const response = await tokenRequest(new URLSearchParams({
|
|
@@ -375,23 +375,39 @@ async function refreshToken(current, signal) {
|
|
|
375
375
|
if (!response.ok) throw new Error(body.error_description ?? body.error ?? "XOPC OAuth refresh failed");
|
|
376
376
|
return credentials(body);
|
|
377
377
|
}
|
|
378
|
-
|
|
378
|
+
function createXopcOAuthProvider(options) {
|
|
379
|
+
return {
|
|
380
|
+
id: options.id,
|
|
381
|
+
name: options.name,
|
|
382
|
+
loginMethods: ["browser", "device_code"],
|
|
383
|
+
login: (callbacks) => login(callbacks, {
|
|
384
|
+
scope: options.scope,
|
|
385
|
+
serviceName: options.name
|
|
386
|
+
}),
|
|
387
|
+
refreshToken,
|
|
388
|
+
getApiKey: (value) => value.access
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
var CLIENT_ID, DEFAULT_CONSOLE_URL, MODEL_SERVICE_SCOPE, TUNNEL_REGISTRATION_SCOPE, CALLBACK_PATH, AUTHORIZATION_TIMEOUT_MS, xopcCloudOAuthProvider, xopcTunnelOAuthProvider;
|
|
379
392
|
var init_xopc_cloud = __esmMin((() => {
|
|
380
393
|
init_pkce();
|
|
381
394
|
CLIENT_ID = "xopc-native";
|
|
382
395
|
DEFAULT_CONSOLE_URL = "https://console.xopc.ai";
|
|
383
|
-
|
|
396
|
+
MODEL_SERVICE_SCOPE = "models:read models:invoke account:usage connectors:read connectors:manage connectors:execute offline_access";
|
|
397
|
+
TUNNEL_REGISTRATION_SCOPE = "tunnel:register";
|
|
384
398
|
CALLBACK_PATH = "/oauth/callback";
|
|
385
399
|
AUTHORIZATION_TIMEOUT_MS = 5 * 6e4;
|
|
386
|
-
xopcCloudOAuthProvider = {
|
|
400
|
+
xopcCloudOAuthProvider = createXopcOAuthProvider({
|
|
387
401
|
id: "xopc-cloud",
|
|
388
402
|
name: "XOPC Model Service",
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
403
|
+
scope: MODEL_SERVICE_SCOPE
|
|
404
|
+
});
|
|
405
|
+
xopcTunnelOAuthProvider = createXopcOAuthProvider({
|
|
406
|
+
id: "xopc-tunnel",
|
|
407
|
+
name: "XOPC Public Tunnel",
|
|
408
|
+
scope: TUNNEL_REGISTRATION_SCOPE
|
|
409
|
+
});
|
|
394
410
|
}));
|
|
395
411
|
//#endregion
|
|
396
412
|
init_xopc_cloud();
|
|
397
|
-
export { init_xopc_cloud, xopcCloudOAuthProvider };
|
|
413
|
+
export { init_xopc_cloud, xopcCloudOAuthProvider, xopcTunnelOAuthProvider };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { buildChannelCatalogForConfig, init_channel_catalog_service } from "../../channels/catalog/channel-catalog-service.js";
|
|
2
2
|
import { init_loader, 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 { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
|
|
2
2
|
import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../capabilities/store-connector.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
|
init_loader();
|
|
8
8
|
function parsePairs(values, option) {
|
|
@@ -13,8 +13,8 @@ import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
|
13
13
|
import { execSync } from "node:child_process";
|
|
14
14
|
import { createHash } from "node:crypto";
|
|
15
15
|
import semver from "semver";
|
|
16
|
-
import { confirm } from "@inquirer/prompts";
|
|
17
16
|
import { Command } from "commander";
|
|
17
|
+
import { confirm } from "@inquirer/prompts";
|
|
18
18
|
//#region src/cli/commands/extension-marketplace.ts
|
|
19
19
|
init_loader();
|
|
20
20
|
init_paths();
|
|
@@ -9,8 +9,8 @@ import { prepareUpdateGlobalDefaults } from "../../gateway/global-defaults-admin
|
|
|
9
9
|
import { disconnectProvider } from "../../providers/provider-disconnect.js";
|
|
10
10
|
import { colors } from "../utils/colors.js";
|
|
11
11
|
import { runCliOAuthLogin } from "../utils/oauth-login.js";
|
|
12
|
-
import { input } from "@inquirer/prompts";
|
|
13
12
|
import { Command } from "commander";
|
|
13
|
+
import { input } from "@inquirer/prompts";
|
|
14
14
|
//#region src/cli/commands/models.ts
|
|
15
15
|
init_credentials();
|
|
16
16
|
init_schema();
|
|
@@ -10,8 +10,8 @@ import { initWorkspace } from "../utils/init-workspace.js";
|
|
|
10
10
|
import { setupModel } from "./onboard/model.js";
|
|
11
11
|
import { getChannelConfigurators } from "./onboard/channels/registry.js";
|
|
12
12
|
import { setupChannels } from "./onboard/channels/index.js";
|
|
13
|
-
import { select } from "@inquirer/prompts";
|
|
14
13
|
import { Command } from "commander";
|
|
14
|
+
import { select } from "@inquirer/prompts";
|
|
15
15
|
//#region src/cli/commands/onboard.ts
|
|
16
16
|
init_schema();
|
|
17
17
|
init_paths_state();
|
|
@@ -38,7 +38,7 @@ function configureTunnel(ctx) {
|
|
|
38
38
|
const brokerUrl = resolveTunnelBrokerUrl(config.tunnel?.brokerUrl);
|
|
39
39
|
getTunnelService().configure({
|
|
40
40
|
brokerUrl,
|
|
41
|
-
registrationSecret: resolveTunnelRegistrationSecret(
|
|
41
|
+
registrationSecret: resolveTunnelRegistrationSecret(brokerUrl, config.tunnel?.registrationSecret),
|
|
42
42
|
autoStart: config.tunnel?.autoStart ?? false,
|
|
43
43
|
gatewayHost: host,
|
|
44
44
|
frpSubdomainHost: resolveFrpSubdomainHost(resolveTunnelBrokerUrl(config.tunnel?.brokerUrl))
|
|
@@ -131,13 +131,12 @@ function createTunnelCommand(ctx) {
|
|
|
131
131
|
});
|
|
132
132
|
console.log("Tunnel security consent recorded.");
|
|
133
133
|
});
|
|
134
|
-
cmd.command("secret").description("Manage tunnel broker registration secret in config").command("set").description("Save tunnel.registrationSecret to xopc.json
|
|
134
|
+
cmd.command("secret").description("Manage tunnel broker registration secret in config").command("set").description("Save tunnel.registrationSecret to xopc.json").argument("[secret]", "Registration secret (prompts securely when omitted in a TTY)").option("--stdin", "Read secret from stdin (single line, trimmed)").action(async (secretArg, opts) => {
|
|
135
135
|
try {
|
|
136
136
|
await saveTunnelRegistrationSecret(ctx, await readTunnelRegistrationSecretFromCli({
|
|
137
137
|
secretArg,
|
|
138
138
|
stdin: opts.stdin
|
|
139
139
|
}));
|
|
140
|
-
if (process.env.XOPC_TUNNEL_REGISTRATION_SECRET?.trim()) console.log("Note: XOPC_TUNNEL_REGISTRATION_SECRET is set in the environment and overrides the saved config at runtime.");
|
|
141
140
|
console.log(`Saved tunnel registration secret to ${ctx.configPath}.`);
|
|
142
141
|
} catch (err) {
|
|
143
142
|
const em = err instanceof Error ? err.message : String(err);
|
|
@@ -227,7 +226,7 @@ function createTunnelCommand(ctx) {
|
|
|
227
226
|
console.log(`# Self-hosted FRP broker sketch for ${domain}`);
|
|
228
227
|
console.log("# 1. Run frps with vhost HTTP/HTTPS and a registration token");
|
|
229
228
|
console.log(`# 2. Point tunnel.brokerUrl to https://${domain}/api`);
|
|
230
|
-
console.log(
|
|
229
|
+
console.log("# 3. Save the broker registration key as tunnel.registrationSecret");
|
|
231
230
|
console.log("");
|
|
232
231
|
console.log(JSON.stringify({
|
|
233
232
|
frps: {
|
|
@@ -237,7 +236,7 @@ function createTunnelCommand(ctx) {
|
|
|
237
236
|
},
|
|
238
237
|
broker: {
|
|
239
238
|
apiUrl: `https://${domain}/api`,
|
|
240
|
-
|
|
239
|
+
registrationSecretConfig: "tunnel.registrationSecret"
|
|
241
240
|
}
|
|
242
241
|
}, null, 2));
|
|
243
242
|
}));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
|
|
2
1
|
import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
|
|
3
2
|
import "../agent-manifest/index.js";
|
|
3
|
+
import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
|
|
4
4
|
import { init_session_key, parseSessionKey } from "../routing/session-key.js";
|
|
5
5
|
import { agentExists, getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
|
|
6
6
|
//#region src/config/agent-profile.ts
|
|
@@ -991,6 +991,15 @@ export declare const GatewayConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
|
991
991
|
listingCacheMs: z.ZodDefault<z.ZodNumber>;
|
|
992
992
|
zipConcurrency: z.ZodDefault<z.ZodNumber>;
|
|
993
993
|
}, z.core.$strip>>;
|
|
994
|
+
note: z.ZodDefault<z.ZodObject<{
|
|
995
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
996
|
+
maxMarkdownBytes: z.ZodDefault<z.ZodNumber>;
|
|
997
|
+
maxAttachmentCount: z.ZodDefault<z.ZodNumber>;
|
|
998
|
+
maxAttachmentSize: z.ZodDefault<z.ZodNumber>;
|
|
999
|
+
maxTotalSize: z.ZodDefault<z.ZodNumber>;
|
|
1000
|
+
assetTicketTtlMs: z.ZodDefault<z.ZodNumber>;
|
|
1001
|
+
revokeOnSourceDelete: z.ZodDefault<z.ZodBoolean>;
|
|
1002
|
+
}, z.core.$strip>>;
|
|
994
1003
|
}, z.core.$strip>>;
|
|
995
1004
|
siteShare: z.ZodOptional<z.ZodObject<{
|
|
996
1005
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -2067,6 +2076,15 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
|
2067
2076
|
listingCacheMs: z.ZodDefault<z.ZodNumber>;
|
|
2068
2077
|
zipConcurrency: z.ZodDefault<z.ZodNumber>;
|
|
2069
2078
|
}, z.core.$strip>>;
|
|
2079
|
+
note: z.ZodDefault<z.ZodObject<{
|
|
2080
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
2081
|
+
maxMarkdownBytes: z.ZodDefault<z.ZodNumber>;
|
|
2082
|
+
maxAttachmentCount: z.ZodDefault<z.ZodNumber>;
|
|
2083
|
+
maxAttachmentSize: z.ZodDefault<z.ZodNumber>;
|
|
2084
|
+
maxTotalSize: z.ZodDefault<z.ZodNumber>;
|
|
2085
|
+
assetTicketTtlMs: z.ZodDefault<z.ZodNumber>;
|
|
2086
|
+
revokeOnSourceDelete: z.ZodDefault<z.ZodBoolean>;
|
|
2087
|
+
}, z.core.$strip>>;
|
|
2070
2088
|
}, z.core.$strip>>;
|
|
2071
2089
|
siteShare: z.ZodOptional<z.ZodObject<{
|
|
2072
2090
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -490,7 +490,7 @@ strict: z.boolean().optional() }).optional();
|
|
|
490
490
|
TunnelConfigSchema = z.object({
|
|
491
491
|
enabled: z.boolean().default(false),
|
|
492
492
|
brokerUrl: z.string().url().default("https://frp.xopc.ai/api"),
|
|
493
|
-
/** Broker register API secret
|
|
493
|
+
/** Broker register API secret. */
|
|
494
494
|
registrationSecret: z.string().min(1).optional(),
|
|
495
495
|
autoStart: z.boolean().default(false),
|
|
496
496
|
subdomain: z.string().optional(),
|
|
@@ -620,6 +620,24 @@ activityDetailDefault: z.enum([
|
|
|
620
620
|
maxDepth: 20,
|
|
621
621
|
listingCacheMs: 6e4,
|
|
622
622
|
zipConcurrency: 1
|
|
623
|
+
}),
|
|
624
|
+
/** Note snapshot-sharing controls. */
|
|
625
|
+
note: z.object({
|
|
626
|
+
enabled: z.boolean().default(true),
|
|
627
|
+
maxMarkdownBytes: z.number().int().min(1024).max(10485760).default(2097152),
|
|
628
|
+
maxAttachmentCount: z.number().int().min(0).max(500).default(50),
|
|
629
|
+
maxAttachmentSize: z.number().int().min(1024).max(1073741824).default(104857600),
|
|
630
|
+
maxTotalSize: z.number().int().min(1024).max(2147483648).default(262144e3),
|
|
631
|
+
assetTicketTtlMs: z.number().int().min(6e4).max(36e5).default(6e5),
|
|
632
|
+
revokeOnSourceDelete: z.boolean().default(true)
|
|
633
|
+
}).default({
|
|
634
|
+
enabled: true,
|
|
635
|
+
maxMarkdownBytes: 2097152,
|
|
636
|
+
maxAttachmentCount: 50,
|
|
637
|
+
maxAttachmentSize: 104857600,
|
|
638
|
+
maxTotalSize: 262144e3,
|
|
639
|
+
assetTicketTtlMs: 6e5,
|
|
640
|
+
revokeOnSourceDelete: true
|
|
623
641
|
})
|
|
624
642
|
}).optional(),
|
|
625
643
|
/** Site-share configuration (static directory or reverse-proxy a local dev server). */
|
|
@@ -7,8 +7,8 @@ import { SlotRegistry, getSlotRegistry, registerSlotType } from "../slots.js";
|
|
|
7
7
|
import { ExtensionDiagnostics, ExtensionLoaderCacheImpl, getExtensionCache, getExtensionDiagnostics } from "../diagnostics.js";
|
|
8
8
|
import "../loader.js";
|
|
9
9
|
import { ExtensionHookRunner, createHookContext, isHookEvent } from "../hooks.js";
|
|
10
|
-
import { defineChannelPluginEntry } from "./channel-entry.js";
|
|
11
10
|
import { registerExtensionCliProgram } from "./channel-helpers.js";
|
|
11
|
+
import { defineChannelPluginEntry } from "./channel-entry.js";
|
|
12
12
|
import { lazyFunction, lazyModule } from "./lazy.js";
|
|
13
13
|
import { createMockExtensionApi, createTestGateway } from "./testing.js";
|
|
14
14
|
//#region src/extensions/sdk/index.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
|
|
2
1
|
import { resolveCapabilityPresetLayer, resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
|
|
2
|
+
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
|
|
3
3
|
import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
|
|
4
4
|
import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
|
|
5
5
|
import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
|
|
@@ -147,6 +147,7 @@ function createHonoApp(config) {
|
|
|
147
147
|
const DEFAULT_API_BODY_MAX = 1 * 1024 * 1024;
|
|
148
148
|
const SKILL_UPLOAD_BODY_MAX = 10 * 1024 * 1024;
|
|
149
149
|
const NOTE_MEDIA_BODY_MAX = 25 * 1024 * 1024;
|
|
150
|
+
const MEDIA_UPLOAD_BODY_MAX = 33 * 1024 * 1024;
|
|
150
151
|
const VOICE_TRANSCRIBE_BODY_MAX = 26 * 1024 * 1024;
|
|
151
152
|
const SESSION_INPUT_BODY_MAX = maxSessionInputRequestBodyBytes();
|
|
152
153
|
const isNoteMediaUploadRequest = (path, method, contentType) => {
|
|
@@ -175,7 +176,7 @@ function createHonoApp(config) {
|
|
|
175
176
|
}));
|
|
176
177
|
app.use("/api/*", async (c, next) => {
|
|
177
178
|
const contentType = c.req.header("content-type");
|
|
178
|
-
const maxSize = c.req.method === "POST" && c.req.path === "/api/tasks" || c.req.method === "POST" && /^\/api\/sessions\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "POST" && /^\/api\/tasks\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "PATCH" && /^\/api\/sessions\/[^/]+\/inputs\/[^/]+$/.test(c.req.path) ? SESSION_INPUT_BODY_MAX : c.req.path === "/api/skills/upload" ? SKILL_UPLOAD_BODY_MAX : c.req.path === "/api/voice/transcriptions" ? VOICE_TRANSCRIBE_BODY_MAX : isNoteMediaUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : isProjectFileUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : discussionUploadBodyMax(c.req.path, c.req.method, contentType) ?? DEFAULT_API_BODY_MAX;
|
|
179
|
+
const maxSize = c.req.method === "POST" && c.req.path === "/api/tasks" || c.req.method === "POST" && /^\/api\/sessions\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "POST" && /^\/api\/tasks\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "PATCH" && /^\/api\/sessions\/[^/]+\/inputs\/[^/]+$/.test(c.req.path) ? SESSION_INPUT_BODY_MAX : c.req.path === "/api/skills/upload" ? SKILL_UPLOAD_BODY_MAX : c.req.path === "/api/voice/transcriptions" ? VOICE_TRANSCRIBE_BODY_MAX : c.req.path === "/api/media" && c.req.method === "POST" ? MEDIA_UPLOAD_BODY_MAX : isNoteMediaUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : isProjectFileUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : discussionUploadBodyMax(c.req.path, c.req.method, contentType) ?? DEFAULT_API_BODY_MAX;
|
|
179
180
|
const maxSizeMb = Math.ceil(maxSize / (1024 * 1024));
|
|
180
181
|
return bodyLimit({
|
|
181
182
|
maxSize,
|
|
@@ -23,6 +23,7 @@ export interface OAuthCompletionReadiness {
|
|
|
23
23
|
export declare function buildOAuthCompletionReadiness(config: Config, catalog: CatalogReadiness): OAuthCompletionReadiness;
|
|
24
24
|
export declare function refreshModelCatalogAfterOAuth(provider: string, service: Pick<GatewayService, 'getModelCatalogSync'>): Promise<CatalogReadiness | undefined>;
|
|
25
25
|
export declare function normalizeDesktopOAuthReturnPath(value: unknown): string | undefined;
|
|
26
|
+
export declare function buildDesktopOAuthReturnUrl(provider: string, sessionId: string, returnPath: unknown): string | undefined;
|
|
26
27
|
export declare function resolveOAuthLoginMethodPreference(params: {
|
|
27
28
|
requestedMethod?: unknown;
|
|
28
29
|
supportedMethods?: readonly string[];
|
|
@@ -82,11 +82,17 @@ function normalizeDesktopOAuthReturnPath(value) {
|
|
|
82
82
|
if (path.length === 0 || path.length > 2048 || !path.startsWith("/") || path.startsWith("//") || path.includes("\\") || /[\u0000-\u001f\u007f]/.test(path)) return;
|
|
83
83
|
return path;
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
const DESKTOP_OAUTH_CALLBACK_PATHS = {
|
|
86
|
+
"xopc-cloud": "model-connected",
|
|
87
|
+
"xopc-tunnel": "tunnel-connected"
|
|
88
|
+
};
|
|
89
|
+
function buildDesktopOAuthReturnUrl(provider, sessionId, returnPath) {
|
|
90
|
+
const callbackPath = DESKTOP_OAUTH_CALLBACK_PATHS[provider];
|
|
91
|
+
if (!callbackPath) return void 0;
|
|
86
92
|
const params = new URLSearchParams({ request_id: sessionId });
|
|
87
93
|
const normalizedReturnPath = normalizeDesktopOAuthReturnPath(returnPath);
|
|
88
94
|
if (normalizedReturnPath) params.set("return_path", normalizedReturnPath);
|
|
89
|
-
return `xopc://cloud
|
|
95
|
+
return `xopc://cloud/${callbackPath}?${params.toString()}`;
|
|
90
96
|
}
|
|
91
97
|
function cancelOAuthSession(session, message = "OAuth flow cancelled") {
|
|
92
98
|
if (session.abortController) session.abortController.abort();
|
|
@@ -142,10 +148,11 @@ function createOAuthAsyncHandler(service) {
|
|
|
142
148
|
const oauthProvider = OAUTH_PROVIDERS[provider];
|
|
143
149
|
if (!oauthProvider) return c.json({ error: `Unknown OAuth provider: ${provider}` }, 400);
|
|
144
150
|
const sessionId = generateSessionId();
|
|
151
|
+
const returnToAppUrl = body.client === "desktop" ? buildDesktopOAuthReturnUrl(provider, sessionId, body.returnPath) : void 0;
|
|
145
152
|
const session = {
|
|
146
153
|
id: sessionId,
|
|
147
154
|
provider,
|
|
148
|
-
...
|
|
155
|
+
...returnToAppUrl ? { returnToAppUrl } : {},
|
|
149
156
|
preferredLoginMethod: preferredOAuthLoginMethod({
|
|
150
157
|
provider,
|
|
151
158
|
requestedMethod: body.loginMethod,
|
|
@@ -378,4 +385,4 @@ async function runOAuthFlow(session, oauthProvider, service) {
|
|
|
378
385
|
}
|
|
379
386
|
}
|
|
380
387
|
//#endregion
|
|
381
|
-
export { buildOAuthCompletionReadiness, createOAuthAsyncHandler, normalizeDesktopOAuthReturnPath, refreshModelCatalogAfterOAuth, resolveOAuthLoginMethodPreference };
|
|
388
|
+
export { buildDesktopOAuthReturnUrl, buildOAuthCompletionReadiness, createOAuthAsyncHandler, normalizeDesktopOAuthReturnPath, refreshModelCatalogAfterOAuth, resolveOAuthLoginMethodPreference };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { enumerateLanGatewayCandidates } from "../../host.js";
|
|
2
|
+
import { getTunnelService } from "../../../tunnel/tunnel-service.js";
|
|
2
3
|
import { prepareLocalVoiceModelAfterProviderSwitch } from "../../../voice/local/provider-switch.js";
|
|
3
4
|
import { buildSafeWebConfigPayload } from "../lib/config-payload.js";
|
|
4
5
|
import { applyAgentsPatch } from "./config-patch/agents.js";
|
|
@@ -70,6 +71,15 @@ function registerConfigRoutes(authenticated, deps) {
|
|
|
70
71
|
ok: false,
|
|
71
72
|
error: finalGwCheck.error
|
|
72
73
|
}, finalGwCheck.status);
|
|
74
|
+
if (body?.tunnel && typeof body.tunnel === "object" && !Array.isArray(body.tunnel) && body.tunnel.registrationSecret === null) try {
|
|
75
|
+
await getTunnelService().stop();
|
|
76
|
+
} catch (err) {
|
|
77
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
78
|
+
return c.json({
|
|
79
|
+
ok: false,
|
|
80
|
+
error: `Failed to stop tunnel before clearing key: ${message}`
|
|
81
|
+
}, 500);
|
|
82
|
+
}
|
|
73
83
|
const result = await service.saveConfig(config);
|
|
74
84
|
if (!result.saved) return c.json({
|
|
75
85
|
ok: false,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createGatewayRouteLogger } from "../lib/route-logger.js";
|
|
2
2
|
import * as os$1 from "node:os";
|
|
3
3
|
import * as path$1 from "node:path";
|
|
4
|
-
import { readdir, realpath, stat } from "node:fs/promises";
|
|
4
|
+
import { mkdir, readdir, realpath, stat } from "node:fs/promises";
|
|
5
5
|
//#region src/gateway/hono/routes/host-fs.ts
|
|
6
6
|
const log = createGatewayRouteLogger("HostFs");
|
|
7
7
|
function jsonError(status, message) {
|
|
@@ -172,6 +172,45 @@ function registerHostFsRoutes(authenticated, _deps) {
|
|
|
172
172
|
return jsonError(500, msg || "Failed to read directory");
|
|
173
173
|
}
|
|
174
174
|
});
|
|
175
|
+
/** Create one directory below an existing absolute directory on the gateway host. */
|
|
176
|
+
authenticated.post("/api/host/fs/directory", async (c) => {
|
|
177
|
+
const body = await c.req.json().catch(() => null);
|
|
178
|
+
const parentPath = body && typeof body === "object" && typeof body.parentPath === "string" ? body.parentPath.trim() : "";
|
|
179
|
+
const name = body && typeof body === "object" && typeof body.name === "string" ? body.name.trim() : "";
|
|
180
|
+
if (!parentPath || !path$1.isAbsolute(parentPath)) return jsonError(400, "An absolute parent path is required");
|
|
181
|
+
if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || name.includes("\0") || name.length > 255) return jsonError(400, "Invalid folder name");
|
|
182
|
+
let resolvedParent;
|
|
183
|
+
try {
|
|
184
|
+
resolvedParent = await realpath(path$1.normalize(parentPath));
|
|
185
|
+
if (!(await stat(resolvedParent)).isDirectory()) return jsonError(400, "Parent path is not a directory");
|
|
186
|
+
} catch (err) {
|
|
187
|
+
log.warn({
|
|
188
|
+
err,
|
|
189
|
+
path: parentPath
|
|
190
|
+
}, "Host fs create parent lookup failed");
|
|
191
|
+
return jsonError(404, "Parent path not found");
|
|
192
|
+
}
|
|
193
|
+
const directoryPath = path$1.join(resolvedParent, name);
|
|
194
|
+
try {
|
|
195
|
+
await mkdir(directoryPath);
|
|
196
|
+
const createdPath = await realpath(directoryPath);
|
|
197
|
+
log.info({ path: createdPath }, "Host fs directory created");
|
|
198
|
+
return c.json({
|
|
199
|
+
ok: true,
|
|
200
|
+
payload: { absolutePath: createdPath }
|
|
201
|
+
}, 201);
|
|
202
|
+
} catch (err) {
|
|
203
|
+
const code = err?.code;
|
|
204
|
+
if (code === "EEXIST") return jsonError(409, "A file or folder with this name already exists");
|
|
205
|
+
log.warn({
|
|
206
|
+
err,
|
|
207
|
+
path: directoryPath
|
|
208
|
+
}, "Host fs directory create failed");
|
|
209
|
+
if (code === "EACCES" || code === "EPERM" || code === "EROFS") return jsonError(403, "Permission denied");
|
|
210
|
+
if (code === "ENOENT") return jsonError(404, "Parent path not found");
|
|
211
|
+
return jsonError(500, "Failed to create folder");
|
|
212
|
+
}
|
|
213
|
+
});
|
|
175
214
|
}
|
|
176
215
|
//#endregion
|
|
177
216
|
export { registerHostFsRoutes };
|
|
@@ -1,15 +1,47 @@
|
|
|
1
1
|
import { TaskRepository } from "../../../tasks/task-repository.js";
|
|
2
2
|
import { parseMediaUri } from "../../../media/uri.js";
|
|
3
|
-
import { mimeTypeFromMediaPath } from "../../../media/store.js";
|
|
3
|
+
import { mimeTypeFromMediaPath, saveMediaBuffer } from "../../../media/store.js";
|
|
4
4
|
import { readMediaReference } from "../../../media/media-reference.js";
|
|
5
5
|
import { TaskContextRepository } from "../../../tasks/task-context-repository.js";
|
|
6
6
|
import { pendingTranscriptReferencesMediaUri } from "../../../agent/inbound/attachment-pipeline.js";
|
|
7
|
+
import { MAX_WEBCHAT_ATTACHMENT_FILE_BYTES } from "../../chat-limits.js";
|
|
7
8
|
import { messagesReferenceMediaUri } from "../../../media/session-references.js";
|
|
8
9
|
import { createGatewayRouteLogger } from "../lib/route-logger.js";
|
|
9
10
|
//#region src/gateway/hono/routes/media.ts
|
|
10
11
|
const log = createGatewayRouteLogger("Media");
|
|
11
12
|
function registerMediaRoutes(authenticated, deps) {
|
|
12
13
|
const tasks = new TaskRepository();
|
|
14
|
+
authenticated.post("/api/media", deps.strictRateLimitMiddleware, async (c) => {
|
|
15
|
+
const file = (await c.req.formData().catch(() => null))?.get("file");
|
|
16
|
+
if (!(file instanceof Blob)) return c.json({
|
|
17
|
+
ok: false,
|
|
18
|
+
error: { message: "Missing required file field: file" }
|
|
19
|
+
}, 400);
|
|
20
|
+
if (file.size === 0) return c.json({
|
|
21
|
+
ok: false,
|
|
22
|
+
error: { message: "Uploaded file is empty" }
|
|
23
|
+
}, 400);
|
|
24
|
+
if (file.size > 33554432) return c.json({
|
|
25
|
+
ok: false,
|
|
26
|
+
error: { message: "Uploaded file exceeds 32 MB limit" }
|
|
27
|
+
}, 413);
|
|
28
|
+
const name = "name" in file && typeof file.name === "string" && file.name.trim() ? file.name.trim() : `upload-${Date.now()}`;
|
|
29
|
+
const saved = await saveMediaBuffer(Buffer.from(await file.arrayBuffer()), {
|
|
30
|
+
bucket: "inbound",
|
|
31
|
+
contentType: file.type || "application/octet-stream",
|
|
32
|
+
maxBytes: MAX_WEBCHAT_ATTACHMENT_FILE_BYTES,
|
|
33
|
+
originalFilename: name
|
|
34
|
+
});
|
|
35
|
+
return c.json({
|
|
36
|
+
ok: true,
|
|
37
|
+
payload: {
|
|
38
|
+
uri: saved.uri,
|
|
39
|
+
mimeType: saved.contentType,
|
|
40
|
+
name,
|
|
41
|
+
size: saved.size
|
|
42
|
+
}
|
|
43
|
+
}, 201);
|
|
44
|
+
});
|
|
13
45
|
authenticated.get("/api/media/read", async (c) => {
|
|
14
46
|
const uriRaw = c.req.query("uri");
|
|
15
47
|
if (!uriRaw || typeof uriRaw !== "string") return c.json({
|