@opengeni/react 0.6.3 → 0.8.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 +20 -6
- package/dist/index.js +538 -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-events.ts +283 -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,42 @@ function formatDurationFacet(durationMs) {
|
|
|
2734
2755
|
}
|
|
2735
2756
|
|
|
2736
2757
|
// src/hooks/use-session-events.ts
|
|
2758
|
+
var TAIL_PAGE_SIZE = 5e3;
|
|
2759
|
+
var INITIAL_GROUP_TARGET = 48;
|
|
2760
|
+
var INITIAL_FETCH_CAP = 3;
|
|
2761
|
+
var OLDER_GROUP_TARGET = 32;
|
|
2762
|
+
var OLDER_FETCH_CAP = 2;
|
|
2763
|
+
var BOUNDARY_PAGE_CAP = 4;
|
|
2737
2764
|
function useSessionEvents(sessionId, options = {}) {
|
|
2738
2765
|
const { client, workspaceId } = useOpenGeni(options);
|
|
2739
2766
|
const enabled = options.enabled ?? true;
|
|
2740
2767
|
const after = options.after ?? 0;
|
|
2768
|
+
const replay = options.replay ?? "windowed";
|
|
2769
|
+
const fullReplay = replay === "full" || after !== 0;
|
|
2741
2770
|
const [events, setEvents] = useState8([]);
|
|
2742
2771
|
const [connectionState, setConnectionState] = useState8("idle");
|
|
2743
2772
|
const [error, setError] = useState8(null);
|
|
2744
|
-
const
|
|
2745
|
-
const
|
|
2773
|
+
const [hasOlder, setHasOlder] = useState8(false);
|
|
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);
|
|
2752
2790
|
lastSequenceRef.current = after;
|
|
2791
|
+
oldestSequenceRef.current = null;
|
|
2792
|
+
hasOlderRef.current = false;
|
|
2793
|
+
loadingOlderRef.current = false;
|
|
2753
2794
|
}
|
|
2754
2795
|
if (!sessionId || !enabled) {
|
|
2755
2796
|
setConnectionState("idle");
|
|
@@ -2767,7 +2808,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
2767
2808
|
pending = [];
|
|
2768
2809
|
const lastInBatch = batch[batch.length - 1];
|
|
2769
2810
|
if (lastInBatch) {
|
|
2770
|
-
lastSequenceRef.current =
|
|
2811
|
+
lastSequenceRef.current = Math.max(lastSequenceRef.current, ...batch.map(eventResumeSequence));
|
|
2771
2812
|
}
|
|
2772
2813
|
setEvents((existing) => [...existing, ...batch]);
|
|
2773
2814
|
};
|
|
@@ -2776,6 +2817,24 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
2776
2817
|
};
|
|
2777
2818
|
void (async () => {
|
|
2778
2819
|
try {
|
|
2820
|
+
if (!fullReplay) {
|
|
2821
|
+
setConnectionState("connecting");
|
|
2822
|
+
const window2 = await loadEventWindow(client, workspaceId, sessionId, {
|
|
2823
|
+
before: Number.MAX_SAFE_INTEGER,
|
|
2824
|
+
pageSize: TAIL_PAGE_SIZE,
|
|
2825
|
+
targetGroups: INITIAL_GROUP_TARGET,
|
|
2826
|
+
maxFetches: INITIAL_FETCH_CAP,
|
|
2827
|
+
signal: controller.signal
|
|
2828
|
+
});
|
|
2829
|
+
if (controller.signal.aborted) {
|
|
2830
|
+
return;
|
|
2831
|
+
}
|
|
2832
|
+
oldestSequenceRef.current = window2.oldestSequence;
|
|
2833
|
+
hasOlderRef.current = window2.hasOlder;
|
|
2834
|
+
lastSequenceRef.current = window2.newestSequence;
|
|
2835
|
+
setHasOlder(window2.hasOlder);
|
|
2836
|
+
setEvents(window2.events);
|
|
2837
|
+
}
|
|
2779
2838
|
const stream = client.streamEvents(workspaceId, sessionId, {
|
|
2780
2839
|
after: lastSequenceRef.current,
|
|
2781
2840
|
signal: controller.signal,
|
|
@@ -2807,7 +2866,51 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
2807
2866
|
clearTimeout(flushTimer);
|
|
2808
2867
|
}
|
|
2809
2868
|
};
|
|
2810
|
-
}, [client, workspaceId, sessionId, after, enabled]);
|
|
2869
|
+
}, [client, workspaceId, sessionId, after, enabled, fullReplay]);
|
|
2870
|
+
const loadOlder = useCallback3(async () => {
|
|
2871
|
+
if (!sessionId || fullReplay || loadingOlderRef.current || !hasOlderRef.current) {
|
|
2872
|
+
return false;
|
|
2873
|
+
}
|
|
2874
|
+
const before = oldestSequenceRef.current;
|
|
2875
|
+
if (before === null) {
|
|
2876
|
+
hasOlderRef.current = false;
|
|
2877
|
+
setHasOlder(false);
|
|
2878
|
+
return false;
|
|
2879
|
+
}
|
|
2880
|
+
const generation = generationRef.current;
|
|
2881
|
+
loadingOlderRef.current = true;
|
|
2882
|
+
setLoadingOlder(true);
|
|
2883
|
+
try {
|
|
2884
|
+
const window2 = await loadEventWindow(client, workspaceId, sessionId, {
|
|
2885
|
+
before,
|
|
2886
|
+
pageSize: TAIL_PAGE_SIZE,
|
|
2887
|
+
targetGroups: OLDER_GROUP_TARGET,
|
|
2888
|
+
maxFetches: OLDER_FETCH_CAP
|
|
2889
|
+
});
|
|
2890
|
+
if (generationRef.current !== generation) {
|
|
2891
|
+
return false;
|
|
2892
|
+
}
|
|
2893
|
+
if (window2.events.length === 0) {
|
|
2894
|
+
oldestSequenceRef.current = null;
|
|
2895
|
+
hasOlderRef.current = false;
|
|
2896
|
+
setHasOlder(false);
|
|
2897
|
+
return false;
|
|
2898
|
+
}
|
|
2899
|
+
oldestSequenceRef.current = window2.oldestSequence;
|
|
2900
|
+
hasOlderRef.current = window2.hasOlder;
|
|
2901
|
+
setHasOlder(window2.hasOlder);
|
|
2902
|
+
setEvents((existing) => {
|
|
2903
|
+
assertPrependOrder(existing, window2.events);
|
|
2904
|
+
return [...window2.events, ...existing];
|
|
2905
|
+
});
|
|
2906
|
+
return window2.hasOlder;
|
|
2907
|
+
} finally {
|
|
2908
|
+
if (generationRef.current === generation) {
|
|
2909
|
+
loadingOlderRef.current = false;
|
|
2910
|
+
setLoadingOlder(false);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
}, [client, workspaceId, sessionId, fullReplay]);
|
|
2811
2914
|
const timeline = useMemo2(() => buildTimeline(events), [events]);
|
|
2812
2915
|
const sessionStatus = useMemo2(() => sessionStatusFromEvents(events), [events]);
|
|
2813
2916
|
return {
|
|
@@ -2816,12 +2919,143 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
2816
2919
|
sessionStatus,
|
|
2817
2920
|
connectionState,
|
|
2818
2921
|
lastSequence: lastSequenceRef.current,
|
|
2922
|
+
hasOlder: fullReplay ? false : hasOlder,
|
|
2923
|
+
loadingOlder: fullReplay ? false : loadingOlder,
|
|
2924
|
+
loadOlder,
|
|
2819
2925
|
error
|
|
2820
2926
|
};
|
|
2821
2927
|
}
|
|
2928
|
+
async function loadEventWindow(client, workspaceId, sessionId, options) {
|
|
2929
|
+
let cursor = options.before;
|
|
2930
|
+
let buffer = [];
|
|
2931
|
+
let reachedStart = false;
|
|
2932
|
+
let fetches = 0;
|
|
2933
|
+
while (fetches < options.maxFetches) {
|
|
2934
|
+
if (buffer.length > 0 && groupCount(buffer) >= options.targetGroups) {
|
|
2935
|
+
break;
|
|
2936
|
+
}
|
|
2937
|
+
const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {
|
|
2938
|
+
pageSize: options.pageSize,
|
|
2939
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2940
|
+
});
|
|
2941
|
+
fetches += 1;
|
|
2942
|
+
if (page.length === 0) {
|
|
2943
|
+
reachedStart = true;
|
|
2944
|
+
break;
|
|
2945
|
+
}
|
|
2946
|
+
assertAscending(page);
|
|
2947
|
+
buffer = [...page, ...buffer];
|
|
2948
|
+
cursor = page[0].sequence;
|
|
2949
|
+
if (isLogStart(page[0])) {
|
|
2950
|
+
reachedStart = true;
|
|
2951
|
+
break;
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
let snapPages = 0;
|
|
2955
|
+
while (!reachedStart && findBoundaryIndex(buffer) === -1 && snapPages < BOUNDARY_PAGE_CAP && fetches < options.maxFetches) {
|
|
2956
|
+
const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {
|
|
2957
|
+
pageSize: options.pageSize,
|
|
2958
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2959
|
+
});
|
|
2960
|
+
fetches += 1;
|
|
2961
|
+
snapPages += 1;
|
|
2962
|
+
if (page.length === 0) {
|
|
2963
|
+
reachedStart = true;
|
|
2964
|
+
break;
|
|
2965
|
+
}
|
|
2966
|
+
assertAscending(page);
|
|
2967
|
+
buffer = [...page, ...buffer];
|
|
2968
|
+
cursor = page[0].sequence;
|
|
2969
|
+
if (isLogStart(page[0])) {
|
|
2970
|
+
reachedStart = true;
|
|
2971
|
+
break;
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
if (!reachedStart) {
|
|
2975
|
+
const boundary = findBoundaryIndex(buffer);
|
|
2976
|
+
if (boundary > 0) {
|
|
2977
|
+
buffer = buffer.slice(boundary);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
const oldest = buffer[0] ?? null;
|
|
2981
|
+
const newest = buffer[buffer.length - 1] ?? null;
|
|
2982
|
+
return {
|
|
2983
|
+
events: buffer,
|
|
2984
|
+
oldestSequence: oldest?.sequence ?? null,
|
|
2985
|
+
newestSequence: newest ? maxResumeSequence(buffer) : 0,
|
|
2986
|
+
hasOlder: buffer.length > 0 && !reachedStart && oldest?.type !== "session.created"
|
|
2987
|
+
};
|
|
2988
|
+
}
|
|
2989
|
+
function findBoundaryIndex(events) {
|
|
2990
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
2991
|
+
const type = events[index].type;
|
|
2992
|
+
if (type === "session.created" || type === "user.message") {
|
|
2993
|
+
return index;
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
return -1;
|
|
2997
|
+
}
|
|
2998
|
+
async function loadPreviousPage(client, workspaceId, sessionId, before, options) {
|
|
2999
|
+
if (options.signal?.aborted) {
|
|
3000
|
+
throw abortError();
|
|
3001
|
+
}
|
|
3002
|
+
const requested = options.pageSize;
|
|
3003
|
+
if (requested === 0) {
|
|
3004
|
+
return Object.assign([], { requested });
|
|
3005
|
+
}
|
|
3006
|
+
const page = await client.listEvents(workspaceId, sessionId, { before, limit: requested, compact: true });
|
|
3007
|
+
if (options.signal?.aborted) {
|
|
3008
|
+
throw abortError();
|
|
3009
|
+
}
|
|
3010
|
+
return Object.assign(page, { requested });
|
|
3011
|
+
}
|
|
3012
|
+
function groupCount(events) {
|
|
3013
|
+
if (events.length === 0) {
|
|
3014
|
+
return 0;
|
|
3015
|
+
}
|
|
3016
|
+
return groupTimeline(buildTimeline(events)).length;
|
|
3017
|
+
}
|
|
3018
|
+
function isLogStart(event) {
|
|
3019
|
+
return event.type === "session.created" || event.sequence <= 1;
|
|
3020
|
+
}
|
|
3021
|
+
function maxResumeSequence(events) {
|
|
3022
|
+
return events.reduce((max, event) => Math.max(max, eventResumeSequence(event)), 0);
|
|
3023
|
+
}
|
|
3024
|
+
function eventResumeSequence(event) {
|
|
3025
|
+
const payload = asRecord2(event.payload);
|
|
3026
|
+
const coalescedUntil = Number(payload.coalescedUntil);
|
|
3027
|
+
return Math.max(event.sequence, Number.isFinite(coalescedUntil) ? Math.floor(coalescedUntil) : 0);
|
|
3028
|
+
}
|
|
3029
|
+
function asRecord2(value) {
|
|
3030
|
+
return value && typeof value === "object" ? value : {};
|
|
3031
|
+
}
|
|
3032
|
+
function assertAscending(events) {
|
|
3033
|
+
for (let index = 1; index < events.length; index += 1) {
|
|
3034
|
+
if (events[index - 1].sequence >= events[index].sequence) {
|
|
3035
|
+
throw new Error("@opengeni/react: session events must be ordered by ascending sequence");
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
function assertPrependOrder(existing, older) {
|
|
3040
|
+
if (!shouldAssertDevelopment() || existing.length === 0 || older.length === 0) {
|
|
3041
|
+
return;
|
|
3042
|
+
}
|
|
3043
|
+
if (older[older.length - 1].sequence >= existing[0].sequence) {
|
|
3044
|
+
throw new Error("@opengeni/react: loadOlder returned overlapping session events");
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
function shouldAssertDevelopment() {
|
|
3048
|
+
const processEnv = globalThis.process?.env;
|
|
3049
|
+
return processEnv !== void 0 && processEnv.NODE_ENV !== "production";
|
|
3050
|
+
}
|
|
3051
|
+
function abortError() {
|
|
3052
|
+
const error = new Error("The operation was aborted.");
|
|
3053
|
+
error.name = "AbortError";
|
|
3054
|
+
return error;
|
|
3055
|
+
}
|
|
2822
3056
|
|
|
2823
3057
|
// src/hooks/use-composer.ts
|
|
2824
|
-
import { useCallback as
|
|
3058
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useRef as useRef3, useState as useState9 } from "react";
|
|
2825
3059
|
function useComposer(sessionId, options = {}) {
|
|
2826
3060
|
const { client, workspaceId } = useOpenGeni(options);
|
|
2827
3061
|
const defaultMode = options.defaultMode ?? "queue";
|
|
@@ -2830,14 +3064,14 @@ function useComposer(sessionId, options = {}) {
|
|
|
2830
3064
|
const [sending, setSending] = useState9(false);
|
|
2831
3065
|
const [interrupting, setInterrupting] = useState9(false);
|
|
2832
3066
|
const [error, setError] = useState9(null);
|
|
2833
|
-
const pendingClientEventId =
|
|
3067
|
+
const pendingClientEventId = useRef3(null);
|
|
2834
3068
|
const onSent = options.onSent;
|
|
2835
|
-
const modeRef =
|
|
3069
|
+
const modeRef = useRef3(mode);
|
|
2836
3070
|
modeRef.current = mode;
|
|
2837
|
-
const sendExtrasRef =
|
|
3071
|
+
const sendExtrasRef = useRef3(options.sendExtras);
|
|
2838
3072
|
sendExtrasRef.current = options.sendExtras;
|
|
2839
3073
|
const targetKey = `${workspaceId}\0${sessionId ?? ""}`;
|
|
2840
|
-
const targetKeyRef =
|
|
3074
|
+
const targetKeyRef = useRef3(targetKey);
|
|
2841
3075
|
useEffect4(() => {
|
|
2842
3076
|
if (targetKeyRef.current !== targetKey) {
|
|
2843
3077
|
targetKeyRef.current = targetKey;
|
|
@@ -2847,7 +3081,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
2847
3081
|
setMode(defaultMode);
|
|
2848
3082
|
}
|
|
2849
3083
|
}, [targetKey, defaultMode]);
|
|
2850
|
-
const send =
|
|
3084
|
+
const send = useCallback4(
|
|
2851
3085
|
async (explicit) => {
|
|
2852
3086
|
const draftAtSend = value;
|
|
2853
3087
|
const text = (explicit ?? draftAtSend).trim();
|
|
@@ -2883,7 +3117,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
2883
3117
|
[client, workspaceId, sessionId, value, sending, onSent]
|
|
2884
3118
|
);
|
|
2885
3119
|
const hasReadyResources = (resolveSendExtras(sendExtrasRef.current).resources?.length ?? 0) > 0;
|
|
2886
|
-
const interrupt =
|
|
3120
|
+
const interrupt = useCallback4(
|
|
2887
3121
|
async (reason) => {
|
|
2888
3122
|
if (!sessionId || interrupting) {
|
|
2889
3123
|
return;
|
|
@@ -2900,7 +3134,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
2900
3134
|
},
|
|
2901
3135
|
[client, workspaceId, sessionId, interrupting]
|
|
2902
3136
|
);
|
|
2903
|
-
const updateValue =
|
|
3137
|
+
const updateValue = useCallback4((next) => {
|
|
2904
3138
|
pendingClientEventId.current = null;
|
|
2905
3139
|
setValue(next);
|
|
2906
3140
|
}, []);
|
|
@@ -2915,7 +3149,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
2915
3149
|
interrupt,
|
|
2916
3150
|
interrupting,
|
|
2917
3151
|
error,
|
|
2918
|
-
clearError:
|
|
3152
|
+
clearError: useCallback4(() => setError(null), [])
|
|
2919
3153
|
};
|
|
2920
3154
|
}
|
|
2921
3155
|
var FILE_ONLY_MESSAGE_TEXT = "(see attached files)";
|
|
@@ -2940,14 +3174,14 @@ function generateClientEventId() {
|
|
|
2940
3174
|
}
|
|
2941
3175
|
|
|
2942
3176
|
// src/hooks/use-file-attachments.ts
|
|
2943
|
-
import { useCallback as
|
|
3177
|
+
import { useCallback as useCallback5, useRef as useRef4, useState as useState10 } from "react";
|
|
2944
3178
|
var isImage = (file) => file.type.startsWith("image/");
|
|
2945
3179
|
function useFileAttachments(options = {}) {
|
|
2946
3180
|
const { client, workspaceId } = useOpenGeni(options);
|
|
2947
3181
|
const pasteFilter = options.pasteFilter ?? isImage;
|
|
2948
3182
|
const [attachments, setAttachments] = useState10([]);
|
|
2949
|
-
const sources =
|
|
2950
|
-
const startUpload =
|
|
3183
|
+
const sources = useRef4(/* @__PURE__ */ new Map());
|
|
3184
|
+
const startUpload = useCallback5((id, file) => {
|
|
2951
3185
|
void client.uploadFile(workspaceId, {
|
|
2952
3186
|
filename: file.name || "file",
|
|
2953
3187
|
contentType: file.type || "application/octet-stream",
|
|
@@ -2958,7 +3192,7 @@ function useFileAttachments(options = {}) {
|
|
|
2958
3192
|
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "failed", error: error instanceof Error ? error.message : String(error) } : attachment));
|
|
2959
3193
|
});
|
|
2960
3194
|
}, [client, workspaceId]);
|
|
2961
|
-
const addFiles =
|
|
3195
|
+
const addFiles = useCallback5((files) => {
|
|
2962
3196
|
for (const file of files) {
|
|
2963
3197
|
const id = crypto.randomUUID();
|
|
2964
3198
|
sources.current.set(id, file);
|
|
@@ -2974,7 +3208,7 @@ function useFileAttachments(options = {}) {
|
|
|
2974
3208
|
startUpload(id, file);
|
|
2975
3209
|
}
|
|
2976
3210
|
}, [startUpload]);
|
|
2977
|
-
const retry =
|
|
3211
|
+
const retry = useCallback5((id) => {
|
|
2978
3212
|
const file = sources.current.get(id);
|
|
2979
3213
|
if (!file) {
|
|
2980
3214
|
return;
|
|
@@ -2982,7 +3216,7 @@ function useFileAttachments(options = {}) {
|
|
|
2982
3216
|
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "uploading", error: void 0 } : attachment));
|
|
2983
3217
|
startUpload(id, file);
|
|
2984
3218
|
}, [startUpload]);
|
|
2985
|
-
const addFromPaste =
|
|
3219
|
+
const addFromPaste = useCallback5((event) => {
|
|
2986
3220
|
const clipboardFiles = event.clipboardData?.files;
|
|
2987
3221
|
if (!clipboardFiles) {
|
|
2988
3222
|
return;
|
|
@@ -2992,7 +3226,7 @@ function useFileAttachments(options = {}) {
|
|
|
2992
3226
|
addFiles(files);
|
|
2993
3227
|
}
|
|
2994
3228
|
}, [addFiles, pasteFilter]);
|
|
2995
|
-
const remove =
|
|
3229
|
+
const remove = useCallback5((id) => {
|
|
2996
3230
|
sources.current.delete(id);
|
|
2997
3231
|
setAttachments((current) => {
|
|
2998
3232
|
const removed = current.find((attachment) => attachment.id === id);
|
|
@@ -3002,7 +3236,7 @@ function useFileAttachments(options = {}) {
|
|
|
3002
3236
|
return current.filter((attachment) => attachment.id !== id);
|
|
3003
3237
|
});
|
|
3004
3238
|
}, []);
|
|
3005
|
-
const clear =
|
|
3239
|
+
const clear = useCallback5(() => {
|
|
3006
3240
|
sources.current.clear();
|
|
3007
3241
|
setAttachments((current) => {
|
|
3008
3242
|
for (const attachment of current) {
|
|
@@ -3026,7 +3260,7 @@ function useFileAttachments(options = {}) {
|
|
|
3026
3260
|
}
|
|
3027
3261
|
|
|
3028
3262
|
// src/hooks/use-turn-queue.ts
|
|
3029
|
-
import { useCallback as
|
|
3263
|
+
import { useCallback as useCallback6, useEffect as useEffect5, useRef as useRef5, useState as useState11 } from "react";
|
|
3030
3264
|
function isTurnQueueEvent(event) {
|
|
3031
3265
|
return event.type.startsWith("turn.");
|
|
3032
3266
|
}
|
|
@@ -3070,9 +3304,9 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3070
3304
|
const [loading, setLoading] = useState11(enabled);
|
|
3071
3305
|
const [error, setError] = useState11(null);
|
|
3072
3306
|
const mutation = useMutationRunner();
|
|
3073
|
-
const generation =
|
|
3074
|
-
const targetKeyRef =
|
|
3075
|
-
const load =
|
|
3307
|
+
const generation = useRef5(0);
|
|
3308
|
+
const targetKeyRef = useRef5(null);
|
|
3309
|
+
const load = useCallback6(async () => {
|
|
3076
3310
|
if (!sessionId) {
|
|
3077
3311
|
return;
|
|
3078
3312
|
}
|
|
@@ -3121,7 +3355,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3121
3355
|
enabled,
|
|
3122
3356
|
...options.events !== void 0 ? { events: options.events } : {}
|
|
3123
3357
|
});
|
|
3124
|
-
const editTurn =
|
|
3358
|
+
const editTurn = useCallback6(
|
|
3125
3359
|
async (turnId, update) => {
|
|
3126
3360
|
if (!sessionId) {
|
|
3127
3361
|
return null;
|
|
@@ -3137,7 +3371,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3137
3371
|
},
|
|
3138
3372
|
[client, workspaceId, sessionId, mutation.run, load]
|
|
3139
3373
|
);
|
|
3140
|
-
const reorderTurns =
|
|
3374
|
+
const reorderTurns = useCallback6(
|
|
3141
3375
|
async (turnIds) => {
|
|
3142
3376
|
if (!sessionId || turnIds.length === 0) {
|
|
3143
3377
|
return null;
|
|
@@ -3156,7 +3390,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3156
3390
|
},
|
|
3157
3391
|
[client, workspaceId, sessionId, mutation.run, load]
|
|
3158
3392
|
);
|
|
3159
|
-
const removeTurn =
|
|
3393
|
+
const removeTurn = useCallback6(
|
|
3160
3394
|
async (turnId) => {
|
|
3161
3395
|
if (!sessionId) {
|
|
3162
3396
|
return null;
|
|
@@ -3190,7 +3424,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3190
3424
|
|
|
3191
3425
|
// src/hooks/use-goal.ts
|
|
3192
3426
|
import { OpenGeniApiError } from "@opengeni/sdk";
|
|
3193
|
-
import { useCallback as
|
|
3427
|
+
import { useCallback as useCallback7, useEffect as useEffect6, useRef as useRef6, useState as useState12 } from "react";
|
|
3194
3428
|
function isGoalEvent(event) {
|
|
3195
3429
|
return event.type.startsWith("goal.");
|
|
3196
3430
|
}
|
|
@@ -3203,9 +3437,9 @@ function useGoal(sessionId, options = {}) {
|
|
|
3203
3437
|
const [loading, setLoading] = useState12(enabled);
|
|
3204
3438
|
const [error, setError] = useState12(null);
|
|
3205
3439
|
const mutation = useMutationRunner();
|
|
3206
|
-
const generation =
|
|
3207
|
-
const targetKeyRef =
|
|
3208
|
-
const load =
|
|
3440
|
+
const generation = useRef6(0);
|
|
3441
|
+
const targetKeyRef = useRef6(null);
|
|
3442
|
+
const load = useCallback7(async () => {
|
|
3209
3443
|
if (!sessionId) {
|
|
3210
3444
|
return;
|
|
3211
3445
|
}
|
|
@@ -3266,7 +3500,7 @@ function useGoal(sessionId, options = {}) {
|
|
|
3266
3500
|
enabled,
|
|
3267
3501
|
...sharedEvents !== void 0 ? { events: sharedEvents } : {}
|
|
3268
3502
|
});
|
|
3269
|
-
const pause =
|
|
3503
|
+
const pause = useCallback7(
|
|
3270
3504
|
async (rationale) => {
|
|
3271
3505
|
if (!sessionId) {
|
|
3272
3506
|
return null;
|
|
@@ -3282,7 +3516,7 @@ function useGoal(sessionId, options = {}) {
|
|
|
3282
3516
|
},
|
|
3283
3517
|
[client, workspaceId, sessionId, mutation.run]
|
|
3284
3518
|
);
|
|
3285
|
-
const resume =
|
|
3519
|
+
const resume = useCallback7(async () => {
|
|
3286
3520
|
if (!sessionId) {
|
|
3287
3521
|
return null;
|
|
3288
3522
|
}
|
|
@@ -3309,12 +3543,12 @@ function useGoal(sessionId, options = {}) {
|
|
|
3309
3543
|
}
|
|
3310
3544
|
|
|
3311
3545
|
// src/hooks/use-session-control.ts
|
|
3312
|
-
import { useCallback as
|
|
3546
|
+
import { useCallback as useCallback8 } from "react";
|
|
3313
3547
|
function useSessionControl(sessionId, options = {}) {
|
|
3314
3548
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3315
3549
|
const interruptMutation = useMutationRunner();
|
|
3316
3550
|
const approvalMutation = useMutationRunner();
|
|
3317
|
-
const interrupt =
|
|
3551
|
+
const interrupt = useCallback8(
|
|
3318
3552
|
async (reason) => {
|
|
3319
3553
|
if (!sessionId) {
|
|
3320
3554
|
return null;
|
|
@@ -3323,7 +3557,7 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
3323
3557
|
},
|
|
3324
3558
|
[client, workspaceId, sessionId, interruptMutation.run]
|
|
3325
3559
|
);
|
|
3326
|
-
const decide =
|
|
3560
|
+
const decide = useCallback8(
|
|
3327
3561
|
async (approvalId, decision, message) => {
|
|
3328
3562
|
if (!sessionId) {
|
|
3329
3563
|
return null;
|
|
@@ -3336,16 +3570,16 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
3336
3570
|
},
|
|
3337
3571
|
[client, workspaceId, sessionId, approvalMutation.run]
|
|
3338
3572
|
);
|
|
3339
|
-
const approve =
|
|
3573
|
+
const approve = useCallback8(
|
|
3340
3574
|
async (approvalId, message) => await decide(approvalId, "approve", message),
|
|
3341
3575
|
[decide]
|
|
3342
3576
|
);
|
|
3343
|
-
const reject =
|
|
3577
|
+
const reject = useCallback8(
|
|
3344
3578
|
async (approvalId, message) => await decide(approvalId, "reject", message),
|
|
3345
3579
|
[decide]
|
|
3346
3580
|
);
|
|
3347
3581
|
const error = approvalMutation.mutationError ?? interruptMutation.mutationError;
|
|
3348
|
-
const clearError =
|
|
3582
|
+
const clearError = useCallback8(() => {
|
|
3349
3583
|
interruptMutation.clearMutationError();
|
|
3350
3584
|
approvalMutation.clearMutationError();
|
|
3351
3585
|
}, [interruptMutation.clearMutationError, approvalMutation.clearMutationError]);
|
|
@@ -3361,11 +3595,11 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
3361
3595
|
}
|
|
3362
3596
|
|
|
3363
3597
|
// src/hooks/use-scheduled-tasks.ts
|
|
3364
|
-
import { useCallback as
|
|
3598
|
+
import { useCallback as useCallback9 } from "react";
|
|
3365
3599
|
function useScheduledTasks(options = {}) {
|
|
3366
3600
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3367
3601
|
const limit = options.limit;
|
|
3368
|
-
const load =
|
|
3602
|
+
const load = useCallback9(
|
|
3369
3603
|
async () => await client.listScheduledTasks(workspaceId, limit !== void 0 ? { limit } : {}),
|
|
3370
3604
|
[client, workspaceId, limit]
|
|
3371
3605
|
);
|
|
@@ -3374,11 +3608,11 @@ function useScheduledTasks(options = {}) {
|
|
|
3374
3608
|
}
|
|
3375
3609
|
|
|
3376
3610
|
// src/hooks/use-workspace-sessions.ts
|
|
3377
|
-
import { useCallback as
|
|
3611
|
+
import { useCallback as useCallback10 } from "react";
|
|
3378
3612
|
function useWorkspaceSessions(options = {}) {
|
|
3379
3613
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3380
3614
|
const limit = options.limit;
|
|
3381
|
-
const load =
|
|
3615
|
+
const load = useCallback10(
|
|
3382
3616
|
async () => await client.listSessions(workspaceId, limit !== void 0 ? { limit } : {}),
|
|
3383
3617
|
[client, workspaceId, limit]
|
|
3384
3618
|
);
|
|
@@ -3387,13 +3621,13 @@ function useWorkspaceSessions(options = {}) {
|
|
|
3387
3621
|
}
|
|
3388
3622
|
|
|
3389
3623
|
// src/hooks/use-environments.ts
|
|
3390
|
-
import { useCallback as
|
|
3624
|
+
import { useCallback as useCallback11 } from "react";
|
|
3391
3625
|
function useEnvironments(options = {}) {
|
|
3392
3626
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3393
|
-
const load =
|
|
3627
|
+
const load = useCallback11(async () => await client.listEnvironments(workspaceId), [client, workspaceId]);
|
|
3394
3628
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });
|
|
3395
3629
|
const mutation = useMutationRunner();
|
|
3396
|
-
const create =
|
|
3630
|
+
const create = useCallback11(
|
|
3397
3631
|
async (request) => {
|
|
3398
3632
|
const result = await mutation.run(() => client.createEnvironment(workspaceId, request));
|
|
3399
3633
|
if (result) {
|
|
@@ -3403,7 +3637,7 @@ function useEnvironments(options = {}) {
|
|
|
3403
3637
|
},
|
|
3404
3638
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3405
3639
|
);
|
|
3406
|
-
const update =
|
|
3640
|
+
const update = useCallback11(
|
|
3407
3641
|
async (environmentId, request) => {
|
|
3408
3642
|
const result = await mutation.run(() => client.updateEnvironment(workspaceId, environmentId, request));
|
|
3409
3643
|
if (result) {
|
|
@@ -3413,7 +3647,7 @@ function useEnvironments(options = {}) {
|
|
|
3413
3647
|
},
|
|
3414
3648
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3415
3649
|
);
|
|
3416
|
-
const remove =
|
|
3650
|
+
const remove = useCallback11(
|
|
3417
3651
|
async (environmentId) => {
|
|
3418
3652
|
const result = await mutation.run(async () => {
|
|
3419
3653
|
await client.deleteEnvironment(workspaceId, environmentId);
|
|
@@ -3426,7 +3660,7 @@ function useEnvironments(options = {}) {
|
|
|
3426
3660
|
},
|
|
3427
3661
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3428
3662
|
);
|
|
3429
|
-
const setVariable =
|
|
3663
|
+
const setVariable = useCallback11(
|
|
3430
3664
|
async (environmentId, name, value) => {
|
|
3431
3665
|
const result = await mutation.run(() => client.setEnvironmentVariable(workspaceId, environmentId, name, value));
|
|
3432
3666
|
if (result) {
|
|
@@ -3436,7 +3670,7 @@ function useEnvironments(options = {}) {
|
|
|
3436
3670
|
},
|
|
3437
3671
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3438
3672
|
);
|
|
3439
|
-
const deleteVariable =
|
|
3673
|
+
const deleteVariable = useCallback11(
|
|
3440
3674
|
async (environmentId, name) => {
|
|
3441
3675
|
const result = await mutation.run(async () => {
|
|
3442
3676
|
await client.deleteEnvironmentVariable(workspaceId, environmentId, name);
|
|
@@ -3466,13 +3700,13 @@ function useEnvironments(options = {}) {
|
|
|
3466
3700
|
}
|
|
3467
3701
|
|
|
3468
3702
|
// src/hooks/use-packs.ts
|
|
3469
|
-
import { useCallback as
|
|
3703
|
+
import { useCallback as useCallback12 } from "react";
|
|
3470
3704
|
function usePacks(options = {}) {
|
|
3471
3705
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3472
|
-
const load =
|
|
3706
|
+
const load = useCallback12(async () => await client.listPacks(workspaceId), [client, workspaceId]);
|
|
3473
3707
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });
|
|
3474
3708
|
const mutation = useMutationRunner();
|
|
3475
|
-
const register =
|
|
3709
|
+
const register = useCallback12(
|
|
3476
3710
|
async (manifest) => {
|
|
3477
3711
|
const result = await mutation.run(() => client.registerPack(workspaceId, manifest));
|
|
3478
3712
|
if (result) {
|
|
@@ -3482,7 +3716,7 @@ function usePacks(options = {}) {
|
|
|
3482
3716
|
},
|
|
3483
3717
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3484
3718
|
);
|
|
3485
|
-
const enable =
|
|
3719
|
+
const enable = useCallback12(
|
|
3486
3720
|
async (packId, request = {}) => {
|
|
3487
3721
|
const result = await mutation.run(() => client.enablePack(workspaceId, packId, request));
|
|
3488
3722
|
if (result) {
|
|
@@ -3492,7 +3726,7 @@ function usePacks(options = {}) {
|
|
|
3492
3726
|
},
|
|
3493
3727
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3494
3728
|
);
|
|
3495
|
-
const remove =
|
|
3729
|
+
const remove = useCallback12(
|
|
3496
3730
|
async (packId) => {
|
|
3497
3731
|
const result = await mutation.run(async () => {
|
|
3498
3732
|
await client.deletePack(workspaceId, packId);
|
|
@@ -3506,7 +3740,7 @@ function usePacks(options = {}) {
|
|
|
3506
3740
|
[client, workspaceId, mutation.run, state.refresh]
|
|
3507
3741
|
);
|
|
3508
3742
|
const installations = state.data?.installations ?? [];
|
|
3509
|
-
const installationFor =
|
|
3743
|
+
const installationFor = useCallback12(
|
|
3510
3744
|
(packId) => installations.find((installation) => installation.packId === packId) ?? null,
|
|
3511
3745
|
[installations]
|
|
3512
3746
|
);
|
|
@@ -3527,13 +3761,13 @@ function usePacks(options = {}) {
|
|
|
3527
3761
|
}
|
|
3528
3762
|
|
|
3529
3763
|
// src/hooks/use-workspaces.ts
|
|
3530
|
-
import { useCallback as
|
|
3764
|
+
import { useCallback as useCallback13 } from "react";
|
|
3531
3765
|
function useWorkspaces(options = {}) {
|
|
3532
3766
|
const client = useOpenGeniClient(options);
|
|
3533
|
-
const load =
|
|
3767
|
+
const load = useCallback13(async () => await client.listWorkspaces(), [client]);
|
|
3534
3768
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });
|
|
3535
3769
|
const mutation = useMutationRunner();
|
|
3536
|
-
const create =
|
|
3770
|
+
const create = useCallback13(
|
|
3537
3771
|
async (request) => {
|
|
3538
3772
|
const result = await mutation.run(() => client.createWorkspace(request));
|
|
3539
3773
|
if (result) {
|
|
@@ -3543,7 +3777,7 @@ function useWorkspaces(options = {}) {
|
|
|
3543
3777
|
},
|
|
3544
3778
|
[client, mutation.run, state.refresh]
|
|
3545
3779
|
);
|
|
3546
|
-
const update =
|
|
3780
|
+
const update = useCallback13(
|
|
3547
3781
|
async (workspaceId, request) => {
|
|
3548
3782
|
const result = await mutation.run(() => client.updateWorkspace(workspaceId, request));
|
|
3549
3783
|
if (result) {
|
|
@@ -3567,12 +3801,12 @@ function useWorkspaces(options = {}) {
|
|
|
3567
3801
|
}
|
|
3568
3802
|
|
|
3569
3803
|
// src/hooks/use-billing-usage.ts
|
|
3570
|
-
import { useCallback as
|
|
3804
|
+
import { useCallback as useCallback14 } from "react";
|
|
3571
3805
|
function useBillingUsage(options = {}) {
|
|
3572
3806
|
const client = useOpenGeniClient(options);
|
|
3573
3807
|
const accountId = options.accountId;
|
|
3574
3808
|
const workspaceId = options.workspaceId;
|
|
3575
|
-
const load =
|
|
3809
|
+
const load = useCallback14(
|
|
3576
3810
|
async () => await client.getBillingUsage({
|
|
3577
3811
|
...accountId !== void 0 ? { accountId } : {},
|
|
3578
3812
|
...workspaceId !== void 0 ? { workspaceId } : {}
|
|
@@ -3590,10 +3824,10 @@ function useBillingUsage(options = {}) {
|
|
|
3590
3824
|
}
|
|
3591
3825
|
|
|
3592
3826
|
// src/hooks/use-available-models.ts
|
|
3593
|
-
import { useCallback as
|
|
3827
|
+
import { useCallback as useCallback15 } from "react";
|
|
3594
3828
|
function useAvailableModels(options = {}) {
|
|
3595
3829
|
const client = useOpenGeniClient(options);
|
|
3596
|
-
const load =
|
|
3830
|
+
const load = useCallback15(async () => await client.getClientConfig(), [client]);
|
|
3597
3831
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });
|
|
3598
3832
|
return {
|
|
3599
3833
|
models: state.data?.models ?? [],
|
|
@@ -3609,7 +3843,7 @@ import {
|
|
|
3609
3843
|
OpenGeniApiError as OpenGeniApiError2,
|
|
3610
3844
|
applyUrlRotation
|
|
3611
3845
|
} from "@opengeni/sdk";
|
|
3612
|
-
import { useCallback as
|
|
3846
|
+
import { useCallback as useCallback16, useEffect as useEffect7, useRef as useRef7, useState as useState13 } from "react";
|
|
3613
3847
|
function desktopAttachable(cell) {
|
|
3614
3848
|
if (cell.transport !== null) return true;
|
|
3615
3849
|
return cell.reason === "lease_cold" || cell.reason === "not_provisioned" || cell.reason === null;
|
|
@@ -3644,9 +3878,9 @@ function useSessionCapabilities(sessionId, options = {}) {
|
|
|
3644
3878
|
const [viewerCapReached, setViewerCapReached] = useState13(false);
|
|
3645
3879
|
const [viewerId, setViewerId] = useState13(null);
|
|
3646
3880
|
const [nonce, setNonce] = useState13(0);
|
|
3647
|
-
const epochRef =
|
|
3648
|
-
const viewerIdRef =
|
|
3649
|
-
const renegotiate =
|
|
3881
|
+
const epochRef = useRef7(0);
|
|
3882
|
+
const viewerIdRef = useRef7(null);
|
|
3883
|
+
const renegotiate = useCallback16(() => {
|
|
3650
3884
|
setNonce((n) => n + 1);
|
|
3651
3885
|
}, []);
|
|
3652
3886
|
useEffect7(() => {
|
|
@@ -3844,7 +4078,7 @@ import {
|
|
|
3844
4078
|
desktopSocketUrl,
|
|
3845
4079
|
nextDesktopState
|
|
3846
4080
|
} from "@opengeni/sdk";
|
|
3847
|
-
import { useEffect as useEffect9, useRef as
|
|
4081
|
+
import { useEffect as useEffect9, useRef as useRef9, useState as useState15 } from "react";
|
|
3848
4082
|
|
|
3849
4083
|
// src/lib/relay-wire.ts
|
|
3850
4084
|
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
|
@@ -3917,7 +4151,7 @@ function decodeStreamFrame(bytes) {
|
|
|
3917
4151
|
}
|
|
3918
4152
|
|
|
3919
4153
|
// src/hooks/use-relay-frame-stream.ts
|
|
3920
|
-
import { useEffect as useEffect8, useRef as
|
|
4154
|
+
import { useEffect as useEffect8, useRef as useRef8, useState as useState14 } from "react";
|
|
3921
4155
|
var TAG_OPEN = 1;
|
|
3922
4156
|
var TAG_OPENACK = 2;
|
|
3923
4157
|
var TAG_FRAME = 3;
|
|
@@ -3935,7 +4169,7 @@ function useRelayFrameStream(options) {
|
|
|
3935
4169
|
const [state, setState] = useState14("idle");
|
|
3936
4170
|
const [error, setError] = useState14(null);
|
|
3937
4171
|
const [nonce, setNonce] = useState14(0);
|
|
3938
|
-
const stateRef =
|
|
4172
|
+
const stateRef = useRef8("idle");
|
|
3939
4173
|
const setBoth = (next) => {
|
|
3940
4174
|
stateRef.current = next;
|
|
3941
4175
|
setState(next);
|
|
@@ -3944,7 +4178,7 @@ function useRelayFrameStream(options) {
|
|
|
3944
4178
|
const transport = capability?.transport ?? null;
|
|
3945
4179
|
const url = capability?.url ?? null;
|
|
3946
4180
|
const token = capability?.token ?? null;
|
|
3947
|
-
const factoryRef =
|
|
4181
|
+
const factoryRef = useRef8(webSocketFactory);
|
|
3948
4182
|
factoryRef.current = webSocketFactory;
|
|
3949
4183
|
useEffect8(() => {
|
|
3950
4184
|
if (typeof window === "undefined") return;
|
|
@@ -4138,7 +4372,7 @@ function useDesktopStream(options) {
|
|
|
4138
4372
|
const [state, setState] = useState15("idle");
|
|
4139
4373
|
const [error, setError] = useState15(null);
|
|
4140
4374
|
const [nonce, setNonce] = useState15(0);
|
|
4141
|
-
const stateRef =
|
|
4375
|
+
const stateRef = useRef9("idle");
|
|
4142
4376
|
const setBoth = (next) => {
|
|
4143
4377
|
stateRef.current = next;
|
|
4144
4378
|
setState(next);
|
|
@@ -4148,11 +4382,11 @@ function useDesktopStream(options) {
|
|
|
4148
4382
|
const token = capability?.token ?? null;
|
|
4149
4383
|
const transport = capability?.transport ?? null;
|
|
4150
4384
|
const mode = capability?.mode ?? "read-only";
|
|
4151
|
-
const rfbRef =
|
|
4152
|
-
const interactiveRef =
|
|
4153
|
-
const scaleViewportRef =
|
|
4154
|
-
const modeRef =
|
|
4155
|
-
const rfbFactoryRef =
|
|
4385
|
+
const rfbRef = useRef9(null);
|
|
4386
|
+
const interactiveRef = useRef9(interactive);
|
|
4387
|
+
const scaleViewportRef = useRef9(scaleViewport);
|
|
4388
|
+
const modeRef = useRef9(mode);
|
|
4389
|
+
const rfbFactoryRef = useRef9(rfbFactory);
|
|
4156
4390
|
interactiveRef.current = interactive;
|
|
4157
4391
|
scaleViewportRef.current = scaleViewport;
|
|
4158
4392
|
modeRef.current = mode;
|
|
@@ -4245,7 +4479,7 @@ import {
|
|
|
4245
4479
|
ttydResizeFrame,
|
|
4246
4480
|
TtydServerCommand
|
|
4247
4481
|
} from "@opengeni/sdk";
|
|
4248
|
-
import { useEffect as useEffect10, useMemo as useMemo3, useRef as
|
|
4482
|
+
import { useEffect as useEffect10, useMemo as useMemo3, useRef as useRef10, useState as useState16 } from "react";
|
|
4249
4483
|
function decodeFrame(data) {
|
|
4250
4484
|
if (typeof data === "string") {
|
|
4251
4485
|
return { command: data.charAt(0), payload: data.slice(1) };
|
|
@@ -4258,13 +4492,13 @@ function decodeFrame(data) {
|
|
|
4258
4492
|
function useTerminalStream(options) {
|
|
4259
4493
|
const { capability, onOutput, onTitle, initialCols, initialRows } = options;
|
|
4260
4494
|
const [status, setStatus] = useState16("closed");
|
|
4261
|
-
const wsRef =
|
|
4262
|
-
const sizeRef =
|
|
4495
|
+
const wsRef = useRef10(null);
|
|
4496
|
+
const sizeRef = useRef10({
|
|
4263
4497
|
cols: initialCols ?? 80,
|
|
4264
4498
|
rows: initialRows ?? 24
|
|
4265
4499
|
});
|
|
4266
|
-
const onOutputRef =
|
|
4267
|
-
const onTitleRef =
|
|
4500
|
+
const onOutputRef = useRef10(onOutput);
|
|
4501
|
+
const onTitleRef = useRef10(onTitle);
|
|
4268
4502
|
onOutputRef.current = onOutput;
|
|
4269
4503
|
onTitleRef.current = onTitle;
|
|
4270
4504
|
const transport = capability?.transport ?? null;
|
|
@@ -4367,7 +4601,7 @@ function useTerminalStream(options) {
|
|
|
4367
4601
|
|
|
4368
4602
|
// src/hooks/use-sandbox-terminal.ts
|
|
4369
4603
|
import { OpenGeniApiError as OpenGeniApiError3 } from "@opengeni/sdk";
|
|
4370
|
-
import { useCallback as
|
|
4604
|
+
import { useCallback as useCallback17, useEffect as useEffect11, useMemo as useMemo4, useRef as useRef11, useState as useState17 } from "react";
|
|
4371
4605
|
function useSandboxTerminal(sessionId, options) {
|
|
4372
4606
|
const { client, workspaceId } = useOpenGeni(options);
|
|
4373
4607
|
const includeAgentFirehose = options.includeAgentFirehose ?? true;
|
|
@@ -4377,7 +4611,7 @@ function useSandboxTerminal(sessionId, options) {
|
|
|
4377
4611
|
const [openedPtyId, setOpenedPtyId] = useState17(null);
|
|
4378
4612
|
const [openError, setOpenError] = useState17(null);
|
|
4379
4613
|
const [reopenNonce, setReopenNonce] = useState17(0);
|
|
4380
|
-
const openInFlight =
|
|
4614
|
+
const openInFlight = useRef11(false);
|
|
4381
4615
|
const boxWarm = liveness === void 0 || liveness === "warm" || liveness === "draining";
|
|
4382
4616
|
useEffect11(() => {
|
|
4383
4617
|
if (!interactive || !sessionId || ptyFilter || !boxWarm) return;
|
|
@@ -4467,7 +4701,7 @@ function useSandboxTerminal(sessionId, options) {
|
|
|
4467
4701
|
});
|
|
4468
4702
|
};
|
|
4469
4703
|
}, [client, workspaceId, sessionId, activePtyId, canWrite, openedPtyId]);
|
|
4470
|
-
const close =
|
|
4704
|
+
const close = useCallback17(() => {
|
|
4471
4705
|
if (!activePtyId || !sessionId) return;
|
|
4472
4706
|
void client.terminalPtyClose(workspaceId, sessionId, { ptyId: activePtyId }).catch(() => {
|
|
4473
4707
|
});
|
|
@@ -4483,7 +4717,7 @@ function useSandboxTerminal(sessionId, options) {
|
|
|
4483
4717
|
}
|
|
4484
4718
|
|
|
4485
4719
|
// src/hooks/use-sandbox-files.ts
|
|
4486
|
-
import { useCallback as
|
|
4720
|
+
import { useCallback as useCallback18, useEffect as useEffect12, useRef as useRef12, useState as useState18 } from "react";
|
|
4487
4721
|
function parentOf(path) {
|
|
4488
4722
|
const i = path.lastIndexOf("/");
|
|
4489
4723
|
return i <= 0 ? "" : path.slice(0, i);
|
|
@@ -4603,15 +4837,15 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4603
4837
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
4604
4838
|
const rootPath = options.rootPath ?? "";
|
|
4605
4839
|
const [tree, setTree] = useState18([]);
|
|
4606
|
-
const treeRef =
|
|
4840
|
+
const treeRef = useRef12([]);
|
|
4607
4841
|
const [loading, setLoading] = useState18(false);
|
|
4608
4842
|
const [expandingPaths, setExpandingPaths] = useState18(/* @__PURE__ */ new Set());
|
|
4609
4843
|
const [error, setError] = useState18(null);
|
|
4610
|
-
const statusRef =
|
|
4611
|
-
const ownRevisionsRef =
|
|
4844
|
+
const statusRef = useRef12(/* @__PURE__ */ new Map());
|
|
4845
|
+
const ownRevisionsRef = useRef12(/* @__PURE__ */ new Set());
|
|
4612
4846
|
const onMutationError = options.onMutationError;
|
|
4613
4847
|
treeRef.current = tree;
|
|
4614
|
-
const applyStatus =
|
|
4848
|
+
const applyStatus = useCallback18((nodes) => {
|
|
4615
4849
|
const overlay = statusRef.current;
|
|
4616
4850
|
if (overlay.size === 0) return nodes;
|
|
4617
4851
|
const walk = (list) => list.map((node) => {
|
|
@@ -4623,7 +4857,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4623
4857
|
});
|
|
4624
4858
|
return walk(nodes);
|
|
4625
4859
|
}, []);
|
|
4626
|
-
const refresh =
|
|
4860
|
+
const refresh = useCallback18(async () => {
|
|
4627
4861
|
if (!sessionId) return;
|
|
4628
4862
|
setLoading(true);
|
|
4629
4863
|
setError(null);
|
|
@@ -4649,7 +4883,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4649
4883
|
setLoading(false);
|
|
4650
4884
|
}
|
|
4651
4885
|
}, [client, workspaceId, sessionId, rootPath, applyStatus]);
|
|
4652
|
-
const expand =
|
|
4886
|
+
const expand = useCallback18(
|
|
4653
4887
|
async (path) => {
|
|
4654
4888
|
if (!sessionId) return;
|
|
4655
4889
|
setExpandingPaths((prev) => {
|
|
@@ -4674,14 +4908,14 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4674
4908
|
},
|
|
4675
4909
|
[client, workspaceId, sessionId, applyStatus]
|
|
4676
4910
|
);
|
|
4677
|
-
const readFile =
|
|
4911
|
+
const readFile = useCallback18(
|
|
4678
4912
|
async (path) => {
|
|
4679
4913
|
if (!sessionId) throw new Error("no session");
|
|
4680
4914
|
return await client.fsRead(workspaceId, sessionId, { path });
|
|
4681
4915
|
},
|
|
4682
4916
|
[client, workspaceId, sessionId]
|
|
4683
4917
|
);
|
|
4684
|
-
const reconcilePath =
|
|
4918
|
+
const reconcilePath = useCallback18(
|
|
4685
4919
|
async (path) => {
|
|
4686
4920
|
if (!sessionId) return;
|
|
4687
4921
|
if (!parentIsLoaded(treeRef.current, path)) return;
|
|
@@ -4700,7 +4934,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4700
4934
|
},
|
|
4701
4935
|
[client, workspaceId, sessionId, applyStatus]
|
|
4702
4936
|
);
|
|
4703
|
-
const runOptimistic =
|
|
4937
|
+
const runOptimistic = useCallback18(
|
|
4704
4938
|
async (opName, apply, op, reconcileParents) => {
|
|
4705
4939
|
const snapshot = treeRef.current;
|
|
4706
4940
|
setTree(applyStatus(apply(snapshot)));
|
|
@@ -4722,7 +4956,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4722
4956
|
},
|
|
4723
4957
|
[applyStatus, reconcilePath, onMutationError]
|
|
4724
4958
|
);
|
|
4725
|
-
const writeFile =
|
|
4959
|
+
const writeFile = useCallback18(
|
|
4726
4960
|
async (path, content) => {
|
|
4727
4961
|
if (!sessionId) throw new Error("no session");
|
|
4728
4962
|
const parent = parentOf(path);
|
|
@@ -4737,7 +4971,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4737
4971
|
},
|
|
4738
4972
|
[client, workspaceId, sessionId, tree, runOptimistic]
|
|
4739
4973
|
);
|
|
4740
|
-
const createFile =
|
|
4974
|
+
const createFile = useCallback18(
|
|
4741
4975
|
async (path) => {
|
|
4742
4976
|
if (!sessionId) throw new Error("no session");
|
|
4743
4977
|
const parent = parentOf(path);
|
|
@@ -4751,7 +4985,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4751
4985
|
},
|
|
4752
4986
|
[client, workspaceId, sessionId, runOptimistic]
|
|
4753
4987
|
);
|
|
4754
|
-
const createDir =
|
|
4988
|
+
const createDir = useCallback18(
|
|
4755
4989
|
async (path) => {
|
|
4756
4990
|
if (!sessionId) throw new Error("no session");
|
|
4757
4991
|
const parent = parentOf(path);
|
|
@@ -4765,7 +4999,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4765
4999
|
},
|
|
4766
5000
|
[client, workspaceId, sessionId, runOptimistic]
|
|
4767
5001
|
);
|
|
4768
|
-
const deleteEntry =
|
|
5002
|
+
const deleteEntry = useCallback18(
|
|
4769
5003
|
async (path, recursive = false) => {
|
|
4770
5004
|
if (!sessionId) throw new Error("no session");
|
|
4771
5005
|
await runOptimistic(
|
|
@@ -4777,7 +5011,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4777
5011
|
},
|
|
4778
5012
|
[client, workspaceId, sessionId, runOptimistic]
|
|
4779
5013
|
);
|
|
4780
|
-
const moveEntry =
|
|
5014
|
+
const moveEntry = useCallback18(
|
|
4781
5015
|
async (path, newPath, opts) => {
|
|
4782
5016
|
if (!sessionId) throw new Error("no session");
|
|
4783
5017
|
const from = parentOf(path);
|
|
@@ -4807,7 +5041,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4807
5041
|
}
|
|
4808
5042
|
void refresh();
|
|
4809
5043
|
}, [enabled, refresh]);
|
|
4810
|
-
const refreshGitOverlay =
|
|
5044
|
+
const refreshGitOverlay = useCallback18(async () => {
|
|
4811
5045
|
if (!sessionId) return;
|
|
4812
5046
|
try {
|
|
4813
5047
|
const status = await client.gitStatus(workspaceId, sessionId, { path: rootPath });
|
|
@@ -4823,10 +5057,10 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4823
5057
|
}
|
|
4824
5058
|
}, [client, workspaceId, sessionId, rootPath, applyStatus]);
|
|
4825
5059
|
const events = options.events;
|
|
4826
|
-
const lastSeqRef =
|
|
4827
|
-
const pendingParentsRef =
|
|
4828
|
-
const pendingGitRef =
|
|
4829
|
-
const debounceRef =
|
|
5060
|
+
const lastSeqRef = useRef12(0);
|
|
5061
|
+
const pendingParentsRef = useRef12(/* @__PURE__ */ new Set());
|
|
5062
|
+
const pendingGitRef = useRef12(false);
|
|
5063
|
+
const debounceRef = useRef12(null);
|
|
4830
5064
|
useEffect12(() => {
|
|
4831
5065
|
if (!enabled || !events) return;
|
|
4832
5066
|
let sawNew = false;
|
|
@@ -4870,7 +5104,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4870
5104
|
},
|
|
4871
5105
|
[]
|
|
4872
5106
|
);
|
|
4873
|
-
const wasLiveRef =
|
|
5107
|
+
const wasLiveRef = useRef12(false);
|
|
4874
5108
|
const liveness = options.liveness;
|
|
4875
5109
|
useEffect12(() => {
|
|
4876
5110
|
const live = liveness === "warm" || liveness === "draining";
|
|
@@ -4898,7 +5132,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4898
5132
|
}
|
|
4899
5133
|
|
|
4900
5134
|
// src/hooks/use-sandbox-git.ts
|
|
4901
|
-
import { useCallback as
|
|
5135
|
+
import { useCallback as useCallback19, useEffect as useEffect13, useRef as useRef13, useState as useState19 } from "react";
|
|
4902
5136
|
function useSandboxGit(sessionId, options = {}) {
|
|
4903
5137
|
const { client, workspaceId } = useOpenGeni(options);
|
|
4904
5138
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
@@ -4911,7 +5145,7 @@ function useSandboxGit(sessionId, options = {}) {
|
|
|
4911
5145
|
const [behind, setBehind] = useState19(0);
|
|
4912
5146
|
const [loading, setLoading] = useState19(false);
|
|
4913
5147
|
const [error, setError] = useState19(null);
|
|
4914
|
-
const refresh =
|
|
5148
|
+
const refresh = useCallback19(async () => {
|
|
4915
5149
|
if (!sessionId) return;
|
|
4916
5150
|
setLoading(true);
|
|
4917
5151
|
setError(null);
|
|
@@ -4943,7 +5177,7 @@ function useSandboxGit(sessionId, options = {}) {
|
|
|
4943
5177
|
void refresh();
|
|
4944
5178
|
}, [enabled, refresh]);
|
|
4945
5179
|
const events = options.events;
|
|
4946
|
-
const lastChangeRef =
|
|
5180
|
+
const lastChangeRef = useRef13(0);
|
|
4947
5181
|
useEffect13(() => {
|
|
4948
5182
|
if (!enabled || !events) return;
|
|
4949
5183
|
let latest = lastChangeRef.current;
|
|
@@ -5192,14 +5426,14 @@ function clearErrorMessage(cause) {
|
|
|
5192
5426
|
}
|
|
5193
5427
|
|
|
5194
5428
|
// src/hooks/use-slash-commands.ts
|
|
5195
|
-
import { useCallback as
|
|
5429
|
+
import { useCallback as useCallback20, useMemo as useMemo5, useRef as useRef14, useState as useState20 } from "react";
|
|
5196
5430
|
function useSlashCommands(options) {
|
|
5197
5431
|
const { commands, context, handlers, value, setValue } = options;
|
|
5198
5432
|
const [highlight, setHighlight] = useState20(0);
|
|
5199
5433
|
const [dismissedValue, setDismissedValue] = useState20(null);
|
|
5200
5434
|
const dismissed = dismissedValue !== null && dismissedValue === value;
|
|
5201
|
-
const navigatedRef =
|
|
5202
|
-
const navTokenRef =
|
|
5435
|
+
const navigatedRef = useRef14(false);
|
|
5436
|
+
const navTokenRef = useRef14(value);
|
|
5203
5437
|
if (navTokenRef.current !== value) {
|
|
5204
5438
|
navTokenRef.current = value;
|
|
5205
5439
|
navigatedRef.current = false;
|
|
@@ -5232,7 +5466,7 @@ function useSlashCommands(options) {
|
|
|
5232
5466
|
const isCommandDraft = parsed !== null && items.length > 0;
|
|
5233
5467
|
const clampedHighlight = items.length === 0 ? 0 : Math.min(highlight, items.length - 1);
|
|
5234
5468
|
const activeArgHint = activeCommand ? argHint(activeCommand.args) : "";
|
|
5235
|
-
const buildContext =
|
|
5469
|
+
const buildContext = useCallback20(
|
|
5236
5470
|
(command) => {
|
|
5237
5471
|
if (!context) {
|
|
5238
5472
|
return null;
|
|
@@ -5241,7 +5475,7 @@ function useSlashCommands(options) {
|
|
|
5241
5475
|
},
|
|
5242
5476
|
[context, handlers]
|
|
5243
5477
|
);
|
|
5244
|
-
const execute =
|
|
5478
|
+
const execute = useCallback20(
|
|
5245
5479
|
async (command, args) => {
|
|
5246
5480
|
const ctx = buildContext(command);
|
|
5247
5481
|
if (!ctx) {
|
|
@@ -5261,20 +5495,20 @@ function useSlashCommands(options) {
|
|
|
5261
5495
|
},
|
|
5262
5496
|
[buildContext, setValue]
|
|
5263
5497
|
);
|
|
5264
|
-
const autocomplete =
|
|
5498
|
+
const autocomplete = useCallback20(
|
|
5265
5499
|
(command) => {
|
|
5266
5500
|
setValue(`/${command.name} `);
|
|
5267
5501
|
setHighlight(0);
|
|
5268
5502
|
},
|
|
5269
5503
|
[setValue]
|
|
5270
5504
|
);
|
|
5271
|
-
const autocompleteHighlighted =
|
|
5505
|
+
const autocompleteHighlighted = useCallback20(() => {
|
|
5272
5506
|
const command = items[clampedHighlight];
|
|
5273
5507
|
if (command) {
|
|
5274
5508
|
autocomplete(command);
|
|
5275
5509
|
}
|
|
5276
5510
|
}, [items, clampedHighlight, autocomplete]);
|
|
5277
|
-
const runResolved =
|
|
5511
|
+
const runResolved = useCallback20(
|
|
5278
5512
|
async (command, options2) => {
|
|
5279
5513
|
if (!parsed) {
|
|
5280
5514
|
return;
|
|
@@ -5297,7 +5531,7 @@ function useSlashCommands(options) {
|
|
|
5297
5531
|
},
|
|
5298
5532
|
[parsed, activeCommand, autocomplete, execute]
|
|
5299
5533
|
);
|
|
5300
|
-
const runHighlighted =
|
|
5534
|
+
const runHighlighted = useCallback20(async () => {
|
|
5301
5535
|
if (!parsed) {
|
|
5302
5536
|
return;
|
|
5303
5537
|
}
|
|
@@ -5316,7 +5550,7 @@ function useSlashCommands(options) {
|
|
|
5316
5550
|
}
|
|
5317
5551
|
await runResolved(command);
|
|
5318
5552
|
}, [parsed, activeCommand, items, clampedHighlight, runResolved]);
|
|
5319
|
-
const runAt =
|
|
5553
|
+
const runAt = useCallback20(
|
|
5320
5554
|
async (index) => {
|
|
5321
5555
|
const command = items[index];
|
|
5322
5556
|
if (!command) {
|
|
@@ -5326,8 +5560,8 @@ function useSlashCommands(options) {
|
|
|
5326
5560
|
},
|
|
5327
5561
|
[items, runResolved]
|
|
5328
5562
|
);
|
|
5329
|
-
const runningRef =
|
|
5330
|
-
const onKeyDown =
|
|
5563
|
+
const runningRef = useRef14(false);
|
|
5564
|
+
const onKeyDown = useCallback20(
|
|
5331
5565
|
(event) => {
|
|
5332
5566
|
if (!open) {
|
|
5333
5567
|
return false;
|
|
@@ -5469,7 +5703,7 @@ function CommandPalette({ open, items, highlight, onHighlight, onRun, argHintTex
|
|
|
5469
5703
|
// src/components/chat-composer.tsx
|
|
5470
5704
|
import { ArrowUpIcon, FileIcon, ImageIcon as ImageIcon2, LoaderCircleIcon, PaperclipIcon, RotateCwIcon, SquareIcon, XIcon as XIcon2 } from "lucide-react";
|
|
5471
5705
|
import { AnimatePresence as AnimatePresence3, motion as motion3 } from "motion/react";
|
|
5472
|
-
import { useCallback as
|
|
5706
|
+
import { useCallback as useCallback21, useEffect as useEffect14, useId as useId2, useMemo as useMemo7, useRef as useRef15, useState as useState21 } from "react";
|
|
5473
5707
|
|
|
5474
5708
|
// src/components/model-picker.tsx
|
|
5475
5709
|
import { ChevronDownIcon } from "lucide-react";
|
|
@@ -5546,15 +5780,15 @@ function ChatComposer({
|
|
|
5546
5780
|
commandContext,
|
|
5547
5781
|
onClearView
|
|
5548
5782
|
}) {
|
|
5549
|
-
const textareaRef =
|
|
5550
|
-
const fileInputRef =
|
|
5783
|
+
const textareaRef = useRef15(null);
|
|
5784
|
+
const fileInputRef = useRef15(null);
|
|
5551
5785
|
const active = status != null && ACTIVE_STATUSES.has(status);
|
|
5552
5786
|
const blockedByUpload = attachments?.uploading === true;
|
|
5553
5787
|
const hasReadyAttachment = (attachments?.readyResources.length ?? 0) > 0;
|
|
5554
5788
|
const canSend = (composer.canSend || hasReadyAttachment) && !blockedByUpload && !composer.sending;
|
|
5555
5789
|
const [dragging, setDragging] = useState21(false);
|
|
5556
5790
|
const dragCarriesFiles = (event) => event.dataTransfer != null && [...event.dataTransfer.types].includes("Files");
|
|
5557
|
-
const handleDragOver =
|
|
5791
|
+
const handleDragOver = useCallback21(
|
|
5558
5792
|
(event) => {
|
|
5559
5793
|
if (!attachments || !dragCarriesFiles(event)) {
|
|
5560
5794
|
return;
|
|
@@ -5564,7 +5798,7 @@ function ChatComposer({
|
|
|
5564
5798
|
},
|
|
5565
5799
|
[attachments]
|
|
5566
5800
|
);
|
|
5567
|
-
const handleDragLeave =
|
|
5801
|
+
const handleDragLeave = useCallback21(
|
|
5568
5802
|
(event) => {
|
|
5569
5803
|
if (!attachments) {
|
|
5570
5804
|
return;
|
|
@@ -5576,7 +5810,7 @@ function ChatComposer({
|
|
|
5576
5810
|
},
|
|
5577
5811
|
[attachments]
|
|
5578
5812
|
);
|
|
5579
|
-
const handleDrop =
|
|
5813
|
+
const handleDrop = useCallback21(
|
|
5580
5814
|
(event) => {
|
|
5581
5815
|
if (!attachments || !dragCarriesFiles(event)) {
|
|
5582
5816
|
return;
|
|
@@ -5593,7 +5827,7 @@ function ChatComposer({
|
|
|
5593
5827
|
const [helpOpen, setHelpOpen] = useState21(false);
|
|
5594
5828
|
const [confirmState, setConfirmState] = useState21(null);
|
|
5595
5829
|
const listboxId = useId2();
|
|
5596
|
-
const resize =
|
|
5830
|
+
const resize = useCallback21(() => {
|
|
5597
5831
|
const textarea = textareaRef.current;
|
|
5598
5832
|
if (!textarea) {
|
|
5599
5833
|
return;
|
|
@@ -5662,14 +5896,14 @@ function ChatComposer({
|
|
|
5662
5896
|
void composer.send();
|
|
5663
5897
|
}
|
|
5664
5898
|
};
|
|
5665
|
-
const handlePaste =
|
|
5899
|
+
const handlePaste = useCallback21(
|
|
5666
5900
|
(event) => {
|
|
5667
5901
|
onPaste?.(event);
|
|
5668
5902
|
attachments?.addFromPaste(event);
|
|
5669
5903
|
},
|
|
5670
5904
|
[onPaste, attachments]
|
|
5671
5905
|
);
|
|
5672
|
-
const handleFileChange =
|
|
5906
|
+
const handleFileChange = useCallback21(
|
|
5673
5907
|
(event) => {
|
|
5674
5908
|
if (event.target.files) {
|
|
5675
5909
|
attachments?.addFiles(event.target.files);
|
|
@@ -5915,7 +6149,7 @@ function ConfirmBar({
|
|
|
5915
6149
|
onConfirm,
|
|
5916
6150
|
returnFocusRef
|
|
5917
6151
|
}) {
|
|
5918
|
-
const confirmRef =
|
|
6152
|
+
const confirmRef = useRef15(null);
|
|
5919
6153
|
const descriptionId = useId2();
|
|
5920
6154
|
useEffect14(() => {
|
|
5921
6155
|
const returnTo = returnFocusRef?.current ?? null;
|
|
@@ -6071,7 +6305,7 @@ import {
|
|
|
6071
6305
|
TriangleAlertIcon as TriangleAlertIcon2
|
|
6072
6306
|
} from "lucide-react";
|
|
6073
6307
|
import { AnimatePresence as AnimatePresence4, motion as motion4 } from "motion/react";
|
|
6074
|
-
import { useCallback as
|
|
6308
|
+
import { useCallback as useCallback22, useEffect as useEffect15, useLayoutEffect, useMemo as useMemo8, useRef as useRef16, useState as useState22 } from "react";
|
|
6075
6309
|
|
|
6076
6310
|
// src/components/markdown.tsx
|
|
6077
6311
|
import { memo } from "react";
|
|
@@ -6230,19 +6464,38 @@ function MessageTimeline({
|
|
|
6230
6464
|
onOpenSession,
|
|
6231
6465
|
toolRegistry = defaultToolRegistry,
|
|
6232
6466
|
autoFollow = true,
|
|
6467
|
+
hasOlder = false,
|
|
6468
|
+
loadingOlder = false,
|
|
6469
|
+
onLoadOlder,
|
|
6233
6470
|
emptyState,
|
|
6234
6471
|
className
|
|
6235
6472
|
}) {
|
|
6236
6473
|
const resolvedItems = useMemo8(() => items ?? buildTimeline(events ?? []), [items, events]);
|
|
6237
6474
|
const groups = useMemo8(() => groupTimeline(resolvedItems), [resolvedItems]);
|
|
6238
|
-
const
|
|
6475
|
+
const firstGroupKey = groups[0] ? timelineGroupKey(groups[0]) : null;
|
|
6476
|
+
const scrollRef = useRef16(null);
|
|
6477
|
+
const topSentinelRef = useRef16(null);
|
|
6478
|
+
const previousBulkFirstKeyRef = useRef16(void 0);
|
|
6239
6479
|
const [pinned, setPinned] = useState22(true);
|
|
6240
|
-
const
|
|
6241
|
-
const
|
|
6480
|
+
const [bulkActive, setBulkActive] = useState22(true);
|
|
6481
|
+
const [revealed, setRevealed] = useState22(false);
|
|
6482
|
+
const programmaticScrollRef = useRef16(false);
|
|
6483
|
+
const assignScrollTop = useCallback22((node, value) => {
|
|
6484
|
+
const previous = node.scrollTop;
|
|
6485
|
+
programmaticScrollRef.current = true;
|
|
6486
|
+
node.scrollTop = value;
|
|
6487
|
+
if (node.scrollTop === previous) {
|
|
6488
|
+
programmaticScrollRef.current = false;
|
|
6489
|
+
}
|
|
6490
|
+
}, []);
|
|
6491
|
+
const pinnedRef = useRef16(true);
|
|
6492
|
+
const anchorRef = useRef16(null);
|
|
6242
6493
|
const lastItem = resolvedItems[resolvedItems.length - 1];
|
|
6243
6494
|
const streaming = lastItem !== void 0 && (lastItem.kind === "agent-message" || lastItem.kind === "reasoning") && lastItem.streaming;
|
|
6244
6495
|
const working = status === "running" && !streaming;
|
|
6245
|
-
const
|
|
6496
|
+
const firstKeyChangedForBulk = previousBulkFirstKeyRef.current !== void 0 && previousBulkFirstKeyRef.current !== firstGroupKey;
|
|
6497
|
+
const bulkRender = groups.length > 0 && (bulkActive || firstKeyChangedForBulk);
|
|
6498
|
+
const captureAnchor = useCallback22(() => {
|
|
6246
6499
|
const node = scrollRef.current;
|
|
6247
6500
|
const inner = node?.firstElementChild;
|
|
6248
6501
|
if (!node || !inner) {
|
|
@@ -6251,6 +6504,9 @@ function MessageTimeline({
|
|
|
6251
6504
|
}
|
|
6252
6505
|
const containerTop = node.getBoundingClientRect().top;
|
|
6253
6506
|
for (const child of Array.from(inner.children)) {
|
|
6507
|
+
if (child instanceof HTMLElement && child.dataset.ogTimelineChrome !== void 0) {
|
|
6508
|
+
continue;
|
|
6509
|
+
}
|
|
6254
6510
|
const rect = child.getBoundingClientRect();
|
|
6255
6511
|
if (rect.bottom > containerTop + 1) {
|
|
6256
6512
|
anchorRef.current = { el: child, top: rect.top - containerTop };
|
|
@@ -6259,12 +6515,43 @@ function MessageTimeline({
|
|
|
6259
6515
|
}
|
|
6260
6516
|
anchorRef.current = null;
|
|
6261
6517
|
}, []);
|
|
6262
|
-
|
|
6518
|
+
useLayoutEffect(() => {
|
|
6263
6519
|
const node = scrollRef.current;
|
|
6264
6520
|
if (node && autoFollow && pinned) {
|
|
6265
|
-
node
|
|
6521
|
+
assignScrollTop(node, node.scrollHeight);
|
|
6522
|
+
}
|
|
6523
|
+
if (!revealed && groups.length > 0) {
|
|
6524
|
+
setRevealed(true);
|
|
6266
6525
|
}
|
|
6267
|
-
}, [resolvedItems, working, autoFollow, pinned]);
|
|
6526
|
+
}, [resolvedItems, working, autoFollow, pinned, revealed, groups.length, assignScrollTop]);
|
|
6527
|
+
useLayoutEffect(() => {
|
|
6528
|
+
if (groups.length === 0 && revealed) {
|
|
6529
|
+
setRevealed(false);
|
|
6530
|
+
}
|
|
6531
|
+
}, [groups.length, revealed]);
|
|
6532
|
+
useLayoutEffect(() => {
|
|
6533
|
+
previousBulkFirstKeyRef.current = firstGroupKey;
|
|
6534
|
+
if (!bulkRender) {
|
|
6535
|
+
return;
|
|
6536
|
+
}
|
|
6537
|
+
setBulkActive(true);
|
|
6538
|
+
const frame = requestFrame(() => setBulkActive(false));
|
|
6539
|
+
return () => cancelFrame(frame);
|
|
6540
|
+
}, [bulkRender, firstGroupKey]);
|
|
6541
|
+
useEffect15(() => {
|
|
6542
|
+
const root = scrollRef.current;
|
|
6543
|
+
const target = topSentinelRef.current;
|
|
6544
|
+
if (!root || !target || !hasOlder || loadingOlder || !onLoadOlder || typeof IntersectionObserver === "undefined") {
|
|
6545
|
+
return;
|
|
6546
|
+
}
|
|
6547
|
+
const observer = new IntersectionObserver((entries) => {
|
|
6548
|
+
if (entries.some((entry) => entry.isIntersecting)) {
|
|
6549
|
+
onLoadOlder();
|
|
6550
|
+
}
|
|
6551
|
+
}, { root, rootMargin: "1600px 0px 0px 0px" });
|
|
6552
|
+
observer.observe(target);
|
|
6553
|
+
return () => observer.disconnect();
|
|
6554
|
+
}, [hasOlder, loadingOlder, onLoadOlder, firstGroupKey]);
|
|
6268
6555
|
useEffect15(() => {
|
|
6269
6556
|
const node = scrollRef.current;
|
|
6270
6557
|
const inner = node?.firstElementChild;
|
|
@@ -6277,7 +6564,7 @@ function MessageTimeline({
|
|
|
6277
6564
|
return;
|
|
6278
6565
|
}
|
|
6279
6566
|
if (autoFollow && pinnedRef.current) {
|
|
6280
|
-
current
|
|
6567
|
+
assignScrollTop(current, current.scrollHeight);
|
|
6281
6568
|
} else {
|
|
6282
6569
|
const anchor = anchorRef.current;
|
|
6283
6570
|
if (anchor && anchor.el.isConnected) {
|
|
@@ -6285,7 +6572,7 @@ function MessageTimeline({
|
|
|
6285
6572
|
const now = anchor.el.getBoundingClientRect().top - containerTop;
|
|
6286
6573
|
const diff = now - anchor.top;
|
|
6287
6574
|
if (diff !== 0) {
|
|
6288
|
-
current.scrollTop
|
|
6575
|
+
assignScrollTop(current, current.scrollTop + diff);
|
|
6289
6576
|
}
|
|
6290
6577
|
}
|
|
6291
6578
|
}
|
|
@@ -6293,32 +6580,47 @@ function MessageTimeline({
|
|
|
6293
6580
|
});
|
|
6294
6581
|
observer.observe(inner);
|
|
6295
6582
|
return () => observer.disconnect();
|
|
6296
|
-
}, [autoFollow, captureAnchor]);
|
|
6583
|
+
}, [autoFollow, captureAnchor, assignScrollTop]);
|
|
6297
6584
|
const onScroll = () => {
|
|
6298
6585
|
const node = scrollRef.current;
|
|
6299
6586
|
if (!node) {
|
|
6300
6587
|
return;
|
|
6301
6588
|
}
|
|
6589
|
+
const programmatic = programmaticScrollRef.current;
|
|
6590
|
+
programmaticScrollRef.current = false;
|
|
6302
6591
|
const nextPinned = node.scrollHeight - node.scrollTop - node.clientHeight < 48;
|
|
6303
|
-
|
|
6304
|
-
|
|
6592
|
+
if (nextPinned || !programmatic) {
|
|
6593
|
+
pinnedRef.current = nextPinned;
|
|
6594
|
+
setPinned(nextPinned);
|
|
6595
|
+
}
|
|
6305
6596
|
captureAnchor();
|
|
6306
6597
|
};
|
|
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
|
-
|
|
6598
|
+
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: [
|
|
6599
|
+
/* @__PURE__ */ jsx15(
|
|
6600
|
+
"div",
|
|
6601
|
+
{
|
|
6602
|
+
ref: scrollRef,
|
|
6603
|
+
onScroll,
|
|
6604
|
+
style: groups.length > 0 && !revealed ? { visibility: "hidden" } : void 0,
|
|
6605
|
+
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 [overflow-anchor:none] sm:px-6",
|
|
6606
|
+
children: /* @__PURE__ */ jsxs12("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: [
|
|
6607
|
+
groups.length === 0 && !working ? emptyState ?? /* @__PURE__ */ jsx15("p", { className: "py-10 text-center text-sm text-og-fg-subtle", children: "No activity yet." }) : null,
|
|
6608
|
+
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,
|
|
6609
|
+
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,
|
|
6610
|
+
groups.map((group) => /* @__PURE__ */ jsx15(
|
|
6611
|
+
TimelineGroupView,
|
|
6612
|
+
{
|
|
6613
|
+
group,
|
|
6614
|
+
renderMessageText,
|
|
6615
|
+
onOpenSession,
|
|
6616
|
+
toolRegistry
|
|
6617
|
+
},
|
|
6618
|
+
timelineGroupKey(group)
|
|
6619
|
+
)),
|
|
6620
|
+
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
|
|
6621
|
+
] })
|
|
6622
|
+
}
|
|
6623
|
+
),
|
|
6322
6624
|
/* @__PURE__ */ jsx15(AnimatePresence4, { children: !pinned && autoFollow ? /* @__PURE__ */ jsxs12(
|
|
6323
6625
|
motion4.button,
|
|
6324
6626
|
{
|
|
@@ -6347,7 +6649,20 @@ function MessageTimeline({
|
|
|
6347
6649
|
]
|
|
6348
6650
|
}
|
|
6349
6651
|
) : null })
|
|
6350
|
-
] }) });
|
|
6652
|
+
] }) }) });
|
|
6653
|
+
}
|
|
6654
|
+
function requestFrame(callback) {
|
|
6655
|
+
if (typeof requestAnimationFrame === "function") {
|
|
6656
|
+
return requestAnimationFrame(callback);
|
|
6657
|
+
}
|
|
6658
|
+
return window.setTimeout(() => callback(performance.now()), 16);
|
|
6659
|
+
}
|
|
6660
|
+
function cancelFrame(id) {
|
|
6661
|
+
if (typeof cancelAnimationFrame === "function") {
|
|
6662
|
+
cancelAnimationFrame(id);
|
|
6663
|
+
return;
|
|
6664
|
+
}
|
|
6665
|
+
window.clearTimeout(id);
|
|
6351
6666
|
}
|
|
6352
6667
|
function TimelineGroupView({
|
|
6353
6668
|
group,
|
|
@@ -6448,7 +6763,8 @@ function UserMessageRow({
|
|
|
6448
6763
|
item,
|
|
6449
6764
|
renderMessageText
|
|
6450
6765
|
}) {
|
|
6451
|
-
|
|
6766
|
+
const enter = useEntranceAnimation();
|
|
6767
|
+
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
6768
|
item.pending ? /* @__PURE__ */ jsx15("span", { className: "px-1 text-og-xs text-og-fg-subtle", children: "queued" }) : null,
|
|
6453
6769
|
/* @__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
6770
|
] }) });
|
|
@@ -6457,8 +6773,9 @@ function AgentMessageRow({
|
|
|
6457
6773
|
item,
|
|
6458
6774
|
renderMessageText
|
|
6459
6775
|
}) {
|
|
6776
|
+
const enter = useEntranceAnimation();
|
|
6460
6777
|
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: [
|
|
6778
|
+
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
6779
|
renderMessageText(item.text, item),
|
|
6463
6780
|
caret
|
|
6464
6781
|
] }) : (
|
|
@@ -6472,8 +6789,9 @@ function AgentMessageRow({
|
|
|
6472
6789
|
) });
|
|
6473
6790
|
}
|
|
6474
6791
|
function SessionStatusRow({ item }) {
|
|
6792
|
+
const enter = useEntranceAnimation();
|
|
6475
6793
|
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: [
|
|
6794
|
+
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
6795
|
/* @__PURE__ */ jsx15("span", { className: "h-px flex-1 bg-og-border" }),
|
|
6478
6796
|
/* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
6479
6797
|
/* @__PURE__ */ jsx15(StatusDot, { status: item.status, className: "size-1" }),
|
|
@@ -6494,8 +6812,9 @@ var GOAL_META = {
|
|
|
6494
6812
|
continuation: { label: "Continuing toward the goal", pill: NEUTRAL_PILL, icon: ArrowRightIcon }
|
|
6495
6813
|
};
|
|
6496
6814
|
function GoalRow({ item }) {
|
|
6815
|
+
const enter = useEntranceAnimation();
|
|
6497
6816
|
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: [
|
|
6817
|
+
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
6818
|
/* @__PURE__ */ jsx15(Icon, { className: "size-3.5 shrink-0" }),
|
|
6500
6819
|
/* @__PURE__ */ jsxs12("span", { className: "truncate", children: [
|
|
6501
6820
|
label,
|
|
@@ -6504,8 +6823,9 @@ function GoalRow({ item }) {
|
|
|
6504
6823
|
] }) });
|
|
6505
6824
|
}
|
|
6506
6825
|
function NoticeRow({ item }) {
|
|
6826
|
+
const enter = useEntranceAnimation();
|
|
6507
6827
|
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: [
|
|
6828
|
+
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
6829
|
/* @__PURE__ */ jsx15(TriangleAlertIcon2, { className: cn("mt-0.5 size-4 shrink-0", item.tone === "cancelled" && "opacity-60") }),
|
|
6510
6830
|
/* @__PURE__ */ jsx15("span", { className: "min-w-0 whitespace-pre-wrap break-words", children: item.text })
|
|
6511
6831
|
] });
|
|
@@ -6571,7 +6891,7 @@ function FleetTile({ session, title, subtitle, onOpen, className }) {
|
|
|
6571
6891
|
}
|
|
6572
6892
|
|
|
6573
6893
|
// src/components/sandbox-terminal.tsx
|
|
6574
|
-
import { useEffect as useEffect16, useRef as
|
|
6894
|
+
import { useEffect as useEffect16, useRef as useRef17, useState as useState23 } from "react";
|
|
6575
6895
|
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
6576
6896
|
function SandboxTerminal({
|
|
6577
6897
|
result,
|
|
@@ -6586,13 +6906,13 @@ function SandboxTerminal({
|
|
|
6586
6906
|
onActivate,
|
|
6587
6907
|
className
|
|
6588
6908
|
}) {
|
|
6589
|
-
const containerRef =
|
|
6590
|
-
const termRef =
|
|
6591
|
-
const fitRef =
|
|
6592
|
-
const writtenRef =
|
|
6909
|
+
const containerRef = useRef17(null);
|
|
6910
|
+
const termRef = useRef17(null);
|
|
6911
|
+
const fitRef = useRef17(null);
|
|
6912
|
+
const writtenRef = useRef17(/* @__PURE__ */ new Set());
|
|
6593
6913
|
const [ready, setReady] = useState23(false);
|
|
6594
6914
|
const ptyWs = terminalCapability?.transport === "pty-ws" && Boolean(terminalCapability?.url);
|
|
6595
|
-
const ptyOutputQueueRef =
|
|
6915
|
+
const ptyOutputQueueRef = useRef17([]);
|
|
6596
6916
|
const ptyStream = useTerminalStream({
|
|
6597
6917
|
capability: ptyWs ? {
|
|
6598
6918
|
transport: terminalCapability.transport,
|
|
@@ -6687,7 +7007,7 @@ function SandboxTerminal({
|
|
|
6687
7007
|
if (!ready || !term || !theme) return;
|
|
6688
7008
|
term.options.theme = theme;
|
|
6689
7009
|
}, [ready, theme]);
|
|
6690
|
-
const enteredPtyRef =
|
|
7010
|
+
const enteredPtyRef = useRef17(false);
|
|
6691
7011
|
useEffect16(() => {
|
|
6692
7012
|
const term = termRef.current;
|
|
6693
7013
|
if (!ready || !term) return;
|
|
@@ -6847,10 +7167,10 @@ import {
|
|
|
6847
7167
|
Trash2Icon
|
|
6848
7168
|
} from "lucide-react";
|
|
6849
7169
|
import {
|
|
6850
|
-
useCallback as
|
|
7170
|
+
useCallback as useCallback23,
|
|
6851
7171
|
useEffect as useEffect17,
|
|
6852
7172
|
useMemo as useMemo9,
|
|
6853
|
-
useRef as
|
|
7173
|
+
useRef as useRef18,
|
|
6854
7174
|
useState as useState24
|
|
6855
7175
|
} from "react";
|
|
6856
7176
|
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
@@ -6897,9 +7217,9 @@ function FileBrowser({
|
|
|
6897
7217
|
const [dragOver, setDragOver] = useState24(null);
|
|
6898
7218
|
const [menu, setMenu] = useState24(null);
|
|
6899
7219
|
const [busy, setBusy] = useState24(false);
|
|
6900
|
-
const containerRef =
|
|
7220
|
+
const containerRef = useRef18(null);
|
|
6901
7221
|
const cursor = active ?? selectedPath ?? null;
|
|
6902
|
-
const expand =
|
|
7222
|
+
const expand = useCallback23(
|
|
6903
7223
|
async (path) => {
|
|
6904
7224
|
const node = findNode(result.tree, path);
|
|
6905
7225
|
if (node && node.kind === "dir" && node.children === void 0) {
|
|
@@ -6917,14 +7237,14 @@ function FileBrowser({
|
|
|
6917
7237
|
},
|
|
6918
7238
|
[result]
|
|
6919
7239
|
);
|
|
6920
|
-
const open =
|
|
7240
|
+
const open = useCallback23(
|
|
6921
7241
|
(path) => {
|
|
6922
7242
|
setExpanded((prev) => new Set(prev).add(path));
|
|
6923
7243
|
void expand(path);
|
|
6924
7244
|
},
|
|
6925
7245
|
[expand]
|
|
6926
7246
|
);
|
|
6927
|
-
const toggle =
|
|
7247
|
+
const toggle = useCallback23(
|
|
6928
7248
|
async (node) => {
|
|
6929
7249
|
if (node.kind !== "dir") return;
|
|
6930
7250
|
const isOpen = expanded.has(node.path);
|
|
@@ -6952,7 +7272,7 @@ function FileBrowser({
|
|
|
6952
7272
|
return rows;
|
|
6953
7273
|
}, [result.tree, expanded]);
|
|
6954
7274
|
const supportsMutation = editable;
|
|
6955
|
-
const runDelete =
|
|
7275
|
+
const runDelete = useCallback23(
|
|
6956
7276
|
async (node) => {
|
|
6957
7277
|
if (!supportsMutation) return;
|
|
6958
7278
|
const recursive = node.kind === "dir";
|
|
@@ -6971,7 +7291,7 @@ function FileBrowser({
|
|
|
6971
7291
|
},
|
|
6972
7292
|
[supportsMutation, confirmDelete, result]
|
|
6973
7293
|
);
|
|
6974
|
-
const commitCreate =
|
|
7294
|
+
const commitCreate = useCallback23(
|
|
6975
7295
|
async (name) => {
|
|
6976
7296
|
const draft = draftCreate;
|
|
6977
7297
|
setDraftCreate(null);
|
|
@@ -6996,7 +7316,7 @@ function FileBrowser({
|
|
|
6996
7316
|
},
|
|
6997
7317
|
[draftCreate, supportsMutation, result, open, onSelectFile]
|
|
6998
7318
|
);
|
|
6999
|
-
const commitRename =
|
|
7319
|
+
const commitRename = useCallback23(
|
|
7000
7320
|
async (name) => {
|
|
7001
7321
|
const draft = draftRename;
|
|
7002
7322
|
setDraftRename(null);
|
|
@@ -7019,7 +7339,7 @@ function FileBrowser({
|
|
|
7019
7339
|
},
|
|
7020
7340
|
[draftRename, supportsMutation, result, selectedPath, active, onSelectFile]
|
|
7021
7341
|
);
|
|
7022
|
-
const startCreate =
|
|
7342
|
+
const startCreate = useCallback23(
|
|
7023
7343
|
(kind) => {
|
|
7024
7344
|
if (!supportsMutation) return;
|
|
7025
7345
|
const anchor = cursor ? findNode(result.tree, cursor) : void 0;
|
|
@@ -7031,7 +7351,7 @@ function FileBrowser({
|
|
|
7031
7351
|
},
|
|
7032
7352
|
[supportsMutation, cursor, result.tree, open]
|
|
7033
7353
|
);
|
|
7034
|
-
const startRename =
|
|
7354
|
+
const startRename = useCallback23(
|
|
7035
7355
|
(node) => {
|
|
7036
7356
|
if (!supportsMutation) return;
|
|
7037
7357
|
setDraftCreate(null);
|
|
@@ -7040,7 +7360,7 @@ function FileBrowser({
|
|
|
7040
7360
|
},
|
|
7041
7361
|
[supportsMutation]
|
|
7042
7362
|
);
|
|
7043
|
-
const onDropOnto =
|
|
7363
|
+
const onDropOnto = useCallback23(
|
|
7044
7364
|
async (targetDir, sourcePath) => {
|
|
7045
7365
|
setDragOver(null);
|
|
7046
7366
|
if (!supportsMutation || !sourcePath) return;
|
|
@@ -7064,7 +7384,7 @@ function FileBrowser({
|
|
|
7064
7384
|
},
|
|
7065
7385
|
[supportsMutation, result, selectedPath, active, onSelectFile]
|
|
7066
7386
|
);
|
|
7067
|
-
const onKeyDown =
|
|
7387
|
+
const onKeyDown = useCallback23(
|
|
7068
7388
|
(e) => {
|
|
7069
7389
|
if (draftCreate || draftRename) return;
|
|
7070
7390
|
if (flatRows.length === 0) return;
|
|
@@ -7413,8 +7733,8 @@ function InlineInput({
|
|
|
7413
7733
|
onCancel
|
|
7414
7734
|
}) {
|
|
7415
7735
|
const [value, setValue] = useState24(initialValue);
|
|
7416
|
-
const ref =
|
|
7417
|
-
const doneRef =
|
|
7736
|
+
const ref = useRef18(null);
|
|
7737
|
+
const doneRef = useRef18(false);
|
|
7418
7738
|
useEffect17(() => {
|
|
7419
7739
|
const el = ref.current;
|
|
7420
7740
|
if (!el) return;
|
|
@@ -7597,10 +7917,10 @@ import { Loader2Icon as Loader2Icon2, SaveIcon } from "lucide-react";
|
|
|
7597
7917
|
import {
|
|
7598
7918
|
lazy as lazy3,
|
|
7599
7919
|
Suspense as Suspense3,
|
|
7600
|
-
useCallback as
|
|
7920
|
+
useCallback as useCallback24,
|
|
7601
7921
|
useEffect as useEffect19,
|
|
7602
7922
|
useMemo as useMemo10,
|
|
7603
|
-
useRef as
|
|
7923
|
+
useRef as useRef19,
|
|
7604
7924
|
useState as useState26
|
|
7605
7925
|
} from "react";
|
|
7606
7926
|
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
@@ -7669,7 +7989,7 @@ function CodeEditor({
|
|
|
7669
7989
|
const [saveError, setSaveError] = useState26(null);
|
|
7670
7990
|
const [savedTick, setSavedTick] = useState26(false);
|
|
7671
7991
|
const dirty = value !== baseline;
|
|
7672
|
-
const lastSeed =
|
|
7992
|
+
const lastSeed = useRef19({ path, contents: initialContents });
|
|
7673
7993
|
useEffect19(() => {
|
|
7674
7994
|
const seedChanged = lastSeed.current.path !== path || lastSeed.current.contents !== initialContents;
|
|
7675
7995
|
if (!seedChanged) return;
|
|
@@ -7712,9 +8032,9 @@ function CodeEditor({
|
|
|
7712
8032
|
cancelled = true;
|
|
7713
8033
|
};
|
|
7714
8034
|
}, [langKey]);
|
|
7715
|
-
const saveRef =
|
|
8035
|
+
const saveRef = useRef19(() => {
|
|
7716
8036
|
});
|
|
7717
|
-
const save =
|
|
8037
|
+
const save = useCallback24(async () => {
|
|
7718
8038
|
if (readOnly) return;
|
|
7719
8039
|
const snapshot = value;
|
|
7720
8040
|
if (snapshot === baseline) return;
|
|
@@ -7858,7 +8178,7 @@ function EditorSkeleton() {
|
|
|
7858
8178
|
|
|
7859
8179
|
// src/components/sandbox-files.tsx
|
|
7860
8180
|
import { FileIcon as FileIcon3 } from "lucide-react";
|
|
7861
|
-
import { useCallback as
|
|
8181
|
+
import { useCallback as useCallback25, useEffect as useEffect20, useMemo as useMemo11, useRef as useRef20, useState as useState27 } from "react";
|
|
7862
8182
|
import { Fragment as Fragment6, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
7863
8183
|
var STATUS_TINT2 = {
|
|
7864
8184
|
added: "text-og-status-idle",
|
|
@@ -7896,7 +8216,7 @@ function SandboxFiles({
|
|
|
7896
8216
|
const [staged, setStaged] = useState27(false);
|
|
7897
8217
|
const [layout, setLayout] = useState27("unified");
|
|
7898
8218
|
const [editMode, setEditMode] = useState27(false);
|
|
7899
|
-
const rootRef =
|
|
8219
|
+
const rootRef = useRef20(null);
|
|
7900
8220
|
const [wide, setWide] = useState27(false);
|
|
7901
8221
|
useEffect20(() => {
|
|
7902
8222
|
const el = rootRef.current;
|
|
@@ -7916,7 +8236,7 @@ function SandboxFiles({
|
|
|
7916
8236
|
const selectedDiff = changed.find((f) => f.path === effectiveSelected) ?? null;
|
|
7917
8237
|
const viewPath = effectiveSelected && !selectedDiff ? effectiveSelected : null;
|
|
7918
8238
|
const fileView = useFileView(viewPath, files.readFile);
|
|
7919
|
-
const selectFile =
|
|
8239
|
+
const selectFile = useCallback25((path) => {
|
|
7920
8240
|
setSelected(path);
|
|
7921
8241
|
setEditMode(false);
|
|
7922
8242
|
}, []);
|
|
@@ -8229,7 +8549,7 @@ function Notice({ children, className }) {
|
|
|
8229
8549
|
|
|
8230
8550
|
// src/components/desktop-viewer.tsx
|
|
8231
8551
|
import { LoaderCircleIcon as LoaderCircleIcon2, MonitorIcon, MousePointerClickIcon, WifiOffIcon } from "lucide-react";
|
|
8232
|
-
import { useEffect as useEffect21, useRef as
|
|
8552
|
+
import { useEffect as useEffect21, useRef as useRef21, useState as useState28 } from "react";
|
|
8233
8553
|
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
8234
8554
|
var DESKTOP_MEDIA_BACKGROUND = "#000";
|
|
8235
8555
|
function isHardUnavailable(reason) {
|
|
@@ -8262,7 +8582,7 @@ function DesktopViewer({
|
|
|
8262
8582
|
connectTimeoutMs = 13e3,
|
|
8263
8583
|
className
|
|
8264
8584
|
}) {
|
|
8265
|
-
const containerRef =
|
|
8585
|
+
const containerRef = useRef21(null);
|
|
8266
8586
|
const [consented, setConsented] = useState28(false);
|
|
8267
8587
|
const [takeControl, setTakeControl] = useState28(interactive ?? false);
|
|
8268
8588
|
const externallyControlled = interactive !== void 0;
|
|
@@ -8304,9 +8624,9 @@ function DesktopViewer({
|
|
|
8304
8624
|
});
|
|
8305
8625
|
const connected = stream.state === "connected";
|
|
8306
8626
|
const hasLiveUrl = Boolean(connectCapability?.url);
|
|
8307
|
-
const streamStateRef =
|
|
8627
|
+
const streamStateRef = useRef21(stream.state);
|
|
8308
8628
|
streamStateRef.current = stream.state;
|
|
8309
|
-
const warmKeyRef =
|
|
8629
|
+
const warmKeyRef = useRef21(null);
|
|
8310
8630
|
useEffect21(() => {
|
|
8311
8631
|
if (!isWatching || !coldWarmable || needsAck || viewerCapReached) {
|
|
8312
8632
|
if (!coldWarmable) warmKeyRef.current = null;
|
|
@@ -8599,7 +8919,7 @@ function defaultNotice(title, body, onRetry) {
|
|
|
8599
8919
|
}
|
|
8600
8920
|
|
|
8601
8921
|
// src/components/workspace-dock.tsx
|
|
8602
|
-
import { useCallback as
|
|
8922
|
+
import { useCallback as useCallback26, useEffect as useEffect22, useLayoutEffect as useLayoutEffect2, useState as useState29 } from "react";
|
|
8603
8923
|
import {
|
|
8604
8924
|
ChevronsLeftRightIcon,
|
|
8605
8925
|
Maximize2Icon,
|
|
@@ -8615,7 +8935,7 @@ import {
|
|
|
8615
8935
|
usePanelRef
|
|
8616
8936
|
} from "react-resizable-panels";
|
|
8617
8937
|
import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
8618
|
-
var useDockLayoutEffect = typeof window === "undefined" ? useEffect22 :
|
|
8938
|
+
var useDockLayoutEffect = typeof window === "undefined" ? useEffect22 : useLayoutEffect2;
|
|
8619
8939
|
var DOCK_OVERLAY_BREAKPOINT = 1024;
|
|
8620
8940
|
function useIsNarrow(maxWidth) {
|
|
8621
8941
|
const [narrow, setNarrow] = useState29(false);
|
|
@@ -8663,14 +8983,14 @@ function WorkspaceDock({
|
|
|
8663
8983
|
const current = activeTab ?? internalTab;
|
|
8664
8984
|
const tabIds = tabs.map((tab) => tab.id).join("\0");
|
|
8665
8985
|
const firstTabId = tabs[0]?.id ?? "";
|
|
8666
|
-
const setTab =
|
|
8986
|
+
const setTab = useCallback26(
|
|
8667
8987
|
(id) => {
|
|
8668
8988
|
setInternalTab(id);
|
|
8669
8989
|
onActiveTabChange?.(id);
|
|
8670
8990
|
},
|
|
8671
8991
|
[onActiveTabChange]
|
|
8672
8992
|
);
|
|
8673
|
-
const setCollapsed =
|
|
8993
|
+
const setCollapsed = useCallback26(
|
|
8674
8994
|
(next) => {
|
|
8675
8995
|
setInternalCollapsed((previous) => previous === next ? previous : next);
|
|
8676
8996
|
onCollapsedChange?.(next);
|
|
@@ -8693,11 +9013,11 @@ function WorkspaceDock({
|
|
|
8693
9013
|
setTab(firstTabId);
|
|
8694
9014
|
}
|
|
8695
9015
|
}, [tabIds, firstTabId, current, setTab]);
|
|
8696
|
-
const collapse =
|
|
9016
|
+
const collapse = useCallback26(() => {
|
|
8697
9017
|
dockPanelRef.current?.collapse();
|
|
8698
9018
|
setCollapsed(true);
|
|
8699
9019
|
}, [dockPanelRef, setCollapsed]);
|
|
8700
|
-
const expand =
|
|
9020
|
+
const expand = useCallback26(() => {
|
|
8701
9021
|
dockPanelRef.current?.expand();
|
|
8702
9022
|
setCollapsed(false);
|
|
8703
9023
|
}, [dockPanelRef, setCollapsed]);
|
|
@@ -8866,7 +9186,7 @@ function DockChrome({
|
|
|
8866
9186
|
}
|
|
8867
9187
|
|
|
8868
9188
|
// src/hooks/use-codex-accounts.ts
|
|
8869
|
-
import { useCallback as
|
|
9189
|
+
import { useCallback as useCallback27, useState as useState30 } from "react";
|
|
8870
9190
|
function isCodexAccountEvent(event) {
|
|
8871
9191
|
return event.type === "codex.account.switched" || event.type === "turn.started";
|
|
8872
9192
|
}
|
|
@@ -8883,7 +9203,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8883
9203
|
const codexClient = options.codexClient ?? client;
|
|
8884
9204
|
const sessionId = options.sessionId;
|
|
8885
9205
|
const sharedEvents = options.events;
|
|
8886
|
-
const load =
|
|
9206
|
+
const load = useCallback27(async () => {
|
|
8887
9207
|
const accountsP = codexClient.listCodexAccounts(workspaceId);
|
|
8888
9208
|
const sessionP = sessionId && codexClient.getSession ? codexClient.getSession(workspaceId, sessionId).catch(() => null) : Promise.resolve(null);
|
|
8889
9209
|
const [acc, session] = await Promise.all([accountsP, sessionP]);
|
|
@@ -8907,7 +9227,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8907
9227
|
() => void state.refresh(),
|
|
8908
9228
|
{ enabled: options.enabled ?? true, ...sharedEvents !== void 0 ? { events: sharedEvents } : {} }
|
|
8909
9229
|
);
|
|
8910
|
-
const pin =
|
|
9230
|
+
const pin = useCallback27(
|
|
8911
9231
|
async (target) => {
|
|
8912
9232
|
if (!sessionId || !codexClient.pinSessionCodexAccount) {
|
|
8913
9233
|
return false;
|
|
@@ -8923,7 +9243,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8923
9243
|
},
|
|
8924
9244
|
[codexClient, workspaceId, sessionId, mutation.run, state.refresh]
|
|
8925
9245
|
);
|
|
8926
|
-
const refreshUsage =
|
|
9246
|
+
const refreshUsage = useCallback27(
|
|
8927
9247
|
async () => {
|
|
8928
9248
|
if (!codexClient.refreshCodexUsage) {
|
|
8929
9249
|
return false;
|