@xopcai/xopc 0.0.241 → 0.0.243
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-CLnbVm9G.js → activity-store-CAah-_8h.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DuBewmbW.js → agent-avatar-dicebear-DDH4HgP7.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BDCfJZhh.js +1 -0
- package/dist/gateway/static/root/assets/agents-B0ZWgf-U.js +1 -0
- package/dist/gateway/static/root/assets/{api-DjBZe303.js → api-B2tKxbcz.js} +1 -1
- package/dist/gateway/static/root/assets/app-management-settings-panel-Blfwszzn.js +1 -0
- package/dist/gateway/static/root/assets/{appearance-settings-B-iul0RG.js → appearance-settings-C3V7Na75.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BiEks0-F.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BOx0EJZs.js → archive-plugin-BmSx7wzY.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Cfk1lwBo.js → attachment-load-BS-S4LJ9.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BTSGvaeS.js → automations-page-C7Y3L30D.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-A3zPkPuo.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-ChZyZK45.js → binary-plugins-BM9B5kcm.js} +1 -1
- package/dist/gateway/static/root/assets/block-editor-BbnpkYP9.js +185 -0
- package/dist/gateway/static/root/assets/browser-settings-page-Dk4FQ7fY.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-jvfcgFG-.js → browser-workflow-inputs-CRnkgZHI.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DrHW7XNi.js → browser-workflows-page-B9qGL-it.js} +2 -2
- package/dist/gateway/static/root/assets/{button-CSEbl4zT.js → button-CtTvuElV.js} +1 -1
- package/dist/gateway/static/root/assets/capabilities-settings-panel--tR_El9e.js +7 -0
- package/dist/gateway/static/root/assets/channels-settings-D347vl_J.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-CC9MFway.js → channels-status-swr-DuY4MGxe.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-DeeZrVbV.js → chat-terminal-dock-DABPvwBT.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-B-tvJkRJ.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-CiqQOeQ3.js → cron-expression-D3bsKbNd.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-CGAMGPfU.js → date-picker-BsGM6Yty.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-CxWeUTsc.js → dependency-picker-Dj3g6YXZ.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-C3QmYO75.js → desktop-pet-C1QT0Sur.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-CAADkWYy.js → desktop-pet-settings-r6kAOnfY.js} +1 -1
- package/dist/gateway/static/root/assets/dist-CpzYSoz7.js +1 -0
- package/dist/gateway/static/root/assets/{dist-DaxPZj9e.js → dist-DBS3OB8K.js} +1 -1
- package/dist/gateway/static/root/assets/dist-DLmwHyAh.js +1 -0
- package/dist/gateway/static/root/assets/es2015-BvLh9GaE.js +41 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-FQXjDJ8P.js → extension-debug-page-DOkf7nh9.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BJE1D5Ji.js → extension-page-Cq2IA4Ho.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-5Ik2tNry.js → extension-settings-page-DQn4qjDZ.js} +1 -1
- package/dist/gateway/static/root/assets/{files-DQjhZjr2.js → files-D6vf3S30.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-cTj71t2a.js → gateway-config-api-DM3poL22.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Bxe_R-JH.js → gateway-config-swr-BC3pgb_P.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-KXBUjNcx.js → gateway-settings-DPgH1hnh.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DJG-I0wW.js → gateway-startup-retry-uMcSfLru.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-C8cVzIcs.js → heartbeat-settings-Bk80-E3b.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-DKo5JiMR.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-Dc_ojQuj.js → image-generation-api-D1qlQA-A.js} +1 -1
- package/dist/gateway/static/root/assets/index-B0WJL9N1.js +71 -0
- package/dist/gateway/static/root/assets/index-Dbh5SXyV.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-pOKl7blR.js → keyboard-shortcuts-settings-BEwvd8ZU.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page--eJ5rmNj.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-Bi6wwKgm.js → local-apps-page-CgkY9E-r.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-C5wr3_pc.js → locale-store-CMZljTJx.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-Z49Td0J9.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-DGlVizWi.js → management-settings-Dv8NSJKt.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-CXP5zBx_.js → markdown-split-Cm0RBB-t.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-D6LxlDxr.js → markdown-view-PPCLt7fu.js} +3 -3
- package/dist/gateway/static/root/assets/{media-plugins-BsENGLr2.js → media-plugins-Bcr5sU1f.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CTSgFlE4.js +3 -0
- package/dist/gateway/static/root/assets/mobile-pairing-wizard-kKDiXofY.js +1 -0
- package/dist/gateway/static/root/assets/{models-hub-cache-Y7GUjxHx.js → models-hub-cache-ZrbGRiGY.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-D2EqpDyo.js → notes-page-CgsaRaGi.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-C1DEE09k.js +4 -0
- package/dist/gateway/static/root/assets/{oauth-api-C5NVcsKE.js → oauth-api-4VeMbkTJ.js} +1 -1
- package/dist/gateway/static/root/assets/popover-select-C-Hj-nXR.js +1 -0
- package/dist/gateway/static/root/assets/{product-delivery-dUJgmBQZ.js → product-delivery-CV4pDOtG.js} +1 -1
- package/dist/gateway/static/root/assets/product-open-page-BU0HiZtv.js +1 -0
- package/dist/gateway/static/root/assets/project-detail-page-isRapnp5.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-zvsjg0mi.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-FXdFaoWM.js → registry-api-CWOtPFrE.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-C9TGZ9Hc.js +1 -0
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-2zm9edMA.js +5 -0
- package/dist/gateway/static/root/assets/{schema-form-BUzdHWx6.js → schema-form-54A5gzkN.js} +1 -1
- package/dist/gateway/static/root/assets/{schemas-zIBW3wiV.js → schemas-BHS7bo06.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-BP8RyiUn.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-D4EMxWAZ.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-C0OBLqpu.js → settings-page-DzDhoyxv.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-NpLQkFCh.js → setup-status-panel-uDicHU1w.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-BtbPYaYC.js → share-preview-page-lOmLCWFS.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-T4Yvouvv.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-DVb7nrXz.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-CYk8pN97.js → skills-page-CnyNH3To.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page.utils-CgDtf2qs.js +1 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-DmCRSvtd.js → system-settings-panel-C8yWfwtR.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-Tzfjlbf3.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-DUko1ZnE.js → theme-store-uxUwr10D.js} +1 -1
- package/dist/gateway/static/root/assets/tunnel-api-Bvg679no.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-W_P8Kiv4.js → use-autosave-D88VGoyG.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-RijPtyfO.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-BZD0j1jc.js → voice-api-key-field-CBHLsMcc.js} +1 -1
- package/dist/gateway/static/root/assets/voice-config-api-MqyI6cgq.js +1 -0
- package/dist/gateway/static/root/assets/work-discovery-overlay-GGe2TQ98.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-C0layUE9.js +3 -0
- package/dist/gateway/static/root/assets/workflows-page-DQXIzBAc.js +5 -0
- package/dist/gateway/static/root/index.html +21 -22
- package/dist/package.js +1 -1
- package/dist/packages/realtime-protocol/src/voice-audio.js +20 -0
- package/dist/packages/realtime-protocol/src/voice.js +208 -0
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/embedded/run-for-session.d.ts +1 -0
- package/dist/src/agent/embedded/run-for-session.js +2 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +2 -1
- package/dist/src/agent/prompt/voice-presentation.d.ts +2 -0
- package/dist/src/agent/prompt/voice-presentation.js +12 -0
- package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -0
- package/dist/src/agent/service/direct-turn-helpers.js +1 -0
- package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
- package/dist/src/agent/service/process-direct-streaming.js +2 -1
- package/dist/src/agent/session/session-config-service.js +4 -2
- package/dist/src/agent/skills/installer.d.ts +1 -0
- package/dist/src/agent/skills/installer.js +9 -6
- package/dist/src/agent/tools/factory.d.ts +2 -0
- package/dist/src/agent/tools/factory.js +5 -1
- package/dist/src/automations/draft/automation-draft-service.js +1 -1
- package/dist/src/config/models-json.d.ts +8 -8
- package/dist/src/config/schema.d.ts +60 -0
- package/dist/src/config/schema.js +36 -4
- package/dist/src/extensions/install.js +1 -1
- package/dist/src/files/file-service.d.ts +1 -0
- package/dist/src/files/file-service.js +4 -0
- package/dist/src/gateway/chat-stream/thinking-delta-coalescer.js +8 -3
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -11
- package/dist/src/gateway/hono/lib/config-payload.js +2 -2
- package/dist/src/gateway/hono/lib/safe-voice-config.d.ts +14 -0
- package/dist/src/gateway/hono/lib/safe-voice-config.js +29 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -2
- package/dist/src/gateway/hono/routes/files.js +7 -0
- package/dist/src/gateway/hono/routes/lazy-fallback.js +18 -4
- package/dist/src/gateway/hono/routes/runtime-tools.js +7 -1
- package/dist/src/gateway/hono/routes/session-input-handler.js +14 -0
- package/dist/src/gateway/hono/routes/sessions.js +4 -1
- package/dist/src/gateway/hono/routes/voice.js +140 -3
- package/dist/src/gateway/server.js +1 -0
- package/dist/src/gateway/service/agent-runner.d.ts +1 -0
- package/dist/src/gateway/service/agent-runner.js +1 -6
- package/dist/src/gateway/service/run-gateway-agent.d.ts +1 -0
- package/dist/src/gateway/service/run-gateway-agent.js +19 -1
- package/dist/src/gateway/service.d.ts +2 -0
- package/dist/src/gateway/service.js +73 -0
- package/dist/src/media-understanding/types.d.ts +61 -0
- package/dist/src/runtime-tools/archive.js +17 -3
- package/dist/src/runtime-tools/command.d.ts +1 -0
- package/dist/src/runtime-tools/command.js +29 -8
- package/dist/src/runtime-tools/environment.d.ts +1 -0
- package/dist/src/runtime-tools/environment.js +11 -16
- package/dist/src/runtime-tools/install-lock.d.ts +1 -1
- package/dist/src/runtime-tools/install-lock.js +34 -21
- package/dist/src/runtime-tools/manager.d.ts +1 -1
- package/dist/src/runtime-tools/manager.js +99 -64
- package/dist/src/runtime-tools/manifest-store.d.ts +2 -0
- package/dist/src/runtime-tools/manifest-store.js +29 -8
- package/dist/src/runtime-tools/paths.d.ts +2 -1
- package/dist/src/runtime-tools/paths.js +19 -8
- package/dist/src/runtime-tools/probe.d.ts +2 -0
- package/dist/src/runtime-tools/probe.js +13 -1
- package/dist/src/runtime-tools/prune.js +21 -7
- package/dist/src/session/client-history.js +12 -0
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/session-context-for-llm.js +8 -0
- package/dist/src/session/store.d.ts +1 -0
- package/dist/src/session/store.js +1 -0
- package/dist/src/session/stored-rows-to-file-entries.js +5 -1
- package/dist/src/session/voice-transcript.d.ts +9 -0
- package/dist/src/session/voice-transcript.js +45 -0
- package/dist/src/storage/sqlite/config-repository.js +9 -0
- package/dist/src/storage/sqlite/remote-context-repository.d.ts +3 -0
- package/dist/src/storage/sqlite/remote-context-repository.js +40 -0
- package/dist/src/storage/sqlite/session-repository.js +13 -0
- package/dist/src/storage/sqlite/user-context-repository.d.ts +3 -1
- package/dist/src/storage/sqlite/user-context-repository.js +50 -4
- package/dist/src/tui/tui.js +2 -1
- package/dist/src/user-context/automatic-context.d.ts +17 -0
- package/dist/src/user-context/automatic-context.js +85 -0
- package/dist/src/user-context/changes.d.ts +7 -0
- package/dist/src/user-context/changes.js +28 -0
- package/dist/src/user-context/planner.js +1 -24
- package/dist/src/user-context/retriever.js +10 -11
- package/dist/src/user-context/selection-policy.d.ts +20 -0
- package/dist/src/user-context/selection-policy.js +33 -0
- package/dist/src/user-context/sources/index.js +2 -2
- package/dist/src/user-context/sources/repository.d.ts +2 -1
- package/dist/src/user-context/sources/repository.js +26 -5
- package/dist/src/voice/dashscope/streaming-stt-session.d.ts +2 -0
- package/dist/src/voice/dashscope/streaming-stt-session.js +249 -0
- package/dist/src/voice/dashscope/streaming-tts-stream.d.ts +12 -0
- package/dist/src/voice/dashscope/streaming-tts-stream.js +153 -0
- package/dist/src/voice/realtime/agentEngine.d.ts +10 -0
- package/dist/src/voice/realtime/agentEngine.js +403 -0
- package/dist/src/voice/realtime/audio-playback-window.d.ts +9 -0
- package/dist/src/voice/realtime/audio-playback-window.js +49 -0
- package/dist/src/voice/realtime/conversation-context.d.ts +11 -0
- package/dist/src/voice/realtime/conversation-context.js +76 -0
- package/dist/src/voice/realtime/engine.d.ts +13 -0
- package/dist/src/voice/realtime/engine.js +1 -0
- package/dist/src/voice/realtime/memory-context.d.ts +17 -0
- package/dist/src/voice/realtime/memory-context.js +100 -0
- package/dist/src/voice/realtime/omniEngine.d.ts +18 -0
- package/dist/src/voice/realtime/omniEngine.js +443 -0
- package/dist/src/voice/realtime/omniRoute.d.ts +10 -0
- package/dist/src/voice/realtime/omniRoute.js +31 -0
- package/dist/src/voice/realtime/runtime.d.ts +99 -0
- package/dist/src/voice/realtime/runtime.js +622 -0
- package/dist/src/voice/realtime/speakable-segmenter.d.ts +10 -0
- package/dist/src/voice/realtime/speakable-segmenter.js +87 -0
- package/dist/src/voice/stt/list-providers.js +2 -1
- package/dist/src/voice/stt/providers/alibaba-transcription.js +13 -1
- package/dist/src/voice/stt/providers/xopc-cloud-transcription.js +23 -0
- package/dist/src/voice/tts/factory.js +1 -0
- package/dist/src/voice/tts/openai-compatible-speech.js +3 -1
- package/dist/src/voice/tts/providers/alibaba-speech.d.ts +1 -5
- package/dist/src/voice/tts/providers/alibaba-speech.js +25 -8
- package/dist/src/voice/tts/providers/edge-speech.js +21 -22
- package/dist/src/voice/tts/providers/minimax-speech.js +6 -3
- package/dist/src/voice/tts/providers/xopc-cloud-speech.js +26 -1
- package/dist/src/voice/tts/speak-core.d.ts +6 -2
- package/dist/src/voice/tts/speak-core.js +46 -34
- package/dist/src/voice/tts/speech-provider-types.d.ts +1 -0
- package/package.json +6 -6
- package/dist/gateway/static/root/assets/Combination-14nmIgxH.js +0 -41
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DbdgX6AA.js +0 -1
- package/dist/gateway/static/root/assets/agents-BX3uRVm4.js +0 -1
- package/dist/gateway/static/root/assets/app-chrome-BeB4KgOf.js +0 -1
- package/dist/gateway/static/root/assets/app-management-settings-panel-D8evZyFQ.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-CoZd_cZu.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-C8RRKT-a.js +0 -6
- package/dist/gateway/static/root/assets/block-editor-DCH9b2Ht.js +0 -184
- package/dist/gateway/static/root/assets/browser-settings-page-D1GPwIfx.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-CrXB1Q-l.js +0 -7
- package/dist/gateway/static/root/assets/channels-settings-DWMSYaNZ.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DXTl1fNB.js +0 -2
- package/dist/gateway/static/root/assets/dist-BPoKqzeH.js +0 -1
- package/dist/gateway/static/root/assets/dist-DqPZM2MH.js +0 -1
- package/dist/gateway/static/root/assets/home-page-NdWtBda5.js +0 -1
- package/dist/gateway/static/root/assets/index-7i2P3312.js +0 -70
- package/dist/gateway/static/root/assets/index-DTo3IcbW.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-C_j_od5f.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-D6PDZEVP.js +0 -2
- package/dist/gateway/static/root/assets/messages-_tYhRAHD.js +0 -3
- package/dist/gateway/static/root/assets/mobile-pairing-wizard-DcEz7qcX.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-Bu0a83Oj.js +0 -4
- package/dist/gateway/static/root/assets/popover-select-DrILF6mR.js +0 -1
- package/dist/gateway/static/root/assets/product-open-page-DMhf1rdz.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-DDHi0Y4Q.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CVMFKpmu.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-B74aErBY.js +0 -1
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Bv-akndY.js +0 -5
- package/dist/gateway/static/root/assets/sessions-page-D2wmGNZE.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CYCCUMEt.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-rf8f1OGq.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BkvclZ_o.js +0 -1
- package/dist/gateway/static/root/assets/skills-page.utils-DGjnz-NG.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-6a2RdDl2.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-Chfiba_x.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-SeOHP6XO.js +0 -1
- package/dist/gateway/static/root/assets/voice-config-api-BO6A8V3Z.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-BfwEoOGL.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-X7Z5_lRX.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-BklMzkg8.js +0 -5
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
2
|
+
import { notifyUserContextChange } from "../../user-context/changes.js";
|
|
2
3
|
import { sessionConfigRowToConfig } from "./row-mappers.js";
|
|
3
4
|
import { ensureSessionInTransaction } from "./session-repository.js";
|
|
4
5
|
//#region src/storage/sqlite/config-repository.ts
|
|
@@ -21,6 +22,10 @@ function listSessionWorkspaceOverrides() {
|
|
|
21
22
|
`).all();
|
|
22
23
|
}
|
|
23
24
|
function setSessionConfig(sessionKey, config, cwd) {
|
|
25
|
+
notifyUserContextChange({
|
|
26
|
+
kind: "session",
|
|
27
|
+
id: sessionKey
|
|
28
|
+
});
|
|
24
29
|
return runSqliteWriteTransaction((db) => {
|
|
25
30
|
ensureSessionInTransaction(db, sessionKey, cwd);
|
|
26
31
|
const updatedAt = Math.max(Date.now(), (readConfigRow(db, sessionKey)?.updated_at ?? 0) + 1);
|
|
@@ -54,6 +59,10 @@ function updateSessionConfig(sessionKey, partial, cwd) {
|
|
|
54
59
|
}, cwd);
|
|
55
60
|
}
|
|
56
61
|
function deleteSessionConfig(sessionKey) {
|
|
62
|
+
notifyUserContextChange({
|
|
63
|
+
kind: "session",
|
|
64
|
+
id: sessionKey
|
|
65
|
+
});
|
|
57
66
|
runSqliteWriteTransaction((db) => {
|
|
58
67
|
db.prepare(`DELETE FROM session_config WHERE session_key = ?`).run(sessionKey);
|
|
59
68
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { getSqliteDatabase } from "./transaction.js";
|
|
2
|
+
import { USER_CONTEXT_PRINCIPAL_ID } from "../../user-context/domain.js";
|
|
3
|
+
//#region src/storage/sqlite/remote-context-repository.ts
|
|
4
|
+
/** Check all provenance, including older evidence, without loading private excerpts. */
|
|
5
|
+
function remoteContextEligibleIds(kind, ids) {
|
|
6
|
+
if (!ids.length) return /* @__PURE__ */ new Set();
|
|
7
|
+
if (ids.length > 200) throw new Error("Context candidate limit exceeded");
|
|
8
|
+
const focus = kind === "focus";
|
|
9
|
+
const table = focus ? "user_focuses" : "user_understandings";
|
|
10
|
+
const versions = focus ? "user_focus_versions" : "user_understanding_versions";
|
|
11
|
+
const links = focus ? "user_focus_evidence_links" : "understanding_evidence_links";
|
|
12
|
+
const id = focus ? "focus_id" : "understanding_id";
|
|
13
|
+
const rows = getSqliteDatabase().prepare(`
|
|
14
|
+
SELECT u.${id} AS id, v.created_by, u.explicitness,
|
|
15
|
+
COUNT(e.evidence_id) AS evidence_count,
|
|
16
|
+
MAX(CASE WHEN e.evidence_id IS NOT NULL AND (
|
|
17
|
+
(e.processing_policy IS NOT NULL AND e.processing_policy <> 'remote_allowed')
|
|
18
|
+
OR e.trust_level = 'untrusted' OR e.principal_id <> u.principal_id
|
|
19
|
+
OR (e.source_run_id IS NOT NULL AND (g.grant_id IS NULL OR g.status <> 'active' OR g.processing_policy <> 'remote_allowed'))
|
|
20
|
+
OR (e.source_type = 'connector' AND (e.processing_policy IS NULL OR e.source_run_id IS NULL))
|
|
21
|
+
OR (e.processing_policy IS NULL AND e.source_type <> 'user' AND e.trust_level <> 'owner')
|
|
22
|
+
) THEN 1 ELSE 0 END) AS blocked
|
|
23
|
+
FROM ${table} u
|
|
24
|
+
JOIN ${versions} v ON v.version_id = u.current_version_id
|
|
25
|
+
LEFT JOIN ${versions} history ON history.${id} = u.${id}
|
|
26
|
+
LEFT JOIN ${links} l ON l.version_id = history.version_id
|
|
27
|
+
LEFT JOIN context_evidence e ON e.evidence_id = l.evidence_id
|
|
28
|
+
LEFT JOIN understanding_source_runs r ON r.run_id = e.source_run_id
|
|
29
|
+
LEFT JOIN understanding_source_grants g ON g.grant_id = r.grant_id
|
|
30
|
+
WHERE u.principal_id = ? AND u.${id} IN (${ids.map(() => "?").join(",")})
|
|
31
|
+
${focus ? `AND (u.source_run_id IS NULL OR EXISTS (
|
|
32
|
+
SELECT 1 FROM understanding_source_runs fr JOIN understanding_source_grants fg ON fg.grant_id = fr.grant_id
|
|
33
|
+
WHERE fr.run_id = u.source_run_id AND fg.status = 'active' AND fg.processing_policy = 'remote_allowed'
|
|
34
|
+
))` : ""}
|
|
35
|
+
GROUP BY u.${id}
|
|
36
|
+
`).all(USER_CONTEXT_PRINCIPAL_ID, ...ids);
|
|
37
|
+
return new Set(rows.filter((row) => !row.blocked && (row.evidence_count > 0 || row.explicitness === "explicit" && row.created_by === "user")).map((row) => row.id));
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { remoteContextEligibleIds };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
2
|
+
import { notifyUserContextChange } from "../../user-context/changes.js";
|
|
2
3
|
import { buildFts5SearchQuery } from "./fts.js";
|
|
3
4
|
import { validateSessionId } from "../../session/session-id.js";
|
|
4
5
|
import { buildDefaultSessionMetadata } from "./session-metadata.js";
|
|
@@ -175,6 +176,10 @@ function sessionSortColumn(sortBy) {
|
|
|
175
176
|
}
|
|
176
177
|
}
|
|
177
178
|
function patchSessionMetadata(sessionKey, updates) {
|
|
179
|
+
if ("projectId" in updates) notifyUserContextChange({
|
|
180
|
+
kind: "session-reset",
|
|
181
|
+
id: sessionKey
|
|
182
|
+
});
|
|
178
183
|
return runSqliteWriteTransaction((db) => {
|
|
179
184
|
const existing = readSessionRow(db, sessionKey);
|
|
180
185
|
if (!existing) throw new Error(`Session not found: ${sessionKey}`);
|
|
@@ -242,6 +247,10 @@ function incrementSessionStatsOnAppend(sessionKey, tokenDelta = 0) {
|
|
|
242
247
|
});
|
|
243
248
|
}
|
|
244
249
|
function resetSessionRecord(sessionKey, cwd) {
|
|
250
|
+
notifyUserContextChange({
|
|
251
|
+
kind: "session-reset",
|
|
252
|
+
id: sessionKey
|
|
253
|
+
});
|
|
245
254
|
return runSqliteWriteTransaction((db) => {
|
|
246
255
|
const existing = readSessionRow(db, sessionKey);
|
|
247
256
|
if (!existing) return null;
|
|
@@ -267,6 +276,10 @@ function resetSessionRecord(sessionKey, cwd) {
|
|
|
267
276
|
});
|
|
268
277
|
}
|
|
269
278
|
function deleteSessionRecord(sessionKey) {
|
|
279
|
+
notifyUserContextChange({
|
|
280
|
+
kind: "session-reset",
|
|
281
|
+
id: sessionKey
|
|
282
|
+
});
|
|
270
283
|
return runSqliteWriteTransaction((db) => {
|
|
271
284
|
const existing = readSessionRow(db, sessionKey);
|
|
272
285
|
if (!existing) return false;
|
|
@@ -18,7 +18,7 @@ export type CreateUnderstandingInput = Omit<UserUnderstanding, 'id' | 'versionId
|
|
|
18
18
|
};
|
|
19
19
|
export declare function createUnderstanding(input: CreateUnderstandingInput, principalId?: string): UserUnderstanding;
|
|
20
20
|
export declare function getUnderstanding(id: string): UserUnderstanding | undefined;
|
|
21
|
-
export declare function listUnderstandings(statuses?: UnderstandingStatus[], principalId?: string): UserUnderstanding[];
|
|
21
|
+
export declare function listUnderstandings(statuses?: UnderstandingStatus[], principalId?: string, limit?: number): UserUnderstanding[];
|
|
22
22
|
export declare function searchActiveUnderstandings(query: string, limit?: number): Array<{
|
|
23
23
|
understanding: UserUnderstanding;
|
|
24
24
|
score: number;
|
|
@@ -52,6 +52,8 @@ export declare function createContextEvidence(input: Omit<ContextEvidence, 'id'
|
|
|
52
52
|
}, principalId?: string): ContextEvidence;
|
|
53
53
|
export declare function linkUnderstandingEvidence(versionId: string, evidenceId: string, relation: 'supports' | 'contradicts' | 'supersedes', confidence: number): void;
|
|
54
54
|
export declare function listUnderstandingEvidence(understandingId: string, relation?: 'supports' | 'contradicts' | 'supersedes'): ContextEvidence[];
|
|
55
|
+
/** Latest source labels for ranking, without fetching evidence bodies per candidate. */
|
|
56
|
+
export declare function understandingSourceBuckets(ids: string[]): Map<string, string>;
|
|
55
57
|
export declare function recordContextRun(input: {
|
|
56
58
|
turnId: string;
|
|
57
59
|
sessionKey: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
2
2
|
import { USER_CONTEXT_PRINCIPAL_ID } from "../../user-context/domain.js";
|
|
3
|
+
import { notifyUserContextChange } from "../../user-context/changes.js";
|
|
3
4
|
import { retrievalQueryAuditValue } from "../../retrieval/audit.js";
|
|
4
5
|
import { buildFts5SearchQuery, fts5RankToScore } from "./fts.js";
|
|
5
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -108,6 +109,10 @@ function getUserProfile(principalId = USER_CONTEXT_PRINCIPAL_ID) {
|
|
|
108
109
|
};
|
|
109
110
|
}
|
|
110
111
|
function updateUserProfile(patch, principalId = USER_CONTEXT_PRINCIPAL_ID) {
|
|
112
|
+
notifyUserContextChange({
|
|
113
|
+
kind: "profile",
|
|
114
|
+
id: "profile"
|
|
115
|
+
});
|
|
111
116
|
const current = getUserProfile(principalId);
|
|
112
117
|
const now = Date.now();
|
|
113
118
|
const next = {
|
|
@@ -163,11 +168,12 @@ function getUnderstanding(id) {
|
|
|
163
168
|
const row = getSqliteDatabase().prepare(`${UNDERSTANDING_SELECT} WHERE u.understanding_id = ?`).get(id);
|
|
164
169
|
return row ? understandingFromRow(row) : void 0;
|
|
165
170
|
}
|
|
166
|
-
function listUnderstandings(statuses, principalId = USER_CONTEXT_PRINCIPAL_ID) {
|
|
171
|
+
function listUnderstandings(statuses, principalId = USER_CONTEXT_PRINCIPAL_ID, limit) {
|
|
167
172
|
const db = getSqliteDatabase();
|
|
168
|
-
|
|
173
|
+
const maxRows = limit === void 0 ? -1 : Math.max(1, Math.min(500, Math.floor(limit)));
|
|
174
|
+
if (!statuses?.length) return db.prepare(`${UNDERSTANDING_SELECT} WHERE u.principal_id = ? ORDER BY u.updated_at DESC LIMIT ?`).all(principalId, maxRows).map(understandingFromRow);
|
|
169
175
|
const placeholders = statuses.map(() => "?").join(", ");
|
|
170
|
-
return db.prepare(`${UNDERSTANDING_SELECT} WHERE u.principal_id = ? AND u.status IN (${placeholders}) ORDER BY u.updated_at DESC
|
|
176
|
+
return db.prepare(`${UNDERSTANDING_SELECT} WHERE u.principal_id = ? AND u.status IN (${placeholders}) ORDER BY u.updated_at DESC LIMIT ?`).all(principalId, ...statuses, maxRows).map(understandingFromRow);
|
|
171
177
|
}
|
|
172
178
|
function searchActiveUnderstandings(query, limit = 50) {
|
|
173
179
|
const ftsQuery = buildFts5SearchQuery(query);
|
|
@@ -193,6 +199,10 @@ function searchActiveUnderstandings(query, limit = 50) {
|
|
|
193
199
|
}));
|
|
194
200
|
}
|
|
195
201
|
function reviseUnderstanding(id, statement, options) {
|
|
202
|
+
notifyUserContextChange({
|
|
203
|
+
kind: "understanding",
|
|
204
|
+
id
|
|
205
|
+
});
|
|
196
206
|
const current = getUnderstanding(id);
|
|
197
207
|
if (!current) throw new Error(`User understanding not found: ${id}`);
|
|
198
208
|
const versionId = randomUUID();
|
|
@@ -210,6 +220,10 @@ function reviseUnderstanding(id, statement, options) {
|
|
|
210
220
|
return getUnderstanding(id);
|
|
211
221
|
}
|
|
212
222
|
function setUnderstandingStatus(id, status, options) {
|
|
223
|
+
notifyUserContextChange({
|
|
224
|
+
kind: "understanding",
|
|
225
|
+
id
|
|
226
|
+
});
|
|
213
227
|
const current = getUnderstanding(id);
|
|
214
228
|
if (!current) throw new Error(`User understanding not found: ${id}`);
|
|
215
229
|
const now = Date.now();
|
|
@@ -237,6 +251,10 @@ function setUnderstandingStatus(id, status, options) {
|
|
|
237
251
|
return result;
|
|
238
252
|
}
|
|
239
253
|
function closeUnderstandingValidity(id, validTo = Date.now()) {
|
|
254
|
+
notifyUserContextChange({
|
|
255
|
+
kind: "understanding",
|
|
256
|
+
id
|
|
257
|
+
});
|
|
240
258
|
getSqliteDatabase().prepare(`UPDATE user_understandings SET valid_to = ?, updated_at = ?
|
|
241
259
|
WHERE understanding_id = ?`).run(validTo, validTo, id);
|
|
242
260
|
const result = getUnderstanding(id);
|
|
@@ -244,6 +262,10 @@ function closeUnderstandingValidity(id, validTo = Date.now()) {
|
|
|
244
262
|
return result;
|
|
245
263
|
}
|
|
246
264
|
function rejectUnderstanding(id, reason, actorType = "runtime") {
|
|
265
|
+
notifyUserContextChange({
|
|
266
|
+
kind: "understanding",
|
|
267
|
+
id
|
|
268
|
+
});
|
|
247
269
|
const current = getUnderstanding(id);
|
|
248
270
|
if (!current) throw new Error(`User understanding not found: ${id}`);
|
|
249
271
|
const now = Date.now();
|
|
@@ -277,6 +299,10 @@ function listUnderstandingStatusEvents(id) {
|
|
|
277
299
|
}));
|
|
278
300
|
}
|
|
279
301
|
function deleteUnderstanding(id) {
|
|
302
|
+
notifyUserContextChange({
|
|
303
|
+
kind: "understanding",
|
|
304
|
+
id
|
|
305
|
+
});
|
|
280
306
|
return runSqliteWriteTransaction((db) => {
|
|
281
307
|
db.prepare("DELETE FROM user_understanding_fts WHERE understanding_id = ?").run(id);
|
|
282
308
|
return Number(db.prepare("DELETE FROM user_understandings WHERE understanding_id = ?").run(id).changes) > 0;
|
|
@@ -342,6 +368,7 @@ function createContextEvidence(input, principalId = USER_CONTEXT_PRINCIPAL_ID) {
|
|
|
342
368
|
AND COALESCE(source_instance_id, '') = COALESCE(?, '') AND source_ref = ?`).get(principalId, input.sourceType, input.sourceInstanceId ?? null, input.sourceRef);
|
|
343
369
|
const derivedHash = input.contentHash ?? (input.redactedExcerpt ? createHash("sha256").update(input.redactedExcerpt).digest("hex") : void 0);
|
|
344
370
|
if (existing) {
|
|
371
|
+
notifyUserContextChange({ kind: "policy" });
|
|
345
372
|
getSqliteDatabase().prepare(`UPDATE context_evidence SET
|
|
346
373
|
source_run_id = COALESCE(source_run_id, ?), source_item_id = COALESCE(source_item_id, ?),
|
|
347
374
|
session_id = COALESCE(session_id, ?), turn_id = COALESCE(turn_id, ?),
|
|
@@ -373,6 +400,11 @@ function createContextEvidence(input, principalId = USER_CONTEXT_PRINCIPAL_ID) {
|
|
|
373
400
|
return evidence;
|
|
374
401
|
}
|
|
375
402
|
function linkUnderstandingEvidence(versionId, evidenceId, relation, confidence) {
|
|
403
|
+
const owner = getSqliteDatabase().prepare("SELECT understanding_id AS id FROM user_understanding_versions WHERE version_id = ?").get(versionId);
|
|
404
|
+
if (owner) notifyUserContextChange({
|
|
405
|
+
kind: "understanding",
|
|
406
|
+
id: owner.id
|
|
407
|
+
});
|
|
376
408
|
getSqliteDatabase().prepare(`INSERT INTO understanding_evidence_links (
|
|
377
409
|
version_id, evidence_id, relation, confidence
|
|
378
410
|
) VALUES (?, ?, ?, ?)
|
|
@@ -385,6 +417,20 @@ function listUnderstandingEvidence(understandingId, relation) {
|
|
|
385
417
|
WHERE v.understanding_id = ? AND (? IS NULL OR l.relation = ?)
|
|
386
418
|
ORDER BY e.observed_at DESC`).all(understandingId, relation ?? null, relation ?? null).map(evidenceFromRow);
|
|
387
419
|
}
|
|
420
|
+
/** Latest source labels for ranking, without fetching evidence bodies per candidate. */
|
|
421
|
+
function understandingSourceBuckets(ids) {
|
|
422
|
+
if (!ids.length) return /* @__PURE__ */ new Map();
|
|
423
|
+
const rows = getSqliteDatabase().prepare(`
|
|
424
|
+
SELECT understanding_id, source_type, source_instance_id, source_ref FROM (
|
|
425
|
+
SELECT v.understanding_id, e.source_type, e.source_instance_id, e.source_ref,
|
|
426
|
+
ROW_NUMBER() OVER (PARTITION BY v.understanding_id ORDER BY e.observed_at DESC) AS rank
|
|
427
|
+
FROM context_evidence e JOIN understanding_evidence_links l ON l.evidence_id = e.evidence_id
|
|
428
|
+
JOIN user_understanding_versions v ON v.version_id = l.version_id
|
|
429
|
+
WHERE v.understanding_id IN (${ids.map(() => "?").join(",")})
|
|
430
|
+
) WHERE rank = 1
|
|
431
|
+
`).all(...ids);
|
|
432
|
+
return new Map(rows.map((row) => [row.understanding_id, `${row.source_type}:${row.source_instance_id ?? row.source_ref.split(":entry:")[0]}`]));
|
|
433
|
+
}
|
|
388
434
|
function recordContextRun(input) {
|
|
389
435
|
const auditedQuery = retrievalQueryAuditValue(input.query);
|
|
390
436
|
const existing = getSqliteDatabase().prepare("SELECT context_run_id FROM context_runs WHERE turn_id = ?").get(input.turnId);
|
|
@@ -486,4 +532,4 @@ function decideContextConsent(id, decision) {
|
|
|
486
532
|
return Number(result.changes) > 0;
|
|
487
533
|
}
|
|
488
534
|
//#endregion
|
|
489
|
-
export { closeUnderstandingValidity, consumeContextConsent, createCollaborationRule, createContextEvidence, createUnderstanding, decideContextConsent, deleteCollaborationRule, deleteUnderstanding, ensureContextConsent, getCollaborationRule, getTurnPersonalization, getUnderstanding, getUserProfile, hasContextConsent, isUnderstandingSuppressed, linkUnderstandingEvidence, listCollaborationRules, listUnderstandingEvidence, listUnderstandingStatusEvents, listUnderstandings, recordContextFeedback, recordContextRun, rejectUnderstanding, reviseCollaborationRule, reviseUnderstanding, searchActiveUnderstandings, setCollaborationRuleStatus, setUnderstandingStatus, updateUserProfile };
|
|
535
|
+
export { closeUnderstandingValidity, consumeContextConsent, createCollaborationRule, createContextEvidence, createUnderstanding, decideContextConsent, deleteCollaborationRule, deleteUnderstanding, ensureContextConsent, getCollaborationRule, getTurnPersonalization, getUnderstanding, getUserProfile, hasContextConsent, isUnderstandingSuppressed, linkUnderstandingEvidence, listCollaborationRules, listUnderstandingEvidence, listUnderstandingStatusEvents, listUnderstandings, recordContextFeedback, recordContextRun, rejectUnderstanding, reviseCollaborationRule, reviseUnderstanding, searchActiveUnderstandings, setCollaborationRuleStatus, setUnderstandingStatus, understandingSourceBuckets, updateUserProfile };
|
package/dist/src/tui/tui.js
CHANGED
|
@@ -477,7 +477,8 @@ async function runTui(opts) {
|
|
|
477
477
|
isHidden: () => hidden,
|
|
478
478
|
focus: () => tui.setFocus(component),
|
|
479
479
|
unfocus: () => tui.setFocus(editor),
|
|
480
|
-
isFocused: () => false
|
|
480
|
+
isFocused: () => false,
|
|
481
|
+
getBounds: () => void 0
|
|
481
482
|
};
|
|
482
483
|
};
|
|
483
484
|
const closeCommandOverlay = () => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type RemoteContextKind } from '../storage/sqlite/remote-context-repository.js';
|
|
2
|
+
import type { UserContextScopeTarget } from './scope.js';
|
|
3
|
+
export interface AutomaticContextReference {
|
|
4
|
+
kind: RemoteContextKind | 'profile';
|
|
5
|
+
id: string;
|
|
6
|
+
version: string;
|
|
7
|
+
}
|
|
8
|
+
export interface AutomaticContextSelection {
|
|
9
|
+
block: string;
|
|
10
|
+
references: AutomaticContextReference[];
|
|
11
|
+
}
|
|
12
|
+
/** Read-only background selection. Never consumes consent or starts a model turn. */
|
|
13
|
+
export declare function selectAutomaticContext(input: UserContextScopeTarget & {
|
|
14
|
+
query: string;
|
|
15
|
+
maxChars: number;
|
|
16
|
+
deadline: number;
|
|
17
|
+
}): AutomaticContextSelection;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { getUserProfile, listUnderstandings } from "../storage/sqlite/user-context-repository.js";
|
|
2
|
+
import { listUserFocuses } from "./sources/repository.js";
|
|
3
|
+
import { UserUnderstandingRetriever } from "./retriever.js";
|
|
4
|
+
import { allowsAutomaticDisclosure, focusRejectionReason, focusScore, rejectionReason } from "./selection-policy.js";
|
|
5
|
+
import { remoteContextEligibleIds } from "../storage/sqlite/remote-context-repository.js";
|
|
6
|
+
//#region src/user-context/automatic-context.ts
|
|
7
|
+
/** Read-only background selection. Never consumes consent or starts a model turn. */
|
|
8
|
+
function selectAutomaticContext(input) {
|
|
9
|
+
const references = [];
|
|
10
|
+
const facts = [];
|
|
11
|
+
const profile = {};
|
|
12
|
+
const render = () => JSON.stringify({ backgroundMemory: {
|
|
13
|
+
profile,
|
|
14
|
+
facts
|
|
15
|
+
} });
|
|
16
|
+
const withinDeadline = () => performance.now() < input.deadline;
|
|
17
|
+
if (input.maxChars < 128 || !withinDeadline()) return {
|
|
18
|
+
block: "",
|
|
19
|
+
references
|
|
20
|
+
};
|
|
21
|
+
const user = getUserProfile();
|
|
22
|
+
for (const key of [
|
|
23
|
+
"callName",
|
|
24
|
+
"locale",
|
|
25
|
+
"timezone",
|
|
26
|
+
"pronouns",
|
|
27
|
+
"role",
|
|
28
|
+
"primaryGoal"
|
|
29
|
+
]) {
|
|
30
|
+
if (!user[key] || user[key].length > 300) continue;
|
|
31
|
+
profile[key] = user[key];
|
|
32
|
+
if (render().length > input.maxChars) delete profile[key];
|
|
33
|
+
}
|
|
34
|
+
if (Object.keys(profile).length) references.push({
|
|
35
|
+
kind: "profile",
|
|
36
|
+
id: "profile",
|
|
37
|
+
version: JSON.stringify(user)
|
|
38
|
+
});
|
|
39
|
+
const query = input.query.trim();
|
|
40
|
+
const candidates = !withinDeadline() ? [] : query ? new UserUnderstandingRetriever().retrieve({
|
|
41
|
+
...input,
|
|
42
|
+
maxCandidates: 50
|
|
43
|
+
}) : listUnderstandings(["active"], void 0, 200).filter((item) => item.explicitness === "explicit" && ["preference", "boundary"].includes(item.kind) && item.durability === "durable").map((understanding) => ({
|
|
44
|
+
understanding,
|
|
45
|
+
score: 1
|
|
46
|
+
}));
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
const eligible = candidates.filter(({ understanding: item, score }) => item.status === "active" && allowsAutomaticDisclosure(item) && !rejectionReason(item, input, now, []) && score > .25);
|
|
49
|
+
const allowed = withinDeadline() ? remoteContextEligibleIds("understanding", eligible.map(({ understanding }) => understanding.id)) : /* @__PURE__ */ new Set();
|
|
50
|
+
const append = (text, origin, reference) => {
|
|
51
|
+
if (!withinDeadline() || facts.length >= 6 || !text.trim()) return;
|
|
52
|
+
facts.push({
|
|
53
|
+
text,
|
|
54
|
+
origin
|
|
55
|
+
});
|
|
56
|
+
if (render().length > input.maxChars) {
|
|
57
|
+
facts.pop();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
references.push(reference);
|
|
61
|
+
};
|
|
62
|
+
for (const { understanding: item } of eligible) if (allowed.has(item.id)) append(item.statement, item.explicitness, {
|
|
63
|
+
kind: "understanding",
|
|
64
|
+
id: item.id,
|
|
65
|
+
version: item.versionId
|
|
66
|
+
});
|
|
67
|
+
if (query && withinDeadline() && facts.length < 6) {
|
|
68
|
+
const focuses = listUserFocuses(["active"], 50).filter((item) => allowsAutomaticDisclosure(item) && !focusRejectionReason(item, input, now)).map((item) => ({
|
|
69
|
+
item,
|
|
70
|
+
score: focusScore(item, query, input)
|
|
71
|
+
})).filter(({ score }) => score > .25).sort((a, b) => b.score - a.score);
|
|
72
|
+
const allowedFocuses = remoteContextEligibleIds("focus", focuses.map(({ item }) => item.id));
|
|
73
|
+
for (const { item } of focuses) if (allowedFocuses.has(item.id)) append(`${item.title}: ${item.summary}`, item.explicitness, {
|
|
74
|
+
kind: "focus",
|
|
75
|
+
id: item.id,
|
|
76
|
+
version: item.versionId ?? String(item.updatedAt)
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
block: references.length ? render() : "",
|
|
81
|
+
references
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { selectAutomaticContext };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface UserContextChange {
|
|
2
|
+
kind: 'profile' | 'understanding' | 'focus' | 'policy' | 'session' | 'session-reset';
|
|
3
|
+
id?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function onUserContextChange(listener: (change: UserContextChange) => void): () => void;
|
|
6
|
+
/** Dispatch after the synchronous write/outer transaction has left the stack. */
|
|
7
|
+
export declare function notifyUserContextChange(change: UserContextChange): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
//#region src/user-context/changes.ts
|
|
4
|
+
init_logger();
|
|
5
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
6
|
+
const log = createLogger("UserContextChanges");
|
|
7
|
+
function onUserContextChange(listener) {
|
|
8
|
+
listeners.add(listener);
|
|
9
|
+
return () => {
|
|
10
|
+
listeners.delete(listener);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Dispatch after the synchronous write/outer transaction has left the stack. */
|
|
14
|
+
function notifyUserContextChange(change) {
|
|
15
|
+
if (!listeners.size) return;
|
|
16
|
+
queueMicrotask(() => {
|
|
17
|
+
for (const listener of listeners) try {
|
|
18
|
+
listener(change);
|
|
19
|
+
} catch (err) {
|
|
20
|
+
log.error({
|
|
21
|
+
err,
|
|
22
|
+
kind: change.kind
|
|
23
|
+
}, "User context change listener failed");
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { notifyUserContextChange, onUserContextChange };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { consumeContextConsent, ensureContextConsent, getUserProfile, listCollaborationRules, listUnderstandingEvidence, listUnderstandings, recordContextRun } from "../storage/sqlite/user-context-repository.js";
|
|
2
|
-
import { retrievalLexicalSimilarity } from "../retrieval/textFeatures.js";
|
|
3
2
|
import { buildRetrievalQueryProfile } from "../retrieval/queryProfile.js";
|
|
4
3
|
import "../storage/sqlite/index.js";
|
|
5
4
|
import { init_session_key, parseSessionKey } from "../routing/session-key.js";
|
|
@@ -9,6 +8,7 @@ import { buildUserContextBlock } from "../agent/memory/context-fence.js";
|
|
|
9
8
|
import { getUnderstandingSourceGrant, getUnderstandingSourceRun, listUserFocuses } from "./sources/repository.js";
|
|
10
9
|
import { matchesUserContextScope } from "./scope.js";
|
|
11
10
|
import { UserUnderstandingRetriever } from "./retriever.js";
|
|
11
|
+
import { focusRejectionReason, focusScore, rejectionReason } from "./selection-policy.js";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
13
|
//#region src/user-context/planner.ts
|
|
14
14
|
init_session_key();
|
|
@@ -103,35 +103,12 @@ function focusSourceDescription(focus) {
|
|
|
103
103
|
label: "Suggested from prior work"
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
|
-
function rejectionReason(item, input, now, timeHints) {
|
|
107
|
-
const historical = timeHints.includes("historical") && item.validTo !== void 0;
|
|
108
|
-
if (item.status === "needs_review" || item.status === "candidate" || item.status === "stale" && !historical) return "needs_review";
|
|
109
|
-
if (item.status === "rejected" || item.status === "archived" && !historical) return "disabled";
|
|
110
|
-
if (!matchesUserContextScope(item.scope, input)) return "scope_mismatch";
|
|
111
|
-
if (item.validFrom && item.validFrom > now && !timeHints.includes("future")) return "not_yet_valid";
|
|
112
|
-
if ((item.validTo && item.validTo < now || item.expiresAt && item.expiresAt < now) && !historical) return "expired";
|
|
113
|
-
if (item.sensitivity === "secret" || item.sensitivity === "regulated") return "sensitive";
|
|
114
|
-
if (item.conflictGroupId) return "conflict";
|
|
115
|
-
}
|
|
116
106
|
function ruleMatches(rule, input) {
|
|
117
107
|
if (rule.status !== "active" || !matchesUserContextScope(rule.scope, input)) return false;
|
|
118
108
|
const channel = typeof rule.conditions.channel === "string" ? rule.conditions.channel : void 0;
|
|
119
109
|
const agentId = typeof rule.conditions.agentId === "string" ? rule.conditions.agentId : void 0;
|
|
120
110
|
return (!channel || channel === input.channel) && (!agentId || agentId === input.agentId);
|
|
121
111
|
}
|
|
122
|
-
function focusRejectionReason(focus, input, now) {
|
|
123
|
-
if (focus.status !== "active") return "disabled";
|
|
124
|
-
if (!matchesUserContextScope(focus.scope, input)) return "scope_mismatch";
|
|
125
|
-
if (focus.validFrom && focus.validFrom > now) return "not_yet_valid";
|
|
126
|
-
if (focus.validTo && focus.validTo < now) return "expired";
|
|
127
|
-
if (focus.sensitivity === "secret" || focus.sensitivity === "regulated") return "sensitive";
|
|
128
|
-
if (focus.disclosurePolicy === "ask_before_reference") return "requires_consent";
|
|
129
|
-
}
|
|
130
|
-
function focusScore(focus, query, scopeInput) {
|
|
131
|
-
const lexical = retrievalLexicalSimilarity(buildRetrievalQueryProfile(query, scopeInput).normalized, `${focus.title} ${focus.summary}`);
|
|
132
|
-
const scoped = focus.scope.type !== "global" && matchesUserContextScope(focus.scope, scopeInput);
|
|
133
|
-
return Math.min(1, lexical * .75 + focus.confidence * .15 + (scoped ? .25 : 0));
|
|
134
|
-
}
|
|
135
112
|
function renderContextBlock(params) {
|
|
136
113
|
const understandingItems = params.items.filter((item) => item.objectType === "understanding");
|
|
137
114
|
return [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { summarizeUnderstandingFeedback } from "../storage/sqlite/user-context-quality-repository.js";
|
|
2
|
-
import {
|
|
2
|
+
import { listUnderstandings, searchActiveUnderstandings, understandingSourceBuckets } from "../storage/sqlite/user-context-repository.js";
|
|
3
3
|
import { normalizeRetrievalText, retrievalLexicalSimilarity } from "../retrieval/textFeatures.js";
|
|
4
4
|
import { buildRetrievalQueryProfile } from "../retrieval/queryProfile.js";
|
|
5
5
|
import "../storage/sqlite/index.js";
|
|
@@ -32,23 +32,18 @@ function temporalAdjustment(item, hints, now) {
|
|
|
32
32
|
}
|
|
33
33
|
return score;
|
|
34
34
|
}
|
|
35
|
-
function sourceBucket(item) {
|
|
36
|
-
if (item.explicitness === "explicit") return "user";
|
|
37
|
-
const evidence = listUnderstandingEvidence(item.id)[0];
|
|
38
|
-
if (!evidence) return `unknown:${item.id}`;
|
|
39
|
-
if (evidence.sourceInstanceId) return `${evidence.sourceType}:${evidence.sourceInstanceId}`;
|
|
40
|
-
return `${evidence.sourceType}:${evidence.sourceRef.split(":entry:")[0]}`;
|
|
41
|
-
}
|
|
42
35
|
function diversify(results, limit) {
|
|
43
36
|
const remaining = [...results];
|
|
44
37
|
const selected = [];
|
|
45
38
|
const sourceCounts = /* @__PURE__ */ new Map();
|
|
46
|
-
const
|
|
39
|
+
const redundancies = /* @__PURE__ */ new Map();
|
|
40
|
+
const evidenceBuckets = understandingSourceBuckets(results.filter((result) => result.understanding.explicitness !== "explicit").map((result) => result.understanding.id));
|
|
41
|
+
const sourceBuckets = new Map(results.map(({ understanding: item }) => [item.id, item.explicitness === "explicit" ? "user" : evidenceBuckets.get(item.id) ?? `unknown:${item.id}`]));
|
|
47
42
|
while (remaining.length && selected.length < limit) {
|
|
48
43
|
let bestIndex = 0;
|
|
49
44
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
50
45
|
for (const [index, candidate] of remaining.entries()) {
|
|
51
|
-
const redundancy =
|
|
46
|
+
const redundancy = redundancies.get(candidate.understanding.id) ?? 0;
|
|
52
47
|
const bucket = sourceBuckets.get(candidate.understanding.id);
|
|
53
48
|
const sourcePenalty = candidate.understanding.explicitness === "explicit" ? 0 : (sourceCounts.get(bucket) ?? 0) * .04;
|
|
54
49
|
const adjusted = candidate.score - redundancy * .18 - sourcePenalty;
|
|
@@ -65,6 +60,10 @@ function diversify(results, limit) {
|
|
|
65
60
|
score: Math.max(0, bestScore),
|
|
66
61
|
reasons: bestScore < candidate.score ? [...candidate.reasons, "diversified"] : candidate.reasons
|
|
67
62
|
});
|
|
63
|
+
if (selected.length < limit) for (const remainingItem of remaining) {
|
|
64
|
+
const id = remainingItem.understanding.id;
|
|
65
|
+
redundancies.set(id, Math.max(redundancies.get(id) ?? 0, retrievalLexicalSimilarity(remainingItem.understanding.statement, candidate.understanding.statement)));
|
|
66
|
+
}
|
|
68
67
|
}
|
|
69
68
|
return selected;
|
|
70
69
|
}
|
|
@@ -90,7 +89,7 @@ var UserUnderstandingRetriever = class {
|
|
|
90
89
|
"active",
|
|
91
90
|
"archived",
|
|
92
91
|
"stale"
|
|
93
|
-
] : ["active"]]
|
|
92
|
+
] : ["active"]], void 0, recentLimit);
|
|
94
93
|
const candidates = /* @__PURE__ */ new Map();
|
|
95
94
|
for (const result of fts) candidates.set(result.understanding.id, result.understanding);
|
|
96
95
|
for (const item of recent) candidates.set(item.id, item);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { UserContextRejectionReason } from '../agent/memory/context/types.js';
|
|
2
|
+
import type { UserUnderstanding } from './domain.js';
|
|
3
|
+
import type { UserFocus } from './sources/types.js';
|
|
4
|
+
/** Automatic remote context never uses sensitive, consent-gated or weakly inferred facts. */
|
|
5
|
+
export declare function allowsAutomaticDisclosure(item: Pick<UserUnderstanding, 'sensitivity' | 'disclosurePolicy' | 'explicitness' | 'confidence'>): boolean;
|
|
6
|
+
export declare function rejectionReason(item: UserUnderstanding, input: {
|
|
7
|
+
sessionKey: string;
|
|
8
|
+
workspaceId: string;
|
|
9
|
+
projectId?: string;
|
|
10
|
+
}, now: number, timeHints: string[]): UserContextRejectionReason | undefined;
|
|
11
|
+
export declare function focusRejectionReason(focus: UserFocus, input: {
|
|
12
|
+
sessionKey: string;
|
|
13
|
+
workspaceId: string;
|
|
14
|
+
projectId?: string;
|
|
15
|
+
}, now: number): UserContextRejectionReason | undefined;
|
|
16
|
+
export declare function focusScore(focus: UserFocus, query: string, scopeInput: {
|
|
17
|
+
sessionKey: string;
|
|
18
|
+
workspaceId: string;
|
|
19
|
+
projectId?: string;
|
|
20
|
+
}): number;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { retrievalLexicalSimilarity } from "../retrieval/textFeatures.js";
|
|
2
|
+
import { buildRetrievalQueryProfile } from "../retrieval/queryProfile.js";
|
|
3
|
+
import { matchesUserContextScope } from "./scope.js";
|
|
4
|
+
//#region src/user-context/selection-policy.ts
|
|
5
|
+
/** Automatic remote context never uses sensitive, consent-gated or weakly inferred facts. */
|
|
6
|
+
function allowsAutomaticDisclosure(item) {
|
|
7
|
+
return item.sensitivity === "normal" && item.disclosurePolicy !== "ask_before_reference" && (item.explicitness !== "inferred" || item.confidence >= .8);
|
|
8
|
+
}
|
|
9
|
+
function rejectionReason(item, input, now, timeHints) {
|
|
10
|
+
const historical = timeHints.includes("historical") && item.validTo !== void 0;
|
|
11
|
+
if (item.status === "needs_review" || item.status === "candidate" || item.status === "stale" && !historical) return "needs_review";
|
|
12
|
+
if (item.status === "rejected" || item.status === "archived" && !historical) return "disabled";
|
|
13
|
+
if (!matchesUserContextScope(item.scope, input)) return "scope_mismatch";
|
|
14
|
+
if (item.validFrom && item.validFrom > now && !timeHints.includes("future")) return "not_yet_valid";
|
|
15
|
+
if ((item.validTo && item.validTo < now || item.expiresAt && item.expiresAt < now) && !historical) return "expired";
|
|
16
|
+
if (item.sensitivity === "secret" || item.sensitivity === "regulated") return "sensitive";
|
|
17
|
+
if (item.conflictGroupId) return "conflict";
|
|
18
|
+
}
|
|
19
|
+
function focusRejectionReason(focus, input, now) {
|
|
20
|
+
if (focus.status !== "active") return "disabled";
|
|
21
|
+
if (!matchesUserContextScope(focus.scope, input)) return "scope_mismatch";
|
|
22
|
+
if (focus.validFrom && focus.validFrom > now) return "not_yet_valid";
|
|
23
|
+
if (focus.validTo && focus.validTo < now) return "expired";
|
|
24
|
+
if (focus.sensitivity === "secret" || focus.sensitivity === "regulated") return "sensitive";
|
|
25
|
+
if (focus.disclosurePolicy === "ask_before_reference") return "requires_consent";
|
|
26
|
+
}
|
|
27
|
+
function focusScore(focus, query, scopeInput) {
|
|
28
|
+
const lexical = retrievalLexicalSimilarity(buildRetrievalQueryProfile(query, scopeInput).normalized, `${focus.title} ${focus.summary}`);
|
|
29
|
+
const scoped = focus.scope.type !== "global" && matchesUserContextScope(focus.scope, scopeInput);
|
|
30
|
+
return Math.min(1, lexical * .75 + focus.confidence * .15 + (scoped ? .25 : 0));
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { allowsAutomaticDisclosure, focusRejectionReason, focusScore, rejectionReason };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus } from "./repository.js";
|
|
1
|
+
import { createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, getUserFocus, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus } from "./repository.js";
|
|
2
2
|
import { clusterUnderstandingSignals, tokenizeUnderstandingSignal } from "./signal-clustering.js";
|
|
3
3
|
import { listUnderstandingSourceDefinitions } from "./catalog.js";
|
|
4
|
-
export { clusterUnderstandingSignals, createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, listUnderstandingSourceDefinitions, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, tokenizeUnderstandingSignal, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus };
|
|
4
|
+
export { clusterUnderstandingSignals, createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, getUserFocus, listUnderstandingSourceDefinitions, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, tokenizeUnderstandingSignal, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus };
|
|
@@ -54,7 +54,8 @@ export declare function updateUnderstandingSourceRun(id: string, patch: {
|
|
|
54
54
|
nowMs?: number;
|
|
55
55
|
}): UnderstandingSourceRun | null;
|
|
56
56
|
export declare function upsertUserFocus(input: UserFocusInput): UserFocus;
|
|
57
|
-
export declare function listUserFocuses(statuses?: UserFocus['status'][]): UserFocus[];
|
|
57
|
+
export declare function listUserFocuses(statuses?: UserFocus['status'][], limit?: number): UserFocus[];
|
|
58
|
+
export declare function getUserFocus(id: string): UserFocus | undefined;
|
|
58
59
|
export declare function updateUserFocus(id: string, patch: Partial<Pick<UserFocus, 'title' | 'summary' | 'status' | 'validFrom' | 'validTo' | 'reviewAt'>>, nowMs?: number): UserFocus | null;
|
|
59
60
|
export declare function deleteUserFocus(id: string): boolean;
|
|
60
61
|
export {};
|