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 +23 -0
- package/dist/agents/loop.js +4 -1
- package/dist/agents/runtime.js +4 -1
- package/dist/client.d.ts +23 -1
- package/dist/client.js +52 -18
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/media.d.ts +126 -0
- package/dist/media.js +540 -0
- package/dist/toolconcurrency.d.ts +16 -0
- package/dist/toolconcurrency.js +59 -0
- package/dist/toolkit.d.ts +3 -0
- package/dist/toolkit.js +1 -1
- package/dist/types.d.ts +4 -1
- package/package.json +3 -2
- package/src/agents/loop.ts +4 -1
- package/src/agents/runtime.ts +4 -1
- package/src/client.ts +72 -21
- package/src/index.ts +2 -0
- package/src/media.ts +604 -0
- package/src/toolconcurrency.ts +67 -0
- package/src/toolkit.ts +4 -1
- package/src/types.ts +4 -1
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:
|
package/dist/agents/loop.js
CHANGED
|
@@ -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
|
-
|
|
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
|
package/dist/agents/runtime.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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";
|
package/dist/media.d.ts
ADDED
|
@@ -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;
|