replicas-cli 0.2.52 → 0.2.54
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.
|
@@ -11,15 +11,15 @@ import {
|
|
|
11
11
|
isAgentBackendEvent,
|
|
12
12
|
parseAgentEvents,
|
|
13
13
|
parseUserMessage
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-SDULF4LX.mjs";
|
|
15
15
|
|
|
16
16
|
// src/interactive/index.tsx
|
|
17
17
|
import { createCliRenderer } from "@opentui/core";
|
|
18
18
|
import { createRoot } from "@opentui/react";
|
|
19
19
|
|
|
20
20
|
// src/interactive/App.tsx
|
|
21
|
-
import { useState as
|
|
22
|
-
import { useKeyboard as
|
|
21
|
+
import { useState as useState8, useEffect as useEffect3, useMemo as useMemo6, useCallback as useCallback7, useRef as useRef5 } from "react";
|
|
22
|
+
import { useKeyboard as useKeyboard5, useRenderer, useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
|
|
23
23
|
import { QueryClient } from "@tanstack/react-query";
|
|
24
24
|
|
|
25
25
|
// ../shared/src/hooks/auth-context.ts
|
|
@@ -114,7 +114,8 @@ function useWorkspaces(page = 1, limit = 100, scope = "organization") {
|
|
|
114
114
|
return useQuery({
|
|
115
115
|
queryKey: ["workspaces", orgId, scope, page, limit],
|
|
116
116
|
queryFn: () => orgFetch(`/v1/workspaces?scope=${scope}&page=${page}&limit=${limit}`),
|
|
117
|
-
enabled: !!orgId
|
|
117
|
+
enabled: !!orgId,
|
|
118
|
+
staleTime: 1e4
|
|
118
119
|
}, auth.queryClient);
|
|
119
120
|
}
|
|
120
121
|
function useCreateWorkspace() {
|
|
@@ -493,7 +494,18 @@ var KEYBINDS = {
|
|
|
493
494
|
"chat-input": "\u21B5 send \u21E5 plan/build",
|
|
494
495
|
info: "j/k nav \u21B5 open o dashboard w wake"
|
|
495
496
|
};
|
|
496
|
-
|
|
497
|
+
var DIFF_KEYBINDS = "j/k nav \u21E5 switch pane";
|
|
498
|
+
var MODE_HINT = "1 chat 2 diff";
|
|
499
|
+
var MODE_HINT_PANELS = /* @__PURE__ */ new Set([
|
|
500
|
+
"chat-tabs",
|
|
501
|
+
"chat-history",
|
|
502
|
+
"info"
|
|
503
|
+
]);
|
|
504
|
+
function StatusBar({ focusPanel, viewingDiff, hasDiffAvailable }) {
|
|
505
|
+
const showingDiffHints = viewingDiff && focusPanel !== "sidebar" && focusPanel !== "info";
|
|
506
|
+
const baseHints = showingDiffHints ? DIFF_KEYBINDS : KEYBINDS[focusPanel];
|
|
507
|
+
const showModeHint = hasDiffAvailable && (showingDiffHints || MODE_HINT_PANELS.has(focusPanel));
|
|
508
|
+
const hints = showModeHint ? `${baseHints} ${MODE_HINT}` : baseHints;
|
|
497
509
|
return /* @__PURE__ */ jsxs(
|
|
498
510
|
"box",
|
|
499
511
|
{
|
|
@@ -507,7 +519,7 @@ function StatusBar({ focusPanel }) {
|
|
|
507
519
|
/* @__PURE__ */ jsx("text", { children: /* @__PURE__ */ jsx("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx("strong", { children: "Replicas" }) }) }),
|
|
508
520
|
/* @__PURE__ */ jsxs("text", { children: [
|
|
509
521
|
/* @__PURE__ */ jsxs("span", { fg: "#555555", children: [
|
|
510
|
-
|
|
522
|
+
hints,
|
|
511
523
|
" "
|
|
512
524
|
] }),
|
|
513
525
|
/* @__PURE__ */ jsxs("span", { fg: "#888888", children: [
|
|
@@ -527,11 +539,11 @@ function StatusBar({ focusPanel }) {
|
|
|
527
539
|
import { useState as useState2, useMemo as useMemo2, useCallback as useCallback3 } from "react";
|
|
528
540
|
import { useKeyboard, useTerminalDimensions } from "@opentui/react";
|
|
529
541
|
import { jsx as jsx2, jsxs as jsxs2 } from "@opentui/react/jsx-runtime";
|
|
530
|
-
function flattenGroups(groups,
|
|
542
|
+
function flattenGroups(groups, collapsedGroups) {
|
|
531
543
|
const items = [];
|
|
532
544
|
for (const group of groups) {
|
|
533
545
|
if (group.id === "__ungrouped__" && group.workspaces.length === 0) continue;
|
|
534
|
-
const expanded =
|
|
546
|
+
const expanded = !collapsedGroups.has(group.id);
|
|
535
547
|
items.push({ type: "group", id: group.id, name: group.name, groupType: group.type, expanded });
|
|
536
548
|
if (expanded) {
|
|
537
549
|
for (const ws of group.workspaces) {
|
|
@@ -566,20 +578,11 @@ function WorkspaceSidebar({
|
|
|
566
578
|
loading
|
|
567
579
|
}) {
|
|
568
580
|
const { height: termHeight } = useTerminalDimensions();
|
|
569
|
-
const [
|
|
570
|
-
() => new Set(groups.map((g) => g.id))
|
|
571
|
-
);
|
|
581
|
+
const [collapsedGroups, setCollapsedGroups] = useState2(/* @__PURE__ */ new Set());
|
|
572
582
|
const [cursorIndex, setCursorIndex] = useState2(0);
|
|
573
583
|
const [scrollOffset, setScrollOffset] = useState2(0);
|
|
574
584
|
const [confirmDelete, setConfirmDelete] = useState2(null);
|
|
575
|
-
const
|
|
576
|
-
const next = new Set(expandedGroups);
|
|
577
|
-
for (const g of groups) {
|
|
578
|
-
if (!next.has(g.id)) next.add(g.id);
|
|
579
|
-
}
|
|
580
|
-
return next;
|
|
581
|
-
}, [expandedGroups, groups]);
|
|
582
|
-
const items = useMemo2(() => flattenGroups(groups, expandedWithNew), [groups, expandedWithNew]);
|
|
585
|
+
const items = useMemo2(() => flattenGroups(groups, collapsedGroups), [groups, collapsedGroups]);
|
|
583
586
|
const clampedCursor = Math.min(cursorIndex, Math.max(0, items.length - 1));
|
|
584
587
|
if (clampedCursor !== cursorIndex) {
|
|
585
588
|
setCursorIndex(clampedCursor);
|
|
@@ -610,7 +613,7 @@ function WorkspaceSidebar({
|
|
|
610
613
|
const handleAction = useCallback3(
|
|
611
614
|
(item) => {
|
|
612
615
|
if (item.type === "group") {
|
|
613
|
-
|
|
616
|
+
setCollapsedGroups((prev) => {
|
|
614
617
|
const next = new Set(prev);
|
|
615
618
|
if (next.has(item.id)) {
|
|
616
619
|
next.delete(item.id);
|
|
@@ -853,12 +856,11 @@ function WorkspaceSidebar({
|
|
|
853
856
|
}
|
|
854
857
|
|
|
855
858
|
// src/interactive/components/ChatArea.tsx
|
|
856
|
-
import { useRef, useEffect as useEffect2 } from "react";
|
|
857
|
-
import { useKeyboard as
|
|
859
|
+
import { useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
860
|
+
import { useKeyboard as useKeyboard3 } from "@opentui/react";
|
|
858
861
|
|
|
859
862
|
// src/interactive/components/ChatMessage.tsx
|
|
860
|
-
import { useState as
|
|
861
|
-
import { SyntaxStyle } from "@opentui/core";
|
|
863
|
+
import { useState as useState5, useMemo as useMemo4 } from "react";
|
|
862
864
|
|
|
863
865
|
// src/interactive/components/Spinner.tsx
|
|
864
866
|
import "opentui-spinner/react";
|
|
@@ -873,168 +875,678 @@ function SpinnerLabel({ color, label }) {
|
|
|
873
875
|
}
|
|
874
876
|
|
|
875
877
|
// src/interactive/components/StructuredUserMessage.tsx
|
|
876
|
-
import { useState as
|
|
878
|
+
import { useState as useState4 } from "react";
|
|
879
|
+
|
|
880
|
+
// src/interactive/components/diff-utils.tsx
|
|
881
|
+
import React2, { useState as useState3, useMemo as useMemo3, useCallback as useCallback4, useRef } from "react";
|
|
882
|
+
import { SyntaxStyle } from "@opentui/core";
|
|
883
|
+
import { useKeyboard as useKeyboard2 } from "@opentui/react";
|
|
877
884
|
import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "@opentui/react/jsx-runtime";
|
|
885
|
+
var sharedSyntaxStyle = null;
|
|
886
|
+
function getSyntaxStyle() {
|
|
887
|
+
if (!sharedSyntaxStyle) {
|
|
888
|
+
sharedSyntaxStyle = SyntaxStyle.fromTheme([
|
|
889
|
+
{ scope: ["markup.heading", "markup.heading.1", "markup.heading.2", "markup.heading.3"], style: { foreground: "#66bb6a", bold: true } },
|
|
890
|
+
{ scope: ["markup.bold", "markup.strong"], style: { foreground: "#ffffff", bold: true } },
|
|
891
|
+
{ scope: ["markup.italic", "markup.emphasis"], style: { foreground: "#e0e0e0", italic: true } },
|
|
892
|
+
{ scope: ["markup.link"], style: { foreground: "#7dcfff", underline: true } },
|
|
893
|
+
{ scope: ["markup.link.url"], style: { foreground: "#7dcfff", underline: true } },
|
|
894
|
+
{ scope: ["markup.link.text"], style: { foreground: "#66bb6a", underline: true } },
|
|
895
|
+
{ scope: ["markup.link.label"], style: { foreground: "#66bb6a", underline: true } },
|
|
896
|
+
{ scope: ["markup.list"], style: { foreground: "#66bb6a" } },
|
|
897
|
+
{ scope: ["markup.quote"], style: { foreground: "#888888", italic: true } },
|
|
898
|
+
{ scope: ["markup.raw", "markup.raw.block"], style: { foreground: "#bb9af7" } },
|
|
899
|
+
{ scope: ["markup.raw.inline"], style: { foreground: "#bb9af7", background: "#1a1a2e" } },
|
|
900
|
+
{ scope: ["keyword", "keyword.control", "keyword.operator"], style: { foreground: "#bb9af7" } },
|
|
901
|
+
{ scope: ["string", "string.quoted"], style: { foreground: "#9ece6a" } },
|
|
902
|
+
{ scope: ["comment", "comment.line", "comment.block"], style: { foreground: "#555555", italic: true } },
|
|
903
|
+
{ scope: ["constant", "constant.numeric", "constant.language"], style: { foreground: "#ff9e64" } },
|
|
904
|
+
{ scope: ["entity.name.function", "support.function"], style: { foreground: "#7aa2f7" } },
|
|
905
|
+
{ scope: ["entity.name.type", "support.type"], style: { foreground: "#2ac3de" } },
|
|
906
|
+
{ scope: ["variable", "variable.other"], style: { foreground: "#c0caf5" } },
|
|
907
|
+
{ scope: ["punctuation"], style: { foreground: "#888888" } }
|
|
908
|
+
]);
|
|
909
|
+
}
|
|
910
|
+
return sharedSyntaxStyle;
|
|
911
|
+
}
|
|
912
|
+
function truncateName(text, maxLen) {
|
|
913
|
+
if (maxLen <= 0) return "";
|
|
914
|
+
if (text.length <= maxLen) return text;
|
|
915
|
+
if (maxLen === 1) return "\u2026";
|
|
916
|
+
return text.slice(0, maxLen - 1) + "\u2026";
|
|
917
|
+
}
|
|
918
|
+
function countDiffStats(diff) {
|
|
919
|
+
let added = 0;
|
|
920
|
+
let removed = 0;
|
|
921
|
+
for (const line of diff.split("\n")) {
|
|
922
|
+
if (line.startsWith("+") && !line.startsWith("+++")) added++;
|
|
923
|
+
else if (line.startsWith("-") && !line.startsWith("---")) removed++;
|
|
924
|
+
}
|
|
925
|
+
return { added, removed };
|
|
926
|
+
}
|
|
927
|
+
var EXT_TO_FILETYPE = {
|
|
928
|
+
ts: "typescript",
|
|
929
|
+
tsx: "typescriptreact",
|
|
930
|
+
js: "javascript",
|
|
931
|
+
jsx: "javascriptreact",
|
|
932
|
+
cts: "typescript",
|
|
933
|
+
mts: "typescript",
|
|
934
|
+
cjs: "javascript",
|
|
935
|
+
mjs: "javascript",
|
|
936
|
+
py: "python",
|
|
937
|
+
rs: "rust",
|
|
938
|
+
go: "go",
|
|
939
|
+
rb: "ruby",
|
|
940
|
+
java: "java",
|
|
941
|
+
kt: "kotlin",
|
|
942
|
+
swift: "swift",
|
|
943
|
+
c: "c",
|
|
944
|
+
cpp: "cpp",
|
|
945
|
+
h: "c",
|
|
946
|
+
hpp: "cpp",
|
|
947
|
+
cs: "csharp",
|
|
948
|
+
css: "css",
|
|
949
|
+
scss: "scss",
|
|
950
|
+
html: "html",
|
|
951
|
+
json: "json",
|
|
952
|
+
yaml: "yaml",
|
|
953
|
+
yml: "yaml",
|
|
954
|
+
toml: "toml",
|
|
955
|
+
md: "markdown",
|
|
956
|
+
sh: "bash",
|
|
957
|
+
bash: "bash",
|
|
958
|
+
zsh: "bash",
|
|
959
|
+
sql: "sql"
|
|
960
|
+
};
|
|
961
|
+
function extFromPath(path) {
|
|
962
|
+
const ext = path.split(".").pop()?.toLowerCase();
|
|
963
|
+
return ext ? EXT_TO_FILETYPE[ext] : void 0;
|
|
964
|
+
}
|
|
965
|
+
function ensureUnifiedHeaders(diff, filePath) {
|
|
966
|
+
if (/^--- /m.test(diff) && /^@@ /m.test(diff)) return diff;
|
|
967
|
+
const file = filePath ?? "a";
|
|
968
|
+
const fileHeaders = `--- a/${file}
|
|
969
|
+
+++ b/${file}
|
|
970
|
+
`;
|
|
971
|
+
if (/^@@ -\d+/m.test(diff)) {
|
|
972
|
+
return fileHeaders + diff;
|
|
973
|
+
}
|
|
974
|
+
const lines = diff.split("\n");
|
|
975
|
+
const diffLines = lines.filter((l) => !l.startsWith("@@"));
|
|
976
|
+
let oldCount = 0;
|
|
977
|
+
let newCount = 0;
|
|
978
|
+
for (const line of diffLines) {
|
|
979
|
+
if (line.startsWith("+") && !line.startsWith("+++")) newCount++;
|
|
980
|
+
else if (line.startsWith("-") && !line.startsWith("---")) oldCount++;
|
|
981
|
+
else if (line.startsWith(" ") || !line.startsWith("+") && !line.startsWith("-") && line.length > 0) {
|
|
982
|
+
oldCount++;
|
|
983
|
+
newCount++;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
const hunk = `@@ -1,${oldCount} +1,${newCount} @@`;
|
|
987
|
+
return `${fileHeaders}${hunk}
|
|
988
|
+
${diffLines.join("\n")}`;
|
|
989
|
+
}
|
|
990
|
+
function diffProps(filePath) {
|
|
991
|
+
return {
|
|
992
|
+
view: "split",
|
|
993
|
+
filetype: filePath ? extFromPath(filePath) : void 0,
|
|
994
|
+
syntaxStyle: getSyntaxStyle(),
|
|
995
|
+
showLineNumbers: true,
|
|
996
|
+
width: "100%",
|
|
997
|
+
wrapMode: "word",
|
|
998
|
+
fg: "#cccccc",
|
|
999
|
+
addedBg: "#0d2b0d",
|
|
1000
|
+
removedBg: "#2b0d0d",
|
|
1001
|
+
contextBg: "#0a0a0a",
|
|
1002
|
+
addedSignColor: "#66bb6a",
|
|
1003
|
+
removedSignColor: "#ff4444",
|
|
1004
|
+
lineNumberFg: "#555555",
|
|
1005
|
+
lineNumberBg: "#0a0a0a",
|
|
1006
|
+
addedLineNumberBg: "#0d2b0d",
|
|
1007
|
+
removedLineNumberBg: "#2b0d0d"
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
function DiffView({ diff, filePath }) {
|
|
1011
|
+
const hunks = useMemo3(() => splitDiffByHunks(diff), [diff]);
|
|
1012
|
+
const props = diffProps(filePath);
|
|
1013
|
+
if (hunks.length <= 1) {
|
|
1014
|
+
return /* @__PURE__ */ jsx4("diff", { diff: ensureUnifiedHeaders(diff, filePath), ...props });
|
|
1015
|
+
}
|
|
1016
|
+
return /* @__PURE__ */ jsx4("box", { flexDirection: "column", children: hunks.map((hunk, i) => {
|
|
1017
|
+
const prev = i > 0 ? hunks[i - 1] : null;
|
|
1018
|
+
const gap = prev ? hunk.newStart - (prev.newStart + prev.newCount) : 0;
|
|
1019
|
+
return /* @__PURE__ */ jsxs4(React2.Fragment, { children: [
|
|
1020
|
+
prev && gap > 0 && /* @__PURE__ */ jsx4("box", { backgroundColor: "#151515", paddingX: 1, height: 1, children: /* @__PURE__ */ jsx4("text", { children: /* @__PURE__ */ jsxs4("span", { fg: "#666666", children: [
|
|
1021
|
+
gap,
|
|
1022
|
+
" unmodified ",
|
|
1023
|
+
gap === 1 ? "line" : "lines"
|
|
1024
|
+
] }) }) }),
|
|
1025
|
+
/* @__PURE__ */ jsx4("diff", { diff: ensureUnifiedHeaders(hunk.body, filePath), ...props })
|
|
1026
|
+
] }, i);
|
|
1027
|
+
}) });
|
|
1028
|
+
}
|
|
1029
|
+
function splitDiffByFile(fullDiff) {
|
|
1030
|
+
const chunks = [];
|
|
1031
|
+
const lines = fullDiff.split("\n");
|
|
1032
|
+
let currentLines = [];
|
|
1033
|
+
let currentPath = "";
|
|
1034
|
+
for (const line of lines) {
|
|
1035
|
+
if (line.startsWith("diff --git ")) {
|
|
1036
|
+
if (currentPath && currentLines.length > 0) {
|
|
1037
|
+
const diff = currentLines.join("\n");
|
|
1038
|
+
chunks.push({ path: currentPath, diff, ...countDiffStats(diff) });
|
|
1039
|
+
}
|
|
1040
|
+
const match = line.match(/^diff --git a\/(.+) b\/(.+)$/);
|
|
1041
|
+
currentPath = match ? match[2] : "";
|
|
1042
|
+
currentLines = [line];
|
|
1043
|
+
} else {
|
|
1044
|
+
currentLines.push(line);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
if (currentPath && currentLines.length > 0) {
|
|
1048
|
+
const diff = currentLines.join("\n");
|
|
1049
|
+
chunks.push({ path: currentPath, diff, ...countDiffStats(diff) });
|
|
1050
|
+
}
|
|
1051
|
+
return chunks;
|
|
1052
|
+
}
|
|
1053
|
+
function splitDiffByHunks(fileDiff) {
|
|
1054
|
+
const hunks = [];
|
|
1055
|
+
const lines = fileDiff.split("\n");
|
|
1056
|
+
let current = null;
|
|
1057
|
+
for (const line of lines) {
|
|
1058
|
+
const match = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/);
|
|
1059
|
+
if (match) {
|
|
1060
|
+
if (current) hunks.push({ body: current.lines.join("\n"), newStart: current.newStart, newCount: current.newCount });
|
|
1061
|
+
current = {
|
|
1062
|
+
lines: [line],
|
|
1063
|
+
newStart: parseInt(match[1], 10),
|
|
1064
|
+
newCount: match[2] ? parseInt(match[2], 10) : 1
|
|
1065
|
+
};
|
|
1066
|
+
} else if (current) {
|
|
1067
|
+
current.lines.push(line);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
if (current) hunks.push({ body: current.lines.join("\n"), newStart: current.newStart, newCount: current.newCount });
|
|
1071
|
+
return hunks;
|
|
1072
|
+
}
|
|
1073
|
+
function buildFileTree(files) {
|
|
1074
|
+
const root = { name: "", children: /* @__PURE__ */ new Map() };
|
|
1075
|
+
files.forEach((file, idx) => {
|
|
1076
|
+
const segments = file.path.split("/");
|
|
1077
|
+
let node = root;
|
|
1078
|
+
for (const seg of segments) {
|
|
1079
|
+
if (!node.children.has(seg)) {
|
|
1080
|
+
node.children.set(seg, { name: seg, children: /* @__PURE__ */ new Map() });
|
|
1081
|
+
}
|
|
1082
|
+
node = node.children.get(seg);
|
|
1083
|
+
}
|
|
1084
|
+
node.fileIndex = idx;
|
|
1085
|
+
node.added = file.added;
|
|
1086
|
+
node.removed = file.removed;
|
|
1087
|
+
});
|
|
1088
|
+
const result = [];
|
|
1089
|
+
function walk(node, depth, accumulatedPath, parentPath) {
|
|
1090
|
+
if (node.fileIndex !== void 0) {
|
|
1091
|
+
const fullPath = parentPath ? `${parentPath}/${node.name}` : node.name;
|
|
1092
|
+
result.push({
|
|
1093
|
+
type: "file",
|
|
1094
|
+
name: node.name,
|
|
1095
|
+
path: fullPath,
|
|
1096
|
+
depth,
|
|
1097
|
+
fileIndex: node.fileIndex,
|
|
1098
|
+
added: node.added,
|
|
1099
|
+
removed: node.removed
|
|
1100
|
+
});
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
const children = Array.from(node.children.values());
|
|
1104
|
+
if (children.length === 1 && children[0].fileIndex === void 0) {
|
|
1105
|
+
walk(children[0], depth, [...accumulatedPath, node.name], parentPath);
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
let folderFullPath = parentPath;
|
|
1109
|
+
if (node.name !== "") {
|
|
1110
|
+
const displayName = [...accumulatedPath, node.name].filter(Boolean).join("/");
|
|
1111
|
+
folderFullPath = parentPath ? `${parentPath}/${displayName}` : displayName;
|
|
1112
|
+
result.push({ type: "folder", name: displayName, path: folderFullPath, depth });
|
|
1113
|
+
}
|
|
1114
|
+
const childDepth = node.name === "" ? depth : depth + 1;
|
|
1115
|
+
for (const child of children) {
|
|
1116
|
+
walk(child, childDepth, [], folderFullPath);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
walk(root, 0, [], "");
|
|
1120
|
+
return result;
|
|
1121
|
+
}
|
|
1122
|
+
var FILE_PANEL_WIDTH = 32;
|
|
1123
|
+
function DiffViewer({ diff, repoName, focused }) {
|
|
1124
|
+
const files = useMemo3(() => splitDiffByFile(diff), [diff]);
|
|
1125
|
+
const tree = useMemo3(() => buildFileTree(files), [files]);
|
|
1126
|
+
const [selectedFileIndex, setSelectedFileIndex] = useState3(0);
|
|
1127
|
+
const [collapsedFolders, setCollapsedFolders] = useState3(/* @__PURE__ */ new Set());
|
|
1128
|
+
const [cursorIndex, setCursorIndex] = useState3(0);
|
|
1129
|
+
const [innerFocus, setInnerFocus] = useState3("files");
|
|
1130
|
+
const safeFileIndex = Math.min(selectedFileIndex, Math.max(0, files.length - 1));
|
|
1131
|
+
const diffScrollRef = useRef(null);
|
|
1132
|
+
const fileTreeScrollRef = useRef(null);
|
|
1133
|
+
const visibleTree = useMemo3(() => {
|
|
1134
|
+
const result = [];
|
|
1135
|
+
let hideUntilDepth = null;
|
|
1136
|
+
for (const node of tree) {
|
|
1137
|
+
if (hideUntilDepth !== null && node.depth <= hideUntilDepth) {
|
|
1138
|
+
hideUntilDepth = null;
|
|
1139
|
+
}
|
|
1140
|
+
if (hideUntilDepth !== null) continue;
|
|
1141
|
+
result.push(node);
|
|
1142
|
+
if (node.type === "folder" && collapsedFolders.has(node.path)) {
|
|
1143
|
+
hideUntilDepth = node.depth;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
return result;
|
|
1147
|
+
}, [tree, collapsedFolders]);
|
|
1148
|
+
const safeCursorIndex = Math.min(cursorIndex, Math.max(0, visibleTree.length - 1));
|
|
1149
|
+
const scrollCursorIntoView = useCallback4((treeIdx) => {
|
|
1150
|
+
const node = visibleTree[treeIdx];
|
|
1151
|
+
if (!node) return;
|
|
1152
|
+
fileTreeScrollRef.current?.scrollChildIntoView(`tree-${node.path}`);
|
|
1153
|
+
}, [visibleTree]);
|
|
1154
|
+
const moveCursor = useCallback4((next) => {
|
|
1155
|
+
const len = visibleTree.length;
|
|
1156
|
+
if (len === 0) return;
|
|
1157
|
+
const wrapped = (next % len + len) % len;
|
|
1158
|
+
setCursorIndex(wrapped);
|
|
1159
|
+
scrollCursorIntoView(wrapped);
|
|
1160
|
+
const node = visibleTree[wrapped];
|
|
1161
|
+
if (node?.type === "file" && node.fileIndex !== void 0) {
|
|
1162
|
+
setSelectedFileIndex(node.fileIndex);
|
|
1163
|
+
}
|
|
1164
|
+
}, [visibleTree, scrollCursorIntoView]);
|
|
1165
|
+
const toggleFolder = useCallback4((folderPath) => {
|
|
1166
|
+
setCollapsedFolders((prev) => {
|
|
1167
|
+
const next = new Set(prev);
|
|
1168
|
+
if (next.has(folderPath)) next.delete(folderPath);
|
|
1169
|
+
else next.add(folderPath);
|
|
1170
|
+
return next;
|
|
1171
|
+
});
|
|
1172
|
+
}, []);
|
|
1173
|
+
const selectFile = useCallback4((fileIndex, treeIndex) => {
|
|
1174
|
+
setSelectedFileIndex(fileIndex);
|
|
1175
|
+
setCursorIndex(treeIndex);
|
|
1176
|
+
scrollCursorIntoView(treeIndex);
|
|
1177
|
+
}, [scrollCursorIntoView]);
|
|
1178
|
+
useKeyboard2((key) => {
|
|
1179
|
+
if (!focused) return;
|
|
1180
|
+
if (key.name === "tab" && !key.shift) {
|
|
1181
|
+
setInnerFocus((f) => f === "files" ? "diff" : "files");
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
if (innerFocus === "files") {
|
|
1185
|
+
if (visibleTree.length > 1 && (key.name === "up" || key.name === "k" && !key.ctrl)) {
|
|
1186
|
+
moveCursor(safeCursorIndex - 1);
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
if (visibleTree.length > 1 && (key.name === "down" || key.name === "j" && !key.ctrl)) {
|
|
1190
|
+
moveCursor(safeCursorIndex + 1);
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
if (key.name === "return" || key.name === "enter") {
|
|
1194
|
+
const node = visibleTree[safeCursorIndex];
|
|
1195
|
+
if (node?.type === "folder") toggleFolder(node.path);
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
if (innerFocus === "diff") {
|
|
1201
|
+
const sb = diffScrollRef.current;
|
|
1202
|
+
if (!sb) return;
|
|
1203
|
+
if (key.ctrl && key.name === "d") {
|
|
1204
|
+
sb.scrollBy((sb.viewport?.height ?? 20) / 2);
|
|
1205
|
+
} else if (key.ctrl && key.name === "u") {
|
|
1206
|
+
sb.scrollBy(-((sb.viewport?.height ?? 20) / 2));
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
const statsColumnWidth = useMemo3(() => {
|
|
1211
|
+
let max = 0;
|
|
1212
|
+
for (const f of files) {
|
|
1213
|
+
const a = f.added > 0 ? `+${f.added}`.length : 0;
|
|
1214
|
+
const r = f.removed > 0 ? `-${f.removed}`.length : 0;
|
|
1215
|
+
const len = a + r + (a > 0 && r > 0 ? 1 : 0);
|
|
1216
|
+
if (len > max) max = len;
|
|
1217
|
+
}
|
|
1218
|
+
return max;
|
|
1219
|
+
}, [files]);
|
|
1220
|
+
if (files.length === 0) {
|
|
1221
|
+
return /* @__PURE__ */ jsxs4("box", { flexGrow: 1, flexDirection: "column", children: [
|
|
1222
|
+
/* @__PURE__ */ jsxs4("box", { paddingX: 1, marginBottom: 1, flexDirection: "row", justifyContent: "space-between", flexShrink: 0, height: 1, children: [
|
|
1223
|
+
/* @__PURE__ */ jsxs4("text", { children: [
|
|
1224
|
+
/* @__PURE__ */ jsx4("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx4("strong", { children: "Diff" }) }),
|
|
1225
|
+
/* @__PURE__ */ jsxs4("span", { fg: "#555555", children: [
|
|
1226
|
+
" ",
|
|
1227
|
+
"\u2502",
|
|
1228
|
+
" "
|
|
1229
|
+
] }),
|
|
1230
|
+
/* @__PURE__ */ jsx4("span", { fg: "#cccccc", children: repoName })
|
|
1231
|
+
] }),
|
|
1232
|
+
/* @__PURE__ */ jsx4("text", { fg: "#555555", children: "1 file" })
|
|
1233
|
+
] }),
|
|
1234
|
+
/* @__PURE__ */ jsx4("scrollbox", { flexGrow: 1, focused, children: /* @__PURE__ */ jsx4("box", { paddingX: 1, children: /* @__PURE__ */ jsx4(DiffView, { diff }) }) })
|
|
1235
|
+
] });
|
|
1236
|
+
}
|
|
1237
|
+
const selected = files[safeFileIndex];
|
|
1238
|
+
const totalAdded = files.reduce((s, f) => s + f.added, 0);
|
|
1239
|
+
const totalRemoved = files.reduce((s, f) => s + f.removed, 0);
|
|
1240
|
+
const filesPaneActive = focused === true && innerFocus === "files";
|
|
1241
|
+
const diffPaneActive = focused === true && innerFocus === "diff";
|
|
1242
|
+
return /* @__PURE__ */ jsxs4("box", { flexGrow: 1, flexDirection: "row", children: [
|
|
1243
|
+
/* @__PURE__ */ jsxs4(
|
|
1244
|
+
"box",
|
|
1245
|
+
{
|
|
1246
|
+
width: FILE_PANEL_WIDTH,
|
|
1247
|
+
flexDirection: "column",
|
|
1248
|
+
backgroundColor: "#0a0a0a",
|
|
1249
|
+
flexShrink: 0,
|
|
1250
|
+
children: [
|
|
1251
|
+
/* @__PURE__ */ jsx4("box", { paddingX: 1, flexShrink: 0, height: 1, children: /* @__PURE__ */ jsxs4("text", { children: [
|
|
1252
|
+
/* @__PURE__ */ jsx4("span", { fg: filesPaneActive ? "#66bb6a" : "#333333", children: filesPaneActive ? "\u25B8 " : " " }),
|
|
1253
|
+
/* @__PURE__ */ jsx4("span", { fg: filesPaneActive ? "#66bb6a" : "#888888", children: filesPaneActive ? /* @__PURE__ */ jsxs4("strong", { children: [
|
|
1254
|
+
files.length,
|
|
1255
|
+
" ",
|
|
1256
|
+
files.length === 1 ? "file" : "files",
|
|
1257
|
+
" changed"
|
|
1258
|
+
] }) : `${files.length} ${files.length === 1 ? "file" : "files"} changed` })
|
|
1259
|
+
] }) }),
|
|
1260
|
+
/* @__PURE__ */ jsx4("scrollbox", { ref: fileTreeScrollRef, flexGrow: 1, focused: false, children: visibleTree.map((node, i) => {
|
|
1261
|
+
const indent = " ".repeat(node.depth);
|
|
1262
|
+
const usable = FILE_PANEL_WIDTH - 2;
|
|
1263
|
+
const isCursor = filesPaneActive && i === safeCursorIndex;
|
|
1264
|
+
if (node.type === "folder") {
|
|
1265
|
+
const isCollapsed = collapsedFolders.has(node.path);
|
|
1266
|
+
const chevron = isCollapsed ? "\u25B8" : "\u25BE";
|
|
1267
|
+
const overhead2 = indent.length + 2;
|
|
1268
|
+
const nameMax2 = Math.max(1, usable - overhead2);
|
|
1269
|
+
const displayName2 = truncateName(node.name, nameMax2);
|
|
1270
|
+
return /* @__PURE__ */ jsx4(
|
|
1271
|
+
"box",
|
|
1272
|
+
{
|
|
1273
|
+
id: `tree-${node.path}`,
|
|
1274
|
+
paddingX: 1,
|
|
1275
|
+
height: 1,
|
|
1276
|
+
backgroundColor: isCursor ? "#1a1a1a" : void 0,
|
|
1277
|
+
onMouseDown: () => {
|
|
1278
|
+
setCursorIndex(i);
|
|
1279
|
+
toggleFolder(node.path);
|
|
1280
|
+
},
|
|
1281
|
+
children: /* @__PURE__ */ jsxs4("text", { children: [
|
|
1282
|
+
/* @__PURE__ */ jsx4("span", { fg: "#555555", children: indent }),
|
|
1283
|
+
/* @__PURE__ */ jsxs4("span", { fg: isCursor ? "#cccccc" : "#888888", children: [
|
|
1284
|
+
chevron,
|
|
1285
|
+
" ",
|
|
1286
|
+
displayName2
|
|
1287
|
+
] })
|
|
1288
|
+
] })
|
|
1289
|
+
},
|
|
1290
|
+
`folder-${node.path}`
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
const isSelectedFile = node.fileIndex === safeFileIndex;
|
|
1294
|
+
const added = node.added ?? 0;
|
|
1295
|
+
const removed = node.removed ?? 0;
|
|
1296
|
+
const addedPart = added > 0 ? `+${added}` : "";
|
|
1297
|
+
const removedPart = removed > 0 ? `-${removed}` : "";
|
|
1298
|
+
const bubbleColor = added > 0 && removed > 0 ? "#ffaa00" : removed > 0 ? "#ff4444" : "#66bb6a";
|
|
1299
|
+
const overhead = indent.length + 2 + statsColumnWidth + 1;
|
|
1300
|
+
const nameMax = Math.max(1, usable - overhead);
|
|
1301
|
+
const displayName = truncateName(node.name, nameMax);
|
|
1302
|
+
const bg = isCursor ? "#0d2b0d" : isSelectedFile ? "#0a1a0a" : void 0;
|
|
1303
|
+
return /* @__PURE__ */ jsxs4(
|
|
1304
|
+
"box",
|
|
1305
|
+
{
|
|
1306
|
+
id: `tree-${node.path}`,
|
|
1307
|
+
paddingX: 1,
|
|
1308
|
+
height: 1,
|
|
1309
|
+
backgroundColor: bg,
|
|
1310
|
+
onMouseDown: () => selectFile(node.fileIndex, i),
|
|
1311
|
+
flexDirection: "row",
|
|
1312
|
+
justifyContent: "space-between",
|
|
1313
|
+
children: [
|
|
1314
|
+
/* @__PURE__ */ jsxs4("text", { children: [
|
|
1315
|
+
/* @__PURE__ */ jsx4("span", { fg: "#555555", children: indent }),
|
|
1316
|
+
/* @__PURE__ */ jsxs4("span", { fg: bubbleColor, children: [
|
|
1317
|
+
"\u25CF",
|
|
1318
|
+
" "
|
|
1319
|
+
] }),
|
|
1320
|
+
/* @__PURE__ */ jsx4("span", { fg: isSelectedFile || isCursor ? "#66bb6a" : "#cccccc", children: displayName })
|
|
1321
|
+
] }),
|
|
1322
|
+
/* @__PURE__ */ jsx4("box", { width: statsColumnWidth, flexShrink: 0, justifyContent: "flex-end", flexDirection: "row", children: /* @__PURE__ */ jsxs4("text", { children: [
|
|
1323
|
+
addedPart && /* @__PURE__ */ jsx4("span", { fg: "#66bb6a", children: addedPart }),
|
|
1324
|
+
addedPart && removedPart && /* @__PURE__ */ jsx4("span", { fg: "#444444", children: " " }),
|
|
1325
|
+
removedPart && /* @__PURE__ */ jsx4("span", { fg: "#ff4444", children: removedPart })
|
|
1326
|
+
] }) })
|
|
1327
|
+
]
|
|
1328
|
+
},
|
|
1329
|
+
`file-${node.path}`
|
|
1330
|
+
);
|
|
1331
|
+
}) })
|
|
1332
|
+
]
|
|
1333
|
+
}
|
|
1334
|
+
),
|
|
1335
|
+
/* @__PURE__ */ jsxs4("box", { flexGrow: 1, flexDirection: "column", children: [
|
|
1336
|
+
/* @__PURE__ */ jsxs4("box", { paddingX: 1, flexDirection: "column", flexShrink: 0, children: [
|
|
1337
|
+
/* @__PURE__ */ jsxs4("box", { flexDirection: "row", justifyContent: "space-between", height: 1, children: [
|
|
1338
|
+
/* @__PURE__ */ jsxs4("text", { children: [
|
|
1339
|
+
/* @__PURE__ */ jsx4("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx4("strong", { children: repoName }) }),
|
|
1340
|
+
totalAdded > 0 && /* @__PURE__ */ jsxs4("span", { fg: "#66bb6a", children: [
|
|
1341
|
+
" +",
|
|
1342
|
+
totalAdded
|
|
1343
|
+
] }),
|
|
1344
|
+
totalAdded > 0 && totalRemoved > 0 && /* @__PURE__ */ jsx4("span", { fg: "#444444", children: " " }),
|
|
1345
|
+
totalRemoved > 0 && /* @__PURE__ */ jsxs4("span", { fg: "#ff4444", children: [
|
|
1346
|
+
"-",
|
|
1347
|
+
totalRemoved
|
|
1348
|
+
] })
|
|
1349
|
+
] }),
|
|
1350
|
+
/* @__PURE__ */ jsxs4("text", { fg: "#555555", children: [
|
|
1351
|
+
safeFileIndex + 1,
|
|
1352
|
+
"/",
|
|
1353
|
+
files.length
|
|
1354
|
+
] })
|
|
1355
|
+
] }),
|
|
1356
|
+
/* @__PURE__ */ jsx4("box", { flexDirection: "row", height: 1, backgroundColor: "#0d0d0d", paddingX: 1, children: /* @__PURE__ */ jsxs4("text", { children: [
|
|
1357
|
+
/* @__PURE__ */ jsx4("span", { fg: diffPaneActive ? "#66bb6a" : "#444444", children: diffPaneActive ? "\u25B8 " : " " }),
|
|
1358
|
+
(() => {
|
|
1359
|
+
const lastSlash = selected.path.lastIndexOf("/");
|
|
1360
|
+
const dir = lastSlash >= 0 ? selected.path.slice(0, lastSlash + 1) : "";
|
|
1361
|
+
const base = lastSlash >= 0 ? selected.path.slice(lastSlash + 1) : selected.path;
|
|
1362
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1363
|
+
dir && /* @__PURE__ */ jsx4("span", { fg: "#666666", children: dir }),
|
|
1364
|
+
/* @__PURE__ */ jsx4("span", { fg: diffPaneActive ? "#66bb6a" : "#ffffff", children: /* @__PURE__ */ jsx4("strong", { children: base }) })
|
|
1365
|
+
] });
|
|
1366
|
+
})()
|
|
1367
|
+
] }) })
|
|
1368
|
+
] }),
|
|
1369
|
+
/* @__PURE__ */ jsx4("scrollbox", { ref: diffScrollRef, flexGrow: 1, focused: focused && innerFocus === "diff", children: /* @__PURE__ */ jsx4("box", { paddingX: 1, children: /* @__PURE__ */ jsx4(DiffView, { diff: selected.diff, filePath: selected.path }) }) })
|
|
1370
|
+
] })
|
|
1371
|
+
] });
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// src/interactive/components/StructuredUserMessage.tsx
|
|
1375
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "@opentui/react/jsx-runtime";
|
|
878
1376
|
function SourceBadge({ source }) {
|
|
879
1377
|
const config = SOURCE_CONFIG[source];
|
|
880
|
-
return /* @__PURE__ */
|
|
1378
|
+
return /* @__PURE__ */ jsx5("text", { children: /* @__PURE__ */ jsx5("span", { fg: "#000000", bg: config.color, children: ` ${config.label} ` }) });
|
|
881
1379
|
}
|
|
882
1380
|
function MetadataPill({ label, value }) {
|
|
883
|
-
return /* @__PURE__ */
|
|
884
|
-
/* @__PURE__ */
|
|
1381
|
+
return /* @__PURE__ */ jsx5("text", { children: label ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1382
|
+
/* @__PURE__ */ jsxs5("span", { fg: "#888888", children: [
|
|
885
1383
|
label,
|
|
886
1384
|
": "
|
|
887
1385
|
] }),
|
|
888
|
-
/* @__PURE__ */
|
|
889
|
-
] }) : /* @__PURE__ */
|
|
1386
|
+
/* @__PURE__ */ jsx5("span", { fg: "#cccccc", children: value })
|
|
1387
|
+
] }) : /* @__PURE__ */ jsx5("span", { fg: "#cccccc", children: value }) });
|
|
890
1388
|
}
|
|
891
1389
|
function MessageBody({ children }) {
|
|
892
1390
|
if (!children) return null;
|
|
893
|
-
return /* @__PURE__ */
|
|
1391
|
+
return /* @__PURE__ */ jsx5("text", { fg: "#ffffff", selectable: true, children });
|
|
894
1392
|
}
|
|
895
1393
|
function ExpandableSection({ label, children }) {
|
|
896
|
-
const [expanded, setExpanded] =
|
|
1394
|
+
const [expanded, setExpanded] = useState4(false);
|
|
897
1395
|
if (!children) return null;
|
|
898
|
-
return /* @__PURE__ */
|
|
899
|
-
/* @__PURE__ */
|
|
900
|
-
/* @__PURE__ */
|
|
1396
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", children: [
|
|
1397
|
+
/* @__PURE__ */ jsx5("box", { onMouseDown: () => setExpanded((e) => !e), children: /* @__PURE__ */ jsxs5("text", { children: [
|
|
1398
|
+
/* @__PURE__ */ jsxs5("span", { fg: "#555555", children: [
|
|
901
1399
|
expanded ? "\u25BE" : "\u25B8",
|
|
902
1400
|
" "
|
|
903
1401
|
] }),
|
|
904
|
-
/* @__PURE__ */
|
|
1402
|
+
/* @__PURE__ */ jsx5("span", { fg: "#888888", children: label })
|
|
905
1403
|
] }) }),
|
|
906
|
-
expanded && /* @__PURE__ */
|
|
1404
|
+
expanded && /* @__PURE__ */ jsx5("box", { paddingLeft: 2, children: /* @__PURE__ */ jsx5("text", { fg: "#888888", selectable: true, children }) })
|
|
1405
|
+
] });
|
|
1406
|
+
}
|
|
1407
|
+
function ExpandableDiffSection({ label, diffContent, filePath }) {
|
|
1408
|
+
const [expanded, setExpanded] = useState4(false);
|
|
1409
|
+
if (!diffContent) return null;
|
|
1410
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", children: [
|
|
1411
|
+
/* @__PURE__ */ jsx5("box", { onMouseDown: () => setExpanded((e) => !e), children: /* @__PURE__ */ jsxs5("text", { children: [
|
|
1412
|
+
/* @__PURE__ */ jsxs5("span", { fg: "#555555", children: [
|
|
1413
|
+
expanded ? "\u25BE" : "\u25B8",
|
|
1414
|
+
" "
|
|
1415
|
+
] }),
|
|
1416
|
+
/* @__PURE__ */ jsx5("span", { fg: "#888888", children: label })
|
|
1417
|
+
] }) }),
|
|
1418
|
+
expanded && /* @__PURE__ */ jsx5("box", { paddingLeft: 1, children: /* @__PURE__ */ jsx5(DiffView, { diff: diffContent, filePath }) })
|
|
907
1419
|
] });
|
|
908
1420
|
}
|
|
909
1421
|
function CIFailureMessage({ data }) {
|
|
910
|
-
return /* @__PURE__ */
|
|
911
|
-
/* @__PURE__ */
|
|
912
|
-
/* @__PURE__ */
|
|
913
|
-
/* @__PURE__ */
|
|
914
|
-
/* @__PURE__ */
|
|
915
|
-
/* @__PURE__ */
|
|
1422
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1423
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1424
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "ci_failure" }),
|
|
1425
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
|
|
1426
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "Workflow", value: data.workflowName }),
|
|
1427
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "Status", value: data.conclusion })
|
|
916
1428
|
] }),
|
|
917
|
-
/* @__PURE__ */
|
|
1429
|
+
/* @__PURE__ */ jsxs5("text", { fg: "#ffffff", children: [
|
|
918
1430
|
"Workflow ",
|
|
919
|
-
/* @__PURE__ */
|
|
1431
|
+
/* @__PURE__ */ jsx5("span", { fg: "#ff4444", children: data.conclusionText }),
|
|
920
1432
|
" on PR #" + data.prNumber
|
|
921
1433
|
] }),
|
|
922
|
-
data.workflowFile && /* @__PURE__ */
|
|
923
|
-
data.runUrl && /* @__PURE__ */
|
|
1434
|
+
data.workflowFile && /* @__PURE__ */ jsx5(MetadataPill, { label: "File", value: data.workflowFile }),
|
|
1435
|
+
data.runUrl && /* @__PURE__ */ jsx5(MetadataPill, { label: "Run", value: data.runUrl })
|
|
924
1436
|
] });
|
|
925
1437
|
}
|
|
926
1438
|
function LinearIssueMessage({ data }) {
|
|
927
|
-
return /* @__PURE__ */
|
|
928
|
-
/* @__PURE__ */
|
|
929
|
-
/* @__PURE__ */
|
|
930
|
-
/* @__PURE__ */
|
|
1439
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1440
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1441
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "linear_issue" }),
|
|
1442
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "", value: data.identifier })
|
|
931
1443
|
] }),
|
|
932
|
-
/* @__PURE__ */
|
|
933
|
-
data.description && data.description !== "No description provided." && /* @__PURE__ */
|
|
934
|
-
/* @__PURE__ */
|
|
935
|
-
data.parentIssue && /* @__PURE__ */
|
|
1444
|
+
/* @__PURE__ */ jsx5("text", { fg: "#ffffff", children: /* @__PURE__ */ jsx5("strong", { children: data.title }) }),
|
|
1445
|
+
data.description && data.description !== "No description provided." && /* @__PURE__ */ jsx5(MessageBody, { children: data.description }),
|
|
1446
|
+
/* @__PURE__ */ jsx5(ExpandableSection, { label: "Additional context", children: data.additionalContext }),
|
|
1447
|
+
data.parentIssue && /* @__PURE__ */ jsx5(ExpandableSection, { label: `Parent: ${data.parentIssue.identifier} - ${data.parentIssue.title}`, children: data.parentIssue.description })
|
|
936
1448
|
] });
|
|
937
1449
|
}
|
|
938
1450
|
function GitHubIssueNewMessage({ data }) {
|
|
939
|
-
return /* @__PURE__ */
|
|
940
|
-
/* @__PURE__ */
|
|
941
|
-
/* @__PURE__ */
|
|
942
|
-
/* @__PURE__ */
|
|
943
|
-
data.triggeringUser && /* @__PURE__ */
|
|
1451
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1452
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1453
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "github_issue_new" }),
|
|
1454
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "Issue", value: `#${data.issueNumber}` }),
|
|
1455
|
+
data.triggeringUser && /* @__PURE__ */ jsx5(MetadataPill, { label: "From", value: `@${data.triggeringUser}` })
|
|
944
1456
|
] }),
|
|
945
|
-
/* @__PURE__ */
|
|
946
|
-
data.triggeringComment && /* @__PURE__ */
|
|
947
|
-
/* @__PURE__ */
|
|
1457
|
+
/* @__PURE__ */ jsx5("text", { fg: "#ffffff", children: /* @__PURE__ */ jsx5("strong", { children: data.issueTitle }) }),
|
|
1458
|
+
data.triggeringComment && /* @__PURE__ */ jsx5(MessageBody, { children: data.triggeringComment }),
|
|
1459
|
+
/* @__PURE__ */ jsx5(ExpandableSection, { label: "Issue description", children: data.issueDescription })
|
|
948
1460
|
] });
|
|
949
1461
|
}
|
|
950
1462
|
function GitHubIssueExistingMessage({ data }) {
|
|
951
|
-
return /* @__PURE__ */
|
|
952
|
-
/* @__PURE__ */
|
|
953
|
-
/* @__PURE__ */
|
|
954
|
-
/* @__PURE__ */
|
|
955
|
-
data.commentUser && /* @__PURE__ */
|
|
1463
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1464
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1465
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "github_issue_existing" }),
|
|
1466
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "Issue", value: `#${data.issueNumber}` }),
|
|
1467
|
+
data.commentUser && /* @__PURE__ */ jsx5(MetadataPill, { label: "From", value: `@${data.commentUser}` })
|
|
956
1468
|
] }),
|
|
957
|
-
/* @__PURE__ */
|
|
1469
|
+
/* @__PURE__ */ jsx5(MessageBody, { children: data.commentBody })
|
|
958
1470
|
] });
|
|
959
1471
|
}
|
|
960
1472
|
function GitHubPRNewMessage({ data }) {
|
|
961
|
-
return /* @__PURE__ */
|
|
962
|
-
/* @__PURE__ */
|
|
963
|
-
/* @__PURE__ */
|
|
964
|
-
/* @__PURE__ */
|
|
965
|
-
data.mentioningUser && /* @__PURE__ */
|
|
1473
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1474
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1475
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "github_pr_new" }),
|
|
1476
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
|
|
1477
|
+
data.mentioningUser && /* @__PURE__ */ jsx5(MetadataPill, { label: "From", value: `@${data.mentioningUser}` })
|
|
966
1478
|
] }),
|
|
967
|
-
/* @__PURE__ */
|
|
1479
|
+
/* @__PURE__ */ jsx5(MessageBody, { children: data.contextMessage })
|
|
968
1480
|
] });
|
|
969
1481
|
}
|
|
970
1482
|
function GitHubPRCodeReviewMessage({ data }) {
|
|
971
|
-
return /* @__PURE__ */
|
|
972
|
-
/* @__PURE__ */
|
|
973
|
-
/* @__PURE__ */
|
|
974
|
-
/* @__PURE__ */
|
|
975
|
-
data.commentUser && /* @__PURE__ */
|
|
976
|
-
data.filePath && /* @__PURE__ */
|
|
1483
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1484
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1485
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "github_pr_existing_review" }),
|
|
1486
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
|
|
1487
|
+
data.commentUser && /* @__PURE__ */ jsx5(MetadataPill, { label: "From", value: `@${data.commentUser}` }),
|
|
1488
|
+
data.filePath && /* @__PURE__ */ jsx5(MetadataPill, { label: "File", value: data.filePath })
|
|
977
1489
|
] }),
|
|
978
|
-
/* @__PURE__ */
|
|
979
|
-
/* @__PURE__ */
|
|
1490
|
+
/* @__PURE__ */ jsx5(MessageBody, { children: data.commentBody }),
|
|
1491
|
+
/* @__PURE__ */ jsx5(ExpandableDiffSection, { label: "Diff context", diffContent: data.diffHunk, filePath: data.filePath })
|
|
980
1492
|
] });
|
|
981
1493
|
}
|
|
982
1494
|
function GitHubPRReviewMessage({ data }) {
|
|
983
|
-
return /* @__PURE__ */
|
|
984
|
-
/* @__PURE__ */
|
|
985
|
-
/* @__PURE__ */
|
|
986
|
-
/* @__PURE__ */
|
|
987
|
-
data.reviewUser && /* @__PURE__ */
|
|
1495
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1496
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1497
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "github_pr_existing_pr_review" }),
|
|
1498
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
|
|
1499
|
+
data.reviewUser && /* @__PURE__ */ jsx5(MetadataPill, { label: "From", value: `@${data.reviewUser}` })
|
|
988
1500
|
] }),
|
|
989
|
-
/* @__PURE__ */
|
|
1501
|
+
/* @__PURE__ */ jsxs5("text", { fg: "#888888", children: [
|
|
990
1502
|
"@" + data.reviewUser + " ",
|
|
991
|
-
/* @__PURE__ */
|
|
1503
|
+
/* @__PURE__ */ jsx5("span", { fg: "#ffffff", children: data.reviewAction })
|
|
992
1504
|
] }),
|
|
993
|
-
data.commentBody && /* @__PURE__ */
|
|
1505
|
+
data.commentBody && /* @__PURE__ */ jsx5(MessageBody, { children: data.commentBody })
|
|
994
1506
|
] });
|
|
995
1507
|
}
|
|
996
1508
|
function GitHubPRGeneralMessage({ data }) {
|
|
997
|
-
return /* @__PURE__ */
|
|
998
|
-
/* @__PURE__ */
|
|
999
|
-
/* @__PURE__ */
|
|
1000
|
-
/* @__PURE__ */
|
|
1001
|
-
data.commentUser && /* @__PURE__ */
|
|
1509
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1510
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1511
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "github_pr_existing_general" }),
|
|
1512
|
+
/* @__PURE__ */ jsx5(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
|
|
1513
|
+
data.commentUser && /* @__PURE__ */ jsx5(MetadataPill, { label: "From", value: `@${data.commentUser}` })
|
|
1002
1514
|
] }),
|
|
1003
|
-
/* @__PURE__ */
|
|
1515
|
+
/* @__PURE__ */ jsx5(MessageBody, { children: data.commentBody })
|
|
1004
1516
|
] });
|
|
1005
1517
|
}
|
|
1006
1518
|
function SlackTaskMessage({ data }) {
|
|
1007
1519
|
const hasDistinctContext = data.threadContext && data.threadContext !== `@${data.latestMessageUser}: ${data.latestMessageText}`;
|
|
1008
|
-
return /* @__PURE__ */
|
|
1009
|
-
/* @__PURE__ */
|
|
1010
|
-
/* @__PURE__ */
|
|
1011
|
-
data.workspaceTarget && /* @__PURE__ */
|
|
1012
|
-
data.latestMessageUser && /* @__PURE__ */
|
|
1520
|
+
return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", gap: 0, children: [
|
|
1521
|
+
/* @__PURE__ */ jsxs5("box", { flexDirection: "row", gap: 1, children: [
|
|
1522
|
+
/* @__PURE__ */ jsx5(SourceBadge, { source: "slack_task" }),
|
|
1523
|
+
data.workspaceTarget && /* @__PURE__ */ jsx5(MetadataPill, { label: "Target", value: data.workspaceTarget }),
|
|
1524
|
+
data.latestMessageUser && /* @__PURE__ */ jsx5(MetadataPill, { label: "From", value: `@${data.latestMessageUser}` })
|
|
1013
1525
|
] }),
|
|
1014
|
-
/* @__PURE__ */
|
|
1015
|
-
hasDistinctContext && /* @__PURE__ */
|
|
1526
|
+
/* @__PURE__ */ jsx5(MessageBody, { children: data.latestMessageText }),
|
|
1527
|
+
hasDistinctContext && /* @__PURE__ */ jsx5(ExpandableSection, { label: "Thread context", children: data.threadContext })
|
|
1016
1528
|
] });
|
|
1017
1529
|
}
|
|
1018
1530
|
function StructuredUserMessage({ parsed }) {
|
|
1019
1531
|
switch (parsed.source) {
|
|
1020
1532
|
case "ci_failure":
|
|
1021
|
-
return /* @__PURE__ */
|
|
1533
|
+
return /* @__PURE__ */ jsx5(CIFailureMessage, { data: parsed });
|
|
1022
1534
|
case "linear_issue":
|
|
1023
|
-
return /* @__PURE__ */
|
|
1535
|
+
return /* @__PURE__ */ jsx5(LinearIssueMessage, { data: parsed });
|
|
1024
1536
|
case "github_issue_new":
|
|
1025
|
-
return /* @__PURE__ */
|
|
1537
|
+
return /* @__PURE__ */ jsx5(GitHubIssueNewMessage, { data: parsed });
|
|
1026
1538
|
case "github_issue_existing":
|
|
1027
|
-
return /* @__PURE__ */
|
|
1539
|
+
return /* @__PURE__ */ jsx5(GitHubIssueExistingMessage, { data: parsed });
|
|
1028
1540
|
case "github_pr_new":
|
|
1029
|
-
return /* @__PURE__ */
|
|
1541
|
+
return /* @__PURE__ */ jsx5(GitHubPRNewMessage, { data: parsed });
|
|
1030
1542
|
case "github_pr_existing_review":
|
|
1031
|
-
return /* @__PURE__ */
|
|
1543
|
+
return /* @__PURE__ */ jsx5(GitHubPRCodeReviewMessage, { data: parsed });
|
|
1032
1544
|
case "github_pr_existing_pr_review":
|
|
1033
|
-
return /* @__PURE__ */
|
|
1545
|
+
return /* @__PURE__ */ jsx5(GitHubPRReviewMessage, { data: parsed });
|
|
1034
1546
|
case "github_pr_existing_general":
|
|
1035
|
-
return /* @__PURE__ */
|
|
1547
|
+
return /* @__PURE__ */ jsx5(GitHubPRGeneralMessage, { data: parsed });
|
|
1036
1548
|
case "slack_task":
|
|
1037
|
-
return /* @__PURE__ */
|
|
1549
|
+
return /* @__PURE__ */ jsx5(SlackTaskMessage, { data: parsed });
|
|
1038
1550
|
default: {
|
|
1039
1551
|
const _exhaustive = parsed;
|
|
1040
1552
|
throw new Error(`Unhandled prompt source: ${_exhaustive.source}`);
|
|
@@ -1043,36 +1555,7 @@ function StructuredUserMessage({ parsed }) {
|
|
|
1043
1555
|
}
|
|
1044
1556
|
|
|
1045
1557
|
// src/interactive/components/ChatMessage.tsx
|
|
1046
|
-
import { Fragment as
|
|
1047
|
-
var sharedSyntaxStyle = null;
|
|
1048
|
-
function getSyntaxStyle() {
|
|
1049
|
-
if (!sharedSyntaxStyle) {
|
|
1050
|
-
sharedSyntaxStyle = SyntaxStyle.fromTheme([
|
|
1051
|
-
// Markdown text styling
|
|
1052
|
-
{ scope: ["markup.heading", "markup.heading.1", "markup.heading.2", "markup.heading.3"], style: { foreground: "#66bb6a", bold: true } },
|
|
1053
|
-
{ scope: ["markup.bold", "markup.strong"], style: { foreground: "#ffffff", bold: true } },
|
|
1054
|
-
{ scope: ["markup.italic", "markup.emphasis"], style: { foreground: "#e0e0e0", italic: true } },
|
|
1055
|
-
{ scope: ["markup.link"], style: { foreground: "#7dcfff", underline: true } },
|
|
1056
|
-
{ scope: ["markup.link.url"], style: { foreground: "#7dcfff", underline: true } },
|
|
1057
|
-
{ scope: ["markup.link.text"], style: { foreground: "#66bb6a", underline: true } },
|
|
1058
|
-
{ scope: ["markup.link.label"], style: { foreground: "#66bb6a", underline: true } },
|
|
1059
|
-
{ scope: ["markup.list"], style: { foreground: "#66bb6a" } },
|
|
1060
|
-
{ scope: ["markup.quote"], style: { foreground: "#888888", italic: true } },
|
|
1061
|
-
{ scope: ["markup.raw", "markup.raw.block"], style: { foreground: "#bb9af7" } },
|
|
1062
|
-
{ scope: ["markup.raw.inline"], style: { foreground: "#bb9af7", background: "#1a1a2e" } },
|
|
1063
|
-
// Code syntax highlighting
|
|
1064
|
-
{ scope: ["keyword", "keyword.control", "keyword.operator"], style: { foreground: "#bb9af7" } },
|
|
1065
|
-
{ scope: ["string", "string.quoted"], style: { foreground: "#9ece6a" } },
|
|
1066
|
-
{ scope: ["comment", "comment.line", "comment.block"], style: { foreground: "#555555", italic: true } },
|
|
1067
|
-
{ scope: ["constant", "constant.numeric", "constant.language"], style: { foreground: "#ff9e64" } },
|
|
1068
|
-
{ scope: ["entity.name.function", "support.function"], style: { foreground: "#7aa2f7" } },
|
|
1069
|
-
{ scope: ["entity.name.type", "support.type"], style: { foreground: "#2ac3de" } },
|
|
1070
|
-
{ scope: ["variable", "variable.other"], style: { foreground: "#c0caf5" } },
|
|
1071
|
-
{ scope: ["punctuation"], style: { foreground: "#888888" } }
|
|
1072
|
-
]);
|
|
1073
|
-
}
|
|
1074
|
-
return sharedSyntaxStyle;
|
|
1075
|
-
}
|
|
1558
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "@opentui/react/jsx-runtime";
|
|
1076
1559
|
var AGENT_LABELS = {
|
|
1077
1560
|
claude: "Claude",
|
|
1078
1561
|
codex: "Codex"
|
|
@@ -1081,15 +1564,15 @@ function truncate2(text, maxLen) {
|
|
|
1081
1564
|
return text.length > maxLen ? text.slice(0, maxLen - 1) + "\u2026" : text;
|
|
1082
1565
|
}
|
|
1083
1566
|
function StatusIcon({ status }) {
|
|
1084
|
-
if (status === "completed") return /* @__PURE__ */
|
|
1567
|
+
if (status === "completed") return /* @__PURE__ */ jsxs6("span", { fg: "#66bb6a", children: [
|
|
1085
1568
|
" ",
|
|
1086
1569
|
"\u2713"
|
|
1087
1570
|
] });
|
|
1088
|
-
if (status === "failed") return /* @__PURE__ */
|
|
1571
|
+
if (status === "failed") return /* @__PURE__ */ jsxs6("span", { fg: "#ff4444", children: [
|
|
1089
1572
|
" ",
|
|
1090
1573
|
"\u2717"
|
|
1091
1574
|
] });
|
|
1092
|
-
if (status === "in_progress") return /* @__PURE__ */
|
|
1575
|
+
if (status === "in_progress") return /* @__PURE__ */ jsxs6("span", { fg: "#ffaa00", children: [
|
|
1093
1576
|
" ",
|
|
1094
1577
|
"\u2026"
|
|
1095
1578
|
] });
|
|
@@ -1103,7 +1586,7 @@ function ActionLine({
|
|
|
1103
1586
|
onToggle,
|
|
1104
1587
|
expanded
|
|
1105
1588
|
}) {
|
|
1106
|
-
return /* @__PURE__ */
|
|
1589
|
+
return /* @__PURE__ */ jsxs6(
|
|
1107
1590
|
"box",
|
|
1108
1591
|
{
|
|
1109
1592
|
paddingX: 1,
|
|
@@ -1111,15 +1594,15 @@ function ActionLine({
|
|
|
1111
1594
|
justifyContent: "space-between",
|
|
1112
1595
|
onMouseDown: onToggle,
|
|
1113
1596
|
children: [
|
|
1114
|
-
/* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1116
|
-
/* @__PURE__ */
|
|
1597
|
+
/* @__PURE__ */ jsxs6("text", { children: [
|
|
1598
|
+
/* @__PURE__ */ jsx6("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx6("strong", { children: label }) }),
|
|
1599
|
+
/* @__PURE__ */ jsxs6("span", { fg: "#cccccc", children: [
|
|
1117
1600
|
" ",
|
|
1118
1601
|
arg.replace(/\n/g, " ").replace(/\s+/g, " ")
|
|
1119
1602
|
] }),
|
|
1120
|
-
/* @__PURE__ */
|
|
1603
|
+
/* @__PURE__ */ jsx6(StatusIcon, { status })
|
|
1121
1604
|
] }),
|
|
1122
|
-
expandable && /* @__PURE__ */
|
|
1605
|
+
expandable && /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#555555", children: expanded ? "\u25BE" : "\u25B8" }) })
|
|
1123
1606
|
]
|
|
1124
1607
|
}
|
|
1125
1608
|
);
|
|
@@ -1130,9 +1613,9 @@ function ExpandableAction({
|
|
|
1130
1613
|
status,
|
|
1131
1614
|
children
|
|
1132
1615
|
}) {
|
|
1133
|
-
const [expanded, setExpanded] =
|
|
1134
|
-
return /* @__PURE__ */
|
|
1135
|
-
/* @__PURE__ */
|
|
1616
|
+
const [expanded, setExpanded] = useState5(false);
|
|
1617
|
+
return /* @__PURE__ */ jsxs6("box", { flexDirection: "column", children: [
|
|
1618
|
+
/* @__PURE__ */ jsx6(
|
|
1136
1619
|
ActionLine,
|
|
1137
1620
|
{
|
|
1138
1621
|
label,
|
|
@@ -1146,12 +1629,59 @@ function ExpandableAction({
|
|
|
1146
1629
|
expanded && children
|
|
1147
1630
|
] });
|
|
1148
1631
|
}
|
|
1632
|
+
var CHANGE_STYLE = {
|
|
1633
|
+
add: { color: "#66bb6a", sign: "+" },
|
|
1634
|
+
delete: { color: "#ff4444", sign: "-" }
|
|
1635
|
+
};
|
|
1636
|
+
var DEFAULT_CHANGE_STYLE = { color: "#ffaa00", sign: "~" };
|
|
1637
|
+
function getChangeStyle(action) {
|
|
1638
|
+
return CHANGE_STYLE[action] ?? DEFAULT_CHANGE_STYLE;
|
|
1639
|
+
}
|
|
1640
|
+
function PatchOperation({ op, defaultExpanded = false }) {
|
|
1641
|
+
const [expanded, setExpanded] = useState5(defaultExpanded);
|
|
1642
|
+
const { color, sign } = getChangeStyle(op.action);
|
|
1643
|
+
const stats = useMemo4(() => op.diff ? countDiffStats(op.diff) : null, [op.diff]);
|
|
1644
|
+
if (!op.diff) {
|
|
1645
|
+
return /* @__PURE__ */ jsxs6("text", { children: [
|
|
1646
|
+
/* @__PURE__ */ jsx6("span", { fg: color, children: sign }),
|
|
1647
|
+
/* @__PURE__ */ jsxs6("span", { fg: "#cccccc", children: [
|
|
1648
|
+
" ",
|
|
1649
|
+
op.path
|
|
1650
|
+
] })
|
|
1651
|
+
] });
|
|
1652
|
+
}
|
|
1653
|
+
return /* @__PURE__ */ jsxs6("box", { flexDirection: "column", children: [
|
|
1654
|
+
/* @__PURE__ */ jsxs6("box", { onMouseDown: () => setExpanded((e) => !e), flexDirection: "row", justifyContent: "space-between", children: [
|
|
1655
|
+
/* @__PURE__ */ jsxs6("text", { children: [
|
|
1656
|
+
/* @__PURE__ */ jsx6("span", { fg: color, children: sign }),
|
|
1657
|
+
/* @__PURE__ */ jsxs6("span", { fg: "#cccccc", children: [
|
|
1658
|
+
" ",
|
|
1659
|
+
op.path
|
|
1660
|
+
] }),
|
|
1661
|
+
stats && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1662
|
+
/* @__PURE__ */ jsx6("span", { fg: "#444444", children: " " }),
|
|
1663
|
+
stats.removed > 0 && /* @__PURE__ */ jsxs6("span", { fg: "#ff4444", children: [
|
|
1664
|
+
"-",
|
|
1665
|
+
stats.removed
|
|
1666
|
+
] }),
|
|
1667
|
+
stats.removed > 0 && stats.added > 0 && /* @__PURE__ */ jsx6("span", { fg: "#444444", children: " " }),
|
|
1668
|
+
stats.added > 0 && /* @__PURE__ */ jsxs6("span", { fg: "#66bb6a", children: [
|
|
1669
|
+
"+",
|
|
1670
|
+
stats.added
|
|
1671
|
+
] })
|
|
1672
|
+
] })
|
|
1673
|
+
] }),
|
|
1674
|
+
/* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#555555", children: expanded ? "\u25BE" : "\u25B8" }) })
|
|
1675
|
+
] }),
|
|
1676
|
+
expanded && /* @__PURE__ */ jsx6("box", { paddingLeft: 1, children: /* @__PURE__ */ jsx6(DiffView, { diff: op.diff, filePath: op.path }) })
|
|
1677
|
+
] });
|
|
1678
|
+
}
|
|
1149
1679
|
function isStructuredPrompt(p) {
|
|
1150
1680
|
return p.source !== "raw";
|
|
1151
1681
|
}
|
|
1152
1682
|
function UserMessageContent({ content }) {
|
|
1153
|
-
const parsed =
|
|
1154
|
-
return /* @__PURE__ */
|
|
1683
|
+
const parsed = useMemo4(() => parseUserMessage(content), [content]);
|
|
1684
|
+
return /* @__PURE__ */ jsx6(
|
|
1155
1685
|
"box",
|
|
1156
1686
|
{
|
|
1157
1687
|
flexDirection: "column",
|
|
@@ -1159,9 +1689,9 @@ function UserMessageContent({ content }) {
|
|
|
1159
1689
|
paddingX: 2,
|
|
1160
1690
|
paddingY: 1,
|
|
1161
1691
|
marginX: 1,
|
|
1162
|
-
children: isStructuredPrompt(parsed) ? /* @__PURE__ */
|
|
1163
|
-
/* @__PURE__ */
|
|
1164
|
-
/* @__PURE__ */
|
|
1692
|
+
children: isStructuredPrompt(parsed) ? /* @__PURE__ */ jsx6(StructuredUserMessage, { parsed }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1693
|
+
/* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx6("strong", { children: "You" }) }) }),
|
|
1694
|
+
/* @__PURE__ */ jsx6("text", { fg: "#ffffff", selectable: true, children: content })
|
|
1165
1695
|
] })
|
|
1166
1696
|
}
|
|
1167
1697
|
);
|
|
@@ -1170,14 +1700,14 @@ function ChatMessage({ message, provider }) {
|
|
|
1170
1700
|
switch (message.type) {
|
|
1171
1701
|
case "user": {
|
|
1172
1702
|
if (message.content === "Request interrupted") {
|
|
1173
|
-
return /* @__PURE__ */
|
|
1703
|
+
return /* @__PURE__ */ jsx6("box", { paddingX: 1, justifyContent: "center", children: /* @__PURE__ */ jsx6("text", { fg: "#555555", children: "--- Request interrupted ---" }) });
|
|
1174
1704
|
}
|
|
1175
|
-
return /* @__PURE__ */
|
|
1705
|
+
return /* @__PURE__ */ jsx6(UserMessageContent, { content: message.content });
|
|
1176
1706
|
}
|
|
1177
1707
|
case "agent":
|
|
1178
|
-
return /* @__PURE__ */
|
|
1179
|
-
/* @__PURE__ */
|
|
1180
|
-
/* @__PURE__ */
|
|
1708
|
+
return /* @__PURE__ */ jsxs6("box", { flexDirection: "column", paddingX: 1, children: [
|
|
1709
|
+
/* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx6("strong", { children: AGENT_LABELS[provider] }) }) }),
|
|
1710
|
+
/* @__PURE__ */ jsx6(
|
|
1181
1711
|
"markdown",
|
|
1182
1712
|
{
|
|
1183
1713
|
content: message.content,
|
|
@@ -1190,57 +1720,54 @@ function ChatMessage({ message, provider }) {
|
|
|
1190
1720
|
)
|
|
1191
1721
|
] });
|
|
1192
1722
|
case "reasoning":
|
|
1193
|
-
return /* @__PURE__ */
|
|
1723
|
+
return /* @__PURE__ */ jsx6("box", { paddingX: 1, children: /* @__PURE__ */ jsx6(SpinnerLabel, { color: "#555555", label: "thinking" }) });
|
|
1194
1724
|
case "command": {
|
|
1195
1725
|
const cmdArg = truncate2(message.command, 60);
|
|
1196
1726
|
const exitSuffix = message.exitCode !== void 0 && message.exitCode !== 0 ? ` (exit ${message.exitCode})` : "";
|
|
1197
1727
|
if (!message.output) {
|
|
1198
|
-
return /* @__PURE__ */
|
|
1728
|
+
return /* @__PURE__ */ jsx6(ActionLine, { label: "Command", arg: cmdArg + exitSuffix, status: message.status });
|
|
1199
1729
|
}
|
|
1200
|
-
return /* @__PURE__ */
|
|
1730
|
+
return /* @__PURE__ */ jsx6(ExpandableAction, { label: "Command", arg: cmdArg + exitSuffix, status: message.status, children: /* @__PURE__ */ jsx6("box", { paddingLeft: 2, paddingX: 1, children: /* @__PURE__ */ jsx6("text", { fg: "#888888", selectable: true, children: message.output.length > 500 ? message.output.slice(0, 500) + "\n\u2026" : message.output }) }) });
|
|
1201
1731
|
}
|
|
1202
1732
|
case "file_change": {
|
|
1203
1733
|
const count = message.changes.length;
|
|
1204
|
-
return /* @__PURE__ */
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
{
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
change.path
|
|
1215
|
-
] })
|
|
1216
|
-
] }, i)) }) });
|
|
1734
|
+
return /* @__PURE__ */ jsx6(ExpandableAction, { label: "Files", arg: `${count}`, status: message.status, children: /* @__PURE__ */ jsx6("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: message.changes.map((change, i) => {
|
|
1735
|
+
const { color, sign } = getChangeStyle(change.kind);
|
|
1736
|
+
return /* @__PURE__ */ jsxs6("text", { children: [
|
|
1737
|
+
/* @__PURE__ */ jsx6("span", { fg: color, children: sign }),
|
|
1738
|
+
/* @__PURE__ */ jsxs6("span", { fg: "#cccccc", children: [
|
|
1739
|
+
" ",
|
|
1740
|
+
change.path
|
|
1741
|
+
] })
|
|
1742
|
+
] }, i);
|
|
1743
|
+
}) }) });
|
|
1217
1744
|
}
|
|
1218
1745
|
case "tool_call": {
|
|
1219
1746
|
const toolArg = truncate2(message.tool, 50);
|
|
1220
1747
|
if (message.output || message.input) {
|
|
1221
|
-
return /* @__PURE__ */
|
|
1222
|
-
message.input && /* @__PURE__ */
|
|
1223
|
-
message.output && /* @__PURE__ */
|
|
1748
|
+
return /* @__PURE__ */ jsx6(ExpandableAction, { label: "Tool", arg: toolArg, status: message.status, children: /* @__PURE__ */ jsxs6("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: [
|
|
1749
|
+
message.input && /* @__PURE__ */ jsx6("text", { fg: "#888888", selectable: true, children: typeof message.input === "string" ? truncate2(message.input, 300) : truncate2(JSON.stringify(message.input, null, 2), 300) }),
|
|
1750
|
+
message.output && /* @__PURE__ */ jsx6("text", { fg: "#888888", selectable: true, children: truncate2(message.output, 300) })
|
|
1224
1751
|
] }) });
|
|
1225
1752
|
}
|
|
1226
|
-
return /* @__PURE__ */
|
|
1753
|
+
return /* @__PURE__ */ jsx6(ActionLine, { label: "Tool", arg: toolArg, status: message.status });
|
|
1227
1754
|
}
|
|
1228
1755
|
case "web_search":
|
|
1229
|
-
return /* @__PURE__ */
|
|
1756
|
+
return /* @__PURE__ */ jsx6(ActionLine, { label: "Search", arg: truncate2(message.query, 50), status: message.status });
|
|
1230
1757
|
case "todo_list": {
|
|
1231
1758
|
const completed = message.items.filter((i) => i.completed).length;
|
|
1232
1759
|
const total = message.items.length;
|
|
1233
|
-
return /* @__PURE__ */
|
|
1234
|
-
/* @__PURE__ */
|
|
1760
|
+
return /* @__PURE__ */ jsxs6("box", { flexDirection: "column", paddingX: 1, children: [
|
|
1761
|
+
/* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#888888", children: /* @__PURE__ */ jsxs6("strong", { children: [
|
|
1235
1762
|
"Plan (",
|
|
1236
1763
|
completed,
|
|
1237
1764
|
"/",
|
|
1238
1765
|
total,
|
|
1239
1766
|
")"
|
|
1240
1767
|
] }) }) }),
|
|
1241
|
-
message.items.map((item, i) => /* @__PURE__ */
|
|
1242
|
-
/* @__PURE__ */
|
|
1243
|
-
/* @__PURE__ */
|
|
1768
|
+
message.items.map((item, i) => /* @__PURE__ */ jsxs6("text", { children: [
|
|
1769
|
+
/* @__PURE__ */ jsx6("span", { fg: item.completed ? "#66bb6a" : "#555555", children: item.completed ? " \u2611" : " \u2610" }),
|
|
1770
|
+
/* @__PURE__ */ jsxs6("span", { fg: "#ffffff", children: [
|
|
1244
1771
|
" ",
|
|
1245
1772
|
item.text
|
|
1246
1773
|
] })
|
|
@@ -1248,26 +1775,15 @@ function ChatMessage({ message, provider }) {
|
|
|
1248
1775
|
] });
|
|
1249
1776
|
}
|
|
1250
1777
|
case "subagent":
|
|
1251
|
-
return /* @__PURE__ */
|
|
1778
|
+
return /* @__PURE__ */ jsx6(ActionLine, { label: "Agent", arg: truncate2(message.description, 50), status: message.status });
|
|
1252
1779
|
case "error":
|
|
1253
|
-
return /* @__PURE__ */
|
|
1780
|
+
return /* @__PURE__ */ jsx6("box", { paddingX: 1, children: /* @__PURE__ */ jsx6("text", { fg: "#ff4444", selectable: true, children: message.message }) });
|
|
1254
1781
|
case "skill":
|
|
1255
|
-
return /* @__PURE__ */
|
|
1782
|
+
return /* @__PURE__ */ jsx6(ActionLine, { label: "Skill", arg: message.skillName + (message.args ? ` ${message.args}` : ""), status: message.status });
|
|
1256
1783
|
case "patch": {
|
|
1257
1784
|
const opCount = message.operations.length;
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
"span",
|
|
1261
|
-
{
|
|
1262
|
-
fg: op.action === "add" ? "#66bb6a" : op.action === "delete" ? "#ff4444" : "#ffaa00",
|
|
1263
|
-
children: op.action === "add" ? "+" : op.action === "delete" ? "-" : "~"
|
|
1264
|
-
}
|
|
1265
|
-
),
|
|
1266
|
-
/* @__PURE__ */ jsxs5("span", { fg: "#cccccc", children: [
|
|
1267
|
-
" ",
|
|
1268
|
-
op.path
|
|
1269
|
-
] })
|
|
1270
|
-
] }, i)) }) });
|
|
1785
|
+
const autoExpand = opCount === 1 && !!message.operations[0].diff;
|
|
1786
|
+
return /* @__PURE__ */ jsx6(ExpandableAction, { label: "Patch", arg: `${opCount}`, children: /* @__PURE__ */ jsx6("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: message.operations.map((op, i) => /* @__PURE__ */ jsx6(PatchOperation, { op, defaultExpanded: autoExpand }, i)) }) });
|
|
1271
1787
|
}
|
|
1272
1788
|
default:
|
|
1273
1789
|
return null;
|
|
@@ -1275,7 +1791,7 @@ function ChatMessage({ message, provider }) {
|
|
|
1275
1791
|
}
|
|
1276
1792
|
|
|
1277
1793
|
// src/interactive/components/ChatArea.tsx
|
|
1278
|
-
import { jsx as
|
|
1794
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "@opentui/react/jsx-runtime";
|
|
1279
1795
|
var textareaKeyBindings = [
|
|
1280
1796
|
{ name: "return", action: "submit" },
|
|
1281
1797
|
{ name: "return", shift: true, action: "newline" },
|
|
@@ -1298,10 +1814,10 @@ function ChatArea({
|
|
|
1298
1814
|
isProcessing,
|
|
1299
1815
|
loading
|
|
1300
1816
|
}) {
|
|
1301
|
-
const textareaRef =
|
|
1302
|
-
const scrollboxRef =
|
|
1303
|
-
const isAtBottomRef =
|
|
1304
|
-
const onSendMessageRef =
|
|
1817
|
+
const textareaRef = useRef2(null);
|
|
1818
|
+
const scrollboxRef = useRef2(null);
|
|
1819
|
+
const isAtBottomRef = useRef2(true);
|
|
1820
|
+
const onSendMessageRef = useRef2(onSendMessage);
|
|
1305
1821
|
onSendMessageRef.current = onSendMessage;
|
|
1306
1822
|
const inputFocused = focusPanel === "chat-input";
|
|
1307
1823
|
const tabsFocused = focusPanel === "chat-tabs";
|
|
@@ -1343,20 +1859,7 @@ function ChatArea({
|
|
|
1343
1859
|
textarea.onSubmit = void 0;
|
|
1344
1860
|
};
|
|
1345
1861
|
}, []);
|
|
1346
|
-
|
|
1347
|
-
if (!historyFocused) return;
|
|
1348
|
-
const scrollbox = scrollboxRef.current;
|
|
1349
|
-
if (!scrollbox) return;
|
|
1350
|
-
if (key.name === "j" || key.name === "down") {
|
|
1351
|
-
scrollbox.scrollBy(3);
|
|
1352
|
-
return;
|
|
1353
|
-
}
|
|
1354
|
-
if (key.name === "k" || key.name === "up") {
|
|
1355
|
-
scrollbox.scrollBy(-3);
|
|
1356
|
-
return;
|
|
1357
|
-
}
|
|
1358
|
-
});
|
|
1359
|
-
useKeyboard2((key) => {
|
|
1862
|
+
useKeyboard3((key) => {
|
|
1360
1863
|
if (!tabsFocused || chats.length <= 1 || !selectedChatId) return;
|
|
1361
1864
|
if (key.name === "left" || key.name === "right" || key.name === "tab" && !key.shift) {
|
|
1362
1865
|
const currentIdx = chats.findIndex((c) => c.id === selectedChatId);
|
|
@@ -1366,7 +1869,7 @@ function ChatArea({
|
|
|
1366
1869
|
}
|
|
1367
1870
|
}
|
|
1368
1871
|
});
|
|
1369
|
-
return /* @__PURE__ */
|
|
1872
|
+
return /* @__PURE__ */ jsxs7(
|
|
1370
1873
|
"box",
|
|
1371
1874
|
{
|
|
1372
1875
|
flexGrow: 1,
|
|
@@ -1378,7 +1881,7 @@ function ChatArea({
|
|
|
1378
1881
|
flexDirection: "column",
|
|
1379
1882
|
backgroundColor: "#000000",
|
|
1380
1883
|
children: [
|
|
1381
|
-
chats.length > 1 && /* @__PURE__ */
|
|
1884
|
+
chats.length > 1 && /* @__PURE__ */ jsx7(
|
|
1382
1885
|
"box",
|
|
1383
1886
|
{
|
|
1384
1887
|
height: 3,
|
|
@@ -1394,7 +1897,7 @@ function ChatArea({
|
|
|
1394
1897
|
children: chats.map((chat) => {
|
|
1395
1898
|
const isSelected = chat.id === selectedChatId;
|
|
1396
1899
|
const label = `${chat.title}${chat.processing ? " ..." : ""}`;
|
|
1397
|
-
return /* @__PURE__ */
|
|
1900
|
+
return /* @__PURE__ */ jsx7(
|
|
1398
1901
|
"box",
|
|
1399
1902
|
{
|
|
1400
1903
|
backgroundColor: isSelected ? "#1a1a1a" : void 0,
|
|
@@ -1403,14 +1906,14 @@ function ChatArea({
|
|
|
1403
1906
|
onSelectChat(chat.id);
|
|
1404
1907
|
onFocus("chat-tabs");
|
|
1405
1908
|
},
|
|
1406
|
-
children: /* @__PURE__ */
|
|
1909
|
+
children: /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: isSelected ? modeColors.text : "#666666", children: label }) })
|
|
1407
1910
|
},
|
|
1408
1911
|
chat.id
|
|
1409
1912
|
);
|
|
1410
1913
|
})
|
|
1411
1914
|
}
|
|
1412
1915
|
),
|
|
1413
|
-
/* @__PURE__ */
|
|
1916
|
+
/* @__PURE__ */ jsx7(
|
|
1414
1917
|
"scrollbox",
|
|
1415
1918
|
{
|
|
1416
1919
|
ref: scrollboxRef,
|
|
@@ -1419,22 +1922,22 @@ function ChatArea({
|
|
|
1419
1922
|
paddingX: 1,
|
|
1420
1923
|
paddingY: 1,
|
|
1421
1924
|
onMouseDown: () => onFocus("chat-history"),
|
|
1422
|
-
children: loading ? /* @__PURE__ */
|
|
1925
|
+
children: loading ? /* @__PURE__ */ jsx7("box", { paddingX: 1, children: /* @__PURE__ */ jsx7("text", { fg: "#666666", children: "Loading messages..." }) }) : displayMessages.length === 0 ? /* @__PURE__ */ jsx7("box", { paddingX: 1, children: /* @__PURE__ */ jsx7("text", { fg: "#666666", children: "No messages yet. Send a message to start chatting." }) }) : (() => {
|
|
1423
1926
|
const activeChat = chats.find((c) => c.id === selectedChatId);
|
|
1424
1927
|
const provider = activeChat?.provider ?? "claude";
|
|
1425
1928
|
const primaryTypes = /* @__PURE__ */ new Set(["user", "agent", "todo_list"]);
|
|
1426
1929
|
return displayMessages.map((msg, i) => {
|
|
1427
1930
|
const prev = i > 0 ? displayMessages[i - 1] : null;
|
|
1428
1931
|
const needsSpacing = prev && (primaryTypes.has(msg.type) || primaryTypes.has(prev.type));
|
|
1429
|
-
return /* @__PURE__ */
|
|
1430
|
-
needsSpacing && /* @__PURE__ */
|
|
1431
|
-
/* @__PURE__ */
|
|
1932
|
+
return /* @__PURE__ */ jsxs7("box", { flexDirection: "column", children: [
|
|
1933
|
+
needsSpacing && /* @__PURE__ */ jsx7("box", { height: 1 }),
|
|
1934
|
+
/* @__PURE__ */ jsx7(ChatMessage, { message: msg, provider })
|
|
1432
1935
|
] }, msg.id || `msg-${i}`);
|
|
1433
1936
|
});
|
|
1434
1937
|
})()
|
|
1435
1938
|
}
|
|
1436
1939
|
),
|
|
1437
|
-
/* @__PURE__ */
|
|
1940
|
+
/* @__PURE__ */ jsxs7(
|
|
1438
1941
|
"box",
|
|
1439
1942
|
{
|
|
1440
1943
|
flexDirection: "column",
|
|
@@ -1444,7 +1947,7 @@ function ChatArea({
|
|
|
1444
1947
|
backgroundColor: "#111111",
|
|
1445
1948
|
onMouseDown: () => onFocus("chat-input"),
|
|
1446
1949
|
children: [
|
|
1447
|
-
/* @__PURE__ */
|
|
1950
|
+
/* @__PURE__ */ jsx7("box", { height: 6, paddingX: 1, children: /* @__PURE__ */ jsx7(
|
|
1448
1951
|
"textarea",
|
|
1449
1952
|
{
|
|
1450
1953
|
ref: textareaRef,
|
|
@@ -1459,7 +1962,7 @@ function ChatArea({
|
|
|
1459
1962
|
height: 5
|
|
1460
1963
|
}
|
|
1461
1964
|
) }),
|
|
1462
|
-
/* @__PURE__ */
|
|
1965
|
+
/* @__PURE__ */ jsxs7(
|
|
1463
1966
|
"box",
|
|
1464
1967
|
{
|
|
1465
1968
|
height: 1,
|
|
@@ -1467,8 +1970,8 @@ function ChatArea({
|
|
|
1467
1970
|
flexDirection: "row",
|
|
1468
1971
|
justifyContent: "space-between",
|
|
1469
1972
|
children: [
|
|
1470
|
-
/* @__PURE__ */
|
|
1471
|
-
isProcessing && /* @__PURE__ */
|
|
1973
|
+
/* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: modeColors.text, children: taskMode === "build" ? "Build" : "Plan" }) }),
|
|
1974
|
+
isProcessing && /* @__PURE__ */ jsx7(SpinnerLabel, { color: "#ffaa00", label: "thinking" })
|
|
1472
1975
|
]
|
|
1473
1976
|
}
|
|
1474
1977
|
)
|
|
@@ -1481,10 +1984,10 @@ function ChatArea({
|
|
|
1481
1984
|
}
|
|
1482
1985
|
|
|
1483
1986
|
// src/interactive/components/WorkspaceInfo.tsx
|
|
1484
|
-
import
|
|
1987
|
+
import React6, { useState as useState6, useMemo as useMemo5, useCallback as useCallback5, useRef as useRef3 } from "react";
|
|
1485
1988
|
import open from "open";
|
|
1486
|
-
import { useKeyboard as
|
|
1487
|
-
import { Fragment as
|
|
1989
|
+
import { useKeyboard as useKeyboard4 } from "@opentui/react";
|
|
1990
|
+
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs8 } from "@opentui/react/jsx-runtime";
|
|
1488
1991
|
var WEB_APP_URL = process.env.REPLICAS_WEB_URL || "https://replicas.dev";
|
|
1489
1992
|
function buildInteractiveItems(workspaceId, status, previews, wakingWorkspaceId) {
|
|
1490
1993
|
const items = [];
|
|
@@ -1499,6 +2002,19 @@ function buildInteractiveItems(workspaceId, status, previews, wakingWorkspaceId)
|
|
|
1499
2002
|
if (workspaceId && status.status === "sleeping" && wakingWorkspaceId !== workspaceId) {
|
|
1500
2003
|
items.push({ type: "wake", workspaceId });
|
|
1501
2004
|
}
|
|
2005
|
+
const repoDiffs = [];
|
|
2006
|
+
if (status.repoStatuses) {
|
|
2007
|
+
for (const repo of status.repoStatuses) {
|
|
2008
|
+
if (repo.gitDiff?.fullDiff && (repo.gitDiff.added > 0 || repo.gitDiff.removed > 0)) {
|
|
2009
|
+
repoDiffs.push({ type: "diff", repoName: repo.name, diff: repo.gitDiff.fullDiff, added: repo.gitDiff.added, removed: repo.gitDiff.removed });
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
items.push({ type: "view-chat" });
|
|
2014
|
+
if (repoDiffs.length > 0) {
|
|
2015
|
+
items.push({ type: "view-diff" });
|
|
2016
|
+
items.push(...repoDiffs);
|
|
2017
|
+
}
|
|
1502
2018
|
for (const preview of previews) {
|
|
1503
2019
|
if (preview.publicUrl) {
|
|
1504
2020
|
items.push({ type: "preview", url: preview.publicUrl, port: preview.port });
|
|
@@ -1523,10 +2039,36 @@ function getItemLabel(item) {
|
|
|
1523
2039
|
return `\u2197 Preview :${item.port}`;
|
|
1524
2040
|
case "pr":
|
|
1525
2041
|
return `\u2197 View PR (${item.repoName})`;
|
|
2042
|
+
case "diff":
|
|
2043
|
+
return `\u25B8 Diff +${item.added} -${item.removed}`;
|
|
2044
|
+
case "view-chat":
|
|
2045
|
+
return "1 Chat";
|
|
2046
|
+
case "view-diff":
|
|
2047
|
+
return "2 Diff";
|
|
1526
2048
|
case "createPr":
|
|
1527
2049
|
return "+ Create PR";
|
|
1528
2050
|
}
|
|
1529
2051
|
}
|
|
2052
|
+
function getItemId(item) {
|
|
2053
|
+
switch (item.type) {
|
|
2054
|
+
case "dashboard":
|
|
2055
|
+
return "info-dashboard";
|
|
2056
|
+
case "wake":
|
|
2057
|
+
return "info-wake";
|
|
2058
|
+
case "preview":
|
|
2059
|
+
return `info-preview-${item.port}`;
|
|
2060
|
+
case "pr":
|
|
2061
|
+
return `info-pr-${item.repoName}`;
|
|
2062
|
+
case "diff":
|
|
2063
|
+
return `info-diff-${item.repoName}`;
|
|
2064
|
+
case "view-chat":
|
|
2065
|
+
return "info-view-chat";
|
|
2066
|
+
case "view-diff":
|
|
2067
|
+
return "info-view-diff";
|
|
2068
|
+
case "createPr":
|
|
2069
|
+
return "info-create-pr";
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
1530
2072
|
var AUTH_METHOD_LABELS = {
|
|
1531
2073
|
oauth: "OAuth",
|
|
1532
2074
|
api_key: "API Key",
|
|
@@ -1535,24 +2077,24 @@ var AUTH_METHOD_LABELS = {
|
|
|
1535
2077
|
};
|
|
1536
2078
|
function StatusDot({ status }) {
|
|
1537
2079
|
if (status === true || status === "yes") {
|
|
1538
|
-
return /* @__PURE__ */
|
|
2080
|
+
return /* @__PURE__ */ jsx8("span", { fg: "#66bb6a", children: "\u2713" });
|
|
1539
2081
|
}
|
|
1540
2082
|
if (status === false || status === "no") {
|
|
1541
|
-
return /* @__PURE__ */
|
|
2083
|
+
return /* @__PURE__ */ jsx8("span", { fg: "#ff4444", children: "\u2717" });
|
|
1542
2084
|
}
|
|
1543
|
-
return /* @__PURE__ */
|
|
2085
|
+
return /* @__PURE__ */ jsx8("span", { fg: "#555555", children: "-" });
|
|
1544
2086
|
}
|
|
1545
2087
|
function SectionLabel({ title }) {
|
|
1546
|
-
return /* @__PURE__ */
|
|
2088
|
+
return /* @__PURE__ */ jsx8("box", { backgroundColor: "#151515", paddingX: 1, children: /* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: "#666666", children: /* @__PURE__ */ jsx8("strong", { children: title.toUpperCase() }) }) }) });
|
|
1547
2089
|
}
|
|
1548
2090
|
function Section({ title, children }) {
|
|
1549
|
-
return /* @__PURE__ */
|
|
1550
|
-
/* @__PURE__ */
|
|
1551
|
-
/* @__PURE__ */
|
|
2091
|
+
return /* @__PURE__ */ jsxs8("box", { flexDirection: "column", marginBottom: 1, children: [
|
|
2092
|
+
/* @__PURE__ */ jsx8(SectionLabel, { title }),
|
|
2093
|
+
/* @__PURE__ */ jsx8("box", { flexDirection: "column", backgroundColor: "#0a0a0a", children })
|
|
1552
2094
|
] });
|
|
1553
2095
|
}
|
|
1554
2096
|
function CardItem({ label, status }) {
|
|
1555
|
-
return /* @__PURE__ */
|
|
2097
|
+
return /* @__PURE__ */ jsxs8(
|
|
1556
2098
|
"box",
|
|
1557
2099
|
{
|
|
1558
2100
|
flexDirection: "row",
|
|
@@ -1561,8 +2103,8 @@ function CardItem({ label, status }) {
|
|
|
1561
2103
|
backgroundColor: "#111111",
|
|
1562
2104
|
marginBottom: 0,
|
|
1563
2105
|
children: [
|
|
1564
|
-
/* @__PURE__ */
|
|
1565
|
-
/* @__PURE__ */
|
|
2106
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: "#cccccc", children: label }) }),
|
|
2107
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8(StatusDot, { status }) })
|
|
1566
2108
|
]
|
|
1567
2109
|
}
|
|
1568
2110
|
);
|
|
@@ -1575,40 +2117,77 @@ function DetailList({
|
|
|
1575
2117
|
const actualSet = new Set(actual);
|
|
1576
2118
|
const rows = uniqueExpected.length > 0 ? uniqueExpected : Array.from(actualSet).sort((a, b) => a.localeCompare(b));
|
|
1577
2119
|
if (rows.length === 0) return null;
|
|
1578
|
-
return /* @__PURE__ */
|
|
2120
|
+
return /* @__PURE__ */ jsx8(Fragment4, { children: rows.map((item, i) => /* @__PURE__ */ jsx8(CardItem, { label: item, status: actualSet.has(item) }, i)) });
|
|
1579
2121
|
}
|
|
1580
|
-
function InteractiveRow({ label, highlighted, disabled, onClick }) {
|
|
2122
|
+
function InteractiveRow({ id, label, highlighted, disabled, onClick }) {
|
|
1581
2123
|
if (disabled) {
|
|
1582
|
-
return /* @__PURE__ */
|
|
2124
|
+
return /* @__PURE__ */ jsx8("box", { id, paddingX: 1, backgroundColor: "#111111", children: /* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: "#444444", children: label }) }) });
|
|
1583
2125
|
}
|
|
1584
|
-
return /* @__PURE__ */
|
|
2126
|
+
return /* @__PURE__ */ jsx8(
|
|
1585
2127
|
"box",
|
|
1586
2128
|
{
|
|
2129
|
+
id,
|
|
1587
2130
|
paddingX: 1,
|
|
1588
2131
|
backgroundColor: highlighted ? "#1a2a1a" : "#111111",
|
|
1589
2132
|
onMouseDown: onClick,
|
|
1590
|
-
children: /* @__PURE__ */
|
|
2133
|
+
children: /* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: highlighted ? "#66bb6a" : "#7dcfff", children: label }) })
|
|
1591
2134
|
}
|
|
1592
2135
|
);
|
|
1593
2136
|
}
|
|
1594
|
-
function
|
|
2137
|
+
function ViewModeRow({
|
|
2138
|
+
id,
|
|
2139
|
+
label,
|
|
2140
|
+
active,
|
|
2141
|
+
highlighted,
|
|
2142
|
+
disabled,
|
|
2143
|
+
onClick
|
|
2144
|
+
}) {
|
|
2145
|
+
const bg = highlighted ? "#1a2a1a" : "#111111";
|
|
2146
|
+
const fg = disabled ? "#444444" : active ? "#66bb6a" : "#cccccc";
|
|
2147
|
+
const marker = active ? "\u25B8" : " ";
|
|
2148
|
+
return /* @__PURE__ */ jsx8(
|
|
2149
|
+
"box",
|
|
2150
|
+
{
|
|
2151
|
+
id,
|
|
2152
|
+
paddingX: 1,
|
|
2153
|
+
backgroundColor: bg,
|
|
2154
|
+
onMouseDown: disabled ? void 0 : onClick,
|
|
2155
|
+
children: /* @__PURE__ */ jsxs8("text", { children: [
|
|
2156
|
+
/* @__PURE__ */ jsxs8("span", { fg: active ? "#66bb6a" : "#555555", children: [
|
|
2157
|
+
marker,
|
|
2158
|
+
" "
|
|
2159
|
+
] }),
|
|
2160
|
+
active ? /* @__PURE__ */ jsx8("span", { fg, children: /* @__PURE__ */ jsx8("strong", { children: label }) }) : /* @__PURE__ */ jsx8("span", { fg, children: label })
|
|
2161
|
+
] })
|
|
2162
|
+
}
|
|
2163
|
+
);
|
|
2164
|
+
}
|
|
2165
|
+
function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, envConfig, previews, onWakeWorkspace, onViewDiff, wakingWorkspaceId, viewMode, viewingDiffRepoName, onSelectChatMode, onSelectDiffMode, onCreatePr, isPlanMode }) {
|
|
1595
2166
|
const borderColor = focused ? "#66bb6a" : "#333333";
|
|
1596
|
-
const [cursorIndex, setCursorIndex] =
|
|
1597
|
-
const interactiveItems =
|
|
2167
|
+
const [cursorIndex, setCursorIndex] = useState6(0);
|
|
2168
|
+
const interactiveItems = useMemo5(() => {
|
|
1598
2169
|
if (!status || !workspaceName) return [];
|
|
1599
2170
|
return buildInteractiveItems(workspaceId, status, previews, wakingWorkspaceId);
|
|
1600
2171
|
}, [workspaceId, workspaceName, status, previews, wakingWorkspaceId]);
|
|
2172
|
+
const diffItems = useMemo5(
|
|
2173
|
+
() => interactiveItems.filter((item) => item.type === "diff"),
|
|
2174
|
+
[interactiveItems]
|
|
2175
|
+
);
|
|
2176
|
+
const hasAnyDiff = diffItems.length > 0;
|
|
1601
2177
|
const safeCursor = interactiveItems.length > 0 ? Math.min(cursorIndex, interactiveItems.length - 1) : 0;
|
|
1602
|
-
const
|
|
2178
|
+
const scrollboxRef = useRef3(null);
|
|
2179
|
+
const moveCursor = useCallback5(
|
|
1603
2180
|
(next) => {
|
|
1604
2181
|
const len = interactiveItems.length;
|
|
1605
2182
|
if (len === 0) return;
|
|
1606
2183
|
const wrapped = (next % len + len) % len;
|
|
1607
2184
|
setCursorIndex(wrapped);
|
|
2185
|
+
const item = interactiveItems[wrapped];
|
|
2186
|
+
if (item) scrollboxRef.current?.scrollChildIntoView(getItemId(item));
|
|
1608
2187
|
},
|
|
1609
|
-
[interactiveItems
|
|
2188
|
+
[interactiveItems]
|
|
1610
2189
|
);
|
|
1611
|
-
const handleAction =
|
|
2190
|
+
const handleAction = useCallback5(
|
|
1612
2191
|
(item) => {
|
|
1613
2192
|
if (!item) return;
|
|
1614
2193
|
switch (item.type) {
|
|
@@ -1627,6 +2206,15 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1627
2206
|
open(item.url).catch(() => {
|
|
1628
2207
|
});
|
|
1629
2208
|
break;
|
|
2209
|
+
case "diff":
|
|
2210
|
+
onViewDiff?.(item.diff, item.repoName);
|
|
2211
|
+
break;
|
|
2212
|
+
case "view-chat":
|
|
2213
|
+
onSelectChatMode();
|
|
2214
|
+
break;
|
|
2215
|
+
case "view-diff":
|
|
2216
|
+
onSelectDiffMode();
|
|
2217
|
+
break;
|
|
1630
2218
|
case "createPr":
|
|
1631
2219
|
if (!isPlanMode) onCreatePr();
|
|
1632
2220
|
break;
|
|
@@ -1634,7 +2222,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1634
2222
|
},
|
|
1635
2223
|
[onWakeWorkspace, onCreatePr]
|
|
1636
2224
|
);
|
|
1637
|
-
|
|
2225
|
+
useKeyboard4((key) => {
|
|
1638
2226
|
if (!focused) return;
|
|
1639
2227
|
if (interactiveItems.length === 0) return;
|
|
1640
2228
|
if (key.name === "j" || key.name === "down") {
|
|
@@ -1668,7 +2256,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1668
2256
|
return;
|
|
1669
2257
|
}
|
|
1670
2258
|
});
|
|
1671
|
-
const isHighlighted =
|
|
2259
|
+
const isHighlighted = useCallback5(
|
|
1672
2260
|
(item) => {
|
|
1673
2261
|
if (!focused) return false;
|
|
1674
2262
|
const idx = interactiveItems.indexOf(item);
|
|
@@ -1676,19 +2264,20 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1676
2264
|
},
|
|
1677
2265
|
[focused, interactiveItems, safeCursor]
|
|
1678
2266
|
);
|
|
1679
|
-
const findItem =
|
|
2267
|
+
const findItem = useCallback5(
|
|
1680
2268
|
(type, key) => {
|
|
1681
2269
|
return interactiveItems.find((item) => {
|
|
1682
2270
|
if (item.type !== type) return false;
|
|
1683
2271
|
if (type === "preview" && key) return item.port === Number(key);
|
|
1684
2272
|
if (type === "pr" && key) return item.repoName === key;
|
|
2273
|
+
if (type === "diff" && key) return item.repoName === key;
|
|
1685
2274
|
return true;
|
|
1686
2275
|
});
|
|
1687
2276
|
},
|
|
1688
2277
|
[interactiveItems]
|
|
1689
2278
|
);
|
|
1690
2279
|
if (!workspaceName) {
|
|
1691
|
-
return /* @__PURE__ */
|
|
2280
|
+
return /* @__PURE__ */ jsx8(
|
|
1692
2281
|
"box",
|
|
1693
2282
|
{
|
|
1694
2283
|
width: 30,
|
|
@@ -1700,12 +2289,12 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1700
2289
|
flexDirection: "column",
|
|
1701
2290
|
paddingX: 1,
|
|
1702
2291
|
backgroundColor: "#000000",
|
|
1703
|
-
children: /* @__PURE__ */
|
|
2292
|
+
children: /* @__PURE__ */ jsx8("text", { fg: "#666666", children: "Select a workspace" })
|
|
1704
2293
|
}
|
|
1705
2294
|
);
|
|
1706
2295
|
}
|
|
1707
2296
|
if (loading || !status) {
|
|
1708
|
-
return /* @__PURE__ */
|
|
2297
|
+
return /* @__PURE__ */ jsx8(
|
|
1709
2298
|
"box",
|
|
1710
2299
|
{
|
|
1711
2300
|
width: 30,
|
|
@@ -1717,7 +2306,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1717
2306
|
flexDirection: "column",
|
|
1718
2307
|
paddingX: 1,
|
|
1719
2308
|
backgroundColor: "#000000",
|
|
1720
|
-
children: /* @__PURE__ */
|
|
2309
|
+
children: /* @__PURE__ */ jsx8("text", { fg: "#666666", children: "Loading..." })
|
|
1721
2310
|
}
|
|
1722
2311
|
);
|
|
1723
2312
|
}
|
|
@@ -1729,7 +2318,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1729
2318
|
const dashboardItem = findItem("dashboard");
|
|
1730
2319
|
const wakeItem = findItem("wake");
|
|
1731
2320
|
const createPrItem = findItem("createPr");
|
|
1732
|
-
return /* @__PURE__ */
|
|
2321
|
+
return /* @__PURE__ */ jsx8(
|
|
1733
2322
|
"box",
|
|
1734
2323
|
{
|
|
1735
2324
|
width: 30,
|
|
@@ -1740,16 +2329,16 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1740
2329
|
titleAlignment: "center",
|
|
1741
2330
|
flexDirection: "column",
|
|
1742
2331
|
backgroundColor: "#000000",
|
|
1743
|
-
children: /* @__PURE__ */
|
|
1744
|
-
/* @__PURE__ */
|
|
1745
|
-
/* @__PURE__ */
|
|
1746
|
-
/* @__PURE__ */
|
|
1747
|
-
/* @__PURE__ */
|
|
2332
|
+
children: /* @__PURE__ */ jsxs8("scrollbox", { ref: scrollboxRef, focused: false, flexGrow: 1, children: [
|
|
2333
|
+
/* @__PURE__ */ jsx8("box", { backgroundColor: "#111111", paddingX: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs8("box", { flexDirection: "column", children: [
|
|
2334
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx8("strong", { children: workspaceName }) }) }),
|
|
2335
|
+
/* @__PURE__ */ jsxs8("text", { children: [
|
|
2336
|
+
/* @__PURE__ */ jsxs8("span", { fg: statusColor, children: [
|
|
1748
2337
|
"\u25CF",
|
|
1749
2338
|
" ",
|
|
1750
2339
|
status.status
|
|
1751
2340
|
] }),
|
|
1752
|
-
env && /* @__PURE__ */
|
|
2341
|
+
env && /* @__PURE__ */ jsxs8("span", { fg: "#555555", children: [
|
|
1753
2342
|
" ",
|
|
1754
2343
|
"\u2502",
|
|
1755
2344
|
" ",
|
|
@@ -1757,103 +2346,158 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1757
2346
|
] })
|
|
1758
2347
|
] })
|
|
1759
2348
|
] }) }),
|
|
1760
|
-
createPrItem && /* @__PURE__ */
|
|
2349
|
+
createPrItem && /* @__PURE__ */ jsx8(
|
|
1761
2350
|
InteractiveRow,
|
|
1762
2351
|
{
|
|
2352
|
+
id: getItemId(createPrItem),
|
|
1763
2353
|
label: getItemLabel(createPrItem),
|
|
1764
2354
|
highlighted: isHighlighted(createPrItem),
|
|
1765
2355
|
disabled: isPlanMode,
|
|
1766
2356
|
onClick: () => handleAction(createPrItem)
|
|
1767
2357
|
}
|
|
1768
2358
|
),
|
|
1769
|
-
dashboardItem && /* @__PURE__ */
|
|
2359
|
+
dashboardItem && /* @__PURE__ */ jsx8(
|
|
1770
2360
|
InteractiveRow,
|
|
1771
2361
|
{
|
|
2362
|
+
id: getItemId(dashboardItem),
|
|
1772
2363
|
label: getItemLabel(dashboardItem),
|
|
1773
2364
|
highlighted: isHighlighted(dashboardItem),
|
|
1774
2365
|
onClick: () => handleAction(dashboardItem)
|
|
1775
2366
|
}
|
|
1776
2367
|
),
|
|
1777
|
-
wakeItem && /* @__PURE__ */
|
|
2368
|
+
wakeItem && /* @__PURE__ */ jsx8(
|
|
1778
2369
|
InteractiveRow,
|
|
1779
2370
|
{
|
|
2371
|
+
id: getItemId(wakeItem),
|
|
1780
2372
|
label: getItemLabel(wakeItem),
|
|
1781
2373
|
highlighted: isHighlighted(wakeItem),
|
|
1782
2374
|
onClick: () => handleAction(wakeItem)
|
|
1783
2375
|
}
|
|
1784
2376
|
),
|
|
1785
|
-
(status.isClaudeProcessing || status.isCodexProcessing) && /* @__PURE__ */
|
|
1786
|
-
status.isClaudeProcessing && /* @__PURE__ */
|
|
2377
|
+
(status.isClaudeProcessing || status.isCodexProcessing) && /* @__PURE__ */ jsxs8("box", { backgroundColor: "#1a1500", paddingX: 1, marginX: 1, marginBottom: 1, children: [
|
|
2378
|
+
status.isClaudeProcessing && /* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsxs8("span", { fg: "#ffaa00", children: [
|
|
1787
2379
|
"\u25C6",
|
|
1788
2380
|
" Claude thinking..."
|
|
1789
2381
|
] }) }),
|
|
1790
|
-
status.isCodexProcessing && /* @__PURE__ */
|
|
2382
|
+
status.isCodexProcessing && /* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsxs8("span", { fg: "#ffaa00", children: [
|
|
1791
2383
|
"\u25C6",
|
|
1792
2384
|
" Codex thinking..."
|
|
1793
2385
|
] }) })
|
|
1794
2386
|
] }),
|
|
1795
|
-
env && /* @__PURE__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
1797
|
-
/* @__PURE__ */
|
|
1798
|
-
/* @__PURE__ */
|
|
2387
|
+
env && /* @__PURE__ */ jsxs8(Section, { title: "Agents", children: [
|
|
2388
|
+
/* @__PURE__ */ jsxs8("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
|
|
2389
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: "#cccccc", children: "Claude" }) }),
|
|
2390
|
+
/* @__PURE__ */ jsx8("text", { children: AUTH_METHOD_LABELS[env.claudeAuthMethod] ? /* @__PURE__ */ jsx8("span", { fg: "#66bb6a", children: AUTH_METHOD_LABELS[env.claudeAuthMethod] }) : /* @__PURE__ */ jsx8("span", { fg: "#ff4444", children: "\u2717" }) })
|
|
1799
2391
|
] }),
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
1802
|
-
/* @__PURE__ */
|
|
2392
|
+
/* @__PURE__ */ jsxs8("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
|
|
2393
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: "#cccccc", children: "Codex" }) }),
|
|
2394
|
+
/* @__PURE__ */ jsx8("text", { children: AUTH_METHOD_LABELS[env.codexAuthMethod] ? /* @__PURE__ */ jsx8("span", { fg: "#66bb6a", children: AUTH_METHOD_LABELS[env.codexAuthMethod] }) : /* @__PURE__ */ jsx8("span", { fg: "#ff4444", children: "\u2717" }) })
|
|
1803
2395
|
] })
|
|
1804
2396
|
] }),
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
/* @__PURE__ */
|
|
2397
|
+
/* @__PURE__ */ jsx8(Section, { title: "View", children: (() => {
|
|
2398
|
+
const chatItem = findItem("view-chat");
|
|
2399
|
+
const diffItem = findItem("view-diff");
|
|
2400
|
+
return /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
2401
|
+
chatItem && /* @__PURE__ */ jsx8(
|
|
2402
|
+
ViewModeRow,
|
|
2403
|
+
{
|
|
2404
|
+
id: getItemId(chatItem),
|
|
2405
|
+
label: "1 Chat",
|
|
2406
|
+
active: viewMode === "chat",
|
|
2407
|
+
highlighted: isHighlighted(chatItem),
|
|
2408
|
+
onClick: () => handleAction(chatItem)
|
|
2409
|
+
}
|
|
2410
|
+
),
|
|
2411
|
+
diffItem ? /* @__PURE__ */ jsx8(
|
|
2412
|
+
ViewModeRow,
|
|
2413
|
+
{
|
|
2414
|
+
id: getItemId(diffItem),
|
|
2415
|
+
label: "2 Diff",
|
|
2416
|
+
active: viewMode === "diff",
|
|
2417
|
+
highlighted: isHighlighted(diffItem),
|
|
2418
|
+
onClick: () => handleAction(diffItem)
|
|
2419
|
+
}
|
|
2420
|
+
) : /* @__PURE__ */ jsx8(ViewModeRow, { label: "2 Diff", active: false, highlighted: false, disabled: true, onClick: () => {
|
|
2421
|
+
} }),
|
|
2422
|
+
hasAnyDiff && diffItems.map((item, i) => {
|
|
2423
|
+
const isActive = viewMode === "diff" && viewingDiffRepoName === item.repoName;
|
|
2424
|
+
const cursorOn = isHighlighted(item);
|
|
2425
|
+
const bg = cursorOn ? "#1a2a1a" : isActive ? "#0d2b0d" : "#111111";
|
|
2426
|
+
const nameColor = isActive || cursorOn ? "#66bb6a" : "#cccccc";
|
|
2427
|
+
return /* @__PURE__ */ jsxs8(
|
|
2428
|
+
"box",
|
|
2429
|
+
{
|
|
2430
|
+
id: getItemId(item),
|
|
2431
|
+
paddingX: 1,
|
|
2432
|
+
backgroundColor: bg,
|
|
2433
|
+
onMouseDown: () => handleAction(item),
|
|
2434
|
+
flexDirection: "row",
|
|
2435
|
+
justifyContent: "space-between",
|
|
2436
|
+
children: [
|
|
2437
|
+
/* @__PURE__ */ jsxs8("text", { children: [
|
|
2438
|
+
/* @__PURE__ */ jsx8("span", { fg: isActive ? "#66bb6a" : "#555555", children: isActive ? " \u25B8 " : " \u2514 " }),
|
|
2439
|
+
isActive ? /* @__PURE__ */ jsx8("span", { fg: nameColor, children: /* @__PURE__ */ jsx8("strong", { children: item.repoName }) }) : /* @__PURE__ */ jsx8("span", { fg: nameColor, children: item.repoName })
|
|
2440
|
+
] }),
|
|
2441
|
+
/* @__PURE__ */ jsxs8("text", { children: [
|
|
2442
|
+
item.added > 0 && /* @__PURE__ */ jsxs8("span", { fg: "#66bb6a", children: [
|
|
2443
|
+
"+",
|
|
2444
|
+
item.added
|
|
2445
|
+
] }),
|
|
2446
|
+
item.added > 0 && item.removed > 0 && /* @__PURE__ */ jsx8("span", { fg: "#444444", children: " " }),
|
|
2447
|
+
item.removed > 0 && /* @__PURE__ */ jsxs8("span", { fg: "#ff4444", children: [
|
|
2448
|
+
"-",
|
|
2449
|
+
item.removed
|
|
2450
|
+
] })
|
|
2451
|
+
] })
|
|
2452
|
+
]
|
|
2453
|
+
},
|
|
2454
|
+
`diff-${i}`
|
|
2455
|
+
);
|
|
2456
|
+
})
|
|
2457
|
+
] });
|
|
2458
|
+
})() }),
|
|
2459
|
+
env && /* @__PURE__ */ jsxs8(Section, { title: "Integrations", children: [
|
|
2460
|
+
/* @__PURE__ */ jsx8(CardItem, { label: "GitHub", status: env.githubAccessConfigured }),
|
|
2461
|
+
/* @__PURE__ */ jsx8(CardItem, { label: "Slack", status: env.slackAccessConfigured }),
|
|
2462
|
+
/* @__PURE__ */ jsx8(CardItem, { label: "Linear", status: env.linearAccessConfigured })
|
|
1809
2463
|
] }),
|
|
1810
|
-
previews.length > 0 && /* @__PURE__ */
|
|
2464
|
+
previews.length > 0 && /* @__PURE__ */ jsx8(Section, { title: "Previews", children: previews.map((preview, i) => {
|
|
1811
2465
|
const previewItem = findItem("preview", String(preview.port));
|
|
1812
|
-
return /* @__PURE__ */
|
|
2466
|
+
return /* @__PURE__ */ jsxs8(
|
|
1813
2467
|
"box",
|
|
1814
2468
|
{
|
|
2469
|
+
id: previewItem ? getItemId(previewItem) : void 0,
|
|
1815
2470
|
flexDirection: "row",
|
|
1816
2471
|
justifyContent: "space-between",
|
|
1817
2472
|
paddingX: 1,
|
|
1818
2473
|
backgroundColor: previewItem && isHighlighted(previewItem) ? "#1a2a1a" : "#111111",
|
|
1819
2474
|
onMouseDown: () => previewItem && handleAction(previewItem),
|
|
1820
2475
|
children: [
|
|
1821
|
-
/* @__PURE__ */
|
|
2476
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsxs8("span", { fg: "#cccccc", children: [
|
|
1822
2477
|
":",
|
|
1823
2478
|
preview.port
|
|
1824
2479
|
] }) }),
|
|
1825
|
-
/* @__PURE__ */
|
|
2480
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: previewItem && isHighlighted(previewItem) ? "#66bb6a" : "#7dcfff", children: "\u2197" }) })
|
|
1826
2481
|
]
|
|
1827
2482
|
},
|
|
1828
2483
|
i
|
|
1829
2484
|
);
|
|
1830
2485
|
}) }),
|
|
1831
|
-
status.repoStatuses && status.repoStatuses.length > 0 && /* @__PURE__ */
|
|
2486
|
+
status.repoStatuses && status.repoStatuses.length > 0 && /* @__PURE__ */ jsx8(Section, { title: "Repositories", children: status.repoStatuses.map((repo, i) => {
|
|
1832
2487
|
const prItem = findItem("pr", repo.name);
|
|
1833
|
-
return /* @__PURE__ */
|
|
1834
|
-
/* @__PURE__ */
|
|
1835
|
-
/* @__PURE__ */
|
|
1836
|
-
/* @__PURE__ */
|
|
2488
|
+
return /* @__PURE__ */ jsxs8(React6.Fragment, { children: [
|
|
2489
|
+
/* @__PURE__ */ jsx8("box", { backgroundColor: "#111111", paddingX: 1, children: /* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx8("strong", { children: repo.name }) }) }) }),
|
|
2490
|
+
/* @__PURE__ */ jsx8("box", { backgroundColor: "#111111", paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: /* @__PURE__ */ jsxs8("text", { children: [
|
|
2491
|
+
/* @__PURE__ */ jsxs8("span", { fg: "#555555", children: [
|
|
1837
2492
|
"\u2514",
|
|
1838
2493
|
" "
|
|
1839
2494
|
] }),
|
|
1840
|
-
/* @__PURE__ */
|
|
2495
|
+
/* @__PURE__ */ jsx8("span", { fg: repo.currentBranch !== repo.defaultBranch ? "#ffaa00" : "#66bb6a", children: repo.currentBranch })
|
|
1841
2496
|
] }) }),
|
|
1842
|
-
|
|
1843
|
-
/* @__PURE__ */ jsx7("span", { fg: "#555555", children: " " }),
|
|
1844
|
-
/* @__PURE__ */ jsxs7("span", { fg: "#66bb6a", children: [
|
|
1845
|
-
"+",
|
|
1846
|
-
repo.gitDiff.added
|
|
1847
|
-
] }),
|
|
1848
|
-
/* @__PURE__ */ jsx7("span", { fg: "#444444", children: " / " }),
|
|
1849
|
-
/* @__PURE__ */ jsxs7("span", { fg: "#ff4444", children: [
|
|
1850
|
-
"-",
|
|
1851
|
-
repo.gitDiff.removed
|
|
1852
|
-
] })
|
|
1853
|
-
] }) }),
|
|
1854
|
-
prItem && /* @__PURE__ */ jsx7(
|
|
2497
|
+
prItem && /* @__PURE__ */ jsx8(
|
|
1855
2498
|
InteractiveRow,
|
|
1856
2499
|
{
|
|
2500
|
+
id: getItemId(prItem),
|
|
1857
2501
|
label: ` ${getItemLabel(prItem)}`,
|
|
1858
2502
|
highlighted: isHighlighted(prItem),
|
|
1859
2503
|
onClick: () => handleAction(prItem)
|
|
@@ -1861,35 +2505,35 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1861
2505
|
)
|
|
1862
2506
|
] }, i);
|
|
1863
2507
|
}) }),
|
|
1864
|
-
env && /* @__PURE__ */
|
|
1865
|
-
/* @__PURE__ */
|
|
1866
|
-
env.repositories.map((repo, i) => /* @__PURE__ */
|
|
1867
|
-
/* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
1869
|
-
/* @__PURE__ */
|
|
1870
|
-
/* @__PURE__ */
|
|
2508
|
+
env && /* @__PURE__ */ jsxs8(Section, { title: "Hooks", children: [
|
|
2509
|
+
/* @__PURE__ */ jsx8(CardItem, { label: "Global warm", status: env.globalWarmHookCompleted.status }),
|
|
2510
|
+
env.repositories.map((repo, i) => /* @__PURE__ */ jsxs8(React6.Fragment, { children: [
|
|
2511
|
+
/* @__PURE__ */ jsx8("box", { backgroundColor: "#111111", paddingX: 1, children: /* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx8("strong", { children: repo.repositoryName }) }) }) }),
|
|
2512
|
+
/* @__PURE__ */ jsxs8("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
|
|
2513
|
+
/* @__PURE__ */ jsxs8("text", { children: [
|
|
2514
|
+
/* @__PURE__ */ jsxs8("span", { fg: "#555555", children: [
|
|
1871
2515
|
"\u251C",
|
|
1872
2516
|
" "
|
|
1873
2517
|
] }),
|
|
1874
|
-
/* @__PURE__ */
|
|
2518
|
+
/* @__PURE__ */ jsx8("span", { fg: "#cccccc", children: "warm" })
|
|
1875
2519
|
] }),
|
|
1876
|
-
/* @__PURE__ */
|
|
2520
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8(StatusDot, { status: repo.warmHookCompleted }) })
|
|
1877
2521
|
] }),
|
|
1878
|
-
/* @__PURE__ */
|
|
1879
|
-
/* @__PURE__ */
|
|
1880
|
-
/* @__PURE__ */
|
|
2522
|
+
/* @__PURE__ */ jsxs8("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
|
|
2523
|
+
/* @__PURE__ */ jsxs8("text", { children: [
|
|
2524
|
+
/* @__PURE__ */ jsxs8("span", { fg: "#555555", children: [
|
|
1881
2525
|
"\u2514",
|
|
1882
2526
|
" "
|
|
1883
2527
|
] }),
|
|
1884
|
-
/* @__PURE__ */
|
|
2528
|
+
/* @__PURE__ */ jsx8("span", { fg: "#cccccc", children: "start" })
|
|
1885
2529
|
] }),
|
|
1886
|
-
/* @__PURE__ */
|
|
2530
|
+
/* @__PURE__ */ jsx8("text", { children: /* @__PURE__ */ jsx8(StatusDot, { status: repo.startHookCompleted }) })
|
|
1887
2531
|
] })
|
|
1888
2532
|
] }, i))
|
|
1889
2533
|
] }),
|
|
1890
|
-
env && (expectedSkills.length > 0 || env.skillsInstalled.length > 0) && /* @__PURE__ */
|
|
1891
|
-
env && (expectedGlobalVars.length > 0 || env.envVarsSet.length > 0) && /* @__PURE__ */
|
|
1892
|
-
env && (expectedGlobalFiles.length > 0 || env.filesUploaded.length > 0) && /* @__PURE__ */
|
|
2534
|
+
env && (expectedSkills.length > 0 || env.skillsInstalled.length > 0) && /* @__PURE__ */ jsx8(Section, { title: "Skills", children: /* @__PURE__ */ jsx8(DetailList, { expected: expectedSkills, actual: env.skillsInstalled }) }),
|
|
2535
|
+
env && (expectedGlobalVars.length > 0 || env.envVarsSet.length > 0) && /* @__PURE__ */ jsx8(Section, { title: "Env Vars", children: /* @__PURE__ */ jsx8(DetailList, { expected: expectedGlobalVars, actual: env.envVarsSet }) }),
|
|
2536
|
+
env && (expectedGlobalFiles.length > 0 || env.filesUploaded.length > 0) && /* @__PURE__ */ jsx8(Section, { title: "Files", children: /* @__PURE__ */ jsx8(DetailList, { expected: expectedGlobalFiles, actual: env.filesUploaded }) })
|
|
1893
2537
|
] })
|
|
1894
2538
|
}
|
|
1895
2539
|
);
|
|
@@ -1899,8 +2543,8 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1899
2543
|
import { useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
|
|
1900
2544
|
|
|
1901
2545
|
// src/interactive/toast-context.tsx
|
|
1902
|
-
import { createContext as createContext2, useContext as useContext2, useState as
|
|
1903
|
-
import { jsx as
|
|
2546
|
+
import { createContext as createContext2, useContext as useContext2, useState as useState7, useCallback as useCallback6, useRef as useRef4 } from "react";
|
|
2547
|
+
import { jsx as jsx9 } from "@opentui/react/jsx-runtime";
|
|
1904
2548
|
var ToastContext = createContext2(null);
|
|
1905
2549
|
function useToast() {
|
|
1906
2550
|
const ctx = useContext2(ToastContext);
|
|
@@ -1908,9 +2552,9 @@ function useToast() {
|
|
|
1908
2552
|
return ctx;
|
|
1909
2553
|
}
|
|
1910
2554
|
function ToastProvider({ children }) {
|
|
1911
|
-
const [current, setCurrent] =
|
|
1912
|
-
const timeoutRef =
|
|
1913
|
-
const show =
|
|
2555
|
+
const [current, setCurrent] = useState7(null);
|
|
2556
|
+
const timeoutRef = useRef4(null);
|
|
2557
|
+
const show = useCallback6((options) => {
|
|
1914
2558
|
const { message, variant = "info", duration = 3e3 } = options;
|
|
1915
2559
|
setCurrent({ message, variant });
|
|
1916
2560
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
@@ -1918,15 +2562,15 @@ function ToastProvider({ children }) {
|
|
|
1918
2562
|
setCurrent(null);
|
|
1919
2563
|
}, duration);
|
|
1920
2564
|
}, []);
|
|
1921
|
-
const error =
|
|
2565
|
+
const error = useCallback6((err) => {
|
|
1922
2566
|
const message = err instanceof Error ? err.message : "An error occurred";
|
|
1923
2567
|
show({ message, variant: "error", duration: 5e3 });
|
|
1924
2568
|
}, [show]);
|
|
1925
|
-
return /* @__PURE__ */
|
|
2569
|
+
return /* @__PURE__ */ jsx9(ToastContext.Provider, { value: { current, show, error }, children });
|
|
1926
2570
|
}
|
|
1927
2571
|
|
|
1928
2572
|
// src/interactive/components/Toast.tsx
|
|
1929
|
-
import { jsx as
|
|
2573
|
+
import { jsx as jsx10 } from "@opentui/react/jsx-runtime";
|
|
1930
2574
|
var VARIANT_COLORS = {
|
|
1931
2575
|
info: { border: "#66bb6a", bg: "#0a1a0a" },
|
|
1932
2576
|
success: { border: "#66bb6a", bg: "#0a1a0a" },
|
|
@@ -1939,7 +2583,7 @@ function Toast() {
|
|
|
1939
2583
|
if (!current) return null;
|
|
1940
2584
|
const colors = VARIANT_COLORS[current.variant] ?? VARIANT_COLORS.info;
|
|
1941
2585
|
const toastWidth = Math.min(60, width - 4);
|
|
1942
|
-
return /* @__PURE__ */
|
|
2586
|
+
return /* @__PURE__ */ jsx10(
|
|
1943
2587
|
"box",
|
|
1944
2588
|
{
|
|
1945
2589
|
position: "absolute",
|
|
@@ -1953,19 +2597,20 @@ function Toast() {
|
|
|
1953
2597
|
border: true,
|
|
1954
2598
|
borderStyle: "rounded",
|
|
1955
2599
|
zIndex: 100,
|
|
1956
|
-
children: /* @__PURE__ */
|
|
2600
|
+
children: /* @__PURE__ */ jsx10("text", { fg: "#ffffff", selectable: true, children: current.message })
|
|
1957
2601
|
}
|
|
1958
2602
|
);
|
|
1959
2603
|
}
|
|
1960
2604
|
|
|
1961
2605
|
// src/interactive/App.tsx
|
|
1962
|
-
import { jsx as
|
|
2606
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "@opentui/react/jsx-runtime";
|
|
1963
2607
|
var FOCUS_ORDER = ["sidebar", "chat-tabs", "chat-history", "chat-input", "info"];
|
|
1964
2608
|
var MOCK_CHATS = [
|
|
1965
2609
|
{ id: "mock-claude", provider: "claude", title: "Claude Code", createdAt: "", updatedAt: "", processing: false },
|
|
1966
2610
|
{ id: "mock-codex", provider: "codex", title: "Codex", createdAt: "", updatedAt: "", processing: false }
|
|
1967
2611
|
];
|
|
1968
2612
|
var MONOLITH_URL = process.env.REPLICAS_MONOLITH_URL || "https://api.replicas.dev";
|
|
2613
|
+
var workspacePollingStarted = false;
|
|
1969
2614
|
var queryClient = new QueryClient({
|
|
1970
2615
|
defaultOptions: {
|
|
1971
2616
|
queries: {
|
|
@@ -1981,15 +2626,24 @@ var authValue = {
|
|
|
1981
2626
|
queryClient
|
|
1982
2627
|
};
|
|
1983
2628
|
function App() {
|
|
1984
|
-
return /* @__PURE__ */
|
|
1985
|
-
/* @__PURE__ */
|
|
1986
|
-
/* @__PURE__ */
|
|
2629
|
+
return /* @__PURE__ */ jsx11(ReplicasAuthProvider, { value: authValue, children: /* @__PURE__ */ jsxs9(ToastProvider, { children: [
|
|
2630
|
+
/* @__PURE__ */ jsx11(AppInner, {}),
|
|
2631
|
+
/* @__PURE__ */ jsx11(Toast, {})
|
|
1987
2632
|
] }) });
|
|
1988
2633
|
}
|
|
1989
2634
|
function AppInner() {
|
|
1990
2635
|
const renderer = useRenderer();
|
|
1991
2636
|
const { width } = useTerminalDimensions3();
|
|
1992
2637
|
const toast = useToast();
|
|
2638
|
+
const rendererRef = useRef5(renderer);
|
|
2639
|
+
rendererRef.current = renderer;
|
|
2640
|
+
if (!workspacePollingStarted) {
|
|
2641
|
+
workspacePollingStarted = true;
|
|
2642
|
+
setInterval(() => {
|
|
2643
|
+
queryClient.invalidateQueries({ queryKey: ["workspaces"] });
|
|
2644
|
+
rendererRef.current.requestRender();
|
|
2645
|
+
}, 3e4);
|
|
2646
|
+
}
|
|
1993
2647
|
useEffect3(() => {
|
|
1994
2648
|
const handler = (selection) => {
|
|
1995
2649
|
const text = selection.getSelectedText();
|
|
@@ -2003,17 +2657,29 @@ function AppInner() {
|
|
|
2003
2657
|
renderer.off("selection", handler);
|
|
2004
2658
|
};
|
|
2005
2659
|
}, [renderer, toast]);
|
|
2006
|
-
const [selectedWorkspaceId, setSelectedWorkspaceId] =
|
|
2007
|
-
const [selectedChatId, setSelectedChatId] =
|
|
2008
|
-
const [focusPanel, setFocusPanel] =
|
|
2009
|
-
const [taskMode, setTaskMode] =
|
|
2010
|
-
const [mockWorkspaces, setMockWorkspaces] =
|
|
2011
|
-
const mockToRealRef =
|
|
2012
|
-
const mockGroupRef =
|
|
2013
|
-
const
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2660
|
+
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState8(null);
|
|
2661
|
+
const [selectedChatId, setSelectedChatId] = useState8(null);
|
|
2662
|
+
const [focusPanel, setFocusPanel] = useState8("sidebar");
|
|
2663
|
+
const [taskMode, setTaskMode] = useState8("build");
|
|
2664
|
+
const [mockWorkspaces, setMockWorkspaces] = useState8([]);
|
|
2665
|
+
const mockToRealRef = useRef5(/* @__PURE__ */ new Map());
|
|
2666
|
+
const mockGroupRef = useRef5(/* @__PURE__ */ new Map());
|
|
2667
|
+
const mockPollingRef = useRef5(null);
|
|
2668
|
+
if (mockWorkspaces.length > 0 && !mockPollingRef.current) {
|
|
2669
|
+
mockPollingRef.current = setInterval(() => {
|
|
2670
|
+
queryClient.invalidateQueries({ queryKey: ["workspaces"] });
|
|
2671
|
+
rendererRef.current.requestRender();
|
|
2672
|
+
}, 5e3);
|
|
2673
|
+
} else if (mockWorkspaces.length === 0 && mockPollingRef.current) {
|
|
2674
|
+
clearInterval(mockPollingRef.current);
|
|
2675
|
+
mockPollingRef.current = null;
|
|
2676
|
+
}
|
|
2677
|
+
const [mockMessages, setMockMessages] = useState8([]);
|
|
2678
|
+
const [mockThinking, setMockThinking] = useState8(false);
|
|
2679
|
+
const pendingMessageRef = useRef5(/* @__PURE__ */ new Map());
|
|
2680
|
+
const [viewingDiff, setViewingDiff] = useState8(null);
|
|
2681
|
+
const [lastViewedDiff, setLastViewedDiff] = useState8(null);
|
|
2682
|
+
const mockIds = useMemo6(() => new Set(mockWorkspaces.map((m) => m.id)), [mockWorkspaces]);
|
|
2017
2683
|
const isMockSelected = selectedWorkspaceId ? mockIds.has(selectedWorkspaceId) : false;
|
|
2018
2684
|
const { data: workspacesData, isLoading: loadingWorkspaces } = useWorkspaces(1, 100, "organization");
|
|
2019
2685
|
const { data: reposData } = useRepositories();
|
|
@@ -2027,7 +2693,7 @@ function AppInner() {
|
|
|
2027
2693
|
);
|
|
2028
2694
|
const { data: chatsData } = useWorkspaceChats(isMockSelected ? null : selectedWorkspaceId);
|
|
2029
2695
|
const chats = isMockSelected ? MOCK_CHATS : chatsData?.chats ?? [];
|
|
2030
|
-
const resolvedChatId =
|
|
2696
|
+
const resolvedChatId = useMemo6(() => {
|
|
2031
2697
|
if (selectedChatId && chats.find((c) => c.id === selectedChatId)) {
|
|
2032
2698
|
return selectedChatId;
|
|
2033
2699
|
}
|
|
@@ -2045,22 +2711,22 @@ function AppInner() {
|
|
|
2045
2711
|
const deleteWorkspaceMutation = useDeleteWorkspace();
|
|
2046
2712
|
const wakeWorkspaceMutation = useWakeWorkspace();
|
|
2047
2713
|
const generateNameMutation = useGenerateWorkspaceName();
|
|
2048
|
-
const [wakingWorkspaceId, setWakingWorkspaceId] =
|
|
2714
|
+
const [wakingWorkspaceId, setWakingWorkspaceId] = useState8(null);
|
|
2049
2715
|
const sendMessageMutation = useSendChatMessage(selectedWorkspaceId, resolvedChatId);
|
|
2050
2716
|
const interruptMutation = useInterruptChat(selectedWorkspaceId, resolvedChatId);
|
|
2051
2717
|
const workspaces = workspacesData?.workspaces ?? [];
|
|
2052
2718
|
const repositories = reposData?.repositories ?? [];
|
|
2053
2719
|
const repositorySets = setsData?.repository_sets ?? [];
|
|
2054
2720
|
const previews = previewsData?.previews ?? [];
|
|
2055
|
-
const allWorkspaces =
|
|
2056
|
-
const groups =
|
|
2721
|
+
const allWorkspaces = useMemo6(() => [...mockWorkspaces, ...workspaces], [mockWorkspaces, workspaces]);
|
|
2722
|
+
const groups = useMemo6(
|
|
2057
2723
|
() => buildGroups(allWorkspaces, workspacesData, repositories, repositorySets, mockGroupRef.current),
|
|
2058
2724
|
[allWorkspaces, workspacesData, repositories, repositorySets]
|
|
2059
2725
|
);
|
|
2060
2726
|
const selectedWorkspace = allWorkspaces.find((ws) => ws.id === selectedWorkspaceId) ?? null;
|
|
2061
2727
|
const selectedChat = chats.find((c) => c.id === resolvedChatId) ?? null;
|
|
2062
2728
|
const isProcessing = mockThinking || (selectedChat?.processing ?? false);
|
|
2063
|
-
const displayMessages =
|
|
2729
|
+
const displayMessages = useMemo6(() => {
|
|
2064
2730
|
if (isMockSelected) return mockMessages;
|
|
2065
2731
|
const rawEvents = historyData?.events ?? [];
|
|
2066
2732
|
const events = rawEvents.filter(isAgentBackendEvent);
|
|
@@ -2117,30 +2783,30 @@ function AppInner() {
|
|
|
2117
2783
|
}
|
|
2118
2784
|
sendMessageMutation.mutate({ message: pending });
|
|
2119
2785
|
}, [selectedWorkspaceId, resolvedChatId, isMockSelected, statusData?.status]);
|
|
2120
|
-
|
|
2121
|
-
if (mockWorkspaces.length === 0) return;
|
|
2122
|
-
const interval = setInterval(() => {
|
|
2123
|
-
queryClient.invalidateQueries({ queryKey: ["workspaces"] });
|
|
2124
|
-
}, 5e3);
|
|
2125
|
-
return () => clearInterval(interval);
|
|
2126
|
-
}, [mockWorkspaces.length]);
|
|
2127
|
-
const handleSelectWorkspace = useCallback6((workspaceId) => {
|
|
2786
|
+
const handleSelectWorkspace = useCallback7((workspaceId) => {
|
|
2128
2787
|
setSelectedWorkspaceId(workspaceId);
|
|
2129
2788
|
setSelectedChatId(null);
|
|
2130
2789
|
setMockMessages([]);
|
|
2131
2790
|
setMockThinking(false);
|
|
2791
|
+
setViewingDiff(null);
|
|
2792
|
+
setLastViewedDiff(null);
|
|
2132
2793
|
setFocusPanel("chat-input");
|
|
2133
2794
|
}, []);
|
|
2134
|
-
const handleFocus =
|
|
2795
|
+
const handleFocus = useCallback7((panel) => {
|
|
2796
|
+
if (panel === "sidebar") {
|
|
2797
|
+
queryClient.invalidateQueries({ queryKey: ["workspaces"] });
|
|
2798
|
+
}
|
|
2135
2799
|
setFocusPanel(panel);
|
|
2136
2800
|
}, []);
|
|
2137
|
-
const handleCreateWorkspace =
|
|
2801
|
+
const handleCreateWorkspace = useCallback7(
|
|
2138
2802
|
async (groupId, groupType) => {
|
|
2139
2803
|
const orgId = getOrganizationId() ?? "";
|
|
2140
2804
|
const mock = createMockWorkspaceRecord(orgId);
|
|
2141
2805
|
mockGroupRef.current.set(mock.id, groupId);
|
|
2142
2806
|
setMockWorkspaces((prev) => [mock, ...prev]);
|
|
2143
2807
|
setSelectedWorkspaceId(mock.id);
|
|
2808
|
+
setViewingDiff(null);
|
|
2809
|
+
setLastViewedDiff(null);
|
|
2144
2810
|
setFocusPanel("chat-input");
|
|
2145
2811
|
try {
|
|
2146
2812
|
const request = groupType === "set" ? { repository_set_id: groupId.replace(/^set:/, ""), name: mock.name, placeholder: true } : { repository_ids: [groupId], name: mock.name, placeholder: true };
|
|
@@ -2154,18 +2820,26 @@ function AppInner() {
|
|
|
2154
2820
|
},
|
|
2155
2821
|
[createWorkspaceMutation, toast]
|
|
2156
2822
|
);
|
|
2157
|
-
const handleDeleteWorkspace =
|
|
2823
|
+
const handleDeleteWorkspace = useCallback7(
|
|
2158
2824
|
async (workspaceId) => {
|
|
2159
2825
|
if (mockIds.has(workspaceId)) {
|
|
2160
2826
|
mockGroupRef.current.delete(workspaceId);
|
|
2161
2827
|
mockToRealRef.current.delete(workspaceId);
|
|
2162
2828
|
setMockWorkspaces((prev) => prev.filter((m) => m.id !== workspaceId));
|
|
2163
|
-
if (selectedWorkspaceId === workspaceId)
|
|
2829
|
+
if (selectedWorkspaceId === workspaceId) {
|
|
2830
|
+
setSelectedWorkspaceId(null);
|
|
2831
|
+
setViewingDiff(null);
|
|
2832
|
+
setLastViewedDiff(null);
|
|
2833
|
+
}
|
|
2164
2834
|
return;
|
|
2165
2835
|
}
|
|
2166
2836
|
try {
|
|
2167
2837
|
await deleteWorkspaceMutation.mutateAsync(workspaceId);
|
|
2168
|
-
if (selectedWorkspaceId === workspaceId)
|
|
2838
|
+
if (selectedWorkspaceId === workspaceId) {
|
|
2839
|
+
setSelectedWorkspaceId(null);
|
|
2840
|
+
setViewingDiff(null);
|
|
2841
|
+
setLastViewedDiff(null);
|
|
2842
|
+
}
|
|
2169
2843
|
toast.show({ message: "Workspace deleted", variant: "info" });
|
|
2170
2844
|
} catch (err) {
|
|
2171
2845
|
toast.error(err);
|
|
@@ -2173,7 +2847,7 @@ function AppInner() {
|
|
|
2173
2847
|
},
|
|
2174
2848
|
[mockIds, selectedWorkspaceId, deleteWorkspaceMutation]
|
|
2175
2849
|
);
|
|
2176
|
-
const handleWakeWorkspace =
|
|
2850
|
+
const handleWakeWorkspace = useCallback7(
|
|
2177
2851
|
async (workspaceId) => {
|
|
2178
2852
|
setWakingWorkspaceId(workspaceId);
|
|
2179
2853
|
try {
|
|
@@ -2187,10 +2861,10 @@ function AppInner() {
|
|
|
2187
2861
|
},
|
|
2188
2862
|
[wakeWorkspaceMutation, toast]
|
|
2189
2863
|
);
|
|
2190
|
-
const handleSelectChat =
|
|
2864
|
+
const handleSelectChat = useCallback7((chatId) => {
|
|
2191
2865
|
setSelectedChatId(chatId);
|
|
2192
2866
|
}, []);
|
|
2193
|
-
|
|
2867
|
+
useKeyboard5((key) => {
|
|
2194
2868
|
if (key.name === "f12") {
|
|
2195
2869
|
renderer.console.toggle();
|
|
2196
2870
|
return;
|
|
@@ -2210,12 +2884,17 @@ function AppInner() {
|
|
|
2210
2884
|
const availablePanels = FOCUS_ORDER.filter((p) => {
|
|
2211
2885
|
if (p === "sidebar" && !showWorkspacePanel) return false;
|
|
2212
2886
|
if ((p === "chat-tabs" || p === "chat-history" || p === "chat-input") && (!selectedWorkspaceId || statusData?.status === "sleeping")) return false;
|
|
2887
|
+
if (viewingDiff && (p === "chat-tabs" || p === "chat-input")) return false;
|
|
2213
2888
|
if (p === "chat-tabs" && chats.length <= 1) return false;
|
|
2214
2889
|
if (p === "info" && !showInfoPanel) return false;
|
|
2215
2890
|
return true;
|
|
2216
2891
|
});
|
|
2217
2892
|
const idx = availablePanels.indexOf(current);
|
|
2218
|
-
|
|
2893
|
+
const next = availablePanels[(idx + 1) % availablePanels.length];
|
|
2894
|
+
if (next === "sidebar") {
|
|
2895
|
+
queryClient.invalidateQueries({ queryKey: ["workspaces"] });
|
|
2896
|
+
}
|
|
2897
|
+
return next;
|
|
2219
2898
|
});
|
|
2220
2899
|
return;
|
|
2221
2900
|
}
|
|
@@ -2223,6 +2902,15 @@ function AppInner() {
|
|
|
2223
2902
|
setTaskMode((m) => m === "build" ? "plan" : "build");
|
|
2224
2903
|
return;
|
|
2225
2904
|
}
|
|
2905
|
+
if ((key.name === "1" || key.name === "2") && focusPanel !== "chat-input") {
|
|
2906
|
+
if (key.name === "1") {
|
|
2907
|
+
setViewingDiff(null);
|
|
2908
|
+
} else if (firstAvailableDiff) {
|
|
2909
|
+
setViewingDiff(firstAvailableDiff);
|
|
2910
|
+
setLastViewedDiff(firstAvailableDiff);
|
|
2911
|
+
}
|
|
2912
|
+
return;
|
|
2913
|
+
}
|
|
2226
2914
|
if (key.name === "w" && focusPanel !== "sidebar" && focusPanel !== "info" && selectedWorkspaceId) {
|
|
2227
2915
|
if (statusData?.status === "sleeping" && !wakingWorkspaceId) {
|
|
2228
2916
|
handleWakeWorkspace(selectedWorkspaceId);
|
|
@@ -2231,7 +2919,33 @@ function AppInner() {
|
|
|
2231
2919
|
}
|
|
2232
2920
|
if (focusPanel === "chat-input") return;
|
|
2233
2921
|
});
|
|
2234
|
-
const
|
|
2922
|
+
const handleViewDiff = useCallback7((diff, repoName) => {
|
|
2923
|
+
setViewingDiff({ diff, repoName });
|
|
2924
|
+
setLastViewedDiff({ diff, repoName });
|
|
2925
|
+
setFocusPanel("chat-history");
|
|
2926
|
+
}, []);
|
|
2927
|
+
const handleSelectChatMode = useCallback7(() => {
|
|
2928
|
+
setViewingDiff(null);
|
|
2929
|
+
setFocusPanel("chat-history");
|
|
2930
|
+
}, []);
|
|
2931
|
+
const firstAvailableDiff = useMemo6(() => {
|
|
2932
|
+
if (lastViewedDiff) return lastViewedDiff;
|
|
2933
|
+
const repos = statusData?.repoStatuses ?? [];
|
|
2934
|
+
for (const repo of repos) {
|
|
2935
|
+
if (repo.gitDiff?.fullDiff && (repo.gitDiff.added > 0 || repo.gitDiff.removed > 0)) {
|
|
2936
|
+
return { diff: repo.gitDiff.fullDiff, repoName: repo.name };
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
return null;
|
|
2940
|
+
}, [lastViewedDiff, statusData?.repoStatuses]);
|
|
2941
|
+
const handleSelectDiffMode = useCallback7(() => {
|
|
2942
|
+
if (firstAvailableDiff) {
|
|
2943
|
+
setViewingDiff(firstAvailableDiff);
|
|
2944
|
+
setLastViewedDiff(firstAvailableDiff);
|
|
2945
|
+
setFocusPanel("chat-history");
|
|
2946
|
+
}
|
|
2947
|
+
}, [firstAvailableDiff]);
|
|
2948
|
+
const handleSendMessage = useCallback7(
|
|
2235
2949
|
async (message) => {
|
|
2236
2950
|
if (!selectedWorkspaceId || !resolvedChatId) return;
|
|
2237
2951
|
if (isMockSelected) {
|
|
@@ -2248,9 +2962,9 @@ function AppInner() {
|
|
|
2248
2962
|
},
|
|
2249
2963
|
[selectedWorkspaceId, resolvedChatId, isMockSelected, sendMessageMutation, taskMode]
|
|
2250
2964
|
);
|
|
2251
|
-
return /* @__PURE__ */
|
|
2252
|
-
/* @__PURE__ */
|
|
2253
|
-
showWorkspacePanel && /* @__PURE__ */
|
|
2965
|
+
return /* @__PURE__ */ jsxs9("box", { flexDirection: "column", width: "100%", height: "100%", backgroundColor: "#000000", children: [
|
|
2966
|
+
/* @__PURE__ */ jsxs9("box", { flexDirection: "row", flexGrow: 1, backgroundColor: "#000000", children: [
|
|
2967
|
+
showWorkspacePanel && /* @__PURE__ */ jsx11(
|
|
2254
2968
|
WorkspaceSidebar,
|
|
2255
2969
|
{
|
|
2256
2970
|
groups,
|
|
@@ -2265,7 +2979,20 @@ function AppInner() {
|
|
|
2265
2979
|
loading: loadingWorkspaces
|
|
2266
2980
|
}
|
|
2267
2981
|
),
|
|
2268
|
-
|
|
2982
|
+
/* @__PURE__ */ jsx11("box", { flexDirection: "column", flexGrow: 1, children: viewingDiff ? /* @__PURE__ */ jsx11(
|
|
2983
|
+
"box",
|
|
2984
|
+
{
|
|
2985
|
+
flexGrow: 1,
|
|
2986
|
+
border: true,
|
|
2987
|
+
borderStyle: "rounded",
|
|
2988
|
+
borderColor: focusPanel !== "sidebar" && focusPanel !== "info" ? "#66bb6a" : "#333333",
|
|
2989
|
+
backgroundColor: "#000000",
|
|
2990
|
+
flexDirection: "column",
|
|
2991
|
+
title: "Diff",
|
|
2992
|
+
titleAlignment: "center",
|
|
2993
|
+
children: /* @__PURE__ */ jsx11(DiffViewer, { diff: viewingDiff.diff, repoName: viewingDiff.repoName, focused: focusPanel !== "sidebar" && focusPanel !== "info" })
|
|
2994
|
+
}
|
|
2995
|
+
) : selectedWorkspaceId && statusData?.status !== "sleeping" ? /* @__PURE__ */ jsx11(
|
|
2269
2996
|
ChatArea,
|
|
2270
2997
|
{
|
|
2271
2998
|
chats,
|
|
@@ -2279,7 +3006,7 @@ function AppInner() {
|
|
|
2279
3006
|
isProcessing,
|
|
2280
3007
|
loading: loadingMessages
|
|
2281
3008
|
}
|
|
2282
|
-
) : selectedWorkspaceId && statusData?.status === "sleeping" ? /* @__PURE__ */
|
|
3009
|
+
) : selectedWorkspaceId && statusData?.status === "sleeping" ? /* @__PURE__ */ jsxs9(
|
|
2283
3010
|
"box",
|
|
2284
3011
|
{
|
|
2285
3012
|
flexGrow: 1,
|
|
@@ -2292,18 +3019,18 @@ function AppInner() {
|
|
|
2292
3019
|
flexDirection: "column",
|
|
2293
3020
|
gap: 1,
|
|
2294
3021
|
children: [
|
|
2295
|
-
/* @__PURE__ */
|
|
3022
|
+
/* @__PURE__ */ jsxs9("text", { fg: "#888888", children: [
|
|
2296
3023
|
"\u263E",
|
|
2297
3024
|
" This workspace is sleeping"
|
|
2298
3025
|
] }),
|
|
2299
|
-
/* @__PURE__ */
|
|
3026
|
+
/* @__PURE__ */ jsxs9("text", { fg: "#555555", children: [
|
|
2300
3027
|
"Press ",
|
|
2301
|
-
/* @__PURE__ */
|
|
3028
|
+
/* @__PURE__ */ jsx11("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx11("strong", { children: "w" }) }),
|
|
2302
3029
|
" to wake it up"
|
|
2303
3030
|
] })
|
|
2304
3031
|
]
|
|
2305
3032
|
}
|
|
2306
|
-
) : /* @__PURE__ */
|
|
3033
|
+
) : /* @__PURE__ */ jsx11(
|
|
2307
3034
|
"box",
|
|
2308
3035
|
{
|
|
2309
3036
|
flexGrow: 1,
|
|
@@ -2313,10 +3040,10 @@ function AppInner() {
|
|
|
2313
3040
|
backgroundColor: "#000000",
|
|
2314
3041
|
justifyContent: "center",
|
|
2315
3042
|
alignItems: "center",
|
|
2316
|
-
children: /* @__PURE__ */
|
|
3043
|
+
children: /* @__PURE__ */ jsx11("text", { fg: "#555555", children: "Create a workspace to begin building!" })
|
|
2317
3044
|
}
|
|
2318
|
-
),
|
|
2319
|
-
showInfoPanel && /* @__PURE__ */
|
|
3045
|
+
) }),
|
|
3046
|
+
showInfoPanel && /* @__PURE__ */ jsx11(
|
|
2320
3047
|
WorkspaceInfo,
|
|
2321
3048
|
{
|
|
2322
3049
|
status: statusData ?? null,
|
|
@@ -2331,31 +3058,38 @@ function AppInner() {
|
|
|
2331
3058
|
},
|
|
2332
3059
|
previews,
|
|
2333
3060
|
onWakeWorkspace: handleWakeWorkspace,
|
|
3061
|
+
onViewDiff: handleViewDiff,
|
|
2334
3062
|
onCreatePr: () => {
|
|
2335
3063
|
if (!resolvedChatId) return;
|
|
2336
3064
|
sendMessageMutation.mutate({ message: "Push changes and create a GitHub PR" });
|
|
2337
3065
|
},
|
|
2338
3066
|
isPlanMode: taskMode === "plan",
|
|
2339
|
-
wakingWorkspaceId
|
|
3067
|
+
wakingWorkspaceId,
|
|
3068
|
+
viewMode: viewingDiff ? "diff" : "chat",
|
|
3069
|
+
viewingDiffRepoName: viewingDiff?.repoName ?? null,
|
|
3070
|
+
onSelectChatMode: handleSelectChatMode,
|
|
3071
|
+
onSelectDiffMode: handleSelectDiffMode
|
|
2340
3072
|
}
|
|
2341
3073
|
)
|
|
2342
3074
|
] }),
|
|
2343
|
-
/* @__PURE__ */
|
|
3075
|
+
/* @__PURE__ */ jsx11(
|
|
2344
3076
|
StatusBar,
|
|
2345
3077
|
{
|
|
2346
|
-
focusPanel
|
|
3078
|
+
focusPanel,
|
|
3079
|
+
viewingDiff: !!viewingDiff,
|
|
3080
|
+
hasDiffAvailable: !!firstAvailableDiff
|
|
2347
3081
|
}
|
|
2348
3082
|
)
|
|
2349
3083
|
] });
|
|
2350
3084
|
}
|
|
2351
3085
|
|
|
2352
3086
|
// src/interactive/index.tsx
|
|
2353
|
-
import { jsx as
|
|
3087
|
+
import { jsx as jsx12 } from "@opentui/react/jsx-runtime";
|
|
2354
3088
|
async function launchInteractive() {
|
|
2355
3089
|
const renderer = await createCliRenderer({
|
|
2356
3090
|
exitOnCtrlC: false
|
|
2357
3091
|
});
|
|
2358
|
-
createRoot(renderer).render(/* @__PURE__ */
|
|
3092
|
+
createRoot(renderer).render(/* @__PURE__ */ jsx12(App, {}));
|
|
2359
3093
|
}
|
|
2360
3094
|
export {
|
|
2361
3095
|
launchInteractive
|