@cueloop/client 0.1.0-alpha.42 → 0.1.0-alpha.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/native/build-pty.sh +51 -0
- package/native/darwin-arm64/libcuelooppty.dylib +0 -0
- package/native/src/pty.zig +193 -0
- package/package.json +5 -6
- package/src/App.plan-review.test.tsx +58 -32
- package/src/components/AnnotationCard.stories.tsx +6 -2
- package/src/components/AnnotationCard.tsx +7 -3
- package/src/components/ConfirmCard.tsx +1 -1
- package/src/components/ReviewRail.tsx +5 -5
- package/src/components/__snapshots__/stories.test.tsx.snap +146 -146
- package/src/components/agent-launcher.stories.tsx +1 -1
- package/src/components/agent-launcher.test.tsx +32 -4
- package/src/components/agent-launcher.tsx +21 -54
- package/src/components/primitives/Button.tsx +4 -1
- package/src/components/terminal-pane.ts +15 -8
- package/src/key-bindings.ts +6 -0
- package/src/pty.test.ts +78 -0
- package/src/pty.ts +222 -0
- package/src/theme.ts +2 -2
|
@@ -849,17 +849,17 @@ exports[`stories catalog ReviewPanel/Compact renders, snapshots, and carries its
|
|
|
849
849
|
`;
|
|
850
850
|
|
|
851
851
|
exports[`stories catalog ReviewPanel/ExpandedNarrow renders, snapshots, and carries its colors: ReviewPanel/ExpandedNarrow 1`] = `
|
|
852
|
-
" The plan takes the width the panel hands back.
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
852
|
+
" The plan takes the width the panel hands back. ╭──────────────────────╮
|
|
853
|
+
│ Review Agent │
|
|
854
|
+
╰──────────────────────╯
|
|
855
|
+
╭─ COMMENT · me ───────╮
|
|
856
|
+
│ Whichidaemonsownss" │
|
|
857
|
+
│ this? │
|
|
858
|
+
╰──────────────────────╯
|
|
859
|
+
╭─ COMMENT · me ───────╮
|
|
860
|
+
│ moveetheestoree" │
|
|
861
|
+
│ behind o… │
|
|
862
|
+
╰──────────────────────╯
|
|
863
863
|
|
|
864
864
|
|
|
865
865
|
|
|
@@ -871,23 +871,23 @@ exports[`stories catalog ReviewPanel/ExpandedNarrow renders, snapshots, and carr
|
|
|
871
871
|
|
|
872
872
|
|
|
873
873
|
|
|
874
|
-
|
|
874
|
+
> Submit review
|
|
875
875
|
|
|
876
876
|
"
|
|
877
877
|
`;
|
|
878
878
|
|
|
879
879
|
exports[`stories catalog ReviewPanel/ExpandedWide renders, snapshots, and carries its colors: ReviewPanel/ExpandedWide 1`] = `
|
|
880
|
-
" The plan takes the width the panel
|
|
881
|
-
hands back.
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
880
|
+
" The plan takes the width the panel ╭────────────────────────────────────────────────╮
|
|
881
|
+
hands back. │ Review Agent │
|
|
882
|
+
╰────────────────────────────────────────────────╯
|
|
883
|
+
╭─ COMMENT · me ─────────────────────────────────╮
|
|
884
|
+
│ "persists sessions" │
|
|
885
|
+
│ Which daemon owns this? │
|
|
886
|
+
╰────────────────────────────────────────────────╯
|
|
887
|
+
╭─ COMMENT · me ─────────────────────────────────╮
|
|
888
|
+
│ "move the store" │
|
|
889
|
+
│ move the store behind o… │
|
|
890
|
+
╰────────────────────────────────────────────────╯
|
|
891
891
|
|
|
892
892
|
|
|
893
893
|
|
|
@@ -899,7 +899,7 @@ exports[`stories catalog ReviewPanel/ExpandedWide renders, snapshots, and carrie
|
|
|
899
899
|
|
|
900
900
|
|
|
901
901
|
|
|
902
|
-
|
|
902
|
+
> Submit review
|
|
903
903
|
|
|
904
904
|
"
|
|
905
905
|
`;
|
|
@@ -933,45 +933,45 @@ exports[`stories catalog ReviewPanel/Hidden renders, snapshots, and carries its
|
|
|
933
933
|
`;
|
|
934
934
|
|
|
935
935
|
exports[`stories catalog ReviewRail/AgentTab renders, snapshots, and carries its colors: ReviewRail/AgentTab 1`] = `
|
|
936
|
-
"
|
|
937
|
-
|
|
938
|
-
|
|
936
|
+
"╭────────────────────────────────╮
|
|
937
|
+
│ Review Agent │
|
|
938
|
+
╰────────────────────────────────╯
|
|
939
|
+
╭────────────────────────────────╮
|
|
940
|
+
│ Claude Code │
|
|
941
|
+
╰────────────────────────────────╯
|
|
942
|
+
╭────────────────────────────────╮
|
|
943
|
+
│ Pi │
|
|
944
|
+
╰────────────────────────────────╯
|
|
945
|
+
╭────────────────────────────────╮
|
|
946
|
+
│ OpenAI Codex │
|
|
947
|
+
╰────────────────────────────────╯
|
|
948
|
+
plan context: seed the plan
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
939
956
|
|
|
940
|
-
Ask an agent about this plan
|
|
941
|
-
╭─────────────────────────────╮
|
|
942
|
-
│ ▛████▜ claude code │
|
|
943
|
-
│ ▜██████▛ launch in rail ▸ │
|
|
944
|
-
│ ▝▝ ▝▝ │
|
|
945
|
-
╰─────────────────────────────╯
|
|
946
957
|
|
|
947
|
-
╭─────────────────────────────╮
|
|
948
|
-
│ ███ pi │
|
|
949
|
-
│ █ █ launch in rail ▸ │
|
|
950
|
-
│ ██ █ │
|
|
951
|
-
│ █ █ │
|
|
952
|
-
╰─────────────────────────────╯
|
|
953
958
|
|
|
954
|
-
╭─────────────────────────────╮
|
|
955
|
-
│ ┌───┐ codex │
|
|
956
|
-
│ │>_ │ launch in rail ▸ │
|
|
957
|
-
│ └───┘ │
|
|
958
|
-
╰─────────────────────────────╯
|
|
959
959
|
|
|
960
960
|
"
|
|
961
961
|
`;
|
|
962
962
|
|
|
963
963
|
exports[`stories catalog ReviewRail/AnnotationStack renders, snapshots, and carries its colors: ReviewRail/AnnotationStack 1`] = `
|
|
964
|
-
"
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
964
|
+
"╭────────────────────────────────╮
|
|
965
|
+
│ Review Agent │
|
|
966
|
+
╰────────────────────────────────╯
|
|
967
|
+
╭─ COMMENT · me ─────────────────╮
|
|
968
|
+
│ "persists sessions" │
|
|
969
|
+
│ Which daemon owns this? │
|
|
970
|
+
╰────────────────────────────────╯
|
|
971
|
+
╭─ COMMENT · me ─────────────────╮
|
|
972
|
+
│ "move the store" │
|
|
973
|
+
│ move the store behind o… │
|
|
974
|
+
╰────────────────────────────────╯
|
|
975
975
|
|
|
976
976
|
|
|
977
977
|
|
|
@@ -983,26 +983,26 @@ exports[`stories catalog ReviewRail/AnnotationStack renders, snapshots, and carr
|
|
|
983
983
|
|
|
984
984
|
|
|
985
985
|
|
|
986
|
-
|
|
986
|
+
Submit review
|
|
987
987
|
|
|
988
988
|
"
|
|
989
989
|
`;
|
|
990
990
|
|
|
991
991
|
exports[`stories catalog ReviewRail/InterleavedStack renders, snapshots, and carries its colors: ReviewRail/InterleavedStack 1`] = `
|
|
992
|
-
"
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
992
|
+
"╭────────────────────────────────╮
|
|
993
|
+
│ Review Agent │
|
|
994
|
+
╰────────────────────────────────╯
|
|
995
|
+
╭─ CUT · me ─────────────────────╮
|
|
996
|
+
│ - add recovery │
|
|
997
|
+
╰────────────────────────────────╯
|
|
998
|
+
╭─ COMMENT · me ─────────────────╮
|
|
999
|
+
│ "persists sessions" │
|
|
1000
|
+
│ Which daemon owns this? │
|
|
1001
|
+
╰────────────────────────────────╯
|
|
1002
|
+
╭─ COMMENT · me ─────────────────╮
|
|
1003
|
+
│ "move the store" │
|
|
1004
|
+
│ move the store behind o… │
|
|
1005
|
+
╰────────────────────────────────╯
|
|
1006
1006
|
|
|
1007
1007
|
|
|
1008
1008
|
|
|
@@ -1011,23 +1011,23 @@ exports[`stories catalog ReviewRail/InterleavedStack renders, snapshots, and car
|
|
|
1011
1011
|
|
|
1012
1012
|
|
|
1013
1013
|
|
|
1014
|
-
|
|
1014
|
+
Submit review
|
|
1015
1015
|
|
|
1016
1016
|
"
|
|
1017
1017
|
`;
|
|
1018
1018
|
|
|
1019
1019
|
exports[`stories catalog ReviewRail/MixedOwnershipStack renders, snapshots, and carries its colors: ReviewRail/MixedOwnershipStack 1`] = `
|
|
1020
|
-
"
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1020
|
+
"╭────────────────────────────────╮
|
|
1021
|
+
│ Review Agent │
|
|
1022
|
+
╰────────────────────────────────╯
|
|
1023
|
+
╭─ COMMENT · me ─────────────────╮
|
|
1024
|
+
│ "persists sessions" │
|
|
1025
|
+
│ Which daemon owns this? │
|
|
1026
|
+
╰────────────────────────────────╯
|
|
1027
|
+
╭─ COMMENT · Priya ──────────────╮
|
|
1028
|
+
│ "move the store" │
|
|
1029
|
+
│ move it behind one inte… │
|
|
1030
|
+
╰────────────────────────────────╯
|
|
1031
1031
|
|
|
1032
1032
|
|
|
1033
1033
|
|
|
@@ -1039,25 +1039,25 @@ exports[`stories catalog ReviewRail/MixedOwnershipStack renders, snapshots, and
|
|
|
1039
1039
|
|
|
1040
1040
|
|
|
1041
1041
|
|
|
1042
|
-
|
|
1042
|
+
Submit review
|
|
1043
1043
|
|
|
1044
1044
|
"
|
|
1045
1045
|
`;
|
|
1046
1046
|
|
|
1047
1047
|
exports[`stories catalog ReviewRail/Removals renders, snapshots, and carries its colors: ReviewRail/Removals 1`] = `
|
|
1048
|
-
"
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1048
|
+
"╭────────────────────────────────╮
|
|
1049
|
+
│ Review Agent │
|
|
1050
|
+
╰────────────────────────────────╯
|
|
1051
|
+
╭─ REJECT · me ──────────────────╮
|
|
1052
|
+
│ - private items = []; │
|
|
1053
|
+
│ + private items = new… │
|
|
1054
|
+
│ undo │
|
|
1055
|
+
╰────────────────────────────────╯
|
|
1056
|
+
╭─ REJECT · me ──────────────────╮
|
|
1057
|
+
│ - return null; │
|
|
1058
|
+
│ + return fallback(); │
|
|
1059
|
+
│ + log(fallback); │
|
|
1060
|
+
╰────────────────────────────────╯
|
|
1061
1061
|
|
|
1062
1062
|
|
|
1063
1063
|
|
|
@@ -1067,23 +1067,23 @@ exports[`stories catalog ReviewRail/Removals renders, snapshots, and carries its
|
|
|
1067
1067
|
|
|
1068
1068
|
|
|
1069
1069
|
|
|
1070
|
-
|
|
1070
|
+
Submit review
|
|
1071
1071
|
|
|
1072
1072
|
"
|
|
1073
1073
|
`;
|
|
1074
1074
|
|
|
1075
1075
|
exports[`stories catalog ReviewRail/Resolved renders, snapshots, and carries its colors: ReviewRail/Resolved 1`] = `
|
|
1076
|
-
"
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1076
|
+
"╭────────────────────────────────╮
|
|
1077
|
+
│ Review Agent │
|
|
1078
|
+
╰────────────────────────────────╯
|
|
1079
|
+
╭─ COMMENT · me · ORPHANED ──────╮
|
|
1080
|
+
│ "persists sessions" │
|
|
1081
|
+
│ Which daemon owns this? │
|
|
1082
|
+
╰────────────────────────────────╯
|
|
1083
|
+
╭─ COMMENT · me · ORPHANED ──────╮
|
|
1084
|
+
│ "move the store" │
|
|
1085
|
+
│ move the store behind o… │
|
|
1086
|
+
╰────────────────────────────────╯
|
|
1087
1087
|
|
|
1088
1088
|
|
|
1089
1089
|
|
|
@@ -1095,23 +1095,23 @@ exports[`stories catalog ReviewRail/Resolved renders, snapshots, and carries its
|
|
|
1095
1095
|
|
|
1096
1096
|
|
|
1097
1097
|
|
|
1098
|
-
|
|
1098
|
+
resolved: approve
|
|
1099
1099
|
|
|
1100
1100
|
"
|
|
1101
1101
|
`;
|
|
1102
1102
|
|
|
1103
1103
|
exports[`stories catalog ReviewRail/SubmitConfirmOpen renders, snapshots, and carries its colors: ReviewRail/SubmitConfirmOpen 1`] = `
|
|
1104
|
-
"
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1104
|
+
"╭────────────────────────────────╮
|
|
1105
|
+
│ Review Agent │
|
|
1106
|
+
╰────────────────────────────────╯
|
|
1107
|
+
╭─ COMMENT · me · ORPHANED ──────╮
|
|
1108
|
+
│ "persists sessions" │
|
|
1109
|
+
│ Which daemon owns this? │
|
|
1110
|
+
╰────────────────────────────────╯
|
|
1111
|
+
╭─ COMMENT · me · ORPHANED ──────╮
|
|
1112
|
+
│ "move the store" │
|
|
1113
|
+
│ move the store behind o… │
|
|
1114
|
+
╰────────────────────────────────╯
|
|
1115
1115
|
|
|
1116
1116
|
|
|
1117
1117
|
|
|
@@ -1121,15 +1121,15 @@ exports[`stories catalog ReviewRail/SubmitConfirmOpen renders, snapshots, and ca
|
|
|
1121
1121
|
|
|
1122
1122
|
|
|
1123
1123
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1124
|
+
╭─ submit review ───────────────╮
|
|
1125
|
+
│ 2 annotations · 0 blocking │
|
|
1126
|
+
│ │
|
|
1127
|
+
│ Comment Approve [Changes] │
|
|
1128
|
+
│ │
|
|
1129
|
+
│ summary for the agent (optiona│
|
|
1130
|
+
│ │
|
|
1131
|
+
│ Submit Cancel │
|
|
1132
|
+
╰───────────────────────────────╯
|
|
1133
1133
|
|
|
1134
1134
|
"
|
|
1135
1135
|
`;
|
|
@@ -1393,30 +1393,30 @@ exports[`stories catalog WalkWizard/WithAgentNote renders, snapshots, and carrie
|
|
|
1393
1393
|
`;
|
|
1394
1394
|
|
|
1395
1395
|
exports[`stories catalog AgentLauncher/Launcher renders, snapshots, and carries its colors: AgentLauncher/Launcher 1`] = `
|
|
1396
|
-
"
|
|
1397
|
-
|
|
1398
|
-
╭────────────────────────────────────╮
|
|
1399
|
-
│ ▛████▜ claude code │
|
|
1400
|
-
│ ▜██████▛ launch in rail ▸ │
|
|
1401
|
-
│ ▝▝ ▝▝ │
|
|
1396
|
+
" ╭────────────────────────────────────╮
|
|
1397
|
+
│ Claude Code │
|
|
1402
1398
|
╰────────────────────────────────────╯
|
|
1403
|
-
|
|
1404
1399
|
╭────────────────────────────────────╮
|
|
1405
|
-
│
|
|
1406
|
-
│ █ █ launch in rail ▸ │
|
|
1407
|
-
│ ██ █ │
|
|
1408
|
-
│ █ █ │
|
|
1400
|
+
│ Pi │
|
|
1409
1401
|
╰────────────────────────────────────╯
|
|
1410
|
-
|
|
1411
1402
|
╭────────────────────────────────────╮
|
|
1412
|
-
│
|
|
1413
|
-
│ │>_ │ launch in rail ▸ │
|
|
1414
|
-
│ └───┘ │
|
|
1403
|
+
│ OpenAI Codex │
|
|
1415
1404
|
╰────────────────────────────────────╯
|
|
1405
|
+
plan context: seed the plan
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
|
|
1416
1418
|
|
|
1417
|
-
plan context: seed the plan ▸
|
|
1418
1419
|
|
|
1419
|
-
agent/worker-3 · pending · rev 1
|
|
1420
1420
|
"
|
|
1421
1421
|
`;
|
|
1422
1422
|
|
|
@@ -21,6 +21,6 @@ export const Launcher: Story = {
|
|
|
21
21
|
<AgentLauncher session={fixturePlanSession()} onLaunchHarness={() => {}} theme={DARK} />
|
|
22
22
|
</RailFrame>
|
|
23
23
|
),
|
|
24
|
-
expectedColors: [DARK.accent
|
|
24
|
+
expectedColors: [DARK.accent],
|
|
25
25
|
size: { width: 40, height: 24 },
|
|
26
26
|
};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { testRender } from "@opentui/react/test-utils";
|
|
4
|
+
import { DARK } from "../theme";
|
|
5
|
+
import { fixturePlanSession } from "./story-fixtures";
|
|
6
|
+
import { waitForText } from "../test-support";
|
|
7
|
+
import { AgentLauncher, HARNESS_LAUNCHERS, planHandoffBriefing } from "./agent-launcher";
|
|
3
8
|
|
|
4
9
|
describe("planHandoffBriefing", () => {
|
|
5
10
|
test("references the session by id and directs the agent to read then annotate, not rewrite", () => {
|
|
@@ -14,8 +19,31 @@ describe("planHandoffBriefing", () => {
|
|
|
14
19
|
});
|
|
15
20
|
|
|
16
21
|
describe("HARNESS_LAUNCHERS", () => {
|
|
17
|
-
test("carries the three
|
|
18
|
-
// Assert
|
|
19
|
-
|
|
22
|
+
test("carries the three harnesses with real binary commands (never the `cc` alias)", () => {
|
|
23
|
+
// Assert - `cc` resolves to the system C compiler when spawned on a PTY, so
|
|
24
|
+
// the Claude harness must run `claude`, the real binary, not the shell alias
|
|
25
|
+
expect(HARNESS_LAUNCHERS.map((harness) => harness.command)).toEqual(["claude", "pi", "codex"]);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("AgentLauncher", () => {
|
|
30
|
+
test("renders a button for every harness, in order", async () => {
|
|
31
|
+
// Arrange
|
|
32
|
+
const setup = await testRender(
|
|
33
|
+
<box style={{ width: 44, height: 20, flexDirection: "column" }}>
|
|
34
|
+
<AgentLauncher session={fixturePlanSession()} onLaunchHarness={() => {}} theme={DARK} />
|
|
35
|
+
</box>,
|
|
36
|
+
{ width: 44, height: 20 },
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Act
|
|
40
|
+
await waitForText(setup, "Claude Code");
|
|
41
|
+
const frame = setup.captureCharFrame();
|
|
42
|
+
|
|
43
|
+
// Assert - all three launcher names present, in launch order
|
|
44
|
+
const names = HARNESS_LAUNCHERS.map((harness) => harness.name);
|
|
45
|
+
const positions = names.map((name) => frame.indexOf(name));
|
|
46
|
+
expect(positions.every((position) => position >= 0)).toBe(true);
|
|
47
|
+
expect(positions).toEqual(positions.toSorted((left, right) => left - right));
|
|
20
48
|
});
|
|
21
49
|
});
|
|
@@ -24,38 +24,24 @@ export interface AgentTerminalHandle {
|
|
|
24
24
|
detach: () => void;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/** One launchable harness: its
|
|
27
|
+
/** One launchable harness: its display name and the rail command. */
|
|
28
28
|
export interface HarnessLauncher {
|
|
29
29
|
id: string;
|
|
30
30
|
name: string;
|
|
31
31
|
/** The shell command that starts the harness, run in the split. */
|
|
32
32
|
command: string;
|
|
33
|
-
/** Brand color for the mark. */
|
|
34
|
-
color: string;
|
|
35
|
-
/** Multi-row mark rendered from the real logo. */
|
|
36
|
-
logo: string[];
|
|
37
33
|
}
|
|
38
34
|
|
|
39
|
-
/**
|
|
40
|
-
const
|
|
35
|
+
/** Off-white for the running-terminal header, shared by every harness. */
|
|
36
|
+
const HARNESS_HEADER_COLOR = "#e4e6ec";
|
|
41
37
|
|
|
42
|
-
/** The bring-your-own harnesses,
|
|
38
|
+
/** The bring-your-own harnesses, in launch order. The command is the real binary
|
|
39
|
+
* name spawned on a PTY (not a shell alias, so `claude` - never `cc`, which is
|
|
40
|
+
* the system C compiler). */
|
|
43
41
|
export const HARNESS_LAUNCHERS: HarnessLauncher[] = [
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
command: "cc",
|
|
48
|
-
color: CLAUDE_CORAL,
|
|
49
|
-
logo: [" ▛████▜", "▜██████▛", " ▝▝ ▝▝"],
|
|
50
|
-
},
|
|
51
|
-
{ id: "pi", name: "pi", command: "pi", color: "#e4e6ec", logo: ["███ ", "█ █ ", "██ █", "█ █"] },
|
|
52
|
-
{
|
|
53
|
-
id: "codex",
|
|
54
|
-
name: "codex",
|
|
55
|
-
command: "codex",
|
|
56
|
-
color: "#e4e6ec",
|
|
57
|
-
logo: ["┌───┐", "│>_ │", "└───┘"],
|
|
58
|
-
},
|
|
42
|
+
{ id: "claude", name: "Claude Code", command: "claude" },
|
|
43
|
+
{ id: "pi", name: "Pi", command: "pi" },
|
|
44
|
+
{ id: "codex", name: "OpenAI Codex", command: "codex" },
|
|
59
45
|
];
|
|
60
46
|
|
|
61
47
|
/** The briefing typed into a launched harness when the plan-context toggle is on. */
|
|
@@ -63,18 +49,6 @@ export function planHandoffBriefing(sessionId: string): string {
|
|
|
63
49
|
return `Review this cueloop plan: read it with 'cueloop session get ${sessionId}', then comment with 'cueloop session annotate ${sessionId} --author me --quote "<exact span>" --body "<comment>"'. Do not rewrite the plan.`;
|
|
64
50
|
}
|
|
65
51
|
|
|
66
|
-
function LogoMark({ harness }: { harness: HarnessLauncher }): React.ReactNode {
|
|
67
|
-
return (
|
|
68
|
-
<box style={{ width: 9, flexShrink: 0, flexDirection: "column", alignItems: "flex-start" }}>
|
|
69
|
-
{harness.logo.map((row) => (
|
|
70
|
-
<text key={row} fg={harness.color}>
|
|
71
|
-
{row}
|
|
72
|
-
</text>
|
|
73
|
-
))}
|
|
74
|
-
</box>
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
52
|
/** Props for the Agent tab body: the session under review plus the launch callbacks. */
|
|
79
53
|
export interface AgentLauncherProps {
|
|
80
54
|
session: ReviewSession;
|
|
@@ -110,7 +84,12 @@ export function AgentLauncher({
|
|
|
110
84
|
if (embeddedTerminalAvailable()) setRunning({ harness, seed });
|
|
111
85
|
else onLaunchHarness(harness.command, seed);
|
|
112
86
|
};
|
|
113
|
-
const detach = (): void =>
|
|
87
|
+
const detach = (): void => {
|
|
88
|
+
// The reconciler's removeChild detaches the pane without destroying it, so
|
|
89
|
+
// kill the child + free the VT here or they leak. shutdown() is idempotent.
|
|
90
|
+
paneRef.current?.shutdown();
|
|
91
|
+
setRunning(null);
|
|
92
|
+
};
|
|
114
93
|
|
|
115
94
|
useEffect(() => {
|
|
116
95
|
if (!running) return onAgentTerminal?.(null);
|
|
@@ -123,9 +102,9 @@ export function AgentLauncher({
|
|
|
123
102
|
return (
|
|
124
103
|
<box style={{ flexDirection: "column", flexGrow: 1 }}>
|
|
125
104
|
<box style={{ flexDirection: "row" }} onMouseUp={detach}>
|
|
126
|
-
<text fg={
|
|
105
|
+
<text fg={HARNESS_HEADER_COLOR}>{running.harness.name}</text>
|
|
127
106
|
<box style={{ flexGrow: 1 }} />
|
|
128
|
-
<text fg={tokens.textDim}>✕ detach
|
|
107
|
+
<text fg={tokens.textDim}>✕ detach</text>
|
|
129
108
|
</box>
|
|
130
109
|
{React.createElement("terminalPane", {
|
|
131
110
|
ref: paneRef,
|
|
@@ -141,40 +120,28 @@ export function AgentLauncher({
|
|
|
141
120
|
|
|
142
121
|
return (
|
|
143
122
|
<box style={{ flexDirection: "column", flexGrow: 1 }}>
|
|
144
|
-
<text fg={tokens.text}>Ask an agent about this plan</text>
|
|
145
|
-
<box style={{ height: 1 }} />
|
|
146
123
|
{HARNESS_LAUNCHERS.map((harness) => (
|
|
147
124
|
<box
|
|
148
125
|
key={harness.id}
|
|
149
126
|
style={{
|
|
150
127
|
flexDirection: "row",
|
|
151
|
-
height:
|
|
128
|
+
height: 3,
|
|
152
129
|
border: true,
|
|
153
130
|
borderStyle: FRAME_BORDER_STYLE,
|
|
154
131
|
backgroundColor: "transparent",
|
|
155
|
-
borderColor: tokens.
|
|
156
|
-
marginBottom: 1,
|
|
132
|
+
borderColor: tokens.text,
|
|
157
133
|
paddingLeft: 1,
|
|
158
134
|
paddingRight: 1,
|
|
159
135
|
}}
|
|
160
136
|
onMouseUp={() => launch(harness)}
|
|
161
137
|
>
|
|
162
|
-
<
|
|
163
|
-
<box style={{ flexDirection: "column", flexGrow: 1, paddingLeft: 1 }}>
|
|
164
|
-
<text fg={tokens.textMuted}>{harness.name}</text>
|
|
165
|
-
<text fg={tokens.textDim}>launch in rail ▸</text>
|
|
166
|
-
</box>
|
|
138
|
+
<text fg={tokens.textMuted}>{harness.name}</text>
|
|
167
139
|
</box>
|
|
168
140
|
))}
|
|
169
141
|
<box style={{ flexDirection: "row" }} onMouseUp={() => setSeedContext((on) => !on)}>
|
|
170
142
|
<text fg={tokens.textDim}>plan context: </text>
|
|
171
|
-
<text fg={tokens.accent}>{seedContext ? "seed the plan
|
|
143
|
+
<text fg={tokens.accent}>{seedContext ? "seed the plan" : "none"}</text>
|
|
172
144
|
</box>
|
|
173
|
-
<box style={{ flexGrow: 1 }} />
|
|
174
|
-
<text fg={tokens.textDim}>
|
|
175
|
-
{session.artifact.meta.agent ?? "unknown"} · {session.status} · rev{" "}
|
|
176
|
-
{session.revisions.length}
|
|
177
|
-
</text>
|
|
178
145
|
</box>
|
|
179
146
|
);
|
|
180
147
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React from "react";
|
|
8
|
+
import type { MouseEvent } from "@opentui/core";
|
|
8
9
|
import type { Theme } from "../../theme";
|
|
9
10
|
import { useComponentTheme } from "../theme-context";
|
|
10
11
|
|
|
@@ -38,7 +39,9 @@ export function Button({
|
|
|
38
39
|
return (
|
|
39
40
|
<box
|
|
40
41
|
style={{ backgroundColor, marginRight }}
|
|
41
|
-
onMouseUp={() => {
|
|
42
|
+
onMouseUp={(event: MouseEvent) => {
|
|
43
|
+
// Consume the press so it never bubbles to an ancestor's onMouseUp (e.g. a card).
|
|
44
|
+
event.stopPropagation();
|
|
42
45
|
if (!isDisabled) onPress();
|
|
43
46
|
}}
|
|
44
47
|
>
|