@opengeni/react 0.6.3 → 0.9.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/README.md +17 -6
- package/dist/index.d.ts +25 -8
- package/dist/index.js +544 -218
- package/dist/index.js.map +1 -1
- package/dist/{machines-Bv9tG7qZ.d.ts → machines-BeZ3bD3t.d.ts} +1 -1
- package/dist/machines.d.ts +1 -1
- package/package.json +2 -2
- package/src/client.ts +1 -0
- package/src/components/message-timeline.tsx +144 -17
- package/src/hooks/use-session-capabilities.ts +3 -2
- package/src/hooks/use-session-events.ts +294 -8
- package/src/timeline/activity-rail.tsx +4 -1
- package/src/timeline/entrance.tsx +30 -0
- package/src/timeline/projection.ts +18 -3
- package/src/timeline/turn-summary.tsx +3 -1
package/dist/index.js
CHANGED
|
@@ -98,7 +98,7 @@ function useSession(sessionId, options = {}) {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
// src/hooks/use-session-events.ts
|
|
101
|
-
import { useEffect as useEffect3, useMemo as useMemo2, useRef, useState as useState8 } from "react";
|
|
101
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState8 } from "react";
|
|
102
102
|
|
|
103
103
|
// src/timeline/projection.ts
|
|
104
104
|
var WORKER_SPAWN_TOOL = "session_create";
|
|
@@ -352,7 +352,7 @@ ${message}` : message;
|
|
|
352
352
|
case "turn.failed": {
|
|
353
353
|
const hadActivity = hasTurnActivity(items, turnId);
|
|
354
354
|
const failureText = failureMessage(payload);
|
|
355
|
-
finalizeOpen(turnId, "
|
|
355
|
+
finalizeOpen(turnId, "cancelled");
|
|
356
356
|
items.push(turnEndItem(event, "failed", failureText));
|
|
357
357
|
if (!hadActivity) {
|
|
358
358
|
items.push({
|
|
@@ -594,8 +594,14 @@ function stampTurnOutcome(groups, turnEnd) {
|
|
|
594
594
|
}
|
|
595
595
|
}
|
|
596
596
|
function applyTurnOutcome(group, turnEnd) {
|
|
597
|
-
|
|
598
|
-
|
|
597
|
+
if (turnEnd.outcome === "complete") {
|
|
598
|
+
group.outcome = "complete";
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
const hasFailed = group.items.some((item) => "status" in item && item.status === "failed");
|
|
602
|
+
const hasInterrupted = group.items.some((item) => "status" in item && item.status === "cancelled");
|
|
603
|
+
group.outcome = hasFailed ? "failed" : hasInterrupted ? "cancelled" : "complete";
|
|
604
|
+
if (turnEnd.failureText && hasFailed) {
|
|
599
605
|
group.failureText = turnEnd.failureText;
|
|
600
606
|
}
|
|
601
607
|
}
|
|
@@ -2492,6 +2498,18 @@ function createDefaultToolRegistry(options = {}) {
|
|
|
2492
2498
|
|
|
2493
2499
|
// src/timeline/activity-rail.tsx
|
|
2494
2500
|
import { BotIcon, BrainIcon, SquareTerminalIcon } from "lucide-react";
|
|
2501
|
+
|
|
2502
|
+
// src/timeline/entrance.tsx
|
|
2503
|
+
import { createContext as createContext3, useContext as useContext3, useRef } from "react";
|
|
2504
|
+
var EntranceAnimationContext = createContext3(true);
|
|
2505
|
+
var EntranceAnimationProvider = EntranceAnimationContext.Provider;
|
|
2506
|
+
function useEntranceAnimation() {
|
|
2507
|
+
const enabled = useContext3(EntranceAnimationContext);
|
|
2508
|
+
const captured = useRef(enabled);
|
|
2509
|
+
return captured.current;
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
// src/timeline/activity-rail.tsx
|
|
2495
2513
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2496
2514
|
function familyOf(item) {
|
|
2497
2515
|
if (item.kind === "tool-call") {
|
|
@@ -2500,6 +2518,7 @@ function familyOf(item) {
|
|
|
2500
2518
|
return item.kind;
|
|
2501
2519
|
}
|
|
2502
2520
|
function ActivityRail({ items, toolRegistry = defaultToolRegistry, onOpenSession, bare, className }) {
|
|
2521
|
+
const enter = useEntranceAnimation();
|
|
2503
2522
|
return /* @__PURE__ */ jsx8(
|
|
2504
2523
|
"div",
|
|
2505
2524
|
{
|
|
@@ -2508,7 +2527,8 @@ function ActivityRail({ items, toolRegistry = defaultToolRegistry, onOpenSession
|
|
|
2508
2527
|
// calm cluster; a family change opens real breathing room (mt-3) below,
|
|
2509
2528
|
// so a long rail reads as a few clusters, not a metronome of rows.
|
|
2510
2529
|
"flex flex-col gap-0.5",
|
|
2511
|
-
!bare && "
|
|
2530
|
+
!bare && "border-l-2 border-og-border pl-3 sm:pl-4",
|
|
2531
|
+
!bare && enter && "animate-og-enter",
|
|
2512
2532
|
className
|
|
2513
2533
|
),
|
|
2514
2534
|
children: items.map((item, index) => {
|
|
@@ -2630,8 +2650,9 @@ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
|
2630
2650
|
function TurnSummary({ items, outcome, failureText, durationMs, defaultOpen, children }) {
|
|
2631
2651
|
const forcedDefaultOpen = useForcedDefaultOpen();
|
|
2632
2652
|
const [open, setOpen] = useState7(defaultOpen ?? forcedDefaultOpen ?? false);
|
|
2653
|
+
const enter = useEntranceAnimation();
|
|
2633
2654
|
const facets = summarizeTurn(items, durationMs);
|
|
2634
|
-
return /* @__PURE__ */ jsxs7(Collapsible2.Root, { open, onOpenChange: setOpen, className: "animate-og-enter", children: [
|
|
2655
|
+
return /* @__PURE__ */ jsxs7(Collapsible2.Root, { open, onOpenChange: setOpen, className: enter ? "animate-og-enter" : void 0, children: [
|
|
2635
2656
|
/* @__PURE__ */ jsxs7(
|
|
2636
2657
|
Collapsible2.Trigger,
|
|
2637
2658
|
{
|
|
@@ -2734,22 +2755,43 @@ function formatDurationFacet(durationMs) {
|
|
|
2734
2755
|
}
|
|
2735
2756
|
|
|
2736
2757
|
// src/hooks/use-session-events.ts
|
|
2758
|
+
var TAIL_PAGE_SIZE = 5e3;
|
|
2759
|
+
var INITIAL_FETCH_CAP = 1;
|
|
2760
|
+
var OLDER_GROUP_TARGET = 32;
|
|
2761
|
+
var OLDER_FETCH_CAP = 2;
|
|
2762
|
+
var BOUNDARY_PAGE_CAP = 4;
|
|
2737
2763
|
function useSessionEvents(sessionId, options = {}) {
|
|
2738
2764
|
const { client, workspaceId } = useOpenGeni(options);
|
|
2739
2765
|
const enabled = options.enabled ?? true;
|
|
2740
2766
|
const after = options.after ?? 0;
|
|
2767
|
+
const replay = options.replay ?? "windowed";
|
|
2768
|
+
const fullReplay = replay === "full" || after !== 0;
|
|
2741
2769
|
const [events, setEvents] = useState8([]);
|
|
2742
2770
|
const [connectionState, setConnectionState] = useState8("idle");
|
|
2743
2771
|
const [error, setError] = useState8(null);
|
|
2744
|
-
const
|
|
2745
|
-
const
|
|
2772
|
+
const [hasOlder, setHasOlder] = useState8(false);
|
|
2773
|
+
const [initialLoading, setInitialLoading] = useState8(true);
|
|
2774
|
+
const [loadingOlder, setLoadingOlder] = useState8(false);
|
|
2775
|
+
const lastSequenceRef = useRef2(after);
|
|
2776
|
+
const oldestSequenceRef = useRef2(null);
|
|
2777
|
+
const hasOlderRef = useRef2(false);
|
|
2778
|
+
const loadingOlderRef = useRef2(false);
|
|
2779
|
+
const streamKeyRef = useRef2(null);
|
|
2780
|
+
const generationRef = useRef2(0);
|
|
2746
2781
|
useEffect3(() => {
|
|
2747
|
-
const streamKey = `${workspaceId}\0${sessionId ?? ""}\0${after}`;
|
|
2782
|
+
const streamKey = `${workspaceId}\0${sessionId ?? ""}\0${after}\0${fullReplay ? "full" : "windowed"}`;
|
|
2748
2783
|
if (streamKeyRef.current !== streamKey) {
|
|
2749
2784
|
streamKeyRef.current = streamKey;
|
|
2785
|
+
generationRef.current += 1;
|
|
2750
2786
|
setEvents([]);
|
|
2751
2787
|
setError(null);
|
|
2788
|
+
setHasOlder(false);
|
|
2789
|
+
setLoadingOlder(false);
|
|
2790
|
+
setInitialLoading(true);
|
|
2752
2791
|
lastSequenceRef.current = after;
|
|
2792
|
+
oldestSequenceRef.current = null;
|
|
2793
|
+
hasOlderRef.current = false;
|
|
2794
|
+
loadingOlderRef.current = false;
|
|
2753
2795
|
}
|
|
2754
2796
|
if (!sessionId || !enabled) {
|
|
2755
2797
|
setConnectionState("idle");
|
|
@@ -2767,7 +2809,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
2767
2809
|
pending = [];
|
|
2768
2810
|
const lastInBatch = batch[batch.length - 1];
|
|
2769
2811
|
if (lastInBatch) {
|
|
2770
|
-
lastSequenceRef.current =
|
|
2812
|
+
lastSequenceRef.current = Math.max(lastSequenceRef.current, ...batch.map(eventResumeSequence));
|
|
2771
2813
|
}
|
|
2772
2814
|
setEvents((existing) => [...existing, ...batch]);
|
|
2773
2815
|
};
|
|
@@ -2776,6 +2818,28 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
2776
2818
|
};
|
|
2777
2819
|
void (async () => {
|
|
2778
2820
|
try {
|
|
2821
|
+
if (!fullReplay) {
|
|
2822
|
+
setConnectionState("connecting");
|
|
2823
|
+
const window2 = await loadEventWindow(client, workspaceId, sessionId, {
|
|
2824
|
+
before: Number.MAX_SAFE_INTEGER,
|
|
2825
|
+
pageSize: TAIL_PAGE_SIZE,
|
|
2826
|
+
targetGroups: Number.POSITIVE_INFINITY,
|
|
2827
|
+
maxFetches: INITIAL_FETCH_CAP,
|
|
2828
|
+
signal: controller.signal
|
|
2829
|
+
});
|
|
2830
|
+
if (controller.signal.aborted) {
|
|
2831
|
+
return;
|
|
2832
|
+
}
|
|
2833
|
+
oldestSequenceRef.current = window2.oldestSequence;
|
|
2834
|
+
hasOlderRef.current = window2.hasOlder;
|
|
2835
|
+
lastSequenceRef.current = window2.newestSequence;
|
|
2836
|
+
setHasOlder(window2.hasOlder);
|
|
2837
|
+
setEvents(window2.events);
|
|
2838
|
+
setInitialLoading(false);
|
|
2839
|
+
}
|
|
2840
|
+
if (fullReplay) {
|
|
2841
|
+
setInitialLoading(false);
|
|
2842
|
+
}
|
|
2779
2843
|
const stream = client.streamEvents(workspaceId, sessionId, {
|
|
2780
2844
|
after: lastSequenceRef.current,
|
|
2781
2845
|
signal: controller.signal,
|
|
@@ -2807,7 +2871,51 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
2807
2871
|
clearTimeout(flushTimer);
|
|
2808
2872
|
}
|
|
2809
2873
|
};
|
|
2810
|
-
}, [client, workspaceId, sessionId, after, enabled]);
|
|
2874
|
+
}, [client, workspaceId, sessionId, after, enabled, fullReplay]);
|
|
2875
|
+
const loadOlder = useCallback3(async () => {
|
|
2876
|
+
if (!sessionId || fullReplay || loadingOlderRef.current || !hasOlderRef.current) {
|
|
2877
|
+
return false;
|
|
2878
|
+
}
|
|
2879
|
+
const before = oldestSequenceRef.current;
|
|
2880
|
+
if (before === null) {
|
|
2881
|
+
hasOlderRef.current = false;
|
|
2882
|
+
setHasOlder(false);
|
|
2883
|
+
return false;
|
|
2884
|
+
}
|
|
2885
|
+
const generation = generationRef.current;
|
|
2886
|
+
loadingOlderRef.current = true;
|
|
2887
|
+
setLoadingOlder(true);
|
|
2888
|
+
try {
|
|
2889
|
+
const window2 = await loadEventWindow(client, workspaceId, sessionId, {
|
|
2890
|
+
before,
|
|
2891
|
+
pageSize: TAIL_PAGE_SIZE,
|
|
2892
|
+
targetGroups: OLDER_GROUP_TARGET,
|
|
2893
|
+
maxFetches: OLDER_FETCH_CAP
|
|
2894
|
+
});
|
|
2895
|
+
if (generationRef.current !== generation) {
|
|
2896
|
+
return false;
|
|
2897
|
+
}
|
|
2898
|
+
if (window2.events.length === 0) {
|
|
2899
|
+
oldestSequenceRef.current = null;
|
|
2900
|
+
hasOlderRef.current = false;
|
|
2901
|
+
setHasOlder(false);
|
|
2902
|
+
return false;
|
|
2903
|
+
}
|
|
2904
|
+
oldestSequenceRef.current = window2.oldestSequence;
|
|
2905
|
+
hasOlderRef.current = window2.hasOlder;
|
|
2906
|
+
setHasOlder(window2.hasOlder);
|
|
2907
|
+
setEvents((existing) => {
|
|
2908
|
+
assertPrependOrder(existing, window2.events);
|
|
2909
|
+
return [...window2.events, ...existing];
|
|
2910
|
+
});
|
|
2911
|
+
return window2.hasOlder;
|
|
2912
|
+
} finally {
|
|
2913
|
+
if (generationRef.current === generation) {
|
|
2914
|
+
loadingOlderRef.current = false;
|
|
2915
|
+
setLoadingOlder(false);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
}, [client, workspaceId, sessionId, fullReplay]);
|
|
2811
2919
|
const timeline = useMemo2(() => buildTimeline(events), [events]);
|
|
2812
2920
|
const sessionStatus = useMemo2(() => sessionStatusFromEvents(events), [events]);
|
|
2813
2921
|
return {
|
|
@@ -2816,12 +2924,144 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
2816
2924
|
sessionStatus,
|
|
2817
2925
|
connectionState,
|
|
2818
2926
|
lastSequence: lastSequenceRef.current,
|
|
2927
|
+
initialLoading: fullReplay ? false : initialLoading,
|
|
2928
|
+
hasOlder: fullReplay ? false : hasOlder,
|
|
2929
|
+
loadingOlder: fullReplay ? false : loadingOlder,
|
|
2930
|
+
loadOlder,
|
|
2819
2931
|
error
|
|
2820
2932
|
};
|
|
2821
2933
|
}
|
|
2934
|
+
async function loadEventWindow(client, workspaceId, sessionId, options) {
|
|
2935
|
+
let cursor = options.before;
|
|
2936
|
+
let buffer = [];
|
|
2937
|
+
let reachedStart = false;
|
|
2938
|
+
let fetches = 0;
|
|
2939
|
+
while (fetches < options.maxFetches) {
|
|
2940
|
+
if (buffer.length > 0 && groupCount(buffer) >= options.targetGroups) {
|
|
2941
|
+
break;
|
|
2942
|
+
}
|
|
2943
|
+
const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {
|
|
2944
|
+
pageSize: options.pageSize,
|
|
2945
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2946
|
+
});
|
|
2947
|
+
fetches += 1;
|
|
2948
|
+
if (page.length === 0) {
|
|
2949
|
+
reachedStart = true;
|
|
2950
|
+
break;
|
|
2951
|
+
}
|
|
2952
|
+
assertAscending(page);
|
|
2953
|
+
buffer = [...page, ...buffer];
|
|
2954
|
+
cursor = page[0].sequence;
|
|
2955
|
+
if (isLogStart(page[0])) {
|
|
2956
|
+
reachedStart = true;
|
|
2957
|
+
break;
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
let snapPages = 0;
|
|
2961
|
+
while (!reachedStart && findBoundaryIndex(buffer) === -1 && snapPages < BOUNDARY_PAGE_CAP && fetches < options.maxFetches) {
|
|
2962
|
+
const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {
|
|
2963
|
+
pageSize: options.pageSize,
|
|
2964
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2965
|
+
});
|
|
2966
|
+
fetches += 1;
|
|
2967
|
+
snapPages += 1;
|
|
2968
|
+
if (page.length === 0) {
|
|
2969
|
+
reachedStart = true;
|
|
2970
|
+
break;
|
|
2971
|
+
}
|
|
2972
|
+
assertAscending(page);
|
|
2973
|
+
buffer = [...page, ...buffer];
|
|
2974
|
+
cursor = page[0].sequence;
|
|
2975
|
+
if (isLogStart(page[0])) {
|
|
2976
|
+
reachedStart = true;
|
|
2977
|
+
break;
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
if (!reachedStart) {
|
|
2981
|
+
const boundary = findBoundaryIndex(buffer);
|
|
2982
|
+
if (boundary > 0) {
|
|
2983
|
+
buffer = buffer.slice(boundary);
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
const oldest = buffer[0] ?? null;
|
|
2987
|
+
const newest = buffer[buffer.length - 1] ?? null;
|
|
2988
|
+
return {
|
|
2989
|
+
events: buffer,
|
|
2990
|
+
oldestSequence: oldest?.sequence ?? null,
|
|
2991
|
+
newestSequence: newest ? maxResumeSequence(buffer) : 0,
|
|
2992
|
+
hasOlder: buffer.length > 0 && !reachedStart && oldest?.type !== "session.created"
|
|
2993
|
+
};
|
|
2994
|
+
}
|
|
2995
|
+
function findBoundaryIndex(events) {
|
|
2996
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
2997
|
+
const type = events[index].type;
|
|
2998
|
+
if (type === "session.created" || type === "user.message") {
|
|
2999
|
+
return index;
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
return -1;
|
|
3003
|
+
}
|
|
3004
|
+
async function loadPreviousPage(client, workspaceId, sessionId, before, options) {
|
|
3005
|
+
if (options.signal?.aborted) {
|
|
3006
|
+
throw abortError();
|
|
3007
|
+
}
|
|
3008
|
+
const requested = options.pageSize;
|
|
3009
|
+
if (requested === 0) {
|
|
3010
|
+
return Object.assign([], { requested });
|
|
3011
|
+
}
|
|
3012
|
+
const page = await client.listEvents(workspaceId, sessionId, { before, limit: requested, compact: true });
|
|
3013
|
+
if (options.signal?.aborted) {
|
|
3014
|
+
throw abortError();
|
|
3015
|
+
}
|
|
3016
|
+
return Object.assign(page, { requested });
|
|
3017
|
+
}
|
|
3018
|
+
function groupCount(events) {
|
|
3019
|
+
if (events.length === 0) {
|
|
3020
|
+
return 0;
|
|
3021
|
+
}
|
|
3022
|
+
return groupTimeline(buildTimeline(events)).length;
|
|
3023
|
+
}
|
|
3024
|
+
function isLogStart(event) {
|
|
3025
|
+
return event.type === "session.created" || event.sequence <= 1;
|
|
3026
|
+
}
|
|
3027
|
+
function maxResumeSequence(events) {
|
|
3028
|
+
return events.reduce((max, event) => Math.max(max, eventResumeSequence(event)), 0);
|
|
3029
|
+
}
|
|
3030
|
+
function eventResumeSequence(event) {
|
|
3031
|
+
const payload = asRecord2(event.payload);
|
|
3032
|
+
const coalescedUntil = Number(payload.coalescedUntil);
|
|
3033
|
+
return Math.max(event.sequence, Number.isFinite(coalescedUntil) ? Math.floor(coalescedUntil) : 0);
|
|
3034
|
+
}
|
|
3035
|
+
function asRecord2(value) {
|
|
3036
|
+
return value && typeof value === "object" ? value : {};
|
|
3037
|
+
}
|
|
3038
|
+
function assertAscending(events) {
|
|
3039
|
+
for (let index = 1; index < events.length; index += 1) {
|
|
3040
|
+
if (events[index - 1].sequence >= events[index].sequence) {
|
|
3041
|
+
throw new Error("@opengeni/react: session events must be ordered by ascending sequence");
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
function assertPrependOrder(existing, older) {
|
|
3046
|
+
if (!shouldAssertDevelopment() || existing.length === 0 || older.length === 0) {
|
|
3047
|
+
return;
|
|
3048
|
+
}
|
|
3049
|
+
if (older[older.length - 1].sequence >= existing[0].sequence) {
|
|
3050
|
+
throw new Error("@opengeni/react: loadOlder returned overlapping session events");
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
function shouldAssertDevelopment() {
|
|
3054
|
+
const processEnv = globalThis.process?.env;
|
|
3055
|
+
return processEnv !== void 0 && processEnv.NODE_ENV !== "production";
|
|
3056
|
+
}
|
|
3057
|
+
function abortError() {
|
|
3058
|
+
const error = new Error("The operation was aborted.");
|
|
3059
|
+
error.name = "AbortError";
|
|
3060
|
+
return error;
|
|
3061
|
+
}
|
|
2822
3062
|
|
|
2823
3063
|
// src/hooks/use-composer.ts
|
|
2824
|
-
import { useCallback as
|
|
3064
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useRef as useRef3, useState as useState9 } from "react";
|
|
2825
3065
|
function useComposer(sessionId, options = {}) {
|
|
2826
3066
|
const { client, workspaceId } = useOpenGeni(options);
|
|
2827
3067
|
const defaultMode = options.defaultMode ?? "queue";
|
|
@@ -2830,14 +3070,14 @@ function useComposer(sessionId, options = {}) {
|
|
|
2830
3070
|
const [sending, setSending] = useState9(false);
|
|
2831
3071
|
const [interrupting, setInterrupting] = useState9(false);
|
|
2832
3072
|
const [error, setError] = useState9(null);
|
|
2833
|
-
const pendingClientEventId =
|
|
3073
|
+
const pendingClientEventId = useRef3(null);
|
|
2834
3074
|
const onSent = options.onSent;
|
|
2835
|
-
const modeRef =
|
|
3075
|
+
const modeRef = useRef3(mode);
|
|
2836
3076
|
modeRef.current = mode;
|
|
2837
|
-
const sendExtrasRef =
|
|
3077
|
+
const sendExtrasRef = useRef3(options.sendExtras);
|
|
2838
3078
|
sendExtrasRef.current = options.sendExtras;
|
|
2839
3079
|
const targetKey = `${workspaceId}\0${sessionId ?? ""}`;
|
|
2840
|
-
const targetKeyRef =
|
|
3080
|
+
const targetKeyRef = useRef3(targetKey);
|
|
2841
3081
|
useEffect4(() => {
|
|
2842
3082
|
if (targetKeyRef.current !== targetKey) {
|
|
2843
3083
|
targetKeyRef.current = targetKey;
|
|
@@ -2847,7 +3087,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
2847
3087
|
setMode(defaultMode);
|
|
2848
3088
|
}
|
|
2849
3089
|
}, [targetKey, defaultMode]);
|
|
2850
|
-
const send =
|
|
3090
|
+
const send = useCallback4(
|
|
2851
3091
|
async (explicit) => {
|
|
2852
3092
|
const draftAtSend = value;
|
|
2853
3093
|
const text = (explicit ?? draftAtSend).trim();
|
|
@@ -2883,7 +3123,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
2883
3123
|
[client, workspaceId, sessionId, value, sending, onSent]
|
|
2884
3124
|
);
|
|
2885
3125
|
const hasReadyResources = (resolveSendExtras(sendExtrasRef.current).resources?.length ?? 0) > 0;
|
|
2886
|
-
const interrupt =
|
|
3126
|
+
const interrupt = useCallback4(
|
|
2887
3127
|
async (reason) => {
|
|
2888
3128
|
if (!sessionId || interrupting) {
|
|
2889
3129
|
return;
|
|
@@ -2900,7 +3140,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
2900
3140
|
},
|
|
2901
3141
|
[client, workspaceId, sessionId, interrupting]
|
|
2902
3142
|
);
|
|
2903
|
-
const updateValue =
|
|
3143
|
+
const updateValue = useCallback4((next) => {
|
|
2904
3144
|
pendingClientEventId.current = null;
|
|
2905
3145
|
setValue(next);
|
|
2906
3146
|
}, []);
|
|
@@ -2915,7 +3155,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
2915
3155
|
interrupt,
|
|
2916
3156
|
interrupting,
|
|
2917
3157
|
error,
|
|
2918
|
-
clearError:
|
|
3158
|
+
clearError: useCallback4(() => setError(null), [])
|
|
2919
3159
|
};
|
|
2920
3160
|
}
|
|
2921
3161
|
var FILE_ONLY_MESSAGE_TEXT = "(see attached files)";
|
|
@@ -2940,14 +3180,14 @@ function generateClientEventId() {
|
|
|
2940
3180
|
}
|
|
2941
3181
|
|
|
2942
3182
|
// src/hooks/use-file-attachments.ts
|
|
2943
|
-
import { useCallback as
|
|
3183
|
+
import { useCallback as useCallback5, useRef as useRef4, useState as useState10 } from "react";
|
|
2944
3184
|
var isImage = (file) => file.type.startsWith("image/");
|
|
2945
3185
|
function useFileAttachments(options = {}) {
|
|
2946
3186
|
const { client, workspaceId } = useOpenGeni(options);
|
|
2947
3187
|
const pasteFilter = options.pasteFilter ?? isImage;
|
|
2948
3188
|
const [attachments, setAttachments] = useState10([]);
|
|
2949
|
-
const sources =
|
|
2950
|
-
const startUpload =
|
|
3189
|
+
const sources = useRef4(/* @__PURE__ */ new Map());
|
|
3190
|
+
const startUpload = useCallback5((id, file) => {
|
|
2951
3191
|
void client.uploadFile(workspaceId, {
|
|
2952
3192
|
filename: file.name || "file",
|
|
2953
3193
|
contentType: file.type || "application/octet-stream",
|
|
@@ -2958,7 +3198,7 @@ function useFileAttachments(options = {}) {
|
|
|
2958
3198
|
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "failed", error: error instanceof Error ? error.message : String(error) } : attachment));
|
|
2959
3199
|
});
|
|
2960
3200
|
}, [client, workspaceId]);
|
|
2961
|
-
const addFiles =
|
|
3201
|
+
const addFiles = useCallback5((files) => {
|
|
2962
3202
|
for (const file of files) {
|
|
2963
3203
|
const id = crypto.randomUUID();
|
|
2964
3204
|
sources.current.set(id, file);
|
|
@@ -2974,7 +3214,7 @@ function useFileAttachments(options = {}) {
|
|
|
2974
3214
|
startUpload(id, file);
|
|
2975
3215
|
}
|
|
2976
3216
|
}, [startUpload]);
|
|
2977
|
-
const retry =
|
|
3217
|
+
const retry = useCallback5((id) => {
|
|
2978
3218
|
const file = sources.current.get(id);
|
|
2979
3219
|
if (!file) {
|
|
2980
3220
|
return;
|
|
@@ -2982,7 +3222,7 @@ function useFileAttachments(options = {}) {
|
|
|
2982
3222
|
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "uploading", error: void 0 } : attachment));
|
|
2983
3223
|
startUpload(id, file);
|
|
2984
3224
|
}, [startUpload]);
|
|
2985
|
-
const addFromPaste =
|
|
3225
|
+
const addFromPaste = useCallback5((event) => {
|
|
2986
3226
|
const clipboardFiles = event.clipboardData?.files;
|
|
2987
3227
|
if (!clipboardFiles) {
|
|
2988
3228
|
return;
|
|
@@ -2992,7 +3232,7 @@ function useFileAttachments(options = {}) {
|
|
|
2992
3232
|
addFiles(files);
|
|
2993
3233
|
}
|
|
2994
3234
|
}, [addFiles, pasteFilter]);
|
|
2995
|
-
const remove =
|
|
3235
|
+
const remove = useCallback5((id) => {
|
|
2996
3236
|
sources.current.delete(id);
|
|
2997
3237
|
setAttachments((current) => {
|
|
2998
3238
|
const removed = current.find((attachment) => attachment.id === id);
|
|
@@ -3002,7 +3242,7 @@ function useFileAttachments(options = {}) {
|
|
|
3002
3242
|
return current.filter((attachment) => attachment.id !== id);
|
|
3003
3243
|
});
|
|
3004
3244
|
}, []);
|
|
3005
|
-
const clear =
|
|
3245
|
+
const clear = useCallback5(() => {
|
|
3006
3246
|
sources.current.clear();
|
|
3007
3247
|
setAttachments((current) => {
|
|
3008
3248
|
for (const attachment of current) {
|
|
@@ -3026,7 +3266,7 @@ function useFileAttachments(options = {}) {
|
|
|
3026
3266
|
}
|
|
3027
3267
|
|
|
3028
3268
|
// src/hooks/use-turn-queue.ts
|
|
3029
|
-
import { useCallback as
|
|
3269
|
+
import { useCallback as useCallback6, useEffect as useEffect5, useRef as useRef5, useState as useState11 } from "react";
|
|
3030
3270
|
function isTurnQueueEvent(event) {
|
|
3031
3271
|
return event.type.startsWith("turn.");
|
|
3032
3272
|
}
|
|
@@ -3070,9 +3310,9 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3070
3310
|
const [loading, setLoading] = useState11(enabled);
|
|
3071
3311
|
const [error, setError] = useState11(null);
|
|
3072
3312
|
const mutation = useMutationRunner();
|
|
3073
|
-
const generation =
|
|
3074
|
-
const targetKeyRef =
|
|
3075
|
-
const load =
|
|
3313
|
+
const generation = useRef5(0);
|
|
3314
|
+
const targetKeyRef = useRef5(null);
|
|
3315
|
+
const load = useCallback6(async () => {
|
|
3076
3316
|
if (!sessionId) {
|
|
3077
3317
|
return;
|
|
3078
3318
|
}
|
|
@@ -3121,7 +3361,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3121
3361
|
enabled,
|
|
3122
3362
|
...options.events !== void 0 ? { events: options.events } : {}
|
|
3123
3363
|
});
|
|
3124
|
-
const editTurn =
|
|
3364
|
+
const editTurn = useCallback6(
|
|
3125
3365
|
async (turnId, update) => {
|
|
3126
3366
|
if (!sessionId) {
|
|
3127
3367
|
return null;
|
|
@@ -3137,7 +3377,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3137
3377
|
},
|
|
3138
3378
|
[client, workspaceId, sessionId, mutation.run, load]
|
|
3139
3379
|
);
|
|
3140
|
-
const reorderTurns =
|
|
3380
|
+
const reorderTurns = useCallback6(
|
|
3141
3381
|
async (turnIds) => {
|
|
3142
3382
|
if (!sessionId || turnIds.length === 0) {
|
|
3143
3383
|
return null;
|
|
@@ -3156,7 +3396,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3156
3396
|
},
|
|
3157
3397
|
[client, workspaceId, sessionId, mutation.run, load]
|
|
3158
3398
|
);
|
|
3159
|
-
const removeTurn =
|
|
3399
|
+
const removeTurn = useCallback6(
|
|
3160
3400
|
async (turnId) => {
|
|
3161
3401
|
if (!sessionId) {
|
|
3162
3402
|
return null;
|
|
@@ -3190,7 +3430,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3190
3430
|
|
|
3191
3431
|
// src/hooks/use-goal.ts
|
|
3192
3432
|
import { OpenGeniApiError } from "@opengeni/sdk";
|
|
3193
|
-
import { useCallback as
|
|
3433
|
+
import { useCallback as useCallback7, useEffect as useEffect6, useRef as useRef6, useState as useState12 } from "react";
|
|
3194
3434
|
function isGoalEvent(event) {
|
|
3195
3435
|
return event.type.startsWith("goal.");
|
|
3196
3436
|
}
|
|
@@ -3203,9 +3443,9 @@ function useGoal(sessionId, options = {}) {
|
|
|
3203
3443
|
const [loading, setLoading] = useState12(enabled);
|
|
3204
3444
|
const [error, setError] = useState12(null);
|
|
3205
3445
|
const mutation = useMutationRunner();
|
|
3206
|
-
const generation =
|
|
3207
|
-
const targetKeyRef =
|
|
3208
|
-
const load =
|
|
3446
|
+
const generation = useRef6(0);
|
|
3447
|
+
const targetKeyRef = useRef6(null);
|
|
3448
|
+
const load = useCallback7(async () => {
|
|
3209
3449
|
if (!sessionId) {
|
|
3210
3450
|
return;
|
|
3211
3451
|
}
|
|
@@ -3266,7 +3506,7 @@ function useGoal(sessionId, options = {}) {
|
|
|
3266
3506
|
enabled,
|
|
3267
3507
|
...sharedEvents !== void 0 ? { events: sharedEvents } : {}
|
|
3268
3508
|
});
|
|
3269
|
-
const pause =
|
|
3509
|
+
const pause = useCallback7(
|
|
3270
3510
|
async (rationale) => {
|
|
3271
3511
|
if (!sessionId) {
|
|
3272
3512
|
return null;
|
|
@@ -3282,7 +3522,7 @@ function useGoal(sessionId, options = {}) {
|
|
|
3282
3522
|
},
|
|
3283
3523
|
[client, workspaceId, sessionId, mutation.run]
|
|
3284
3524
|
);
|
|
3285
|
-
const resume =
|
|
3525
|
+
const resume = useCallback7(async () => {
|
|
3286
3526
|
if (!sessionId) {
|
|
3287
3527
|
return null;
|
|
3288
3528
|
}
|
|
@@ -3309,12 +3549,12 @@ function useGoal(sessionId, options = {}) {
|
|
|
3309
3549
|
}
|
|
3310
3550
|
|
|
3311
3551
|
// src/hooks/use-session-control.ts
|
|
3312
|
-
import { useCallback as
|
|
3552
|
+
import { useCallback as useCallback8 } from "react";
|
|
3313
3553
|
function useSessionControl(sessionId, options = {}) {
|
|
3314
3554
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3315
3555
|
const interruptMutation = useMutationRunner();
|
|
3316
3556
|
const approvalMutation = useMutationRunner();
|
|
3317
|
-
const interrupt =
|
|
3557
|
+
const interrupt = useCallback8(
|
|
3318
3558
|
async (reason) => {
|
|
3319
3559
|
if (!sessionId) {
|
|
3320
3560
|
return null;
|
|
@@ -3323,7 +3563,7 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
3323
3563
|
},
|
|
3324
3564
|
[client, workspaceId, sessionId, interruptMutation.run]
|
|
3325
3565
|
);
|
|
3326
|
-
const decide =
|
|
3566
|
+
const decide = useCallback8(
|
|
3327
3567
|
async (approvalId, decision, message) => {
|
|
3328
3568
|
if (!sessionId) {
|
|
3329
3569
|
return null;
|
|
@@ -3336,16 +3576,16 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
3336
3576
|
},
|
|
3337
3577
|
[client, workspaceId, sessionId, approvalMutation.run]
|
|
3338
3578
|
);
|
|
3339
|
-
const approve =
|
|
3579
|
+
const approve = useCallback8(
|
|
3340
3580
|
async (approvalId, message) => await decide(approvalId, "approve", message),
|
|
3341
3581
|
[decide]
|
|
3342
3582
|
);
|
|
3343
|
-
const reject =
|
|
3583
|
+
const reject = useCallback8(
|
|
3344
3584
|
async (approvalId, message) => await decide(approvalId, "reject", message),
|
|
3345
3585
|
[decide]
|
|
3346
3586
|
);
|
|
3347
3587
|
const error = approvalMutation.mutationError ?? interruptMutation.mutationError;
|
|
3348
|
-
const clearError =
|
|
3588
|
+
const clearError = useCallback8(() => {
|
|
3349
3589
|
interruptMutation.clearMutationError();
|
|
3350
3590
|
approvalMutation.clearMutationError();
|
|
3351
3591
|
}, [interruptMutation.clearMutationError, approvalMutation.clearMutationError]);
|
|
@@ -3361,11 +3601,11 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
3361
3601
|
}
|
|
3362
3602
|
|
|
3363
3603
|
// src/hooks/use-scheduled-tasks.ts
|
|
3364
|
-
import { useCallback as
|
|
3604
|
+
import { useCallback as useCallback9 } from "react";
|
|
3365
3605
|
function useScheduledTasks(options = {}) {
|
|
3366
3606
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3367
3607
|
const limit = options.limit;
|
|
3368
|
-
const load =
|
|
3608
|
+
const load = useCallback9(
|
|
3369
3609
|
async () => await client.listScheduledTasks(workspaceId, limit !== void 0 ? { limit } : {}),
|
|
3370
3610
|
[client, workspaceId, limit]
|
|
3371
3611
|
);
|
|
@@ -3374,11 +3614,11 @@ function useScheduledTasks(options = {}) {
|
|
|
3374
3614
|
}
|
|
3375
3615
|
|
|
3376
3616
|
// src/hooks/use-workspace-sessions.ts
|
|
3377
|
-
import { useCallback as
|
|
3617
|
+
import { useCallback as useCallback10 } from "react";
|
|
3378
3618
|
function useWorkspaceSessions(options = {}) {
|
|
3379
3619
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3380
3620
|
const limit = options.limit;
|
|
3381
|
-
const load =
|
|
3621
|
+
const load = useCallback10(
|
|
3382
3622
|
async () => await client.listSessions(workspaceId, limit !== void 0 ? { limit } : {}),
|
|
3383
3623
|
[client, workspaceId, limit]
|
|
3384
3624
|
);
|
|
@@ -3387,13 +3627,13 @@ function useWorkspaceSessions(options = {}) {
|
|
|
3387
3627
|
}
|
|
3388
3628
|
|
|
3389
3629
|
// src/hooks/use-environments.ts
|
|
3390
|
-
import { useCallback as
|
|
3630
|
+
import { useCallback as useCallback11 } from "react";
|
|
3391
3631
|
function useEnvironments(options = {}) {
|
|
3392
3632
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3393
|
-
const load =
|
|
3633
|
+
const load = useCallback11(async () => await client.listEnvironments(workspaceId), [client, workspaceId]);
|
|
3394
3634
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });
|
|
3395
3635
|
const mutation = useMutationRunner();
|
|
3396
|
-
const create =
|
|
3636
|
+
const create = useCallback11(
|
|
3397
3637
|
async (request) => {
|
|
3398
3638
|
const result = await mutation.run(() => client.createEnvironment(workspaceId, request));
|
|
3399
3639
|
if (result) {
|
|
@@ -3403,7 +3643,7 @@ function useEnvironments(options = {}) {
|
|
|
3403
3643
|
},
|
|
3404
3644
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3405
3645
|
);
|
|
3406
|
-
const update =
|
|
3646
|
+
const update = useCallback11(
|
|
3407
3647
|
async (environmentId, request) => {
|
|
3408
3648
|
const result = await mutation.run(() => client.updateEnvironment(workspaceId, environmentId, request));
|
|
3409
3649
|
if (result) {
|
|
@@ -3413,7 +3653,7 @@ function useEnvironments(options = {}) {
|
|
|
3413
3653
|
},
|
|
3414
3654
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3415
3655
|
);
|
|
3416
|
-
const remove =
|
|
3656
|
+
const remove = useCallback11(
|
|
3417
3657
|
async (environmentId) => {
|
|
3418
3658
|
const result = await mutation.run(async () => {
|
|
3419
3659
|
await client.deleteEnvironment(workspaceId, environmentId);
|
|
@@ -3426,7 +3666,7 @@ function useEnvironments(options = {}) {
|
|
|
3426
3666
|
},
|
|
3427
3667
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3428
3668
|
);
|
|
3429
|
-
const setVariable =
|
|
3669
|
+
const setVariable = useCallback11(
|
|
3430
3670
|
async (environmentId, name, value) => {
|
|
3431
3671
|
const result = await mutation.run(() => client.setEnvironmentVariable(workspaceId, environmentId, name, value));
|
|
3432
3672
|
if (result) {
|
|
@@ -3436,7 +3676,7 @@ function useEnvironments(options = {}) {
|
|
|
3436
3676
|
},
|
|
3437
3677
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3438
3678
|
);
|
|
3439
|
-
const deleteVariable =
|
|
3679
|
+
const deleteVariable = useCallback11(
|
|
3440
3680
|
async (environmentId, name) => {
|
|
3441
3681
|
const result = await mutation.run(async () => {
|
|
3442
3682
|
await client.deleteEnvironmentVariable(workspaceId, environmentId, name);
|
|
@@ -3466,13 +3706,13 @@ function useEnvironments(options = {}) {
|
|
|
3466
3706
|
}
|
|
3467
3707
|
|
|
3468
3708
|
// src/hooks/use-packs.ts
|
|
3469
|
-
import { useCallback as
|
|
3709
|
+
import { useCallback as useCallback12 } from "react";
|
|
3470
3710
|
function usePacks(options = {}) {
|
|
3471
3711
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3472
|
-
const load =
|
|
3712
|
+
const load = useCallback12(async () => await client.listPacks(workspaceId), [client, workspaceId]);
|
|
3473
3713
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });
|
|
3474
3714
|
const mutation = useMutationRunner();
|
|
3475
|
-
const register =
|
|
3715
|
+
const register = useCallback12(
|
|
3476
3716
|
async (manifest) => {
|
|
3477
3717
|
const result = await mutation.run(() => client.registerPack(workspaceId, manifest));
|
|
3478
3718
|
if (result) {
|
|
@@ -3482,7 +3722,7 @@ function usePacks(options = {}) {
|
|
|
3482
3722
|
},
|
|
3483
3723
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3484
3724
|
);
|
|
3485
|
-
const enable =
|
|
3725
|
+
const enable = useCallback12(
|
|
3486
3726
|
async (packId, request = {}) => {
|
|
3487
3727
|
const result = await mutation.run(() => client.enablePack(workspaceId, packId, request));
|
|
3488
3728
|
if (result) {
|
|
@@ -3492,7 +3732,7 @@ function usePacks(options = {}) {
|
|
|
3492
3732
|
},
|
|
3493
3733
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3494
3734
|
);
|
|
3495
|
-
const remove =
|
|
3735
|
+
const remove = useCallback12(
|
|
3496
3736
|
async (packId) => {
|
|
3497
3737
|
const result = await mutation.run(async () => {
|
|
3498
3738
|
await client.deletePack(workspaceId, packId);
|
|
@@ -3506,7 +3746,7 @@ function usePacks(options = {}) {
|
|
|
3506
3746
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3507
3747
|
);
|
|
3508
3748
|
const installations = state.data?.installations ?? [];
|
|
3509
|
-
const installationFor =
|
|
3749
|
+
const installationFor = useCallback12(
|
|
3510
3750
|
(packId) => installations.find((installation) => installation.packId === packId) ?? null,
|
|
3511
3751
|
[installations]
|
|
3512
3752
|
);
|
|
@@ -3527,13 +3767,13 @@ function usePacks(options = {}) {
|
|
|
3527
3767
|
}
|
|
3528
3768
|
|
|
3529
3769
|
// src/hooks/use-workspaces.ts
|
|
3530
|
-
import { useCallback as
|
|
3770
|
+
import { useCallback as useCallback13 } from "react";
|
|
3531
3771
|
function useWorkspaces(options = {}) {
|
|
3532
3772
|
const client = useOpenGeniClient(options);
|
|
3533
|
-
const load =
|
|
3773
|
+
const load = useCallback13(async () => await client.listWorkspaces(), [client]);
|
|
3534
3774
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });
|
|
3535
3775
|
const mutation = useMutationRunner();
|
|
3536
|
-
const create =
|
|
3776
|
+
const create = useCallback13(
|
|
3537
3777
|
async (request) => {
|
|
3538
3778
|
const result = await mutation.run(() => client.createWorkspace(request));
|
|
3539
3779
|
if (result) {
|
|
@@ -3543,7 +3783,7 @@ function useWorkspaces(options = {}) {
|
|
|
3543
3783
|
},
|
|
3544
3784
|
[client, mutation.run, state.refresh]
|
|
3545
3785
|
);
|
|
3546
|
-
const update =
|
|
3786
|
+
const update = useCallback13(
|
|
3547
3787
|
async (workspaceId, request) => {
|
|
3548
3788
|
const result = await mutation.run(() => client.updateWorkspace(workspaceId, request));
|
|
3549
3789
|
if (result) {
|
|
@@ -3567,12 +3807,12 @@ function useWorkspaces(options = {}) {
|
|
|
3567
3807
|
}
|
|
3568
3808
|
|
|
3569
3809
|
// src/hooks/use-billing-usage.ts
|
|
3570
|
-
import { useCallback as
|
|
3810
|
+
import { useCallback as useCallback14 } from "react";
|
|
3571
3811
|
function useBillingUsage(options = {}) {
|
|
3572
3812
|
const client = useOpenGeniClient(options);
|
|
3573
3813
|
const accountId = options.accountId;
|
|
3574
3814
|
const workspaceId = options.workspaceId;
|
|
3575
|
-
const load =
|
|
3815
|
+
const load = useCallback14(
|
|
3576
3816
|
async () => await client.getBillingUsage({
|
|
3577
3817
|
...accountId !== void 0 ? { accountId } : {},
|
|
3578
3818
|
...workspaceId !== void 0 ? { workspaceId } : {}
|
|
@@ -3590,10 +3830,10 @@ function useBillingUsage(options = {}) {
|
|
|
3590
3830
|
}
|
|
3591
3831
|
|
|
3592
3832
|
// src/hooks/use-available-models.ts
|
|
3593
|
-
import { useCallback as
|
|
3833
|
+
import { useCallback as useCallback15 } from "react";
|
|
3594
3834
|
function useAvailableModels(options = {}) {
|
|
3595
3835
|
const client = useOpenGeniClient(options);
|
|
3596
|
-
const load =
|
|
3836
|
+
const load = useCallback15(async () => await client.getClientConfig(), [client]);
|
|
3597
3837
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });
|
|
3598
3838
|
return {
|
|
3599
3839
|
models: state.data?.models ?? [],
|
|
@@ -3609,7 +3849,7 @@ import {
|
|
|
3609
3849
|
OpenGeniApiError as OpenGeniApiError2,
|
|
3610
3850
|
applyUrlRotation
|
|
3611
3851
|
} from "@opengeni/sdk";
|
|
3612
|
-
import { useCallback as
|
|
3852
|
+
import { useCallback as useCallback16, useEffect as useEffect7, useRef as useRef7, useState as useState13 } from "react";
|
|
3613
3853
|
function desktopAttachable(cell) {
|
|
3614
3854
|
if (cell.transport !== null) return true;
|
|
3615
3855
|
return cell.reason === "lease_cold" || cell.reason === "not_provisioned" || cell.reason === null;
|
|
@@ -3644,9 +3884,9 @@ function useSessionCapabilities(sessionId, options = {}) {
|
|
|
3644
3884
|
const [viewerCapReached, setViewerCapReached] = useState13(false);
|
|
3645
3885
|
const [viewerId, setViewerId] = useState13(null);
|
|
3646
3886
|
const [nonce, setNonce] = useState13(0);
|
|
3647
|
-
const epochRef =
|
|
3648
|
-
const viewerIdRef =
|
|
3649
|
-
const renegotiate =
|
|
3887
|
+
const epochRef = useRef7(0);
|
|
3888
|
+
const viewerIdRef = useRef7(null);
|
|
3889
|
+
const renegotiate = useCallback16(() => {
|
|
3650
3890
|
setNonce((n) => n + 1);
|
|
3651
3891
|
}, []);
|
|
3652
3892
|
useEffect7(() => {
|
|
@@ -3844,7 +4084,7 @@ import {
|
|
|
3844
4084
|
desktopSocketUrl,
|
|
3845
4085
|
nextDesktopState
|
|
3846
4086
|
} from "@opengeni/sdk";
|
|
3847
|
-
import { useEffect as useEffect9, useRef as
|
|
4087
|
+
import { useEffect as useEffect9, useRef as useRef9, useState as useState15 } from "react";
|
|
3848
4088
|
|
|
3849
4089
|
// src/lib/relay-wire.ts
|
|
3850
4090
|
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
|
@@ -3917,7 +4157,7 @@ function decodeStreamFrame(bytes) {
|
|
|
3917
4157
|
}
|
|
3918
4158
|
|
|
3919
4159
|
// src/hooks/use-relay-frame-stream.ts
|
|
3920
|
-
import { useEffect as useEffect8, useRef as
|
|
4160
|
+
import { useEffect as useEffect8, useRef as useRef8, useState as useState14 } from "react";
|
|
3921
4161
|
var TAG_OPEN = 1;
|
|
3922
4162
|
var TAG_OPENACK = 2;
|
|
3923
4163
|
var TAG_FRAME = 3;
|
|
@@ -3935,7 +4175,7 @@ function useRelayFrameStream(options) {
|
|
|
3935
4175
|
const [state, setState] = useState14("idle");
|
|
3936
4176
|
const [error, setError] = useState14(null);
|
|
3937
4177
|
const [nonce, setNonce] = useState14(0);
|
|
3938
|
-
const stateRef =
|
|
4178
|
+
const stateRef = useRef8("idle");
|
|
3939
4179
|
const setBoth = (next) => {
|
|
3940
4180
|
stateRef.current = next;
|
|
3941
4181
|
setState(next);
|
|
@@ -3944,7 +4184,7 @@ function useRelayFrameStream(options) {
|
|
|
3944
4184
|
const transport = capability?.transport ?? null;
|
|
3945
4185
|
const url = capability?.url ?? null;
|
|
3946
4186
|
const token = capability?.token ?? null;
|
|
3947
|
-
const factoryRef =
|
|
4187
|
+
const factoryRef = useRef8(webSocketFactory);
|
|
3948
4188
|
factoryRef.current = webSocketFactory;
|
|
3949
4189
|
useEffect8(() => {
|
|
3950
4190
|
if (typeof window === "undefined") return;
|
|
@@ -4138,7 +4378,7 @@ function useDesktopStream(options) {
|
|
|
4138
4378
|
const [state, setState] = useState15("idle");
|
|
4139
4379
|
const [error, setError] = useState15(null);
|
|
4140
4380
|
const [nonce, setNonce] = useState15(0);
|
|
4141
|
-
const stateRef =
|
|
4381
|
+
const stateRef = useRef9("idle");
|
|
4142
4382
|
const setBoth = (next) => {
|
|
4143
4383
|
stateRef.current = next;
|
|
4144
4384
|
setState(next);
|
|
@@ -4148,11 +4388,11 @@ function useDesktopStream(options) {
|
|
|
4148
4388
|
const token = capability?.token ?? null;
|
|
4149
4389
|
const transport = capability?.transport ?? null;
|
|
4150
4390
|
const mode = capability?.mode ?? "read-only";
|
|
4151
|
-
const rfbRef =
|
|
4152
|
-
const interactiveRef =
|
|
4153
|
-
const scaleViewportRef =
|
|
4154
|
-
const modeRef =
|
|
4155
|
-
const rfbFactoryRef =
|
|
4391
|
+
const rfbRef = useRef9(null);
|
|
4392
|
+
const interactiveRef = useRef9(interactive);
|
|
4393
|
+
const scaleViewportRef = useRef9(scaleViewport);
|
|
4394
|
+
const modeRef = useRef9(mode);
|
|
4395
|
+
const rfbFactoryRef = useRef9(rfbFactory);
|
|
4156
4396
|
interactiveRef.current = interactive;
|
|
4157
4397
|
scaleViewportRef.current = scaleViewport;
|
|
4158
4398
|
modeRef.current = mode;
|
|
@@ -4245,7 +4485,7 @@ import {
|
|
|
4245
4485
|
ttydResizeFrame,
|
|
4246
4486
|
TtydServerCommand
|
|
4247
4487
|
} from "@opengeni/sdk";
|
|
4248
|
-
import { useEffect as useEffect10, useMemo as useMemo3, useRef as
|
|
4488
|
+
import { useEffect as useEffect10, useMemo as useMemo3, useRef as useRef10, useState as useState16 } from "react";
|
|
4249
4489
|
function decodeFrame(data) {
|
|
4250
4490
|
if (typeof data === "string") {
|
|
4251
4491
|
return { command: data.charAt(0), payload: data.slice(1) };
|
|
@@ -4258,13 +4498,13 @@ function decodeFrame(data) {
|
|
|
4258
4498
|
function useTerminalStream(options) {
|
|
4259
4499
|
const { capability, onOutput, onTitle, initialCols, initialRows } = options;
|
|
4260
4500
|
const [status, setStatus] = useState16("closed");
|
|
4261
|
-
const wsRef =
|
|
4262
|
-
const sizeRef =
|
|
4501
|
+
const wsRef = useRef10(null);
|
|
4502
|
+
const sizeRef = useRef10({
|
|
4263
4503
|
cols: initialCols ?? 80,
|
|
4264
4504
|
rows: initialRows ?? 24
|
|
4265
4505
|
});
|
|
4266
|
-
const onOutputRef =
|
|
4267
|
-
const onTitleRef =
|
|
4506
|
+
const onOutputRef = useRef10(onOutput);
|
|
4507
|
+
const onTitleRef = useRef10(onTitle);
|
|
4268
4508
|
onOutputRef.current = onOutput;
|
|
4269
4509
|
onTitleRef.current = onTitle;
|
|
4270
4510
|
const transport = capability?.transport ?? null;
|
|
@@ -4367,7 +4607,7 @@ function useTerminalStream(options) {
|
|
|
4367
4607
|
|
|
4368
4608
|
// src/hooks/use-sandbox-terminal.ts
|
|
4369
4609
|
import { OpenGeniApiError as OpenGeniApiError3 } from "@opengeni/sdk";
|
|
4370
|
-
import { useCallback as
|
|
4610
|
+
import { useCallback as useCallback17, useEffect as useEffect11, useMemo as useMemo4, useRef as useRef11, useState as useState17 } from "react";
|
|
4371
4611
|
function useSandboxTerminal(sessionId, options) {
|
|
4372
4612
|
const { client, workspaceId } = useOpenGeni(options);
|
|
4373
4613
|
const includeAgentFirehose = options.includeAgentFirehose ?? true;
|
|
@@ -4377,7 +4617,7 @@ function useSandboxTerminal(sessionId, options) {
|
|
|
4377
4617
|
const [openedPtyId, setOpenedPtyId] = useState17(null);
|
|
4378
4618
|
const [openError, setOpenError] = useState17(null);
|
|
4379
4619
|
const [reopenNonce, setReopenNonce] = useState17(0);
|
|
4380
|
-
const openInFlight =
|
|
4620
|
+
const openInFlight = useRef11(false);
|
|
4381
4621
|
const boxWarm = liveness === void 0 || liveness === "warm" || liveness === "draining";
|
|
4382
4622
|
useEffect11(() => {
|
|
4383
4623
|
if (!interactive || !sessionId || ptyFilter || !boxWarm) return;
|
|
@@ -4467,7 +4707,7 @@ function useSandboxTerminal(sessionId, options) {
|
|
|
4467
4707
|
});
|
|
4468
4708
|
};
|
|
4469
4709
|
}, [client, workspaceId, sessionId, activePtyId, canWrite, openedPtyId]);
|
|
4470
|
-
const close =
|
|
4710
|
+
const close = useCallback17(() => {
|
|
4471
4711
|
if (!activePtyId || !sessionId) return;
|
|
4472
4712
|
void client.terminalPtyClose(workspaceId, sessionId, { ptyId: activePtyId }).catch(() => {
|
|
4473
4713
|
});
|
|
@@ -4483,7 +4723,7 @@ function useSandboxTerminal(sessionId, options) {
|
|
|
4483
4723
|
}
|
|
4484
4724
|
|
|
4485
4725
|
// src/hooks/use-sandbox-files.ts
|
|
4486
|
-
import { useCallback as
|
|
4726
|
+
import { useCallback as useCallback18, useEffect as useEffect12, useRef as useRef12, useState as useState18 } from "react";
|
|
4487
4727
|
function parentOf(path) {
|
|
4488
4728
|
const i = path.lastIndexOf("/");
|
|
4489
4729
|
return i <= 0 ? "" : path.slice(0, i);
|
|
@@ -4603,15 +4843,15 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4603
4843
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
4604
4844
|
const rootPath = options.rootPath ?? "";
|
|
4605
4845
|
const [tree, setTree] = useState18([]);
|
|
4606
|
-
const treeRef =
|
|
4846
|
+
const treeRef = useRef12([]);
|
|
4607
4847
|
const [loading, setLoading] = useState18(false);
|
|
4608
4848
|
const [expandingPaths, setExpandingPaths] = useState18(/* @__PURE__ */ new Set());
|
|
4609
4849
|
const [error, setError] = useState18(null);
|
|
4610
|
-
const statusRef =
|
|
4611
|
-
const ownRevisionsRef =
|
|
4850
|
+
const statusRef = useRef12(/* @__PURE__ */ new Map());
|
|
4851
|
+
const ownRevisionsRef = useRef12(/* @__PURE__ */ new Set());
|
|
4612
4852
|
const onMutationError = options.onMutationError;
|
|
4613
4853
|
treeRef.current = tree;
|
|
4614
|
-
const applyStatus =
|
|
4854
|
+
const applyStatus = useCallback18((nodes) => {
|
|
4615
4855
|
const overlay = statusRef.current;
|
|
4616
4856
|
if (overlay.size === 0) return nodes;
|
|
4617
4857
|
const walk = (list) => list.map((node) => {
|
|
@@ -4623,7 +4863,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4623
4863
|
});
|
|
4624
4864
|
return walk(nodes);
|
|
4625
4865
|
}, []);
|
|
4626
|
-
const refresh =
|
|
4866
|
+
const refresh = useCallback18(async () => {
|
|
4627
4867
|
if (!sessionId) return;
|
|
4628
4868
|
setLoading(true);
|
|
4629
4869
|
setError(null);
|
|
@@ -4649,7 +4889,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4649
4889
|
setLoading(false);
|
|
4650
4890
|
}
|
|
4651
4891
|
}, [client, workspaceId, sessionId, rootPath, applyStatus]);
|
|
4652
|
-
const expand =
|
|
4892
|
+
const expand = useCallback18(
|
|
4653
4893
|
async (path) => {
|
|
4654
4894
|
if (!sessionId) return;
|
|
4655
4895
|
setExpandingPaths((prev) => {
|
|
@@ -4674,14 +4914,14 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4674
4914
|
},
|
|
4675
4915
|
[client, workspaceId, sessionId, applyStatus]
|
|
4676
4916
|
);
|
|
4677
|
-
const readFile =
|
|
4917
|
+
const readFile = useCallback18(
|
|
4678
4918
|
async (path) => {
|
|
4679
4919
|
if (!sessionId) throw new Error("no session");
|
|
4680
4920
|
return await client.fsRead(workspaceId, sessionId, { path });
|
|
4681
4921
|
},
|
|
4682
4922
|
[client, workspaceId, sessionId]
|
|
4683
4923
|
);
|
|
4684
|
-
const reconcilePath =
|
|
4924
|
+
const reconcilePath = useCallback18(
|
|
4685
4925
|
async (path) => {
|
|
4686
4926
|
if (!sessionId) return;
|
|
4687
4927
|
if (!parentIsLoaded(treeRef.current, path)) return;
|
|
@@ -4700,7 +4940,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4700
4940
|
},
|
|
4701
4941
|
[client, workspaceId, sessionId, applyStatus]
|
|
4702
4942
|
);
|
|
4703
|
-
const runOptimistic =
|
|
4943
|
+
const runOptimistic = useCallback18(
|
|
4704
4944
|
async (opName, apply, op, reconcileParents) => {
|
|
4705
4945
|
const snapshot = treeRef.current;
|
|
4706
4946
|
setTree(applyStatus(apply(snapshot)));
|
|
@@ -4722,7 +4962,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4722
4962
|
},
|
|
4723
4963
|
[applyStatus, reconcilePath, onMutationError]
|
|
4724
4964
|
);
|
|
4725
|
-
const writeFile =
|
|
4965
|
+
const writeFile = useCallback18(
|
|
4726
4966
|
async (path, content) => {
|
|
4727
4967
|
if (!sessionId) throw new Error("no session");
|
|
4728
4968
|
const parent = parentOf(path);
|
|
@@ -4737,7 +4977,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4737
4977
|
},
|
|
4738
4978
|
[client, workspaceId, sessionId, tree, runOptimistic]
|
|
4739
4979
|
);
|
|
4740
|
-
const createFile =
|
|
4980
|
+
const createFile = useCallback18(
|
|
4741
4981
|
async (path) => {
|
|
4742
4982
|
if (!sessionId) throw new Error("no session");
|
|
4743
4983
|
const parent = parentOf(path);
|
|
@@ -4751,7 +4991,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4751
4991
|
},
|
|
4752
4992
|
[client, workspaceId, sessionId, runOptimistic]
|
|
4753
4993
|
);
|
|
4754
|
-
const createDir =
|
|
4994
|
+
const createDir = useCallback18(
|
|
4755
4995
|
async (path) => {
|
|
4756
4996
|
if (!sessionId) throw new Error("no session");
|
|
4757
4997
|
const parent = parentOf(path);
|
|
@@ -4765,7 +5005,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4765
5005
|
},
|
|
4766
5006
|
[client, workspaceId, sessionId, runOptimistic]
|
|
4767
5007
|
);
|
|
4768
|
-
const deleteEntry =
|
|
5008
|
+
const deleteEntry = useCallback18(
|
|
4769
5009
|
async (path, recursive = false) => {
|
|
4770
5010
|
if (!sessionId) throw new Error("no session");
|
|
4771
5011
|
await runOptimistic(
|
|
@@ -4777,7 +5017,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4777
5017
|
},
|
|
4778
5018
|
[client, workspaceId, sessionId, runOptimistic]
|
|
4779
5019
|
);
|
|
4780
|
-
const moveEntry =
|
|
5020
|
+
const moveEntry = useCallback18(
|
|
4781
5021
|
async (path, newPath, opts) => {
|
|
4782
5022
|
if (!sessionId) throw new Error("no session");
|
|
4783
5023
|
const from = parentOf(path);
|
|
@@ -4807,7 +5047,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4807
5047
|
}
|
|
4808
5048
|
void refresh();
|
|
4809
5049
|
}, [enabled, refresh]);
|
|
4810
|
-
const refreshGitOverlay =
|
|
5050
|
+
const refreshGitOverlay = useCallback18(async () => {
|
|
4811
5051
|
if (!sessionId) return;
|
|
4812
5052
|
try {
|
|
4813
5053
|
const status = await client.gitStatus(workspaceId, sessionId, { path: rootPath });
|
|
@@ -4823,10 +5063,10 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4823
5063
|
}
|
|
4824
5064
|
}, [client, workspaceId, sessionId, rootPath, applyStatus]);
|
|
4825
5065
|
const events = options.events;
|
|
4826
|
-
const lastSeqRef =
|
|
4827
|
-
const pendingParentsRef =
|
|
4828
|
-
const pendingGitRef =
|
|
4829
|
-
const debounceRef =
|
|
5066
|
+
const lastSeqRef = useRef12(0);
|
|
5067
|
+
const pendingParentsRef = useRef12(/* @__PURE__ */ new Set());
|
|
5068
|
+
const pendingGitRef = useRef12(false);
|
|
5069
|
+
const debounceRef = useRef12(null);
|
|
4830
5070
|
useEffect12(() => {
|
|
4831
5071
|
if (!enabled || !events) return;
|
|
4832
5072
|
let sawNew = false;
|
|
@@ -4870,7 +5110,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4870
5110
|
},
|
|
4871
5111
|
[]
|
|
4872
5112
|
);
|
|
4873
|
-
const wasLiveRef =
|
|
5113
|
+
const wasLiveRef = useRef12(false);
|
|
4874
5114
|
const liveness = options.liveness;
|
|
4875
5115
|
useEffect12(() => {
|
|
4876
5116
|
const live = liveness === "warm" || liveness === "draining";
|
|
@@ -4898,7 +5138,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4898
5138
|
}
|
|
4899
5139
|
|
|
4900
5140
|
// src/hooks/use-sandbox-git.ts
|
|
4901
|
-
import { useCallback as
|
|
5141
|
+
import { useCallback as useCallback19, useEffect as useEffect13, useRef as useRef13, useState as useState19 } from "react";
|
|
4902
5142
|
function useSandboxGit(sessionId, options = {}) {
|
|
4903
5143
|
const { client, workspaceId } = useOpenGeni(options);
|
|
4904
5144
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
@@ -4911,7 +5151,7 @@ function useSandboxGit(sessionId, options = {}) {
|
|
|
4911
5151
|
const [behind, setBehind] = useState19(0);
|
|
4912
5152
|
const [loading, setLoading] = useState19(false);
|
|
4913
5153
|
const [error, setError] = useState19(null);
|
|
4914
|
-
const refresh =
|
|
5154
|
+
const refresh = useCallback19(async () => {
|
|
4915
5155
|
if (!sessionId) return;
|
|
4916
5156
|
setLoading(true);
|
|
4917
5157
|
setError(null);
|
|
@@ -4943,7 +5183,7 @@ function useSandboxGit(sessionId, options = {}) {
|
|
|
4943
5183
|
void refresh();
|
|
4944
5184
|
}, [enabled, refresh]);
|
|
4945
5185
|
const events = options.events;
|
|
4946
|
-
const lastChangeRef =
|
|
5186
|
+
const lastChangeRef = useRef13(0);
|
|
4947
5187
|
useEffect13(() => {
|
|
4948
5188
|
if (!enabled || !events) return;
|
|
4949
5189
|
let latest = lastChangeRef.current;
|
|
@@ -5192,14 +5432,14 @@ function clearErrorMessage(cause) {
|
|
|
5192
5432
|
}
|
|
5193
5433
|
|
|
5194
5434
|
// src/hooks/use-slash-commands.ts
|
|
5195
|
-
import { useCallback as
|
|
5435
|
+
import { useCallback as useCallback20, useMemo as useMemo5, useRef as useRef14, useState as useState20 } from "react";
|
|
5196
5436
|
function useSlashCommands(options) {
|
|
5197
5437
|
const { commands, context, handlers, value, setValue } = options;
|
|
5198
5438
|
const [highlight, setHighlight] = useState20(0);
|
|
5199
5439
|
const [dismissedValue, setDismissedValue] = useState20(null);
|
|
5200
5440
|
const dismissed = dismissedValue !== null && dismissedValue === value;
|
|
5201
|
-
const navigatedRef =
|
|
5202
|
-
const navTokenRef =
|
|
5441
|
+
const navigatedRef = useRef14(false);
|
|
5442
|
+
const navTokenRef = useRef14(value);
|
|
5203
5443
|
if (navTokenRef.current !== value) {
|
|
5204
5444
|
navTokenRef.current = value;
|
|
5205
5445
|
navigatedRef.current = false;
|
|
@@ -5232,7 +5472,7 @@ function useSlashCommands(options) {
|
|
|
5232
5472
|
const isCommandDraft = parsed !== null && items.length > 0;
|
|
5233
5473
|
const clampedHighlight = items.length === 0 ? 0 : Math.min(highlight, items.length - 1);
|
|
5234
5474
|
const activeArgHint = activeCommand ? argHint(activeCommand.args) : "";
|
|
5235
|
-
const buildContext =
|
|
5475
|
+
const buildContext = useCallback20(
|
|
5236
5476
|
(command) => {
|
|
5237
5477
|
if (!context) {
|
|
5238
5478
|
return null;
|
|
@@ -5241,7 +5481,7 @@ function useSlashCommands(options) {
|
|
|
5241
5481
|
},
|
|
5242
5482
|
[context, handlers]
|
|
5243
5483
|
);
|
|
5244
|
-
const execute =
|
|
5484
|
+
const execute = useCallback20(
|
|
5245
5485
|
async (command, args) => {
|
|
5246
5486
|
const ctx = buildContext(command);
|
|
5247
5487
|
if (!ctx) {
|
|
@@ -5261,20 +5501,20 @@ function useSlashCommands(options) {
|
|
|
5261
5501
|
},
|
|
5262
5502
|
[buildContext, setValue]
|
|
5263
5503
|
);
|
|
5264
|
-
const autocomplete =
|
|
5504
|
+
const autocomplete = useCallback20(
|
|
5265
5505
|
(command) => {
|
|
5266
5506
|
setValue(`/${command.name} `);
|
|
5267
5507
|
setHighlight(0);
|
|
5268
5508
|
},
|
|
5269
5509
|
[setValue]
|
|
5270
5510
|
);
|
|
5271
|
-
const autocompleteHighlighted =
|
|
5511
|
+
const autocompleteHighlighted = useCallback20(() => {
|
|
5272
5512
|
const command = items[clampedHighlight];
|
|
5273
5513
|
if (command) {
|
|
5274
5514
|
autocomplete(command);
|
|
5275
5515
|
}
|
|
5276
5516
|
}, [items, clampedHighlight, autocomplete]);
|
|
5277
|
-
const runResolved =
|
|
5517
|
+
const runResolved = useCallback20(
|
|
5278
5518
|
async (command, options2) => {
|
|
5279
5519
|
if (!parsed) {
|
|
5280
5520
|
return;
|
|
@@ -5297,7 +5537,7 @@ function useSlashCommands(options) {
|
|
|
5297
5537
|
},
|
|
5298
5538
|
[parsed, activeCommand, autocomplete, execute]
|
|
5299
5539
|
);
|
|
5300
|
-
const runHighlighted =
|
|
5540
|
+
const runHighlighted = useCallback20(async () => {
|
|
5301
5541
|
if (!parsed) {
|
|
5302
5542
|
return;
|
|
5303
5543
|
}
|
|
@@ -5316,7 +5556,7 @@ function useSlashCommands(options) {
|
|
|
5316
5556
|
}
|
|
5317
5557
|
await runResolved(command);
|
|
5318
5558
|
}, [parsed, activeCommand, items, clampedHighlight, runResolved]);
|
|
5319
|
-
const runAt =
|
|
5559
|
+
const runAt = useCallback20(
|
|
5320
5560
|
async (index) => {
|
|
5321
5561
|
const command = items[index];
|
|
5322
5562
|
if (!command) {
|
|
@@ -5326,8 +5566,8 @@ function useSlashCommands(options) {
|
|
|
5326
5566
|
},
|
|
5327
5567
|
[items, runResolved]
|
|
5328
5568
|
);
|
|
5329
|
-
const runningRef =
|
|
5330
|
-
const onKeyDown =
|
|
5569
|
+
const runningRef = useRef14(false);
|
|
5570
|
+
const onKeyDown = useCallback20(
|
|
5331
5571
|
(event) => {
|
|
5332
5572
|
if (!open) {
|
|
5333
5573
|
return false;
|
|
@@ -5469,7 +5709,7 @@ function CommandPalette({ open, items, highlight, onHighlight, onRun, argHintTex
|
|
|
5469
5709
|
// src/components/chat-composer.tsx
|
|
5470
5710
|
import { ArrowUpIcon, FileIcon, ImageIcon as ImageIcon2, LoaderCircleIcon, PaperclipIcon, RotateCwIcon, SquareIcon, XIcon as XIcon2 } from "lucide-react";
|
|
5471
5711
|
import { AnimatePresence as AnimatePresence3, motion as motion3 } from "motion/react";
|
|
5472
|
-
import { useCallback as
|
|
5712
|
+
import { useCallback as useCallback21, useEffect as useEffect14, useId as useId2, useMemo as useMemo7, useRef as useRef15, useState as useState21 } from "react";
|
|
5473
5713
|
|
|
5474
5714
|
// src/components/model-picker.tsx
|
|
5475
5715
|
import { ChevronDownIcon } from "lucide-react";
|
|
@@ -5546,15 +5786,15 @@ function ChatComposer({
|
|
|
5546
5786
|
commandContext,
|
|
5547
5787
|
onClearView
|
|
5548
5788
|
}) {
|
|
5549
|
-
const textareaRef =
|
|
5550
|
-
const fileInputRef =
|
|
5789
|
+
const textareaRef = useRef15(null);
|
|
5790
|
+
const fileInputRef = useRef15(null);
|
|
5551
5791
|
const active = status != null && ACTIVE_STATUSES.has(status);
|
|
5552
5792
|
const blockedByUpload = attachments?.uploading === true;
|
|
5553
5793
|
const hasReadyAttachment = (attachments?.readyResources.length ?? 0) > 0;
|
|
5554
5794
|
const canSend = (composer.canSend || hasReadyAttachment) && !blockedByUpload && !composer.sending;
|
|
5555
5795
|
const [dragging, setDragging] = useState21(false);
|
|
5556
5796
|
const dragCarriesFiles = (event) => event.dataTransfer != null && [...event.dataTransfer.types].includes("Files");
|
|
5557
|
-
const handleDragOver =
|
|
5797
|
+
const handleDragOver = useCallback21(
|
|
5558
5798
|
(event) => {
|
|
5559
5799
|
if (!attachments || !dragCarriesFiles(event)) {
|
|
5560
5800
|
return;
|
|
@@ -5564,7 +5804,7 @@ function ChatComposer({
|
|
|
5564
5804
|
},
|
|
5565
5805
|
[attachments]
|
|
5566
5806
|
);
|
|
5567
|
-
const handleDragLeave =
|
|
5807
|
+
const handleDragLeave = useCallback21(
|
|
5568
5808
|
(event) => {
|
|
5569
5809
|
if (!attachments) {
|
|
5570
5810
|
return;
|
|
@@ -5576,7 +5816,7 @@ function ChatComposer({
|
|
|
5576
5816
|
},
|
|
5577
5817
|
[attachments]
|
|
5578
5818
|
);
|
|
5579
|
-
const handleDrop =
|
|
5819
|
+
const handleDrop = useCallback21(
|
|
5580
5820
|
(event) => {
|
|
5581
5821
|
if (!attachments || !dragCarriesFiles(event)) {
|
|
5582
5822
|
return;
|
|
@@ -5593,7 +5833,7 @@ function ChatComposer({
|
|
|
5593
5833
|
const [helpOpen, setHelpOpen] = useState21(false);
|
|
5594
5834
|
const [confirmState, setConfirmState] = useState21(null);
|
|
5595
5835
|
const listboxId = useId2();
|
|
5596
|
-
const resize =
|
|
5836
|
+
const resize = useCallback21(() => {
|
|
5597
5837
|
const textarea = textareaRef.current;
|
|
5598
5838
|
if (!textarea) {
|
|
5599
5839
|
return;
|
|
@@ -5662,14 +5902,14 @@ function ChatComposer({
|
|
|
5662
5902
|
void composer.send();
|
|
5663
5903
|
}
|
|
5664
5904
|
};
|
|
5665
|
-
const handlePaste =
|
|
5905
|
+
const handlePaste = useCallback21(
|
|
5666
5906
|
(event) => {
|
|
5667
5907
|
onPaste?.(event);
|
|
5668
5908
|
attachments?.addFromPaste(event);
|
|
5669
5909
|
},
|
|
5670
5910
|
[onPaste, attachments]
|
|
5671
5911
|
);
|
|
5672
|
-
const handleFileChange =
|
|
5912
|
+
const handleFileChange = useCallback21(
|
|
5673
5913
|
(event) => {
|
|
5674
5914
|
if (event.target.files) {
|
|
5675
5915
|
attachments?.addFiles(event.target.files);
|
|
@@ -5915,7 +6155,7 @@ function ConfirmBar({
|
|
|
5915
6155
|
onConfirm,
|
|
5916
6156
|
returnFocusRef
|
|
5917
6157
|
}) {
|
|
5918
|
-
const confirmRef =
|
|
6158
|
+
const confirmRef = useRef15(null);
|
|
5919
6159
|
const descriptionId = useId2();
|
|
5920
6160
|
useEffect14(() => {
|
|
5921
6161
|
const returnTo = returnFocusRef?.current ?? null;
|
|
@@ -6071,7 +6311,7 @@ import {
|
|
|
6071
6311
|
TriangleAlertIcon as TriangleAlertIcon2
|
|
6072
6312
|
} from "lucide-react";
|
|
6073
6313
|
import { AnimatePresence as AnimatePresence4, motion as motion4 } from "motion/react";
|
|
6074
|
-
import { useCallback as
|
|
6314
|
+
import { useCallback as useCallback22, useEffect as useEffect15, useLayoutEffect, useMemo as useMemo8, useRef as useRef16, useState as useState22 } from "react";
|
|
6075
6315
|
|
|
6076
6316
|
// src/components/markdown.tsx
|
|
6077
6317
|
import { memo } from "react";
|
|
@@ -6230,19 +6470,38 @@ function MessageTimeline({
|
|
|
6230
6470
|
onOpenSession,
|
|
6231
6471
|
toolRegistry = defaultToolRegistry,
|
|
6232
6472
|
autoFollow = true,
|
|
6473
|
+
hasOlder = false,
|
|
6474
|
+
loadingOlder = false,
|
|
6475
|
+
onLoadOlder,
|
|
6233
6476
|
emptyState,
|
|
6234
6477
|
className
|
|
6235
6478
|
}) {
|
|
6236
6479
|
const resolvedItems = useMemo8(() => items ?? buildTimeline(events ?? []), [items, events]);
|
|
6237
6480
|
const groups = useMemo8(() => groupTimeline(resolvedItems), [resolvedItems]);
|
|
6238
|
-
const
|
|
6481
|
+
const firstGroupKey = groups[0] ? timelineGroupKey(groups[0]) : null;
|
|
6482
|
+
const scrollRef = useRef16(null);
|
|
6483
|
+
const topSentinelRef = useRef16(null);
|
|
6484
|
+
const previousBulkFirstKeyRef = useRef16(void 0);
|
|
6239
6485
|
const [pinned, setPinned] = useState22(true);
|
|
6240
|
-
const
|
|
6241
|
-
const
|
|
6486
|
+
const [bulkActive, setBulkActive] = useState22(true);
|
|
6487
|
+
const [revealed, setRevealed] = useState22(false);
|
|
6488
|
+
const programmaticScrollRef = useRef16(false);
|
|
6489
|
+
const assignScrollTop = useCallback22((node, value) => {
|
|
6490
|
+
const previous = node.scrollTop;
|
|
6491
|
+
programmaticScrollRef.current = true;
|
|
6492
|
+
node.scrollTop = value;
|
|
6493
|
+
if (node.scrollTop === previous) {
|
|
6494
|
+
programmaticScrollRef.current = false;
|
|
6495
|
+
}
|
|
6496
|
+
}, []);
|
|
6497
|
+
const pinnedRef = useRef16(true);
|
|
6498
|
+
const anchorRef = useRef16(null);
|
|
6242
6499
|
const lastItem = resolvedItems[resolvedItems.length - 1];
|
|
6243
6500
|
const streaming = lastItem !== void 0 && (lastItem.kind === "agent-message" || lastItem.kind === "reasoning") && lastItem.streaming;
|
|
6244
6501
|
const working = status === "running" && !streaming;
|
|
6245
|
-
const
|
|
6502
|
+
const firstKeyChangedForBulk = previousBulkFirstKeyRef.current !== void 0 && previousBulkFirstKeyRef.current !== firstGroupKey;
|
|
6503
|
+
const bulkRender = groups.length > 0 && (bulkActive || firstKeyChangedForBulk);
|
|
6504
|
+
const captureAnchor = useCallback22(() => {
|
|
6246
6505
|
const node = scrollRef.current;
|
|
6247
6506
|
const inner = node?.firstElementChild;
|
|
6248
6507
|
if (!node || !inner) {
|
|
@@ -6251,6 +6510,9 @@ function MessageTimeline({
|
|
|
6251
6510
|
}
|
|
6252
6511
|
const containerTop = node.getBoundingClientRect().top;
|
|
6253
6512
|
for (const child of Array.from(inner.children)) {
|
|
6513
|
+
if (child instanceof HTMLElement && child.dataset.ogTimelineChrome !== void 0) {
|
|
6514
|
+
continue;
|
|
6515
|
+
}
|
|
6254
6516
|
const rect = child.getBoundingClientRect();
|
|
6255
6517
|
if (rect.bottom > containerTop + 1) {
|
|
6256
6518
|
anchorRef.current = { el: child, top: rect.top - containerTop };
|
|
@@ -6259,12 +6521,43 @@ function MessageTimeline({
|
|
|
6259
6521
|
}
|
|
6260
6522
|
anchorRef.current = null;
|
|
6261
6523
|
}, []);
|
|
6262
|
-
|
|
6524
|
+
useLayoutEffect(() => {
|
|
6263
6525
|
const node = scrollRef.current;
|
|
6264
6526
|
if (node && autoFollow && pinned) {
|
|
6265
|
-
node
|
|
6527
|
+
assignScrollTop(node, node.scrollHeight);
|
|
6528
|
+
}
|
|
6529
|
+
if (!revealed && groups.length > 0) {
|
|
6530
|
+
setRevealed(true);
|
|
6266
6531
|
}
|
|
6267
|
-
}, [resolvedItems, working, autoFollow, pinned]);
|
|
6532
|
+
}, [resolvedItems, working, autoFollow, pinned, revealed, groups.length, assignScrollTop]);
|
|
6533
|
+
useLayoutEffect(() => {
|
|
6534
|
+
if (groups.length === 0 && revealed) {
|
|
6535
|
+
setRevealed(false);
|
|
6536
|
+
}
|
|
6537
|
+
}, [groups.length, revealed]);
|
|
6538
|
+
useLayoutEffect(() => {
|
|
6539
|
+
previousBulkFirstKeyRef.current = firstGroupKey;
|
|
6540
|
+
if (!bulkRender) {
|
|
6541
|
+
return;
|
|
6542
|
+
}
|
|
6543
|
+
setBulkActive(true);
|
|
6544
|
+
const frame = requestFrame(() => setBulkActive(false));
|
|
6545
|
+
return () => cancelFrame(frame);
|
|
6546
|
+
}, [bulkRender, firstGroupKey]);
|
|
6547
|
+
useEffect15(() => {
|
|
6548
|
+
const root = scrollRef.current;
|
|
6549
|
+
const target = topSentinelRef.current;
|
|
6550
|
+
if (!root || !target || !hasOlder || loadingOlder || !onLoadOlder || typeof IntersectionObserver === "undefined") {
|
|
6551
|
+
return;
|
|
6552
|
+
}
|
|
6553
|
+
const observer = new IntersectionObserver((entries) => {
|
|
6554
|
+
if (entries.some((entry) => entry.isIntersecting)) {
|
|
6555
|
+
onLoadOlder();
|
|
6556
|
+
}
|
|
6557
|
+
}, { root, rootMargin: "1600px 0px 0px 0px" });
|
|
6558
|
+
observer.observe(target);
|
|
6559
|
+
return () => observer.disconnect();
|
|
6560
|
+
}, [hasOlder, loadingOlder, onLoadOlder, firstGroupKey]);
|
|
6268
6561
|
useEffect15(() => {
|
|
6269
6562
|
const node = scrollRef.current;
|
|
6270
6563
|
const inner = node?.firstElementChild;
|
|
@@ -6277,7 +6570,7 @@ function MessageTimeline({
|
|
|
6277
6570
|
return;
|
|
6278
6571
|
}
|
|
6279
6572
|
if (autoFollow && pinnedRef.current) {
|
|
6280
|
-
current
|
|
6573
|
+
assignScrollTop(current, current.scrollHeight);
|
|
6281
6574
|
} else {
|
|
6282
6575
|
const anchor = anchorRef.current;
|
|
6283
6576
|
if (anchor && anchor.el.isConnected) {
|
|
@@ -6285,7 +6578,7 @@ function MessageTimeline({
|
|
|
6285
6578
|
const now = anchor.el.getBoundingClientRect().top - containerTop;
|
|
6286
6579
|
const diff = now - anchor.top;
|
|
6287
6580
|
if (diff !== 0) {
|
|
6288
|
-
current.scrollTop
|
|
6581
|
+
assignScrollTop(current, current.scrollTop + diff);
|
|
6289
6582
|
}
|
|
6290
6583
|
}
|
|
6291
6584
|
}
|
|
@@ -6293,32 +6586,47 @@ function MessageTimeline({
|
|
|
6293
6586
|
});
|
|
6294
6587
|
observer.observe(inner);
|
|
6295
6588
|
return () => observer.disconnect();
|
|
6296
|
-
}, [autoFollow, captureAnchor]);
|
|
6589
|
+
}, [autoFollow, captureAnchor, assignScrollTop]);
|
|
6297
6590
|
const onScroll = () => {
|
|
6298
6591
|
const node = scrollRef.current;
|
|
6299
6592
|
if (!node) {
|
|
6300
6593
|
return;
|
|
6301
6594
|
}
|
|
6595
|
+
const programmatic = programmaticScrollRef.current;
|
|
6596
|
+
programmaticScrollRef.current = false;
|
|
6302
6597
|
const nextPinned = node.scrollHeight - node.scrollTop - node.clientHeight < 48;
|
|
6303
|
-
|
|
6304
|
-
|
|
6598
|
+
if (nextPinned || !programmatic) {
|
|
6599
|
+
pinnedRef.current = nextPinned;
|
|
6600
|
+
setPinned(nextPinned);
|
|
6601
|
+
}
|
|
6305
6602
|
captureAnchor();
|
|
6306
6603
|
};
|
|
6307
|
-
return /* @__PURE__ */ jsx15(LightboxProvider, { children: /* @__PURE__ */ jsxs12("div", { className: cn("og-root relative flex min-h-0 flex-col", className), children: [
|
|
6308
|
-
/* @__PURE__ */ jsx15(
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6604
|
+
return /* @__PURE__ */ jsx15(LightboxProvider, { children: /* @__PURE__ */ jsx15(EntranceAnimationProvider, { value: !bulkRender, children: /* @__PURE__ */ jsxs12("div", { className: cn("og-root relative flex min-h-0 flex-col", className), children: [
|
|
6605
|
+
/* @__PURE__ */ jsx15(
|
|
6606
|
+
"div",
|
|
6607
|
+
{
|
|
6608
|
+
ref: scrollRef,
|
|
6609
|
+
onScroll,
|
|
6610
|
+
style: groups.length > 0 && !revealed ? { visibility: "hidden" } : void 0,
|
|
6611
|
+
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 [overflow-anchor:none] sm:px-6",
|
|
6612
|
+
children: /* @__PURE__ */ jsxs12("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: [
|
|
6613
|
+
groups.length === 0 && !working ? emptyState ?? /* @__PURE__ */ jsx15("p", { className: "py-10 text-center text-sm text-og-fg-subtle", children: "No activity yet." }) : null,
|
|
6614
|
+
hasOlder ? /* @__PURE__ */ jsx15("div", { ref: topSentinelRef, "data-og-top-sentinel": "", "data-og-timeline-chrome": "", "aria-hidden": "true", className: "h-px w-full shrink-0" }) : null,
|
|
6615
|
+
loadingOlder ? /* @__PURE__ */ jsx15("div", { "data-og-timeline-chrome": "", className: "flex items-center gap-2 text-sm", children: /* @__PURE__ */ jsx15("span", { className: "og-shimmer-text font-medium", children: "Loading earlier activity\u2026" }) }) : null,
|
|
6616
|
+
groups.map((group) => /* @__PURE__ */ jsx15(
|
|
6617
|
+
TimelineGroupView,
|
|
6618
|
+
{
|
|
6619
|
+
group,
|
|
6620
|
+
renderMessageText,
|
|
6621
|
+
onOpenSession,
|
|
6622
|
+
toolRegistry
|
|
6623
|
+
},
|
|
6624
|
+
timelineGroupKey(group)
|
|
6625
|
+
)),
|
|
6626
|
+
working ? /* @__PURE__ */ jsx15("div", { className: "flex items-center gap-2 text-sm", children: /* @__PURE__ */ jsx15("span", { className: "og-shimmer-text font-medium", children: "Working\u2026" }) }) : null
|
|
6627
|
+
] })
|
|
6628
|
+
}
|
|
6629
|
+
),
|
|
6322
6630
|
/* @__PURE__ */ jsx15(AnimatePresence4, { children: !pinned && autoFollow ? /* @__PURE__ */ jsxs12(
|
|
6323
6631
|
motion4.button,
|
|
6324
6632
|
{
|
|
@@ -6347,7 +6655,20 @@ function MessageTimeline({
|
|
|
6347
6655
|
]
|
|
6348
6656
|
}
|
|
6349
6657
|
) : null })
|
|
6350
|
-
] }) });
|
|
6658
|
+
] }) }) });
|
|
6659
|
+
}
|
|
6660
|
+
function requestFrame(callback) {
|
|
6661
|
+
if (typeof requestAnimationFrame === "function") {
|
|
6662
|
+
return requestAnimationFrame(callback);
|
|
6663
|
+
}
|
|
6664
|
+
return window.setTimeout(() => callback(performance.now()), 16);
|
|
6665
|
+
}
|
|
6666
|
+
function cancelFrame(id) {
|
|
6667
|
+
if (typeof cancelAnimationFrame === "function") {
|
|
6668
|
+
cancelAnimationFrame(id);
|
|
6669
|
+
return;
|
|
6670
|
+
}
|
|
6671
|
+
window.clearTimeout(id);
|
|
6351
6672
|
}
|
|
6352
6673
|
function TimelineGroupView({
|
|
6353
6674
|
group,
|
|
@@ -6448,7 +6769,8 @@ function UserMessageRow({
|
|
|
6448
6769
|
item,
|
|
6449
6770
|
renderMessageText
|
|
6450
6771
|
}) {
|
|
6451
|
-
|
|
6772
|
+
const enter = useEntranceAnimation();
|
|
6773
|
+
return /* @__PURE__ */ jsx15("div", { className: cn(enter && "animate-og-enter", "flex justify-end"), children: /* @__PURE__ */ jsxs12("div", { className: "flex max-w-[85%] min-w-0 flex-col items-end gap-1", children: [
|
|
6452
6774
|
item.pending ? /* @__PURE__ */ jsx15("span", { className: "px-1 text-og-xs text-og-fg-subtle", children: "queued" }) : null,
|
|
6453
6775
|
/* @__PURE__ */ jsx15("div", { className: "w-fit max-w-full min-w-0 rounded-og-lg rounded-br-og-xs border border-og-border bg-og-surface-2 px-4 py-2.5 text-og-md leading-6 text-og-fg", children: renderMessageText ? renderMessageText(item.text, item) : /* @__PURE__ */ jsx15(Markdown, { children: item.text }) })
|
|
6454
6776
|
] }) });
|
|
@@ -6457,8 +6779,9 @@ function AgentMessageRow({
|
|
|
6457
6779
|
item,
|
|
6458
6780
|
renderMessageText
|
|
6459
6781
|
}) {
|
|
6782
|
+
const enter = useEntranceAnimation();
|
|
6460
6783
|
const caret = item.streaming ? /* @__PURE__ */ jsx15("span", { className: "ml-0.5 inline-block h-[1.1em] w-[2px] translate-y-[3px] animate-og-blink rounded-full bg-og-accent", "aria-hidden": true }) : null;
|
|
6461
|
-
return /* @__PURE__ */ jsx15("div", { className: "animate-og-enter min-w-0 text-og-md leading-7 text-og-fg", children: renderMessageText ? /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
6784
|
+
return /* @__PURE__ */ jsx15("div", { className: cn(enter && "animate-og-enter", "min-w-0 text-og-md leading-7 text-og-fg"), children: renderMessageText ? /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
6462
6785
|
renderMessageText(item.text, item),
|
|
6463
6786
|
caret
|
|
6464
6787
|
] }) : (
|
|
@@ -6472,8 +6795,9 @@ function AgentMessageRow({
|
|
|
6472
6795
|
) });
|
|
6473
6796
|
}
|
|
6474
6797
|
function SessionStatusRow({ item }) {
|
|
6798
|
+
const enter = useEntranceAnimation();
|
|
6475
6799
|
const meta = SESSION_STATUS_META[item.status];
|
|
6476
|
-
return /* @__PURE__ */ jsxs12("div", { className: "animate-og-enter flex items-center gap-3 text-og-xs text-og-fg-subtle", role: "status", children: [
|
|
6800
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn(enter && "animate-og-enter", "flex items-center gap-3 text-og-xs text-og-fg-subtle"), role: "status", children: [
|
|
6477
6801
|
/* @__PURE__ */ jsx15("span", { className: "h-px flex-1 bg-og-border" }),
|
|
6478
6802
|
/* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
6479
6803
|
/* @__PURE__ */ jsx15(StatusDot, { status: item.status, className: "size-1" }),
|
|
@@ -6494,8 +6818,9 @@ var GOAL_META = {
|
|
|
6494
6818
|
continuation: { label: "Continuing toward the goal", pill: NEUTRAL_PILL, icon: ArrowRightIcon }
|
|
6495
6819
|
};
|
|
6496
6820
|
function GoalRow({ item }) {
|
|
6821
|
+
const enter = useEntranceAnimation();
|
|
6497
6822
|
const { label, pill, icon: Icon } = GOAL_META[item.action];
|
|
6498
|
-
return /* @__PURE__ */ jsx15("div", { className: "animate-og-enter flex justify-center", children: /* @__PURE__ */ jsxs12("span", { className: cn("inline-flex max-w-full items-center gap-1.5 rounded-full border px-3 py-1 text-og-sm", pill), children: [
|
|
6823
|
+
return /* @__PURE__ */ jsx15("div", { className: cn(enter && "animate-og-enter", "flex justify-center"), children: /* @__PURE__ */ jsxs12("span", { className: cn("inline-flex max-w-full items-center gap-1.5 rounded-full border px-3 py-1 text-og-sm", pill), children: [
|
|
6499
6824
|
/* @__PURE__ */ jsx15(Icon, { className: "size-3.5 shrink-0" }),
|
|
6500
6825
|
/* @__PURE__ */ jsxs12("span", { className: "truncate", children: [
|
|
6501
6826
|
label,
|
|
@@ -6504,8 +6829,9 @@ function GoalRow({ item }) {
|
|
|
6504
6829
|
] }) });
|
|
6505
6830
|
}
|
|
6506
6831
|
function NoticeRow({ item }) {
|
|
6832
|
+
const enter = useEntranceAnimation();
|
|
6507
6833
|
const tone = item.tone === "failed" ? "border-og-status-failed/35 bg-og-status-failed/10 text-og-status-failed" : item.tone === "waiting" ? "border-og-status-waiting/35 bg-og-status-waiting/10 text-og-status-waiting" : "border-og-border bg-og-surface-1 text-og-fg-muted";
|
|
6508
|
-
return /* @__PURE__ */ jsxs12("div", { className: cn("animate-og-enter flex items-start gap-2.5 rounded-og-md border px-3.5 py-2.5 text-sm", tone), role: "status", children: [
|
|
6834
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn(enter && "animate-og-enter", "flex items-start gap-2.5 rounded-og-md border px-3.5 py-2.5 text-sm", tone), role: "status", children: [
|
|
6509
6835
|
/* @__PURE__ */ jsx15(TriangleAlertIcon2, { className: cn("mt-0.5 size-4 shrink-0", item.tone === "cancelled" && "opacity-60") }),
|
|
6510
6836
|
/* @__PURE__ */ jsx15("span", { className: "min-w-0 whitespace-pre-wrap break-words", children: item.text })
|
|
6511
6837
|
] });
|
|
@@ -6571,7 +6897,7 @@ function FleetTile({ session, title, subtitle, onOpen, className }) {
|
|
|
6571
6897
|
}
|
|
6572
6898
|
|
|
6573
6899
|
// src/components/sandbox-terminal.tsx
|
|
6574
|
-
import { useEffect as useEffect16, useRef as
|
|
6900
|
+
import { useEffect as useEffect16, useRef as useRef17, useState as useState23 } from "react";
|
|
6575
6901
|
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
6576
6902
|
function SandboxTerminal({
|
|
6577
6903
|
result,
|
|
@@ -6586,13 +6912,13 @@ function SandboxTerminal({
|
|
|
6586
6912
|
onActivate,
|
|
6587
6913
|
className
|
|
6588
6914
|
}) {
|
|
6589
|
-
const containerRef =
|
|
6590
|
-
const termRef =
|
|
6591
|
-
const fitRef =
|
|
6592
|
-
const writtenRef =
|
|
6915
|
+
const containerRef = useRef17(null);
|
|
6916
|
+
const termRef = useRef17(null);
|
|
6917
|
+
const fitRef = useRef17(null);
|
|
6918
|
+
const writtenRef = useRef17(/* @__PURE__ */ new Set());
|
|
6593
6919
|
const [ready, setReady] = useState23(false);
|
|
6594
6920
|
const ptyWs = terminalCapability?.transport === "pty-ws" && Boolean(terminalCapability?.url);
|
|
6595
|
-
const ptyOutputQueueRef =
|
|
6921
|
+
const ptyOutputQueueRef = useRef17([]);
|
|
6596
6922
|
const ptyStream = useTerminalStream({
|
|
6597
6923
|
capability: ptyWs ? {
|
|
6598
6924
|
transport: terminalCapability.transport,
|
|
@@ -6687,7 +7013,7 @@ function SandboxTerminal({
|
|
|
6687
7013
|
if (!ready || !term || !theme) return;
|
|
6688
7014
|
term.options.theme = theme;
|
|
6689
7015
|
}, [ready, theme]);
|
|
6690
|
-
const enteredPtyRef =
|
|
7016
|
+
const enteredPtyRef = useRef17(false);
|
|
6691
7017
|
useEffect16(() => {
|
|
6692
7018
|
const term = termRef.current;
|
|
6693
7019
|
if (!ready || !term) return;
|
|
@@ -6847,10 +7173,10 @@ import {
|
|
|
6847
7173
|
Trash2Icon
|
|
6848
7174
|
} from "lucide-react";
|
|
6849
7175
|
import {
|
|
6850
|
-
useCallback as
|
|
7176
|
+
useCallback as useCallback23,
|
|
6851
7177
|
useEffect as useEffect17,
|
|
6852
7178
|
useMemo as useMemo9,
|
|
6853
|
-
useRef as
|
|
7179
|
+
useRef as useRef18,
|
|
6854
7180
|
useState as useState24
|
|
6855
7181
|
} from "react";
|
|
6856
7182
|
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
@@ -6897,9 +7223,9 @@ function FileBrowser({
|
|
|
6897
7223
|
const [dragOver, setDragOver] = useState24(null);
|
|
6898
7224
|
const [menu, setMenu] = useState24(null);
|
|
6899
7225
|
const [busy, setBusy] = useState24(false);
|
|
6900
|
-
const containerRef =
|
|
7226
|
+
const containerRef = useRef18(null);
|
|
6901
7227
|
const cursor = active ?? selectedPath ?? null;
|
|
6902
|
-
const expand =
|
|
7228
|
+
const expand = useCallback23(
|
|
6903
7229
|
async (path) => {
|
|
6904
7230
|
const node = findNode(result.tree, path);
|
|
6905
7231
|
if (node && node.kind === "dir" && node.children === void 0) {
|
|
@@ -6917,14 +7243,14 @@ function FileBrowser({
|
|
|
6917
7243
|
},
|
|
6918
7244
|
[result]
|
|
6919
7245
|
);
|
|
6920
|
-
const open =
|
|
7246
|
+
const open = useCallback23(
|
|
6921
7247
|
(path) => {
|
|
6922
7248
|
setExpanded((prev) => new Set(prev).add(path));
|
|
6923
7249
|
void expand(path);
|
|
6924
7250
|
},
|
|
6925
7251
|
[expand]
|
|
6926
7252
|
);
|
|
6927
|
-
const toggle =
|
|
7253
|
+
const toggle = useCallback23(
|
|
6928
7254
|
async (node) => {
|
|
6929
7255
|
if (node.kind !== "dir") return;
|
|
6930
7256
|
const isOpen = expanded.has(node.path);
|
|
@@ -6952,7 +7278,7 @@ function FileBrowser({
|
|
|
6952
7278
|
return rows;
|
|
6953
7279
|
}, [result.tree, expanded]);
|
|
6954
7280
|
const supportsMutation = editable;
|
|
6955
|
-
const runDelete =
|
|
7281
|
+
const runDelete = useCallback23(
|
|
6956
7282
|
async (node) => {
|
|
6957
7283
|
if (!supportsMutation) return;
|
|
6958
7284
|
const recursive = node.kind === "dir";
|
|
@@ -6971,7 +7297,7 @@ function FileBrowser({
|
|
|
6971
7297
|
},
|
|
6972
7298
|
[supportsMutation, confirmDelete, result]
|
|
6973
7299
|
);
|
|
6974
|
-
const commitCreate =
|
|
7300
|
+
const commitCreate = useCallback23(
|
|
6975
7301
|
async (name) => {
|
|
6976
7302
|
const draft = draftCreate;
|
|
6977
7303
|
setDraftCreate(null);
|
|
@@ -6996,7 +7322,7 @@ function FileBrowser({
|
|
|
6996
7322
|
},
|
|
6997
7323
|
[draftCreate, supportsMutation, result, open, onSelectFile]
|
|
6998
7324
|
);
|
|
6999
|
-
const commitRename =
|
|
7325
|
+
const commitRename = useCallback23(
|
|
7000
7326
|
async (name) => {
|
|
7001
7327
|
const draft = draftRename;
|
|
7002
7328
|
setDraftRename(null);
|
|
@@ -7019,7 +7345,7 @@ function FileBrowser({
|
|
|
7019
7345
|
},
|
|
7020
7346
|
[draftRename, supportsMutation, result, selectedPath, active, onSelectFile]
|
|
7021
7347
|
);
|
|
7022
|
-
const startCreate =
|
|
7348
|
+
const startCreate = useCallback23(
|
|
7023
7349
|
(kind) => {
|
|
7024
7350
|
if (!supportsMutation) return;
|
|
7025
7351
|
const anchor = cursor ? findNode(result.tree, cursor) : void 0;
|
|
@@ -7031,7 +7357,7 @@ function FileBrowser({
|
|
|
7031
7357
|
},
|
|
7032
7358
|
[supportsMutation, cursor, result.tree, open]
|
|
7033
7359
|
);
|
|
7034
|
-
const startRename =
|
|
7360
|
+
const startRename = useCallback23(
|
|
7035
7361
|
(node) => {
|
|
7036
7362
|
if (!supportsMutation) return;
|
|
7037
7363
|
setDraftCreate(null);
|
|
@@ -7040,7 +7366,7 @@ function FileBrowser({
|
|
|
7040
7366
|
},
|
|
7041
7367
|
[supportsMutation]
|
|
7042
7368
|
);
|
|
7043
|
-
const onDropOnto =
|
|
7369
|
+
const onDropOnto = useCallback23(
|
|
7044
7370
|
async (targetDir, sourcePath) => {
|
|
7045
7371
|
setDragOver(null);
|
|
7046
7372
|
if (!supportsMutation || !sourcePath) return;
|
|
@@ -7064,7 +7390,7 @@ function FileBrowser({
|
|
|
7064
7390
|
},
|
|
7065
7391
|
[supportsMutation, result, selectedPath, active, onSelectFile]
|
|
7066
7392
|
);
|
|
7067
|
-
const onKeyDown =
|
|
7393
|
+
const onKeyDown = useCallback23(
|
|
7068
7394
|
(e) => {
|
|
7069
7395
|
if (draftCreate || draftRename) return;
|
|
7070
7396
|
if (flatRows.length === 0) return;
|
|
@@ -7413,8 +7739,8 @@ function InlineInput({
|
|
|
7413
7739
|
onCancel
|
|
7414
7740
|
}) {
|
|
7415
7741
|
const [value, setValue] = useState24(initialValue);
|
|
7416
|
-
const ref =
|
|
7417
|
-
const doneRef =
|
|
7742
|
+
const ref = useRef18(null);
|
|
7743
|
+
const doneRef = useRef18(false);
|
|
7418
7744
|
useEffect17(() => {
|
|
7419
7745
|
const el = ref.current;
|
|
7420
7746
|
if (!el) return;
|
|
@@ -7597,10 +7923,10 @@ import { Loader2Icon as Loader2Icon2, SaveIcon } from "lucide-react";
|
|
|
7597
7923
|
import {
|
|
7598
7924
|
lazy as lazy3,
|
|
7599
7925
|
Suspense as Suspense3,
|
|
7600
|
-
useCallback as
|
|
7926
|
+
useCallback as useCallback24,
|
|
7601
7927
|
useEffect as useEffect19,
|
|
7602
7928
|
useMemo as useMemo10,
|
|
7603
|
-
useRef as
|
|
7929
|
+
useRef as useRef19,
|
|
7604
7930
|
useState as useState26
|
|
7605
7931
|
} from "react";
|
|
7606
7932
|
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
@@ -7669,7 +7995,7 @@ function CodeEditor({
|
|
|
7669
7995
|
const [saveError, setSaveError] = useState26(null);
|
|
7670
7996
|
const [savedTick, setSavedTick] = useState26(false);
|
|
7671
7997
|
const dirty = value !== baseline;
|
|
7672
|
-
const lastSeed =
|
|
7998
|
+
const lastSeed = useRef19({ path, contents: initialContents });
|
|
7673
7999
|
useEffect19(() => {
|
|
7674
8000
|
const seedChanged = lastSeed.current.path !== path || lastSeed.current.contents !== initialContents;
|
|
7675
8001
|
if (!seedChanged) return;
|
|
@@ -7712,9 +8038,9 @@ function CodeEditor({
|
|
|
7712
8038
|
cancelled = true;
|
|
7713
8039
|
};
|
|
7714
8040
|
}, [langKey]);
|
|
7715
|
-
const saveRef =
|
|
8041
|
+
const saveRef = useRef19(() => {
|
|
7716
8042
|
});
|
|
7717
|
-
const save =
|
|
8043
|
+
const save = useCallback24(async () => {
|
|
7718
8044
|
if (readOnly) return;
|
|
7719
8045
|
const snapshot = value;
|
|
7720
8046
|
if (snapshot === baseline) return;
|
|
@@ -7858,7 +8184,7 @@ function EditorSkeleton() {
|
|
|
7858
8184
|
|
|
7859
8185
|
// src/components/sandbox-files.tsx
|
|
7860
8186
|
import { FileIcon as FileIcon3 } from "lucide-react";
|
|
7861
|
-
import { useCallback as
|
|
8187
|
+
import { useCallback as useCallback25, useEffect as useEffect20, useMemo as useMemo11, useRef as useRef20, useState as useState27 } from "react";
|
|
7862
8188
|
import { Fragment as Fragment6, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
7863
8189
|
var STATUS_TINT2 = {
|
|
7864
8190
|
added: "text-og-status-idle",
|
|
@@ -7896,7 +8222,7 @@ function SandboxFiles({
|
|
|
7896
8222
|
const [staged, setStaged] = useState27(false);
|
|
7897
8223
|
const [layout, setLayout] = useState27("unified");
|
|
7898
8224
|
const [editMode, setEditMode] = useState27(false);
|
|
7899
|
-
const rootRef =
|
|
8225
|
+
const rootRef = useRef20(null);
|
|
7900
8226
|
const [wide, setWide] = useState27(false);
|
|
7901
8227
|
useEffect20(() => {
|
|
7902
8228
|
const el = rootRef.current;
|
|
@@ -7916,7 +8242,7 @@ function SandboxFiles({
|
|
|
7916
8242
|
const selectedDiff = changed.find((f) => f.path === effectiveSelected) ?? null;
|
|
7917
8243
|
const viewPath = effectiveSelected && !selectedDiff ? effectiveSelected : null;
|
|
7918
8244
|
const fileView = useFileView(viewPath, files.readFile);
|
|
7919
|
-
const selectFile =
|
|
8245
|
+
const selectFile = useCallback25((path) => {
|
|
7920
8246
|
setSelected(path);
|
|
7921
8247
|
setEditMode(false);
|
|
7922
8248
|
}, []);
|
|
@@ -8229,7 +8555,7 @@ function Notice({ children, className }) {
|
|
|
8229
8555
|
|
|
8230
8556
|
// src/components/desktop-viewer.tsx
|
|
8231
8557
|
import { LoaderCircleIcon as LoaderCircleIcon2, MonitorIcon, MousePointerClickIcon, WifiOffIcon } from "lucide-react";
|
|
8232
|
-
import { useEffect as useEffect21, useRef as
|
|
8558
|
+
import { useEffect as useEffect21, useRef as useRef21, useState as useState28 } from "react";
|
|
8233
8559
|
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
8234
8560
|
var DESKTOP_MEDIA_BACKGROUND = "#000";
|
|
8235
8561
|
function isHardUnavailable(reason) {
|
|
@@ -8262,7 +8588,7 @@ function DesktopViewer({
|
|
|
8262
8588
|
connectTimeoutMs = 13e3,
|
|
8263
8589
|
className
|
|
8264
8590
|
}) {
|
|
8265
|
-
const containerRef =
|
|
8591
|
+
const containerRef = useRef21(null);
|
|
8266
8592
|
const [consented, setConsented] = useState28(false);
|
|
8267
8593
|
const [takeControl, setTakeControl] = useState28(interactive ?? false);
|
|
8268
8594
|
const externallyControlled = interactive !== void 0;
|
|
@@ -8304,9 +8630,9 @@ function DesktopViewer({
|
|
|
8304
8630
|
});
|
|
8305
8631
|
const connected = stream.state === "connected";
|
|
8306
8632
|
const hasLiveUrl = Boolean(connectCapability?.url);
|
|
8307
|
-
const streamStateRef =
|
|
8633
|
+
const streamStateRef = useRef21(stream.state);
|
|
8308
8634
|
streamStateRef.current = stream.state;
|
|
8309
|
-
const warmKeyRef =
|
|
8635
|
+
const warmKeyRef = useRef21(null);
|
|
8310
8636
|
useEffect21(() => {
|
|
8311
8637
|
if (!isWatching || !coldWarmable || needsAck || viewerCapReached) {
|
|
8312
8638
|
if (!coldWarmable) warmKeyRef.current = null;
|
|
@@ -8599,7 +8925,7 @@ function defaultNotice(title, body, onRetry) {
|
|
|
8599
8925
|
}
|
|
8600
8926
|
|
|
8601
8927
|
// src/components/workspace-dock.tsx
|
|
8602
|
-
import { useCallback as
|
|
8928
|
+
import { useCallback as useCallback26, useEffect as useEffect22, useLayoutEffect as useLayoutEffect2, useState as useState29 } from "react";
|
|
8603
8929
|
import {
|
|
8604
8930
|
ChevronsLeftRightIcon,
|
|
8605
8931
|
Maximize2Icon,
|
|
@@ -8615,7 +8941,7 @@ import {
|
|
|
8615
8941
|
usePanelRef
|
|
8616
8942
|
} from "react-resizable-panels";
|
|
8617
8943
|
import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
8618
|
-
var useDockLayoutEffect = typeof window === "undefined" ? useEffect22 :
|
|
8944
|
+
var useDockLayoutEffect = typeof window === "undefined" ? useEffect22 : useLayoutEffect2;
|
|
8619
8945
|
var DOCK_OVERLAY_BREAKPOINT = 1024;
|
|
8620
8946
|
function useIsNarrow(maxWidth) {
|
|
8621
8947
|
const [narrow, setNarrow] = useState29(false);
|
|
@@ -8663,14 +8989,14 @@ function WorkspaceDock({
|
|
|
8663
8989
|
const current = activeTab ?? internalTab;
|
|
8664
8990
|
const tabIds = tabs.map((tab) => tab.id).join("\0");
|
|
8665
8991
|
const firstTabId = tabs[0]?.id ?? "";
|
|
8666
|
-
const setTab =
|
|
8992
|
+
const setTab = useCallback26(
|
|
8667
8993
|
(id) => {
|
|
8668
8994
|
setInternalTab(id);
|
|
8669
8995
|
onActiveTabChange?.(id);
|
|
8670
8996
|
},
|
|
8671
8997
|
[onActiveTabChange]
|
|
8672
8998
|
);
|
|
8673
|
-
const setCollapsed =
|
|
8999
|
+
const setCollapsed = useCallback26(
|
|
8674
9000
|
(next) => {
|
|
8675
9001
|
setInternalCollapsed((previous) => previous === next ? previous : next);
|
|
8676
9002
|
onCollapsedChange?.(next);
|
|
@@ -8693,11 +9019,11 @@ function WorkspaceDock({
|
|
|
8693
9019
|
setTab(firstTabId);
|
|
8694
9020
|
}
|
|
8695
9021
|
}, [tabIds, firstTabId, current, setTab]);
|
|
8696
|
-
const collapse =
|
|
9022
|
+
const collapse = useCallback26(() => {
|
|
8697
9023
|
dockPanelRef.current?.collapse();
|
|
8698
9024
|
setCollapsed(true);
|
|
8699
9025
|
}, [dockPanelRef, setCollapsed]);
|
|
8700
|
-
const expand =
|
|
9026
|
+
const expand = useCallback26(() => {
|
|
8701
9027
|
dockPanelRef.current?.expand();
|
|
8702
9028
|
setCollapsed(false);
|
|
8703
9029
|
}, [dockPanelRef, setCollapsed]);
|
|
@@ -8866,7 +9192,7 @@ function DockChrome({
|
|
|
8866
9192
|
}
|
|
8867
9193
|
|
|
8868
9194
|
// src/hooks/use-codex-accounts.ts
|
|
8869
|
-
import { useCallback as
|
|
9195
|
+
import { useCallback as useCallback27, useState as useState30 } from "react";
|
|
8870
9196
|
function isCodexAccountEvent(event) {
|
|
8871
9197
|
return event.type === "codex.account.switched" || event.type === "turn.started";
|
|
8872
9198
|
}
|
|
@@ -8883,7 +9209,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8883
9209
|
const codexClient = options.codexClient ?? client;
|
|
8884
9210
|
const sessionId = options.sessionId;
|
|
8885
9211
|
const sharedEvents = options.events;
|
|
8886
|
-
const load =
|
|
9212
|
+
const load = useCallback27(async () => {
|
|
8887
9213
|
const accountsP = codexClient.listCodexAccounts(workspaceId);
|
|
8888
9214
|
const sessionP = sessionId && codexClient.getSession ? codexClient.getSession(workspaceId, sessionId).catch(() => null) : Promise.resolve(null);
|
|
8889
9215
|
const [acc, session] = await Promise.all([accountsP, sessionP]);
|
|
@@ -8907,7 +9233,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8907
9233
|
() => void state.refresh(),
|
|
8908
9234
|
{ enabled: options.enabled ?? true, ...sharedEvents !== void 0 ? { events: sharedEvents } : {} }
|
|
8909
9235
|
);
|
|
8910
|
-
const pin =
|
|
9236
|
+
const pin = useCallback27(
|
|
8911
9237
|
async (target) => {
|
|
8912
9238
|
if (!sessionId || !codexClient.pinSessionCodexAccount) {
|
|
8913
9239
|
return false;
|
|
@@ -8923,7 +9249,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8923
9249
|
},
|
|
8924
9250
|
[codexClient, workspaceId, sessionId, mutation.run, state.refresh]
|
|
8925
9251
|
);
|
|
8926
|
-
const refreshUsage =
|
|
9252
|
+
const refreshUsage = useCallback27(
|
|
8927
9253
|
async () => {
|
|
8928
9254
|
if (!codexClient.refreshCodexUsage) {
|
|
8929
9255
|
return false;
|