@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.
Files changed (385) hide show
  1. package/README.md +4 -3
  2. package/README.zh-CN.md +4 -3
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CxfXpPWs.js → agent-avatar-dicebear-BDG0hI-J.js} +1 -1
  6. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-ArM6Sm9S.js +1 -0
  7. package/dist/gateway/static/root/assets/agent-plugin-dialog-BX_Bhre1.js +1 -0
  8. package/dist/gateway/static/root/assets/agents-BiQqpMw0.js +70 -0
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-p7fZB4dT.js → app-management-settings-panel-DgttzUCG.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-C-clVcfp.js → appearance-settings-CHpyWV8Z.js} +1 -1
  11. package/dist/gateway/static/root/assets/apps-page-BhfYQcm8.js +1 -0
  12. package/dist/gateway/static/root/assets/{archive-plugin-Xm6xChUX.js → archive-plugin-B7Q7Oeo7.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-Di8kuG4L.js → attachment-load-BYwqQ8qN.js} +1 -1
  14. package/dist/gateway/static/root/assets/{automations-page-GUZgDhKj.js → automations-page-CsvAtTNd.js} +1 -1
  15. package/dist/gateway/static/root/assets/automations-workspace-DMH_1Ped.js +7 -0
  16. package/dist/gateway/static/root/assets/{binary-plugins-OCrDjC9O.js → binary-plugins-DdgWCI-M.js} +1 -1
  17. package/dist/gateway/static/root/assets/{block-editor-m9tqvu7x.js → block-editor-DyOagNnn.js} +3 -3
  18. package/dist/gateway/static/root/assets/{browser-automation-inputs-DSWXq9lI.js → browser-automation-inputs-CwF8OQFN.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-automations-page-DuOaridE.js → browser-automations-page-D_EQjiiu.js} +2 -2
  20. package/dist/gateway/static/root/assets/browser-settings-page-BE6691Jz.js +3 -0
  21. package/dist/gateway/static/root/assets/capabilities-page-MweWNrC1.js +2 -0
  22. package/dist/gateway/static/root/assets/capabilities-settings-panel-CdSWkh89.js +8 -0
  23. package/dist/gateway/static/root/assets/capability-header-actions-C5F2GNE9.js +1 -0
  24. package/dist/gateway/static/root/assets/capability-icon-BYm2-nS-.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-NGfwR3He.js +1 -0
  26. package/dist/gateway/static/root/assets/{chat-terminal-dock-BfnVh8oo.js → chat-terminal-dock-C6tl9Rfw.js} +2 -2
  27. package/dist/gateway/static/root/assets/computer-settings-page-C0MsVw4l.js +1 -0
  28. package/dist/gateway/static/root/assets/connector-service-page-DsF60pPs.js +1 -0
  29. package/dist/gateway/static/root/assets/connectors-page-BE8NdQcR.js +2 -0
  30. package/dist/gateway/static/root/assets/{date-picker-CtDyij_x.js → date-picker-CELKKqYN.js} +1 -1
  31. package/dist/gateway/static/root/assets/dependency-picker-BcEwCnI5.js +1 -0
  32. package/dist/gateway/static/root/assets/{desktop-pet-BsIYCAkG.js → desktop-pet-Ww7Gm8-x.js} +1 -1
  33. package/dist/gateway/static/root/assets/desktop-pet-settings-D-dbAxGu.js +1 -0
  34. package/dist/gateway/static/root/assets/device-pairing-wizard-DsYY6szg.js +1 -0
  35. package/dist/gateway/static/root/assets/directory-picker-path-field-CVmuCRyO.js +1 -0
  36. package/dist/gateway/static/root/assets/ellipsis-0k4rZLoy.js +1 -0
  37. package/dist/gateway/static/root/assets/{extension-debug-page-Ct9pABNW.js → extension-debug-page-UUHNJj-d.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-page-BktsR4hj.js → extension-page-BvL452mX.js} +1 -1
  39. package/dist/gateway/static/root/assets/{extension-settings-page-BQJc-vXH.js → extension-settings-page-CrNnUSOs.js} +1 -1
  40. package/dist/gateway/static/root/assets/external-link-DjqjBmc3.js +1 -0
  41. package/dist/gateway/static/root/assets/eye-CABVeTq0.js +1 -0
  42. package/dist/gateway/static/root/assets/folder-open-CyzJ19I9.js +1 -0
  43. package/dist/gateway/static/root/assets/{gateway-config-swr-CoQVulMd.js → gateway-config-swr-DMm1vU51.js} +1 -1
  44. package/dist/gateway/static/root/assets/gateway-settings-DrHhtZqv.js +1 -0
  45. package/dist/gateway/static/root/assets/{gateway-startup-retry-B5GJ-CQV.js → gateway-startup-retry-Ck6tj6yE.js} +1 -1
  46. package/dist/gateway/static/root/assets/globe-DSSGFWFn.js +1 -0
  47. package/dist/gateway/static/root/assets/home-page-YgI6jfGA.js +1 -0
  48. package/dist/gateway/static/root/assets/{image-generation-api-DvWDkbk1.js → image-generation-api-BOh6j0BF.js} +1 -1
  49. package/dist/gateway/static/root/assets/imports-page-BuqdzA7h.js +1 -0
  50. package/dist/gateway/static/root/assets/index-DJmO2VAY.css +1 -0
  51. package/dist/gateway/static/root/assets/index-vCIBfJp7.js +121 -0
  52. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-ctJLm8TP.js → keyboard-shortcuts-settings-D9L7IdUg.js} +1 -1
  53. package/dist/gateway/static/root/assets/link-2-D_ZKYUW7.js +1 -0
  54. package/dist/gateway/static/root/assets/loader-circle-CifKLtgG.js +1 -0
  55. package/dist/gateway/static/root/assets/local-app-workbench-page-DO8uUtos.js +1 -0
  56. package/dist/gateway/static/root/assets/{local-apps-page-BxC_LTqq.js → local-apps-page-BEvyufm7.js} +1 -1
  57. package/dist/gateway/static/root/assets/locale-store-DAOwT3Zp.js +1 -0
  58. package/dist/gateway/static/root/assets/logs-page-Jev1m9sS.js +2 -0
  59. package/dist/gateway/static/root/assets/management-settings-41i7B1RO.js +1 -0
  60. package/dist/gateway/static/root/assets/{markdown-view-Dft8ASFD.js → markdown-view-nL4xzvI8.js} +2 -2
  61. package/dist/gateway/static/root/assets/{media-plugins-ni5zJ4Ok.js → media-plugins-dHbcqMan.js} +1 -1
  62. package/dist/gateway/static/root/assets/message-square-plus-XP0tGdlV.js +1 -0
  63. package/dist/gateway/static/root/assets/messages-BZbt9x1y.js +3 -0
  64. package/dist/gateway/static/root/assets/minimize-2-DtOGrlpo.js +1 -0
  65. package/dist/gateway/static/root/assets/note-detail-panel-DonP0E6Q.js +5 -0
  66. package/dist/gateway/static/root/assets/note-image-lightbox-1qg2v-9j.js +1 -0
  67. package/dist/gateway/static/root/assets/notes-page-CYHMeVKo.js +8 -0
  68. package/dist/gateway/static/root/assets/page-context-capture-button-BKsMcPOy.js +1 -0
  69. package/dist/gateway/static/root/assets/pencil-DmIY3Oa-.js +1 -0
  70. package/dist/gateway/static/root/assets/preview-open-alternatives-Du18QgWc.js +1 -0
  71. package/dist/gateway/static/root/assets/{product-open-page-DQctU8z3.js → product-open-page-IY1QL6s0.js} +1 -1
  72. package/dist/gateway/static/root/assets/project-detail-page-Bpw9mxfV.js +1 -0
  73. package/dist/gateway/static/root/assets/projects-page-BdYbDNUn.js +1 -0
  74. package/dist/gateway/static/root/assets/{registry-api-DWWO6ajd.js → registry-api-DCFXWBOt.js} +1 -1
  75. package/dist/gateway/static/root/assets/remote-access-hub-CLhbz3TF.js +1 -0
  76. package/dist/gateway/static/root/assets/rotate-cw-LIg3Am9S.js +1 -0
  77. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-xhOSYfiX.js → runtime-tools-settings-panel-CuTFmXyj.js} +2 -2
  78. package/dist/gateway/static/root/assets/scenes-page-XwK2IEmr.js +2 -0
  79. package/dist/gateway/static/root/assets/{schema-form-z8IeSdBp.js → schema-form-qWQii8IU.js} +1 -1
  80. package/dist/gateway/static/root/assets/search-DA7gz22f.js +1 -0
  81. package/dist/gateway/static/root/assets/sessions-page-4-QoiDES.js +1 -0
  82. package/dist/gateway/static/root/assets/settings-advanced-gate-BggQVM1y.js +1 -0
  83. package/dist/gateway/static/root/assets/settings-form-section-B0ZBr0L9.js +1 -0
  84. package/dist/gateway/static/root/assets/{settings-page-Br9no5e4.js → settings-page-DpII4NO3.js} +1 -1
  85. package/dist/gateway/static/root/assets/settings-page-layout-X1x-2Cp9.js +1 -0
  86. package/dist/gateway/static/root/assets/setup-status-panel-HPpC7EE0.js +1 -0
  87. package/dist/gateway/static/root/assets/{share-preview-page-CE0SER59.js → share-preview-page-B2CGYZHc.js} +1 -1
  88. package/dist/gateway/static/root/assets/shares-settings-DhVCRYGP.js +1 -0
  89. package/dist/gateway/static/root/assets/skill-api-_ddww47C.js +1 -0
  90. package/dist/gateway/static/root/assets/skill-reload-api-XPZkWJJe.js +1 -0
  91. package/dist/gateway/static/root/assets/skills-page-uF7DkJMC.js +2 -0
  92. package/dist/gateway/static/root/assets/system-settings-panel-25ABVt7H.js +1 -0
  93. package/dist/gateway/static/root/assets/task-detail-page-gepxhO4j.js +1 -0
  94. package/dist/gateway/static/root/assets/tunnel-api-CwQGBI_4.js +1 -0
  95. package/dist/gateway/static/root/assets/use-autosave-CL3wytbs.js +1 -0
  96. package/dist/gateway/static/root/assets/user-model-page-DldQW9Wh.js +2 -0
  97. package/dist/gateway/static/root/assets/{voice-api-key-field-By6Lgbse.js → voice-api-key-field-zjAzQrx4.js} +1 -1
  98. package/dist/gateway/static/root/assets/voice-config-api-DvzQ-128.js +1 -0
  99. package/dist/gateway/static/root/assets/{work-discovery-overlay-DdhgIlyf.js → work-discovery-overlay-MaPPjWwl.js} +1 -1
  100. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BOJYQaxX.js → workflow-run-setup-panel-C3dQN1fE.js} +2 -2
  101. package/dist/gateway/static/root/assets/workflows-page-B9lnTU3U.js +6 -0
  102. package/dist/gateway/static/root/connector-icons/SOURCES.md +1 -0
  103. package/dist/gateway/static/root/connector-icons/wecom.svg +9 -0
  104. package/dist/gateway/static/root/index.html +20 -8
  105. package/dist/package.js +1 -1
  106. package/dist/src/agent/agent-instance-gateway.d.ts +2 -2
  107. package/dist/src/agent/agent-manager.d.ts +5 -2
  108. package/dist/src/agent/agent-manager.js +77 -23
  109. package/dist/src/agent/background-review/coordinator.d.ts +2 -7
  110. package/dist/src/agent/background-review/coordinator.js +17 -34
  111. package/dist/src/agent/background-review/prompts.d.ts +13 -5
  112. package/dist/src/agent/background-review/prompts.js +17 -12
  113. package/dist/src/agent/background-review/run-background-review.d.ts +3 -3
  114. package/dist/src/agent/background-review/run-background-review.js +59 -44
  115. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +1 -1
  116. package/dist/src/agent/capabilities/definitions.d.ts +3 -2
  117. package/dist/src/agent/capabilities/definitions.js +3 -2
  118. package/dist/src/agent/context/execution-context.js +5 -2
  119. package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
  120. package/dist/src/agent/image/tool-model-config.js +1 -1
  121. package/dist/src/agent/mcp/index.js +1 -1
  122. package/dist/src/agent/mcp/mcp-transport.js +2 -2
  123. package/dist/src/agent/mcp/oauth/index.js +1 -1
  124. package/dist/src/agent/mcp/oauth/mcp-oauth-manager.js +2 -2
  125. package/dist/src/agent/mcp/oauth/mcp-oauth-provider.js +1 -1
  126. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
  127. package/dist/src/agent/orchestration/llm-turn-retry.js +2 -15
  128. package/dist/src/agent/prompt/sections/tooling.js +3 -0
  129. package/dist/src/agent/service/direct-turn-helpers.js +1 -1
  130. package/dist/src/agent/service.d.ts +1 -0
  131. package/dist/src/agent/service.js +5 -2
  132. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +12 -0
  133. package/dist/src/agent/tasks/task-judge-service.js +1 -1
  134. package/dist/src/agent/tools/factory.js +3 -2
  135. package/dist/src/agent/tools/index.d.ts +1 -0
  136. package/dist/src/agent/tools/index.js +2 -1
  137. package/dist/src/agent/tools/user-context-tool.js +29 -4
  138. package/dist/src/agent/tools/workflow-manage-tool.d.ts +2 -0
  139. package/dist/src/agent/tools/workflow-manage-tool.js +225 -0
  140. package/dist/src/agent/tools/xopc-use-tool.js +1 -1
  141. package/dist/src/agent-catalog/capabilities.js +2 -2
  142. package/dist/src/auth/credentials.js +1 -1
  143. package/dist/src/auth/oauth-provider-lock.js +1 -1
  144. package/dist/src/auth/sync-provider-auth.js +1 -1
  145. package/dist/src/automations/capabilities/drafts.js +1 -1
  146. package/dist/src/automations/domain/types.d.ts +7 -1
  147. package/dist/src/automations/draft/automation-draft-service.js +13 -4
  148. package/dist/src/automations/service/action-executor.d.ts +2 -2
  149. package/dist/src/automations/service/action-executor.js +36 -13
  150. package/dist/src/automations/service/automation-service.js +2 -1
  151. package/dist/src/bootstrap/application-state.js +1 -1
  152. package/dist/src/browser/automations/index.js +2 -2
  153. package/dist/src/browser/automations/service.d.ts +11 -2
  154. package/dist/src/browser/automations/service.js +19 -5
  155. package/dist/src/capabilities/readiness/from-config.d.ts +0 -1
  156. package/dist/src/capabilities/readiness/from-config.js +2 -4
  157. package/dist/src/capabilities/runtime/dispatcher.js +1 -1
  158. package/dist/src/capabilities/runtime/product.js +1 -1
  159. package/dist/src/chat-commands/agent-edit.js +1 -1
  160. package/dist/src/chat-commands/builtins/config.js +1 -1
  161. package/dist/src/chat-previews/service.js +1 -2
  162. package/dist/src/cli/commands/agent.js +1 -1
  163. package/dist/src/cli/commands/agents.js +1 -1
  164. package/dist/src/cli/commands/auth.js +1 -1
  165. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  166. package/dist/src/cli/commands/extension-agent-plugin.js +2 -1
  167. package/dist/src/cli/commands/models.js +1 -1
  168. package/dist/src/cli/commands/onboard/model.js +3 -3
  169. package/dist/src/cli/commands/providers.js +1 -1
  170. package/dist/src/cli/utils/init-workspace-core.js +1 -1
  171. package/dist/src/config/index.js +4 -4
  172. package/dist/src/config/loader.js +2 -2
  173. package/dist/src/config/models-json.js +1 -1
  174. package/dist/src/config/schema.js +5 -5
  175. package/dist/src/connectors/china-catalog.js +5 -1
  176. package/dist/src/connectors/connected-source-ingestion.js +6 -1
  177. package/dist/src/connectors/connected-source-observations.d.ts +10 -0
  178. package/dist/src/connectors/connected-source-observations.js +80 -0
  179. package/dist/src/connectors/connected-source-understanding.js +198 -8
  180. package/dist/src/connectors/learning-coordinator.js +63 -26
  181. package/dist/src/connectors/learning-recipes.js +19 -2
  182. package/dist/src/discussions/audio-repair.d.ts +1 -1
  183. package/dist/src/discussions/live-worker.js +1 -3
  184. package/dist/src/discussions/recording.js +2 -2
  185. package/dist/src/discussions/sealer.js +2 -2
  186. package/dist/src/extensions/agent-plugins/auth.d.ts +2 -2
  187. package/dist/src/extensions/agent-plugins/auth.js +6 -35
  188. package/dist/src/extensions/agent-plugins/credentials.d.ts +2 -0
  189. package/dist/src/extensions/agent-plugins/credentials.js +37 -0
  190. package/dist/src/extensions/agent-plugins/plugin-oauth-scope.d.ts +1 -0
  191. package/dist/src/extensions/agent-plugins/plugin-oauth-scope.js +8 -0
  192. package/dist/src/extensions/agent-plugins/validation.js +1 -1
  193. package/dist/src/extensions/bundled-extension-activation.d.ts +3 -1
  194. package/dist/src/extensions/bundled-extension-activation.js +5 -8
  195. package/dist/src/extensions/marketplace.d.ts +4 -0
  196. package/dist/src/extensions/marketplace.js +4 -0
  197. package/dist/src/gateway/agents-admin.js +2 -2
  198. package/dist/src/gateway/file-path-classifier.js +1 -1
  199. package/dist/src/gateway/file-space-service.d.ts +9 -2
  200. package/dist/src/gateway/gateway-workflow-host.types.d.ts +1 -0
  201. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  202. package/dist/src/gateway/hono/routes/agent-plugins.js +2 -1
  203. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +27 -5
  204. package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -2
  205. package/dist/src/gateway/hono/routes/config.js +0 -3
  206. package/dist/src/gateway/hono/routes/connectors.js +3 -10
  207. package/dist/src/gateway/hono/routes/context-sources.d.ts +0 -1
  208. package/dist/src/gateway/hono/routes/context-sources.js +12 -15
  209. package/dist/src/gateway/hono/routes/notes.js +2 -2
  210. package/dist/src/gateway/hono/routes/projects.js +2 -2
  211. package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
  212. package/dist/src/gateway/hono/routes/status.js +0 -1
  213. package/dist/src/gateway/hono/routes/tasks.js +1 -1
  214. package/dist/src/gateway/hono/routes/user-model.js +21 -3
  215. package/dist/src/gateway/hono/routes/voice.js +0 -67
  216. package/dist/src/gateway/hono/routes/workflows.js +1 -23
  217. package/dist/src/gateway/image-generation-setup.js +2 -2
  218. package/dist/src/gateway/lock.js +1 -1
  219. package/dist/src/gateway/service/config-coordinator.d.ts +4 -4
  220. package/dist/src/gateway/service/config-coordinator.js +6 -6
  221. package/dist/src/gateway/service/marketplace-service.js +8 -6
  222. package/dist/src/gateway/service.d.ts +1 -1
  223. package/dist/src/gateway/service.js +20 -18
  224. package/dist/src/gateway/xopc-cloud-capability-setup.js +1 -1
  225. package/dist/src/home-intelligence/generator.js +7 -6
  226. package/dist/src/home-intelligence/host.js +1 -1
  227. package/dist/src/local-apps/service.js +1 -1
  228. package/dist/src/media-understanding/types.d.ts +1 -1
  229. package/dist/src/memory-maintenance/service.d.ts +1 -0
  230. package/dist/src/memory-maintenance/service.js +13 -0
  231. package/dist/src/migrations/retired-local-stt.d.ts +2 -0
  232. package/dist/src/migrations/retired-local-stt.js +52 -0
  233. package/dist/src/migrations/runner.js +2 -1
  234. package/dist/src/providers/model-catalog-persistence.js +1 -1
  235. package/dist/src/providers/model-response.d.ts +2 -0
  236. package/dist/src/providers/model-response.js +24 -1
  237. package/dist/src/session/turn-outcome-projector.js +1 -1
  238. package/dist/src/storage/sqlite/connection.js +1 -0
  239. package/dist/src/storage/sqlite/migrations/207_user_model_policy_contract.sql +121 -0
  240. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  241. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  242. package/dist/src/storage/sqlite/schema.js +1 -1
  243. package/dist/src/storage/sqlite/sql-assets.d.ts +1 -0
  244. package/dist/src/storage/sqlite/sql-assets.js +7 -4
  245. package/dist/src/tasks/capabilities/read.js +2 -2
  246. package/dist/src/tasks/index.js +2 -2
  247. package/dist/src/tasks/task-application-service.d.ts +1 -0
  248. package/dist/src/tasks/task-application-service.js +4 -2
  249. package/dist/src/tasks/task-context-assembler.js +10 -1
  250. package/dist/src/tasks/task-run-dispatcher.d.ts +1 -0
  251. package/dist/src/tasks/task-run-dispatcher.js +15 -2
  252. package/dist/src/tui/backends/embedded-backend.js +6 -3
  253. package/dist/src/tui/tui-commands.js +2 -2
  254. package/dist/src/tui/tui-startup-resources.js +1 -1
  255. package/dist/src/tui/tui.js +3 -3
  256. package/dist/src/user-context/sources/consent-repository.d.ts +7 -0
  257. package/dist/src/user-context/sources/consent-repository.js +81 -0
  258. package/dist/src/user-context/sources/index.d.ts +1 -0
  259. package/dist/src/user-context/sources/index.js +2 -1
  260. package/dist/src/user-context/sources/repository.js +73 -1
  261. package/dist/src/user-context/sources/types.d.ts +16 -0
  262. package/dist/src/user-model/action-rule-suggestions.d.ts +11 -0
  263. package/dist/src/user-model/action-rule-suggestions.js +29 -0
  264. package/dist/src/user-model/bootstrap.js +1 -1
  265. package/dist/src/user-model/capture/executor.js +83 -7
  266. package/dist/src/user-model/capture/semantic.d.ts +5 -2
  267. package/dist/src/user-model/capture/semantic.js +27 -11
  268. package/dist/src/user-model/domain.d.ts +26 -0
  269. package/dist/src/user-model/domain.js +40 -2
  270. package/dist/src/user-model/index.d.ts +2 -0
  271. package/dist/src/user-model/index.js +6 -4
  272. package/dist/src/user-model/maintenance-policy.d.ts +1 -0
  273. package/dist/src/user-model/maintenance-policy.js +13 -0
  274. package/dist/src/user-model/observation-repository.d.ts +48 -0
  275. package/dist/src/user-model/observation-repository.js +100 -0
  276. package/dist/src/user-model/repository.d.ts +5 -0
  277. package/dist/src/user-model/repository.js +121 -10
  278. package/dist/src/user-model/usage-policy.d.ts +5 -2
  279. package/dist/src/user-model/usage-policy.js +2 -2
  280. package/dist/src/voice/audio/normalize.d.ts +1 -1
  281. package/dist/src/voice/audio/normalize.js +1 -1
  282. package/dist/src/voice/{local → audio}/wav.js +1 -1
  283. package/dist/src/voice/language-profile.js +10 -16
  284. package/dist/src/voice/metadata/builtin.js +0 -46
  285. package/dist/src/voice/platform-streams.js +15 -7
  286. package/dist/src/voice/realtime/agentEngine.js +19 -3
  287. package/dist/src/voice/realtime/pcmFrameBuffer.js +2 -1
  288. package/dist/src/voice/realtime/persona-context.js +1 -1
  289. package/dist/src/voice/realtime/playback-echo.js +16 -1
  290. package/dist/src/voice/stt/providers/index.d.ts +0 -1
  291. package/dist/src/voice/stt/providers/index.js +1 -2
  292. package/dist/src/voice/stt/types.js +3 -4
  293. package/dist/src/voice/tts/merge-config.js +1 -1
  294. package/dist/src/voice/tts/speech-registry.d.ts +1 -1
  295. package/dist/src/voice/tts/types.d.ts +1 -1
  296. package/dist/src/work-discovery/analyzer.js +6 -5
  297. package/dist/src/work-discovery/service.js +2 -2
  298. package/dist/src/work-discovery/types.d.ts +1 -1
  299. package/dist/src/workflows/authoring/index.d.ts +1 -0
  300. package/dist/src/workflows/authoring/index.js +2 -1
  301. package/dist/src/workflows/authoring/workflow-draft-defaults.d.ts +3 -0
  302. package/dist/src/workflows/authoring/workflow-draft-defaults.js +63 -0
  303. package/dist/src/workflows/context/workflow-context.js +5 -1
  304. package/dist/src/workflows/domain/index.js +1 -1
  305. package/dist/src/workflows/engine/workflow-engine.js +1 -1
  306. package/dist/src/workflows/index.js +4 -4
  307. package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
  308. package/dist/src/workflows/service/workflow-run-service.js +39 -7
  309. package/dist/src/workflows/service/workflow-session-bridge.js +2 -2
  310. package/package.json +12 -16
  311. package/skills/engineering/workflow-authoring/SKILL.md +32 -0
  312. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CDHe8gJf.js +0 -1
  313. package/dist/gateway/static/root/assets/agent-plugin-dialog-DMv-udoZ.js +0 -1
  314. package/dist/gateway/static/root/assets/agents-D_xOAXgj.js +0 -1
  315. package/dist/gateway/static/root/assets/apps-page-Dz2g7eAN.js +0 -1
  316. package/dist/gateway/static/root/assets/automations-workspace-BUZhG9aJ.js +0 -7
  317. package/dist/gateway/static/root/assets/browser-settings-page-D2_PgHep.js +0 -3
  318. package/dist/gateway/static/root/assets/capabilities-settings-panel-7Y_pJqyt.js +0 -8
  319. package/dist/gateway/static/root/assets/channels-settings-B-Igy1ro.js +0 -1
  320. package/dist/gateway/static/root/assets/computer-settings-page-aRG2lU4w.js +0 -1
  321. package/dist/gateway/static/root/assets/connector-service-page-B5EhnfJH.js +0 -1
  322. package/dist/gateway/static/root/assets/connectors-page-7HfRt1LW.js +0 -2
  323. package/dist/gateway/static/root/assets/dependency-picker-z6ouWxmz.js +0 -1
  324. package/dist/gateway/static/root/assets/desktop-pet-settings-z-0aQ5ct.js +0 -1
  325. package/dist/gateway/static/root/assets/device-pairing-wizard-DlmhQvY5.js +0 -1
  326. package/dist/gateway/static/root/assets/gateway-settings-BfDVlvy6.js +0 -1
  327. package/dist/gateway/static/root/assets/home-page-CI_eQTPL.js +0 -1
  328. package/dist/gateway/static/root/assets/imports-page-DFpQfHVU.js +0 -1
  329. package/dist/gateway/static/root/assets/index-19rMUT3d.js +0 -121
  330. package/dist/gateway/static/root/assets/index-BKL5tg2f.css +0 -1
  331. package/dist/gateway/static/root/assets/local-app-workbench-page-C9kaP3Dy.js +0 -1
  332. package/dist/gateway/static/root/assets/locale-store-BPZR8x9b.js +0 -1
  333. package/dist/gateway/static/root/assets/logs-page-Ok5SpG-G.js +0 -2
  334. package/dist/gateway/static/root/assets/management-settings-aOzRaQHM.js +0 -1
  335. package/dist/gateway/static/root/assets/messages-kFWhF6_t.js +0 -3
  336. package/dist/gateway/static/root/assets/note-detail-panel-C9OEltN9.js +0 -5
  337. package/dist/gateway/static/root/assets/notes-page-Dj9rMgdi.js +0 -8
  338. package/dist/gateway/static/root/assets/page-context-capture-button-BJA3d8vU.js +0 -1
  339. package/dist/gateway/static/root/assets/page-tabs-Dyc3wKkl.js +0 -1
  340. package/dist/gateway/static/root/assets/preview-open-alternatives-tIOIQbNX.js +0 -1
  341. package/dist/gateway/static/root/assets/project-detail-page-Dy-EwZcc.js +0 -1
  342. package/dist/gateway/static/root/assets/projects-page-JaGKa6rM.js +0 -1
  343. package/dist/gateway/static/root/assets/remote-access-hub-Cb8-nd60.js +0 -1
  344. package/dist/gateway/static/root/assets/scenes-page-ClBkFdRY.js +0 -2
  345. package/dist/gateway/static/root/assets/sessions-page-BYW5l_nY.js +0 -1
  346. package/dist/gateway/static/root/assets/settings-advanced-gate-CDNwmXuH.js +0 -1
  347. package/dist/gateway/static/root/assets/settings-form-section-BXTJAser.js +0 -1
  348. package/dist/gateway/static/root/assets/settings-page-layout-D6745w0p.js +0 -1
  349. package/dist/gateway/static/root/assets/setup-status-panel-D2N9764S.js +0 -1
  350. package/dist/gateway/static/root/assets/shares-settings-Dk3_QOKQ.js +0 -1
  351. package/dist/gateway/static/root/assets/skill-reload-api-CPt61fEv.js +0 -1
  352. package/dist/gateway/static/root/assets/skills-page-Db6PB2C6.js +0 -2
  353. package/dist/gateway/static/root/assets/skills-page.utils-DrtW5FBy.js +0 -1
  354. package/dist/gateway/static/root/assets/system-settings-panel-CuY1Zh5s.js +0 -1
  355. package/dist/gateway/static/root/assets/task-detail-page-o7RiDUMi.js +0 -1
  356. package/dist/gateway/static/root/assets/tunnel-api-PGHDgvWb.js +0 -1
  357. package/dist/gateway/static/root/assets/use-autosave-B55oBQUt.js +0 -1
  358. package/dist/gateway/static/root/assets/user-model-page-DspelwAa.js +0 -2
  359. package/dist/gateway/static/root/assets/voice-config-api-BaxITrwZ.js +0 -1
  360. package/dist/gateway/static/root/assets/workflows-page-6ObD0IQZ.js +0 -6
  361. package/dist/src/voice/local/model-files.d.ts +0 -14
  362. package/dist/src/voice/local/model-files.js +0 -92
  363. package/dist/src/voice/local/model-manager.d.ts +0 -18
  364. package/dist/src/voice/local/model-manager.js +0 -133
  365. package/dist/src/voice/local/models.d.ts +0 -28
  366. package/dist/src/voice/local/models.js +0 -99
  367. package/dist/src/voice/local/provider-switch.d.ts +0 -4
  368. package/dist/src/voice/local/provider-switch.js +0 -36
  369. package/dist/src/voice/local/runtime-client.d.ts +0 -28
  370. package/dist/src/voice/local/runtime-client.js +0 -183
  371. package/dist/src/voice/local/runtime-worker.d.ts +0 -1
  372. package/dist/src/voice/local/runtime-worker.js +0 -271
  373. package/dist/src/voice/stt/providers/local-transcription.d.ts +0 -2
  374. package/dist/src/voice/stt/providers/local-transcription.js +0 -53
  375. package/dist/src/workflows/draft/index.d.ts +0 -3
  376. package/dist/src/workflows/draft/index.js +0 -3
  377. package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +0 -22
  378. package/dist/src/workflows/draft/workflow-draft-prompt.js +0 -54
  379. package/dist/src/workflows/draft/workflow-draft-service.d.ts +0 -12
  380. package/dist/src/workflows/draft/workflow-draft-service.js +0 -125
  381. package/dist/src/workflows/draft/workflow-draft-validator.d.ts +0 -4
  382. package/dist/src/workflows/draft/workflow-draft-validator.js +0 -123
  383. package/dist/src/workflows/draft/workflow-draft.types.d.ts +0 -44
  384. package/dist/src/workflows/draft/workflow-draft.types.js +0 -1
  385. /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
- ) 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);
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) db.prepare(`INSERT INTO user_assertion_evidence (
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.sensitivity !== "normal") return { action: "suppressed" };
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
- getSqliteDatabase().prepare(`INSERT INTO user_assertion_evidence (
356
- assertion_id, evidence_id, relation, confidence, created_at
357
- ) VALUES (?, ?, ?, ?, ?)
358
- ON CONFLICT(assertion_id, evidence_id, relation) DO UPDATE SET confidence = excluded.confidence`).run(assertionId, evidenceId, relation, confidence, now);
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): boolean;
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 '../local/wav.js';
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 "../local/wav.js";
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,4 @@
1
- //#region src/voice/local/wav.ts
1
+ //#region src/voice/audio/wav.ts
2
2
  var UnsupportedWavEncodingError = class extends Error {
3
3
  constructor(message) {
4
4
  super(message);
@@ -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 ?? true,
43
- provider: audio?.provider ?? "xopc-local",
41
+ enabled: audio?.enabled ?? false,
42
+ provider: audio?.provider ?? "openai",
44
43
  fallback: audio?.fallback ?? {
45
44
  enabled: false,
46
- order: ["xopc-local"]
45
+ order: []
47
46
  },
48
47
  providers: {
49
48
  ...audio?.providers ?? {},
50
- "xopc-local": {
51
- model: DEFAULT_LOCAL_VOICE_MODEL_ID,
52
- ...audio?.providers?.["xopc-local"] ?? {}
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
- ended = true;
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
- if (!ended) {
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
- if (claim.request.purpose === "conversation" && activeResponse?.audioStarted && isLikelyPlaybackEcho(text, activeResponse.audibleText)) {
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: activeResponse.id,
462
+ responseId: playback.responseId,
447
463
  transcriptCharacters: text.length
448
- }, "Ignored finalized transcription matching active voice playback");
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 || bytes.byteLength % 2) throw new Error("PCM16 audio must contain complete samples");
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
- return spoken.includes(heard);
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, localTranscriptionProvider, openAiTranscriptionProvider, xopcCloudTranscriptionProvider };
4
+ export { alibabaTranscriptionProvider, openAiTranscriptionProvider, xopcCloudTranscriptionProvider };