feat: send live flow context to AI Assist for full editor awareness
The AI panel now sends the current tree structure (troubleshooting) or steps + intake form (procedural/maintenance) with each message. This gives the AI full visibility into node details, questions, descriptions, options, and intake form fields — not just the node ID. - Backend: add flow_context param to schema, endpoint, and service - Frontend: add getFlowContext callback to useEditorAI hook - TreeEditorPage: passes treeStructure as flow context - ProceduralEditorPage: passes steps + intakeForm as flow context Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ export interface SendMessageParams {
|
||||
content: string
|
||||
actionType?: AIActionType
|
||||
focalNodeId?: string | null
|
||||
flowContext?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
export const editorAIApi = {
|
||||
@@ -17,11 +18,12 @@ export const editorAIApi = {
|
||||
return data
|
||||
},
|
||||
|
||||
sendMessage: async ({ sessionId, content, actionType, focalNodeId }: SendMessageParams) => {
|
||||
sendMessage: async ({ sessionId, content, actionType, focalNodeId, flowContext }: SendMessageParams) => {
|
||||
const { data } = await apiClient.post(`/ai/chat/sessions/${sessionId}/messages`, {
|
||||
content,
|
||||
action_type: actionType || 'open_chat',
|
||||
focal_node_id: focalNodeId,
|
||||
flow_context: flowContext || undefined,
|
||||
})
|
||||
return data
|
||||
},
|
||||
|
||||
@@ -10,9 +10,11 @@ import type {
|
||||
interface UseEditorAIOptions {
|
||||
flowType: 'troubleshooting' | 'procedural'
|
||||
treeId?: string | null
|
||||
/** Returns the live flow structure from the editor for AI context */
|
||||
getFlowContext?: () => Record<string, unknown> | null
|
||||
}
|
||||
|
||||
export function useEditorAI({ flowType, treeId }: UseEditorAIOptions) {
|
||||
export function useEditorAI({ flowType, treeId, getFlowContext }: UseEditorAIOptions) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [focalNodeId, setFocalNodeId] = useState<string | null>(null)
|
||||
const [contextMenu, setContextMenu] = useState<{
|
||||
@@ -95,6 +97,7 @@ export function useEditorAI({ flowType, treeId }: UseEditorAIOptions) {
|
||||
content: currentInput,
|
||||
actionType: currentAction,
|
||||
focalNodeId: currentFocalNodeId,
|
||||
flowContext: getFlowContext?.() || null,
|
||||
})
|
||||
|
||||
setMessages((prev) => [
|
||||
@@ -118,7 +121,7 @@ export function useEditorAI({ flowType, treeId }: UseEditorAIOptions) {
|
||||
setIsLoading(false)
|
||||
pendingActionRef.current = 'open_chat'
|
||||
}
|
||||
}, [input, isLoading, ensureSession, focalNodeId])
|
||||
}, [input, isLoading, ensureSession, focalNodeId, getFlowContext])
|
||||
|
||||
const triggerAction = useCallback(
|
||||
(nodeId: string, actionType: AIActionType, prompt: string) => {
|
||||
|
||||
@@ -53,6 +53,12 @@ export function ProceduralEditorPage() {
|
||||
const editorAI = useEditorAI({
|
||||
flowType: 'procedural',
|
||||
treeId: id,
|
||||
getFlowContext: useCallback(() => {
|
||||
return {
|
||||
steps: steps as unknown as Record<string, unknown>[],
|
||||
intake_form: intakeForm,
|
||||
}
|
||||
}, [steps, intakeForm]),
|
||||
})
|
||||
|
||||
const isMaintenance = treeType === 'maintenance'
|
||||
|
||||
@@ -85,6 +85,10 @@ export function TreeEditorPage() {
|
||||
const editorAI = useEditorAI({
|
||||
flowType: 'troubleshooting',
|
||||
treeId: id,
|
||||
getFlowContext: useCallback(() => {
|
||||
if (!treeStructure) return null
|
||||
return treeStructure as unknown as Record<string, unknown>
|
||||
}, [treeStructure]),
|
||||
})
|
||||
|
||||
const previousEditingNodeRef = useRef<string | null>(null)
|
||||
|
||||
Reference in New Issue
Block a user