@ozaiya/openclaw-channel 0.3.0 → 0.5.0

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.
@@ -0,0 +1,326 @@
1
+ const URL_MATCHER = /\bhttps?:\/\/[^\s<>"'`]+/giu;
2
+ const OPTIONS_BLOCK_MATCHER = /<options>([\s\S]*?)<\/options>/giu;
3
+ const OPTION_ITEM_MATCHER = /<option>([\s\S]*?)<\/option>/giu;
4
+ const CHOICE_LIST_LINE_MATCHER = /^\s*(?:[-*]|\d+[.)])\s+(.+?)\s*$/u;
5
+ const CHOICE_PROMPT_CUE_MATCHER = /(choose|select|pick|which|option|continue|next step|want me to|请选择|选择|选项|继续|下一步|要我|想让我|哪个)/iu;
6
+ const STRUCTURED_CALLBACK_PREFIX = "oz_cb1:";
7
+ const MAX_STRUCTURED_CALLBACK_LABEL_LENGTH = 160;
8
+ export const MAX_AUTOMATIC_LINK_PREVIEWS = 3;
9
+ const MIN_AUTO_CHOICE_COUNT = 2;
10
+ const MAX_AUTO_CHOICE_COUNT = 6;
11
+ const MAX_AUTO_CHOICE_LABEL_LENGTH = 80;
12
+ const MAX_STANDALONE_AUTO_CHOICE_LABEL_LENGTH = 40;
13
+ const MAX_SUMMARY_TEXT_LENGTH = 240;
14
+ export function normalizeMessageText(text) {
15
+ const normalized = text?.trim();
16
+ return normalized ? normalized : undefined;
17
+ }
18
+ function normalizeUrl(value) {
19
+ const normalized = value?.trim();
20
+ if (!normalized)
21
+ return undefined;
22
+ try {
23
+ return new URL(normalized).toString();
24
+ }
25
+ catch {
26
+ return undefined;
27
+ }
28
+ }
29
+ export function trimTrailingUrlPunctuation(value) {
30
+ let trimmed = value.trim();
31
+ while (trimmed) {
32
+ const lastChar = trimmed.slice(-1);
33
+ if (".,;!?".includes(lastChar)) {
34
+ trimmed = trimmed.slice(0, -1);
35
+ continue;
36
+ }
37
+ if (lastChar === ")") {
38
+ const openParens = trimmed.match(/\(/g)?.length ?? 0;
39
+ const closeParens = trimmed.match(/\)/g)?.length ?? 0;
40
+ if (closeParens > openParens) {
41
+ trimmed = trimmed.slice(0, -1);
42
+ continue;
43
+ }
44
+ }
45
+ break;
46
+ }
47
+ return trimmed;
48
+ }
49
+ export function extractUrlsFromText(text, limit = MAX_AUTOMATIC_LINK_PREVIEWS) {
50
+ const urls = [];
51
+ const seen = new Set();
52
+ for (const match of text.matchAll(URL_MATCHER)) {
53
+ const normalizedUrl = normalizeUrl(trimTrailingUrlPunctuation(match[0]));
54
+ if (!normalizedUrl || seen.has(normalizedUrl)) {
55
+ continue;
56
+ }
57
+ seen.add(normalizedUrl);
58
+ urls.push(normalizedUrl);
59
+ if (urls.length >= limit) {
60
+ break;
61
+ }
62
+ }
63
+ return urls;
64
+ }
65
+ function summarizeText(value) {
66
+ const normalized = normalizeMessageText(value);
67
+ if (!normalized)
68
+ return undefined;
69
+ if (normalized.length <= MAX_SUMMARY_TEXT_LENGTH) {
70
+ return normalized;
71
+ }
72
+ return `${normalized.slice(0, MAX_SUMMARY_TEXT_LENGTH - 3)}...`;
73
+ }
74
+ function encodeStructuredCallbackData(payload) {
75
+ return `${STRUCTURED_CALLBACK_PREFIX}${Buffer.from(JSON.stringify(payload), "utf8").toString("base64url")}`;
76
+ }
77
+ function buildDefaultCallbackData(label, indexRef) {
78
+ indexRef.current += 1;
79
+ return label.length <= MAX_STRUCTURED_CALLBACK_LABEL_LENGTH
80
+ ? encodeStructuredCallbackData({ kind: "option", label, index: indexRef.current })
81
+ : label;
82
+ }
83
+ export function parseStructuredCallbackData(callbackData) {
84
+ if (!callbackData.startsWith(STRUCTURED_CALLBACK_PREFIX)) {
85
+ return null;
86
+ }
87
+ try {
88
+ const decoded = Buffer.from(callbackData.slice(STRUCTURED_CALLBACK_PREFIX.length), "base64url").toString("utf8");
89
+ const parsed = JSON.parse(decoded);
90
+ if (parsed.kind !== "option") {
91
+ return null;
92
+ }
93
+ const label = normalizeMessageText(typeof parsed.label === "string" ? parsed.label : undefined);
94
+ const index = Number(parsed.index);
95
+ if (!label || !Number.isInteger(index) || index < 1) {
96
+ return null;
97
+ }
98
+ return { kind: "option", label, index };
99
+ }
100
+ catch {
101
+ return null;
102
+ }
103
+ }
104
+ function formatCallbackDataForSummary(button) {
105
+ const structured = parseStructuredCallbackData(button.callbackData);
106
+ if (!structured) {
107
+ return `"${button.text}" => ${button.callbackData}`;
108
+ }
109
+ if (structured.label === button.text) {
110
+ return `"${button.text}"`;
111
+ }
112
+ return `"${button.text}" => option("${structured.label}")`;
113
+ }
114
+ export function normalizeLinkPreviews(previews) {
115
+ if (!Array.isArray(previews)) {
116
+ return [];
117
+ }
118
+ const normalized = [];
119
+ const seenUrls = new Set();
120
+ for (const preview of previews) {
121
+ const url = normalizeUrl(preview?.url);
122
+ if (!url || seenUrls.has(url)) {
123
+ continue;
124
+ }
125
+ seenUrls.add(url);
126
+ normalized.push({
127
+ url,
128
+ title: normalizeMessageText(preview.title),
129
+ description: summarizeText(preview.description),
130
+ image: preview.image?.trim() || undefined,
131
+ siteName: normalizeMessageText(preview.siteName),
132
+ });
133
+ }
134
+ return normalized;
135
+ }
136
+ function formatLinkPreviewLine(preview, index, opts = {}) {
137
+ const { includeUrls = true } = opts;
138
+ const labelParts = [preview.title ? `"${preview.title}"` : null, preview.siteName ? `site ${preview.siteName}` : null]
139
+ .filter((value) => Boolean(value));
140
+ const lines = [`- [${index + 1}] ${labelParts.join(" | ") || "preview"}`];
141
+ if (includeUrls) {
142
+ lines.push(` url=${preview.url}`);
143
+ }
144
+ if (preview.description) {
145
+ lines.push(` description=${preview.description}`);
146
+ }
147
+ if (preview.image) {
148
+ lines.push(` image=${preview.image}`);
149
+ }
150
+ return lines.join("\n");
151
+ }
152
+ export function buildLinkPreviewSummary(previews, opts = {}) {
153
+ const normalized = normalizeLinkPreviews(previews);
154
+ if (normalized.length === 0)
155
+ return undefined;
156
+ return [
157
+ "[Link Previews]",
158
+ ...normalized.map((preview, index) => formatLinkPreviewLine(preview, index, opts)),
159
+ ].join("\n");
160
+ }
161
+ export function normalizeInlineKeyboardRows(inlineKeyboard) {
162
+ return Array.isArray(inlineKeyboard?.rows)
163
+ ? inlineKeyboard.rows
164
+ .map((row) => Array.isArray(row)
165
+ ? row
166
+ .map((button) => ({
167
+ text: button?.text?.trim() ?? "",
168
+ callbackData: button?.callbackData?.trim() ?? "",
169
+ }))
170
+ .filter((button) => button.text && button.callbackData)
171
+ : [])
172
+ .filter((row) => row.length > 0)
173
+ : [];
174
+ }
175
+ export function buildInlineKeyboardSummary(inlineKeyboard) {
176
+ const rows = normalizeInlineKeyboardRows(inlineKeyboard);
177
+ if (rows.length === 0)
178
+ return undefined;
179
+ return [
180
+ "[Inline Buttons]",
181
+ ...rows.map((row, rowIndex) => `- row ${rowIndex + 1}: ${row.map((button) => formatCallbackDataForSummary(button)).join(" | ")}`),
182
+ ].join("\n");
183
+ }
184
+ export function buildOptionInlineKeyboardRows(options, indexRef = { current: 0 }) {
185
+ return options
186
+ .map((option) => normalizeMessageText(option))
187
+ .filter((option) => Boolean(option))
188
+ .map((option) => [{
189
+ text: option,
190
+ callbackData: buildDefaultCallbackData(option, indexRef),
191
+ }]);
192
+ }
193
+ function normalizeLooseButtonRow(row, indexRef) {
194
+ return row
195
+ .map((button) => {
196
+ if (typeof button === "string") {
197
+ const text = normalizeMessageText(button);
198
+ return text ? { text, callbackData: buildDefaultCallbackData(text, indexRef) } : null;
199
+ }
200
+ const text = normalizeMessageText(typeof button === "object" && button && "text" in button && typeof button.text === "string"
201
+ ? button.text
202
+ : undefined);
203
+ if (!text) {
204
+ return null;
205
+ }
206
+ const callbackData = normalizeMessageText(typeof button === "object" && button && "callbackData" in button && typeof button.callbackData === "string"
207
+ ? button.callbackData
208
+ : undefined) ?? buildDefaultCallbackData(text, indexRef);
209
+ return {
210
+ text,
211
+ callbackData,
212
+ };
213
+ })
214
+ .filter((button) => Boolean(button));
215
+ }
216
+ export function normalizeToolInlineKeyboardRows(params) {
217
+ const indexRef = { current: 0 };
218
+ const optionRows = Array.isArray(params.options)
219
+ ? buildOptionInlineKeyboardRows(params.options.filter((option) => typeof option === "string"), indexRef)
220
+ : [];
221
+ if (!Array.isArray(params.buttons) || params.buttons.length === 0) {
222
+ return optionRows;
223
+ }
224
+ const rows = params.buttons
225
+ .map((entry) => Array.isArray(entry)
226
+ ? normalizeLooseButtonRow(entry, indexRef)
227
+ : normalizeLooseButtonRow([entry], indexRef))
228
+ .filter((row) => row.length > 0);
229
+ return rows.length > 0 ? rows : optionRows;
230
+ }
231
+ function getLastNonEmptyLine(lines) {
232
+ for (let index = lines.length - 1; index >= 0; index -= 1) {
233
+ const line = normalizeMessageText(lines[index]);
234
+ if (line) {
235
+ return line;
236
+ }
237
+ }
238
+ return undefined;
239
+ }
240
+ function shouldAutoConvertChoiceList(options, prefixText) {
241
+ if (options.length < MIN_AUTO_CHOICE_COUNT || options.length > MAX_AUTO_CHOICE_COUNT) {
242
+ return false;
243
+ }
244
+ if (options.some((option) => option.length > MAX_AUTO_CHOICE_LABEL_LENGTH)) {
245
+ return false;
246
+ }
247
+ if (!prefixText) {
248
+ return options.length <= 4 && options.every((option) => option.length <= MAX_STANDALONE_AUTO_CHOICE_LABEL_LENGTH);
249
+ }
250
+ const lastPrefixLine = getLastNonEmptyLine(prefixText.split("\n"));
251
+ if (!lastPrefixLine) {
252
+ return false;
253
+ }
254
+ return CHOICE_PROMPT_CUE_MATCHER.test(lastPrefixLine) || /[??]$/.test(lastPrefixLine);
255
+ }
256
+ export function stripTrailingChoiceList(text) {
257
+ const lines = text.split("\n");
258
+ let endIndex = lines.length - 1;
259
+ while (endIndex >= 0 && lines[endIndex]?.trim() === "") {
260
+ endIndex -= 1;
261
+ }
262
+ if (endIndex < 0) {
263
+ return { text: undefined, rows: [] };
264
+ }
265
+ const optionLines = [];
266
+ let scanIndex = endIndex;
267
+ while (scanIndex >= 0) {
268
+ const line = lines[scanIndex] ?? "";
269
+ if (line.trim() === "") {
270
+ if (optionLines.length === 0) {
271
+ scanIndex -= 1;
272
+ continue;
273
+ }
274
+ break;
275
+ }
276
+ const match = line.match(CHOICE_LIST_LINE_MATCHER);
277
+ if (!match) {
278
+ break;
279
+ }
280
+ optionLines.unshift(match[1]);
281
+ scanIndex -= 1;
282
+ }
283
+ if (optionLines.length === 0) {
284
+ return { text, rows: [] };
285
+ }
286
+ const prefixText = normalizeMessageText(lines.slice(0, scanIndex + 1).join("\n"));
287
+ const options = optionLines
288
+ .map((line) => normalizeMessageText(line))
289
+ .filter((line) => Boolean(line));
290
+ if (options.length !== optionLines.length || !shouldAutoConvertChoiceList(options, prefixText)) {
291
+ return { text, rows: [] };
292
+ }
293
+ return {
294
+ text: prefixText,
295
+ rows: buildOptionInlineKeyboardRows(options),
296
+ };
297
+ }
298
+ export function stripOptionBlocks(text) {
299
+ let hasParsedBlock = false;
300
+ const indexRef = { current: 0 };
301
+ const rows = [];
302
+ const stripped = text.replace(OPTIONS_BLOCK_MATCHER, (fullMatch, blockContent) => {
303
+ const items = [...blockContent.matchAll(OPTION_ITEM_MATCHER)]
304
+ .map((match) => normalizeMessageText(match[1]))
305
+ .filter((item) => Boolean(item));
306
+ if (items.length === 0) {
307
+ return fullMatch;
308
+ }
309
+ hasParsedBlock = true;
310
+ rows.push(...buildOptionInlineKeyboardRows(items, indexRef));
311
+ return "";
312
+ });
313
+ if (!hasParsedBlock) {
314
+ return { text, rows: [] };
315
+ }
316
+ const normalizedText = stripped
317
+ .split("\n")
318
+ .map((line) => line.trimEnd())
319
+ .join("\n")
320
+ .replace(/\n{3,}/g, "\n\n");
321
+ return {
322
+ text: normalizeMessageText(normalizedText),
323
+ rows,
324
+ };
325
+ }
326
+ //# sourceMappingURL=richContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"richContent.js","sourceRoot":"","sources":["../../src/richContent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { OzaiyaAccountConfig, OzaiyaChannelConfig, ResolvedOzaiyaSttConfig } from "./types.js";
2
+ export type StagedAudioAttachment = {
3
+ kind: "audio";
4
+ name: string;
5
+ mime: string;
6
+ duration: number | null;
7
+ stagedPath: string;
8
+ url: string;
9
+ };
10
+ export type AudioTranscriptionResult = {
11
+ transcript: string;
12
+ source: "openai" | "local-command";
13
+ attachment: StagedAudioAttachment;
14
+ };
15
+ export declare function resolveOzaiyaSttConfig(channelConfig: OzaiyaChannelConfig | null | undefined, accountConfig?: OzaiyaAccountConfig | null): ResolvedOzaiyaSttConfig;
16
+ export declare function selectInboundAudioForTranscription(params: {
17
+ stt: ResolvedOzaiyaSttConfig;
18
+ messageText?: string;
19
+ stagedAttachments: Array<{
20
+ kind: string;
21
+ name: string;
22
+ mime: string;
23
+ duration: number | null;
24
+ stagedPath: string;
25
+ url: string;
26
+ }>;
27
+ }): StagedAudioAttachment | null;
28
+ export declare function maybeTranscribeInboundAudio(params: {
29
+ stt: ResolvedOzaiyaSttConfig;
30
+ messageText?: string;
31
+ stagedAttachments: Array<{
32
+ kind: string;
33
+ name: string;
34
+ mime: string;
35
+ duration: number | null;
36
+ stagedPath: string;
37
+ url: string;
38
+ }>;
39
+ log?: {
40
+ info?: (message: string) => void;
41
+ warn?: (message: string) => void;
42
+ };
43
+ }): Promise<AudioTranscriptionResult | null>;
44
+ export declare function buildVoiceTranscriptSection(transcript: string | undefined): string | undefined;
45
+ export declare function prependVoiceTranscriptToAgentInput(agentInput: string | undefined, transcript: string | undefined): string | undefined;
@@ -0,0 +1,241 @@
1
+ import { spawn } from "node:child_process";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { normalizeMessageText } from "./richContent.js";
5
+ const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
6
+ const DEFAULT_OPENAI_STT_MODEL = "gpt-4o-mini-transcribe";
7
+ const DEFAULT_STT_TIMEOUT_MS = 20_000;
8
+ const DEFAULT_STT_MAX_DURATION_SECONDS = 180;
9
+ function resolvePositiveInteger(value) {
10
+ if (typeof value !== "number" || !Number.isFinite(value))
11
+ return undefined;
12
+ const rounded = Math.round(value);
13
+ return rounded > 0 ? rounded : undefined;
14
+ }
15
+ function resolveMaxDurationSeconds(value) {
16
+ if (value === null)
17
+ return null;
18
+ return resolvePositiveInteger(value);
19
+ }
20
+ function resolveStringRecord(value) {
21
+ if (!value)
22
+ return undefined;
23
+ const entries = Object.entries(value)
24
+ .map(([key, entryValue]) => [key.trim(), entryValue.trim()])
25
+ .filter(([key, entryValue]) => key && entryValue);
26
+ return entries.length > 0 ? Object.fromEntries(entries) : undefined;
27
+ }
28
+ export function resolveOzaiyaSttConfig(channelConfig, accountConfig) {
29
+ const shared = channelConfig?.stt;
30
+ const scoped = accountConfig?.stt;
31
+ const mode = scoped?.mode ?? shared?.mode ?? "disabled";
32
+ return {
33
+ mode,
34
+ timeoutMs: resolvePositiveInteger(scoped?.timeoutMs)
35
+ ?? resolvePositiveInteger(shared?.timeoutMs)
36
+ ?? DEFAULT_STT_TIMEOUT_MS,
37
+ maxDurationSeconds: resolveMaxDurationSeconds(scoped?.maxDurationSeconds)
38
+ ?? resolveMaxDurationSeconds(shared?.maxDurationSeconds)
39
+ ?? DEFAULT_STT_MAX_DURATION_SECONDS,
40
+ openai: {
41
+ apiKey: scoped?.openai?.apiKey?.trim()
42
+ || shared?.openai?.apiKey?.trim()
43
+ || process.env.OPENAI_API_KEY?.trim()
44
+ || undefined,
45
+ baseUrl: scoped?.openai?.baseUrl?.trim()
46
+ || shared?.openai?.baseUrl?.trim()
47
+ || process.env.OPENAI_BASE_URL?.trim()
48
+ || DEFAULT_OPENAI_BASE_URL,
49
+ model: scoped?.openai?.model?.trim()
50
+ || shared?.openai?.model?.trim()
51
+ || DEFAULT_OPENAI_STT_MODEL,
52
+ organization: scoped?.openai?.organization?.trim()
53
+ || shared?.openai?.organization?.trim()
54
+ || process.env.OPENAI_ORGANIZATION?.trim()
55
+ || undefined,
56
+ project: scoped?.openai?.project?.trim()
57
+ || shared?.openai?.project?.trim()
58
+ || process.env.OPENAI_PROJECT?.trim()
59
+ || undefined,
60
+ },
61
+ localCommand: {
62
+ command: scoped?.localCommand?.command?.trim()
63
+ || shared?.localCommand?.command?.trim()
64
+ || undefined,
65
+ args: (scoped?.localCommand?.args ?? shared?.localCommand?.args ?? [])
66
+ .map((entry) => entry.trim())
67
+ .filter(Boolean),
68
+ cwd: scoped?.localCommand?.cwd?.trim()
69
+ || shared?.localCommand?.cwd?.trim()
70
+ || undefined,
71
+ env: resolveStringRecord(scoped?.localCommand?.env)
72
+ ?? resolveStringRecord(shared?.localCommand?.env),
73
+ },
74
+ };
75
+ }
76
+ export function selectInboundAudioForTranscription(params) {
77
+ const { stt, messageText, stagedAttachments } = params;
78
+ if (stt.mode === "disabled")
79
+ return null;
80
+ if (normalizeMessageText(messageText))
81
+ return null;
82
+ const audio = stagedAttachments.find((attachment) => attachment.kind === "audio");
83
+ if (!audio)
84
+ return null;
85
+ if (stt.maxDurationSeconds != null
86
+ && typeof audio.duration === "number"
87
+ && Number.isFinite(audio.duration)
88
+ && audio.duration > stt.maxDurationSeconds) {
89
+ return null;
90
+ }
91
+ return {
92
+ kind: "audio",
93
+ name: audio.name,
94
+ mime: audio.mime,
95
+ duration: audio.duration,
96
+ stagedPath: audio.stagedPath,
97
+ url: audio.url,
98
+ };
99
+ }
100
+ function interpolateTemplate(value, attachment) {
101
+ const fileName = attachment.name || path.basename(attachment.stagedPath);
102
+ return value
103
+ .replaceAll("{input}", attachment.stagedPath)
104
+ .replaceAll("{mime}", attachment.mime)
105
+ .replaceAll("{filename}", fileName)
106
+ .replaceAll("{url}", attachment.url);
107
+ }
108
+ async function transcribeWithOpenAI(attachment, stt) {
109
+ const apiKey = stt.openai.apiKey;
110
+ if (!apiKey) {
111
+ throw new Error("stt.openai.apiKey or OPENAI_API_KEY is required for mode=openai");
112
+ }
113
+ const audioBuffer = await fs.readFile(attachment.stagedPath);
114
+ const form = new FormData();
115
+ form.set("file", new Blob([audioBuffer], { type: attachment.mime || "application/octet-stream" }), attachment.name || path.basename(attachment.stagedPath) || "audio");
116
+ form.set("model", stt.openai.model);
117
+ const headers = {
118
+ Authorization: `Bearer ${apiKey}`,
119
+ };
120
+ if (stt.openai.organization) {
121
+ headers["OpenAI-Organization"] = stt.openai.organization;
122
+ }
123
+ if (stt.openai.project) {
124
+ headers["OpenAI-Project"] = stt.openai.project;
125
+ }
126
+ const response = await fetch(`${stt.openai.baseUrl.replace(/\/+$/, "")}/audio/transcriptions`, {
127
+ method: "POST",
128
+ headers,
129
+ body: form,
130
+ signal: AbortSignal.timeout(stt.timeoutMs),
131
+ });
132
+ if (!response.ok) {
133
+ throw new Error(`OpenAI STT failed with HTTP ${response.status}`);
134
+ }
135
+ const payload = await response.json();
136
+ const transcript = normalizeMessageText(typeof payload.text === "string" ? payload.text : undefined);
137
+ if (!transcript) {
138
+ throw new Error("OpenAI STT returned empty transcript");
139
+ }
140
+ return transcript;
141
+ }
142
+ async function transcribeWithLocalCommand(attachment, stt) {
143
+ const command = stt.localCommand.command;
144
+ if (!command) {
145
+ throw new Error("stt.localCommand.command is required for mode=local-command");
146
+ }
147
+ const rawArgs = stt.localCommand.args.map((entry) => interpolateTemplate(entry, attachment));
148
+ const args = rawArgs.some((entry) => entry.includes(attachment.stagedPath))
149
+ ? rawArgs
150
+ : [...rawArgs, attachment.stagedPath];
151
+ const env = {
152
+ ...process.env,
153
+ ...(stt.localCommand.env
154
+ ? Object.fromEntries(Object.entries(stt.localCommand.env).map(([key, value]) => [key, interpolateTemplate(value, attachment)]))
155
+ : {}),
156
+ };
157
+ const transcript = await new Promise((resolve, reject) => {
158
+ const child = spawn(command, args, {
159
+ cwd: stt.localCommand.cwd,
160
+ env,
161
+ stdio: ["ignore", "pipe", "pipe"],
162
+ });
163
+ let stdout = "";
164
+ let stderr = "";
165
+ let settled = false;
166
+ const timeout = setTimeout(() => {
167
+ if (settled)
168
+ return;
169
+ settled = true;
170
+ child.kill("SIGKILL");
171
+ reject(new Error(`local STT command timed out after ${stt.timeoutMs}ms`));
172
+ }, stt.timeoutMs);
173
+ child.stdout.on("data", (chunk) => {
174
+ stdout += chunk.toString();
175
+ });
176
+ child.stderr.on("data", (chunk) => {
177
+ stderr += chunk.toString();
178
+ });
179
+ child.on("error", (err) => {
180
+ if (settled)
181
+ return;
182
+ settled = true;
183
+ clearTimeout(timeout);
184
+ reject(err);
185
+ });
186
+ child.on("close", (code) => {
187
+ if (settled)
188
+ return;
189
+ settled = true;
190
+ clearTimeout(timeout);
191
+ if (code !== 0) {
192
+ reject(new Error(`local STT command exited with code ${code}${stderr.trim() ? `: ${stderr.trim()}` : ""}`));
193
+ return;
194
+ }
195
+ const normalized = normalizeMessageText(stdout);
196
+ if (!normalized) {
197
+ reject(new Error(`local STT command returned empty transcript${stderr.trim() ? `: ${stderr.trim()}` : ""}`));
198
+ return;
199
+ }
200
+ resolve(normalized);
201
+ });
202
+ });
203
+ return transcript;
204
+ }
205
+ export async function maybeTranscribeInboundAudio(params) {
206
+ const { stt, messageText, stagedAttachments, log } = params;
207
+ const attachment = selectInboundAudioForTranscription({
208
+ stt,
209
+ messageText,
210
+ stagedAttachments,
211
+ });
212
+ if (!attachment)
213
+ return null;
214
+ try {
215
+ const source = stt.mode === "openai" ? "openai" : "local-command";
216
+ const transcript = source === "openai"
217
+ ? await transcribeWithOpenAI(attachment, stt)
218
+ : await transcribeWithLocalCommand(attachment, stt);
219
+ log?.info?.(`ozaiya: transcribed inbound audio "${attachment.name}" via ${source}`);
220
+ return {
221
+ transcript,
222
+ source,
223
+ attachment,
224
+ };
225
+ }
226
+ catch (err) {
227
+ log?.warn?.(`ozaiya: failed to transcribe inbound audio "${attachment.name}" via ${stt.mode}: ${err instanceof Error ? err.message : String(err)}`);
228
+ return null;
229
+ }
230
+ }
231
+ export function buildVoiceTranscriptSection(transcript) {
232
+ const normalized = normalizeMessageText(transcript);
233
+ return normalized ? `[Voice Transcript]\n${normalized}` : undefined;
234
+ }
235
+ export function prependVoiceTranscriptToAgentInput(agentInput, transcript) {
236
+ const transcriptSection = buildVoiceTranscriptSection(transcript);
237
+ if (!transcriptSection)
238
+ return agentInput;
239
+ return agentInput ? `${transcriptSection}\n\n${agentInput}` : transcriptSection;
240
+ }
241
+ //# sourceMappingURL=transcribeAudio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcribeAudio.js","sourceRoot":"","sources":["../../src/transcribeAudio.ts"],"names":[],"mappings":"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"}