@tinkrapp/widget 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -60,10 +60,13 @@ var WidgetAPI = class {
60
60
  return response;
61
61
  }
62
62
  async sendMessage(sessionId, content) {
63
- const response = await this.request(`/sessions/${sessionId}/messages`, {
64
- method: "POST",
65
- body: JSON.stringify({ content })
66
- });
63
+ const response = await this.request(
64
+ `/sessions/${sessionId}/messages`,
65
+ {
66
+ method: "POST",
67
+ body: JSON.stringify({ content })
68
+ }
69
+ );
67
70
  return response;
68
71
  }
69
72
  async getHistory(sessionId) {
@@ -91,7 +94,7 @@ var WidgetAPI = class {
91
94
  ...options,
92
95
  headers: {
93
96
  "Content-Type": "application/json",
94
- "Authorization": `Bearer ${this.config.apiKey}`,
97
+ Authorization: `Bearer ${this.config.apiKey}`,
95
98
  ...options.headers
96
99
  }
97
100
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/events.ts","../src/core/api.ts","../src/core/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["type EventHandler<T = unknown> = (payload: T) => void;\n\nexport class TypedEventEmitter<TEvents extends Record<string, unknown>> {\n private listeners = new Map<keyof TEvents, Set<EventHandler>>();\n\n on<K extends keyof TEvents>(\n event: K,\n handler: EventHandler<TEvents[K]>\n ): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler as EventHandler);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n off<K extends keyof TEvents>(\n event: K,\n handler: EventHandler<TEvents[K]>\n ): void {\n this.listeners.get(event)?.delete(handler as EventHandler);\n }\n\n emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n this.listeners.get(event)?.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n console.error(`Error in ${String(event)} handler:`, error);\n }\n });\n }\n\n clear(): void {\n this.listeners.clear();\n }\n\n removeAllListeners(event?: keyof TEvents): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n}\n\n","import type { WidgetConfig, Message, ChatSession, Artifact } from './types';\n\nexport class WidgetAPI {\n private config: Required<WidgetConfig>;\n\n constructor(config: WidgetConfig) {\n this.config = {\n baseUrl: process.env.WIDGET_API_URL || 'http://localhost:3000',\n userId: '',\n debug: false,\n assistantId: config.apiKey, // Default to apiKey for backwards compatibility\n ...config,\n };\n }\n\n async createSession(): Promise<ChatSession> {\n const response = await this.request<ChatSession>('/sessions', {\n method: 'POST',\n body: JSON.stringify({\n // apiKey IS the assistantId\n assistantId: this.config.apiKey,\n userId: this.config.userId,\n }),\n });\n return response;\n }\n\n async sendMessage(sessionId: string, content: string): Promise<Message> {\n const response = await this.request<Message>(`/sessions/${sessionId}/messages`, {\n method: 'POST',\n body: JSON.stringify({ content }),\n });\n return response;\n }\n\n async getHistory(sessionId: string): Promise<Message[]> {\n return this.request<Message[]>(`/sessions/${sessionId}/messages`);\n }\n\n async getSessions(): Promise<ChatSession[]> {\n return this.request<ChatSession[]>('/sessions');\n }\n\n async getArtifacts(): Promise<Artifact[]> {\n return this.request<Artifact[]>('/artifacts');\n }\n\n async getArtifact(id: string): Promise<Artifact> {\n return this.request<Artifact>(`/artifacts/${id}`);\n }\n\n async createArtifact(artifact: Omit<Artifact, 'id' | 'createdAt' | 'updatedAt'>): Promise<Artifact> {\n return this.request<Artifact>('/artifacts', {\n method: 'POST',\n body: JSON.stringify(artifact),\n });\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.config.baseUrl}${endpoint}`;\n \n this.log('Request:', url, options);\n\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.apiKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.message || `HTTP ${response.status}`);\n }\n\n return response.json();\n }\n\n private log(...args: unknown[]): void {\n if (this.config.debug) {\n console.log('[CourseAI]', ...args);\n }\n }\n}\n\n","import { TypedEventEmitter } from './events';\nimport { WidgetAPI } from './api';\nimport type {\n WidgetConfig,\n WidgetState,\n WidgetEvents,\n Message,\n ChatSession,\n} from './types';\n\nexport class WidgetClient {\n private config: WidgetConfig;\n private state: WidgetState = { status: 'idle' };\n private events = new TypedEventEmitter<WidgetEvents>();\n private api: WidgetAPI;\n\n constructor(config: WidgetConfig) {\n this.config = config;\n this.api = new WidgetAPI(config);\n }\n\n /**\n * Initialize the widget and create a chat session\n */\n async initialize(): Promise<void> {\n if (this.state.status !== 'idle') {\n throw new Error('Widget already initialized');\n }\n\n this.setState({ status: 'initializing' });\n\n try {\n const session = await this.api.createSession();\n this.setState({ status: 'ready', session });\n this.events.emit('session:created', { session });\n } catch (error) {\n const widgetError = {\n code: 'INIT_FAILED',\n message: error instanceof Error ? error.message : 'Unknown error',\n details: error,\n };\n this.setState({ status: 'error', error: widgetError });\n this.events.emit('error', { error: widgetError });\n throw error;\n }\n }\n\n /**\n * Send a message to the AI assistant\n */\n async sendMessage(content: string): Promise<Message> {\n if (this.state.status !== 'ready') {\n throw new Error('Widget not ready. Call initialize() first.');\n }\n\n const userMessage: Message = {\n id: crypto.randomUUID(),\n role: 'user',\n content,\n timestamp: Date.now(),\n };\n\n // Optimistically add user message\n const session = {\n ...this.state.session,\n messages: [...this.state.session.messages, userMessage],\n };\n this.setState({ status: 'ready', session });\n this.events.emit('message:sent', { message: userMessage });\n\n // Set loading state\n this.setState({ status: 'loading' });\n\n try {\n const assistantMessage = await this.api.sendMessage(\n session.id,\n content\n );\n\n const updatedSession = {\n ...session,\n messages: [...session.messages, assistantMessage],\n };\n\n this.setState({ status: 'ready', session: updatedSession });\n this.events.emit('message:received', { message: assistantMessage });\n\n return assistantMessage;\n } catch (error) {\n const widgetError = {\n code: 'SEND_MESSAGE_FAILED',\n message: error instanceof Error ? error.message : 'Failed to send message',\n details: error,\n };\n \n // Revert to previous state with user message still included\n this.setState({ status: 'ready', session });\n this.events.emit('error', { error: widgetError });\n throw error;\n }\n }\n\n /**\n * Get current state\n */\n getState(): WidgetState {\n return this.state;\n }\n\n /**\n * Get the API instance for direct calls\n */\n getAPI(): WidgetAPI {\n return this.api;\n }\n\n /**\n * Get the widget configuration\n */\n getConfig(): WidgetConfig {\n return this.config;\n }\n\n /**\n * Subscribe to events\n */\n on<K extends keyof WidgetEvents>(\n event: K,\n handler: (payload: WidgetEvents[K]) => void\n ): () => void {\n return this.events.on(event, handler);\n }\n\n /**\n * Unsubscribe from events\n */\n off<K extends keyof WidgetEvents>(\n event: K,\n handler: (payload: WidgetEvents[K]) => void\n ): void {\n this.events.off(event, handler);\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.events.clear();\n this.setState({ status: 'idle' });\n }\n\n private setState(newState: WidgetState): void {\n const previous = this.state;\n this.state = newState;\n this.events.emit('state:change', { previous, current: newState });\n }\n}\n\n"]}
1
+ {"version":3,"sources":["../src/core/events.ts","../src/core/api.ts","../src/core/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["type EventHandler<T = unknown> = (payload: T) => void;\n\nexport class TypedEventEmitter<TEvents extends Record<string, unknown>> {\n private listeners = new Map<keyof TEvents, Set<EventHandler>>();\n\n on<K extends keyof TEvents>(\n event: K,\n handler: EventHandler<TEvents[K]>\n ): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler as EventHandler);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n off<K extends keyof TEvents>(\n event: K,\n handler: EventHandler<TEvents[K]>\n ): void {\n this.listeners.get(event)?.delete(handler as EventHandler);\n }\n\n emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n this.listeners.get(event)?.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n console.error(`Error in ${String(event)} handler:`, error);\n }\n });\n }\n\n clear(): void {\n this.listeners.clear();\n }\n\n removeAllListeners(event?: keyof TEvents): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n}\n\n","import type { Artifact, ChatSession, Message, WidgetConfig } from './types'\n\n/**\n * Resolved config with required core fields but optional context fields\n */\ntype ResolvedConfig = Required<\n Pick<WidgetConfig, 'apiKey' | 'assistantId' | 'baseUrl' | 'userId' | 'debug'>\n> &\n Pick<WidgetConfig, 'userContext' | 'lessonContext'>\n\nexport class WidgetAPI {\n private config: ResolvedConfig\n\n constructor(config: WidgetConfig) {\n this.config = {\n baseUrl: process.env.APP_URL || 'http://localhost:3000',\n userId: '',\n debug: false,\n assistantId: config.apiKey, // Default to apiKey for backwards compatibility\n ...config,\n }\n }\n\n async createSession(): Promise<ChatSession> {\n const response = await this.request<ChatSession>('/sessions', {\n method: 'POST',\n body: JSON.stringify({\n // apiKey IS the assistantId\n assistantId: this.config.apiKey,\n userId: this.config.userId,\n }),\n })\n return response\n }\n\n async sendMessage(sessionId: string, content: string): Promise<Message> {\n const response = await this.request<Message>(\n `/sessions/${sessionId}/messages`,\n {\n method: 'POST',\n body: JSON.stringify({ content }),\n },\n )\n return response\n }\n\n async getHistory(sessionId: string): Promise<Message[]> {\n return this.request<Message[]>(`/sessions/${sessionId}/messages`)\n }\n\n async getSessions(): Promise<ChatSession[]> {\n return this.request<ChatSession[]>('/sessions')\n }\n\n async getArtifacts(): Promise<Artifact[]> {\n return this.request<Artifact[]>('/artifacts')\n }\n\n async getArtifact(id: string): Promise<Artifact> {\n return this.request<Artifact>(`/artifacts/${id}`)\n }\n\n async createArtifact(\n artifact: Omit<Artifact, 'id' | 'createdAt' | 'updatedAt'>,\n ): Promise<Artifact> {\n return this.request<Artifact>('/artifacts', {\n method: 'POST',\n body: JSON.stringify(artifact),\n })\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${this.config.baseUrl}${endpoint}`\n\n this.log('Request:', url, options)\n\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n ...options.headers,\n },\n })\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}))\n throw new Error(error.message || `HTTP ${response.status}`)\n }\n\n return response.json()\n }\n\n private log(...args: unknown[]): void {\n if (this.config.debug) {\n console.log('[CourseAI]', ...args)\n }\n }\n}\n","import { TypedEventEmitter } from './events';\nimport { WidgetAPI } from './api';\nimport type {\n WidgetConfig,\n WidgetState,\n WidgetEvents,\n Message,\n ChatSession,\n} from './types';\n\nexport class WidgetClient {\n private config: WidgetConfig;\n private state: WidgetState = { status: 'idle' };\n private events = new TypedEventEmitter<WidgetEvents>();\n private api: WidgetAPI;\n\n constructor(config: WidgetConfig) {\n this.config = config;\n this.api = new WidgetAPI(config);\n }\n\n /**\n * Initialize the widget and create a chat session\n */\n async initialize(): Promise<void> {\n if (this.state.status !== 'idle') {\n throw new Error('Widget already initialized');\n }\n\n this.setState({ status: 'initializing' });\n\n try {\n const session = await this.api.createSession();\n this.setState({ status: 'ready', session });\n this.events.emit('session:created', { session });\n } catch (error) {\n const widgetError = {\n code: 'INIT_FAILED',\n message: error instanceof Error ? error.message : 'Unknown error',\n details: error,\n };\n this.setState({ status: 'error', error: widgetError });\n this.events.emit('error', { error: widgetError });\n throw error;\n }\n }\n\n /**\n * Send a message to the AI assistant\n */\n async sendMessage(content: string): Promise<Message> {\n if (this.state.status !== 'ready') {\n throw new Error('Widget not ready. Call initialize() first.');\n }\n\n const userMessage: Message = {\n id: crypto.randomUUID(),\n role: 'user',\n content,\n timestamp: Date.now(),\n };\n\n // Optimistically add user message\n const session = {\n ...this.state.session,\n messages: [...this.state.session.messages, userMessage],\n };\n this.setState({ status: 'ready', session });\n this.events.emit('message:sent', { message: userMessage });\n\n // Set loading state\n this.setState({ status: 'loading' });\n\n try {\n const assistantMessage = await this.api.sendMessage(\n session.id,\n content\n );\n\n const updatedSession = {\n ...session,\n messages: [...session.messages, assistantMessage],\n };\n\n this.setState({ status: 'ready', session: updatedSession });\n this.events.emit('message:received', { message: assistantMessage });\n\n return assistantMessage;\n } catch (error) {\n const widgetError = {\n code: 'SEND_MESSAGE_FAILED',\n message: error instanceof Error ? error.message : 'Failed to send message',\n details: error,\n };\n \n // Revert to previous state with user message still included\n this.setState({ status: 'ready', session });\n this.events.emit('error', { error: widgetError });\n throw error;\n }\n }\n\n /**\n * Get current state\n */\n getState(): WidgetState {\n return this.state;\n }\n\n /**\n * Get the API instance for direct calls\n */\n getAPI(): WidgetAPI {\n return this.api;\n }\n\n /**\n * Get the widget configuration\n */\n getConfig(): WidgetConfig {\n return this.config;\n }\n\n /**\n * Subscribe to events\n */\n on<K extends keyof WidgetEvents>(\n event: K,\n handler: (payload: WidgetEvents[K]) => void\n ): () => void {\n return this.events.on(event, handler);\n }\n\n /**\n * Unsubscribe from events\n */\n off<K extends keyof WidgetEvents>(\n event: K,\n handler: (payload: WidgetEvents[K]) => void\n ): void {\n this.events.off(event, handler);\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.events.clear();\n this.setState({ status: 'idle' });\n }\n\n private setState(newState: WidgetState): void {\n const previous = this.state;\n this.state = newState;\n this.events.emit('state:change', { previous, current: newState });\n }\n}\n\n"]}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as Artifact, f as ArtifactCategory, C as ChatSession, M as Message, a as WidgetAPI, W as WidgetClient, b as WidgetConfig, e as WidgetError, d as WidgetEvents, c as WidgetState } from './client-CExUGn7b.cjs';
1
+ export { A as Artifact, f as ArtifactCategory, C as ChatSession, M as Message, a as WidgetAPI, W as WidgetClient, b as WidgetConfig, e as WidgetError, d as WidgetEvents, c as WidgetState } from './client-BFcAYuri.cjs';
2
2
 
3
3
  type EventHandler<T = unknown> = (payload: T) => void;
4
4
  declare class TypedEventEmitter<TEvents extends Record<string, unknown>> {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as Artifact, f as ArtifactCategory, C as ChatSession, M as Message, a as WidgetAPI, W as WidgetClient, b as WidgetConfig, e as WidgetError, d as WidgetEvents, c as WidgetState } from './client-CExUGn7b.js';
1
+ export { A as Artifact, f as ArtifactCategory, C as ChatSession, M as Message, a as WidgetAPI, W as WidgetClient, b as WidgetConfig, e as WidgetError, d as WidgetEvents, c as WidgetState } from './client-BFcAYuri.js';
2
2
 
3
3
  type EventHandler<T = unknown> = (payload: T) => void;
4
4
  declare class TypedEventEmitter<TEvents extends Record<string, unknown>> {
package/dist/index.js CHANGED
@@ -58,10 +58,13 @@ var WidgetAPI = class {
58
58
  return response;
59
59
  }
60
60
  async sendMessage(sessionId, content) {
61
- const response = await this.request(`/sessions/${sessionId}/messages`, {
62
- method: "POST",
63
- body: JSON.stringify({ content })
64
- });
61
+ const response = await this.request(
62
+ `/sessions/${sessionId}/messages`,
63
+ {
64
+ method: "POST",
65
+ body: JSON.stringify({ content })
66
+ }
67
+ );
65
68
  return response;
66
69
  }
67
70
  async getHistory(sessionId) {
@@ -89,7 +92,7 @@ var WidgetAPI = class {
89
92
  ...options,
90
93
  headers: {
91
94
  "Content-Type": "application/json",
92
- "Authorization": `Bearer ${this.config.apiKey}`,
95
+ Authorization: `Bearer ${this.config.apiKey}`,
93
96
  ...options.headers
94
97
  }
95
98
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/events.ts","../src/core/api.ts","../src/core/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["type EventHandler<T = unknown> = (payload: T) => void;\n\nexport class TypedEventEmitter<TEvents extends Record<string, unknown>> {\n private listeners = new Map<keyof TEvents, Set<EventHandler>>();\n\n on<K extends keyof TEvents>(\n event: K,\n handler: EventHandler<TEvents[K]>\n ): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler as EventHandler);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n off<K extends keyof TEvents>(\n event: K,\n handler: EventHandler<TEvents[K]>\n ): void {\n this.listeners.get(event)?.delete(handler as EventHandler);\n }\n\n emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n this.listeners.get(event)?.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n console.error(`Error in ${String(event)} handler:`, error);\n }\n });\n }\n\n clear(): void {\n this.listeners.clear();\n }\n\n removeAllListeners(event?: keyof TEvents): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n}\n\n","import type { WidgetConfig, Message, ChatSession, Artifact } from './types';\n\nexport class WidgetAPI {\n private config: Required<WidgetConfig>;\n\n constructor(config: WidgetConfig) {\n this.config = {\n baseUrl: process.env.WIDGET_API_URL || 'http://localhost:3000',\n userId: '',\n debug: false,\n assistantId: config.apiKey, // Default to apiKey for backwards compatibility\n ...config,\n };\n }\n\n async createSession(): Promise<ChatSession> {\n const response = await this.request<ChatSession>('/sessions', {\n method: 'POST',\n body: JSON.stringify({\n // apiKey IS the assistantId\n assistantId: this.config.apiKey,\n userId: this.config.userId,\n }),\n });\n return response;\n }\n\n async sendMessage(sessionId: string, content: string): Promise<Message> {\n const response = await this.request<Message>(`/sessions/${sessionId}/messages`, {\n method: 'POST',\n body: JSON.stringify({ content }),\n });\n return response;\n }\n\n async getHistory(sessionId: string): Promise<Message[]> {\n return this.request<Message[]>(`/sessions/${sessionId}/messages`);\n }\n\n async getSessions(): Promise<ChatSession[]> {\n return this.request<ChatSession[]>('/sessions');\n }\n\n async getArtifacts(): Promise<Artifact[]> {\n return this.request<Artifact[]>('/artifacts');\n }\n\n async getArtifact(id: string): Promise<Artifact> {\n return this.request<Artifact>(`/artifacts/${id}`);\n }\n\n async createArtifact(artifact: Omit<Artifact, 'id' | 'createdAt' | 'updatedAt'>): Promise<Artifact> {\n return this.request<Artifact>('/artifacts', {\n method: 'POST',\n body: JSON.stringify(artifact),\n });\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.config.baseUrl}${endpoint}`;\n \n this.log('Request:', url, options);\n\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.apiKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.message || `HTTP ${response.status}`);\n }\n\n return response.json();\n }\n\n private log(...args: unknown[]): void {\n if (this.config.debug) {\n console.log('[CourseAI]', ...args);\n }\n }\n}\n\n","import { TypedEventEmitter } from './events';\nimport { WidgetAPI } from './api';\nimport type {\n WidgetConfig,\n WidgetState,\n WidgetEvents,\n Message,\n ChatSession,\n} from './types';\n\nexport class WidgetClient {\n private config: WidgetConfig;\n private state: WidgetState = { status: 'idle' };\n private events = new TypedEventEmitter<WidgetEvents>();\n private api: WidgetAPI;\n\n constructor(config: WidgetConfig) {\n this.config = config;\n this.api = new WidgetAPI(config);\n }\n\n /**\n * Initialize the widget and create a chat session\n */\n async initialize(): Promise<void> {\n if (this.state.status !== 'idle') {\n throw new Error('Widget already initialized');\n }\n\n this.setState({ status: 'initializing' });\n\n try {\n const session = await this.api.createSession();\n this.setState({ status: 'ready', session });\n this.events.emit('session:created', { session });\n } catch (error) {\n const widgetError = {\n code: 'INIT_FAILED',\n message: error instanceof Error ? error.message : 'Unknown error',\n details: error,\n };\n this.setState({ status: 'error', error: widgetError });\n this.events.emit('error', { error: widgetError });\n throw error;\n }\n }\n\n /**\n * Send a message to the AI assistant\n */\n async sendMessage(content: string): Promise<Message> {\n if (this.state.status !== 'ready') {\n throw new Error('Widget not ready. Call initialize() first.');\n }\n\n const userMessage: Message = {\n id: crypto.randomUUID(),\n role: 'user',\n content,\n timestamp: Date.now(),\n };\n\n // Optimistically add user message\n const session = {\n ...this.state.session,\n messages: [...this.state.session.messages, userMessage],\n };\n this.setState({ status: 'ready', session });\n this.events.emit('message:sent', { message: userMessage });\n\n // Set loading state\n this.setState({ status: 'loading' });\n\n try {\n const assistantMessage = await this.api.sendMessage(\n session.id,\n content\n );\n\n const updatedSession = {\n ...session,\n messages: [...session.messages, assistantMessage],\n };\n\n this.setState({ status: 'ready', session: updatedSession });\n this.events.emit('message:received', { message: assistantMessage });\n\n return assistantMessage;\n } catch (error) {\n const widgetError = {\n code: 'SEND_MESSAGE_FAILED',\n message: error instanceof Error ? error.message : 'Failed to send message',\n details: error,\n };\n \n // Revert to previous state with user message still included\n this.setState({ status: 'ready', session });\n this.events.emit('error', { error: widgetError });\n throw error;\n }\n }\n\n /**\n * Get current state\n */\n getState(): WidgetState {\n return this.state;\n }\n\n /**\n * Get the API instance for direct calls\n */\n getAPI(): WidgetAPI {\n return this.api;\n }\n\n /**\n * Get the widget configuration\n */\n getConfig(): WidgetConfig {\n return this.config;\n }\n\n /**\n * Subscribe to events\n */\n on<K extends keyof WidgetEvents>(\n event: K,\n handler: (payload: WidgetEvents[K]) => void\n ): () => void {\n return this.events.on(event, handler);\n }\n\n /**\n * Unsubscribe from events\n */\n off<K extends keyof WidgetEvents>(\n event: K,\n handler: (payload: WidgetEvents[K]) => void\n ): void {\n this.events.off(event, handler);\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.events.clear();\n this.setState({ status: 'idle' });\n }\n\n private setState(newState: WidgetState): void {\n const previous = this.state;\n this.state = newState;\n this.events.emit('state:change', { previous, current: newState });\n }\n}\n\n"]}
1
+ {"version":3,"sources":["../src/core/events.ts","../src/core/api.ts","../src/core/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["type EventHandler<T = unknown> = (payload: T) => void;\n\nexport class TypedEventEmitter<TEvents extends Record<string, unknown>> {\n private listeners = new Map<keyof TEvents, Set<EventHandler>>();\n\n on<K extends keyof TEvents>(\n event: K,\n handler: EventHandler<TEvents[K]>\n ): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler as EventHandler);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n off<K extends keyof TEvents>(\n event: K,\n handler: EventHandler<TEvents[K]>\n ): void {\n this.listeners.get(event)?.delete(handler as EventHandler);\n }\n\n emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n this.listeners.get(event)?.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n console.error(`Error in ${String(event)} handler:`, error);\n }\n });\n }\n\n clear(): void {\n this.listeners.clear();\n }\n\n removeAllListeners(event?: keyof TEvents): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n}\n\n","import type { Artifact, ChatSession, Message, WidgetConfig } from './types'\n\n/**\n * Resolved config with required core fields but optional context fields\n */\ntype ResolvedConfig = Required<\n Pick<WidgetConfig, 'apiKey' | 'assistantId' | 'baseUrl' | 'userId' | 'debug'>\n> &\n Pick<WidgetConfig, 'userContext' | 'lessonContext'>\n\nexport class WidgetAPI {\n private config: ResolvedConfig\n\n constructor(config: WidgetConfig) {\n this.config = {\n baseUrl: process.env.APP_URL || 'http://localhost:3000',\n userId: '',\n debug: false,\n assistantId: config.apiKey, // Default to apiKey for backwards compatibility\n ...config,\n }\n }\n\n async createSession(): Promise<ChatSession> {\n const response = await this.request<ChatSession>('/sessions', {\n method: 'POST',\n body: JSON.stringify({\n // apiKey IS the assistantId\n assistantId: this.config.apiKey,\n userId: this.config.userId,\n }),\n })\n return response\n }\n\n async sendMessage(sessionId: string, content: string): Promise<Message> {\n const response = await this.request<Message>(\n `/sessions/${sessionId}/messages`,\n {\n method: 'POST',\n body: JSON.stringify({ content }),\n },\n )\n return response\n }\n\n async getHistory(sessionId: string): Promise<Message[]> {\n return this.request<Message[]>(`/sessions/${sessionId}/messages`)\n }\n\n async getSessions(): Promise<ChatSession[]> {\n return this.request<ChatSession[]>('/sessions')\n }\n\n async getArtifacts(): Promise<Artifact[]> {\n return this.request<Artifact[]>('/artifacts')\n }\n\n async getArtifact(id: string): Promise<Artifact> {\n return this.request<Artifact>(`/artifacts/${id}`)\n }\n\n async createArtifact(\n artifact: Omit<Artifact, 'id' | 'createdAt' | 'updatedAt'>,\n ): Promise<Artifact> {\n return this.request<Artifact>('/artifacts', {\n method: 'POST',\n body: JSON.stringify(artifact),\n })\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${this.config.baseUrl}${endpoint}`\n\n this.log('Request:', url, options)\n\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n ...options.headers,\n },\n })\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}))\n throw new Error(error.message || `HTTP ${response.status}`)\n }\n\n return response.json()\n }\n\n private log(...args: unknown[]): void {\n if (this.config.debug) {\n console.log('[CourseAI]', ...args)\n }\n }\n}\n","import { TypedEventEmitter } from './events';\nimport { WidgetAPI } from './api';\nimport type {\n WidgetConfig,\n WidgetState,\n WidgetEvents,\n Message,\n ChatSession,\n} from './types';\n\nexport class WidgetClient {\n private config: WidgetConfig;\n private state: WidgetState = { status: 'idle' };\n private events = new TypedEventEmitter<WidgetEvents>();\n private api: WidgetAPI;\n\n constructor(config: WidgetConfig) {\n this.config = config;\n this.api = new WidgetAPI(config);\n }\n\n /**\n * Initialize the widget and create a chat session\n */\n async initialize(): Promise<void> {\n if (this.state.status !== 'idle') {\n throw new Error('Widget already initialized');\n }\n\n this.setState({ status: 'initializing' });\n\n try {\n const session = await this.api.createSession();\n this.setState({ status: 'ready', session });\n this.events.emit('session:created', { session });\n } catch (error) {\n const widgetError = {\n code: 'INIT_FAILED',\n message: error instanceof Error ? error.message : 'Unknown error',\n details: error,\n };\n this.setState({ status: 'error', error: widgetError });\n this.events.emit('error', { error: widgetError });\n throw error;\n }\n }\n\n /**\n * Send a message to the AI assistant\n */\n async sendMessage(content: string): Promise<Message> {\n if (this.state.status !== 'ready') {\n throw new Error('Widget not ready. Call initialize() first.');\n }\n\n const userMessage: Message = {\n id: crypto.randomUUID(),\n role: 'user',\n content,\n timestamp: Date.now(),\n };\n\n // Optimistically add user message\n const session = {\n ...this.state.session,\n messages: [...this.state.session.messages, userMessage],\n };\n this.setState({ status: 'ready', session });\n this.events.emit('message:sent', { message: userMessage });\n\n // Set loading state\n this.setState({ status: 'loading' });\n\n try {\n const assistantMessage = await this.api.sendMessage(\n session.id,\n content\n );\n\n const updatedSession = {\n ...session,\n messages: [...session.messages, assistantMessage],\n };\n\n this.setState({ status: 'ready', session: updatedSession });\n this.events.emit('message:received', { message: assistantMessage });\n\n return assistantMessage;\n } catch (error) {\n const widgetError = {\n code: 'SEND_MESSAGE_FAILED',\n message: error instanceof Error ? error.message : 'Failed to send message',\n details: error,\n };\n \n // Revert to previous state with user message still included\n this.setState({ status: 'ready', session });\n this.events.emit('error', { error: widgetError });\n throw error;\n }\n }\n\n /**\n * Get current state\n */\n getState(): WidgetState {\n return this.state;\n }\n\n /**\n * Get the API instance for direct calls\n */\n getAPI(): WidgetAPI {\n return this.api;\n }\n\n /**\n * Get the widget configuration\n */\n getConfig(): WidgetConfig {\n return this.config;\n }\n\n /**\n * Subscribe to events\n */\n on<K extends keyof WidgetEvents>(\n event: K,\n handler: (payload: WidgetEvents[K]) => void\n ): () => void {\n return this.events.on(event, handler);\n }\n\n /**\n * Unsubscribe from events\n */\n off<K extends keyof WidgetEvents>(\n event: K,\n handler: (payload: WidgetEvents[K]) => void\n ): void {\n this.events.off(event, handler);\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.events.clear();\n this.setState({ status: 'idle' });\n }\n\n private setState(newState: WidgetState): void {\n const previous = this.state;\n this.state = newState;\n this.events.emit('state:change', { previous, current: newState });\n }\n}\n\n"]}
package/dist/react.cjs CHANGED
@@ -114,10 +114,13 @@ var WidgetAPI = class {
114
114
  return response;
115
115
  }
116
116
  async sendMessage(sessionId, content) {
117
- const response = await this.request(`/sessions/${sessionId}/messages`, {
118
- method: "POST",
119
- body: JSON.stringify({ content })
120
- });
117
+ const response = await this.request(
118
+ `/sessions/${sessionId}/messages`,
119
+ {
120
+ method: "POST",
121
+ body: JSON.stringify({ content })
122
+ }
123
+ );
121
124
  return response;
122
125
  }
123
126
  async getHistory(sessionId) {
@@ -145,7 +148,7 @@ var WidgetAPI = class {
145
148
  ...options,
146
149
  headers: {
147
150
  "Content-Type": "application/json",
148
- "Authorization": `Bearer ${this.config.apiKey}`,
151
+ Authorization: `Bearer ${this.config.apiKey}`,
149
152
  ...options.headers
150
153
  }
151
154
  });
@@ -279,6 +282,28 @@ var WidgetClient = class {
279
282
  this.events.emit("state:change", { previous, current: newState });
280
283
  }
281
284
  };
285
+ var LessonContext = React2.createContext({
286
+ lessonContext: null,
287
+ hasLessonContext: false
288
+ });
289
+ function LessonContextProvider({
290
+ children,
291
+ lessonContext
292
+ }) {
293
+ return /* @__PURE__ */ jsxRuntime.jsx(
294
+ LessonContext.Provider,
295
+ {
296
+ value: {
297
+ lessonContext: lessonContext ?? null,
298
+ hasLessonContext: !!lessonContext
299
+ },
300
+ children
301
+ }
302
+ );
303
+ }
304
+ function useLessonContext() {
305
+ return React2.useContext(LessonContext);
306
+ }
282
307
  var MessageContext = React2.createContext(null);
283
308
  function MessageContextProvider({ children }) {
284
309
  const [selectedContext, setSelectedContext] = React2.useState([]);
@@ -1674,15 +1699,25 @@ var WidgetContext = React2.createContext(null);
1674
1699
  function generateUserId() {
1675
1700
  return crypto.randomUUID();
1676
1701
  }
1677
- function createApiHeaders(userId, assistantId) {
1678
- return {
1702
+ function createApiHeaders(userId, assistantId, userContext) {
1703
+ const headers = {
1679
1704
  "Content-Type": "application/json",
1680
1705
  "X-User-Id": userId,
1681
1706
  "X-Assistant-Id": assistantId
1682
1707
  };
1708
+ if (userContext?.firstName) {
1709
+ headers["X-User-First-Name"] = userContext.firstName;
1710
+ }
1711
+ if (userContext?.lastName) {
1712
+ headers["X-User-Last-Name"] = userContext.lastName;
1713
+ }
1714
+ if (userContext?.email) {
1715
+ headers["X-User-Email"] = userContext.email;
1716
+ }
1717
+ return headers;
1683
1718
  }
1684
- function createThreadListAdapter(baseUrl, userId, assistantId) {
1685
- const headers = createApiHeaders(userId, assistantId);
1719
+ function createThreadListAdapter(baseUrl, userId, assistantId, userContext) {
1720
+ const headers = createApiHeaders(userId, assistantId, userContext);
1686
1721
  return {
1687
1722
  // List all threads for this user
1688
1723
  async list() {
@@ -1809,13 +1844,13 @@ function createThreadListAdapter(baseUrl, userId, assistantId) {
1809
1844
  }
1810
1845
  };
1811
1846
  }
1812
- async function saveMessages(baseUrl, userId, assistantId, threadId, messages) {
1847
+ async function saveMessages(baseUrl, userId, assistantId, threadId, messages, userContext) {
1813
1848
  try {
1814
1849
  const response = await fetch(
1815
1850
  `${baseUrl}/api/widget/threads/${threadId}/messages/sync`,
1816
1851
  {
1817
1852
  method: "POST",
1818
- headers: createApiHeaders(userId, assistantId),
1853
+ headers: createApiHeaders(userId, assistantId, userContext),
1819
1854
  body: JSON.stringify({ messages })
1820
1855
  }
1821
1856
  );
@@ -1826,8 +1861,8 @@ async function saveMessages(baseUrl, userId, assistantId, threadId, messages) {
1826
1861
  console.error("[Messages] Sync error:", error);
1827
1862
  }
1828
1863
  }
1829
- function createHistoryAdapter(baseUrl, userId, assistantId, remoteId) {
1830
- const headers = createApiHeaders(userId, assistantId);
1864
+ function createHistoryAdapter(baseUrl, userId, assistantId, remoteId, userContext) {
1865
+ const headers = createApiHeaders(userId, assistantId, userContext);
1831
1866
  return {
1832
1867
  async load() {
1833
1868
  console.log("[History] load() called, remoteId:", remoteId);
@@ -1925,8 +1960,8 @@ function AssistantRuntimeWrapper({
1925
1960
  const clearContextRef = React2.useRef(clearContext);
1926
1961
  clearContextRef.current = clearContext;
1927
1962
  const threadListAdapter = React2.useMemo(
1928
- () => createThreadListAdapter(baseUrl, userId, assistantId),
1929
- [baseUrl, userId, assistantId]
1963
+ () => createThreadListAdapter(baseUrl, userId, assistantId, config.userContext),
1964
+ [baseUrl, userId, assistantId, config.userContext]
1930
1965
  );
1931
1966
  const runtime = react$1.unstable_useRemoteThreadListRuntime({
1932
1967
  runtimeHook: function useChatThreadRuntime() {
@@ -1936,17 +1971,33 @@ function AssistantRuntimeWrapper({
1936
1971
  const threadIdRef = React2.useRef(threadId);
1937
1972
  threadIdRef.current = threadId;
1938
1973
  const history = React2.useMemo(
1939
- () => createHistoryAdapter(baseUrl, userId, assistantId, threadId),
1940
- [threadId]
1974
+ () => createHistoryAdapter(
1975
+ baseUrl,
1976
+ userId,
1977
+ assistantId,
1978
+ threadId,
1979
+ config.userContext
1980
+ ),
1981
+ [threadId, config.userContext]
1941
1982
  );
1942
1983
  const transport = React2.useMemo(() => {
1943
1984
  console.log("[Widget] Creating transport for threadId:", threadId);
1985
+ const transportHeaders = {
1986
+ "X-User-Id": userId,
1987
+ "X-Assistant-Id": assistantId
1988
+ };
1989
+ if (config.userContext?.firstName) {
1990
+ transportHeaders["X-User-First-Name"] = config.userContext.firstName;
1991
+ }
1992
+ if (config.userContext?.lastName) {
1993
+ transportHeaders["X-User-Last-Name"] = config.userContext.lastName;
1994
+ }
1995
+ if (config.userContext?.email) {
1996
+ transportHeaders["X-User-Email"] = config.userContext.email;
1997
+ }
1944
1998
  return new reactAiSdk.AssistantChatTransport({
1945
1999
  api: `${baseUrl}/api/widget/chat`,
1946
- headers: {
1947
- "X-User-Id": userId,
1948
- "X-Assistant-Id": assistantId
1949
- },
2000
+ headers: transportHeaders,
1950
2001
  // Use body as a function to dynamically include context
1951
2002
  body: () => {
1952
2003
  const currentContext = contextRef.current();
@@ -1972,7 +2023,7 @@ function AssistantRuntimeWrapper({
1972
2023
  };
1973
2024
  }
1974
2025
  });
1975
- }, [threadId]);
2026
+ }, [threadId, config.userContext]);
1976
2027
  const runtime2 = reactAiSdk.useChatRuntime({
1977
2028
  transport,
1978
2029
  adapters: { history },
@@ -1990,7 +2041,8 @@ function AssistantRuntimeWrapper({
1990
2041
  userId,
1991
2042
  assistantId,
1992
2043
  currentThreadId,
1993
- messages
2044
+ messages,
2045
+ config.userContext
1994
2046
  );
1995
2047
  }
1996
2048
  }
@@ -2004,7 +2056,9 @@ function AssistantRuntimeWrapper({
2004
2056
  function WidgetProvider({
2005
2057
  config,
2006
2058
  children,
2007
- autoInitialize = true
2059
+ // Legacy client initialization - disabled by default as the new assistant-ui
2060
+ // runtime handles session/thread management via the thread list adapter
2061
+ autoInitialize = false
2008
2062
  }) {
2009
2063
  const [userId] = React2.useState(() => config.userId || generateUserId());
2010
2064
  const [client] = React2.useState(() => new WidgetClient(config));
@@ -2025,7 +2079,7 @@ function WidgetProvider({
2025
2079
  () => ({ client, state, userId }),
2026
2080
  [client, state, userId]
2027
2081
  );
2028
- return /* @__PURE__ */ jsxRuntime.jsx(react$2.CacheProvider, { value: widgetCache, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(WidgetContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(MessageContextProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeWrapper, { config, userId, children }) }) }) }) });
2082
+ return /* @__PURE__ */ jsxRuntime.jsx(react$2.CacheProvider, { value: widgetCache, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(WidgetContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(LessonContextProvider, { lessonContext: config.lessonContext, children: /* @__PURE__ */ jsxRuntime.jsx(MessageContextProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeWrapper, { config, userId, children }) }) }) }) }) });
2029
2083
  }
2030
2084
  function useWidget() {
2031
2085
  const context = React2.useContext(WidgetContext);
@@ -3428,7 +3482,10 @@ var MentionComposerInput = React2.forwardRef(
3428
3482
  const walkForText = (node2) => {
3429
3483
  if (node2 === range.endContainer) {
3430
3484
  if (node2.nodeType === Node.TEXT_NODE) {
3431
- textBeforeCursor += (node2.textContent || "").slice(0, range.endOffset);
3485
+ textBeforeCursor += (node2.textContent || "").slice(
3486
+ 0,
3487
+ range.endOffset
3488
+ );
3432
3489
  }
3433
3490
  return true;
3434
3491
  }
@@ -3467,7 +3524,14 @@ var MentionComposerInput = React2.forwardRef(
3467
3524
  triggerPositionRef.current = null;
3468
3525
  onTriggerDismissed?.();
3469
3526
  }
3470
- }, [syncToRuntime, getPlainText, getCursorPosition, onInput, onTriggerDetected, onTriggerDismissed]);
3527
+ }, [
3528
+ syncToRuntime,
3529
+ getPlainText,
3530
+ getCursorPosition,
3531
+ onInput,
3532
+ onTriggerDetected,
3533
+ onTriggerDismissed
3534
+ ]);
3471
3535
  const handleKeyDown = React2.useCallback(
3472
3536
  (e) => {
3473
3537
  if (e.key === "Enter" && !e.shiftKey) {
@@ -3500,7 +3564,9 @@ var MentionComposerInput = React2.forwardRef(
3500
3564
  e.preventDefault();
3501
3565
  const mentionId = prevSibling.dataset.mentionId;
3502
3566
  prevSibling.parentNode?.removeChild(prevSibling);
3503
- setInlineMentions((prev2) => prev2.filter((m) => m.id !== mentionId));
3567
+ setInlineMentions(
3568
+ (prev2) => prev2.filter((m) => m.id !== mentionId)
3569
+ );
3504
3570
  onMentionRemove?.(mentionId);
3505
3571
  syncToRuntime();
3506
3572
  return;
@@ -3513,7 +3579,9 @@ var MentionComposerInput = React2.forwardRef(
3513
3579
  e.preventDefault();
3514
3580
  const mentionId = childAtOffset.dataset.mentionId;
3515
3581
  childAtOffset.parentNode?.removeChild(childAtOffset);
3516
- setInlineMentions((prev2) => prev2.filter((m) => m.id !== mentionId));
3582
+ setInlineMentions(
3583
+ (prev2) => prev2.filter((m) => m.id !== mentionId)
3584
+ );
3517
3585
  onMentionRemove?.(mentionId);
3518
3586
  syncToRuntime();
3519
3587
  return;
@@ -3750,7 +3818,8 @@ var CATEGORY_LABELS = {
3750
3818
  attachment: "Attachments",
3751
3819
  description: "Description",
3752
3820
  caption: "Video",
3753
- link: "Links"
3821
+ link: "Links",
3822
+ lesson: "Current Lesson"
3754
3823
  };
3755
3824
  function useContextMention(options = {}) {
3756
3825
  const { onInsertMention } = options;
@@ -3759,7 +3828,31 @@ function useContextMention(options = {}) {
3759
3828
  throw new Error("useContextMention must be used within a WidgetProvider");
3760
3829
  }
3761
3830
  const { client } = widgetContext;
3762
- const { selectedContext: selectedItems, addContextItem, removeContextItem, clearContext } = useMessageContext();
3831
+ const {
3832
+ selectedContext: selectedItems,
3833
+ addContextItem,
3834
+ removeContextItem,
3835
+ clearContext
3836
+ } = useMessageContext();
3837
+ const { lessonContext, hasLessonContext } = useLessonContext();
3838
+ React2.useEffect(() => {
3839
+ if (hasLessonContext && lessonContext) {
3840
+ const lessonItem = {
3841
+ id: lessonContext.lessonId,
3842
+ type: "lesson",
3843
+ title: lessonContext.lessonTitle,
3844
+ lessonTitle: lessonContext.lessonTitle,
3845
+ chapterTitle: lessonContext.chapterTitle
3846
+ };
3847
+ if (!selectedItems.some((item) => item.id === lessonItem.id)) {
3848
+ console.log(
3849
+ "[ContextMention] Auto-adding current lesson context:",
3850
+ lessonItem.title
3851
+ );
3852
+ addContextItem(lessonItem);
3853
+ }
3854
+ }
3855
+ }, [hasLessonContext]);
3763
3856
  const [isOpen, setIsOpen] = React2.useState(false);
3764
3857
  const [searchTerm, setSearchTerm] = React2.useState("");
3765
3858
  const [activeIndex, setActiveIndex] = React2.useState(0);
@@ -3789,7 +3882,10 @@ function useContextMention(options = {}) {
3789
3882
  }
3790
3883
  );
3791
3884
  if (!response.ok) {
3792
- console.error("[ContextMention] Failed to fetch context:", response.status);
3885
+ console.error(
3886
+ "[ContextMention] Failed to fetch context:",
3887
+ response.status
3888
+ );
3793
3889
  return;
3794
3890
  }
3795
3891
  const data = await response.json();
@@ -3840,7 +3936,13 @@ function useContextMention(options = {}) {
3840
3936
  closePopover();
3841
3937
  onInsertMention?.(item);
3842
3938
  }
3843
- }, [flattenedItems, activeIndex, addContextItem, closePopover, onInsertMention]);
3939
+ }, [
3940
+ flattenedItems,
3941
+ activeIndex,
3942
+ addContextItem,
3943
+ closePopover,
3944
+ onInsertMention
3945
+ ]);
3844
3946
  const selectItem = React2.useCallback(
3845
3947
  (item) => {
3846
3948
  addContextItem(item);
@@ -3849,9 +3951,12 @@ function useContextMention(options = {}) {
3849
3951
  },
3850
3952
  [addContextItem, closePopover, onInsertMention]
3851
3953
  );
3852
- const removeItem = React2.useCallback((itemId) => {
3853
- removeContextItem(itemId);
3854
- }, [removeContextItem]);
3954
+ const removeItem = React2.useCallback(
3955
+ (itemId) => {
3956
+ removeContextItem(itemId);
3957
+ },
3958
+ [removeContextItem]
3959
+ );
3855
3960
  const clearAll = React2.useCallback(() => {
3856
3961
  clearContext();
3857
3962
  }, [clearContext]);