@hraness/kb 0.17.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/DISCLOSURE +43 -0
- package/LICENSE +21 -0
- package/README.md +545 -0
- package/dist/agent-context.js +35 -0
- package/dist/agent-guide-audit.js +18 -0
- package/dist/attachments.js +19 -0
- package/dist/authoring.js +33 -0
- package/dist/benchmark.js +19 -0
- package/dist/capture.js +49 -0
- package/dist/cli.js +3646 -0
- package/dist/clip/acquire.js +57 -0
- package/dist/clip/args.js +21 -0
- package/dist/clip/bounded-byte-buffer.js +9 -0
- package/dist/clip/browser-profiles.js +17 -0
- package/dist/clip/bundle-reader.js +11 -0
- package/dist/clip/cli.js +27 -0
- package/dist/clip/cookies.js +21 -0
- package/dist/clip/defuddle-worker.js +84 -0
- package/dist/clip/doctor.js +32 -0
- package/dist/clip/jobs.js +784 -0
- package/dist/clip/network-proxy.js +9 -0
- package/dist/clip/network.js +28 -0
- package/dist/clip/persist.js +30 -0
- package/dist/clip/refresh.js +11 -0
- package/dist/clip/terminal.js +11 -0
- package/dist/evaluation-builder.js +12238 -0
- package/dist/evaluation-kb.js +26 -0
- package/dist/evaluation.js +35 -0
- package/dist/git.js +39 -0
- package/dist/graph.js +39 -0
- package/dist/index-01jj6rbv.js +1103 -0
- package/dist/index-06c9ctr6.js +738 -0
- package/dist/index-0kavxzqj.js +2480 -0
- package/dist/index-1gwbassd.js +743 -0
- package/dist/index-1n418kb9.js +827 -0
- package/dist/index-1vrd1rmn.js +56 -0
- package/dist/index-1xxnjn0d.js +171 -0
- package/dist/index-3rm7cz6h.js +373 -0
- package/dist/index-3v2z4f0q.js +328 -0
- package/dist/index-48pz4jpc.js +392 -0
- package/dist/index-4j3tt0c3.js +234 -0
- package/dist/index-5n05se68.js +307 -0
- package/dist/index-5vwpzb5a.js +764 -0
- package/dist/index-6g2pv9d2.js +370 -0
- package/dist/index-7fzc32gf.js +712 -0
- package/dist/index-84x0vjjp.js +432 -0
- package/dist/index-adx6khj5.js +488 -0
- package/dist/index-b88v3vtm.js +805 -0
- package/dist/index-cv6fh7z5.js +462 -0
- package/dist/index-cxfrakt7.js +1067 -0
- package/dist/index-d13v9ckt.js +150 -0
- package/dist/index-dycjbhw2.js +1943 -0
- package/dist/index-dyqwejk5.js +531 -0
- package/dist/index-e5fbsywq.js +658 -0
- package/dist/index-f984hw45.js +927 -0
- package/dist/index-gh719d91.js +63 -0
- package/dist/index-hgve9rh2.js +2046 -0
- package/dist/index-hya40gb2.js +474 -0
- package/dist/index-j4zgmzjr.js +152 -0
- package/dist/index-jsmvyyvf.js +1166 -0
- package/dist/index-kh0pwvdd.js +1974 -0
- package/dist/index-mqx4nd6v.js +119 -0
- package/dist/index-mxxxytys.js +1254 -0
- package/dist/index-n5dd7r0v.js +711 -0
- package/dist/index-npg9z1a4.js +431 -0
- package/dist/index-pj501bh1.js +140 -0
- package/dist/index-qry4vhxk.js +1041 -0
- package/dist/index-s2gw5aw9.js +199 -0
- package/dist/index-vvdj6kca.js +70 -0
- package/dist/index-w2zc0vwa.js +571 -0
- package/dist/index-x3fthpsc.js +585 -0
- package/dist/index-zr53sf63.js +44 -0
- package/dist/index-zxdy5pby.js +2728 -0
- package/dist/index-zzhgcwyt.js +966 -0
- package/dist/index.js +453 -0
- package/dist/navigation.js +13 -0
- package/dist/pdf.js +85 -0
- package/dist/percolate.js +24 -0
- package/dist/portfolio.js +77 -0
- package/dist/query.js +29 -0
- package/dist/repository-memory.js +60 -0
- package/dist/sdk.js +36 -0
- package/dist/search-rules.js +34 -0
- package/dist/search.js +22 -0
- package/dist/semantic.js +39 -0
- package/dist/source-inbox.js +17 -0
- package/dist/untrusted-content.js +32 -0
- package/dist/url-intelligence.js +74 -0
- package/dist/workflow.js +23 -0
- package/dist/workflows/decision-context.js +20 -0
- package/dist/workflows/explain-change.js +8 -0
- package/dist/workflows/index.js +28 -0
- package/dist/workflows/plan-radar.js +10 -0
- package/package.json +409 -0
- package/skills/kb/AGENTS.md +19 -0
- package/skills/kb/SKILL.md +82 -0
- package/skills/kb/agents/openai.yaml +4 -0
- package/skills/kb/references/pdf-review.md +51 -0
- package/skills/kb/references/percolate.md +144 -0
- package/skills/kb/references/plan-structure.md +105 -0
- package/skills/kb/references/plan.md +115 -0
- package/skills/kb/references/query.md +231 -0
- package/skills/kb/references/refresh.md +133 -0
- package/skills/kb/references/save-pdf.md +125 -0
- package/skills/kb/references/save-url.md +178 -0
- package/skills/kb/references/url-authentication.md +75 -0
- package/skills/kb/references/url-platforms.md +25 -0
- package/src/agent-context.ts +1241 -0
- package/src/agent-guide-audit.ts +750 -0
- package/src/attachments.ts +723 -0
- package/src/authoring.ts +1725 -0
- package/src/benchmark.ts +362 -0
- package/src/capture.ts +68 -0
- package/src/cli.ts +3660 -0
- package/src/clip/acquire.ts +1273 -0
- package/src/clip/archive-today.ts +402 -0
- package/src/clip/args.ts +423 -0
- package/src/clip/assets.ts +262 -0
- package/src/clip/bounded-byte-buffer.ts +75 -0
- package/src/clip/browser-profiles.ts +372 -0
- package/src/clip/bundle-reader.ts +608 -0
- package/src/clip/capture.ts +1054 -0
- package/src/clip/cli.ts +181 -0
- package/src/clip/cookies.ts +512 -0
- package/src/clip/doctor.ts +1110 -0
- package/src/clip/extract.ts +868 -0
- package/src/clip/jobs.ts +959 -0
- package/src/clip/lib.ts +861 -0
- package/src/clip/media.ts +1474 -0
- package/src/clip/metadata-search-tool/Cargo.lock +2498 -0
- package/src/clip/metadata-search-tool/Cargo.toml +18 -0
- package/src/clip/metadata-search-tool/runner.ts +685 -0
- package/src/clip/metadata-search-tool/src/main.rs +389 -0
- package/src/clip/metadata-search.ts +687 -0
- package/src/clip/network-proxy.ts +627 -0
- package/src/clip/network.ts +950 -0
- package/src/clip/package-root.ts +54 -0
- package/src/clip/persist.ts +1472 -0
- package/src/clip/platforms.ts +1824 -0
- package/src/clip/refresh.ts +197 -0
- package/src/clip/structured.ts +432 -0
- package/src/clip/terminal.ts +197 -0
- package/src/clip/url-intelligence.ts +581 -0
- package/src/clip/url-metadata-backfill.ts +616 -0
- package/src/clip/url-metadata-cli.ts +251 -0
- package/src/clip/url-metadata.ts +1397 -0
- package/src/evaluation-analysis-v2.ts +1440 -0
- package/src/evaluation-builder.ts +2539 -0
- package/src/evaluation-corpus-authoring.ts +2052 -0
- package/src/evaluation-evidence.ts +1147 -0
- package/src/evaluation-execution-v2.ts +426 -0
- package/src/evaluation-implementation.ts +131 -0
- package/src/evaluation-kb-closure.ts +1430 -0
- package/src/evaluation-kb-runner-v2.ts +735 -0
- package/src/evaluation-kb-v2.ts +2567 -0
- package/src/evaluation-kb.ts +1018 -0
- package/src/evaluation-measurement-v2.ts +1462 -0
- package/src/evaluation-packing-v2.ts +452 -0
- package/src/evaluation-redaction.ts +28 -0
- package/src/evaluation-v2.ts +3857 -0
- package/src/evaluation.ts +1220 -0
- package/src/git.ts +1276 -0
- package/src/graph.ts +1487 -0
- package/src/index.ts +20 -0
- package/src/init.ts +123 -0
- package/src/navigation.ts +277 -0
- package/src/note-lock.ts +529 -0
- package/src/pdf/args.ts +202 -0
- package/src/pdf/capture.ts +298 -0
- package/src/pdf/cli.ts +159 -0
- package/src/pdf/extract.ts +303 -0
- package/src/pdf/layout.ts +618 -0
- package/src/pdf/markdown.ts +154 -0
- package/src/pdf/model.ts +234 -0
- package/src/pdf/ocr.ts +190 -0
- package/src/pdf/persist.ts +314 -0
- package/src/pdf/source.ts +135 -0
- package/src/pdf/tools.ts +146 -0
- package/src/pdf.ts +92 -0
- package/src/percolate.ts +877 -0
- package/src/portfolio-audit.ts +574 -0
- package/src/portfolio-identity.ts +162 -0
- package/src/portfolio-registry.ts +473 -0
- package/src/portfolio.ts +765 -0
- package/src/query.ts +646 -0
- package/src/repository-memory.ts +1150 -0
- package/src/sdk.ts +1452 -0
- package/src/search-rules.ts +712 -0
- package/src/search.ts +710 -0
- package/src/semantic-runtime.ts +1139 -0
- package/src/semantic.ts +2480 -0
- package/src/source-inbox.ts +232 -0
- package/src/untrusted-content.ts +401 -0
- package/src/url-intelligence.ts +104 -0
- package/src/vault.ts +636 -0
- package/src/workflow.ts +653 -0
- package/src/workflows/decision-context.ts +81 -0
- package/src/workflows/explain-change.ts +73 -0
- package/src/workflows/index.ts +3 -0
- package/src/workflows/plan-radar.ts +101 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/clip/browser-profiles.ts
|
|
3
|
+
import {
|
|
4
|
+
chmodSync,
|
|
5
|
+
closeSync,
|
|
6
|
+
constants,
|
|
7
|
+
existsSync,
|
|
8
|
+
fstatSync,
|
|
9
|
+
fsyncSync,
|
|
10
|
+
lstatSync,
|
|
11
|
+
mkdirSync,
|
|
12
|
+
openSync,
|
|
13
|
+
readdirSync,
|
|
14
|
+
readSync,
|
|
15
|
+
realpathSync,
|
|
16
|
+
rmSync,
|
|
17
|
+
unlinkSync,
|
|
18
|
+
writeSync
|
|
19
|
+
} from "fs";
|
|
20
|
+
import { homedir } from "os";
|
|
21
|
+
import { basename, dirname, isAbsolute, join, resolve, sep } from "path";
|
|
22
|
+
var profileSkipNames = new Set([
|
|
23
|
+
"Cache",
|
|
24
|
+
"Code Cache",
|
|
25
|
+
"GPUCache",
|
|
26
|
+
"GrShaderCache",
|
|
27
|
+
"GraphiteDawnCache",
|
|
28
|
+
"ShaderCache",
|
|
29
|
+
"DawnGraphiteCache",
|
|
30
|
+
"DawnWebGPUCache",
|
|
31
|
+
"Crashpad"
|
|
32
|
+
]);
|
|
33
|
+
var maxProfileEntries = 1e5;
|
|
34
|
+
var maxProfileBytes = 5 * 1024 * 1024 * 1024;
|
|
35
|
+
var maxLocalStateBytes = 16 * 1024 * 1024;
|
|
36
|
+
|
|
37
|
+
class BrowserProfileSnapshotError extends Error {
|
|
38
|
+
constructor(message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = "BrowserProfileSnapshotError";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function isSafeNamedProfile(value) {
|
|
44
|
+
if (value.length < 1 || value.length > 256 || value.trim() !== value || value.startsWith("-") || value === "." || value === "..")
|
|
45
|
+
return false;
|
|
46
|
+
for (let index = 0;index < value.length; index += 1) {
|
|
47
|
+
const code = value.charCodeAt(index);
|
|
48
|
+
if (code <= 31 || code >= 127 && code <= 159 || code === 1564 || code === 8206 || code === 8207 || code >= 8232 && code <= 8238 || code >= 8294 && code <= 8297)
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return !value.includes("/") && !value.includes("\\");
|
|
52
|
+
}
|
|
53
|
+
function profilePath(value) {
|
|
54
|
+
const pathLike = isAbsolute(value) || value.startsWith(`.${sep}`) || value.startsWith(`..${sep}`) || value.startsWith(`~${sep}`) || value.includes("/") || value.includes("\\");
|
|
55
|
+
if (!pathLike && !isSafeNamedProfile(value))
|
|
56
|
+
throw new Error("browser profile name is unsafe");
|
|
57
|
+
if (!pathLike)
|
|
58
|
+
return null;
|
|
59
|
+
try {
|
|
60
|
+
const expanded = value.startsWith(`~${sep}`) ? join(homedir(), value.slice(2)) : resolve(value);
|
|
61
|
+
const entry = lstatSync(expanded);
|
|
62
|
+
if (entry.isSymbolicLink() || !entry.isDirectory()) {
|
|
63
|
+
throw new BrowserProfileSnapshotError("browser profile path must be a real directory");
|
|
64
|
+
}
|
|
65
|
+
return realpathSync(expanded);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error instanceof BrowserProfileSnapshotError)
|
|
68
|
+
throw error;
|
|
69
|
+
throw new BrowserProfileSnapshotError("browser profile path is unavailable or unsafe");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function sameEntry(left, right) {
|
|
73
|
+
return left.dev === right.dev && left.ino === right.ino;
|
|
74
|
+
}
|
|
75
|
+
function copyProfileFile(sourcePath, destinationPath, observed, budget) {
|
|
76
|
+
const noFollow = "O_NOFOLLOW" in constants ? constants.O_NOFOLLOW : 0;
|
|
77
|
+
const nonBlock = "O_NONBLOCK" in constants ? constants.O_NONBLOCK : 0;
|
|
78
|
+
let input = null;
|
|
79
|
+
let output = null;
|
|
80
|
+
let completed = false;
|
|
81
|
+
try {
|
|
82
|
+
input = openSync(sourcePath, constants.O_RDONLY | noFollow | nonBlock);
|
|
83
|
+
const opened = fstatSync(input);
|
|
84
|
+
if (!opened.isFile() || !sameEntry(observed, opened)) {
|
|
85
|
+
throw new BrowserProfileSnapshotError("browser profile entry changed before it could be copied");
|
|
86
|
+
}
|
|
87
|
+
if (opened.size > maxProfileBytes - budget.bytes) {
|
|
88
|
+
throw new BrowserProfileSnapshotError("browser profile clone exceeded its safety bounds");
|
|
89
|
+
}
|
|
90
|
+
output = openSync(destinationPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollow, 384);
|
|
91
|
+
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
92
|
+
let copied = 0;
|
|
93
|
+
for (;; ) {
|
|
94
|
+
const count = readSync(input, buffer, 0, buffer.byteLength, null);
|
|
95
|
+
if (count === 0)
|
|
96
|
+
break;
|
|
97
|
+
if (count > maxProfileBytes - budget.bytes - copied) {
|
|
98
|
+
throw new BrowserProfileSnapshotError("browser profile clone exceeded its safety bounds");
|
|
99
|
+
}
|
|
100
|
+
let offset = 0;
|
|
101
|
+
while (offset < count) {
|
|
102
|
+
const written = writeSync(output, buffer, offset, count - offset);
|
|
103
|
+
if (written < 1)
|
|
104
|
+
throw new BrowserProfileSnapshotError("browser profile file copy made no progress");
|
|
105
|
+
offset += written;
|
|
106
|
+
}
|
|
107
|
+
copied += count;
|
|
108
|
+
}
|
|
109
|
+
const after = fstatSync(input);
|
|
110
|
+
if (!sameEntry(observed, after) || after.size !== observed.size || copied !== observed.size || after.mtimeMs !== observed.mtimeMs)
|
|
111
|
+
throw new BrowserProfileSnapshotError("browser profile entry changed while it was copied");
|
|
112
|
+
fsyncSync(output);
|
|
113
|
+
budget.bytes += copied;
|
|
114
|
+
completed = true;
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (error instanceof BrowserProfileSnapshotError)
|
|
117
|
+
throw error;
|
|
118
|
+
throw new BrowserProfileSnapshotError("browser profile file could not be copied");
|
|
119
|
+
} finally {
|
|
120
|
+
if (output !== null)
|
|
121
|
+
closeSync(output);
|
|
122
|
+
if (input !== null)
|
|
123
|
+
closeSync(input);
|
|
124
|
+
if (!completed) {
|
|
125
|
+
try {
|
|
126
|
+
unlinkSync(destinationPath);
|
|
127
|
+
} catch {}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function copyProfileEntry(sourcePath, destinationPath, budget, root = false) {
|
|
132
|
+
const name = basename(sourcePath);
|
|
133
|
+
if (!root && (name.startsWith("Singleton") || name === "DevToolsActivePort" || profileSkipNames.has(name)))
|
|
134
|
+
return;
|
|
135
|
+
const observed = lstatSync(sourcePath);
|
|
136
|
+
if (observed.isSymbolicLink()) {
|
|
137
|
+
if (root)
|
|
138
|
+
throw new BrowserProfileSnapshotError("browser profile path must be a real directory");
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!observed.isFile() && !observed.isDirectory()) {
|
|
142
|
+
throw new BrowserProfileSnapshotError("browser profile contains an unsupported nonregular entry");
|
|
143
|
+
}
|
|
144
|
+
if (root && !observed.isDirectory()) {
|
|
145
|
+
throw new BrowserProfileSnapshotError("browser profile path must be a real directory");
|
|
146
|
+
}
|
|
147
|
+
budget.entries += 1;
|
|
148
|
+
if (budget.entries > maxProfileEntries) {
|
|
149
|
+
throw new BrowserProfileSnapshotError("browser profile clone exceeded its safety bounds");
|
|
150
|
+
}
|
|
151
|
+
if (observed.isFile()) {
|
|
152
|
+
copyProfileFile(sourcePath, destinationPath, observed, budget);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
mkdirSync(destinationPath, { mode: 448 });
|
|
156
|
+
chmodSync(destinationPath, 448);
|
|
157
|
+
for (const child of readdirSync(sourcePath).sort()) {
|
|
158
|
+
copyProfileEntry(join(sourcePath, child), join(destinationPath, child), budget);
|
|
159
|
+
}
|
|
160
|
+
const after = lstatSync(sourcePath);
|
|
161
|
+
if (!after.isDirectory() || after.isSymbolicLink() || !sameEntry(observed, after) || after.size !== observed.size || after.mtimeMs !== observed.mtimeMs || after.ctimeMs !== observed.ctimeMs)
|
|
162
|
+
throw new BrowserProfileSnapshotError("browser profile directory changed while it was copied");
|
|
163
|
+
}
|
|
164
|
+
function cloneProfile(source, destination) {
|
|
165
|
+
if (existsSync(destination))
|
|
166
|
+
throw new BrowserProfileSnapshotError("browser profile destination already exists");
|
|
167
|
+
try {
|
|
168
|
+
copyProfileEntry(source, destination, { entries: 0, bytes: 0 }, true);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
rmSync(destination, { recursive: true, force: true });
|
|
171
|
+
if (error instanceof BrowserProfileSnapshotError)
|
|
172
|
+
throw error;
|
|
173
|
+
throw new BrowserProfileSnapshotError("browser profile snapshot failed");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function missingFile(error) {
|
|
177
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
178
|
+
}
|
|
179
|
+
function localStateEntry(path) {
|
|
180
|
+
try {
|
|
181
|
+
return lstatSync(path);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (missingFile(error))
|
|
184
|
+
return null;
|
|
185
|
+
throw new BrowserProfileSnapshotError("Chromium Local State is unavailable or unsafe");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function assertChromiumUserDataIdle(userDataRoot) {
|
|
189
|
+
let names;
|
|
190
|
+
try {
|
|
191
|
+
names = readdirSync(userDataRoot);
|
|
192
|
+
} catch {
|
|
193
|
+
throw new BrowserProfileSnapshotError("Chromium user-data root could not be inspected");
|
|
194
|
+
}
|
|
195
|
+
if (names.some((name) => name.startsWith("Singleton") || name === "DevToolsActivePort")) {
|
|
196
|
+
throw new BrowserProfileSnapshotError("Chromium profile is active or retains a stale process lock; fully quit the browser and retry");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function copyBoundedLocalState(source, destination) {
|
|
200
|
+
const entry = localStateEntry(source);
|
|
201
|
+
if (entry === null || entry.isSymbolicLink() || !entry.isFile()) {
|
|
202
|
+
throw new BrowserProfileSnapshotError("Chromium Local State must be one regular file");
|
|
203
|
+
}
|
|
204
|
+
if (entry.size > maxLocalStateBytes) {
|
|
205
|
+
throw new BrowserProfileSnapshotError("Chromium Local State exceeds its safety bound");
|
|
206
|
+
}
|
|
207
|
+
const noFollow = "O_NOFOLLOW" in constants ? constants.O_NOFOLLOW : 0;
|
|
208
|
+
let input = null;
|
|
209
|
+
let output = null;
|
|
210
|
+
let outputCreated = false;
|
|
211
|
+
let completed = false;
|
|
212
|
+
try {
|
|
213
|
+
input = openSync(source, constants.O_RDONLY | noFollow);
|
|
214
|
+
const opened = fstatSync(input);
|
|
215
|
+
if (!opened.isFile() || !sameEntry(entry, opened) || opened.size !== entry.size || opened.size > maxLocalStateBytes)
|
|
216
|
+
throw new BrowserProfileSnapshotError("Chromium Local State changed before it could be copied");
|
|
217
|
+
output = openSync(destination, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 384);
|
|
218
|
+
outputCreated = true;
|
|
219
|
+
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
220
|
+
let copied = 0;
|
|
221
|
+
for (;; ) {
|
|
222
|
+
const count = readSync(input, buffer, 0, Math.min(buffer.length, maxLocalStateBytes + 1 - copied), null);
|
|
223
|
+
if (count === 0)
|
|
224
|
+
break;
|
|
225
|
+
copied += count;
|
|
226
|
+
if (copied > maxLocalStateBytes) {
|
|
227
|
+
throw new BrowserProfileSnapshotError("Chromium Local State exceeds its safety bound");
|
|
228
|
+
}
|
|
229
|
+
let offset = 0;
|
|
230
|
+
while (offset < count) {
|
|
231
|
+
const written = writeSync(output, buffer, offset, count - offset);
|
|
232
|
+
if (written < 1)
|
|
233
|
+
throw new BrowserProfileSnapshotError("Chromium Local State copy made no progress");
|
|
234
|
+
offset += written;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
const after = fstatSync(input);
|
|
238
|
+
if (copied !== entry.size || !sameEntry(entry, after) || after.size !== entry.size || after.mtimeMs !== entry.mtimeMs)
|
|
239
|
+
throw new BrowserProfileSnapshotError("Chromium Local State changed while it was copied");
|
|
240
|
+
fsyncSync(output);
|
|
241
|
+
completed = true;
|
|
242
|
+
} catch (error) {
|
|
243
|
+
if (error instanceof BrowserProfileSnapshotError)
|
|
244
|
+
throw error;
|
|
245
|
+
throw new BrowserProfileSnapshotError("Chromium Local State could not be copied");
|
|
246
|
+
} finally {
|
|
247
|
+
if (output !== null)
|
|
248
|
+
closeSync(output);
|
|
249
|
+
if (input !== null)
|
|
250
|
+
closeSync(input);
|
|
251
|
+
if (outputCreated && !completed) {
|
|
252
|
+
try {
|
|
253
|
+
unlinkSync(destination);
|
|
254
|
+
} catch {}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function cloneBrowserProfile(source, privateDirectory) {
|
|
259
|
+
let selectedSource = source;
|
|
260
|
+
let userDataRoot = dirname(source);
|
|
261
|
+
let localState = join(userDataRoot, "Local State");
|
|
262
|
+
let stateEntry = localStateEntry(localState);
|
|
263
|
+
if (stateEntry === null) {
|
|
264
|
+
const rootLocalState = join(source, "Local State");
|
|
265
|
+
const rootStateEntry = localStateEntry(rootLocalState);
|
|
266
|
+
if (rootStateEntry === null) {
|
|
267
|
+
const destination = join(privateDirectory, "profile");
|
|
268
|
+
cloneProfile(source, destination);
|
|
269
|
+
return { userDataPath: destination };
|
|
270
|
+
}
|
|
271
|
+
const defaultProfile = join(source, "Default");
|
|
272
|
+
let defaultEntry;
|
|
273
|
+
try {
|
|
274
|
+
defaultEntry = lstatSync(defaultProfile);
|
|
275
|
+
} catch {
|
|
276
|
+
throw new BrowserProfileSnapshotError("Chromium Default profile is unavailable or unsafe");
|
|
277
|
+
}
|
|
278
|
+
if (defaultEntry.isSymbolicLink() || !defaultEntry.isDirectory()) {
|
|
279
|
+
throw new BrowserProfileSnapshotError("Chromium Default profile must be one real directory");
|
|
280
|
+
}
|
|
281
|
+
selectedSource = defaultProfile;
|
|
282
|
+
userDataRoot = source;
|
|
283
|
+
localState = rootLocalState;
|
|
284
|
+
stateEntry = rootStateEntry;
|
|
285
|
+
}
|
|
286
|
+
if (stateEntry.isSymbolicLink() || !stateEntry.isFile()) {
|
|
287
|
+
throw new BrowserProfileSnapshotError("Chromium Local State must be one regular file");
|
|
288
|
+
}
|
|
289
|
+
if (stateEntry.size > maxLocalStateBytes) {
|
|
290
|
+
throw new BrowserProfileSnapshotError("Chromium Local State exceeds its safety bound");
|
|
291
|
+
}
|
|
292
|
+
assertChromiumUserDataIdle(userDataRoot);
|
|
293
|
+
const userData = join(privateDirectory, "profile-user-data");
|
|
294
|
+
mkdirSync(userData, { mode: 448 });
|
|
295
|
+
chmodSync(userData, 448);
|
|
296
|
+
const selectedProfile = join(userData, "Default");
|
|
297
|
+
try {
|
|
298
|
+
cloneProfile(selectedSource, selectedProfile);
|
|
299
|
+
copyBoundedLocalState(localState, join(userData, "Local State"));
|
|
300
|
+
return { userDataPath: userData, profileDirectory: "Default" };
|
|
301
|
+
} catch (error) {
|
|
302
|
+
rmSync(userData, { recursive: true, force: true });
|
|
303
|
+
throw error;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export { BrowserProfileSnapshotError, isSafeNamedProfile, profilePath, cloneProfile, copyBoundedLocalState, cloneBrowserProfile };
|