@yourgpt/copilot-sdk 2.1.5-alpha.4 → 2.1.5-alpha.6

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.
Files changed (102) hide show
  1. package/dist/{MessageTree-CSIHErPK.d.ts → MessageTree-Clhiv_k2.d.ts} +4 -3
  2. package/dist/{MessageTree-B0JGQOCi.d.cts → MessageTree-Dt9qfJ55.d.cts} +4 -3
  3. package/dist/{chunk-XUR3IOPX.cjs → chunk-2QLF7XM7.cjs} +1557 -3120
  4. package/dist/chunk-2QLF7XM7.cjs.map +1 -0
  5. package/dist/{chunk-NUXLAZOE.cjs → chunk-3ZDRX7J2.cjs} +2 -2
  6. package/dist/{chunk-NUXLAZOE.cjs.map → chunk-3ZDRX7J2.cjs.map} +1 -1
  7. package/dist/{chunk-RKGRQRZU.js → chunk-533K2Z7C.js} +4 -4
  8. package/dist/{chunk-RKGRQRZU.js.map → chunk-533K2Z7C.js.map} +1 -1
  9. package/dist/chunk-5EGBIQYS.cjs +292 -0
  10. package/dist/chunk-5EGBIQYS.cjs.map +1 -0
  11. package/dist/{chunk-3AONOZLY.js → chunk-AIVXGTWS.js} +2 -2
  12. package/dist/chunk-AIVXGTWS.js.map +1 -0
  13. package/dist/{chunk-LLM7AHMO.js → chunk-DDZLRCVX.js} +2 -2
  14. package/dist/{chunk-LLM7AHMO.js.map → chunk-DDZLRCVX.js.map} +1 -1
  15. package/dist/{chunk-FLZO2FO3.js → chunk-I2XOCFHG.js} +1558 -3071
  16. package/dist/chunk-I2XOCFHG.js.map +1 -0
  17. package/dist/{chunk-EEH3L64W.js → chunk-PSNLKMZH.js} +73 -11
  18. package/dist/chunk-PSNLKMZH.js.map +1 -0
  19. package/dist/chunk-PURFAD2P.js +2020 -0
  20. package/dist/chunk-PURFAD2P.js.map +1 -0
  21. package/dist/chunk-QTGEEBRW.cjs +2077 -0
  22. package/dist/chunk-QTGEEBRW.cjs.map +1 -0
  23. package/dist/{chunk-TPB7XED6.cjs → chunk-TPDMBDQX.cjs} +2 -2
  24. package/dist/chunk-TPDMBDQX.cjs.map +1 -0
  25. package/dist/chunk-TXQ37MAO.js +287 -0
  26. package/dist/chunk-TXQ37MAO.js.map +1 -0
  27. package/dist/{chunk-B4YDIMP3.cjs → chunk-VION33GW.cjs} +92 -30
  28. package/dist/chunk-VION33GW.cjs.map +1 -0
  29. package/dist/{chunk-MDS23G2S.cjs → chunk-Y2A6AMGO.cjs} +10 -10
  30. package/dist/{chunk-MDS23G2S.cjs.map → chunk-Y2A6AMGO.cjs.map} +1 -1
  31. package/dist/core/index.cjs +93 -93
  32. package/dist/core/index.d.cts +3 -3
  33. package/dist/core/index.d.ts +3 -3
  34. package/dist/core/index.js +5 -5
  35. package/dist/experimental/index.cjs +644 -0
  36. package/dist/experimental/index.cjs.map +1 -0
  37. package/dist/experimental/index.d.cts +924 -0
  38. package/dist/experimental/index.d.ts +924 -0
  39. package/dist/experimental/index.js +611 -0
  40. package/dist/experimental/index.js.map +1 -0
  41. package/dist/{index-D7169xuR.d.ts → index-D8zza1Q8.d.ts} +1 -1
  42. package/dist/{index-CzJB8Ddo.d.cts → index-DCVjTdIZ.d.cts} +1 -1
  43. package/dist/mcp/index.d.cts +3 -3
  44. package/dist/mcp/index.d.ts +3 -3
  45. package/dist/react/index.cjs +140 -123
  46. package/dist/react/index.d.cts +378 -10
  47. package/dist/react/index.d.ts +378 -10
  48. package/dist/react/index.js +7 -6
  49. package/dist/styles.css +45 -0
  50. package/dist/tools/anthropic/index.cjs +3 -3
  51. package/dist/tools/anthropic/index.d.cts +1 -1
  52. package/dist/tools/anthropic/index.d.ts +1 -1
  53. package/dist/tools/anthropic/index.js +2 -2
  54. package/dist/tools/brave/index.cjs +6 -6
  55. package/dist/tools/brave/index.d.cts +1 -1
  56. package/dist/tools/brave/index.d.ts +1 -1
  57. package/dist/tools/brave/index.js +3 -3
  58. package/dist/tools/exa/index.cjs +6 -6
  59. package/dist/tools/exa/index.d.cts +1 -1
  60. package/dist/tools/exa/index.d.ts +1 -1
  61. package/dist/tools/exa/index.js +3 -3
  62. package/dist/tools/google/index.cjs +6 -6
  63. package/dist/tools/google/index.d.cts +1 -1
  64. package/dist/tools/google/index.d.ts +1 -1
  65. package/dist/tools/google/index.js +4 -4
  66. package/dist/tools/openai/index.cjs +6 -6
  67. package/dist/tools/openai/index.d.cts +1 -1
  68. package/dist/tools/openai/index.d.ts +1 -1
  69. package/dist/tools/openai/index.js +3 -3
  70. package/dist/tools/searxng/index.cjs +6 -6
  71. package/dist/tools/searxng/index.d.cts +1 -1
  72. package/dist/tools/searxng/index.d.ts +1 -1
  73. package/dist/tools/searxng/index.js +3 -3
  74. package/dist/tools/serper/index.cjs +6 -6
  75. package/dist/tools/serper/index.d.cts +1 -1
  76. package/dist/tools/serper/index.d.ts +1 -1
  77. package/dist/tools/serper/index.js +3 -3
  78. package/dist/tools/tavily/index.cjs +6 -6
  79. package/dist/tools/tavily/index.d.cts +1 -1
  80. package/dist/tools/tavily/index.d.ts +1 -1
  81. package/dist/tools/tavily/index.js +3 -3
  82. package/dist/tools/web-search/index.cjs +7 -7
  83. package/dist/tools/web-search/index.d.cts +2 -2
  84. package/dist/tools/web-search/index.d.ts +2 -2
  85. package/dist/tools/web-search/index.js +4 -4
  86. package/dist/{tools-tmksfhUo.d.cts → tools-DcS6Aeao.d.cts} +7 -3
  87. package/dist/{tools-tmksfhUo.d.ts → tools-DcS6Aeao.d.ts} +7 -3
  88. package/dist/{types-BqwW3Baj.d.ts → types-BUYni9B8.d.ts} +1 -1
  89. package/dist/{types-BLw7mxtW.d.cts → types-Cvg4DUoc.d.cts} +1 -1
  90. package/dist/ui/index.cjs +1297 -596
  91. package/dist/ui/index.cjs.map +1 -1
  92. package/dist/ui/index.d.cts +136 -9
  93. package/dist/ui/index.d.ts +136 -9
  94. package/dist/ui/index.js +1128 -436
  95. package/dist/ui/index.js.map +1 -1
  96. package/package.json +6 -1
  97. package/dist/chunk-3AONOZLY.js.map +0 -1
  98. package/dist/chunk-B4YDIMP3.cjs.map +0 -1
  99. package/dist/chunk-EEH3L64W.js.map +0 -1
  100. package/dist/chunk-FLZO2FO3.js.map +0 -1
  101. package/dist/chunk-TPB7XED6.cjs.map +0 -1
  102. package/dist/chunk-XUR3IOPX.cjs.map +0 -1
@@ -0,0 +1,2077 @@
1
+ 'use strict';
2
+
3
+ var chunk2QLF7XM7_cjs = require('./chunk-2QLF7XM7.cjs');
4
+ var chunkVION33GW_cjs = require('./chunk-VION33GW.cjs');
5
+ var react = require('react');
6
+ var z = require('zod');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var z__namespace = /*#__PURE__*/_interopNamespace(z);
27
+
28
+ function useAIActions(actions) {
29
+ const { registerAction, unregisterAction } = chunk2QLF7XM7_cjs.useCopilot();
30
+ react.useEffect(() => {
31
+ for (const action of actions) {
32
+ registerAction(action);
33
+ }
34
+ return () => {
35
+ for (const action of actions) {
36
+ unregisterAction(action.name);
37
+ }
38
+ };
39
+ }, [actions, registerAction, unregisterAction]);
40
+ }
41
+ function useAIAction(action) {
42
+ useAIActions([action]);
43
+ }
44
+ function useAITools(options = {}) {
45
+ const {
46
+ screenshot = false,
47
+ console: consoleCapture = false,
48
+ network = false,
49
+ requireConsent = true,
50
+ screenshotOptions,
51
+ consoleOptions,
52
+ networkOptions,
53
+ onConsentRequest,
54
+ autoStart = true
55
+ } = options;
56
+ const [isEnabled] = react.useState(screenshot || consoleCapture || network);
57
+ const [activeCaptures, setActiveCaptures] = react.useState({
58
+ console: false,
59
+ network: false
60
+ });
61
+ const [pendingConsent, setPendingConsent] = react.useState(null);
62
+ const consentResolverRef = react.useRef(null);
63
+ const rememberedConsentRef = react.useRef(/* @__PURE__ */ new Set());
64
+ react.useEffect(() => {
65
+ if (!autoStart || !isEnabled) return;
66
+ if (consoleCapture && !chunkVION33GW_cjs.isConsoleCaptureActive()) {
67
+ chunkVION33GW_cjs.startConsoleCapture(consoleOptions);
68
+ setActiveCaptures((prev) => ({ ...prev, console: true }));
69
+ }
70
+ if (network && !chunkVION33GW_cjs.isNetworkCaptureActive()) {
71
+ chunkVION33GW_cjs.startNetworkCapture(networkOptions);
72
+ setActiveCaptures((prev) => ({ ...prev, network: true }));
73
+ }
74
+ return () => {
75
+ chunkVION33GW_cjs.stopConsoleCapture();
76
+ chunkVION33GW_cjs.stopNetworkCapture();
77
+ };
78
+ }, [
79
+ autoStart,
80
+ isEnabled,
81
+ consoleCapture,
82
+ network,
83
+ consoleOptions,
84
+ networkOptions
85
+ ]);
86
+ const captureScreenshotFn = react.useCallback(
87
+ async (opts) => {
88
+ if (!screenshot) {
89
+ throw new Error("Screenshot capture is not enabled");
90
+ }
91
+ if (!chunkVION33GW_cjs.isScreenshotSupported()) {
92
+ throw new Error(
93
+ "Screenshot capture is not supported in this environment"
94
+ );
95
+ }
96
+ return chunkVION33GW_cjs.captureScreenshot({ ...screenshotOptions, ...opts });
97
+ },
98
+ [screenshot, screenshotOptions]
99
+ );
100
+ const getConsoleLogsFn = react.useCallback(
101
+ (opts) => {
102
+ if (!consoleCapture) {
103
+ return { logs: [], totalCaptured: 0 };
104
+ }
105
+ return chunkVION33GW_cjs.getConsoleLogs({ ...consoleOptions, ...opts });
106
+ },
107
+ [consoleCapture, consoleOptions]
108
+ );
109
+ const getNetworkRequestsFn = react.useCallback(
110
+ (opts) => {
111
+ if (!network) {
112
+ return { requests: [], totalCaptured: 0 };
113
+ }
114
+ return chunkVION33GW_cjs.getNetworkRequests({ ...networkOptions, ...opts });
115
+ },
116
+ [network, networkOptions]
117
+ );
118
+ const requestConsent = react.useCallback(
119
+ async (tools, reason = "") => {
120
+ const enabledTools = tools.filter((tool2) => {
121
+ if (tool2 === "screenshot") return screenshot;
122
+ if (tool2 === "console") return consoleCapture;
123
+ if (tool2 === "network") return network;
124
+ return false;
125
+ });
126
+ if (enabledTools.length === 0) {
127
+ return { approved: [], denied: [] };
128
+ }
129
+ if (!requireConsent) {
130
+ return { approved: enabledTools, denied: [] };
131
+ }
132
+ const needsConsent = enabledTools.filter(
133
+ (tool2) => !rememberedConsentRef.current.has(tool2)
134
+ );
135
+ if (needsConsent.length === 0) {
136
+ return { approved: enabledTools, denied: [] };
137
+ }
138
+ const request = {
139
+ tools: needsConsent,
140
+ reason,
141
+ keywords: []
142
+ };
143
+ if (onConsentRequest) {
144
+ const response = await onConsentRequest(request);
145
+ if (response.remember) {
146
+ response.approved.forEach(
147
+ (tool2) => rememberedConsentRef.current.add(tool2)
148
+ );
149
+ }
150
+ return response;
151
+ }
152
+ return new Promise((resolve) => {
153
+ setPendingConsent(request);
154
+ consentResolverRef.current = (response) => {
155
+ if (response.remember) {
156
+ response.approved.forEach(
157
+ (tool2) => rememberedConsentRef.current.add(tool2)
158
+ );
159
+ }
160
+ resolve(response);
161
+ };
162
+ });
163
+ },
164
+ [screenshot, consoleCapture, network, requireConsent, onConsentRequest]
165
+ );
166
+ const respondToConsent = react.useCallback((response) => {
167
+ if (consentResolverRef.current) {
168
+ consentResolverRef.current(response);
169
+ consentResolverRef.current = null;
170
+ }
171
+ setPendingConsent(null);
172
+ }, []);
173
+ const captureContext = react.useCallback(
174
+ async (tools) => {
175
+ const toolsToCapture = tools || ["screenshot", "console", "network"];
176
+ const context = {
177
+ timestamp: Date.now()
178
+ };
179
+ const captures = [];
180
+ if (toolsToCapture.includes("screenshot") && screenshot) {
181
+ captures.push(
182
+ captureScreenshotFn().then((result) => {
183
+ context.screenshot = result;
184
+ }).catch(() => {
185
+ })
186
+ );
187
+ }
188
+ if (toolsToCapture.includes("console") && consoleCapture) {
189
+ context.consoleLogs = getConsoleLogsFn();
190
+ }
191
+ if (toolsToCapture.includes("network") && network) {
192
+ context.networkRequests = getNetworkRequestsFn();
193
+ }
194
+ await Promise.all(captures);
195
+ return context;
196
+ },
197
+ [
198
+ screenshot,
199
+ consoleCapture,
200
+ network,
201
+ captureScreenshotFn,
202
+ getConsoleLogsFn,
203
+ getNetworkRequestsFn
204
+ ]
205
+ );
206
+ const startCapturing = react.useCallback(() => {
207
+ if (consoleCapture && !chunkVION33GW_cjs.isConsoleCaptureActive()) {
208
+ chunkVION33GW_cjs.startConsoleCapture(consoleOptions);
209
+ setActiveCaptures((prev) => ({ ...prev, console: true }));
210
+ }
211
+ if (network && !chunkVION33GW_cjs.isNetworkCaptureActive()) {
212
+ chunkVION33GW_cjs.startNetworkCapture(networkOptions);
213
+ setActiveCaptures((prev) => ({ ...prev, network: true }));
214
+ }
215
+ }, [consoleCapture, network, consoleOptions, networkOptions]);
216
+ const stopCapturing = react.useCallback(() => {
217
+ chunkVION33GW_cjs.stopConsoleCapture();
218
+ chunkVION33GW_cjs.stopNetworkCapture();
219
+ setActiveCaptures({ console: false, network: false });
220
+ }, []);
221
+ const clearCaptured = react.useCallback(() => {
222
+ chunkVION33GW_cjs.clearConsoleLogs();
223
+ chunkVION33GW_cjs.clearNetworkRequests();
224
+ }, []);
225
+ const formatForAI = react.useCallback((context) => {
226
+ const parts = [];
227
+ if (context.screenshot) {
228
+ parts.push(
229
+ `Screenshot captured (${context.screenshot.width}x${context.screenshot.height}, ${context.screenshot.format})`
230
+ );
231
+ }
232
+ if (context.consoleLogs && context.consoleLogs.logs.length > 0) {
233
+ parts.push(chunkVION33GW_cjs.formatLogsForAI(context.consoleLogs.logs));
234
+ }
235
+ if (context.networkRequests && context.networkRequests.requests.length > 0) {
236
+ parts.push(chunkVION33GW_cjs.formatRequestsForAI(context.networkRequests.requests));
237
+ }
238
+ return parts.length > 0 ? parts.join("\n\n---\n\n") : "No context captured.";
239
+ }, []);
240
+ const detectIntentFn = react.useCallback(
241
+ (message) => {
242
+ const result = chunkVION33GW_cjs.detectIntent(message);
243
+ result.suggestedTools = result.suggestedTools.filter((tool2) => {
244
+ if (tool2 === "screenshot") return screenshot;
245
+ if (tool2 === "console") return consoleCapture;
246
+ if (tool2 === "network") return network;
247
+ return false;
248
+ });
249
+ return result;
250
+ },
251
+ [screenshot, consoleCapture, network]
252
+ );
253
+ return react.useMemo(
254
+ () => ({
255
+ isEnabled,
256
+ activeCaptures,
257
+ captureScreenshot: captureScreenshotFn,
258
+ getConsoleLogs: getConsoleLogsFn,
259
+ getNetworkRequests: getNetworkRequestsFn,
260
+ captureContext,
261
+ detectIntent: detectIntentFn,
262
+ requestConsent,
263
+ startCapturing,
264
+ stopCapturing,
265
+ clearCaptured,
266
+ formatForAI,
267
+ pendingConsent,
268
+ respondToConsent
269
+ }),
270
+ [
271
+ isEnabled,
272
+ activeCaptures,
273
+ captureScreenshotFn,
274
+ getConsoleLogsFn,
275
+ getNetworkRequestsFn,
276
+ captureContext,
277
+ detectIntentFn,
278
+ requestConsent,
279
+ startCapturing,
280
+ stopCapturing,
281
+ clearCaptured,
282
+ formatForAI,
283
+ pendingConsent,
284
+ respondToConsent
285
+ ]
286
+ );
287
+ }
288
+ function convertZodSchema(schema, _toolName) {
289
+ try {
290
+ const zodWithJsonSchema = z__namespace;
291
+ if (typeof zodWithJsonSchema.toJSONSchema === "function") {
292
+ const jsonSchema = zodWithJsonSchema.toJSONSchema(
293
+ schema
294
+ );
295
+ if (jsonSchema.type === "object") {
296
+ return {
297
+ type: "object",
298
+ properties: jsonSchema.properties || {},
299
+ required: jsonSchema.required
300
+ };
301
+ }
302
+ }
303
+ } catch {
304
+ }
305
+ return chunkVION33GW_cjs.zodObjectToInputSchema(schema);
306
+ }
307
+ function useToolWithSchema(config, dependencies = []) {
308
+ const { registerTool, unregisterTool } = chunk2QLF7XM7_cjs.useCopilot();
309
+ const configRef = react.useRef(config);
310
+ configRef.current = config;
311
+ const inputSchema = react.useMemo(() => {
312
+ try {
313
+ return convertZodSchema(config.schema, config.name);
314
+ } catch (error) {
315
+ console.warn(
316
+ `[useToolWithSchema] Failed to convert Zod schema for tool "${config.name}"`,
317
+ error
318
+ );
319
+ return {
320
+ type: "object",
321
+ properties: {}
322
+ };
323
+ }
324
+ }, [config.schema, config.name]);
325
+ react.useEffect(() => {
326
+ const tool2 = {
327
+ name: config.name,
328
+ description: config.description,
329
+ location: "client",
330
+ inputSchema,
331
+ handler: async (params, context) => {
332
+ return configRef.current.handler(params, context);
333
+ },
334
+ render: config.render,
335
+ available: config.available ?? true
336
+ };
337
+ registerTool(tool2);
338
+ return () => {
339
+ unregisterTool(config.name);
340
+ };
341
+ }, [config.name, inputSchema, ...dependencies]);
342
+ }
343
+ function useToolsWithSchema(tools, dependencies = []) {
344
+ const { registerTool, unregisterTool } = chunk2QLF7XM7_cjs.useCopilot();
345
+ const toolsRef = react.useRef(tools);
346
+ toolsRef.current = tools;
347
+ react.useEffect(() => {
348
+ const toolNames = [];
349
+ for (const config of tools) {
350
+ let inputSchema;
351
+ try {
352
+ inputSchema = convertZodSchema(config.schema, config.name);
353
+ } catch (error) {
354
+ console.warn(
355
+ `[useToolsWithSchema] Failed to convert Zod schema for tool "${config.name}"`,
356
+ error
357
+ );
358
+ inputSchema = { type: "object", properties: {} };
359
+ }
360
+ const tool2 = {
361
+ name: config.name,
362
+ description: config.description,
363
+ location: "client",
364
+ inputSchema,
365
+ handler: async (params, context) => {
366
+ const currentConfig = toolsRef.current.find(
367
+ (t) => t.name === config.name
368
+ );
369
+ if (currentConfig) {
370
+ return currentConfig.handler(params, context);
371
+ }
372
+ return { success: false, error: "Tool handler not found" };
373
+ },
374
+ available: config.available ?? true
375
+ };
376
+ registerTool(tool2);
377
+ toolNames.push(config.name);
378
+ }
379
+ return () => {
380
+ for (const name of toolNames) {
381
+ unregisterTool(name);
382
+ }
383
+ };
384
+ }, [tools.map((t) => t.name).join(","), ...dependencies]);
385
+ }
386
+ var CopilotContext = react.createContext(null);
387
+ function useCopilotContext() {
388
+ const context = react.useContext(CopilotContext);
389
+ if (!context) {
390
+ throw new Error("useCopilotContext must be used within a CopilotProvider");
391
+ }
392
+ return context;
393
+ }
394
+
395
+ // src/react/hooks/useToolExecutor.ts
396
+ function useToolExecutor() {
397
+ const {
398
+ registeredTools,
399
+ config,
400
+ chat,
401
+ addToolExecution,
402
+ updateToolExecution
403
+ } = useCopilotContext();
404
+ const toolsRef = react.useRef(registeredTools);
405
+ toolsRef.current = registeredTools;
406
+ const executeTool = react.useCallback(
407
+ async (toolCall) => {
408
+ const tool2 = toolsRef.current.find((t) => t.name === toolCall.name);
409
+ if (!tool2) {
410
+ return {
411
+ success: false,
412
+ error: `Unknown tool: ${toolCall.name}`
413
+ };
414
+ }
415
+ if (!tool2.handler) {
416
+ return {
417
+ success: false,
418
+ error: `Tool "${toolCall.name}" has no handler`
419
+ };
420
+ }
421
+ const execution = {
422
+ id: toolCall.id,
423
+ name: toolCall.name,
424
+ args: toolCall.input,
425
+ status: "executing",
426
+ timestamp: Date.now(),
427
+ approvalStatus: "none",
428
+ hidden: tool2.hidden
429
+ };
430
+ addToolExecution?.(execution);
431
+ try {
432
+ const startTime = Date.now();
433
+ const result = await tool2.handler(toolCall.input);
434
+ const duration = Date.now() - startTime;
435
+ updateToolExecution?.(toolCall.id, {
436
+ status: result.success ? "completed" : "error",
437
+ result,
438
+ error: result.error,
439
+ duration
440
+ });
441
+ return result;
442
+ } catch (error) {
443
+ const errorMessage = error instanceof Error ? error.message : "Tool execution failed";
444
+ updateToolExecution?.(toolCall.id, {
445
+ status: "error",
446
+ error: errorMessage
447
+ });
448
+ return {
449
+ success: false,
450
+ error: errorMessage
451
+ };
452
+ }
453
+ },
454
+ [addToolExecution, updateToolExecution]
455
+ );
456
+ const sendToolResult = react.useCallback(
457
+ async (toolCallId, result) => {
458
+ const runtimeUrl = config.runtimeUrl || config.cloud?.endpoint;
459
+ if (!runtimeUrl) {
460
+ console.warn(
461
+ "[useToolExecutor] No runtime URL configured, cannot send tool result"
462
+ );
463
+ return;
464
+ }
465
+ const baseUrl = runtimeUrl.replace(/\/chat\/?$/, "");
466
+ try {
467
+ const response = await fetch(`${baseUrl}/tool-result`, {
468
+ method: "POST",
469
+ headers: {
470
+ "Content-Type": "application/json"
471
+ },
472
+ body: JSON.stringify({
473
+ threadId: chat.threadId || "default",
474
+ toolCallId,
475
+ result
476
+ })
477
+ });
478
+ if (!response.ok) {
479
+ console.error(
480
+ "[useToolExecutor] Failed to send tool result:",
481
+ await response.text()
482
+ );
483
+ }
484
+ } catch (error) {
485
+ console.error("[useToolExecutor] Error sending tool result:", error);
486
+ }
487
+ },
488
+ [config.runtimeUrl, config.cloud?.endpoint, chat.threadId]
489
+ );
490
+ const getTool = react.useCallback((name) => {
491
+ return toolsRef.current.find((t) => t.name === name);
492
+ }, []);
493
+ const hasTool = react.useCallback((name) => {
494
+ return toolsRef.current.some((t) => t.name === name);
495
+ }, []);
496
+ return {
497
+ executeTool,
498
+ sendToolResult,
499
+ getTool,
500
+ hasTool
501
+ };
502
+ }
503
+ function useSuggestions(options = {}) {
504
+ const {
505
+ count = 3,
506
+ context,
507
+ suggestions: staticSuggestions,
508
+ autoRefresh = true
509
+ } = options;
510
+ const { chat, actions, config } = useCopilotContext();
511
+ const [suggestions, setSuggestions] = react.useState([]);
512
+ const [isLoading, setIsLoading] = react.useState(false);
513
+ const normalizedStatic = react.useMemo(
514
+ () => staticSuggestions?.map((s) => typeof s === "string" ? { text: s } : s),
515
+ [staticSuggestions]
516
+ );
517
+ const refresh = react.useCallback(async () => {
518
+ if (normalizedStatic) {
519
+ setSuggestions(normalizedStatic.slice(0, count));
520
+ return;
521
+ }
522
+ if (!config.cloud) {
523
+ return;
524
+ }
525
+ setIsLoading(true);
526
+ try {
527
+ const endpoint = config.cloud.endpoint || "https://api.yourgpt.ai/v1";
528
+ const response = await fetch(`${endpoint}/suggestions`, {
529
+ method: "POST",
530
+ headers: {
531
+ "Content-Type": "application/json",
532
+ Authorization: `Bearer ${config.cloud.apiKey}`
533
+ },
534
+ body: JSON.stringify({
535
+ botId: config.cloud.botId,
536
+ count,
537
+ context,
538
+ messages: chat.messages.slice(-5)
539
+ // Last 5 messages for context
540
+ })
541
+ });
542
+ if (response.ok) {
543
+ const data = await response.json();
544
+ setSuggestions(
545
+ data.suggestions.map(
546
+ (s) => typeof s === "string" ? { text: s } : s
547
+ )
548
+ );
549
+ }
550
+ } catch (error) {
551
+ console.error("Failed to fetch suggestions:", error);
552
+ } finally {
553
+ setIsLoading(false);
554
+ }
555
+ }, [config.cloud, count, context, chat.messages, normalizedStatic]);
556
+ const select = react.useCallback(
557
+ (suggestion) => {
558
+ const text = typeof suggestion === "string" ? suggestion : suggestion.text;
559
+ actions.sendMessage(text);
560
+ },
561
+ [actions]
562
+ );
563
+ react.useEffect(() => {
564
+ if (autoRefresh && chat.messages.length === 0) {
565
+ refresh();
566
+ }
567
+ }, [autoRefresh, chat.messages.length, refresh]);
568
+ return {
569
+ suggestions: normalizedStatic?.slice(0, count) || suggestions,
570
+ isLoading,
571
+ refresh,
572
+ select
573
+ };
574
+ }
575
+ function useAgent(options) {
576
+ const { name, initialState = {}, onStateChange } = options;
577
+ const { config } = useCopilotContext();
578
+ const [state, setStateInternal] = react.useState(initialState);
579
+ const [isRunning, setIsRunning] = react.useState(false);
580
+ const [nodeName, setNodeName] = react.useState(null);
581
+ const [error, setError] = react.useState(null);
582
+ const abortControllerRef = react.useRef(null);
583
+ const getEndpoint = react.useCallback(() => {
584
+ if (config.cloud) {
585
+ return `${config.cloud.endpoint || "https://api.yourgpt.ai/v1"}/agents/${name}`;
586
+ }
587
+ return `${config.runtimeUrl || "/api"}/agents/${name}`;
588
+ }, [config, name]);
589
+ const start = react.useCallback(
590
+ async (input) => {
591
+ setIsRunning(true);
592
+ setError(null);
593
+ abortControllerRef.current = new AbortController();
594
+ try {
595
+ const endpoint = getEndpoint();
596
+ const headers = {
597
+ "Content-Type": "application/json"
598
+ };
599
+ if (config.cloud?.apiKey) {
600
+ headers["Authorization"] = `Bearer ${config.cloud.apiKey}`;
601
+ }
602
+ const response = await fetch(`${endpoint}/start`, {
603
+ method: "POST",
604
+ headers,
605
+ body: JSON.stringify({
606
+ input: typeof input === "string" ? { message: input } : input,
607
+ state
608
+ }),
609
+ signal: abortControllerRef.current.signal
610
+ });
611
+ if (!response.ok) {
612
+ throw new Error(`Agent error: ${response.status}`);
613
+ }
614
+ for await (const event of chunkVION33GW_cjs.streamSSE(response)) {
615
+ handleAgentEvent(event);
616
+ }
617
+ } catch (err) {
618
+ if (err.name !== "AbortError") {
619
+ setError(err instanceof Error ? err : new Error("Unknown error"));
620
+ }
621
+ } finally {
622
+ setIsRunning(false);
623
+ abortControllerRef.current = null;
624
+ }
625
+ },
626
+ [config, getEndpoint, state]
627
+ );
628
+ const handleAgentEvent = react.useCallback(
629
+ (event) => {
630
+ if (event.type === "error") {
631
+ setError(new Error(event.message));
632
+ return;
633
+ }
634
+ if ("state" in event && event.state) {
635
+ setStateInternal(event.state);
636
+ onStateChange?.(event.state);
637
+ }
638
+ if ("nodeName" in event && event.nodeName) {
639
+ setNodeName(event.nodeName);
640
+ }
641
+ },
642
+ [onStateChange]
643
+ );
644
+ const stop = react.useCallback(() => {
645
+ abortControllerRef.current?.abort();
646
+ }, []);
647
+ const setState = react.useCallback(
648
+ (partialState) => {
649
+ setStateInternal((prev) => {
650
+ const newState = { ...prev, ...partialState };
651
+ onStateChange?.(newState);
652
+ return newState;
653
+ });
654
+ },
655
+ [onStateChange]
656
+ );
657
+ react.useEffect(() => {
658
+ return () => {
659
+ abortControllerRef.current?.abort();
660
+ };
661
+ }, []);
662
+ return {
663
+ state,
664
+ isRunning,
665
+ nodeName,
666
+ start,
667
+ stop,
668
+ setState,
669
+ error
670
+ };
671
+ }
672
+
673
+ // src/react/utils/knowledge-base.ts
674
+ var KNOWLEDGE_BASE_API = "https://api.yourgpt.ai/chatbot/v1/searchIndexDocument";
675
+ async function searchKnowledgeBase(query, config) {
676
+ try {
677
+ const response = await fetch(KNOWLEDGE_BASE_API, {
678
+ method: "POST",
679
+ headers: {
680
+ accept: "*/*",
681
+ "content-type": "application/json",
682
+ authorization: `Bearer ${config.token}`
683
+ },
684
+ body: JSON.stringify({
685
+ project_uid: config.projectUid,
686
+ query,
687
+ page: 1,
688
+ limit: String(config.limit || 10),
689
+ app_id: config.appId || "1"
690
+ })
691
+ });
692
+ if (!response.ok) {
693
+ return {
694
+ success: false,
695
+ results: [],
696
+ error: `API error: ${response.status} ${response.statusText}`
697
+ };
698
+ }
699
+ const data = await response.json();
700
+ const results = (data.data || data.results || []).map((item) => ({
701
+ id: item.id || item._id || String(Math.random()),
702
+ title: item.title || item.name || void 0,
703
+ content: item.content || item.text || item.snippet || "",
704
+ score: item.score || item.relevance || void 0,
705
+ url: item.url || item.source_url || void 0,
706
+ metadata: item.metadata || {}
707
+ }));
708
+ return {
709
+ success: true,
710
+ results,
711
+ total: data.total || results.length,
712
+ page: data.page || 1
713
+ };
714
+ } catch (error) {
715
+ return {
716
+ success: false,
717
+ results: [],
718
+ error: error instanceof Error ? error.message : "Unknown error"
719
+ };
720
+ }
721
+ }
722
+ function formatKnowledgeResultsForAI(results) {
723
+ if (results.length === 0) {
724
+ return "No relevant documents found in the knowledge base.";
725
+ }
726
+ return results.map((result, index) => {
727
+ const parts = [`[${index + 1}]`];
728
+ if (result.title) parts.push(`**${result.title}**`);
729
+ parts.push(result.content);
730
+ if (result.url) parts.push(`Source: ${result.url}`);
731
+ return parts.join("\n");
732
+ }).join("\n\n---\n\n");
733
+ }
734
+
735
+ // src/react/hooks/useKnowledgeBase.ts
736
+ function useKnowledgeBase(config) {
737
+ const { registerTool, unregisterTool } = chunk2QLF7XM7_cjs.useCopilot();
738
+ const configRef = react.useRef(config);
739
+ configRef.current = config;
740
+ const handleSearch = react.useCallback(
741
+ async (params) => {
742
+ const query = params.query;
743
+ if (!query) {
744
+ return {
745
+ success: false,
746
+ error: "Query is required"
747
+ };
748
+ }
749
+ const currentConfig = configRef.current;
750
+ const kbConfig = {
751
+ projectUid: currentConfig.projectUid,
752
+ token: currentConfig.token,
753
+ appId: currentConfig.appId,
754
+ limit: currentConfig.limit || 5
755
+ };
756
+ const response = await searchKnowledgeBase(
757
+ query,
758
+ kbConfig
759
+ );
760
+ if (!response.success) {
761
+ return {
762
+ success: false,
763
+ error: response.error || "Knowledge base search failed"
764
+ };
765
+ }
766
+ const formattedResults = formatKnowledgeResultsForAI(response.results);
767
+ return {
768
+ success: true,
769
+ message: formattedResults,
770
+ data: {
771
+ resultCount: response.results.length,
772
+ total: response.total
773
+ }
774
+ };
775
+ },
776
+ []
777
+ );
778
+ react.useEffect(() => {
779
+ if (config.enabled === false) {
780
+ return;
781
+ }
782
+ registerTool({
783
+ name: "search_knowledge",
784
+ description: "Search the knowledge base for relevant information about the product, documentation, or company. Use this to answer questions about features, pricing, policies, guides, or any factual information.",
785
+ location: "client",
786
+ inputSchema: {
787
+ type: "object",
788
+ properties: {
789
+ query: {
790
+ type: "string",
791
+ description: "The search query to find relevant information in the knowledge base"
792
+ }
793
+ },
794
+ required: ["query"]
795
+ },
796
+ handler: handleSearch
797
+ });
798
+ return () => {
799
+ unregisterTool("search_knowledge");
800
+ };
801
+ }, [
802
+ config.enabled,
803
+ config.projectUid,
804
+ config.token,
805
+ registerTool,
806
+ unregisterTool,
807
+ handleSearch
808
+ ]);
809
+ }
810
+ var DEFAULT_CAPABILITIES = {
811
+ supportsVision: false,
812
+ supportsTools: true,
813
+ supportsThinking: false,
814
+ supportsStreaming: true,
815
+ supportsPDF: false,
816
+ supportsAudio: false,
817
+ supportsVideo: false,
818
+ maxTokens: 8192,
819
+ supportedImageTypes: [],
820
+ supportsJsonMode: false,
821
+ supportsSystemMessages: true
822
+ };
823
+ function useCapabilities() {
824
+ const { config } = useCopilotContext();
825
+ const [capabilities, setCapabilities] = react.useState(DEFAULT_CAPABILITIES);
826
+ const [provider, setProvider] = react.useState("unknown");
827
+ const [model, setModel] = react.useState("unknown");
828
+ const [supportedModels, setSupportedModels] = react.useState([]);
829
+ const [isLoading, setIsLoading] = react.useState(true);
830
+ const [error, setError] = react.useState(null);
831
+ const capabilitiesUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/chat\/?$/, "/capabilities") : null;
832
+ const fetchCapabilities = react.useCallback(async () => {
833
+ if (!capabilitiesUrl) {
834
+ setIsLoading(false);
835
+ return;
836
+ }
837
+ try {
838
+ setIsLoading(true);
839
+ setError(null);
840
+ const response = await fetch(capabilitiesUrl);
841
+ if (!response.ok) {
842
+ throw new Error(`Failed to fetch capabilities: ${response.status}`);
843
+ }
844
+ const data = await response.json();
845
+ setCapabilities(data.capabilities);
846
+ setProvider(data.provider);
847
+ setModel(data.model);
848
+ setSupportedModels(data.supportedModels);
849
+ } catch (err) {
850
+ setError(err instanceof Error ? err : new Error("Unknown error"));
851
+ } finally {
852
+ setIsLoading(false);
853
+ }
854
+ }, [capabilitiesUrl]);
855
+ react.useEffect(() => {
856
+ fetchCapabilities();
857
+ }, [fetchCapabilities]);
858
+ return {
859
+ /** Current model capabilities */
860
+ capabilities,
861
+ /** Current provider name */
862
+ provider,
863
+ /** Current model ID */
864
+ model,
865
+ /** List of supported models for current provider */
866
+ supportedModels,
867
+ /** Whether capabilities are being loaded */
868
+ isLoading,
869
+ /** Error if fetch failed */
870
+ error,
871
+ /** Refetch capabilities */
872
+ refetch: fetchCapabilities
873
+ };
874
+ }
875
+ function useFeatureSupport(feature) {
876
+ const { capabilities } = useCapabilities();
877
+ return capabilities[feature] ?? false;
878
+ }
879
+ function useSupportedMediaTypes() {
880
+ const { capabilities } = useCapabilities();
881
+ return {
882
+ /** Supported image MIME types */
883
+ imageTypes: capabilities.supportedImageTypes || [],
884
+ /** Supported audio MIME types */
885
+ audioTypes: capabilities.supportedAudioTypes || [],
886
+ /** Supported video MIME types */
887
+ videoTypes: capabilities.supportedVideoTypes || [],
888
+ /** Whether any image types are supported */
889
+ hasImageSupport: (capabilities.supportedImageTypes?.length ?? 0) > 0,
890
+ /** Whether any audio types are supported */
891
+ hasAudioSupport: (capabilities.supportedAudioTypes?.length ?? 0) > 0,
892
+ /** Whether any video types are supported */
893
+ hasVideoSupport: (capabilities.supportedVideoTypes?.length ?? 0) > 0
894
+ };
895
+ }
896
+ function useDevLogger() {
897
+ const ctx = useCopilotContext();
898
+ return react.useMemo(() => {
899
+ const toolExecutions = (ctx.agentLoop?.toolExecutions || []).map(
900
+ (exec) => ({
901
+ id: exec.id,
902
+ name: exec.name,
903
+ status: exec.status,
904
+ approvalStatus: exec.approvalStatus || "not_required"
905
+ })
906
+ );
907
+ const pendingApprovalsCount = ctx.pendingApprovals?.length || 0;
908
+ const registeredTools = (ctx.registeredTools || []).map((tool2) => ({
909
+ name: tool2.name,
910
+ location: tool2.location || "client"
911
+ }));
912
+ const registeredActions = (ctx.registeredActions || []).map((action) => ({
913
+ name: action.name
914
+ }));
915
+ const storedPermissions = (ctx.storedPermissions || []).map((p) => ({
916
+ toolName: p.toolName,
917
+ level: p.level
918
+ }));
919
+ return {
920
+ chat: {
921
+ isLoading: ctx.chat?.isLoading || false,
922
+ messageCount: ctx.chat?.messages?.length || 0,
923
+ threadId: ctx.chat?.threadId || "none",
924
+ error: ctx.chat?.error?.message || null
925
+ },
926
+ tools: {
927
+ isEnabled: !!ctx.toolsConfig,
928
+ isCapturing: ctx.tools?.isCapturing || false,
929
+ pendingConsent: !!ctx.tools?.pendingConsent
930
+ },
931
+ agentLoop: {
932
+ toolExecutions,
933
+ pendingApprovals: pendingApprovalsCount,
934
+ iteration: ctx.agentLoop?.iteration || 0,
935
+ maxIterations: ctx.agentLoop?.maxIterations || 10
936
+ },
937
+ registered: {
938
+ tools: registeredTools,
939
+ actions: registeredActions,
940
+ contextCount: ctx.contextTree?.length || 0
941
+ },
942
+ permissions: {
943
+ stored: storedPermissions,
944
+ loaded: ctx.permissionsLoaded || false
945
+ },
946
+ config: {
947
+ runtimeUrl: ctx.config?.runtimeUrl || ctx.config?.cloud?.endpoint || ""
948
+ }
949
+ };
950
+ }, [
951
+ ctx.chat,
952
+ ctx.tools,
953
+ ctx.toolsConfig,
954
+ ctx.agentLoop,
955
+ ctx.pendingApprovals,
956
+ ctx.registeredTools,
957
+ ctx.registeredActions,
958
+ ctx.contextTree,
959
+ ctx.storedPermissions,
960
+ ctx.permissionsLoaded,
961
+ ctx.config
962
+ ]);
963
+ }
964
+
965
+ // src/react/internal/ReactThreadManagerState.ts
966
+ var ReactThreadManagerState = class {
967
+ constructor(initialThreads) {
968
+ this._threads = [];
969
+ this._currentThreadId = null;
970
+ this._currentThread = null;
971
+ this._loadStatus = "idle";
972
+ this._error = void 0;
973
+ // Callbacks for React subscriptions (useSyncExternalStore)
974
+ this.subscribers = /* @__PURE__ */ new Set();
975
+ // ============================================
976
+ // Subscription (for useSyncExternalStore)
977
+ // ============================================
978
+ /**
979
+ * Subscribe to state changes.
980
+ * Returns an unsubscribe function.
981
+ *
982
+ * @example
983
+ * ```tsx
984
+ * const threads = useSyncExternalStore(
985
+ * state.subscribe,
986
+ * () => state.threads
987
+ * );
988
+ * ```
989
+ */
990
+ this.subscribe = (callback) => {
991
+ this.subscribers.add(callback);
992
+ return () => {
993
+ this.subscribers.delete(callback);
994
+ };
995
+ };
996
+ if (initialThreads) {
997
+ this._threads = initialThreads;
998
+ }
999
+ }
1000
+ // ============================================
1001
+ // Getters
1002
+ // ============================================
1003
+ get threads() {
1004
+ return this._threads;
1005
+ }
1006
+ get currentThreadId() {
1007
+ return this._currentThreadId;
1008
+ }
1009
+ get currentThread() {
1010
+ return this._currentThread;
1011
+ }
1012
+ get loadStatus() {
1013
+ return this._loadStatus;
1014
+ }
1015
+ get error() {
1016
+ return this._error;
1017
+ }
1018
+ // ============================================
1019
+ // Setters (trigger reactivity)
1020
+ // ============================================
1021
+ set threads(value) {
1022
+ this._threads = value;
1023
+ this.notify();
1024
+ }
1025
+ // ============================================
1026
+ // Mutations
1027
+ // ============================================
1028
+ setThreads(threads) {
1029
+ this._threads = threads;
1030
+ this.notify();
1031
+ }
1032
+ setCurrentThread(thread) {
1033
+ this._currentThread = thread;
1034
+ this._currentThreadId = thread?.id ?? null;
1035
+ this.notify();
1036
+ }
1037
+ setCurrentThreadId(id) {
1038
+ this._currentThreadId = id;
1039
+ this.notify();
1040
+ }
1041
+ addThread(thread) {
1042
+ this._threads = [thread, ...this._threads];
1043
+ this.notify();
1044
+ }
1045
+ updateThread(id, updates) {
1046
+ this._threads = this._threads.map(
1047
+ (t) => t.id === id ? { ...t, ...updates } : t
1048
+ );
1049
+ if (updates.updatedAt) {
1050
+ this._threads = [...this._threads].sort(
1051
+ (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime()
1052
+ );
1053
+ }
1054
+ if (this._currentThread?.id === id) {
1055
+ this._currentThread = { ...this._currentThread, ...updates };
1056
+ }
1057
+ this.notify();
1058
+ }
1059
+ removeThread(id) {
1060
+ this._threads = this._threads.filter((t) => t.id !== id);
1061
+ if (this._currentThreadId === id) {
1062
+ this._currentThreadId = null;
1063
+ this._currentThread = null;
1064
+ }
1065
+ this.notify();
1066
+ }
1067
+ setLoadStatus(status) {
1068
+ this._loadStatus = status;
1069
+ this.notify();
1070
+ }
1071
+ setError(error) {
1072
+ this._error = error;
1073
+ this.notify();
1074
+ }
1075
+ // ============================================
1076
+ // Snapshots (for useSyncExternalStore)
1077
+ // ============================================
1078
+ getThreadsSnapshot() {
1079
+ return this._threads;
1080
+ }
1081
+ getCurrentThreadSnapshot() {
1082
+ return this._currentThread;
1083
+ }
1084
+ getLoadStatusSnapshot() {
1085
+ return this._loadStatus;
1086
+ }
1087
+ getErrorSnapshot() {
1088
+ return this._error;
1089
+ }
1090
+ // ============================================
1091
+ // Private Methods
1092
+ // ============================================
1093
+ notify() {
1094
+ this.subscribers.forEach((cb) => cb());
1095
+ }
1096
+ /**
1097
+ * Cleanup subscriptions
1098
+ */
1099
+ dispose() {
1100
+ this.subscribers.clear();
1101
+ }
1102
+ };
1103
+ function createReactThreadManagerState(initialThreads) {
1104
+ return new ReactThreadManagerState(initialThreads);
1105
+ }
1106
+
1107
+ // src/react/internal/ReactThreadManager.ts
1108
+ var _ReactThreadManager = class _ReactThreadManager extends chunkVION33GW_cjs.ThreadManager {
1109
+ constructor(config = {}, callbacks = {}) {
1110
+ const reactState = new ReactThreadManagerState();
1111
+ super({ ...config, state: reactState }, callbacks);
1112
+ // ============================================
1113
+ // Subscription Methods (for useSyncExternalStore)
1114
+ // ============================================
1115
+ /**
1116
+ * Subscribe to state changes
1117
+ * Use with useSyncExternalStore
1118
+ */
1119
+ this.subscribe = (callback) => {
1120
+ return this.state.subscribe(callback);
1121
+ };
1122
+ // ============================================
1123
+ // Snapshot Getters (for useSyncExternalStore)
1124
+ // ============================================
1125
+ /**
1126
+ * Get threads snapshot
1127
+ */
1128
+ this.getThreadsSnapshot = () => {
1129
+ return this.state.getThreadsSnapshot();
1130
+ };
1131
+ /**
1132
+ * Get current thread snapshot
1133
+ */
1134
+ this.getCurrentThreadSnapshot = () => {
1135
+ return this.state.getCurrentThreadSnapshot();
1136
+ };
1137
+ /**
1138
+ * Get current thread ID snapshot
1139
+ */
1140
+ this.getCurrentThreadIdSnapshot = () => {
1141
+ return this.state.currentThreadId;
1142
+ };
1143
+ /**
1144
+ * Get load status snapshot
1145
+ */
1146
+ this.getLoadStatusSnapshot = () => {
1147
+ return this.state.getLoadStatusSnapshot();
1148
+ };
1149
+ /**
1150
+ * Get error snapshot
1151
+ */
1152
+ this.getErrorSnapshot = () => {
1153
+ return this.state.getErrorSnapshot();
1154
+ };
1155
+ /**
1156
+ * Get isLoading snapshot
1157
+ */
1158
+ this.getIsLoadingSnapshot = () => {
1159
+ return this.state.getLoadStatusSnapshot() === "loading";
1160
+ };
1161
+ /**
1162
+ * Get threads snapshot for server (always empty for hydration consistency)
1163
+ */
1164
+ this.getThreadsServerSnapshot = () => {
1165
+ return _ReactThreadManager.EMPTY_THREADS;
1166
+ };
1167
+ /**
1168
+ * Get current thread snapshot for server (always null)
1169
+ */
1170
+ this.getCurrentThreadServerSnapshot = () => {
1171
+ return null;
1172
+ };
1173
+ /**
1174
+ * Get current thread ID snapshot for server (always null)
1175
+ */
1176
+ this.getCurrentThreadIdServerSnapshot = () => {
1177
+ return null;
1178
+ };
1179
+ /**
1180
+ * Get load status snapshot for server (always "idle")
1181
+ */
1182
+ this.getLoadStatusServerSnapshot = () => {
1183
+ return _ReactThreadManager.IDLE_STATUS;
1184
+ };
1185
+ /**
1186
+ * Get error snapshot for server (always undefined)
1187
+ */
1188
+ this.getErrorServerSnapshot = () => {
1189
+ return void 0;
1190
+ };
1191
+ /**
1192
+ * Get isLoading snapshot for server (always false)
1193
+ */
1194
+ this.getIsLoadingServerSnapshot = () => {
1195
+ return false;
1196
+ };
1197
+ }
1198
+ // ============================================
1199
+ // Cleanup
1200
+ // ============================================
1201
+ /**
1202
+ * Dispose of the manager
1203
+ */
1204
+ async dispose() {
1205
+ this.state.dispose();
1206
+ await super.dispose();
1207
+ }
1208
+ };
1209
+ // ============================================
1210
+ // Server Snapshots (for SSR - stable cached values)
1211
+ // ============================================
1212
+ // Cached values for server snapshots (must be stable references)
1213
+ _ReactThreadManager.EMPTY_THREADS = [];
1214
+ _ReactThreadManager.IDLE_STATUS = "idle";
1215
+ var ReactThreadManager = _ReactThreadManager;
1216
+ function createReactThreadManager(config, callbacks) {
1217
+ return new ReactThreadManager(config, callbacks);
1218
+ }
1219
+
1220
+ // src/react/hooks/useThreadManager.ts
1221
+ var defaultManager = null;
1222
+ function getDefaultManager() {
1223
+ if (!defaultManager) {
1224
+ defaultManager = createReactThreadManager();
1225
+ }
1226
+ return defaultManager;
1227
+ }
1228
+ var internalManager = null;
1229
+ function getInternalManager(config) {
1230
+ if (!internalManager) {
1231
+ internalManager = createReactThreadManager(
1232
+ {
1233
+ adapter: config.adapter,
1234
+ saveDebounce: config.saveDebounce,
1235
+ autoLoad: config.autoLoad,
1236
+ autoRestoreLastThread: config.autoRestoreLastThread
1237
+ },
1238
+ config.callbacks
1239
+ );
1240
+ }
1241
+ return internalManager;
1242
+ }
1243
+ function useThreadManager(config) {
1244
+ const manager = react.useMemo(() => {
1245
+ if (!config) {
1246
+ return getDefaultManager();
1247
+ }
1248
+ if (!config.adapter) {
1249
+ return getInternalManager(config);
1250
+ }
1251
+ return createReactThreadManager(
1252
+ {
1253
+ adapter: config.adapter,
1254
+ saveDebounce: config.saveDebounce,
1255
+ autoLoad: config.autoLoad,
1256
+ autoRestoreLastThread: config.autoRestoreLastThread
1257
+ },
1258
+ config.callbacks
1259
+ );
1260
+ }, [
1261
+ config?.adapter,
1262
+ config?.saveDebounce,
1263
+ config?.autoLoad,
1264
+ config?.autoRestoreLastThread
1265
+ // Note: callbacks are intentionally not in deps to avoid recreating manager
1266
+ ]);
1267
+ const threads = react.useSyncExternalStore(
1268
+ manager.subscribe,
1269
+ manager.getThreadsSnapshot,
1270
+ manager.getThreadsServerSnapshot
1271
+ // SSR - always empty array
1272
+ );
1273
+ const currentThread = react.useSyncExternalStore(
1274
+ manager.subscribe,
1275
+ manager.getCurrentThreadSnapshot,
1276
+ manager.getCurrentThreadServerSnapshot
1277
+ // SSR - always null
1278
+ );
1279
+ const currentThreadId = react.useSyncExternalStore(
1280
+ manager.subscribe,
1281
+ manager.getCurrentThreadIdSnapshot,
1282
+ manager.getCurrentThreadIdServerSnapshot
1283
+ // SSR - always null
1284
+ );
1285
+ const loadStatus = react.useSyncExternalStore(
1286
+ manager.subscribe,
1287
+ manager.getLoadStatusSnapshot,
1288
+ manager.getLoadStatusServerSnapshot
1289
+ // SSR - always "idle"
1290
+ );
1291
+ const error = react.useSyncExternalStore(
1292
+ manager.subscribe,
1293
+ manager.getErrorSnapshot,
1294
+ manager.getErrorServerSnapshot
1295
+ // SSR - always undefined
1296
+ );
1297
+ const isLoading = react.useSyncExternalStore(
1298
+ manager.subscribe,
1299
+ manager.getIsLoadingSnapshot,
1300
+ manager.getIsLoadingServerSnapshot
1301
+ // SSR - always false
1302
+ );
1303
+ react.useEffect(() => {
1304
+ return () => {
1305
+ if (config?.adapter && manager !== defaultManager && manager !== internalManager) {
1306
+ manager.dispose();
1307
+ }
1308
+ };
1309
+ }, [manager, config]);
1310
+ react.useEffect(() => {
1311
+ const handleBeforeUnload = () => {
1312
+ if (manager.hasPendingChanges) {
1313
+ manager.saveNow().catch(() => {
1314
+ });
1315
+ }
1316
+ };
1317
+ if (typeof window !== "undefined") {
1318
+ window.addEventListener("beforeunload", handleBeforeUnload);
1319
+ return () => {
1320
+ window.removeEventListener("beforeunload", handleBeforeUnload);
1321
+ };
1322
+ }
1323
+ }, [manager]);
1324
+ const createThread = react.useCallback(
1325
+ (options) => manager.createThread(options),
1326
+ [manager]
1327
+ );
1328
+ const switchThread = react.useCallback(
1329
+ (id) => manager.switchThread(id),
1330
+ [manager]
1331
+ );
1332
+ const updateCurrentThread = react.useCallback(
1333
+ (updates) => manager.updateCurrentThread(updates),
1334
+ [manager]
1335
+ );
1336
+ const deleteThread = react.useCallback(
1337
+ (id) => manager.deleteThread(id),
1338
+ [manager]
1339
+ );
1340
+ const clearCurrentThread = react.useCallback(
1341
+ () => manager.clearCurrentThread(),
1342
+ [manager]
1343
+ );
1344
+ const refreshThreads = react.useCallback(() => manager.loadThreads(), [manager]);
1345
+ const saveNow = react.useCallback(() => manager.saveNow(), [manager]);
1346
+ const clearAllThreads = react.useCallback(
1347
+ () => manager.clearAllThreads(),
1348
+ [manager]
1349
+ );
1350
+ const messages = react.useMemo(
1351
+ () => currentThread?.messages ?? [],
1352
+ [currentThread]
1353
+ );
1354
+ const setMessages = react.useCallback(
1355
+ (newMessages) => updateCurrentThread({ messages: newMessages }),
1356
+ [updateCurrentThread]
1357
+ );
1358
+ const hasPendingChanges = manager.hasPendingChanges;
1359
+ return {
1360
+ // State
1361
+ threads,
1362
+ currentThread,
1363
+ currentThreadId,
1364
+ isLoading,
1365
+ loadStatus,
1366
+ error,
1367
+ // Actions
1368
+ createThread,
1369
+ switchThread,
1370
+ updateCurrentThread,
1371
+ deleteThread,
1372
+ clearCurrentThread,
1373
+ refreshThreads,
1374
+ saveNow,
1375
+ clearAllThreads,
1376
+ // Utilities
1377
+ messages,
1378
+ setMessages,
1379
+ hasPendingChanges
1380
+ };
1381
+ }
1382
+
1383
+ // src/react/hooks/useThread.ts
1384
+ function useThread() {
1385
+ const { threadId, setActiveThread, renewSession, sessionStatus } = chunk2QLF7XM7_cjs.useCopilot();
1386
+ return {
1387
+ threadId,
1388
+ sessionStatus,
1389
+ switchThread: setActiveThread,
1390
+ newThread: () => setActiveThread(null),
1391
+ renewSession
1392
+ };
1393
+ }
1394
+ function useMCPUIIntents(config = {}) {
1395
+ const {
1396
+ onToolCall,
1397
+ onIntent,
1398
+ onPrompt,
1399
+ onNotify,
1400
+ onLink,
1401
+ requireConsent = { tool: false, link: true }
1402
+ } = config;
1403
+ const handleIntent = react.useCallback(
1404
+ async (intent, context) => {
1405
+ switch (intent.type) {
1406
+ case "tool": {
1407
+ if (requireConsent.tool) ;
1408
+ await onToolCall?.(intent.name, intent.arguments, context);
1409
+ break;
1410
+ }
1411
+ case "intent": {
1412
+ await onIntent?.(intent.action, intent.data, context);
1413
+ break;
1414
+ }
1415
+ case "prompt": {
1416
+ onPrompt?.(intent.text, context);
1417
+ break;
1418
+ }
1419
+ case "notify": {
1420
+ onNotify?.(intent.message, intent.level, context);
1421
+ break;
1422
+ }
1423
+ case "link": {
1424
+ const shouldContinue = onLink?.(intent.url, intent.newTab, context);
1425
+ if (shouldContinue === false) {
1426
+ break;
1427
+ }
1428
+ if (requireConsent.link) {
1429
+ const isSafeUrl = intent.url.startsWith("https://") || intent.url.startsWith("http://localhost");
1430
+ if (!isSafeUrl) {
1431
+ console.warn(
1432
+ "[MCP-UI] Blocked potentially unsafe link:",
1433
+ intent.url
1434
+ );
1435
+ break;
1436
+ }
1437
+ }
1438
+ if (typeof window !== "undefined") {
1439
+ if (intent.newTab !== false) {
1440
+ window.open(intent.url, "_blank", "noopener,noreferrer");
1441
+ } else {
1442
+ window.location.href = intent.url;
1443
+ }
1444
+ }
1445
+ break;
1446
+ }
1447
+ default: {
1448
+ console.warn(
1449
+ "[MCP-UI] Unknown intent type:",
1450
+ intent.type
1451
+ );
1452
+ }
1453
+ }
1454
+ },
1455
+ [onToolCall, onIntent, onPrompt, onNotify, onLink, requireConsent]
1456
+ );
1457
+ return react.useMemo(
1458
+ () => ({
1459
+ handleIntent
1460
+ }),
1461
+ [handleIntent]
1462
+ );
1463
+ }
1464
+ function createMessageIntentHandler(sendMessage) {
1465
+ return {
1466
+ onIntent: async (action, data) => {
1467
+ const dataStr = data ? ` with ${JSON.stringify(data)}` : "";
1468
+ await sendMessage(`User action: ${action}${dataStr}`);
1469
+ },
1470
+ onPrompt: (text) => {
1471
+ sendMessage(text);
1472
+ },
1473
+ onNotify: (message, level) => {
1474
+ if (level === "error") {
1475
+ sendMessage(`Error: ${message}`);
1476
+ }
1477
+ }
1478
+ };
1479
+ }
1480
+ function createToolIntentHandler(callTool) {
1481
+ return {
1482
+ onToolCall: async (name, args) => {
1483
+ await callTool(name, args);
1484
+ }
1485
+ };
1486
+ }
1487
+ function getLastResponseUsage(messages) {
1488
+ for (let i = messages.length - 1; i >= 0; i--) {
1489
+ const msg = messages[i];
1490
+ if (msg.role === "assistant" && msg.metadata?.usage) {
1491
+ const u = msg.metadata.usage;
1492
+ const prompt = u.prompt_tokens ?? 0;
1493
+ const completion = u.completion_tokens ?? 0;
1494
+ return {
1495
+ prompt_tokens: prompt,
1496
+ completion_tokens: completion,
1497
+ total_tokens: u.total_tokens ?? prompt + completion
1498
+ };
1499
+ }
1500
+ }
1501
+ return null;
1502
+ }
1503
+ function useContextStats() {
1504
+ const { contextChars, contextUsage, registeredTools, messages } = chunk2QLF7XM7_cjs.useCopilot();
1505
+ const toolCount = react.useMemo(() => registeredTools.length, [registeredTools]);
1506
+ const messageCount = react.useMemo(
1507
+ () => messages.filter((m) => m.role !== "system").length,
1508
+ [messages]
1509
+ );
1510
+ const totalTokens = react.useMemo(() => {
1511
+ if (contextUsage) return contextUsage.total.tokens;
1512
+ return Math.ceil(contextChars / 3.5);
1513
+ }, [contextUsage, contextChars]);
1514
+ const usagePercent = react.useMemo(() => {
1515
+ if (contextUsage) return contextUsage.total.percent;
1516
+ return 0;
1517
+ }, [contextUsage]);
1518
+ const lastResponseUsage = react.useMemo(
1519
+ () => getLastResponseUsage(messages),
1520
+ [messages]
1521
+ );
1522
+ return {
1523
+ contextUsage,
1524
+ totalTokens,
1525
+ usagePercent,
1526
+ contextChars,
1527
+ toolCount,
1528
+ messageCount,
1529
+ lastResponseUsage
1530
+ };
1531
+ }
1532
+ var DEV_CONTENT_WARN_THRESHOLD = 2e3;
1533
+ function useSkill(skill) {
1534
+ const { register, unregister } = chunk2QLF7XM7_cjs.useSkillContext();
1535
+ if (process.env.NODE_ENV !== "production" && skill.source.type === "inline" && skill.source.content.length > DEV_CONTENT_WARN_THRESHOLD) {
1536
+ console.warn(
1537
+ `[copilot-sdk/skills] Inline skill "${skill.name}" has ${skill.source.content.length} characters. Inline skills are sent on every request \u2014 keep them under ${DEV_CONTENT_WARN_THRESHOLD} characters. Consider using a file or URL skill instead.`
1538
+ );
1539
+ }
1540
+ react.useEffect(() => {
1541
+ if (skill.source.type !== "inline") {
1542
+ console.warn(
1543
+ `[copilot-sdk/skills] useSkill only supports inline skills client-side. Skill "${skill.name}" has source type "${skill.source.type}" and will be skipped.`
1544
+ );
1545
+ return;
1546
+ }
1547
+ const resolved = {
1548
+ ...skill,
1549
+ content: skill.source.content
1550
+ };
1551
+ register(resolved);
1552
+ return () => {
1553
+ unregister(skill.name);
1554
+ };
1555
+ }, [
1556
+ skill.name,
1557
+ skill.source.type === "inline" ? skill.source.content : "",
1558
+ skill.strategy,
1559
+ skill.description
1560
+ ]);
1561
+ }
1562
+ function useSkillStatus() {
1563
+ const { skills, registry } = chunk2QLF7XM7_cjs.useSkillContext();
1564
+ const has = react.useCallback(
1565
+ (name) => registry.has(name),
1566
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1567
+ [skills]
1568
+ );
1569
+ return {
1570
+ skills,
1571
+ count: skills.length,
1572
+ has
1573
+ };
1574
+ }
1575
+ function useMessageCheckpoints() {
1576
+ const { messages, setMessages } = chunk2QLF7XM7_cjs.useCopilot();
1577
+ const checkpointMapRef = react.useRef(/* @__PURE__ */ new Map());
1578
+ const prevUserMsgCountRef = react.useRef(0);
1579
+ const [revision, bump] = react.useReducer((n) => n + 1, 0);
1580
+ react.useEffect(() => {
1581
+ const userMessages = messages.filter((m) => m.role === "user");
1582
+ const count = userMessages.length;
1583
+ if (count > prevUserMsgCountRef.current) {
1584
+ const newUserMsg = userMessages[count - 1];
1585
+ if (!checkpointMapRef.current.has(newUserMsg.id)) {
1586
+ const msgIndex = messages.findIndex((m) => m.id === newUserMsg.id);
1587
+ checkpointMapRef.current.set(newUserMsg.id, {
1588
+ id: `cp_${newUserMsg.id}`,
1589
+ messageId: newUserMsg.id,
1590
+ timestamp: Date.now(),
1591
+ messages: structuredClone(messages.slice(0, msgIndex))
1592
+ });
1593
+ bump();
1594
+ }
1595
+ prevUserMsgCountRef.current = count;
1596
+ }
1597
+ }, [messages]);
1598
+ const hasCheckpoint = react.useCallback(
1599
+ (messageId) => checkpointMapRef.current.has(messageId),
1600
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1601
+ [revision]
1602
+ );
1603
+ const getCheckpoint = react.useCallback(
1604
+ (messageId) => checkpointMapRef.current.get(messageId),
1605
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1606
+ [revision]
1607
+ );
1608
+ const restore = react.useCallback(
1609
+ (messageId) => {
1610
+ const cp = checkpointMapRef.current.get(messageId);
1611
+ if (!cp) return void 0;
1612
+ setMessages(cp.messages);
1613
+ checkpointMapRef.current.forEach((c, k) => {
1614
+ if (c.timestamp > cp.timestamp) checkpointMapRef.current.delete(k);
1615
+ });
1616
+ prevUserMsgCountRef.current = cp.messages.filter(
1617
+ (m) => m.role === "user"
1618
+ ).length;
1619
+ bump();
1620
+ return cp;
1621
+ },
1622
+ [setMessages]
1623
+ );
1624
+ const save = react.useCallback(
1625
+ (messageId, label) => {
1626
+ const msgIndex = messages.findIndex((m) => m.id === messageId);
1627
+ if (msgIndex === -1) return void 0;
1628
+ const cp = {
1629
+ id: `cp_${messageId}`,
1630
+ messageId,
1631
+ timestamp: Date.now(),
1632
+ label,
1633
+ messages: structuredClone(messages.slice(0, msgIndex))
1634
+ };
1635
+ checkpointMapRef.current.set(messageId, cp);
1636
+ bump();
1637
+ return cp;
1638
+ },
1639
+ [messages]
1640
+ );
1641
+ const clear = react.useCallback(() => {
1642
+ checkpointMapRef.current.clear();
1643
+ prevUserMsgCountRef.current = 0;
1644
+ bump();
1645
+ }, []);
1646
+ const checkpoints = react.useMemo(
1647
+ () => Array.from(checkpointMapRef.current.values()).sort(
1648
+ (a, b) => a.timestamp - b.timestamp
1649
+ ),
1650
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1651
+ [revision]
1652
+ );
1653
+ return { checkpoints, hasCheckpoint, getCheckpoint, restore, save, clear };
1654
+ }
1655
+
1656
+ // src/react/utils/permission-storage.ts
1657
+ var DEFAULT_KEY_PREFIX = "yourgpt-permissions";
1658
+ function createPermissionStorage(config) {
1659
+ switch (config.type) {
1660
+ case "localStorage":
1661
+ return createBrowserStorageAdapter(
1662
+ typeof window !== "undefined" ? localStorage : null,
1663
+ config.keyPrefix
1664
+ );
1665
+ case "sessionStorage":
1666
+ return createBrowserStorageAdapter(
1667
+ typeof window !== "undefined" ? sessionStorage : null,
1668
+ config.keyPrefix
1669
+ );
1670
+ case "memory":
1671
+ default:
1672
+ return createMemoryStorageAdapter();
1673
+ }
1674
+ }
1675
+ function createBrowserStorageAdapter(storage, keyPrefix = DEFAULT_KEY_PREFIX) {
1676
+ const getStorageKey = () => keyPrefix;
1677
+ const loadPermissions = () => {
1678
+ if (!storage) return /* @__PURE__ */ new Map();
1679
+ try {
1680
+ const data = storage.getItem(getStorageKey());
1681
+ if (!data) return /* @__PURE__ */ new Map();
1682
+ const parsed = JSON.parse(data);
1683
+ return new Map(parsed.map((p) => [p.toolName, p]));
1684
+ } catch {
1685
+ return /* @__PURE__ */ new Map();
1686
+ }
1687
+ };
1688
+ const savePermissions = (permissions) => {
1689
+ if (!storage) return;
1690
+ try {
1691
+ storage.setItem(
1692
+ getStorageKey(),
1693
+ JSON.stringify(Array.from(permissions.values()))
1694
+ );
1695
+ } catch (e) {
1696
+ console.warn("[PermissionStorage] Failed to save permissions:", e);
1697
+ }
1698
+ };
1699
+ return {
1700
+ async get(toolName) {
1701
+ const permissions = loadPermissions();
1702
+ return permissions.get(toolName) || null;
1703
+ },
1704
+ async set(permission) {
1705
+ const permissions = loadPermissions();
1706
+ permissions.set(permission.toolName, permission);
1707
+ savePermissions(permissions);
1708
+ },
1709
+ async remove(toolName) {
1710
+ const permissions = loadPermissions();
1711
+ permissions.delete(toolName);
1712
+ savePermissions(permissions);
1713
+ },
1714
+ async getAll() {
1715
+ const permissions = loadPermissions();
1716
+ return Array.from(permissions.values());
1717
+ },
1718
+ async clear() {
1719
+ if (!storage) return;
1720
+ storage.removeItem(getStorageKey());
1721
+ }
1722
+ };
1723
+ }
1724
+ function createMemoryStorageAdapter() {
1725
+ const permissions = /* @__PURE__ */ new Map();
1726
+ return {
1727
+ async get(toolName) {
1728
+ return permissions.get(toolName) || null;
1729
+ },
1730
+ async set(permission) {
1731
+ permissions.set(permission.toolName, permission);
1732
+ },
1733
+ async remove(toolName) {
1734
+ permissions.delete(toolName);
1735
+ },
1736
+ async getAll() {
1737
+ return Array.from(permissions.values());
1738
+ },
1739
+ async clear() {
1740
+ permissions.clear();
1741
+ }
1742
+ };
1743
+ }
1744
+ function createSessionPermissionCache() {
1745
+ return /* @__PURE__ */ new Map();
1746
+ }
1747
+
1748
+ // src/react/internal/ReactChat.ts
1749
+ var ReactChat = class extends chunk2QLF7XM7_cjs.AbstractChat {
1750
+ constructor(config) {
1751
+ const reactState = new chunk2QLF7XM7_cjs.ReactChatState(config.initialMessages);
1752
+ const init = {
1753
+ runtimeUrl: config.runtimeUrl,
1754
+ systemPrompt: config.systemPrompt,
1755
+ llm: config.llm,
1756
+ threadId: config.threadId,
1757
+ onCreateSession: config.onCreateSession,
1758
+ yourgptConfig: config.yourgptConfig,
1759
+ streaming: config.streaming ?? true,
1760
+ headers: config.headers,
1761
+ initialMessages: config.initialMessages,
1762
+ state: reactState,
1763
+ callbacks: config.callbacks,
1764
+ debug: config.debug
1765
+ };
1766
+ super(init);
1767
+ // ============================================
1768
+ // Subscribe (for useSyncExternalStore)
1769
+ // ============================================
1770
+ /**
1771
+ * Subscribe to state changes.
1772
+ * Returns an unsubscribe function.
1773
+ *
1774
+ * @example
1775
+ * ```tsx
1776
+ * const messages = useSyncExternalStore(
1777
+ * chat.subscribe,
1778
+ * () => chat.messages
1779
+ * );
1780
+ * ```
1781
+ */
1782
+ this.subscribe = (callback) => {
1783
+ return this.reactState.subscribe(callback);
1784
+ };
1785
+ this.reactState = reactState;
1786
+ }
1787
+ // ============================================
1788
+ // Event handling shortcuts
1789
+ // ============================================
1790
+ /**
1791
+ * Subscribe to tool calls events
1792
+ */
1793
+ onToolCalls(handler) {
1794
+ return this.on("toolCalls", handler);
1795
+ }
1796
+ /**
1797
+ * Subscribe to done events
1798
+ */
1799
+ onDone(handler) {
1800
+ return this.on("done", handler);
1801
+ }
1802
+ /**
1803
+ * Subscribe to error events
1804
+ */
1805
+ onError(handler) {
1806
+ return this.on("error", handler);
1807
+ }
1808
+ // ============================================
1809
+ // Branching API — pass-throughs to ReactChatState
1810
+ // ============================================
1811
+ /**
1812
+ * Navigate to a sibling branch (makes it the active path).
1813
+ */
1814
+ switchBranch(messageId) {
1815
+ this.reactState.switchBranch(messageId);
1816
+ }
1817
+ /**
1818
+ * Get branch navigation info for a message.
1819
+ * Returns null if the message has no siblings.
1820
+ */
1821
+ getBranchInfo(messageId) {
1822
+ return this.reactState.getBranchInfo(messageId);
1823
+ }
1824
+ /**
1825
+ * Get all messages across all branches (for persistence).
1826
+ */
1827
+ getAllMessages() {
1828
+ return this.reactState.getAllMessages();
1829
+ }
1830
+ /**
1831
+ * Whether any message has siblings (branching has occurred).
1832
+ */
1833
+ get hasBranches() {
1834
+ return this.reactState.hasBranches;
1835
+ }
1836
+ // ============================================
1837
+ // Override dispose to clean up state
1838
+ // ============================================
1839
+ dispose() {
1840
+ super.dispose();
1841
+ this.reactState.dispose();
1842
+ }
1843
+ /**
1844
+ * Revive a disposed instance (for React StrictMode compatibility)
1845
+ */
1846
+ revive() {
1847
+ super.revive();
1848
+ this.reactState.revive();
1849
+ }
1850
+ };
1851
+ function createReactChat(config) {
1852
+ return new ReactChat(config);
1853
+ }
1854
+ function useChat(config) {
1855
+ const chatRef = react.useRef(null);
1856
+ const isThreadIdControlled = Object.prototype.hasOwnProperty.call(
1857
+ config,
1858
+ "threadId"
1859
+ );
1860
+ const lastControlledThreadIdRef = react.useRef({
1861
+ controlled: isThreadIdControlled,
1862
+ value: config.threadId
1863
+ });
1864
+ const [input, setInput] = react.useState("");
1865
+ if (chatRef.current !== null && chatRef.current.disposed) {
1866
+ chatRef.current.revive();
1867
+ }
1868
+ if (chatRef.current === null) {
1869
+ chatRef.current = createReactChat({
1870
+ runtimeUrl: config.runtimeUrl,
1871
+ systemPrompt: config.systemPrompt,
1872
+ llm: config.llm,
1873
+ threadId: config.threadId,
1874
+ onCreateSession: config.onCreateSession,
1875
+ yourgptConfig: config.yourgptConfig,
1876
+ streaming: config.streaming,
1877
+ headers: config.headers,
1878
+ initialMessages: config.initialMessages,
1879
+ debug: config.debug,
1880
+ callbacks: {
1881
+ onMessagesChange: config.onMessagesChange,
1882
+ onError: config.onError,
1883
+ onFinish: config.onFinish,
1884
+ onToolCalls: config.onToolCalls
1885
+ }
1886
+ });
1887
+ }
1888
+ react.useEffect(() => {
1889
+ const prev = lastControlledThreadIdRef.current;
1890
+ const controlChanged = prev.controlled !== isThreadIdControlled;
1891
+ const valueChanged = prev.value !== config.threadId;
1892
+ if (!controlChanged && !valueChanged) {
1893
+ return;
1894
+ }
1895
+ lastControlledThreadIdRef.current = {
1896
+ controlled: isThreadIdControlled,
1897
+ value: config.threadId
1898
+ };
1899
+ if (!isThreadIdControlled) {
1900
+ return;
1901
+ }
1902
+ chatRef.current?.setActiveThread(config.threadId ?? null);
1903
+ }, [config.threadId, isThreadIdControlled]);
1904
+ const messages = react.useSyncExternalStore(
1905
+ chatRef.current.subscribe,
1906
+ () => chatRef.current.messages,
1907
+ () => chatRef.current.messages
1908
+ // Server snapshot
1909
+ );
1910
+ const status = react.useSyncExternalStore(
1911
+ chatRef.current.subscribe,
1912
+ () => chatRef.current.status,
1913
+ () => "ready"
1914
+ // Server snapshot
1915
+ );
1916
+ const error = react.useSyncExternalStore(
1917
+ chatRef.current.subscribe,
1918
+ () => chatRef.current.error,
1919
+ () => void 0
1920
+ // Server snapshot
1921
+ );
1922
+ const hasBranches = react.useSyncExternalStore(
1923
+ chatRef.current.subscribe,
1924
+ () => chatRef.current.hasBranches,
1925
+ () => false
1926
+ );
1927
+ const isLoading = status === "streaming" || status === "submitted";
1928
+ const sendMessage = react.useCallback(
1929
+ async (content, attachments) => {
1930
+ await chatRef.current?.sendMessage(content, attachments);
1931
+ setInput("");
1932
+ },
1933
+ []
1934
+ );
1935
+ const stop = react.useCallback(() => {
1936
+ chatRef.current?.stop();
1937
+ }, []);
1938
+ const clearMessages = react.useCallback(() => {
1939
+ chatRef.current?.clearMessages();
1940
+ }, []);
1941
+ const setMessages = react.useCallback((messages2) => {
1942
+ chatRef.current?.setMessages(messages2);
1943
+ }, []);
1944
+ const regenerate = react.useCallback(async (messageId) => {
1945
+ await chatRef.current?.regenerate(messageId);
1946
+ }, []);
1947
+ const continueWithToolResults = react.useCallback(
1948
+ async (toolResults) => {
1949
+ await chatRef.current?.continueWithToolResults(toolResults);
1950
+ },
1951
+ []
1952
+ );
1953
+ const switchBranch = react.useCallback((messageId) => {
1954
+ chatRef.current?.switchBranch(messageId);
1955
+ }, []);
1956
+ const getBranchInfo = react.useCallback((messageId) => {
1957
+ return chatRef.current?.getBranchInfo(messageId) ?? null;
1958
+ }, []);
1959
+ const editMessage = react.useCallback(
1960
+ async (messageId, newContent) => {
1961
+ await chatRef.current?.sendMessage(newContent, void 0, {
1962
+ editMessageId: messageId
1963
+ });
1964
+ setInput("");
1965
+ },
1966
+ []
1967
+ );
1968
+ react.useEffect(() => {
1969
+ return () => {
1970
+ chatRef.current?.dispose();
1971
+ };
1972
+ }, []);
1973
+ return {
1974
+ messages,
1975
+ status,
1976
+ error,
1977
+ isLoading,
1978
+ input,
1979
+ setInput,
1980
+ sendMessage,
1981
+ stop,
1982
+ clearMessages,
1983
+ setMessages,
1984
+ regenerate,
1985
+ continueWithToolResults,
1986
+ chatRef,
1987
+ // Branching
1988
+ switchBranch,
1989
+ getBranchInfo,
1990
+ editMessage,
1991
+ hasBranches
1992
+ };
1993
+ }
1994
+
1995
+ // src/react/skill/define-skill.ts
1996
+ function defineSkill(def) {
1997
+ return def;
1998
+ }
1999
+ function useCopilotEvent(eventType, handler) {
2000
+ const { subscribeToStreamEvents } = chunk2QLF7XM7_cjs.useCopilot();
2001
+ const handlerRef = react.useRef(handler);
2002
+ handlerRef.current = handler;
2003
+ react.useEffect(() => {
2004
+ const unsub = subscribeToStreamEvents((chunk) => {
2005
+ if (eventType === "*" || chunk.type === eventType) {
2006
+ handlerRef.current(chunk);
2007
+ }
2008
+ });
2009
+ return unsub;
2010
+ }, [subscribeToStreamEvents, eventType]);
2011
+ }
2012
+ var EMPTY_META = {};
2013
+ function useMessageMeta(messageId) {
2014
+ const { messageMeta } = chunk2QLF7XM7_cjs.useCopilot();
2015
+ const meta = react.useSyncExternalStore(
2016
+ messageMeta.subscribe,
2017
+ () => messageId ? messageMeta.getMeta(messageId) : EMPTY_META,
2018
+ () => EMPTY_META
2019
+ );
2020
+ const setMeta = react.useCallback(
2021
+ (next) => {
2022
+ if (!messageId) return;
2023
+ messageMeta.setMeta(messageId, next);
2024
+ },
2025
+ [messageMeta, messageId]
2026
+ );
2027
+ const updateMeta = react.useCallback(
2028
+ (updater) => {
2029
+ if (!messageId) return;
2030
+ messageMeta.updateMeta(
2031
+ messageId,
2032
+ (prev) => updater(prev)
2033
+ );
2034
+ },
2035
+ [messageMeta, messageId]
2036
+ );
2037
+ return { meta, setMeta, updateMeta };
2038
+ }
2039
+
2040
+ exports.ReactChat = ReactChat;
2041
+ exports.ReactThreadManager = ReactThreadManager;
2042
+ exports.ReactThreadManagerState = ReactThreadManagerState;
2043
+ exports.createMessageIntentHandler = createMessageIntentHandler;
2044
+ exports.createPermissionStorage = createPermissionStorage;
2045
+ exports.createReactChat = createReactChat;
2046
+ exports.createReactThreadManager = createReactThreadManager;
2047
+ exports.createReactThreadManagerState = createReactThreadManagerState;
2048
+ exports.createSessionPermissionCache = createSessionPermissionCache;
2049
+ exports.createToolIntentHandler = createToolIntentHandler;
2050
+ exports.defineSkill = defineSkill;
2051
+ exports.formatKnowledgeResultsForAI = formatKnowledgeResultsForAI;
2052
+ exports.searchKnowledgeBase = searchKnowledgeBase;
2053
+ exports.useAIAction = useAIAction;
2054
+ exports.useAIActions = useAIActions;
2055
+ exports.useAITools = useAITools;
2056
+ exports.useAgent = useAgent;
2057
+ exports.useCapabilities = useCapabilities;
2058
+ exports.useChat = useChat;
2059
+ exports.useContextStats = useContextStats;
2060
+ exports.useCopilotEvent = useCopilotEvent;
2061
+ exports.useDevLogger = useDevLogger;
2062
+ exports.useFeatureSupport = useFeatureSupport;
2063
+ exports.useKnowledgeBase = useKnowledgeBase;
2064
+ exports.useMCPUIIntents = useMCPUIIntents;
2065
+ exports.useMessageCheckpoints = useMessageCheckpoints;
2066
+ exports.useMessageMeta = useMessageMeta;
2067
+ exports.useSkill = useSkill;
2068
+ exports.useSkillStatus = useSkillStatus;
2069
+ exports.useSuggestions = useSuggestions;
2070
+ exports.useSupportedMediaTypes = useSupportedMediaTypes;
2071
+ exports.useThread = useThread;
2072
+ exports.useThreadManager = useThreadManager;
2073
+ exports.useToolExecutor = useToolExecutor;
2074
+ exports.useToolWithSchema = useToolWithSchema;
2075
+ exports.useToolsWithSchema = useToolsWithSchema;
2076
+ //# sourceMappingURL=chunk-QTGEEBRW.cjs.map
2077
+ //# sourceMappingURL=chunk-QTGEEBRW.cjs.map