@tangle-network/sandbox-ui 2.0.22 → 3.0.1
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 +6 -0
- package/dist/{AgentTree-KO1TJXBq.js → AgentTree-CJRVpgPq.js} +8 -8
- package/dist/ResearchReport-CSNpZ-pj.js +2063 -0
- package/dist/ResearchReport-CmFYqNVY.d.ts +36 -0
- package/dist/{chat-BU39pb2j.js → chat-BrlLa4rg.js} +2 -2
- package/dist/chat.d.ts +1 -1
- package/dist/chat.js +1 -1
- package/dist/globals.css +106 -297
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +2 -2
- package/dist/{index-Due7tY0w.d.ts → index-5zOVKgDT.d.ts} +2 -2
- package/dist/{index-D2_4ONCz.d.ts → index-DpzFSqjG.d.ts} +1 -7
- package/dist/{index-BoKSR0s9.d.ts → index-YU_b9xCK.d.ts} +2 -2
- package/dist/index.d.ts +6 -6
- package/dist/index.js +9 -9
- package/dist/record/ResearchReport.d.ts +2 -0
- package/dist/record/ResearchReport.js +1 -0
- package/dist/{record-BGcR48YY.js → record-Ct_MZeZC.js} +1 -1
- package/dist/record.d.ts +2 -35
- package/dist/record.js +2 -2061
- package/dist/report-viewer.js +130 -90
- package/dist/run/live.js +14 -33
- package/dist/run/record.js +2 -2
- package/dist/run.d.ts +2 -2
- package/dist/run.js +5 -5
- package/dist/runtime-viewer/{AgentGraphCanvas-DDvaU9Rg-DlNZxJ20.js → AgentGraphCanvas-DGq7_u8--WPFPgd72.js} +2254 -2282
- package/dist/runtime-viewer/latest-events-CRq9sGkK-YFXUh9qO.js +9586 -0
- package/dist/runtime-viewer/{sandbox-ui-CUj4Q1P_.css → sandbox-ui-BEziPi7D.css} +1 -1
- package/dist/styles.css +107 -298
- package/dist/tailwind.css +72 -13
- package/dist/{trace-workspace-DkakKRLV.js → trace-workspace-BiJbv9WQ.js} +2 -2
- package/dist/use-follow-tail-Ht7fZGQQ.js +1 -0
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +1 -1
- package/dist/{workspace--GvnZNpH.js → workspace-CAdAoNmW.js} +11 -17
- package/dist/workspace-viewer.js +10146 -12805
- package/dist/workspace.d.ts +1 -1
- package/dist/workspace.js +1 -1
- package/package.json +11 -7
- package/dist/runtime-viewer/latest-events-CabhXynX-Dp_vs0Px.js +0 -3671
- package/dist/use-follow-tail-Ckx5ZSV2.js +0 -1
package/dist/tailwind.css
CHANGED
|
@@ -904,6 +904,7 @@
|
|
|
904
904
|
--default-font-family: var(--font-sans);
|
|
905
905
|
--default-mono-font-family: var(--font-mono);
|
|
906
906
|
--radius-full: 999px;
|
|
907
|
+
--shadow-card: 0 1px 2px hsl(var(--shadow-color) / 0.3);
|
|
907
908
|
}
|
|
908
909
|
}
|
|
909
910
|
@layer utilities.agent-graph-base {
|
|
@@ -1096,6 +1097,9 @@
|
|
|
1096
1097
|
.left-3, :scope:is(.left-3) {
|
|
1097
1098
|
left: calc(var(--spacing) * 3);
|
|
1098
1099
|
}
|
|
1100
|
+
.z-50, :scope:is(.z-50) {
|
|
1101
|
+
z-index: 50;
|
|
1102
|
+
}
|
|
1099
1103
|
.container, :scope:is(.container) {
|
|
1100
1104
|
width: 100%;
|
|
1101
1105
|
@media (width >= 40rem) {
|
|
@@ -1174,12 +1178,21 @@
|
|
|
1174
1178
|
.w-8, :scope:is(.w-8) {
|
|
1175
1179
|
width: calc(var(--spacing) * 8);
|
|
1176
1180
|
}
|
|
1181
|
+
.w-64, :scope:is(.w-64) {
|
|
1182
|
+
width: calc(var(--spacing) * 64);
|
|
1183
|
+
}
|
|
1184
|
+
.w-72, :scope:is(.w-72) {
|
|
1185
|
+
width: calc(var(--spacing) * 72);
|
|
1186
|
+
}
|
|
1177
1187
|
.w-full, :scope:is(.w-full) {
|
|
1178
1188
|
width: 100%;
|
|
1179
1189
|
}
|
|
1180
1190
|
.max-w-64, :scope:is(.max-w-64) {
|
|
1181
1191
|
max-width: calc(var(--spacing) * 64);
|
|
1182
1192
|
}
|
|
1193
|
+
.max-w-\[calc\(100vw-2rem\)\], :scope:is(.max-w-\[calc\(100vw-2rem\)\]) {
|
|
1194
|
+
max-width: calc(100vw - 2rem);
|
|
1195
|
+
}
|
|
1183
1196
|
.\!min-w-0, :scope:is(.\!min-w-0) {
|
|
1184
1197
|
min-width: 0px !important;
|
|
1185
1198
|
}
|
|
@@ -1192,6 +1205,9 @@
|
|
|
1192
1205
|
.shrink-0, :scope:is(.shrink-0) {
|
|
1193
1206
|
flex-shrink: 0;
|
|
1194
1207
|
}
|
|
1208
|
+
.origin-\(--radix-popover-content-transform-origin\), :scope:is(.origin-\(--radix-popover-content-transform-origin\)) {
|
|
1209
|
+
transform-origin: var(--radix-popover-content-transform-origin);
|
|
1210
|
+
}
|
|
1195
1211
|
.-rotate-90, :scope:is(.-rotate-90) {
|
|
1196
1212
|
rotate: calc(90deg * -1);
|
|
1197
1213
|
}
|
|
@@ -1201,6 +1217,9 @@
|
|
|
1201
1217
|
.animate-\[tangle-breathe_var\(--motion-ambient\)_infinite\], :scope:is(.animate-\[tangle-breathe_var\(--motion-ambient\)_infinite\]) {
|
|
1202
1218
|
animation: tangle-breathe var(--motion-ambient) infinite;
|
|
1203
1219
|
}
|
|
1220
|
+
.cursor-pointer, :scope:is(.cursor-pointer) {
|
|
1221
|
+
cursor: pointer;
|
|
1222
|
+
}
|
|
1204
1223
|
.grid-cols-\[minmax\(0\,1fr\)_auto\],:scope:is(.grid-cols-\[minmax\(0\,1fr\)_auto\]) {
|
|
1205
1224
|
grid-template-columns: minmax(0,1fr) auto;
|
|
1206
1225
|
}
|
|
@@ -1332,6 +1351,9 @@
|
|
|
1332
1351
|
.pt-3, :scope:is(.pt-3) {
|
|
1333
1352
|
padding-top: calc(var(--spacing) * 3);
|
|
1334
1353
|
}
|
|
1354
|
+
.pb-2, :scope:is(.pb-2) {
|
|
1355
|
+
padding-bottom: calc(var(--spacing) * 2);
|
|
1356
|
+
}
|
|
1335
1357
|
.text-center, :scope:is(.text-center) {
|
|
1336
1358
|
text-align: center;
|
|
1337
1359
|
}
|
|
@@ -1363,6 +1385,10 @@
|
|
|
1363
1385
|
--tw-leading: 18px;
|
|
1364
1386
|
line-height: 18px;
|
|
1365
1387
|
}
|
|
1388
|
+
.leading-none, :scope:is(.leading-none) {
|
|
1389
|
+
--tw-leading: 1;
|
|
1390
|
+
line-height: 1;
|
|
1391
|
+
}
|
|
1366
1392
|
.font-medium, :scope:is(.font-medium) {
|
|
1367
1393
|
--tw-font-weight: var(--font-weight-medium);
|
|
1368
1394
|
font-weight: var(--font-weight-medium);
|
|
@@ -1400,9 +1426,20 @@
|
|
|
1400
1426
|
--tw-numeric-spacing: tabular-nums;
|
|
1401
1427
|
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
1402
1428
|
}
|
|
1429
|
+
.underline-offset-4, :scope:is(.underline-offset-4) {
|
|
1430
|
+
text-underline-offset: 4px;
|
|
1431
|
+
}
|
|
1403
1432
|
.opacity-0, :scope:is(.opacity-0) {
|
|
1404
1433
|
opacity: 0%;
|
|
1405
1434
|
}
|
|
1435
|
+
.shadow, :scope:is(.shadow) {
|
|
1436
|
+
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
1437
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
1438
|
+
}
|
|
1439
|
+
.shadow-\[var\(--shadow-card\)\], :scope:is(.shadow-\[var\(--shadow-card\)\]) {
|
|
1440
|
+
--tw-shadow: var(--shadow-card);
|
|
1441
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
1442
|
+
}
|
|
1406
1443
|
.shadow-sm, :scope:is(.shadow-sm) {
|
|
1407
1444
|
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
1408
1445
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
@@ -1411,6 +1448,18 @@
|
|
|
1411
1448
|
--tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
1412
1449
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
1413
1450
|
}
|
|
1451
|
+
.outline-hidden, :scope:is(.outline-hidden) {
|
|
1452
|
+
--tw-outline-style: none;
|
|
1453
|
+
outline-style: none;
|
|
1454
|
+
@media (forced-colors: active) {
|
|
1455
|
+
outline: 2px solid transparent;
|
|
1456
|
+
outline-offset: 2px;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
.blur, :scope:is(.blur) {
|
|
1460
|
+
--tw-blur: blur(8px);
|
|
1461
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
1462
|
+
}
|
|
1414
1463
|
.grayscale, :scope:is(.grayscale) {
|
|
1415
1464
|
--tw-grayscale: grayscale(100%);
|
|
1416
1465
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
@@ -1437,6 +1486,9 @@
|
|
|
1437
1486
|
.hover\:text-foreground:hover, :scope:is(.hover\:text-foreground:hover) {
|
|
1438
1487
|
color: hsl(var(--foreground));
|
|
1439
1488
|
}
|
|
1489
|
+
.hover\:underline:hover, :scope:is(.hover\:underline:hover) {
|
|
1490
|
+
text-decoration-line: underline;
|
|
1491
|
+
}
|
|
1440
1492
|
.hover\:grayscale-0:hover, :scope:is(.hover\:grayscale-0:hover) {
|
|
1441
1493
|
--tw-grayscale: grayscale(0%);
|
|
1442
1494
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
@@ -1452,7 +1504,22 @@
|
|
|
1452
1504
|
.aria-pressed\:bg-muted[aria-pressed="true"], :scope:is(.aria-pressed\:bg-muted[aria-pressed="true"]) {
|
|
1453
1505
|
background-color: hsl(var(--muted));
|
|
1454
1506
|
}
|
|
1507
|
+
.data-\[state\=closed\]\:\[animation\:tangle-surface-absent_var\(--motion-dismiss\)_both\][data-state="closed"], :scope:is(.data-\[state\=closed\]\:\[animation\:tangle-surface-absent_var\(--motion-dismiss\)_both\][data-state="closed"]) {
|
|
1508
|
+
animation: tangle-surface-absent var(--motion-dismiss) both;
|
|
1509
|
+
}
|
|
1510
|
+
.data-\[state\=delayed-open\]\:\[animation\:tangle-surface-present_var\(--motion-surface\)_both\][data-state="delayed-open"], :scope:is(.data-\[state\=delayed-open\]\:\[animation\:tangle-surface-present_var\(--motion-surface\)_both\][data-state="delayed-open"]) {
|
|
1511
|
+
animation: tangle-surface-present var(--motion-surface) both;
|
|
1512
|
+
}
|
|
1513
|
+
.data-\[state\=instant-open\]\:\[animation\:tangle-surface-present_var\(--motion-surface\)_both\][data-state="instant-open"], :scope:is(.data-\[state\=instant-open\]\:\[animation\:tangle-surface-present_var\(--motion-surface\)_both\][data-state="instant-open"]) {
|
|
1514
|
+
animation: tangle-surface-present var(--motion-surface) both;
|
|
1515
|
+
}
|
|
1516
|
+
.data-\[state\=open\]\:\[animation\:tangle-surface-present_var\(--motion-surface\)_both\][data-state="open"], :scope:is(.data-\[state\=open\]\:\[animation\:tangle-surface-present_var\(--motion-surface\)_both\][data-state="open"]) {
|
|
1517
|
+
animation: tangle-surface-present var(--motion-surface) both;
|
|
1518
|
+
}
|
|
1455
1519
|
@media (prefers-reduced-motion: reduce) {
|
|
1520
|
+
.motion-reduce\:animate-none\!, :scope:is(.motion-reduce\:animate-none\!) {
|
|
1521
|
+
animation: none !important;
|
|
1522
|
+
}
|
|
1456
1523
|
.motion-reduce\:transition-none, :scope:is(.motion-reduce\:transition-none) {
|
|
1457
1524
|
transition-property: none;
|
|
1458
1525
|
}
|
|
@@ -2707,6 +2774,8 @@ svg.react-flow__connectionline {
|
|
|
2707
2774
|
}
|
|
2708
2775
|
}
|
|
2709
2776
|
@keyframes tangle-intro-enter { from { opacity: 0; transform: translateY(var(--arrive-distance)); } to { opacity: 1; transform: none; } }
|
|
2777
|
+
@keyframes tangle-surface-present { from { --tangle-presence: 0; } to { --tangle-presence: 1; } }
|
|
2778
|
+
@keyframes tangle-surface-absent { from { --tangle-presence: 1; } to { --tangle-presence: 0; } }
|
|
2710
2779
|
|
|
2711
2780
|
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2712
2781
|
@layer theme, base, ar-base, components, utilities;
|
|
@@ -5725,9 +5794,6 @@ button.tgc-count-label {
|
|
|
5725
5794
|
.fw-root .fw-link-up::before {
|
|
5726
5795
|
right: -3.25px;
|
|
5727
5796
|
}
|
|
5728
|
-
.fw-root .fw-card-anchor {
|
|
5729
|
-
display: contents;
|
|
5730
|
-
}
|
|
5731
5797
|
.fw-root .fw-seg-alt {
|
|
5732
5798
|
filter: brightness(.78);
|
|
5733
5799
|
}
|
|
@@ -5752,9 +5818,8 @@ button.tgc-count-label {
|
|
|
5752
5818
|
box-shadow: 0 0 0 3px var(--fw-surface);
|
|
5753
5819
|
}
|
|
5754
5820
|
.fw-root .fw-card {
|
|
5755
|
-
position:
|
|
5756
|
-
|
|
5757
|
-
width: min(320px, calc(100% - 16px));
|
|
5821
|
+
position: relative;
|
|
5822
|
+
width: 100%;
|
|
5758
5823
|
max-height: min(60vh, 560px);
|
|
5759
5824
|
overflow-y: auto;
|
|
5760
5825
|
overscroll-behavior: contain;
|
|
@@ -5763,13 +5828,7 @@ button.tgc-count-label {
|
|
|
5763
5828
|
background: var(--fw-raised);
|
|
5764
5829
|
border: 1px solid var(--fw-border);
|
|
5765
5830
|
box-shadow: var(--shadow-dropdown);
|
|
5766
|
-
transition:
|
|
5767
|
-
}
|
|
5768
|
-
.fw-root .fw-card[role="tooltip"] {
|
|
5769
|
-
pointer-events: none;
|
|
5770
|
-
}
|
|
5771
|
-
.fw-root .fw-card-above .fw-card {
|
|
5772
|
-
transform: translateY(-100%);
|
|
5831
|
+
transition: opacity var(--motion-control);
|
|
5773
5832
|
}
|
|
5774
5833
|
.fw-root .fw-card-agent {
|
|
5775
5834
|
display: flex;
|
|
@@ -2,7 +2,7 @@ import { t as cn } from "./utils-BER_bdgE.js";
|
|
|
2
2
|
import { i as modelBrandFor, t as ModelBrandStack } from "./model-brand-BQlarCIo.js";
|
|
3
3
|
import { t as ProviderIcon } from "./provider-logo-CPKRPHcS.js";
|
|
4
4
|
import { t as AgentGraph$1 } from "./AgentGraph-BGWx9hhS.js";
|
|
5
|
-
import { t as useFollowTail } from "./use-follow-tail-
|
|
5
|
+
import { t as useFollowTail } from "./use-follow-tail-Ht7fZGQQ.js";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { useMemo, useReducer, useRef, useState } from "react";
|
|
8
8
|
import { X } from "lucide-react";
|
|
@@ -314,7 +314,7 @@ function agentGraphAt(spans, byId, at, epoch, cards, extraEdges = []) {
|
|
|
314
314
|
id: span.id,
|
|
315
315
|
label: card?.label ?? span.name,
|
|
316
316
|
model: card?.model ?? span.detail,
|
|
317
|
-
status: at === null && card?.status ? card.status : state
|
|
317
|
+
status: at === null && card?.status ? card.status : state,
|
|
318
318
|
costUsd: at === null ? card?.costUsd ?? span.costUsd : span.endMs <= at ? span.costUsd : void 0,
|
|
319
319
|
startedAt: epoch == null || !Number.isFinite(epoch) ? at === null ? card?.startedAt : void 0 : epoch + span.startMs,
|
|
320
320
|
...timing,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useFollowTail as t } from "@tangle-network/ui/hooks/use-follow-tail";
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, plainTextFromMarkdown, timeAgo, truncateText } from "@tangle-network/ui/utils";
|
|
2
|
-
export { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, plainTextFromMarkdown, timeAgo, truncateText };
|
|
1
|
+
import { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatAxisDuration, formatBytes, formatClock, formatCompact, formatCost, formatCount, formatDuration, formatSpanDuration, formatUptime, formatUtcTime, getToolCategory, getToolDisplayMetadata, getToolErrorText, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, plainTextFromMarkdown, timeAgo, truncateText } from "@tangle-network/ui/utils";
|
|
2
|
+
export { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatAxisDuration, formatBytes, formatClock, formatCompact, formatCost, formatCount, formatDuration, formatSpanDuration, formatUptime, formatUtcTime, getToolCategory, getToolDisplayMetadata, getToolErrorText, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, plainTextFromMarkdown, timeAgo, truncateText };
|
package/dist/utils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, plainTextFromMarkdown, timeAgo, truncateText } from "@tangle-network/ui/utils";
|
|
1
|
+
export { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatAxisDuration, formatBytes, formatClock, formatCompact, formatCost, formatCount, formatDuration, formatSpanDuration, formatUptime, formatUtcTime, getToolCategory, getToolDisplayMetadata, getToolErrorText, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, plainTextFromMarkdown, timeAgo, truncateText } from "@tangle-network/ui/utils";
|
|
@@ -1091,27 +1091,21 @@ function RuntimePane({ title = "Runtime", subtitle = "Session state, execution o
|
|
|
1091
1091
|
const MINUTE = 6e4;
|
|
1092
1092
|
const HOUR = 60 * MINUTE;
|
|
1093
1093
|
const DAY = 24 * HOUR;
|
|
1094
|
-
const
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
*/
|
|
1094
|
+
const UNITS = [
|
|
1095
|
+
["y", 365 * DAY],
|
|
1096
|
+
["mo", 30 * DAY],
|
|
1097
|
+
["w", 7 * DAY],
|
|
1098
|
+
["d", DAY],
|
|
1099
|
+
["h", HOUR],
|
|
1100
|
+
["m", MINUTE]
|
|
1101
|
+
];
|
|
1102
|
+
/** Compact age without an ago suffix; invalid dates are empty and future dates read now. */
|
|
1104
1103
|
function formatRelativeAge(date, now = Date.now()) {
|
|
1105
1104
|
const timestamp = date instanceof Date ? date.getTime() : new Date(date).getTime();
|
|
1106
1105
|
if (Number.isNaN(timestamp)) return "";
|
|
1107
1106
|
const elapsed = Math.max(0, now - timestamp);
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
if (elapsed < DAY) return `${Math.floor(elapsed / HOUR)}h`;
|
|
1111
|
-
if (elapsed < WEEK) return `${Math.floor(elapsed / DAY)}d`;
|
|
1112
|
-
if (elapsed < MONTH) return `${Math.floor(elapsed / WEEK)}w`;
|
|
1113
|
-
if (elapsed < YEAR) return `${Math.floor(elapsed / MONTH)}mo`;
|
|
1114
|
-
return `${Math.floor(elapsed / YEAR)}y`;
|
|
1107
|
+
const unit = UNITS.find(([, duration]) => !(elapsed < duration));
|
|
1108
|
+
return unit ? `${Math.floor(elapsed / unit[1])}${unit[0]}` : "now";
|
|
1115
1109
|
}
|
|
1116
1110
|
// src/workspace/session-optimistic.ts
|
|
1117
1111
|
/**
|