toolnexus 0.27.0 → 0.29.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.
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from "./native.js";
8
8
  export * from "./http.js";
9
9
  export * from "./a2a.js";
10
10
  export * from "./acp.js";
11
+ export * from "./transcript_search.js";
11
12
  export * from "./serve.js";
12
13
  export * from "./mcpserve.js";
13
14
  export * from "./mcphandler.js";
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ export * from "./native.js";
8
8
  export * from "./http.js";
9
9
  export * from "./a2a.js";
10
10
  export * from "./acp.js";
11
+ export * from "./transcript_search.js";
11
12
  export * from "./serve.js";
12
13
  export * from "./mcpserve.js";
13
14
  export * from "./mcphandler.js";
package/dist/mcp.js CHANGED
@@ -6,6 +6,7 @@
6
6
  import { readFileSync } from "node:fs";
7
7
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
8
8
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
9
+ import { AjvJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/ajv";
9
10
  import { AdoptedStdioTransport } from "./mcp2026/stdio.js";
10
11
  import { ElicitRequestSchema } from "@modelcontextprotocol/sdk/types.js";
11
12
  import { sanitize } from "./types.js";
@@ -398,8 +399,19 @@ function resourceTools(servers) {
398
399
  * exists. Separated from connect so the caller ALWAYS holds a closeable reference — even if the
399
400
  * connect is later abandoned by a timeout/abort, `client.close()` still terminates any spawned
400
401
  * stdio child (no orphaned processes on cancellation). */
402
+ /**
403
+ * The SDK's default validator, built on first use instead of per Client. Building an Ajv instance
404
+ * (meta-schemas + formats) costs ~2-3 ms on every connect, yet it is only consulted when a tool
405
+ * declares an `outputSchema`. Same validator, same results — just not paid for up front.
406
+ */
407
+ class LazyAjvValidator {
408
+ inner;
409
+ getValidator(schema) {
410
+ return (this.inner ??= new AjvJsonSchemaValidator()).getValidator(schema);
411
+ }
412
+ }
401
413
  function newMcpClient(waitFor) {
402
- const client = new Client({ name: "toolnexus", version: "0.1.0" }, { capabilities: waitFor ? { elicitation: {} } : {} });
414
+ const client = new Client({ name: "toolnexus", version: "0.1.0" }, { capabilities: waitFor ? { elicitation: {} } : {}, jsonSchemaValidator: new LazyAjvValidator() });
403
415
  if (waitFor) {
404
416
  client.setRequestHandler(ElicitRequestSchema, async (request) => answerToElicitResult(await waitFor(elicitationToRequest(request.params))));
405
417
  }
package/dist/media.d.ts CHANGED
@@ -1,6 +1,132 @@
1
+ import type { ContentPart } from "./content.js";
1
2
  import type { Tool } from "./types.js";
2
- export type MediaVerb = "image" | "video" | "speech" | "transcribe" | "cloneVoice" | "talking";
3
+ export type MediaVerb = "image" | "video" | "speech" | "music" | "transcribe" | "cloneVoice" | "talk";
3
4
  export type MediaKind = "image" | "video" | "audio" | "text";
5
+ export interface MediaVerbArg {
6
+ name: string;
7
+ type: string;
8
+ items?: string;
9
+ description: string;
10
+ required?: boolean;
11
+ }
12
+ export interface MediaVerbSpec {
13
+ verb: MediaVerb;
14
+ tool: string;
15
+ description: string;
16
+ args: MediaVerbArg[];
17
+ }
18
+ /** Canonical verbs — `conformance/media/verbs.json`, embedded verbatim (byte contract). */
19
+ export declare const MEDIA_VERBS: MediaVerbSpec[];
20
+ export interface MediaFile {
21
+ type: "image" | "audio" | "file";
22
+ mimeType: string;
23
+ /** `http(s)` URL, or `file://` + `path` for a local file. */
24
+ url?: string;
25
+ /** Absolute local path (download mode, or a CLI's own file in url mode). */
26
+ path?: string;
27
+ /** Standard padded base64 (inline mode). */
28
+ data?: string;
29
+ }
30
+ export type MediaResultStatus = "completed" | "failed" | "timeout" | "cancelled" | "unavailable" | (string & {});
31
+ export interface MediaResult {
32
+ files: MediaFile[];
33
+ text?: string;
34
+ jobId?: string;
35
+ status: MediaResultStatus;
36
+ /** Provider-reported usage only, never estimated (§7G.12 D21). */
37
+ usage?: MediaUsage;
38
+ /** Who served the call: the preset id, the HTTP style's name (else "style"), or the client's name (§7G.10b). */
39
+ style?: string;
40
+ /** The configured model for the verb of a loaded style, when one was set; never guessed. */
41
+ model?: string;
42
+ }
43
+ /** §7G.12 D21: what the provider reported; absent fields are absent. */
44
+ export interface MediaUsage {
45
+ inputTokens?: number;
46
+ outputTokens?: number;
47
+ costUsd?: number;
48
+ raw?: Record<string, unknown>;
49
+ }
50
+ export interface MediaProgress {
51
+ verb: MediaVerb;
52
+ client: string;
53
+ jobId?: string;
54
+ status: string;
55
+ elapsedMs: number;
56
+ }
57
+ /** Per-call context (§7G.2). */
58
+ export interface MediaContext {
59
+ signal?: AbortSignal;
60
+ /** Absolute deadline (epoch ms or Date); the job ends at the earlier of it and `loop.timeoutMs`. */
61
+ deadline?: number | Date;
62
+ /** Called for every progress status; when absent the client's `loop.onProgress` is used. */
63
+ progress?: (p: MediaProgress) => void;
64
+ /** Function face only: top-level keys overwrite the request body last. */
65
+ providerOptions?: Record<string, unknown>;
66
+ }
67
+ /** Per-call options of the typed verbs (`media.image({ prompt, signal })`). */
68
+ export type MediaCallOptions = MediaContext;
69
+ export interface MediaArgSpec {
70
+ name: string;
71
+ required: boolean;
72
+ }
73
+ /** Any media provider (§7G.2). Every verb is optional; `supports(verb)` is the truth. */
74
+ export interface MediaClient {
75
+ readonly name: string;
76
+ supports(verb: MediaVerb | string): boolean;
77
+ /** Accepted canonical args; absent ⇒ every canonical arg of the verb, canonical required. */
78
+ args?(verb: MediaVerb | string): MediaArgSpec[];
79
+ image?(args: Record<string, unknown>, ctx: MediaContext): Promise<MediaResult>;
80
+ video?(args: Record<string, unknown>, ctx: MediaContext): Promise<MediaResult>;
81
+ speech?(args: Record<string, unknown>, ctx: MediaContext): Promise<MediaResult>;
82
+ music?(args: Record<string, unknown>, ctx: MediaContext): Promise<MediaResult>;
83
+ transcribe?(args: Record<string, unknown>, ctx: MediaContext): Promise<MediaResult>;
84
+ cloneVoice?(args: Record<string, unknown>, ctx: MediaContext): Promise<MediaResult>;
85
+ talk?(args: Record<string, unknown>, ctx: MediaContext): Promise<MediaResult>;
86
+ }
87
+ export type MediaErrorStatus = "failed" | "timeout" | "cancelled" | "unavailable";
88
+ /** A failed media verb (§7G.2): message, status and the job id when known. */
89
+ export declare class MediaError extends Error {
90
+ readonly status: MediaErrorStatus;
91
+ jobId?: string;
92
+ constructor(message: string, status?: MediaErrorStatus, jobId?: string);
93
+ }
94
+ /** The client cannot serve the call now (no credits, quota, no key, CLI missing, ZDR …). */
95
+ export declare class MediaUnavailableError extends MediaError {
96
+ constructor(message: string, jobId?: string);
97
+ }
98
+ export type GatherMode = "url" | "download" | "inline";
99
+ /** One config shape for every built-in client (§7G.4). */
100
+ export interface MediaClientConfig {
101
+ /** Model of the client's primary verb (CLI clients: `-m <model>`). */
102
+ model?: string;
103
+ /** Per-verb model override; wins over `model` and the default. */
104
+ models?: Partial<Record<MediaVerb, string>>;
105
+ /** API key; default the client's env var, read at call time. Never logged. */
106
+ key?: string;
107
+ /** Base URL override (any compatible server). */
108
+ url?: string;
109
+ /** CLI argv prefix (a string is one executable, never shell-split). */
110
+ command?: string | string[];
111
+ loop?: {
112
+ intervalMs?: number;
113
+ timeoutMs?: number;
114
+ onProgress?: (p: MediaProgress) => void;
115
+ };
116
+ /**
117
+ * `name`, when set, names saved files `<name><ext>`, then `<name>-2<ext>`, … (first free name);
118
+ * sanitised to `[A-Za-z0-9._-]`, leading `.`/`-` dropped; empty ⇒ the default naming (§7G.10b).
119
+ */
120
+ gather?: {
121
+ mode?: GatherMode;
122
+ dir?: string;
123
+ maxBytes?: number;
124
+ keep?: boolean;
125
+ name?: string;
126
+ };
127
+ /** HTTP transport (the same seam as the LLM client's `fetch`). Omit ⇒ global fetch. */
128
+ fetch?: typeof fetch;
129
+ }
4
130
  export interface MediaVerbStyle {
5
131
  mode: "sync" | "async";
6
132
  kind: MediaKind;
@@ -10,6 +136,7 @@ export interface MediaVerbStyle {
10
136
  };
11
137
  defaults?: Record<string, unknown>;
12
138
  args: Record<string, string>;
139
+ required?: string[];
13
140
  idPath?: string;
14
141
  poll?: {
15
142
  method?: string;
@@ -24,6 +151,7 @@ export interface MediaVerbStyle {
24
151
  resultPath: string;
25
152
  }
26
153
  export interface MediaStyle {
154
+ name?: string;
27
155
  baseUrl: string;
28
156
  headers?: Record<string, string>;
29
157
  errorEnvelope?: {
@@ -33,33 +161,313 @@ export interface MediaStyle {
33
161
  };
34
162
  verbs: Partial<Record<MediaVerb, MediaVerbStyle>>;
35
163
  }
36
- export interface MediaFile {
37
- type: "image" | "audio" | "file";
164
+ /** The a2e.ai preset — `examples/media-styles/a2e.json`, embedded verbatim. */
165
+ export declare const A2E_STYLE: MediaStyle & {
166
+ _doc?: string;
167
+ };
168
+ /**
169
+ * Built-in CLI presets for {@link loadMediaStyle} (ADR 0042): media through a locally installed,
170
+ * logged-in CLI on the user's own subscription, no API key. The `*Mock` twins behave the same
171
+ * (name, verbs, args, prompt folding, errors) but never start a process and return a fixed file.
172
+ */
173
+ export declare const MediaStyle: {
174
+ /** The `grok` CLI: image and video. */
175
+ readonly XaiGrokCli: "xai-grok-cli";
176
+ /** The `codex` CLI: image only. */
177
+ readonly OpenAICodexCli: "openai-codex-cli";
178
+ /** Google's Antigravity CLI `agy`: image only. */
179
+ readonly GoogleAgyCli: "google-agy-cli";
180
+ readonly XaiGrokCliMock: "xai-grok-cli-mock";
181
+ readonly OpenAICodexCliMock: "openai-codex-cli-mock";
182
+ readonly GoogleAgyCliMock: "google-agy-cli-mock";
183
+ };
184
+ /** A built-in CLI preset name. */
185
+ export type MediaStylePreset = (typeof MediaStyle)[keyof typeof MediaStyle];
186
+ /**
187
+ * A loaded style (§7G.7): an HTTP style file or a built-in CLI preset, configured and usable as a
188
+ * {@link MediaClient} anywhere one is accepted — `createMedia(loadMediaStyle("xai-grok-cli"))`.
189
+ */
190
+ export declare class LoadedMediaStyle implements MediaClient {
191
+ readonly name: string;
192
+ /** The preset name, when this is a built-in CLI preset. */
193
+ readonly preset?: MediaStylePreset;
194
+ /** The parsed style, when this is an HTTP style. */
195
+ readonly style?: MediaStyle;
196
+ /** The config the style was loaded with. */
197
+ readonly config: MediaClientConfig;
198
+ private readonly client;
199
+ constructor(source: MediaStyle | MediaStylePreset, config?: MediaClientConfig);
200
+ supports(verb: MediaVerb | string): boolean;
201
+ /** Who serves calls: the preset id, else the HTTP style's name, else "style" (§7G.10b). */
202
+ get id(): string;
203
+ /**
204
+ * Can this style run? Cheap and side-effect free (§7G.10b): a CLI preset's command is found and
205
+ * its own login file exists (never read); an HTTP style's config key or header `${VAR}`s are set.
206
+ */
207
+ available(): MediaAvailability;
208
+ args(verb: MediaVerb | string): MediaArgSpec[];
209
+ private call;
210
+ image(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
211
+ video(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
212
+ speech(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
213
+ music(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
214
+ transcribe(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
215
+ cloneVoice(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
216
+ talk(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
217
+ }
218
+ /** The cheap pre-flight answer of {@link LoadedMediaStyle.available} (§7G.10b). */
219
+ export interface MediaAvailability {
220
+ installed: boolean;
221
+ loggedIn: boolean;
222
+ reason: string;
223
+ }
224
+ /** Set to "0", every mock preset reports unavailable. */
225
+ export declare const MEDIA_MOCK_AVAILABLE_ENV = "TOOLNEXUS_MEDIA_MOCK_AVAILABLE";
226
+ /**
227
+ * Load a style: a built-in CLI preset ({@link MediaStyle}`.XaiGrokCli`, …) or a style JSON file
228
+ * (throws the §7G.7 style errors). `config` configures the client behind it (model, command, loop, gather).
229
+ */
230
+ export declare function loadMediaStyle(pathOrPreset: MediaStylePreset | string, config?: MediaClientConfig): LoadedMediaStyle;
231
+ interface HttpRes {
232
+ status: number;
233
+ headers: Headers;
234
+ bytes: Uint8Array;
235
+ over: boolean;
236
+ }
237
+ interface SendOpts {
238
+ json?: unknown;
239
+ body?: Uint8Array;
240
+ contentType?: string;
241
+ /** false ⇒ never send client headers (downloads, input fetches). */
242
+ auth?: boolean;
243
+ /** Stop reading the body at limit + 1 bytes. */
244
+ limit?: number;
245
+ }
246
+ /** One job's HTTP: redirects by hand, the origin header rule, the per-request deadline. */
247
+ declare class HttpJob {
248
+ readonly client: string;
249
+ readonly verb: string;
250
+ private readonly headers;
251
+ private readonly doFetch;
252
+ readonly timeoutMs: number;
253
+ readonly deadline: number;
254
+ readonly signal?: AbortSignal | undefined;
255
+ jobId?: string;
256
+ private readonly origin;
257
+ constructor(client: string, verb: string, baseUrl: string, headers: () => Record<string, string>, doFetch: typeof fetch, timeoutMs: number, deadline: number, signal?: AbortSignal | undefined);
258
+ timedOut(): MediaError;
259
+ send(url: string, method: string, opts?: SendOpts): Promise<HttpRes>;
260
+ /** A provider API call: unavailable mapping, then any other non-2xx is `HTTP <s>: <body>`. */
261
+ api(method: string, url: string, opts?: SendOpts): Promise<HttpRes>;
262
+ json(method: string, url: string, opts?: SendOpts): Promise<{
263
+ data: any;
264
+ res: HttpRes;
265
+ }>;
266
+ /** §7G.5 download: GET, no client headers, capped at maxBytes. */
267
+ download(url: string, maxBytes: number): Promise<{
268
+ bytes: Uint8Array;
269
+ contentType?: string;
270
+ }>;
271
+ }
272
+ type RawResult = {
273
+ bytes: Uint8Array;
274
+ mimeType: string;
275
+ } | {
276
+ base64: string;
38
277
  mimeType: string;
278
+ } | {
279
+ dataUrl: string;
280
+ } | {
39
281
  url: string;
282
+ } | {
283
+ path: string;
284
+ };
285
+ interface GatherCfg {
286
+ mode: GatherMode;
287
+ dir: string;
288
+ maxBytes: number;
289
+ keep: boolean;
290
+ slug: string;
40
291
  }
41
- export interface MediaResult {
42
- files: MediaFile[];
43
- text?: string;
44
- jobId?: string;
45
- status: string;
292
+ declare class Gatherer {
293
+ readonly cfg: GatherCfg;
294
+ readonly client: string;
295
+ readonly verb: string;
296
+ readonly kind: MediaKind;
297
+ readonly job?: HttpJob | undefined;
298
+ constructor(cfg: GatherCfg, client: string, verb: string, kind: MediaKind, job?: HttpJob | undefined);
299
+ private tooBig;
300
+ private keepBytes;
301
+ private target;
302
+ one(raw: RawResult): Promise<MediaFile>;
303
+ all(raws: RawResult[]): Promise<MediaFile[]>;
46
304
  }
47
- export interface MediaProgress {
305
+ interface CallEnv {
306
+ started: number;
307
+ deadline: number;
308
+ timeoutMs: number;
309
+ report: (status: string, jobId?: string) => void;
310
+ }
311
+ interface StyleInternals {
312
+ keyEnv?: string;
313
+ gatherMode?: GatherMode;
314
+ }
315
+ /** A media client over one JSON style (the ADR 0036 engine). Named `style.name ?? "style"`. */
316
+ export declare class StyleMediaClient implements MediaClient {
317
+ readonly name: string;
318
+ protected readonly style: MediaStyle;
319
+ protected readonly config: MediaClientConfig;
320
+ private readonly internals;
321
+ constructor(style: MediaStyle, config?: MediaClientConfig, internals?: StyleInternals);
322
+ supports(verb: string): boolean;
323
+ args(verb: string): MediaArgSpec[];
324
+ image(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
325
+ video(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
326
+ speech(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
327
+ music(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
328
+ transcribe(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
329
+ cloneVoice(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
330
+ talk(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
331
+ /** Hook for subclasses: the request body's defaults for a verb. */
332
+ protected defaults(_verb: MediaVerb, spec: MediaVerbStyle): Record<string, unknown>;
333
+ protected baseUrl(): string;
334
+ private run;
335
+ }
336
+ /** Make a media client from a parsed style (§7G.7). */
337
+ export declare function styleMediaClient(style: MediaStyle | LoadedMediaStyle, config?: MediaClientConfig): StyleMediaClient;
338
+ /** a2e.ai (§7G.9): a style client over the embedded preset, `A2E_API_KEY`, gather `download`. */
339
+ export declare class A2EMediaClient extends StyleMediaClient {
340
+ constructor(config?: MediaClientConfig);
341
+ protected defaults(verb: MediaVerb, spec: MediaVerbStyle): Record<string, unknown>;
342
+ }
343
+ interface ApiDef {
344
+ name: string;
345
+ keyEnv: string;
346
+ defaultUrl: string;
347
+ auth: (key: string) => Record<string, string>;
348
+ primary: MediaVerb;
349
+ interval: number;
350
+ verbs: Partial<Record<MediaVerb, MediaArgSpec[]>>;
351
+ }
352
+ interface ApiCall {
48
353
  verb: MediaVerb;
49
- jobId: string;
50
- status: string;
354
+ base: string;
355
+ job: HttpJob;
356
+ env: CallEnv;
357
+ gather: Gatherer;
358
+ interval: number;
359
+ maxBytes: number;
51
360
  }
52
- export interface MediaOptions {
53
- onProgress?: (p: MediaProgress) => void;
54
- /** HTTP transport (same seam as the LLM client's `fetch`). Omit ⇒ global fetch. */
55
- fetch?: typeof fetch;
361
+ /** The shared HTTP base for code-defined API clients (§7G.8 rules, gather, unavailable). */
362
+ export declare abstract class ApiMediaClient implements MediaClient {
363
+ readonly name: string;
364
+ protected readonly config: MediaClientConfig;
365
+ private readonly def;
366
+ protected constructor(def: ApiDef, config?: MediaClientConfig);
367
+ supports(verb: string): boolean;
368
+ args(verb: string): MediaArgSpec[];
369
+ /** The model for a verb: `models[verb]`, else `model` for the primary verb, else the default. */
370
+ protected model(verb: MediaVerb, dflt: string): string;
371
+ protected begin(verb: MediaVerb, ctx: MediaContext): ApiCall;
372
+ /** Poll until `check` says done; `check` returns the status text and an optional failure. */
373
+ protected pollUntil(c: ApiCall, ctx: MediaContext, check: () => Promise<{
374
+ status: string;
375
+ done: boolean;
376
+ error?: string;
377
+ }>): Promise<void>;
378
+ protected run(c: ApiCall, fn: () => Promise<MediaResult>): Promise<MediaResult>;
56
379
  }
57
- /** Per-call options of the function face. */
58
- export interface MediaCallOptions {
59
- /** Top-level keys overwrite the request body last. Never exposed on the tool face. */
60
- providerOptions?: Record<string, unknown>;
61
- signal?: AbortSignal;
380
+ /** ElevenLabs (§7G.9): speech (live-verified), music, transcribe, cloneVoice. */
381
+ export declare class ElevenLabsMediaClient extends ApiMediaClient {
382
+ constructor(config?: MediaClientConfig);
383
+ speech(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
384
+ music(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
385
+ transcribe(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
386
+ cloneVoice(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
387
+ }
388
+ /** OpenAI (§7G.9): image (live-verified), video, speech, transcribe; `url` ⇒ any compatible server. */
389
+ export declare class OpenAIMediaClient extends ApiMediaClient {
390
+ constructor(config?: MediaClientConfig);
391
+ image(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
392
+ speech(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
393
+ transcribe(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
394
+ video(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
395
+ }
396
+ /** OpenRouter (§7G.9): image through chat completions (live-verified). */
397
+ export declare class OpenRouterMediaClient extends ApiMediaClient {
398
+ constructor(config?: MediaClientConfig);
399
+ image(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
400
+ }
401
+ /** fal (§7G.9): the queue API for any hosted model id — image (live-verified), video. */
402
+ export declare class FalMediaClient extends ApiMediaClient {
403
+ constructor(config?: MediaClientConfig);
404
+ image(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
405
+ video(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
406
+ private queue;
407
+ }
408
+ /** What one JSON line of a CLI's stdout means. */
409
+ export interface CliEvent {
410
+ session?: string;
411
+ text?: string;
412
+ paths?: string[];
413
+ error?: string;
414
+ status?: string;
415
+ /** Provider-reported usage (§7G.12 D21). */
416
+ usage?: MediaUsage;
62
417
  }
418
+ /** How a {@link CliMediaClient} drives one CLI. */
419
+ export interface CliSpec {
420
+ name: string;
421
+ /** Default argv prefix when `config.command` is absent. */
422
+ command: string;
423
+ /** Prompt template per supported verb; `{prompt}` is replaced. */
424
+ templates: Partial<Record<MediaVerb, string>>;
425
+ /** Client argv after the command, for one run. */
426
+ argv(prompt: string, cwd: string, model?: string): string[];
427
+ /** Fixed env added to the process env. */
428
+ env?: Record<string, string>;
429
+ parse(obj: Record<string, unknown>, line: string): CliEvent;
430
+ /** A folder whose entries are candidate files once the session is known. */
431
+ folder?(session: string): string | undefined;
432
+ /** An unavailable message for the last error, or undefined (⇒ failed). */
433
+ unavailable?(error: string, verb: MediaVerb): string | undefined;
434
+ }
435
+ /** Runs a local subscription CLI once, headless, and collects the files it made (§7G.10). */
436
+ export declare class CliMediaClient implements MediaClient {
437
+ readonly name: string;
438
+ protected readonly config: MediaClientConfig;
439
+ private readonly spec;
440
+ /** Never start the CLI; write a fixed file instead (§7G CLI mock presets). */
441
+ private readonly mock;
442
+ constructor(spec: CliSpec, config?: MediaClientConfig, opts?: {
443
+ mock?: boolean;
444
+ });
445
+ supports(verb: string): boolean;
446
+ args(verb: string): MediaArgSpec[];
447
+ image(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
448
+ video(args: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
449
+ private run;
450
+ /**
451
+ * The CLI mock (§7G CLI mock presets): no process. Writes `<gather.dir>/<client>-mock-<verb>.<png|mp4>`
452
+ * (gather.dir default `<tmp>/toolnexus-media`) holding `toolnexus mock <verb>` and gathers it like a
453
+ * real CLI file; text = the exact prompt the CLI would have received; jobId "mock".
454
+ */
455
+ private mockRun;
456
+ }
457
+ /**
458
+ * The prompt a CLI style receives (§7G CLI hint folding): `prompt`, then the present size hints in
459
+ * canonical verb order as ` (h1, h2)`; nothing appended when none is present.
460
+ */
461
+ export declare function foldMediaPrompt(verb: MediaVerb | string, args: Record<string, unknown>): string;
462
+ /** Grok CLI (§7G.10): image, video via `grok -p … --output-format streaming-json`. */
463
+ export declare class GrokMediaClient extends CliMediaClient {
464
+ constructor(config?: MediaClientConfig);
465
+ }
466
+ /** Codex CLI (§7G.10): image via `codex exec --json` (ChatGPT plan). */
467
+ export declare class CodexMediaClient extends CliMediaClient {
468
+ constructor(config?: MediaClientConfig);
469
+ }
470
+ type VerbInput<T> = T & MediaCallOptions;
63
471
  export type ImageArgs = {
64
472
  prompt: string;
65
473
  width?: number;
@@ -77,50 +485,53 @@ export type SpeechArgs = {
77
485
  text: string;
78
486
  voice?: string;
79
487
  };
488
+ export type MusicArgs = {
489
+ prompt: string;
490
+ seconds?: number;
491
+ instrumental?: boolean;
492
+ lyrics?: string;
493
+ };
80
494
  export type TranscribeArgs = {
81
495
  audio: string;
496
+ language?: string;
82
497
  };
83
498
  export type CloneVoiceArgs = {
84
499
  name: string;
85
500
  samples: string[];
86
501
  };
87
- export type TalkingArgs = {
502
+ export type TalkArgs = {
88
503
  image: string;
89
- audio: string;
504
+ audio?: string;
505
+ text?: string;
506
+ voice?: string;
90
507
  };
91
- export interface MediaVerbArg {
92
- name: string;
93
- type: string;
94
- items?: string;
95
- description: string;
96
- required?: boolean;
97
- }
98
- export interface MediaVerbSpec {
99
- verb: MediaVerb;
100
- tool: string;
101
- description: string;
102
- args: MediaVerbArg[];
103
- }
104
- /** Canonical verbs — `conformance/media/verbs.json`, embedded verbatim (byte contract). */
105
- export declare const MEDIA_VERBS: MediaVerbSpec[];
106
- /** Read one style file (JSON). */
107
- export declare function loadMediaStyle(path: string): MediaStyle;
508
+ /** The seven verbs over an ordered list of clients; falls through only on `unavailable`. */
108
509
  export declare class Media {
109
- private readonly opts;
110
- private readonly styles;
111
- constructor(styles: MediaStyle | MediaStyle[], opts?: MediaOptions);
112
- private resolve;
113
- /** Generic entry point: run `verb` with normalised `args` (§7G engine). */
114
- generate(verb: MediaVerb | string, args: Record<string, unknown>, callOpts?: MediaCallOptions): Promise<MediaResult>;
510
+ readonly clients: MediaClient[];
511
+ constructor(clients: MediaClient | MediaClient[]);
512
+ supports(verb: MediaVerb | string): boolean;
513
+ /** Every verb some source supports, in canonical verb order. */
514
+ verbs(): MediaVerb[];
515
+ /** "style" when every source is a loaded style, else "client". */
516
+ private noun;
517
+ /** Generic entry point: route `verb` with canonical `args`. */
518
+ generate(verb: MediaVerb | string, args?: Record<string, unknown>, ctx?: MediaContext): Promise<MediaResult>;
519
+ private route;
115
520
  private typed;
116
- image(input: ImageArgs & MediaCallOptions): Promise<MediaResult>;
117
- video(input: VideoArgs & MediaCallOptions): Promise<MediaResult>;
118
- speech(input: SpeechArgs & MediaCallOptions): Promise<MediaResult>;
119
- transcribe(input: TranscribeArgs & MediaCallOptions): Promise<MediaResult>;
120
- cloneVoice(input: CloneVoiceArgs & MediaCallOptions): Promise<MediaResult>;
121
- talking(input: TalkingArgs & MediaCallOptions): Promise<MediaResult>;
122
- /** One Tool (source "media") per supported verb, in canonical order (§7G tool face). */
521
+ image(input: VerbInput<ImageArgs>): Promise<MediaResult>;
522
+ video(input: VerbInput<VideoArgs>): Promise<MediaResult>;
523
+ speech(input: VerbInput<SpeechArgs>): Promise<MediaResult>;
524
+ music(input: VerbInput<MusicArgs>): Promise<MediaResult>;
525
+ transcribe(input: VerbInput<TranscribeArgs>): Promise<MediaResult>;
526
+ cloneVoice(input: VerbInput<CloneVoiceArgs>): Promise<MediaResult>;
527
+ talk(input: VerbInput<TalkArgs>): Promise<MediaResult>;
528
+ /** One Tool (source "media") per verb any client supports, in `verbs.json` order (§7G.6). */
123
529
  tools(): Tool[];
124
530
  }
125
- /** Build a media engine over one style or a list (first style declaring a verb wins). */
126
- export declare function createMedia(styles: MediaStyle | MediaStyle[], opts?: MediaOptions): Media;
531
+ /** The saved file's absolute path for a part a media tool produced, if it has one (D20). */
532
+ export declare function mediaPartPath(part: ContentPart): string | undefined;
533
+ /** Route the seven verbs over one client or an ordered list (§7G.3). */
534
+ export declare function createMedia(clients: MediaClient | MediaClient[]): Media;
535
+ /** One-shot sugar: `createMedia(loadMediaStyle(style, config)).generate(verb, args)`. */
536
+ export declare function generateMedia(style: MediaStylePreset | string, verb: MediaVerb | string, args?: Record<string, unknown>, config?: MediaClientConfig): Promise<MediaResult>;
537
+ export {};