@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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
|
|
2
|
+
import { enqueueTaskAttentionRequiredEvent } from "./task-change-events.js";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
//#region src/tasks/task-run-repository.ts
|
|
4
5
|
const ACTIVE_RUN_STATUSES = [
|
|
@@ -237,6 +238,18 @@ var TaskRunRepository = class {
|
|
|
237
238
|
reason: input.reason.trim(),
|
|
238
239
|
resumeAt: input.resumeAt
|
|
239
240
|
}, input.actor ?? { kind: "system" }, now);
|
|
241
|
+
if (input.kind === "user_input" || input.kind === "approval") {
|
|
242
|
+
const task = db.prepare("SELECT title, project_id FROM tasks WHERE task_id = ?").get(input.taskId);
|
|
243
|
+
if (task) enqueueTaskAttentionRequiredEvent(db, {
|
|
244
|
+
taskId: input.taskId,
|
|
245
|
+
taskTitle: task.title,
|
|
246
|
+
...task.project_id ? { projectId: task.project_id } : {},
|
|
247
|
+
reason: input.kind,
|
|
248
|
+
detail: input.reason.trim(),
|
|
249
|
+
correlationId: id,
|
|
250
|
+
occurredAt: now
|
|
251
|
+
});
|
|
252
|
+
}
|
|
240
253
|
});
|
|
241
254
|
return this.requireWait(id);
|
|
242
255
|
}
|
|
@@ -96,6 +96,10 @@ export declare const UserMemoryConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
|
96
96
|
}, z.core.$strict>>;
|
|
97
97
|
export declare const UserUnderstandingConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
98
98
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
99
|
+
processingPolicy: z.ZodDefault<z.ZodEnum<{
|
|
100
|
+
local_only: "local_only";
|
|
101
|
+
remote_allowed: "remote_allowed";
|
|
102
|
+
}>>;
|
|
99
103
|
adaptiveCadence: z.ZodDefault<z.ZodBoolean>;
|
|
100
104
|
reviewIntervalTurns: z.ZodDefault<z.ZodNumber>;
|
|
101
105
|
maxHistoryMessages: z.ZodDefault<z.ZodNumber>;
|
|
@@ -204,6 +208,10 @@ export declare const UserContextConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
|
204
208
|
}, z.core.$strict>>;
|
|
205
209
|
understanding: z.ZodDefault<z.ZodObject<{
|
|
206
210
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
211
|
+
processingPolicy: z.ZodDefault<z.ZodEnum<{
|
|
212
|
+
local_only: "local_only";
|
|
213
|
+
remote_allowed: "remote_allowed";
|
|
214
|
+
}>>;
|
|
207
215
|
adaptiveCadence: z.ZodDefault<z.ZodBoolean>;
|
|
208
216
|
reviewIntervalTurns: z.ZodDefault<z.ZodNumber>;
|
|
209
217
|
maxHistoryMessages: z.ZodDefault<z.ZodNumber>;
|
|
@@ -91,12 +91,14 @@ var init_config = __esmMin((() => {
|
|
|
91
91
|
});
|
|
92
92
|
UserUnderstandingConfigSchema = z.object({
|
|
93
93
|
enabled: z.boolean().default(true),
|
|
94
|
+
processingPolicy: z.enum(["local_only", "remote_allowed"]).default("remote_allowed"),
|
|
94
95
|
adaptiveCadence: z.boolean().default(true),
|
|
95
96
|
reviewIntervalTurns: z.number().int().min(1).max(1e3).default(10),
|
|
96
97
|
maxHistoryMessages: z.number().int().min(1).max(200).default(80),
|
|
97
98
|
maxDurationMs: z.number().int().min(1e3).max(6e5).default(12e4)
|
|
98
99
|
}).strict().default({
|
|
99
100
|
enabled: true,
|
|
101
|
+
processingPolicy: "remote_allowed",
|
|
100
102
|
adaptiveCadence: true,
|
|
101
103
|
reviewIntervalTurns: 10,
|
|
102
104
|
maxHistoryMessages: 80,
|
|
@@ -161,6 +163,7 @@ var init_config = __esmMin((() => {
|
|
|
161
163
|
},
|
|
162
164
|
understanding: {
|
|
163
165
|
enabled: true,
|
|
166
|
+
processingPolicy: "remote_allowed",
|
|
164
167
|
adaptiveCadence: true,
|
|
165
168
|
reviewIntervalTurns: 10,
|
|
166
169
|
maxHistoryMessages: 80,
|
|
@@ -97,7 +97,10 @@ async function runContextConsolidation(input) {
|
|
|
97
97
|
const evidenceCount = distinctEvidenceCount(understanding.id, "supports");
|
|
98
98
|
const contradictionCount = distinctEvidenceCount(understanding.id, "contradicts");
|
|
99
99
|
if (understanding.validTo != null && understanding.validTo <= now || understanding.expiresAt != null && understanding.expiresAt <= now) {
|
|
100
|
-
setUnderstandingStatus(understanding.id, "stale"
|
|
100
|
+
setUnderstandingStatus(understanding.id, "stale", {
|
|
101
|
+
actorType: "runtime",
|
|
102
|
+
source: "consolidation-expired"
|
|
103
|
+
});
|
|
101
104
|
recordContextConsolidationDecision({
|
|
102
105
|
runId: run.runId,
|
|
103
106
|
understandingId: understanding.id,
|
|
@@ -110,7 +113,10 @@ async function runContextConsolidation(input) {
|
|
|
110
113
|
continue;
|
|
111
114
|
}
|
|
112
115
|
if (contradictionCount > 0) {
|
|
113
|
-
setUnderstandingStatus(understanding.id, "needs_review"
|
|
116
|
+
setUnderstandingStatus(understanding.id, "needs_review", {
|
|
117
|
+
actorType: "runtime",
|
|
118
|
+
source: "consolidation-contradiction"
|
|
119
|
+
});
|
|
114
120
|
recordContextConsolidationDecision({
|
|
115
121
|
runId: run.runId,
|
|
116
122
|
understandingId: understanding.id,
|
|
@@ -123,7 +129,10 @@ async function runContextConsolidation(input) {
|
|
|
123
129
|
continue;
|
|
124
130
|
}
|
|
125
131
|
if (understanding.status === "active" && understanding.reviewAt != null && understanding.reviewAt <= now) {
|
|
126
|
-
setUnderstandingStatus(understanding.id, "needs_review"
|
|
132
|
+
setUnderstandingStatus(understanding.id, "needs_review", {
|
|
133
|
+
actorType: "runtime",
|
|
134
|
+
source: "consolidation-review-due"
|
|
135
|
+
});
|
|
127
136
|
recordContextConsolidationDecision({
|
|
128
137
|
runId: run.runId,
|
|
129
138
|
understandingId: understanding.id,
|
|
@@ -136,7 +145,10 @@ async function runContextConsolidation(input) {
|
|
|
136
145
|
continue;
|
|
137
146
|
}
|
|
138
147
|
if (understanding.status === "candidate" && evidenceCount >= resolved.minEvidenceSources) {
|
|
139
|
-
setUnderstandingStatus(understanding.id, "needs_review"
|
|
148
|
+
setUnderstandingStatus(understanding.id, "needs_review", {
|
|
149
|
+
actorType: "runtime",
|
|
150
|
+
source: "consolidation-evidence-threshold"
|
|
151
|
+
});
|
|
140
152
|
recordContextConsolidationDecision({
|
|
141
153
|
runId: run.runId,
|
|
142
154
|
understandingId: understanding.id,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Config } from '../../config/schema.js';
|
|
2
|
+
import type { MemoryManager } from '../../agent/memory/manager.js';
|
|
3
|
+
import type { UnderstandingReviewResult } from '../../agent/memory/understanding/types.js';
|
|
4
|
+
import { type ExtractorId } from './registry.js';
|
|
5
|
+
import type { SemanticEvidence, SemanticUnderstandingInterpretation } from './semantic.js';
|
|
6
|
+
export type UnderstandingEvidenceMessage = SemanticEvidence & {
|
|
7
|
+
createdAt: number;
|
|
8
|
+
message: unknown;
|
|
9
|
+
};
|
|
10
|
+
export declare function emptyUnderstandingReview(): UnderstandingReviewResult;
|
|
11
|
+
export declare function executeUnderstandingInterpretation(params: {
|
|
12
|
+
interpretation: SemanticUnderstandingInterpretation;
|
|
13
|
+
evidence: UnderstandingEvidenceMessage[];
|
|
14
|
+
extractionRunId: string;
|
|
15
|
+
extractorId: ExtractorId;
|
|
16
|
+
sessionKey: string;
|
|
17
|
+
turnId?: string;
|
|
18
|
+
memoryManager: MemoryManager;
|
|
19
|
+
getConfig: () => Config | undefined;
|
|
20
|
+
reviewSource: 'turn' | 'background';
|
|
21
|
+
processingPolicy: 'local_only' | 'remote_allowed';
|
|
22
|
+
}): Promise<UnderstandingReviewResult>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { createContextEvidence, getTurnPersonalization, getUnderstanding, recordContextFeedback, rejectUnderstanding, setUnderstandingStatus } from "../../storage/sqlite/user-context-repository.js";
|
|
2
|
+
import { getSessionMetadata } from "../../storage/sqlite/session-repository.js";
|
|
3
|
+
import "../../storage/sqlite/index.js";
|
|
4
|
+
import { extractionInputHash } from "./registry.js";
|
|
5
|
+
//#region src/user-context/extraction/executor.ts
|
|
6
|
+
function emptyUnderstandingReview() {
|
|
7
|
+
return {
|
|
8
|
+
proposed: 0,
|
|
9
|
+
created: 0,
|
|
10
|
+
deduplicated: 0,
|
|
11
|
+
rejected: 0,
|
|
12
|
+
createdRecords: [],
|
|
13
|
+
writeOutputs: []
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function resolveWritePolicy(config) {
|
|
17
|
+
const memory = config?.userContext.memory;
|
|
18
|
+
if (!memory || memory.mode === "off" || memory.mode === "readOnly") return "deny";
|
|
19
|
+
return memory.writePolicy?.understanding ?? (memory.mode === "auto" ? "allow" : "confirm");
|
|
20
|
+
}
|
|
21
|
+
function recordTargetFeedback(turnId, targetIds, rating, reason) {
|
|
22
|
+
if (!turnId || targetIds.length === 0) return;
|
|
23
|
+
const personalization = getTurnPersonalization(turnId);
|
|
24
|
+
if (!personalization) return;
|
|
25
|
+
for (const objectId of targetIds) recordContextFeedback({
|
|
26
|
+
turnId,
|
|
27
|
+
runId: personalization.runId,
|
|
28
|
+
objectType: "understanding",
|
|
29
|
+
objectId,
|
|
30
|
+
rating,
|
|
31
|
+
reason
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async function executeUnderstandingInterpretation(params) {
|
|
35
|
+
const { interpretation } = params;
|
|
36
|
+
const result = emptyUnderstandingReview();
|
|
37
|
+
const targets = interpretation.targetUnderstandingIds.flatMap((id) => {
|
|
38
|
+
const item = getUnderstanding(id);
|
|
39
|
+
return item ? [item] : [];
|
|
40
|
+
});
|
|
41
|
+
const targetIds = targets.map((item) => item.id);
|
|
42
|
+
const policy = resolveWritePolicy(params.getConfig());
|
|
43
|
+
if (interpretation.intent === "memory_forget") {
|
|
44
|
+
for (const target of targets) {
|
|
45
|
+
const rejected = rejectUnderstanding(target.id, "explicit user forget request", "user");
|
|
46
|
+
result.writeOutputs.push({
|
|
47
|
+
candidateKey: rejected.canonicalKey,
|
|
48
|
+
objectId: rejected.id,
|
|
49
|
+
versionId: rejected.versionId,
|
|
50
|
+
outcome: "rejected"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
result.rejected += targets.length;
|
|
54
|
+
recordTargetFeedback(params.turnId, targetIds, "irrelevant", "explicit_user_forget_request");
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
if (interpretation.intent === "memory_confirm" && policy !== "deny") {
|
|
58
|
+
for (const target of targets) {
|
|
59
|
+
const confirmed = setUnderstandingStatus(target.id, "active", {
|
|
60
|
+
explicitness: "explicit",
|
|
61
|
+
confidence: 1,
|
|
62
|
+
actorType: "user",
|
|
63
|
+
source: "semantic-memory-confirmation"
|
|
64
|
+
});
|
|
65
|
+
result.createdRecords.push({
|
|
66
|
+
id: confirmed.id,
|
|
67
|
+
content: confirmed.statement,
|
|
68
|
+
kind: confirmed.kind,
|
|
69
|
+
status: confirmed.status
|
|
70
|
+
});
|
|
71
|
+
result.writeOutputs.push({
|
|
72
|
+
candidateKey: confirmed.canonicalKey,
|
|
73
|
+
objectId: confirmed.id,
|
|
74
|
+
versionId: confirmed.versionId,
|
|
75
|
+
outcome: "deduplicated"
|
|
76
|
+
});
|
|
77
|
+
result.deduplicated += 1;
|
|
78
|
+
}
|
|
79
|
+
recordTargetFeedback(params.turnId, targetIds, "helpful", "explicit_user_confirmation");
|
|
80
|
+
}
|
|
81
|
+
if (interpretation.intent === "memory_correct" && targets.length && interpretation.candidates.length === 0) {
|
|
82
|
+
for (const target of targets) setUnderstandingStatus(target.id, "needs_review", {
|
|
83
|
+
actorType: "user",
|
|
84
|
+
source: "semantic-memory-correction"
|
|
85
|
+
});
|
|
86
|
+
recordTargetFeedback(params.turnId, targetIds, "wrong", "explicit_user_correction_without_replacement");
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
if (interpretation.candidates.length === 0) return result;
|
|
90
|
+
if (policy === "deny") {
|
|
91
|
+
result.proposed = interpretation.candidates.length;
|
|
92
|
+
result.rejected = interpretation.candidates.length;
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
const evidenceByRef = new Map(params.evidence.map((entry) => [entry.ref, entry]));
|
|
96
|
+
const candidates = interpretation.candidates.map((candidate) => ({
|
|
97
|
+
...candidate,
|
|
98
|
+
explicitness: policy === "confirm" && candidate.explicitness === "explicit" ? "observed" : candidate.explicitness
|
|
99
|
+
}));
|
|
100
|
+
const evidenceIdsByRef = /* @__PURE__ */ new Map();
|
|
101
|
+
for (const ref of new Set(candidates.flatMap((candidate) => candidate.evidenceRefs))) {
|
|
102
|
+
const entry = evidenceByRef.get(ref);
|
|
103
|
+
if (!entry || entry.role !== "user") continue;
|
|
104
|
+
const evidence = createContextEvidence({
|
|
105
|
+
sourceType: "conversation",
|
|
106
|
+
sourceRef: `session:${params.sessionKey}:entry:${entry.ref}`,
|
|
107
|
+
sourceRunId: params.extractionRunId,
|
|
108
|
+
sessionId: params.sessionKey,
|
|
109
|
+
...params.turnId ? { turnId: params.turnId } : {},
|
|
110
|
+
messageId: entry.ref,
|
|
111
|
+
contentHash: extractionInputHash(JSON.stringify(entry.message)),
|
|
112
|
+
retentionPolicy: "derived_only",
|
|
113
|
+
processingPolicy: params.processingPolicy,
|
|
114
|
+
extractorId: params.extractorId,
|
|
115
|
+
extractorVersion: "1",
|
|
116
|
+
trustLevel: "owner",
|
|
117
|
+
observedAt: entry.createdAt
|
|
118
|
+
});
|
|
119
|
+
evidenceIdsByRef.set(ref, evidence.id);
|
|
120
|
+
}
|
|
121
|
+
const projectId = getSessionMetadata(params.sessionKey)?.projectId;
|
|
122
|
+
for (const candidate of candidates) {
|
|
123
|
+
const applied = await params.memoryManager.applyUnderstandingCandidates([candidate], {
|
|
124
|
+
sessionKey: params.sessionKey,
|
|
125
|
+
...projectId ? { projectId } : {},
|
|
126
|
+
evidenceIds: candidate.evidenceRefs.flatMap((ref) => evidenceIdsByRef.get(ref) ?? []),
|
|
127
|
+
reviewSource: params.reviewSource,
|
|
128
|
+
extractionRunId: params.extractionRunId,
|
|
129
|
+
...interpretation.intent === "memory_correct" ? { supersedesRecordIds: targetIds } : {}
|
|
130
|
+
});
|
|
131
|
+
result.proposed += applied.proposed;
|
|
132
|
+
result.created += applied.created;
|
|
133
|
+
result.deduplicated += applied.deduplicated;
|
|
134
|
+
result.rejected += applied.rejected;
|
|
135
|
+
result.createdRecords.push(...applied.createdRecords);
|
|
136
|
+
result.writeOutputs.push(...applied.writeOutputs ?? []);
|
|
137
|
+
}
|
|
138
|
+
if (interpretation.intent === "memory_correct" && result.created > 0) recordTargetFeedback(params.turnId, targetIds, "wrong", "explicit_user_correction_with_replacement");
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { emptyUnderstandingReview, executeUnderstandingInterpretation };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ContextExtractionRun } from '../../storage/sqlite/index.js';
|
|
2
2
|
import type { UnderstandingKind } from '../domain.js';
|
|
3
|
-
export type ExtractorId = '
|
|
3
|
+
export type ExtractorId = 'turn-semantics' | 'transcript-synthesis' | 'connector-semantic';
|
|
4
4
|
export type ExtractorDefinition = {
|
|
5
5
|
id: ExtractorId;
|
|
6
6
|
version: string;
|
|
@@ -14,62 +14,33 @@ const UNDERSTANDING_KINDS = [
|
|
|
14
14
|
"derived_insight"
|
|
15
15
|
];
|
|
16
16
|
const DEFINITIONS = {
|
|
17
|
-
"
|
|
18
|
-
id: "
|
|
17
|
+
"turn-semantics": {
|
|
18
|
+
id: "turn-semantics",
|
|
19
19
|
version: "1",
|
|
20
20
|
inputKinds: ["conversation"],
|
|
21
21
|
requiredProcessingPolicy: "local_only",
|
|
22
22
|
authorityCeiling: "user_explicit",
|
|
23
23
|
candidateKinds: UNDERSTANDING_KINDS,
|
|
24
24
|
maxAutomaticStatus: "active",
|
|
25
|
-
timeoutMs:
|
|
26
|
-
},
|
|
27
|
-
"deterministic-signal": {
|
|
28
|
-
id: "deterministic-signal",
|
|
29
|
-
version: "1",
|
|
30
|
-
inputKinds: ["conversation", "task"],
|
|
31
|
-
requiredProcessingPolicy: "local_only",
|
|
32
|
-
authorityCeiling: "user_observed",
|
|
33
|
-
candidateKinds: UNDERSTANDING_KINDS,
|
|
34
|
-
maxAutomaticStatus: "candidate",
|
|
35
|
-
timeoutMs: 500
|
|
25
|
+
timeoutMs: 3e4
|
|
36
26
|
},
|
|
37
27
|
"transcript-synthesis": {
|
|
38
28
|
id: "transcript-synthesis",
|
|
39
29
|
version: "1",
|
|
40
30
|
inputKinds: ["conversation"],
|
|
41
|
-
requiredProcessingPolicy: "
|
|
31
|
+
requiredProcessingPolicy: "local_only",
|
|
42
32
|
authorityCeiling: "system_inferred",
|
|
43
33
|
candidateKinds: UNDERSTANDING_KINDS,
|
|
44
34
|
maxAutomaticStatus: "candidate",
|
|
45
35
|
timeoutMs: 3e4
|
|
46
36
|
},
|
|
47
|
-
"connector-structural": {
|
|
48
|
-
id: "connector-structural",
|
|
49
|
-
version: "1",
|
|
50
|
-
inputKinds: ["connector"],
|
|
51
|
-
requiredProcessingPolicy: "local_only",
|
|
52
|
-
authorityCeiling: "external_untrusted",
|
|
53
|
-
candidateKinds: [
|
|
54
|
-
"project_context",
|
|
55
|
-
"current_state",
|
|
56
|
-
"routine"
|
|
57
|
-
],
|
|
58
|
-
maxAutomaticStatus: "candidate",
|
|
59
|
-
timeoutMs: 1e4
|
|
60
|
-
},
|
|
61
37
|
"connector-semantic": {
|
|
62
38
|
id: "connector-semantic",
|
|
63
39
|
version: "1",
|
|
64
40
|
inputKinds: ["connector", "file"],
|
|
65
41
|
requiredProcessingPolicy: "remote_allowed",
|
|
66
42
|
authorityCeiling: "external_untrusted",
|
|
67
|
-
candidateKinds: [
|
|
68
|
-
"preference",
|
|
69
|
-
"routine",
|
|
70
|
-
"current_state",
|
|
71
|
-
"project_context"
|
|
72
|
-
],
|
|
43
|
+
candidateKinds: ["preference", "routine"],
|
|
73
44
|
maxAutomaticStatus: "candidate",
|
|
74
45
|
timeoutMs: 3e4
|
|
75
46
|
}
|
|
@@ -39,7 +39,10 @@ function repairExtractedContext(filter) {
|
|
|
39
39
|
});
|
|
40
40
|
continue;
|
|
41
41
|
}
|
|
42
|
-
setUnderstandingStatus(output.objectId, "archived"
|
|
42
|
+
setUnderstandingStatus(output.objectId, "archived", {
|
|
43
|
+
actorType: "runtime",
|
|
44
|
+
source: "context-extraction-repair"
|
|
45
|
+
});
|
|
43
46
|
} else {
|
|
44
47
|
const focus = listUserFocuses().find((item) => item.id === output.objectId);
|
|
45
48
|
if (!focus) continue;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { UnderstandingCandidate } from '../../agent/memory/understanding/types.js';
|
|
2
|
+
export declare const UNDERSTANDING_INTENTS: readonly ["memory_create", "memory_query", "memory_confirm", "memory_correct", "memory_forget", "user_assertion", "task_request", "none"];
|
|
3
|
+
export type UnderstandingIntent = typeof UNDERSTANDING_INTENTS[number];
|
|
4
|
+
export type SemanticEvidence = {
|
|
5
|
+
ref: string;
|
|
6
|
+
role: 'user' | 'assistant';
|
|
7
|
+
text: string;
|
|
8
|
+
};
|
|
9
|
+
export type SemanticUnderstandingCandidate = UnderstandingCandidate & {
|
|
10
|
+
evidenceRefs: string[];
|
|
11
|
+
};
|
|
12
|
+
export type SemanticUnderstandingInterpretation = {
|
|
13
|
+
intent: UnderstandingIntent;
|
|
14
|
+
candidates: SemanticUnderstandingCandidate[];
|
|
15
|
+
targetUnderstandingIds: string[];
|
|
16
|
+
abstentionReason?: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function parseSemanticUnderstanding(raw: string, evidence: SemanticEvidence[], allowedTargetIds?: string[]): SemanticUnderstandingInterpretation | null;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { UNDERSTANDING_KINDS } from "../domain.js";
|
|
2
|
+
import { isDurableUnderstandingCandidate } from "../understandingQuality.js";
|
|
3
|
+
import { inferMemorySensitivity } from "../../agent/memory/sensitivity.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
//#region src/user-context/extraction/semantic.ts
|
|
6
|
+
const UNDERSTANDING_INTENTS = [
|
|
7
|
+
"memory_create",
|
|
8
|
+
"memory_query",
|
|
9
|
+
"memory_confirm",
|
|
10
|
+
"memory_correct",
|
|
11
|
+
"memory_forget",
|
|
12
|
+
"user_assertion",
|
|
13
|
+
"task_request",
|
|
14
|
+
"none"
|
|
15
|
+
];
|
|
16
|
+
const EvidenceSchema = z.object({
|
|
17
|
+
ref: z.string().min(1),
|
|
18
|
+
quote: z.string().min(1)
|
|
19
|
+
}).strict();
|
|
20
|
+
const CandidateSchema = z.object({
|
|
21
|
+
factKey: z.string().regex(/^[a-z0-9][a-z0-9:-]{2,119}$/),
|
|
22
|
+
statement: z.string().min(4).max(600),
|
|
23
|
+
kind: z.enum(UNDERSTANDING_KINDS),
|
|
24
|
+
explicitness: z.enum([
|
|
25
|
+
"explicit",
|
|
26
|
+
"observed",
|
|
27
|
+
"inferred"
|
|
28
|
+
]),
|
|
29
|
+
durability: z.enum([
|
|
30
|
+
"ephemeral",
|
|
31
|
+
"durable",
|
|
32
|
+
"recurring"
|
|
33
|
+
]),
|
|
34
|
+
scopeHint: z.enum([
|
|
35
|
+
"global",
|
|
36
|
+
"workspace",
|
|
37
|
+
"project",
|
|
38
|
+
"session"
|
|
39
|
+
]),
|
|
40
|
+
confidence: z.number().min(0).max(1),
|
|
41
|
+
importance: z.number().min(0).max(1),
|
|
42
|
+
sensitivity: z.enum([
|
|
43
|
+
"normal",
|
|
44
|
+
"personal",
|
|
45
|
+
"secret",
|
|
46
|
+
"regulated"
|
|
47
|
+
]).optional(),
|
|
48
|
+
disclosurePolicy: z.enum([
|
|
49
|
+
"silent",
|
|
50
|
+
"referenceable",
|
|
51
|
+
"ask_before_reference"
|
|
52
|
+
]).optional(),
|
|
53
|
+
evidence: z.array(EvidenceSchema).min(1).max(8),
|
|
54
|
+
selfContained: z.boolean(),
|
|
55
|
+
unresolvedReferences: z.array(z.string()).max(8)
|
|
56
|
+
}).strict();
|
|
57
|
+
const InterpretationSchema = z.object({
|
|
58
|
+
intent: z.enum(UNDERSTANDING_INTENTS),
|
|
59
|
+
candidates: z.array(CandidateSchema).max(8),
|
|
60
|
+
targetUnderstandingIds: z.array(z.string().min(1)).max(8),
|
|
61
|
+
abstentionReason: z.string().max(500).optional()
|
|
62
|
+
}).strict();
|
|
63
|
+
const CANDIDATE_INTENTS = new Set([
|
|
64
|
+
"memory_create",
|
|
65
|
+
"memory_confirm",
|
|
66
|
+
"memory_correct",
|
|
67
|
+
"user_assertion"
|
|
68
|
+
]);
|
|
69
|
+
const QUESTION_END = /[??]\s*$/u;
|
|
70
|
+
function extractJson(raw) {
|
|
71
|
+
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(raw)?.[1];
|
|
72
|
+
const start = raw.indexOf("{");
|
|
73
|
+
const end = raw.lastIndexOf("}");
|
|
74
|
+
const candidate = fenced ?? (start >= 0 && end > start ? raw.slice(start, end + 1) : raw);
|
|
75
|
+
return JSON.parse(candidate);
|
|
76
|
+
}
|
|
77
|
+
function comparableText(value) {
|
|
78
|
+
return value.normalize("NFKC").toLocaleLowerCase().replace(/\s+/g, " ").trim();
|
|
79
|
+
}
|
|
80
|
+
function quoteIsGrounded(quote, source) {
|
|
81
|
+
return comparableText(source).includes(comparableText(quote));
|
|
82
|
+
}
|
|
83
|
+
function bigramSimilarity(left, right) {
|
|
84
|
+
const pairs = (value) => {
|
|
85
|
+
const normalized = comparableText(value).replace(/[^\p{L}\p{N}]/gu, "");
|
|
86
|
+
const output = /* @__PURE__ */ new Set();
|
|
87
|
+
for (let index = 0; index < normalized.length - 1; index += 1) output.add(normalized.slice(index, index + 2));
|
|
88
|
+
return output;
|
|
89
|
+
};
|
|
90
|
+
const a = pairs(left);
|
|
91
|
+
const b = pairs(right);
|
|
92
|
+
if (!a.size || !b.size) return 0;
|
|
93
|
+
let overlap = 0;
|
|
94
|
+
for (const pair of a) if (b.has(pair)) overlap += 1;
|
|
95
|
+
return 2 * overlap / (a.size + b.size);
|
|
96
|
+
}
|
|
97
|
+
function effectiveExplicitness(intent, declared) {
|
|
98
|
+
if (intent === "memory_create" || intent === "memory_correct" || intent === "memory_confirm") return declared;
|
|
99
|
+
return declared === "explicit" ? "observed" : declared;
|
|
100
|
+
}
|
|
101
|
+
function parseSemanticUnderstanding(raw, evidence, allowedTargetIds = []) {
|
|
102
|
+
let parsed;
|
|
103
|
+
try {
|
|
104
|
+
const result = InterpretationSchema.safeParse(extractJson(raw));
|
|
105
|
+
if (!result.success) return null;
|
|
106
|
+
parsed = result.data;
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const evidenceByRef = new Map(evidence.map((item) => [item.ref, item]));
|
|
111
|
+
const allowedTargets = new Set(allowedTargetIds);
|
|
112
|
+
const candidates = [];
|
|
113
|
+
if (CANDIDATE_INTENTS.has(parsed.intent)) for (const item of parsed.candidates) {
|
|
114
|
+
if (!item.selfContained || item.unresolvedReferences.length > 0) continue;
|
|
115
|
+
if (QUESTION_END.test(item.statement)) continue;
|
|
116
|
+
if (!isDurableUnderstandingCandidate(item.kind, item.statement)) continue;
|
|
117
|
+
if (!item.evidence.every((claim) => {
|
|
118
|
+
const source = evidenceByRef.get(claim.ref);
|
|
119
|
+
return source?.role === "user" && quoteIsGrounded(claim.quote, source.text);
|
|
120
|
+
})) continue;
|
|
121
|
+
if (item.explicitness === "explicit") {
|
|
122
|
+
const quotedText = item.evidence.map((claim) => claim.quote).join(" ");
|
|
123
|
+
if (bigramSimilarity(item.statement, quotedText) < .45) continue;
|
|
124
|
+
}
|
|
125
|
+
const evidenceRefs = [...new Set(item.evidence.map((claim) => claim.ref))];
|
|
126
|
+
candidates.push({
|
|
127
|
+
kind: item.kind,
|
|
128
|
+
content: item.statement.trim(),
|
|
129
|
+
canonicalKey: `understanding:${item.kind}:${item.factKey}`,
|
|
130
|
+
confidence: item.confidence,
|
|
131
|
+
importance: item.importance,
|
|
132
|
+
explicitness: effectiveExplicitness(parsed.intent, item.explicitness),
|
|
133
|
+
durability: item.durability,
|
|
134
|
+
sensitivity: item.sensitivity ?? inferMemorySensitivity(item.statement),
|
|
135
|
+
disclosurePolicy: item.disclosurePolicy ?? "referenceable",
|
|
136
|
+
payload: { scopeHint: item.scopeHint },
|
|
137
|
+
evidenceRefs
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
intent: parsed.intent,
|
|
142
|
+
candidates,
|
|
143
|
+
targetUnderstandingIds: [...new Set(parsed.targetUnderstandingIds.filter((id) => allowedTargets.has(id)))],
|
|
144
|
+
...parsed.abstentionReason ? { abstentionReason: parsed.abstentionReason } : {}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//#endregion
|
|
148
|
+
export { UNDERSTANDING_INTENTS, parseSemanticUnderstanding };
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
const INCOMPLETE_PREFIX = /^(?:and\b|also\b|then\b|plus\b|as\s+well\s+as\b|which\b|that\b|并且|并将|以及|然后|同时|另外|还有|而且|或者|的事项|事项[,,、::]?)/i;
|
|
3
3
|
const DEFERRED_OR_NEGATED_ACTION = /(?:not\s+now|no\s+need\s+to|do\s+not\s+(?:start|proceed)|don't\s+(?:start|proceed)|later\s+maybe|暂时不用|暂时不(?:用|要|开始)?|先不用|无需|不用开始|不要推进|不需要推进)/i;
|
|
4
4
|
const ONE_OFF_ACTION_PREFIX = /^(?:please\s+|update\b|investigate\b|summari[sz]e\b|fix\b|write\b|add\b|record\b|track\b)|^(?:请|帮我|更新|调查|汇总|整理|修复|写入|加入|记录|跟进)/i;
|
|
5
|
+
const DURABLE_MARKER = /(?:从现在起|今后|以后|长期|每次|每回|始终|一直|默认|下次|教训|原则|习惯|from now on|going forward|long[- ]term|every time|always|by default|next time|lesson|principle|habit)/i;
|
|
6
|
+
const TURN_EXECUTION_INSTRUCTION = /(?:不要再问|别再问|直接执行|立即执行|当前任务|这次|本次|现在就|do not ask|don't ask|just do it|execute directly|proceed now|this task|this time)/i;
|
|
5
7
|
function meaningfulLength(content) {
|
|
6
8
|
return content.normalize("NFKC").replace(/[\p{P}\p{S}\s]/gu, "").length;
|
|
7
9
|
}
|
|
@@ -15,6 +17,8 @@ function isActionableUnderstandingContent(content) {
|
|
|
15
17
|
function isDurableUnderstandingCandidate(kind, content) {
|
|
16
18
|
if (!isStandaloneUnderstandingContent(content)) return false;
|
|
17
19
|
if ((kind === "commitment" || kind === "long_term_goal") && ONE_OFF_ACTION_PREFIX.test(content.trim())) return false;
|
|
20
|
+
if (kind === "task_lesson" && !DURABLE_MARKER.test(content)) return false;
|
|
21
|
+
if (kind === "boundary" && TURN_EXECUTION_INSTRUCTION.test(content) && !DURABLE_MARKER.test(content)) return false;
|
|
18
22
|
return true;
|
|
19
23
|
}
|
|
20
24
|
function comparableText(content) {
|
|
@@ -83,7 +83,9 @@ function validateProfileCandidate(value, allowedRefs) {
|
|
|
83
83
|
if (!value || typeof value !== "object") return null;
|
|
84
84
|
const item = value;
|
|
85
85
|
const category = item.category === "role" || item.category === "responsibility" || item.category === "preference" || item.category === "routine" ? item.category : void 0;
|
|
86
|
-
if (!category || typeof item.statement !== "string") return null;
|
|
86
|
+
if (!category || typeof item.statement !== "string" || typeof item.factKey !== "string") return null;
|
|
87
|
+
const factKey = item.factKey.trim().toLocaleLowerCase();
|
|
88
|
+
if (!/^[a-z0-9][a-z0-9:-]{2,119}$/.test(factKey)) return null;
|
|
87
89
|
const statement = item.statement.trim().slice(0, 500);
|
|
88
90
|
if (statement.length < 4) return null;
|
|
89
91
|
const confidence = item.confidence === "high" || item.confidence === "low" ? item.confidence : "medium";
|
|
@@ -92,6 +94,7 @@ function validateProfileCandidate(value, allowedRefs) {
|
|
|
92
94
|
return {
|
|
93
95
|
id: randomUUID(),
|
|
94
96
|
category,
|
|
97
|
+
factKey,
|
|
95
98
|
statement,
|
|
96
99
|
confidence,
|
|
97
100
|
evidence: strings(item.evidence, 4).map((entry) => entry.slice(0, 300)),
|
|
@@ -183,7 +186,8 @@ async function analyzeWorkContext(input) {
|
|
|
183
186
|
"Return only one JSON object with projectSummary, currentState, uncertainties, suggestions, profileCandidates, workThreads, conversationStarter, lowConfidence, and contextQuestion.",
|
|
184
187
|
"profileCandidates contains only user-specific role, responsibility, preference, or routine facts that are directly supported and would remain useful outside this repository snapshot.",
|
|
185
188
|
"Do not put the project stack, packages, architecture, deployment setup, repository conventions, or current task in profileCandidates. Put project facts in projectSummary/currentState and current work in workThreads.",
|
|
186
|
-
"Each profile candidate has category (role, responsibility, preference, or routine), statement, confidence, and evidence.",
|
|
189
|
+
"Each profile candidate has category (role, responsibility, preference, or routine), factKey, statement, confidence, and evidence.",
|
|
190
|
+
"factKey is a stable language-neutral lowercase identifier such as workflow:code-review:github; equivalent facts in different languages must use the same factKey.",
|
|
187
191
|
USER_FACING_UNDERSTANDING_WRITING_GUIDANCE,
|
|
188
192
|
"Do not infer sensitive traits, identity, health, finances, political views, or anything not directly supported by the work evidence.",
|
|
189
193
|
"workThreads contains every distinct evidence-backed work stream with topicKey, title, summary, horizon, status, confidence, and evidenceRefs. Do not merge unrelated streams to force a fixed count.",
|
|
@@ -288,7 +292,8 @@ async function analyzeUnderstandingBatch(input) {
|
|
|
288
292
|
"Return only one JSON object with profileCandidates and workThreads.",
|
|
289
293
|
"Return at most 8 profileCandidates and at most 8 workThreads. Prefer the strongest distinct findings.",
|
|
290
294
|
"profileCandidates contains only user-specific role, responsibility, preference, or routine facts with direct support. Current tasks belong in workThreads; project technologies, packages, architecture, and repository conventions are not user facts.",
|
|
291
|
-
"Each profile candidate has category (role, responsibility, preference, or routine), statement, confidence, evidence, and evidenceRefs.",
|
|
295
|
+
"Each profile candidate has category (role, responsibility, preference, or routine), factKey, statement, confidence, evidence, and evidenceRefs.",
|
|
296
|
+
"factKey is a stable language-neutral lowercase identifier such as workflow:code-review:github; equivalent facts in different languages must use the same factKey.",
|
|
292
297
|
USER_FACING_UNDERSTANDING_WRITING_GUIDANCE,
|
|
293
298
|
"Each work thread has topicKey, title, summary, status, horizon, confidence, and evidenceRefs.",
|
|
294
299
|
"Every evidenceRefs value must be one of the supplied refs. Omit anything without direct support.",
|
|
@@ -359,7 +364,7 @@ function mergeProfileCandidates(candidates) {
|
|
|
359
364
|
high: 3
|
|
360
365
|
};
|
|
361
366
|
for (const candidate of candidates) {
|
|
362
|
-
const key = `${candidate.category}:${candidate.
|
|
367
|
+
const key = `${candidate.category}:${candidate.factKey}`;
|
|
363
368
|
const existing = merged.get(key);
|
|
364
369
|
if (!existing) {
|
|
365
370
|
merged.set(key, candidate);
|
|
@@ -164,8 +164,7 @@ function understandingKind(category) {
|
|
|
164
164
|
return "project_context";
|
|
165
165
|
}
|
|
166
166
|
function understandingKey(candidate) {
|
|
167
|
-
|
|
168
|
-
return `work-discovery:${candidate.category}:${createHash("sha256").update(normalized).digest("hex").slice(0, 20)}`;
|
|
167
|
+
return `understanding:${understandingKind(candidate.category)}:${candidate.factKey}`;
|
|
169
168
|
}
|
|
170
169
|
function sameScope(left, right) {
|
|
171
170
|
return left.type === right.type && left.id === right.id;
|
|
@@ -202,7 +201,7 @@ function decideUnderstanding(input, expectedSourcePrefix) {
|
|
|
202
201
|
const current = getUnderstanding(input.understandingId);
|
|
203
202
|
const owned = current && listUnderstandingEvidence(current.id).some((evidence) => evidence.sourceRef.startsWith(expectedSourcePrefix));
|
|
204
203
|
if (!current || !owned || current.status === "archived") return void 0;
|
|
205
|
-
if (input.status === "rejected") return rejectUnderstanding(current.id, "Rejected from work discovery review");
|
|
204
|
+
if (input.status === "rejected") return rejectUnderstanding(current.id, "Rejected from work discovery review", "user");
|
|
206
205
|
const statement = input.status === "edited" ? input.statement?.trim().slice(0, 500) : void 0;
|
|
207
206
|
if (input.status === "edited" && !statement) return void 0;
|
|
208
207
|
return setUnderstandingStatus((statement ? reviseUnderstanding(current.id, statement, {
|
|
@@ -211,7 +210,9 @@ function decideUnderstanding(input, expectedSourcePrefix) {
|
|
|
211
210
|
changeReason: "Edited during work discovery review"
|
|
212
211
|
}) : current).id, "active", {
|
|
213
212
|
explicitness: "explicit",
|
|
214
|
-
confidence: 1
|
|
213
|
+
confidence: 1,
|
|
214
|
+
actorType: "user",
|
|
215
|
+
source: "work-discovery-review"
|
|
215
216
|
});
|
|
216
217
|
}
|
|
217
218
|
function sessionMetadata(agentId, peerId) {
|
|
@@ -167,6 +167,7 @@ export interface WorkDiscoveryProfileCandidate {
|
|
|
167
167
|
id: string;
|
|
168
168
|
understandingId?: string;
|
|
169
169
|
category: 'role' | 'responsibility' | 'preference' | 'routine';
|
|
170
|
+
factKey: string;
|
|
170
171
|
statement: string;
|
|
171
172
|
confidence: 'high' | 'medium' | 'low';
|
|
172
173
|
evidence: string[];
|