@xopcai/xopc 0.0.229 → 0.0.230

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 (78) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CsFAJTIN.js → agent-avatar-dicebear-Bp_wmuGW.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agents-DA4b6_0C.js → agents-CKG93dlc.js} +1 -1
  5. package/dist/gateway/static/root/assets/{app-management-settings-panel-7KcMWuah.js → app-management-settings-panel-CwAPK4Jm.js} +1 -1
  6. package/dist/gateway/static/root/assets/{appearance-settings-Cqlw7Fif.js → appearance-settings-DsGLvqTb.js} +1 -1
  7. package/dist/gateway/static/root/assets/{apps-page-CsnhdGZ2.js → apps-page-Ee9qOQEx.js} +1 -1
  8. package/dist/gateway/static/root/assets/{attachment-load-q4pDpqkF.js → attachment-load-B4qqigAQ.js} +1 -1
  9. package/dist/gateway/static/root/assets/{automations-page-BuTqjKGX.js → automations-page-B8ImehSW.js} +1 -1
  10. package/dist/gateway/static/root/assets/{automations-workspace-CD0E2ThS.js → automations-workspace-BNFAfNwC.js} +1 -1
  11. package/dist/gateway/static/root/assets/{binary-plugins-DUce1Bsc.js → binary-plugins-DaJbyYc2.js} +1 -1
  12. package/dist/gateway/static/root/assets/{block-editor-D8Ejp-QR.js → block-editor-Kl25XWJc.js} +1 -1
  13. package/dist/gateway/static/root/assets/{browser-settings-page-CY1k3MMd.js → browser-settings-page-Cg6NgwE_.js} +1 -1
  14. package/dist/gateway/static/root/assets/{browser-workflows-page-BDvZbR9v.js → browser-workflows-page-DjMxs33B.js} +1 -1
  15. package/dist/gateway/static/root/assets/{capabilities-settings-panel-D1VfotHQ.js → capabilities-settings-panel-NvJKgF1u.js} +1 -1
  16. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-DXHqRLpU.js → capability-presets-settings-panel-C2uBdALe.js} +1 -1
  17. package/dist/gateway/static/root/assets/{channels-settings-DrFL57M_.js → channels-settings-CIcYKMEs.js} +1 -1
  18. package/dist/gateway/static/root/assets/{chat-terminal-dock-h1CKexNz.js → chat-terminal-dock-BiU_4Rq6.js} +1 -1
  19. package/dist/gateway/static/root/assets/{connectors-page-DUAyfFCF.js → connectors-page-CEEcmUiP.js} +1 -1
  20. package/dist/gateway/static/root/assets/{cron-expression-DlaQQOId.js → cron-expression-Cs_5pUPT.js} +1 -1
  21. package/dist/gateway/static/root/assets/{date-picker-8R1sXJKb.js → date-picker-y1kWrFVU.js} +1 -1
  22. package/dist/gateway/static/root/assets/{dependency-picker-CWur0821.js → dependency-picker-skc62zrn.js} +1 -1
  23. package/dist/gateway/static/root/assets/{desktop-pet-settings-CAQMLVtd.js → desktop-pet-settings-BVVCBgYK.js} +1 -1
  24. package/dist/gateway/static/root/assets/{desktop-pet-Knl-zNDU.js → desktop-pet-ux9DxchT.js} +1 -1
  25. package/dist/gateway/static/root/assets/{directory-picker-path-field-Caaz4Rw5.js → directory-picker-path-field-V8vZP0Dy.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-debug-page-B965Mc15.js → extension-debug-page-Dh6DDuvQ.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-page-C0UnkBi5.js → extension-page-8OKQDEat.js} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-settings-page-BUSIAZCR.js → extension-settings-page-BgSV0Nny.js} +1 -1
  29. package/dist/gateway/static/root/assets/{gateway-config-api-DkH0eEgy.js → gateway-config-api-Dlc6eaTG.js} +1 -1
  30. package/dist/gateway/static/root/assets/{gateway-settings-BBgLDm6I.js → gateway-settings-DqQgiAUv.js} +1 -1
  31. package/dist/gateway/static/root/assets/{heartbeat-settings-BtEHVXWD.js → heartbeat-settings-Pxqk5GFH.js} +1 -1
  32. package/dist/gateway/static/root/assets/{home-page-5SU2TNJj.js → home-page-1xjo6wE4.js} +1 -1
  33. package/dist/gateway/static/root/assets/{index-BNWhgmjs.js → index-Bbd_dXui.js} +17 -17
  34. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CsRz8NrS.js → keyboard-shortcuts-settings-BSFNqxzY.js} +1 -1
  35. package/dist/gateway/static/root/assets/{local-app-workbench-page-DYPEUgpP.js → local-app-workbench-page-heQ4-PJ7.js} +1 -1
  36. package/dist/gateway/static/root/assets/{local-apps-page-CTBNUG4a.js → local-apps-page-DzU6yZ9-.js} +1 -1
  37. package/dist/gateway/static/root/assets/{logs-page-B0P7rG2B.js → logs-page-BblnS6Jy.js} +1 -1
  38. package/dist/gateway/static/root/assets/{management-settings-YqUAEwQo.js → management-settings-B8hM56HS.js} +1 -1
  39. package/dist/gateway/static/root/assets/{markdown-split-dxpSCXb8.js → markdown-split-DRbZjxMK.js} +1 -1
  40. package/dist/gateway/static/root/assets/{media-plugins-CJ00i1Lg.js → media-plugins-B8vMe5VX.js} +1 -1
  41. package/dist/gateway/static/root/assets/{notes-page-DEnbnkIt.js → notes-page-B-YZ7iuK.js} +1 -1
  42. package/dist/gateway/static/root/assets/{notes-workbench-DmVYu_Oc.js → notes-workbench-CAM09C8b.js} +2 -2
  43. package/dist/gateway/static/root/assets/{product-open-page-BHxo9U95.js → product-open-page-DkWcyki5.js} +1 -1
  44. package/dist/gateway/static/root/assets/{project-detail-page-DV2nGmsq.js → project-detail-page-BIPIwgU2.js} +1 -1
  45. package/dist/gateway/static/root/assets/{projects-page-BNIFwFfc.js → projects-page-B_kzTn1K.js} +1 -1
  46. package/dist/gateway/static/root/assets/{remote-access-hub-DLXqKiA_.js → remote-access-hub-CtD8DsD-.js} +1 -1
  47. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BpQ2GI-0.js → runtime-tools-settings-panel-Bq_ETeal.js} +1 -1
  48. package/dist/gateway/static/root/assets/{schema-form-HE1G26Lx.js → schema-form-BogTlrsP.js} +1 -1
  49. package/dist/gateway/static/root/assets/{sessions-page-DWaXf_25.js → sessions-page-B8n9HI1y.js} +1 -1
  50. package/dist/gateway/static/root/assets/settings-advanced-gate-xlhdRTME.js +1 -0
  51. package/dist/gateway/static/root/assets/{settings-form-section-CXAn0Xhy.js → settings-form-section-Coy1Cbp6.js} +1 -1
  52. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DsFu7Bcv.js → settings-loading-skeleton-B5GU7iCG.js} +1 -1
  53. package/dist/gateway/static/root/assets/{settings-page-C4iib9nO.js → settings-page-Dd-BRu12.js} +1 -1
  54. package/dist/gateway/static/root/assets/{setup-status-panel-BA83Wr1d.js → setup-status-panel-CwEFAVWx.js} +1 -1
  55. package/dist/gateway/static/root/assets/{share-preview-page-BOGl3s6M.js → share-preview-page-DzXw9UQJ.js} +1 -1
  56. package/dist/gateway/static/root/assets/{shares-settings-Q2MdGaBi.js → shares-settings-Bk6UQOwS.js} +1 -1
  57. package/dist/gateway/static/root/assets/{skill-reload-api-cFtfVeFU.js → skill-reload-api-DrmQZ3Au.js} +1 -1
  58. package/dist/gateway/static/root/assets/{skills-page-CdaFtNw9.js → skills-page-Brxb6QnW.js} +1 -1
  59. package/dist/gateway/static/root/assets/{skills-page.utils-DYaAddUL.js → skills-page.utils-FB5LtEGm.js} +1 -1
  60. package/dist/gateway/static/root/assets/{system-settings-panel-Co7gilRd.js → system-settings-panel-ChosWt8n.js} +1 -1
  61. package/dist/gateway/static/root/assets/{task-detail-page-5B1pswu8.js → task-detail-page-CW2sJbdc.js} +1 -1
  62. package/dist/gateway/static/root/assets/{use-autosave-DnnZtMpA.js → use-autosave-2SqnmSKD.js} +1 -1
  63. package/dist/gateway/static/root/assets/{user-context-page-Dr1FKjXv.js → user-context-page-Bq9KB-Oj.js} +1 -1
  64. package/dist/gateway/static/root/assets/{voice-api-key-field-wetUpi3i.js → voice-api-key-field-DtTIF6M8.js} +1 -1
  65. package/dist/gateway/static/root/assets/{work-discovery-overlay-tbTWASJJ.js → work-discovery-overlay-CK3aZDdE.js} +1 -1
  66. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Dy0fDs8w.js → workflow-run-setup-panel-BjOuddkX.js} +1 -1
  67. package/dist/gateway/static/root/assets/{workflows-page-IVP3GSkI.js → workflows-page-CcbGEQol.js} +1 -1
  68. package/dist/gateway/static/root/index.html +1 -1
  69. package/dist/package.js +1 -1
  70. package/dist/src/agent/inbound/turn-dispatcher.js +1 -1
  71. package/dist/src/agent/service/process-direct-streaming.js +4 -1
  72. package/dist/src/agent/service/webchat-tts.d.ts +2 -0
  73. package/dist/src/agent/service/webchat-tts.js +15 -2
  74. package/dist/src/agent/tools/tts-tool.js +19 -13
  75. package/dist/src/gateway/chat-stream/mapper.js +11 -0
  76. package/dist/src/gateway/hono/routes/voice.js +1 -1
  77. package/package.json +1 -1
  78. package/dist/gateway/static/root/assets/settings-advanced-gate-JFCbnCL2.js +0 -1
@@ -1,8 +1,8 @@
1
1
  import { queueEmbeddedSteer } from "../embedded/runs.js";
2
2
  import { buildDirectUserMessageContent } from "../service/build-direct-message-content.js";
3
+ import { maybeEmitWebchatTts } from "../service/webchat-tts.js";
3
4
  import { runProcessDirectStreaming } from "../service/process-direct-streaming.js";
4
5
  import { runProcessDirect } from "../service/process-direct-one-shot.js";
5
- import { maybeEmitWebchatTts } from "../service/webchat-tts.js";
6
6
  //#region src/agent/inbound/turn-dispatcher.ts
7
7
  var TurnDispatcher = class {
8
8
  cfg;
@@ -13,6 +13,7 @@ import { isSessionSourceBinding, summarizeSourceContext } from "../source-contex
13
13
  import { injectSourceContextsIntoUserMessage } from "../source-context/injector.js";
14
14
  import { AsyncQueue, AsyncQueueOverflowError } from "./async-queue.js";
15
15
  import { hydratePerTurnState, runDirectAgentTurn, tryRunSlashCommand } from "./direct-turn-helpers.js";
16
+ import { isSuccessfulWebchatTtsToolEvent } from "./webchat-tts.js";
16
17
  //#region src/agent/service/process-direct-streaming.ts
17
18
  const MAX_BUFFERED_STREAM_EVENTS = 512;
18
19
  const LOSSY_STREAM_EVENT_TYPES = new Set([
@@ -151,6 +152,7 @@ async function* runProcessDirectStreaming(deps, input) {
151
152
  let userAborted = false;
152
153
  let abortHandled = false;
153
154
  let inboundVoice = false;
155
+ let explicitTtsEmitted = false;
154
156
  let ranSlashCommand = false;
155
157
  let mergedUserText = input.content;
156
158
  let webchatSlashReceipt;
@@ -299,6 +301,7 @@ async function* runProcessDirectStreaming(deps, input) {
299
301
  runId: input.runId,
300
302
  onEvent: (embeddedEvent) => {
301
303
  const event = { ...embeddedEvent };
304
+ if (isSuccessfulWebchatTtsToolEvent(event)) explicitTtsEmitted = true;
302
305
  if (event.type === "error" && typeof event.content === "string") event.content = formatStreamError(event.content);
303
306
  pushVisible(event);
304
307
  }
@@ -329,7 +332,7 @@ async function* runProcessDirectStreaming(deps, input) {
329
332
  sessionKey,
330
333
  droppedEvents: queue.droppedCount
331
334
  }, "Coalesced stream progress events because the consumer fell behind");
332
- if (!userAborted && !streamOverflowed && channel === "webchat") try {
335
+ if (!userAborted && !streamOverflowed && channel === "webchat" && !explicitTtsEmitted) try {
333
336
  const ttsAudioEvent = await deps.maybeEmitWebchatTts(sessionKey, inboundVoice);
334
337
  if (ttsAudioEvent) queue.push(ttsAudioEvent);
335
338
  } catch (ttsErr) {
@@ -15,6 +15,8 @@ export type WebchatTtsDeps = {
15
15
  warn: (obj: Record<string, unknown>, msg: string) => void;
16
16
  };
17
17
  };
18
+ /** True when the explicit TTS tool already produced durable Webchat audio. */
19
+ export declare function isSuccessfulWebchatTtsToolEvent(event: unknown): boolean;
18
20
  /**
19
21
  * Generate TTS for webchat when config allows; persist under `{stateDir}/media/tts/`.
20
22
  */
@@ -3,9 +3,22 @@ import { speak } from "../../voice/tts/speak-core.js";
3
3
  import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
4
4
  import { getChannelOutputFormat, shouldUseTTS } from "../../voice/tts/service.js";
5
5
  import { compressAudio } from "../../voice/tts/audio.js";
6
- import "../../voice/tts/index.js";
7
6
  import { persistOutboundTtsAudio } from "../../channels/attachments/outbound-tts-persist.js";
7
+ import "../../voice/tts/index.js";
8
8
  //#region src/agent/service/webchat-tts.ts
9
+ /** True when the explicit TTS tool already produced durable Webchat audio. */
10
+ function isSuccessfulWebchatTtsToolEvent(event) {
11
+ if (!event || typeof event !== "object" || Array.isArray(event)) return false;
12
+ const row = event;
13
+ if (row.type !== "tool_execution_end" || row.toolName !== "text_to_speech" || row.isError === true) return false;
14
+ const result = row.result && typeof row.result === "object" && !Array.isArray(row.result) ? row.result : null;
15
+ const details = result?.details && typeof result.details === "object" && !Array.isArray(result.details) ? result.details : null;
16
+ return Array.isArray(details?.media) && details.media.some((item) => {
17
+ if (!item || typeof item !== "object" || Array.isArray(item)) return false;
18
+ const media = item;
19
+ return typeof media.uri === "string" && media.uri.trim().length > 0;
20
+ });
21
+ }
9
22
  /**
10
23
  * Generate TTS for webchat when config allows; persist under `{stateDir}/media/tts/`.
11
24
  */
@@ -57,4 +70,4 @@ async function appendMediaToLastAssistant(sessionStore, sessionKey, ref) {
57
70
  }
58
71
  }
59
72
  //#endregion
60
- export { appendMediaToLastAssistant, maybeEmitWebchatTts };
73
+ export { appendMediaToLastAssistant, isSuccessfulWebchatTtsToolEvent, maybeEmitWebchatTts };
@@ -4,6 +4,7 @@ import { speak } from "../../voice/tts/speak-core.js";
4
4
  import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
5
5
  import { getChannelOutputFormat } from "../../voice/tts/service.js";
6
6
  import { compressAudio } from "../../voice/tts/audio.js";
7
+ import { persistOutboundTtsAudio } from "../../channels/attachments/outbound-tts-persist.js";
7
8
  import { Type } from "@sinclair/typebox";
8
9
  //#region src/agent/tools/tts-tool.ts
9
10
  init_logger();
@@ -72,30 +73,35 @@ function createTextToSpeechTool(deps) {
72
73
  });
73
74
  const wavTarget = outFmt.format === "mp3" ? "mp3" : "opus";
74
75
  const { buffer: compressedAudio, format: compressedFormat } = await compressAudio(Buffer.from(result.audio), result.format, wavTarget);
75
- const dataUrl = `data:${compressedFormat === "opus" ? "audio/ogg" : compressedFormat === "mp3" || compressedFormat === "mpeg" ? "audio/mpeg" : `audio/${compressedFormat}`};base64,${compressedAudio.toString("base64")}`;
76
- const msg = {
77
- channel: ctx.channel,
78
- chat_id: ctx.chatId,
79
- content: "",
80
- mediaUrl: dataUrl,
81
- mediaType: "audio",
82
- audioAsVoice: outFmt.voiceCompatible
83
- };
84
- await deps.bus.publishOutbound(msg);
76
+ const mimeType = compressedFormat === "opus" ? "audio/ogg" : compressedFormat === "mp3" || compressedFormat === "mpeg" ? "audio/mpeg" : `audio/${compressedFormat}`;
77
+ const media = ctx.channel === "webchat" ? await persistOutboundTtsAudio(compressedAudio, compressedFormat) : void 0;
78
+ if (!media) {
79
+ const msg = {
80
+ channel: ctx.channel,
81
+ chat_id: ctx.chatId,
82
+ content: "",
83
+ mediaUrl: `data:${mimeType};base64,${compressedAudio.toString("base64")}`,
84
+ mediaType: "audio",
85
+ audioAsVoice: outFmt.voiceCompatible
86
+ };
87
+ await deps.bus.publishOutbound(msg);
88
+ }
85
89
  log.info({
86
90
  provider: result.provider,
87
91
  format: compressedFormat,
92
+ channel: ctx.channel,
88
93
  textLength: params.text.length,
89
94
  audioSize: compressedAudio.length
90
- }, "TTS tool sent audio");
95
+ }, ctx.channel === "webchat" ? "TTS tool attached audio" : "TTS tool sent audio");
91
96
  return {
92
97
  content: [{
93
98
  type: "text",
94
- text: `✅ Sent voice message (${result.provider}, ${compressedFormat}).`
99
+ text: ctx.channel === "webchat" ? `✅ Attached voice message (${result.provider}, ${compressedFormat}).` : `✅ Sent voice message (${result.provider}, ${compressedFormat}).`
95
100
  }],
96
101
  details: {
97
102
  provider: result.provider,
98
- format: compressedFormat
103
+ format: compressedFormat,
104
+ ...media ? { media: [media] } : {}
99
105
  }
100
106
  };
101
107
  } catch (error) {
@@ -342,6 +342,17 @@ var ChatStreamMapper = class {
342
342
  errorMessage: event.isError ? result?.text ?? extractText(result?.content) : void 0
343
343
  })];
344
344
  const details = asRecord(fullResult?.details);
345
+ if (toolName === "text_to_speech" && !event.isError && details) {
346
+ const audio = (Array.isArray(details.media) ? details.media : []).map(asRecord).find((item) => item?.type === "voice" || String(item?.mimeType ?? "").startsWith("audio/"));
347
+ const uri = typeof audio?.uri === "string" ? audio.uri.trim() : "";
348
+ if (uri) events.push(this.make("tts_audio", {
349
+ uri,
350
+ mimeType: typeof audio?.mimeType === "string" ? audio.mimeType : "audio/mpeg",
351
+ name: typeof audio?.name === "string" ? audio.name : "voice.mp3",
352
+ attachTo: "last_assistant",
353
+ messageId
354
+ }));
355
+ }
345
356
  if (toolName === "exec_command" && details) events.push(this.make("command_completed", {
346
357
  messageId,
347
358
  toolCallId,
@@ -14,8 +14,8 @@ import "../../../voice/stt/index.js";
14
14
  import { listSttProvidersForApi } from "../../../voice/stt/list-providers.js";
15
15
  import "../../../voice/tts/index.js";
16
16
  import { createGatewayRouteLogger } from "../lib/route-logger.js";
17
- import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
18
17
  import { listTtsProvidersForApi } from "../../../voice/tts/list-providers.js";
18
+ import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
19
19
  //#region src/gateway/hono/routes/voice.ts
20
20
  init_providers();
21
21
  const log = createGatewayRouteLogger("Voice");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.229",
3
+ "version": "0.0.230",
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",
@@ -1 +0,0 @@
1
- import{Or as e}from"./index-BNWhgmjs.js";function t(t){let{children:n,fallback:r}=t,i=r===void 0?null:r;return e()?n:i}export{t};