@tutti-os/agent-gui 0.0.39 → 0.0.41
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/README.md +40 -0
- package/dist/{AgentMessageMarkdown-BVeh06AJ.d.ts → AgentMessageMarkdown-Cts0dAIm.d.ts} +4 -156
- package/dist/agent-conversation/index.d.ts +2 -1
- package/dist/agent-conversation/index.js +5 -5
- package/dist/agent-message-center/index.js +7 -7
- package/dist/agent-message-center/index.js.map +1 -1
- package/dist/app/renderer/agentactivity.css +298 -21
- package/dist/{chunk-46IYJEZX.js → chunk-3PVSIL3H.js} +5 -5
- package/dist/{chunk-RE3AHBX6.js → chunk-3WZWZHAJ.js} +2 -2
- package/dist/{chunk-Y2DQJPTL.js → chunk-42WP3P5C.js} +2 -2
- package/dist/chunk-4K22O34C.js +123 -0
- package/dist/chunk-4K22O34C.js.map +1 -0
- package/dist/{chunk-Y5SE2XMU.js → chunk-5LVFYNIP.js} +5 -2
- package/dist/{chunk-Y5SE2XMU.js.map → chunk-5LVFYNIP.js.map} +1 -1
- package/dist/{chunk-C7ZZZXKB.js → chunk-5U4SXENC.js} +5 -5
- package/dist/{chunk-ZWJBG2JM.js → chunk-EFDGMXTB.js} +62 -7
- package/dist/chunk-EFDGMXTB.js.map +1 -0
- package/dist/{chunk-JNGYJ7GM.js → chunk-EU7RWKHE.js} +2 -2
- package/dist/{chunk-IXIGWLQY.js → chunk-F5DYXCY3.js} +1 -1
- package/dist/{chunk-IXIGWLQY.js.map → chunk-F5DYXCY3.js.map} +1 -1
- package/dist/{chunk-WJPEKD3F.js → chunk-LKOPLDPM.js} +5 -1
- package/dist/chunk-LKOPLDPM.js.map +1 -0
- package/dist/{chunk-3AXEEQMV.js → chunk-MUJYJDZH.js} +12 -11
- package/dist/chunk-MUJYJDZH.js.map +1 -0
- package/dist/{chunk-5HQDW73P.js → chunk-OLZP2EFK.js} +231 -46
- package/dist/chunk-OLZP2EFK.js.map +1 -0
- package/dist/{chunk-XL2EKJTQ.js → chunk-QIPMH6XO.js} +137 -37
- package/dist/chunk-QIPMH6XO.js.map +1 -0
- package/dist/{chunk-B2JKDZSR.js → chunk-TXXWUG2J.js} +1 -1
- package/dist/chunk-TXXWUG2J.js.map +1 -0
- package/dist/context-mention-palette/index.js +6 -6
- package/dist/i18n/index.d.ts +4 -0
- package/dist/i18n/index.js +1 -1
- package/dist/index.d.ts +134 -102
- package/dist/index.js +374 -154
- package/dist/index.js.map +1 -1
- package/dist/types-xMz0lJWt.d.ts +173 -0
- package/dist/workbench/contribution.d.ts +5 -0
- package/dist/workbench/contribution.js +5 -4
- package/dist/workbench/index.d.ts +11 -3
- package/dist/workbench/index.js +5 -4
- package/dist/workbench/launch.d.ts +1 -0
- package/dist/workbench/launch.js +2 -2
- package/dist/workbench/providerCatalog.d.ts +1 -0
- package/dist/workbench/state.d.ts +1 -0
- package/dist/workbench/state.js +2 -1
- package/dist/workbench/types.d.ts +6 -0
- package/dist/workbench/types.js +1 -1
- package/dist/workspace-agent-generated-files.js +2 -2
- package/package.json +12 -12
- package/dist/chunk-3AXEEQMV.js.map +0 -1
- package/dist/chunk-5HQDW73P.js.map +0 -1
- package/dist/chunk-B2JKDZSR.js.map +0 -1
- package/dist/chunk-WJPEKD3F.js.map +0 -1
- package/dist/chunk-XL2EKJTQ.js.map +0 -1
- package/dist/chunk-ZWJBG2JM.js.map +0 -1
- /package/dist/{chunk-46IYJEZX.js.map → chunk-3PVSIL3H.js.map} +0 -0
- /package/dist/{chunk-RE3AHBX6.js.map → chunk-3WZWZHAJ.js.map} +0 -0
- /package/dist/{chunk-Y2DQJPTL.js.map → chunk-42WP3P5C.js.map} +0 -0
- /package/dist/{chunk-C7ZZZXKB.js.map → chunk-5U4SXENC.js.map} +0 -0
- /package/dist/{chunk-JNGYJ7GM.js.map → chunk-EU7RWKHE.js.map} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getOptionalAgentHostApi,
|
|
3
3
|
useOptionalAgentHostApi
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-TXXWUG2J.js";
|
|
5
5
|
import {
|
|
6
6
|
translate,
|
|
7
7
|
useTranslation
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LKOPLDPM.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveAgentWorkspaceFileVisualKind
|
|
11
11
|
} from "./chunk-PJP5BUU6.js";
|
|
@@ -192,7 +192,7 @@ import {
|
|
|
192
192
|
useEffect as useEffect3,
|
|
193
193
|
useContext,
|
|
194
194
|
memo,
|
|
195
|
-
useMemo
|
|
195
|
+
useMemo,
|
|
196
196
|
useState as useState4
|
|
197
197
|
} from "react";
|
|
198
198
|
|
|
@@ -202,9 +202,14 @@ import {
|
|
|
202
202
|
isValidElement,
|
|
203
203
|
useCallback as useCallback2,
|
|
204
204
|
useEffect,
|
|
205
|
-
useMemo,
|
|
206
205
|
useState as useState2
|
|
207
206
|
} from "react";
|
|
207
|
+
import {
|
|
208
|
+
ToastProvider,
|
|
209
|
+
ToastRoot,
|
|
210
|
+
ToastTitle,
|
|
211
|
+
ToastViewport
|
|
212
|
+
} from "@tutti-os/ui-system";
|
|
208
213
|
import { CopyIcon, DownloadIcon } from "lucide-react";
|
|
209
214
|
import Zoom from "react-medium-image-zoom";
|
|
210
215
|
|
|
@@ -261,12 +266,19 @@ async function blobToBase64(blob) {
|
|
|
261
266
|
reader.readAsDataURL(blob);
|
|
262
267
|
});
|
|
263
268
|
}
|
|
264
|
-
async function
|
|
269
|
+
async function pngBlobFromSrc(src) {
|
|
270
|
+
const blob = await imageSrcToPngBlob(src);
|
|
271
|
+
if (!blob) {
|
|
272
|
+
throw new Error("image conversion failed");
|
|
273
|
+
}
|
|
274
|
+
return blob;
|
|
275
|
+
}
|
|
276
|
+
async function copyImageWithWebClipboard(data) {
|
|
265
277
|
if (typeof navigator === "undefined" || typeof navigator.clipboard?.write !== "function" || typeof ClipboardItem === "undefined") {
|
|
266
278
|
return false;
|
|
267
279
|
}
|
|
268
280
|
try {
|
|
269
|
-
await navigator.clipboard.write([new ClipboardItem({ "image/png":
|
|
281
|
+
await navigator.clipboard.write([new ClipboardItem({ "image/png": data })]);
|
|
270
282
|
return true;
|
|
271
283
|
} catch {
|
|
272
284
|
return false;
|
|
@@ -274,19 +286,20 @@ async function copyImageWithWebClipboard(blob) {
|
|
|
274
286
|
}
|
|
275
287
|
async function copyImageToClipboard(src, hostClipboard) {
|
|
276
288
|
try {
|
|
289
|
+
if (!hostClipboard?.writeImage) {
|
|
290
|
+
return await copyImageWithWebClipboard(pngBlobFromSrc(src));
|
|
291
|
+
}
|
|
277
292
|
const blob = await imageSrcToPngBlob(src);
|
|
278
293
|
if (!blob) {
|
|
279
294
|
return false;
|
|
280
295
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
await
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
} catch {
|
|
289
|
-
}
|
|
296
|
+
try {
|
|
297
|
+
await hostClipboard.writeImage({
|
|
298
|
+
data: await blobToBase64(blob),
|
|
299
|
+
mimeType: "image/png"
|
|
300
|
+
});
|
|
301
|
+
return true;
|
|
302
|
+
} catch {
|
|
290
303
|
}
|
|
291
304
|
return copyImageWithWebClipboard(blob);
|
|
292
305
|
} catch {
|
|
@@ -338,6 +351,7 @@ function ConversationImageContextMenu({
|
|
|
338
351
|
// app/renderer/components/ZoomableImage.tsx
|
|
339
352
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
340
353
|
function ZoomableImage({
|
|
354
|
+
alt,
|
|
341
355
|
className,
|
|
342
356
|
downloadName,
|
|
343
357
|
onContextMenu,
|
|
@@ -346,13 +360,11 @@ function ZoomableImage({
|
|
|
346
360
|
...props
|
|
347
361
|
}) {
|
|
348
362
|
const { t } = useTranslation();
|
|
363
|
+
const agentHostApi = useOptionalAgentHostApi();
|
|
349
364
|
const actionSource = typeof src === "string" && src.trim() ? src.trim() : null;
|
|
350
365
|
const hasImageActions = Boolean(actionSource && downloadName !== void 0);
|
|
351
|
-
const resolvedDownloadName = useMemo(
|
|
352
|
-
() => resolveImageDownloadName(downloadName, actionSource),
|
|
353
|
-
[actionSource, downloadName]
|
|
354
|
-
);
|
|
355
366
|
const [contextMenuPosition, setContextMenuPosition] = useState2(null);
|
|
367
|
+
const [copyStatus, setCopyStatus] = useState2(null);
|
|
356
368
|
const closeContextMenu = useCallback2(() => {
|
|
357
369
|
setContextMenuPosition(null);
|
|
358
370
|
}, []);
|
|
@@ -367,6 +379,13 @@ function ZoomableImage({
|
|
|
367
379
|
document.removeEventListener("scroll", closeContextMenu, true);
|
|
368
380
|
};
|
|
369
381
|
}, [closeContextMenu, contextMenuPosition]);
|
|
382
|
+
useEffect(() => {
|
|
383
|
+
if (!copyStatus || copyStatus.busy) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const timer = setTimeout(() => setCopyStatus(null), 1600);
|
|
387
|
+
return () => clearTimeout(timer);
|
|
388
|
+
}, [copyStatus]);
|
|
370
389
|
const handleContextMenu = useCallback2(
|
|
371
390
|
(event) => {
|
|
372
391
|
onContextMenu?.(event);
|
|
@@ -374,7 +393,12 @@ function ZoomableImage({
|
|
|
374
393
|
return;
|
|
375
394
|
}
|
|
376
395
|
event.preventDefault();
|
|
377
|
-
|
|
396
|
+
event.stopPropagation();
|
|
397
|
+
setContextMenuPosition({
|
|
398
|
+
x: event.clientX,
|
|
399
|
+
y: event.clientY,
|
|
400
|
+
inZoomDialog: Boolean(event.currentTarget.closest(".tsh-zoom-dialog"))
|
|
401
|
+
});
|
|
378
402
|
},
|
|
379
403
|
[actionSource, hasImageActions, onContextMenu]
|
|
380
404
|
);
|
|
@@ -382,9 +406,28 @@ function ZoomableImage({
|
|
|
382
406
|
if (!actionSource) {
|
|
383
407
|
return;
|
|
384
408
|
}
|
|
409
|
+
const copyingMessage = t("common.copying");
|
|
410
|
+
setCopyStatus({
|
|
411
|
+
busy: true,
|
|
412
|
+
message: copyingMessage,
|
|
413
|
+
variant: "success"
|
|
414
|
+
});
|
|
385
415
|
closeContextMenu();
|
|
386
|
-
await
|
|
387
|
-
|
|
416
|
+
const copied = await Promise.race([
|
|
417
|
+
copyImageToClipboard(actionSource, agentHostApi?.clipboard),
|
|
418
|
+
new Promise((resolve) => {
|
|
419
|
+
window.setTimeout(() => resolve(false), 5e3);
|
|
420
|
+
})
|
|
421
|
+
]);
|
|
422
|
+
const message = t(
|
|
423
|
+
copied ? "agentHost.agentGui.messageCopied" : "common.copyFailed"
|
|
424
|
+
);
|
|
425
|
+
setCopyStatus({
|
|
426
|
+
busy: false,
|
|
427
|
+
message,
|
|
428
|
+
variant: copied ? "success" : "destructive"
|
|
429
|
+
});
|
|
430
|
+
}, [actionSource, agentHostApi?.clipboard, closeContextMenu, t]);
|
|
388
431
|
const handleCopyImageAction = useCallback2(() => {
|
|
389
432
|
void handleCopyImage().catch(() => void 0);
|
|
390
433
|
}, [handleCopyImage]);
|
|
@@ -393,8 +436,11 @@ function ZoomableImage({
|
|
|
393
436
|
return;
|
|
394
437
|
}
|
|
395
438
|
closeContextMenu();
|
|
396
|
-
downloadImage(
|
|
397
|
-
|
|
439
|
+
downloadImage(
|
|
440
|
+
actionSource,
|
|
441
|
+
resolveImageDownloadName(downloadName, actionSource, alt)
|
|
442
|
+
);
|
|
443
|
+
}, [actionSource, alt, closeContextMenu, downloadName]);
|
|
398
444
|
const actionButtons = hasImageActions ? /* @__PURE__ */ jsx2(
|
|
399
445
|
ImageActionButtons,
|
|
400
446
|
{
|
|
@@ -410,7 +456,9 @@ function ZoomableImage({
|
|
|
410
456
|
}) => {
|
|
411
457
|
const zoomSrc = isValidElement(img) && typeof img.props.src === "string" ? img.props.src : null;
|
|
412
458
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
413
|
-
|
|
459
|
+
actionButtons && img && zoomSrc ? cloneElement(img, {
|
|
460
|
+
onContextMenu: handleContextMenu
|
|
461
|
+
}) : !actionButtons && img && zoomSrc ? /* @__PURE__ */ jsx2(
|
|
414
462
|
ConversationImageContextMenu,
|
|
415
463
|
{
|
|
416
464
|
src: zoomSrc,
|
|
@@ -419,7 +467,37 @@ function ZoomableImage({
|
|
|
419
467
|
children: img
|
|
420
468
|
}
|
|
421
469
|
) : img,
|
|
422
|
-
actionButtons ? /* @__PURE__ */ jsx2("div", { className: "tsh-zoom-dialog__image-actions nodrag tsh-desktop-no-drag", children:
|
|
470
|
+
actionButtons ? /* @__PURE__ */ jsx2("div", { className: "tsh-zoom-dialog__image-actions nodrag tsh-desktop-no-drag", children: /* @__PURE__ */ jsx2(
|
|
471
|
+
ImageActionButtons,
|
|
472
|
+
{
|
|
473
|
+
copyLabel: t("common.copyImage"),
|
|
474
|
+
downloadLabel: t("common.downloadImage"),
|
|
475
|
+
onCopy: handleCopyImageAction,
|
|
476
|
+
onDownload: handleDownloadImage
|
|
477
|
+
}
|
|
478
|
+
) }) : null,
|
|
479
|
+
contextMenuPosition?.inZoomDialog && actionButtons ? /* @__PURE__ */ jsx2(
|
|
480
|
+
"div",
|
|
481
|
+
{
|
|
482
|
+
className: "tsh-image-context-menu nodrag tsh-desktop-no-drag",
|
|
483
|
+
style: {
|
|
484
|
+
left: contextMenuPosition.x,
|
|
485
|
+
top: contextMenuPosition.y
|
|
486
|
+
},
|
|
487
|
+
role: "menu",
|
|
488
|
+
onClick: (event) => event.stopPropagation(),
|
|
489
|
+
children: /* @__PURE__ */ jsx2(
|
|
490
|
+
ImageActionButtons,
|
|
491
|
+
{
|
|
492
|
+
copyLabel: t("common.copyImage"),
|
|
493
|
+
downloadLabel: t("common.downloadImage"),
|
|
494
|
+
itemRole: "menuitem",
|
|
495
|
+
onCopy: handleCopyImageAction,
|
|
496
|
+
onDownload: handleDownloadImage
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
}
|
|
500
|
+
) : null,
|
|
423
501
|
cloneElement(buttonUnzoom, {
|
|
424
502
|
className: cn(
|
|
425
503
|
buttonUnzoom.props.className,
|
|
@@ -442,6 +520,7 @@ function ZoomableImage({
|
|
|
442
520
|
"img",
|
|
443
521
|
{
|
|
444
522
|
...props,
|
|
523
|
+
alt,
|
|
445
524
|
src,
|
|
446
525
|
onContextMenu: hasImageActions ? handleContextMenu : onContextMenu,
|
|
447
526
|
className: cn("nodrag tsh-desktop-no-drag cursor-zoom-in", className)
|
|
@@ -449,7 +528,7 @@ function ZoomableImage({
|
|
|
449
528
|
)
|
|
450
529
|
}
|
|
451
530
|
),
|
|
452
|
-
contextMenuPosition && actionButtons ? /* @__PURE__ */ jsx2(
|
|
531
|
+
contextMenuPosition && !contextMenuPosition.inZoomDialog && actionButtons ? /* @__PURE__ */ jsx2(
|
|
453
532
|
"div",
|
|
454
533
|
{
|
|
455
534
|
className: "tsh-image-context-menu nodrag tsh-desktop-no-drag",
|
|
@@ -470,9 +549,52 @@ function ZoomableImage({
|
|
|
470
549
|
}
|
|
471
550
|
)
|
|
472
551
|
}
|
|
552
|
+
) : null,
|
|
553
|
+
copyStatus ? /* @__PURE__ */ jsx2(
|
|
554
|
+
ImageCopyStatusToast,
|
|
555
|
+
{
|
|
556
|
+
busy: copyStatus.busy,
|
|
557
|
+
message: copyStatus.message,
|
|
558
|
+
variant: copyStatus.variant,
|
|
559
|
+
onOpenChange: (open) => {
|
|
560
|
+
if (!open) {
|
|
561
|
+
setCopyStatus(null);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
473
565
|
) : null
|
|
474
566
|
] });
|
|
475
567
|
}
|
|
568
|
+
function ImageCopyStatusToast({
|
|
569
|
+
busy,
|
|
570
|
+
message,
|
|
571
|
+
onOpenChange,
|
|
572
|
+
variant
|
|
573
|
+
}) {
|
|
574
|
+
return /* @__PURE__ */ jsxs2(ToastProvider, { duration: 1600, swipeDirection: "right", children: [
|
|
575
|
+
/* @__PURE__ */ jsx2(
|
|
576
|
+
ToastRoot,
|
|
577
|
+
{
|
|
578
|
+
open: true,
|
|
579
|
+
anchor: "viewport",
|
|
580
|
+
busy,
|
|
581
|
+
variant,
|
|
582
|
+
onOpenChange,
|
|
583
|
+
children: /* @__PURE__ */ jsx2(ToastTitle, { children: message })
|
|
584
|
+
}
|
|
585
|
+
),
|
|
586
|
+
/* @__PURE__ */ jsx2(
|
|
587
|
+
ToastViewport,
|
|
588
|
+
{
|
|
589
|
+
className: "nodrag tsh-desktop-no-drag",
|
|
590
|
+
style: {
|
|
591
|
+
top: "max(20px, calc(var(--cove-titlebar-reserve, 0px) + 10px))",
|
|
592
|
+
zIndex: 100303
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
)
|
|
596
|
+
] });
|
|
597
|
+
}
|
|
476
598
|
function ImageActionButtons({
|
|
477
599
|
copyLabel,
|
|
478
600
|
downloadLabel,
|
|
@@ -481,17 +603,34 @@ function ImageActionButtons({
|
|
|
481
603
|
onDownload
|
|
482
604
|
}) {
|
|
483
605
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
484
|
-
/* @__PURE__ */ jsxs2(
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
606
|
+
/* @__PURE__ */ jsxs2(
|
|
607
|
+
"button",
|
|
608
|
+
{
|
|
609
|
+
type: "button",
|
|
610
|
+
role: itemRole,
|
|
611
|
+
title: copyLabel,
|
|
612
|
+
onClick: (event) => {
|
|
613
|
+
event.preventDefault();
|
|
614
|
+
event.stopPropagation();
|
|
615
|
+
onCopy();
|
|
616
|
+
},
|
|
617
|
+
children: [
|
|
618
|
+
/* @__PURE__ */ jsx2(CopyIcon, { "aria-hidden": "true", className: "size-4" }),
|
|
619
|
+
/* @__PURE__ */ jsx2("span", { children: copyLabel })
|
|
620
|
+
]
|
|
621
|
+
}
|
|
622
|
+
),
|
|
488
623
|
/* @__PURE__ */ jsxs2(
|
|
489
624
|
"button",
|
|
490
625
|
{
|
|
491
626
|
type: "button",
|
|
492
627
|
role: itemRole,
|
|
493
628
|
title: downloadLabel,
|
|
494
|
-
onClick:
|
|
629
|
+
onClick: (event) => {
|
|
630
|
+
event.preventDefault();
|
|
631
|
+
event.stopPropagation();
|
|
632
|
+
onDownload();
|
|
633
|
+
},
|
|
495
634
|
children: [
|
|
496
635
|
/* @__PURE__ */ jsx2(DownloadIcon, { "aria-hidden": "true", className: "size-4" }),
|
|
497
636
|
/* @__PURE__ */ jsx2("span", { children: downloadLabel })
|
|
@@ -509,14 +648,61 @@ function downloadImage(src, name) {
|
|
|
509
648
|
link.click();
|
|
510
649
|
link.remove();
|
|
511
650
|
}
|
|
512
|
-
function resolveImageDownloadName(name, src) {
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
|
|
651
|
+
function resolveImageDownloadName(name, src, alt) {
|
|
652
|
+
const semanticName = resolveImageNameBase(name) ?? resolveImageNameBase(alt) ?? resolveImageNameBase(src) ?? "image";
|
|
653
|
+
const extension = resolveImageNameExtension(name) ?? resolveImageNameExtension(src) ?? resolveDataImageExtension(src) ?? "png";
|
|
654
|
+
return `${semanticName}-${formatImageDownloadTimestamp(/* @__PURE__ */ new Date())}-${createDownloadRandomSuffix()}.${extension}`;
|
|
655
|
+
}
|
|
656
|
+
function resolveImageNameBase(value) {
|
|
657
|
+
const segment = imageNameSegment(value);
|
|
658
|
+
if (!segment) {
|
|
659
|
+
return null;
|
|
660
|
+
}
|
|
661
|
+
const base = segment.replace(/\.[A-Za-z0-9]{2,8}$/u, "");
|
|
662
|
+
const sanitized = stripControlCharacters(base).replace(/[\\/:*?"<>|#%&{}$!'@+`=]+/gu, "-").replace(/\s+/gu, "-").replace(/-+/gu, "-").replace(/^-|-$/gu, "").slice(0, 80);
|
|
663
|
+
return sanitized || null;
|
|
664
|
+
}
|
|
665
|
+
function stripControlCharacters(value) {
|
|
666
|
+
return Array.from(value).filter((char) => char.charCodeAt(0) >= 32).join("");
|
|
667
|
+
}
|
|
668
|
+
function resolveImageNameExtension(value) {
|
|
669
|
+
const segment = imageNameSegment(value);
|
|
670
|
+
const match = segment?.match(/\.([A-Za-z0-9]{2,8})$/u);
|
|
671
|
+
if (!match?.[1]) {
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
return normalizeImageExtension(match[1]);
|
|
675
|
+
}
|
|
676
|
+
function imageNameSegment(value) {
|
|
677
|
+
const trimmed = value?.trim();
|
|
678
|
+
if (!trimmed) {
|
|
679
|
+
return null;
|
|
680
|
+
}
|
|
681
|
+
const withoutQuery = decodeURIComponentSafe(
|
|
682
|
+
trimmed.split(/[?#]/, 1)[0] ?? ""
|
|
683
|
+
);
|
|
684
|
+
return withoutQuery.split(/[\\/]/).pop()?.trim() || null;
|
|
685
|
+
}
|
|
686
|
+
function resolveDataImageExtension(src) {
|
|
687
|
+
const match = src?.match(/^data:image\/([A-Za-z0-9.+-]+)[;,]/u);
|
|
688
|
+
return match?.[1] ? normalizeImageExtension(match[1]) : null;
|
|
689
|
+
}
|
|
690
|
+
function normalizeImageExtension(extension) {
|
|
691
|
+
const normalized = extension.toLowerCase();
|
|
692
|
+
if (normalized === "jpeg") {
|
|
693
|
+
return "jpg";
|
|
694
|
+
}
|
|
695
|
+
if (normalized === "svg+xml") {
|
|
696
|
+
return "svg";
|
|
516
697
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
698
|
+
return normalized.replace(/[^a-z0-9]/gu, "") || "png";
|
|
699
|
+
}
|
|
700
|
+
function formatImageDownloadTimestamp(date) {
|
|
701
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
702
|
+
return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
|
|
703
|
+
}
|
|
704
|
+
function createDownloadRandomSuffix() {
|
|
705
|
+
return Math.random().toString(36).slice(2, 6).padEnd(4, "0");
|
|
520
706
|
}
|
|
521
707
|
function decodeURIComponentSafe(value) {
|
|
522
708
|
try {
|
|
@@ -1281,7 +1467,7 @@ function AgentMessageMarkdown({
|
|
|
1281
1467
|
maxCharsPerSecond: STREAMING_MARKDOWN_MAX_CHARS_PER_SECOND,
|
|
1282
1468
|
trailingFlushChars: STREAMING_MARKDOWN_TAIL_FLUSH_CHARS
|
|
1283
1469
|
});
|
|
1284
|
-
const stabilizedContent =
|
|
1470
|
+
const stabilizedContent = useMemo(
|
|
1285
1471
|
() => stabilizeStreamingMarkdownTail(visibleContent, {
|
|
1286
1472
|
streaming
|
|
1287
1473
|
}).content,
|
|
@@ -1295,11 +1481,11 @@ function AgentMessageMarkdown({
|
|
|
1295
1481
|
const shouldCollapse = collapsible && isLikelyLongerThanLineLimit(stabilizedContent);
|
|
1296
1482
|
const isCollapsed = shouldCollapse && !isExpanded;
|
|
1297
1483
|
const ContainerTag = inline ? "span" : "div";
|
|
1298
|
-
const contentSignature =
|
|
1484
|
+
const contentSignature = useMemo(
|
|
1299
1485
|
() => hashMarkdownProfilerContent(stabilizedContent),
|
|
1300
1486
|
[stabilizedContent]
|
|
1301
1487
|
);
|
|
1302
|
-
const normalizedContent =
|
|
1488
|
+
const normalizedContent = useMemo(
|
|
1303
1489
|
() => linkBareLocalAbsolutePaths(
|
|
1304
1490
|
normalizeMentionMarkdownLinks(
|
|
1305
1491
|
normalizePlainIssueMentionTitle ? normalizePlainIssueMentionTitleContent(
|
|
@@ -1345,7 +1531,7 @@ function AgentMessageMarkdown({
|
|
|
1345
1531
|
},
|
|
1346
1532
|
[handleLinkClick]
|
|
1347
1533
|
);
|
|
1348
|
-
const markdownComponents =
|
|
1534
|
+
const markdownComponents = useMemo(
|
|
1349
1535
|
() => ({
|
|
1350
1536
|
a: (props) => /* @__PURE__ */ jsx3(
|
|
1351
1537
|
MarkdownLink,
|
|
@@ -1444,7 +1630,7 @@ function StreamingMarkdownBlocks({
|
|
|
1444
1630
|
content,
|
|
1445
1631
|
components
|
|
1446
1632
|
}) {
|
|
1447
|
-
const blocks =
|
|
1633
|
+
const blocks = useMemo(
|
|
1448
1634
|
() => splitStreamingMarkdownBlocks(content),
|
|
1449
1635
|
[content]
|
|
1450
1636
|
);
|
|
@@ -3018,11 +3204,10 @@ export {
|
|
|
3018
3204
|
resolveWorkspaceFilePathCandidate,
|
|
3019
3205
|
resolveWorkspaceFileLinkAction,
|
|
3020
3206
|
resolveWorkspaceLinkAction,
|
|
3021
|
-
ConversationImageContextMenu,
|
|
3022
3207
|
ZoomableImage,
|
|
3023
3208
|
AgentMessageMarkdown,
|
|
3024
3209
|
AgentGUIConversation_styles_default,
|
|
3025
3210
|
CustomScrollArea,
|
|
3026
3211
|
MessageSquareMoreIcon
|
|
3027
3212
|
};
|
|
3028
|
-
//# sourceMappingURL=chunk-
|
|
3213
|
+
//# sourceMappingURL=chunk-OLZP2EFK.js.map
|