@xopcai/xopc 0.0.125 → 0.0.126
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/README.md +56 -102
- package/README.zh-CN.md +51 -98
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/schema/config-schema.d.ts +6 -6
- package/dist/extensions/feishu/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
- package/dist/extensions/telegram/src/config-schema.d.ts +8 -8
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +1 -1
- package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/workflow-progress.js +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BKDKICZV.js → agent-avatar-dicebear-C70vgt60.js} +1 -1
- package/dist/gateway/static/root/assets/agents-DRYVahI-.js +2 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-DI4BqHKW.js → app-management-settings-panel-D9-HW6cy.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-6_ie3NQ4.js → appearance-settings-BHlahIDL.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BdJ1eQg3.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-kUHEJ1HK.js → archive-plugin-B-aoIt0w.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Dm-9prpU.js → attachment-load-BD0G0FD5.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-OTxQTPnC.js → automation-suggestion-card-iJRVI7aZ.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-D8hYQbkl.js +4 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DllA_jQ0.js → binary-plugins-B0mNlVSz.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-Cm6CWNj1.js → block-editor-CJY9Lu5G.js} +6 -6
- package/dist/gateway/static/root/assets/browser-settings-page-CiWEO-Iy.js +8 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-VJ89b6I2.js → capability-presets-api-Bgc8ag55.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-BaPj8wC2.js → capability-presets-settings-panel-B1nIi0TC.js} +1 -1
- package/dist/gateway/static/root/assets/{channel-recipient-api-B5PwBEUx.js → channel-recipient-api-0sauApoC.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-BddPdqVo.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-Ba2GDhSE.js +2 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-DySMzOF6.js → directory-picker-path-field-CiEc4KmY.js} +1 -1
- package/dist/gateway/static/root/assets/{dreaming-settings-D_AjSnV_.js → dreaming-settings-4bvpk5wr.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-BaM0FpW7.js → extension-debug-page-BbyczVZ3.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DuZWVOGA.js → extension-page-DLN1I3DR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DarVtbmJ.js → extension-settings-page-D9VGHmYJ.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-NFKfkqrd.js → fetch-5V96dUz3.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CFEm9rgy.js → gateway-config-api-BtIzObwp.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-BMk2S5td.js → gateway-settings-KFsGGDhg.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Dtwh_yGg.js → gateway-startup-retry-DEMad2wt.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-create-dialog-BKP7ylcG.js → goal-create-dialog-4PcF6Sh6.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-B482PSaG.js +1 -0
- package/dist/gateway/static/root/assets/{goals-config-api-DTWZNA_Y.js → goals-config-api-CVN7-pdM.js} +1 -1
- package/dist/gateway/static/root/assets/{goals-page-CTmA3hWK.js → goals-page-CUdgJuDn.js} +2 -2
- package/dist/gateway/static/root/assets/{goals-settings-Bhct0ZT-.js → goals-settings-IYCH3-Pi.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-C-UxSU4a.js → heartbeat-settings-Cf_a2Bmz.js} +1 -1
- package/dist/gateway/static/root/assets/index-CA2tR2vm.js +256 -0
- package/dist/gateway/static/root/assets/index-Ds3u0LOk.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DCjy2y4d.js → keyboard-shortcuts-settings-lKTg6St7.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-BCporcNH.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-split-BaqxP-GQ.js → markdown-split-Bv4k6iGJ.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DQ_EXloK.js → media-plugins-Bbi8g3N8.js} +1 -1
- package/dist/gateway/static/root/assets/messages-C22hxE1N.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-D68Pyow7.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-CuUMOiyv.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-Dx2N5zTk.js +2 -0
- package/dist/gateway/static/root/assets/{page-tabs-EIZhLppK.js → page-tabs-Cp395RYD.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-r_uB4Epr.js → preview-open-alternatives-DqV5OM4m.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-sB8AzZi3.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-LBnJqWK2.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-Dbj0o6SC.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-B132Uf-2.js → save-bar-controls-BItmzAzI.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-B5qshALm.js → schedule-field-BQ8IjjCn.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CvLmkdS9.js → schema-form-BRpD6x3d.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DhDZKspB.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BvXLMNL6.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-pRlvqsAf.js → settings-collapsible-section-BKSPQM4R.js} +1 -1
- package/dist/gateway/static/root/assets/settings-form-section-BmyfthNQ.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-Cfm9UxAr.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-layout-Bls5tfbH.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-kQEsTGAs.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-v6-IOp8t.js → share-preview-page-DbYZNAPb.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-BtR4B0kn.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CJNVOWoK.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DcWDHrt3.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-HUU2FFjM.js → system-settings-panel-DKDAojWM.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-AH160QHh.js → typed-models-lib-BCCV4Kkp.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BXzDmjCQ.js → use-channel-catalog-NBqg3iFY.js} +1 -1
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-DxwnQvQ3.js → user-profile-settings-panel-suQ2x-LB.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-i5POEtqd.js → utils-DPGVr3tS.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-DaJASKFP.js +1 -0
- package/dist/gateway/static/root/assets/{work-item-detail-page-CD6FL_Rs.js → work-item-detail-page-BrCZpAWh.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-ClVVMgN-.js → workflow-run-setup-panel-BTkRVNAh.js} +2 -2
- package/dist/gateway/static/root/assets/{workflow-start-dialog-Dv4ZA1T0.js → workflow-start-dialog-DAImVtdO.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-vyJ8wSXm.js +18 -0
- package/dist/gateway/static/root/index.html +5 -5
- package/dist/package.js +1 -1
- package/dist/src/activity/context.d.ts +11 -0
- package/dist/src/activity/context.js +36 -0
- package/dist/src/activity/context.js.map +1 -0
- package/dist/src/activity/emitter.d.ts +6 -0
- package/dist/src/activity/emitter.js +43 -0
- package/dist/src/activity/emitter.js.map +1 -0
- package/dist/src/activity/index.d.ts +3 -0
- package/dist/src/activity/index.js +3 -0
- package/dist/src/activity/service.d.ts +12 -0
- package/dist/src/activity/service.js +59 -0
- package/dist/src/activity/service.js.map +1 -0
- package/dist/src/activity/types.d.ts +109 -0
- package/dist/src/activity/types.js +1 -0
- package/dist/src/agent/agent-manager.d.ts +7 -0
- package/dist/src/agent/agent-manager.js +7 -4
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/context/project-context.js +2 -2
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/embedded/run-for-session.js +1 -1
- package/dist/src/agent/goals/post-turn.js +2 -2
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
- package/dist/src/agent/service.js +6 -3
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +7 -0
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +1 -1
- package/dist/src/agent/tool-manuals/index.js +15 -6
- package/dist/src/agent/tool-manuals/index.js.map +1 -1
- package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -0
- package/dist/src/agent/tool-manuals/xopc-use.js +204 -0
- package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -0
- package/dist/src/agent/tools/factory.d.ts +7 -0
- package/dist/src/agent/tools/factory.js +9 -0
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/goal-tool.js +2 -2
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/workflow-tool.js +1 -1
- package/dist/src/agent/tools/xopc-use-tool.d.ts +34 -0
- package/dist/src/agent/tools/xopc-use-tool.js +636 -0
- package/dist/src/agent/tools/xopc-use-tool.js.map +1 -0
- package/dist/src/agent-manifest/schema.d.ts +27 -27
- package/dist/src/automations/api/routes.js +1 -1
- package/dist/src/automations/domain/validation.d.ts +55 -55
- package/dist/src/automations/draft/automation-draft-validator.d.ts +25 -25
- package/dist/src/automations/service/action-executor.js +2 -2
- package/dist/src/browser/cdp-local-launcher.js +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +3 -3
- package/dist/src/browser/providers/cloakbrowser.js +2 -2
- package/dist/src/browser/providers/playwright-doctor.js +1 -1
- package/dist/src/browser/stealth.js +1 -1
- package/dist/src/chat-commands/agent-edit.js +1 -1
- package/dist/src/chat-commands/builtins/config.js +1 -1
- package/dist/src/chat-commands/builtins/goal.js +2 -2
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +2 -2
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/goal.js +3 -3
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/project.js +4 -4
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +1 -1
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.d.ts +14 -14
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.d.ts +60 -60
- package/dist/src/daemon/launchd.js +1 -1
- package/dist/src/daemon/systemd.js +1 -1
- package/dist/src/extensions/discover-extensions.js +1 -1
- package/dist/src/extensions/loader.js +2 -2
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +14 -14
- package/dist/src/gateway/hono/lib/static-ui.js +1 -1
- package/dist/src/gateway/hono/middleware/log-context.js +8 -1
- package/dist/src/gateway/hono/middleware/log-context.js.map +1 -1
- package/dist/src/gateway/hono/routes/activity.d.ts +14 -0
- package/dist/src/gateway/hono/routes/activity.js +72 -0
- package/dist/src/gateway/hono/routes/activity.js.map +1 -0
- package/dist/src/gateway/hono/routes/goals.js +1 -1
- package/dist/src/gateway/hono/routes/index.js +2 -0
- package/dist/src/gateway/hono/routes/index.js.map +1 -1
- package/dist/src/gateway/hono/routes/memory.js +2 -2
- package/dist/src/gateway/hono/routes/projects.js +65 -15
- package/dist/src/gateway/hono/routes/projects.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +101 -2
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +2 -2
- package/dist/src/gateway/lock.js +1 -1
- package/dist/src/gateway/ports.js +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +10 -0
- package/dist/src/gateway/service/sessions-api.js +31 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.js +12 -9
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/goals/goal-store.js +1 -1
- package/dist/src/goals/goal-store.js.map +1 -1
- package/dist/src/goals/goal-workflow-judge.js +1 -1
- package/dist/src/infra/ports.js +1 -1
- package/dist/src/infra/ssh-tunnel.js +1 -1
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/migrations/runner.js +1 -1
- package/dist/src/notes/service.js +65 -6
- package/dist/src/notes/service.js.map +1 -1
- package/dist/src/notes/store.js +1 -1
- package/dist/src/projects/project-service.d.ts +2 -1
- package/dist/src/projects/project-service.js +59 -2
- package/dist/src/projects/project-service.js.map +1 -1
- package/dist/src/projects/project-store.d.ts +2 -1
- package/dist/src/projects/project-store.js +43 -0
- package/dist/src/projects/project-store.js.map +1 -1
- package/dist/src/projects/types.d.ts +10 -0
- package/dist/src/projects/workspace.js +1 -1
- package/dist/src/routing/agent-session-key.js +1 -1
- package/dist/src/routing/resolve-route.js +1 -1
- package/dist/src/routing/resolve-tui-session-key.js +1 -1
- package/dist/src/session/client-history.d.ts +3 -0
- package/dist/src/session/client-history.js +24 -9
- package/dist/src/session/client-history.js.map +1 -1
- package/dist/src/session/init-session-turn.js +1 -1
- package/dist/src/session/resolve-session.js +1 -1
- package/dist/src/session/session-title.js +2 -2
- package/dist/src/session/store.js +1 -1
- package/dist/src/session/types.d.ts +4 -0
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/storage/sqlite/activity-repository.d.ts +8 -0
- package/dist/src/storage/sqlite/activity-repository.js +208 -0
- package/dist/src/storage/sqlite/activity-repository.js.map +1 -0
- package/dist/src/storage/sqlite/connection.js +1 -1
- package/dist/src/storage/sqlite/index.d.ts +1 -0
- package/dist/src/storage/sqlite/index.js +2 -1
- package/dist/src/storage/sqlite/migrations/024_activity_events.sql +62 -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.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/row-mappers.js +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +63 -0
- package/dist/src/storage/sqlite/session-repository.js +11 -0
- package/dist/src/storage/sqlite/session-repository.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +13 -0
- package/dist/src/tui/backends/embedded-backend.js +76 -7
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +13 -0
- package/dist/src/tui/backends/gateway-sse-backend.js +53 -0
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/chat-history.js +16 -3
- package/dist/src/tui/chat-history.js.map +1 -1
- package/dist/src/tui/clipboard-image.js +1 -1
- package/dist/src/tui/components/chat-log.d.ts +23 -3
- package/dist/src/tui/components/chat-log.js +68 -9
- package/dist/src/tui/components/chat-log.js.map +1 -1
- package/dist/src/tui/components/tui-bottom-bar.js +9 -5
- package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +16 -0
- package/dist/src/tui/tui-command-formatters.js +2 -2
- package/dist/src/tui/tui-commands.d.ts +9 -0
- package/dist/src/tui/tui-commands.js +95 -6
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-picker-overlay.d.ts +1 -0
- package/dist/src/tui/tui-picker-overlay.js +36 -1
- package/dist/src/tui/tui-picker-overlay.js.map +1 -1
- package/dist/src/tui/tui-picker-services.d.ts +13 -0
- package/dist/src/tui/tui-run-state.js +11 -0
- package/dist/src/tui/tui-run-state.js.map +1 -1
- package/dist/src/tui/tui-run-status-format.d.ts +3 -0
- package/dist/src/tui/tui-run-status-format.js +33 -0
- package/dist/src/tui/tui-run-status-format.js.map +1 -0
- package/dist/src/tui/tui-session-actions.d.ts +5 -0
- package/dist/src/tui/tui-session-actions.js +24 -0
- package/dist/src/tui/tui-session-actions.js.map +1 -1
- package/dist/src/tui/tui-timeline-picker.d.ts +19 -0
- package/dist/src/tui/tui-timeline-picker.js +81 -0
- package/dist/src/tui/tui-timeline-picker.js.map +1 -0
- package/dist/src/tui/tui-timeline.d.ts +15 -0
- package/dist/src/tui/tui-timeline.js +65 -0
- package/dist/src/tui/tui-timeline.js.map +1 -0
- package/dist/src/tui/tui-types.d.ts +1 -0
- package/dist/src/tui/tui-types.js +1 -0
- package/dist/src/tui/tui-types.js.map +1 -1
- package/dist/src/tui/tui.js +31 -25
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/utils/index.js +1 -1
- package/dist/src/utils/logger/index.js +1 -1
- package/dist/src/utils/logger/stats.d.ts +3 -3
- package/dist/src/utils/logger.js +1 -1
- package/dist/src/work-items/agent-context.d.ts +5 -1
- package/dist/src/work-items/agent-context.js +39 -3
- package/dist/src/work-items/agent-context.js.map +1 -1
- package/dist/src/work-items/work-item-service.d.ts +2 -0
- package/dist/src/work-items/work-item-service.js +97 -0
- package/dist/src/work-items/work-item-service.js.map +1 -1
- package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +1 -1
- package/package.json +5 -5
- package/dist/gateway/static/root/assets/agents-BnTB7-c5.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-B6bG65SW.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-1lVbo0dS.js +0 -1
- package/dist/gateway/static/root/assets/browser-settings-page-CzDBlOK0.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-Df4m7p1k.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-BMTphmHS.js +0 -2
- package/dist/gateway/static/root/assets/goal-detail-page-C2cTxf71.js +0 -1
- package/dist/gateway/static/root/assets/index-BNHDd2j1.css +0 -1
- package/dist/gateway/static/root/assets/index-BPXLPMuY.js +0 -193
- package/dist/gateway/static/root/assets/logs-page-CGc3_CQU.js +0 -2
- package/dist/gateway/static/root/assets/messages-CjuIJcZl.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-Drz4UQMb.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-CY1ylng1.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-X7IaD--t.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-DE5adRBE.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CuOb1k6F.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BOxNrUVA.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CY0IQcGW.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-D4NBNVCB.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-BBYUDLVd.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DaO7zYZM.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-layout-D8g9PAek.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Bks0CLLT.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-CEZsKm9r.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-oTkHbb9W.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-DigsbZ6K.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-CEJklEgb.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-OLQiUpoW.js +0 -18
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
//#region src/storage/sqlite/activity-repository.ts
|
|
4
|
+
function parseJson(json, fallback) {
|
|
5
|
+
try {
|
|
6
|
+
return JSON.parse(json);
|
|
7
|
+
} catch {
|
|
8
|
+
return fallback;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function eventFromRow(row) {
|
|
12
|
+
return {
|
|
13
|
+
id: row.id,
|
|
14
|
+
type: row.type,
|
|
15
|
+
primaryObject: {
|
|
16
|
+
kind: row.primary_object_kind,
|
|
17
|
+
id: row.primary_object_id,
|
|
18
|
+
title: row.primary_object_title ?? void 0
|
|
19
|
+
},
|
|
20
|
+
actor: parseJson(row.actor_json, { kind: "system" }),
|
|
21
|
+
initiator: row.initiator_json ? parseJson(row.initiator_json, void 0) : void 0,
|
|
22
|
+
source: parseJson(row.source_json, { kind: "system" }),
|
|
23
|
+
payload: parseJson(row.payload_json, {}),
|
|
24
|
+
visibility: row.visibility,
|
|
25
|
+
importance: row.importance,
|
|
26
|
+
createdAt: row.created_at
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function scopeFromRow(row) {
|
|
30
|
+
return {
|
|
31
|
+
activityId: row.activity_id,
|
|
32
|
+
scopeKind: row.scope_kind,
|
|
33
|
+
scopeId: row.scope_id,
|
|
34
|
+
reason: row.reason
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function relatedProjectFromRow(row) {
|
|
38
|
+
return {
|
|
39
|
+
activityId: row.activity_id,
|
|
40
|
+
projectId: row.project_id,
|
|
41
|
+
reason: row.reason,
|
|
42
|
+
confidence: row.confidence,
|
|
43
|
+
computedAt: row.computed_at
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function objectLinkFromRow(row) {
|
|
47
|
+
return {
|
|
48
|
+
id: row.id,
|
|
49
|
+
from: {
|
|
50
|
+
kind: row.from_kind,
|
|
51
|
+
id: row.from_id,
|
|
52
|
+
title: row.from_title ?? void 0
|
|
53
|
+
},
|
|
54
|
+
to: {
|
|
55
|
+
kind: row.to_kind,
|
|
56
|
+
id: row.to_id,
|
|
57
|
+
title: row.to_title ?? void 0
|
|
58
|
+
},
|
|
59
|
+
relation: row.relation,
|
|
60
|
+
source: row.source,
|
|
61
|
+
createdAt: row.created_at
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function listScopesForActivity(activityId) {
|
|
65
|
+
return getSqliteDatabase().prepare(`SELECT activity_id, scope_kind, scope_id, reason
|
|
66
|
+
FROM activity_scopes
|
|
67
|
+
WHERE activity_id = ?
|
|
68
|
+
ORDER BY scope_kind ASC, scope_id ASC, reason ASC`).all(activityId).map((row) => scopeFromRow(row));
|
|
69
|
+
}
|
|
70
|
+
function listRelatedProjectsForActivity(activityId) {
|
|
71
|
+
return getSqliteDatabase().prepare(`SELECT activity_id, project_id, reason, confidence, computed_at
|
|
72
|
+
FROM activity_related_projects
|
|
73
|
+
WHERE activity_id = ?
|
|
74
|
+
ORDER BY project_id ASC, reason ASC`).all(activityId).map((row) => relatedProjectFromRow(row));
|
|
75
|
+
}
|
|
76
|
+
function eventWithRelations(row) {
|
|
77
|
+
const event = eventFromRow(row);
|
|
78
|
+
return {
|
|
79
|
+
...event,
|
|
80
|
+
scopes: listScopesForActivity(event.id),
|
|
81
|
+
relatedProjects: listRelatedProjectsForActivity(event.id)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function normalizeLimit(limit) {
|
|
85
|
+
return Math.max(1, Math.min(100, Math.floor(limit ?? 50)));
|
|
86
|
+
}
|
|
87
|
+
function normalizeOffset(offset) {
|
|
88
|
+
return Math.max(0, Math.floor(offset ?? 0));
|
|
89
|
+
}
|
|
90
|
+
function visibilityClause(visibility, params) {
|
|
91
|
+
if (!visibility) return "";
|
|
92
|
+
params.push(visibility);
|
|
93
|
+
return "WHERE visibility = ?";
|
|
94
|
+
}
|
|
95
|
+
function listResult(rows, total, limit, offset) {
|
|
96
|
+
return {
|
|
97
|
+
items: rows.map(eventWithRelations),
|
|
98
|
+
total,
|
|
99
|
+
limit,
|
|
100
|
+
offset,
|
|
101
|
+
hasMore: offset + rows.length < total
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function recordActivityEvent(input) {
|
|
105
|
+
const id = input.id ?? randomUUID();
|
|
106
|
+
const now = input.nowMs ?? Date.now();
|
|
107
|
+
const visibility = input.visibility ?? "timeline";
|
|
108
|
+
const importance = input.importance ?? "normal";
|
|
109
|
+
const payload = input.payload ?? {};
|
|
110
|
+
runSqliteWriteTransaction((db) => {
|
|
111
|
+
db.prepare(`INSERT INTO activity_events (
|
|
112
|
+
id, type, primary_object_kind, primary_object_id, primary_object_title,
|
|
113
|
+
actor_json, initiator_json, source_json, payload_json,
|
|
114
|
+
visibility, importance, created_at
|
|
115
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.type, input.primaryObject.kind, input.primaryObject.id, input.primaryObject.title ?? null, JSON.stringify(input.actor), input.initiator ? JSON.stringify(input.initiator) : null, JSON.stringify(input.source), JSON.stringify(payload), visibility, importance, now);
|
|
116
|
+
for (const scope of input.scopes ?? []) db.prepare(`INSERT OR IGNORE INTO activity_scopes (activity_id, scope_kind, scope_id, reason)
|
|
117
|
+
VALUES (?, ?, ?, ?)`).run(id, scope.scopeKind, scope.scopeId, scope.reason);
|
|
118
|
+
for (const related of input.relatedProjects ?? []) db.prepare(`INSERT OR REPLACE INTO activity_related_projects (
|
|
119
|
+
activity_id, project_id, reason, confidence, computed_at
|
|
120
|
+
) VALUES (?, ?, ?, ?, ?)`).run(id, related.projectId, related.reason, related.confidence, related.computedAt ?? now);
|
|
121
|
+
});
|
|
122
|
+
const event = getActivityEventRecord(id);
|
|
123
|
+
if (!event) throw new Error(`Activity event was not persisted: ${id}`);
|
|
124
|
+
return event;
|
|
125
|
+
}
|
|
126
|
+
function getActivityEventRecord(id) {
|
|
127
|
+
const row = getSqliteDatabase().prepare(`SELECT *
|
|
128
|
+
FROM activity_events
|
|
129
|
+
WHERE id = ?`).get(id);
|
|
130
|
+
return row ? eventWithRelations(row) : null;
|
|
131
|
+
}
|
|
132
|
+
function listActivityRecords(options = {}) {
|
|
133
|
+
const limit = normalizeLimit(options.limit);
|
|
134
|
+
const offset = normalizeOffset(options.offset);
|
|
135
|
+
const params = [];
|
|
136
|
+
const where = visibilityClause(options.visibility, params);
|
|
137
|
+
const total = getSqliteDatabase().prepare(`SELECT COUNT(*) AS count FROM activity_events ${where}`).get(...params).count;
|
|
138
|
+
return listResult(getSqliteDatabase().prepare(`SELECT *
|
|
139
|
+
FROM activity_events
|
|
140
|
+
${where}
|
|
141
|
+
ORDER BY created_at DESC, id DESC
|
|
142
|
+
LIMIT ? OFFSET ?`).all(...params, limit, offset).map((row) => row), total, limit, offset);
|
|
143
|
+
}
|
|
144
|
+
function listObjectActivityRecords(options) {
|
|
145
|
+
const limit = normalizeLimit(options.limit);
|
|
146
|
+
const offset = normalizeOffset(options.offset);
|
|
147
|
+
const params = [options.object.kind, options.object.id];
|
|
148
|
+
const visibility = options.visibility ? "AND visibility = ?" : "";
|
|
149
|
+
if (options.visibility) params.push(options.visibility);
|
|
150
|
+
const total = getSqliteDatabase().prepare(`SELECT COUNT(*) AS count
|
|
151
|
+
FROM activity_events
|
|
152
|
+
WHERE primary_object_kind = ? AND primary_object_id = ?
|
|
153
|
+
${visibility}`).get(...params).count;
|
|
154
|
+
return listResult(getSqliteDatabase().prepare(`SELECT *
|
|
155
|
+
FROM activity_events
|
|
156
|
+
WHERE primary_object_kind = ? AND primary_object_id = ?
|
|
157
|
+
${visibility}
|
|
158
|
+
ORDER BY created_at DESC, id DESC
|
|
159
|
+
LIMIT ? OFFSET ?`).all(...params, limit, offset).map((row) => row), total, limit, offset);
|
|
160
|
+
}
|
|
161
|
+
function listProjectActivityRecords(options) {
|
|
162
|
+
const limit = normalizeLimit(options.limit);
|
|
163
|
+
const offset = normalizeOffset(options.offset);
|
|
164
|
+
const params = ["project", options.projectId];
|
|
165
|
+
const relatedClause = options.includeRelated ? `OR EXISTS (
|
|
166
|
+
SELECT 1 FROM activity_related_projects ar
|
|
167
|
+
WHERE ar.activity_id = ae.id AND ar.project_id = ?
|
|
168
|
+
)` : "";
|
|
169
|
+
if (options.includeRelated) params.push(options.projectId);
|
|
170
|
+
const visibilityClauseSql = options.visibility ? "AND ae.visibility = ?" : "";
|
|
171
|
+
if (options.visibility) params.push(options.visibility);
|
|
172
|
+
const baseWhere = `EXISTS (
|
|
173
|
+
SELECT 1 FROM activity_scopes s
|
|
174
|
+
WHERE s.activity_id = ae.id AND s.scope_kind = ? AND s.scope_id = ?
|
|
175
|
+
) ${relatedClause}`;
|
|
176
|
+
const total = getSqliteDatabase().prepare(`SELECT COUNT(*) AS count
|
|
177
|
+
FROM activity_events ae
|
|
178
|
+
WHERE (${baseWhere})
|
|
179
|
+
${visibilityClauseSql}`).get(...params).count;
|
|
180
|
+
return listResult(getSqliteDatabase().prepare(`SELECT ae.*
|
|
181
|
+
FROM activity_events ae
|
|
182
|
+
WHERE (${baseWhere})
|
|
183
|
+
${visibilityClauseSql}
|
|
184
|
+
ORDER BY ae.created_at DESC, ae.id DESC
|
|
185
|
+
LIMIT ? OFFSET ?`).all(...params, limit, offset).map((row) => row), total, limit, offset);
|
|
186
|
+
}
|
|
187
|
+
function createObjectLinkRecord(input) {
|
|
188
|
+
const id = input.id ?? randomUUID();
|
|
189
|
+
const now = input.nowMs ?? Date.now();
|
|
190
|
+
runSqliteWriteTransaction((db) => {
|
|
191
|
+
db.prepare(`INSERT INTO object_links (
|
|
192
|
+
id, from_kind, from_id, from_title, to_kind, to_id, to_title, relation, source, created_at
|
|
193
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.from.kind, input.from.id, input.from.title ?? null, input.to.kind, input.to.id, input.to.title ?? null, input.relation, input.source, now);
|
|
194
|
+
});
|
|
195
|
+
const row = getSqliteDatabase().prepare(`SELECT * FROM object_links WHERE id = ?`).get(id);
|
|
196
|
+
if (!row) throw new Error(`Object link was not persisted: ${id}`);
|
|
197
|
+
return objectLinkFromRow(row);
|
|
198
|
+
}
|
|
199
|
+
function listObjectLinkRecords(object) {
|
|
200
|
+
return getSqliteDatabase().prepare(`SELECT *
|
|
201
|
+
FROM object_links
|
|
202
|
+
WHERE (from_kind = ? AND from_id = ?) OR (to_kind = ? AND to_id = ?)
|
|
203
|
+
ORDER BY created_at DESC, id DESC`).all(object.kind, object.id, object.kind, object.id).map((row) => objectLinkFromRow(row));
|
|
204
|
+
}
|
|
205
|
+
//#endregion
|
|
206
|
+
export { createObjectLinkRecord, getActivityEventRecord, listActivityRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, recordActivityEvent };
|
|
207
|
+
|
|
208
|
+
//# sourceMappingURL=activity-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-repository.js","names":[],"sources":["../../../../src/storage/sqlite/activity-repository.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type {\n ActivityEvent,\n ActivityEventWithRelations,\n ActivityListResult,\n ActivityObjectRef,\n ActivityRelatedProject,\n ActivityScope,\n ActivitySource,\n ActivityPrincipal,\n CreateObjectLinkInput,\n ListActivityOptions,\n ListObjectActivityOptions,\n ListProjectActivityOptions,\n ObjectLink,\n RecordActivityInput,\n} from '../../activity/types.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\ntype ActivityEventRow = {\n id: string;\n type: string;\n primary_object_kind: string;\n primary_object_id: string;\n primary_object_title: string | null;\n actor_json: string;\n initiator_json: string | null;\n source_json: string;\n payload_json: string;\n visibility: string;\n importance: string;\n created_at: number;\n};\n\ntype ActivityScopeRow = {\n activity_id: string;\n scope_kind: string;\n scope_id: string;\n reason: string;\n};\n\ntype ActivityRelatedProjectRow = {\n activity_id: string;\n project_id: string;\n reason: string;\n confidence: number;\n computed_at: number;\n};\n\ntype ObjectLinkRow = {\n id: string;\n from_kind: string;\n from_id: string;\n from_title: string | null;\n to_kind: string;\n to_id: string;\n to_title: string | null;\n relation: string;\n source: string;\n created_at: number;\n};\n\ntype CountRow = { count: number };\ntype SqlParam = string | number | bigint | null;\n\nfunction parseJson<T>(json: string, fallback: T): T {\n try {\n return JSON.parse(json) as T;\n } catch {\n return fallback;\n }\n}\n\nfunction eventFromRow(row: ActivityEventRow): ActivityEvent {\n return {\n id: row.id,\n type: row.type,\n primaryObject: {\n kind: row.primary_object_kind as ActivityObjectRef['kind'],\n id: row.primary_object_id,\n title: row.primary_object_title ?? undefined,\n },\n actor: parseJson<ActivityPrincipal>(row.actor_json, { kind: 'system' }),\n initiator: row.initiator_json ? parseJson<ActivityPrincipal | undefined>(row.initiator_json, undefined) : undefined,\n source: parseJson<ActivitySource>(row.source_json, { kind: 'system' }),\n payload: parseJson<Record<string, unknown>>(row.payload_json, {}),\n visibility: row.visibility as ActivityEvent['visibility'],\n importance: row.importance as ActivityEvent['importance'],\n createdAt: row.created_at,\n };\n}\n\nfunction scopeFromRow(row: ActivityScopeRow): ActivityScope {\n return {\n activityId: row.activity_id,\n scopeKind: row.scope_kind as ActivityScope['scopeKind'],\n scopeId: row.scope_id,\n reason: row.reason as ActivityScope['reason'],\n };\n}\n\nfunction relatedProjectFromRow(row: ActivityRelatedProjectRow): ActivityRelatedProject {\n return {\n activityId: row.activity_id,\n projectId: row.project_id,\n reason: row.reason as ActivityRelatedProject['reason'],\n confidence: row.confidence,\n computedAt: row.computed_at,\n };\n}\n\nfunction objectLinkFromRow(row: ObjectLinkRow): ObjectLink {\n return {\n id: row.id,\n from: {\n kind: row.from_kind as ActivityObjectRef['kind'],\n id: row.from_id,\n title: row.from_title ?? undefined,\n },\n to: {\n kind: row.to_kind as ActivityObjectRef['kind'],\n id: row.to_id,\n title: row.to_title ?? undefined,\n },\n relation: row.relation as ObjectLink['relation'],\n source: row.source as ObjectLink['source'],\n createdAt: row.created_at,\n };\n}\n\nfunction listScopesForActivity(activityId: string): ActivityScope[] {\n return getSqliteDatabase()\n .prepare(\n `SELECT activity_id, scope_kind, scope_id, reason\n FROM activity_scopes\n WHERE activity_id = ?\n ORDER BY scope_kind ASC, scope_id ASC, reason ASC`,\n )\n .all(activityId)\n .map((row) => scopeFromRow(row as ActivityScopeRow));\n}\n\nfunction listRelatedProjectsForActivity(activityId: string): ActivityRelatedProject[] {\n return getSqliteDatabase()\n .prepare(\n `SELECT activity_id, project_id, reason, confidence, computed_at\n FROM activity_related_projects\n WHERE activity_id = ?\n ORDER BY project_id ASC, reason ASC`,\n )\n .all(activityId)\n .map((row) => relatedProjectFromRow(row as ActivityRelatedProjectRow));\n}\n\nfunction eventWithRelations(row: ActivityEventRow): ActivityEventWithRelations {\n const event = eventFromRow(row);\n return {\n ...event,\n scopes: listScopesForActivity(event.id),\n relatedProjects: listRelatedProjectsForActivity(event.id),\n };\n}\n\nfunction normalizeLimit(limit: number | undefined): number {\n return Math.max(1, Math.min(100, Math.floor(limit ?? 50)));\n}\n\nfunction normalizeOffset(offset: number | undefined): number {\n return Math.max(0, Math.floor(offset ?? 0));\n}\n\nfunction visibilityClause(visibility: string | undefined, params: SqlParam[]): string {\n if (!visibility) return '';\n params.push(visibility);\n return 'WHERE visibility = ?';\n}\n\nfunction listResult(rows: ActivityEventRow[], total: number, limit: number, offset: number): ActivityListResult {\n return {\n items: rows.map(eventWithRelations),\n total,\n limit,\n offset,\n hasMore: offset + rows.length < total,\n };\n}\n\nexport function recordActivityEvent(input: RecordActivityInput): ActivityEventWithRelations {\n const id = input.id ?? randomUUID();\n const now = input.nowMs ?? Date.now();\n const visibility = input.visibility ?? 'timeline';\n const importance = input.importance ?? 'normal';\n const payload = input.payload ?? {};\n\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO activity_events (\n id, type, primary_object_kind, primary_object_id, primary_object_title,\n actor_json, initiator_json, source_json, payload_json,\n visibility, importance, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.type,\n input.primaryObject.kind,\n input.primaryObject.id,\n input.primaryObject.title ?? null,\n JSON.stringify(input.actor),\n input.initiator ? JSON.stringify(input.initiator) : null,\n JSON.stringify(input.source),\n JSON.stringify(payload),\n visibility,\n importance,\n now,\n );\n\n for (const scope of input.scopes ?? []) {\n db.prepare(\n `INSERT OR IGNORE INTO activity_scopes (activity_id, scope_kind, scope_id, reason)\n VALUES (?, ?, ?, ?)`,\n ).run(id, scope.scopeKind, scope.scopeId, scope.reason);\n }\n\n for (const related of input.relatedProjects ?? []) {\n db.prepare(\n `INSERT OR REPLACE INTO activity_related_projects (\n activity_id, project_id, reason, confidence, computed_at\n ) VALUES (?, ?, ?, ?, ?)`,\n ).run(id, related.projectId, related.reason, related.confidence, related.computedAt ?? now);\n }\n });\n\n const event = getActivityEventRecord(id);\n if (!event) {\n throw new Error(`Activity event was not persisted: ${id}`);\n }\n return event;\n}\n\nexport function getActivityEventRecord(id: string): ActivityEventWithRelations | null {\n const row = getSqliteDatabase()\n .prepare(\n `SELECT *\n FROM activity_events\n WHERE id = ?`,\n )\n .get(id) as ActivityEventRow | undefined;\n return row ? eventWithRelations(row) : null;\n}\n\nexport function listActivityRecords(options: ListActivityOptions = {}): ActivityListResult {\n const limit = normalizeLimit(options.limit);\n const offset = normalizeOffset(options.offset);\n const params: SqlParam[] = [];\n const where = visibilityClause(options.visibility, params);\n const total = (getSqliteDatabase()\n .prepare(`SELECT COUNT(*) AS count FROM activity_events ${where}`)\n .get(...params) as CountRow).count;\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT *\n FROM activity_events\n ${where}\n ORDER BY created_at DESC, id DESC\n LIMIT ? OFFSET ?`,\n )\n .all(...params, limit, offset)\n .map((row) => row as ActivityEventRow);\n return listResult(rows, total, limit, offset);\n}\n\nexport function listObjectActivityRecords(options: ListObjectActivityOptions): ActivityListResult {\n const limit = normalizeLimit(options.limit);\n const offset = normalizeOffset(options.offset);\n const params: SqlParam[] = [options.object.kind, options.object.id];\n const visibility = options.visibility ? 'AND visibility = ?' : '';\n if (options.visibility) params.push(options.visibility);\n const total = (getSqliteDatabase()\n .prepare(\n `SELECT COUNT(*) AS count\n FROM activity_events\n WHERE primary_object_kind = ? AND primary_object_id = ?\n ${visibility}`,\n )\n .get(...params) as CountRow).count;\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT *\n FROM activity_events\n WHERE primary_object_kind = ? AND primary_object_id = ?\n ${visibility}\n ORDER BY created_at DESC, id DESC\n LIMIT ? OFFSET ?`,\n )\n .all(...params, limit, offset)\n .map((row) => row as ActivityEventRow);\n return listResult(rows, total, limit, offset);\n}\n\nexport function listProjectActivityRecords(options: ListProjectActivityOptions): ActivityListResult {\n const limit = normalizeLimit(options.limit);\n const offset = normalizeOffset(options.offset);\n const params: SqlParam[] = ['project', options.projectId];\n const relatedClause = options.includeRelated\n ? `OR EXISTS (\n SELECT 1 FROM activity_related_projects ar\n WHERE ar.activity_id = ae.id AND ar.project_id = ?\n )`\n : '';\n if (options.includeRelated) params.push(options.projectId);\n const visibilityClauseSql = options.visibility ? 'AND ae.visibility = ?' : '';\n if (options.visibility) params.push(options.visibility);\n\n const baseWhere = `EXISTS (\n SELECT 1 FROM activity_scopes s\n WHERE s.activity_id = ae.id AND s.scope_kind = ? AND s.scope_id = ?\n ) ${relatedClause}`;\n\n const total = (getSqliteDatabase()\n .prepare(\n `SELECT COUNT(*) AS count\n FROM activity_events ae\n WHERE (${baseWhere})\n ${visibilityClauseSql}`,\n )\n .get(...params) as CountRow).count;\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT ae.*\n FROM activity_events ae\n WHERE (${baseWhere})\n ${visibilityClauseSql}\n ORDER BY ae.created_at DESC, ae.id DESC\n LIMIT ? OFFSET ?`,\n )\n .all(...params, limit, offset)\n .map((row) => row as ActivityEventRow);\n return listResult(rows, total, limit, offset);\n}\n\nexport function createObjectLinkRecord(input: CreateObjectLinkInput): ObjectLink {\n const id = input.id ?? randomUUID();\n const now = input.nowMs ?? Date.now();\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO object_links (\n id, from_kind, from_id, from_title, to_kind, to_id, to_title, relation, source, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.from.kind,\n input.from.id,\n input.from.title ?? null,\n input.to.kind,\n input.to.id,\n input.to.title ?? null,\n input.relation,\n input.source,\n now,\n );\n });\n const row = getSqliteDatabase()\n .prepare(`SELECT * FROM object_links WHERE id = ?`)\n .get(id) as ObjectLinkRow | undefined;\n if (!row) {\n throw new Error(`Object link was not persisted: ${id}`);\n }\n return objectLinkFromRow(row);\n}\n\nexport function listObjectLinkRecords(object: ActivityObjectRef): ObjectLink[] {\n return getSqliteDatabase()\n .prepare(\n `SELECT *\n FROM object_links\n WHERE (from_kind = ? AND from_id = ?) OR (to_kind = ? AND to_id = ?)\n ORDER BY created_at DESC, id DESC`,\n )\n .all(object.kind, object.id, object.kind, object.id)\n .map((row) => objectLinkFromRow(row as ObjectLinkRow));\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { resolveXopcDatabasePath } from "../../config/paths-state.js";
|
|
2
2
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
3
|
import { init_logger } from "../../utils/logger.js";
|
|
4
|
+
import { ensureXopcDatabaseSchema } from "./schema.js";
|
|
4
5
|
import { requireNodeSqlite } from "../../infra/node-sqlite.js";
|
|
5
6
|
import { installSqliteTransientRejectionHandler } from "../../infra/unhandled-rejections.js";
|
|
6
|
-
import { ensureXopcDatabaseSchema } from "./schema.js";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import fs from "node:fs";
|
|
9
9
|
import childProcess from "node:child_process";
|
|
@@ -14,3 +14,4 @@ export { deleteNoteAgentContextRecord, getNoteAgentContextRecord, upsertNoteAgen
|
|
|
14
14
|
export { resolveAgentIdFromMemoriesDir, searchMemoryIndex, syncMemoryIndex, type MemorySearchHit, } from './memory-index-repository.js';
|
|
15
15
|
export { appendMemorySignal, appendMemoryTraceEvent, deleteMemoryRecord, getMemoryProviderState, getMemoryRecord, listMemorySignals, listMemoryTraceEvents, listMemoryRecords, searchMemoryRecords, setMemoryProviderState, setMemoryTraceFeedback, summarizeMemoryRecallFeedback, upsertMemoryRecord, type AppendMemorySignalInput, type AppendMemoryTraceEventInput, type ListMemoryRecordsOptions, type MemoryRecallFeedbackSummary, type MemorySignalRowPayload, type MemoryTraceFeedback, type MemoryTraceEventPayload, type SearchMemoryRecordsOptions, type SetMemoryTraceFeedbackInput, type UpsertMemoryRecordInput, } from './memory-records-repository.js';
|
|
16
16
|
export { deleteSessionConfig, getSessionConfig, hasSessionConfig, setSessionConfig, updateSessionConfig, } from './config-repository.js';
|
|
17
|
+
export { createObjectLinkRecord, getActivityEventRecord, listActivityRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, recordActivityEvent, } from './activity-repository.js';
|
|
@@ -15,4 +15,5 @@ import { deleteNoteAgentContextRecord, getNoteAgentContextRecord, upsertNoteAgen
|
|
|
15
15
|
import { resolveAgentIdFromMemoriesDir, searchMemoryIndex, syncMemoryIndex } from "./memory-index-repository.js";
|
|
16
16
|
import { appendMemorySignal, appendMemoryTraceEvent, deleteMemoryRecord, getMemoryProviderState, getMemoryRecord, listMemoryRecords, listMemorySignals, listMemoryTraceEvents, searchMemoryRecords, setMemoryProviderState, setMemoryTraceFeedback, summarizeMemoryRecallFeedback, upsertMemoryRecord } from "./memory-records-repository.js";
|
|
17
17
|
import { deleteSessionConfig, getSessionConfig, hasSessionConfig, setSessionConfig, updateSessionConfig } from "./config-repository.js";
|
|
18
|
-
|
|
18
|
+
import { createObjectLinkRecord, getActivityEventRecord, listActivityRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, recordActivityEvent } from "./activity-repository.js";
|
|
19
|
+
export { DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, appendMemorySignal, appendMemoryTraceEvent, appendTranscriptEntry, applyPendingMigrations, buildDefaultSessionMetadata, buildGlobalSessionStats, captureCompactionCheckpoint, classifyStoredRow, closeXopcDatabase, createObjectLinkRecord, deleteMemoryRecord, deleteNoteAgentContextRecord, deleteNoteRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionKeyBySessionId, getActivityEventRecord, getCompactionCheckpointDetail, getCurrentSessionId, getGlobalSessionStats, getMemoryProviderState, getMemoryRecord, getNoteAgentContextRecord, getNoteRecord, getSessionConfig, getSessionMetadata, getSessionPersistedLevels, getSqliteDatabase, getXopcDatabase, hasSessionConfig, incrementSessionStatsOnAppend, inspectSchemaMigrationStatus, isXopcDatabaseOpen, listActivityRecords, listCompactionCheckpoints, listMemoryRecords, listMemorySignals, listMemoryTraceEvents, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, loadCheckpointRows, loadLlmMessagesForSession, loadTranscriptRows, loadTranscriptRowsForSession, metadataToSessionInsert, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, readSchemaVersion, readSchemaVersionForTest, recordActivityEvent, replaceTranscriptRows, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveAgentIdFromMemoriesDir, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreCompactionCheckpoint, runSqliteWriteTransaction, searchMemoryIndex, searchMemoryRecords, sessionConfigRowToConfig, sessionRowToMetadata, setMemoryProviderState, setMemoryTraceFeedback, setSessionConfig, summarizeMemoryRecallFeedback, syncMemoryIndex, transcriptEntryRowToStoredRow, updateSessionConfig, updateSessionStats, upsertMemoryRecord, upsertNoteAgentContextRecord, upsertNoteRecord };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS activity_events (
|
|
2
|
+
id TEXT PRIMARY KEY,
|
|
3
|
+
type TEXT NOT NULL,
|
|
4
|
+
primary_object_kind TEXT NOT NULL,
|
|
5
|
+
primary_object_id TEXT NOT NULL,
|
|
6
|
+
primary_object_title TEXT,
|
|
7
|
+
actor_json TEXT NOT NULL,
|
|
8
|
+
initiator_json TEXT,
|
|
9
|
+
source_json TEXT NOT NULL,
|
|
10
|
+
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
11
|
+
visibility TEXT NOT NULL,
|
|
12
|
+
importance TEXT NOT NULL,
|
|
13
|
+
created_at INTEGER NOT NULL
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_activity_events_created
|
|
17
|
+
ON activity_events(created_at DESC);
|
|
18
|
+
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_activity_events_object_created
|
|
20
|
+
ON activity_events(primary_object_kind, primary_object_id, created_at DESC);
|
|
21
|
+
|
|
22
|
+
CREATE TABLE IF NOT EXISTS activity_scopes (
|
|
23
|
+
activity_id TEXT NOT NULL,
|
|
24
|
+
scope_kind TEXT NOT NULL,
|
|
25
|
+
scope_id TEXT NOT NULL,
|
|
26
|
+
reason TEXT NOT NULL,
|
|
27
|
+
PRIMARY KEY (activity_id, scope_kind, scope_id, reason)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_activity_scopes_scope
|
|
31
|
+
ON activity_scopes(scope_kind, scope_id, activity_id);
|
|
32
|
+
|
|
33
|
+
CREATE TABLE IF NOT EXISTS object_links (
|
|
34
|
+
id TEXT PRIMARY KEY,
|
|
35
|
+
from_kind TEXT NOT NULL,
|
|
36
|
+
from_id TEXT NOT NULL,
|
|
37
|
+
from_title TEXT,
|
|
38
|
+
to_kind TEXT NOT NULL,
|
|
39
|
+
to_id TEXT NOT NULL,
|
|
40
|
+
to_title TEXT,
|
|
41
|
+
relation TEXT NOT NULL,
|
|
42
|
+
source TEXT NOT NULL,
|
|
43
|
+
created_at INTEGER NOT NULL
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
CREATE INDEX IF NOT EXISTS idx_object_links_from
|
|
47
|
+
ON object_links(from_kind, from_id);
|
|
48
|
+
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_object_links_to
|
|
50
|
+
ON object_links(to_kind, to_id);
|
|
51
|
+
|
|
52
|
+
CREATE TABLE IF NOT EXISTS activity_related_projects (
|
|
53
|
+
activity_id TEXT NOT NULL,
|
|
54
|
+
project_id TEXT NOT NULL,
|
|
55
|
+
reason TEXT NOT NULL,
|
|
56
|
+
confidence REAL NOT NULL,
|
|
57
|
+
computed_at INTEGER NOT NULL,
|
|
58
|
+
PRIMARY KEY (activity_id, project_id, reason)
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE INDEX IF NOT EXISTS idx_activity_related_projects_project
|
|
62
|
+
ON activity_related_projects(project_id, activity_id);
|
|
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
|
|
|
3
3
|
/** Baseline schema version applied from schema.sql on first open. */
|
|
4
4
|
export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
5
5
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
6
|
-
export declare const XOPC_DB_SCHEMA_VERSION =
|
|
6
|
+
export declare const XOPC_DB_SCHEMA_VERSION = 24;
|
|
7
7
|
export declare function resolveMigrationsDir(override?: string): string;
|
|
8
8
|
/**
|
|
9
9
|
* Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
|
|
@@ -12,7 +12,7 @@ const log = createLogger("Sqlite:Migrations");
|
|
|
12
12
|
/** Baseline schema version applied from schema.sql on first open. */
|
|
13
13
|
const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
14
14
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
15
|
-
const XOPC_DB_SCHEMA_VERSION =
|
|
15
|
+
const XOPC_DB_SCHEMA_VERSION = 24;
|
|
16
16
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
17
17
|
function resolveMigrationsDir(override) {
|
|
18
18
|
if (override) return override;
|
|
@@ -46,7 +46,7 @@ function applySingleMigration(db, migration) {
|
|
|
46
46
|
* Each step runs in its own transaction and updates schema_meta on success.
|
|
47
47
|
*/
|
|
48
48
|
function applyPendingMigrations(db, options = {}) {
|
|
49
|
-
const targetVersion = options.targetVersion ??
|
|
49
|
+
const targetVersion = options.targetVersion ?? 24;
|
|
50
50
|
let currentVersion = readSchemaVersion(db);
|
|
51
51
|
if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
|
|
52
52
|
if (currentVersion >= targetVersion) return currentVersion;
|
|
@@ -62,7 +62,7 @@ function applyPendingMigrations(db, options = {}) {
|
|
|
62
62
|
}
|
|
63
63
|
/** Inspect schema version without mutating the database. */
|
|
64
64
|
function inspectSchemaMigrationStatus(db, options = {}) {
|
|
65
|
-
const appVersion = options.targetVersion ??
|
|
65
|
+
const appVersion = options.targetVersion ?? 24;
|
|
66
66
|
const dbVersion = readSchemaVersion(db);
|
|
67
67
|
if (dbVersion > appVersion) return {
|
|
68
68
|
dbVersion,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","names":[],"sources":["../../../../../src/storage/sqlite/migrations/runner.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { DatabaseSync } from 'node:sqlite';\n\nimport { createLogger } from '../../../utils/logger.js';\nimport { readSchemaVersion, setSchemaVersion } from '../schema-version.js';\nimport { discoverSqlMigrations } from './discover.js';\nimport {\n DatabaseSchemaMigrationGapError,\n DatabaseSchemaTooNewError,\n} from './errors.js';\nimport type { ApplyMigrationsOptions, SqlMigration } from './types.js';\n\nconst log = createLogger('Sqlite:Migrations');\n\n/** Baseline schema version applied from schema.sql on first open. */\nexport const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;\n\n/** Latest schema version this release supports (increment when adding migrations). */\nexport const XOPC_DB_SCHEMA_VERSION =
|
|
1
|
+
{"version":3,"file":"runner.js","names":[],"sources":["../../../../../src/storage/sqlite/migrations/runner.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { DatabaseSync } from 'node:sqlite';\n\nimport { createLogger } from '../../../utils/logger.js';\nimport { readSchemaVersion, setSchemaVersion } from '../schema-version.js';\nimport { discoverSqlMigrations } from './discover.js';\nimport {\n DatabaseSchemaMigrationGapError,\n DatabaseSchemaTooNewError,\n} from './errors.js';\nimport type { ApplyMigrationsOptions, SqlMigration } from './types.js';\n\nconst log = createLogger('Sqlite:Migrations');\n\n/** Baseline schema version applied from schema.sql on first open. */\nexport const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;\n\n/** Latest schema version this release supports (increment when adding migrations). */\nexport const XOPC_DB_SCHEMA_VERSION = 24;\n\nconst MODULE_DIR = dirname(fileURLToPath(import.meta.url));\n\nexport function resolveMigrationsDir(override?: string): string {\n if (override) {\n return override;\n }\n // Packaged Electron gateway bundle: `out/server/index.js` + `out/server/migrations/`.\n const siblingDir = join(MODULE_DIR, 'migrations');\n if (existsSync(siblingDir)) {\n return siblingDir;\n }\n // Dev / dist: SQL files live next to `migrations/runner.js`.\n return MODULE_DIR;\n}\n\nfunction migrationByTarget(\n migrations: SqlMigration[],\n targetVersion: number,\n): SqlMigration | undefined {\n return migrations.find((migration) => migration.targetVersion === targetVersion);\n}\n\nfunction applySingleMigration(db: DatabaseSync, migration: SqlMigration): void {\n log.info({ targetVersion: migration.targetVersion, file: migration.filename }, 'Applying SQLite migration');\n db.exec('BEGIN IMMEDIATE');\n try {\n db.exec(migration.sql);\n setSchemaVersion(db, migration.targetVersion);\n db.exec('COMMIT');\n } catch (error) {\n try {\n db.exec('ROLLBACK');\n } catch {\n /* preserve original error */\n }\n const em = error instanceof Error ? error.message : String(error);\n throw new Error(\n `SQLite migration to v${migration.targetVersion} (${migration.filename}) failed: ${em}`,\n { cause: error },\n );\n }\n}\n\n/**\n * Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.\n * Each step runs in its own transaction and updates schema_meta on success.\n */\nexport function applyPendingMigrations(\n db: DatabaseSync,\n options: ApplyMigrationsOptions = {},\n): number {\n const targetVersion = options.targetVersion ?? XOPC_DB_SCHEMA_VERSION;\n let currentVersion = readSchemaVersion(db);\n\n if (currentVersion > targetVersion) {\n throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);\n }\n\n if (currentVersion >= targetVersion) {\n return currentVersion;\n }\n\n const migrations = discoverSqlMigrations(resolveMigrationsDir(options.migrationsDir));\n\n while (currentVersion < targetVersion) {\n const nextVersion = currentVersion + 1;\n const migration = migrationByTarget(migrations, nextVersion);\n if (!migration) {\n throw new DatabaseSchemaMigrationGapError(currentVersion, targetVersion, nextVersion);\n }\n applySingleMigration(db, migration);\n currentVersion = nextVersion;\n }\n\n return currentVersion;\n}\n\nexport type SchemaMigrationStatus = {\n dbVersion: number;\n appVersion: number;\n pendingVersions: number[];\n isTooNew: boolean;\n hasMigrationGap: boolean;\n missingVersion: number | null;\n};\n\n/** Inspect schema version without mutating the database. */\nexport function inspectSchemaMigrationStatus(\n db: DatabaseSync,\n options: Pick<ApplyMigrationsOptions, 'migrationsDir' | 'targetVersion'> = {},\n): SchemaMigrationStatus {\n const appVersion = options.targetVersion ?? XOPC_DB_SCHEMA_VERSION;\n const dbVersion = readSchemaVersion(db);\n const isTooNew = dbVersion > appVersion;\n\n if (isTooNew) {\n return {\n dbVersion,\n appVersion,\n pendingVersions: [],\n isTooNew: true,\n hasMigrationGap: false,\n missingVersion: null,\n };\n }\n\n const migrations = discoverSqlMigrations(resolveMigrationsDir(options.migrationsDir));\n const pendingVersions: number[] = [];\n let hasMigrationGap = false;\n let missingVersion: number | null = null;\n\n for (let version = dbVersion + 1; version <= appVersion; version++) {\n if (migrationByTarget(migrations, version)) {\n pendingVersions.push(version);\n } else {\n hasMigrationGap = true;\n missingVersion = version;\n break;\n }\n }\n\n return {\n dbVersion,\n appVersion,\n pendingVersions,\n isTooNew: false,\n hasMigrationGap,\n missingVersion,\n };\n}\n"],"mappings":";;;;;;;;;aAMwD;AASxD,MAAM,MAAM,aAAa,oBAAoB;;AAG7C,MAAa,kCAAkC;;AAG/C,MAAa,yBAAyB;AAEtC,MAAM,aAAa,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAE1D,SAAgB,qBAAqB,UAA2B;AAC9D,KAAI,SACF,QAAO;CAGT,MAAM,aAAa,KAAK,YAAY,aAAa;AACjD,KAAI,WAAW,WAAW,CACxB,QAAO;AAGT,QAAO;;AAGT,SAAS,kBACP,YACA,eAC0B;AAC1B,QAAO,WAAW,MAAM,cAAc,UAAU,kBAAkB,cAAc;;AAGlF,SAAS,qBAAqB,IAAkB,WAA+B;AAC7E,KAAI,KAAK;EAAE,eAAe,UAAU;EAAe,MAAM,UAAU;EAAU,EAAE,4BAA4B;AAC3G,IAAG,KAAK,kBAAkB;AAC1B,KAAI;AACF,KAAG,KAAK,UAAU,IAAI;AACtB,mBAAiB,IAAI,UAAU,cAAc;AAC7C,KAAG,KAAK,SAAS;UACV,OAAO;AACd,MAAI;AACF,MAAG,KAAK,WAAW;UACb;EAGR,MAAM,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACjE,QAAM,IAAI,MACR,wBAAwB,UAAU,cAAc,IAAI,UAAU,SAAS,YAAY,MACnF,EAAE,OAAO,OAAO,CACjB;;;;;;;AAQL,SAAgB,uBACd,IACA,UAAkC,EAAE,EAC5B;CACR,MAAM,gBAAgB,QAAQ,iBAAA;CAC9B,IAAI,iBAAiB,kBAAkB,GAAG;AAE1C,KAAI,iBAAiB,cACnB,OAAM,IAAI,0BAA0B,gBAAgB,cAAc;AAGpE,KAAI,kBAAkB,cACpB,QAAO;CAGT,MAAM,aAAa,sBAAsB,qBAAqB,QAAQ,cAAc,CAAC;AAErF,QAAO,iBAAiB,eAAe;EACrC,MAAM,cAAc,iBAAiB;EACrC,MAAM,YAAY,kBAAkB,YAAY,YAAY;AAC5D,MAAI,CAAC,UACH,OAAM,IAAI,gCAAgC,gBAAgB,eAAe,YAAY;AAEvF,uBAAqB,IAAI,UAAU;AACnC,mBAAiB;;AAGnB,QAAO;;;AAaT,SAAgB,6BACd,IACA,UAA2E,EAAE,EACtD;CACvB,MAAM,aAAa,QAAQ,iBAAA;CAC3B,MAAM,YAAY,kBAAkB,GAAG;AAGvC,KAFiB,YAAY,WAG3B,QAAO;EACL;EACA;EACA,iBAAiB,EAAE;EACnB,UAAU;EACV,iBAAiB;EACjB,gBAAgB;EACjB;CAGH,MAAM,aAAa,sBAAsB,qBAAqB,QAAQ,cAAc,CAAC;CACrF,MAAM,kBAA4B,EAAE;CACpC,IAAI,kBAAkB;CACtB,IAAI,iBAAgC;AAEpC,MAAK,IAAI,UAAU,YAAY,GAAG,WAAW,YAAY,UACvD,KAAI,kBAAkB,YAAY,QAAQ,CACxC,iBAAgB,KAAK,QAAQ;MACxB;AACL,oBAAkB;AAClB,mBAAiB;AACjB;;AAIJ,QAAO;EACL;EACA;EACA;EACA,UAAU;EACV;EACA;EACD"}
|
|
@@ -19,7 +19,7 @@ const log = createLogger('Sqlite:Migrations');
|
|
|
19
19
|
export const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
20
20
|
|
|
21
21
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
22
|
-
export const XOPC_DB_SCHEMA_VERSION =
|
|
22
|
+
export const XOPC_DB_SCHEMA_VERSION = 24;
|
|
23
23
|
|
|
24
24
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
25
25
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { init_agent_session_key, resolveAgentIdFromSessionKey } from "../../routing/agent-session-key.js";
|
|
2
1
|
import "../../session/types.js";
|
|
3
2
|
import { buildDefaultSessionMetadata } from "./session-metadata.js";
|
|
4
3
|
import { isTranscriptContextEntry } from "../../session/session-context-for-llm.js";
|
|
4
|
+
import { init_agent_session_key, resolveAgentIdFromSessionKey } from "../../routing/agent-session-key.js";
|
|
5
5
|
//#region src/storage/sqlite/row-mappers.ts
|
|
6
6
|
init_agent_session_key();
|
|
7
7
|
function parseJson(raw) {
|
|
@@ -31,7 +31,7 @@ function ensureXopcDatabaseSchema(db) {
|
|
|
31
31
|
bootstrapFreshDatabase(db);
|
|
32
32
|
currentVersion = 11;
|
|
33
33
|
}
|
|
34
|
-
applyPendingMigrations(db, { targetVersion:
|
|
34
|
+
applyPendingMigrations(db, { targetVersion: 24 });
|
|
35
35
|
}
|
|
36
36
|
//#endregion
|
|
37
37
|
export { SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_SCHEMA_VERSION, ensureSchemaMetaTable, ensureXopcDatabaseSchema, readSchemaVersion, readSchemaVersionForTest, setSchemaVersion };
|
|
@@ -482,6 +482,69 @@ CREATE TABLE IF NOT EXISTS work_item_update_suggestions (
|
|
|
482
482
|
CREATE INDEX IF NOT EXISTS idx_work_item_update_suggestions_item
|
|
483
483
|
ON work_item_update_suggestions(work_item_id, status, created_at DESC);
|
|
484
484
|
|
|
485
|
+
CREATE TABLE IF NOT EXISTS activity_events (
|
|
486
|
+
id TEXT PRIMARY KEY,
|
|
487
|
+
type TEXT NOT NULL,
|
|
488
|
+
primary_object_kind TEXT NOT NULL,
|
|
489
|
+
primary_object_id TEXT NOT NULL,
|
|
490
|
+
primary_object_title TEXT,
|
|
491
|
+
actor_json TEXT NOT NULL,
|
|
492
|
+
initiator_json TEXT,
|
|
493
|
+
source_json TEXT NOT NULL,
|
|
494
|
+
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
495
|
+
visibility TEXT NOT NULL,
|
|
496
|
+
importance TEXT NOT NULL,
|
|
497
|
+
created_at INTEGER NOT NULL
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
CREATE INDEX IF NOT EXISTS idx_activity_events_created
|
|
501
|
+
ON activity_events(created_at DESC);
|
|
502
|
+
|
|
503
|
+
CREATE INDEX IF NOT EXISTS idx_activity_events_object_created
|
|
504
|
+
ON activity_events(primary_object_kind, primary_object_id, created_at DESC);
|
|
505
|
+
|
|
506
|
+
CREATE TABLE IF NOT EXISTS activity_scopes (
|
|
507
|
+
activity_id TEXT NOT NULL,
|
|
508
|
+
scope_kind TEXT NOT NULL,
|
|
509
|
+
scope_id TEXT NOT NULL,
|
|
510
|
+
reason TEXT NOT NULL,
|
|
511
|
+
PRIMARY KEY (activity_id, scope_kind, scope_id, reason)
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
CREATE INDEX IF NOT EXISTS idx_activity_scopes_scope
|
|
515
|
+
ON activity_scopes(scope_kind, scope_id, activity_id);
|
|
516
|
+
|
|
517
|
+
CREATE TABLE IF NOT EXISTS object_links (
|
|
518
|
+
id TEXT PRIMARY KEY,
|
|
519
|
+
from_kind TEXT NOT NULL,
|
|
520
|
+
from_id TEXT NOT NULL,
|
|
521
|
+
from_title TEXT,
|
|
522
|
+
to_kind TEXT NOT NULL,
|
|
523
|
+
to_id TEXT NOT NULL,
|
|
524
|
+
to_title TEXT,
|
|
525
|
+
relation TEXT NOT NULL,
|
|
526
|
+
source TEXT NOT NULL,
|
|
527
|
+
created_at INTEGER NOT NULL
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
CREATE INDEX IF NOT EXISTS idx_object_links_from
|
|
531
|
+
ON object_links(from_kind, from_id);
|
|
532
|
+
|
|
533
|
+
CREATE INDEX IF NOT EXISTS idx_object_links_to
|
|
534
|
+
ON object_links(to_kind, to_id);
|
|
535
|
+
|
|
536
|
+
CREATE TABLE IF NOT EXISTS activity_related_projects (
|
|
537
|
+
activity_id TEXT NOT NULL,
|
|
538
|
+
project_id TEXT NOT NULL,
|
|
539
|
+
reason TEXT NOT NULL,
|
|
540
|
+
confidence REAL NOT NULL,
|
|
541
|
+
computed_at INTEGER NOT NULL,
|
|
542
|
+
PRIMARY KEY (activity_id, project_id, reason)
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
CREATE INDEX IF NOT EXISTS idx_activity_related_projects_project
|
|
546
|
+
ON activity_related_projects(project_id, activity_id);
|
|
547
|
+
|
|
485
548
|
CREATE TABLE IF NOT EXISTS goal_context_messages (
|
|
486
549
|
goal_id TEXT PRIMARY KEY,
|
|
487
550
|
text TEXT NOT NULL DEFAULT '',
|
|
@@ -93,6 +93,17 @@ function listSessionMetadata(query = {}) {
|
|
|
93
93
|
if (query.projectId) {
|
|
94
94
|
conditions.push(`s.project_id = ?`);
|
|
95
95
|
params.push(query.projectId);
|
|
96
|
+
} else if (query.unassigned) conditions.push(`(s.project_id IS NULL OR s.project_id = '')`);
|
|
97
|
+
if (query.updatedAfter !== void 0) {
|
|
98
|
+
const clauses = [`s.updated_at >= ?`];
|
|
99
|
+
params.push(query.updatedAfter);
|
|
100
|
+
if (query.includePinned) clauses.push(`s.status = 'pinned'`);
|
|
101
|
+
const includeSessionKey = query.includeSessionKey?.trim();
|
|
102
|
+
if (includeSessionKey) {
|
|
103
|
+
clauses.push(`s.session_key = ?`);
|
|
104
|
+
params.push(includeSessionKey);
|
|
105
|
+
}
|
|
106
|
+
conditions.push(`(${clauses.join(" OR ")})`);
|
|
96
107
|
}
|
|
97
108
|
if (query.channel) {
|
|
98
109
|
const rawChannels = query.channel.split(",").map((c) => c.trim().toLowerCase()).filter(Boolean);
|