toolnexus 0.23.0 → 0.24.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/README.md CHANGED
@@ -135,6 +135,29 @@ const out = await gate(c, state, questions, [
135
135
  filter, content and model batteries into `hooks`. A `beforeLLM` hook may return `{ model }` to
136
136
  send another model for that turn only.
137
137
 
138
+ ## Media generation
139
+
140
+ Generate images, video and speech (plus transcription, voice cloning and talking-head video)
141
+ from a **JSON style** instead of provider code. Async jobs are started and polled for you. The same
142
+ verbs become agent tools (`generate_image`, `generate_video`, `generate_speech`, …), and whatever
143
+ they produce lands in `RunResult.files`. `examples/media-styles/a2e.json` ships first and reads
144
+ `A2E_API_KEY` at call time. Its result URLs expire in 3–30 days, so save what you keep. SPEC §7G;
145
+ guide: <https://muthuishere.github.io/toolnexus/media/>.
146
+
147
+ ```ts
148
+ import { loadMediaStyle, createMedia, createToolkit } from "toolnexus"
149
+
150
+ const media = createMedia(loadMediaStyle("examples/media-styles/a2e.json"), {
151
+ onProgress: ({ verb, status }) => console.log(verb, status),
152
+ })
153
+ const img = await media.image({ prompt: "a red fox in fresh snow", width: 1024, height: 768 })
154
+ const vid = await media.video({ prompt: "the fox blinks", image: img.files[0].url, seconds: 5 })
155
+
156
+ const tk = await createToolkit({ media }) // the agent gets generate_image, …
157
+ const res = await agent.run("Draw a fox, then animate it.", { toolkit: tk })
158
+ for (const f of res.files) console.log(f.from, f.mimeType, f.url)
159
+ ```
160
+
138
161
  ## Documentation
139
162
 
140
163
  Everything else — the full surface, with runnable examples — lives on the docs site:
@@ -76,6 +76,7 @@ export async function runGated(ask, prompt, completion) {
76
76
  throw new Error("toolnexus: completion.verify is required");
77
77
  }
78
78
  let accumulated = [];
79
+ let accFiles = [];
79
80
  let last;
80
81
  let reason = "";
81
82
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
@@ -84,7 +85,9 @@ export async function runGated(ask, prompt, completion) {
84
85
  // The gate judges the ACCUMULATED work, so an agent cannot escape it by
85
86
  // declining to re-declare its plan on a retry.
86
87
  accumulated = [...accumulated, ...r.toolCalls];
87
- const judged = { ...r, toolCalls: accumulated };
88
+ // RunResult.files is derived from toolCalls, so it accumulates with them (§8).
89
+ accFiles = [...accFiles, ...(r.files ?? [])];
90
+ const judged = { ...r, toolCalls: accumulated, files: accFiles };
88
91
  last = judged;
89
92
  if (r.status && r.status !== "done") {
90
93
  // The run stopped for its own reason (suspension, budget). If the gate was
@@ -751,7 +751,7 @@ export class AgentRuntime {
751
751
  const team = [...(parent.def.team ?? [])].sort();
752
752
  const advertised = team.map((n) => (this.registry[n] ? `${n}: ${this.registry[n].does}` : n)).join("; ");
753
753
  const rt = this;
754
- return defineTool({
754
+ const tool = defineTool({
755
755
  name: "task",
756
756
  description: `Delegate a subtask to an isolated subagent (it runs on a fresh transcript and returns only its final answer). Available agents — ${advertised}`,
757
757
  inputSchema: {
@@ -813,5 +813,8 @@ export class AgentRuntime {
813
813
  };
814
814
  },
815
815
  });
816
+ // Each subagent is isolated and the runtime's own gate schedules the children,
817
+ // so a fan-out of task calls runs concurrently (SPEC §8 "Tool scheduling").
818
+ return { ...tool, concurrencySafe: () => true };
816
819
  }
817
820
  }
package/dist/client.d.ts CHANGED
@@ -7,7 +7,7 @@ import type { Toolkit } from "./toolkit.js";
7
7
  import type { ToolHints, ToolResult, Request, Answer } from "./types.js";
8
8
  import { type PromptCacheOptions } from "./promptcache.js";
9
9
  import { type ToolTier, type ToolTierOptions } from "./tooltiers.js";
10
- import type { PromptInput, UnsupportedPartMode } from "./content.js";
10
+ import type { ContentPart, PromptInput, UnsupportedPartMode } from "./content.js";
11
11
  import type { TranslateRequest, TranslateResult } from "./translate.js";
12
12
  export type ClientStyle = "openai" | "anthropic";
13
13
  export interface ClientOptions {
@@ -26,6 +26,10 @@ export interface ClientOptions {
26
26
  headers?: Record<string, string>;
27
27
  systemPrompt?: string;
28
28
  maxTurns?: number;
29
+ /** Cap on concurrency-safe tool calls of one response running at once (SPEC §8 "Tool
30
+ * scheduling"). Absent ⇒ env `TOOLNEXUS_MAX_TOOL_CONCURRENCY` when a positive integer, else 10.
31
+ * Unsafe calls (anything not read-only) always run alone. */
32
+ maxToolConcurrency?: number;
29
33
  hooks?: Hooks;
30
34
  /** Retries on transient LLM errors (`429`/`500`/`502`/`503`/`504`/`529` + network). Default 2.
31
35
  * Widen the status set with `retryableStatuses`. */
@@ -299,7 +303,19 @@ export interface ToolCallRecord {
299
303
  output: string;
300
304
  isError: boolean;
301
305
  metadata?: Record<string, unknown>;
306
+ /** §8: the ToolResult's parts — present iff the result had parts. */
307
+ parts?: ContentPart[];
302
308
  }
309
+ /** §8 RunResult.files entry: a non-text part a tool call produced this run. */
310
+ export type RunFile = {
311
+ type: "image" | "file" | "audio";
312
+ mimeType: string;
313
+ url?: string;
314
+ data?: string;
315
+ name?: string;
316
+ from: string;
317
+ callId: string;
318
+ };
303
319
  /** Token usage, summed across every LLM round trip in the run. */
304
320
  export interface Usage {
305
321
  promptTokens: number;
@@ -319,6 +335,8 @@ export interface RunResult {
319
335
  messages: any[];
320
336
  /** Every tool call made, with its output, error flag, and metadata. */
321
337
  toolCalls: ToolCallRecord[];
338
+ /** Every non-text part produced by tool calls this run, in call order (§8). Always present. */
339
+ files: RunFile[];
322
340
  /** Total number of tool calls (= toolCalls.length). */
323
341
  toolCallCount: number;
324
342
  /** Number of LLM round trips. */
@@ -491,6 +509,10 @@ export declare class Client {
491
509
  /** Run one tool through beforeTool/afterTool hooks (mutate args, short-circuit, transform result). */
492
510
  private runTool;
493
511
  private runToolDirect;
512
+ /** Runs one response's calls under the tool schedule (SPEC §8 "Tool scheduling"). */
513
+ private schedule;
514
+ /** One call's safety; looks through `call_tool` to the tool it names. Unknown ⇒ unsafe. */
515
+ private callSafe;
494
516
  /** ToolTiers `call_tool {name, arguments}` -> the real call; undefined when tiers are off. */
495
517
  private unwrapCall;
496
518
  /** The RunResult.toolCalls entry: a `call_tool` call is recorded as the real tool with its
package/dist/client.js CHANGED
@@ -3,6 +3,7 @@ import { toOpenAI, toAnthropic } from "./adapters.js";
3
3
  import { applyPromptCache } from "./promptcache.js";
4
4
  import { buildToolPlan, toolSearch, unwrapCallTool } from "./tooltiers.js";
5
5
  import { isRetryableStatus, retryAfterMs } from "./retry.js";
6
+ import { isConcurrencySafe, resolveMaxToolConcurrency, scheduleCalls } from "./toolconcurrency.js";
6
7
  import { toOpenAIWire, toAnthropicWire, checkPromptParts } from "./wire.js";
7
8
  import { finishReasonFor, argsString, openAIMessagesToAnthropic, openAIToolsToAnthropic, openAIToolChoiceToAnthropic, hasSystemMessage, } from "./translate.js";
8
9
  /**
@@ -106,6 +107,20 @@ function delay(ms, signal) {
106
107
  signal.addEventListener("abort", () => { clearTimeout(t); reject(signal.reason ?? new Error("aborted")); }, { once: true });
107
108
  });
108
109
  }
110
+ /** Model tool-call id of each record, kept off the record itself (§8 shape has no id). */
111
+ const callIds = new WeakMap();
112
+ /** RunResult.files: every non-text part of every tool call, in call order (§8). */
113
+ function runFiles(toolCalls) {
114
+ const out = [];
115
+ for (const r of toolCalls) {
116
+ for (const p of r.parts ?? []) {
117
+ if (p.type === "text")
118
+ continue;
119
+ out.push({ ...p, from: r.name, callId: callIds.get(r) ?? "" });
120
+ }
121
+ }
122
+ return out;
123
+ }
109
124
  function addUsage(acc, raw, style) {
110
125
  if (!raw)
111
126
  return;
@@ -718,15 +733,34 @@ export class Client {
718
733
  this.emitTool(name, source, result, t0);
719
734
  return { args: a, result };
720
735
  }
736
+ /** Runs one response's calls under the tool schedule (SPEC §8 "Tool scheduling"). */
737
+ schedule(toolkit, items, key, fn) {
738
+ return scheduleCalls(items, (item) => {
739
+ const [name, args] = key(item);
740
+ return this.callSafe(toolkit, name, args);
741
+ }, resolveMaxToolConcurrency(this.opts.maxToolConcurrency), fn);
742
+ }
743
+ /** One call's safety; looks through `call_tool` to the tool it names. Unknown ⇒ unsafe. */
744
+ callSafe(toolkit, name, args) {
745
+ if (this.opts.toolTiers && name === "tool_search")
746
+ return true;
747
+ const inner = this.unwrapCall(name, args ?? {});
748
+ const tool = toolkit?.get(inner ? inner.name : name);
749
+ return tool ? isConcurrencySafe(tool, inner ? inner.args : (args ?? {})) : false;
750
+ }
721
751
  /** ToolTiers `call_tool {name, arguments}` -> the real call; undefined when tiers are off. */
722
752
  unwrapCall(name, args) {
723
753
  return this.opts.toolTiers ? unwrapCallTool(name, args) : undefined;
724
754
  }
725
755
  /** The RunResult.toolCalls entry: a `call_tool` call is recorded as the real tool with its
726
756
  * inner arguments, the name hooks and stream events see (the transcript keeps the wrapper). */
727
- toolCallRecord(name, args, result) {
757
+ toolCallRecord(name, args, result, callId) {
728
758
  const inner = this.unwrapCall(name, args);
729
- return { name: inner ? inner.name : name, args: inner ? inner.args : args, output: result.output, isError: result.isError, metadata: result.metadata };
759
+ const rec = { name: inner ? inner.name : name, args: inner ? inner.args : args, output: result.output, isError: result.isError, metadata: result.metadata };
760
+ if (result.parts?.length)
761
+ rec.parts = result.parts;
762
+ callIds.set(rec, callId ?? "");
763
+ return rec;
730
764
  }
731
765
  /** The stream's tool_call event, naming the real tool for a `call_tool` call. */
732
766
  callEvent(id, name, args) {
@@ -886,7 +920,7 @@ export class Client {
886
920
  return this.endRun(runStart, lastModel, msg.content ?? "", messages, toolCalls, turns, usage);
887
921
  // execute all tool calls in this turn concurrently (true parallel tool calling)
888
922
  done.clear();
889
- const settled = await untilAborted(signal, Promise.all(calls.map(async (call) => {
923
+ const settled = await untilAborted(signal, this.schedule(toolkit, calls, (call) => [call.function.name, safeJson(call.function.arguments)], async (call) => {
890
924
  let { args, result } = await this.runTool(toolkit, call.function.name, safeJson(call.function.arguments), call.id, turn, signal);
891
925
  let halted;
892
926
  const req = pendingOf(result);
@@ -898,12 +932,12 @@ export class Client {
898
932
  if (!halted && call.id)
899
933
  done.set(call.id, result);
900
934
  return { call, args, result, halted };
901
- })));
935
+ }));
902
936
  // Record in tool-call order; on the FIRST durable halt, surface it and stop — deterministic,
903
937
  // and the later suspensions' placeholder results never enter the transcript (they re-suspend
904
938
  // on resume). Mirrors the streaming path.
905
939
  for (const s of settled) {
906
- toolCalls.push(this.toolCallRecord(s.call.function.name, s.args, s.result));
940
+ toolCalls.push(this.toolCallRecord(s.call.function.name, s.args, s.result, s.call.id));
907
941
  messages.push(toolMessage(s.call.id, s.call.function.name, s.result));
908
942
  if (s.halted)
909
943
  return this.pendingRun(runStart, lastModel, s.halted, messages, toolCalls, turns, usage);
@@ -919,7 +953,7 @@ export class Client {
919
953
  }
920
954
  result(model, text, messages, toolCalls, turns, usage, exhausted = false) {
921
955
  const incomplete = exhausted && text === "";
922
- const r = { text, messages, toolCalls, toolCallCount: toolCalls.length, turns, usage, model, status: incomplete ? "incomplete" : "done" };
956
+ const r = { text, messages, toolCalls, files: runFiles(toolCalls), toolCallCount: toolCalls.length, turns, usage, model, status: incomplete ? "incomplete" : "done" };
923
957
  if (incomplete)
924
958
  r.limit = "maxTurns";
925
959
  return r;
@@ -927,7 +961,7 @@ export class Client {
927
961
  /** §10: a run halted because a tool suspended and no `waitFor` was configured. */
928
962
  pendingRun(runStart, model, request, messages, toolCalls, turns, usage) {
929
963
  this.emit({ event: "run", model, turns, toolCalls: toolCalls.length, totalTokens: usage.totalTokens, ms: Date.now() - runStart });
930
- return { text: request.prompt, messages, toolCalls, toolCallCount: toolCalls.length, turns, usage, model, status: "pending", pending: request };
964
+ return { text: request.prompt, messages, toolCalls, files: runFiles(toolCalls), toolCallCount: toolCalls.length, turns, usage, model, status: "pending", pending: request };
931
965
  }
932
966
  /**
933
967
  * §10: resolve a suspended tool result. Calls `waitFor(request)`, and on `ok` re-executes the
@@ -1008,7 +1042,7 @@ export class Client {
1008
1042
  }
1009
1043
  // execute all tool_use blocks in this turn concurrently (true parallel tool calling)
1010
1044
  done.clear();
1011
- const settled = await untilAborted(signal, Promise.all(uses.map(async (use) => {
1045
+ const settled = await untilAborted(signal, this.schedule(toolkit, uses, (use) => [use.name, use.input ?? {}], async (use) => {
1012
1046
  let { args, result } = await this.runTool(toolkit, use.name, use.input ?? {}, use.id, turn, signal);
1013
1047
  let halted;
1014
1048
  const req = pendingOf(result);
@@ -1020,14 +1054,14 @@ export class Client {
1020
1054
  if (!halted && use.id)
1021
1055
  done.set(use.id, result);
1022
1056
  return { use, args, result, halted };
1023
- })));
1057
+ }));
1024
1058
  // Record in tool-call order; on the FIRST durable halt, include that tool_result block, stop
1025
1059
  // building the content, and surface it — deterministic (G3), later suspensions re-suspend on
1026
1060
  // resume. Mirrors the OpenAI path and the streaming loops.
1027
1061
  const content = [];
1028
1062
  let halted;
1029
1063
  for (const s of settled) {
1030
- toolCalls.push(this.toolCallRecord(s.use.name, s.args, s.result));
1064
+ toolCalls.push(this.toolCallRecord(s.use.name, s.args, s.result, s.use.id));
1031
1065
  content.push(toolResultBlock(s.use.id, s.result));
1032
1066
  if (s.halted) {
1033
1067
  halted = s.halted;
@@ -1136,12 +1170,12 @@ export class Client {
1136
1170
  for (const c of calls)
1137
1171
  yield this.callEvent(c.id, c.name, safeJson(c.args));
1138
1172
  done.clear();
1139
- const settled = await untilAborted(signal, Promise.all(calls.map(async (c) => {
1173
+ const settled = await untilAborted(signal, this.schedule(toolkit, calls, (c) => [c.name, safeJson(c.args)], async (c) => {
1140
1174
  const r = await this.runTool(toolkit, c.name, safeJson(c.args), c.id, turn, signal);
1141
1175
  if (!pendingOf(r.result) && c.id)
1142
1176
  done.set(c.id, r.result);
1143
1177
  return r;
1144
- })));
1178
+ }));
1145
1179
  for (let i = 0; i < calls.length; i++) {
1146
1180
  const c = calls[i];
1147
1181
  let { args, result } = settled[i];
@@ -1151,13 +1185,13 @@ export class Client {
1151
1185
  const r = await this.resolvePending(toolkit, c.name, args, req, c.id, turn, signal);
1152
1186
  result = r.result;
1153
1187
  if (r.halted) {
1154
- toolCalls.push(this.toolCallRecord(c.name, args, result));
1188
+ toolCalls.push(this.toolCallRecord(c.name, args, result, c.id));
1155
1189
  messages.push(toolMessage(c.id, c.name, result));
1156
1190
  yield { type: "done", result: this.pendingRun(runStart, lastModel, r.halted, messages, toolCalls, turns, usage) };
1157
1191
  return;
1158
1192
  }
1159
1193
  }
1160
- toolCalls.push(this.toolCallRecord(c.name, args, result));
1194
+ toolCalls.push(this.toolCallRecord(c.name, args, result, c.id));
1161
1195
  messages.push(toolMessage(c.id, c.name, result));
1162
1196
  yield this.resultEvent(c.id, c.name, safeJson(c.args), result);
1163
1197
  }
@@ -1256,12 +1290,12 @@ export class Client {
1256
1290
  for (const u of uses)
1257
1291
  yield this.callEvent(u.id, u.name, u.input);
1258
1292
  done.clear();
1259
- const settled = await untilAborted(signal, Promise.all(uses.map(async (u) => {
1293
+ const settled = await untilAborted(signal, this.schedule(toolkit, uses, (u) => [u.name, u.input ?? {}], async (u) => {
1260
1294
  const r = await this.runTool(toolkit, u.name, u.input ?? {}, u.id, turn, signal);
1261
1295
  if (!pendingOf(r.result) && u.id)
1262
1296
  done.set(u.id, r.result);
1263
1297
  return r;
1264
- })));
1298
+ }));
1265
1299
  const results = [];
1266
1300
  for (let i = 0; i < uses.length; i++) {
1267
1301
  const u = uses[i];
@@ -1272,14 +1306,14 @@ export class Client {
1272
1306
  const r = await this.resolvePending(toolkit, u.name, args, req, u.id, turn, signal);
1273
1307
  result = r.result;
1274
1308
  if (r.halted) {
1275
- toolCalls.push(this.toolCallRecord(u.name, args, result));
1309
+ toolCalls.push(this.toolCallRecord(u.name, args, result, u.id));
1276
1310
  results.push(toolResultBlock(u.id, result));
1277
1311
  messages.push({ role: "user", content: results });
1278
1312
  yield { type: "done", result: this.pendingRun(runStart, lastModel, r.halted, messages, toolCalls, turns, usage) };
1279
1313
  return;
1280
1314
  }
1281
1315
  }
1282
- toolCalls.push(this.toolCallRecord(u.name, args, result));
1316
+ toolCalls.push(this.toolCallRecord(u.name, args, result, u.id));
1283
1317
  results.push(toolResultBlock(u.id, result));
1284
1318
  yield this.resultEvent(u.id, u.name, u.input, result);
1285
1319
  }
package/dist/index.d.ts CHANGED
@@ -22,5 +22,7 @@ export * from "./batteries.js";
22
22
  export { State, context, questionMap, ask, gate, decide, applyGate, applyPolicy, answersOf, staticClassifier, Tape, DEFAULT_BANDS, type NamedQuestion, type Band, type Bands, type Answers, type Rule, type GateOutcome, type Policy, } from "./judge.js";
23
23
  export * from "./promptcache.js";
24
24
  export * from "./tooltiers.js";
25
+ export * from "./toolconcurrency.js";
25
26
  export * from "./models.js";
26
27
  export * from "./builtin_extras.js";
28
+ export * from "./media.js";
package/dist/index.js CHANGED
@@ -25,5 +25,7 @@ export * from "./batteries.js";
25
25
  export { State, context, questionMap, ask, gate, decide, applyGate, applyPolicy, answersOf, staticClassifier, Tape, DEFAULT_BANDS, } from "./judge.js";
26
26
  export * from "./promptcache.js";
27
27
  export * from "./tooltiers.js";
28
+ export * from "./toolconcurrency.js";
28
29
  export * from "./models.js";
29
30
  export * from "./builtin_extras.js";
31
+ export * from "./media.js";
@@ -0,0 +1,126 @@
1
+ import type { Tool } from "./types.js";
2
+ export type MediaVerb = "image" | "video" | "speech" | "transcribe" | "cloneVoice" | "talking";
3
+ export type MediaKind = "image" | "video" | "audio" | "text";
4
+ export interface MediaVerbStyle {
5
+ mode: "sync" | "async";
6
+ kind: MediaKind;
7
+ start: {
8
+ method?: string;
9
+ path: string;
10
+ };
11
+ defaults?: Record<string, unknown>;
12
+ args: Record<string, string>;
13
+ idPath?: string;
14
+ poll?: {
15
+ method?: string;
16
+ path: string;
17
+ statusPath: string;
18
+ done?: string[];
19
+ failed?: string[];
20
+ errorPath?: string;
21
+ intervalMs?: number;
22
+ timeoutMs?: number;
23
+ };
24
+ resultPath: string;
25
+ }
26
+ export interface MediaStyle {
27
+ baseUrl: string;
28
+ headers?: Record<string, string>;
29
+ errorEnvelope?: {
30
+ codePath: string;
31
+ okValues: unknown[];
32
+ messagePath?: string;
33
+ };
34
+ verbs: Partial<Record<MediaVerb, MediaVerbStyle>>;
35
+ }
36
+ export interface MediaFile {
37
+ type: "image" | "audio" | "file";
38
+ mimeType: string;
39
+ url: string;
40
+ }
41
+ export interface MediaResult {
42
+ files: MediaFile[];
43
+ text?: string;
44
+ jobId?: string;
45
+ status: string;
46
+ }
47
+ export interface MediaProgress {
48
+ verb: MediaVerb;
49
+ jobId: string;
50
+ status: string;
51
+ }
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;
56
+ }
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;
62
+ }
63
+ export type ImageArgs = {
64
+ prompt: string;
65
+ width?: number;
66
+ height?: number;
67
+ aspectRatio?: string;
68
+ seed?: number;
69
+ };
70
+ export type VideoArgs = {
71
+ prompt: string;
72
+ image?: string;
73
+ seconds?: number;
74
+ aspectRatio?: string;
75
+ };
76
+ export type SpeechArgs = {
77
+ text: string;
78
+ voice?: string;
79
+ };
80
+ export type TranscribeArgs = {
81
+ audio: string;
82
+ };
83
+ export type CloneVoiceArgs = {
84
+ name: string;
85
+ samples: string[];
86
+ };
87
+ export type TalkingArgs = {
88
+ image: string;
89
+ audio: string;
90
+ };
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;
108
+ 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>;
115
+ 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). */
123
+ tools(): Tool[];
124
+ }
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;