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