@webskill/chatbot 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +26 -6
- package/dist/chatbot.css +9 -3
- package/dist/index.d.ts +284 -174
- package/dist/index.js +967 -1486
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -6,10 +6,10 @@ import { t as yaml } from "./yaml-C888tCbJ.js";
|
|
|
6
6
|
import { t as json } from "./json-BOcU6nei.js";
|
|
7
7
|
import { t as typescript } from "./typescript-DAau_Qyl.js";
|
|
8
8
|
import { t as jsx$1 } from "./jsx-D2Jv0wvt.js";
|
|
9
|
-
import { AnthropicClient, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FullDisclosureRouter, GoogleGenAiClient, OpenAiCompatibleClient, SkillDiscovery, WebSkillError, WebSkillRuntime, messageOf } from "@webskill/sdk";
|
|
9
|
+
import { AnthropicClient, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FsRunTraceStore, FsSessionStore, FullDisclosureRouter, GoogleGenAiClient, OpenAiCompatibleClient, SkillDiscovery, WebSkillError, WebSkillRuntime, isUnsupportedRunSnapshot, messageOf, summarizeToolCalls, textParts } from "@webskill/sdk";
|
|
10
10
|
import { BrowserWorkerScriptExecutor } from "@webskill/sdk/browser";
|
|
11
|
-
import { JsonRenderSpecSurface, NativeSpecSurface, OpenUiSpecSurface, ReactBridgeState, UiSurfaceList, UiSurfaceSnapshotList } from "@webskill/sdk/ui-react";
|
|
12
|
-
import { A2UI_SPEC_FORM_PATH,
|
|
11
|
+
import { JsonRenderSpecSurface, NativeSpecSurface, OpenUiSpecSurface, ReactBridgeState, SpecInteractionChannel, UiSurfaceList, UiSurfaceSnapshotList, probeJsonRenderAvailability } from "@webskill/sdk/ui-react";
|
|
12
|
+
import { A2UI_SPEC_FORM_PATH, createUiCatalogToolSource, fromA2uiSpecAction, fromA2uiSurfaceAction, interactionToFormModel, interactionToUiSpec, loadOpenUiPeers, loadWebSkillLitCatalog, renderMiniChart, shapeInteractionValue, toA2uiSpecMessages, toA2uiSurfaceAction, toVercelToolInvocation, uiCatalog } from "@webskill/sdk/ui";
|
|
13
13
|
import * as React$1 from "react";
|
|
14
14
|
import React, { Children, Component, Fragment, createContext, createElement, forwardRef, isValidElement, memo, useCallback, useContext, useDeferredValue, useEffect, useEffectEvent, useId, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
15
15
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -183,6 +183,70 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
183
183
|
return Component;
|
|
184
184
|
};
|
|
185
185
|
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/archive-restore.mjs
|
|
188
|
+
/**
|
|
189
|
+
* @license lucide-react v1.27.0 - ISC
|
|
190
|
+
*
|
|
191
|
+
* This source code is licensed under the ISC license.
|
|
192
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
193
|
+
*/
|
|
194
|
+
const __iconNode$33 = [
|
|
195
|
+
["rect", {
|
|
196
|
+
width: "20",
|
|
197
|
+
height: "5",
|
|
198
|
+
x: "2",
|
|
199
|
+
y: "3",
|
|
200
|
+
rx: "1",
|
|
201
|
+
key: "1wp1u1"
|
|
202
|
+
}],
|
|
203
|
+
["path", {
|
|
204
|
+
d: "M4 8v11a2 2 0 0 0 2 2h2",
|
|
205
|
+
key: "tvwodi"
|
|
206
|
+
}],
|
|
207
|
+
["path", {
|
|
208
|
+
d: "M20 8v11a2 2 0 0 1-2 2h-2",
|
|
209
|
+
key: "1gkqxj"
|
|
210
|
+
}],
|
|
211
|
+
["path", {
|
|
212
|
+
d: "m9 15 3-3 3 3",
|
|
213
|
+
key: "1pd0qc"
|
|
214
|
+
}],
|
|
215
|
+
["path", {
|
|
216
|
+
d: "M12 12v9",
|
|
217
|
+
key: "192myk"
|
|
218
|
+
}]
|
|
219
|
+
];
|
|
220
|
+
const ArchiveRestore = createLucideIcon("archive-restore", __iconNode$33);
|
|
221
|
+
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/archive.mjs
|
|
224
|
+
/**
|
|
225
|
+
* @license lucide-react v1.27.0 - ISC
|
|
226
|
+
*
|
|
227
|
+
* This source code is licensed under the ISC license.
|
|
228
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
229
|
+
*/
|
|
230
|
+
const __iconNode$32 = [
|
|
231
|
+
["rect", {
|
|
232
|
+
width: "20",
|
|
233
|
+
height: "5",
|
|
234
|
+
x: "2",
|
|
235
|
+
y: "3",
|
|
236
|
+
rx: "1",
|
|
237
|
+
key: "1wp1u1"
|
|
238
|
+
}],
|
|
239
|
+
["path", {
|
|
240
|
+
d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8",
|
|
241
|
+
key: "1s80jp"
|
|
242
|
+
}],
|
|
243
|
+
["path", {
|
|
244
|
+
d: "M10 12h4",
|
|
245
|
+
key: "a56b0p"
|
|
246
|
+
}]
|
|
247
|
+
];
|
|
248
|
+
const Archive = createLucideIcon("archive", __iconNode$32);
|
|
249
|
+
|
|
186
250
|
//#endregion
|
|
187
251
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/arrow-up.mjs
|
|
188
252
|
/**
|
|
@@ -191,14 +255,14 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
191
255
|
* This source code is licensed under the ISC license.
|
|
192
256
|
* See the LICENSE file in the root directory of this source tree.
|
|
193
257
|
*/
|
|
194
|
-
const __iconNode$
|
|
258
|
+
const __iconNode$31 = [["path", {
|
|
195
259
|
d: "m5 12 7-7 7 7",
|
|
196
260
|
key: "hav0vg"
|
|
197
261
|
}], ["path", {
|
|
198
262
|
d: "M12 19V5",
|
|
199
263
|
key: "x0mq9r"
|
|
200
264
|
}]];
|
|
201
|
-
const ArrowUp = createLucideIcon("arrow-up", __iconNode$
|
|
265
|
+
const ArrowUp = createLucideIcon("arrow-up", __iconNode$31);
|
|
202
266
|
|
|
203
267
|
//#endregion
|
|
204
268
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/check.mjs
|
|
@@ -208,11 +272,11 @@ const ArrowUp = createLucideIcon("arrow-up", __iconNode$30);
|
|
|
208
272
|
* This source code is licensed under the ISC license.
|
|
209
273
|
* See the LICENSE file in the root directory of this source tree.
|
|
210
274
|
*/
|
|
211
|
-
const __iconNode$
|
|
275
|
+
const __iconNode$30 = [["path", {
|
|
212
276
|
d: "M20 6 9 17l-5-5",
|
|
213
277
|
key: "1gmf2c"
|
|
214
278
|
}]];
|
|
215
|
-
const Check = createLucideIcon("check", __iconNode$
|
|
279
|
+
const Check = createLucideIcon("check", __iconNode$30);
|
|
216
280
|
|
|
217
281
|
//#endregion
|
|
218
282
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/chevron-down.mjs
|
|
@@ -222,11 +286,11 @@ const Check = createLucideIcon("check", __iconNode$29);
|
|
|
222
286
|
* This source code is licensed under the ISC license.
|
|
223
287
|
* See the LICENSE file in the root directory of this source tree.
|
|
224
288
|
*/
|
|
225
|
-
const __iconNode$
|
|
289
|
+
const __iconNode$29 = [["path", {
|
|
226
290
|
d: "m6 9 6 6 6-6",
|
|
227
291
|
key: "qrunsl"
|
|
228
292
|
}]];
|
|
229
|
-
const ChevronDown = createLucideIcon("chevron-down", __iconNode$
|
|
293
|
+
const ChevronDown = createLucideIcon("chevron-down", __iconNode$29);
|
|
230
294
|
|
|
231
295
|
//#endregion
|
|
232
296
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/circle-check.mjs
|
|
@@ -236,7 +300,7 @@ const ChevronDown = createLucideIcon("chevron-down", __iconNode$28);
|
|
|
236
300
|
* This source code is licensed under the ISC license.
|
|
237
301
|
* See the LICENSE file in the root directory of this source tree.
|
|
238
302
|
*/
|
|
239
|
-
const __iconNode$
|
|
303
|
+
const __iconNode$28 = [["circle", {
|
|
240
304
|
cx: "12",
|
|
241
305
|
cy: "12",
|
|
242
306
|
r: "10",
|
|
@@ -245,7 +309,7 @@ const __iconNode$27 = [["circle", {
|
|
|
245
309
|
d: "m9 12 2 2 4-4",
|
|
246
310
|
key: "dzmm74"
|
|
247
311
|
}]];
|
|
248
|
-
const CircleCheck = createLucideIcon("circle-check", __iconNode$
|
|
312
|
+
const CircleCheck = createLucideIcon("circle-check", __iconNode$28);
|
|
249
313
|
|
|
250
314
|
//#endregion
|
|
251
315
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/circle-question-mark.mjs
|
|
@@ -255,7 +319,7 @@ const CircleCheck = createLucideIcon("circle-check", __iconNode$27);
|
|
|
255
319
|
* This source code is licensed under the ISC license.
|
|
256
320
|
* See the LICENSE file in the root directory of this source tree.
|
|
257
321
|
*/
|
|
258
|
-
const __iconNode$
|
|
322
|
+
const __iconNode$27 = [
|
|
259
323
|
["circle", {
|
|
260
324
|
cx: "12",
|
|
261
325
|
cy: "12",
|
|
@@ -271,7 +335,7 @@ const __iconNode$26 = [
|
|
|
271
335
|
key: "p32p05"
|
|
272
336
|
}]
|
|
273
337
|
];
|
|
274
|
-
const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$
|
|
338
|
+
const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$27);
|
|
275
339
|
|
|
276
340
|
//#endregion
|
|
277
341
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/circle-x.mjs
|
|
@@ -281,7 +345,7 @@ const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$2
|
|
|
281
345
|
* This source code is licensed under the ISC license.
|
|
282
346
|
* See the LICENSE file in the root directory of this source tree.
|
|
283
347
|
*/
|
|
284
|
-
const __iconNode$
|
|
348
|
+
const __iconNode$26 = [
|
|
285
349
|
["circle", {
|
|
286
350
|
cx: "12",
|
|
287
351
|
cy: "12",
|
|
@@ -297,7 +361,7 @@ const __iconNode$25 = [
|
|
|
297
361
|
key: "z0biqf"
|
|
298
362
|
}]
|
|
299
363
|
];
|
|
300
|
-
const CircleX = createLucideIcon("circle-x", __iconNode$
|
|
364
|
+
const CircleX = createLucideIcon("circle-x", __iconNode$26);
|
|
301
365
|
|
|
302
366
|
//#endregion
|
|
303
367
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/clipboard-list.mjs
|
|
@@ -307,7 +371,7 @@ const CircleX = createLucideIcon("circle-x", __iconNode$25);
|
|
|
307
371
|
* This source code is licensed under the ISC license.
|
|
308
372
|
* See the LICENSE file in the root directory of this source tree.
|
|
309
373
|
*/
|
|
310
|
-
const __iconNode$
|
|
374
|
+
const __iconNode$25 = [
|
|
311
375
|
["rect", {
|
|
312
376
|
width: "8",
|
|
313
377
|
height: "4",
|
|
@@ -338,7 +402,7 @@ const __iconNode$24 = [
|
|
|
338
402
|
key: "18s6g9"
|
|
339
403
|
}]
|
|
340
404
|
];
|
|
341
|
-
const ClipboardList = createLucideIcon("clipboard-list", __iconNode$
|
|
405
|
+
const ClipboardList = createLucideIcon("clipboard-list", __iconNode$25);
|
|
342
406
|
|
|
343
407
|
//#endregion
|
|
344
408
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/copy.mjs
|
|
@@ -348,7 +412,7 @@ const ClipboardList = createLucideIcon("clipboard-list", __iconNode$24);
|
|
|
348
412
|
* This source code is licensed under the ISC license.
|
|
349
413
|
* See the LICENSE file in the root directory of this source tree.
|
|
350
414
|
*/
|
|
351
|
-
const __iconNode$
|
|
415
|
+
const __iconNode$24 = [["rect", {
|
|
352
416
|
width: "14",
|
|
353
417
|
height: "14",
|
|
354
418
|
x: "8",
|
|
@@ -360,7 +424,7 @@ const __iconNode$23 = [["rect", {
|
|
|
360
424
|
d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",
|
|
361
425
|
key: "zix9uf"
|
|
362
426
|
}]];
|
|
363
|
-
const Copy = createLucideIcon("copy", __iconNode$
|
|
427
|
+
const Copy = createLucideIcon("copy", __iconNode$24);
|
|
364
428
|
|
|
365
429
|
//#endregion
|
|
366
430
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/download.mjs
|
|
@@ -370,7 +434,7 @@ const Copy = createLucideIcon("copy", __iconNode$23);
|
|
|
370
434
|
* This source code is licensed under the ISC license.
|
|
371
435
|
* See the LICENSE file in the root directory of this source tree.
|
|
372
436
|
*/
|
|
373
|
-
const __iconNode$
|
|
437
|
+
const __iconNode$23 = [
|
|
374
438
|
["path", {
|
|
375
439
|
d: "M12 15V3",
|
|
376
440
|
key: "m9g1x1"
|
|
@@ -384,7 +448,7 @@ const __iconNode$22 = [
|
|
|
384
448
|
key: "brsn70"
|
|
385
449
|
}]
|
|
386
450
|
];
|
|
387
|
-
const Download = createLucideIcon("download", __iconNode$
|
|
451
|
+
const Download = createLucideIcon("download", __iconNode$23);
|
|
388
452
|
|
|
389
453
|
//#endregion
|
|
390
454
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/external-link.mjs
|
|
@@ -394,7 +458,7 @@ const Download = createLucideIcon("download", __iconNode$22);
|
|
|
394
458
|
* This source code is licensed under the ISC license.
|
|
395
459
|
* See the LICENSE file in the root directory of this source tree.
|
|
396
460
|
*/
|
|
397
|
-
const __iconNode$
|
|
461
|
+
const __iconNode$22 = [
|
|
398
462
|
["path", {
|
|
399
463
|
d: "M15 3h6v6",
|
|
400
464
|
key: "1q9fwt"
|
|
@@ -408,7 +472,7 @@ const __iconNode$21 = [
|
|
|
408
472
|
key: "a6xqqp"
|
|
409
473
|
}]
|
|
410
474
|
];
|
|
411
|
-
const ExternalLink = createLucideIcon("external-link", __iconNode$
|
|
475
|
+
const ExternalLink = createLucideIcon("external-link", __iconNode$22);
|
|
412
476
|
|
|
413
477
|
//#endregion
|
|
414
478
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/file.mjs
|
|
@@ -418,14 +482,14 @@ const ExternalLink = createLucideIcon("external-link", __iconNode$21);
|
|
|
418
482
|
* This source code is licensed under the ISC license.
|
|
419
483
|
* See the LICENSE file in the root directory of this source tree.
|
|
420
484
|
*/
|
|
421
|
-
const __iconNode$
|
|
485
|
+
const __iconNode$21 = [["path", {
|
|
422
486
|
d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
|
|
423
487
|
key: "1oefj6"
|
|
424
488
|
}], ["path", {
|
|
425
489
|
d: "M14 2v5a1 1 0 0 0 1 1h5",
|
|
426
490
|
key: "wfsgrz"
|
|
427
491
|
}]];
|
|
428
|
-
const File = createLucideIcon("file", __iconNode$
|
|
492
|
+
const File = createLucideIcon("file", __iconNode$21);
|
|
429
493
|
|
|
430
494
|
//#endregion
|
|
431
495
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/list-checks.mjs
|
|
@@ -435,7 +499,7 @@ const File = createLucideIcon("file", __iconNode$20);
|
|
|
435
499
|
* This source code is licensed under the ISC license.
|
|
436
500
|
* See the LICENSE file in the root directory of this source tree.
|
|
437
501
|
*/
|
|
438
|
-
const __iconNode$
|
|
502
|
+
const __iconNode$20 = [
|
|
439
503
|
["path", {
|
|
440
504
|
d: "M13 5h8",
|
|
441
505
|
key: "a7qcls"
|
|
@@ -457,7 +521,7 @@ const __iconNode$19 = [
|
|
|
457
521
|
key: "1obspn"
|
|
458
522
|
}]
|
|
459
523
|
];
|
|
460
|
-
const ListChecks = createLucideIcon("list-checks", __iconNode$
|
|
524
|
+
const ListChecks = createLucideIcon("list-checks", __iconNode$20);
|
|
461
525
|
|
|
462
526
|
//#endregion
|
|
463
527
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/loader-circle.mjs
|
|
@@ -467,11 +531,11 @@ const ListChecks = createLucideIcon("list-checks", __iconNode$19);
|
|
|
467
531
|
* This source code is licensed under the ISC license.
|
|
468
532
|
* See the LICENSE file in the root directory of this source tree.
|
|
469
533
|
*/
|
|
470
|
-
const __iconNode$
|
|
534
|
+
const __iconNode$19 = [["path", {
|
|
471
535
|
d: "M21 12a9 9 0 1 1-6.219-8.56",
|
|
472
536
|
key: "13zald"
|
|
473
537
|
}]];
|
|
474
|
-
const LoaderCircle = createLucideIcon("loader-circle", __iconNode$
|
|
538
|
+
const LoaderCircle = createLucideIcon("loader-circle", __iconNode$19);
|
|
475
539
|
|
|
476
540
|
//#endregion
|
|
477
541
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/menu.mjs
|
|
@@ -481,7 +545,7 @@ const LoaderCircle = createLucideIcon("loader-circle", __iconNode$18);
|
|
|
481
545
|
* This source code is licensed under the ISC license.
|
|
482
546
|
* See the LICENSE file in the root directory of this source tree.
|
|
483
547
|
*/
|
|
484
|
-
const __iconNode$
|
|
548
|
+
const __iconNode$18 = [
|
|
485
549
|
["path", {
|
|
486
550
|
d: "M4 5h16",
|
|
487
551
|
key: "1tepv9"
|
|
@@ -495,7 +559,7 @@ const __iconNode$17 = [
|
|
|
495
559
|
key: "1djgab"
|
|
496
560
|
}]
|
|
497
561
|
];
|
|
498
|
-
const Menu = createLucideIcon("menu", __iconNode$
|
|
562
|
+
const Menu = createLucideIcon("menu", __iconNode$18);
|
|
499
563
|
|
|
500
564
|
//#endregion
|
|
501
565
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/message-circle-question-mark.mjs
|
|
@@ -505,7 +569,7 @@ const Menu = createLucideIcon("menu", __iconNode$17);
|
|
|
505
569
|
* This source code is licensed under the ISC license.
|
|
506
570
|
* See the LICENSE file in the root directory of this source tree.
|
|
507
571
|
*/
|
|
508
|
-
const __iconNode$
|
|
572
|
+
const __iconNode$17 = [
|
|
509
573
|
["path", {
|
|
510
574
|
d: "M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",
|
|
511
575
|
key: "1sd12s"
|
|
@@ -519,7 +583,7 @@ const __iconNode$16 = [
|
|
|
519
583
|
key: "p32p05"
|
|
520
584
|
}]
|
|
521
585
|
];
|
|
522
|
-
const MessageCircleQuestionMark = createLucideIcon("message-circle-question-mark", __iconNode$
|
|
586
|
+
const MessageCircleQuestionMark = createLucideIcon("message-circle-question-mark", __iconNode$17);
|
|
523
587
|
|
|
524
588
|
//#endregion
|
|
525
589
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/panel-right-open.mjs
|
|
@@ -529,7 +593,7 @@ const MessageCircleQuestionMark = createLucideIcon("message-circle-question-mark
|
|
|
529
593
|
* This source code is licensed under the ISC license.
|
|
530
594
|
* See the LICENSE file in the root directory of this source tree.
|
|
531
595
|
*/
|
|
532
|
-
const __iconNode$
|
|
596
|
+
const __iconNode$16 = [
|
|
533
597
|
["rect", {
|
|
534
598
|
width: "18",
|
|
535
599
|
height: "18",
|
|
@@ -547,7 +611,7 @@ const __iconNode$15 = [
|
|
|
547
611
|
key: "1pgupc"
|
|
548
612
|
}]
|
|
549
613
|
];
|
|
550
|
-
const PanelRightOpen = createLucideIcon("panel-right-open", __iconNode$
|
|
614
|
+
const PanelRightOpen = createLucideIcon("panel-right-open", __iconNode$16);
|
|
551
615
|
|
|
552
616
|
//#endregion
|
|
553
617
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/paperclip.mjs
|
|
@@ -557,11 +621,28 @@ const PanelRightOpen = createLucideIcon("panel-right-open", __iconNode$15);
|
|
|
557
621
|
* This source code is licensed under the ISC license.
|
|
558
622
|
* See the LICENSE file in the root directory of this source tree.
|
|
559
623
|
*/
|
|
560
|
-
const __iconNode$
|
|
624
|
+
const __iconNode$15 = [["path", {
|
|
561
625
|
d: "m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551",
|
|
562
626
|
key: "1miecu"
|
|
563
627
|
}]];
|
|
564
|
-
const Paperclip = createLucideIcon("paperclip", __iconNode$
|
|
628
|
+
const Paperclip = createLucideIcon("paperclip", __iconNode$15);
|
|
629
|
+
|
|
630
|
+
//#endregion
|
|
631
|
+
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/pencil.mjs
|
|
632
|
+
/**
|
|
633
|
+
* @license lucide-react v1.27.0 - ISC
|
|
634
|
+
*
|
|
635
|
+
* This source code is licensed under the ISC license.
|
|
636
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
637
|
+
*/
|
|
638
|
+
const __iconNode$14 = [["path", {
|
|
639
|
+
d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
|
|
640
|
+
key: "1a8usu"
|
|
641
|
+
}], ["path", {
|
|
642
|
+
d: "m15 5 4 4",
|
|
643
|
+
key: "1mk7zo"
|
|
644
|
+
}]];
|
|
645
|
+
const Pencil = createLucideIcon("pencil", __iconNode$14);
|
|
565
646
|
|
|
566
647
|
//#endregion
|
|
567
648
|
//#region ../../node_modules/.pnpm/lucide-react@1.27.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/play.mjs
|
|
@@ -913,8 +994,8 @@ function Label({ className = "", ...props }) {
|
|
|
913
994
|
|
|
914
995
|
//#endregion
|
|
915
996
|
//#region ../../node_modules/.pnpm/@radix-ui+react-compose-refs@1.1.5_@types+react@19.2.17_react@19.2.8/node_modules/@radix-ui/react-compose-refs/dist/index.mjs
|
|
916
|
-
var __defProp$
|
|
917
|
-
var __name$
|
|
997
|
+
var __defProp$21 = Object.defineProperty;
|
|
998
|
+
var __name$21 = (target, value) => __defProp$21(target, "name", {
|
|
918
999
|
value,
|
|
919
1000
|
configurable: true
|
|
920
1001
|
});
|
|
@@ -922,7 +1003,7 @@ function setRef$2(ref, value) {
|
|
|
922
1003
|
if (typeof ref === "function") return ref(value);
|
|
923
1004
|
else if (ref !== null && ref !== void 0) ref.current = value;
|
|
924
1005
|
}
|
|
925
|
-
__name$
|
|
1006
|
+
__name$21(setRef$2, "setRef");
|
|
926
1007
|
function composeRefs$1(...refs) {
|
|
927
1008
|
return (node) => {
|
|
928
1009
|
let hasCleanup = false;
|
|
@@ -940,16 +1021,16 @@ function composeRefs$1(...refs) {
|
|
|
940
1021
|
};
|
|
941
1022
|
};
|
|
942
1023
|
}
|
|
943
|
-
__name$
|
|
1024
|
+
__name$21(composeRefs$1, "composeRefs");
|
|
944
1025
|
function useComposedRefs$1(...refs) {
|
|
945
1026
|
return React$1.useCallback(composeRefs$1(...refs), refs);
|
|
946
1027
|
}
|
|
947
|
-
__name$
|
|
1028
|
+
__name$21(useComposedRefs$1, "useComposedRefs");
|
|
948
1029
|
|
|
949
1030
|
//#endregion
|
|
950
1031
|
//#region ../../node_modules/.pnpm/@radix-ui+react-context@1.2.2_@types+react@19.2.17_react@19.2.8/node_modules/@radix-ui/react-context/dist/index.mjs
|
|
951
|
-
var __defProp$
|
|
952
|
-
var __name$
|
|
1032
|
+
var __defProp$20 = Object.defineProperty;
|
|
1033
|
+
var __name$20 = (target, value) => __defProp$20(target, "name", {
|
|
953
1034
|
value,
|
|
954
1035
|
configurable: true
|
|
955
1036
|
});
|
|
@@ -957,7 +1038,7 @@ var __name$21 = (target, value) => __defProp$21(target, "name", {
|
|
|
957
1038
|
function createContext2(rootComponentName, defaultContext) {
|
|
958
1039
|
const Context = React$1.createContext(defaultContext);
|
|
959
1040
|
Context.displayName = rootComponentName + "Context";
|
|
960
|
-
const Provider = /* @__PURE__ */ __name$
|
|
1041
|
+
const Provider = /* @__PURE__ */ __name$20((props) => {
|
|
961
1042
|
const { children, ...context } = props;
|
|
962
1043
|
const value = React$1.useMemo(() => context, Object.values(context));
|
|
963
1044
|
return /* @__PURE__ */ jsx(Context.Provider, {
|
|
@@ -974,10 +1055,10 @@ function createContext2(rootComponentName, defaultContext) {
|
|
|
974
1055
|
if (optional) return void 0;
|
|
975
1056
|
throw new Error(`\`${consumerName}\` must be used within \`${rootComponentName}\``);
|
|
976
1057
|
}
|
|
977
|
-
__name$
|
|
1058
|
+
__name$20(useContext2, "useContext");
|
|
978
1059
|
return [Provider, useContext2];
|
|
979
1060
|
}
|
|
980
|
-
__name$
|
|
1061
|
+
__name$20(createContext2, "createContext");
|
|
981
1062
|
// @__NO_SIDE_EFFECTS__
|
|
982
1063
|
function createContextScope(scopeName, createContextScopeDeps = []) {
|
|
983
1064
|
let defaultContexts = [];
|
|
@@ -986,7 +1067,7 @@ function createContextScope(scopeName, createContextScopeDeps = []) {
|
|
|
986
1067
|
BaseContext.displayName = rootComponentName + "Context";
|
|
987
1068
|
const index = defaultContexts.length;
|
|
988
1069
|
defaultContexts = [...defaultContexts, defaultContext];
|
|
989
|
-
const Provider = /* @__PURE__ */ __name$
|
|
1070
|
+
const Provider = /* @__PURE__ */ __name$20((props) => {
|
|
990
1071
|
const { scope, children, ...context } = props;
|
|
991
1072
|
const Context = scope?.[scopeName]?.[index] || BaseContext;
|
|
992
1073
|
const value = React$1.useMemo(() => context, Object.values(context));
|
|
@@ -1005,15 +1086,15 @@ function createContextScope(scopeName, createContextScopeDeps = []) {
|
|
|
1005
1086
|
if (optional) return void 0;
|
|
1006
1087
|
throw new Error(`\`${consumerName}\` must be used within \`${rootComponentName}\``);
|
|
1007
1088
|
}
|
|
1008
|
-
__name$
|
|
1089
|
+
__name$20(useContext2, "useContext");
|
|
1009
1090
|
return [Provider, useContext2];
|
|
1010
1091
|
}
|
|
1011
|
-
__name$
|
|
1012
|
-
const createScope = /* @__PURE__ */ __name$
|
|
1092
|
+
__name$20(createContext3, "createContext");
|
|
1093
|
+
const createScope = /* @__PURE__ */ __name$20(() => {
|
|
1013
1094
|
const scopeContexts = defaultContexts.map((defaultContext) => {
|
|
1014
1095
|
return React$1.createContext(defaultContext);
|
|
1015
1096
|
});
|
|
1016
|
-
return /* @__PURE__ */ __name$
|
|
1097
|
+
return /* @__PURE__ */ __name$20(function useScope(scope) {
|
|
1017
1098
|
const contexts = scope?.[scopeName] || scopeContexts;
|
|
1018
1099
|
return React$1.useMemo(() => ({ [`__scope${scopeName}`]: {
|
|
1019
1100
|
...scope,
|
|
@@ -1024,16 +1105,16 @@ function createContextScope(scopeName, createContextScopeDeps = []) {
|
|
|
1024
1105
|
createScope.scopeName = scopeName;
|
|
1025
1106
|
return [createContext3, composeContextScopes(createScope, ...createContextScopeDeps)];
|
|
1026
1107
|
}
|
|
1027
|
-
__name$
|
|
1108
|
+
__name$20(createContextScope, "createContextScope");
|
|
1028
1109
|
function composeContextScopes(...scopes) {
|
|
1029
1110
|
const baseScope = scopes[0];
|
|
1030
1111
|
if (scopes.length === 1) return baseScope;
|
|
1031
|
-
const createScope = /* @__PURE__ */ __name$
|
|
1112
|
+
const createScope = /* @__PURE__ */ __name$20(() => {
|
|
1032
1113
|
const scopeHooks = scopes.map((createScope2) => ({
|
|
1033
1114
|
useScope: createScope2(),
|
|
1034
1115
|
scopeName: createScope2.scopeName
|
|
1035
1116
|
}));
|
|
1036
|
-
return /* @__PURE__ */ __name$
|
|
1117
|
+
return /* @__PURE__ */ __name$20(function useComposedScopes(overrideScopes) {
|
|
1037
1118
|
const nextScopes = scopeHooks.reduce((nextScopes2, { useScope, scopeName }) => {
|
|
1038
1119
|
const currentScope = useScope(overrideScopes)[`__scope${scopeName}`];
|
|
1039
1120
|
return {
|
|
@@ -1047,33 +1128,33 @@ function composeContextScopes(...scopes) {
|
|
|
1047
1128
|
createScope.scopeName = baseScope.scopeName;
|
|
1048
1129
|
return createScope;
|
|
1049
1130
|
}
|
|
1050
|
-
__name$
|
|
1131
|
+
__name$20(composeContextScopes, "composeContextScopes");
|
|
1051
1132
|
|
|
1052
1133
|
//#endregion
|
|
1053
1134
|
//#region ../../node_modules/.pnpm/@radix-ui+primitive@1.1.7/node_modules/@radix-ui/primitive/dist/index.mjs
|
|
1054
|
-
var __defProp$
|
|
1055
|
-
var __name$
|
|
1135
|
+
var __defProp$19 = Object.defineProperty;
|
|
1136
|
+
var __name$19 = (target, value) => __defProp$19(target, "name", {
|
|
1056
1137
|
value,
|
|
1057
1138
|
configurable: true
|
|
1058
1139
|
});
|
|
1059
1140
|
var canUseDOM = !!(typeof window !== "undefined" && window.document && window.document.createElement);
|
|
1060
1141
|
function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
|
|
1061
|
-
return /* @__PURE__ */ __name$
|
|
1142
|
+
return /* @__PURE__ */ __name$19(function handleEvent(event) {
|
|
1062
1143
|
originalEventHandler?.(event);
|
|
1063
1144
|
if (checkForDefaultPrevented === false || !event || !event.defaultPrevented) return ourEventHandler?.(event);
|
|
1064
1145
|
}, "handleEvent");
|
|
1065
1146
|
}
|
|
1066
|
-
__name$
|
|
1147
|
+
__name$19(composeEventHandlers, "composeEventHandlers");
|
|
1067
1148
|
function getOwnerWindow(element) {
|
|
1068
1149
|
if (!canUseDOM) throw new Error("Cannot access window outside of the DOM");
|
|
1069
1150
|
return element?.ownerDocument?.defaultView ?? window;
|
|
1070
1151
|
}
|
|
1071
|
-
__name$
|
|
1152
|
+
__name$19(getOwnerWindow, "getOwnerWindow");
|
|
1072
1153
|
function getOwnerDocument(element) {
|
|
1073
1154
|
if (!canUseDOM) throw new Error("Cannot access document outside of the DOM");
|
|
1074
1155
|
return element?.ownerDocument ?? document;
|
|
1075
1156
|
}
|
|
1076
|
-
__name$
|
|
1157
|
+
__name$19(getOwnerDocument, "getOwnerDocument");
|
|
1077
1158
|
function getActiveElement(node, activeDescendant = false) {
|
|
1078
1159
|
const { activeElement } = getOwnerDocument(node);
|
|
1079
1160
|
if (!activeElement?.nodeName) return null;
|
|
@@ -1087,11 +1168,11 @@ function getActiveElement(node, activeDescendant = false) {
|
|
|
1087
1168
|
}
|
|
1088
1169
|
return activeElement;
|
|
1089
1170
|
}
|
|
1090
|
-
__name$
|
|
1171
|
+
__name$19(getActiveElement, "getActiveElement");
|
|
1091
1172
|
function isFrame(element) {
|
|
1092
1173
|
return element.tagName === "IFRAME";
|
|
1093
1174
|
}
|
|
1094
|
-
__name$
|
|
1175
|
+
__name$19(isFrame, "isFrame");
|
|
1095
1176
|
|
|
1096
1177
|
//#endregion
|
|
1097
1178
|
//#region ../../node_modules/.pnpm/@radix-ui+react-use-layout-effect@1.1.4_@types+react@19.2.17_react@19.2.8/node_modules/@radix-ui/react-use-layout-effect/dist/index.mjs
|
|
@@ -1099,8 +1180,8 @@ var useLayoutEffect2 = globalThis?.document ? React$1.useLayoutEffect : () => {}
|
|
|
1099
1180
|
|
|
1100
1181
|
//#endregion
|
|
1101
1182
|
//#region ../../node_modules/.pnpm/@radix-ui+react-use-effect-event@0.0.5_@types+react@19.2.17_react@19.2.8/node_modules/@radix-ui/react-use-effect-event/dist/index.mjs
|
|
1102
|
-
var __defProp$
|
|
1103
|
-
var __name$
|
|
1183
|
+
var __defProp$18 = Object.defineProperty;
|
|
1184
|
+
var __name$18 = (target, value) => __defProp$18(target, "name", {
|
|
1104
1185
|
value,
|
|
1105
1186
|
configurable: true
|
|
1106
1187
|
});
|
|
@@ -1119,17 +1200,17 @@ function useEffectEvent$1(callback) {
|
|
|
1119
1200
|
});
|
|
1120
1201
|
return React$1.useMemo(() => ((...args) => ref.current?.(...args)), []);
|
|
1121
1202
|
}
|
|
1122
|
-
__name$
|
|
1203
|
+
__name$18(useEffectEvent$1, "useEffectEvent");
|
|
1123
1204
|
|
|
1124
1205
|
//#endregion
|
|
1125
1206
|
//#region ../../node_modules/.pnpm/@radix-ui+react-use-controllable-state@1.2.6_@types+react@19.2.17_react@19.2.8/node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs
|
|
1126
|
-
var __defProp$
|
|
1127
|
-
var __name$
|
|
1207
|
+
var __defProp$17 = Object.defineProperty;
|
|
1208
|
+
var __name$17 = (target, value) => __defProp$17(target, "name", {
|
|
1128
1209
|
value,
|
|
1129
1210
|
configurable: true
|
|
1130
1211
|
});
|
|
1131
1212
|
var useInsertionEffect$1 = React$1[" useInsertionEffect ".trim().toString()] || useLayoutEffect2;
|
|
1132
|
-
function useControllableState({ prop, defaultProp, onChange = /* @__PURE__ */ __name$
|
|
1213
|
+
function useControllableState({ prop, defaultProp, onChange = /* @__PURE__ */ __name$17(() => {}, "onChange"), caller }) {
|
|
1133
1214
|
const [uncontrolledProp, setUncontrolledProp, onChangeRef] = useUncontrolledState({
|
|
1134
1215
|
defaultProp,
|
|
1135
1216
|
onChange
|
|
@@ -1146,7 +1227,7 @@ function useControllableState({ prop, defaultProp, onChange = /* @__PURE__ */ __
|
|
|
1146
1227
|
}
|
|
1147
1228
|
return [value, React$1.useCallback((nextValue) => {
|
|
1148
1229
|
if (isControlled) {
|
|
1149
|
-
const value2 = isFunction$
|
|
1230
|
+
const value2 = isFunction$1(nextValue) ? nextValue(prop) : nextValue;
|
|
1150
1231
|
if (value2 !== prop) onChangeRef.current?.(value2);
|
|
1151
1232
|
} else setUncontrolledProp(nextValue);
|
|
1152
1233
|
}, [
|
|
@@ -1156,7 +1237,7 @@ function useControllableState({ prop, defaultProp, onChange = /* @__PURE__ */ __
|
|
|
1156
1237
|
onChangeRef
|
|
1157
1238
|
])];
|
|
1158
1239
|
}
|
|
1159
|
-
__name$
|
|
1240
|
+
__name$17(useControllableState, "useControllableState");
|
|
1160
1241
|
function useUncontrolledState({ defaultProp, onChange }) {
|
|
1161
1242
|
const [value, setValue] = React$1.useState(defaultProp);
|
|
1162
1243
|
const prevValueRef = React$1.useRef(value);
|
|
@@ -1176,11 +1257,11 @@ function useUncontrolledState({ defaultProp, onChange }) {
|
|
|
1176
1257
|
onChangeRef
|
|
1177
1258
|
];
|
|
1178
1259
|
}
|
|
1179
|
-
__name$
|
|
1180
|
-
function isFunction$
|
|
1260
|
+
__name$17(useUncontrolledState, "useUncontrolledState");
|
|
1261
|
+
function isFunction$1(value) {
|
|
1181
1262
|
return typeof value === "function";
|
|
1182
1263
|
}
|
|
1183
|
-
__name$
|
|
1264
|
+
__name$17(isFunction$1, "isFunction");
|
|
1184
1265
|
var SYNC_STATE = Symbol("RADIX:SYNC_STATE");
|
|
1185
1266
|
function useControllableStateReducer(reducer, userArgs, initialArg, init) {
|
|
1186
1267
|
const { prop: controlledState, defaultProp, onChange: onChangeProp, caller } = userArgs;
|
|
@@ -1239,12 +1320,12 @@ function useControllableStateReducer(reducer, userArgs, initialArg, init) {
|
|
|
1239
1320
|
]);
|
|
1240
1321
|
return [state, dispatch];
|
|
1241
1322
|
}
|
|
1242
|
-
__name$
|
|
1323
|
+
__name$17(useControllableStateReducer, "useControllableStateReducer");
|
|
1243
1324
|
|
|
1244
1325
|
//#endregion
|
|
1245
1326
|
//#region ../../node_modules/.pnpm/@radix-ui+react-use-size@1.1.4_@types+react@19.2.17_react@19.2.8/node_modules/@radix-ui/react-use-size/dist/index.mjs
|
|
1246
|
-
var __defProp$
|
|
1247
|
-
var __name$
|
|
1327
|
+
var __defProp$16 = Object.defineProperty;
|
|
1328
|
+
var __name$16 = (target, value) => __defProp$16(target, "name", {
|
|
1248
1329
|
value,
|
|
1249
1330
|
configurable: true
|
|
1250
1331
|
});
|
|
@@ -1282,12 +1363,12 @@ function useSize(element) {
|
|
|
1282
1363
|
}, [element]);
|
|
1283
1364
|
return size;
|
|
1284
1365
|
}
|
|
1285
|
-
__name$
|
|
1366
|
+
__name$16(useSize, "useSize");
|
|
1286
1367
|
|
|
1287
1368
|
//#endregion
|
|
1288
1369
|
//#region ../../node_modules/.pnpm/@radix-ui+react-presence@1.1.10_@types+react-dom@19.2.3_@types+react@19.2.17__@types+re_138587ba593102bdcf335a5673d92068/node_modules/@radix-ui/react-presence/dist/index.mjs
|
|
1289
|
-
var __defProp$
|
|
1290
|
-
var __name$
|
|
1370
|
+
var __defProp$15 = Object.defineProperty;
|
|
1371
|
+
var __name$15 = (target, value) => __defProp$15(target, "name", {
|
|
1291
1372
|
value,
|
|
1292
1373
|
configurable: true
|
|
1293
1374
|
});
|
|
@@ -1296,8 +1377,8 @@ function useStateMachine(initialState, machine) {
|
|
|
1296
1377
|
return machine[state][event] ?? state;
|
|
1297
1378
|
}, initialState);
|
|
1298
1379
|
}
|
|
1299
|
-
__name$
|
|
1300
|
-
var Presence = /* @__PURE__ */ __name$
|
|
1380
|
+
__name$15(useStateMachine, "useStateMachine");
|
|
1381
|
+
var Presence = /* @__PURE__ */ __name$15((props) => {
|
|
1301
1382
|
const { present, children } = props;
|
|
1302
1383
|
const presence = usePresence$1(present);
|
|
1303
1384
|
const child = typeof children === "function" ? children({ present: presence.isPresent }) : React$1.Children.only(children);
|
|
@@ -1346,7 +1427,7 @@ function usePresence$1(present) {
|
|
|
1346
1427
|
if (node) {
|
|
1347
1428
|
let timeoutId;
|
|
1348
1429
|
const ownerWindow = node.ownerDocument.defaultView ?? window;
|
|
1349
|
-
const handleAnimationEnd = /* @__PURE__ */ __name$
|
|
1430
|
+
const handleAnimationEnd = /* @__PURE__ */ __name$15((event) => {
|
|
1350
1431
|
const isCurrentAnimation = getAnimationName(stylesRef.current).includes(CSS.escape(event.animationName));
|
|
1351
1432
|
if (event.target === node && isCurrentAnimation) {
|
|
1352
1433
|
send("ANIMATION_END");
|
|
@@ -1359,7 +1440,7 @@ function usePresence$1(present) {
|
|
|
1359
1440
|
}
|
|
1360
1441
|
}
|
|
1361
1442
|
}, "handleAnimationEnd");
|
|
1362
|
-
const handleAnimationStart = /* @__PURE__ */ __name$
|
|
1443
|
+
const handleAnimationStart = /* @__PURE__ */ __name$15((event) => {
|
|
1363
1444
|
if (event.target === node) prevAnimationNameRef.current = getAnimationName(stylesRef.current);
|
|
1364
1445
|
}, "handleAnimationStart");
|
|
1365
1446
|
node.addEventListener("animationstart", handleAnimationStart);
|
|
@@ -1385,12 +1466,12 @@ function usePresence$1(present) {
|
|
|
1385
1466
|
}, [])
|
|
1386
1467
|
};
|
|
1387
1468
|
}
|
|
1388
|
-
__name$
|
|
1469
|
+
__name$15(usePresence$1, "usePresence");
|
|
1389
1470
|
function setRef$1(ref, value) {
|
|
1390
1471
|
if (typeof ref === "function") return ref(value);
|
|
1391
1472
|
else if (ref !== null && ref !== void 0) ref.current = value;
|
|
1392
1473
|
}
|
|
1393
|
-
__name$
|
|
1474
|
+
__name$15(setRef$1, "setRef");
|
|
1394
1475
|
function useStableComposedRefs(...refs) {
|
|
1395
1476
|
const refsRef = React$1.useRef(refs);
|
|
1396
1477
|
refsRef.current = refs;
|
|
@@ -1411,11 +1492,11 @@ function useStableComposedRefs(...refs) {
|
|
|
1411
1492
|
};
|
|
1412
1493
|
}, []);
|
|
1413
1494
|
}
|
|
1414
|
-
__name$
|
|
1495
|
+
__name$15(useStableComposedRefs, "useStableComposedRefs");
|
|
1415
1496
|
function getAnimationName(styles) {
|
|
1416
1497
|
return styles?.animationName || "none";
|
|
1417
1498
|
}
|
|
1418
|
-
__name$
|
|
1499
|
+
__name$15(getAnimationName, "getAnimationName");
|
|
1419
1500
|
function getElementRef$1(element) {
|
|
1420
1501
|
let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
|
|
1421
1502
|
let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
|
|
@@ -1425,12 +1506,12 @@ function getElementRef$1(element) {
|
|
|
1425
1506
|
if (mayWarn) return element.props.ref;
|
|
1426
1507
|
return element.props.ref || element.ref;
|
|
1427
1508
|
}
|
|
1428
|
-
__name$
|
|
1509
|
+
__name$15(getElementRef$1, "getElementRef");
|
|
1429
1510
|
|
|
1430
1511
|
//#endregion
|
|
1431
1512
|
//#region ../../node_modules/.pnpm/@radix-ui+react-slot@1.3.3_@types+react@19.2.17_react@19.2.8/node_modules/@radix-ui/react-slot/dist/index.mjs
|
|
1432
|
-
var __defProp$
|
|
1433
|
-
var __name$
|
|
1513
|
+
var __defProp$14 = Object.defineProperty;
|
|
1514
|
+
var __name$14 = (target, value) => __defProp$14(target, "name", {
|
|
1434
1515
|
value,
|
|
1435
1516
|
configurable: true
|
|
1436
1517
|
});
|
|
@@ -1467,17 +1548,17 @@ function createSlot(ownerName) {
|
|
|
1467
1548
|
Slot2.displayName = `${ownerName}.Slot`;
|
|
1468
1549
|
return Slot2;
|
|
1469
1550
|
}
|
|
1470
|
-
__name$
|
|
1551
|
+
__name$14(createSlot, "createSlot");
|
|
1471
1552
|
var SLOTTABLE_IDENTIFIER = Symbol.for("radix.slottable");
|
|
1472
1553
|
// @__NO_SIDE_EFFECTS__
|
|
1473
1554
|
function createSlottable(ownerName) {
|
|
1474
|
-
const Slottable2 = /* @__PURE__ */ __name$
|
|
1555
|
+
const Slottable2 = /* @__PURE__ */ __name$14((props) => "child" in props ? props.children(props.child) : props.children, "Slottable");
|
|
1475
1556
|
Slottable2.displayName = `${ownerName}.Slottable`;
|
|
1476
1557
|
Slottable2.__radixId = SLOTTABLE_IDENTIFIER;
|
|
1477
1558
|
return Slottable2;
|
|
1478
1559
|
}
|
|
1479
|
-
__name$
|
|
1480
|
-
var getSlottableElementFromSlottable = /* @__PURE__ */ __name$
|
|
1560
|
+
__name$14(createSlottable, "createSlottable");
|
|
1561
|
+
var getSlottableElementFromSlottable = /* @__PURE__ */ __name$14((slottable, child) => {
|
|
1481
1562
|
if ("child" in slottable.props) {
|
|
1482
1563
|
const child2 = slottable.props.child;
|
|
1483
1564
|
if (!React$1.isValidElement(child2)) return null;
|
|
@@ -1508,7 +1589,7 @@ function mergeProps(slotProps, childProps) {
|
|
|
1508
1589
|
...overrideProps
|
|
1509
1590
|
};
|
|
1510
1591
|
}
|
|
1511
|
-
__name$
|
|
1592
|
+
__name$14(mergeProps, "mergeProps");
|
|
1512
1593
|
function getElementRef(element) {
|
|
1513
1594
|
let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
|
|
1514
1595
|
let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
|
|
@@ -1518,32 +1599,32 @@ function getElementRef(element) {
|
|
|
1518
1599
|
if (mayWarn) return element.props.ref;
|
|
1519
1600
|
return element.props.ref || element.ref;
|
|
1520
1601
|
}
|
|
1521
|
-
__name$
|
|
1602
|
+
__name$14(getElementRef, "getElementRef");
|
|
1522
1603
|
function isSlottable(child) {
|
|
1523
1604
|
return React$1.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
|
|
1524
1605
|
}
|
|
1525
|
-
__name$
|
|
1606
|
+
__name$14(isSlottable, "isSlottable");
|
|
1526
1607
|
var REACT_LAZY_TYPE = Symbol.for("react.lazy");
|
|
1527
1608
|
function isLazyComponent(element) {
|
|
1528
1609
|
return element != null && typeof element === "object" && "$$typeof" in element && element.$$typeof === REACT_LAZY_TYPE && "_payload" in element && isPromiseLike(element._payload);
|
|
1529
1610
|
}
|
|
1530
|
-
__name$
|
|
1611
|
+
__name$14(isLazyComponent, "isLazyComponent");
|
|
1531
1612
|
function isPromiseLike(value) {
|
|
1532
1613
|
return typeof value === "object" && value !== null && "then" in value;
|
|
1533
1614
|
}
|
|
1534
|
-
__name$
|
|
1535
|
-
var createSlotError = /* @__PURE__ */ __name$
|
|
1615
|
+
__name$14(isPromiseLike, "isPromiseLike");
|
|
1616
|
+
var createSlotError = /* @__PURE__ */ __name$14((ownerName) => {
|
|
1536
1617
|
return `${ownerName} failed to slot onto its children. Expected a single React element child or \`Slottable\`.`;
|
|
1537
1618
|
}, "createSlotError");
|
|
1538
|
-
var createSlottableError = /* @__PURE__ */ __name$
|
|
1619
|
+
var createSlottableError = /* @__PURE__ */ __name$14((ownerName) => {
|
|
1539
1620
|
return `${ownerName} failed to slot onto its \`Slottable\`. Expected \`Slottable\` to receive a single React element child.`;
|
|
1540
1621
|
}, "createSlottableError");
|
|
1541
1622
|
var use = React$1[" use ".trim().toString()];
|
|
1542
1623
|
|
|
1543
1624
|
//#endregion
|
|
1544
1625
|
//#region ../../node_modules/.pnpm/@radix-ui+react-primitive@2.1.10_@types+react-dom@19.2.3_@types+react@19.2.17__@types+r_be17283a23f513d7b972453cc36e2a96/node_modules/@radix-ui/react-primitive/dist/index.mjs
|
|
1545
|
-
var __defProp$
|
|
1546
|
-
var __name$
|
|
1626
|
+
var __defProp$13 = Object.defineProperty;
|
|
1627
|
+
var __name$13 = (target, value) => __defProp$13(target, "name", {
|
|
1547
1628
|
value,
|
|
1548
1629
|
configurable: true
|
|
1549
1630
|
});
|
|
@@ -1585,230 +1666,7 @@ var Primitive = [
|
|
|
1585
1666
|
function dispatchDiscreteCustomEvent(target, event) {
|
|
1586
1667
|
if (target) ReactDOM.flushSync(() => target.dispatchEvent(event));
|
|
1587
1668
|
}
|
|
1588
|
-
__name$
|
|
1589
|
-
|
|
1590
|
-
//#endregion
|
|
1591
|
-
//#region ../../node_modules/.pnpm/@radix-ui+react-checkbox@1.3.11_@types+react-dom@19.2.3_@types+react@19.2.17__@types+re_f6e0f4835f2e28dbd2e5cb3844d005eb/node_modules/@radix-ui/react-checkbox/dist/index.mjs
|
|
1592
|
-
var __defProp$13 = Object.defineProperty;
|
|
1593
|
-
var __name$13 = (target, value) => __defProp$13(target, "name", {
|
|
1594
|
-
value,
|
|
1595
|
-
configurable: true
|
|
1596
|
-
});
|
|
1597
|
-
var CHECKBOX_NAME = "Checkbox";
|
|
1598
|
-
var [createCheckboxContext, createCheckboxScope] = createContextScope(CHECKBOX_NAME);
|
|
1599
|
-
var [CheckboxProviderImpl, useCheckboxContext] = createCheckboxContext(CHECKBOX_NAME);
|
|
1600
|
-
function CheckboxProvider(props) {
|
|
1601
|
-
const { __scopeCheckbox, checked: checkedProp, children, defaultChecked, disabled, form, name, onCheckedChange, required, value = "on", internal_do_not_use_render } = props;
|
|
1602
|
-
const [checked, setChecked] = useControllableState({
|
|
1603
|
-
prop: checkedProp,
|
|
1604
|
-
defaultProp: defaultChecked ?? false,
|
|
1605
|
-
onChange: onCheckedChange,
|
|
1606
|
-
caller: CHECKBOX_NAME
|
|
1607
|
-
});
|
|
1608
|
-
const [control, setControl] = React$1.useState(null);
|
|
1609
|
-
const [bubbleInput, setBubbleInput] = React$1.useState(null);
|
|
1610
|
-
const hasConsumerStoppedPropagationRef = React$1.useRef(false);
|
|
1611
|
-
const [userInteractionCount, onUserInteraction] = React$1.useReducer((count) => count + 1, 0);
|
|
1612
|
-
const isFormControl = control ? !!form || !!control.closest("form") : true;
|
|
1613
|
-
const context = {
|
|
1614
|
-
checked,
|
|
1615
|
-
disabled,
|
|
1616
|
-
setChecked,
|
|
1617
|
-
control,
|
|
1618
|
-
setControl,
|
|
1619
|
-
name,
|
|
1620
|
-
form,
|
|
1621
|
-
value,
|
|
1622
|
-
hasConsumerStoppedPropagationRef,
|
|
1623
|
-
userInteractionCount,
|
|
1624
|
-
onUserInteraction,
|
|
1625
|
-
required,
|
|
1626
|
-
defaultChecked: isIndeterminate(defaultChecked) ? false : defaultChecked,
|
|
1627
|
-
isFormControl,
|
|
1628
|
-
bubbleInput,
|
|
1629
|
-
setBubbleInput
|
|
1630
|
-
};
|
|
1631
|
-
return /* @__PURE__ */ jsx(CheckboxProviderImpl, {
|
|
1632
|
-
scope: __scopeCheckbox,
|
|
1633
|
-
...context,
|
|
1634
|
-
children: isFunction$1(internal_do_not_use_render) ? internal_do_not_use_render(context) : children
|
|
1635
|
-
});
|
|
1636
|
-
}
|
|
1637
|
-
__name$13(CheckboxProvider, "CheckboxProvider");
|
|
1638
|
-
var TRIGGER_NAME$3 = "CheckboxTrigger";
|
|
1639
|
-
var CheckboxTrigger = /* @__PURE__ */ React$1.forwardRef(/* @__PURE__ */ __name$13(function CheckboxTrigger2({ __scopeCheckbox, onKeyDown, onClick, ...checkboxProps }, forwardedRef) {
|
|
1640
|
-
const { control, value, disabled, checked, required, setControl, setChecked, hasConsumerStoppedPropagationRef, onUserInteraction, isFormControl, bubbleInput } = useCheckboxContext(TRIGGER_NAME$3, __scopeCheckbox);
|
|
1641
|
-
const composedRefs = useComposedRefs$1(forwardedRef, setControl);
|
|
1642
|
-
const initialCheckedStateRef = React$1.useRef(checked);
|
|
1643
|
-
React$1.useEffect(() => {
|
|
1644
|
-
const form = control?.form;
|
|
1645
|
-
if (form) {
|
|
1646
|
-
const reset = /* @__PURE__ */ __name$13(() => setChecked(initialCheckedStateRef.current), "reset");
|
|
1647
|
-
form.addEventListener("reset", reset);
|
|
1648
|
-
return () => form.removeEventListener("reset", reset);
|
|
1649
|
-
}
|
|
1650
|
-
}, [control, setChecked]);
|
|
1651
|
-
return /* @__PURE__ */ jsx(Primitive.button, {
|
|
1652
|
-
type: "button",
|
|
1653
|
-
role: "checkbox",
|
|
1654
|
-
"aria-checked": isIndeterminate(checked) ? "mixed" : checked,
|
|
1655
|
-
"aria-required": required,
|
|
1656
|
-
"data-state": getState$3(checked),
|
|
1657
|
-
"data-disabled": disabled ? "" : void 0,
|
|
1658
|
-
disabled,
|
|
1659
|
-
value,
|
|
1660
|
-
...checkboxProps,
|
|
1661
|
-
ref: composedRefs,
|
|
1662
|
-
onKeyDown: composeEventHandlers(onKeyDown, (event) => {
|
|
1663
|
-
if (event.key === "Enter") event.preventDefault();
|
|
1664
|
-
}),
|
|
1665
|
-
onClick: composeEventHandlers(onClick, (event) => {
|
|
1666
|
-
onUserInteraction();
|
|
1667
|
-
setChecked((prevChecked) => isIndeterminate(prevChecked) ? true : !prevChecked);
|
|
1668
|
-
if (bubbleInput && isFormControl) {
|
|
1669
|
-
hasConsumerStoppedPropagationRef.current = event.isPropagationStopped();
|
|
1670
|
-
if (!hasConsumerStoppedPropagationRef.current) event.stopPropagation();
|
|
1671
|
-
}
|
|
1672
|
-
})
|
|
1673
|
-
});
|
|
1674
|
-
}, "CheckboxTrigger"));
|
|
1675
|
-
var Checkbox$1 = /* @__PURE__ */ React$1.forwardRef(/* @__PURE__ */ __name$13(function Checkbox2(props, forwardedRef) {
|
|
1676
|
-
const { __scopeCheckbox, name, checked, defaultChecked, required, disabled, value, onCheckedChange, form, ...checkboxProps } = props;
|
|
1677
|
-
return /* @__PURE__ */ jsx(CheckboxProvider, {
|
|
1678
|
-
__scopeCheckbox,
|
|
1679
|
-
checked,
|
|
1680
|
-
defaultChecked,
|
|
1681
|
-
disabled,
|
|
1682
|
-
required,
|
|
1683
|
-
onCheckedChange,
|
|
1684
|
-
name,
|
|
1685
|
-
form,
|
|
1686
|
-
value,
|
|
1687
|
-
internal_do_not_use_render: ({ isFormControl }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(CheckboxTrigger, {
|
|
1688
|
-
...checkboxProps,
|
|
1689
|
-
ref: forwardedRef,
|
|
1690
|
-
__scopeCheckbox
|
|
1691
|
-
}), isFormControl && /* @__PURE__ */ jsx(CheckboxBubbleInput, { __scopeCheckbox })] })
|
|
1692
|
-
});
|
|
1693
|
-
}, "Checkbox"));
|
|
1694
|
-
var INDICATOR_NAME = "CheckboxIndicator";
|
|
1695
|
-
var CheckboxIndicator = /* @__PURE__ */ React$1.forwardRef(/* @__PURE__ */ __name$13(function CheckboxIndicator2(props, forwardedRef) {
|
|
1696
|
-
const { __scopeCheckbox, forceMount, ...indicatorProps } = props;
|
|
1697
|
-
const context = useCheckboxContext(INDICATOR_NAME, __scopeCheckbox);
|
|
1698
|
-
return /* @__PURE__ */ jsx(Presence, {
|
|
1699
|
-
present: forceMount || isIndeterminate(context.checked) || context.checked === true,
|
|
1700
|
-
children: /* @__PURE__ */ jsx(Primitive.span, {
|
|
1701
|
-
"data-state": getState$3(context.checked),
|
|
1702
|
-
"data-disabled": context.disabled ? "" : void 0,
|
|
1703
|
-
...indicatorProps,
|
|
1704
|
-
ref: forwardedRef,
|
|
1705
|
-
style: {
|
|
1706
|
-
pointerEvents: "none",
|
|
1707
|
-
...props.style
|
|
1708
|
-
}
|
|
1709
|
-
})
|
|
1710
|
-
});
|
|
1711
|
-
}, "CheckboxIndicator"));
|
|
1712
|
-
var BUBBLE_INPUT_NAME$1 = "CheckboxBubbleInput";
|
|
1713
|
-
var CheckboxBubbleInput = /* @__PURE__ */ React$1.forwardRef(/* @__PURE__ */ __name$13(function CheckboxBubbleInput2({ __scopeCheckbox, onClick, ...props }, forwardedRef) {
|
|
1714
|
-
const { control, hasConsumerStoppedPropagationRef, userInteractionCount, checked, defaultChecked, required, disabled, name, value, form, bubbleInput, setBubbleInput } = useCheckboxContext(BUBBLE_INPUT_NAME$1, __scopeCheckbox);
|
|
1715
|
-
const composedRefs = useComposedRefs$1(forwardedRef, setBubbleInput);
|
|
1716
|
-
const controlSize = useSize(control);
|
|
1717
|
-
const shouldStopClickPropagationRef = React$1.useRef(false);
|
|
1718
|
-
const prevCheckedRef = React$1.useRef(checked);
|
|
1719
|
-
const prevUserInteractionCountRef = React$1.useRef(userInteractionCount);
|
|
1720
|
-
React$1.useEffect(() => {
|
|
1721
|
-
const input = bubbleInput;
|
|
1722
|
-
if (!input) return;
|
|
1723
|
-
const inputProto = window.HTMLInputElement.prototype;
|
|
1724
|
-
const setChecked = Object.getOwnPropertyDescriptor(inputProto, "checked").set;
|
|
1725
|
-
const isUserInteraction = userInteractionCount !== prevUserInteractionCountRef.current;
|
|
1726
|
-
prevUserInteractionCountRef.current = userInteractionCount;
|
|
1727
|
-
const checkedChanged = prevCheckedRef.current !== checked;
|
|
1728
|
-
prevCheckedRef.current = checked;
|
|
1729
|
-
const bubbles = !(isUserInteraction && hasConsumerStoppedPropagationRef.current);
|
|
1730
|
-
if (checkedChanged && setChecked) {
|
|
1731
|
-
shouldStopClickPropagationRef.current = !isUserInteraction;
|
|
1732
|
-
const event = new Event("click", { bubbles });
|
|
1733
|
-
input.indeterminate = isIndeterminate(checked);
|
|
1734
|
-
setChecked.call(input, isIndeterminate(checked) ? false : checked);
|
|
1735
|
-
input.dispatchEvent(event);
|
|
1736
|
-
shouldStopClickPropagationRef.current = false;
|
|
1737
|
-
}
|
|
1738
|
-
}, [
|
|
1739
|
-
bubbleInput,
|
|
1740
|
-
checked,
|
|
1741
|
-
hasConsumerStoppedPropagationRef,
|
|
1742
|
-
userInteractionCount
|
|
1743
|
-
]);
|
|
1744
|
-
const defaultCheckedRef = React$1.useRef(isIndeterminate(checked) ? false : checked);
|
|
1745
|
-
return /* @__PURE__ */ jsx(Primitive.input, {
|
|
1746
|
-
type: "checkbox",
|
|
1747
|
-
"aria-hidden": true,
|
|
1748
|
-
defaultChecked: defaultChecked ?? defaultCheckedRef.current,
|
|
1749
|
-
required,
|
|
1750
|
-
disabled,
|
|
1751
|
-
name,
|
|
1752
|
-
value,
|
|
1753
|
-
form,
|
|
1754
|
-
...props,
|
|
1755
|
-
tabIndex: -1,
|
|
1756
|
-
ref: composedRefs,
|
|
1757
|
-
onClick: composeEventHandlers(onClick, (event) => {
|
|
1758
|
-
if (shouldStopClickPropagationRef.current) event.stopPropagation();
|
|
1759
|
-
}),
|
|
1760
|
-
style: {
|
|
1761
|
-
...props.style,
|
|
1762
|
-
...controlSize,
|
|
1763
|
-
position: "absolute",
|
|
1764
|
-
pointerEvents: "none",
|
|
1765
|
-
opacity: 0,
|
|
1766
|
-
margin: 0,
|
|
1767
|
-
transform: "translateX(-100%)"
|
|
1768
|
-
}
|
|
1769
|
-
});
|
|
1770
|
-
}, "CheckboxBubbleInput"));
|
|
1771
|
-
function isFunction$1(value) {
|
|
1772
|
-
return typeof value === "function";
|
|
1773
|
-
}
|
|
1774
|
-
__name$13(isFunction$1, "isFunction");
|
|
1775
|
-
function isIndeterminate(checked) {
|
|
1776
|
-
return checked === "indeterminate";
|
|
1777
|
-
}
|
|
1778
|
-
__name$13(isIndeterminate, "isIndeterminate");
|
|
1779
|
-
function getState$3(checked) {
|
|
1780
|
-
return isIndeterminate(checked) ? "indeterminate" : checked ? "checked" : "unchecked";
|
|
1781
|
-
}
|
|
1782
|
-
__name$13(getState$3, "getState");
|
|
1783
|
-
|
|
1784
|
-
//#endregion
|
|
1785
|
-
//#region ../ui-kit/src/components/Checkbox.tsx
|
|
1786
|
-
/** Source-owned shadcn-style checkbox backed by Radix for keyboard semantics. */
|
|
1787
|
-
function Checkbox({ className = "", invalid = false, "aria-invalid": ariaInvalid, ...props }) {
|
|
1788
|
-
return /* @__PURE__ */ jsx(Checkbox$1, {
|
|
1789
|
-
"aria-invalid": invalid ? true : ariaInvalid,
|
|
1790
|
-
className: `inline-flex size-4 shrink-0 items-center justify-center rounded-sm border bg-surface shadow-xs outline-none transition-colors disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground ${invalid ? "border-destructive focus-visible:ring-destructive/20" : "border-input focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/20"} ${className}`,
|
|
1791
|
-
...props,
|
|
1792
|
-
children: /* @__PURE__ */ jsx(CheckboxIndicator, {
|
|
1793
|
-
className: "flex items-center justify-center",
|
|
1794
|
-
children: /* @__PURE__ */ jsx(Check, {
|
|
1795
|
-
className: "size-3",
|
|
1796
|
-
"aria-hidden": true
|
|
1797
|
-
})
|
|
1798
|
-
})
|
|
1799
|
-
});
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
|
-
//#endregion
|
|
1803
|
-
//#region ../ui-kit/src/components/Textarea.tsx
|
|
1804
|
-
/** Source-owned textarea with the same form-control states as Input. */
|
|
1805
|
-
function Textarea({ className = "", invalid = false, "aria-invalid": ariaInvalid, ...props }) {
|
|
1806
|
-
return /* @__PURE__ */ jsx("textarea", {
|
|
1807
|
-
"aria-invalid": invalid ? true : ariaInvalid,
|
|
1808
|
-
className: `min-h-20 w-full resize-y rounded-md border bg-surface px-3 py-2 text-sm text-ink shadow-xs outline-none transition-colors placeholder:text-muted disabled:cursor-not-allowed disabled:opacity-50 ${invalid ? "border-destructive focus-visible:ring-destructive/20" : "border-input focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/20"} ${className}`,
|
|
1809
|
-
...props
|
|
1810
|
-
});
|
|
1811
|
-
}
|
|
1669
|
+
__name$13(dispatchDiscreteCustomEvent, "dispatchDiscreteCustomEvent");
|
|
1812
1670
|
|
|
1813
1671
|
//#endregion
|
|
1814
1672
|
//#region ../../node_modules/.pnpm/@radix-ui+react-switch@1.3.7_@types+react-dom@19.2.3_@types+react@19.2.17__@types+react_e96baf15833549650471eefa4ffd78d0/node_modules/@radix-ui/react-switch/dist/index.mjs
|
|
@@ -40690,6 +40548,10 @@ function defaultRuntimeConfig() {
|
|
|
40690
40548
|
approvalScope: "once-per-run"
|
|
40691
40549
|
},
|
|
40692
40550
|
router: { strategy: "progressive" },
|
|
40551
|
+
hooks: {
|
|
40552
|
+
timeoutMs: 5e3,
|
|
40553
|
+
failOnHookError: false
|
|
40554
|
+
},
|
|
40693
40555
|
streaming: true,
|
|
40694
40556
|
renderResult: true,
|
|
40695
40557
|
sandbox: {
|
|
@@ -40699,6 +40561,10 @@ function defaultRuntimeConfig() {
|
|
|
40699
40561
|
readReference: true,
|
|
40700
40562
|
writeArtifact: true,
|
|
40701
40563
|
confirm: true
|
|
40564
|
+
},
|
|
40565
|
+
remoteUrl: {
|
|
40566
|
+
allowHttp: false,
|
|
40567
|
+
allowPrivateHosts: false
|
|
40702
40568
|
}
|
|
40703
40569
|
},
|
|
40704
40570
|
llm: {
|
|
@@ -40719,6 +40585,7 @@ function mergeRuntimeConfigDefaults(partial) {
|
|
|
40719
40585
|
loop: sub("loop", d.loop),
|
|
40720
40586
|
interaction: sub("interaction", d.interaction),
|
|
40721
40587
|
router: sub("router", d.router),
|
|
40588
|
+
hooks: sub("hooks", d.hooks),
|
|
40722
40589
|
streaming: typeof p["streaming"] === "boolean" ? p["streaming"] : d.streaming,
|
|
40723
40590
|
renderResult: typeof p["renderResult"] === "boolean" ? p["renderResult"] : d.renderResult,
|
|
40724
40591
|
sandbox: {
|
|
@@ -40726,6 +40593,10 @@ function mergeRuntimeConfigDefaults(partial) {
|
|
|
40726
40593
|
capabilities: {
|
|
40727
40594
|
...d.sandbox.capabilities,
|
|
40728
40595
|
...p["sandbox"]?.["capabilities"] ?? {}
|
|
40596
|
+
},
|
|
40597
|
+
remoteUrl: {
|
|
40598
|
+
...d.sandbox.remoteUrl,
|
|
40599
|
+
...p["sandbox"]?.["remoteUrl"] ?? {}
|
|
40729
40600
|
}
|
|
40730
40601
|
},
|
|
40731
40602
|
llm: sub("llm", d.llm)
|
|
@@ -40747,8 +40618,36 @@ function withRuntimeConfigDefaults(store) {
|
|
|
40747
40618
|
//#endregion
|
|
40748
40619
|
//#region src/core/interactionBridge.ts
|
|
40749
40620
|
/**
|
|
40621
|
+
* 渲染档 → 能力集。四档在 0.4.0 起 interaction/surface 全部等价,
|
|
40622
|
+
* 差别只剩「是否依赖 optional peer」。作为可注入值传入 CompositeUiBridge,
|
|
40623
|
+
* 便于宿主按实际装配情况覆盖(例如已确认某 peer 不可用)。
|
|
40624
|
+
* @experimental
|
|
40625
|
+
*/
|
|
40626
|
+
const DEFAULT_RENDERER_CAPABILITIES = {
|
|
40627
|
+
native: {
|
|
40628
|
+
interaction: true,
|
|
40629
|
+
surface: true
|
|
40630
|
+
},
|
|
40631
|
+
a2ui: {
|
|
40632
|
+
interaction: true,
|
|
40633
|
+
surface: true,
|
|
40634
|
+
requiresPeer: "@a2ui/lit"
|
|
40635
|
+
},
|
|
40636
|
+
openui: {
|
|
40637
|
+
interaction: true,
|
|
40638
|
+
surface: true,
|
|
40639
|
+
requiresPeer: "@openuidev/react-lang"
|
|
40640
|
+
},
|
|
40641
|
+
vercel: {
|
|
40642
|
+
interaction: true,
|
|
40643
|
+
surface: true,
|
|
40644
|
+
requiresPeer: "@json-render/react"
|
|
40645
|
+
}
|
|
40646
|
+
};
|
|
40647
|
+
/**
|
|
40750
40648
|
* 探测 A2UI Lit 渲染器是否可用(@a2ui/lit 为 optional peer,未安装时 import 失败)。
|
|
40751
40649
|
* Appearance/设置区据此对 A2UI 档置灰;仅动态 import,不强依赖。
|
|
40650
|
+
* @experimental
|
|
40752
40651
|
*/
|
|
40753
40652
|
async function probeA2uiAvailability() {
|
|
40754
40653
|
try {
|
|
@@ -40763,6 +40662,7 @@ async function probeA2uiAvailability() {
|
|
|
40763
40662
|
* 经 @lit/context 向 surface 子树注入 renderMarkdown(markdown-it + dompurify),
|
|
40764
40663
|
* 消除 "[MarkdownDirective] can't render markdown" 降级。
|
|
40765
40664
|
* 未安装时返回 false(宿主可据此保留产品化限制说明)。
|
|
40665
|
+
* @experimental
|
|
40766
40666
|
*/
|
|
40767
40667
|
async function configureA2uiMarkdown(mount) {
|
|
40768
40668
|
let deps;
|
|
@@ -40790,6 +40690,7 @@ async function configureA2uiMarkdown(mount) {
|
|
|
40790
40690
|
/**
|
|
40791
40691
|
* 探测 OpenUI 渲染器是否可用(@openuidev/react-lang 为 optional peer)。
|
|
40792
40692
|
* Appearance/设置区据此对 OpenUI 档置灰;仅动态 import,不强依赖。
|
|
40693
|
+
* @experimental
|
|
40793
40694
|
*/
|
|
40794
40695
|
async function probeOpenUiAvailability() {
|
|
40795
40696
|
try {
|
|
@@ -40799,135 +40700,52 @@ async function probeOpenUiAvailability() {
|
|
|
40799
40700
|
return false;
|
|
40800
40701
|
}
|
|
40801
40702
|
}
|
|
40802
|
-
/**
|
|
40803
|
-
|
|
40804
|
-
|
|
40805
|
-
|
|
40806
|
-
|
|
40807
|
-
|
|
40808
|
-
* - attach/detach 标记渲染视图是否挂载(未挂载时桥直接降级 native,不悬挂请求)。
|
|
40809
|
-
*/
|
|
40810
|
-
var OpenUiChannel = class {
|
|
40811
|
-
#current;
|
|
40812
|
-
#listeners = /* @__PURE__ */ new Set();
|
|
40813
|
-
#attached = 0;
|
|
40814
|
-
#failure;
|
|
40815
|
-
/** React useSyncExternalStore 兼容订阅 */
|
|
40816
|
-
subscribe = (listener) => {
|
|
40817
|
-
this.#listeners.add(listener);
|
|
40818
|
-
return () => this.#listeners.delete(listener);
|
|
40819
|
-
};
|
|
40820
|
-
get current() {
|
|
40821
|
-
return this.#current?.session;
|
|
40822
|
-
}
|
|
40823
|
-
get isAttached() {
|
|
40824
|
-
return this.#attached > 0;
|
|
40825
|
-
}
|
|
40826
|
-
/** react 层初始化失败原因(未安装 @openuidev/react-lang 等);记录后粘性生效 */
|
|
40827
|
-
get failure() {
|
|
40828
|
-
return this.#failure;
|
|
40829
|
-
}
|
|
40830
|
-
attach() {
|
|
40831
|
-
this.#attached += 1;
|
|
40832
|
-
}
|
|
40833
|
-
detach() {
|
|
40834
|
-
this.#attached = Math.max(0, this.#attached - 1);
|
|
40835
|
-
}
|
|
40836
|
-
request(input) {
|
|
40837
|
-
if (this.#current) this.#settle({
|
|
40838
|
-
id: this.#current.session.request.id,
|
|
40839
|
-
cancelled: true
|
|
40840
|
-
});
|
|
40841
|
-
return new Promise((resolve, reject) => {
|
|
40842
|
-
this.#current = {
|
|
40843
|
-
session: {
|
|
40844
|
-
request: input,
|
|
40845
|
-
lang: toOpenUiLang(input)
|
|
40846
|
-
},
|
|
40847
|
-
resolve,
|
|
40848
|
-
reject
|
|
40849
|
-
};
|
|
40850
|
-
this.#emit();
|
|
40851
|
-
});
|
|
40852
|
-
}
|
|
40853
|
-
/** runtime 交互超时/取消:以 cancelled resolve 挂起的 request(防悬挂 + 残留) */
|
|
40854
|
-
cancel(id) {
|
|
40855
|
-
if (this.#current?.session.request.id === id) this.#settle({
|
|
40856
|
-
id,
|
|
40857
|
-
cancelled: true
|
|
40858
|
-
});
|
|
40859
|
-
}
|
|
40860
|
-
/** react 层 OpenUI 动作回传(fromOpenUiAction:Allow → value:true;Deny/Cancel → cancelled:true) */
|
|
40861
|
-
handleAction(action) {
|
|
40862
|
-
if (!this.#current) return;
|
|
40863
|
-
this.#settle(fromOpenUiAction(action));
|
|
40864
|
-
}
|
|
40865
|
-
/** react 层初始化失败:挂起请求 reject 并记录原因(桥读取后降级 native) */
|
|
40866
|
-
fail(message) {
|
|
40867
|
-
this.#failure = message;
|
|
40868
|
-
const pending = this.#current;
|
|
40869
|
-
this.#current = void 0;
|
|
40870
|
-
this.#emit();
|
|
40871
|
-
pending?.reject(new Error(message));
|
|
40872
|
-
}
|
|
40873
|
-
#settle(response) {
|
|
40874
|
-
const pending = this.#current;
|
|
40875
|
-
this.#current = void 0;
|
|
40876
|
-
this.#emit();
|
|
40877
|
-
pending?.resolve(response);
|
|
40878
|
-
}
|
|
40879
|
-
#emit() {
|
|
40880
|
-
for (const listener of [...this.#listeners]) listener();
|
|
40881
|
-
}
|
|
40703
|
+
/** 渲染档在告警文案里的显示名(面向用户,不用内部 kind 字面量) */
|
|
40704
|
+
const RENDERER_LABEL = {
|
|
40705
|
+
native: "native",
|
|
40706
|
+
a2ui: "A2UI",
|
|
40707
|
+
openui: "OpenUI",
|
|
40708
|
+
vercel: "json-render"
|
|
40882
40709
|
};
|
|
40883
40710
|
/**
|
|
40884
40711
|
* 复合 UiBridge(P2/P3 渲染框架档):
|
|
40885
40712
|
* - streamingText / renderResult 始终委托 ReactBridgeState(结果块数据源不变);
|
|
40886
40713
|
* - 交互 request/cancel 按渲染档分发:native → ReactBridgeState(InteractionCard),
|
|
40887
|
-
*
|
|
40888
|
-
*
|
|
40889
|
-
*
|
|
40890
|
-
* -
|
|
40891
|
-
*
|
|
40714
|
+
* 其余三档 → SpecInteractionChannel(core 产出 catalog 节点树,react 层交给本档
|
|
40715
|
+
* 已有的 spec 渲染路径:A2uiSpecSurface / OpenUiSpecSurface / JsonRenderSpecSurface);
|
|
40716
|
+
* - 每次交互开始/结束发 interaction-requested/resolved 事件;
|
|
40717
|
+
* - 非 native 档初始化失败(optional peer 未安装等)降级 native + warning 事件,不阻断 run。
|
|
40718
|
+
* @stable
|
|
40892
40719
|
*/
|
|
40893
40720
|
var CompositeUiBridge = class {
|
|
40894
40721
|
#deps;
|
|
40895
|
-
#
|
|
40896
|
-
/**
|
|
40722
|
+
#capabilities;
|
|
40723
|
+
/** 非 native 档失败/未挂载后粘性降级 native(同一引擎内不逐请求重复告警) */
|
|
40897
40724
|
#downgraded = false;
|
|
40898
40725
|
constructor(deps) {
|
|
40899
40726
|
this.#deps = deps;
|
|
40727
|
+
this.#capabilities = deps.capabilities ?? DEFAULT_RENDERER_CAPABILITIES;
|
|
40900
40728
|
}
|
|
40901
|
-
/**
|
|
40729
|
+
/** 渲染档热切换:清降级状态(新档立即生效,无需重装配 runtime) */
|
|
40902
40730
|
reset() {
|
|
40903
|
-
this.#a2ui = void 0;
|
|
40904
40731
|
this.#downgraded = false;
|
|
40905
40732
|
}
|
|
40906
40733
|
async request(input) {
|
|
40907
40734
|
const renderer = this.#deps.getRenderer();
|
|
40908
|
-
if (
|
|
40909
|
-
const
|
|
40910
|
-
|
|
40911
|
-
else return this.#requestA2ui(bridge, input);
|
|
40912
|
-
}
|
|
40913
|
-
if (renderer === "openui" && !this.#downgraded) {
|
|
40914
|
-
const channel = this.#deps.getOpenUiChannel();
|
|
40735
|
+
if (this.#inTier(renderer)) {
|
|
40736
|
+
const channel = this.#deps.getInteractionChannel();
|
|
40737
|
+
const label = RENDERER_LABEL[renderer];
|
|
40915
40738
|
const failure = channel.failure;
|
|
40916
|
-
if (failure !== void 0) this.#downgrade(`The
|
|
40917
|
-
else if (!channel.isAttached) this.#downgrade(
|
|
40918
|
-
else return this.#
|
|
40739
|
+
if (failure !== void 0) this.#downgrade(`The ${label} renderer failed to initialize (${failure}); falling back to native interaction cards`);
|
|
40740
|
+
else if (!channel.isAttached) this.#downgrade(`The ${label} renderer is selected but its interaction view is not attached; falling back to native interaction cards`);
|
|
40741
|
+
else return this.#requestInTier(channel, label, input);
|
|
40919
40742
|
}
|
|
40920
40743
|
return this.#requestNative(input);
|
|
40921
40744
|
}
|
|
40922
|
-
/** runtime
|
|
40745
|
+
/** runtime 交互超时/取消:按档委托(通道 cancel 会以 cancelled resolve 挂起的 request) */
|
|
40923
40746
|
cancel(id) {
|
|
40924
|
-
|
|
40925
|
-
|
|
40926
|
-
this.#a2ui.bridge.cancel(id);
|
|
40927
|
-
return;
|
|
40928
|
-
}
|
|
40929
|
-
if (renderer === "openui" && !this.#downgraded) {
|
|
40930
|
-
this.#deps.getOpenUiChannel().cancel(id);
|
|
40747
|
+
if (this.#inTier(this.#deps.getRenderer())) {
|
|
40748
|
+
this.#deps.getInteractionChannel().cancel(id);
|
|
40931
40749
|
return;
|
|
40932
40750
|
}
|
|
40933
40751
|
this.#deps.reactBridge.cancel(id);
|
|
@@ -40947,36 +40765,11 @@ var CompositeUiBridge = class {
|
|
|
40947
40765
|
onTextDelta(runId, delta) {
|
|
40948
40766
|
return this.#deps.reactBridge.onTextDelta(runId, delta);
|
|
40949
40767
|
}
|
|
40950
|
-
/**
|
|
40951
|
-
#
|
|
40952
|
-
|
|
40953
|
-
if (!mount) return void 0;
|
|
40954
|
-
if (!this.#a2ui || this.#a2ui.mount !== mount) this.#a2ui = {
|
|
40955
|
-
mount,
|
|
40956
|
-
bridge: new LitRendererBridge({ mount })
|
|
40957
|
-
};
|
|
40958
|
-
return this.#a2ui.bridge;
|
|
40959
|
-
}
|
|
40960
|
-
async #requestA2ui(bridge, input) {
|
|
40961
|
-
this.#deps.emit({
|
|
40962
|
-
type: "interaction-requested",
|
|
40963
|
-
id: input.id,
|
|
40964
|
-
requestType: input.type
|
|
40965
|
-
});
|
|
40966
|
-
try {
|
|
40967
|
-
const response = await bridge.request(input);
|
|
40968
|
-
this.#emitResolved(input, response);
|
|
40969
|
-
return response;
|
|
40970
|
-
} catch (e) {
|
|
40971
|
-
this.#emitResolved(input, {
|
|
40972
|
-
id: input.id,
|
|
40973
|
-
cancelled: true
|
|
40974
|
-
});
|
|
40975
|
-
this.#downgrade(`The A2UI renderer failed to initialize (${messageOf(e)}); falling back to native interaction cards`);
|
|
40976
|
-
return this.#requestNative(input);
|
|
40977
|
-
}
|
|
40768
|
+
/** 本档能否自行渲染交互(能力表允许且未粘性降级) */
|
|
40769
|
+
#inTier(renderer) {
|
|
40770
|
+
return renderer !== "native" && this.#capabilities[renderer].interaction && !this.#downgraded;
|
|
40978
40771
|
}
|
|
40979
|
-
async #
|
|
40772
|
+
async #requestInTier(channel, label, input) {
|
|
40980
40773
|
this.#deps.emit({
|
|
40981
40774
|
type: "interaction-requested",
|
|
40982
40775
|
id: input.id,
|
|
@@ -40991,7 +40784,7 @@ var CompositeUiBridge = class {
|
|
|
40991
40784
|
id: input.id,
|
|
40992
40785
|
cancelled: true
|
|
40993
40786
|
});
|
|
40994
|
-
this.#downgrade(`The
|
|
40787
|
+
this.#downgrade(`The ${label} renderer failed to initialize (${messageOf(e)}); falling back to native interaction cards`);
|
|
40995
40788
|
return this.#requestNative(input);
|
|
40996
40789
|
}
|
|
40997
40790
|
}
|
|
@@ -41024,31 +40817,11 @@ var CompositeUiBridge = class {
|
|
|
41024
40817
|
}
|
|
41025
40818
|
};
|
|
41026
40819
|
|
|
41027
|
-
//#endregion
|
|
41028
|
-
//#region src/core/traceSink.ts
|
|
41029
|
-
/** 写 `<chatRoot>/traces/<runId>.json`;写失败降级 console.warn,不阻断对话 */
|
|
41030
|
-
async function writeRunTrace(fs, chatRoot, run) {
|
|
41031
|
-
const trace = {
|
|
41032
|
-
runId: run.id,
|
|
41033
|
-
sessionId: run.sessionId,
|
|
41034
|
-
startedAt: run.startedAt,
|
|
41035
|
-
...run.endedAt ? { endedAt: run.endedAt } : {},
|
|
41036
|
-
status: run.status === "completed" || run.status === "cancelled" ? run.status : "failed",
|
|
41037
|
-
activeSkills: run.activeSkillNames,
|
|
41038
|
-
events: run.trace
|
|
41039
|
-
};
|
|
41040
|
-
try {
|
|
41041
|
-
await fs.writeText(`${chatRoot}/traces/${run.id}.json`, JSON.stringify(trace, null, 2));
|
|
41042
|
-
} catch (e) {
|
|
41043
|
-
console.warn(`Failed to persist run trace "${run.id}": ${messageOf(e)}`);
|
|
41044
|
-
}
|
|
41045
|
-
}
|
|
41046
|
-
|
|
41047
40820
|
//#endregion
|
|
41048
40821
|
//#region src/core/chatEngine.ts
|
|
41049
40822
|
/** 注入模型的单个附件正文上限(超出截断并标注) */
|
|
41050
40823
|
const ATTACHMENT_TEXT_LIMIT = 32 * 1024;
|
|
41051
|
-
/**
|
|
40824
|
+
/** sdk 的 `SessionMeta` → chatbot 的列表视图类型(跨层适配,非复刻) */
|
|
41052
40825
|
const toSessionMeta = (session) => ({
|
|
41053
40826
|
id: session.id,
|
|
41054
40827
|
createdAt: session.createdAt,
|
|
@@ -41076,7 +40849,7 @@ function createDemoLlm() {
|
|
|
41076
40849
|
return reply ?? "";
|
|
41077
40850
|
};
|
|
41078
40851
|
return {
|
|
41079
|
-
complete: async () => ({ content: nextReply() }),
|
|
40852
|
+
complete: async () => ({ content: textParts(nextReply()) }),
|
|
41080
40853
|
async *stream() {
|
|
41081
40854
|
const content = nextReply();
|
|
41082
40855
|
const chunkSize = Math.max(1, Math.ceil(content.length / 3));
|
|
@@ -41123,6 +40896,7 @@ function createRuntimeLlm(config) {
|
|
|
41123
40896
|
/**
|
|
41124
40897
|
* 对话框引擎:装配 WebSkillRuntime + 会话持久化 + 事件分发。
|
|
41125
40898
|
* llmConfig.load() 是异步的,runtime 在首次 send 前懒装配(#ensureReady)。
|
|
40899
|
+
* @stable
|
|
41126
40900
|
*/
|
|
41127
40901
|
var ChatEngine = class {
|
|
41128
40902
|
bridge;
|
|
@@ -41137,24 +40911,32 @@ var ChatEngine = class {
|
|
|
41137
40911
|
#listeners = /* @__PURE__ */ new Set();
|
|
41138
40912
|
/** runId → 已激活技能累积(skill-activated 事件用;终态清理) */
|
|
41139
40913
|
#runSkills = /* @__PURE__ */ new Map();
|
|
41140
|
-
/** runId → callId → 已发出的工具事件种类(live 与 trace 重放去重;同 callId 同事件不重复发) */
|
|
41141
|
-
#emittedToolEvents = /* @__PURE__ */ new Map();
|
|
41142
40914
|
/** 当前渲染框架档(复合 uiBridge 分发;setRenderer 热切换) */
|
|
41143
40915
|
#renderer;
|
|
41144
|
-
/**
|
|
41145
|
-
#
|
|
41146
|
-
/** openui 档交互通道(Chatbot 的 OpenUiInteraction attach 后生效) */
|
|
41147
|
-
#openUiChannel = new OpenUiChannel();
|
|
40916
|
+
/** 非 native 三档共用的交互通道(Chatbot 的 SpecInteraction attach 后生效) */
|
|
40917
|
+
#interactionChannel = new SpecInteractionChannel();
|
|
41148
40918
|
/** 装配时按 RuntimeConfig 应用(interaction 分发 + renderResult/streaming 透传 ReactBridgeState) */
|
|
41149
40919
|
#uiBridge;
|
|
41150
40920
|
/** RuntimeConfig.loop.maxHistoryMessages(装配时捕获,createSession 透传) */
|
|
41151
40921
|
#maxHistoryMessages;
|
|
41152
40922
|
/** Serializes OPFS draft writes so a slower prior keystroke cannot overwrite a newer value. */
|
|
41153
40923
|
#surfaceDraftWrites = /* @__PURE__ */ new Map();
|
|
40924
|
+
/** run trace 落盘(写失败降级 warn,不阻断对话) */
|
|
40925
|
+
#traceStore;
|
|
40926
|
+
/** 会话落盘;缺省是本包内引用 `FsSessionStore` 的唯一处 */
|
|
40927
|
+
#sessions;
|
|
41154
40928
|
constructor(adapter, options = {}) {
|
|
41155
40929
|
this.#adapter = adapter;
|
|
41156
40930
|
this.#options = options;
|
|
41157
40931
|
this.#chatRoot = (options.chatRoot ?? "/chat").replace(/\/+$/, "");
|
|
40932
|
+
this.#traceStore = new FsRunTraceStore({
|
|
40933
|
+
root: `${this.#chatRoot}/traces`,
|
|
40934
|
+
fs: adapter.storage
|
|
40935
|
+
});
|
|
40936
|
+
this.#sessions = options.sessionStore ?? new FsSessionStore({
|
|
40937
|
+
root: `${this.#chatRoot}/sessions`,
|
|
40938
|
+
fs: adapter.storage
|
|
40939
|
+
});
|
|
41158
40940
|
this.#renderer = options.renderer ?? "native";
|
|
41159
40941
|
this.bridge = new ReactBridgeState({ onSurfaceDraftChange: (runId, surfaceId, value) => this.#persistSurfaceDraft(runId, surfaceId, value) });
|
|
41160
40942
|
const accumulate = this.bridge.onTextDelta.bind(this.bridge);
|
|
@@ -41169,8 +40951,7 @@ var ChatEngine = class {
|
|
|
41169
40951
|
this.#uiBridge = new CompositeUiBridge({
|
|
41170
40952
|
reactBridge: this.bridge,
|
|
41171
40953
|
getRenderer: () => this.#renderer,
|
|
41172
|
-
|
|
41173
|
-
getOpenUiChannel: () => this.#openUiChannel,
|
|
40954
|
+
getInteractionChannel: () => this.#interactionChannel,
|
|
41174
40955
|
emit: (event) => this.#emit(event)
|
|
41175
40956
|
});
|
|
41176
40957
|
}
|
|
@@ -41184,13 +40965,9 @@ var ChatEngine = class {
|
|
|
41184
40965
|
this.#renderer = renderer;
|
|
41185
40966
|
this.#uiBridge.reset();
|
|
41186
40967
|
}
|
|
41187
|
-
/**
|
|
41188
|
-
|
|
41189
|
-
this.#
|
|
41190
|
-
}
|
|
41191
|
-
/** openui 档交互通道(Chatbot 的 OpenUiInteraction 订阅/attach;core 只产出 lang 文本) */
|
|
41192
|
-
get openUiChannel() {
|
|
41193
|
-
return this.#openUiChannel;
|
|
40968
|
+
/** 非 native 三档共用的交互通道(Chatbot 的 SpecInteraction 订阅/attach;core 只产出 catalog 节点树) */
|
|
40969
|
+
get interactionChannel() {
|
|
40970
|
+
return this.#interactionChannel;
|
|
41194
40971
|
}
|
|
41195
40972
|
/** 探测 @a2ui/lit 是否安装(Appearance/设置区 A2UI 档置灰判定) */
|
|
41196
40973
|
probeA2uiAvailability() {
|
|
@@ -41217,43 +40994,48 @@ var ChatEngine = class {
|
|
|
41217
40994
|
reloadLlm() {
|
|
41218
40995
|
this.reloadConfig();
|
|
41219
40996
|
}
|
|
41220
|
-
|
|
41221
|
-
|
|
41222
|
-
|
|
41223
|
-
|
|
41224
|
-
|
|
41225
|
-
|
|
41226
|
-
|
|
41227
|
-
|
|
41228
|
-
|
|
41229
|
-
|
|
41230
|
-
|
|
41231
|
-
|
|
41232
|
-
|
|
41233
|
-
}
|
|
41234
|
-
return metas.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
40997
|
+
/**
|
|
40998
|
+
* 会话列表页。归档会话也返回:UI 自己分区展示。
|
|
40999
|
+
* `limit` 不给默认值——缺省属于 `SessionStore` 实现,在这里兜底就等于只下推了一半。
|
|
41000
|
+
*/
|
|
41001
|
+
async listSessions(options = {}) {
|
|
41002
|
+
const page = await this.#sessions.list({
|
|
41003
|
+
includeArchived: true,
|
|
41004
|
+
...options
|
|
41005
|
+
});
|
|
41006
|
+
return {
|
|
41007
|
+
items: page.items.map(toSessionMeta),
|
|
41008
|
+
...page.nextCursor !== void 0 ? { nextCursor: page.nextCursor } : {}
|
|
41009
|
+
};
|
|
41235
41010
|
}
|
|
41236
41011
|
async createSession() {
|
|
41237
|
-
const session = {
|
|
41238
|
-
id: newId("session"),
|
|
41239
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41240
|
-
messages: []
|
|
41241
|
-
};
|
|
41242
|
-
await this.#writeSession(session);
|
|
41012
|
+
const session = await this.#sessions.create({ id: newId("session") });
|
|
41243
41013
|
this.#currentSessionId = session.id;
|
|
41244
41014
|
return {
|
|
41245
41015
|
id: session.id,
|
|
41246
41016
|
createdAt: session.createdAt
|
|
41247
41017
|
};
|
|
41248
41018
|
}
|
|
41249
|
-
|
|
41250
|
-
|
|
41019
|
+
/**
|
|
41020
|
+
* 选中会话并取**最新**一页历史(页内时间升序)。
|
|
41021
|
+
* 返回全量 `ChatMessage[]` 的旧签名已移除:长会话下它强迫每个调用方拿全量。
|
|
41022
|
+
*/
|
|
41023
|
+
async selectSession(id, options = {}) {
|
|
41024
|
+
const page = await this.#sessions.listMessages(id, options);
|
|
41251
41025
|
this.#currentSessionId = id;
|
|
41252
|
-
return
|
|
41026
|
+
return page;
|
|
41027
|
+
}
|
|
41028
|
+
/** 向历史方向再取一页;`cursor` 只能来自上一页的 `nextCursor` */
|
|
41029
|
+
async loadMoreMessages(cursor, options = {}) {
|
|
41030
|
+
const sessionId = this.#currentSessionId;
|
|
41031
|
+
if (!sessionId) throw new WebSkillError("VALIDATION_FAILED", "Cannot load more messages: no active session");
|
|
41032
|
+
return this.#sessions.listMessages(sessionId, {
|
|
41033
|
+
cursor,
|
|
41034
|
+
...options
|
|
41035
|
+
});
|
|
41253
41036
|
}
|
|
41254
41037
|
async deleteSession(id) {
|
|
41255
|
-
|
|
41256
|
-
if (await this.#adapter.storage.exists(path)) await this.#adapter.storage.remove(path);
|
|
41038
|
+
await this.#sessions.delete(id);
|
|
41257
41039
|
const attachments = `${this.attachmentsRoot}/${id}`;
|
|
41258
41040
|
if (await this.#adapter.storage.exists(attachments)) await this.#adapter.storage.remove(attachments, { recursive: true });
|
|
41259
41041
|
this.#handles.delete(id);
|
|
@@ -41261,36 +41043,32 @@ var ChatEngine = class {
|
|
|
41261
41043
|
}
|
|
41262
41044
|
/** 重命名会话:写入 title 并锁定(后续 send 不再用首条消息覆盖) */
|
|
41263
41045
|
async renameSession(id, title) {
|
|
41264
|
-
|
|
41265
|
-
session.title = title;
|
|
41266
|
-
session.titleLocked = true;
|
|
41267
|
-
await this.#writeSession(session);
|
|
41046
|
+
await this.#sessions.setTitle(id, title, { lock: true });
|
|
41268
41047
|
this.#emit({
|
|
41269
41048
|
type: "session-updated",
|
|
41270
|
-
session: toSessionMeta(
|
|
41049
|
+
session: toSessionMeta(await this.#requireSession(id))
|
|
41271
41050
|
});
|
|
41272
41051
|
}
|
|
41273
41052
|
/** 归档会话(仅标记,消息与 trace 不动) */
|
|
41274
41053
|
async archiveSession(id) {
|
|
41275
|
-
await this.#setArchived(id, true);
|
|
41054
|
+
await this.#sessions.setArchived(id, true);
|
|
41055
|
+
this.#emit({
|
|
41056
|
+
type: "session-updated",
|
|
41057
|
+
session: toSessionMeta(await this.#requireSession(id))
|
|
41058
|
+
});
|
|
41276
41059
|
}
|
|
41277
41060
|
/** 取消归档 */
|
|
41278
41061
|
async unarchiveSession(id) {
|
|
41279
|
-
await this.#setArchived(id, false);
|
|
41280
|
-
}
|
|
41281
|
-
async #setArchived(id, archived) {
|
|
41282
|
-
const session = await this.#readSession(id);
|
|
41283
|
-
session.archived = archived;
|
|
41284
|
-
await this.#writeSession(session);
|
|
41062
|
+
await this.#sessions.setArchived(id, false);
|
|
41285
41063
|
this.#emit({
|
|
41286
41064
|
type: "session-updated",
|
|
41287
|
-
session: toSessionMeta(
|
|
41065
|
+
session: toSessionMeta(await this.#requireSession(id))
|
|
41288
41066
|
});
|
|
41289
41067
|
}
|
|
41290
41068
|
/** 重发语义:取该 user 消息文本重新 send(assistant 应答新起一轮;不重写历史) */
|
|
41291
41069
|
async retry(messageId) {
|
|
41292
41070
|
const sessionId = this.#currentSessionId;
|
|
41293
|
-
const message = (sessionId ? await this.#
|
|
41071
|
+
const message = (sessionId ? await this.#sessions.get(sessionId) : void 0)?.messages.find((m) => m.id === messageId);
|
|
41294
41072
|
if (!sessionId || !message || message.role !== "user") throw new WebSkillError("VALIDATION_FAILED", `Cannot retry message "${messageId}": no matching user message in the active session`);
|
|
41295
41073
|
await this.send(message.text);
|
|
41296
41074
|
}
|
|
@@ -41300,23 +41078,21 @@ var ChatEngine = class {
|
|
|
41300
41078
|
*/
|
|
41301
41079
|
async editAndResend(messageId, text) {
|
|
41302
41080
|
const sessionId = this.#currentSessionId;
|
|
41303
|
-
const session = sessionId ? await this.#
|
|
41081
|
+
const session = sessionId ? await this.#sessions.get(sessionId) : void 0;
|
|
41304
41082
|
const index = session?.messages.findIndex((m) => m.id === messageId) ?? -1;
|
|
41305
41083
|
const target = session && index >= 0 ? session.messages[index] : void 0;
|
|
41306
|
-
if (!session || !target || target.role !== "user") throw new WebSkillError("VALIDATION_FAILED", `Cannot edit message "${messageId}": no matching user message in the active session`);
|
|
41307
|
-
|
|
41308
|
-
await this.#writeSession(session);
|
|
41084
|
+
if (!sessionId || !session || !target || target.role !== "user") throw new WebSkillError("VALIDATION_FAILED", `Cannot edit message "${messageId}": no matching user message in the active session`);
|
|
41085
|
+
await this.#sessions.replaceMessages(sessionId, session.messages.slice(0, index));
|
|
41309
41086
|
await this.send(text);
|
|
41310
41087
|
}
|
|
41311
41088
|
/** 从当前会话消息列表删除指定消息并持久化(消息不存在/无当前会话时静默跳过) */
|
|
41312
41089
|
async deleteMessage(messageId) {
|
|
41313
41090
|
const sessionId = this.#currentSessionId;
|
|
41314
41091
|
if (!sessionId) return;
|
|
41315
|
-
const session = await this.#
|
|
41092
|
+
const session = await this.#requireSession(sessionId);
|
|
41316
41093
|
const next = session.messages.filter((m) => m.id !== messageId);
|
|
41317
41094
|
if (next.length === session.messages.length) return;
|
|
41318
|
-
|
|
41319
|
-
await this.#writeSession(session);
|
|
41095
|
+
await this.#sessions.replaceMessages(sessionId, next);
|
|
41320
41096
|
}
|
|
41321
41097
|
/**
|
|
41322
41098
|
* 驱动当前 session 的一轮 run。同 session 并发由 runtime session handle 内部
|
|
@@ -41327,7 +41103,7 @@ var ChatEngine = class {
|
|
|
41327
41103
|
if (text.trim() === "" && attachments.length === 0) return;
|
|
41328
41104
|
const runtime = await this.#ensureReady();
|
|
41329
41105
|
const sessionId = this.#currentSessionId ?? (await this.createSession()).id;
|
|
41330
|
-
const session = await this.#
|
|
41106
|
+
const session = await this.#requireSession(sessionId);
|
|
41331
41107
|
const prompt = await this.#withAttachments(text, attachments);
|
|
41332
41108
|
const userMessage = {
|
|
41333
41109
|
id: newId("msg"),
|
|
@@ -41339,9 +41115,8 @@ var ChatEngine = class {
|
|
|
41339
41115
|
kind: "text"
|
|
41340
41116
|
})) } : {}
|
|
41341
41117
|
};
|
|
41342
|
-
|
|
41343
|
-
if (!session.title && !session.titleLocked)
|
|
41344
|
-
await this.#writeSession(session);
|
|
41118
|
+
await this.#sessions.appendMessages(sessionId, [userMessage]);
|
|
41119
|
+
if (!session.title && !session.titleLocked) await this.#sessions.setTitle(sessionId, text.slice(0, 30));
|
|
41345
41120
|
this.#emit({
|
|
41346
41121
|
type: "message-complete",
|
|
41347
41122
|
message: userMessage
|
|
@@ -41349,7 +41124,7 @@ var ChatEngine = class {
|
|
|
41349
41124
|
const handle = this.#sessionHandle(runtime, sessionId);
|
|
41350
41125
|
try {
|
|
41351
41126
|
const result = await handle.run(prompt);
|
|
41352
|
-
await this.#finishRun(
|
|
41127
|
+
await this.#finishRun(sessionId, result);
|
|
41353
41128
|
} catch (e) {
|
|
41354
41129
|
this.#emitError(e);
|
|
41355
41130
|
}
|
|
@@ -41374,7 +41149,7 @@ var ChatEngine = class {
|
|
|
41374
41149
|
cancel(runId) {
|
|
41375
41150
|
return this.#runtime?.cancel(runId) ?? false;
|
|
41376
41151
|
}
|
|
41377
|
-
/**
|
|
41152
|
+
/** 列出 interrupted run(InterruptedBanner 数据源);版本不受支持的项带 unsupported 标记 */
|
|
41378
41153
|
async listInterrupted() {
|
|
41379
41154
|
return this.#snapshotStore().list();
|
|
41380
41155
|
}
|
|
@@ -41393,8 +41168,9 @@ var ChatEngine = class {
|
|
|
41393
41168
|
runId
|
|
41394
41169
|
});
|
|
41395
41170
|
const result = await runtime.resumeRun(runId);
|
|
41396
|
-
const
|
|
41397
|
-
await this.#
|
|
41171
|
+
const sessionId = result.run.sessionId;
|
|
41172
|
+
if (!await this.#sessions.get(sessionId)) await this.#sessions.create({ id: sessionId });
|
|
41173
|
+
await this.#finishRun(sessionId, result);
|
|
41398
41174
|
} catch (e) {
|
|
41399
41175
|
this.#emitError(e);
|
|
41400
41176
|
}
|
|
@@ -41479,6 +41255,21 @@ var ChatEngine = class {
|
|
|
41479
41255
|
return this.#wrappedRuntimeConfig;
|
|
41480
41256
|
}
|
|
41481
41257
|
#wrappedRuntimeConfig;
|
|
41258
|
+
/**
|
|
41259
|
+
* 治理 port → `WebSkillRuntimeDeps` 的逐字段透传(F1)。
|
|
41260
|
+
* 逐字段展开而不是整体 spread:`exactOptionalPropertyTypes` 下把 `undefined`
|
|
41261
|
+
* 显式传给可选字段与不传不等价,而「不传」才是关闭。
|
|
41262
|
+
*/
|
|
41263
|
+
#governanceDeps() {
|
|
41264
|
+
const g = this.#options.governance;
|
|
41265
|
+
if (g === void 0) return {};
|
|
41266
|
+
return {
|
|
41267
|
+
...g.skillStateGuard !== void 0 ? { skillStateGuard: g.skillStateGuard } : {},
|
|
41268
|
+
...g.skillIntegrityGuard !== void 0 ? { skillIntegrityGuard: g.skillIntegrityGuard } : {},
|
|
41269
|
+
...g.skillOutcomeReporter !== void 0 ? { skillOutcomeReporter: g.skillOutcomeReporter } : {},
|
|
41270
|
+
...g.catalogFilter !== void 0 ? { catalogFilter: g.catalogFilter } : {}
|
|
41271
|
+
};
|
|
41272
|
+
}
|
|
41482
41273
|
async #assemble() {
|
|
41483
41274
|
const fs = this.#adapter.storage;
|
|
41484
41275
|
const rc = await this.#runtimeConfigStore()?.load();
|
|
@@ -41517,8 +41308,10 @@ var ChatEngine = class {
|
|
|
41517
41308
|
root: `${this.#chatRoot}/memory`,
|
|
41518
41309
|
fs
|
|
41519
41310
|
}),
|
|
41311
|
+
...this.#options.hooks ? { hooks: this.#applyHooksConfig(this.#options.hooks, rc) } : {},
|
|
41520
41312
|
externalTools: [...pageSkillSource ? [pageSkillSource] : [], ...this.#options.generativeUi ? [createUiCatalogToolSource()] : []],
|
|
41521
41313
|
skillProviders: pageSkillSource ? [pageSkillSource] : [],
|
|
41314
|
+
...this.#governanceDeps(),
|
|
41522
41315
|
...Object.keys(loopConfig).length > 0 ? { config: loopConfig } : {},
|
|
41523
41316
|
...model ? { model } : {}
|
|
41524
41317
|
});
|
|
@@ -41530,60 +41323,50 @@ var ChatEngine = class {
|
|
|
41530
41323
|
runId: event.runId
|
|
41531
41324
|
});
|
|
41532
41325
|
}
|
|
41533
|
-
|
|
41326
|
+
const toolData = event.phase === "execute" && event.data.kind === "tool" ? event.data : void 0;
|
|
41327
|
+
if (!toolData) this.#emit({
|
|
41534
41328
|
type: "lifecycle",
|
|
41535
41329
|
runId: event.runId,
|
|
41536
|
-
phase: event.phase,
|
|
41537
41330
|
at: Date.parse(event.ts),
|
|
41331
|
+
phase: event.phase,
|
|
41538
41332
|
...event.data ? { data: event.data } : {}
|
|
41539
41333
|
});
|
|
41540
41334
|
if (event.phase === "activate") {
|
|
41541
|
-
const
|
|
41542
|
-
|
|
41543
|
-
|
|
41544
|
-
|
|
41545
|
-
|
|
41546
|
-
|
|
41547
|
-
|
|
41548
|
-
|
|
41549
|
-
|
|
41550
|
-
|
|
41551
|
-
}
|
|
41552
|
-
|
|
41553
|
-
|
|
41554
|
-
|
|
41555
|
-
|
|
41556
|
-
|
|
41557
|
-
|
|
41558
|
-
|
|
41559
|
-
|
|
41560
|
-
|
|
41561
|
-
|
|
41562
|
-
|
|
41563
|
-
|
|
41564
|
-
|
|
41565
|
-
|
|
41566
|
-
...args
|
|
41567
|
-
});
|
|
41568
|
-
} else if (status === "completed" || status === "failed") {
|
|
41569
|
-
if (this.#markToolEvent(event.runId, callId, status)) this.#emit({
|
|
41570
|
-
type: status === "completed" ? "tool-completed" : "tool-failed",
|
|
41571
|
-
runId: event.runId,
|
|
41572
|
-
callId,
|
|
41573
|
-
name,
|
|
41574
|
-
...args
|
|
41575
|
-
});
|
|
41576
|
-
}
|
|
41335
|
+
const skills = this.#runSkills.get(event.runId) ?? /* @__PURE__ */ new Set();
|
|
41336
|
+
skills.add(event.data.skillName);
|
|
41337
|
+
this.#runSkills.set(event.runId, skills);
|
|
41338
|
+
this.#emit({
|
|
41339
|
+
type: "skill-activated",
|
|
41340
|
+
runId: event.runId,
|
|
41341
|
+
skills: [...skills].sort()
|
|
41342
|
+
});
|
|
41343
|
+
} else if (toolData) {
|
|
41344
|
+
const { status, callId, name } = toolData;
|
|
41345
|
+
const args = toolData.args === "" ? {} : { args: toolData.args };
|
|
41346
|
+
if (status === "started") this.#emit({
|
|
41347
|
+
type: "tool-started",
|
|
41348
|
+
runId: event.runId,
|
|
41349
|
+
callId,
|
|
41350
|
+
name,
|
|
41351
|
+
...args
|
|
41352
|
+
});
|
|
41353
|
+
else this.#emit({
|
|
41354
|
+
type: status === "completed" ? "tool-completed" : "tool-failed",
|
|
41355
|
+
runId: event.runId,
|
|
41356
|
+
callId,
|
|
41357
|
+
name,
|
|
41358
|
+
...args
|
|
41359
|
+
});
|
|
41577
41360
|
} else if (event.phase === "complete" || event.phase === "fail") this.#runSkills.delete(event.runId);
|
|
41578
41361
|
});
|
|
41579
41362
|
this.#runtime = runtime;
|
|
41580
41363
|
return runtime;
|
|
41581
41364
|
}
|
|
41582
|
-
/** run 终态公共路径(send / resume
|
|
41583
|
-
async #finishRun(
|
|
41365
|
+
/** run 终态公共路径(send / resume 共用):消息持久化 → trace 落盘 → 事件 */
|
|
41366
|
+
async #finishRun(sessionId, result) {
|
|
41584
41367
|
const run = result.run;
|
|
41585
41368
|
const status = run.status === "completed" || run.status === "cancelled" ? run.status : "failed";
|
|
41586
|
-
const toolCalls =
|
|
41369
|
+
const toolCalls = summarizeToolCalls(run);
|
|
41587
41370
|
const latest = this.bridge.latestResult;
|
|
41588
41371
|
const blocks = latest && latest.runId === run.id ? latest.blocks.filter((block) => block.type !== "markdown" || block.text.trim() !== result.output.trim()) : void 0;
|
|
41589
41372
|
const surfaces = this.bridge.surfaceSnapshots.filter((snapshot) => snapshot.runId === run.id);
|
|
@@ -41598,9 +41381,8 @@ var ChatEngine = class {
|
|
|
41598
41381
|
...surfaces.length > 0 ? { surfaces } : {},
|
|
41599
41382
|
...toolCalls.length > 0 ? { toolCalls } : {}
|
|
41600
41383
|
};
|
|
41601
|
-
|
|
41602
|
-
await this.#
|
|
41603
|
-
await writeRunTrace(this.#adapter.storage, this.#chatRoot, run);
|
|
41384
|
+
await this.#sessions.appendMessages(sessionId, [assistantMessage]);
|
|
41385
|
+
await this.#traceStore.put(run);
|
|
41604
41386
|
this.#emit({
|
|
41605
41387
|
type: "run-completed",
|
|
41606
41388
|
runId: run.id,
|
|
@@ -41613,67 +41395,6 @@ var ChatEngine = class {
|
|
|
41613
41395
|
message: assistantMessage
|
|
41614
41396
|
});
|
|
41615
41397
|
this.#runSkills.delete(run.id);
|
|
41616
|
-
this.#emittedToolEvents.delete(run.id);
|
|
41617
|
-
}
|
|
41618
|
-
/**
|
|
41619
|
-
* 工具事件去重标记:live(runtime.events)与 trace 重放共用。
|
|
41620
|
-
* 返回 true 表示该 (runId, callId, kind) 首次标记(应发出事件),false 表示已发过。
|
|
41621
|
-
*/
|
|
41622
|
-
#markToolEvent(runId, callId, kind) {
|
|
41623
|
-
let byCallId = this.#emittedToolEvents.get(runId);
|
|
41624
|
-
if (!byCallId) {
|
|
41625
|
-
byCallId = /* @__PURE__ */ new Map();
|
|
41626
|
-
this.#emittedToolEvents.set(runId, byCallId);
|
|
41627
|
-
}
|
|
41628
|
-
let kinds = byCallId.get(callId);
|
|
41629
|
-
if (!kinds) {
|
|
41630
|
-
kinds = /* @__PURE__ */ new Set();
|
|
41631
|
-
byCallId.set(callId, kinds);
|
|
41632
|
-
}
|
|
41633
|
-
if (kinds.has(kind)) return false;
|
|
41634
|
-
kinds.add(kind);
|
|
41635
|
-
return true;
|
|
41636
|
-
}
|
|
41637
|
-
/**
|
|
41638
|
-
* 工具事件 trace 重放(去重兜底):live 已发出的 (callId, kind) 不重复发;
|
|
41639
|
-
* 返回该 run 的工具调用终态序列(写入 assistant 消息,trace 为权威来源)。
|
|
41640
|
-
*/
|
|
41641
|
-
#replayToolEvents(run) {
|
|
41642
|
-
const toolCalls = [];
|
|
41643
|
-
for (const event of run.trace) {
|
|
41644
|
-
if (event.type !== "tool.started" && event.type !== "tool.completed" && event.type !== "tool.failed") continue;
|
|
41645
|
-
const name = event.data?.["name"];
|
|
41646
|
-
const callId = event.data?.["callId"];
|
|
41647
|
-
if (typeof name !== "string" || typeof callId !== "string") continue;
|
|
41648
|
-
const args = typeof event.data?.["args"] === "string" ? { args: event.data["args"] } : {};
|
|
41649
|
-
if (event.type === "tool.started") {
|
|
41650
|
-
if (this.#markToolEvent(run.id, callId, "started")) this.#emit({
|
|
41651
|
-
type: "tool-started",
|
|
41652
|
-
runId: run.id,
|
|
41653
|
-
callId,
|
|
41654
|
-
name,
|
|
41655
|
-
...args
|
|
41656
|
-
});
|
|
41657
|
-
} else {
|
|
41658
|
-
const status = event.type === "tool.completed" ? "completed" : "failed";
|
|
41659
|
-
const durationMs = typeof event.data?.["durationMs"] === "number" ? { durationMs: event.data["durationMs"] } : {};
|
|
41660
|
-
if (this.#markToolEvent(run.id, callId, status)) this.#emit({
|
|
41661
|
-
type: status === "completed" ? "tool-completed" : "tool-failed",
|
|
41662
|
-
runId: run.id,
|
|
41663
|
-
callId,
|
|
41664
|
-
name,
|
|
41665
|
-
...args
|
|
41666
|
-
});
|
|
41667
|
-
toolCalls.push({
|
|
41668
|
-
callId,
|
|
41669
|
-
name,
|
|
41670
|
-
status,
|
|
41671
|
-
...args,
|
|
41672
|
-
...durationMs
|
|
41673
|
-
});
|
|
41674
|
-
}
|
|
41675
|
-
}
|
|
41676
|
-
return toolCalls;
|
|
41677
41398
|
}
|
|
41678
41399
|
#snapshotStore() {
|
|
41679
41400
|
return new FsRunSnapshotStore({
|
|
@@ -41681,6 +41402,14 @@ var ChatEngine = class {
|
|
|
41681
41402
|
fs: this.#adapter.storage
|
|
41682
41403
|
});
|
|
41683
41404
|
}
|
|
41405
|
+
/** 钩子执行策略来自 console 编辑的 RuntimeConfig;钩子本身由宿主注册,UI 不碰函数 */
|
|
41406
|
+
#applyHooksConfig(hooks, rc) {
|
|
41407
|
+
if (rc) {
|
|
41408
|
+
hooks.timeoutMs = rc.hooks.timeoutMs;
|
|
41409
|
+
hooks.failOnHookError = rc.hooks.failOnHookError;
|
|
41410
|
+
}
|
|
41411
|
+
return hooks;
|
|
41412
|
+
}
|
|
41684
41413
|
/** 每个 session 一个 runtime session 句柄(跨 run 历史延续),Map 缓存 */
|
|
41685
41414
|
#sessionHandle(runtime, sessionId) {
|
|
41686
41415
|
let handle = this.#handles.get(sessionId);
|
|
@@ -41693,26 +41422,10 @@ var ChatEngine = class {
|
|
|
41693
41422
|
}
|
|
41694
41423
|
return handle;
|
|
41695
41424
|
}
|
|
41696
|
-
#
|
|
41697
|
-
|
|
41698
|
-
|
|
41699
|
-
|
|
41700
|
-
const path = this.#sessionPath(id);
|
|
41701
|
-
if (!await this.#adapter.storage.exists(path)) throw new WebSkillError("FS_NOT_FOUND", `Chat session "${id}" not found at ${path}`);
|
|
41702
|
-
return JSON.parse(await this.#adapter.storage.readText(path));
|
|
41703
|
-
}
|
|
41704
|
-
/** resume 用:会话文件被删除时用空会话兜底(恢复不因此失败) */
|
|
41705
|
-
async #readSessionOrNew(id) {
|
|
41706
|
-
const path = this.#sessionPath(id);
|
|
41707
|
-
if (await this.#adapter.storage.exists(path)) return JSON.parse(await this.#adapter.storage.readText(path));
|
|
41708
|
-
return {
|
|
41709
|
-
id,
|
|
41710
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41711
|
-
messages: []
|
|
41712
|
-
};
|
|
41713
|
-
}
|
|
41714
|
-
async #writeSession(session) {
|
|
41715
|
-
await this.#adapter.storage.writeText(this.#sessionPath(session.id), JSON.stringify(session, null, 2));
|
|
41425
|
+
async #requireSession(id) {
|
|
41426
|
+
const session = await this.#sessions.get(id);
|
|
41427
|
+
if (!session) throw new WebSkillError("FS_NOT_FOUND", `Chat session "${id}" not found under ${this.#chatRoot}/sessions`);
|
|
41428
|
+
return session;
|
|
41716
41429
|
}
|
|
41717
41430
|
};
|
|
41718
41431
|
|
|
@@ -41722,6 +41435,7 @@ var ChatEngine = class {
|
|
|
41722
41435
|
* chatbot 双语字典:全部 UI 文案的单一来源(英文为主,zh 条目齐全)。
|
|
41723
41436
|
* 特性区块(WelcomeScreen / SettingsDrawer 各节 / authorize 说明等)必须含
|
|
41724
41437
|
* title + description 双语条目——"会说话的 UI"的文案底座。
|
|
41438
|
+
* @stable
|
|
41725
41439
|
*/
|
|
41726
41440
|
const chatbotDictionary = defineDictionary({
|
|
41727
41441
|
en: {
|
|
@@ -41734,6 +41448,14 @@ const chatbotDictionary = defineDictionary({
|
|
|
41734
41448
|
"session.searchPlaceholder": "Search sessions…",
|
|
41735
41449
|
"session.empty": "No conversations yet.",
|
|
41736
41450
|
"session.delete": "Delete session: {title}",
|
|
41451
|
+
"session.rename": "Rename session: {title}",
|
|
41452
|
+
"session.renameInput": "New title for session: {title}",
|
|
41453
|
+
"session.archive": "Archive session: {title}",
|
|
41454
|
+
"session.unarchive": "Unarchive session: {title}",
|
|
41455
|
+
"session.archived": "Archived",
|
|
41456
|
+
"session.loadEarlier": "Load earlier sessions",
|
|
41457
|
+
"session.loading": "Loading…",
|
|
41458
|
+
"message.loadEarlier": "Load earlier messages",
|
|
41737
41459
|
"welcome.title": "The official WebSkill SDK chat",
|
|
41738
41460
|
"welcome.assistantTitle": "How can I help?",
|
|
41739
41461
|
"welcome.description": "This chat is the reference implementation of the WebSkill SDK. Ask in natural language: the agent routes your request to installed skills, asks for missing details with native forms, and shows you every step of the run.",
|
|
@@ -41853,6 +41575,7 @@ const chatbotDictionary = defineDictionary({
|
|
|
41853
41575
|
"vercel.preview.title": "Vercel AI SDK data contract",
|
|
41854
41576
|
"vercel.preview.badge": "Preview",
|
|
41855
41577
|
"vercel.preview.description": "This is the data contract for integrating the Vercel AI SDK — a payload preview, not a full runtime. The interaction renders as JSON instead of a form; cancel to end it.",
|
|
41578
|
+
"surface.legacy.placeholder": "Generative UI from an earlier version is no longer rendered.",
|
|
41856
41579
|
"error.title": "Something went wrong",
|
|
41857
41580
|
"error.suggestion": "Check the model configuration in Settings, or try again.",
|
|
41858
41581
|
"error.dismiss": "Dismiss"
|
|
@@ -41867,6 +41590,14 @@ const chatbotDictionary = defineDictionary({
|
|
|
41867
41590
|
"session.searchPlaceholder": "搜索会话…",
|
|
41868
41591
|
"session.empty": "暂无会话。",
|
|
41869
41592
|
"session.delete": "删除会话:{title}",
|
|
41593
|
+
"session.rename": "重命名会话:{title}",
|
|
41594
|
+
"session.renameInput": "会话新标题:{title}",
|
|
41595
|
+
"session.archive": "归档会话:{title}",
|
|
41596
|
+
"session.unarchive": "取消归档:{title}",
|
|
41597
|
+
"session.archived": "已归档",
|
|
41598
|
+
"session.loadEarlier": "加载更早的会话",
|
|
41599
|
+
"session.loading": "加载中…",
|
|
41600
|
+
"message.loadEarlier": "加载更早的消息",
|
|
41870
41601
|
"welcome.title": "WebSkill SDK 官方对话框",
|
|
41871
41602
|
"welcome.assistantTitle": "我可以帮你做什么?",
|
|
41872
41603
|
"welcome.description": "本对话框是 WebSkill SDK 的官方参考实现。用自然语言提问:Agent 会把请求路由到已安装的技能,用原生表单补齐缺失信息,并实时展示运行的每一步。",
|
|
@@ -41986,23 +41717,18 @@ const chatbotDictionary = defineDictionary({
|
|
|
41986
41717
|
"vercel.preview.title": "Vercel AI SDK 数据契约",
|
|
41987
41718
|
"vercel.preview.badge": "预览",
|
|
41988
41719
|
"vercel.preview.description": "这是接入 Vercel AI SDK 时的数据契约——payload 预览,非完整运行时。交互以 JSON 而非表单呈现;点击取消结束本次交互。",
|
|
41720
|
+
"surface.legacy.placeholder": "旧版本生成的界面已不再渲染。",
|
|
41989
41721
|
"error.title": "出错了",
|
|
41990
41722
|
"error.suggestion": "请检查设置中的模型配置,或重试。",
|
|
41991
41723
|
"error.dismiss": "关闭"
|
|
41992
41724
|
}
|
|
41993
41725
|
});
|
|
41994
41726
|
const i18n = createI18n(chatbotDictionary);
|
|
41995
|
-
/** chatbot 组件取文案:t('welcome.title') / t('tool.summary.other', { count: 3 }) */
|
|
41727
|
+
/** chatbot 组件取文案:t('welcome.title') / t('tool.summary.other', { count: 3 }) @stable */
|
|
41996
41728
|
const useT = i18n.useT;
|
|
41997
41729
|
|
|
41998
41730
|
//#endregion
|
|
41999
41731
|
//#region src/react/A2uiSurfaceHost.tsx
|
|
42000
|
-
function usesBasicCatalog(snapshot) {
|
|
42001
|
-
return snapshot.surface.kind === "metric" || snapshot.surface.kind === "file" && !snapshot.surface.actions?.length;
|
|
42002
|
-
}
|
|
42003
|
-
function specProps(snapshot) {
|
|
42004
|
-
return snapshot.surface.props;
|
|
42005
|
-
}
|
|
42006
41732
|
/**
|
|
42007
41733
|
* A2UI 回落原因(0.2.8 G2)。
|
|
42008
41734
|
* 之前这里是裸 `catch {}`:缺 optional peer 与真实渲染崩溃表现完全一致——都是静默回落、
|
|
@@ -42021,17 +41747,20 @@ function fallbackReason(error) {
|
|
|
42021
41747
|
return typeof code === "string" && code !== "" ? code : "a2ui-render-failed";
|
|
42022
41748
|
}
|
|
42023
41749
|
/**
|
|
42024
|
-
* catalog 声明树经 BYOC catalog 的 Lit 元素渲染。
|
|
41750
|
+
* `a2ui` 档:catalog 声明树经 BYOC catalog 的 Lit 元素渲染。
|
|
42025
41751
|
* 元素与协议里公布的 `catalog_definition` 派生自同一份 shape,因此这里
|
|
42026
41752
|
* 不需要第二套映射;缺 optional peer 时回落到 native 渲染而不是留白。
|
|
41753
|
+
*
|
|
41754
|
+
* 交互请求(路径 A)与模型产出的 surface(路径 B)共用本组件——这是 0.4.0 B4
|
|
41755
|
+
* 「同一档下命中同一个渲染入口」的落点,`data-testid` 因此对两条路径一致。
|
|
42027
41756
|
*/
|
|
42028
|
-
function A2uiSpecSurface({
|
|
41757
|
+
function A2uiSpecSurface({ spec, surfaceId, actions, onAction, registry, runId, draft, onDraftChange }) {
|
|
42029
41758
|
const mountRef = useRef(null);
|
|
42030
41759
|
const [fallback, setFallback] = useState();
|
|
42031
41760
|
const emit = useEffectEvent((actionId, value) => {
|
|
42032
|
-
const declared = (
|
|
41761
|
+
const declared = (actions ?? []).find((action) => action.id === actionId);
|
|
42033
41762
|
onAction?.({
|
|
42034
|
-
surfaceId
|
|
41763
|
+
surfaceId,
|
|
42035
41764
|
actionId,
|
|
42036
41765
|
intent: declared?.intent ?? "select",
|
|
42037
41766
|
...declared?.nonce ? { nonce: declared.nonce } : {},
|
|
@@ -42041,7 +41770,7 @@ function A2uiSpecSurface({ snapshot, onAction }) {
|
|
|
42041
41770
|
useEffect(() => {
|
|
42042
41771
|
let disposed = false;
|
|
42043
41772
|
let surfaceElement;
|
|
42044
|
-
const
|
|
41773
|
+
const a2uiSurfaceId = `webskill-spec-${surfaceId}`;
|
|
42045
41774
|
(async () => {
|
|
42046
41775
|
try {
|
|
42047
41776
|
const [{ MessageProcessor }, lit, catalog] = await Promise.all([
|
|
@@ -42052,10 +41781,11 @@ function A2uiSpecSurface({ snapshot, onAction }) {
|
|
|
42052
41781
|
lit.A2uiSurface;
|
|
42053
41782
|
const mount = mountRef.current;
|
|
42054
41783
|
if (disposed || !mount) return;
|
|
41784
|
+
configureA2uiMarkdown(mount);
|
|
42055
41785
|
const processor = new MessageProcessor([catalog, lit.basicCatalog], (action) => {
|
|
42056
41786
|
const decoded = fromA2uiSpecAction(action);
|
|
42057
41787
|
if (!decoded) return;
|
|
42058
|
-
const values = processor.getClientDataModel("v0.9.1")?.surfaces?.[
|
|
41788
|
+
const values = processor.getClientDataModel("v0.9.1")?.surfaces?.[a2uiSurfaceId]?.[A2UI_SPEC_FORM_PATH.slice(1)];
|
|
42059
41789
|
emit(decoded.actionId, values ?? {});
|
|
42060
41790
|
}, { version: "v0.9.1" });
|
|
42061
41791
|
processor.onSurfaceCreated((surface) => {
|
|
@@ -42064,58 +41794,9 @@ function A2uiSpecSurface({ snapshot, onAction }) {
|
|
|
42064
41794
|
surfaceElement.surface = surface;
|
|
42065
41795
|
mount.replaceChildren(surfaceElement);
|
|
42066
41796
|
});
|
|
42067
|
-
processor.processMessages(toA2uiSpecMessages(uiCatalog,
|
|
42068
|
-
} catch (error) {
|
|
42069
|
-
reportA2uiFallback(snapshot.surface.id, "spec", error);
|
|
42070
|
-
if (!disposed) setFallback(fallbackReason(error));
|
|
42071
|
-
}
|
|
42072
|
-
})();
|
|
42073
|
-
return () => {
|
|
42074
|
-
disposed = true;
|
|
42075
|
-
surfaceElement?.remove();
|
|
42076
|
-
};
|
|
42077
|
-
}, [snapshot]);
|
|
42078
|
-
if (fallback) {
|
|
42079
|
-
const surface = snapshot.surface;
|
|
42080
|
-
return /* @__PURE__ */ jsx("div", {
|
|
42081
|
-
"data-testid": "a2ui-spec-surface",
|
|
42082
|
-
"data-renderer": "native-fallback",
|
|
42083
|
-
"data-fallback-reason": fallback,
|
|
42084
|
-
children: /* @__PURE__ */ jsx(NativeSpecSurface, {
|
|
42085
|
-
surfaceId: surface.id,
|
|
42086
|
-
spec: specProps(snapshot).spec,
|
|
42087
|
-
actions: surface.actions ?? [],
|
|
42088
|
-
...onAction ? { onAction } : {}
|
|
42089
|
-
})
|
|
42090
|
-
});
|
|
42091
|
-
}
|
|
42092
|
-
return /* @__PURE__ */ jsx("div", {
|
|
42093
|
-
ref: mountRef,
|
|
42094
|
-
"data-testid": "a2ui-spec-surface",
|
|
42095
|
-
"data-webskill-provenance": "a2ui-catalog"
|
|
42096
|
-
});
|
|
42097
|
-
}
|
|
42098
|
-
function A2uiStandardSurface({ snapshot, registry }) {
|
|
42099
|
-
const mountRef = useRef(null);
|
|
42100
|
-
const [fallback, setFallback] = useState();
|
|
42101
|
-
useEffect(() => {
|
|
42102
|
-
let disposed = false;
|
|
42103
|
-
let surfaceElement;
|
|
42104
|
-
(async () => {
|
|
42105
|
-
try {
|
|
42106
|
-
const [{ MessageProcessor }, { A2uiSurface, basicCatalog }] = await Promise.all([import("@a2ui/web_core/v0_9"), import("@a2ui/lit/v0_9")]);
|
|
42107
|
-
const mount = mountRef.current;
|
|
42108
|
-
if (disposed || !mount) return;
|
|
42109
|
-
const processor = new MessageProcessor([basicCatalog], () => void 0, { version: "v0.9.1" });
|
|
42110
|
-
processor.onSurfaceCreated((surface) => {
|
|
42111
|
-
if (disposed) return;
|
|
42112
|
-
surfaceElement = mount.ownerDocument.createElement("a2ui-surface");
|
|
42113
|
-
surfaceElement.surface = surface;
|
|
42114
|
-
mount.replaceChildren(surfaceElement);
|
|
42115
|
-
});
|
|
42116
|
-
processor.processMessages(toA2uiSurfaceMessages(snapshot));
|
|
41797
|
+
processor.processMessages(toA2uiSpecMessages(uiCatalog, spec, { surfaceId: a2uiSurfaceId }));
|
|
42117
41798
|
} catch (error) {
|
|
42118
|
-
reportA2uiFallback(
|
|
41799
|
+
reportA2uiFallback(surfaceId, "spec", error);
|
|
42119
41800
|
if (!disposed) setFallback(fallbackReason(error));
|
|
42120
41801
|
}
|
|
42121
41802
|
})();
|
|
@@ -42123,65 +41804,52 @@ function A2uiStandardSurface({ snapshot, registry }) {
|
|
|
42123
41804
|
disposed = true;
|
|
42124
41805
|
surfaceElement?.remove();
|
|
42125
41806
|
};
|
|
42126
|
-
}, [
|
|
41807
|
+
}, [spec, surfaceId]);
|
|
42127
41808
|
if (fallback) return /* @__PURE__ */ jsx("div", {
|
|
42128
|
-
"data-testid": "a2ui-
|
|
41809
|
+
"data-testid": "a2ui-spec-surface",
|
|
42129
41810
|
"data-renderer": "native-fallback",
|
|
42130
41811
|
"data-fallback-reason": fallback,
|
|
42131
|
-
children: /* @__PURE__ */ jsx(
|
|
42132
|
-
|
|
42133
|
-
|
|
41812
|
+
children: /* @__PURE__ */ jsx(NativeSpecSurface, {
|
|
41813
|
+
surfaceId,
|
|
41814
|
+
spec,
|
|
41815
|
+
actions: actions ?? [],
|
|
41816
|
+
...registry ? { registry } : {},
|
|
41817
|
+
...runId ? { runId } : {},
|
|
41818
|
+
...draft ? { draft } : {},
|
|
41819
|
+
...onAction ? { onAction } : {},
|
|
41820
|
+
...onDraftChange ? { onDraftChange } : {}
|
|
42134
41821
|
})
|
|
42135
41822
|
});
|
|
42136
41823
|
return /* @__PURE__ */ jsx("div", {
|
|
42137
41824
|
ref: mountRef,
|
|
42138
|
-
"data-testid": "a2ui-
|
|
42139
|
-
"data-webskill-provenance": "a2ui-
|
|
41825
|
+
"data-testid": "a2ui-spec-surface",
|
|
41826
|
+
"data-webskill-provenance": "a2ui-catalog"
|
|
42140
41827
|
});
|
|
42141
41828
|
}
|
|
42142
|
-
/** Renders persisted
|
|
41829
|
+
/** Renders persisted WebSkill UI spec snapshots through the A2UI BYOC catalog. @experimental */
|
|
42143
41830
|
function A2uiSurfaceSnapshotHost({ snapshots, registry, onAction, drafts, onDraftChange }) {
|
|
42144
|
-
const specSnapshots = snapshots.filter((snapshot) => isUiSpecSurface(snapshot.surface));
|
|
42145
|
-
const rest = snapshots.filter((snapshot) => !isUiSpecSurface(snapshot.surface));
|
|
42146
|
-
const standardSnapshots = rest.filter(usesBasicCatalog);
|
|
42147
|
-
const extensionSnapshots = rest.filter((snapshot) => !usesBasicCatalog(snapshot));
|
|
42148
41831
|
if (snapshots.length === 0) return null;
|
|
42149
|
-
return /* @__PURE__ */
|
|
41832
|
+
return /* @__PURE__ */ jsx("div", {
|
|
42150
41833
|
"data-testid": "a2ui-surface-host",
|
|
42151
|
-
children:
|
|
42152
|
-
|
|
42153
|
-
|
|
42154
|
-
|
|
42155
|
-
|
|
42156
|
-
|
|
42157
|
-
|
|
42158
|
-
|
|
42159
|
-
|
|
42160
|
-
|
|
42161
|
-
"data-testid": "a2ui-surface-extension",
|
|
42162
|
-
"data-webskill-provenance": "a2ui-extension",
|
|
42163
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
42164
|
-
className: "sr-only",
|
|
42165
|
-
children: "WebSkill extension"
|
|
42166
|
-
}), /* @__PURE__ */ jsx(UiSurfaceSnapshotList, {
|
|
42167
|
-
snapshots: extensionSnapshots,
|
|
42168
|
-
...registry ? { registry } : {},
|
|
42169
|
-
...onAction ? { onAction } : {},
|
|
42170
|
-
...drafts ? { drafts } : {},
|
|
42171
|
-
...onDraftChange ? { onDraftChange } : {}
|
|
42172
|
-
})]
|
|
42173
|
-
}) : null
|
|
42174
|
-
]
|
|
41834
|
+
children: snapshots.map((snapshot) => /* @__PURE__ */ jsx(A2uiSpecSurface, {
|
|
41835
|
+
surfaceId: snapshot.id,
|
|
41836
|
+
spec: snapshot.node,
|
|
41837
|
+
actions: snapshot.actions ?? [],
|
|
41838
|
+
registry,
|
|
41839
|
+
onAction,
|
|
41840
|
+
runId: snapshot.runId,
|
|
41841
|
+
draft: drafts?.[snapshot.id],
|
|
41842
|
+
onDraftChange
|
|
41843
|
+
}, snapshot.id))
|
|
42175
41844
|
});
|
|
42176
41845
|
}
|
|
42177
|
-
/** Renders
|
|
41846
|
+
/** Renders WebSkill UI spec snapshots from live bridge state through the A2UI BYOC catalog. @experimental */
|
|
42178
41847
|
function A2uiSurfaceHost({ bridge, runId, registry }) {
|
|
42179
41848
|
const snapshots = useSyncExternalStore(bridge.subscribe, () => bridge.surfaceSnapshots);
|
|
42180
41849
|
const visibleSnapshots = runId === void 0 ? snapshots : snapshots.filter((snapshot) => snapshot.runId === runId);
|
|
42181
|
-
const actionableSnapshots = visibleSnapshots.filter((snapshot) => isUiSpecSurface(snapshot.surface) || !usesBasicCatalog(snapshot));
|
|
42182
41850
|
const handleAction = (event) => {
|
|
42183
|
-
const snapshot =
|
|
42184
|
-
const action = snapshot
|
|
41851
|
+
const snapshot = visibleSnapshots.find((candidate) => candidate.id === event.surfaceId);
|
|
41852
|
+
const action = snapshot?.actions?.find((candidate) => candidate.id === event.actionId);
|
|
42185
41853
|
if (!snapshot || !action) return;
|
|
42186
41854
|
const decoded = fromA2uiSurfaceAction(toA2uiSurfaceAction(snapshot, action, event.value));
|
|
42187
41855
|
if (!decoded?.runId || !decoded.nonce) return;
|
|
@@ -42362,7 +42030,7 @@ function lifecyclePart(step) {
|
|
|
42362
42030
|
phase: step.phase,
|
|
42363
42031
|
at: step.at,
|
|
42364
42032
|
...step.endedAt !== void 0 ? { endedAt: step.endedAt } : {},
|
|
42365
|
-
...step.
|
|
42033
|
+
...step.note !== void 0 ? { note: step.note } : {}
|
|
42366
42034
|
}
|
|
42367
42035
|
};
|
|
42368
42036
|
}
|
|
@@ -42557,7 +42225,7 @@ function useWebSkillAui({ messages, live, sessions, currentSessionId, sessionsLo
|
|
|
42557
42225
|
//#region src/react/AssistantUiShell.tsx
|
|
42558
42226
|
/**
|
|
42559
42227
|
* assistant-ui only owns the React thread primitives. WebSkill remains the
|
|
42560
|
-
* source of truth for messages, sessions, Runtime actions, and
|
|
42228
|
+
* source of truth for messages, sessions, Runtime actions, and UI spec surface data.
|
|
42561
42229
|
*/
|
|
42562
42230
|
function AssistantUiShellProvider({ children, ...props }) {
|
|
42563
42231
|
return /* @__PURE__ */ jsx(AuiProvider, {
|
|
@@ -42568,15 +42236,23 @@ function AssistantUiShellProvider({ children, ...props }) {
|
|
|
42568
42236
|
children: /* @__PURE__ */ jsx(ThreadPrimitive.ViewportProvider, { children })
|
|
42569
42237
|
});
|
|
42570
42238
|
}
|
|
42571
|
-
function AssistantUiMessageList({ messages, renderMessage }) {
|
|
42239
|
+
function AssistantUiMessageList({ messages, earlier, renderMessage }) {
|
|
42240
|
+
const t = useT();
|
|
42572
42241
|
const byId = useMemo(() => new Map(messages.map((message) => [message.id, message])), [messages]);
|
|
42573
|
-
return /* @__PURE__ */
|
|
42242
|
+
return /* @__PURE__ */ jsxs(ThreadPrimitive.Root, {
|
|
42574
42243
|
"data-testid": "assistant-ui-thread",
|
|
42575
42244
|
className: "flex w-full min-w-0 flex-col gap-4",
|
|
42576
|
-
children:
|
|
42245
|
+
children: [earlier ? /* @__PURE__ */ jsx("button", {
|
|
42246
|
+
type: "button",
|
|
42247
|
+
"data-testid": "load-earlier-messages",
|
|
42248
|
+
disabled: earlier.loading,
|
|
42249
|
+
onClick: earlier.onLoad,
|
|
42250
|
+
className: "self-center rounded-md border border-border px-3 py-1.5 text-sm text-muted transition-colors hover:bg-subtle hover:text-ink disabled:opacity-60",
|
|
42251
|
+
children: earlier.loading ? t("session.loading") : t("message.loadEarlier")
|
|
42252
|
+
}) : null, /* @__PURE__ */ jsx(ThreadPrimitive.Messages, { children: ({ message }) => /* @__PURE__ */ jsx(MessagePrimitive.Root, {
|
|
42577
42253
|
"data-webskill-message-role": message.role,
|
|
42578
42254
|
children: renderMessage(byId.get(message.id))
|
|
42579
|
-
}) })
|
|
42255
|
+
}) })]
|
|
42580
42256
|
});
|
|
42581
42257
|
}
|
|
42582
42258
|
/** Uses assistant-ui's scroll and accessibility viewport for the controlled external thread. */
|
|
@@ -42666,12 +42342,85 @@ function AssistantUiComposer({ running, disabled = false, placeholder, attachmen
|
|
|
42666
42342
|
})
|
|
42667
42343
|
});
|
|
42668
42344
|
}
|
|
42345
|
+
/**
|
|
42346
|
+
* 一行会话。归档区与常规区共用:两边只差 archive/unarchive 一个按钮,
|
|
42347
|
+
* 各写一份迟早会漂。重命名走 `aui.threads.item()`——assistant-ui 没有 Rename primitive,
|
|
42348
|
+
* 但 threads 客户端有 `rename` 方法(ChatEngine.renameSession 的入口)。
|
|
42349
|
+
*/
|
|
42350
|
+
function SessionRow({ id, title, active, archived, renaming, onNavigate, onStartRename, onEndRename }) {
|
|
42351
|
+
const t = useT();
|
|
42352
|
+
const aui = useAui();
|
|
42353
|
+
const iconButton = "inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100 hover:bg-subtle hover:text-ink";
|
|
42354
|
+
const commitRename = (next) => {
|
|
42355
|
+
const trimmed = next.trim();
|
|
42356
|
+
if (trimmed !== "" && trimmed !== title) aui.threads.item({ id }).rename(trimmed);
|
|
42357
|
+
onEndRename();
|
|
42358
|
+
};
|
|
42359
|
+
return /* @__PURE__ */ jsxs(ThreadListItemPrimitive.Root, {
|
|
42360
|
+
role: "listitem",
|
|
42361
|
+
"data-webskill-session-archived": archived ? "true" : void 0,
|
|
42362
|
+
className: "group flex items-center gap-1",
|
|
42363
|
+
children: [renaming ? /* @__PURE__ */ jsx("input", {
|
|
42364
|
+
autoFocus: true,
|
|
42365
|
+
"aria-label": t("session.renameInput", { title }),
|
|
42366
|
+
defaultValue: title,
|
|
42367
|
+
onBlur: (event) => commitRename(event.target.value),
|
|
42368
|
+
onKeyDown: (event) => {
|
|
42369
|
+
if (event.key === "Enter") commitRename(event.currentTarget.value);
|
|
42370
|
+
if (event.key === "Escape") onEndRename();
|
|
42371
|
+
},
|
|
42372
|
+
className: "min-w-0 flex-1 rounded-md border border-input bg-background px-2.5 py-2 text-sm text-ink outline-none focus:border-ring"
|
|
42373
|
+
}) : /* @__PURE__ */ jsx(ThreadListItemPrimitive.Trigger, {
|
|
42374
|
+
"data-webskill-thread-id": id,
|
|
42375
|
+
"aria-current": active ? "page" : void 0,
|
|
42376
|
+
onClick: onNavigate,
|
|
42377
|
+
className: `min-w-0 flex-1 truncate rounded-md px-2.5 py-2 text-left text-sm transition-colors ${active ? "bg-subtle font-medium text-ink" : "text-muted hover:bg-subtle hover:text-ink"}`,
|
|
42378
|
+
children: /* @__PURE__ */ jsx(ThreadListItemPrimitive.Title, { fallback: id })
|
|
42379
|
+
}), renaming ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
42380
|
+
/* @__PURE__ */ jsx("button", {
|
|
42381
|
+
type: "button",
|
|
42382
|
+
"aria-label": t("session.rename", { title }),
|
|
42383
|
+
onClick: onStartRename,
|
|
42384
|
+
className: iconButton,
|
|
42385
|
+
children: /* @__PURE__ */ jsx(Pencil, {
|
|
42386
|
+
className: "size-3.5",
|
|
42387
|
+
"aria-hidden": true
|
|
42388
|
+
})
|
|
42389
|
+
}),
|
|
42390
|
+
archived ? /* @__PURE__ */ jsx(ThreadListItemPrimitive.Unarchive, {
|
|
42391
|
+
"aria-label": t("session.unarchive", { title }),
|
|
42392
|
+
className: iconButton,
|
|
42393
|
+
children: /* @__PURE__ */ jsx(ArchiveRestore, {
|
|
42394
|
+
className: "size-3.5",
|
|
42395
|
+
"aria-hidden": true
|
|
42396
|
+
})
|
|
42397
|
+
}) : /* @__PURE__ */ jsx(ThreadListItemPrimitive.Archive, {
|
|
42398
|
+
"aria-label": t("session.archive", { title }),
|
|
42399
|
+
className: iconButton,
|
|
42400
|
+
children: /* @__PURE__ */ jsx(Archive, {
|
|
42401
|
+
className: "size-3.5",
|
|
42402
|
+
"aria-hidden": true
|
|
42403
|
+
})
|
|
42404
|
+
}),
|
|
42405
|
+
/* @__PURE__ */ jsx(ThreadListItemPrimitive.Delete, {
|
|
42406
|
+
"aria-label": t("session.delete", { title }),
|
|
42407
|
+
className: `${iconButton} hover:bg-danger-soft hover:text-danger`,
|
|
42408
|
+
children: /* @__PURE__ */ jsx(Trash2, {
|
|
42409
|
+
className: "size-3.5",
|
|
42410
|
+
"aria-hidden": true
|
|
42411
|
+
})
|
|
42412
|
+
})
|
|
42413
|
+
] })]
|
|
42414
|
+
});
|
|
42415
|
+
}
|
|
42669
42416
|
/** Sessions are read through the assistant-ui threads client, which ChatEngine drives. */
|
|
42670
|
-
function AssistantUiSessionList({ className = "", onNavigate }) {
|
|
42417
|
+
function AssistantUiSessionList({ className = "", onNavigate, hasEarlier = false, loadingEarlier = false, onLoadEarlier }) {
|
|
42671
42418
|
const t = useT();
|
|
42672
42419
|
const [query, setQuery] = useState("");
|
|
42420
|
+
const [renamingId, setRenamingId] = useState();
|
|
42673
42421
|
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
42674
42422
|
const threadIds = useAuiState((s) => s.threads.threadIds);
|
|
42423
|
+
const archivedThreadIds = useAuiState((s) => s.threads.archivedThreadIds);
|
|
42675
42424
|
const threadItems = useAuiState((s) => s.threads.threadItems);
|
|
42676
42425
|
const mainThreadId = useAuiState((s) => s.threads.mainThreadId);
|
|
42677
42426
|
const matches = useMemo(() => {
|
|
@@ -42681,6 +42430,7 @@ function AssistantUiSessionList({ className = "", onNavigate }) {
|
|
|
42681
42430
|
};
|
|
42682
42431
|
}, [threadItems, normalizedQuery]);
|
|
42683
42432
|
const visibleCount = threadIds.filter(matches).length;
|
|
42433
|
+
const visibleArchivedCount = archivedThreadIds.filter(matches).length;
|
|
42684
42434
|
return /* @__PURE__ */ jsxs(ThreadListPrimitive.Root, {
|
|
42685
42435
|
"data-testid": "assistant-ui-thread-list",
|
|
42686
42436
|
"aria-label": t("session.title"),
|
|
@@ -42716,32 +42466,53 @@ function AssistantUiSessionList({ className = "", onNavigate }) {
|
|
|
42716
42466
|
/* @__PURE__ */ jsxs("div", {
|
|
42717
42467
|
className: "min-h-0 flex-1 overflow-y-auto px-2 pb-3",
|
|
42718
42468
|
role: "list",
|
|
42719
|
-
children: [
|
|
42720
|
-
|
|
42721
|
-
|
|
42722
|
-
|
|
42723
|
-
|
|
42724
|
-
|
|
42725
|
-
|
|
42726
|
-
|
|
42727
|
-
|
|
42728
|
-
|
|
42729
|
-
|
|
42730
|
-
|
|
42731
|
-
|
|
42732
|
-
|
|
42733
|
-
|
|
42734
|
-
|
|
42735
|
-
|
|
42736
|
-
|
|
42737
|
-
|
|
42738
|
-
|
|
42739
|
-
|
|
42740
|
-
|
|
42741
|
-
|
|
42742
|
-
|
|
42743
|
-
|
|
42744
|
-
|
|
42469
|
+
children: [
|
|
42470
|
+
hasEarlier && onLoadEarlier ? /* @__PURE__ */ jsx("button", {
|
|
42471
|
+
type: "button",
|
|
42472
|
+
"data-testid": "load-earlier-sessions",
|
|
42473
|
+
disabled: loadingEarlier,
|
|
42474
|
+
onClick: onLoadEarlier,
|
|
42475
|
+
className: "mb-1 w-full rounded-md px-2.5 py-2 text-sm text-muted transition-colors hover:bg-subtle hover:text-ink disabled:opacity-60",
|
|
42476
|
+
children: loadingEarlier ? t("session.loading") : t("session.loadEarlier")
|
|
42477
|
+
}) : null,
|
|
42478
|
+
visibleCount === 0 ? /* @__PURE__ */ jsx("p", {
|
|
42479
|
+
className: "px-2 py-4 text-sm text-muted",
|
|
42480
|
+
children: t("session.empty")
|
|
42481
|
+
}) : null,
|
|
42482
|
+
/* @__PURE__ */ jsx(ThreadListPrimitive.Items, { children: ({ threadListItem }) => {
|
|
42483
|
+
if (!matches(threadListItem.id)) return null;
|
|
42484
|
+
return /* @__PURE__ */ jsx(SessionRow, {
|
|
42485
|
+
id: threadListItem.id,
|
|
42486
|
+
title: threadListItem.title ?? threadListItem.id,
|
|
42487
|
+
active: threadListItem.id === mainThreadId,
|
|
42488
|
+
archived: false,
|
|
42489
|
+
renaming: renamingId === threadListItem.id,
|
|
42490
|
+
onNavigate,
|
|
42491
|
+
onStartRename: () => setRenamingId(threadListItem.id),
|
|
42492
|
+
onEndRename: () => setRenamingId(void 0)
|
|
42493
|
+
});
|
|
42494
|
+
} }),
|
|
42495
|
+
visibleArchivedCount > 0 ? /* @__PURE__ */ jsx("p", {
|
|
42496
|
+
className: "px-2.5 pb-1 pt-4 text-xs font-medium uppercase tracking-wide text-muted",
|
|
42497
|
+
children: t("session.archived")
|
|
42498
|
+
}) : null,
|
|
42499
|
+
/* @__PURE__ */ jsx(ThreadListPrimitive.Items, {
|
|
42500
|
+
archived: true,
|
|
42501
|
+
children: ({ threadListItem }) => {
|
|
42502
|
+
if (!matches(threadListItem.id)) return null;
|
|
42503
|
+
return /* @__PURE__ */ jsx(SessionRow, {
|
|
42504
|
+
id: threadListItem.id,
|
|
42505
|
+
title: threadListItem.title ?? threadListItem.id,
|
|
42506
|
+
active: threadListItem.id === mainThreadId,
|
|
42507
|
+
archived: true,
|
|
42508
|
+
renaming: renamingId === threadListItem.id,
|
|
42509
|
+
onNavigate,
|
|
42510
|
+
onStartRename: () => setRenamingId(threadListItem.id),
|
|
42511
|
+
onEndRename: () => setRenamingId(void 0)
|
|
42512
|
+
});
|
|
42513
|
+
}
|
|
42514
|
+
})
|
|
42515
|
+
]
|
|
42745
42516
|
})
|
|
42746
42517
|
]
|
|
42747
42518
|
});
|
|
@@ -42921,8 +42692,7 @@ function LifecycleStep({ data }) {
|
|
|
42921
42692
|
const at = typeof data["at"] === "number" ? data["at"] : void 0;
|
|
42922
42693
|
const endedAt = typeof data["endedAt"] === "number" ? data["endedAt"] : void 0;
|
|
42923
42694
|
const duration = at !== void 0 && endedAt !== void 0 ? formatDuration(endedAt - at) : void 0;
|
|
42924
|
-
const
|
|
42925
|
-
const note = readString(detail, "strategy") ?? readString(detail, "type") ?? readString(detail, "reason");
|
|
42695
|
+
const note = readString(data, "note");
|
|
42926
42696
|
const label = t(key);
|
|
42927
42697
|
return /* @__PURE__ */ jsxs("li", {
|
|
42928
42698
|
"aria-label": duration ? `${label}, ${duration}` : label,
|
|
@@ -43094,279 +42864,18 @@ function WebSkillMessageParts() {
|
|
|
43094
42864
|
});
|
|
43095
42865
|
}
|
|
43096
42866
|
|
|
43097
|
-
//#endregion
|
|
43098
|
-
//#region src/react/OpenUiInteraction.tsx
|
|
43099
|
-
const inputClass = "w-full rounded-lg border border-border bg-surface px-3 py-2 text-sm text-ink transition-colors placeholder:text-muted hover:border-ring";
|
|
43100
|
-
/**
|
|
43101
|
-
* openui-lang 组件词汇的 ui-kit 视觉实现(与 @webskill/ui toOpenUiLang 的约定一致:
|
|
43102
|
-
* Form/Text/TextField/NumberField/BooleanField/SelectField/SubmitButton/CancelButton)。
|
|
43103
|
-
* 视觉对齐 native InteractionCard 的表单样式。
|
|
43104
|
-
*/
|
|
43105
|
-
function buildOpenUiLibrary(openui, z, options = {}) {
|
|
43106
|
-
const { defineComponent, createLibrary, useStateField, useTriggerAction } = openui;
|
|
43107
|
-
const requiredMark = (required) => required ? /* @__PURE__ */ jsx("span", {
|
|
43108
|
-
className: "text-danger",
|
|
43109
|
-
children: " *"
|
|
43110
|
-
}) : null;
|
|
43111
|
-
const TextField = defineComponent({
|
|
43112
|
-
name: "TextField",
|
|
43113
|
-
description: "text input",
|
|
43114
|
-
props: z.object({
|
|
43115
|
-
name: z.string(),
|
|
43116
|
-
label: z.string().optional(),
|
|
43117
|
-
required: z.boolean().optional(),
|
|
43118
|
-
defaultValue: z.string().nullable().optional()
|
|
43119
|
-
}),
|
|
43120
|
-
component: function TextFieldRenderer({ props }) {
|
|
43121
|
-
const field = useStateField(props.name, props.defaultValue ?? "");
|
|
43122
|
-
return /* @__PURE__ */ jsxs("label", {
|
|
43123
|
-
className: "flex flex-col gap-1 text-sm text-ink",
|
|
43124
|
-
children: [/* @__PURE__ */ jsxs("span", { children: [props.label ?? props.name, requiredMark(props.required)] }), /* @__PURE__ */ jsx("input", {
|
|
43125
|
-
className: inputClass,
|
|
43126
|
-
value: String(field.value ?? ""),
|
|
43127
|
-
onChange: (e) => field.setValue(e.target.value)
|
|
43128
|
-
})]
|
|
43129
|
-
});
|
|
43130
|
-
}
|
|
43131
|
-
});
|
|
43132
|
-
const NumberField = defineComponent({
|
|
43133
|
-
name: "NumberField",
|
|
43134
|
-
description: "number input",
|
|
43135
|
-
props: z.object({
|
|
43136
|
-
name: z.string(),
|
|
43137
|
-
label: z.string().optional(),
|
|
43138
|
-
required: z.boolean().optional()
|
|
43139
|
-
}),
|
|
43140
|
-
component: function NumberFieldRenderer({ props }) {
|
|
43141
|
-
const field = useStateField(props.name, null);
|
|
43142
|
-
return /* @__PURE__ */ jsxs("label", {
|
|
43143
|
-
className: "flex flex-col gap-1 text-sm text-ink",
|
|
43144
|
-
children: [/* @__PURE__ */ jsxs("span", { children: [props.label ?? props.name, requiredMark(props.required)] }), /* @__PURE__ */ jsx("input", {
|
|
43145
|
-
type: "number",
|
|
43146
|
-
className: inputClass,
|
|
43147
|
-
value: field.value === void 0 || field.value === null ? "" : String(field.value),
|
|
43148
|
-
onChange: (e) => field.setValue(e.target.value === "" ? void 0 : Number(e.target.value))
|
|
43149
|
-
})]
|
|
43150
|
-
});
|
|
43151
|
-
}
|
|
43152
|
-
});
|
|
43153
|
-
const BooleanField = defineComponent({
|
|
43154
|
-
name: "BooleanField",
|
|
43155
|
-
description: "checkbox",
|
|
43156
|
-
props: z.object({
|
|
43157
|
-
name: z.string(),
|
|
43158
|
-
label: z.string().optional(),
|
|
43159
|
-
defaultValue: z.boolean().optional()
|
|
43160
|
-
}),
|
|
43161
|
-
component: function BooleanFieldRenderer({ props }) {
|
|
43162
|
-
const field = useStateField(props.name, props.defaultValue ?? false);
|
|
43163
|
-
return /* @__PURE__ */ jsxs("label", {
|
|
43164
|
-
className: "flex items-center gap-2 text-sm text-ink",
|
|
43165
|
-
children: [/* @__PURE__ */ jsx("input", {
|
|
43166
|
-
type: "checkbox",
|
|
43167
|
-
className: "size-4 accent-primary",
|
|
43168
|
-
checked: field.value === true,
|
|
43169
|
-
onChange: (e) => field.setValue(e.target.checked)
|
|
43170
|
-
}), /* @__PURE__ */ jsx("span", { children: props.label ?? props.name })]
|
|
43171
|
-
});
|
|
43172
|
-
}
|
|
43173
|
-
});
|
|
43174
|
-
const SelectField = defineComponent({
|
|
43175
|
-
name: "SelectField",
|
|
43176
|
-
description: "select input",
|
|
43177
|
-
props: z.object({
|
|
43178
|
-
name: z.string(),
|
|
43179
|
-
label: z.string().optional(),
|
|
43180
|
-
options: z.array(z.object({
|
|
43181
|
-
label: z.string(),
|
|
43182
|
-
value: z.unknown()
|
|
43183
|
-
}))
|
|
43184
|
-
}),
|
|
43185
|
-
component: function SelectFieldRenderer({ props }) {
|
|
43186
|
-
const field = useStateField(props.name, props.options[0]?.value ?? "");
|
|
43187
|
-
return /* @__PURE__ */ jsxs("label", {
|
|
43188
|
-
className: "flex flex-col gap-1 text-sm text-ink",
|
|
43189
|
-
children: [/* @__PURE__ */ jsx("span", { children: props.label ?? props.name }), /* @__PURE__ */ jsx("select", {
|
|
43190
|
-
className: inputClass,
|
|
43191
|
-
value: JSON.stringify(field.value ?? ""),
|
|
43192
|
-
onChange: (e) => field.setValue(JSON.parse(e.target.value)),
|
|
43193
|
-
children: props.options.map((option, i) => /* @__PURE__ */ jsx("option", {
|
|
43194
|
-
value: JSON.stringify(option.value),
|
|
43195
|
-
children: option.label
|
|
43196
|
-
}, i))
|
|
43197
|
-
})]
|
|
43198
|
-
});
|
|
43199
|
-
}
|
|
43200
|
-
});
|
|
43201
|
-
const SubmitButton = defineComponent({
|
|
43202
|
-
name: "SubmitButton",
|
|
43203
|
-
description: "submit button",
|
|
43204
|
-
props: z.object({
|
|
43205
|
-
label: z.string(),
|
|
43206
|
-
actionType: z.string(),
|
|
43207
|
-
requestId: z.string()
|
|
43208
|
-
}),
|
|
43209
|
-
component: function SubmitButtonRenderer({ props }) {
|
|
43210
|
-
const trigger = useTriggerAction();
|
|
43211
|
-
return /* @__PURE__ */ jsx(Button, {
|
|
43212
|
-
onClick: () => void trigger(props.label, void 0, {
|
|
43213
|
-
type: props.actionType,
|
|
43214
|
-
params: { id: props.requestId }
|
|
43215
|
-
}),
|
|
43216
|
-
children: props.label
|
|
43217
|
-
});
|
|
43218
|
-
}
|
|
43219
|
-
});
|
|
43220
|
-
const CancelButton = defineComponent({
|
|
43221
|
-
name: "CancelButton",
|
|
43222
|
-
description: "cancel button",
|
|
43223
|
-
props: z.object({
|
|
43224
|
-
label: z.string(),
|
|
43225
|
-
actionType: z.string(),
|
|
43226
|
-
requestId: z.string()
|
|
43227
|
-
}),
|
|
43228
|
-
component: function CancelButtonRenderer({ props }) {
|
|
43229
|
-
const trigger = useTriggerAction();
|
|
43230
|
-
return /* @__PURE__ */ jsx(Button, {
|
|
43231
|
-
variant: "secondary",
|
|
43232
|
-
onClick: () => void trigger(props.label, void 0, {
|
|
43233
|
-
type: props.actionType,
|
|
43234
|
-
params: { id: props.requestId }
|
|
43235
|
-
}),
|
|
43236
|
-
children: props.label
|
|
43237
|
-
});
|
|
43238
|
-
}
|
|
43239
|
-
});
|
|
43240
|
-
const Text = defineComponent({
|
|
43241
|
-
name: "Text",
|
|
43242
|
-
description: "plain display text",
|
|
43243
|
-
props: z.object({ content: z.string() }),
|
|
43244
|
-
component: function TextRenderer({ props }) {
|
|
43245
|
-
return /* @__PURE__ */ jsx("p", {
|
|
43246
|
-
className: "text-sm break-words text-muted",
|
|
43247
|
-
children: props.content
|
|
43248
|
-
});
|
|
43249
|
-
}
|
|
43250
|
-
});
|
|
43251
|
-
const components = [
|
|
43252
|
-
defineComponent({
|
|
43253
|
-
name: "Form",
|
|
43254
|
-
description: "form container",
|
|
43255
|
-
props: z.object({
|
|
43256
|
-
title: z.string().nullable().optional(),
|
|
43257
|
-
children: z.array(z.any()).optional()
|
|
43258
|
-
}),
|
|
43259
|
-
component: function FormRenderer({ props, renderNode }) {
|
|
43260
|
-
return /* @__PURE__ */ jsxs("form", {
|
|
43261
|
-
className: "flex flex-col gap-3",
|
|
43262
|
-
onSubmit: (e) => {
|
|
43263
|
-
e.preventDefault();
|
|
43264
|
-
},
|
|
43265
|
-
children: [props.title ? /* @__PURE__ */ jsx("h3", {
|
|
43266
|
-
className: "font-display text-sm font-semibold text-ink",
|
|
43267
|
-
children: props.title
|
|
43268
|
-
}) : null, (props.children ?? []).map((child, i) => /* @__PURE__ */ jsx("div", { children: renderNode(child) }, i))]
|
|
43269
|
-
});
|
|
43270
|
-
}
|
|
43271
|
-
}),
|
|
43272
|
-
Text,
|
|
43273
|
-
TextField,
|
|
43274
|
-
NumberField,
|
|
43275
|
-
BooleanField,
|
|
43276
|
-
SelectField,
|
|
43277
|
-
SubmitButton,
|
|
43278
|
-
CancelButton
|
|
43279
|
-
];
|
|
43280
|
-
if (options.onSurfaceAction) {
|
|
43281
|
-
const WebSkillSurfaceHost = defineComponent({
|
|
43282
|
-
name: "WebSkillSurfaceHost",
|
|
43283
|
-
description: "controlled WebSkill structured UI surface",
|
|
43284
|
-
props: z.object({ descriptor: z.any() }),
|
|
43285
|
-
component: function WebSkillSurfaceHostRenderer({ props }) {
|
|
43286
|
-
if (props.descriptor?.type !== "webskill-surface") return null;
|
|
43287
|
-
return /* @__PURE__ */ jsx("div", {
|
|
43288
|
-
"data-webskill-provenance": props.descriptor.provenance,
|
|
43289
|
-
children: /* @__PURE__ */ jsx(UiSurfaceSnapshotList, {
|
|
43290
|
-
snapshots: [props.descriptor.snapshot],
|
|
43291
|
-
...options.registry ? { registry: options.registry } : {},
|
|
43292
|
-
onAction: options.onSurfaceAction,
|
|
43293
|
-
...options.drafts ? { drafts: options.drafts } : {},
|
|
43294
|
-
...options.onSurfaceDraftChange ? { onDraftChange: options.onSurfaceDraftChange } : {}
|
|
43295
|
-
})
|
|
43296
|
-
});
|
|
43297
|
-
}
|
|
43298
|
-
});
|
|
43299
|
-
components.push(WebSkillSurfaceHost);
|
|
43300
|
-
}
|
|
43301
|
-
return createLibrary({
|
|
43302
|
-
components,
|
|
43303
|
-
root: options.root ?? "Form"
|
|
43304
|
-
});
|
|
43305
|
-
}
|
|
43306
|
-
/**
|
|
43307
|
-
* openui 档交互视图:订阅 OpenUiChannel(core 产出 openui-lang 文本),动态加载
|
|
43308
|
-
* optional peer @openuidev/react-lang 的 Renderer 渲染;动作事件回传 channel.handleAction。
|
|
43309
|
-
* 模块加载失败 → channel.fail(桥粘性降级 native,InteractionCard 接管)。
|
|
43310
|
-
*/
|
|
43311
|
-
function OpenUiInteraction({ channel }) {
|
|
43312
|
-
const session = useSyncExternalStore(channel.subscribe, () => channel.current);
|
|
43313
|
-
const [ready, setReady] = useState();
|
|
43314
|
-
useEffect(() => {
|
|
43315
|
-
channel.attach();
|
|
43316
|
-
return () => channel.detach();
|
|
43317
|
-
}, [channel]);
|
|
43318
|
-
useEffect(() => {
|
|
43319
|
-
let cancelled = false;
|
|
43320
|
-
(async () => {
|
|
43321
|
-
try {
|
|
43322
|
-
const { openui, z } = await loadOpenUiPeers();
|
|
43323
|
-
if (!cancelled) setReady({
|
|
43324
|
-
Renderer: openui.Renderer,
|
|
43325
|
-
library: buildOpenUiLibrary(openui, z)
|
|
43326
|
-
});
|
|
43327
|
-
} catch (e) {
|
|
43328
|
-
if (!cancelled) channel.fail(messageOf(e));
|
|
43329
|
-
}
|
|
43330
|
-
})();
|
|
43331
|
-
return () => {
|
|
43332
|
-
cancelled = true;
|
|
43333
|
-
};
|
|
43334
|
-
}, [channel]);
|
|
43335
|
-
if (!session || !ready) return null;
|
|
43336
|
-
const { Renderer, library } = ready;
|
|
43337
|
-
return /* @__PURE__ */ jsx("div", {
|
|
43338
|
-
"data-testid": "openui-interaction",
|
|
43339
|
-
className: "rounded-card border border-border bg-surface px-4 py-4 shadow-card",
|
|
43340
|
-
children: /* @__PURE__ */ jsx(Renderer, {
|
|
43341
|
-
response: session.lang,
|
|
43342
|
-
library,
|
|
43343
|
-
onAction: (action) => channel.handleAction(action)
|
|
43344
|
-
})
|
|
43345
|
-
});
|
|
43346
|
-
}
|
|
43347
|
-
|
|
43348
42867
|
//#endregion
|
|
43349
42868
|
//#region src/react/OpenUiSurfaceHost.tsx
|
|
43350
|
-
/** Renders persisted
|
|
43351
|
-
function OpenUiSurfaceSnapshotHost({ snapshots,
|
|
43352
|
-
const [ready, setReady] = useState();
|
|
42869
|
+
/** Renders persisted UI spec snapshots through the OpenUI extension without a live bridge. @experimental */
|
|
42870
|
+
function OpenUiSurfaceSnapshotHost({ snapshots, onAction }) {
|
|
42871
|
+
const [ready, setReady] = useState(false);
|
|
43353
42872
|
const [fallbackReason, setFallbackReason] = useState();
|
|
43354
|
-
const emitAction = useEffectEvent((event) => onAction?.(event));
|
|
43355
42873
|
useEffect(() => {
|
|
43356
42874
|
let cancelled = false;
|
|
43357
42875
|
(async () => {
|
|
43358
42876
|
try {
|
|
43359
|
-
|
|
43360
|
-
if (!cancelled) setReady(
|
|
43361
|
-
Renderer: openui.Renderer,
|
|
43362
|
-
library: buildOpenUiLibrary(openui, z, {
|
|
43363
|
-
root: "WebSkillSurfaceHost",
|
|
43364
|
-
...registry ? { registry } : {},
|
|
43365
|
-
onSurfaceAction: emitAction,
|
|
43366
|
-
...drafts ? { drafts } : {},
|
|
43367
|
-
...onDraftChange ? { onSurfaceDraftChange: onDraftChange } : {}
|
|
43368
|
-
})
|
|
43369
|
-
});
|
|
42877
|
+
await loadOpenUiPeers();
|
|
42878
|
+
if (!cancelled) setReady(true);
|
|
43370
42879
|
} catch (error) {
|
|
43371
42880
|
const reason = error?.code === "UI_UNAVAILABLE" ? "openui-peer-missing" : "openui-load-failed";
|
|
43372
42881
|
if (reason !== "openui-peer-missing") console.warn("[webskill] OpenUI renderer unavailable, falling back to native", { error });
|
|
@@ -43376,63 +42885,40 @@ function OpenUiSurfaceSnapshotHost({ snapshots, registry, onAction, drafts, onDr
|
|
|
43376
42885
|
return () => {
|
|
43377
42886
|
cancelled = true;
|
|
43378
42887
|
};
|
|
43379
|
-
}, [
|
|
42888
|
+
}, []);
|
|
43380
42889
|
if (snapshots.length === 0) return null;
|
|
43381
|
-
|
|
43382
|
-
const legacy = snapshots.filter((snapshot) => !isUiSpecSurface(snapshot.surface));
|
|
43383
|
-
const specNodes = specs.map((snapshot) => {
|
|
43384
|
-
const surface = snapshot.surface;
|
|
43385
|
-
return /* @__PURE__ */ jsx(OpenUiSpecSurface, { spec: surface.props.spec }, surface.id);
|
|
43386
|
-
});
|
|
43387
|
-
if (!ready) return /* @__PURE__ */ jsxs("div", {
|
|
42890
|
+
return /* @__PURE__ */ jsx("div", {
|
|
43388
42891
|
"data-testid": "openui-surface-host",
|
|
43389
|
-
"data-renderer": "native-fallback",
|
|
42892
|
+
"data-renderer": ready ? "openui" : "native-fallback",
|
|
43390
42893
|
...fallbackReason ? { "data-fallback-reason": fallbackReason } : {},
|
|
43391
|
-
children:
|
|
43392
|
-
|
|
43393
|
-
|
|
43394
|
-
|
|
43395
|
-
...
|
|
43396
|
-
|
|
43397
|
-
}) : null]
|
|
43398
|
-
});
|
|
43399
|
-
const { Renderer, library } = ready;
|
|
43400
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
43401
|
-
"data-testid": "openui-surface-host",
|
|
43402
|
-
"data-renderer": "openui",
|
|
43403
|
-
children: [specNodes, legacy.map((snapshot) => /* @__PURE__ */ jsx(Renderer, {
|
|
43404
|
-
response: toOpenUiSurfaceLang(snapshot),
|
|
43405
|
-
library
|
|
43406
|
-
}, snapshot.surface.id))]
|
|
42894
|
+
children: snapshots.map((snapshot) => /* @__PURE__ */ jsx(OpenUiSpecSurface, {
|
|
42895
|
+
spec: snapshot.node,
|
|
42896
|
+
surfaceId: snapshot.id,
|
|
42897
|
+
actions: snapshot.actions ?? [],
|
|
42898
|
+
...onAction ? { onAction } : {}
|
|
42899
|
+
}, snapshot.id))
|
|
43407
42900
|
});
|
|
43408
42901
|
}
|
|
43409
|
-
/** Renders
|
|
43410
|
-
function OpenUiSurfaceHost({ bridge, runId
|
|
42902
|
+
/** Renders WebSkill UI spec snapshots through an OpenUI library extension. @experimental */
|
|
42903
|
+
function OpenUiSurfaceHost({ bridge, runId }) {
|
|
43411
42904
|
const snapshots = useSyncExternalStore(bridge.subscribe, () => bridge.surfaceSnapshots);
|
|
43412
42905
|
const visibleSnapshots = runId === void 0 ? snapshots : snapshots.filter((snapshot) => snapshot.runId === runId);
|
|
43413
42906
|
const handleAction = (event) => {
|
|
43414
|
-
const
|
|
43415
|
-
|
|
43416
|
-
|
|
43417
|
-
});
|
|
43418
|
-
if (!action?.runId || !action.nonce) return;
|
|
42907
|
+
const snapshot = visibleSnapshots.find((candidate) => candidate.id === event.surfaceId);
|
|
42908
|
+
const capability = snapshot?.actions?.find((candidate) => candidate.id === event.actionId);
|
|
42909
|
+
if (!snapshot?.runId || !capability?.nonce) return;
|
|
43419
42910
|
bridge.resolveSurfaceAction({
|
|
43420
|
-
runId:
|
|
43421
|
-
surfaceId:
|
|
43422
|
-
actionId:
|
|
43423
|
-
intent:
|
|
43424
|
-
nonce:
|
|
43425
|
-
...
|
|
43426
|
-
...action.cancelled ? { cancelled: true } : {}
|
|
42911
|
+
runId: snapshot.runId,
|
|
42912
|
+
surfaceId: event.surfaceId,
|
|
42913
|
+
actionId: event.actionId,
|
|
42914
|
+
intent: event.intent,
|
|
42915
|
+
nonce: capability.nonce,
|
|
42916
|
+
...event.value ? { value: event.value } : {}
|
|
43427
42917
|
});
|
|
43428
42918
|
};
|
|
43429
|
-
const drafts = runId ? bridge.surfaceDrafts(runId) : {};
|
|
43430
42919
|
return /* @__PURE__ */ jsx(OpenUiSurfaceSnapshotHost, {
|
|
43431
42920
|
snapshots: visibleSnapshots,
|
|
43432
|
-
|
|
43433
|
-
onAction: handleAction,
|
|
43434
|
-
drafts,
|
|
43435
|
-
onDraftChange: (event) => bridge.setSurfaceDraft(event.runId, event.surfaceId, event.value)
|
|
42921
|
+
onAction: handleAction
|
|
43436
42922
|
});
|
|
43437
42923
|
}
|
|
43438
42924
|
|
|
@@ -53510,6 +52996,7 @@ function Block({ block, runId, onDownload }) {
|
|
|
53510
52996
|
/**
|
|
53511
52997
|
* 结果块列表(AnimatePresence 逐块入场):markdown / json / table / chart / image / file。
|
|
53512
52998
|
* 历史消息(ChatMessage.blocks)与当前 run(ResultBlocksPro)共用的渲染形态。
|
|
52999
|
+
* @stable
|
|
53513
53000
|
*/
|
|
53514
53001
|
function ResultBlockList({ blocks, runId, onDownload }) {
|
|
53515
53002
|
return /* @__PURE__ */ jsx(AnimatePresence, {
|
|
@@ -53531,6 +53018,7 @@ function ResultBlockList({ blocks, runId, onDownload }) {
|
|
|
53531
53018
|
/**
|
|
53532
53019
|
* run 完成结果块渐进挂载(AnimatePresence 逐块入场):
|
|
53533
53020
|
* markdown / json / table / chart / image / file + artifact 下载卡。
|
|
53021
|
+
* @stable
|
|
53534
53022
|
*/
|
|
53535
53023
|
function ResultBlocksPro({ bridge, activeRunId, onDownload }) {
|
|
53536
53024
|
const t = useT();
|
|
@@ -53573,7 +53061,7 @@ function ResultBlocksPro({ bridge, activeRunId, onDownload }) {
|
|
|
53573
53061
|
|
|
53574
53062
|
//#endregion
|
|
53575
53063
|
//#region src/react/SkillBadges.tsx
|
|
53576
|
-
/** 消息底部展示该 run 激活的技能名徽章(无技能不渲染) */
|
|
53064
|
+
/** 消息底部展示该 run 激活的技能名徽章(无技能不渲染) @stable */
|
|
53577
53065
|
function SkillBadges({ skills }) {
|
|
53578
53066
|
const t = useT();
|
|
53579
53067
|
if (skills.length === 0) return null;
|
|
@@ -53599,56 +53087,42 @@ function SkillBadges({ skills }) {
|
|
|
53599
53087
|
|
|
53600
53088
|
//#endregion
|
|
53601
53089
|
//#region src/react/VercelSurfaceHost.tsx
|
|
53602
|
-
/** Renders persisted
|
|
53603
|
-
function VercelSurfaceSnapshotHost({ snapshots,
|
|
53604
|
-
|
|
53605
|
-
|
|
53606
|
-
const specs = dataParts.filter((part) => isUiSpecSurface(part.data.snapshot.surface));
|
|
53607
|
-
const legacy = dataParts.filter((part) => !isUiSpecSurface(part.data.snapshot.surface));
|
|
53608
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
53090
|
+
/** Renders persisted UI spec snapshots through the json-render registry without a live bridge. @experimental */
|
|
53091
|
+
function VercelSurfaceSnapshotHost({ snapshots, onAction }) {
|
|
53092
|
+
if (snapshots.length === 0) return null;
|
|
53093
|
+
return /* @__PURE__ */ jsx("div", {
|
|
53609
53094
|
"data-testid": "vercel-surface-snapshot-host",
|
|
53610
|
-
"data-surface-parts":
|
|
53611
|
-
children:
|
|
53612
|
-
|
|
53613
|
-
|
|
53614
|
-
|
|
53615
|
-
|
|
53616
|
-
|
|
53617
|
-
...onAction ? { onAction } : {},
|
|
53618
|
-
...drafts ? { drafts } : {},
|
|
53619
|
-
...onDraftChange ? { onDraftChange } : {}
|
|
53620
|
-
}) : null]
|
|
53095
|
+
"data-surface-parts": snapshots.length,
|
|
53096
|
+
children: snapshots.map((snapshot) => /* @__PURE__ */ jsx(JsonRenderSpecSurface, {
|
|
53097
|
+
spec: snapshot.node,
|
|
53098
|
+
surfaceId: snapshot.id,
|
|
53099
|
+
actions: snapshot.actions ?? [],
|
|
53100
|
+
...onAction ? { onAction } : {}
|
|
53101
|
+
}, snapshot.id))
|
|
53621
53102
|
});
|
|
53622
53103
|
}
|
|
53623
|
-
/** Consumes
|
|
53624
|
-
function VercelSurfaceHost({ bridge, runId
|
|
53104
|
+
/** Consumes WebSkill UI spec snapshots with a json-render surface renderer. @experimental */
|
|
53105
|
+
function VercelSurfaceHost({ bridge, runId }) {
|
|
53625
53106
|
const visibleSnapshots = useSyncExternalStore(bridge.subscribe, () => bridge.surfaceSnapshots).filter((snapshot) => runId === void 0 || snapshot.runId === runId);
|
|
53107
|
+
if (visibleSnapshots.length === 0) return null;
|
|
53626
53108
|
const handleAction = (event) => {
|
|
53627
|
-
const
|
|
53628
|
-
|
|
53629
|
-
|
|
53630
|
-
});
|
|
53631
|
-
if (!action?.runId || !action.nonce) return;
|
|
53109
|
+
const snapshot = visibleSnapshots.find((candidate) => candidate.id === event.surfaceId);
|
|
53110
|
+
const capability = snapshot?.actions?.find((candidate) => candidate.id === event.actionId);
|
|
53111
|
+
if (!snapshot?.runId || !capability?.nonce) return;
|
|
53632
53112
|
bridge.resolveSurfaceAction({
|
|
53633
|
-
runId:
|
|
53634
|
-
surfaceId:
|
|
53635
|
-
actionId:
|
|
53636
|
-
intent:
|
|
53637
|
-
nonce:
|
|
53638
|
-
...
|
|
53639
|
-
...action.cancelled ? { cancelled: true } : {}
|
|
53113
|
+
runId: snapshot.runId,
|
|
53114
|
+
surfaceId: event.surfaceId,
|
|
53115
|
+
actionId: event.actionId,
|
|
53116
|
+
intent: event.intent,
|
|
53117
|
+
nonce: capability.nonce,
|
|
53118
|
+
...event.value ? { value: event.value } : {}
|
|
53640
53119
|
});
|
|
53641
53120
|
};
|
|
53642
|
-
if (visibleSnapshots.length === 0) return null;
|
|
53643
|
-
const drafts = runId ? bridge.surfaceDrafts(runId) : {};
|
|
53644
53121
|
return /* @__PURE__ */ jsx("div", {
|
|
53645
53122
|
"data-testid": "vercel-surface-host",
|
|
53646
53123
|
children: /* @__PURE__ */ jsx(VercelSurfaceSnapshotHost, {
|
|
53647
53124
|
snapshots: visibleSnapshots,
|
|
53648
|
-
|
|
53649
|
-
onAction: handleAction,
|
|
53650
|
-
drafts,
|
|
53651
|
-
onDraftChange: (event) => bridge.setSurfaceDraft(event.runId, event.surfaceId, event.value)
|
|
53125
|
+
onAction: handleAction
|
|
53652
53126
|
})
|
|
53653
53127
|
});
|
|
53654
53128
|
}
|
|
@@ -53660,23 +53134,30 @@ function HistoricalSurfaces({ snapshots, renderer, registry }) {
|
|
|
53660
53134
|
snapshots,
|
|
53661
53135
|
...registry ? { registry } : {}
|
|
53662
53136
|
});
|
|
53663
|
-
if (renderer === "openui") return /* @__PURE__ */ jsx(OpenUiSurfaceSnapshotHost, {
|
|
53664
|
-
|
|
53665
|
-
...registry ? { registry } : {}
|
|
53666
|
-
});
|
|
53667
|
-
if (renderer === "vercel") return /* @__PURE__ */ jsx(VercelSurfaceSnapshotHost, {
|
|
53668
|
-
snapshots,
|
|
53669
|
-
...registry ? { registry } : {}
|
|
53670
|
-
});
|
|
53137
|
+
if (renderer === "openui") return /* @__PURE__ */ jsx(OpenUiSurfaceSnapshotHost, { snapshots });
|
|
53138
|
+
if (renderer === "vercel") return /* @__PURE__ */ jsx(VercelSurfaceSnapshotHost, { snapshots });
|
|
53671
53139
|
return /* @__PURE__ */ jsx(UiSurfaceSnapshotList, {
|
|
53672
53140
|
snapshots,
|
|
53673
53141
|
...registry ? { registry } : {}
|
|
53674
53142
|
});
|
|
53675
53143
|
}
|
|
53144
|
+
/**
|
|
53145
|
+
* 旧版本会话里的 surface 条目是六类 `{ surface: { kind } }`,没有节点树,任何渲染器都吃不下。
|
|
53146
|
+
* 判定只看渲染入口是否成立,不做深校验:深校验属于产出侧,历史消息只决定「渲染还是占位」。
|
|
53147
|
+
*/
|
|
53148
|
+
function isRenderableSpec(snapshot) {
|
|
53149
|
+
if (typeof snapshot !== "object" || snapshot === null) return false;
|
|
53150
|
+
const node = snapshot.node;
|
|
53151
|
+
if (typeof node !== "object" || node === null) return false;
|
|
53152
|
+
return typeof node.component === "string";
|
|
53153
|
+
}
|
|
53676
53154
|
/** WebSkill domain content rendered beneath a Base message without choosing its chat layout. */
|
|
53677
53155
|
function WebSkillMessageExtensions({ message, onDownload, surfaceRegistry, renderer }) {
|
|
53156
|
+
const t = useT();
|
|
53678
53157
|
if (message.role === "user") return null;
|
|
53679
53158
|
const blocks = message.blocks?.filter((block) => block.type !== "markdown" || block.text.trim() !== message.text.trim());
|
|
53159
|
+
const surfaces = message.surfaces ?? [];
|
|
53160
|
+
const renderable = surfaces.filter(isRenderableSpec);
|
|
53680
53161
|
return /* @__PURE__ */ jsxs("div", {
|
|
53681
53162
|
className: "min-w-0 w-full",
|
|
53682
53163
|
children: [
|
|
@@ -53685,11 +53166,16 @@ function WebSkillMessageExtensions({ message, onDownload, surfaceRegistry, rende
|
|
|
53685
53166
|
runId: message.runId ?? "",
|
|
53686
53167
|
...onDownload ? { onDownload } : {}
|
|
53687
53168
|
}) : null,
|
|
53688
|
-
|
|
53689
|
-
snapshots:
|
|
53169
|
+
renderable.length > 0 ? /* @__PURE__ */ jsx(HistoricalSurfaces, {
|
|
53170
|
+
snapshots: renderable,
|
|
53690
53171
|
...renderer ? { renderer } : {},
|
|
53691
53172
|
...surfaceRegistry ? { registry: surfaceRegistry } : {}
|
|
53692
53173
|
}) : null,
|
|
53174
|
+
renderable.length < surfaces.length ? /* @__PURE__ */ jsx("p", {
|
|
53175
|
+
"data-testid": "legacy-surface-placeholder",
|
|
53176
|
+
className: "my-2 rounded-lg border border-border bg-canvas px-3 py-2 text-xs text-muted",
|
|
53177
|
+
children: t("surface.legacy.placeholder")
|
|
53178
|
+
}) : null,
|
|
53693
53179
|
/* @__PURE__ */ jsx(SkillBadges, { skills: message.activeSkillNames ?? [] })
|
|
53694
53180
|
]
|
|
53695
53181
|
});
|
|
@@ -53906,23 +53392,35 @@ const start = (runId, at) => ({
|
|
|
53906
53392
|
text: "",
|
|
53907
53393
|
chunks: 0
|
|
53908
53394
|
});
|
|
53909
|
-
function appendPhase(live,
|
|
53910
|
-
const display = DISPLAY_PHASE[phase];
|
|
53395
|
+
function appendPhase(live, event) {
|
|
53396
|
+
const display = DISPLAY_PHASE[event.phase];
|
|
53911
53397
|
const last = live.phases.at(-1);
|
|
53912
53398
|
if (last?.phase === display) return live;
|
|
53913
53399
|
const closed = last ? [...live.phases.slice(0, -1), {
|
|
53914
53400
|
...last,
|
|
53915
|
-
endedAt: at
|
|
53401
|
+
endedAt: event.at
|
|
53916
53402
|
}] : [];
|
|
53403
|
+
const note = phaseNote(event);
|
|
53917
53404
|
return {
|
|
53918
53405
|
...live,
|
|
53919
53406
|
phases: [...closed, {
|
|
53920
53407
|
phase: display,
|
|
53921
|
-
at,
|
|
53922
|
-
...
|
|
53408
|
+
at: event.at,
|
|
53409
|
+
...note ? { note } : {}
|
|
53923
53410
|
}]
|
|
53924
53411
|
};
|
|
53925
53412
|
}
|
|
53413
|
+
/** 相位摘要:唯一读 `data` 的地方,此处事件还带着 `phase` 判别,下游不必再猜键名 */
|
|
53414
|
+
function phaseNote(event) {
|
|
53415
|
+
switch (event.phase) {
|
|
53416
|
+
case "route": return event.data.strategy;
|
|
53417
|
+
case "activate": return event.data.skillName;
|
|
53418
|
+
case "interact": return event.data.kind === "interaction" ? event.data.interactionType : event.data.actionId;
|
|
53419
|
+
case "complete":
|
|
53420
|
+
case "fail": return event.data.reason;
|
|
53421
|
+
default: return;
|
|
53422
|
+
}
|
|
53423
|
+
}
|
|
53926
53424
|
/**
|
|
53927
53425
|
* ChatEvent → 进行中 run 的 part 累积器。返回 undefined 表示当前没有进行中的 run。
|
|
53928
53426
|
* 只处理属于当前 runId 的事件,跨 run 的迟到事件被忽略。
|
|
@@ -53936,7 +53434,7 @@ function reduceLiveRun(live, event, at) {
|
|
|
53936
53434
|
}
|
|
53937
53435
|
if (!live || !("runId" in event) || event.runId !== live.runId) return live;
|
|
53938
53436
|
switch (event.type) {
|
|
53939
|
-
case "lifecycle": return appendPhase(live, event
|
|
53437
|
+
case "lifecycle": return appendPhase(live, event);
|
|
53940
53438
|
case "skill-activated": return {
|
|
53941
53439
|
...live,
|
|
53942
53440
|
skills: event.skills
|
|
@@ -53975,7 +53473,7 @@ function reduceLiveRun(live, event, at) {
|
|
|
53975
53473
|
|
|
53976
53474
|
//#endregion
|
|
53977
53475
|
//#region src/react/ErrorCard.tsx
|
|
53978
|
-
/** 结构化错误卡:错误码徽章 + 描述 + 建议(engine error 事件 / 失败 run) */
|
|
53476
|
+
/** 结构化错误卡:错误码徽章 + 描述 + 建议(engine error 事件 / 失败 run) @stable */
|
|
53979
53477
|
function ErrorCard({ code, message, onDismiss }) {
|
|
53980
53478
|
const t = useT();
|
|
53981
53479
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -54029,9 +53527,42 @@ function ErrorCard({ code, message, onDismiss }) {
|
|
|
54029
53527
|
});
|
|
54030
53528
|
}
|
|
54031
53529
|
|
|
53530
|
+
//#endregion
|
|
53531
|
+
//#region src/react/interactionLabels.ts
|
|
53532
|
+
/**
|
|
53533
|
+
* 交互卡的界面文案:生成器(`@webskill/ui`)与语言无关,本地化由持有字典的宿主注入。
|
|
53534
|
+
* 四档共用本函数,切换渲染档不会让同一个请求出现两套文案。
|
|
53535
|
+
*/
|
|
53536
|
+
function interactionLabels(request, t) {
|
|
53537
|
+
return {
|
|
53538
|
+
title: request.type === "form" && request.title ? request.title : t(`interaction.${request.type}.title`),
|
|
53539
|
+
submitLabel: t(request.type === "authorize" ? "interaction.allow" : request.type === "confirm" ? "interaction.confirm" : "interaction.submit"),
|
|
53540
|
+
cancelLabel: t(request.type === "authorize" ? "interaction.deny" : "interaction.cancel")
|
|
53541
|
+
};
|
|
53542
|
+
}
|
|
53543
|
+
|
|
54032
53544
|
//#endregion
|
|
54033
53545
|
//#region src/react/InteractionCard.tsx
|
|
54034
|
-
/**
|
|
53546
|
+
/** 交互表单的两个动作:与 surface 侧共用 catalog 的 submit / cancel 语义 */
|
|
53547
|
+
const INTERACTION_ACTIONS$1 = [{
|
|
53548
|
+
id: "submit",
|
|
53549
|
+
intent: "submit"
|
|
53550
|
+
}, {
|
|
53551
|
+
id: "cancel",
|
|
53552
|
+
intent: "cancel"
|
|
53553
|
+
}];
|
|
53554
|
+
const kindIcons = {
|
|
53555
|
+
ask: MessageCircleQuestionMark,
|
|
53556
|
+
confirm: CircleQuestionMark,
|
|
53557
|
+
form: ClipboardList,
|
|
53558
|
+
select: ListChecks,
|
|
53559
|
+
authorize: ShieldAlert
|
|
53560
|
+
};
|
|
53561
|
+
/**
|
|
53562
|
+
* 订阅 bridge.pending 渲染五类交互卡(native 档;其它档降级后也由它接管)。
|
|
53563
|
+
* 表单本体走 `NativeSpecSurface`——与 native 档 surface 侧同一个渲染入口。
|
|
53564
|
+
* @stable
|
|
53565
|
+
*/
|
|
54035
53566
|
function InteractionCard({ bridge }) {
|
|
54036
53567
|
const pending = useSyncExternalStore(bridge.subscribe, () => bridge.pending);
|
|
54037
53568
|
if (!pending) return null;
|
|
@@ -54040,102 +53571,25 @@ function InteractionCard({ bridge }) {
|
|
|
54040
53571
|
bridge
|
|
54041
53572
|
}, pending.id);
|
|
54042
53573
|
}
|
|
54043
|
-
/** 单个表单控件(ask/form 用;data-webskill-control 契约与 collectValues 对齐) */
|
|
54044
|
-
function Field({ control, invalid }) {
|
|
54045
|
-
const t = useT();
|
|
54046
|
-
const id = `webskill-field-${control.name}`;
|
|
54047
|
-
const label = /* @__PURE__ */ jsxs(Fragment$1, { children: [control.label, control.required ? /* @__PURE__ */ jsx("span", {
|
|
54048
|
-
className: "text-danger",
|
|
54049
|
-
children: " *"
|
|
54050
|
-
}) : null] });
|
|
54051
|
-
let element;
|
|
54052
|
-
switch (control.control) {
|
|
54053
|
-
case "boolean":
|
|
54054
|
-
element = /* @__PURE__ */ jsx(Checkbox, {
|
|
54055
|
-
id,
|
|
54056
|
-
"data-webskill-control": control.name,
|
|
54057
|
-
defaultChecked: control.defaultValue === true ? true : void 0,
|
|
54058
|
-
invalid
|
|
54059
|
-
});
|
|
54060
|
-
break;
|
|
54061
|
-
case "select":
|
|
54062
|
-
element = /* @__PURE__ */ jsx("select", {
|
|
54063
|
-
id,
|
|
54064
|
-
"data-webskill-control": control.name,
|
|
54065
|
-
"aria-invalid": invalid || void 0,
|
|
54066
|
-
className: "h-9 w-full rounded-md border border-input bg-surface px-3 text-sm text-ink shadow-xs outline-none transition-colors focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/20",
|
|
54067
|
-
...control.defaultValue !== void 0 ? { defaultValue: JSON.stringify(control.defaultValue) } : {},
|
|
54068
|
-
children: (control.options ?? []).map((option, i) => /* @__PURE__ */ jsx("option", {
|
|
54069
|
-
value: JSON.stringify(option.value),
|
|
54070
|
-
children: option.label
|
|
54071
|
-
}, i))
|
|
54072
|
-
});
|
|
54073
|
-
break;
|
|
54074
|
-
case "textarea":
|
|
54075
|
-
element = /* @__PURE__ */ jsx(Textarea, {
|
|
54076
|
-
id,
|
|
54077
|
-
"data-webskill-control": control.name,
|
|
54078
|
-
invalid,
|
|
54079
|
-
rows: 3,
|
|
54080
|
-
defaultValue: control.defaultValue !== void 0 ? String(control.defaultValue) : ""
|
|
54081
|
-
});
|
|
54082
|
-
break;
|
|
54083
|
-
default: element = /* @__PURE__ */ jsx(Input, {
|
|
54084
|
-
type: control.control === "number" ? "number" : "text",
|
|
54085
|
-
id,
|
|
54086
|
-
"data-webskill-control": control.name,
|
|
54087
|
-
invalid,
|
|
54088
|
-
defaultValue: control.defaultValue !== void 0 ? String(control.defaultValue) : ""
|
|
54089
|
-
});
|
|
54090
|
-
}
|
|
54091
|
-
return /* @__PURE__ */ jsx(FormField, {
|
|
54092
|
-
label,
|
|
54093
|
-
htmlFor: id,
|
|
54094
|
-
...control.description ? { description: control.description } : {},
|
|
54095
|
-
...invalid ? { error: t("interaction.required") } : {},
|
|
54096
|
-
children: element
|
|
54097
|
-
});
|
|
54098
|
-
}
|
|
54099
|
-
const kindIcons = {
|
|
54100
|
-
ask: MessageCircleQuestionMark,
|
|
54101
|
-
confirm: CircleQuestionMark,
|
|
54102
|
-
form: ClipboardList,
|
|
54103
|
-
select: ListChecks,
|
|
54104
|
-
authorize: ShieldAlert
|
|
54105
|
-
};
|
|
54106
53574
|
function ActiveInteractionCard({ request, bridge }) {
|
|
54107
53575
|
const t = useT();
|
|
54108
|
-
const
|
|
54109
|
-
const
|
|
54110
|
-
const
|
|
54111
|
-
const
|
|
54112
|
-
|
|
54113
|
-
|
|
54114
|
-
|
|
54115
|
-
|
|
54116
|
-
|
|
54117
|
-
cancelled: true
|
|
54118
|
-
});
|
|
54119
|
-
const submitForm = () => {
|
|
54120
|
-
if (!formRef.current) return;
|
|
54121
|
-
const { values, missingRequired } = collectValues(model.controls, formRef.current);
|
|
54122
|
-
if (missingRequired.length > 0) {
|
|
54123
|
-
setInvalid(missingRequired);
|
|
53576
|
+
const spec = interactionToUiSpec(request, interactionLabels(request, t));
|
|
53577
|
+
const isAuthorize = request.type === "authorize";
|
|
53578
|
+
const Icon = kindIcons[request.type];
|
|
53579
|
+
const handleAction = (event) => {
|
|
53580
|
+
if (event.intent !== "submit") {
|
|
53581
|
+
bridge.resolve({
|
|
53582
|
+
id: request.id,
|
|
53583
|
+
cancelled: true
|
|
53584
|
+
});
|
|
54124
53585
|
return;
|
|
54125
53586
|
}
|
|
54126
|
-
|
|
54127
|
-
|
|
54128
|
-
|
|
54129
|
-
|
|
54130
|
-
|
|
54131
|
-
|
|
54132
|
-
t,
|
|
54133
|
-
formRef,
|
|
54134
|
-
invalid,
|
|
54135
|
-
submitForm,
|
|
54136
|
-
resolve,
|
|
54137
|
-
cancel
|
|
54138
|
-
});
|
|
53587
|
+
const value = shapeInteractionValue(interactionToFormModel(request), event.value ?? {});
|
|
53588
|
+
bridge.resolve({
|
|
53589
|
+
id: request.id,
|
|
53590
|
+
value
|
|
53591
|
+
});
|
|
53592
|
+
};
|
|
54139
53593
|
return /* @__PURE__ */ jsxs(motion.div, {
|
|
54140
53594
|
...fadeInUp,
|
|
54141
53595
|
className: `rounded-card border shadow-card ${isAuthorize ? "border-warning/50 bg-warning-soft" : "border-border bg-surface"}`,
|
|
@@ -54147,132 +53601,51 @@ function ActiveInteractionCard({ request, bridge }) {
|
|
|
54147
53601
|
className: "size-4",
|
|
54148
53602
|
"aria-hidden": true
|
|
54149
53603
|
})
|
|
54150
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
54151
|
-
className: "min-w-0 flex-1",
|
|
54152
|
-
children: [
|
|
54153
|
-
|
|
54154
|
-
|
|
54155
|
-
|
|
54156
|
-
|
|
54157
|
-
|
|
54158
|
-
|
|
54159
|
-
|
|
53604
|
+
}), request.type === "authorize" ? /* @__PURE__ */ jsxs("div", {
|
|
53605
|
+
className: "flex min-w-0 flex-1 flex-col gap-2",
|
|
53606
|
+
children: [
|
|
53607
|
+
/* @__PURE__ */ jsxs("div", {
|
|
53608
|
+
className: "flex items-center gap-2",
|
|
53609
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
53610
|
+
className: "text-xs font-medium text-muted",
|
|
53611
|
+
children: t("interaction.authorize.capability")
|
|
53612
|
+
}), /* @__PURE__ */ jsx(Badge, {
|
|
53613
|
+
tone: "warning",
|
|
53614
|
+
children: request.capability
|
|
53615
|
+
})]
|
|
53616
|
+
}),
|
|
53617
|
+
/* @__PURE__ */ jsx("p", {
|
|
53618
|
+
className: "text-xs text-muted",
|
|
53619
|
+
children: t("interaction.authorize.description")
|
|
53620
|
+
}),
|
|
53621
|
+
request.details !== void 0 ? /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
53622
|
+
className: "mb-1 text-xs font-medium text-muted",
|
|
53623
|
+
children: t("interaction.authorize.details")
|
|
53624
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
53625
|
+
className: "max-h-40 overflow-auto rounded-lg border border-border bg-canvas p-3 font-mono text-xs text-ink",
|
|
53626
|
+
children: JSON.stringify(request.details, null, 2)
|
|
53627
|
+
})] }) : null
|
|
53628
|
+
]
|
|
53629
|
+
}) : null]
|
|
54160
53630
|
}), /* @__PURE__ */ jsx("div", {
|
|
54161
53631
|
className: "px-4 py-4",
|
|
54162
|
-
children:
|
|
54163
|
-
|
|
54164
|
-
|
|
54165
|
-
|
|
54166
|
-
|
|
54167
|
-
|
|
54168
|
-
switch (model.kind) {
|
|
54169
|
-
case "ask": return t("interaction.ask.title");
|
|
54170
|
-
case "confirm": return t("interaction.confirm.title");
|
|
54171
|
-
case "select": return t("interaction.select.title");
|
|
54172
|
-
case "authorize": return t("interaction.authorize.title");
|
|
54173
|
-
default: return t("interaction.form.title");
|
|
54174
|
-
}
|
|
54175
|
-
}
|
|
54176
|
-
function renderBody(model, request, deps) {
|
|
54177
|
-
const { t, formRef, invalid, submitForm, resolve, cancel } = deps;
|
|
54178
|
-
if (model.kind === "authorize") {
|
|
54179
|
-
const capability = request.type === "authorize" ? request.capability : void 0;
|
|
54180
|
-
const details = request.type === "authorize" ? request.details : void 0;
|
|
54181
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
54182
|
-
className: "flex flex-col gap-3",
|
|
54183
|
-
children: [
|
|
54184
|
-
capability ? /* @__PURE__ */ jsxs("div", {
|
|
54185
|
-
className: "flex items-center gap-2",
|
|
54186
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
54187
|
-
className: "text-xs font-medium text-muted",
|
|
54188
|
-
children: t("interaction.authorize.capability")
|
|
54189
|
-
}), /* @__PURE__ */ jsx(Badge, {
|
|
54190
|
-
tone: "warning",
|
|
54191
|
-
children: capability
|
|
54192
|
-
})]
|
|
54193
|
-
}) : null,
|
|
54194
|
-
/* @__PURE__ */ jsx("p", {
|
|
54195
|
-
className: "text-xs text-muted",
|
|
54196
|
-
children: t("interaction.authorize.description")
|
|
54197
|
-
}),
|
|
54198
|
-
details !== void 0 ? /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
54199
|
-
className: "mb-1 text-xs font-medium text-muted",
|
|
54200
|
-
children: t("interaction.authorize.details")
|
|
54201
|
-
}), /* @__PURE__ */ jsx("pre", {
|
|
54202
|
-
className: "max-h-40 overflow-auto rounded-lg border border-border bg-canvas p-3 font-mono text-xs text-ink",
|
|
54203
|
-
children: JSON.stringify(details, null, 2)
|
|
54204
|
-
})] }) : null,
|
|
54205
|
-
/* @__PURE__ */ jsxs("div", {
|
|
54206
|
-
className: "flex items-center gap-2",
|
|
54207
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
54208
|
-
onClick: () => resolve(shapeInteractionValue(model, {})),
|
|
54209
|
-
children: t("interaction.allow")
|
|
54210
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
54211
|
-
variant: "danger",
|
|
54212
|
-
onClick: cancel,
|
|
54213
|
-
children: t("interaction.deny")
|
|
54214
|
-
})]
|
|
54215
|
-
})
|
|
54216
|
-
]
|
|
54217
|
-
});
|
|
54218
|
-
}
|
|
54219
|
-
if (model.kind === "confirm") return /* @__PURE__ */ jsxs("div", {
|
|
54220
|
-
className: "flex items-center gap-2",
|
|
54221
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
54222
|
-
onClick: () => resolve(shapeInteractionValue(model, { confirmed: true })),
|
|
54223
|
-
children: t("interaction.confirm")
|
|
54224
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
54225
|
-
variant: "secondary",
|
|
54226
|
-
onClick: cancel,
|
|
54227
|
-
children: t("interaction.cancel")
|
|
54228
|
-
})]
|
|
54229
|
-
});
|
|
54230
|
-
if (model.kind === "select") return /* @__PURE__ */ jsxs("div", {
|
|
54231
|
-
className: "flex flex-col gap-3",
|
|
54232
|
-
children: [/* @__PURE__ */ jsx("ul", {
|
|
54233
|
-
className: "flex flex-col gap-1.5",
|
|
54234
|
-
children: (model.controls[0]?.options ?? []).map((option, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
|
|
54235
|
-
type: "button",
|
|
54236
|
-
onClick: () => resolve(shapeInteractionValue(model, { selected: option.value })),
|
|
54237
|
-
className: "w-full cursor-pointer rounded-lg border border-border bg-surface px-3.5 py-2.5 text-left text-sm text-ink transition-colors hover:border-ring hover:bg-subtle",
|
|
54238
|
-
children: option.label
|
|
54239
|
-
}) }, i))
|
|
54240
|
-
}), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, {
|
|
54241
|
-
variant: "secondary",
|
|
54242
|
-
onClick: cancel,
|
|
54243
|
-
children: t("interaction.cancel")
|
|
54244
|
-
}) })]
|
|
54245
|
-
});
|
|
54246
|
-
return /* @__PURE__ */ jsxs("form", {
|
|
54247
|
-
ref: formRef,
|
|
54248
|
-
noValidate: true,
|
|
54249
|
-
className: "flex flex-col gap-3",
|
|
54250
|
-
onSubmit: (event) => {
|
|
54251
|
-
event.preventDefault();
|
|
54252
|
-
submitForm();
|
|
54253
|
-
},
|
|
54254
|
-
children: [model.controls.map((control) => /* @__PURE__ */ jsx(Field, {
|
|
54255
|
-
control,
|
|
54256
|
-
invalid: invalid.includes(control.name)
|
|
54257
|
-
}, control.name)), /* @__PURE__ */ jsxs("div", {
|
|
54258
|
-
className: "flex items-center gap-2",
|
|
54259
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
54260
|
-
type: "submit",
|
|
54261
|
-
children: t("interaction.submit")
|
|
54262
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
54263
|
-
variant: "secondary",
|
|
54264
|
-
onClick: cancel,
|
|
54265
|
-
children: t("interaction.cancel")
|
|
54266
|
-
})]
|
|
53632
|
+
children: /* @__PURE__ */ jsx(NativeSpecSurface, {
|
|
53633
|
+
surfaceId: request.id,
|
|
53634
|
+
spec,
|
|
53635
|
+
actions: INTERACTION_ACTIONS$1,
|
|
53636
|
+
onAction: handleAction
|
|
53637
|
+
})
|
|
54267
53638
|
})]
|
|
54268
53639
|
});
|
|
54269
53640
|
}
|
|
54270
53641
|
|
|
54271
53642
|
//#endregion
|
|
54272
53643
|
//#region src/react/InterruptedBanner.tsx
|
|
53644
|
+
const resumable = (list) => list.filter((entry) => !isUnsupportedRunSnapshot(entry));
|
|
54273
53645
|
/**
|
|
54274
53646
|
* 未完成对话提示条:挂载/会话切换时检查 interrupted 快照,非空则顶部 banner
|
|
54275
53647
|
* + Resume(engine.resume 后等待中的表单重新进入 bridge.pending)。
|
|
53648
|
+
* @stable
|
|
54276
53649
|
*/
|
|
54277
53650
|
function InterruptedBanner({ engine, sessionId }) {
|
|
54278
53651
|
const t = useT();
|
|
@@ -54280,7 +53653,7 @@ function InterruptedBanner({ engine, sessionId }) {
|
|
|
54280
53653
|
useEffect(() => {
|
|
54281
53654
|
let cancelled = false;
|
|
54282
53655
|
engine.listInterrupted().then((list) => {
|
|
54283
|
-
if (!cancelled) setInterrupted(list);
|
|
53656
|
+
if (!cancelled) setInterrupted(resumable(list));
|
|
54284
53657
|
}).catch(() => {});
|
|
54285
53658
|
return () => {
|
|
54286
53659
|
cancelled = true;
|
|
@@ -54290,7 +53663,7 @@ function InterruptedBanner({ engine, sessionId }) {
|
|
|
54290
53663
|
if (!current) return null;
|
|
54291
53664
|
const resume = () => {
|
|
54292
53665
|
engine.resume(current.runId).then(async () => {
|
|
54293
|
-
setInterrupted(await engine.listInterrupted());
|
|
53666
|
+
setInterrupted(resumable(await engine.listInterrupted()));
|
|
54294
53667
|
});
|
|
54295
53668
|
};
|
|
54296
53669
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -54324,6 +53697,68 @@ function InterruptedBanner({ engine, sessionId }) {
|
|
|
54324
53697
|
});
|
|
54325
53698
|
}
|
|
54326
53699
|
|
|
53700
|
+
//#endregion
|
|
53701
|
+
//#region src/react/SpecInteraction.tsx
|
|
53702
|
+
/** 交互表单的两个动作:与 surface 侧共用 catalog 的 submit / cancel 语义 */
|
|
53703
|
+
const INTERACTION_ACTIONS = [{
|
|
53704
|
+
id: "submit",
|
|
53705
|
+
intent: "submit"
|
|
53706
|
+
}, {
|
|
53707
|
+
id: "cancel",
|
|
53708
|
+
intent: "cancel"
|
|
53709
|
+
}];
|
|
53710
|
+
/** 各档的 spec 渲染入口——交互(路径 A)与 surface(路径 B)在同一档下命中同一个组件 */
|
|
53711
|
+
const SURFACES = {
|
|
53712
|
+
a2ui: A2uiSpecSurface,
|
|
53713
|
+
openui: OpenUiSpecSurface,
|
|
53714
|
+
vercel: JsonRenderSpecSurface
|
|
53715
|
+
};
|
|
53716
|
+
/** optional peer 探测:缺包时通知通道,桥据此粘性降级 native(不悬挂请求、不阻断 run) */
|
|
53717
|
+
const PROBES = {
|
|
53718
|
+
a2ui: probeA2uiAvailability,
|
|
53719
|
+
openui: probeOpenUiAvailability,
|
|
53720
|
+
vercel: probeJsonRenderAvailability
|
|
53721
|
+
};
|
|
53722
|
+
const MISSING_PEER = {
|
|
53723
|
+
a2ui: "@a2ui/lit and @a2ui/web_core are not installed in this host",
|
|
53724
|
+
openui: "@openuidev/react-lang is not installed in this host",
|
|
53725
|
+
vercel: "@json-render/core and @json-render/react are not installed in this host"
|
|
53726
|
+
};
|
|
53727
|
+
/**
|
|
53728
|
+
* 非 native 三档的交互视图(路径 A):订阅 SpecInteractionChannel(core 产出 catalog
|
|
53729
|
+
* 节点树),交给本档 surface 侧同一个渲染入口渲染;提交/取消经 handleAction 回传。
|
|
53730
|
+
* 未挂载时桥直接降级 native(不悬挂请求)。
|
|
53731
|
+
* @experimental
|
|
53732
|
+
*/
|
|
53733
|
+
function SpecInteraction({ channel, renderer }) {
|
|
53734
|
+
const t = useT();
|
|
53735
|
+
const session = useSyncExternalStore(channel.subscribe, () => channel.current);
|
|
53736
|
+
useEffect(() => {
|
|
53737
|
+
channel.labelsFor = (request) => interactionLabels(request, t);
|
|
53738
|
+
}, [channel, t]);
|
|
53739
|
+
useEffect(() => {
|
|
53740
|
+
channel.attach();
|
|
53741
|
+
return () => channel.detach();
|
|
53742
|
+
}, [channel]);
|
|
53743
|
+
useEffect(() => {
|
|
53744
|
+
let cancelled = false;
|
|
53745
|
+
PROBES[renderer]().then((available) => {
|
|
53746
|
+
if (!cancelled && !available) channel.fail(MISSING_PEER[renderer]);
|
|
53747
|
+
});
|
|
53748
|
+
return () => {
|
|
53749
|
+
cancelled = true;
|
|
53750
|
+
};
|
|
53751
|
+
}, [channel, renderer]);
|
|
53752
|
+
if (!session) return null;
|
|
53753
|
+
const Surface = SURFACES[renderer];
|
|
53754
|
+
return /* @__PURE__ */ jsx(Surface, {
|
|
53755
|
+
surfaceId: session.request.id,
|
|
53756
|
+
spec: session.spec,
|
|
53757
|
+
actions: INTERACTION_ACTIONS,
|
|
53758
|
+
onAction: (event) => channel.handleAction(event)
|
|
53759
|
+
});
|
|
53760
|
+
}
|
|
53761
|
+
|
|
54327
53762
|
//#endregion
|
|
54328
53763
|
//#region src/react/SettingsDrawer.tsx
|
|
54329
53764
|
const PROVIDERS = [
|
|
@@ -54347,7 +53782,7 @@ function createProbeClient(provider, form) {
|
|
|
54347
53782
|
model: form.model
|
|
54348
53783
|
});
|
|
54349
53784
|
}
|
|
54350
|
-
/** 设置抽屉:LLM 配置(三协议供应商 / 能力探测 / Demo model 标识 / 流式与 temperature)+ 外观(主题/语言) */
|
|
53785
|
+
/** 设置抽屉:LLM 配置(三协议供应商 / 能力探测 / Demo model 标识 / 流式与 temperature)+ 外观(主题/语言) @stable */
|
|
54351
53786
|
function SettingsDrawer({ open, llmConfig, runtimeConfig, theme, locale, renderer, onAppearanceChange, onSaved, onClose }) {
|
|
54352
53787
|
const t = useT();
|
|
54353
53788
|
const [provider, setProvider] = useState("openai-compatible");
|
|
@@ -54717,53 +54152,6 @@ function useChatLayout(layout = "auto") {
|
|
|
54717
54152
|
};
|
|
54718
54153
|
}
|
|
54719
54154
|
|
|
54720
|
-
//#endregion
|
|
54721
|
-
//#region src/react/VercelPayloadPreview.tsx
|
|
54722
|
-
/**
|
|
54723
|
-
* vercel 档(payload 预览):不渲染表单,展示 InteractionRequest 经 toVercelToolInvocation
|
|
54724
|
-
* 转换后的 Vercel AI SDK 数据契约 JSON 卡。仅提供 Cancel 结束交互(非完整运行时)。
|
|
54725
|
-
*/
|
|
54726
|
-
function VercelPayloadPreview({ bridge }) {
|
|
54727
|
-
const t = useT();
|
|
54728
|
-
const pending = useSyncExternalStore(bridge.subscribe, () => bridge.pending);
|
|
54729
|
-
if (!pending) return null;
|
|
54730
|
-
const payload = toVercelToolInvocation(pending);
|
|
54731
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
54732
|
-
"data-testid": "vercel-payload-preview",
|
|
54733
|
-
className: "rounded-card border border-border bg-surface shadow-card",
|
|
54734
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
54735
|
-
className: "flex items-center gap-2 px-4 pt-4",
|
|
54736
|
-
children: [/* @__PURE__ */ jsx("h3", {
|
|
54737
|
-
className: "font-display text-sm font-semibold text-ink",
|
|
54738
|
-
children: t("vercel.preview.title")
|
|
54739
|
-
}), /* @__PURE__ */ jsx(Badge, {
|
|
54740
|
-
tone: "neutral",
|
|
54741
|
-
children: t("vercel.preview.badge")
|
|
54742
|
-
})]
|
|
54743
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
54744
|
-
className: "flex flex-col gap-3 px-4 py-4",
|
|
54745
|
-
children: [
|
|
54746
|
-
/* @__PURE__ */ jsx("p", {
|
|
54747
|
-
className: "text-xs text-muted",
|
|
54748
|
-
children: t("vercel.preview.description")
|
|
54749
|
-
}),
|
|
54750
|
-
/* @__PURE__ */ jsx("pre", {
|
|
54751
|
-
className: "max-h-64 overflow-auto rounded-lg border border-border bg-canvas p-3 font-mono text-xs text-ink",
|
|
54752
|
-
children: JSON.stringify(payload, null, 2)
|
|
54753
|
-
}),
|
|
54754
|
-
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, {
|
|
54755
|
-
variant: "secondary",
|
|
54756
|
-
onClick: () => bridge.resolve({
|
|
54757
|
-
id: pending.id,
|
|
54758
|
-
cancelled: true
|
|
54759
|
-
}),
|
|
54760
|
-
children: t("interaction.cancel")
|
|
54761
|
-
}) })
|
|
54762
|
-
]
|
|
54763
|
-
})]
|
|
54764
|
-
});
|
|
54765
|
-
}
|
|
54766
|
-
|
|
54767
54155
|
//#endregion
|
|
54768
54156
|
//#region src/react/Chatbot.tsx
|
|
54769
54157
|
const toErrorMessage = (e) => e instanceof Error ? e.message : String(e);
|
|
@@ -54786,14 +54174,17 @@ async function downloadArtifactFile(storage, chatRoot, file) {
|
|
|
54786
54174
|
/**
|
|
54787
54175
|
* ChatEngine owns message/session/runtime state while assistant-ui Base owns the
|
|
54788
54176
|
* presentation shell and accessible thread primitives.
|
|
54177
|
+
* @stable
|
|
54789
54178
|
*/
|
|
54790
|
-
function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, renderer: rendererProp, surfaceRegistry, layout = "auto", onAppearanceChange }) {
|
|
54179
|
+
function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, renderer: rendererProp, surfaceRegistry, layout = "auto", onAppearanceChange, onEngineReady }) {
|
|
54791
54180
|
const engine = useMemo(() => new ChatEngine(adapter, {
|
|
54792
54181
|
...config?.chatRoot ? { chatRoot: config.chatRoot } : {},
|
|
54793
54182
|
...config?.llm ? { llm: config.llm } : {},
|
|
54794
54183
|
...config?.loopConfig ? { loopConfig: config.loopConfig } : {},
|
|
54795
54184
|
...config?.runtimeConfig ? { runtimeConfig: config.runtimeConfig } : {},
|
|
54796
54185
|
...config?.generativeUi ? { generativeUi: true } : {},
|
|
54186
|
+
...config?.hooks ? { hooks: config.hooks } : {},
|
|
54187
|
+
...config?.governance ? { governance: config.governance } : {},
|
|
54797
54188
|
...rendererProp ? { renderer: rendererProp } : {}
|
|
54798
54189
|
}), [
|
|
54799
54190
|
adapter,
|
|
@@ -54802,8 +54193,13 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
54802
54193
|
config?.loopConfig,
|
|
54803
54194
|
config?.runtimeConfig,
|
|
54804
54195
|
config?.generativeUi,
|
|
54196
|
+
config?.hooks,
|
|
54197
|
+
config?.governance,
|
|
54805
54198
|
rendererProp
|
|
54806
54199
|
]);
|
|
54200
|
+
useEffect(() => {
|
|
54201
|
+
onEngineReady?.(engine);
|
|
54202
|
+
}, [engine, onEngineReady]);
|
|
54807
54203
|
const [theme, setTheme] = useState(themeProp ?? "light");
|
|
54808
54204
|
const [locale, setLocale] = useState(localeProp ?? "en");
|
|
54809
54205
|
const [renderer, setRenderer] = useState(rendererProp ?? "native");
|
|
@@ -54823,6 +54219,11 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
54823
54219
|
const [sessions, setSessions] = useState([]);
|
|
54824
54220
|
/** 首次 listSessions 未完成(threads 客户端的 isLoading) */
|
|
54825
54221
|
const [sessionsLoading, setSessionsLoading] = useState(true);
|
|
54222
|
+
/** 分页游标:非空即「还有更早的一页」。页大小归 SessionStore,这里不覆写 limit */
|
|
54223
|
+
const [sessionsCursor, setSessionsCursor] = useState();
|
|
54224
|
+
const [messagesCursor, setMessagesCursor] = useState();
|
|
54225
|
+
const [loadingEarlierSessions, setLoadingEarlierSessions] = useState(false);
|
|
54226
|
+
const [loadingEarlierMessages, setLoadingEarlierMessages] = useState(false);
|
|
54826
54227
|
const [currentSessionId, setCurrentSessionId] = useState();
|
|
54827
54228
|
const [sending, setSending] = useState(false);
|
|
54828
54229
|
/** 当前活跃 runId(run-started 捕获;Stop 按钮 engine.cancel 用) */
|
|
@@ -54832,14 +54233,15 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
54832
54233
|
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
54833
54234
|
/** 当前进行中 run 的 part 累积器(流式正文 / 工具 / 生命周期步进的唯一来源) */
|
|
54834
54235
|
const [live, setLive] = useState();
|
|
54835
|
-
/** a2ui 档交互容器显隐(interaction-requested/resolved 事件驱动) */
|
|
54836
|
-
const [a2uiActive, setA2uiActive] = useState(false);
|
|
54837
54236
|
const [interactionPending, setInteractionPending] = useState(false);
|
|
54838
54237
|
/** pending 交互归属的会话(跨会话查看时隐藏交互卡,防串台) */
|
|
54839
54238
|
const [interactionSessionId, setInteractionSessionId] = useState();
|
|
54840
54239
|
/** currentSessionId 的 ref 镜像(事件订阅闭包 [engine] 内读取最新值) */
|
|
54841
54240
|
const sessionRef = useRef(currentSessionId);
|
|
54842
54241
|
sessionRef.current = currentSessionId;
|
|
54242
|
+
/** sessions 的 ref 镜像(handleSend 判定「这次是否会生成标题」,不想为此进依赖表) */
|
|
54243
|
+
const sessionsRef = useRef(sessions);
|
|
54244
|
+
sessionsRef.current = sessions;
|
|
54843
54245
|
const { containerRef, resolved: resolvedLayout } = useChatLayout(layout);
|
|
54844
54246
|
/** 附件按钮只在存储确实可写时出现(R11:不渲染点了就报错的按钮) */
|
|
54845
54247
|
const [attachmentsReady, setAttachmentsReady] = useState(false);
|
|
@@ -54858,30 +54260,26 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
54858
54260
|
cancelled = true;
|
|
54859
54261
|
};
|
|
54860
54262
|
}, [adapter, engine]);
|
|
54861
|
-
/** a2ui 交互容器 ref:挂载即注入引擎(卸载传 null),引擎懒建 LitRendererBridge 渲染其中;
|
|
54862
|
-
同时为容器配置 @a2ui/markdown-it(optional peer,缺失时保持纯文本降级) */
|
|
54863
|
-
const interactionMountRef = useCallback((el) => {
|
|
54864
|
-
engine.setInteractionMount(el);
|
|
54865
|
-
if (el) configureA2uiMarkdown(el).then((configured) => {
|
|
54866
|
-
if (!configured) console.warn("A2UI markdown renderer is not configured: install @a2ui/markdown-it to render markdown in A2UI interactions");
|
|
54867
|
-
});
|
|
54868
|
-
}, [engine]);
|
|
54869
54263
|
const refreshSessions = useCallback(async () => {
|
|
54870
|
-
|
|
54264
|
+
const page = await engine.listSessions();
|
|
54265
|
+
setSessions(page.items);
|
|
54266
|
+
setSessionsCursor(page.nextCursor);
|
|
54871
54267
|
}, [engine]);
|
|
54872
54268
|
useEffect(() => {
|
|
54873
54269
|
let cancelled = false;
|
|
54874
54270
|
(async () => {
|
|
54875
|
-
const
|
|
54271
|
+
const page = await engine.listSessions();
|
|
54876
54272
|
if (cancelled) return;
|
|
54877
|
-
setSessions(
|
|
54273
|
+
setSessions(page.items);
|
|
54274
|
+
setSessionsCursor(page.nextCursor);
|
|
54878
54275
|
setSessionsLoading(false);
|
|
54879
|
-
const latest =
|
|
54276
|
+
const latest = page.items[page.items.length - 1];
|
|
54880
54277
|
if (!latest) return;
|
|
54881
54278
|
const history = await engine.selectSession(latest.id);
|
|
54882
54279
|
if (cancelled) return;
|
|
54883
54280
|
setCurrentSessionId(latest.id);
|
|
54884
|
-
setMessages(history);
|
|
54281
|
+
setMessages(history.items);
|
|
54282
|
+
setMessagesCursor(history.nextCursor);
|
|
54885
54283
|
})().catch((e) => {
|
|
54886
54284
|
if (!cancelled) {
|
|
54887
54285
|
setSessionsLoading(false);
|
|
@@ -54904,12 +54302,10 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
54904
54302
|
setMessages((prev) => prev.some((message) => message.id === event.message.id) ? prev : [...prev, event.message]);
|
|
54905
54303
|
break;
|
|
54906
54304
|
case "interaction-requested":
|
|
54907
|
-
setA2uiActive(true);
|
|
54908
54305
|
setInteractionPending(true);
|
|
54909
54306
|
setInteractionSessionId(sessionRef.current);
|
|
54910
54307
|
break;
|
|
54911
54308
|
case "interaction-resolved":
|
|
54912
|
-
setA2uiActive(false);
|
|
54913
54309
|
setInteractionPending(false);
|
|
54914
54310
|
setInteractionSessionId(void 0);
|
|
54915
54311
|
break;
|
|
@@ -54934,12 +54330,16 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
54934
54330
|
}), [engine]);
|
|
54935
54331
|
const handleSend = useCallback((text, attachments = []) => {
|
|
54936
54332
|
(async () => {
|
|
54937
|
-
|
|
54333
|
+
let sessionId = currentSessionId;
|
|
54334
|
+
if (!sessionId) {
|
|
54938
54335
|
const meta = await engine.createSession();
|
|
54336
|
+
sessionId = meta.id;
|
|
54939
54337
|
setCurrentSessionId(meta.id);
|
|
54940
54338
|
await refreshSessions();
|
|
54941
54339
|
}
|
|
54340
|
+
const needsTitle = sessionsRef.current.find((session) => session.id === sessionId)?.title === void 0;
|
|
54942
54341
|
await engine.send(text, attachments);
|
|
54342
|
+
if (needsTitle) await refreshSessions();
|
|
54943
54343
|
})().catch((e) => setError({ message: toErrorMessage(e) }));
|
|
54944
54344
|
}, [
|
|
54945
54345
|
engine,
|
|
@@ -54961,14 +54361,41 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
54961
54361
|
const handleSelect = useCallback((id) => {
|
|
54962
54362
|
engine.selectSession(id).then((history) => {
|
|
54963
54363
|
setCurrentSessionId(id);
|
|
54964
|
-
setMessages(history);
|
|
54364
|
+
setMessages(history.items);
|
|
54365
|
+
setMessagesCursor(history.nextCursor);
|
|
54965
54366
|
setDrawerOpen(false);
|
|
54966
54367
|
}).catch((e) => setError({ message: toErrorMessage(e) }));
|
|
54967
54368
|
}, [engine]);
|
|
54369
|
+
/** 向历史方向再取一页:页内升序,所以是**前插**而不是追加 */
|
|
54370
|
+
const handleLoadEarlierMessages = useCallback(() => {
|
|
54371
|
+
if (!messagesCursor || loadingEarlierMessages) return;
|
|
54372
|
+
setLoadingEarlierMessages(true);
|
|
54373
|
+
engine.loadMoreMessages(messagesCursor).then((page) => {
|
|
54374
|
+
setMessages((prev) => [...page.items, ...prev]);
|
|
54375
|
+
setMessagesCursor(page.nextCursor);
|
|
54376
|
+
}).catch((e) => setError({ message: toErrorMessage(e) })).finally(() => setLoadingEarlierMessages(false));
|
|
54377
|
+
}, [
|
|
54378
|
+
engine,
|
|
54379
|
+
messagesCursor,
|
|
54380
|
+
loadingEarlierMessages
|
|
54381
|
+
]);
|
|
54382
|
+
const handleLoadEarlierSessions = useCallback(() => {
|
|
54383
|
+
if (!sessionsCursor || loadingEarlierSessions) return;
|
|
54384
|
+
setLoadingEarlierSessions(true);
|
|
54385
|
+
engine.listSessions({ cursor: sessionsCursor }).then((page) => {
|
|
54386
|
+
setSessions((prev) => [...page.items, ...prev]);
|
|
54387
|
+
setSessionsCursor(page.nextCursor);
|
|
54388
|
+
}).catch((e) => setError({ message: toErrorMessage(e) })).finally(() => setLoadingEarlierSessions(false));
|
|
54389
|
+
}, [
|
|
54390
|
+
engine,
|
|
54391
|
+
sessionsCursor,
|
|
54392
|
+
loadingEarlierSessions
|
|
54393
|
+
]);
|
|
54968
54394
|
const handleCreate = useCallback(() => {
|
|
54969
54395
|
engine.createSession().then(async (meta) => {
|
|
54970
54396
|
setCurrentSessionId(meta.id);
|
|
54971
54397
|
setMessages([]);
|
|
54398
|
+
setMessagesCursor(void 0);
|
|
54972
54399
|
await refreshSessions();
|
|
54973
54400
|
}).catch((e) => setError({ message: toErrorMessage(e) }));
|
|
54974
54401
|
}, [engine, refreshSessions]);
|
|
@@ -55033,7 +54460,12 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
55033
54460
|
"data-layout": resolvedLayout,
|
|
55034
54461
|
className: `webskill-aui-shell flex h-full min-h-0 flex-row font-sans text-ink ${theme === "dark" ? "dark" : ""}`,
|
|
55035
54462
|
children: [
|
|
55036
|
-
/* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(AssistantUiSessionList, {
|
|
54463
|
+
/* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(AssistantUiSessionList, {
|
|
54464
|
+
className: "hidden lg:flex",
|
|
54465
|
+
hasEarlier: sessionsCursor !== void 0,
|
|
54466
|
+
loadingEarlier: loadingEarlierSessions,
|
|
54467
|
+
onLoadEarlier: handleLoadEarlierSessions
|
|
54468
|
+
}), /* @__PURE__ */ jsx(Sheet, {
|
|
55037
54469
|
open: drawerOpen,
|
|
55038
54470
|
onOpenChange: setDrawerOpen,
|
|
55039
54471
|
children: /* @__PURE__ */ jsx(SheetContent, {
|
|
@@ -55042,7 +54474,10 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
55042
54474
|
className: "p-0 lg:hidden",
|
|
55043
54475
|
children: /* @__PURE__ */ jsx(AssistantUiSessionList, {
|
|
55044
54476
|
className: "h-full w-full border-r-0",
|
|
55045
|
-
onNavigate: () => setDrawerOpen(false)
|
|
54477
|
+
onNavigate: () => setDrawerOpen(false),
|
|
54478
|
+
hasEarlier: sessionsCursor !== void 0,
|
|
54479
|
+
loadingEarlier: loadingEarlierSessions,
|
|
54480
|
+
onLoadEarlier: handleLoadEarlierSessions
|
|
55046
54481
|
})
|
|
55047
54482
|
})
|
|
55048
54483
|
})] }),
|
|
@@ -55075,6 +54510,10 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
55075
54510
|
}) : null,
|
|
55076
54511
|
/* @__PURE__ */ jsx(AssistantUiMessageList, {
|
|
55077
54512
|
messages,
|
|
54513
|
+
...messagesCursor !== void 0 ? { earlier: {
|
|
54514
|
+
loading: loadingEarlierMessages,
|
|
54515
|
+
onLoad: handleLoadEarlierMessages
|
|
54516
|
+
} } : {},
|
|
55078
54517
|
renderMessage: (message) => /* @__PURE__ */ jsx(AssistantUiMessage, {
|
|
55079
54518
|
message,
|
|
55080
54519
|
onRetry: handleRetry,
|
|
@@ -55087,18 +54526,14 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
55087
54526
|
}),
|
|
55088
54527
|
(() => {
|
|
55089
54528
|
const interactionVisible = interactionSessionId === void 0 || interactionSessionId === currentSessionId;
|
|
55090
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
55091
|
-
|
|
55092
|
-
|
|
55093
|
-
|
|
55094
|
-
|
|
55095
|
-
|
|
55096
|
-
|
|
55097
|
-
|
|
55098
|
-
children: /* @__PURE__ */ jsx(OpenUiInteraction, { channel: engine.openUiChannel })
|
|
55099
|
-
}) : null,
|
|
55100
|
-
interactionVisible ? renderer === "vercel" ? /* @__PURE__ */ jsx(VercelPayloadPreview, { bridge: engine.bridge }) : /* @__PURE__ */ jsx(InteractionCard, { bridge: engine.bridge }) : null
|
|
55101
|
-
] });
|
|
54529
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [renderer !== "native" ? /* @__PURE__ */ jsx("div", {
|
|
54530
|
+
"data-testid": "spec-interaction-slot",
|
|
54531
|
+
className: interactionVisible ? void 0 : "hidden",
|
|
54532
|
+
children: /* @__PURE__ */ jsx(SpecInteraction, {
|
|
54533
|
+
channel: engine.interactionChannel,
|
|
54534
|
+
renderer
|
|
54535
|
+
})
|
|
54536
|
+
}) : null, interactionVisible ? /* @__PURE__ */ jsx(InteractionCard, { bridge: engine.bridge }) : null] });
|
|
55102
54537
|
})(),
|
|
55103
54538
|
/* @__PURE__ */ jsx(ResultBlocksPro, {
|
|
55104
54539
|
bridge: engine.bridge,
|
|
@@ -55112,13 +54547,11 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
55112
54547
|
}) : null,
|
|
55113
54548
|
renderer === "vercel" && currentRunId ? /* @__PURE__ */ jsx(VercelSurfaceHost, {
|
|
55114
54549
|
bridge: engine.bridge,
|
|
55115
|
-
runId: currentRunId
|
|
55116
|
-
...surfaceRegistry ? { registry: surfaceRegistry } : {}
|
|
54550
|
+
runId: currentRunId
|
|
55117
54551
|
}) : null,
|
|
55118
54552
|
renderer === "openui" && currentRunId ? /* @__PURE__ */ jsx(OpenUiSurfaceHost, {
|
|
55119
54553
|
bridge: engine.bridge,
|
|
55120
|
-
runId: currentRunId
|
|
55121
|
-
...surfaceRegistry ? { registry: surfaceRegistry } : {}
|
|
54554
|
+
runId: currentRunId
|
|
55122
54555
|
}) : null,
|
|
55123
54556
|
renderer === "a2ui" && currentRunId ? /* @__PURE__ */ jsx(A2uiSurfaceHost, {
|
|
55124
54557
|
bridge: engine.bridge,
|
|
@@ -55160,4 +54593,52 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
55160
54593
|
}
|
|
55161
54594
|
|
|
55162
54595
|
//#endregion
|
|
55163
|
-
|
|
54596
|
+
//#region src/react/VercelPayloadPreview.tsx
|
|
54597
|
+
/**
|
|
54598
|
+
* vercel 档(payload 预览):不渲染表单,展示 InteractionRequest 经 toVercelToolInvocation
|
|
54599
|
+
* 转换后的 Vercel AI SDK 数据契约 JSON 卡。仅提供 Cancel 结束交互(非完整运行时)。
|
|
54600
|
+
* @experimental
|
|
54601
|
+
*/
|
|
54602
|
+
function VercelPayloadPreview({ bridge }) {
|
|
54603
|
+
const t = useT();
|
|
54604
|
+
const pending = useSyncExternalStore(bridge.subscribe, () => bridge.pending);
|
|
54605
|
+
if (!pending) return null;
|
|
54606
|
+
const payload = toVercelToolInvocation(pending);
|
|
54607
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
54608
|
+
"data-testid": "vercel-payload-preview",
|
|
54609
|
+
className: "rounded-card border border-border bg-surface shadow-card",
|
|
54610
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
54611
|
+
className: "flex items-center gap-2 px-4 pt-4",
|
|
54612
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
54613
|
+
className: "font-display text-sm font-semibold text-ink",
|
|
54614
|
+
children: t("vercel.preview.title")
|
|
54615
|
+
}), /* @__PURE__ */ jsx(Badge, {
|
|
54616
|
+
tone: "neutral",
|
|
54617
|
+
children: t("vercel.preview.badge")
|
|
54618
|
+
})]
|
|
54619
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
54620
|
+
className: "flex flex-col gap-3 px-4 py-4",
|
|
54621
|
+
children: [
|
|
54622
|
+
/* @__PURE__ */ jsx("p", {
|
|
54623
|
+
className: "text-xs text-muted",
|
|
54624
|
+
children: t("vercel.preview.description")
|
|
54625
|
+
}),
|
|
54626
|
+
/* @__PURE__ */ jsx("pre", {
|
|
54627
|
+
className: "max-h-64 overflow-auto rounded-lg border border-border bg-canvas p-3 font-mono text-xs text-ink",
|
|
54628
|
+
children: JSON.stringify(payload, null, 2)
|
|
54629
|
+
}),
|
|
54630
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, {
|
|
54631
|
+
variant: "secondary",
|
|
54632
|
+
onClick: () => bridge.resolve({
|
|
54633
|
+
id: pending.id,
|
|
54634
|
+
cancelled: true
|
|
54635
|
+
}),
|
|
54636
|
+
children: t("interaction.cancel")
|
|
54637
|
+
}) })
|
|
54638
|
+
]
|
|
54639
|
+
})]
|
|
54640
|
+
});
|
|
54641
|
+
}
|
|
54642
|
+
|
|
54643
|
+
//#endregion
|
|
54644
|
+
export { A2uiSurfaceHost, A2uiSurfaceSnapshotHost, ChatEngine, Chatbot, CompositeUiBridge, DEFAULT_RENDERER_CAPABILITIES, ErrorCard, InteractionCard, InterruptedBanner, OpenUiSurfaceHost, OpenUiSurfaceSnapshotHost, ResultBlockList, ResultBlocksPro, SettingsDrawer, SkillBadges, SpecInteraction, VercelPayloadPreview, VercelSurfaceHost, VercelSurfaceSnapshotHost, chatbotDictionary, configureA2uiMarkdown, probeA2uiAvailability, probeOpenUiAvailability, useT };
|