Add top_p/top_k/min_p/presence_penalty to AGENTS.md frontmatter and thread through inference (agents.ts parser → Agent type → stream-phase → sentinel summaries). Null means omit from request body, preserving provider defaults. Wire ask_user_input interactive card into both BooCoder frontends: the CoderPane in BooChat's SPA (CoderMessageList now renders AskUserInputCard instead of ToolCallLine for ask_user_input tool calls) and the standalone coder SPA (MessageBubble + new AskUserInputCard + shadcn ui primitives). Additional fixes: SessionLandingPage uses ChatInput with slash-command support and lazy chat creation; Session.tsx hydrate-race fix for empty pane promotion; AgentPicker wider dropdown with line-clamp; ModelPicker min-width; Textarea converted to forwardRef; Recon agent added to AGENTS.md; codecontext host port exposed in docker-compose. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
102 lines
3.2 KiB
TypeScript
102 lines
3.2 KiB
TypeScript
import type { Project, Session, Chat, Message, PendingChange, AskUserAnswer } from './types';
|
|
|
|
export class ApiError extends Error {
|
|
constructor(
|
|
public status: number,
|
|
public body: unknown,
|
|
) {
|
|
super(
|
|
typeof body === 'object' && body && 'error' in body
|
|
? String((body as { error: unknown }).error)
|
|
: `HTTP ${status}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
async function request<T>(path: string, init: RequestInit = {}): Promise<T> {
|
|
const res = await fetch(path, {
|
|
...init,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
...(init.headers ?? {}),
|
|
},
|
|
});
|
|
if (res.status === 204) return undefined as T;
|
|
const text = await res.text();
|
|
const data = text ? JSON.parse(text) : undefined;
|
|
if (!res.ok) throw new ApiError(res.status, data);
|
|
return data as T;
|
|
}
|
|
|
|
export const api = {
|
|
health: () => request<{ ok: boolean; db: boolean; tools: number }>('/api/health'),
|
|
|
|
projects: {
|
|
list: (params?: { status?: 'open' | 'archived' }) =>
|
|
request<Project[]>(`/api/projects${params?.status ? `?status=${params.status}` : ''}`),
|
|
},
|
|
|
|
sessions: {
|
|
listForProject: (projectId: string, status?: 'open' | 'archived') =>
|
|
request<Session[]>(
|
|
`/api/projects/${projectId}/sessions${status ? `?status=${status}` : ''}`,
|
|
),
|
|
get: (id: string) => request<Session>(`/api/sessions/${id}`),
|
|
},
|
|
|
|
chats: {
|
|
listForSession: (sessionId: string) =>
|
|
request<Chat[]>(`/api/sessions/${sessionId}/chats`),
|
|
create: (sessionId: string, body?: { name?: string }) =>
|
|
request<Chat>(`/api/sessions/${sessionId}/chats`, {
|
|
method: 'POST',
|
|
body: JSON.stringify(body ?? {}),
|
|
}),
|
|
answerUserInput: (chatId: string, toolCallId: string, answers: AskUserAnswer[]) =>
|
|
request<{ tool_message_id: string; assistant_message_id: string }>(
|
|
`/api/chats/${chatId}/answer_user_input`,
|
|
{
|
|
method: 'POST',
|
|
body: JSON.stringify({ tool_call_id: toolCallId, answers }),
|
|
},
|
|
),
|
|
},
|
|
|
|
messages: {
|
|
send: (sessionId: string, chatId: string, content: string) =>
|
|
request<{ user_message_id: string; assistant_message_id: string }>(
|
|
`/api/sessions/${sessionId}/messages`,
|
|
{
|
|
method: 'POST',
|
|
body: JSON.stringify({ content, chat_id: chatId }),
|
|
},
|
|
),
|
|
stop: (sessionId: string) =>
|
|
request<{ cancelled: boolean }>(`/api/sessions/${sessionId}/stop`, {
|
|
method: 'POST',
|
|
}),
|
|
},
|
|
|
|
pending: {
|
|
list: (sessionId: string) =>
|
|
request<PendingChange[]>(`/api/sessions/${sessionId}/pending`),
|
|
applyAll: (sessionId: string) =>
|
|
request<{ results: Array<{ id: string; success: boolean; error?: string }> }>(
|
|
`/api/sessions/${sessionId}/pending/apply`,
|
|
{ method: 'POST' },
|
|
),
|
|
applyOne: (changeId: string) =>
|
|
request<{ success: boolean; error?: string }>(`/api/pending/${changeId}/apply`, {
|
|
method: 'POST',
|
|
}),
|
|
rejectOne: (changeId: string) =>
|
|
request<{ ok: boolean }>(`/api/pending/${changeId}/reject`, {
|
|
method: 'POST',
|
|
}),
|
|
rewindOne: (changeId: string) =>
|
|
request<{ success: boolean; error?: string }>(`/api/pending/${changeId}/rewind`, {
|
|
method: 'POST',
|
|
}),
|
|
},
|
|
};
|