From 30d7d6e5a3bf29a5e7fceb4a4cc953713d93cd59 Mon Sep 17 00:00:00 2001 From: chihlasm Date: Tue, 24 Mar 2026 09:20:36 +0000 Subject: [PATCH] feat: add frontend API clients for branches, handoffs, and resolutions Adds branchesApi (getBranches, createFork, updateBranchStatus, switchBranch, reviveBranch, sendBranchMessage), handoffsApi (createHandoff, listHandoffs, claimHandoff, getQueue), and resolutionsApi (getOutputs, editOutput, pushOutput). All exported from api/index.ts. Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/api/branches.ts | 67 +++++++++++++++++++++++++++++++++ frontend/src/api/handoffs.ts | 39 +++++++++++++++++++ frontend/src/api/index.ts | 3 ++ frontend/src/api/resolutions.ts | 42 +++++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 frontend/src/api/branches.ts create mode 100644 frontend/src/api/handoffs.ts create mode 100644 frontend/src/api/resolutions.ts diff --git a/frontend/src/api/branches.ts b/frontend/src/api/branches.ts new file mode 100644 index 00000000..8ed391f3 --- /dev/null +++ b/frontend/src/api/branches.ts @@ -0,0 +1,67 @@ +import apiClient from './client' +import type { + BranchTreeResponse, + ForkCreateRequest, + ForkPointResponse, + BranchSwitchResponse, + ReviveRequest, + BranchMessageRequest, + BranchMessageResponse, +} from '@/types/branching' + +export const branchesApi = { + async getBranches(sessionId: string): Promise { + const response = await apiClient.get( + `/ai-sessions/${sessionId}/branches` + ) + return response.data + }, + + async createFork(sessionId: string, data: ForkCreateRequest): Promise { + const response = await apiClient.post( + `/ai-sessions/${sessionId}/branches/fork`, + data + ) + return response.data + }, + + async updateBranchStatus( + sessionId: string, + branchId: string, + status: string, + reason?: string + ): Promise { + await apiClient.patch( + `/ai-sessions/${sessionId}/branches/${branchId}/status`, + { status, reason } + ) + }, + + async switchBranch(sessionId: string, branchId: string): Promise { + const response = await apiClient.post( + `/ai-sessions/${sessionId}/branches/${branchId}/switch` + ) + return response.data + }, + + async reviveBranch(sessionId: string, branchId: string, data: ReviveRequest): Promise { + await apiClient.post( + `/ai-sessions/${sessionId}/branches/${branchId}/revive`, + data + ) + }, + + async sendBranchMessage( + sessionId: string, + branchId: string, + data: BranchMessageRequest + ): Promise { + const response = await apiClient.post( + `/ai-sessions/${sessionId}/branches/${branchId}/message`, + data + ) + return response.data + }, +} + +export default branchesApi diff --git a/frontend/src/api/handoffs.ts b/frontend/src/api/handoffs.ts new file mode 100644 index 00000000..d85ae992 --- /dev/null +++ b/frontend/src/api/handoffs.ts @@ -0,0 +1,39 @@ +import apiClient from './client' +import type { + HandoffCreateRequest, + HandoffResponse, + QueueItemResponse, +} from '@/types/branching' + +export const handoffsApi = { + async createHandoff(sessionId: string, data: HandoffCreateRequest): Promise { + const response = await apiClient.post( + `/ai-sessions/${sessionId}/handoff`, + data + ) + return response.data + }, + + async listHandoffs(sessionId: string): Promise { + const response = await apiClient.get( + `/ai-sessions/${sessionId}/handoffs` + ) + return response.data + }, + + async claimHandoff(handoffId: string): Promise { + const response = await apiClient.post( + `/handoffs/${handoffId}/claim` + ) + return response.data + }, + + async getQueue(params?: { intent?: 'park' | 'escalate'; limit?: number }): Promise { + const response = await apiClient.get('/handoffs/queue', { + params, + }) + return response.data + }, +} + +export default handoffsApi diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 904792dd..b362e193 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -32,3 +32,6 @@ export { publicTemplatesApi } from './publicTemplates' export { uploadsApi, default as uploadsApiDefault } from './uploads' export { scriptBuilderApi } from './scriptBuilder' export { betaFeedbackApi } from './betaFeedback' +export { branchesApi } from './branches' +export { handoffsApi } from './handoffs' +export { resolutionsApi } from './resolutions' diff --git a/frontend/src/api/resolutions.ts b/frontend/src/api/resolutions.ts new file mode 100644 index 00000000..6c5a9f15 --- /dev/null +++ b/frontend/src/api/resolutions.ts @@ -0,0 +1,42 @@ +import apiClient from './client' +import type { + AllResolutionOutputsResponse, + ResolutionOutputResponse, + ResolutionOutputEditRequest, + ResolutionOutputPushRequest, +} from '@/types/branching' + +export const resolutionsApi = { + async getOutputs(sessionId: string): Promise { + const response = await apiClient.get( + `/ai-sessions/${sessionId}/resolution-outputs` + ) + return response.data + }, + + async editOutput( + sessionId: string, + outputId: string, + data: ResolutionOutputEditRequest + ): Promise { + const response = await apiClient.patch( + `/ai-sessions/${sessionId}/resolution-outputs/${outputId}`, + data + ) + return response.data + }, + + async pushOutput( + sessionId: string, + outputId: string, + data: ResolutionOutputPushRequest + ): Promise { + const response = await apiClient.post( + `/ai-sessions/${sessionId}/resolution-outputs/${outputId}/push`, + data + ) + return response.data + }, +} + +export default resolutionsApi