claude-yes 1.32.3 → 1.33.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/cli.js +337 -180
- package/dist/index.js +164 -35
- package/package.json +4 -2
- package/ts/cli.ts +22 -5
- package/ts/index.ts +45 -20
- package/ts/parseCliArgs.ts +11 -0
- package/ts/pidStore.ts +135 -0
package/ts/pidStore.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import Datastore from "@seald-io/nedb";
|
|
2
|
+
import { mkdir } from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { logger } from "./logger.ts";
|
|
5
|
+
|
|
6
|
+
export interface PidRecord {
|
|
7
|
+
pid: number;
|
|
8
|
+
cli: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
prompt?: string;
|
|
11
|
+
logFile: string;
|
|
12
|
+
fifoFile: string;
|
|
13
|
+
status: "idle" | "active" | "exited";
|
|
14
|
+
exitReason: string;
|
|
15
|
+
exitCode?: number;
|
|
16
|
+
startedAt: number;
|
|
17
|
+
updatedAt: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class PidStore {
|
|
21
|
+
protected db!: Datastore<PidRecord>;
|
|
22
|
+
private baseDir: string;
|
|
23
|
+
|
|
24
|
+
constructor(workingDir: string) {
|
|
25
|
+
this.baseDir = path.resolve(workingDir, ".agent-yes");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async init(): Promise<void> {
|
|
29
|
+
await mkdir(path.join(this.baseDir, "logs"), { recursive: true });
|
|
30
|
+
await mkdir(path.join(this.baseDir, "fifo"), { recursive: true });
|
|
31
|
+
|
|
32
|
+
this.db = new Datastore<PidRecord>({
|
|
33
|
+
filename: path.join(this.baseDir, "pid.jsonl"),
|
|
34
|
+
autoload: true,
|
|
35
|
+
});
|
|
36
|
+
await this.db.loadDatabaseAsync();
|
|
37
|
+
await this.cleanStaleRecords();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async registerProcess({
|
|
41
|
+
pid,
|
|
42
|
+
cli,
|
|
43
|
+
args,
|
|
44
|
+
prompt,
|
|
45
|
+
}: {
|
|
46
|
+
pid: number;
|
|
47
|
+
cli: string;
|
|
48
|
+
args: string[];
|
|
49
|
+
prompt?: string;
|
|
50
|
+
}): Promise<PidRecord> {
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
const record: PidRecord = {
|
|
53
|
+
pid,
|
|
54
|
+
cli,
|
|
55
|
+
args,
|
|
56
|
+
prompt,
|
|
57
|
+
logFile: this.getLogPath(pid),
|
|
58
|
+
fifoFile: this.getFifoPath(pid),
|
|
59
|
+
status: "active",
|
|
60
|
+
exitReason: "",
|
|
61
|
+
startedAt: now,
|
|
62
|
+
updatedAt: now,
|
|
63
|
+
};
|
|
64
|
+
await this.db.insertAsync(record);
|
|
65
|
+
logger.debug(`[pidStore] Registered process ${pid}`);
|
|
66
|
+
return record;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async updateStatus(
|
|
70
|
+
pid: number,
|
|
71
|
+
status: PidRecord["status"],
|
|
72
|
+
extra?: { exitReason?: string; exitCode?: number },
|
|
73
|
+
): Promise<void> {
|
|
74
|
+
const update: Partial<PidRecord> = {
|
|
75
|
+
status,
|
|
76
|
+
updatedAt: Date.now(),
|
|
77
|
+
...extra,
|
|
78
|
+
};
|
|
79
|
+
await this.db.updateAsync({ pid }, { $set: update }, {});
|
|
80
|
+
logger.debug(`[pidStore] Updated process ${pid} status=${status}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
getLogPath(pid: number): string {
|
|
84
|
+
return path.resolve(this.baseDir, "logs", `${pid}.log`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
getFifoPath(pid: number): string {
|
|
88
|
+
return path.resolve(this.baseDir, "fifo", `${pid}.stdin`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async cleanStaleRecords(): Promise<void> {
|
|
92
|
+
const activeRecords = await this.db.findAsync({
|
|
93
|
+
status: { $ne: "exited" } as any,
|
|
94
|
+
});
|
|
95
|
+
for (const record of activeRecords) {
|
|
96
|
+
if (!this.isProcessAlive(record.pid)) {
|
|
97
|
+
await this.db.updateAsync(
|
|
98
|
+
{ pid: record.pid },
|
|
99
|
+
{
|
|
100
|
+
$set: {
|
|
101
|
+
status: "exited" as const,
|
|
102
|
+
exitReason: "stale-cleanup",
|
|
103
|
+
updatedAt: Date.now(),
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{},
|
|
107
|
+
);
|
|
108
|
+
logger.debug(`[pidStore] Cleaned stale record for PID ${record.pid}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async close(): Promise<void> {
|
|
114
|
+
await this.db.compactDatafileAsync();
|
|
115
|
+
logger.debug("[pidStore] Database compacted and closed");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private isProcessAlive(pid: number): boolean {
|
|
119
|
+
try {
|
|
120
|
+
process.kill(pid, 0);
|
|
121
|
+
return true;
|
|
122
|
+
} catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static async findActiveFifo(workingDir: string): Promise<string | null> {
|
|
128
|
+
const store = new PidStore(workingDir);
|
|
129
|
+
await store.init();
|
|
130
|
+
const records = await store.db.findAsync({ status: { $ne: "exited" } as any });
|
|
131
|
+
await store.close();
|
|
132
|
+
const sorted = records.sort((a, b) => b.startedAt - a.startedAt);
|
|
133
|
+
return sorted[0]?.fifoFile ?? null;
|
|
134
|
+
}
|
|
135
|
+
}
|