baxian 0.0.1 → 0.2.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/LICENSE +201 -0
- package/README.md +19 -1
- package/dist/agent/bootstrap-poller.d.ts +34 -0
- package/dist/agent/bootstrap-poller.d.ts.map +1 -0
- package/dist/agent/bootstrap-poller.js +93 -0
- package/dist/agent/bootstrap-poller.js.map +1 -0
- package/dist/agent/bootstrap.d.ts +39 -0
- package/dist/agent/bootstrap.d.ts.map +1 -0
- package/dist/agent/bootstrap.js +214 -0
- package/dist/agent/bootstrap.js.map +1 -0
- package/dist/agent/index.d.ts +8 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +8 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/manager.d.ts +280 -0
- package/dist/agent/manager.d.ts.map +1 -0
- package/dist/agent/manager.js +3666 -0
- package/dist/agent/manager.js.map +1 -0
- package/dist/agent/marker-protocol.d.ts +12 -0
- package/dist/agent/marker-protocol.d.ts.map +1 -0
- package/dist/agent/marker-protocol.js +52 -0
- package/dist/agent/marker-protocol.js.map +1 -0
- package/dist/agent/pane-streamer-manager.d.ts +24 -0
- package/dist/agent/pane-streamer-manager.d.ts.map +1 -0
- package/dist/agent/pane-streamer-manager.js +107 -0
- package/dist/agent/pane-streamer-manager.js.map +1 -0
- package/dist/agent/pane-streamer.d.ts +97 -0
- package/dist/agent/pane-streamer.d.ts.map +1 -0
- package/dist/agent/pane-streamer.js +382 -0
- package/dist/agent/pane-streamer.js.map +1 -0
- package/dist/agent/post-approve-marker-watcher.d.ts +29 -0
- package/dist/agent/post-approve-marker-watcher.d.ts.map +1 -0
- package/dist/agent/post-approve-marker-watcher.js +160 -0
- package/dist/agent/post-approve-marker-watcher.js.map +1 -0
- package/dist/agent/preflight.d.ts +9 -0
- package/dist/agent/preflight.d.ts.map +1 -0
- package/dist/agent/preflight.js +164 -0
- package/dist/agent/preflight.js.map +1 -0
- package/dist/agent/prompt.d.ts +44 -0
- package/dist/agent/prompt.d.ts.map +1 -0
- package/dist/agent/prompt.js +252 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/repo-store.d.ts +27 -0
- package/dist/agent/repo-store.d.ts.map +1 -0
- package/dist/agent/repo-store.js +152 -0
- package/dist/agent/repo-store.js.map +1 -0
- package/dist/agent/runner.d.ts +46 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +241 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/spec-review-marker-watcher.d.ts +33 -0
- package/dist/agent/spec-review-marker-watcher.d.ts.map +1 -0
- package/dist/agent/spec-review-marker-watcher.js +180 -0
- package/dist/agent/spec-review-marker-watcher.js.map +1 -0
- package/dist/agent/tmux-probe-poller.d.ts +78 -0
- package/dist/agent/tmux-probe-poller.d.ts.map +1 -0
- package/dist/agent/tmux-probe-poller.js +418 -0
- package/dist/agent/tmux-probe-poller.js.map +1 -0
- package/dist/agent/tmux.d.ts +78 -0
- package/dist/agent/tmux.d.ts.map +1 -0
- package/dist/agent/tmux.js +395 -0
- package/dist/agent/tmux.js.map +1 -0
- package/dist/agent/worktree.d.ts +10 -0
- package/dist/agent/worktree.d.ts.map +1 -0
- package/dist/agent/worktree.js +41 -0
- package/dist/agent/worktree.js.map +1 -0
- package/dist/api/agents.d.ts +3 -0
- package/dist/api/agents.d.ts.map +1 -0
- package/dist/api/agents.js +29 -0
- package/dist/api/agents.js.map +1 -0
- package/dist/api/config.d.ts +5 -0
- package/dist/api/config.d.ts.map +1 -0
- package/dist/api/config.js +114 -0
- package/dist/api/config.js.map +1 -0
- package/dist/api/events.d.ts +3 -0
- package/dist/api/events.d.ts.map +1 -0
- package/dist/api/events.js +11 -0
- package/dist/api/events.js.map +1 -0
- package/dist/api/pollers.d.ts +3 -0
- package/dist/api/pollers.d.ts.map +1 -0
- package/dist/api/pollers.js +4 -0
- package/dist/api/pollers.js.map +1 -0
- package/dist/api/probe.d.ts +9 -0
- package/dist/api/probe.d.ts.map +1 -0
- package/dist/api/probe.js +87 -0
- package/dist/api/probe.js.map +1 -0
- package/dist/api/projects.d.ts +3 -0
- package/dist/api/projects.d.ts.map +1 -0
- package/dist/api/projects.js +602 -0
- package/dist/api/projects.js.map +1 -0
- package/dist/api/restart.d.ts +3 -0
- package/dist/api/restart.d.ts.map +1 -0
- package/dist/api/restart.js +20 -0
- package/dist/api/restart.js.map +1 -0
- package/dist/api/tasks.d.ts +3 -0
- package/dist/api/tasks.d.ts.map +1 -0
- package/dist/api/tasks.js +136 -0
- package/dist/api/tasks.js.map +1 -0
- package/dist/app.d.ts +51 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +169 -0
- package/dist/app.js.map +1 -0
- package/dist/cli.d.ts +20 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +319 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/backup.d.ts +3 -0
- package/dist/config/backup.d.ts.map +1 -0
- package/dist/config/backup.js +44 -0
- package/dist/config/backup.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +42 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +197 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/mutex.d.ts +2 -0
- package/dist/config/mutex.d.ts.map +1 -0
- package/dist/config/mutex.js +7 -0
- package/dist/config/mutex.js.map +1 -0
- package/dist/config/normalizer.d.ts +2 -0
- package/dist/config/normalizer.d.ts.map +1 -0
- package/dist/config/normalizer.js +42 -0
- package/dist/config/normalizer.js.map +1 -0
- package/dist/config/validator.d.ts +7 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +278 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -0
- package/dist/event/broker.d.ts +11 -0
- package/dist/event/broker.d.ts.map +1 -0
- package/dist/event/broker.js +47 -0
- package/dist/event/broker.js.map +1 -0
- package/dist/event/bus.d.ts +12 -0
- package/dist/event/bus.d.ts.map +1 -0
- package/dist/event/bus.js +35 -0
- package/dist/event/bus.js.map +1 -0
- package/dist/event/handlers.d.ts +6 -0
- package/dist/event/handlers.d.ts.map +1 -0
- package/dist/event/handlers.js +1121 -0
- package/dist/event/handlers.js.map +1 -0
- package/dist/event/index.d.ts +4 -0
- package/dist/event/index.d.ts.map +1 -0
- package/dist/event/index.js +4 -0
- package/dist/event/index.js.map +1 -0
- package/dist/event/log.d.ts +9 -0
- package/dist/event/log.d.ts.map +1 -0
- package/dist/event/log.js +43 -0
- package/dist/event/log.js.map +1 -0
- package/dist/event/publish.d.ts +37 -0
- package/dist/event/publish.d.ts.map +1 -0
- package/dist/event/publish.js +197 -0
- package/dist/event/publish.js.map +1 -0
- package/dist/event/ws.d.ts +3 -0
- package/dist/event/ws.d.ts.map +1 -0
- package/dist/event/ws.js +169 -0
- package/dist/event/ws.js.map +1 -0
- package/dist/github/index.d.ts +4 -0
- package/dist/github/index.d.ts.map +1 -0
- package/dist/github/index.js +3 -0
- package/dist/github/index.js.map +1 -0
- package/dist/github/mapper.d.ts +51 -0
- package/dist/github/mapper.d.ts.map +1 -0
- package/dist/github/mapper.js +191 -0
- package/dist/github/mapper.js.map +1 -0
- package/dist/github/poller.d.ts +64 -0
- package/dist/github/poller.d.ts.map +1 -0
- package/dist/github/poller.js +513 -0
- package/dist/github/poller.js.map +1 -0
- package/dist/github/resolver.d.ts +8 -0
- package/dist/github/resolver.d.ts.map +1 -0
- package/dist/github/resolver.js +24 -0
- package/dist/github/resolver.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +310 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/restart-sentinel.d.ts +18 -0
- package/dist/lifecycle/restart-sentinel.d.ts.map +1 -0
- package/dist/lifecycle/restart-sentinel.js +61 -0
- package/dist/lifecycle/restart-sentinel.js.map +1 -0
- package/dist/lifecycle/restart.d.ts +21 -0
- package/dist/lifecycle/restart.d.ts.map +1 -0
- package/dist/lifecycle/restart.js +57 -0
- package/dist/lifecycle/restart.js.map +1 -0
- package/dist/shared/constants.d.ts +18 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +60 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +3 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/types.d.ts +263 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/skill/index.d.ts +2 -0
- package/dist/skill/index.d.ts.map +1 -0
- package/dist/skill/index.js +2 -0
- package/dist/skill/index.js.map +1 -0
- package/dist/skill/registry.d.ts +30 -0
- package/dist/skill/registry.d.ts.map +1 -0
- package/dist/skill/registry.js +174 -0
- package/dist/skill/registry.js.map +1 -0
- package/dist/skills/UPSTREAM.md +38 -0
- package/dist/skills/baxian-rules/SKILL.md +68 -0
- package/dist/skills/merge-sync/SKILL.md +42 -0
- package/dist/skills/pr-feedback/SKILL.md +117 -0
- package/dist/skills/pr-recheck/SKILL.md +52 -0
- package/dist/skills/pr-review/SKILL.md +60 -0
- package/dist/skills/spells/SKILL.md +41 -0
- package/dist/skills/task-check/SKILL.md +26 -0
- package/dist/state/agent-store.d.ts +21 -0
- package/dist/state/agent-store.d.ts.map +1 -0
- package/dist/state/agent-store.js +145 -0
- package/dist/state/agent-store.js.map +1 -0
- package/dist/state/error-record-store.d.ts +40 -0
- package/dist/state/error-record-store.d.ts.map +1 -0
- package/dist/state/error-record-store.js +203 -0
- package/dist/state/error-record-store.js.map +1 -0
- package/dist/state/index.d.ts +5 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +5 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/init.d.ts +2 -0
- package/dist/state/init.d.ts.map +1 -0
- package/dist/state/init.js +13 -0
- package/dist/state/init.js.map +1 -0
- package/dist/state/lock.d.ts +9 -0
- package/dist/state/lock.d.ts.map +1 -0
- package/dist/state/lock.js +36 -0
- package/dist/state/lock.js.map +1 -0
- package/dist/state/post-approve-store.d.ts +23 -0
- package/dist/state/post-approve-store.d.ts.map +1 -0
- package/dist/state/post-approve-store.js +79 -0
- package/dist/state/post-approve-store.js.map +1 -0
- package/dist/state/process-lock.d.ts +24 -0
- package/dist/state/process-lock.d.ts.map +1 -0
- package/dist/state/process-lock.js +175 -0
- package/dist/state/process-lock.js.map +1 -0
- package/dist/state/snapshot.d.ts +38 -0
- package/dist/state/snapshot.d.ts.map +1 -0
- package/dist/state/snapshot.js +134 -0
- package/dist/state/snapshot.js.map +1 -0
- package/dist/state/task-store.d.ts +25 -0
- package/dist/state/task-store.d.ts.map +1 -0
- package/dist/state/task-store.js +167 -0
- package/dist/state/task-store.js.map +1 -0
- package/dist/terminal/attach.d.ts +7 -0
- package/dist/terminal/attach.d.ts.map +1 -0
- package/dist/terminal/attach.js +26 -0
- package/dist/terminal/attach.js.map +1 -0
- package/dist/terminal/index.d.ts +3 -0
- package/dist/terminal/index.d.ts.map +1 -0
- package/dist/terminal/index.js +3 -0
- package/dist/terminal/index.js.map +1 -0
- package/dist/terminal/key-sanitizer.d.ts +2 -0
- package/dist/terminal/key-sanitizer.d.ts.map +1 -0
- package/dist/terminal/key-sanitizer.js +9 -0
- package/dist/terminal/key-sanitizer.js.map +1 -0
- package/dist/terminal/stream-ws.d.ts +3 -0
- package/dist/terminal/stream-ws.d.ts.map +1 -0
- package/dist/terminal/stream-ws.js +426 -0
- package/dist/terminal/stream-ws.js.map +1 -0
- package/dist/terminal/ws-auth.d.ts +5 -0
- package/dist/terminal/ws-auth.d.ts.map +1 -0
- package/dist/terminal/ws-auth.js +45 -0
- package/dist/terminal/ws-auth.js.map +1 -0
- package/dist/timing/debounced-task.d.ts +9 -0
- package/dist/timing/debounced-task.d.ts.map +1 -0
- package/dist/timing/debounced-task.js +23 -0
- package/dist/timing/debounced-task.js.map +1 -0
- package/dist/timing/periodic-task-runner.d.ts +21 -0
- package/dist/timing/periodic-task-runner.d.ts.map +1 -0
- package/dist/timing/periodic-task-runner.js +61 -0
- package/dist/timing/periodic-task-runner.js.map +1 -0
- package/dist/web/assets/index-53CBbz4w.js +4 -0
- package/dist/web/assets/index-B9D6BV08.css +1 -0
- package/dist/web/assets/react-BG4Iuztk.js +40 -0
- package/dist/web/assets/router-B_Nv0oRz.js +12 -0
- package/dist/web/assets/xterm-CFbL2ovg.css +32 -0
- package/dist/web/assets/xterm-D5X2JljJ.js +9 -0
- package/dist/web/index.html +17 -0
- package/package.json +44 -5
- package/index.js +0 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { appendFile, readFile, readdir, rename, unlink, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
export class ErrorRecordStore {
|
|
5
|
+
dir;
|
|
6
|
+
chain = Promise.resolve();
|
|
7
|
+
constructor(dir) {
|
|
8
|
+
this.dir = dir;
|
|
9
|
+
}
|
|
10
|
+
async append(input) {
|
|
11
|
+
const write = this.chain.then(async () => {
|
|
12
|
+
const occurredAt = input.occurredAt ?? new Date().toISOString();
|
|
13
|
+
const record = {
|
|
14
|
+
id: `err_${randomUUID()}`,
|
|
15
|
+
agentId: input.agentId,
|
|
16
|
+
projectId: input.projectId,
|
|
17
|
+
operation: input.operation,
|
|
18
|
+
reason: input.reason,
|
|
19
|
+
message: input.message,
|
|
20
|
+
occurredAt,
|
|
21
|
+
...(input.taskId ? { taskId: input.taskId } : {}),
|
|
22
|
+
...(input.observation ? { observation: input.observation } : {}),
|
|
23
|
+
...(input.recommendation ? { recommendation: input.recommendation } : {}),
|
|
24
|
+
};
|
|
25
|
+
await appendFile(join(this.dir, `${occurredAt.slice(0, 10)}.jsonl`), JSON.stringify(record) + '\n');
|
|
26
|
+
return record;
|
|
27
|
+
});
|
|
28
|
+
this.chain = write.catch(() => undefined);
|
|
29
|
+
return write;
|
|
30
|
+
}
|
|
31
|
+
async latestForAgent(agentId) {
|
|
32
|
+
const records = await this.readAll();
|
|
33
|
+
return records
|
|
34
|
+
.filter(record => record.agentId === agentId)
|
|
35
|
+
.sort((a, b) => b.occurredAt.localeCompare(a.occurredAt))[0];
|
|
36
|
+
}
|
|
37
|
+
async latestBootstrapForAgent(agentId) {
|
|
38
|
+
const records = await this.readAll();
|
|
39
|
+
return records
|
|
40
|
+
.filter(record => record.agentId === agentId && record.operation === 'bootstrap')
|
|
41
|
+
.sort((a, b) => b.occurredAt.localeCompare(a.occurredAt))[0];
|
|
42
|
+
}
|
|
43
|
+
// Batched variant for buildAllAgentSnapshots — one readAll() per snapshot pass instead of
|
|
44
|
+
// N (agent count) × full-history scan. Returns the most recent bootstrap record per agentId.
|
|
45
|
+
async latestBootstrapByAgent() {
|
|
46
|
+
const records = await this.readAll();
|
|
47
|
+
const latest = new Map();
|
|
48
|
+
for (const record of records) {
|
|
49
|
+
if (record.operation !== 'bootstrap')
|
|
50
|
+
continue;
|
|
51
|
+
const prev = latest.get(record.agentId);
|
|
52
|
+
if (!prev || record.occurredAt > prev.occurredAt) {
|
|
53
|
+
latest.set(record.agentId, record);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return latest;
|
|
57
|
+
}
|
|
58
|
+
// Drops every record for an agentId by rewriting each affected jsonl. Called from
|
|
59
|
+
// agent-delete so an id reused later (delete + recreate) doesn't inherit stale bootstrap
|
|
60
|
+
// errors from the previous incarnation. Best-effort; partial failures are logged not thrown.
|
|
61
|
+
async purgeAgent(agentId) {
|
|
62
|
+
const idMarker = `"agentId":${JSON.stringify(agentId)}`;
|
|
63
|
+
return this.rewriteFiltered({
|
|
64
|
+
mayMatch: content => content.includes(idMarker),
|
|
65
|
+
shouldDrop: record => record.agentId === agentId,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// Narrower variant: drops only bootstrap-operation records for one agent, called from
|
|
69
|
+
// runSingleTarget's success path on EVERY tick. Hot path — quickCheck must be cheap and
|
|
70
|
+
// truly short-circuit (read alone, no parse, no rewrite) in the common no-stale case.
|
|
71
|
+
async purgeBootstrapForAgent(agentId) {
|
|
72
|
+
const idMarker = `"agentId":${JSON.stringify(agentId)}`;
|
|
73
|
+
const opMarker = '"operation":"bootstrap"';
|
|
74
|
+
return this.rewriteFiltered({
|
|
75
|
+
mayMatch: content => content.includes(idMarker) && content.includes(opMarker),
|
|
76
|
+
shouldDrop: record => record.agentId === agentId && record.operation === 'bootstrap',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// One-shot sweep on startup / config-replace: drop bootstrap-operation records for every
|
|
80
|
+
// agent NOT currently in the auto-bootstrap set. Covers:
|
|
81
|
+
// (a) agent transitioned from auto-mode to explicit workdir (id stays, leaves bootstrap)
|
|
82
|
+
// (b) agent deleted while server was down
|
|
83
|
+
// (c) PATCH /config saved then restartRequired — old poller appended a fresh stale record
|
|
84
|
+
// in the window before restart; sweep on next startup clears it
|
|
85
|
+
// Done in a single rewriteFiltered pass — one full-history scan per startup rather than
|
|
86
|
+
// N (stale agents) × full scans.
|
|
87
|
+
async sweepStaleBootstrapErrors(activeAgentIds) {
|
|
88
|
+
return this.rewriteFiltered({
|
|
89
|
+
mayMatch: content => content.includes('"operation":"bootstrap"'),
|
|
90
|
+
shouldDrop: record => record.operation === 'bootstrap' && !activeAgentIds.has(record.agentId),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Shared rewrite-with-filter helper. shouldDrop returns true for records to remove.
|
|
94
|
+
// Uses tmp file + atomic rename per jsonl to survive crash/disk-full mid-rewrite
|
|
95
|
+
// (in-place writeFile would otherwise truncate the file and lose unrelated history).
|
|
96
|
+
// mayMatch lets callers short-circuit per file BEFORE the parse loop — without it, every
|
|
97
|
+
// call still parses the whole history even when nothing matches, defeating the rewrite skip.
|
|
98
|
+
rewriteFiltered(opts) {
|
|
99
|
+
const result = this.chain.then(async () => {
|
|
100
|
+
let files;
|
|
101
|
+
try {
|
|
102
|
+
files = await readdir(this.dir);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return { removed: 0 };
|
|
106
|
+
}
|
|
107
|
+
let removed = 0;
|
|
108
|
+
for (const file of files.filter(f => f.endsWith('.jsonl'))) {
|
|
109
|
+
const path = join(this.dir, file);
|
|
110
|
+
let content;
|
|
111
|
+
try {
|
|
112
|
+
content = await readFile(path, 'utf-8');
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
console.warn(`[ErrorRecordStore] rewriteFiltered: skipping unreadable ${file}:`, err);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (!opts.mayMatch(content))
|
|
119
|
+
continue;
|
|
120
|
+
const lines = content.split('\n');
|
|
121
|
+
const kept = [];
|
|
122
|
+
let fileRemoved = 0;
|
|
123
|
+
for (const line of lines) {
|
|
124
|
+
if (!line)
|
|
125
|
+
continue;
|
|
126
|
+
let record;
|
|
127
|
+
try {
|
|
128
|
+
record = JSON.parse(line);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
kept.push(line);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (opts.shouldDrop(record)) {
|
|
135
|
+
fileRemoved++;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
kept.push(line);
|
|
139
|
+
}
|
|
140
|
+
if (fileRemoved === 0)
|
|
141
|
+
continue;
|
|
142
|
+
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
143
|
+
try {
|
|
144
|
+
await writeFile(tmp, kept.length > 0 ? kept.join('\n') + '\n' : '');
|
|
145
|
+
await rename(tmp, path);
|
|
146
|
+
// Only count records as removed after the atomic rename succeeds. If writeFile or
|
|
147
|
+
// rename fails the original file is untouched, and callers (bootstrap.ts uses
|
|
148
|
+
// removed > 0 as a state-change signal) must not be misled into publishing a
|
|
149
|
+
// "stale error cleared" event for a purge that didn't actually happen.
|
|
150
|
+
removed += fileRemoved;
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
console.warn(`[ErrorRecordStore] rewriteFiltered: atomic rewrite failed for ${file}:`, err);
|
|
154
|
+
// Best-effort tmp cleanup so a partial write doesn't accumulate orphan .tmp files.
|
|
155
|
+
try {
|
|
156
|
+
await unlink(tmp);
|
|
157
|
+
}
|
|
158
|
+
catch { /* ignore — tmp may not exist if writeFile failed early */ }
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return { removed };
|
|
162
|
+
});
|
|
163
|
+
this.chain = result.catch(() => undefined);
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
toSummary(record) {
|
|
167
|
+
return {
|
|
168
|
+
id: record.id,
|
|
169
|
+
reason: record.reason,
|
|
170
|
+
message: record.message,
|
|
171
|
+
occurredAt: record.occurredAt,
|
|
172
|
+
...(record.recommendation ? { recommendation: record.recommendation } : {}),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async readAll() {
|
|
176
|
+
let files;
|
|
177
|
+
try {
|
|
178
|
+
files = await readdir(this.dir);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return [];
|
|
182
|
+
}
|
|
183
|
+
const records = [];
|
|
184
|
+
for (const file of files.filter(f => f.endsWith('.jsonl')).sort()) {
|
|
185
|
+
try {
|
|
186
|
+
const content = await readFile(join(this.dir, file), 'utf-8');
|
|
187
|
+
for (const line of content.trim().split('\n').filter(Boolean)) {
|
|
188
|
+
try {
|
|
189
|
+
records.push(JSON.parse(line));
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
console.warn(`[ErrorRecordStore] skipping unreadable line in ${file}:`, err);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
console.warn(`[ErrorRecordStore] skipping unreadable file ${file}:`, err);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return records;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=error-record-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-record-store.js","sourceRoot":"","sources":["../../src/state/error-record-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAmB,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/state/init.ts"],"names":[],"mappings":"AAGA,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASjE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export async function initStateDir(baseDir) {
|
|
4
|
+
await Promise.all([
|
|
5
|
+
mkdir(join(baseDir, 'state', 'agents'), { recursive: true }),
|
|
6
|
+
mkdir(join(baseDir, 'state', 'errors'), { recursive: true }),
|
|
7
|
+
mkdir(join(baseDir, 'state', 'tasks'), { recursive: true }),
|
|
8
|
+
mkdir(join(baseDir, 'state', 'post-approve'), { recursive: true }),
|
|
9
|
+
mkdir(join(baseDir, 'events'), { recursive: true }),
|
|
10
|
+
mkdir(join(baseDir, 'locks'), { recursive: true }),
|
|
11
|
+
]);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/state/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe;IAChD,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAClE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;KACnD,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class LockManager {
|
|
2
|
+
private dir;
|
|
3
|
+
constructor(dir: string);
|
|
4
|
+
acquire(agentId: string): Promise<boolean>;
|
|
5
|
+
release(agentId: string): Promise<void>;
|
|
6
|
+
isLocked(agentId: string): Promise<boolean>;
|
|
7
|
+
private path;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/state/lock.ts"],"names":[],"mappings":"AAGA,qBAAa,WAAW;IACV,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,MAAM;IAEzB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAa1C,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASjD,OAAO,CAAC,IAAI;CAGb"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { writeFile, unlink, stat } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export class LockManager {
|
|
4
|
+
dir;
|
|
5
|
+
constructor(dir) {
|
|
6
|
+
this.dir = dir;
|
|
7
|
+
}
|
|
8
|
+
async acquire(agentId) {
|
|
9
|
+
try {
|
|
10
|
+
await writeFile(this.path(agentId), JSON.stringify({ agentId, acquiredAt: new Date().toISOString() }) + '\n', { flag: 'wx' });
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async release(agentId) {
|
|
18
|
+
try {
|
|
19
|
+
await unlink(this.path(agentId));
|
|
20
|
+
}
|
|
21
|
+
catch { /* ignore */ }
|
|
22
|
+
}
|
|
23
|
+
async isLocked(agentId) {
|
|
24
|
+
try {
|
|
25
|
+
await stat(this.path(agentId));
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
path(agentId) {
|
|
33
|
+
return join(this.dir, `${agentId}.lock`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/state/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,OAAO,WAAW;IACF;IAApB,YAAoB,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;IAAG,CAAC;IAEnC,KAAK,CAAC,OAAO,CAAC,OAAe;QAC3B,IAAI,CAAC;YACH,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAClB,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,GAAG,IAAI,EACxE,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAe;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAEO,IAAI,CAAC,OAAe;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PostApproveCompletion {
|
|
2
|
+
token: string;
|
|
3
|
+
approvedHeadSha: string;
|
|
4
|
+
updatedAt: string;
|
|
5
|
+
redispatchCount?: number;
|
|
6
|
+
pendingRedispatch?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class PostApproveStore {
|
|
9
|
+
private readonly dir?;
|
|
10
|
+
private readonly memory;
|
|
11
|
+
constructor(dir?: string | undefined);
|
|
12
|
+
get(taskId: string): Promise<PostApproveCompletion | null>;
|
|
13
|
+
set(taskId: string, value: {
|
|
14
|
+
token: string;
|
|
15
|
+
approvedHeadSha: string;
|
|
16
|
+
redispatchCount?: number;
|
|
17
|
+
pendingRedispatch?: boolean;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
clear(taskId: string): Promise<void>;
|
|
20
|
+
clearIfMatches(taskId: string, token: string): Promise<boolean>;
|
|
21
|
+
private path;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=post-approve-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-approve-store.d.ts","sourceRoot":"","sources":["../../src/state/post-approve-store.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAElB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAiBD,qBAAa,gBAAgB;IAGf,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;IAFjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;gBAEtC,GAAG,CAAC,EAAE,MAAM,YAAA;IAEnC,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAU1D,GAAG,CACP,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B,GACA,OAAO,CAAC,IAAI,CAAC;IAmBV,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAapC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOrE,OAAO,CAAC,IAAI;CAGb"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
function sanitizeCompletion(raw) {
|
|
4
|
+
const value = (raw ?? {});
|
|
5
|
+
if (typeof value.token !== 'string' || value.token.trim() === '')
|
|
6
|
+
return null;
|
|
7
|
+
if (typeof value.approvedHeadSha !== 'string' || value.approvedHeadSha.trim() === '')
|
|
8
|
+
return null;
|
|
9
|
+
return {
|
|
10
|
+
token: value.token,
|
|
11
|
+
approvedHeadSha: value.approvedHeadSha,
|
|
12
|
+
updatedAt: typeof value.updatedAt === 'string' ? value.updatedAt : new Date().toISOString(),
|
|
13
|
+
...(typeof value.redispatchCount === 'number' && Number.isFinite(value.redispatchCount)
|
|
14
|
+
? { redispatchCount: value.redispatchCount }
|
|
15
|
+
: {}),
|
|
16
|
+
...(value.pendingRedispatch === true ? { pendingRedispatch: true } : {}),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export class PostApproveStore {
|
|
20
|
+
dir;
|
|
21
|
+
memory = new Map();
|
|
22
|
+
constructor(dir) {
|
|
23
|
+
this.dir = dir;
|
|
24
|
+
}
|
|
25
|
+
async get(taskId) {
|
|
26
|
+
if (!this.dir)
|
|
27
|
+
return this.memory.get(taskId) ?? null;
|
|
28
|
+
try {
|
|
29
|
+
const content = await readFile(this.path(taskId), 'utf-8');
|
|
30
|
+
return sanitizeCompletion(JSON.parse(content));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async set(taskId, value) {
|
|
37
|
+
const completion = {
|
|
38
|
+
token: value.token,
|
|
39
|
+
approvedHeadSha: value.approvedHeadSha,
|
|
40
|
+
updatedAt: new Date().toISOString(),
|
|
41
|
+
...(typeof value.redispatchCount === 'number' ? { redispatchCount: value.redispatchCount } : {}),
|
|
42
|
+
...(value.pendingRedispatch === true ? { pendingRedispatch: true } : {}),
|
|
43
|
+
};
|
|
44
|
+
if (!this.dir) {
|
|
45
|
+
this.memory.set(taskId, completion);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
await mkdir(this.dir, { recursive: true });
|
|
49
|
+
const final = this.path(taskId);
|
|
50
|
+
const tmp = `${final}.${process.pid}.${Date.now()}.tmp`;
|
|
51
|
+
await writeFile(tmp, JSON.stringify(completion, null, 2) + '\n');
|
|
52
|
+
await rename(tmp, final);
|
|
53
|
+
}
|
|
54
|
+
async clear(taskId) {
|
|
55
|
+
if (!this.dir) {
|
|
56
|
+
this.memory.delete(taskId);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
await unlink(this.path(taskId));
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const code = err?.code;
|
|
64
|
+
if (code !== 'ENOENT')
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async clearIfMatches(taskId, token) {
|
|
69
|
+
const current = await this.get(taskId);
|
|
70
|
+
if (!current || current.token !== token)
|
|
71
|
+
return false;
|
|
72
|
+
await this.clear(taskId);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
path(taskId) {
|
|
76
|
+
return join(this.dir, `${encodeURIComponent(taskId)}.json`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=post-approve-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-approve-store.js","sourceRoot":"","sources":["../../src/state/post-approve-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface ProcessLockInfo {
|
|
2
|
+
pid: number;
|
|
3
|
+
acquiredAt: string;
|
|
4
|
+
ownerId: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class ProcessLockError extends Error {
|
|
7
|
+
readonly existing?: ProcessLockInfo | undefined;
|
|
8
|
+
constructor(message: string, existing?: ProcessLockInfo | undefined);
|
|
9
|
+
}
|
|
10
|
+
/** Single-instance guard. Stale locks require manual cleanup (auto-unlink races). */
|
|
11
|
+
export declare class ProcessLock {
|
|
12
|
+
private acquired;
|
|
13
|
+
private ownerId;
|
|
14
|
+
private readonly path;
|
|
15
|
+
constructor(stateDir: string, fileName?: string);
|
|
16
|
+
/** Returns the lock info on success; throws {@link ProcessLockError} otherwise. */
|
|
17
|
+
acquire(): Promise<ProcessLockInfo>;
|
|
18
|
+
release(): Promise<void>;
|
|
19
|
+
releaseSync(): void;
|
|
20
|
+
isAcquired(): boolean;
|
|
21
|
+
getPath(): string;
|
|
22
|
+
private readExistingDetailed;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=process-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-lock.d.ts","sourceRoot":"","sources":["../../src/state/process-lock.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,gBAAiB,SAAQ,KAAK;aACI,QAAQ,CAAC,EAAE,eAAe;gBAA3D,OAAO,EAAE,MAAM,EAAkB,QAAQ,CAAC,EAAE,eAAe,YAAA;CAIxE;AAED,qFAAqF;AACrF,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB;IAI1D,mFAAmF;IAC7E,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IAyCnC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA0C9B,WAAW,IAAI,IAAI;IA8BnB,UAAU,IAAI,OAAO;IAIrB,OAAO,IAAI,MAAM;YAIH,oBAAoB;CA+BnC"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { writeFile, readFile, unlink } from 'node:fs/promises';
|
|
2
|
+
import { readFileSync, unlinkSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
const LOCK_FILE = '.baxian-server.lock';
|
|
6
|
+
const STALE_PROBE_SIGNAL = 0;
|
|
7
|
+
export class ProcessLockError extends Error {
|
|
8
|
+
existing;
|
|
9
|
+
constructor(message, existing) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.existing = existing;
|
|
12
|
+
this.name = 'ProcessLockError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Single-instance guard. Stale locks require manual cleanup (auto-unlink races). */
|
|
16
|
+
export class ProcessLock {
|
|
17
|
+
acquired = false;
|
|
18
|
+
ownerId = null;
|
|
19
|
+
path;
|
|
20
|
+
constructor(stateDir, fileName = LOCK_FILE) {
|
|
21
|
+
this.path = join(stateDir, fileName);
|
|
22
|
+
}
|
|
23
|
+
/** Returns the lock info on success; throws {@link ProcessLockError} otherwise. */
|
|
24
|
+
async acquire() {
|
|
25
|
+
const ownerId = randomUUID();
|
|
26
|
+
const info = {
|
|
27
|
+
pid: process.pid,
|
|
28
|
+
acquiredAt: new Date().toISOString(),
|
|
29
|
+
ownerId,
|
|
30
|
+
};
|
|
31
|
+
const payload = `${JSON.stringify(info)}\n`;
|
|
32
|
+
try {
|
|
33
|
+
await writeFile(this.path, payload, { flag: 'wx' });
|
|
34
|
+
this.acquired = true;
|
|
35
|
+
this.ownerId = ownerId;
|
|
36
|
+
return info;
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const code = err?.code;
|
|
40
|
+
if (code !== 'EEXIST')
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
const status = await this.readExistingDetailed();
|
|
44
|
+
if (status.kind === 'info' && isAlive(status.info.pid)) {
|
|
45
|
+
throw new ProcessLockError(`another baxian server appears to hold the lock at ${this.path} ` +
|
|
46
|
+
`(pid=${status.info.pid}, acquiredAt=${status.info.acquiredAt}); refusing to start`, status.info);
|
|
47
|
+
}
|
|
48
|
+
const detail = status.kind === 'info'
|
|
49
|
+
? `(prior owner pid=${status.info.pid} acquiredAt=${status.info.acquiredAt} no longer alive); `
|
|
50
|
+
: status.kind === 'malformed'
|
|
51
|
+
? '(file is malformed / unreadable owner info); '
|
|
52
|
+
: '(file vanished between EEXIST and re-read; another process may be racing); ';
|
|
53
|
+
throw new ProcessLockError(`stale lock file at ${this.path} ${detail}` +
|
|
54
|
+
`verify no baxian server is running and remove the file manually before retrying`, status.kind === 'info' ? status.info : undefined);
|
|
55
|
+
}
|
|
56
|
+
async release() {
|
|
57
|
+
if (!this.acquired)
|
|
58
|
+
return;
|
|
59
|
+
const ownerId = this.ownerId;
|
|
60
|
+
const status = await this.readExistingDetailed();
|
|
61
|
+
if (status.kind === 'missing') {
|
|
62
|
+
this.acquired = false;
|
|
63
|
+
this.ownerId = null;
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (status.kind === 'malformed') {
|
|
67
|
+
throw new ProcessLockError(`lock file at ${this.path} is malformed; cannot prove ownership, refusing to delete. ` +
|
|
68
|
+
`Verify no baxian server is running and remove the file manually if appropriate.`);
|
|
69
|
+
}
|
|
70
|
+
if (status.info.ownerId !== ownerId) {
|
|
71
|
+
this.acquired = false;
|
|
72
|
+
this.ownerId = null;
|
|
73
|
+
throw new ProcessLockError(`lock at ${this.path} was replaced by a different owner ` +
|
|
74
|
+
`(expected ${ownerId}, found ${status.info.ownerId} pid=${status.info.pid}); ` +
|
|
75
|
+
`not deleting another process's lock`, status.info);
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
await unlink(this.path);
|
|
79
|
+
this.acquired = false;
|
|
80
|
+
this.ownerId = null;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
const code = err?.code;
|
|
84
|
+
if (code === 'ENOENT') {
|
|
85
|
+
this.acquired = false;
|
|
86
|
+
this.ownerId = null;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Best-effort sync release for `process.once('exit', ...)` where async fs is dropped.
|
|
93
|
+
releaseSync() {
|
|
94
|
+
if (!this.acquired)
|
|
95
|
+
return;
|
|
96
|
+
let raw;
|
|
97
|
+
try {
|
|
98
|
+
raw = readFileSync(this.path, 'utf-8');
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (err?.code === 'ENOENT') {
|
|
102
|
+
this.acquired = false;
|
|
103
|
+
this.ownerId = null;
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
let parsed;
|
|
108
|
+
try {
|
|
109
|
+
parsed = JSON.parse(raw);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (typeof parsed.ownerId !== 'string' || parsed.ownerId !== this.ownerId) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
unlinkSync(this.path);
|
|
119
|
+
this.acquired = false;
|
|
120
|
+
this.ownerId = null;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// best-effort: process is exiting anyway
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
isAcquired() {
|
|
127
|
+
return this.acquired;
|
|
128
|
+
}
|
|
129
|
+
getPath() {
|
|
130
|
+
return this.path;
|
|
131
|
+
}
|
|
132
|
+
async readExistingDetailed() {
|
|
133
|
+
let raw;
|
|
134
|
+
try {
|
|
135
|
+
raw = await readFile(this.path, 'utf-8');
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
const code = err?.code;
|
|
139
|
+
if (code === 'ENOENT')
|
|
140
|
+
return { kind: 'missing' };
|
|
141
|
+
throw err;
|
|
142
|
+
}
|
|
143
|
+
let parsed;
|
|
144
|
+
try {
|
|
145
|
+
parsed = JSON.parse(raw);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return { kind: 'malformed' };
|
|
149
|
+
}
|
|
150
|
+
if (typeof parsed.pid !== 'number' || typeof parsed.acquiredAt !== 'string') {
|
|
151
|
+
return { kind: 'malformed' };
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
kind: 'info',
|
|
155
|
+
info: {
|
|
156
|
+
pid: parsed.pid,
|
|
157
|
+
acquiredAt: parsed.acquiredAt,
|
|
158
|
+
ownerId: typeof parsed.ownerId === 'string' ? parsed.ownerId : '',
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function isAlive(pid) {
|
|
164
|
+
if (!Number.isFinite(pid) || pid <= 0)
|
|
165
|
+
return false;
|
|
166
|
+
try {
|
|
167
|
+
process.kill(pid, STALE_PROBE_SIGNAL);
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
// EPERM: process exists, owned by another user.
|
|
172
|
+
return err?.code === 'EPERM';
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=process-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-lock.js","sourceRoot":"","sources":["../../src/state/process-lock.ts"],"names":[],"mappings":"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"}
|