@opengeni/react 3.5.1-canary.0 → 3.7.0-canary.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/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +229 -6
- package/dist/artifacts.js.map +1 -1
- package/dist/{chunk-IB27C53Y.js → chunk-C6WDLHBA.js} +31 -23
- package/dist/chunk-C6WDLHBA.js.map +1 -0
- package/dist/{chunk-WY3MELVJ.js → chunk-DOK4KZF2.js} +119 -8
- package/dist/chunk-DOK4KZF2.js.map +1 -0
- package/dist/{chunk-TJFMMDQU.js → chunk-FJBOU2TH.js} +112 -6
- package/dist/chunk-FJBOU2TH.js.map +1 -0
- package/dist/{chunk-UNCXXIQR.js → chunk-R55HFTT3.js} +66 -24
- package/dist/chunk-R55HFTT3.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/components/artifacts/index.d.ts +1 -1
- package/dist/components/artifacts/published-html-artifact-frame.d.ts +45 -3
- package/dist/components/composer.d.ts +2 -0
- package/dist/components/session-chrome.d.ts +1 -1
- package/dist/composer.js +1 -1
- package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-YZ3ZKWMM.js} +2 -1
- package/dist/fleet-decision-row-YZ3ZKWMM.js.map +1 -0
- package/dist/hooks/use-file-attachments.d.ts +6 -0
- package/dist/hooks/use-sandbox-files.d.ts +4 -1
- package/dist/hooks/use-workspace-edit.d.ts +4 -0
- package/dist/index.js +114 -58
- package/dist/index.js.map +1 -1
- package/dist/session-ui.js +2 -2
- package/dist/session.js +2 -2
- package/dist/timeline/registry.d.ts +2 -0
- package/dist/timeline/types.d.ts +1 -1
- package/package.json +2 -2
- package/src/artifacts.ts +3 -0
- package/src/client.ts +2 -1
- package/src/components/artifacts/index.ts +3 -0
- package/src/components/artifacts/published-html-artifact-frame.tsx +284 -4
- package/src/components/composer.tsx +89 -25
- package/src/components/message-timeline.tsx +32 -8
- package/src/components/sandbox-workspace.tsx +11 -1
- package/src/components/session-chrome.tsx +3 -3
- package/src/hooks/use-file-attachments.ts +34 -0
- package/src/hooks/use-sandbox-files.ts +68 -20
- package/src/hooks/use-session-events.ts +21 -26
- package/src/hooks/use-workspace-edit.ts +23 -5
- package/src/timeline/fleet-decision-projection.ts +2 -1
- package/src/timeline/fleet-decision-row.tsx +1 -0
- package/src/timeline/projection.ts +151 -7
- package/src/timeline/registry.ts +15 -3
- package/src/timeline/tool-renderers.tsx +117 -1
- package/src/timeline/types.ts +8 -1
- package/dist/chunk-IB27C53Y.js.map +0 -1
- package/dist/chunk-TJFMMDQU.js.map +0 -1
- package/dist/chunk-UNCXXIQR.js.map +0 -1
- package/dist/chunk-WY3MELVJ.js.map +0 -1
- package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -95,7 +95,7 @@ import {
|
|
|
95
95
|
useSlashCommands,
|
|
96
96
|
useTranscription,
|
|
97
97
|
useVoiceInput
|
|
98
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-R55HFTT3.js";
|
|
99
99
|
import {
|
|
100
100
|
BillingClassMark,
|
|
101
101
|
ModelPolicyPicker,
|
|
@@ -163,7 +163,7 @@ import {
|
|
|
163
163
|
useThemeType,
|
|
164
164
|
userMessageLikelyNeedsDisclosure,
|
|
165
165
|
v4aToGitFileDiff
|
|
166
|
-
} from "./chunk-
|
|
166
|
+
} from "./chunk-DOK4KZF2.js";
|
|
167
167
|
import {
|
|
168
168
|
TimelineAnnotationsChip
|
|
169
169
|
} from "./chunk-W3OUAH6M.js";
|
|
@@ -209,7 +209,7 @@ import {
|
|
|
209
209
|
useSessionLineage,
|
|
210
210
|
useSessionMcpApprovalPolicy,
|
|
211
211
|
useTurnQueue
|
|
212
|
-
} from "./chunk-
|
|
212
|
+
} from "./chunk-C6WDLHBA.js";
|
|
213
213
|
import {
|
|
214
214
|
FILE_ONLY_MESSAGE_TEXT,
|
|
215
215
|
composeSendInput,
|
|
@@ -237,7 +237,7 @@ import {
|
|
|
237
237
|
projectPendingHumanInputRequests,
|
|
238
238
|
sessionStatusFromEvents,
|
|
239
239
|
toolDisplayName
|
|
240
|
-
} from "./chunk-
|
|
240
|
+
} from "./chunk-FJBOU2TH.js";
|
|
241
241
|
import {
|
|
242
242
|
COMPOSER_PAYMENT_REQUIRED_MESSAGE,
|
|
243
243
|
CREDIT_EXHAUSTION_MESSAGE,
|
|
@@ -2085,8 +2085,11 @@ function normalizeRoot(root) {
|
|
|
2085
2085
|
const normalized = slashNormalized.replace(/\/+$/, "");
|
|
2086
2086
|
return normalized === "." ? "" : normalized;
|
|
2087
2087
|
}
|
|
2088
|
+
function isAbsoluteTreePath(path) {
|
|
2089
|
+
return path.startsWith("/") || /^[A-Za-z]:\//u.test(path);
|
|
2090
|
+
}
|
|
2088
2091
|
function joinTreeRoot(root, path) {
|
|
2089
|
-
if (!root || path
|
|
2092
|
+
if (!root || isAbsoluteTreePath(path)) return path;
|
|
2090
2093
|
return root === "/" ? `/${path}` : `${root}/${path}`;
|
|
2091
2094
|
}
|
|
2092
2095
|
function qualifyStatusPath(root, path, treeRoot) {
|
|
@@ -2174,6 +2177,7 @@ var FS_LIST_BATCH_REQUEST_LIMIT = 16;
|
|
|
2174
2177
|
function initialDirectoryFrontier(rootPath, repoPaths) {
|
|
2175
2178
|
const root = normalizeRoot(rootPath);
|
|
2176
2179
|
const rootParts = root.split("/").filter(Boolean);
|
|
2180
|
+
const rootPrefix = root.startsWith("//") ? "//" : root.startsWith("/") ? "/" : "";
|
|
2177
2181
|
const paths = /* @__PURE__ */ new Set();
|
|
2178
2182
|
for (const repoPath of repoPaths) {
|
|
2179
2183
|
const canonicalRepoPath = joinTreeRoot(root, normalizeRoot(repoPath));
|
|
@@ -2181,7 +2185,7 @@ function initialDirectoryFrontier(rootPath, repoPaths) {
|
|
|
2181
2185
|
if (rootParts.some((part, index) => parts[index] !== part)) continue;
|
|
2182
2186
|
for (let depth = rootParts.length + 1; depth <= parts.length; depth += 1) {
|
|
2183
2187
|
const path = parts.slice(0, depth).join("/");
|
|
2184
|
-
paths.add(
|
|
2188
|
+
paths.add(`${rootPrefix}${path}`);
|
|
2185
2189
|
}
|
|
2186
2190
|
}
|
|
2187
2191
|
return [...paths].sort((a, b) => a.split("/").length - b.split("/").length || a.localeCompare(b)).slice(0, 8);
|
|
@@ -2291,6 +2295,12 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2291
2295
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
2292
2296
|
const active = options.active ?? true;
|
|
2293
2297
|
const rootPath = options.rootPath ?? "";
|
|
2298
|
+
const routeEpoch = options.route?.epoch ?? null;
|
|
2299
|
+
const routeRoot = options.route?.root ?? null;
|
|
2300
|
+
const route = useMemo6(
|
|
2301
|
+
() => routeEpoch !== null && routeRoot !== null ? { epoch: routeEpoch, root: routeRoot } : void 0,
|
|
2302
|
+
[routeEpoch, routeRoot]
|
|
2303
|
+
);
|
|
2294
2304
|
const repoPathsKey = [
|
|
2295
2305
|
...new Set((options.repoPaths?.length ? options.repoPaths : [rootPath]).map(normalizeRoot))
|
|
2296
2306
|
].join("\0");
|
|
@@ -2301,7 +2311,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2301
2311
|
const acceptsEventReadsRef = useRef5(acceptsEventReads);
|
|
2302
2312
|
acceptsEventReadsRef.current = acceptsEventReads;
|
|
2303
2313
|
const hasLiveIoFence = options.liveness !== void 0;
|
|
2304
|
-
const identityKey = `${workspaceId}\0${sessionId ?? ""}\0${rootPath}\0${repoPathsKey}`;
|
|
2314
|
+
const identityKey = `${workspaceId}\0${sessionId ?? ""}\0${rootPath}\0${repoPathsKey}\0${routeEpoch ?? ""}\0${routeRoot ?? ""}`;
|
|
2305
2315
|
const [tree, setTree] = useState4([]);
|
|
2306
2316
|
const treeRef = useRef5([]);
|
|
2307
2317
|
const [loading, setLoading] = useState4(false);
|
|
@@ -2364,7 +2374,8 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2364
2374
|
const frontierPaths = initialDirectoryFrontier(rootPath, repoPaths);
|
|
2365
2375
|
const listRequests = [rootPath, ...frontierPaths].map((path) => ({
|
|
2366
2376
|
path,
|
|
2367
|
-
depth: 1
|
|
2377
|
+
depth: 1,
|
|
2378
|
+
...route ? { route } : {}
|
|
2368
2379
|
}));
|
|
2369
2380
|
const listedBatch = await client.fsListBatch(
|
|
2370
2381
|
workspaceId,
|
|
@@ -2433,7 +2444,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2433
2444
|
if (refreshGenerationRef.current === generation) setGitLoading(false);
|
|
2434
2445
|
if (refreshAbortRef.current === refreshAbort) refreshAbortRef.current = null;
|
|
2435
2446
|
}
|
|
2436
|
-
}, [client, workspaceId, sessionId, rootPath, repoPaths, applyStatus]);
|
|
2447
|
+
}, [client, workspaceId, sessionId, rootPath, repoPaths, route, applyStatus]);
|
|
2437
2448
|
const seedFromCapture = useCallback15(
|
|
2438
2449
|
(manifest) => {
|
|
2439
2450
|
const overlay = /* @__PURE__ */ new Map();
|
|
@@ -2477,7 +2488,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2477
2488
|
const listed = await client.fsList(
|
|
2478
2489
|
workspaceId,
|
|
2479
2490
|
sessionId,
|
|
2480
|
-
{ path, depth: 1 },
|
|
2491
|
+
{ path, depth: 1, ...route ? { route } : {} },
|
|
2481
2492
|
{ signal: identitySignal }
|
|
2482
2493
|
);
|
|
2483
2494
|
if (identityGenerationRef.current !== identityGeneration) return;
|
|
@@ -2497,7 +2508,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2497
2508
|
}
|
|
2498
2509
|
}
|
|
2499
2510
|
},
|
|
2500
|
-
[client, workspaceId, sessionId, capture, source, applyStatus]
|
|
2511
|
+
[client, workspaceId, sessionId, capture, source, route, applyStatus]
|
|
2501
2512
|
);
|
|
2502
2513
|
const readFile = useCallback15(
|
|
2503
2514
|
async (path, requestOptions = {}) => {
|
|
@@ -2570,9 +2581,14 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2570
2581
|
}
|
|
2571
2582
|
throw new Error("Captured file download failed after refreshing its URL.");
|
|
2572
2583
|
}
|
|
2573
|
-
return await client.fsRead(
|
|
2584
|
+
return await client.fsRead(
|
|
2585
|
+
workspaceId,
|
|
2586
|
+
sessionId,
|
|
2587
|
+
{ path, ...route ? { route } : {} },
|
|
2588
|
+
{ signal }
|
|
2589
|
+
);
|
|
2574
2590
|
},
|
|
2575
|
-
[client, workspaceId, sessionId, capture, source]
|
|
2591
|
+
[client, workspaceId, sessionId, capture, source, route]
|
|
2576
2592
|
);
|
|
2577
2593
|
const reconcilePath = useCallback15(
|
|
2578
2594
|
async (path, requestSignal) => {
|
|
@@ -2582,7 +2598,12 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2582
2598
|
const signal = requestSignal ? AbortSignal.any([identitySignal, requestSignal]) : identitySignal;
|
|
2583
2599
|
if (!parentIsLoaded(treeRef.current, path, rootPath)) return;
|
|
2584
2600
|
try {
|
|
2585
|
-
const listed = await client.fsList(
|
|
2601
|
+
const listed = await client.fsList(
|
|
2602
|
+
workspaceId,
|
|
2603
|
+
sessionId,
|
|
2604
|
+
{ path, depth: 1, ...route ? { route } : {} },
|
|
2605
|
+
{ signal }
|
|
2606
|
+
);
|
|
2586
2607
|
if (identityGenerationRef.current !== identityGeneration) return;
|
|
2587
2608
|
const children = (listed.root.children ?? []).map((node) => fsNodeToTree(node));
|
|
2588
2609
|
if (path === normalizeRoot(rootPath)) {
|
|
@@ -2596,7 +2617,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2596
2617
|
} catch {
|
|
2597
2618
|
}
|
|
2598
2619
|
},
|
|
2599
|
-
[client, workspaceId, sessionId, rootPath, applyStatus]
|
|
2620
|
+
[client, workspaceId, sessionId, rootPath, route, applyStatus]
|
|
2600
2621
|
);
|
|
2601
2622
|
const reconcilePaths = useCallback15(
|
|
2602
2623
|
async (requestedPaths, requestSignal) => {
|
|
@@ -2613,7 +2634,13 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2613
2634
|
const listed = await client.fsListBatch(
|
|
2614
2635
|
workspaceId,
|
|
2615
2636
|
sessionId,
|
|
2616
|
-
{
|
|
2637
|
+
{
|
|
2638
|
+
requests: chunk.map((path) => ({
|
|
2639
|
+
path,
|
|
2640
|
+
depth: 1,
|
|
2641
|
+
...route ? { route } : {}
|
|
2642
|
+
}))
|
|
2643
|
+
},
|
|
2617
2644
|
{ signal }
|
|
2618
2645
|
);
|
|
2619
2646
|
if (identityGenerationRef.current !== identityGeneration) return;
|
|
@@ -2637,7 +2664,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2637
2664
|
}
|
|
2638
2665
|
}
|
|
2639
2666
|
},
|
|
2640
|
-
[client, workspaceId, sessionId, rootPath, applyStatus]
|
|
2667
|
+
[client, workspaceId, sessionId, rootPath, route, applyStatus]
|
|
2641
2668
|
);
|
|
2642
2669
|
const runOptimistic = useCallback15(
|
|
2643
2670
|
async (opName, apply, op, reconcileParents) => {
|
|
@@ -2690,7 +2717,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2690
2717
|
const live = await client.fsRead(
|
|
2691
2718
|
workspaceId,
|
|
2692
2719
|
sessionId,
|
|
2693
|
-
{ path },
|
|
2720
|
+
{ path, ...route ? { route } : {} },
|
|
2694
2721
|
{ signal: identitySignal }
|
|
2695
2722
|
);
|
|
2696
2723
|
if (identityGenerationRef.current !== identityGeneration) {
|
|
@@ -2707,13 +2734,14 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2707
2734
|
return await client.fsWrite(workspaceId, sessionId, {
|
|
2708
2735
|
path,
|
|
2709
2736
|
content,
|
|
2710
|
-
overwrite: true
|
|
2737
|
+
overwrite: true,
|
|
2738
|
+
...route ? { route } : {}
|
|
2711
2739
|
});
|
|
2712
2740
|
},
|
|
2713
2741
|
exists ? [] : [parent]
|
|
2714
2742
|
);
|
|
2715
2743
|
},
|
|
2716
|
-
[client, workspaceId, sessionId, tree, rootPath, runOptimistic]
|
|
2744
|
+
[client, workspaceId, sessionId, tree, rootPath, route, runOptimistic]
|
|
2717
2745
|
);
|
|
2718
2746
|
const createFile = useCallback15(
|
|
2719
2747
|
async (path) => {
|
|
@@ -2731,12 +2759,13 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2731
2759
|
() => client.fsWrite(workspaceId, sessionId, {
|
|
2732
2760
|
path,
|
|
2733
2761
|
content: "",
|
|
2734
|
-
overwrite: false
|
|
2762
|
+
overwrite: false,
|
|
2763
|
+
...route ? { route } : {}
|
|
2735
2764
|
}),
|
|
2736
2765
|
[parent]
|
|
2737
2766
|
);
|
|
2738
2767
|
},
|
|
2739
|
-
[client, workspaceId, sessionId, rootPath, runOptimistic]
|
|
2768
|
+
[client, workspaceId, sessionId, rootPath, route, runOptimistic]
|
|
2740
2769
|
);
|
|
2741
2770
|
const createDir = useCallback15(
|
|
2742
2771
|
async (path) => {
|
|
@@ -2751,11 +2780,15 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2751
2780
|
await runOptimistic(
|
|
2752
2781
|
"create folder",
|
|
2753
2782
|
(nodes) => insertNode(nodes, parent, node, rootPath),
|
|
2754
|
-
() => client.fsMkdir(workspaceId, sessionId, {
|
|
2783
|
+
() => client.fsMkdir(workspaceId, sessionId, {
|
|
2784
|
+
path,
|
|
2785
|
+
recursive: true,
|
|
2786
|
+
...route ? { route } : {}
|
|
2787
|
+
}),
|
|
2755
2788
|
[parent]
|
|
2756
2789
|
);
|
|
2757
2790
|
},
|
|
2758
|
-
[client, workspaceId, sessionId, rootPath, runOptimistic]
|
|
2791
|
+
[client, workspaceId, sessionId, rootPath, route, runOptimistic]
|
|
2759
2792
|
);
|
|
2760
2793
|
const deleteEntry = useCallback15(
|
|
2761
2794
|
async (path, recursive = false) => {
|
|
@@ -2763,11 +2796,15 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2763
2796
|
await runOptimistic(
|
|
2764
2797
|
"delete",
|
|
2765
2798
|
(nodes) => removeNode(nodes, path, rootPath),
|
|
2766
|
-
() => client.fsDelete(workspaceId, sessionId, {
|
|
2799
|
+
() => client.fsDelete(workspaceId, sessionId, {
|
|
2800
|
+
path,
|
|
2801
|
+
recursive,
|
|
2802
|
+
...route ? { route } : {}
|
|
2803
|
+
}),
|
|
2767
2804
|
[parentWithinTree(path, rootPath)]
|
|
2768
2805
|
);
|
|
2769
2806
|
},
|
|
2770
|
-
[client, workspaceId, sessionId, rootPath, runOptimistic]
|
|
2807
|
+
[client, workspaceId, sessionId, rootPath, route, runOptimistic]
|
|
2771
2808
|
);
|
|
2772
2809
|
const moveEntry = useCallback15(
|
|
2773
2810
|
async (path, newPath, opts) => {
|
|
@@ -2785,12 +2822,13 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
2785
2822
|
() => client.fsMove(workspaceId, sessionId, {
|
|
2786
2823
|
path,
|
|
2787
2824
|
newPath,
|
|
2788
|
-
overwrite: opts?.overwrite ?? false
|
|
2825
|
+
overwrite: opts?.overwrite ?? false,
|
|
2826
|
+
...route ? { route } : {}
|
|
2789
2827
|
}),
|
|
2790
2828
|
to === from ? [from] : [from, to]
|
|
2791
2829
|
);
|
|
2792
2830
|
},
|
|
2793
|
-
[client, workspaceId, sessionId, rootPath, runOptimistic]
|
|
2831
|
+
[client, workspaceId, sessionId, rootPath, route, runOptimistic]
|
|
2794
2832
|
);
|
|
2795
2833
|
const captureRef = useRef5(capture);
|
|
2796
2834
|
captureRef.current = capture;
|
|
@@ -3615,7 +3653,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
|
|
|
3615
3653
|
}
|
|
3616
3654
|
|
|
3617
3655
|
// src/hooks/use-workspace-edit.ts
|
|
3618
|
-
import { useCallback as useCallback18, useEffect as useEffect9, useRef as useRef8, useState as useState7 } from "react";
|
|
3656
|
+
import { useCallback as useCallback18, useEffect as useEffect9, useMemo as useMemo8, useRef as useRef8, useState as useState7 } from "react";
|
|
3619
3657
|
function isLive(liveness) {
|
|
3620
3658
|
return sandboxAcceptsLiveIo(liveness);
|
|
3621
3659
|
}
|
|
@@ -3623,9 +3661,15 @@ function useWorkspaceEdit(sessionId, options = {}) {
|
|
|
3623
3661
|
const { client, workspaceId } = useOpenGeni(options);
|
|
3624
3662
|
const path = options.path ?? null;
|
|
3625
3663
|
const baseContent = options.baseContent ?? null;
|
|
3664
|
+
const routeEpoch = options.route?.epoch;
|
|
3665
|
+
const routeRoot = options.route?.root;
|
|
3666
|
+
const route = useMemo8(
|
|
3667
|
+
() => routeEpoch !== void 0 && routeRoot !== void 0 ? { epoch: routeEpoch, root: routeRoot } : void 0,
|
|
3668
|
+
[routeEpoch, routeRoot]
|
|
3669
|
+
);
|
|
3626
3670
|
const live = isLive(options.liveness);
|
|
3627
3671
|
const offline = options.offline === true;
|
|
3628
|
-
const identityKey = `${workspaceId}\0${sessionId ?? ""}\0${path ?? ""}`;
|
|
3672
|
+
const identityKey = `${workspaceId}\0${sessionId ?? ""}\0${path ?? ""}\0${routeEpoch ?? ""}\0${routeRoot ?? ""}`;
|
|
3629
3673
|
const [buffer, setBuffer] = useState7(null);
|
|
3630
3674
|
const [wantsWarm, setWantsWarm] = useState7(false);
|
|
3631
3675
|
const [flush, setFlush] = useState7("idle");
|
|
@@ -3694,7 +3738,7 @@ function useWorkspaceEdit(sessionId, options = {}) {
|
|
|
3694
3738
|
const liveRead = await client.fsRead(
|
|
3695
3739
|
workspaceId,
|
|
3696
3740
|
sessionId,
|
|
3697
|
-
{ path },
|
|
3741
|
+
{ path, ...route ? { route } : {} },
|
|
3698
3742
|
{ signal: readAbort.signal }
|
|
3699
3743
|
);
|
|
3700
3744
|
if (readAbortRef.current === readAbort) readAbortRef.current = null;
|
|
@@ -3706,7 +3750,12 @@ function useWorkspaceEdit(sessionId, options = {}) {
|
|
|
3706
3750
|
return;
|
|
3707
3751
|
}
|
|
3708
3752
|
}
|
|
3709
|
-
await client.fsWrite(workspaceId, sessionId, {
|
|
3753
|
+
await client.fsWrite(workspaceId, sessionId, {
|
|
3754
|
+
path,
|
|
3755
|
+
content,
|
|
3756
|
+
overwrite: true,
|
|
3757
|
+
...route ? { route } : {}
|
|
3758
|
+
});
|
|
3710
3759
|
if (identityGenerationRef.current !== identityGeneration) return;
|
|
3711
3760
|
setConflict(null);
|
|
3712
3761
|
setFlush("flushed");
|
|
@@ -3722,7 +3771,7 @@ function useWorkspaceEdit(sessionId, options = {}) {
|
|
|
3722
3771
|
}
|
|
3723
3772
|
}
|
|
3724
3773
|
},
|
|
3725
|
-
[client, workspaceId, sessionId, path, baseContent, stateIdentity, identityKey]
|
|
3774
|
+
[client, workspaceId, sessionId, path, baseContent, route, stateIdentity, identityKey]
|
|
3726
3775
|
);
|
|
3727
3776
|
useEffect9(() => {
|
|
3728
3777
|
if (offline) return;
|
|
@@ -3774,7 +3823,7 @@ function useWorkspaceEdit(sessionId, options = {}) {
|
|
|
3774
3823
|
}
|
|
3775
3824
|
|
|
3776
3825
|
// src/hooks/use-machine-chip.ts
|
|
3777
|
-
import { useMemo as
|
|
3826
|
+
import { useMemo as useMemo9 } from "react";
|
|
3778
3827
|
function formatAsOf(capturedAt, now) {
|
|
3779
3828
|
const then = Date.parse(capturedAt);
|
|
3780
3829
|
if (Number.isNaN(then)) return "recently";
|
|
@@ -3824,7 +3873,7 @@ function useMachineChip(input) {
|
|
|
3824
3873
|
capturedAt,
|
|
3825
3874
|
now
|
|
3826
3875
|
} = input;
|
|
3827
|
-
return
|
|
3876
|
+
return useMemo9(
|
|
3828
3877
|
() => deriveMachineChip({
|
|
3829
3878
|
liveness,
|
|
3830
3879
|
capabilitiesState,
|
|
@@ -4765,7 +4814,7 @@ import {
|
|
|
4765
4814
|
useEffect as useEffect13,
|
|
4766
4815
|
useId as useId2,
|
|
4767
4816
|
useLayoutEffect as useLayoutEffect2,
|
|
4768
|
-
useMemo as
|
|
4817
|
+
useMemo as useMemo11,
|
|
4769
4818
|
useRef as useRef11,
|
|
4770
4819
|
useState as useState10
|
|
4771
4820
|
} from "react";
|
|
@@ -4773,11 +4822,11 @@ import { AlertDialog } from "radix-ui";
|
|
|
4773
4822
|
import { VList } from "virtua";
|
|
4774
4823
|
|
|
4775
4824
|
// src/lib/use-unicode-fonts.ts
|
|
4776
|
-
import { useEffect as useEffect12, useMemo as
|
|
4825
|
+
import { useEffect as useEffect12, useMemo as useMemo10 } from "react";
|
|
4777
4826
|
var japaneseScript = /[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/u;
|
|
4778
4827
|
var arabicScript = /[\u0600-\u06ff\u0750-\u077f\u0870-\u08ff\ufb50-\ufdff\ufe70-\ufefc]/u;
|
|
4779
4828
|
function useUnicodeFallbackFonts(values) {
|
|
4780
|
-
const content =
|
|
4829
|
+
const content = useMemo10(() => collectUnicodeContent(values), [values]);
|
|
4781
4830
|
useEffect12(() => {
|
|
4782
4831
|
if (content.japanese) {
|
|
4783
4832
|
void import("./noto-sans-jp-loader.generated-HFGLYBR3.js").then(({ loadNotoSansJp }) => loadNotoSansJp(content.japanese)).catch(() => void 0);
|
|
@@ -4901,7 +4950,7 @@ function FileBrowser({
|
|
|
4901
4950
|
() => typeof document === "undefined" ? null : document.getElementById(treeId),
|
|
4902
4951
|
[treeId]
|
|
4903
4952
|
);
|
|
4904
|
-
const visibleTree =
|
|
4953
|
+
const visibleTree = useMemo11(
|
|
4905
4954
|
() => visibleFileTree(result.tree, isNodeVisible),
|
|
4906
4955
|
[isNodeVisible, result.tree]
|
|
4907
4956
|
);
|
|
@@ -5002,7 +5051,7 @@ function FileBrowser({
|
|
|
5002
5051
|
[expanded, expand]
|
|
5003
5052
|
);
|
|
5004
5053
|
const cold = result.source !== "live";
|
|
5005
|
-
const renderItems =
|
|
5054
|
+
const renderItems = useMemo11(() => {
|
|
5006
5055
|
const items = [];
|
|
5007
5056
|
if (draftCreate && draftCreate.parent === "") {
|
|
5008
5057
|
items.push({ type: "create", parent: "", kind: draftCreate.kind, depth: 0 });
|
|
@@ -5033,22 +5082,22 @@ function FileBrowser({
|
|
|
5033
5082
|
walk(visibleTree, 0);
|
|
5034
5083
|
return items;
|
|
5035
5084
|
}, [visibleTree, expanded, draftCreate, loadingPaths, result.expandingPaths, cold]);
|
|
5036
|
-
const unicodeFontPaths =
|
|
5085
|
+
const unicodeFontPaths = useMemo11(
|
|
5037
5086
|
() => renderItems.flatMap((item) => item.type === "node" ? [item.node.path] : []),
|
|
5038
5087
|
[renderItems]
|
|
5039
5088
|
);
|
|
5040
5089
|
useUnicodeFallbackFonts(unicodeFontPaths);
|
|
5041
|
-
const flatRows =
|
|
5090
|
+
const flatRows = useMemo11(
|
|
5042
5091
|
() => renderItems.flatMap(
|
|
5043
5092
|
(item) => item.type === "node" ? [{ node: item.node, depth: item.depth }] : []
|
|
5044
5093
|
),
|
|
5045
5094
|
[renderItems]
|
|
5046
5095
|
);
|
|
5047
|
-
const rowIndexByPath =
|
|
5096
|
+
const rowIndexByPath = useMemo11(
|
|
5048
5097
|
() => new Map(flatRows.map((row, index) => [row.node.path, index])),
|
|
5049
5098
|
[flatRows]
|
|
5050
5099
|
);
|
|
5051
|
-
const treePositionByPath =
|
|
5100
|
+
const treePositionByPath = useMemo11(() => {
|
|
5052
5101
|
const positions = /* @__PURE__ */ new Map();
|
|
5053
5102
|
const visit = (nodes) => {
|
|
5054
5103
|
nodes.forEach((node, index) => {
|
|
@@ -6009,14 +6058,14 @@ import {
|
|
|
6009
6058
|
useEffect as useEffect15,
|
|
6010
6059
|
useId as useId3,
|
|
6011
6060
|
useLayoutEffect as useLayoutEffect3,
|
|
6012
|
-
useMemo as
|
|
6061
|
+
useMemo as useMemo13,
|
|
6013
6062
|
useRef as useRef13,
|
|
6014
6063
|
useState as useState12
|
|
6015
6064
|
} from "react";
|
|
6016
6065
|
import { VList as VList2 } from "virtua";
|
|
6017
6066
|
|
|
6018
6067
|
// src/hooks/use-windowed-sections.ts
|
|
6019
|
-
import { useCallback as useCallback20, useEffect as useEffect14, useMemo as
|
|
6068
|
+
import { useCallback as useCallback20, useEffect as useEffect14, useMemo as useMemo12, useRef as useRef12, useState as useState11 } from "react";
|
|
6020
6069
|
function computeWindowRange(heights, scrollTop, viewport, overscan) {
|
|
6021
6070
|
const n = heights.length;
|
|
6022
6071
|
if (n === 0) return { start: 0, end: 0 };
|
|
@@ -6099,7 +6148,7 @@ function useWindowedSections(opts) {
|
|
|
6099
6148
|
return next;
|
|
6100
6149
|
});
|
|
6101
6150
|
}, []);
|
|
6102
|
-
const offsets =
|
|
6151
|
+
const offsets = useMemo12(() => {
|
|
6103
6152
|
const out = new Array(count + 1);
|
|
6104
6153
|
out[0] = 0;
|
|
6105
6154
|
for (let i = 0; i < count; i++) out[i + 1] = (out[i] ?? 0) + Math.max(heights[i] ?? 0, 0);
|
|
@@ -6317,12 +6366,12 @@ function WorkbenchChanges({
|
|
|
6317
6366
|
const [layout, setLayout] = useState12("unified");
|
|
6318
6367
|
const [activePath, setActivePath] = useState12(null);
|
|
6319
6368
|
const pickerId = useId3();
|
|
6320
|
-
const unicodeFontPaths =
|
|
6369
|
+
const unicodeFontPaths = useMemo13(
|
|
6321
6370
|
() => diff.flatMap((file) => file.oldPath ? [file.path, file.oldPath] : [file.path]),
|
|
6322
6371
|
[diff]
|
|
6323
6372
|
);
|
|
6324
6373
|
useUnicodeFallbackFonts(unicodeFontPaths);
|
|
6325
|
-
const { orderedFiles, rows, grouped } =
|
|
6374
|
+
const { orderedFiles, rows, grouped } = useMemo13(() => buildRail(diff), [diff]);
|
|
6326
6375
|
const selectedIndex = orderedFiles.findIndex((file) => file.path === activePath);
|
|
6327
6376
|
const activeIndex = selectedIndex >= 0 ? selectedIndex : 0;
|
|
6328
6377
|
useChangesLayoutEffect(() => {
|
|
@@ -6352,8 +6401,8 @@ function WorkbenchChanges({
|
|
|
6352
6401
|
return () => query.removeListener(update);
|
|
6353
6402
|
}
|
|
6354
6403
|
}, []);
|
|
6355
|
-
const additions =
|
|
6356
|
-
const deletions =
|
|
6404
|
+
const additions = useMemo13(() => diff.reduce((sum, f) => sum + f.additions, 0), [diff]);
|
|
6405
|
+
const deletions = useMemo13(() => diff.reduce((sum, f) => sum + f.deletions, 0), [diff]);
|
|
6357
6406
|
const estimateHeight = useCallback21(
|
|
6358
6407
|
(index) => {
|
|
6359
6408
|
const file = orderedFiles[index];
|
|
@@ -6838,7 +6887,7 @@ import { Loader2Icon, SaveIcon } from "lucide-react";
|
|
|
6838
6887
|
import {
|
|
6839
6888
|
useCallback as useCallback22,
|
|
6840
6889
|
useEffect as useEffect17,
|
|
6841
|
-
useMemo as
|
|
6890
|
+
useMemo as useMemo14,
|
|
6842
6891
|
useRef as useRef14,
|
|
6843
6892
|
useState as useState14
|
|
6844
6893
|
} from "react";
|
|
@@ -6946,7 +6995,7 @@ function CodeEditor({
|
|
|
6946
6995
|
},
|
|
6947
6996
|
[baseline, onEditIntent]
|
|
6948
6997
|
);
|
|
6949
|
-
const langKey =
|
|
6998
|
+
const langKey = useMemo14(() => languageForPath(path), [path]);
|
|
6950
6999
|
useEffect17(() => {
|
|
6951
7000
|
let cancelled = false;
|
|
6952
7001
|
void (async () => {
|
|
@@ -7040,7 +7089,7 @@ function CodeEditor({
|
|
|
7040
7089
|
return () => clearTimeout(t);
|
|
7041
7090
|
}, [savedTick]);
|
|
7042
7091
|
const fileName = path.split("/").filter(Boolean).pop() ?? path;
|
|
7043
|
-
const cmExtensions =
|
|
7092
|
+
const cmExtensions = useMemo14(() => {
|
|
7044
7093
|
if (!bundle) return [];
|
|
7045
7094
|
const exts = [bundle.saveKeymapExtension(() => saveRef.current())];
|
|
7046
7095
|
if (bundle.languageExtension) exts.push(bundle.languageExtension);
|
|
@@ -8413,7 +8462,7 @@ import {
|
|
|
8413
8462
|
Suspense as Suspense2,
|
|
8414
8463
|
useCallback as useCallback25,
|
|
8415
8464
|
useEffect as useEffect20,
|
|
8416
|
-
useMemo as
|
|
8465
|
+
useMemo as useMemo15,
|
|
8417
8466
|
useRef as useRef17,
|
|
8418
8467
|
useState as useState17
|
|
8419
8468
|
} from "react";
|
|
@@ -8453,6 +8502,11 @@ var WORKBENCH_SURFACES = [
|
|
|
8453
8502
|
function isWorkbenchSurface(value) {
|
|
8454
8503
|
return WORKBENCH_SURFACES.includes(value);
|
|
8455
8504
|
}
|
|
8505
|
+
function isCanonicalAbsoluteSandboxPath(value) {
|
|
8506
|
+
if (!value) return false;
|
|
8507
|
+
const portable = value.replaceAll("\\", "/");
|
|
8508
|
+
return portable.startsWith("/") || /^[A-Za-z]:\//u.test(portable);
|
|
8509
|
+
}
|
|
8456
8510
|
function sourceDrivenDefaultTab(hasChanges, changesEnabled, filesEnabled) {
|
|
8457
8511
|
if (hasChanges && changesEnabled) return WORKBENCH_TAB_CHANGES;
|
|
8458
8512
|
if (filesEnabled) return WORKBENCH_TAB_FILES;
|
|
@@ -8647,6 +8701,7 @@ function useSandboxWorkspaceTabs(options) {
|
|
|
8647
8701
|
const liveness = capabilities?.liveness;
|
|
8648
8702
|
const liveIoLiveness = liveness ?? null;
|
|
8649
8703
|
const fileSystemOn = capabilities?.FileSystem.available ?? false;
|
|
8704
|
+
const fileSystemRoute = capabilities ? { epoch: capabilities.leaseEpoch, root: capabilities.FileSystem.root } : void 0;
|
|
8650
8705
|
const fsReadOnly = capabilities?.FileSystem.readOnly ?? false;
|
|
8651
8706
|
const filesEditable = fileSystemOn && !fsReadOnly && sandboxAcceptsLiveIo(liveness);
|
|
8652
8707
|
const gitOn = capabilities?.Git.available ?? false;
|
|
@@ -8678,7 +8733,7 @@ function useSandboxWorkspaceTabs(options) {
|
|
|
8678
8733
|
const captureAvailable = captureState.available;
|
|
8679
8734
|
const liveWorkspaceExpected = sandboxAcceptsLiveIo(liveness);
|
|
8680
8735
|
const capturePending = !liveWorkspaceExpected && (captureState.fileCount === null || captureState.loading);
|
|
8681
|
-
const repoPaths =
|
|
8736
|
+
const repoPaths = useMemo15(() => {
|
|
8682
8737
|
const advertised = capabilities?.Git.repos ?? [];
|
|
8683
8738
|
if (advertised.length > 0) return advertised;
|
|
8684
8739
|
return captureState.capture?.repos.map((repo) => repo.root) ?? [];
|
|
@@ -8708,7 +8763,8 @@ function useSandboxWorkspaceTabs(options) {
|
|
|
8708
8763
|
active: filesActive && !turnInFlight,
|
|
8709
8764
|
// A deliberate canonical absolute-path open browses in the selected target's
|
|
8710
8765
|
// advertised namespace, so the authoritative tree and link share exact paths.
|
|
8711
|
-
...requestedFilePath
|
|
8766
|
+
...isCanonicalAbsoluteSandboxPath(requestedFilePath) && capabilities?.FileSystem.root ? { rootPath: capabilities.FileSystem.root } : {},
|
|
8767
|
+
...fileSystemRoute ? { route: fileSystemRoute } : {},
|
|
8712
8768
|
repoPaths,
|
|
8713
8769
|
liveness: liveIoLiveness,
|
|
8714
8770
|
capture: captureState.capture,
|
|
@@ -8792,7 +8848,7 @@ function useSandboxWorkspaceTabs(options) {
|
|
|
8792
8848
|
}
|
|
8793
8849
|
}
|
|
8794
8850
|
const defaultTab = defaultTabRef.current.value;
|
|
8795
|
-
const tabs =
|
|
8851
|
+
const tabs = useMemo15(() => {
|
|
8796
8852
|
const list = [];
|
|
8797
8853
|
if (changesEnabled)
|
|
8798
8854
|
list.push({
|