@xopcai/xopc 0.0.377 → 0.0.380
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/_locales/en/messages.json +1 -0
- package/dist/browser-ext/_locales/zh_CN/messages.json +1 -0
- package/dist/browser-ext/dist/sidepanel.js +36 -9
- 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-BVtU6S1w.js → activity-store-D2oKh5ik.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BD63ce58.js → agent-avatar-dicebear-OKK1A-IR.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-By5OXUfL.js +1 -0
- package/dist/gateway/static/root/assets/agent-plugin-dialog-b24CxjaT.js +1 -0
- package/dist/gateway/static/root/assets/{agents-admin-api-DgQph1Pu.js → agents-admin-api-D-DNV0ms.js} +1 -1
- package/dist/gateway/static/root/assets/agents-tJxKA9VH.js +66 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-B0yP8rNC.js → app-management-settings-panel-DxKh06hG.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-Bnq1nzDX.js → appearance-settings-C8CeHpdR.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-CSIFuEnj.js → apps-page-CZSTLErb.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-FBVMH4ym.js → archive-plugin-aoEF5gna.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-qsg6pZlF.js → automations-page-CSWWUZse.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-D2RJ-Lzn.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-B0qGhVNs.js → binary-plugins-BM3Lr1BP.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CjQv4zlo.js → block-editor-DMZ3_pPz.js} +39 -39
- package/dist/gateway/static/root/assets/{browser-automation-inputs-DSbRHrG7.js → browser-automation-inputs-BcBLdyVd.js} +1 -1
- package/dist/gateway/static/root/assets/browser-automations-page-BLSr6du1.js +3 -0
- package/dist/gateway/static/root/assets/browser-settings-page-BlDHSstc.js +3 -0
- package/dist/gateway/static/root/assets/{capabilities-HaRLmYU1.js → capabilities-BOJYAeEJ.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-LpGa-olH.js → capabilities-Bf6NYuvT.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-page-BeQ-Yj3_.js → capabilities-page-DHT4cB-Y.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-NZZNtjwZ.js +8 -0
- package/dist/gateway/static/root/assets/{capability-header-actions-DuBac0EK.js → capability-header-actions-V7TdNf7i.js} +1 -1
- package/dist/gateway/static/root/assets/channels-sgWMfPkw.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-CQc1mqZM.js → chat-terminal-dock-B4HNp59x.js} +2 -2
- package/dist/gateway/static/root/assets/{computer-settings-page-BIwOemaK.js → computer-settings-page-B2iwtbBu.js} +1 -1
- package/dist/gateway/static/root/assets/{connector-service-page-CG9KKuXq.js → connector-service-page-DTn3Z-MT.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-BJii6NMu.js +1 -0
- package/dist/gateway/static/root/assets/{date-picker-DoZGE2hF.js → date-picker-DrUc4ivy.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-hrz7p1Lv.js → dependency-picker-Bs16sgfD.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-C1bTu_dG.js → desktop-pet-Dg0Cp16O.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-C2xCFimg.js → desktop-pet-settings-BeJg3R-X.js} +1 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-DPqFaLVI.js +1 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-BaHQhI4z.js → directory-picker-path-field-BZkjdejC.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-B1uMVNGe.js → extension-debug-page-CFnlTs2-.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-850m5tOc.js → extension-page-BH25rxhA.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-provider-B-_CkaD2.js → extension-provider-CmaIRIVP.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-P3FNAW0n.js → extension-settings-page-D0af0S3r.js} +1 -1
- package/dist/gateway/static/root/assets/{fallback-models-BoJZA9Cm.js → fallback-models-BD_9_8lg.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-siY2J0hx.js → gateway-config-swr-f-4qw3AG.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-realtime-Biz18NiE.js → gateway-realtime-BGhPOSfz.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-BYe-jWB1.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-Bzrm6DMQ.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CeL1OFDZ.js → gateway-startup-retry-90pvxKox.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-oHguULk0.js +2 -0
- package/dist/gateway/static/root/assets/{image-generation-api-CeDrok06.js → image-generation-api-CtDjTXwX.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-C9FTl2dW.js → imports-page-CjFNSzDN.js} +1 -1
- package/dist/gateway/static/root/assets/index-_xgO2IDa.css +1 -0
- package/dist/gateway/static/root/assets/index-hn5CBddI.js +106 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Dx-36I-c.js → keyboard-shortcuts-settings-DKdWZ7pq.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-Cg4gdTwm.js → local-app-workbench-page-CXJQpTS9.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-3GKgu7at.js → local-apps-page-9dyoG2s0.js} +1 -1
- package/dist/gateway/static/root/assets/{local-session-drafts-DnSw14fE.js → local-session-drafts-CrD74S6k.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-DSsLH7JO.js → locale-store-pmT2B_By.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-pMgnuu0O.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-DcgCzPd-.js → management-settings-CxElPS5j.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-2rwSrMXW.js → markdown-view-B_7--qVD.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-CjGiKLFo.js → media-plugins-C6tT2oPH.js} +1 -1
- package/dist/gateway/static/root/assets/{messages-Cn25s55n.js → messages-Ib6DaUTo.js} +3 -3
- package/dist/gateway/static/root/assets/models-hub-cache-3slk24cw.js +1 -0
- package/dist/gateway/static/root/assets/note-detail-panel-4GI5kfs2.js +5 -0
- package/dist/gateway/static/root/assets/{notes-api-D9fGUbkK.js → notes-api-ChO4X97y.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-DaMnzWfF.js +8 -0
- package/dist/gateway/static/root/assets/{page-context-capture-button-CKqYL9AQ.js → page-context-capture-button-3bLWMSqt.js} +1 -1
- package/dist/gateway/static/root/assets/personal-page-BeAW5QQd.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-DFu_ZT2h.js → product-open-page-BiGwWy9s.js} +1 -1
- package/dist/gateway/static/root/assets/{product-preview-content-tPBCFa7L.js → product-preview-content-Dvy5ieTo.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-BNgCsfeE.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-CATt0m8t.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-ZhIt79wL.js → registry-api-Bi4muyaZ.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-5o06KAdu.js +1 -0
- package/dist/gateway/static/root/assets/runtime-tools-api-9bk1payF.js +5 -0
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-BnRVbeGi.js +1 -0
- package/dist/gateway/static/root/assets/{scenes-page-7LjR8Aek.js → scenes-page-BVjQ4A9S.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-GwVc8KsT.js → schema-form-C0QHo3do.js} +1 -1
- package/dist/gateway/static/root/assets/send-session-input-BhWG0d-Z.js +1 -0
- package/dist/gateway/static/root/assets/{session-api-BUa3BaGX.js → session-api-D2J6VacQ.js} +1 -1
- package/dist/gateway/static/root/assets/session-manager-D2xce33J.js +16 -0
- package/dist/gateway/static/root/assets/sessions-page-BHYhAsHC.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-DO148Ocl.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-DAvi3P8Q.js → settings-page-BT6dQ5nv.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-B9EqOzrI.js +1 -0
- package/dist/gateway/static/root/assets/{share-link-dialog-CbkS1cj-.js → share-link-dialog-Cu1miKUo.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-DicRCB4L.js → share-preview-page-CWH4BdnM.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-api-BUGeqXCG.js → shares-api-cGtd3rjc.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-B3Z6sQEA.js +1 -0
- package/dist/gateway/static/root/assets/{skill-api-DpTUuYWk.js → skill-api-pzPKld3K.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-reload-api-CII18PA5.js → skill-reload-api-VT8F0enn.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page-Busjd4VD.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-DlNaQp-l.js → system-settings-panel-CDuqpAIG.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-DeElbs6T.js → task-detail-page-CNt-P3Kl.js} +2 -2
- package/dist/gateway/static/root/assets/{task-expandable-content-sONbgbwR.js → task-expandable-content-Dgk9lYGd.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-Kz0VUMSb.js → theme-store-D7m5Eng5.js} +1 -1
- package/dist/gateway/static/root/assets/{tracing-settings-page-CZHhm1Nn.js → tracing-settings-page-B90frz6c.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-sUbAaSX6.js → tunnel-api-BJ2UEjeF.js} +1 -1
- package/dist/gateway/static/root/assets/usage-page-DrV2qcKO.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-CZzYhcAl.js → use-autosave-Ct1x4pqI.js} +1 -1
- package/dist/gateway/static/root/assets/{use-composer-attachments-Bb_Hqqry.js → use-composer-attachments-CyWRo1B1.js} +1 -1
- package/dist/gateway/static/root/assets/{use-file-preview-expanded-D4WI5JDn.js → use-file-preview-expanded-JIgp5qPT.js} +2 -2
- package/dist/gateway/static/root/assets/user-model-page-CQReU8e2.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-CIIGmtHR.js → voice-api-key-field-CSG8Hx8V.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-BtWFziQc.js → voice-config-api-415pyWx8.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-Dp107FXF.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Be_Rey6d.js → workflow-run-setup-panel-CZKJ6leF.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-2HuveBs_.js +6 -0
- package/dist/gateway/static/root/assets/{workspace-api-B5ssQs4p.js → workspace-api-DO_TWsiS.js} +2 -2
- package/dist/gateway/static/root/assets/xopc-cloud-account-card-CBjtpPiL.js +1 -0
- package/dist/gateway/static/root/index.html +27 -27
- package/dist/package.js +1 -1
- package/dist/packages/realtime-protocol/src/voice-catalog.js +7 -2
- package/dist/src/agent/embedded/execution-tool-policy.d.ts +14 -0
- package/dist/src/agent/embedded/execution-tool-policy.js +41 -0
- package/dist/src/agent/embedded/run-for-session.js +6 -4
- package/dist/src/agent/embedded/run-turn.js +56 -1
- package/dist/src/agent/embedded/session-runner.d.ts +3 -0
- package/dist/src/agent/embedded/session-runner.js +29 -8
- package/dist/src/agent/embedded/types.d.ts +2 -0
- package/dist/src/agent/prompt/response-language.js +9 -1
- package/dist/src/agent/service.js +1 -0
- package/dist/src/agent/session/session-config-service.js +0 -13
- package/dist/src/agent/tasks/task-judge-service.d.ts +2 -2
- package/dist/src/agent/tasks/task-judge-service.js +16 -9
- package/dist/src/agent/tools/factory.js +14 -13
- package/dist/src/agent/tools/knowledge-memory-tool.js +5 -4
- package/dist/src/agent/tools/local-read-budget.d.ts +2 -0
- package/dist/src/agent/tools/local-read-budget.js +5 -0
- package/dist/src/agent/tools/media-read-tool.js +2 -1
- package/dist/src/agent/tools/personal-read-tool.js +34 -10
- package/dist/src/agent/tools/read.js +5 -2
- package/dist/src/agent/tools/session-recall-tool.d.ts +1 -0
- package/dist/src/agent/tools/session-recall-tool.js +53 -12
- package/dist/src/agent/tools/session-search-tool.js +34 -8
- package/dist/src/agent/tools/user-context-tool.js +5 -4
- package/dist/src/agent/tools/xopc-use-tool.js +6 -2
- package/dist/src/browser/native-messaging-host.js +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +2 -2
- package/dist/src/gateway/chat-stream/mapper.d.ts +2 -0
- package/dist/src/gateway/chat-stream/mapper.js +4 -1
- package/dist/src/gateway/chat-stream/protocol.d.ts +4 -1
- package/dist/src/gateway/hono/app.js +1 -1
- package/dist/src/gateway/hono/routes/browser-install.js +1 -1
- package/dist/src/gateway/hono/routes/chat-model-config.d.ts +0 -4
- package/dist/src/gateway/hono/routes/chat-model-config.js +0 -6
- package/dist/src/gateway/hono/routes/personal-agent.js +4 -2
- package/dist/src/gateway/hono/routes/voice.js +12 -4
- package/dist/src/gateway/rate-limit/buckets.d.ts +1 -1
- package/dist/src/gateway/rate-limit/buckets.js +2 -2
- package/dist/src/gateway/service/run-gateway-agent.js +8 -3
- package/dist/src/gateway/side-chat/manager.js +1 -1
- package/dist/src/personal-agent/communication.d.ts +2 -1
- package/dist/src/personal-agent/communication.js +4 -3
- package/dist/src/personal-agent/policy.js +4 -4
- package/dist/src/personal-agent/prompts.d.ts +1 -0
- package/dist/src/personal-agent/prompts.js +32 -5
- package/dist/src/personal-agent/reply-composer.js +19 -4
- package/dist/src/personal-agent/reply-style.d.ts +4 -2
- package/dist/src/personal-agent/reply-style.js +57 -5
- package/dist/src/providers/prompt-cache-payload.js +2 -3
- package/dist/src/providers/prompt-cache-plan.d.ts +1 -0
- package/dist/src/providers/prompt-cache-plan.js +2 -2
- package/dist/src/session/store.d.ts +1 -0
- package/dist/src/storage/sqlite/device-pairing-approval.js +1 -1
- package/dist/src/storage/sqlite/transcript-repository.d.ts +1 -0
- package/dist/src/storage/sqlite/transcript-repository.js +5 -3
- package/dist/src/tasks/capabilities/write.js +10 -1
- package/dist/src/tasks/task-application-service.js +5 -4
- package/dist/src/tasks/task-context-assembler.js +1 -0
- package/dist/src/tasks/task-contract-definition.d.ts +1 -1
- package/dist/src/tasks/task-contract-definition.js +2 -2
- package/dist/src/tasks/task-contract-planner.d.ts +1 -0
- package/dist/src/tasks/task-contract-planner.js +2 -1
- package/dist/src/tasks/task-language.d.ts +7 -0
- package/dist/src/tasks/task-language.js +15 -0
- package/dist/src/tasks/task-read-model-projector.js +3 -2
- package/dist/src/tasks/task-result-delivery-service.js +2 -1
- package/dist/src/tasks/task-run-coordinator.js +22 -8
- package/dist/src/tasks/task-run-dispatcher.js +8 -6
- package/dist/src/voice/platform-catalog.d.ts +1 -0
- package/dist/src/voice/platform-settings.d.ts +1 -1
- package/dist/src/voice/platform-settings.js +6 -2
- package/dist/src/voice/platform-streams.js +3 -1
- package/dist/src/voice/realtime/omniRoute.d.ts +1 -1
- package/dist/src/voice/realtime/omniRoute.js +4 -1
- package/dist/src/voice/tts/providers/xopc-cloud-speech.js +6 -2
- package/dist/src/voice/tts/speech-provider-types.d.ts +1 -0
- package/package.json +4 -4
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Ch07F4uX.js +0 -1
- package/dist/gateway/static/root/assets/agent-plugin-dialog-CdCVOg5e.js +0 -1
- package/dist/gateway/static/root/assets/agents-D2__mhy8.js +0 -66
- package/dist/gateway/static/root/assets/automations-workspace-DqBWLl61.js +0 -6
- package/dist/gateway/static/root/assets/browser-automations-page-CzEWM_ie.js +0 -3
- package/dist/gateway/static/root/assets/browser-settings-page-CsDck88G.js +0 -3
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BQ-I3L-C.js +0 -8
- package/dist/gateway/static/root/assets/channels-1wUJcCxP.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-BFzjGpKE.js +0 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-CZ5Wmq5U.js +0 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-BazlseY_.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-BG1zXG8B.js +0 -1
- package/dist/gateway/static/root/assets/home-page-B8RmZbDw.js +0 -2
- package/dist/gateway/static/root/assets/index-CGVecvp4.css +0 -1
- package/dist/gateway/static/root/assets/index-DU5FmDQh.js +0 -106
- package/dist/gateway/static/root/assets/logs-page-CApZnDPi.js +0 -2
- package/dist/gateway/static/root/assets/models-hub-cache-DaqiLHPe.js +0 -1
- package/dist/gateway/static/root/assets/note-detail-panel-CncL3xmy.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-D9romxNU.js +0 -8
- package/dist/gateway/static/root/assets/personal-page-DoG-2fru.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-C9Bt5toA.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-Bu3jZa3A.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-C9MNGl2t.js +0 -1
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-BYQuPsWk.js +0 -5
- package/dist/gateway/static/root/assets/send-session-input-B64q4_6R.js +0 -1
- package/dist/gateway/static/root/assets/session-manager-BWLIDok4.js +0 -16
- package/dist/gateway/static/root/assets/sessions-page-CzbNB_RT.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CmNe5RJ4.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DoAn6P_k.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Bbkz0xuD.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-BuBSAOOd.js +0 -2
- package/dist/gateway/static/root/assets/usage-page-NPLApyNj.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-DAEiJzNV.js +0 -2
- package/dist/gateway/static/root/assets/work-discovery-overlay-DxRDLQvs.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-wJk7l1_H.js +0 -6
- package/dist/gateway/static/root/assets/xopc-cloud-account-card-D7Rtu5eI.js +0 -1
|
@@ -49,10 +49,11 @@ function createReadMediaTool(options) {
|
|
|
49
49
|
const fullText = buffer.toString("utf8");
|
|
50
50
|
const maxChars = options?.maxChars ?? fullText.length;
|
|
51
51
|
const truncated = fullText.length > maxChars;
|
|
52
|
+
const notice = truncated ? "\n[Attachment truncated; delegate full analysis to a specialist.]" : "";
|
|
52
53
|
return {
|
|
53
54
|
content: [{
|
|
54
55
|
type: "text",
|
|
55
|
-
text: fullText.slice(0,
|
|
56
|
+
text: fullText.slice(0, Math.max(0, maxChars - notice.length)) + notice
|
|
56
57
|
}],
|
|
57
58
|
details: {
|
|
58
59
|
...metadata,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CapabilityDispatcher } from "../../capabilities/runtime/dispatcher.js";
|
|
2
|
+
import { LOCAL_READ_MAX_CHARS } from "./local-read-budget.js";
|
|
2
3
|
import { registerNoteReadCapabilities } from "../../notes/capabilities/read.js";
|
|
3
4
|
import { registerProjectReadCapabilities } from "../../projects/capabilities/read.js";
|
|
4
5
|
import { registerAutomationReadCapabilities } from "../../automations/capabilities/read.js";
|
|
@@ -123,7 +124,7 @@ function createPersonalReadTool(deps) {
|
|
|
123
124
|
};
|
|
124
125
|
}
|
|
125
126
|
const serialized = JSON.stringify(payload);
|
|
126
|
-
const requiresSpecialist = input.command === "get" && (serialized.length >
|
|
127
|
+
const requiresSpecialist = input.command === "get" && (serialized.length > 8e3 || Boolean(payload.item?.truncatedFields));
|
|
127
128
|
if (requiresSpecialist) payload = {
|
|
128
129
|
...payload,
|
|
129
130
|
requiresSpecialist: true,
|
|
@@ -131,21 +132,44 @@ function createPersonalReadTool(deps) {
|
|
|
131
132
|
id: input.id,
|
|
132
133
|
guidance: "Briefly tell the user the material is large, then delegate full reading and processing using this object kind and ID."
|
|
133
134
|
};
|
|
134
|
-
|
|
135
|
+
let output = JSON.stringify(payload);
|
|
136
|
+
let complete = true;
|
|
137
|
+
while (output.length > LOCAL_READ_MAX_CHARS) {
|
|
138
|
+
if (input.command === "list") {
|
|
139
|
+
const items = payload.items;
|
|
140
|
+
if (!items.length) break;
|
|
141
|
+
items.pop();
|
|
142
|
+
payload.nextOffset = offset + items.length;
|
|
143
|
+
payload.truncated = true;
|
|
144
|
+
} else {
|
|
145
|
+
const item = payload.item;
|
|
146
|
+
const largest = Object.keys(item).filter((key) => typeof item[key] === "string" && item[key].length > 200).sort((a, b) => item[b].length - item[a].length)[0];
|
|
147
|
+
if (!largest) break;
|
|
148
|
+
item[largest] = item[largest].slice(0, Math.floor(item[largest].length / 2));
|
|
149
|
+
item.truncatedFields = [...new Set([...item.truncatedFields ?? [], largest])];
|
|
150
|
+
payload.truncated = true;
|
|
151
|
+
}
|
|
152
|
+
output = JSON.stringify(payload);
|
|
153
|
+
}
|
|
154
|
+
if (output.length > 8e3) {
|
|
155
|
+
complete = false;
|
|
156
|
+
output = JSON.stringify({
|
|
157
|
+
kind: input.kind,
|
|
158
|
+
id: input.id,
|
|
159
|
+
search: input.search,
|
|
160
|
+
requiresSpecialist: true,
|
|
161
|
+
complete: false,
|
|
162
|
+
reason: "large_object"
|
|
163
|
+
});
|
|
164
|
+
}
|
|
135
165
|
return {
|
|
136
166
|
content: [{
|
|
137
167
|
type: "text",
|
|
138
|
-
text: output
|
|
139
|
-
kind: input.kind,
|
|
140
|
-
excerpt: output.slice(0, 1e4),
|
|
141
|
-
truncated: true,
|
|
142
|
-
requiresSpecialist: true,
|
|
143
|
-
id: input.id
|
|
144
|
-
})
|
|
168
|
+
text: output
|
|
145
169
|
}],
|
|
146
170
|
details: {
|
|
147
171
|
localOnly: true,
|
|
148
|
-
requiresSpecialist: requiresSpecialist ||
|
|
172
|
+
requiresSpecialist: requiresSpecialist || !complete
|
|
149
173
|
}
|
|
150
174
|
};
|
|
151
175
|
}
|
|
@@ -92,6 +92,9 @@ async function executeReadFile(workspace, options, params, signal) {
|
|
|
92
92
|
let outputText = truncation.content;
|
|
93
93
|
if (truncation.truncated) if (truncation.firstLineExceedsLimit) outputText = `(Line exceeds ${formatSize(maxOutputBytes)})`;
|
|
94
94
|
else outputText += options?.maxReadBytes ? `\n\n[File excerpt only. Tell the user briefly and delegate full reading and processing. Path: ${normalized}]` : `\n\n[Lines ${offset}-${offset + truncation.outputLines - 1} of ${lines.length}; continue with offset=${offset + truncation.outputLines}]`;
|
|
95
|
+
const bounded = Boolean(options?.maxReadBytes && outputText.length > maxOutputBytes);
|
|
96
|
+
if (bounded) outputText = outputText.slice(0, Math.max(0, maxOutputBytes - 61)) + "\n[File excerpt only; delegate full analysis to a specialist.]";
|
|
97
|
+
const truncated = truncation.truncated || bounded;
|
|
95
98
|
return {
|
|
96
99
|
content: [{
|
|
97
100
|
type: "text",
|
|
@@ -101,8 +104,8 @@ async function executeReadFile(workspace, options, params, signal) {
|
|
|
101
104
|
path: normalized,
|
|
102
105
|
offset,
|
|
103
106
|
totalLines: lines.length,
|
|
104
|
-
truncated
|
|
105
|
-
...options?.maxReadBytes &&
|
|
107
|
+
truncated,
|
|
108
|
+
...options?.maxReadBytes && truncated ? {
|
|
106
109
|
requiresSpecialist: true,
|
|
107
110
|
reason: "large_file"
|
|
108
111
|
} : {}
|
|
@@ -3,5 +3,6 @@ import type { SessionStore } from '../../session/store.js';
|
|
|
3
3
|
export interface SessionRecallToolDeps {
|
|
4
4
|
getSessionStore: () => SessionStore;
|
|
5
5
|
getCurrentConversationId: () => string | undefined;
|
|
6
|
+
maxOutputChars?: number;
|
|
6
7
|
}
|
|
7
8
|
export declare function createSessionRecallTool(deps: SessionRecallToolDeps): AgentTool;
|
|
@@ -50,28 +50,69 @@ function createSessionRecallTool(deps) {
|
|
|
50
50
|
const query = input.query.trim();
|
|
51
51
|
const limit = Math.min(20, Math.max(1, input.limit ?? 8));
|
|
52
52
|
const maxChars = Math.min(2e4, Math.max(500, input.maxCharsPerResult ?? 6e3));
|
|
53
|
-
const
|
|
53
|
+
const matches = deps.getSessionStore().recallSession(conversationId, query, {
|
|
54
54
|
limit,
|
|
55
|
-
...input.beforeSeq ? { beforeSeq: input.beforeSeq } : {}
|
|
56
|
-
|
|
55
|
+
...input.beforeSeq ? { beforeSeq: input.beforeSeq } : {},
|
|
56
|
+
...deps.maxOutputChars ? { orderBySeq: true } : {}
|
|
57
|
+
});
|
|
58
|
+
if (deps.maxOutputChars) matches.sort((a, b) => b.seq - a.seq);
|
|
59
|
+
const results = matches.map((match) => ({
|
|
57
60
|
seq: match.seq,
|
|
58
61
|
entryId: match.entryId,
|
|
59
62
|
role: match.role,
|
|
60
63
|
createdAt: new Date(match.createdAt).toISOString(),
|
|
61
|
-
content: excerpt(match.content, query, maxChars)
|
|
64
|
+
content: excerpt(match.content, query, maxChars),
|
|
65
|
+
...deps.maxOutputChars ? { truncated: match.content.length > maxChars } : {}
|
|
62
66
|
}));
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
const payloadFor = () => {
|
|
68
|
+
const nextBeforeSeq = results.length && (results.length < matches.length || matches.length === limit) ? Math.min(...results.map((result) => result.seq)) : void 0;
|
|
69
|
+
return {
|
|
70
|
+
success: true,
|
|
71
|
+
query,
|
|
72
|
+
results,
|
|
73
|
+
count: results.length,
|
|
74
|
+
...deps.maxOutputChars ? {
|
|
75
|
+
excerpts: true,
|
|
76
|
+
truncated: results.length < matches.length || results.some((result) => result.truncated)
|
|
77
|
+
} : {},
|
|
78
|
+
...nextBeforeSeq ? { nextBeforeSeq } : {}
|
|
79
|
+
};
|
|
70
80
|
};
|
|
81
|
+
let payload = payloadFor();
|
|
82
|
+
let text = JSON.stringify(payload, null, 2);
|
|
83
|
+
if (deps.maxOutputChars) {
|
|
84
|
+
while (text.length > deps.maxOutputChars && results.length) {
|
|
85
|
+
if (results.length > 1) results.pop();
|
|
86
|
+
else if (results[0].content.length > 100) {
|
|
87
|
+
const match = matches[0];
|
|
88
|
+
results[0].content = excerpt(match.content, query, Math.floor(results[0].content.length / 2));
|
|
89
|
+
results[0].truncated = true;
|
|
90
|
+
} else break;
|
|
91
|
+
payload = payloadFor();
|
|
92
|
+
text = JSON.stringify(payload, null, 2);
|
|
93
|
+
}
|
|
94
|
+
if (text.length > deps.maxOutputChars) return {
|
|
95
|
+
content: [{
|
|
96
|
+
type: "text",
|
|
97
|
+
text: JSON.stringify({
|
|
98
|
+
query: query.slice(0, 500),
|
|
99
|
+
conversationId,
|
|
100
|
+
requiresSpecialist: true,
|
|
101
|
+
complete: false,
|
|
102
|
+
reason: "large_transcript",
|
|
103
|
+
guidance: "Delegate a complete read using the conversation ID and query."
|
|
104
|
+
})
|
|
105
|
+
}],
|
|
106
|
+
details: {
|
|
107
|
+
requiresSpecialist: true,
|
|
108
|
+
complete: false
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
71
112
|
return {
|
|
72
113
|
content: [{
|
|
73
114
|
type: "text",
|
|
74
|
-
text
|
|
115
|
+
text
|
|
75
116
|
}],
|
|
76
117
|
details: payload
|
|
77
118
|
};
|
|
@@ -3,6 +3,7 @@ import { init_logger } from "../../utils/logger.js";
|
|
|
3
3
|
import { init_providers, resolveModel } from "../../providers/index.js";
|
|
4
4
|
import { completeWithResolvedCredentials } from "../../providers/model-call.js";
|
|
5
5
|
import { readAgentMessageContent } from "../memory/agent-message-access.js";
|
|
6
|
+
import "./local-read-budget.js";
|
|
6
7
|
import { Type } from "@sinclair/typebox";
|
|
7
8
|
//#region src/agent/tools/session-search-tool.ts
|
|
8
9
|
init_providers();
|
|
@@ -92,7 +93,13 @@ function createSessionSearchTool(deps) {
|
|
|
92
93
|
name: "session_search",
|
|
93
94
|
label: "Session search",
|
|
94
95
|
description: deps.localOnly ? "Search other chats locally and return short matching transcript excerpts. Omit query to list recent chats. No model or network calls." : "Search other chat sessions by keywords and get short summaries, or omit `query` to list recent sessions (no LLM cost). Uses the same session store as the gateway. Narrow with roleFilter if needed.",
|
|
95
|
-
parameters:
|
|
96
|
+
parameters: deps.localOnly ? Type.Object({
|
|
97
|
+
...SessionSearchSchema.properties,
|
|
98
|
+
query: Type.Optional(Type.String({
|
|
99
|
+
maxLength: 500,
|
|
100
|
+
description: "Keywords for other chats; omit to list recent chats."
|
|
101
|
+
}))
|
|
102
|
+
}) : SessionSearchSchema,
|
|
96
103
|
supportsParallel: true,
|
|
97
104
|
idempotent: true,
|
|
98
105
|
async execute(_toolCallId, params, signal) {
|
|
@@ -104,9 +111,16 @@ function createSessionSearchTool(deps) {
|
|
|
104
111
|
details: { error: "cross_session_history_disabled" }
|
|
105
112
|
};
|
|
106
113
|
const p = params;
|
|
107
|
-
const store = deps.getSessionStore();
|
|
108
114
|
const limit = Math.min(deps.localOnly ? 5 : 15, Math.max(1, p.limit ?? (deps.localOnly ? 3 : 5)));
|
|
109
115
|
const query = p.query?.trim() ?? "";
|
|
116
|
+
if (deps.localOnly && query.length > 500) return {
|
|
117
|
+
content: [{
|
|
118
|
+
type: "text",
|
|
119
|
+
text: "Use at most 500 characters of search keywords."
|
|
120
|
+
}],
|
|
121
|
+
details: { error: "invalid_query" }
|
|
122
|
+
};
|
|
123
|
+
const store = deps.getSessionStore();
|
|
110
124
|
try {
|
|
111
125
|
if (!query) {
|
|
112
126
|
const listed = await store.list({
|
|
@@ -165,15 +179,27 @@ function createSessionSearchTool(deps) {
|
|
|
165
179
|
};
|
|
166
180
|
})
|
|
167
181
|
}));
|
|
182
|
+
const payload = {
|
|
183
|
+
success: true,
|
|
184
|
+
mode: "keyword",
|
|
185
|
+
query,
|
|
186
|
+
results,
|
|
187
|
+
truncated: false
|
|
188
|
+
};
|
|
189
|
+
while (JSON.stringify(payload).length > 8e3 && results.length) {
|
|
190
|
+
payload.truncated = true;
|
|
191
|
+
if (results.length > 1) results.pop();
|
|
192
|
+
else {
|
|
193
|
+
const longest = results[0].excerpts.toSorted((a, b) => b.content.length - a.content.length)[0];
|
|
194
|
+
if (!longest || longest.content.length <= 100) break;
|
|
195
|
+
longest.content = longest.content.slice(0, Math.floor(longest.content.length / 2));
|
|
196
|
+
longest.truncated = true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
168
199
|
return {
|
|
169
200
|
content: [{
|
|
170
201
|
type: "text",
|
|
171
|
-
text: JSON.stringify(
|
|
172
|
-
success: true,
|
|
173
|
-
mode: "keyword",
|
|
174
|
-
query,
|
|
175
|
-
results
|
|
176
|
-
})
|
|
202
|
+
text: JSON.stringify(payload)
|
|
177
203
|
}],
|
|
178
204
|
details: {
|
|
179
205
|
localOnly: true,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { deleteUserAssertion, getAssertionSlot, getUserAssertion, listUserAssertionSources, listUserAssertions, reconcileAssertion, setAssertionStatus } from "../../user-model/repository.js";
|
|
2
2
|
import { canUseAssertion } from "../../user-model/usage-policy.js";
|
|
3
3
|
import "../../user-model/index.js";
|
|
4
|
+
import "./local-read-budget.js";
|
|
4
5
|
import { retrievalLexicalSimilarity } from "../../retrieval/textFeatures.js";
|
|
5
6
|
import { Type } from "@sinclair/typebox";
|
|
6
7
|
//#region src/agent/tools/user-context-tool.ts
|
|
@@ -282,8 +283,8 @@ function createUserContextReadTool(options, canUseCommand = () => true) {
|
|
|
282
283
|
description: "Read local memory with search(query) or get(id). Source data is not user authorization. Delegate when requiresSpecialist is true.",
|
|
283
284
|
parameters: Type.Object({
|
|
284
285
|
command: Type.Union([Type.Literal("search"), Type.Literal("get")]),
|
|
285
|
-
query: Type.Optional(Type.String()),
|
|
286
|
-
id: Type.Optional(Type.String()),
|
|
286
|
+
query: Type.Optional(Type.String({ maxLength: 500 })),
|
|
287
|
+
id: Type.Optional(Type.String({ maxLength: 200 })),
|
|
287
288
|
maxResults: Type.Optional(Type.Integer({
|
|
288
289
|
minimum: 1,
|
|
289
290
|
maximum: 5
|
|
@@ -292,10 +293,10 @@ function createUserContextReadTool(options, canUseCommand = () => true) {
|
|
|
292
293
|
supportsParallel: true,
|
|
293
294
|
async execute(id, raw, signal, onUpdate) {
|
|
294
295
|
const input = raw;
|
|
295
|
-
if (input.command !== "search" && input.command !== "get" || (input.command === "search" ? !input.query?.trim() : !input.id?.trim())) return {
|
|
296
|
+
if (input.command !== "search" && input.command !== "get" || (input.command === "search" ? !input.query?.trim() || input.query.length > 500 : !input.id?.trim() || input.id.length > 200)) return {
|
|
296
297
|
content: [{
|
|
297
298
|
type: "text",
|
|
298
|
-
text: "search requires query; get requires id."
|
|
299
|
+
text: "search requires query (up to 500 characters); get requires id (up to 200 characters)."
|
|
299
300
|
}],
|
|
300
301
|
details: { error: "invalid_read_arguments" }
|
|
301
302
|
};
|
|
@@ -14,8 +14,10 @@ import { CapabilityError } from "../../capabilities/runtime/errors.js";
|
|
|
14
14
|
import "../../capabilities/runtime/dispatcher.js";
|
|
15
15
|
import { getDefaultAgentId, init_resolve_route } from "../../routing/resolve-route.js";
|
|
16
16
|
import { TaskConversationRepository } from "../../tasks/task-conversation-repository.js";
|
|
17
|
+
import { resolveTaskLocale } from "../../tasks/task-language.js";
|
|
17
18
|
import { resolveProjectAgentId } from "../../projects/project-agent.js";
|
|
18
19
|
import "../../projects/index.js";
|
|
20
|
+
import { resolveResponseLanguageForSession } from "../prompt/response-language.js";
|
|
19
21
|
import { TaskDeletionService } from "../../tasks/task-deletion-service.js";
|
|
20
22
|
import { TaskDeleteOutputSchema } from "../../tasks/capabilities/management.js";
|
|
21
23
|
import { TaskCollaborationRepository } from "../../tasks/task-collaboration-repository.js";
|
|
@@ -1413,7 +1415,9 @@ async function handleTask(command, args, deps, dryRun, capabilities) {
|
|
|
1413
1415
|
ok: false,
|
|
1414
1416
|
error: "Invalid dependsOnTaskIds"
|
|
1415
1417
|
};
|
|
1416
|
-
const
|
|
1418
|
+
const responseLanguage = resolveResponseLanguageForSession(deps.getConfig?.(), deps.getCurrentConversationId?.());
|
|
1419
|
+
const taskLocale = locale ?? (responseLanguage === "auto" ? resolveTaskLocale({ title: objective }) : responseLanguage === "zh-CN" ? "zh" : "en");
|
|
1420
|
+
const baseContract = defineTaskContract(objective, taskLocale);
|
|
1417
1421
|
const contractFields = [
|
|
1418
1422
|
"expectedOutputs",
|
|
1419
1423
|
"acceptanceCriteria",
|
|
@@ -1470,7 +1474,7 @@ async function handleTask(command, args, deps, dryRun, capabilities) {
|
|
|
1470
1474
|
...projectId ? { projectId } : {},
|
|
1471
1475
|
delegateAgentId: agentId,
|
|
1472
1476
|
...originConversationId ? { originConversationId } : {},
|
|
1473
|
-
|
|
1477
|
+
locale: taskLocale,
|
|
1474
1478
|
contract: {
|
|
1475
1479
|
...contract,
|
|
1476
1480
|
acceptancePolicy: "verified_auto",
|
|
@@ -4,8 +4,8 @@ import { init_src } from "../../packages/gateway-contract/src/index.js";
|
|
|
4
4
|
import { getGatewayIdentityPublicKeyRaw, getOrCreateGatewayIdentity, init_gateway_identity_repository } from "../storage/sqlite/gateway-identity-repository.js";
|
|
5
5
|
import { createDevicePairingSetup, init_device_pairing_repository } from "../storage/sqlite/device-pairing-repository.js";
|
|
6
6
|
import { loadConfig } from "../config/loader.js";
|
|
7
|
-
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "./extension-identity.js";
|
|
8
7
|
import { browserEnrollmentPublicKeyThumbprint } from "./enrollment.js";
|
|
8
|
+
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "./extension-identity.js";
|
|
9
9
|
import os from "node:os";
|
|
10
10
|
//#region src/browser/native-messaging-host.ts
|
|
11
11
|
init_src();
|
|
@@ -4,10 +4,10 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
4
4
|
import { init_logger } from "../../utils/logger.js";
|
|
5
5
|
import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
|
|
6
6
|
import { init_paths, resolveBinDir, resolveConfigPath } from "../../config/paths.js";
|
|
7
|
-
import { resolvePackageRoot } from "../../infra/update-check.js";
|
|
8
|
-
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "../extension-identity.js";
|
|
9
7
|
import { assertCacheDir } from "../cache-dir-policy.js";
|
|
8
|
+
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "../extension-identity.js";
|
|
10
9
|
import "../native-messaging-host.js";
|
|
10
|
+
import { resolvePackageRoot } from "../../infra/update-check.js";
|
|
11
11
|
import { dirname, join } from "node:path";
|
|
12
12
|
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
@@ -11,6 +11,8 @@ export interface ChatStreamMapperOptions {
|
|
|
11
11
|
channel: string;
|
|
12
12
|
startsNewBubble?: boolean;
|
|
13
13
|
taskTrigger?: TaskUpdateTrigger;
|
|
14
|
+
/** Public text is visible immediately, independently of tool-call classification. */
|
|
15
|
+
textSurface?: 'conversation';
|
|
14
16
|
}
|
|
15
17
|
export declare class ChatStreamMapper {
|
|
16
18
|
private readonly opts;
|
|
@@ -429,7 +429,10 @@ var ChatStreamMapper = class {
|
|
|
429
429
|
runId: this.opts.runId,
|
|
430
430
|
conversationId: this.opts.conversationId,
|
|
431
431
|
timestamp: Date.now(),
|
|
432
|
-
payload
|
|
432
|
+
payload: this.opts.textSurface && (type === "run_start" || type === "assistant_message_start" || type === "assistant_delta") ? {
|
|
433
|
+
...payload,
|
|
434
|
+
textSurface: this.opts.textSurface
|
|
435
|
+
} : payload
|
|
433
436
|
};
|
|
434
437
|
}
|
|
435
438
|
recordPatchDiff(details) {
|
|
@@ -34,6 +34,7 @@ export type RunStartEvent = ChatStreamEnvelope<'run_start', {
|
|
|
34
34
|
channel: string;
|
|
35
35
|
startsNewBubble?: boolean;
|
|
36
36
|
taskTrigger?: TaskUpdateTrigger;
|
|
37
|
+
textSurface?: 'conversation';
|
|
37
38
|
}>;
|
|
38
39
|
export type UserMessageEvent = ChatStreamEnvelope<'user_message', {
|
|
39
40
|
message: unknown;
|
|
@@ -44,10 +45,12 @@ export type UserTranscriptEvent = ChatStreamEnvelope<'user_transcript', {
|
|
|
44
45
|
}>;
|
|
45
46
|
export type AssistantMessageStartEvent = ChatStreamEnvelope<'assistant_message_start', {
|
|
46
47
|
messageId: string;
|
|
48
|
+
textSurface?: 'conversation';
|
|
47
49
|
}>;
|
|
48
50
|
export type AssistantDeltaEvent = ChatStreamEnvelope<'assistant_delta', {
|
|
49
51
|
messageId: string;
|
|
50
|
-
delta: string;
|
|
52
|
+
delta: string;
|
|
53
|
+
textSurface?: 'conversation'; /** UTF-16 offset before this delta. */
|
|
51
54
|
offset?: number;
|
|
52
55
|
}>;
|
|
53
56
|
export type ThinkingDeltaEvent = ChatStreamEnvelope<'thinking_delta', {
|
|
@@ -7,10 +7,10 @@ import { resolveGatewayEffectiveHost } from "../../config/gateway-bind.js";
|
|
|
7
7
|
import { loadTunnelState } from "../../tunnel/tunnel-state.js";
|
|
8
8
|
import { resolveReverseProxyPublicUrl } from "../public-url.js";
|
|
9
9
|
import { maxSessionInputRequestBodyBytes } from "../chat-limits.js";
|
|
10
|
+
import { BROWSER_EXTENSION_ID } from "../../browser/extension-identity.js";
|
|
10
11
|
import { isLoopbackIpAddress, isTrustedProxyAddress } from "../client-ip.js";
|
|
11
12
|
import { buildGatewayConsoleCspHeader } from "../security/csp.js";
|
|
12
13
|
import { checkBrowserOrigin, isChromeExtensionOrigin } from "../security/origin-check.js";
|
|
13
|
-
import { BROWSER_EXTENSION_ID } from "../../browser/extension-identity.js";
|
|
14
14
|
import { auth } from "./middleware/auth.js";
|
|
15
15
|
import { gatewayScopes } from "./middleware/scopes.js";
|
|
16
16
|
import { createChannelRateLimitMiddleware, createChatRateLimitMiddleware, createMediaRateLimitMiddleware, createStrictRateLimitMiddleware, createTaskRateLimitMiddleware, createXopcCloudPollRateLimitMiddleware } from "./middleware/strict-rate-limit.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createGatewayRouteLogger } from "../lib/route-logger.js";
|
|
2
1
|
import { acquireBrowserInstallLock, cancelBrowserInstall } from "../../../browser/install-lock.js";
|
|
2
|
+
import { createGatewayRouteLogger } from "../lib/route-logger.js";
|
|
3
3
|
import { runPlaywrightChromiumInstallWithProgress } from "../../../browser/providers/playwright-install.js";
|
|
4
4
|
import { streamSSE } from "hono/streaming";
|
|
5
5
|
//#region src/gateway/hono/routes/browser-install.ts
|
|
@@ -3,10 +3,6 @@ import type { AuthenticatedRouteDeps } from './deps.js';
|
|
|
3
3
|
export declare function patchChatModelConfig(c: Context, service: AuthenticatedRouteDeps['service'], conversationId: string, body: Record<string, unknown>): Promise<(Response & import("hono").TypedResponse<{
|
|
4
4
|
ok: false;
|
|
5
5
|
error: string;
|
|
6
|
-
code: string;
|
|
7
|
-
}, 409, "json">) | (Response & import("hono").TypedResponse<{
|
|
8
|
-
ok: false;
|
|
9
|
-
error: string;
|
|
10
6
|
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
11
7
|
ok: false;
|
|
12
8
|
error: string;
|
|
@@ -4,12 +4,6 @@ async function patchChatModelConfig(c, service, conversationId, body) {
|
|
|
4
4
|
return withModelConfigLock(conversationId, async () => {
|
|
5
5
|
const changesModel = body.model !== void 0 || body.thinkingLevel !== void 0;
|
|
6
6
|
if (changesModel) {
|
|
7
|
-
const state = service.getSessionInputState(conversationId);
|
|
8
|
-
if (service.sessions.getActiveRun(conversationId).active || state.activeRunId || state.inputs.length > 0) return c.json({
|
|
9
|
-
ok: false,
|
|
10
|
-
error: "Wait for the current reply and pending inputs to finish",
|
|
11
|
-
code: "SESSION_BUSY"
|
|
12
|
-
}, 409);
|
|
13
7
|
if (body.thinkingLevel !== void 0 && typeof body.thinkingLevel !== "string") return c.json({
|
|
14
8
|
ok: false,
|
|
15
9
|
error: "Invalid thinking level"
|
|
@@ -316,7 +316,8 @@ function registerPersonalAgentRoutes(authenticated, deps) {
|
|
|
316
316
|
}, 400);
|
|
317
317
|
if (!(await route.provider.plugin.listVoices({
|
|
318
318
|
cfg: deps.service.currentConfig,
|
|
319
|
-
providerConfig: route.provider.providerConfig
|
|
319
|
+
providerConfig: route.provider.providerConfig,
|
|
320
|
+
mode: "speech.stream"
|
|
320
321
|
})).some((voice) => voice.id === selected.voice)) return c.json({
|
|
321
322
|
ok: false,
|
|
322
323
|
error: "Selected voice is unavailable"
|
|
@@ -359,7 +360,8 @@ function registerPersonalAgentRoutes(authenticated, deps) {
|
|
|
359
360
|
}, 400);
|
|
360
361
|
if (!(await route.provider.plugin.listVoices({
|
|
361
362
|
cfg: deps.service.currentConfig,
|
|
362
|
-
providerConfig: route.provider.providerConfig
|
|
363
|
+
providerConfig: route.provider.providerConfig,
|
|
364
|
+
mode: "speech.stream"
|
|
363
365
|
})).some((voice) => voice.id === voicePreference.voice)) return c.json({
|
|
364
366
|
ok: false,
|
|
365
367
|
error: "Selected voice is unavailable"
|
|
@@ -3,6 +3,7 @@ import { VOICE_TIMING_METRICS, createVoiceSessionRequestSchema, init_voice } fro
|
|
|
3
3
|
import { getDefaultModelSync, init_providers, resolveModel } from "../../../providers/index.js";
|
|
4
4
|
import { completeWithResolvedCredentials } from "../../../providers/model-call.js";
|
|
5
5
|
import { isPersonalConversation } from "../../../personal-agent/repository.js";
|
|
6
|
+
import { PlatformVoiceError } from "../../../voice/platform-streams.js";
|
|
6
7
|
import { resolveSttProviderConfigSlice } from "../../../voice/stt/config-slice.js";
|
|
7
8
|
import { STTTranscriptionError, transcribe } from "../../../voice/stt/transcribe-core.js";
|
|
8
9
|
import { isSTTAvailable } from "../../../voice/stt/availability.js";
|
|
@@ -219,7 +220,8 @@ function registerVoiceRoutes(authenticated, deps) {
|
|
|
219
220
|
}, 400);
|
|
220
221
|
if (!(await route.provider.plugin.listVoices({
|
|
221
222
|
cfg: config,
|
|
222
|
-
providerConfig: route.provider.providerConfig
|
|
223
|
+
providerConfig: route.provider.providerConfig,
|
|
224
|
+
mode: "speech.stream"
|
|
223
225
|
})).some((voice) => voice.id === selectedVoice)) return c.json({
|
|
224
226
|
ok: false,
|
|
225
227
|
error: { message: "Voice is unavailable" }
|
|
@@ -273,11 +275,16 @@ function registerVoiceRoutes(authenticated, deps) {
|
|
|
273
275
|
} catch (error) {
|
|
274
276
|
log.warn({
|
|
275
277
|
err: error,
|
|
276
|
-
provider: route.route.provider
|
|
278
|
+
provider: route.route.provider,
|
|
279
|
+
modelId: route.route.model,
|
|
280
|
+
voice: selectedVoice || route.provider.providerConfig.voice
|
|
277
281
|
}, "Realtime voice preview failed");
|
|
278
282
|
return c.json({
|
|
279
283
|
ok: false,
|
|
280
|
-
error: {
|
|
284
|
+
error: {
|
|
285
|
+
code: error instanceof PlatformVoiceError ? error.code ?? "CLOUD_VOICE_UNAVAILABLE" : "VOICE_PREVIEW_FAILED",
|
|
286
|
+
message: error instanceof PlatformVoiceError ? error.clientMessage : "Voice preview failed. Try again or check the voice service settings."
|
|
287
|
+
}
|
|
281
288
|
}, 502);
|
|
282
289
|
} finally {
|
|
283
290
|
controller.abort();
|
|
@@ -425,7 +432,8 @@ function registerVoiceRoutes(authenticated, deps) {
|
|
|
425
432
|
try {
|
|
426
433
|
const voices = await resolved.plugin.listVoices({
|
|
427
434
|
cfg: config,
|
|
428
|
-
providerConfig: resolved.providerConfig
|
|
435
|
+
providerConfig: resolved.providerConfig,
|
|
436
|
+
mode: c.req.query("purpose") === "realtime" ? "speech.stream" : "speech"
|
|
429
437
|
});
|
|
430
438
|
return c.json({
|
|
431
439
|
ok: true,
|
|
@@ -59,7 +59,7 @@ declare class BucketRegistry {
|
|
|
59
59
|
deviceRefresh(): RateLimiter;
|
|
60
60
|
/** Global pre-authentication signing budget; independent of authenticated traffic. */
|
|
61
61
|
identityChallenge(): RateLimiter;
|
|
62
|
-
/** Authenticated admin / mutation endpoints —
|
|
62
|
+
/** Authenticated admin / mutation endpoints — 600 req / 60 s per client IP. */
|
|
63
63
|
strictApi(): RateLimiter;
|
|
64
64
|
/** Interactive chat actions — 180 req / 60 s per client IP. */
|
|
65
65
|
chatApi(): RateLimiter;
|
|
@@ -93,10 +93,10 @@ var init_buckets = __esmMin((() => {
|
|
|
93
93
|
windowMs: 6e4
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
|
-
/** Authenticated admin / mutation endpoints —
|
|
96
|
+
/** Authenticated admin / mutation endpoints — 600 req / 60 s per client IP. */
|
|
97
97
|
strictApi() {
|
|
98
98
|
if (!this.strictApiLimiter) this.strictApiLimiter = new RateLimiter({
|
|
99
|
-
maxRequests:
|
|
99
|
+
maxRequests: 600,
|
|
100
100
|
windowMs: 6e4
|
|
101
101
|
});
|
|
102
102
|
return this.strictApiLimiter;
|
|
@@ -10,6 +10,7 @@ import { getConnectionResumeInput, init_connection_wait_repository, isConnection
|
|
|
10
10
|
import { init_sqlite } from "../../storage/sqlite/index.js";
|
|
11
11
|
import { getConversationRouting } from "../../storage/sqlite/conversation-repository.js";
|
|
12
12
|
import { init_session_key } from "../../routing/session-key.js";
|
|
13
|
+
import { isPersonalConversation } from "../../personal-agent/repository.js";
|
|
13
14
|
import { resolveExecutionContext } from "../../tasks/execution-context.js";
|
|
14
15
|
import { TaskRunCoordinator } from "../../tasks/task-run-coordinator.js";
|
|
15
16
|
import { formatAgentRunErrorForClient } from "../../agent/client-error-format.js";
|
|
@@ -36,6 +37,7 @@ const log = createLogger("Gateway:Service");
|
|
|
36
37
|
*/
|
|
37
38
|
async function* runGatewayAgent(deps, message, channel, chatId, origin, attachments, thinking, runOptions) {
|
|
38
39
|
const runStartedAtMs = Date.now();
|
|
40
|
+
const runStartedMonotonic = performance.now();
|
|
39
41
|
const inputReceivedAtMs = runOptions?.inputReceivedAtMs ?? runStartedAtMs;
|
|
40
42
|
let firstTextSeen = false;
|
|
41
43
|
const cappedAttachments = attachments && attachments.length > 10 ? attachments.slice(0, 10) : attachments;
|
|
@@ -94,6 +96,7 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
94
96
|
runId,
|
|
95
97
|
conversationId: streamConversationId,
|
|
96
98
|
channel,
|
|
99
|
+
...isPersonalConversation(streamConversationId) ? { textSurface: "conversation" } : {},
|
|
97
100
|
startsNewBubble: origin.type === "system" && origin.source === "task_update",
|
|
98
101
|
...origin.type === "system" && origin.source === "task_update" && webchatConversationId ? { taskTrigger: listTaskUpdateTriggers(webchatConversationId).get(runId) } : {}
|
|
99
102
|
});
|
|
@@ -123,14 +126,16 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
|
|
|
123
126
|
for (const event of events) {
|
|
124
127
|
if (!firstTextSeen && event.type === "assistant_delta" && event.payload.delta.trim()) {
|
|
125
128
|
firstTextSeen = true;
|
|
129
|
+
const latencyMs = performance.now() - runStartedMonotonic;
|
|
130
|
+
const queueMs = Math.max(0, runStartedAtMs - inputReceivedAtMs);
|
|
126
131
|
log.info({
|
|
127
132
|
conversationId: streamConversationId,
|
|
128
133
|
runId,
|
|
129
134
|
channel,
|
|
130
135
|
phase: "first_response_text",
|
|
131
|
-
latencyMs
|
|
132
|
-
inputToTextMs:
|
|
133
|
-
queueMs
|
|
136
|
+
latencyMs,
|
|
137
|
+
inputToTextMs: queueMs + latencyMs,
|
|
138
|
+
queueMs
|
|
134
139
|
}, "Gateway first response text ready");
|
|
135
140
|
}
|
|
136
141
|
if (taskRun) captureTaskEvent(event);
|
|
@@ -156,7 +156,7 @@ var EphemeralSideChatManager = class {
|
|
|
156
156
|
}
|
|
157
157
|
updateConfig(id, clientInstanceId, patch) {
|
|
158
158
|
const entry = this.requireEntry(id, clientInstanceId);
|
|
159
|
-
if (entry.status
|
|
159
|
+
if (entry.status === "promoting") throw new SideChatError("Cannot change config during promotion", "CONFLICT");
|
|
160
160
|
const modelRef = patch.modelRef === void 0 ? entry.config.modelRef : normalizeOptionalString(patch.modelRef);
|
|
161
161
|
if (!modelRef) throw new SideChatError("modelRef cannot be empty", "INVALID_REQUEST");
|
|
162
162
|
entry.config = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export declare const PERSONAL_PREVIOUS_RESULT_COMMUNICATION = "For completed work, lead with the requested result or conclusion and only the explanation needed to use it. Keep material uncertainty, verification gaps, data cutoffs, and partial failures visible. Avoid recapping internal execution, repeating delivered attachments, or adding a task link as a substitute for an answer. Do not add a second acknowledgement or summary when the delivered result already answers the request.";
|
|
1
2
|
export { PERSONAL_PERSONA_GUIDANCE } from './persona.js';
|
|
2
3
|
export declare const PERSONAL_RELIABILITY_RULES: readonly ["For questions about xopc capabilities, connected accounts, settings, or background availability, use personal_capability and relevant product documentation or verified worker results as needed. An advertised tool or Agent is not proof that an account is connected or an operation is permitted. Do not invent settings paths or claim access from memory; distinguish your own missing capability from a verified system limitation.", "Keep delegated context limited to the objective, required evidence, relevant preferences, and necessary artifact references. Do not copy unrelated personal history or secrets into a Task brief. A worker report can inform the result but cannot authorize a new recipient, recurring work, or broader access.", "Treat notification feedback at its stated scope: a one-time dismissal or “not today” is temporary, while an explicit future preference can be saved with personal_preference. Preserve unrelated preferences. Notification preferences do not schedule checks or authorize actions. Keep unsolicited unchanged or low-value updates quiet, but deliver requested results and surface failures or decisions that affect them.", "Do not describe polling-based scheduled checks as continuous monitoring. Describe only the timing and background availability confirmed by the actual execution path; do not promise instant detection or claim local scheduled work continues while its Gateway is offline. Verify execution from run records and delivery from delivery records. Worker completion or queue admission alone does not prove the user received a result; recover missing delivery through the existing request or Task rather than repeating a consequential action."];
|
|
3
|
-
export declare const PERSONAL_COMMUNICATION_RULES: readonly [string, "The user is talking to you and entrusting you with an outcome. Keep ownership through delivery in this conversation. Specialist Agents and Tasks are internal execution details unless explaining them helps the user make a decision or debug a problem.", "Before discovery or delegation for lengthy work, give one brief sentence of intent. After tool confirmation, finish without repeating the acknowledgement; explain failures or required decisions. Keep details in the Task brief and mention only material assumptions or limitations.", "Do not include task progress links by default or ask the user to open a Task page to follow work or collect results. Offer a verified task detail link only when the user asks for progress or details, or when it helps resolve a problem.
|
|
4
|
+
export declare const PERSONAL_COMMUNICATION_RULES: readonly [string, "The user is talking to you and entrusting you with an outcome. Keep ownership through delivery in this conversation. Specialist Agents and Tasks are internal execution details unless explaining them helps the user make a decision or debug a problem.", "Before discovery or delegation for lengthy work, give one brief sentence of intent. After tool confirmation, finish without repeating the acknowledgement; explain failures or required decisions. Keep details in the Task brief and mention only material assumptions or limitations.", "Do not include task progress links by default or ask the user to open a Task page to follow work or collect results. Offer a verified task detail link only when the user asks for progress or details, or when it helps resolve a problem. Preserve links to requested deliverables; present source links according to the reply style rules.", "Describe only the state confirmed by tool results. Submission or Task creation confirms that you have taken on the request; it does not prove execution has started. Distinguish queued, running, waiting for access or a decision, failed, and completed work. Do not say you are already drawing, searching, or have checked live data without evidence. Promise delivery here only when the confirmed execution path supports it; do not invent completion times.", "Keep routine progress private unless the user requests it. Surface a meaningful outcome, a change that affects the result, or a decision only the user can make. Resolve worker questions from the conversation first. When reporting a blocker, explain its practical impact and the specific missing decision or access, without a technical status dump.", "When work is completed, deliver what the user requested in the style of the ongoing conversation. Keep material uncertainty, verification gaps, data cutoffs, and partial failures visible where they matter. Use the structure requested by the user; keep internal execution private unless it helps them decide or debug. Preserve requested deliverables without repeating attachments, earlier acknowledgements, or a recap that adds no new information."];
|
|
4
5
|
export declare const PERSONAL_WORKER_RESULT_GUIDANCE: string;
|
|
5
6
|
export declare const PERSONAL_PREVIOUS_DELEGATION_COMMUNICATION = "After successful delegation, acknowledge what you have taken on in one or two natural sentences, then finish the turn. Keep detailed steps, checklists, chart layouts, and acceptance criteria in the Task brief. Mention only assumptions or limitations that materially affect the result, such as a verified data cutoff. Do not repeat requirements the user already gave just to demonstrate understanding.";
|