@keystrokehq/keystroke 0.1.36 → 0.1.37
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/agent.cjs +263 -11
- package/dist/agent.cjs.map +1 -1
- package/dist/agent.mjs +263 -11
- package/dist/agent.mjs.map +1 -1
- package/dist/config.d.cts +2 -2
- package/dist/config.d.mts +2 -2
- package/dist/{dist-iDcp4e6O.mjs → dist-1heZMRTe.mjs} +172 -3
- package/dist/dist-1heZMRTe.mjs.map +1 -0
- package/dist/{dist-Di6PqKAu.cjs → dist-DlIUXcOB.cjs} +189 -2
- package/dist/dist-DlIUXcOB.cjs.map +1 -0
- package/dist/index-DUSEfNrG.d.cts.map +1 -1
- package/dist/index-DUSEfNrG.d.mts.map +1 -1
- package/dist/{token-DUN0yjzi.mjs → token-CJ2Rrkyp.mjs} +2 -2
- package/dist/{token-DUN0yjzi.mjs.map → token-CJ2Rrkyp.mjs.map} +1 -1
- package/dist/{token-CQiw-m2-.cjs → token-qixf8bl9.cjs} +2 -2
- package/dist/{token-CQiw-m2-.cjs.map → token-qixf8bl9.cjs.map} +1 -1
- package/dist/trigger.cjs +1 -1
- package/dist/trigger.mjs +1 -1
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.mjs +1 -1
- package/package.json +1 -1
- package/dist/dist-Di6PqKAu.cjs.map +0 -1
- package/dist/dist-iDcp4e6O.mjs.map +0 -1
package/dist/agent.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as stripPromptContext, a as PublicModelsResponseSchema, b as parseChatAttachmentServePath, d as formatAgentTimestampContext, g as mcpContentBlocksToAiSdkParts, h as mcpContentBlocksFromToolOutput, i as LLM_KEY_SOURCE_HEADER, m as isRedundantMcpJsonText, n as DEFAULT_CLOUD_PLATFORM_ORIGIN, u as defineTool, v as modelSupportsMediaType, x as requiredDisplayTextSchema } from "./dist-DeRiK01E.mjs";
|
|
2
2
|
import { c as getRunSignal, f as isWithinActionExecution, h as resolveActionTool, l as getWorkflowRunHandle, u as isAction } from "./dist-BPiGiKZI.mjs";
|
|
3
|
-
import { $ as
|
|
3
|
+
import { $ as getSession, A as extractJsonMiddleware, C as connectMcpDefinition, D as isMcp, E as defineMcp, F as output_exports, G as MESSAGE_EVENT_TYPE, H as generateId, I as readUIMessageStream, J as clearLiveMessage, K as addAgentSessionDuration, L as toUIMessageStream, M as generateText, N as hasToolCall, O as ToolLoopAgent, P as isFileUIPart, Q as getProjectScopeId, R as wrapLanguageModel, S as withCredentialAssignments, T as connectMcpStdio, U as jsonSchema, W as tool, X as failAgentSession, Y as createSession, Z as getAgentByRoute, _ as createCredentialResolver, at as touchSession, b as resolveActionCredentials, ct as withSpan, et as listMessageEvents, f as resolveWorkflowTool, g as captureCredentialToolErrors, h as buildCredentialRunContext, it as setSessionTitle, j as generateObject, k as convertToModelMessages, l as isWorkflow, nt as resolveRunSourceFromTraceContext, ot as captureConsole, q as appendEvent, rt as setSessionLiveMessage, st as getTraceContext, tt as recordLlmUsageFromAssistantMessage, v as enrichCredentialError, w as connectMcpServer, x as resolveMcpTools, y as isCredentialError, z as createGateway } from "./dist-1heZMRTe.mjs";
|
|
4
4
|
import { $ as materializeSandbox, Q as loadAssetManifest, Z as getBoundAppRoot, a as createSandbox, c as defineSkill, dt as resolveAgentRoot, f as materializeSkills, g as sandboxSystemPromptInjection, it as resolveSandboxDefinition, o as createStubInvokeToolBridge, pt as resolveSessionRoot, r as createInvokeToolBridge, s as defaultWorkspacesRoot, ut as ensureWorkspaceDir } from "./dist-DL3p2pu7.mjs";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -1170,6 +1170,85 @@ function llmUsageFromLanguageModelUsage(usage, resolved, options) {
|
|
|
1170
1170
|
}
|
|
1171
1171
|
};
|
|
1172
1172
|
}
|
|
1173
|
+
/** Synthetic tool name for structured output when responseFormat is unreliable. */
|
|
1174
|
+
const STRUCTURED_OUTPUT_SUBMIT_TOOL_NAME = "submit_structured_output";
|
|
1175
|
+
const SUBMIT_TOOL_VENDORS = new Set([
|
|
1176
|
+
"zai",
|
|
1177
|
+
"minimax",
|
|
1178
|
+
"alibaba",
|
|
1179
|
+
"deepseek"
|
|
1180
|
+
]);
|
|
1181
|
+
function structuredOutputSubmitToolVendor(modelId) {
|
|
1182
|
+
const { vendor } = splitAgentModelId(modelId);
|
|
1183
|
+
return SUBMIT_TOOL_VENDORS.has(vendor);
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Use a submit tool instead of responseFormat.
|
|
1187
|
+
*
|
|
1188
|
+
* - Agent + tools: z-ai GLM only (native json mode works for schema-only agent calls).
|
|
1189
|
+
* - promptLlm: z-ai, minimax, alibaba, and deepseek — no gateway endpoint exposes reliable
|
|
1190
|
+
* response_format, so schema-only `generateObject` fails validation.
|
|
1191
|
+
*/
|
|
1192
|
+
function usesStructuredOutputSubmitTool(args) {
|
|
1193
|
+
if (!args.structuredOutput || !structuredOutputSubmitToolVendor(args.modelId)) return false;
|
|
1194
|
+
if (args.promptLlm) return true;
|
|
1195
|
+
const { vendor } = splitAgentModelId(args.modelId);
|
|
1196
|
+
return (vendor === "zai" || vendor === "alibaba") && (args.hasTools ?? false);
|
|
1197
|
+
}
|
|
1198
|
+
function appendStructuredOutputSubmitTool(tools, schema) {
|
|
1199
|
+
return {
|
|
1200
|
+
...tools,
|
|
1201
|
+
[STRUCTURED_OUTPUT_SUBMIT_TOOL_NAME]: tool({
|
|
1202
|
+
description: "Submit the final structured result after completing any required tool calls. Include every required schema field.",
|
|
1203
|
+
inputSchema: schema,
|
|
1204
|
+
execute: async (input) => input
|
|
1205
|
+
})
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
function resolveStructuredOutputStopWhen(args) {
|
|
1209
|
+
if (!usesStructuredOutputSubmitTool(args)) return;
|
|
1210
|
+
return hasToolCall(STRUCTURED_OUTPUT_SUBMIT_TOOL_NAME);
|
|
1211
|
+
}
|
|
1212
|
+
function extractStructuredOutputFromSubmitTool(args) {
|
|
1213
|
+
for (let index = args.steps.length - 1; index >= 0; index -= 1) {
|
|
1214
|
+
const step = args.steps[index];
|
|
1215
|
+
if (!step) continue;
|
|
1216
|
+
for (const toolCall of step.toolCalls) if (toolCall.toolName === "submit_structured_output") return args.schema.parse(toolCall.input);
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Alibaba rejects `response_format: json_object` unless messages contain the word "json".
|
|
1221
|
+
* Applies when structured output is enabled (including tool-loop steps that carry responseFormat).
|
|
1222
|
+
*/
|
|
1223
|
+
function augmentInstructionsForStructuredOutput(args) {
|
|
1224
|
+
if (!args.structuredOutput) return args.instructions;
|
|
1225
|
+
const { vendor } = splitAgentModelId(args.modelId);
|
|
1226
|
+
let instructions = args.instructions;
|
|
1227
|
+
const submitTool = usesStructuredOutputSubmitTool({
|
|
1228
|
+
modelId: args.modelId,
|
|
1229
|
+
structuredOutput: args.structuredOutput,
|
|
1230
|
+
hasTools: args.hasTools ?? false,
|
|
1231
|
+
promptLlm: args.promptLlm
|
|
1232
|
+
});
|
|
1233
|
+
if (vendor === "alibaba" && !/\bjson\b/i.test(instructions)) instructions = `${instructions}\n\nWhen returning structured data, output valid json.`;
|
|
1234
|
+
if (submitTool) if (args.hasTools) instructions = `${instructions}\n\nCall the available tools first, then call ${STRUCTURED_OUTPUT_SUBMIT_TOOL_NAME} with the final result matching the schema. Do not return prose or raw json as the final answer.${vendor === "alibaba" ? " Do not return tool arguments or guesses as the final schema." : ""}`;
|
|
1235
|
+
else instructions = `${instructions}\n\nCall ${STRUCTURED_OUTPUT_SUBMIT_TOOL_NAME} with the final result matching the schema. Do not return prose or raw json as the final answer.`;
|
|
1236
|
+
else if (vendor === "zai") instructions = `${instructions}\n\nReturn the final answer as raw json matching the schema with every required field. Do not use markdown, bold, or prose in the structured response.`;
|
|
1237
|
+
return instructions;
|
|
1238
|
+
}
|
|
1239
|
+
function parseRepairedStructuredOutput(args) {
|
|
1240
|
+
const trimmed = args.text.trim();
|
|
1241
|
+
const candidates = [
|
|
1242
|
+
trimmed,
|
|
1243
|
+
trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i)?.[1]?.trim(),
|
|
1244
|
+
trimmed.match(/\{[\s\S]*\}/)?.[0]
|
|
1245
|
+
].filter((value) => Boolean(value));
|
|
1246
|
+
for (const candidate of candidates) try {
|
|
1247
|
+
return args.schema.parse(JSON.parse(candidate));
|
|
1248
|
+
} catch {
|
|
1249
|
+
continue;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1173
1252
|
/**
|
|
1174
1253
|
* Baked-in AI SDK `providerOptions` a model needs for structured output.
|
|
1175
1254
|
*
|
|
@@ -1189,6 +1268,70 @@ function resolveProviderOptions(args) {
|
|
|
1189
1268
|
const { vendor } = splitAgentModelId(args.modelId);
|
|
1190
1269
|
if (vendor === "anthropic") return { anthropic: { structuredOutputMode: "outputFormat" } };
|
|
1191
1270
|
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Wrap gateway models that need middleware for reliable structured output parsing.
|
|
1273
|
+
*
|
|
1274
|
+
* z-ai GLM models often wrap JSON in markdown fences; AI SDK's `extractJsonMiddleware` strips them.
|
|
1275
|
+
* See vercel/ai middleware docs and vercel/ai#12491.
|
|
1276
|
+
*/
|
|
1277
|
+
function wrapLanguageModelForStructuredOutput(args) {
|
|
1278
|
+
if (!args.structuredOutput) return args.languageModel;
|
|
1279
|
+
if (usesStructuredOutputSubmitTool({
|
|
1280
|
+
modelId: args.modelId,
|
|
1281
|
+
structuredOutput: args.structuredOutput,
|
|
1282
|
+
hasTools: args.hasTools ?? false
|
|
1283
|
+
})) return args.languageModel;
|
|
1284
|
+
const { vendor } = splitAgentModelId(args.modelId);
|
|
1285
|
+
if (vendor !== "zai") return args.languageModel;
|
|
1286
|
+
return wrapLanguageModel({
|
|
1287
|
+
model: args.languageModel,
|
|
1288
|
+
middleware: extractJsonMiddleware()
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
function needsStructuredOutputToolGuard(modelId) {
|
|
1292
|
+
const { vendor, directId } = splitAgentModelId(modelId);
|
|
1293
|
+
if (vendor === "anthropic") return !directId.includes("haiku");
|
|
1294
|
+
return false;
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Vendor-scoped guard for structured output + tools (BUS-2823).
|
|
1298
|
+
*
|
|
1299
|
+
* Anthropic Sonnet-class models may satisfy structured output on step 1 without calling tools;
|
|
1300
|
+
* AI SDK's tool loop then stops. Force `toolChoice: "required"` until the first tool result,
|
|
1301
|
+
* then release for the final structured step.
|
|
1302
|
+
*
|
|
1303
|
+
* Do not generalize: Gemini rejects forced tool choice + schema; Anthropic Haiku rejects forced
|
|
1304
|
+
* tool choice + thinking. z-ai GLM uses {@link usesStructuredOutputSubmitTool} instead.
|
|
1305
|
+
*/
|
|
1306
|
+
function resolveStructuredOutputPrepareStep(args) {
|
|
1307
|
+
if (!args.structuredOutput || !args.hasTools) return;
|
|
1308
|
+
if (!needsStructuredOutputToolGuard(args.modelId)) return;
|
|
1309
|
+
return ({ steps }) => {
|
|
1310
|
+
if (steps.some((step) => step.toolResults.length > 0)) return {};
|
|
1311
|
+
return { toolChoice: "required" };
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Alibaba and minimax thinking mode conflicts with forced tool_choice on structured promptLlm calls.
|
|
1316
|
+
*/
|
|
1317
|
+
function resolveReasoningForStructuredOutputPromptLlm(args) {
|
|
1318
|
+
if (!usesStructuredOutputSubmitTool({
|
|
1319
|
+
modelId: args.modelId,
|
|
1320
|
+
structuredOutput: args.structuredOutput,
|
|
1321
|
+
promptLlm: true
|
|
1322
|
+
})) return args.thinkingLevel;
|
|
1323
|
+
const { vendor } = splitAgentModelId(args.modelId);
|
|
1324
|
+
if (vendor === "alibaba" || vendor === "minimax") return "none";
|
|
1325
|
+
return args.thinkingLevel;
|
|
1326
|
+
}
|
|
1327
|
+
/** Alibaba may require the word "json" in user messages when response_format is enabled. */
|
|
1328
|
+
function augmentInputForStructuredOutput(args) {
|
|
1329
|
+
if (!args.structuredOutput) return args.input;
|
|
1330
|
+
const { vendor } = splitAgentModelId(args.modelId);
|
|
1331
|
+
if (vendor !== "alibaba") return args.input;
|
|
1332
|
+
if (/\bjson\b/i.test(args.input)) return args.input;
|
|
1333
|
+
return `${args.input}\n\nReturn the final answer as json matching the schema.`;
|
|
1334
|
+
}
|
|
1192
1335
|
/** Plain-text tool error for UI streams, model replay, and JSON persistence. */
|
|
1193
1336
|
function getToolExecutionErrorMessage(error) {
|
|
1194
1337
|
if (error instanceof Error) return error.message;
|
|
@@ -1217,7 +1360,11 @@ async function streamAgentPrompt(config, input, options) {
|
|
|
1217
1360
|
const userMessage = {
|
|
1218
1361
|
id: generateId(),
|
|
1219
1362
|
role: "user",
|
|
1220
|
-
parts: buildUserMessageParts(
|
|
1363
|
+
parts: buildUserMessageParts(augmentInputForStructuredOutput({
|
|
1364
|
+
input,
|
|
1365
|
+
modelId: config.resolvedModel.modelId,
|
|
1366
|
+
structuredOutput: Boolean(options.outputSchema)
|
|
1367
|
+
}), config.files)
|
|
1221
1368
|
};
|
|
1222
1369
|
const priorMessages = [...config.messages, userMessage];
|
|
1223
1370
|
const newMessages = [userMessage];
|
|
@@ -1232,25 +1379,55 @@ async function streamAgentPrompt(config, input, options) {
|
|
|
1232
1379
|
});
|
|
1233
1380
|
try {
|
|
1234
1381
|
if (config.files?.length && !config.experimentalDownload) throw new Error("Chat attachments require worker storage (STORAGE_* / KEYSTROKE_WORKSPACES_BUCKET)");
|
|
1235
|
-
|
|
1382
|
+
let aiTools = gateToolSetMedia({
|
|
1236
1383
|
...agentToolsToAiToolSet(config.tools),
|
|
1237
1384
|
...config.mcpToolSet
|
|
1238
1385
|
}, config.resolvedModel.capabilities);
|
|
1386
|
+
const structuredOutput = Boolean(options.outputSchema);
|
|
1387
|
+
const hasTools = Object.keys(aiTools).length > 0;
|
|
1388
|
+
const submitToolOutput = usesStructuredOutputSubmitTool({
|
|
1389
|
+
modelId: config.resolvedModel.modelId,
|
|
1390
|
+
structuredOutput,
|
|
1391
|
+
hasTools
|
|
1392
|
+
});
|
|
1393
|
+
if (submitToolOutput && options.outputSchema) aiTools = appendStructuredOutputSubmitTool(aiTools, options.outputSchema);
|
|
1239
1394
|
let messagesForModel = await applyCapabilityPlaceholderToMessages(priorMessages, config.resolvedModel.capabilities);
|
|
1240
1395
|
if (config.experimentalDownload) messagesForModel = await hydrateChatAttachmentMessages(messagesForModel, config.experimentalDownload);
|
|
1241
1396
|
const modelMessages = await convertToModelMessages(messagesForModel);
|
|
1242
1397
|
const providerOptions = resolveProviderOptions({
|
|
1243
1398
|
modelId: config.resolvedModel.modelId,
|
|
1244
|
-
structuredOutput
|
|
1399
|
+
structuredOutput
|
|
1400
|
+
});
|
|
1401
|
+
const prepareStep = resolveStructuredOutputPrepareStep({
|
|
1402
|
+
modelId: config.resolvedModel.modelId,
|
|
1403
|
+
structuredOutput,
|
|
1404
|
+
hasTools
|
|
1405
|
+
});
|
|
1406
|
+
const stopWhen = resolveStructuredOutputStopWhen({
|
|
1407
|
+
modelId: config.resolvedModel.modelId,
|
|
1408
|
+
structuredOutput,
|
|
1409
|
+
hasTools
|
|
1245
1410
|
});
|
|
1246
1411
|
const streamResult = await new ToolLoopAgent({
|
|
1247
|
-
model:
|
|
1248
|
-
|
|
1412
|
+
model: wrapLanguageModelForStructuredOutput({
|
|
1413
|
+
languageModel: config.resolvedModel.languageModel,
|
|
1414
|
+
modelId: config.resolvedModel.modelId,
|
|
1415
|
+
structuredOutput,
|
|
1416
|
+
hasTools
|
|
1417
|
+
}),
|
|
1418
|
+
instructions: augmentInstructionsForStructuredOutput({
|
|
1419
|
+
instructions: config.systemPrompt,
|
|
1420
|
+
modelId: config.resolvedModel.modelId,
|
|
1421
|
+
structuredOutput,
|
|
1422
|
+
hasTools
|
|
1423
|
+
}),
|
|
1249
1424
|
tools: aiTools,
|
|
1250
1425
|
reasoning: config.thinkingLevel,
|
|
1251
1426
|
...config.experimentalDownload ? { experimental_download: config.experimentalDownload } : {},
|
|
1252
|
-
|
|
1253
|
-
...providerOptions ? { providerOptions } : {}
|
|
1427
|
+
...!submitToolOutput && options.outputSchema ? { output: output_exports.object({ schema: options.outputSchema }) } : {},
|
|
1428
|
+
...providerOptions ? { providerOptions } : {},
|
|
1429
|
+
...prepareStep ? { prepareStep } : {},
|
|
1430
|
+
...stopWhen ? { stopWhen } : {}
|
|
1254
1431
|
}).stream({
|
|
1255
1432
|
messages: modelMessages,
|
|
1256
1433
|
abortSignal: options.signal,
|
|
@@ -1317,7 +1494,22 @@ async function streamAgentPrompt(config, input, options) {
|
|
|
1317
1494
|
});
|
|
1318
1495
|
}
|
|
1319
1496
|
text = await streamResult.text;
|
|
1320
|
-
if (options.outputSchema)
|
|
1497
|
+
if (options.outputSchema) if (submitToolOutput) {
|
|
1498
|
+
output = extractStructuredOutputFromSubmitTool({
|
|
1499
|
+
steps: await streamResult.steps,
|
|
1500
|
+
schema: options.outputSchema
|
|
1501
|
+
});
|
|
1502
|
+
if (output === void 0) throw new Error(`Structured output was not submitted via ${STRUCTURED_OUTPUT_SUBMIT_TOOL_NAME}`);
|
|
1503
|
+
} else try {
|
|
1504
|
+
output = await streamResult.output;
|
|
1505
|
+
} catch (caught) {
|
|
1506
|
+
const repaired = parseRepairedStructuredOutput({
|
|
1507
|
+
text,
|
|
1508
|
+
schema: options.outputSchema
|
|
1509
|
+
});
|
|
1510
|
+
if (repaired !== void 0) output = repaired;
|
|
1511
|
+
else throw caught;
|
|
1512
|
+
}
|
|
1321
1513
|
await emit({
|
|
1322
1514
|
type: "agent_end",
|
|
1323
1515
|
messages: newMessages
|
|
@@ -2399,17 +2591,77 @@ async function runPromptText(opts, hooks) {
|
|
|
2399
2591
|
await recordUsage(resolved, result.usage, hooks, result.response?.headers);
|
|
2400
2592
|
return result.text;
|
|
2401
2593
|
}
|
|
2594
|
+
async function runPromptObjectViaSubmitTool(opts, hooks) {
|
|
2595
|
+
const schema = opts.outputSchema;
|
|
2596
|
+
if (!schema) throw new Error("outputSchema is required for structured LLM output");
|
|
2597
|
+
const resolved = await resolvePromptModel(opts.model);
|
|
2598
|
+
const providerOptions = resolveProviderOptions({
|
|
2599
|
+
modelId: resolved.modelId,
|
|
2600
|
+
structuredOutput: true
|
|
2601
|
+
});
|
|
2602
|
+
const tools = appendStructuredOutputSubmitTool({}, schema);
|
|
2603
|
+
const system = augmentInstructionsForStructuredOutput({
|
|
2604
|
+
instructions: opts.system ?? "",
|
|
2605
|
+
modelId: resolved.modelId,
|
|
2606
|
+
structuredOutput: true,
|
|
2607
|
+
promptLlm: true
|
|
2608
|
+
});
|
|
2609
|
+
const prompt = augmentInputForStructuredOutput({
|
|
2610
|
+
input: opts.prompt,
|
|
2611
|
+
modelId: resolved.modelId,
|
|
2612
|
+
structuredOutput: true
|
|
2613
|
+
});
|
|
2614
|
+
const thinkingLevel = resolveReasoningForStructuredOutputPromptLlm({
|
|
2615
|
+
modelId: resolved.modelId,
|
|
2616
|
+
thinkingLevel: opts.thinkingLevel,
|
|
2617
|
+
structuredOutput: true
|
|
2618
|
+
});
|
|
2619
|
+
const result = await generateText({
|
|
2620
|
+
model: resolved.languageModel,
|
|
2621
|
+
...system.trim() ? { system } : {},
|
|
2622
|
+
prompt,
|
|
2623
|
+
tools,
|
|
2624
|
+
toolChoice: "required",
|
|
2625
|
+
stopWhen: hasToolCall(STRUCTURED_OUTPUT_SUBMIT_TOOL_NAME),
|
|
2626
|
+
...opts.temperature !== void 0 ? { temperature: opts.temperature } : {},
|
|
2627
|
+
...opts.maxTokens !== void 0 ? { maxOutputTokens: opts.maxTokens } : {},
|
|
2628
|
+
...reasoningCallOption(thinkingLevel),
|
|
2629
|
+
...providerOptions ? { providerOptions } : {}
|
|
2630
|
+
});
|
|
2631
|
+
await recordUsage(resolved, result.usage, hooks, result.response?.headers);
|
|
2632
|
+
const fromSteps = extractStructuredOutputFromSubmitTool({
|
|
2633
|
+
steps: await result.steps,
|
|
2634
|
+
schema
|
|
2635
|
+
});
|
|
2636
|
+
if (fromSteps !== void 0) return fromSteps;
|
|
2637
|
+
throw new Error(`Structured output was not submitted via ${STRUCTURED_OUTPUT_SUBMIT_TOOL_NAME}`);
|
|
2638
|
+
}
|
|
2402
2639
|
async function runPromptObject(opts, hooks) {
|
|
2403
2640
|
const schema = opts.outputSchema;
|
|
2404
2641
|
if (!schema) throw new Error("outputSchema is required for structured LLM output");
|
|
2405
2642
|
const resolved = await resolvePromptModel(opts.model);
|
|
2643
|
+
if (usesStructuredOutputSubmitTool({
|
|
2644
|
+
modelId: resolved.modelId,
|
|
2645
|
+
structuredOutput: true,
|
|
2646
|
+
promptLlm: true
|
|
2647
|
+
})) return runPromptObjectViaSubmitTool(opts, hooks);
|
|
2406
2648
|
const providerOptions = resolveProviderOptions({
|
|
2407
2649
|
modelId: resolved.modelId,
|
|
2408
2650
|
structuredOutput: true
|
|
2409
2651
|
});
|
|
2652
|
+
const languageModel = wrapLanguageModelForStructuredOutput({
|
|
2653
|
+
languageModel: resolved.languageModel,
|
|
2654
|
+
modelId: resolved.modelId,
|
|
2655
|
+
structuredOutput: true
|
|
2656
|
+
});
|
|
2657
|
+
const system = augmentInstructionsForStructuredOutput({
|
|
2658
|
+
instructions: opts.system ?? "",
|
|
2659
|
+
modelId: resolved.modelId,
|
|
2660
|
+
structuredOutput: true
|
|
2661
|
+
});
|
|
2410
2662
|
const result = await generateObject({
|
|
2411
|
-
model:
|
|
2412
|
-
system:
|
|
2663
|
+
model: languageModel,
|
|
2664
|
+
...system.trim() ? { system } : {},
|
|
2413
2665
|
prompt: opts.prompt,
|
|
2414
2666
|
schema,
|
|
2415
2667
|
...opts.temperature !== void 0 ? { temperature: opts.temperature } : {},
|