agent-yes 1.72.4 → 1.73.2
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/agent-yes.config.schema.json +32 -8
- package/default.config.yaml +154 -0
- package/dist/SUPPORTED_CLIS-C7sGMdKJ.js +10 -0
- package/dist/{agent-yes.config-CtQprJrA.js → agent-yes.config-CyP5iRZf.js} +75 -119
- package/dist/cli.js +147 -16
- package/dist/index.js +3 -2
- package/dist/logger-B9h0djqx.js +51 -0
- package/dist/package-DpfHTSW2.js +7 -0
- package/dist/pidStore-B4yDm3TL.js +4 -0
- package/dist/pidStore-CPrgJSJi.js +319 -0
- package/dist/{runningLock-BBI_URhR.js → runningLock-DQWJSptq.js} +3 -3
- package/dist/{tray-CPpdxTV-.js → tray-Bzb1owBN.js} +4 -4
- package/dist/{SUPPORTED_CLIS-Bqw9gxey.js → ts-CsdLrLod.js} +146 -362
- package/package.json +9 -3
- package/ts/cli.ts +16 -9
- package/ts/configLoader.spec.ts +19 -0
- package/ts/configLoader.ts +8 -2
- package/ts/configShared.spec.ts +97 -0
- package/ts/configShared.ts +158 -0
- package/ts/index.ts +93 -102
- package/ts/logger.spec.ts +27 -0
- package/ts/logger.ts +63 -19
- package/ts/parseCliArgs.spec.ts +88 -0
- package/ts/parseCliArgs.ts +48 -10
- package/ts/rustBinary.ts +68 -0
- package/ts/versionChecker.spec.ts +48 -0
- package/ts/versionChecker.ts +67 -10
- package/ts/xterm-proxy.ts +130 -0
- package/dist/logger-CX77vJDA.js +0 -16
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as getRunningAgentCount } from "./runningLock-
|
|
1
|
+
import { n as getRunningAgentCount } from "./runningLock-DQWJSptq.js";
|
|
2
|
+
import { existsSync } from "fs";
|
|
2
3
|
import { mkdir, readFile, unlink, writeFile } from "fs/promises";
|
|
3
|
-
import path from "path";
|
|
4
4
|
import { homedir } from "os";
|
|
5
|
-
import
|
|
5
|
+
import path from "path";
|
|
6
6
|
|
|
7
7
|
//#region ts/tray.ts
|
|
8
8
|
const POLL_INTERVAL = 2e3;
|
|
@@ -175,4 +175,4 @@ async function startTray() {
|
|
|
175
175
|
|
|
176
176
|
//#endregion
|
|
177
177
|
export { ensureTray, startTray };
|
|
178
|
-
//# sourceMappingURL=tray-
|
|
178
|
+
//# sourceMappingURL=tray-Bzb1owBN.js.map
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { n as logger, t as addTransport } from "./logger-B9h0djqx.js";
|
|
2
|
+
import { n as version } from "./package-DpfHTSW2.js";
|
|
3
|
+
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-DQWJSptq.js";
|
|
4
|
+
import { t as PidStore } from "./pidStore-CPrgJSJi.js";
|
|
3
5
|
import { arch, platform } from "process";
|
|
4
6
|
import { execSync } from "child_process";
|
|
7
|
+
import { closeSync, constants, createReadStream, existsSync, mkdirSync, openSync } from "fs";
|
|
8
|
+
import { mkdir, readFile, readdir, unlink, writeFile } from "fs/promises";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
import path, { dirname, join } from "path";
|
|
5
11
|
import { execaCommandSync, parseCommandString } from "execa";
|
|
6
12
|
import { fromReadable, fromWritable } from "from-node-stream";
|
|
7
|
-
import { appendFile, mkdir, readFile, readdir, rename, unlink, writeFile } from "fs/promises";
|
|
8
|
-
import path, { dirname, join } from "path";
|
|
9
13
|
import DIE from "phpdie";
|
|
10
14
|
import sflow from "sflow";
|
|
11
|
-
import
|
|
12
|
-
import { homedir } from "os";
|
|
13
|
-
import winston from "winston";
|
|
14
|
-
import { closeSync, constants, createReadStream, existsSync, fsyncSync, mkdirSync, openSync } from "fs";
|
|
15
|
+
import xterm from "@xterm/headless";
|
|
15
16
|
import { createServer } from "net";
|
|
16
|
-
import { lock } from "proper-lockfile";
|
|
17
17
|
import { execSync as execSync$1 } from "node:child_process";
|
|
18
18
|
import { fileURLToPath } from "url";
|
|
19
19
|
import os from "node:os";
|
|
@@ -37,6 +37,109 @@ var __exportAll = (all, no_symbols) => {
|
|
|
37
37
|
return target;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region ts/xterm-proxy.ts
|
|
42
|
+
const { Terminal } = xterm;
|
|
43
|
+
/**
|
|
44
|
+
* XtermProxy wraps @xterm/headless to act as a full xterm terminal emulator
|
|
45
|
+
* between a PTY process and downstream consumers.
|
|
46
|
+
*
|
|
47
|
+
* It automatically responds to ALL terminal queries (DSR, DA, OSC, etc.)
|
|
48
|
+
* by piping xterm's onData responses back to the PTY — so the spawned
|
|
49
|
+
* process never blocks waiting for a terminal reply, even in non-TTY
|
|
50
|
+
* environments or when the real terminal is backgrounded.
|
|
51
|
+
*/
|
|
52
|
+
var XtermProxy = class {
|
|
53
|
+
term;
|
|
54
|
+
writeToPty;
|
|
55
|
+
readableController = null;
|
|
56
|
+
/** Downstream readable — passthrough of PTY output for sflow pipeline */
|
|
57
|
+
readable;
|
|
58
|
+
constructor(opts) {
|
|
59
|
+
const cols = opts.cols ?? 80;
|
|
60
|
+
const rows = opts.rows ?? 24;
|
|
61
|
+
this.writeToPty = opts.writeToPty;
|
|
62
|
+
this.term = new Terminal({
|
|
63
|
+
cols,
|
|
64
|
+
rows,
|
|
65
|
+
allowProposedApi: true,
|
|
66
|
+
scrollback: 1e4
|
|
67
|
+
});
|
|
68
|
+
this.term.onData((data) => {
|
|
69
|
+
logger.debug("xterm-proxy|onData response", data);
|
|
70
|
+
this.writeToPty(data);
|
|
71
|
+
});
|
|
72
|
+
this.readable = new ReadableStream({ start: (controller) => {
|
|
73
|
+
this.readableController = controller;
|
|
74
|
+
} });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Feed PTY output into the xterm emulator.
|
|
78
|
+
* - xterm processes escape sequences and updates internal state
|
|
79
|
+
* - Terminal queries (ESC[6n, ESC[c, etc.) trigger onData → writeToPty
|
|
80
|
+
* - Raw data is pushed to readable for downstream consumption
|
|
81
|
+
*/
|
|
82
|
+
write(data) {
|
|
83
|
+
this.term.write(data, () => {
|
|
84
|
+
try {
|
|
85
|
+
this.readableController?.enqueue(data);
|
|
86
|
+
} catch {}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** Get cursor position from xterm's buffer state */
|
|
90
|
+
getCursorPosition() {
|
|
91
|
+
const buf = this.term.buffer.active;
|
|
92
|
+
return {
|
|
93
|
+
row: buf.cursorY,
|
|
94
|
+
col: buf.cursorX
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the last N lines of rendered terminal content (plain text, no ANSI).
|
|
99
|
+
* Equivalent to terminal-render's tail(n).
|
|
100
|
+
*/
|
|
101
|
+
tail(n) {
|
|
102
|
+
const buf = this.term.buffer.active;
|
|
103
|
+
const totalLines = buf.length;
|
|
104
|
+
const startLine = Math.max(0, totalLines - n);
|
|
105
|
+
const lines = [];
|
|
106
|
+
for (let i = startLine; i < totalLines; i++) {
|
|
107
|
+
const line = buf.getLine(i);
|
|
108
|
+
lines.push(line ? line.translateToString(true) : "");
|
|
109
|
+
}
|
|
110
|
+
while (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
|
|
111
|
+
return lines.join("\n");
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Render the full terminal buffer as plain text.
|
|
115
|
+
* Equivalent to terminal-render's render().
|
|
116
|
+
*/
|
|
117
|
+
render() {
|
|
118
|
+
const buf = this.term.buffer.active;
|
|
119
|
+
const lines = [];
|
|
120
|
+
for (let i = 0; i < buf.length; i++) {
|
|
121
|
+
const line = buf.getLine(i);
|
|
122
|
+
lines.push(line ? line.translateToString(true) : "");
|
|
123
|
+
}
|
|
124
|
+
while (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
|
|
125
|
+
return lines.join("\n");
|
|
126
|
+
}
|
|
127
|
+
/** Resize the virtual terminal */
|
|
128
|
+
resize(cols, rows) {
|
|
129
|
+
this.term.resize(cols, rows);
|
|
130
|
+
}
|
|
131
|
+
/** Clean up resources */
|
|
132
|
+
dispose() {
|
|
133
|
+
if (this.readableController) {
|
|
134
|
+
try {
|
|
135
|
+
this.readableController.close();
|
|
136
|
+
} catch {}
|
|
137
|
+
this.readableController = null;
|
|
138
|
+
}
|
|
139
|
+
this.term.dispose();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
40
143
|
//#endregion
|
|
41
144
|
//#region ts/resume/codexSessionManager.ts
|
|
42
145
|
const getSessionsFile = () => process.env.CLI_YES_TEST_HOME ? path.join(process.env.CLI_YES_TEST_HOME, ".config", "agent-yes", "codex-sessions.json") : path.join(homedir(), ".config", "agent-yes", "codex-sessions.json");
|
|
@@ -336,317 +439,6 @@ async function createLinuxFifo(cli, customPath) {
|
|
|
336
439
|
}
|
|
337
440
|
}
|
|
338
441
|
|
|
339
|
-
//#endregion
|
|
340
|
-
//#region ts/JsonlStore.ts
|
|
341
|
-
/**
|
|
342
|
-
* A lightweight NeDB-style JSONL persistence layer.
|
|
343
|
-
*
|
|
344
|
-
* - Append-only writes (one JSON object per line)
|
|
345
|
-
* - Same `_id` → last line wins (fields merged)
|
|
346
|
-
* - `$$deleted` lines act as tombstones
|
|
347
|
-
* - Crash recovery: skip partial last line, recover from temp file
|
|
348
|
-
* - Multi-process safe via proper-lockfile (reads don't need lock)
|
|
349
|
-
* - Compact on close: deduplicates into clean file via atomic rename
|
|
350
|
-
*/
|
|
351
|
-
var JsonlStore = class {
|
|
352
|
-
filePath;
|
|
353
|
-
tempPath;
|
|
354
|
-
docs = /* @__PURE__ */ new Map();
|
|
355
|
-
constructor(filePath) {
|
|
356
|
-
this.filePath = filePath;
|
|
357
|
-
this.tempPath = filePath + "~";
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* Load all records from the JSONL file. No lock needed.
|
|
361
|
-
* Handles crash recovery: partial last line skipped, temp file recovery.
|
|
362
|
-
*/
|
|
363
|
-
async load() {
|
|
364
|
-
await mkdir(path.dirname(this.filePath), { recursive: true });
|
|
365
|
-
if (!existsSync(this.filePath) && existsSync(this.tempPath)) {
|
|
366
|
-
logger.debug("[JsonlStore] Recovering from temp file");
|
|
367
|
-
await rename(this.tempPath, this.filePath);
|
|
368
|
-
}
|
|
369
|
-
this.docs = /* @__PURE__ */ new Map();
|
|
370
|
-
let raw = "";
|
|
371
|
-
try {
|
|
372
|
-
raw = await readFile(this.filePath, "utf-8");
|
|
373
|
-
} catch (err) {
|
|
374
|
-
if (err.code === "ENOENT") return this.docs;
|
|
375
|
-
throw err;
|
|
376
|
-
}
|
|
377
|
-
const lines = raw.split("\n");
|
|
378
|
-
let corruptCount = 0;
|
|
379
|
-
for (const line of lines) {
|
|
380
|
-
const trimmed = line.trim();
|
|
381
|
-
if (!trimmed) continue;
|
|
382
|
-
try {
|
|
383
|
-
const doc = JSON.parse(trimmed);
|
|
384
|
-
if (!doc._id) continue;
|
|
385
|
-
if (doc.$$deleted) this.docs.delete(doc._id);
|
|
386
|
-
else {
|
|
387
|
-
const existing = this.docs.get(doc._id);
|
|
388
|
-
if (existing) this.docs.set(doc._id, {
|
|
389
|
-
...existing,
|
|
390
|
-
...doc
|
|
391
|
-
});
|
|
392
|
-
else this.docs.set(doc._id, doc);
|
|
393
|
-
}
|
|
394
|
-
} catch {
|
|
395
|
-
corruptCount++;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
if (corruptCount > 0) logger.debug(`[JsonlStore] Skipped ${corruptCount} corrupt line(s) in ${this.filePath}`);
|
|
399
|
-
return this.docs;
|
|
400
|
-
}
|
|
401
|
-
/** Get all live documents. */
|
|
402
|
-
getAll() {
|
|
403
|
-
return Array.from(this.docs.values());
|
|
404
|
-
}
|
|
405
|
-
/** Find a document by _id. */
|
|
406
|
-
getById(id) {
|
|
407
|
-
return this.docs.get(id);
|
|
408
|
-
}
|
|
409
|
-
/** Find documents matching a predicate. */
|
|
410
|
-
find(predicate) {
|
|
411
|
-
return this.getAll().filter(predicate);
|
|
412
|
-
}
|
|
413
|
-
/** Find first document matching a predicate. */
|
|
414
|
-
findOne(predicate) {
|
|
415
|
-
for (const doc of this.docs.values()) if (predicate(doc)) return doc;
|
|
416
|
-
}
|
|
417
|
-
/**
|
|
418
|
-
* Append a new document. Acquires lock.
|
|
419
|
-
* If no _id is provided, one is generated.
|
|
420
|
-
*/
|
|
421
|
-
async append(doc) {
|
|
422
|
-
const id = doc._id || generateId();
|
|
423
|
-
const { _id: _, ...rest } = doc;
|
|
424
|
-
const fullDoc = {
|
|
425
|
-
_id: id,
|
|
426
|
-
...rest
|
|
427
|
-
};
|
|
428
|
-
return await this.withLock(async () => {
|
|
429
|
-
await appendFile(this.filePath, JSON.stringify(fullDoc) + "\n");
|
|
430
|
-
const existing = this.docs.get(fullDoc._id);
|
|
431
|
-
if (existing) this.docs.set(fullDoc._id, {
|
|
432
|
-
...existing,
|
|
433
|
-
...fullDoc
|
|
434
|
-
});
|
|
435
|
-
else this.docs.set(fullDoc._id, fullDoc);
|
|
436
|
-
return fullDoc;
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Update a document by _id. Appends a merge line. Acquires lock.
|
|
441
|
-
*/
|
|
442
|
-
async updateById(id, patch) {
|
|
443
|
-
await this.withLock(async () => {
|
|
444
|
-
const line = {
|
|
445
|
-
_id: id,
|
|
446
|
-
...patch
|
|
447
|
-
};
|
|
448
|
-
await appendFile(this.filePath, JSON.stringify(line) + "\n");
|
|
449
|
-
const existing = this.docs.get(id);
|
|
450
|
-
if (existing) this.docs.set(id, {
|
|
451
|
-
...existing,
|
|
452
|
-
...patch
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* Delete a document by _id. Appends a tombstone. Acquires lock.
|
|
458
|
-
*/
|
|
459
|
-
async deleteById(id) {
|
|
460
|
-
await this.withLock(async () => {
|
|
461
|
-
const tombstone = {
|
|
462
|
-
_id: id,
|
|
463
|
-
$$deleted: true
|
|
464
|
-
};
|
|
465
|
-
await appendFile(this.filePath, JSON.stringify(tombstone) + "\n");
|
|
466
|
-
this.docs.delete(id);
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Compact the file: deduplicate entries, remove tombstones.
|
|
471
|
-
* Writes to temp file, fsyncs, then atomic renames.
|
|
472
|
-
* Acquires lock.
|
|
473
|
-
*/
|
|
474
|
-
async compact() {
|
|
475
|
-
const lines = Array.from(this.docs.values()).map((doc) => {
|
|
476
|
-
const { _id, $$deleted: _$$deleted, ...rest } = doc;
|
|
477
|
-
return JSON.stringify({
|
|
478
|
-
_id,
|
|
479
|
-
...rest
|
|
480
|
-
});
|
|
481
|
-
}).join("\n");
|
|
482
|
-
const content = lines ? lines + "\n" : "";
|
|
483
|
-
try {
|
|
484
|
-
await this.withLock(async () => {
|
|
485
|
-
await writeFile(this.tempPath, content);
|
|
486
|
-
const fd = openSync(this.tempPath, "r");
|
|
487
|
-
fsyncSync(fd);
|
|
488
|
-
closeSync(fd);
|
|
489
|
-
await rename(this.tempPath, this.filePath);
|
|
490
|
-
});
|
|
491
|
-
} catch {
|
|
492
|
-
await writeFile(this.filePath, content);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
async withLock(fn) {
|
|
496
|
-
const dir = path.dirname(this.filePath);
|
|
497
|
-
let release;
|
|
498
|
-
try {
|
|
499
|
-
release = await lock(dir, {
|
|
500
|
-
lockfilePath: this.filePath + ".lock",
|
|
501
|
-
retries: {
|
|
502
|
-
retries: 5,
|
|
503
|
-
minTimeout: 50,
|
|
504
|
-
maxTimeout: 500
|
|
505
|
-
}
|
|
506
|
-
});
|
|
507
|
-
return await fn();
|
|
508
|
-
} finally {
|
|
509
|
-
if (release) await release();
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
|
-
let idCounter = 0;
|
|
514
|
-
function generateId() {
|
|
515
|
-
return Date.now().toString(36) + (idCounter++).toString(36) + Math.random().toString(36).slice(2, 6);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
//#endregion
|
|
519
|
-
//#region ts/pidStore.ts
|
|
520
|
-
var PidStore = class PidStore {
|
|
521
|
-
storeDir;
|
|
522
|
-
store;
|
|
523
|
-
constructor(workingDir) {
|
|
524
|
-
this.storeDir = path.resolve(workingDir, ".agent-yes");
|
|
525
|
-
this.store = new JsonlStore(path.join(this.storeDir, "pid-records.jsonl"));
|
|
526
|
-
}
|
|
527
|
-
async init() {
|
|
528
|
-
try {
|
|
529
|
-
await this.ensureGitignore();
|
|
530
|
-
await this.store.load();
|
|
531
|
-
await this.cleanStaleRecords();
|
|
532
|
-
} catch (error) {
|
|
533
|
-
logger.warn("[pidStore] Failed to initialize:", error);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
async registerProcess({ pid, cli, args, prompt, cwd }) {
|
|
537
|
-
const now = Date.now();
|
|
538
|
-
const record = {
|
|
539
|
-
pid,
|
|
540
|
-
cli,
|
|
541
|
-
args: JSON.stringify(args),
|
|
542
|
-
prompt,
|
|
543
|
-
cwd,
|
|
544
|
-
logFile: path.resolve(this.getLogDir(), `${pid}.log`),
|
|
545
|
-
fifoFile: this.getFifoPath(pid),
|
|
546
|
-
status: "active",
|
|
547
|
-
exitReason: "",
|
|
548
|
-
startedAt: now
|
|
549
|
-
};
|
|
550
|
-
const existing = this.store.findOne((doc) => doc.pid === pid);
|
|
551
|
-
if (existing) await this.store.updateById(existing._id, record);
|
|
552
|
-
else await this.store.append(record);
|
|
553
|
-
const result = this.store.findOne((doc) => doc.pid === pid);
|
|
554
|
-
if (!result) {
|
|
555
|
-
const allRecords = this.store.getAll();
|
|
556
|
-
logger.error(`[pidStore] Failed to find record for PID ${pid}. All records:`, allRecords);
|
|
557
|
-
throw new Error(`Failed to register process ${pid}`);
|
|
558
|
-
}
|
|
559
|
-
logger.debug(`[pidStore] Registered process ${pid}`);
|
|
560
|
-
return result;
|
|
561
|
-
}
|
|
562
|
-
async updateStatus(pid, status, extra) {
|
|
563
|
-
const existing = this.store.findOne((doc) => doc.pid === pid);
|
|
564
|
-
if (!existing) return;
|
|
565
|
-
const patch = { status };
|
|
566
|
-
if (extra?.exitReason !== void 0) patch.exitReason = extra.exitReason;
|
|
567
|
-
if (extra?.exitCode !== void 0) patch.exitCode = extra.exitCode;
|
|
568
|
-
await this.store.updateById(existing._id, patch);
|
|
569
|
-
logger.debug(`[pidStore] Updated process ${pid} status=${status}`);
|
|
570
|
-
}
|
|
571
|
-
getAllRecords() {
|
|
572
|
-
return this.store.getAll();
|
|
573
|
-
}
|
|
574
|
-
getLogDir() {
|
|
575
|
-
return path.resolve(this.storeDir, "logs");
|
|
576
|
-
}
|
|
577
|
-
getFifoPath(pid) {
|
|
578
|
-
if (process.platform === "win32") return `\\\\.\\pipe\\agent-yes-${pid}`;
|
|
579
|
-
else return path.resolve(this.storeDir, "fifo", `${pid}.stdin`);
|
|
580
|
-
}
|
|
581
|
-
async cleanStaleRecords() {
|
|
582
|
-
const activeRecords = this.store.find((r) => r.status !== "exited");
|
|
583
|
-
for (const record of activeRecords) if (!this.isProcessAlive(record.pid)) {
|
|
584
|
-
await this.store.updateById(record._id, {
|
|
585
|
-
status: "exited",
|
|
586
|
-
exitReason: "stale-cleanup"
|
|
587
|
-
});
|
|
588
|
-
logger.debug(`[pidStore] Cleaned stale record for PID ${record.pid}`);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
async close() {
|
|
592
|
-
try {
|
|
593
|
-
await this.store.compact();
|
|
594
|
-
} catch (error) {
|
|
595
|
-
logger.debug("[pidStore] Compact on close failed:", error);
|
|
596
|
-
}
|
|
597
|
-
logger.debug("[pidStore] Database compacted and closed");
|
|
598
|
-
}
|
|
599
|
-
isProcessAlive(pid) {
|
|
600
|
-
try {
|
|
601
|
-
process.kill(pid, 0);
|
|
602
|
-
return true;
|
|
603
|
-
} catch {
|
|
604
|
-
return false;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
async ensureGitignore() {
|
|
608
|
-
const gitignorePath = path.join(this.storeDir, ".gitignore");
|
|
609
|
-
const gitignoreContent = `# Auto-generated .gitignore for agent-yes
|
|
610
|
-
# Ignore all log files and runtime data
|
|
611
|
-
logs/
|
|
612
|
-
fifo/
|
|
613
|
-
pid-db/
|
|
614
|
-
*.jsonl
|
|
615
|
-
*.jsonl~
|
|
616
|
-
*.jsonl.lock
|
|
617
|
-
*.sqlite
|
|
618
|
-
*.sqlite-*
|
|
619
|
-
*.log
|
|
620
|
-
*.raw.log
|
|
621
|
-
*.lines.log
|
|
622
|
-
*.debug.log
|
|
623
|
-
|
|
624
|
-
# Ignore .gitignore itself
|
|
625
|
-
.gitignore
|
|
626
|
-
|
|
627
|
-
`;
|
|
628
|
-
try {
|
|
629
|
-
await mkdir(this.storeDir, { recursive: true });
|
|
630
|
-
await writeFile(gitignorePath, gitignoreContent, { flag: "wx" });
|
|
631
|
-
logger.debug(`[pidStore] Created .gitignore in ${this.storeDir}`);
|
|
632
|
-
} catch (error) {
|
|
633
|
-
if (error.code !== "EEXIST") logger.warn(`[pidStore] Failed to create .gitignore:`, error);
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
static async findActiveFifo(workingDir) {
|
|
637
|
-
try {
|
|
638
|
-
const store = new PidStore(workingDir);
|
|
639
|
-
await store.init();
|
|
640
|
-
const records = store.store.find((r) => r.status !== "exited").sort((a, b) => b.startedAt - a.startedAt);
|
|
641
|
-
await store.close();
|
|
642
|
-
return records[0]?.fifoFile ?? null;
|
|
643
|
-
} catch (error) {
|
|
644
|
-
logger.warn("[pidStore] findActiveFifo failed:", error);
|
|
645
|
-
return null;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
};
|
|
649
|
-
|
|
650
442
|
//#endregion
|
|
651
443
|
//#region ts/idleWaiter.ts
|
|
652
444
|
/**
|
|
@@ -758,11 +550,14 @@ async function initializeLogPaths(pidStore, pid) {
|
|
|
758
550
|
* Setup debug logging to file
|
|
759
551
|
* @param debuggingLogsPath Path to debug log file
|
|
760
552
|
*/
|
|
761
|
-
function setupDebugLogging(debuggingLogsPath) {
|
|
762
|
-
if (debuggingLogsPath)
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
553
|
+
async function setupDebugLogging(debuggingLogsPath) {
|
|
554
|
+
if (debuggingLogsPath) {
|
|
555
|
+
const { default: winston } = await import("winston");
|
|
556
|
+
await addTransport(new winston.transports.File({
|
|
557
|
+
filename: debuggingLogsPath,
|
|
558
|
+
level: "debug"
|
|
559
|
+
}));
|
|
560
|
+
}
|
|
766
561
|
}
|
|
767
562
|
/**
|
|
768
563
|
* Save rendered terminal output to log file
|
|
@@ -812,11 +607,6 @@ function tryCatch(catchFn, fn) {
|
|
|
812
607
|
};
|
|
813
608
|
}
|
|
814
609
|
|
|
815
|
-
//#endregion
|
|
816
|
-
//#region package.json
|
|
817
|
-
var name = "agent-yes";
|
|
818
|
-
var version = "1.72.4";
|
|
819
|
-
|
|
820
610
|
//#endregion
|
|
821
611
|
//#region ts/pty-fix.ts
|
|
822
612
|
var pty_fix_exports = /* @__PURE__ */ __exportAll({});
|
|
@@ -1242,7 +1032,7 @@ async function notifyWebhook(status, details, cwd = process.cwd()) {
|
|
|
1242
1032
|
|
|
1243
1033
|
//#endregion
|
|
1244
1034
|
//#region ts/index.ts
|
|
1245
|
-
const config = await import("./agent-yes.config-
|
|
1035
|
+
const config = await import("./agent-yes.config-CyP5iRZf.js").then((mod) => mod.default || mod);
|
|
1246
1036
|
const CLIS_CONFIG = config.clis;
|
|
1247
1037
|
/**
|
|
1248
1038
|
* Main function to run agent-cli with automatic yes/no responses
|
|
@@ -1299,9 +1089,11 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1299
1089
|
if (verbose) logger.debug(`[stdin] isTTY: ${process.stdin.isTTY}, setRawMode available: ${!!process.stdin.setRawMode}`);
|
|
1300
1090
|
process.stdin.setRawMode?.(true);
|
|
1301
1091
|
if (verbose) logger.debug(`[stdin] Raw mode set, isRaw: ${process.stdin.isRaw}`);
|
|
1302
|
-
|
|
1303
|
-
const
|
|
1304
|
-
|
|
1092
|
+
let shellWrite = () => {};
|
|
1093
|
+
const xtermProxy = new XtermProxy({
|
|
1094
|
+
...getTerminalDimensions(),
|
|
1095
|
+
writeToPty: (data) => shellWrite(data)
|
|
1096
|
+
});
|
|
1305
1097
|
logger.debug(`Using ${ptyPackage} for pseudo terminal management.`);
|
|
1306
1098
|
if (!!process.env.CLAUDE_PPID) logger.info(`[${cli}-yes] Running as sub-agent (CLAUDE_PPID=${process.env.CLAUDE_PPID})`);
|
|
1307
1099
|
const cliConf = CLIS_CONFIG[cli] || {};
|
|
@@ -1393,9 +1185,10 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1393
1185
|
install,
|
|
1394
1186
|
ptyOptions
|
|
1395
1187
|
});
|
|
1188
|
+
shellWrite = (data) => shell.write(data);
|
|
1396
1189
|
function onData(data) {
|
|
1397
1190
|
const currentPid = shell.pid;
|
|
1398
|
-
|
|
1191
|
+
xtermProxy.write(data);
|
|
1399
1192
|
globalAgentRegistry.appendStdout(currentPid, data);
|
|
1400
1193
|
}
|
|
1401
1194
|
shell.onData(onData);
|
|
@@ -1412,7 +1205,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1412
1205
|
}
|
|
1413
1206
|
notifyWebhook("RUNNING", prompt ?? "", workingDir).catch(() => null);
|
|
1414
1207
|
const logPaths = await initializeLogPaths(pidStore, shell.pid);
|
|
1415
|
-
setupDebugLogging(logPaths.debuggingLogsPath);
|
|
1208
|
+
await setupDebugLogging(logPaths.debuggingLogsPath);
|
|
1416
1209
|
const ctx = new AgentContext({
|
|
1417
1210
|
shell,
|
|
1418
1211
|
pidStore,
|
|
@@ -1479,6 +1272,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1479
1272
|
env: ptyEnv
|
|
1480
1273
|
};
|
|
1481
1274
|
shell = pty.spawn(bin, args, restartPtyOptions);
|
|
1275
|
+
shellWrite = (data) => shell.write(data);
|
|
1482
1276
|
try {
|
|
1483
1277
|
await pidStore.registerProcess({
|
|
1484
1278
|
pid: shell.pid,
|
|
@@ -1561,6 +1355,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1561
1355
|
env: ptyEnv
|
|
1562
1356
|
};
|
|
1563
1357
|
shell = pty.spawn(cli, restoreArgs, restorePtyOptions);
|
|
1358
|
+
shellWrite = (data) => shell.write(data);
|
|
1564
1359
|
try {
|
|
1565
1360
|
await pidStore.registerProcess({
|
|
1566
1361
|
pid: shell.pid,
|
|
@@ -1609,15 +1404,16 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1609
1404
|
process.stdout.on("resize", () => {
|
|
1610
1405
|
const { cols, rows } = getTerminalDimensions();
|
|
1611
1406
|
shell.resize(cols, rows);
|
|
1407
|
+
xtermProxy.resize(cols, rows);
|
|
1612
1408
|
});
|
|
1613
1409
|
const isStillWorkingQ = () => {
|
|
1614
|
-
const rendered =
|
|
1410
|
+
const rendered = xtermProxy.tail(24).replace(/\s+/g, " ");
|
|
1615
1411
|
return conf.working?.some((rgx) => rgx.test(rendered));
|
|
1616
1412
|
};
|
|
1617
1413
|
let lastHeartbeatRendered = "";
|
|
1618
1414
|
const heartbeatInterval = setInterval(async () => {
|
|
1619
1415
|
try {
|
|
1620
|
-
const rendered = removeControlCharacters(
|
|
1416
|
+
const rendered = removeControlCharacters(xtermProxy.tail(12));
|
|
1621
1417
|
if (rendered === lastHeartbeatRendered) return;
|
|
1622
1418
|
lastHeartbeatRendered = rendered;
|
|
1623
1419
|
const lines = rendered.split("\n").filter((line) => line.trim());
|
|
@@ -1792,7 +1588,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1792
1588
|
await ctx.stdinReady.wait();
|
|
1793
1589
|
shell.write(data);
|
|
1794
1590
|
} }),
|
|
1795
|
-
readable:
|
|
1591
|
+
readable: xtermProxy.readable
|
|
1796
1592
|
}).forEach(() => {
|
|
1797
1593
|
ctx.idleWaiter.ping();
|
|
1798
1594
|
pidStore.updateStatus(shell.pid, "active").catch(() => null);
|
|
@@ -1808,19 +1604,10 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1808
1604
|
}).catch(() => f.run());
|
|
1809
1605
|
}).by(function consoleResponder(e) {
|
|
1810
1606
|
let lastRendered = "";
|
|
1811
|
-
return e.forEach((
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
return;
|
|
1816
|
-
}
|
|
1817
|
-
if (process.stdin.isTTY) return;
|
|
1818
|
-
if (!chunk.includes("\x1B[6n")) return;
|
|
1819
|
-
const { col, row } = terminalRender.getCursorPosition();
|
|
1820
|
-
shell.write(`\u001b[${row};${col}R`);
|
|
1821
|
-
logger.debug(`cursor|respond position: row=${String(row)}, col=${String(col)}`);
|
|
1822
|
-
}).forEach(async (line, lineIndex) => {
|
|
1823
|
-
if (terminalRender.tail(24) === lastRendered) return;
|
|
1607
|
+
return e.forEach(async (line, lineIndex) => {
|
|
1608
|
+
const rendered = xtermProxy.tail(24);
|
|
1609
|
+
if (rendered === lastRendered) return;
|
|
1610
|
+
lastRendered = rendered;
|
|
1824
1611
|
logger.debug(`stdout|${line}`);
|
|
1825
1612
|
if (conf.ready?.some((rx) => line.match(rx))) {
|
|
1826
1613
|
logger.debug(`ready |${line}`);
|
|
@@ -1854,15 +1641,16 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1854
1641
|
}
|
|
1855
1642
|
});
|
|
1856
1643
|
}).by((s) => removeControlCharactersFromStdout ? s.map((e) => removeControlCharacters(e)) : s).by(createTerminatorStream(pendingExitCode.promise)).to(fromWritable(process.stdout));
|
|
1857
|
-
await saveLogFile(ctx.logPaths.logPath,
|
|
1644
|
+
await saveLogFile(ctx.logPaths.logPath, xtermProxy.render());
|
|
1858
1645
|
const exitCode = await pendingExitCode.promise;
|
|
1859
1646
|
logger.info(`[${cli}-yes] ${cli} exited with code ${exitCode}`);
|
|
1860
1647
|
await pidStore.close();
|
|
1861
|
-
|
|
1862
|
-
|
|
1648
|
+
const finalRender = xtermProxy.render();
|
|
1649
|
+
xtermProxy.dispose();
|
|
1650
|
+
await saveDeprecatedLogFile(logFile, finalRender, verbose);
|
|
1863
1651
|
return {
|
|
1864
1652
|
exitCode,
|
|
1865
|
-
logs:
|
|
1653
|
+
logs: finalRender
|
|
1866
1654
|
};
|
|
1867
1655
|
async function exitAgent() {
|
|
1868
1656
|
ctx.robust = false;
|
|
@@ -1890,9 +1678,5 @@ function sleep(ms) {
|
|
|
1890
1678
|
}
|
|
1891
1679
|
|
|
1892
1680
|
//#endregion
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
//#endregion
|
|
1897
|
-
export { AgentContext as a, PidStore as c, config as i, removeControlCharacters as l, CLIS_CONFIG as n, name as o, agentYes as r, version as s, SUPPORTED_CLIS as t };
|
|
1898
|
-
//# sourceMappingURL=SUPPORTED_CLIS-Bqw9gxey.js.map
|
|
1681
|
+
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1682
|
+
//# sourceMappingURL=ts-CsdLrLod.js.map
|