claude-yes 1.73.2 → 1.75.0

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.
@@ -0,0 +1,11 @@
1
+ import { t as CLIS_CONFIG } from "./ts-D_iRstH9.js";
2
+ import "./logger-B9h0djqx.js";
3
+ import "./pidStore-CHLHMBEM.js";
4
+ import "./globalPidIndex-DNEh8a_O.js";
5
+
6
+ //#region ts/SUPPORTED_CLIS.ts
7
+ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
8
+
9
+ //#endregion
10
+ export { SUPPORTED_CLIS };
11
+ //# sourceMappingURL=SUPPORTED_CLIS-Dzf60ENT.js.map
@@ -288,4 +288,4 @@ async function getDefaultConfig() {
288
288
 
289
289
  //#endregion
290
290
  export { agent_yes_config_default as default };
291
- //# sourceMappingURL=agent-yes.config-CyP5iRZf.js.map
291
+ //# sourceMappingURL=agent-yes.config-1LMoK18R.js.map
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  import { n as logger } from "./logger-B9h0djqx.js";
3
- import { n as version, t as name } from "./package-DpfHTSW2.js";
3
+ import { n as version, t as name } from "./package-CE0J-uFT.js";
4
4
  import { argv } from "process";
5
5
  import { execFileSync, spawn } from "child_process";
6
6
  import ms from "ms";
@@ -634,16 +634,23 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
634
634
  process.exit(0);
635
635
  }
636
636
  }
637
+ {
638
+ const { isSubcommand, runSubcommand } = await import("./subcommands-DpOqSs-b.js");
639
+ if (isSubcommand(process.argv[2])) {
640
+ const code = await runSubcommand(process.argv);
641
+ process.exit(code ?? 0);
642
+ }
643
+ }
637
644
  await checkAndAutoUpdate();
638
645
  logger.info(versionString());
639
646
  const config = parseCliArgs(process.argv);
640
647
  if (config.tray) {
641
- const { startTray } = await import("./tray-Bzb1owBN.js");
648
+ const { startTray } = await import("./tray-D5deJPjk.js");
642
649
  await startTray();
643
650
  await new Promise(() => {});
644
651
  }
645
652
  {
646
- const { ensureTray } = await import("./tray-Bzb1owBN.js");
653
+ const { ensureTray } = await import("./tray-D5deJPjk.js");
647
654
  ensureTray();
648
655
  }
649
656
  if (config.useRust) {
@@ -657,7 +664,7 @@ if (config.useRust) {
657
664
  }
658
665
  }
659
666
  if (rustBinary) {
660
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-C7sGMdKJ.js");
667
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-Dzf60ENT.js");
661
668
  const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
662
669
  if (config.verbose) {
663
670
  console.log(`[rust] Using binary: ${rustBinary}`);
@@ -687,7 +694,7 @@ if (config.showVersion) {
687
694
  process.exit(0);
688
695
  }
689
696
  if (config.appendPrompt) {
690
- const { PidStore } = await import("./pidStore-B4yDm3TL.js");
697
+ const { PidStore } = await import("./pidStore-DR1yPY3t.js");
691
698
  const ipcPath = await PidStore.findActiveFifo(process.cwd());
692
699
  if (!ipcPath) {
693
700
  console.error("No active agent with IPC found in current directory.");
@@ -0,0 +1,103 @@
1
+ import { n as logger } from "./logger-B9h0djqx.js";
2
+ import { appendFile, mkdir, readFile } from "fs/promises";
3
+ import { homedir } from "os";
4
+ import path from "path";
5
+ import { lock } from "proper-lockfile";
6
+
7
+ //#region ts/globalPidIndex.ts
8
+ const GLOBAL_DIR = path.join(homedir(), ".agent-yes");
9
+ const GLOBAL_FILE = path.join(GLOBAL_DIR, "pids.jsonl");
10
+ async function ensureDir() {
11
+ await mkdir(GLOBAL_DIR, { recursive: true });
12
+ }
13
+ async function withLock(fn) {
14
+ await ensureDir();
15
+ let release;
16
+ try {
17
+ release = await lock(GLOBAL_DIR, {
18
+ lockfilePath: GLOBAL_FILE + ".lock",
19
+ retries: {
20
+ retries: 5,
21
+ minTimeout: 50,
22
+ maxTimeout: 500
23
+ }
24
+ });
25
+ return await fn();
26
+ } finally {
27
+ await release?.();
28
+ }
29
+ }
30
+ /** Append one full record line. Caller must provide all required fields. */
31
+ async function appendGlobalPid(record) {
32
+ try {
33
+ await withLock(async () => {
34
+ await appendFile(GLOBAL_FILE, JSON.stringify(record) + "\n");
35
+ });
36
+ } catch (error) {
37
+ logger.debug("[globalPidIndex] append failed:", error);
38
+ }
39
+ }
40
+ /** Append a partial status update by pid (status, exit_code, exit_reason). */
41
+ async function updateGlobalPidStatus(pid, patch) {
42
+ try {
43
+ await withLock(async () => {
44
+ const existing = (await readGlobalPidsRaw()).find((r) => r.pid === pid);
45
+ if (!existing) return;
46
+ const merged = {
47
+ ...existing,
48
+ ...patch
49
+ };
50
+ await appendFile(GLOBAL_FILE, JSON.stringify(merged) + "\n");
51
+ });
52
+ } catch (error) {
53
+ logger.debug("[globalPidIndex] updateStatus failed:", error);
54
+ }
55
+ }
56
+ /**
57
+ * Read the file once without merge logic — internal helper for status updates.
58
+ */
59
+ async function readGlobalPidsRaw() {
60
+ let raw;
61
+ try {
62
+ raw = await readFile(GLOBAL_FILE, "utf-8");
63
+ } catch (err) {
64
+ if (err.code === "ENOENT") return [];
65
+ throw err;
66
+ }
67
+ const merged = /* @__PURE__ */ new Map();
68
+ for (const line of raw.split("\n")) {
69
+ const trimmed = line.trim();
70
+ if (!trimmed) continue;
71
+ try {
72
+ const doc = JSON.parse(trimmed);
73
+ if (typeof doc.pid !== "number") continue;
74
+ const prev = merged.get(doc.pid);
75
+ merged.set(doc.pid, prev ? {
76
+ ...prev,
77
+ ...doc
78
+ } : doc);
79
+ } catch {}
80
+ }
81
+ return Array.from(merged.values());
82
+ }
83
+ /**
84
+ * Read all records, last-line-per-pid wins (events get merged).
85
+ * Optionally filter to live processes only.
86
+ */
87
+ async function readGlobalPids(opts = {}) {
88
+ const records = await readGlobalPidsRaw();
89
+ if (!opts.liveOnly) return records;
90
+ return records.filter((r) => r.status !== "exited" && isProcessAlive(r.pid));
91
+ }
92
+ function isProcessAlive(pid) {
93
+ try {
94
+ process.kill(pid, 0);
95
+ return true;
96
+ } catch {
97
+ return false;
98
+ }
99
+ }
100
+
101
+ //#endregion
102
+ export { readGlobalPids as n, updateGlobalPidStatus as r, appendGlobalPid as t };
103
+ //# sourceMappingURL=globalPidIndex-DNEh8a_O.js.map
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
- import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-CsdLrLod.js";
1
+ import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-D_iRstH9.js";
2
2
  import "./logger-B9h0djqx.js";
3
- import "./pidStore-CPrgJSJi.js";
3
+ import "./pidStore-CHLHMBEM.js";
4
+ import "./globalPidIndex-DNEh8a_O.js";
4
5
 
5
6
  export { AgentContext, CLIS_CONFIG, config, agentYes as default, removeControlCharacters };
@@ -1,7 +1,7 @@
1
1
  //#region package.json
2
2
  var name = "agent-yes";
3
- var version = "1.73.1";
3
+ var version = "1.74.0";
4
4
 
5
5
  //#endregion
6
6
  export { version as n, name as t };
7
- //# sourceMappingURL=package-DpfHTSW2.js.map
7
+ //# sourceMappingURL=package-CE0J-uFT.js.map
@@ -1,4 +1,5 @@
1
1
  import { n as logger } from "./logger-B9h0djqx.js";
2
+ import { r as updateGlobalPidStatus, t as appendGlobalPid } from "./globalPidIndex-DNEh8a_O.js";
2
3
  import { closeSync, existsSync, fsyncSync, openSync } from "fs";
3
4
  import { appendFile, mkdir, readFile, rename, writeFile } from "fs/promises";
4
5
  import path from "path";
@@ -202,14 +203,17 @@ var PidStore = class PidStore {
202
203
  }
203
204
  async registerProcess({ pid, cli, args, prompt, cwd }) {
204
205
  const now = Date.now();
206
+ const argsJson = JSON.stringify(args);
207
+ const logFile = path.resolve(this.getLogDir(), `${pid}.log`);
208
+ const fifoFile = this.getFifoPath(pid);
205
209
  const record = {
206
210
  pid,
207
211
  cli,
208
- args: JSON.stringify(args),
212
+ args: argsJson,
209
213
  prompt,
210
214
  cwd,
211
- logFile: path.resolve(this.getLogDir(), `${pid}.log`),
212
- fifoFile: this.getFifoPath(pid),
215
+ logFile,
216
+ fifoFile,
213
217
  status: "active",
214
218
  exitReason: "",
215
219
  startedAt: now
@@ -224,6 +228,18 @@ var PidStore = class PidStore {
224
228
  throw new Error(`Failed to register process ${pid}`);
225
229
  }
226
230
  logger.debug(`[pidStore] Registered process ${pid}`);
231
+ appendGlobalPid({
232
+ pid,
233
+ cli,
234
+ prompt: prompt ?? null,
235
+ cwd,
236
+ log_file: logFile,
237
+ fifo_file: fifoFile,
238
+ status: "active",
239
+ exit_code: null,
240
+ exit_reason: null,
241
+ started_at: now
242
+ }).catch(() => null);
227
243
  return result;
228
244
  }
229
245
  async updateStatus(pid, status, extra) {
@@ -234,6 +250,11 @@ var PidStore = class PidStore {
234
250
  if (extra?.exitCode !== void 0) patch.exitCode = extra.exitCode;
235
251
  await this.store.updateById(existing._id, patch);
236
252
  logger.debug(`[pidStore] Updated process ${pid} status=${status}`);
253
+ updateGlobalPidStatus(pid, {
254
+ status,
255
+ exit_code: extra?.exitCode ?? null,
256
+ exit_reason: extra?.exitReason ?? null
257
+ }).catch(() => null);
237
258
  }
238
259
  getAllRecords() {
239
260
  return this.store.getAll();
@@ -316,4 +337,4 @@ pid-db/
316
337
 
317
338
  //#endregion
318
339
  export { PidStore as t };
319
- //# sourceMappingURL=pidStore-CPrgJSJi.js.map
340
+ //# sourceMappingURL=pidStore-CHLHMBEM.js.map
@@ -0,0 +1,5 @@
1
+ import "./logger-B9h0djqx.js";
2
+ import { t as PidStore } from "./pidStore-CHLHMBEM.js";
3
+ import "./globalPidIndex-DNEh8a_O.js";
4
+
5
+ export { PidStore };
@@ -0,0 +1,391 @@
1
+ import "./logger-B9h0djqx.js";
2
+ import { n as readGlobalPids } from "./globalPidIndex-DNEh8a_O.js";
3
+ import { readFile, stat } from "fs/promises";
4
+ import { homedir } from "os";
5
+ import path from "path";
6
+
7
+ //#region ts/subcommands.ts
8
+ /**
9
+ * `cy ls / read / cat / tail / head / send` subcommand implementations.
10
+ *
11
+ * Mirrors the principles of koho's `terminal-ws-lib.ts` (session list, render
12
+ * via @xterm/headless, keyword-keyed input) — but file-based instead of via
13
+ * a daemon. Reads ~/.agent-yes/pids.jsonl (cross-runtime global index, written
14
+ * by both the TS PidStore and the Rust pid_store::PidStore) and the per-pid
15
+ * raw log files.
16
+ *
17
+ * Returns null when argv[2] is not a known subcommand so cli.ts falls through
18
+ * to the normal agent-spawning flow.
19
+ */
20
+ /**
21
+ * Read the per-cwd TS PidStore JSONL and convert to the global record shape,
22
+ * so pre-existing TS agents that were spawned before the global-index mirror
23
+ * shipped still show up in `cy ls`. Merging is done in `mergeRecords`.
24
+ */
25
+ async function readLocalTsPids(cwd) {
26
+ const jsonlPath = path.join(cwd, ".agent-yes", "pid-records.jsonl");
27
+ let raw;
28
+ try {
29
+ raw = await readFile(jsonlPath, "utf-8");
30
+ } catch {
31
+ return [];
32
+ }
33
+ const docs = /* @__PURE__ */ new Map();
34
+ for (const line of raw.split("\n")) {
35
+ const trimmed = line.trim();
36
+ if (!trimmed) continue;
37
+ try {
38
+ const doc = JSON.parse(trimmed);
39
+ if (!doc._id) continue;
40
+ if (doc.$$deleted) {
41
+ docs.delete(doc._id);
42
+ continue;
43
+ }
44
+ const prev = docs.get(doc._id);
45
+ docs.set(doc._id, prev ? {
46
+ ...prev,
47
+ ...doc
48
+ } : doc);
49
+ } catch {}
50
+ }
51
+ return Array.from(docs.values()).map((d) => ({
52
+ pid: d.pid,
53
+ cli: d.cli,
54
+ prompt: d.prompt ?? null,
55
+ cwd: d.cwd,
56
+ log_file: d.logFile ?? null,
57
+ fifo_file: d.fifoFile ?? null,
58
+ status: d.status ?? "active",
59
+ exit_code: d.exitCode ?? null,
60
+ exit_reason: d.exitReason ?? null,
61
+ started_at: d.startedAt ?? 0
62
+ }));
63
+ }
64
+ /** Merge by pid; later entries (typically from the global file) win. */
65
+ function mergeRecords(...buckets) {
66
+ const out = /* @__PURE__ */ new Map();
67
+ for (const bucket of buckets) for (const r of bucket) {
68
+ const prev = out.get(r.pid);
69
+ out.set(r.pid, prev ? {
70
+ ...prev,
71
+ ...r
72
+ } : r);
73
+ }
74
+ return Array.from(out.values());
75
+ }
76
+ const SUBCOMMANDS = new Set([
77
+ "ls",
78
+ "list",
79
+ "ps",
80
+ "read",
81
+ "cat",
82
+ "tail",
83
+ "head",
84
+ "send"
85
+ ]);
86
+ function isSubcommand(name) {
87
+ return !!name && SUBCOMMANDS.has(name);
88
+ }
89
+ /**
90
+ * Top-level entry. Returns the desired process exit code, or null if argv
91
+ * is not a subcommand invocation.
92
+ */
93
+ async function runSubcommand(argv) {
94
+ const sub = argv[2];
95
+ if (!isSubcommand(sub)) return null;
96
+ const rest = argv.slice(3);
97
+ try {
98
+ switch (sub) {
99
+ case "ls":
100
+ case "list":
101
+ case "ps": return await cmdLs(rest);
102
+ case "read":
103
+ case "cat": return await cmdRead(rest, { mode: "cat" });
104
+ case "tail": return await cmdRead(rest, { mode: "tail" });
105
+ case "head": return await cmdRead(rest, { mode: "head" });
106
+ case "send": return await cmdSend(rest);
107
+ default: return null;
108
+ }
109
+ } catch (err) {
110
+ const msg = err instanceof Error ? err.message : String(err);
111
+ process.stderr.write(`cy ${sub}: ${msg}\n`);
112
+ return 1;
113
+ }
114
+ }
115
+ function parseArgs(rest) {
116
+ const flags = {};
117
+ const positional = [];
118
+ for (let i = 0; i < rest.length; i++) {
119
+ const arg = rest[i];
120
+ if (arg.startsWith("--")) {
121
+ const eq = arg.indexOf("=");
122
+ if (eq >= 0) flags[arg.slice(2, eq)] = arg.slice(eq + 1);
123
+ else {
124
+ const key = arg.slice(2);
125
+ const next = rest[i + 1];
126
+ if ([
127
+ "all",
128
+ "json",
129
+ "latest"
130
+ ].includes(key) || !next || next.startsWith("-")) flags[key] = true;
131
+ else {
132
+ flags[key] = next;
133
+ i++;
134
+ }
135
+ }
136
+ } else if (arg.startsWith("-") && arg.length > 1) if (arg === "-n") {
137
+ flags["n"] = rest[i + 1] ?? "";
138
+ i++;
139
+ } else flags[arg.slice(1)] = true;
140
+ else positional.push(arg);
141
+ }
142
+ return {
143
+ flags,
144
+ positional
145
+ };
146
+ }
147
+ function commonOpts(flags) {
148
+ return {
149
+ all: !!flags.all,
150
+ cwdScope: typeof flags.cwd === "string" ? path.resolve(flags.cwd) : flags.cwd === true ? process.cwd() : null,
151
+ latest: !!flags.latest,
152
+ json: !!flags.json
153
+ };
154
+ }
155
+ function matchKeyword(record, keyword) {
156
+ if (!keyword) return true;
157
+ const kw = keyword.toLowerCase();
158
+ if (/^\d+$/.test(keyword) && record.pid === Number(keyword)) return true;
159
+ if (record.cwd.toLowerCase().includes(kw)) return true;
160
+ if (record.cli.toLowerCase() === kw) return true;
161
+ if (record.prompt && record.prompt.toLowerCase().includes(kw)) return true;
162
+ return false;
163
+ }
164
+ async function listRecords(keyword, opts) {
165
+ let records = mergeRecords(await readLocalTsPids(process.cwd()), opts.cwdScope ? await readLocalTsPids(opts.cwdScope) : [], await readGlobalPids());
166
+ if (!opts.all) records = records.filter((r) => r.status !== "exited" && isPidAlive(r.pid));
167
+ if (opts.cwdScope) {
168
+ const scope = opts.cwdScope;
169
+ records = records.filter((r) => r.cwd === scope || r.cwd.startsWith(scope + path.sep));
170
+ }
171
+ if (keyword) records = records.filter((r) => matchKeyword(r, keyword));
172
+ records.sort((a, b) => b.started_at - a.started_at);
173
+ return records;
174
+ }
175
+ function isPidAlive(pid) {
176
+ try {
177
+ process.kill(pid, 0);
178
+ return true;
179
+ } catch {
180
+ return false;
181
+ }
182
+ }
183
+ async function resolveOne(keyword, opts) {
184
+ if (!keyword) throw new Error("keyword required (pid, cwd substring, cli name, or prompt substring)");
185
+ const matches = await listRecords(keyword, opts);
186
+ if (matches.length === 0) throw new Error(`no running agent matched "${keyword}"`);
187
+ if (matches.length === 1) return matches[0];
188
+ if (opts.latest) return matches[0];
189
+ const lines = matches.slice(0, 10).map((r) => ` ${r.pid} ${r.cli} ${r.cwd}`).join("\n");
190
+ throw new Error(`keyword "${keyword}" matched ${matches.length} agents — disambiguate by pid or pass --latest:\n${lines}`);
191
+ }
192
+ async function cmdLs(rest) {
193
+ const { flags, positional } = parseArgs(rest);
194
+ const opts = commonOpts(flags);
195
+ const keyword = positional[0];
196
+ const records = await listRecords(keyword, opts);
197
+ if (opts.json) {
198
+ process.stdout.write(JSON.stringify(records, null, 2) + "\n");
199
+ return 0;
200
+ }
201
+ if (records.length === 0) {
202
+ process.stderr.write(keyword ? `no running agents matched "${keyword}"\n` : "no running agents\n");
203
+ return 0;
204
+ }
205
+ const termWidth = process.stdout.columns ?? 120;
206
+ const rawCwds = records.map((r) => shortenPath(r.cwd));
207
+ const widths = {
208
+ pid: Math.max(3, ...records.map((r) => String(r.pid).length)),
209
+ cli: Math.max(3, ...records.map((r) => r.cli.length)),
210
+ status: Math.max(6, ...records.map((r) => r.status.length)),
211
+ age: Math.max(3, ...records.map((r) => humanizeAge(Date.now() - r.started_at).length)),
212
+ cwd: Math.max(3, ...rawCwds.map((c) => c.length))
213
+ };
214
+ const fixedWidth = widths.pid + widths.cli + widths.status + widths.age + widths.cwd + 10;
215
+ const promptBudget = Math.max(20, termWidth - fixedWidth - 1);
216
+ const rows = records.map((r) => ({
217
+ pid: String(r.pid),
218
+ cli: r.cli,
219
+ status: r.status,
220
+ age: humanizeAge(Date.now() - r.started_at),
221
+ cwd: shortenPath(r.cwd),
222
+ prompt: truncate(r.prompt ?? "", promptBudget)
223
+ }));
224
+ const header = [
225
+ "PID".padEnd(widths.pid),
226
+ "CLI".padEnd(widths.cli),
227
+ "STATUS".padEnd(widths.status),
228
+ "AGE".padEnd(widths.age),
229
+ "CWD".padEnd(widths.cwd),
230
+ "PROMPT"
231
+ ].join(" ") + "\n";
232
+ process.stdout.write(header);
233
+ for (const r of rows) process.stdout.write([
234
+ r.pid.padEnd(widths.pid),
235
+ r.cli.padEnd(widths.cli),
236
+ r.status.padEnd(widths.status),
237
+ r.age.padEnd(widths.age),
238
+ r.cwd.padEnd(widths.cwd),
239
+ r.prompt
240
+ ].join(" ") + "\n");
241
+ return 0;
242
+ }
243
+ function humanizeAge(ms) {
244
+ if (ms < 1e3) return "0s";
245
+ const s = Math.floor(ms / 1e3);
246
+ if (s < 60) return `${s}s`;
247
+ const m = Math.floor(s / 60);
248
+ if (m < 60) return `${m}m`;
249
+ const h = Math.floor(m / 60);
250
+ if (h < 24) return `${h}h`;
251
+ return `${Math.floor(h / 24)}d`;
252
+ }
253
+ function shortenPath(p) {
254
+ const home = homedir();
255
+ return p.startsWith(home) ? "~" + p.slice(home.length) : p;
256
+ }
257
+ function truncate(s, n) {
258
+ if (s.length <= n) return s;
259
+ return s.slice(0, n - 1) + "…";
260
+ }
261
+ async function cmdRead(rest, { mode }) {
262
+ const { flags, positional } = parseArgs(rest);
263
+ const opts = commonOpts(flags);
264
+ const keyword = positional[0];
265
+ const nFlag = typeof flags.n === "string" ? Number(flags.n) : void 0;
266
+ const n = nFlag !== void 0 && Number.isFinite(nFlag) && nFlag > 0 ? Math.floor(nFlag) : mode === "cat" ? 0 : 96;
267
+ const record = await resolveOne(keyword, opts);
268
+ const logPath = record.log_file;
269
+ if (!logPath) throw new Error(`pid ${record.pid}: no log_file recorded`);
270
+ let stats;
271
+ try {
272
+ stats = await stat(logPath);
273
+ } catch {
274
+ throw new Error(`pid ${record.pid}: log file not found at ${logPath}`);
275
+ }
276
+ if (!stats.isFile()) throw new Error(`pid ${record.pid}: log path is not a file: ${logPath}`);
277
+ const rendered = await renderRawLog(await readFile(logPath), {
278
+ mode,
279
+ n
280
+ });
281
+ process.stdout.write(rendered);
282
+ if (!rendered.endsWith("\n")) process.stdout.write("\n");
283
+ return 0;
284
+ }
285
+ /**
286
+ * Feed the raw PTY bytes through @xterm/headless and emit plain text.
287
+ * Same approach as koho's renderTerminalBuffer + agent-yes's XtermProxy.
288
+ */
289
+ async function renderRawLog(buf, { mode, n }) {
290
+ const cols = 200;
291
+ const rows = 50;
292
+ const scrollback = Math.max(5e4, n + rows + 100);
293
+ try {
294
+ const { Terminal } = await import("@xterm/headless");
295
+ const term = new Terminal({
296
+ cols,
297
+ rows,
298
+ scrollback,
299
+ allowProposedApi: true
300
+ });
301
+ await new Promise((resolve) => term.write(buf, resolve));
302
+ const active = term.buffer.active;
303
+ const lines = [];
304
+ for (let i = 0; i < active.length; i++) {
305
+ const line = active.getLine(i);
306
+ lines.push(line ? line.translateToString(false).trimEnd() : "");
307
+ }
308
+ while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
309
+ if (mode === "cat") return lines.join("\n");
310
+ if (mode === "tail") return lines.slice(Math.max(0, lines.length - n)).join("\n");
311
+ return lines.slice(0, n).join("\n");
312
+ } catch {
313
+ let text = new TextDecoder().decode(buf);
314
+ text = text.replace(/\x1b\[[0-?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-Z\\-_]/g, "").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
315
+ const lines = text.split("\n");
316
+ if (mode === "cat") return lines.join("\n");
317
+ if (mode === "tail") return lines.slice(Math.max(0, lines.length - n)).join("\n");
318
+ return lines.slice(0, n).join("\n");
319
+ }
320
+ }
321
+ async function cmdSend(rest) {
322
+ const { flags, positional } = parseArgs(rest);
323
+ const opts = commonOpts(flags);
324
+ const keyword = positional[0];
325
+ const message = positional.slice(1).join(" ");
326
+ if (!keyword) throw new Error("usage: cy send <keyword> <msg> [--code=enter|esc|ctrl-c|ctrl-y|tab|none]");
327
+ const trailing = controlCodeFromName(typeof flags.code === "string" ? flags.code.toLowerCase() : "enter");
328
+ const record = await resolveOne(keyword, opts);
329
+ const fifoPath = record.fifo_file;
330
+ if (!fifoPath) throw new Error(`pid ${record.pid}: no fifo_file recorded — agent was not started with --stdpush (or was spawned by Rust which doesn't yet support FIFO IPC; see ROADMAP item 10)`);
331
+ const payload = (message ?? "") + trailing;
332
+ await writeToIpc(fifoPath, payload);
333
+ process.stdout.write(`sent to pid ${record.pid} (${record.cli}): ${truncate(payload, 80)}\n`);
334
+ return 0;
335
+ }
336
+ function controlCodeFromName(name) {
337
+ switch (name) {
338
+ case "enter":
339
+ case "cr":
340
+ case "return": return "\r";
341
+ case "esc":
342
+ case "escape": return "\x1B";
343
+ case "ctrl-c":
344
+ case "ctrlc": return "";
345
+ case "ctrl-y":
346
+ case "ctrly": return "";
347
+ case "ctrl-d":
348
+ case "ctrld": return "";
349
+ case "tab": return " ";
350
+ case "none":
351
+ case "": return "";
352
+ default:
353
+ const m = /^raw:0x([0-9a-f]+)$/i.exec(name);
354
+ if (m) return String.fromCharCode(parseInt(m[1], 16));
355
+ throw new Error(`unknown --code=${name}`);
356
+ }
357
+ }
358
+ async function writeToIpc(ipcPath, payload) {
359
+ if (process.platform === "win32") {
360
+ const { connect } = await import("net");
361
+ await new Promise((resolve, reject) => {
362
+ const client = connect(ipcPath);
363
+ const timer = setTimeout(() => {
364
+ client.destroy();
365
+ reject(/* @__PURE__ */ new Error("named pipe connect timeout"));
366
+ }, 5e3);
367
+ client.on("connect", () => {
368
+ clearTimeout(timer);
369
+ client.write(payload);
370
+ client.end();
371
+ resolve();
372
+ });
373
+ client.on("error", (err) => {
374
+ clearTimeout(timer);
375
+ reject(err);
376
+ });
377
+ });
378
+ } else {
379
+ const { openSync, writeFileSync, closeSync } = await import("fs");
380
+ const fd = openSync(ipcPath, "w");
381
+ try {
382
+ writeFileSync(fd, payload);
383
+ } finally {
384
+ closeSync(fd);
385
+ }
386
+ }
387
+ }
388
+
389
+ //#endregion
390
+ export { isSubcommand, runSubcommand };
391
+ //# sourceMappingURL=subcommands-DpOqSs-b.js.map
@@ -175,4 +175,4 @@ async function startTray() {
175
175
 
176
176
  //#endregion
177
177
  export { ensureTray, startTray };
178
- //# sourceMappingURL=tray-Bzb1owBN.js.map
178
+ //# sourceMappingURL=tray-D5deJPjk.js.map
@@ -1,7 +1,7 @@
1
1
  import { n as logger, t as addTransport } from "./logger-B9h0djqx.js";
2
- import { n as version } from "./package-DpfHTSW2.js";
2
+ import { n as version } from "./package-CE0J-uFT.js";
3
3
  import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-DQWJSptq.js";
4
- import { t as PidStore } from "./pidStore-CPrgJSJi.js";
4
+ import { t as PidStore } from "./pidStore-CHLHMBEM.js";
5
5
  import { arch, platform } from "process";
6
6
  import { execSync } from "child_process";
7
7
  import { closeSync, constants, createReadStream, existsSync, mkdirSync, openSync } from "fs";
@@ -1032,7 +1032,7 @@ async function notifyWebhook(status, details, cwd = process.cwd()) {
1032
1032
 
1033
1033
  //#endregion
1034
1034
  //#region ts/index.ts
1035
- const config = await import("./agent-yes.config-CyP5iRZf.js").then((mod) => mod.default || mod);
1035
+ const config = await import("./agent-yes.config-1LMoK18R.js").then((mod) => mod.default || mod);
1036
1036
  const CLIS_CONFIG = config.clis;
1037
1037
  /**
1038
1038
  * Main function to run agent-cli with automatic yes/no responses
@@ -1679,4 +1679,4 @@ function sleep(ms) {
1679
1679
 
1680
1680
  //#endregion
1681
1681
  export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
1682
- //# sourceMappingURL=ts-CsdLrLod.js.map
1682
+ //# sourceMappingURL=ts-D_iRstH9.js.map