agents
Version:
A home for your AI agents
120 lines (119 loc) • 3.22 kB
JavaScript
import { n as parseChannelMessage, t as channelMessageJsonSchema } from "../tool-schema-CBjGPrsQ.js";
import { jsonSchema, tool } from "ai";
//#region src/channels/ai-sdk.ts
const channelMessageSchema = jsonSchema(channelMessageJsonSchema, { validate(value) {
try {
return {
success: true,
value: parseChannelMessage(value)
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error : new Error(String(error))
};
}
} });
/**
* Adapt one Host-resolved surface to an AI SDK tool.
*
* The caller chooses the key used in its ToolSet and owns model-facing policy
* such as the description, examples, metadata, and approval requirement.
*/
function createSendMessageTool(host, surface, options = {}) {
return tool({
...options,
inputSchema: channelMessageSchema,
execute: (message) => host.deliver(surface, message)
});
}
function toChannelChunk(part) {
switch (part.type) {
case "text-delta": return {
type: "text",
text: part.text
};
case "reasoning-delta": return {
type: "reasoning",
text: part.text
};
case "source": return part.sourceType === "url" ? {
type: "source",
url: part.url,
...part.title !== void 0 && { title: part.title }
} : void 0;
case "tool-call": return {
type: "tool",
id: part.toolCallId,
name: part.toolName,
status: "started"
};
case "tool-result": return {
type: "tool",
id: part.toolCallId,
name: part.toolName,
status: "completed"
};
case "tool-error": return {
type: "tool",
id: part.toolCallId,
name: part.toolName,
status: "failed"
};
default: return;
}
}
/**
* Project an AI SDK `fullStream` onto neutral Channel chunks.
*
* Parts a Channel cannot express are dropped, which keeps provider part
* shapes out of `ChannelChunk`. An `error` or `abort` part errors the returned
* stream, so a generation that fails part-way reaches a Channel as the
* abnormal ending it is rather than as a complete answer.
*/
function toChannelChunks(fullStream) {
const parts = fullStream[Symbol.asyncIterator]();
let sourceClosed = false;
async function closeSource(reason) {
if (sourceClosed) return;
sourceClosed = true;
await parts.return?.(reason);
}
return new ReadableStream({
async pull(controller) {
try {
while (true) {
const { done, value } = await parts.next();
if (done) {
sourceClosed = true;
controller.close();
return;
}
if (value.type === "error") {
const error = value.error instanceof Error ? value.error : new Error(String(value.error));
await closeSource().catch(() => {});
controller.error(error);
return;
}
if (value.type === "abort") {
const error = new Error(value.reason ?? "The generation was aborted");
await closeSource().catch(() => {});
controller.error(error);
return;
}
const chunk = toChannelChunk(value);
if (!chunk) continue;
controller.enqueue(chunk);
return;
}
} catch (error) {
await closeSource().catch(() => {});
controller.error(error);
}
},
cancel: closeSource
});
}
//#endregion
export { createSendMessageTool, toChannelChunks };
//# sourceMappingURL=ai-sdk.js.map