claude-yes 1.13.0 → 1.14.1
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/cli.js +242 -4
- package/dist/index.js +242 -4
- package/index.ts +40 -29
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -5075,6 +5075,238 @@ function sleepms(ms) {
|
|
|
5075
5075
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5076
5076
|
}
|
|
5077
5077
|
|
|
5078
|
+
// node_modules/terminal-render/dist/index.js
|
|
5079
|
+
class TerminalTextRender {
|
|
5080
|
+
lines = [""];
|
|
5081
|
+
cursorRow = 0;
|
|
5082
|
+
cursorCol = 0;
|
|
5083
|
+
savedCursorRow = 0;
|
|
5084
|
+
savedCursorCol = 0;
|
|
5085
|
+
isAtRestoredPosition = false;
|
|
5086
|
+
write(data) {
|
|
5087
|
+
for (let i = 0;i < data.length; i++) {
|
|
5088
|
+
const char = data[i];
|
|
5089
|
+
switch (char) {
|
|
5090
|
+
case "\r":
|
|
5091
|
+
this.cursorCol = 0;
|
|
5092
|
+
break;
|
|
5093
|
+
case `
|
|
5094
|
+
`:
|
|
5095
|
+
this.cursorRow++;
|
|
5096
|
+
this.cursorCol = 0;
|
|
5097
|
+
while (this.lines.length <= this.cursorRow) {
|
|
5098
|
+
this.lines.push("");
|
|
5099
|
+
}
|
|
5100
|
+
break;
|
|
5101
|
+
case "\b":
|
|
5102
|
+
if (this.cursorCol > 0) {
|
|
5103
|
+
this.cursorCol--;
|
|
5104
|
+
}
|
|
5105
|
+
break;
|
|
5106
|
+
case "\t":
|
|
5107
|
+
this.cursorCol = Math.floor((this.cursorCol + 8) / 8) * 8;
|
|
5108
|
+
break;
|
|
5109
|
+
default:
|
|
5110
|
+
if (char === "\x1B") {
|
|
5111
|
+
if (this.isEraseSequence(data, i)) {
|
|
5112
|
+
i = this.handleEraseSequence(data, i) - 1;
|
|
5113
|
+
} else if (i + 1 < data.length && data[i + 1] === "[") {
|
|
5114
|
+
const escapeStart = i;
|
|
5115
|
+
i += 2;
|
|
5116
|
+
let escapeEnd = i;
|
|
5117
|
+
while (escapeEnd < data.length && !/[a-zA-Z]/.test(data[escapeEnd])) {
|
|
5118
|
+
escapeEnd++;
|
|
5119
|
+
}
|
|
5120
|
+
if (escapeEnd < data.length) {
|
|
5121
|
+
const escapeCode = data.slice(escapeStart + 2, escapeEnd);
|
|
5122
|
+
const command = data[escapeEnd];
|
|
5123
|
+
this.handleAnsiEscape(escapeCode, command);
|
|
5124
|
+
i = escapeEnd;
|
|
5125
|
+
}
|
|
5126
|
+
} else if (i + 1 < data.length && data[i + 1] === "c") {
|
|
5127
|
+
this.lines = [""];
|
|
5128
|
+
this.cursorRow = 0;
|
|
5129
|
+
this.cursorCol = 0;
|
|
5130
|
+
this.savedCursorRow = 0;
|
|
5131
|
+
this.savedCursorCol = 0;
|
|
5132
|
+
i++;
|
|
5133
|
+
}
|
|
5134
|
+
} else {
|
|
5135
|
+
this.ensureLine(this.cursorRow);
|
|
5136
|
+
const line = this.lines[this.cursorRow];
|
|
5137
|
+
if (this.isAtRestoredPosition && this.cursorCol < line.length) {
|
|
5138
|
+
this.lines[this.cursorRow] = line.substring(0, this.cursorCol) + char + line.substring(this.cursorCol);
|
|
5139
|
+
this.isAtRestoredPosition = false;
|
|
5140
|
+
} else if (this.cursorCol >= line.length) {
|
|
5141
|
+
this.lines[this.cursorRow] = line + " ".repeat(this.cursorCol - line.length) + char;
|
|
5142
|
+
} else {
|
|
5143
|
+
this.lines[this.cursorRow] = line.substring(0, this.cursorCol) + char + line.substring(this.cursorCol + 1);
|
|
5144
|
+
}
|
|
5145
|
+
this.cursorCol++;
|
|
5146
|
+
}
|
|
5147
|
+
break;
|
|
5148
|
+
}
|
|
5149
|
+
}
|
|
5150
|
+
return this;
|
|
5151
|
+
}
|
|
5152
|
+
ensureLine(row) {
|
|
5153
|
+
while (this.lines.length <= row) {
|
|
5154
|
+
this.lines.push("");
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5157
|
+
handleAnsiEscape(escapeCode, command) {
|
|
5158
|
+
switch (command) {
|
|
5159
|
+
case "A": {
|
|
5160
|
+
const upLines = parseInt(escapeCode) || 1;
|
|
5161
|
+
this.cursorRow = Math.max(0, this.cursorRow - upLines);
|
|
5162
|
+
break;
|
|
5163
|
+
}
|
|
5164
|
+
case "B": {
|
|
5165
|
+
const downLines = parseInt(escapeCode) || 1;
|
|
5166
|
+
const originalRow = this.cursorRow;
|
|
5167
|
+
this.cursorRow += downLines;
|
|
5168
|
+
if (this.cursorRow > originalRow + 1) {
|
|
5169
|
+
this.cursorCol = 0;
|
|
5170
|
+
}
|
|
5171
|
+
this.ensureLine(this.cursorRow);
|
|
5172
|
+
break;
|
|
5173
|
+
}
|
|
5174
|
+
case "C": {
|
|
5175
|
+
const forwardCols = parseInt(escapeCode) || 1;
|
|
5176
|
+
this.cursorCol += forwardCols;
|
|
5177
|
+
break;
|
|
5178
|
+
}
|
|
5179
|
+
case "D": {
|
|
5180
|
+
const backwardCols = parseInt(escapeCode) || 1;
|
|
5181
|
+
this.cursorCol = Math.max(0, this.cursorCol - backwardCols);
|
|
5182
|
+
break;
|
|
5183
|
+
}
|
|
5184
|
+
case "E": {
|
|
5185
|
+
const nextLines = parseInt(escapeCode) || 1;
|
|
5186
|
+
this.cursorRow += nextLines;
|
|
5187
|
+
this.cursorCol = 0;
|
|
5188
|
+
this.ensureLine(this.cursorRow);
|
|
5189
|
+
break;
|
|
5190
|
+
}
|
|
5191
|
+
case "F": {
|
|
5192
|
+
const prevLines = parseInt(escapeCode) || 1;
|
|
5193
|
+
this.cursorRow = Math.max(0, this.cursorRow - prevLines);
|
|
5194
|
+
this.cursorCol = 0;
|
|
5195
|
+
break;
|
|
5196
|
+
}
|
|
5197
|
+
case "G": {
|
|
5198
|
+
if (escapeCode === "") {
|
|
5199
|
+
const currentLine = this.lines[this.cursorRow] || "";
|
|
5200
|
+
if (this.cursorRow === 0 && this.lines.length === 1 && this.cursorCol === currentLine.length && currentLine.length > 0) {
|
|
5201
|
+
this.cursorCol = Math.max(0, this.cursorCol - 1);
|
|
5202
|
+
} else {
|
|
5203
|
+
this.cursorCol = 0;
|
|
5204
|
+
}
|
|
5205
|
+
} else {
|
|
5206
|
+
const col = parseInt(escapeCode) || 1;
|
|
5207
|
+
this.cursorCol = Math.max(0, col - 1);
|
|
5208
|
+
}
|
|
5209
|
+
break;
|
|
5210
|
+
}
|
|
5211
|
+
case "H":
|
|
5212
|
+
case "f": {
|
|
5213
|
+
const parts = escapeCode.split(";");
|
|
5214
|
+
this.cursorRow = Math.max(0, (parseInt(parts[0]) || 1) - 1);
|
|
5215
|
+
this.cursorCol = Math.max(0, (parseInt(parts[1]) || 1) - 1);
|
|
5216
|
+
this.isAtRestoredPosition = false;
|
|
5217
|
+
this.ensureLine(this.cursorRow);
|
|
5218
|
+
break;
|
|
5219
|
+
}
|
|
5220
|
+
case "J":
|
|
5221
|
+
if (escapeCode === "2") {
|
|
5222
|
+
this.lines = [""];
|
|
5223
|
+
this.cursorRow = 0;
|
|
5224
|
+
this.cursorCol = 0;
|
|
5225
|
+
}
|
|
5226
|
+
break;
|
|
5227
|
+
case "K":
|
|
5228
|
+
if (escapeCode === "" || escapeCode === "0") {
|
|
5229
|
+
this.ensureLine(this.cursorRow);
|
|
5230
|
+
this.lines[this.cursorRow] = this.lines[this.cursorRow].substring(0, this.cursorCol);
|
|
5231
|
+
} else if (escapeCode === "1") {
|
|
5232
|
+
this.ensureLine(this.cursorRow);
|
|
5233
|
+
this.lines[this.cursorRow] = " ".repeat(this.cursorCol) + this.lines[this.cursorRow].substring(this.cursorCol);
|
|
5234
|
+
} else if (escapeCode === "2") {
|
|
5235
|
+
this.ensureLine(this.cursorRow);
|
|
5236
|
+
this.lines[this.cursorRow] = "";
|
|
5237
|
+
}
|
|
5238
|
+
break;
|
|
5239
|
+
case "s":
|
|
5240
|
+
this.savedCursorRow = this.cursorRow;
|
|
5241
|
+
this.savedCursorCol = this.cursorCol;
|
|
5242
|
+
break;
|
|
5243
|
+
case "u":
|
|
5244
|
+
this.cursorRow = this.savedCursorRow;
|
|
5245
|
+
this.cursorCol = this.savedCursorCol;
|
|
5246
|
+
this.isAtRestoredPosition = true;
|
|
5247
|
+
this.ensureLine(this.cursorRow);
|
|
5248
|
+
break;
|
|
5249
|
+
}
|
|
5250
|
+
}
|
|
5251
|
+
render() {
|
|
5252
|
+
const trimmedLines = [...this.lines];
|
|
5253
|
+
while (trimmedLines.length > 1 && trimmedLines[trimmedLines.length - 1] === "") {
|
|
5254
|
+
trimmedLines.pop();
|
|
5255
|
+
}
|
|
5256
|
+
return trimmedLines.join(`
|
|
5257
|
+
`);
|
|
5258
|
+
}
|
|
5259
|
+
clear() {
|
|
5260
|
+
this.lines = [""];
|
|
5261
|
+
this.cursorRow = 0;
|
|
5262
|
+
this.cursorCol = 0;
|
|
5263
|
+
this.savedCursorRow = 0;
|
|
5264
|
+
this.savedCursorCol = 0;
|
|
5265
|
+
}
|
|
5266
|
+
isEraseSequence(data, i) {
|
|
5267
|
+
const remaining = data.slice(i);
|
|
5268
|
+
if (!remaining.startsWith("\x1B[2K")) {
|
|
5269
|
+
return false;
|
|
5270
|
+
}
|
|
5271
|
+
let pos = 4;
|
|
5272
|
+
while (pos < remaining.length && remaining.slice(pos, pos + 8) === "\x1B[1A\x1B[2K") {
|
|
5273
|
+
pos += 8;
|
|
5274
|
+
}
|
|
5275
|
+
return pos < remaining.length && remaining.slice(pos, pos + 3) === "\x1B[G";
|
|
5276
|
+
}
|
|
5277
|
+
handleEraseSequence(data, i) {
|
|
5278
|
+
const remaining = data.slice(i);
|
|
5279
|
+
if (!remaining.startsWith("\x1B[2K")) {
|
|
5280
|
+
return i;
|
|
5281
|
+
}
|
|
5282
|
+
let pos = 4;
|
|
5283
|
+
let linesToClear = 1;
|
|
5284
|
+
while (pos < remaining.length && remaining.slice(pos, pos + 8) === "\x1B[1A\x1B[2K") {
|
|
5285
|
+
pos += 8;
|
|
5286
|
+
linesToClear++;
|
|
5287
|
+
}
|
|
5288
|
+
if (pos >= remaining.length || remaining.slice(pos, pos + 3) !== "\x1B[G") {
|
|
5289
|
+
return i;
|
|
5290
|
+
}
|
|
5291
|
+
pos += 3;
|
|
5292
|
+
const currentRow = this.cursorRow;
|
|
5293
|
+
if (linesToClear === 2 && remaining === "\x1B[2K\x1B[1A\x1B[2K\x1B[G") {
|
|
5294
|
+
for (let i2 = 0;i2 < 2 && currentRow + i2 < this.lines.length; i2++) {
|
|
5295
|
+
this.lines[currentRow + i2] = "";
|
|
5296
|
+
}
|
|
5297
|
+
this.cursorCol = 0;
|
|
5298
|
+
} else {
|
|
5299
|
+
const startRow = Math.max(0, currentRow - linesToClear + 1);
|
|
5300
|
+
for (let row = startRow;row <= currentRow && row < this.lines.length; row++) {
|
|
5301
|
+
this.lines[row] = "";
|
|
5302
|
+
}
|
|
5303
|
+
this.cursorRow = startRow;
|
|
5304
|
+
this.cursorCol = 0;
|
|
5305
|
+
}
|
|
5306
|
+
return i + pos;
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
|
|
5078
5310
|
// index.ts
|
|
5079
5311
|
async function claudeYes({
|
|
5080
5312
|
continueOnCrash,
|
|
@@ -5155,17 +5387,22 @@ async function claudeYes({
|
|
|
5155
5387
|
}),
|
|
5156
5388
|
readable: shellOutputStream.readable
|
|
5157
5389
|
};
|
|
5390
|
+
const ttr = new TerminalTextRender;
|
|
5158
5391
|
const idleWatcher = createIdleWatcher(async () => {
|
|
5159
5392
|
if (exitOnIdle) {
|
|
5160
|
-
|
|
5161
|
-
|
|
5393
|
+
if (ttr.render().match(/esc to interrupt|to run in background/)) {
|
|
5394
|
+
console.warn("[CLAUDE-YES] Claude is idle, but seems still working, not exiting yet");
|
|
5395
|
+
} else {
|
|
5396
|
+
console.warn("[CLAUDE-YES] Claude is idle, exiting...");
|
|
5397
|
+
await exitClaudeCode();
|
|
5398
|
+
}
|
|
5162
5399
|
}
|
|
5163
5400
|
}, idleTimeout);
|
|
5164
5401
|
const confirm = async () => {
|
|
5165
5402
|
await sleepms(200);
|
|
5166
5403
|
shell.write("\r");
|
|
5167
5404
|
};
|
|
5168
|
-
await src_default(fromReadable(process.stdin)).map((buffer2) => buffer2.toString()).by(shellStdio).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).forEach(async (e2) => {
|
|
5405
|
+
await src_default(fromReadable(process.stdin)).forEach(() => idleWatcher.ping()).map((buffer2) => buffer2.toString()).forEach((text) => ttr.write(text)).by(shellStdio).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).forEach(async (e2) => {
|
|
5169
5406
|
if (e2.match(/❯ 1. Yes/))
|
|
5170
5407
|
return await confirm();
|
|
5171
5408
|
if (e2.match(/❯ 1. Dark mode✔|Press Enter to continue…/))
|
|
@@ -5174,7 +5411,8 @@ async function claudeYes({
|
|
|
5174
5411
|
errorNoConversation = true;
|
|
5175
5412
|
return;
|
|
5176
5413
|
}
|
|
5177
|
-
}).run()).replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line).
|
|
5414
|
+
}).run()).replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout));
|
|
5415
|
+
return ttr.render();
|
|
5178
5416
|
}
|
|
5179
5417
|
// node_modules/enhanced-ms/dist/index.js
|
|
5180
5418
|
var units = {
|
package/dist/index.js
CHANGED
|
@@ -4855,6 +4855,238 @@ function sleepms(ms) {
|
|
|
4855
4855
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4856
4856
|
}
|
|
4857
4857
|
|
|
4858
|
+
// node_modules/terminal-render/dist/index.js
|
|
4859
|
+
class TerminalTextRender {
|
|
4860
|
+
lines = [""];
|
|
4861
|
+
cursorRow = 0;
|
|
4862
|
+
cursorCol = 0;
|
|
4863
|
+
savedCursorRow = 0;
|
|
4864
|
+
savedCursorCol = 0;
|
|
4865
|
+
isAtRestoredPosition = false;
|
|
4866
|
+
write(data) {
|
|
4867
|
+
for (let i = 0;i < data.length; i++) {
|
|
4868
|
+
const char = data[i];
|
|
4869
|
+
switch (char) {
|
|
4870
|
+
case "\r":
|
|
4871
|
+
this.cursorCol = 0;
|
|
4872
|
+
break;
|
|
4873
|
+
case `
|
|
4874
|
+
`:
|
|
4875
|
+
this.cursorRow++;
|
|
4876
|
+
this.cursorCol = 0;
|
|
4877
|
+
while (this.lines.length <= this.cursorRow) {
|
|
4878
|
+
this.lines.push("");
|
|
4879
|
+
}
|
|
4880
|
+
break;
|
|
4881
|
+
case "\b":
|
|
4882
|
+
if (this.cursorCol > 0) {
|
|
4883
|
+
this.cursorCol--;
|
|
4884
|
+
}
|
|
4885
|
+
break;
|
|
4886
|
+
case "\t":
|
|
4887
|
+
this.cursorCol = Math.floor((this.cursorCol + 8) / 8) * 8;
|
|
4888
|
+
break;
|
|
4889
|
+
default:
|
|
4890
|
+
if (char === "\x1B") {
|
|
4891
|
+
if (this.isEraseSequence(data, i)) {
|
|
4892
|
+
i = this.handleEraseSequence(data, i) - 1;
|
|
4893
|
+
} else if (i + 1 < data.length && data[i + 1] === "[") {
|
|
4894
|
+
const escapeStart = i;
|
|
4895
|
+
i += 2;
|
|
4896
|
+
let escapeEnd = i;
|
|
4897
|
+
while (escapeEnd < data.length && !/[a-zA-Z]/.test(data[escapeEnd])) {
|
|
4898
|
+
escapeEnd++;
|
|
4899
|
+
}
|
|
4900
|
+
if (escapeEnd < data.length) {
|
|
4901
|
+
const escapeCode = data.slice(escapeStart + 2, escapeEnd);
|
|
4902
|
+
const command = data[escapeEnd];
|
|
4903
|
+
this.handleAnsiEscape(escapeCode, command);
|
|
4904
|
+
i = escapeEnd;
|
|
4905
|
+
}
|
|
4906
|
+
} else if (i + 1 < data.length && data[i + 1] === "c") {
|
|
4907
|
+
this.lines = [""];
|
|
4908
|
+
this.cursorRow = 0;
|
|
4909
|
+
this.cursorCol = 0;
|
|
4910
|
+
this.savedCursorRow = 0;
|
|
4911
|
+
this.savedCursorCol = 0;
|
|
4912
|
+
i++;
|
|
4913
|
+
}
|
|
4914
|
+
} else {
|
|
4915
|
+
this.ensureLine(this.cursorRow);
|
|
4916
|
+
const line = this.lines[this.cursorRow];
|
|
4917
|
+
if (this.isAtRestoredPosition && this.cursorCol < line.length) {
|
|
4918
|
+
this.lines[this.cursorRow] = line.substring(0, this.cursorCol) + char + line.substring(this.cursorCol);
|
|
4919
|
+
this.isAtRestoredPosition = false;
|
|
4920
|
+
} else if (this.cursorCol >= line.length) {
|
|
4921
|
+
this.lines[this.cursorRow] = line + " ".repeat(this.cursorCol - line.length) + char;
|
|
4922
|
+
} else {
|
|
4923
|
+
this.lines[this.cursorRow] = line.substring(0, this.cursorCol) + char + line.substring(this.cursorCol + 1);
|
|
4924
|
+
}
|
|
4925
|
+
this.cursorCol++;
|
|
4926
|
+
}
|
|
4927
|
+
break;
|
|
4928
|
+
}
|
|
4929
|
+
}
|
|
4930
|
+
return this;
|
|
4931
|
+
}
|
|
4932
|
+
ensureLine(row) {
|
|
4933
|
+
while (this.lines.length <= row) {
|
|
4934
|
+
this.lines.push("");
|
|
4935
|
+
}
|
|
4936
|
+
}
|
|
4937
|
+
handleAnsiEscape(escapeCode, command) {
|
|
4938
|
+
switch (command) {
|
|
4939
|
+
case "A": {
|
|
4940
|
+
const upLines = parseInt(escapeCode) || 1;
|
|
4941
|
+
this.cursorRow = Math.max(0, this.cursorRow - upLines);
|
|
4942
|
+
break;
|
|
4943
|
+
}
|
|
4944
|
+
case "B": {
|
|
4945
|
+
const downLines = parseInt(escapeCode) || 1;
|
|
4946
|
+
const originalRow = this.cursorRow;
|
|
4947
|
+
this.cursorRow += downLines;
|
|
4948
|
+
if (this.cursorRow > originalRow + 1) {
|
|
4949
|
+
this.cursorCol = 0;
|
|
4950
|
+
}
|
|
4951
|
+
this.ensureLine(this.cursorRow);
|
|
4952
|
+
break;
|
|
4953
|
+
}
|
|
4954
|
+
case "C": {
|
|
4955
|
+
const forwardCols = parseInt(escapeCode) || 1;
|
|
4956
|
+
this.cursorCol += forwardCols;
|
|
4957
|
+
break;
|
|
4958
|
+
}
|
|
4959
|
+
case "D": {
|
|
4960
|
+
const backwardCols = parseInt(escapeCode) || 1;
|
|
4961
|
+
this.cursorCol = Math.max(0, this.cursorCol - backwardCols);
|
|
4962
|
+
break;
|
|
4963
|
+
}
|
|
4964
|
+
case "E": {
|
|
4965
|
+
const nextLines = parseInt(escapeCode) || 1;
|
|
4966
|
+
this.cursorRow += nextLines;
|
|
4967
|
+
this.cursorCol = 0;
|
|
4968
|
+
this.ensureLine(this.cursorRow);
|
|
4969
|
+
break;
|
|
4970
|
+
}
|
|
4971
|
+
case "F": {
|
|
4972
|
+
const prevLines = parseInt(escapeCode) || 1;
|
|
4973
|
+
this.cursorRow = Math.max(0, this.cursorRow - prevLines);
|
|
4974
|
+
this.cursorCol = 0;
|
|
4975
|
+
break;
|
|
4976
|
+
}
|
|
4977
|
+
case "G": {
|
|
4978
|
+
if (escapeCode === "") {
|
|
4979
|
+
const currentLine = this.lines[this.cursorRow] || "";
|
|
4980
|
+
if (this.cursorRow === 0 && this.lines.length === 1 && this.cursorCol === currentLine.length && currentLine.length > 0) {
|
|
4981
|
+
this.cursorCol = Math.max(0, this.cursorCol - 1);
|
|
4982
|
+
} else {
|
|
4983
|
+
this.cursorCol = 0;
|
|
4984
|
+
}
|
|
4985
|
+
} else {
|
|
4986
|
+
const col = parseInt(escapeCode) || 1;
|
|
4987
|
+
this.cursorCol = Math.max(0, col - 1);
|
|
4988
|
+
}
|
|
4989
|
+
break;
|
|
4990
|
+
}
|
|
4991
|
+
case "H":
|
|
4992
|
+
case "f": {
|
|
4993
|
+
const parts = escapeCode.split(";");
|
|
4994
|
+
this.cursorRow = Math.max(0, (parseInt(parts[0]) || 1) - 1);
|
|
4995
|
+
this.cursorCol = Math.max(0, (parseInt(parts[1]) || 1) - 1);
|
|
4996
|
+
this.isAtRestoredPosition = false;
|
|
4997
|
+
this.ensureLine(this.cursorRow);
|
|
4998
|
+
break;
|
|
4999
|
+
}
|
|
5000
|
+
case "J":
|
|
5001
|
+
if (escapeCode === "2") {
|
|
5002
|
+
this.lines = [""];
|
|
5003
|
+
this.cursorRow = 0;
|
|
5004
|
+
this.cursorCol = 0;
|
|
5005
|
+
}
|
|
5006
|
+
break;
|
|
5007
|
+
case "K":
|
|
5008
|
+
if (escapeCode === "" || escapeCode === "0") {
|
|
5009
|
+
this.ensureLine(this.cursorRow);
|
|
5010
|
+
this.lines[this.cursorRow] = this.lines[this.cursorRow].substring(0, this.cursorCol);
|
|
5011
|
+
} else if (escapeCode === "1") {
|
|
5012
|
+
this.ensureLine(this.cursorRow);
|
|
5013
|
+
this.lines[this.cursorRow] = " ".repeat(this.cursorCol) + this.lines[this.cursorRow].substring(this.cursorCol);
|
|
5014
|
+
} else if (escapeCode === "2") {
|
|
5015
|
+
this.ensureLine(this.cursorRow);
|
|
5016
|
+
this.lines[this.cursorRow] = "";
|
|
5017
|
+
}
|
|
5018
|
+
break;
|
|
5019
|
+
case "s":
|
|
5020
|
+
this.savedCursorRow = this.cursorRow;
|
|
5021
|
+
this.savedCursorCol = this.cursorCol;
|
|
5022
|
+
break;
|
|
5023
|
+
case "u":
|
|
5024
|
+
this.cursorRow = this.savedCursorRow;
|
|
5025
|
+
this.cursorCol = this.savedCursorCol;
|
|
5026
|
+
this.isAtRestoredPosition = true;
|
|
5027
|
+
this.ensureLine(this.cursorRow);
|
|
5028
|
+
break;
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
render() {
|
|
5032
|
+
const trimmedLines = [...this.lines];
|
|
5033
|
+
while (trimmedLines.length > 1 && trimmedLines[trimmedLines.length - 1] === "") {
|
|
5034
|
+
trimmedLines.pop();
|
|
5035
|
+
}
|
|
5036
|
+
return trimmedLines.join(`
|
|
5037
|
+
`);
|
|
5038
|
+
}
|
|
5039
|
+
clear() {
|
|
5040
|
+
this.lines = [""];
|
|
5041
|
+
this.cursorRow = 0;
|
|
5042
|
+
this.cursorCol = 0;
|
|
5043
|
+
this.savedCursorRow = 0;
|
|
5044
|
+
this.savedCursorCol = 0;
|
|
5045
|
+
}
|
|
5046
|
+
isEraseSequence(data, i) {
|
|
5047
|
+
const remaining = data.slice(i);
|
|
5048
|
+
if (!remaining.startsWith("\x1B[2K")) {
|
|
5049
|
+
return false;
|
|
5050
|
+
}
|
|
5051
|
+
let pos = 4;
|
|
5052
|
+
while (pos < remaining.length && remaining.slice(pos, pos + 8) === "\x1B[1A\x1B[2K") {
|
|
5053
|
+
pos += 8;
|
|
5054
|
+
}
|
|
5055
|
+
return pos < remaining.length && remaining.slice(pos, pos + 3) === "\x1B[G";
|
|
5056
|
+
}
|
|
5057
|
+
handleEraseSequence(data, i) {
|
|
5058
|
+
const remaining = data.slice(i);
|
|
5059
|
+
if (!remaining.startsWith("\x1B[2K")) {
|
|
5060
|
+
return i;
|
|
5061
|
+
}
|
|
5062
|
+
let pos = 4;
|
|
5063
|
+
let linesToClear = 1;
|
|
5064
|
+
while (pos < remaining.length && remaining.slice(pos, pos + 8) === "\x1B[1A\x1B[2K") {
|
|
5065
|
+
pos += 8;
|
|
5066
|
+
linesToClear++;
|
|
5067
|
+
}
|
|
5068
|
+
if (pos >= remaining.length || remaining.slice(pos, pos + 3) !== "\x1B[G") {
|
|
5069
|
+
return i;
|
|
5070
|
+
}
|
|
5071
|
+
pos += 3;
|
|
5072
|
+
const currentRow = this.cursorRow;
|
|
5073
|
+
if (linesToClear === 2 && remaining === "\x1B[2K\x1B[1A\x1B[2K\x1B[G") {
|
|
5074
|
+
for (let i2 = 0;i2 < 2 && currentRow + i2 < this.lines.length; i2++) {
|
|
5075
|
+
this.lines[currentRow + i2] = "";
|
|
5076
|
+
}
|
|
5077
|
+
this.cursorCol = 0;
|
|
5078
|
+
} else {
|
|
5079
|
+
const startRow = Math.max(0, currentRow - linesToClear + 1);
|
|
5080
|
+
for (let row = startRow;row <= currentRow && row < this.lines.length; row++) {
|
|
5081
|
+
this.lines[row] = "";
|
|
5082
|
+
}
|
|
5083
|
+
this.cursorRow = startRow;
|
|
5084
|
+
this.cursorCol = 0;
|
|
5085
|
+
}
|
|
5086
|
+
return i + pos;
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
|
|
4858
5090
|
// index.ts
|
|
4859
5091
|
async function claudeYes({
|
|
4860
5092
|
continueOnCrash,
|
|
@@ -4935,17 +5167,22 @@ async function claudeYes({
|
|
|
4935
5167
|
}),
|
|
4936
5168
|
readable: shellOutputStream.readable
|
|
4937
5169
|
};
|
|
5170
|
+
const ttr = new TerminalTextRender;
|
|
4938
5171
|
const idleWatcher = createIdleWatcher(async () => {
|
|
4939
5172
|
if (exitOnIdle) {
|
|
4940
|
-
|
|
4941
|
-
|
|
5173
|
+
if (ttr.render().match(/esc to interrupt|to run in background/)) {
|
|
5174
|
+
console.warn("[CLAUDE-YES] Claude is idle, but seems still working, not exiting yet");
|
|
5175
|
+
} else {
|
|
5176
|
+
console.warn("[CLAUDE-YES] Claude is idle, exiting...");
|
|
5177
|
+
await exitClaudeCode();
|
|
5178
|
+
}
|
|
4942
5179
|
}
|
|
4943
5180
|
}, idleTimeout);
|
|
4944
5181
|
const confirm = async () => {
|
|
4945
5182
|
await sleepms(200);
|
|
4946
5183
|
shell.write("\r");
|
|
4947
5184
|
};
|
|
4948
|
-
await src_default(fromReadable(process.stdin)).map((buffer2) => buffer2.toString()).by(shellStdio).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).forEach(async (e2) => {
|
|
5185
|
+
await src_default(fromReadable(process.stdin)).forEach(() => idleWatcher.ping()).map((buffer2) => buffer2.toString()).forEach((text) => ttr.write(text)).by(shellStdio).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).forEach(async (e2) => {
|
|
4949
5186
|
if (e2.match(/❯ 1. Yes/))
|
|
4950
5187
|
return await confirm();
|
|
4951
5188
|
if (e2.match(/❯ 1. Dark mode✔|Press Enter to continue…/))
|
|
@@ -4954,7 +5191,8 @@ async function claudeYes({
|
|
|
4954
5191
|
errorNoConversation = true;
|
|
4955
5192
|
return;
|
|
4956
5193
|
}
|
|
4957
|
-
}).run()).replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line).
|
|
5194
|
+
}).run()).replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout));
|
|
5195
|
+
return ttr.render();
|
|
4958
5196
|
}
|
|
4959
5197
|
export {
|
|
4960
5198
|
removeControlCharacters,
|
package/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { fromReadable, fromWritable } from
|
|
2
|
-
import sflow from
|
|
3
|
-
import { createIdleWatcher } from
|
|
4
|
-
import { removeControlCharacters } from
|
|
5
|
-
import { sleepms } from
|
|
6
|
-
|
|
1
|
+
import { fromReadable, fromWritable } from 'from-node-stream';
|
|
2
|
+
import sflow from 'sflow';
|
|
3
|
+
import { createIdleWatcher } from './createIdleWatcher';
|
|
4
|
+
import { removeControlCharacters } from './removeControlCharacters';
|
|
5
|
+
import { sleepms } from './utils';
|
|
6
|
+
import { TerminalTextRender } from 'terminal-render';
|
|
7
7
|
// for debug only
|
|
8
8
|
// if (import.meta.main) await main();
|
|
9
9
|
// async function main() {
|
|
@@ -42,27 +42,27 @@ export default async function claudeYes({
|
|
|
42
42
|
} = {}) {
|
|
43
43
|
const defaultTimeout = 5e3; // 5 seconds idle timeout
|
|
44
44
|
const idleTimeout =
|
|
45
|
-
typeof exitOnIdle ===
|
|
45
|
+
typeof exitOnIdle === 'number' ? exitOnIdle : defaultTimeout;
|
|
46
46
|
|
|
47
47
|
console.log(
|
|
48
|
-
|
|
48
|
+
'⭐ Starting claude, automatically responding to yes/no prompts...'
|
|
49
49
|
);
|
|
50
50
|
console.log(
|
|
51
|
-
|
|
51
|
+
'⚠️ Important Security Warning: Only run this on trusted repositories. This tool automatically responds to prompts and can execute commands without user confirmation. Be aware of potential prompt injection attacks where malicious code or instructions could be embedded in files or user inputs to manipulate the automated responses.'
|
|
52
52
|
);
|
|
53
53
|
|
|
54
54
|
process.stdin.setRawMode?.(true); //must be called any stdout/stdin usage
|
|
55
|
-
const prefix =
|
|
55
|
+
const prefix = ''; // "YESC|"
|
|
56
56
|
const PREFIXLENGTH = prefix.length;
|
|
57
57
|
let errorNoConversation = false; // match 'No conversation found to continue'
|
|
58
58
|
|
|
59
59
|
const shellOutputStream = new TransformStream<string, string>();
|
|
60
60
|
const outputWriter = shellOutputStream.writable.getWriter();
|
|
61
61
|
const pty = globalThis.Bun
|
|
62
|
-
? await import(
|
|
63
|
-
: await import(
|
|
64
|
-
let shell = pty.spawn(
|
|
65
|
-
name:
|
|
62
|
+
? await import('bun-pty')
|
|
63
|
+
: await import('node-pty');
|
|
64
|
+
let shell = pty.spawn('claude', claudeArgs, {
|
|
65
|
+
name: 'xterm-color',
|
|
66
66
|
cols: process.stdout.columns - PREFIXLENGTH,
|
|
67
67
|
rows: process.stdout.rows,
|
|
68
68
|
cwd,
|
|
@@ -81,13 +81,13 @@ export default async function claudeYes({
|
|
|
81
81
|
if (continueOnCrash && exitCode !== 0) {
|
|
82
82
|
if (errorNoConversation) {
|
|
83
83
|
console.log(
|
|
84
|
-
'Claude crashed with "No conversation found to continue", exiting...'
|
|
84
|
+
'Claude crashed with "No conversation found to continue", exiting...'
|
|
85
85
|
);
|
|
86
86
|
void process.exit(exitCode);
|
|
87
87
|
}
|
|
88
|
-
console.log(
|
|
89
|
-
shell = pty.spawn(
|
|
90
|
-
name:
|
|
88
|
+
console.log('Claude crashed, restarting...');
|
|
89
|
+
shell = pty.spawn('claude', ['continue', '--continue'], {
|
|
90
|
+
name: 'xterm-color',
|
|
91
91
|
cols: process.stdout.columns - PREFIXLENGTH,
|
|
92
92
|
rows: process.stdout.rows,
|
|
93
93
|
cwd,
|
|
@@ -102,7 +102,7 @@ export default async function claudeYes({
|
|
|
102
102
|
|
|
103
103
|
const exitClaudeCode = async () => {
|
|
104
104
|
// send exit command to the shell, must sleep a bit to avoid claude treat it as pasted input
|
|
105
|
-
await sflow([
|
|
105
|
+
await sflow(['\r', '/exit', '\r'])
|
|
106
106
|
.forEach(async (e) => {
|
|
107
107
|
await sleepms(200);
|
|
108
108
|
shell.write(e);
|
|
@@ -116,7 +116,7 @@ export default async function claudeYes({
|
|
|
116
116
|
shell.onExit(() => {
|
|
117
117
|
resolve();
|
|
118
118
|
exited = true;
|
|
119
|
-
})
|
|
119
|
+
})
|
|
120
120
|
), // resolve when shell exits
|
|
121
121
|
// if shell doesn't exit in 5 seconds, kill it
|
|
122
122
|
new Promise<void>((resolve) =>
|
|
@@ -124,13 +124,13 @@ export default async function claudeYes({
|
|
|
124
124
|
if (exited) return; // if shell already exited, do nothing
|
|
125
125
|
shell.kill(); // kill the shell process if it doesn't exit in time
|
|
126
126
|
resolve();
|
|
127
|
-
}, 5000)
|
|
127
|
+
}, 5000)
|
|
128
128
|
), // 5 seconds timeout
|
|
129
129
|
]);
|
|
130
130
|
};
|
|
131
131
|
|
|
132
132
|
// when current tty resized, resize the pty
|
|
133
|
-
process.stdout.on(
|
|
133
|
+
process.stdout.on('resize', () => {
|
|
134
134
|
const { columns, rows } = process.stdout;
|
|
135
135
|
shell.resize(columns - PREFIXLENGTH, rows);
|
|
136
136
|
});
|
|
@@ -143,24 +143,33 @@ export default async function claudeYes({
|
|
|
143
143
|
readable: shellOutputStream.readable,
|
|
144
144
|
};
|
|
145
145
|
|
|
146
|
+
const ttr = new TerminalTextRender();
|
|
146
147
|
const idleWatcher = createIdleWatcher(async () => {
|
|
147
148
|
if (exitOnIdle) {
|
|
148
|
-
|
|
149
|
-
|
|
149
|
+
if (ttr.render().match(/esc to interrupt|to run in background/)) {
|
|
150
|
+
console.warn(
|
|
151
|
+
'[CLAUDE-YES] Claude is idle, but seems still working, not exiting yet'
|
|
152
|
+
);
|
|
153
|
+
} else {
|
|
154
|
+
console.warn('[CLAUDE-YES] Claude is idle, exiting...');
|
|
155
|
+
await exitClaudeCode();
|
|
156
|
+
}
|
|
150
157
|
}
|
|
151
158
|
}, idleTimeout);
|
|
152
159
|
const confirm = async () => {
|
|
153
160
|
await sleepms(200);
|
|
154
|
-
shell.write(
|
|
161
|
+
shell.write('\r');
|
|
155
162
|
};
|
|
156
163
|
await sflow(fromReadable<Buffer>(process.stdin))
|
|
164
|
+
.forEach(() => idleWatcher.ping()) // ping the idle watcher on output for last active time to keep track of claude status
|
|
157
165
|
.map((buffer) => buffer.toString())
|
|
166
|
+
.forEach((text) => ttr.write(text))
|
|
158
167
|
// .forEach(e => appendFile('.cache/io.log', "input |" + JSON.stringify(e) + '\n')) // for debugging
|
|
159
168
|
.by(shellStdio)
|
|
160
169
|
.forkTo((e) =>
|
|
161
170
|
e
|
|
162
171
|
.map((e) => removeControlCharacters(e as string))
|
|
163
|
-
.map((e) => e.replaceAll(
|
|
172
|
+
.map((e) => e.replaceAll('\r', '')) // remove carriage return
|
|
164
173
|
.forEach(async (e) => {
|
|
165
174
|
if (e.match(/❯ 1. Yes/)) return await confirm();
|
|
166
175
|
if (e.match(/❯ 1. Dark mode✔|Press Enter to continue…/))
|
|
@@ -170,15 +179,17 @@ export default async function claudeYes({
|
|
|
170
179
|
return;
|
|
171
180
|
}
|
|
172
181
|
})
|
|
182
|
+
|
|
173
183
|
// .forEach(e => appendFile('.cache/io.log', "output|" + JSON.stringify(e) + '\n')) // for debugging
|
|
174
|
-
.run()
|
|
184
|
+
.run()
|
|
175
185
|
)
|
|
176
186
|
.replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line) // add prefix
|
|
177
|
-
.forEach(() => idleWatcher.ping()) // ping the idle watcher on output for last active time to keep track of claude status
|
|
178
187
|
.map((e) =>
|
|
179
|
-
removeControlCharactersFromStdout ? removeControlCharacters(e) : e
|
|
188
|
+
removeControlCharactersFromStdout ? removeControlCharacters(e) : e
|
|
180
189
|
)
|
|
181
190
|
.to(fromWritable(process.stdout));
|
|
191
|
+
|
|
192
|
+
return ttr.render(); // return full rendered logs
|
|
182
193
|
}
|
|
183
194
|
|
|
184
195
|
export { removeControlCharacters };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-yes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.1",
|
|
4
4
|
"homepage": "https://github.com/snomiao/claude-yes#readme",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "snomiao <snomiao@gmail.com>",
|
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
"types": "./index.ts",
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"bun-pty": "^0.3.2",
|
|
65
|
-
"node-pty": "^1.0.0"
|
|
65
|
+
"node-pty": "^1.0.0",
|
|
66
|
+
"terminal-render": "^1.1.0"
|
|
66
67
|
},
|
|
67
68
|
"lint-staged": {
|
|
68
69
|
"*.{ts,js,json,md}": [
|