@copilotkit/runtime
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
215 lines (213 loc) • 6.53 kB
JavaScript
require("reflect-metadata");
const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
let _copilotkit_shared = require("@copilotkit/shared");
let _ag_ui_client = require("@ag-ui/client");
//#region src/agent/converters/aisdk.ts
/**
* Converts an AI SDK `fullStream` into AG-UI `BaseEvent` objects.
*
* This is a pure converter — it does NOT emit lifecycle events
* (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class)
* is responsible for those.
*
* Terminal stream events (finish, error, abort) cause the generator to
* return so the caller can handle lifecycle appropriately.
*/
async function* convertAISDKStream(fullStream, abortSignal) {
let messageId = (0, _copilotkit_shared.randomUUID)();
let reasoningMessageId = (0, _copilotkit_shared.randomUUID)();
let isInReasoning = false;
const toolCallStates = /* @__PURE__ */ new Map();
const ensureToolCallState = (toolCallId) => {
let state = toolCallStates.get(toolCallId);
if (!state) {
state = {
started: false,
hasArgsDelta: false,
ended: false
};
toolCallStates.set(toolCallId, state);
}
return state;
};
/**
* Auto-close an open reasoning lifecycle.
* Some AI SDK providers (notably @ai-sdk/anthropic) never emit "reasoning-end",
* which leaves downstream state machines stuck. This helper emits the
* missing REASONING_MESSAGE_END + REASONING_END events so the stream
* can transition to text, tool-call, or finish phases.
*/
function* closeReasoningIfOpen() {
if (!isInReasoning) return;
isInReasoning = false;
yield {
type: _ag_ui_client.EventType.REASONING_MESSAGE_END,
messageId: reasoningMessageId
};
yield {
type: _ag_ui_client.EventType.REASONING_END,
messageId: reasoningMessageId
};
}
try {
for await (const part of fullStream) {
const p = part;
if (p.type !== "reasoning-delta") yield* closeReasoningIfOpen();
switch (p.type) {
case "abort": return;
case "reasoning-start": {
const providedId = "id" in p ? p.id : void 0;
reasoningMessageId = providedId && providedId !== "0" ? providedId : (0, _copilotkit_shared.randomUUID)();
yield {
type: _ag_ui_client.EventType.REASONING_START,
messageId: reasoningMessageId
};
yield {
type: _ag_ui_client.EventType.REASONING_MESSAGE_START,
messageId: reasoningMessageId,
role: "reasoning"
};
isInReasoning = true;
break;
}
case "reasoning-delta": {
const delta = p.text ?? "";
if (!delta) break;
yield {
type: _ag_ui_client.EventType.REASONING_MESSAGE_CONTENT,
messageId: reasoningMessageId,
delta
};
break;
}
case "reasoning-end": break;
case "tool-input-start": {
const toolCallId = p.id;
const state = ensureToolCallState(toolCallId);
state.toolName = p.toolName;
if (!state.started) {
state.started = true;
yield {
type: _ag_ui_client.EventType.TOOL_CALL_START,
parentMessageId: messageId,
toolCallId,
toolCallName: p.toolName
};
}
break;
}
case "tool-input-delta": {
const toolCallId = p.id;
const state = ensureToolCallState(toolCallId);
state.hasArgsDelta = true;
yield {
type: _ag_ui_client.EventType.TOOL_CALL_ARGS,
toolCallId,
delta: p.delta
};
break;
}
case "tool-input-end": break;
case "text-start": {
const providedId = "id" in p ? p.id : void 0;
messageId = providedId && providedId !== "0" ? providedId : (0, _copilotkit_shared.randomUUID)();
break;
}
case "text-delta": {
const textDelta = "text" in p ? p.text : "";
yield {
type: _ag_ui_client.EventType.TEXT_MESSAGE_CHUNK,
role: "assistant",
messageId,
delta: textDelta
};
break;
}
case "tool-call": {
const toolCallId = p.toolCallId;
const state = ensureToolCallState(toolCallId);
state.toolName = p.toolName ?? state.toolName;
if (!state.started) {
state.started = true;
yield {
type: _ag_ui_client.EventType.TOOL_CALL_START,
parentMessageId: messageId,
toolCallId,
toolCallName: p.toolName
};
}
if (!state.hasArgsDelta && "input" in p && p.input !== void 0) {
let serializedInput = "";
if (typeof p.input === "string") serializedInput = p.input;
else try {
serializedInput = JSON.stringify(p.input);
} catch {
serializedInput = String(p.input);
}
if (serializedInput.length > 0) {
yield {
type: _ag_ui_client.EventType.TOOL_CALL_ARGS,
toolCallId,
delta: serializedInput
};
state.hasArgsDelta = true;
}
}
if (!state.ended) {
state.ended = true;
yield {
type: _ag_ui_client.EventType.TOOL_CALL_END,
toolCallId
};
}
break;
}
case "tool-result": {
const toolResult = "output" in p ? p.output : "result" in p ? p.result : null;
const toolName = "toolName" in p ? p.toolName : "";
toolCallStates.delete(p.toolCallId);
if (toolName === "AGUISendStateSnapshot" && toolResult && typeof toolResult === "object") {
const snapshot = toolResult.snapshot;
if (snapshot !== void 0) yield {
type: _ag_ui_client.EventType.STATE_SNAPSHOT,
snapshot
};
} else if (toolName === "AGUISendStateDelta" && toolResult && typeof toolResult === "object") {
const delta = toolResult.delta;
if (delta !== void 0) yield {
type: _ag_ui_client.EventType.STATE_DELTA,
delta
};
}
let serializedResult;
try {
serializedResult = JSON.stringify(toolResult);
} catch {
serializedResult = `[Unserializable tool result from ${toolName || "unknown tool"}]`;
}
yield {
type: _ag_ui_client.EventType.TOOL_CALL_RESULT,
role: "tool",
messageId: (0, _copilotkit_shared.randomUUID)(),
toolCallId: p.toolCallId,
content: serializedResult
};
break;
}
case "finish": return;
case "error": {
if (abortSignal.aborted) return;
const err = p.error ?? p.message ?? p.cause;
if (err instanceof Error) throw err;
throw new Error(typeof err === "string" ? err : `AI SDK stream error: ${JSON.stringify(p)}`);
}
default: break;
}
}
} finally {
yield* closeReasoningIfOpen();
}
}
//#endregion
exports.convertAISDKStream = convertAISDKStream;
//# sourceMappingURL=aisdk.cjs.map