@openai/agents-core
Version:
The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.
431 lines • 17.2 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SandboxMemoryGenerationManager = void 0;
exports.getOrCreateSandboxMemoryGenerationManager = getOrCreateSandboxMemoryGenerationManager;
const _shims_1 = require("@openai/agents-core/_shims");
const zod_1 = require("zod");
const errors_1 = require("../../errors.js");
const logger_1 = __importStar(require("../../logger.js"));
const manifest_1 = require("../manifest.js");
const sessionLifecycle_1 = require("../runtime/sessionLifecycle.js");
const spans_1 = require("../runtime/spans.js");
const stableJson_1 = require("../shared/stableJson.js");
const rollouts_1 = require("./rollouts.js");
const storage_1 = require("./storage.js");
const prompts_1 = require("./prompts.js");
const RolloutExtractionArtifactsSchema = zod_1.z.object({
rollout_summary: zod_1.z.string(),
rollout_slug: zod_1.z.string(),
raw_memory: zod_1.z.string(),
});
const managersBySession = new WeakMap();
const objectIds = new WeakMap();
let nextObjectId = 1;
function getOrCreateSandboxMemoryGenerationManager(args) {
if (args.memory.generate === null) {
throw new errors_1.UserError('SandboxMemoryGenerationManager requires Memory.generate to be enabled.');
}
const layout = normalizedLayout(args.memory);
const layoutKey = memoryLayoutKey(args.memory);
let registry = managersBySession.get(args.session);
const existing = registry?.get(layoutKey);
if (existing) {
const nextSignature = memoryGenerationSignature(args.memory.generate);
if (existing.generationSignature !== nextSignature) {
throw new errors_1.UserError('Sandbox session already has a different Memory generation config attached for this memory layout.');
}
if (existing.manager.isStopped()) {
registry.delete(layoutKey);
if (registry.size === 0) {
managersBySession.delete(args.session);
registry = undefined;
}
}
else {
existing.manager.updateRuntimeContext({
runAs: args.runAs,
runAgent: args.runAgent,
tracingParent: args.tracingParent,
});
return existing.manager;
}
}
if (registry) {
for (const entry of registry.values()) {
if (entry.layout.memoriesDir === layout.memoriesDir) {
throw new errors_1.UserError(`Sandbox session already has a Memory generation capability for memoriesDir=${layout.memoriesDir}. Use a different memoriesDir for isolated memories, or the same layout to share memory.`);
}
if (entry.layout.sessionsDir === layout.sessionsDir) {
throw new errors_1.UserError(`Sandbox session already has a Memory generation capability for sessionsDir=${layout.sessionsDir}. Use a different sessionsDir for isolated memories, or the same layout to share memory.`);
}
}
}
const manager = new SandboxMemoryGenerationManager(args);
registry ??= new Map();
registry.set(layoutKey, {
memory: args.memory,
manager,
generationSignature: memoryGenerationSignature(args.memory.generate),
layout,
});
managersBySession.set(args.session, registry);
return manager;
}
class SandboxMemoryGenerationManager {
session;
memory;
runAs;
runAgent;
tracingParent;
storage;
pendingRolloutIds = new Set();
flushPromise;
stopped = false;
unregisterPreStopHook;
constructor(args) {
this.session = args.session;
this.memory = args.memory;
this.runAs = args.runAs;
this.runAgent = args.runAgent;
this.tracingParent = args.tracingParent;
this.storage = new storage_1.SandboxMemoryStorage({
session: args.session,
runAs: args.runAs,
store: args.memory.store,
tracingParent: args.tracingParent,
});
this.unregisterPreStopHook = (0, sessionLifecycle_1.registerSandboxPreStopHook)(this.session, async () => {
await this.flush();
});
}
isStopped() {
return this.stopped;
}
updateRuntimeContext(args) {
this.runAs = args.runAs;
this.runAgent = args.runAgent;
this.tracingParent = args.tracingParent;
this.storage.updateRuntimeContext({
runAs: args.runAs,
tracingParent: args.tracingParent,
});
}
async enqueueState(state, args) {
if (this.memory.generate === null || this.stopped) {
return;
}
const rolloutId = (0, rollouts_1.resolveMemoryRolloutId)({
...args.rolloutIdentity,
fallbackId: (0, _shims_1.randomUUID)(),
});
const payload = (0, rollouts_1.buildMemoryRolloutPayload)(state, {
rolloutId,
exception: args.exception,
inputOverride: args.inputOverride,
});
await (0, spans_1.withSandboxSpan)('sandbox.memory.enqueue_rollout', {
rollout_id: rolloutId,
}, async () => {
await this.storage.ensureLayout(this.memory);
await this.storage.appendJsonl((0, storage_1.joinRelativePaths)(this.memory.layout.sessionsDir, `${rolloutId}.jsonl`), payload);
this.pendingRolloutIds.add(rolloutId);
}, this.tracingParent);
}
async flush() {
if (this.flushPromise) {
await this.flushPromise;
return;
}
this.flushPromise = this.flushOnce();
try {
await this.flushPromise;
}
finally {
this.flushPromise = undefined;
}
}
async flushOnce() {
if (this.memory.generate === null) {
return;
}
if (this.stopped) {
this.unregister();
return;
}
this.stopped = true;
try {
await (0, spans_1.withSandboxSpan)('sandbox.memory.flush', {
rollout_count: this.pendingRolloutIds.size,
}, async () => {
await this.storage.ensureLayout(this.memory);
let wroteArtifacts = false;
for (const rolloutId of [...this.pendingRolloutIds].sort()) {
try {
const extraction = await this.runPhaseOne(rolloutId);
if (!validateRolloutArtifacts(extraction)) {
continue;
}
await this.persistPhaseOneArtifacts(rolloutId, extraction);
wroteArtifacts = true;
}
catch (error) {
(0, logger_1.logModelAndToolActionWarning)(logger_1.default, 'Sandbox memory phase 1 failed:', error, { rolloutId });
}
}
if (wroteArtifacts) {
try {
await this.runPhaseTwo();
}
catch (error) {
(0, logger_1.logModelAndToolActionWarning)(logger_1.default, 'Sandbox memory phase 2 failed:', error);
}
}
}, this.tracingParent);
}
finally {
this.pendingRolloutIds.clear();
this.unregister();
}
}
async runPhaseOne(rolloutId) {
const generate = this.memory.generate;
if (generate === null) {
throw new errors_1.UserError('Memory generation is disabled.');
}
const transcriptPath = (0, storage_1.joinRelativePaths)(this.memory.layout.sessionsDir, `${rolloutId}.jsonl`);
const transcript = await this.storage.readText(transcriptPath);
if (!transcript) {
throw new errors_1.UserError(`Memory rollout transcript was not found: ${transcriptPath}`);
}
const { SandboxAgent } = await Promise.resolve().then(() => __importStar(require("../agent.js")));
const phaseOneAgent = new SandboxAgent({
name: 'sandbox-memory-phase-one',
instructions: (0, prompts_1.renderRolloutExtractionInstructions)(generate.extraPrompt),
model: generate.phaseOneModel,
modelSettings: generate.phaseOneModelSettings,
outputType: RolloutExtractionArtifactsSchema,
defaultManifest: this.currentManifest(),
runAs: this.runAs,
});
const result = await this.runAgent(phaseOneAgent, (0, prompts_1.renderRolloutExtractionUserPrompt)({
terminalMetadataJson: (0, rollouts_1.renderPhaseOnePrompt)(transcript),
rolloutContents: transcript,
}), {
sandbox: {
session: this.session,
manifest: this.currentManifest(),
},
maxTurns: 500,
});
return RolloutExtractionArtifactsSchema.parse(result.finalOutput);
}
async persistPhaseOneArtifacts(rolloutId, extraction) {
const memoriesDir = this.memory.layout.memoriesDir;
const transcriptPath = (0, storage_1.joinRelativePaths)(this.memory.layout.sessionsDir, `${rolloutId}.jsonl`);
const transcript = await this.storage.readText(transcriptPath);
const metadata = rolloutMetadataFromTranscript(transcript ?? '');
const slug = (0, rollouts_1.normalizeRolloutSlug)(extraction.rollout_slug);
const rolloutPath = (0, storage_1.joinRelativePaths)(this.memory.layout.sessionsDir, `${rolloutId}.jsonl`);
const rolloutSummaryFile = (0, storage_1.joinRelativePaths)('rollout_summaries', `${rolloutId}_${slug}.md`);
await this.storage.writeText((0, storage_1.joinRelativePaths)(memoriesDir, 'raw_memories', `${rolloutId}.md`), formatRawMemory({
updatedAt: metadata.updatedAt,
rolloutId,
rolloutPath,
rolloutSummaryFile,
terminalState: metadata.terminalState,
rawMemory: extraction.raw_memory,
}));
await this.storage.writeText((0, storage_1.joinRelativePaths)(memoriesDir, rolloutSummaryFile), formatRolloutSummary({
updatedAt: metadata.updatedAt,
rolloutPath,
sessionId: String(this.session.state.sessionId ?? ''),
terminalState: metadata.terminalState,
rolloutSummary: extraction.rollout_summary,
}));
}
async runPhaseTwo() {
const generate = this.memory.generate;
if (generate === null) {
throw new errors_1.UserError('Memory generation is disabled.');
}
const selection = await this.storage.buildPhaseTwoInputSelection({
memoriesDir: this.memory.layout.memoriesDir,
maxRawMemoriesForConsolidation: generate.maxRawMemoriesForConsolidation ?? 256,
});
if (!(await this.storage.rebuildRawMemories({
memoriesDir: this.memory.layout.memoriesDir,
selectedItems: selection.selected,
}))) {
return;
}
const { SandboxAgent } = await Promise.resolve().then(() => __importStar(require("../agent.js")));
const phaseTwoAgent = new SandboxAgent({
name: 'sandbox-memory-phase-two',
model: generate.phaseTwoModel,
modelSettings: generate.phaseTwoModelSettings,
defaultManifest: this.currentManifest(),
runAs: this.runAs,
});
await this.runAgent(phaseTwoAgent, (0, prompts_1.renderMemoryConsolidationPrompt)({
memoryRoot: this.memory.layout.memoriesDir,
selection,
extraPrompt: generate.extraPrompt,
}), {
sandbox: {
session: this.session,
manifest: this.currentManifest(),
},
maxTurns: generate.phaseTwoMaxTurns ?? 500,
});
await this.storage.writePhaseTwoSelection({
memoriesDir: this.memory.layout.memoriesDir,
selectedItems: selection.selected,
});
}
currentManifest() {
return new manifest_1.Manifest(this.session.state.manifest);
}
unregister() {
this.unregisterPreStopHook?.();
this.unregisterPreStopHook = undefined;
const registry = managersBySession.get(this.session);
if (!registry) {
return;
}
const layoutKey = memoryLayoutKey(this.memory);
const existing = registry.get(layoutKey);
if (existing?.manager === this) {
registry.delete(layoutKey);
}
if (registry.size === 0) {
managersBySession.delete(this.session);
}
}
}
exports.SandboxMemoryGenerationManager = SandboxMemoryGenerationManager;
function validateRolloutArtifacts(artifacts) {
const hasSlug = artifacts.rollout_slug.trim().length > 0;
const hasSummary = artifacts.rollout_summary.trim().length > 0;
const hasRawMemory = artifacts.raw_memory.trim().length > 0;
if (!hasSlug && !hasSummary && !hasRawMemory) {
return false;
}
if (!hasSlug || !hasSummary || !hasRawMemory) {
throw new errors_1.UserError('Phase 1 returned partially-empty memory artifacts.');
}
(0, rollouts_1.normalizeRolloutSlug)(artifacts.rollout_slug);
return true;
}
function rolloutMetadataFromTranscript(transcript) {
const payloads = transcript
.split('\n')
.filter((line) => line.trim().length > 0)
.map((line) => JSON.parse(line));
const lastPayload = payloads[payloads.length - 1];
if (!lastPayload) {
return {
updatedAt: 'unknown',
terminalState: 'unknown',
};
}
const terminalMetadata = lastPayload.terminal_metadata;
const terminalState = terminalMetadata && typeof terminalMetadata === 'object'
? String(terminalMetadata.terminal_state ??
'unknown')
: 'unknown';
return {
updatedAt: typeof lastPayload.updated_at === 'string'
? lastPayload.updated_at
: 'unknown',
terminalState,
};
}
function formatRawMemory(args) {
return [
`rollout_id: ${args.rolloutId}`,
`updated_at: ${args.updatedAt}`,
`rollout_path: ${args.rolloutPath}`,
`rollout_summary_file: ${args.rolloutSummaryFile}`,
`terminal_state: ${args.terminalState}`,
'',
args.rawMemory.trimEnd(),
'',
].join('\n');
}
function formatRolloutSummary(args) {
return [
`session_id: ${args.sessionId}`,
`updated_at: ${args.updatedAt}`,
`rollout_path: ${args.rolloutPath}`,
`terminal_state: ${args.terminalState}`,
'',
args.rolloutSummary.trimEnd(),
'',
].join('\n');
}
function normalizedLayout(memory) {
return {
memoriesDir: normalizeLayoutPath(memory.layout.memoriesDir),
sessionsDir: normalizeLayoutPath(memory.layout.sessionsDir),
summaryFile: normalizeLayoutPath(memory.layout.summaryFile),
};
}
function memoryLayoutKey(memory) {
const layout = normalizedLayout(memory);
return `${layout.memoriesDir}\0${layout.sessionsDir}\0${layout.summaryFile}`;
}
function normalizeLayoutPath(value) {
return value
.split('/')
.filter((part) => part.length > 0 && part !== '.')
.join('/');
}
function memoryGenerationSignature(generate) {
return (0, stableJson_1.stableJsonStringify)(generate, {
encodeFunction: (value) => `function:${value.name || 'anonymous'}`,
encodeNonPlainObject: (value) => `object:${objectId(value)}`,
});
}
function objectId(value) {
const existing = objectIds.get(value);
if (existing) {
return existing;
}
const id = nextObjectId++;
objectIds.set(value, id);
return id;
}
//# sourceMappingURL=generation.js.map