@xopcai/xopc 0.0.210 → 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-JLmEb1p0.js → activity-store-Xw-pOm9A.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CI1zQfzY.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-C6MmWfcb.js → api-CZK-lRew.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-Cd02GGpV.js → app-management-settings-panel-BLFIG09j.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-Db-h2I3G.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-CMHzJT2a.js → archive-plugin-B9LsFfEx.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-BzhI2LoH.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-DsUeHvZO.js → binary-plugins-DbqhT_JB.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CFfsIeZ4.js → block-editor-BGpHwxZ5.js} +4 -4
- package/dist/gateway/static/root/assets/browser-settings-page-CrhpQl-e.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-BiWghvJ0.js → browser-workflow-inputs-BXlon_hL.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DPLdT6Zn.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-CTxGFvsS.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-BklVUOxC.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-0F4Jmma2.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-BvIZ51ty.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-BHmwaMbO.js → cron-expression-DzQN7zBR.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-fj_pPCv5.js → date-picker-B-r5O5qd.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-DsWvwOv-.js → dependency-picker-Ch2XBU2s.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-mjkF0Xxh.js → desktop-pet-BdjX8jde.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-ClwUpRYu.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-DC69wplH.js → extension-debug-page-6OGgOucD.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DCtk6zdJ.js → extension-page-Cf6MUfCF.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-Bkm4zzv-.js → extension-settings-page-pSY_ZvQZ.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-Dr_NQt7v.js → gateway-config-api-CFJMng9v.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-CEfv8N1J.js → gateway-config-swr-DpiY6aub.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-aQYxNePf.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-B8hebJ7s.js → gateway-startup-retry-BZ_6ChP4.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-CI33q9i1.js +1 -0
- package/dist/gateway/static/root/assets/home-page-CAIaWs6r.js +1 -0
- package/dist/gateway/static/root/assets/image-generation-api-DPndEWOU.js +1 -0
- 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-DCQvf05d.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-B3Ugd0my.js → local-apps-page-Crf6c3SK.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-hDBVeG3G.js → locale-store-BYSRjM6g.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-nXdF3wOT.js → logs-page-BpfLQWex.js} +2 -2
- package/dist/gateway/static/root/assets/{management-settings-C-S5Llq3.js → management-settings-mxyYWKgM.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-DuVq37Uh.js → markdown-split-kZaPrUTM.js} +1 -1
- package/dist/gateway/static/root/assets/markdown-view-DD_PgVue.css +1 -0
- package/dist/gateway/static/root/assets/{markdown-view-D8eO_6h3.js → markdown-view-DlsczsQ1.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-C1V6pkX3.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-Dn71ZV8c.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-B5a5aSoS.js → page-tabs-C4UkhX2U.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-5041AIBX.js → preview-open-alternatives-nzcjh6y0.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-7UkouFQU.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-DvaXzHYS.js → runtime-tools-settings-panel-CVqPSfUb.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-Dlxl_5X0.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-CSaiuuer.js → settings-form-section-BaWFAZv4.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-H3mJwt3r.js → settings-loading-skeleton-BWmdZfNg.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-Cs7zA4BS.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-Bdpw5m7M.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-Bup3Lg1Z.js → skills-page-Bi2IWpU0.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-D22ORR21.js → skills-page.utils-BancvwN2.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-GmtWsfjB.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-CtY8RwMX.js → theme-store-D1_t_31B.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-C2aOdlEA.js → typed-models-lib-C2LhiQq5.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-DOj5i8d_.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-5WfurWYa.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-bBA8LinI.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 +13 -11
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +1 -1
- package/dist/src/agent/image/generation/providers/xopc-cloud.js +2 -1
- package/dist/src/agent/image/tool-model-config.js +15 -9
- package/dist/src/agent/memory/builtin-provider.js +0 -1
- package/dist/src/agent/memory/create-memory-manager.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +23 -7
- package/dist/src/agent-runtime/index.js +1 -1
- package/dist/src/agent-runtime/runtime-profile.js +1 -1
- package/dist/src/auth/oauth/xopc-cloud.js +1 -1
- package/dist/src/capabilities/readiness/from-config.d.ts +10 -0
- package/dist/src/capabilities/readiness/from-config.js +128 -0
- package/dist/src/capabilities/readiness/index.d.ts +3 -0
- package/dist/src/capabilities/readiness/index.js +3 -0
- package/dist/src/capabilities/readiness/planner.d.ts +3 -0
- package/dist/src/capabilities/readiness/planner.js +56 -0
- package/dist/src/capabilities/readiness/types.d.ts +35 -0
- package/dist/src/capabilities/readiness/types.js +1 -0
- package/dist/src/cli/commands/agent.js +9 -0
- package/dist/src/cli/commands/auth.js +4 -3
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/models.js +2 -1
- package/dist/src/cli/commands/onboard/model.d.ts +3 -21
- package/dist/src/cli/commands/onboard/model.js +10 -86
- package/dist/src/cli/commands/tunnel.js +3 -3
- package/dist/src/cli/utils/oauth-login.d.ts +2 -0
- package/dist/src/cli/utils/oauth-login.js +9 -1
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/paths-state.d.ts +2 -0
- package/dist/src/config/paths-state.js +5 -1
- package/dist/src/config/paths.d.ts +1 -1
- package/dist/src/config/paths.js +2 -2
- package/dist/src/config/schema.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 +3 -1
- package/dist/src/connectors/composio-sessions.js +15 -8
- package/dist/src/connectors/composio.js +10 -4
- package/dist/src/connectors/connected-source-cursor.d.ts +9 -0
- package/dist/src/connectors/connected-source-cursor.js +30 -0
- package/dist/src/connectors/connected-source-ingestion.js +128 -65
- package/dist/src/connectors/connected-source-normalizers.d.ts +1 -0
- package/dist/src/connectors/connected-source-normalizers.js +33 -2
- package/dist/src/connectors/connected-source-sanitization.d.ts +1 -0
- package/dist/src/connectors/connected-source-sanitization.js +21 -0
- package/dist/src/connectors/connector-identity.js +10 -2
- package/dist/src/connectors/content-enrichment.d.ts +29 -0
- package/dist/src/connectors/content-enrichment.js +273 -0
- package/dist/src/connectors/learning-coordinator.js +1 -2
- package/dist/src/connectors/learning-recipes.js +30 -33
- package/dist/src/connectors/runtime-adapter-registry.js +2 -2
- package/dist/src/discussions/live-worker.d.ts +1 -0
- package/dist/src/discussions/live-worker.js +7 -1
- package/dist/src/discussions/repository.js +11 -1
- package/dist/src/discussions/sealer.d.ts +1 -1
- package/dist/src/discussions/sealer.js +16 -7
- package/dist/src/discussions/service.js +6 -2
- package/dist/src/discussions/transcript.d.ts +2 -0
- package/dist/src/discussions/transcript.js +42 -3
- package/dist/src/discussions/types.d.ts +4 -0
- 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/hono/app.js +8 -3
- 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.d.ts +4 -0
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +9 -2
- package/dist/src/gateway/hono/oauth-async.d.ts +11 -5
- package/dist/src/gateway/hono/oauth-async.js +29 -16
- package/dist/src/gateway/hono/oauth.d.ts +1 -3
- package/dist/src/gateway/hono/oauth.js +22 -22
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/connectors.js +10 -3
- package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
- package/dist/src/gateway/hono/routes/discussions.js +2 -1
- 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/lazy-bundles.js +2 -1
- package/dist/src/gateway/hono/routes/models.js +59 -5
- 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/understanding-sources.js +29 -0
- package/dist/src/gateway/hono/routes/voice.d.ts +1 -2
- package/dist/src/gateway/hono/routes/voice.js +16 -35
- package/dist/src/gateway/hono/routes/workflows.js +69 -0
- package/dist/src/gateway/index.js +2 -2
- package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
- package/dist/src/gateway/rate-limit/buckets.js +12 -0
- 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/session-input-coordinator.js +1 -2
- package/dist/src/gateway/service.d.ts +1 -0
- package/dist/src/gateway/service.js +37 -7
- package/dist/src/knowledge/connected-understanding-pipeline.d.ts +1 -1
- package/dist/src/knowledge/connected-understanding-pipeline.js +74 -25
- package/dist/src/knowledge/ingestion-service.js +33 -15
- package/dist/src/knowledge/types.d.ts +2 -0
- package/dist/src/media-understanding/audio-transcription-runner.d.ts +2 -0
- package/dist/src/media-understanding/audio-transcription-runner.js +3 -1
- package/dist/src/media-understanding/runner.js +3 -1
- package/dist/src/media-understanding/types.d.ts +2 -0
- 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 +9 -0
- package/dist/src/providers/model-catalog-persistence.js +172 -0
- package/dist/src/providers/model-catalog-ranking.d.ts +2 -0
- package/dist/src/providers/model-catalog-ranking.js +17 -0
- package/dist/src/providers/model-catalog-store.d.ts +9 -57
- package/dist/src/providers/model-catalog-store.js +24 -5
- package/dist/src/providers/model-catalog-sync-service.d.ts +3 -3
- package/dist/src/providers/model-catalog-sync-service.js +12 -7
- 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-auth-service.d.ts +1 -0
- package/dist/src/providers/provider-auth-service.js +3 -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 +3 -0
- package/dist/src/providers/provider-disconnect.js +11 -0
- package/dist/src/providers/xopc-cloud-catalog-coordinator.d.ts +56 -0
- package/dist/src/providers/xopc-cloud-catalog-coordinator.js +182 -0
- package/dist/src/providers/xopc-cloud-model-source.d.ts +6 -10
- package/dist/src/providers/xopc-cloud-model-source.js +49 -27
- package/dist/src/storage/sqlite/knowledge-repository.d.ts +1 -0
- package/dist/src/storage/sqlite/knowledge-repository.js +4 -0
- 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/storage/sqlite/user-context-quality-repository.d.ts +8 -0
- package/dist/src/storage/sqlite/user-context-quality-repository.js +21 -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/backends/embedded-backend.js +11 -3
- package/dist/src/tui/tui-oauth-login.js +5 -0
- package/dist/src/tui/xopc-tui-keybindings.d.ts +2 -2
- package/dist/src/tunnel/index.js +2 -2
- package/dist/src/user-context/sources/activity-clustering.js +30 -117
- package/dist/src/user-context/sources/index.d.ts +1 -0
- package/dist/src/user-context/sources/index.js +2 -1
- package/dist/src/user-context/sources/signal-clustering.d.ts +18 -0
- package/dist/src/user-context/sources/signal-clustering.js +131 -0
- package/dist/src/voice/audio/normalize.d.ts +18 -0
- package/dist/src/voice/audio/normalize.js +175 -0
- package/dist/src/voice/language-profile.d.ts +1 -4
- package/dist/src/voice/language-profile.js +2 -25
- package/dist/src/voice/local/runtime-client.d.ts +2 -0
- package/dist/src/voice/local/runtime-client.js +20 -1
- package/dist/src/voice/local/runtime-worker.js +7 -13
- package/dist/src/voice/local/wav.d.ts +3 -0
- package/dist/src/voice/local/wav.js +11 -5
- package/dist/src/voice/stt/availability.d.ts +1 -4
- package/dist/src/voice/stt/availability.js +3 -15
- package/dist/src/voice/stt/config.js +1 -0
- package/dist/src/voice/stt/factory.js +23 -0
- package/dist/src/voice/stt/index.d.ts +1 -0
- package/dist/src/voice/stt/index.js +2 -2
- package/dist/src/voice/stt/list-providers.js +1 -1
- package/dist/src/voice/stt/providers/local-transcription.js +7 -3
- package/dist/src/voice/stt/providers/xopc-cloud-transcription.js +3 -1
- package/dist/src/voice/stt/transcribe-core.d.ts +5 -1
- package/dist/src/voice/stt/transcribe-core.js +13 -5
- package/dist/src/voice/stt/types.d.ts +2 -0
- package/dist/src/voice/tts/factory.d.ts +1 -1
- package/dist/src/voice/tts/factory.js +23 -1
- package/dist/src/voice/tts/merge-config.js +5 -3
- package/dist/src/voice/tts/providers/xopc-cloud-speech.js +3 -1
- package/dist/src/voice/tts/types.d.ts +2 -0
- package/dist/src/voice/tts/types.js +4 -2
- package/dist/src/work-discovery/evaluation.d.ts +23 -0
- package/dist/src/work-discovery/evaluation.js +18 -1
- package/dist/src/work-discovery/index.js +2 -2
- 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 +9 -8
- package/dist/gateway/static/root/assets/agents-DqGMj3QJ.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-BT7F4WBI.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-CwOXGV9z.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-CyRLhCod.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-jRKcS7lZ.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-B3bKdtwU.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-yZBWH02s.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-C3zlimZd.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-OX4KvUkA.js +0 -2
- package/dist/gateway/static/root/assets/directory-picker-path-field-OkqRFyRL.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-V1XVxjHa.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-CWUBAQrE.js +0 -1
- package/dist/gateway/static/root/assets/home-page-D57cYRd3.js +0 -1
- package/dist/gateway/static/root/assets/index-DJ7HSgKs.js +0 -85
- package/dist/gateway/static/root/assets/index-PNBFdxHb.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-BbAiMZE1.js +0 -2
- package/dist/gateway/static/root/assets/markdown-view-B12xeflb.css +0 -1
- package/dist/gateway/static/root/assets/messages-1qg_hOOd.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-BYPoZeRw.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-D27nOKbo.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CdB5cJJ-.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DFoZ3UNS.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-C1cbIcJ7.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DnXRlQXS.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CwgMODfJ.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-hlUgIkrp.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DR31B_Gz.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-CTKDpxhf.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-keJJYpix.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-D5_MH3n3.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-BcvBiebt.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-Cz2VpWdj.js +0 -5
- package/dist/src/voice/local/runtime-dispatcher.d.ts +0 -9
- package/dist/src/voice/local/runtime-dispatcher.js +0 -20
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { getKnowledgeSourceItem, listKnowledgeSourceItems, upsertKnowledgeSourceItems } from "../storage/sqlite/knowledge-repository.js";
|
|
2
|
+
import { getConnectorConnection, getConnectorInstallation } from "../storage/sqlite/connector-repository.js";
|
|
3
|
+
import "../storage/sqlite/index.js";
|
|
4
|
+
import { ComposioSessionsAdapter } from "./composio-sessions.js";
|
|
5
|
+
import { ConnectedKnowledgePipeline } from "../knowledge/connected-knowledge-pipeline.js";
|
|
6
|
+
import { sanitizeConnectedSourceValue } from "./connected-source-sanitization.js";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { isAbsolute, join, relative, sep } from "node:path";
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import { mkdtemp, readFile, realpath, rm } from "node:fs/promises";
|
|
11
|
+
//#region src/connectors/content-enrichment.ts
|
|
12
|
+
const MAX_SELECTION = 5;
|
|
13
|
+
const MAX_CONTENT_BYTES = 1e6;
|
|
14
|
+
const MAX_CONTENT_CHARS = 24e3;
|
|
15
|
+
const GOOGLE_DOCUMENT_MIME = "application/vnd.google-apps.document";
|
|
16
|
+
const DOWNLOADABLE_TEXT_MIMES = new Set([
|
|
17
|
+
"application/json",
|
|
18
|
+
"application/xml",
|
|
19
|
+
"text/csv",
|
|
20
|
+
"text/html",
|
|
21
|
+
"text/markdown",
|
|
22
|
+
"text/plain",
|
|
23
|
+
"text/tab-separated-values",
|
|
24
|
+
"text/xml"
|
|
25
|
+
]);
|
|
26
|
+
function record(value) {
|
|
27
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
28
|
+
}
|
|
29
|
+
function normalizedRecord(item) {
|
|
30
|
+
if (!item.normalizedText) return {};
|
|
31
|
+
try {
|
|
32
|
+
return record(JSON.parse(item.normalizedText));
|
|
33
|
+
} catch {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function text(value) {
|
|
38
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
39
|
+
}
|
|
40
|
+
function candidateFor(item) {
|
|
41
|
+
if (item.deletedAt || item.sensitivity === "secret" || item.sensitivity === "regulated") return void 0;
|
|
42
|
+
const toolkit = text(item.metadata.toolkit);
|
|
43
|
+
const value = normalizedRecord(item);
|
|
44
|
+
const title = text(value.title) ?? text(value.subject);
|
|
45
|
+
if (!title) return void 0;
|
|
46
|
+
if (toolkit === "gmail" && item.itemType === "email") return {
|
|
47
|
+
sourceItemId: item.id,
|
|
48
|
+
sourceInstanceId: item.sourceInstanceId,
|
|
49
|
+
toolkit,
|
|
50
|
+
title,
|
|
51
|
+
occurredAt: item.occurredAt
|
|
52
|
+
};
|
|
53
|
+
const mimeType = text(item.metadata.mimeType) ?? text(value.mimeType);
|
|
54
|
+
if (toolkit === "googledrive" && item.itemType === "cloud_document" && mimeType && (mimeType === GOOGLE_DOCUMENT_MIME || DOWNLOADABLE_TEXT_MIMES.has(mimeType))) return {
|
|
55
|
+
sourceItemId: item.id,
|
|
56
|
+
sourceInstanceId: item.sourceInstanceId,
|
|
57
|
+
toolkit,
|
|
58
|
+
title,
|
|
59
|
+
occurredAt: item.occurredAt,
|
|
60
|
+
mimeType
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function listConnectedContentCandidates(options) {
|
|
64
|
+
const limit = Math.max(1, Math.min(20, options.limit ?? 10));
|
|
65
|
+
const items = listKnowledgeSourceItems({
|
|
66
|
+
agentId: options.agentId,
|
|
67
|
+
includeDeleted: false,
|
|
68
|
+
limit: 500
|
|
69
|
+
});
|
|
70
|
+
const completedReads = new Set(items.map((item) => text(item.metadata.sourceMetadataItemId)).filter((id) => Boolean(id)));
|
|
71
|
+
return items.filter((item) => !completedReads.has(item.id)).map(candidateFor).filter((candidate) => Boolean(candidate)).slice(0, limit);
|
|
72
|
+
}
|
|
73
|
+
function contentRecipe(item) {
|
|
74
|
+
const toolkit = text(item.metadata.toolkit);
|
|
75
|
+
if (toolkit === "gmail" && item.itemType === "email") return {
|
|
76
|
+
actionId: "GMAIL_GET_EMAIL",
|
|
77
|
+
args: { message_id: item.externalId },
|
|
78
|
+
mode: "inline"
|
|
79
|
+
};
|
|
80
|
+
const value = normalizedRecord(item);
|
|
81
|
+
const mimeType = text(item.metadata.mimeType) ?? text(value.mimeType);
|
|
82
|
+
if (toolkit === "googledrive" && item.itemType === "cloud_document" && mimeType === GOOGLE_DOCUMENT_MIME) return {
|
|
83
|
+
actionId: "GOOGLEDRIVE_EXPORT_GOOGLE_WORKSPACE_FILE",
|
|
84
|
+
args: {
|
|
85
|
+
fileId: item.externalId,
|
|
86
|
+
mimeType: "text/plain"
|
|
87
|
+
},
|
|
88
|
+
mode: "file"
|
|
89
|
+
};
|
|
90
|
+
if (toolkit === "googledrive" && item.itemType === "cloud_document" && mimeType && DOWNLOADABLE_TEXT_MIMES.has(mimeType)) return {
|
|
91
|
+
actionId: "GOOGLEDRIVE_DOWNLOAD_FILE",
|
|
92
|
+
args: { file_id: item.externalId },
|
|
93
|
+
mode: "file"
|
|
94
|
+
};
|
|
95
|
+
throw new Error("This source item does not support bounded content reading.");
|
|
96
|
+
}
|
|
97
|
+
function collectInlineText(value, output, depth = 0) {
|
|
98
|
+
if (depth > 8 || output.join("\n").length >= MAX_CONTENT_CHARS) return;
|
|
99
|
+
if (Array.isArray(value)) {
|
|
100
|
+
for (const item of value) collectInlineText(item, output, depth + 1);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const row = record(value);
|
|
104
|
+
for (const [key, nested] of Object.entries(row)) {
|
|
105
|
+
if (typeof nested === "string" && [
|
|
106
|
+
"body",
|
|
107
|
+
"content",
|
|
108
|
+
"plainText",
|
|
109
|
+
"plain_text",
|
|
110
|
+
"snippet",
|
|
111
|
+
"text"
|
|
112
|
+
].includes(key)) {
|
|
113
|
+
if (nested.trim()) output.push(nested.trim());
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (nested && typeof nested === "object") collectInlineText(nested, output, depth + 1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function inlineContent(result) {
|
|
120
|
+
const values = [];
|
|
121
|
+
collectInlineText(result, values);
|
|
122
|
+
return [...new Set(values)].join("\n\n").slice(0, MAX_CONTENT_CHARS);
|
|
123
|
+
}
|
|
124
|
+
function candidateFilePaths(value, output, depth = 0) {
|
|
125
|
+
if (depth > 8) return;
|
|
126
|
+
if (typeof value === "string") {
|
|
127
|
+
if (value.startsWith("file://")) output.push(new URL(value).pathname);
|
|
128
|
+
else if (isAbsolute(value)) output.push(value);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (Array.isArray(value)) {
|
|
132
|
+
for (const item of value) candidateFilePaths(item, output, depth + 1);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
for (const nested of Object.values(record(value))) candidateFilePaths(nested, output, depth + 1);
|
|
136
|
+
}
|
|
137
|
+
async function downloadedContent(result, downloadDirectory) {
|
|
138
|
+
const directory = await realpath(downloadDirectory);
|
|
139
|
+
const paths = [];
|
|
140
|
+
candidateFilePaths(result, paths);
|
|
141
|
+
for (const path of paths) {
|
|
142
|
+
const resolved = await realpath(path).catch(() => void 0);
|
|
143
|
+
if (!resolved) continue;
|
|
144
|
+
const pathFromDirectory = relative(directory, resolved);
|
|
145
|
+
if (pathFromDirectory.startsWith(`..${sep}`) || pathFromDirectory === ".." || isAbsolute(pathFromDirectory)) continue;
|
|
146
|
+
const content = await readFile(resolved);
|
|
147
|
+
if (content.byteLength > MAX_CONTENT_BYTES) throw new Error("Downloaded content exceeds the 1 MB read limit.");
|
|
148
|
+
return content.toString("utf8").slice(0, MAX_CONTENT_CHARS);
|
|
149
|
+
}
|
|
150
|
+
throw new Error("The connector did not return readable text content.");
|
|
151
|
+
}
|
|
152
|
+
function updatedSourceItem(item, content, actionId) {
|
|
153
|
+
const contentReadAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
154
|
+
const sanitizedContent = String(sanitizeConnectedSourceValue(content));
|
|
155
|
+
const normalizedText = JSON.stringify({
|
|
156
|
+
...normalizedRecord(item),
|
|
157
|
+
content: sanitizedContent,
|
|
158
|
+
contentReadAt
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
sourceInstanceId: item.sourceInstanceId,
|
|
162
|
+
collectionScope: "content-reads",
|
|
163
|
+
externalId: item.id,
|
|
164
|
+
itemType: "connected_content",
|
|
165
|
+
authorRole: item.authorRole,
|
|
166
|
+
occurredAt: item.occurredAt,
|
|
167
|
+
sourceUpdatedAt: item.sourceUpdatedAt,
|
|
168
|
+
contentHash: createHash("sha256").update(normalizedText).digest("hex"),
|
|
169
|
+
normalizedText,
|
|
170
|
+
payloadRef: item.payloadRef,
|
|
171
|
+
metadata: {
|
|
172
|
+
...item.metadata,
|
|
173
|
+
explicitContentRead: true,
|
|
174
|
+
sourceMetadataItemId: item.id,
|
|
175
|
+
contentReadActionId: actionId,
|
|
176
|
+
contentReadAt
|
|
177
|
+
},
|
|
178
|
+
sensitivity: item.sensitivity,
|
|
179
|
+
retentionClass: "bounded",
|
|
180
|
+
synthesisPipeline: "connected_knowledge",
|
|
181
|
+
synthesisStatus: "pending"
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
async function readConnectedContent(input) {
|
|
185
|
+
const sourceItemIds = [...new Set(input.sourceItemIds.map((id) => id.trim()).filter(Boolean))];
|
|
186
|
+
if (!sourceItemIds.length || sourceItemIds.length > MAX_SELECTION) throw new Error(`Select between 1 and ${MAX_SELECTION} source items.`);
|
|
187
|
+
const downloadDirectory = await mkdtemp(join(tmpdir(), "xopc-content-read-"));
|
|
188
|
+
const adapter = input.adapterFactory?.(downloadDirectory) ?? new ComposioSessionsAdapter({ fileDownloadDir: downloadDirectory });
|
|
189
|
+
const result = {
|
|
190
|
+
requested: sourceItemIds.length,
|
|
191
|
+
completed: 0,
|
|
192
|
+
failed: [],
|
|
193
|
+
recordIds: []
|
|
194
|
+
};
|
|
195
|
+
const updatedSources = /* @__PURE__ */ new Set();
|
|
196
|
+
const completedReads = new Set(listKnowledgeSourceItems({
|
|
197
|
+
agentId: input.agentId,
|
|
198
|
+
includeDeleted: false,
|
|
199
|
+
limit: 500
|
|
200
|
+
}).map((item) => text(item.metadata.sourceMetadataItemId)).filter((id) => Boolean(id)));
|
|
201
|
+
try {
|
|
202
|
+
for (const sourceItemId of sourceItemIds) try {
|
|
203
|
+
const item = getKnowledgeSourceItem(sourceItemId);
|
|
204
|
+
if (!item || item.deletedAt || item.metadata.agentId !== input.agentId) throw new Error("Source item is unavailable.");
|
|
205
|
+
if (completedReads.has(item.id)) throw new Error("Source item content was already read.");
|
|
206
|
+
if (!candidateFor(item)) throw new Error("Source item is not eligible for content reading.");
|
|
207
|
+
const connectorId = text(item.metadata.connectorId);
|
|
208
|
+
const connectionId = text(item.metadata.connectionId);
|
|
209
|
+
const toolkit = text(item.metadata.toolkit);
|
|
210
|
+
if (!connectorId || !connectionId || !toolkit) throw new Error("Source item has incomplete connector provenance.");
|
|
211
|
+
const connection = getConnectorConnection(connectionId);
|
|
212
|
+
const installation = getConnectorInstallation(`${connectorId}-local-owner`);
|
|
213
|
+
if (!connection || connection.status !== "active" || !installation?.enabled) throw new Error("The connected account is not active.");
|
|
214
|
+
const recipe = contentRecipe(item);
|
|
215
|
+
const execution = await adapter.executeWithPolicy({
|
|
216
|
+
context: {
|
|
217
|
+
principalId: connection.principalId,
|
|
218
|
+
toolkits: [toolkit]
|
|
219
|
+
},
|
|
220
|
+
installation: {
|
|
221
|
+
...installation,
|
|
222
|
+
maxScope: "read",
|
|
223
|
+
confirmationPolicy: "always"
|
|
224
|
+
},
|
|
225
|
+
connection,
|
|
226
|
+
agentId: input.agentId,
|
|
227
|
+
action: {
|
|
228
|
+
connectorId,
|
|
229
|
+
actionId: recipe.actionId,
|
|
230
|
+
toolkit,
|
|
231
|
+
scope: "read",
|
|
232
|
+
curated: true,
|
|
233
|
+
cachedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
234
|
+
},
|
|
235
|
+
args: recipe.args,
|
|
236
|
+
confirmed: true
|
|
237
|
+
});
|
|
238
|
+
if (execution.decision !== "allowed") throw new Error(execution.reason);
|
|
239
|
+
const content = recipe.mode === "inline" ? inlineContent(execution.result) : await downloadedContent(execution.result, downloadDirectory);
|
|
240
|
+
if (!content.trim()) throw new Error("The connector returned empty text content.");
|
|
241
|
+
upsertKnowledgeSourceItems([updatedSourceItem(item, content, recipe.actionId)]);
|
|
242
|
+
completedReads.add(item.id);
|
|
243
|
+
updatedSources.add(item.sourceInstanceId);
|
|
244
|
+
result.completed += 1;
|
|
245
|
+
} catch (error) {
|
|
246
|
+
result.failed.push({
|
|
247
|
+
sourceItemId,
|
|
248
|
+
error: error instanceof Error ? error.message : String(error)
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
for (const sourceInstanceId of updatedSources) {
|
|
252
|
+
const item = listKnowledgeSourceItems({
|
|
253
|
+
sourceInstanceId,
|
|
254
|
+
synthesisStatus: "pending",
|
|
255
|
+
limit: 1
|
|
256
|
+
})[0];
|
|
257
|
+
if (!item) continue;
|
|
258
|
+
const synthesized = await new ConnectedKnowledgePipeline({
|
|
259
|
+
agentId: input.agentId,
|
|
260
|
+
workspaceId: text(item.metadata.workspaceId) ?? "default"
|
|
261
|
+
}).processPending(sourceInstanceId);
|
|
262
|
+
result.recordIds.push(...synthesized.recordIds);
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
265
|
+
} finally {
|
|
266
|
+
await rm(downloadDirectory, {
|
|
267
|
+
recursive: true,
|
|
268
|
+
force: true
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
//#endregion
|
|
273
|
+
export { listConnectedContentCandidates, readConnectedContent };
|
|
@@ -27,7 +27,6 @@ function connectorSourceCategory(toolkit) {
|
|
|
27
27
|
if (toolkit === "gmail") return "mail";
|
|
28
28
|
if (toolkit === "googlecalendar") return "calendar";
|
|
29
29
|
if (toolkit === "github" || toolkit === "linear") return "code_activity";
|
|
30
|
-
if (toolkit === "slack") return "messages";
|
|
31
30
|
return "files";
|
|
32
31
|
}
|
|
33
32
|
function ensureUnderstandingSourceRun(job, toolkit, displayName) {
|
|
@@ -189,7 +188,7 @@ function startConnectorLearningCoordinator(options) {
|
|
|
189
188
|
itemsIndexed
|
|
190
189
|
}));
|
|
191
190
|
publish(updateConnectorLearningJob(job.id, { phase: "deriving" }));
|
|
192
|
-
const understanding = await new ConnectedUnderstandingPipeline(options.getMemoryManager()).process(job.
|
|
191
|
+
const understanding = await new ConnectedUnderstandingPipeline(options.getMemoryManager()).process(job.agentId);
|
|
193
192
|
for (const record of understanding.createdRecords.filter((item) => item.kind === "project_context")) upsertUserFocus({
|
|
194
193
|
canonicalKey: `connector-focus:${job.accountId}:${record.id}`,
|
|
195
194
|
title: record.content.slice(0, 120),
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { decodeConnectedSourceCursor } from "./connected-source-cursor.js";
|
|
1
2
|
//#region src/connectors/learning-recipes.ts
|
|
2
3
|
function buildConnectorLearningArguments(plan, stream, input, identity) {
|
|
4
|
+
const cursor = decodeConnectedSourceCursor(input.cursor);
|
|
3
5
|
if (plan.toolkit === "github" && stream.scope === "authored-work") {
|
|
4
6
|
const username = typeof identity.username === "string" ? identity.username.trim() : "";
|
|
5
7
|
if (!username) throw new Error("GitHub activity sync requires the authenticated username.");
|
|
@@ -8,18 +10,28 @@ function buildConnectorLearningArguments(plan, stream, input, identity) {
|
|
|
8
10
|
q: `author:${username} sort:updated-desc`
|
|
9
11
|
};
|
|
10
12
|
}
|
|
11
|
-
if (!input.cursor) return { ...stream.arguments };
|
|
12
13
|
if (plan.toolkit === "gmail") {
|
|
13
|
-
const after = Math.floor(Date.parse(
|
|
14
|
-
return
|
|
14
|
+
const after = cursor?.checkpoint ? Math.floor(Date.parse(cursor.checkpoint) / 1e3) : NaN;
|
|
15
|
+
return {
|
|
15
16
|
...stream.arguments,
|
|
16
|
-
query: `after:${after} -in:spam -in:trash`
|
|
17
|
-
|
|
17
|
+
...Number.isFinite(after) ? { query: `after:${after} -in:spam -in:trash` } : {},
|
|
18
|
+
...cursor?.pageToken ? { page_token: cursor.pageToken } : {}
|
|
19
|
+
};
|
|
18
20
|
}
|
|
19
21
|
if (plan.toolkit === "googlecalendar") return {
|
|
20
22
|
...stream.arguments,
|
|
21
|
-
|
|
23
|
+
...cursor?.syncToken ? { sync_token: cursor.syncToken } : {},
|
|
24
|
+
...cursor?.pageToken ? { page_token: cursor.pageToken } : {}
|
|
22
25
|
};
|
|
26
|
+
if (plan.toolkit === "googledrive") {
|
|
27
|
+
const checkpoint = cursor?.checkpoint && Number.isFinite(Date.parse(cursor.checkpoint)) ? cursor.checkpoint : void 0;
|
|
28
|
+
const baseQuery = typeof stream.arguments.q === "string" ? stream.arguments.q : "";
|
|
29
|
+
return {
|
|
30
|
+
...stream.arguments,
|
|
31
|
+
...checkpoint ? { q: [baseQuery, `modifiedTime > '${checkpoint}'`].filter(Boolean).join(" and ") } : {},
|
|
32
|
+
...cursor?.pageToken ? { pageToken: cursor.pageToken } : {}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
23
35
|
return { ...stream.arguments };
|
|
24
36
|
}
|
|
25
37
|
const PLANS = {
|
|
@@ -32,6 +44,8 @@ const PLANS = {
|
|
|
32
44
|
kind: "activity",
|
|
33
45
|
arguments: {
|
|
34
46
|
max_results: 100,
|
|
47
|
+
include_payload: false,
|
|
48
|
+
verbose: false,
|
|
35
49
|
query: "newer_than:30d -in:spam -in:trash"
|
|
36
50
|
}
|
|
37
51
|
}],
|
|
@@ -42,47 +56,30 @@ const PLANS = {
|
|
|
42
56
|
toolkit: "googlecalendar",
|
|
43
57
|
streams: [{
|
|
44
58
|
scope: "events",
|
|
45
|
-
actionId: "
|
|
59
|
+
actionId: "GOOGLECALENDAR_SYNC_EVENTS",
|
|
46
60
|
kind: "activity",
|
|
47
|
-
arguments: { max_results:
|
|
61
|
+
arguments: { max_results: 500 }
|
|
48
62
|
}],
|
|
49
63
|
bootstrapWindowDays: 90,
|
|
50
64
|
intervalMinutes: 15
|
|
51
65
|
},
|
|
52
66
|
googledrive: {
|
|
53
67
|
toolkit: "googledrive",
|
|
68
|
+
identityProbe: { actionId: "GOOGLEDRIVE_GET_ABOUT" },
|
|
54
69
|
streams: [{
|
|
55
70
|
scope: "files",
|
|
56
|
-
actionId: "
|
|
71
|
+
actionId: "GOOGLEDRIVE_FIND_FILE",
|
|
57
72
|
kind: "inventory",
|
|
58
|
-
arguments: {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
toolkit: "notion",
|
|
65
|
-
streams: [{
|
|
66
|
-
scope: "pages",
|
|
67
|
-
actionId: "NOTION_SEARCH",
|
|
68
|
-
kind: "inventory",
|
|
69
|
-
arguments: {}
|
|
73
|
+
arguments: {
|
|
74
|
+
q: "trashed = false",
|
|
75
|
+
orderBy: "modifiedTime desc",
|
|
76
|
+
pageSize: 100,
|
|
77
|
+
fields: "nextPageToken,files(id,name,mimeType,createdTime,modifiedTime,owners,webViewLink,trashed)"
|
|
78
|
+
}
|
|
70
79
|
}],
|
|
71
80
|
bootstrapWindowDays: 90,
|
|
72
81
|
intervalMinutes: 30
|
|
73
82
|
},
|
|
74
|
-
slack: {
|
|
75
|
-
toolkit: "slack",
|
|
76
|
-
identityProbe: { actionId: "SLACK_TEST_AUTH" },
|
|
77
|
-
streams: [{
|
|
78
|
-
scope: "channels",
|
|
79
|
-
actionId: "SLACK_LIST_CHANNELS",
|
|
80
|
-
kind: "inventory",
|
|
81
|
-
arguments: {}
|
|
82
|
-
}],
|
|
83
|
-
bootstrapWindowDays: 30,
|
|
84
|
-
intervalMinutes: 15
|
|
85
|
-
},
|
|
86
83
|
github: {
|
|
87
84
|
toolkit: "github",
|
|
88
85
|
identityProbe: { actionId: "GITHUB_GET_THE_AUTHENTICATED_USER" },
|
|
@@ -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`;
|
|
@@ -42,13 +42,19 @@ var DiscussionLiveWorker = class {
|
|
|
42
42
|
if (this.running) return;
|
|
43
43
|
this.running = true;
|
|
44
44
|
try {
|
|
45
|
-
await Promise.all(Array.from({ length: this.
|
|
45
|
+
await Promise.all(Array.from({ length: this.resolveConcurrency() }, () => this.processOne()));
|
|
46
46
|
} finally {
|
|
47
47
|
this.running = false;
|
|
48
48
|
const waiters = this.stoppedWaiters.splice(0);
|
|
49
49
|
for (const resolve of waiters) resolve();
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
+
resolveConcurrency() {
|
|
53
|
+
if (this.deps.transcribeSegment) return this.concurrency;
|
|
54
|
+
const config = this.deps.getConfig();
|
|
55
|
+
const sttConfig = mergeSttConfigFromAppConfig(config.tools?.media?.audio, config.tools?.media);
|
|
56
|
+
return sttConfig.provider === "xopc-local" || sttConfig.provider === "local" ? 1 : this.concurrency;
|
|
57
|
+
}
|
|
52
58
|
async processOne() {
|
|
53
59
|
const segment = claimNextDiscussionTranscriptSegment(this.owner);
|
|
54
60
|
if (!segment) return;
|
|
@@ -128,13 +128,23 @@ function getDiscussionMetrics() {
|
|
|
128
128
|
WHERE s.discussion_id = d.id AND s.status = 'confirmed') - d.recording_started_at) first_ms,
|
|
129
129
|
AVG(CASE WHEN d.completed_at IS NOT NULL THEN d.completed_at - d.recording_started_at END) complete_ms
|
|
130
130
|
FROM discussion_captures d`).get();
|
|
131
|
+
const segmentMetrics = db.prepare(`SELECT
|
|
132
|
+
COUNT(*) total,
|
|
133
|
+
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) failed,
|
|
134
|
+
SUM(CASE WHEN attempt_count > 1 THEN 1 ELSE 0 END) retried,
|
|
135
|
+
AVG(CASE WHEN status = 'confirmed' THEN updated_at - created_at END) latency_ms
|
|
136
|
+
FROM discussion_transcript_segments`).get();
|
|
131
137
|
const byStatus = Object.fromEntries(DISCUSSION_STATUSES.map((status) => [status, 0]));
|
|
132
138
|
for (const row of rows) byStatus[row.status] = row.count;
|
|
133
139
|
return {
|
|
134
140
|
total: rows.reduce((sum, row) => sum + row.count, 0),
|
|
135
141
|
byStatus,
|
|
136
142
|
averageTimeToFirstTranscriptMs: timing.first_ms == null ? null : Math.max(0, Math.round(timing.first_ms)),
|
|
137
|
-
averageTimeToCompleteMs: timing.complete_ms == null ? null : Math.max(0, Math.round(timing.complete_ms))
|
|
143
|
+
averageTimeToCompleteMs: timing.complete_ms == null ? null : Math.max(0, Math.round(timing.complete_ms)),
|
|
144
|
+
totalSegments: segmentMetrics.total,
|
|
145
|
+
failedSegments: segmentMetrics.failed ?? 0,
|
|
146
|
+
retriedSegments: segmentMetrics.retried ?? 0,
|
|
147
|
+
averageSegmentLatencyMs: segmentMetrics.latency_ms == null ? null : Math.max(0, Math.round(segmentMetrics.latency_ms))
|
|
138
148
|
};
|
|
139
149
|
}
|
|
140
150
|
function updateDiscussionCapture(id, patch, expectedStatuses) {
|
|
@@ -4,7 +4,7 @@ import type { DiscussionCapture } from './types.js';
|
|
|
4
4
|
export interface DiscussionSealerDeps {
|
|
5
5
|
notes: NotesService;
|
|
6
6
|
getConfig: () => Config;
|
|
7
|
-
transcribeRecording?: (
|
|
7
|
+
transcribeRecording?: (filePath: string, capture: DiscussionCapture, signal?: AbortSignal) => Promise<{
|
|
8
8
|
text: string;
|
|
9
9
|
language?: string;
|
|
10
10
|
}>;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { forEachNormalizedAudioSegment } from "../voice/audio/normalize.js";
|
|
3
4
|
import { transcribe } from "../voice/stt/transcribe-core.js";
|
|
4
5
|
import { isSTTAvailable } from "../voice/stt/availability.js";
|
|
5
6
|
import { mergeSttConfigFromAppConfig } from "../voice/stt/config.js";
|
|
6
7
|
import "../voice/stt/index.js";
|
|
7
8
|
import { getDiscussionCapture, listDiscussionCaptures, listDiscussionTranscriptSegments, updateDiscussionCapture } from "./repository.js";
|
|
8
|
-
import { assembleDiscussionTranscript } from "./transcript.js";
|
|
9
|
+
import { appendSequentialTranscript, assembleDiscussionTranscript } from "./transcript.js";
|
|
9
10
|
import { createHash } from "node:crypto";
|
|
10
|
-
import { readFile } from "node:fs/promises";
|
|
11
11
|
//#region src/discussions/sealer.ts
|
|
12
12
|
init_logger();
|
|
13
13
|
const log = createLogger("DiscussionSealer");
|
|
@@ -85,15 +85,24 @@ var DiscussionSealer = class {
|
|
|
85
85
|
async transcribeFullRecording(capture) {
|
|
86
86
|
const attachment = await this.deps.notes.getAttachmentPath(capture.noteId, capture.audioAttachmentId);
|
|
87
87
|
if (!attachment) throw new Error("Discussion audio file is missing");
|
|
88
|
-
|
|
89
|
-
if (this.deps.transcribeRecording) return this.deps.transcribeRecording(buffer, capture);
|
|
88
|
+
if (this.deps.transcribeRecording) return this.deps.transcribeRecording(attachment.filePath, capture);
|
|
90
89
|
const config = this.deps.getConfig();
|
|
91
90
|
const sttConfig = mergeSttConfigFromAppConfig(config.tools?.media?.audio, config.tools?.media);
|
|
92
91
|
if (!isSTTAvailable(sttConfig)) throw new Error("STT is not configured");
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
let text = "";
|
|
93
|
+
let language;
|
|
94
|
+
await forEachNormalizedAudioSegment({ filePath: attachment.filePath }, async (buffer, index) => {
|
|
95
|
+
const result = await transcribe(buffer, sttConfig, {
|
|
96
|
+
mime: "audio/wav",
|
|
97
|
+
fileName: `discussion-recovery-${index}.wav`
|
|
98
|
+
});
|
|
99
|
+
text = appendSequentialTranscript(text, result.text);
|
|
100
|
+
language ??= result.language;
|
|
96
101
|
});
|
|
102
|
+
return {
|
|
103
|
+
text,
|
|
104
|
+
...language ? { language } : {}
|
|
105
|
+
};
|
|
97
106
|
}
|
|
98
107
|
fail(capture, stage, code, message) {
|
|
99
108
|
const current = getDiscussionCapture(capture.id);
|
|
@@ -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;
|
|
@@ -1,15 +1,54 @@
|
|
|
1
1
|
//#region src/discussions/transcript.ts
|
|
2
|
+
function searchableCharacters(value) {
|
|
3
|
+
let text = "";
|
|
4
|
+
const sourceEnds = [];
|
|
5
|
+
let sourceOffset = 0;
|
|
6
|
+
for (const character of value) {
|
|
7
|
+
sourceOffset += character.length;
|
|
8
|
+
if (!/[\p{L}\p{N}]/u.test(character)) continue;
|
|
9
|
+
text += character.toLocaleLowerCase();
|
|
10
|
+
sourceEnds.push(sourceOffset);
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
text,
|
|
14
|
+
sourceEnds
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function joinOverlap(left, remainder) {
|
|
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}`;
|
|
32
|
+
}
|
|
2
33
|
function appendTranscriptWithoutOverlap(existing, next) {
|
|
3
34
|
const left = existing.trim();
|
|
4
35
|
const right = next.trim();
|
|
5
36
|
if (!left) return right;
|
|
6
37
|
if (!right) return left;
|
|
7
38
|
const max = Math.min(200, left.length, right.length);
|
|
8
|
-
for (let size = max; size >= 8; size -= 1) if (left.slice(-size).toLocaleLowerCase() === right.slice(0, size).toLocaleLowerCase()) return
|
|
9
|
-
|
|
39
|
+
for (let size = max; size >= 8; size -= 1) if (left.slice(-size).toLocaleLowerCase() === right.slice(0, size).toLocaleLowerCase()) return joinOverlap(left, right.slice(size));
|
|
40
|
+
const leftSearchable = searchableCharacters(left).text.slice(-200);
|
|
41
|
+
const rightSearchable = searchableCharacters(right);
|
|
42
|
+
const normalizedMax = Math.min(leftSearchable.length, rightSearchable.text.length);
|
|
43
|
+
for (let size = normalizedMax; size >= 5; size -= 1) {
|
|
44
|
+
if (leftSearchable.slice(-size) !== rightSearchable.text.slice(0, size)) continue;
|
|
45
|
+
const sourceEnd = rightSearchable.sourceEnds[size - 1];
|
|
46
|
+
return joinOverlap(left, right.slice(sourceEnd));
|
|
47
|
+
}
|
|
48
|
+
return appendSequentialTranscript(left, right);
|
|
10
49
|
}
|
|
11
50
|
function assembleDiscussionTranscript(segments) {
|
|
12
51
|
return segments.reduce((text, segment) => appendTranscriptWithoutOverlap(text, segment.displayText ?? ""), "");
|
|
13
52
|
}
|
|
14
53
|
//#endregion
|
|
15
|
-
export { appendTranscriptWithoutOverlap, assembleDiscussionTranscript };
|
|
54
|
+
export { appendSequentialTranscript, appendTranscriptWithoutOverlap, assembleDiscussionTranscript };
|
|
@@ -132,6 +132,10 @@ export interface DiscussionMetrics {
|
|
|
132
132
|
byStatus: Record<DiscussionStatus, number>;
|
|
133
133
|
averageTimeToFirstTranscriptMs: number | null;
|
|
134
134
|
averageTimeToCompleteMs: number | null;
|
|
135
|
+
totalSegments: number;
|
|
136
|
+
failedSegments: number;
|
|
137
|
+
retriedSegments: number;
|
|
138
|
+
averageSegmentLatencyMs: number | null;
|
|
135
139
|
}
|
|
136
140
|
export interface DiscussionDetail {
|
|
137
141
|
discussion: DiscussionCapture;
|
|
@@ -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;
|