replicas-cli 0.2.339 → 0.2.341
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/index.mjs +171 -131
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -9597,7 +9597,7 @@ var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
|
9597
9597
|
var REPLICAS_CONFIG_FILENAMES = ["replicas.json", "replicas.yaml", "replicas.yml"];
|
|
9598
9598
|
|
|
9599
9599
|
// ../shared/src/cli-version.ts
|
|
9600
|
-
var CLI_VERSION = "0.2.
|
|
9600
|
+
var CLI_VERSION = "0.2.341";
|
|
9601
9601
|
|
|
9602
9602
|
// ../shared/src/engine/environment.ts
|
|
9603
9603
|
var DESKTOP_NOVNC_PORT = 6080;
|
|
@@ -16298,7 +16298,7 @@ import { createCliRenderer } from "@opentui/core";
|
|
|
16298
16298
|
import { createRoot } from "@opentui/react";
|
|
16299
16299
|
|
|
16300
16300
|
// src/interactive/App.tsx
|
|
16301
|
-
import { useState as
|
|
16301
|
+
import { useState as useState7, useEffect as useEffect2, useMemo as useMemo5, useCallback as useCallback9, useRef as useRef6 } from "react";
|
|
16302
16302
|
import { useKeyboard as useKeyboard5, useRenderer, useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
|
|
16303
16303
|
import { QueryClient } from "@tanstack/react-query";
|
|
16304
16304
|
|
|
@@ -16320,8 +16320,74 @@ function useEffectOnMount(effect) {
|
|
|
16320
16320
|
useEffect(effect, []);
|
|
16321
16321
|
}
|
|
16322
16322
|
|
|
16323
|
+
// ../shared/src/hooks/useReconnectingSseStream.ts
|
|
16324
|
+
import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
16325
|
+
function useReconnectingSseStream(options) {
|
|
16326
|
+
const { enabled, openStream, onEvent, onConnect, onNotOk, reconnectDelayMs = 1e3, coalesceMs } = options;
|
|
16327
|
+
const connectedRef = useRef(false);
|
|
16328
|
+
const subscribe = useCallback(
|
|
16329
|
+
(notify) => {
|
|
16330
|
+
if (!enabled) return () => {
|
|
16331
|
+
};
|
|
16332
|
+
const controller = new AbortController();
|
|
16333
|
+
let cancelled = false;
|
|
16334
|
+
let debounce = null;
|
|
16335
|
+
const setConnected = (value) => {
|
|
16336
|
+
if (connectedRef.current === value) return;
|
|
16337
|
+
connectedRef.current = value;
|
|
16338
|
+
notify();
|
|
16339
|
+
};
|
|
16340
|
+
const emit = (event) => {
|
|
16341
|
+
if (coalesceMs === void 0) {
|
|
16342
|
+
void onEvent(event);
|
|
16343
|
+
return;
|
|
16344
|
+
}
|
|
16345
|
+
if (debounce) clearTimeout(debounce);
|
|
16346
|
+
debounce = setTimeout(() => void onEvent(event), coalesceMs);
|
|
16347
|
+
};
|
|
16348
|
+
const connect = async () => {
|
|
16349
|
+
try {
|
|
16350
|
+
const response = await openStream(controller.signal);
|
|
16351
|
+
if (!response.ok || !response.body) {
|
|
16352
|
+
setConnected(false);
|
|
16353
|
+
return onNotOk?.(response) === "stop";
|
|
16354
|
+
}
|
|
16355
|
+
setConnected(true);
|
|
16356
|
+
onConnect?.();
|
|
16357
|
+
await readSseStream(response.body, emit, () => !cancelled);
|
|
16358
|
+
return false;
|
|
16359
|
+
} catch {
|
|
16360
|
+
setConnected(false);
|
|
16361
|
+
return false;
|
|
16362
|
+
}
|
|
16363
|
+
};
|
|
16364
|
+
const run = async () => {
|
|
16365
|
+
while (!cancelled) {
|
|
16366
|
+
const stop = await connect();
|
|
16367
|
+
if (cancelled || stop) break;
|
|
16368
|
+
await new Promise((resolve2) => setTimeout(resolve2, reconnectDelayMs));
|
|
16369
|
+
}
|
|
16370
|
+
};
|
|
16371
|
+
run().catch(() => setConnected(false));
|
|
16372
|
+
return () => {
|
|
16373
|
+
cancelled = true;
|
|
16374
|
+
controller.abort();
|
|
16375
|
+
if (debounce) clearTimeout(debounce);
|
|
16376
|
+
setConnected(false);
|
|
16377
|
+
};
|
|
16378
|
+
},
|
|
16379
|
+
[enabled, openStream, onEvent, onConnect, onNotOk, reconnectDelayMs, coalesceMs]
|
|
16380
|
+
);
|
|
16381
|
+
const connected = useSyncExternalStore(
|
|
16382
|
+
subscribe,
|
|
16383
|
+
() => connectedRef.current,
|
|
16384
|
+
() => false
|
|
16385
|
+
);
|
|
16386
|
+
return { connected };
|
|
16387
|
+
}
|
|
16388
|
+
|
|
16323
16389
|
// ../shared/src/hooks/fetch.ts
|
|
16324
|
-
import { useCallback } from "react";
|
|
16390
|
+
import { useCallback as useCallback2 } from "react";
|
|
16325
16391
|
var REDIRECT_STATUSES2 = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
16326
16392
|
var MAX_REDIRECTS2 = 5;
|
|
16327
16393
|
async function fetchWithRedirects2(url, init, attempt = 0) {
|
|
@@ -16347,7 +16413,7 @@ async function fetchWithRedirects2(url, init, attempt = 0) {
|
|
|
16347
16413
|
}
|
|
16348
16414
|
function useOrgFetch() {
|
|
16349
16415
|
const auth = useReplicasAuth();
|
|
16350
|
-
return
|
|
16416
|
+
return useCallback2(
|
|
16351
16417
|
async function orgFetch(url, options) {
|
|
16352
16418
|
const token = await auth.getAccessToken();
|
|
16353
16419
|
const orgId = auth.getOrganizationId();
|
|
@@ -16375,7 +16441,7 @@ function useOrgFetch() {
|
|
|
16375
16441
|
}
|
|
16376
16442
|
function useRawOrgFetch() {
|
|
16377
16443
|
const auth = useReplicasAuth();
|
|
16378
|
-
return
|
|
16444
|
+
return useCallback2(
|
|
16379
16445
|
async function rawOrgFetch(url, options) {
|
|
16380
16446
|
const token = await auth.getAccessToken();
|
|
16381
16447
|
const orgId = auth.getOrganizationId();
|
|
@@ -16392,7 +16458,7 @@ function useRawOrgFetch() {
|
|
|
16392
16458
|
}
|
|
16393
16459
|
|
|
16394
16460
|
// ../shared/src/hooks/useWorkspaces.ts
|
|
16395
|
-
import { useCallback as
|
|
16461
|
+
import { useCallback as useCallback3 } from "react";
|
|
16396
16462
|
import { useQuery, useMutation } from "@tanstack/react-query";
|
|
16397
16463
|
function useWorkspaces(viewModes, page = 1, limit = 100) {
|
|
16398
16464
|
const auth = useReplicasAuth();
|
|
@@ -16444,7 +16510,7 @@ function useWaitForWorkspaceActive() {
|
|
|
16444
16510
|
const auth = useReplicasAuth();
|
|
16445
16511
|
const orgFetch = useOrgFetch();
|
|
16446
16512
|
const orgId = auth.getOrganizationId();
|
|
16447
|
-
return
|
|
16513
|
+
return useCallback3(async (workspaceId) => {
|
|
16448
16514
|
try {
|
|
16449
16515
|
const result = await auth.queryClient.fetchQuery({
|
|
16450
16516
|
queryKey: ["workspace-wait-active", orgId, workspaceId],
|
|
@@ -16516,7 +16582,7 @@ function useGenerateWorkspaceName() {
|
|
|
16516
16582
|
}
|
|
16517
16583
|
|
|
16518
16584
|
// ../shared/src/hooks/useWorkspaceEngine.ts
|
|
16519
|
-
import { useCallback as
|
|
16585
|
+
import { useCallback as useCallback4 } from "react";
|
|
16520
16586
|
import { useQuery as useQuery2, useMutation as useMutation2 } from "@tanstack/react-query";
|
|
16521
16587
|
function upsertChat(chats, chat) {
|
|
16522
16588
|
const existingIndex = chats.findIndex((item) => item.id === chat.id);
|
|
@@ -16644,8 +16710,7 @@ function useWorkspaceEvents(workspaceId, enabled = true) {
|
|
|
16644
16710
|
const auth = useReplicasAuth();
|
|
16645
16711
|
const rawFetch = useRawOrgFetch();
|
|
16646
16712
|
const qc = auth.queryClient;
|
|
16647
|
-
const
|
|
16648
|
-
const handleEvent = useCallback3((event) => {
|
|
16713
|
+
const handleEvent = useCallback4((event) => {
|
|
16649
16714
|
if (!workspaceId) return;
|
|
16650
16715
|
const chatsKey = ["workspace-chats", workspaceId];
|
|
16651
16716
|
if (event.type === "chat.created" || event.type === "chat.updated") {
|
|
@@ -16723,43 +16788,18 @@ function useWorkspaceEvents(workspaceId, enabled = true) {
|
|
|
16723
16788
|
return;
|
|
16724
16789
|
}
|
|
16725
16790
|
}, [qc, workspaceId]);
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
return false;
|
|
16739
|
-
}
|
|
16740
|
-
setConnected(true);
|
|
16741
|
-
await readSseStream(response.body, handleEvent, () => !cancelled);
|
|
16742
|
-
return false;
|
|
16743
|
-
} catch {
|
|
16744
|
-
setConnected(false);
|
|
16745
|
-
return false;
|
|
16746
|
-
}
|
|
16747
|
-
};
|
|
16748
|
-
const run = async () => {
|
|
16749
|
-
while (!cancelled) {
|
|
16750
|
-
await connect();
|
|
16751
|
-
if (cancelled) break;
|
|
16752
|
-
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
16753
|
-
}
|
|
16754
|
-
};
|
|
16755
|
-
run().catch(() => setConnected(false));
|
|
16756
|
-
return () => {
|
|
16757
|
-
cancelled = true;
|
|
16758
|
-
controller.abort();
|
|
16759
|
-
setConnected(false);
|
|
16760
|
-
};
|
|
16761
|
-
}, [enabled, handleEvent, rawFetch, workspaceId]);
|
|
16762
|
-
return useMemo(() => ({ connected }), [connected]);
|
|
16791
|
+
const openStream = useCallback4(
|
|
16792
|
+
(signal) => rawFetch(`/v1/workspaces/${workspaceId}/events`, {
|
|
16793
|
+
headers: { Accept: "text/event-stream" },
|
|
16794
|
+
signal
|
|
16795
|
+
}),
|
|
16796
|
+
[rawFetch, workspaceId]
|
|
16797
|
+
);
|
|
16798
|
+
return useReconnectingSseStream({
|
|
16799
|
+
enabled: workspaceId != null && enabled,
|
|
16800
|
+
openStream,
|
|
16801
|
+
onEvent: handleEvent
|
|
16802
|
+
});
|
|
16763
16803
|
}
|
|
16764
16804
|
|
|
16765
16805
|
// ../shared/src/hooks/useRepositories.ts
|
|
@@ -16839,7 +16879,7 @@ function StatusBar({ focusPanel, viewingDiff, hasDiffAvailable }) {
|
|
|
16839
16879
|
}
|
|
16840
16880
|
|
|
16841
16881
|
// src/interactive/components/WorkspaceSidebar.tsx
|
|
16842
|
-
import { useState
|
|
16882
|
+
import { useState, useMemo, useCallback as useCallback5 } from "react";
|
|
16843
16883
|
import { useKeyboard, useTerminalDimensions } from "@opentui/react";
|
|
16844
16884
|
import { jsx as jsx2, jsxs as jsxs2 } from "@opentui/react/jsx-runtime";
|
|
16845
16885
|
function flattenGroups(groups, collapsedGroups) {
|
|
@@ -16885,17 +16925,17 @@ function WorkspaceSidebar({
|
|
|
16885
16925
|
loading
|
|
16886
16926
|
}) {
|
|
16887
16927
|
const { height: termHeight } = useTerminalDimensions();
|
|
16888
|
-
const [collapsedGroups, setCollapsedGroups] =
|
|
16889
|
-
const [cursorIndex, setCursorIndex] =
|
|
16890
|
-
const [scrollOffset, setScrollOffset] =
|
|
16891
|
-
const [confirmArchive, setConfirmArchive] =
|
|
16892
|
-
const items =
|
|
16928
|
+
const [collapsedGroups, setCollapsedGroups] = useState(/* @__PURE__ */ new Set());
|
|
16929
|
+
const [cursorIndex, setCursorIndex] = useState(0);
|
|
16930
|
+
const [scrollOffset, setScrollOffset] = useState(0);
|
|
16931
|
+
const [confirmArchive, setConfirmArchive] = useState(null);
|
|
16932
|
+
const items = useMemo(() => flattenGroups(groups, collapsedGroups), [groups, collapsedGroups]);
|
|
16893
16933
|
const clampedCursor = Math.min(cursorIndex, Math.max(0, items.length - 1));
|
|
16894
16934
|
if (clampedCursor !== cursorIndex) {
|
|
16895
16935
|
setCursorIndex(clampedCursor);
|
|
16896
16936
|
}
|
|
16897
16937
|
const visibleHeight = Math.max(1, termHeight - 4);
|
|
16898
|
-
const adjustScroll =
|
|
16938
|
+
const adjustScroll = useCallback5(
|
|
16899
16939
|
(newCursor) => {
|
|
16900
16940
|
let newOffset = scrollOffset;
|
|
16901
16941
|
if (newCursor < newOffset) {
|
|
@@ -16907,7 +16947,7 @@ function WorkspaceSidebar({
|
|
|
16907
16947
|
},
|
|
16908
16948
|
[scrollOffset, visibleHeight]
|
|
16909
16949
|
);
|
|
16910
|
-
const moveCursor =
|
|
16950
|
+
const moveCursor = useCallback5(
|
|
16911
16951
|
(next) => {
|
|
16912
16952
|
const len = items.length;
|
|
16913
16953
|
if (len === 0) return;
|
|
@@ -16917,7 +16957,7 @@ function WorkspaceSidebar({
|
|
|
16917
16957
|
},
|
|
16918
16958
|
[items.length, adjustScroll]
|
|
16919
16959
|
);
|
|
16920
|
-
const handleAction =
|
|
16960
|
+
const handleAction = useCallback5(
|
|
16921
16961
|
(item) => {
|
|
16922
16962
|
if (item.type === "group") {
|
|
16923
16963
|
setCollapsedGroups((prev) => {
|
|
@@ -16937,7 +16977,7 @@ function WorkspaceSidebar({
|
|
|
16937
16977
|
},
|
|
16938
16978
|
[onSelectWorkspace, onCreateWorkspace]
|
|
16939
16979
|
);
|
|
16940
|
-
const handleArchive =
|
|
16980
|
+
const handleArchive = useCallback5(() => {
|
|
16941
16981
|
const item = items[cursorIndex];
|
|
16942
16982
|
if (!item || item.type !== "workspace") return;
|
|
16943
16983
|
if (confirmArchive === item.workspaceId) {
|
|
@@ -16947,7 +16987,7 @@ function WorkspaceSidebar({
|
|
|
16947
16987
|
setConfirmArchive(item.workspaceId);
|
|
16948
16988
|
}
|
|
16949
16989
|
}, [items, cursorIndex, confirmArchive, onArchiveWorkspace]);
|
|
16950
|
-
const moveCursorAndClearConfirm =
|
|
16990
|
+
const moveCursorAndClearConfirm = useCallback5(
|
|
16951
16991
|
(next) => {
|
|
16952
16992
|
setConfirmArchive(null);
|
|
16953
16993
|
moveCursor(next);
|
|
@@ -17015,7 +17055,7 @@ function WorkspaceSidebar({
|
|
|
17015
17055
|
return;
|
|
17016
17056
|
}
|
|
17017
17057
|
});
|
|
17018
|
-
const handleItemClick =
|
|
17058
|
+
const handleItemClick = useCallback5(
|
|
17019
17059
|
(globalIndex) => {
|
|
17020
17060
|
setConfirmArchive(null);
|
|
17021
17061
|
setCursorIndex(globalIndex);
|
|
@@ -17024,7 +17064,7 @@ function WorkspaceSidebar({
|
|
|
17024
17064
|
},
|
|
17025
17065
|
[items, handleAction]
|
|
17026
17066
|
);
|
|
17027
|
-
const handleArchiveClick =
|
|
17067
|
+
const handleArchiveClick = useCallback5(
|
|
17028
17068
|
(workspaceId, e) => {
|
|
17029
17069
|
e?.preventDefault?.();
|
|
17030
17070
|
if (confirmArchive === workspaceId) {
|
|
@@ -17162,11 +17202,11 @@ function WorkspaceSidebar({
|
|
|
17162
17202
|
}
|
|
17163
17203
|
|
|
17164
17204
|
// src/interactive/components/ChatArea.tsx
|
|
17165
|
-
import { useRef as
|
|
17205
|
+
import { useRef as useRef3 } from "react";
|
|
17166
17206
|
import { useKeyboard as useKeyboard3 } from "@opentui/react";
|
|
17167
17207
|
|
|
17168
17208
|
// src/interactive/components/ChatMessage.tsx
|
|
17169
|
-
import { useState as
|
|
17209
|
+
import { useState as useState4, useMemo as useMemo3 } from "react";
|
|
17170
17210
|
|
|
17171
17211
|
// src/interactive/components/Spinner.tsx
|
|
17172
17212
|
import "opentui-spinner/react";
|
|
@@ -17181,10 +17221,10 @@ function SpinnerLabel({ color, label }) {
|
|
|
17181
17221
|
}
|
|
17182
17222
|
|
|
17183
17223
|
// src/interactive/components/StructuredUserMessage.tsx
|
|
17184
|
-
import { useState as
|
|
17224
|
+
import { useState as useState3 } from "react";
|
|
17185
17225
|
|
|
17186
17226
|
// src/interactive/components/diff-utils.tsx
|
|
17187
|
-
import React2, { useState as
|
|
17227
|
+
import React2, { useState as useState2, useMemo as useMemo2, useCallback as useCallback6, useRef as useRef2 } from "react";
|
|
17188
17228
|
import { SyntaxStyle } from "@opentui/core";
|
|
17189
17229
|
import { useKeyboard as useKeyboard2 } from "@opentui/react";
|
|
17190
17230
|
import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "@opentui/react/jsx-runtime";
|
|
@@ -17314,7 +17354,7 @@ function diffProps(filePath) {
|
|
|
17314
17354
|
};
|
|
17315
17355
|
}
|
|
17316
17356
|
function DiffView({ diff, filePath }) {
|
|
17317
|
-
const hunks =
|
|
17357
|
+
const hunks = useMemo2(() => splitDiffByHunks(diff), [diff]);
|
|
17318
17358
|
const props = diffProps(filePath);
|
|
17319
17359
|
if (hunks.length <= 1) {
|
|
17320
17360
|
return /* @__PURE__ */ jsx4("diff", { diff: ensureUnifiedHeaders(diff, filePath), ...props });
|
|
@@ -17427,16 +17467,16 @@ function buildFileTree(files) {
|
|
|
17427
17467
|
}
|
|
17428
17468
|
var FILE_PANEL_WIDTH = 32;
|
|
17429
17469
|
function DiffViewer({ diff, repoName, focused }) {
|
|
17430
|
-
const files =
|
|
17431
|
-
const tree =
|
|
17432
|
-
const [selectedFileIndex, setSelectedFileIndex] =
|
|
17433
|
-
const [collapsedFolders, setCollapsedFolders] =
|
|
17434
|
-
const [cursorIndex, setCursorIndex] =
|
|
17435
|
-
const [innerFocus, setInnerFocus] =
|
|
17470
|
+
const files = useMemo2(() => splitDiffByFile(diff), [diff]);
|
|
17471
|
+
const tree = useMemo2(() => buildFileTree(files), [files]);
|
|
17472
|
+
const [selectedFileIndex, setSelectedFileIndex] = useState2(0);
|
|
17473
|
+
const [collapsedFolders, setCollapsedFolders] = useState2(/* @__PURE__ */ new Set());
|
|
17474
|
+
const [cursorIndex, setCursorIndex] = useState2(0);
|
|
17475
|
+
const [innerFocus, setInnerFocus] = useState2("files");
|
|
17436
17476
|
const safeFileIndex = Math.min(selectedFileIndex, Math.max(0, files.length - 1));
|
|
17437
|
-
const diffScrollRef =
|
|
17438
|
-
const fileTreeScrollRef =
|
|
17439
|
-
const visibleTree =
|
|
17477
|
+
const diffScrollRef = useRef2(null);
|
|
17478
|
+
const fileTreeScrollRef = useRef2(null);
|
|
17479
|
+
const visibleTree = useMemo2(() => {
|
|
17440
17480
|
const result = [];
|
|
17441
17481
|
let hideUntilDepth = null;
|
|
17442
17482
|
for (const node of tree) {
|
|
@@ -17452,12 +17492,12 @@ function DiffViewer({ diff, repoName, focused }) {
|
|
|
17452
17492
|
return result;
|
|
17453
17493
|
}, [tree, collapsedFolders]);
|
|
17454
17494
|
const safeCursorIndex = Math.min(cursorIndex, Math.max(0, visibleTree.length - 1));
|
|
17455
|
-
const scrollCursorIntoView =
|
|
17495
|
+
const scrollCursorIntoView = useCallback6((treeIdx) => {
|
|
17456
17496
|
const node = visibleTree[treeIdx];
|
|
17457
17497
|
if (!node) return;
|
|
17458
17498
|
fileTreeScrollRef.current?.scrollChildIntoView(`tree-${node.path}`);
|
|
17459
17499
|
}, [visibleTree]);
|
|
17460
|
-
const moveCursor =
|
|
17500
|
+
const moveCursor = useCallback6((next) => {
|
|
17461
17501
|
const len = visibleTree.length;
|
|
17462
17502
|
if (len === 0) return;
|
|
17463
17503
|
const wrapped = (next % len + len) % len;
|
|
@@ -17468,7 +17508,7 @@ function DiffViewer({ diff, repoName, focused }) {
|
|
|
17468
17508
|
setSelectedFileIndex(node.fileIndex);
|
|
17469
17509
|
}
|
|
17470
17510
|
}, [visibleTree, scrollCursorIntoView]);
|
|
17471
|
-
const toggleFolder =
|
|
17511
|
+
const toggleFolder = useCallback6((folderPath) => {
|
|
17472
17512
|
setCollapsedFolders((prev) => {
|
|
17473
17513
|
const next = new Set(prev);
|
|
17474
17514
|
if (next.has(folderPath)) next.delete(folderPath);
|
|
@@ -17476,7 +17516,7 @@ function DiffViewer({ diff, repoName, focused }) {
|
|
|
17476
17516
|
return next;
|
|
17477
17517
|
});
|
|
17478
17518
|
}, []);
|
|
17479
|
-
const selectFile =
|
|
17519
|
+
const selectFile = useCallback6((fileIndex, treeIndex) => {
|
|
17480
17520
|
setSelectedFileIndex(fileIndex);
|
|
17481
17521
|
setCursorIndex(treeIndex);
|
|
17482
17522
|
scrollCursorIntoView(treeIndex);
|
|
@@ -17513,7 +17553,7 @@ function DiffViewer({ diff, repoName, focused }) {
|
|
|
17513
17553
|
}
|
|
17514
17554
|
}
|
|
17515
17555
|
});
|
|
17516
|
-
const statsColumnWidth =
|
|
17556
|
+
const statsColumnWidth = useMemo2(() => {
|
|
17517
17557
|
let max = 0;
|
|
17518
17558
|
for (const f of files) {
|
|
17519
17559
|
const a = f.added > 0 ? `+${f.added}`.length : 0;
|
|
@@ -17697,7 +17737,7 @@ function MessageBody({ children }) {
|
|
|
17697
17737
|
return /* @__PURE__ */ jsx5("text", { fg: "#ffffff", selectable: true, children });
|
|
17698
17738
|
}
|
|
17699
17739
|
function ExpandableSection({ label, children }) {
|
|
17700
|
-
const [expanded, setExpanded] =
|
|
17740
|
+
const [expanded, setExpanded] = useState3(false);
|
|
17701
17741
|
if (!children) return null;
|
|
17702
17742
|
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", children: [
|
|
17703
17743
|
/* @__PURE__ */ jsx5("box", { onMouseDown: () => setExpanded((e) => !e), children: /* @__PURE__ */ jsxs5("text", { children: [
|
|
@@ -17711,7 +17751,7 @@ function ExpandableSection({ label, children }) {
|
|
|
17711
17751
|
] });
|
|
17712
17752
|
}
|
|
17713
17753
|
function ExpandableDiffSection({ label, diffContent, filePath }) {
|
|
17714
|
-
const [expanded, setExpanded] =
|
|
17754
|
+
const [expanded, setExpanded] = useState3(false);
|
|
17715
17755
|
if (!diffContent) return null;
|
|
17716
17756
|
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", children: [
|
|
17717
17757
|
/* @__PURE__ */ jsx5("box", { onMouseDown: () => setExpanded((e) => !e), children: /* @__PURE__ */ jsxs5("text", { children: [
|
|
@@ -17954,7 +17994,7 @@ function ExpandableAction({
|
|
|
17954
17994
|
status,
|
|
17955
17995
|
children
|
|
17956
17996
|
}) {
|
|
17957
|
-
const [expanded, setExpanded] =
|
|
17997
|
+
const [expanded, setExpanded] = useState4(false);
|
|
17958
17998
|
return /* @__PURE__ */ jsxs6("box", { flexDirection: "column", children: [
|
|
17959
17999
|
/* @__PURE__ */ jsx6(
|
|
17960
18000
|
ActionLine,
|
|
@@ -17979,9 +18019,9 @@ function getChangeStyle(action) {
|
|
|
17979
18019
|
return CHANGE_STYLE[action] ?? DEFAULT_CHANGE_STYLE;
|
|
17980
18020
|
}
|
|
17981
18021
|
function PatchOperation({ op, defaultExpanded = false }) {
|
|
17982
|
-
const [expanded, setExpanded] =
|
|
18022
|
+
const [expanded, setExpanded] = useState4(defaultExpanded);
|
|
17983
18023
|
const { color, sign } = getChangeStyle(op.action);
|
|
17984
|
-
const stats =
|
|
18024
|
+
const stats = useMemo3(() => op.diff ? countDiffStats(op.diff) : null, [op.diff]);
|
|
17985
18025
|
if (!op.diff) {
|
|
17986
18026
|
return /* @__PURE__ */ jsxs6("text", { children: [
|
|
17987
18027
|
/* @__PURE__ */ jsx6("span", { fg: color, children: sign }),
|
|
@@ -18021,7 +18061,7 @@ function isStructuredPrompt(p) {
|
|
|
18021
18061
|
return p.source !== "raw";
|
|
18022
18062
|
}
|
|
18023
18063
|
function UserMessageContent({ content }) {
|
|
18024
|
-
const parsed =
|
|
18064
|
+
const parsed = useMemo3(() => parseUserMessage(content), [content]);
|
|
18025
18065
|
return /* @__PURE__ */ jsx6(
|
|
18026
18066
|
"box",
|
|
18027
18067
|
{
|
|
@@ -18158,10 +18198,10 @@ function ChatArea({
|
|
|
18158
18198
|
agentLabel,
|
|
18159
18199
|
agentConnectHelp
|
|
18160
18200
|
}) {
|
|
18161
|
-
const textareaRef =
|
|
18162
|
-
const scrollboxRef =
|
|
18163
|
-
const isAtBottomRef =
|
|
18164
|
-
const onSendMessageRef =
|
|
18201
|
+
const textareaRef = useRef3(null);
|
|
18202
|
+
const scrollboxRef = useRef3(null);
|
|
18203
|
+
const isAtBottomRef = useRef3(true);
|
|
18204
|
+
const onSendMessageRef = useRef3(onSendMessage);
|
|
18165
18205
|
onSendMessageRef.current = onSendMessage;
|
|
18166
18206
|
const inputFocused = focusPanel === "chat-input";
|
|
18167
18207
|
const tabsFocused = focusPanel === "chat-tabs";
|
|
@@ -18333,7 +18373,7 @@ function ChatArea({
|
|
|
18333
18373
|
}
|
|
18334
18374
|
|
|
18335
18375
|
// src/interactive/components/WorkspaceInfo.tsx
|
|
18336
|
-
import React6, { useState as
|
|
18376
|
+
import React6, { useState as useState5, useMemo as useMemo4, useCallback as useCallback7, useRef as useRef4 } from "react";
|
|
18337
18377
|
import open4 from "open";
|
|
18338
18378
|
import { useKeyboard as useKeyboard4 } from "@opentui/react";
|
|
18339
18379
|
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs8 } from "@opentui/react/jsx-runtime";
|
|
@@ -18521,19 +18561,19 @@ function ViewModeRow({
|
|
|
18521
18561
|
}
|
|
18522
18562
|
function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, agentAvailability, previews, onWakeWorkspace, onViewDiff, wakingWorkspaceId, viewMode, viewingDiffRepoName, onSelectChatMode, onSelectDiffMode, onCreatePr, isPlanMode }) {
|
|
18523
18563
|
const borderColor = focused ? "#3eeba3" : "#333333";
|
|
18524
|
-
const [cursorIndex, setCursorIndex] =
|
|
18525
|
-
const interactiveItems =
|
|
18564
|
+
const [cursorIndex, setCursorIndex] = useState5(0);
|
|
18565
|
+
const interactiveItems = useMemo4(() => {
|
|
18526
18566
|
if (!status || !workspaceName) return [];
|
|
18527
18567
|
return buildInteractiveItems(workspaceId, status, previews, wakingWorkspaceId);
|
|
18528
18568
|
}, [workspaceId, workspaceName, status, previews, wakingWorkspaceId]);
|
|
18529
|
-
const diffItems =
|
|
18569
|
+
const diffItems = useMemo4(
|
|
18530
18570
|
() => interactiveItems.filter((item) => item.type === "diff"),
|
|
18531
18571
|
[interactiveItems]
|
|
18532
18572
|
);
|
|
18533
18573
|
const hasAnyDiff = diffItems.length > 0;
|
|
18534
18574
|
const safeCursor = interactiveItems.length > 0 ? Math.min(cursorIndex, interactiveItems.length - 1) : 0;
|
|
18535
|
-
const scrollboxRef =
|
|
18536
|
-
const moveCursor =
|
|
18575
|
+
const scrollboxRef = useRef4(null);
|
|
18576
|
+
const moveCursor = useCallback7(
|
|
18537
18577
|
(next) => {
|
|
18538
18578
|
const len = interactiveItems.length;
|
|
18539
18579
|
if (len === 0) return;
|
|
@@ -18544,7 +18584,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
|
|
|
18544
18584
|
},
|
|
18545
18585
|
[interactiveItems]
|
|
18546
18586
|
);
|
|
18547
|
-
const handleAction =
|
|
18587
|
+
const handleAction = useCallback7(
|
|
18548
18588
|
(item) => {
|
|
18549
18589
|
if (!item) return;
|
|
18550
18590
|
switch (item.type) {
|
|
@@ -18613,7 +18653,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
|
|
|
18613
18653
|
return;
|
|
18614
18654
|
}
|
|
18615
18655
|
});
|
|
18616
|
-
const isHighlighted =
|
|
18656
|
+
const isHighlighted = useCallback7(
|
|
18617
18657
|
(item) => {
|
|
18618
18658
|
if (!focused) return false;
|
|
18619
18659
|
const idx = interactiveItems.indexOf(item);
|
|
@@ -18621,7 +18661,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
|
|
|
18621
18661
|
},
|
|
18622
18662
|
[focused, interactiveItems, safeCursor]
|
|
18623
18663
|
);
|
|
18624
|
-
const findItem =
|
|
18664
|
+
const findItem = useCallback7(
|
|
18625
18665
|
(type, key) => {
|
|
18626
18666
|
return interactiveItems.find((item) => {
|
|
18627
18667
|
if (item.type !== type) return false;
|
|
@@ -18915,7 +18955,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
|
|
|
18915
18955
|
import { useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
|
|
18916
18956
|
|
|
18917
18957
|
// src/interactive/toast-context.tsx
|
|
18918
|
-
import { createContext as createContext2, useContext as useContext2, useState as
|
|
18958
|
+
import { createContext as createContext2, useContext as useContext2, useState as useState6, useCallback as useCallback8, useRef as useRef5 } from "react";
|
|
18919
18959
|
import { jsx as jsx9 } from "@opentui/react/jsx-runtime";
|
|
18920
18960
|
var ToastContext = createContext2(null);
|
|
18921
18961
|
function useToast() {
|
|
@@ -18924,9 +18964,9 @@ function useToast() {
|
|
|
18924
18964
|
return ctx;
|
|
18925
18965
|
}
|
|
18926
18966
|
function ToastProvider({ children }) {
|
|
18927
|
-
const [current, setCurrent] =
|
|
18928
|
-
const timeoutRef =
|
|
18929
|
-
const show =
|
|
18967
|
+
const [current, setCurrent] = useState6(null);
|
|
18968
|
+
const timeoutRef = useRef5(null);
|
|
18969
|
+
const show = useCallback8((options) => {
|
|
18930
18970
|
const { message, variant = "info", duration = 3e3 } = options;
|
|
18931
18971
|
setCurrent({ message, variant });
|
|
18932
18972
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
@@ -18934,7 +18974,7 @@ function ToastProvider({ children }) {
|
|
|
18934
18974
|
setCurrent(null);
|
|
18935
18975
|
}, duration);
|
|
18936
18976
|
}, []);
|
|
18937
|
-
const error =
|
|
18977
|
+
const error = useCallback8((err) => {
|
|
18938
18978
|
const message = err instanceof Error ? err.message : "An error occurred";
|
|
18939
18979
|
show({ message, variant: "error", duration: 5e3 });
|
|
18940
18980
|
}, [show]);
|
|
@@ -19013,7 +19053,7 @@ function AppInner() {
|
|
|
19013
19053
|
const renderer = useRenderer();
|
|
19014
19054
|
const { width } = useTerminalDimensions3();
|
|
19015
19055
|
const toast = useToast();
|
|
19016
|
-
const rendererRef =
|
|
19056
|
+
const rendererRef = useRef6(renderer);
|
|
19017
19057
|
rendererRef.current = renderer;
|
|
19018
19058
|
if (!workspacePollingStarted) {
|
|
19019
19059
|
workspacePollingStarted = true;
|
|
@@ -19022,7 +19062,7 @@ function AppInner() {
|
|
|
19022
19062
|
rendererRef.current.requestRender();
|
|
19023
19063
|
}, 3e4);
|
|
19024
19064
|
}
|
|
19025
|
-
|
|
19065
|
+
useEffect2(() => {
|
|
19026
19066
|
const handler = (selection) => {
|
|
19027
19067
|
const text = selection.getSelectedText();
|
|
19028
19068
|
if (text) {
|
|
@@ -19035,15 +19075,15 @@ function AppInner() {
|
|
|
19035
19075
|
renderer.off("selection", handler);
|
|
19036
19076
|
};
|
|
19037
19077
|
}, [renderer, toast]);
|
|
19038
|
-
const [selectedWorkspaceId, setSelectedWorkspaceId] =
|
|
19039
|
-
const [selectedChatId, setSelectedChatId] =
|
|
19040
|
-
const [focusPanel, setFocusPanel] =
|
|
19041
|
-
const [taskMode, setTaskMode] =
|
|
19042
|
-
const [mockMessages, setMockMessages] =
|
|
19043
|
-
const [mockThinking, setMockThinking] =
|
|
19044
|
-
const pendingMessageRef =
|
|
19045
|
-
const [viewingDiff, setViewingDiff] =
|
|
19046
|
-
const [lastViewedDiff, setLastViewedDiff] =
|
|
19078
|
+
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState7(null);
|
|
19079
|
+
const [selectedChatId, setSelectedChatId] = useState7(null);
|
|
19080
|
+
const [focusPanel, setFocusPanel] = useState7("sidebar");
|
|
19081
|
+
const [taskMode, setTaskMode] = useState7("build");
|
|
19082
|
+
const [mockMessages, setMockMessages] = useState7([]);
|
|
19083
|
+
const [mockThinking, setMockThinking] = useState7(false);
|
|
19084
|
+
const pendingMessageRef = useRef6(/* @__PURE__ */ new Map());
|
|
19085
|
+
const [viewingDiff, setViewingDiff] = useState7(null);
|
|
19086
|
+
const [lastViewedDiff, setLastViewedDiff] = useState7(null);
|
|
19047
19087
|
const { data: workspacesData, isLoading: loadingWorkspaces } = useWorkspaces(WORKSPACE_SIDEBAR_VIEWS);
|
|
19048
19088
|
const { data: setsData } = useRepositorySets();
|
|
19049
19089
|
const { data: envsData } = useEnvironments();
|
|
@@ -19059,7 +19099,7 @@ function AppInner() {
|
|
|
19059
19099
|
);
|
|
19060
19100
|
const { data: chatsData } = useWorkspaceChats(isMockSelected ? null : selectedWorkspaceId);
|
|
19061
19101
|
const chats = isMockSelected ? MOCK_CHATS : chatsData?.chats ?? [];
|
|
19062
|
-
const resolvedChatId =
|
|
19102
|
+
const resolvedChatId = useMemo5(() => {
|
|
19063
19103
|
if (selectedChatId && chats.find((c) => c.id === selectedChatId)) {
|
|
19064
19104
|
return selectedChatId;
|
|
19065
19105
|
}
|
|
@@ -19078,13 +19118,13 @@ function AppInner() {
|
|
|
19078
19118
|
const archiveWorkspaceMutation = useArchiveWorkspace();
|
|
19079
19119
|
const wakeWorkspaceMutation = useWakeWorkspace();
|
|
19080
19120
|
const generateNameMutation = useGenerateWorkspaceName();
|
|
19081
|
-
const [wakingWorkspaceId, setWakingWorkspaceId] =
|
|
19121
|
+
const [wakingWorkspaceId, setWakingWorkspaceId] = useState7(null);
|
|
19082
19122
|
const sendMessageMutation = useSendChatMessage(selectedWorkspaceId, resolvedChatId);
|
|
19083
19123
|
const interruptMutation = useInterruptChat(selectedWorkspaceId, resolvedChatId);
|
|
19084
19124
|
const repositorySets = setsData?.repository_sets ?? [];
|
|
19085
19125
|
const environments = envsData?.environments ?? [];
|
|
19086
19126
|
const previews = previewsData?.previews ?? [];
|
|
19087
|
-
const groups =
|
|
19127
|
+
const groups = useMemo5(
|
|
19088
19128
|
() => buildGroups(workspaces, workspacesData, environments, repositorySets),
|
|
19089
19129
|
[workspaces, workspacesData, environments, repositorySets]
|
|
19090
19130
|
);
|
|
@@ -19094,7 +19134,7 @@ function AppInner() {
|
|
|
19094
19134
|
const agentAvailable = agentAvailability ? selectedAgent === "codex" ? agentAvailability.codex.available : selectedAgent === "cursor" ? agentAvailability.cursor.available : selectedAgent === "relay" ? agentAvailability.relay.available : agentAvailability.claude.available : true;
|
|
19095
19135
|
const agentLabel = getProviderDisplayName(selectedAgent, "long");
|
|
19096
19136
|
const agentConnectHelp = getAgentConnectHelp(selectedAgent);
|
|
19097
|
-
const displayMessages =
|
|
19137
|
+
const displayMessages = useMemo5(() => {
|
|
19098
19138
|
if (isMockSelected) return mockMessages;
|
|
19099
19139
|
const rawEvents = historyData?.events ?? [];
|
|
19100
19140
|
const events = rawEvents.filter(isAgentBackendEvent);
|
|
@@ -19103,7 +19143,7 @@ function AppInner() {
|
|
|
19103
19143
|
}, [isMockSelected, mockMessages, historyData, selectedChat?.provider]);
|
|
19104
19144
|
const showInfoPanel = width >= 100;
|
|
19105
19145
|
const showWorkspacePanel = width >= 60;
|
|
19106
|
-
const [prevIsMockSelected, setPrevIsMockSelected] =
|
|
19146
|
+
const [prevIsMockSelected, setPrevIsMockSelected] = useState7(isMockSelected);
|
|
19107
19147
|
if (prevIsMockSelected !== isMockSelected) {
|
|
19108
19148
|
setPrevIsMockSelected(isMockSelected);
|
|
19109
19149
|
if (prevIsMockSelected && !isMockSelected) {
|
|
@@ -19112,7 +19152,7 @@ function AppInner() {
|
|
|
19112
19152
|
setMockThinking(false);
|
|
19113
19153
|
}
|
|
19114
19154
|
}
|
|
19115
|
-
|
|
19155
|
+
useEffect2(() => {
|
|
19116
19156
|
if (!selectedWorkspaceId || isMockSelected) return;
|
|
19117
19157
|
if (!resolvedChatId || resolvedChatId.startsWith("mock-")) return;
|
|
19118
19158
|
if (statusData?.status !== "active") return;
|
|
@@ -19126,7 +19166,7 @@ function AppInner() {
|
|
|
19126
19166
|
}
|
|
19127
19167
|
sendMessageMutation.mutate({ message: pending });
|
|
19128
19168
|
}, [selectedWorkspaceId, resolvedChatId, isMockSelected, statusData?.status]);
|
|
19129
|
-
const handleSelectWorkspace =
|
|
19169
|
+
const handleSelectWorkspace = useCallback9((workspaceId) => {
|
|
19130
19170
|
setSelectedWorkspaceId(workspaceId);
|
|
19131
19171
|
setSelectedChatId(null);
|
|
19132
19172
|
setMockMessages([]);
|
|
@@ -19135,13 +19175,13 @@ function AppInner() {
|
|
|
19135
19175
|
setLastViewedDiff(null);
|
|
19136
19176
|
setFocusPanel("chat-input");
|
|
19137
19177
|
}, []);
|
|
19138
|
-
const handleFocus =
|
|
19178
|
+
const handleFocus = useCallback9((panel) => {
|
|
19139
19179
|
if (panel === "sidebar") {
|
|
19140
19180
|
queryClient.invalidateQueries({ queryKey: ["workspaces"] });
|
|
19141
19181
|
}
|
|
19142
19182
|
setFocusPanel(panel);
|
|
19143
19183
|
}, []);
|
|
19144
|
-
const handleCreateWorkspace =
|
|
19184
|
+
const handleCreateWorkspace = useCallback9(
|
|
19145
19185
|
async (group) => {
|
|
19146
19186
|
if (group.id === "__ungrouped__") {
|
|
19147
19187
|
toast.error("Cannot create a workspace in the Other / Ungrouped folder");
|
|
@@ -19159,7 +19199,7 @@ function AppInner() {
|
|
|
19159
19199
|
},
|
|
19160
19200
|
[createWorkspaceMutation, toast]
|
|
19161
19201
|
);
|
|
19162
|
-
const handleArchiveWorkspace =
|
|
19202
|
+
const handleArchiveWorkspace = useCallback9(
|
|
19163
19203
|
async (workspaceId) => {
|
|
19164
19204
|
try {
|
|
19165
19205
|
await archiveWorkspaceMutation.mutateAsync(workspaceId);
|
|
@@ -19170,7 +19210,7 @@ function AppInner() {
|
|
|
19170
19210
|
},
|
|
19171
19211
|
[archiveWorkspaceMutation]
|
|
19172
19212
|
);
|
|
19173
|
-
const handleWakeWorkspace =
|
|
19213
|
+
const handleWakeWorkspace = useCallback9(
|
|
19174
19214
|
async (workspaceId) => {
|
|
19175
19215
|
setWakingWorkspaceId(workspaceId);
|
|
19176
19216
|
try {
|
|
@@ -19184,7 +19224,7 @@ function AppInner() {
|
|
|
19184
19224
|
},
|
|
19185
19225
|
[wakeWorkspaceMutation, toast]
|
|
19186
19226
|
);
|
|
19187
|
-
const handleSelectChat =
|
|
19227
|
+
const handleSelectChat = useCallback9((chatId) => {
|
|
19188
19228
|
setSelectedChatId(chatId);
|
|
19189
19229
|
}, []);
|
|
19190
19230
|
useKeyboard5((key) => {
|
|
@@ -19242,16 +19282,16 @@ function AppInner() {
|
|
|
19242
19282
|
}
|
|
19243
19283
|
if (focusPanel === "chat-input") return;
|
|
19244
19284
|
});
|
|
19245
|
-
const handleViewDiff =
|
|
19285
|
+
const handleViewDiff = useCallback9((diff, repoName) => {
|
|
19246
19286
|
setViewingDiff({ diff, repoName });
|
|
19247
19287
|
setLastViewedDiff({ diff, repoName });
|
|
19248
19288
|
setFocusPanel("chat-history");
|
|
19249
19289
|
}, []);
|
|
19250
|
-
const handleSelectChatMode =
|
|
19290
|
+
const handleSelectChatMode = useCallback9(() => {
|
|
19251
19291
|
setViewingDiff(null);
|
|
19252
19292
|
setFocusPanel("chat-history");
|
|
19253
19293
|
}, []);
|
|
19254
|
-
const firstAvailableDiff =
|
|
19294
|
+
const firstAvailableDiff = useMemo5(() => {
|
|
19255
19295
|
if (lastViewedDiff) return lastViewedDiff;
|
|
19256
19296
|
const repos2 = statusData?.repoStatuses ?? [];
|
|
19257
19297
|
for (const repo of repos2) {
|
|
@@ -19261,14 +19301,14 @@ function AppInner() {
|
|
|
19261
19301
|
}
|
|
19262
19302
|
return null;
|
|
19263
19303
|
}, [lastViewedDiff, statusData?.repoStatuses]);
|
|
19264
|
-
const handleSelectDiffMode =
|
|
19304
|
+
const handleSelectDiffMode = useCallback9(() => {
|
|
19265
19305
|
if (firstAvailableDiff) {
|
|
19266
19306
|
setViewingDiff(firstAvailableDiff);
|
|
19267
19307
|
setLastViewedDiff(firstAvailableDiff);
|
|
19268
19308
|
setFocusPanel("chat-history");
|
|
19269
19309
|
}
|
|
19270
19310
|
}, [firstAvailableDiff]);
|
|
19271
|
-
const handleSendMessage =
|
|
19311
|
+
const handleSendMessage = useCallback9(
|
|
19272
19312
|
async (message) => {
|
|
19273
19313
|
if (!selectedWorkspaceId || !resolvedChatId) return;
|
|
19274
19314
|
if (isMockSelected) {
|