humanish 0.15.0 → 0.15.2
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 +33 -31
- package/dist/claude-agent-sdk.js +14 -7
- package/dist/claude-agent-sdk.js.map +1 -1
- package/dist/codex-app-server-ui.d.ts +1 -1
- package/dist/codex-app-server-ui.js +69 -39
- package/dist/codex-app-server-ui.js.map +1 -1
- package/dist/codex-app-server.d.ts +3 -0
- package/dist/codex-app-server.js +15 -8
- package/dist/codex-app-server.js.map +1 -1
- package/dist/concurrent-shared-world-lab.js +18 -16
- package/dist/concurrent-shared-world-lab.js.map +1 -1
- package/dist/core/git-state.d.ts +2 -0
- package/dist/core/git-state.js +152 -17
- package/dist/core/git-state.js.map +1 -1
- package/dist/core/git-workspace.d.ts +31 -0
- package/dist/core/git-workspace.js +447 -0
- package/dist/core/git-workspace.js.map +1 -0
- package/dist/cua-actor-lab.d.ts +3 -2
- package/dist/cua-actor-lab.js +34 -23
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/e2b-terminal-lab.js +111 -46
- package/dist/e2b-terminal-lab.js.map +1 -1
- package/dist/feedback.js +139 -101
- package/dist/feedback.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +108 -22
- package/dist/init.js.map +1 -1
- package/dist/lab-config.d.ts +5 -0
- package/dist/lab-config.js +38 -0
- package/dist/lab-config.js.map +1 -1
- package/dist/labs.js +258 -52
- package/dist/labs.js.map +1 -1
- package/dist/observer-assets.js +3 -2
- package/dist/observer-assets.js.map +1 -1
- package/dist/observer-static.js +131 -17
- package/dist/observer-static.js.map +1 -1
- package/dist/observer.js +263 -66
- package/dist/observer.js.map +1 -1
- package/dist/openai-responses-cu.js +18 -4
- package/dist/openai-responses-cu.js.map +1 -1
- package/dist/oss-lab.js +59 -14
- package/dist/oss-lab.js.map +1 -1
- package/dist/oss-meta-lab.d.ts +2 -4
- package/dist/oss-meta-lab.js +117 -477
- package/dist/oss-meta-lab.js.map +1 -1
- package/dist/program.js +23 -21
- package/dist/program.js.map +1 -1
- package/dist/run-paths.d.ts +56 -0
- package/dist/run-paths.js +340 -0
- package/dist/run-paths.js.map +1 -0
- package/dist/run.d.ts +14 -4
- package/dist/run.js +595 -306
- package/dist/run.js.map +1 -1
- package/dist/scripted-browser-actor.d.ts +7 -4
- package/dist/scripted-browser-actor.js +154 -41
- package/dist/scripted-browser-actor.js.map +1 -1
- package/dist/scripted-browser-lab.js +95 -45
- package/dist/scripted-browser-lab.js.map +1 -1
- package/dist/selected-output-paths.d.ts +49 -0
- package/dist/selected-output-paths.js +354 -0
- package/dist/selected-output-paths.js.map +1 -0
- package/dist/shared-world-lab.js +13 -12
- package/dist/shared-world-lab.js.map +1 -1
- package/dist/source-archive.js +44 -1
- package/dist/source-archive.js.map +1 -1
- package/docs/architecture/oss-lab-poc.md +8 -0
- package/docs/assets/humanish-observer-hero.png +0 -0
- package/docs/contracts/policy.md +7 -1
- package/docs/goals/current.md +20 -1
- package/docs/product/open-source-install-experience.md +9 -1
- package/docs/ramp/README.md +14 -7
- package/package.json +1 -1
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { lstat, open, readdir, realpath } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export const GIT_METADATA_INSPECTION_FAILED_NOTE = "Git metadata could not be inspected safely.";
|
|
5
|
+
export const GIT_METADATA_CONTAINMENT_FAILED_NOTE = "Git metadata failed containment validation.";
|
|
6
|
+
/**
|
|
7
|
+
* Resolve one physical Git worktree without trusting ambient Git discovery.
|
|
8
|
+
*
|
|
9
|
+
* A regular `.git` file is accepted only for Git's exact linked-worktree
|
|
10
|
+
* topology: `<common>/.git/worktrees/<name>` plus single-link `commondir` and
|
|
11
|
+
* `gitdir` backpointer files. Arbitrary `gitdir:` redirects (including valid
|
|
12
|
+
* separate-git-dir repositories) are deliberately unavailable because they
|
|
13
|
+
* delegate metadata authority outside the selected project without a
|
|
14
|
+
* verifiable backlink.
|
|
15
|
+
*/
|
|
16
|
+
export async function inspectVerifiedGitWorkspace(cwdInput) {
|
|
17
|
+
let current;
|
|
18
|
+
try {
|
|
19
|
+
current = await realpath(path.resolve(cwdInput));
|
|
20
|
+
const cwdStats = await lstat(current);
|
|
21
|
+
if (cwdStats.isSymbolicLink() || !cwdStats.isDirectory()) {
|
|
22
|
+
return unsafeInspection(current, GIT_METADATA_INSPECTION_FAILED_NOTE);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return unsafeInspection(path.resolve(cwdInput), GIT_METADATA_INSPECTION_FAILED_NOTE);
|
|
27
|
+
}
|
|
28
|
+
while (true) {
|
|
29
|
+
const dotGitPath = path.join(current, ".git");
|
|
30
|
+
let dotGitStats;
|
|
31
|
+
try {
|
|
32
|
+
dotGitStats = await lstat(dotGitPath, { bigint: true });
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (!isNodeError(error) || error.code !== "ENOENT") {
|
|
36
|
+
return unsafeInspection(current, GIT_METADATA_INSPECTION_FAILED_NOTE);
|
|
37
|
+
}
|
|
38
|
+
const parent = path.dirname(current);
|
|
39
|
+
if (parent === current) {
|
|
40
|
+
return { status: "missing" };
|
|
41
|
+
}
|
|
42
|
+
current = parent;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (dotGitStats.isSymbolicLink()) {
|
|
46
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
47
|
+
}
|
|
48
|
+
if (dotGitStats.isDirectory()) {
|
|
49
|
+
try {
|
|
50
|
+
if (await realpath(dotGitPath) !== dotGitPath) {
|
|
51
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
52
|
+
}
|
|
53
|
+
// A normal worktree does not need commondir. Accepting one here would
|
|
54
|
+
// let a contained `.git/` silently redirect config, refs, and objects.
|
|
55
|
+
if (await pathExists(path.join(dotGitPath, "commondir"))) {
|
|
56
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
57
|
+
}
|
|
58
|
+
const configOverrides = [];
|
|
59
|
+
const workspace = {
|
|
60
|
+
commonDir: dotGitPath,
|
|
61
|
+
configOverrides,
|
|
62
|
+
gitDir: dotGitPath,
|
|
63
|
+
kind: "directory",
|
|
64
|
+
trustRoot: current,
|
|
65
|
+
worktreeRoot: current
|
|
66
|
+
};
|
|
67
|
+
return await validateCriticalGitMetadata(workspace)
|
|
68
|
+
? { status: "verified", workspace: freezeVerifiedWorkspace(workspace, configOverrides) }
|
|
69
|
+
: unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!dotGitStats.isFile() || dotGitStats.nlink !== 1n) {
|
|
76
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const dotGit = await readSingleLinkRegularFile(dotGitPath);
|
|
80
|
+
const declaredGitDir = dotGit ? parseGitdirFile(dotGit.text) : null;
|
|
81
|
+
if (!dotGit || !declaredGitDir) {
|
|
82
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
83
|
+
}
|
|
84
|
+
const gitDir = await realpath(path.isAbsolute(declaredGitDir)
|
|
85
|
+
? declaredGitDir
|
|
86
|
+
: path.resolve(current, declaredGitDir));
|
|
87
|
+
if (!await isPhysicalDirectory(gitDir)) {
|
|
88
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
89
|
+
}
|
|
90
|
+
const commondir = await readSingleLinkRegularFile(path.join(gitDir, "commondir"));
|
|
91
|
+
const backpointer = await readSingleLinkRegularFile(path.join(gitDir, "gitdir"));
|
|
92
|
+
const declaredCommonDir = commondir ? parseSinglePathLine(commondir.text) : null;
|
|
93
|
+
const declaredBackpointer = backpointer ? parseSinglePathLine(backpointer.text) : null;
|
|
94
|
+
if (!commondir || !backpointer || !declaredCommonDir || !declaredBackpointer) {
|
|
95
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
96
|
+
}
|
|
97
|
+
const commonDir = await realpath(path.resolve(gitDir, declaredCommonDir));
|
|
98
|
+
if (!await isPhysicalDirectory(commonDir)
|
|
99
|
+
|| path.basename(commonDir) !== ".git"
|
|
100
|
+
|| path.dirname(gitDir) !== path.join(commonDir, "worktrees")
|
|
101
|
+
|| path.basename(gitDir).length === 0) {
|
|
102
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
103
|
+
}
|
|
104
|
+
const physicalBackpointer = await realpath(path.isAbsolute(declaredBackpointer)
|
|
105
|
+
? declaredBackpointer
|
|
106
|
+
: path.resolve(gitDir, declaredBackpointer));
|
|
107
|
+
if (physicalBackpointer !== dotGitPath) {
|
|
108
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
109
|
+
}
|
|
110
|
+
const trustRoot = path.dirname(commonDir);
|
|
111
|
+
if (!await isPhysicalDirectory(trustRoot)
|
|
112
|
+
|| await realpath(path.join(trustRoot, ".git")) !== commonDir
|
|
113
|
+
|| !await stillSameSingleLinkFile(dotGitPath, dotGit.identity)
|
|
114
|
+
|| !await stillSameSingleLinkFile(path.join(gitDir, "commondir"), commondir.identity)
|
|
115
|
+
|| !await stillSameSingleLinkFile(path.join(gitDir, "gitdir"), backpointer.identity)) {
|
|
116
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
117
|
+
}
|
|
118
|
+
const configOverrides = [];
|
|
119
|
+
const workspace = {
|
|
120
|
+
commonDir,
|
|
121
|
+
configOverrides,
|
|
122
|
+
gitDir,
|
|
123
|
+
kind: "linked-worktree",
|
|
124
|
+
trustRoot,
|
|
125
|
+
worktreeRoot: current
|
|
126
|
+
};
|
|
127
|
+
return await validateCriticalGitMetadata(workspace)
|
|
128
|
+
? { status: "verified", workspace: freezeVerifiedWorkspace(workspace, configOverrides) }
|
|
129
|
+
: unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return unsafeInspection(current, GIT_METADATA_CONTAINMENT_FAILED_NOTE);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function validateCriticalGitMetadata(workspace) {
|
|
137
|
+
if (!await isPhysicalDirectory(workspace.gitDir)
|
|
138
|
+
|| !await isPhysicalDirectory(workspace.commonDir)
|
|
139
|
+
|| !await isPhysicalDirectory(workspace.worktreeRoot)) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
const criticalFiles = new Set([
|
|
143
|
+
path.join(workspace.gitDir, "HEAD"),
|
|
144
|
+
path.join(workspace.gitDir, "index"),
|
|
145
|
+
path.join(workspace.gitDir, "config.worktree"),
|
|
146
|
+
path.join(workspace.commonDir, "config"),
|
|
147
|
+
path.join(workspace.commonDir, "config.worktree"),
|
|
148
|
+
path.join(workspace.commonDir, "info", "attributes"),
|
|
149
|
+
path.join(workspace.commonDir, "info", "exclude"),
|
|
150
|
+
path.join(workspace.commonDir, "packed-refs")
|
|
151
|
+
]);
|
|
152
|
+
for (const filePath of criticalFiles) {
|
|
153
|
+
if (!await isSingleLinkRegularFileOrMissing(filePath)) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Split indexes are selected by the contained index but read as sibling
|
|
158
|
+
// metadata. Do not let one redirect Git through a symlink or hardlink.
|
|
159
|
+
const gitDirEntries = await readdir(workspace.gitDir).catch(() => []);
|
|
160
|
+
for (const entry of gitDirEntries) {
|
|
161
|
+
if (/^sharedindex\.[0-9a-f]+$/i.test(entry)) {
|
|
162
|
+
if (!await isSingleLinkRegularFileOrMissing(path.join(workspace.gitDir, entry))) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
for (const directory of [
|
|
168
|
+
path.join(workspace.commonDir, "objects"),
|
|
169
|
+
path.join(workspace.commonDir, "refs")
|
|
170
|
+
]) {
|
|
171
|
+
if (!await isPhysicalDirectoryOrMissing(directory)) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const head = await readSingleLinkRegularFile(path.join(workspace.gitDir, "HEAD"), true);
|
|
176
|
+
if (head && !await validateHeadReference(workspace, head.text)) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
const alternatesPath = path.join(workspace.commonDir, "objects", "info", "alternates");
|
|
180
|
+
if (!await isSingleLinkRegularFileOrMissing(alternatesPath)) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
const alternates = await readSingleLinkRegularFile(alternatesPath, true);
|
|
184
|
+
if (alternates && !await alternatesStayInsideCommonDir(workspace.commonDir, alternates.text)) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
const overrides = await collectExecutableConfigOverrides(workspace);
|
|
188
|
+
if (!overrides) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
workspace.configOverrides.push(...overrides);
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
async function collectExecutableConfigOverrides(workspace) {
|
|
195
|
+
const filters = new Set();
|
|
196
|
+
const diffs = new Set();
|
|
197
|
+
for (const configPath of new Set([
|
|
198
|
+
path.join(workspace.commonDir, "config"),
|
|
199
|
+
path.join(workspace.gitDir, "config.worktree")
|
|
200
|
+
])) {
|
|
201
|
+
const config = await readSingleLinkRegularFile(configPath, true);
|
|
202
|
+
if (!config)
|
|
203
|
+
continue;
|
|
204
|
+
for (const line of config.text.split(/\r?\n/)) {
|
|
205
|
+
if (/^\s*\[\s*include(?:\s*\]|if\b)/i.test(line)) {
|
|
206
|
+
// Includes can introduce executable config from an unbound path after
|
|
207
|
+
// this file was inspected. Provenance capture does not need them.
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
const sectionStart = /^\s*\[\s*(filter|diff)\b/i.exec(line);
|
|
211
|
+
if (!sectionStart)
|
|
212
|
+
continue;
|
|
213
|
+
const section = /^\s*\[\s*(filter|diff)\s+(?:"((?:\\.|[^"\\])*)"|\.\s*([^\]\s]+))\s*\]\s*(?:[#;].*)?$/i.exec(line);
|
|
214
|
+
if (!section)
|
|
215
|
+
return null;
|
|
216
|
+
const rawDriver = section[2] === undefined ? section[3] : unescapeGitConfigSubsection(section[2]);
|
|
217
|
+
if (!rawDriver || !/^[A-Za-z0-9_.-]+$/.test(rawDriver))
|
|
218
|
+
return null;
|
|
219
|
+
if (section[1]?.toLowerCase() === "filter")
|
|
220
|
+
filters.add(rawDriver);
|
|
221
|
+
else
|
|
222
|
+
diffs.add(rawDriver);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const overrides = [];
|
|
226
|
+
for (const driver of [...filters].sort()) {
|
|
227
|
+
overrides.push(`filter.${driver}.clean=`, `filter.${driver}.smudge=`, `filter.${driver}.process=`, `filter.${driver}.required=false`);
|
|
228
|
+
}
|
|
229
|
+
for (const driver of [...diffs].sort()) {
|
|
230
|
+
overrides.push(`diff.${driver}.command=`, `diff.${driver}.textconv=`);
|
|
231
|
+
}
|
|
232
|
+
return overrides;
|
|
233
|
+
}
|
|
234
|
+
function unescapeGitConfigSubsection(value) {
|
|
235
|
+
let result = "";
|
|
236
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
237
|
+
const char = value[index];
|
|
238
|
+
if (char !== "\\") {
|
|
239
|
+
result += char;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const escaped = value[index + 1];
|
|
243
|
+
if (escaped !== "\\" && escaped !== "\"")
|
|
244
|
+
return null;
|
|
245
|
+
result += escaped;
|
|
246
|
+
index += 1;
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
250
|
+
function freezeVerifiedWorkspace(workspace, configOverrides) {
|
|
251
|
+
Object.freeze(configOverrides);
|
|
252
|
+
return Object.freeze(workspace);
|
|
253
|
+
}
|
|
254
|
+
async function validateHeadReference(workspace, headText) {
|
|
255
|
+
const value = headText.trim();
|
|
256
|
+
if (/^[0-9a-f]{40}(?:[0-9a-f]{24})?$/i.test(value)) {
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
if (!value.startsWith("ref: ")) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
const ref = value.slice("ref: ".length);
|
|
263
|
+
if (!isSafeGitRef(ref)) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
// Normal branch refs live under the common directory. Per-worktree refs may
|
|
267
|
+
// live under the admin directory. Validate either existing path without
|
|
268
|
+
// requiring an unborn branch to have a loose ref.
|
|
269
|
+
const candidates = [path.join(workspace.commonDir, ...ref.split("/"))];
|
|
270
|
+
if (workspace.gitDir !== workspace.commonDir) {
|
|
271
|
+
candidates.push(path.join(workspace.gitDir, ...ref.split("/")));
|
|
272
|
+
}
|
|
273
|
+
for (const candidate of candidates) {
|
|
274
|
+
if (!await validateOptionalContainedFileChain(candidate.startsWith(`${workspace.gitDir}${path.sep}`) ? workspace.gitDir : workspace.commonDir, candidate)) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
async function validateOptionalContainedFileChain(root, filePath) {
|
|
281
|
+
const relative = path.relative(root, filePath);
|
|
282
|
+
if (!relative || relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
let current = root;
|
|
286
|
+
const segments = relative.split(path.sep);
|
|
287
|
+
for (const [index, segment] of segments.entries()) {
|
|
288
|
+
current = path.join(current, segment);
|
|
289
|
+
let stats;
|
|
290
|
+
try {
|
|
291
|
+
stats = await lstat(current, { bigint: true });
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
return isNodeError(error) && error.code === "ENOENT";
|
|
295
|
+
}
|
|
296
|
+
if (stats.isSymbolicLink())
|
|
297
|
+
return false;
|
|
298
|
+
if (index < segments.length - 1) {
|
|
299
|
+
if (!stats.isDirectory())
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
else if (!stats.isFile() || stats.nlink !== 1n) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
async function alternatesStayInsideCommonDir(commonDir, text) {
|
|
309
|
+
const objectDir = path.join(commonDir, "objects");
|
|
310
|
+
for (const line of text.split(/\r?\n/).map((value) => value.trim()).filter(Boolean)) {
|
|
311
|
+
const candidate = path.isAbsolute(line) ? line : path.resolve(objectDir, line);
|
|
312
|
+
let physical;
|
|
313
|
+
try {
|
|
314
|
+
physical = await realpath(candidate);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
const relative = path.relative(commonDir, physical);
|
|
320
|
+
if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
function parseGitdirFile(text) {
|
|
327
|
+
const match = /^gitdir:\s*([^\r\n]+)\r?\n?$/.exec(text);
|
|
328
|
+
return match?.[1]?.trim() || null;
|
|
329
|
+
}
|
|
330
|
+
function parseSinglePathLine(text) {
|
|
331
|
+
const match = /^([^\r\n]+)\r?\n?$/.exec(text);
|
|
332
|
+
return match?.[1]?.trim() || null;
|
|
333
|
+
}
|
|
334
|
+
function isSafeGitRef(value) {
|
|
335
|
+
return value.startsWith("refs/")
|
|
336
|
+
&& !value.includes("\\")
|
|
337
|
+
&& !value.includes("\0")
|
|
338
|
+
&& !value.includes("//")
|
|
339
|
+
&& value.split("/").every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
|
|
340
|
+
}
|
|
341
|
+
async function readSingleLinkRegularFile(filePath, allowMissing = false) {
|
|
342
|
+
let before;
|
|
343
|
+
try {
|
|
344
|
+
before = await lstat(filePath, { bigint: true });
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
if (allowMissing && isNodeError(error) && error.code === "ENOENT") {
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
if (before.isSymbolicLink() || !before.isFile() || before.nlink !== 1n) {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
const handle = await open(filePath, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
356
|
+
try {
|
|
357
|
+
const opened = await handle.stat({ bigint: true });
|
|
358
|
+
if (!opened.isFile()
|
|
359
|
+
|| opened.nlink !== 1n
|
|
360
|
+
|| opened.dev !== before.dev
|
|
361
|
+
|| opened.ino !== before.ino) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
const text = await handle.readFile("utf8");
|
|
365
|
+
return Object.freeze({
|
|
366
|
+
identity: Object.freeze({ dev: opened.dev, ino: opened.ino }),
|
|
367
|
+
text
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
finally {
|
|
371
|
+
await handle.close();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
async function isSingleLinkRegularFileOrMissing(filePath) {
|
|
375
|
+
let before;
|
|
376
|
+
try {
|
|
377
|
+
before = await lstat(filePath, { bigint: true });
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
return isNodeError(error) && error.code === "ENOENT";
|
|
381
|
+
}
|
|
382
|
+
if (before.isSymbolicLink() || !before.isFile() || before.nlink !== 1n) {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
const handle = await open(filePath, constants.O_RDONLY | constants.O_NOFOLLOW).catch(() => null);
|
|
386
|
+
if (!handle)
|
|
387
|
+
return false;
|
|
388
|
+
try {
|
|
389
|
+
const opened = await handle.stat({ bigint: true });
|
|
390
|
+
return opened.isFile()
|
|
391
|
+
&& opened.nlink === 1n
|
|
392
|
+
&& opened.dev === before.dev
|
|
393
|
+
&& opened.ino === before.ino;
|
|
394
|
+
}
|
|
395
|
+
finally {
|
|
396
|
+
await handle.close();
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async function stillSameSingleLinkFile(filePath, identity) {
|
|
400
|
+
try {
|
|
401
|
+
const stats = await lstat(filePath, { bigint: true });
|
|
402
|
+
return !stats.isSymbolicLink()
|
|
403
|
+
&& stats.isFile()
|
|
404
|
+
&& stats.nlink === 1n
|
|
405
|
+
&& stats.dev === identity.dev
|
|
406
|
+
&& stats.ino === identity.ino;
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
async function isPhysicalDirectory(directory) {
|
|
413
|
+
try {
|
|
414
|
+
const stats = await lstat(directory);
|
|
415
|
+
return !stats.isSymbolicLink() && stats.isDirectory() && await realpath(directory) === directory;
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
async function isPhysicalDirectoryOrMissing(directory) {
|
|
422
|
+
try {
|
|
423
|
+
const stats = await lstat(directory);
|
|
424
|
+
return !stats.isSymbolicLink() && stats.isDirectory() && await realpath(directory) === directory;
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
return isNodeError(error) && error.code === "ENOENT";
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
async function pathExists(filePath) {
|
|
431
|
+
try {
|
|
432
|
+
await lstat(filePath);
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
catch (error) {
|
|
436
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
437
|
+
return false;
|
|
438
|
+
throw error;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function unsafeInspection(worktreeRoot, note) {
|
|
442
|
+
return { note, status: "unsafe", worktreeRoot };
|
|
443
|
+
}
|
|
444
|
+
function isNodeError(error) {
|
|
445
|
+
return error instanceof Error && "code" in error;
|
|
446
|
+
}
|
|
447
|
+
//# sourceMappingURL=git-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-workspace.js","sourceRoot":"","sources":["../../src/core/git-workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,mCAAmC,GAAG,6CAA6C,CAAC;AACjG,MAAM,CAAC,MAAM,oCAAoC,GAAG,6CAA6C,CAAC;AAyBlG;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,QAAgB;IAChE,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;YACzD,OAAO,gBAAgB,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,mCAAmC,CAAC,CAAC;IACvF,CAAC;IAED,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9C,IAAI,WAAW,CAAC;QAChB,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnD,OAAO,gBAAgB,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC;YACxE,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YAC/B,CAAC;YACD,OAAO,GAAG,MAAM,CAAC;YACjB,SAAS;QACX,CAAC;QAED,IAAI,WAAW,CAAC,cAAc,EAAE,EAAE,CAAC;YACjC,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,IAAI,MAAM,QAAQ,CAAC,UAAU,CAAC,KAAK,UAAU,EAAE,CAAC;oBAC9C,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;gBACzE,CAAC;gBACD,sEAAsE;gBACtE,uEAAuE;gBACvE,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;oBACzD,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;gBACzE,CAAC;gBACD,MAAM,eAAe,GAAa,EAAE,CAAC;gBACrC,MAAM,SAAS,GAAyB;oBACtC,SAAS,EAAE,UAAU;oBACrB,eAAe;oBACf,MAAM,EAAE,UAAU;oBAClB,IAAI,EAAE,WAAW;oBACjB,SAAS,EAAE,OAAO;oBAClB,YAAY,EAAE,OAAO;iBACtB,CAAC;gBACF,OAAO,MAAM,2BAA2B,CAAC,SAAS,CAAC;oBACjD,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,uBAAuB,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE;oBACxF,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;YACtE,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,WAAW,CAAC,KAAK,KAAK,EAAE,EAAE,CAAC;YACtD,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC,UAAU,CAAC,CAAC;YAC3D,MAAM,cAAc,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACpE,IAAI,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC/B,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAC3B,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;gBAC7B,CAAC,CAAC,cAAc;gBAChB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAC1C,CAAC;YACF,IAAI,CAAC,MAAM,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvC,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;YAClF,MAAM,WAAW,GAAG,MAAM,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;YACjF,MAAM,iBAAiB,GAAG,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACjF,MAAM,mBAAmB,GAAG,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACvF,IAAI,CAAC,SAAS,IAAI,CAAC,WAAW,IAAI,CAAC,iBAAiB,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC7E,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;YAC1E,IACE,CAAC,MAAM,mBAAmB,CAAC,SAAS,CAAC;mBAClC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,MAAM;mBACnC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC;mBAC1D,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EACrC,CAAC;gBACD,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,mBAAmB,GAAG,MAAM,QAAQ,CACxC,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC;gBAClC,CAAC,CAAC,mBAAmB;gBACrB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAC9C,CAAC;YACF,IAAI,mBAAmB,KAAK,UAAU,EAAE,CAAC;gBACvC,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC1C,IACE,CAAC,MAAM,mBAAmB,CAAC,SAAS,CAAC;mBAClC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,KAAK,SAAS;mBAC1D,CAAC,MAAM,uBAAuB,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC;mBAC3D,CAAC,MAAM,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC;mBAClF,CAAC,MAAM,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,EACpF,CAAC;gBACD,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,eAAe,GAAa,EAAE,CAAC;YACrC,MAAM,SAAS,GAAyB;gBACtC,SAAS;gBACT,eAAe;gBACf,MAAM;gBACN,IAAI,EAAE,iBAAiB;gBACvB,SAAS;gBACT,YAAY,EAAE,OAAO;aACtB,CAAC;YACF,OAAO,MAAM,2BAA2B,CAAC,SAAS,CAAC;gBACjD,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,uBAAuB,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE;gBACxF,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;QACtE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,gBAAgB,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,2BAA2B,CAAC,SAA+B;IACxE,IACE,CAAC,MAAM,mBAAmB,CAAC,SAAS,CAAC,MAAM,CAAC;WACzC,CAAC,MAAM,mBAAmB,CAAC,SAAS,CAAC,SAAS,CAAC;WAC/C,CAAC,MAAM,mBAAmB,CAAC,SAAS,CAAC,YAAY,CAAC,EACrD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,iBAAiB,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,iBAAiB,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,aAAa,CAAC;KAC9C,CAAC,CAAC;IACH,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;QACrC,IAAI,CAAC,MAAM,gCAAgC,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,uEAAuE;IACvE,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IACtE,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,IAAI,2BAA2B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,MAAM,gCAAgC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;gBAChF,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,SAAS,IAAI;QACtB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;KACvC,EAAE,CAAC;QACF,IAAI,CAAC,MAAM,4BAA4B,CAAC,SAAS,CAAC,EAAE,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;IACxF,IAAI,IAAI,IAAI,CAAC,MAAM,qBAAqB,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IACvF,IAAI,CAAC,MAAM,gCAAgC,CAAC,cAAc,CAAC,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,yBAAyB,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACzE,IAAI,UAAU,IAAI,CAAC,MAAM,6BAA6B,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7F,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,gCAAgC,CAAC,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IACA,SAAS,CAAC,eAA4B,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,gCAAgC,CAAC,SAA+B;IAC7E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,UAAU,IAAI,IAAI,GAAG,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,iBAAiB,CAAC;KAC/C,CAAC,EAAE,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACjE,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,IAAI,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjD,sEAAsE;gBACtE,kEAAkE;gBAClE,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,YAAY,GAAG,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,IAAI,CAAC,YAAY;gBAAE,SAAS;YAC5B,MAAM,OAAO,GAAG,uFAAuF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnH,IAAI,CAAC,OAAO;gBAAE,OAAO,IAAI,CAAC;YAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YAClG,IAAI,CAAC,SAAS,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpE,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,QAAQ;gBAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;;gBAC9D,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACzC,SAAS,CAAC,IAAI,CACZ,UAAU,MAAM,SAAS,EACzB,UAAU,MAAM,UAAU,EAC1B,UAAU,MAAM,WAAW,EAC3B,UAAU,MAAM,iBAAiB,CAClC,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,SAAS,CAAC,IAAI,CAAC,QAAQ,MAAM,WAAW,EAAE,QAAQ,MAAM,YAAY,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,2BAA2B,CAAC,KAAa;IAChD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACjC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACtD,MAAM,IAAI,OAAO,CAAC;QAClB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,uBAAuB,CAC9B,SAA+B,EAC/B,eAAyB;IAEzB,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,SAA+B,EAAE,QAAgB;IACpF,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,kCAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,4EAA4E;IAC5E,wEAAwE;IACxE,kDAAkD;IAClD,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvE,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,SAAS,EAAE,CAAC;QAC7C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;IACD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,kCAAkC,CAC3C,SAAS,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,EAC/F,SAAS,CACV,EAAE,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,kCAAkC,CAAC,IAAY,EAAE,QAAgB;IAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxG,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtC,IAAI,KAAK,CAAC;QACV,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;QACvD,CAAC;QACD,IAAI,KAAK,CAAC,cAAc,EAAE;YAAE,OAAO,KAAK,CAAC;QACzC,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;gBAAE,OAAO,KAAK,CAAC;QACzC,CAAC;aAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,KAAK,KAAK,EAAE,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,6BAA6B,CAAC,SAAiB,EAAE,IAAY;IAC1E,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAClD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACpF,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC/E,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACpD,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3F,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,KAAK,GAAG,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;AACpC,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;AACpC,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;WAC3B,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;WACrB,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;WACrB,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;WACrB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC;AACtG,CAAC;AAED,KAAK,UAAU,yBAAyB,CACtC,QAAgB,EAChB,YAAY,GAAG,KAAK;IAEpB,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,YAAY,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,MAAM,CAAC,KAAK,KAAK,EAAE,EAAE,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IAC/E,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,IACE,CAAC,MAAM,CAAC,MAAM,EAAE;eACb,MAAM,CAAC,KAAK,KAAK,EAAE;eACnB,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG;eACzB,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,EAC5B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3C,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;YAC7D,IAAI;SACL,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gCAAgC,CAAC,QAAgB;IAC9D,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;IACvD,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,MAAM,CAAC,KAAK,KAAK,EAAE,EAAE,CAAC;QACvE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACjG,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,OAAO,MAAM,CAAC,MAAM,EAAE;eACjB,MAAM,CAAC,KAAK,KAAK,EAAE;eACnB,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG;eACzB,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,CAAC;IACjC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,QAAgB,EAAE,QAAsB;IAC7E,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE;eACzB,KAAK,CAAC,MAAM,EAAE;eACd,KAAK,CAAC,KAAK,KAAK,EAAE;eAClB,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,GAAG;eAC1B,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,GAAG,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,SAAiB;IAClD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,MAAM,QAAQ,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC;IACnG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,4BAA4B,CAAC,SAAiB;IAC3D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,MAAM,QAAQ,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC;IACnG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;IACvD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAChE,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CACvB,YAAoB,EACpB,IAA8F;IAE9F,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,CAAC;AACnD,CAAC"}
|
package/dist/cua-actor-lab.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { type DetachedTimers } from "./e2b-detached.js";
|
|
|
8
8
|
import { type DevicePreset } from "./device-presets.js";
|
|
9
9
|
import { type LabActorLane, type LabConfig, type LabDesktopBrowser, type LabSubjectServe, type LabSubjectState } from "./lab-config.js";
|
|
10
10
|
import { renderObserver, type ObserverResult } from "./observer.js";
|
|
11
|
+
import { type PreparedOutputDirectory } from "./selected-output-paths.js";
|
|
11
12
|
import { type LocalTreeArchive } from "./source-archive.js";
|
|
12
13
|
import type { StopWhen } from "./stop-conditions.js";
|
|
13
14
|
import { type RunBundle, type RunRerunLineage, type RunProviderResource, type RunSubjectProvenance, type RunSubjectStateStepRecord } from "./run.js";
|
|
@@ -395,7 +396,7 @@ export interface CuaLaneDeps {
|
|
|
395
396
|
perLaneSandboxMs: number;
|
|
396
397
|
timeoutMs: number;
|
|
397
398
|
laneCount: number;
|
|
398
|
-
artifactRoot:
|
|
399
|
+
artifactRoot: PreparedOutputDirectory;
|
|
399
400
|
redactScreenshots: boolean;
|
|
400
401
|
scrubKnownValues: (text: string) => string;
|
|
401
402
|
runSession: (options: CuaActorSessionOptions) => Promise<CuaLoopResult>;
|
|
@@ -430,7 +431,7 @@ export interface LaneRunOutcome {
|
|
|
430
431
|
/** Build a lane's writeScreenshot closure: writes under screenshots/<screenshotDir>/ and records
|
|
431
432
|
* the relative path the trace references (screenshots/<name> at N=1; screenshots/<laneId>/<name>
|
|
432
433
|
* at N>1). */
|
|
433
|
-
export declare function makeLaneWriteScreenshot(artifactRoot:
|
|
434
|
+
export declare function makeLaneWriteScreenshot(artifactRoot: PreparedOutputDirectory, spec: {
|
|
434
435
|
screenshotDir: string;
|
|
435
436
|
}, screenshots: string[]): (name: string, bytes: Buffer) => Promise<string>;
|
|
436
437
|
/**
|
package/dist/cua-actor-lab.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// conformant humanish.actor-trace.v1 projection, whose `redaction.screenshots` records the
|
|
22
22
|
// run's actual mode ("raw" | "blurred" | "n/a") — every label downstream derives from it.
|
|
23
23
|
import { randomBytes } from "node:crypto";
|
|
24
|
-
import {
|
|
24
|
+
import { readFile, realpath, rm } from "node:fs/promises";
|
|
25
25
|
import path from "node:path";
|
|
26
26
|
import { runDesktopCommandOrThrow, toErrorMessage } from "./command-failure.js";
|
|
27
27
|
import { pathToFileURL } from "node:url";
|
|
@@ -37,6 +37,8 @@ import { assertScreenshotEvidence } from "./image-evidence.js";
|
|
|
37
37
|
import { buildObserverData } from "./observer-data.js";
|
|
38
38
|
import { attachObserverRuntimeStreamUrls, renderObserver } from "./observer.js";
|
|
39
39
|
import { containsSensitive, digestText, redactedTail, redactText } from "./redaction.js";
|
|
40
|
+
import { assertPreparedSelectedOutputDirectory, assertSafeOutputPathSegment, prepareContainedOutputDirectory, prepareSelectedOutputDirectory, writeContainedOutputFile, writePreparedRunLatestPointer } from "./selected-output-paths.js";
|
|
41
|
+
import { prepareRunArtifactPaths, validatePreparedRunArtifactPaths } from "./run-paths.js";
|
|
40
42
|
import { createLocalTreeArchive } from "./source-archive.js";
|
|
41
43
|
import { buildRunSource, loadRunBundle, PUBLIC_TARGET_CWD, REVIEW_SCHEMA, RUN_BUNDLE_SCHEMA } from "./run.js";
|
|
42
44
|
export const CUA_ACTOR_LAB_SCHEMA = "humanish.cua-lab-result.v2";
|
|
@@ -386,13 +388,16 @@ function phaseEventIdSuffix(type) {
|
|
|
386
388
|
* the relative path the trace references (screenshots/<name> at N=1; screenshots/<laneId>/<name>
|
|
387
389
|
* at N>1). */
|
|
388
390
|
export function makeLaneWriteScreenshot(artifactRoot, spec, screenshots) {
|
|
391
|
+
if (spec.screenshotDir) {
|
|
392
|
+
assertSafeOutputPathSegment(spec.screenshotDir, "Screenshot lane id");
|
|
393
|
+
}
|
|
389
394
|
const dirParts = spec.screenshotDir ? ["screenshots", spec.screenshotDir] : ["screenshots"];
|
|
390
395
|
const relPrefix = spec.screenshotDir ? path.posix.join("screenshots", spec.screenshotDir) : "screenshots";
|
|
391
396
|
return async (name, bytes) => {
|
|
397
|
+
assertSafeOutputPathSegment(name, "Screenshot name");
|
|
392
398
|
const rel = path.posix.join(relPrefix, name);
|
|
393
399
|
assertScreenshotEvidence(rel, bytes);
|
|
394
|
-
await
|
|
395
|
-
await writeFile(path.join(artifactRoot, ...dirParts, name), bytes);
|
|
400
|
+
await writeContainedOutputFile(artifactRoot, path.join(...dirParts, name), bytes);
|
|
396
401
|
screenshots.push(rel);
|
|
397
402
|
return rel;
|
|
398
403
|
};
|
|
@@ -881,8 +886,7 @@ export async function runCuaLane(spec, deps) {
|
|
|
881
886
|
}
|
|
882
887
|
}
|
|
883
888
|
if (session) {
|
|
884
|
-
await
|
|
885
|
-
await writeFile(path.join(deps.artifactRoot, spec.traceArtifactPath), `${JSON.stringify(session.trace, null, 2)}\n`, "utf8");
|
|
889
|
+
await writeContainedOutputFile(deps.artifactRoot, spec.traceArtifactPath, `${JSON.stringify(session.trace, null, 2)}\n`, "utf8");
|
|
886
890
|
if (session.trace.redaction.screenshots === "raw") {
|
|
887
891
|
warnings.push("Screenshots are full-fidelity (raw) for local use — the bundle stays in gitignored .humanish and nothing scans these pixels; review them before sharing anywhere. Set policies.redactScreenshots: true to blur a share-as-is bundle.");
|
|
888
892
|
}
|
|
@@ -949,8 +953,7 @@ async function runInProcessLane(spec, deps) {
|
|
|
949
953
|
sessionError = redactText(deps.scrubKnownValues(toErrorMessage(error)));
|
|
950
954
|
}
|
|
951
955
|
if (session) {
|
|
952
|
-
await
|
|
953
|
-
await writeFile(path.join(deps.artifactRoot, spec.traceArtifactPath), `${JSON.stringify(session.trace, null, 2)}\n`, "utf8");
|
|
956
|
+
await writeContainedOutputFile(deps.artifactRoot, spec.traceArtifactPath, `${JSON.stringify(session.trace, null, 2)}\n`, "utf8");
|
|
954
957
|
if (session.trace.redaction.screenshots === "raw") {
|
|
955
958
|
warnings.push("Screenshots are full-fidelity (raw) for local use — the bundle stays in gitignored .humanish and nothing scans these pixels; review them before sharing anywhere. Set policies.redactScreenshots: true to blur a share-as-is bundle.");
|
|
956
959
|
}
|
|
@@ -1180,7 +1183,12 @@ function subjectProvenanceArg(subject, publicRepo, subjectEnvNames) {
|
|
|
1180
1183
|
}
|
|
1181
1184
|
export async function runCuaActorLab(options) {
|
|
1182
1185
|
const { config, dryRun } = options;
|
|
1183
|
-
|
|
1186
|
+
// Capture the physical project before reading or invoking any caller hook. A supported
|
|
1187
|
+
// symlink cwd remains valid, but retargeting that alias from a hook cannot redirect source
|
|
1188
|
+
// reads, local-tree packing, managed run storage, or Observer output into another project.
|
|
1189
|
+
const physicalCwd = await realpath(path.resolve(options.cwd));
|
|
1190
|
+
const projectRoot = await prepareSelectedOutputDirectory(path.dirname(physicalCwd), physicalCwd);
|
|
1191
|
+
const cwd = projectRoot.physicalPath;
|
|
1184
1192
|
const hooks = options.hooks ?? {};
|
|
1185
1193
|
let liveObserver;
|
|
1186
1194
|
const runtimeStreamUrls = [];
|
|
@@ -1320,6 +1328,7 @@ export async function runCuaActorLab(options) {
|
|
|
1320
1328
|
emitPreflightPlan(plan, config.id);
|
|
1321
1329
|
}
|
|
1322
1330
|
hooks.onPreflight?.(plan);
|
|
1331
|
+
await assertPreparedSelectedOutputDirectory(projectRoot);
|
|
1323
1332
|
// Read keys once into locals (names only; values never logged or persisted).
|
|
1324
1333
|
const openaiApiKey = env.OPENAI_API_KEY?.trim() ?? "";
|
|
1325
1334
|
const e2bApiKey = env.E2B_API_KEY?.trim() ?? "";
|
|
@@ -1348,12 +1357,14 @@ export async function runCuaActorLab(options) {
|
|
|
1348
1357
|
}
|
|
1349
1358
|
}
|
|
1350
1359
|
const runId = options.runId ?? makeCuaRunId();
|
|
1351
|
-
const
|
|
1360
|
+
const runPaths = await prepareRunArtifactPaths(cwd, runId);
|
|
1361
|
+
const artifactRoot = runPaths.absoluteRunRoot;
|
|
1362
|
+
const physicalArtifactRoot = runPaths.physicalRunRoot;
|
|
1352
1363
|
const createdAt = new Date().toISOString();
|
|
1353
1364
|
const timeoutMs = config.execution?.timeoutMs ?? DEFAULT_SESSION_TIMEOUT_MS;
|
|
1354
1365
|
const requestTimeoutMs = readPositiveInt(env.HUMANISH_E2B_REQUEST_TIMEOUT_MS, 60_000);
|
|
1355
1366
|
const redactScreenshots = config.policies?.redactScreenshots === true;
|
|
1356
|
-
await
|
|
1367
|
+
await prepareContainedOutputDirectory(runPaths, "screenshots");
|
|
1357
1368
|
const source = await buildRunSource({
|
|
1358
1369
|
capturedAt: createdAt,
|
|
1359
1370
|
cwd,
|
|
@@ -1404,7 +1415,7 @@ export async function runCuaActorLab(options) {
|
|
|
1404
1415
|
perLaneSandboxMs: resolvePerLaneSandboxMs(config),
|
|
1405
1416
|
timeoutMs,
|
|
1406
1417
|
laneCount,
|
|
1407
|
-
artifactRoot,
|
|
1418
|
+
artifactRoot: runPaths,
|
|
1408
1419
|
redactScreenshots,
|
|
1409
1420
|
scrubKnownValues,
|
|
1410
1421
|
runSession,
|
|
@@ -1461,7 +1472,7 @@ export async function runCuaActorLab(options) {
|
|
|
1461
1472
|
subjectEnvNames,
|
|
1462
1473
|
inProgress: true
|
|
1463
1474
|
});
|
|
1464
|
-
await writeCuaRunArtifacts(
|
|
1475
|
+
await writeCuaRunArtifacts(inProgressBundle, createdAt, runPaths);
|
|
1465
1476
|
liveObserver = observerResultForCuaArtifacts(cwd, runId, artifactRoot, [
|
|
1466
1477
|
"Live CUA Observer is attached before final verification; stream auth URLs are runtime-only and are not persisted."
|
|
1467
1478
|
]);
|
|
@@ -1570,7 +1581,7 @@ export async function runCuaActorLab(options) {
|
|
|
1570
1581
|
bundle,
|
|
1571
1582
|
context: {
|
|
1572
1583
|
bundle,
|
|
1573
|
-
runDir:
|
|
1584
|
+
runDir: physicalArtifactRoot,
|
|
1574
1585
|
labId: config.id,
|
|
1575
1586
|
runId,
|
|
1576
1587
|
actor: descriptor.id,
|
|
@@ -1582,7 +1593,7 @@ export async function runCuaActorLab(options) {
|
|
|
1582
1593
|
warnings: adapterWarnings,
|
|
1583
1594
|
hookLabel: "cuaHooks"
|
|
1584
1595
|
});
|
|
1585
|
-
await writeCuaRunArtifacts(
|
|
1596
|
+
await writeCuaRunArtifacts(bundle, createdAt, runPaths);
|
|
1586
1597
|
const observer = await render(cwd, runId, { open: options.open === true });
|
|
1587
1598
|
if (observer.ok && runtimeStreamUrls.length > 0) {
|
|
1588
1599
|
attachObserverRuntimeStreamUrls(observer, runtimeStreamUrls);
|
|
@@ -1705,21 +1716,21 @@ function buildLaneSummary(outcomes, laneCount, plan, dryRun) {
|
|
|
1705
1716
|
waves: plan.waves
|
|
1706
1717
|
};
|
|
1707
1718
|
}
|
|
1708
|
-
async function writeCuaRunArtifacts(
|
|
1719
|
+
async function writeCuaRunArtifacts(bundle, updatedAt, preparedRunPaths) {
|
|
1720
|
+
const runPaths = await validatePreparedRunArtifactPaths(preparedRunPaths);
|
|
1709
1721
|
const publicBundle = {
|
|
1710
1722
|
...bundle,
|
|
1711
1723
|
cwd: PUBLIC_TARGET_CWD
|
|
1712
1724
|
};
|
|
1713
|
-
await
|
|
1714
|
-
await
|
|
1715
|
-
await
|
|
1716
|
-
await
|
|
1717
|
-
await
|
|
1718
|
-
await
|
|
1719
|
-
await writeFile(path.join(cwd, ".humanish", "runs", "latest.json"), `${JSON.stringify({
|
|
1725
|
+
await writeContainedOutputFile(runPaths, "run.json", `${JSON.stringify(publicBundle, null, 2)}\n`, "utf8");
|
|
1726
|
+
await writeContainedOutputFile(runPaths, "review.json", `${JSON.stringify(publicBundle.review, null, 2)}\n`, "utf8");
|
|
1727
|
+
await writeContainedOutputFile(runPaths, "review.md", renderCuaReviewMarkdown(publicBundle), "utf8");
|
|
1728
|
+
await writeContainedOutputFile(runPaths, "events.ndjson", `${publicBundle.events.map((event) => JSON.stringify(event)).join("\n")}\n`, "utf8");
|
|
1729
|
+
await writeContainedOutputFile(runPaths, "observer/observer-data.json", `${JSON.stringify(buildObserverData(publicBundle), null, 2)}\n`, "utf8");
|
|
1730
|
+
await writePreparedRunLatestPointer(runPaths, `${JSON.stringify({
|
|
1720
1731
|
schema: "humanish.latest-run.v1",
|
|
1721
1732
|
runId: publicBundle.runId,
|
|
1722
|
-
path:
|
|
1733
|
+
path: runPaths.relativeRunRoot,
|
|
1723
1734
|
updatedAt
|
|
1724
1735
|
}, null, 2)}\n`, "utf8");
|
|
1725
1736
|
}
|