@xopcai/xopc 0.0.325 → 0.0.330
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/README.md +4 -3
- package/README.zh-CN.md +4 -3
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CxfXpPWs.js → agent-avatar-dicebear-BDG0hI-J.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-ArM6Sm9S.js +1 -0
- package/dist/gateway/static/root/assets/agent-plugin-dialog-BX_Bhre1.js +1 -0
- package/dist/gateway/static/root/assets/agents-BiQqpMw0.js +70 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-p7fZB4dT.js → app-management-settings-panel-DgttzUCG.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-C-clVcfp.js → appearance-settings-CHpyWV8Z.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BhfYQcm8.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-Xm6xChUX.js → archive-plugin-B7Q7Oeo7.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Di8kuG4L.js → attachment-load-BYwqQ8qN.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-GUZgDhKj.js → automations-page-CsvAtTNd.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-DMH_1Ped.js +7 -0
- package/dist/gateway/static/root/assets/{binary-plugins-OCrDjC9O.js → binary-plugins-DdgWCI-M.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-m9tqvu7x.js → block-editor-DyOagNnn.js} +3 -3
- package/dist/gateway/static/root/assets/{browser-automation-inputs-DSWXq9lI.js → browser-automation-inputs-CwF8OQFN.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-DuOaridE.js → browser-automations-page-D_EQjiiu.js} +2 -2
- package/dist/gateway/static/root/assets/browser-settings-page-BE6691Jz.js +3 -0
- package/dist/gateway/static/root/assets/capabilities-page-MweWNrC1.js +2 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-CdSWkh89.js +8 -0
- package/dist/gateway/static/root/assets/capability-header-actions-C5F2GNE9.js +1 -0
- package/dist/gateway/static/root/assets/capability-icon-BYm2-nS-.js +1 -0
- package/dist/gateway/static/root/assets/channels-NGfwR3He.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-BfnVh8oo.js → chat-terminal-dock-C6tl9Rfw.js} +2 -2
- package/dist/gateway/static/root/assets/computer-settings-page-C0MsVw4l.js +1 -0
- package/dist/gateway/static/root/assets/connector-service-page-DsF60pPs.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-BE8NdQcR.js +2 -0
- package/dist/gateway/static/root/assets/{date-picker-CtDyij_x.js → date-picker-CELKKqYN.js} +1 -1
- package/dist/gateway/static/root/assets/dependency-picker-BcEwCnI5.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-BsIYCAkG.js → desktop-pet-Ww7Gm8-x.js} +1 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-D-dbAxGu.js +1 -0
- package/dist/gateway/static/root/assets/device-pairing-wizard-DsYY6szg.js +1 -0
- package/dist/gateway/static/root/assets/directory-picker-path-field-CVmuCRyO.js +1 -0
- package/dist/gateway/static/root/assets/ellipsis-0k4rZLoy.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-Ct9pABNW.js → extension-debug-page-UUHNJj-d.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BktsR4hj.js → extension-page-BvL452mX.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BQJc-vXH.js → extension-settings-page-CrNnUSOs.js} +1 -1
- package/dist/gateway/static/root/assets/external-link-DjqjBmc3.js +1 -0
- package/dist/gateway/static/root/assets/eye-CABVeTq0.js +1 -0
- package/dist/gateway/static/root/assets/folder-open-CyzJ19I9.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-swr-CoQVulMd.js → gateway-config-swr-DMm1vU51.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-DrHhtZqv.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-B5GJ-CQV.js → gateway-startup-retry-Ck6tj6yE.js} +1 -1
- package/dist/gateway/static/root/assets/globe-DSSGFWFn.js +1 -0
- package/dist/gateway/static/root/assets/home-page-YgI6jfGA.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-DvWDkbk1.js → image-generation-api-BOh6j0BF.js} +1 -1
- package/dist/gateway/static/root/assets/imports-page-BuqdzA7h.js +1 -0
- package/dist/gateway/static/root/assets/index-DJmO2VAY.css +1 -0
- package/dist/gateway/static/root/assets/index-vCIBfJp7.js +121 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-ctJLm8TP.js → keyboard-shortcuts-settings-D9L7IdUg.js} +1 -1
- package/dist/gateway/static/root/assets/link-2-D_ZKYUW7.js +1 -0
- package/dist/gateway/static/root/assets/loader-circle-CifKLtgG.js +1 -0
- package/dist/gateway/static/root/assets/local-app-workbench-page-DO8uUtos.js +1 -0
- package/dist/gateway/static/root/assets/{local-apps-page-BxC_LTqq.js → local-apps-page-BEvyufm7.js} +1 -1
- package/dist/gateway/static/root/assets/locale-store-DAOwT3Zp.js +1 -0
- package/dist/gateway/static/root/assets/logs-page-Jev1m9sS.js +2 -0
- package/dist/gateway/static/root/assets/management-settings-41i7B1RO.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-view-Dft8ASFD.js → markdown-view-nL4xzvI8.js} +2 -2
- package/dist/gateway/static/root/assets/{media-plugins-ni5zJ4Ok.js → media-plugins-dHbcqMan.js} +1 -1
- package/dist/gateway/static/root/assets/message-square-plus-XP0tGdlV.js +1 -0
- package/dist/gateway/static/root/assets/messages-BZbt9x1y.js +3 -0
- package/dist/gateway/static/root/assets/minimize-2-DtOGrlpo.js +1 -0
- package/dist/gateway/static/root/assets/note-detail-panel-DonP0E6Q.js +5 -0
- package/dist/gateway/static/root/assets/note-image-lightbox-1qg2v-9j.js +1 -0
- package/dist/gateway/static/root/assets/notes-page-CYHMeVKo.js +8 -0
- package/dist/gateway/static/root/assets/page-context-capture-button-BKsMcPOy.js +1 -0
- package/dist/gateway/static/root/assets/pencil-DmIY3Oa-.js +1 -0
- package/dist/gateway/static/root/assets/preview-open-alternatives-Du18QgWc.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-DQctU8z3.js → product-open-page-IY1QL6s0.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-Bpw9mxfV.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BdYbDNUn.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-DWWO6ajd.js → registry-api-DCFXWBOt.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CLhbz3TF.js +1 -0
- package/dist/gateway/static/root/assets/rotate-cw-LIg3Am9S.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-xhOSYfiX.js → runtime-tools-settings-panel-CuTFmXyj.js} +2 -2
- package/dist/gateway/static/root/assets/scenes-page-XwK2IEmr.js +2 -0
- package/dist/gateway/static/root/assets/{schema-form-z8IeSdBp.js → schema-form-qWQii8IU.js} +1 -1
- package/dist/gateway/static/root/assets/search-DA7gz22f.js +1 -0
- package/dist/gateway/static/root/assets/sessions-page-4-QoiDES.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BggQVM1y.js +1 -0
- package/dist/gateway/static/root/assets/settings-form-section-B0ZBr0L9.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-Br9no5e4.js → settings-page-DpII4NO3.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-layout-X1x-2Cp9.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-HPpC7EE0.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-CE0SER59.js → share-preview-page-B2CGYZHc.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-DhVCRYGP.js +1 -0
- package/dist/gateway/static/root/assets/skill-api-_ddww47C.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-XPZkWJJe.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-uF7DkJMC.js +2 -0
- package/dist/gateway/static/root/assets/system-settings-panel-25ABVt7H.js +1 -0
- package/dist/gateway/static/root/assets/task-detail-page-gepxhO4j.js +1 -0
- package/dist/gateway/static/root/assets/tunnel-api-CwQGBI_4.js +1 -0
- package/dist/gateway/static/root/assets/use-autosave-CL3wytbs.js +1 -0
- package/dist/gateway/static/root/assets/user-model-page-DldQW9Wh.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-By6Lgbse.js → voice-api-key-field-zjAzQrx4.js} +1 -1
- package/dist/gateway/static/root/assets/voice-config-api-DvzQ-128.js +1 -0
- package/dist/gateway/static/root/assets/{work-discovery-overlay-DdhgIlyf.js → work-discovery-overlay-MaPPjWwl.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BOJYQaxX.js → workflow-run-setup-panel-C3dQN1fE.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-B9lnTU3U.js +6 -0
- package/dist/gateway/static/root/connector-icons/SOURCES.md +1 -0
- package/dist/gateway/static/root/connector-icons/wecom.svg +9 -0
- package/dist/gateway/static/root/index.html +20 -8
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-instance-gateway.d.ts +2 -2
- package/dist/src/agent/agent-manager.d.ts +5 -2
- package/dist/src/agent/agent-manager.js +77 -23
- package/dist/src/agent/background-review/coordinator.d.ts +2 -7
- package/dist/src/agent/background-review/coordinator.js +17 -34
- package/dist/src/agent/background-review/prompts.d.ts +13 -5
- package/dist/src/agent/background-review/prompts.js +17 -12
- package/dist/src/agent/background-review/run-background-review.d.ts +3 -3
- package/dist/src/agent/background-review/run-background-review.js +59 -44
- package/dist/src/agent/bootstrap/filter-bootstrap-files.js +1 -1
- package/dist/src/agent/capabilities/definitions.d.ts +3 -2
- package/dist/src/agent/capabilities/definitions.js +3 -2
- package/dist/src/agent/context/execution-context.js +5 -2
- package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
- package/dist/src/agent/image/tool-model-config.js +1 -1
- package/dist/src/agent/mcp/index.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +2 -2
- package/dist/src/agent/mcp/oauth/index.js +1 -1
- package/dist/src/agent/mcp/oauth/mcp-oauth-manager.js +2 -2
- package/dist/src/agent/mcp/oauth/mcp-oauth-provider.js +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
- package/dist/src/agent/orchestration/llm-turn-retry.js +2 -15
- package/dist/src/agent/prompt/sections/tooling.js +3 -0
- package/dist/src/agent/service/direct-turn-helpers.js +1 -1
- package/dist/src/agent/service.d.ts +1 -0
- package/dist/src/agent/service.js +5 -2
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +12 -0
- package/dist/src/agent/tasks/task-judge-service.js +1 -1
- package/dist/src/agent/tools/factory.js +3 -2
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/user-context-tool.js +29 -4
- package/dist/src/agent/tools/workflow-manage-tool.d.ts +2 -0
- package/dist/src/agent/tools/workflow-manage-tool.js +225 -0
- package/dist/src/agent/tools/xopc-use-tool.js +1 -1
- package/dist/src/agent-catalog/capabilities.js +2 -2
- package/dist/src/auth/credentials.js +1 -1
- package/dist/src/auth/oauth-provider-lock.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/automations/capabilities/drafts.js +1 -1
- package/dist/src/automations/domain/types.d.ts +7 -1
- package/dist/src/automations/draft/automation-draft-service.js +13 -4
- package/dist/src/automations/service/action-executor.d.ts +2 -2
- package/dist/src/automations/service/action-executor.js +36 -13
- package/dist/src/automations/service/automation-service.js +2 -1
- package/dist/src/bootstrap/application-state.js +1 -1
- package/dist/src/browser/automations/index.js +2 -2
- package/dist/src/browser/automations/service.d.ts +11 -2
- package/dist/src/browser/automations/service.js +19 -5
- package/dist/src/capabilities/readiness/from-config.d.ts +0 -1
- package/dist/src/capabilities/readiness/from-config.js +2 -4
- package/dist/src/capabilities/runtime/dispatcher.js +1 -1
- package/dist/src/capabilities/runtime/product.js +1 -1
- package/dist/src/chat-commands/agent-edit.js +1 -1
- package/dist/src/chat-commands/builtins/config.js +1 -1
- package/dist/src/chat-previews/service.js +1 -2
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/agents.js +1 -1
- package/dist/src/cli/commands/auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/extension-agent-plugin.js +2 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard/model.js +3 -3
- package/dist/src/cli/commands/providers.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +1 -1
- package/dist/src/config/index.js +4 -4
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.js +5 -5
- package/dist/src/connectors/china-catalog.js +5 -1
- package/dist/src/connectors/connected-source-ingestion.js +6 -1
- package/dist/src/connectors/connected-source-observations.d.ts +10 -0
- package/dist/src/connectors/connected-source-observations.js +80 -0
- package/dist/src/connectors/connected-source-understanding.js +198 -8
- package/dist/src/connectors/learning-coordinator.js +63 -26
- package/dist/src/connectors/learning-recipes.js +19 -2
- package/dist/src/discussions/audio-repair.d.ts +1 -1
- package/dist/src/discussions/live-worker.js +1 -3
- package/dist/src/discussions/recording.js +2 -2
- package/dist/src/discussions/sealer.js +2 -2
- package/dist/src/extensions/agent-plugins/auth.d.ts +2 -2
- package/dist/src/extensions/agent-plugins/auth.js +6 -35
- package/dist/src/extensions/agent-plugins/credentials.d.ts +2 -0
- package/dist/src/extensions/agent-plugins/credentials.js +37 -0
- package/dist/src/extensions/agent-plugins/plugin-oauth-scope.d.ts +1 -0
- package/dist/src/extensions/agent-plugins/plugin-oauth-scope.js +8 -0
- package/dist/src/extensions/agent-plugins/validation.js +1 -1
- package/dist/src/extensions/bundled-extension-activation.d.ts +3 -1
- package/dist/src/extensions/bundled-extension-activation.js +5 -8
- package/dist/src/extensions/marketplace.d.ts +4 -0
- package/dist/src/extensions/marketplace.js +4 -0
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/file-path-classifier.js +1 -1
- package/dist/src/gateway/file-space-service.d.ts +9 -2
- package/dist/src/gateway/gateway-workflow-host.types.d.ts +1 -0
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/routes/agent-plugins.js +2 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +27 -5
- package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -2
- package/dist/src/gateway/hono/routes/config.js +0 -3
- package/dist/src/gateway/hono/routes/connectors.js +3 -10
- package/dist/src/gateway/hono/routes/context-sources.d.ts +0 -1
- package/dist/src/gateway/hono/routes/context-sources.js +12 -15
- package/dist/src/gateway/hono/routes/notes.js +2 -2
- package/dist/src/gateway/hono/routes/projects.js +2 -2
- package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
- package/dist/src/gateway/hono/routes/status.js +0 -1
- package/dist/src/gateway/hono/routes/tasks.js +1 -1
- package/dist/src/gateway/hono/routes/user-model.js +21 -3
- package/dist/src/gateway/hono/routes/voice.js +0 -67
- package/dist/src/gateway/hono/routes/workflows.js +1 -23
- package/dist/src/gateway/image-generation-setup.js +2 -2
- package/dist/src/gateway/lock.js +1 -1
- package/dist/src/gateway/service/config-coordinator.d.ts +4 -4
- package/dist/src/gateway/service/config-coordinator.js +6 -6
- package/dist/src/gateway/service/marketplace-service.js +8 -6
- package/dist/src/gateway/service.d.ts +1 -1
- package/dist/src/gateway/service.js +20 -18
- package/dist/src/gateway/xopc-cloud-capability-setup.js +1 -1
- package/dist/src/home-intelligence/generator.js +7 -6
- package/dist/src/home-intelligence/host.js +1 -1
- package/dist/src/local-apps/service.js +1 -1
- package/dist/src/media-understanding/types.d.ts +1 -1
- package/dist/src/memory-maintenance/service.d.ts +1 -0
- package/dist/src/memory-maintenance/service.js +13 -0
- package/dist/src/migrations/retired-local-stt.d.ts +2 -0
- package/dist/src/migrations/retired-local-stt.js +52 -0
- package/dist/src/migrations/runner.js +2 -1
- package/dist/src/providers/model-catalog-persistence.js +1 -1
- package/dist/src/providers/model-response.d.ts +2 -0
- package/dist/src/providers/model-response.js +24 -1
- package/dist/src/session/turn-outcome-projector.js +1 -1
- package/dist/src/storage/sqlite/connection.js +1 -0
- package/dist/src/storage/sqlite/migrations/207_user_model_policy_contract.sql +121 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/sql-assets.d.ts +1 -0
- package/dist/src/storage/sqlite/sql-assets.js +7 -4
- package/dist/src/tasks/capabilities/read.js +2 -2
- package/dist/src/tasks/index.js +2 -2
- package/dist/src/tasks/task-application-service.d.ts +1 -0
- package/dist/src/tasks/task-application-service.js +4 -2
- package/dist/src/tasks/task-context-assembler.js +10 -1
- package/dist/src/tasks/task-run-dispatcher.d.ts +1 -0
- package/dist/src/tasks/task-run-dispatcher.js +15 -2
- package/dist/src/tui/backends/embedded-backend.js +6 -3
- package/dist/src/tui/tui-commands.js +2 -2
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui.js +3 -3
- package/dist/src/user-context/sources/consent-repository.d.ts +7 -0
- package/dist/src/user-context/sources/consent-repository.js +81 -0
- package/dist/src/user-context/sources/index.d.ts +1 -0
- package/dist/src/user-context/sources/index.js +2 -1
- package/dist/src/user-context/sources/repository.js +73 -1
- package/dist/src/user-context/sources/types.d.ts +16 -0
- package/dist/src/user-model/action-rule-suggestions.d.ts +11 -0
- package/dist/src/user-model/action-rule-suggestions.js +29 -0
- package/dist/src/user-model/bootstrap.js +1 -1
- package/dist/src/user-model/capture/executor.js +83 -7
- package/dist/src/user-model/capture/semantic.d.ts +5 -2
- package/dist/src/user-model/capture/semantic.js +27 -11
- package/dist/src/user-model/domain.d.ts +26 -0
- package/dist/src/user-model/domain.js +40 -2
- package/dist/src/user-model/index.d.ts +2 -0
- package/dist/src/user-model/index.js +6 -4
- package/dist/src/user-model/maintenance-policy.d.ts +1 -0
- package/dist/src/user-model/maintenance-policy.js +13 -0
- package/dist/src/user-model/observation-repository.d.ts +48 -0
- package/dist/src/user-model/observation-repository.js +100 -0
- package/dist/src/user-model/repository.d.ts +5 -0
- package/dist/src/user-model/repository.js +121 -10
- package/dist/src/user-model/usage-policy.d.ts +5 -2
- package/dist/src/user-model/usage-policy.js +2 -2
- package/dist/src/voice/audio/normalize.d.ts +1 -1
- package/dist/src/voice/audio/normalize.js +1 -1
- package/dist/src/voice/{local → audio}/wav.js +1 -1
- package/dist/src/voice/language-profile.js +10 -16
- package/dist/src/voice/metadata/builtin.js +0 -46
- package/dist/src/voice/platform-streams.js +15 -7
- package/dist/src/voice/realtime/agentEngine.js +19 -3
- package/dist/src/voice/realtime/pcmFrameBuffer.js +2 -1
- package/dist/src/voice/realtime/persona-context.js +1 -1
- package/dist/src/voice/realtime/playback-echo.js +16 -1
- package/dist/src/voice/stt/providers/index.d.ts +0 -1
- package/dist/src/voice/stt/providers/index.js +1 -2
- package/dist/src/voice/stt/types.js +3 -4
- package/dist/src/voice/tts/merge-config.js +1 -1
- package/dist/src/voice/tts/speech-registry.d.ts +1 -1
- package/dist/src/voice/tts/types.d.ts +1 -1
- package/dist/src/work-discovery/analyzer.js +6 -5
- package/dist/src/work-discovery/service.js +2 -2
- package/dist/src/work-discovery/types.d.ts +1 -1
- package/dist/src/workflows/authoring/index.d.ts +1 -0
- package/dist/src/workflows/authoring/index.js +2 -1
- package/dist/src/workflows/authoring/workflow-draft-defaults.d.ts +3 -0
- package/dist/src/workflows/authoring/workflow-draft-defaults.js +63 -0
- package/dist/src/workflows/context/workflow-context.js +5 -1
- package/dist/src/workflows/domain/index.js +1 -1
- package/dist/src/workflows/engine/workflow-engine.js +1 -1
- package/dist/src/workflows/index.js +4 -4
- package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
- package/dist/src/workflows/service/workflow-run-service.js +39 -7
- package/dist/src/workflows/service/workflow-session-bridge.js +2 -2
- package/package.json +12 -16
- package/skills/engineering/workflow-authoring/SKILL.md +32 -0
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CDHe8gJf.js +0 -1
- package/dist/gateway/static/root/assets/agent-plugin-dialog-DMv-udoZ.js +0 -1
- package/dist/gateway/static/root/assets/agents-D_xOAXgj.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-Dz2g7eAN.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-BUZhG9aJ.js +0 -7
- package/dist/gateway/static/root/assets/browser-settings-page-D2_PgHep.js +0 -3
- package/dist/gateway/static/root/assets/capabilities-settings-panel-7Y_pJqyt.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-B-Igy1ro.js +0 -1
- package/dist/gateway/static/root/assets/computer-settings-page-aRG2lU4w.js +0 -1
- package/dist/gateway/static/root/assets/connector-service-page-B5EhnfJH.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-7HfRt1LW.js +0 -2
- package/dist/gateway/static/root/assets/dependency-picker-z6ouWxmz.js +0 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-z-0aQ5ct.js +0 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-DlmhQvY5.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-BfDVlvy6.js +0 -1
- package/dist/gateway/static/root/assets/home-page-CI_eQTPL.js +0 -1
- package/dist/gateway/static/root/assets/imports-page-DFpQfHVU.js +0 -1
- package/dist/gateway/static/root/assets/index-19rMUT3d.js +0 -121
- package/dist/gateway/static/root/assets/index-BKL5tg2f.css +0 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-C9kaP3Dy.js +0 -1
- package/dist/gateway/static/root/assets/locale-store-BPZR8x9b.js +0 -1
- package/dist/gateway/static/root/assets/logs-page-Ok5SpG-G.js +0 -2
- package/dist/gateway/static/root/assets/management-settings-aOzRaQHM.js +0 -1
- package/dist/gateway/static/root/assets/messages-kFWhF6_t.js +0 -3
- package/dist/gateway/static/root/assets/note-detail-panel-C9OEltN9.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-Dj9rMgdi.js +0 -8
- package/dist/gateway/static/root/assets/page-context-capture-button-BJA3d8vU.js +0 -1
- package/dist/gateway/static/root/assets/page-tabs-Dyc3wKkl.js +0 -1
- package/dist/gateway/static/root/assets/preview-open-alternatives-tIOIQbNX.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-Dy-EwZcc.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-JaGKa6rM.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-Cb8-nd60.js +0 -1
- package/dist/gateway/static/root/assets/scenes-page-ClBkFdRY.js +0 -2
- package/dist/gateway/static/root/assets/sessions-page-BYW5l_nY.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CDNwmXuH.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-BXTJAser.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-layout-D6745w0p.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-D2N9764S.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Dk3_QOKQ.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CPt61fEv.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-Db6PB2C6.js +0 -2
- package/dist/gateway/static/root/assets/skills-page.utils-DrtW5FBy.js +0 -1
- package/dist/gateway/static/root/assets/system-settings-panel-CuY1Zh5s.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-o7RiDUMi.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-PGHDgvWb.js +0 -1
- package/dist/gateway/static/root/assets/use-autosave-B55oBQUt.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-DspelwAa.js +0 -2
- package/dist/gateway/static/root/assets/voice-config-api-BaxITrwZ.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-6ObD0IQZ.js +0 -6
- package/dist/src/voice/local/model-files.d.ts +0 -14
- package/dist/src/voice/local/model-files.js +0 -92
- package/dist/src/voice/local/model-manager.d.ts +0 -18
- package/dist/src/voice/local/model-manager.js +0 -133
- package/dist/src/voice/local/models.d.ts +0 -28
- package/dist/src/voice/local/models.js +0 -99
- package/dist/src/voice/local/provider-switch.d.ts +0 -4
- package/dist/src/voice/local/provider-switch.js +0 -36
- package/dist/src/voice/local/runtime-client.d.ts +0 -28
- package/dist/src/voice/local/runtime-client.js +0 -183
- package/dist/src/voice/local/runtime-worker.d.ts +0 -1
- package/dist/src/voice/local/runtime-worker.js +0 -271
- package/dist/src/voice/stt/providers/local-transcription.d.ts +0 -2
- package/dist/src/voice/stt/providers/local-transcription.js +0 -53
- package/dist/src/workflows/draft/index.d.ts +0 -3
- package/dist/src/workflows/draft/index.js +0 -3
- package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +0 -22
- package/dist/src/workflows/draft/workflow-draft-prompt.js +0 -54
- package/dist/src/workflows/draft/workflow-draft-service.d.ts +0 -12
- package/dist/src/workflows/draft/workflow-draft-service.js +0 -125
- package/dist/src/workflows/draft/workflow-draft-validator.d.ts +0 -4
- package/dist/src/workflows/draft/workflow-draft-validator.js +0 -123
- package/dist/src/workflows/draft/workflow-draft.types.d.ts +0 -44
- package/dist/src/workflows/draft/workflow-draft.types.js +0 -1
- /package/dist/src/voice/{local → audio}/wav.d.ts +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
|
|
2
|
+
import { init_domain } from "./domain.js";
|
|
3
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
4
|
+
//#region src/user-model/observation-repository.ts
|
|
5
|
+
init_transaction();
|
|
6
|
+
init_domain();
|
|
7
|
+
function fromRow(row) {
|
|
8
|
+
return {
|
|
9
|
+
id: row.observation_id,
|
|
10
|
+
principalId: row.principal_id,
|
|
11
|
+
domain: row.domain,
|
|
12
|
+
type: row.observation_type,
|
|
13
|
+
subject: {
|
|
14
|
+
type: row.subject_type,
|
|
15
|
+
id: row.subject_id
|
|
16
|
+
},
|
|
17
|
+
value: JSON.parse(row.value_json),
|
|
18
|
+
context: JSON.parse(row.context_json),
|
|
19
|
+
sensitivityCategories: JSON.parse(row.sensitivity_categories_json),
|
|
20
|
+
ownerAttribution: row.owner_attribution,
|
|
21
|
+
observedAt: row.observed_at,
|
|
22
|
+
...row.valid_to === null ? {} : { validTo: row.valid_to },
|
|
23
|
+
...row.delete_after === null ? {} : { deleteAfter: row.delete_after },
|
|
24
|
+
...row.source_grant_id === null ? {} : { sourceGrantId: row.source_grant_id },
|
|
25
|
+
...row.source_item_id === null ? {} : { sourceItemId: row.source_item_id },
|
|
26
|
+
...row.evidence_id === null ? {} : { evidenceId: row.evidence_id },
|
|
27
|
+
contentHash: row.content_hash,
|
|
28
|
+
createdAt: row.created_at
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function recordUserModelObservation(input) {
|
|
32
|
+
if (!input.type.trim() || !input.subject.id.trim()) throw new Error("Observation type and subject id are required.");
|
|
33
|
+
if (!Number.isFinite(input.observedAt)) throw new Error("Observation observedAt must be finite.");
|
|
34
|
+
const principalId = input.principalId ?? "local-owner";
|
|
35
|
+
const contentHash = input.contentHash ?? createHash("sha256").update(JSON.stringify([
|
|
36
|
+
principalId,
|
|
37
|
+
input.domain,
|
|
38
|
+
input.type,
|
|
39
|
+
input.subject,
|
|
40
|
+
input.value,
|
|
41
|
+
input.context,
|
|
42
|
+
input.ownerAttribution,
|
|
43
|
+
input.observedAt,
|
|
44
|
+
input.sourceGrantId,
|
|
45
|
+
input.sourceItemId
|
|
46
|
+
])).digest("hex");
|
|
47
|
+
const id = randomUUID();
|
|
48
|
+
const now = input.nowMs ?? Date.now();
|
|
49
|
+
runSqliteWriteTransaction((db) => db.prepare(`INSERT INTO user_model_observations (
|
|
50
|
+
observation_id, principal_id, domain, observation_type, subject_type, subject_id,
|
|
51
|
+
value_json, context_json, sensitivity_categories_json, owner_attribution, observed_at,
|
|
52
|
+
valid_to, delete_after, source_grant_id, source_item_id, evidence_id, content_hash, created_at
|
|
53
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
54
|
+
ON CONFLICT(principal_id, content_hash) DO UPDATE SET
|
|
55
|
+
observed_at = MAX(user_model_observations.observed_at, excluded.observed_at),
|
|
56
|
+
valid_to = excluded.valid_to, delete_after = excluded.delete_after`).run(id, principalId, input.domain, input.type.trim(), input.subject.type, input.subject.id.trim(), JSON.stringify(input.value), JSON.stringify(input.context), JSON.stringify(input.sensitivityCategories), input.ownerAttribution, input.observedAt, input.validTo ?? null, input.deleteAfter ?? null, input.sourceGrantId ?? null, input.sourceItemId ?? null, input.evidenceId ?? null, contentHash, now));
|
|
57
|
+
return fromRow(getSqliteDatabase().prepare(`SELECT * FROM user_model_observations
|
|
58
|
+
WHERE principal_id = ? AND content_hash = ?`).get(principalId, contentHash));
|
|
59
|
+
}
|
|
60
|
+
function listUserModelObservations(input = {}) {
|
|
61
|
+
const clauses = ["principal_id = ?"];
|
|
62
|
+
const values = [input.principalId ?? "local-owner"];
|
|
63
|
+
if (input.domain) {
|
|
64
|
+
clauses.push("domain = ?");
|
|
65
|
+
values.push(input.domain);
|
|
66
|
+
}
|
|
67
|
+
if (input.sourceGrantId) {
|
|
68
|
+
clauses.push("source_grant_id = ?");
|
|
69
|
+
values.push(input.sourceGrantId);
|
|
70
|
+
}
|
|
71
|
+
values.push(Math.max(1, Math.min(2e3, input.limit ?? 200)));
|
|
72
|
+
return getSqliteDatabase().prepare(`SELECT * FROM user_model_observations
|
|
73
|
+
WHERE ${clauses.join(" AND ")} ORDER BY observed_at DESC LIMIT ?`).all(...values).map(fromRow);
|
|
74
|
+
}
|
|
75
|
+
function deleteUserModelObservationsForGrant(grantId) {
|
|
76
|
+
return Number(getSqliteDatabase().prepare("DELETE FROM user_model_observations WHERE source_grant_id = ?").run(grantId).changes);
|
|
77
|
+
}
|
|
78
|
+
function linkUserAssertions(input) {
|
|
79
|
+
if (input.fromAssertionId === input.toAssertionId) throw new Error("An assertion cannot link to itself.");
|
|
80
|
+
if (!Number.isFinite(input.confidence) || input.confidence < 0 || input.confidence > 1) throw new Error("Assertion-edge confidence must be between 0 and 1.");
|
|
81
|
+
getSqliteDatabase().prepare(`INSERT INTO user_assertion_edges (
|
|
82
|
+
from_assertion_id, to_assertion_id, relation, confidence, created_at
|
|
83
|
+
) VALUES (?, ?, ?, ?, ?)
|
|
84
|
+
ON CONFLICT(from_assertion_id, to_assertion_id, relation)
|
|
85
|
+
DO UPDATE SET confidence = excluded.confidence`).run(input.fromAssertionId, input.toAssertionId, input.relation, input.confidence, input.nowMs ?? Date.now());
|
|
86
|
+
}
|
|
87
|
+
function listUserAssertionEdges(assertionIds) {
|
|
88
|
+
const ids = [...new Set(assertionIds?.filter(Boolean) ?? [])];
|
|
89
|
+
const where = ids.length ? `WHERE from_assertion_id IN (${ids.map(() => "?").join(",")}) OR to_assertion_id IN (${ids.map(() => "?").join(",")})` : "";
|
|
90
|
+
return getSqliteDatabase().prepare(`SELECT * FROM user_assertion_edges ${where}
|
|
91
|
+
ORDER BY created_at DESC`).all(...ids, ...ids).map((row) => ({
|
|
92
|
+
fromAssertionId: row.from_assertion_id,
|
|
93
|
+
toAssertionId: row.to_assertion_id,
|
|
94
|
+
relation: row.relation,
|
|
95
|
+
confidence: row.confidence,
|
|
96
|
+
createdAt: row.created_at
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { deleteUserModelObservationsForGrant, linkUserAssertions, listUserAssertionEdges, listUserModelObservations, recordUserModelObservation };
|
|
@@ -26,6 +26,11 @@ export declare function getActiveAssertionForSlot(input: {
|
|
|
26
26
|
}): UserAssertion | undefined;
|
|
27
27
|
export declare function getUserTimezone(): string | undefined;
|
|
28
28
|
export declare function linkAssertionEvidence(assertionId: string, evidenceId: string, relation: 'supports' | 'contradicts' | 'supersedes', confidence: number, now?: number): void;
|
|
29
|
+
export declare function mergeAssertionObservation(input: {
|
|
30
|
+
assertionId: string;
|
|
31
|
+
candidate: AssertionCandidate;
|
|
32
|
+
evidenceIds: string[];
|
|
33
|
+
}, now?: number): UserAssertion;
|
|
29
34
|
export declare function setAssertionStatus(assertionId: string, status: AssertionStatus, input: {
|
|
30
35
|
actor: 'user' | 'runtime' | 'maintenance' | 'migration';
|
|
31
36
|
reason: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
|
|
2
|
-
import { USER_MODEL_PRINCIPAL_ID, init_domain, validateCandidate, validateScope } from "./domain.js";
|
|
2
|
+
import { USER_MODEL_PRINCIPAL_ID, defaultAssertionDomain, defaultAssertionLayer, init_domain, validateCandidate, validateScope } from "./domain.js";
|
|
3
3
|
import { clearMemoryAudit, isMemorySuppressed, memoryFingerprint, restoreMemory, suppressMemory } from "../user-context/memory-suppression.js";
|
|
4
4
|
import { defaultReviewAt, requiresBoundedValidity } from "./temporal.js";
|
|
5
5
|
import { basename } from "node:path";
|
|
@@ -42,6 +42,17 @@ function assertionFromRow(row) {
|
|
|
42
42
|
volatility: row.volatility,
|
|
43
43
|
sensitivity: row.sensitivity,
|
|
44
44
|
disclosurePolicy: row.disclosure_policy,
|
|
45
|
+
domain: row.domain,
|
|
46
|
+
layer: row.model_layer,
|
|
47
|
+
sensitivityCategories: JSON.parse(row.sensitivity_categories_json),
|
|
48
|
+
purposeIds: JSON.parse(row.purpose_ids_json),
|
|
49
|
+
allowedUses: JSON.parse(row.allowed_uses_json),
|
|
50
|
+
...row.allowed_agent_ids_json === null ? {} : { allowedAgentIds: JSON.parse(row.allowed_agent_ids_json) },
|
|
51
|
+
...row.consent_receipt_id === null ? {} : { consentReceiptId: row.consent_receipt_id },
|
|
52
|
+
supportCount: row.support_count,
|
|
53
|
+
independentSourceCount: row.independent_source_count,
|
|
54
|
+
...row.last_supported_at === null ? {} : { lastSupportedAt: row.last_supported_at },
|
|
55
|
+
...row.delete_after === null ? {} : { deleteAfter: row.delete_after },
|
|
45
56
|
applicability: JSON.parse(row.applicability_json),
|
|
46
57
|
...row.valid_from === null ? {} : { validFrom: row.valid_from },
|
|
47
58
|
...row.valid_to === null ? {} : { validTo: row.valid_to },
|
|
@@ -87,21 +98,49 @@ function initialStatus(candidate) {
|
|
|
87
98
|
if (requiresBoundedValidity(candidate.kind, candidate.volatility) && candidate.validTo === void 0) return "needs_review";
|
|
88
99
|
return candidate.authority === "user_explicit" ? "active" : "candidate";
|
|
89
100
|
}
|
|
101
|
+
function assertConsentAllowsCandidate(db, candidate, domain) {
|
|
102
|
+
if (!candidate.consentReceiptId) return;
|
|
103
|
+
const row = db.prepare(`SELECT purposes_json, allowed_domains_json, denied_domains_json,
|
|
104
|
+
allowed_agent_ids_json, revoked_at
|
|
105
|
+
FROM understanding_consent_receipts WHERE receipt_id = ?`).get(candidate.consentReceiptId);
|
|
106
|
+
if (!row || row.revoked_at !== null) throw new Error("Assertion consent receipt is unavailable or revoked.");
|
|
107
|
+
const purposes = JSON.parse(row.purposes_json);
|
|
108
|
+
const allowedDomains = JSON.parse(row.allowed_domains_json);
|
|
109
|
+
const deniedDomains = JSON.parse(row.denied_domains_json);
|
|
110
|
+
const requestedPurposes = candidate.purposeIds ?? ["personalization"];
|
|
111
|
+
if (!allowedDomains.includes(domain) || deniedDomains.includes(domain)) throw new Error(`Consent does not allow the ${domain} domain.`);
|
|
112
|
+
if (requestedPurposes.some((purpose) => !purposes.includes(purpose))) throw new Error("Consent does not allow every requested purpose.");
|
|
113
|
+
if (row.allowed_agent_ids_json) {
|
|
114
|
+
const allowedAgents = JSON.parse(row.allowed_agent_ids_json);
|
|
115
|
+
if (!candidate.allowedAgentIds || candidate.allowedAgentIds.some((agentId) => !allowedAgents.includes(agentId))) throw new Error("Consent does not allow every requested agent.");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
90
118
|
function insertAssertion(db, slotId, candidate, status, now, supersedesAssertionId) {
|
|
91
119
|
const id = randomUUID();
|
|
92
120
|
const reviewAt = candidate.reviewAt ?? defaultReviewAt(candidate.volatility, candidate.observedAt) ?? null;
|
|
121
|
+
const domain = candidate.domain ?? defaultAssertionDomain(candidate.kind);
|
|
122
|
+
const layer = candidate.layer ?? defaultAssertionLayer(candidate);
|
|
93
123
|
db.prepare(`INSERT INTO user_assertions (
|
|
94
124
|
assertion_id, slot_id, kind, value_json, normalized_value, statement, authority, status,
|
|
95
125
|
confidence, declared_importance, inferred_importance, consequence, actionability,
|
|
96
126
|
volatility, sensitivity, disclosure_policy, applicability_json, valid_from, valid_to,
|
|
97
|
-
observed_at, recorded_at, review_at, supersedes_assertion_id, created_by, created_at
|
|
98
|
-
|
|
127
|
+
observed_at, recorded_at, review_at, supersedes_assertion_id, created_by, created_at,
|
|
128
|
+
domain, model_layer, sensitivity_categories_json, purpose_ids_json, allowed_uses_json,
|
|
129
|
+
allowed_agent_ids_json, consent_receipt_id, delete_after
|
|
130
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, slotId, candidate.kind, JSON.stringify(candidate.value), candidate.normalizedValue.trim(), candidate.statement.trim(), candidate.authority, status, candidate.confidence, candidate.declaredImportance ?? null, candidate.inferredImportance, candidate.consequence, candidate.actionability, candidate.volatility, candidate.sensitivity, candidate.disclosurePolicy, JSON.stringify(candidate.applicability ?? {}), candidate.validFrom ?? null, candidate.validTo ?? null, candidate.observedAt, now, reviewAt, supersedesAssertionId ?? null, candidate.createdBy, now, domain, layer, JSON.stringify(candidate.sensitivityCategories ?? []), JSON.stringify(candidate.purposeIds ?? ["personalization"]), JSON.stringify(candidate.allowedUses ?? [
|
|
131
|
+
"answer",
|
|
132
|
+
"rank",
|
|
133
|
+
"recommend"
|
|
134
|
+
]), candidate.allowedAgentIds ? JSON.stringify(candidate.allowedAgentIds) : null, candidate.consentReceiptId ?? null, candidate.deleteAfter ?? null);
|
|
99
135
|
db.prepare(`INSERT INTO user_assertions_fts(statement, assertion_id, slot_id) VALUES (?, ?, ?)`).run(candidate.statement.trim(), id, slotId);
|
|
100
136
|
recordStatusEvent(db, id, null, status, candidate.createdBy === "connector" ? "runtime" : candidate.createdBy, "Assertion admitted.", now);
|
|
101
|
-
if (candidate.evidenceId)
|
|
137
|
+
if (candidate.evidenceId) {
|
|
138
|
+
db.prepare(`INSERT INTO user_assertion_evidence (
|
|
102
139
|
assertion_id, evidence_id, relation, confidence, created_at
|
|
103
140
|
) VALUES (?, ?, 'supports', ?, ?)
|
|
104
141
|
ON CONFLICT(assertion_id, evidence_id, relation) DO UPDATE SET confidence = excluded.confidence`).run(id, candidate.evidenceId, candidate.evidenceConfidence ?? candidate.confidence, now);
|
|
142
|
+
refreshEvidenceStats(db, id);
|
|
143
|
+
}
|
|
105
144
|
return assertionFromRow(db.prepare("SELECT * FROM user_assertions WHERE assertion_id = ?").get(id));
|
|
106
145
|
}
|
|
107
146
|
function recordStatusEvent(db, assertionId, fromStatus, toStatus, actor, reason, now) {
|
|
@@ -115,6 +154,27 @@ function attachEvidence(db, assertionId, candidate, now) {
|
|
|
115
154
|
assertion_id, evidence_id, relation, confidence, created_at
|
|
116
155
|
) VALUES (?, ?, 'supports', ?, ?)
|
|
117
156
|
ON CONFLICT(assertion_id, evidence_id, relation) DO UPDATE SET confidence = excluded.confidence`).run(assertionId, candidate.evidenceId, candidate.evidenceConfidence ?? candidate.confidence, now);
|
|
157
|
+
refreshEvidenceStats(db, assertionId);
|
|
158
|
+
}
|
|
159
|
+
function refreshEvidenceStats(db, assertionId) {
|
|
160
|
+
db.prepare(`UPDATE user_assertions SET
|
|
161
|
+
support_count = (
|
|
162
|
+
SELECT COUNT(*) FROM user_assertion_evidence evidence
|
|
163
|
+
WHERE evidence.assertion_id = user_assertions.assertion_id AND evidence.relation = 'supports'
|
|
164
|
+
),
|
|
165
|
+
independent_source_count = (
|
|
166
|
+
SELECT COUNT(DISTINCT COALESCE(context.source_instance_id, context.source_type || ':' || context.source_ref))
|
|
167
|
+
FROM user_assertion_evidence evidence
|
|
168
|
+
JOIN context_evidence context ON context.evidence_id = evidence.evidence_id
|
|
169
|
+
WHERE evidence.assertion_id = user_assertions.assertion_id AND evidence.relation = 'supports'
|
|
170
|
+
),
|
|
171
|
+
last_supported_at = (
|
|
172
|
+
SELECT MAX(context.observed_at)
|
|
173
|
+
FROM user_assertion_evidence evidence
|
|
174
|
+
JOIN context_evidence context ON context.evidence_id = evidence.evidence_id
|
|
175
|
+
WHERE evidence.assertion_id = user_assertions.assertion_id AND evidence.relation = 'supports'
|
|
176
|
+
)
|
|
177
|
+
WHERE assertion_id = ?`).run(assertionId);
|
|
118
178
|
}
|
|
119
179
|
function closeValidity(db, assertion, boundary, now) {
|
|
120
180
|
if (assertion.validFrom !== void 0 && boundary <= assertion.validFrom) {
|
|
@@ -138,10 +198,15 @@ function authorityRank(authority) {
|
|
|
138
198
|
user_explicit: 3
|
|
139
199
|
}[authority];
|
|
140
200
|
}
|
|
201
|
+
function requiresExplicitSensitiveConsent(candidate) {
|
|
202
|
+
const domain = candidate.domain ?? defaultAssertionDomain(candidate.kind);
|
|
203
|
+
return candidate.sensitivity !== "normal" || Boolean(candidate.sensitivityCategories?.length) || domain === "health";
|
|
204
|
+
}
|
|
141
205
|
function reconcileAssertion(candidate, now = Date.now(), options = {}) {
|
|
142
206
|
validateCandidate(candidate);
|
|
143
207
|
return runSqliteWriteTransaction((db) => {
|
|
144
|
-
if (candidate.authority !== "user_explicit" && candidate
|
|
208
|
+
if (candidate.authority !== "user_explicit" && requiresExplicitSensitiveConsent(candidate)) return { action: "suppressed" };
|
|
209
|
+
assertConsentAllowsCandidate(db, candidate, candidate.domain ?? defaultAssertionDomain(candidate.kind));
|
|
145
210
|
const keys = assertionFingerprints(candidate);
|
|
146
211
|
if (options.restoreDeleted && candidate.authority === "user_explicit") restoreMemory(db, keys);
|
|
147
212
|
if (isMemorySuppressed(db, keys)) return { action: "suppressed" };
|
|
@@ -199,6 +264,16 @@ function reconcileAssertion(candidate, now = Date.now(), options = {}) {
|
|
|
199
264
|
previousAssertion: getUserAssertion(current.id)
|
|
200
265
|
};
|
|
201
266
|
}
|
|
267
|
+
if ((candidate.volatility === "dynamic" || candidate.volatility === "event") && candidate.observedAt > current.observedAt && authorityRank(candidate.authority) >= authorityRank(current.authority)) {
|
|
268
|
+
const assertion = insertAssertion(db, slot.id, candidate, status, now, current.id);
|
|
269
|
+
closeValidity(db, current, candidate.validFrom ?? candidate.observedAt, now);
|
|
270
|
+
updateStatus(db, current, "archived", "Replaced by a newer time-varying observation.", now);
|
|
271
|
+
return {
|
|
272
|
+
action: "superseded",
|
|
273
|
+
assertion,
|
|
274
|
+
previousAssertion: getUserAssertion(current.id)
|
|
275
|
+
};
|
|
276
|
+
}
|
|
202
277
|
const assertion = insertAssertion(db, slot.id, candidate, candidate.authority === "user_explicit" ? "needs_review" : "conflicted", now);
|
|
203
278
|
if (current.authority !== "user_explicit" && candidate.authority !== "user_explicit") updateStatus(db, current, "conflicted", "Overlapping assertion has a different value.", now);
|
|
204
279
|
return {
|
|
@@ -352,10 +427,46 @@ function getUserTimezone() {
|
|
|
352
427
|
}
|
|
353
428
|
function linkAssertionEvidence(assertionId, evidenceId, relation, confidence, now = Date.now()) {
|
|
354
429
|
if (!Number.isFinite(confidence) || confidence < 0 || confidence > 1) throw new Error("Evidence confidence must be between 0 and 1.");
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
430
|
+
runSqliteWriteTransaction((db) => {
|
|
431
|
+
db.prepare(`INSERT INTO user_assertion_evidence (
|
|
432
|
+
assertion_id, evidence_id, relation, confidence, created_at
|
|
433
|
+
) VALUES (?, ?, ?, ?, ?)
|
|
434
|
+
ON CONFLICT(assertion_id, evidence_id, relation) DO UPDATE SET confidence = excluded.confidence`).run(assertionId, evidenceId, relation, confidence, now);
|
|
435
|
+
refreshEvidenceStats(db, assertionId);
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
function mergeAssertionObservation(input, now = Date.now()) {
|
|
439
|
+
validateCandidate(input.candidate);
|
|
440
|
+
return runSqliteWriteTransaction((db) => {
|
|
441
|
+
const current = getUserAssertion(input.assertionId);
|
|
442
|
+
if (!current || current.status === "archived" || current.status === "rejected") throw new Error(`User assertion is not available for merge: ${input.assertionId}`);
|
|
443
|
+
const slot = getAssertionSlot(current.slotId);
|
|
444
|
+
const principalId = input.candidate.principalId ?? "local-owner";
|
|
445
|
+
if (!slot || slot.principalId !== principalId || slot.subject.type !== input.candidate.subject.type || slot.subject.id !== input.candidate.subject.id.trim() || slot.scope.type !== input.candidate.scope.type || (slot.scope.id ?? "") !== (input.candidate.scope.id?.trim() ?? "")) throw new Error("Merge target does not match the candidate subject and scope.");
|
|
446
|
+
if (input.candidate.authority !== "user_explicit" && requiresExplicitSensitiveConsent(input.candidate)) throw new Error("Sensitive inferred understanding cannot be merged automatically.");
|
|
447
|
+
assertConsentAllowsCandidate(db, input.candidate, input.candidate.domain ?? defaultAssertionDomain(input.candidate.kind));
|
|
448
|
+
const observedAt = Math.max(current.observedAt, input.candidate.observedAt);
|
|
449
|
+
const reviewAt = input.candidate.reviewAt ?? defaultReviewAt(current.volatility, observedAt) ?? null;
|
|
450
|
+
let status = current.status;
|
|
451
|
+
let authority = current.authority;
|
|
452
|
+
let confidence = current.confidence;
|
|
453
|
+
if (input.candidate.authority === "user_explicit") {
|
|
454
|
+
authority = "user_explicit";
|
|
455
|
+
confidence = input.candidate.confidence;
|
|
456
|
+
status = initialStatus(input.candidate);
|
|
457
|
+
} else if (current.status === "stale" && (current.validTo === void 0 || current.validTo >= now)) status = "candidate";
|
|
458
|
+
db.prepare(`UPDATE user_assertions
|
|
459
|
+
SET authority = ?, status = ?, confidence = ?, observed_at = ?, review_at = ?
|
|
460
|
+
WHERE assertion_id = ?`).run(authority, status, confidence, observedAt, reviewAt, current.id);
|
|
461
|
+
const insertEvidence = db.prepare(`INSERT INTO user_assertion_evidence (
|
|
462
|
+
assertion_id, evidence_id, relation, confidence, created_at
|
|
463
|
+
) VALUES (?, ?, 'supports', ?, ?)
|
|
464
|
+
ON CONFLICT(assertion_id, evidence_id, relation) DO UPDATE SET confidence = excluded.confidence`);
|
|
465
|
+
for (const evidenceId of new Set(input.evidenceIds)) insertEvidence.run(current.id, evidenceId, input.candidate.confidence, now);
|
|
466
|
+
refreshEvidenceStats(db, current.id);
|
|
467
|
+
if (status !== current.status) recordStatusEvent(db, current.id, current.status, status, "runtime", "Fresh evidence merged into this understanding.", now);
|
|
468
|
+
return getUserAssertion(current.id);
|
|
469
|
+
});
|
|
359
470
|
}
|
|
360
471
|
function setAssertionStatus(assertionId, status, input) {
|
|
361
472
|
const current = getUserAssertion(assertionId);
|
|
@@ -445,4 +556,4 @@ function refreshSupportingObservation(db, current, candidate, now) {
|
|
|
445
556
|
if (current.status === "stale" && (current.validTo === void 0 || current.validTo >= now)) updateStatus(db, current, "candidate", "Fresh source evidence supports this understanding.", now);
|
|
446
557
|
}
|
|
447
558
|
//#endregion
|
|
448
|
-
export { deleteUserAssertion, getActiveAssertionByPredicate, getActiveAssertionForSlot, getAssertionSlot, getUserAssertion, getUserTimezone, linkAssertionEvidence, listSlotAssertions, listUserAssertionSources, listUserAssertions, reconcileAssertion, setAssertionStatus };
|
|
559
|
+
export { deleteUserAssertion, getActiveAssertionByPredicate, getActiveAssertionForSlot, getAssertionSlot, getUserAssertion, getUserTimezone, linkAssertionEvidence, listSlotAssertions, listUserAssertionSources, listUserAssertions, mergeAssertionObservation, reconcileAssertion, setAssertionStatus };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import type { UserAssertion } from './domain.js';
|
|
1
|
+
import type { AssertionAllowedUse, UserAssertion } from './domain.js';
|
|
2
2
|
/** Automatic personalization never grants execution authority. */
|
|
3
3
|
export declare function isWorkingAssumption(assertion: UserAssertion): boolean;
|
|
4
|
-
export declare function canUseAssertion(assertion: UserAssertion, asOf?: number
|
|
4
|
+
export declare function canUseAssertion(assertion: UserAssertion, asOf?: number, context?: {
|
|
5
|
+
use?: AssertionAllowedUse;
|
|
6
|
+
agentId?: string;
|
|
7
|
+
}): boolean;
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
function isWorkingAssumption(assertion) {
|
|
4
4
|
return (assertion.status === "candidate" || assertion.status === "active") && (assertion.authority === "user_observed" || assertion.authority === "system_inferred") && assertion.confidence >= .7 && (assertion.consequence === "low" || assertion.consequence === "medium") && assertion.sensitivity === "normal" && assertion.disclosurePolicy !== "ask_before_reference";
|
|
5
5
|
}
|
|
6
|
-
function canUseAssertion(assertion, asOf = Date.now()) {
|
|
7
|
-
return (assertion.validFrom === void 0 || assertion.validFrom <= asOf) && (assertion.validTo === void 0 || assertion.validTo >= asOf) && (assertion.reviewAt === void 0 || assertion.reviewAt > asOf) && assertion.sensitivity !== "secret" && assertion.sensitivity !== "regulated" && assertion.disclosurePolicy !== "ask_before_reference" && (assertion.status === "active" && assertion.authority === "user_explicit" || isWorkingAssumption(assertion));
|
|
6
|
+
function canUseAssertion(assertion, asOf = Date.now(), context = {}) {
|
|
7
|
+
return (assertion.validFrom === void 0 || assertion.validFrom <= asOf) && (assertion.validTo === void 0 || assertion.validTo >= asOf) && (assertion.deleteAfter === void 0 || assertion.deleteAfter > asOf) && (assertion.reviewAt === void 0 || assertion.reviewAt > asOf) && (!context.use || !assertion.allowedUses || assertion.allowedUses.includes(context.use)) && (!assertion.allowedAgentIds || Boolean(context.agentId && assertion.allowedAgentIds.includes(context.agentId))) && assertion.sensitivity !== "secret" && assertion.sensitivity !== "regulated" && assertion.disclosurePolicy !== "ask_before_reference" && (assertion.status === "active" && assertion.authority === "user_explicit" || isWorkingAssumption(assertion));
|
|
8
8
|
}
|
|
9
9
|
//#endregion
|
|
10
10
|
export { canUseAssertion, isWorkingAssumption };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DecodedPcmAudio } from '
|
|
1
|
+
import { type DecodedPcmAudio } from './wav.js';
|
|
2
2
|
export type AudioFormat = 'wav' | 'webm' | 'ogg' | 'mp3' | 'mp4' | 'unknown';
|
|
3
3
|
export declare class AudioNormalizationError extends Error {
|
|
4
4
|
readonly code = "unsupported_audio_codec";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { UnsupportedWavEncodingError, decodeWavToMonoFloat32 } from "
|
|
1
|
+
import { UnsupportedWavEncodingError, decodeWavToMonoFloat32 } from "./wav.js";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { spawn, spawnSync } from "node:child_process";
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { DEFAULT_LOCAL_VOICE_MODEL_ID } from "./local/models.js";
|
|
2
1
|
//#region src/voice/language-profile.ts
|
|
3
2
|
function resolveVoiceLanguageProfile(language) {
|
|
4
3
|
return language === "zh" ? {
|
|
@@ -39,17 +38,21 @@ function initializeVoiceDefaults(config, language = inferProductLanguageFromEnvi
|
|
|
39
38
|
const audio = config.tools.media.audio;
|
|
40
39
|
config.tools.media.audio = {
|
|
41
40
|
...audio,
|
|
42
|
-
enabled: audio?.enabled ??
|
|
43
|
-
provider: audio?.provider ?? "
|
|
41
|
+
enabled: audio?.enabled ?? false,
|
|
42
|
+
provider: audio?.provider ?? "openai",
|
|
44
43
|
fallback: audio?.fallback ?? {
|
|
45
44
|
enabled: false,
|
|
46
|
-
order: [
|
|
45
|
+
order: []
|
|
47
46
|
},
|
|
48
47
|
providers: {
|
|
49
48
|
...audio?.providers ?? {},
|
|
50
|
-
|
|
51
|
-
model:
|
|
52
|
-
...audio?.providers?.
|
|
49
|
+
alibaba: {
|
|
50
|
+
model: "qwen-audio-3.0-asr-flash",
|
|
51
|
+
...audio?.providers?.alibaba ?? {}
|
|
52
|
+
},
|
|
53
|
+
openai: {
|
|
54
|
+
model: "gpt-4o-mini-transcribe",
|
|
55
|
+
...audio?.providers?.openai ?? {}
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
};
|
|
@@ -74,15 +77,6 @@ function applyAutomaticVoiceLanguage(config, language) {
|
|
|
74
77
|
languageMode: "auto",
|
|
75
78
|
language
|
|
76
79
|
};
|
|
77
|
-
const audio = config.tools?.media?.audio;
|
|
78
|
-
if (audio?.provider === "xopc-local") audio.providers = {
|
|
79
|
-
...audio.providers ?? {},
|
|
80
|
-
"xopc-local": {
|
|
81
|
-
...audio.providers?.["xopc-local"] ?? {},
|
|
82
|
-
model: DEFAULT_LOCAL_VOICE_MODEL_ID,
|
|
83
|
-
language: profile.sttLanguage
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
80
|
const tts = config.messages?.tts;
|
|
87
81
|
if (tts?.provider === "edge") tts.providers = {
|
|
88
82
|
...tts.providers ?? {},
|
|
@@ -16,28 +16,6 @@ const alibabaSttModels = [{
|
|
|
16
16
|
id: "qwen-audio-3.0-asr-flash",
|
|
17
17
|
name: "Qwen Audio 3.0 ASR Flash"
|
|
18
18
|
}];
|
|
19
|
-
const localSttModels = [
|
|
20
|
-
{
|
|
21
|
-
id: "sensevoice-small",
|
|
22
|
-
name: "SenseVoice Small 中文(推荐)",
|
|
23
|
-
description: "约 230 MB · 普通话、粤语、中英混说"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
id: "tiny",
|
|
27
|
-
name: "Whisper Tiny (Fastest)",
|
|
28
|
-
description: "About 45 MB"
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: "base",
|
|
32
|
-
name: "Whisper Base (Multilingual)",
|
|
33
|
-
description: "About 80 MB"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: "small",
|
|
37
|
-
name: "Whisper Small (Higher quality)",
|
|
38
|
-
description: "About 245 MB"
|
|
39
|
-
}
|
|
40
|
-
];
|
|
41
19
|
const alibabaTtsModels = [
|
|
42
20
|
{
|
|
43
21
|
id: "qwen-tts",
|
|
@@ -141,30 +119,6 @@ const edgeVoices = [
|
|
|
141
119
|
}
|
|
142
120
|
];
|
|
143
121
|
const builtinVoiceProviderMetadata = [
|
|
144
|
-
{
|
|
145
|
-
id: "xopc-local",
|
|
146
|
-
capability: "stt",
|
|
147
|
-
displayName: "xopc Local Voice",
|
|
148
|
-
description: "Private on-device Chinese and multilingual transcription. Audio never leaves this device.",
|
|
149
|
-
aliases: ["local"],
|
|
150
|
-
models: localSttModels,
|
|
151
|
-
fields: [{
|
|
152
|
-
key: "model",
|
|
153
|
-
label: "Model",
|
|
154
|
-
type: "select",
|
|
155
|
-
options: localSttModels,
|
|
156
|
-
defaultValue: "sensevoice-small"
|
|
157
|
-
}, {
|
|
158
|
-
key: "language",
|
|
159
|
-
label: "Language hint",
|
|
160
|
-
type: "string",
|
|
161
|
-
placeholder: "zh"
|
|
162
|
-
}],
|
|
163
|
-
diagnostics: {
|
|
164
|
-
requiresApiKey: false,
|
|
165
|
-
configPath: "tools.media.audio.providers.xopc-local"
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
122
|
{
|
|
169
123
|
id: "xopc-cloud",
|
|
170
124
|
capability: "stt",
|
|
@@ -198,6 +198,12 @@ async function openPlatformTts(request) {
|
|
|
198
198
|
highWaterMark: MAX_BUFFERED_BYTES,
|
|
199
199
|
size: (chunk) => chunk.byteLength
|
|
200
200
|
});
|
|
201
|
+
const finishAudio = () => {
|
|
202
|
+
if (ended) return;
|
|
203
|
+
ended = true;
|
|
204
|
+
clearTimeout(timer);
|
|
205
|
+
controller.close();
|
|
206
|
+
};
|
|
201
207
|
const connection = connect(request.baseUrl, request.apiKey, request.signal, (event) => {
|
|
202
208
|
if (event.type === "session.updated" && !ready) {
|
|
203
209
|
if (event.session?.output_sample_rate !== 24e3) throw new Error("Unsupported TTS audio format");
|
|
@@ -212,16 +218,21 @@ async function openPlatformTts(request) {
|
|
|
212
218
|
} else if ((event.type === "response.done" || event.type === "text.flushed") && !finishSent) {
|
|
213
219
|
finishSent = true;
|
|
214
220
|
connection.send({ type: "session.finish" });
|
|
221
|
+
} else if (event.type === "response.audio.done") {
|
|
222
|
+
if (!finishSent) {
|
|
223
|
+
finishSent = true;
|
|
224
|
+
connection.send({ type: "session.finish" });
|
|
225
|
+
}
|
|
226
|
+
finishAudio();
|
|
215
227
|
} else if (event.type === "response.audio.delta") {
|
|
216
228
|
if (!ready || typeof event.delta !== "string" || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(event.delta)) throw new Error("Invalid platform audio");
|
|
217
229
|
const bytes = Buffer.from(event.delta, "base64");
|
|
230
|
+
if (!bytes.length) return;
|
|
218
231
|
if (bytes.length % 2 || bytes.length > MAX_BUFFERED_BYTES) throw new Error("Invalid platform audio");
|
|
219
232
|
controller.enqueue(bytes);
|
|
220
233
|
if ((controller.desiredSize ?? 0) <= 0) connection.pause();
|
|
221
234
|
} else if (event.type === "session.finished") {
|
|
222
|
-
|
|
223
|
-
clearTimeout(timer);
|
|
224
|
-
controller.close();
|
|
235
|
+
finishAudio();
|
|
225
236
|
connection.close();
|
|
226
237
|
}
|
|
227
238
|
}, (error) => {
|
|
@@ -249,10 +260,7 @@ async function openPlatformTts(request) {
|
|
|
249
260
|
release: async () => {
|
|
250
261
|
clearTimeout(timer);
|
|
251
262
|
connection.close();
|
|
252
|
-
|
|
253
|
-
ended = true;
|
|
254
|
-
controller.close();
|
|
255
|
-
}
|
|
263
|
+
finishAudio();
|
|
256
264
|
}
|
|
257
265
|
};
|
|
258
266
|
}
|
|
@@ -12,6 +12,7 @@ init_logger();
|
|
|
12
12
|
const log = createLogger("Voice:Agent");
|
|
13
13
|
const AGENT_TTS_MAX_SEGMENT_CHARACTERS = 180;
|
|
14
14
|
const AGENT_TTS_MIN_SEGMENT_CHARACTERS = 24;
|
|
15
|
+
const PLAYBACK_ECHO_TAIL_MS = 3e3;
|
|
15
16
|
function createAgentVoiceEngine(options) {
|
|
16
17
|
const claim = options.claim;
|
|
17
18
|
const stt = claim.stt;
|
|
@@ -33,6 +34,7 @@ function createAgentVoiceEngine(options) {
|
|
|
33
34
|
let bufferedBytes = 0;
|
|
34
35
|
let finalCount = 0;
|
|
35
36
|
let committing = false;
|
|
37
|
+
let recentPlayback;
|
|
36
38
|
const finalizedUtterances = /* @__PURE__ */ new Set();
|
|
37
39
|
let pendingTurn;
|
|
38
40
|
const turn = new TurnCoordinator(claim.silenceDurationMs, (text, decision, turnId) => {
|
|
@@ -130,6 +132,11 @@ function createAgentVoiceEngine(options) {
|
|
|
130
132
|
if (!phraseMarkedAudible && item.value.byteLength > 0) {
|
|
131
133
|
phraseMarkedAudible = true;
|
|
132
134
|
response.audibleText = `${response.audibleText} ${phrase}`.trim().slice(-8e3);
|
|
135
|
+
recentPlayback = {
|
|
136
|
+
responseId: response.id,
|
|
137
|
+
text: response.audibleText,
|
|
138
|
+
expiresAt: Date.now() + PLAYBACK_ECHO_TAIL_MS
|
|
139
|
+
};
|
|
133
140
|
}
|
|
134
141
|
if (!response.audioStarted) {
|
|
135
142
|
response.audioStarted = true;
|
|
@@ -320,6 +327,11 @@ function createAgentVoiceEngine(options) {
|
|
|
320
327
|
}
|
|
321
328
|
await response.playback.drain(response.abortController.signal);
|
|
322
329
|
if (activeResponse !== response || response.abortController.signal.aborted) return;
|
|
330
|
+
if (response.audioStarted && response.audibleText) recentPlayback = {
|
|
331
|
+
responseId: response.id,
|
|
332
|
+
text: response.audibleText,
|
|
333
|
+
expiresAt: Date.now() + PLAYBACK_ECHO_TAIL_MS
|
|
334
|
+
};
|
|
323
335
|
if (response.audioStarted) send("response.audio.done", { responseId: response.id });
|
|
324
336
|
send("response.done", {
|
|
325
337
|
responseId: response.id,
|
|
@@ -439,13 +451,17 @@ function createAgentVoiceEngine(options) {
|
|
|
439
451
|
}
|
|
440
452
|
finalizedUtterances.add(event.utteranceId);
|
|
441
453
|
finalCount += 1;
|
|
442
|
-
|
|
454
|
+
const playback = activeResponse?.audioStarted ? {
|
|
455
|
+
responseId: activeResponse.id,
|
|
456
|
+
text: activeResponse.audibleText
|
|
457
|
+
} : recentPlayback && recentPlayback.expiresAt >= Date.now() ? recentPlayback : void 0;
|
|
458
|
+
if (claim.request.purpose === "conversation" && playback && isLikelyPlaybackEcho(text, playback.text)) {
|
|
443
459
|
bufferFinal(event.utteranceId, "");
|
|
444
460
|
log.debug({
|
|
445
461
|
sessionId: claim.sessionId,
|
|
446
|
-
responseId:
|
|
462
|
+
responseId: playback.responseId,
|
|
447
463
|
transcriptCharacters: text.length
|
|
448
|
-
}, "Ignored finalized transcription matching
|
|
464
|
+
}, "Ignored finalized transcription matching recent voice playback");
|
|
449
465
|
return;
|
|
450
466
|
}
|
|
451
467
|
send("input.transcript.final", {
|
|
@@ -4,7 +4,8 @@ const PCM_24KHZ_20MS_BYTES = 960;
|
|
|
4
4
|
var PcmFrameBuffer = class {
|
|
5
5
|
remainder = new Uint8Array();
|
|
6
6
|
push(bytes) {
|
|
7
|
-
if (!bytes.byteLength
|
|
7
|
+
if (!bytes.byteLength) return [];
|
|
8
|
+
if (bytes.byteLength % 2) throw new Error("PCM16 audio must contain complete samples");
|
|
8
9
|
const pending = new Uint8Array(this.remainder.byteLength + bytes.byteLength);
|
|
9
10
|
pending.set(this.remainder);
|
|
10
11
|
pending.set(bytes, this.remainder.byteLength);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { init_agent_scope, resolveAgentProfileDir } from "../../agent/agent-scope.js";
|
|
2
|
-
import { DEFAULT_IDENTITY_FILENAME, DEFAULT_SOUL_FILENAME } from "../../agent/context/workspace.js";
|
|
3
2
|
import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
|
|
3
|
+
import { DEFAULT_IDENTITY_FILENAME, DEFAULT_SOUL_FILENAME } from "../../agent/context/workspace.js";
|
|
4
4
|
import { loadProfileBootstrapFiles } from "../../agent/bootstrap/load-bootstrap-files.js";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { statSync } from "node:fs";
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
function normalizeSpeech(text) {
|
|
3
3
|
return text.toLocaleLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}]/gu, "");
|
|
4
4
|
}
|
|
5
|
+
function closestSubstringEditDistance(pattern, text) {
|
|
6
|
+
const needle = Array.from(pattern);
|
|
7
|
+
const haystack = Array.from(text);
|
|
8
|
+
let previous = new Uint16Array(haystack.length + 1);
|
|
9
|
+
for (let index = 0; index <= haystack.length; index += 1) previous[index] = 0;
|
|
10
|
+
for (let row = 1; row <= needle.length; row += 1) {
|
|
11
|
+
const current = new Uint16Array(haystack.length + 1);
|
|
12
|
+
current[0] = row;
|
|
13
|
+
for (let column = 1; column <= haystack.length; column += 1) current[column] = Math.min(previous[column] + 1, current[column - 1] + 1, previous[column - 1] + (needle[row - 1] === haystack[column - 1] ? 0 : 1));
|
|
14
|
+
previous = current;
|
|
15
|
+
}
|
|
16
|
+
return Math.min(...previous);
|
|
17
|
+
}
|
|
5
18
|
/** Conservatively identifies finalized ASR that is already in audible assistant output. */
|
|
6
19
|
function isLikelyPlaybackEcho(transcript, assistantText) {
|
|
7
20
|
const heard = normalizeSpeech(transcript);
|
|
@@ -9,7 +22,9 @@ function isLikelyPlaybackEcho(transcript, assistantText) {
|
|
|
9
22
|
if (!heard || !spoken) return false;
|
|
10
23
|
const containsCjk = /\p{Script=Han}/u.test(heard);
|
|
11
24
|
if (heard.length < (containsCjk ? 3 : 6)) return false;
|
|
12
|
-
|
|
25
|
+
if (spoken.includes(heard)) return true;
|
|
26
|
+
if (heard.length < (containsCjk ? 6 : 10)) return false;
|
|
27
|
+
return closestSubstringEditDistance(heard, spoken) / Array.from(heard).length <= .22;
|
|
13
28
|
}
|
|
14
29
|
//#endregion
|
|
15
30
|
export { isLikelyPlaybackEcho };
|
|
@@ -12,5 +12,4 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export { openAiTranscriptionProvider } from './openai-transcription.js';
|
|
14
14
|
export { alibabaTranscriptionProvider } from './alibaba-transcription.js';
|
|
15
|
-
export { localTranscriptionProvider } from './local-transcription.js';
|
|
16
15
|
export { xopcCloudTranscriptionProvider } from './xopc-cloud-transcription.js';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { openAiTranscriptionProvider } from "./openai-transcription.js";
|
|
2
2
|
import { alibabaTranscriptionProvider } from "./alibaba-transcription.js";
|
|
3
|
-
import { localTranscriptionProvider } from "./local-transcription.js";
|
|
4
3
|
import { xopcCloudTranscriptionProvider } from "./xopc-cloud-transcription.js";
|
|
5
|
-
export { alibabaTranscriptionProvider,
|
|
4
|
+
export { alibabaTranscriptionProvider, openAiTranscriptionProvider, xopcCloudTranscriptionProvider };
|