import { hostApiFetch } from './host-api'; import type { CodingConversationMetadata, CodingProjectConfigSnapshot, CodingProjectSummary, } from '@/types/coding-project'; import type { ProjectType } from '../../shared/project-config'; import type { ProjectIdentityChoice } from '../../shared/coding-project-contracts'; const CANONICAL_PROJECT_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u; export function isCanonicalCodingProjectId(value: string): boolean { return CANONICAL_PROJECT_ID_PATTERN.test(value.trim()); } export interface CodingProjectCatalog { projects: CodingProjectSummary[]; activeProjectId: string | null; } export async function listCodingProjects(): Promise { return await hostApiFetch('/api/coding/projects'); } export async function openCodingProject(projectPath: string): Promise { const response = await hostApiFetch<{ project: CodingProjectSummary }>('/api/coding/projects/open', { method: 'POST', body: JSON.stringify({ projectPath }), }); return response.project; } export async function createCodingProject(input: { projectPath?: string; parentPath?: string; projectName?: string; projectType?: ProjectType; identity: ProjectIdentityChoice; }): Promise { const response = await hostApiFetch<{ snapshot: CodingProjectConfigSnapshot }>('/api/coding/projects/create', { method: 'POST', body: JSON.stringify(input), }); return response.snapshot; } export async function resolveCodingProjectIdentity( localProjectId: string, identity: ProjectIdentityChoice, ): Promise { const response = await hostApiFetch<{ snapshot: CodingProjectConfigSnapshot }>( '/api/coding/projects/identity', { method: 'POST', body: JSON.stringify({ localProjectId, identity }), }, ); return response.snapshot; } export async function makeCodingProjectIndependentCopy( localProjectId: string, ): Promise { const response = await hostApiFetch<{ snapshot: CodingProjectConfigSnapshot }>( '/api/coding/projects/identity/independent-copy', { method: 'POST', body: JSON.stringify({ localProjectId, confirmed: true }), }, ); return response.snapshot; } export async function setActiveCodingProject(projectId: string): Promise { const response = await hostApiFetch<{ project: CodingProjectSummary }>('/api/coding/projects/active', { method: 'POST', body: JSON.stringify({ projectId }), }); return response.project; } export async function removeCodingProject(projectId: string): Promise { await hostApiFetch('/api/coding/projects/remove', { method: 'POST', body: JSON.stringify({ projectId }), }); } export async function getCodingProjectConfig( projectId: string, ): Promise { const response = await hostApiFetch<{ snapshot: CodingProjectConfigSnapshot }>( `/api/coding/projects/config?projectId=${encodeURIComponent(projectId)}`, ); return response.snapshot; } export async function listCodingProjectConversations( projectId: string, ): Promise { const response = await hostApiFetch<{ conversations: CodingConversationMetadata[] }>( `/api/coding/projects/conversations?projectId=${encodeURIComponent(projectId)}`, ); return response.conversations; } export async function createCodingProjectConversation(input: { projectId: string; agentId: string; title: string; }): Promise { const response = await hostApiFetch<{ conversation: CodingConversationMetadata }>( '/api/coding/projects/conversations', { method: 'POST', body: JSON.stringify(input), }, ); return response.conversation; } export async function patchCodingProjectConversation( conversationId: string, patch: { title?: string; archived?: boolean; unread?: boolean }, ): Promise { const response = await hostApiFetch<{ conversation: CodingConversationMetadata }>( `/api/coding/conversations/${encodeURIComponent(conversationId)}`, { method: 'PATCH', body: JSON.stringify(patch) }, ); return response.conversation; } export async function deleteCodingProjectConversation(conversationId: string): Promise { await hostApiFetch( `/api/coding/conversations/${encodeURIComponent(conversationId)}`, { method: 'DELETE' }, ); }