@pify/swarm 0.9.0 → 0.9.1
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/extensions/swarm.ts +2 -3
- package/package.json +1 -1
- package/src/consent.ts +26 -0
package/extensions/swarm.ts
CHANGED
|
@@ -32,8 +32,8 @@ import {
|
|
|
32
32
|
decideConsent,
|
|
33
33
|
envConsent,
|
|
34
34
|
parseConsent,
|
|
35
|
+
persistConsent,
|
|
35
36
|
readConsent,
|
|
36
|
-
writeConsent,
|
|
37
37
|
} from "../src/consent.ts";
|
|
38
38
|
import { LiveChildren, cancelNote, type CancelReason } from "../src/cancel.ts";
|
|
39
39
|
import { DELIVERY_TYPE, deliveryMessage, pendingResult } from "../src/pending.ts";
|
|
@@ -630,8 +630,7 @@ export default function swarm(pi: ExtensionAPI) {
|
|
|
630
630
|
),
|
|
631
631
|
);
|
|
632
632
|
try {
|
|
633
|
-
|
|
634
|
-
`);
|
|
633
|
+
persistConsent(file, ctx.cwd, "agents", approved);
|
|
635
634
|
} catch {
|
|
636
635
|
// An unwritable consent file costs us the memory of the answer, not the answer.
|
|
637
636
|
}
|
package/package.json
CHANGED
package/src/consent.ts
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
* around the first.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
20
|
+
|
|
19
21
|
/** What to do with a project-supplied file this session. */
|
|
20
22
|
export type ConsentVerdict = "allow" | "refuse" | "ask";
|
|
21
23
|
|
|
@@ -80,6 +82,30 @@ export function writeConsent(
|
|
|
80
82
|
return { ...file, [key]: { ...(file[key] ?? {}), [scope]: allowed } };
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Record a consent answer to disk without losing a concurrent writer's scope.
|
|
87
|
+
*
|
|
88
|
+
* Several @pify packages share this one file (keyed by cwd → {scope: bool}), and
|
|
89
|
+
* each asks the user with an `await` between reading the file and writing it
|
|
90
|
+
* back. If two flows both read the old file, then both write, the second write
|
|
91
|
+
* drops the scope the first added. So re-read and re-parse the file HERE, right
|
|
92
|
+
* before writing, with no `await` in between — the merge always starts from the
|
|
93
|
+
* freshest on-disk state, and within a single (single-threaded) process the
|
|
94
|
+
* read-modify-write can no longer interleave. Cross-process races remain
|
|
95
|
+
* theoretically possible but fail safe: the worst case is a re-prompt, never a
|
|
96
|
+
* silently-granted consent.
|
|
97
|
+
*/
|
|
98
|
+
export function persistConsent(file: string, cwd: string, scope: string, allowed: boolean): void {
|
|
99
|
+
let raw: string | null = null;
|
|
100
|
+
try {
|
|
101
|
+
raw = readFileSync(file, "utf8");
|
|
102
|
+
} catch {
|
|
103
|
+
raw = null;
|
|
104
|
+
}
|
|
105
|
+
const next = writeConsent(parseConsent(raw), cwd, scope, allowed);
|
|
106
|
+
writeFileSync(file, `${JSON.stringify(next, null, 2)}\n`);
|
|
107
|
+
}
|
|
108
|
+
|
|
83
109
|
/** Tolerate anything on disk: a corrupt consent file means "never asked". */
|
|
84
110
|
export function parseConsent(raw: string | null): ConsentFile {
|
|
85
111
|
if (!raw) return {};
|