@xopcai/xopc 0.0.227 → 0.0.229
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-CsFAJTIN.js} +1 -1
- package/dist/gateway/static/root/assets/agents-DA4b6_0C.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-7KcMWuah.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-BoH2NAUX.js → appearance-settings-Cqlw7Fif.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-CsnhdGZ2.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-q4pDpqkF.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-ZKeAAVxD.js → automations-page-BuTqjKGX.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-CD0E2ThS.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-Cy9er6w-.js → binary-plugins-DUce1Bsc.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-Cc0wWvNX.js → block-editor-D8Ejp-QR.js} +3 -3
- package/dist/gateway/static/root/assets/browser-settings-page-CY1k3MMd.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-BDvZbR9v.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-D1VfotHQ.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-DXHqRLpU.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-DrFL57M_.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-h1CKexNz.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-DUAyfFCF.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-BnSQc4Ek.js → cron-expression-DlaQQOId.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BbuG7zQ_.js → date-picker-8R1sXJKb.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-snZeqOmG.js → dependency-picker-CWur0821.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-DJQ8JoR1.js → desktop-pet-Knl-zNDU.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-B9txsRtv.js → desktop-pet-settings-CAQMLVtd.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-D7WKWkNB.js → directory-picker-path-field-Caaz4Rw5.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-D_7cOCj2.js → extension-debug-page-B965Mc15.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Bwu47iUb.js → extension-page-C0UnkBi5.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-Dwg4dSZM.js → extension-settings-page-BUSIAZCR.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-jURUSte_.js → gateway-config-api-DkH0eEgy.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-BBgLDm6I.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-BtEHVXWD.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-5SU2TNJj.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-BNWhgmjs.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-CsRz8NrS.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-DYPEUgpP.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-D19R-xsz.js → local-apps-page-CTBNUG4a.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-B0P7rG2B.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-G0y7zmfY.js → management-settings-YqUAEwQo.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-B69d2HWt.js → markdown-split-dxpSCXb8.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-CJ00i1Lg.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-DEnbnkIt.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-DmVYu_Oc.js +4 -0
- package/dist/gateway/static/root/assets/{product-open-page-HxArIvoN.js → product-open-page-BHxo9U95.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-DV2nGmsq.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BNIFwFfc.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-DLXqKiA_.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bf03UNGD.js → runtime-tools-settings-panel-BpQ2GI-0.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CIXMBgx5.js → schema-form-HE1G26Lx.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DWaXf_25.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-JFCbnCL2.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-DgdB26mE.js → settings-form-section-CXAn0Xhy.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-efk5W6lG.js → settings-loading-skeleton-DsFu7Bcv.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-BHVf4gEP.js → settings-page-C4iib9nO.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-WK0dGNMv.js → setup-status-panel-BA83Wr1d.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-Cod-w2qm.js → share-preview-page-BOGl3s6M.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-CUqQ31gt.js → shares-settings-Q2MdGaBi.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-cFtfVeFU.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-DwCcipqK.js → skills-page-CdaFtNw9.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-3WSbtl3S.js → skills-page.utils-DYaAddUL.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-C5VxqC_s.js → system-settings-panel-Co7gilRd.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-5B1pswu8.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-DnnZtMpA.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-Dr1FKjXv.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-EmJ-8aZu.js → voice-api-key-field-wetUpi3i.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-zsk6E3Mi.js → work-discovery-overlay-tbTWASJJ.js} +1 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-Dy0fDs8w.js +3 -0
- package/dist/gateway/static/root/assets/workflows-page-IVP3GSkI.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-instance-gateway.d.ts +1 -1
- package/dist/src/agent/agent-manager.d.ts +1 -1
- package/dist/src/agent/agent-manager.js +18 -3
- package/dist/src/agent/background-review/prompts.d.ts +8 -2
- package/dist/src/agent/background-review/prompts.js +25 -12
- package/dist/src/agent/background-review/run-background-review.d.ts +7 -2
- package/dist/src/agent/background-review/run-background-review.js +175 -160
- 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/index.d.ts +1 -1
- package/dist/src/agent/memory/index.js +2 -2
- package/dist/src/agent/memory/manager.d.ts +1 -11
- package/dist/src/agent/memory/manager.js +0 -16
- package/dist/src/agent/memory/understanding/service.d.ts +0 -11
- package/dist/src/agent/memory/understanding/service.js +7 -173
- package/dist/src/agent/memory/user-context-coordinator.d.ts +1 -3
- package/dist/src/agent/memory/user-context-coordinator.js +3 -66
- package/dist/src/agent/orchestration/agent-orchestrator.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/service/direct-turn-helpers.js +1 -1
- 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/config/schema.d.ts +4 -0
- package/dist/src/config/schema.js +1 -0
- package/dist/src/connectors/connected-source-understanding.js +35 -21
- package/dist/src/connectors/learning-coordinator.js +1 -42
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/chat-stream/mapper.d.ts +2 -0
- package/dist/src/gateway/chat-stream/mapper.js +5 -0
- 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/hono/routes/understanding-sources.js +4 -1
- package/dist/src/gateway/hono/routes/you.js +29 -11
- package/dist/src/gateway/service/agent-runner.js +6 -2
- package/dist/src/gateway/service/run-gateway-agent.js +58 -2
- 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/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 +160 -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 +2 -2
- package/dist/src/storage/sqlite/index.js +3 -3
- package/dist/src/storage/sqlite/migrations/136_product_notifications.sql +79 -0
- package/dist/src/storage/sqlite/migrations/137_understanding_status_audit.sql +71 -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-context-repository.d.ts +16 -4
- package/dist/src/storage/sqlite/user-context-repository.js +56 -12
- 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/config.d.ts +8 -0
- package/dist/src/user-context/config.js +3 -0
- package/dist/src/user-context/consolidation.js +16 -4
- package/dist/src/user-context/extraction/executor.d.ts +22 -0
- package/dist/src/user-context/extraction/executor.js +142 -0
- package/dist/src/user-context/extraction/registry.d.ts +1 -1
- package/dist/src/user-context/extraction/registry.js +5 -34
- package/dist/src/user-context/extraction/repair.js +4 -1
- package/dist/src/user-context/extraction/semantic.d.ts +18 -0
- package/dist/src/user-context/extraction/semantic.js +148 -0
- package/dist/src/user-context/understandingQuality.js +4 -0
- package/dist/src/work-discovery/analyzer.js +9 -4
- package/dist/src/work-discovery/service.d.ts +1 -0
- package/dist/src/work-discovery/service.js +5 -4
- package/dist/src/work-discovery/types.d.ts +1 -0
- package/package.json +14 -8
- 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/agent/memory/understanding/correction.d.ts +0 -3
- package/dist/src/agent/memory/understanding/correction.js +0 -39
- package/dist/src/knowledge/connected-understanding-pipeline.d.ts +0 -17
- package/dist/src/knowledge/connected-understanding-pipeline.js +0 -278
- 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
|
@@ -6,7 +6,6 @@ import { upsertUserFocus } from "../user-context/sources/repository.js";
|
|
|
6
6
|
import { claimRegisteredExtraction } from "../user-context/extraction/registry.js";
|
|
7
7
|
import { allowsRemoteSourceProcessing } from "../user-context/sources/processing-policy.js";
|
|
8
8
|
import { analyzeUnderstandingSources } from "../work-discovery/analyzer.js";
|
|
9
|
-
import { createHash } from "node:crypto";
|
|
10
9
|
//#region src/connectors/connected-source-understanding.ts
|
|
11
10
|
const MAX_CONNECTED_ITEMS = 150;
|
|
12
11
|
function normalizedValue(item) {
|
|
@@ -60,17 +59,14 @@ function connectedItemsForUnderstanding(items) {
|
|
|
60
59
|
}];
|
|
61
60
|
});
|
|
62
61
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
if (category === "routine") return "routine";
|
|
66
|
-
return "project_context";
|
|
62
|
+
function isConnectedPortraitCandidate(candidate) {
|
|
63
|
+
return candidate.category === "preference" || candidate.category === "routine";
|
|
67
64
|
}
|
|
68
65
|
function understandingCandidate(candidate) {
|
|
69
|
-
const normalized = candidate.statement.toLocaleLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
70
66
|
return {
|
|
71
|
-
kind:
|
|
67
|
+
kind: candidate.category,
|
|
72
68
|
content: candidate.statement,
|
|
73
|
-
canonicalKey: `
|
|
69
|
+
canonicalKey: `understanding:${candidate.category}:${candidate.factKey}`,
|
|
74
70
|
confidence: candidate.confidence === "high" ? .9 : candidate.confidence === "medium" ? .72 : .55,
|
|
75
71
|
importance: .68,
|
|
76
72
|
explicitness: "inferred",
|
|
@@ -84,6 +80,18 @@ function hasLongVerbatimOverlap(value, sourceTexts, minimumLength = 32) {
|
|
|
84
80
|
if (normalized.length < minimumLength) return false;
|
|
85
81
|
return sourceTexts.some((source) => source.replace(/\s+/g, " ").includes(normalized));
|
|
86
82
|
}
|
|
83
|
+
function evidenceDate(item) {
|
|
84
|
+
const timestamp = item.occurredAt ?? item.modifiedAt;
|
|
85
|
+
return timestamp == null ? void 0 : new Date(timestamp).toISOString().slice(0, 10);
|
|
86
|
+
}
|
|
87
|
+
function durableConnectedEvidence(candidate, itemsByRef) {
|
|
88
|
+
if (candidate.confidence !== "high") return [];
|
|
89
|
+
const items = [...new Set(candidate.evidenceRefs ?? [])].flatMap((ref) => itemsByRef.get(ref) ?? []);
|
|
90
|
+
if (items.some((item) => item.ownerAttribution !== "user")) return [];
|
|
91
|
+
const required = candidate.category === "routine" ? 3 : 2;
|
|
92
|
+
const dates = new Set(items.map(evidenceDate).filter((value) => Boolean(value)));
|
|
93
|
+
return items.length >= required && dates.size >= required ? items : [];
|
|
94
|
+
}
|
|
87
95
|
async function deriveConnectedSourceUnderstanding(input) {
|
|
88
96
|
const knowledgeItems = listKnowledgeSourceItems({
|
|
89
97
|
agentId: input.agentId,
|
|
@@ -115,22 +123,28 @@ async function deriveConnectedSourceUnderstanding(input) {
|
|
|
115
123
|
items
|
|
116
124
|
});
|
|
117
125
|
const rawTexts = items.flatMap((item) => item.text ? [item.text] : []);
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
const reviewed =
|
|
121
|
-
agentId: input.agentId,
|
|
122
|
-
sourceItemIds,
|
|
123
|
-
sourceText: "Bounded semantic synthesis from explicitly connected work sources.",
|
|
124
|
-
source: {
|
|
125
|
-
provider: "connected-sources",
|
|
126
|
-
sourceInstanceId: input.sourceInstanceId
|
|
127
|
-
},
|
|
128
|
-
reviewSource: "background",
|
|
129
|
-
extractionRunId: extraction.run.id
|
|
130
|
-
}) : {
|
|
126
|
+
const itemsByRef = new Map(items.map((item) => [item.evidenceRef, item]));
|
|
127
|
+
const profileCandidates = analysis.profileCandidates.filter(isConnectedPortraitCandidate).filter((candidate) => !hasLongVerbatimOverlap(candidate.statement, rawTexts) && durableConnectedEvidence(candidate, itemsByRef).length > 0);
|
|
128
|
+
const reviewed = {
|
|
131
129
|
created: 0,
|
|
132
130
|
writeOutputs: []
|
|
133
131
|
};
|
|
132
|
+
for (const candidate of profileCandidates) {
|
|
133
|
+
const evidenceItems = durableConnectedEvidence(candidate, itemsByRef);
|
|
134
|
+
const applied = await input.memoryManager.applyUnderstandingCandidates([understandingCandidate(candidate)], {
|
|
135
|
+
agentId: input.agentId,
|
|
136
|
+
sourceItemIds: evidenceItems.map((item) => item.id).slice(0, 20),
|
|
137
|
+
sourceText: "Bounded semantic synthesis from explicitly connected work sources.",
|
|
138
|
+
source: {
|
|
139
|
+
provider: "connected-sources",
|
|
140
|
+
sourceInstanceId: input.sourceInstanceId
|
|
141
|
+
},
|
|
142
|
+
reviewSource: "background",
|
|
143
|
+
extractionRunId: extraction.run.id
|
|
144
|
+
});
|
|
145
|
+
reviewed.created += applied.created;
|
|
146
|
+
reviewed.writeOutputs.push(...applied.writeOutputs ?? []);
|
|
147
|
+
}
|
|
134
148
|
const focuses = analysis.workThreadCandidates.filter((candidate) => !hasLongVerbatimOverlap(candidate.title, rawTexts) && !hasLongVerbatimOverlap(candidate.summary, rawTexts)).map((candidate) => upsertUserFocus({
|
|
135
149
|
canonicalKey: `connected-focus:${candidate.topicKey}`,
|
|
136
150
|
title: candidate.title,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
-
import { finishContextExtractionRun } from "../storage/sqlite/context-extraction-repository.js";
|
|
4
3
|
import { claimNextConnectorLearningJob, enqueueConnectorLearningJob, listConnectorLearningJobs, recoverStaleConnectorLearningJobs, setConnectorLearningPaused, updateConnectorLearningJob } from "../storage/sqlite/connector-learning-repository.js";
|
|
5
4
|
import { getConnectorInstallation, listConnectorConnections, upsertConnectorConnection } from "../storage/sqlite/connector-repository.js";
|
|
6
5
|
import { getConnectorAccount, reconcileConnectorAccount } from "../storage/sqlite/connector-account-repository.js";
|
|
@@ -11,10 +10,8 @@ import { ComposioSessionsAdapter } from "./composio-sessions.js";
|
|
|
11
10
|
import { buildConnectorLearningArguments, getConnectorLearningPlan } from "./learning-recipes.js";
|
|
12
11
|
import { getConnectorDefinition } from "./catalog.js";
|
|
13
12
|
import { createUnderstandingSourceRun, getUnderstandingSourceGrant, listUnderstandingSourceRuns, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceRun, upsertUnderstandingSourceGrant } from "../user-context/sources/repository.js";
|
|
14
|
-
import { claimRegisteredExtraction } from "../user-context/extraction/registry.js";
|
|
15
13
|
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
16
14
|
import { ConnectedKnowledgePipeline } from "../knowledge/connected-knowledge-pipeline.js";
|
|
17
|
-
import { ConnectedUnderstandingPipeline } from "../knowledge/connected-understanding-pipeline.js";
|
|
18
15
|
import "../knowledge/index.js";
|
|
19
16
|
import { ingestComposioConnectedSource } from "./connected-source-ingestion.js";
|
|
20
17
|
import { deriveConnectedSourceUnderstanding } from "./connected-source-understanding.js";
|
|
@@ -210,44 +207,6 @@ function startConnectorLearningCoordinator(options) {
|
|
|
210
207
|
itemsIndexed
|
|
211
208
|
}));
|
|
212
209
|
publish(updateConnectorLearningJob(job.id, { phase: "deriving" }));
|
|
213
|
-
const structuralExtraction = claimRegisteredExtraction({
|
|
214
|
-
extractorId: "connector-structural",
|
|
215
|
-
sourceRef: `understanding-source-run:${sourceRun.id}`,
|
|
216
|
-
contentForHash: `${job.sourceInstanceId}:${itemsSeen}:${itemsIndexed}`,
|
|
217
|
-
processingPolicy: "local_only",
|
|
218
|
-
destination: "deterministic"
|
|
219
|
-
});
|
|
220
|
-
let understanding = {
|
|
221
|
-
proposed: 0,
|
|
222
|
-
created: 0,
|
|
223
|
-
deduplicated: 0,
|
|
224
|
-
rejected: 0,
|
|
225
|
-
createdRecords: [],
|
|
226
|
-
writeOutputs: []
|
|
227
|
-
};
|
|
228
|
-
if (structuralExtraction.shouldExecute) try {
|
|
229
|
-
understanding = await new ConnectedUnderstandingPipeline(options.getMemoryManager()).process(job.agentId, structuralExtraction.run.id);
|
|
230
|
-
finishContextExtractionRun({
|
|
231
|
-
runId: structuralExtraction.run.id,
|
|
232
|
-
status: "completed",
|
|
233
|
-
outputs: (understanding.writeOutputs ?? []).map((output) => ({
|
|
234
|
-
candidateKey: output.candidateKey,
|
|
235
|
-
...output.objectId ? {
|
|
236
|
-
objectType: "understanding",
|
|
237
|
-
objectId: output.objectId
|
|
238
|
-
} : {},
|
|
239
|
-
...output.versionId ? { versionId: output.versionId } : {},
|
|
240
|
-
outcome: output.outcome
|
|
241
|
-
}))
|
|
242
|
-
});
|
|
243
|
-
} catch (error) {
|
|
244
|
-
finishContextExtractionRun({
|
|
245
|
-
runId: structuralExtraction.run.id,
|
|
246
|
-
status: "failed",
|
|
247
|
-
errorCode: "extractor_failed"
|
|
248
|
-
});
|
|
249
|
-
throw error;
|
|
250
|
-
}
|
|
251
210
|
let semantic = {
|
|
252
211
|
created: 0,
|
|
253
212
|
focusCount: 0,
|
|
@@ -276,7 +235,7 @@ function startConnectorLearningCoordinator(options) {
|
|
|
276
235
|
connectorId: job.connectorId
|
|
277
236
|
}, `Connected source semantic analysis failed: ${errorMessage}`);
|
|
278
237
|
}
|
|
279
|
-
const candidatesCreated =
|
|
238
|
+
const candidatesCreated = semantic.created + semantic.focusCount;
|
|
280
239
|
const incomplete = enrichmentErrors.length > 0 || semantic.status !== "completed";
|
|
281
240
|
const completed = updateConnectorLearningJob(job.id, {
|
|
282
241
|
status: "completed",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { resolveCapabilityPresetLayer, resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
|
|
2
1
|
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
|
|
2
|
+
import { resolveCapabilityPresetLayer, resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
|
|
3
3
|
import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
|
|
4
4
|
import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
|
|
5
5
|
import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
|
|
@@ -15,6 +15,7 @@ export declare class ChatStreamMapper {
|
|
|
15
15
|
private currentAssistantMessageId;
|
|
16
16
|
private lastAssistantMessageId;
|
|
17
17
|
private currentAssistantText;
|
|
18
|
+
private lastAssistantText;
|
|
18
19
|
private currentAssistantReviewEmitted;
|
|
19
20
|
private toolCallToMessageId;
|
|
20
21
|
private turnDiffs;
|
|
@@ -28,6 +29,7 @@ export declare class ChatStreamMapper {
|
|
|
28
29
|
start(): ChatStreamEvent[];
|
|
29
30
|
end(status: ChatStreamStatus, summary?: string): ChatStreamEvent[];
|
|
30
31
|
error(message: string, code?: string): ChatStreamEvent[];
|
|
32
|
+
getLastAssistantText(): string;
|
|
31
33
|
private mapMessageStart;
|
|
32
34
|
private mapMessageUpdate;
|
|
33
35
|
private mapAssistantSnapshot;
|
|
@@ -14,6 +14,7 @@ var ChatStreamMapper = class {
|
|
|
14
14
|
currentAssistantMessageId;
|
|
15
15
|
lastAssistantMessageId;
|
|
16
16
|
currentAssistantText = "";
|
|
17
|
+
lastAssistantText = "";
|
|
17
18
|
currentAssistantReviewEmitted = false;
|
|
18
19
|
toolCallToMessageId = /* @__PURE__ */ new Map();
|
|
19
20
|
turnDiffs = [];
|
|
@@ -154,6 +155,9 @@ var ChatStreamMapper = class {
|
|
|
154
155
|
petFeedback: createPetFeedback("error", { recoverable: false })
|
|
155
156
|
})];
|
|
156
157
|
}
|
|
158
|
+
getLastAssistantText() {
|
|
159
|
+
return this.currentAssistantText || this.lastAssistantText;
|
|
160
|
+
}
|
|
157
161
|
mapMessageStart(raw) {
|
|
158
162
|
if (raw?.role !== "assistant") return [];
|
|
159
163
|
const messageId = this.nextAssistantMessageId();
|
|
@@ -260,6 +264,7 @@ var ChatStreamMapper = class {
|
|
|
260
264
|
presentation: hasToolCall(message) ? "narration" : "answer",
|
|
261
265
|
usage: extractUsage(message)
|
|
262
266
|
}));
|
|
267
|
+
if (this.currentAssistantText) this.lastAssistantText = this.currentAssistantText;
|
|
263
268
|
this.lastAssistantMessageId = messageId;
|
|
264
269
|
this.currentAssistantMessageId = void 0;
|
|
265
270
|
this.currentAssistantText = "";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolActivity } from '@xopcai/gateway-contract';
|
|
1
|
+
import type { ToolActivity, TurnOutcome } from '@xopcai/gateway-contract';
|
|
2
2
|
export type ChatStreamStatus = 'success' | 'error' | 'cancelled';
|
|
3
3
|
export type PetFeedbackTaskState = 'working' | 'waiting' | 'success' | 'error';
|
|
4
4
|
export type PetFeedbackSensitivity = 'public' | 'private';
|
|
@@ -142,6 +142,7 @@ export type TurnDiffEvent = ChatStreamEnvelope<'turn_diff', {
|
|
|
142
142
|
added: number;
|
|
143
143
|
removed: number;
|
|
144
144
|
}>;
|
|
145
|
+
export type TurnOutcomeEvent = ChatStreamEnvelope<'turn_outcome', TurnOutcome>;
|
|
145
146
|
export type ReviewStartEvent = ChatStreamEnvelope<'review_start', {
|
|
146
147
|
messageId: string;
|
|
147
148
|
reviewId: string;
|
|
@@ -237,4 +238,4 @@ export type StreamErrorEvent = ChatStreamEnvelope<'error', {
|
|
|
237
238
|
recoverable?: boolean;
|
|
238
239
|
petFeedback: PetFeedback;
|
|
239
240
|
}>;
|
|
240
|
-
export type ChatStreamEvent = RunStartEvent | UserMessageEvent | UserTranscriptEvent | AssistantMessageStartEvent | AssistantDeltaEvent | ThinkingDeltaEvent | ThinkingEndEvent | ToolStartEvent | ToolUpdateEvent | ToolEndEvent | CommandStartedEvent | CommandOutputDeltaEvent | CommandCompletedEvent | PatchAppliedEvent | TurnPlanUpdatedEvent | TaskPlanUpdatedEvent | TurnDiffEvent | ReviewStartEvent | ReviewDeltaEvent | ReviewEndEvent | ReviewEvent | AssistantMessageEndEvent | ProgressEvent | CompactionEvent | TtsAudioEvent | ClarifyRequestEvent | MemoryConsentRequiredEvent | MemoryCapturedEvent | MemoryCandidateEvent | RunEndEvent | StreamErrorEvent;
|
|
241
|
+
export type ChatStreamEvent = RunStartEvent | UserMessageEvent | UserTranscriptEvent | AssistantMessageStartEvent | AssistantDeltaEvent | ThinkingDeltaEvent | ThinkingEndEvent | ToolStartEvent | ToolUpdateEvent | ToolEndEvent | CommandStartedEvent | CommandOutputDeltaEvent | CommandCompletedEvent | PatchAppliedEvent | TurnPlanUpdatedEvent | TaskPlanUpdatedEvent | TurnDiffEvent | TurnOutcomeEvent | ReviewStartEvent | ReviewDeltaEvent | ReviewEndEvent | ReviewEvent | AssistantMessageEndEvent | ProgressEvent | CompactionEvent | TtsAudioEvent | ClarifyRequestEvent | MemoryConsentRequiredEvent | MemoryCapturedEvent | MemoryCandidateEvent | RunEndEvent | StreamErrorEvent;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AgentStreamRunStatus, TurnOutcome } from '@xopcai/gateway-contract';
|
|
2
|
+
import type { ChatStreamEvent } from './protocol.js';
|
|
3
|
+
export declare class TurnOutcomeCollector {
|
|
4
|
+
private readonly runId;
|
|
5
|
+
private readonly environment;
|
|
6
|
+
private readonly deliverables;
|
|
7
|
+
private readonly evidence;
|
|
8
|
+
private readonly files;
|
|
9
|
+
private readonly diffs;
|
|
10
|
+
private added;
|
|
11
|
+
private removed;
|
|
12
|
+
private failedToolCount;
|
|
13
|
+
constructor(runId: string, environment?: 'workspace' | 'worktree' | 'remote_runtime');
|
|
14
|
+
capture(event: ChatStreamEvent): void;
|
|
15
|
+
finalize(status: AgentStreamRunStatus, summary?: string): TurnOutcome;
|
|
16
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { TurnOutcomeDeliverableSchema } from "../../../packages/gateway-contract/src/turn-outcome.js";
|
|
2
|
+
//#region src/gateway/chat-stream/turn-outcome-collector.ts
|
|
3
|
+
const VERIFICATION_COMMAND = /(^|[\s:/_-])(test|vitest|jest|pytest|lint|typecheck|type-check|build)([\s:/_-]|$)/i;
|
|
4
|
+
const MAX_OUTCOME_DIFF_CHARS = 2e5;
|
|
5
|
+
function asRecord(value) {
|
|
6
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
7
|
+
}
|
|
8
|
+
function optionalString(value) {
|
|
9
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
10
|
+
}
|
|
11
|
+
function fileStatus(kind) {
|
|
12
|
+
if (kind === "add") return "added";
|
|
13
|
+
if (kind === "delete") return "deleted";
|
|
14
|
+
if (kind === "move") return "renamed";
|
|
15
|
+
if (kind === "update") return "modified";
|
|
16
|
+
}
|
|
17
|
+
function changedFiles(changes) {
|
|
18
|
+
return changes.flatMap((value) => {
|
|
19
|
+
const row = asRecord(value);
|
|
20
|
+
const path = optionalString(row?.moveTo) ?? optionalString(row?.path);
|
|
21
|
+
if (!path) return [];
|
|
22
|
+
return [{
|
|
23
|
+
path,
|
|
24
|
+
...fileStatus(row?.kind) ? { status: fileStatus(row?.kind) } : {},
|
|
25
|
+
...typeof row?.added === "number" ? { added: Math.max(0, row.added) } : {},
|
|
26
|
+
...typeof row?.removed === "number" ? { removed: Math.max(0, row.removed) } : {}
|
|
27
|
+
}];
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function structuredDeliverables(details) {
|
|
31
|
+
if (!Array.isArray(details.artifacts)) return [];
|
|
32
|
+
return details.artifacts.flatMap((value) => {
|
|
33
|
+
const parsed = TurnOutcomeDeliverableSchema.safeParse(value);
|
|
34
|
+
return parsed.success ? [parsed.data] : [];
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
var TurnOutcomeCollector = class {
|
|
38
|
+
deliverables = /* @__PURE__ */ new Map();
|
|
39
|
+
evidence = /* @__PURE__ */ new Map();
|
|
40
|
+
files = /* @__PURE__ */ new Map();
|
|
41
|
+
diffs = [];
|
|
42
|
+
added = 0;
|
|
43
|
+
removed = 0;
|
|
44
|
+
failedToolCount = 0;
|
|
45
|
+
constructor(runId, environment = "workspace") {
|
|
46
|
+
this.runId = runId;
|
|
47
|
+
this.environment = environment;
|
|
48
|
+
}
|
|
49
|
+
capture(event) {
|
|
50
|
+
if (event.type === "tool_end") {
|
|
51
|
+
if (event.payload.status !== "success") {
|
|
52
|
+
this.failedToolCount += 1;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const details = asRecord(event.payload.result?.details);
|
|
56
|
+
if (!details) return;
|
|
57
|
+
for (const artifact of structuredDeliverables(details)) this.deliverables.set(artifact.artifactId, artifact);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (event.type === "patch_applied") {
|
|
61
|
+
for (const file of changedFiles(event.payload.changes)) this.files.set(file.path, file);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (event.type === "turn_diff") {
|
|
65
|
+
for (const path of event.payload.files) if (!this.files.has(path)) this.files.set(path, { path });
|
|
66
|
+
if (event.payload.diff.trim()) this.diffs.push(event.payload.diff);
|
|
67
|
+
this.added += Math.max(0, event.payload.added);
|
|
68
|
+
this.removed += Math.max(0, event.payload.removed);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (event.type === "command_completed" && VERIFICATION_COMMAND.test(event.payload.command)) {
|
|
72
|
+
const status = event.payload.exitCode === 0 && !event.payload.timedOut ? "passed" : "failed";
|
|
73
|
+
this.evidence.set(event.payload.toolCallId, {
|
|
74
|
+
evidenceId: `${this.runId}:${event.payload.toolCallId}:check`,
|
|
75
|
+
kind: "check",
|
|
76
|
+
label: event.payload.command,
|
|
77
|
+
status,
|
|
78
|
+
command: event.payload.command,
|
|
79
|
+
...event.payload.durationMs !== void 0 ? { durationMs: event.payload.durationMs } : {}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
finalize(status, summary) {
|
|
84
|
+
const evidence = [...this.evidence.values()];
|
|
85
|
+
const partial = this.failedToolCount > 0 || evidence.some((item) => item.status === "failed");
|
|
86
|
+
const fullDiff = this.diffs.join("\n");
|
|
87
|
+
const diffTruncated = fullDiff.length > MAX_OUTCOME_DIFF_CHARS;
|
|
88
|
+
return {
|
|
89
|
+
version: 1,
|
|
90
|
+
outcomeId: `${this.runId}:outcome`,
|
|
91
|
+
runId: this.runId,
|
|
92
|
+
turnId: this.runId,
|
|
93
|
+
status: status === "error" ? "failed" : status === "cancelled" || partial ? "partial" : "succeeded",
|
|
94
|
+
...summary?.trim() ? { summary: summary.trim() } : {},
|
|
95
|
+
deliverables: [...this.deliverables.values()],
|
|
96
|
+
...this.files.size > 0 || this.diffs.length > 0 ? { changeSet: {
|
|
97
|
+
changeSetId: `${this.runId}:changes`,
|
|
98
|
+
files: [...this.files.values()],
|
|
99
|
+
added: this.added,
|
|
100
|
+
removed: this.removed,
|
|
101
|
+
diff: diffTruncated ? fullDiff.slice(0, MAX_OUTCOME_DIFF_CHARS) : fullDiff,
|
|
102
|
+
...diffTruncated ? { diffTruncated: true } : {},
|
|
103
|
+
environment: this.environment
|
|
104
|
+
} } : {},
|
|
105
|
+
evidence,
|
|
106
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
//#endregion
|
|
111
|
+
export { TurnOutcomeCollector };
|
|
@@ -52,7 +52,7 @@ function resolveCacheControl(relativePath) {
|
|
|
52
52
|
function resolveContentType(relativePath) {
|
|
53
53
|
return MIME_TYPES[relativePath.split(".").pop()?.toLowerCase() || ""] || "application/octet-stream";
|
|
54
54
|
}
|
|
55
|
-
function
|
|
55
|
+
function readStaticFile(relativePath, cache) {
|
|
56
56
|
const filePath = resolve(UI_STATIC_ROOT, relativePath);
|
|
57
57
|
try {
|
|
58
58
|
const content = readFileSync(filePath);
|
|
@@ -62,8 +62,10 @@ function loadIntoCache(relativePath) {
|
|
|
62
62
|
etag: computeEtag(content),
|
|
63
63
|
cacheControl: resolveCacheControl(relativePath)
|
|
64
64
|
};
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
if (cache) {
|
|
66
|
+
fileCache.set(relativePath, cached);
|
|
67
|
+
stats.entries = fileCache.size;
|
|
68
|
+
}
|
|
67
69
|
stats.misses += 1;
|
|
68
70
|
return cached;
|
|
69
71
|
} catch {
|
|
@@ -71,12 +73,13 @@ function loadIntoCache(relativePath) {
|
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
function getCachedFile(relativePath) {
|
|
76
|
+
if (relativePath === "index.html") return readStaticFile(relativePath, false);
|
|
74
77
|
const cached = fileCache.get(relativePath);
|
|
75
78
|
if (cached) {
|
|
76
79
|
stats.hits += 1;
|
|
77
80
|
return cached;
|
|
78
81
|
}
|
|
79
|
-
return
|
|
82
|
+
return readStaticFile(relativePath, true);
|
|
80
83
|
}
|
|
81
84
|
function getStaticUiCacheStats() {
|
|
82
85
|
return { ...stats };
|
|
@@ -92,7 +95,6 @@ function resolveStaticUiRootForTests() {
|
|
|
92
95
|
return UI_STATIC_ROOT;
|
|
93
96
|
}
|
|
94
97
|
const DEFAULT_PREWARM_PATHS = [
|
|
95
|
-
"index.html",
|
|
96
98
|
"favicon.ico",
|
|
97
99
|
"logo.svg",
|
|
98
100
|
"logo-dark.svg"
|
|
@@ -8,6 +8,7 @@ import { registerProjectsRoutes } from "./projects.js";
|
|
|
8
8
|
import { registerProjectSkillRoutes } from "./project-skills.js";
|
|
9
9
|
import { registerSearchRoutes } from "./search.js";
|
|
10
10
|
import { registerMobileRoutes } from "./mobile.js";
|
|
11
|
+
import { registerNotificationRoutes } from "./notifications.js";
|
|
11
12
|
import { registerInteractionStateRoutes } from "./interaction-state.js";
|
|
12
13
|
import { registerComposerHistoryRoutes } from "./composer-history.js";
|
|
13
14
|
import { registerEndpointToolRoutes } from "./endpoint-tools.js";
|
|
@@ -35,6 +36,7 @@ function registerCoreAuthenticatedRoutes(authenticated, deps) {
|
|
|
35
36
|
registerProactiveRoutes(authenticated, deps);
|
|
36
37
|
registerSearchRoutes(authenticated, deps);
|
|
37
38
|
registerMobileRoutes(authenticated, deps);
|
|
39
|
+
registerNotificationRoutes(authenticated, deps);
|
|
38
40
|
registerInteractionStateRoutes(authenticated, deps);
|
|
39
41
|
registerComposerHistoryRoutes(authenticated, deps);
|
|
40
42
|
registerEndpointToolRoutes(authenticated, deps);
|
|
@@ -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";
|
|
@@ -67,7 +67,10 @@ function applySourceRevocationChoices(impact, options) {
|
|
|
67
67
|
} else updateUserFocus(id, { status: "paused" });
|
|
68
68
|
for (const id of impact.understandingIds) if (options.derived === "delete") {
|
|
69
69
|
if (deleteUnderstanding(id)) derivedDeleted += 1;
|
|
70
|
-
} else setUnderstandingStatus(id, "needs_review"
|
|
70
|
+
} else setUnderstandingStatus(id, "needs_review", {
|
|
71
|
+
actorType: "runtime",
|
|
72
|
+
source: "understanding-source-revoked"
|
|
73
|
+
});
|
|
71
74
|
if (options.derived === "delete" && impact.sourceInstanceId) derivedDeleted += deleteMemoryRecordsBySourceInstanceId(impact.sourceInstanceId);
|
|
72
75
|
const rawDeleted = options.raw === "delete" && impact.sourceInstanceId ? deleteKnowledgeSourceItems(impact.sourceInstanceId) : 0;
|
|
73
76
|
return {
|