@statelyai/agent 1.1.6 → 2.0.0-alpha.6
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/LICENSE +21 -0
- package/dist/ai-sdk.cjs +249 -0
- package/dist/ai-sdk.d.cts +168 -0
- package/dist/ai-sdk.d.mts +168 -0
- package/dist/ai-sdk.mjs +241 -0
- package/dist/cli.cjs +63 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +64 -0
- package/dist/decision-CX3YdwrO.cjs +1239 -0
- package/dist/decision-D1654JdD.mjs +940 -0
- package/dist/index.cjs +54 -0
- package/dist/index.d.cts +1217 -0
- package/dist/index.d.mts +1194 -405
- package/dist/index.mjs +3 -588
- package/dist/openai-compat.cjs +319 -0
- package/dist/openai-compat.d.cts +98 -0
- package/dist/openai-compat.d.mts +98 -0
- package/dist/openai-compat.mjs +312 -0
- package/dist/src-CEa947Dm.mjs +2449 -0
- package/dist/src-wBfi-kTA.cjs +2568 -0
- package/dist/text-logic-1ZQkO3zr.d.cts +682 -0
- package/dist/text-logic-2EMJIS-n.d.mts +682 -0
- package/dist/types-BHjeDdch.d.cts +208 -0
- package/dist/types-Cq1YlAQ6.d.mts +208 -0
- package/dist/utils-CWUCa3pF.d.mts +108 -0
- package/dist/utils-lK1wnL2i.d.cts +108 -0
- package/dist/zod.cjs +31 -0
- package/dist/zod.d.cts +30 -0
- package/dist/zod.d.mts +30 -0
- package/dist/zod.mjs +30 -0
- package/package.json +109 -28
- package/readme.md +144 -6
- package/schemas/agent-workflow.json +527 -0
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.env.template +0 -3
- package/.github/actions/ci-setup/action.yml +0 -24
- package/.github/workflows/release.yml +0 -46
- package/.vscode/launch.json +0 -28
- package/CHANGELOG.md +0 -222
- package/dist/index.d.ts +0 -428
- package/dist/index.js +0 -621
- package/examples/chatbot.ts +0 -71
- package/examples/cot.ts +0 -89
- package/examples/email.ts +0 -118
- package/examples/example.ts +0 -81
- package/examples/goal.ts +0 -94
- package/examples/helpers/helpers.ts +0 -17
- package/examples/helpers/loader.ts +0 -32
- package/examples/helpers/runner.ts +0 -27
- package/examples/joke.ts +0 -225
- package/examples/multi.ts +0 -103
- package/examples/newspaper.ts +0 -324
- package/examples/number.ts +0 -102
- package/examples/raffle.ts +0 -105
- package/examples/sandbox.ts +0 -28
- package/examples/simple.ts +0 -39
- package/examples/support.ts +0 -147
- package/examples/ticTacToe.ts +0 -224
- package/examples/todo.ts +0 -137
- package/examples/tutor.ts +0 -100
- package/examples/verify.ts +0 -120
- package/examples/weather.ts +0 -178
- package/examples/wiki.ts +0 -30
- package/examples/word.ts +0 -171
- package/src/adapters/vercel.ts +0 -7
- package/src/agent-experimental.ts +0 -221
- package/src/agent.test.ts +0 -506
- package/src/agent.ts +0 -300
- package/src/decision.test.ts +0 -179
- package/src/decision.ts +0 -84
- package/src/index.ts +0 -4
- package/src/memory.ts +0 -25
- package/src/planners/shortestPathPlanner.ts +0 -22
- package/src/planners/simplePlanner.ts +0 -139
- package/src/schemas.ts +0 -11
- package/src/strategies/chain-of-note.ts +0 -155
- package/src/templates/defaultText.ts +0 -18
- package/src/text.ts +0 -241
- package/src/types.ts +0 -499
- package/src/utils.ts +0 -72
- package/tsconfig.json +0 -109
- package/vitest.config.ts +0 -9
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_decision = require("./decision-CX3YdwrO.cjs");
|
|
3
|
+
//#region src/openai-compat/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* OpenAI-compatible Chat Completions adapter — a COMPLETE `{ generateText,
|
|
6
|
+
* streamText, decide }` executor set built on raw `fetch`, with zero runtime
|
|
7
|
+
* dependencies (no `openai` package, no Vercel AI SDK).
|
|
8
|
+
*
|
|
9
|
+
* The OpenAI Chat Completions wire format is the lingua franca of hosted and
|
|
10
|
+
* local inference: Groq, Together, Fireworks, OpenRouter, vLLM, Ollama, LM
|
|
11
|
+
* Studio, and OpenAI itself all speak it. Point `baseUrl` at any of them.
|
|
12
|
+
*
|
|
13
|
+
* Compare `createAiSdkExecutors` in `../ai-sdk/index.ts` (the AI-SDK-backed
|
|
14
|
+
* adapter) — same three-function contract, different transport. The request
|
|
15
|
+
* mapping is ported from `examples/openai-sdk-host/index.ts`, but wired
|
|
16
|
+
* against `POST {baseUrl}/chat/completions` instead of the `openai` package.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Reads a Standard Schema's optional `~standard.jsonSchema.input()` extension
|
|
20
|
+
* (implemented by e.g. Zod v4's `z.toJSONSchema`), awaiting it when it returns
|
|
21
|
+
* a Promise. Returns `undefined` when the schema doesn't expose the extension.
|
|
22
|
+
* Thin re-export of core's {@link getJsonSchema}.
|
|
23
|
+
*/
|
|
24
|
+
const extractJsonSchema = require_decision.getJsonSchema;
|
|
25
|
+
/** Maps `AgentTextRequest.messages`/`system`/`prompt` to Chat Completions messages. */
|
|
26
|
+
function toOpenAiMessages(request) {
|
|
27
|
+
if (request.messages) return request.messages.flatMap((message) => {
|
|
28
|
+
const content = typeof message.content === "string" ? message.content : "";
|
|
29
|
+
switch (message.role) {
|
|
30
|
+
case "system": return [{
|
|
31
|
+
role: "system",
|
|
32
|
+
content
|
|
33
|
+
}];
|
|
34
|
+
case "user": return [{
|
|
35
|
+
role: "user",
|
|
36
|
+
content
|
|
37
|
+
}];
|
|
38
|
+
case "assistant": return [{
|
|
39
|
+
role: "assistant",
|
|
40
|
+
content
|
|
41
|
+
}];
|
|
42
|
+
case "tool": return message.content.map((part) => ({
|
|
43
|
+
role: "tool",
|
|
44
|
+
content: part.output.type === "text" || part.output.type === "error-text" ? part.output.value : JSON.stringify(part.output.value),
|
|
45
|
+
tool_call_id: part.toolCallId
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const messages = [];
|
|
50
|
+
if (request.system) messages.push({
|
|
51
|
+
role: "system",
|
|
52
|
+
content: request.system
|
|
53
|
+
});
|
|
54
|
+
messages.push({
|
|
55
|
+
role: "user",
|
|
56
|
+
content: request.prompt ?? ""
|
|
57
|
+
});
|
|
58
|
+
return messages;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Maps sampling/stop settings. Targets `max_tokens` (not
|
|
62
|
+
* `max_completion_tokens`) — it's the field every OpenAI-compatible backend
|
|
63
|
+
* accepts (Ollama, vLLM, Groq, …), where `max_completion_tokens` is
|
|
64
|
+
* OpenAI-only. Undefined fields are pruned so they never hit the wire.
|
|
65
|
+
*/
|
|
66
|
+
function toOpenAiCallSettings(request) {
|
|
67
|
+
return pruneUndefined({
|
|
68
|
+
temperature: request.temperature,
|
|
69
|
+
max_tokens: request.maxOutputTokens,
|
|
70
|
+
top_p: request.topP,
|
|
71
|
+
seed: request.seed,
|
|
72
|
+
stop: request.stopSequences
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/** One wire function tool per `AgentTools` entry. */
|
|
76
|
+
function toOpenAiTools(tools) {
|
|
77
|
+
return Object.entries(tools).flatMap(([name, descriptor]) => {
|
|
78
|
+
if (!descriptor) return [];
|
|
79
|
+
const inputSchema = typeof descriptor === "function" ? void 0 : descriptor.inputSchema;
|
|
80
|
+
return [{
|
|
81
|
+
type: "function",
|
|
82
|
+
function: {
|
|
83
|
+
name,
|
|
84
|
+
description: typeof descriptor === "function" ? void 0 : descriptor.description,
|
|
85
|
+
parameters: (require_decision.isStandardSchema(inputSchema) ? require_decision.getJsonSchemaSync(inputSchema) : void 0) ?? {}
|
|
86
|
+
}
|
|
87
|
+
}];
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** One wire function tool per candidate decision event — the
|
|
91
|
+
* "tool-per-event + tool_choice: 'required'" recipe. */
|
|
92
|
+
function toOpenAiEventTools(events) {
|
|
93
|
+
return events.map((event) => ({
|
|
94
|
+
type: "function",
|
|
95
|
+
function: {
|
|
96
|
+
name: event.toolName,
|
|
97
|
+
description: `Choose the '${event.type}' move.`,
|
|
98
|
+
parameters: require_decision.getJsonSchemaSync(event.inputSchema) ?? {}
|
|
99
|
+
}
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
/** Messages for a decision request, with prior failed `attempts` rendered as
|
|
103
|
+
* appended user messages (via core's {@link renderDecisionAttempts}) so
|
|
104
|
+
* retries converge. */
|
|
105
|
+
function toDecisionMessages(request) {
|
|
106
|
+
const messages = toOpenAiMessages(request);
|
|
107
|
+
for (const attempt of require_decision.renderDecisionAttempts(request)) messages.push({
|
|
108
|
+
role: "user",
|
|
109
|
+
content: attempt.content
|
|
110
|
+
});
|
|
111
|
+
return messages;
|
|
112
|
+
}
|
|
113
|
+
function pruneUndefined(record) {
|
|
114
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== void 0));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Builds a complete `{ generateText, streamText, decide }` executor set over
|
|
118
|
+
* the OpenAI Chat Completions wire format via raw `fetch`.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* const executors = createOpenAiCompatExecutors({
|
|
123
|
+
* baseUrl: 'https://api.groq.com/openai/v1',
|
|
124
|
+
* apiKey: process.env.GROQ_API_KEY,
|
|
125
|
+
* models: { quick: 'llama-3.3-70b-versatile' },
|
|
126
|
+
* });
|
|
127
|
+
* const result = await runAgent(machine, { input, executors });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
function createOpenAiCompatExecutors(options) {
|
|
131
|
+
const doFetch = options.fetch ?? globalThis.fetch;
|
|
132
|
+
if (!doFetch) throw new Error("createOpenAiCompatExecutors: no `fetch` available — pass options.fetch for this runtime.");
|
|
133
|
+
const url = `${options.baseUrl.replace(/\/+$/, "")}/chat/completions`;
|
|
134
|
+
function resolveModel(modelRef) {
|
|
135
|
+
const resolved = options.models?.[modelRef] ?? modelRef ?? options.model;
|
|
136
|
+
if (!resolved) throw new Error("createOpenAiCompatExecutors: no model to send — set request.model, options.model, or options.models.");
|
|
137
|
+
return resolved;
|
|
138
|
+
}
|
|
139
|
+
function buildHeaders() {
|
|
140
|
+
return {
|
|
141
|
+
"content-type": "application/json",
|
|
142
|
+
...options.apiKey ? { authorization: `Bearer ${options.apiKey}` } : {},
|
|
143
|
+
...options.headers
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async function post(body, signal) {
|
|
147
|
+
const response = await doFetch(url, {
|
|
148
|
+
method: "POST",
|
|
149
|
+
headers: buildHeaders(),
|
|
150
|
+
body: JSON.stringify(body),
|
|
151
|
+
signal
|
|
152
|
+
});
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
const snippet = await response.text().catch(() => "");
|
|
155
|
+
throw new Error(`createOpenAiCompatExecutors: ${url} responded ${response.status} ${response.statusText}: ` + snippet.slice(0, 500));
|
|
156
|
+
}
|
|
157
|
+
return response;
|
|
158
|
+
}
|
|
159
|
+
const generateText = async (request, info) => {
|
|
160
|
+
const tools = toOpenAiTools(request.tools);
|
|
161
|
+
const body = {
|
|
162
|
+
model: resolveModel(request.model),
|
|
163
|
+
messages: toOpenAiMessages(request),
|
|
164
|
+
...toOpenAiCallSettings(request),
|
|
165
|
+
...tools.length > 0 ? { tools } : {},
|
|
166
|
+
...request.toolChoice ? { tool_choice: toWireToolChoice(request.toolChoice) } : {}
|
|
167
|
+
};
|
|
168
|
+
const structured = require_decision.getAgentOutputMode(request.outputSchema) === "structured";
|
|
169
|
+
if (structured) {
|
|
170
|
+
const jsonSchema = await require_decision.getJsonSchema(require_decision.buildEnvelopeSchema(request.outputSchema, { reasoning: request.reasoning }));
|
|
171
|
+
body.response_format = jsonSchema ? {
|
|
172
|
+
type: "json_schema",
|
|
173
|
+
json_schema: {
|
|
174
|
+
name: "output",
|
|
175
|
+
schema: jsonSchema,
|
|
176
|
+
strict: false
|
|
177
|
+
}
|
|
178
|
+
} : { type: "json_object" };
|
|
179
|
+
}
|
|
180
|
+
const json = await (await post(body, info?.signal)).json();
|
|
181
|
+
const choice = json.choices?.[0];
|
|
182
|
+
const content = choice?.message?.content ?? "";
|
|
183
|
+
if (structured) {
|
|
184
|
+
let parsed;
|
|
185
|
+
try {
|
|
186
|
+
parsed = content ? JSON.parse(content) : void 0;
|
|
187
|
+
} catch (error) {
|
|
188
|
+
throw new Error(`createOpenAiCompatExecutors: generateText${nameSuffix(request)} — structured request returned non-JSON content: ${errorMessage(error)}`);
|
|
189
|
+
}
|
|
190
|
+
let output = parsed;
|
|
191
|
+
let reasoning;
|
|
192
|
+
if (parsed && typeof parsed === "object" && "result" in parsed) {
|
|
193
|
+
output = parsed.result;
|
|
194
|
+
const rawReasoning = parsed.reasoning;
|
|
195
|
+
if (typeof rawReasoning === "string") reasoning = rawReasoning;
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
output,
|
|
199
|
+
...reasoning !== void 0 ? { reasoning } : {},
|
|
200
|
+
usage: json.usage,
|
|
201
|
+
finishReason: choice?.finish_reason ?? void 0
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
output: content,
|
|
206
|
+
usage: json.usage,
|
|
207
|
+
finishReason: choice?.finish_reason ?? void 0
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
const streamText = async (request, info) => {
|
|
211
|
+
const response = await post({
|
|
212
|
+
model: resolveModel(request.model),
|
|
213
|
+
messages: toOpenAiMessages(request),
|
|
214
|
+
...toOpenAiCallSettings(request),
|
|
215
|
+
stream: true
|
|
216
|
+
}, info?.signal);
|
|
217
|
+
let text = "";
|
|
218
|
+
for await (const data of iterateSse(response, request)) {
|
|
219
|
+
let chunk;
|
|
220
|
+
try {
|
|
221
|
+
chunk = JSON.parse(data);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
throw new Error(`createOpenAiCompatExecutors: streamText${nameSuffix(request)} — malformed SSE JSON chunk: ${errorMessage(error)}`);
|
|
224
|
+
}
|
|
225
|
+
const delta = chunk.choices?.[0]?.delta?.content;
|
|
226
|
+
if (delta) {
|
|
227
|
+
text += delta;
|
|
228
|
+
info?.onChunk?.(delta);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return { output: text };
|
|
232
|
+
};
|
|
233
|
+
const decide = async (request) => {
|
|
234
|
+
const tools = toOpenAiEventTools(request.events);
|
|
235
|
+
const json = await (await post({
|
|
236
|
+
model: resolveModel(request.model),
|
|
237
|
+
messages: toDecisionMessages(request),
|
|
238
|
+
tools,
|
|
239
|
+
tool_choice: "required",
|
|
240
|
+
...pruneUndefined({
|
|
241
|
+
temperature: request.temperature,
|
|
242
|
+
max_tokens: request.maxOutputTokens,
|
|
243
|
+
top_p: request.topP,
|
|
244
|
+
seed: request.seed,
|
|
245
|
+
stop: request.stopSequences
|
|
246
|
+
})
|
|
247
|
+
}, request.signal)).json();
|
|
248
|
+
const choice = json.choices?.[0];
|
|
249
|
+
const toolCall = choice?.message?.tool_calls?.[0];
|
|
250
|
+
if (!toolCall || toolCall.type && toolCall.type !== "function" || !toolCall.function?.name) throw new Error("createOpenAiCompatExecutors: decide — model did not call an event tool.");
|
|
251
|
+
const chosenEvent = request.events.find((event) => event.toolName === toolCall.function.name);
|
|
252
|
+
if (!chosenEvent) throw new Error(`createOpenAiCompatExecutors: decide — model called unknown tool '${toolCall.function.name}'.`);
|
|
253
|
+
let args = {};
|
|
254
|
+
if (toolCall.function.arguments) try {
|
|
255
|
+
args = JSON.parse(toolCall.function.arguments);
|
|
256
|
+
} catch (error) {
|
|
257
|
+
throw new Error(`createOpenAiCompatExecutors: decide — could not parse tool arguments for '${chosenEvent.type}': ${errorMessage(error)}`);
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
event: {
|
|
261
|
+
...args && typeof args === "object" ? args : {},
|
|
262
|
+
type: chosenEvent.type
|
|
263
|
+
},
|
|
264
|
+
usage: json.usage,
|
|
265
|
+
finishReason: choice?.finish_reason ?? void 0
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
return {
|
|
269
|
+
generateText,
|
|
270
|
+
streamText,
|
|
271
|
+
decide
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
/** Maps an `AgentToolChoice` to the wire `tool_choice` shape. */
|
|
275
|
+
function toWireToolChoice(toolChoice) {
|
|
276
|
+
return typeof toolChoice === "object" ? {
|
|
277
|
+
type: "function",
|
|
278
|
+
function: { name: toolChoice.name }
|
|
279
|
+
} : toolChoice;
|
|
280
|
+
}
|
|
281
|
+
async function* iterateSse(response, request) {
|
|
282
|
+
const body = response.body;
|
|
283
|
+
if (!body) throw new Error(`createOpenAiCompatExecutors: streamText${nameSuffix(request)} — response has no body to read SSE from.`);
|
|
284
|
+
const reader = body.getReader();
|
|
285
|
+
const decoder = new TextDecoder();
|
|
286
|
+
let buffer = "";
|
|
287
|
+
const flushLine = function* (line) {
|
|
288
|
+
const trimmed = line.trim();
|
|
289
|
+
if (!trimmed || !trimmed.startsWith("data:")) return;
|
|
290
|
+
const data = trimmed.slice(5).trim();
|
|
291
|
+
if (data && data !== "[DONE]") yield data;
|
|
292
|
+
};
|
|
293
|
+
while (true) {
|
|
294
|
+
const { done, value } = await reader.read();
|
|
295
|
+
if (done) break;
|
|
296
|
+
buffer += decoder.decode(value, { stream: true });
|
|
297
|
+
let newlineIndex;
|
|
298
|
+
while ((newlineIndex = buffer.indexOf("\n")) !== -1) {
|
|
299
|
+
const line = buffer.slice(0, newlineIndex);
|
|
300
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
301
|
+
yield* flushLine(line);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
yield* flushLine(buffer);
|
|
305
|
+
}
|
|
306
|
+
function nameSuffix(request) {
|
|
307
|
+
return request.name ? ` '${request.name}'` : "";
|
|
308
|
+
}
|
|
309
|
+
function errorMessage(error) {
|
|
310
|
+
return error instanceof Error ? error.message : String(error);
|
|
311
|
+
}
|
|
312
|
+
//#endregion
|
|
313
|
+
exports.createOpenAiCompatExecutors = createOpenAiCompatExecutors;
|
|
314
|
+
exports.extractJsonSchema = extractJsonSchema;
|
|
315
|
+
exports.toDecisionMessages = toDecisionMessages;
|
|
316
|
+
exports.toOpenAiCallSettings = toOpenAiCallSettings;
|
|
317
|
+
exports.toOpenAiEventTools = toOpenAiEventTools;
|
|
318
|
+
exports.toOpenAiMessages = toOpenAiMessages;
|
|
319
|
+
exports.toOpenAiTools = toOpenAiTools;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { c as AgentTools } from "./types-BHjeDdch.cjs";
|
|
2
|
+
import { B as AgentEventDescriptor, D as AgentDecisionExecutor, k as AgentDecisionRequest, l as AgentTextRequest, s as AgentRequestExecutors } from "./text-logic-1ZQkO3zr.cjs";
|
|
3
|
+
import { r as getJsonSchema } from "./utils-lK1wnL2i.cjs";
|
|
4
|
+
|
|
5
|
+
//#region src/openai-compat/index.d.ts
|
|
6
|
+
interface WireMessage {
|
|
7
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
8
|
+
content: string;
|
|
9
|
+
tool_call_id?: string;
|
|
10
|
+
}
|
|
11
|
+
interface WireTool {
|
|
12
|
+
type: "function";
|
|
13
|
+
function: {
|
|
14
|
+
name: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
parameters: Record<string, unknown>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Reads a Standard Schema's optional `~standard.jsonSchema.input()` extension
|
|
21
|
+
* (implemented by e.g. Zod v4's `z.toJSONSchema`), awaiting it when it returns
|
|
22
|
+
* a Promise. Returns `undefined` when the schema doesn't expose the extension.
|
|
23
|
+
* Thin re-export of core's {@link getJsonSchema}.
|
|
24
|
+
*/
|
|
25
|
+
declare const extractJsonSchema: typeof getJsonSchema;
|
|
26
|
+
/** Maps `AgentTextRequest.messages`/`system`/`prompt` to Chat Completions messages. */
|
|
27
|
+
declare function toOpenAiMessages(request: Pick<AgentTextRequest, "system" | "prompt" | "messages">): WireMessage[];
|
|
28
|
+
/**
|
|
29
|
+
* Maps sampling/stop settings. Targets `max_tokens` (not
|
|
30
|
+
* `max_completion_tokens`) — it's the field every OpenAI-compatible backend
|
|
31
|
+
* accepts (Ollama, vLLM, Groq, …), where `max_completion_tokens` is
|
|
32
|
+
* OpenAI-only. Undefined fields are pruned so they never hit the wire.
|
|
33
|
+
*/
|
|
34
|
+
declare function toOpenAiCallSettings(request: AgentTextRequest): Record<string, unknown>;
|
|
35
|
+
/** One wire function tool per `AgentTools` entry. */
|
|
36
|
+
declare function toOpenAiTools(tools: AgentTools): WireTool[];
|
|
37
|
+
/** One wire function tool per candidate decision event — the
|
|
38
|
+
* "tool-per-event + tool_choice: 'required'" recipe. */
|
|
39
|
+
declare function toOpenAiEventTools(events: AgentEventDescriptor[]): WireTool[];
|
|
40
|
+
/** Messages for a decision request, with prior failed `attempts` rendered as
|
|
41
|
+
* appended user messages (via core's {@link renderDecisionAttempts}) so
|
|
42
|
+
* retries converge. */
|
|
43
|
+
declare function toDecisionMessages(request: Pick<AgentDecisionRequest, "messages" | "prompt" | "events" | "attempts">): WireMessage[];
|
|
44
|
+
/** Minimal `fetch` shape the adapter needs — matches the global `fetch` and
|
|
45
|
+
* Cloudflare Workers' `fetch`, so a custom transport is drop-in. */
|
|
46
|
+
type FetchLike = (input: string, init: {
|
|
47
|
+
method: string;
|
|
48
|
+
headers: Record<string, string>;
|
|
49
|
+
body: string;
|
|
50
|
+
signal?: AbortSignal;
|
|
51
|
+
}) => Promise<{
|
|
52
|
+
ok: boolean;
|
|
53
|
+
status: number;
|
|
54
|
+
statusText: string;
|
|
55
|
+
text(): Promise<string>;
|
|
56
|
+
json(): Promise<unknown>;
|
|
57
|
+
body: ReadableStream<Uint8Array> | null;
|
|
58
|
+
}>;
|
|
59
|
+
/** Options for {@link createOpenAiCompatExecutors}. */
|
|
60
|
+
interface CreateOpenAiCompatExecutorsOptions {
|
|
61
|
+
/** Base URL of the Chat Completions API, e.g. `"https://api.groq.com/openai/v1"`
|
|
62
|
+
* or `"http://localhost:11434/v1"`. `/chat/completions` is appended. */
|
|
63
|
+
baseUrl: string;
|
|
64
|
+
/** Bearer token sent as `Authorization: Bearer <apiKey>`. Omit for keyless
|
|
65
|
+
* local servers (Ollama, LM Studio). */
|
|
66
|
+
apiKey?: string;
|
|
67
|
+
/** Extra headers merged onto every request (e.g. `HTTP-Referer` for OpenRouter). */
|
|
68
|
+
headers?: Record<string, string>;
|
|
69
|
+
/** `fetch` override for Workers/tests. Defaults to the global `fetch`. */
|
|
70
|
+
fetch?: FetchLike;
|
|
71
|
+
/** Default wire model id, used when a request's model ref is empty. */
|
|
72
|
+
model?: string;
|
|
73
|
+
/** Model ref → wire model id map. A `request.model` present here resolves
|
|
74
|
+
* to its mapped id; otherwise it passes through as the wire id. */
|
|
75
|
+
models?: Record<string, string>;
|
|
76
|
+
}
|
|
77
|
+
/** `createOpenAiCompatExecutors` always populates all three executor slots. */
|
|
78
|
+
interface OpenAiCompatExecutors extends AgentRequestExecutors {
|
|
79
|
+
streamText: NonNullable<AgentRequestExecutors["streamText"]>;
|
|
80
|
+
decide: AgentDecisionExecutor;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Builds a complete `{ generateText, streamText, decide }` executor set over
|
|
84
|
+
* the OpenAI Chat Completions wire format via raw `fetch`.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* const executors = createOpenAiCompatExecutors({
|
|
89
|
+
* baseUrl: 'https://api.groq.com/openai/v1',
|
|
90
|
+
* apiKey: process.env.GROQ_API_KEY,
|
|
91
|
+
* models: { quick: 'llama-3.3-70b-versatile' },
|
|
92
|
+
* });
|
|
93
|
+
* const result = await runAgent(machine, { input, executors });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
declare function createOpenAiCompatExecutors(options: CreateOpenAiCompatExecutorsOptions): OpenAiCompatExecutors;
|
|
97
|
+
//#endregion
|
|
98
|
+
export { CreateOpenAiCompatExecutorsOptions, FetchLike, OpenAiCompatExecutors, createOpenAiCompatExecutors, extractJsonSchema, toDecisionMessages, toOpenAiCallSettings, toOpenAiEventTools, toOpenAiMessages, toOpenAiTools };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { c as AgentTools } from "./types-Cq1YlAQ6.mjs";
|
|
2
|
+
import { B as AgentEventDescriptor, D as AgentDecisionExecutor, k as AgentDecisionRequest, l as AgentTextRequest, s as AgentRequestExecutors } from "./text-logic-2EMJIS-n.mjs";
|
|
3
|
+
import { r as getJsonSchema } from "./utils-CWUCa3pF.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/openai-compat/index.d.ts
|
|
6
|
+
interface WireMessage {
|
|
7
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
8
|
+
content: string;
|
|
9
|
+
tool_call_id?: string;
|
|
10
|
+
}
|
|
11
|
+
interface WireTool {
|
|
12
|
+
type: "function";
|
|
13
|
+
function: {
|
|
14
|
+
name: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
parameters: Record<string, unknown>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Reads a Standard Schema's optional `~standard.jsonSchema.input()` extension
|
|
21
|
+
* (implemented by e.g. Zod v4's `z.toJSONSchema`), awaiting it when it returns
|
|
22
|
+
* a Promise. Returns `undefined` when the schema doesn't expose the extension.
|
|
23
|
+
* Thin re-export of core's {@link getJsonSchema}.
|
|
24
|
+
*/
|
|
25
|
+
declare const extractJsonSchema: typeof getJsonSchema;
|
|
26
|
+
/** Maps `AgentTextRequest.messages`/`system`/`prompt` to Chat Completions messages. */
|
|
27
|
+
declare function toOpenAiMessages(request: Pick<AgentTextRequest, "system" | "prompt" | "messages">): WireMessage[];
|
|
28
|
+
/**
|
|
29
|
+
* Maps sampling/stop settings. Targets `max_tokens` (not
|
|
30
|
+
* `max_completion_tokens`) — it's the field every OpenAI-compatible backend
|
|
31
|
+
* accepts (Ollama, vLLM, Groq, …), where `max_completion_tokens` is
|
|
32
|
+
* OpenAI-only. Undefined fields are pruned so they never hit the wire.
|
|
33
|
+
*/
|
|
34
|
+
declare function toOpenAiCallSettings(request: AgentTextRequest): Record<string, unknown>;
|
|
35
|
+
/** One wire function tool per `AgentTools` entry. */
|
|
36
|
+
declare function toOpenAiTools(tools: AgentTools): WireTool[];
|
|
37
|
+
/** One wire function tool per candidate decision event — the
|
|
38
|
+
* "tool-per-event + tool_choice: 'required'" recipe. */
|
|
39
|
+
declare function toOpenAiEventTools(events: AgentEventDescriptor[]): WireTool[];
|
|
40
|
+
/** Messages for a decision request, with prior failed `attempts` rendered as
|
|
41
|
+
* appended user messages (via core's {@link renderDecisionAttempts}) so
|
|
42
|
+
* retries converge. */
|
|
43
|
+
declare function toDecisionMessages(request: Pick<AgentDecisionRequest, "messages" | "prompt" | "events" | "attempts">): WireMessage[];
|
|
44
|
+
/** Minimal `fetch` shape the adapter needs — matches the global `fetch` and
|
|
45
|
+
* Cloudflare Workers' `fetch`, so a custom transport is drop-in. */
|
|
46
|
+
type FetchLike = (input: string, init: {
|
|
47
|
+
method: string;
|
|
48
|
+
headers: Record<string, string>;
|
|
49
|
+
body: string;
|
|
50
|
+
signal?: AbortSignal;
|
|
51
|
+
}) => Promise<{
|
|
52
|
+
ok: boolean;
|
|
53
|
+
status: number;
|
|
54
|
+
statusText: string;
|
|
55
|
+
text(): Promise<string>;
|
|
56
|
+
json(): Promise<unknown>;
|
|
57
|
+
body: ReadableStream<Uint8Array> | null;
|
|
58
|
+
}>;
|
|
59
|
+
/** Options for {@link createOpenAiCompatExecutors}. */
|
|
60
|
+
interface CreateOpenAiCompatExecutorsOptions {
|
|
61
|
+
/** Base URL of the Chat Completions API, e.g. `"https://api.groq.com/openai/v1"`
|
|
62
|
+
* or `"http://localhost:11434/v1"`. `/chat/completions` is appended. */
|
|
63
|
+
baseUrl: string;
|
|
64
|
+
/** Bearer token sent as `Authorization: Bearer <apiKey>`. Omit for keyless
|
|
65
|
+
* local servers (Ollama, LM Studio). */
|
|
66
|
+
apiKey?: string;
|
|
67
|
+
/** Extra headers merged onto every request (e.g. `HTTP-Referer` for OpenRouter). */
|
|
68
|
+
headers?: Record<string, string>;
|
|
69
|
+
/** `fetch` override for Workers/tests. Defaults to the global `fetch`. */
|
|
70
|
+
fetch?: FetchLike;
|
|
71
|
+
/** Default wire model id, used when a request's model ref is empty. */
|
|
72
|
+
model?: string;
|
|
73
|
+
/** Model ref → wire model id map. A `request.model` present here resolves
|
|
74
|
+
* to its mapped id; otherwise it passes through as the wire id. */
|
|
75
|
+
models?: Record<string, string>;
|
|
76
|
+
}
|
|
77
|
+
/** `createOpenAiCompatExecutors` always populates all three executor slots. */
|
|
78
|
+
interface OpenAiCompatExecutors extends AgentRequestExecutors {
|
|
79
|
+
streamText: NonNullable<AgentRequestExecutors["streamText"]>;
|
|
80
|
+
decide: AgentDecisionExecutor;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Builds a complete `{ generateText, streamText, decide }` executor set over
|
|
84
|
+
* the OpenAI Chat Completions wire format via raw `fetch`.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* const executors = createOpenAiCompatExecutors({
|
|
89
|
+
* baseUrl: 'https://api.groq.com/openai/v1',
|
|
90
|
+
* apiKey: process.env.GROQ_API_KEY,
|
|
91
|
+
* models: { quick: 'llama-3.3-70b-versatile' },
|
|
92
|
+
* });
|
|
93
|
+
* const result = await runAgent(machine, { input, executors });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
declare function createOpenAiCompatExecutors(options: CreateOpenAiCompatExecutorsOptions): OpenAiCompatExecutors;
|
|
97
|
+
//#endregion
|
|
98
|
+
export { CreateOpenAiCompatExecutorsOptions, FetchLike, OpenAiCompatExecutors, createOpenAiCompatExecutors, extractJsonSchema, toDecisionMessages, toOpenAiCallSettings, toOpenAiEventTools, toOpenAiMessages, toOpenAiTools };
|