mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 11:33:14 +00:00
* feat: update cli for local * feat: file diff formatting * fix: udate diff format * fix: show green/red diffs * fix: modifications * feat: str based replacement * feat: update streaming to allow submissions * feat: traces * fix: wrap text * feat: update cli * fix: remove json * fix: remove write fill diff * fix: mods * fix: updates to logging * fix: add trace replay service * feat: update logs * fix: remove debugging * fix: lint * fix: unused vars * fix: updates * fix: formatting * fix: update streaming value * fix: replace constants * feat: mods * nit: change interrupt * nit: remove question
100 lines
2.8 KiB
TypeScript
100 lines
2.8 KiB
TypeScript
import { formatDisplayLog } from "./logger.js";
|
|
|
|
export interface TraceReplayCallbacks {
|
|
setLogs: (updater: (prev: string[]) => string[]) => void; // eslint-disable-line no-unused-vars
|
|
setLoadingLogs: (loading: boolean) => void; // eslint-disable-line no-unused-vars
|
|
}
|
|
|
|
export class TraceReplayService {
|
|
private callbacks: TraceReplayCallbacks;
|
|
private rawLogs: any[] = [];
|
|
|
|
constructor(callbacks: TraceReplayCallbacks) {
|
|
this.callbacks = callbacks;
|
|
}
|
|
|
|
/**
|
|
* Get formatted logs for display
|
|
*/
|
|
getFormattedLogs(): string[] {
|
|
const formattedLogs: string[] = [];
|
|
|
|
for (const chunk of this.rawLogs) {
|
|
if (typeof chunk === "string") {
|
|
const formatted = formatDisplayLog(chunk);
|
|
formattedLogs.push(...formatted);
|
|
} else if (chunk && chunk.data) {
|
|
// Process all chunks with data, not just "updates" events
|
|
const formatted = formatDisplayLog(chunk);
|
|
formattedLogs.push(...formatted);
|
|
}
|
|
}
|
|
|
|
return formattedLogs;
|
|
}
|
|
|
|
/**
|
|
* Update the display with formatted logs
|
|
*/
|
|
private updateDisplay() {
|
|
const formattedLogs = this.getFormattedLogs();
|
|
this.callbacks.setLogs(() => formattedLogs);
|
|
}
|
|
|
|
async replayFromTrace(langsmithRun: any, playbackSpeed: number = 500) {
|
|
this.rawLogs = [];
|
|
this.callbacks.setLogs(() => []);
|
|
this.callbacks.setLoadingLogs(true);
|
|
|
|
try {
|
|
const messages = langsmithRun.messages || [];
|
|
|
|
for (let i = 0; i < messages.length; i++) {
|
|
const message = messages[i];
|
|
|
|
// Convert LangSmith message to the format expected by formatDisplayLog
|
|
const mockChunk = {
|
|
event: "updates",
|
|
data: {
|
|
agent: {
|
|
messages: [message],
|
|
},
|
|
},
|
|
};
|
|
this.rawLogs.push(mockChunk);
|
|
this.updateDisplay();
|
|
|
|
if (this.rawLogs.length === 1) {
|
|
this.callbacks.setLoadingLogs(false);
|
|
}
|
|
|
|
// Add delay between messages to simulate streaming
|
|
if (i < messages.length - 1) {
|
|
await new Promise((resolve) => setTimeout(resolve, playbackSpeed));
|
|
}
|
|
}
|
|
|
|
// Check for interrupt data in the trace and add it at the end
|
|
if (langsmithRun.__interrupt__ || langsmithRun.interrupt) {
|
|
const interruptData =
|
|
langsmithRun.__interrupt__ || langsmithRun.interrupt;
|
|
const interruptChunk = {
|
|
event: "interrupt",
|
|
data: {
|
|
__interrupt__: Array.isArray(interruptData)
|
|
? interruptData
|
|
: [interruptData],
|
|
},
|
|
};
|
|
this.rawLogs.push(interruptChunk);
|
|
this.updateDisplay();
|
|
}
|
|
} catch (err: any) {
|
|
this.rawLogs.push(`Error during replay: ${err.message}`);
|
|
this.updateDisplay();
|
|
this.callbacks.setLoadingLogs(false);
|
|
} finally {
|
|
this.callbacks.setLoadingLogs(false);
|
|
}
|
|
}
|
|
}
|