codeam-cli 1.1.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +63 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -110,7 +110,7 @@ var import_picocolors = __toESM(require("picocolors"));
|
|
|
110
110
|
// package.json
|
|
111
111
|
var package_default = {
|
|
112
112
|
name: "codeam-cli",
|
|
113
|
-
version: "1.1.
|
|
113
|
+
version: "1.1.3",
|
|
114
114
|
description: "Remote control Claude Code from your mobile device",
|
|
115
115
|
main: "dist/index.js",
|
|
116
116
|
bin: {
|
|
@@ -840,11 +840,37 @@ function renderToLines(raw) {
|
|
|
840
840
|
}
|
|
841
841
|
return screen;
|
|
842
842
|
}
|
|
843
|
+
function detectSelector(lines) {
|
|
844
|
+
const hasNav = lines.some((l) => /Enter to select.*↑.*↓.*navigate/i.test(l));
|
|
845
|
+
if (!hasNav) return null;
|
|
846
|
+
const options = [];
|
|
847
|
+
const questionLines = [];
|
|
848
|
+
for (const line of lines) {
|
|
849
|
+
const t = line.trim();
|
|
850
|
+
if (!t) continue;
|
|
851
|
+
if (/^[─━—═]{3,}$/.test(t)) continue;
|
|
852
|
+
if (/^[✳✢✶✻✽⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]\s/.test(t)) continue;
|
|
853
|
+
if (/esc.{0,5}to.{0,5}interrupt/i.test(t)) continue;
|
|
854
|
+
if (/high\s*[·•]\s*\/effort/i.test(t)) continue;
|
|
855
|
+
if (/Enter to select/i.test(t)) continue;
|
|
856
|
+
if (/^[❯>]\s*$/.test(t)) continue;
|
|
857
|
+
const optMatch = t.match(/^[❯>]?\s*(\d+)\.\s+(.+)/);
|
|
858
|
+
if (optMatch) {
|
|
859
|
+
options.push(optMatch[2].trim());
|
|
860
|
+
continue;
|
|
861
|
+
}
|
|
862
|
+
if (line.length > 0 && (line[0] === " " || line[0] === " ") && line.trim().length > 0) continue;
|
|
863
|
+
if (/^[❯>]\s+\S/.test(t)) continue;
|
|
864
|
+
questionLines.push(t);
|
|
865
|
+
}
|
|
866
|
+
if (options.length === 0) return null;
|
|
867
|
+
return { question: questionLines.join("\n").trim(), options };
|
|
868
|
+
}
|
|
843
869
|
function filterChrome(lines) {
|
|
844
870
|
return lines.filter((line) => {
|
|
845
871
|
const t = line.trim();
|
|
846
872
|
if (!t) return false;
|
|
847
|
-
if (/^[
|
|
873
|
+
if (/^[─━—═─\-]{3,}$/.test(t)) return false;
|
|
848
874
|
if (/^[✳✢✶✻✽✴✷✸✹⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏◐◑◒◓▁▂▃▄▅▆▇█]\s/.test(t)) return false;
|
|
849
875
|
if (/esc.{0,5}to.{0,5}interrupt/i.test(t)) return false;
|
|
850
876
|
if (/high\s*[·•]\s*\/effort/i.test(t)) return false;
|
|
@@ -856,11 +882,6 @@ function filterChrome(lines) {
|
|
|
856
882
|
return true;
|
|
857
883
|
});
|
|
858
884
|
}
|
|
859
|
-
function extractContent(raw) {
|
|
860
|
-
const lines = renderToLines(raw);
|
|
861
|
-
const filtered = filterChrome(lines);
|
|
862
|
-
return filtered.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
863
|
-
}
|
|
864
885
|
var OutputService = class _OutputService {
|
|
865
886
|
constructor(sessionId, pluginId) {
|
|
866
887
|
this.sessionId = sessionId;
|
|
@@ -868,20 +889,17 @@ var OutputService = class _OutputService {
|
|
|
868
889
|
}
|
|
869
890
|
sessionId;
|
|
870
891
|
pluginId;
|
|
871
|
-
/** Raw PTY bytes — processed only when we need to send content. */
|
|
872
892
|
rawBuffer = "";
|
|
873
893
|
lastSentContent = "";
|
|
874
894
|
pollTimer = null;
|
|
875
895
|
startTime = 0;
|
|
876
896
|
active = false;
|
|
877
|
-
/** When the last chunk of printable raw content arrived. */
|
|
878
897
|
lastPushTime = 0;
|
|
879
898
|
static POLL_MS = 1e3;
|
|
880
|
-
/** No new printable content for 3 s → Claude finished responding. */
|
|
881
899
|
static IDLE_MS = 3e3;
|
|
882
|
-
/**
|
|
900
|
+
/** Shorter idle threshold for selector detection (UI is ready immediately). */
|
|
901
|
+
static SELECTOR_IDLE_MS = 1500;
|
|
883
902
|
static EMPTY_TIMEOUT_MS = 3e4;
|
|
884
|
-
/** Hard cap — clear typing state after 2 min no matter what. */
|
|
885
903
|
static MAX_MS = 12e4;
|
|
886
904
|
newTurn() {
|
|
887
905
|
this.stopPoll();
|
|
@@ -912,7 +930,19 @@ var OutputService = class _OutputService {
|
|
|
912
930
|
this.finalize();
|
|
913
931
|
return;
|
|
914
932
|
}
|
|
915
|
-
const
|
|
933
|
+
const lines = renderToLines(this.rawBuffer);
|
|
934
|
+
const selector = detectSelector(lines);
|
|
935
|
+
if (selector) {
|
|
936
|
+
const idleMs2 = this.lastPushTime > 0 ? now - this.lastPushTime : elapsed;
|
|
937
|
+
if (idleMs2 >= _OutputService.SELECTOR_IDLE_MS) {
|
|
938
|
+
this.stopPoll();
|
|
939
|
+
this.active = false;
|
|
940
|
+
this.postChunk({ type: "select_prompt", content: selector.question, options: selector.options, done: true }).catch(() => {
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
const content = filterChrome(lines).join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
916
946
|
if (!content) {
|
|
917
947
|
if (elapsed >= _OutputService.EMPTY_TIMEOUT_MS) this.finalize();
|
|
918
948
|
return;
|
|
@@ -929,11 +959,18 @@ var OutputService = class _OutputService {
|
|
|
929
959
|
}
|
|
930
960
|
}
|
|
931
961
|
finalize() {
|
|
932
|
-
const
|
|
962
|
+
const lines = renderToLines(this.rawBuffer);
|
|
963
|
+
const selector = detectSelector(lines);
|
|
933
964
|
this.stopPoll();
|
|
934
965
|
this.active = false;
|
|
935
|
-
|
|
936
|
-
|
|
966
|
+
if (selector) {
|
|
967
|
+
this.postChunk({ type: "select_prompt", content: selector.question, options: selector.options, done: true }).catch(() => {
|
|
968
|
+
});
|
|
969
|
+
} else {
|
|
970
|
+
const content = filterChrome(lines).join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
971
|
+
this.postChunk({ type: "text", content, done: true }).catch(() => {
|
|
972
|
+
});
|
|
973
|
+
}
|
|
937
974
|
}
|
|
938
975
|
stopPoll() {
|
|
939
976
|
if (this.pollTimer) {
|
|
@@ -1022,6 +1059,12 @@ async function start() {
|
|
|
1022
1059
|
if (input) sendPrompt(input);
|
|
1023
1060
|
break;
|
|
1024
1061
|
}
|
|
1062
|
+
case "select_option": {
|
|
1063
|
+
const index = cmd.payload.index ?? 0;
|
|
1064
|
+
const arrows = "\x1B[B".repeat(Math.max(0, index));
|
|
1065
|
+
sendPrompt(arrows);
|
|
1066
|
+
break;
|
|
1067
|
+
}
|
|
1025
1068
|
case "stop_task":
|
|
1026
1069
|
claude.interrupt();
|
|
1027
1070
|
break;
|
|
@@ -1042,6 +1085,10 @@ async function start() {
|
|
|
1042
1085
|
} else if (cmdType === "provide_input") {
|
|
1043
1086
|
const input = inner.input;
|
|
1044
1087
|
if (input) sendPrompt(input);
|
|
1088
|
+
} else if (cmdType === "select_option") {
|
|
1089
|
+
const index = inner.index ?? 0;
|
|
1090
|
+
const arrows = "\x1B[B".repeat(Math.max(0, index));
|
|
1091
|
+
sendPrompt(arrows);
|
|
1045
1092
|
} else if (cmdType === "stop_task") {
|
|
1046
1093
|
claude.interrupt();
|
|
1047
1094
|
}
|