89332e1cbb
* fix(backend): start agent immediately for passthrough quick-chat sessions Passthrough profiles need a running PTY for the terminal to attach. When launchPrepare is called with a passthrough profile, upgrade the request to launchStart so the PTY exists by the time the frontend renders the terminal. * fix(web): render passthrough terminal in quick chat for passthrough profiles Quick chat used MessageList + ChatInputArea unconditionally, so passthrough profiles showed an empty chat with no agent output (PTY never attached). Render PassthroughTerminal when the active session is passthrough, mirroring the task-page branch. Passthrough is detected via session.is_passthrough or, before WS hydrates, via the agent profile's cli_passthrough flag — looked up through a new agentProfileId stored on quickChat session entries (set by the picker on selection and seeded by SSR for restored sessions). * style(web): apply prettier formatting * fix(web): address review feedback on quick-chat passthrough rendering - Narrow `metadata.agent_profile_id` to string at runtime via a `readAgentProfileId` helper instead of a blind type cast. - Collapse `useIsQuickChatPassthrough` into a single `useShallow` selector to avoid three separate store subscriptions. * fix(backend): prevent launchPrepare ↔ launchStart recursion for passthrough When passthrough quick-chat sessions hit a workflow step that blocks auto-start, launchStart's downgrade to launchPrepare would have re-upgraded back into launchStart and looped forever. Skip the passthrough upgrade when AutoStart=true, since that flag uniquely identifies the downgrade path. Adds tests for `isPassthroughProfile` and a regression test that runs the launchStart→launchPrepare path under a deadline so future recursions surface. * test(web): cover existing agentProfileId preservation on reopen * style(web): apply prettier formatting * test(backend): seed task with blocked workflow step in recursion regression Without persisted task and step, shouldBlockAutoStart short-circuited to false, the test bypassed the launchStart→launchPrepare downgrade entirely, and removing the recursion guard would still pass. Seed the task with a WorkflowStepID mapping to a step lacking auto_start_agent so the guard is the only thing preventing the bounce. Verified by temporarily removing the guard — the test now times out as expected. * test(backend): cover ResolveAgentProfile error path in isPassthroughProfile
117 lines
3.2 KiB
TypeScript
117 lines
3.2 KiB
TypeScript
import { fetchJson, type ApiRequestOptions } from "../client";
|
|
import type {
|
|
ListWorkspacesResponse,
|
|
ListRepositoriesResponse,
|
|
RepositoryBranchesResponse,
|
|
ListRepositoryScriptsResponse,
|
|
Workspace,
|
|
} from "@/lib/types/http";
|
|
|
|
// Workspace operations
|
|
export async function createWorkspace(
|
|
payload: { name: string; description?: string },
|
|
options?: ApiRequestOptions,
|
|
) {
|
|
return fetchJson<Workspace>("/api/v1/workspaces", {
|
|
...options,
|
|
init: { method: "POST", body: JSON.stringify(payload), ...(options?.init ?? {}) },
|
|
});
|
|
}
|
|
|
|
export async function listWorkspaces(options?: ApiRequestOptions) {
|
|
return fetchJson<ListWorkspacesResponse>("/api/v1/workspaces", options);
|
|
}
|
|
|
|
// Repository operations
|
|
export async function listRepositories(
|
|
workspaceId: string,
|
|
params?: { includeScripts?: boolean },
|
|
options?: ApiRequestOptions,
|
|
) {
|
|
const searchParams = new URLSearchParams();
|
|
if (params?.includeScripts) {
|
|
searchParams.set("include_scripts", "true");
|
|
}
|
|
const queryString = searchParams.toString();
|
|
const url = `/api/v1/workspaces/${workspaceId}/repositories${queryString ? `?${queryString}` : ""}`;
|
|
return fetchJson<ListRepositoriesResponse>(url, options);
|
|
}
|
|
|
|
export async function listRepositoryBranches(repositoryId: string, options?: ApiRequestOptions) {
|
|
return fetchJson<RepositoryBranchesResponse>(
|
|
`/api/v1/repositories/${repositoryId}/branches`,
|
|
options,
|
|
);
|
|
}
|
|
|
|
export async function listRepositoryScripts(repositoryId: string, options?: ApiRequestOptions) {
|
|
return fetchJson<ListRepositoryScriptsResponse>(
|
|
`/api/v1/repositories/${repositoryId}/scripts`,
|
|
options,
|
|
);
|
|
}
|
|
|
|
// Quick Chat operations
|
|
export type StartQuickChatRequest = {
|
|
title?: string;
|
|
repository_id?: string;
|
|
agent_profile_id?: string;
|
|
executor_id?: string;
|
|
prompt?: string;
|
|
local_path?: string;
|
|
repository_name?: string;
|
|
default_branch?: string;
|
|
base_branch?: string;
|
|
};
|
|
|
|
export type StartQuickChatResponse = {
|
|
task_id: string;
|
|
session_id: string;
|
|
};
|
|
|
|
export async function startQuickChat(
|
|
workspaceId: string,
|
|
payload: StartQuickChatRequest,
|
|
options?: ApiRequestOptions,
|
|
) {
|
|
return fetchJson<StartQuickChatResponse>(`/api/v1/workspaces/${workspaceId}/quick-chat`, {
|
|
...options,
|
|
init: { method: "POST", body: JSON.stringify(payload), ...(options?.init ?? {}) },
|
|
});
|
|
}
|
|
|
|
export async function listQuickChatSessions(workspaceId: string, options?: ApiRequestOptions) {
|
|
return fetchJson<{
|
|
tasks: Array<{
|
|
id: string;
|
|
title: string;
|
|
workspace_id: string;
|
|
primary_session_id?: string | null;
|
|
metadata?: Record<string, unknown> | null;
|
|
}>;
|
|
}>(`/api/v1/workspaces/${workspaceId}/tasks?only_ephemeral=true&exclude_config=true`, options);
|
|
}
|
|
|
|
// Config Chat operations
|
|
export type StartConfigChatRequest = {
|
|
agent_profile_id?: string;
|
|
executor_id?: string;
|
|
prompt?: string;
|
|
};
|
|
|
|
export type StartConfigChatResponse = {
|
|
task_id: string;
|
|
session_id: string;
|
|
};
|
|
|
|
export async function startConfigChat(
|
|
workspaceId: string,
|
|
payload: StartConfigChatRequest,
|
|
options?: ApiRequestOptions,
|
|
) {
|
|
return fetchJson<StartConfigChatResponse>(`/api/v1/workspaces/${workspaceId}/config-chat`, {
|
|
...options,
|
|
init: { method: "POST", body: JSON.stringify(payload), ...(options?.init ?? {}) },
|
|
});
|
|
}
|