@xopcai/xopc 0.0.308 → 0.0.311
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/_locales/en/messages.json +8 -0
- package/dist/browser-ext/_locales/zh_CN/messages.json +8 -0
- package/dist/browser-ext/dist/assets/{sidepanel-BbSQr-6P.css → sidepanel-DD6GEMvc.css} +16 -0
- package/dist/browser-ext/dist/sidepanel.html +1 -1
- package/dist/browser-ext/dist/sidepanel.js +537 -96
- 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-wgSB2HYK.js → activity-store-DVUTs1fk.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-dUotwUO6.js → agent-avatar-dicebear-zKINl7UH.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-D2ePZKdY.js +1 -0
- package/dist/gateway/static/root/assets/{agents-VPDIGRSS.js → agents-BiD9STyv.js} +1 -1
- package/dist/gateway/static/root/assets/{api-BKHmTb0w.js → api-_aHQA8bd.js} +1 -1
- package/dist/gateway/static/root/assets/{app-link-BiBXVEvp.js → app-link-wamYbNUl.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-zPz0rOND.js → app-management-settings-panel-C94LAxyt.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DhvhR43G.js → appearance-settings-CP01zHvC.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-B7DmSJQj.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BQVZMreT.js → archive-plugin-SwWFt5MT.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CPE-TMPf.js → attachment-load-DdTFml9l.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-C4IAy_zF.js → automations-page-Kmr5WVFp.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-bkijiu-Y.js +7 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DgTl7diZ.js → binary-plugins-47UTtDNq.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CcOVA-Gw.js → block-editor-DvzZkMG8.js} +3 -3
- package/dist/gateway/static/root/assets/{browser-automation-inputs-BzkJog8e.js → browser-automation-inputs-C611KRBx.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page--zKAgj1k.js → browser-automations-page-DrUKNL9X.js} +2 -2
- package/dist/gateway/static/root/assets/browser-settings-page-Dhf_MWCf.js +3 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BCubrDf8.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-e4T1DEfN.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-BfLd2rIJ.js → chat-terminal-dock-Bg_m7HUE.js} +2 -2
- package/dist/gateway/static/root/assets/{chunk-KS7C4IRE-Cq1tE_3b.js → chunk-KS7C4IRE-BMYIfy9x.js} +2 -2
- package/dist/gateway/static/root/assets/computer-settings-page-CosCmVsT.js +1 -0
- package/dist/gateway/static/root/assets/{connector-service-page-BlC1OXX4.js → connector-service-page-BL-hSR7_.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-C0WWxnxJ.js +2 -0
- package/dist/gateway/static/root/assets/date-picker-DqYFVasF.js +1 -0
- package/dist/gateway/static/root/assets/{dependency-picker-CF_zYzxX.js → dependency-picker-DCyyFLKp.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-CDwtLR7Z.js → desktop-pet-CFnnpRA_.js} +1 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-U5wWRH4c.js +1 -0
- package/dist/gateway/static/root/assets/device-pairing-wizard-BhHxvFO1.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-CX5OXxEU.js → extension-debug-page-DA8WJ3-E.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BytR1PaY.js → extension-page-C2BIB88m.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CkaMJA5F.js → extension-settings-page-kpYo979N.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-B6wHa6ZI.js → gateway-config-swr-DUDX42qY.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-realtime-B53R0CA4.js → gateway-realtime-CGOW0-b4.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-D4um_sV7.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-CE9t1yTa.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DRzGnEV-.js → gateway-startup-retry-Cf8OxlvY.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-C7Ezx8Du.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-Ck_pyDom.js → image-generation-api-D2YorS--.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-DrtbjL8O.js → imports-page-NPk698vI.js} +1 -1
- package/dist/gateway/static/root/assets/index-1wIKA-kM.css +1 -0
- package/dist/gateway/static/root/assets/index-DxYitLp8.js +79 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BlZh41Xq.js → keyboard-shortcuts-settings-BhreF0_O.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CPmynb3x.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DbP7wWuh.js → local-apps-page-DOZZBdqj.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-msTfRK8P.js → locale-store-DA0Z5jM_.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-C0n66FiO.js → logs-page-M8kz26yo.js} +2 -2
- package/dist/gateway/static/root/assets/{management-settings-i6GhxpGV.js → management-settings-JLqHYQvY.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-BInabSKf.js → markdown-view-BDpcjR_Z.js} +1 -1
- package/dist/gateway/static/root/assets/markdown-view-DSjfHfaW.css +1 -0
- package/dist/gateway/static/root/assets/{media-plugins-CnWChQ3Y.js → media-plugins-B75SWUJd.js} +1 -1
- package/dist/gateway/static/root/assets/messages-4BtQKYlM.js +3 -0
- package/dist/gateway/static/root/assets/note-detail-panel-B_Ft0M32.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-C32mxSD-.js +8 -0
- package/dist/gateway/static/root/assets/{page-tabs-BWitjb3e.js → page-tabs-CMlQUzT6.js} +1 -1
- package/dist/gateway/static/root/assets/{popover-select-9i-ZtHXL.js → popover-select-B-GDnZO9.js} +1 -1
- package/dist/gateway/static/root/assets/preview-open-alternatives-cZ2hszQT.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-gmi5LLwM.js → product-open-page-CPoSbglF.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-DYttWua0.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-D46drWbl.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-BSWtko7U.js → registry-api-C0DCx3wv.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-C9n9Nuhi.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-CtOjKGWg.js → runtime-tools-settings-panel-bMLWRApp.js} +2 -2
- package/dist/gateway/static/root/assets/scenes-page-Dw3hmHAr.js +1 -0
- package/dist/gateway/static/root/assets/{schema-form-DkyyDcl2.js → schema-form-UVJV_7AS.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-C8P6ff91.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-whpUsAy3.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-C0JDGN_V.js → settings-form-section-BqzOqonM.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-DQ9RJ8-b.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-layout-D3Spald3.js +1 -0
- package/dist/gateway/static/root/assets/{settings-shell-layer-context-DCp6ykjQ.js → settings-shell-layer-context-BTQUDoJ2.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-C8u601m8.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-Bt1K657Y.js → share-preview-page-BcgYzA7y.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-Bv-2rZ8e.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-LM-cgWUS.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-ggmb7rCW.js +2 -0
- package/dist/gateway/static/root/assets/{skills-page.utils-vq5Ujm03.js → skills-page.utils-ADABzrtk.js} +1 -1
- package/dist/gateway/static/root/assets/system-settings-panel-DfkcW_Za.js +1 -0
- package/dist/gateway/static/root/assets/task-detail-page-DC4yqDFd.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-1SZ-HFHX.js → theme-store-CegIlB8d.js} +1 -1
- package/dist/gateway/static/root/assets/tunnel-api-CTuwTdMm.js +1 -0
- package/dist/gateway/static/root/assets/use-autosave-5ZDd9XKh.js +1 -0
- package/dist/gateway/static/root/assets/user-model-page-BFKFhdZ0.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-B2pZCcxY.js → voice-api-key-field-D3urfd-n.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-DgJML_uM.js → voice-config-api-DTyMdGOR.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-Bptv7bEY.js → work-discovery-overlay-JzM3Ylbs.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BijCrNc4.js → workflow-run-setup-panel-Bn2CtRdB.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-BiCmt98A.js +6 -0
- package/dist/gateway/static/root/connector-icons/SOURCES.md +0 -2
- package/dist/gateway/static/root/index.html +17 -20
- package/dist/gateway/static/root/notification-sw.js +1 -1
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/notifications.js +12 -11
- package/dist/packages/gateway-contract/src/proactive.js +6 -6
- package/dist/packages/gateway-contract/src/project-monitoring.js +4 -4
- package/dist/packages/gateway-contract/src/project-operating.js +1 -4
- package/dist/packages/gateway-contract/src/sessions.js +6 -1
- package/dist/src/agent/agent-manager.d.ts +2 -6
- package/dist/src/agent/agent-manager.js +31 -5
- package/dist/src/agent/background-review/run-background-review.js +1 -1
- package/dist/src/agent/child-agent-factory.d.ts +1 -0
- package/dist/src/agent/child-agent-factory.js +18 -4
- package/dist/src/agent/coding/repository-instructions.d.ts +4 -0
- package/dist/src/agent/coding/repository-instructions.js +46 -2
- package/dist/src/agent/commands/command-registry.js +1 -1
- package/dist/src/agent/context/execution-scope.js +1 -1
- package/dist/src/agent/data-acquisition/git.d.ts +17 -0
- package/dist/src/agent/data-acquisition/git.js +100 -0
- package/dist/src/agent/data-acquisition/render.d.ts +7 -0
- package/dist/src/agent/data-acquisition/render.js +79 -0
- package/dist/src/agent/data-acquisition/scheduler.d.ts +12 -0
- package/dist/src/agent/data-acquisition/scheduler.js +53 -0
- package/dist/src/agent/data-acquisition/schema.d.ts +75 -0
- package/dist/src/agent/data-acquisition/schema.js +206 -0
- package/dist/src/agent/data-acquisition/service.d.ts +10 -0
- package/dist/src/agent/data-acquisition/service.js +292 -0
- package/dist/src/agent/data-acquisition/types.d.ts +37 -0
- package/dist/src/agent/data-acquisition/types.js +5 -0
- package/dist/src/agent/embedded/run-turn.js +16 -4
- package/dist/src/agent/embedded/session-runner.d.ts +1 -0
- package/dist/src/agent/embedded/session-runner.js +3 -0
- package/dist/src/agent/embedded/tool-result-truncation.js +11 -0
- package/dist/src/agent/embedded/xopc-tools-bridge.js +2 -1
- package/dist/src/agent/external-tools/cliProvider.d.ts +47 -0
- package/dist/src/agent/external-tools/cliProvider.js +317 -0
- package/dist/src/agent/external-tools/composio-provider.js +15 -4
- package/dist/src/agent/external-tools/gateway-tools.js +10 -3
- package/dist/src/agent/external-tools/index.js +14 -1
- package/dist/src/agent/external-tools/read-policy.d.ts +6 -0
- package/dist/src/agent/external-tools/read-policy.js +21 -0
- package/dist/src/agent/external-tools/service.d.ts +1 -0
- package/dist/src/agent/external-tools/service.js +4 -1
- package/dist/src/agent/external-tools/types.d.ts +3 -1
- package/dist/src/agent/external-tools/types.js +1 -0
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
- package/dist/src/agent/mcp/oauth/mcp-oauth-manager.js +1 -1
- package/dist/src/agent/memory/turn-provenance.js +2 -1
- package/dist/src/agent/orchestration/agent-turn-policy.js +25 -10
- package/dist/src/agent/orchestration/delegation-scope.d.ts +9 -0
- package/dist/src/agent/orchestration/delegation-scope.js +11 -0
- package/dist/src/agent/prompt/sections/tooling.js +3 -1
- package/dist/src/agent/prompt/subagent-context.js +4 -2
- package/dist/src/agent/sandbox/fileAccess.d.ts +2 -0
- package/dist/src/agent/sandbox/fileAccess.js +31 -2
- package/dist/src/agent/service/parse-outbound-session-key.js +1 -1
- package/dist/src/agent/service.js +1 -0
- package/dist/src/agent/service.types.d.ts +2 -0
- package/dist/src/agent/tools/dataBatch.d.ts +4 -0
- package/dist/src/agent/tools/dataBatch.js +50 -0
- package/dist/src/agent/tools/delegate-tool.d.ts +6 -3
- package/dist/src/agent/tools/delegate-tool.js +65 -48
- package/dist/src/agent/tools/delegation-parent-policy.d.ts +7 -0
- package/dist/src/agent/tools/delegation-parent-policy.js +41 -0
- package/dist/src/agent/tools/delegation-policy.d.ts +16 -0
- package/dist/src/agent/tools/delegation-policy.js +93 -0
- package/dist/src/agent/tools/factory.d.ts +4 -0
- package/dist/src/agent/tools/factory.js +45 -5
- package/dist/src/agent/tools/fetch-text.d.ts +7 -0
- package/dist/src/agent/tools/fetch-text.js +86 -0
- package/dist/src/agent/tools/find.js +1 -1
- package/dist/src/agent/tools/grep.js +11 -23
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/knowledge-memory-tool.js +10 -2
- package/dist/src/agent/tools/read.js +7 -5
- package/dist/src/agent/tools/repository-search.d.ts +12 -2
- package/dist/src/agent/tools/repository-search.js +127 -74
- package/dist/src/agent/tools/search/providers/xopc-cloud.d.ts +20 -0
- package/dist/src/agent/tools/search/providers/xopc-cloud.js +56 -0
- package/dist/src/agent/tools/search/registry.d.ts +4 -2
- package/dist/src/agent/tools/search/registry.js +5 -3
- package/dist/src/agent/tools/web.js +19 -28
- package/dist/src/agent/tools/xopc-use-tool.d.ts +4 -2
- package/dist/src/agent/tools/xopc-use-tool.js +46 -43
- package/dist/src/agent/workflow/subagent-runner.js +25 -3
- package/dist/src/agent/workflow/workflow-child-tools.js +13 -8
- package/dist/src/agent-config/schema.d.ts +7 -0
- package/dist/src/agent-config/schema.js +2 -0
- package/dist/src/automations/service/automation-service.d.ts +0 -4
- package/dist/src/automations/service/automation-service.js +0 -31
- package/dist/src/capabilities/store-connector.js +46 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/project.js +1 -1
- package/dist/src/config/schema.d.ts +8 -4
- package/dist/src/config/schema.js +2 -12
- package/dist/src/config/web-patch.js +0 -5
- package/dist/src/connectors/account-selection.d.ts +14 -0
- package/dist/src/connectors/account-selection.js +26 -0
- package/dist/src/connectors/china-catalog.js +93 -226
- package/dist/src/connectors/cli/adapterRegistry.d.ts +4 -0
- package/dist/src/connectors/cli/adapterRegistry.js +26 -0
- package/dist/src/connectors/cli/adapters/lark.d.ts +2 -0
- package/dist/src/connectors/cli/adapters/lark.js +143 -0
- package/dist/src/connectors/cli/adapters/larkShortcuts.d.ts +3 -0
- package/dist/src/connectors/cli/adapters/larkShortcuts.js +64 -0
- package/dist/src/connectors/cli/adapters/wecom.d.ts +2 -0
- package/dist/src/connectors/cli/adapters/wecom.js +97 -0
- package/dist/src/connectors/cli/adapters/wps365/bundle.js +575 -0
- package/dist/src/connectors/cli/adapters/wps365.d.ts +2 -0
- package/dist/src/connectors/cli/adapters/wps365.js +115 -0
- package/dist/src/connectors/cli/assets.d.ts +3 -0
- package/dist/src/connectors/cli/assets.js +44 -0
- package/dist/src/connectors/cli/authorization.d.ts +16 -0
- package/dist/src/connectors/cli/authorization.js +184 -0
- package/dist/src/connectors/cli/distributions.d.ts +4 -0
- package/dist/src/connectors/cli/distributions.js +69 -0
- package/dist/src/connectors/cli/installer.d.ts +5 -0
- package/dist/src/connectors/cli/installer.js +102 -0
- package/dist/src/connectors/cli/lifecycle.d.ts +1 -0
- package/dist/src/connectors/cli/lifecycle.js +19 -0
- package/dist/src/connectors/cli/process.d.ts +18 -0
- package/dist/src/connectors/cli/process.js +100 -0
- package/dist/src/connectors/cli/protocol.d.ts +10 -0
- package/dist/src/connectors/cli/protocol.js +63 -0
- package/dist/src/connectors/cli/runtime.d.ts +10 -0
- package/dist/src/connectors/cli/runtime.js +93 -0
- package/dist/src/connectors/cli/store.d.ts +35 -0
- package/dist/src/connectors/cli/store.js +121 -0
- package/dist/src/connectors/cli/types.d.ts +73 -0
- package/dist/src/connectors/composio-backends.js +1 -1
- package/dist/src/connectors/composio-sessions.d.ts +1 -0
- package/dist/src/connectors/composio-sessions.js +8 -3
- package/dist/src/connectors/composio.js +1 -1
- package/dist/src/connectors/connection-candidates.js +22 -3
- package/dist/src/connectors/connection-recovery-service.d.ts +1 -0
- package/dist/src/connectors/connection-recovery-service.js +53 -8
- package/dist/src/connectors/health.js +52 -0
- package/dist/src/connectors/instances.js +5 -1
- package/dist/src/connectors/lifecycle.js +2 -0
- package/dist/src/connectors/principal.js +2 -1
- package/dist/src/connectors/runtime-adapter-registry.js +31 -0
- package/dist/src/connectors/types.d.ts +13 -1
- package/dist/src/connectors/usage.js +1 -1
- package/dist/src/connectors/workflow-preflight.js +8 -4
- package/dist/src/extensions/install.js +1 -1
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/hono/app.d.ts +2 -0
- package/dist/src/gateway/hono/app.js +4 -2
- package/dist/src/gateway/hono/lib/config-payload.d.ts +2 -15
- package/dist/src/gateway/hono/lib/config-payload.js +0 -11
- package/dist/src/gateway/hono/routes/cli-connectors.d.ts +3 -0
- package/dist/src/gateway/hono/routes/cli-connectors.js +219 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +2 -2
- package/dist/src/gateway/hono/routes/config-patch/gateway.js +0 -59
- package/dist/src/gateway/hono/routes/config.js +0 -16
- package/dist/src/gateway/hono/routes/connectors.js +21 -22
- package/dist/src/gateway/hono/routes/deps.d.ts +2 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js +4 -17
- package/dist/src/gateway/hono/routes/projects.js +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +0 -1
- package/dist/src/gateway/hono/routes/scenes.d.ts +3 -0
- package/dist/src/gateway/hono/routes/scenes.js +142 -0
- package/dist/src/gateway/hono/routes/sessions.js +141 -13
- package/dist/src/gateway/hono/routes/tasks.js +0 -46
- package/dist/src/gateway/hono/routes/user-model.js +54 -1
- package/dist/src/gateway/scenes/browserNotifications.d.ts +4 -0
- package/dist/src/gateway/scenes/browserNotifications.js +54 -0
- package/dist/src/gateway/scenes/host.d.ts +34 -0
- package/dist/src/gateway/scenes/host.js +129 -0
- package/dist/src/gateway/scenes/mailContext.d.ts +32 -0
- package/dist/src/gateway/scenes/mailContext.js +235 -0
- package/dist/src/gateway/security/gateway-scopes.js +0 -4
- package/dist/src/gateway/security/index.js +1 -1
- package/dist/src/gateway/service/config-coordinator.d.ts +1 -10
- package/dist/src/gateway/service/config-coordinator.js +0 -16
- package/dist/src/gateway/service/run-gateway-agent.js +1 -1
- package/dist/src/gateway/service.d.ts +4 -25
- package/dist/src/gateway/service.js +44 -99
- package/dist/src/gateway/session-context-summary.js +2 -1
- package/dist/src/infra/unhandled-rejections.js +1 -1
- package/dist/src/migrations/runner.js +1 -4
- package/dist/src/notifications/browser-endpoint.d.ts +2 -0
- package/dist/src/notifications/browser-endpoint.js +13 -0
- package/dist/src/notifications/browserSubscriptions.d.ts +20 -0
- package/dist/src/notifications/browserSubscriptions.js +59 -0
- package/dist/src/notifications/browserTransport.d.ts +9 -0
- package/dist/src/notifications/browserTransport.js +64 -0
- package/dist/src/notifications/dispatch.d.ts +46 -0
- package/dist/src/notifications/dispatch.js +109 -0
- package/dist/src/notifications/domain-delivery.d.ts +21 -0
- package/dist/src/notifications/planner.js +0 -36
- package/dist/src/notifications/quietHours.d.ts +6 -0
- package/dist/src/notifications/quietHours.js +23 -0
- package/dist/src/notifications/resultOutbox.d.ts +23 -0
- package/dist/src/notifications/resultOutbox.js +49 -0
- package/dist/src/notifications/service.d.ts +18 -4
- package/dist/src/notifications/service.js +42 -61
- package/dist/src/notifications/store.d.ts +2 -1
- package/dist/src/notifications/store.js +7 -8
- package/dist/src/projects/project-service.d.ts +1 -4
- package/dist/src/projects/project-service.js +2 -30
- package/dist/src/projects/workspace.js +1 -1
- package/dist/src/providers/model-catalog-persistence.js +19 -1
- package/dist/src/providers/model-catalog-store.js +1 -0
- package/dist/src/providers/model-catalog-types.d.ts +17 -0
- package/dist/src/providers/xopc-cloud-model-source.js +27 -0
- package/dist/src/scenes/agentExecutor.d.ts +8 -0
- package/dist/src/scenes/agentExecutor.js +63 -0
- package/dist/src/scenes/contracts.d.ts +118 -0
- package/dist/src/scenes/contracts.js +145 -0
- package/dist/src/scenes/execution.d.ts +56 -0
- package/dist/src/scenes/execution.js +168 -0
- package/dist/src/scenes/httpServices.d.ts +34 -0
- package/dist/src/scenes/inbox.d.ts +16 -0
- package/dist/src/scenes/inbox.js +68 -0
- package/dist/src/scenes/mailContext.d.ts +20 -0
- package/dist/src/scenes/mailContext.js +106 -0
- package/dist/src/scenes/mailObservations.d.ts +20 -0
- package/dist/src/scenes/mailObservations.js +107 -0
- package/dist/src/scenes/maintenance.d.ts +3 -0
- package/dist/src/scenes/maintenance.js +24 -0
- package/dist/src/scenes/metrics.d.ts +35 -0
- package/dist/src/scenes/metrics.js +94 -0
- package/dist/src/scenes/notificationEligibility.d.ts +17 -0
- package/dist/src/scenes/notificationEligibility.js +72 -0
- package/dist/src/scenes/notificationPublication.d.ts +7 -0
- package/dist/src/scenes/notificationPublication.js +43 -0
- package/dist/src/scenes/preferences.d.ts +40 -0
- package/dist/src/scenes/preferences.js +108 -0
- package/dist/src/scenes/readiness.d.ts +7 -0
- package/dist/src/scenes/readiness.js +20 -0
- package/dist/src/scenes/repository.d.ts +174 -0
- package/dist/src/scenes/repository.js +740 -0
- package/dist/src/scenes/resultNotifications.d.ts +17 -0
- package/dist/src/scenes/resultNotifications.js +204 -0
- package/dist/src/scenes/runtime.d.ts +25 -0
- package/dist/src/scenes/runtime.js +101 -0
- package/dist/src/scenes/schedule.d.ts +9 -0
- package/dist/src/scenes/schedule.js +45 -0
- package/dist/src/scenes/service.d.ts +29 -0
- package/dist/src/scenes/service.js +116 -0
- package/dist/src/scenes/templates.d.ts +64 -0
- package/dist/src/scenes/templates.js +76 -0
- package/dist/src/scenes/userNotes.d.ts +10 -0
- package/dist/src/scenes/userNotes.js +34 -0
- package/dist/src/session/resolve-session.js +2 -1
- package/dist/src/session/store.js +2 -1
- package/dist/src/share/share-config.js +0 -5
- package/dist/src/share/site-share-config.js +0 -5
- package/dist/src/storage/sqlite/connection-wait-repository.js +20 -7
- package/dist/src/storage/sqlite/connection.js +1 -1
- package/dist/src/storage/sqlite/connector-account-repository.js +1 -0
- package/dist/src/storage/sqlite/connector-sync-policy-repository.d.ts +0 -4
- package/dist/src/storage/sqlite/connector-sync-policy-repository.js +3 -17
- package/dist/src/storage/sqlite/conversation-repository.js +2 -1
- package/dist/src/storage/sqlite/index.d.ts +1 -0
- package/dist/src/storage/sqlite/index.js +4 -2
- package/dist/src/storage/sqlite/migrations/186_sidebar_layout.sql +16 -0
- package/dist/src/storage/sqlite/migrations/187_cli_connectors.sql +34 -0
- package/dist/src/storage/sqlite/migrations/188_scene_storage.sql +2 -0
- package/dist/src/storage/sqlite/migrations/189_scene_source_health.sql +8 -0
- package/dist/src/storage/sqlite/migrations/conversation-backup.d.ts +2 -0
- package/dist/src/storage/sqlite/migrations/conversation-backup.js +7 -3
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +20 -44
- package/dist/src/storage/sqlite/migrations/scene-reset.d.ts +5 -0
- package/dist/src/storage/sqlite/migrations/scene-reset.js +40 -0
- package/dist/src/storage/sqlite/scenes-schema.d.ts +8 -0
- package/dist/src/storage/sqlite/scenes-schema.js +61 -0
- package/dist/src/storage/sqlite/schema.js +4 -10
- package/dist/src/storage/sqlite/schemas/notifications.sql +65 -0
- package/dist/src/storage/sqlite/schemas/scenes.sql +212 -0
- package/dist/src/storage/sqlite/session-read-repository.d.ts +8 -0
- package/dist/src/storage/sqlite/session-read-repository.js +35 -0
- package/dist/src/storage/sqlite/session-repository.d.ts +1 -1
- package/dist/src/storage/sqlite/session-repository.js +2 -25
- package/dist/src/storage/sqlite/sidebar-layout-repository.d.ts +12 -0
- package/dist/src/storage/sqlite/sidebar-layout-repository.js +53 -0
- package/dist/src/storage/sqlite/sql-assets.d.ts +2 -0
- package/dist/src/storage/sqlite/sql-assets.js +18 -0
- package/dist/src/storage/sqlite/transaction.d.ts +2 -0
- package/dist/src/storage/sqlite/transaction.js +20 -1
- package/dist/src/tasks/home-query-service.d.ts +0 -2
- package/dist/src/tasks/home-query-service.js +13 -43
- package/dist/src/tasks/index.d.ts +0 -1
- package/dist/src/tasks/index.js +4 -5
- package/dist/src/tasks/project-operating-view-service.js +1 -4
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/tui/tui-commands.js +1 -1
- package/dist/src/user-model/goals.d.ts +10 -0
- package/dist/src/user-model/goals.js +29 -1
- package/dist/src/user-model/index.js +2 -2
- package/dist/src/voice/realtime/memory-context.js +2 -1
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/package.json +5 -3
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-C6LflMXr.js +0 -1
- package/dist/gateway/static/root/assets/api-DFOlahZv.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-Pmslbzzr.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-Fx5VUJRu.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-DBms6d35.js +0 -3
- package/dist/gateway/static/root/assets/capabilities-settings-panel-epdDWIZy.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-B0bsDtmP.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-B2JwuTjG.js +0 -1
- package/dist/gateway/static/root/assets/computer-settings-page-Ckgc0Py-.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-By33-bF1.js +0 -2
- package/dist/gateway/static/root/assets/cron-expression-CqNE-nf6.js +0 -2
- package/dist/gateway/static/root/assets/date-picker-BS9ZjzYJ.js +0 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-C0djIc1J.js +0 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-CDKj9LQj.js +0 -1
- package/dist/gateway/static/root/assets/external-link-DjqjBmc3.js +0 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-BLDgrJ30.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-_YU-1p0z.js +0 -1
- package/dist/gateway/static/root/assets/globe-DSSGFWFn.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-CVIvvm4x.js +0 -1
- package/dist/gateway/static/root/assets/home-page-COCHelcL.js +0 -1
- package/dist/gateway/static/root/assets/index-CDfcPiPb.js +0 -79
- package/dist/gateway/static/root/assets/index-CRu1p38D.css +0 -1
- package/dist/gateway/static/root/assets/loader-circle-CifKLtgG.js +0 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-D7_Raxjw.js +0 -2
- package/dist/gateway/static/root/assets/markdown-view-Y68dCxuc.css +0 -1
- package/dist/gateway/static/root/assets/messages-F74LVAiU.js +0 -3
- package/dist/gateway/static/root/assets/note-detail-panel-C59d8vDW.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-C1GBPrVI.js +0 -8
- package/dist/gateway/static/root/assets/preview-open-alternatives-UaCWCxZv.js +0 -1
- package/dist/gateway/static/root/assets/proactive-page-CtSFJxoM.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-ILTmQ1YN.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-snl4rOQZ.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BbaAcEN3.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-DrWL71O8.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BG0kl4HT.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DiIyMQ52.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-layout-X1x-2Cp9.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-EPazhoZO.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-g2MdRXSZ.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-B1DPzu98.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-Wd0uYSPG.js +0 -2
- package/dist/gateway/static/root/assets/system-settings-panel-Cz1P-HDH.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-BG3A5gPZ.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-DQGoFuZO.js +0 -1
- package/dist/gateway/static/root/assets/use-autosave-DVDlBb95.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-qM5UiTGx.js +0 -2
- package/dist/gateway/static/root/assets/workflows-page-DRy1RAYH.js +0 -6
- package/dist/gateway/static/root/connector-icons/wps-calendar.svg +0 -14
- package/dist/gateway/static/root/connector-icons/wps-mail.svg +0 -7
- package/dist/src/connectors/source-change-publisher.d.ts +0 -17
- package/dist/src/connectors/source-change-publisher.js +0 -151
- package/dist/src/gateway/heartbeat/check-store.d.ts +0 -18
- package/dist/src/gateway/heartbeat/check-store.js +0 -74
- package/dist/src/gateway/heartbeat/index.d.ts +0 -1
- package/dist/src/gateway/heartbeat/index.js +0 -2
- package/dist/src/gateway/heartbeat/service.d.ts +0 -55
- package/dist/src/gateway/heartbeat/service.js +0 -228
- package/dist/src/gateway/hono/routes/proactive-control.d.ts +0 -3
- package/dist/src/gateway/hono/routes/proactive-control.js +0 -135
- package/dist/src/gateway/hono/routes/proactive.d.ts +0 -4
- package/dist/src/gateway/hono/routes/proactive.js +0 -164
- package/dist/src/gateway/hono/routes/workspace.d.ts +0 -3
- package/dist/src/gateway/hono/routes/workspace.js +0 -62
- package/dist/src/gateway/workspace-heartbeat-path.d.ts +0 -3
- package/dist/src/gateway/workspace-heartbeat-path.js +0 -14
- package/dist/src/migrations/conversation-routing-config.d.ts +0 -2
- package/dist/src/migrations/conversation-routing-config.js +0 -42
- package/dist/src/notifications/proactive-channel.d.ts +0 -8
- package/dist/src/notifications/proactive-channel.js +0 -60
- package/dist/src/notifications/proactive-policy.d.ts +0 -3
- package/dist/src/notifications/proactive-policy.js +0 -35
- package/dist/src/notifications/web-push.d.ts +0 -19
- package/dist/src/notifications/web-push.js +0 -185
- package/dist/src/proactive/actions/service.d.ts +0 -1
- package/dist/src/proactive/actions/service.js +0 -82
- package/dist/src/proactive/events/envelope.d.ts +0 -2
- package/dist/src/proactive/events/envelope.js +0 -54
- package/dist/src/proactive/events/product-event-bridge.d.ts +0 -7
- package/dist/src/proactive/events/product-event-bridge.js +0 -87
- package/dist/src/proactive/events/publisher.d.ts +0 -4
- package/dist/src/proactive/events/repository.d.ts +0 -9
- package/dist/src/proactive/events/repository.js +0 -63
- package/dist/src/proactive/events/types.d.ts +0 -44
- package/dist/src/proactive/events/types.js +0 -15
- package/dist/src/proactive/execution/agent-executor.d.ts +0 -21
- package/dist/src/proactive/execution/agent-executor.js +0 -125
- package/dist/src/proactive/execution/authorization.d.ts +0 -7
- package/dist/src/proactive/execution/authorization.js +0 -71
- package/dist/src/proactive/execution/context.d.ts +0 -49
- package/dist/src/proactive/execution/context.js +0 -408
- package/dist/src/proactive/execution/insight.d.ts +0 -14
- package/dist/src/proactive/execution/insight.js +0 -132
- package/dist/src/proactive/execution/repository.d.ts +0 -28
- package/dist/src/proactive/execution/repository.js +0 -211
- package/dist/src/proactive/execution/types.d.ts +0 -80
- package/dist/src/proactive/execution/worker.d.ts +0 -15
- package/dist/src/proactive/execution/worker.js +0 -146
- package/dist/src/proactive/experience.d.ts +0 -89
- package/dist/src/proactive/experience.js +0 -195
- package/dist/src/proactive/follow-ups.d.ts +0 -128
- package/dist/src/proactive/follow-ups.js +0 -182
- package/dist/src/proactive/inbox/cards.d.ts +0 -21
- package/dist/src/proactive/inbox/cards.js +0 -276
- package/dist/src/proactive/inbox/delivery.d.ts +0 -6
- package/dist/src/proactive/inbox/delivery.js +0 -54
- package/dist/src/proactive/inbox/digest.d.ts +0 -8
- package/dist/src/proactive/inbox/digest.js +0 -123
- package/dist/src/proactive/inbox/lifecycle.d.ts +0 -4
- package/dist/src/proactive/inbox/lifecycle.js +0 -62
- package/dist/src/proactive/inbox/notification-policy.d.ts +0 -1
- package/dist/src/proactive/inbox/notification-policy.js +0 -25
- package/dist/src/proactive/inbox/repository.d.ts +0 -25
- package/dist/src/proactive/inbox/repository.js +0 -244
- package/dist/src/proactive/inbox/service.d.ts +0 -23
- package/dist/src/proactive/inbox/service.js +0 -46
- package/dist/src/proactive/inbox/types.d.ts +0 -64
- package/dist/src/proactive/inbox/worker.d.ts +0 -13
- package/dist/src/proactive/inbox/worker.js +0 -71
- package/dist/src/proactive/index.d.ts +0 -20
- package/dist/src/proactive/index.js +0 -14
- package/dist/src/proactive/mail-thread.d.ts +0 -13
- package/dist/src/proactive/mail-thread.js +0 -55
- package/dist/src/proactive/maintenance.d.ts +0 -4
- package/dist/src/proactive/maintenance.js +0 -28
- package/dist/src/proactive/metrics.d.ts +0 -10
- package/dist/src/proactive/metrics.js +0 -28
- package/dist/src/proactive/policy/presence.d.ts +0 -2
- package/dist/src/proactive/policy/presence.js +0 -30
- package/dist/src/proactive/policy/service.d.ts +0 -54
- package/dist/src/proactive/policy/service.js +0 -123
- package/dist/src/proactive/routing/batch-repository.d.ts +0 -27
- package/dist/src/proactive/routing/batch-repository.js +0 -57
- package/dist/src/proactive/routing/matcher.d.ts +0 -5
- package/dist/src/proactive/routing/matcher.js +0 -57
- package/dist/src/proactive/routing/types.d.ts +0 -44
- package/dist/src/proactive/routing/types.js +0 -1
- package/dist/src/proactive/scenarios/control.d.ts +0 -52
- package/dist/src/proactive/scenarios/control.js +0 -75
- package/dist/src/proactive/scenarios/prompt-composer.d.ts +0 -14
- package/dist/src/proactive/scenarios/prompt-composer.js +0 -26
- package/dist/src/proactive/scenarios/repository.d.ts +0 -23
- package/dist/src/proactive/scenarios/repository.js +0 -174
- package/dist/src/proactive/scenarios/service.d.ts +0 -15
- package/dist/src/proactive/scenarios/service.js +0 -26
- package/dist/src/proactive/scenarios/types.d.ts +0 -43
- package/dist/src/proactive/scenarios/types.js +0 -1
- package/dist/src/proactive/service.d.ts +0 -25
- package/dist/src/proactive/service.js +0 -78
- package/dist/src/proactive/source-freshness.d.ts +0 -8
- package/dist/src/proactive/source-freshness.js +0 -28
- package/dist/src/proactive/status.d.ts +0 -2
- package/dist/src/proactive/status.js +0 -22
- package/dist/src/proactive/temporal/schedule.d.ts +0 -3
- package/dist/src/proactive/temporal/schedule.js +0 -68
- package/dist/src/proactive/temporal/worker.d.ts +0 -17
- package/dist/src/proactive/temporal/worker.js +0 -129
- package/dist/src/tasks/project-monitoring-service.d.ts +0 -32
- package/dist/src/tasks/project-monitoring-service.js +0 -118
- /package/dist/src/{proactive/execution → connectors/cli}/types.js +0 -0
- /package/dist/src/{proactive/events/publisher.js → notifications/domain-delivery.js} +0 -0
- /package/dist/src/{proactive/inbox/types.js → scenes/httpServices.js} +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { intersectPermissions, sceneContentHash } from "./contracts.js";
|
|
2
|
+
import { SceneSourceNotReady, sceneSourceFailureReason } from "./readiness.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region src/scenes/execution.ts
|
|
5
|
+
const readOnlyResultSchema = z.strictObject({
|
|
6
|
+
kind: z.enum([
|
|
7
|
+
"no_change",
|
|
8
|
+
"observation",
|
|
9
|
+
"artifact",
|
|
10
|
+
"decision"
|
|
11
|
+
]),
|
|
12
|
+
summary: z.string().max(32e3),
|
|
13
|
+
evidenceIds: z.array(z.string().min(1)).max(100)
|
|
14
|
+
}).refine((result) => result.kind === "no_change" || result.summary.trim().length > 0 && result.evidenceIds.length > 0, "A useful result requires evidence");
|
|
15
|
+
var SceneExecutionRejected = class extends Error {
|
|
16
|
+
constructor(reason) {
|
|
17
|
+
super(reason);
|
|
18
|
+
this.reason = reason;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
function evidenceAllowed(item, activation, permissions, now) {
|
|
22
|
+
if (!item.id || !item.revision || !Number.isFinite(item.freshUntil) || item.freshUntil <= now) return false;
|
|
23
|
+
if (item.ownerId !== activation.ownerId || item.workspaceId !== activation.workspaceId) return false;
|
|
24
|
+
if (item.accountId !== void 0 && !permissions.accountIds.includes(item.accountId)) return false;
|
|
25
|
+
const scope = activation.scope;
|
|
26
|
+
if (scope.kind === "objects") return scope.ids.includes(item.subjectId);
|
|
27
|
+
if (scope.kind === "project") return item.projectId === scope.id;
|
|
28
|
+
if (scope.kind === "conversation") return item.conversationId === scope.id;
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
/** Runs one durable claim without exposing messaging, filesystem or write tools. */
|
|
32
|
+
var SceneExecutionService = class {
|
|
33
|
+
constructor(repository, providers, executor, authorize, clock = Date.now) {
|
|
34
|
+
this.repository = repository;
|
|
35
|
+
this.providers = providers;
|
|
36
|
+
this.executor = executor;
|
|
37
|
+
this.authorize = authorize;
|
|
38
|
+
this.clock = clock;
|
|
39
|
+
if (new Set(providers.map((provider) => provider.id)).size !== providers.length) throw new Error("Duplicate scene context providers");
|
|
40
|
+
}
|
|
41
|
+
async runNext(worker, outerSignal) {
|
|
42
|
+
outerSignal?.throwIfAborted();
|
|
43
|
+
const claim = this.repository.claimNext(worker, this.clock(), 62e4);
|
|
44
|
+
if (!claim) return "idle";
|
|
45
|
+
const runInput = this.repository.getRunInput(claim, this.clock());
|
|
46
|
+
if (!runInput) return "discarded";
|
|
47
|
+
const { activation, subjectId, accountId, notBefore } = runInput;
|
|
48
|
+
const template = this.repository.getTemplate(activation.templateKey, activation.templateVersion);
|
|
49
|
+
if (!this.repository.renewLease(claim, this.clock(), template.execution.limits.timeoutSeconds * 1e3 + 5e3)) return "discarded";
|
|
50
|
+
const controller = new AbortController();
|
|
51
|
+
const abort = () => controller.abort(outerSignal?.reason);
|
|
52
|
+
outerSignal?.addEventListener("abort", abort, { once: true });
|
|
53
|
+
if (outerSignal?.aborted) abort();
|
|
54
|
+
const timeout = setTimeout(() => controller.abort(/* @__PURE__ */ new Error("Scene execution timed out")), template.execution.limits.timeoutSeconds * 1e3);
|
|
55
|
+
let stopWaiting;
|
|
56
|
+
const aborted = new Promise((_, reject) => {
|
|
57
|
+
const listener = () => reject(controller.signal.reason ?? /* @__PURE__ */ new Error("Scene execution aborted"));
|
|
58
|
+
controller.signal.addEventListener("abort", listener, { once: true });
|
|
59
|
+
stopWaiting = () => controller.signal.removeEventListener("abort", listener);
|
|
60
|
+
if (controller.signal.aborted) listener();
|
|
61
|
+
});
|
|
62
|
+
const assertCurrent = () => {
|
|
63
|
+
controller.signal.throwIfAborted();
|
|
64
|
+
if (!this.repository.getRunInput(claim, this.clock())) throw new SceneExecutionRejected("activation_changed");
|
|
65
|
+
};
|
|
66
|
+
const readContext = async () => {
|
|
67
|
+
assertCurrent();
|
|
68
|
+
let granted;
|
|
69
|
+
try {
|
|
70
|
+
granted = await this.authorize(activation);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (template.contextProviders.includes("mail")) this.repository.recordSourceHealth(activation, sceneSourceFailureReason(error), this.clock(), this.clock() + 6e4);
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
assertCurrent();
|
|
76
|
+
const permissions = intersectPermissions(granted, activation.permissions, {
|
|
77
|
+
accountIds: accountId === void 0 ? activation.permissions.accountIds : [accountId],
|
|
78
|
+
contextProviders: template.contextProviders,
|
|
79
|
+
effectHandlers: []
|
|
80
|
+
});
|
|
81
|
+
const evidence = [];
|
|
82
|
+
for (const providerId of template.contextProviders) {
|
|
83
|
+
if (!permissions.contextProviders.includes(providerId)) {
|
|
84
|
+
if (providerId === "mail") this.repository.recordSourceHealth(activation, "needs_permission", this.clock(), this.clock() + 6e4);
|
|
85
|
+
throw new SceneExecutionRejected("needs_permission");
|
|
86
|
+
}
|
|
87
|
+
const provider = this.providers.find((item) => item.id === providerId);
|
|
88
|
+
if (!provider) throw new SceneExecutionRejected("provider_unavailable");
|
|
89
|
+
let items;
|
|
90
|
+
try {
|
|
91
|
+
items = await provider.read({
|
|
92
|
+
activation,
|
|
93
|
+
subjectId,
|
|
94
|
+
permissions,
|
|
95
|
+
notBefore,
|
|
96
|
+
signal: controller.signal
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (providerId === "mail" && !outerSignal?.aborted) this.repository.recordSourceHealth(activation, sceneSourceFailureReason(error), this.clock(), this.clock() + 6e4);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
assertCurrent();
|
|
103
|
+
if (providerId === "mail" && items.some((item) => item.accountId === void 0)) throw new SceneExecutionRejected("missing_account_identity");
|
|
104
|
+
if (items.some((item) => !evidenceAllowed(item, activation, permissions, this.clock()))) throw new SceneExecutionRejected("unauthorized_or_stale_evidence");
|
|
105
|
+
evidence.push(...items);
|
|
106
|
+
}
|
|
107
|
+
if (evidence.length > 100 || evidence.reduce((size, item) => size + item.content.length, 0) > 12e4) throw new SceneExecutionRejected("context_budget_exceeded");
|
|
108
|
+
if (new Set(evidence.map((item) => item.id)).size !== evidence.length) throw new SceneExecutionRejected("duplicate_evidence");
|
|
109
|
+
evidence.sort((left, right) => left.id.localeCompare(right.id));
|
|
110
|
+
const fingerprint = sceneContentHash(evidence.map(({ freshUntil: _freshUntil, ...item }) => item));
|
|
111
|
+
if (template.contextProviders.includes("mail")) this.repository.recordSourceHealth(activation, null, this.clock());
|
|
112
|
+
return {
|
|
113
|
+
evidence,
|
|
114
|
+
fingerprint,
|
|
115
|
+
permissions
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
const execute = async () => {
|
|
119
|
+
const snapshot = await readContext();
|
|
120
|
+
if (!this.repository.saveSnapshot(claim, snapshot.fingerprint, snapshot.evidence.map((item) => item.id), this.clock())) return "discarded";
|
|
121
|
+
if (this.repository.reuseUnchangedResult(claim, snapshot.fingerprint, this.clock(), true)) {
|
|
122
|
+
const current = await readContext();
|
|
123
|
+
assertCurrent();
|
|
124
|
+
if (current.fingerprint !== snapshot.fingerprint || sceneContentHash(current.permissions) !== sceneContentHash(snapshot.permissions)) throw new SceneExecutionRejected("source_changed");
|
|
125
|
+
if (this.repository.reuseUnchangedResult(claim, snapshot.fingerprint, this.clock())) return "completed";
|
|
126
|
+
}
|
|
127
|
+
if (snapshot.evidence.length > 0 && !this.repository.reserveModelCall(claim, this.clock())) {
|
|
128
|
+
const now = this.clock();
|
|
129
|
+
return this.repository.deferRun(claim, now, "daily_budget", (Math.floor(now / 864e5) + 1) * 864e5);
|
|
130
|
+
}
|
|
131
|
+
const raw = snapshot.evidence.length === 0 ? {
|
|
132
|
+
kind: "no_change",
|
|
133
|
+
summary: "",
|
|
134
|
+
evidenceIds: []
|
|
135
|
+
} : await this.executor.execute({
|
|
136
|
+
template,
|
|
137
|
+
goal: activation.goal,
|
|
138
|
+
evidence: snapshot.evidence,
|
|
139
|
+
signal: controller.signal,
|
|
140
|
+
onUsage: (usage) => {
|
|
141
|
+
assertCurrent();
|
|
142
|
+
this.repository.recordModelUsage(claim, usage, this.clock());
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
assertCurrent();
|
|
146
|
+
const result = readOnlyResultSchema.parse(raw);
|
|
147
|
+
if (!template.allowedOutcomeKinds.includes(result.kind)) throw new SceneExecutionRejected("invalid_model_result");
|
|
148
|
+
if (result.evidenceIds.some((id) => !snapshot.evidence.some((item) => item.id === id))) throw new SceneExecutionRejected("unknown_evidence");
|
|
149
|
+
const current = await readContext();
|
|
150
|
+
assertCurrent();
|
|
151
|
+
if (current.fingerprint !== snapshot.fingerprint || sceneContentHash(current.permissions) !== sceneContentHash(snapshot.permissions)) throw new SceneExecutionRejected("source_changed");
|
|
152
|
+
return this.repository.finishReadOnlyRun(claim, result, this.clock()) ? "completed" : "discarded";
|
|
153
|
+
};
|
|
154
|
+
try {
|
|
155
|
+
return await Promise.race([execute(), aborted]);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
if (!controller.signal.aborted && error instanceof SceneSourceNotReady) return this.repository.deferRun(claim, this.clock(), "source_not_ready", this.clock() + 6e4);
|
|
158
|
+
this.repository.failRun(claim, this.clock(), controller.signal.aborted ? "execution_aborted" : error instanceof SceneExecutionRejected ? error.reason : error instanceof z.ZodError || error instanceof SyntaxError ? "invalid_model_result" : "execution_failed");
|
|
159
|
+
return "failed";
|
|
160
|
+
} finally {
|
|
161
|
+
clearTimeout(timeout);
|
|
162
|
+
stopWaiting?.();
|
|
163
|
+
outerSignal?.removeEventListener("abort", abort);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
//#endregion
|
|
168
|
+
export { SceneExecutionService, readOnlyResultSchema };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { BrowserSubscriptionService } from '../notifications/browserSubscriptions.js';
|
|
2
|
+
import type { ScenePrincipal } from './contracts.js';
|
|
3
|
+
import type { SceneInboxService } from './inbox.js';
|
|
4
|
+
import type { SceneRepository } from './repository.js';
|
|
5
|
+
import type { SceneApplicationService } from './service.js';
|
|
6
|
+
import type { SceneMailContextProvider } from './mailContext.js';
|
|
7
|
+
import type { ScenePreferenceService } from './preferences.js';
|
|
8
|
+
import type { SceneMetrics } from './metrics.js';
|
|
9
|
+
/** An explicitly installed scene domain; never resolves to the old runtime. */
|
|
10
|
+
export interface SceneHttpServices {
|
|
11
|
+
repository: SceneRepository;
|
|
12
|
+
application: SceneApplicationService;
|
|
13
|
+
inbox: SceneInboxService;
|
|
14
|
+
mail: SceneMailContextProvider;
|
|
15
|
+
mailDiscovery?: {
|
|
16
|
+
listAccounts(principal: ScenePrincipal): Array<{
|
|
17
|
+
id: string;
|
|
18
|
+
label: string;
|
|
19
|
+
}>;
|
|
20
|
+
searchSources(principal: ScenePrincipal, value: unknown, signal: AbortSignal): Promise<Array<{
|
|
21
|
+
id: string;
|
|
22
|
+
accountId: string;
|
|
23
|
+
subject: string;
|
|
24
|
+
sender: string;
|
|
25
|
+
}>>;
|
|
26
|
+
};
|
|
27
|
+
metrics: SceneMetrics;
|
|
28
|
+
preferences: ScenePreferenceService;
|
|
29
|
+
browser: BrowserSubscriptionService;
|
|
30
|
+
}
|
|
31
|
+
export interface SceneAccess {
|
|
32
|
+
principal: ScenePrincipal;
|
|
33
|
+
services: SceneHttpServices;
|
|
34
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { ScenePrincipal } from './contracts.js';
|
|
3
|
+
/** Feedback records a user's judgment, never an inferred successful action. */
|
|
4
|
+
export declare class SceneInboxService {
|
|
5
|
+
private readonly db;
|
|
6
|
+
private readonly clock;
|
|
7
|
+
constructor(db: DatabaseSync, clock?: () => number);
|
|
8
|
+
setRead(principal: ScenePrincipal, id: string, read: boolean): void;
|
|
9
|
+
feedback(principal: ScenePrincipal, id: string, value: unknown): number;
|
|
10
|
+
getFeedback(principal: ScenePrincipal, id: string): {
|
|
11
|
+
rating: string;
|
|
12
|
+
note: string;
|
|
13
|
+
revision: number;
|
|
14
|
+
} | null;
|
|
15
|
+
private assertVisible;
|
|
16
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { SceneConflictError, SceneNotFoundError } from "./repository.js";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region src/scenes/inbox.ts
|
|
5
|
+
const feedbackSchema = z.strictObject({
|
|
6
|
+
expectedRevision: z.number().int().nonnegative(),
|
|
7
|
+
rating: z.enum(["useful", "not_useful"]),
|
|
8
|
+
note: z.string().trim().max(2e3).optional()
|
|
9
|
+
});
|
|
10
|
+
const actionable = `withdrawn_at IS NULL AND (expires_at IS NULL OR expires_at > ?)
|
|
11
|
+
AND (status IN ('unread', 'read') OR (status = 'snoozed' AND snoozed_until <= ?))`;
|
|
12
|
+
/** Feedback records a user's judgment, never an inferred successful action. */
|
|
13
|
+
var SceneInboxService = class {
|
|
14
|
+
constructor(db, clock = Date.now) {
|
|
15
|
+
this.db = db;
|
|
16
|
+
this.clock = clock;
|
|
17
|
+
}
|
|
18
|
+
setRead(principal, id, read) {
|
|
19
|
+
if (typeof read !== "boolean") throw new Error("Read state must be a boolean");
|
|
20
|
+
this.assertVisible(principal, id);
|
|
21
|
+
const now = this.clock();
|
|
22
|
+
if (this.db.prepare(`UPDATE scene_presentations SET status = ?, revision = revision + 1, updated_at = ? WHERE id = ? AND ${actionable}`).run(read ? "read" : "unread", now, id, now, now).changes !== 1) throw new SceneConflictError("Scene presentation was withdrawn");
|
|
23
|
+
}
|
|
24
|
+
feedback(principal, id, value) {
|
|
25
|
+
const input = feedbackSchema.parse(value);
|
|
26
|
+
this.assertVisible(principal, id);
|
|
27
|
+
this.db.exec("SAVEPOINT scene_feedback_write");
|
|
28
|
+
try {
|
|
29
|
+
const now = this.clock();
|
|
30
|
+
const note = input.note ?? String(this.db.prepare("SELECT note FROM scene_feedback WHERE presentation_id = ?").get(id)?.note ?? "");
|
|
31
|
+
if ((input.expectedRevision === 0 ? this.db.prepare(`INSERT INTO scene_feedback (presentation_id, rating, note, revision, updated_at)
|
|
32
|
+
SELECT ?, ?, ?, 1, ? WHERE EXISTS (SELECT 1 FROM scene_presentations WHERE id = ? AND ${actionable})
|
|
33
|
+
ON CONFLICT(presentation_id) DO NOTHING`).run(id, input.rating, note, now, id, now, now) : this.db.prepare(`UPDATE scene_feedback SET rating = ?, note = ?, revision = revision + 1, updated_at = ?
|
|
34
|
+
WHERE presentation_id = ? AND revision = ?
|
|
35
|
+
AND EXISTS (SELECT 1 FROM scene_presentations WHERE id = ? AND ${actionable})`).run(input.rating, note, now, id, input.expectedRevision, id, now, now)).changes !== 1) throw new SceneConflictError("Scene feedback changed");
|
|
36
|
+
this.db.prepare(`INSERT INTO scene_feedback_history(id, presentation_id, rating, note, revision, recorded_at)
|
|
37
|
+
VALUES (?, ?, ?, ?, ?, ?)`).run(randomUUID(), id, input.rating, note, input.expectedRevision + 1, now);
|
|
38
|
+
this.db.exec("RELEASE scene_feedback_write");
|
|
39
|
+
return input.expectedRevision + 1;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
this.db.exec("ROLLBACK TO scene_feedback_write");
|
|
42
|
+
this.db.exec("RELEASE scene_feedback_write");
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
getFeedback(principal, id) {
|
|
47
|
+
this.assertVisible(principal, id);
|
|
48
|
+
const row = this.db.prepare("SELECT rating, note, revision FROM scene_feedback WHERE presentation_id = ?").get(id);
|
|
49
|
+
return row ? {
|
|
50
|
+
rating: String(row.rating),
|
|
51
|
+
note: String(row.note),
|
|
52
|
+
revision: Number(row.revision)
|
|
53
|
+
} : null;
|
|
54
|
+
}
|
|
55
|
+
assertVisible(principal, id) {
|
|
56
|
+
if (!principal.ownerId?.trim() || !principal.workspaceId?.trim()) throw new Error("Scene principal is required");
|
|
57
|
+
const row = this.db.prepare(`SELECT p.status, p.withdrawn_at, p.expires_at, p.snoozed_until FROM scene_presentations p
|
|
58
|
+
JOIN scene_outcomes o ON o.id = p.outcome_id JOIN scene_runs r ON r.id = o.run_id
|
|
59
|
+
JOIN scene_activations a ON a.id = r.activation_id
|
|
60
|
+
WHERE p.id = ? AND a.owner_id = ? AND a.workspace_id = ?`).get(id, principal.ownerId, principal.workspaceId);
|
|
61
|
+
if (!row) throw new SceneNotFoundError("Scene presentation not found");
|
|
62
|
+
const now = this.clock();
|
|
63
|
+
if (row.status === "withdrawn" || row.withdrawn_at !== null) throw new SceneConflictError("Scene presentation was withdrawn");
|
|
64
|
+
if (row.status === "resolved" || row.expires_at !== null && Number(row.expires_at) <= now || row.status === "snoozed" && (row.snoozed_until === null || Number(row.snoozed_until) > now)) throw new SceneConflictError("Scene presentation is not currently actionable");
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
//#endregion
|
|
68
|
+
export { SceneInboxService };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { SceneContextProvider, SceneEvidence } from './execution.js';
|
|
3
|
+
import type { SceneActivation, ScenePrincipal } from './contracts.js';
|
|
4
|
+
/** Reads a bounded, account-scoped thread from synchronized connector knowledge. */
|
|
5
|
+
export declare class SceneMailContextProvider implements SceneContextProvider {
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly clock;
|
|
8
|
+
readonly id = "mail";
|
|
9
|
+
constructor(db: DatabaseSync, clock?: () => number);
|
|
10
|
+
/** Resolve current account grants for the exact delegated source, including reconnects and revocation. */
|
|
11
|
+
authorizedAccounts(activation: SceneActivation): string[];
|
|
12
|
+
/** Picker metadata only; choosing an item still requires explicit activation consent. */
|
|
13
|
+
listSources(principal: ScenePrincipal, limit?: number, afterId?: string): {
|
|
14
|
+
id: string;
|
|
15
|
+
accountId: string;
|
|
16
|
+
subject: string;
|
|
17
|
+
sender: string;
|
|
18
|
+
}[];
|
|
19
|
+
read(input: Parameters<SceneContextProvider['read']>[0]): Promise<SceneEvidence[]>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { SceneSourceNotReady } from "./readiness.js";
|
|
2
|
+
//#region src/scenes/mailContext.ts
|
|
3
|
+
const accountJoin = `JOIN connector_accounts a ON a.id = c.account_id AND a.current_connection_id = c.id
|
|
4
|
+
AND a.principal_id = c.principal_id AND a.connector_id = c.connector_id
|
|
5
|
+
JOIN connector_installations installation ON installation.id = c.installation_id
|
|
6
|
+
AND installation.principal_id = c.principal_id AND installation.connector_id = c.connector_id`;
|
|
7
|
+
const accountPolicy = `a.enabled = 1 AND installation.enabled = 1 AND c.status = 'active'
|
|
8
|
+
AND json_array_length(installation.allowed_agent_ids_json) = 0 AND a.allowed_agent_ids_json IS NULL
|
|
9
|
+
AND (installation.selected_account_ids_json = 'null' OR EXISTS
|
|
10
|
+
(SELECT 1 FROM json_each(installation.selected_account_ids_json) WHERE value = a.id))`;
|
|
11
|
+
/** Reads a bounded, account-scoped thread from synchronized connector knowledge. */
|
|
12
|
+
var SceneMailContextProvider = class {
|
|
13
|
+
id = "mail";
|
|
14
|
+
constructor(db, clock = Date.now) {
|
|
15
|
+
this.db = db;
|
|
16
|
+
this.clock = clock;
|
|
17
|
+
}
|
|
18
|
+
/** Resolve current account grants for the exact delegated source, including reconnects and revocation. */
|
|
19
|
+
authorizedAccounts(activation) {
|
|
20
|
+
if (activation.scope.kind !== "objects" || activation.scope.ids.length !== 1) return [];
|
|
21
|
+
const row = this.db.prepare(`SELECT a.id FROM knowledge_source_items k
|
|
22
|
+
JOIN connector_connections c ON c.id = json_extract(CASE WHEN json_valid(k.metadata_json) THEN k.metadata_json ELSE '{}' END, '$.connectionId')
|
|
23
|
+
${accountJoin}
|
|
24
|
+
WHERE k.item_id = ? AND k.item_type = 'email' AND k.deleted_at IS NULL
|
|
25
|
+
AND k.sensitivity NOT IN ('secret', 'regulated')
|
|
26
|
+
AND json_valid(k.metadata_json) AND json_valid(k.normalized_text)
|
|
27
|
+
AND json_type(k.normalized_text, '$.threadId') = 'text'
|
|
28
|
+
AND length(trim(json_extract(k.normalized_text, '$.threadId'))) > 0
|
|
29
|
+
AND NOT EXISTS (SELECT 1 FROM json_each(k.normalized_text, '$.labels') WHERE value IN ('DRAFT', 'TRASH', 'SPAM'))
|
|
30
|
+
AND json_extract(k.metadata_json, '$.workspaceId') = ? AND c.principal_id = ?
|
|
31
|
+
AND ${accountPolicy}
|
|
32
|
+
AND (c.expires_at IS NULL OR julianday(c.expires_at) > julianday(?, 'unixepoch'))`).get(activation.scope.ids[0], activation.workspaceId, activation.ownerId, this.clock() / 1e3);
|
|
33
|
+
return row && activation.permissions.accountIds.includes(String(row.id)) ? [String(row.id)] : [];
|
|
34
|
+
}
|
|
35
|
+
/** Picker metadata only; choosing an item still requires explicit activation consent. */
|
|
36
|
+
listSources(principal, limit = 50, afterId = "") {
|
|
37
|
+
if (!principal.ownerId.trim() || !principal.workspaceId.trim()) throw new Error("Scene principal is required");
|
|
38
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100) throw new Error("Invalid source list limit");
|
|
39
|
+
return this.db.prepare(`SELECT k.item_id AS id, a.id AS accountId,
|
|
40
|
+
substr(json_extract(k.normalized_text, '$.subject'), 1, 300) AS subject,
|
|
41
|
+
substr(json_extract(k.normalized_text, '$.sender'), 1, 300) AS sender
|
|
42
|
+
FROM knowledge_source_items k
|
|
43
|
+
JOIN connector_connections c ON c.id = json_extract(CASE WHEN json_valid(k.metadata_json) THEN k.metadata_json ELSE '{}' END, '$.connectionId')
|
|
44
|
+
${accountJoin}
|
|
45
|
+
WHERE k.item_type = 'email' AND k.deleted_at IS NULL AND k.sensitivity NOT IN ('secret', 'regulated')
|
|
46
|
+
AND json_valid(k.normalized_text) AND json_valid(k.metadata_json)
|
|
47
|
+
AND json_extract(k.metadata_json, '$.workspaceId') = ? AND c.principal_id = ?
|
|
48
|
+
AND ${accountPolicy}
|
|
49
|
+
AND (c.expires_at IS NULL OR julianday(c.expires_at) > julianday(?, 'unixepoch'))
|
|
50
|
+
AND json_type(k.normalized_text, '$.threadId') = 'text' AND length(trim(json_extract(k.normalized_text, '$.threadId'))) > 0
|
|
51
|
+
AND NOT EXISTS (SELECT 1 FROM json_each(k.normalized_text, '$.labels') WHERE value IN ('DRAFT', 'TRASH', 'SPAM'))
|
|
52
|
+
AND k.item_id > ? ORDER BY k.item_id LIMIT ?`).all(principal.workspaceId, principal.ownerId, this.clock() / 1e3, afterId, limit).map((row) => ({
|
|
53
|
+
id: String(row.id),
|
|
54
|
+
accountId: String(row.accountId),
|
|
55
|
+
subject: typeof row.subject === "string" ? row.subject : "",
|
|
56
|
+
sender: typeof row.sender === "string" ? row.sender : ""
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
async read(input) {
|
|
60
|
+
input.signal.throwIfAborted();
|
|
61
|
+
if (!input.permissions.contextProviders.includes(this.id)) throw new Error("Mail context permission is required");
|
|
62
|
+
const origin = this.db.prepare(`SELECT * FROM knowledge_source_items WHERE item_id = ? AND item_type = 'email' AND deleted_at IS NULL`).get(input.subjectId);
|
|
63
|
+
if (!origin) throw new Error("Mail source unavailable");
|
|
64
|
+
const metadata = JSON.parse(origin.metadata_json);
|
|
65
|
+
if (metadata.workspaceId !== input.activation.workspaceId || typeof metadata.connectionId !== "string") throw new Error("Mail source workspace mismatch");
|
|
66
|
+
const connection = this.db.prepare(`SELECT c.account_id, c.expires_at FROM connector_connections c
|
|
67
|
+
${accountJoin} WHERE c.id = ? AND c.principal_id = ? AND ${accountPolicy}`).get(metadata.connectionId, input.activation.ownerId);
|
|
68
|
+
if (!connection || !input.permissions.accountIds.includes(connection.account_id)) throw new Error("Mail account permission is required");
|
|
69
|
+
if (connection.expires_at !== null && !(Date.parse(connection.expires_at) > this.clock())) throw new Error("Mail connection is expired");
|
|
70
|
+
const fields = JSON.parse(origin.normalized_text);
|
|
71
|
+
if (typeof fields.threadId !== "string" || !fields.threadId.trim()) throw new Error("Mail thread identity unavailable");
|
|
72
|
+
if (Array.isArray(fields.labels) && fields.labels.some((label) => [
|
|
73
|
+
"DRAFT",
|
|
74
|
+
"TRASH",
|
|
75
|
+
"SPAM"
|
|
76
|
+
].includes(label))) throw new Error("Mail origin is not an active message");
|
|
77
|
+
const sync = this.db.prepare(`SELECT status, started_at, finished_at FROM knowledge_sync_runs
|
|
78
|
+
WHERE source_instance_id = ? AND collection_scope = ? ORDER BY started_at DESC, rowid DESC LIMIT 1`).get(origin.source_instance_id, origin.collection_scope);
|
|
79
|
+
const now = this.clock();
|
|
80
|
+
if (!sync || sync.status !== "succeeded" || sync.finished_at === null || sync.finished_at < sync.started_at || sync.started_at > now || sync.finished_at > now || sync.started_at + 30 * 6e4 <= now || input.notBefore !== void 0 && sync.started_at < input.notBefore) throw new SceneSourceNotReady();
|
|
81
|
+
const messages = this.db.prepare(`SELECT * FROM knowledge_source_items
|
|
82
|
+
WHERE source_instance_id = ? AND collection_scope = ? AND item_type = 'email' AND deleted_at IS NULL
|
|
83
|
+
AND json_valid(normalized_text) AND json_valid(metadata_json)
|
|
84
|
+
AND json_extract(normalized_text, '$.threadId') = ?
|
|
85
|
+
AND json_extract(metadata_json, '$.connectionId') = ?
|
|
86
|
+
AND json_extract(metadata_json, '$.workspaceId') = ?
|
|
87
|
+
AND NOT EXISTS (SELECT 1 FROM json_each(normalized_text, '$.labels') WHERE value IN ('DRAFT', 'TRASH', 'SPAM'))
|
|
88
|
+
ORDER BY occurred_at, item_id LIMIT 31`).all(origin.source_instance_id, origin.collection_scope, fields.threadId, metadata.connectionId, input.activation.workspaceId);
|
|
89
|
+
if (!messages.length || messages.length > 30) throw new Error("Mail thread cannot be read completely within its budget");
|
|
90
|
+
if (messages.some((item) => ["secret", "regulated"].includes(item.sensitivity))) throw new Error("Mail thread contains restricted evidence");
|
|
91
|
+
input.signal.throwIfAborted();
|
|
92
|
+
return messages.map((item) => ({
|
|
93
|
+
id: item.item_id,
|
|
94
|
+
subjectId: input.subjectId,
|
|
95
|
+
ownerId: input.activation.ownerId,
|
|
96
|
+
workspaceId: input.activation.workspaceId,
|
|
97
|
+
accountId: connection.account_id,
|
|
98
|
+
revision: item.content_hash,
|
|
99
|
+
freshUntil: sync.started_at + 30 * 6e4,
|
|
100
|
+
...item.occurred_at !== null ? { occurredAt: item.occurred_at } : {},
|
|
101
|
+
content: item.normalized_text
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
//#endregion
|
|
106
|
+
export { SceneMailContextProvider };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type SceneActivation, type ScenePermission } from './contracts.js';
|
|
2
|
+
import type { SceneContextProvider } from './execution.js';
|
|
3
|
+
import { SceneRepository } from './repository.js';
|
|
4
|
+
/** Observes only explicitly delegated threads; the host owns scan scheduling. */
|
|
5
|
+
export declare class SceneMailObservationService {
|
|
6
|
+
private readonly repository;
|
|
7
|
+
private readonly provider;
|
|
8
|
+
private readonly authorize;
|
|
9
|
+
private readonly clock;
|
|
10
|
+
private readonly intervalMs;
|
|
11
|
+
private readonly itemTimeoutMs;
|
|
12
|
+
private nextScanAt;
|
|
13
|
+
private readonly failures;
|
|
14
|
+
constructor(repository: SceneRepository, provider: SceneContextProvider, authorize: (activation: SceneActivation) => Promise<ScenePermission>, clock?: () => number, intervalMs?: number, itemTimeoutMs?: number);
|
|
15
|
+
scan(signal: AbortSignal, afterId?: string, progress?: (id: string) => void): Promise<{
|
|
16
|
+
changed: number;
|
|
17
|
+
unavailable: number;
|
|
18
|
+
nextCursor: string | null;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { intersectPermissions, sceneContentHash } from "./contracts.js";
|
|
2
|
+
import { sceneSourceFailureReason } from "./readiness.js";
|
|
3
|
+
//#region src/scenes/mailObservations.ts
|
|
4
|
+
/** Observes only explicitly delegated threads; the host owns scan scheduling. */
|
|
5
|
+
var SceneMailObservationService = class {
|
|
6
|
+
nextScanAt = 0;
|
|
7
|
+
failures = /* @__PURE__ */ new Map();
|
|
8
|
+
constructor(repository, provider, authorize, clock = Date.now, intervalMs = 0, itemTimeoutMs = 5e3) {
|
|
9
|
+
this.repository = repository;
|
|
10
|
+
this.provider = provider;
|
|
11
|
+
this.authorize = authorize;
|
|
12
|
+
this.clock = clock;
|
|
13
|
+
this.intervalMs = intervalMs;
|
|
14
|
+
this.itemTimeoutMs = itemTimeoutMs;
|
|
15
|
+
if (provider.id !== "mail") throw new Error("Mail observation requires the mail context provider");
|
|
16
|
+
}
|
|
17
|
+
async scan(signal, afterId = "", progress) {
|
|
18
|
+
signal.throwIfAborted();
|
|
19
|
+
if (!afterId && this.clock() < this.nextScanAt) return {
|
|
20
|
+
changed: 0,
|
|
21
|
+
unavailable: 0,
|
|
22
|
+
nextCursor: null
|
|
23
|
+
};
|
|
24
|
+
const items = this.repository.listMailObservationItems(afterId, this.clock());
|
|
25
|
+
const started = Date.now();
|
|
26
|
+
let lastId = afterId;
|
|
27
|
+
let processed = 0;
|
|
28
|
+
let changed = 0;
|
|
29
|
+
let unavailable = 0;
|
|
30
|
+
for (const { principal, item } of items) {
|
|
31
|
+
signal.throwIfAborted();
|
|
32
|
+
if (Date.now() - started >= 2e4) break;
|
|
33
|
+
lastId = item.id;
|
|
34
|
+
processed += 1;
|
|
35
|
+
const backoff = this.failures.get(item.accountId);
|
|
36
|
+
if (this.intervalMs > 0 && backoff && backoff.until > this.clock()) {
|
|
37
|
+
progress?.(lastId);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const abort = () => controller.abort(signal.reason);
|
|
42
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
43
|
+
const timeout = setTimeout(() => controller.abort(/* @__PURE__ */ new Error("Mail item timed out")), this.itemTimeoutMs);
|
|
44
|
+
let rejectAbort = () => {};
|
|
45
|
+
const aborted = new Promise((_, reject) => {
|
|
46
|
+
rejectAbort = () => reject(controller.signal.reason);
|
|
47
|
+
controller.signal.addEventListener("abort", rejectAbort, { once: true });
|
|
48
|
+
});
|
|
49
|
+
let activation;
|
|
50
|
+
try {
|
|
51
|
+
activation = this.repository.getActivation(principal, item.activationId);
|
|
52
|
+
const template = this.repository.getTemplate(activation.templateKey, activation.templateVersion);
|
|
53
|
+
if (!template.contextProviders.includes("mail") || !template.triggers.some((trigger) => trigger.type === "event" && trigger.eventType === "mail.thread.changed") || activation.scope.kind !== "objects" || !activation.scope.ids.includes(item.subjectId)) throw new Error("Mail observation is outside the template or delegated scope");
|
|
54
|
+
const permissions = intersectPermissions(activation.permissions, await Promise.race([this.authorize(activation), aborted]), {
|
|
55
|
+
accountIds: [item.accountId],
|
|
56
|
+
contextProviders: ["mail"],
|
|
57
|
+
effectHandlers: []
|
|
58
|
+
});
|
|
59
|
+
signal.throwIfAborted();
|
|
60
|
+
if (!this.repository.isMailObservationCurrent(activation, item, this.clock())) throw new Error("Mail delegation changed during authorization");
|
|
61
|
+
if (!permissions.accountIds.includes(item.accountId) || !permissions.contextProviders.includes("mail")) throw new Error("Mail observation permission is required");
|
|
62
|
+
const evidence = await Promise.race([this.provider.read({
|
|
63
|
+
activation,
|
|
64
|
+
permissions,
|
|
65
|
+
subjectId: item.subjectId,
|
|
66
|
+
signal: controller.signal
|
|
67
|
+
}), aborted]);
|
|
68
|
+
signal.throwIfAborted();
|
|
69
|
+
if (!evidence.length || evidence.length > 100 || new Set(evidence.map((entry) => entry.id)).size !== evidence.length || evidence.reduce((size, entry) => size + entry.content.length, 0) > 12e4 || evidence.some((entry) => !entry.id || !entry.revision || entry.ownerId !== principal.ownerId || entry.workspaceId !== principal.workspaceId || entry.accountId !== item.accountId || entry.subjectId !== item.subjectId || !Number.isFinite(entry.freshUntil) || entry.freshUntil <= this.clock())) throw new Error("Mail observation is incomplete or unauthorized");
|
|
70
|
+
const currentPermissions = intersectPermissions(permissions, await Promise.race([this.authorize(activation), aborted]));
|
|
71
|
+
signal.throwIfAborted();
|
|
72
|
+
if (!this.repository.isMailObservationCurrent(activation, item, this.clock())) throw new Error("Mail delegation changed during observation");
|
|
73
|
+
if (sceneContentHash(currentPermissions) !== sceneContentHash(permissions)) throw new Error("Mail observation permission changed");
|
|
74
|
+
this.repository.recordSourceHealth(activation, null, this.clock());
|
|
75
|
+
this.failures.delete(item.accountId);
|
|
76
|
+
const fingerprint = sceneContentHash(evidence.map(({ freshUntil: _freshUntil, ...entry }) => entry).sort((a, b) => a.id.localeCompare(b.id)));
|
|
77
|
+
if (this.repository.observeMailWorkItem(principal, item, fingerprint, this.clock())) changed += 1;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
signal.throwIfAborted();
|
|
80
|
+
unavailable += 1;
|
|
81
|
+
const retryDelay = Math.max(this.intervalMs, Math.min(3e5, 1e4 * 2 ** Math.min((backoff?.count ?? 0) + 1, 5)));
|
|
82
|
+
if (activation && this.repository.isMailObservationCurrent(activation, item, this.clock())) this.repository.recordSourceHealth(activation, sceneSourceFailureReason(error), this.clock(), this.clock() + Math.max(retryDelay, 6e4));
|
|
83
|
+
if (this.intervalMs > 0) {
|
|
84
|
+
const count = Math.min((backoff?.count ?? 0) + 1, 5);
|
|
85
|
+
this.failures.set(item.accountId, {
|
|
86
|
+
count,
|
|
87
|
+
until: this.clock() + Math.min(3e5, 1e4 * 2 ** count)
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
} finally {
|
|
91
|
+
clearTimeout(timeout);
|
|
92
|
+
signal.removeEventListener("abort", abort);
|
|
93
|
+
controller.signal.removeEventListener("abort", rejectAbort);
|
|
94
|
+
if (!signal.aborted) progress?.(lastId);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const nextCursor = processed < items.length || items.length === 100 ? lastId : null;
|
|
98
|
+
if (nextCursor === null) this.nextScanAt = this.clock() + this.intervalMs;
|
|
99
|
+
return {
|
|
100
|
+
changed,
|
|
101
|
+
unavailable,
|
|
102
|
+
nextCursor
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
export { SceneMailObservationService };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { init_transaction, runSqliteSavepoint } from "../storage/sqlite/transaction.js";
|
|
2
|
+
//#region src/scenes/maintenance.ts
|
|
3
|
+
init_transaction();
|
|
4
|
+
/** Keeps identity/deduplication rows; removes bounded old payloads only after their work is terminal. */
|
|
5
|
+
function maintainSceneStorage(db, now = Date.now()) {
|
|
6
|
+
const cutoff = now - 90 * 864e5;
|
|
7
|
+
runSqliteSavepoint(db, () => {
|
|
8
|
+
db.prepare("DELETE FROM scene_connector_usage WHERE utc_day < ?").run(Math.floor(cutoff / 864e5));
|
|
9
|
+
db.prepare("DELETE FROM notification_presence WHERE expires_at <= ?").run(now);
|
|
10
|
+
db.prepare("DELETE FROM notification_browser_subscriptions WHERE expires_at <= ?").run(now);
|
|
11
|
+
db.prepare(`DELETE FROM scene_mail_sources WHERE id IN (SELECT s.id FROM scene_mail_sources s
|
|
12
|
+
WHERE s.selected_at < ? AND NOT EXISTS (SELECT 1 FROM scene_activations a, json_each(a.scope_json, '$.ids') ids WHERE ids.value = s.id)
|
|
13
|
+
ORDER BY selected_at LIMIT 100)`).run(now - 30 * 864e5);
|
|
14
|
+
for (const table of [
|
|
15
|
+
"scene_context_snapshots",
|
|
16
|
+
"scene_model_reservations",
|
|
17
|
+
"scene_model_usage"
|
|
18
|
+
]) db.prepare(`DELETE FROM ${table} WHERE run_id IN (SELECT DISTINCT r.id FROM scene_runs r JOIN ${table} t ON t.run_id = r.id
|
|
19
|
+
WHERE r.status NOT IN ('running', 'retry_wait') AND r.created_at < ? ORDER BY r.created_at LIMIT 100)`).run(cutoff);
|
|
20
|
+
db.prepare("DELETE FROM notification_attention_budget WHERE dedupe_key IN (SELECT dedupe_key FROM notification_attention_budget WHERE created_at < ? LIMIT 100)").run(cutoff);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { maintainSceneStorage };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { ScenePrincipal } from './contracts.js';
|
|
3
|
+
/** Explicit feedback is a usefulness signal, not proof of adoption or saved time. */
|
|
4
|
+
export declare class SceneMetrics {
|
|
5
|
+
private readonly db;
|
|
6
|
+
private readonly clock;
|
|
7
|
+
constructor(db: DatabaseSync, clock?: () => number);
|
|
8
|
+
diagnostics(principal: ScenePrincipal): {
|
|
9
|
+
checksPaused: boolean;
|
|
10
|
+
pendingChecks: number;
|
|
11
|
+
oldestDueWaitMs: number;
|
|
12
|
+
lastSevenDays: {
|
|
13
|
+
modelCalls: number;
|
|
14
|
+
connectorReads: number;
|
|
15
|
+
tokens: number;
|
|
16
|
+
estimatedCost: number;
|
|
17
|
+
};
|
|
18
|
+
notifications: Record<string, import("node:sqlite").SQLOutputValue>[];
|
|
19
|
+
activations: Record<string, import("node:sqlite").SQLOutputValue>[];
|
|
20
|
+
};
|
|
21
|
+
forUser(principal: ScenePrincipal, days?: number): {
|
|
22
|
+
window: {
|
|
23
|
+
since: number;
|
|
24
|
+
until: number;
|
|
25
|
+
days: number;
|
|
26
|
+
};
|
|
27
|
+
ratedOutcomes: number;
|
|
28
|
+
usefulOutcomes: number;
|
|
29
|
+
unhelpfulOutcomes: number;
|
|
30
|
+
scenesWithUsefulOutcomes: number;
|
|
31
|
+
checks: number;
|
|
32
|
+
failedChecks: number;
|
|
33
|
+
skippedChecks: number;
|
|
34
|
+
};
|
|
35
|
+
}
|