UNPKG

@openai/agents-core

Version:

The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.

180 lines • 8.48 kB
import { registerPreparedAgentTools } from "../../agentToolConfiguration.mjs"; import { getDefaultModel } from "../../defaultModel.mjs"; import { UserError } from "../../errors.mjs"; import { selectModel } from "../../runner/modelSettings.mjs"; import { cloneManifest, Manifest } from "../manifest.mjs"; import { getDefaultSandboxInstructions, renderFilesystemInstructions, renderInstructionSection, renderRemoteMountPolicyInstructions, } from "./prompts.mjs"; import { manifestWithRunAsUser, sandboxRunAsName } from "./runAsManifest.mjs"; import { SandboxWorkspaceScope } from "../workspacePaths.mjs"; export { getDefaultSandboxInstructions } from "./prompts.mjs"; export function cloneSandboxCapabilities(capabilities) { return capabilities.map((capability) => capability.clone()); } export function prepareSandboxAgent({ agent, session, capabilities, runConfigModel, processManifest = true, tracingParent, workspaceScope = new SandboxWorkspaceScope(), }) { const { model: resolvedModel, modelInstance: resolvedModelInstance } = resolveSandboxModel(agent, runConfigModel); // Capabilities are cloned before binding because tools, instructions, and model // sampling parameters can depend on the live session for this run. const boundCapabilities = cloneSandboxCapabilities(capabilities ?? agent.capabilities).map((capability) => capability .bind(session) .bindRunAs(agent.runAs) .bindModel(resolvedModel, resolvedModelInstance) .bindTracingParent(tracingParent) .bindWorkspaceScope(workspaceScope)); const boundCapabilityTypes = new Set(boundCapabilities.map((capability) => capability.type)); const canEditorAccessPath = boundCapabilityTypes.has('filesystem') ? resolveEditorPathAccess(session, sandboxRunAsName(agent.runAs)) : undefined; const runtimeManifest = processManifest ? boundCapabilities.reduce((manifest, capability) => capability.processManifest(manifest), resolveManifest(agent, session)) : resolveManifest(agent, session); for (const capability of boundCapabilities) { const missingTypes = [...capability.requiredCapabilityTypes()].filter((requiredType) => !boundCapabilityTypes.has(requiredType)); if (missingTypes.length > 0) { throw new UserError(`${capability.type} requires missing capabilities: ${missingTypes.sort().join(', ')}`); } } const providerData = boundCapabilities.reduce((samplingParams, capability) => // Provider data often nests model-specific settings; merge recursively so a // capability can add its section without replacing user-supplied siblings. mergeSandboxProviderData(samplingParams, capability.samplingParams({ model: resolvedModel, ...(resolvedModelInstance ? { modelInstance: resolvedModelInstance } : {}), })), {}); const capabilityTools = boundCapabilities.flatMap((capability) => capability.tools()); const tools = [...agent.tools, ...capabilityTools]; const prepared = agent.clone({ capabilities: boundCapabilities, tools, modelSettings: { ...agent.modelSettings, providerData: mergeSandboxProviderData(agent.modelSettings.providerData, providerData), }, instructions: async (runContext, preparedAgent) => { const capabilityInstructions = await Promise.all(boundCapabilities.map((capability) => capability.instructions(runtimeManifest))); const segments = []; const baseInstructions = await renderBaseInstructions(agent, runContext, preparedAgent); if (baseInstructions) { segments.push(baseInstructions); } const agentInstructions = await renderAgentInstructions(agent.instructions, runContext, preparedAgent); if (agentInstructions) { segments.push(renderInstructionSection('Agent instructions', agentInstructions)); } const capabilityFragments = capabilityInstructions.filter((fragment) => Boolean(fragment)); if (capabilityFragments.length > 0) { segments.push(renderInstructionSection('Sandbox capability instructions', capabilityFragments.join('\n\n'))); } const remoteMountPolicy = renderRemoteMountPolicyInstructions(runtimeManifest, canEditorAccessPath); if (remoteMountPolicy) { segments.push(renderInstructionSection('Sandbox remote mount policy', remoteMountPolicy)); } segments.push(renderFilesystemInstructions(runtimeManifest, workspaceScope)); return segments.join('\n\n'); }, }); registerPreparedAgentTools(prepared, agent, capabilityTools); prepared.runtimeManifest = runtimeManifest; return prepared; } function resolveEditorPathAccess(session, runAs) { const editor = session.createEditor?.(runAs); if (typeof editor?.canAccessPathForEdit !== 'function') { return undefined; } return editor.canAccessPathForEdit.bind(editor); } function resolveManifest(agent, session) { const manifestCandidate = session.state.manifest ?? agent.defaultManifest ?? new Manifest(); return manifestWithRunAsUser(cloneManifest(manifestCandidate), agent.runAs); } function resolveSandboxModel(agent, runConfigModel) { let runConfigModelForSelection; let runConfigModelInstance; if (isResolvedSandboxRuntimeModel(runConfigModel)) { runConfigModelForSelection = runConfigModel.model; runConfigModelInstance = runConfigModel.modelInstance; } else { runConfigModelForSelection = runConfigModel; runConfigModelInstance = runConfigModel && typeof runConfigModel !== 'string' ? runConfigModel : undefined; } const selectedModel = selectModel(agent.model, runConfigModelForSelection); if (typeof selectedModel === 'string' && selectedModel.trim().length > 0) { return { model: selectedModel, ...(selectedModel === runConfigModelForSelection && runConfigModelInstance ? { modelInstance: runConfigModelInstance } : {}), }; } if (selectedModel && typeof selectedModel !== 'string') { return { model: getSandboxRuntimeModelName(selectedModel) ?? getDefaultModel(), modelInstance: selectedModel, }; } return { model: getDefaultModel(), ...(runConfigModelInstance ? { modelInstance: runConfigModelInstance } : {}), }; } function isResolvedSandboxRuntimeModel(model) { return (typeof model === 'object' && model !== null && 'model' in model && typeof model.model === 'string' && 'modelInstance' in model); } function getSandboxRuntimeModelName(model) { const candidate = model?.model ?? model?.name; return typeof candidate === 'string' && candidate.trim().length > 0 ? candidate : undefined; } async function renderAgentInstructions(instructions, runContext, agent) { if (typeof instructions === 'function') { return await instructions(runContext, agent); } return instructions; } async function renderBaseInstructions(agent, runContext, preparedAgent) { const baseInstructions = agent.baseInstructions ?? getDefaultSandboxInstructions(); if (typeof baseInstructions === 'function') { return await baseInstructions(runContext, preparedAgent); } return baseInstructions; } function mergeSandboxProviderData(base, update) { if (!base) { return mergePlainRecords({}, update); } return mergePlainRecords(base, update); } function mergePlainRecords(base, update) { const merged = { ...base }; for (const [key, updateValue] of Object.entries(update)) { const baseValue = merged[key]; if (isPlainRecord(baseValue) && isPlainRecord(updateValue)) { merged[key] = mergePlainRecords(baseValue, updateValue); continue; } merged[key] = updateValue; } return merged; } function isPlainRecord(value) { if (typeof value !== 'object' || value === null || Array.isArray(value)) { return false; } const prototype = Object.getPrototypeOf(value); return prototype === Object.prototype || prototype === null; } //# sourceMappingURL=agentPreparation.mjs.map