@xopcai/xopc 0.0.215 → 0.0.217

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 (141) hide show
  1. package/README.md +4 -4
  2. package/README.zh-CN.md +4 -4
  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/{activity-store-k-mNF_Dq.js → activity-store-D6trMTyZ.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-0Am1Zsai.js → agent-avatar-dicebear-CAQdFrcu.js} +1 -1
  7. package/dist/gateway/static/root/assets/agents-C6q_vDzP.js +68 -0
  8. package/dist/gateway/static/root/assets/{api-BjN2udFQ.js → api-B9pZAyMB.js} +1 -1
  9. package/dist/gateway/static/root/assets/app-management-settings-panel-DRsTwFbF.js +1 -0
  10. package/dist/gateway/static/root/assets/{appearance-settings-CoB0hGf9.js → appearance-settings-B99NaPTf.js} +1 -1
  11. package/dist/gateway/static/root/assets/apps-page-Dx66anqa.js +1 -0
  12. package/dist/gateway/static/root/assets/{archive-plugin-BczSorEI.js → archive-plugin-BF0q7N24.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-D1SDGB0m.js → attachment-load-D1qmjGDo.js} +1 -1
  14. package/dist/gateway/static/root/assets/{automations-page-BTgWPOP6.js → automations-page-Ccu4yRFa.js} +1 -1
  15. package/dist/gateway/static/root/assets/automations-workspace-CHbA8d-P.js +6 -0
  16. package/dist/gateway/static/root/assets/{binary-plugins-6tFOQHNC.js → binary-plugins-DooqxEZz.js} +1 -1
  17. package/dist/gateway/static/root/assets/{block-editor-Cm7txOU2.js → block-editor-Dqg9kvb9.js} +47 -47
  18. package/dist/gateway/static/root/assets/browser-settings-page-CpRc-9Jy.js +8 -0
  19. package/dist/gateway/static/root/assets/{browser-workflow-inputs-Coz8pWzP.js → browser-workflow-inputs-CsIh8ySc.js} +1 -1
  20. package/dist/gateway/static/root/assets/{browser-workflows-page-DJGD7LOd.js → browser-workflows-page-BXQFxT0p.js} +2 -2
  21. package/dist/gateway/static/root/assets/capabilities-settings-panel-C89FGECN.js +7 -0
  22. package/dist/gateway/static/root/assets/{capability-presets-api-BF3G84qe.js → capability-presets-api-BX9U0FRh.js} +1 -1
  23. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-v85bB-Lt.js → capability-presets-settings-panel-XT6WEz9E.js} +2 -2
  24. package/dist/gateway/static/root/assets/{channel-recipient-api-8Uz95P40.js → channel-recipient-api-CUBTQ0Bz.js} +1 -1
  25. package/dist/gateway/static/root/assets/channels-settings-DhKk1oNT.js +1 -0
  26. package/dist/gateway/static/root/assets/channels-status-swr-CiwOOoVL.js +1 -0
  27. package/dist/gateway/static/root/assets/{chat-terminal-dock-DioZkaaj.js → chat-terminal-dock-CTbkTsc2.js} +2 -2
  28. package/dist/gateway/static/root/assets/circle-check-C23XjkUj.js +1 -0
  29. package/dist/gateway/static/root/assets/connectors-page-BDn3HTzX.js +2 -0
  30. package/dist/gateway/static/root/assets/{cron-expression-BTNvqkwt.js → cron-expression-XzPZhzVM.js} +1 -1
  31. package/dist/gateway/static/root/assets/{date-picker-wMj_1toq.js → date-picker-BmZjs4Bq.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dependency-picker-PlfH-GH8.js → dependency-picker-ndtb88_T.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-C3nO_ocM.js → desktop-pet-DZjW-7Tw.js} +1 -1
  34. package/dist/gateway/static/root/assets/desktop-pet-settings-C7BLs783.js +1 -0
  35. package/dist/gateway/static/root/assets/{directory-picker-path-field-BIqsbDII.js → directory-picker-path-field-BWiap88p.js} +1 -1
  36. package/dist/gateway/static/root/assets/electron-env-DH5wF8X8.js +1 -0
  37. package/dist/gateway/static/root/assets/{extension-debug-page-C1o3Jn7L.js → extension-debug-page-D7APnE3n.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-page-Drjulq3q.js → extension-page-BhV5hz70.js} +1 -1
  39. package/dist/gateway/static/root/assets/{extension-settings-page-XsMPJFYn.js → extension-settings-page-BhbcGuiJ.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-config-api-D9xHVpb9.js → gateway-config-api-CUt9bIpL.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-config-swr-l2w9ecXl.js → gateway-config-swr-BTH9HVUk.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-settings-BaVojQd4.js → gateway-settings-RafSECLG.js} +1 -1
  43. package/dist/gateway/static/root/assets/{gateway-startup-retry-XUzMGmLZ.js → gateway-startup-retry-DAEk_tnd.js} +1 -1
  44. package/dist/gateway/static/root/assets/{heartbeat-settings-dQH2-fGh.js → heartbeat-settings-CwVPlPLB.js} +1 -1
  45. package/dist/gateway/static/root/assets/{home-page-CMqS6l_m.js → home-page-CbdBcCwC.js} +1 -1
  46. package/dist/gateway/static/root/assets/{image-generation-api-CDoOrDMq.js → image-generation-api-HqcQrSed.js} +1 -1
  47. package/dist/gateway/static/root/assets/index-AbNnQyKk.css +2 -0
  48. package/dist/gateway/static/root/assets/index-CMLkr37Y.js +108 -0
  49. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-BG6lShzn.js +1 -0
  50. package/dist/gateway/static/root/assets/local-app-workbench-page-DdaPtQ5M.js +2 -0
  51. package/dist/gateway/static/root/assets/{local-apps-page-8w0FZ7TD.js → local-apps-page-vaz8ewe2.js} +1 -1
  52. package/dist/gateway/static/root/assets/{locale-store-BIOMAhmR.js → locale-store-De8wYkd7.js} +1 -1
  53. package/dist/gateway/static/root/assets/{logs-page-FiVowm1N.js → logs-page-CjxMHTQO.js} +2 -2
  54. package/dist/gateway/static/root/assets/{management-settings-DdYouU4o.js → management-settings-tqTGCHt0.js} +1 -1
  55. package/dist/gateway/static/root/assets/{markdown-split-D_kDeT-f.js → markdown-split-BGx8Aao0.js} +1 -1
  56. package/dist/gateway/static/root/assets/{markdown-view-BMDQYc6E.js → markdown-view-ybRARsPs.js} +1 -1
  57. package/dist/gateway/static/root/assets/{media-plugins-BDgbIz9p.js → media-plugins-xbM-SSP5.js} +1 -1
  58. package/dist/gateway/static/root/assets/messages-VI9m1xJl.js +3 -0
  59. package/dist/gateway/static/root/assets/{notes-api-lKPk0Voa.js → notes-api-D9CCwyWK.js} +1 -1
  60. package/dist/gateway/static/root/assets/{notes-page-Bw2MQ4M8.js → notes-page-CMNBbg6g.js} +1 -1
  61. package/dist/gateway/static/root/assets/notes-workbench-V9C-8vSn.js +4 -0
  62. package/dist/gateway/static/root/assets/{page-tabs-B7dlng5v.js → page-tabs-e99j9S9K.js} +1 -1
  63. package/dist/gateway/static/root/assets/preview-open-alternatives-DW9MDOva.js +1 -0
  64. package/dist/gateway/static/root/assets/{product-open-page--m0DziFF.js → product-open-page-CZdzgPZW.js} +1 -1
  65. package/dist/gateway/static/root/assets/project-detail-page-DHmAUggu.js +1 -0
  66. package/dist/gateway/static/root/assets/projects-page-D0EiN69Y.js +1 -0
  67. package/dist/gateway/static/root/assets/{registry-api-BFwvRxBn.js → registry-api-DYmKEwiG.js} +1 -1
  68. package/dist/gateway/static/root/assets/remote-access-hub-BuAVFk2O.js +1 -0
  69. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-6QadzIxb.js → runtime-tools-settings-panel-DQ12tLCL.js} +2 -2
  70. package/dist/gateway/static/root/assets/{schema-form-ChJycivC.js → schema-form-DNCDIkqC.js} +1 -1
  71. package/dist/gateway/static/root/assets/sessions-page-hzlTfgOl.js +1 -0
  72. package/dist/gateway/static/root/assets/settings-advanced-gate-BlCoA_9h.js +1 -0
  73. package/dist/gateway/static/root/assets/{settings-form-section-DRazyNED.js → settings-form-section-z0JH53Fu.js} +1 -1
  74. package/dist/gateway/static/root/assets/{settings-loading-skeleton-CdEdSb5L.js → settings-loading-skeleton-xgo41cfo.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-BL0rlziB.js → settings-page-8astk_1U.js} +1 -1
  76. package/dist/gateway/static/root/assets/setup-status-panel-fZQfoJAk.js +1 -0
  77. package/dist/gateway/static/root/assets/{share-preview-page-CKK5swgV.js → share-preview-page-BBZV4AGy.js} +1 -1
  78. package/dist/gateway/static/root/assets/shares-settings-B5dPMq3Y.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-i1PGf1V2.js +1 -0
  80. package/dist/gateway/static/root/assets/skills-page-BSN2VaqR.js +2 -0
  81. package/dist/gateway/static/root/assets/{skills-page.utils-4_15-T3G.js → skills-page.utils-HmoDhJVh.js} +1 -1
  82. package/dist/gateway/static/root/assets/system-settings-panel-CSibO8vj.js +1 -0
  83. package/dist/gateway/static/root/assets/task-detail-page-HCKZ11E8.js +1 -0
  84. package/dist/gateway/static/root/assets/{theme-store-BrbF9cgL.js → theme-store-STx6jo38.js} +1 -1
  85. package/dist/gateway/static/root/assets/{typed-models-lib-CzB0r79r.js → typed-models-lib-zrYg51t3.js} +1 -1
  86. package/dist/gateway/static/root/assets/{use-autosave-D_fuJIDo.js → use-autosave-CqFVx92z.js} +1 -1
  87. package/dist/gateway/static/root/assets/user-context-page-CqG56cDS.js +1 -0
  88. package/dist/gateway/static/root/assets/voice-api-key-field-pYDiKKMo.js +1 -0
  89. package/dist/gateway/static/root/assets/{work-discovery-overlay-CSgiFeW2.js → work-discovery-overlay-LJLw9zf0.js} +1 -1
  90. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DstMFHA8.js → workflow-run-setup-panel-D0WhQ3kI.js} +2 -2
  91. package/dist/gateway/static/root/assets/workflows-page-DQAJzV5w.js +5 -0
  92. package/dist/gateway/static/root/index.html +13 -11
  93. package/dist/package.js +1 -1
  94. package/dist/packages/realtime-client/src/index.js +17 -2
  95. package/dist/src/gateway/hono/lib/static-ui.js +1 -0
  96. package/dist/src/gateway/hono/oauth-async.d.ts +4 -0
  97. package/dist/src/gateway/hono/oauth-async.js +24 -1
  98. package/dist/src/gateway/hono/oauth.js +14 -1
  99. package/dist/src/gateway/hono/routes/config.js +3 -0
  100. package/dist/src/gateway/hono/routes/public-gateway.js +16 -0
  101. package/dist/src/gateway/hono/routes/voice.js +1 -1
  102. package/dist/src/gateway/service.js +1 -3
  103. package/dist/src/gateway/xopc-cloud-capability-setup.d.ts +41 -0
  104. package/dist/src/gateway/xopc-cloud-capability-setup.js +142 -0
  105. package/dist/src/voice/language-profile.d.ts +0 -2
  106. package/dist/src/voice/language-profile.js +2 -30
  107. package/dist/src/voice/local/provider-switch.d.ts +4 -0
  108. package/dist/src/voice/local/provider-switch.js +36 -0
  109. package/package.json +4 -4
  110. package/dist/gateway/static/root/assets/agents-BhWSwa4h.js +0 -68
  111. package/dist/gateway/static/root/assets/app-management-settings-panel-BCHmLiA7.js +0 -1
  112. package/dist/gateway/static/root/assets/apps-page-DloObQ8z.js +0 -1
  113. package/dist/gateway/static/root/assets/automations-workspace-CbOSi-Uh.js +0 -6
  114. package/dist/gateway/static/root/assets/browser-settings-page-UhIguuT0.js +0 -8
  115. package/dist/gateway/static/root/assets/capabilities-settings-panel-BPe2vu-c.js +0 -7
  116. package/dist/gateway/static/root/assets/channels-settings-Dj3wNboO.js +0 -1
  117. package/dist/gateway/static/root/assets/channels-status-swr-NfU9X-P5.js +0 -1
  118. package/dist/gateway/static/root/assets/connectors-api-DHBX8LgY.js +0 -1
  119. package/dist/gateway/static/root/assets/connectors-page-B8Z692Fe.js +0 -2
  120. package/dist/gateway/static/root/assets/desktop-pet-settings-BZSODwlA.js +0 -1
  121. package/dist/gateway/static/root/assets/index-BDwfvp1w.css +0 -2
  122. package/dist/gateway/static/root/assets/index-CjbvsIPf.js +0 -108
  123. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-so_XFXVC.js +0 -1
  124. package/dist/gateway/static/root/assets/local-app-workbench-page-Dp1zGjrI.js +0 -2
  125. package/dist/gateway/static/root/assets/messages-CbbZKEfO.js +0 -3
  126. package/dist/gateway/static/root/assets/notes-workbench-DpMDd8Sm.js +0 -4
  127. package/dist/gateway/static/root/assets/preview-open-alternatives-Bzi2ia11.js +0 -1
  128. package/dist/gateway/static/root/assets/project-detail-page-D8AglzWN.js +0 -1
  129. package/dist/gateway/static/root/assets/projects-page-D0X6kb12.js +0 -1
  130. package/dist/gateway/static/root/assets/remote-access-hub-MxuXgfuY.js +0 -1
  131. package/dist/gateway/static/root/assets/sessions-page-DGZbtPXx.js +0 -1
  132. package/dist/gateway/static/root/assets/settings-advanced-gate-DLg_9-bb.js +0 -1
  133. package/dist/gateway/static/root/assets/setup-status-panel-D-nQiA7z.js +0 -1
  134. package/dist/gateway/static/root/assets/shares-settings-IDLLIYA5.js +0 -1
  135. package/dist/gateway/static/root/assets/skill-reload-api-C_ivBD5y.js +0 -1
  136. package/dist/gateway/static/root/assets/skills-page-t0eKREk9.js +0 -2
  137. package/dist/gateway/static/root/assets/system-settings-panel-CERY3Drp.js +0 -1
  138. package/dist/gateway/static/root/assets/task-detail-page-CS9BX5BO.js +0 -1
  139. package/dist/gateway/static/root/assets/user-context-page-BvBzRI8P.js +0 -1
  140. package/dist/gateway/static/root/assets/voice-api-key-field-ztq8iQAp.js +0 -1
  141. package/dist/gateway/static/root/assets/workflows-page-XD3Pmm1p.js +0 -5
@@ -1,4 +1,5 @@
1
1
  import { enumerateLanGatewayCandidates } from "../../host.js";
2
+ import { prepareLocalVoiceModelAfterProviderSwitch } from "../../../voice/local/provider-switch.js";
2
3
  import { buildSafeWebConfigPayload } from "../lib/config-payload.js";
3
4
  import { applyAgentsPatch } from "./config-patch/agents.js";
4
5
  import { applyChannelsPatch } from "./config-patch/channels.js";
@@ -51,6 +52,7 @@ function registerConfigRoutes(authenticated, deps) {
51
52
  authenticated.patch("/api/config", strictRateLimitMiddleware, async (c) => {
52
53
  const body = await c.req.json();
53
54
  const config = service.currentConfig;
55
+ const previousSttProvider = config.tools?.media?.audio?.provider;
54
56
  applyAgentsPatch(config, body);
55
57
  applyChannelsPatch(config, body);
56
58
  const gatewayResult = applyGatewayPatch(config, body);
@@ -73,6 +75,7 @@ function registerConfigRoutes(authenticated, deps) {
73
75
  ok: false,
74
76
  error: result.error
75
77
  }, 500);
78
+ prepareLocalVoiceModelAfterProviderSwitch(previousSttProvider, service.currentConfig);
76
79
  if (body.gateway?.heartbeat !== void 0 && typeof body.gateway.heartbeat === "object") service.reloadHeartbeatFromCurrentConfig();
77
80
  const safeConfig = await buildSafeWebConfigPayload(service, { locale: localeFromRequest(c) });
78
81
  return c.json({
@@ -7,6 +7,17 @@ import { serveStaticFile } from "../lib/static-ui.js";
7
7
  import { createHash } from "node:crypto";
8
8
  //#region src/gateway/hono/routes/public-gateway.ts
9
9
  init_package_version();
10
+ const PUBLIC_UI_ROOT_ASSETS = [
11
+ "apple-touch-icon.png",
12
+ "favicon-16x16.png",
13
+ "favicon-32x32.png",
14
+ "favicon.png",
15
+ "favicon.svg",
16
+ "notification-sw.js",
17
+ "pwa-192x192.png",
18
+ "pwa-512x512.png",
19
+ "site.webmanifest"
20
+ ];
10
21
  function registerPublicGatewayRoutes(app, service) {
11
22
  app.get("/health", (c) => {
12
23
  return c.json(service.getHealth());
@@ -171,6 +182,11 @@ function registerPublicGatewayRoutes(app, service) {
171
182
  if (fallback) return fallback;
172
183
  return c.text("Not found", 404);
173
184
  });
185
+ for (const assetPath of PUBLIC_UI_ROOT_ASSETS) app.get(`/${assetPath}`, (c) => {
186
+ const response = serveStaticFile(assetPath, c.req.raw);
187
+ if (response) return response;
188
+ return c.text("Not found", 404);
189
+ });
174
190
  app.get("/logo.svg", (c) => {
175
191
  const response = serveStaticFile("logo.svg", c.req.raw);
176
192
  if (response) return response;
@@ -12,8 +12,8 @@ import { mergeSttConfigFromAppConfig } from "../../../voice/stt/config.js";
12
12
  import "../../../voice/stt/index.js";
13
13
  import { listSttProvidersForApi } from "../../../voice/stt/list-providers.js";
14
14
  import "../../../voice/tts/index.js";
15
- import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
16
15
  import { createGatewayRouteLogger } from "../lib/route-logger.js";
16
+ import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
17
17
  import { listTtsProvidersForApi } from "../../../voice/tts/list-providers.js";
18
18
  //#region src/gateway/hono/routes/voice.ts
19
19
  init_providers();
@@ -116,7 +116,7 @@ import { GatewayAgentRunner } from "./service/agent-runner.js";
116
116
  import { RealtimeRuntime } from "../realtime/runtime.js";
117
117
  import { GatewayReadiness } from "./startup-readiness.js";
118
118
  import { createGatewayStartupTrace } from "./startup-trace.js";
119
- import { applyAutomaticVoiceLanguage, inferProductLanguageFromEnvironment, initializeVoiceDefaults, prepareConfiguredLocalVoiceModel } from "../voice/language-profile.js";
119
+ import { applyAutomaticVoiceLanguage, inferProductLanguageFromEnvironment, initializeVoiceDefaults } from "../voice/language-profile.js";
120
120
  import crypto from "crypto";
121
121
  //#region src/gateway/service.ts
122
122
  init_agent_scope();
@@ -793,7 +793,6 @@ var GatewayService = class {
793
793
  this.proactiveWorker.start();
794
794
  this.proactiveTemporalWorker.start();
795
795
  this.proactiveInboxWorker.start();
796
- prepareConfiguredLocalVoiceModel(this.config);
797
796
  this.startupTrace = createGatewayStartupTrace();
798
797
  this.readiness.markStarting(this.startTime);
799
798
  const trace = this.startupTrace;
@@ -1268,7 +1267,6 @@ var GatewayService = class {
1268
1267
  error: saved.error ?? "Failed to save voice language"
1269
1268
  };
1270
1269
  }
1271
- prepareConfiguredLocalVoiceModel(this.config);
1272
1270
  return {
1273
1271
  applied: changed,
1274
1272
  language,
@@ -0,0 +1,41 @@
1
+ import type { Config } from '../config/schema.js';
2
+ import type { CatalogSource } from '../providers/model-catalog-store.js';
3
+ type CloudCapability = 'vision' | 'image-generation' | 'stt' | 'tts';
4
+ export interface XopcCloudCapabilitySelection {
5
+ vision: string;
6
+ imageGeneration: string;
7
+ stt: string;
8
+ tts: string;
9
+ ttsVoice: string;
10
+ }
11
+ export type PrepareXopcCloudCapabilitySetupResult = {
12
+ ok: true;
13
+ config: Config;
14
+ selection: XopcCloudCapabilitySelection;
15
+ } | {
16
+ ok: false;
17
+ error: string;
18
+ missing: CloudCapability[];
19
+ };
20
+ export type ApplyXopcCloudCapabilitySetupResult = {
21
+ configured: true;
22
+ selection: XopcCloudCapabilitySelection;
23
+ } | {
24
+ configured: false;
25
+ error: string;
26
+ missing?: CloudCapability[];
27
+ };
28
+ export declare function selectXopcCloudCapabilities(source: CatalogSource): {
29
+ selection?: XopcCloudCapabilitySelection;
30
+ missing: CloudCapability[];
31
+ };
32
+ /** Build one atomic config update for every managed XOPC Cloud media capability. */
33
+ export declare function prepareXopcCloudCapabilitySetup(config: Config, source: CatalogSource): PrepareXopcCloudCapabilitySetupResult;
34
+ export declare function applyXopcCloudCapabilitySetup(service: {
35
+ currentConfig: Config;
36
+ saveConfig(config: Config): Promise<{
37
+ saved: boolean;
38
+ error?: string;
39
+ }>;
40
+ }): Promise<ApplyXopcCloudCapabilitySetupResult>;
41
+ export {};
@@ -0,0 +1,142 @@
1
+ import { getModelCatalogStore, init_model_catalog_store } from "../providers/model-catalog-store.js";
2
+ import { compareCatalogModels } from "../providers/model-catalog-ranking.js";
3
+ import { ensureGlobalDefaultsConfig, prepareUpdateGlobalDefaults } from "./global-defaults-admin.js";
4
+ //#region src/gateway/xopc-cloud-capability-setup.ts
5
+ init_model_catalog_store();
6
+ function supportsCapability(model, capability) {
7
+ if (model.availability !== "available") return false;
8
+ if (capability === "vision") return model.kind === "language" && model.input.includes("image");
9
+ if (capability === "image-generation") return model.kind === "image" && model.operations.includes("images.generate");
10
+ if (capability === "stt") return model.kind === "stt" && model.operations.includes("audio.transcription");
11
+ return model.kind === "tts" && model.operations.includes("audio.speech") && Boolean(model.tts?.defaultVoice);
12
+ }
13
+ function recommendedModel(source, capability) {
14
+ const recommendation = source.recommended?.[capability];
15
+ return source.models.filter((model) => supportsCapability(model, capability)).sort((left, right) => compareCatalogModels(left, right, recommendation))[0];
16
+ }
17
+ function selectXopcCloudCapabilities(source) {
18
+ const vision = recommendedModel(source, "vision");
19
+ const imageGeneration = recommendedModel(source, "image-generation");
20
+ const stt = recommendedModel(source, "stt");
21
+ const tts = recommendedModel(source, "tts");
22
+ const missing = [];
23
+ if (!vision) missing.push("vision");
24
+ if (!imageGeneration) missing.push("image-generation");
25
+ if (!stt) missing.push("stt");
26
+ if (!tts) missing.push("tts");
27
+ if (!vision || !imageGeneration || !stt || !tts || !tts.tts?.defaultVoice) return { missing };
28
+ return {
29
+ missing,
30
+ selection: {
31
+ vision: vision.id,
32
+ imageGeneration: imageGeneration.id,
33
+ stt: stt.id,
34
+ tts: tts.id,
35
+ ttsVoice: tts.tts.defaultVoice
36
+ }
37
+ };
38
+ }
39
+ /** Build one atomic config update for every managed XOPC Cloud media capability. */
40
+ function prepareXopcCloudCapabilitySetup(config, source) {
41
+ const selected = selectXopcCloudCapabilities(source);
42
+ if (!selected.selection) return {
43
+ ok: false,
44
+ error: `XOPC Cloud is missing required capabilities: ${selected.missing.join(", ")}`,
45
+ missing: selected.missing
46
+ };
47
+ const selection = selected.selection;
48
+ const normalized = ensureGlobalDefaultsConfig(config);
49
+ const presetId = normalized.agents.defaultPreset;
50
+ const currentModels = normalized.agents.capabilityPresets[presetId]?.models;
51
+ const defaultsUpdate = prepareUpdateGlobalDefaults(normalized, { models: {
52
+ ...currentModels,
53
+ imageModel: {
54
+ ...currentModels?.imageModel,
55
+ primary: `xopc-cloud/${selection.vision}`
56
+ },
57
+ imageGenerationModel: {
58
+ ...currentModels?.imageGenerationModel,
59
+ primary: `xopc-cloud/${selection.imageGeneration}`
60
+ }
61
+ } });
62
+ if (defaultsUpdate.ok === false) return {
63
+ ok: false,
64
+ error: defaultsUpdate.error,
65
+ missing: []
66
+ };
67
+ const withDefaults = defaultsUpdate.data.nextConfig;
68
+ const currentStt = withDefaults.tools?.media?.audio;
69
+ const currentTts = withDefaults.messages?.tts;
70
+ return {
71
+ ok: true,
72
+ selection,
73
+ config: {
74
+ ...withDefaults,
75
+ tools: {
76
+ ...withDefaults.tools,
77
+ media: {
78
+ ...withDefaults.tools?.media,
79
+ audio: {
80
+ ...currentStt,
81
+ enabled: true,
82
+ provider: "xopc-cloud",
83
+ fallback: {
84
+ enabled: false,
85
+ order: ["xopc-cloud"]
86
+ },
87
+ providers: {
88
+ ...currentStt?.providers ?? {},
89
+ "xopc-cloud": {
90
+ ...currentStt?.providers?.["xopc-cloud"] ?? {},
91
+ model: selection.stt
92
+ }
93
+ }
94
+ }
95
+ }
96
+ },
97
+ messages: {
98
+ ...withDefaults.messages,
99
+ tts: {
100
+ ...currentTts,
101
+ enabled: true,
102
+ provider: "xopc-cloud",
103
+ trigger: currentTts?.trigger ?? "off",
104
+ maxTextLength: currentTts?.maxTextLength ?? 512,
105
+ timeoutMs: currentTts?.timeoutMs ?? 6e4,
106
+ providers: {
107
+ ...currentTts?.providers ?? {},
108
+ "xopc-cloud": {
109
+ ...currentTts?.providers?.["xopc-cloud"] ?? {},
110
+ model: selection.tts,
111
+ voice: selection.ttsVoice
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ };
118
+ }
119
+ async function applyXopcCloudCapabilitySetup(service) {
120
+ const source = getModelCatalogStore().getSource("xopc-cloud");
121
+ if (!source) return {
122
+ configured: false,
123
+ error: "XOPC Cloud model catalog is unavailable"
124
+ };
125
+ const prepared = prepareXopcCloudCapabilitySetup(service.currentConfig, source);
126
+ if (prepared.ok === false) return {
127
+ configured: false,
128
+ error: prepared.error,
129
+ missing: prepared.missing
130
+ };
131
+ const saved = await service.saveConfig(prepared.config);
132
+ if (!saved.saved) return {
133
+ configured: false,
134
+ error: saved.error ?? "Failed to save XOPC Cloud capability configuration"
135
+ };
136
+ return {
137
+ configured: true,
138
+ selection: prepared.selection
139
+ };
140
+ }
141
+ //#endregion
142
+ export { applyXopcCloudCapabilitySetup, prepareXopcCloudCapabilitySetup, selectXopcCloudCapabilities };
@@ -13,5 +13,3 @@ export declare function inferProductLanguageFromEnvironment(): ProductLanguage;
13
13
  export declare function initializeVoiceDefaults(config: Config, language?: ProductLanguage): boolean;
14
14
  /** Apply product language only to providers whose language mapping is known. */
15
15
  export declare function applyAutomaticVoiceLanguage(config: Config, language: ProductLanguage): boolean;
16
- /** Start the model download without delaying gateway readiness. */
17
- export declare function prepareConfiguredLocalVoiceModel(config: Config): void;
@@ -1,10 +1,5 @@
1
- import { createLogger } from "../utils/logger/index.js";
2
- import { init_logger } from "../utils/logger.js";
3
- import { DEFAULT_LOCAL_VOICE_MODEL_ID, isLocalVoiceModelInstalled } from "./local/models.js";
4
- import { startLocalVoiceModelInstall } from "./local/model-manager.js";
1
+ import { DEFAULT_LOCAL_VOICE_MODEL_ID } from "./local/models.js";
5
2
  //#region src/voice/language-profile.ts
6
- init_logger();
7
- const log = createLogger("Voice:Language");
8
3
  function resolveVoiceLanguageProfile(language) {
9
4
  return language === "zh" ? {
10
5
  language,
@@ -104,28 +99,5 @@ function applyAutomaticVoiceLanguage(config, language) {
104
99
  tts: config.messages?.tts
105
100
  });
106
101
  }
107
- /** Start the model download without delaying gateway readiness. */
108
- function prepareConfiguredLocalVoiceModel(config) {
109
- const audio = config.tools?.media?.audio;
110
- if (audio?.enabled === false || (audio?.provider ?? "xopc-local") !== "xopc-local") return;
111
- const configuredModel = audio?.providers?.["xopc-local"]?.model;
112
- const modelId = typeof configuredModel === "string" && configuredModel.trim() ? configuredModel.trim() : DEFAULT_LOCAL_VOICE_MODEL_ID;
113
- if (isLocalVoiceModelInstalled(modelId)) return;
114
- try {
115
- startLocalVoiceModelInstall(modelId);
116
- log.info({
117
- modelId,
118
- phase: "startup_prepare"
119
- }, "Local voice model preparation started");
120
- } catch (err) {
121
- const errorMessage = err instanceof Error ? err.message : String(err);
122
- log.warn({
123
- err,
124
- modelId,
125
- errorMessage,
126
- phase: "startup_prepare"
127
- }, `Local voice model preparation failed: ${errorMessage}`);
128
- }
129
- }
130
102
  //#endregion
131
- export { applyAutomaticVoiceLanguage, inferProductLanguageFromEnvironment, initializeVoiceDefaults, prepareConfiguredLocalVoiceModel, resolveVoiceLanguageProfile };
103
+ export { applyAutomaticVoiceLanguage, inferProductLanguageFromEnvironment, initializeVoiceDefaults, resolveVoiceLanguageProfile };
@@ -0,0 +1,4 @@
1
+ import type { Config } from '../../config/schema.js';
2
+ export declare function localVoiceModelForProviderSwitch(previousProvider: string | undefined, config: Config): string | null;
3
+ /** Start a missing local STT model only after the provider changes to xopc-local. */
4
+ export declare function prepareLocalVoiceModelAfterProviderSwitch(previousProvider: string | undefined, config: Config): void;
@@ -0,0 +1,36 @@
1
+ import { createLogger } from "../../utils/logger/index.js";
2
+ import { init_logger } from "../../utils/logger.js";
3
+ import { DEFAULT_LOCAL_VOICE_MODEL_ID, isLocalVoiceModelInstalled } from "./models.js";
4
+ import { startLocalVoiceModelInstall } from "./model-manager.js";
5
+ //#region src/voice/local/provider-switch.ts
6
+ init_logger();
7
+ const log = createLogger("Voice:Local");
8
+ function localVoiceModelForProviderSwitch(previousProvider, config) {
9
+ const audio = config.tools?.media?.audio;
10
+ const previous = previousProvider?.trim() || "xopc-local";
11
+ if (audio?.enabled === false || previous === "xopc-local" || audio?.provider !== "xopc-local") return null;
12
+ const configuredModel = audio.providers?.["xopc-local"]?.model;
13
+ return typeof configuredModel === "string" && configuredModel.trim() ? configuredModel.trim() : DEFAULT_LOCAL_VOICE_MODEL_ID;
14
+ }
15
+ /** Start a missing local STT model only after the provider changes to xopc-local. */
16
+ function prepareLocalVoiceModelAfterProviderSwitch(previousProvider, config) {
17
+ const modelId = localVoiceModelForProviderSwitch(previousProvider, config);
18
+ if (!modelId || isLocalVoiceModelInstalled(modelId)) return;
19
+ try {
20
+ startLocalVoiceModelInstall(modelId);
21
+ log.info({
22
+ modelId,
23
+ phase: "provider_switch"
24
+ }, "Local voice model preparation started");
25
+ } catch (err) {
26
+ const errorMessage = err instanceof Error ? err.message : String(err);
27
+ log.warn({
28
+ err,
29
+ modelId,
30
+ errorMessage,
31
+ phase: "provider_switch"
32
+ }, `Local voice model preparation failed: ${errorMessage}`);
33
+ }
34
+ }
35
+ //#endregion
36
+ export { localVoiceModelForProviderSwitch, prepareLocalVoiceModelAfterProviderSwitch };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.215",
3
+ "version": "0.0.217",
4
4
  "description": "Local-first personal AI assistant with reviewable user understanding, durable tasks, workflows, automations, and local or cloud models.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -163,10 +163,10 @@
163
163
  "vitepress": "^1.6.4",
164
164
  "vitest": "4.1.5",
165
165
  "vue": "^3.5.35",
166
- "@xopcai/gateway-contract": "0.0.0",
167
166
  "@xopcai/endpoint-tools-protocol": "0.0.0",
168
- "@xopcai/realtime-protocol": "0.0.0",
169
- "@xopcai/realtime-client": "0.0.0"
167
+ "@xopcai/gateway-contract": "0.0.0",
168
+ "@xopcai/realtime-client": "0.0.0",
169
+ "@xopcai/realtime-protocol": "0.0.0"
170
170
  },
171
171
  "scripts": {
172
172
  "assets:brand": "node scripts/generate-brand-assets.mjs",