Adds the "Who's using Ask?" picker (GET /api/ask/users), actor
resolution via x-ask-user (src/lib/agent/context.ts), and thread
persistence (src/lib/chat/threads.ts, /api/chat/threads routes).
/api/chat now accepts { threadId?, message, display?, images? } and
persists each turn as its own append-only ask_messages row; the old
{ history } body still works for one release. chat-view.tsx gained the
picker, a thread sidebar (new/select/rename/archive), and ?thread=<id>
in the URL.
Live browser check skipped: ask_threads/ask_messages/ask_log don't
exist yet in the target PocketBase (Task 1's schema is dry-run only,
pending the user's --apply). Covered by mocked unit tests instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
/**
|
|
* GET /api/chat/threads — the actor's threads, newest first.
|
|
* POST /api/chat/threads — creates an empty thread owned by the actor.
|
|
*/
|
|
import { pbAdmin } from "@/lib/pb";
|
|
import { resolveActor } from "@/lib/agent/context";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export async function GET(request: Request) {
|
|
const actor = await resolveActor(request);
|
|
if (actor instanceof Response) return actor;
|
|
|
|
const pb = await pbAdmin();
|
|
const rows = await pb.collection("ask_threads").getFullList({
|
|
filter: pb.filter("owner = {:owner}", { owner: actor.id }),
|
|
sort: "-last_message_at,-created",
|
|
});
|
|
|
|
return Response.json({ threads: rows });
|
|
}
|
|
|
|
export async function POST(request: Request) {
|
|
const actor = await resolveActor(request);
|
|
if (actor instanceof Response) return actor;
|
|
|
|
let body: Record<string, unknown> = {};
|
|
try {
|
|
body = await request.json();
|
|
} catch {
|
|
// An empty body is fine — "New thread" sends none.
|
|
}
|
|
const title = typeof body.title === "string" && body.title.trim() ? body.title.trim() : "New thread";
|
|
|
|
const pb = await pbAdmin();
|
|
const created = await pb.collection("ask_threads").create({
|
|
title,
|
|
owner: actor.id,
|
|
archived: false,
|
|
});
|
|
|
|
return Response.json({ id: created.id, title: created.title });
|
|
}
|