crewly 1.20.213 → 1.20.214

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 (34) hide show
  1. package/dist/backend/backend/src/constants.d.ts +67 -0
  2. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  3. package/dist/backend/backend/src/constants.js +77 -0
  4. package/dist/backend/backend/src/constants.js.map +1 -1
  5. package/dist/backend/backend/src/controllers/talk/talk-transcribe.controller.d.ts +37 -0
  6. package/dist/backend/backend/src/controllers/talk/talk-transcribe.controller.d.ts.map +1 -0
  7. package/dist/backend/backend/src/controllers/talk/talk-transcribe.controller.js +97 -0
  8. package/dist/backend/backend/src/controllers/talk/talk-transcribe.controller.js.map +1 -0
  9. package/dist/backend/backend/src/controllers/talk/talk-transcribe.routes.d.ts +18 -0
  10. package/dist/backend/backend/src/controllers/talk/talk-transcribe.routes.d.ts.map +1 -0
  11. package/dist/backend/backend/src/controllers/talk/talk-transcribe.routes.js +25 -0
  12. package/dist/backend/backend/src/controllers/talk/talk-transcribe.routes.js.map +1 -0
  13. package/dist/backend/backend/src/index.d.ts.map +1 -1
  14. package/dist/backend/backend/src/index.js +6 -4
  15. package/dist/backend/backend/src/index.js.map +1 -1
  16. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  17. package/dist/backend/backend/src/routes/api.routes.js +4 -0
  18. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  19. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
  20. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +6 -0
  21. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
  22. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  23. package/dist/backend/backend/src/services/slack/slack-initializer.js +2 -1
  24. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  25. package/dist/backend/backend/src/services/talk/talk-transcribe.service.d.ts +344 -0
  26. package/dist/backend/backend/src/services/talk/talk-transcribe.service.d.ts.map +1 -0
  27. package/dist/backend/backend/src/services/talk/talk-transcribe.service.js +642 -0
  28. package/dist/backend/backend/src/services/talk/talk-transcribe.service.js.map +1 -0
  29. package/dist/backend/build-info.json +2 -2
  30. package/dist/cli/backend/src/constants.d.ts +67 -0
  31. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  32. package/dist/cli/backend/src/constants.js +77 -0
  33. package/dist/cli/backend/src/constants.js.map +1 -1
  34. package/package.json +1 -1
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Talk transcription — speech-to-text for the portal Talk page on the
3
+ * owner's own machine (specs/2026-10-04-talk-whisper-transcribe.md, #1074).
4
+ *
5
+ * The phone records a short clip and sends it over the relay to the machine
6
+ * of the agent being talked to; this service turns it into text with
7
+ * whisper.cpp and hands the text back. It never sends anything to an agent:
8
+ * the owner reads, edits and confirms the text on the phone first.
9
+ *
10
+ * Engine: the `transcribe-audio` skill's — same `whisper-cli` lookup order,
11
+ * same large-v3-turbo model file, same ffmpeg normalisation to 16 kHz mono
12
+ * WAV. Its setup block is what installs the pieces ({@link startSetup}).
13
+ *
14
+ * Properties:
15
+ * - **One at a time.** whisper uses most of the CPU; requests queue behind
16
+ * the running one (at most {@link TALK_TRANSCRIBE_CONSTANTS.MAX_QUEUE}
17
+ * waiting) and share one deadline that includes the wait.
18
+ * - **Nothing kept.** Audio is written to a private temp dir that is removed
19
+ * in `finally`; neither audio nor transcript is ever logged.
20
+ * - **Clear failures.** Every refusal carries a code the phone acts on by
21
+ * falling back to on-device recognition: `whisper_unavailable`,
22
+ * `too_long`, `timeout`, `failed` (and `busy`, `invalid_audio`).
23
+ *
24
+ * @module services/talk/talk-transcribe.service
25
+ */
26
+ import { type ComponentLogger } from '../core/logger.service.js';
27
+ import type { RunCommand } from '../harness/harness.types.js';
28
+ declare const C: {
29
+ readonly SKILL_ID: "transcribe-audio";
30
+ readonly CAPABILITY: "talk_whisper";
31
+ readonly MODEL_FILENAME: "ggml-large-v3-turbo-q5_0.bin";
32
+ readonly MODEL_DIRS: readonly [".flopost/whisper", ".cache/whisper-models"];
33
+ readonly HOME_BIN_CANDIDATES: readonly [".flopost/whisper/whisper-cli"];
34
+ readonly WHISPER_BINARY: "whisper-cli";
35
+ readonly FFMPEG_BINARY: "ffmpeg";
36
+ readonly MAX_AUDIO_BYTES: number;
37
+ readonly MAX_DURATION_SEC: 90;
38
+ readonly REQUEST_TIMEOUT_MS: 45000;
39
+ readonly MAX_QUEUE: 3;
40
+ readonly SAMPLE_RATE: 16000;
41
+ readonly WAV_BYTES_PER_SEC: 32000;
42
+ readonly WAV_HEADER_BYTES: 44;
43
+ readonly THREADS_RESERVED: 2;
44
+ readonly MIN_THREADS: 4;
45
+ readonly PROMPT_PREFIX: "以下是普通话的句子。";
46
+ readonly GLOSSARY: readonly ["Crewly", "CE", "Crewly Cloud", "Slack"];
47
+ readonly MAX_VOCAB_CHARS: 400;
48
+ readonly LANGUAGES: readonly ["auto", "zh", "en"];
49
+ readonly MIME_EXTENSIONS: Readonly<Record<string, string>>;
50
+ readonly TEMP_PREFIX: "crewly-talk-stt-";
51
+ readonly CODES: {
52
+ readonly WHISPER_UNAVAILABLE: "whisper_unavailable";
53
+ readonly TOO_LONG: "too_long";
54
+ readonly TIMEOUT: "timeout";
55
+ readonly FAILED: "failed";
56
+ readonly BUSY: "busy";
57
+ readonly INVALID_AUDIO: "invalid_audio";
58
+ readonly OWNER_ONLY: "owner_only";
59
+ };
60
+ };
61
+ /** Error code returned to the phone. */
62
+ export type TalkTranscribeCode = (typeof C.CODES)[keyof typeof C.CODES];
63
+ /** HTTP status for each refusal. */
64
+ export declare const TALK_TRANSCRIBE_HTTP_STATUS: Readonly<Record<TalkTranscribeCode, number>>;
65
+ /** A refusal with a machine-readable code. Its message never contains audio or transcript. */
66
+ export declare class TalkTranscribeError extends Error {
67
+ readonly code: TalkTranscribeCode;
68
+ /**
69
+ * @param code - What went wrong (the phone falls back on any of them)
70
+ * @param message - Short English explanation
71
+ */
72
+ constructor(code: TalkTranscribeCode, message: string);
73
+ /** HTTP status for this refusal. */
74
+ get httpStatus(): number;
75
+ }
76
+ /** Where the engine's pieces are (null = missing). */
77
+ export interface WhisperEngine {
78
+ whisperBin: string | null;
79
+ model: string | null;
80
+ ffmpeg: string | null;
81
+ }
82
+ /** The setup job started from the phone, as far as this service knows. */
83
+ export interface TalkSetupState {
84
+ state: 'running' | 'succeeded' | 'failed';
85
+ jobId?: string;
86
+ message?: string;
87
+ }
88
+ /** `GET /api/talk/transcribe/status` data. */
89
+ export interface TalkTranscribeStatus {
90
+ /** whisper-cli, the model and ffmpeg are all present */
91
+ whisperReady: boolean;
92
+ /** Missing pieces, by the skill's setup step ids (`ffmpeg`, `whisper-cli`, `whisper-model`) */
93
+ missing: string[];
94
+ /** This machine's name (for "Whisper · <machine>") */
95
+ deviceName: string;
96
+ /** A transcription is running */
97
+ busy: boolean;
98
+ /** Requests waiting behind it */
99
+ queued: number;
100
+ maxDurationSec: number;
101
+ maxAudioBytes: number;
102
+ /** Setup started from the phone, if any */
103
+ setup?: TalkSetupState;
104
+ }
105
+ /** Input to {@link TalkTranscribeService.transcribe}. */
106
+ export interface TranscribeInput {
107
+ /** Base64 audio (a `data:` URL prefix is tolerated) */
108
+ audio: unknown;
109
+ /** Container type from MediaRecorder, e.g. `audio/mp4` or `audio/webm;codecs=opus` */
110
+ mimeType: unknown;
111
+ /** `auto` (default), `zh` or `en` */
112
+ language?: unknown;
113
+ }
114
+ /** A finished transcription. */
115
+ export interface TranscribeResult {
116
+ text: string;
117
+ /** Language whisper detected (or was told) */
118
+ language: string;
119
+ durationSec: number;
120
+ engine: 'whisper.cpp';
121
+ deviceName: string;
122
+ /** Time spent, including any wait in the queue (ms) */
123
+ elapsedMs: number;
124
+ }
125
+ /** Injectable dependencies (all optional). */
126
+ export interface TalkTranscribeDeps {
127
+ run?: RunCommand;
128
+ env?: NodeJS.ProcessEnv;
129
+ homeDir?: () => string;
130
+ crewlyHome?: () => string;
131
+ isExecutable?: (file: string) => boolean;
132
+ isFile?: (file: string) => boolean;
133
+ /** Team / agent / project names for the vocabulary prompt */
134
+ vocabulary?: () => Promise<string[]>;
135
+ deviceName?: () => Promise<string>;
136
+ /** Start the transcribe-audio skill setup in the background */
137
+ startSetup?: () => Promise<TalkSetupState>;
138
+ /** Current state of a setup job */
139
+ setupJob?: (jobId: string) => Promise<TalkSetupState | null>;
140
+ tmpDir?: () => string;
141
+ cpuCount?: () => number;
142
+ now?: () => number;
143
+ logger?: ComponentLogger;
144
+ /** Overrides of the limits (tests) */
145
+ limits?: Partial<{
146
+ maxAudioBytes: number;
147
+ maxDurationSec: number;
148
+ requestTimeoutMs: number;
149
+ maxQueue: number;
150
+ }>;
151
+ }
152
+ /**
153
+ * Temp-file extension for a MediaRecorder type (`audio/webm;codecs=opus` → `webm`).
154
+ *
155
+ * @param mimeType - Container type
156
+ * @returns Extension, or null when the type is not audio we take
157
+ */
158
+ export declare function extensionForMime(mimeType: string): string | null;
159
+ /**
160
+ * Decode the base64 body, refusing anything malformed or over the size cap
161
+ * before decoding it.
162
+ *
163
+ * @param audio - Base64 string, optionally a `data:` URL
164
+ * @param maxBytes - Size cap of the decoded audio
165
+ * @returns The audio bytes
166
+ * @throws TalkTranscribeError `invalid_audio` or `too_long`
167
+ */
168
+ export declare function decodeAudio(audio: unknown, maxBytes: number): Buffer;
169
+ /**
170
+ * The initial prompt: the Simplified-Chinese bias sentence, then the owner
171
+ * glossary and this machine's team / agent / project names, so names like
172
+ * "CE" are not heard as "侧". Bounded so whisper keeps all of it.
173
+ *
174
+ * @param names - Vocabulary from this machine
175
+ * @param maxChars - Bound on the vocabulary part
176
+ * @returns Prompt text
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * buildVocabularyPrompt(['Marketing', 'Ella']);
181
+ * // '以下是普通话的句子。Crewly、CE、Crewly Cloud、Slack、Marketing、Ella。'
182
+ * ```
183
+ */
184
+ export declare function buildVocabularyPrompt(names: readonly string[], maxChars?: number): string;
185
+ /**
186
+ * Join whisper segments: a space only between two Latin-script edges, so
187
+ * Chinese stays unspaced and English words stay apart.
188
+ *
189
+ * @param segments - Segment texts
190
+ * @returns The transcript
191
+ */
192
+ export declare function joinSegments(segments: readonly string[]): string;
193
+ /** Talk speech-to-text with whisper.cpp. */
194
+ export declare class TalkTranscribeService {
195
+ private readonly run;
196
+ private readonly env;
197
+ private readonly homeDir;
198
+ private readonly crewlyHome;
199
+ private readonly isExecutable;
200
+ private readonly isFile;
201
+ private readonly vocabulary;
202
+ private readonly deviceNameFn;
203
+ private readonly startSetupFn;
204
+ private readonly setupJobFn;
205
+ private readonly tmpDir;
206
+ private readonly cpuCount;
207
+ private readonly now;
208
+ private readonly logger;
209
+ private readonly maxAudioBytes;
210
+ private readonly maxDurationSec;
211
+ private readonly requestTimeoutMs;
212
+ private readonly maxQueue;
213
+ private running;
214
+ private readonly waiters;
215
+ private lastSetup;
216
+ /**
217
+ * @param deps - Injectable dependencies
218
+ */
219
+ constructor(deps?: TalkTranscribeDeps);
220
+ /**
221
+ * PATH searched for commands: `$CREWLY_HOME/bin`, the process PATH, then
222
+ * the usual system and Homebrew dirs (a backend started by launchd often
223
+ * lacks /opt/homebrew/bin) — the skill setup runner's search path.
224
+ *
225
+ * @returns PATH string
226
+ */
227
+ private searchPath;
228
+ /**
229
+ * Find whisper-cli, the model and ffmpeg. Checked on every call (cheap
230
+ * file checks), so a finished setup is seen at once.
231
+ *
232
+ * Order, as in `transcribe-audio/execute.sh`: `FLOPOST_WHISPER_BIN`,
233
+ * `~/.flopost/whisper/whisper-cli`, `$CREWLY_HOME/bin`, PATH, Homebrew;
234
+ * model: `FLOPOST_WHISPER_MODEL`, `~/.flopost/whisper/`, `~/.cache/whisper-models/`.
235
+ *
236
+ * @returns Paths (null = missing)
237
+ */
238
+ resolveEngine(): WhisperEngine;
239
+ /**
240
+ * Missing pieces, named by the skill's setup step ids.
241
+ *
242
+ * @param engine - Resolved engine
243
+ * @returns e.g. `['whisper-model']`
244
+ */
245
+ private missingParts;
246
+ /**
247
+ * Whether a transcription can run here now.
248
+ *
249
+ * @returns True when whisper-cli, the model and ffmpeg are present
250
+ */
251
+ isReady(): boolean;
252
+ /**
253
+ * Capabilities for the Cloud heartbeat: `talk_whisper` while ready.
254
+ *
255
+ * @returns Capability list
256
+ */
257
+ capabilities(): string[];
258
+ /**
259
+ * This machine's name, never failing.
260
+ *
261
+ * @returns Device name
262
+ */
263
+ private deviceName;
264
+ /**
265
+ * Status for the phone: ready or not, what is missing, queue, setup.
266
+ *
267
+ * @returns Status
268
+ */
269
+ getStatus(): Promise<TalkTranscribeStatus>;
270
+ /**
271
+ * The last setup job, refreshed from the job service.
272
+ *
273
+ * @returns State, or null when none was started here
274
+ */
275
+ private currentSetup;
276
+ /**
277
+ * Install ffmpeg, whisper-cli and the model with the transcribe-audio
278
+ * skill's setup block, in the background (unattended; the skill is
279
+ * official). Returns at once.
280
+ *
281
+ * @returns The setup state (`succeeded` when everything was already there)
282
+ * @throws TalkTranscribeError `failed` when setup cannot be started
283
+ */
284
+ startSetup(): Promise<TalkSetupState>;
285
+ /**
286
+ * Take the one-at-a-time slot, waiting until `deadline` at most.
287
+ *
288
+ * @param deadline - Absolute ms
289
+ * @throws TalkTranscribeError `busy` (queue full) or `timeout`
290
+ */
291
+ private acquire;
292
+ /** Hand the slot to the next waiter, or free it. */
293
+ private release;
294
+ /**
295
+ * Transcribe one clip.
296
+ *
297
+ * Validation (type, size, engine present) happens before queueing; the
298
+ * deadline covers the wait, ffmpeg and whisper. Temp files are removed in
299
+ * `finally`. Logs carry only sizes, durations and codes.
300
+ *
301
+ * @param input - Base64 audio, container type, language hint
302
+ * @returns The transcript
303
+ * @throws TalkTranscribeError with a code the phone falls back on
304
+ *
305
+ * @example
306
+ * ```ts
307
+ * const r = await svc.transcribe({ audio: b64, mimeType: 'audio/mp4' });
308
+ * // { text: '帮我看一下 CE 的网站', language: 'zh', durationSec: 3.2, ... }
309
+ * ```
310
+ */
311
+ transcribe(input: TranscribeInput): Promise<TranscribeResult>;
312
+ /**
313
+ * ffmpeg → WAV, duration check, whisper-cli → JSON → text.
314
+ *
315
+ * @param engine - Resolved paths (all present)
316
+ * @param workDir - Private temp dir
317
+ * @param bytes - Encoded audio
318
+ * @param ext - Input extension
319
+ * @param language - `auto` / `zh` / `en`
320
+ * @param deadline - Absolute ms
321
+ * @returns Text, language, duration
322
+ */
323
+ private runEngine;
324
+ }
325
+ /**
326
+ * The process-wide service, created with the default dependencies on first use.
327
+ *
328
+ * @returns The service
329
+ */
330
+ export declare function getTalkTranscribeService(): TalkTranscribeService;
331
+ /**
332
+ * Replace the process-wide service (tests; null resets).
333
+ *
334
+ * @param service - Service or null
335
+ */
336
+ export declare function setTalkTranscribeService(service: TalkTranscribeService | null): void;
337
+ /**
338
+ * Capabilities for the Cloud heartbeat (`talk_whisper` while Whisper is ready).
339
+ *
340
+ * @returns Capability list
341
+ */
342
+ export declare function talkTranscribeCapabilities(): string[];
343
+ export {};
344
+ //# sourceMappingURL=talk-transcribe.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"talk-transcribe.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/talk/talk-transcribe.service.ts"],"names":[],"mappings":"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"}