{"version":3,"sources":["../src/components/ai-provider/ai-messages.tsx"],"sourcesContent":["/**\n * An internal context to separate the messages state (which is constantly changing) from the rest of VN SDK context\n */\n\nimport {\n  ReactNode,\n  useEffect,\n  useState,\n  useRef,\n  useCallback,\n  useMemo,\n  createContext,\n  useContext,\n} from \"react\";\nimport { AiMessagesContext } from \"../../context/ai-messages-context\";\nimport {\n  loadMessagesFromJsonRepresentation,\n  Message,\n  GraphQLError,\n} from \"@vn-sdk/runtime-client-gql\";\nimport { useAiContext } from \"../../context/ai-context\";\nimport { useToast } from \"../toast/toast-provider\";\nimport { shouldShowDevConsole } from \"../../utils/dev-console\";\nimport {\n  ErrorVisibility,\n  AiSDKApiDiscoveryError,\n  AiSDKRemoteEndpointDiscoveryError,\n  AiSDKAgentDiscoveryError,\n  AiSDKError,\n  AiSDKErrorCode,\n} from \"@vn-sdk/shared\";\nimport { SuggestionItem } from \"../../utils/suggestions\";\n\n// Helper to determine if error should show as banner based on visibility and legacy patterns\nfunction shouldShowAsBanner(gqlError: GraphQLError): boolean {\n  const extensions = gqlError.extensions;\n  if (!extensions) return false;\n\n  // Priority 1: Check error code for discovery errors (these should always be banners)\n  const code = extensions.code as AiSDKErrorCode;\n  if (\n    code === AiSDKErrorCode.AGENT_NOT_FOUND ||\n    code === AiSDKErrorCode.API_NOT_FOUND ||\n    code === AiSDKErrorCode.REMOTE_ENDPOINT_NOT_FOUND ||\n    code === AiSDKErrorCode.CONFIGURATION_ERROR ||\n    code === AiSDKErrorCode.MISSING_PUBLIC_API_KEY_ERROR ||\n    code === AiSDKErrorCode.UPGRADE_REQUIRED_ERROR\n  ) {\n    return true;\n  }\n\n  // Priority 2: Check banner visibility\n  if (extensions.visibility === ErrorVisibility.BANNER) {\n    return true;\n  }\n\n  // Priority 3: Check for critical errors that should be banners regardless of formal classification\n  const errorMessage = gqlError.message.toLowerCase();\n  if (\n    errorMessage.includes(\"api key\") ||\n    errorMessage.includes(\"401\") ||\n    errorMessage.includes(\"unauthorized\") ||\n    errorMessage.includes(\"authentication\") ||\n    errorMessage.includes(\"incorrect api key\")\n  ) {\n    return true;\n  }\n\n  // Priority 4: Legacy stack trace detection for discovery errors\n  const originalError = extensions.originalError as any;\n  if (originalError?.stack) {\n    return (\n      originalError.stack.includes(\"AiApiDiscoveryError\") ||\n      originalError.stack.includes(\"AiSDKRemoteEndpointDiscoveryError\") ||\n      originalError.stack.includes(\"AiSDKAgentDiscoveryError\")\n    );\n  }\n\n  return false;\n}\n\n/**\n * MessagesTap is used to mitigate performance issues when we only need\n * a snapshot of the messages, not a continuously updating stream of messages.\n */\n\nexport type MessagesTap = {\n  getMessagesFromTap: () => Message[];\n  updateTapMessages: (messages: Message[]) => void;\n};\n\nconst MessagesTapContext = createContext<MessagesTap | null>(null);\n\nexport function useMessagesTap() {\n  const tap = useContext(MessagesTapContext);\n  if (!tap) throw new Error(\"useMessagesTap must be used inside <MessagesTapProvider>\");\n  return tap;\n}\n\nexport function MessagesTapProvider({ children }: { children: React.ReactNode }) {\n  const messagesRef = useRef<Message[]>([]);\n\n  const tapRef = useRef<MessagesTap>({\n    getMessagesFromTap: () => messagesRef.current,\n    updateTapMessages: (messages: Message[]) => {\n      messagesRef.current = messages;\n    },\n  });\n\n  return (\n    <MessagesTapContext.Provider value={tapRef.current}>{children}</MessagesTapContext.Provider>\n  );\n}\n\n/**\n * VN SDK messages context.\n */\n\nexport function AiMessages({ children }: { children: ReactNode }) {\n  const [messages, setMessages] = useState<Message[]>([]);\n  const lastLoadedThreadId = useRef<string>();\n  const lastLoadedAgentName = useRef<string>();\n  const lastLoadedMessages = useRef<string>();\n\n  const { updateTapMessages } = useMessagesTap();\n\n  const { threadId, agentSession, runtimeClient, showDevConsole, onError, aiApiConfig } =\n    useAiContext();\n  const { setBannerError } = useToast();\n\n  // Helper function to trace UI errors (similar to useAiRuntimeClient)\n  const traceUIError = useCallback(\n    async (error: AiSDKError, originalError?: any) => {\n      // Just check if onError and publicApiKey are defined\n      if (!onError || !aiApiConfig.publicApiKey) return;\n\n      try {\n        const traceEvent = {\n          type: \"error\" as const,\n          timestamp: Date.now(),\n          context: {\n            source: \"ui\" as const,\n            request: {\n              operation: \"loadAgentState\",\n              url: aiApiConfig.chatApiEndpoint,\n              startTime: Date.now(),\n            },\n            technical: {\n              environment: \"browser\",\n              userAgent: typeof navigator !== \"undefined\" ? navigator.userAgent : undefined,\n              stackTrace: originalError instanceof Error ? originalError.stack : undefined,\n            },\n          },\n          error,\n        };\n        await onError(traceEvent);\n      } catch (traceError) {\n        console.error(\"Error in AiMessages onError handler:\", traceError);\n      }\n    },\n    [onError, aiApiConfig.publicApiKey, aiApiConfig.chatApiEndpoint],\n  );\n\n  const createStructuredError = (gqlError: GraphQLError): AiSDKError | null => {\n    const extensions = gqlError.extensions;\n    const originalError = extensions?.originalError as any;\n\n    // Priority: Check stack trace for discovery errors first\n    if (originalError?.stack) {\n      if (originalError.stack.includes(\"AiApiDiscoveryError\")) {\n        return new AiSDKApiDiscoveryError({ message: originalError.message });\n      }\n      if (originalError.stack.includes(\"AiSDKRemoteEndpointDiscoveryError\")) {\n        return new AiSDKRemoteEndpointDiscoveryError({ message: originalError.message });\n      }\n      if (originalError.stack.includes(\"AiSDKAgentDiscoveryError\")) {\n        return new AiSDKAgentDiscoveryError({\n          agentName: \"\",\n          availableAgents: [],\n        });\n      }\n    }\n\n    // Fallback: Use the formal error code if available\n    const message = originalError?.message || gqlError.message;\n    const code = extensions?.code as AiSDKErrorCode;\n\n    if (code) {\n      return new AiSDKError({ message, code });\n    }\n\n    return null;\n  };\n\n  const handleGraphQLErrors = useCallback(\n    (error: any) => {\n      if (error.graphQLErrors?.length) {\n        const graphQLErrors = error.graphQLErrors as GraphQLError[];\n\n        // Route all errors to banners for consistent UI\n        const routeError = (gqlError: GraphQLError) => {\n          const extensions = gqlError.extensions;\n          const visibility = extensions?.visibility as ErrorVisibility;\n          const isDev = shouldShowDevConsole(showDevConsole);\n\n          if (!isDev) {\n            console.error(\"VN SDK Error (hidden in production):\", gqlError.message);\n            return;\n          }\n\n          // Silent errors - just log\n          if (visibility === ErrorVisibility.SILENT) {\n            console.error(\"VN SDK Silent Error:\", gqlError.message);\n            return;\n          }\n\n          // All other errors (including DEV_ONLY) show as banners for consistency\n          const ckError = createStructuredError(gqlError);\n          if (ckError) {\n            setBannerError(ckError);\n            // Trace the structured error\n            traceUIError(ckError, gqlError);\n          } else {\n            // Fallback: create a generic error for unstructured GraphQL errors\n            const fallbackError = new AiSDKError({\n              message: gqlError.message,\n              code: AiSDKErrorCode.UNKNOWN,\n            });\n            setBannerError(fallbackError);\n            // Trace the fallback error\n            traceUIError(fallbackError, gqlError);\n          }\n        };\n\n        // Process all errors as banners\n        graphQLErrors.forEach(routeError);\n      } else {\n        const isDev = shouldShowDevConsole(showDevConsole);\n        if (!isDev) {\n          console.error(\"VN SDK Error (hidden in production):\", error);\n        } else {\n          // Route non-GraphQL errors to banner as well\n          const fallbackError = new AiSDKError({\n            message: error?.message || String(error),\n            code: AiSDKErrorCode.UNKNOWN,\n          });\n          setBannerError(fallbackError);\n          // Trace the non-GraphQL error\n          traceUIError(fallbackError, error);\n        }\n      }\n    },\n    [setBannerError, showDevConsole, traceUIError],\n  );\n\n  useEffect(() => {\n    if (!threadId || threadId === lastLoadedThreadId.current) return;\n    if (\n      threadId === lastLoadedThreadId.current &&\n      agentSession?.agentName === lastLoadedAgentName.current\n    ) {\n      return;\n    }\n\n    const fetchMessages = async () => {\n      if (!agentSession?.agentName) return;\n\n      const result = await runtimeClient.loadAgentState({\n        threadId,\n        agentName: agentSession?.agentName,\n      });\n\n      // Check for GraphQL errors and manually trigger error handling\n      if (result.error) {\n        // Update refs to prevent infinite retries of the same failed request\n        lastLoadedThreadId.current = threadId;\n        lastLoadedAgentName.current = agentSession?.agentName;\n        handleGraphQLErrors(result.error);\n        return; // Don't try to process the data if there's an error\n      }\n\n      const newMessages = result.data?.loadAgentState?.messages;\n      if (newMessages === lastLoadedMessages.current) return;\n\n      if (result.data?.loadAgentState) {\n        lastLoadedMessages.current = newMessages;\n        lastLoadedThreadId.current = threadId;\n        lastLoadedAgentName.current = agentSession?.agentName;\n\n        const messages = loadMessagesFromJsonRepresentation(JSON.parse(newMessages || \"[]\"));\n        setMessages(messages);\n      }\n    };\n    void fetchMessages();\n  }, [threadId, agentSession?.agentName]);\n\n  useEffect(() => {\n    updateTapMessages(messages);\n  }, [messages, updateTapMessages]);\n\n  const memoizedChildren = useMemo(() => children, [children]);\n  const [suggestions, setSuggestions] = useState<SuggestionItem[]>([]);\n\n  return (\n    <AiMessagesContext.Provider\n      value={{\n        messages,\n        setMessages,\n        suggestions,\n        setSuggestions,\n      }}\n    >\n      {memoizedChildren}\n    </AiMessagesContext.Provider>\n  );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAIA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,OAGK;AAIP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAgFH;AAnBJ,IAAM,qBAAqB,cAAkC,IAAI;AAE1D,SAAS,iBAAiB;AAC/B,QAAM,MAAM,WAAW,kBAAkB;AACzC,MAAI,CAAC;AAAK,UAAM,IAAI,MAAM,0DAA0D;AACpF,SAAO;AACT;AAEO,SAAS,oBAAoB,EAAE,SAAS,GAAkC;AAC/E,QAAM,cAAc,OAAkB,CAAC,CAAC;AAExC,QAAM,SAAS,OAAoB;AAAA,IACjC,oBAAoB,MAAM,YAAY;AAAA,IACtC,mBAAmB,CAAC,aAAwB;AAC1C,kBAAY,UAAU;AAAA,IACxB;AAAA,EACF,CAAC;AAED,SACE,oBAAC,mBAAmB,UAAnB,EAA4B,OAAO,OAAO,SAAU,UAAS;AAElE;AAMO,SAAS,WAAW,EAAE,SAAS,GAA4B;AAChE,QAAM,CAAC,UAAU,WAAW,IAAI,SAAoB,CAAC,CAAC;AACtD,QAAM,qBAAqB,OAAe;AAC1C,QAAM,sBAAsB,OAAe;AAC3C,QAAM,qBAAqB,OAAe;AAE1C,QAAM,EAAE,kBAAkB,IAAI,eAAe;AAE7C,QAAM,EAAE,UAAU,cAAc,eAAe,gBAAgB,SAAS,YAAY,IAClF,aAAa;AACf,QAAM,EAAE,eAAe,IAAI,SAAS;AAGpC,QAAM,eAAe;AAAA,IACnB,CAAO,OAAmB,kBAAwB;AAEhD,UAAI,CAAC,WAAW,CAAC,YAAY;AAAc;AAE3C,UAAI;AACF,cAAM,aAAa;AAAA,UACjB,MAAM;AAAA,UACN,WAAW,KAAK,IAAI;AAAA,UACpB,SAAS;AAAA,YACP,QAAQ;AAAA,YACR,SAAS;AAAA,cACP,WAAW;AAAA,cACX,KAAK,YAAY;AAAA,cACjB,WAAW,KAAK,IAAI;AAAA,YACtB;AAAA,YACA,WAAW;AAAA,cACT,aAAa;AAAA,cACb,WAAW,OAAO,cAAc,cAAc,UAAU,YAAY;AAAA,cACpE,YAAY,yBAAyB,QAAQ,cAAc,QAAQ;AAAA,YACrE;AAAA,UACF;AAAA,UACA;AAAA,QACF;AACA,cAAM,QAAQ,UAAU;AAAA,MAC1B,SAAS,YAAP;AACA,gBAAQ,MAAM,wCAAwC,UAAU;AAAA,MAClE;AAAA,IACF;AAAA,IACA,CAAC,SAAS,YAAY,cAAc,YAAY,eAAe;AAAA,EACjE;AAEA,QAAM,wBAAwB,CAAC,aAA8C;AAC3E,UAAM,aAAa,SAAS;AAC5B,UAAM,gBAAgB,yCAAY;AAGlC,QAAI,+CAAe,OAAO;AACxB,UAAI,cAAc,MAAM,SAAS,qBAAqB,GAAG;AACvD,eAAO,IAAI,uBAAuB,EAAE,SAAS,cAAc,QAAQ,CAAC;AAAA,MACtE;AACA,UAAI,cAAc,MAAM,SAAS,mCAAmC,GAAG;AACrE,eAAO,IAAI,kCAAkC,EAAE,SAAS,cAAc,QAAQ,CAAC;AAAA,MACjF;AACA,UAAI,cAAc,MAAM,SAAS,0BAA0B,GAAG;AAC5D,eAAO,IAAI,yBAAyB;AAAA,UAClC,WAAW;AAAA,UACX,iBAAiB,CAAC;AAAA,QACpB,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,WAAU,+CAAe,YAAW,SAAS;AACnD,UAAM,OAAO,yCAAY;AAEzB,QAAI,MAAM;AACR,aAAO,IAAI,WAAW,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,sBAAsB;AAAA,IAC1B,CAAC,UAAe;AAnMpB;AAoMM,WAAI,WAAM,kBAAN,mBAAqB,QAAQ;AAC/B,cAAM,gBAAgB,MAAM;AAG5B,cAAM,aAAa,CAAC,aAA2B;AAC7C,gBAAM,aAAa,SAAS;AAC5B,gBAAM,aAAa,yCAAY;AAC/B,gBAAM,QAAQ,qBAAqB,cAAc;AAEjD,cAAI,CAAC,OAAO;AACV,oBAAQ,MAAM,wCAAwC,SAAS,OAAO;AACtE;AAAA,UACF;AAGA,cAAI,eAAe,gBAAgB,QAAQ;AACzC,oBAAQ,MAAM,wBAAwB,SAAS,OAAO;AACtD;AAAA,UACF;AAGA,gBAAM,UAAU,sBAAsB,QAAQ;AAC9C,cAAI,SAAS;AACX,2BAAe,OAAO;AAEtB,yBAAa,SAAS,QAAQ;AAAA,UAChC,OAAO;AAEL,kBAAM,gBAAgB,IAAI,WAAW;AAAA,cACnC,SAAS,SAAS;AAAA,cAClB,MAAM,eAAe;AAAA,YACvB,CAAC;AACD,2BAAe,aAAa;AAE5B,yBAAa,eAAe,QAAQ;AAAA,UACtC;AAAA,QACF;AAGA,sBAAc,QAAQ,UAAU;AAAA,MAClC,OAAO;AACL,cAAM,QAAQ,qBAAqB,cAAc;AACjD,YAAI,CAAC,OAAO;AACV,kBAAQ,MAAM,wCAAwC,KAAK;AAAA,QAC7D,OAAO;AAEL,gBAAM,gBAAgB,IAAI,WAAW;AAAA,YACnC,UAAS,+BAAO,YAAW,OAAO,KAAK;AAAA,YACvC,MAAM,eAAe;AAAA,UACvB,CAAC;AACD,yBAAe,aAAa;AAE5B,uBAAa,eAAe,KAAK;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,gBAAgB,gBAAgB,YAAY;AAAA,EAC/C;AAEA,YAAU,MAAM;AACd,QAAI,CAAC,YAAY,aAAa,mBAAmB;AAAS;AAC1D,QACE,aAAa,mBAAmB,YAChC,6CAAc,eAAc,oBAAoB,SAChD;AACA;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAY;AAxQtC;AAyQM,UAAI,EAAC,6CAAc;AAAW;AAE9B,YAAM,SAAS,MAAM,cAAc,eAAe;AAAA,QAChD;AAAA,QACA,WAAW,6CAAc;AAAA,MAC3B,CAAC;AAGD,UAAI,OAAO,OAAO;AAEhB,2BAAmB,UAAU;AAC7B,4BAAoB,UAAU,6CAAc;AAC5C,4BAAoB,OAAO,KAAK;AAChC;AAAA,MACF;AAEA,YAAM,eAAc,kBAAO,SAAP,mBAAa,mBAAb,mBAA6B;AACjD,UAAI,gBAAgB,mBAAmB;AAAS;AAEhD,WAAI,YAAO,SAAP,mBAAa,gBAAgB;AAC/B,2BAAmB,UAAU;AAC7B,2BAAmB,UAAU;AAC7B,4BAAoB,UAAU,6CAAc;AAE5C,cAAMA,YAAW,mCAAmC,KAAK,MAAM,eAAe,IAAI,CAAC;AACnF,oBAAYA,SAAQ;AAAA,MACtB;AAAA,IACF;AACA,SAAK,cAAc;AAAA,EACrB,GAAG,CAAC,UAAU,6CAAc,SAAS,CAAC;AAEtC,YAAU,MAAM;AACd,sBAAkB,QAAQ;AAAA,EAC5B,GAAG,CAAC,UAAU,iBAAiB,CAAC;AAEhC,QAAM,mBAAmB,QAAQ,MAAM,UAAU,CAAC,QAAQ,CAAC;AAC3D,QAAM,CAAC,aAAa,cAAc,IAAI,SAA2B,CAAC,CAAC;AAEnE,SACE;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;","names":["messages"]}