@tangle-network/sandbox-ui 0.3.7 → 0.3.10
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/dist/active-sessions-store-CeOmXgv5.d.ts +85 -0
- package/dist/artifact-pane-Bh45Ssco.d.ts +24 -0
- package/dist/{chat-container-B34uj-J1.d.ts → chat-container-Dn1jWtWo.d.ts} +15 -3
- package/dist/chat.d.ts +16 -4
- package/dist/chat.js +2 -2
- package/dist/{chunk-PXRPYAMM.js → chunk-6H3EFUUC.js} +96 -74
- package/dist/{chunk-WUR652Y3.js → chunk-72UEKFZ2.js} +113 -89
- package/dist/{chunk-5LV6DZZF.js → chunk-FOQTE67I.js} +278 -21
- package/dist/chunk-MGCVTFKB.js +10910 -0
- package/dist/chunk-OEX7NZE3.js +321 -0
- package/dist/chunk-Q56BYXQF.js +61 -0
- package/dist/{chunk-ZSNOGOUX.js → chunk-RQOX5JRR.js} +541 -76
- package/dist/{chunk-PDV7W4NY.js → chunk-SULQQJPB.js} +1 -56
- package/dist/chunk-W4LM3QYZ.js +54 -0
- package/dist/{chunk-JF6E2DS5.js → chunk-ZYGWTIWO.js} +171 -155
- package/dist/document-editor-pane-Bk-9MQmw.d.ts +116 -0
- package/dist/document-editor-pane-GRIQOJHB.js +11 -0
- package/dist/editor.d.ts +7 -84
- package/dist/editor.js +18 -699
- package/dist/{expanded-tool-detail-BDi_h_dZ.d.ts → expanded-tool-detail-DM5M_T9h.d.ts} +10 -2
- package/dist/{file-tabs-CmaoDVBI.d.ts → file-tabs-BLfxfmAH.d.ts} +1 -22
- package/dist/files.d.ts +25 -3
- package/dist/files.js +2 -1
- package/dist/hooks.d.ts +3 -1
- package/dist/hooks.js +6 -1
- package/dist/index.d.ts +12 -6
- package/dist/index.js +21 -8
- package/dist/pages.js +4 -2
- package/dist/primitives.js +4 -2
- package/dist/run.d.ts +1 -1
- package/dist/run.js +1 -1
- package/dist/sdk-hooks.d.ts +32 -1
- package/dist/sdk-hooks.js +6 -1
- package/dist/stores.d.ts +1 -0
- package/dist/stores.js +60 -1
- package/dist/types.d.ts +2 -0
- package/dist/workspace.d.ts +84 -6
- package/dist/workspace.js +10 -4
- package/package.json +17 -6
|
@@ -759,7 +759,8 @@ var InlineToolItem = memo9(
|
|
|
759
759
|
renderToolDetail,
|
|
760
760
|
groupPosition = "single",
|
|
761
761
|
className,
|
|
762
|
-
contentClassName
|
|
762
|
+
contentClassName,
|
|
763
|
+
actions
|
|
763
764
|
}) => {
|
|
764
765
|
const [open, setOpen] = useState3(false);
|
|
765
766
|
const meta = getToolDisplayMetadata(part);
|
|
@@ -780,49 +781,59 @@ var InlineToolItem = memo9(
|
|
|
780
781
|
last: "rounded-t-[var(--radius-sm)] rounded-b-[var(--radius-lg)]"
|
|
781
782
|
}[groupPosition];
|
|
782
783
|
return /* @__PURE__ */ jsxs10(Collapsible.Root, { open, onOpenChange: setOpen, children: [
|
|
783
|
-
/* @__PURE__ */
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
/* @__PURE__ */
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
/* @__PURE__ */ jsxs10("div", { className: "
|
|
810
|
-
/* @__PURE__ */
|
|
811
|
-
|
|
812
|
-
|
|
784
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-2", children: [
|
|
785
|
+
/* @__PURE__ */ jsx11(Collapsible.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs10(
|
|
786
|
+
"button",
|
|
787
|
+
{
|
|
788
|
+
className: cn(
|
|
789
|
+
"w-full border text-left transition-colors",
|
|
790
|
+
"border-[var(--border-subtle)] bg-[var(--bg-card)] hover:border-[var(--border-accent-hover)] hover:bg-[var(--bg-hover)]/35",
|
|
791
|
+
open && "border-[var(--border-accent)] bg-[var(--bg-hover)]/30",
|
|
792
|
+
shapeClass,
|
|
793
|
+
className
|
|
794
|
+
),
|
|
795
|
+
children: [
|
|
796
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-3 px-3 py-3", children: [
|
|
797
|
+
/* @__PURE__ */ jsx11(
|
|
798
|
+
"div",
|
|
799
|
+
{
|
|
800
|
+
className: cn(
|
|
801
|
+
"flex h-8 w-8 shrink-0 items-center justify-center rounded-[var(--radius-md)] border",
|
|
802
|
+
isRunning && "border-[var(--border-accent)] bg-[var(--brand-cool)]/12 text-[var(--brand-cool)]",
|
|
803
|
+
isComplete && "border-emerald-500/30 bg-emerald-500/12 text-emerald-200",
|
|
804
|
+
isError && "border-red-500/30 bg-red-500/10 text-red-200",
|
|
805
|
+
!isRunning && !isComplete && !isError && "border-[var(--border-subtle)] bg-[var(--bg-section)] text-[var(--text-muted)]"
|
|
806
|
+
),
|
|
807
|
+
children: isRunning ? /* @__PURE__ */ jsx11(Loader24, { className: "h-4 w-4 animate-spin" }) : isComplete ? /* @__PURE__ */ jsx11(CheckCircle2, { className: "h-4 w-4" }) : isError ? /* @__PURE__ */ jsx11(AlertCircle2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx11(DefaultIcon, { className: "h-4 w-4" })
|
|
808
|
+
}
|
|
809
|
+
),
|
|
810
|
+
/* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1", children: [
|
|
811
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
|
|
812
|
+
/* @__PURE__ */ jsx11("span", { className: "truncate text-sm font-medium text-[var(--text-primary)]", children: meta.title }),
|
|
813
|
+
isError ? /* @__PURE__ */ jsx11("span", { className: "rounded-full border border-red-500/30 bg-red-500/10 px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-red-200", children: "Failed" }) : null,
|
|
814
|
+
isRunning ? /* @__PURE__ */ jsx11("span", { className: "rounded-full border border-[var(--border-accent)] bg-[var(--brand-cool)]/10 px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[var(--brand-cool)]", children: "Running" }) : null
|
|
815
|
+
] }),
|
|
816
|
+
meta.description ? /* @__PURE__ */ jsx11("div", { className: "mt-1 truncate text-xs font-[var(--font-mono)] text-[var(--text-muted)]", children: meta.description }) : null
|
|
813
817
|
] }),
|
|
814
|
-
|
|
818
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
819
|
+
isRunning && startTime ? /* @__PURE__ */ jsx11(LiveDuration, { startTime }) : null,
|
|
820
|
+
!isRunning && durationMs != null ? /* @__PURE__ */ jsx11("span", { className: "rounded-full border border-[var(--border-subtle)] bg-[var(--bg-section)] px-2 py-0.5 text-[11px] font-[var(--font-mono)] text-[var(--text-muted)]", children: formatDuration(durationMs) }) : null,
|
|
821
|
+
open ? /* @__PURE__ */ jsx11(ChevronDown2, { className: "h-3.5 w-3.5 text-[var(--text-muted)]" }) : /* @__PURE__ */ jsx11(ChevronRight2, { className: "h-3.5 w-3.5 text-[var(--text-muted)]" })
|
|
822
|
+
] })
|
|
815
823
|
] }),
|
|
816
|
-
/* @__PURE__ */
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
824
|
+
errorText && !open ? /* @__PURE__ */ jsx11("div", { className: "border-t border-[var(--border-subtle)] px-3 py-2 text-xs text-red-200", children: errorText }) : null
|
|
825
|
+
]
|
|
826
|
+
}
|
|
827
|
+
) }),
|
|
828
|
+
actions ? /* @__PURE__ */ jsx11(
|
|
829
|
+
"div",
|
|
830
|
+
{
|
|
831
|
+
className: "flex shrink-0 flex-wrap items-center justify-end gap-1.5 pt-1",
|
|
832
|
+
onClick: (event) => event.stopPropagation(),
|
|
833
|
+
children: actions
|
|
834
|
+
}
|
|
835
|
+
) : null
|
|
836
|
+
] }),
|
|
826
837
|
/* @__PURE__ */ jsx11(Collapsible.Content, { className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp", children: /* @__PURE__ */ jsx11("div", { className: cn("mt-2 pl-4", contentClassName), children: renderToolDetail?.(part) ?? /* @__PURE__ */ jsx11(ExpandedToolDetail, { part }) }) })
|
|
827
838
|
] });
|
|
828
839
|
}
|
|
@@ -967,14 +978,17 @@ function CategoryBadges({ categories }) {
|
|
|
967
978
|
[categories]
|
|
968
979
|
);
|
|
969
980
|
if (sorted.length === 0) return null;
|
|
970
|
-
return /* @__PURE__ */ jsx13("div", { className: "flex items-center gap-1", children: sorted.map((cat) => {
|
|
981
|
+
return /* @__PURE__ */ jsx13("div", { className: "flex items-center gap-1.5", children: sorted.map((cat) => {
|
|
971
982
|
const Icon = CATEGORY_ICON_MAP[cat] ?? Settings2;
|
|
972
|
-
return /* @__PURE__ */
|
|
983
|
+
return /* @__PURE__ */ jsxs12(
|
|
973
984
|
"span",
|
|
974
985
|
{
|
|
975
986
|
title: cat,
|
|
976
|
-
className: "flex h-
|
|
977
|
-
children:
|
|
987
|
+
className: "flex h-7 items-center gap-1 rounded-full border border-[var(--border-subtle)] bg-[linear-gradient(180deg,rgba(255,255,255,0.04),transparent)] px-2 text-[11px] uppercase tracking-[0.12em] text-[var(--text-muted)]",
|
|
988
|
+
children: [
|
|
989
|
+
/* @__PURE__ */ jsx13(Icon, { className: "h-3.5 w-3.5" }),
|
|
990
|
+
/* @__PURE__ */ jsx13("span", { children: cat })
|
|
991
|
+
]
|
|
978
992
|
},
|
|
979
993
|
cat
|
|
980
994
|
);
|
|
@@ -1010,7 +1024,9 @@ var RunGroup = memo11(
|
|
|
1010
1024
|
collapsed,
|
|
1011
1025
|
onToggle,
|
|
1012
1026
|
branding = DEFAULT_BRANDING,
|
|
1013
|
-
renderToolDetail
|
|
1027
|
+
renderToolDetail,
|
|
1028
|
+
headerActions,
|
|
1029
|
+
renderToolActions
|
|
1014
1030
|
}) => {
|
|
1015
1031
|
const allParts = useMemo5(() => {
|
|
1016
1032
|
const parts = [];
|
|
@@ -1033,53 +1049,56 @@ var RunGroup = memo11(
|
|
|
1033
1049
|
return null;
|
|
1034
1050
|
}
|
|
1035
1051
|
return /* @__PURE__ */ jsxs12(Collapsible3.Root, { open: !collapsed, onOpenChange: () => onToggle(), children: [
|
|
1036
|
-
/* @__PURE__ */
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
1046
|
-
/* @__PURE__ */ jsx13(
|
|
1047
|
-
"div",
|
|
1048
|
-
{
|
|
1049
|
-
className: cn(
|
|
1050
|
-
"flex h-10 w-10 shrink-0 items-center justify-center rounded-[var(--radius-lg)] border bg-[var(--bg-section)]",
|
|
1051
|
-
branding.borderClass
|
|
1052
|
-
),
|
|
1053
|
-
children: /* @__PURE__ */ jsx13(Bot2, { className: cn("h-4 w-4", branding.accentClass) })
|
|
1054
|
-
}
|
|
1052
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3", children: [
|
|
1053
|
+
/* @__PURE__ */ jsx13(Collapsible3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx13(
|
|
1054
|
+
"button",
|
|
1055
|
+
{
|
|
1056
|
+
className: cn(
|
|
1057
|
+
"w-full rounded-[calc(var(--radius-xl)+2px)] border px-4 py-3.5 text-left transition-colors shadow-[var(--shadow-card)] backdrop-blur-sm",
|
|
1058
|
+
"bg-[radial-gradient(circle_at_top_left,rgba(96,165,250,0.12),transparent_34%),linear-gradient(180deg,rgba(255,255,255,0.03),transparent_30%),var(--bg-card)] hover:bg-[radial-gradient(circle_at_top_left,rgba(96,165,250,0.16),transparent_34%),linear-gradient(180deg,rgba(255,255,255,0.04),transparent_30%),var(--bg-card)]",
|
|
1059
|
+
collapsed ? branding.borderClass : "border-[var(--border-subtle)]",
|
|
1060
|
+
branding.bgClass
|
|
1055
1061
|
),
|
|
1056
|
-
/* @__PURE__ */ jsxs12("div", { className: "
|
|
1057
|
-
/* @__PURE__ */
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
"
|
|
1062
|
+
children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
1063
|
+
/* @__PURE__ */ jsx13(
|
|
1064
|
+
"div",
|
|
1065
|
+
{
|
|
1066
|
+
className: cn(
|
|
1067
|
+
"flex h-11 w-11 shrink-0 items-center justify-center rounded-[calc(var(--radius-lg)+2px)] border bg-[linear-gradient(135deg,rgba(82,164,255,0.22),rgba(82,164,255,0.06))] shadow-[var(--shadow-accent)]",
|
|
1068
|
+
branding.borderClass
|
|
1069
|
+
),
|
|
1070
|
+
children: /* @__PURE__ */ jsx13(Bot2, { className: cn("h-4 w-4", branding.accentClass) })
|
|
1071
|
+
}
|
|
1072
|
+
),
|
|
1073
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
1074
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1075
|
+
/* @__PURE__ */ jsx13("span", { className: cn("text-sm font-semibold tracking-[0.01em]", branding.textClass), children: branding.label }),
|
|
1076
|
+
isStreaming ? /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1 rounded-full border border-[var(--border-accent)] bg-[linear-gradient(135deg,rgba(82,164,255,0.22),rgba(82,164,255,0.08))] px-2.5 py-0.5 text-[11px] font-semibold uppercase tracking-[0.08em] text-[var(--brand-cool)]", children: [
|
|
1077
|
+
/* @__PURE__ */ jsx13(Loader25, { className: "h-3 w-3 animate-spin" }),
|
|
1078
|
+
"Running"
|
|
1079
|
+
] }) : /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1 rounded-full border border-[var(--border-subtle)] bg-[linear-gradient(180deg,rgba(255,255,255,0.04),transparent)] px-2.5 py-0.5 text-[11px] font-semibold uppercase tracking-[0.08em] text-[var(--text-muted)]", children: [
|
|
1080
|
+
/* @__PURE__ */ jsx13(Sparkles, { className: "h-3 w-3" }),
|
|
1081
|
+
"Complete"
|
|
1082
|
+
] })
|
|
1083
|
+
] }),
|
|
1084
|
+
/* @__PURE__ */ jsxs12("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-[var(--text-muted)]", children: [
|
|
1085
|
+
renderSummary(run) ? /* @__PURE__ */ jsx13("span", { children: renderSummary(run) }) : null,
|
|
1086
|
+
collapsed && run.summaryText ? /* @__PURE__ */ jsx13("span", { className: "min-w-0 truncate text-[var(--text-secondary)]", children: run.summaryText }) : null
|
|
1065
1087
|
] })
|
|
1066
1088
|
] }),
|
|
1067
|
-
/* @__PURE__ */
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
}
|
|
1076
|
-
) }),
|
|
1077
|
-
collapsed && run.summaryText && /* @__PURE__ */ jsx13("div", { className: "px-4 py-2 text-sm text-[var(--text-muted)] line-clamp-2", children: run.summaryText }),
|
|
1089
|
+
/* @__PURE__ */ jsx13(CategoryBadges, { categories: stats.toolCategories }),
|
|
1090
|
+
!collapsed ? /* @__PURE__ */ jsx13(ChevronDown4, { className: "h-4 w-4 shrink-0 text-[var(--text-muted)]" }) : /* @__PURE__ */ jsx13(ChevronRight4, { className: "h-4 w-4 shrink-0 text-[var(--text-muted)]" })
|
|
1091
|
+
] })
|
|
1092
|
+
}
|
|
1093
|
+
) }),
|
|
1094
|
+
headerActions ? /* @__PURE__ */ jsx13("div", { className: "flex shrink-0 flex-wrap items-center justify-end gap-1.5 pt-1", children: headerActions }) : null
|
|
1095
|
+
] }),
|
|
1096
|
+
collapsed && run.summaryText && /* @__PURE__ */ jsx13("div", { className: "px-4 py-2 text-sm leading-6 text-[var(--text-muted)] line-clamp-2", children: run.summaryText }),
|
|
1078
1097
|
/* @__PURE__ */ jsx13(Collapsible3.Content, { className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp", children: /* @__PURE__ */ jsx13(
|
|
1079
1098
|
"div",
|
|
1080
1099
|
{
|
|
1081
1100
|
className: cn(
|
|
1082
|
-
"mt-2 space-y-
|
|
1101
|
+
"mt-2 space-y-3 rounded-[calc(var(--radius-xl)+2px)] border border-[var(--border-subtle)] p-3.5 shadow-[var(--shadow-card)]",
|
|
1083
1102
|
branding.containerBgClass
|
|
1084
1103
|
),
|
|
1085
1104
|
children: allParts.map(({ part, msgId, index }, partIndex) => {
|
|
@@ -1090,7 +1109,12 @@ var RunGroup = memo11(
|
|
|
1090
1109
|
{
|
|
1091
1110
|
part,
|
|
1092
1111
|
renderToolDetail,
|
|
1093
|
-
groupPosition: getToolGroupPosition(partIndex, allParts)
|
|
1112
|
+
groupPosition: getToolGroupPosition(partIndex, allParts),
|
|
1113
|
+
actions: renderToolActions?.(part, {
|
|
1114
|
+
run,
|
|
1115
|
+
messageId: msgId,
|
|
1116
|
+
partIndex: index
|
|
1117
|
+
})
|
|
1094
1118
|
},
|
|
1095
1119
|
key
|
|
1096
1120
|
);
|
|
@@ -1109,7 +1133,7 @@ var RunGroup = memo11(
|
|
|
1109
1133
|
return /* @__PURE__ */ jsx13(
|
|
1110
1134
|
"div",
|
|
1111
1135
|
{
|
|
1112
|
-
className: "rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--bg-card)] px-4 py-4",
|
|
1136
|
+
className: "rounded-[calc(var(--radius-lg)+2px)] border border-[var(--border-subtle)] bg-[radial-gradient(circle_at_top_left,rgba(96,165,250,0.08),transparent_36%),linear-gradient(180deg,rgba(255,255,255,0.03),transparent_30%),var(--bg-card)] px-4 py-4",
|
|
1113
1137
|
children: /* @__PURE__ */ jsx13(Markdown, { children: part.text })
|
|
1114
1138
|
},
|
|
1115
1139
|
key
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseToolEvent
|
|
3
3
|
} from "./chunk-CCKNIAS7.js";
|
|
4
|
+
import {
|
|
5
|
+
bumpActiveSessionActivity,
|
|
6
|
+
registerActiveSession,
|
|
7
|
+
setActiveSessionAttention,
|
|
8
|
+
setActiveSessionConnection,
|
|
9
|
+
setActiveSessionError,
|
|
10
|
+
setActiveSessionRunning,
|
|
11
|
+
setForegroundActiveSession,
|
|
12
|
+
unregisterActiveSession,
|
|
13
|
+
updateActiveSessionMeta
|
|
14
|
+
} from "./chunk-OEX7NZE3.js";
|
|
4
15
|
|
|
5
16
|
// src/hooks/use-tool-call-stream.ts
|
|
6
17
|
import { useState, useCallback, useRef } from "react";
|
|
@@ -744,8 +755,252 @@ function useSdkSession({
|
|
|
744
755
|
};
|
|
745
756
|
}
|
|
746
757
|
|
|
758
|
+
// src/hooks/use-realtime-session.ts
|
|
759
|
+
import { createElement, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
|
|
760
|
+
function parseEvent(message) {
|
|
761
|
+
try {
|
|
762
|
+
const parsed = JSON.parse(message);
|
|
763
|
+
return typeof parsed?.type === "string" ? parsed : null;
|
|
764
|
+
} catch {
|
|
765
|
+
return null;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
function eventTimestamp(event) {
|
|
769
|
+
const rootTimestamp = event.timestamp;
|
|
770
|
+
if (typeof rootTimestamp === "number" && Number.isFinite(rootTimestamp)) {
|
|
771
|
+
return rootTimestamp;
|
|
772
|
+
}
|
|
773
|
+
const raw = event.data?.timestamp ?? event.data?.ts ?? event.data?.time ?? event.data?.eventAt;
|
|
774
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
function resolveErrorMessage(event) {
|
|
778
|
+
const message = event.data?.message;
|
|
779
|
+
return typeof message === "string" && message.length > 0 ? message : null;
|
|
780
|
+
}
|
|
781
|
+
function updateStoreFromEvent(sessionId, event) {
|
|
782
|
+
const lastEventAt = eventTimestamp(event) ?? Date.now();
|
|
783
|
+
bumpActiveSessionActivity(sessionId, { lastEventAt });
|
|
784
|
+
if (event.type === "session.run.started") {
|
|
785
|
+
setActiveSessionRunning(sessionId, true, { lastEventAt });
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
if (event.type === "session.run.completed" || event.type === "done" || event.type === "result") {
|
|
789
|
+
setActiveSessionRunning(sessionId, false, { lastEventAt });
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (event.type === "session.attention") {
|
|
793
|
+
setActiveSessionAttention(sessionId, true, { lastEventAt });
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
if (event.type === "error" || event.type === "session.run.failed") {
|
|
797
|
+
setActiveSessionError(sessionId, resolveErrorMessage(event) ?? "Session error");
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
function useRealtimeSession({
|
|
802
|
+
sessionId,
|
|
803
|
+
projectId = null,
|
|
804
|
+
projectLabel,
|
|
805
|
+
title,
|
|
806
|
+
href,
|
|
807
|
+
metadata,
|
|
808
|
+
connectUrl,
|
|
809
|
+
enabled = true,
|
|
810
|
+
foreground = true,
|
|
811
|
+
keepRegistered = true,
|
|
812
|
+
reconnect = true,
|
|
813
|
+
reconnectIntervalMs = 1500,
|
|
814
|
+
maxReconnectAttempts = Infinity,
|
|
815
|
+
transportMode = "websocket",
|
|
816
|
+
onEvent,
|
|
817
|
+
onOpen,
|
|
818
|
+
onClose,
|
|
819
|
+
onError
|
|
820
|
+
}) {
|
|
821
|
+
const [connectionState, setConnectionState] = useState4("disconnected");
|
|
822
|
+
const [lastError, setLastError] = useState4(null);
|
|
823
|
+
const [reconnectAttempts, setReconnectAttempts] = useState4(0);
|
|
824
|
+
const socketRef = useRef4(null);
|
|
825
|
+
const timerRef = useRef4(null);
|
|
826
|
+
const reconnectAttemptsRef = useRef4(0);
|
|
827
|
+
const shouldReconnectRef = useRef4(true);
|
|
828
|
+
const registration = useMemo2(
|
|
829
|
+
() => ({
|
|
830
|
+
sessionId,
|
|
831
|
+
projectId,
|
|
832
|
+
projectLabel,
|
|
833
|
+
title,
|
|
834
|
+
href,
|
|
835
|
+
metadata
|
|
836
|
+
}),
|
|
837
|
+
[href, metadata, projectId, projectLabel, sessionId, title]
|
|
838
|
+
);
|
|
839
|
+
useEffect2(() => {
|
|
840
|
+
if (!sessionId || !keepRegistered) return void 0;
|
|
841
|
+
registerActiveSession(registration);
|
|
842
|
+
return () => {
|
|
843
|
+
unregisterActiveSession(sessionId);
|
|
844
|
+
};
|
|
845
|
+
}, [keepRegistered, registration, sessionId]);
|
|
846
|
+
useEffect2(() => {
|
|
847
|
+
if (!sessionId || !keepRegistered) return;
|
|
848
|
+
updateActiveSessionMeta(sessionId, {
|
|
849
|
+
projectId,
|
|
850
|
+
projectLabel,
|
|
851
|
+
title,
|
|
852
|
+
href,
|
|
853
|
+
metadata
|
|
854
|
+
});
|
|
855
|
+
}, [href, keepRegistered, metadata, projectId, projectLabel, sessionId, title]);
|
|
856
|
+
useEffect2(() => {
|
|
857
|
+
if (!sessionId || !foreground) return void 0;
|
|
858
|
+
setForegroundActiveSession(sessionId);
|
|
859
|
+
return () => {
|
|
860
|
+
setForegroundActiveSession(null);
|
|
861
|
+
};
|
|
862
|
+
}, [foreground, sessionId]);
|
|
863
|
+
useEffect2(() => {
|
|
864
|
+
if (!enabled || !sessionId || !connectUrl || typeof window === "undefined") {
|
|
865
|
+
setConnectionState("disconnected");
|
|
866
|
+
if (sessionId) {
|
|
867
|
+
setActiveSessionConnection(sessionId, {
|
|
868
|
+
connectionState: "disconnected",
|
|
869
|
+
reconnectState: "idle",
|
|
870
|
+
transportMode
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
return void 0;
|
|
874
|
+
}
|
|
875
|
+
shouldReconnectRef.current = true;
|
|
876
|
+
const clearReconnectTimer = () => {
|
|
877
|
+
if (timerRef.current != null) {
|
|
878
|
+
window.clearTimeout(timerRef.current);
|
|
879
|
+
timerRef.current = null;
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
const connect = () => {
|
|
883
|
+
clearReconnectTimer();
|
|
884
|
+
setConnectionState(reconnectAttemptsRef.current > 0 ? "reconnecting" : "connecting");
|
|
885
|
+
setActiveSessionConnection(sessionId, {
|
|
886
|
+
connectionState: reconnectAttemptsRef.current > 0 ? "reconnecting" : "connecting",
|
|
887
|
+
reconnectState: reconnectAttemptsRef.current > 0 ? "reconnecting" : "idle",
|
|
888
|
+
transportMode,
|
|
889
|
+
lastError: null
|
|
890
|
+
});
|
|
891
|
+
const socket = new window.WebSocket(connectUrl);
|
|
892
|
+
socketRef.current = socket;
|
|
893
|
+
socket.onopen = () => {
|
|
894
|
+
reconnectAttemptsRef.current = 0;
|
|
895
|
+
setReconnectAttempts(0);
|
|
896
|
+
setLastError(null);
|
|
897
|
+
setConnectionState("connected");
|
|
898
|
+
registerActiveSession(registration);
|
|
899
|
+
setActiveSessionConnection(sessionId, {
|
|
900
|
+
connectionState: "connected",
|
|
901
|
+
reconnectState: "idle",
|
|
902
|
+
transportMode,
|
|
903
|
+
lastError: null,
|
|
904
|
+
lastEventAt: Date.now()
|
|
905
|
+
});
|
|
906
|
+
onOpen?.();
|
|
907
|
+
};
|
|
908
|
+
socket.onmessage = (message) => {
|
|
909
|
+
const event = parseEvent(message.data);
|
|
910
|
+
if (!event) return;
|
|
911
|
+
registerActiveSession(registration);
|
|
912
|
+
updateStoreFromEvent(sessionId, event);
|
|
913
|
+
onEvent?.(event);
|
|
914
|
+
};
|
|
915
|
+
socket.onerror = () => {
|
|
916
|
+
const nextError = "Realtime session connection error";
|
|
917
|
+
setLastError(nextError);
|
|
918
|
+
setConnectionState("error");
|
|
919
|
+
setActiveSessionConnection(sessionId, {
|
|
920
|
+
connectionState: "error",
|
|
921
|
+
reconnectState: reconnect ? "reconnecting" : "failed",
|
|
922
|
+
transportMode,
|
|
923
|
+
lastError: nextError
|
|
924
|
+
});
|
|
925
|
+
onError?.(new Error(nextError));
|
|
926
|
+
};
|
|
927
|
+
socket.onclose = () => {
|
|
928
|
+
socketRef.current = null;
|
|
929
|
+
onClose?.();
|
|
930
|
+
if (!shouldReconnectRef.current || !reconnect) {
|
|
931
|
+
setConnectionState("disconnected");
|
|
932
|
+
setActiveSessionConnection(sessionId, {
|
|
933
|
+
connectionState: "disconnected",
|
|
934
|
+
reconnectState: "idle",
|
|
935
|
+
transportMode
|
|
936
|
+
});
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
reconnectAttemptsRef.current += 1;
|
|
940
|
+
setReconnectAttempts(reconnectAttemptsRef.current);
|
|
941
|
+
if (reconnectAttemptsRef.current > maxReconnectAttempts) {
|
|
942
|
+
setConnectionState("error");
|
|
943
|
+
setActiveSessionConnection(sessionId, {
|
|
944
|
+
connectionState: "error",
|
|
945
|
+
reconnectState: "failed",
|
|
946
|
+
transportMode,
|
|
947
|
+
lastError: "Unable to reconnect to realtime session"
|
|
948
|
+
});
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
setConnectionState("reconnecting");
|
|
952
|
+
timerRef.current = window.setTimeout(connect, reconnectIntervalMs);
|
|
953
|
+
};
|
|
954
|
+
};
|
|
955
|
+
connect();
|
|
956
|
+
return () => {
|
|
957
|
+
shouldReconnectRef.current = false;
|
|
958
|
+
clearReconnectTimer();
|
|
959
|
+
const socket = socketRef.current;
|
|
960
|
+
socketRef.current = null;
|
|
961
|
+
if (socket && socket.readyState < WebSocket.CLOSING) {
|
|
962
|
+
socket.close();
|
|
963
|
+
}
|
|
964
|
+
};
|
|
965
|
+
}, [
|
|
966
|
+
connectUrl,
|
|
967
|
+
enabled,
|
|
968
|
+
maxReconnectAttempts,
|
|
969
|
+
onClose,
|
|
970
|
+
onError,
|
|
971
|
+
onEvent,
|
|
972
|
+
onOpen,
|
|
973
|
+
reconnect,
|
|
974
|
+
reconnectIntervalMs,
|
|
975
|
+
registration,
|
|
976
|
+
sessionId,
|
|
977
|
+
transportMode
|
|
978
|
+
]);
|
|
979
|
+
return {
|
|
980
|
+
connectionState,
|
|
981
|
+
lastError,
|
|
982
|
+
reconnectAttempts,
|
|
983
|
+
isConnected: connectionState === "connected"
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
function RealtimeSessionRegistryItem(props) {
|
|
987
|
+
useRealtimeSession({
|
|
988
|
+
...props,
|
|
989
|
+
foreground: props.foreground ?? false
|
|
990
|
+
});
|
|
991
|
+
return null;
|
|
992
|
+
}
|
|
993
|
+
function RealtimeSessionRegistry({ sessions }) {
|
|
994
|
+
return sessions.map(
|
|
995
|
+
(session) => createElement(RealtimeSessionRegistryItem, {
|
|
996
|
+
key: session.key ?? session.sessionId,
|
|
997
|
+
...session
|
|
998
|
+
})
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
747
1002
|
// src/hooks/use-session-stream.ts
|
|
748
|
-
import { useCallback as useCallback4, useEffect as
|
|
1003
|
+
import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef5, useState as useState5 } from "react";
|
|
749
1004
|
var _insertionCounter = 0;
|
|
750
1005
|
function mapApiMessage(msg) {
|
|
751
1006
|
const created = msg.info.timestamp ? new Date(msg.info.timestamp).getTime() : Date.now();
|
|
@@ -795,13 +1050,13 @@ function useSessionStream({
|
|
|
795
1050
|
sessionId,
|
|
796
1051
|
enabled = true
|
|
797
1052
|
}) {
|
|
798
|
-
const [messages, setMessages] =
|
|
799
|
-
const [partMap, setPartMap] =
|
|
800
|
-
const [isStreaming, setIsStreaming] =
|
|
801
|
-
const [error, setError] =
|
|
802
|
-
const [connected, setConnected] =
|
|
803
|
-
const abortRef =
|
|
804
|
-
const streamingMsgIdRef =
|
|
1053
|
+
const [messages, setMessages] = useState5([]);
|
|
1054
|
+
const [partMap, setPartMap] = useState5({});
|
|
1055
|
+
const [isStreaming, setIsStreaming] = useState5(false);
|
|
1056
|
+
const [error, setError] = useState5(null);
|
|
1057
|
+
const [connected, setConnected] = useState5(false);
|
|
1058
|
+
const abortRef = useRef5(null);
|
|
1059
|
+
const streamingMsgIdRef = useRef5(null);
|
|
805
1060
|
const refetch = useCallback4(async () => {
|
|
806
1061
|
if (!token || !sessionId || !apiUrl) return;
|
|
807
1062
|
try {
|
|
@@ -988,7 +1243,7 @@ function useSessionStream({
|
|
|
988
1243
|
setError(msg);
|
|
989
1244
|
}
|
|
990
1245
|
}, [apiUrl, token, sessionId]);
|
|
991
|
-
|
|
1246
|
+
useEffect3(() => {
|
|
992
1247
|
if (!enabled || !token || !sessionId) return;
|
|
993
1248
|
refetch();
|
|
994
1249
|
connectSSE();
|
|
@@ -1001,12 +1256,12 @@ function useSessionStream({
|
|
|
1001
1256
|
}
|
|
1002
1257
|
|
|
1003
1258
|
// src/hooks/use-dropdown-menu.ts
|
|
1004
|
-
import { useEffect as
|
|
1259
|
+
import { useEffect as useEffect4, useRef as useRef6, useState as useState6 } from "react";
|
|
1005
1260
|
function useDropdownMenu(options) {
|
|
1006
1261
|
const closeOnEsc = options?.closeOnEsc ?? true;
|
|
1007
|
-
const [open, setOpen] =
|
|
1008
|
-
const ref =
|
|
1009
|
-
|
|
1262
|
+
const [open, setOpen] = useState6(false);
|
|
1263
|
+
const ref = useRef6(null);
|
|
1264
|
+
useEffect4(() => {
|
|
1010
1265
|
function handleClick(e) {
|
|
1011
1266
|
if (ref.current && !ref.current.contains(e.target)) {
|
|
1012
1267
|
setOpen(false);
|
|
@@ -1017,7 +1272,7 @@ function useDropdownMenu(options) {
|
|
|
1017
1272
|
}
|
|
1018
1273
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
1019
1274
|
}, [open]);
|
|
1020
|
-
|
|
1275
|
+
useEffect4(() => {
|
|
1021
1276
|
if (!open || !closeOnEsc) return;
|
|
1022
1277
|
function handleKey(e) {
|
|
1023
1278
|
if (e.key === "Escape") setOpen(false);
|
|
@@ -1035,7 +1290,7 @@ function useDropdownMenu(options) {
|
|
|
1035
1290
|
}
|
|
1036
1291
|
|
|
1037
1292
|
// src/hooks/use-sidecar-auth.ts
|
|
1038
|
-
import { useState as
|
|
1293
|
+
import { useState as useState7, useCallback as useCallback5, useEffect as useEffect5, useRef as useRef7 } from "react";
|
|
1039
1294
|
function storageKey(resourceId, apiUrl) {
|
|
1040
1295
|
return `sidecar_session_${resourceId}__${apiUrl}`;
|
|
1041
1296
|
}
|
|
@@ -1067,11 +1322,11 @@ function clearSession(resourceId, apiUrl) {
|
|
|
1067
1322
|
}
|
|
1068
1323
|
function useSidecarAuth({ resourceId, apiUrl, signMessage }) {
|
|
1069
1324
|
const cached = loadSession(resourceId, apiUrl);
|
|
1070
|
-
const [token, setToken] =
|
|
1071
|
-
const [expiresAt, setExpiresAt] =
|
|
1072
|
-
const [isAuthenticating, setIsAuthenticating] =
|
|
1073
|
-
const [error, setError] =
|
|
1074
|
-
const refreshTimerRef =
|
|
1325
|
+
const [token, setToken] = useState7(cached?.token ?? null);
|
|
1326
|
+
const [expiresAt, setExpiresAt] = useState7(cached?.expiresAt ?? 0);
|
|
1327
|
+
const [isAuthenticating, setIsAuthenticating] = useState7(false);
|
|
1328
|
+
const [error, setError] = useState7(null);
|
|
1329
|
+
const refreshTimerRef = useRef7(void 0);
|
|
1075
1330
|
const clearCachedToken = useCallback5(() => {
|
|
1076
1331
|
setToken(null);
|
|
1077
1332
|
setExpiresAt(0);
|
|
@@ -1112,7 +1367,7 @@ function useSidecarAuth({ resourceId, apiUrl, signMessage }) {
|
|
|
1112
1367
|
setIsAuthenticating(false);
|
|
1113
1368
|
}
|
|
1114
1369
|
}, [resourceId, apiUrl, signMessage, clearCachedToken]);
|
|
1115
|
-
|
|
1370
|
+
useEffect5(() => {
|
|
1116
1371
|
if (refreshTimerRef.current) {
|
|
1117
1372
|
clearTimeout(refreshTimerRef.current);
|
|
1118
1373
|
}
|
|
@@ -1147,6 +1402,8 @@ export {
|
|
|
1147
1402
|
useToolCallStream,
|
|
1148
1403
|
useSSEStream,
|
|
1149
1404
|
useSdkSession,
|
|
1405
|
+
useRealtimeSession,
|
|
1406
|
+
RealtimeSessionRegistry,
|
|
1150
1407
|
useSessionStream,
|
|
1151
1408
|
useDropdownMenu,
|
|
1152
1409
|
useSidecarAuth
|