UNPKG

agents

Version:

A home for your AI agents

148 lines (147 loc) • 4.47 kB
//#region src/experimental/channels/web/protocol.ts /** * The header carrying a connection's WebIdentity from the gateway to the * agent. The gateway always sets it, so a client cannot supply its own; an * agent must not take WebSocket upgrades from any other route. */ const WEB_IDENTITY_HEADER = "x-channels-identity"; /** * Parse a text frame. Returns undefined for anything that is not a Channels * frame, so the socket's other protocols keep working. */ function parseClientFrame(text) { let frame; try { frame = JSON.parse(text); } catch { return; } if (!isObject(frame) || typeof frame.type !== "string") return void 0; if (frame.type === "channels:subscribe") { const { responseId, from } = frame; if (typeof responseId !== "string") return { invalid: "responseId" }; if (from !== void 0 && !Number.isInteger(from)) return { invalid: "from" }; return { type: "channels:subscribe", responseId, ...typeof from === "number" && { from } }; } if (frame.type === "channels:list-conversations") return isId(frame.requestId) ? { type: "channels:list-conversations", requestId: frame.requestId } : { invalid: "requestId" }; if (frame.type !== "channels:event") return void 0; const event = frame.event; const eventId = isObject(event) ? event.eventId : void 0; if (!isObject(event) || !isId(eventId)) return { invalid: "eventId" }; const parsed = parseEvent(event, eventId); return typeof parsed === "string" ? { invalid: parsed, eventId } : { type: "channels:event", event: parsed }; } function isObject(value) { return typeof value === "object" && value !== null && !Array.isArray(value); } function isId(value) { return typeof value === "string" && value.length > 0; } /** The event, or the name of the first invalid field. */ function parseEvent(event, eventId) { switch (event.type) { case "message": { const message = event.message; if (!isObject(message) || !isId(message.id)) return "message.id"; if (message.role !== "user") return "message.role"; const parts = message.parts; if (!Array.isArray(parts) || !parts.every(isPart)) return "message.parts"; return { type: "message", eventId, message: { id: message.id, role: "user", parts, ...isObject(message.metadata) && { metadata: message.metadata } }, ...clientTools(event.clientTools) }; } case "tool-result": { const { turnId, toolCallId, result } = event; if (!isId(turnId)) return "turnId"; if (!isId(toolCallId)) return "toolCallId"; if (!isObject(result) || typeof result.ok !== "boolean") return "result"; return { type: "tool-result", eventId, turnId, toolCallId, result: result.ok ? { ok: true, output: result.output ?? null } : { ok: false, ...typeof result.errorText === "string" && { errorText: result.errorText } }, ...clientTools(event.clientTools) }; } case "approval-response": { const { turnId, approvalId, approved, reason } = event; if (!isId(turnId)) return "turnId"; if (!isId(approvalId)) return "approvalId"; if (typeof approved !== "boolean") return "approved"; return { type: "approval-response", eventId, turnId, approvalId, approved, ...typeof reason === "string" && { reason } }; } case "cancel": return isId(event.turnId) ? { type: "cancel", eventId, turnId: event.turnId } : "turnId"; case "conversation-create": case "conversation-fork": return { type: event.type, eventId }; case "conversation-reset": if (event.handoff !== void 0 && typeof event.handoff !== "string") return "handoff"; return { type: "conversation-reset", eventId, ...event.handoff && { handoff: event.handoff } }; default: return "type"; } } function isPart(part) { return isObject(part) && typeof part.type === "string"; } /** Keeps tools with a name, dropping a schema that is not an object. */ function clientTools(value) { if (!Array.isArray(value)) return {}; const tools = []; for (const tool of value) { if (!isObject(tool) || !isId(tool.name)) continue; tools.push({ name: tool.name, ...typeof tool.description === "string" && { description: tool.description }, ...isObject(tool.inputSchema) && { inputSchema: tool.inputSchema } }); } return { clientTools: tools }; } //#endregion export { parseClientFrame as n, WEB_IDENTITY_HEADER as t }; //# sourceMappingURL=protocol-y2sSY584.js.map