UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

138 lines (137 loc) • 4.82 kB
import { n as validateJsonSchemaValue } from "../../schema-validator-CbLrj3Mc.mjs"; import { x as createAssistantMessageEventStream } from "../../llm-DhFAPKg8.mjs"; import { t as buildAssistantMessage } from "../../stream-message-shared-CYuIJ_XF.mjs"; import "../../json-schema-runtime-j7GCYcMi.mjs"; import { r as quoteUnsafeIntegerLiterals } from "../../json-unsafe-integers-BeeNmB5X.mjs"; import { d as failTransportStream, o as createEmptyTransportUsage } from "../../provider-transport-runtime-B0sLTuvL.mjs"; //#region extensions/apple-fm/stream.ts /** Native tools propose calls; the OpenClaw agent loop validates and executes them. */ function createAppleFmStream(native) { return (model, context, options) => { const stream = createAssistantMessageEventStream(); const message = buildAssistantMessage({ model, content: [], usage: createEmptyTransportUsage(), stopReason: "stop" }); stream.push({ type: "start", partial: message }); (async () => { try { options?.signal?.throwIfAborted(); const responseFormat = options?.responseFormat ? structuredClone(options.responseFormat) : void 0; const request = { systemPrompt: context.systemPrompt, messages: context.messages, tools: context.tools ?? [], maxTokens: options?.maxTokens ?? model.maxTokens, temperature: options?.temperature, responseFormat: responseFormat ? structuredClone(responseFormat) : void 0 }; const payload = await options?.onPayload?.(request, model) ?? request; if (!payload || typeof payload !== "object") throw new Error("Apple Foundation Models requires an object request."); options?.signal?.throwIfAborted(); const result = await native.run(payload, { signal: options?.signal }); options?.signal?.throwIfAborted(); if (responseFormat && result.toolCalls.length === 0) { const unsafeNumberMessage = "Apple Foundation Models returned an invalid structured response: an unsafe numeric value cannot be validated without losing precision."; if (quoteUnsafeIntegerLiterals(result.text) !== result.text) throw new Error(unsafeNumberMessage); let value; try { value = JSON.parse(result.text, (_key, parsedValue) => { if (typeof parsedValue === "number" && (!Number.isFinite(parsedValue) || Number.isInteger(parsedValue) && !Number.isSafeInteger(parsedValue))) throw new Error(unsafeNumberMessage); return parsedValue; }); } catch (error) { if (!(error instanceof SyntaxError)) throw error; } if (value === void 0) throw new Error("Apple Foundation Models returned an invalid structured response: malformed JSON."); const validation = validateJsonSchemaValue({ schema: responseFormat, cacheKey: "apple-fm.structured-response", value, applyDefaults: false }); if (!validation.ok) throw new Error(`Apple Foundation Models returned an invalid structured response at ${validation.errors.map((error) => error.path).join(", ")}.`); } message.usage.input = result.inputTokens; message.usage.output = result.outputTokens; message.usage.totalTokens = result.inputTokens + result.outputTokens; message.usage.cacheTelemetry = { state: "unavailable" }; message.usage.contextUsage = { state: "available", promptTokens: result.inputTokens, totalTokens: message.usage.totalTokens }; if (result.text) { message.content.push({ type: "text", text: result.text }); stream.push({ type: "text_start", contentIndex: 0, partial: message }); stream.push({ type: "text_delta", contentIndex: 0, delta: result.text, partial: message }); stream.push({ type: "text_end", contentIndex: 0, content: result.text, partial: message }); } for (const call of result.toolCalls) { const toolCall = { type: "toolCall", ...call }; const contentIndex = message.content.length; message.content.push(toolCall); stream.push({ type: "toolcall_start", contentIndex, partial: message }); stream.push({ type: "toolcall_delta", contentIndex, delta: JSON.stringify(call.arguments), partial: message }); stream.push({ type: "toolcall_end", contentIndex, toolCall, partial: message }); } message.stopReason = result.toolCalls.length ? "toolUse" : "stop"; stream.push({ type: "done", reason: message.stopReason, message }); stream.end(message); } catch (error) { failTransportStream({ stream, output: message, error, signal: options?.signal }); } })(); return stream; }; } //#endregion export { createAppleFmStream };