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,58 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { existsSync } from "fs";
|
||||
import { randomUUID } from "crypto";
|
||||
import { allowFileRoot } from "@/lib/file-access";
|
||||
import { invalidateSessionListCache } from "@/lib/session-reader";
|
||||
import { startRpcSession } from "@/lib/rpc-manager";
|
||||
// POST /api/agent/new body: { cwd: string; type: string; message?: string; ... }
|
||||
// Spawns a brand-new pi session. Most calls immediately send the first command;
|
||||
// type:"ensure_session" only creates the runtime so clients can query commands.
|
||||
// Returns { sessionId, data } where sessionId is pi's real session id.
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const body = await req.json() as { cwd?: string; [key: string]: unknown };
|
||||
const { cwd, ...command } = body;
|
||||
|
||||
if (!cwd || typeof cwd !== "string") {
|
||||
return NextResponse.json({ error: "cwd is required" }, { status: 400 });
|
||||
}
|
||||
if (!existsSync(cwd)) {
|
||||
return NextResponse.json({ error: `Directory does not exist: ${cwd}` }, { status: 400 });
|
||||
}
|
||||
|
||||
// Use a one-time key so startRpcSession's lock doesn't conflict with real session ids
|
||||
const { provider, modelId, toolNames, thinkingLevel, ...promptCommand } = command as { provider?: string; modelId?: string; toolNames?: string[]; thinkingLevel?: string; [key: string]: unknown };
|
||||
|
||||
// Must be unique per request: startRpcSession coalesces concurrent callers
|
||||
// that share a key onto one session. Date.now() (ms resolution) collides for
|
||||
// requests in the same millisecond, merging two new sessions into one.
|
||||
const tempKey = `__new__${randomUUID()}`;
|
||||
const { session, realSessionId } = await startRpcSession(tempKey, "", cwd, toolNames);
|
||||
|
||||
// Keep the files-route allowed-roots cache (see app/api/files/[...path]/route.ts)
|
||||
// in sync so the new cwd is immediately readable via /api/files. Without this,
|
||||
// a file request under a brand-new cwd would 403 for up to the cache TTL.
|
||||
allowFileRoot(cwd);
|
||||
invalidateSessionListCache();
|
||||
|
||||
// Apply pre-selected model before sending the prompt
|
||||
if (provider && modelId) {
|
||||
await session.send({ type: "set_model", provider, modelId });
|
||||
}
|
||||
|
||||
// Apply pre-selected thinking level before sending the prompt
|
||||
if (thinkingLevel) {
|
||||
await session.send({ type: "set_thinking_level", level: thinkingLevel });
|
||||
}
|
||||
|
||||
if (promptCommand.type === "ensure_session") {
|
||||
return NextResponse.json({ success: true, sessionId: realSessionId, data: null });
|
||||
}
|
||||
|
||||
const result = await session.send(promptCommand);
|
||||
|
||||
return NextResponse.json({ success: true, sessionId: realSessionId, data: result });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: String(error) }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user