@xopcai/xopc 0.0.225 → 0.0.228
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-CtTYnku4.js → activity-store-M0nAY5XB.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-dizuqu_4.js → agent-avatar-dicebear-CjGZBs4C.js} +1 -1
- package/dist/gateway/static/root/assets/agents-B0NI4_NI.js +68 -0
- package/dist/gateway/static/root/assets/{api-CLRMz2BT.js → api-BywYxpaS.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-Cnk-DtQh.js → app-management-settings-panel--SjycrXk.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-wP0rogVI.js → appearance-settings-8G-TVUtg.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-2NiqD-YP.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-Cpzsm-DM.js → archive-plugin-7_DXaMTP.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Bd2OOoEK.js → attachment-load-Bx44zSpz.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-DNqhguyk.js → automations-page-CrKAHqc0.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-Q3g9cf0h.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-Dcma5HdI.js → binary-plugins-DjDwnHAQ.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-D-B8ThwK.js → block-editor-7aMOKoZM.js} +3 -3
- package/dist/gateway/static/root/assets/browser-settings-page-DTwPkmAC.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-BAPZIXrs.js → browser-workflow-inputs-8NC2qDRF.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DHtaSKEh.js → browser-workflows-page-DVLrWKz_.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-YcP4FbN7.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-zsZQ7im3.js → capability-presets-api-o0y9WgAI.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-AcPjHHia.js +3 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-Cp8iaaXp.js → channel-recipient-api-C5ABr73b.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-Ca94Q1D-.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-38FsOnR0.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-Dr6Rq2ln.js → chat-terminal-dock-BR-_7KC0.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-SGxfLTd6.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-BiXrpzmo.js → cron-expression-D8-c-Tkw.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BPuRtwKt.js → date-picker-kV-Jyl9J.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-BNC_W7wI.js → dependency-picker-CwKcrfGj.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-DzOpt5nI.js → desktop-pet-D9rnchu3.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BW0brCvH.js → desktop-pet-settings-CTs5WGzk.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-Baml0uTS.js → directory-picker-path-field-CCl0aaDm.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CBXyKmfS.js → extension-debug-page-Cau40SvC.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BBhcr_SZ.js → extension-page-BsJXdvIL.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-4rwWpN9_.js → extension-settings-page-qWqJyF7-.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-Dg-BlBe4.js → gateway-config-api-BI0SELXm.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Du0MvK9s.js → gateway-config-swr-BWGjnmDl.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-BOuYZOYe.js → gateway-settings-6ZdOIC7F.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-JbjcHCaN.js → gateway-startup-retry-B_zrtccP.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-KBwhXeFD.js +1 -0
- package/dist/gateway/static/root/assets/home-page-BA2M4CLi.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-G2tfPvKP.js → image-generation-api-YKP2me5Z.js} +1 -1
- package/dist/gateway/static/root/assets/index-BX0dz1JK.js +70 -0
- package/dist/gateway/static/root/assets/index-D_hrEKXM.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-L1Vtxgp9.js → keyboard-shortcuts-settings-kHtpnyEm.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-D2nkn09R.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page--thlkBLS.js → local-apps-page-BCXa0oUa.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-DqJz-cOR.js → locale-store-CXhjfe4q.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-D3sNst0K.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-p55fR4XO.js → management-settings-tHnlfOAQ.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-DwMcRlBR.js → markdown-split-BMLqHHr5.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-DD_PgVue.css → markdown-view-CLzTdVLW.css} +1 -1
- package/dist/gateway/static/root/assets/markdown-view-DvM5PWEH.js +201 -0
- package/dist/gateway/static/root/assets/{media-plugins-O6H3GZn7.js → media-plugins-DybwqTgv.js} +1 -1
- package/dist/gateway/static/root/assets/messages-BMdD0LWk.js +3 -0
- package/dist/gateway/static/root/assets/{notes-api-CrjQbmk1.js → notes-api-BFsOGYkd.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-miO9ig9C.js → notes-page-C24SfF6r.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-CTdZc3ov.js +4 -0
- package/dist/gateway/static/root/assets/{product-open-page-BOu07nXf.js → product-open-page-DBfCVlJq.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-COHaEpbA.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-lMnST7D_.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-Bf_HDLUJ.js → registry-api-BFZrVYfy.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BIRKBvO_.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DthuRqUH.js → runtime-tools-settings-panel-BPEGTip5.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-8W8PhXxa.js → schema-form-Dxlu60Td.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CATO9G3y.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-Cco_W41x.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-CrsKGYiG.js → settings-form-section-ChXh3Bwk.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-WJtI0AAq.js → settings-loading-skeleton-BCAUqIe2.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-PCjwRF47.js → settings-page-D25W9Okr.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-D65CwlNC.js → setup-status-panel-DsN7Z4Fl.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-BGtvLLeZ.js → share-preview-page-CRFnUaNb.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CAX0eNaP.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-Doy1gghe.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-C_npyryI.js → skills-page-Cl7jjTK7.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-C46Sd78k.js → skills-page.utils-BiCl4nb5.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-DomTLwki.js → system-settings-panel-BuESR7ZT.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-BRiy8NL3.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-Ce7wq__X.js → theme-store-DOdCjyuw.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-Do9mCRcY.js → use-autosave-Dg1mgJ_l.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-CqoADNKu.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-Bc5p-0tX.js → voice-api-key-field-BDNexlVR.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-BieqsmT1.js → work-discovery-overlay-BHTfeaWL.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DVj8iYvm.js → workflow-run-setup-panel-Cf_w-NZy.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-j0P-uECz.js +5 -0
- package/dist/gateway/static/root/index.html +12 -12
- package/dist/gateway/static/root/notification-sw.js +1 -1
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/notifications.js +56 -0
- package/dist/packages/gateway-contract/src/turn-outcome.js +114 -0
- package/dist/src/agent/agent-manager.d.ts +3 -1
- package/dist/src/agent/agent-manager.js +22 -5
- package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +1 -0
- package/dist/src/agent/lifecycle/timeout-wrapper.js +7 -6
- package/dist/src/agent/mcp/mcp-transport-config.d.ts +1 -1
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
- package/dist/src/agent/memory/understanding/service.js +1 -0
- package/dist/src/agent/memory/understanding/types.d.ts +1 -0
- package/dist/src/agent/orchestration/run-agent-turn-with-timeout.d.ts +2 -2
- package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +4 -4
- package/dist/src/agent/service.d.ts +2 -0
- package/dist/src/agent/service.js +6 -0
- package/dist/src/agent/skills/index.d.ts +22 -2
- package/dist/src/agent/skills/index.js +74 -32
- package/dist/src/agent/skills/skill-sources.d.ts +0 -1
- package/dist/src/agent/skills/skill-sources.js +1 -11
- package/dist/src/agent/tools/create-share-tool.js +14 -1
- package/dist/src/agent/tools/exec-command.js +3 -3
- package/dist/src/agent/tools/execute-code-tool.js +1 -1
- package/dist/src/agent/tools/executor.js +2 -2
- package/dist/src/agent/tools/image-generate-tool.js +12 -0
- package/dist/src/agent/tools/send-media.js +11 -0
- package/dist/src/agent/tools/xopc-use-tool.js +1 -1
- package/dist/src/cli/command-loaders.js +1 -0
- package/dist/src/cli/command-manifest.js +4 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/history.d.ts +1 -0
- package/dist/src/cli/commands/history.js +50 -0
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/connectors/connected-source-understanding.js +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/chat-stream/protocol.d.ts +3 -2
- package/dist/src/gateway/chat-stream/turn-outcome-collector.d.ts +16 -0
- package/dist/src/gateway/chat-stream/turn-outcome-collector.js +111 -0
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/static-ui.js +7 -5
- package/dist/src/gateway/hono/routes/connectors.js +18 -16
- package/dist/src/gateway/hono/routes/index.js +2 -0
- package/dist/src/gateway/hono/routes/mobile.js +18 -40
- package/dist/src/gateway/hono/routes/notifications.d.ts +3 -0
- package/dist/src/gateway/hono/routes/notifications.js +45 -0
- package/dist/src/gateway/hono/routes/project-skills.js +30 -2
- package/dist/src/gateway/hono/routes/sessions.js +31 -0
- package/dist/src/gateway/hono/routes/tasks.js +1 -1
- package/dist/src/gateway/hono/routes/voice.js +1 -1
- package/dist/src/gateway/hono/routes/you.js +52 -0
- package/dist/src/gateway/service/agent-runner.js +6 -2
- package/dist/src/gateway/service/run-gateway-agent.js +53 -1
- package/dist/src/gateway/service/sessions-api.d.ts +6 -0
- package/dist/src/gateway/service/sessions-api.js +60 -3
- package/dist/src/gateway/service.d.ts +2 -2
- package/dist/src/gateway/service.js +8 -7
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/history/ctx/exporter.d.ts +14 -0
- package/dist/src/history/ctx/exporter.js +99 -0
- package/dist/src/history/ctx/format.d.ts +25 -0
- package/dist/src/history/ctx/format.js +282 -0
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/knowledge/connected-understanding-pipeline.js +12 -3
- package/dist/src/knowledge/index.d.ts +0 -1
- package/dist/src/knowledge/index.js +1 -2
- package/dist/src/media/session-references.d.ts +6 -0
- package/dist/src/media/session-references.js +24 -3
- package/dist/src/notifications/device-store.d.ts +16 -0
- package/dist/src/notifications/device-store.js +96 -0
- package/dist/src/notifications/planner.d.ts +6 -0
- package/dist/src/notifications/planner.js +156 -0
- package/dist/src/notifications/service.d.ts +18 -0
- package/dist/src/notifications/service.js +184 -0
- package/dist/src/notifications/store.d.ts +53 -0
- package/dist/src/notifications/store.js +184 -0
- package/dist/src/notifications/types.d.ts +29 -0
- package/dist/src/notifications/types.js +14 -0
- package/dist/src/projects/project-skill-service.d.ts +28 -6
- package/dist/src/projects/project-skill-service.js +76 -29
- package/dist/src/session/client-history.d.ts +3 -1
- package/dist/src/session/client-history.js +13 -0
- package/dist/src/session/index.d.ts +1 -1
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/manager.js +6 -0
- package/dist/src/session/store.d.ts +15 -0
- package/dist/src/session/store.js +58 -0
- package/dist/src/storage/sqlite/index.d.ts +2 -1
- package/dist/src/storage/sqlite/index.js +3 -2
- package/dist/src/storage/sqlite/migrations/135_user_people.sql +59 -0
- package/dist/src/storage/sqlite/migrations/136_product_notifications.sql +79 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/session-input-repository.d.ts +5 -0
- package/dist/src/storage/sqlite/session-input-repository.js +9 -1
- package/dist/src/storage/sqlite/user-people-repository.d.ts +32 -0
- package/dist/src/storage/sqlite/user-people-repository.js +246 -0
- package/dist/src/tasks/index.js +2 -2
- package/dist/src/tasks/task-application-service.js +42 -6
- package/dist/src/tasks/task-change-events.d.ts +9 -0
- package/dist/src/tasks/task-change-events.js +17 -1
- package/dist/src/tasks/task-outbox-dispatcher.js +5 -1
- package/dist/src/tasks/task-run-dispatcher.js +4 -2
- package/dist/src/tasks/task-run-repository.js +13 -0
- package/dist/src/user-context/relationships/indexer.d.ts +13 -0
- package/dist/src/user-context/relationships/indexer.js +185 -0
- package/dist/src/user-context/relationships/service.d.ts +22 -0
- package/dist/src/user-context/relationships/service.js +50 -0
- package/dist/src/user-context/relationships/types.d.ts +55 -0
- package/dist/src/user-context/relationships/types.js +10 -0
- package/dist/src/user-context/sources/repository.d.ts +1 -1
- package/dist/src/user-context/sources/repository.js +8 -2
- package/dist/src/work-discovery/service.js +1 -1
- package/package.json +2 -2
- package/dist/gateway/static/root/assets/agents-DeEEFZJ4.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-Db5YNHVM.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-CNT05YTb.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-UbDj3LIq.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-CiO152QS.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Bc_hRwfL.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-CFW7zBoT.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-5rNVq7iI.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DLBr5nre.js +0 -2
- package/dist/gateway/static/root/assets/heartbeat-settings-Dq4YAlSx.js +0 -1
- package/dist/gateway/static/root/assets/home-page-BIXkO0Ck.js +0 -1
- package/dist/gateway/static/root/assets/index-Csccu8sa.js +0 -74
- package/dist/gateway/static/root/assets/index-D3_xSYKd.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-D-eacBcO.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-BRCglHvd.js +0 -2
- package/dist/gateway/static/root/assets/markdown-view-CTB9u15e.js +0 -69
- package/dist/gateway/static/root/assets/mermaid-render-BbqDc_LQ.js +0 -134
- package/dist/gateway/static/root/assets/messages-CeydamsI.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-_13lmvmF.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-BStRkOQr.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CY03RxVr.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-B19llkld.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BDA2qbTd.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BONIDX4v.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-CdzVKrBl.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CsRWid5h.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-B6YFX7kK.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-CiCQA40E.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-AG04TTuH.js +0 -5
- package/dist/src/knowledge/people-graph.d.ts +0 -25
- package/dist/src/knowledge/people-graph.js +0 -92
- package/dist/src/mobile/notification-service.d.ts +0 -9
- package/dist/src/mobile/notification-service.js +0 -156
- package/dist/src/mobile/notification-store.d.ts +0 -28
- package/dist/src/mobile/notification-store.js +0 -132
- package/dist/src/mobile/notification-types.d.ts +0 -37
- package/dist/src/mobile/notification-types.js +0 -9
|
@@ -1,156 +0,0 @@
|
|
|
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 === "task.needs_input") return preferences.needsInput;
|
|
10
|
-
if (type === "task.blocked") return preferences.failed;
|
|
11
|
-
if (type === "automation.failed") return preferences.automationFailed;
|
|
12
|
-
if (type === "proactive.insight") return preferences.needsInput;
|
|
13
|
-
return preferences.completed;
|
|
14
|
-
}
|
|
15
|
-
function taskEvent(payload) {
|
|
16
|
-
if (!payload || typeof payload !== "object") return null;
|
|
17
|
-
const data = payload;
|
|
18
|
-
const task = data.task;
|
|
19
|
-
const taskId = typeof task?.id === "string" ? task.id : typeof data.taskId === "string" ? data.taskId : "";
|
|
20
|
-
if (!taskId) return null;
|
|
21
|
-
const type = data.reason === "blocked" ? "task.blocked" : typeof data.reason === "string" ? "task.needs_input" : data.to === "closed" && data.resolution === "done" ? "task.completed" : void 0;
|
|
22
|
-
if (!type) return null;
|
|
23
|
-
const route = `/tasks/${encodeURIComponent(taskId)}`;
|
|
24
|
-
return {
|
|
25
|
-
type,
|
|
26
|
-
entity: {
|
|
27
|
-
kind: "task",
|
|
28
|
-
id: taskId
|
|
29
|
-
},
|
|
30
|
-
priority: type === "task.needs_input" || type === "task.blocked" ? "high" : "normal",
|
|
31
|
-
title: type === "task.needs_input" ? "Action needed" : type === "task.blocked" ? "Task blocked" : "Task completed",
|
|
32
|
-
body: typeof task?.title === "string" ? task.title.slice(0, 120) : void 0,
|
|
33
|
-
deepLink: route,
|
|
34
|
-
payload: {
|
|
35
|
-
route,
|
|
36
|
-
taskId,
|
|
37
|
-
eventType: type
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
function automationEvent(payload) {
|
|
42
|
-
if (!payload || typeof payload !== "object") return null;
|
|
43
|
-
const event = payload;
|
|
44
|
-
if (event.notificationPolicy === "none") return null;
|
|
45
|
-
if (event.notificationPolicy === "attention" && event.requiresAttention !== true) return null;
|
|
46
|
-
const run = event.run;
|
|
47
|
-
if (!run || run.status !== "failed" && run.status !== "timeout" && run.status !== "succeeded") return null;
|
|
48
|
-
const type = run.status === "succeeded" ? "automation.completed" : "automation.failed";
|
|
49
|
-
const route = `/automations?automation=${encodeURIComponent(run.automationId)}&run=${encodeURIComponent(run.id)}`;
|
|
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: route,
|
|
60
|
-
payload: {
|
|
61
|
-
route,
|
|
62
|
-
automationId: run.automationId,
|
|
63
|
-
runId: run.id,
|
|
64
|
-
eventType: type
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
function proactiveInsightEvent(payload) {
|
|
69
|
-
if (!payload || typeof payload !== "object") return null;
|
|
70
|
-
const item = payload;
|
|
71
|
-
if (typeof item.id !== "string" || typeof item.insight?.id !== "string" || typeof item.insight.title !== "string") return null;
|
|
72
|
-
const route = `/inbox?item=${encodeURIComponent(item.id)}`;
|
|
73
|
-
return {
|
|
74
|
-
type: "proactive.insight",
|
|
75
|
-
entity: {
|
|
76
|
-
kind: "insight",
|
|
77
|
-
id: item.insight.id
|
|
78
|
-
},
|
|
79
|
-
priority: item.insight.urgency === "high" || item.insight.urgency === "critical" ? "high" : "normal",
|
|
80
|
-
title: item.insight.title.slice(0, 120),
|
|
81
|
-
body: typeof item.insight.summary === "string" ? item.insight.summary.slice(0, 180) : void 0,
|
|
82
|
-
deepLink: route,
|
|
83
|
-
payload: {
|
|
84
|
-
route,
|
|
85
|
-
inboxItemId: item.id,
|
|
86
|
-
eventType: "proactive.insight"
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
/** Converts gateway domain events into a portable mobile activity and push payload. */
|
|
91
|
-
function mobileNotificationEventFromGatewayEvent(type, payload) {
|
|
92
|
-
if (type === "task.attention_required.v2" || type === "task.phase_changed.v2") return taskEvent(payload);
|
|
93
|
-
if (type === "automation.run.completed") return automationEvent(payload);
|
|
94
|
-
if (type === "proactive.inbox.created") return proactiveInsightEvent(payload);
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
async function sendExpoPush(token, event) {
|
|
98
|
-
const response = await fetch(EXPO_PUSH_URL, {
|
|
99
|
-
method: "POST",
|
|
100
|
-
headers: {
|
|
101
|
-
"content-type": "application/json",
|
|
102
|
-
accept: "application/json"
|
|
103
|
-
},
|
|
104
|
-
body: JSON.stringify({
|
|
105
|
-
to: token,
|
|
106
|
-
title: event.title,
|
|
107
|
-
body: event.body,
|
|
108
|
-
sound: event.priority === "high" ? "default" : void 0,
|
|
109
|
-
priority: event.priority,
|
|
110
|
-
data: {
|
|
111
|
-
eventId: event.id,
|
|
112
|
-
...event.payload
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
});
|
|
116
|
-
if (!response.ok) throw new Error(`Expo push request failed (${response.status})`);
|
|
117
|
-
const result = await response.json().catch(() => null);
|
|
118
|
-
const item = Array.isArray(result?.data) ? result?.data[0] : result?.data;
|
|
119
|
-
if (item?.status === "error") {
|
|
120
|
-
if (item.details?.error === "DeviceNotRegistered") {
|
|
121
|
-
disableMobileDeviceForPushToken(token);
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
throw new Error(`Expo push rejected: ${item.details?.error ?? "unknown error"}`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
var MobileNotificationService = class {
|
|
128
|
-
sent = /* @__PURE__ */ new Set();
|
|
129
|
-
handleGatewayEvent(type, payload) {
|
|
130
|
-
this.deliverGatewayEvent(type, payload).catch((err) => {
|
|
131
|
-
log.warn({
|
|
132
|
-
err,
|
|
133
|
-
eventType: type
|
|
134
|
-
}, "Mobile notification delivery failed");
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
async deliverGatewayEvent(type, payload) {
|
|
138
|
-
const event = mobileNotificationEventFromGatewayEvent(type, payload);
|
|
139
|
-
if (!event) return;
|
|
140
|
-
const dedupeKey = `${event.type}:${event.entity.kind}:${event.entity.id}:${JSON.stringify(event.payload)}`;
|
|
141
|
-
if (this.sent.has(dedupeKey)) return;
|
|
142
|
-
this.sent.add(dedupeKey);
|
|
143
|
-
try {
|
|
144
|
-
await this.deliver(event);
|
|
145
|
-
} finally {
|
|
146
|
-
this.sent.delete(dedupeKey);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
async deliver(input) {
|
|
150
|
-
const event = createMobileActivityEvent(input);
|
|
151
|
-
const devices = listEnabledMobileDevices().filter((device) => shouldDeliver(event.type, device.preferences));
|
|
152
|
-
await Promise.all(devices.map((device) => sendExpoPush(device.pushToken, event)));
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
//#endregion
|
|
156
|
-
export { MobileNotificationService, mobileNotificationEventFromGatewayEvent };
|
|
@@ -1,28 +0,0 @@
|
|
|
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;
|
|
@@ -1,132 +0,0 @@
|
|
|
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 };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export type MobilePlatform = 'ios' | 'android';
|
|
2
|
-
export type MobileNotificationPermission = 'granted' | 'denied' | 'unknown';
|
|
3
|
-
export type MobileNotificationPriority = 'normal' | 'high';
|
|
4
|
-
export type MobileNotificationEventType = 'task.needs_input' | 'task.blocked' | 'task.completed' | 'automation.failed' | 'automation.completed' | 'proactive.insight';
|
|
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: 'task' | 'automation' | 'insight';
|
|
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;
|