Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Local browser UI for the [pi coding agent](https://github.com/earendil-works/pi)

## Features

- **Session workspace**: browse, resume, rename, export, and delete conversations grouped by project, with running state, context usage, cost, and compaction details.
- **Session workspace**: browse, resume, rename, pin, manually order pinned conversations, export, and delete conversations grouped by project, with running state, context usage, cost, and compaction details.
- **Two ways to branch**: **New session** creates an independent session file from an earlier message; **Edit from here** creates a branch inside the current session.
- **Project file tools**: browse and upload files, inspect Git diffs, and preview source, Markdown, images, audio, PDFs, and DOCX files with automatic refresh.
- **Git worktrees**: switch checkouts from the sidebar while keeping sessions from the same repository grouped together.
Expand Down
10 changes: 7 additions & 3 deletions app/api/agent/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,16 @@ export async function POST(

return NextResponse.json({ success: true, data: result });
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
const promptBusy = commandType === "prompt"
&& !promptAccepted
&& getRpcSession(id)?.isRunning() === true;
return NextResponse.json({
error: error instanceof Error ? error.message : String(error),
error: message,
...(commandType === "prompt" && !promptAccepted
? { code: "prompt_rejected", accepted: false }
? { code: promptBusy ? "prompt_busy" : "prompt_rejected", accepted: false }
: {}),
}, { status: 500 });
}, { status: promptBusy ? 409 : 500 });
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/api/agent/new/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export async function POST(req: Request) {
// 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();
invalidateSessionListCache(session.sessionFile ? [session.sessionFile] : undefined);

const state = await session.send({ type: "get_state" }) as {
model?: { id: string; provider: string };
Expand Down
2 changes: 2 additions & 0 deletions app/api/agent/running/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextResponse } from "next/server";
import { getSessionListVersion } from "@/lib/session-reader";
import { refreshSessionIndexInBackground } from "@/lib/session-index";
import {
getCompletionNotificationSuppressedRpcSessionIds,
getRunningRpcSessionIds,
Expand All @@ -9,6 +10,7 @@ export const dynamic = "force-dynamic";

// GET /api/agent/running - Lightweight snapshot for visible-tab polling.
export async function GET() {
refreshSessionIndexInBackground();
return NextResponse.json(
{
sessionListVersion: getSessionListVersion(),
Expand Down
Loading