agent-yes 1.75.1 → 1.75.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/README.md CHANGED
@@ -130,6 +130,25 @@ claude-yes --exit-on-idle=60s "run all tests and commit current changes"
130
130
  claude-code-execute claude-yes "your task here"
131
131
  ```
132
132
 
133
+ ### Inspect and message running agents (`cy ls / read / send`)
134
+
135
+ From any terminal you can list and interact with agents that are already
136
+ running on the machine — both TS- and Rust-spawned ones:
137
+
138
+ ```bash
139
+ cy ls # list all running agents
140
+ cy ls codex # filter (matches pid, cwd, cli, or prompt)
141
+ cy tail <keyword> # render last 96 lines via @xterm/headless
142
+ cy read <keyword> # full rendered log
143
+ cy send <keyword> "next: run tests" # append a prompt to that agent's stdin
144
+ cy send <keyword> "" --code=ctrl-c # send a Ctrl+C
145
+ ```
146
+
147
+ `cy` (and `ay` / `agent-yes`) writes to a shared registry at
148
+ `~/.agent-yes/pids.jsonl` and a per-pid FIFO at `~/.agent-yes/fifo/<pid>.stdin`,
149
+ so subcommands work whether the target agent is the TS or Rust runtime.
150
+ Detailed reference (Japanese): [`docs/cy-subcommands.md`](./docs/cy-subcommands.md).
151
+
133
152
  ### Docker Usage
134
153
 
135
154
  You can run `agent-yes` in a Docker container with all AI CLI tools pre-installed.
@@ -0,0 +1,11 @@
1
+ import { t as CLIS_CONFIG } from "./ts-Cuys5-PF.js";
2
+ import "./logger-B9h0djqx.js";
3
+ import "./pidStore-C1JXxoPi.js";
4
+ import "./globalPidIndex-Cr-g75QF.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-C2w9JqbM.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-DRIilF5m.js";
3
+ import { n as version, t as name } from "./package-8zpT1iww.js";
4
4
  import { argv } from "process";
5
5
  import { execFileSync, spawn } from "child_process";
6
6
  import ms from "ms";
@@ -635,7 +635,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
635
635
  }
636
636
  }
637
637
  {
638
- const { isSubcommand, runSubcommand } = await import("./subcommands-NWIZy8od.js");
638
+ const { isSubcommand, runSubcommand } = await import("./subcommands-DSm9WL-6.js");
639
639
  if (isSubcommand(process.argv[2])) {
640
640
  const code = await runSubcommand(process.argv);
641
641
  process.exit(code ?? 0);
@@ -664,7 +664,7 @@ if (config.useRust) {
664
664
  }
665
665
  }
666
666
  if (rustBinary) {
667
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-CqAT1Zud.js");
667
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-C2w9JqbM.js");
668
668
  const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
669
669
  if (config.verbose) {
670
670
  console.log(`[rust] Using binary: ${rustBinary}`);
@@ -694,7 +694,7 @@ if (config.showVersion) {
694
694
  process.exit(0);
695
695
  }
696
696
  if (config.appendPrompt) {
697
- const { PidStore } = await import("./pidStore-CF54dFqr.js");
697
+ const { PidStore } = await import("./pidStore-BCsY5BW3.js");
698
698
  const ipcPath = await PidStore.findActiveFifo(process.cwd());
699
699
  if (!ipcPath) {
700
700
  console.error("No active agent with IPC found in current directory.");
@@ -1,5 +1,5 @@
1
1
  import { n as logger } from "./logger-B9h0djqx.js";
2
- import { appendFile, mkdir, readFile } from "fs/promises";
2
+ import { appendFile, mkdir, readFile, rename, writeFile } from "fs/promises";
3
3
  import { homedir } from "os";
4
4
  import path from "path";
5
5
  import { lock } from "proper-lockfile";
@@ -108,7 +108,37 @@ function isProcessAlive(pid) {
108
108
  return false;
109
109
  }
110
110
  }
111
+ const COMPACT_THRESHOLD_LINES = 500;
112
+ /**
113
+ * Best-effort compaction: rewrite the JSONL file with one line per known pid,
114
+ * dropping records whose pid is dead AND status is exited (those won't be
115
+ * referenced by `cy ls` anyway). Triggered opportunistically when the raw
116
+ * file grows past `COMPACT_THRESHOLD_LINES`. Safe to call unconditionally;
117
+ * it no-ops when the file is already small enough.
118
+ */
119
+ async function maybeCompactGlobalPids() {
120
+ let raw;
121
+ try {
122
+ raw = await readFile(resolveGlobalFile(), "utf-8");
123
+ } catch (err) {
124
+ if (err.code === "ENOENT") return;
125
+ return;
126
+ }
127
+ const lineCount = raw.split("\n").filter((l) => l.trim()).length;
128
+ if (lineCount < COMPACT_THRESHOLD_LINES) return;
129
+ try {
130
+ await withLock(async () => {
131
+ const keep = (await readGlobalPidsRaw()).filter((r) => r.status !== "exited" || isProcessAlive(r.pid));
132
+ const tmpFile = resolveGlobalFile() + ".compact";
133
+ await writeFile(tmpFile, keep.map((r) => JSON.stringify(r)).join("\n") + (keep.length ? "\n" : ""));
134
+ await rename(tmpFile, resolveGlobalFile());
135
+ logger.debug(`[globalPidIndex] compacted ${lineCount} → ${keep.length} lines`);
136
+ });
137
+ } catch (error) {
138
+ logger.debug("[globalPidIndex] compact failed:", error);
139
+ }
140
+ }
111
141
 
112
142
  //#endregion
113
- export { readGlobalPids as n, updateGlobalPidStatus as r, appendGlobalPid as t };
114
- //# sourceMappingURL=globalPidIndex-BHCkWll6.js.map
143
+ export { updateGlobalPidStatus as i, maybeCompactGlobalPids as n, readGlobalPids as r, appendGlobalPid as t };
144
+ //# sourceMappingURL=globalPidIndex-Cr-g75QF.js.map
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-DfT_yx7e.js";
1
+ import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-Cuys5-PF.js";
2
2
  import "./logger-B9h0djqx.js";
3
- import "./pidStore-CYmzzaQQ.js";
4
- import "./globalPidIndex-BHCkWll6.js";
3
+ import "./pidStore-C1JXxoPi.js";
4
+ import "./globalPidIndex-Cr-g75QF.js";
5
5
 
6
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.75.0";
3
+ var version = "1.75.1";
4
4
 
5
5
  //#endregion
6
6
  export { version as n, name as t };
7
- //# sourceMappingURL=package-DRIilF5m.js.map
7
+ //# sourceMappingURL=package-8zpT1iww.js.map
@@ -0,0 +1,5 @@
1
+ import "./logger-B9h0djqx.js";
2
+ import { t as PidStore } from "./pidStore-C1JXxoPi.js";
3
+ import "./globalPidIndex-Cr-g75QF.js";
4
+
5
+ export { PidStore };
@@ -1,5 +1,5 @@
1
1
  import { n as logger } from "./logger-B9h0djqx.js";
2
- import { r as updateGlobalPidStatus, t as appendGlobalPid } from "./globalPidIndex-BHCkWll6.js";
2
+ import { i as updateGlobalPidStatus, n as maybeCompactGlobalPids, t as appendGlobalPid } from "./globalPidIndex-Cr-g75QF.js";
3
3
  import { closeSync, existsSync, fsyncSync, openSync } from "fs";
4
4
  import { appendFile, mkdir, readFile, rename, writeFile } from "fs/promises";
5
5
  import path from "path";
@@ -239,7 +239,7 @@ var PidStore = class PidStore {
239
239
  exit_code: null,
240
240
  exit_reason: null,
241
241
  started_at: now
242
- }).catch(() => null);
242
+ }).then(() => maybeCompactGlobalPids()).catch(() => null);
243
243
  return result;
244
244
  }
245
245
  async updateStatus(pid, status, extra) {
@@ -337,4 +337,4 @@ pid-db/
337
337
 
338
338
  //#endregion
339
339
  export { PidStore as t };
340
- //# sourceMappingURL=pidStore-CYmzzaQQ.js.map
340
+ //# sourceMappingURL=pidStore-C1JXxoPi.js.map
@@ -1,5 +1,5 @@
1
1
  import "./logger-B9h0djqx.js";
2
- import { n as readGlobalPids } from "./globalPidIndex-BHCkWll6.js";
2
+ import { r as readGlobalPids } from "./globalPidIndex-Cr-g75QF.js";
3
3
  import { readFile, stat } from "fs/promises";
4
4
  import { homedir } from "os";
5
5
  import path from "path";
@@ -388,4 +388,4 @@ async function writeToIpc(ipcPath, payload) {
388
388
 
389
389
  //#endregion
390
390
  export { isSubcommand, runSubcommand };
391
- //# sourceMappingURL=subcommands-NWIZy8od.js.map
391
+ //# sourceMappingURL=subcommands-DSm9WL-6.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-DRIilF5m.js";
2
+ import { n as version } from "./package-8zpT1iww.js";
3
3
  import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-DQWJSptq.js";
4
- import { t as PidStore } from "./pidStore-CYmzzaQQ.js";
4
+ import { t as PidStore } from "./pidStore-C1JXxoPi.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";
@@ -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-DfT_yx7e.js.map
1682
+ //# sourceMappingURL=ts-Cuys5-PF.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-yes",
3
- "version": "1.75.1",
3
+ "version": "1.75.2",
4
4
  "description": "A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses.",
5
5
  "keywords": [
6
6
  "ai",
@@ -142,6 +142,69 @@ describe("globalPidIndex", () => {
142
142
  expect(records).toEqual([]);
143
143
  });
144
144
 
145
+ it("maybeCompactGlobalPids no-ops when below threshold", async () => {
146
+ const mod = await loadModule();
147
+ await mod.appendGlobalPid({
148
+ pid: 1234,
149
+ cli: "claude",
150
+ prompt: null,
151
+ cwd: "/a",
152
+ log_file: null,
153
+ status: "active",
154
+ exit_code: null,
155
+ exit_reason: null,
156
+ started_at: 1,
157
+ });
158
+ const before = (await import("fs/promises")).readFile;
159
+ const beforeContent = await before(mod.getGlobalPidIndexPath(), "utf-8");
160
+ await mod.maybeCompactGlobalPids();
161
+ const afterContent = await before(mod.getGlobalPidIndexPath(), "utf-8");
162
+ expect(afterContent).toBe(beforeContent);
163
+ });
164
+
165
+ it("maybeCompactGlobalPids collapses event spam to one line per pid", async () => {
166
+ const mod = await loadModule();
167
+ // Emit > 500 status events across two pids (one alive, one will be exited+dead)
168
+ for (let i = 0; i < 260; i++) {
169
+ await mod.appendGlobalPid({
170
+ pid: process.pid,
171
+ cli: "claude",
172
+ prompt: null,
173
+ cwd: "/a",
174
+ log_file: null,
175
+ status: "active",
176
+ exit_code: null,
177
+ exit_reason: null,
178
+ started_at: 1,
179
+ });
180
+ await mod.appendGlobalPid({
181
+ pid: 999999, // dead
182
+ cli: "codex",
183
+ prompt: null,
184
+ cwd: "/b",
185
+ log_file: null,
186
+ status: "exited",
187
+ exit_code: 0,
188
+ exit_reason: "done",
189
+ started_at: 1,
190
+ });
191
+ }
192
+ const fs = await import("fs/promises");
193
+ const before = (await fs.readFile(mod.getGlobalPidIndexPath(), "utf-8")).split("\n").length;
194
+ await mod.maybeCompactGlobalPids();
195
+ const after = (await fs.readFile(mod.getGlobalPidIndexPath(), "utf-8")).split("\n").length;
196
+ // Compaction must have shrunk the file dramatically and dropped the
197
+ // dead-and-exited pid 999999 entirely.
198
+ expect(after).toBeLessThan(before / 10);
199
+ const records = await mod.readGlobalPids();
200
+ expect(records.map((r) => r.pid)).toEqual([process.pid]);
201
+ });
202
+
203
+ it("maybeCompactGlobalPids on missing file is a noop", async () => {
204
+ const mod = await loadModule();
205
+ await mod.maybeCompactGlobalPids(); // no throw, no error
206
+ });
207
+
145
208
  it("skips corrupt lines without throwing", async () => {
146
209
  const mod = await loadModule();
147
210
  await mod.appendGlobalPid({
@@ -1,4 +1,4 @@
1
- import { appendFile, mkdir, readFile } from "fs/promises";
1
+ import { appendFile, mkdir, readFile, rename, writeFile } from "fs/promises";
2
2
  import { homedir } from "os";
3
3
  import path from "path";
4
4
  import { lock } from "proper-lockfile";
@@ -153,3 +153,40 @@ function isProcessAlive(pid: number): boolean {
153
153
  return false;
154
154
  }
155
155
  }
156
+
157
+ const COMPACT_THRESHOLD_LINES = 500; // raw events; one merged record per pid
158
+
159
+ /**
160
+ * Best-effort compaction: rewrite the JSONL file with one line per known pid,
161
+ * dropping records whose pid is dead AND status is exited (those won't be
162
+ * referenced by `cy ls` anyway). Triggered opportunistically when the raw
163
+ * file grows past `COMPACT_THRESHOLD_LINES`. Safe to call unconditionally;
164
+ * it no-ops when the file is already small enough.
165
+ */
166
+ export async function maybeCompactGlobalPids(): Promise<void> {
167
+ let raw: string;
168
+ try {
169
+ raw = await readFile(resolveGlobalFile(), "utf-8");
170
+ } catch (err: any) {
171
+ if (err.code === "ENOENT") return;
172
+ return;
173
+ }
174
+ const lineCount = raw.split("\n").filter((l) => l.trim()).length;
175
+ if (lineCount < COMPACT_THRESHOLD_LINES) return;
176
+
177
+ try {
178
+ await withLock(async () => {
179
+ const merged = await readGlobalPidsRaw();
180
+ // Drop dead-and-exited entries; keep dead-but-not-yet-exited so a later
181
+ // status-update from elsewhere can still be matched against them.
182
+ const keep = merged.filter((r) => r.status !== "exited" || isProcessAlive(r.pid));
183
+ const tmpFile = resolveGlobalFile() + ".compact";
184
+ const content = keep.map((r) => JSON.stringify(r)).join("\n") + (keep.length ? "\n" : "");
185
+ await writeFile(tmpFile, content);
186
+ await rename(tmpFile, resolveGlobalFile());
187
+ logger.debug(`[globalPidIndex] compacted ${lineCount} → ${keep.length} lines`);
188
+ });
189
+ } catch (error) {
190
+ logger.debug("[globalPidIndex] compact failed:", error);
191
+ }
192
+ }
package/ts/pidStore.ts CHANGED
@@ -2,7 +2,11 @@ import { mkdir, writeFile } from "fs/promises";
2
2
  import path from "path";
3
3
  import { logger } from "./logger.ts";
4
4
  import { JsonlStore } from "./JsonlStore.ts";
5
- import { appendGlobalPid, updateGlobalPidStatus } from "./globalPidIndex.ts";
5
+ import {
6
+ appendGlobalPid,
7
+ maybeCompactGlobalPids,
8
+ updateGlobalPidStatus,
9
+ } from "./globalPidIndex.ts";
6
10
 
7
11
  export interface PidRecord {
8
12
  _id?: string;
@@ -100,7 +104,9 @@ export class PidStore {
100
104
  exit_code: null,
101
105
  exit_reason: null,
102
106
  started_at: now,
103
- }).catch(() => null);
107
+ })
108
+ .then(() => maybeCompactGlobalPids())
109
+ .catch(() => null);
104
110
 
105
111
  return result;
106
112
  }
@@ -1,11 +0,0 @@
1
- import { t as CLIS_CONFIG } from "./ts-DfT_yx7e.js";
2
- import "./logger-B9h0djqx.js";
3
- import "./pidStore-CYmzzaQQ.js";
4
- import "./globalPidIndex-BHCkWll6.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-CqAT1Zud.js.map
@@ -1,5 +0,0 @@
1
- import "./logger-B9h0djqx.js";
2
- import { t as PidStore } from "./pidStore-CYmzzaQQ.js";
3
- import "./globalPidIndex-BHCkWll6.js";
4
-
5
- export { PidStore };