@xopcai/xopc 0.0.269 → 0.0.272
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/dist/assets/{auth-cwEj8rFb.js → auth-C1QI-uMG.js} +65 -14
- package/dist/browser-ext/dist/background.js +23 -2
- package/dist/browser-ext/dist/pairing-handoff.js +51 -0
- package/dist/browser-ext/dist/sidepanel.html +1 -1
- package/dist/browser-ext/dist/sidepanel.js +39 -27
- package/dist/browser-ext/manifest.json +12 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-DcwCSY6s.js → activity-store-DffqjeqQ.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-D0NBOWC4.js → agent-avatar-dicebear-Cwj4HCYY.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-6CLfLxVc.js +1 -0
- package/dist/gateway/static/root/assets/agents-B6mu64fY.js +1 -0
- package/dist/gateway/static/root/assets/{api-eaPO-mdr.js → api-CGLdye4i.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-E3xm2teY.js → app-management-settings-panel-BLujSbaw.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-CiZOjgls.js → appearance-settings-BXMcueb8.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BEgy4hY3.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-D09yo_Hc.js → archive-plugin-D4bUampf.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CNYb8Qru.js → attachment-load-CBGNA2Ys.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-DsrfW5ii.js → automations-page-dQyolNmy.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-DxRFrmrV.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-OWlaGqlY.js → binary-plugins-bbvp81h2.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CVND3M6r.js → block-editor-C8e6Wri4.js} +3 -3
- package/dist/gateway/static/root/assets/{browser-automation-inputs-D7IzVK_J.js → browser-automation-inputs-oJWJtQa6.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-CQ6cCpIv.js → browser-automations-page-CAcJQSjN.js} +2 -2
- package/dist/gateway/static/root/assets/browser-settings-page-TLAlqcPo.js +8 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-z-K_jrZz.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-Dzrk33aB.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-D4JrgJKa.js → channels-status-swr-CfOPNnVr.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-BUjnhT7C.js → chat-terminal-dock-9ZOl92kh.js} +2 -2
- package/dist/gateway/static/root/assets/clock-3-DnrAnuyZ.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-B1dIoRNi.js +2 -0
- package/dist/gateway/static/root/assets/cron-expression-C26e13YU.js +2 -0
- package/dist/gateway/static/root/assets/date-picker-Dj6FRLF9.js +1 -0
- package/dist/gateway/static/root/assets/{dependency-picker-Z6Nf0Wjq.js → dependency-picker-D1q89tVc.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-C0F5Iqnc.js → desktop-pet-DfqZBvhp.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-Bj_W6HL1.js → desktop-pet-settings-HCEh2MOm.js} +1 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-CPth92s6.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-Ba09EnAn.js → extension-debug-page-C8cAWVoK.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-C88aGXJs.js → extension-page-5N87Vaym.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-D85SAUFP.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-swr-bjzk_4hn.js → gateway-config-swr-BjsDnB_n.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-Dqx8PmcT.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DrbIzFyB.js → gateway-startup-retry-BIf0eLWX.js} +1 -1
- package/dist/gateway/static/root/assets/git-branch-Dh9uxTot.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-BpDWGE1a.js +1 -0
- package/dist/gateway/static/root/assets/home-page-DJaqpC8-.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-CBWU9Ner.js → image-generation-api-1m8xTVS_.js} +1 -1
- package/dist/gateway/static/root/assets/index-C6PmD0cK.js +74 -0
- package/dist/gateway/static/root/assets/index-DKy1Qn1_.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B8Z7kKQY.js → keyboard-shortcuts-settings-Byy8mCSq.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-l2AEiG2C.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-CLSfzkRp.js → local-apps-page-BPo0wBgM.js} +1 -1
- package/dist/gateway/static/root/assets/locale-store-CRNble2Z.js +1 -0
- package/dist/gateway/static/root/assets/logs-page-X5FdLlXK.js +2 -0
- package/dist/gateway/static/root/assets/management-settings-DT6NoIjm.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-view-DIcfrLmG.js → markdown-view-AglreSOj.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-CSv6-xTA.js → media-plugins-Bzka9qXu.js} +1 -1
- package/dist/gateway/static/root/assets/message-circle-Badhj-4D.js +1 -0
- package/dist/gateway/static/root/assets/message-square-fVE7Ghj1.js +1 -0
- package/dist/gateway/static/root/assets/{messages-BRjoarIr.js → messages-DH_HCgmw.js} +3 -3
- package/dist/gateway/static/root/assets/note-detail-panel-BUJPoaGZ.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-BwFpWRuo.js +8 -0
- package/dist/gateway/static/root/assets/{page-tabs-BfV-PQa5.js → page-tabs-Ys0p65Lt.js} +1 -1
- package/dist/gateway/static/root/assets/popover-select-Dz_Qis2R.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-DQS7NFpg.js → preview-open-alternatives-iknB5xEp.js} +1 -1
- package/dist/gateway/static/root/assets/proactive-card-BPZDgNNR.js +1 -0
- package/dist/gateway/static/root/assets/proactive-page-CxdZR-p2.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-BIhjZLKg.js → product-open-page-W1o3f-kz.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-BU1RKAcy.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-z0X0tL8G.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-CwveUfe8.js → registry-api-DmYFpjsH.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-NNTut2I8.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DMQ0wpNg.js → runtime-tools-settings-panel-DP1XyYO8.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-C91g2PRU.js → schema-form-BMYKdzsH.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-B6SsHlz5.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BQu8bAcN.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-Cem6L49Y.js → settings-form-section-2LGjz7bu.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-afDUxqlV.js → settings-page-7DjpC9_C.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Dj9jFWJt.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-CVEVHksg.js → share-preview-page-BxYdSi8c.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CMqE0KuK.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BXqSJymN.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-CNrq1W6C.js → skills-page-DNEScMZH.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page.utils-q88l65YU.js +1 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-BLE8PxWE.js → system-settings-panel-8NIssGKj.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-L6dp9v2y.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-BejLVjIT.js → theme-store-BXZG3S25.js} +1 -1
- package/dist/gateway/static/root/assets/tunnel-api-CWsRPM84.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-DmgEA8Qb.js → use-autosave-BwQuoTQU.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-D4BucMrZ.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-sZ0J83SF.js → voice-api-key-field-Bd03Ic0s.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-BEbz3avx.js → voice-config-api-gggUp3u9.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-BXnAlbmO.js → work-discovery-overlay-DF8PR_pK.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BkwFey0a.js → workflow-run-setup-panel-BiAAWlir.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-DryKUMfA.js +6 -0
- package/dist/gateway/static/root/index.html +15 -11
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/device-pairing.js +2 -1
- package/dist/packages/gateway-contract/src/notifications.js +2 -2
- package/dist/packages/gateway-contract/src/proactive.js +22 -6
- package/dist/packages/gateway-contract/src/session-identity.js +37 -0
- package/dist/src/agent/memory/compaction-chunks.d.ts +18 -0
- package/dist/src/agent/memory/compaction-chunks.js +53 -0
- package/dist/src/agent/memory/compaction-request.d.ts +12 -0
- package/dist/src/agent/memory/compaction-request.js +72 -0
- package/dist/src/agent/memory/compaction.d.ts +3 -0
- package/dist/src/agent/memory/compaction.js +166 -118
- package/dist/src/agent/service.js +1 -0
- package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
- package/dist/src/agent/tool-manuals/xopc-use.js +19 -1
- package/dist/src/agent/tools/factory.js +1 -0
- package/dist/src/agent/tools/xopc-use-tool.d.ts +3 -2
- package/dist/src/agent/tools/xopc-use-tool.js +48 -4
- package/dist/src/browser/automations/schema.d.ts +1 -1
- package/dist/src/browser/automations/service.d.ts +1 -1
- package/dist/src/browser/native-messaging-host.js +3 -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 +5 -0
- package/dist/src/connectors/connected-source-ingestion.js +1 -1
- package/dist/src/connectors/connected-source-normalizers.js +3 -0
- package/dist/src/connectors/connection-recovery-service.js +1 -1
- package/dist/src/connectors/health.js +1 -1
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/app.js +1 -0
- package/dist/src/gateway/hono/middleware/auth.d.ts +1 -2
- package/dist/src/gateway/hono/middleware/auth.js +49 -31
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +11 -15
- package/dist/src/gateway/hono/routes/browser-session.d.ts +3 -0
- package/dist/src/gateway/hono/routes/browser-session.js +43 -0
- package/dist/src/gateway/hono/routes/capabilities.js +1 -1
- package/dist/src/gateway/hono/routes/connectors.js +1 -1
- package/dist/src/gateway/hono/routes/devices.js +61 -96
- package/dist/src/gateway/hono/routes/exposure.js +3 -7
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/mcp.js +1 -1
- package/dist/src/gateway/hono/routes/models.js +60 -1
- package/dist/src/gateway/hono/routes/notes.js +3 -7
- package/dist/src/gateway/hono/routes/proactive-control.js +31 -24
- package/dist/src/gateway/hono/routes/sessions.js +11 -0
- package/dist/src/gateway/hono/routes/shares.js +8 -20
- package/dist/src/gateway/hono/routes/site-shares.js +4 -8
- package/dist/src/gateway/hono/routes/tunnel.js +13 -13
- package/dist/src/gateway/image-generation-setup.d.ts +17 -0
- package/dist/src/gateway/image-generation-setup.js +30 -21
- package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
- package/dist/src/gateway/rate-limit/buckets.js +10 -0
- package/dist/src/gateway/runtime-config.js +2 -0
- package/dist/src/gateway/security/browser-session.d.ts +5 -0
- package/dist/src/gateway/security/browser-session.js +45 -0
- package/dist/src/gateway/security/gateway-principal.d.ts +1 -0
- package/dist/src/gateway/service.d.ts +1 -0
- package/dist/src/gateway/service.js +21 -11
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/rate-limit/keyed-store.d.ts +3 -0
- package/dist/src/infra/rate-limit/keyed-store.js +9 -2
- package/dist/src/notifications/web-push.js +1 -1
- package/dist/src/proactive/actions/service.js +4 -2
- package/dist/src/proactive/execution/authorization.d.ts +2 -0
- package/dist/src/proactive/execution/authorization.js +39 -1
- package/dist/src/proactive/execution/context.d.ts +4 -0
- package/dist/src/proactive/execution/context.js +51 -5
- package/dist/src/proactive/execution/insight.js +3 -1
- package/dist/src/proactive/execution/repository.js +15 -5
- package/dist/src/proactive/execution/types.d.ts +2 -0
- package/dist/src/proactive/execution/worker.js +7 -2
- package/dist/src/proactive/experience.d.ts +69 -0
- package/dist/src/proactive/experience.js +90 -0
- package/dist/src/proactive/follow-ups.d.ts +123 -0
- package/dist/src/proactive/follow-ups.js +169 -0
- package/dist/src/proactive/inbox/cards.js +35 -6
- package/dist/src/proactive/inbox/delivery.js +4 -2
- package/dist/src/proactive/inbox/digest.js +2 -2
- package/dist/src/proactive/inbox/lifecycle.js +4 -1
- package/dist/src/proactive/inbox/notification-policy.js +4 -2
- package/dist/src/proactive/inbox/repository.js +17 -11
- package/dist/src/proactive/inbox/types.d.ts +2 -0
- package/dist/src/proactive/inbox/worker.js +1 -1
- package/dist/src/proactive/index.js +2 -2
- package/dist/src/proactive/mail-thread.d.ts +13 -0
- package/dist/src/proactive/mail-thread.js +54 -0
- package/dist/src/proactive/policy/service.d.ts +3 -5
- package/dist/src/proactive/policy/service.js +3 -5
- package/dist/src/proactive/scenarios/control.d.ts +4 -7
- package/dist/src/proactive/scenarios/control.js +3 -4
- package/dist/src/proactive/scenarios/preview.js +1 -1
- package/dist/src/proactive/scenarios/prompt-composer.js +2 -0
- package/dist/src/proactive/service.js +1 -1
- package/dist/src/proactive/temporal/worker.d.ts +1 -0
- package/dist/src/proactive/temporal/worker.js +18 -4
- package/dist/src/realtime/runtime.d.ts +2 -1
- package/dist/src/realtime/runtime.js +9 -3
- package/dist/src/realtime/tickets.d.ts +1 -0
- package/dist/src/realtime/tickets.js +3 -0
- package/dist/src/session/store.d.ts +2 -0
- package/dist/src/session/store.js +17 -2
- package/dist/src/session/types.d.ts +2 -1
- package/dist/src/storage/sqlite/browser-session-repository.d.ts +17 -0
- package/dist/src/storage/sqlite/browser-session-repository.js +54 -0
- package/dist/src/storage/sqlite/device-pairing-approval.js +2 -1
- package/dist/src/storage/sqlite/device-pairing-repository.d.ts +4 -10
- package/dist/src/storage/sqlite/device-pairing-repository.js +10 -62
- package/dist/src/storage/sqlite/index.d.ts +1 -1
- package/dist/src/storage/sqlite/index.js +2 -2
- package/dist/src/storage/sqlite/migrations/162_proactive_product.sql +7 -0
- package/dist/src/storage/sqlite/migrations/163_proactive_follow_ups.sql +29 -0
- package/dist/src/storage/sqlite/migrations/164_browser_sessions.sql +8 -0
- package/dist/src/storage/sqlite/migrations/165_device_pairing_target.sql +40 -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/session-identity-sql.d.ts +2 -0
- package/dist/src/storage/sqlite/session-identity-sql.js +18 -0
- package/dist/src/storage/sqlite/session-repository.js +26 -22
- package/dist/src/tasks/home-query-service.js +1 -1
- package/dist/src/tasks/index.js +4 -4
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tunnel/auth-policy.d.ts +3 -0
- package/dist/src/tunnel/auth-policy.js +8 -0
- package/dist/src/tunnel/broker-client.d.ts +5 -15
- package/dist/src/tunnel/broker-client.js +37 -49
- package/dist/src/tunnel/frpc-binary.d.ts +8 -6
- package/dist/src/tunnel/frpc-binary.js +76 -88
- package/dist/src/tunnel/frpc-config.d.ts +2 -1
- package/dist/src/tunnel/frpc-config.js +29 -12
- package/dist/src/tunnel/frpc-release.d.ts +27 -0
- package/dist/src/tunnel/frpc-release.js +30 -0
- package/dist/src/tunnel/gateway-lifecycle.js +8 -2
- package/dist/src/tunnel/index.js +2 -1
- package/dist/src/tunnel/registration-proof.d.ts +19 -0
- package/dist/src/tunnel/registration-proof.js +37 -0
- package/dist/src/tunnel/tunnel-persist.js +3 -1
- package/dist/src/tunnel/tunnel-service.d.ts +1 -0
- package/dist/src/tunnel/tunnel-service.js +35 -8
- package/dist/src/tunnel/tunnel-state.js +11 -5
- package/dist/src/tunnel/tunnel-types.d.ts +2 -0
- package/dist/src/tunnel/well-known.js +5 -1
- package/dist/src/user-context/config.js +2 -2
- package/dist/src/utils/logger/redact.js +4 -0
- package/dist/src/voice/dashscope/streaming-stt-session.js +1 -0
- package/dist/src/voice/dashscope/streaming-tts-stream.d.ts +1 -0
- package/dist/src/voice/dashscope/streaming-tts-stream.js +8 -0
- package/dist/src/voice/realtime/agentBroker.js +1 -1
- package/dist/src/voice/realtime/agentEngine.js +1 -1
- package/dist/src/voice/realtime/pcm-output-gain.d.ts +2 -0
- package/dist/src/voice/realtime/pcm-output-gain.js +16 -0
- package/dist/src/voice/realtime/runtime.d.ts +1 -0
- package/dist/src/voice/realtime/runtime.js +21 -3
- package/dist/src/voice/realtime/runtime.types.d.ts +1 -0
- package/dist/src/workflows/service/workflow-run-service.js +3 -1
- package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -0
- package/dist/src/workflows/service/workflow-session-bridge.js +1 -0
- package/package.json +4 -4
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-qKCezlBg.js +0 -1
- package/dist/gateway/static/root/assets/agents-BMhnZKhP.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-DduJDWGY.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-X7hNHCjW.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-BZ7nK_pN.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BfKvJO1C.js +0 -7
- package/dist/gateway/static/root/assets/channels-settings-D1UDxJuA.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-C2nuqs_O.js +0 -2
- package/dist/gateway/static/root/assets/cron-expression-DlyRIyUn.js +0 -2
- package/dist/gateway/static/root/assets/date-picker-CU-ij_yE.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-CMyt0A32.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-ogv8ZbvG.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-BnrMRKaZ.js +0 -1
- package/dist/gateway/static/root/assets/home-page-CbcJCREd.js +0 -1
- package/dist/gateway/static/root/assets/index-7PZ6jmhy.css +0 -2
- package/dist/gateway/static/root/assets/index-CfyyA9-g.js +0 -74
- package/dist/gateway/static/root/assets/local-app-workbench-page-D5XVZnK1.js +0 -2
- package/dist/gateway/static/root/assets/locale-store-BQ2HKTWb.js +0 -1
- package/dist/gateway/static/root/assets/logs-page-CWDU1AGN.js +0 -2
- package/dist/gateway/static/root/assets/management-settings-CuFNgQUy.js +0 -1
- package/dist/gateway/static/root/assets/mobile-pairing-wizard-C7d_ztgp.js +0 -1
- package/dist/gateway/static/root/assets/note-detail-panel-D5JuBLyt.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-C5-ccCi4.js +0 -8
- package/dist/gateway/static/root/assets/popover-select-CKBYnT3c.js +0 -1
- package/dist/gateway/static/root/assets/proactive-page-fHjPigmx.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-6v_khvEt.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CCy1aK4V.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-pkqKRnch.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-Cr4E4cap.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-D1JRDRyL.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Cc_iP_vv.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-BrMECMAB.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DuqIDYjc.js +0 -1
- package/dist/gateway/static/root/assets/skills-page.utils-D1wGfm22.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-m0oXUKl2.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-Dur80zSQ.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-Dl10D_5q.js +0 -2
- package/dist/gateway/static/root/assets/workflows-page-CswgoIFU.js +0 -6
- package/dist/src/proactive/actions/workflow.d.ts +0 -15
- package/dist/src/proactive/actions/workflow.js +0 -88
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { getSqliteDatabase } from "../../storage/sqlite/transaction.js";
|
|
2
2
|
import { getAssertionSlot, listUserAssertions } from "../../user-model/repository.js";
|
|
3
3
|
import "../../user-model/index.js";
|
|
4
|
-
import { getDiscussionCapture, getLatestDiscussionOrganization } from "../../discussions/repository.js";
|
|
5
4
|
import { authorizedConnectedSource } from "./authorization.js";
|
|
5
|
+
import { authorizedMailThread, requireMailFollowUp } from "../follow-ups.js";
|
|
6
|
+
import { getDiscussionCapture, getLatestDiscussionOrganization } from "../../discussions/repository.js";
|
|
6
7
|
import { wrapExternalContent } from "../../gateway/security/external-content.js";
|
|
7
8
|
//#region src/proactive/execution/context.ts
|
|
8
9
|
const MAX_EVENT_COUNT = 50;
|
|
@@ -27,7 +28,12 @@ function emptyContext() {
|
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
30
|
function authorizedConnectedSourceItem(event, scenarioKey) {
|
|
30
|
-
|
|
31
|
+
const item = authorizedConnectedSource(event.subject_id, event.workspace_id, scenarioKey, event.agent_id);
|
|
32
|
+
if (item && event.type === "connected_source.calendar_window.v1") {
|
|
33
|
+
const payload = JSON.parse(event.payload_json);
|
|
34
|
+
if (payload.meetingStartsAt !== item.occurredAt || payload.contentHash && payload.contentHash !== item.contentHash) return null;
|
|
35
|
+
}
|
|
36
|
+
return item;
|
|
31
37
|
}
|
|
32
38
|
var EventBatchContextProvider = class {
|
|
33
39
|
id = "event_batch";
|
|
@@ -53,11 +59,13 @@ var ConnectedSourceContextProvider = class {
|
|
|
53
59
|
async collect(input) {
|
|
54
60
|
const items = [];
|
|
55
61
|
const snapshotItems = [];
|
|
62
|
+
const seen = /* @__PURE__ */ new Set();
|
|
56
63
|
const evidenceIds = [];
|
|
57
64
|
for (const event of eventRows(input.eventIds)) {
|
|
58
65
|
if (!event.type.startsWith("connected_source.") || event.type.includes("_deleted.")) continue;
|
|
59
66
|
const item = authorizedConnectedSourceItem(event, input.scenarioKey);
|
|
60
|
-
if (!item) continue;
|
|
67
|
+
if (!item || seen.has(item.id)) continue;
|
|
68
|
+
seen.add(item.id);
|
|
61
69
|
const evidenceId = `source-item:${item.id}`;
|
|
62
70
|
const common = {
|
|
63
71
|
evidenceId,
|
|
@@ -325,6 +333,43 @@ var DiscussionContextProvider = class {
|
|
|
325
333
|
};
|
|
326
334
|
}
|
|
327
335
|
};
|
|
336
|
+
var MailFollowUpContextProvider = class {
|
|
337
|
+
id = "follow_up";
|
|
338
|
+
async collect(input) {
|
|
339
|
+
const event = eventRows(input.eventIds).findLast((row) => row.subject_kind === "mail_follow_up");
|
|
340
|
+
if (!event) return emptyContext();
|
|
341
|
+
const follow = requireMailFollowUp(event.workspace_id, event.subject_id);
|
|
342
|
+
const thread = authorizedMailThread(follow);
|
|
343
|
+
if (!thread || follow.status !== "watching") return emptyContext();
|
|
344
|
+
const common = {
|
|
345
|
+
followUpId: follow.id,
|
|
346
|
+
revision: follow.revision,
|
|
347
|
+
fingerprint: thread.fingerprint,
|
|
348
|
+
dueAt: follow.due_at,
|
|
349
|
+
deadlinePassed: Date.parse(follow.due_at) <= Date.now()
|
|
350
|
+
};
|
|
351
|
+
return {
|
|
352
|
+
content: {
|
|
353
|
+
...common,
|
|
354
|
+
instructions: follow.instructions,
|
|
355
|
+
items: thread.items.map((item) => ({
|
|
356
|
+
evidenceId: `source-item:${item.id}`,
|
|
357
|
+
occurredAt: item.occurredAt,
|
|
358
|
+
content: wrapExternalContent(item.normalizedText?.slice(0, 4e3) ?? "", { source: "email" })
|
|
359
|
+
}))
|
|
360
|
+
},
|
|
361
|
+
snapshotContent: {
|
|
362
|
+
...common,
|
|
363
|
+
items: thread.items.map((item) => ({
|
|
364
|
+
sourceItemId: item.id,
|
|
365
|
+
contentHash: item.contentHash,
|
|
366
|
+
occurredAt: item.occurredAt
|
|
367
|
+
}))
|
|
368
|
+
},
|
|
369
|
+
evidenceIds: thread.items.map((item) => `source-item:${item.id}`)
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
};
|
|
328
373
|
var ContextProviderRegistry = class {
|
|
329
374
|
constructor(providers = [
|
|
330
375
|
new EventBatchContextProvider(),
|
|
@@ -334,7 +379,8 @@ var ContextProviderRegistry = class {
|
|
|
334
379
|
new MeetingWorkspaceContextProvider(),
|
|
335
380
|
new ProjectStateContextProvider(),
|
|
336
381
|
new AutomationStateContextProvider(),
|
|
337
|
-
new DiscussionContextProvider()
|
|
382
|
+
new DiscussionContextProvider(),
|
|
383
|
+
new MailFollowUpContextProvider()
|
|
338
384
|
]) {
|
|
339
385
|
this.providers = providers;
|
|
340
386
|
}
|
|
@@ -357,4 +403,4 @@ var ContextProviderRegistry = class {
|
|
|
357
403
|
}
|
|
358
404
|
};
|
|
359
405
|
//#endregion
|
|
360
|
-
export { AutomationStateContextProvider, ConnectedSourceContextProvider, ContextProviderRegistry, DiscussionContextProvider, EventBatchContextProvider, InternalObjectContextProvider, MeetingWorkspaceContextProvider, ProjectStateContextProvider, UserModelContextProvider };
|
|
406
|
+
export { AutomationStateContextProvider, ConnectedSourceContextProvider, ContextProviderRegistry, DiscussionContextProvider, EventBatchContextProvider, InternalObjectContextProvider, MailFollowUpContextProvider, MeetingWorkspaceContextProvider, ProjectStateContextProvider, UserModelContextProvider };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ProactiveArtifactSchema } from "../../../packages/gateway-contract/src/proactive.js";
|
|
1
2
|
import { stripCodeFences } from "../../providers/model-response.js";
|
|
2
3
|
//#region src/proactive/execution/insight.ts
|
|
3
4
|
const URGENCY = new Set([
|
|
@@ -65,6 +66,7 @@ function parseInsightCandidate(raw, allowedEvidenceIds) {
|
|
|
65
66
|
const proposedAction = parseProposedAction(row.proposedAction);
|
|
66
67
|
if (proposedAction && (!decision || decision.options.length !== 2 || decision.options[0]?.id !== "approve" || decision.options[1]?.id !== "reject")) throw new Error("Insight proposedAction requires approve and reject decision options");
|
|
67
68
|
return {
|
|
69
|
+
...row.artifact != null ? { artifact: ProactiveArtifactSchema.parse(row.artifact) } : {},
|
|
68
70
|
title: boundedText(row.title, "title", 160),
|
|
69
71
|
summary: boundedText(row.summary, "summary", 1200),
|
|
70
72
|
whyNow: boundedText(row.whyNow, "whyNow", 800),
|
|
@@ -91,7 +93,7 @@ function isValuableInsight(candidate, policy = {
|
|
|
91
93
|
minConfidence: .65,
|
|
92
94
|
minScore: .6
|
|
93
95
|
}) {
|
|
94
|
-
return candidate.confidence >= policy.minConfidence && candidate.urgency !== "low" && scoreInsight(candidate) >= policy.minScore;
|
|
96
|
+
return candidate.confidence >= policy.minConfidence && (candidate.urgency !== "low" || Boolean(candidate.artifact)) && scoreInsight(candidate) >= policy.minScore;
|
|
95
97
|
}
|
|
96
98
|
function parseAnalysisResult(raw, allowedEvidenceIds) {
|
|
97
99
|
let value;
|
|
@@ -107,11 +107,19 @@ function finishRun(input, now = /* @__PURE__ */ new Date()) {
|
|
|
107
107
|
JOIN proactive_events e ON e.event_id = be.event_id
|
|
108
108
|
WHERE be.batch_id = ?
|
|
109
109
|
ORDER BY e.subject_kind, e.subject_id`).all(input.run.batchId).map((row) => `${str(row, "subject_kind")}:${str(row, "subject_id")}`);
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
const snapshot = db.prepare(`SELECT c.content_json FROM proactive_runs r JOIN proactive_context_snapshots c
|
|
111
|
+
ON c.snapshot_id = r.context_snapshot_id WHERE r.run_id = ?`).get(input.run.id);
|
|
112
|
+
const sourceVersions = snapshot ? JSON.parse(snapshot.content_json) : {};
|
|
113
|
+
const fingerprint = input.candidate ? createHash("sha256").update([
|
|
114
|
+
...subjectScope,
|
|
115
|
+
JSON.stringify(input.candidate.artifact ?? null),
|
|
116
|
+
JSON.stringify(sourceVersions.connected_source ?? sourceVersions.project_state ?? sourceVersions.follow_up ?? null),
|
|
117
|
+
...[
|
|
118
|
+
input.candidate.title,
|
|
119
|
+
input.candidate.summary,
|
|
120
|
+
input.candidate.recommendation
|
|
121
|
+
].map((value) => value.trim().toLowerCase().replace(/\s+/g, " "))
|
|
122
|
+
].join("\n")).digest("hex") : void 0;
|
|
115
123
|
const duplicate = fingerprint ? db.prepare(`SELECT 1 FROM proactive_insights
|
|
116
124
|
WHERE subscription_id = ? AND scenario_key = ? AND content_fingerprint = ? AND created_at >= ? LIMIT 1`).get(input.run.subscriptionId, input.run.scenarioKey, fingerprint, (/* @__PURE__ */ new Date(now.getTime() - (input.cooldownSeconds ?? 10080 * 60) * 1e3)).toISOString()) : void 0;
|
|
117
125
|
const valuable = Boolean(input.candidate) && !duplicate;
|
|
@@ -141,6 +149,7 @@ function finishRun(input, now = /* @__PURE__ */ new Date()) {
|
|
|
141
149
|
why_now, impact, recommendation, work_done, decision_json, proposed_action_json, urgency, confidence, value_score,
|
|
142
150
|
evidence_ids_json, content_fingerprint, created_at)
|
|
143
151
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(insight.id, insight.runId, insight.subscriptionId, insight.scenarioKey, insight.title, insight.summary, insight.whyNow, insight.impact, insight.recommendation, insight.workDone, insight.decision ? JSON.stringify(insight.decision) : null, insight.proposedAction ? JSON.stringify(insight.proposedAction) : null, insight.urgency, insight.confidence, insight.valueScore, JSON.stringify(insight.evidenceIds), fingerprint, insight.createdAt);
|
|
152
|
+
if (insight.artifact) db.prepare("UPDATE proactive_insights SET artifact_json = ? WHERE insight_id = ?").run(JSON.stringify(insight.artifact), insight.id);
|
|
144
153
|
return insight;
|
|
145
154
|
});
|
|
146
155
|
}
|
|
@@ -165,6 +174,7 @@ function listInsights(limit = 50) {
|
|
|
165
174
|
impact: str(row, "impact"),
|
|
166
175
|
recommendation: str(row, "recommendation"),
|
|
167
176
|
workDone: str(row, "work_done"),
|
|
177
|
+
...row.artifact_json ? { artifact: JSON.parse(str(row, "artifact_json")) } : {},
|
|
168
178
|
...row.decision_json ? { decision: JSON.parse(str(row, "decision_json")) } : {},
|
|
169
179
|
...row.proposed_action_json ? { proposedAction: JSON.parse(str(row, "proposed_action_json")) } : {},
|
|
170
180
|
urgency: str(row, "urgency"),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ProactiveArtifact } from '@xopcai/gateway-contract';
|
|
1
2
|
export interface ContextSnapshot {
|
|
2
3
|
id: string;
|
|
3
4
|
batchId: string;
|
|
@@ -6,6 +7,7 @@ export interface ContextSnapshot {
|
|
|
6
7
|
createdAt: string;
|
|
7
8
|
}
|
|
8
9
|
export interface InsightCandidate {
|
|
10
|
+
artifact?: ProactiveArtifact;
|
|
9
11
|
title: string;
|
|
10
12
|
summary: string;
|
|
11
13
|
whyNow: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { getSqliteDatabase } from "../../storage/sqlite/transaction.js";
|
|
4
|
+
import { authorizedConnectedSource } from "./authorization.js";
|
|
4
5
|
import { effectiveProactivePolicy } from "../policy/service.js";
|
|
5
6
|
import { getPromptRevision, getScenario } from "../scenarios/repository.js";
|
|
6
7
|
import { composeScenarioPrompt } from "../scenarios/prompt-composer.js";
|
|
@@ -9,6 +10,7 @@ import { ContextProviderRegistry } from "./context.js";
|
|
|
9
10
|
import { attachSnapshot, claimNextRun, eventIdsForBatch, failRun, finishRun, saveSnapshot } from "./repository.js";
|
|
10
11
|
import { isValuableInsight, parseAnalysisResult, scoreInsight } from "./insight.js";
|
|
11
12
|
import { randomUUID } from "node:crypto";
|
|
13
|
+
import { isDeepStrictEqual } from "node:util";
|
|
12
14
|
//#region src/proactive/execution/worker.ts
|
|
13
15
|
init_logger();
|
|
14
16
|
const log = createLogger("ProactiveWorker");
|
|
@@ -86,11 +88,14 @@ var ProactiveWorker = class {
|
|
|
86
88
|
subscriptionId: run.subscriptionId
|
|
87
89
|
});
|
|
88
90
|
const revoked = context.evidenceIds.some((id) => !latestContext.evidenceIds.includes(id));
|
|
89
|
-
const
|
|
91
|
+
const changed = !isDeepStrictEqual(context.snapshotContent ?? context.content, latestContext.snapshotContent ?? latestContext.content);
|
|
92
|
+
const unavailable = context.evidenceIds.some((id) => id.startsWith("source-item:") && !authorizedConnectedSource(id.slice(12), effectiveProactivePolicy(run.subscriptionId).workspaceId, run.scenarioKey));
|
|
93
|
+
const result = revoked || changed ? {
|
|
90
94
|
result: "no_insight",
|
|
91
|
-
reason: "source_unavailable"
|
|
95
|
+
reason: unavailable ? "source_unavailable" : "source_changed"
|
|
92
96
|
} : parseAnalysisResult(output.text, new Set(latestContext.evidenceIds));
|
|
93
97
|
const candidate = result.result === "insight" ? result.candidate : void 0;
|
|
98
|
+
if (run.scenarioKey === "communication_follow_up" && (candidate?.decision || candidate?.proposedAction)) throw new Error("Communication preparation must return a draft or update; actions require the conversation confirmation flow");
|
|
94
99
|
const valueScore = candidate ? scoreInsight(candidate) : 0;
|
|
95
100
|
const enabled = effectiveProactivePolicy(run.subscriptionId).enabled;
|
|
96
101
|
const valuable = enabled && candidate && isValuableInsight(candidate, scenario.valuePolicy);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export declare function startDelegation(workspace: string, value: unknown): {
|
|
2
|
+
effectiveLevel: "off" | "active" | "quiet" | "balanced";
|
|
3
|
+
schedule: Record<string, import("node:sqlite").SQLOutputValue>;
|
|
4
|
+
revision: number;
|
|
5
|
+
level: "off" | "active" | "quiet" | "balanced";
|
|
6
|
+
delivery: "digest" | "inbox" | "important";
|
|
7
|
+
completedAt: string;
|
|
8
|
+
scanIntervalMinutes: number;
|
|
9
|
+
userInstructions: string;
|
|
10
|
+
id: string;
|
|
11
|
+
scenarioKey: string;
|
|
12
|
+
workspaceId: string;
|
|
13
|
+
scopeKind: "workspace" | "project";
|
|
14
|
+
scopeId: string;
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
activePromptRevisionId?: string;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
updatedAt: string;
|
|
19
|
+
};
|
|
20
|
+
/** Queue work in the existing worker; HTTP and conversation requests do not own model runs. */
|
|
21
|
+
export declare function checkDelegation(workspace: string, id: string): {
|
|
22
|
+
status: "queued";
|
|
23
|
+
};
|
|
24
|
+
export declare function delegationOverview(workspace: string): {
|
|
25
|
+
followUps: {
|
|
26
|
+
id: string;
|
|
27
|
+
subscriptionId: string;
|
|
28
|
+
instructions: string;
|
|
29
|
+
dueAt: string;
|
|
30
|
+
status: "completed" | "paused" | "watching";
|
|
31
|
+
revision: number;
|
|
32
|
+
lastCheckedAt: string;
|
|
33
|
+
sessionKey: string;
|
|
34
|
+
sourceAvailable: boolean;
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
subject: string;
|
|
37
|
+
latestMessageAt: string;
|
|
38
|
+
latestDirection: string;
|
|
39
|
+
lastSyncedAt: string;
|
|
40
|
+
syncFailed: boolean;
|
|
41
|
+
}[];
|
|
42
|
+
needsDecision: import("@xopcai/gateway-contract/src/proactive.js").ProactiveCard[];
|
|
43
|
+
prepared: import("@xopcai/gateway-contract/src/proactive.js").ProactiveCard[];
|
|
44
|
+
updates: import("@xopcai/gateway-contract/src/proactive.js").ProactiveCard[];
|
|
45
|
+
delegations: {
|
|
46
|
+
effectiveEnabled: boolean;
|
|
47
|
+
project: Record<string, import("node:sqlite").SQLOutputValue>;
|
|
48
|
+
latestRun: Record<string, import("node:sqlite").SQLOutputValue>;
|
|
49
|
+
pending: boolean;
|
|
50
|
+
effectiveLevel: "off" | "active" | "quiet" | "balanced";
|
|
51
|
+
schedule: Record<string, import("node:sqlite").SQLOutputValue>;
|
|
52
|
+
revision: number;
|
|
53
|
+
level: "off" | "active" | "quiet" | "balanced";
|
|
54
|
+
delivery: "digest" | "inbox" | "important";
|
|
55
|
+
completedAt: string;
|
|
56
|
+
scanIntervalMinutes: number;
|
|
57
|
+
userInstructions: string;
|
|
58
|
+
id: string;
|
|
59
|
+
scenarioKey: string;
|
|
60
|
+
workspaceId: string;
|
|
61
|
+
scopeKind: "workspace" | "project";
|
|
62
|
+
scopeId: string;
|
|
63
|
+
enabled: boolean;
|
|
64
|
+
activePromptRevisionId?: string;
|
|
65
|
+
createdAt: string;
|
|
66
|
+
updatedAt: string;
|
|
67
|
+
}[];
|
|
68
|
+
};
|
|
69
|
+
export declare function completeDeliveredProjects(now?: Date): void;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
|
|
2
|
+
import { ProactiveConflict, effectiveProactivePolicy } from "./policy/service.js";
|
|
3
|
+
import { controlledSubscriptions, createControlledSubscription, requireSubscription, updateControlledSubscription } from "./scenarios/control.js";
|
|
4
|
+
import { ProactiveScenarioService } from "./scenarios/service.js";
|
|
5
|
+
import { ProactiveEventService } from "./service.js";
|
|
6
|
+
import { listMailFollowUps } from "./follow-ups.js";
|
|
7
|
+
import { getCard } from "./inbox/cards.js";
|
|
8
|
+
import { scanDueProjects } from "./temporal/schedule.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
//#region src/proactive/experience.ts
|
|
11
|
+
const DelegateSchema = z.object({
|
|
12
|
+
scenarioKey: z.enum([
|
|
13
|
+
"project_delivery_risk",
|
|
14
|
+
"meeting_preparation",
|
|
15
|
+
"discussion_follow_up"
|
|
16
|
+
]),
|
|
17
|
+
projectId: z.string().min(1).optional(),
|
|
18
|
+
instructions: z.string().trim().min(1).max(12e3)
|
|
19
|
+
}).strict();
|
|
20
|
+
function startDelegation(workspace, value) {
|
|
21
|
+
const input = DelegateSchema.parse(value);
|
|
22
|
+
if (input.scenarioKey === "project_delivery_risk" && !input.projectId) throw new Error("Choose a project");
|
|
23
|
+
if (input.scenarioKey !== "project_delivery_risk" && input.projectId) throw new Error("This service uses workspace sources");
|
|
24
|
+
const subscription = createControlledSubscription(workspace, {
|
|
25
|
+
scenarioKey: input.scenarioKey,
|
|
26
|
+
scopeKind: input.projectId ? "project" : "workspace",
|
|
27
|
+
scopeId: input.projectId ?? workspace,
|
|
28
|
+
userInstructions: input.instructions
|
|
29
|
+
});
|
|
30
|
+
if (input.projectId && effectiveProactivePolicy(subscription.id).enabled) checkDelegation(workspace, subscription.id);
|
|
31
|
+
return subscription;
|
|
32
|
+
}
|
|
33
|
+
/** Queue work in the existing worker; HTTP and conversation requests do not own model runs. */
|
|
34
|
+
function checkDelegation(workspace, id) {
|
|
35
|
+
const sub = requireSubscription(id, workspace);
|
|
36
|
+
if (!effectiveProactivePolicy(id).enabled) throw new Error("Resume this service before checking");
|
|
37
|
+
if (sub.scopeKind !== "project") throw new Error("This service checks when connected sources change");
|
|
38
|
+
return runSqliteWriteTransaction((db) => {
|
|
39
|
+
if (db.prepare("SELECT 1 FROM proactive_signal_batches WHERE subscription_id = ? AND status IN ('collecting', 'ready', 'processing')").get(id)) return { status: "queued" };
|
|
40
|
+
const last = db.prepare("SELECT MAX(started_at) AS at FROM proactive_runs WHERE subscription_id = ?").get(id);
|
|
41
|
+
if (last.at && Date.parse(last.at) > Date.now() - 6e4) throw new ProactiveConflict("A check just finished; try again in a minute");
|
|
42
|
+
db.prepare(`INSERT INTO proactive_schedule_state(subscription_id, next_due_at) VALUES (?, ?)
|
|
43
|
+
ON CONFLICT(subscription_id) DO UPDATE SET next_due_at = excluded.next_due_at, last_fingerprint = NULL`).run(id, (/* @__PURE__ */ new Date()).toISOString());
|
|
44
|
+
scanDueProjects(new ProactiveEventService(() => new ProactiveScenarioService().routes()));
|
|
45
|
+
db.prepare("UPDATE proactive_signal_batches SET ready_at = ?, status = 'ready' WHERE subscription_id = ? AND status = 'collecting'").run((/* @__PURE__ */ new Date()).toISOString(), id);
|
|
46
|
+
return { status: "queued" };
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function delegationOverview(workspace) {
|
|
50
|
+
const db = getSqliteDatabase();
|
|
51
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
52
|
+
const cards = db.prepare(`SELECT i.inbox_item_id FROM proactive_inbox_items i
|
|
53
|
+
JOIN proactive_insights x USING(insight_id) JOIN proactive_scenario_subscriptions s USING(subscription_id)
|
|
54
|
+
WHERE s.workspace_id = ? AND i.withdrawn_at IS NULL AND i.status IN ('unread', 'read')
|
|
55
|
+
AND (i.expires_at IS NULL OR i.expires_at > ?)
|
|
56
|
+
ORDER BY CASE WHEN x.action_status = 'approval_required' THEN 0 WHEN x.artifact_json IS NOT NULL THEN 1 ELSE 2 END,
|
|
57
|
+
x.value_score DESC, i.updated_at DESC LIMIT 100`).all(workspace, now).map((row) => getCard(row.inbox_item_id, workspace)).filter((card) => !["withdrawn", "expired"].includes(card.status));
|
|
58
|
+
return {
|
|
59
|
+
followUps: listMailFollowUps(workspace),
|
|
60
|
+
needsDecision: cards.filter((card) => card.decision && card.actionStatus !== "completed"),
|
|
61
|
+
prepared: cards.filter((card) => card.artifact && !card.decision),
|
|
62
|
+
updates: cards.filter((card) => !card.artifact && !card.decision),
|
|
63
|
+
delegations: controlledSubscriptions(workspace).map((sub) => ({
|
|
64
|
+
...sub,
|
|
65
|
+
effectiveEnabled: effectiveProactivePolicy(sub.id).enabled,
|
|
66
|
+
project: sub.scopeKind === "project" ? db.prepare("SELECT name, status FROM projects WHERE project_id = ?").get(sub.scopeId) ?? null : null,
|
|
67
|
+
latestRun: db.prepare(`SELECT status, outcome_reason AS reason, completed_at AS completedAt, started_at AS startedAt, error_message AS error
|
|
68
|
+
FROM proactive_runs WHERE subscription_id = ? ORDER BY started_at DESC LIMIT 1`).get(sub.id) ?? null,
|
|
69
|
+
pending: Boolean(db.prepare("SELECT 1 FROM proactive_signal_batches WHERE subscription_id = ? AND status IN ('collecting', 'ready', 'processing')").get(sub.id))
|
|
70
|
+
}))
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function completeDeliveredProjects(now = /* @__PURE__ */ new Date()) {
|
|
74
|
+
const db = getSqliteDatabase();
|
|
75
|
+
const rows = db.prepare(`SELECT s.subscription_id, s.workspace_id FROM proactive_scenario_subscriptions s
|
|
76
|
+
JOIN projects p ON p.project_id = s.scope_id WHERE s.scope_kind = 'project' AND s.enabled = 1
|
|
77
|
+
AND p.status IN ('completed', 'cancelled', 'archived')`).all();
|
|
78
|
+
for (const row of rows) {
|
|
79
|
+
const current = controlledSubscriptions(row.workspace_id).find((sub) => sub.id === row.subscription_id);
|
|
80
|
+
updateControlledSubscription(row.workspace_id, row.subscription_id, {
|
|
81
|
+
expectedRevision: current.revision,
|
|
82
|
+
enabled: false,
|
|
83
|
+
completedAt: now.toISOString()
|
|
84
|
+
});
|
|
85
|
+
db.prepare(`UPDATE proactive_inbox_items SET status = 'resolved', resolution = 'project_ended', updated_at = ?
|
|
86
|
+
WHERE insight_id IN (SELECT insight_id FROM proactive_insights WHERE subscription_id = ?) AND status <> 'resolved'`).run(now.toISOString(), row.subscription_id);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
export { checkDelegation, completeDeliveredProjects, delegationOverview, startDelegation };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { ProactiveEventService } from './service.js';
|
|
2
|
+
export declare const COMMUNICATION_SCENARIO = "communication_follow_up";
|
|
3
|
+
export type MailFollowUp = {
|
|
4
|
+
id: string;
|
|
5
|
+
subscription_id: string;
|
|
6
|
+
workspace_id: string;
|
|
7
|
+
source_item_id: string;
|
|
8
|
+
instructions: string;
|
|
9
|
+
due_at: string;
|
|
10
|
+
status: 'watching' | 'paused' | 'completed';
|
|
11
|
+
revision: number;
|
|
12
|
+
last_fingerprint: string | null;
|
|
13
|
+
last_checked_at: string | null;
|
|
14
|
+
session_key: string | null;
|
|
15
|
+
};
|
|
16
|
+
export declare function requireMailFollowUp(workspace: string, id: string): MailFollowUp;
|
|
17
|
+
export declare function authorizedMailThread(follow: MailFollowUp): {
|
|
18
|
+
origin: import("../knowledge/types.js").KnowledgeSourceItem;
|
|
19
|
+
items: import("../knowledge/types.js").KnowledgeSourceItem[];
|
|
20
|
+
threadKey: string;
|
|
21
|
+
fingerprint: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function mailFollowUpView(follow: MailFollowUp): {
|
|
24
|
+
id: string;
|
|
25
|
+
subscriptionId: string;
|
|
26
|
+
instructions: string;
|
|
27
|
+
dueAt: string;
|
|
28
|
+
status: "completed" | "paused" | "watching";
|
|
29
|
+
revision: number;
|
|
30
|
+
lastCheckedAt: string;
|
|
31
|
+
sessionKey: string;
|
|
32
|
+
sourceAvailable: boolean;
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
subject: string;
|
|
35
|
+
latestMessageAt: string;
|
|
36
|
+
latestDirection: string;
|
|
37
|
+
lastSyncedAt: string;
|
|
38
|
+
syncFailed: boolean;
|
|
39
|
+
};
|
|
40
|
+
export declare function listMailFollowUps(workspace: string): {
|
|
41
|
+
id: string;
|
|
42
|
+
subscriptionId: string;
|
|
43
|
+
instructions: string;
|
|
44
|
+
dueAt: string;
|
|
45
|
+
status: "completed" | "paused" | "watching";
|
|
46
|
+
revision: number;
|
|
47
|
+
lastCheckedAt: string;
|
|
48
|
+
sessionKey: string;
|
|
49
|
+
sourceAvailable: boolean;
|
|
50
|
+
enabled: boolean;
|
|
51
|
+
subject: string;
|
|
52
|
+
latestMessageAt: string;
|
|
53
|
+
latestDirection: string;
|
|
54
|
+
lastSyncedAt: string;
|
|
55
|
+
syncFailed: boolean;
|
|
56
|
+
}[];
|
|
57
|
+
export declare function mailFollowUpSources(workspace: string): {
|
|
58
|
+
id: string;
|
|
59
|
+
subject: string;
|
|
60
|
+
sender: string;
|
|
61
|
+
occurredAt: string;
|
|
62
|
+
accountLabel: string;
|
|
63
|
+
}[];
|
|
64
|
+
export declare function startMailFollowUp(workspace: string, value: unknown): {
|
|
65
|
+
id: string;
|
|
66
|
+
subscriptionId: string;
|
|
67
|
+
instructions: string;
|
|
68
|
+
dueAt: string;
|
|
69
|
+
status: "completed" | "paused" | "watching";
|
|
70
|
+
revision: number;
|
|
71
|
+
lastCheckedAt: string;
|
|
72
|
+
sessionKey: string;
|
|
73
|
+
sourceAvailable: boolean;
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
subject: string;
|
|
76
|
+
latestMessageAt: string;
|
|
77
|
+
latestDirection: string;
|
|
78
|
+
lastSyncedAt: string;
|
|
79
|
+
syncFailed: boolean;
|
|
80
|
+
};
|
|
81
|
+
export declare function updateMailFollowUp(workspace: string, id: string, value: unknown): {
|
|
82
|
+
id: string;
|
|
83
|
+
subscriptionId: string;
|
|
84
|
+
instructions: string;
|
|
85
|
+
dueAt: string;
|
|
86
|
+
status: "completed" | "paused" | "watching";
|
|
87
|
+
revision: number;
|
|
88
|
+
lastCheckedAt: string;
|
|
89
|
+
sessionKey: string;
|
|
90
|
+
sourceAvailable: boolean;
|
|
91
|
+
enabled: boolean;
|
|
92
|
+
subject: string;
|
|
93
|
+
latestMessageAt: string;
|
|
94
|
+
latestDirection: string;
|
|
95
|
+
lastSyncedAt: string;
|
|
96
|
+
syncFailed: boolean;
|
|
97
|
+
};
|
|
98
|
+
/** Keep the existing chat and its exact connector confirmation flow as the write boundary. */
|
|
99
|
+
export declare function continueMailFollowUp(workspace: string, id: string, sessionKey: string): {
|
|
100
|
+
followUp: {
|
|
101
|
+
id: string;
|
|
102
|
+
subscriptionId: string;
|
|
103
|
+
instructions: string;
|
|
104
|
+
dueAt: string;
|
|
105
|
+
status: "completed" | "paused" | "watching";
|
|
106
|
+
revision: number;
|
|
107
|
+
lastCheckedAt: string;
|
|
108
|
+
sessionKey: string;
|
|
109
|
+
sourceAvailable: boolean;
|
|
110
|
+
enabled: boolean;
|
|
111
|
+
subject: string;
|
|
112
|
+
latestMessageAt: string;
|
|
113
|
+
latestDirection: string;
|
|
114
|
+
lastSyncedAt: string;
|
|
115
|
+
syncFailed: boolean;
|
|
116
|
+
};
|
|
117
|
+
connectionId: unknown;
|
|
118
|
+
sourceItemId: string;
|
|
119
|
+
threadId: string;
|
|
120
|
+
instruction: string;
|
|
121
|
+
};
|
|
122
|
+
/** Poll only delegated threads; unchanged threads and passed deadlines produce no repeat signals. */
|
|
123
|
+
export declare function scanMailFollowUps(events: ProactiveEventService, now?: Date): number;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
|
|
2
|
+
import { listKnowledgeSourceItems } from "../storage/sqlite/knowledge-repository.js";
|
|
3
|
+
import { getConnectorConnection } from "../storage/sqlite/connector-repository.js";
|
|
4
|
+
import { emailFields, readMailThread } from "./mail-thread.js";
|
|
5
|
+
import { authorizedConnectedSource } from "./execution/authorization.js";
|
|
6
|
+
import { ProactiveConflict, effectiveProactivePolicy } from "./policy/service.js";
|
|
7
|
+
import { listSubscriptions } from "./scenarios/repository.js";
|
|
8
|
+
import { createControlledSubscription } from "./scenarios/control.js";
|
|
9
|
+
import { ProactiveScenarioService } from "./scenarios/service.js";
|
|
10
|
+
import { ProactiveEventService } from "./service.js";
|
|
11
|
+
import { randomUUID } from "node:crypto";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
//#region src/proactive/follow-ups.ts
|
|
14
|
+
const COMMUNICATION_SCENARIO = "communication_follow_up";
|
|
15
|
+
const CreateSchema = z.object({
|
|
16
|
+
sourceItemId: z.string().min(1),
|
|
17
|
+
instructions: z.string().trim().min(1).max(12e3),
|
|
18
|
+
dueAt: z.string().datetime()
|
|
19
|
+
}).strict();
|
|
20
|
+
const UpdateSchema = z.object({
|
|
21
|
+
expectedRevision: z.number().int().positive(),
|
|
22
|
+
instructions: z.string().trim().min(1).max(12e3).optional(),
|
|
23
|
+
dueAt: z.string().datetime().optional(),
|
|
24
|
+
status: z.enum([
|
|
25
|
+
"watching",
|
|
26
|
+
"paused",
|
|
27
|
+
"completed"
|
|
28
|
+
]).optional()
|
|
29
|
+
}).strict();
|
|
30
|
+
function requireMailFollowUp(workspace, id) {
|
|
31
|
+
const row = getSqliteDatabase().prepare("SELECT * FROM proactive_follow_ups WHERE id = ? AND workspace_id = ?").get(id, workspace);
|
|
32
|
+
if (!row) throw new Error("Follow-up not found");
|
|
33
|
+
return row;
|
|
34
|
+
}
|
|
35
|
+
function authorizedMailThread(follow) {
|
|
36
|
+
if (!authorizedConnectedSource(follow.source_item_id, follow.workspace_id, "communication_follow_up")) return null;
|
|
37
|
+
const thread = readMailThread(follow.source_item_id);
|
|
38
|
+
if (!thread || thread.items.some((item) => !authorizedConnectedSource(item.id, follow.workspace_id, "communication_follow_up") || item.metadata.connectionId !== thread.origin.metadata.connectionId)) return null;
|
|
39
|
+
return thread;
|
|
40
|
+
}
|
|
41
|
+
function mailFollowUpView(follow) {
|
|
42
|
+
const thread = authorizedMailThread(follow);
|
|
43
|
+
const latest = thread?.items.at(-1);
|
|
44
|
+
const sync = thread ? getSqliteDatabase().prepare("SELECT status, error, finished_at FROM knowledge_sync_runs WHERE source_instance_id = ? ORDER BY started_at DESC LIMIT 1").get(thread.origin.sourceInstanceId) : void 0;
|
|
45
|
+
return {
|
|
46
|
+
id: follow.id,
|
|
47
|
+
subscriptionId: follow.subscription_id,
|
|
48
|
+
instructions: follow.instructions,
|
|
49
|
+
dueAt: follow.due_at,
|
|
50
|
+
status: follow.status,
|
|
51
|
+
revision: follow.revision,
|
|
52
|
+
lastCheckedAt: follow.last_checked_at,
|
|
53
|
+
sessionKey: follow.session_key,
|
|
54
|
+
sourceAvailable: Boolean(thread),
|
|
55
|
+
enabled: effectiveProactivePolicy(follow.subscription_id).enabled,
|
|
56
|
+
subject: thread ? emailFields(thread.origin.normalizedText).subject ?? "Email follow-up" : null,
|
|
57
|
+
latestMessageAt: latest?.occurredAt ?? null,
|
|
58
|
+
latestDirection: latest ? emailFields(latest.normalizedText).labels?.includes("SENT") ? "sent" : emailFields(latest.normalizedText).labels?.includes("INBOX") ? "received" : "unknown" : null,
|
|
59
|
+
lastSyncedAt: sync?.finished_at ? new Date(sync.finished_at).toISOString() : null,
|
|
60
|
+
syncFailed: Boolean(sync?.error)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function listMailFollowUps(workspace) {
|
|
64
|
+
return getSqliteDatabase().prepare("SELECT * FROM proactive_follow_ups WHERE workspace_id = ? ORDER BY updated_at DESC").all(workspace).map(mailFollowUpView);
|
|
65
|
+
}
|
|
66
|
+
function mailFollowUpSources(workspace) {
|
|
67
|
+
const seen = /* @__PURE__ */ new Set();
|
|
68
|
+
return listKnowledgeSourceItems({
|
|
69
|
+
itemType: "email",
|
|
70
|
+
limit: 500
|
|
71
|
+
}).flatMap((item) => {
|
|
72
|
+
if (!authorizedConnectedSource(item.id, workspace, "communication_follow_up")) return [];
|
|
73
|
+
const thread = readMailThread(item.id);
|
|
74
|
+
if (!thread || seen.has(thread.threadKey)) return [];
|
|
75
|
+
seen.add(thread.threadKey);
|
|
76
|
+
const fields = emailFields(item.normalizedText);
|
|
77
|
+
const connection = getConnectorConnection(String(item.metadata.connectionId));
|
|
78
|
+
const account = connection?.alias ?? connection?.identity.email ?? connection?.identity.name;
|
|
79
|
+
return [{
|
|
80
|
+
id: item.id,
|
|
81
|
+
subject: fields.subject ?? "Email",
|
|
82
|
+
sender: fields.sender ?? "",
|
|
83
|
+
occurredAt: item.occurredAt,
|
|
84
|
+
accountLabel: typeof account === "string" ? account : "Connected email account"
|
|
85
|
+
}];
|
|
86
|
+
}).slice(0, 100);
|
|
87
|
+
}
|
|
88
|
+
function startMailFollowUp(workspace, value) {
|
|
89
|
+
const input = CreateSchema.parse(value);
|
|
90
|
+
if (Date.parse(input.dueAt) <= Date.now()) throw new Error("Choose a future follow-up time");
|
|
91
|
+
if (!authorizedConnectedSource(input.sourceItemId, workspace, "communication_follow_up")) throw new Error("Authorize this email account for proactive follow-up first");
|
|
92
|
+
const thread = readMailThread(input.sourceItemId);
|
|
93
|
+
if (!thread) throw new Error("This email has no available thread");
|
|
94
|
+
return runSqliteWriteTransaction((db) => {
|
|
95
|
+
if (db.prepare("SELECT 1 FROM proactive_follow_ups WHERE workspace_id = ? AND thread_key = ?").get(workspace, thread.threadKey)) throw new ProactiveConflict("This conversation is already delegated; update the existing follow-up");
|
|
96
|
+
const sub = listSubscriptions("communication_follow_up").find((item) => item.workspaceId === workspace) ?? createControlledSubscription(workspace, {
|
|
97
|
+
scenarioKey: "communication_follow_up",
|
|
98
|
+
scopeKind: "workspace",
|
|
99
|
+
scopeId: workspace
|
|
100
|
+
});
|
|
101
|
+
const id = randomUUID();
|
|
102
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
103
|
+
db.prepare(`INSERT INTO proactive_follow_ups(id, subscription_id, workspace_id, source_item_id, thread_key, instructions, due_at, created_at, updated_at)
|
|
104
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, sub.id, workspace, input.sourceItemId, thread.threadKey, input.instructions, input.dueAt, now, now);
|
|
105
|
+
scanMailFollowUps(new ProactiveEventService(() => new ProactiveScenarioService().routes()));
|
|
106
|
+
return mailFollowUpView(requireMailFollowUp(workspace, id));
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function updateMailFollowUp(workspace, id, value) {
|
|
110
|
+
const input = UpdateSchema.parse(value);
|
|
111
|
+
return runSqliteWriteTransaction((db) => {
|
|
112
|
+
const row = requireMailFollowUp(workspace, id);
|
|
113
|
+
if (row.revision !== input.expectedRevision) throw new ProactiveConflict("Follow-up changed; refresh before editing");
|
|
114
|
+
if (input.dueAt && Date.parse(input.dueAt) <= Date.now()) throw new Error("Choose a future follow-up time");
|
|
115
|
+
db.prepare(`UPDATE proactive_follow_ups SET instructions = ?, due_at = ?, status = ?, revision = revision + 1,
|
|
116
|
+
last_fingerprint = NULL, updated_at = ? WHERE id = ?`).run(input.instructions ?? row.instructions, input.dueAt ?? row.due_at, input.status ?? row.status, (/* @__PURE__ */ new Date()).toISOString(), id);
|
|
117
|
+
scanMailFollowUps(new ProactiveEventService(() => new ProactiveScenarioService().routes()));
|
|
118
|
+
return mailFollowUpView(requireMailFollowUp(workspace, id));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/** Keep the existing chat and its exact connector confirmation flow as the write boundary. */
|
|
122
|
+
function continueMailFollowUp(workspace, id, sessionKey) {
|
|
123
|
+
const follow = requireMailFollowUp(workspace, id);
|
|
124
|
+
const thread = authorizedMailThread(follow);
|
|
125
|
+
if (!thread || follow.status !== "watching" || !effectiveProactivePolicy(follow.subscription_id).enabled) throw new Error("Resume and authorize this follow-up before continuing");
|
|
126
|
+
getSqliteDatabase().prepare("UPDATE proactive_follow_ups SET session_key = ? WHERE id = ?").run(sessionKey, id);
|
|
127
|
+
return {
|
|
128
|
+
followUp: mailFollowUpView(requireMailFollowUp(workspace, id)),
|
|
129
|
+
connectionId: thread.origin.metadata.connectionId,
|
|
130
|
+
sourceItemId: thread.origin.id,
|
|
131
|
+
threadId: emailFields(thread.origin.normalizedText).threadId,
|
|
132
|
+
instruction: "Read the current card and latest thread using this exact connection. Review the recipients and complete draft with the user before sending through the connector approval flow. Never infer successful delivery from a draft or approval. Use provider results, then continue watching synchronized replies."
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** Poll only delegated threads; unchanged threads and passed deadlines produce no repeat signals. */
|
|
136
|
+
function scanMailFollowUps(events, now = /* @__PURE__ */ new Date()) {
|
|
137
|
+
const db = getSqliteDatabase();
|
|
138
|
+
let published = 0;
|
|
139
|
+
for (const follow of db.prepare("SELECT * FROM proactive_follow_ups WHERE status = 'watching'").all()) {
|
|
140
|
+
if (!effectiveProactivePolicy(follow.subscription_id, now).enabled) continue;
|
|
141
|
+
const thread = authorizedMailThread(follow);
|
|
142
|
+
if (!thread) continue;
|
|
143
|
+
const fingerprint = `${follow.revision}:${thread.fingerprint}:${Date.parse(follow.due_at) <= now.getTime() ? "due" : "waiting"}`;
|
|
144
|
+
if (fingerprint !== follow.last_fingerprint) {
|
|
145
|
+
if (events.publish({
|
|
146
|
+
type: "proactive.follow_up.v1",
|
|
147
|
+
schemaVersion: 1,
|
|
148
|
+
source: {
|
|
149
|
+
kind: "connector",
|
|
150
|
+
id: String(thread.origin.metadata.connectionId)
|
|
151
|
+
},
|
|
152
|
+
subject: {
|
|
153
|
+
kind: "mail_follow_up",
|
|
154
|
+
id: follow.id
|
|
155
|
+
},
|
|
156
|
+
actor: { kind: "system" },
|
|
157
|
+
scope: { workspaceId: follow.workspace_id },
|
|
158
|
+
occurredAt: now.toISOString(),
|
|
159
|
+
dedupeKey: `mail-follow-up:${follow.id}:${fingerprint}`,
|
|
160
|
+
sensitivity: "personal",
|
|
161
|
+
payload: { followUpId: follow.id }
|
|
162
|
+
}, now).inserted) published++;
|
|
163
|
+
}
|
|
164
|
+
db.prepare("UPDATE proactive_follow_ups SET last_fingerprint = ?, last_checked_at = ? WHERE id = ?").run(fingerprint, now.toISOString(), follow.id);
|
|
165
|
+
}
|
|
166
|
+
return published;
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
export { COMMUNICATION_SCENARIO, authorizedMailThread, continueMailFollowUp, listMailFollowUps, mailFollowUpSources, mailFollowUpView, requireMailFollowUp, scanMailFollowUps, startMailFollowUp, updateMailFollowUp };
|