@meetsmore-oss/use-ai-client 1.7.0 → 1.9.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.js CHANGED
@@ -4,13 +4,10 @@ import {
4
4
  } from "./chunk-STF3H6F5.js";
5
5
 
6
6
  // src/useAI.ts
7
- import { useState as useState14, useEffect as useEffect11, useRef as useRef13, useCallback as useCallback12, useMemo as useMemo6 } from "react";
7
+ import { useState as useState14, useEffect as useEffect12, useLayoutEffect, useRef as useRef14, useCallback as useCallback13, useMemo as useMemo6 } from "react";
8
8
 
9
9
  // src/providers/useAIProvider.tsx
10
- import { createContext as createContext4, useContext as useContext4, useState as useState13, useEffect as useEffect10, useCallback as useCallback11, useRef as useRef11 } from "react";
11
-
12
- // src/types.ts
13
- import { EventType, ErrorCode, TOOL_APPROVAL_REQUEST } from "@meetsmore-oss/use-ai-core";
10
+ import { createContext as createContext4, useContext as useContext4, useState as useState13, useEffect as useEffect11, useCallback as useCallback12, useRef as useRef12 } from "react";
14
11
 
15
12
  // src/theme/strings.ts
16
13
  import { createContext, useContext } from "react";
@@ -1641,7 +1638,8 @@ function ToolApprovalDialog({
1641
1638
  const [showDetails, setShowDetails] = useState4(false);
1642
1639
  const displayName = annotations?.title || toolCallName;
1643
1640
  const isBatch = toolCount > 1;
1644
- const message = isBatch ? strings.toolApproval.batchMessage?.replace("{count}", String(toolCount)) ?? `${toolCount} actions are waiting for your approval` : strings.toolApproval.message.replace("{toolName}", displayName);
1641
+ const runtimeMessage = pendingTools.find((t) => t.message)?.message;
1642
+ const message = runtimeMessage ? runtimeMessage : isBatch ? strings.toolApproval.batchMessage?.replace("{count}", String(toolCount)) ?? `${toolCount} actions are waiting for your approval` : strings.toolApproval.message.replace("{toolName}", displayName);
1645
1643
  const getToolDisplayName = (tool) => tool.annotations?.title || tool.toolCallName;
1646
1644
  return /* @__PURE__ */ jsxs7(
1647
1645
  "div",
@@ -3051,7 +3049,7 @@ function UseAIChat({ floating = false }) {
3051
3049
 
3052
3050
  // src/client.ts
3053
3051
  import { io } from "socket.io-client";
3054
- import { EventType as EventType2 } from "@meetsmore-oss/use-ai-core";
3052
+ import { EventType } from "@meetsmore-oss/use-ai-core";
3055
3053
  import { v4 as uuidv42 } from "uuid";
3056
3054
  var UseAIClient = class {
3057
3055
  /**
@@ -3146,7 +3144,7 @@ var UseAIClient = class {
3146
3144
  });
3147
3145
  }
3148
3146
  handleEvent(event) {
3149
- if (event.type === EventType2.RUN_STARTED) {
3147
+ if (event.type === EventType.RUN_STARTED) {
3150
3148
  this._currentAssistantMessage = {
3151
3149
  id: uuidv42(),
3152
3150
  role: "assistant",
@@ -3154,31 +3152,31 @@ var UseAIClient = class {
3154
3152
  };
3155
3153
  this._currentAssistantToolCalls = [];
3156
3154
  }
3157
- if (event.type === EventType2.TEXT_MESSAGE_START) {
3155
+ if (event.type === EventType.TEXT_MESSAGE_START) {
3158
3156
  const e = event;
3159
3157
  this._currentMessageId = e.messageId;
3160
3158
  this._currentMessageContent = "";
3161
- } else if (event.type === EventType2.TEXT_MESSAGE_CONTENT) {
3159
+ } else if (event.type === EventType.TEXT_MESSAGE_CONTENT) {
3162
3160
  const e = event;
3163
3161
  this._currentMessageContent += e.delta;
3164
- } else if (event.type === EventType2.TEXT_MESSAGE_END) {
3162
+ } else if (event.type === EventType.TEXT_MESSAGE_END) {
3165
3163
  if (this._currentAssistantMessage) {
3166
3164
  this._currentAssistantMessage.content = this._currentMessageContent;
3167
3165
  }
3168
3166
  this._currentMessageId = null;
3169
- } else if (event.type === EventType2.TOOL_CALL_START) {
3167
+ } else if (event.type === EventType.TOOL_CALL_START) {
3170
3168
  const e = event;
3171
3169
  this.currentToolCalls.set(e.toolCallId, {
3172
3170
  name: e.toolCallName,
3173
3171
  args: ""
3174
3172
  });
3175
- } else if (event.type === EventType2.TOOL_CALL_ARGS) {
3173
+ } else if (event.type === EventType.TOOL_CALL_ARGS) {
3176
3174
  const e = event;
3177
3175
  const toolCall = this.currentToolCalls.get(e.toolCallId);
3178
3176
  if (toolCall) {
3179
3177
  toolCall.args += e.delta;
3180
3178
  }
3181
- } else if (event.type === EventType2.TOOL_CALL_END) {
3179
+ } else if (event.type === EventType.TOOL_CALL_END) {
3182
3180
  const e = event;
3183
3181
  const toolCall = this.currentToolCalls.get(e.toolCallId);
3184
3182
  if (toolCall) {
@@ -3191,7 +3189,7 @@ var UseAIClient = class {
3191
3189
  }
3192
3190
  });
3193
3191
  }
3194
- } else if (event.type === EventType2.RUN_FINISHED) {
3192
+ } else if (event.type === EventType.RUN_FINISHED) {
3195
3193
  if (this._currentAssistantMessage) {
3196
3194
  const assistantMessage = {
3197
3195
  id: this._currentAssistantMessage.id,
@@ -3308,7 +3306,13 @@ var UseAIClient = class {
3308
3306
  messageId: uuidv42(),
3309
3307
  toolCallId,
3310
3308
  content: JSON.stringify(result),
3311
- role: "tool"
3309
+ role: "tool",
3310
+ // use-ai extension: include current tools and state for mid-run updates
3311
+ // (e.g., when navigation causes new components to mount)
3312
+ forwardedProps: {
3313
+ tools: this._tools,
3314
+ state: this._state
3315
+ }
3312
3316
  }
3313
3317
  };
3314
3318
  const toolResultMsg = {
@@ -3371,7 +3375,7 @@ var UseAIClient = class {
3371
3375
  */
3372
3376
  onTextMessage(handler) {
3373
3377
  return this.onEvent("text-message-handler", (event) => {
3374
- if (event.type === EventType2.TEXT_MESSAGE_END && this._currentMessageContent) {
3378
+ if (event.type === EventType.TEXT_MESSAGE_END && this._currentMessageContent) {
3375
3379
  handler(this._currentMessageContent);
3376
3380
  }
3377
3381
  });
@@ -3385,7 +3389,7 @@ var UseAIClient = class {
3385
3389
  */
3386
3390
  onToolCall(handler) {
3387
3391
  return this.onEvent("tool-call-handler", (event) => {
3388
- if (event.type === EventType2.TOOL_CALL_END) {
3392
+ if (event.type === EventType.TOOL_CALL_END) {
3389
3393
  const e = event;
3390
3394
  const toolCall = this.currentToolCalls.get(e.toolCallId);
3391
3395
  if (toolCall) {
@@ -3602,7 +3606,8 @@ function defineTool(description, schemaOrFn, fnOrOptions, options) {
3602
3606
  let actualFn;
3603
3607
  let actualOptions;
3604
3608
  if (isNoParamFunction) {
3605
- actualFn = schemaOrFn;
3609
+ const noParamFn = schemaOrFn;
3610
+ actualFn = (_input, ctx) => noParamFn(ctx);
3606
3611
  actualOptions = fnOrOptions || {};
3607
3612
  } else {
3608
3613
  actualFn = fnOrOptions;
@@ -3636,21 +3641,21 @@ function defineTool(description, schemaOrFn, fnOrOptions, options) {
3636
3641
  }
3637
3642
  return toolDef;
3638
3643
  },
3639
- async _execute(input) {
3644
+ async _execute(input, ctx) {
3640
3645
  const validated = this._zodSchema.parse(input);
3641
- return await actualFn(validated);
3646
+ return await actualFn(validated, ctx);
3642
3647
  }
3643
3648
  };
3644
3649
  }
3645
3650
  function convertToolsToDefinitions(tools) {
3646
3651
  return Object.entries(tools).map(([name, tool]) => tool._toToolDefinition(name));
3647
3652
  }
3648
- async function executeDefinedTool(tools, toolName, input) {
3653
+ async function executeDefinedTool(tools, toolName, input, ctx) {
3649
3654
  const tool = tools[toolName];
3650
3655
  if (!tool) {
3651
3656
  throw new Error(`Tool "${toolName}" not found`);
3652
3657
  }
3653
- return await tool._execute(input);
3658
+ return await tool._execute(input, ctx);
3654
3659
  }
3655
3660
 
3656
3661
  // src/providers/chatRepository/LocalStorageChatRepository.ts
@@ -3850,11 +3855,7 @@ function useChatManagement({
3850
3855
  clientRef,
3851
3856
  messages,
3852
3857
  setMessages,
3853
- onSendMessage,
3854
- setOpen,
3855
- connected,
3856
- loading,
3857
- hasPendingApproval
3858
+ connected
3858
3859
  }) {
3859
3860
  const [currentChatId, setCurrentChatId] = useState6(null);
3860
3861
  const [pendingChatId, setPendingChatId] = useState6(null);
@@ -3885,7 +3886,7 @@ function useChatManagement({
3885
3886
  const reloadMessages = useCallback4(async (chatId) => {
3886
3887
  const loadedMessages = await loadChatMessages(chatId);
3887
3888
  setMessages(loadedMessages);
3888
- }, [loadChatMessages]);
3889
+ }, [loadChatMessages, setMessages]);
3889
3890
  const createNewChat = useCallback4(async (options) => {
3890
3891
  console.log("[ChatManagement] createNewChat called - currentChatId:", currentChatId, "pendingChatId:", pendingChatId, "messages.length:", messages.length);
3891
3892
  if (pendingChatId && messages.length === 0) {
@@ -3906,7 +3907,7 @@ function useChatManagement({
3906
3907
  }
3907
3908
  console.log("[ChatManagement] Created pending chat:", chatId, "(will activate on first message)");
3908
3909
  return chatId;
3909
- }, [currentChatId, pendingChatId, messages, repository, clientRef]);
3910
+ }, [currentChatId, pendingChatId, messages, repository, clientRef, setMessages]);
3910
3911
  const loadChat = useCallback4(async (chatId) => {
3911
3912
  setPendingChatId(chatId);
3912
3913
  await reloadMessages(chatId);
@@ -3927,7 +3928,7 @@ function useChatManagement({
3927
3928
  setMessages([]);
3928
3929
  }
3929
3930
  console.log("[ChatManagement] Deleted chat:", chatId);
3930
- }, [currentChatId, pendingChatId, repository]);
3931
+ }, [currentChatId, pendingChatId, repository, setMessages]);
3931
3932
  const listChats = useCallback4(async () => {
3932
3933
  return await repository.listChats();
3933
3934
  }, [repository]);
@@ -3941,7 +3942,7 @@ function useChatManagement({
3941
3942
  console.log("[ChatManagement] Cleared current chat:", currentChatId);
3942
3943
  }
3943
3944
  }
3944
- }, [currentChatId, repository]);
3945
+ }, [currentChatId, repository, setMessages]);
3945
3946
  const getCurrentChat = useCallback4(async () => {
3946
3947
  const chatId = pendingChatId || currentChatId;
3947
3948
  if (!chatId) return null;
@@ -4068,76 +4069,8 @@ function useChatManagement({
4068
4069
  }
4069
4070
  })();
4070
4071
  }
4071
- }, [currentChatId, pendingChatId, createNewChat, repository, loadChatMessages, clientRef]);
4072
+ }, [currentChatId, pendingChatId, createNewChat, repository, loadChatMessages, clientRef, setMessages]);
4072
4073
  const displayedChatId = pendingChatId || currentChatId;
4073
- const pendingMessagesRef = useRef5([]);
4074
- const isProcessingQueueRef = useRef5(false);
4075
- const loadingRef = useRef5(loading);
4076
- useEffect5(() => {
4077
- loadingRef.current = loading;
4078
- }, [loading]);
4079
- const hasPendingApprovalRef = useRef5(hasPendingApproval);
4080
- useEffect5(() => {
4081
- hasPendingApprovalRef.current = hasPendingApproval;
4082
- }, [hasPendingApproval]);
4083
- const processMessageQueue = useCallback4(async () => {
4084
- if (isProcessingQueueRef.current || pendingMessagesRef.current.length === 0 || !onSendMessage) {
4085
- return;
4086
- }
4087
- isProcessingQueueRef.current = true;
4088
- while (pendingMessagesRef.current.length > 0) {
4089
- const { message, options } = pendingMessagesRef.current.shift();
4090
- const { newChat = false, attachments = [], openChat = true, metadata, forwardedProps } = options ?? {};
4091
- if (newChat) {
4092
- await createNewChat({ metadata });
4093
- }
4094
- const fileAttachments = await Promise.all(
4095
- attachments.map(async (file) => {
4096
- let preview;
4097
- if (file.type.startsWith("image/")) {
4098
- preview = await new Promise((resolve) => {
4099
- const reader = new FileReader();
4100
- reader.onload = () => resolve(typeof reader.result === "string" ? reader.result : void 0);
4101
- reader.onerror = () => resolve(void 0);
4102
- reader.readAsDataURL(file);
4103
- });
4104
- }
4105
- return {
4106
- id: crypto.randomUUID(),
4107
- file,
4108
- preview
4109
- };
4110
- })
4111
- );
4112
- await onSendMessage(message, fileAttachments.length > 0 ? fileAttachments : void 0, forwardedProps);
4113
- if (openChat && setOpen) {
4114
- setOpen(true);
4115
- }
4116
- await new Promise((resolve) => {
4117
- const checkReady = () => {
4118
- setTimeout(() => {
4119
- if (!loadingRef.current && !hasPendingApprovalRef.current) {
4120
- resolve();
4121
- } else {
4122
- checkReady();
4123
- }
4124
- }, 100);
4125
- };
4126
- checkReady();
4127
- });
4128
- }
4129
- isProcessingQueueRef.current = false;
4130
- }, [onSendMessage, createNewChat, setOpen]);
4131
- const sendMessage = useCallback4(async (message, options) => {
4132
- if (!onSendMessage) {
4133
- throw new Error("sendMessage is not available (onSendMessage callback not provided)");
4134
- }
4135
- if (!connected) {
4136
- throw new Error("Not connected to UseAI server");
4137
- }
4138
- pendingMessagesRef.current.push({ message, options });
4139
- await processMessageQueue();
4140
- }, [onSendMessage, connected, processMessageQueue]);
4141
4074
  return {
4142
4075
  currentChatId,
4143
4076
  pendingChatId,
@@ -4151,7 +4084,6 @@ function useChatManagement({
4151
4084
  saveUserMessage,
4152
4085
  saveAIResponse,
4153
4086
  reloadMessages,
4154
- sendMessage,
4155
4087
  getCurrentChat,
4156
4088
  updateMetadata,
4157
4089
  currentChatIdSnapshot,
@@ -4399,16 +4331,26 @@ function useCommandManagement({
4399
4331
  };
4400
4332
  }
4401
4333
 
4402
- // src/hooks/useToolRegistry.ts
4334
+ // src/hooks/useToolSystem.ts
4403
4335
  import { useState as useState9, useCallback as useCallback7, useRef as useRef7, useMemo as useMemo4 } from "react";
4404
- function useToolRegistry() {
4336
+ function useToolSystem({
4337
+ clientRef,
4338
+ buildState
4339
+ }) {
4405
4340
  const toolRegistryRef = useRef7(/* @__PURE__ */ new Map());
4406
4341
  const [toolRegistryVersion, setToolRegistryVersion] = useState9(0);
4407
4342
  const toolOwnershipRef = useRef7(/* @__PURE__ */ new Map());
4408
4343
  const invisibleRef = useRef7(/* @__PURE__ */ new Set());
4344
+ const readyStateRef = useRef7(/* @__PURE__ */ new Map());
4345
+ const readyListenersRef = useRef7(/* @__PURE__ */ new Set());
4346
+ const waitersRef = useRef7(/* @__PURE__ */ new Map());
4347
+ const [pendingApprovals, setPendingApprovals] = useState9([]);
4348
+ const pendingApprovalToolCallsRef = useRef7(/* @__PURE__ */ new Map());
4349
+ const runtimeApprovalResolversRef = useRef7(/* @__PURE__ */ new Map());
4409
4350
  const registerTools = useCallback7((id, tools, options) => {
4410
4351
  const existingTools = toolRegistryRef.current.get(id);
4411
4352
  toolRegistryRef.current.set(id, tools);
4353
+ readyStateRef.current.set(id, false);
4412
4354
  if (existingTools) {
4413
4355
  const existingKeys = Object.keys(existingTools).sort().join(",");
4414
4356
  const newKeys = Object.keys(tools).sort().join(",");
@@ -4427,6 +4369,13 @@ function useToolRegistry() {
4427
4369
  invisibleRef.current.delete(id);
4428
4370
  }
4429
4371
  }, []);
4372
+ const signalReady = useCallback7((id) => {
4373
+ if (!toolRegistryRef.current.has(id)) {
4374
+ return;
4375
+ }
4376
+ readyStateRef.current.set(id, true);
4377
+ readyListenersRef.current.forEach((listener) => listener());
4378
+ }, []);
4430
4379
  const unregisterTools = useCallback7((id) => {
4431
4380
  const tools = toolRegistryRef.current.get(id);
4432
4381
  if (tools) {
@@ -4435,8 +4384,10 @@ function useToolRegistry() {
4435
4384
  });
4436
4385
  }
4437
4386
  toolRegistryRef.current.delete(id);
4387
+ readyStateRef.current.delete(id);
4438
4388
  setToolRegistryVersion((v) => v + 1);
4439
4389
  invisibleRef.current.delete(id);
4390
+ readyListenersRef.current.forEach((listener) => listener());
4440
4391
  }, []);
4441
4392
  const isInvisible = useCallback7((id) => {
4442
4393
  return invisibleRef.current.has(id);
@@ -4451,14 +4402,187 @@ function useToolRegistry() {
4451
4402
  const hasTools = toolRegistryRef.current.size > 0;
4452
4403
  const aggregatedToolsRef = useRef7(aggregatedTools);
4453
4404
  aggregatedToolsRef.current = aggregatedTools;
4405
+ const waitForToolsToStabilize = useCallback7(async () => {
4406
+ const maxWaitMs = 500;
4407
+ const checkAllReady = () => {
4408
+ if (readyStateRef.current.size === 0) return true;
4409
+ for (const ready of readyStateRef.current.values()) {
4410
+ if (!ready) return false;
4411
+ }
4412
+ return true;
4413
+ };
4414
+ await new Promise((resolve) => setTimeout(resolve, 0));
4415
+ if (checkAllReady()) {
4416
+ return;
4417
+ }
4418
+ return new Promise((resolve) => {
4419
+ let safetyTimeout = null;
4420
+ let resolved = false;
4421
+ const cleanup = () => {
4422
+ if (resolved) return;
4423
+ resolved = true;
4424
+ if (safetyTimeout) clearTimeout(safetyTimeout);
4425
+ readyListenersRef.current.delete(onReadyChange);
4426
+ };
4427
+ const onReadyChange = () => {
4428
+ if (resolved) return;
4429
+ if (checkAllReady()) {
4430
+ cleanup();
4431
+ resolve();
4432
+ }
4433
+ };
4434
+ safetyTimeout = setTimeout(() => {
4435
+ cleanup();
4436
+ resolve();
4437
+ }, maxWaitMs);
4438
+ readyListenersRef.current.add(onReadyChange);
4439
+ onReadyChange();
4440
+ });
4441
+ }, []);
4442
+ const registerWaiter = useCallback7((id, waiter) => {
4443
+ waitersRef.current.set(id, waiter);
4444
+ }, []);
4445
+ const unregisterWaiter = useCallback7((id) => {
4446
+ waitersRef.current.delete(id);
4447
+ }, []);
4448
+ const getWaiter = useCallback7((id) => {
4449
+ return waitersRef.current.get(id);
4450
+ }, []);
4451
+ const handleApprovalRequest = useCallback7((event) => {
4452
+ console.log("[useToolSystem] Tool approval requested:", event.toolCallName, event.toolCallId);
4453
+ setPendingApprovals((prev) => [
4454
+ ...prev,
4455
+ {
4456
+ toolCallId: event.toolCallId,
4457
+ toolCallName: event.toolCallName,
4458
+ toolCallArgs: event.toolCallArgs,
4459
+ annotations: event.annotations,
4460
+ message: event.message,
4461
+ metadata: event.metadata
4462
+ }
4463
+ ]);
4464
+ }, []);
4465
+ const executeToolCall = useCallback7(async (toolCallId, name, input) => {
4466
+ const client = clientRef.current;
4467
+ if (!client) {
4468
+ console.error("[useToolSystem] No client available for tool execution");
4469
+ return;
4470
+ }
4471
+ try {
4472
+ const ownerId = toolOwnershipRef.current.get(name);
4473
+ console.log(`[useToolSystem] Tool "${name}" owned by component:`, ownerId);
4474
+ const ctx = {
4475
+ requestApproval: ({ message, metadata }) => {
4476
+ return new Promise((resolve) => {
4477
+ const approvalId = `${toolCallId}-runtime-${Date.now()}`;
4478
+ runtimeApprovalResolversRef.current.set(approvalId, resolve);
4479
+ setPendingApprovals((prev) => [
4480
+ ...prev,
4481
+ {
4482
+ toolCallId: approvalId,
4483
+ toolCallName: name,
4484
+ toolCallArgs: input || {},
4485
+ message,
4486
+ metadata
4487
+ }
4488
+ ]);
4489
+ });
4490
+ }
4491
+ };
4492
+ console.log("[useToolSystem] Executing tool...");
4493
+ const result = await executeDefinedTool(aggregatedToolsRef.current, name, input, ctx);
4494
+ const isErrorResult = result && typeof result === "object" && ("error" in result || result.success === false);
4495
+ const ownerIsInvisible = ownerId ? isInvisible(ownerId) : false;
4496
+ if (ownerId && !isErrorResult && !ownerIsInvisible) {
4497
+ const waiter = getWaiter(ownerId);
4498
+ if (waiter) {
4499
+ console.log(`[useToolSystem] Waiting for prompt change from ${ownerId}...`);
4500
+ await waiter();
4501
+ console.log("[useToolSystem] Prompt change wait complete");
4502
+ }
4503
+ } else if (isErrorResult) {
4504
+ console.log("[useToolSystem] Tool returned error, skipping prompt wait");
4505
+ } else if (ownerIsInvisible) {
4506
+ console.log("[useToolSystem] Component is invisible, skipping prompt wait");
4507
+ }
4508
+ console.log("[useToolSystem] Waiting for tools to stabilize...");
4509
+ await waitForToolsToStabilize();
4510
+ console.log("[useToolSystem] Tools stabilized");
4511
+ const updatedState = buildState();
4512
+ console.log(`[useToolSystem] Updated state (aggregated from all hooks)`);
4513
+ client.sendToolResponse(toolCallId, result, updatedState);
4514
+ } catch (err) {
4515
+ console.error("Tool execution error:", err);
4516
+ client.sendToolResponse(toolCallId, {
4517
+ error: err instanceof Error ? err.message : "Unknown error"
4518
+ });
4519
+ }
4520
+ }, [clientRef, isInvisible, getWaiter, waitForToolsToStabilize, buildState]);
4521
+ const storePendingToolCall = useCallback7((toolCallId, name, input, toolCallData) => {
4522
+ console.log(`[useToolSystem] Storing pending tool call "${name}" for approval`);
4523
+ pendingApprovalToolCallsRef.current.set(toolCallId, { name, input, toolCallData });
4524
+ }, []);
4525
+ const executePendingToolAfterApproval = useCallback7(async (toolCallId) => {
4526
+ const pendingTool = pendingApprovalToolCallsRef.current.get(toolCallId);
4527
+ if (!pendingTool) {
4528
+ console.warn(`[useToolSystem] No pending tool found for ${toolCallId}`);
4529
+ return;
4530
+ }
4531
+ pendingApprovalToolCallsRef.current.delete(toolCallId);
4532
+ await executeToolCall(toolCallId, pendingTool.name, pendingTool.input);
4533
+ }, [executeToolCall]);
4534
+ const approveAll = useCallback7(async () => {
4535
+ if (!clientRef.current) return;
4536
+ console.log("[useToolSystem] Approving all tool calls:", pendingApprovals.length);
4537
+ const pendingTools = [...pendingApprovals];
4538
+ setPendingApprovals([]);
4539
+ for (const pending of pendingTools) {
4540
+ const runtimeResolver = runtimeApprovalResolversRef.current.get(pending.toolCallId);
4541
+ if (runtimeResolver) {
4542
+ runtimeApprovalResolversRef.current.delete(pending.toolCallId);
4543
+ runtimeResolver({ approved: true });
4544
+ } else {
4545
+ clientRef.current.sendToolApprovalResponse(pending.toolCallId, true);
4546
+ await executePendingToolAfterApproval(pending.toolCallId);
4547
+ }
4548
+ }
4549
+ }, [clientRef, pendingApprovals, executePendingToolAfterApproval]);
4550
+ const rejectAll = useCallback7((reason) => {
4551
+ if (!clientRef.current) return;
4552
+ console.log("[useToolSystem] Rejecting all tool calls:", pendingApprovals.length, reason);
4553
+ const pendingTools = [...pendingApprovals];
4554
+ setPendingApprovals([]);
4555
+ for (const pending of pendingTools) {
4556
+ const runtimeResolver = runtimeApprovalResolversRef.current.get(pending.toolCallId);
4557
+ if (runtimeResolver) {
4558
+ runtimeApprovalResolversRef.current.delete(pending.toolCallId);
4559
+ runtimeResolver({ approved: false, reason });
4560
+ } else {
4561
+ clientRef.current.sendToolApprovalResponse(pending.toolCallId, false, reason);
4562
+ pendingApprovalToolCallsRef.current.delete(pending.toolCallId);
4563
+ }
4564
+ }
4565
+ }, [clientRef, pendingApprovals]);
4454
4566
  return {
4567
+ // Registry
4455
4568
  registerTools,
4456
4569
  unregisterTools,
4457
4570
  isInvisible,
4458
4571
  aggregatedTools,
4459
4572
  hasTools,
4460
4573
  aggregatedToolsRef,
4461
- toolOwnershipRef
4574
+ signalReady,
4575
+ toolRegistryVersion,
4576
+ // Waiters
4577
+ registerWaiter,
4578
+ unregisterWaiter,
4579
+ // Execution
4580
+ pendingApprovals,
4581
+ handleApprovalRequest,
4582
+ executeToolCall,
4583
+ storePendingToolCall,
4584
+ approveAll,
4585
+ rejectAll
4462
4586
  };
4463
4587
  }
4464
4588
 
@@ -4471,7 +4595,6 @@ function usePromptState({
4471
4595
  }) {
4472
4596
  const promptsRef = useRef8(/* @__PURE__ */ new Map());
4473
4597
  const suggestionsRef = useRef8(/* @__PURE__ */ new Map());
4474
- const waitersRef = useRef8(/* @__PURE__ */ new Map());
4475
4598
  const [suggestionsVersion, setSuggestionsVersion] = useState10(0);
4476
4599
  const buildStateFromPrompts = useCallback8(() => {
4477
4600
  const promptParts = [];
@@ -4508,15 +4631,6 @@ function usePromptState({
4508
4631
  clientRef.current.updateState(buildStateFromPrompts());
4509
4632
  }
4510
4633
  }, [buildStateFromPrompts, clientRef, connected]);
4511
- const registerWaiter = useCallback8((id, waiter) => {
4512
- waitersRef.current.set(id, waiter);
4513
- }, []);
4514
- const unregisterWaiter = useCallback8((id) => {
4515
- waitersRef.current.delete(id);
4516
- }, []);
4517
- const getWaiter = useCallback8((id) => {
4518
- return waitersRef.current.get(id);
4519
- }, []);
4520
4634
  const aggregatedSuggestions = useMemo5(() => {
4521
4635
  const allSuggestions = [];
4522
4636
  suggestionsRef.current.forEach((suggestions) => {
@@ -4526,11 +4640,8 @@ function usePromptState({
4526
4640
  }, [suggestionsVersion]);
4527
4641
  return {
4528
4642
  updatePrompt,
4529
- registerWaiter,
4530
- unregisterWaiter,
4531
- getWaiter,
4532
4643
  aggregatedSuggestions,
4533
- promptsRef
4644
+ buildStateFromPrompts
4534
4645
  };
4535
4646
  }
4536
4647
 
@@ -4596,116 +4707,190 @@ function useFeedback({
4596
4707
  };
4597
4708
  }
4598
4709
 
4599
- // src/hooks/useToolExecution.ts
4710
+ // src/hooks/useServerEvents.ts
4600
4711
  import { useState as useState12, useCallback as useCallback10, useRef as useRef10 } from "react";
4601
- function useToolExecution({
4602
- clientRef,
4603
- aggregatedToolsRef,
4604
- toolOwnershipRef,
4605
- promptsRef,
4606
- isInvisible,
4607
- getWaiter
4712
+
4713
+ // src/types.ts
4714
+ import { EventType as EventType2, ErrorCode, TOOL_APPROVAL_REQUEST } from "@meetsmore-oss/use-ai-core";
4715
+
4716
+ // src/hooks/useServerEvents.ts
4717
+ function useServerEvents({
4718
+ toolSystem,
4719
+ saveAIResponse,
4720
+ strings
4608
4721
  }) {
4609
- const [pendingApprovals, setPendingApprovals] = useState12([]);
4610
- const pendingApprovalToolCallsRef = useRef10(/* @__PURE__ */ new Map());
4611
- const handleApprovalRequest = useCallback10((event) => {
4612
- console.log("[useToolExecution] Tool approval requested:", event.toolCallName, event.toolCallId);
4613
- setPendingApprovals((prev) => [
4614
- ...prev,
4615
- {
4616
- toolCallId: event.toolCallId,
4617
- toolCallName: event.toolCallName,
4618
- toolCallArgs: event.toolCallArgs,
4619
- annotations: event.annotations
4722
+ const [loading, setLoading] = useState12(false);
4723
+ const [streamingText, setStreamingText] = useState12("");
4724
+ const streamingChatIdRef = useRef10(null);
4725
+ const [executingToolRaw, setExecutingTool] = useState12(null);
4726
+ const executingToolFallbackRef = useRef10(null);
4727
+ const clearStreamingText = useCallback10(() => {
4728
+ setStreamingText("");
4729
+ }, []);
4730
+ const toolSystemRef = useRef10(toolSystem);
4731
+ toolSystemRef.current = toolSystem;
4732
+ const saveAIResponseRef = useRef10(saveAIResponse);
4733
+ saveAIResponseRef.current = saveAIResponse;
4734
+ const stringsRef = useRef10(strings);
4735
+ stringsRef.current = strings;
4736
+ const handleServerEvent = useCallback10(async (client, event) => {
4737
+ const ts = toolSystemRef.current;
4738
+ const strs = stringsRef.current;
4739
+ if (event.type === EventType2.TOOL_CALL_START) {
4740
+ const e = event;
4741
+ const tool = ts.aggregatedToolsRef.current[e.toolCallName];
4742
+ const title = e.annotations?.title ?? tool?._options?.annotations?.title ?? null;
4743
+ if (!title) {
4744
+ const fallbacks = strs.toolExecution.fallbackMessages;
4745
+ executingToolFallbackRef.current = fallbacks[Math.floor(Math.random() * fallbacks.length)];
4620
4746
  }
4621
- ]);
4747
+ setExecutingTool({ toolCallId: e.toolCallId, title });
4748
+ } else if (event.type === EventType2.TOOL_CALL_END) {
4749
+ const toolCallEnd = event;
4750
+ const toolCallId = toolCallEnd.toolCallId;
4751
+ setExecutingTool((prev) => prev?.toolCallId === toolCallId ? null : prev);
4752
+ const toolCallData = client.currentToolCalls.get(toolCallId);
4753
+ if (!toolCallData) {
4754
+ console.error(`[ServerEvents] Tool call ${toolCallId} not found`);
4755
+ return;
4756
+ }
4757
+ const name = toolCallData.name;
4758
+ const input = JSON.parse(toolCallData.args);
4759
+ const tool = ts.aggregatedToolsRef.current[name];
4760
+ if (!tool) {
4761
+ console.log(`[ServerEvents] Tool "${name}" not found in useAI tools, skipping (likely a workflow tool)`);
4762
+ return;
4763
+ }
4764
+ if (tool._options?.annotations?.destructiveHint === true) {
4765
+ console.log(`[ServerEvents] Tool "${name}" requires approval, deferring execution`);
4766
+ ts.storePendingToolCall(toolCallId, name, input, toolCallData);
4767
+ return;
4768
+ }
4769
+ await ts.executeToolCall(toolCallId, name, input);
4770
+ } else if (event.type === TOOL_APPROVAL_REQUEST) {
4771
+ const e = event;
4772
+ ts.handleApprovalRequest(e);
4773
+ } else if (event.type === EventType2.TEXT_MESSAGE_CONTENT) {
4774
+ const contentEvent = event;
4775
+ setStreamingText((prev) => prev + contentEvent.delta);
4776
+ } else if (event.type === EventType2.TEXT_MESSAGE_END) {
4777
+ setStreamingText("");
4778
+ streamingChatIdRef.current = null;
4779
+ } else if (event.type === EventType2.RUN_FINISHED) {
4780
+ const content = client.currentMessageContent;
4781
+ if (content) {
4782
+ const finishedEvent = event;
4783
+ const traceId = finishedEvent.runId;
4784
+ saveAIResponseRef.current(content, void 0, traceId);
4785
+ }
4786
+ setLoading(false);
4787
+ } else if (event.type === EventType2.RUN_ERROR) {
4788
+ const errorEvent = event;
4789
+ const errorCode = errorEvent.message;
4790
+ console.error("[ServerEvents] Run error:", errorCode);
4791
+ const userMessage = strs.errors[errorCode] || strs.errors[ErrorCode.UNKNOWN_ERROR];
4792
+ saveAIResponseRef.current(userMessage, "error");
4793
+ setStreamingText("");
4794
+ streamingChatIdRef.current = null;
4795
+ setLoading(false);
4796
+ }
4622
4797
  }, []);
4623
- const executeToolCall = useCallback10(async (toolCallId, name, input) => {
4624
- const client = clientRef.current;
4625
- if (!client) {
4626
- console.error("[useToolExecution] No client available for tool execution");
4798
+ const executingTool = executingToolRaw ? {
4799
+ displayText: executingToolRaw.title ?? executingToolFallbackRef.current ?? strings.toolExecution.fallbackMessages[0]
4800
+ } : null;
4801
+ return {
4802
+ loading,
4803
+ setLoading,
4804
+ streamingText,
4805
+ clearStreamingText,
4806
+ executingTool,
4807
+ streamingChatIdRef,
4808
+ handleServerEvent
4809
+ };
4810
+ }
4811
+
4812
+ // src/hooks/useMessageQueue.ts
4813
+ import { useCallback as useCallback11, useRef as useRef11, useEffect as useEffect10 } from "react";
4814
+ function useMessageQueue({
4815
+ sendFn,
4816
+ createNewChat,
4817
+ setOpen,
4818
+ connected,
4819
+ loading,
4820
+ hasPendingApproval
4821
+ }) {
4822
+ const pendingMessagesRef = useRef11([]);
4823
+ const isProcessingQueueRef = useRef11(false);
4824
+ const sendFnRef = useRef11(sendFn);
4825
+ sendFnRef.current = sendFn;
4826
+ const createNewChatRef = useRef11(createNewChat);
4827
+ createNewChatRef.current = createNewChat;
4828
+ const setOpenRef = useRef11(setOpen);
4829
+ setOpenRef.current = setOpen;
4830
+ const loadingRef = useRef11(loading);
4831
+ useEffect10(() => {
4832
+ loadingRef.current = loading;
4833
+ }, [loading]);
4834
+ const hasPendingApprovalRef = useRef11(hasPendingApproval);
4835
+ useEffect10(() => {
4836
+ hasPendingApprovalRef.current = hasPendingApproval;
4837
+ }, [hasPendingApproval]);
4838
+ const processMessageQueue = useCallback11(async () => {
4839
+ if (isProcessingQueueRef.current || pendingMessagesRef.current.length === 0) {
4627
4840
  return;
4628
4841
  }
4629
- try {
4630
- const ownerId = toolOwnershipRef.current.get(name);
4631
- console.log(`[useToolExecution] Tool "${name}" owned by component:`, ownerId);
4632
- console.log("[useToolExecution] Executing tool...");
4633
- const result = await executeDefinedTool(aggregatedToolsRef.current, name, input);
4634
- const isErrorResult = result && typeof result === "object" && ("error" in result || result.success === false);
4635
- const ownerIsInvisible = ownerId ? isInvisible(ownerId) : false;
4636
- if (ownerId && !isErrorResult && !ownerIsInvisible) {
4637
- const waiter = getWaiter(ownerId);
4638
- if (waiter) {
4639
- console.log(`[useToolExecution] Waiting for prompt change from ${ownerId}...`);
4640
- await waiter();
4641
- console.log("[useToolExecution] Prompt change wait complete");
4642
- }
4643
- } else if (isErrorResult) {
4644
- console.log("[useToolExecution] Tool returned error, skipping prompt wait");
4645
- } else if (ownerIsInvisible) {
4646
- console.log("[useToolExecution] Component is invisible, skipping prompt wait");
4842
+ isProcessingQueueRef.current = true;
4843
+ while (pendingMessagesRef.current.length > 0) {
4844
+ const { message, options } = pendingMessagesRef.current.shift();
4845
+ const { newChat = false, attachments = [], openChat = true, metadata, forwardedProps } = options ?? {};
4846
+ if (newChat) {
4847
+ await createNewChatRef.current({ metadata });
4647
4848
  }
4648
- let updatedState = null;
4649
- if (ownerId) {
4650
- const prompt = promptsRef.current.get(ownerId);
4651
- if (prompt) {
4652
- updatedState = { context: prompt };
4653
- console.log(`[useToolExecution] Updated state from ${ownerId}`);
4654
- }
4849
+ const fileAttachments = await Promise.all(
4850
+ attachments.map(async (file) => {
4851
+ let preview;
4852
+ if (file.type.startsWith("image/")) {
4853
+ preview = await new Promise((resolve) => {
4854
+ const reader = new FileReader();
4855
+ reader.onload = () => resolve(typeof reader.result === "string" ? reader.result : void 0);
4856
+ reader.onerror = () => resolve(void 0);
4857
+ reader.readAsDataURL(file);
4858
+ });
4859
+ }
4860
+ return {
4861
+ id: crypto.randomUUID(),
4862
+ file,
4863
+ preview
4864
+ };
4865
+ })
4866
+ );
4867
+ await sendFnRef.current(message, fileAttachments.length > 0 ? fileAttachments : void 0, forwardedProps);
4868
+ if (openChat && setOpenRef.current) {
4869
+ setOpenRef.current(true);
4655
4870
  }
4656
- client.sendToolResponse(toolCallId, result, updatedState);
4657
- } catch (err) {
4658
- console.error("Tool execution error:", err);
4659
- client.sendToolResponse(toolCallId, {
4660
- error: err instanceof Error ? err.message : "Unknown error"
4871
+ await new Promise((resolve) => {
4872
+ const checkReady = () => {
4873
+ setTimeout(() => {
4874
+ if (!loadingRef.current && !hasPendingApprovalRef.current) {
4875
+ resolve();
4876
+ } else {
4877
+ checkReady();
4878
+ }
4879
+ }, 100);
4880
+ };
4881
+ checkReady();
4661
4882
  });
4662
4883
  }
4663
- }, [clientRef, aggregatedToolsRef, toolOwnershipRef, promptsRef, isInvisible, getWaiter]);
4664
- const storePendingToolCall = useCallback10((toolCallId, name, input, toolCallData) => {
4665
- console.log(`[useToolExecution] Storing pending tool call "${name}" for approval`);
4666
- pendingApprovalToolCallsRef.current.set(toolCallId, { name, input, toolCallData });
4884
+ isProcessingQueueRef.current = false;
4667
4885
  }, []);
4668
- const executePendingToolAfterApproval = useCallback10(async (toolCallId) => {
4669
- const pendingTool = pendingApprovalToolCallsRef.current.get(toolCallId);
4670
- if (!pendingTool) {
4671
- console.warn(`[useToolExecution] No pending tool found for ${toolCallId}`);
4672
- return;
4673
- }
4674
- pendingApprovalToolCallsRef.current.delete(toolCallId);
4675
- await executeToolCall(toolCallId, pendingTool.name, pendingTool.input);
4676
- }, [executeToolCall]);
4677
- const approveAll = useCallback10(async () => {
4678
- if (!clientRef.current) return;
4679
- console.log("[useToolExecution] Approving all tool calls:", pendingApprovals.length);
4680
- const pendingTools = [...pendingApprovals];
4681
- for (const pending of pendingTools) {
4682
- clientRef.current.sendToolApprovalResponse(pending.toolCallId, true);
4683
- }
4684
- setPendingApprovals([]);
4685
- for (const tool of pendingTools) {
4686
- await executePendingToolAfterApproval(tool.toolCallId);
4687
- }
4688
- }, [clientRef, pendingApprovals, executePendingToolAfterApproval]);
4689
- const rejectAll = useCallback10((reason) => {
4690
- if (!clientRef.current) return;
4691
- console.log("[useToolExecution] Rejecting all tool calls:", pendingApprovals.length, reason);
4692
- const pendingTools = [...pendingApprovals];
4693
- for (const pending of pendingTools) {
4694
- clientRef.current.sendToolApprovalResponse(pending.toolCallId, false, reason);
4695
- }
4696
- setPendingApprovals([]);
4697
- for (const tool of pendingTools) {
4698
- pendingApprovalToolCallsRef.current.delete(tool.toolCallId);
4886
+ const sendMessage = useCallback11(async (message, options) => {
4887
+ if (!connected) {
4888
+ throw new Error("Not connected to UseAI server");
4699
4889
  }
4700
- }, [clientRef, pendingApprovals]);
4701
- return {
4702
- pendingApprovals,
4703
- handleApprovalRequest,
4704
- executeToolCall,
4705
- storePendingToolCall,
4706
- approveAll,
4707
- rejectAll
4708
- };
4890
+ pendingMessagesRef.current.push({ message, options });
4891
+ await processMessageQueue();
4892
+ }, [connected, processMessageQueue]);
4893
+ return { sendMessage };
4709
4894
  }
4710
4895
 
4711
4896
  // src/providers/useAIProvider.tsx
@@ -4720,16 +4905,18 @@ var noOpContextValue = {
4720
4905
  register: () => {
4721
4906
  },
4722
4907
  unregister: () => {
4723
- }
4724
- },
4725
- prompts: {
4726
- update: () => {
4908
+ },
4909
+ signalReady: () => {
4727
4910
  },
4728
4911
  registerWaiter: () => {
4729
4912
  },
4730
4913
  unregisterWaiter: () => {
4731
4914
  }
4732
4915
  },
4916
+ prompts: {
4917
+ update: () => {
4918
+ }
4919
+ },
4733
4920
  chat: {
4734
4921
  currentId: null,
4735
4922
  create: async () => "",
@@ -4791,87 +4978,41 @@ function UseAIProvider({
4791
4978
  const strings = { ...defaultStrings, ...customStrings };
4792
4979
  const [connected, setConnected] = useState13(false);
4793
4980
  const [isChatOpen, setIsChatOpen] = useState13(false);
4794
- const [loading, setLoading] = useState13(false);
4795
4981
  const [messages, setMessages] = useState13([]);
4796
4982
  const [fileProcessingState, setFileProcessingState] = useState13(null);
4797
- const handleSetChatOpen = useCallback11((open) => {
4983
+ const handleSetChatOpen = useCallback12((open) => {
4798
4984
  setIsChatOpen(open);
4799
4985
  onOpenChange?.(open);
4800
4986
  }, [onOpenChange]);
4801
- const [streamingText, setStreamingText] = useState13("");
4802
- const streamingChatIdRef = useRef11(null);
4803
- const [executingTool, setExecutingTool] = useState13(null);
4804
- const executingToolFallbackRef = useRef11(null);
4805
- const clientRef = useRef11(null);
4806
- const repositoryRef = useRef11(
4987
+ const clientRef = useRef12(null);
4988
+ const repositoryRef = useRef12(
4807
4989
  chatRepository || new LocalStorageChatRepository()
4808
4990
  );
4809
- const handleSendMessageRef = useRef11(null);
4810
- const {
4811
- registerTools,
4812
- unregisterTools,
4813
- isInvisible,
4814
- aggregatedTools,
4815
- hasTools,
4816
- aggregatedToolsRef,
4817
- toolOwnershipRef
4818
- } = useToolRegistry();
4819
- const {
4820
- updatePrompt,
4821
- registerWaiter,
4822
- unregisterWaiter,
4823
- getWaiter,
4824
- aggregatedSuggestions,
4825
- promptsRef
4826
- } = usePromptState({
4991
+ const promptState = usePromptState({
4827
4992
  systemPrompt,
4828
4993
  clientRef,
4829
4994
  connected
4830
4995
  });
4831
- const stableSendMessage = useCallback11(async (message, attachments, forwardedProps) => {
4832
- if (handleSendMessageRef.current) {
4833
- await handleSendMessageRef.current(message, attachments, forwardedProps);
4834
- }
4835
- }, []);
4836
- const toolExecution = useToolExecution({
4996
+ const toolSystem = useToolSystem({
4837
4997
  clientRef,
4838
- aggregatedToolsRef,
4839
- toolOwnershipRef,
4840
- promptsRef,
4841
- isInvisible,
4842
- getWaiter
4998
+ buildState: promptState.buildStateFromPrompts
4843
4999
  });
4844
5000
  const chatManagement = useChatManagement({
4845
5001
  repository: repositoryRef.current,
4846
5002
  clientRef,
4847
5003
  messages,
4848
5004
  setMessages,
4849
- onSendMessage: stableSendMessage,
4850
- setOpen: handleSetChatOpen,
4851
- connected,
4852
- loading,
4853
- hasPendingApproval: toolExecution.pendingApprovals.length > 0
5005
+ connected
5006
+ });
5007
+ const serverEvents = useServerEvents({
5008
+ toolSystem,
5009
+ saveAIResponse: chatManagement.saveAIResponse,
5010
+ strings
4854
5011
  });
4855
- const {
4856
- currentChatId,
4857
- pendingChatId,
4858
- displayedChatId,
4859
- createNewChat,
4860
- loadChat,
4861
- deleteChat,
4862
- listChats,
4863
- clearCurrentChat,
4864
- activatePendingChat,
4865
- saveUserMessage,
4866
- saveAIResponse,
4867
- sendMessage,
4868
- getCurrentChat,
4869
- updateMetadata
4870
- } = chatManagement;
4871
5012
  const feedback = useFeedback({
4872
5013
  clientRef,
4873
5014
  repository: repositoryRef.current,
4874
- getDisplayedChatId: () => displayedChatId,
5015
+ getDisplayedChatId: () => chatManagement.displayedChatId,
4875
5016
  setMessages
4876
5017
  });
4877
5018
  const {
@@ -4887,7 +5028,9 @@ function UseAIProvider({
4887
5028
  renameCommand,
4888
5029
  deleteCommand
4889
5030
  } = useCommandManagement({ repository: commandRepository });
4890
- useEffect10(() => {
5031
+ const handleServerEventRef = useRef12(serverEvents.handleServerEvent);
5032
+ handleServerEventRef.current = serverEvents.handleServerEvent;
5033
+ useEffect11(() => {
4891
5034
  console.log("[UseAIProvider] Initializing client with serverUrl:", serverUrl);
4892
5035
  const client = new UseAIClient(serverUrl);
4893
5036
  const unsubscribeConnection = client.onConnectionStateChange((isConnected) => {
@@ -4897,64 +5040,7 @@ function UseAIProvider({
4897
5040
  console.log("[UseAIProvider] Connecting...");
4898
5041
  client.connect();
4899
5042
  const unsubscribe = client.onEvent("globalChat", async (event) => {
4900
- if (event.type === EventType.TOOL_CALL_START) {
4901
- const e = event;
4902
- const tool = aggregatedToolsRef.current[e.toolCallName];
4903
- const title = e.annotations?.title ?? tool?._options?.annotations?.title ?? null;
4904
- if (!title) {
4905
- const fallbacks = strings.toolExecution.fallbackMessages;
4906
- executingToolFallbackRef.current = fallbacks[Math.floor(Math.random() * fallbacks.length)];
4907
- }
4908
- setExecutingTool({ toolCallId: e.toolCallId, title });
4909
- } else if (event.type === EventType.TOOL_CALL_END) {
4910
- const toolCallEnd = event;
4911
- const toolCallId = toolCallEnd.toolCallId;
4912
- setExecutingTool((prev) => prev?.toolCallId === toolCallId ? null : prev);
4913
- const toolCallData = client["currentToolCalls"].get(toolCallId);
4914
- if (!toolCallData) {
4915
- console.error(`[Provider] Tool call ${toolCallId} not found`);
4916
- return;
4917
- }
4918
- const name = toolCallData.name;
4919
- const input = JSON.parse(toolCallData.args);
4920
- const tool = aggregatedToolsRef.current[name];
4921
- if (!tool) {
4922
- console.log(`[Provider] Tool "${name}" not found in useAI tools, skipping (likely a workflow tool)`);
4923
- return;
4924
- }
4925
- if (tool._options?.annotations?.destructiveHint === true) {
4926
- console.log(`[Provider] Tool "${name}" requires approval, deferring execution`);
4927
- toolExecution.storePendingToolCall(toolCallId, name, input, toolCallData);
4928
- return;
4929
- }
4930
- await toolExecution.executeToolCall(toolCallId, name, input);
4931
- } else if (event.type === TOOL_APPROVAL_REQUEST) {
4932
- const e = event;
4933
- toolExecution.handleApprovalRequest(e);
4934
- } else if (event.type === EventType.TEXT_MESSAGE_CONTENT) {
4935
- const contentEvent = event;
4936
- setStreamingText((prev) => prev + contentEvent.delta);
4937
- } else if (event.type === EventType.TEXT_MESSAGE_END) {
4938
- setStreamingText("");
4939
- streamingChatIdRef.current = null;
4940
- } else if (event.type === EventType.RUN_FINISHED) {
4941
- const content = client.currentMessageContent;
4942
- if (content) {
4943
- const finishedEvent = event;
4944
- const traceId = finishedEvent.runId;
4945
- saveAIResponse(content, void 0, traceId);
4946
- }
4947
- setLoading(false);
4948
- } else if (event.type === EventType.RUN_ERROR) {
4949
- const errorEvent = event;
4950
- const errorCode = errorEvent.message;
4951
- console.error("[Provider] Run error:", errorCode);
4952
- const userMessage = strings.errors[errorCode] || strings.errors[ErrorCode.UNKNOWN_ERROR];
4953
- saveAIResponse(userMessage, "error");
4954
- setStreamingText("");
4955
- streamingChatIdRef.current = null;
4956
- setLoading(false);
4957
- }
5043
+ await handleServerEventRef.current(client, event);
4958
5044
  });
4959
5045
  clientRef.current = client;
4960
5046
  return () => {
@@ -4963,11 +5049,11 @@ function UseAIProvider({
4963
5049
  client.disconnect();
4964
5050
  };
4965
5051
  }, [serverUrl]);
4966
- const lastRegisteredToolsRef = useRef11("");
4967
- useEffect10(() => {
5052
+ const lastRegisteredToolsRef = useRef12("");
5053
+ useEffect11(() => {
4968
5054
  const client = clientRef.current;
4969
- if (!client || !client.isConnected() || !hasTools) return;
4970
- const toolKeys = Object.keys(aggregatedTools).sort().join(",");
5055
+ if (!client || !client.isConnected() || !toolSystem.hasTools) return;
5056
+ const toolKeys = Object.keys(toolSystem.aggregatedTools).sort().join(",");
4971
5057
  if (toolKeys === lastRegisteredToolsRef.current) {
4972
5058
  console.log("[Provider] Skipping re-registration, tools unchanged");
4973
5059
  return;
@@ -4975,19 +5061,19 @@ function UseAIProvider({
4975
5061
  lastRegisteredToolsRef.current = toolKeys;
4976
5062
  console.log("[Provider] Registering tools:", toolKeys);
4977
5063
  try {
4978
- const toolDefinitions = convertToolsToDefinitions(aggregatedTools);
5064
+ const toolDefinitions = convertToolsToDefinitions(toolSystem.aggregatedTools);
4979
5065
  console.log(`[Provider] Registering ${toolDefinitions.length} tools`);
4980
5066
  client.registerTools(toolDefinitions);
4981
5067
  } catch (err) {
4982
5068
  console.error("Failed to register tools:", err);
4983
5069
  }
4984
- }, [hasTools, aggregatedTools, connected]);
4985
- const handleSendMessage = useCallback11(async (message, attachments, messageForwardedProps) => {
5070
+ }, [toolSystem.hasTools, toolSystem.aggregatedTools, connected]);
5071
+ const handleSendMessage = useCallback12(async (message, attachments, messageForwardedProps) => {
4986
5072
  if (!clientRef.current) return;
4987
- setStreamingText("");
4988
- const activatedChatId = activatePendingChat();
4989
- const activeChatId = activatedChatId || currentChatId;
4990
- streamingChatIdRef.current = activeChatId;
5073
+ serverEvents.clearStreamingText();
5074
+ const activatedChatId = chatManagement.activatePendingChat();
5075
+ const activeChatId = activatedChatId || chatManagement.currentChatId;
5076
+ serverEvents.streamingChatIdRef.current = activeChatId;
4991
5077
  let persistedContent = message;
4992
5078
  let multimodalContent;
4993
5079
  if (attachments && attachments.length > 0) {
@@ -5007,12 +5093,12 @@ function UseAIProvider({
5007
5093
  }
5008
5094
  persistedContent = persistedParts;
5009
5095
  if (activeChatId) {
5010
- await saveUserMessage(activeChatId, persistedContent);
5096
+ await chatManagement.saveUserMessage(activeChatId, persistedContent);
5011
5097
  }
5012
- setLoading(true);
5098
+ serverEvents.setLoading(true);
5013
5099
  try {
5014
5100
  const fileContent = await processAttachments(attachments, {
5015
- getCurrentChat,
5101
+ getCurrentChat: chatManagement.getCurrentChat,
5016
5102
  backend: fileUploadConfig?.backend,
5017
5103
  transformers: fileUploadConfig?.transformers,
5018
5104
  onFileProgress: (_fileId, state) => {
@@ -5025,16 +5111,16 @@ function UseAIProvider({
5025
5111
  }
5026
5112
  multimodalContent.push(...fileContent);
5027
5113
  } catch (error) {
5028
- setLoading(false);
5114
+ serverEvents.setLoading(false);
5029
5115
  throw error;
5030
5116
  } finally {
5031
5117
  setFileProcessingState(null);
5032
5118
  }
5033
5119
  } else {
5034
5120
  if (activeChatId) {
5035
- await saveUserMessage(activeChatId, persistedContent);
5121
+ await chatManagement.saveUserMessage(activeChatId, persistedContent);
5036
5122
  }
5037
- setLoading(true);
5123
+ serverEvents.setLoading(true);
5038
5124
  }
5039
5125
  const providerResult = forwardedPropsProvider ? forwardedPropsProvider() : {};
5040
5126
  const providerProps = providerResult instanceof Promise ? await providerResult : providerResult;
@@ -5047,31 +5133,39 @@ function UseAIProvider({
5047
5133
  multimodalContent,
5048
5134
  Object.keys(mergedForwardedProps).length > 0 ? mergedForwardedProps : void 0
5049
5135
  );
5050
- }, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig, getCurrentChat, forwardedPropsProvider]);
5051
- handleSendMessageRef.current = handleSendMessage;
5136
+ }, [chatManagement, serverEvents, fileUploadConfig, forwardedPropsProvider]);
5137
+ const messageQueue = useMessageQueue({
5138
+ sendFn: handleSendMessage,
5139
+ createNewChat: chatManagement.createNewChat,
5140
+ setOpen: handleSetChatOpen,
5141
+ connected,
5142
+ loading: serverEvents.loading,
5143
+ hasPendingApproval: toolSystem.pendingApprovals.length > 0
5144
+ });
5052
5145
  const value = {
5053
5146
  serverUrl,
5054
5147
  connected,
5055
5148
  client: clientRef.current,
5056
5149
  tools: {
5057
- register: registerTools,
5058
- unregister: unregisterTools
5150
+ register: toolSystem.registerTools,
5151
+ unregister: toolSystem.unregisterTools,
5152
+ signalReady: toolSystem.signalReady,
5153
+ registerWaiter: toolSystem.registerWaiter,
5154
+ unregisterWaiter: toolSystem.unregisterWaiter
5059
5155
  },
5060
5156
  prompts: {
5061
- update: updatePrompt,
5062
- registerWaiter,
5063
- unregisterWaiter
5157
+ update: promptState.updatePrompt
5064
5158
  },
5065
5159
  chat: {
5066
- currentId: currentChatId,
5067
- create: createNewChat,
5068
- load: loadChat,
5069
- delete: deleteChat,
5070
- list: listChats,
5071
- clear: clearCurrentChat,
5072
- sendMessage,
5073
- get: getCurrentChat,
5074
- updateMetadata
5160
+ currentId: chatManagement.currentChatId,
5161
+ create: chatManagement.createNewChat,
5162
+ load: chatManagement.loadChat,
5163
+ delete: chatManagement.deleteChat,
5164
+ list: chatManagement.listChats,
5165
+ clear: chatManagement.clearCurrentChat,
5166
+ sendMessage: messageQueue.sendMessage,
5167
+ get: chatManagement.getCurrentChat,
5168
+ updateMetadata: chatManagement.updateMetadata
5075
5169
  },
5076
5170
  agents: {
5077
5171
  available: availableAgents,
@@ -5087,26 +5181,23 @@ function UseAIProvider({
5087
5181
  delete: deleteCommand
5088
5182
  }
5089
5183
  };
5090
- const effectiveStreamingText = streamingChatIdRef.current === displayedChatId ? streamingText : "";
5091
- const executingToolDisplay = executingTool ? {
5092
- displayText: executingTool.title ?? executingToolFallbackRef.current ?? strings.toolExecution.fallbackMessages[0]
5093
- } : null;
5184
+ const effectiveStreamingText = serverEvents.streamingChatIdRef.current === chatManagement.displayedChatId ? serverEvents.streamingText : "";
5094
5185
  const chatUIContextValue = {
5095
5186
  connected,
5096
- loading,
5187
+ loading: serverEvents.loading,
5097
5188
  sendMessage: handleSendMessage,
5098
5189
  messages,
5099
5190
  streamingText: effectiveStreamingText,
5100
- suggestions: aggregatedSuggestions,
5191
+ suggestions: promptState.aggregatedSuggestions,
5101
5192
  fileUploadConfig,
5102
5193
  fileProcessing: fileProcessingState,
5103
5194
  history: {
5104
- currentId: displayedChatId,
5105
- create: createNewChat,
5106
- load: loadChat,
5107
- delete: deleteChat,
5108
- list: listChats,
5109
- get: getCurrentChat
5195
+ currentId: chatManagement.displayedChatId,
5196
+ create: chatManagement.createNewChat,
5197
+ load: chatManagement.loadChat,
5198
+ delete: chatManagement.deleteChat,
5199
+ list: chatManagement.listChats,
5200
+ get: chatManagement.getCurrentChat
5110
5201
  },
5111
5202
  agents: {
5112
5203
  available: availableAgents,
@@ -5125,11 +5216,11 @@ function UseAIProvider({
5125
5216
  setOpen: handleSetChatOpen
5126
5217
  },
5127
5218
  tools: {
5128
- executing: executingToolDisplay,
5219
+ executing: serverEvents.executingTool,
5129
5220
  pending: {
5130
- tools: toolExecution.pendingApprovals,
5131
- approveAll: toolExecution.approveAll,
5132
- rejectAll: toolExecution.rejectAll
5221
+ tools: toolSystem.pendingApprovals,
5222
+ approveAll: toolSystem.approveAll,
5223
+ rejectAll: toolSystem.rejectAll
5133
5224
  }
5134
5225
  },
5135
5226
  feedback: {
@@ -5143,15 +5234,15 @@ function UseAIProvider({
5143
5234
  const chatPanelProps = {
5144
5235
  onSendMessage: handleSendMessage,
5145
5236
  messages,
5146
- loading,
5237
+ loading: serverEvents.loading,
5147
5238
  connected,
5148
5239
  streamingText: effectiveStreamingText,
5149
- currentChatId: displayedChatId,
5150
- onNewChat: createNewChat,
5151
- onLoadChat: loadChat,
5152
- onDeleteChat: deleteChat,
5153
- onListChats: listChats,
5154
- suggestions: aggregatedSuggestions,
5240
+ currentChatId: chatManagement.displayedChatId,
5241
+ onNewChat: chatManagement.createNewChat,
5242
+ onLoadChat: chatManagement.loadChat,
5243
+ onDeleteChat: chatManagement.deleteChat,
5244
+ onListChats: chatManagement.listChats,
5245
+ suggestions: promptState.aggregatedSuggestions,
5155
5246
  availableAgents,
5156
5247
  defaultAgent,
5157
5248
  selectedAgent,
@@ -5162,12 +5253,12 @@ function UseAIProvider({
5162
5253
  onSaveCommand: saveCommand,
5163
5254
  onRenameCommand: renameCommand,
5164
5255
  onDeleteCommand: deleteCommand,
5165
- executingTool: executingToolDisplay,
5256
+ executingTool: serverEvents.executingTool,
5166
5257
  feedbackEnabled: feedback.enabled,
5167
5258
  onFeedback: feedback.submitFeedback,
5168
- pendingApprovals: toolExecution.pendingApprovals,
5169
- onApproveToolCall: toolExecution.pendingApprovals.length > 0 ? toolExecution.approveAll : void 0,
5170
- onRejectToolCall: toolExecution.pendingApprovals.length > 0 ? toolExecution.rejectAll : void 0
5259
+ pendingApprovals: toolSystem.pendingApprovals,
5260
+ onApproveToolCall: toolSystem.pendingApprovals.length > 0 ? toolSystem.approveAll : void 0,
5261
+ onRejectToolCall: toolSystem.pendingApprovals.length > 0 ? toolSystem.rejectAll : void 0
5171
5262
  };
5172
5263
  const renderDefaultChat = () => {
5173
5264
  if (isUIDisabled) return null;
@@ -5188,9 +5279,9 @@ function UseAIProvider({
5188
5279
  onClose: () => handleSetChatOpen(false),
5189
5280
  onSendMessage: handleSendMessage,
5190
5281
  messages,
5191
- loading,
5282
+ loading: serverEvents.loading,
5192
5283
  connected,
5193
- suggestions: aggregatedSuggestions,
5284
+ suggestions: promptState.aggregatedSuggestions,
5194
5285
  availableAgents,
5195
5286
  defaultAgent,
5196
5287
  selectedAgent,
@@ -5231,11 +5322,11 @@ function useAIContext() {
5231
5322
  }
5232
5323
 
5233
5324
  // src/hooks/useStableTools.ts
5234
- import { useRef as useRef12 } from "react";
5325
+ import { useRef as useRef13 } from "react";
5235
5326
  function useStableTools(tools) {
5236
- const latestToolsRef = useRef12({});
5237
- const stableToolsRef = useRef12({});
5238
- const prevToolNamesRef = useRef12("");
5327
+ const latestToolsRef = useRef13({});
5328
+ const stableToolsRef = useRef13({});
5329
+ const prevToolNamesRef = useRef13("");
5239
5330
  if (!tools) {
5240
5331
  latestToolsRef.current = {};
5241
5332
  return void 0;
@@ -5266,19 +5357,19 @@ function useStableTools(tools) {
5266
5357
  return stableToolsRef.current;
5267
5358
  }
5268
5359
  function createStableToolWrapper(name, tool, latestToolsRef) {
5269
- const stableHandler = (input) => {
5360
+ const stableHandler = (input, ctx) => {
5270
5361
  const currentTool = latestToolsRef.current[name];
5271
5362
  if (!currentTool) {
5272
5363
  throw new Error(`Tool "${name}" no longer exists`);
5273
5364
  }
5274
- return currentTool.fn(input);
5365
+ return currentTool.fn(input, ctx);
5275
5366
  };
5276
- const stableExecute = async (input) => {
5367
+ const stableExecute = async (input, ctx) => {
5277
5368
  const currentTool = latestToolsRef.current[name];
5278
5369
  if (!currentTool) {
5279
5370
  throw new Error(`Tool "${name}" no longer exists`);
5280
5371
  }
5281
- return await currentTool._execute(input);
5372
+ return await currentTool._execute(input, ctx);
5282
5373
  };
5283
5374
  return {
5284
5375
  description: tool.description,
@@ -5303,27 +5394,27 @@ function namespaceTools(tools, namespace) {
5303
5394
  function useAI(options = {}) {
5304
5395
  const { enabled = true } = options;
5305
5396
  const { connected, tools, client, prompts } = useAIContext();
5306
- const { register: registerTools, unregister: unregisterTools } = tools;
5307
- const { update: updatePrompt, registerWaiter, unregisterWaiter } = prompts;
5397
+ const { register: registerTools, unregister: unregisterTools, signalReady, registerWaiter, unregisterWaiter } = tools;
5398
+ const { update: updatePrompt } = prompts;
5308
5399
  const [response, setResponse] = useState14(null);
5309
5400
  const [loading, setLoading] = useState14(false);
5310
5401
  const [error, setError] = useState14(null);
5311
- const hookId = useRef13(`useAI-${Math.random().toString(36).substr(2, 9)}`);
5312
- const toolsRef = useRef13({});
5313
- const componentRef = useRef13(null);
5314
- const promptChangeResolvers = useRef13([]);
5402
+ const hookId = useRef14(`useAI-${Math.random().toString(36).substr(2, 9)}`);
5403
+ const toolsRef = useRef14({});
5404
+ const componentRef = useRef14(null);
5405
+ const promptChangeResolvers = useRef14([]);
5315
5406
  const stableTools = useStableTools(options.tools);
5316
5407
  const toolsKey = useMemo6(() => {
5317
5408
  if (!options.tools) return "";
5318
5409
  return Object.keys(options.tools).sort().join(",");
5319
5410
  }, [options.tools]);
5320
5411
  const memoizedSuggestions = useMemo6(() => options.suggestions, [options.suggestions]);
5321
- useEffect11(() => {
5412
+ useEffect12(() => {
5322
5413
  if (componentRef.current) {
5323
5414
  componentRef.current.setAttribute("data-useai-context", "true");
5324
5415
  }
5325
5416
  }, []);
5326
- const waitForPromptChange = useCallback12(() => {
5417
+ const waitForPromptChange = useCallback13(() => {
5327
5418
  return new Promise((resolve) => {
5328
5419
  const timeoutMs = 100;
5329
5420
  const timeoutId = setTimeout(() => {
@@ -5340,14 +5431,14 @@ function useAI(options = {}) {
5340
5431
  promptChangeResolvers.current.push(resolveAndCleanup);
5341
5432
  });
5342
5433
  }, []);
5343
- useEffect11(() => {
5434
+ useEffect12(() => {
5344
5435
  if (!enabled || options.invisible) return;
5345
5436
  registerWaiter(hookId.current, waitForPromptChange);
5346
5437
  return () => {
5347
5438
  unregisterWaiter(hookId.current);
5348
5439
  };
5349
5440
  }, [enabled, options.invisible, registerWaiter, unregisterWaiter, waitForPromptChange]);
5350
- useEffect11(() => {
5441
+ useEffect12(() => {
5351
5442
  if (!enabled) return;
5352
5443
  updatePrompt(hookId.current, options.prompt, memoizedSuggestions);
5353
5444
  if (promptChangeResolvers.current.length > 0) {
@@ -5355,29 +5446,30 @@ function useAI(options = {}) {
5355
5446
  promptChangeResolvers.current = [];
5356
5447
  }
5357
5448
  }, [enabled, options.prompt, memoizedSuggestions, updatePrompt]);
5358
- const updatePromptRef = useRef13(updatePrompt);
5449
+ const updatePromptRef = useRef14(updatePrompt);
5359
5450
  updatePromptRef.current = updatePrompt;
5360
- useEffect11(() => {
5451
+ useEffect12(() => {
5361
5452
  const id = hookId.current;
5362
5453
  return () => {
5363
5454
  updatePromptRef.current(id, void 0, void 0);
5364
5455
  };
5365
5456
  }, []);
5366
- useEffect11(() => {
5457
+ useLayoutEffect(() => {
5367
5458
  if (!enabled) return;
5368
5459
  if (stableTools) {
5369
5460
  const componentId = options.id || componentRef.current?.id;
5370
5461
  const toolsToRegister = componentId ? namespaceTools(stableTools, componentId) : stableTools;
5371
5462
  registerTools(hookId.current, toolsToRegister, { invisible: options.invisible });
5372
5463
  toolsRef.current = toolsToRegister;
5464
+ signalReady(hookId.current);
5373
5465
  }
5374
5466
  return () => {
5375
5467
  if (stableTools) {
5376
5468
  unregisterTools(hookId.current);
5377
5469
  }
5378
5470
  };
5379
- }, [enabled, toolsKey, stableTools, options.id, options.invisible, registerTools, unregisterTools]);
5380
- useEffect11(() => {
5471
+ }, [enabled, toolsKey, stableTools, options.id, options.invisible, registerTools, unregisterTools, signalReady]);
5472
+ useEffect12(() => {
5381
5473
  if (!enabled || !client) return;
5382
5474
  const unsubscribe = client.onEvent(hookId.current, (event) => {
5383
5475
  handleAGUIEvent(event);
@@ -5386,9 +5478,9 @@ function useAI(options = {}) {
5386
5478
  unsubscribe();
5387
5479
  };
5388
5480
  }, [enabled, client]);
5389
- const handleAGUIEvent = useCallback12(async (event) => {
5481
+ const handleAGUIEvent = useCallback13(async (event) => {
5390
5482
  switch (event.type) {
5391
- case EventType.TEXT_MESSAGE_END: {
5483
+ case EventType2.TEXT_MESSAGE_END: {
5392
5484
  const content = client?.currentMessageContent;
5393
5485
  if (content) {
5394
5486
  setResponse(content);
@@ -5396,7 +5488,7 @@ function useAI(options = {}) {
5396
5488
  }
5397
5489
  break;
5398
5490
  }
5399
- case EventType.RUN_ERROR: {
5491
+ case EventType2.RUN_ERROR: {
5400
5492
  const errorEvent = event;
5401
5493
  const error2 = new Error(errorEvent.message);
5402
5494
  setError(error2);
@@ -5406,7 +5498,7 @@ function useAI(options = {}) {
5406
5498
  }
5407
5499
  }
5408
5500
  }, [client, options.onError]);
5409
- const generate = useCallback12(async (prompt) => {
5501
+ const generate = useCallback13(async (prompt) => {
5410
5502
  if (!enabled) {
5411
5503
  const error2 = new Error("AI features are disabled");
5412
5504
  setError(error2);
@@ -5442,7 +5534,7 @@ function useAI(options = {}) {
5442
5534
  }
5443
5535
 
5444
5536
  // src/useAIWorkflow.ts
5445
- import { useState as useState15, useCallback as useCallback13, useRef as useRef14, useEffect as useEffect12 } from "react";
5537
+ import { useState as useState15, useCallback as useCallback14, useRef as useRef15, useEffect as useEffect13 } from "react";
5446
5538
  import { EventType as EventType3 } from "@meetsmore-oss/use-ai-core";
5447
5539
  import { v4 as uuidv43 } from "uuid";
5448
5540
  function useAIWorkflow(runner, workflowId) {
@@ -5450,9 +5542,9 @@ function useAIWorkflow(runner, workflowId) {
5450
5542
  const [status, setStatus] = useState15("idle");
5451
5543
  const [text, setText] = useState15(null);
5452
5544
  const [error, setError] = useState15(null);
5453
- const currentWorkflowRef = useRef14(null);
5454
- const eventListenerIdRef = useRef14(`useAIWorkflow-${Math.random().toString(36).substr(2, 9)}`);
5455
- const handleWorkflowEvent = useCallback13(async (event) => {
5545
+ const currentWorkflowRef = useRef15(null);
5546
+ const eventListenerIdRef = useRef15(`useAIWorkflow-${Math.random().toString(36).substr(2, 9)}`);
5547
+ const handleWorkflowEvent = useCallback14(async (event) => {
5456
5548
  const currentWorkflow = currentWorkflowRef.current;
5457
5549
  if (!currentWorkflow) return;
5458
5550
  if (event.type === EventType3.RUN_STARTED) {
@@ -5485,7 +5577,10 @@ function useAIWorkflow(runner, workflowId) {
5485
5577
  console.log(`[useAIWorkflow] Executing tool: ${toolName}`, toolArgs);
5486
5578
  console.log(`[useAIWorkflow] Available tools:`, Object.keys(currentWorkflow.tools));
5487
5579
  try {
5488
- const result = await executeDefinedTool(currentWorkflow.tools, toolName, toolArgs);
5580
+ const noopCtx = {
5581
+ requestApproval: async () => ({ approved: true })
5582
+ };
5583
+ const result = await executeDefinedTool(currentWorkflow.tools, toolName, toolArgs, noopCtx);
5489
5584
  currentWorkflow.toolCalls.push({
5490
5585
  toolName,
5491
5586
  args: toolArgs,
@@ -5537,14 +5632,14 @@ function useAIWorkflow(runner, workflowId) {
5537
5632
  }
5538
5633
  }
5539
5634
  }, [client]);
5540
- useEffect12(() => {
5635
+ useEffect13(() => {
5541
5636
  if (!client) return;
5542
5637
  const unsubscribe = client.onEvent(eventListenerIdRef.current, handleWorkflowEvent);
5543
5638
  return () => {
5544
5639
  unsubscribe();
5545
5640
  };
5546
5641
  }, [client, handleWorkflowEvent]);
5547
- const trigger = useCallback13(async (options) => {
5642
+ const trigger = useCallback14(async (options) => {
5548
5643
  if (!client?.isConnected()) {
5549
5644
  const err = new Error("Not connected to server");
5550
5645
  setError(err);
@@ -5635,12 +5730,14 @@ export {
5635
5730
  useDropdownState,
5636
5731
  useFeedback,
5637
5732
  useFileUpload,
5733
+ useMessageQueue,
5638
5734
  usePromptState,
5735
+ useServerEvents,
5639
5736
  useSlashCommands,
5640
5737
  useStableTools,
5641
5738
  useStrings,
5642
5739
  useTheme,
5643
- useToolRegistry,
5740
+ useToolSystem,
5644
5741
  validateCommandName,
5645
5742
  z2 as z
5646
5743
  };