mirror of
https://github.com/luckyyzh/pi-agent-integrated.git
synced 2026-10-03 02:59:35 +00:00
feat: integrate Pi backend and Pi Web
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import { resolveSessionPath } from "@/lib/session-reader";
|
||||
import { getRpcSession, startRpcSession } from "@/lib/rpc-manager";
|
||||
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
// GET /api/agent/[id]/events - SSE stream of agent events
|
||||
export async function GET(
|
||||
req: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
|
||||
// Fast path: already-running session
|
||||
let session = getRpcSession(id);
|
||||
if (!session || !session.isAlive()) {
|
||||
const filePath = await resolveSessionPath(id);
|
||||
if (!filePath) {
|
||||
return new Response("Session not found", { status: 404 });
|
||||
}
|
||||
const cwd = SessionManager.open(filePath).getHeader()?.cwd ?? process.cwd();
|
||||
try {
|
||||
({ session } = await startRpcSession(id, filePath, cwd));
|
||||
} catch (error) {
|
||||
return new Response(`Failed to start agent: ${error}`, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
const encode = (data: unknown) => {
|
||||
const text = `data: ${JSON.stringify(data)}\n\n`;
|
||||
controller.enqueue(new TextEncoder().encode(text));
|
||||
};
|
||||
|
||||
// Send initial connected event
|
||||
encode({ type: "connected", sessionId: id });
|
||||
|
||||
const unsubscribe = session.onEvent((event) => {
|
||||
encode(event);
|
||||
});
|
||||
|
||||
// Heartbeat every 30s to prevent server/proxy timeout (Next.js default ~120-150s)
|
||||
const heartbeat = setInterval(() => {
|
||||
try {
|
||||
controller.enqueue(new TextEncoder().encode(":\n\n"));
|
||||
} catch {
|
||||
// controller already closed
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
// Cleanup when client disconnects
|
||||
const cleanup = () => {
|
||||
clearInterval(heartbeat);
|
||||
unsubscribe();
|
||||
controller.close();
|
||||
};
|
||||
|
||||
// Detect client disconnect via abort signal
|
||||
req.signal?.addEventListener("abort", cleanup);
|
||||
},
|
||||
});
|
||||
|
||||
return new Response(stream, {
|
||||
headers: {
|
||||
"Content-Type": "text/event-stream",
|
||||
"Cache-Control": "no-cache",
|
||||
Connection: "keep-alive",
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user