@xopcai/xopc 0.0.127 → 0.0.129
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CgGgO4OV.js → agent-avatar-dicebear-DHzfg5D-.js} +1 -1
- package/dist/gateway/static/root/assets/agents-CMxKKFQD.js +2 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-ptk9c5BN.js +1 -0
- package/dist/gateway/static/root/assets/{appearance-settings-BnHQW7Hv.js → appearance-settings-bYeEj3IW.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-DdZvDf5B.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-5NXT7Zqv.js → archive-plugin-Dy6lsTHw.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DghwhYe0.js → attachment-load-qOtBYR6Y.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-DYmESgwl.js → automation-suggestion-card-BFH-RfaV.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-B8JTjkCr.js +4 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DSbPKdWX.js → binary-plugins-DJvi_thc.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CoZ-_np-.js → block-editor-DlMnizlt.js} +4 -4
- package/dist/gateway/static/root/assets/browser-settings-page-slHLiZgi.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-D4q7vHVJ.js +1 -0
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Dng8Grpv.js +1 -0
- package/dist/gateway/static/root/assets/channel-recipient-api-BrW5Kcgc.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-KIsISXw0.js +1 -0
- package/dist/gateway/static/root/assets/{code-editor-gbRgS14t.js → code-editor--tMO38Tr.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-C5fx4Qs9.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-Jmdn6q47.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-npJ0Oh5p.js → desktop-pet-settings-B-u63N4e.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-BR2ItBuf.js → directory-picker-path-field-8p1ehIHn.js} +1 -1
- package/dist/gateway/static/root/assets/dreaming-settings-CCkKP-I4.js +3 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-Tl0f1rNv.js → extension-debug-page-DJ1ABK95.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Ck7QuwE3.js → extension-page-CP9P2lGM.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-DnhU-tx0.js +1 -0
- package/dist/gateway/static/root/assets/fetch-BMjlW0g1.js +1 -0
- package/dist/gateway/static/root/assets/gateway-config-api-CjxDn46s.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-TING7224.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Yh8h3hkj.js → gateway-startup-retry-CY5W2Pp4.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-2lPbGfp3.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-DHWVRafk.js +4 -0
- package/dist/gateway/static/root/assets/goals-config-api-BqhuxG8P.js +1 -0
- package/dist/gateway/static/root/assets/goals-page-CMk-9ZYN.js +2 -0
- package/dist/gateway/static/root/assets/goals-settings-BHzOAU_l.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-BQIm0P3V.js +1 -0
- package/dist/gateway/static/root/assets/{html-workspace-editor-DV90ddkE.js → html-workspace-editor-COqmtESs.js} +1 -1
- package/dist/gateway/static/root/assets/index-C4k6QSXw.js +257 -0
- package/dist/gateway/static/root/assets/index-EKmpPvZj.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CfQrt_Rb.js → keyboard-shortcuts-settings-BrENZzM7.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-BiL302Ve.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-editor-BFOjBBla.js → markdown-editor-jD1LPiP-.js} +2 -2
- package/dist/gateway/static/root/assets/{markdown-split-BwiMdCf_.js → markdown-split-BYF4ReGM.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DhoizyZv.js → media-plugins-CpQDz-QJ.js} +1 -1
- package/dist/gateway/static/root/assets/messages-YzjnURPJ.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-CFPpl3Cq.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-BurgcdVZ.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-BAELRM_O.js +2 -0
- package/dist/gateway/static/root/assets/{page-tabs-DDC2t4Z8.js → page-tabs-RnYYOIWO.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-BTmk-XDM.js → preview-open-alternatives-CTRt06Ri.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-iXX1Ceo2.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-GDVTFAY7.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-BUrbUnwv.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-DqU-yKIh.js → save-bar-controls-c4pZeikq.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-CUttkoSB.js → schedule-field-Cb6R7iuP.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CVSQA9nI.js → schema-form-BqET_hEP.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CiOreA2k.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-C-qvptlu.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-CK7ogS-P.js → settings-collapsible-section-DuOvqNsI.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-Bugp38Fa.js → settings-form-section-DptSsbWd.js} +1 -1
- package/dist/gateway/static/root/assets/settings-loading-skeleton-BlVfBCb9.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-layout-DBRWwdhh.js → settings-page-layout-DVt69dJJ.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-xQx2Pkg5.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-DWB8VdLK.js +1 -0
- package/dist/gateway/static/root/assets/share-preview-page-8m_ACH0z.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-CgxfhNxI.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BBFUOxmf.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-bo695odu.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-DJ6YuLqR.js → system-settings-panel-CW22OkZ4.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-B0T7N8Km.js → typed-models-lib-BqpGAKxV.js} +1 -1
- package/dist/gateway/static/root/assets/url-DFGNSBNT.js +1 -0
- package/dist/gateway/static/root/assets/use-channel-catalog-CPdJ0o0i.js +1 -0
- package/dist/gateway/static/root/assets/user-profile-settings-panel-CERVLuaW.js +1 -0
- package/dist/gateway/static/root/assets/{utils-CehXcWAY.js → utils-BnmysurA.js} +1 -1
- package/dist/gateway/static/root/assets/vendor-codemirror-C1WKjCk5.js +45 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-Jr3jvPcB.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-B-8rex4u.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-c4jeaohQ.js → workflow-run-setup-panel-Ci9GSPnS.js} +2 -2
- package/dist/gateway/static/root/assets/{workflow-start-dialog-ENRHjoqa.js → workflow-start-dialog-BhDj8pqH.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-Brb3UGvs.js +18 -0
- package/dist/gateway/static/root/index.html +7 -6
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +3 -0
- package/dist/src/agent/agent-manager.js +14 -6
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/capabilities/definitions.d.ts +14 -0
- package/dist/src/agent/capabilities/definitions.js +19 -0
- package/dist/src/agent/capabilities/definitions.js.map +1 -1
- package/dist/src/agent/goals/post-turn.js +23 -2
- package/dist/src/agent/goals/post-turn.js.map +1 -1
- package/dist/src/agent/messaging/command-handler.d.ts +4 -0
- package/dist/src/agent/messaging/command-handler.js +6 -0
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/service.d.ts +2 -0
- package/dist/src/agent/service.js +23 -0
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/skills/hub-lock.d.ts +5 -5
- package/dist/src/agent/skills/hub-lock.js +12 -12
- package/dist/src/agent/skills/hub-lock.js.map +1 -1
- package/dist/src/agent/skills/hub-pull.d.ts +15 -0
- package/dist/src/agent/skills/hub-pull.js +299 -24
- package/dist/src/agent/skills/hub-pull.js.map +1 -1
- package/dist/src/agent/skills/index.js +4 -40
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/install-target.d.ts +3 -0
- package/dist/src/agent/skills/install-target.js +11 -0
- package/dist/src/agent/skills/install-target.js.map +1 -0
- package/dist/src/agent/skills/managed-store.d.ts +5 -3
- package/dist/src/agent/skills/managed-store.js +10 -9
- package/dist/src/agent/skills/managed-store.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +5 -3
- package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +21 -1
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +62 -6
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
- package/dist/src/agent/skills/marketplace/resolve-adapter.js +1 -1
- package/dist/src/agent/skills/marketplace/resolve-adapter.js.map +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +2 -2
- package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -6
- package/dist/src/agent/skills/skill-manager.js.map +1 -1
- package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
- package/dist/src/agent/skills/workspace-skills-dir.js +5 -1
- package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -1
- package/dist/src/agent/tools/automation-tool.d.ts +6 -6
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +20 -20
- package/dist/src/agent/tools/composio-tool.d.ts +3 -3
- package/dist/src/agent/tools/desktop-pet-tool.d.ts +7 -7
- package/dist/src/agent/tools/factory.d.ts +3 -0
- package/dist/src/agent/tools/factory.js +6 -1
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/goal-tool.d.ts +16 -16
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/skill-install-tool.d.ts +28 -0
- package/dist/src/agent/tools/skill-install-tool.js +81 -0
- package/dist/src/agent/tools/skill-install-tool.js.map +1 -0
- package/dist/src/agent/tools/skill-manage-tool.js +3 -6
- package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
- package/dist/src/agent/tools/tool-manual-tool.d.ts +2 -2
- package/dist/src/agent/tools/xopc-use-tool.d.ts +5 -5
- package/dist/src/automations/domain/types.d.ts +1 -0
- package/dist/src/automations/draft/automation-draft-service.js +1 -1
- package/dist/src/automations/service/automation-service.js +9 -0
- package/dist/src/automations/service/automation-service.js.map +1 -1
- package/dist/src/browser/schemas.d.ts +52 -52
- package/dist/src/capabilities/store-connector.d.ts +17 -0
- package/dist/src/capabilities/store-connector.js +191 -0
- package/dist/src/capabilities/store-connector.js.map +1 -0
- package/dist/src/chat-commands/builtins/skill.d.ts +1 -0
- package/dist/src/chat-commands/builtins/skill.js +132 -0
- package/dist/src/chat-commands/builtins/skill.js.map +1 -0
- package/dist/src/chat-commands/context.d.ts +3 -0
- package/dist/src/chat-commands/context.js +2 -0
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/index.d.ts +1 -0
- package/dist/src/chat-commands/index.js +3 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +17 -0
- package/dist/src/cli/command-loaders.js +1 -0
- package/dist/src/cli/command-loaders.js.map +1 -1
- package/dist/src/cli/command-manifest.js +4 -0
- package/dist/src/cli/command-manifest.js.map +1 -1
- package/dist/src/cli/commands/agent.js +2 -2
- package/dist/src/cli/commands/connectors.d.ts +4 -0
- package/dist/src/cli/commands/connectors.js +96 -0
- package/dist/src/cli/commands/connectors.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/commands/profile.js +1 -1
- package/dist/src/cli/commands/skills.js +1 -1
- package/dist/src/cli/commands/tunnel.js +1 -1
- package/dist/src/cli/commands/update.js +1 -1
- package/dist/src/cli/extension-cli-register.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/index.js +1 -1
- package/dist/src/config/schema.js +2 -2
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/connectors/health.js +1 -1
- package/dist/src/connectors/install.js +3 -1
- package/dist/src/connectors/install.js.map +1 -1
- package/dist/src/connectors/materialize.js +2 -0
- package/dist/src/connectors/materialize.js.map +1 -1
- package/dist/src/connectors/types.d.ts +19 -1
- package/dist/src/extensions/install.js +1 -1
- package/dist/src/extensions/types/manifest.d.ts +1 -1
- package/dist/src/extensions/update.js +5 -3
- package/dist/src/extensions/update.js.map +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/chat-stream/mapper.js +5 -1
- package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
- package/dist/src/gateway/chat-stream/protocol.d.ts +2 -0
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/middleware/auth.d.ts +2 -2
- package/dist/src/gateway/hono/middleware/logger.d.ts +1 -1
- package/dist/src/gateway/hono/middleware/route-errors.d.ts +1 -1
- package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +2 -2
- package/dist/src/gateway/hono/routes/capabilities.d.ts +3 -0
- package/dist/src/gateway/hono/routes/capabilities.js +79 -0
- package/dist/src/gateway/hono/routes/capabilities.js.map +1 -0
- package/dist/src/gateway/hono/routes/commands-skills.js +81 -3
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/connectors.js +2 -2
- package/dist/src/gateway/hono/routes/goals.js +212 -3
- package/dist/src/gateway/hono/routes/goals.js.map +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/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/mcp.js +1 -1
- package/dist/src/gateway/hono/routes/mobile.d.ts +3 -0
- package/dist/src/gateway/hono/routes/mobile.js +113 -0
- package/dist/src/gateway/hono/routes/mobile.js.map +1 -0
- package/dist/src/gateway/hono/routes/projects.js +17 -0
- package/dist/src/gateway/hono/routes/projects.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +4 -1
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/hono/sse.d.ts +3 -3
- package/dist/src/gateway/run-loop.js +1 -1
- package/dist/src/gateway/service/marketplace-service.d.ts +23 -1
- package/dist/src/gateway/service/marketplace-service.js +57 -6
- package/dist/src/gateway/service/marketplace-service.js.map +1 -1
- package/dist/src/gateway/service.d.ts +2 -0
- package/dist/src/gateway/service.js +12 -2
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/goals/goal-contract-draft.d.ts +15 -0
- package/dist/src/goals/goal-contract-draft.js +114 -0
- package/dist/src/goals/goal-contract-draft.js.map +1 -0
- package/dist/src/goals/goal-evidence-review.d.ts +15 -0
- package/dist/src/goals/goal-evidence-review.js +91 -0
- package/dist/src/goals/goal-evidence-review.js.map +1 -0
- package/dist/src/goals/goal-runner.js +3 -1
- package/dist/src/goals/goal-runner.js.map +1 -1
- package/dist/src/goals/goal-service.d.ts +17 -1
- package/dist/src/goals/goal-service.js +44 -3
- package/dist/src/goals/goal-service.js.map +1 -1
- package/dist/src/goals/goal-store.d.ts +18 -1
- package/dist/src/goals/goal-store.js +190 -1
- package/dist/src/goals/goal-store.js.map +1 -1
- package/dist/src/goals/index.d.ts +4 -0
- package/dist/src/goals/index.js +3 -1
- package/dist/src/goals/types.d.ts +42 -0
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/mobile/notification-service.d.ts +8 -0
- package/dist/src/mobile/notification-service.js +139 -0
- package/dist/src/mobile/notification-service.js.map +1 -0
- package/dist/src/mobile/notification-store.d.ts +28 -0
- package/dist/src/mobile/notification-store.js +134 -0
- package/dist/src/mobile/notification-store.js.map +1 -0
- package/dist/src/mobile/notification-types.d.ts +37 -0
- package/dist/src/mobile/notification-types.js +11 -0
- package/dist/src/mobile/notification-types.js.map +1 -0
- package/dist/src/storage/sqlite/migrations/026_goal_contracts.sql +10 -0
- package/dist/src/storage/sqlite/migrations/027_mobile_notifications.sql +43 -0
- package/dist/src/storage/sqlite/migrations/028_goal_evidence_requirements.sql +47 -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/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +44 -0
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/package.json +1 -1
- package/skills/THIRD_PARTY_NOTICES.md +16 -0
- package/skills/creative/algorithmic-art/SKILL.md +37 -0
- package/skills/creative/algorithmic-art/templates/generator-template.js +27 -0
- package/skills/creative/algorithmic-art/templates/viewer.html +27 -0
- package/skills/documents/doc-coauthoring/SKILL.md +40 -0
- package/skills/documents/doc-coauthoring/references/reader-review.md +9 -0
- package/skills/documents/docx/SKILL.md +40 -0
- package/skills/documents/docx/references/editing-checklist.md +8 -0
- package/skills/documents/docx/scripts/inspect_ooxml.py +36 -0
- package/skills/documents/docx/scripts/render_docx.py +33 -0
- package/skills/documents/pdf/SKILL.md +47 -0
- package/skills/documents/pdf/references/operations.md +16 -0
- package/skills/documents/pdf/scripts/inspect_pdf.py +41 -0
- package/skills/documents/pdf/scripts/render_pdf.py +32 -0
- package/skills/documents/pptx/SKILL.md +41 -0
- package/skills/documents/pptx/references/qa-checklist.md +6 -0
- package/skills/documents/pptx/scripts/inspect_ooxml.py +34 -0
- package/skills/documents/pptx/scripts/render_pptx.py +33 -0
- package/skills/engineering/define-goal/SKILL.md +41 -0
- package/skills/engineering/define-goal/references/objective-rubric.md +12 -0
- package/dist/gateway/static/root/assets/agents-k59l7NMb.js +0 -2
- package/dist/gateway/static/root/assets/app-management-settings-panel-DeQsTsyy.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-BG9b4abG.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-De8mVutL.js +0 -4
- package/dist/gateway/static/root/assets/browser-settings-page-C_ZRa4LF.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-api-hny224j-.js +0 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Drc0qLsw.js +0 -1
- package/dist/gateway/static/root/assets/channel-recipient-api-DAlOHxKJ.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-CA20zBV9.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-qMyMB5te.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-XG6Vb_fZ.js +0 -1
- package/dist/gateway/static/root/assets/dreaming-settings-CkUZ997f.js +0 -3
- package/dist/gateway/static/root/assets/extension-settings-page-3RMhQtZ3.js +0 -1
- package/dist/gateway/static/root/assets/fetch-pg2ErdAk.js +0 -1
- package/dist/gateway/static/root/assets/gateway-config-api-DbG97ia2.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-B8cyqKk-.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-DmeW7Zz3.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-DrTyGbVD.js +0 -1
- package/dist/gateway/static/root/assets/goals-config-api-CxCWGIBB.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-DV1bJhIh.js +0 -2
- package/dist/gateway/static/root/assets/goals-settings-9DrfOkP5.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-KaDpZrv0.js +0 -1
- package/dist/gateway/static/root/assets/index-C2F0Clvm.js +0 -256
- package/dist/gateway/static/root/assets/index-COQSX5d_.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-C9dpiNTF.js +0 -2
- package/dist/gateway/static/root/assets/messages-DmnbiNxU.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-zdCdmBmH.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-MpGeFfPt.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-DYCM3yd2.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-Cu0ElRnS.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-DakNaUjZ.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DYKjt7L9.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CcGHDsz1.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CuFdeKNu.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-0AJoUvxi.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-D6a_hEk7.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-BtsuETKF.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-CcEFT7S9.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BcN_RuTD.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-BbRZZZA5.js +0 -2
- package/dist/gateway/static/root/assets/use-channel-catalog-C6vrxdzZ.js +0 -1
- package/dist/gateway/static/root/assets/user-profile-settings-panel-DZ0nKMgj.js +0 -1
- package/dist/gateway/static/root/assets/vendor-codemirror-BvNgyE1Q.js +0 -45
- package/dist/gateway/static/root/assets/voice-api-key-field-2QKflCx8.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-DfJnuWq1.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-BJwwFTm_.js +0 -18
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { createMobileActivityEvent, disableMobileDeviceForPushToken, listEnabledMobileDevices } from "./notification-store.js";
|
|
4
|
+
//#region src/mobile/notification-service.ts
|
|
5
|
+
init_logger();
|
|
6
|
+
const log = createLogger("MobileNotifications");
|
|
7
|
+
const EXPO_PUSH_URL = "https://exp.host/--/api/v2/push/send";
|
|
8
|
+
function shouldDeliver(type, preferences) {
|
|
9
|
+
if (type === "goal.needs_input") return preferences.needsInput;
|
|
10
|
+
if (type === "goal.blocked") return preferences.failed;
|
|
11
|
+
if (type === "automation.failed") return preferences.automationFailed;
|
|
12
|
+
return preferences.completed;
|
|
13
|
+
}
|
|
14
|
+
function goalEvent(payload) {
|
|
15
|
+
if (!payload || typeof payload !== "object") return null;
|
|
16
|
+
const data = payload;
|
|
17
|
+
const goal = data.goal;
|
|
18
|
+
const goalId = typeof goal?.id === "string" ? goal.id : typeof data.goalId === "string" ? data.goalId : "";
|
|
19
|
+
const status = typeof data.status === "string" ? data.status : "";
|
|
20
|
+
if (!goalId || ![
|
|
21
|
+
"needs_input",
|
|
22
|
+
"blocked",
|
|
23
|
+
"done"
|
|
24
|
+
].includes(status)) return null;
|
|
25
|
+
const type = status === "needs_input" ? "goal.needs_input" : status === "blocked" ? "goal.blocked" : "goal.completed";
|
|
26
|
+
const sessionKey = typeof goal?.activeSessionKey === "string" ? goal.activeSessionKey : "";
|
|
27
|
+
const route = sessionKey ? `/chat/${encodeURIComponent(sessionKey)}` : "/";
|
|
28
|
+
return {
|
|
29
|
+
type,
|
|
30
|
+
entity: {
|
|
31
|
+
kind: "goal",
|
|
32
|
+
id: goalId
|
|
33
|
+
},
|
|
34
|
+
priority: type === "goal.needs_input" || type === "goal.blocked" ? "high" : "normal",
|
|
35
|
+
title: type === "goal.needs_input" ? "Action needed" : type === "goal.blocked" ? "Goal blocked" : "Goal completed",
|
|
36
|
+
body: typeof goal?.title === "string" ? goal.title.slice(0, 120) : void 0,
|
|
37
|
+
deepLink: route,
|
|
38
|
+
payload: {
|
|
39
|
+
route,
|
|
40
|
+
goalId,
|
|
41
|
+
eventType: type
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function automationEvent(payload) {
|
|
46
|
+
if (!payload || typeof payload !== "object") return null;
|
|
47
|
+
const run = payload.run;
|
|
48
|
+
if (!run || run.status !== "failed" && run.status !== "timeout" && run.status !== "succeeded") return null;
|
|
49
|
+
const type = run.status === "succeeded" ? "automation.completed" : "automation.failed";
|
|
50
|
+
return {
|
|
51
|
+
type,
|
|
52
|
+
entity: {
|
|
53
|
+
kind: "automation",
|
|
54
|
+
id: run.automationId
|
|
55
|
+
},
|
|
56
|
+
priority: type === "automation.failed" ? "high" : "normal",
|
|
57
|
+
title: type === "automation.failed" ? "Automation failed" : "Automation completed",
|
|
58
|
+
body: run.automationName.slice(0, 120),
|
|
59
|
+
deepLink: "/automation",
|
|
60
|
+
payload: {
|
|
61
|
+
route: "/automation",
|
|
62
|
+
automationId: run.automationId,
|
|
63
|
+
runId: run.id,
|
|
64
|
+
eventType: type
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** Converts gateway domain events into a portable mobile activity and push payload. */
|
|
69
|
+
function mobileNotificationEventFromGatewayEvent(type, payload) {
|
|
70
|
+
if (type === "goal.status.updated") return goalEvent(payload);
|
|
71
|
+
if (type === "automation.run.completed") return automationEvent(payload);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
async function sendExpoPush(token, event) {
|
|
75
|
+
const response = await fetch(EXPO_PUSH_URL, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: {
|
|
78
|
+
"content-type": "application/json",
|
|
79
|
+
accept: "application/json"
|
|
80
|
+
},
|
|
81
|
+
body: JSON.stringify({
|
|
82
|
+
to: token,
|
|
83
|
+
title: event.title,
|
|
84
|
+
body: event.body,
|
|
85
|
+
sound: event.priority === "high" ? "default" : void 0,
|
|
86
|
+
priority: event.priority,
|
|
87
|
+
data: {
|
|
88
|
+
eventId: event.id,
|
|
89
|
+
...event.payload
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) throw new Error(`Expo push request failed (${response.status})`);
|
|
94
|
+
const result = await response.json().catch(() => null);
|
|
95
|
+
const item = Array.isArray(result?.data) ? result?.data[0] : result?.data;
|
|
96
|
+
if (item?.status === "error") {
|
|
97
|
+
if (item.details?.error === "DeviceNotRegistered") {
|
|
98
|
+
disableMobileDeviceForPushToken(token);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
throw new Error(`Expo push rejected: ${item.details?.error ?? "unknown error"}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
var MobileNotificationService = class {
|
|
105
|
+
sent = /* @__PURE__ */ new Set();
|
|
106
|
+
handleGatewayEvent(type, payload) {
|
|
107
|
+
const event = mobileNotificationEventFromGatewayEvent(type, payload);
|
|
108
|
+
if (!event) return;
|
|
109
|
+
const dedupeKey = `${event.type}:${event.entity.kind}:${event.entity.id}:${JSON.stringify(event.payload)}`;
|
|
110
|
+
if (this.sent.has(dedupeKey)) return;
|
|
111
|
+
this.sent.add(dedupeKey);
|
|
112
|
+
this.deliver(event).catch((err) => {
|
|
113
|
+
log.warn({
|
|
114
|
+
err,
|
|
115
|
+
eventType: event.type,
|
|
116
|
+
entityId: event.entity.id
|
|
117
|
+
}, "Mobile notification delivery failed");
|
|
118
|
+
}).finally(() => this.sent.delete(dedupeKey));
|
|
119
|
+
}
|
|
120
|
+
async deliver(input) {
|
|
121
|
+
const event = createMobileActivityEvent(input);
|
|
122
|
+
const devices = listEnabledMobileDevices().filter((device) => shouldDeliver(event.type, device.preferences));
|
|
123
|
+
await Promise.all(devices.map(async (device) => {
|
|
124
|
+
try {
|
|
125
|
+
await sendExpoPush(device.pushToken, event);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
log.warn({
|
|
128
|
+
err,
|
|
129
|
+
eventId: event.id,
|
|
130
|
+
deviceId: device.id
|
|
131
|
+
}, "Mobile push request failed");
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
//#endregion
|
|
137
|
+
export { MobileNotificationService, mobileNotificationEventFromGatewayEvent };
|
|
138
|
+
|
|
139
|
+
//# sourceMappingURL=notification-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-service.js","names":[],"sources":["../../../src/mobile/notification-service.ts"],"sourcesContent":["import { createLogger } from '../utils/logger.js';\nimport type { AutomationRun } from '../automations/domain/types.js';\n\nimport {\n createMobileActivityEvent,\n disableMobileDeviceForPushToken,\n listEnabledMobileDevices,\n} from './notification-store.js';\nimport type {\n MobileActivityEvent,\n MobileNotificationEventType,\n} from './notification-types.js';\n\nconst log = createLogger('MobileNotifications');\nconst EXPO_PUSH_URL = 'https://exp.host/--/api/v2/push/send';\n\ntype GoalPayload = {\n goal?: { id?: unknown; title?: unknown; activeSessionKey?: unknown };\n goalId?: unknown;\n status?: unknown;\n};\n\ntype ExpoPushResult = { status?: string; details?: { error?: string } };\n\nfunction shouldDeliver(type: MobileNotificationEventType, preferences: {\n needsInput: boolean;\n failed: boolean;\n completed: boolean;\n automationFailed: boolean;\n}): boolean {\n if (type === 'goal.needs_input') return preferences.needsInput;\n if (type === 'goal.blocked') return preferences.failed;\n if (type === 'automation.failed') return preferences.automationFailed;\n return preferences.completed;\n}\n\nfunction goalEvent(payload: unknown): Omit<MobileActivityEvent, 'id' | 'createdAt'> | null {\n if (!payload || typeof payload !== 'object') return null;\n const data = payload as GoalPayload;\n const goal = data.goal;\n const goalId = typeof goal?.id === 'string' ? goal.id : typeof data.goalId === 'string' ? data.goalId : '';\n const status = typeof data.status === 'string' ? data.status : '';\n if (!goalId || !['needs_input', 'blocked', 'done'].includes(status)) return null;\n const type: MobileNotificationEventType = status === 'needs_input'\n ? 'goal.needs_input'\n : status === 'blocked'\n ? 'goal.blocked'\n : 'goal.completed';\n const sessionKey = typeof goal?.activeSessionKey === 'string' ? goal.activeSessionKey : '';\n const route = sessionKey ? `/chat/${encodeURIComponent(sessionKey)}` : '/';\n return {\n type,\n entity: { kind: 'goal', id: goalId },\n priority: type === 'goal.needs_input' || type === 'goal.blocked' ? 'high' : 'normal',\n title: type === 'goal.needs_input' ? 'Action needed' : type === 'goal.blocked' ? 'Goal blocked' : 'Goal completed',\n body: typeof goal?.title === 'string' ? goal.title.slice(0, 120) : undefined,\n deepLink: route,\n payload: { route, goalId, eventType: type },\n };\n}\n\nfunction automationEvent(payload: unknown): Omit<MobileActivityEvent, 'id' | 'createdAt'> | null {\n if (!payload || typeof payload !== 'object') return null;\n const run = (payload as { run?: AutomationRun }).run;\n if (!run || (run.status !== 'failed' && run.status !== 'timeout' && run.status !== 'succeeded')) return null;\n const type: MobileNotificationEventType = run.status === 'succeeded'\n ? 'automation.completed'\n : 'automation.failed';\n return {\n type,\n entity: { kind: 'automation', id: run.automationId },\n priority: type === 'automation.failed' ? 'high' : 'normal',\n title: type === 'automation.failed' ? 'Automation failed' : 'Automation completed',\n body: run.automationName.slice(0, 120),\n deepLink: '/automation',\n payload: { route: '/automation', automationId: run.automationId, runId: run.id, eventType: type },\n };\n}\n\n/** Converts gateway domain events into a portable mobile activity and push payload. */\nexport function mobileNotificationEventFromGatewayEvent(\n type: string,\n payload: unknown,\n): Omit<MobileActivityEvent, 'id' | 'createdAt'> | null {\n if (type === 'goal.status.updated') return goalEvent(payload);\n if (type === 'automation.run.completed') return automationEvent(payload);\n return null;\n}\n\nasync function sendExpoPush(token: string, event: MobileActivityEvent): Promise<void> {\n const response = await fetch(EXPO_PUSH_URL, {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'application/json' },\n body: JSON.stringify({\n to: token,\n title: event.title,\n body: event.body,\n sound: event.priority === 'high' ? 'default' : undefined,\n priority: event.priority,\n data: { eventId: event.id, ...event.payload },\n }),\n });\n if (!response.ok) throw new Error(`Expo push request failed (${response.status})`);\n const result = await response.json().catch(() => null) as { data?: ExpoPushResult | ExpoPushResult[] } | null;\n const item = Array.isArray(result?.data) ? result?.data[0] : result?.data;\n if (item?.status === 'error') {\n if (item.details?.error === 'DeviceNotRegistered') {\n disableMobileDeviceForPushToken(token);\n return;\n }\n throw new Error(`Expo push rejected: ${item.details?.error ?? 'unknown error'}`);\n }\n}\n\nexport class MobileNotificationService {\n private readonly sent = new Set<string>();\n\n handleGatewayEvent(type: string, payload: unknown): void {\n const event = mobileNotificationEventFromGatewayEvent(type, payload);\n if (!event) return;\n const dedupeKey = `${event.type}:${event.entity.kind}:${event.entity.id}:${JSON.stringify(event.payload)}`;\n if (this.sent.has(dedupeKey)) return;\n this.sent.add(dedupeKey);\n void this.deliver(event)\n .catch((err) => {\n log.warn({ err, eventType: event.type, entityId: event.entity.id }, 'Mobile notification delivery failed');\n })\n .finally(() => this.sent.delete(dedupeKey));\n }\n\n private async deliver(input: Omit<MobileActivityEvent, 'id' | 'createdAt'>): Promise<void> {\n const event = createMobileActivityEvent(input);\n const devices = listEnabledMobileDevices().filter((device) => shouldDeliver(event.type, device.preferences));\n await Promise.all(devices.map(async (device) => {\n try {\n await sendExpoPush(device.pushToken, event);\n } catch (err) {\n log.warn({ err, eventId: event.id, deviceId: device.id }, 'Mobile push request failed');\n }\n }));\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type MobileActivityEvent, type MobileDevice, type MobileNotificationPermission, type MobileNotificationPreferences, type MobilePlatform } from './notification-types.js';
|
|
2
|
+
export type RegisterMobileDeviceInput = {
|
|
3
|
+
id: string;
|
|
4
|
+
platform: MobilePlatform;
|
|
5
|
+
pushToken: string;
|
|
6
|
+
permissions: MobileNotificationPermission;
|
|
7
|
+
preferences?: Partial<MobileNotificationPreferences>;
|
|
8
|
+
appVersion?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function registerMobileDevice(input: RegisterMobileDeviceInput): MobileDevice;
|
|
11
|
+
export declare function getMobileDevice(deviceId: string): MobileDevice | null;
|
|
12
|
+
export declare function listEnabledMobileDevices(): MobileDevice[];
|
|
13
|
+
export declare function updateMobileDevicePreferences(deviceId: string, patch: Partial<MobileNotificationPreferences>): MobileDevice | null;
|
|
14
|
+
export declare function removeMobileDevice(deviceId: string): boolean;
|
|
15
|
+
export declare function disableMobileDeviceForPushToken(pushToken: string): void;
|
|
16
|
+
export type CreateMobileActivityEventInput = Omit<MobileActivityEvent, 'id' | 'createdAt'> & {
|
|
17
|
+
id?: string;
|
|
18
|
+
createdAt?: number;
|
|
19
|
+
};
|
|
20
|
+
export declare function createMobileActivityEvent(input: CreateMobileActivityEventInput): MobileActivityEvent;
|
|
21
|
+
export declare function listMobileActivityEvents(options?: {
|
|
22
|
+
cursor?: number;
|
|
23
|
+
limit?: number;
|
|
24
|
+
}): {
|
|
25
|
+
items: MobileActivityEvent[];
|
|
26
|
+
nextCursor: number | null;
|
|
27
|
+
};
|
|
28
|
+
export declare function acknowledgeMobileActivityEvent(eventId: string, deviceId: string): boolean;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
|
|
2
|
+
import { DEFAULT_MOBILE_NOTIFICATION_PREFERENCES } from "./notification-types.js";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
//#region src/mobile/notification-store.ts
|
|
5
|
+
function parseJson(raw, fallback) {
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(raw);
|
|
8
|
+
} catch {
|
|
9
|
+
return fallback;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function normalizePreferences(input) {
|
|
13
|
+
return {
|
|
14
|
+
needsInput: input?.needsInput ?? DEFAULT_MOBILE_NOTIFICATION_PREFERENCES.needsInput,
|
|
15
|
+
failed: input?.failed ?? DEFAULT_MOBILE_NOTIFICATION_PREFERENCES.failed,
|
|
16
|
+
completed: input?.completed ?? DEFAULT_MOBILE_NOTIFICATION_PREFERENCES.completed,
|
|
17
|
+
automationFailed: input?.automationFailed ?? DEFAULT_MOBILE_NOTIFICATION_PREFERENCES.automationFailed
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function deviceFromRow(row) {
|
|
21
|
+
return {
|
|
22
|
+
id: row.device_id,
|
|
23
|
+
platform: row.platform === "android" ? "android" : "ios",
|
|
24
|
+
pushToken: row.push_token,
|
|
25
|
+
enabled: row.enabled !== 0,
|
|
26
|
+
permissions: row.permissions === "granted" || row.permissions === "denied" ? row.permissions : "unknown",
|
|
27
|
+
preferences: normalizePreferences(parseJson(row.preferences_json, {})),
|
|
28
|
+
appVersion: row.app_version ?? void 0,
|
|
29
|
+
lastSeenAt: row.last_seen_at,
|
|
30
|
+
createdAt: row.created_at,
|
|
31
|
+
updatedAt: row.updated_at
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function activityFromRow(row) {
|
|
35
|
+
return {
|
|
36
|
+
id: row.event_id,
|
|
37
|
+
type: row.event_type,
|
|
38
|
+
entity: {
|
|
39
|
+
kind: row.entity_kind,
|
|
40
|
+
id: row.entity_id
|
|
41
|
+
},
|
|
42
|
+
priority: row.priority,
|
|
43
|
+
title: row.title,
|
|
44
|
+
body: row.body ?? void 0,
|
|
45
|
+
deepLink: row.deep_link,
|
|
46
|
+
payload: parseJson(row.payload_json, {}),
|
|
47
|
+
createdAt: row.created_at
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function registerMobileDevice(input) {
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
const preferences = input.preferences ? normalizePreferences(input.preferences) : getMobileDevice(input.id)?.preferences ?? normalizePreferences();
|
|
53
|
+
runSqliteWriteTransaction((db) => {
|
|
54
|
+
db.prepare(`DELETE FROM mobile_devices
|
|
55
|
+
WHERE push_provider = 'expo' AND push_token = ? AND device_id <> ?`).run(input.pushToken, input.id);
|
|
56
|
+
db.prepare(`INSERT INTO mobile_devices (
|
|
57
|
+
device_id, platform, push_token, permissions, preferences_json,
|
|
58
|
+
app_version, last_seen_at, created_at, updated_at
|
|
59
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
60
|
+
ON CONFLICT(device_id) DO UPDATE SET
|
|
61
|
+
platform = excluded.platform,
|
|
62
|
+
push_token = excluded.push_token,
|
|
63
|
+
enabled = 1,
|
|
64
|
+
permissions = excluded.permissions,
|
|
65
|
+
preferences_json = excluded.preferences_json,
|
|
66
|
+
app_version = excluded.app_version,
|
|
67
|
+
last_seen_at = excluded.last_seen_at,
|
|
68
|
+
updated_at = excluded.updated_at`).run(input.id, input.platform, input.pushToken, input.permissions, JSON.stringify(preferences), input.appVersion?.trim() || null, now, now, now);
|
|
69
|
+
});
|
|
70
|
+
return getMobileDevice(input.id);
|
|
71
|
+
}
|
|
72
|
+
function getMobileDevice(deviceId) {
|
|
73
|
+
const row = getSqliteDatabase().prepare(`SELECT * FROM mobile_devices WHERE device_id = ?`).get(deviceId);
|
|
74
|
+
return row ? deviceFromRow(row) : null;
|
|
75
|
+
}
|
|
76
|
+
function listEnabledMobileDevices() {
|
|
77
|
+
return getSqliteDatabase().prepare(`SELECT * FROM mobile_devices WHERE enabled = 1 AND permissions = 'granted' ORDER BY updated_at DESC`).all().map(deviceFromRow);
|
|
78
|
+
}
|
|
79
|
+
function updateMobileDevicePreferences(deviceId, patch) {
|
|
80
|
+
const current = getMobileDevice(deviceId);
|
|
81
|
+
if (!current) return null;
|
|
82
|
+
const preferences = normalizePreferences({
|
|
83
|
+
...current.preferences,
|
|
84
|
+
...patch
|
|
85
|
+
});
|
|
86
|
+
runSqliteWriteTransaction((db) => {
|
|
87
|
+
db.prepare(`UPDATE mobile_devices SET preferences_json = ?, updated_at = ? WHERE device_id = ?`).run(JSON.stringify(preferences), Date.now(), deviceId);
|
|
88
|
+
});
|
|
89
|
+
return getMobileDevice(deviceId);
|
|
90
|
+
}
|
|
91
|
+
function removeMobileDevice(deviceId) {
|
|
92
|
+
return runSqliteWriteTransaction((db) => db.prepare(`DELETE FROM mobile_devices WHERE device_id = ?`).run(deviceId).changes > 0);
|
|
93
|
+
}
|
|
94
|
+
function disableMobileDeviceForPushToken(pushToken) {
|
|
95
|
+
runSqliteWriteTransaction((db) => {
|
|
96
|
+
db.prepare(`UPDATE mobile_devices SET enabled = 0, updated_at = ? WHERE push_token = ?`).run(Date.now(), pushToken);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function createMobileActivityEvent(input) {
|
|
100
|
+
const event = {
|
|
101
|
+
...input,
|
|
102
|
+
id: input.id ?? randomUUID(),
|
|
103
|
+
createdAt: input.createdAt ?? Date.now()
|
|
104
|
+
};
|
|
105
|
+
runSqliteWriteTransaction((db) => {
|
|
106
|
+
db.prepare(`INSERT INTO mobile_activity_events (
|
|
107
|
+
event_id, event_type, entity_kind, entity_id, priority, title, body,
|
|
108
|
+
deep_link, payload_json, created_at
|
|
109
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(event.id, event.type, event.entity.kind, event.entity.id, event.priority, event.title, event.body ?? null, event.deepLink, JSON.stringify(event.payload), event.createdAt);
|
|
110
|
+
});
|
|
111
|
+
return event;
|
|
112
|
+
}
|
|
113
|
+
function listMobileActivityEvents(options) {
|
|
114
|
+
const limit = Math.max(1, Math.min(100, options?.limit ?? 50));
|
|
115
|
+
const cursor = options?.cursor;
|
|
116
|
+
const items = (cursor == null ? getSqliteDatabase().prepare(`SELECT * FROM mobile_activity_events ORDER BY created_at DESC LIMIT ?`).all(limit) : getSqliteDatabase().prepare(`SELECT * FROM mobile_activity_events WHERE created_at < ? ORDER BY created_at DESC LIMIT ?`).all(cursor, limit)).map(activityFromRow);
|
|
117
|
+
return {
|
|
118
|
+
items,
|
|
119
|
+
nextCursor: items.length === limit ? items[items.length - 1].createdAt : null
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function acknowledgeMobileActivityEvent(eventId, deviceId) {
|
|
123
|
+
if (!getMobileDevice(deviceId)) return false;
|
|
124
|
+
if (!getSqliteDatabase().prepare(`SELECT 1 FROM mobile_activity_events WHERE event_id = ?`).get(eventId)) return false;
|
|
125
|
+
runSqliteWriteTransaction((db) => {
|
|
126
|
+
db.prepare(`INSERT OR REPLACE INTO mobile_activity_acknowledgements (event_id, device_id, acknowledged_at)
|
|
127
|
+
VALUES (?, ?, ?)`).run(eventId, deviceId, Date.now());
|
|
128
|
+
});
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
132
|
+
export { acknowledgeMobileActivityEvent, createMobileActivityEvent, disableMobileDeviceForPushToken, getMobileDevice, listEnabledMobileDevices, listMobileActivityEvents, registerMobileDevice, removeMobileDevice, updateMobileDevicePreferences };
|
|
133
|
+
|
|
134
|
+
//# sourceMappingURL=notification-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-store.js","names":[],"sources":["../../../src/mobile/notification-store.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { getSqliteDatabase, runSqliteWriteTransaction } from '../storage/sqlite/transaction.js';\n\nimport {\n DEFAULT_MOBILE_NOTIFICATION_PREFERENCES,\n type MobileActivityEvent,\n type MobileDevice,\n type MobileNotificationPermission,\n type MobileNotificationPreferences,\n type MobilePlatform,\n} from './notification-types.js';\n\ntype MobileDeviceRow = {\n device_id: string;\n platform: string;\n push_token: string;\n enabled: number;\n permissions: string;\n preferences_json: string;\n app_version: string | null;\n last_seen_at: number;\n created_at: number;\n updated_at: number;\n};\n\ntype MobileActivityEventRow = {\n event_id: string;\n event_type: MobileActivityEvent['type'];\n entity_kind: MobileActivityEvent['entity']['kind'];\n entity_id: string;\n priority: MobileActivityEvent['priority'];\n title: string;\n body: string | null;\n deep_link: string;\n payload_json: string;\n created_at: number;\n};\n\nfunction parseJson<T>(raw: string, fallback: T): T {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n}\n\nfunction normalizePreferences(input?: Partial<MobileNotificationPreferences>): MobileNotificationPreferences {\n return {\n needsInput: input?.needsInput ?? DEFAULT_MOBILE_NOTIFICATION_PREFERENCES.needsInput,\n failed: input?.failed ?? DEFAULT_MOBILE_NOTIFICATION_PREFERENCES.failed,\n completed: input?.completed ?? DEFAULT_MOBILE_NOTIFICATION_PREFERENCES.completed,\n automationFailed: input?.automationFailed ?? DEFAULT_MOBILE_NOTIFICATION_PREFERENCES.automationFailed,\n };\n}\n\nfunction deviceFromRow(row: MobileDeviceRow): MobileDevice {\n return {\n id: row.device_id,\n platform: row.platform === 'android' ? 'android' : 'ios',\n pushToken: row.push_token,\n enabled: row.enabled !== 0,\n permissions: row.permissions === 'granted' || row.permissions === 'denied' ? row.permissions : 'unknown',\n preferences: normalizePreferences(parseJson<Partial<MobileNotificationPreferences>>(row.preferences_json, {})),\n appVersion: row.app_version ?? undefined,\n lastSeenAt: row.last_seen_at,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nfunction activityFromRow(row: MobileActivityEventRow): MobileActivityEvent {\n return {\n id: row.event_id,\n type: row.event_type,\n entity: { kind: row.entity_kind, id: row.entity_id },\n priority: row.priority,\n title: row.title,\n body: row.body ?? undefined,\n deepLink: row.deep_link,\n payload: parseJson<Record<string, unknown>>(row.payload_json, {}),\n createdAt: row.created_at,\n };\n}\n\nexport type RegisterMobileDeviceInput = {\n id: string;\n platform: MobilePlatform;\n pushToken: string;\n permissions: MobileNotificationPermission;\n preferences?: Partial<MobileNotificationPreferences>;\n appVersion?: string;\n};\n\nexport function registerMobileDevice(input: RegisterMobileDeviceInput): MobileDevice {\n const now = Date.now();\n const preferences = input.preferences\n ? normalizePreferences(input.preferences)\n : getMobileDevice(input.id)?.preferences ?? normalizePreferences();\n runSqliteWriteTransaction((db) => {\n // An Expo token can rotate or be restored onto a new installation id. Keep one\n // active device record per token so the unique index cannot reject a re-register.\n db.prepare(\n `DELETE FROM mobile_devices\n WHERE push_provider = 'expo' AND push_token = ? AND device_id <> ?`,\n ).run(input.pushToken, input.id);\n db.prepare(\n `INSERT INTO mobile_devices (\n device_id, platform, push_token, permissions, preferences_json,\n app_version, last_seen_at, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(device_id) DO UPDATE SET\n platform = excluded.platform,\n push_token = excluded.push_token,\n enabled = 1,\n permissions = excluded.permissions,\n preferences_json = excluded.preferences_json,\n app_version = excluded.app_version,\n last_seen_at = excluded.last_seen_at,\n updated_at = excluded.updated_at`,\n ).run(\n input.id,\n input.platform,\n input.pushToken,\n input.permissions,\n JSON.stringify(preferences),\n input.appVersion?.trim() || null,\n now,\n now,\n now,\n );\n });\n return getMobileDevice(input.id)!;\n}\n\nexport function getMobileDevice(deviceId: string): MobileDevice | null {\n const row = getSqliteDatabase()\n .prepare(`SELECT * FROM mobile_devices WHERE device_id = ?`)\n .get(deviceId) as MobileDeviceRow | undefined;\n return row ? deviceFromRow(row) : null;\n}\n\nexport function listEnabledMobileDevices(): MobileDevice[] {\n return (getSqliteDatabase()\n .prepare(`SELECT * FROM mobile_devices WHERE enabled = 1 AND permissions = 'granted' ORDER BY updated_at DESC`)\n .all() as MobileDeviceRow[]).map(deviceFromRow);\n}\n\nexport function updateMobileDevicePreferences(\n deviceId: string,\n patch: Partial<MobileNotificationPreferences>,\n): MobileDevice | null {\n const current = getMobileDevice(deviceId);\n if (!current) return null;\n const preferences = normalizePreferences({ ...current.preferences, ...patch });\n runSqliteWriteTransaction((db) => {\n db.prepare(`UPDATE mobile_devices SET preferences_json = ?, updated_at = ? WHERE device_id = ?`)\n .run(JSON.stringify(preferences), Date.now(), deviceId);\n });\n return getMobileDevice(deviceId);\n}\n\nexport function removeMobileDevice(deviceId: string): boolean {\n return runSqliteWriteTransaction((db) =>\n db.prepare(`DELETE FROM mobile_devices WHERE device_id = ?`).run(deviceId).changes > 0,\n );\n}\n\nexport function disableMobileDeviceForPushToken(pushToken: string): void {\n runSqliteWriteTransaction((db) => {\n db.prepare(`UPDATE mobile_devices SET enabled = 0, updated_at = ? WHERE push_token = ?`)\n .run(Date.now(), pushToken);\n });\n}\n\nexport type CreateMobileActivityEventInput = Omit<MobileActivityEvent, 'id' | 'createdAt'> & {\n id?: string;\n createdAt?: number;\n};\n\nexport function createMobileActivityEvent(input: CreateMobileActivityEventInput): MobileActivityEvent {\n const event: MobileActivityEvent = {\n ...input,\n id: input.id ?? randomUUID(),\n createdAt: input.createdAt ?? Date.now(),\n };\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO mobile_activity_events (\n event_id, event_type, entity_kind, entity_id, priority, title, body,\n deep_link, payload_json, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n event.id,\n event.type,\n event.entity.kind,\n event.entity.id,\n event.priority,\n event.title,\n event.body ?? null,\n event.deepLink,\n JSON.stringify(event.payload),\n event.createdAt,\n );\n });\n return event;\n}\n\nexport function listMobileActivityEvents(options?: { cursor?: number; limit?: number }): {\n items: MobileActivityEvent[];\n nextCursor: number | null;\n} {\n const limit = Math.max(1, Math.min(100, options?.limit ?? 50));\n const cursor = options?.cursor;\n const rows = (cursor == null\n ? getSqliteDatabase().prepare(`SELECT * FROM mobile_activity_events ORDER BY created_at DESC LIMIT ?`).all(limit)\n : getSqliteDatabase().prepare(`SELECT * FROM mobile_activity_events WHERE created_at < ? ORDER BY created_at DESC LIMIT ?`).all(cursor, limit)\n ) as MobileActivityEventRow[];\n const items = rows.map(activityFromRow);\n return { items, nextCursor: items.length === limit ? items[items.length - 1]!.createdAt : null };\n}\n\nexport function acknowledgeMobileActivityEvent(eventId: string, deviceId: string): boolean {\n if (!getMobileDevice(deviceId)) return false;\n const exists = getSqliteDatabase()\n .prepare(`SELECT 1 FROM mobile_activity_events WHERE event_id = ?`)\n .get(eventId);\n if (!exists) return false;\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT OR REPLACE INTO mobile_activity_acknowledgements (event_id, device_id, acknowledged_at)\n VALUES (?, ?, ?)`,\n ).run(eventId, deviceId, Date.now());\n });\n return true;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type MobilePlatform = 'ios' | 'android';
|
|
2
|
+
export type MobileNotificationPermission = 'granted' | 'denied' | 'unknown';
|
|
3
|
+
export type MobileNotificationPriority = 'normal' | 'high';
|
|
4
|
+
export type MobileNotificationEventType = 'goal.needs_input' | 'goal.blocked' | 'goal.completed' | 'automation.failed' | 'automation.completed';
|
|
5
|
+
export type MobileNotificationPreferences = {
|
|
6
|
+
needsInput: boolean;
|
|
7
|
+
failed: boolean;
|
|
8
|
+
completed: boolean;
|
|
9
|
+
automationFailed: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type MobileDevice = {
|
|
12
|
+
id: string;
|
|
13
|
+
platform: MobilePlatform;
|
|
14
|
+
pushToken: string;
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
permissions: MobileNotificationPermission;
|
|
17
|
+
preferences: MobileNotificationPreferences;
|
|
18
|
+
appVersion?: string;
|
|
19
|
+
lastSeenAt: number;
|
|
20
|
+
createdAt: number;
|
|
21
|
+
updatedAt: number;
|
|
22
|
+
};
|
|
23
|
+
export type MobileActivityEvent = {
|
|
24
|
+
id: string;
|
|
25
|
+
type: MobileNotificationEventType;
|
|
26
|
+
entity: {
|
|
27
|
+
kind: 'goal' | 'automation';
|
|
28
|
+
id: string;
|
|
29
|
+
};
|
|
30
|
+
priority: MobileNotificationPriority;
|
|
31
|
+
title: string;
|
|
32
|
+
body?: string;
|
|
33
|
+
deepLink: string;
|
|
34
|
+
payload: Record<string, unknown>;
|
|
35
|
+
createdAt: number;
|
|
36
|
+
};
|
|
37
|
+
export declare const DEFAULT_MOBILE_NOTIFICATION_PREFERENCES: MobileNotificationPreferences;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/mobile/notification-types.ts
|
|
2
|
+
const DEFAULT_MOBILE_NOTIFICATION_PREFERENCES = {
|
|
3
|
+
needsInput: true,
|
|
4
|
+
failed: true,
|
|
5
|
+
completed: false,
|
|
6
|
+
automationFailed: true
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { DEFAULT_MOBILE_NOTIFICATION_PREFERENCES };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=notification-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-types.js","names":[],"sources":["../../../src/mobile/notification-types.ts"],"sourcesContent":["export type MobilePlatform = 'ios' | 'android';\nexport type MobileNotificationPermission = 'granted' | 'denied' | 'unknown';\nexport type MobileNotificationPriority = 'normal' | 'high';\nexport type MobileNotificationEventType =\n | 'goal.needs_input'\n | 'goal.blocked'\n | 'goal.completed'\n | 'automation.failed'\n | 'automation.completed';\n\nexport type MobileNotificationPreferences = {\n needsInput: boolean;\n failed: boolean;\n completed: boolean;\n automationFailed: boolean;\n};\n\nexport type MobileDevice = {\n id: string;\n platform: MobilePlatform;\n pushToken: string;\n enabled: boolean;\n permissions: MobileNotificationPermission;\n preferences: MobileNotificationPreferences;\n appVersion?: string;\n lastSeenAt: number;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type MobileActivityEvent = {\n id: string;\n type: MobileNotificationEventType;\n entity: { kind: 'goal' | 'automation'; id: string };\n priority: MobileNotificationPriority;\n title: string;\n body?: string;\n deepLink: string;\n payload: Record<string, unknown>;\n createdAt: number;\n};\n\nexport const DEFAULT_MOBILE_NOTIFICATION_PREFERENCES: MobileNotificationPreferences = {\n needsInput: true,\n failed: true,\n completed: false,\n automationFailed: true,\n};\n"],"mappings":";AA0CA,MAAa,0CAAyE;CACpF,YAAY;CACZ,QAAQ;CACR,WAAW;CACX,kBAAkB;CACnB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS goal_contracts (
|
|
2
|
+
goal_id TEXT PRIMARY KEY,
|
|
3
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
4
|
+
objective TEXT NOT NULL,
|
|
5
|
+
scope_boundary TEXT,
|
|
6
|
+
evidence_plan_json TEXT NOT NULL DEFAULT '[]',
|
|
7
|
+
created_at INTEGER NOT NULL,
|
|
8
|
+
updated_at INTEGER NOT NULL,
|
|
9
|
+
FOREIGN KEY (goal_id) REFERENCES goals(goal_id) ON DELETE CASCADE
|
|
10
|
+
);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS mobile_devices (
|
|
2
|
+
device_id TEXT PRIMARY KEY,
|
|
3
|
+
platform TEXT NOT NULL,
|
|
4
|
+
push_token TEXT NOT NULL,
|
|
5
|
+
push_provider TEXT NOT NULL DEFAULT 'expo',
|
|
6
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
7
|
+
permissions TEXT NOT NULL DEFAULT 'unknown',
|
|
8
|
+
preferences_json TEXT NOT NULL DEFAULT '{}',
|
|
9
|
+
app_version TEXT,
|
|
10
|
+
last_seen_at INTEGER NOT NULL,
|
|
11
|
+
created_at INTEGER NOT NULL,
|
|
12
|
+
updated_at INTEGER NOT NULL
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_mobile_devices_push_token
|
|
16
|
+
ON mobile_devices(push_provider, push_token);
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_mobile_devices_enabled
|
|
18
|
+
ON mobile_devices(enabled, updated_at DESC);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS mobile_activity_events (
|
|
21
|
+
event_id TEXT PRIMARY KEY,
|
|
22
|
+
event_type TEXT NOT NULL,
|
|
23
|
+
entity_kind TEXT NOT NULL,
|
|
24
|
+
entity_id TEXT NOT NULL,
|
|
25
|
+
priority TEXT NOT NULL,
|
|
26
|
+
title TEXT NOT NULL,
|
|
27
|
+
body TEXT,
|
|
28
|
+
deep_link TEXT NOT NULL,
|
|
29
|
+
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
30
|
+
created_at INTEGER NOT NULL
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_mobile_activity_events_created
|
|
34
|
+
ON mobile_activity_events(created_at DESC);
|
|
35
|
+
|
|
36
|
+
CREATE TABLE IF NOT EXISTS mobile_activity_acknowledgements (
|
|
37
|
+
event_id TEXT NOT NULL,
|
|
38
|
+
device_id TEXT NOT NULL,
|
|
39
|
+
acknowledged_at INTEGER NOT NULL,
|
|
40
|
+
PRIMARY KEY (event_id, device_id),
|
|
41
|
+
FOREIGN KEY (event_id) REFERENCES mobile_activity_events(event_id) ON DELETE CASCADE,
|
|
42
|
+
FOREIGN KEY (device_id) REFERENCES mobile_devices(device_id) ON DELETE CASCADE
|
|
43
|
+
);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS goal_evidence_requirements (
|
|
2
|
+
requirement_id TEXT PRIMARY KEY,
|
|
3
|
+
goal_id TEXT NOT NULL,
|
|
4
|
+
text TEXT NOT NULL,
|
|
5
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
6
|
+
review_reason TEXT,
|
|
7
|
+
review_confidence REAL,
|
|
8
|
+
reviewed_by TEXT,
|
|
9
|
+
reviewed_at INTEGER,
|
|
10
|
+
requires_human_approval INTEGER NOT NULL DEFAULT 1,
|
|
11
|
+
created_at INTEGER NOT NULL,
|
|
12
|
+
updated_at INTEGER NOT NULL,
|
|
13
|
+
sort_order INTEGER NOT NULL,
|
|
14
|
+
UNIQUE(goal_id, text),
|
|
15
|
+
FOREIGN KEY (goal_id) REFERENCES goals(goal_id) ON DELETE CASCADE
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_goal_evidence_requirements_goal_order
|
|
19
|
+
ON goal_evidence_requirements(goal_id, sort_order ASC);
|
|
20
|
+
|
|
21
|
+
CREATE TABLE IF NOT EXISTS goal_evidence_requirement_links (
|
|
22
|
+
requirement_id TEXT NOT NULL,
|
|
23
|
+
evidence_id TEXT NOT NULL,
|
|
24
|
+
linked_by TEXT NOT NULL,
|
|
25
|
+
created_at INTEGER NOT NULL,
|
|
26
|
+
PRIMARY KEY (requirement_id, evidence_id),
|
|
27
|
+
FOREIGN KEY (requirement_id) REFERENCES goal_evidence_requirements(requirement_id) ON DELETE CASCADE,
|
|
28
|
+
FOREIGN KEY (evidence_id) REFERENCES goal_evidence(evidence_id) ON DELETE CASCADE
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_goal_evidence_requirement_links_evidence
|
|
32
|
+
ON goal_evidence_requirement_links(evidence_id);
|
|
33
|
+
|
|
34
|
+
INSERT OR IGNORE INTO goal_evidence_requirements (
|
|
35
|
+
requirement_id, goal_id, text, status, requires_human_approval, created_at, updated_at, sort_order
|
|
36
|
+
)
|
|
37
|
+
SELECT
|
|
38
|
+
lower(hex(randomblob(16))),
|
|
39
|
+
goal_contracts.goal_id,
|
|
40
|
+
json_each.value,
|
|
41
|
+
'pending',
|
|
42
|
+
1,
|
|
43
|
+
goal_contracts.created_at,
|
|
44
|
+
goal_contracts.updated_at,
|
|
45
|
+
CAST(json_each.key AS INTEGER) + 1
|
|
46
|
+
FROM goal_contracts, json_each(goal_contracts.evidence_plan_json)
|
|
47
|
+
WHERE json_valid(goal_contracts.evidence_plan_json) AND json_each.type = 'text';
|
|
@@ -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 = 28;
|
|
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 = 28;
|
|
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 ?? 28;
|
|
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 ?? 28;
|
|
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 = 28;\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 = 28;
|
|
23
23
|
|
|
24
24
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
25
25
|
|
|
@@ -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: 28 });
|
|
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 };
|