agent-yes 1.84.0 → 1.86.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.
- package/dist/{SUPPORTED_CLIS-BdYQ3v93.js → SUPPORTED_CLIS-BlWg00sP.js} +3 -3
- package/dist/cli.js +5 -5
- package/dist/index.js +2 -2
- package/dist/remotes-CFrho898.js +131 -0
- package/dist/remotes-kfUzk-JT.js +3 -0
- package/dist/serve-D0NnTXRD.js +303 -0
- package/dist/subcommands-BDiS305D.js +6 -0
- package/dist/{subcommands-DjO8lthH.js → subcommands-BpGEGOQM.js} +440 -78
- package/dist/{tray-CH_G7aXM.js → tray-DHuD0nEk.js} +1 -1
- package/dist/{ts-DP0dIeoe.js → ts-DWuvdSWr.js} +2 -2
- package/dist/{versionChecker-DtDqoy3L.js → versionChecker-BCrJk4Zj.js} +2 -2
- package/package.json +1 -1
- package/ts/remotes.ts +161 -0
- package/ts/serve.ts +373 -0
- package/ts/subcommands.spec.ts +478 -35
- package/ts/subcommands.ts +544 -95
package/ts/subcommands.spec.ts
CHANGED
|
@@ -27,41 +27,6 @@ async function loadModule() {
|
|
|
27
27
|
return await import("./subcommands.ts");
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
describe("subcommands.parseArgs", () => {
|
|
31
|
-
it("collects positional args and bare flags", async () => {
|
|
32
|
-
const { parseArgs } = await loadModule();
|
|
33
|
-
const out = parseArgs(["foo", "bar", "--all"]);
|
|
34
|
-
expect(out.positional).toEqual(["foo", "bar"]);
|
|
35
|
-
expect(out.flags.all).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("parses --key=value form", async () => {
|
|
39
|
-
const { parseArgs } = await loadModule();
|
|
40
|
-
const out = parseArgs(["--code=enter"]);
|
|
41
|
-
expect(out.flags.code).toBe("enter");
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("parses --key value form for non-boolean keys", async () => {
|
|
45
|
-
const { parseArgs } = await loadModule();
|
|
46
|
-
const out = parseArgs(["--cwd", "/tmp/foo"]);
|
|
47
|
-
expect(out.flags.cwd).toBe("/tmp/foo");
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("treats well-known boolean flags as boolean even with a following positional", async () => {
|
|
51
|
-
const { parseArgs } = await loadModule();
|
|
52
|
-
const out = parseArgs(["--all", "claude"]);
|
|
53
|
-
expect(out.flags.all).toBe(true);
|
|
54
|
-
expect(out.positional).toEqual(["claude"]);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("supports -n N short form", async () => {
|
|
58
|
-
const { parseArgs } = await loadModule();
|
|
59
|
-
const out = parseArgs(["-n", "50", "keyword"]);
|
|
60
|
-
expect(out.flags.n).toBe("50");
|
|
61
|
-
expect(out.positional).toEqual(["keyword"]);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
30
|
describe("subcommands.controlCodeFromName", () => {
|
|
66
31
|
it("maps named codes to the right control bytes", async () => {
|
|
67
32
|
const { controlCodeFromName } = await loadModule();
|
|
@@ -525,6 +490,484 @@ describe("subcommands.cmdSend writes bytes to FIFO", () => {
|
|
|
525
490
|
});
|
|
526
491
|
});
|
|
527
492
|
|
|
493
|
+
// ---------------------------------------------------------------------------
|
|
494
|
+
// cmdLs additional arg coverage
|
|
495
|
+
// ---------------------------------------------------------------------------
|
|
496
|
+
|
|
497
|
+
describe("subcommands.cmdLs -h / --help", () => {
|
|
498
|
+
function captureStdout() {
|
|
499
|
+
const chunks: string[] = [];
|
|
500
|
+
const orig = process.stdout.write.bind(process.stdout);
|
|
501
|
+
(process.stdout as any).write = (s: any) => {
|
|
502
|
+
chunks.push(String(s));
|
|
503
|
+
return true;
|
|
504
|
+
};
|
|
505
|
+
return {
|
|
506
|
+
get text() {
|
|
507
|
+
return chunks.join("");
|
|
508
|
+
},
|
|
509
|
+
restore() {
|
|
510
|
+
process.stdout.write = orig;
|
|
511
|
+
},
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
it("ay ls -h prints usage to stdout and exits 0", async () => {
|
|
516
|
+
const { runSubcommand } = await loadModule();
|
|
517
|
+
const cap = captureStdout();
|
|
518
|
+
let code: number | null;
|
|
519
|
+
try {
|
|
520
|
+
code = await runSubcommand(["bun", "cli.js", "ls", "-h"]);
|
|
521
|
+
} finally {
|
|
522
|
+
cap.restore();
|
|
523
|
+
}
|
|
524
|
+
expect(code).toBe(0);
|
|
525
|
+
expect(cap.text).toMatch(/Usage:/);
|
|
526
|
+
expect(cap.text).toMatch(/--all/);
|
|
527
|
+
expect(cap.text).toMatch(/--json/);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
it("ay ls --help prints usage to stdout and exits 0", async () => {
|
|
531
|
+
const { runSubcommand } = await loadModule();
|
|
532
|
+
const cap = captureStdout();
|
|
533
|
+
let code: number | null;
|
|
534
|
+
try {
|
|
535
|
+
code = await runSubcommand(["bun", "cli.js", "ls", "--help"]);
|
|
536
|
+
} finally {
|
|
537
|
+
cap.restore();
|
|
538
|
+
}
|
|
539
|
+
expect(code).toBe(0);
|
|
540
|
+
expect(cap.text).toMatch(/Usage:/);
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
describe("subcommands.cmdLs --all / --active / keyword filter / aliases", () => {
|
|
545
|
+
function captureOutput() {
|
|
546
|
+
const out: string[] = [];
|
|
547
|
+
const err: string[] = [];
|
|
548
|
+
const origOut = process.stdout.write.bind(process.stdout);
|
|
549
|
+
const origErr = process.stderr.write.bind(process.stderr);
|
|
550
|
+
(process.stdout as any).write = (s: any) => {
|
|
551
|
+
out.push(String(s));
|
|
552
|
+
return true;
|
|
553
|
+
};
|
|
554
|
+
(process.stderr as any).write = (s: any) => {
|
|
555
|
+
err.push(String(s));
|
|
556
|
+
return true;
|
|
557
|
+
};
|
|
558
|
+
return {
|
|
559
|
+
get stdout() {
|
|
560
|
+
return out.join("");
|
|
561
|
+
},
|
|
562
|
+
get stderr() {
|
|
563
|
+
return err.join("");
|
|
564
|
+
},
|
|
565
|
+
restore() {
|
|
566
|
+
process.stdout.write = origOut;
|
|
567
|
+
process.stderr.write = origErr;
|
|
568
|
+
},
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
it("--all shows exited agents", async () => {
|
|
573
|
+
const mod = await loadModule();
|
|
574
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
575
|
+
await appendGlobalPid({
|
|
576
|
+
pid: 1, // pid 1 is almost never the test process, so isPidAlive returns false
|
|
577
|
+
cli: "claude",
|
|
578
|
+
prompt: "exited agent",
|
|
579
|
+
cwd: process.cwd(),
|
|
580
|
+
log_file: null,
|
|
581
|
+
status: "exited",
|
|
582
|
+
exit_code: 0,
|
|
583
|
+
exit_reason: "done",
|
|
584
|
+
started_at: Date.now() - 10_000,
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
const cap = captureOutput();
|
|
588
|
+
let code: number | null;
|
|
589
|
+
try {
|
|
590
|
+
code = await mod.runSubcommand(["bun", "cli.js", "ls", "--all", "--json"]);
|
|
591
|
+
} finally {
|
|
592
|
+
cap.restore();
|
|
593
|
+
}
|
|
594
|
+
expect(code).toBe(0);
|
|
595
|
+
const parsed = JSON.parse(cap.stdout);
|
|
596
|
+
expect(Array.isArray(parsed)).toBe(true);
|
|
597
|
+
expect(parsed.some((r: any) => r.prompt === "exited agent")).toBe(true);
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
it("keyword filter restricts results to matching agents", async () => {
|
|
601
|
+
const mod = await loadModule();
|
|
602
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
603
|
+
await appendGlobalPid({
|
|
604
|
+
pid: process.pid,
|
|
605
|
+
cli: "claude",
|
|
606
|
+
prompt: "unique-xyzzy-prompt",
|
|
607
|
+
cwd: process.cwd(),
|
|
608
|
+
log_file: null,
|
|
609
|
+
status: "active",
|
|
610
|
+
exit_code: null,
|
|
611
|
+
exit_reason: null,
|
|
612
|
+
started_at: Date.now(),
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
const cap = captureOutput();
|
|
616
|
+
let code: number | null;
|
|
617
|
+
try {
|
|
618
|
+
code = await mod.runSubcommand(["bun", "cli.js", "ls", "--json", "unique-xyzzy-prompt"]);
|
|
619
|
+
} finally {
|
|
620
|
+
cap.restore();
|
|
621
|
+
}
|
|
622
|
+
expect(code).toBe(0);
|
|
623
|
+
const parsed = JSON.parse(cap.stdout);
|
|
624
|
+
expect(parsed.every((r: any) => r.prompt?.includes("unique-xyzzy-prompt"))).toBe(true);
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
it("keyword filter returns 'no running agents' when nothing matches", async () => {
|
|
628
|
+
const { runSubcommand } = await loadModule();
|
|
629
|
+
const stderr: string[] = [];
|
|
630
|
+
const orig = process.stderr.write.bind(process.stderr);
|
|
631
|
+
(process.stderr as any).write = (s: any) => {
|
|
632
|
+
stderr.push(String(s));
|
|
633
|
+
return true;
|
|
634
|
+
};
|
|
635
|
+
try {
|
|
636
|
+
const code = await runSubcommand(["bun", "cli.js", "ls", "no-match-zzzzzz"]);
|
|
637
|
+
expect(code).toBe(0);
|
|
638
|
+
expect(stderr.join("")).toMatch(/no running agents matched/);
|
|
639
|
+
} finally {
|
|
640
|
+
process.stderr.write = orig;
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
it("list alias routes to cmdLs", async () => {
|
|
645
|
+
const { runSubcommand } = await loadModule();
|
|
646
|
+
const stderr: string[] = [];
|
|
647
|
+
const orig = process.stderr.write.bind(process.stderr);
|
|
648
|
+
(process.stderr as any).write = (s: any) => {
|
|
649
|
+
stderr.push(String(s));
|
|
650
|
+
return true;
|
|
651
|
+
};
|
|
652
|
+
try {
|
|
653
|
+
const code = await runSubcommand(["bun", "cli.js", "list"]);
|
|
654
|
+
expect(code).toBe(0);
|
|
655
|
+
} finally {
|
|
656
|
+
process.stderr.write = orig;
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
it("ps alias routes to cmdLs", async () => {
|
|
661
|
+
const { runSubcommand } = await loadModule();
|
|
662
|
+
const stderr: string[] = [];
|
|
663
|
+
const orig = process.stderr.write.bind(process.stderr);
|
|
664
|
+
(process.stderr as any).write = (s: any) => {
|
|
665
|
+
stderr.push(String(s));
|
|
666
|
+
return true;
|
|
667
|
+
};
|
|
668
|
+
try {
|
|
669
|
+
const code = await runSubcommand(["bun", "cli.js", "ps"]);
|
|
670
|
+
expect(code).toBe(0);
|
|
671
|
+
} finally {
|
|
672
|
+
process.stderr.write = orig;
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
// ---------------------------------------------------------------------------
|
|
678
|
+
// cmdRead — head and cat modes
|
|
679
|
+
// ---------------------------------------------------------------------------
|
|
680
|
+
|
|
681
|
+
describe("subcommands.cmdRead head and cat modes", () => {
|
|
682
|
+
it("head emits first N lines", async () => {
|
|
683
|
+
const { runSubcommand } = await loadModule();
|
|
684
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
685
|
+
const tmp = await mkdtemp(path.join(tmpdir(), "ay-head-log-"));
|
|
686
|
+
try {
|
|
687
|
+
const logPath = path.join(tmp, "x.raw.log");
|
|
688
|
+
const lines: string[] = [];
|
|
689
|
+
for (let i = 0; i < 50; i++) lines.push(`line-${i}`);
|
|
690
|
+
await writeFile(logPath, lines.join("\r\n") + "\r\n");
|
|
691
|
+
|
|
692
|
+
await appendGlobalPid({
|
|
693
|
+
pid: process.pid,
|
|
694
|
+
cli: "claude",
|
|
695
|
+
prompt: null,
|
|
696
|
+
cwd: process.cwd(),
|
|
697
|
+
log_file: logPath,
|
|
698
|
+
status: "active",
|
|
699
|
+
exit_code: null,
|
|
700
|
+
exit_reason: null,
|
|
701
|
+
started_at: Date.now(),
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
const stdout: string[] = [];
|
|
705
|
+
const orig = process.stdout.write.bind(process.stdout);
|
|
706
|
+
(process.stdout as any).write = (s: any) => {
|
|
707
|
+
stdout.push(String(s));
|
|
708
|
+
return true;
|
|
709
|
+
};
|
|
710
|
+
const stderr_chunks: string[] = [];
|
|
711
|
+
const origErr = process.stderr.write.bind(process.stderr);
|
|
712
|
+
(process.stderr as any).write = (s: any) => {
|
|
713
|
+
stderr_chunks.push(String(s));
|
|
714
|
+
return true;
|
|
715
|
+
};
|
|
716
|
+
try {
|
|
717
|
+
const code = await runSubcommand(["bun", "cli.js", "head", String(process.pid), "-n", "5"]);
|
|
718
|
+
expect(code).toBe(0);
|
|
719
|
+
} finally {
|
|
720
|
+
process.stdout.write = orig;
|
|
721
|
+
process.stderr.write = origErr;
|
|
722
|
+
}
|
|
723
|
+
const text = stdout.join("");
|
|
724
|
+
expect(text).toMatch(/line-0/);
|
|
725
|
+
expect(text).toMatch(/line-4/);
|
|
726
|
+
expect(text).not.toMatch(/line-10\b/);
|
|
727
|
+
} finally {
|
|
728
|
+
await rm(tmp, { recursive: true, force: true }).catch(() => null);
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
it("cat emits all lines", async () => {
|
|
733
|
+
const { runSubcommand } = await loadModule();
|
|
734
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
735
|
+
const tmp = await mkdtemp(path.join(tmpdir(), "ay-cat-log-"));
|
|
736
|
+
try {
|
|
737
|
+
const logPath = path.join(tmp, "x.raw.log");
|
|
738
|
+
await writeFile(logPath, "alpha\r\nbeta\r\ngamma\r\n");
|
|
739
|
+
|
|
740
|
+
await appendGlobalPid({
|
|
741
|
+
pid: process.pid,
|
|
742
|
+
cli: "claude",
|
|
743
|
+
prompt: null,
|
|
744
|
+
cwd: process.cwd(),
|
|
745
|
+
log_file: logPath,
|
|
746
|
+
status: "active",
|
|
747
|
+
exit_code: null,
|
|
748
|
+
exit_reason: null,
|
|
749
|
+
started_at: Date.now(),
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
const stdout: string[] = [];
|
|
753
|
+
const orig = process.stdout.write.bind(process.stdout);
|
|
754
|
+
(process.stdout as any).write = (s: any) => {
|
|
755
|
+
stdout.push(String(s));
|
|
756
|
+
return true;
|
|
757
|
+
};
|
|
758
|
+
const stderr_chunks: string[] = [];
|
|
759
|
+
const origErr = process.stderr.write.bind(process.stderr);
|
|
760
|
+
(process.stderr as any).write = (s: any) => {
|
|
761
|
+
stderr_chunks.push(String(s));
|
|
762
|
+
return true;
|
|
763
|
+
};
|
|
764
|
+
try {
|
|
765
|
+
const code = await runSubcommand(["bun", "cli.js", "cat", String(process.pid)]);
|
|
766
|
+
expect(code).toBe(0);
|
|
767
|
+
} finally {
|
|
768
|
+
process.stdout.write = orig;
|
|
769
|
+
process.stderr.write = origErr;
|
|
770
|
+
}
|
|
771
|
+
const text = stdout.join("");
|
|
772
|
+
expect(text).toMatch(/alpha/);
|
|
773
|
+
expect(text).toMatch(/beta/);
|
|
774
|
+
expect(text).toMatch(/gamma/);
|
|
775
|
+
} finally {
|
|
776
|
+
await rm(tmp, { recursive: true, force: true }).catch(() => null);
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
// ---------------------------------------------------------------------------
|
|
782
|
+
// cmdNote
|
|
783
|
+
// ---------------------------------------------------------------------------
|
|
784
|
+
|
|
785
|
+
describe("subcommands.cmdNote", () => {
|
|
786
|
+
it("throws usage error when no keyword given", async () => {
|
|
787
|
+
const { runSubcommand } = await loadModule();
|
|
788
|
+
const stderr: string[] = [];
|
|
789
|
+
const orig = process.stderr.write.bind(process.stderr);
|
|
790
|
+
(process.stderr as any).write = (s: any) => {
|
|
791
|
+
stderr.push(String(s));
|
|
792
|
+
return true;
|
|
793
|
+
};
|
|
794
|
+
try {
|
|
795
|
+
const code = await runSubcommand(["bun", "cli.js", "note"]);
|
|
796
|
+
expect(code).toBe(1);
|
|
797
|
+
expect(stderr.join("")).toMatch(/usage:/i);
|
|
798
|
+
} finally {
|
|
799
|
+
process.stderr.write = orig;
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
it("sets a note on a matched agent", async () => {
|
|
804
|
+
const mod = await loadModule();
|
|
805
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
806
|
+
await appendGlobalPid({
|
|
807
|
+
pid: process.pid,
|
|
808
|
+
cli: "claude",
|
|
809
|
+
prompt: "note-target",
|
|
810
|
+
cwd: process.cwd(),
|
|
811
|
+
log_file: null,
|
|
812
|
+
status: "active",
|
|
813
|
+
exit_code: null,
|
|
814
|
+
exit_reason: null,
|
|
815
|
+
started_at: Date.now(),
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
const stdout: string[] = [];
|
|
819
|
+
const origOut = process.stdout.write.bind(process.stdout);
|
|
820
|
+
(process.stdout as any).write = (s: any) => {
|
|
821
|
+
stdout.push(String(s));
|
|
822
|
+
return true;
|
|
823
|
+
};
|
|
824
|
+
const origErr = process.stderr.write.bind(process.stderr);
|
|
825
|
+
(process.stderr as any).write = () => true;
|
|
826
|
+
try {
|
|
827
|
+
const code = await mod.runSubcommand([
|
|
828
|
+
"bun",
|
|
829
|
+
"cli.js",
|
|
830
|
+
"note",
|
|
831
|
+
String(process.pid),
|
|
832
|
+
"my note text",
|
|
833
|
+
]);
|
|
834
|
+
expect(code).toBe(0);
|
|
835
|
+
expect(stdout.join("")).toMatch(/note set/);
|
|
836
|
+
} finally {
|
|
837
|
+
process.stdout.write = origOut;
|
|
838
|
+
process.stderr.write = origErr;
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
it("clears a note when no text given", async () => {
|
|
843
|
+
const mod = await loadModule();
|
|
844
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
845
|
+
await appendGlobalPid({
|
|
846
|
+
pid: process.pid,
|
|
847
|
+
cli: "claude",
|
|
848
|
+
prompt: "note-clear-target",
|
|
849
|
+
cwd: process.cwd(),
|
|
850
|
+
log_file: null,
|
|
851
|
+
status: "active",
|
|
852
|
+
exit_code: null,
|
|
853
|
+
exit_reason: null,
|
|
854
|
+
started_at: Date.now(),
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
const stdout: string[] = [];
|
|
858
|
+
const origOut = process.stdout.write.bind(process.stdout);
|
|
859
|
+
(process.stdout as any).write = (s: any) => {
|
|
860
|
+
stdout.push(String(s));
|
|
861
|
+
return true;
|
|
862
|
+
};
|
|
863
|
+
(process.stderr as any).write = () => true;
|
|
864
|
+
try {
|
|
865
|
+
const code = await mod.runSubcommand(["bun", "cli.js", "note", String(process.pid)]);
|
|
866
|
+
expect(code).toBe(0);
|
|
867
|
+
expect(stdout.join("")).toMatch(/cleared note/);
|
|
868
|
+
} finally {
|
|
869
|
+
process.stdout.write = origOut;
|
|
870
|
+
process.stderr.write = process.stderr.write; // no-op restore (silenced above)
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
// ---------------------------------------------------------------------------
|
|
876
|
+
// cmdStatus
|
|
877
|
+
// ---------------------------------------------------------------------------
|
|
878
|
+
|
|
879
|
+
describe("subcommands.cmdStatus", () => {
|
|
880
|
+
it("throws usage error when no keyword given", async () => {
|
|
881
|
+
const { runSubcommand } = await loadModule();
|
|
882
|
+
const stderr: string[] = [];
|
|
883
|
+
const orig = process.stderr.write.bind(process.stderr);
|
|
884
|
+
(process.stderr as any).write = (s: any) => {
|
|
885
|
+
stderr.push(String(s));
|
|
886
|
+
return true;
|
|
887
|
+
};
|
|
888
|
+
try {
|
|
889
|
+
const code = await runSubcommand(["bun", "cli.js", "status"]);
|
|
890
|
+
expect(code).toBe(1);
|
|
891
|
+
expect(stderr.join("")).toMatch(/usage:/i);
|
|
892
|
+
} finally {
|
|
893
|
+
process.stderr.write = orig;
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
it("emits JSON snapshot for a matched agent", async () => {
|
|
898
|
+
const mod = await loadModule();
|
|
899
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
900
|
+
await appendGlobalPid({
|
|
901
|
+
pid: process.pid,
|
|
902
|
+
cli: "claude",
|
|
903
|
+
prompt: "status-test",
|
|
904
|
+
cwd: process.cwd(),
|
|
905
|
+
log_file: null,
|
|
906
|
+
status: "active",
|
|
907
|
+
exit_code: null,
|
|
908
|
+
exit_reason: null,
|
|
909
|
+
started_at: Date.now() - 1000,
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
const stdout: string[] = [];
|
|
913
|
+
const origOut = process.stdout.write.bind(process.stdout);
|
|
914
|
+
(process.stdout as any).write = (s: any) => {
|
|
915
|
+
stdout.push(String(s));
|
|
916
|
+
return true;
|
|
917
|
+
};
|
|
918
|
+
(process.stderr as any).write = () => true;
|
|
919
|
+
try {
|
|
920
|
+
const code = await mod.runSubcommand(["bun", "cli.js", "status", String(process.pid)]);
|
|
921
|
+
expect(code).toBe(0);
|
|
922
|
+
} finally {
|
|
923
|
+
process.stdout.write = origOut;
|
|
924
|
+
}
|
|
925
|
+
const snap = JSON.parse(stdout.join(""));
|
|
926
|
+
expect(snap).toMatchObject({ pid: process.pid, cli: "claude" });
|
|
927
|
+
expect(typeof snap.age_ms).toBe("number");
|
|
928
|
+
});
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
// ---------------------------------------------------------------------------
|
|
932
|
+
// cmdRestart
|
|
933
|
+
// ---------------------------------------------------------------------------
|
|
934
|
+
|
|
935
|
+
describe("subcommands.cmdRestart", () => {
|
|
936
|
+
it("returns 1 and warns when the agent is still alive", async () => {
|
|
937
|
+
const mod = await loadModule();
|
|
938
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
939
|
+
await appendGlobalPid({
|
|
940
|
+
pid: process.pid,
|
|
941
|
+
cli: "claude",
|
|
942
|
+
prompt: "restart-live-test",
|
|
943
|
+
cwd: process.cwd(),
|
|
944
|
+
log_file: null,
|
|
945
|
+
status: "active",
|
|
946
|
+
exit_code: null,
|
|
947
|
+
exit_reason: null,
|
|
948
|
+
started_at: Date.now(),
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
const stderr: string[] = [];
|
|
952
|
+
const origErr = process.stderr.write.bind(process.stderr);
|
|
953
|
+
(process.stderr as any).write = (s: any) => {
|
|
954
|
+
stderr.push(String(s));
|
|
955
|
+
return true;
|
|
956
|
+
};
|
|
957
|
+
try {
|
|
958
|
+
const code = await mod.runSubcommand(["bun", "cli.js", "restart", String(process.pid)]);
|
|
959
|
+
expect(code).toBe(1);
|
|
960
|
+
expect(stderr.join("")).toMatch(/still running/);
|
|
961
|
+
} finally {
|
|
962
|
+
process.stderr.write = origErr;
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
// ---------------------------------------------------------------------------
|
|
968
|
+
// listRecords merges per-cwd TS file with global
|
|
969
|
+
// ---------------------------------------------------------------------------
|
|
970
|
+
|
|
528
971
|
describe("subcommands.listRecords merges per-cwd TS file with global", () => {
|
|
529
972
|
it("includes records from <cwd>/.agent-yes/pid-records.jsonl", async () => {
|
|
530
973
|
// Write a fake per-cwd file that uses the live process pid so liveOnly
|