2025-07-29 17:37:13 -04:00
|
|
|
/**
|
|
|
|
|
* Utility functions for CLI app
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { Client, StreamMode } from "@langchain/langgraph-sdk";
|
|
|
|
|
import {
|
|
|
|
|
OPEN_SWE_STREAM_MODE,
|
2025-08-01 15:50:40 -04:00
|
|
|
LOCAL_MODE_HEADER,
|
2025-08-22 16:58:27 -04:00
|
|
|
OPEN_SWE_V2_GRAPH_ID,
|
2025-07-29 17:37:13 -04:00
|
|
|
} from "@open-swe/shared/constants";
|
|
|
|
|
import { formatDisplayLog } from "./logger.js";
|
2025-08-05 18:52:45 -04:00
|
|
|
|
2025-07-29 17:37:13 -04:00
|
|
|
const LANGGRAPH_URL = process.env.LANGGRAPH_URL || "http://localhost:2024";
|
|
|
|
|
|
|
|
|
|
/**
|
2025-08-22 16:58:27 -04:00
|
|
|
* Submit feedback to the coding agent
|
2025-07-29 17:37:13 -04:00
|
|
|
*/
|
|
|
|
|
export async function submitFeedback({
|
|
|
|
|
plannerFeedback,
|
|
|
|
|
plannerThreadId,
|
|
|
|
|
setLogs,
|
|
|
|
|
setPlannerFeedback,
|
2025-08-01 15:50:40 -04:00
|
|
|
setStreamingPhase,
|
2025-07-29 17:37:13 -04:00
|
|
|
}: {
|
|
|
|
|
plannerFeedback: string;
|
|
|
|
|
plannerThreadId: string;
|
2025-08-05 18:52:45 -04:00
|
|
|
setLogs: (updater: (prev: string[]) => string[]) => void; // eslint-disable-line no-unused-vars
|
2025-08-06 09:41:11 -07:00
|
|
|
setPlannerFeedback: () => void;
|
2025-08-05 18:52:45 -04:00
|
|
|
setStreamingPhase: (phase: "streaming" | "awaitingFeedback" | "done") => void; // eslint-disable-line no-unused-vars
|
2025-07-29 17:37:13 -04:00
|
|
|
}) {
|
|
|
|
|
try {
|
2025-08-01 15:50:40 -04:00
|
|
|
// Set streaming phase back to streaming when feedback submission starts
|
|
|
|
|
setStreamingPhase("streaming");
|
2025-07-29 17:37:13 -04:00
|
|
|
|
2025-08-05 18:52:45 -04:00
|
|
|
// Create client for local mode
|
|
|
|
|
const client = new Client({
|
|
|
|
|
apiUrl: LANGGRAPH_URL,
|
|
|
|
|
defaultHeaders: {
|
|
|
|
|
[LOCAL_MODE_HEADER]: "true",
|
|
|
|
|
},
|
|
|
|
|
});
|
2025-07-29 17:37:13 -04:00
|
|
|
|
|
|
|
|
const formatted = formatDisplayLog(`Human feedback: ${plannerFeedback}`);
|
|
|
|
|
if (formatted.length > 0) {
|
|
|
|
|
setLogs((prev) => [...prev, ...formatted]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a new stream with the feedback
|
2025-08-22 16:58:27 -04:00
|
|
|
const stream = await client.runs.stream(
|
|
|
|
|
plannerThreadId,
|
|
|
|
|
OPEN_SWE_V2_GRAPH_ID,
|
|
|
|
|
{
|
|
|
|
|
command: {
|
|
|
|
|
resume: [
|
|
|
|
|
{
|
|
|
|
|
type: plannerFeedback === "approve" ? "accept" : "ignore",
|
|
|
|
|
args: null,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
streamMode: OPEN_SWE_STREAM_MODE as StreamMode[],
|
2025-07-29 17:37:13 -04:00
|
|
|
},
|
2025-08-22 16:58:27 -04:00
|
|
|
);
|
2025-07-29 17:37:13 -04:00
|
|
|
|
|
|
|
|
// Process the stream response
|
|
|
|
|
for await (const chunk of stream) {
|
|
|
|
|
const formatted = formatDisplayLog(chunk);
|
|
|
|
|
if (formatted.length > 0) {
|
|
|
|
|
setLogs((prev) => [...prev, ...formatted]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-01 15:50:40 -04:00
|
|
|
|
|
|
|
|
// Set streaming phase to done when complete
|
|
|
|
|
setStreamingPhase("done");
|
2025-07-29 17:37:13 -04:00
|
|
|
} catch (error: unknown) {
|
|
|
|
|
const errorMessage =
|
|
|
|
|
error instanceof Error ? error.message : "Unknown error";
|
|
|
|
|
setLogs((prev) => [...prev, `Error submitting feedback: ${errorMessage}`]);
|
2025-08-01 15:50:40 -04:00
|
|
|
// Set streaming phase to done even on error
|
|
|
|
|
setStreamingPhase("done");
|
2025-07-29 17:37:13 -04:00
|
|
|
} finally {
|
|
|
|
|
// Clear feedback state
|
|
|
|
|
setPlannerFeedback();
|
|
|
|
|
}
|
|
|
|
|
}
|