first commit
This commit is contained in:
67
async-agent-lab/live/run.ts
Normal file
67
async-agent-lab/live/run.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { mkdtempSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import type { LLM } from '../agent/llm.ts';
|
||||
import { RUNS_DIR } from '../agent/workspace.ts';
|
||||
import { Runtime } from './runtime.ts';
|
||||
import { asynchronous, runAsync } from './scenarios/async.ts';
|
||||
import { background, runBackground } from './scenarios/background.ts';
|
||||
import { blocking, runBlocking } from './scenarios/blocking.ts';
|
||||
import { sync, runSync } from './scenarios/sync.ts';
|
||||
import type { LiveBody, LiveEvent } from './types.ts';
|
||||
|
||||
export const scenarios = [
|
||||
{ ...sync, execute: runSync },
|
||||
{ ...background, execute: runBackground },
|
||||
{ ...blocking, execute: runBlocking },
|
||||
{ ...asynchronous, execute: runAsync },
|
||||
];
|
||||
|
||||
export class LiveRun {
|
||||
readonly id: string;
|
||||
readonly workspace: string;
|
||||
readonly events: LiveEvent[] = [];
|
||||
readonly listeners = new Set<(event: LiveEvent) => void>();
|
||||
readonly runtime: Runtime;
|
||||
private startedAt = Date.now();
|
||||
private closed = false;
|
||||
private scenario: (typeof scenarios)[number];
|
||||
private llm: LLM;
|
||||
|
||||
constructor(scenario: (typeof scenarios)[number], llm: LLM) {
|
||||
this.scenario = scenario;
|
||||
this.llm = llm;
|
||||
this.workspace = mkdtempSync(join(RUNS_DIR, `${scenario.id}-`));
|
||||
this.id = this.workspace.split('/').at(-1)!;
|
||||
this.runtime = new Runtime(scenario, this.workspace, llm, (event) => this.record(event));
|
||||
this.record({ type: 'run.start', id: this.id, scenario: scenario.id, workspace: this.workspace, startedAt: this.startedAt });
|
||||
}
|
||||
|
||||
private record(body: LiveBody) {
|
||||
if (this.closed) return;
|
||||
const secret = this.llm.provider.apiKey;
|
||||
const serialized = JSON.stringify(body);
|
||||
const safe = secret && serialized.includes(secret) ? JSON.parse(serialized.replaceAll(secret, '[已隐藏]')) as LiveBody : body;
|
||||
const event = { ...safe, seq: this.events.length + 1, t: Date.now() - this.startedAt };
|
||||
this.events.push(event);
|
||||
for (const listener of this.listeners) listener(event);
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.record({ type: 'run.state', state: 'running' });
|
||||
try {
|
||||
const summary = await this.scenario.execute(this.runtime);
|
||||
this.record({ type: 'run.state', state: 'done', summary });
|
||||
} catch (error) {
|
||||
this.record({ type: 'run.state', state: 'error', note: (error as Error).message });
|
||||
} finally {
|
||||
this.closed = true;
|
||||
this.runtime.stop();
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.record({ type: 'run.state', state: 'stopped' });
|
||||
this.closed = true;
|
||||
this.runtime.stop();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user