UNPKG

agent-contracts-runtime

Version:

Runtime bridge for executing agent-contracts workflows on Agent SDKs

239 lines 8.33 kB
// src/adapters/openai-agents-sdk.ts function buildInputGuardrails(guardrails) { return [ { name: "contract-runtime-guardrail", execute: async ({ input }) => { const inputStr = typeof input === "string" ? input : JSON.stringify(input); const results = guardrails.runChecks({ command: inputStr }); const blocking = results.filter((r) => !r.passed && r.action === "block"); return { outputInfo: { results }, tripwireTriggered: blocking.length > 0 }; } } ]; } var OpenAIAgentsSdkAdapter = class _OpenAIAgentsSdkAdapter { model; maxTurns; guardrailHooks; tools; agentName; signal; cacheConfig; lastResponseId = null; lastAgent = null; lastMemoryRef = null; AgentClass = null; runFn = null; streamRunFn = null; constructor(config = {}) { this.model = config.model; this.maxTurns = config.maxTurns; this.guardrailHooks = config.guardrailHooks; this.tools = config.tools; this.agentName = config.agentName ?? "contract-agent"; this.signal = config.signal; this.cacheConfig = config.cacheConfig ?? { enabled: true }; } // ------------------------------------------------------------------------- // Internal helpers // ------------------------------------------------------------------------- async resolveSdk() { if (this.AgentClass && this.runFn) { return { Agent: this.AgentClass, run: this.runFn, streamRun: this.streamRunFn ?? void 0 }; } const sdk = await import("@openai/agents"); this.AgentClass = sdk.Agent; this.runFn = sdk.run; return { Agent: this.AgentClass, run: this.runFn }; } createAgent(Agent, instructions, _readonly, agents) { const opts = { name: this.agentName, instructions }; if (this.model) opts.model = this.model; if (this.tools) opts.tools = this.tools; if (this.guardrailHooks) { opts.inputGuardrails = buildInputGuardrails(this.guardrailHooks); } if (agents && agents.length > 0) { opts.handoffs = agents.map((a) => { const subOpts = { name: a.name, instructions: a.prompt }; if (a.model) subOpts.model = a.model; if (a.tools) subOpts.tools = a.tools; return new Agent(subOpts); }); } return new Agent(opts); } buildRunOptions(previousResponseId) { const opts = {}; if (this.maxTurns !== void 0) opts.maxTurns = this.maxTurns; if (this.signal) opts.signal = this.signal; if (previousResponseId) opts.previousResponseId = previousResponseId; return opts; } extractOutput(result) { if (typeof result.finalOutput === "string") { return result.finalOutput; } if (result.finalOutput !== void 0 && result.finalOutput !== null) { return JSON.stringify(result.finalOutput, null, 2); } if (result.newItems) { const textParts = []; for (const item of result.newItems) { if (item.type === "message_output_item" || item.type === "text") { const rawItem = item.rawItem; if (rawItem?.content) { const content = rawItem.content; if (Array.isArray(content)) { for (const part of content) { if (typeof part === "object" && part !== null && "text" in part) { textParts.push(part.text); } } } else if (typeof content === "string") { textParts.push(content); } } } } if (textParts.length > 0) return textParts.join("\n"); } return ""; } async runWithProgress(agent, input, runOpts, onProgress) { const { run, streamRun } = await this.resolveSdk(); if (!onProgress || !streamRun) { return run(agent, input, runOpts); } const streamResult = await streamRun(agent, input, runOpts); for await (const event of streamResult.streamEvents()) { emitProgressFromOpenAIEvent(event, onProgress); } return streamResult; } // ------------------------------------------------------------------------- // SdkAdapter interface // ------------------------------------------------------------------------- async send(prompt, options) { this.lastResponseId = null; this.lastAgent = null; this.lastMemoryRef = null; const { Agent } = await this.resolveSdk(); const split = options.splitPrompt; let instructions; let runInput; if (split && this.cacheConfig.enabled !== false) { instructions = split.system.join("\n\n---\n\n"); runInput = split.user; } else { instructions = prompt; runInput = prompt; } const agent = this.createAgent(Agent, instructions, options.readonly, options.agents); const runOpts = this.buildRunOptions(); const result = await this.runWithProgress(agent, runInput, runOpts, options.onProgress); this.lastResponseId = result.lastResponseId ?? null; this.lastAgent = agent; this.lastMemoryRef = this.lastResponseId ? { id: this.lastResponseId, provider: "openai-responses", compat: "openai-agents-sdk@0.10", created_at: (/* @__PURE__ */ new Date()).toISOString() } : null; return this.extractOutput(result); } async followUp(message) { if (!this.lastResponseId) { throw new Error("followUp() called before send() \u2014 no active session"); } const { run } = await this.resolveSdk(); const agent = this.lastAgent; const runOpts = this.buildRunOptions(this.lastResponseId); const result = await run(agent, message, runOpts); this.lastResponseId = result.lastResponseId ?? this.lastResponseId; return this.extractOutput(result); } async sendExecution(request) { this.lastResponseId = null; this.lastAgent = null; this.lastMemoryRef = null; const { Agent } = await this.resolveSdk(); const split = request.splitPrompt; let instructions; let runInput; if (split && this.cacheConfig.enabled !== false) { instructions = split.system.join("\n\n---\n\n"); runInput = split.user; } else { instructions = request.prompt; runInput = request.prompt; } const agents = request.options.agents ?? request.agents; const agent = this.createAgent(Agent, instructions, request.options.readonly, agents); const runOpts = this.buildRunOptions(request.memoryRef?.id); const result = await this.runWithProgress(agent, runInput, runOpts, request.options.onProgress); this.lastResponseId = result.lastResponseId ?? null; this.lastAgent = agent; this.lastMemoryRef = this.lastResponseId ? { id: this.lastResponseId, provider: "openai-responses", compat: "openai-agents-sdk@0.10", created_at: (/* @__PURE__ */ new Date()).toISOString(), parent_run_id: request.memoryRef?.id } : null; return this.extractOutput(result); } getLastMemoryRef() { return this.lastMemoryRef; } isCompatible(compat) { return compat.startsWith("openai-agents-sdk@"); } // ------------------------------------------------------------------------- // Test support // ------------------------------------------------------------------------- /** * Inject custom Agent constructor and run function for testing. * Bypasses the dynamic import of @openai/agents. */ static withRunFn(AgentClass, runFn, config, streamRunFn) { const adapter = new _OpenAIAgentsSdkAdapter(config); adapter.AgentClass = AgentClass; adapter.runFn = runFn; adapter.streamRunFn = streamRunFn ?? null; return adapter; } }; function emitProgressFromOpenAIEvent(event, onProgress) { switch (event.type) { case "tool_called": if (event.item?.toolName) { onProgress({ type: "tool_use", tool_name: event.item.toolName }); } break; case "tool_output": onProgress({ type: "tool_result" }); break; case "reasoning_item_created": onProgress({ type: "text", message: "Reasoning..." }); break; case "handoff_occurred": if (event.item?.agent?.name) { onProgress({ type: "status", message: `Handoff to ${event.item.agent.name}` }); } break; default: break; } } export { OpenAIAgentsSdkAdapter }; //# sourceMappingURL=openai-agents-sdk.js.map