@xopcai/xopc 0.0.211 → 0.0.213
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/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-BzjFoSr0.js → activity-store-Xw-pOm9A.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DTfjhfVE.js → agent-avatar-dicebear-Ca1bciiK.js} +1 -1
- package/dist/gateway/static/root/assets/agents-DD3TqNrC.js +68 -0
- package/dist/gateway/static/root/assets/{api-D269PnU9.js → api-CZK-lRew.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BFpfQDWc.js → app-management-settings-panel-BLFIG09j.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DLxFdqhY.js → appearance-settings-BsTWUq1i.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-cJkDKn72.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-DPlH4dnc.js → archive-plugin-B9LsFfEx.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-xqfLLd0I.js → attachment-load-CsWiFfmN.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-CbjU2e75.js +1 -0
- package/dist/gateway/static/root/assets/automations-workspace-C4xyo0c4.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-C0tuoPXk.js → binary-plugins-DbqhT_JB.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-Deyphj1o.js → block-editor-BGpHwxZ5.js} +47 -47
- package/dist/gateway/static/root/assets/browser-settings-page-CrhpQl-e.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-CYEbXyRF.js → browser-workflow-inputs-BXlon_hL.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-Bf0tPbGi.js → browser-workflows-page-B3BBDM_r.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-B9MoPW9u.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-DPkFA_-R.js → capability-presets-api-BqvMm6UW.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-BmwldV9R.js +3 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-DqKaAcnZ.js → channel-recipient-api-9uca5kDa.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CwLqWcy_.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-DeBw3du9.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-CTDRZa7e.js → chat-terminal-dock-DJjYT3WX.js} +2 -2
- package/dist/gateway/static/root/assets/{chunk-KS7C4IRE-BMhrPKJC.js → chunk-KS7C4IRE-BaASWQor.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-api-Buu8fif8.js → connectors-api-XCLfuDrN.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-CVkGtcMS.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-DTLR82NB.js → cron-expression-DzQN7zBR.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-DyNogHQH.js → date-picker-B-r5O5qd.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-BpnCuo7B.js → dependency-picker-Ch2XBU2s.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-CDKI4gVB.js → desktop-pet-BdjX8jde.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DjT5C2a3.js → desktop-pet-settings-CzjjgMMn.js} +1 -1
- package/dist/gateway/static/root/assets/directory-picker-path-field-BCTgGTk4.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-DWf2z7q5.js → extension-debug-page-6OGgOucD.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Dorx0kf9.js → extension-page-Cf6MUfCF.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-B1wU9ZOB.js → extension-settings-page-pSY_ZvQZ.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-B1lG4dNr.js → gateway-config-api-CFJMng9v.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-BIxuwPQi.js → gateway-config-swr-DpiY6aub.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DqIOqJjM.js → gateway-settings-aQYxNePf.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-BpZgd4U-.js → gateway-startup-retry-BZ_6ChP4.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-DG4Kmgkc.js → heartbeat-settings-CI33q9i1.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-CAIaWs6r.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-PkhYohDa.js → image-generation-api-DPndEWOU.js} +1 -1
- package/dist/gateway/static/root/assets/index-BhstAl5i.js +108 -0
- package/dist/gateway/static/root/assets/index-DQzjgIkQ.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-6OQT3gQF.js → keyboard-shortcuts-settings-CbLJRGXR.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-BqFnCaKT.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DfruRAmE.js → local-apps-page-Crf6c3SK.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-C5MK9WcP.js → locale-store-BYSRjM6g.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-BpfLQWex.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-L1VYkywO.js → management-settings-mxyYWKgM.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-oqgHbqt-.js → markdown-split-kZaPrUTM.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-V4rcPPH0.js → markdown-view-DlsczsQ1.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Bb6gSX2o.js → media-plugins-Dk67jaG6.js} +1 -1
- package/dist/gateway/static/root/assets/messages-DyM8OOVG.js +3 -0
- package/dist/gateway/static/root/assets/notes-api-DaeeQw8A.js +1 -0
- package/dist/gateway/static/root/assets/{notes-page-B1rOXjpT.js → notes-page-CQDzw8fX.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-BYiROmRJ.js +4 -0
- package/dist/gateway/static/root/assets/{page-tabs-CBuCKeyy.js → page-tabs-C4UkhX2U.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-BQ0tLfPO.js → preview-open-alternatives-nzcjh6y0.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-DPeFn7Hu.js → product-open-page-3FvW5cHm.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-p45i1sMj.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-Y9yXB4DX.js +1 -0
- package/dist/gateway/static/root/assets/registry-api-Bu6OGEY2.js +2 -0
- package/dist/gateway/static/root/assets/remote-access-hub-CNsGY0VS.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BCfQNzjG.js → runtime-tools-settings-panel-CVqPSfUb.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-Bo7YbHYN.js → schema-form-Dz6eZpqv.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-BAtpgb1t.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-pgBQ21Oe.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-B9dnKr3M.js → settings-form-section-BaWFAZv4.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-CYDV2JtY.js → settings-loading-skeleton-BWmdZfNg.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-DbrIYfS9.js → settings-page-Btcb-Dc8.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-BNllZUFP.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-olgr7LLN.js → share-preview-page-CGzY3S0N.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CncwbTHY.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CcW2dhSW.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-PE16CNw5.js → skills-page-Bi2IWpU0.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-nXmBcBxt.js → skills-page.utils-BancvwN2.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-C3qPwAdY.js → system-settings-panel-CihjIzWx.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-SSNFtY-d.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-KR5Otp5w.js → theme-store-D1_t_31B.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-lMZodtDF.js → typed-models-lib-C2LhiQq5.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-CKpatP3S.js → use-autosave-tf_8rxAK.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-BnPTFEar.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-CDcv0Wbh.js → voice-api-key-field-DN-y7Zfe.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-bqqH4aZ9.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BAHYNlQt.js → workflow-run-setup-panel-2H33iXOB.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-BnfxRf1q.js +5 -0
- package/dist/gateway/static/root/index.html +12 -10
- package/dist/package.js +1 -1
- package/dist/src/auth/oauth/xopc-cloud.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/tunnel.js +3 -3
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/connectors/composio-managed-client.d.ts +60 -0
- package/dist/src/connectors/composio-managed-client.js +135 -0
- package/dist/src/connectors/composio-managed-events.d.ts +41 -0
- package/dist/src/connectors/composio-managed-events.js +105 -0
- package/dist/src/connectors/composio-sessions.d.ts +2 -1
- package/dist/src/connectors/composio-sessions.js +13 -7
- package/dist/src/connectors/composio.js +2 -1
- package/dist/src/connectors/connected-source-ingestion.js +67 -25
- package/dist/src/connectors/health.js +1 -1
- package/dist/src/connectors/learning-recipes.js +2 -0
- package/dist/src/connectors/runtime-adapter-registry.js +2 -2
- package/dist/src/discussions/sealer.js +2 -2
- package/dist/src/discussions/service.js +6 -2
- package/dist/src/discussions/transcript.d.ts +2 -0
- package/dist/src/discussions/transcript.js +16 -3
- package/dist/src/extensions/install.d.ts +10 -0
- package/dist/src/extensions/install.js +111 -14
- package/dist/src/extensions/loader.js +22 -18
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/middleware/auth.js +2 -2
- package/dist/src/gateway/hono/middleware/logger.js +1 -1
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/connectors.js +11 -4
- package/dist/src/gateway/hono/routes/exposure.js +1 -1
- package/dist/src/gateway/hono/routes/home.d.ts +1 -1
- package/dist/src/gateway/hono/routes/home.js +2 -2
- package/dist/src/gateway/hono/routes/mcp.js +1 -1
- package/dist/src/gateway/hono/routes/shares.js +1 -1
- package/dist/src/gateway/hono/routes/tunnel.js +3 -3
- package/dist/src/gateway/hono/routes/workflows.js +69 -0
- package/dist/src/gateway/index.js +2 -2
- package/dist/src/gateway/runtime-config.js +2 -2
- package/dist/src/gateway/security/audit.js +2 -2
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service.d.ts +1 -0
- package/dist/src/gateway/service.js +25 -10
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/notes/note-attachment-sync.js +1 -1
- package/dist/src/notes/service.d.ts +1 -0
- package/dist/src/notes/service.js +2 -1
- package/dist/src/notes/types.d.ts +2 -0
- package/dist/src/providers/model-catalog-persistence.d.ts +1 -1
- package/dist/src/providers/model-catalog-store.d.ts +2 -60
- package/dist/src/providers/model-catalog-types.d.ts +60 -0
- package/dist/src/providers/model-catalog-types.js +1 -0
- package/dist/src/providers/provider-disconnect-core.d.ts +11 -0
- package/dist/src/providers/provider-disconnect-core.js +35 -0
- package/dist/src/providers/provider-disconnect.d.ts +2 -10
- package/dist/src/providers/provider-disconnect.js +4 -26
- package/dist/src/providers/xopc-cloud-catalog-coordinator.js +2 -2
- package/dist/src/storage/sqlite/migrations/124_workflow_context_snapshots.sql +15 -0
- package/dist/src/storage/sqlite/migrations/125_project_workflow_presets.sql +12 -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/tasks/home-query-service.d.ts +12 -127
- package/dist/src/tasks/home-query-service.js +73 -271
- package/dist/src/tasks/index.js +2 -2
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/xopc-tui-keybindings.d.ts +2 -2
- package/dist/src/tunnel/index.js +2 -2
- package/dist/src/voice/audio/normalize.d.ts +1 -0
- package/dist/src/voice/audio/normalize.js +24 -4
- package/dist/src/voice/local/wav.d.ts +3 -0
- package/dist/src/voice/local/wav.js +10 -4
- package/dist/src/work-discovery/service.js +6 -8
- package/dist/src/work-discovery/types.d.ts +2 -0
- package/dist/src/workflows/context/workflow-context-snapshot-repository.d.ts +21 -0
- package/dist/src/workflows/context/workflow-context-snapshot-repository.js +40 -0
- package/dist/src/workflows/context/workflow-context.d.ts +18 -0
- package/dist/src/workflows/context/workflow-context.js +159 -0
- package/dist/src/workflows/domain/run.d.ts +10 -1
- package/dist/src/workflows/engine/workflow-engine.d.ts +1 -0
- package/dist/src/workflows/engine/workflow-engine.js +2 -0
- package/dist/src/workflows/project-presets/project-workflow-preset-repository.d.ts +20 -0
- package/dist/src/workflows/project-presets/project-workflow-preset-repository.js +38 -0
- package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
- package/dist/src/workflows/service/workflow-run-service.js +107 -22
- package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -0
- package/dist/src/workflows/service/workflow-writeback-service.d.ts +9 -0
- package/dist/src/workflows/service/workflow-writeback-service.js +106 -0
- package/package.json +6 -6
- package/dist/gateway/static/root/assets/agents-CjhgfuVJ.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-CjmlGB5V.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-4m6Ey6wG.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-CAGCYx8U.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-CKfLsxTI.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-CpipKNqX.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-Bvq-O4pt.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-CrMld2l7.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-CSQRzaVn.js +0 -2
- package/dist/gateway/static/root/assets/directory-picker-path-field-DlJY90TM.js +0 -1
- package/dist/gateway/static/root/assets/home-page-BhqItS_s.js +0 -1
- package/dist/gateway/static/root/assets/index-DLhvsU9B.css +0 -2
- package/dist/gateway/static/root/assets/index-_cuTcWjB.js +0 -107
- package/dist/gateway/static/root/assets/local-app-workbench-page-DWjTmzxw.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-BA5efZ8B.js +0 -2
- package/dist/gateway/static/root/assets/messages-ctG2e-ix.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-CkHXVmKP.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-DCqet9-L.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-D0t_AjzG.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BUWPoBvw.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-vLhrrM3m.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-OP1y0Y8M.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Cxc-Ejl5.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-ZOqC6-aA.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DwvC3Iuf.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-DCRB-5q-.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-CoiedRuA.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-CGdT22un.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-BwaU1RqI.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-DHYmh9G7.js +0 -5
|
@@ -7,8 +7,9 @@ import { checkEngineCompatibility } from "./engine-check.js";
|
|
|
7
7
|
import { collectExtensionPackageDependencyIssues } from "./package-contract.js";
|
|
8
8
|
import { dirname, isAbsolute, join, resolve, sep } from "path";
|
|
9
9
|
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
|
|
10
|
-
import {
|
|
10
|
+
import { execFileSync } from "node:child_process";
|
|
11
11
|
import AdmZip from "adm-zip";
|
|
12
|
+
import semver from "semver";
|
|
12
13
|
import { tmpdir } from "os";
|
|
13
14
|
//#region src/extensions/install.ts
|
|
14
15
|
/**
|
|
@@ -21,6 +22,58 @@ init_package_version();
|
|
|
21
22
|
init_logger();
|
|
22
23
|
const log = createLogger("ExtensionInstall");
|
|
23
24
|
const NPM_INSTALL_ENV = process.env.XOPC_EXTENSION_NPM_INSTALL?.trim().toLowerCase();
|
|
25
|
+
const NPM_INSTALL_SCRIPTS_ENV = process.env.XOPC_EXTENSION_NPM_INSTALL_SCRIPTS?.trim().toLowerCase();
|
|
26
|
+
const ALLOW_NPM_INSTALL_SCRIPTS = [
|
|
27
|
+
"1",
|
|
28
|
+
"true",
|
|
29
|
+
"allow"
|
|
30
|
+
].includes(NPM_INSTALL_SCRIPTS_ENV ?? "");
|
|
31
|
+
const NPM_PACKAGE_PART_RE = /^(?![._])[a-z0-9][a-z0-9._~-]*$/;
|
|
32
|
+
/** Accept registry package names with an optional exact semver; reject URLs, paths, tags, and ranges. */
|
|
33
|
+
function validateNpmPackageSpec(packageSpec) {
|
|
34
|
+
if (!packageSpec || packageSpec !== packageSpec.trim() || /\s/.test(packageSpec)) return {
|
|
35
|
+
ok: false,
|
|
36
|
+
error: "npm package spec must not be empty or contain whitespace"
|
|
37
|
+
};
|
|
38
|
+
let packageName = packageSpec;
|
|
39
|
+
let version;
|
|
40
|
+
if (packageSpec.startsWith("@")) {
|
|
41
|
+
const slashIndex = packageSpec.indexOf("/");
|
|
42
|
+
const versionSeparator = packageSpec.lastIndexOf("@");
|
|
43
|
+
if (slashIndex <= 1) return {
|
|
44
|
+
ok: false,
|
|
45
|
+
error: "Invalid scoped npm package name"
|
|
46
|
+
};
|
|
47
|
+
if (versionSeparator > slashIndex) {
|
|
48
|
+
packageName = packageSpec.slice(0, versionSeparator);
|
|
49
|
+
version = packageSpec.slice(versionSeparator + 1);
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
const versionSeparator = packageSpec.lastIndexOf("@");
|
|
53
|
+
if (versionSeparator > 0) {
|
|
54
|
+
packageName = packageSpec.slice(0, versionSeparator);
|
|
55
|
+
version = packageSpec.slice(versionSeparator + 1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (packageName.length > 214) return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: "npm package name exceeds 214 characters"
|
|
61
|
+
};
|
|
62
|
+
const parts = packageName.startsWith("@") ? packageName.slice(1).split("/") : [packageName];
|
|
63
|
+
if (parts.length !== (packageName.startsWith("@") ? 2 : 1) || parts.some((part) => !NPM_PACKAGE_PART_RE.test(part))) return {
|
|
64
|
+
ok: false,
|
|
65
|
+
error: "Only npm registry package names are allowed (for example pkg or @scope/pkg)"
|
|
66
|
+
};
|
|
67
|
+
if (version !== void 0 && !semver.valid(version)) return {
|
|
68
|
+
ok: false,
|
|
69
|
+
error: "npm package versions must be exact semver values; tags and ranges are not allowed"
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
ok: true,
|
|
73
|
+
packageName,
|
|
74
|
+
...version ? { version } : {}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
24
77
|
function extractExecSyncOutput(error) {
|
|
25
78
|
if (!error || typeof error !== "object") return "";
|
|
26
79
|
const o = error;
|
|
@@ -41,8 +94,9 @@ function truncateOutput(text, max = 4500) {
|
|
|
41
94
|
}
|
|
42
95
|
/**
|
|
43
96
|
* Install production `node_modules` for an unpacked extension (package.json dependencies).
|
|
44
|
-
* Uses pnpm when `pnpm-lock.yaml` is present, otherwise npm.
|
|
45
|
-
*
|
|
97
|
+
* Uses pnpm when `pnpm-lock.yaml` is present, otherwise npm. Lifecycle scripts are disabled by
|
|
98
|
+
* default; set `XOPC_EXTENSION_NPM_INSTALL_SCRIPTS=allow` only for a reviewed extension that needs
|
|
99
|
+
* them. Set `XOPC_EXTENSION_NPM_INSTALL=skip` to skip dependency installation entirely.
|
|
46
100
|
*/
|
|
47
101
|
function installExtensionProdDependencies(extensionDir) {
|
|
48
102
|
if (NPM_INSTALL_ENV === "skip" || NPM_INSTALL_ENV === "0" || NPM_INSTALL_ENV === "false") {
|
|
@@ -65,9 +119,9 @@ function installExtensionProdDependencies(extensionDir) {
|
|
|
65
119
|
env: process.env,
|
|
66
120
|
...process.platform === "win32" ? { shell: process.env.ComSpec && process.env.ComSpec.trim() || "cmd.exe" } : {}
|
|
67
121
|
};
|
|
68
|
-
const run = (label,
|
|
122
|
+
const run = (label, executable, args) => {
|
|
69
123
|
try {
|
|
70
|
-
|
|
124
|
+
execFileSync(executable, args, execOpts);
|
|
71
125
|
return { ok: true };
|
|
72
126
|
} catch (err) {
|
|
73
127
|
const out = truncateOutput(extractExecSyncOutput(err));
|
|
@@ -77,17 +131,38 @@ function installExtensionProdDependencies(extensionDir) {
|
|
|
77
131
|
};
|
|
78
132
|
}
|
|
79
133
|
};
|
|
80
|
-
|
|
81
|
-
|
|
134
|
+
const usePnpm = existsSync(join(extensionDir, "pnpm-lock.yaml"));
|
|
135
|
+
const scriptArgs = ALLOW_NPM_INSTALL_SCRIPTS ? [] : ["--ignore-scripts"];
|
|
136
|
+
const npmExecutable = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
137
|
+
const pnpmExecutable = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
138
|
+
if (usePnpm) {
|
|
139
|
+
const pnpm = run("pnpm", pnpmExecutable, [
|
|
140
|
+
"install",
|
|
141
|
+
"--prod",
|
|
142
|
+
"--no-frozen-lockfile",
|
|
143
|
+
...scriptArgs
|
|
144
|
+
]);
|
|
82
145
|
if (pnpm.ok) return pnpm;
|
|
83
|
-
const npmFallback = run("npm",
|
|
146
|
+
const npmFallback = run("npm", npmExecutable, [
|
|
147
|
+
"install",
|
|
148
|
+
"--omit=dev",
|
|
149
|
+
"--no-audit",
|
|
150
|
+
"--no-fund",
|
|
151
|
+
...scriptArgs
|
|
152
|
+
]);
|
|
84
153
|
if (npmFallback.ok) {
|
|
85
154
|
log.warn({ extensionDir }, "pnpm failed; extension dependencies installed with npm instead");
|
|
86
155
|
return { ok: true };
|
|
87
156
|
}
|
|
88
157
|
return npmFallback;
|
|
89
158
|
}
|
|
90
|
-
return run("npm",
|
|
159
|
+
return run("npm", npmExecutable, [
|
|
160
|
+
"install",
|
|
161
|
+
"--omit=dev",
|
|
162
|
+
"--no-audit",
|
|
163
|
+
"--no-fund",
|
|
164
|
+
...scriptArgs
|
|
165
|
+
]);
|
|
91
166
|
}
|
|
92
167
|
function isSafeZipPath(name) {
|
|
93
168
|
if (!name) return false;
|
|
@@ -261,11 +336,20 @@ function resolveExtensionsDir(workspaceDir, global = false) {
|
|
|
261
336
|
* Install extension from npm package
|
|
262
337
|
*/
|
|
263
338
|
async function installFromNpm(packageSpec, extensionsDir, timeoutMs = 12e4) {
|
|
264
|
-
const
|
|
339
|
+
const validation = validateNpmPackageSpec(packageSpec);
|
|
340
|
+
if (validation.ok === false) return {
|
|
341
|
+
ok: false,
|
|
342
|
+
error: `Invalid npm package spec: ${validation.error}`
|
|
343
|
+
};
|
|
344
|
+
const tmpDir = mkdtempSync(join(tmpdir(), "xopc-install-"));
|
|
265
345
|
try {
|
|
266
346
|
console.log(`📦 Downloading ${packageSpec} from npm...`);
|
|
267
|
-
|
|
268
|
-
|
|
347
|
+
const packedFile = execFileSync(process.platform === "win32" ? "npm.cmd" : "npm", [
|
|
348
|
+
"pack",
|
|
349
|
+
packageSpec,
|
|
350
|
+
"--pack-destination",
|
|
351
|
+
tmpDir
|
|
352
|
+
], {
|
|
269
353
|
timeout: timeoutMs,
|
|
270
354
|
encoding: "utf-8",
|
|
271
355
|
stdio: "pipe"
|
|
@@ -274,9 +358,22 @@ async function installFromNpm(packageSpec, extensionsDir, timeoutMs = 12e4) {
|
|
|
274
358
|
ok: false,
|
|
275
359
|
error: "Failed to download package from npm"
|
|
276
360
|
};
|
|
361
|
+
if (packedFile !== packedFile.split(/[\\/]/).pop() || !packedFile.endsWith(".tgz")) return {
|
|
362
|
+
ok: false,
|
|
363
|
+
error: "npm returned an invalid archive filename"
|
|
364
|
+
};
|
|
277
365
|
const archivePath = join(tmpDir, packedFile);
|
|
366
|
+
if (!existsSync(archivePath)) return {
|
|
367
|
+
ok: false,
|
|
368
|
+
error: "npm package archive was not created"
|
|
369
|
+
};
|
|
278
370
|
console.log(`📂 Extracting ${packedFile}...`);
|
|
279
|
-
|
|
371
|
+
execFileSync("tar", [
|
|
372
|
+
"-xzf",
|
|
373
|
+
archivePath,
|
|
374
|
+
"-C",
|
|
375
|
+
tmpDir
|
|
376
|
+
], {
|
|
280
377
|
timeout: 3e4,
|
|
281
378
|
stdio: "pipe"
|
|
282
379
|
});
|
|
@@ -532,4 +629,4 @@ function readManifest(extensionDir) {
|
|
|
532
629
|
}
|
|
533
630
|
}
|
|
534
631
|
//#endregion
|
|
535
|
-
export { installExtensionFromStoreZip, installFromLocal, installFromNpm, listAllExtensions, peekExtensionIdFromStoreZip, peekExtensionManifestFromStoreZip, peekExtensionPackageJsonFromStoreZip, removeExtension, resolveExtensionsDir };
|
|
632
|
+
export { installExtensionFromStoreZip, installFromLocal, installFromNpm, listAllExtensions, peekExtensionIdFromStoreZip, peekExtensionManifestFromStoreZip, peekExtensionPackageJsonFromStoreZip, removeExtension, resolveExtensionsDir, validateNpmPackageSpec };
|
|
@@ -290,13 +290,6 @@ var ExtensionLoader = class {
|
|
|
290
290
|
}
|
|
291
291
|
async loadExtension(config) {
|
|
292
292
|
try {
|
|
293
|
-
const cacheKey = this.cache.buildKey(this.options, [config.id]);
|
|
294
|
-
const cached = this.cache.get(cacheKey);
|
|
295
|
-
if (cached) {
|
|
296
|
-
log.debug({ extensionId: config.id }, "Extension loaded from cache");
|
|
297
|
-
return cached;
|
|
298
|
-
}
|
|
299
|
-
if (this.extensionInstances.has(config.id)) return this.extensionInstances.get(config.id);
|
|
300
293
|
let extensionPath;
|
|
301
294
|
if (isAbsolute(config.path)) extensionPath = config.path;
|
|
302
295
|
else extensionPath = resolveExtensionPath(config.path, this.options) || resolveExtensionPath(config.id, this.options);
|
|
@@ -314,19 +307,30 @@ var ExtensionLoader = class {
|
|
|
314
307
|
}, "Resolved extension path");
|
|
315
308
|
const source = config.source || "bundled";
|
|
316
309
|
const safetyResult = checkExtensionPathSafety(extensionPath, extensionPath, source);
|
|
317
|
-
if (!safetyResult.safe) {
|
|
310
|
+
if (this.securityConfig.checkPermissions && !safetyResult.safe) {
|
|
318
311
|
logSecurityIssue(config.id, safetyResult);
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}, "Extension blocked by security policy");
|
|
326
|
-
return null;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
312
|
+
this.diagnostics.error(config.id, `Unsafe extension path: ${safetyResult.detail}`);
|
|
313
|
+
log.error({
|
|
314
|
+
extensionId: config.id,
|
|
315
|
+
reason: safetyResult.reason
|
|
316
|
+
}, "Extension blocked because its path is unsafe");
|
|
317
|
+
return null;
|
|
329
318
|
}
|
|
319
|
+
if (source !== "bundled" && !isExtensionAllowed(config.id, this.securityConfig)) {
|
|
320
|
+
this.diagnostics.error(config.id, "Extension is not present in extensions.security.allow");
|
|
321
|
+
log.error({
|
|
322
|
+
extensionId: config.id,
|
|
323
|
+
source
|
|
324
|
+
}, "Extension blocked because it is not trusted by security policy");
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
const cacheKey = this.cache.buildKey(this.options, [config.id]);
|
|
328
|
+
const cached = this.cache.get(cacheKey);
|
|
329
|
+
if (cached) {
|
|
330
|
+
log.debug({ extensionId: config.id }, "Extension loaded from cache");
|
|
331
|
+
return cached;
|
|
332
|
+
}
|
|
333
|
+
if (this.extensionInstances.has(config.id)) return this.extensionInstances.get(config.id);
|
|
330
334
|
provenanceTracker.track(config.id, source);
|
|
331
335
|
const manifest = this.loadManifest(extensionPath);
|
|
332
336
|
if (!manifest) {
|
|
@@ -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";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { shouldSilence, stripHeartbeatToken } from "../../heartbeat/tokens.js";
|
|
4
|
+
import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
|
|
4
5
|
import { isWithinActiveHours } from "../../heartbeat/active-hours.js";
|
|
5
6
|
import { isHeartbeatContentEmpty } from "../../heartbeat/content-check.js";
|
|
6
|
-
import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
|
|
7
7
|
import { createHeartbeatWake } from "../../heartbeat/wake.js";
|
|
8
8
|
import { resolveHeartbeatMdPath } from "../workspace-heartbeat-path.js";
|
|
9
9
|
import { readFile } from "fs/promises";
|
|
@@ -8,10 +8,10 @@ import { getProviderRegistry, init_plugin_registry } from "../../../providers/pl
|
|
|
8
8
|
import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
|
|
9
9
|
import { normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
|
|
10
10
|
import { resolveShareConfig } from "../../../share/share-config.js";
|
|
11
|
-
import { maskTunnelSecretForWeb } from "../../../tunnel/env.js";
|
|
12
11
|
import { resolveSessionConfigForWeb, resolveUpdateConfigForWeb } from "../../../config/web-patch.js";
|
|
13
12
|
import { GENERIC_MASKED_SECRET, maskSecretLength } from "./mask-secret-length.js";
|
|
14
13
|
import { safeToolsWebForGet } from "../../config-tools-web.js";
|
|
14
|
+
import { maskTunnelSecretForWeb } from "../../../tunnel/env.js";
|
|
15
15
|
import { buildSafeProvidersConfigForWeb } from "./safe-providers-config.js";
|
|
16
16
|
import { maskSttConfigForWeb, maskTtsConfigForWeb } from "./safe-voice-config.js";
|
|
17
17
|
//#region src/gateway/hono/lib/config-payload.ts
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { logAuthEvent } from "../../../utils/logger/audit.js";
|
|
2
2
|
import { createLogger } from "../../../utils/logger/index.js";
|
|
3
3
|
import { init_logger } from "../../../utils/logger.js";
|
|
4
|
+
import { safeEqualSecret } from "../../security/secret-equal.js";
|
|
5
|
+
import { resolveClientIpFromRequest } from "../../client-ip.js";
|
|
4
6
|
import { authPolicyConfig, buckets, resolveAuthRateLimit } from "../../rate-limit/buckets.js";
|
|
5
7
|
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
6
8
|
import { resolveAuthTracking } from "../../rate-limit/auth-policy.js";
|
|
7
9
|
import { isAuthRateLimitGloballyDisabled } from "../../rate-limit/env-flags.js";
|
|
8
10
|
import "../../rate-limit/index.js";
|
|
9
|
-
import { safeEqualSecret } from "../../security/secret-equal.js";
|
|
10
|
-
import { resolveClientIpFromRequest } from "../../client-ip.js";
|
|
11
11
|
import { authorizeTrustedProxy } from "../../trusted-proxy.js";
|
|
12
12
|
import { createMiddleware } from "hono/factory";
|
|
13
13
|
import { getConnInfo } from "@hono/node-server/conninfo";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../../utils/logger.js";
|
|
3
|
-
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
4
3
|
import { resolveClientIpFromRequest } from "../../client-ip.js";
|
|
4
|
+
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
5
5
|
import { createMiddleware } from "hono/factory";
|
|
6
6
|
import { getConnInfo } from "@hono/node-server/conninfo";
|
|
7
7
|
//#region src/gateway/hono/middleware/logger.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createLogger } from "../../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../../utils/logger.js";
|
|
3
|
+
import { resolveClientIpFromRequest } from "../../client-ip.js";
|
|
3
4
|
import { buckets } from "../../rate-limit/buckets.js";
|
|
4
5
|
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
5
6
|
import "../../rate-limit/index.js";
|
|
6
|
-
import { resolveClientIpFromRequest } from "../../client-ip.js";
|
|
7
7
|
import { createMiddleware } from "hono/factory";
|
|
8
8
|
import { getConnInfo } from "@hono/node-server/conninfo";
|
|
9
9
|
//#region src/gateway/hono/middleware/strict-rate-limit.ts
|
|
@@ -3,11 +3,11 @@ import { BindingsConfigSchema, BrowserConfigSchema, McpConfigSchema, VoiceConfig
|
|
|
3
3
|
import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
|
|
4
4
|
import { canonicalizeConfiguredMcpServer } from "../../../../config/mcp-config-normalize.js";
|
|
5
5
|
import { setTuiDefaultAgentConfig } from "../../../../commands/agents.config.js";
|
|
6
|
-
import { mergeTunnelConfigPatch } from "../../../../tunnel/tunnel-config.js";
|
|
7
6
|
import { mergeGatewaySkillsMarketplacePatch, mergeSessionConfigPatch, mergeUpdateConfigPatch } from "../../../../config/web-patch.js";
|
|
8
7
|
import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../../../auth.js";
|
|
9
8
|
import { isMaskedSecretPatchValue } from "../../lib/mask-secret-length.js";
|
|
10
9
|
import { applyToolsWebPatch } from "../../../config-tools-web.js";
|
|
10
|
+
import { mergeTunnelConfigPatch } from "../../../../tunnel/tunnel-config.js";
|
|
11
11
|
import { assertGatewayRuntimeConfig } from "../../../runtime-config.js";
|
|
12
12
|
import { mergeSttConfigPatch, mergeTtsConfigPatch } from "../../lib/safe-voice-config.js";
|
|
13
13
|
import { PATCH_OK, patchError } from "./result.js";
|
|
@@ -14,14 +14,15 @@ import { getConnectorDefinition, listConnectorCatalog } from "../../../connector
|
|
|
14
14
|
import { listUnderstandingSourceGrants, revokeUnderstandingSourceGrant } from "../../../user-context/sources/repository.js";
|
|
15
15
|
import { recordConnectorHealthUsage } from "../../../connectors/usage.js";
|
|
16
16
|
import { getConnectorInstance, listConnectorInstances } from "../../../connectors/instances.js";
|
|
17
|
+
import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
|
|
17
18
|
import { startConnectorAuthorization } from "../../../connectors/auth-provider-registry.js";
|
|
18
19
|
import { composioLogoResponse } from "../../../connectors/composio-logo.js";
|
|
20
|
+
import { inspectManagedComposioStatus } from "../../../connectors/composio-managed-client.js";
|
|
19
21
|
import { appendComposioTriggerEvent, listComposioTriggerEvents } from "../../../connectors/composio-triggers.js";
|
|
20
22
|
import { buildConnectedPeopleGraph } from "../../../knowledge/people-graph.js";
|
|
21
23
|
import "../../../knowledge/index.js";
|
|
22
24
|
import { ingestLocalFolderSource } from "../../../connectors/connected-source-ingestion.js";
|
|
23
25
|
import { previewConnectorDefinition, testConnectorInstance } from "../../../connectors/health.js";
|
|
24
|
-
import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
|
|
25
26
|
import { setConnectorEnabled } from "../../../connectors/lifecycle.js";
|
|
26
27
|
import { projectComposioConnectionStatus } from "../../../connectors/runtime-status.js";
|
|
27
28
|
//#region src/gateway/hono/routes/connectors.ts
|
|
@@ -592,10 +593,13 @@ function registerConnectorRoutes(authenticated, deps) {
|
|
|
592
593
|
}
|
|
593
594
|
});
|
|
594
595
|
authenticated.get("/api/connectors/composio/setup-status", async (c) => {
|
|
595
|
-
const
|
|
596
|
+
const status = Boolean(await resolveComposioApiKey()) ? {
|
|
597
|
+
configured: true,
|
|
598
|
+
mode: "byok"
|
|
599
|
+
} : await inspectManagedComposioStatus();
|
|
596
600
|
return c.json({
|
|
597
601
|
ok: true,
|
|
598
|
-
payload:
|
|
602
|
+
payload: status
|
|
599
603
|
});
|
|
600
604
|
});
|
|
601
605
|
authenticated.post("/api/connectors/composio/setup", strictRateLimitMiddleware, async (c) => {
|
|
@@ -605,7 +609,10 @@ function registerConnectorRoutes(authenticated, deps) {
|
|
|
605
609
|
await configureComposioApiKey(apiKey);
|
|
606
610
|
return c.json({
|
|
607
611
|
ok: true,
|
|
608
|
-
payload: {
|
|
612
|
+
payload: {
|
|
613
|
+
configured: true,
|
|
614
|
+
mode: "byok"
|
|
615
|
+
}
|
|
609
616
|
});
|
|
610
617
|
} catch (error) {
|
|
611
618
|
return c.json({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { consumeTunnelMutationLimit } from "../../../tunnel/tunnel-rate-limit.js";
|
|
2
1
|
import { extractToken } from "../../auth.js";
|
|
3
2
|
import { getExposureManager } from "../../../remote-access/exposure-manager.js";
|
|
3
|
+
import { consumeTunnelMutationLimit } from "../../../tunnel/tunnel-rate-limit.js";
|
|
4
4
|
//#region src/gateway/hono/routes/exposure.ts
|
|
5
5
|
function requireGatewayToken(c) {
|
|
6
6
|
return extractToken({ authorization: c.req.header("authorization") ?? void 0 }) ?? null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Hono } from 'hono';
|
|
2
2
|
import type { AuthenticatedRouteDeps } from './deps.js';
|
|
3
|
-
export {
|
|
3
|
+
export { buildHomeWorkbench, decisionFromTask } from '../../../tasks/home-query-service.js';
|
|
4
4
|
/** Register the unified work-home read model and its decision actions. */
|
|
5
5
|
export declare function registerHomeRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void;
|
|
@@ -2,7 +2,7 @@ import { acknowledgeHomeAttention } from "../../../storage/sqlite/home-attention
|
|
|
2
2
|
import { decideConnectorApproval } from "../../../storage/sqlite/connector-repository.js";
|
|
3
3
|
import "../../../storage/sqlite/index.js";
|
|
4
4
|
import { listGatewayAgents } from "../../agents-admin.js";
|
|
5
|
-
import { HomeQueryService,
|
|
5
|
+
import { HomeQueryService, buildHomeWorkbench, decisionFromTask } from "../../../tasks/home-query-service.js";
|
|
6
6
|
//#region src/gateway/hono/routes/home.ts
|
|
7
7
|
/** Register the unified work-home read model and its decision actions. */
|
|
8
8
|
function registerHomeRoutes(authenticated, deps) {
|
|
@@ -90,4 +90,4 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
//#endregion
|
|
93
|
-
export {
|
|
93
|
+
export { buildHomeWorkbench, decisionFromTask, registerHomeRoutes };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { canonicalizeConfiguredMcpServer, normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
|
|
2
2
|
import { loadMergedBundleMcpConfig } from "../../../agent/mcp/bundle-mcp-config.js";
|
|
3
|
-
import { getWorkspacePath } from "../../../config/workspace-path-helpers.js";
|
|
4
3
|
import { isManagedConnectorServer } from "../../../connectors/materialize.js";
|
|
4
|
+
import { getWorkspacePath } from "../../../config/workspace-path-helpers.js";
|
|
5
5
|
import { listBundleMcpServerCapabilitiesForGateway, listBundleMcpServerToolsForGateway } from "../../../agent/mcp/bundle-mcp-gateway.js";
|
|
6
6
|
//#region src/gateway/hono/routes/mcp.ts
|
|
7
7
|
function registerMcpRoutes(authenticated, deps) {
|
|
@@ -8,8 +8,8 @@ import { resolveShareUrl, resolveSiteShareUrl } from "../../../share/share-url.j
|
|
|
8
8
|
import { resolveReverseProxyPublicUrl } from "../../public-url.js";
|
|
9
9
|
import { audienceDefaults, cleanupStagedSite, decideShareKind, forgetStagedSite, makeDescription, makeTitle, probeShareTarget, rememberStagedSite, stageSingleHtmlAsSite } from "../../../share/share-auto.js";
|
|
10
10
|
import { deleteThumbnail, placeholderSvg, readThumbnail, scheduleThumbnail, thumbnailContentType, thumbnailExists } from "../../../share/share-thumbnail.js";
|
|
11
|
-
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
12
11
|
import { extractToken } from "../../auth.js";
|
|
12
|
+
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
13
13
|
import { renderFolderLandingPage, renderShareExpiredPage, renderShareLandingPage } from "../../../share/share-landing.js";
|
|
14
14
|
import { consumeSharePublicLimit } from "../../../share/share-rate-limit.js";
|
|
15
15
|
import { createZipStream, planDirectoryFiles } from "../../../share/share-zip.js";
|
|
@@ -2,18 +2,18 @@ import { init_public_url, validatePublicUrl } from "../../../config/public-url.j
|
|
|
2
2
|
import { resolveGatewayEffectiveHost } from "../../../config/gateway-bind.js";
|
|
3
3
|
import { loadTunnelState } from "../../../tunnel/tunnel-state.js";
|
|
4
4
|
import { resolveReverseProxyPublicUrl } from "../../public-url.js";
|
|
5
|
+
import { extractToken } from "../../auth.js";
|
|
5
6
|
import { TUNNEL_CONSENT_REQUIRED_CODE, TunnelConsentError, assertTunnelMayStart, getTunnelConsentState } from "../../../tunnel/consent.js";
|
|
6
7
|
import { getTunnelRegistrationSecretMeta, readTunnelRegistrationSecretFromConfigOnly, resolveTunnelBrokerUrl } from "../../../tunnel/env.js";
|
|
7
|
-
import { applyTunnelConsentToConfig, setTunnelEnabledInConfig } from "../../../tunnel/tunnel-config.js";
|
|
8
8
|
import { createPairingSecret, exchangePairingSecretOnce, getCachedPairingExchange } from "../../../tunnel/pairing.js";
|
|
9
9
|
import { logTunnelAudit } from "../../../tunnel/tunnel-audit.js";
|
|
10
10
|
import { getTunnelService, hashGatewayToken } from "../../../tunnel/tunnel-service.js";
|
|
11
11
|
import { configureTunnelFromGatewayConfig } from "../../../tunnel/gateway-lifecycle.js";
|
|
12
|
+
import { applyTunnelConsentToConfig, setTunnelEnabledInConfig } from "../../../tunnel/tunnel-config.js";
|
|
12
13
|
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
14
|
+
import { applyLanPairingGatewayPatch } from "../../../tunnel/enable-lan-pairing.js";
|
|
13
15
|
import { consumeTunnelMutationLimit } from "../../../tunnel/tunnel-rate-limit.js";
|
|
14
16
|
import "../../../tunnel/index.js";
|
|
15
|
-
import { extractToken } from "../../auth.js";
|
|
16
|
-
import { applyLanPairingGatewayPatch } from "../../../tunnel/enable-lan-pairing.js";
|
|
17
17
|
import { buildMobileConnectUrlOrder, resolveMobilePairLanUrl, validateMobilePairBaseUrl } from "../../../tunnel/pair-url.js";
|
|
18
18
|
import { buildMobilePairContext } from "../../../tunnel/pair-context.js";
|
|
19
19
|
import { consumePairingExchangeFailLimit } from "../../../tunnel/pairing-rate-limit.js";
|
|
@@ -10,10 +10,39 @@ import { WorkflowDraftService } from "../../../workflows/draft/workflow-draft-se
|
|
|
10
10
|
import { WorkflowDraftConflictError, WorkflowDraftStore } from "../../../workflows/authoring/workflow-draft-store.js";
|
|
11
11
|
import "../../../workflows/authoring/index.js";
|
|
12
12
|
import "../../../workflows/draft/index.js";
|
|
13
|
+
import { ProjectWorkflowPresetRepository } from "../../../workflows/project-presets/project-workflow-preset-repository.js";
|
|
13
14
|
import { basename, join } from "node:path";
|
|
14
15
|
import { readFile, stat } from "node:fs/promises";
|
|
15
16
|
//#region src/gateway/hono/routes/workflows.ts
|
|
16
17
|
init_agent_scope();
|
|
18
|
+
const WORKFLOW_CONTEXT_KINDS = new Set([
|
|
19
|
+
"project",
|
|
20
|
+
"task",
|
|
21
|
+
"note",
|
|
22
|
+
"session",
|
|
23
|
+
"attachment",
|
|
24
|
+
"memory"
|
|
25
|
+
]);
|
|
26
|
+
function parseWorkflowContextRefs(value) {
|
|
27
|
+
if (value === void 0) return void 0;
|
|
28
|
+
if (!Array.isArray(value) || value.length > 50) throw new Error("contextRefs must be an array with at most 50 items");
|
|
29
|
+
return value.map((candidate) => {
|
|
30
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) throw new Error("Invalid workflow context reference");
|
|
31
|
+
const ref = candidate;
|
|
32
|
+
const kind = typeof ref.kind === "string" ? ref.kind : "";
|
|
33
|
+
const id = typeof ref.id === "string" ? ref.id.trim() : "";
|
|
34
|
+
if (!WORKFLOW_CONTEXT_KINDS.has(kind) || !id || id.length > 512) throw new Error("Invalid workflow context reference");
|
|
35
|
+
const role = typeof ref.role === "string" ? ref.role.trim() : void 0;
|
|
36
|
+
const title = typeof ref.title === "string" ? ref.title.trim() : void 0;
|
|
37
|
+
if ((role?.length ?? 0) > 64 || (title?.length ?? 0) > 256) throw new Error("Invalid workflow context reference");
|
|
38
|
+
return {
|
|
39
|
+
kind,
|
|
40
|
+
id,
|
|
41
|
+
...role ? { role } : {},
|
|
42
|
+
...title ? { title } : {}
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
}
|
|
17
46
|
function registerWorkflowRoutes(authenticated, deps) {
|
|
18
47
|
const { service } = deps;
|
|
19
48
|
const workflowRunService = service.createWorkflowRunService();
|
|
@@ -38,6 +67,38 @@ function registerWorkflowRoutes(authenticated, deps) {
|
|
|
38
67
|
return c.json({ error: err instanceof Error ? err.message : "Workflow definition not found" }, 404);
|
|
39
68
|
}
|
|
40
69
|
});
|
|
70
|
+
authenticated.get("/api/workflows/project-presets", (c) => {
|
|
71
|
+
const projectId = c.req.query("projectId")?.trim();
|
|
72
|
+
if (!projectId) return c.json({ error: "projectId is required" }, 400);
|
|
73
|
+
if (!service.projects.get(projectId)) return c.json({ error: "Project not found" }, 404);
|
|
74
|
+
return c.json({ presets: new ProjectWorkflowPresetRepository().list(projectId) });
|
|
75
|
+
});
|
|
76
|
+
authenticated.put("/api/workflows/project-presets/:definitionId", async (c) => {
|
|
77
|
+
const definitionId = c.req.param("definitionId").trim();
|
|
78
|
+
const body = await readJsonBody(c.req.raw);
|
|
79
|
+
const projectId = body.projectId?.trim();
|
|
80
|
+
if (!projectId) return c.json({ error: "projectId is required" }, 400);
|
|
81
|
+
if (!service.projects.get(projectId)) return c.json({ error: "Project not found" }, 404);
|
|
82
|
+
try {
|
|
83
|
+
createWorkflowCatalog().load(definitionId);
|
|
84
|
+
const contextRefs = parseWorkflowContextRefs(body.contextRefs) ?? [];
|
|
85
|
+
if (contextRefs.some((ref) => ref.kind !== "task" && ref.kind !== "note")) return c.json({ error: "Project workflow presets support task and note context only" }, 400);
|
|
86
|
+
const preset = new ProjectWorkflowPresetRepository().save({
|
|
87
|
+
projectId,
|
|
88
|
+
definitionId,
|
|
89
|
+
contextRefs
|
|
90
|
+
});
|
|
91
|
+
return c.json({ preset });
|
|
92
|
+
} catch (cause) {
|
|
93
|
+
return c.json({ error: cause instanceof Error ? cause.message : "Could not save project workflow" }, 400);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
authenticated.delete("/api/workflows/project-presets/:definitionId", (c) => {
|
|
97
|
+
const projectId = c.req.query("projectId")?.trim();
|
|
98
|
+
if (!projectId) return c.json({ error: "projectId is required" }, 400);
|
|
99
|
+
const removed = new ProjectWorkflowPresetRepository().remove(projectId, c.req.param("definitionId"));
|
|
100
|
+
return c.json({ removed });
|
|
101
|
+
});
|
|
41
102
|
authenticated.post("/api/workflows/definitions/validate", async (c) => {
|
|
42
103
|
const body = await readJsonBody(c.req.raw);
|
|
43
104
|
const result = validateWorkflowDefinitionInput({
|
|
@@ -206,6 +267,7 @@ function registerWorkflowRoutes(authenticated, deps) {
|
|
|
206
267
|
const catalog = createWorkflowCatalog();
|
|
207
268
|
try {
|
|
208
269
|
if (!catalog.remove(id)) return c.json({ error: "User workflow not found or cannot delete built-in workflow" }, 404);
|
|
270
|
+
new ProjectWorkflowPresetRepository().removeDefinition(id);
|
|
209
271
|
const drafts = new WorkflowDraftStore().list(id);
|
|
210
272
|
for (const draft of drafts) new WorkflowDraftStore().remove(draft.id);
|
|
211
273
|
return c.json({ removed: true });
|
|
@@ -228,6 +290,12 @@ function registerWorkflowRoutes(authenticated, deps) {
|
|
|
228
290
|
const taskRunId = body.taskRunId?.trim();
|
|
229
291
|
const projectId = body.projectId?.trim();
|
|
230
292
|
if (projectId && !service.projects.get(projectId)) return c.json({ error: "Project not found" }, 404);
|
|
293
|
+
let contextRefs;
|
|
294
|
+
try {
|
|
295
|
+
contextRefs = parseWorkflowContextRefs(body.contextRefs);
|
|
296
|
+
} catch (cause) {
|
|
297
|
+
return c.json({ error: cause instanceof Error ? cause.message : "Invalid workflow context references" }, 400);
|
|
298
|
+
}
|
|
231
299
|
const explicitAgentId = body.agentId ?? c.req.query("agentId");
|
|
232
300
|
const agentId = projectId ? resolveProjectAgentId({
|
|
233
301
|
config: service.currentConfig,
|
|
@@ -240,6 +308,7 @@ function registerWorkflowRoutes(authenticated, deps) {
|
|
|
240
308
|
definitionId,
|
|
241
309
|
taskRunId,
|
|
242
310
|
projectId,
|
|
311
|
+
contextRefs,
|
|
243
312
|
input: body.inputEnvelope ? void 0 : body.input,
|
|
244
313
|
inputEnvelope: body.inputEnvelope,
|
|
245
314
|
goal: body.goal,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { buildDefaultCorsOrigins, isAllInterfacesHost, isLoopbackHost, resolveEffectiveGatewayPort, resolveGatewayServiceListenPort } from "./host.js";
|
|
2
2
|
import { defaultGatewayBindMode, isContainerEnvironment, resolveGatewayBindHost, resolveGatewayBindHostSync, resolveGatewayBindMode, resolveGatewayEffectiveHost } from "../config/gateway-bind.js";
|
|
3
|
+
import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
|
|
4
|
+
import { resolveGatewayListenHost, resolveGatewayListenPlan } from "./listen.js";
|
|
3
5
|
import { buckets } from "./rate-limit/buckets.js";
|
|
4
6
|
import { isGatewayStrictSecurityEnabled } from "./rate-limit/env-flags.js";
|
|
5
7
|
import "./rate-limit/index.js";
|
|
6
|
-
import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
|
|
7
|
-
import { resolveGatewayListenHost, resolveGatewayListenPlan } from "./listen.js";
|
|
8
8
|
import { assertGatewayRuntimeConfig } from "./runtime-config.js";
|
|
9
9
|
import { restartGatewayProcessWithFreshPid } from "./respawn.js";
|
|
10
10
|
import { GatewayService } from "./service.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isAllInterfacesHost, isLoopbackHost, resolveGatewayCorsOrigins } from "./host.js";
|
|
2
|
-
import { isAuthRateLimitGloballyDisabled, isGatewayStrictSecurityEnabled } from "./rate-limit/env-flags.js";
|
|
3
|
-
import "./rate-limit/index.js";
|
|
4
2
|
import { resolveGatewayListenPlan } from "./listen.js";
|
|
5
3
|
import { assertTailscaleExposureCompatible } from "./tailscale-lifecycle.js";
|
|
4
|
+
import { isAuthRateLimitGloballyDisabled, isGatewayStrictSecurityEnabled } from "./rate-limit/env-flags.js";
|
|
5
|
+
import "./rate-limit/index.js";
|
|
6
6
|
//#region src/gateway/runtime-config.ts
|
|
7
7
|
function hasSharedSecret(auth) {
|
|
8
8
|
if (auth.mode === "trusted-proxy") return true;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
-
import { isAuthRateLimitGloballyDisabled, isGatewayStrictSecurityEnabled } from "../rate-limit/env-flags.js";
|
|
4
|
-
import "../rate-limit/index.js";
|
|
5
3
|
import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../auth.js";
|
|
6
4
|
import { resolveGatewayListenPlan } from "../listen.js";
|
|
7
5
|
import { collectExposureConflicts, isRemoteGatewayInsecure, isTailnetBindUnavailable } from "../../remote-access/exposure-guards.js";
|
|
6
|
+
import { isAuthRateLimitGloballyDisabled, isGatewayStrictSecurityEnabled } from "../rate-limit/env-flags.js";
|
|
7
|
+
import "../rate-limit/index.js";
|
|
8
8
|
import { assertGatewayRuntimeConfig } from "../runtime-config.js";
|
|
9
9
|
//#region src/gateway/security/audit.ts
|
|
10
10
|
init_logger();
|
|
@@ -4,12 +4,12 @@ import { loadConfig, saveConfig } from "../../config/loader.js";
|
|
|
4
4
|
import { getModelRegistry } from "../../providers/model-registry.js";
|
|
5
5
|
import { init_providers } from "../../providers/index.js";
|
|
6
6
|
import { disposeAllSessionMcpRuntimes } from "../../agent/mcp/bundle-mcp-runtime.js";
|
|
7
|
-
import { sanitizeTunnelConfig } from "../../tunnel/tunnel-config.js";
|
|
8
7
|
import { reloadImageGenerationProviders } from "../../agent/image/generation/provider-registry.js";
|
|
9
8
|
import "../../agent/mcp/bundle-mcp-tools.js";
|
|
10
9
|
import { ConfigHotReloader } from "../../config/reload.js";
|
|
11
10
|
import "../../config/index.js";
|
|
12
11
|
import { computeBundledExtensionExtensionsPatch } from "../../extensions/bundled-extension-activation.js";
|
|
12
|
+
import { sanitizeTunnelConfig } from "../../tunnel/tunnel-config.js";
|
|
13
13
|
//#region src/gateway/service/config-coordinator.ts
|
|
14
14
|
init_providers();
|
|
15
15
|
init_logger();
|
|
@@ -67,6 +67,7 @@ export declare class GatewayService {
|
|
|
67
67
|
private workflowRunServiceInstance;
|
|
68
68
|
private taskRunDispatcher;
|
|
69
69
|
private taskRunDispatchTimer;
|
|
70
|
+
private managedComposioEventPoller?;
|
|
70
71
|
private mobileNotifications;
|
|
71
72
|
private connectorSupervisor;
|
|
72
73
|
private connectorLearningCoordinator;
|