feat(l1): frontend api/types for next-node, intake outcome, categories
Add IntakeOutcome/IntakeResult/NearMiss, TreeNode union, NextNodeRequest/Result, L1Categories types; add ai_build to SessionKind; retype intake() to IntakeResult and add nextNode/escalations/getCategories/setCategories methods. nextNode body carries node_text (backend advance_ai_build stores it). tsc -b clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
import { apiClient } from './client'
|
import { apiClient } from './client'
|
||||||
import type {
|
import type {
|
||||||
IntakeRequest,
|
IntakeRequest,
|
||||||
IntakeResponse,
|
IntakeResult,
|
||||||
|
L1Categories,
|
||||||
|
NextNodeRequest,
|
||||||
|
NextNodeResult,
|
||||||
QueueRow,
|
QueueRow,
|
||||||
WalkSession,
|
WalkSession,
|
||||||
AdhocNote,
|
AdhocNote,
|
||||||
@@ -9,7 +12,23 @@ import type {
|
|||||||
|
|
||||||
export const l1Api = {
|
export const l1Api = {
|
||||||
intake: (body: IntakeRequest) =>
|
intake: (body: IntakeRequest) =>
|
||||||
apiClient.post<IntakeResponse>('/l1/intake', body).then(r => r.data),
|
apiClient.post<IntakeResult>('/l1/intake', body).then(r => r.data),
|
||||||
|
|
||||||
|
nextNode: (sessionId: string, body: NextNodeRequest) =>
|
||||||
|
apiClient
|
||||||
|
.post<NextNodeResult>(`/l1/sessions/${sessionId}/next-node`, body)
|
||||||
|
.then(r => r.data),
|
||||||
|
|
||||||
|
escalations: () =>
|
||||||
|
apiClient.get<WalkSession[]>('/l1/escalations').then(r => r.data),
|
||||||
|
|
||||||
|
getCategories: () =>
|
||||||
|
apiClient.get<L1Categories>('/accounts/me/l1-categories').then(r => r.data),
|
||||||
|
|
||||||
|
setCategories: (enabled: string[]) =>
|
||||||
|
apiClient
|
||||||
|
.patch<L1Categories>('/accounts/me/l1-categories', { enabled })
|
||||||
|
.then(r => r.data),
|
||||||
|
|
||||||
queue: (statusFilter?: string) =>
|
queue: (statusFilter?: string) =>
|
||||||
apiClient.get<QueueRow[]>('/l1/queue', {
|
apiClient.get<QueueRow[]>('/l1/queue', {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export type SessionKind = 'flow' | 'proposal' | 'adhoc'
|
export type SessionKind = 'flow' | 'proposal' | 'adhoc' | 'ai_build'
|
||||||
export type SessionStatus = 'active' | 'resolved' | 'escalated' | 'abandoned'
|
export type SessionStatus = 'active' | 'resolved' | 'escalated' | 'abandoned'
|
||||||
export type TicketKind = 'psa' | 'internal'
|
export type TicketKind = 'psa' | 'internal'
|
||||||
|
|
||||||
@@ -42,11 +42,53 @@ export interface IntakeRequest {
|
|||||||
customer_name?: string
|
customer_name?: string
|
||||||
customer_contact?: string
|
customer_contact?: string
|
||||||
flow_id?: string
|
flow_id?: string
|
||||||
|
force_build?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IntakeResponse {
|
export type IntakeOutcome = 'matched' | 'suggest' | 'out_of_scope' | 'build'
|
||||||
session_id: string
|
|
||||||
session_kind: SessionKind
|
export interface NearMiss {
|
||||||
ticket_id: string
|
flow_id: string
|
||||||
ticket_kind: TicketKind
|
flow_name: string
|
||||||
|
score: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Phase 2A intake response — `outcome` drives the frontend dispatch.
|
||||||
|
* Session fields are present only for `matched` / `build`. */
|
||||||
|
export interface IntakeResult {
|
||||||
|
outcome: IntakeOutcome
|
||||||
|
session_id?: string
|
||||||
|
session_kind?: SessionKind
|
||||||
|
ticket_id?: string
|
||||||
|
ticket_kind?: TicketKind
|
||||||
|
flow_id?: string // for 'matched'
|
||||||
|
near_miss?: NearMiss // for 'suggest'
|
||||||
|
category?: string // for 'out_of_scope'
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A single node of an AI-built decision tree, returned by /next-node. */
|
||||||
|
export type TreeNode =
|
||||||
|
| { node_type: 'question'; id: string; text: string }
|
||||||
|
| { node_type: 'instruction'; id: string; text: string }
|
||||||
|
| { node_type: 'resolved'; id: string; text: string }
|
||||||
|
| { node_type: 'escalate'; id: string; reason_category?: string; text: string }
|
||||||
|
| { node_type: 'needs_review'; id: string; text: string }
|
||||||
|
|
||||||
|
export interface NextNodeRequest {
|
||||||
|
node_id?: string
|
||||||
|
node_text?: string // rendered text of the node being answered
|
||||||
|
answer?: 'yes' | 'no'
|
||||||
|
acknowledged?: boolean
|
||||||
|
note?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NextNodeResult {
|
||||||
|
node: TreeNode
|
||||||
|
session_status: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface L1Categories {
|
||||||
|
enabled: string[]
|
||||||
|
available: string[]
|
||||||
|
hard_floor: string[]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user