@spinabot/brigade 1.11.2 → 1.13.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.
Files changed (79) hide show
  1. package/README.md +56 -0
  2. package/dist/agents/tools/edge-tts.d.ts +44 -0
  3. package/dist/agents/tools/edge-tts.d.ts.map +1 -0
  4. package/dist/agents/tools/edge-tts.js +142 -0
  5. package/dist/agents/tools/edge-tts.js.map +1 -0
  6. package/dist/agents/tools/generate-music-tool.d.ts +61 -0
  7. package/dist/agents/tools/generate-music-tool.d.ts.map +1 -0
  8. package/dist/agents/tools/generate-music-tool.js +286 -0
  9. package/dist/agents/tools/generate-music-tool.js.map +1 -0
  10. package/dist/agents/tools/generate-speech-tool.d.ts +69 -0
  11. package/dist/agents/tools/generate-speech-tool.d.ts.map +1 -0
  12. package/dist/agents/tools/generate-speech-tool.js +331 -0
  13. package/dist/agents/tools/generate-speech-tool.js.map +1 -0
  14. package/dist/agents/tools/generate-video-tool.d.ts +111 -0
  15. package/dist/agents/tools/generate-video-tool.d.ts.map +1 -0
  16. package/dist/agents/tools/generate-video-tool.js +1028 -0
  17. package/dist/agents/tools/generate-video-tool.js.map +1 -0
  18. package/dist/agents/tools/media-command.d.ts +47 -0
  19. package/dist/agents/tools/media-command.d.ts.map +1 -0
  20. package/dist/agents/tools/media-command.js +93 -0
  21. package/dist/agents/tools/media-command.js.map +1 -0
  22. package/dist/agents/tools/registry.d.ts.map +1 -1
  23. package/dist/agents/tools/registry.js +27 -0
  24. package/dist/agents/tools/registry.js.map +1 -1
  25. package/dist/agents/tools/transcribe-audio-tool.d.ts +96 -0
  26. package/dist/agents/tools/transcribe-audio-tool.d.ts.map +1 -0
  27. package/dist/agents/tools/transcribe-audio-tool.js +577 -0
  28. package/dist/agents/tools/transcribe-audio-tool.js.map +1 -0
  29. package/dist/buildstamp.json +1 -1
  30. package/dist/cli/commands/connect.d.ts +6 -0
  31. package/dist/cli/commands/connect.d.ts.map +1 -1
  32. package/dist/cli/commands/connect.js +7 -0
  33. package/dist/cli/commands/connect.js.map +1 -1
  34. package/dist/cli/commands/doctor.d.ts.map +1 -1
  35. package/dist/cli/commands/doctor.js +2 -1
  36. package/dist/cli/commands/doctor.js.map +1 -1
  37. package/dist/cli/commands/expose.d.ts.map +1 -1
  38. package/dist/cli/commands/expose.js +22 -3
  39. package/dist/cli/commands/expose.js.map +1 -1
  40. package/dist/cli/commands/gateway.d.ts +12 -0
  41. package/dist/cli/commands/gateway.d.ts.map +1 -1
  42. package/dist/cli/commands/gateway.js +114 -2
  43. package/dist/cli/commands/gateway.js.map +1 -1
  44. package/dist/cli/commands/status.d.ts.map +1 -1
  45. package/dist/cli/commands/status.js +2 -1
  46. package/dist/cli/commands/status.js.map +1 -1
  47. package/dist/cli/program/build-program.d.ts.map +1 -1
  48. package/dist/cli/program/build-program.js +36 -0
  49. package/dist/cli/program/build-program.js.map +1 -1
  50. package/dist/config/io.d.ts +13 -0
  51. package/dist/config/io.d.ts.map +1 -1
  52. package/dist/config/io.js.map +1 -1
  53. package/dist/core/gateway-auth.d.ts +86 -0
  54. package/dist/core/gateway-auth.d.ts.map +1 -0
  55. package/dist/core/gateway-auth.js +156 -0
  56. package/dist/core/gateway-auth.js.map +1 -0
  57. package/dist/core/gateway-probe.d.ts +5 -0
  58. package/dist/core/gateway-probe.d.ts.map +1 -1
  59. package/dist/core/gateway-probe.js +2 -1
  60. package/dist/core/gateway-probe.js.map +1 -1
  61. package/dist/core/gateway-spawn.d.ts.map +1 -1
  62. package/dist/core/gateway-spawn.js +5 -2
  63. package/dist/core/gateway-spawn.js.map +1 -1
  64. package/dist/core/server.d.ts.map +1 -1
  65. package/dist/core/server.js +21 -1
  66. package/dist/core/server.js.map +1 -1
  67. package/dist/core/tunnel/auth-proxy.d.ts +3 -2
  68. package/dist/core/tunnel/auth-proxy.d.ts.map +1 -1
  69. package/dist/core/tunnel/auth-proxy.js +8 -34
  70. package/dist/core/tunnel/auth-proxy.js.map +1 -1
  71. package/dist/core/tunnel/manager.d.ts +4 -2
  72. package/dist/core/tunnel/manager.d.ts.map +1 -1
  73. package/dist/core/tunnel/manager.js +3 -2
  74. package/dist/core/tunnel/manager.js.map +1 -1
  75. package/dist/tui/client.d.ts +8 -0
  76. package/dist/tui/client.d.ts.map +1 -1
  77. package/dist/tui/client.js +5 -1
  78. package/dist/tui/client.js.map +1 -1
  79. package/package.json +1 -1
@@ -0,0 +1,331 @@
1
+ /**
2
+ * `generate_speech` tool — text-to-speech (TTS), modeled on the proven
3
+ * `generate_image` self-contained pattern.
4
+ *
5
+ * Why this tool exists
6
+ * --------------------
7
+ * Same reasoning as `generate_image`: without a first-class tool, "read this
8
+ * out loud" / "make a voiceover" sends the model to raw `curl` against a TTS
9
+ * API — the key flows through a shell, the (binary) audio response gets
10
+ * mangled by a text-only parser, and a billed synthesis is dropped. This tool
11
+ * owns the call in-process: stored auth, validated params, a parser that
12
+ * understands each provider's audio shape, and a saved file the model hands to
13
+ * `send_media`.
14
+ *
15
+ * Providers (auto-selected by which key is configured, preference order):
16
+ * • openai — POST /v1/audio/speech → mp3 bytes (gpt-4o-mini-tts / tts-1)
17
+ * • elevenlabs — POST /v1/text-to-speech/{voice} → mp3 bytes
18
+ * • google — Gemini TTS generateContent (AUDIO modality) → base64 PCM,
19
+ * wrapped into a WAV container here.
20
+ * Keys resolve through `resolveMediaProviderKey` (the same credential-store +
21
+ * env path the media-understanding subsystem uses), so TTS works for whichever
22
+ * provider the operator already configured — no bespoke auth.
23
+ *
24
+ * Flow: synthesize → bytes saved under `<cache>/audio/` → result text carries a
25
+ * `MEDIA:<saved-path>` line → the model delivers with `send_media({path})`.
26
+ */
27
+ import fs from "node:fs";
28
+ import path from "node:path";
29
+ import { Type } from "typebox";
30
+ import { resolveCacheDir, DEFAULT_AGENT_ID } from "../../config/paths.js";
31
+ import { loadConfig } from "../../core/config.js";
32
+ import { resolveMediaProviderKey } from "../media-understanding/config.js";
33
+ import { synthesizeEdge } from "./edge-tts.js";
34
+ import { runCommandTts } from "./media-command.js";
35
+ import { jsonResult } from "./common.js";
36
+ /** Synthesis can take a few seconds for long input; bound each HTTP call. */
37
+ const REQUEST_TIMEOUT_MS = 120_000;
38
+ /** Hard cap on input length — providers reject very long text; fail clearly. */
39
+ const MAX_INPUT_CHARS = 8_000;
40
+ /** Preference order when no provider is pinned: first AVAILABLE one wins. Keyed
41
+ * cloud providers come first; a configured local `command` (offline piper /
42
+ * kitten-tts) is next; the free `edge` (Microsoft "Read Aloud" WS, no key) is the
43
+ * always-available last fallback. */
44
+ const PROVIDER_PREFERENCE = ["openai", "elevenlabs", "google", "minimax", "xai", "command", "edge"];
45
+ const DEFAULTS = {
46
+ openai: { model: "gpt-4o-mini-tts", voice: "alloy" },
47
+ elevenlabs: { model: "eleven_multilingual_v2", voice: "21m00Tcm4TlvDq8ikWAM" },
48
+ google: { model: "gemini-2.5-flash-preview-tts", voice: "Kore" },
49
+ minimax: { model: "speech-2.8-hd", voice: "English_expressive_narrator" },
50
+ xai: { model: "", voice: "eve" },
51
+ command: { model: "", voice: "" },
52
+ edge: { model: "", voice: "en-US-AvaNeural" },
53
+ };
54
+ const GenerateSpeechParams = Type.Object({
55
+ action: Type.Optional(Type.Union([Type.Literal("generate"), Type.Literal("list")], {
56
+ description: 'Optional: "generate" (default) or "list" to see which TTS providers are configured.',
57
+ })),
58
+ text: Type.Optional(Type.String({ description: "The text to speak aloud." })),
59
+ provider: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("elevenlabs"), Type.Literal("google"), Type.Literal("minimax"), Type.Literal("xai"), Type.Literal("command"), Type.Literal("edge")], { description: "Optional TTS provider override. `edge` is FREE (no key). Default: first available (cloud preferred, edge fallback)." })),
60
+ voice: Type.Optional(Type.String({
61
+ description: "Optional voice. OpenAI: alloy/echo/fable/onyx/nova/shimmer/sage/coral/… · ElevenLabs: a voice id · Google: Kore/Puck/Charon/… Defaults to a sensible voice per provider.",
62
+ })),
63
+ model: Type.Optional(Type.String({ description: "Optional model override for the chosen provider." })),
64
+ filename: Type.Optional(Type.String({ description: "Optional output filename hint (basename preserved, saved under the managed audio dir)." })),
65
+ });
66
+ export function makeGenerateSpeechTool(opts = {}) {
67
+ const agentId = opts.agentId ?? DEFAULT_AGENT_ID;
68
+ const fetchFn = opts.fetchFn ?? fetch;
69
+ const resolveKey = opts.resolveKey ?? ((p) => resolveMediaProviderKey(p, agentId));
70
+ const edgeSynth = opts.edgeSynth ??
71
+ ((text, voice, signal) => synthesizeEdge({ text, voice, ...(signal ? { signal } : {}) }));
72
+ const ttsCommand = opts.ttsCommand ?? resolveTtsCommand();
73
+ // Edge is FREE (no key) → always available; `command` needs a configured local
74
+ // CLI; every cloud provider needs a key.
75
+ const isAvailable = (p) => p === "edge" ? true : p === "command" ? ttsCommand.length > 0 : resolveKey(p).length > 0;
76
+ return {
77
+ name: "generate_speech",
78
+ label: "Generate Speech",
79
+ displaySummary: "synthesizing speech",
80
+ // Billed per call (cloud TTS) — owner-gated like generate_image.
81
+ ownerOnly: true,
82
+ description: [
83
+ "Turn text into spoken audio (text-to-speech). USE THIS — never call a TTS API with bash/curl: the key must not flow through a shell, and the binary audio response is parsed here.",
84
+ 'action="generate" (default): requires `text`. Saves an audio file and returns its REAL path as a `MEDIA:<path>` line — reference that path exactly; never invent one.',
85
+ "Auto-selects the first configured provider (OpenAI → ElevenLabs → Google); override with `provider`/`voice`/`model`.",
86
+ "To play it for the operator on a chat surface, follow up with `send_media({path})` — generation does NOT auto-send.",
87
+ 'action="list": show which TTS providers have a configured key.',
88
+ ].join(" "),
89
+ parameters: GenerateSpeechParams,
90
+ execute: async (_id, args, signal) => {
91
+ const action = args.action ?? "generate";
92
+ if (action === "list") {
93
+ const providers = PROVIDER_PREFERENCE.filter(isAvailable);
94
+ return jsonResult({
95
+ action,
96
+ providers,
97
+ ok: true,
98
+ message: providers.length > 0
99
+ ? `${providers.length} TTS provider(s) available: ${providers.join(", ")} (edge is free, no key).`
100
+ : "No TTS provider available. Add an OpenAI/ElevenLabs/Google key with `brigade onboard` (or edge works free).",
101
+ });
102
+ }
103
+ const text = (args.text ?? "").trim();
104
+ if (!text) {
105
+ return fail(action, "`text` is required for action=generate.");
106
+ }
107
+ if (text.length > MAX_INPUT_CHARS) {
108
+ return fail(action, `\`text\` is too long (${text.length} chars; max ${MAX_INPUT_CHARS}). Split it into shorter calls.`);
109
+ }
110
+ // Resolve the provider: explicit override (must be keyed) else first keyed.
111
+ let provider;
112
+ if (args.provider) {
113
+ if (!isAvailable(args.provider)) {
114
+ return fail(action, `Provider "${args.provider}" has no configured key. Add one with \`brigade onboard\`, or omit \`provider\` to auto-select (or use the free \`edge\`).`);
115
+ }
116
+ provider = args.provider;
117
+ }
118
+ else {
119
+ provider = PROVIDER_PREFERENCE.find(isAvailable);
120
+ }
121
+ if (!provider) {
122
+ return fail(action, "No TTS provider is available. Add an OpenAI/ElevenLabs/Google API key with `brigade onboard` — or use the free `edge` provider (no key needed).");
123
+ }
124
+ const apiKey = resolveKey(provider);
125
+ const model = args.model?.trim() || resolveConfiguredModel(provider) || DEFAULTS[provider].model;
126
+ const voice = args.voice?.trim() || DEFAULTS[provider].voice;
127
+ let audio;
128
+ try {
129
+ audio =
130
+ provider === "edge"
131
+ ? { bytes: await edgeSynth(text, voice, signal), extension: "mp3" }
132
+ : provider === "command"
133
+ ? runCommandTts(ttsCommand, { text, voice }, opts.commandRunner ? { runFn: opts.commandRunner } : {})
134
+ : await synthesize({ provider, fetchFn, apiKey, model, voice, text, signal });
135
+ }
136
+ catch (err) {
137
+ return fail(action, `TTS via ${provider} failed: ${err instanceof Error ? err.message : String(err)}`, { provider, model, voice });
138
+ }
139
+ const outDir = opts.outDirOverride ?? path.join(resolveCacheDir(), "audio");
140
+ fs.mkdirSync(outDir, { recursive: true });
141
+ const outPath = path.join(outDir, buildFileName(args.filename, audio.extension));
142
+ fs.writeFileSync(outPath, audio.bytes);
143
+ return {
144
+ content: [
145
+ {
146
+ type: "text",
147
+ text: [
148
+ `Synthesized speech with ${model ? `${provider}/${model}` : provider} (voice: ${voice}).`,
149
+ `MEDIA:${outPath}`,
150
+ "Deliver with send_media({path}) — generation does not auto-send.",
151
+ ].join("\n"),
152
+ },
153
+ ],
154
+ details: { action, provider, model, voice, path: outPath, ok: true },
155
+ };
156
+ },
157
+ };
158
+ }
159
+ /* ───────────────────────── provider plumbing ───────────────────────── */
160
+ async function synthesize(params) {
161
+ switch (params.provider) {
162
+ case "openai":
163
+ return synthesizeOpenAI(params);
164
+ case "elevenlabs":
165
+ return synthesizeElevenLabs(params);
166
+ case "google":
167
+ return synthesizeGoogle(params);
168
+ case "minimax":
169
+ return synthesizeMiniMax(params);
170
+ case "xai":
171
+ return synthesizeXai(params);
172
+ }
173
+ }
174
+ async function synthesizeOpenAI(p) {
175
+ const res = await p.fetchFn("https://api.openai.com/v1/audio/speech", {
176
+ method: "POST",
177
+ headers: { Authorization: `Bearer ${p.apiKey}`, "Content-Type": "application/json" },
178
+ body: JSON.stringify({ model: p.model, input: p.text, voice: p.voice, response_format: "mp3" }),
179
+ signal: withTimeout(p.signal, REQUEST_TIMEOUT_MS),
180
+ });
181
+ if (!res.ok)
182
+ throw new Error(`HTTP ${res.status} ${(await safeText(res)).slice(0, 200)}`);
183
+ return { bytes: Buffer.from(await res.arrayBuffer()), extension: "mp3" };
184
+ }
185
+ async function synthesizeElevenLabs(p) {
186
+ const res = await p.fetchFn(`https://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(p.voice)}`, {
187
+ method: "POST",
188
+ headers: { "xi-api-key": p.apiKey, "Content-Type": "application/json", Accept: "audio/mpeg" },
189
+ body: JSON.stringify({ text: p.text, model_id: p.model }),
190
+ signal: withTimeout(p.signal, REQUEST_TIMEOUT_MS),
191
+ });
192
+ if (!res.ok)
193
+ throw new Error(`HTTP ${res.status} ${(await safeText(res)).slice(0, 200)}`);
194
+ return { bytes: Buffer.from(await res.arrayBuffer()), extension: "mp3" };
195
+ }
196
+ async function synthesizeGoogle(p) {
197
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(p.model)}:generateContent?key=${encodeURIComponent(p.apiKey)}`;
198
+ const res = await p.fetchFn(url, {
199
+ method: "POST",
200
+ headers: { "Content-Type": "application/json" },
201
+ body: JSON.stringify({
202
+ contents: [{ parts: [{ text: p.text }] }],
203
+ generationConfig: {
204
+ responseModalities: ["AUDIO"],
205
+ speechConfig: { voiceConfig: { prebuiltVoiceConfig: { voiceName: p.voice } } },
206
+ },
207
+ }),
208
+ signal: withTimeout(p.signal, REQUEST_TIMEOUT_MS),
209
+ });
210
+ if (!res.ok)
211
+ throw new Error(`HTTP ${res.status} ${(await safeText(res)).slice(0, 200)}`);
212
+ const body = (await res.json());
213
+ const part = body.candidates?.[0]?.content?.parts?.find((x) => x.inlineData?.data);
214
+ const data = part?.inlineData?.data;
215
+ if (!data)
216
+ throw new Error("Gemini returned no audio data.");
217
+ const pcm = Buffer.from(data, "base64");
218
+ // Gemini TTS returns raw 16-bit PCM (mimeType like "audio/L16;codec=pcm;rate=24000").
219
+ const rate = parseInt(/rate=(\d+)/.exec(part?.inlineData?.mimeType ?? "")?.[1] ?? "24000", 10) || 24000;
220
+ return { bytes: wrapPcmAsWav(pcm, rate), extension: "wav" };
221
+ }
222
+ async function synthesizeMiniMax(p) {
223
+ const res = await p.fetchFn("https://api.minimax.io/v1/t2a_v2", {
224
+ method: "POST",
225
+ headers: { Authorization: `Bearer ${p.apiKey}`, "Content-Type": "application/json" },
226
+ body: JSON.stringify({
227
+ model: p.model,
228
+ text: p.text,
229
+ voice_setting: { voice_id: p.voice, speed: 1.0, vol: 1.0, pitch: 0 },
230
+ audio_setting: { format: "mp3", sample_rate: 32000 },
231
+ }),
232
+ signal: withTimeout(p.signal, REQUEST_TIMEOUT_MS),
233
+ });
234
+ if (!res.ok)
235
+ throw new Error(`HTTP ${res.status} ${(await safeText(res)).slice(0, 200)}`);
236
+ const body = (await res.json());
237
+ if (body.base_resp && body.base_resp.status_code !== 0) {
238
+ throw new Error(`MiniMax error ${body.base_resp.status_code}: ${body.base_resp.status_msg ?? ""}`);
239
+ }
240
+ const hex = body.data?.audio;
241
+ if (!hex)
242
+ throw new Error("MiniMax returned no audio.");
243
+ // MiniMax returns the audio as a hex-encoded string in data.audio.
244
+ return { bytes: Buffer.from(hex, "hex"), extension: "mp3" };
245
+ }
246
+ async function synthesizeXai(p) {
247
+ const res = await p.fetchFn("https://api.x.ai/v1/tts", {
248
+ method: "POST",
249
+ headers: { Authorization: `Bearer ${p.apiKey}`, "Content-Type": "application/json" },
250
+ body: JSON.stringify({ text: p.text, voice_id: p.voice, language: "en" }),
251
+ signal: withTimeout(p.signal, REQUEST_TIMEOUT_MS),
252
+ });
253
+ if (!res.ok)
254
+ throw new Error(`HTTP ${res.status} ${(await safeText(res)).slice(0, 200)}`);
255
+ return { bytes: Buffer.from(await res.arrayBuffer()), extension: "mp3" };
256
+ }
257
+ /** Wrap raw 16-bit mono little-endian PCM in a minimal WAV (RIFF) container. */
258
+ export function wrapPcmAsWav(pcm, sampleRate, channels = 1, bitsPerSample = 16) {
259
+ const byteRate = (sampleRate * channels * bitsPerSample) / 8;
260
+ const blockAlign = (channels * bitsPerSample) / 8;
261
+ const header = Buffer.alloc(44);
262
+ header.write("RIFF", 0);
263
+ header.writeUInt32LE(36 + pcm.length, 4);
264
+ header.write("WAVE", 8);
265
+ header.write("fmt ", 12);
266
+ header.writeUInt32LE(16, 16); // PCM fmt chunk size
267
+ header.writeUInt16LE(1, 20); // audio format = PCM
268
+ header.writeUInt16LE(channels, 22);
269
+ header.writeUInt32LE(sampleRate, 24);
270
+ header.writeUInt32LE(byteRate, 28);
271
+ header.writeUInt16LE(blockAlign, 32);
272
+ header.writeUInt16LE(bitsPerSample, 34);
273
+ header.write("data", 36);
274
+ header.writeUInt32LE(pcm.length, 40);
275
+ return Buffer.concat([header, pcm]);
276
+ }
277
+ /* ───────────────────────── helpers ───────────────────────── */
278
+ /** The local-TTS command template (env override, then config), or "" if unset. */
279
+ function resolveTtsCommand() {
280
+ const env = process.env.BRIGADE_TTS_COMMAND?.trim();
281
+ if (env)
282
+ return env;
283
+ try {
284
+ const cfg = loadConfig();
285
+ const c = cfg.tools?.speech?.command;
286
+ if (typeof c === "string" && c.trim())
287
+ return c.trim();
288
+ }
289
+ catch {
290
+ /* default below */
291
+ }
292
+ return "";
293
+ }
294
+ function resolveConfiguredModel(provider) {
295
+ try {
296
+ const cfg = loadConfig();
297
+ const m = cfg.tools?.speech?.models?.[provider];
298
+ if (typeof m === "string" && m.trim())
299
+ return m.trim();
300
+ }
301
+ catch {
302
+ /* default below */
303
+ }
304
+ return undefined;
305
+ }
306
+ function buildFileName(hint, extension) {
307
+ const stamp = Date.now().toString(36);
308
+ const base = hint
309
+ ? path.basename(hint).replace(/\.[a-z0-9]+$/i, "").replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 48)
310
+ : `speech-${stamp}`;
311
+ return `${base}.${extension}`;
312
+ }
313
+ function fail(action, message, extra = {}) {
314
+ return jsonResult({ action, ok: false, message, ...extra });
315
+ }
316
+ async function safeText(res) {
317
+ try {
318
+ return await res.text();
319
+ }
320
+ catch {
321
+ return "";
322
+ }
323
+ }
324
+ /** Compose the caller's signal with a hard per-request timeout. */
325
+ function withTimeout(signal, ms) {
326
+ const timeoutSignal = AbortSignal.timeout(ms);
327
+ if (!signal)
328
+ return timeoutSignal;
329
+ return AbortSignal.any([signal, timeoutSignal]);
330
+ }
331
+ //# sourceMappingURL=generate-speech-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-speech-tool.js","sourceRoot":"","sources":["../../../src/agents/tools/generate-speech-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * `generate_video` tool — text-to-video / image-to-video generation, modeled
3
+ * on the proven self-contained `generate_speech` / `generate_image` pattern.
4
+ *
5
+ * Why this tool exists
6
+ * --------------------
7
+ * Same reasoning as `generate_image` / `generate_speech`: without a first-class
8
+ * tool, "make me a video" / "animate this image" sends the model to raw `curl`
9
+ * against a video API — the key flows through a shell, the async submit→poll→
10
+ * download dance is hand-rolled (and dropped half-way), and a BILLED render is
11
+ * lost. This tool owns the call in-process: stored auth, validated params, the
12
+ * provider-specific async flow (submit a job → poll its status → download the
13
+ * finished mp4), and a saved file the model hands to `send_media`.
14
+ *
15
+ * Most video providers are ASYNC: a POST submits a job and returns an id; a
16
+ * status GET is polled on an interval until the job is done/failed; the final
17
+ * video URL is then downloaded (GET) and the bytes saved. We poll inline (the
18
+ * tool's `execute` is async) via `pollUntil(...)`, treating any unknown /
19
+ * transient status as "keep polling".
20
+ *
21
+ * Providers (auto-selected by which key is configured, preference order):
22
+ * • openrouter — POST /api/v1/videos (Veo by default); may return the video
23
+ * inline (url / data-url) OR an {id} to poll. NEWER API —
24
+ * implemented flexibly (deep-searches the body for the first
25
+ * mp4 / data:video URL). [per-spec; treat as unverified]
26
+ * • fal — queue.fal.run/{model} submit → status_url poll → response_url
27
+ * • openai — Sora: POST /v1/videos → poll → /v1/videos/{id}/content
28
+ * • xai — grok-imagine-video: POST /v1/videos/generations → poll
29
+ * • minimax — Hailuo: POST /v1/video_generation → query task → file fetch
30
+ * • runway — gen4_turbo: POST /v1/text_to_video (or image_to_video) → poll
31
+ * Keys resolve through `resolveMediaProviderKey` (the same credential-store +
32
+ * env path the media-understanding subsystem uses), so video works for whichever
33
+ * provider the operator already configured — no bespoke auth.
34
+ *
35
+ * Flow: generate → bytes saved under `<cache>/video/` → result text carries a
36
+ * `MEDIA:<saved-path>` line → the model delivers with `send_media({path})`.
37
+ */
38
+ import { Type } from "typebox";
39
+ import type { BrigadeTool } from "./types.js";
40
+ type VideoProviderId = "openrouter" | "fal" | "openai" | "xai" | "minimax" | "runway" | "google" | "byteplus" | "alibaba" | "together";
41
+ declare const GenerateVideoParams: Type.TObject<{
42
+ action: Type.TOptional<Type.TUnion<[Type.TLiteral<"generate">, Type.TLiteral<"list">]>>;
43
+ prompt: Type.TOptional<Type.TString>;
44
+ image: Type.TOptional<Type.TString>;
45
+ provider: Type.TOptional<Type.TUnion<[Type.TLiteral<"openrouter">, Type.TLiteral<"fal">, Type.TLiteral<"openai">, Type.TLiteral<"xai">, Type.TLiteral<"minimax">, Type.TLiteral<"runway">, Type.TLiteral<"google">, Type.TLiteral<"byteplus">, Type.TLiteral<"alibaba">, Type.TLiteral<"together">]>>;
46
+ model: Type.TOptional<Type.TString>;
47
+ durationSeconds: Type.TOptional<Type.TInteger>;
48
+ aspectRatio: Type.TOptional<Type.TString>;
49
+ resolution: Type.TOptional<Type.TString>;
50
+ filename: Type.TOptional<Type.TString>;
51
+ }>;
52
+ interface GenerateVideoDetails {
53
+ action: "generate" | "list";
54
+ provider?: string;
55
+ model?: string;
56
+ path?: string;
57
+ providers?: string[];
58
+ ok: boolean;
59
+ message?: string;
60
+ }
61
+ export interface MakeGenerateVideoToolOptions {
62
+ /** Caller's agent id — drives which credential store backs the key. */
63
+ agentId?: string;
64
+ /** Test seam: replaces global fetch. */
65
+ fetchFn?: typeof fetch;
66
+ /** Test seam: output directory override. Default `<cache>/video`. */
67
+ outDirOverride?: string;
68
+ /** Test seam: per-provider API-key resolver override. */
69
+ resolveKey?: (provider: VideoProviderId) => string;
70
+ /**
71
+ * Test seam: base poll interval in ms. Real default keeps the provider-
72
+ * specific cadence below; tests set this tiny so they don't actually wait.
73
+ * When set, it scales every provider's interval down to this value.
74
+ */
75
+ pollIntervalMs?: number;
76
+ }
77
+ export declare function makeGenerateVideoTool(opts?: MakeGenerateVideoToolOptions): BrigadeTool<typeof GenerateVideoParams, GenerateVideoDetails>;
78
+ /**
79
+ * Sentinel a poll callback returns to mean "not finished yet — keep polling".
80
+ * Using a unique symbol (rather than `undefined`) lets the callback's resolved
81
+ * value type infer `T` cleanly while keeping the keep-polling signal
82
+ * unambiguous and impossible to collide with a real result value.
83
+ */
84
+ export declare const POLL_AGAIN: unique symbol;
85
+ /**
86
+ * Generic inline poller. Calls `fn` every `intervalMs` until it returns a real
87
+ * value (returned) or throws (propagated as a hard failure). Returning
88
+ * `POLL_AGAIN` (an unknown / transient / queued status) just waits and retries.
89
+ * Bounded by BOTH `maxAttempts` AND the absolute `POLL_TIMEOUT_MS` wall-clock
90
+ * ceiling so a wedged job can never hang the agent loop forever.
91
+ */
92
+ export declare function pollUntil<T>(fn: () => Promise<T | typeof POLL_AGAIN>, options: {
93
+ intervalMs: number;
94
+ maxAttempts: number;
95
+ }): Promise<T>;
96
+ /**
97
+ * Download the final video. If the URL is a `data:` URL, decode its base64
98
+ * payload directly; otherwise GET the URL and read the body as bytes. The
99
+ * provider key is sent as a Bearer header for same-origin signed URLs that
100
+ * still require auth; cross-origin CDN URLs simply ignore it.
101
+ */
102
+ export declare function downloadVideo(url: string, fetchFn: typeof fetch, apiKey: string, signal?: AbortSignal): Promise<Buffer>;
103
+ /**
104
+ * Deep-search an arbitrary JSON body for the first usable video URL — an
105
+ * `https://…mp4` (or any https URL on a key that smells like a video field) or
106
+ * a `data:video…` data URL. Used by the providers (chiefly OpenRouter) whose
107
+ * exact response field for the finished video isn't pinned down.
108
+ */
109
+ export declare function findVideoUrl(body: unknown): string | undefined;
110
+ export {};
111
+ //# sourceMappingURL=generate-video-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-video-tool.d.ts","sourceRoot":"","sources":["../../../src/agents/tools/generate-video-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAKH,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAM/B,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAC;AAc/D,KAAK,eAAe,GACjB,YAAY,GACZ,KAAK,GACL,QAAQ,GACR,KAAK,GACL,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,SAAS,GACT,UAAU,CAAC;AA8Bd,QAAA,MAAM,mBAAmB;;;;;;;;;;EAuCvB,CAAC;AAEH,UAAU,oBAAoB;IAC7B,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,4BAA4B;IAC5C,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,MAAM,CAAC;IACnD;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,qBAAqB,CACpC,IAAI,GAAE,4BAAiC,GACrC,WAAW,CAAC,OAAO,mBAAmB,EAAE,oBAAoB,CAAC,CA6H/D;AA6kBD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,MAA6B,CAAC;AAE9D;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAChC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,OAAO,UAAU,CAAC,EACxC,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClD,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAClC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,KAAK,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,MAAM,CAAC,CAcjB;AAuGD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAyB9D"}