replicas-cli 0.2.41 → 0.2.43

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.
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  import {
3
+ SOURCE_CONFIG,
3
4
  buildGroups,
4
5
  createMockWorkspaceRecord,
5
6
  createUserMessage,
@@ -8,16 +9,17 @@ import {
8
9
  getOrganizationId,
9
10
  getValidToken,
10
11
  isAgentBackendEvent,
11
- parseAgentEvents
12
- } from "./chunk-IO4QHXPW.mjs";
12
+ parseAgentEvents,
13
+ parseUserMessage
14
+ } from "./chunk-D6VVVHKH.mjs";
13
15
 
14
16
  // src/interactive/index.tsx
15
17
  import { createCliRenderer } from "@opentui/core";
16
18
  import { createRoot } from "@opentui/react";
17
19
 
18
20
  // src/interactive/App.tsx
19
- import { useState as useState5, useEffect as useEffect3, useMemo as useMemo3, useCallback as useCallback5, useRef as useRef3 } from "react";
20
- import { useKeyboard as useKeyboard3, useRenderer, useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
21
+ import { useState as useState7, useEffect as useEffect3, useMemo as useMemo5, useCallback as useCallback6, useRef as useRef3 } from "react";
22
+ import { useKeyboard as useKeyboard4, useRenderer, useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
21
23
  import { QueryClient } from "@tanstack/react-query";
22
24
 
23
25
  // ../shared/src/hooks/auth-context.ts
@@ -488,7 +490,7 @@ var KEYBINDS = {
488
490
  "chat-tabs": "\u2190/\u2192 switch tabs",
489
491
  "chat-history": "j/k scroll",
490
492
  "chat-input": "\u21B5 send \u21E5 plan/build",
491
- info: "j/k scroll o dashboard w wake"
493
+ info: "j/k nav \u21B5 open o dashboard w wake"
492
494
  };
493
495
  function StatusBar({ focusPanel }) {
494
496
  return /* @__PURE__ */ jsxs(
@@ -852,7 +854,7 @@ import { useRef, useEffect as useEffect2 } from "react";
852
854
  import { useKeyboard as useKeyboard2 } from "@opentui/react";
853
855
 
854
856
  // src/interactive/components/ChatMessage.tsx
855
- import { useState as useState3 } from "react";
857
+ import { useState as useState4, useMemo as useMemo3 } from "react";
856
858
  import { SyntaxStyle } from "@opentui/core";
857
859
 
858
860
  // src/interactive/components/Spinner.tsx
@@ -867,8 +869,178 @@ function SpinnerLabel({ color, label }) {
867
869
  ] });
868
870
  }
869
871
 
872
+ // src/interactive/components/StructuredUserMessage.tsx
873
+ import { useState as useState3 } from "react";
874
+ import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "@opentui/react/jsx-runtime";
875
+ function SourceBadge({ source }) {
876
+ const config = SOURCE_CONFIG[source];
877
+ return /* @__PURE__ */ jsx4("text", { children: /* @__PURE__ */ jsx4("span", { fg: "#000000", bg: config.color, children: ` ${config.label} ` }) });
878
+ }
879
+ function MetadataPill({ label, value }) {
880
+ return /* @__PURE__ */ jsx4("text", { children: label ? /* @__PURE__ */ jsxs4(Fragment, { children: [
881
+ /* @__PURE__ */ jsxs4("span", { fg: "#888888", children: [
882
+ label,
883
+ ": "
884
+ ] }),
885
+ /* @__PURE__ */ jsx4("span", { fg: "#cccccc", children: value })
886
+ ] }) : /* @__PURE__ */ jsx4("span", { fg: "#cccccc", children: value }) });
887
+ }
888
+ function MessageBody({ children }) {
889
+ if (!children) return null;
890
+ return /* @__PURE__ */ jsx4("text", { fg: "#ffffff", selectable: true, children });
891
+ }
892
+ function ExpandableSection({ label, children }) {
893
+ const [expanded, setExpanded] = useState3(false);
894
+ if (!children) return null;
895
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", children: [
896
+ /* @__PURE__ */ jsx4("box", { onMouseDown: () => setExpanded((e) => !e), children: /* @__PURE__ */ jsxs4("text", { children: [
897
+ /* @__PURE__ */ jsxs4("span", { fg: "#555555", children: [
898
+ expanded ? "\u25BE" : "\u25B8",
899
+ " "
900
+ ] }),
901
+ /* @__PURE__ */ jsx4("span", { fg: "#888888", children: label })
902
+ ] }) }),
903
+ expanded && /* @__PURE__ */ jsx4("box", { paddingLeft: 2, children: /* @__PURE__ */ jsx4("text", { fg: "#888888", selectable: true, children }) })
904
+ ] });
905
+ }
906
+ function CIFailureMessage({ data }) {
907
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
908
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
909
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "ci_failure" }),
910
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
911
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "Workflow", value: data.workflowName }),
912
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "Status", value: data.conclusion })
913
+ ] }),
914
+ /* @__PURE__ */ jsxs4("text", { fg: "#ffffff", children: [
915
+ "Workflow ",
916
+ /* @__PURE__ */ jsx4("span", { fg: "#ff4444", children: data.conclusionText }),
917
+ " on PR #" + data.prNumber
918
+ ] }),
919
+ data.workflowFile && /* @__PURE__ */ jsx4(MetadataPill, { label: "File", value: data.workflowFile }),
920
+ data.runUrl && /* @__PURE__ */ jsx4(MetadataPill, { label: "Run", value: data.runUrl })
921
+ ] });
922
+ }
923
+ function LinearIssueMessage({ data }) {
924
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
925
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
926
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "linear_issue" }),
927
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "", value: data.identifier })
928
+ ] }),
929
+ /* @__PURE__ */ jsx4("text", { fg: "#ffffff", children: /* @__PURE__ */ jsx4("strong", { children: data.title }) }),
930
+ data.description && data.description !== "No description provided." && /* @__PURE__ */ jsx4(MessageBody, { children: data.description }),
931
+ /* @__PURE__ */ jsx4(ExpandableSection, { label: "Additional context", children: data.additionalContext }),
932
+ data.parentIssue && /* @__PURE__ */ jsx4(ExpandableSection, { label: `Parent: ${data.parentIssue.identifier} - ${data.parentIssue.title}`, children: data.parentIssue.description })
933
+ ] });
934
+ }
935
+ function GitHubIssueNewMessage({ data }) {
936
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
937
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
938
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "github_issue_new" }),
939
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "Issue", value: `#${data.issueNumber}` }),
940
+ data.triggeringUser && /* @__PURE__ */ jsx4(MetadataPill, { label: "From", value: `@${data.triggeringUser}` })
941
+ ] }),
942
+ /* @__PURE__ */ jsx4("text", { fg: "#ffffff", children: /* @__PURE__ */ jsx4("strong", { children: data.issueTitle }) }),
943
+ data.triggeringComment && /* @__PURE__ */ jsx4(MessageBody, { children: data.triggeringComment }),
944
+ /* @__PURE__ */ jsx4(ExpandableSection, { label: "Issue description", children: data.issueDescription })
945
+ ] });
946
+ }
947
+ function GitHubIssueExistingMessage({ data }) {
948
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
949
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
950
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "github_issue_existing" }),
951
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "Issue", value: `#${data.issueNumber}` }),
952
+ data.commentUser && /* @__PURE__ */ jsx4(MetadataPill, { label: "From", value: `@${data.commentUser}` })
953
+ ] }),
954
+ /* @__PURE__ */ jsx4(MessageBody, { children: data.commentBody })
955
+ ] });
956
+ }
957
+ function GitHubPRNewMessage({ data }) {
958
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
959
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
960
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "github_pr_new" }),
961
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
962
+ data.mentioningUser && /* @__PURE__ */ jsx4(MetadataPill, { label: "From", value: `@${data.mentioningUser}` })
963
+ ] }),
964
+ /* @__PURE__ */ jsx4(MessageBody, { children: data.contextMessage })
965
+ ] });
966
+ }
967
+ function GitHubPRCodeReviewMessage({ data }) {
968
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
969
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
970
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "github_pr_existing_review" }),
971
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
972
+ data.commentUser && /* @__PURE__ */ jsx4(MetadataPill, { label: "From", value: `@${data.commentUser}` }),
973
+ data.filePath && /* @__PURE__ */ jsx4(MetadataPill, { label: "File", value: data.filePath })
974
+ ] }),
975
+ /* @__PURE__ */ jsx4(MessageBody, { children: data.commentBody }),
976
+ /* @__PURE__ */ jsx4(ExpandableSection, { label: "Diff context", children: data.diffHunk })
977
+ ] });
978
+ }
979
+ function GitHubPRReviewMessage({ data }) {
980
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
981
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
982
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "github_pr_existing_pr_review" }),
983
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
984
+ data.reviewUser && /* @__PURE__ */ jsx4(MetadataPill, { label: "From", value: `@${data.reviewUser}` })
985
+ ] }),
986
+ /* @__PURE__ */ jsxs4("text", { fg: "#888888", children: [
987
+ "@" + data.reviewUser + " ",
988
+ /* @__PURE__ */ jsx4("span", { fg: "#ffffff", children: data.reviewAction })
989
+ ] }),
990
+ data.commentBody && /* @__PURE__ */ jsx4(MessageBody, { children: data.commentBody })
991
+ ] });
992
+ }
993
+ function GitHubPRGeneralMessage({ data }) {
994
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
995
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
996
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "github_pr_existing_general" }),
997
+ /* @__PURE__ */ jsx4(MetadataPill, { label: "PR", value: `#${data.prNumber}` }),
998
+ data.commentUser && /* @__PURE__ */ jsx4(MetadataPill, { label: "From", value: `@${data.commentUser}` })
999
+ ] }),
1000
+ /* @__PURE__ */ jsx4(MessageBody, { children: data.commentBody })
1001
+ ] });
1002
+ }
1003
+ function SlackTaskMessage({ data }) {
1004
+ const hasDistinctContext = data.threadContext && data.threadContext !== `@${data.latestMessageUser}: ${data.latestMessageText}`;
1005
+ return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", gap: 0, children: [
1006
+ /* @__PURE__ */ jsxs4("box", { flexDirection: "row", gap: 1, children: [
1007
+ /* @__PURE__ */ jsx4(SourceBadge, { source: "slack_task" }),
1008
+ data.workspaceTarget && /* @__PURE__ */ jsx4(MetadataPill, { label: "Target", value: data.workspaceTarget }),
1009
+ data.latestMessageUser && /* @__PURE__ */ jsx4(MetadataPill, { label: "From", value: `@${data.latestMessageUser}` })
1010
+ ] }),
1011
+ /* @__PURE__ */ jsx4(MessageBody, { children: data.latestMessageText }),
1012
+ hasDistinctContext && /* @__PURE__ */ jsx4(ExpandableSection, { label: "Thread context", children: data.threadContext })
1013
+ ] });
1014
+ }
1015
+ function StructuredUserMessage({ parsed }) {
1016
+ switch (parsed.source) {
1017
+ case "ci_failure":
1018
+ return /* @__PURE__ */ jsx4(CIFailureMessage, { data: parsed });
1019
+ case "linear_issue":
1020
+ return /* @__PURE__ */ jsx4(LinearIssueMessage, { data: parsed });
1021
+ case "github_issue_new":
1022
+ return /* @__PURE__ */ jsx4(GitHubIssueNewMessage, { data: parsed });
1023
+ case "github_issue_existing":
1024
+ return /* @__PURE__ */ jsx4(GitHubIssueExistingMessage, { data: parsed });
1025
+ case "github_pr_new":
1026
+ return /* @__PURE__ */ jsx4(GitHubPRNewMessage, { data: parsed });
1027
+ case "github_pr_existing_review":
1028
+ return /* @__PURE__ */ jsx4(GitHubPRCodeReviewMessage, { data: parsed });
1029
+ case "github_pr_existing_pr_review":
1030
+ return /* @__PURE__ */ jsx4(GitHubPRReviewMessage, { data: parsed });
1031
+ case "github_pr_existing_general":
1032
+ return /* @__PURE__ */ jsx4(GitHubPRGeneralMessage, { data: parsed });
1033
+ case "slack_task":
1034
+ return /* @__PURE__ */ jsx4(SlackTaskMessage, { data: parsed });
1035
+ default: {
1036
+ const _exhaustive = parsed;
1037
+ throw new Error(`Unhandled prompt source: ${_exhaustive.source}`);
1038
+ }
1039
+ }
1040
+ }
1041
+
870
1042
  // src/interactive/components/ChatMessage.tsx
871
- import { jsx as jsx4, jsxs as jsxs4 } from "@opentui/react/jsx-runtime";
1043
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "@opentui/react/jsx-runtime";
872
1044
  var sharedSyntaxStyle = null;
873
1045
  function getSyntaxStyle() {
874
1046
  if (!sharedSyntaxStyle) {
@@ -906,15 +1078,15 @@ function truncate2(text, maxLen) {
906
1078
  return text.length > maxLen ? text.slice(0, maxLen - 1) + "\u2026" : text;
907
1079
  }
908
1080
  function StatusIcon({ status }) {
909
- if (status === "completed") return /* @__PURE__ */ jsxs4("span", { fg: "#66bb6a", children: [
1081
+ if (status === "completed") return /* @__PURE__ */ jsxs5("span", { fg: "#66bb6a", children: [
910
1082
  " ",
911
1083
  "\u2713"
912
1084
  ] });
913
- if (status === "failed") return /* @__PURE__ */ jsxs4("span", { fg: "#ff4444", children: [
1085
+ if (status === "failed") return /* @__PURE__ */ jsxs5("span", { fg: "#ff4444", children: [
914
1086
  " ",
915
1087
  "\u2717"
916
1088
  ] });
917
- if (status === "in_progress") return /* @__PURE__ */ jsxs4("span", { fg: "#ffaa00", children: [
1089
+ if (status === "in_progress") return /* @__PURE__ */ jsxs5("span", { fg: "#ffaa00", children: [
918
1090
  " ",
919
1091
  "\u2026"
920
1092
  ] });
@@ -928,7 +1100,7 @@ function ActionLine({
928
1100
  onToggle,
929
1101
  expanded
930
1102
  }) {
931
- return /* @__PURE__ */ jsxs4(
1103
+ return /* @__PURE__ */ jsxs5(
932
1104
  "box",
933
1105
  {
934
1106
  paddingX: 1,
@@ -936,15 +1108,15 @@ function ActionLine({
936
1108
  justifyContent: "space-between",
937
1109
  onMouseDown: onToggle,
938
1110
  children: [
939
- /* @__PURE__ */ jsxs4("text", { children: [
940
- /* @__PURE__ */ jsx4("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx4("strong", { children: label }) }),
941
- /* @__PURE__ */ jsxs4("span", { fg: "#cccccc", children: [
1111
+ /* @__PURE__ */ jsxs5("text", { children: [
1112
+ /* @__PURE__ */ jsx5("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx5("strong", { children: label }) }),
1113
+ /* @__PURE__ */ jsxs5("span", { fg: "#cccccc", children: [
942
1114
  " ",
943
1115
  arg.replace(/\n/g, " ").replace(/\s+/g, " ")
944
1116
  ] }),
945
- /* @__PURE__ */ jsx4(StatusIcon, { status })
1117
+ /* @__PURE__ */ jsx5(StatusIcon, { status })
946
1118
  ] }),
947
- expandable && /* @__PURE__ */ jsx4("text", { children: /* @__PURE__ */ jsx4("span", { fg: "#555555", children: expanded ? "\u25BE" : "\u25B8" }) })
1119
+ expandable && /* @__PURE__ */ jsx5("text", { children: /* @__PURE__ */ jsx5("span", { fg: "#555555", children: expanded ? "\u25BE" : "\u25B8" }) })
948
1120
  ]
949
1121
  }
950
1122
  );
@@ -955,9 +1127,9 @@ function ExpandableAction({
955
1127
  status,
956
1128
  children
957
1129
  }) {
958
- const [expanded, setExpanded] = useState3(false);
959
- return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", children: [
960
- /* @__PURE__ */ jsx4(
1130
+ const [expanded, setExpanded] = useState4(false);
1131
+ return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", children: [
1132
+ /* @__PURE__ */ jsx5(
961
1133
  ActionLine,
962
1134
  {
963
1135
  label,
@@ -971,30 +1143,38 @@ function ExpandableAction({
971
1143
  expanded && children
972
1144
  ] });
973
1145
  }
1146
+ function isStructuredPrompt(p) {
1147
+ return p.source !== "raw";
1148
+ }
1149
+ function UserMessageContent({ content }) {
1150
+ const parsed = useMemo3(() => parseUserMessage(content), [content]);
1151
+ return /* @__PURE__ */ jsx5(
1152
+ "box",
1153
+ {
1154
+ flexDirection: "column",
1155
+ backgroundColor: "#151515",
1156
+ paddingX: 2,
1157
+ paddingY: 1,
1158
+ marginX: 1,
1159
+ children: isStructuredPrompt(parsed) ? /* @__PURE__ */ jsx5(StructuredUserMessage, { parsed }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
1160
+ /* @__PURE__ */ jsx5("text", { children: /* @__PURE__ */ jsx5("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx5("strong", { children: "You" }) }) }),
1161
+ /* @__PURE__ */ jsx5("text", { fg: "#ffffff", selectable: true, children: content })
1162
+ ] })
1163
+ }
1164
+ );
1165
+ }
974
1166
  function ChatMessage({ message, provider }) {
975
1167
  switch (message.type) {
976
- case "user":
1168
+ case "user": {
977
1169
  if (message.content === "Request interrupted") {
978
- return /* @__PURE__ */ jsx4("box", { paddingX: 1, justifyContent: "center", children: /* @__PURE__ */ jsx4("text", { fg: "#555555", children: "--- Request interrupted ---" }) });
1170
+ return /* @__PURE__ */ jsx5("box", { paddingX: 1, justifyContent: "center", children: /* @__PURE__ */ jsx5("text", { fg: "#555555", children: "--- Request interrupted ---" }) });
979
1171
  }
980
- return /* @__PURE__ */ jsxs4(
981
- "box",
982
- {
983
- flexDirection: "column",
984
- backgroundColor: "#151515",
985
- paddingX: 2,
986
- paddingY: 1,
987
- marginX: 1,
988
- children: [
989
- /* @__PURE__ */ jsx4("text", { children: /* @__PURE__ */ jsx4("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx4("strong", { children: "You" }) }) }),
990
- /* @__PURE__ */ jsx4("text", { fg: "#ffffff", selectable: true, children: message.content })
991
- ]
992
- }
993
- );
1172
+ return /* @__PURE__ */ jsx5(UserMessageContent, { content: message.content });
1173
+ }
994
1174
  case "agent":
995
- return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", paddingX: 1, children: [
996
- /* @__PURE__ */ jsx4("text", { children: /* @__PURE__ */ jsx4("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx4("strong", { children: AGENT_LABELS[provider] }) }) }),
997
- /* @__PURE__ */ jsx4(
1175
+ return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", paddingX: 1, children: [
1176
+ /* @__PURE__ */ jsx5("text", { children: /* @__PURE__ */ jsx5("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx5("strong", { children: AGENT_LABELS[provider] }) }) }),
1177
+ /* @__PURE__ */ jsx5(
998
1178
  "markdown",
999
1179
  {
1000
1180
  content: message.content,
@@ -1007,26 +1187,26 @@ function ChatMessage({ message, provider }) {
1007
1187
  )
1008
1188
  ] });
1009
1189
  case "reasoning":
1010
- return /* @__PURE__ */ jsx4("box", { paddingX: 1, children: /* @__PURE__ */ jsx4(SpinnerLabel, { color: "#555555", label: "thinking" }) });
1190
+ return /* @__PURE__ */ jsx5("box", { paddingX: 1, children: /* @__PURE__ */ jsx5(SpinnerLabel, { color: "#555555", label: "thinking" }) });
1011
1191
  case "command": {
1012
1192
  const cmdArg = truncate2(message.command, 60);
1013
1193
  const exitSuffix = message.exitCode !== void 0 && message.exitCode !== 0 ? ` (exit ${message.exitCode})` : "";
1014
1194
  if (!message.output) {
1015
- return /* @__PURE__ */ jsx4(ActionLine, { label: "Command", arg: cmdArg + exitSuffix, status: message.status });
1195
+ return /* @__PURE__ */ jsx5(ActionLine, { label: "Command", arg: cmdArg + exitSuffix, status: message.status });
1016
1196
  }
1017
- return /* @__PURE__ */ jsx4(ExpandableAction, { label: "Command", arg: cmdArg + exitSuffix, status: message.status, children: /* @__PURE__ */ jsx4("box", { paddingLeft: 2, paddingX: 1, children: /* @__PURE__ */ jsx4("text", { fg: "#888888", selectable: true, children: message.output.length > 500 ? message.output.slice(0, 500) + "\n\u2026" : message.output }) }) });
1197
+ return /* @__PURE__ */ jsx5(ExpandableAction, { label: "Command", arg: cmdArg + exitSuffix, status: message.status, children: /* @__PURE__ */ jsx5("box", { paddingLeft: 2, paddingX: 1, children: /* @__PURE__ */ jsx5("text", { fg: "#888888", selectable: true, children: message.output.length > 500 ? message.output.slice(0, 500) + "\n\u2026" : message.output }) }) });
1018
1198
  }
1019
1199
  case "file_change": {
1020
1200
  const count = message.changes.length;
1021
- return /* @__PURE__ */ jsx4(ExpandableAction, { label: "Files", arg: `${count}`, status: message.status, children: /* @__PURE__ */ jsx4("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: message.changes.map((change, i) => /* @__PURE__ */ jsxs4("text", { children: [
1022
- /* @__PURE__ */ jsx4(
1201
+ return /* @__PURE__ */ jsx5(ExpandableAction, { label: "Files", arg: `${count}`, status: message.status, children: /* @__PURE__ */ jsx5("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: message.changes.map((change, i) => /* @__PURE__ */ jsxs5("text", { children: [
1202
+ /* @__PURE__ */ jsx5(
1023
1203
  "span",
1024
1204
  {
1025
1205
  fg: change.kind === "add" ? "#66bb6a" : change.kind === "delete" ? "#ff4444" : "#ffaa00",
1026
1206
  children: change.kind === "add" ? "+" : change.kind === "delete" ? "-" : "~"
1027
1207
  }
1028
1208
  ),
1029
- /* @__PURE__ */ jsxs4("span", { fg: "#cccccc", children: [
1209
+ /* @__PURE__ */ jsxs5("span", { fg: "#cccccc", children: [
1030
1210
  " ",
1031
1211
  change.path
1032
1212
  ] })
@@ -1035,29 +1215,29 @@ function ChatMessage({ message, provider }) {
1035
1215
  case "tool_call": {
1036
1216
  const toolArg = truncate2(message.tool, 50);
1037
1217
  if (message.output || message.input) {
1038
- return /* @__PURE__ */ jsx4(ExpandableAction, { label: "Tool", arg: toolArg, status: message.status, children: /* @__PURE__ */ jsxs4("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: [
1039
- message.input && /* @__PURE__ */ jsx4("text", { fg: "#888888", selectable: true, children: typeof message.input === "string" ? truncate2(message.input, 300) : truncate2(JSON.stringify(message.input, null, 2), 300) }),
1040
- message.output && /* @__PURE__ */ jsx4("text", { fg: "#888888", selectable: true, children: truncate2(message.output, 300) })
1218
+ return /* @__PURE__ */ jsx5(ExpandableAction, { label: "Tool", arg: toolArg, status: message.status, children: /* @__PURE__ */ jsxs5("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: [
1219
+ message.input && /* @__PURE__ */ jsx5("text", { fg: "#888888", selectable: true, children: typeof message.input === "string" ? truncate2(message.input, 300) : truncate2(JSON.stringify(message.input, null, 2), 300) }),
1220
+ message.output && /* @__PURE__ */ jsx5("text", { fg: "#888888", selectable: true, children: truncate2(message.output, 300) })
1041
1221
  ] }) });
1042
1222
  }
1043
- return /* @__PURE__ */ jsx4(ActionLine, { label: "Tool", arg: toolArg, status: message.status });
1223
+ return /* @__PURE__ */ jsx5(ActionLine, { label: "Tool", arg: toolArg, status: message.status });
1044
1224
  }
1045
1225
  case "web_search":
1046
- return /* @__PURE__ */ jsx4(ActionLine, { label: "Search", arg: truncate2(message.query, 50), status: message.status });
1226
+ return /* @__PURE__ */ jsx5(ActionLine, { label: "Search", arg: truncate2(message.query, 50), status: message.status });
1047
1227
  case "todo_list": {
1048
1228
  const completed = message.items.filter((i) => i.completed).length;
1049
1229
  const total = message.items.length;
1050
- return /* @__PURE__ */ jsxs4("box", { flexDirection: "column", paddingX: 1, children: [
1051
- /* @__PURE__ */ jsx4("text", { children: /* @__PURE__ */ jsx4("span", { fg: "#888888", children: /* @__PURE__ */ jsxs4("strong", { children: [
1230
+ return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", paddingX: 1, children: [
1231
+ /* @__PURE__ */ jsx5("text", { children: /* @__PURE__ */ jsx5("span", { fg: "#888888", children: /* @__PURE__ */ jsxs5("strong", { children: [
1052
1232
  "Plan (",
1053
1233
  completed,
1054
1234
  "/",
1055
1235
  total,
1056
1236
  ")"
1057
1237
  ] }) }) }),
1058
- message.items.map((item, i) => /* @__PURE__ */ jsxs4("text", { children: [
1059
- /* @__PURE__ */ jsx4("span", { fg: item.completed ? "#66bb6a" : "#555555", children: item.completed ? " \u2611" : " \u2610" }),
1060
- /* @__PURE__ */ jsxs4("span", { fg: "#ffffff", children: [
1238
+ message.items.map((item, i) => /* @__PURE__ */ jsxs5("text", { children: [
1239
+ /* @__PURE__ */ jsx5("span", { fg: item.completed ? "#66bb6a" : "#555555", children: item.completed ? " \u2611" : " \u2610" }),
1240
+ /* @__PURE__ */ jsxs5("span", { fg: "#ffffff", children: [
1061
1241
  " ",
1062
1242
  item.text
1063
1243
  ] })
@@ -1065,22 +1245,22 @@ function ChatMessage({ message, provider }) {
1065
1245
  ] });
1066
1246
  }
1067
1247
  case "subagent":
1068
- return /* @__PURE__ */ jsx4(ActionLine, { label: "Agent", arg: truncate2(message.description, 50), status: message.status });
1248
+ return /* @__PURE__ */ jsx5(ActionLine, { label: "Agent", arg: truncate2(message.description, 50), status: message.status });
1069
1249
  case "error":
1070
- return /* @__PURE__ */ jsx4("box", { paddingX: 1, children: /* @__PURE__ */ jsx4("text", { fg: "#ff4444", selectable: true, children: message.message }) });
1250
+ return /* @__PURE__ */ jsx5("box", { paddingX: 1, children: /* @__PURE__ */ jsx5("text", { fg: "#ff4444", selectable: true, children: message.message }) });
1071
1251
  case "skill":
1072
- return /* @__PURE__ */ jsx4(ActionLine, { label: "Skill", arg: message.skillName + (message.args ? ` ${message.args}` : ""), status: message.status });
1252
+ return /* @__PURE__ */ jsx5(ActionLine, { label: "Skill", arg: message.skillName + (message.args ? ` ${message.args}` : ""), status: message.status });
1073
1253
  case "patch": {
1074
1254
  const opCount = message.operations.length;
1075
- return /* @__PURE__ */ jsx4(ExpandableAction, { label: "Patch", arg: `${opCount}`, children: /* @__PURE__ */ jsx4("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: message.operations.map((op, i) => /* @__PURE__ */ jsxs4("text", { children: [
1076
- /* @__PURE__ */ jsx4(
1255
+ return /* @__PURE__ */ jsx5(ExpandableAction, { label: "Patch", arg: `${opCount}`, children: /* @__PURE__ */ jsx5("box", { flexDirection: "column", paddingLeft: 2, paddingX: 1, children: message.operations.map((op, i) => /* @__PURE__ */ jsxs5("text", { children: [
1256
+ /* @__PURE__ */ jsx5(
1077
1257
  "span",
1078
1258
  {
1079
1259
  fg: op.action === "add" ? "#66bb6a" : op.action === "delete" ? "#ff4444" : "#ffaa00",
1080
1260
  children: op.action === "add" ? "+" : op.action === "delete" ? "-" : "~"
1081
1261
  }
1082
1262
  ),
1083
- /* @__PURE__ */ jsxs4("span", { fg: "#cccccc", children: [
1263
+ /* @__PURE__ */ jsxs5("span", { fg: "#cccccc", children: [
1084
1264
  " ",
1085
1265
  op.path
1086
1266
  ] })
@@ -1092,7 +1272,7 @@ function ChatMessage({ message, provider }) {
1092
1272
  }
1093
1273
 
1094
1274
  // src/interactive/components/ChatArea.tsx
1095
- import { jsx as jsx5, jsxs as jsxs5 } from "@opentui/react/jsx-runtime";
1275
+ import { jsx as jsx6, jsxs as jsxs6 } from "@opentui/react/jsx-runtime";
1096
1276
  var textareaKeyBindings = [
1097
1277
  { name: "return", action: "submit" },
1098
1278
  { name: "return", shift: true, action: "newline" },
@@ -1183,7 +1363,7 @@ function ChatArea({
1183
1363
  }
1184
1364
  }
1185
1365
  });
1186
- return /* @__PURE__ */ jsxs5(
1366
+ return /* @__PURE__ */ jsxs6(
1187
1367
  "box",
1188
1368
  {
1189
1369
  flexGrow: 1,
@@ -1195,7 +1375,7 @@ function ChatArea({
1195
1375
  flexDirection: "column",
1196
1376
  backgroundColor: "#000000",
1197
1377
  children: [
1198
- chats.length > 1 && /* @__PURE__ */ jsx5(
1378
+ chats.length > 1 && /* @__PURE__ */ jsx6(
1199
1379
  "box",
1200
1380
  {
1201
1381
  height: 3,
@@ -1211,7 +1391,7 @@ function ChatArea({
1211
1391
  children: chats.map((chat) => {
1212
1392
  const isSelected = chat.id === selectedChatId;
1213
1393
  const label = `${chat.title}${chat.processing ? " ..." : ""}`;
1214
- return /* @__PURE__ */ jsx5(
1394
+ return /* @__PURE__ */ jsx6(
1215
1395
  "box",
1216
1396
  {
1217
1397
  backgroundColor: isSelected ? "#1a1a1a" : void 0,
@@ -1220,14 +1400,14 @@ function ChatArea({
1220
1400
  onSelectChat(chat.id);
1221
1401
  onFocus("chat-tabs");
1222
1402
  },
1223
- children: /* @__PURE__ */ jsx5("text", { children: /* @__PURE__ */ jsx5("span", { fg: isSelected ? modeColors.text : "#666666", children: label }) })
1403
+ children: /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: isSelected ? modeColors.text : "#666666", children: label }) })
1224
1404
  },
1225
1405
  chat.id
1226
1406
  );
1227
1407
  })
1228
1408
  }
1229
1409
  ),
1230
- /* @__PURE__ */ jsx5(
1410
+ /* @__PURE__ */ jsx6(
1231
1411
  "scrollbox",
1232
1412
  {
1233
1413
  ref: scrollboxRef,
@@ -1236,22 +1416,22 @@ function ChatArea({
1236
1416
  paddingX: 1,
1237
1417
  paddingY: 1,
1238
1418
  onMouseDown: () => onFocus("chat-history"),
1239
- children: loading ? /* @__PURE__ */ jsx5("box", { paddingX: 1, children: /* @__PURE__ */ jsx5("text", { fg: "#666666", children: "Loading messages..." }) }) : displayMessages.length === 0 ? /* @__PURE__ */ jsx5("box", { paddingX: 1, children: /* @__PURE__ */ jsx5("text", { fg: "#666666", children: "No messages yet. Send a message to start chatting." }) }) : (() => {
1419
+ children: loading ? /* @__PURE__ */ jsx6("box", { paddingX: 1, children: /* @__PURE__ */ jsx6("text", { fg: "#666666", children: "Loading messages..." }) }) : displayMessages.length === 0 ? /* @__PURE__ */ jsx6("box", { paddingX: 1, children: /* @__PURE__ */ jsx6("text", { fg: "#666666", children: "No messages yet. Send a message to start chatting." }) }) : (() => {
1240
1420
  const activeChat = chats.find((c) => c.id === selectedChatId);
1241
1421
  const provider = activeChat?.provider ?? "claude";
1242
1422
  const primaryTypes = /* @__PURE__ */ new Set(["user", "agent", "todo_list"]);
1243
1423
  return displayMessages.map((msg, i) => {
1244
1424
  const prev = i > 0 ? displayMessages[i - 1] : null;
1245
1425
  const needsSpacing = prev && (primaryTypes.has(msg.type) || primaryTypes.has(prev.type));
1246
- return /* @__PURE__ */ jsxs5("box", { flexDirection: "column", children: [
1247
- needsSpacing && /* @__PURE__ */ jsx5("box", { height: 1 }),
1248
- /* @__PURE__ */ jsx5(ChatMessage, { message: msg, provider })
1426
+ return /* @__PURE__ */ jsxs6("box", { flexDirection: "column", children: [
1427
+ needsSpacing && /* @__PURE__ */ jsx6("box", { height: 1 }),
1428
+ /* @__PURE__ */ jsx6(ChatMessage, { message: msg, provider })
1249
1429
  ] }, msg.id || `msg-${i}`);
1250
1430
  });
1251
1431
  })()
1252
1432
  }
1253
1433
  ),
1254
- /* @__PURE__ */ jsxs5(
1434
+ /* @__PURE__ */ jsxs6(
1255
1435
  "box",
1256
1436
  {
1257
1437
  flexDirection: "column",
@@ -1261,7 +1441,7 @@ function ChatArea({
1261
1441
  backgroundColor: "#111111",
1262
1442
  onMouseDown: () => onFocus("chat-input"),
1263
1443
  children: [
1264
- /* @__PURE__ */ jsx5("box", { height: 6, paddingX: 1, children: /* @__PURE__ */ jsx5(
1444
+ /* @__PURE__ */ jsx6("box", { height: 6, paddingX: 1, children: /* @__PURE__ */ jsx6(
1265
1445
  "textarea",
1266
1446
  {
1267
1447
  ref: textareaRef,
@@ -1276,7 +1456,7 @@ function ChatArea({
1276
1456
  height: 5
1277
1457
  }
1278
1458
  ) }),
1279
- /* @__PURE__ */ jsxs5(
1459
+ /* @__PURE__ */ jsxs6(
1280
1460
  "box",
1281
1461
  {
1282
1462
  height: 1,
@@ -1284,8 +1464,8 @@ function ChatArea({
1284
1464
  flexDirection: "row",
1285
1465
  justifyContent: "space-between",
1286
1466
  children: [
1287
- /* @__PURE__ */ jsx5("text", { children: /* @__PURE__ */ jsx5("span", { fg: modeColors.text, children: taskMode === "build" ? "Build" : "Plan" }) }),
1288
- isProcessing && /* @__PURE__ */ jsx5(SpinnerLabel, { color: "#ffaa00", label: "thinking" })
1467
+ /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: modeColors.text, children: taskMode === "build" ? "Build" : "Plan" }) }),
1468
+ isProcessing && /* @__PURE__ */ jsx6(SpinnerLabel, { color: "#ffaa00", label: "thinking" })
1289
1469
  ]
1290
1470
  }
1291
1471
  )
@@ -1298,10 +1478,45 @@ function ChatArea({
1298
1478
  }
1299
1479
 
1300
1480
  // src/interactive/components/WorkspaceInfo.tsx
1301
- import React4 from "react";
1481
+ import React5, { useState as useState5, useMemo as useMemo4, useCallback as useCallback4 } from "react";
1302
1482
  import open from "open";
1303
- import { Fragment, jsx as jsx6, jsxs as jsxs6 } from "@opentui/react/jsx-runtime";
1483
+ import { useKeyboard as useKeyboard3 } from "@opentui/react";
1484
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "@opentui/react/jsx-runtime";
1304
1485
  var WEB_APP_URL = process.env.REPLICAS_WEB_URL || "https://replicas.dev";
1486
+ function buildInteractiveItems(workspaceId, status, previews, wakingWorkspaceId) {
1487
+ const items = [];
1488
+ if (workspaceId) {
1489
+ items.push({ type: "dashboard", workspaceId });
1490
+ }
1491
+ if (workspaceId && status.status === "sleeping" && wakingWorkspaceId !== workspaceId) {
1492
+ items.push({ type: "wake", workspaceId });
1493
+ }
1494
+ for (const preview of previews) {
1495
+ if (preview.publicUrl) {
1496
+ items.push({ type: "preview", url: preview.publicUrl, port: preview.port });
1497
+ }
1498
+ }
1499
+ if (status.repoStatuses) {
1500
+ for (const repo of status.repoStatuses) {
1501
+ if (repo.prUrl) {
1502
+ items.push({ type: "pr", url: repo.prUrl, repoName: repo.name });
1503
+ }
1504
+ }
1505
+ }
1506
+ return items;
1507
+ }
1508
+ function getItemLabel(item) {
1509
+ switch (item.type) {
1510
+ case "dashboard":
1511
+ return "\u2197 Open in Dashboard";
1512
+ case "wake":
1513
+ return "\u25B6 Wake";
1514
+ case "preview":
1515
+ return `\u2197 Preview :${item.port}`;
1516
+ case "pr":
1517
+ return `\u2197 View PR (${item.repoName})`;
1518
+ }
1519
+ }
1305
1520
  var AUTH_METHOD_LABELS = {
1306
1521
  oauth: "OAuth",
1307
1522
  api_key: "API Key",
@@ -1310,24 +1525,24 @@ var AUTH_METHOD_LABELS = {
1310
1525
  };
1311
1526
  function StatusDot({ status }) {
1312
1527
  if (status === true || status === "yes") {
1313
- return /* @__PURE__ */ jsx6("span", { fg: "#66bb6a", children: "\u2713" });
1528
+ return /* @__PURE__ */ jsx7("span", { fg: "#66bb6a", children: "\u2713" });
1314
1529
  }
1315
1530
  if (status === false || status === "no") {
1316
- return /* @__PURE__ */ jsx6("span", { fg: "#ff4444", children: "\u2717" });
1531
+ return /* @__PURE__ */ jsx7("span", { fg: "#ff4444", children: "\u2717" });
1317
1532
  }
1318
- return /* @__PURE__ */ jsx6("span", { fg: "#555555", children: "-" });
1533
+ return /* @__PURE__ */ jsx7("span", { fg: "#555555", children: "-" });
1319
1534
  }
1320
1535
  function SectionLabel({ title }) {
1321
- return /* @__PURE__ */ jsx6("box", { backgroundColor: "#151515", paddingX: 1, children: /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#666666", children: /* @__PURE__ */ jsx6("strong", { children: title.toUpperCase() }) }) }) });
1536
+ return /* @__PURE__ */ jsx7("box", { backgroundColor: "#151515", paddingX: 1, children: /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: "#666666", children: /* @__PURE__ */ jsx7("strong", { children: title.toUpperCase() }) }) }) });
1322
1537
  }
1323
1538
  function Section({ title, children }) {
1324
- return /* @__PURE__ */ jsxs6("box", { flexDirection: "column", marginBottom: 1, children: [
1325
- /* @__PURE__ */ jsx6(SectionLabel, { title }),
1326
- /* @__PURE__ */ jsx6("box", { flexDirection: "column", backgroundColor: "#0a0a0a", children })
1539
+ return /* @__PURE__ */ jsxs7("box", { flexDirection: "column", marginBottom: 1, children: [
1540
+ /* @__PURE__ */ jsx7(SectionLabel, { title }),
1541
+ /* @__PURE__ */ jsx7("box", { flexDirection: "column", backgroundColor: "#0a0a0a", children })
1327
1542
  ] });
1328
1543
  }
1329
1544
  function CardItem({ label, status }) {
1330
- return /* @__PURE__ */ jsxs6(
1545
+ return /* @__PURE__ */ jsxs7(
1331
1546
  "box",
1332
1547
  {
1333
1548
  flexDirection: "row",
@@ -1336,8 +1551,8 @@ function CardItem({ label, status }) {
1336
1551
  backgroundColor: "#111111",
1337
1552
  marginBottom: 0,
1338
1553
  children: [
1339
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#cccccc", children: label }) }),
1340
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6(StatusDot, { status }) })
1554
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: "#cccccc", children: label }) }),
1555
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7(StatusDot, { status }) })
1341
1556
  ]
1342
1557
  }
1343
1558
  );
@@ -1350,12 +1565,112 @@ function DetailList({
1350
1565
  const actualSet = new Set(actual);
1351
1566
  const rows = uniqueExpected.length > 0 ? uniqueExpected : Array.from(actualSet).sort((a, b) => a.localeCompare(b));
1352
1567
  if (rows.length === 0) return null;
1353
- return /* @__PURE__ */ jsx6(Fragment, { children: rows.map((item, i) => /* @__PURE__ */ jsx6(CardItem, { label: item, status: actualSet.has(item) }, i)) });
1568
+ return /* @__PURE__ */ jsx7(Fragment3, { children: rows.map((item, i) => /* @__PURE__ */ jsx7(CardItem, { label: item, status: actualSet.has(item) }, i)) });
1569
+ }
1570
+ function InteractiveRow({ label, highlighted, onClick }) {
1571
+ return /* @__PURE__ */ jsx7(
1572
+ "box",
1573
+ {
1574
+ paddingX: 1,
1575
+ backgroundColor: highlighted ? "#1a2a1a" : "#111111",
1576
+ onMouseDown: onClick,
1577
+ children: /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: highlighted ? "#66bb6a" : "#7dcfff", children: label }) })
1578
+ }
1579
+ );
1354
1580
  }
1355
1581
  function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, envConfig, previews, onWakeWorkspace, wakingWorkspaceId }) {
1356
1582
  const borderColor = focused ? "#66bb6a" : "#333333";
1583
+ const [cursorIndex, setCursorIndex] = useState5(0);
1584
+ const interactiveItems = useMemo4(() => {
1585
+ if (!status || !workspaceName) return [];
1586
+ return buildInteractiveItems(workspaceId, status, previews, wakingWorkspaceId);
1587
+ }, [workspaceId, workspaceName, status, previews, wakingWorkspaceId]);
1588
+ const safeCursor = interactiveItems.length > 0 ? Math.min(cursorIndex, interactiveItems.length - 1) : 0;
1589
+ const moveCursor = useCallback4(
1590
+ (next) => {
1591
+ const clamped = Math.max(0, Math.min(interactiveItems.length - 1, next));
1592
+ setCursorIndex(clamped);
1593
+ },
1594
+ [interactiveItems.length]
1595
+ );
1596
+ const handleAction = useCallback4(
1597
+ (item) => {
1598
+ if (!item) return;
1599
+ switch (item.type) {
1600
+ case "dashboard":
1601
+ open(`${WEB_APP_URL}/dashboard?workspaceId=${item.workspaceId}`).catch(() => {
1602
+ });
1603
+ break;
1604
+ case "wake":
1605
+ onWakeWorkspace(item.workspaceId);
1606
+ break;
1607
+ case "preview":
1608
+ open(item.url).catch(() => {
1609
+ });
1610
+ break;
1611
+ case "pr":
1612
+ open(item.url).catch(() => {
1613
+ });
1614
+ break;
1615
+ }
1616
+ },
1617
+ [onWakeWorkspace]
1618
+ );
1619
+ useKeyboard3((key) => {
1620
+ if (!focused) return;
1621
+ if (interactiveItems.length === 0) return;
1622
+ if (key.name === "j" || key.name === "down") {
1623
+ moveCursor(safeCursor + 1);
1624
+ return;
1625
+ }
1626
+ if (key.name === "k" || key.name === "up") {
1627
+ moveCursor(safeCursor - 1);
1628
+ return;
1629
+ }
1630
+ if (key.name === "g" && !key.shift) {
1631
+ moveCursor(0);
1632
+ return;
1633
+ }
1634
+ if (key.name === "g" && key.shift) {
1635
+ moveCursor(interactiveItems.length - 1);
1636
+ return;
1637
+ }
1638
+ if (key.name === "enter" || key.name === "return") {
1639
+ handleAction(interactiveItems[safeCursor]);
1640
+ return;
1641
+ }
1642
+ if (key.name === "o") {
1643
+ const dashboardItem2 = interactiveItems.find((item) => item.type === "dashboard");
1644
+ if (dashboardItem2) handleAction(dashboardItem2);
1645
+ return;
1646
+ }
1647
+ if (key.name === "w") {
1648
+ const wakeItem2 = interactiveItems.find((item) => item.type === "wake");
1649
+ if (wakeItem2) handleAction(wakeItem2);
1650
+ return;
1651
+ }
1652
+ });
1653
+ const isHighlighted = useCallback4(
1654
+ (item) => {
1655
+ if (!focused) return false;
1656
+ const idx = interactiveItems.indexOf(item);
1657
+ return idx === safeCursor;
1658
+ },
1659
+ [focused, interactiveItems, safeCursor]
1660
+ );
1661
+ const findItem = useCallback4(
1662
+ (type, key) => {
1663
+ return interactiveItems.find((item) => {
1664
+ if (item.type !== type) return false;
1665
+ if (type === "preview" && key) return item.port === Number(key);
1666
+ if (type === "pr" && key) return item.repoName === key;
1667
+ return true;
1668
+ });
1669
+ },
1670
+ [interactiveItems]
1671
+ );
1357
1672
  if (!workspaceName) {
1358
- return /* @__PURE__ */ jsx6(
1673
+ return /* @__PURE__ */ jsx7(
1359
1674
  "box",
1360
1675
  {
1361
1676
  width: 30,
@@ -1367,12 +1682,12 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
1367
1682
  flexDirection: "column",
1368
1683
  paddingX: 1,
1369
1684
  backgroundColor: "#000000",
1370
- children: /* @__PURE__ */ jsx6("text", { fg: "#666666", children: "Select a workspace" })
1685
+ children: /* @__PURE__ */ jsx7("text", { fg: "#666666", children: "Select a workspace" })
1371
1686
  }
1372
1687
  );
1373
1688
  }
1374
1689
  if (loading || !status) {
1375
- return /* @__PURE__ */ jsx6(
1690
+ return /* @__PURE__ */ jsx7(
1376
1691
  "box",
1377
1692
  {
1378
1693
  width: 30,
@@ -1384,7 +1699,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
1384
1699
  flexDirection: "column",
1385
1700
  paddingX: 1,
1386
1701
  backgroundColor: "#000000",
1387
- children: /* @__PURE__ */ jsx6("text", { fg: "#666666", children: "Loading..." })
1702
+ children: /* @__PURE__ */ jsx7("text", { fg: "#666666", children: "Loading..." })
1388
1703
  }
1389
1704
  );
1390
1705
  }
@@ -1393,7 +1708,9 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
1393
1708
  const expectedSkills = (envConfig.skills?.environment_skills ?? []).map((s) => s.source);
1394
1709
  const expectedGlobalVars = (envConfig.variables?.environment_variables ?? []).filter((v) => v.scope_type === "global").map((v) => v.key);
1395
1710
  const expectedGlobalFiles = (envConfig.files?.environment_files ?? []).filter((f) => f.scope_type === "global").map((f) => f.path);
1396
- return /* @__PURE__ */ jsx6(
1711
+ const dashboardItem = findItem("dashboard");
1712
+ const wakeItem = findItem("wake");
1713
+ return /* @__PURE__ */ jsx7(
1397
1714
  "box",
1398
1715
  {
1399
1716
  width: 30,
@@ -1404,141 +1721,147 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
1404
1721
  titleAlignment: "center",
1405
1722
  flexDirection: "column",
1406
1723
  backgroundColor: "#000000",
1407
- children: /* @__PURE__ */ jsxs6("scrollbox", { focused, flexGrow: 1, children: [
1408
- /* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs6("box", { flexDirection: "column", children: [
1409
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx6("strong", { children: workspaceName }) }) }),
1410
- /* @__PURE__ */ jsxs6("text", { children: [
1411
- /* @__PURE__ */ jsxs6("span", { fg: statusColor, children: [
1724
+ children: /* @__PURE__ */ jsxs7("scrollbox", { focused, flexGrow: 1, children: [
1725
+ /* @__PURE__ */ jsx7("box", { backgroundColor: "#111111", paddingX: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs7("box", { flexDirection: "column", children: [
1726
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx7("strong", { children: workspaceName }) }) }),
1727
+ /* @__PURE__ */ jsxs7("text", { children: [
1728
+ /* @__PURE__ */ jsxs7("span", { fg: statusColor, children: [
1412
1729
  "\u25CF",
1413
1730
  " ",
1414
1731
  status.status
1415
1732
  ] }),
1416
- env && /* @__PURE__ */ jsxs6("span", { fg: "#555555", children: [
1733
+ env && /* @__PURE__ */ jsxs7("span", { fg: "#555555", children: [
1417
1734
  " ",
1418
1735
  "\u2502",
1419
1736
  " ",
1420
1737
  env.engineVersion
1421
1738
  ] })
1422
- ] }),
1423
- workspaceId && /* @__PURE__ */ jsx6(
1424
- "box",
1425
- {
1426
- onMouseDown: () => {
1427
- open(`${WEB_APP_URL}/dashboard?workspaceId=${workspaceId}`).catch(() => {
1428
- });
1429
- },
1430
- children: /* @__PURE__ */ jsxs6("text", { children: [
1431
- /* @__PURE__ */ jsxs6("span", { fg: "#7dcfff", children: [
1432
- "\u2197",
1433
- " Open in Dashboard"
1434
- ] }),
1435
- /* @__PURE__ */ jsx6("span", { fg: "#555555", children: " (o)" })
1436
- ] })
1437
- }
1438
- ),
1439
- workspaceId && status.status === "sleeping" && /* @__PURE__ */ jsx6(
1440
- "box",
1441
- {
1442
- onMouseDown: () => {
1443
- if (wakingWorkspaceId !== workspaceId) onWakeWorkspace(workspaceId);
1444
- },
1445
- children: /* @__PURE__ */ jsxs6("text", { children: [
1446
- /* @__PURE__ */ jsx6("span", { fg: wakingWorkspaceId === workspaceId ? "#888888" : "#66bb6a", children: wakingWorkspaceId === workspaceId ? "\u25CC Waking..." : "\u25B6 Wake" }),
1447
- /* @__PURE__ */ jsx6("span", { fg: "#555555", children: " (w)" })
1448
- ] })
1449
- }
1450
- )
1739
+ ] })
1451
1740
  ] }) }),
1452
- (status.isClaudeProcessing || status.isCodexProcessing) && /* @__PURE__ */ jsxs6("box", { backgroundColor: "#1a1500", paddingX: 1, marginX: 1, marginBottom: 1, children: [
1453
- status.isClaudeProcessing && /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsxs6("span", { fg: "#ffaa00", children: [
1741
+ dashboardItem && /* @__PURE__ */ jsx7(
1742
+ InteractiveRow,
1743
+ {
1744
+ label: getItemLabel(dashboardItem),
1745
+ highlighted: isHighlighted(dashboardItem),
1746
+ onClick: () => handleAction(dashboardItem)
1747
+ }
1748
+ ),
1749
+ wakeItem && /* @__PURE__ */ jsx7(
1750
+ InteractiveRow,
1751
+ {
1752
+ label: getItemLabel(wakeItem),
1753
+ highlighted: isHighlighted(wakeItem),
1754
+ onClick: () => handleAction(wakeItem)
1755
+ }
1756
+ ),
1757
+ (status.isClaudeProcessing || status.isCodexProcessing) && /* @__PURE__ */ jsxs7("box", { backgroundColor: "#1a1500", paddingX: 1, marginX: 1, marginBottom: 1, children: [
1758
+ status.isClaudeProcessing && /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsxs7("span", { fg: "#ffaa00", children: [
1454
1759
  "\u25C6",
1455
1760
  " Claude thinking..."
1456
1761
  ] }) }),
1457
- status.isCodexProcessing && /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsxs6("span", { fg: "#ffaa00", children: [
1762
+ status.isCodexProcessing && /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsxs7("span", { fg: "#ffaa00", children: [
1458
1763
  "\u25C6",
1459
1764
  " Codex thinking..."
1460
1765
  ] }) })
1461
1766
  ] }),
1462
- env && /* @__PURE__ */ jsxs6(Section, { title: "Agents", children: [
1463
- /* @__PURE__ */ jsxs6("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1464
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#cccccc", children: "Claude" }) }),
1465
- /* @__PURE__ */ jsx6("text", { children: AUTH_METHOD_LABELS[env.claudeAuthMethod] ? /* @__PURE__ */ jsx6("span", { fg: "#66bb6a", children: AUTH_METHOD_LABELS[env.claudeAuthMethod] }) : /* @__PURE__ */ jsx6("span", { fg: "#ff4444", children: "\u2717" }) })
1767
+ env && /* @__PURE__ */ jsxs7(Section, { title: "Agents", children: [
1768
+ /* @__PURE__ */ jsxs7("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1769
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: "#cccccc", children: "Claude" }) }),
1770
+ /* @__PURE__ */ jsx7("text", { children: AUTH_METHOD_LABELS[env.claudeAuthMethod] ? /* @__PURE__ */ jsx7("span", { fg: "#66bb6a", children: AUTH_METHOD_LABELS[env.claudeAuthMethod] }) : /* @__PURE__ */ jsx7("span", { fg: "#ff4444", children: "\u2717" }) })
1466
1771
  ] }),
1467
- /* @__PURE__ */ jsxs6("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1468
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#cccccc", children: "Codex" }) }),
1469
- /* @__PURE__ */ jsx6("text", { children: AUTH_METHOD_LABELS[env.codexAuthMethod] ? /* @__PURE__ */ jsx6("span", { fg: "#66bb6a", children: AUTH_METHOD_LABELS[env.codexAuthMethod] }) : /* @__PURE__ */ jsx6("span", { fg: "#ff4444", children: "\u2717" }) })
1772
+ /* @__PURE__ */ jsxs7("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1773
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: "#cccccc", children: "Codex" }) }),
1774
+ /* @__PURE__ */ jsx7("text", { children: AUTH_METHOD_LABELS[env.codexAuthMethod] ? /* @__PURE__ */ jsx7("span", { fg: "#66bb6a", children: AUTH_METHOD_LABELS[env.codexAuthMethod] }) : /* @__PURE__ */ jsx7("span", { fg: "#ff4444", children: "\u2717" }) })
1470
1775
  ] })
1471
1776
  ] }),
1472
- env && /* @__PURE__ */ jsxs6(Section, { title: "Integrations", children: [
1473
- /* @__PURE__ */ jsx6(CardItem, { label: "GitHub", status: env.githubAccessConfigured }),
1474
- /* @__PURE__ */ jsx6(CardItem, { label: "Slack", status: env.slackAccessConfigured }),
1475
- /* @__PURE__ */ jsx6(CardItem, { label: "Linear", status: env.linearAccessConfigured })
1777
+ env && /* @__PURE__ */ jsxs7(Section, { title: "Integrations", children: [
1778
+ /* @__PURE__ */ jsx7(CardItem, { label: "GitHub", status: env.githubAccessConfigured }),
1779
+ /* @__PURE__ */ jsx7(CardItem, { label: "Slack", status: env.slackAccessConfigured }),
1780
+ /* @__PURE__ */ jsx7(CardItem, { label: "Linear", status: env.linearAccessConfigured })
1476
1781
  ] }),
1477
- previews.length > 0 && /* @__PURE__ */ jsx6(Section, { title: "Previews", children: previews.map((preview, i) => /* @__PURE__ */ jsxs6("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1478
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsxs6("span", { fg: "#cccccc", children: [
1479
- ":",
1480
- preview.port
1481
- ] }) }),
1482
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("a", { href: preview.publicUrl, children: /* @__PURE__ */ jsx6("span", { fg: "#66bb6a", children: "\u2197" }) }) })
1483
- ] }, i)) }),
1484
- status.repoStatuses && status.repoStatuses.length > 0 && /* @__PURE__ */ jsx6(Section, { title: "Repositories", children: status.repoStatuses.map((repo, i) => /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
1485
- /* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, children: /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx6("strong", { children: repo.name }) }) }) }),
1486
- /* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: /* @__PURE__ */ jsxs6("text", { children: [
1487
- /* @__PURE__ */ jsxs6("span", { fg: "#555555", children: [
1488
- "\u2514",
1489
- " "
1490
- ] }),
1491
- /* @__PURE__ */ jsx6("span", { fg: repo.currentBranch !== repo.defaultBranch ? "#ffaa00" : "#66bb6a", children: repo.currentBranch })
1492
- ] }) }),
1493
- repo.gitDiff && (repo.gitDiff.added > 0 || repo.gitDiff.removed > 0) && /* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, flexDirection: "row", children: /* @__PURE__ */ jsxs6("text", { children: [
1494
- /* @__PURE__ */ jsx6("span", { fg: "#555555", children: " " }),
1495
- /* @__PURE__ */ jsxs6("span", { fg: "#66bb6a", children: [
1496
- "+",
1497
- repo.gitDiff.added
1498
- ] }),
1499
- /* @__PURE__ */ jsx6("span", { fg: "#444444", children: " / " }),
1500
- /* @__PURE__ */ jsxs6("span", { fg: "#ff4444", children: [
1501
- "-",
1502
- repo.gitDiff.removed
1503
- ] })
1504
- ] }) }),
1505
- repo.prUrl && /* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, children: /* @__PURE__ */ jsxs6("text", { children: [
1506
- /* @__PURE__ */ jsx6("span", { fg: "#555555", children: " " }),
1507
- /* @__PURE__ */ jsx6("a", { href: repo.prUrl, children: /* @__PURE__ */ jsxs6("span", { fg: "#66bb6a", children: [
1508
- "View PR ",
1509
- "\u2197"
1510
- ] }) })
1511
- ] }) })
1512
- ] }, i)) }),
1513
- env && /* @__PURE__ */ jsxs6(Section, { title: "Hooks", children: [
1514
- /* @__PURE__ */ jsx6(CardItem, { label: "Global warm", status: env.globalWarmHookCompleted.status }),
1515
- env.repositories.map((repo, i) => /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
1516
- /* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, children: /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx6("strong", { children: repo.repositoryName }) }) }) }),
1517
- /* @__PURE__ */ jsxs6("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1518
- /* @__PURE__ */ jsxs6("text", { children: [
1519
- /* @__PURE__ */ jsxs6("span", { fg: "#555555", children: [
1782
+ previews.length > 0 && /* @__PURE__ */ jsx7(Section, { title: "Previews", children: previews.map((preview, i) => {
1783
+ const previewItem = findItem("preview", String(preview.port));
1784
+ return /* @__PURE__ */ jsxs7(
1785
+ "box",
1786
+ {
1787
+ flexDirection: "row",
1788
+ justifyContent: "space-between",
1789
+ paddingX: 1,
1790
+ backgroundColor: previewItem && isHighlighted(previewItem) ? "#1a2a1a" : "#111111",
1791
+ onMouseDown: () => previewItem && handleAction(previewItem),
1792
+ children: [
1793
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsxs7("span", { fg: "#cccccc", children: [
1794
+ ":",
1795
+ preview.port
1796
+ ] }) }),
1797
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: previewItem && isHighlighted(previewItem) ? "#66bb6a" : "#7dcfff", children: "\u2197" }) })
1798
+ ]
1799
+ },
1800
+ i
1801
+ );
1802
+ }) }),
1803
+ status.repoStatuses && status.repoStatuses.length > 0 && /* @__PURE__ */ jsx7(Section, { title: "Repositories", children: status.repoStatuses.map((repo, i) => {
1804
+ const prItem = findItem("pr", repo.name);
1805
+ return /* @__PURE__ */ jsxs7(React5.Fragment, { children: [
1806
+ /* @__PURE__ */ jsx7("box", { backgroundColor: "#111111", paddingX: 1, children: /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx7("strong", { children: repo.name }) }) }) }),
1807
+ /* @__PURE__ */ jsx7("box", { backgroundColor: "#111111", paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: /* @__PURE__ */ jsxs7("text", { children: [
1808
+ /* @__PURE__ */ jsxs7("span", { fg: "#555555", children: [
1809
+ "\u2514",
1810
+ " "
1811
+ ] }),
1812
+ /* @__PURE__ */ jsx7("span", { fg: repo.currentBranch !== repo.defaultBranch ? "#ffaa00" : "#66bb6a", children: repo.currentBranch })
1813
+ ] }) }),
1814
+ repo.gitDiff && (repo.gitDiff.added > 0 || repo.gitDiff.removed > 0) && /* @__PURE__ */ jsx7("box", { backgroundColor: "#111111", paddingX: 1, flexDirection: "row", children: /* @__PURE__ */ jsxs7("text", { children: [
1815
+ /* @__PURE__ */ jsx7("span", { fg: "#555555", children: " " }),
1816
+ /* @__PURE__ */ jsxs7("span", { fg: "#66bb6a", children: [
1817
+ "+",
1818
+ repo.gitDiff.added
1819
+ ] }),
1820
+ /* @__PURE__ */ jsx7("span", { fg: "#444444", children: " / " }),
1821
+ /* @__PURE__ */ jsxs7("span", { fg: "#ff4444", children: [
1822
+ "-",
1823
+ repo.gitDiff.removed
1824
+ ] })
1825
+ ] }) }),
1826
+ prItem && /* @__PURE__ */ jsx7(
1827
+ InteractiveRow,
1828
+ {
1829
+ label: ` ${getItemLabel(prItem)}`,
1830
+ highlighted: isHighlighted(prItem),
1831
+ onClick: () => handleAction(prItem)
1832
+ }
1833
+ )
1834
+ ] }, i);
1835
+ }) }),
1836
+ env && /* @__PURE__ */ jsxs7(Section, { title: "Hooks", children: [
1837
+ /* @__PURE__ */ jsx7(CardItem, { label: "Global warm", status: env.globalWarmHookCompleted.status }),
1838
+ env.repositories.map((repo, i) => /* @__PURE__ */ jsxs7(React5.Fragment, { children: [
1839
+ /* @__PURE__ */ jsx7("box", { backgroundColor: "#111111", paddingX: 1, children: /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx7("strong", { children: repo.repositoryName }) }) }) }),
1840
+ /* @__PURE__ */ jsxs7("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1841
+ /* @__PURE__ */ jsxs7("text", { children: [
1842
+ /* @__PURE__ */ jsxs7("span", { fg: "#555555", children: [
1520
1843
  "\u251C",
1521
1844
  " "
1522
1845
  ] }),
1523
- /* @__PURE__ */ jsx6("span", { fg: "#cccccc", children: "warm" })
1846
+ /* @__PURE__ */ jsx7("span", { fg: "#cccccc", children: "warm" })
1524
1847
  ] }),
1525
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6(StatusDot, { status: repo.warmHookCompleted }) })
1848
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7(StatusDot, { status: repo.warmHookCompleted }) })
1526
1849
  ] }),
1527
- /* @__PURE__ */ jsxs6("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1528
- /* @__PURE__ */ jsxs6("text", { children: [
1529
- /* @__PURE__ */ jsxs6("span", { fg: "#555555", children: [
1850
+ /* @__PURE__ */ jsxs7("box", { flexDirection: "row", justifyContent: "space-between", paddingX: 1, backgroundColor: "#111111", children: [
1851
+ /* @__PURE__ */ jsxs7("text", { children: [
1852
+ /* @__PURE__ */ jsxs7("span", { fg: "#555555", children: [
1530
1853
  "\u2514",
1531
1854
  " "
1532
1855
  ] }),
1533
- /* @__PURE__ */ jsx6("span", { fg: "#cccccc", children: "start" })
1856
+ /* @__PURE__ */ jsx7("span", { fg: "#cccccc", children: "start" })
1534
1857
  ] }),
1535
- /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6(StatusDot, { status: repo.startHookCompleted }) })
1858
+ /* @__PURE__ */ jsx7("text", { children: /* @__PURE__ */ jsx7(StatusDot, { status: repo.startHookCompleted }) })
1536
1859
  ] })
1537
1860
  ] }, i))
1538
1861
  ] }),
1539
- env && (expectedSkills.length > 0 || env.skillsInstalled.length > 0) && /* @__PURE__ */ jsx6(Section, { title: "Skills", children: /* @__PURE__ */ jsx6(DetailList, { expected: expectedSkills, actual: env.skillsInstalled }) }),
1540
- env && (expectedGlobalVars.length > 0 || env.envVarsSet.length > 0) && /* @__PURE__ */ jsx6(Section, { title: "Env Vars", children: /* @__PURE__ */ jsx6(DetailList, { expected: expectedGlobalVars, actual: env.envVarsSet }) }),
1541
- env && (expectedGlobalFiles.length > 0 || env.filesUploaded.length > 0) && /* @__PURE__ */ jsx6(Section, { title: "Files", children: /* @__PURE__ */ jsx6(DetailList, { expected: expectedGlobalFiles, actual: env.filesUploaded }) })
1862
+ env && (expectedSkills.length > 0 || env.skillsInstalled.length > 0) && /* @__PURE__ */ jsx7(Section, { title: "Skills", children: /* @__PURE__ */ jsx7(DetailList, { expected: expectedSkills, actual: env.skillsInstalled }) }),
1863
+ env && (expectedGlobalVars.length > 0 || env.envVarsSet.length > 0) && /* @__PURE__ */ jsx7(Section, { title: "Env Vars", children: /* @__PURE__ */ jsx7(DetailList, { expected: expectedGlobalVars, actual: env.envVarsSet }) }),
1864
+ env && (expectedGlobalFiles.length > 0 || env.filesUploaded.length > 0) && /* @__PURE__ */ jsx7(Section, { title: "Files", children: /* @__PURE__ */ jsx7(DetailList, { expected: expectedGlobalFiles, actual: env.filesUploaded }) })
1542
1865
  ] })
1543
1866
  }
1544
1867
  );
@@ -1548,8 +1871,8 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
1548
1871
  import { useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
1549
1872
 
1550
1873
  // src/interactive/toast-context.tsx
1551
- import { createContext as createContext2, useContext as useContext2, useState as useState4, useCallback as useCallback4, useRef as useRef2 } from "react";
1552
- import { jsx as jsx7 } from "@opentui/react/jsx-runtime";
1874
+ import { createContext as createContext2, useContext as useContext2, useState as useState6, useCallback as useCallback5, useRef as useRef2 } from "react";
1875
+ import { jsx as jsx8 } from "@opentui/react/jsx-runtime";
1553
1876
  var ToastContext = createContext2(null);
1554
1877
  function useToast() {
1555
1878
  const ctx = useContext2(ToastContext);
@@ -1557,9 +1880,9 @@ function useToast() {
1557
1880
  return ctx;
1558
1881
  }
1559
1882
  function ToastProvider({ children }) {
1560
- const [current, setCurrent] = useState4(null);
1883
+ const [current, setCurrent] = useState6(null);
1561
1884
  const timeoutRef = useRef2(null);
1562
- const show = useCallback4((options) => {
1885
+ const show = useCallback5((options) => {
1563
1886
  const { message, variant = "info", duration = 3e3 } = options;
1564
1887
  setCurrent({ message, variant });
1565
1888
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
@@ -1567,15 +1890,15 @@ function ToastProvider({ children }) {
1567
1890
  setCurrent(null);
1568
1891
  }, duration);
1569
1892
  }, []);
1570
- const error = useCallback4((err) => {
1893
+ const error = useCallback5((err) => {
1571
1894
  const message = err instanceof Error ? err.message : "An error occurred";
1572
1895
  show({ message, variant: "error", duration: 5e3 });
1573
1896
  }, [show]);
1574
- return /* @__PURE__ */ jsx7(ToastContext.Provider, { value: { current, show, error }, children });
1897
+ return /* @__PURE__ */ jsx8(ToastContext.Provider, { value: { current, show, error }, children });
1575
1898
  }
1576
1899
 
1577
1900
  // src/interactive/components/Toast.tsx
1578
- import { jsx as jsx8 } from "@opentui/react/jsx-runtime";
1901
+ import { jsx as jsx9 } from "@opentui/react/jsx-runtime";
1579
1902
  var VARIANT_COLORS = {
1580
1903
  info: { border: "#66bb6a", bg: "#0a1a0a" },
1581
1904
  success: { border: "#66bb6a", bg: "#0a1a0a" },
@@ -1588,7 +1911,7 @@ function Toast() {
1588
1911
  if (!current) return null;
1589
1912
  const colors = VARIANT_COLORS[current.variant] ?? VARIANT_COLORS.info;
1590
1913
  const toastWidth = Math.min(60, width - 4);
1591
- return /* @__PURE__ */ jsx8(
1914
+ return /* @__PURE__ */ jsx9(
1592
1915
  "box",
1593
1916
  {
1594
1917
  position: "absolute",
@@ -1602,13 +1925,13 @@ function Toast() {
1602
1925
  border: true,
1603
1926
  borderStyle: "rounded",
1604
1927
  zIndex: 100,
1605
- children: /* @__PURE__ */ jsx8("text", { fg: "#ffffff", selectable: true, children: current.message })
1928
+ children: /* @__PURE__ */ jsx9("text", { fg: "#ffffff", selectable: true, children: current.message })
1606
1929
  }
1607
1930
  );
1608
1931
  }
1609
1932
 
1610
1933
  // src/interactive/App.tsx
1611
- import { jsx as jsx9, jsxs as jsxs7 } from "@opentui/react/jsx-runtime";
1934
+ import { jsx as jsx10, jsxs as jsxs8 } from "@opentui/react/jsx-runtime";
1612
1935
  var FOCUS_ORDER = ["sidebar", "chat-tabs", "chat-history", "chat-input", "info"];
1613
1936
  var MOCK_CHATS = [
1614
1937
  { id: "mock-claude", provider: "claude", title: "Claude Code", createdAt: "", updatedAt: "", processing: false },
@@ -1630,9 +1953,9 @@ var authValue = {
1630
1953
  queryClient
1631
1954
  };
1632
1955
  function App() {
1633
- return /* @__PURE__ */ jsx9(ReplicasAuthProvider, { value: authValue, children: /* @__PURE__ */ jsxs7(ToastProvider, { children: [
1634
- /* @__PURE__ */ jsx9(AppInner, {}),
1635
- /* @__PURE__ */ jsx9(Toast, {})
1956
+ return /* @__PURE__ */ jsx10(ReplicasAuthProvider, { value: authValue, children: /* @__PURE__ */ jsxs8(ToastProvider, { children: [
1957
+ /* @__PURE__ */ jsx10(AppInner, {}),
1958
+ /* @__PURE__ */ jsx10(Toast, {})
1636
1959
  ] }) });
1637
1960
  }
1638
1961
  function AppInner() {
@@ -1652,17 +1975,17 @@ function AppInner() {
1652
1975
  renderer.off("selection", handler);
1653
1976
  };
1654
1977
  }, [renderer, toast]);
1655
- const [selectedWorkspaceId, setSelectedWorkspaceId] = useState5(null);
1656
- const [selectedChatId, setSelectedChatId] = useState5(null);
1657
- const [focusPanel, setFocusPanel] = useState5("sidebar");
1658
- const [taskMode, setTaskMode] = useState5("build");
1659
- const [mockWorkspaces, setMockWorkspaces] = useState5([]);
1978
+ const [selectedWorkspaceId, setSelectedWorkspaceId] = useState7(null);
1979
+ const [selectedChatId, setSelectedChatId] = useState7(null);
1980
+ const [focusPanel, setFocusPanel] = useState7("sidebar");
1981
+ const [taskMode, setTaskMode] = useState7("build");
1982
+ const [mockWorkspaces, setMockWorkspaces] = useState7([]);
1660
1983
  const mockToRealRef = useRef3(/* @__PURE__ */ new Map());
1661
1984
  const mockGroupRef = useRef3(/* @__PURE__ */ new Map());
1662
- const [mockMessages, setMockMessages] = useState5([]);
1663
- const [mockThinking, setMockThinking] = useState5(false);
1985
+ const [mockMessages, setMockMessages] = useState7([]);
1986
+ const [mockThinking, setMockThinking] = useState7(false);
1664
1987
  const pendingMessageRef = useRef3(/* @__PURE__ */ new Map());
1665
- const mockIds = useMemo3(() => new Set(mockWorkspaces.map((m) => m.id)), [mockWorkspaces]);
1988
+ const mockIds = useMemo5(() => new Set(mockWorkspaces.map((m) => m.id)), [mockWorkspaces]);
1666
1989
  const isMockSelected = selectedWorkspaceId ? mockIds.has(selectedWorkspaceId) : false;
1667
1990
  const { data: workspacesData, isLoading: loadingWorkspaces } = useWorkspaces(1, 100, "organization");
1668
1991
  const { data: reposData } = useRepositories();
@@ -1676,7 +1999,7 @@ function AppInner() {
1676
1999
  );
1677
2000
  const { data: chatsData } = useWorkspaceChats(isMockSelected ? null : selectedWorkspaceId);
1678
2001
  const chats = isMockSelected ? MOCK_CHATS : chatsData?.chats ?? [];
1679
- const resolvedChatId = useMemo3(() => {
2002
+ const resolvedChatId = useMemo5(() => {
1680
2003
  if (selectedChatId && chats.find((c) => c.id === selectedChatId)) {
1681
2004
  return selectedChatId;
1682
2005
  }
@@ -1694,22 +2017,22 @@ function AppInner() {
1694
2017
  const deleteWorkspaceMutation = useDeleteWorkspace();
1695
2018
  const wakeWorkspaceMutation = useWakeWorkspace();
1696
2019
  const generateNameMutation = useGenerateWorkspaceName();
1697
- const [wakingWorkspaceId, setWakingWorkspaceId] = useState5(null);
2020
+ const [wakingWorkspaceId, setWakingWorkspaceId] = useState7(null);
1698
2021
  const sendMessageMutation = useSendChatMessage(selectedWorkspaceId, resolvedChatId);
1699
2022
  const interruptMutation = useInterruptChat(selectedWorkspaceId, resolvedChatId);
1700
2023
  const workspaces = workspacesData?.workspaces ?? [];
1701
2024
  const repositories = reposData?.repositories ?? [];
1702
2025
  const repositorySets = setsData?.repository_sets ?? [];
1703
2026
  const previews = previewsData?.previews ?? [];
1704
- const allWorkspaces = useMemo3(() => [...mockWorkspaces, ...workspaces], [mockWorkspaces, workspaces]);
1705
- const groups = useMemo3(
2027
+ const allWorkspaces = useMemo5(() => [...mockWorkspaces, ...workspaces], [mockWorkspaces, workspaces]);
2028
+ const groups = useMemo5(
1706
2029
  () => buildGroups(allWorkspaces, workspacesData, repositories, repositorySets, mockGroupRef.current),
1707
2030
  [allWorkspaces, workspacesData, repositories, repositorySets]
1708
2031
  );
1709
2032
  const selectedWorkspace = allWorkspaces.find((ws) => ws.id === selectedWorkspaceId) ?? null;
1710
2033
  const selectedChat = chats.find((c) => c.id === resolvedChatId) ?? null;
1711
2034
  const isProcessing = mockThinking || (selectedChat?.processing ?? false);
1712
- const displayMessages = useMemo3(() => {
2035
+ const displayMessages = useMemo5(() => {
1713
2036
  if (isMockSelected) return mockMessages;
1714
2037
  const rawEvents = historyData?.events ?? [];
1715
2038
  const events = rawEvents.filter(isAgentBackendEvent);
@@ -1773,17 +2096,17 @@ function AppInner() {
1773
2096
  }, 5e3);
1774
2097
  return () => clearInterval(interval);
1775
2098
  }, [mockWorkspaces.length]);
1776
- const handleSelectWorkspace = useCallback5((workspaceId) => {
2099
+ const handleSelectWorkspace = useCallback6((workspaceId) => {
1777
2100
  setSelectedWorkspaceId(workspaceId);
1778
2101
  setSelectedChatId(null);
1779
2102
  setMockMessages([]);
1780
2103
  setMockThinking(false);
1781
2104
  setFocusPanel("chat-input");
1782
2105
  }, []);
1783
- const handleFocus = useCallback5((panel) => {
2106
+ const handleFocus = useCallback6((panel) => {
1784
2107
  setFocusPanel(panel);
1785
2108
  }, []);
1786
- const handleCreateWorkspace = useCallback5(
2109
+ const handleCreateWorkspace = useCallback6(
1787
2110
  async (groupId, groupType) => {
1788
2111
  const orgId = getOrganizationId() ?? "";
1789
2112
  const mock = createMockWorkspaceRecord(orgId);
@@ -1802,7 +2125,7 @@ function AppInner() {
1802
2125
  },
1803
2126
  [createWorkspaceMutation, toast]
1804
2127
  );
1805
- const handleDeleteWorkspace = useCallback5(
2128
+ const handleDeleteWorkspace = useCallback6(
1806
2129
  async (workspaceId) => {
1807
2130
  if (mockIds.has(workspaceId)) {
1808
2131
  mockGroupRef.current.delete(workspaceId);
@@ -1821,7 +2144,7 @@ function AppInner() {
1821
2144
  },
1822
2145
  [mockIds, selectedWorkspaceId, deleteWorkspaceMutation]
1823
2146
  );
1824
- const handleWakeWorkspace = useCallback5(
2147
+ const handleWakeWorkspace = useCallback6(
1825
2148
  async (workspaceId) => {
1826
2149
  setWakingWorkspaceId(workspaceId);
1827
2150
  try {
@@ -1835,10 +2158,10 @@ function AppInner() {
1835
2158
  },
1836
2159
  [wakeWorkspaceMutation, toast]
1837
2160
  );
1838
- const handleSelectChat = useCallback5((chatId) => {
2161
+ const handleSelectChat = useCallback6((chatId) => {
1839
2162
  setSelectedChatId(chatId);
1840
2163
  }, []);
1841
- useKeyboard3((key) => {
2164
+ useKeyboard4((key) => {
1842
2165
  if (key.name === "f12") {
1843
2166
  renderer.console.toggle();
1844
2167
  return;
@@ -1871,13 +2194,7 @@ function AppInner() {
1871
2194
  setTaskMode((m) => m === "build" ? "plan" : "build");
1872
2195
  return;
1873
2196
  }
1874
- if (key.name === "o" && focusPanel === "info" && selectedWorkspaceId) {
1875
- const webUrl = process.env.REPLICAS_WEB_URL || "https://replicas.dev";
1876
- import("open").then((mod) => mod.default(`${webUrl}/dashboard?workspaceId=${selectedWorkspaceId}`)).catch(() => {
1877
- });
1878
- return;
1879
- }
1880
- if (key.name === "w" && focusPanel !== "sidebar" && selectedWorkspaceId) {
2197
+ if (key.name === "w" && focusPanel !== "sidebar" && focusPanel !== "info" && selectedWorkspaceId) {
1881
2198
  if (statusData?.status === "sleeping" && !wakingWorkspaceId) {
1882
2199
  handleWakeWorkspace(selectedWorkspaceId);
1883
2200
  }
@@ -1885,7 +2202,7 @@ function AppInner() {
1885
2202
  }
1886
2203
  if (focusPanel === "chat-input") return;
1887
2204
  });
1888
- const handleSendMessage = useCallback5(
2205
+ const handleSendMessage = useCallback6(
1889
2206
  async (message) => {
1890
2207
  if (!selectedWorkspaceId || !resolvedChatId) return;
1891
2208
  if (isMockSelected) {
@@ -1902,9 +2219,9 @@ function AppInner() {
1902
2219
  },
1903
2220
  [selectedWorkspaceId, resolvedChatId, isMockSelected, sendMessageMutation, taskMode]
1904
2221
  );
1905
- return /* @__PURE__ */ jsxs7("box", { flexDirection: "column", width: "100%", height: "100%", backgroundColor: "#000000", children: [
1906
- /* @__PURE__ */ jsxs7("box", { flexDirection: "row", flexGrow: 1, backgroundColor: "#000000", children: [
1907
- showWorkspacePanel && /* @__PURE__ */ jsx9(
2222
+ return /* @__PURE__ */ jsxs8("box", { flexDirection: "column", width: "100%", height: "100%", backgroundColor: "#000000", children: [
2223
+ /* @__PURE__ */ jsxs8("box", { flexDirection: "row", flexGrow: 1, backgroundColor: "#000000", children: [
2224
+ showWorkspacePanel && /* @__PURE__ */ jsx10(
1908
2225
  WorkspaceSidebar,
1909
2226
  {
1910
2227
  groups,
@@ -1919,7 +2236,7 @@ function AppInner() {
1919
2236
  loading: loadingWorkspaces
1920
2237
  }
1921
2238
  ),
1922
- selectedWorkspaceId && statusData?.status !== "sleeping" ? /* @__PURE__ */ jsx9(
2239
+ selectedWorkspaceId && statusData?.status !== "sleeping" ? /* @__PURE__ */ jsx10(
1923
2240
  ChatArea,
1924
2241
  {
1925
2242
  chats,
@@ -1933,7 +2250,7 @@ function AppInner() {
1933
2250
  isProcessing,
1934
2251
  loading: loadingMessages
1935
2252
  }
1936
- ) : selectedWorkspaceId && statusData?.status === "sleeping" ? /* @__PURE__ */ jsxs7(
2253
+ ) : selectedWorkspaceId && statusData?.status === "sleeping" ? /* @__PURE__ */ jsxs8(
1937
2254
  "box",
1938
2255
  {
1939
2256
  flexGrow: 1,
@@ -1946,18 +2263,18 @@ function AppInner() {
1946
2263
  flexDirection: "column",
1947
2264
  gap: 1,
1948
2265
  children: [
1949
- /* @__PURE__ */ jsxs7("text", { fg: "#888888", children: [
2266
+ /* @__PURE__ */ jsxs8("text", { fg: "#888888", children: [
1950
2267
  "\u263E",
1951
2268
  " This workspace is sleeping"
1952
2269
  ] }),
1953
- /* @__PURE__ */ jsxs7("text", { fg: "#555555", children: [
2270
+ /* @__PURE__ */ jsxs8("text", { fg: "#555555", children: [
1954
2271
  "Press ",
1955
- /* @__PURE__ */ jsx9("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx9("strong", { children: "w" }) }),
2272
+ /* @__PURE__ */ jsx10("span", { fg: "#66bb6a", children: /* @__PURE__ */ jsx10("strong", { children: "w" }) }),
1956
2273
  " to wake it up"
1957
2274
  ] })
1958
2275
  ]
1959
2276
  }
1960
- ) : /* @__PURE__ */ jsx9(
2277
+ ) : /* @__PURE__ */ jsx10(
1961
2278
  "box",
1962
2279
  {
1963
2280
  flexGrow: 1,
@@ -1967,10 +2284,10 @@ function AppInner() {
1967
2284
  backgroundColor: "#000000",
1968
2285
  justifyContent: "center",
1969
2286
  alignItems: "center",
1970
- children: /* @__PURE__ */ jsx9("text", { fg: "#555555", children: "Create a workspace to begin building!" })
2287
+ children: /* @__PURE__ */ jsx10("text", { fg: "#555555", children: "Create a workspace to begin building!" })
1971
2288
  }
1972
2289
  ),
1973
- showInfoPanel && /* @__PURE__ */ jsx9(
2290
+ showInfoPanel && /* @__PURE__ */ jsx10(
1974
2291
  WorkspaceInfo,
1975
2292
  {
1976
2293
  status: statusData ?? null,
@@ -1989,7 +2306,7 @@ function AppInner() {
1989
2306
  }
1990
2307
  )
1991
2308
  ] }),
1992
- /* @__PURE__ */ jsx9(
2309
+ /* @__PURE__ */ jsx10(
1993
2310
  StatusBar,
1994
2311
  {
1995
2312
  focusPanel
@@ -1999,12 +2316,12 @@ function AppInner() {
1999
2316
  }
2000
2317
 
2001
2318
  // src/interactive/index.tsx
2002
- import { jsx as jsx10 } from "@opentui/react/jsx-runtime";
2319
+ import { jsx as jsx11 } from "@opentui/react/jsx-runtime";
2003
2320
  async function launchInteractive() {
2004
2321
  const renderer = await createCliRenderer({
2005
2322
  exitOnCtrlC: false
2006
2323
  });
2007
- createRoot(renderer).render(/* @__PURE__ */ jsx10(App, {}));
2324
+ createRoot(renderer).render(/* @__PURE__ */ jsx11(App, {}));
2008
2325
  }
2009
2326
  export {
2010
2327
  launchInteractive