@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
package/README.md CHANGED
@@ -119,6 +119,7 @@ backend β€” all under one `~/.brigade/` directory you fully own.
119
119
  | πŸ“… **Always-on** | Run as a headless WebSocket gateway with a crash supervisor, cron jobs, and OS service install. |
120
120
  | πŸ’¬ **Channels** | Talk to your crew from WhatsApp and Telegram today; the adapter contract is built for more. |
121
121
  | πŸ”— **1,000+ connectors** | Gmail, Slack, GitHub, Notion, Calendar, Linear… via the built-in Composio tool. |
122
+ | πŸ“„ **Reads & writes documents** | Send a PDF, Office doc, image, audio, or video and your crew *understands* it β€” then have it **create or edit** Word, Excel, PowerPoint, and PDF files and hand them back. |
122
123
  | 🧩 **MCP** | Expose your long-term memory to any MCP client (`brigade mcp`), or connect MCP servers in. |
123
124
  | πŸ—„οΈ **Your storage** | Default filesystem mode, or an optional **fully self-hosted Convex** backend with at-rest encryption. |
124
125
  | πŸ” **Yours** | Everything lives under `~/.brigade/`. Keys are stored locally at mode `0600`. `rm -rf ~/.brigade` wipes it clean. |
@@ -283,6 +284,17 @@ to **PLATFORM**, open **Settings β†’ API Keys**, and copy the `ak_…` key. Hand
283
284
  Brigade once (*"set my Composio key to `ak_…`"*) and it's verified and stored encrypted.
284
285
  Full guide: **[docs/composio.md](docs/composio.md)**.
285
286
 
287
+ ### πŸ“„ Documents & media
288
+ Send your crew a file and it actually **reads** it: the `analyze_media` tool
289
+ understands PDFs (text or scanned), Word / Excel / PowerPoint (including the images
290
+ embedded inside them), plain images, audio, and video β€” auto-selecting the right
291
+ provider and caching the result. The write side, `make_document` and
292
+ `edit_document`, **creates and edits** Word / Excel / PowerPoint / PDF in place:
293
+ fill templates and form fields, set cells and formulas, add charts, and
294
+ merge / split / stamp / watermark PDFs β€” all with pure-JS libraries, no sandbox.
295
+ Drop a document into a channel and Brigade sees it; ask for a report and it hands
296
+ one back with `send_media`.
297
+
286
298
  ### 🧩 MCP
287
299
  Run `brigade mcp` to expose your long-term memory to any MCP client (Claude Desktop,
288
300
  editors, etc.) as add/search/context tools over stdio, owner-bound.
@@ -294,6 +306,14 @@ by a per-agent approval allowlist (`brigade exec`). Secrets in config use `${VAR
294
306
  references that resolve at read time and are never persisted resolved. Optional
295
307
  **AES-256-GCM at-rest encryption** in Convex mode (`brigade encrypt`).
296
308
 
309
+ **Optional gateway tokens.** The gateway is unauthenticated and localhost-only by
310
+ default β€” ideal for a single machine. Want more? Add one or more access tokens
311
+ (`brigade gateway token new`) and every connection must then present a valid one
312
+ (`Authorization: Bearer`, `x-brigade-token`, or `?token=`). **Multiple tokens** are
313
+ supported, so you can hand a distinct token to each device and revoke one without
314
+ disturbing the rest, and the same tokens secure `brigade expose`. Entirely opt-in:
315
+ with no tokens configured, nothing changes.
316
+
297
317
  ### πŸ”€ Carrow β€” cross-model continuity
298
318
  Switch models mid-conversation **without losing context**. Carrow carries the full
299
319
  transcript onto the new model (it's the same session), **re-anchors your thinking
@@ -342,6 +362,7 @@ principle is the same: *independent verification, never the agent judging itself
342
362
  | `brigade status` | Snapshot config, sessions, and gateway state (`--json`) |
343
363
  | `brigade doctor` | Health-check Node, config, providers, prompts, logs, gateway (`--json`, `--strict`, `--gateway <url>`) |
344
364
  | `brigade logs` | Tail today's gateway log (`--follow`) |
365
+ | `brigade update` Β· `upgrade` | Update Brigade to the latest code and restart the gateway (`--check`, `--no-restart`) |
345
366
 
346
367
  ### Gateway
347
368
 
@@ -351,6 +372,8 @@ principle is the same: *independent verification, never the agent judging itself
351
372
  | `brigade gateway status` Β· `stop` Β· `restart` | Inspect / stop / restart the running gateway |
352
373
  | `brigade gateway install` Β· `uninstall` | Install/remove as a system service (launchd / systemd / Task Scheduler) |
353
374
  | `brigade gateway supervise` | Out-of-process crash watchdog (respawns a wedged gateway) |
375
+ | `brigade expose` Β· `expose stop` | Publish the gateway to the public internet via a secure, token-gated tunnel (alias: `bloody benchmark`) |
376
+ | `brigade gateway token new` Β· `list` Β· `add` Β· `revoke` | Manage **optional** access tokens (multiple supported). No tokens β†’ the gateway stays unauthenticated + localhost-only |
354
377
 
355
378
  ### Agents
356
379
 
@@ -428,6 +451,10 @@ brigade gateway stop
428
451
  brigade gateway restart
429
452
  brigade gateway install # install as a system service (launchd / systemd / Task Scheduler)
430
453
  brigade gateway supervise # out-of-process crash watchdog
454
+
455
+ brigade gateway token new # generate + store an access token (printed once)
456
+ brigade gateway token list # show configured tokens (masked) + whether auth is on
457
+ brigade gateway token revoke 1 # remove a token by its number (or its exact value)
431
458
  ```
432
459
 
433
460
  | Flag | Default | Notes |
@@ -438,6 +465,13 @@ brigade gateway supervise # out-of-process crash watchdog
438
465
  | `--quiet` | off | Suppress the live console stream |
439
466
  | `--log-level X` | `info` | `debug` / `info` / `warn` / `error` |
440
467
 
468
+ **Optional authentication.** By default the gateway is unauthenticated and refuses to
469
+ bind anywhere but loopback. To require a token, run `brigade gateway token new` (repeat
470
+ for multiple tokens) and restart the gateway. On the same machine, clients read the
471
+ token from config automatically; elsewhere pass `--token <t>` or set
472
+ `BRIGADE_GATEWAY_TOKEN`. `BRIGADE_GATEWAY_TOKENS` (comma-separated) adds tokens via the
473
+ environment. Remove every token to return to open, localhost-only mode.
474
+
441
475
  ### `brigade connect`
442
476
 
443
477
  Attaches a TUI to a running gateway. Same chat experience as `brigade`, but the
@@ -485,6 +519,27 @@ brigade doctor --json # machine-readable
485
519
  brigade doctor --strict # exit 1 on warnings (CI mode)
486
520
  ```
487
521
 
522
+ ### `brigade update`
523
+
524
+ Bring Brigade up to date and reload the gateway. It auto-detects how Brigade is
525
+ installed and does the right thing:
526
+
527
+ - **npm global** β€” `npm i -g @spinabot/brigade@latest`, then restart.
528
+ - **source checkout** β€” `git pull` (fast-forward, only when your tree is clean and
529
+ behind upstream β€” a dirty tree is left untouched and rebuilt as-is), then
530
+ `npm install`, `npm run build`, then restart.
531
+
532
+ ```bash
533
+ brigade update # update + restart the gateway
534
+ brigade upgrade # alias of update
535
+ brigade update --check # report whether newer code is available; change nothing
536
+ brigade update --no-restart
537
+ ```
538
+
539
+ If Brigade is installed as a background service (`brigade gateway install`) the
540
+ restart is automatic; if you run the gateway in the foreground, restart it yourself
541
+ to load the new code. Same behavior on macOS, Linux, and Windows.
542
+
488
543
  ### `brigade config`
489
544
 
490
545
  Read and write the local config without opening the TUI.
@@ -605,6 +660,7 @@ Every agent gets a curated toolset. Mutating/privileged tools are owner-gated
605
660
  - **Web:** `web_search`, `fetch_url`, `browser` (when a provider is configured)
606
661
  - **Connectors:** `composio` (1,000+ apps), `oauth_authorize`
607
662
  - **Generation:** `generate_image`
663
+ - **Documents & media:** `analyze_media` (read/understand PDF Β· Office Β· image Β· audio Β· video), `make_document` Β· `edit_document` (create & edit Word/Excel/PowerPoint/PDF)
608
664
  - **Channels:** `send_message`, `send_media` (when a channel is linked)
609
665
 
610
666
  ---
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Microsoft Edge "Read Aloud" text-to-speech over WebSocket β€” FREE, no API key.
3
+ *
4
+ * This is the same free endpoint the `node-edge-tts` package uses (the Bing /
5
+ * "Read Aloud" TTS WebSocket). Auth is an embedded TrustedClientToken plus a
6
+ * computed `Sec-MS-GEC` token (a SHA-256 of the current Windows file-time ticks,
7
+ * floored to 5 minutes, concatenated with the token). The socket sends a
8
+ * `speech.config` frame then an `ssml` frame; audio arrives as binary WS frames
9
+ * (after a `Path:audio` header) and the turn ends on a `Path:turn.end` text
10
+ * frame. Returns MP3 bytes.
11
+ *
12
+ * Re-implemented self-contained (no new dependency) over the `ws` package that
13
+ * Brigade already ships for the gateway/TUI.
14
+ */
15
+ /** Minimal WebSocket surface edge-tts uses β€” lets tests inject a fake socket. */
16
+ export interface EdgeWebSocketLike {
17
+ on(event: "open" | "message" | "error" | "close", cb: (...args: unknown[]) => void): void;
18
+ send(data: string): void;
19
+ close(): void;
20
+ }
21
+ export interface EdgeTtsOptions {
22
+ text: string;
23
+ voice: string;
24
+ outputFormat?: string;
25
+ signal?: AbortSignal;
26
+ timeoutMs?: number;
27
+ /** Test seam: inject a WebSocket factory instead of opening a real socket. */
28
+ wsFactory?: (url: string, headers: Record<string, string>) => EdgeWebSocketLike;
29
+ }
30
+ /** Synthesize speech via the free Edge endpoint. Resolves with MP3 bytes. */
31
+ export declare function synthesizeEdge(opts: EdgeTtsOptions): Promise<Buffer>;
32
+ /**
33
+ * The `Sec-MS-GEC` auth token: uppercase SHA-256 hex of `${ticks}${TrustedClientToken}`,
34
+ * where `ticks` = Windows file time (100-ns intervals since 1601-01-01) floored to
35
+ * the nearest 5 minutes. BigInt math β€” the tick count exceeds Number.MAX_SAFE_INTEGER.
36
+ */
37
+ export declare function secMsGec(nowMs?: number): string;
38
+ /** The opening `speech.config` frame carrying the requested output format. */
39
+ export declare function configFrame(outputFormat: string): string;
40
+ /** The `ssml` frame carrying the voice + escaped text. */
41
+ export declare function ssmlFrame(text: string, voice: string): string;
42
+ /** Minimal XML escaping for SSML text content. */
43
+ export declare function escapeXml(s: string): string;
44
+ //# sourceMappingURL=edge-tts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-tts.d.ts","sourceRoot":"","sources":["../../../src/agents/tools/edge-tts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IACjC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1F,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,iBAAiB,CAAC;CAChF;AAED,6EAA6E;AAC7E,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsE1E;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,GAAE,MAAmB,GAAG,MAAM,CAK3D;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAYxD;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED,kDAAkD;AAClD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO3C"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Microsoft Edge "Read Aloud" text-to-speech over WebSocket β€” FREE, no API key.
3
+ *
4
+ * This is the same free endpoint the `node-edge-tts` package uses (the Bing /
5
+ * "Read Aloud" TTS WebSocket). Auth is an embedded TrustedClientToken plus a
6
+ * computed `Sec-MS-GEC` token (a SHA-256 of the current Windows file-time ticks,
7
+ * floored to 5 minutes, concatenated with the token). The socket sends a
8
+ * `speech.config` frame then an `ssml` frame; audio arrives as binary WS frames
9
+ * (after a `Path:audio` header) and the turn ends on a `Path:turn.end` text
10
+ * frame. Returns MP3 bytes.
11
+ *
12
+ * Re-implemented self-contained (no new dependency) over the `ws` package that
13
+ * Brigade already ships for the gateway/TUI.
14
+ */
15
+ import crypto from "node:crypto";
16
+ import { WebSocket } from "ws";
17
+ const TRUSTED_TOKEN = "6A5AA1D4EAFF4E9FB37E23D68491D6F4";
18
+ const GEC_VERSION = "1-131.0.2903.86";
19
+ const WSS_BASE = "wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1";
20
+ const CHROME_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0";
21
+ /** Synthesize speech via the free Edge endpoint. Resolves with MP3 bytes. */
22
+ export async function synthesizeEdge(opts) {
23
+ const outputFormat = opts.outputFormat ?? "audio-24khz-48kbitrate-mono-mp3";
24
+ const url = `${WSS_BASE}?TrustedClientToken=${TRUSTED_TOKEN}&Sec-MS-GEC=${secMsGec()}&Sec-MS-GEC-Version=${GEC_VERSION}`;
25
+ const headers = {
26
+ "User-Agent": CHROME_UA,
27
+ Origin: "chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold",
28
+ "Accept-Language": "en-US,en;q=0.9",
29
+ };
30
+ const ws = opts.wsFactory
31
+ ? opts.wsFactory(url, headers)
32
+ : new WebSocket(url, { headers });
33
+ return await new Promise((resolve, reject) => {
34
+ const chunks = [];
35
+ let settled = false;
36
+ const timer = setTimeout(() => fail(new Error("Edge TTS timed out")), opts.timeoutMs ?? 30_000);
37
+ const onAbort = () => fail(new Error("aborted"));
38
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
39
+ const cleanup = () => {
40
+ clearTimeout(timer);
41
+ opts.signal?.removeEventListener("abort", onAbort);
42
+ try {
43
+ ws.close();
44
+ }
45
+ catch {
46
+ /* ignore */
47
+ }
48
+ };
49
+ function fail(err) {
50
+ if (settled)
51
+ return;
52
+ settled = true;
53
+ cleanup();
54
+ reject(err);
55
+ }
56
+ function done() {
57
+ if (settled)
58
+ return;
59
+ settled = true;
60
+ cleanup();
61
+ if (chunks.length === 0)
62
+ reject(new Error("Edge TTS produced no audio"));
63
+ else
64
+ resolve(Buffer.concat(chunks));
65
+ }
66
+ ws.on("open", () => {
67
+ ws.send(configFrame(outputFormat));
68
+ ws.send(ssmlFrame(opts.text, opts.voice));
69
+ });
70
+ ws.on("message", (...args) => {
71
+ const data = args[0];
72
+ const isBinary = args[1] === true;
73
+ const buf = Buffer.isBuffer(data)
74
+ ? data
75
+ : data instanceof ArrayBuffer
76
+ ? Buffer.from(data)
77
+ : Buffer.from(String(data), "utf8");
78
+ if (isBinary) {
79
+ // Binary frame: first 2 bytes = big-endian header length; audio follows.
80
+ if (buf.length < 2)
81
+ return;
82
+ const headerLen = buf.readUInt16BE(0);
83
+ const header = buf.subarray(2, 2 + headerLen).toString("utf8");
84
+ if (header.includes("Path:audio"))
85
+ chunks.push(buf.subarray(2 + headerLen));
86
+ }
87
+ else if (buf.toString("utf8").includes("Path:turn.end")) {
88
+ done();
89
+ }
90
+ });
91
+ ws.on("error", (...args) => {
92
+ const e = args[0];
93
+ fail(e instanceof Error ? e : new Error(String(e)));
94
+ });
95
+ ws.on("close", () => {
96
+ if (!settled)
97
+ done();
98
+ });
99
+ });
100
+ }
101
+ /**
102
+ * The `Sec-MS-GEC` auth token: uppercase SHA-256 hex of `${ticks}${TrustedClientToken}`,
103
+ * where `ticks` = Windows file time (100-ns intervals since 1601-01-01) floored to
104
+ * the nearest 5 minutes. BigInt math β€” the tick count exceeds Number.MAX_SAFE_INTEGER.
105
+ */
106
+ export function secMsGec(nowMs = Date.now()) {
107
+ const secondsSince1601 = BigInt(Math.floor(nowMs / 1000) + 11_644_473_600);
108
+ const roundedSeconds = (secondsSince1601 / 300n) * 300n;
109
+ const ticks = roundedSeconds * 10000000n;
110
+ return crypto.createHash("sha256").update(`${ticks}${TRUSTED_TOKEN}`).digest("hex").toUpperCase();
111
+ }
112
+ /** The opening `speech.config` frame carrying the requested output format. */
113
+ export function configFrame(outputFormat) {
114
+ const cfg = {
115
+ context: {
116
+ synthesis: {
117
+ audio: {
118
+ metadataoptions: { sentenceBoundaryEnabled: false, wordBoundaryEnabled: false },
119
+ outputFormat,
120
+ },
121
+ },
122
+ },
123
+ };
124
+ return `X-Timestamp:${new Date().toString()}\r\nContent-Type:application/json; charset=utf-8\r\nPath:speech.config\r\n\r\n${JSON.stringify(cfg)}`;
125
+ }
126
+ /** The `ssml` frame carrying the voice + escaped text. */
127
+ export function ssmlFrame(text, voice) {
128
+ const id = crypto.randomUUID().replace(/-/g, "");
129
+ const ssml = `<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='en-US'>` +
130
+ `<voice name='${voice}'><prosody pitch='+0Hz' rate='+0%' volume='+0%'>${escapeXml(text)}</prosody></voice></speak>`;
131
+ return `X-RequestId:${id}\r\nContent-Type:application/ssml+xml\r\nX-Timestamp:${new Date().toString()}Z\r\nPath:ssml\r\n\r\n${ssml}`;
132
+ }
133
+ /** Minimal XML escaping for SSML text content. */
134
+ export function escapeXml(s) {
135
+ return s
136
+ .replace(/&/g, "&amp;")
137
+ .replace(/</g, "&lt;")
138
+ .replace(/>/g, "&gt;")
139
+ .replace(/'/g, "&apos;")
140
+ .replace(/"/g, "&quot;");
141
+ }
142
+ //# sourceMappingURL=edge-tts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-tts.js","sourceRoot":"","sources":["../../../src/agents/tools/edge-tts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * `generate_music` tool β€” text-to-music generation, modeled on the proven
3
+ * `generate_speech` self-contained pattern.
4
+ *
5
+ * Why this tool exists
6
+ * --------------------
7
+ * Same reasoning as `generate_speech`/`generate_image`: without a first-class
8
+ * tool, "make a song" / "compose background music" sends the model to raw
9
+ * `curl` against a music API β€” the key flows through a shell, the (binary or
10
+ * base64) audio response gets mangled by a text-only parser, and a billed
11
+ * generation is dropped. This tool owns the call in-process: stored auth,
12
+ * validated params, a parser that understands each provider's audio shape, and
13
+ * a saved file the model hands to `send_media`.
14
+ *
15
+ * Providers (auto-selected by which key is configured, preference order):
16
+ * β€’ google β€” Lyria via Gemini generateContent (AUDIO modality) β†’ base64
17
+ * audio (mp3). Single POST, no poll.
18
+ * β€’ minimax β€” Music generation β†’ URL or inline (hex/base64) audio (mp3).
19
+ * β€’ elevenlabs β€” Music endpoint β†’ raw mp3 bytes.
20
+ * Keys resolve through `resolveMediaProviderKey` (the same credential-store +
21
+ * env path the media-understanding subsystem uses), so music generation works
22
+ * for whichever provider the operator already configured β€” no bespoke auth.
23
+ *
24
+ * Flow: generate β†’ bytes saved under `<cache>/audio/` β†’ result text carries a
25
+ * `MEDIA:<saved-path>` line β†’ the model delivers with `send_media({path})`.
26
+ */
27
+ import { Type } from "typebox";
28
+ import type { BrigadeTool } from "./types.js";
29
+ type MusicProviderId = "google" | "minimax" | "elevenlabs";
30
+ declare const GenerateMusicParams: Type.TObject<{
31
+ action: Type.TOptional<Type.TUnion<[Type.TLiteral<"generate">, Type.TLiteral<"list">]>>;
32
+ prompt: Type.TOptional<Type.TString>;
33
+ lyrics: Type.TOptional<Type.TString>;
34
+ instrumental: Type.TOptional<Type.TBoolean>;
35
+ provider: Type.TOptional<Type.TUnion<[Type.TLiteral<"google">, Type.TLiteral<"minimax">, Type.TLiteral<"elevenlabs">]>>;
36
+ model: Type.TOptional<Type.TString>;
37
+ durationSeconds: Type.TOptional<Type.TInteger>;
38
+ filename: Type.TOptional<Type.TString>;
39
+ }>;
40
+ interface GenerateMusicDetails {
41
+ action: "generate" | "list";
42
+ provider?: string;
43
+ model?: string;
44
+ path?: string;
45
+ providers?: string[];
46
+ ok: boolean;
47
+ message?: string;
48
+ }
49
+ export interface MakeGenerateMusicToolOptions {
50
+ /** Caller's agent id β€” drives which credential store backs the key. */
51
+ agentId?: string;
52
+ /** Test seam: replaces global fetch. */
53
+ fetchFn?: typeof fetch;
54
+ /** Test seam: output directory override. Default `<cache>/audio`. */
55
+ outDirOverride?: string;
56
+ /** Test seam: per-provider API-key resolver override. */
57
+ resolveKey?: (provider: MusicProviderId) => string;
58
+ }
59
+ export declare function makeGenerateMusicTool(opts?: MakeGenerateMusicToolOptions): BrigadeTool<typeof GenerateMusicParams, GenerateMusicDetails>;
60
+ export {};
61
+ //# sourceMappingURL=generate-music-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-music-tool.d.ts","sourceRoot":"","sources":["../../../src/agents/tools/generate-music-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAM/B,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAC;AAO/D,KAAK,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;AAW3D,QAAA,MAAM,mBAAmB;;;;;;;;;EAwBvB,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;CACnD;AAED,wBAAgB,qBAAqB,CACpC,IAAI,GAAE,4BAAiC,GACrC,WAAW,CAAC,OAAO,mBAAmB,EAAE,oBAAoB,CAAC,CAwG/D"}