@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
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { init_xopc_cloud_config, resolveXopcModelRouterUrl } from "../providers/xopc-cloud-config.js";
|
|
2
|
+
import { getProviderAuthService, init_provider_auth_service } from "../providers/provider-auth-service.js";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
//#region src/connectors/composio-managed-client.ts
|
|
5
|
+
init_provider_auth_service();
|
|
6
|
+
init_xopc_cloud_config();
|
|
7
|
+
var ManagedComposioError = class extends Error {
|
|
8
|
+
constructor(message, status, code) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.name = "ManagedComposioError";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var ManagedComposioClient = class {
|
|
16
|
+
mode = "managed";
|
|
17
|
+
fetchImpl;
|
|
18
|
+
routerUrl;
|
|
19
|
+
credentials;
|
|
20
|
+
constructor(options = {}) {
|
|
21
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
22
|
+
this.routerUrl = resolveXopcModelRouterUrl(options.routerUrl);
|
|
23
|
+
this.credentials = options.credentials ?? getProviderAuthService();
|
|
24
|
+
}
|
|
25
|
+
sessions = { create: async (_userId, config = {}) => {
|
|
26
|
+
if (config.authConfigs && Object.keys(config.authConfigs).length > 0) throw new Error("Custom Composio auth configs require BYOK mode.");
|
|
27
|
+
const enabledToolkits = Array.isArray(config.toolkits) ? config.toolkits : config.toolkits && "enable" in config.toolkits ? config.toolkits.enable : [];
|
|
28
|
+
const connectedAccounts = Object.fromEntries(Object.entries(config.connectedAccounts ?? {}).map(([toolkit, value]) => [toolkit, Array.isArray(value) ? value : [value]]));
|
|
29
|
+
return this.session(enabledToolkits, connectedAccounts);
|
|
30
|
+
} };
|
|
31
|
+
connectedAccounts = {
|
|
32
|
+
list: async () => this.request({ path: "/connectors/composio/connections" }),
|
|
33
|
+
delete: async (id) => this.request({
|
|
34
|
+
path: `/connectors/composio/connections/${encodeURIComponent(id)}`,
|
|
35
|
+
method: "DELETE"
|
|
36
|
+
}),
|
|
37
|
+
refresh: async (id) => this.request({
|
|
38
|
+
path: `/connectors/composio/connections/${encodeURIComponent(id)}/refresh`,
|
|
39
|
+
method: "POST"
|
|
40
|
+
})
|
|
41
|
+
};
|
|
42
|
+
authConfigs = { list: async () => ({ items: [] }) };
|
|
43
|
+
toolkits = { get: async (slug) => {
|
|
44
|
+
const response = await this.request({ path: `/connectors/composio/toolkits/${encodeURIComponent(slug)}/auth` });
|
|
45
|
+
return {
|
|
46
|
+
composioManagedAuthSchemes: response.auth.managedAuthAvailable ? ["OAUTH2"] : [],
|
|
47
|
+
authConfigDetails: response.auth.requiresCustomAuthConfig ? [{}] : []
|
|
48
|
+
};
|
|
49
|
+
} };
|
|
50
|
+
async status() {
|
|
51
|
+
return this.request({ path: "/connectors/composio/status" });
|
|
52
|
+
}
|
|
53
|
+
async events(after = 0, limit = 50) {
|
|
54
|
+
return this.request({ path: `/connectors/composio/events?after=${after}&limit=${limit}` });
|
|
55
|
+
}
|
|
56
|
+
session(toolkits, connectedAccounts) {
|
|
57
|
+
const toolkit = () => {
|
|
58
|
+
if (toolkits.length !== 1 || !toolkits[0]) throw new Error("Managed Composio sessions require exactly one toolkit for this operation.");
|
|
59
|
+
return toolkits[0];
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
sessionId: "managed",
|
|
63
|
+
toolkits: async () => {
|
|
64
|
+
return { items: (await this.request({ path: "/connectors/composio/toolkits" })).items };
|
|
65
|
+
},
|
|
66
|
+
authorize: async (requestedToolkit, options) => {
|
|
67
|
+
return (await this.request({
|
|
68
|
+
path: "/connectors/composio/authorizations",
|
|
69
|
+
method: "POST",
|
|
70
|
+
body: {
|
|
71
|
+
toolkit: requestedToolkit,
|
|
72
|
+
alias: options?.alias
|
|
73
|
+
}
|
|
74
|
+
})).item;
|
|
75
|
+
},
|
|
76
|
+
search: async () => {
|
|
77
|
+
return (await this.request({ path: `/connectors/composio/toolkits/${encodeURIComponent(toolkit())}/tools` })).result;
|
|
78
|
+
},
|
|
79
|
+
execute: async (toolSlug, args = {}, options) => {
|
|
80
|
+
const selected = options?.account ?? connectedAccounts[toolkit()]?.[0];
|
|
81
|
+
return (await this.request({
|
|
82
|
+
path: "/connectors/composio/execute",
|
|
83
|
+
method: "POST",
|
|
84
|
+
body: {
|
|
85
|
+
toolkit: toolkit(),
|
|
86
|
+
toolSlug,
|
|
87
|
+
args,
|
|
88
|
+
...selected ? { accountId: selected } : {}
|
|
89
|
+
},
|
|
90
|
+
headers: { "idempotency-key": randomUUID() }
|
|
91
|
+
})).result;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async request(input) {
|
|
96
|
+
const accessToken = await this.credentials.resolveApiKey("xopc-cloud");
|
|
97
|
+
if (!accessToken) throw new ManagedComposioError("Sign in to XOPC Cloud to use managed app connections.", 401, "xopc_cloud_not_configured");
|
|
98
|
+
const response = await this.fetchImpl(`${this.routerUrl}${input.path}`, {
|
|
99
|
+
method: input.method ?? "GET",
|
|
100
|
+
headers: {
|
|
101
|
+
authorization: `Bearer ${accessToken}`,
|
|
102
|
+
accept: "application/json",
|
|
103
|
+
...input.body === void 0 ? {} : { "content-type": "application/json" },
|
|
104
|
+
...input.headers
|
|
105
|
+
},
|
|
106
|
+
...input.body === void 0 ? {} : { body: JSON.stringify(input.body) },
|
|
107
|
+
signal: AbortSignal.timeout(6e4)
|
|
108
|
+
});
|
|
109
|
+
const body = await response.json().catch(() => null);
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
const code = typeof body?.error?.code === "string" ? body.error.code : void 0;
|
|
112
|
+
const fallback = response.status === 403 && code === "insufficient_scope" ? "Reconnect XOPC Cloud to grant app connection permissions." : `Managed Composio request failed (${response.status})`;
|
|
113
|
+
throw new ManagedComposioError(typeof body?.error?.message === "string" ? body.error.message : fallback, response.status, code);
|
|
114
|
+
}
|
|
115
|
+
return body;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
async function inspectManagedComposioStatus(options = {}) {
|
|
119
|
+
try {
|
|
120
|
+
const status = await new ManagedComposioClient(options).status();
|
|
121
|
+
return {
|
|
122
|
+
configured: status.configured,
|
|
123
|
+
mode: "managed",
|
|
124
|
+
...!status.configured ? { reason: "service_unavailable" } : {}
|
|
125
|
+
};
|
|
126
|
+
} catch (error) {
|
|
127
|
+
return {
|
|
128
|
+
configured: false,
|
|
129
|
+
mode: "managed",
|
|
130
|
+
reason: error instanceof ManagedComposioError && error.code === "insufficient_scope" ? "reauthorization_required" : error instanceof ManagedComposioError && error.status === 401 ? "signin_required" : "service_unavailable"
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { ManagedComposioClient, inspectManagedComposioStatus };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Config } from '../config/schema.js';
|
|
2
|
+
type ManagedEvent = {
|
|
3
|
+
sequence: number;
|
|
4
|
+
id: string;
|
|
5
|
+
type: string;
|
|
6
|
+
toolkit?: string;
|
|
7
|
+
connectionId?: string;
|
|
8
|
+
payload: unknown;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
};
|
|
11
|
+
type ManagedEventClient = {
|
|
12
|
+
events(after?: number, limit?: number): Promise<{
|
|
13
|
+
items: ManagedEvent[];
|
|
14
|
+
nextCursor: number;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
17
|
+
export declare class ManagedComposioEventPoller {
|
|
18
|
+
private readonly input;
|
|
19
|
+
private timer?;
|
|
20
|
+
private cursor;
|
|
21
|
+
private syncing?;
|
|
22
|
+
constructor(input: {
|
|
23
|
+
getConfig: () => Config;
|
|
24
|
+
triggerAutomation: (event: {
|
|
25
|
+
type: string;
|
|
26
|
+
source: string;
|
|
27
|
+
payload: Record<string, unknown>;
|
|
28
|
+
}) => Promise<unknown>;
|
|
29
|
+
requestLearning: (toolkit: string) => void;
|
|
30
|
+
setLearningPaused: (connectionId: string, paused: boolean) => void;
|
|
31
|
+
client?: ManagedEventClient;
|
|
32
|
+
hasByok?: () => Promise<boolean>;
|
|
33
|
+
intervalMs?: number;
|
|
34
|
+
});
|
|
35
|
+
start(): void;
|
|
36
|
+
stop(): void;
|
|
37
|
+
sync(): Promise<void>;
|
|
38
|
+
private runSync;
|
|
39
|
+
private process;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { claimConnectorWebhookDelivery, completeConnectorWebhookDelivery, releaseConnectorWebhookDelivery } from "../storage/sqlite/connector-repository.js";
|
|
4
|
+
import "../storage/sqlite/index.js";
|
|
5
|
+
import { resolveComposioApiKey } from "./composio-sessions.js";
|
|
6
|
+
import { ManagedComposioClient } from "./composio-managed-client.js";
|
|
7
|
+
import { appendComposioTriggerEvent, applyComposioConnectionLifecycleEvent, normalizeComposioTriggerPayload } from "./composio-triggers.js";
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
//#region src/connectors/composio-managed-events.ts
|
|
10
|
+
init_logger();
|
|
11
|
+
const log = createLogger("Connectors:ComposioManagedEvents");
|
|
12
|
+
function hasInstalledComposioToolkit(config) {
|
|
13
|
+
return Object.values(config.connectors?.instances ?? {}).some((value) => {
|
|
14
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
15
|
+
const runtime = value.runtime;
|
|
16
|
+
return Boolean(runtime && typeof runtime === "object" && !Array.isArray(runtime) && runtime.type === "composio" && runtime.role === "toolkit");
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
var ManagedComposioEventPoller = class {
|
|
20
|
+
timer;
|
|
21
|
+
cursor = 0;
|
|
22
|
+
syncing;
|
|
23
|
+
constructor(input) {
|
|
24
|
+
this.input = input;
|
|
25
|
+
}
|
|
26
|
+
start() {
|
|
27
|
+
if (this.timer) return;
|
|
28
|
+
this.sync().catch(() => {});
|
|
29
|
+
this.timer = setInterval(() => {
|
|
30
|
+
this.sync().catch(() => {});
|
|
31
|
+
}, this.input.intervalMs ?? 15e3);
|
|
32
|
+
this.timer.unref?.();
|
|
33
|
+
}
|
|
34
|
+
stop() {
|
|
35
|
+
if (this.timer) clearInterval(this.timer);
|
|
36
|
+
this.timer = void 0;
|
|
37
|
+
}
|
|
38
|
+
sync() {
|
|
39
|
+
this.syncing ??= this.runSync().finally(() => {
|
|
40
|
+
this.syncing = void 0;
|
|
41
|
+
});
|
|
42
|
+
return this.syncing;
|
|
43
|
+
}
|
|
44
|
+
async runSync() {
|
|
45
|
+
const config = this.input.getConfig();
|
|
46
|
+
const hasByok = this.input.hasByok ?? (async () => Boolean(await resolveComposioApiKey()));
|
|
47
|
+
if (!hasInstalledComposioToolkit(config) || await hasByok()) return;
|
|
48
|
+
const client = this.input.client ?? new ManagedComposioClient();
|
|
49
|
+
try {
|
|
50
|
+
for (let page = 0; page < 20; page += 1) {
|
|
51
|
+
const response = await client.events(this.cursor, 100);
|
|
52
|
+
for (const event of response.items) await this.process(config, event);
|
|
53
|
+
const next = Math.max(this.cursor, response.nextCursor);
|
|
54
|
+
if (next === this.cursor || response.items.length === 0) break;
|
|
55
|
+
this.cursor = next;
|
|
56
|
+
if (response.items.length < 100) break;
|
|
57
|
+
}
|
|
58
|
+
} catch (error) {
|
|
59
|
+
log.debug({
|
|
60
|
+
err: error,
|
|
61
|
+
phase: "event_poll"
|
|
62
|
+
}, "Managed Composio event poll skipped");
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async process(config, event) {
|
|
67
|
+
const payload = event.payload && typeof event.payload === "object" && !Array.isArray(event.payload) ? {
|
|
68
|
+
...event.payload,
|
|
69
|
+
id: event.id
|
|
70
|
+
} : {
|
|
71
|
+
id: event.id,
|
|
72
|
+
type: event.type,
|
|
73
|
+
data: event.payload
|
|
74
|
+
};
|
|
75
|
+
const hash = createHash("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
76
|
+
if (claimConnectorWebhookDelivery({
|
|
77
|
+
id: event.id,
|
|
78
|
+
provider: "composio",
|
|
79
|
+
payloadHash: hash
|
|
80
|
+
}) !== "claimed") return;
|
|
81
|
+
try {
|
|
82
|
+
const normalized = normalizeComposioTriggerPayload(payload, event.id);
|
|
83
|
+
const inactiveConnectionId = applyComposioConnectionLifecycleEvent(payload);
|
|
84
|
+
if (inactiveConnectionId) this.input.setLearningPaused(inactiveConnectionId, true);
|
|
85
|
+
await appendComposioTriggerEvent(config, payload);
|
|
86
|
+
const toolkit = normalized.toolkit ?? event.toolkit;
|
|
87
|
+
if (toolkit) this.input.requestLearning(toolkit);
|
|
88
|
+
await this.input.triggerAutomation({
|
|
89
|
+
type: `connector.${normalized.trigger ?? normalized.type}`,
|
|
90
|
+
source: toolkit ? `composio:${toolkit}` : "composio",
|
|
91
|
+
payload: {
|
|
92
|
+
...normalized.data,
|
|
93
|
+
connectorId: toolkit ? `composio-${toolkit}` : "composio",
|
|
94
|
+
webhookId: event.id
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
completeConnectorWebhookDelivery(event.id);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
releaseConnectorWebhookDelivery(event.id, error);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
//#endregion
|
|
105
|
+
export { ManagedComposioEventPoller };
|
|
@@ -2,7 +2,7 @@ import type { ToolRouterCreateSessionConfig } from '@composio/core';
|
|
|
2
2
|
import { CredentialResolver } from '../auth/credentials.js';
|
|
3
3
|
import type { ConnectorActionMetadata, ConnectorConnection, ConnectorInstallationPolicy } from './types.js';
|
|
4
4
|
export declare function resolveComposioApiKey(resolver?: CredentialResolver): Promise<string | null>;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function assertComposioAccessConfigured(resolver?: CredentialResolver): Promise<'byok' | 'managed'>;
|
|
6
6
|
export type ComposioToolkitCatalogItem = {
|
|
7
7
|
slug: string;
|
|
8
8
|
name: string;
|
|
@@ -72,6 +72,7 @@ export type ComposioSessionLike = {
|
|
|
72
72
|
}): Promise<unknown>;
|
|
73
73
|
};
|
|
74
74
|
export type ComposioSessionsClient = {
|
|
75
|
+
mode?: 'managed' | 'byok';
|
|
75
76
|
sessions: {
|
|
76
77
|
create(userId: string, config?: ToolRouterCreateSessionConfig): Promise<ComposioSessionLike>;
|
|
77
78
|
};
|
|
@@ -17,10 +17,10 @@ const COMPOSIO_API_KEY_PROVIDER = "connector-composio-api-key";
|
|
|
17
17
|
async function resolveComposioApiKey(resolver = new CredentialResolver()) {
|
|
18
18
|
return (await resolver.resolveApiKey(COMPOSIO_API_KEY_PROVIDER).catch(() => void 0))?.trim() || process.env.XOPC_COMPOSIO_API_KEY?.trim() || process.env.COMPOSIO_API_KEY?.trim() || null;
|
|
19
19
|
}
|
|
20
|
-
async function
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
20
|
+
async function assertComposioAccessConfigured(resolver = new CredentialResolver()) {
|
|
21
|
+
if (await resolveComposioApiKey(resolver)) return "byok";
|
|
22
|
+
if ((await resolver.resolveApiKey("xopc-cloud").catch(() => null))?.trim()) return "managed";
|
|
23
|
+
throw new Error("Composio API key is not configured and XOPC Cloud is not signed in. Install the \"Composio API Key\" connector first or sign in to XOPC Cloud.");
|
|
24
24
|
}
|
|
25
25
|
function stableHash(value) {
|
|
26
26
|
return createHash("sha256").update(value).digest("hex").slice(0, 24);
|
|
@@ -91,7 +91,11 @@ var ComposioSessionsAdapter = class {
|
|
|
91
91
|
}
|
|
92
92
|
const resolver = options.resolver ?? new CredentialResolver();
|
|
93
93
|
this.createClient = async () => {
|
|
94
|
-
const apiKey = await
|
|
94
|
+
const apiKey = await resolveComposioApiKey(resolver);
|
|
95
|
+
if (!apiKey) {
|
|
96
|
+
const { ManagedComposioClient } = await import("./composio-managed-client.js");
|
|
97
|
+
return new ManagedComposioClient();
|
|
98
|
+
}
|
|
95
99
|
let Composio;
|
|
96
100
|
let PiProvider;
|
|
97
101
|
try {
|
|
@@ -99,7 +103,7 @@ var ComposioSessionsAdapter = class {
|
|
|
99
103
|
} catch (cause) {
|
|
100
104
|
throw new Error("The xopc installation is missing the bundled Composio runtime. Reinstall @xopcai/xopc and restart the gateway.", { cause });
|
|
101
105
|
}
|
|
102
|
-
|
|
106
|
+
const client = new Composio({
|
|
103
107
|
apiKey,
|
|
104
108
|
baseURL: process.env.XOPC_COMPOSIO_BASE_URL?.trim() || void 0,
|
|
105
109
|
allowTracking: false,
|
|
@@ -109,6 +113,8 @@ var ComposioSessionsAdapter = class {
|
|
|
109
113
|
provider: new PiProvider(),
|
|
110
114
|
host: "xopc"
|
|
111
115
|
});
|
|
116
|
+
client.mode = "byok";
|
|
117
|
+
return client;
|
|
112
118
|
};
|
|
113
119
|
}
|
|
114
120
|
async createSession(context) {
|
|
@@ -375,4 +381,4 @@ var ComposioSessionsAdapter = class {
|
|
|
375
381
|
}
|
|
376
382
|
};
|
|
377
383
|
//#endregion
|
|
378
|
-
export { ComposioSessionsAdapter,
|
|
384
|
+
export { ComposioSessionsAdapter, assertComposioAccessConfigured, createComposioPrincipalId, resolveComposioApiKey };
|
|
@@ -2,7 +2,7 @@ import { getConnectorConnection, getConnectorInstallation, listConnectorConnecti
|
|
|
2
2
|
import { getConnectorAccount, refreshConnectorAccountCurrent } from "../storage/sqlite/connector-account-repository.js";
|
|
3
3
|
import { CredentialResolver, init_credentials } from "../auth/credentials.js";
|
|
4
4
|
import { connectorIdentityKey } from "./connector-identity.js";
|
|
5
|
-
import { ComposioSessionsAdapter } from "./composio-sessions.js";
|
|
5
|
+
import { ComposioSessionsAdapter, assertComposioAccessConfigured } from "./composio-sessions.js";
|
|
6
6
|
import { COMPOSIO_AGENT_READY_TOOLKITS, COMPOSIO_TOOLKIT_DISPLAY_NAMES, connectorDefinitionFromComposioToolkit } from "./composio-catalog.js";
|
|
7
7
|
import { consumeConnectorSetupSecretRef } from "./setup-secrets.js";
|
|
8
8
|
//#region src/connectors/composio.ts
|
|
@@ -370,6 +370,7 @@ async function listComposioConnections(resolver = new CredentialResolver()) {
|
|
|
370
370
|
async function inspectComposioConnectorHealth(toolkit, resolver = new CredentialResolver()) {
|
|
371
371
|
const normalizedToolkit = normalizeToolkit(toolkit);
|
|
372
372
|
try {
|
|
373
|
+
await assertComposioAccessConfigured(resolver);
|
|
373
374
|
const connections = (await listComposioConnections(resolver)).filter((connection) => connection.toolkit.toLowerCase() === normalizedToolkit);
|
|
374
375
|
const byAccount = /* @__PURE__ */ new Map();
|
|
375
376
|
for (const connection of connections) {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
1
3
|
import { getConnectorInstallation, listConnectorConnections } from "../storage/sqlite/connector-repository.js";
|
|
2
4
|
import "../storage/sqlite/index.js";
|
|
3
5
|
import { ComposioSessionsAdapter } from "./composio-sessions.js";
|
|
4
6
|
import { decodeConnectedSourceCursor, encodeConnectedSourceCursor } from "./connected-source-cursor.js";
|
|
5
7
|
import { scopeForComposioAction } from "./composio.js";
|
|
6
8
|
import { getConnectorDefinition } from "./catalog.js";
|
|
7
|
-
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
8
9
|
import { getConnectorInstance } from "./instances.js";
|
|
10
|
+
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
9
11
|
import { KnowledgeIngestionService } from "../knowledge/ingestion-service.js";
|
|
10
12
|
import { ConnectedKnowledgePipeline } from "../knowledge/connected-knowledge-pipeline.js";
|
|
11
13
|
import { LocalFolderKnowledgeSourceAdapter } from "../knowledge/local-folder-adapter.js";
|
|
@@ -14,6 +16,8 @@ import { normalizeConnectedSourceResult } from "./connected-source-normalizers.j
|
|
|
14
16
|
import { sanitizeConnectedSourceValue } from "./connected-source-sanitization.js";
|
|
15
17
|
import { createHash } from "node:crypto";
|
|
16
18
|
//#region src/connectors/connected-source-ingestion.ts
|
|
19
|
+
init_logger();
|
|
20
|
+
const log = createLogger("ConnectedSourceIngestion");
|
|
17
21
|
const COMPOSIO_CONNECTED_SOURCE_TOOLKITS = new Set([
|
|
18
22
|
"gmail",
|
|
19
23
|
"googlecalendar",
|
|
@@ -99,6 +103,17 @@ function paginationValue(result, ...keys) {
|
|
|
99
103
|
if (typeof value === "string" && value.trim()) return value.trim();
|
|
100
104
|
}
|
|
101
105
|
}
|
|
106
|
+
function isPayloadTooLargeError(error) {
|
|
107
|
+
const details = asRecord(error);
|
|
108
|
+
const status = details?.status ?? details?.statusCode;
|
|
109
|
+
const code = details?.code;
|
|
110
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
111
|
+
return String(status) === "413" || String(code) === "4345" || /\b413\b|ToolRouterV2_PayloadTooLarge|payload is too large/i.test(message);
|
|
112
|
+
}
|
|
113
|
+
function maxResultsValue(args) {
|
|
114
|
+
const value = args.max_results;
|
|
115
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
116
|
+
}
|
|
102
117
|
function resultToSourceItems(input) {
|
|
103
118
|
return normalizeConnectedSourceResult(input).slice(0, 200).map((entity) => {
|
|
104
119
|
const record = entity.value;
|
|
@@ -142,6 +157,7 @@ function resultToSourceItems(input) {
|
|
|
142
157
|
}
|
|
143
158
|
var ComposioKnowledgeSourceAdapter = class {
|
|
144
159
|
kind = "composio";
|
|
160
|
+
adaptiveMaxResults;
|
|
145
161
|
constructor(input) {
|
|
146
162
|
this.input = input;
|
|
147
163
|
}
|
|
@@ -149,32 +165,58 @@ var ComposioKnowledgeSourceAdapter = class {
|
|
|
149
165
|
const cursor = decodeConnectedSourceCursor(pull.cursor);
|
|
150
166
|
const scanStartedAt = cursor?.scanStartedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
151
167
|
const warnings = pull.cursor && !cursor ? ["Stored connected-source cursor was invalid and was replaced."] : [];
|
|
152
|
-
const execute = (cursorValue) =>
|
|
153
|
-
|
|
154
|
-
principalId: "local-owner",
|
|
155
|
-
toolkits: [this.input.toolkit]
|
|
156
|
-
},
|
|
157
|
-
installation: {
|
|
158
|
-
...this.input.installation,
|
|
159
|
-
maxScope: "read",
|
|
160
|
-
confirmationPolicy: "never"
|
|
161
|
-
},
|
|
162
|
-
connection: this.input.connection,
|
|
163
|
-
agentId: this.input.agentId,
|
|
164
|
-
action: {
|
|
165
|
-
connectorId: this.input.connectorId,
|
|
166
|
-
actionId: this.input.actionId,
|
|
167
|
-
toolkit: this.input.toolkit,
|
|
168
|
-
scope: "read",
|
|
169
|
-
curated: true,
|
|
170
|
-
cachedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
171
|
-
},
|
|
172
|
-
args: this.input.buildArguments?.({
|
|
168
|
+
const execute = async (cursorValue) => {
|
|
169
|
+
const configuredArgs = this.input.buildArguments?.({
|
|
173
170
|
...pull,
|
|
174
171
|
cursor: cursorValue
|
|
175
|
-
}) ?? this.input.arguments
|
|
176
|
-
|
|
177
|
-
|
|
172
|
+
}) ?? this.input.arguments;
|
|
173
|
+
const configuredMaxResults = maxResultsValue(configuredArgs);
|
|
174
|
+
let args = this.adaptiveMaxResults && configuredMaxResults && configuredMaxResults > this.adaptiveMaxResults ? {
|
|
175
|
+
...configuredArgs,
|
|
176
|
+
max_results: this.adaptiveMaxResults
|
|
177
|
+
} : configuredArgs;
|
|
178
|
+
for (;;) try {
|
|
179
|
+
return await this.input.adapter.executeWithPolicy({
|
|
180
|
+
context: {
|
|
181
|
+
principalId: "local-owner",
|
|
182
|
+
toolkits: [this.input.toolkit]
|
|
183
|
+
},
|
|
184
|
+
installation: {
|
|
185
|
+
...this.input.installation,
|
|
186
|
+
maxScope: "read",
|
|
187
|
+
confirmationPolicy: "never"
|
|
188
|
+
},
|
|
189
|
+
connection: this.input.connection,
|
|
190
|
+
agentId: this.input.agentId,
|
|
191
|
+
action: {
|
|
192
|
+
connectorId: this.input.connectorId,
|
|
193
|
+
actionId: this.input.actionId,
|
|
194
|
+
toolkit: this.input.toolkit,
|
|
195
|
+
scope: "read",
|
|
196
|
+
curated: true,
|
|
197
|
+
cachedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
198
|
+
},
|
|
199
|
+
args,
|
|
200
|
+
confirmed: true
|
|
201
|
+
});
|
|
202
|
+
} catch (error) {
|
|
203
|
+
const currentMaxResults = maxResultsValue(args);
|
|
204
|
+
if (!isPayloadTooLargeError(error) || !currentMaxResults || currentMaxResults <= 1) throw error;
|
|
205
|
+
const reducedMaxResults = Math.max(1, Math.floor(currentMaxResults / 2));
|
|
206
|
+
this.adaptiveMaxResults = reducedMaxResults;
|
|
207
|
+
log.info({
|
|
208
|
+
connectorId: this.input.connectorId,
|
|
209
|
+
actionId: this.input.actionId,
|
|
210
|
+
previousMaxResults: currentMaxResults,
|
|
211
|
+
maxResults: reducedMaxResults,
|
|
212
|
+
phase: "payload_too_large_retry"
|
|
213
|
+
}, `Retrying connector action with page size ${reducedMaxResults}`);
|
|
214
|
+
args = {
|
|
215
|
+
...args,
|
|
216
|
+
max_results: reducedMaxResults
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
};
|
|
178
220
|
let execution;
|
|
179
221
|
try {
|
|
180
222
|
execution = await execute(pull.cursor);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
2
1
|
import { materializeConnectorMcpServer } from "./materialize.js";
|
|
3
2
|
import { getConnectorInstance } from "./instances.js";
|
|
3
|
+
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
4
4
|
import { listBundleMcpServerCapabilitiesForGateway } from "../agent/mcp/bundle-mcp-gateway.js";
|
|
5
5
|
//#region src/connectors/health.ts
|
|
6
6
|
function classifyConnectorHealthError(error) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isXopcDatabaseOpen } from "../storage/sqlite/connection.js";
|
|
2
2
|
import { deleteConnectorInstallation, getConnectorInstallation, upsertConnectorInstallation } from "../storage/sqlite/connector-repository.js";
|
|
3
3
|
import "../storage/sqlite/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import { assertComposioAccessConfigured } from "./composio-sessions.js";
|
|
5
5
|
import { saveComposioApiKey } from "./composio.js";
|
|
6
6
|
import { saveConnectorSecrets } from "./secret-store.js";
|
|
7
7
|
import { isManagedConnectorServer, materializeConnectorMcpServer } from "./materialize.js";
|
|
@@ -106,7 +106,7 @@ registerConnectorRuntimeAdapter({
|
|
|
106
106
|
async install({ config, definition, input, resolver }) {
|
|
107
107
|
if (definition.runtime.type !== "composio") throw new Error(`Invalid Composio connector definition: ${definition.id}`);
|
|
108
108
|
if (definition.runtime.role === "credential") await saveComposioApiKey(input, resolver);
|
|
109
|
-
if (definition.runtime.role === "toolkit") await
|
|
109
|
+
if (definition.runtime.role === "toolkit") await assertComposioAccessConfigured(resolver);
|
|
110
110
|
const instance = installRecord(config, definition, definition.runtime.role === "toolkit" ? { scope: "read" } : {}, definition.runtime.role === "toolkit" ? { config: input.config ?? {} } : {});
|
|
111
111
|
if (definition.runtime.role === "toolkit" && isXopcDatabaseOpen()) {
|
|
112
112
|
const installationId = `${definition.id}-local-owner`;
|
|
@@ -6,7 +6,7 @@ import { isSTTAvailable } from "../voice/stt/availability.js";
|
|
|
6
6
|
import { mergeSttConfigFromAppConfig } from "../voice/stt/config.js";
|
|
7
7
|
import "../voice/stt/index.js";
|
|
8
8
|
import { getDiscussionCapture, listDiscussionCaptures, listDiscussionTranscriptSegments, updateDiscussionCapture } from "./repository.js";
|
|
9
|
-
import {
|
|
9
|
+
import { appendSequentialTranscript, assembleDiscussionTranscript } from "./transcript.js";
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
//#region src/discussions/sealer.ts
|
|
12
12
|
init_logger();
|
|
@@ -96,7 +96,7 @@ var DiscussionSealer = class {
|
|
|
96
96
|
mime: "audio/wav",
|
|
97
97
|
fileName: `discussion-recovery-${index}.wav`
|
|
98
98
|
});
|
|
99
|
-
text =
|
|
99
|
+
text = appendSequentialTranscript(text, result.text);
|
|
100
100
|
language ??= result.language;
|
|
101
101
|
});
|
|
102
102
|
return {
|
|
@@ -153,13 +153,16 @@ var DiscussionService = class {
|
|
|
153
153
|
uploadSegment(input) {
|
|
154
154
|
const capture = getDiscussionCapture(input.discussionId);
|
|
155
155
|
if (!capture) throw new DiscussionServiceError("not_found", "Discussion not found");
|
|
156
|
-
|
|
156
|
+
const acceptsSegments = capture.status === "recording" || capture.status === "stopping";
|
|
157
|
+
const originalRecordingSupersedesSegment = capture.audioAttachmentId && (capture.status === "sealing" || capture.status === "organizing" || capture.status === "completed");
|
|
158
|
+
if (!acceptsSegments && !originalRecordingSupersedesSegment) throw new DiscussionServiceError("conflict", "Discussion no longer accepts transcript segments");
|
|
157
159
|
if (!Number.isInteger(input.sequence) || input.sequence < 0 || input.sequence > 2e3) throw new DiscussionServiceError("invalid_input", "Invalid segment sequence");
|
|
158
160
|
if (input.file.mimeType !== "audio/wav" && input.file.mimeType !== "audio/x-wav") throw new DiscussionServiceError("invalid_input", "Live transcript segments must be WAV audio");
|
|
159
161
|
if (input.file.buffer.length === 0 || input.file.buffer.length > 2097152) throw new DiscussionServiceError("invalid_input", "Live transcript segment is empty or too large");
|
|
160
162
|
if (!Number.isFinite(input.startedAtMs) || !Number.isFinite(input.endedAtMs) || input.startedAtMs < 0 || input.endedAtMs <= input.startedAtMs || input.endedAtMs - input.startedAtMs > 25e3) throw new DiscussionServiceError("invalid_input", "Invalid live transcript segment timing");
|
|
161
163
|
const actualSha256 = createHash("sha256").update(input.file.buffer).digest("hex");
|
|
162
164
|
if (input.sha256 !== actualSha256) throw new DiscussionServiceError("invalid_input", "Segment checksum mismatch");
|
|
165
|
+
if (originalRecordingSupersedesSegment) return this.transcript(input.discussionId);
|
|
163
166
|
const existing = getDiscussionTranscriptSegment(input.discussionId, input.sequence);
|
|
164
167
|
if (existing && existing.audioSha256 !== actualSha256) throw new DiscussionServiceError("conflict", "Segment sequence already contains different audio");
|
|
165
168
|
if (!existing) {
|
|
@@ -219,7 +222,8 @@ var DiscussionService = class {
|
|
|
219
222
|
name: file.name.trim().slice(0, 200) || `discussion-${id}.webm`,
|
|
220
223
|
buffer: file.buffer,
|
|
221
224
|
mimeType: file.mimeType,
|
|
222
|
-
duration: Math.round(durationMs / 1e3)
|
|
225
|
+
duration: Math.round(durationMs / 1e3),
|
|
226
|
+
retainWithoutReference: true
|
|
223
227
|
});
|
|
224
228
|
if (!attachment) throw new DiscussionServiceError("not_found", "Discussion note not found");
|
|
225
229
|
try {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { DiscussionTranscriptSegment } from './types.js';
|
|
2
|
+
/** Joins transcripts from adjacent audio chunks that have no audio overlap. */
|
|
3
|
+
export declare function appendSequentialTranscript(existing: string, next: string): string;
|
|
2
4
|
export declare function appendTranscriptWithoutOverlap(existing: string, next: string): string;
|
|
3
5
|
export declare function assembleDiscussionTranscript(segments: DiscussionTranscriptSegment[]): string;
|
|
@@ -15,7 +15,20 @@ function searchableCharacters(value) {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
function joinOverlap(left, remainder) {
|
|
18
|
-
|
|
18
|
+
const next = /\p{P}$/u.test(left) ? remainder.replace(/^\p{P}+/u, "") : remainder;
|
|
19
|
+
if (!next || /^\s/u.test(next)) return `${left}${next}`.trim();
|
|
20
|
+
const leftCharacter = Array.from(left).findLast((character) => /[\p{L}\p{N}\p{S}]/u.test(character));
|
|
21
|
+
const rightCharacter = Array.from(next).find((character) => /[\p{L}\p{N}\p{S}]/u.test(character));
|
|
22
|
+
const compactScript = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
|
|
23
|
+
return `${left}${leftCharacter && rightCharacter && !compactScript.test(leftCharacter) && !compactScript.test(rightCharacter) ? " " : ""}${next}`.trim();
|
|
24
|
+
}
|
|
25
|
+
/** Joins transcripts from adjacent audio chunks that have no audio overlap. */
|
|
26
|
+
function appendSequentialTranscript(existing, next) {
|
|
27
|
+
const left = existing.trim();
|
|
28
|
+
const right = next.trim();
|
|
29
|
+
if (!left) return right;
|
|
30
|
+
if (!right) return left;
|
|
31
|
+
return `${left}\n${right}`;
|
|
19
32
|
}
|
|
20
33
|
function appendTranscriptWithoutOverlap(existing, next) {
|
|
21
34
|
const left = existing.trim();
|
|
@@ -32,10 +45,10 @@ function appendTranscriptWithoutOverlap(existing, next) {
|
|
|
32
45
|
const sourceEnd = rightSearchable.sourceEnds[size - 1];
|
|
33
46
|
return joinOverlap(left, right.slice(sourceEnd));
|
|
34
47
|
}
|
|
35
|
-
return
|
|
48
|
+
return appendSequentialTranscript(left, right);
|
|
36
49
|
}
|
|
37
50
|
function assembleDiscussionTranscript(segments) {
|
|
38
51
|
return segments.reduce((text, segment) => appendTranscriptWithoutOverlap(text, segment.displayText ?? ""), "");
|
|
39
52
|
}
|
|
40
53
|
//#endregion
|
|
41
|
-
export { appendTranscriptWithoutOverlap, assembleDiscussionTranscript };
|
|
54
|
+
export { appendSequentialTranscript, appendTranscriptWithoutOverlap, assembleDiscussionTranscript };
|
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
* Supports installing from npm packages, local directories, and xopc-store zips
|
|
4
4
|
* Supports three-tier storage: workspace, global, bundled
|
|
5
5
|
*/
|
|
6
|
+
export type ValidatedNpmPackageSpec = {
|
|
7
|
+
ok: true;
|
|
8
|
+
packageName: string;
|
|
9
|
+
version?: string;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
error: string;
|
|
13
|
+
};
|
|
14
|
+
/** Accept registry package names with an optional exact semver; reject URLs, paths, tags, and ranges. */
|
|
15
|
+
export declare function validateNpmPackageSpec(packageSpec: string): ValidatedNpmPackageSpec;
|
|
6
16
|
export interface InstallOptions {
|
|
7
17
|
source: 'npm' | 'local';
|
|
8
18
|
targetDir: string;
|