@assistant-ui/react 0.11.23 → 0.11.25

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.
@@ -278,8 +278,8 @@ export declare const useEditComposerAttachment: {
278
278
  file?: File;
279
279
  content?: import("../..").ThreadUserMessagePart[];
280
280
  } & {
281
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
282
- file: File;
281
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
282
+ content: import("../..").ThreadUserMessagePart[];
283
283
  } & {
284
284
  readonly source: "edit-composer";
285
285
  } & {
@@ -292,8 +292,8 @@ export declare const useEditComposerAttachment: {
292
292
  file?: File;
293
293
  content?: import("../..").ThreadUserMessagePart[];
294
294
  } & {
295
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
296
- content: import("../..").ThreadUserMessagePart[];
295
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
296
+ file: File;
297
297
  } & {
298
298
  readonly source: "edit-composer";
299
299
  } & {
@@ -307,8 +307,8 @@ export declare const useEditComposerAttachment: {
307
307
  file?: File;
308
308
  content?: import("../..").ThreadUserMessagePart[];
309
309
  } & {
310
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
311
- file: File;
310
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
311
+ content: import("../..").ThreadUserMessagePart[];
312
312
  } & {
313
313
  readonly source: "edit-composer";
314
314
  } & {
@@ -321,8 +321,8 @@ export declare const useEditComposerAttachment: {
321
321
  file?: File;
322
322
  content?: import("../..").ThreadUserMessagePart[];
323
323
  } & {
324
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
325
- content: import("../..").ThreadUserMessagePart[];
324
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
325
+ file: File;
326
326
  } & {
327
327
  readonly source: "edit-composer";
328
328
  } & {
@@ -336,8 +336,8 @@ export declare const useEditComposerAttachment: {
336
336
  file?: File;
337
337
  content?: import("../..").ThreadUserMessagePart[];
338
338
  } & {
339
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
340
- file: File;
339
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
340
+ content: import("../..").ThreadUserMessagePart[];
341
341
  } & {
342
342
  readonly source: "edit-composer";
343
343
  } & {
@@ -350,8 +350,8 @@ export declare const useEditComposerAttachment: {
350
350
  file?: File;
351
351
  content?: import("../..").ThreadUserMessagePart[];
352
352
  } & {
353
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
354
- content: import("../..").ThreadUserMessagePart[];
353
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
354
+ file: File;
355
355
  } & {
356
356
  readonly source: "edit-composer";
357
357
  } & {
@@ -364,8 +364,8 @@ export declare const useEditComposerAttachment: {
364
364
  file?: File;
365
365
  content?: import("../..").ThreadUserMessagePart[];
366
366
  } & {
367
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
368
- file: File;
367
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
368
+ content: import("../..").ThreadUserMessagePart[];
369
369
  } & {
370
370
  readonly source: "edit-composer";
371
371
  } & {
@@ -378,8 +378,8 @@ export declare const useEditComposerAttachment: {
378
378
  file?: File;
379
379
  content?: import("../..").ThreadUserMessagePart[];
380
380
  } & {
381
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
382
- content: import("../..").ThreadUserMessagePart[];
381
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
382
+ file: File;
383
383
  } & {
384
384
  readonly source: "edit-composer";
385
385
  } & {
@@ -395,8 +395,8 @@ export declare const useEditComposerAttachment: {
395
395
  file?: File;
396
396
  content?: import("../..").ThreadUserMessagePart[];
397
397
  } & {
398
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
399
- file: File;
398
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
399
+ content: import("../..").ThreadUserMessagePart[];
400
400
  } & {
401
401
  readonly source: "edit-composer";
402
402
  } & {
@@ -409,8 +409,8 @@ export declare const useEditComposerAttachment: {
409
409
  file?: File;
410
410
  content?: import("../..").ThreadUserMessagePart[];
411
411
  } & {
412
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
413
- content: import("../..").ThreadUserMessagePart[];
412
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
413
+ file: File;
414
414
  } & {
415
415
  readonly source: "edit-composer";
416
416
  } & {
@@ -426,8 +426,8 @@ export declare const useEditComposerAttachment: {
426
426
  file?: File;
427
427
  content?: import("../..").ThreadUserMessagePart[];
428
428
  } & {
429
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
430
- file: File;
429
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
430
+ content: import("../..").ThreadUserMessagePart[];
431
431
  } & {
432
432
  readonly source: "edit-composer";
433
433
  } & {
@@ -440,8 +440,8 @@ export declare const useEditComposerAttachment: {
440
440
  file?: File;
441
441
  content?: import("../..").ThreadUserMessagePart[];
442
442
  } & {
443
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
444
- content: import("../..").ThreadUserMessagePart[];
443
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
444
+ file: File;
445
445
  } & {
446
446
  readonly source: "edit-composer";
447
447
  } & {
@@ -457,8 +457,8 @@ export declare const useEditComposerAttachment: {
457
457
  file?: File;
458
458
  content?: import("../..").ThreadUserMessagePart[];
459
459
  } & {
460
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
461
- file: File;
460
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
461
+ content: import("../..").ThreadUserMessagePart[];
462
462
  } & {
463
463
  readonly source: "edit-composer";
464
464
  } & {
@@ -471,8 +471,8 @@ export declare const useEditComposerAttachment: {
471
471
  file?: File;
472
472
  content?: import("../..").ThreadUserMessagePart[];
473
473
  } & {
474
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
475
- content: import("../..").ThreadUserMessagePart[];
474
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
475
+ file: File;
476
476
  } & {
477
477
  readonly source: "edit-composer";
478
478
  } & {
@@ -489,8 +489,8 @@ export declare const useEditComposerAttachment: {
489
489
  file?: File;
490
490
  content?: import("../..").ThreadUserMessagePart[];
491
491
  } & {
492
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
493
- file: File;
492
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
493
+ content: import("../..").ThreadUserMessagePart[];
494
494
  } & {
495
495
  readonly source: "edit-composer";
496
496
  } & {
@@ -503,8 +503,8 @@ export declare const useEditComposerAttachment: {
503
503
  file?: File;
504
504
  content?: import("../..").ThreadUserMessagePart[];
505
505
  } & {
506
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
507
- content: import("../..").ThreadUserMessagePart[];
506
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
507
+ file: File;
508
508
  } & {
509
509
  readonly source: "edit-composer";
510
510
  } & {
@@ -518,8 +518,8 @@ export declare const useEditComposerAttachment: {
518
518
  file?: File;
519
519
  content?: import("../..").ThreadUserMessagePart[];
520
520
  } & {
521
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
522
- file: File;
521
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
522
+ content: import("../..").ThreadUserMessagePart[];
523
523
  } & {
524
524
  readonly source: "edit-composer";
525
525
  } & {
@@ -532,8 +532,8 @@ export declare const useEditComposerAttachment: {
532
532
  file?: File;
533
533
  content?: import("../..").ThreadUserMessagePart[];
534
534
  } & {
535
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
536
- content: import("../..").ThreadUserMessagePart[];
535
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
536
+ file: File;
537
537
  } & {
538
538
  readonly source: "edit-composer";
539
539
  } & {
@@ -549,8 +549,8 @@ export declare const useEditComposerAttachment: {
549
549
  file?: File;
550
550
  content?: import("../..").ThreadUserMessagePart[];
551
551
  } & {
552
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
553
- file: File;
552
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
553
+ content: import("../..").ThreadUserMessagePart[];
554
554
  } & {
555
555
  readonly source: "edit-composer";
556
556
  } & {
@@ -563,8 +563,8 @@ export declare const useEditComposerAttachment: {
563
563
  file?: File;
564
564
  content?: import("../..").ThreadUserMessagePart[];
565
565
  } & {
566
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
567
- content: import("../..").ThreadUserMessagePart[];
566
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
567
+ file: File;
568
568
  } & {
569
569
  readonly source: "edit-composer";
570
570
  } & {
@@ -581,8 +581,8 @@ export declare const useEditComposerAttachment: {
581
581
  file?: File;
582
582
  content?: import("../..").ThreadUserMessagePart[];
583
583
  } & {
584
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
585
- file: File;
584
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
585
+ content: import("../..").ThreadUserMessagePart[];
586
586
  } & {
587
587
  readonly source: "edit-composer";
588
588
  } & {
@@ -595,8 +595,8 @@ export declare const useEditComposerAttachment: {
595
595
  file?: File;
596
596
  content?: import("../..").ThreadUserMessagePart[];
597
597
  } & {
598
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
599
- content: import("../..").ThreadUserMessagePart[];
598
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
599
+ file: File;
600
600
  } & {
601
601
  readonly source: "edit-composer";
602
602
  } & {
@@ -610,8 +610,8 @@ export declare const useEditComposerAttachment: {
610
610
  file?: File;
611
611
  content?: import("../..").ThreadUserMessagePart[];
612
612
  } & {
613
- status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
614
- file: File;
613
+ status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
614
+ content: import("../..").ThreadUserMessagePart[];
615
615
  } & {
616
616
  readonly source: "edit-composer";
617
617
  } & {
@@ -624,8 +624,8 @@ export declare const useEditComposerAttachment: {
624
624
  file?: File;
625
625
  content?: import("../..").ThreadUserMessagePart[];
626
626
  } & {
627
- status: import("../../types/AttachmentTypes").CompleteAttachmentStatus;
628
- content: import("../..").ThreadUserMessagePart[];
627
+ status: import("../../types/AttachmentTypes").PendingAttachmentStatus;
628
+ file: File;
629
629
  } & {
630
630
  readonly source: "edit-composer";
631
631
  } & {
@@ -1 +1 @@
1
- {"version":3,"file":"useToolInvocations.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,IAAI,EACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,yBAAyB,EACzB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAejB,KAAK,wBAAwB,GAAG;IAC9B,KAAK,EAAE,uBAAuB,CAAC;IAC/B,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACvD,eAAe,EAAE,CACf,OAAO,EACH,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACnC,CAAC,CACC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,KACtC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,KAC1C,IAAI,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,CAAC;AAExE,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB;;;yBAgLF,MAAM,WAAW,OAAO;EAehD"}
1
+ {"version":3,"file":"useToolInvocations.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,IAAI,EACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,yBAAyB,EACzB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAejB,KAAK,wBAAwB,GAAG;IAC9B,KAAK,EAAE,uBAAuB,CAAC;IAC/B,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACvD,eAAe,EAAE,CACf,OAAO,EACH,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACnC,CAAC,CACC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,KACtC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,KAC1C,IAAI,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,CAAC;AAExE,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB;;;yBA2LF,MAAM,WAAW,OAAO;EAiBhD"}
@@ -41,7 +41,10 @@ function useToolInvocations({
41
41
  humanInputRef.current.set(toolCallId, { resolve, reject });
42
42
  setToolStatuses((prev) => ({
43
43
  ...prev,
44
- [toolCallId]: { type: "interrupt", payload: { type: "human", payload } }
44
+ [toolCallId]: {
45
+ type: "interrupt",
46
+ payload: { type: "human", payload }
47
+ }
45
48
  }));
46
49
  });
47
50
  }
@@ -74,72 +77,74 @@ function useToolInvocations({
74
77
  const ignoredToolIds = useRef(/* @__PURE__ */ new Set());
75
78
  const isInititialState = useRef(true);
76
79
  useEffect(() => {
77
- if (isInititialState.current) {
78
- state.messages.forEach((message) => {
79
- message.content.forEach((content) => {
80
- if (content.type === "tool-call") {
81
- ignoredToolIds.current.add(content.toolCallId);
82
- }
83
- });
84
- });
85
- isInititialState.current = false;
86
- } else {
87
- state.messages.forEach((message) => {
80
+ const processMessages = (messages) => {
81
+ messages.forEach((message) => {
88
82
  message.content.forEach((content) => {
89
83
  if (content.type === "tool-call") {
90
- if (ignoredToolIds.current.has(content.toolCallId)) {
91
- return;
92
- }
93
- let lastState = lastToolStates.current[content.toolCallId];
94
- if (!lastState) {
95
- const toolCallController = controller.addToolCallPart({
96
- toolName: content.toolName,
97
- toolCallId: content.toolCallId
98
- });
99
- lastState = {
100
- argsText: "",
101
- hasResult: false,
102
- controller: toolCallController
103
- };
104
- lastToolStates.current[content.toolCallId] = lastState;
105
- }
106
- if (content.argsText !== lastState.argsText) {
107
- if (!content.argsText.startsWith(lastState.argsText)) {
108
- throw new Error(
109
- `Tool call argsText can only be appended, not updated: ${content.argsText} does not start with ${lastState.argsText}`
84
+ if (isInititialState.current) {
85
+ ignoredToolIds.current.add(content.toolCallId);
86
+ } else {
87
+ if (ignoredToolIds.current.has(content.toolCallId)) {
88
+ return;
89
+ }
90
+ let lastState = lastToolStates.current[content.toolCallId];
91
+ if (!lastState) {
92
+ const toolCallController = controller.addToolCallPart({
93
+ toolName: content.toolName,
94
+ toolCallId: content.toolCallId
95
+ });
96
+ lastState = {
97
+ argsText: "",
98
+ hasResult: false,
99
+ controller: toolCallController
100
+ };
101
+ lastToolStates.current[content.toolCallId] = lastState;
102
+ }
103
+ if (content.argsText !== lastState.argsText) {
104
+ if (!content.argsText.startsWith(lastState.argsText)) {
105
+ throw new Error(
106
+ `Tool call argsText can only be appended, not updated: ${content.argsText} does not start with ${lastState.argsText}`
107
+ );
108
+ }
109
+ const argsTextDelta = content.argsText.slice(
110
+ lastState.argsText.length
110
111
  );
112
+ lastState.controller.argsText.append(argsTextDelta);
113
+ if (isArgsTextComplete(content.argsText)) {
114
+ lastState.controller.argsText.close();
115
+ }
116
+ lastToolStates.current[content.toolCallId] = {
117
+ argsText: content.argsText,
118
+ hasResult: lastState.hasResult,
119
+ controller: lastState.controller
120
+ };
111
121
  }
112
- const argsTextDelta = content.argsText.slice(
113
- lastState.argsText.length
114
- );
115
- lastState.controller.argsText.append(argsTextDelta);
116
- if (isArgsTextComplete(content.argsText)) {
117
- lastState.controller.argsText.close();
122
+ if (content.result !== void 0 && !lastState.hasResult) {
123
+ lastState.controller.setResponse(
124
+ new ToolResponse({
125
+ result: content.result,
126
+ artifact: content.artifact,
127
+ isError: content.isError
128
+ })
129
+ );
130
+ lastState.controller.close();
131
+ lastToolStates.current[content.toolCallId] = {
132
+ hasResult: true,
133
+ argsText: lastState.argsText,
134
+ controller: lastState.controller
135
+ };
118
136
  }
119
- lastToolStates.current[content.toolCallId] = {
120
- argsText: content.argsText,
121
- hasResult: lastState.hasResult,
122
- controller: lastState.controller
123
- };
124
137
  }
125
- if (content.result !== void 0 && !lastState.hasResult) {
126
- lastState.controller.setResponse(
127
- new ToolResponse({
128
- result: content.result,
129
- artifact: content.artifact,
130
- isError: content.isError
131
- })
132
- );
133
- lastState.controller.close();
134
- lastToolStates.current[content.toolCallId] = {
135
- hasResult: true,
136
- argsText: lastState.argsText,
137
- controller: lastState.controller
138
- };
138
+ if (content.messages) {
139
+ processMessages(content.messages);
139
140
  }
140
141
  }
141
142
  });
142
143
  });
144
+ };
145
+ processMessages(state.messages);
146
+ if (isInititialState.current) {
147
+ isInititialState.current = false;
143
148
  }
144
149
  }, [state, controller, onResult]);
145
150
  const abort = () => {
@@ -168,7 +173,9 @@ function useToolInvocations({
168
173
  });
169
174
  handlers.resolve(payload);
170
175
  } else {
171
- throw new Error(`Tool call ${toolCallId} is not waiting for human input`);
176
+ throw new Error(
177
+ `Tool call ${toolCallId} is not waiting for human input`
178
+ );
172
179
  }
173
180
  }
174
181
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n createAssistantStreamController,\n ToolCallStreamController,\n ToolResponse,\n unstable_toolResultStream,\n type Tool,\n} from \"assistant-stream\";\nimport type {\n AssistantTransportCommand,\n AssistantTransportState,\n} from \"./types\";\nimport {\n AssistantMetaTransformStream,\n type ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\nconst isArgsTextComplete = (argsText: string) => {\n try {\n JSON.parse(argsText);\n return true;\n } catch {\n return false;\n }\n};\n\ntype UseToolInvocationsParams = {\n state: AssistantTransportState;\n getTools: () => Record<string, Tool> | undefined;\n onResult: (command: AssistantTransportCommand) => void;\n setToolStatuses: (\n updater:\n | Record<string, ToolExecutionStatus>\n | ((\n prev: Record<string, ToolExecutionStatus>,\n ) => Record<string, ToolExecutionStatus>),\n ) => void;\n};\n\nexport type ToolExecutionStatus =\n | { type: \"executing\" }\n | { type: \"interrupt\"; payload: { type: \"human\"; payload: unknown } };\n\nexport function useToolInvocations({\n state,\n getTools,\n onResult,\n setToolStatuses,\n}: UseToolInvocationsParams) {\n const lastToolStates = useRef<\n Record<\n string,\n {\n argsText: string;\n hasResult: boolean;\n controller: ToolCallStreamController;\n }\n >\n >({});\n\n const humanInputRef = useRef<\n Map<\n string,\n {\n resolve: (payload: unknown) => void;\n reject: (reason: unknown) => void;\n }\n >\n >(new Map());\n\n const acRef = useRef<AbortController>(new AbortController());\n const [controller] = useState(() => {\n const [stream, controller] = createAssistantStreamController();\n const transform = unstable_toolResultStream(\n getTools,\n () => acRef.current?.signal ?? new AbortController().signal,\n (toolCallId: string, payload: unknown) => {\n return new Promise<unknown>((resolve, reject) => {\n // Reject previous human input request if it exists\n const previous = humanInputRef.current.get(toolCallId);\n if (previous) {\n previous.reject(\n new Error(\"Human input request was superseded by a new request\"),\n );\n }\n\n humanInputRef.current.set(toolCallId, { resolve, reject });\n setToolStatuses((prev) => ({\n ...prev,\n [toolCallId]: { type: \"interrupt\", payload: { type: \"human\", payload } },\n }));\n });\n },\n );\n stream\n .pipeThrough(transform)\n .pipeThrough(new AssistantMetaTransformStream())\n .pipeTo(\n new WritableStream({\n write(chunk) {\n if (chunk.type === \"result\") {\n // the tool call result was already set by the backend\n if (lastToolStates.current[chunk.meta.toolCallId]?.hasResult)\n return;\n\n onResult({\n type: \"add-tool-result\",\n toolCallId: chunk.meta.toolCallId,\n toolName: chunk.meta.toolName,\n result: chunk.result,\n isError: chunk.isError,\n ...(chunk.artifact && { artifact: chunk.artifact }),\n });\n\n // Clear status when result is set\n setToolStatuses((prev) => {\n const next = { ...prev };\n delete next[chunk.meta.toolCallId];\n return next;\n });\n }\n },\n }),\n );\n\n return controller;\n });\n\n const ignoredToolIds = useRef<Set<string>>(new Set());\n const isInititialState = useRef(true);\n\n useEffect(() => {\n if (isInititialState.current) {\n state.messages.forEach((message) => {\n message.content.forEach((content) => {\n if (content.type === \"tool-call\") {\n ignoredToolIds.current.add(content.toolCallId);\n }\n });\n });\n isInititialState.current = false;\n } else {\n state.messages.forEach((message) => {\n message.content.forEach((content) => {\n if (content.type === \"tool-call\") {\n if (ignoredToolIds.current.has(content.toolCallId)) {\n return;\n }\n let lastState = lastToolStates.current[content.toolCallId];\n if (!lastState) {\n const toolCallController = controller.addToolCallPart({\n toolName: content.toolName,\n toolCallId: content.toolCallId,\n });\n lastState = {\n argsText: \"\",\n hasResult: false,\n controller: toolCallController,\n };\n lastToolStates.current[content.toolCallId] = lastState;\n }\n\n if (content.argsText !== lastState.argsText) {\n if (!content.argsText.startsWith(lastState.argsText)) {\n throw new Error(\n `Tool call argsText can only be appended, not updated: ${content.argsText} does not start with ${lastState.argsText}`,\n );\n }\n\n const argsTextDelta = content.argsText.slice(\n lastState.argsText.length,\n );\n lastState.controller.argsText.append(argsTextDelta);\n\n if (isArgsTextComplete(content.argsText)) {\n lastState.controller.argsText.close();\n }\n\n lastToolStates.current[content.toolCallId] = {\n argsText: content.argsText,\n hasResult: lastState.hasResult,\n controller: lastState.controller,\n };\n }\n\n if (content.result !== undefined && !lastState.hasResult) {\n lastState.controller.setResponse(\n new ToolResponse({\n result: content.result as ReadonlyJSONValue,\n artifact: content.artifact as ReadonlyJSONValue | undefined,\n isError: content.isError,\n }),\n );\n lastState.controller.close();\n\n lastToolStates.current[content.toolCallId] = {\n hasResult: true,\n argsText: lastState.argsText,\n controller: lastState.controller,\n };\n }\n }\n });\n });\n }\n }, [state, controller, onResult]);\n\n const abort = () => {\n humanInputRef.current.forEach(({ reject }) => {\n reject(new Error(\"Tool execution aborted\"));\n });\n humanInputRef.current.clear();\n setToolStatuses({});\n\n acRef.current.abort();\n acRef.current = new AbortController();\n };\n\n return {\n reset: () => {\n abort();\n isInititialState.current = true;\n },\n abort,\n resume: (toolCallId: string, payload: unknown) => {\n const handlers = humanInputRef.current.get(toolCallId);\n if (handlers) {\n humanInputRef.current.delete(toolCallId);\n setToolStatuses((prev) => {\n const next = { ...prev };\n delete next[toolCallId];\n return next;\n });\n handlers.resolve(payload);\n } else {\n throw new Error(`Tool call ${toolCallId} is not waiting for human input`);\n }\n },\n };\n}\n"],"mappings":"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","names":["controller"]}
1
+ {"version":3,"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n createAssistantStreamController,\n ToolCallStreamController,\n ToolResponse,\n unstable_toolResultStream,\n type Tool,\n} from \"assistant-stream\";\nimport type {\n AssistantTransportCommand,\n AssistantTransportState,\n} from \"./types\";\nimport {\n AssistantMetaTransformStream,\n type ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\nconst isArgsTextComplete = (argsText: string) => {\n try {\n JSON.parse(argsText);\n return true;\n } catch {\n return false;\n }\n};\n\ntype UseToolInvocationsParams = {\n state: AssistantTransportState;\n getTools: () => Record<string, Tool> | undefined;\n onResult: (command: AssistantTransportCommand) => void;\n setToolStatuses: (\n updater:\n | Record<string, ToolExecutionStatus>\n | ((\n prev: Record<string, ToolExecutionStatus>,\n ) => Record<string, ToolExecutionStatus>),\n ) => void;\n};\n\nexport type ToolExecutionStatus =\n | { type: \"executing\" }\n | { type: \"interrupt\"; payload: { type: \"human\"; payload: unknown } };\n\nexport function useToolInvocations({\n state,\n getTools,\n onResult,\n setToolStatuses,\n}: UseToolInvocationsParams) {\n const lastToolStates = useRef<\n Record<\n string,\n {\n argsText: string;\n hasResult: boolean;\n controller: ToolCallStreamController;\n }\n >\n >({});\n\n const humanInputRef = useRef<\n Map<\n string,\n {\n resolve: (payload: unknown) => void;\n reject: (reason: unknown) => void;\n }\n >\n >(new Map());\n\n const acRef = useRef<AbortController>(new AbortController());\n const [controller] = useState(() => {\n const [stream, controller] = createAssistantStreamController();\n const transform = unstable_toolResultStream(\n getTools,\n () => acRef.current?.signal ?? new AbortController().signal,\n (toolCallId: string, payload: unknown) => {\n return new Promise<unknown>((resolve, reject) => {\n // Reject previous human input request if it exists\n const previous = humanInputRef.current.get(toolCallId);\n if (previous) {\n previous.reject(\n new Error(\"Human input request was superseded by a new request\"),\n );\n }\n\n humanInputRef.current.set(toolCallId, { resolve, reject });\n setToolStatuses((prev) => ({\n ...prev,\n [toolCallId]: {\n type: \"interrupt\",\n payload: { type: \"human\", payload },\n },\n }));\n });\n },\n );\n stream\n .pipeThrough(transform)\n .pipeThrough(new AssistantMetaTransformStream())\n .pipeTo(\n new WritableStream({\n write(chunk) {\n if (chunk.type === \"result\") {\n // the tool call result was already set by the backend\n if (lastToolStates.current[chunk.meta.toolCallId]?.hasResult)\n return;\n\n onResult({\n type: \"add-tool-result\",\n toolCallId: chunk.meta.toolCallId,\n toolName: chunk.meta.toolName,\n result: chunk.result,\n isError: chunk.isError,\n ...(chunk.artifact && { artifact: chunk.artifact }),\n });\n\n // Clear status when result is set\n setToolStatuses((prev) => {\n const next = { ...prev };\n delete next[chunk.meta.toolCallId];\n return next;\n });\n }\n },\n }),\n );\n\n return controller;\n });\n\n const ignoredToolIds = useRef<Set<string>>(new Set());\n const isInititialState = useRef(true);\n\n useEffect(() => {\n const processMessages = (\n messages: readonly (typeof state.messages)[number][],\n ) => {\n messages.forEach((message) => {\n message.content.forEach((content) => {\n if (content.type === \"tool-call\") {\n if (isInititialState.current) {\n ignoredToolIds.current.add(content.toolCallId);\n } else {\n if (ignoredToolIds.current.has(content.toolCallId)) {\n return;\n }\n let lastState = lastToolStates.current[content.toolCallId];\n if (!lastState) {\n const toolCallController = controller.addToolCallPart({\n toolName: content.toolName,\n toolCallId: content.toolCallId,\n });\n lastState = {\n argsText: \"\",\n hasResult: false,\n controller: toolCallController,\n };\n lastToolStates.current[content.toolCallId] = lastState;\n }\n\n if (content.argsText !== lastState.argsText) {\n if (!content.argsText.startsWith(lastState.argsText)) {\n throw new Error(\n `Tool call argsText can only be appended, not updated: ${content.argsText} does not start with ${lastState.argsText}`,\n );\n }\n\n const argsTextDelta = content.argsText.slice(\n lastState.argsText.length,\n );\n lastState.controller.argsText.append(argsTextDelta);\n\n if (isArgsTextComplete(content.argsText)) {\n lastState.controller.argsText.close();\n }\n\n lastToolStates.current[content.toolCallId] = {\n argsText: content.argsText,\n hasResult: lastState.hasResult,\n controller: lastState.controller,\n };\n }\n\n if (content.result !== undefined && !lastState.hasResult) {\n lastState.controller.setResponse(\n new ToolResponse({\n result: content.result as ReadonlyJSONValue,\n artifact: content.artifact as ReadonlyJSONValue | undefined,\n isError: content.isError,\n }),\n );\n lastState.controller.close();\n\n lastToolStates.current[content.toolCallId] = {\n hasResult: true,\n argsText: lastState.argsText,\n controller: lastState.controller,\n };\n }\n }\n\n // Recursively process nested messages\n if (content.messages) {\n processMessages(content.messages);\n }\n }\n });\n });\n };\n\n processMessages(state.messages);\n\n if (isInititialState.current) {\n isInititialState.current = false;\n }\n }, [state, controller, onResult]);\n\n const abort = () => {\n humanInputRef.current.forEach(({ reject }) => {\n reject(new Error(\"Tool execution aborted\"));\n });\n humanInputRef.current.clear();\n setToolStatuses({});\n\n acRef.current.abort();\n acRef.current = new AbortController();\n };\n\n return {\n reset: () => {\n abort();\n isInititialState.current = true;\n },\n abort,\n resume: (toolCallId: string, payload: unknown) => {\n const handlers = humanInputRef.current.get(toolCallId);\n if (handlers) {\n humanInputRef.current.delete(toolCallId);\n setToolStatuses((prev) => {\n const next = { ...prev };\n delete next[toolCallId];\n return next;\n });\n handlers.resolve(payload);\n } else {\n throw new Error(\n `Tool call ${toolCallId} is not waiting for human input`,\n );\n }\n },\n };\n}\n"],"mappings":"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","names":["controller"]}
@@ -1,8 +1,24 @@
1
1
  import { ActionButtonElement, ActionButtonProps } from "../../utils/createActionButton";
2
- declare const useThreadSuggestion: ({ prompt, autoSend, }: {
2
+ declare const useThreadSuggestion: ({ prompt, send, clearComposer, autoSend, method: _method, }: {
3
+ /** The suggestion prompt. */
3
4
  prompt: string;
4
- method?: "replace";
5
+ /**
6
+ * When true, automatically sends the message.
7
+ * When false, replaces or appends the composer text with the suggestion - depending on the value of `clearComposer`.
8
+ */
9
+ send?: boolean | undefined;
10
+ /**
11
+ * Whether to clear the composer after sending.
12
+ * When send is set to false, determines if composer text is replaced with suggestion (true, default),
13
+ * or if it's appended to the composer text (false).
14
+ *
15
+ * @default true
16
+ */
17
+ clearComposer?: boolean | undefined;
18
+ /** @deprecated Use `send` instead. */
5
19
  autoSend?: boolean | undefined;
20
+ /** @deprecated Use `clearComposer` instead. */
21
+ method?: "replace";
6
22
  }) => (() => void) | null;
7
23
  export declare namespace ThreadPrimitiveSuggestion {
8
24
  type Element = ActionButtonElement;
@@ -11,9 +27,25 @@ export declare namespace ThreadPrimitiveSuggestion {
11
27
  export declare const ThreadPrimitiveSuggestion: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement> & {
12
28
  asChild?: boolean;
13
29
  }, "ref"> & {
30
+ /** The suggestion prompt. */
14
31
  prompt: string;
15
- method?: "replace";
32
+ /**
33
+ * When true, automatically sends the message.
34
+ * When false, replaces or appends the composer text with the suggestion - depending on the value of `clearComposer`.
35
+ */
36
+ send?: boolean | undefined;
37
+ /**
38
+ * Whether to clear the composer after sending.
39
+ * When send is set to false, determines if composer text is replaced with suggestion (true, default),
40
+ * or if it's appended to the composer text (false).
41
+ *
42
+ * @default true
43
+ */
44
+ clearComposer?: boolean | undefined;
45
+ /** @deprecated Use `send` instead. */
16
46
  autoSend?: boolean | undefined;
47
+ /** @deprecated Use `clearComposer` instead. */
48
+ method?: "replace";
17
49
  } & import("react").RefAttributes<HTMLButtonElement>>;
18
50
  export {};
19
51
  //# sourceMappingURL=ThreadSuggestion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadSuggestion.d.ts","sourceRoot":"","sources":["../../../src/primitives/thread/ThreadSuggestion.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;AAIxC,QAAA,MAAM,mBAAmB,GAAI,uBAG1B;IACD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC,wBAeA,CAAC;AAEF,yBAAiB,yBAAyB,CAAC;IACzC,KAAY,OAAO,GAAG,mBAAmB,CAAC;IAC1C,KAAY,KAAK,GAAG,iBAAiB,CAAC,OAAO,mBAAmB,CAAC,CAAC;CACnE;AAED,eAAO,MAAM,yBAAyB;;;YAzB5B,MAAM;aACL,SAAS;eACP,OAAO,GAAG,SAAS;qDA2B/B,CAAC"}
1
+ {"version":3,"file":"ThreadSuggestion.d.ts","sourceRoot":"","sources":["../../../src/primitives/thread/ThreadSuggestion.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;AAIxC,QAAA,MAAM,mBAAmB,GAAI,6DAM1B;IACD,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE3B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAEpC,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE/B,+CAA+C;IAC/C,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,wBA8BA,CAAC;AAEF,yBAAiB,yBAAyB,CAAC;IACzC,KAAY,OAAO,GAAG,mBAAmB,CAAC;IAC1C,KAAY,KAAK,GAAG,iBAAiB,CAAC,OAAO,mBAAmB,CAAC,CAAC;CACnE;AAED,eAAO,MAAM,yBAAyB;;;IA5DpC,6BAA6B;YACrB,MAAM;IAEd;;;OAGG;WACI,OAAO,GAAG,SAAS;IAE1B;;;;;;OAMG;oBACa,OAAO,GAAG,SAAS;IAEnC,sCAAsC;eAC3B,OAAO,GAAG,SAAS;IAE9B,+CAA+C;aACtC,SAAS;qDA0CnB,CAAC"}
@@ -8,25 +8,37 @@ import { useCallback } from "react";
8
8
  import { useAssistantState, useAssistantApi } from "../../context/index.js";
9
9
  var useThreadSuggestion = ({
10
10
  prompt,
11
- autoSend
11
+ send,
12
+ clearComposer = true,
13
+ autoSend,
14
+ method: _method
12
15
  }) => {
13
16
  const api = useAssistantApi();
14
17
  const disabled = useAssistantState(({ thread }) => thread.isDisabled);
18
+ const resolvedSend = send ?? autoSend ?? false;
15
19
  const callback = useCallback(() => {
16
20
  const isRunning = api.thread().getState().isRunning;
17
- if (autoSend && !isRunning) {
21
+ if (resolvedSend && !isRunning) {
18
22
  api.thread().append(prompt);
23
+ if (clearComposer) {
24
+ api.composer().setText("");
25
+ }
19
26
  } else {
20
- api.composer().setText(prompt);
27
+ if (clearComposer) {
28
+ api.composer().setText(prompt);
29
+ } else {
30
+ const currentText = api.composer().getState().text;
31
+ api.composer().setText(currentText.trim() ? `${currentText} ${prompt}` : prompt);
32
+ }
21
33
  }
22
- }, [api, autoSend, prompt]);
34
+ }, [api, resolvedSend, clearComposer, prompt]);
23
35
  if (disabled) return null;
24
36
  return callback;
25
37
  };
26
38
  var ThreadPrimitiveSuggestion = createActionButton(
27
39
  "ThreadPrimitive.Suggestion",
28
40
  useThreadSuggestion,
29
- ["prompt", "autoSend", "method"]
41
+ ["prompt", "send", "clearComposer", "autoSend", "method"]
30
42
  );
31
43
  export {
32
44
  ThreadPrimitiveSuggestion
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/primitives/thread/ThreadSuggestion.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ActionButtonElement,\n ActionButtonProps,\n createActionButton,\n} from \"../../utils/createActionButton\";\nimport { useCallback } from \"react\";\nimport { useAssistantState, useAssistantApi } from \"../../context\";\n\nconst useThreadSuggestion = ({\n prompt,\n autoSend,\n}: {\n prompt: string;\n method?: \"replace\";\n autoSend?: boolean | undefined;\n}) => {\n const api = useAssistantApi();\n const disabled = useAssistantState(({ thread }) => thread.isDisabled);\n\n const callback = useCallback(() => {\n const isRunning = api.thread().getState().isRunning;\n if (autoSend && !isRunning) {\n api.thread().append(prompt);\n } else {\n api.composer().setText(prompt);\n }\n }, [api, autoSend, prompt]);\n\n if (disabled) return null;\n return callback;\n};\n\nexport namespace ThreadPrimitiveSuggestion {\n export type Element = ActionButtonElement;\n export type Props = ActionButtonProps<typeof useThreadSuggestion>;\n}\n\nexport const ThreadPrimitiveSuggestion = createActionButton(\n \"ThreadPrimitive.Suggestion\",\n useThreadSuggestion,\n [\"prompt\", \"autoSend\", \"method\"],\n);\n"],"mappings":";;;AAEA;AAAA,EAGE;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB,uBAAuB;AAEnD,IAAM,sBAAsB,CAAC;AAAA,EAC3B;AAAA,EACA;AACF,MAIM;AACJ,QAAM,MAAM,gBAAgB;AAC5B,QAAM,WAAW,kBAAkB,CAAC,EAAE,OAAO,MAAM,OAAO,UAAU;AAEpE,QAAM,WAAW,YAAY,MAAM;AACjC,UAAM,YAAY,IAAI,OAAO,EAAE,SAAS,EAAE;AAC1C,QAAI,YAAY,CAAC,WAAW;AAC1B,UAAI,OAAO,EAAE,OAAO,MAAM;AAAA,IAC5B,OAAO;AACL,UAAI,SAAS,EAAE,QAAQ,MAAM;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,KAAK,UAAU,MAAM,CAAC;AAE1B,MAAI,SAAU,QAAO;AACrB,SAAO;AACT;AAOO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA,CAAC,UAAU,YAAY,QAAQ;AACjC;","names":[]}
1
+ {"version":3,"sources":["../../../src/primitives/thread/ThreadSuggestion.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ActionButtonElement,\n ActionButtonProps,\n createActionButton,\n} from \"../../utils/createActionButton\";\nimport { useCallback } from \"react\";\nimport { useAssistantState, useAssistantApi } from \"../../context\";\n\nconst useThreadSuggestion = ({\n prompt,\n send,\n clearComposer = true,\n autoSend,\n method: _method,\n}: {\n /** The suggestion prompt. */\n prompt: string;\n\n /**\n * When true, automatically sends the message.\n * When false, replaces or appends the composer text with the suggestion - depending on the value of `clearComposer`.\n */\n send?: boolean | undefined;\n\n /**\n * Whether to clear the composer after sending.\n * When send is set to false, determines if composer text is replaced with suggestion (true, default),\n * or if it's appended to the composer text (false).\n *\n * @default true\n */\n clearComposer?: boolean | undefined;\n\n /** @deprecated Use `send` instead. */\n autoSend?: boolean | undefined;\n\n /** @deprecated Use `clearComposer` instead. */\n method?: \"replace\";\n}) => {\n const api = useAssistantApi();\n const disabled = useAssistantState(({ thread }) => thread.isDisabled);\n\n // ========== Deprecation Mapping ==========\n const resolvedSend = send ?? autoSend ?? false;\n // ==========================================\n\n const callback = useCallback(() => {\n const isRunning = api.thread().getState().isRunning;\n\n if (resolvedSend && !isRunning) {\n api.thread().append(prompt);\n if (clearComposer) {\n api.composer().setText(\"\");\n }\n } else {\n if (clearComposer) {\n api.composer().setText(prompt);\n } else {\n const currentText = api.composer().getState().text;\n api\n .composer()\n .setText(currentText.trim() ? `${currentText} ${prompt}` : prompt);\n }\n }\n }, [api, resolvedSend, clearComposer, prompt]);\n\n if (disabled) return null;\n return callback;\n};\n\nexport namespace ThreadPrimitiveSuggestion {\n export type Element = ActionButtonElement;\n export type Props = ActionButtonProps<typeof useThreadSuggestion>;\n}\n\nexport const ThreadPrimitiveSuggestion = createActionButton(\n \"ThreadPrimitive.Suggestion\",\n useThreadSuggestion,\n [\"prompt\", \"send\", \"clearComposer\", \"autoSend\", \"method\"],\n);\n"],"mappings":";;;AAEA;AAAA,EAGE;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB,uBAAuB;AAEnD,IAAM,sBAAsB,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA,QAAQ;AACV,MAwBM;AACJ,QAAM,MAAM,gBAAgB;AAC5B,QAAM,WAAW,kBAAkB,CAAC,EAAE,OAAO,MAAM,OAAO,UAAU;AAGpE,QAAM,eAAe,QAAQ,YAAY;AAGzC,QAAM,WAAW,YAAY,MAAM;AACjC,UAAM,YAAY,IAAI,OAAO,EAAE,SAAS,EAAE;AAE1C,QAAI,gBAAgB,CAAC,WAAW;AAC9B,UAAI,OAAO,EAAE,OAAO,MAAM;AAC1B,UAAI,eAAe;AACjB,YAAI,SAAS,EAAE,QAAQ,EAAE;AAAA,MAC3B;AAAA,IACF,OAAO;AACL,UAAI,eAAe;AACjB,YAAI,SAAS,EAAE,QAAQ,MAAM;AAAA,MAC/B,OAAO;AACL,cAAM,cAAc,IAAI,SAAS,EAAE,SAAS,EAAE;AAC9C,YACG,SAAS,EACT,QAAQ,YAAY,KAAK,IAAI,GAAG,WAAW,IAAI,MAAM,KAAK,MAAM;AAAA,MACrE;AAAA,IACF;AAAA,EACF,GAAG,CAAC,KAAK,cAAc,eAAe,MAAM,CAAC;AAE7C,MAAI,SAAU,QAAO;AACrB,SAAO;AACT;AAOO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA,CAAC,UAAU,QAAQ,iBAAiB,YAAY,QAAQ;AAC1D;","names":[]}