agentrinse 0.4.0 → 0.5.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/README.md +57 -48
- package/dist/adapters/claude-cache.d.ts +3 -0
- package/dist/adapters/claude-cache.d.ts.map +1 -0
- package/dist/adapters/claude-cache.js +67 -0
- package/dist/adapters/claude-cache.js.map +1 -0
- package/dist/adapters/claude-debug.d.ts +3 -0
- package/dist/adapters/claude-debug.d.ts.map +1 -0
- package/dist/adapters/claude-debug.js +100 -0
- package/dist/adapters/claude-debug.js.map +1 -0
- package/dist/adapters/claude-retention.d.ts +36 -0
- package/dist/adapters/claude-retention.d.ts.map +1 -0
- package/dist/adapters/claude-retention.js +176 -0
- package/dist/adapters/claude-retention.js.map +1 -0
- package/dist/adapters/copilot-maintenance.d.ts +23 -0
- package/dist/adapters/copilot-maintenance.d.ts.map +1 -0
- package/dist/adapters/copilot-maintenance.js +53 -0
- package/dist/adapters/copilot-maintenance.js.map +1 -0
- package/dist/adapters/provider-adapter.d.ts +1 -0
- package/dist/adapters/provider-adapter.d.ts.map +1 -1
- package/dist/adapters/provider-adapter.js +209 -4
- package/dist/adapters/provider-adapter.js.map +1 -1
- package/dist/adapters/provider-root.d.ts +8 -0
- package/dist/adapters/provider-root.d.ts.map +1 -0
- package/dist/adapters/provider-root.js +27 -0
- package/dist/adapters/provider-root.js.map +1 -0
- package/dist/adapters/provider-specs.d.ts.map +1 -1
- package/dist/adapters/provider-specs.js +10 -0
- package/dist/adapters/provider-specs.js.map +1 -1
- package/dist/adapters/registry.d.ts.map +1 -1
- package/dist/adapters/registry.js +1 -0
- package/dist/adapters/registry.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +2 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/purge.d.ts +7 -1
- package/dist/commands/purge.d.ts.map +1 -1
- package/dist/commands/purge.js +23 -0
- package/dist/commands/purge.js.map +1 -1
- package/dist/commands/show.d.ts.map +1 -1
- package/dist/commands/show.js +3 -0
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/undo.d.ts +4 -1
- package/dist/commands/undo.d.ts.map +1 -1
- package/dist/commands/undo.js +18 -1
- package/dist/commands/undo.js.map +1 -1
- package/dist/contracts/action.d.ts +335 -2
- package/dist/contracts/action.d.ts.map +1 -1
- package/dist/contracts/action.js +52 -1
- package/dist/contracts/action.js.map +1 -1
- package/dist/contracts/finding.d.ts +153 -2
- package/dist/contracts/finding.d.ts.map +1 -1
- package/dist/contracts/plan.d.ts +152 -2
- package/dist/contracts/plan.d.ts.map +1 -1
- package/dist/contracts/plan.js +1 -1
- package/dist/contracts/plan.js.map +1 -1
- package/dist/contracts/provider-file-quarantine.d.ts +221 -0
- package/dist/contracts/provider-file-quarantine.d.ts.map +1 -0
- package/dist/contracts/provider-file-quarantine.js +61 -0
- package/dist/contracts/provider-file-quarantine.js.map +1 -0
- package/dist/contracts/report.d.ts +153 -2
- package/dist/contracts/report.d.ts.map +1 -1
- package/dist/contracts/resource.d.ts +3 -0
- package/dist/contracts/resource.d.ts.map +1 -1
- package/dist/contracts/resource.js +1 -0
- package/dist/contracts/resource.js.map +1 -1
- package/dist/contracts/run.d.ts +94 -0
- package/dist/contracts/run.d.ts.map +1 -1
- package/dist/contracts/run.js +7 -0
- package/dist/contracts/run.js.map +1 -1
- package/dist/core/apply.d.ts +5 -1
- package/dist/core/apply.d.ts.map +1 -1
- package/dist/core/apply.js +74 -3
- package/dist/core/apply.js.map +1 -1
- package/dist/core/no-clobber-rename.d.ts +1 -0
- package/dist/core/no-clobber-rename.d.ts.map +1 -1
- package/dist/core/no-clobber-rename.js +44 -0
- package/dist/core/no-clobber-rename.js.map +1 -1
- package/dist/core/pinned-file.d.ts +37 -0
- package/dist/core/pinned-file.d.ts.map +1 -0
- package/dist/core/pinned-file.js +228 -0
- package/dist/core/pinned-file.js.map +1 -0
- package/dist/core/plan.d.ts.map +1 -1
- package/dist/core/plan.js +4 -1
- package/dist/core/plan.js.map +1 -1
- package/dist/core/process-ownership.d.ts +1 -0
- package/dist/core/process-ownership.d.ts.map +1 -1
- package/dist/core/process-ownership.js +17 -3
- package/dist/core/process-ownership.js.map +1 -1
- package/dist/core/provider-file-executor.d.ts +40 -0
- package/dist/core/provider-file-executor.d.ts.map +1 -0
- package/dist/core/provider-file-executor.js +259 -0
- package/dist/core/provider-file-executor.js.map +1 -0
- package/dist/core/provider-file-identity.d.ts +8 -0
- package/dist/core/provider-file-identity.d.ts.map +1 -0
- package/dist/core/provider-file-identity.js +113 -0
- package/dist/core/provider-file-identity.js.map +1 -0
- package/dist/core/provider-file-policy.d.ts +19 -0
- package/dist/core/provider-file-policy.d.ts.map +1 -0
- package/dist/core/provider-file-policy.js +72 -0
- package/dist/core/provider-file-policy.js.map +1 -0
- package/dist/core/provider-file-recovery.d.ts +25 -0
- package/dist/core/provider-file-recovery.d.ts.map +1 -0
- package/dist/core/provider-file-recovery.js +393 -0
- package/dist/core/provider-file-recovery.js.map +1 -0
- package/dist/core/provider-file-revalidation.d.ts +20 -0
- package/dist/core/provider-file-revalidation.d.ts.map +1 -0
- package/dist/core/provider-file-revalidation.js +60 -0
- package/dist/core/provider-file-revalidation.js.map +1 -0
- package/dist/core/provider-processes.d.ts +18 -0
- package/dist/core/provider-processes.d.ts.map +1 -0
- package/dist/core/provider-processes.js +90 -0
- package/dist/core/provider-processes.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/state/json-file.d.ts +2 -1
- package/dist/state/json-file.d.ts.map +1 -1
- package/dist/state/json-file.js +59 -2
- package/dist/state/json-file.js.map +1 -1
- package/dist/state/layout.d.ts +1 -0
- package/dist/state/layout.d.ts.map +1 -1
- package/dist/state/layout.js +1 -0
- package/dist/state/layout.js.map +1 -1
- package/dist/state/run-journal.d.ts.map +1 -1
- package/dist/state/run-journal.js +8 -2
- package/dist/state/run-journal.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/schemas/audit.schema.json +786 -1
- package/schemas/plan.schema.json +785 -1
- package/schemas/provider-file-quarantine.schema.json +741 -0
- package/schemas/run.schema.json +85 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { lstat } from "node:fs/promises";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { providerFileQuarantineEntrySchema, } from "../contracts/provider-file-quarantine.js";
|
|
6
|
+
import { writeJsonAtomic } from "../state/json-file.js";
|
|
7
|
+
import { renameAtNoReplace } from "./no-clobber-rename.js";
|
|
8
|
+
import { openPinnedProviderFile, openPinnedProviderParent, } from "./pinned-file.js";
|
|
9
|
+
import { inspectProviderFile, providerFileIdentityMatches, providerFileStatsMatch, } from "./provider-file-identity.js";
|
|
10
|
+
import { providerFileQuarantinePath } from "./provider-file-executor.js";
|
|
11
|
+
import { inspectProviderProcesses } from "./provider-processes.js";
|
|
12
|
+
import { findProcessesUsingFile } from "./process-ownership.js";
|
|
13
|
+
export function providerFilePurgeIsolationPath(quarantineDirectory, entryId) {
|
|
14
|
+
return join(quarantineDirectory, `${entryId}.payload.purging`);
|
|
15
|
+
}
|
|
16
|
+
const EMPTY_FILE_SHA256 = createHash("sha256").digest("hex");
|
|
17
|
+
function isMissing(error) {
|
|
18
|
+
return (error instanceof Error && "code" in error && error.code === "ENOENT");
|
|
19
|
+
}
|
|
20
|
+
async function pathExists(path) {
|
|
21
|
+
try {
|
|
22
|
+
await lstat(path);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (isMissing(error)) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function openValidatedFile(path, ownerRoot, identity, allowSealedMode = false) {
|
|
33
|
+
const handle = await openPinnedProviderFile(path, ownerRoot);
|
|
34
|
+
try {
|
|
35
|
+
const stats = await handle.stat();
|
|
36
|
+
if (!stats.isFile()) {
|
|
37
|
+
throw new Error(`provider-file recovery target is not a regular file: ${path}`);
|
|
38
|
+
}
|
|
39
|
+
if (!providerFileStatsMatch(stats, identity, allowSealedMode)) {
|
|
40
|
+
throw new Error(`provider-file descriptor identity changed: ${path}`);
|
|
41
|
+
}
|
|
42
|
+
return handle;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
await handle.close().catch(() => undefined);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function openValidatedWritableFile(path, ownerRoot, identity, readHandle) {
|
|
50
|
+
const openWritable = () => openPinnedProviderFile(path, ownerRoot, constants.O_RDWR);
|
|
51
|
+
let writeHandle;
|
|
52
|
+
let modeAdjusted = false;
|
|
53
|
+
try {
|
|
54
|
+
try {
|
|
55
|
+
writeHandle = await openWritable();
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (!(error instanceof Error) ||
|
|
59
|
+
!("code" in error) ||
|
|
60
|
+
!["EACCES", "EPERM"].includes(error.code ?? "")) {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
await readHandle.chmod((identity.mode & 0o7777) | 0o200);
|
|
64
|
+
await readHandle.sync();
|
|
65
|
+
modeAdjusted = true;
|
|
66
|
+
writeHandle = await openWritable();
|
|
67
|
+
}
|
|
68
|
+
const writableMode = modeAdjusted ? identity.mode | 0o200 : identity.mode;
|
|
69
|
+
if (!providerFileStatsMatch(await writeHandle.stat(), { ...identity, mode: writableMode })) {
|
|
70
|
+
throw new Error(`provider-file writable descriptor identity changed: ${path}`);
|
|
71
|
+
}
|
|
72
|
+
await readHandle.chmod(identity.mode & ~0o222);
|
|
73
|
+
await readHandle.sync();
|
|
74
|
+
if (!providerFileStatsMatch(await readHandle.stat(), identity, true) ||
|
|
75
|
+
!providerFileStatsMatch(await writeHandle.stat(), identity, true)) {
|
|
76
|
+
throw new Error(`provider-file descriptor identity changed while sealing purge: ${path}`);
|
|
77
|
+
}
|
|
78
|
+
return writeHandle;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
await writeHandle?.close().catch(() => undefined);
|
|
82
|
+
if (modeAdjusted) {
|
|
83
|
+
await readHandle.chmod(identity.mode & 0o7777).catch(() => undefined);
|
|
84
|
+
await readHandle.sync().catch(() => undefined);
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function restoreValidatedMode(path, identity) {
|
|
90
|
+
const handle = await openValidatedFile(path, identity.ownerRoot, identity, true);
|
|
91
|
+
try {
|
|
92
|
+
await handle.chmod(identity.mode & 0o7777);
|
|
93
|
+
await handle.sync();
|
|
94
|
+
if (!providerFileStatsMatch(await handle.stat(), identity)) {
|
|
95
|
+
throw new Error(`provider-file mode repair changed descriptor identity: ${path}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
await handle.close();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function assertOwnedPaths(entry, options) {
|
|
103
|
+
const expectedManifest = join(options.quarantineDirectory, `${entry.entryId}.json`);
|
|
104
|
+
const expectedPayload = providerFileQuarantinePath(options.quarantineDirectory, entry.entryId);
|
|
105
|
+
if (resolve(options.manifestPath) !== resolve(expectedManifest) ||
|
|
106
|
+
resolve(entry.quarantinePath) !== resolve(expectedPayload) ||
|
|
107
|
+
resolve(entry.originalPath) !== resolve(entry.target.path)) {
|
|
108
|
+
throw new Error("provider-file recovery manifest contains paths outside its owned set");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async function persist(entry, options) {
|
|
112
|
+
const parsed = providerFileQuarantineEntrySchema.parse(entry);
|
|
113
|
+
assertOwnedPaths(parsed, options);
|
|
114
|
+
await writeJsonAtomic(options.manifestPath, parsed, {
|
|
115
|
+
privateDirectories: [options.quarantineDirectory],
|
|
116
|
+
});
|
|
117
|
+
return parsed;
|
|
118
|
+
}
|
|
119
|
+
function movedIdentityMatches(actual, entry) {
|
|
120
|
+
const expected = entry.target;
|
|
121
|
+
return (actual.provider === expected.provider &&
|
|
122
|
+
actual.device === expected.device &&
|
|
123
|
+
actual.inode === expected.inode &&
|
|
124
|
+
actual.linkCount === expected.linkCount &&
|
|
125
|
+
(actual.mode === expected.mode || actual.mode === (expected.mode & ~0o222)) &&
|
|
126
|
+
actual.mtimeMs === expected.mtimeMs &&
|
|
127
|
+
actual.measuredBytes === expected.measuredBytes &&
|
|
128
|
+
actual.contentSha256 === expected.contentSha256);
|
|
129
|
+
}
|
|
130
|
+
function purgedMarkerMatches(actual, entry) {
|
|
131
|
+
const expected = entry.target;
|
|
132
|
+
return (actual.provider === expected.provider &&
|
|
133
|
+
actual.device === expected.device &&
|
|
134
|
+
actual.inode === expected.inode &&
|
|
135
|
+
actual.linkCount === expected.linkCount &&
|
|
136
|
+
actual.mode === (expected.mode & ~0o222) &&
|
|
137
|
+
actual.measuredBytes === 0 &&
|
|
138
|
+
actual.contentSha256 === EMPTY_FILE_SHA256);
|
|
139
|
+
}
|
|
140
|
+
async function inspectOriginal(entry) {
|
|
141
|
+
if (!(await pathExists(entry.originalPath))) {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
return inspectProviderFile(entry.originalPath, entry.target.ownerRoot, entry.target.provider);
|
|
145
|
+
}
|
|
146
|
+
async function inspectQuarantine(entry, options) {
|
|
147
|
+
return inspectPayload(entry.quarantinePath, entry, options);
|
|
148
|
+
}
|
|
149
|
+
async function inspectPurgeIsolation(entry, options) {
|
|
150
|
+
return inspectPayload(providerFilePurgeIsolationPath(options.quarantineDirectory, entry.entryId), entry, options);
|
|
151
|
+
}
|
|
152
|
+
async function inspectPayload(path, entry, options) {
|
|
153
|
+
if (!(await pathExists(path))) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
return inspectProviderFile(path, options.quarantineDirectory, entry.target.provider);
|
|
157
|
+
}
|
|
158
|
+
async function reconcile(entry, options) {
|
|
159
|
+
assertOwnedPaths(entry, options);
|
|
160
|
+
const [original, quarantine, purgeIsolation] = await Promise.all([
|
|
161
|
+
inspectOriginal(entry),
|
|
162
|
+
inspectQuarantine(entry, options),
|
|
163
|
+
inspectPurgeIsolation(entry, options),
|
|
164
|
+
]);
|
|
165
|
+
const occupiedPathCount = [original, quarantine, purgeIsolation].filter((identity) => identity !== undefined).length;
|
|
166
|
+
if (occupiedPathCount > 1) {
|
|
167
|
+
throw new Error("provider-file recovery state is ambiguous: multiple paths are occupied");
|
|
168
|
+
}
|
|
169
|
+
if (occupiedPathCount === 0) {
|
|
170
|
+
if (entry.status === "purging" || entry.status === "purged") {
|
|
171
|
+
return persist({
|
|
172
|
+
...entry,
|
|
173
|
+
status: "purged",
|
|
174
|
+
purgedAt: entry.purgedAt ?? (options.dependencies?.clock ?? (() => new Date()))().toISOString(),
|
|
175
|
+
}, options);
|
|
176
|
+
}
|
|
177
|
+
throw new Error("provider-file recovery state is ambiguous: both paths are missing");
|
|
178
|
+
}
|
|
179
|
+
if (original !== undefined) {
|
|
180
|
+
if (!providerFileIdentityMatches(original, entry.target, true)) {
|
|
181
|
+
throw new Error("provider-file original path no longer matches the recovery manifest");
|
|
182
|
+
}
|
|
183
|
+
await assertOffline(entry, entry.originalPath, options.dependencies ?? {});
|
|
184
|
+
await restoreValidatedMode(entry.originalPath, entry.target);
|
|
185
|
+
if (["preparing", "restoring", "restored"].includes(entry.status)) {
|
|
186
|
+
return persist({
|
|
187
|
+
...entry,
|
|
188
|
+
status: "restored",
|
|
189
|
+
restoredAt: entry.restoredAt ?? (options.dependencies?.clock ?? (() => new Date()))().toISOString(),
|
|
190
|
+
diagnostic: undefined,
|
|
191
|
+
}, options);
|
|
192
|
+
}
|
|
193
|
+
throw new Error("provider-file recovery found unexpected content at the original path");
|
|
194
|
+
}
|
|
195
|
+
if (purgeIsolation !== undefined) {
|
|
196
|
+
if (["purging", "purged"].includes(entry.status) &&
|
|
197
|
+
purgedMarkerMatches(purgeIsolation, entry)) {
|
|
198
|
+
return persist({
|
|
199
|
+
...entry,
|
|
200
|
+
status: "purged",
|
|
201
|
+
purgedAt: entry.purgedAt ?? (options.dependencies?.clock ?? (() => new Date()))().toISOString(),
|
|
202
|
+
quarantineIdentity: purgeIsolation,
|
|
203
|
+
diagnostic: undefined,
|
|
204
|
+
}, options);
|
|
205
|
+
}
|
|
206
|
+
if (entry.status !== "purging" || !movedIdentityMatches(purgeIsolation, entry)) {
|
|
207
|
+
throw new Error("provider-file purge isolation payload does not match its manifest");
|
|
208
|
+
}
|
|
209
|
+
return persist({
|
|
210
|
+
...entry,
|
|
211
|
+
status: "purging",
|
|
212
|
+
quarantineIdentity: purgeIsolation,
|
|
213
|
+
}, options);
|
|
214
|
+
}
|
|
215
|
+
if (quarantine === undefined || !movedIdentityMatches(quarantine, entry)) {
|
|
216
|
+
throw new Error("provider-file quarantine payload no longer matches the recovery manifest");
|
|
217
|
+
}
|
|
218
|
+
if (["preparing", "quarantined", "restoring", "purging", "partial"].includes(entry.status)) {
|
|
219
|
+
return persist({
|
|
220
|
+
...entry,
|
|
221
|
+
status: ["restoring", "purging"].includes(entry.status) ? entry.status : "quarantined",
|
|
222
|
+
quarantineIdentity: quarantine,
|
|
223
|
+
}, options);
|
|
224
|
+
}
|
|
225
|
+
return entry;
|
|
226
|
+
}
|
|
227
|
+
async function assertOffline(entry, path, dependencies) {
|
|
228
|
+
const processes = await (dependencies.inspectProcesses ?? inspectProviderProcesses)(entry.target.provider);
|
|
229
|
+
if (processes.status !== "idle") {
|
|
230
|
+
throw new Error(processes.status === "busy"
|
|
231
|
+
? `${entry.target.provider} is running; provider-file recovery is refused`
|
|
232
|
+
: `${entry.target.provider} process state is unknown: ${processes.reason}`);
|
|
233
|
+
}
|
|
234
|
+
const handles = await (dependencies.inspectOpenHandles ?? findProcessesUsingFile)(path);
|
|
235
|
+
if (handles.status !== "idle") {
|
|
236
|
+
throw new Error(handles.status === "busy"
|
|
237
|
+
? "a process has the provider-file recovery path open"
|
|
238
|
+
: `provider-file descriptor state is unknown: ${handles.reason}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
export async function undoProviderFileQuarantine(input, options) {
|
|
242
|
+
const dependencies = options.dependencies ?? {};
|
|
243
|
+
const clock = dependencies.clock ?? (() => new Date());
|
|
244
|
+
let entry = await reconcile(providerFileQuarantineEntrySchema.parse(input), options);
|
|
245
|
+
if (entry.status === "restored") {
|
|
246
|
+
return entry;
|
|
247
|
+
}
|
|
248
|
+
if (entry.status !== "quarantined" &&
|
|
249
|
+
entry.status !== "restoring" &&
|
|
250
|
+
entry.status !== "partial") {
|
|
251
|
+
throw new Error(`provider-file quarantine entry cannot be restored from ${entry.status}`);
|
|
252
|
+
}
|
|
253
|
+
await assertOffline(entry, entry.quarantinePath, dependencies);
|
|
254
|
+
const sourceHandle = await openValidatedFile(entry.quarantinePath, options.quarantineDirectory, entry.quarantineIdentity, true);
|
|
255
|
+
const destination = await openPinnedProviderParent(entry.target.ownerRoot, entry.target.relativePath);
|
|
256
|
+
try {
|
|
257
|
+
await sourceHandle.chmod(entry.target.mode & ~0o222);
|
|
258
|
+
await sourceHandle.sync();
|
|
259
|
+
if (!providerFileStatsMatch(await sourceHandle.stat(), entry.target, true)) {
|
|
260
|
+
throw new Error("provider-file payload changed while it was sealed for restore");
|
|
261
|
+
}
|
|
262
|
+
entry = await persist({ ...entry, status: "restoring", quarantineIdentity: entry.quarantineIdentity }, options);
|
|
263
|
+
if (dependencies.move !== undefined) {
|
|
264
|
+
await dependencies.move(entry.quarantinePath, entry.originalPath);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
await renameAtNoReplace(sourceHandle.parent.fd, sourceHandle.basename, destination.parent.fd, destination.basename, dependencies.platform ?? process.platform);
|
|
268
|
+
}
|
|
269
|
+
const restoredHandle = await openPinnedProviderFile(entry.originalPath, entry.target.ownerRoot).catch(() => undefined);
|
|
270
|
+
const restoredStats = await restoredHandle?.stat().catch(() => undefined);
|
|
271
|
+
await restoredHandle?.close().catch(() => undefined);
|
|
272
|
+
if (restoredStats === undefined || !providerFileStatsMatch(restoredStats, entry.target, true)) {
|
|
273
|
+
if (dependencies.move !== undefined) {
|
|
274
|
+
await dependencies.move(entry.originalPath, entry.quarantinePath);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
await renameAtNoReplace(destination.parent.fd, destination.basename, sourceHandle.parent.fd, sourceHandle.basename, dependencies.platform ?? process.platform);
|
|
278
|
+
}
|
|
279
|
+
throw new Error("provider-file restore pathname changed before the atomic move");
|
|
280
|
+
}
|
|
281
|
+
await Promise.all([destination.parent.sync(), sourceHandle.parent.sync()]);
|
|
282
|
+
const sealedRestored = await inspectProviderFile(entry.originalPath, entry.target.ownerRoot, entry.target.provider);
|
|
283
|
+
if (!providerFileIdentityMatches(sealedRestored, entry.target, true)) {
|
|
284
|
+
throw new Error("restored provider file no longer matches the recovery manifest");
|
|
285
|
+
}
|
|
286
|
+
await sourceHandle.chmod(entry.target.mode & 0o7777);
|
|
287
|
+
await sourceHandle.sync();
|
|
288
|
+
const finalHandle = await openPinnedProviderFile(entry.originalPath, entry.target.ownerRoot).catch(() => undefined);
|
|
289
|
+
const finalStats = await finalHandle?.stat().catch(() => undefined);
|
|
290
|
+
await finalHandle?.close().catch(() => undefined);
|
|
291
|
+
if (!providerFileStatsMatch(await sourceHandle.stat(), entry.target) ||
|
|
292
|
+
finalStats === undefined ||
|
|
293
|
+
!providerFileStatsMatch(finalStats, entry.target)) {
|
|
294
|
+
throw new Error("restored provider file mode changed before recovery completed");
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
await Promise.all([
|
|
299
|
+
sourceHandle.close().catch(() => undefined),
|
|
300
|
+
destination.parent.close().catch(() => undefined),
|
|
301
|
+
]);
|
|
302
|
+
}
|
|
303
|
+
return persist({
|
|
304
|
+
...entry,
|
|
305
|
+
status: "restored",
|
|
306
|
+
restoredAt: clock().toISOString(),
|
|
307
|
+
diagnostic: undefined,
|
|
308
|
+
}, options);
|
|
309
|
+
}
|
|
310
|
+
export async function purgeProviderFileQuarantine(input, options) {
|
|
311
|
+
const dependencies = options.dependencies ?? {};
|
|
312
|
+
const clock = dependencies.clock ?? (() => new Date());
|
|
313
|
+
let entry = await reconcile(providerFileQuarantineEntrySchema.parse(input), options);
|
|
314
|
+
if (entry.status === "purged") {
|
|
315
|
+
return { entry, reclaimedBytes: 0 };
|
|
316
|
+
}
|
|
317
|
+
if (entry.status !== "quarantined" && entry.status !== "purging") {
|
|
318
|
+
throw new Error(`provider-file quarantine entry cannot be purged from ${entry.status}`);
|
|
319
|
+
}
|
|
320
|
+
if (!options.allowUnexpired && Date.parse(entry.expiresAt) > clock().getTime()) {
|
|
321
|
+
throw new Error(`provider-file quarantine entry has not expired: ${entry.entryId}`);
|
|
322
|
+
}
|
|
323
|
+
const purgeIsolationPath = providerFilePurgeIsolationPath(options.quarantineDirectory, entry.entryId);
|
|
324
|
+
const alreadyIsolated = await pathExists(purgeIsolationPath);
|
|
325
|
+
const payloadPath = alreadyIsolated ? purgeIsolationPath : entry.quarantinePath;
|
|
326
|
+
await assertOffline(entry, payloadPath, dependencies);
|
|
327
|
+
const payloadHandle = await openValidatedFile(payloadPath, options.quarantineDirectory, entry.quarantineIdentity, true);
|
|
328
|
+
let writableHandle;
|
|
329
|
+
try {
|
|
330
|
+
writableHandle = await openValidatedWritableFile(payloadPath, options.quarantineDirectory, entry.target, payloadHandle);
|
|
331
|
+
entry = await persist({ ...entry, status: "purging", quarantineIdentity: entry.quarantineIdentity }, options);
|
|
332
|
+
if (!alreadyIsolated) {
|
|
333
|
+
if (dependencies.move !== undefined) {
|
|
334
|
+
await dependencies.move(entry.quarantinePath, purgeIsolationPath);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
await renameAtNoReplace(payloadHandle.parent.fd, payloadHandle.basename, payloadHandle.parent.fd, `${entry.entryId}.payload.purging`, dependencies.platform ?? process.platform);
|
|
338
|
+
}
|
|
339
|
+
const isolatedHandle = await openPinnedProviderFile(purgeIsolationPath, options.quarantineDirectory).catch(() => undefined);
|
|
340
|
+
const isolatedStats = await isolatedHandle?.stat().catch(() => undefined);
|
|
341
|
+
await isolatedHandle?.close().catch(() => undefined);
|
|
342
|
+
if (isolatedStats === undefined ||
|
|
343
|
+
!providerFileStatsMatch(isolatedStats, entry.target, true) ||
|
|
344
|
+
!providerFileStatsMatch(await payloadHandle.stat(), entry.target, true)) {
|
|
345
|
+
let rollbackError;
|
|
346
|
+
try {
|
|
347
|
+
if (dependencies.move !== undefined) {
|
|
348
|
+
await dependencies.move(purgeIsolationPath, entry.quarantinePath);
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
await renameAtNoReplace(payloadHandle.parent.fd, `${entry.entryId}.payload.purging`, payloadHandle.parent.fd, payloadHandle.basename, dependencies.platform ?? process.platform);
|
|
352
|
+
}
|
|
353
|
+
await payloadHandle.parent.sync();
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
rollbackError = error;
|
|
357
|
+
}
|
|
358
|
+
if (rollbackError !== undefined) {
|
|
359
|
+
throw new AggregateError([new Error("provider-file purge claimed an unexpected inode"), rollbackError], "provider-file purge claim rollback failed");
|
|
360
|
+
}
|
|
361
|
+
throw new Error("provider-file purge pathname changed before the atomic claim; the unexpected inode was restored");
|
|
362
|
+
}
|
|
363
|
+
await payloadHandle.parent.sync();
|
|
364
|
+
}
|
|
365
|
+
await (dependencies.truncateHandle ?? ((handle) => handle.truncate(0)))(writableHandle);
|
|
366
|
+
await writableHandle.sync();
|
|
367
|
+
const truncatedStats = await writableHandle.stat();
|
|
368
|
+
if (!truncatedStats.isFile() ||
|
|
369
|
+
truncatedStats.dev !== entry.target.device ||
|
|
370
|
+
truncatedStats.ino !== entry.target.inode ||
|
|
371
|
+
truncatedStats.nlink !== entry.target.linkCount ||
|
|
372
|
+
truncatedStats.size !== 0) {
|
|
373
|
+
throw new Error("provider-file purge did not truncate the claimed inode");
|
|
374
|
+
}
|
|
375
|
+
const purgedMarker = await inspectProviderFile(purgeIsolationPath, options.quarantineDirectory, entry.target.provider);
|
|
376
|
+
if (!purgedMarkerMatches(purgedMarker, entry)) {
|
|
377
|
+
throw new Error("provider-file purge marker no longer names the claimed inode");
|
|
378
|
+
}
|
|
379
|
+
entry = await persist({
|
|
380
|
+
...entry,
|
|
381
|
+
status: "purged",
|
|
382
|
+
purgedAt: clock().toISOString(),
|
|
383
|
+
quarantineIdentity: purgedMarker,
|
|
384
|
+
diagnostic: undefined,
|
|
385
|
+
}, options);
|
|
386
|
+
}
|
|
387
|
+
finally {
|
|
388
|
+
await writableHandle?.close().catch(() => undefined);
|
|
389
|
+
await payloadHandle.close();
|
|
390
|
+
}
|
|
391
|
+
return { entry, reclaimedBytes: entry.target.measuredBytes };
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=provider-file-recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-file-recovery.js","sourceRoot":"","sources":["../../src/core/provider-file-recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ProviderFileQuarantineAction } from "../contracts/action.js";
|
|
2
|
+
import type { Diagnostic } from "../contracts/diagnostic.js";
|
|
3
|
+
import type { AgentRinseConfig } from "../config/schema.js";
|
|
4
|
+
import { type ProviderProcessResult } from "./provider-processes.js";
|
|
5
|
+
import { type ProcessOwnershipResult } from "./process-ownership.js";
|
|
6
|
+
export type ProviderFileRevalidationResult = {
|
|
7
|
+
status: "ready";
|
|
8
|
+
} | {
|
|
9
|
+
status: "stale";
|
|
10
|
+
diagnostic: Diagnostic;
|
|
11
|
+
};
|
|
12
|
+
export type ProviderFileRevalidationDependencies = {
|
|
13
|
+
clock?: () => Date;
|
|
14
|
+
authorizeTarget?: (action: ProviderFileQuarantineAction) => Promise<void>;
|
|
15
|
+
allowedHandlePids?: ReadonlySet<number>;
|
|
16
|
+
inspectProcesses?: (provider: ProviderFileQuarantineAction["adapter"]) => Promise<ProviderProcessResult>;
|
|
17
|
+
inspectOpenHandles?: (path: string) => Promise<ProcessOwnershipResult>;
|
|
18
|
+
};
|
|
19
|
+
export declare function revalidateProviderFileQuarantine(action: ProviderFileQuarantineAction, home?: string, config?: AgentRinseConfig, dependencies?: ProviderFileRevalidationDependencies): Promise<ProviderFileRevalidationResult>;
|
|
20
|
+
//# sourceMappingURL=provider-file-revalidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-file-revalidation.d.ts","sourceRoot":"","sources":["../../src/core/provider-file-revalidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EAA4B,KAAK,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC/F,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAE7F,MAAM,MAAM,8BAA8B,GACtC;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC;AAEhD,MAAM,MAAM,oCAAoC,GAAG;IACjD,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,4BAA4B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,iBAAiB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,gBAAgB,CAAC,EAAE,CACjB,QAAQ,EAAE,4BAA4B,CAAC,SAAS,CAAC,KAC9C,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACpC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACxE,CAAC;AAmBF,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,4BAA4B,EACpC,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,gBAAgB,EACzB,YAAY,GAAE,oCAAyC,GACtD,OAAO,CAAC,8BAA8B,CAAC,CA6EzC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { inspectProviderFile, providerFileIdentityMatches } from "./provider-file-identity.js";
|
|
2
|
+
import { authorizeProviderFileAction } from "./provider-file-policy.js";
|
|
3
|
+
import { inspectProviderProcesses } from "./provider-processes.js";
|
|
4
|
+
import { findProcessesUsingFile } from "./process-ownership.js";
|
|
5
|
+
function stale(action, code, message) {
|
|
6
|
+
return {
|
|
7
|
+
status: "stale",
|
|
8
|
+
diagnostic: {
|
|
9
|
+
severity: "warning",
|
|
10
|
+
code,
|
|
11
|
+
message,
|
|
12
|
+
adapter: action.adapter,
|
|
13
|
+
resourceId: action.resourceId,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function revalidateProviderFileQuarantine(action, home, config, dependencies = {}) {
|
|
18
|
+
try {
|
|
19
|
+
const authorizeTarget = dependencies.authorizeTarget ??
|
|
20
|
+
(home !== undefined && config !== undefined
|
|
21
|
+
? (selectedAction) => authorizeProviderFileAction(selectedAction, home, config, process.platform, process.env, (dependencies.clock ?? (() => new Date()))())
|
|
22
|
+
: undefined);
|
|
23
|
+
if (authorizeTarget === undefined) {
|
|
24
|
+
throw new Error("provider-file execution requires an approved provider policy");
|
|
25
|
+
}
|
|
26
|
+
await authorizeTarget(action);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return stale(action, "PROVIDER_FILE_POLICY_REFUSED", error instanceof Error ? error.message : String(error));
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const actual = await inspectProviderFile(action.target.path, action.target.ownerRoot, action.target.provider);
|
|
33
|
+
if (!providerFileIdentityMatches(actual, action.target)) {
|
|
34
|
+
return stale(action, "PROVIDER_FILE_IDENTITY_CHANGED", "provider file identity changed");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return stale(action, "PROVIDER_FILE_IDENTITY_CHANGED", error instanceof Error ? error.message : String(error));
|
|
39
|
+
}
|
|
40
|
+
const processes = await (dependencies.inspectProcesses ?? inspectProviderProcesses)(action.adapter);
|
|
41
|
+
if (processes.status !== "idle") {
|
|
42
|
+
return stale(action, processes.status === "busy" ? "PROVIDER_ACTIVE" : "PROVIDER_STATE_UNKNOWN", processes.status === "busy"
|
|
43
|
+
? `${action.adapter} is running`
|
|
44
|
+
: `${action.adapter} process state is unknown: ${processes.reason}`);
|
|
45
|
+
}
|
|
46
|
+
const handles = await (dependencies.inspectOpenHandles ?? findProcessesUsingFile)(action.target.path);
|
|
47
|
+
const externalMatches = handles.status === "busy"
|
|
48
|
+
? handles.matches.filter((match) => !dependencies.allowedHandlePids?.has(match.pid))
|
|
49
|
+
: [];
|
|
50
|
+
if (handles.status === "unknown" || externalMatches.length > 0) {
|
|
51
|
+
const message = handles.status === "unknown"
|
|
52
|
+
? `provider file descriptor state is unknown: ${handles.reason}`
|
|
53
|
+
: "a process has the provider file open";
|
|
54
|
+
return stale(action, externalMatches.length > 0
|
|
55
|
+
? "PROVIDER_FILE_DESCRIPTOR_ACTIVE"
|
|
56
|
+
: "PROVIDER_FILE_DESCRIPTOR_STATE_UNKNOWN", message);
|
|
57
|
+
}
|
|
58
|
+
return { status: "ready" };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=provider-file-revalidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-file-revalidation.js","sourceRoot":"","sources":["../../src/core/provider-file-revalidation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ProviderMutationId } from "../contracts/action.js";
|
|
2
|
+
export type ProviderProcessResult = {
|
|
3
|
+
status: "idle";
|
|
4
|
+
pids: [];
|
|
5
|
+
} | {
|
|
6
|
+
status: "busy";
|
|
7
|
+
pids: number[];
|
|
8
|
+
} | {
|
|
9
|
+
status: "unknown";
|
|
10
|
+
pids: [];
|
|
11
|
+
reason: string;
|
|
12
|
+
};
|
|
13
|
+
export type ProviderProcessOptions = {
|
|
14
|
+
runPs?: () => Promise<string>;
|
|
15
|
+
};
|
|
16
|
+
export declare function providerProcessListArguments(): string[];
|
|
17
|
+
export declare function inspectProviderProcesses(provider: ProviderMutationId, options?: ProviderProcessOptions): Promise<ProviderProcessResult>;
|
|
18
|
+
//# sourceMappingURL=provider-processes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-processes.d.ts","sourceRoot":"","sources":["../../src/core/provider-processes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAIjE,MAAM,MAAM,qBAAqB,GAC7B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,EAAE,CAAA;CAAE,GAC5B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAClC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/B,CAAC;AAiCF,wBAAgB,4BAA4B,IAAI,MAAM,EAAE,CAEvD;AAcD,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CA0ChC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
const COMMAND_PATTERNS = {
|
|
5
|
+
claude: [
|
|
6
|
+
/(?:^|\s)(?:\S*[/\\])?claude(?:\.exe)?(?:\s|$)/iu,
|
|
7
|
+
/(?:^|\s)(?:\S*[/\\])?claude-code(?:\.exe)?(?:\s|$)/iu,
|
|
8
|
+
/@anthropic-ai[/\\]claude-code/iu,
|
|
9
|
+
/Claude\.app[/\\]Contents[/\\]MacOS[/\\]Claude/iu,
|
|
10
|
+
],
|
|
11
|
+
cursor: [
|
|
12
|
+
/(?:^|\s)(?:\S*[/\\])?cursor(?:\.exe)?(?:\s|$)/iu,
|
|
13
|
+
/cursor-agent/iu,
|
|
14
|
+
/Cursor\.app[/\\]Contents[/\\]MacOS[/\\]Cursor/iu,
|
|
15
|
+
/Cursor Helper/iu,
|
|
16
|
+
],
|
|
17
|
+
copilot: [
|
|
18
|
+
/(?:^|\s)(?:\S*[/\\])?copilot(?:\.exe)?(?:\s|$)/iu,
|
|
19
|
+
/@github[/\\]copilot/iu,
|
|
20
|
+
/github-copilot/iu,
|
|
21
|
+
],
|
|
22
|
+
zed: [
|
|
23
|
+
/(?:^|\s)(?:\S*[/\\])?zed(?:\.exe)?(?:\s|$)/iu,
|
|
24
|
+
/zed-editor/iu,
|
|
25
|
+
/Zed\.app[/\\]Contents[/\\]MacOS[/\\]zed/iu,
|
|
26
|
+
],
|
|
27
|
+
opencode: [/(?:^|\s)(?:\S*[/\\])?opencode(?:\.exe)?(?:\s|$)/iu],
|
|
28
|
+
grok: [/(?:^|\s)(?:\S*[/\\])?grok(?:\.exe)?(?:\s|$)/iu, /grok-build/iu],
|
|
29
|
+
};
|
|
30
|
+
function commandMatches(provider, commandLine) {
|
|
31
|
+
return COMMAND_PATTERNS[provider].some((pattern) => pattern.test(commandLine));
|
|
32
|
+
}
|
|
33
|
+
export function providerProcessListArguments() {
|
|
34
|
+
return ["-ww", "-axo", "pid=,args="];
|
|
35
|
+
}
|
|
36
|
+
async function defaultPs() {
|
|
37
|
+
const result = await execFileAsync("ps", providerProcessListArguments(), {
|
|
38
|
+
encoding: "utf8",
|
|
39
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
40
|
+
timeout: 10_000,
|
|
41
|
+
});
|
|
42
|
+
if (result.stderr !== "") {
|
|
43
|
+
throw new Error(`ps reported incomplete process data: ${result.stderr.trim()}`);
|
|
44
|
+
}
|
|
45
|
+
return result.stdout;
|
|
46
|
+
}
|
|
47
|
+
export async function inspectProviderProcesses(provider, options = {}) {
|
|
48
|
+
try {
|
|
49
|
+
const output = await (options.runPs ?? defaultPs)();
|
|
50
|
+
const pids = [];
|
|
51
|
+
let observed = 0;
|
|
52
|
+
let incomplete = false;
|
|
53
|
+
for (const line of output.split("\n")) {
|
|
54
|
+
if (line.trim() === "") {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const match = /^\s*(\d+)\s+(.+?)\s*$/u.exec(line);
|
|
58
|
+
if (match === null) {
|
|
59
|
+
incomplete = true;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
observed += 1;
|
|
63
|
+
const pid = Number.parseInt(match[1], 10);
|
|
64
|
+
if (pid !== process.pid && commandMatches(provider, match[2])) {
|
|
65
|
+
pids.push(pid);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (pids.length > 0) {
|
|
69
|
+
return { status: "busy", pids };
|
|
70
|
+
}
|
|
71
|
+
if (observed === 0 || incomplete) {
|
|
72
|
+
return {
|
|
73
|
+
status: "unknown",
|
|
74
|
+
pids: [],
|
|
75
|
+
reason: observed === 0
|
|
76
|
+
? "ps returned no process records"
|
|
77
|
+
: "ps returned an unparseable process record",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return { status: "idle", pids: [] };
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return {
|
|
84
|
+
status: "unknown",
|
|
85
|
+
pids: [],
|
|
86
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=provider-processes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-processes.js","sourceRoot":"","sources":["../../src/core/provider-processes.ts"],"names":[],"mappings":"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"}
|