feat: preserve stereo channels and require reviewed speaker roles

This commit is contained in:
2026-10-08 16:15:41 +08:00
parent 13948f5982
commit a20d3565af
28 changed files with 1134 additions and 113 deletions
+13 -2
View File
@@ -11,6 +11,15 @@ export interface FollowupField {
readonly?: boolean
}
export type FollowupFields = Record<FollowupKind, FollowupField[]>
export type FollowupAudioChannel = 0 | 1
export type FollowupChannelRoles = 'unconfirmed' | 'left_service' | 'right_service'
export interface FollowupTranscriptSegment {
id: string
start_ms: number
end_ms: number
text: string
channel?: FollowupAudioChannel
}
export interface FollowupCapabilities {
enabled: boolean
audio_verified: boolean
@@ -31,7 +40,7 @@ export interface FollowupReviewItem {
time_estimated: boolean
time_text: string
date_text: string
evidence: Array<{ text: string; start_ms?: number; end_ms?: number; segment_id?: string; position_type?: 'segment' }>
evidence: Array<{ text: string; start_ms?: number; end_ms?: number; segment_id?: string; position_type?: 'segment'; channel?: FollowupAudioChannel }>
needs_review: boolean
selected: boolean
target_id: number | null
@@ -68,6 +77,8 @@ export interface FollowupTaskSummary {
export interface FollowupTaskDetail extends FollowupTaskSummary {
summary: string
transcript: string
transcript_segments?: FollowupTranscriptSegment[]
channel_roles?: FollowupChannelRoles
uncertainties: unknown[]
items: FollowupReviewItem[]
fields?: FollowupFields
@@ -110,7 +121,7 @@ export async function followupAudioUploadChunk(uploadId: string, index: number,
}
export const followupAudioUploadComplete = (uploadId: string, signal?: AbortSignal) => post<{ upload_id: string; duration_seconds: number; sha256: string }>('uploadComplete', { upload_id: uploadId }, signal)
export const followupAudioCreate = (data: { diagnosis_id: number; upload_id: string; recorded_at: string; model_key: string }, signal?: AbortSignal) => post<{ task_id: number; status: string; reused?: boolean; reuse_message?: string }>('create', data, signal)
export const followupAudioSaveDraft = (data: { id: number; version: number; items: FollowupReviewItem[] }, signal?: AbortSignal) => post<FollowupTaskDetail>('saveDraft', data, signal)
export const followupAudioSaveDraft = (data: { id: number; version: number; items: FollowupReviewItem[]; channel_roles?: FollowupChannelRoles }, signal?: AbortSignal) => post<FollowupTaskDetail>('saveDraft', data, signal)
export const followupAudioApply = (data: { id: number; version: number; items: FollowupReviewItem[] }, signal?: AbortSignal) => post<{ id: number; status: 'applied'; applied_items: unknown[] }>('apply', data, signal)
export const followupAudioRetry = (id: number, signal?: AbortSignal) => post<{ id: number; status: string }>('retry', { id }, signal)
/** The existing request interceptor puts the token in a header, never in the audio URL. */