@xopcai/xopc 0.0.227 → 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-BevwE16n.js → activity-store-M0nAY5XB.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BggVQrEZ.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-Bx_BpIt8.js → api-BywYxpaS.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BtKP9n2r.js → app-management-settings-panel--SjycrXk.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-BoH2NAUX.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-DnceUyxm.js → archive-plugin-7_DXaMTP.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Bh8_9gkr.js → attachment-load-Bx44zSpz.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-ZKeAAVxD.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-Cy9er6w-.js → binary-plugins-DjDwnHAQ.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-Cc0wWvNX.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-BS7rpLLl.js → browser-workflow-inputs-8NC2qDRF.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-BdBVUZXm.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-D1Lqz0Tt.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-CGuEl-l2.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-CdX_7aQh.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-BnSQc4Ek.js → cron-expression-D8-c-Tkw.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BbuG7zQ_.js → date-picker-kV-Jyl9J.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-snZeqOmG.js → dependency-picker-CwKcrfGj.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-DJQ8JoR1.js → desktop-pet-D9rnchu3.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-B9txsRtv.js → desktop-pet-settings-CTs5WGzk.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-D7WKWkNB.js → directory-picker-path-field-CCl0aaDm.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-D_7cOCj2.js → extension-debug-page-Cau40SvC.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Bwu47iUb.js → extension-page-BsJXdvIL.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-Dwg4dSZM.js → extension-settings-page-qWqJyF7-.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-jURUSte_.js → gateway-config-api-BI0SELXm.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-6SQXF1yR.js → gateway-config-swr-BWGjnmDl.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-UklJOMLX.js → gateway-settings-6ZdOIC7F.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DqWaxyvZ.js → gateway-startup-retry-B_zrtccP.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-Djs_nduD.js → heartbeat-settings-KBwhXeFD.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-BA2M4CLi.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-Bxmt6LEr.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-ByVsCH3d.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-D19R-xsz.js → local-apps-page-BCXa0oUa.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-Ci1Qi0Q-.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-G0y7zmfY.js → management-settings-tHnlfOAQ.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-B69d2HWt.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-6TWEQgN_.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-DLsnnZCS.js → notes-api-BFsOGYkd.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-CkRJJKDm.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-HxArIvoN.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-lEar5FOV.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-Bf03UNGD.js → runtime-tools-settings-panel-BPEGTip5.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CIXMBgx5.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-DgdB26mE.js → settings-form-section-ChXh3Bwk.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-efk5W6lG.js → settings-loading-skeleton-BCAUqIe2.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-BHVf4gEP.js → settings-page-D25W9Okr.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-WK0dGNMv.js → setup-status-panel-DsN7Z4Fl.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-Cod-w2qm.js → share-preview-page-CRFnUaNb.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-CUqQ31gt.js → shares-settings-CAX0eNaP.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-Doy1gghe.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-DwCcipqK.js → skills-page-Cl7jjTK7.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-3WSbtl3S.js → skills-page.utils-BiCl4nb5.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-C5VxqC_s.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-Dd89g_ki.js → theme-store-DOdCjyuw.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-CeV8VJh2.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-EmJ-8aZu.js → voice-api-key-field-BDNexlVR.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-zsk6E3Mi.js → work-discovery-overlay-BHTfeaWL.js} +1 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-Cf_w-NZy.js +3 -0
- 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/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/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/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/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/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/hono/lib/static-ui.js +7 -5
- 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/sessions.js +31 -0
- package/dist/src/gateway/hono/routes/tasks.js +1 -1
- 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/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/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/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 +1 -1
- package/dist/src/storage/sqlite/index.js +2 -2
- 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/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/package.json +2 -2
- package/dist/gateway/static/root/assets/agents-TJpjRHnr.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-CZ4Da51l.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-2Y00PvJU.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-CbJD27_j.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-Dv8y6OuP.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-TZmjzWzt.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-g-68dutA.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-D7KsAeWh.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DXA0rAvQ.js +0 -2
- package/dist/gateway/static/root/assets/home-page-i6bXCHdo.js +0 -1
- package/dist/gateway/static/root/assets/index-BBBE89vm.css +0 -2
- package/dist/gateway/static/root/assets/index-BsD5wygl.js +0 -74
- package/dist/gateway/static/root/assets/local-app-workbench-page-BCKEDMlP.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-Cy9YQK7j.js +0 -2
- package/dist/gateway/static/root/assets/markdown-view-CBM-v2ph.js +0 -69
- package/dist/gateway/static/root/assets/mermaid-render-BbqDc_LQ.js +0 -134
- package/dist/gateway/static/root/assets/messages-CtOJwGW3.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-B10T3hGX.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-DsqRlgsy.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-Bu2PN8OK.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CXACdJ2f.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CS2knWDT.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-ByFGk0q_.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DweAPjI8.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-DEj-BFMP.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-f7yh7aD5.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-CBAYvm3G.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-BN0JmHrG.js +0 -5
- 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,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { registerNotificationDevice, removeNotificationDevice, updateNotificationDevicePreferences } from "../../../notifications/device-store.js";
|
|
2
2
|
//#region src/gateway/hono/routes/mobile.ts
|
|
3
3
|
function stringField(value, maxLength) {
|
|
4
4
|
return typeof value === "string" && value.trim().length > 0 && value.trim().length <= maxLength ? value.trim() : null;
|
|
@@ -9,10 +9,15 @@ function parsePreferences(value) {
|
|
|
9
9
|
const source = value;
|
|
10
10
|
const result = {};
|
|
11
11
|
for (const key of [
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
12
|
+
"chatCompleted",
|
|
13
|
+
"chatFailed",
|
|
14
|
+
"taskNeedsInput",
|
|
15
|
+
"taskBlocked",
|
|
16
|
+
"taskFailed",
|
|
17
|
+
"taskCompleted",
|
|
18
|
+
"automationCompleted",
|
|
19
|
+
"automationFailed",
|
|
20
|
+
"proactiveInsight"
|
|
16
21
|
]) {
|
|
17
22
|
if (source[key] === void 0) continue;
|
|
18
23
|
if (typeof source[key] !== "boolean") return null;
|
|
@@ -26,15 +31,8 @@ function parsePlatform(value) {
|
|
|
26
31
|
function parsePermission(value) {
|
|
27
32
|
return value === "granted" || value === "denied" || value === "unknown" ? value : null;
|
|
28
33
|
}
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
const parsed = Number.parseInt(value, 10);
|
|
32
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
33
|
-
}
|
|
34
|
-
function parseLimit(value) {
|
|
35
|
-
if (!value) return void 0;
|
|
36
|
-
const parsed = Number.parseInt(value, 10);
|
|
37
|
-
return Number.isFinite(parsed) ? Math.max(1, Math.min(100, parsed)) : void 0;
|
|
34
|
+
function parseLocale(value) {
|
|
35
|
+
return value === "en" || value === "zh" ? value : null;
|
|
38
36
|
}
|
|
39
37
|
function registerMobileRoutes(authenticated, _deps) {
|
|
40
38
|
authenticated.post("/api/mobile/devices/register", async (c) => {
|
|
@@ -44,17 +42,19 @@ function registerMobileRoutes(authenticated, _deps) {
|
|
|
44
42
|
const platform = parsePlatform(body?.platform);
|
|
45
43
|
const permissions = parsePermission(body?.permissions);
|
|
46
44
|
const preferences = parsePreferences(body?.preferences);
|
|
45
|
+
const locale = parseLocale(body?.locale);
|
|
47
46
|
const appVersion = body?.appVersion === void 0 ? void 0 : stringField(body.appVersion, 128);
|
|
48
|
-
if (!id || !pushToken || !platform || !permissions || preferences === null || appVersion === null) return c.json({
|
|
47
|
+
if (!id || !pushToken || !platform || !permissions || !locale || preferences === null || appVersion === null) return c.json({
|
|
49
48
|
ok: false,
|
|
50
49
|
error: "Invalid mobile device registration"
|
|
51
50
|
}, 400);
|
|
52
|
-
const device =
|
|
51
|
+
const device = registerNotificationDevice({
|
|
53
52
|
id,
|
|
54
53
|
pushToken,
|
|
55
54
|
platform,
|
|
56
55
|
permissions,
|
|
57
56
|
preferences,
|
|
57
|
+
locale,
|
|
58
58
|
appVersion
|
|
59
59
|
});
|
|
60
60
|
return c.json({
|
|
@@ -68,7 +68,7 @@ function registerMobileRoutes(authenticated, _deps) {
|
|
|
68
68
|
ok: false,
|
|
69
69
|
error: "Invalid notification preferences"
|
|
70
70
|
}, 400);
|
|
71
|
-
const device =
|
|
71
|
+
const device = updateNotificationDevicePreferences(c.req.param("id"), preferences);
|
|
72
72
|
if (!device) return c.json({
|
|
73
73
|
ok: false,
|
|
74
74
|
error: "Mobile device not found"
|
|
@@ -81,31 +81,9 @@ function registerMobileRoutes(authenticated, _deps) {
|
|
|
81
81
|
authenticated.delete("/api/mobile/devices/:id", (c) => {
|
|
82
82
|
return c.json({
|
|
83
83
|
ok: true,
|
|
84
|
-
removed:
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
authenticated.get("/api/mobile/activity", (c) => {
|
|
88
|
-
const result = listMobileActivityEvents({
|
|
89
|
-
cursor: parseCursor(c.req.query("cursor")),
|
|
90
|
-
limit: parseLimit(c.req.query("limit"))
|
|
91
|
-
});
|
|
92
|
-
return c.json({
|
|
93
|
-
ok: true,
|
|
94
|
-
...result
|
|
84
|
+
removed: removeNotificationDevice(c.req.param("id"))
|
|
95
85
|
});
|
|
96
86
|
});
|
|
97
|
-
authenticated.post("/api/mobile/activity/:id/ack", async (c) => {
|
|
98
|
-
const deviceId = stringField((await c.req.json().catch(() => null))?.deviceId, 160);
|
|
99
|
-
if (!deviceId) return c.json({
|
|
100
|
-
ok: false,
|
|
101
|
-
error: "deviceId is required"
|
|
102
|
-
}, 400);
|
|
103
|
-
if (!acknowledgeMobileActivityEvent(c.req.param("id"), deviceId)) return c.json({
|
|
104
|
-
ok: false,
|
|
105
|
-
error: "Activity event or mobile device not found"
|
|
106
|
-
}, 404);
|
|
107
|
-
return c.json({ ok: true });
|
|
108
|
-
});
|
|
109
87
|
}
|
|
110
88
|
//#endregion
|
|
111
89
|
export { registerMobileRoutes };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { acknowledgeNotification, listNotificationEvents, notificationDeliveryMetrics } from "../../../notifications/store.js";
|
|
2
|
+
//#region src/gateway/hono/routes/notifications.ts
|
|
3
|
+
function integerQuery(value, min, max) {
|
|
4
|
+
if (!value) return void 0;
|
|
5
|
+
const parsed = Number.parseInt(value, 10);
|
|
6
|
+
return Number.isFinite(parsed) ? Math.max(min, Math.min(max, parsed)) : void 0;
|
|
7
|
+
}
|
|
8
|
+
function stringField(value, maxLength) {
|
|
9
|
+
return typeof value === "string" && value.trim().length > 0 && value.trim().length <= maxLength ? value.trim() : null;
|
|
10
|
+
}
|
|
11
|
+
function registerNotificationRoutes(authenticated, _deps) {
|
|
12
|
+
authenticated.get("/api/notifications", (c) => {
|
|
13
|
+
const result = listNotificationEvents({
|
|
14
|
+
afterId: c.req.query("after")?.trim() || void 0,
|
|
15
|
+
since: integerQuery(c.req.query("since"), 0, Number.MAX_SAFE_INTEGER),
|
|
16
|
+
limit: integerQuery(c.req.query("limit"), 1, 100)
|
|
17
|
+
});
|
|
18
|
+
return c.json({
|
|
19
|
+
ok: true,
|
|
20
|
+
...result
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
authenticated.post("/api/notifications/:id/ack", async (c) => {
|
|
24
|
+
const body = await c.req.json().catch(() => null);
|
|
25
|
+
const consumerId = stringField(body?.consumerId, 160);
|
|
26
|
+
const surface = body?.surface;
|
|
27
|
+
if (!consumerId || surface !== "web" && surface !== "electron" && surface !== "mobile") return c.json({
|
|
28
|
+
ok: false,
|
|
29
|
+
error: "Invalid notification acknowledgement"
|
|
30
|
+
}, 400);
|
|
31
|
+
if (!acknowledgeNotification(c.req.param("id"), consumerId, surface)) return c.json({
|
|
32
|
+
ok: false,
|
|
33
|
+
error: "Notification not found"
|
|
34
|
+
}, 404);
|
|
35
|
+
return c.json({ ok: true });
|
|
36
|
+
});
|
|
37
|
+
authenticated.get("/api/notifications/metrics", (c) => {
|
|
38
|
+
return c.json({
|
|
39
|
+
ok: true,
|
|
40
|
+
deliveries: notificationDeliveryMetrics()
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { registerNotificationRoutes };
|
|
@@ -60,6 +60,14 @@ function buildDirectSessionMetadata(params) {
|
|
|
60
60
|
}
|
|
61
61
|
function registerSessionsRoutes(authenticated, deps) {
|
|
62
62
|
const { service } = deps;
|
|
63
|
+
authenticated.get("/api/session-runs", (c) => {
|
|
64
|
+
const blocked = ensureGatewayReadyForSessions(c, service, "sessions.list");
|
|
65
|
+
if (blocked) return blocked;
|
|
66
|
+
return c.json({
|
|
67
|
+
ok: true,
|
|
68
|
+
payload: { runs: service.sessions.listActiveRuns() }
|
|
69
|
+
});
|
|
70
|
+
});
|
|
63
71
|
authenticated.get("/api/sidebar/chat-list", async (c) => {
|
|
64
72
|
const blocked = ensureGatewayReadyForSessions(c, service, "sessions.list");
|
|
65
73
|
if (blocked) return blocked;
|
|
@@ -648,6 +656,29 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
648
656
|
}, 400);
|
|
649
657
|
}
|
|
650
658
|
});
|
|
659
|
+
authenticated.post("/api/sessions/:key/fork-at-turn", async (c) => {
|
|
660
|
+
const key = c.req.param("key");
|
|
661
|
+
const body = await c.req.json().catch(() => ({}));
|
|
662
|
+
const lastTurnId = typeof body.lastTurnId === "string" ? body.lastTurnId.trim() : "";
|
|
663
|
+
if (!lastTurnId) return c.json({
|
|
664
|
+
ok: false,
|
|
665
|
+
error: "lastTurnId is required"
|
|
666
|
+
}, 400);
|
|
667
|
+
try {
|
|
668
|
+
const result = await service.sessions.forkAtTurn(key, lastTurnId);
|
|
669
|
+
return c.json({
|
|
670
|
+
ok: true,
|
|
671
|
+
...result
|
|
672
|
+
}, 201);
|
|
673
|
+
} catch (err) {
|
|
674
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
675
|
+
const status = errorMessage.startsWith("Session not found:") ? 404 : 409;
|
|
676
|
+
return c.json({
|
|
677
|
+
ok: false,
|
|
678
|
+
error: errorMessage
|
|
679
|
+
}, status);
|
|
680
|
+
}
|
|
681
|
+
});
|
|
651
682
|
authenticated.post("/api/sessions/:key/fork-row", async (c) => {
|
|
652
683
|
const key = c.req.param("key");
|
|
653
684
|
const body = await c.req.json().catch(() => ({}));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { runSqliteWriteTransaction } from "../../../storage/sqlite/transaction.js";
|
|
2
2
|
import { TaskRepository } from "../../../tasks/task-repository.js";
|
|
3
3
|
import { TaskConversationRepository } from "../../../tasks/task-conversation-repository.js";
|
|
4
|
+
import { enqueueTaskChangedEvent } from "../../../tasks/task-change-events.js";
|
|
4
5
|
import { TaskRunRepository } from "../../../tasks/task-run-repository.js";
|
|
5
6
|
import { TaskReadModelProjector } from "../../../tasks/task-read-model-projector.js";
|
|
6
7
|
import { TaskPhaseSchema } from "../../../../packages/gateway-contract/src/task-lifecycle.js";
|
|
@@ -8,7 +9,6 @@ import { TaskBoardPositionRequestSchema, TaskCommandRequestSchema, TaskContextIn
|
|
|
8
9
|
import { ProjectMonitoringUpdateSchema } from "../../../../packages/gateway-contract/src/project-monitoring.js";
|
|
9
10
|
import { resolveProjectAgentId } from "../../../projects/project-agent.js";
|
|
10
11
|
import { TaskContextRepository } from "../../../tasks/task-context-repository.js";
|
|
11
|
-
import { enqueueTaskChangedEvent } from "../../../tasks/task-change-events.js";
|
|
12
12
|
import { TaskDependencyError, TaskDependencyService } from "../../../tasks/task-dependency-service.js";
|
|
13
13
|
import { TaskApplicationService } from "../../../tasks/task-application-service.js";
|
|
14
14
|
import { ProjectMonitoringService } from "../../../tasks/project-monitoring-service.js";
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { listActiveSessionInputRuns } from "../../storage/sqlite/session-input-repository.js";
|
|
4
|
+
import "../../storage/sqlite/index.js";
|
|
3
5
|
import { ClarifyBridge } from "../clarify-bridge.js";
|
|
4
6
|
import { runGatewayAgent } from "./run-gateway-agent.js";
|
|
5
7
|
import { fitSourceContextsToBudget } from "../../agent/source-context/budget.js";
|
|
@@ -75,10 +77,12 @@ var GatewayAgentRunner = class {
|
|
|
75
77
|
return this.activeWebchatRunBySession.has(sessionKey);
|
|
76
78
|
}
|
|
77
79
|
getActiveRunId(sessionKey) {
|
|
78
|
-
return this.activeWebchatRunBySession.get(sessionKey);
|
|
80
|
+
return this.activeWebchatRunBySession.get(sessionKey) ?? this.inputs.snapshot(sessionKey).activeRunId;
|
|
79
81
|
}
|
|
80
82
|
listActiveRuns() {
|
|
81
|
-
|
|
83
|
+
const runs = new Map(listActiveSessionInputRuns().map(({ sessionKey, runId }) => [sessionKey, runId]));
|
|
84
|
+
for (const [sessionKey, runId] of this.activeWebchatRunBySession) runs.set(sessionKey, runId);
|
|
85
|
+
return [...runs].map(([sessionKey, runId]) => ({
|
|
82
86
|
sessionKey,
|
|
83
87
|
runId
|
|
84
88
|
}));
|
|
@@ -13,6 +13,7 @@ import { ChatStreamMapper } from "../chat-stream/mapper.js";
|
|
|
13
13
|
import { resolveWebchatSessionKey } from "../resolve-webchat-session-key.js";
|
|
14
14
|
import { recordExplicitRelationshipFollowUp } from "../../user-context/relationship-continuity.js";
|
|
15
15
|
import { coalesceThinkingDeltas } from "../chat-stream/thinking-delta-coalescer.js";
|
|
16
|
+
import { TurnOutcomeCollector } from "../chat-stream/turn-outcome-collector.js";
|
|
16
17
|
import crypto from "crypto";
|
|
17
18
|
//#region src/gateway/service/run-gateway-agent.ts
|
|
18
19
|
init_logger();
|
|
@@ -34,9 +35,11 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
34
35
|
let taskRunStatus = "failed";
|
|
35
36
|
let taskRunSummary = "Agent run ended unexpectedly";
|
|
36
37
|
let terminalStatus = "error";
|
|
38
|
+
let runTopicCompleted = false;
|
|
37
39
|
let webchatSessionKey;
|
|
38
40
|
let webchatSessionId;
|
|
39
41
|
let webchatMetadata;
|
|
42
|
+
let outcomeEnvironment = "workspace";
|
|
40
43
|
if (channel === "webchat") {
|
|
41
44
|
const resolved = resolveWebchatSessionKey({ sessionKey: chatId });
|
|
42
45
|
if (resolved.ok === false) throw new Error(resolved.error);
|
|
@@ -65,6 +68,8 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
65
68
|
channel,
|
|
66
69
|
metadata: webchatMetadata
|
|
67
70
|
});
|
|
71
|
+
if (/remote/i.test(executionContext.strategy ?? "")) outcomeEnvironment = "remote_runtime";
|
|
72
|
+
else if (/worktree/i.test(executionContext.strategy ?? "")) outcomeEnvironment = "worktree";
|
|
68
73
|
taskRun = TaskRunCoordinator.start({
|
|
69
74
|
runId,
|
|
70
75
|
context: executionContext,
|
|
@@ -76,8 +81,11 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
76
81
|
sessionKey: streamSessionKey,
|
|
77
82
|
channel
|
|
78
83
|
});
|
|
84
|
+
const outcomeCollector = new TurnOutcomeCollector(runId, outcomeEnvironment);
|
|
85
|
+
let outcomeFinalized = false;
|
|
79
86
|
let registeredActiveWebchatRun = false;
|
|
80
87
|
const captureTaskEvent = (event) => {
|
|
88
|
+
outcomeCollector.capture(event);
|
|
81
89
|
if (event.type === "task_plan_updated") {
|
|
82
90
|
taskRun?.capturePlan(event.payload.items);
|
|
83
91
|
return;
|
|
@@ -102,6 +110,30 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
102
110
|
yield event;
|
|
103
111
|
}
|
|
104
112
|
};
|
|
113
|
+
const finalizeOutcome = async (status, summary) => {
|
|
114
|
+
if (outcomeFinalized) return [];
|
|
115
|
+
outcomeFinalized = true;
|
|
116
|
+
const outcome = outcomeCollector.finalize(status, summary);
|
|
117
|
+
if (webchatSessionKey) try {
|
|
118
|
+
await sessionIndex.appendTranscriptCustomEntry(webchatSessionKey, {
|
|
119
|
+
customType: "turn_outcome",
|
|
120
|
+
data: outcome
|
|
121
|
+
});
|
|
122
|
+
} catch (err) {
|
|
123
|
+
log.warn({
|
|
124
|
+
err,
|
|
125
|
+
runId,
|
|
126
|
+
sessionKey: webchatSessionKey
|
|
127
|
+
}, `Turn outcome persistence failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
128
|
+
}
|
|
129
|
+
return [{
|
|
130
|
+
type: "turn_outcome",
|
|
131
|
+
runId,
|
|
132
|
+
sessionKey: streamSessionKey,
|
|
133
|
+
timestamp: Date.now(),
|
|
134
|
+
payload: outcome
|
|
135
|
+
}];
|
|
136
|
+
};
|
|
105
137
|
try {
|
|
106
138
|
yield* emitAndYield(mapper.start());
|
|
107
139
|
if (channel === "webchat" && webchatSessionKey) {
|
|
@@ -141,8 +173,10 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
141
173
|
taskRunStatus = mergedSignal.aborted ? "cancelled" : "succeeded";
|
|
142
174
|
terminalStatus = endStatus;
|
|
143
175
|
taskRunSummary = endSummary;
|
|
176
|
+
yield* emitAndYield(await finalizeOutcome(endStatus, endSummary));
|
|
144
177
|
yield* emitAndYield(mapper.end(endStatus, endSummary));
|
|
145
178
|
completeRealtimeTopic(`run:${runId}`);
|
|
179
|
+
runTopicCompleted = true;
|
|
146
180
|
return {
|
|
147
181
|
status: mergedSignal.aborted ? "aborted" : "ok",
|
|
148
182
|
summary: mergedSignal.aborted ? "Interrupted" : "Message processed successfully"
|
|
@@ -163,8 +197,10 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
163
197
|
taskRunSummary = em;
|
|
164
198
|
const errorContent = formatAgentRunErrorForClient(streamError);
|
|
165
199
|
yield* emitAndYield(mapper.error(errorContent));
|
|
200
|
+
yield* emitAndYield(await finalizeOutcome("error", streamError));
|
|
166
201
|
yield* emitAndYield(mapper.end("error", streamError));
|
|
167
202
|
completeRealtimeTopic(`run:${runId}`);
|
|
203
|
+
runTopicCompleted = true;
|
|
168
204
|
return {
|
|
169
205
|
status: "error",
|
|
170
206
|
summary: streamError
|
|
@@ -247,6 +283,7 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
247
283
|
presentation: "answer"
|
|
248
284
|
}
|
|
249
285
|
}]);
|
|
286
|
+
yield* emitAndYield(await finalizeOutcome("success", "Message processed"));
|
|
250
287
|
yield* emitAndYield(mapper.end("success", "Message processed"));
|
|
251
288
|
taskRunStatus = "succeeded";
|
|
252
289
|
taskRunSummary = "Message processed";
|
|
@@ -257,6 +294,7 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
257
294
|
} catch (error) {
|
|
258
295
|
const em = error instanceof Error ? error.message : String(error);
|
|
259
296
|
taskRunStatus = "failed";
|
|
297
|
+
terminalStatus = "error";
|
|
260
298
|
taskRunSummary = em;
|
|
261
299
|
log.error({
|
|
262
300
|
err: error,
|
|
@@ -266,6 +304,17 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
266
304
|
channel,
|
|
267
305
|
chatId
|
|
268
306
|
}, `Agent run failed: ${em}`);
|
|
307
|
+
if (channel === "webchat" && !runTopicCompleted) {
|
|
308
|
+
yield* emitAndYield(mapper.error(formatAgentRunErrorForClient(em)));
|
|
309
|
+
yield* emitAndYield(await finalizeOutcome("error", em));
|
|
310
|
+
yield* emitAndYield(mapper.end("error", em));
|
|
311
|
+
completeRealtimeTopic(`run:${runId}`);
|
|
312
|
+
runTopicCompleted = true;
|
|
313
|
+
return {
|
|
314
|
+
status: "error",
|
|
315
|
+
summary: em
|
|
316
|
+
};
|
|
317
|
+
}
|
|
269
318
|
throw error;
|
|
270
319
|
} finally {
|
|
271
320
|
if (taskRun) try {
|
|
@@ -292,7 +341,10 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
292
341
|
sessionKey: webchatSessionKey,
|
|
293
342
|
status: terminalStatus,
|
|
294
343
|
completedAtMs: Date.now(),
|
|
295
|
-
|
|
344
|
+
target: {
|
|
345
|
+
kind: "chat",
|
|
346
|
+
sessionKey: webchatSessionKey
|
|
347
|
+
},
|
|
296
348
|
source: "webchat",
|
|
297
349
|
...metaAfter?.name?.trim() ? { sessionTitle: metaAfter.name.trim().slice(0, 100) } : {}
|
|
298
350
|
});
|
|
@@ -159,6 +159,12 @@ export declare class GatewaySessionsApi {
|
|
|
159
159
|
sessionKey: string;
|
|
160
160
|
rowCount: number;
|
|
161
161
|
}>;
|
|
162
|
+
forkAtTurn(sourceKey: string, lastTurnId: string): Promise<{
|
|
163
|
+
sessionKey: string;
|
|
164
|
+
rowCount: number;
|
|
165
|
+
lastTurnId: string;
|
|
166
|
+
session: NonNullable<Awaited<ReturnType<GatewaySessionsApi['getSession']>>>;
|
|
167
|
+
}>;
|
|
162
168
|
btwQuery(sessionKey: string, question: string): Promise<{
|
|
163
169
|
text: string;
|
|
164
170
|
error?: string;
|
|
@@ -1,11 +1,28 @@
|
|
|
1
|
+
import { init_agent_session_key, resolveAgentIdFromSessionKey } from "../../routing/agent-session-key.js";
|
|
2
|
+
import { buildSessionKey, init_session_key } from "../../routing/session-key.js";
|
|
1
3
|
import { retireSessionMcpRuntimeForSessionKey } from "../../agent/mcp/bundle-mcp-runtime.js";
|
|
2
4
|
import "../../agent/mcp/bundle-mcp-tools.js";
|
|
3
5
|
import { buildSessionTimeline } from "../../session/transcript-outline.js";
|
|
4
6
|
import { transcriptRowsToClientHistory } from "../../session/client-history.js";
|
|
5
|
-
import {
|
|
7
|
+
import { collectMediaUrisFromValues, deleteMediaUris } from "../../media/session-references.js";
|
|
6
8
|
import { getDistinctSessionChatIds } from "./session-chat-ids.js";
|
|
7
9
|
import { performSessionReset } from "../session-reset-service.js";
|
|
10
|
+
import { randomUUID } from "node:crypto";
|
|
8
11
|
//#region src/gateway/service/sessions-api.ts
|
|
12
|
+
/**
|
|
13
|
+
* GatewaySessionsApi — session CRUD, search, compaction, tag/pin/archive,
|
|
14
|
+
* stats, and chat-id grouping for the gateway REST surface.
|
|
15
|
+
*
|
|
16
|
+
* Twenty-four methods, previously sitting on `GatewayService` as a mix of
|
|
17
|
+
* one-line `sessionIndex.*` delegations and small composite operations (e.g.
|
|
18
|
+
* `restoreCheckpoint` also evicts the in-memory agent, `runCompaction` also
|
|
19
|
+
* appends a transcript context entry). Centralising them here lets routes
|
|
20
|
+
* depend on the narrow `GatewaySessionsApi` surface instead of the full
|
|
21
|
+
* `GatewayService`, and keeps the gateway composition root focused on
|
|
22
|
+
* lifecycle + wiring.
|
|
23
|
+
*/
|
|
24
|
+
init_session_key();
|
|
25
|
+
init_agent_session_key();
|
|
9
26
|
function clampWindowSpan(value, fallback) {
|
|
10
27
|
const parsed = Math.trunc(value ?? fallback);
|
|
11
28
|
if (!Number.isFinite(parsed)) return fallback;
|
|
@@ -117,10 +134,10 @@ var GatewaySessionsApi = class {
|
|
|
117
134
|
return result;
|
|
118
135
|
}
|
|
119
136
|
async delete(key) {
|
|
120
|
-
const
|
|
137
|
+
const transcriptRows = await this.opts.sessionIndex.getStore().loadTranscriptHistoryRows(key).catch(() => []);
|
|
121
138
|
const result = await this.opts.sessionIndex.deleteSession(key);
|
|
122
139
|
if (result) {
|
|
123
|
-
await deleteMediaUris(
|
|
140
|
+
await deleteMediaUris(collectMediaUrisFromValues(transcriptRows));
|
|
124
141
|
this.opts.getAgentService().evictSessionAgent(key);
|
|
125
142
|
await retireSessionMcpRuntimeForSessionKey({
|
|
126
143
|
sessionKey: key,
|
|
@@ -185,6 +202,46 @@ var GatewaySessionsApi = class {
|
|
|
185
202
|
forkRows(key, targetKey, options = {}) {
|
|
186
203
|
return this.opts.sessionIndex.forkSessionRows(key, targetKey, options);
|
|
187
204
|
}
|
|
205
|
+
async forkAtTurn(sourceKey, lastTurnId) {
|
|
206
|
+
const source = await this.opts.sessionIndex.getSessionMetadata(sourceKey);
|
|
207
|
+
if (!source) throw new Error(`Session not found: ${sourceKey}`);
|
|
208
|
+
if (source.sessionType !== "chat") throw new Error("Only chat sessions can be forked");
|
|
209
|
+
const normalizedTurnId = lastTurnId.trim();
|
|
210
|
+
if (!normalizedTurnId) throw new Error("lastTurnId is required");
|
|
211
|
+
if (this.opts.getActiveWebchatRunId(sourceKey)?.trim() === normalizedTurnId) throw new Error("Cannot fork a turn that is still running");
|
|
212
|
+
const agentId = source.routing?.agentId?.trim() || resolveAgentIdFromSessionKey(sourceKey);
|
|
213
|
+
const chatId = `chat_${randomUUID()}`;
|
|
214
|
+
const targetKey = buildSessionKey({
|
|
215
|
+
agentId,
|
|
216
|
+
source: "webchat",
|
|
217
|
+
accountId: "default",
|
|
218
|
+
peerKind: "direct",
|
|
219
|
+
peerId: chatId
|
|
220
|
+
});
|
|
221
|
+
const result = await this.opts.sessionIndex.forkSessionAtTurn(sourceKey, {
|
|
222
|
+
targetKey,
|
|
223
|
+
lastTurnId: normalizedTurnId,
|
|
224
|
+
targetMetadata: {
|
|
225
|
+
sourceChannel: "webchat",
|
|
226
|
+
sourceChatId: `default:direct:${chatId}`,
|
|
227
|
+
sessionType: "chat",
|
|
228
|
+
routing: {
|
|
229
|
+
agentId,
|
|
230
|
+
source: "webchat",
|
|
231
|
+
accountId: "default",
|
|
232
|
+
peerKind: "direct",
|
|
233
|
+
peerId: chatId
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
const session = await this.getSession(result.sessionKey);
|
|
238
|
+
if (!session) throw new Error(`Forked session not found: ${result.sessionKey}`);
|
|
239
|
+
return {
|
|
240
|
+
...result,
|
|
241
|
+
lastTurnId: normalizedTurnId,
|
|
242
|
+
session
|
|
243
|
+
};
|
|
244
|
+
}
|
|
188
245
|
btwQuery(sessionKey, question) {
|
|
189
246
|
return this.opts.getAgentService().sessionInspector.btwQuery(sessionKey, question);
|
|
190
247
|
}
|
|
@@ -68,7 +68,7 @@ export declare class GatewayService {
|
|
|
68
68
|
private taskRunDispatcher;
|
|
69
69
|
private taskRunDispatchTimer;
|
|
70
70
|
private managedComposioEventPoller?;
|
|
71
|
-
private
|
|
71
|
+
private notificationService;
|
|
72
72
|
private connectorSupervisor;
|
|
73
73
|
private connectorLearningCoordinator;
|
|
74
74
|
private connectedSourceChangePublisher;
|
|
@@ -120,7 +120,7 @@ export declare class GatewayService {
|
|
|
120
120
|
private ensureAgentService;
|
|
121
121
|
private ensureHeartbeatService;
|
|
122
122
|
private createTaskRunDispatcher;
|
|
123
|
-
private
|
|
123
|
+
private createNotificationService;
|
|
124
124
|
dispatchTaskRuns(): void;
|
|
125
125
|
ensureTaskConversation(taskId: string, options?: {
|
|
126
126
|
runId?: string;
|
|
@@ -92,7 +92,7 @@ import { auditGatewayConfig } from "./security/audit.js";
|
|
|
92
92
|
import { getXopcCloudCatalogCoordinator } from "../providers/xopc-cloud-catalog-coordinator.js";
|
|
93
93
|
import { ModelCatalogSyncService } from "../providers/model-catalog-sync-service.js";
|
|
94
94
|
import { runBootstrapMigrationsSync } from "../migrations/runner.js";
|
|
95
|
-
import {
|
|
95
|
+
import { NotificationService } from "../notifications/service.js";
|
|
96
96
|
import { LocalAppService } from "../local-apps/service.js";
|
|
97
97
|
import "../local-apps/index.js";
|
|
98
98
|
import { createRuntimeBrowserRecipeService } from "../browser/recipes/runtime-service.js";
|
|
@@ -185,7 +185,7 @@ var GatewayService = class {
|
|
|
185
185
|
taskRunDispatcher = null;
|
|
186
186
|
taskRunDispatchTimer = null;
|
|
187
187
|
managedComposioEventPoller;
|
|
188
|
-
|
|
188
|
+
notificationService = null;
|
|
189
189
|
connectorSupervisor = null;
|
|
190
190
|
connectorLearningCoordinator = null;
|
|
191
191
|
connectedSourceChangePublisher = null;
|
|
@@ -239,7 +239,6 @@ var GatewayService = class {
|
|
|
239
239
|
this.proactiveTemporalWorker = new ProactiveTemporalWorker(this.proactive);
|
|
240
240
|
this.proactiveInboxWorker = new ProactiveInboxWorker({ deliver: async ({ inboxItem }) => {
|
|
241
241
|
this.emit("proactive.inbox.created", inboxItem);
|
|
242
|
-
await this.createMobileNotificationService().deliverGatewayEvent("proactive.inbox.created", inboxItem);
|
|
243
242
|
} });
|
|
244
243
|
let bootstrapConfigChanged = initializeVoiceDefaults(this.config, inferProductLanguageFromEnvironment());
|
|
245
244
|
const starterResult = ensureStarterAgentsInitialized(this.config);
|
|
@@ -574,9 +573,9 @@ var GatewayService = class {
|
|
|
574
573
|
});
|
|
575
574
|
return this.taskRunDispatcher;
|
|
576
575
|
}
|
|
577
|
-
|
|
578
|
-
if (!this.
|
|
579
|
-
return this.
|
|
576
|
+
createNotificationService() {
|
|
577
|
+
if (!this.notificationService) this.notificationService = new NotificationService({ publish: (type, payload) => this.realtime.broker.publish("gateway", type, payload) });
|
|
578
|
+
return this.notificationService;
|
|
580
579
|
}
|
|
581
580
|
dispatchTaskRuns() {
|
|
582
581
|
new TaskSignalService().tick();
|
|
@@ -798,6 +797,7 @@ var GatewayService = class {
|
|
|
798
797
|
});
|
|
799
798
|
log.debug("Starting gateway service...");
|
|
800
799
|
openXopcDatabase();
|
|
800
|
+
this.createNotificationService().start();
|
|
801
801
|
this.startTime = Date.now();
|
|
802
802
|
this.running = true;
|
|
803
803
|
this.taskRunDispatchTimer = setInterval(() => this.dispatchTaskRuns(), 1e3);
|
|
@@ -1103,6 +1103,7 @@ var GatewayService = class {
|
|
|
1103
1103
|
await this.discussionLiveWorker.stop();
|
|
1104
1104
|
this.proactiveTemporalWorker.stop();
|
|
1105
1105
|
await this.proactiveInboxWorker.stop();
|
|
1106
|
+
this.notificationService?.stop();
|
|
1106
1107
|
if (this.taskRunDispatchTimer) {
|
|
1107
1108
|
clearInterval(this.taskRunDispatchTimer);
|
|
1108
1109
|
this.taskRunDispatchTimer = null;
|
|
@@ -1543,7 +1544,7 @@ var GatewayService = class {
|
|
|
1543
1544
|
}
|
|
1544
1545
|
emit(type, payload) {
|
|
1545
1546
|
this.realtime.broker.publish("gateway", type, payload);
|
|
1546
|
-
this.
|
|
1547
|
+
this.createNotificationService().handleGatewayEvent(type, payload);
|
|
1547
1548
|
}
|
|
1548
1549
|
handleAutomationRunCompleted(run) {
|
|
1549
1550
|
this.automationService.get(run.automationId).then((automation) => {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
export interface CtxHistoryExportResult {
|
|
3
|
+
outputDir: string;
|
|
4
|
+
historyPath: string;
|
|
5
|
+
manifestPath: string;
|
|
6
|
+
sessionCount: number;
|
|
7
|
+
eventCount: number;
|
|
8
|
+
changed: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveDefaultCtxHistoryExportDir(env?: NodeJS.ProcessEnv): string;
|
|
11
|
+
export declare function exportCtxHistory(db: DatabaseSync, options?: {
|
|
12
|
+
outputDir?: string;
|
|
13
|
+
env?: NodeJS.ProcessEnv;
|
|
14
|
+
}): Promise<CtxHistoryExportResult>;
|