@userreason/wizard 0.3.0 → 0.3.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 +44 -51
- package/dist/agent-note.js +6 -5
- package/dist/agent-skill.js +5 -4
- package/dist/analytics.js +2 -2
- package/dist/bin.js +55 -51
- package/dist/{chunk-SFODN2YB.js → chunk-4INLEQE2.js} +2 -2
- package/dist/{chunk-77SK7TKZ.js → chunk-7AAH6C4L.js} +928 -631
- package/dist/{chunk-Z6ZY7X2K.js → chunk-7O7H3PIM.js} +6 -6
- package/dist/{chunk-VXWLSQYK.js → chunk-CSZW2ULJ.js} +39 -17
- package/dist/{chunk-P6DOSGRZ.js → chunk-DMXUXEQI.js} +1 -1
- package/dist/{chunk-GOYBYAUH.js → chunk-EVNEX5N5.js} +1 -1
- package/dist/{chunk-UN24JFV2.js → chunk-KF37D5WL.js} +1 -1
- package/dist/{chunk-5IO5LY22.js → chunk-LEJFE4U5.js} +2 -2
- package/dist/{chunk-MFGJ2KPT.js → chunk-NNPYUATH.js} +1 -1
- package/dist/chunk-PJQOSDYS.js +50 -0
- package/dist/{chunk-YYFC7TM2.js → chunk-Q5U5UOQN.js} +7 -5
- package/dist/{chunk-NZ65XDNL.js → chunk-SB3AYQWG.js} +4 -4
- package/dist/{chunk-CADA5WZ3.js → chunk-TOID3NYP.js} +13 -6
- package/dist/{chunk-ZHHIHHLU.js → chunk-TRBSH5G7.js} +5 -5
- package/dist/{chunk-2UEUVLCB.js → chunk-XASPGFYK.js} +3 -3
- package/dist/{chunk-F4FKAUQN.js → chunk-XPFKXLIZ.js} +2 -2
- package/dist/{chunk-HIF6NUNK.js → chunk-ZHJV247H.js} +6 -8
- package/dist/cli-access.js +3 -3
- package/dist/connection.js +2 -2
- package/dist/first-survey.js +2 -2
- package/dist/footer.js +5 -4
- package/dist/global-cli.js +5 -4
- package/dist/install-diagnostics.js +9 -0
- package/dist/integrate.js +4 -3
- package/dist/project.js +3 -2
- package/dist/setup-flow.js +9 -8
- package/dist/setup.js +8 -7
- package/dist/startup.js +2 -2
- package/dist/state.js +5 -4
- package/dist/ui.js +2 -2
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
// node_modules/typescript/lib/typescript.js
|
|
9
9
|
var require_typescript = __commonJS({
|
|
10
10
|
"node_modules/typescript/lib/typescript.js"(exports, module) {
|
|
11
|
-
var
|
|
11
|
+
var ts3 = {};
|
|
12
12
|
((module2) => {
|
|
13
13
|
"use strict";
|
|
14
14
|
var __defProp = Object.defineProperty;
|
|
@@ -2271,7 +2271,7 @@ var require_typescript = __commonJS({
|
|
|
2271
2271
|
walkUpParenthesizedTypesAndGetParentAndChild: () => walkUpParenthesizedTypesAndGetParentAndChild,
|
|
2272
2272
|
whitespaceOrMapCommentRegExp: () => whitespaceOrMapCommentRegExp,
|
|
2273
2273
|
writeCommentRange: () => writeCommentRange,
|
|
2274
|
-
writeFile: () =>
|
|
2274
|
+
writeFile: () => writeFile3,
|
|
2275
2275
|
writeFileEnsuringDirectories: () => writeFileEnsuringDirectories,
|
|
2276
2276
|
zipWith: () => zipWith
|
|
2277
2277
|
});
|
|
@@ -20914,7 +20914,7 @@ ${lanes.join("\n")}
|
|
|
20914
20914
|
sourceFilePath = isSourceFileInCommonSourceDirectory ? sourceFilePath.substring(commonSourceDirectory.length) : sourceFilePath;
|
|
20915
20915
|
return combinePaths(newDirPath, sourceFilePath);
|
|
20916
20916
|
}
|
|
20917
|
-
function
|
|
20917
|
+
function writeFile3(host, diagnostics, fileName, text2, writeByteOrderMark, sourceFiles, data) {
|
|
20918
20918
|
host.writeFile(
|
|
20919
20919
|
fileName,
|
|
20920
20920
|
text2,
|
|
@@ -33436,8 +33436,8 @@ ${lanes.join("\n")}
|
|
|
33436
33436
|
return void 0;
|
|
33437
33437
|
}
|
|
33438
33438
|
function tryRenameExternalModule(factory2, moduleName, sourceFile3) {
|
|
33439
|
-
const
|
|
33440
|
-
return
|
|
33439
|
+
const rename6 = sourceFile3.renamedDependencies && sourceFile3.renamedDependencies.get(moduleName.text);
|
|
33440
|
+
return rename6 ? factory2.createStringLiteral(rename6) : void 0;
|
|
33441
33441
|
}
|
|
33442
33442
|
function tryGetModuleNameFromFile(factory2, file, host, options) {
|
|
33443
33443
|
if (!file) {
|
|
@@ -36865,8 +36865,8 @@ ${lanes.join("\n")}
|
|
|
36865
36865
|
function isMissingList(arr) {
|
|
36866
36866
|
return !!arr.isMissingList;
|
|
36867
36867
|
}
|
|
36868
|
-
function parseBracketedList(kind, parseElement,
|
|
36869
|
-
if (parseExpected(
|
|
36868
|
+
function parseBracketedList(kind, parseElement, open9, close) {
|
|
36869
|
+
if (parseExpected(open9)) {
|
|
36870
36870
|
const result = parseDelimitedList(kind, parseElement);
|
|
36871
36871
|
parseExpected(close);
|
|
36872
36872
|
return result;
|
|
@@ -39301,7 +39301,7 @@ ${lanes.join("\n")}
|
|
|
39301
39301
|
);
|
|
39302
39302
|
return finishNode(factory2.createJsxSpreadAttribute(expression), pos);
|
|
39303
39303
|
}
|
|
39304
|
-
function parseJsxClosingElement(
|
|
39304
|
+
function parseJsxClosingElement(open9, inExpressionContext) {
|
|
39305
39305
|
const pos = getNodePos();
|
|
39306
39306
|
parseExpected(
|
|
39307
39307
|
31
|
|
@@ -39315,7 +39315,7 @@ ${lanes.join("\n")}
|
|
|
39315
39315
|
/*shouldAdvance*/
|
|
39316
39316
|
false
|
|
39317
39317
|
)) {
|
|
39318
|
-
if (inExpressionContext || !tagNamesAreEquivalent(
|
|
39318
|
+
if (inExpressionContext || !tagNamesAreEquivalent(open9.tagName, tagName)) {
|
|
39319
39319
|
nextToken();
|
|
39320
39320
|
} else {
|
|
39321
39321
|
scanJsxText();
|
|
@@ -129665,7 +129665,7 @@ ${lanes.join("\n")}
|
|
|
129665
129665
|
return;
|
|
129666
129666
|
}
|
|
129667
129667
|
const buildInfo = host.getBuildInfo() || { version };
|
|
129668
|
-
|
|
129668
|
+
writeFile3(
|
|
129669
129669
|
host,
|
|
129670
129670
|
emitterDiagnostics,
|
|
129671
129671
|
buildInfoPath,
|
|
@@ -129877,7 +129877,7 @@ ${lanes.join("\n")}
|
|
|
129877
129877
|
}
|
|
129878
129878
|
if (sourceMapFilePath) {
|
|
129879
129879
|
const sourceMap = sourceMapGenerator.toString();
|
|
129880
|
-
|
|
129880
|
+
writeFile3(
|
|
129881
129881
|
host,
|
|
129882
129882
|
emitterDiagnostics,
|
|
129883
129883
|
sourceMapFilePath,
|
|
@@ -129892,7 +129892,7 @@ ${lanes.join("\n")}
|
|
|
129892
129892
|
}
|
|
129893
129893
|
const text2 = writer.getText();
|
|
129894
129894
|
const data = { sourceMapUrlPos, diagnostics: transform2.diagnostics };
|
|
129895
|
-
|
|
129895
|
+
writeFile3(host, emitterDiagnostics, jsFilePath, text2, !!compilerOptions.emitBOM, sourceFiles, data);
|
|
129896
129896
|
writer.clear();
|
|
129897
129897
|
return !data.skippedDtsWrite;
|
|
129898
129898
|
}
|
|
@@ -167558,19 +167558,19 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
167558
167558
|
}
|
|
167559
167559
|
function convertNamedExport(sourceFile3, assignment, changes, exports2) {
|
|
167560
167560
|
const { text: text2 } = assignment.left.name;
|
|
167561
|
-
const
|
|
167562
|
-
if (
|
|
167561
|
+
const rename6 = exports2.get(text2);
|
|
167562
|
+
if (rename6 !== void 0) {
|
|
167563
167563
|
const newNodes = [
|
|
167564
167564
|
makeConst(
|
|
167565
167565
|
/*modifiers*/
|
|
167566
167566
|
void 0,
|
|
167567
|
-
|
|
167567
|
+
rename6,
|
|
167568
167568
|
assignment.right
|
|
167569
167569
|
),
|
|
167570
167570
|
makeExportDeclaration([factory.createExportSpecifier(
|
|
167571
167571
|
/*isTypeOnly*/
|
|
167572
167572
|
false,
|
|
167573
|
-
|
|
167573
|
+
rename6,
|
|
167574
167574
|
text2
|
|
167575
167575
|
)])
|
|
167576
167576
|
];
|
|
@@ -188111,18 +188111,18 @@ ${content}
|
|
|
188111
188111
|
/* Code */
|
|
188112
188112
|
);
|
|
188113
188113
|
}
|
|
188114
|
-
function spanForObjectOrArrayLiteral(node,
|
|
188114
|
+
function spanForObjectOrArrayLiteral(node, open9 = 19) {
|
|
188115
188115
|
return spanForNode(
|
|
188116
188116
|
node,
|
|
188117
188117
|
/*autoCollapse*/
|
|
188118
188118
|
false,
|
|
188119
188119
|
/*useFullStart*/
|
|
188120
188120
|
!isArrayLiteralExpression(node.parent) && !isCallExpression(node.parent),
|
|
188121
|
-
|
|
188121
|
+
open9
|
|
188122
188122
|
);
|
|
188123
188123
|
}
|
|
188124
|
-
function spanForNode(hintSpanNode, autoCollapse = false, useFullStart = true,
|
|
188125
|
-
const openToken = findChildOfKind(n,
|
|
188124
|
+
function spanForNode(hintSpanNode, autoCollapse = false, useFullStart = true, open9 = 19, close = open9 === 19 ? 20 : 24) {
|
|
188125
|
+
const openToken = findChildOfKind(n, open9, sourceFile3);
|
|
188126
188126
|
const closeToken = findChildOfKind(n, close, sourceFile3);
|
|
188127
188127
|
return openToken && closeToken && spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile3, autoCollapse, useFullStart);
|
|
188128
188128
|
}
|
|
@@ -190913,9 +190913,9 @@ ${options.prefix}` : "\n" : options.prefix
|
|
|
190913
190913
|
return end;
|
|
190914
190914
|
}
|
|
190915
190915
|
function getClassOrObjectBraceEnds(cls, sourceFile3) {
|
|
190916
|
-
const
|
|
190916
|
+
const open9 = findChildOfKind(cls, 19, sourceFile3);
|
|
190917
190917
|
const close = findChildOfKind(cls, 20, sourceFile3);
|
|
190918
|
-
return [
|
|
190918
|
+
return [open9 == null ? void 0 : open9.end, close == null ? void 0 : close.end];
|
|
190919
190919
|
}
|
|
190920
190920
|
function getMembersOrProperties(node) {
|
|
190921
190921
|
return isObjectLiteralExpression(node) ? node.properties : node.members;
|
|
@@ -197774,7 +197774,7 @@ ${options.prefix}` : "\n" : options.prefix
|
|
|
197774
197774
|
walkUpParenthesizedTypesAndGetParentAndChild: () => walkUpParenthesizedTypesAndGetParentAndChild,
|
|
197775
197775
|
whitespaceOrMapCommentRegExp: () => whitespaceOrMapCommentRegExp,
|
|
197776
197776
|
writeCommentRange: () => writeCommentRange,
|
|
197777
|
-
writeFile: () =>
|
|
197777
|
+
writeFile: () => writeFile3,
|
|
197778
197778
|
writeFileEnsuringDirectories: () => writeFileEnsuringDirectories,
|
|
197779
197779
|
zipWith: () => zipWith
|
|
197780
197780
|
});
|
|
@@ -210736,9 +210736,9 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
210736
210736
|
};
|
|
210737
210737
|
}
|
|
210738
210738
|
})({ get exports() {
|
|
210739
|
-
return
|
|
210739
|
+
return ts3;
|
|
210740
210740
|
}, set exports(v) {
|
|
210741
|
-
|
|
210741
|
+
ts3 = v;
|
|
210742
210742
|
if (typeof module !== "undefined" && module.exports) {
|
|
210743
210743
|
module.exports = v;
|
|
210744
210744
|
}
|
|
@@ -211799,8 +211799,8 @@ var productionProfile = {
|
|
|
211799
211799
|
kind: "production",
|
|
211800
211800
|
apiEnvironment: "production",
|
|
211801
211801
|
docsUrl: PRODUCTION_DOCS,
|
|
211802
|
-
sdkVersion: "0.5.
|
|
211803
|
-
cliVersion: "0.2.
|
|
211802
|
+
sdkVersion: "0.5.3",
|
|
211803
|
+
cliVersion: "0.2.1"
|
|
211804
211804
|
};
|
|
211805
211805
|
function parsePackageProfile(value) {
|
|
211806
211806
|
const data = object(value, "package profile");
|
|
@@ -211874,14 +211874,14 @@ async function discoverAuthConfig(url, development = false, fetcher = fetch) {
|
|
|
211874
211874
|
if (!response.headers.get("content-type")?.toLowerCase().startsWith("application/json") || !response.body)
|
|
211875
211875
|
throw new Error("Invalid UserReason authentication configuration response");
|
|
211876
211876
|
const reader = response.body.getReader(), chunks = [];
|
|
211877
|
-
let
|
|
211877
|
+
let bytes2 = 0;
|
|
211878
211878
|
try {
|
|
211879
211879
|
while (true) {
|
|
211880
211880
|
const part = await reader.read();
|
|
211881
211881
|
if (part.done)
|
|
211882
211882
|
break;
|
|
211883
|
-
|
|
211884
|
-
if (
|
|
211883
|
+
bytes2 += part.value.byteLength;
|
|
211884
|
+
if (bytes2 > 4096) {
|
|
211885
211885
|
await reader.cancel();
|
|
211886
211886
|
throw new Error("UserReason authentication configuration response is too large");
|
|
211887
211887
|
}
|
|
@@ -211890,7 +211890,7 @@ async function discoverAuthConfig(url, development = false, fetcher = fetch) {
|
|
|
211890
211890
|
} finally {
|
|
211891
211891
|
reader.releaseLock();
|
|
211892
211892
|
}
|
|
211893
|
-
const buffer = new Uint8Array(
|
|
211893
|
+
const buffer = new Uint8Array(bytes2);
|
|
211894
211894
|
let offset = 0;
|
|
211895
211895
|
for (const chunk of chunks) {
|
|
211896
211896
|
buffer.set(chunk, offset);
|
|
@@ -212618,8 +212618,8 @@ function detectAgentHarness(env = process.env) {
|
|
|
212618
212618
|
function createUiKit({ level, light = false, ascii = false, stream = process.stdout } = {}) {
|
|
212619
212619
|
const lv = level ?? detectColorLevel({ stream });
|
|
212620
212620
|
const rgb = light ? LIGHT : DARK, p256 = light ? LIGHT256 : DARK256, p16 = light ? LIGHT16 : DARK16;
|
|
212621
|
-
const
|
|
212622
|
-
const paint = (role) => (text2) => lv === 0 ? String(text2) : `${
|
|
212621
|
+
const open9 = (role) => lv === 3 ? `${ESC}38;2;${rgb[role].join(";")}m` : lv === 2 ? `${ESC}38;5;${p256[role]}m` : `${ESC}${p16[role]}m`;
|
|
212622
|
+
const paint = (role) => (text2) => lv === 0 ? String(text2) : `${open9(role)}${text2}${ESC}39m`;
|
|
212623
212623
|
const c = {
|
|
212624
212624
|
accent: paint("accent"),
|
|
212625
212625
|
good: paint("good"),
|
|
@@ -212786,18 +212786,18 @@ async function telemetryEnabled() {
|
|
|
212786
212786
|
function validRecord(value) {
|
|
212787
212787
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
212788
212788
|
return false;
|
|
212789
|
-
const
|
|
212789
|
+
const record2 = value;
|
|
212790
212790
|
const common = ["event_id", "occurred_at", "run_id", "surface", "release_version", "execution_mode", "workspace_id", "site_id", "source_site_environment"];
|
|
212791
|
-
const allowed =
|
|
212792
|
-
if (Object.keys(
|
|
212791
|
+
const allowed = record2.event === "ur.wizard.step" ? [...common, "event", "flow_version", "content_version", "step_id", "phase", "duration_ms", "reason", "selection_source", "framework", "package_manager", "resumed", "guidance_file"] : [...common, "event", "command", "success_count", "failure_count", "total_duration_ms", "max_duration_ms"];
|
|
212792
|
+
if (Object.keys(record2).some((key) => !allowed.includes(key)) || !idPattern.test(record2.event_id) || !idPattern.test(record2.run_id) || !versionPattern.test(record2.release_version) || !["interactive", "agent", "ci", "noninteractive"].includes(record2.execution_mode))
|
|
212793
212793
|
return false;
|
|
212794
|
-
if (!Number.isFinite(Date.parse(
|
|
212794
|
+
if (!Number.isFinite(Date.parse(record2.occurred_at)) || Date.now() - Date.parse(record2.occurred_at) > ttl || Date.parse(record2.occurred_at) > Date.now() + 3e5)
|
|
212795
212795
|
return false;
|
|
212796
|
-
if (
|
|
212796
|
+
if (record2.workspace_id && !idPattern.test(record2.workspace_id) || record2.site_id && (!record2.workspace_id || !idPattern.test(record2.site_id)) || record2.source_site_environment && !["development", "production"].includes(record2.source_site_environment))
|
|
212797
212797
|
return false;
|
|
212798
|
-
if (
|
|
212799
|
-
return
|
|
212800
|
-
return
|
|
212798
|
+
if (record2.event === "ur.wizard.step")
|
|
212799
|
+
return record2.surface === "wizard" && WIZARD_STEPS.includes(record2.step_id) && WIZARD_PHASES.includes(record2.phase) && versionPattern.test(record2.flow_version) && versionPattern.test(record2.content_version) && (record2.duration_ms === void 0 || number(record2.duration_ms)) && (record2.reason === void 0 || TELEMETRY_REASONS.includes(record2.reason)) && (record2.selection_source === void 0 || ["prompt", "flag", "default"].includes(record2.selection_source)) && (record2.framework === void 0 || ["react", "next", "vue", "vanilla"].includes(record2.framework)) && (record2.package_manager === void 0 || ["npm", "pnpm", "yarn"].includes(record2.package_manager)) && (record2.resumed === void 0 || typeof record2.resumed === "boolean") && (record2.guidance_file === void 0 || ["AGENTS.md", "CLAUDE.md"].includes(record2.guidance_file));
|
|
212800
|
+
return record2.event === "ur.cli.usage" && record2.surface === "cli" && commands.has(record2.command) && Number.isSafeInteger(record2.success_count) && number(record2.success_count, 1e4) && Number.isSafeInteger(record2.failure_count) && number(record2.failure_count, 1e4) && record2.success_count + record2.failure_count > 0 && number(record2.total_duration_ms, 864e9) && number(record2.max_duration_ms) && record2.total_duration_ms >= record2.max_duration_ms;
|
|
212801
212801
|
}
|
|
212802
212802
|
var ToolTelemetry = class {
|
|
212803
212803
|
options;
|
|
@@ -212861,18 +212861,18 @@ var ToolTelemetry = class {
|
|
|
212861
212861
|
step(step_id, phase, details = {}) {
|
|
212862
212862
|
if (!this.active || this.options.surface !== "wizard" || this.pending.length >= maximumRecords)
|
|
212863
212863
|
return;
|
|
212864
|
-
const
|
|
212865
|
-
if (
|
|
212866
|
-
|
|
212867
|
-
if (validRecord(
|
|
212868
|
-
this.pending.push({ scope: this.scope(), record:
|
|
212864
|
+
const record2 = { ...this.common(), ...this.wizardContext, ...details, event: "ur.wizard.step", flow_version: WIZARD_FLOW_VERSION, content_version: WIZARD_CONTENT_VERSION, step_id, phase };
|
|
212865
|
+
if (record2.duration_ms !== void 0)
|
|
212866
|
+
record2.duration_ms = duration(record2.duration_ms);
|
|
212867
|
+
if (validRecord(record2))
|
|
212868
|
+
this.pending.push({ scope: this.scope(), record: record2 });
|
|
212869
212869
|
}
|
|
212870
212870
|
command(command2, success, durationMs) {
|
|
212871
212871
|
if (!this.active || this.options.surface !== "cli")
|
|
212872
212872
|
return;
|
|
212873
|
-
const
|
|
212874
|
-
if (validRecord(
|
|
212875
|
-
this.pending.push({ scope: this.scope(), record:
|
|
212873
|
+
const record2 = { ...this.common(), event: "ur.cli.usage", command: commands.has(command2) ? command2 : "unknown", success_count: success ? 1 : 0, failure_count: success ? 0 : 1, total_duration_ms: duration(durationMs), max_duration_ms: duration(durationMs) };
|
|
212874
|
+
if (validRecord(record2))
|
|
212875
|
+
this.pending.push({ scope: this.scope(), record: record2 });
|
|
212876
212876
|
}
|
|
212877
212877
|
/** Save a bounded checkpoint without introducing a network call into a wizard step. */
|
|
212878
212878
|
checkpoint() {
|
|
@@ -212915,29 +212915,29 @@ ${scope2}`).digest("hex");
|
|
|
212915
212915
|
} catch {
|
|
212916
212916
|
}
|
|
212917
212917
|
state.records = this.aggregate([...state.records, ...queued], new Set(state.frozen_ids)).slice(-maximumRecords);
|
|
212918
|
-
state.frozen_ids = state.frozen_ids.filter((id) => state.records.some((
|
|
212918
|
+
state.frozen_ids = state.frozen_ids.filter((id) => state.records.some((record2) => record2.event_id === id));
|
|
212919
212919
|
await atomicJson(path, state);
|
|
212920
212920
|
this.pending = this.pending.filter((item) => item.scope !== scope2);
|
|
212921
212921
|
if (!state.records.length || storeOnly || this.options.offline || !authorized || !force && Date.now() - state.last_attempt < (this.options.minimumIntervalMs ?? 6e4))
|
|
212922
212922
|
continue;
|
|
212923
212923
|
const records = [];
|
|
212924
|
-
for (const
|
|
212925
|
-
const candidate = { schema_version: 1, installation_id: state.installation_id, records: [...records,
|
|
212924
|
+
for (const record2 of state.records.slice(0, 50)) {
|
|
212925
|
+
const candidate = { schema_version: 1, installation_id: state.installation_id, records: [...records, record2] };
|
|
212926
212926
|
if (Buffer.byteLength(JSON.stringify(candidate)) > 3e4)
|
|
212927
212927
|
break;
|
|
212928
|
-
records.push(
|
|
212928
|
+
records.push(record2);
|
|
212929
212929
|
}
|
|
212930
212930
|
if (!records.length)
|
|
212931
212931
|
continue;
|
|
212932
212932
|
state.last_attempt = Date.now();
|
|
212933
|
-
state.frozen_ids = [.../* @__PURE__ */ new Set([...state.frozen_ids, ...records.map((
|
|
212933
|
+
state.frozen_ids = [.../* @__PURE__ */ new Set([...state.frozen_ids, ...records.map((record2) => record2.event_id)])];
|
|
212934
212934
|
await atomicJson(path, state);
|
|
212935
212935
|
const response = await this.fetcher(`${this.origin}/v1/telemetry/developer-tools`, { method: "POST", headers: { "Content-Type": "application/json", ...scope2 !== "anonymous" && this.session ? { Authorization: `Bearer ${this.session.accessToken}` } : {} }, redirect: "error", signal: AbortSignal.timeout(scope2 === "anonymous" ? 500 : 1500), body: JSON.stringify({ schema_version: 1, installation_id: state.installation_id, records }) });
|
|
212936
212936
|
await response.body?.cancel().catch(() => {
|
|
212937
212937
|
});
|
|
212938
212938
|
if (response.ok) {
|
|
212939
212939
|
state.records = state.records.slice(records.length);
|
|
212940
|
-
state.frozen_ids = state.frozen_ids.filter((id) => state.records.some((
|
|
212940
|
+
state.frozen_ids = state.frozen_ids.filter((id) => state.records.some((record2) => record2.event_id === id));
|
|
212941
212941
|
await atomicJson(path, state);
|
|
212942
212942
|
}
|
|
212943
212943
|
} catch {
|
|
@@ -212953,22 +212953,22 @@ ${scope2}`).digest("hex");
|
|
|
212953
212953
|
}
|
|
212954
212954
|
aggregate(records, frozen) {
|
|
212955
212955
|
const result = [], aggregates = /* @__PURE__ */ new Map();
|
|
212956
|
-
for (const
|
|
212957
|
-
if (
|
|
212958
|
-
result.push(
|
|
212956
|
+
for (const record2 of records) {
|
|
212957
|
+
if (record2.event !== "ur.cli.usage" || frozen.has(record2.event_id)) {
|
|
212958
|
+
result.push(record2);
|
|
212959
212959
|
continue;
|
|
212960
212960
|
}
|
|
212961
|
-
const key = JSON.stringify([
|
|
212961
|
+
const key = JSON.stringify([record2.command, record2.release_version, record2.execution_mode, record2.workspace_id, record2.site_id, record2.source_site_environment]);
|
|
212962
212962
|
const previous = aggregates.get(key);
|
|
212963
|
-
if (!previous || previous.success_count +
|
|
212964
|
-
const next = { ...
|
|
212963
|
+
if (!previous || previous.success_count + record2.success_count > 1e4 || previous.failure_count + record2.failure_count > 1e4 || previous.total_duration_ms + record2.total_duration_ms > 864e9) {
|
|
212964
|
+
const next = { ...record2 };
|
|
212965
212965
|
aggregates.set(key, next);
|
|
212966
212966
|
result.push(next);
|
|
212967
212967
|
} else {
|
|
212968
|
-
previous.success_count +=
|
|
212969
|
-
previous.failure_count +=
|
|
212970
|
-
previous.total_duration_ms +=
|
|
212971
|
-
previous.max_duration_ms = Math.max(previous.max_duration_ms,
|
|
212968
|
+
previous.success_count += record2.success_count;
|
|
212969
|
+
previous.failure_count += record2.failure_count;
|
|
212970
|
+
previous.total_duration_ms += record2.total_duration_ms;
|
|
212971
|
+
previous.max_duration_ms = Math.max(previous.max_duration_ms, record2.max_duration_ms);
|
|
212972
212972
|
}
|
|
212973
212973
|
}
|
|
212974
212974
|
return result;
|
|
@@ -213024,6 +213024,235 @@ import { createHash as createHash4, randomUUID as randomUUID5 } from "node:crypt
|
|
|
213024
213024
|
import { lstat as lstat2, realpath, readdir as readdir2, open as open4, readFile as readFile4 } from "node:fs/promises";
|
|
213025
213025
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
213026
213026
|
import { execFile } from "node:child_process";
|
|
213027
|
+
|
|
213028
|
+
// node_modules/@userreason/cli/dist/recommendation-source.js
|
|
213029
|
+
var import_typescript = __toESM(require_typescript(), 1);
|
|
213030
|
+
import { posix } from "node:path";
|
|
213031
|
+
var bytes = (text2) => Buffer.byteLength(text2);
|
|
213032
|
+
var limits = { roots: 64, total: 164e3, file: 26e3, span: 16e3, workflow: 38e3, support: 8e3, shared: 5e3, excerpts: 200 };
|
|
213033
|
+
function analyze(file) {
|
|
213034
|
+
const ast = import_typescript.default.createSourceFile(file.path, file.text, import_typescript.default.ScriptTarget.Latest, true, /\.[cm]?jsx?$/.test(file.path) ? import_typescript.default.ScriptKind.JSX : /\.tsx$/.test(file.path) ? import_typescript.default.ScriptKind.TSX : import_typescript.default.ScriptKind.TS);
|
|
213035
|
+
const imports = [], tags = /* @__PURE__ */ new Set(), handlers = /* @__PURE__ */ new Set(), templates = [];
|
|
213036
|
+
const walk = (node) => {
|
|
213037
|
+
if (import_typescript.default.isImportDeclaration(node) && import_typescript.default.isStringLiteral(node.moduleSpecifier)) {
|
|
213038
|
+
const names = [], bindings = node.importClause?.namedBindings;
|
|
213039
|
+
if (node.importClause?.name)
|
|
213040
|
+
names.push(node.importClause.name.text);
|
|
213041
|
+
if (bindings && import_typescript.default.isNamedImports(bindings))
|
|
213042
|
+
names.push(...bindings.elements.map((element) => element.name.text));
|
|
213043
|
+
imports.push({ specifier: node.moduleSpecifier.text, names });
|
|
213044
|
+
}
|
|
213045
|
+
if (import_typescript.default.isExportDeclaration(node) && node.moduleSpecifier && import_typescript.default.isStringLiteral(node.moduleSpecifier))
|
|
213046
|
+
imports.push({ specifier: node.moduleSpecifier.text, names: [] });
|
|
213047
|
+
if (import_typescript.default.isJsxOpeningElement(node) || import_typescript.default.isJsxSelfClosingElement(node))
|
|
213048
|
+
tags.add(node.tagName.getText(ast).split(".")[0]);
|
|
213049
|
+
if (import_typescript.default.isJsxAttribute(node) && /^on[A-Z]/.test(node.name.getText(ast))) {
|
|
213050
|
+
const ids = (child) => {
|
|
213051
|
+
if (import_typescript.default.isIdentifier(child))
|
|
213052
|
+
handlers.add(child.text);
|
|
213053
|
+
import_typescript.default.forEachChild(child, ids);
|
|
213054
|
+
};
|
|
213055
|
+
import_typescript.default.forEachChild(node, ids);
|
|
213056
|
+
}
|
|
213057
|
+
if (import_typescript.default.isPropertyAssignment(node) && node.name.getText(ast) === "templateUrl" && import_typescript.default.isStringLiteral(node.initializer))
|
|
213058
|
+
templates.push(node.initializer.text);
|
|
213059
|
+
import_typescript.default.forEachChild(node, walk);
|
|
213060
|
+
};
|
|
213061
|
+
walk(ast);
|
|
213062
|
+
if (/\.(?:vue|svelte|html)$/.test(file.path))
|
|
213063
|
+
for (const match of file.text.matchAll(/(?:\([\w.:-]+\)|@[\w.:-]+)\s*=\s*["']([^"']+)["']/g))
|
|
213064
|
+
for (const call of match[1].matchAll(/([A-Za-z_$][\w$]*)\s*\(/g))
|
|
213065
|
+
handlers.add(call[1]);
|
|
213066
|
+
return { ast, imports, rendered: new Set(imports.filter((item) => item.names.some((name) => tags.has(name))).map((item) => item.specifier)), handlers, templates };
|
|
213067
|
+
}
|
|
213068
|
+
function recommendationSourceWindows(file, requiredHandlers = []) {
|
|
213069
|
+
const lines = file.text.split("\n");
|
|
213070
|
+
const make = (start, end) => ({ path: file.path, start, end, text: lines.slice(start - 1, end).join("\n") });
|
|
213071
|
+
if (bytes(file.text) <= limits.file)
|
|
213072
|
+
return [make(1, lines.length)];
|
|
213073
|
+
if (!/\.[cm]?[jt]sx?$/.test(file.path))
|
|
213074
|
+
return [];
|
|
213075
|
+
const a = analyze(file), units = [];
|
|
213076
|
+
for (const handler of requiredHandlers)
|
|
213077
|
+
a.handlers.add(handler);
|
|
213078
|
+
const add = (node, priority) => units.push({ start: a.ast.getLineAndCharacterOfPosition(node.getStart(a.ast)).line + 1, end: a.ast.getLineAndCharacterOfPosition(node.end).line + 1, priority });
|
|
213079
|
+
const inspect = (node) => {
|
|
213080
|
+
if (import_typescript.default.isImportDeclaration(node) || import_typescript.default.isExportDeclaration(node)) {
|
|
213081
|
+
add(node, 2);
|
|
213082
|
+
return;
|
|
213083
|
+
}
|
|
213084
|
+
if ((import_typescript.default.isFunctionDeclaration(node) || import_typescript.default.isArrowFunction(node) || import_typescript.default.isFunctionExpression(node)) && node.body && import_typescript.default.isBlock(node.body)) {
|
|
213085
|
+
for (const statement of node.body.statements) {
|
|
213086
|
+
const raw = statement.getText(a.ast);
|
|
213087
|
+
const names = import_typescript.default.isVariableStatement(statement) ? statement.declarationList.declarations.map((declaration) => declaration.name.getText(a.ast)) : import_typescript.default.isFunctionDeclaration(statement) && statement.name ? [statement.name.text] : [];
|
|
213088
|
+
add(statement, /return\s*\(?\s*</.test(raw) || /useEffect|useState|useCallback|useMemo/.test(raw) || names.some((name) => a.handlers.has(name)) ? 0 : 1);
|
|
213089
|
+
}
|
|
213090
|
+
return;
|
|
213091
|
+
}
|
|
213092
|
+
if (import_typescript.default.isClassDeclaration(node)) {
|
|
213093
|
+
for (const member of node.members)
|
|
213094
|
+
add(member, member.name && a.handlers.has(member.name.getText(a.ast)) ? 0 : 1);
|
|
213095
|
+
return;
|
|
213096
|
+
}
|
|
213097
|
+
if (import_typescript.default.isVariableStatement(node)) {
|
|
213098
|
+
let expanded = false;
|
|
213099
|
+
for (const declaration of node.declarationList.declarations)
|
|
213100
|
+
if (declaration.initializer && (import_typescript.default.isArrowFunction(declaration.initializer) || import_typescript.default.isFunctionExpression(declaration.initializer))) {
|
|
213101
|
+
inspect(declaration.initializer);
|
|
213102
|
+
expanded = true;
|
|
213103
|
+
}
|
|
213104
|
+
if (!expanded)
|
|
213105
|
+
add(node, 2);
|
|
213106
|
+
return;
|
|
213107
|
+
}
|
|
213108
|
+
add(node, 2);
|
|
213109
|
+
};
|
|
213110
|
+
for (const node of a.ast.statements)
|
|
213111
|
+
inspect(node);
|
|
213112
|
+
const selected = [];
|
|
213113
|
+
let retained = 0;
|
|
213114
|
+
for (const unit of units.sort((a2, b) => a2.priority - b.priority || a2.start - b.start)) {
|
|
213115
|
+
if (selected.some((window2) => window2.start <= unit.start && window2.end >= unit.end))
|
|
213116
|
+
continue;
|
|
213117
|
+
const window = make(unit.start, unit.end), length = bytes(window.text);
|
|
213118
|
+
if (length > limits.span || retained + length > limits.file)
|
|
213119
|
+
continue;
|
|
213120
|
+
selected.push(window);
|
|
213121
|
+
retained += length;
|
|
213122
|
+
}
|
|
213123
|
+
return selected.sort((a2, b) => a2.start - b.start);
|
|
213124
|
+
}
|
|
213125
|
+
var shell = (path) => /^(?:app|main|router|routes|layout)\.[cm]?[jt]sx?$/i.test(posix.basename(path)) || /\/app\.component\.(?:ts|html)$/.test(path);
|
|
213126
|
+
var rank = (path) => /\/(?:routes|pages|screens|views)\//.test("/" + path) ? 0 : /\.component\.html$/.test(path) ? 1 : 2;
|
|
213127
|
+
var family = (path) => {
|
|
213128
|
+
const parts = path.split("/"), index = parts.findIndex((part) => ["routes", "pages", "screens", "views"].includes(part));
|
|
213129
|
+
return index >= 0 ? parts.slice(0, index + 2).join("/") : posix.dirname(path);
|
|
213130
|
+
};
|
|
213131
|
+
function connectedRecommendationSource(candidates, maxPacketBytes = 262144) {
|
|
213132
|
+
const files2 = new Map(candidates.map((file) => [file.path, file])), analyses = /* @__PURE__ */ new Map();
|
|
213133
|
+
const record2 = (path) => {
|
|
213134
|
+
if (!analyses.has(path))
|
|
213135
|
+
analyses.set(path, analyze(files2.get(path)));
|
|
213136
|
+
return analyses.get(path);
|
|
213137
|
+
};
|
|
213138
|
+
const resolve3 = (from, specifier) => {
|
|
213139
|
+
const base = specifier.startsWith(".") ? posix.normalize(posix.join(posix.dirname(from), specifier)) : specifier.startsWith("@/") ? `src/${specifier.slice(2)}` : "";
|
|
213140
|
+
if (!base)
|
|
213141
|
+
return void 0;
|
|
213142
|
+
return [base, ...[".tsx", ".ts", ".jsx", ".js", ".vue", ".svelte", ".html", "/index.tsx", "/index.ts", "/index.jsx", "/index.js"].map((ext) => base + ext)].find((path) => files2.has(path));
|
|
213143
|
+
};
|
|
213144
|
+
const references = (path) => {
|
|
213145
|
+
const a = record2(path);
|
|
213146
|
+
return [
|
|
213147
|
+
...a.imports.flatMap((item) => {
|
|
213148
|
+
const target = resolve3(path, item.specifier);
|
|
213149
|
+
return target ? [{ target, rendered: a.rendered.has(item.specifier), template: false }] : [];
|
|
213150
|
+
}),
|
|
213151
|
+
...a.templates.flatMap((template) => {
|
|
213152
|
+
const target = resolve3(path, template);
|
|
213153
|
+
return target ? [{ target, rendered: true, template: true }] : [];
|
|
213154
|
+
}),
|
|
213155
|
+
.../\.component\.html$/.test(path) && files2.has(path.replace(/\.html$/, ".ts")) ? [{ target: path.replace(/\.html$/, ".ts"), rendered: true, template: true }] : []
|
|
213156
|
+
].sort((a2, b) => Number(b.rendered) - Number(a2.rendered) || a2.target.localeCompare(b.target));
|
|
213157
|
+
};
|
|
213158
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
213159
|
+
for (const file of candidates.filter((file2) => rank(file2.path) < 2 && !shell(file2.path))) {
|
|
213160
|
+
const key = family(file.path);
|
|
213161
|
+
buckets.set(key, [...buckets.get(key) ?? [], file]);
|
|
213162
|
+
}
|
|
213163
|
+
for (const bucket of buckets.values())
|
|
213164
|
+
bucket.sort((a, b) => a.path.split("/").length - b.path.split("/").length || a.path.localeCompare(b.path));
|
|
213165
|
+
const queues = [...buckets].sort((a, b) => a[0].localeCompare(b[0])), seeds = [];
|
|
213166
|
+
for (let i = 0; seeds.length < Math.min(limits.roots, [...buckets.values()].reduce((n, values) => n + values.length, 0)); i++)
|
|
213167
|
+
for (const [, bucket] of queues)
|
|
213168
|
+
if (bucket[i] && seeds.length < limits.roots)
|
|
213169
|
+
seeds.push(bucket[i].path);
|
|
213170
|
+
if (!seeds.length)
|
|
213171
|
+
seeds.push(...candidates.filter((file) => shell(file.path)).map((file) => file.path).slice(0, limits.roots));
|
|
213172
|
+
if (!seeds.length)
|
|
213173
|
+
seeds.push(...candidates.filter((file) => /\.(?:[cm]?[jt]sx?|vue|svelte|html)$/.test(file.path)).map((file) => file.path).slice(0, limits.roots));
|
|
213174
|
+
const rootSet = new Set(seeds), owner = new Map(seeds.map((path) => [path, path]));
|
|
213175
|
+
const find = (path) => {
|
|
213176
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
213177
|
+
while (owner.get(path) !== path && !seen2.has(path)) {
|
|
213178
|
+
seen2.add(path);
|
|
213179
|
+
path = owner.get(path);
|
|
213180
|
+
}
|
|
213181
|
+
return path;
|
|
213182
|
+
};
|
|
213183
|
+
for (const seed of seeds)
|
|
213184
|
+
for (const edge of references(seed))
|
|
213185
|
+
if (edge.rendered && rootSet.has(edge.target) && find(seed) !== find(edge.target))
|
|
213186
|
+
owner.set(find(edge.target), find(seed));
|
|
213187
|
+
const groups = /* @__PURE__ */ new Map();
|
|
213188
|
+
for (const seed of seeds) {
|
|
213189
|
+
const key = find(seed);
|
|
213190
|
+
groups.set(key, [...groups.get(key) ?? [], seed]);
|
|
213191
|
+
}
|
|
213192
|
+
const workflows = [];
|
|
213193
|
+
for (const roots of groups.values()) {
|
|
213194
|
+
const windows = [], seen2 = /* @__PURE__ */ new Set(), queue = roots.map((path) => ({ path, depth: 0 }));
|
|
213195
|
+
let retained2 = 0, support = 0;
|
|
213196
|
+
const append2 = (path, supporting, handlers = []) => {
|
|
213197
|
+
for (const window of recommendationSourceWindows(files2.get(path), handlers)) {
|
|
213198
|
+
const key = `${path}:${window.start}:${window.end}`, length = bytes(window.text);
|
|
213199
|
+
if (seen2.has(key) || retained2 + length > limits.workflow || supporting && support + length > limits.support)
|
|
213200
|
+
continue;
|
|
213201
|
+
seen2.add(key);
|
|
213202
|
+
windows.push(window);
|
|
213203
|
+
retained2 += length;
|
|
213204
|
+
if (supporting)
|
|
213205
|
+
support += length;
|
|
213206
|
+
}
|
|
213207
|
+
};
|
|
213208
|
+
for (const root of roots)
|
|
213209
|
+
append2(root, false);
|
|
213210
|
+
const visited = /* @__PURE__ */ new Set();
|
|
213211
|
+
while (queue.length) {
|
|
213212
|
+
const item = queue.shift();
|
|
213213
|
+
if (visited.has(item.path) || item.depth > 2)
|
|
213214
|
+
continue;
|
|
213215
|
+
visited.add(item.path);
|
|
213216
|
+
for (const edge of references(item.path).slice(0, 12)) {
|
|
213217
|
+
if (rootSet.has(edge.target) && !roots.includes(edge.target))
|
|
213218
|
+
continue;
|
|
213219
|
+
append2(edge.target, !roots.includes(edge.target), edge.template ? [...record2(item.path).handlers] : []);
|
|
213220
|
+
if (edge.rendered || edge.template)
|
|
213221
|
+
queue.push({ path: edge.target, depth: item.depth + 1 });
|
|
213222
|
+
}
|
|
213223
|
+
}
|
|
213224
|
+
if (windows.length)
|
|
213225
|
+
workflows.push(windows);
|
|
213226
|
+
}
|
|
213227
|
+
const selected = [], seen = /* @__PURE__ */ new Set();
|
|
213228
|
+
let retained = 0, wireBytes = 512;
|
|
213229
|
+
const append = (window) => {
|
|
213230
|
+
const key = `${window.path}:${window.start}:${window.end}`, length = bytes(window.text);
|
|
213231
|
+
if (seen.has(key) || selected.length >= limits.excerpts || retained + length > limits.total)
|
|
213232
|
+
return;
|
|
213233
|
+
const encoded = bytes(JSON.stringify({ kind: "local_source", id: `source_${selected.length + 1}`, path: window.path, file_hash: "0".repeat(64), excerpt_hash: "0".repeat(64), snapshot_id: "00000000-0000-4000-8000-000000000000", start_line: window.start, end_line: window.end, excerpt: window.text })) + 1;
|
|
213234
|
+
if (wireBytes + encoded > maxPacketBytes)
|
|
213235
|
+
return;
|
|
213236
|
+
seen.add(key);
|
|
213237
|
+
selected.push(window);
|
|
213238
|
+
retained += length;
|
|
213239
|
+
wireBytes += encoded;
|
|
213240
|
+
};
|
|
213241
|
+
let shared = 0;
|
|
213242
|
+
for (const file of candidates.filter((file2) => shell(file2.path)).slice(0, 8))
|
|
213243
|
+
for (const window of recommendationSourceWindows(file))
|
|
213244
|
+
if (shared + bytes(window.text) <= limits.shared) {
|
|
213245
|
+
append(window);
|
|
213246
|
+
shared += bytes(window.text);
|
|
213247
|
+
}
|
|
213248
|
+
for (let i = 0; i < Math.max(0, ...workflows.map((windows) => windows.length)); i++)
|
|
213249
|
+
for (const windows of workflows)
|
|
213250
|
+
if (windows[i])
|
|
213251
|
+
append(windows[i]);
|
|
213252
|
+
return selected;
|
|
213253
|
+
}
|
|
213254
|
+
|
|
213255
|
+
// node_modules/@userreason/cli/dist/first-survey-source.js
|
|
213027
213256
|
var sourceHash = (value) => createHash4("sha256").update(value).digest("hex");
|
|
213028
213257
|
var forbidden = /(^|\/)(?:\.git|\.env(?:\..*)?|node_modules|vendor|dist|build|coverage|\.next|\.nuxt|\.cache|\.output|public|uploads?|datasets?|fixtures?|__fixtures__|backups?|credentials?|secrets?)(\/|$)|(?:\.min\.[cm]?js|\.map|\.lock|\.(?:pem|key|p12|pfx|sqlite|db|csv|parquet|log|snap))$|(^|\/)(?:package-lock\.json|yarn\.lock|pnpm-lock\.yaml|\.npmrc|\.netrc|id_rsa|id_ed25519)$/i;
|
|
213029
213258
|
var sourceFile = /(?:\.(?:[cm]?[jt]sx?|vue|svelte|json|md))$/i;
|
|
@@ -213044,12 +213273,12 @@ async function collectFirstSurveySource(input) {
|
|
|
213044
213273
|
const root = await realpath(input.root);
|
|
213045
213274
|
if (root !== input.root || !(await lstat2(root)).isDirectory())
|
|
213046
213275
|
throw new Error("Application root must be a canonical directory, not a symlink");
|
|
213047
|
-
const maxFiles = safeLimits(input.maxFiles, 200, 200);
|
|
213048
|
-
const maxBytes = safeLimits(input.maxBytes, input.recommendations ? 2 * 1024 * 1024 : 500 * 1024, input.recommendations ? 2 * 1024 * 1024 : 500 * 1024);
|
|
213049
|
-
const maxPacketBytes = safeLimits(input.maxPacketBytes, 1e4, 1e4);
|
|
213276
|
+
const maxFiles = safeLimits(input.maxFiles, input.benchmark ? 1200 : 200, input.benchmark ? 1200 : 200);
|
|
213277
|
+
const maxBytes = safeLimits(input.maxBytes, input.benchmark ? 12 * 1024 * 1024 : input.recommendations ? 2 * 1024 * 1024 : 500 * 1024, input.benchmark ? 12 * 1024 * 1024 : input.recommendations ? 2 * 1024 * 1024 : 500 * 1024);
|
|
213278
|
+
const maxPacketBytes = safeLimits(input.maxPacketBytes, input.benchmark ? 262144 : 1e4, input.benchmark ? 262144 : 1e4);
|
|
213050
213279
|
const snapshot_id = input.snapshotId ?? randomUUID5();
|
|
213051
213280
|
const omitted = [], evidence = [];
|
|
213052
|
-
let inspected = 0,
|
|
213281
|
+
let inspected = 0, bytes2 = 0, packetBytes = 0, truncated = false, entries = 0;
|
|
213053
213282
|
const candidates = [];
|
|
213054
213283
|
const rootIgnore = (0, import_ignore.default)();
|
|
213055
213284
|
for (const name of [".gitignore", ".ignore", ".userreasonignore"]) {
|
|
@@ -213071,7 +213300,7 @@ async function collectFirstSurveySource(input) {
|
|
|
213071
213300
|
const check = () => input.signal?.throwIfAborted();
|
|
213072
213301
|
async function walk(directory2, inherited) {
|
|
213073
213302
|
check();
|
|
213074
|
-
if (entries >= 2e3 || inspected >= maxFiles ||
|
|
213303
|
+
if (entries >= (input.benchmark ? 2e4 : 2e3) || inspected >= maxFiles || bytes2 >= maxBytes) {
|
|
213075
213304
|
truncated = true;
|
|
213076
213305
|
return;
|
|
213077
213306
|
}
|
|
@@ -213087,18 +213316,20 @@ async function collectFirstSurveySource(input) {
|
|
|
213087
213316
|
}
|
|
213088
213317
|
}
|
|
213089
213318
|
const names = (await readdir2(directory2)).sort((a, b) => {
|
|
213090
|
-
const
|
|
213091
|
-
return
|
|
213319
|
+
const rank2 = (s) => /^(package\.json|README\.md)$/.test(s) ? 0 : /init|route|page|screen|state|event|app|main/i.test(s) ? 1 : 2;
|
|
213320
|
+
return rank2(a) - rank2(b) || a.localeCompare(b);
|
|
213092
213321
|
});
|
|
213093
213322
|
for (const name of names) {
|
|
213094
213323
|
check();
|
|
213095
|
-
if (++entries > 2e3 || inspected >= maxFiles ||
|
|
213324
|
+
if (++entries > (input.benchmark ? 2e4 : 2e3) || inspected >= maxFiles || bytes2 >= maxBytes) {
|
|
213096
213325
|
truncated = true;
|
|
213097
213326
|
break;
|
|
213098
213327
|
}
|
|
213099
213328
|
const absolute = resolve(directory2, name), path = relative(root, absolute).split(sep).join("/");
|
|
213100
213329
|
if (forbidden.test(path))
|
|
213101
213330
|
continue;
|
|
213331
|
+
if (input.benchmark && /(?:^|\/)(?:scripts|tools|test|tests|__tests__|e2e|docs|examples|storybook|\.storybook)(?:\/|$)/i.test(path))
|
|
213332
|
+
continue;
|
|
213102
213333
|
if (input.recommendations && /^(?:\.agents|\.cursor|\.codex)(?:\/|$)/.test(path))
|
|
213103
213334
|
continue;
|
|
213104
213335
|
const stat = await lstat2(absolute);
|
|
@@ -213124,13 +213355,13 @@ async function collectFirstSurveySource(input) {
|
|
|
213124
213355
|
continue;
|
|
213125
213356
|
inspected++;
|
|
213126
213357
|
const fileBudget = input.recommendations ? 256e3 : 32768;
|
|
213127
|
-
if (stat.size > fileBudget || stat.size +
|
|
213358
|
+
if (stat.size > fileBudget || stat.size + bytes2 > maxBytes) {
|
|
213128
213359
|
omitted.push({ path, reason: "size budget" });
|
|
213129
213360
|
truncated = true;
|
|
213130
213361
|
continue;
|
|
213131
213362
|
}
|
|
213132
|
-
const { constants:
|
|
213133
|
-
const handle = await open4(absolute,
|
|
213363
|
+
const { constants: constants5 } = await import("node:fs");
|
|
213364
|
+
const handle = await open4(absolute, constants5.O_RDONLY | constants5.O_NOFOLLOW);
|
|
213134
213365
|
let data;
|
|
213135
213366
|
try {
|
|
213136
213367
|
const opened = await handle.stat();
|
|
@@ -213144,7 +213375,7 @@ async function collectFirstSurveySource(input) {
|
|
|
213144
213375
|
} finally {
|
|
213145
213376
|
await handle.close();
|
|
213146
213377
|
}
|
|
213147
|
-
|
|
213378
|
+
bytes2 += data.length;
|
|
213148
213379
|
let text2;
|
|
213149
213380
|
try {
|
|
213150
213381
|
text2 = new TextDecoder("utf-8", { fatal: true }).decode(data);
|
|
@@ -213183,10 +213414,15 @@ async function collectFirstSurveySource(input) {
|
|
|
213183
213414
|
}
|
|
213184
213415
|
}
|
|
213185
213416
|
await walk(root, [{ base: root, rules: rootIgnore }]);
|
|
213186
|
-
if (input.
|
|
213187
|
-
const
|
|
213417
|
+
if (input.benchmark) {
|
|
213418
|
+
for (const file of connectedRecommendationSource(candidates, maxPacketBytes)) {
|
|
213419
|
+
evidence.push({ kind: "local_source", id: `source_${evidence.length + 1}`, path: file.path, file_hash: sourceHash(candidates.find((c) => c.path === file.path).text), excerpt_hash: sourceHash(file.text), snapshot_id, start_line: file.start, end_line: file.end, excerpt: file.text });
|
|
213420
|
+
}
|
|
213421
|
+
truncated = candidates.length > evidence.length || evidence.some((e) => e.start_line !== 1 || e.excerpt !== candidates.find((c) => c.path === e.path)?.text);
|
|
213422
|
+
} else if (input.recommendations) {
|
|
213423
|
+
const rank2 = (p) => /\/(?:pages|screens|views)\//i.test("/" + p) ? 0 : /\/(?:app|routes?)\.[^.]+$/i.test(p) ? 1 : /components\//.test(p) ? 2 : 3;
|
|
213188
213424
|
const interactions = (f) => (f.text.match(/onClick|onSubmit|onChange|const handle[A-Z]|function handle[A-Z]/g) ?? []).length;
|
|
213189
|
-
candidates.sort((a, b) =>
|
|
213425
|
+
candidates.sort((a, b) => rank2(a.path) - rank2(b.path) || a.path.split("/").length - b.path.split("/").length || interactions(b) - interactions(a) || a.path.localeCompare(b.path));
|
|
213190
213426
|
const areas = /* @__PURE__ */ new Map();
|
|
213191
213427
|
for (const file of candidates) {
|
|
213192
213428
|
const key = file.path.split("/").slice(0, -1).join("/");
|
|
@@ -213389,7 +213625,7 @@ async function firstSurvey(client, root, workspace2, site2, ui, mode = "start")
|
|
|
213389
213625
|
state = { ...state, id: randomUUID6(), state: "source_review", plan: void 0, digest: void 0, saves: {} };
|
|
213390
213626
|
}
|
|
213391
213627
|
const metadata = object(await client.request("/onboarding/v1/planning/describe", lookup()), "planning destination");
|
|
213392
|
-
const
|
|
213628
|
+
const limits2 = { input_tokens: 12e3, output_tokens: 4e3, deadline_ms: 35e3 };
|
|
213393
213629
|
if (!state.plan) {
|
|
213394
213630
|
if (state.state === "analyzing") {
|
|
213395
213631
|
const existing = object(await client.request("/onboarding/v1/planning/get", lookup()), "plan");
|
|
@@ -213405,7 +213641,7 @@ async function firstSurvey(client, root, workspace2, site2, ui, mode = "start")
|
|
|
213405
213641
|
ui.show("Only the chosen application root is inspected. No sibling packages are included. Secret detection is best effort; review every excerpt.");
|
|
213406
213642
|
const selection = await ui.answer("Relative files/directories to include, comma separated (blank: bounded application root; no siblings)");
|
|
213407
213643
|
const preview = await collectFirstSurveySource({ root, signal: ui.signal, selected: selection.trim() ? selection.split(",").map((p) => p.trim()) : void 0 });
|
|
213408
|
-
ui.show(JSON.stringify({ root, packages: preview.packages, installed_sdk: preview.packages.length ? "metadata found, runtime unverified" : "unknown: verify using installed skill", manifest: preview.evidence.map(({ excerpt, ...rest }) => rest), omitted: preview.omitted, truncated: preview.truncated, destination: metadata.destination, provider_model: metadata.model, provider_prices: metadata.prices, provider_policy: metadata.policy, configuration_fingerprint: metadata.configuration_fingerprint, retention: "Receipt and private plan: seven days, deleted on next planning activity; submitted source packets are not stored by UserReason; generated plans can quote source. Provider policy must be reviewed separately.", budget: `${
|
|
213644
|
+
ui.show(JSON.stringify({ root, packages: preview.packages, installed_sdk: preview.packages.length ? "metadata found, runtime unverified" : "unknown: verify using installed skill", manifest: preview.evidence.map(({ excerpt, ...rest }) => rest), omitted: preview.omitted, truncated: preview.truncated, destination: metadata.destination, provider_model: metadata.model, provider_prices: metadata.prices, provider_policy: metadata.policy, configuration_fingerprint: metadata.configuration_fingerprint, retention: "Receipt and private plan: seven days, deleted on next planning activity; submitted source packets are not stored by UserReason; generated plans can quote source. Provider policy must be reviewed separately.", budget: `${limits2.input_tokens} input / ${limits2.output_tokens} completion tokens (including reasoning); ${limits2.deadline_ms / 1e3} seconds`, capabilities: preview.capabilities, capability_status: preview.capability_status }));
|
|
213409
213645
|
ui.show(JSON.stringify(preview.evidence));
|
|
213410
213646
|
if (!await ui.confirm("Approve uploading exactly this source packet to the displayed provider?")) {
|
|
213411
213647
|
ui.show("Manual path: use prompt validate with your own evidence-labelled definition, then explicitly approve prompt create. No source processing is required.");
|
|
@@ -213428,7 +213664,7 @@ async function firstSurvey(client, root, workspace2, site2, ui, mode = "start")
|
|
|
213428
213664
|
check();
|
|
213429
213665
|
state.state = "analyzing";
|
|
213430
213666
|
await save();
|
|
213431
|
-
const response = object(await client.request("/onboarding/v1/planning/analyze", { schema_version: 1, session_id: state.id, request_id: randomUUID6(), scope: lookup().scope, packages: preview.packages, capabilities: preview.capabilities, evidence, previous_plan_digest: state.digest ?? null, limits, consent: { packet_digest: sourceHash(JSON.stringify(evidence)), destination: metadata.destination, policy_version: "first-survey-v1", configuration_fingerprint: metadata.configuration_fingerprint, authorized_at: (/* @__PURE__ */ new Date()).toISOString(), git_authorized: git } }, ui.signal), "analysis");
|
|
213667
|
+
const response = object(await client.request("/onboarding/v1/planning/analyze", { schema_version: 1, session_id: state.id, request_id: randomUUID6(), scope: lookup().scope, packages: preview.packages, capabilities: preview.capabilities, evidence, previous_plan_digest: state.digest ?? null, limits: limits2, consent: { packet_digest: sourceHash(JSON.stringify(evidence)), destination: metadata.destination, policy_version: "first-survey-v1", configuration_fingerprint: metadata.configuration_fingerprint, authorized_at: (/* @__PURE__ */ new Date()).toISOString(), git_authorized: git } }, ui.signal), "analysis");
|
|
213432
213668
|
check();
|
|
213433
213669
|
state.plan = response.result;
|
|
213434
213670
|
state.digest = sourceHash(JSON.stringify(state.plan));
|
|
@@ -213512,227 +213748,11 @@ async function firstSurvey(client, root, workspace2, site2, ui, mode = "start")
|
|
|
213512
213748
|
}
|
|
213513
213749
|
}
|
|
213514
213750
|
|
|
213515
|
-
// node_modules/@userreason/cli/dist/
|
|
213516
|
-
|
|
213517
|
-
const controller = new AbortController();
|
|
213518
|
-
const prepared = collectFirstSurveySource({ root, signal: controller.signal, recommendations: true }).then((preview) => ({ preview }), () => ({ preview: void 0 }));
|
|
213519
|
-
return {
|
|
213520
|
-
root,
|
|
213521
|
-
async take(signal) {
|
|
213522
|
-
signal?.throwIfAborted();
|
|
213523
|
-
const cached = await prepared;
|
|
213524
|
-
signal?.throwIfAborted();
|
|
213525
|
-
if (cached.preview) {
|
|
213526
|
-
try {
|
|
213527
|
-
await verifyFirstSurveySource(root, cached.preview.evidence);
|
|
213528
|
-
return cached.preview;
|
|
213529
|
-
} catch {
|
|
213530
|
-
signal?.throwIfAborted();
|
|
213531
|
-
}
|
|
213532
|
-
}
|
|
213533
|
-
return collectFirstSurveySource({ root, signal, recommendations: true });
|
|
213534
|
-
},
|
|
213535
|
-
cancel() {
|
|
213536
|
-
controller.abort();
|
|
213537
|
-
}
|
|
213538
|
-
};
|
|
213539
|
-
}
|
|
213540
|
-
|
|
213541
|
-
// node_modules/@userreason/cli/dist/recommended-surveys.js
|
|
213542
|
-
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
213751
|
+
// node_modules/@userreason/cli/dist/setup-store.js
|
|
213752
|
+
import { createHash as createHash5, randomUUID as randomUUID7 } from "node:crypto";
|
|
213543
213753
|
import { constants as constants2 } from "node:fs";
|
|
213544
|
-
import { mkdir as mkdir6, open as open6,
|
|
213754
|
+
import { lstat as lstat4, mkdir as mkdir6, open as open6, opendir, readFile as readFile6, realpath as realpath2, rename as rename4, rm as rm3 } from "node:fs/promises";
|
|
213545
213755
|
import { join as join6 } from "node:path";
|
|
213546
|
-
var record2 = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
213547
|
-
async function recommendedSurveys(client, root, workspace2, site2, ui, options = {}) {
|
|
213548
|
-
if (!options.sourceConsent)
|
|
213549
|
-
return { state: "skipped" };
|
|
213550
|
-
if (!ui.chooseMany)
|
|
213551
|
-
throw Error("Survey selection requires a checkbox interface");
|
|
213552
|
-
const scope2 = {
|
|
213553
|
-
api: client.config.apiUrl,
|
|
213554
|
-
workspace_id: workspace2,
|
|
213555
|
-
site_id: site2
|
|
213556
|
-
};
|
|
213557
|
-
const scopeKey = sourceHash(JSON.stringify([root, scope2]));
|
|
213558
|
-
const dir = join6(configDirectory(), "recommended-surveys");
|
|
213559
|
-
await mkdir6(dir, { recursive: true, mode: 448 });
|
|
213560
|
-
const path = join6(dir, scopeKey + ".json");
|
|
213561
|
-
const lock = await open6(path + ".lock", "wx", 384);
|
|
213562
|
-
const preparation = options.preparation ?? prepareFirstSurveyLocally(root);
|
|
213563
|
-
let state = {
|
|
213564
|
-
version: 1,
|
|
213565
|
-
scope: scopeKey,
|
|
213566
|
-
expires: Date.now() + 7 * 864e5,
|
|
213567
|
-
candidates: [],
|
|
213568
|
-
sources: [],
|
|
213569
|
-
receipts: {}
|
|
213570
|
-
};
|
|
213571
|
-
const save = async () => {
|
|
213572
|
-
const tmp = path + "." + randomUUID7() + ".tmp";
|
|
213573
|
-
await writeFile3(tmp, JSON.stringify(state), { flag: "wx", mode: 384 });
|
|
213574
|
-
await rename4(tmp, path);
|
|
213575
|
-
};
|
|
213576
|
-
const check = () => ui.signal?.throwIfAborted();
|
|
213577
|
-
try {
|
|
213578
|
-
try {
|
|
213579
|
-
const file = await open6(path, constants2.O_RDONLY | constants2.O_NOFOLLOW);
|
|
213580
|
-
try {
|
|
213581
|
-
if ((await file.stat()).size > 128e3)
|
|
213582
|
-
throw Error("Invalid recommendation cache");
|
|
213583
|
-
const old = JSON.parse(await file.readFile("utf8"));
|
|
213584
|
-
if (old.version !== 1 || old.scope !== scopeKey)
|
|
213585
|
-
throw Error("Recommendation scope changed");
|
|
213586
|
-
if (old.expires > Date.now())
|
|
213587
|
-
state = old;
|
|
213588
|
-
} finally {
|
|
213589
|
-
await file.close();
|
|
213590
|
-
}
|
|
213591
|
-
} catch (e) {
|
|
213592
|
-
if (e.code !== "ENOENT")
|
|
213593
|
-
throw e;
|
|
213594
|
-
}
|
|
213595
|
-
check();
|
|
213596
|
-
if (!state.selected) {
|
|
213597
|
-
if (state.candidates.length) {
|
|
213598
|
-
try {
|
|
213599
|
-
await verifyFirstSurveySource(root, state.sources);
|
|
213600
|
-
} catch {
|
|
213601
|
-
state.candidates = [];
|
|
213602
|
-
state.sources = [];
|
|
213603
|
-
}
|
|
213604
|
-
}
|
|
213605
|
-
if (!state.candidates.length) {
|
|
213606
|
-
const generate = async () => {
|
|
213607
|
-
const preview = await preparation.take(ui.signal);
|
|
213608
|
-
if (!preview.evidence.length)
|
|
213609
|
-
throw Error("No product source available");
|
|
213610
|
-
const metadata = record2(await client.request("/onboarding/v1/planning/describe", { schema_version: 1, session_id: randomUUID7(), scope: scope2 }, ui.signal));
|
|
213611
|
-
if (!record2(metadata.recommendations).version)
|
|
213612
|
-
throw Error("Development recommendation pipeline is unavailable");
|
|
213613
|
-
await verifyFirstSurveySource(root, preview.evidence);
|
|
213614
|
-
const response = record2(await client.request("/onboarding/v1/planning/analyze", {
|
|
213615
|
-
schema_version: 1,
|
|
213616
|
-
session_id: randomUUID7(),
|
|
213617
|
-
request_id: randomUUID7(),
|
|
213618
|
-
scope: scope2,
|
|
213619
|
-
packages: preview.packages,
|
|
213620
|
-
capabilities: [
|
|
213621
|
-
...preview.capabilities,
|
|
213622
|
-
"recommended_surveys:v1"
|
|
213623
|
-
],
|
|
213624
|
-
evidence: preview.evidence,
|
|
213625
|
-
previous_plan_digest: null,
|
|
213626
|
-
limits: {
|
|
213627
|
-
input_tokens: 12e3,
|
|
213628
|
-
output_tokens: 4e3,
|
|
213629
|
-
deadline_ms: 4e4
|
|
213630
|
-
},
|
|
213631
|
-
consent: {
|
|
213632
|
-
packet_digest: sourceHash(JSON.stringify(preview.evidence)),
|
|
213633
|
-
destination: metadata.destination,
|
|
213634
|
-
configuration_fingerprint: metadata.configuration_fingerprint,
|
|
213635
|
-
policy_version: "first-survey-v1",
|
|
213636
|
-
authorized_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
213637
|
-
git_authorized: false
|
|
213638
|
-
}
|
|
213639
|
-
}, ui.signal));
|
|
213640
|
-
await verifyFirstSurveySource(root, preview.evidence);
|
|
213641
|
-
const candidates = record2(response.result).candidates;
|
|
213642
|
-
if (!Array.isArray(candidates))
|
|
213643
|
-
throw Error("Invalid recommendations");
|
|
213644
|
-
state.candidates = candidates.slice(0, 3);
|
|
213645
|
-
state.sources = preview.evidence.map(({ path: path2, file_hash }) => ({
|
|
213646
|
-
path: path2,
|
|
213647
|
-
file_hash
|
|
213648
|
-
}));
|
|
213649
|
-
await save();
|
|
213650
|
-
};
|
|
213651
|
-
try {
|
|
213652
|
-
if (ui.loading)
|
|
213653
|
-
await ui.loading("Finding recommended surveys", generate);
|
|
213654
|
-
else
|
|
213655
|
-
await generate();
|
|
213656
|
-
} catch (error) {
|
|
213657
|
-
check();
|
|
213658
|
-
ui.show("Recommendations are unavailable right now. Setup is complete; rerun the wizard to try again.");
|
|
213659
|
-
return {
|
|
213660
|
-
state: "unavailable",
|
|
213661
|
-
error: error instanceof Error ? error.message : "unavailable"
|
|
213662
|
-
};
|
|
213663
|
-
}
|
|
213664
|
-
}
|
|
213665
|
-
if (!state.candidates.length) {
|
|
213666
|
-
ui.show("No supported survey recommendations yet. Setup is complete.");
|
|
213667
|
-
return { state: "empty" };
|
|
213668
|
-
}
|
|
213669
|
-
ui.show("Select surveys to get started. We\u2019ll create drafts in your workspace. Nothing will be published.");
|
|
213670
|
-
const selected = await ui.chooseMany("Recommended surveys", state.candidates.map((c) => ({
|
|
213671
|
-
value: c.id,
|
|
213672
|
-
label: `${String(c.definition.name)} \u2014 ${c.question}`,
|
|
213673
|
-
hint: `${c.opportunity.claim} Delivery can be configured later.`
|
|
213674
|
-
})), []);
|
|
213675
|
-
check();
|
|
213676
|
-
if (!selected.length)
|
|
213677
|
-
return { state: "skipped" };
|
|
213678
|
-
if (new Set(selected).size !== selected.length || selected.some((id) => !state.candidates.some((c) => c.id === id)))
|
|
213679
|
-
throw Error("Invalid survey selection");
|
|
213680
|
-
await verifyFirstSurveySource(root, state.sources);
|
|
213681
|
-
for (const id of selected) {
|
|
213682
|
-
const c = state.candidates.find((c2) => c2.id === id);
|
|
213683
|
-
const validation = record2(await client.read("prompts.validate", {
|
|
213684
|
-
workspaceId: workspace2,
|
|
213685
|
-
siteId: site2,
|
|
213686
|
-
definition: c.definition
|
|
213687
|
-
}));
|
|
213688
|
-
if (validation.valid !== true)
|
|
213689
|
-
throw Error("A recommended draft did not validate");
|
|
213690
|
-
}
|
|
213691
|
-
state.selected = selected;
|
|
213692
|
-
for (const id of selected)
|
|
213693
|
-
state.receipts[id] = {
|
|
213694
|
-
prompt: randomUUID7(),
|
|
213695
|
-
request: randomUUID7(),
|
|
213696
|
-
definition: state.candidates.find((c) => c.id === id).definition
|
|
213697
|
-
};
|
|
213698
|
-
await save();
|
|
213699
|
-
}
|
|
213700
|
-
let count = 0;
|
|
213701
|
-
for (const id of state.selected) {
|
|
213702
|
-
check();
|
|
213703
|
-
const receipt = state.receipts[id];
|
|
213704
|
-
if (!receipt)
|
|
213705
|
-
throw Error("Missing draft receipt");
|
|
213706
|
-
if (!receipt.result) {
|
|
213707
|
-
receipt.result = await client.promptCommand({
|
|
213708
|
-
workspaceId: workspace2,
|
|
213709
|
-
siteId: site2,
|
|
213710
|
-
action: "create",
|
|
213711
|
-
promptId: receipt.prompt,
|
|
213712
|
-
requestId: receipt.request,
|
|
213713
|
-
definition: receipt.definition
|
|
213714
|
-
});
|
|
213715
|
-
await save();
|
|
213716
|
-
}
|
|
213717
|
-
const saved = record2(receipt.result), link = record2(saved.links).edit;
|
|
213718
|
-
ui.show(`Draft saved: ${String(receipt.definition.name)}${typeof link === "string" ? `
|
|
213719
|
-
${link}` : ""}`);
|
|
213720
|
-
count++;
|
|
213721
|
-
}
|
|
213722
|
-
ui.show(`${count} survey draft${count === 1 ? "" : "s"} saved. Nothing was published.`);
|
|
213723
|
-
return { state: "saved", count, receipts: state.receipts };
|
|
213724
|
-
} finally {
|
|
213725
|
-
preparation.cancel();
|
|
213726
|
-
await lock.close();
|
|
213727
|
-
await unlink3(path + ".lock");
|
|
213728
|
-
}
|
|
213729
|
-
}
|
|
213730
|
-
|
|
213731
|
-
// node_modules/@userreason/cli/dist/setup-store.js
|
|
213732
|
-
import { createHash as createHash5, randomUUID as randomUUID8 } from "node:crypto";
|
|
213733
|
-
import { constants as constants3 } from "node:fs";
|
|
213734
|
-
import { lstat as lstat4, mkdir as mkdir7, open as open7, opendir, readFile as readFile6, realpath as realpath2, rename as rename5, rm as rm3 } from "node:fs/promises";
|
|
213735
|
-
import { join as join7 } from "node:path";
|
|
213736
213756
|
var SetupError = class extends Error {
|
|
213737
213757
|
code;
|
|
213738
213758
|
constructor(code, message) {
|
|
@@ -213755,7 +213775,7 @@ function parseStoredSetup(value) {
|
|
|
213755
213775
|
function storePath(origin2, setupId) {
|
|
213756
213776
|
const key = createHash5("sha256").update(`${apiUrl(origin2)}
|
|
213757
213777
|
${uuid(setupId)}`).digest("hex");
|
|
213758
|
-
return
|
|
213778
|
+
return join6(configDirectory(), "setup-v1", `${key}.json`);
|
|
213759
213779
|
}
|
|
213760
213780
|
var retentionMs = 7 * 24 * 60 * 60 * 1e3;
|
|
213761
213781
|
var pruneBatch = 128;
|
|
@@ -213763,7 +213783,7 @@ async function readSetupRecord(path) {
|
|
|
213763
213783
|
const before = await lstat4(path);
|
|
213764
213784
|
if (!before.isFile() || before.isSymbolicLink() || before.size > 65536)
|
|
213765
213785
|
throw new Error("invalid setup file");
|
|
213766
|
-
const file = await
|
|
213786
|
+
const file = await open6(path, constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0));
|
|
213767
213787
|
try {
|
|
213768
213788
|
const info = await file.stat();
|
|
213769
213789
|
if (!info.isFile() || info.ino !== before.ino || info.dev !== before.dev || info.size > 65536)
|
|
@@ -213799,7 +213819,7 @@ async function pruneSetupSessions(now = Date.now()) {
|
|
|
213799
213819
|
return { scanned: 0, removed: 0 };
|
|
213800
213820
|
let directory2;
|
|
213801
213821
|
try {
|
|
213802
|
-
const path =
|
|
213822
|
+
const path = join6(configDirectory(), "setup-v1"), info = await lstat4(path);
|
|
213803
213823
|
if (!info.isDirectory() || info.isSymbolicLink())
|
|
213804
213824
|
return { scanned: 0, removed: 0 };
|
|
213805
213825
|
directory2 = await opendir(path);
|
|
@@ -213815,7 +213835,7 @@ async function pruneSetupSessions(now = Date.now()) {
|
|
|
213815
213835
|
}
|
|
213816
213836
|
if (!entry.isFile() || !/^[a-f0-9]{64}\.json$/.test(entry.name))
|
|
213817
213837
|
continue;
|
|
213818
|
-
const path =
|
|
213838
|
+
const path = join6(configDirectory(), "setup-v1", entry.name);
|
|
213819
213839
|
try {
|
|
213820
213840
|
const { data, info } = await readSetupRecord(path);
|
|
213821
213841
|
if (storePath(data.api_url, data.setup_id) !== path || Date.parse(data.created_at) > now - retentionMs)
|
|
@@ -213831,22 +213851,22 @@ async function pruneSetupSessions(now = Date.now()) {
|
|
|
213831
213851
|
}
|
|
213832
213852
|
async function saveSetupSession(value) {
|
|
213833
213853
|
const data = parseStoredSetup(value), path = storePath(data.api_url, data.setup_id);
|
|
213834
|
-
const temporary = `${path}.${
|
|
213854
|
+
const temporary = `${path}.${randomUUID7()}.tmp`;
|
|
213835
213855
|
try {
|
|
213836
|
-
const directory2 =
|
|
213837
|
-
await
|
|
213856
|
+
const directory2 = join6(configDirectory(), "setup-v1");
|
|
213857
|
+
await mkdir6(directory2, { recursive: true, mode: 448 });
|
|
213838
213858
|
const info = await lstat4(directory2);
|
|
213839
213859
|
if (!info.isDirectory() || info.isSymbolicLink())
|
|
213840
213860
|
throw new SetupError("setup_store_failed", "The setup store must be a regular private directory, not a symbolic link.");
|
|
213841
213861
|
await pruneSetupSessions();
|
|
213842
|
-
const file = await
|
|
213862
|
+
const file = await open6(temporary, "wx", 384);
|
|
213843
213863
|
try {
|
|
213844
213864
|
await file.writeFile(JSON.stringify(data) + "\n");
|
|
213845
213865
|
await file.sync();
|
|
213846
213866
|
} finally {
|
|
213847
213867
|
await file.close();
|
|
213848
213868
|
}
|
|
213849
|
-
await
|
|
213869
|
+
await rename4(temporary, path);
|
|
213850
213870
|
} catch (error) {
|
|
213851
213871
|
if (error instanceof SetupError)
|
|
213852
213872
|
throw error;
|
|
@@ -213861,7 +213881,7 @@ async function loadSetupSession(origin2, setupId, directory2, now = Date.now())
|
|
|
213861
213881
|
let info;
|
|
213862
213882
|
const path = storePath(origin2, setupId);
|
|
213863
213883
|
try {
|
|
213864
|
-
const parent = await lstat4(
|
|
213884
|
+
const parent = await lstat4(join6(configDirectory(), "setup-v1"));
|
|
213865
213885
|
if (!parent.isDirectory() || parent.isSymbolicLink())
|
|
213866
213886
|
throw new Error("invalid setup directory");
|
|
213867
213887
|
({ data, info } = await readSetupRecord(path));
|
|
@@ -213880,11 +213900,11 @@ async function loadSetupSession(origin2, setupId, directory2, now = Date.now())
|
|
|
213880
213900
|
}
|
|
213881
213901
|
async function setupPrivateDirectory(...parts) {
|
|
213882
213902
|
let path = configDirectory();
|
|
213883
|
-
await
|
|
213903
|
+
await mkdir6(path, { recursive: true, mode: 448 });
|
|
213884
213904
|
for (const part of ["", "setup-v1", ...parts]) {
|
|
213885
213905
|
if (part) {
|
|
213886
|
-
path =
|
|
213887
|
-
await
|
|
213906
|
+
path = join6(path, part);
|
|
213907
|
+
await mkdir6(path, { mode: 448 }).catch((error) => {
|
|
213888
213908
|
if (error.code !== "EEXIST")
|
|
213889
213909
|
throw error;
|
|
213890
213910
|
});
|
|
@@ -213895,17 +213915,59 @@ async function setupPrivateDirectory(...parts) {
|
|
|
213895
213915
|
}
|
|
213896
213916
|
return path;
|
|
213897
213917
|
}
|
|
213918
|
+
async function recoverSetupProjectLock(directory2) {
|
|
213919
|
+
const locks = await setupPrivateDirectory("project-locks");
|
|
213920
|
+
const path = join6(locks, `${await setupProjectFingerprint(directory2)}.lock`);
|
|
213921
|
+
let info;
|
|
213922
|
+
try {
|
|
213923
|
+
info = await lstat4(path);
|
|
213924
|
+
} catch (error) {
|
|
213925
|
+
if (error.code === "ENOENT")
|
|
213926
|
+
return false;
|
|
213927
|
+
throw error;
|
|
213928
|
+
}
|
|
213929
|
+
if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1 || info.size > 1024)
|
|
213930
|
+
throw new SetupError("setup_lock_failed", "The project lock needs manual review.");
|
|
213931
|
+
const file = await open6(path, constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0));
|
|
213932
|
+
try {
|
|
213933
|
+
const now = await file.stat();
|
|
213934
|
+
if (now.ino !== info.ino || now.dev !== info.dev)
|
|
213935
|
+
throw new Error("changed lock");
|
|
213936
|
+
const value = JSON.parse(await file.readFile("utf8"));
|
|
213937
|
+
if (!Number.isInteger(value.pid) || value.pid < 1 || typeof value.owner !== "string")
|
|
213938
|
+
throw new Error("invalid lock");
|
|
213939
|
+
try {
|
|
213940
|
+
process.kill(value.pid, 0);
|
|
213941
|
+
throw new SetupError("setup_project_locked", `Another wizard is still running for this project (PID ${value.pid}). Return to its terminal and finish or stop that run before retrying.`);
|
|
213942
|
+
} catch (error) {
|
|
213943
|
+
if (error.code !== "ESRCH")
|
|
213944
|
+
throw error;
|
|
213945
|
+
}
|
|
213946
|
+
return removeSameRecord(path, info);
|
|
213947
|
+
} finally {
|
|
213948
|
+
await file.close();
|
|
213949
|
+
}
|
|
213950
|
+
}
|
|
213898
213951
|
async function withSetupProjectLock(directory2, operation) {
|
|
213899
213952
|
const fingerprint = await setupProjectFingerprint(directory2);
|
|
213900
213953
|
const locks = await setupPrivateDirectory("project-locks");
|
|
213901
|
-
const path =
|
|
213954
|
+
const path = join6(locks, `${fingerprint}.lock`), owner = randomUUID7();
|
|
213902
213955
|
let file;
|
|
213903
213956
|
try {
|
|
213904
|
-
file = await
|
|
213957
|
+
file = await open6(path, "wx", 384);
|
|
213905
213958
|
} catch (error) {
|
|
213906
|
-
if (error.code
|
|
213907
|
-
throw new SetupError("
|
|
213908
|
-
|
|
213959
|
+
if (error.code !== "EEXIST")
|
|
213960
|
+
throw new SetupError("setup_lock_failed", "Unable to lock this project for setup. Check local configuration-directory access.");
|
|
213961
|
+
try {
|
|
213962
|
+
await recoverSetupProjectLock(directory2);
|
|
213963
|
+
file = await open6(path, "wx", 384);
|
|
213964
|
+
} catch (recoveryError) {
|
|
213965
|
+
if (recoveryError instanceof SetupError)
|
|
213966
|
+
throw recoveryError;
|
|
213967
|
+
if (recoveryError.code === "EEXIST")
|
|
213968
|
+
throw new SetupError("setup_project_locked", "Another wizard acquired this project. Return to its terminal and finish or stop that run before retrying.");
|
|
213969
|
+
throw new SetupError("setup_lock_failed", "The existing project lock could not be verified safely. No lock or installation receipt was removed.");
|
|
213970
|
+
}
|
|
213909
213971
|
}
|
|
213910
213972
|
const lockInfo = await file.stat();
|
|
213911
213973
|
try {
|
|
@@ -213923,7 +213985,7 @@ async function withSetupProjectLock(directory2, operation) {
|
|
|
213923
213985
|
}
|
|
213924
213986
|
|
|
213925
213987
|
// node_modules/@userreason/cli/dist/setup.js
|
|
213926
|
-
import { createHash as createHash6, randomBytes, randomUUID as
|
|
213988
|
+
import { createHash as createHash6, randomBytes, randomUUID as randomUUID8 } from "node:crypto";
|
|
213927
213989
|
|
|
213928
213990
|
// node_modules/@userreason/cli/dist/setup-wire.js
|
|
213929
213991
|
var fail = () => {
|
|
@@ -213983,6 +214045,22 @@ var revision = refine(text(1, 19, /^[1-9][0-9]*$/), (value) => BigInt(value) <=
|
|
|
213983
214045
|
var generation = integer(1, 2147483647);
|
|
213984
214046
|
var shortText = (value) => text(1, 240, /^[^\u0000-\u001f\u007f]*$/)(typeof value === "string" ? value.trim() : value);
|
|
213985
214047
|
var identifier = text(1, 80, /^[A-Za-z0-9_-]+$/);
|
|
214048
|
+
var canonicalOrigin = refine(text(1, 2048), (value) => {
|
|
214049
|
+
try {
|
|
214050
|
+
const url = new URL(value);
|
|
214051
|
+
return ["https:", "http:"].includes(url.protocol) && !url.username && !url.password && !url.hostname.includes("*") && url.origin === value;
|
|
214052
|
+
} catch {
|
|
214053
|
+
return false;
|
|
214054
|
+
}
|
|
214055
|
+
});
|
|
214056
|
+
var localRegistry = refine(text(1, 200), (value) => {
|
|
214057
|
+
try {
|
|
214058
|
+
const url = new URL(value);
|
|
214059
|
+
return url.protocol === "http:" && ["127.0.0.1", "localhost", "[::1]"].includes(url.hostname) && !url.username && !url.password && url.pathname === "/" && !url.search && !url.hash;
|
|
214060
|
+
} catch {
|
|
214061
|
+
return false;
|
|
214062
|
+
}
|
|
214063
|
+
});
|
|
213986
214064
|
var relativePath = refine(text(1, 240), (value) => !value.startsWith("/") && !/[\\:\u0000-\u001f\u007f]/.test(value) && value.split("/").every((part) => !["", ".", ".."].includes(part)));
|
|
213987
214065
|
var scope = { schema_version: literal(1), setup_id: uuid2 };
|
|
213988
214066
|
var setupPhases = ["configuring", "awaiting_local_approval", "applying", "ready_for_recommendations", "analyzing", "selecting_drafts", "creating_drafts", "agent_test", "complete", "cancelled", "expired"];
|
|
@@ -213998,7 +214076,9 @@ var parseSetupCapabilities = shape({
|
|
|
213998
214076
|
insert_footer: bool,
|
|
213999
214077
|
source_review: bool,
|
|
214000
214078
|
sample_read: bool,
|
|
214079
|
+
onboarding_v2: optional(bool),
|
|
214001
214080
|
project_name: optional(refine(shortText, (value) => value.length <= 120 && !/[\/\\]/.test(value))),
|
|
214081
|
+
launcher: optional(shape({ wizard_version: text(1, 80, /^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?(?:\+[A-Za-z0-9.-]+)?$/), api_origin: canonicalOrigin, registry: optional(localRegistry) })),
|
|
214002
214082
|
terminal: optional(shape({ platform: oneOf(["macos", "windows", "linux", "other"]), app: oneOf(["apple_terminal", "iterm2", "windows_terminal", "vscode", "cursor", "warp", "ghostty", "wezterm", "alacritty", "kitty", "generic"]) }))
|
|
214003
214083
|
});
|
|
214004
214084
|
var choices = shape({ install_sdk: bool, install_skill: bool, footer_badge: bool });
|
|
@@ -214045,14 +214125,14 @@ function parseSetupLocalPlan(value) {
|
|
|
214045
214125
|
var sampleState = refine(shape({ status: oneOf(["not_started", "waiting", "received", "skipped"]), first_received_at: nullable(timestamp), latest_received_at: nullable(timestamp), latest_request_id: nullable(uuid2) }), (value) => value.first_received_at === null === (value.latest_received_at === null) && value.latest_received_at === null === (value.latest_request_id === null) && (value.status !== "received" || value.first_received_at !== null));
|
|
214046
214126
|
var draftOutcome = refine(shape({ candidate_id: identifier, status: oneOf(["pending", "succeeded", "failed"]), prompt_id: uuid2, request_id: uuid2, revision: nullable(revision), code: nullable(oneOf(resultCodes)) }), (value) => value.status !== "succeeded" || value.revision !== null);
|
|
214047
214127
|
var sourceErrors = ["planning_unavailable", "planning_paused", "planning_daily_budget", "planning_allowance_exhausted", "planning_provider_unavailable", "planning_policy_changed", "planning_consent_expired", "planning_input_budget", "planning_invalid_output", "planning_timeout", "source_changed", "source_unavailable", "recommendations_no_source", "operation_failed"];
|
|
214048
|
-
var sourceState = refine(shape({ preparation_id: uuid2, status: oneOf(["pending", "approved", "analyzing", "ready", "failed", "skipped"]), packet_digest: hash, provider_fingerprint: hash, authorized_at: nullable(timestamp), expires_at: timestamp, error_code: nullable(oneOf(sourceErrors)) }), (value) => (!["approved", "analyzing", "ready"].includes(value.status) || value.authorized_at !== null) && (value.authorized_at === null || Date.parse(value.expires_at) > Date.parse(value.authorized_at) && Date.parse(value.expires_at) - Date.parse(value.authorized_at) <= 6e5));
|
|
214049
|
-
var sourceFile2 = refine(shape({ path: relativePath, file_hash: hash, excerpt_hash: hash, bytes: integer(0,
|
|
214050
|
-
var parseSetupSourceManifest = refine(bounded(shape({ packet_digest: hash, snapshot_id: uuid2, files: array(sourceFile2, 0, 200, (value) => value.path), omitted_files: integer(0, 1e6), truncated: bool, git_included: literal(false) })), (value) => value.files.reduce((sum, file) => sum + file.bytes, 0) <=
|
|
214128
|
+
var sourceState = refine(shape({ preparation_id: uuid2, status: oneOf(["pending", "approved", "analyzing", "ready", "failed", "skipped"]), packet_digest: hash, provider_fingerprint: hash, authorized_at: nullable(timestamp), expires_at: timestamp, error_code: nullable(oneOf(sourceErrors)), analysis_id: optional(uuid2), analysis_started_at: optional(timestamp), analysis_completed_at: optional(timestamp), deadline_at: optional(timestamp), timings: optional(shape({ extraction_ms: optional(integer(0, Number.MAX_SAFE_INTEGER)), consolidation_ms: optional(integer(0, Number.MAX_SAFE_INTEGER)), authoring_ms: optional(integer(0, Number.MAX_SAFE_INTEGER)), total_ms: optional(integer(0, Number.MAX_SAFE_INTEGER)) })) }), (value) => (!["approved", "analyzing", "ready"].includes(value.status) || value.authorized_at !== null) && (!value.deadline_at || Boolean(value.analysis_started_at && Date.parse(value.deadline_at) > Date.parse(value.analysis_started_at) && Date.parse(value.deadline_at) - Date.parse(value.analysis_started_at) <= 24e4)) && (!value.analysis_completed_at || Boolean(value.analysis_started_at && Date.parse(value.analysis_completed_at) >= Date.parse(value.analysis_started_at))) && (value.authorized_at === null || Date.parse(value.expires_at) > Date.parse(value.authorized_at) && Date.parse(value.expires_at) - Date.parse(value.authorized_at) <= 6e5));
|
|
214129
|
+
var sourceFile2 = refine(shape({ path: relativePath, file_hash: hash, excerpt_hash: hash, bytes: integer(0, 262144), start_line: integer(1, Number.MAX_SAFE_INTEGER), end_line: integer(1, Number.MAX_SAFE_INTEGER) }), (value) => value.end_line >= value.start_line);
|
|
214130
|
+
var parseSetupSourceManifest = refine(bounded(shape({ packet_digest: hash, snapshot_id: uuid2, files: array(sourceFile2, 0, 200, (value) => `${value.path}:${value.start_line}:${value.end_line}`), omitted_files: integer(0, 1e6), truncated: bool, git_included: literal(false) })), (value) => value.files.reduce((sum, file) => sum + file.bytes, 0) <= 262144);
|
|
214051
214131
|
var sourcePackage = shape({ name: (value) => text(1, 100)(typeof value === "string" ? value.trim() : value), version: (value) => text(1, 100)(typeof value === "string" ? value.trim() : value) });
|
|
214052
214132
|
var sourcePackages = array(sourcePackage, 0, 30, (value) => value.name);
|
|
214053
214133
|
var evidencePath = refine(text(1, 500), (value) => !value.startsWith("/") && !value.includes("\\") && !value.split("/").some((part) => ["", ".", ".."].includes(part)));
|
|
214054
|
-
var sourceEvidence = refine(shape({ kind: literal("local_source"), id: identifier, path: evidencePath, file_hash: hash, excerpt_hash: hash, snapshot_id: uuid2, start_line: integer(1, Number.MAX_SAFE_INTEGER), end_line: integer(1, Number.MAX_SAFE_INTEGER), excerpt: text(0,
|
|
214055
|
-
var planningLimits = shape({ input_tokens: integer(256,
|
|
214134
|
+
var sourceEvidence = refine(shape({ kind: literal("local_source"), id: identifier, path: evidencePath, file_hash: hash, excerpt_hash: hash, snapshot_id: uuid2, start_line: integer(1, Number.MAX_SAFE_INTEGER), end_line: integer(1, Number.MAX_SAFE_INTEGER), excerpt: text(0, 3e4) }), (value) => value.end_line >= value.start_line && value.excerpt.split("\n").length === value.end_line - value.start_line + 1);
|
|
214135
|
+
var planningLimits = shape({ input_tokens: integer(256, 262144), output_tokens: integer(256, 32768), deadline_ms: integer(1e3, 24e4) });
|
|
214056
214136
|
var providerDestination = refine(text(1, 200), (value) => {
|
|
214057
214137
|
try {
|
|
214058
214138
|
const url = new URL(value);
|
|
@@ -214112,7 +214192,7 @@ var parseSetupPollInput = shape(scope);
|
|
|
214112
214192
|
var parseSetupLocalPlanInput = bounded(shape({ ...scope, request_id: uuid2, expected_revision: revision, plan: localPlan }));
|
|
214113
214193
|
var parseSetupSourceInfoInput = shape(scope);
|
|
214114
214194
|
var parseSetupSourcePlanInput = refine(bounded(shape({ ...scope, request_id: uuid2, expected_revision: revision, manifest: parseSetupSourceManifest, packages: sourcePackages })), (value) => value.request_id === value.manifest.snapshot_id);
|
|
214115
|
-
var parseSetupSourceUploadInput = refine(
|
|
214195
|
+
var parseSetupSourceUploadInput = refine(shape({ ...scope, preparation_id: uuid2, project_fingerprint: hash, evidence: array(sourceEvidence, 0, 220, (value) => value.id) }), (value) => Buffer.byteLength(JSON.stringify(value)) <= 3e5 && new Set(value.evidence.map((item) => `${item.path}:${item.start_line}:${item.end_line}`)).size === value.evidence.length && Buffer.byteLength(JSON.stringify(value.evidence)) <= 262144 && value.evidence.every((item) => item.snapshot_id === value.preparation_id));
|
|
214116
214196
|
var parseSetupSourceInfo = refine(bounded(shape({ schema_version: literal(1), session: parseSetupSession, preparation: nullable(shape({ preparation_id: uuid2, manifest: parseSetupSourceManifest, packages: sourcePackages, configuration: planningConfiguration })) })), (value) => value.preparation === null || value.preparation.preparation_id === value.preparation.manifest.snapshot_id);
|
|
214117
214197
|
var parseSetupClaimInput = shape({ ...scope, request_id: uuid2, executor_generation: generation });
|
|
214118
214198
|
var parseSetupClaimResult = bounded(shape({ schema_version: literal(1), command: nullable(command), session: parseSetupSession }));
|
|
@@ -214196,7 +214276,7 @@ async function request(origin2, operation, body, token, options, retries = 0) {
|
|
|
214196
214276
|
if (!["discovery", "start", "exchange", "poll", "plan", "claim", "start-command", "report", "heartbeat", "reconcile", "sample-read", "source-info", "source-plan", "source-upload"].includes(operation))
|
|
214197
214277
|
throw new SetupError("invalid_setup_operation", "Unsupported setup operation.");
|
|
214198
214278
|
const encoded = body === void 0 ? void 0 : JSON.stringify(body);
|
|
214199
|
-
if (encoded && Buffer.byteLength(encoded) > 65536)
|
|
214279
|
+
if (encoded && Buffer.byteLength(encoded) > (operation === "source-upload" ? 3e5 : 65536))
|
|
214200
214280
|
throw new SetupError("setup_request_too_large", "Setup request exceeds 64 KiB.");
|
|
214201
214281
|
const url = `${apiUrl(origin2)}${operation === "discovery" ? "/onboarding/v1/auth-config?setup=1" : `/onboarding/v1/setup/${operation}`}`;
|
|
214202
214282
|
const measurementDisabled = options.measurementDisabled === true || !await telemetryEnabled().catch(() => false);
|
|
@@ -214209,7 +214289,7 @@ async function request(origin2, operation, body, token, options, retries = 0) {
|
|
|
214209
214289
|
redirect: "error",
|
|
214210
214290
|
headers: { Accept: "application/json", ...encoded === void 0 ? {} : { "Content-Type": "application/json" }, ...token ? { Authorization: `Bearer ${token}` } : {}, ...measurementDisabled ? { "x-ur-measurement-disabled": "1" } : {} },
|
|
214211
214291
|
...encoded === void 0 ? {} : { body: encoded },
|
|
214212
|
-
signal: AbortSignal.any([AbortSignal.timeout(operation === "source-upload" ?
|
|
214292
|
+
signal: AbortSignal.any([AbortSignal.timeout(operation === "source-upload" ? 25e4 : 1e4), ...options.signal ? [options.signal] : []])
|
|
214213
214293
|
});
|
|
214214
214294
|
} catch (error) {
|
|
214215
214295
|
options.signal?.throwIfAborted();
|
|
@@ -214296,7 +214376,9 @@ async function finishBrowserSetup(pending, options) {
|
|
|
214296
214376
|
throw new SetupError("invalid_setup_response", "The approved setup response does not match this project or active session.");
|
|
214297
214377
|
const connected = { schema_version: 1, state: "connected", setup_id: pending.setup_id, api_url: pending.api_url, project_fingerprint: pending.project_fingerprint, created_at: new Date(now()).toISOString(), expires_at: result.expires_at, access_token: result.access_token };
|
|
214298
214378
|
await saveSetupSession(connected);
|
|
214299
|
-
|
|
214379
|
+
const client = new BrowserSetupClient(connected, options);
|
|
214380
|
+
const session2 = await client.heartbeat({ schema_version: 1, setup_id: connected.setup_id, executor_generation: result.session.executor_generation, operation_id: null, lease_generation: null });
|
|
214381
|
+
return { client, session: session2 };
|
|
214300
214382
|
}
|
|
214301
214383
|
options.onProgress?.("waiting");
|
|
214302
214384
|
await delay(Math.max(0, Math.min(2e3, deadline - now())), options);
|
|
@@ -214308,9 +214390,11 @@ async function resumeBrowserSetup(origin2, setupId, directory2, options = {}) {
|
|
|
214308
214390
|
if (saved.state === "pending")
|
|
214309
214391
|
return finishBrowserSetup(saved, options);
|
|
214310
214392
|
const client = new BrowserSetupClient(saved, options);
|
|
214311
|
-
|
|
214393
|
+
const current = await client.poll();
|
|
214394
|
+
const session2 = terminal.has(current.phase) ? current : await client.heartbeat({ schema_version: 1, setup_id: saved.setup_id, executor_generation: current.executor_generation, operation_id: null, lease_generation: null });
|
|
214395
|
+
return { client, session: session2 };
|
|
214312
214396
|
}
|
|
214313
|
-
var BrowserSetupClient = class {
|
|
214397
|
+
var BrowserSetupClient = class _BrowserSetupClient {
|
|
214314
214398
|
#stored;
|
|
214315
214399
|
#options;
|
|
214316
214400
|
constructor(stored, options = {}) {
|
|
@@ -214325,6 +214409,10 @@ var BrowserSetupClient = class {
|
|
|
214325
214409
|
const { setup_id, api_url, project_fingerprint, expires_at } = this.#stored;
|
|
214326
214410
|
return { setup_id, api_url, project_fingerprint, expires_at };
|
|
214327
214411
|
}
|
|
214412
|
+
/** Share the same saved capability while binding requests to one run's lifetime. */
|
|
214413
|
+
withSignal(signal) {
|
|
214414
|
+
return new _BrowserSetupClient(this.#stored, { ...this.#options, signal: AbortSignal.any([signal, ...this.#options.signal ? [this.#options.signal] : []]) });
|
|
214415
|
+
}
|
|
214328
214416
|
async call(operation, body, retries = 0) {
|
|
214329
214417
|
if (Date.parse(this.#stored.expires_at) <= (this.#options.now ?? Date.now)())
|
|
214330
214418
|
throw new SetupError("setup_expired", "Setup access expired. Start a new setup; it cannot be refreshed into ordinary CLI access.");
|
|
@@ -214395,7 +214483,7 @@ var BrowserSetupClient = class {
|
|
|
214395
214483
|
this.scoped(body);
|
|
214396
214484
|
return this.view(await this.call("reconcile", body));
|
|
214397
214485
|
}
|
|
214398
|
-
async sample(requestId =
|
|
214486
|
+
async sample(requestId = randomUUID8()) {
|
|
214399
214487
|
const active = await this.poll();
|
|
214400
214488
|
if (active.phase !== "agent_test" || !["waiting", "received"].includes(active.sample.status))
|
|
214401
214489
|
throw new SetupError("setup_sample_unavailable", "This setup is not waiting for its optional sample read. Open that step in the browser first.");
|
|
@@ -214406,17 +214494,177 @@ var BrowserSetupClient = class {
|
|
|
214406
214494
|
}
|
|
214407
214495
|
};
|
|
214408
214496
|
|
|
214497
|
+
// node_modules/@userreason/cli/dist/setup-diagnostics.js
|
|
214498
|
+
function sanitizeSetupDiagnostic(value, secrets = []) {
|
|
214499
|
+
let text2 = value.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "").replace(/[\x00-\x08\x0b-\x1f\x7f]/g, "");
|
|
214500
|
+
const environmentSecrets = Object.entries(process.env).filter(([key, value2]) => /token|secret|password|api[_-]?key|authorization/i.test(key) && value2 && value2.length >= 4).map(([, value2]) => value2);
|
|
214501
|
+
for (const secret2 of [...secrets, ...environmentSecrets].filter((value2) => value2.length >= 4).sort((a, b) => b.length - a.length))
|
|
214502
|
+
text2 = text2.split(secret2).join("[redacted]");
|
|
214503
|
+
text2 = text2.replace(/\b(Bearer|Basic)\s+[^\s]+/gi, "$1 [redacted]");
|
|
214504
|
+
text2 = text2.replace(/((?:_authToken|_password|password|access_token|refresh_token|api_key|authorization)\s*[:=]\s*)[^\s]+/gi, "$1[redacted]");
|
|
214505
|
+
text2 = text2.replace(/\b(?:gh[pousr]_[A-Za-z0-9_]+|github_pat_[A-Za-z0-9_]+|npm_[A-Za-z0-9]+|sk-[A-Za-z0-9_-]{16,})\b/g, "[redacted]");
|
|
214506
|
+
text2 = text2.replace(/https?:\/\/[^\s<>"']+/g, (value2) => {
|
|
214507
|
+
try {
|
|
214508
|
+
const url = new URL(value2);
|
|
214509
|
+
url.username = "";
|
|
214510
|
+
url.password = "";
|
|
214511
|
+
url.search = "";
|
|
214512
|
+
url.hash = "";
|
|
214513
|
+
return url.toString();
|
|
214514
|
+
} catch {
|
|
214515
|
+
return "[invalid URL]";
|
|
214516
|
+
}
|
|
214517
|
+
});
|
|
214518
|
+
return text2.trim().slice(0, 8e3);
|
|
214519
|
+
}
|
|
214520
|
+
|
|
214409
214521
|
// node_modules/@userreason/cli/dist/setup-executor.js
|
|
214410
|
-
import { randomUUID as
|
|
214411
|
-
import { constants as
|
|
214412
|
-
import { lstat as lstat6, open as
|
|
214413
|
-
import { join as
|
|
214522
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
214523
|
+
import { constants as constants4 } from "node:fs";
|
|
214524
|
+
import { lstat as lstat6, open as open8, opendir as opendir2, rename as rename5, rm as rm4 } from "node:fs/promises";
|
|
214525
|
+
import { join as join8 } from "node:path";
|
|
214526
|
+
|
|
214527
|
+
// node_modules/@userreason/cli/dist/setup-heartbeat.js
|
|
214528
|
+
var terminal2 = /* @__PURE__ */ new Set(["complete", "cancelled", "expired"]);
|
|
214529
|
+
function setupAbortable(work, signal) {
|
|
214530
|
+
if (!signal)
|
|
214531
|
+
return work;
|
|
214532
|
+
signal.throwIfAborted();
|
|
214533
|
+
return new Promise((resolve3, reject) => {
|
|
214534
|
+
const abort = () => reject(signal.reason);
|
|
214535
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
214536
|
+
work.then(resolve3, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
214537
|
+
});
|
|
214538
|
+
}
|
|
214539
|
+
var SetupHeartbeat = class {
|
|
214540
|
+
client;
|
|
214541
|
+
options;
|
|
214542
|
+
session;
|
|
214543
|
+
timer;
|
|
214544
|
+
pending;
|
|
214545
|
+
stopped = false;
|
|
214546
|
+
paused = 0;
|
|
214547
|
+
failure;
|
|
214548
|
+
lease;
|
|
214549
|
+
lifetime = new AbortController();
|
|
214550
|
+
signal;
|
|
214551
|
+
constructor(client, options = {}) {
|
|
214552
|
+
this.client = client;
|
|
214553
|
+
this.options = options;
|
|
214554
|
+
this.signal = AbortSignal.any([this.lifetime.signal, ...options.signal ? [options.signal] : []]);
|
|
214555
|
+
}
|
|
214556
|
+
observe(next) {
|
|
214557
|
+
const current = this.session;
|
|
214558
|
+
if (!current || BigInt(next.revision) >= BigInt(current.revision)) {
|
|
214559
|
+
const heartbeat = current?.heartbeat_at && (!next.heartbeat_at || Date.parse(current.heartbeat_at) > Date.parse(next.heartbeat_at)) ? current.heartbeat_at : next.heartbeat_at;
|
|
214560
|
+
this.session = { ...next, heartbeat_at: heartbeat };
|
|
214561
|
+
}
|
|
214562
|
+
if (terminal2.has(this.session.phase) && !this.signal.aborted)
|
|
214563
|
+
this.lifetime.abort(new Error("Setup ended"));
|
|
214564
|
+
if (!this.stopped && !this.timer && !this.pending && !this.paused && !terminal2.has(this.session.phase))
|
|
214565
|
+
this.schedule(0);
|
|
214566
|
+
return this.session;
|
|
214567
|
+
}
|
|
214568
|
+
get current() {
|
|
214569
|
+
return this.session;
|
|
214570
|
+
}
|
|
214571
|
+
setLease(lease) {
|
|
214572
|
+
this.lease = lease;
|
|
214573
|
+
}
|
|
214574
|
+
latest(fallback) {
|
|
214575
|
+
return this.observe(fallback);
|
|
214576
|
+
}
|
|
214577
|
+
check() {
|
|
214578
|
+
this.options.signal?.throwIfAborted();
|
|
214579
|
+
if (this.failure)
|
|
214580
|
+
throw this.failure;
|
|
214581
|
+
}
|
|
214582
|
+
schedule(delay2 = this.options.heartbeatMs ?? 1e4) {
|
|
214583
|
+
if (this.stopped || this.paused || !this.session || terminal2.has(this.session.phase) || this.signal.aborted)
|
|
214584
|
+
return;
|
|
214585
|
+
this.timer = setTimeout(() => {
|
|
214586
|
+
this.timer = void 0;
|
|
214587
|
+
void this.pulse();
|
|
214588
|
+
}, delay2);
|
|
214589
|
+
}
|
|
214590
|
+
async pulse() {
|
|
214591
|
+
if (this.pending)
|
|
214592
|
+
return this.pending;
|
|
214593
|
+
if (this.stopped || this.paused || this.signal.aborted || !this.session || terminal2.has(this.session.phase))
|
|
214594
|
+
return;
|
|
214595
|
+
if (this.timer) {
|
|
214596
|
+
clearTimeout(this.timer);
|
|
214597
|
+
this.timer = void 0;
|
|
214598
|
+
}
|
|
214599
|
+
const session2 = this.session;
|
|
214600
|
+
this.pending = setupAbortable(this.client.heartbeat({
|
|
214601
|
+
schema_version: 1,
|
|
214602
|
+
setup_id: this.client.identity.setup_id,
|
|
214603
|
+
executor_generation: session2.executor_generation,
|
|
214604
|
+
operation_id: this.lease?.operation_id ?? null,
|
|
214605
|
+
lease_generation: this.lease?.lease_generation ?? null
|
|
214606
|
+
}), this.signal).then((value) => {
|
|
214607
|
+
this.observe(value);
|
|
214608
|
+
}).catch((error) => {
|
|
214609
|
+
if (!this.stopped && !this.options.signal?.aborted) {
|
|
214610
|
+
this.failure = error;
|
|
214611
|
+
this.lifetime.abort(error);
|
|
214612
|
+
}
|
|
214613
|
+
}).finally(() => {
|
|
214614
|
+
this.pending = void 0;
|
|
214615
|
+
this.schedule();
|
|
214616
|
+
});
|
|
214617
|
+
return this.pending;
|
|
214618
|
+
}
|
|
214619
|
+
/** Finish the old lease's in-flight heartbeat before closing it in a report. */
|
|
214620
|
+
async duringReport(operation) {
|
|
214621
|
+
this.paused++;
|
|
214622
|
+
if (this.timer) {
|
|
214623
|
+
clearTimeout(this.timer);
|
|
214624
|
+
this.timer = void 0;
|
|
214625
|
+
}
|
|
214626
|
+
try {
|
|
214627
|
+
await this.pending;
|
|
214628
|
+
this.lease = void 0;
|
|
214629
|
+
return await operation();
|
|
214630
|
+
} finally {
|
|
214631
|
+
this.paused--;
|
|
214632
|
+
this.schedule();
|
|
214633
|
+
}
|
|
214634
|
+
}
|
|
214635
|
+
async stop() {
|
|
214636
|
+
this.stopped = true;
|
|
214637
|
+
if (this.timer)
|
|
214638
|
+
clearTimeout(this.timer);
|
|
214639
|
+
this.lifetime.abort(new Error("Setup run ended"));
|
|
214640
|
+
await this.pending;
|
|
214641
|
+
}
|
|
214642
|
+
};
|
|
214643
|
+
function observeSetupClient(client, heartbeat, signal) {
|
|
214644
|
+
return new Proxy(client, { get(target, key, receiver) {
|
|
214645
|
+
const value = Reflect.get(target, key, target);
|
|
214646
|
+
if (typeof value !== "function")
|
|
214647
|
+
return value;
|
|
214648
|
+
if (key === "withSignal")
|
|
214649
|
+
return value.bind(target);
|
|
214650
|
+
return async (...args) => {
|
|
214651
|
+
if (key !== "report")
|
|
214652
|
+
signal?.throwIfAborted();
|
|
214653
|
+
const requestSignal = ["poll", "discovery", "sourceInfo", "sourceUpload"].includes(String(key)) ? signal : void 0;
|
|
214654
|
+
const result = await setupAbortable(Reflect.apply(value, target, args), requestSignal);
|
|
214655
|
+
const view = result && typeof result === "object" && "session" in result ? result.session : result;
|
|
214656
|
+
if (view && typeof view === "object" && "phase" in view && "revision" in view && typeof view.phase === "string" && typeof view.revision === "string")
|
|
214657
|
+
heartbeat.observe(view);
|
|
214658
|
+
return result;
|
|
214659
|
+
};
|
|
214660
|
+
} });
|
|
214661
|
+
}
|
|
214414
214662
|
|
|
214415
214663
|
// node_modules/@userreason/cli/dist/setup-files.js
|
|
214416
214664
|
import { createHash as createHash7 } from "node:crypto";
|
|
214417
|
-
import { constants as
|
|
214418
|
-
import { lstat as lstat5, mkdir as
|
|
214419
|
-
import { join as
|
|
214665
|
+
import { constants as constants3 } from "node:fs";
|
|
214666
|
+
import { lstat as lstat5, mkdir as mkdir7, open as open7, realpath as realpath3 } from "node:fs/promises";
|
|
214667
|
+
import { join as join7, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
214420
214668
|
var setupHash = (value) => createHash7("sha256").update(value).digest("hex");
|
|
214421
214669
|
function setupCanonical(value) {
|
|
214422
214670
|
if (Array.isArray(value))
|
|
@@ -214435,14 +214683,14 @@ async function checkedPath(directory2, name, createParents = false) {
|
|
|
214435
214683
|
throw new SetupError("setup_path_unsafe", "The reviewed path escapes the project.");
|
|
214436
214684
|
let parent = root;
|
|
214437
214685
|
for (const part of name.split("/").slice(0, -1)) {
|
|
214438
|
-
parent =
|
|
214686
|
+
parent = join7(parent, part);
|
|
214439
214687
|
let info = await lstat5(parent).catch((error) => {
|
|
214440
214688
|
if (error.code === "ENOENT")
|
|
214441
214689
|
return null;
|
|
214442
214690
|
throw error;
|
|
214443
214691
|
});
|
|
214444
214692
|
if (!info && createParents) {
|
|
214445
|
-
await
|
|
214693
|
+
await mkdir7(parent);
|
|
214446
214694
|
info = await lstat5(parent);
|
|
214447
214695
|
}
|
|
214448
214696
|
if (!info)
|
|
@@ -214464,15 +214712,15 @@ async function readSetupFile(directory2, path) {
|
|
|
214464
214712
|
}
|
|
214465
214713
|
if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1 || before.size > 2e6)
|
|
214466
214714
|
throw new SetupError("setup_path_unsafe", "A reviewed file is not a bounded ordinary file.");
|
|
214467
|
-
const handle = await
|
|
214715
|
+
const handle = await open7(target, constants3.O_RDONLY | (constants3.O_NOFOLLOW ?? 0));
|
|
214468
214716
|
try {
|
|
214469
214717
|
const current = await handle.stat();
|
|
214470
214718
|
if (before.dev !== current.dev || before.ino !== current.ino || current.nlink !== 1 || current.size > 2e6)
|
|
214471
214719
|
throw new SetupError("setup_path_unsafe", "A reviewed file changed while reading.");
|
|
214472
|
-
const
|
|
214473
|
-
if (
|
|
214720
|
+
const bytes2 = await handle.readFile();
|
|
214721
|
+
if (bytes2.length > 2e6)
|
|
214474
214722
|
throw new SetupError("setup_path_unsafe", "A reviewed file exceeds the size limit.");
|
|
214475
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(
|
|
214723
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes2);
|
|
214476
214724
|
} finally {
|
|
214477
214725
|
await handle.close();
|
|
214478
214726
|
}
|
|
@@ -214486,7 +214734,7 @@ async function writeSetupFile(directory2, file) {
|
|
|
214486
214734
|
if (file.before === file.after)
|
|
214487
214735
|
return;
|
|
214488
214736
|
const info = file.before === null ? null : await lstat5(target);
|
|
214489
|
-
const handle = await
|
|
214737
|
+
const handle = await open7(target, info ? constants3.O_WRONLY | (constants3.O_NOFOLLOW ?? 0) : constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | (constants3.O_NOFOLLOW ?? 0), 420);
|
|
214490
214738
|
try {
|
|
214491
214739
|
const now = await handle.stat();
|
|
214492
214740
|
if (!now.isFile() || now.nlink !== 1 || info && (now.dev !== info.dev || now.ino !== info.ino))
|
|
@@ -214508,7 +214756,7 @@ async function verifySetupFiles(directory2, files2, state) {
|
|
|
214508
214756
|
}
|
|
214509
214757
|
|
|
214510
214758
|
// node_modules/@userreason/cli/dist/setup-executor.js
|
|
214511
|
-
var
|
|
214759
|
+
var terminal3 = /* @__PURE__ */ new Set(["complete", "cancelled", "expired"]);
|
|
214512
214760
|
var stopped = /* @__PURE__ */ new Set(["ready_for_recommendations", "analyzing", "selecting_drafts", "creating_drafts", "agent_test"]);
|
|
214513
214761
|
var limit = 8e6;
|
|
214514
214762
|
var retention = 7 * 864e5;
|
|
@@ -214539,27 +214787,27 @@ function validatePrepared(value) {
|
|
|
214539
214787
|
async function journalPath(client) {
|
|
214540
214788
|
const directory2 = await setupPrivateDirectory("receipts");
|
|
214541
214789
|
await pruneSetupExecutionReceipts();
|
|
214542
|
-
return
|
|
214790
|
+
return join8(directory2, `${setupHash(`${client.identity.api_url}
|
|
214543
214791
|
${client.identity.setup_id}`)}.json`);
|
|
214544
214792
|
}
|
|
214545
214793
|
async function pruneSetupExecutionReceipts(now = Date.now()) {
|
|
214546
214794
|
const directory2 = await setupPrivateDirectory("receipts");
|
|
214547
|
-
let removed = 0, scanned = 0,
|
|
214795
|
+
let removed = 0, scanned = 0, bytes2 = 0;
|
|
214548
214796
|
for await (const entry of await opendir2(directory2)) {
|
|
214549
214797
|
if (++scanned > 128)
|
|
214550
214798
|
break;
|
|
214551
214799
|
if (!entry.isFile() || !/^[a-f0-9]{64}\.json$/.test(entry.name))
|
|
214552
214800
|
continue;
|
|
214553
|
-
const path =
|
|
214801
|
+
const path = join8(directory2, entry.name);
|
|
214554
214802
|
let handle;
|
|
214555
214803
|
try {
|
|
214556
214804
|
const info = await lstat6(path);
|
|
214557
214805
|
if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1 || info.size > limit)
|
|
214558
214806
|
continue;
|
|
214559
|
-
|
|
214560
|
-
if (
|
|
214807
|
+
bytes2 += info.size;
|
|
214808
|
+
if (bytes2 > 16e6)
|
|
214561
214809
|
break;
|
|
214562
|
-
handle = await
|
|
214810
|
+
handle = await open8(path, constants4.O_RDONLY | (constants4.O_NOFOLLOW ?? 0));
|
|
214563
214811
|
const opened = await handle.stat();
|
|
214564
214812
|
if (opened.ino !== info.ino || opened.dev !== info.dev)
|
|
214565
214813
|
continue;
|
|
@@ -214589,7 +214837,7 @@ function validateJournal(data, identity, active = true) {
|
|
|
214589
214837
|
if (data.plan)
|
|
214590
214838
|
data.plan = validatePrepared(data.plan);
|
|
214591
214839
|
for (const [operationId, receipt] of Object.entries(data.receipts)) {
|
|
214592
|
-
if (!uuid3(operationId) || !receipt || typeof receipt !== "object" || Array.isArray(receipt) || Object.keys(receipt).some((key) => !["input_digest", "stage", "outcome", "outputs", "request_id"].includes(key)) || !/^[a-f0-9]{64}$/.test(receipt.input_digest) || !["claimed", "running", "settled"].includes(receipt.stage) || !uuid3(receipt.request_id) || receipt.stage === "settled" !== Boolean(receipt.outcome))
|
|
214840
|
+
if (!uuid3(operationId) || !receipt || typeof receipt !== "object" || Array.isArray(receipt) || Object.keys(receipt).some((key) => !["input_digest", "stage", "outcome", "diagnostic", "outputs", "request_id"].includes(key)) || receipt.diagnostic !== void 0 && (typeof receipt.diagnostic !== "string" || receipt.diagnostic.length > 8e3) || !/^[a-f0-9]{64}$/.test(receipt.input_digest) || !["claimed", "running", "settled"].includes(receipt.stage) || !uuid3(receipt.request_id) || receipt.stage === "settled" !== Boolean(receipt.outcome))
|
|
214593
214841
|
throw new Error("invalid operation receipt");
|
|
214594
214842
|
const operation = data.plan?.operations.find((item) => setupDigest(item.effect) === receipt.input_digest);
|
|
214595
214843
|
if (!operation)
|
|
@@ -214614,19 +214862,19 @@ async function loadJournal(path, client) {
|
|
|
214614
214862
|
const info = await lstat6(path);
|
|
214615
214863
|
if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1 || info.size > limit)
|
|
214616
214864
|
throw new Error("unsafe receipt");
|
|
214617
|
-
handle = await
|
|
214865
|
+
handle = await open8(path, constants4.O_RDONLY | (constants4.O_NOFOLLOW ?? 0));
|
|
214618
214866
|
const current = await handle.stat();
|
|
214619
214867
|
if (info.ino !== current.ino || info.dev !== current.dev || current.size > limit)
|
|
214620
214868
|
throw new Error("changed receipt");
|
|
214621
|
-
const
|
|
214622
|
-
if (
|
|
214869
|
+
const bytes2 = await handle.readFile();
|
|
214870
|
+
if (bytes2.length > limit)
|
|
214623
214871
|
throw new Error("large receipt");
|
|
214624
|
-
const data = JSON.parse(
|
|
214872
|
+
const data = JSON.parse(bytes2.toString());
|
|
214625
214873
|
return validateJournal(data, client.identity);
|
|
214626
214874
|
} catch (error) {
|
|
214627
214875
|
if (error.code === "ENOENT") {
|
|
214628
214876
|
const now = Date.now();
|
|
214629
|
-
return { version: 1, setup_id: client.identity.setup_id, api_url: client.identity.api_url, project_fingerprint: client.identity.project_fingerprint, created_at: new Date(now).toISOString(), retain_until: new Date(now + retention).toISOString(), plan_request_id:
|
|
214877
|
+
return { version: 1, setup_id: client.identity.setup_id, api_url: client.identity.api_url, project_fingerprint: client.identity.project_fingerprint, created_at: new Date(now).toISOString(), retain_until: new Date(now + retention).toISOString(), plan_request_id: randomUUID9(), claim_request_id: randomUUID9(), receipts: {} };
|
|
214630
214878
|
}
|
|
214631
214879
|
throw new SetupError("setup_receipt_invalid", "The local receipt needs review. No local effects were repeated.");
|
|
214632
214880
|
} finally {
|
|
@@ -214637,16 +214885,16 @@ async function saveJournal(path, journal) {
|
|
|
214637
214885
|
const contents = JSON.stringify(journal);
|
|
214638
214886
|
if (Buffer.byteLength(contents) > limit)
|
|
214639
214887
|
throw new SetupError("setup_plan_too_large", "The prepared local plan exceeds the private receipt limit.");
|
|
214640
|
-
const temporary = `${path}.${
|
|
214888
|
+
const temporary = `${path}.${randomUUID9()}.tmp`;
|
|
214641
214889
|
try {
|
|
214642
|
-
const handle = await
|
|
214890
|
+
const handle = await open8(temporary, "wx", 384);
|
|
214643
214891
|
try {
|
|
214644
214892
|
await handle.writeFile(contents);
|
|
214645
214893
|
await handle.sync();
|
|
214646
214894
|
} finally {
|
|
214647
214895
|
await handle.close();
|
|
214648
214896
|
}
|
|
214649
|
-
await
|
|
214897
|
+
await rename5(temporary, path);
|
|
214650
214898
|
} finally {
|
|
214651
214899
|
await rm4(temporary, { force: true }).catch(() => {
|
|
214652
214900
|
});
|
|
@@ -214669,167 +214917,176 @@ async function verified(directory2, operation, runtime, receipt) {
|
|
|
214669
214917
|
return false;
|
|
214670
214918
|
return runtime.verify ? runtime.verify(operation) : operation.effect.kind !== "install_packages";
|
|
214671
214919
|
}
|
|
214672
|
-
async function runSetupExecutor(client, directory2, runtime, options = {}) {
|
|
214920
|
+
async function runSetupExecutor(client, directory2, runtime, options = {}, sharedHeartbeat) {
|
|
214673
214921
|
if (await setupProjectFingerprint(directory2) !== client.identity.project_fingerprint)
|
|
214674
214922
|
throw new SetupError("setup_binding_mismatch", "This executor belongs to another project.");
|
|
214675
|
-
|
|
214676
|
-
|
|
214677
|
-
|
|
214678
|
-
|
|
214679
|
-
|
|
214680
|
-
|
|
214681
|
-
|
|
214682
|
-
|
|
214683
|
-
|
|
214684
|
-
|
|
214685
|
-
|
|
214686
|
-
|
|
214687
|
-
|
|
214923
|
+
const heartbeat = sharedHeartbeat ?? new SetupHeartbeat(client, options);
|
|
214924
|
+
client = observeSetupClient(client, heartbeat, options.signal);
|
|
214925
|
+
try {
|
|
214926
|
+
return await withSetupProjectLock(directory2, async () => {
|
|
214927
|
+
const path = await journalPath(client), journal = await loadJournal(path, client);
|
|
214928
|
+
const shownErrors = /* @__PURE__ */ new Set();
|
|
214929
|
+
const showError = (id, receipt) => {
|
|
214930
|
+
if (!receipt.diagnostic || shownErrors.has(id))
|
|
214931
|
+
return;
|
|
214932
|
+
const operation = journal.plan?.operations.find((item) => setupDigest(item.effect) === receipt.input_digest);
|
|
214933
|
+
if (!operation)
|
|
214934
|
+
return;
|
|
214935
|
+
shownErrors.add(id);
|
|
214936
|
+
try {
|
|
214937
|
+
options.onOperationError?.({ kind: operation.effect.kind, message: sanitizeSetupDiagnostic(receipt.diagnostic), receiptPath: path });
|
|
214938
|
+
} catch {
|
|
214939
|
+
}
|
|
214940
|
+
};
|
|
214941
|
+
for (const [id, receipt] of Object.entries(journal.receipts))
|
|
214942
|
+
showError(id, receipt);
|
|
214943
|
+
let session2 = await client.poll(), polls = 0;
|
|
214944
|
+
const scope2 = { schema_version: 1, setup_id: client.identity.setup_id };
|
|
214945
|
+
const pause2 = async () => {
|
|
214946
|
+
if (options.sleep)
|
|
214947
|
+
await options.sleep(options.pollMs ?? 2e3);
|
|
214948
|
+
else
|
|
214949
|
+
await new Promise((resolve3, reject) => {
|
|
214950
|
+
const timer = setTimeout(done, options.pollMs ?? 2e3);
|
|
214951
|
+
function done() {
|
|
214952
|
+
options.signal?.removeEventListener("abort", abort);
|
|
214953
|
+
resolve3();
|
|
214954
|
+
}
|
|
214955
|
+
function abort() {
|
|
214956
|
+
clearTimeout(timer);
|
|
214957
|
+
reject(options.signal?.reason);
|
|
214958
|
+
}
|
|
214959
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
214960
|
+
});
|
|
214961
|
+
};
|
|
214962
|
+
while (true) {
|
|
214963
|
+
heartbeat.check();
|
|
214964
|
+
session2 = heartbeat.latest(session2);
|
|
214965
|
+
options.onSession?.(session2);
|
|
214966
|
+
if (terminal3.has(session2.phase) || stopped.has(session2.phase) || options.maxPolls !== void 0 && polls++ >= options.maxPolls) {
|
|
214967
|
+
if (session2.phase === "cancelled") {
|
|
214968
|
+
const known = session2.commands.find((command3) => command3.status === "running" && journal.receipts[command3.operation_id]?.outcome);
|
|
214969
|
+
if (known)
|
|
214970
|
+
session2 = await client.report({ ...scope2, operation_id: known.operation_id, executor_generation: known.executor_generation, lease_generation: known.lease_generation, ...journal.receipts[known.operation_id].outcome });
|
|
214971
|
+
}
|
|
214972
|
+
return session2;
|
|
214973
|
+
}
|
|
214974
|
+
if (session2.phase === "configuring") {
|
|
214975
|
+
if (!session2.site_id || !session2.workspace_id) {
|
|
214976
|
+
await heartbeat.pulse();
|
|
214977
|
+
heartbeat.check();
|
|
214978
|
+
session2 = heartbeat.latest(session2);
|
|
214979
|
+
await pause2();
|
|
214980
|
+
session2 = await client.poll();
|
|
214981
|
+
continue;
|
|
214688
214982
|
}
|
|
214689
|
-
|
|
214690
|
-
|
|
214691
|
-
|
|
214983
|
+
const targetDigest = setupDigest({ workspace_id: session2.workspace_id, site_id: session2.site_id, api_url: client.identity.api_url });
|
|
214984
|
+
if (!journal.plan || journal.plan.wire.choices_digest !== setupDigest(session2.choices) || journal.target_digest !== targetDigest) {
|
|
214985
|
+
if (Object.keys(journal.receipts).length)
|
|
214986
|
+
throw new SetupError("setup_plan_changed", "A completed local plan cannot be replaced without a new setup.");
|
|
214987
|
+
journal.plan = validatePrepared(await setupAbortable(runtime.prepare(session2), heartbeat.signal));
|
|
214988
|
+
journal.target_digest = targetDigest;
|
|
214989
|
+
journal.plan_request_id = randomUUID9();
|
|
214990
|
+
await saveJournal(path, journal);
|
|
214692
214991
|
}
|
|
214693
|
-
|
|
214694
|
-
|
|
214695
|
-
|
|
214696
|
-
|
|
214697
|
-
|
|
214698
|
-
|
|
214699
|
-
|
|
214700
|
-
|
|
214701
|
-
const known = session2.commands.find((command3) => command3.status === "running" && journal.receipts[command3.operation_id]?.outcome);
|
|
214702
|
-
if (known)
|
|
214703
|
-
session2 = await client.report({ ...scope2, operation_id: known.operation_id, executor_generation: known.executor_generation, lease_generation: known.lease_generation, ...journal.receipts[known.operation_id].outcome });
|
|
214992
|
+
try {
|
|
214993
|
+
session2 = await client.plan({ ...scope2, request_id: journal.plan_request_id, expected_revision: session2.revision, plan: journal.plan.wire });
|
|
214994
|
+
} catch (error) {
|
|
214995
|
+
if (!(error instanceof SetupError) || error.code !== "revision_conflict")
|
|
214996
|
+
throw error;
|
|
214997
|
+
session2 = await client.poll();
|
|
214998
|
+
}
|
|
214999
|
+
continue;
|
|
214704
215000
|
}
|
|
214705
|
-
|
|
214706
|
-
|
|
214707
|
-
|
|
214708
|
-
|
|
214709
|
-
|
|
215001
|
+
if (!journal.plan || !session2.local_plan || setupDigest(session2.local_plan) !== setupDigest(journal.plan.wire))
|
|
215002
|
+
throw new SetupError("setup_plan_missing", "The browser-approved local plan is unavailable on this computer. No effects were applied.");
|
|
215003
|
+
if (session2.phase !== "applying") {
|
|
215004
|
+
await heartbeat.pulse();
|
|
215005
|
+
heartbeat.check();
|
|
215006
|
+
session2 = heartbeat.latest(session2);
|
|
214710
215007
|
await pause2();
|
|
214711
215008
|
session2 = await client.poll();
|
|
214712
215009
|
continue;
|
|
214713
215010
|
}
|
|
214714
|
-
const
|
|
214715
|
-
if (
|
|
214716
|
-
|
|
214717
|
-
|
|
214718
|
-
|
|
214719
|
-
|
|
214720
|
-
|
|
215011
|
+
const unknown = session2.commands.find((command3) => command3.status === "outcome_unknown" || command3.status === "running" || command3.status === "leased" && journal.receipts[command3.operation_id]);
|
|
215012
|
+
if (unknown) {
|
|
215013
|
+
const operation2 = journal.plan.operations.find((item) => setupDigest(item.effect) === unknown.input_digest);
|
|
215014
|
+
if (!operation2)
|
|
215015
|
+
throw new SetupError("setup_command_mismatch", "The command does not match the local reviewed plan.");
|
|
215016
|
+
const receipt2 = journal.receipts[unknown.operation_id];
|
|
215017
|
+
if (unknown.status !== "outcome_unknown") {
|
|
215018
|
+
await pause2();
|
|
215019
|
+
session2 = await client.poll();
|
|
215020
|
+
continue;
|
|
215021
|
+
}
|
|
215022
|
+
const stillVerified = await verified(directory2, operation2, runtime, receipt2);
|
|
215023
|
+
const outcome = receipt2?.outcome && receipt2.outcome.status !== "succeeded" ? receipt2.outcome : stillVerified ? { status: "succeeded", result: { code: "already_present", verified: true } } : { status: "manual", result: { code: receipt2?.outcome?.status === "succeeded" ? "review_required" : "outcome_unknown" } };
|
|
215024
|
+
const requestId = receipt2?.request_id ?? randomUUID9();
|
|
215025
|
+
journal.receipts[unknown.operation_id] = { input_digest: unknown.input_digest, stage: "settled", outcome, diagnostic: receipt2?.diagnostic, outputs: receipt2?.outputs, request_id: requestId };
|
|
214721
215026
|
await saveJournal(path, journal);
|
|
215027
|
+
session2 = await client.reconcile({ ...scope2, request_id: requestId, project_fingerprint: client.identity.project_fingerprint, executor_generation: session2.executor_generation, operation_id: unknown.operation_id, input_digest: unknown.input_digest, ...outcome });
|
|
215028
|
+
continue;
|
|
214722
215029
|
}
|
|
214723
|
-
|
|
214724
|
-
|
|
214725
|
-
|
|
214726
|
-
|
|
214727
|
-
throw new SetupError("setup_plan_missing", "The browser-approved local plan is unavailable on this computer. No effects were applied.");
|
|
214728
|
-
if (session2.phase !== "applying") {
|
|
214729
|
-
session2 = await client.heartbeat({ ...scope2, executor_generation: session2.executor_generation, operation_id: null, lease_generation: null });
|
|
214730
|
-
await pause2();
|
|
214731
|
-
session2 = await client.poll();
|
|
214732
|
-
continue;
|
|
214733
|
-
}
|
|
214734
|
-
const unknown = session2.commands.find((command3) => command3.status === "outcome_unknown" || command3.status === "running" || command3.status === "leased" && journal.receipts[command3.operation_id]);
|
|
214735
|
-
if (unknown) {
|
|
214736
|
-
const operation2 = journal.plan.operations.find((item) => setupDigest(item.effect) === unknown.input_digest);
|
|
214737
|
-
if (!operation2)
|
|
214738
|
-
throw new SetupError("setup_command_mismatch", "The command does not match the local reviewed plan.");
|
|
214739
|
-
const receipt2 = journal.receipts[unknown.operation_id];
|
|
214740
|
-
if (unknown.status !== "outcome_unknown") {
|
|
215030
|
+
const claimed = await client.claim({ ...scope2, request_id: journal.claim_request_id, executor_generation: session2.executor_generation });
|
|
215031
|
+
session2 = claimed.session;
|
|
215032
|
+
const command2 = claimed.command;
|
|
215033
|
+
if (!command2) {
|
|
214741
215034
|
await pause2();
|
|
214742
215035
|
session2 = await client.poll();
|
|
214743
215036
|
continue;
|
|
214744
215037
|
}
|
|
214745
|
-
|
|
214746
|
-
|
|
214747
|
-
const
|
|
214748
|
-
|
|
215038
|
+
if (command2.status !== "leased")
|
|
215039
|
+
continue;
|
|
215040
|
+
const operation = journal.plan.operations.find((item) => item.effect.effect_id === command2.input.effect_id);
|
|
215041
|
+
if (!operation || setupDigest(operation.effect) !== command2.input_digest || setupDigest(operation.effect) !== setupDigest(command2.input))
|
|
215042
|
+
throw new SetupError("setup_command_mismatch", "The command differs from the approved local plan.");
|
|
215043
|
+
const lease = { ...scope2, operation_id: command2.operation_id, executor_generation: command2.executor_generation, lease_generation: command2.lease_generation };
|
|
215044
|
+
if (journal.receipts[command2.operation_id])
|
|
215045
|
+
throw new SetupError("setup_replay_refused", "A local receipt already exists. Reconcile before attempting this command again.");
|
|
215046
|
+
const receipt = { input_digest: command2.input_digest, stage: "claimed", request_id: randomUUID9() };
|
|
215047
|
+
journal.receipts[command2.operation_id] = receipt;
|
|
214749
215048
|
await saveJournal(path, journal);
|
|
214750
|
-
|
|
214751
|
-
|
|
214752
|
-
|
|
214753
|
-
|
|
214754
|
-
|
|
214755
|
-
|
|
214756
|
-
|
|
214757
|
-
|
|
214758
|
-
|
|
214759
|
-
|
|
214760
|
-
|
|
214761
|
-
|
|
214762
|
-
|
|
214763
|
-
|
|
214764
|
-
|
|
214765
|
-
|
|
214766
|
-
|
|
214767
|
-
|
|
214768
|
-
|
|
214769
|
-
|
|
214770
|
-
|
|
214771
|
-
|
|
214772
|
-
|
|
214773
|
-
|
|
214774
|
-
|
|
214775
|
-
|
|
214776
|
-
|
|
214777
|
-
|
|
214778
|
-
|
|
214779
|
-
|
|
214780
|
-
|
|
214781
|
-
|
|
214782
|
-
|
|
214783
|
-
|
|
214784
|
-
|
|
214785
|
-
if (heartbeatBusy)
|
|
214786
|
-
return;
|
|
214787
|
-
heartbeatBusy = true;
|
|
214788
|
-
inFlightHeartbeat = client.heartbeat(lease).then((value) => {
|
|
214789
|
-
session2 = value;
|
|
214790
|
-
if (terminal2.has(value.phase))
|
|
214791
|
-
controller.abort(new Error("Setup ended"));
|
|
214792
|
-
}, (error) => {
|
|
214793
|
-
heartbeatFailure = error;
|
|
214794
|
-
controller.abort(error);
|
|
214795
|
-
}).finally(() => {
|
|
214796
|
-
heartbeatBusy = false;
|
|
214797
|
-
});
|
|
214798
|
-
}, options.heartbeatMs ?? 1e4);
|
|
214799
|
-
try {
|
|
214800
|
-
controller.signal.throwIfAborted();
|
|
214801
|
-
if (!await verifySetupFiles(directory2, operation.files, "before"))
|
|
214802
|
-
throw new SetupError("setup_files_changed", "Files changed after browser approval.");
|
|
214803
|
-
for (const guard of operation.guards ?? []) {
|
|
214804
|
-
const content = await readSetupFile(directory2, guard.path);
|
|
214805
|
-
if ((content === null ? null : setupHash(content)) !== guard.before_hash)
|
|
214806
|
-
throw new SetupError("setup_files_changed", "A package configuration changed after review.");
|
|
214807
|
-
}
|
|
214808
|
-
if (operation.effect.kind === "install_packages")
|
|
214809
|
-
for (const file of operation.effect.managed_outputs ?? []) {
|
|
214810
|
-
const content = await readSetupFile(directory2, file.path);
|
|
214811
|
-
if ((content === null ? null : setupHash(content)) !== file.before_hash)
|
|
214812
|
-
throw new SetupError("setup_files_changed", "Package-manager outputs changed after approval.");
|
|
214813
|
-
}
|
|
214814
|
-
const code = await runtime.apply(operation, controller.signal);
|
|
214815
|
-
controller.signal.throwIfAborted();
|
|
214816
|
-
receipt.outputs = await outputs(directory2, operation);
|
|
214817
|
-
if (!await verified(directory2, operation, runtime, receipt))
|
|
214818
|
-
throw new SetupError("setup_verification_failed", "The completed effect did not match the reviewed files.");
|
|
214819
|
-
receipt.outcome = { status: "succeeded", result: { code, verified: true } };
|
|
214820
|
-
} catch (error) {
|
|
214821
|
-
receipt.outcome = { status: error instanceof SetupError && error.code === "setup_files_changed" ? "manual" : "failed", result: { code: controller.signal.aborted || heartbeatFailure ? "outcome_unknown" : error instanceof SetupError && error.code === "setup_files_changed" ? "review_required" : "operation_failed" } };
|
|
214822
|
-
} finally {
|
|
214823
|
-
clearInterval(timer);
|
|
214824
|
-
await inFlightHeartbeat;
|
|
214825
|
-
options.signal?.removeEventListener("abort", abort);
|
|
215049
|
+
heartbeat.setLease(lease);
|
|
215050
|
+
session2 = await client.startCommand(lease);
|
|
215051
|
+
receipt.stage = "running";
|
|
215052
|
+
await saveJournal(path, journal);
|
|
215053
|
+
const operationSignal = heartbeat.signal;
|
|
215054
|
+
try {
|
|
215055
|
+
operationSignal.throwIfAborted();
|
|
215056
|
+
if (!await verifySetupFiles(directory2, operation.files, "before"))
|
|
215057
|
+
throw new SetupError("setup_files_changed", "Files changed after browser approval.");
|
|
215058
|
+
for (const guard of operation.guards ?? []) {
|
|
215059
|
+
const content = await readSetupFile(directory2, guard.path);
|
|
215060
|
+
if ((content === null ? null : setupHash(content)) !== guard.before_hash)
|
|
215061
|
+
throw new SetupError("setup_files_changed", "A package configuration changed after review.");
|
|
215062
|
+
}
|
|
215063
|
+
if (operation.effect.kind === "install_packages")
|
|
215064
|
+
for (const file of operation.effect.managed_outputs ?? []) {
|
|
215065
|
+
const content = await readSetupFile(directory2, file.path);
|
|
215066
|
+
if ((content === null ? null : setupHash(content)) !== file.before_hash)
|
|
215067
|
+
throw new SetupError("setup_files_changed", "Package-manager outputs changed after approval.");
|
|
215068
|
+
}
|
|
215069
|
+
const code = await runtime.apply(operation, operationSignal);
|
|
215070
|
+
operationSignal.throwIfAborted();
|
|
215071
|
+
receipt.outputs = await outputs(directory2, operation);
|
|
215072
|
+
if (!await verified(directory2, operation, runtime, receipt))
|
|
215073
|
+
throw new SetupError("setup_verification_failed", "The completed effect did not match the reviewed files.");
|
|
215074
|
+
receipt.outcome = { status: "succeeded", result: { code, verified: true } };
|
|
215075
|
+
} catch (error) {
|
|
215076
|
+
receipt.outcome = { status: error instanceof SetupError && error.code === "setup_files_changed" ? "manual" : "failed", result: { code: operationSignal.aborted ? "outcome_unknown" : error instanceof SetupError && error.code === "setup_files_changed" ? "review_required" : "operation_failed" } };
|
|
215077
|
+
receipt.diagnostic = sanitizeSetupDiagnostic(error instanceof Error ? error.message : "Local operation failed without an error message.");
|
|
215078
|
+
}
|
|
215079
|
+
receipt.stage = "settled";
|
|
215080
|
+
journal.claim_request_id = randomUUID9();
|
|
215081
|
+
await saveJournal(path, journal);
|
|
215082
|
+
showError(command2.operation_id, receipt);
|
|
215083
|
+
session2 = await heartbeat.duringReport(() => client.report({ ...lease, ...receipt.outcome }));
|
|
214826
215084
|
}
|
|
214827
|
-
|
|
214828
|
-
|
|
214829
|
-
|
|
214830
|
-
|
|
214831
|
-
|
|
214832
|
-
});
|
|
215085
|
+
});
|
|
215086
|
+
} finally {
|
|
215087
|
+
if (!sharedHeartbeat)
|
|
215088
|
+
await heartbeat.stop();
|
|
215089
|
+
}
|
|
214833
215090
|
}
|
|
214834
215091
|
|
|
214835
215092
|
// node_modules/@userreason/cli/dist/setup-terminal.js
|
|
@@ -214840,20 +215097,21 @@ function detectSetupTerminal(platform = process.platform, environment = process.
|
|
|
214840
215097
|
}
|
|
214841
215098
|
|
|
214842
215099
|
// node_modules/@userreason/cli/dist/setup-runner.js
|
|
214843
|
-
import { randomUUID as
|
|
215100
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
214844
215101
|
import { realpath as realpath4 } from "node:fs/promises";
|
|
214845
215102
|
|
|
214846
215103
|
// node_modules/@userreason/cli/dist/setup-source.js
|
|
214847
|
-
import { randomUUID as
|
|
214848
|
-
async function prepareSetupSource(directory2, preparationId =
|
|
215104
|
+
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
215105
|
+
async function prepareSetupSource(directory2, preparationId = randomUUID10(), signal, expanded = false) {
|
|
214849
215106
|
signal?.throwIfAborted();
|
|
214850
|
-
const preview = await collectFirstSurveySource({ root: directory2, snapshotId: preparationId, recommendations: true, signal });
|
|
215107
|
+
const preview = await collectFirstSurveySource({ root: directory2, snapshotId: preparationId, recommendations: true, benchmark: expanded, signal });
|
|
214851
215108
|
await verifyFirstSurveySource(directory2, preview.evidence);
|
|
214852
215109
|
const evidence = preview.evidence, packages = preview.packages;
|
|
214853
215110
|
const prepared = {
|
|
214854
215111
|
preparation_id: preparationId,
|
|
214855
215112
|
evidence,
|
|
214856
215113
|
packages,
|
|
215114
|
+
expanded,
|
|
214857
215115
|
manifest: {
|
|
214858
215116
|
packet_digest: setupDigest({ evidence, packages }),
|
|
214859
215117
|
snapshot_id: preparationId,
|
|
@@ -214880,8 +215138,8 @@ async function prepareSetupSource(directory2, preparationId = randomUUID11(), si
|
|
|
214880
215138
|
});
|
|
214881
215139
|
return prepared;
|
|
214882
215140
|
}
|
|
214883
|
-
async function restoreSetupSource(directory2, approved, signal) {
|
|
214884
|
-
const prepared = await prepareSetupSource(directory2, approved.preparation_id, signal);
|
|
215141
|
+
async function restoreSetupSource(directory2, approved, signal, expanded) {
|
|
215142
|
+
const prepared = await prepareSetupSource(directory2, approved.preparation_id, signal, expanded ?? approved.manifest.files.reduce((n, file) => n + file.bytes, 0) > 1e4);
|
|
214885
215143
|
if (setupDigest(prepared.manifest) !== setupDigest(approved.manifest) || setupDigest(prepared.packages) !== setupDigest(approved.packages))
|
|
214886
215144
|
throw new SetupError("setup_source_changed", "Application source or installed package metadata changed. Review a new source packet in the browser before analysis.");
|
|
214887
215145
|
return prepared;
|
|
@@ -214895,12 +215153,12 @@ async function verifySetupSource(directory2, packet, signal) {
|
|
|
214895
215153
|
} catch {
|
|
214896
215154
|
throw new SetupError("setup_source_changed", "Application files changed. Review a new source packet before analysis.");
|
|
214897
215155
|
}
|
|
214898
|
-
await restoreSetupSource(directory2, packet, signal);
|
|
215156
|
+
await restoreSetupSource(directory2, packet, signal, packet.expanded);
|
|
214899
215157
|
signal?.throwIfAborted();
|
|
214900
215158
|
}
|
|
214901
215159
|
|
|
214902
215160
|
// node_modules/@userreason/cli/dist/setup-runner.js
|
|
214903
|
-
var
|
|
215161
|
+
var terminal4 = /* @__PURE__ */ new Set(["complete", "cancelled", "expired"]);
|
|
214904
215162
|
var localPhases = /* @__PURE__ */ new Set(["configuring", "awaiting_local_approval", "applying"]);
|
|
214905
215163
|
function pause(milliseconds, options) {
|
|
214906
215164
|
options.signal?.throwIfAborted();
|
|
@@ -214918,133 +215176,173 @@ function pause(milliseconds, options) {
|
|
|
214918
215176
|
options.signal?.addEventListener("abort", abort, { once: true });
|
|
214919
215177
|
});
|
|
214920
215178
|
}
|
|
214921
|
-
async function
|
|
214922
|
-
|
|
214923
|
-
|
|
214924
|
-
|
|
214925
|
-
|
|
214926
|
-
|
|
214927
|
-
|
|
214928
|
-
|
|
214929
|
-
|
|
214930
|
-
|
|
214931
|
-
|
|
214932
|
-
|
|
214933
|
-
const accept = (next) => {
|
|
214934
|
-
if (BigInt(next.revision) >= BigInt(session2.revision))
|
|
214935
|
-
session2 = next;
|
|
214936
|
-
};
|
|
214937
|
-
const issue = (code) => {
|
|
214938
|
-
if (!issues.has(code)) {
|
|
214939
|
-
issues.add(code);
|
|
214940
|
-
options.onSourceIssue?.(code);
|
|
214941
|
-
}
|
|
214942
|
-
};
|
|
214943
|
-
let sourceAvailable = false;
|
|
215179
|
+
async function prepareEarly(client, directory2, options) {
|
|
215180
|
+
const scope2 = { schema_version: 1, setup_id: client.identity.setup_id };
|
|
215181
|
+
try {
|
|
215182
|
+
let session2 = await client.poll();
|
|
215183
|
+
if (session2.source || !(await client.discovery()).browser_setup.source_analysis)
|
|
215184
|
+
return;
|
|
215185
|
+
const packet = options.preparedSource ? await setupAbortable(options.preparedSource, options.signal) ?? await prepareSetupSource(directory2, randomUUID11(), options.signal, true) : await prepareSetupSource(directory2, randomUUID11(), options.signal, true);
|
|
215186
|
+
let conflicts = 0;
|
|
215187
|
+
while (true) {
|
|
215188
|
+
session2 = await client.poll();
|
|
215189
|
+
if (session2.source || terminal4.has(session2.phase))
|
|
215190
|
+
return;
|
|
214944
215191
|
try {
|
|
214945
|
-
|
|
215192
|
+
session2 = await client.sourcePlan({ ...scope2, request_id: packet.preparation_id, expected_revision: session2.revision, manifest: packet.manifest, packages: packet.packages });
|
|
215193
|
+
break;
|
|
214946
215194
|
} catch (error) {
|
|
214947
|
-
if (!(error instanceof
|
|
215195
|
+
if (!(error instanceof SetupError) || error.code !== "revision_conflict" || ++conflicts >= 5)
|
|
214948
215196
|
throw error;
|
|
214949
215197
|
}
|
|
214950
|
-
|
|
214951
|
-
|
|
214952
|
-
|
|
214953
|
-
|
|
214954
|
-
|
|
214955
|
-
|
|
214956
|
-
|
|
214957
|
-
|
|
214958
|
-
|
|
214959
|
-
|
|
214960
|
-
|
|
214961
|
-
|
|
214962
|
-
|
|
214963
|
-
|
|
214964
|
-
|
|
214965
|
-
|
|
214966
|
-
|
|
214967
|
-
|
|
214968
|
-
|
|
214969
|
-
|
|
214970
|
-
|
|
214971
|
-
|
|
214972
|
-
|
|
214973
|
-
|
|
214974
|
-
|
|
214975
|
-
|
|
214976
|
-
|
|
214977
|
-
|
|
214978
|
-
|
|
214979
|
-
|
|
214980
|
-
|
|
214981
|
-
|
|
214982
|
-
|
|
214983
|
-
|
|
215198
|
+
}
|
|
215199
|
+
if (session2.source?.status !== "approved" || session2.source.preparation_id !== packet.preparation_id)
|
|
215200
|
+
return;
|
|
215201
|
+
await verifySetupSource(directory2, packet, options.signal);
|
|
215202
|
+
options.onSession?.(session2);
|
|
215203
|
+
await client.sourceUpload({ ...scope2, preparation_id: packet.preparation_id, project_fingerprint: client.identity.project_fingerprint, evidence: packet.evidence });
|
|
215204
|
+
} catch (error) {
|
|
215205
|
+
options.signal?.throwIfAborted();
|
|
215206
|
+
options.onSourceIssue?.(error instanceof SetupError ? error.code : "source_unavailable");
|
|
215207
|
+
}
|
|
215208
|
+
}
|
|
215209
|
+
async function runBrowserSetup(client, directory2, runtime, options = {}) {
|
|
215210
|
+
directory2 = await realpath4(directory2);
|
|
215211
|
+
const lifetime = new AbortController();
|
|
215212
|
+
const runSignal = AbortSignal.any([lifetime.signal, ...options.signal ? [options.signal] : []]);
|
|
215213
|
+
const base = client.withSignal?.(runSignal) ?? client;
|
|
215214
|
+
const heartbeat = new SetupHeartbeat(base, { ...options, signal: runSignal });
|
|
215215
|
+
client = observeSetupClient(base.withSignal?.(heartbeat.signal) ?? base, heartbeat, heartbeat.signal);
|
|
215216
|
+
const suppliedSignal = options.signal;
|
|
215217
|
+
options = { ...options, signal: heartbeat.signal };
|
|
215218
|
+
let polls = 0;
|
|
215219
|
+
const early = options.automaticSetup ? prepareEarly(client, directory2, options) : Promise.resolve();
|
|
215220
|
+
void early.catch(() => {
|
|
215221
|
+
});
|
|
215222
|
+
try {
|
|
215223
|
+
while (true) {
|
|
215224
|
+
let session2;
|
|
215225
|
+
session2 = await runSetupExecutor(client, directory2, runtime, options, heartbeat);
|
|
215226
|
+
await early;
|
|
215227
|
+
if (options.automaticSetup)
|
|
215228
|
+
session2 = await client.poll();
|
|
215229
|
+
if (terminal4.has(session2.phase) || localPhases.has(session2.phase))
|
|
215230
|
+
return session2;
|
|
215231
|
+
const result = await withSetupProjectLock(directory2, async () => {
|
|
215232
|
+
let packet, observedPreparation;
|
|
215233
|
+
let preparationAttempted = false, failedPreparationRevision, notifiedSample = false;
|
|
215234
|
+
const uploadAttempts = /* @__PURE__ */ new Set(), issues = /* @__PURE__ */ new Set();
|
|
215235
|
+
const scope2 = { schema_version: 1, setup_id: client.identity.setup_id };
|
|
215236
|
+
const accept = (next) => {
|
|
215237
|
+
if (BigInt(next.revision) >= BigInt(session2.revision))
|
|
215238
|
+
session2 = next;
|
|
215239
|
+
};
|
|
215240
|
+
const issue = (code) => {
|
|
215241
|
+
if (!issues.has(code)) {
|
|
215242
|
+
issues.add(code);
|
|
215243
|
+
options.onSourceIssue?.(code);
|
|
214984
215244
|
}
|
|
214985
|
-
|
|
214986
|
-
|
|
214987
|
-
|
|
214988
|
-
|
|
214989
|
-
|
|
214990
|
-
|
|
214991
|
-
|
|
214992
|
-
|
|
214993
|
-
|
|
214994
|
-
|
|
214995
|
-
|
|
214996
|
-
|
|
214997
|
-
|
|
214998
|
-
|
|
214999
|
-
|
|
215000
|
-
|
|
215001
|
-
|
|
215002
|
-
|
|
215003
|
-
|
|
215004
|
-
|
|
215005
|
-
|
|
215006
|
-
|
|
215007
|
-
|
|
215008
|
-
|
|
215009
|
-
|
|
215010
|
-
|
|
215011
|
-
if (
|
|
215012
|
-
|
|
215013
|
-
packet = packet?.preparation_id === approved.preparation_id ? packet : await restoreSetupSource(directory2, approved, options.signal);
|
|
215014
|
-
options.onSourcePrepared?.(packet);
|
|
215015
|
-
await verifySetupSource(directory2, packet, options.signal);
|
|
215016
|
-
if (heartbeatError)
|
|
215017
|
-
throw heartbeatError;
|
|
215018
|
-
if (terminal3.has(session2.phase) || session2.source?.preparation_id !== approved.preparation_id || session2.source.status !== "approved")
|
|
215019
|
-
throw new SetupError("setup_source_changed", "Source approval changed before upload.");
|
|
215020
|
-
accept(await client.sourceUpload({
|
|
215021
|
-
...scope2,
|
|
215022
|
-
preparation_id: packet.preparation_id,
|
|
215023
|
-
project_fingerprint: client.identity.project_fingerprint,
|
|
215024
|
-
evidence: packet.evidence
|
|
215025
|
-
}));
|
|
215245
|
+
};
|
|
215246
|
+
let sourceAvailable = false;
|
|
215247
|
+
try {
|
|
215248
|
+
sourceAvailable = (await client.discovery()).browser_setup.source_analysis && session2.capabilities.source_review;
|
|
215249
|
+
} catch (error) {
|
|
215250
|
+
if (!(error instanceof BrowserSetupUnavailable))
|
|
215251
|
+
throw error;
|
|
215252
|
+
}
|
|
215253
|
+
try {
|
|
215254
|
+
while (true) {
|
|
215255
|
+
heartbeat.check();
|
|
215256
|
+
session2 = heartbeat.latest(session2);
|
|
215257
|
+
options.onSession?.(session2);
|
|
215258
|
+
if (terminal4.has(session2.phase) || localPhases.has(session2.phase) || options.maxPolls !== void 0 && polls++ >= options.maxPolls)
|
|
215259
|
+
return session2;
|
|
215260
|
+
if (session2.phase === "agent_test" && session2.sample.status === "waiting" && !notifiedSample) {
|
|
215261
|
+
notifiedSample = true;
|
|
215262
|
+
options.onSample?.(session2);
|
|
215263
|
+
}
|
|
215264
|
+
const source = session2.source;
|
|
215265
|
+
if (!source && failedPreparationRevision && session2.revision !== failedPreparationRevision) {
|
|
215266
|
+
preparationAttempted = false;
|
|
215267
|
+
failedPreparationRevision = void 0;
|
|
215268
|
+
issues.clear();
|
|
215269
|
+
}
|
|
215270
|
+
if (source?.preparation_id !== observedPreparation) {
|
|
215271
|
+
if (observedPreparation && !source)
|
|
215272
|
+
preparationAttempted = false;
|
|
215026
215273
|
packet = void 0;
|
|
215027
|
-
|
|
215028
|
-
|
|
215029
|
-
|
|
215274
|
+
observedPreparation = source?.preparation_id;
|
|
215275
|
+
issues.clear();
|
|
215276
|
+
}
|
|
215277
|
+
if (session2.phase === "ready_for_recommendations" && !source && sourceAvailable && !preparationAttempted) {
|
|
215278
|
+
preparationAttempted = true;
|
|
215279
|
+
try {
|
|
215280
|
+
packet = await prepareSetupSource(directory2, randomUUID11(), options.signal, options.automaticSetup);
|
|
215281
|
+
options.onSourcePrepared?.(packet);
|
|
215282
|
+
accept(await client.sourcePlan({
|
|
215283
|
+
...scope2,
|
|
215284
|
+
request_id: packet.preparation_id,
|
|
215285
|
+
expected_revision: session2.revision,
|
|
215286
|
+
manifest: packet.manifest,
|
|
215287
|
+
packages: packet.packages
|
|
215288
|
+
}));
|
|
215289
|
+
observedPreparation = session2.source?.preparation_id;
|
|
215290
|
+
} catch (error) {
|
|
215291
|
+
options.signal?.throwIfAborted();
|
|
215292
|
+
failedPreparationRevision = session2.revision;
|
|
215293
|
+
issue(error instanceof SetupError ? error.code : "source_unavailable");
|
|
215294
|
+
}
|
|
215295
|
+
} else if (source?.status === "approved" && sourceAvailable && !uploadAttempts.has(source.preparation_id)) {
|
|
215296
|
+
uploadAttempts.add(source.preparation_id);
|
|
215297
|
+
try {
|
|
215298
|
+
const info = await client.sourceInfo();
|
|
215299
|
+
accept(info.session);
|
|
215300
|
+
const approved = info.preparation, current = session2.source;
|
|
215301
|
+
if (!approved || current?.status !== "approved" || approved.preparation_id !== source.preparation_id || approved.manifest.packet_digest !== current.packet_digest || approved.configuration.configuration_fingerprint !== current.provider_fingerprint)
|
|
215302
|
+
throw new SetupError("setup_source_changed", "Review a new source packet in the browser.");
|
|
215303
|
+
if (Date.parse(current.expires_at) <= Date.now())
|
|
215304
|
+
throw new SetupError("planning_consent_expired", "Review source consent again in the browser.");
|
|
215305
|
+
packet = packet?.preparation_id === approved.preparation_id ? packet : await restoreSetupSource(directory2, approved, options.signal, options.automaticSetup);
|
|
215306
|
+
options.onSourcePrepared?.(packet);
|
|
215307
|
+
await verifySetupSource(directory2, packet, options.signal);
|
|
215308
|
+
heartbeat.check();
|
|
215309
|
+
if (terminal4.has(session2.phase) || session2.source?.preparation_id !== approved.preparation_id || session2.source.status !== "approved")
|
|
215310
|
+
throw new SetupError("setup_source_changed", "Source approval changed before upload.");
|
|
215311
|
+
accept(await client.sourceUpload({
|
|
215312
|
+
...scope2,
|
|
215313
|
+
preparation_id: packet.preparation_id,
|
|
215314
|
+
project_fingerprint: client.identity.project_fingerprint,
|
|
215315
|
+
evidence: packet.evidence
|
|
215316
|
+
}));
|
|
215317
|
+
packet = void 0;
|
|
215318
|
+
} catch (error) {
|
|
215319
|
+
options.signal?.throwIfAborted();
|
|
215320
|
+
issue(error instanceof SetupError ? error.code : "source_unavailable");
|
|
215321
|
+
}
|
|
215030
215322
|
}
|
|
215323
|
+
await pause(options.pollMs ?? 2e3, options);
|
|
215324
|
+
accept(await client.poll());
|
|
215031
215325
|
}
|
|
215032
|
-
|
|
215033
|
-
|
|
215326
|
+
} finally {
|
|
215327
|
+
packet = void 0;
|
|
215034
215328
|
}
|
|
215035
|
-
}
|
|
215036
|
-
|
|
215037
|
-
|
|
215038
|
-
|
|
215039
|
-
|
|
215040
|
-
|
|
215041
|
-
if (!
|
|
215042
|
-
return
|
|
215329
|
+
});
|
|
215330
|
+
if (!localPhases.has(result.phase) || options.maxPolls !== void 0)
|
|
215331
|
+
return result;
|
|
215332
|
+
}
|
|
215333
|
+
} catch (error) {
|
|
215334
|
+
const current = heartbeat.current;
|
|
215335
|
+
if (!suppliedSignal?.aborted && current && terminal4.has(current.phase))
|
|
215336
|
+
return current;
|
|
215337
|
+
throw error;
|
|
215338
|
+
} finally {
|
|
215339
|
+
lifetime.abort(new Error("Setup run ended"));
|
|
215340
|
+
await Promise.allSettled([early, heartbeat.stop()]);
|
|
215043
215341
|
}
|
|
215044
215342
|
}
|
|
215045
215343
|
|
|
215046
215344
|
// node_modules/@userreason/cli/dist/project.js
|
|
215047
|
-
var
|
|
215345
|
+
var import_typescript2 = __toESM(require_typescript(), 1);
|
|
215048
215346
|
|
|
215049
215347
|
// node_modules/@userreason/cli/dist/help.js
|
|
215050
215348
|
var GROUPS = [
|
|
@@ -215088,8 +215386,6 @@ export {
|
|
|
215088
215386
|
ToolTelemetry,
|
|
215089
215387
|
firstSurveyHandoff,
|
|
215090
215388
|
firstSurvey,
|
|
215091
|
-
prepareFirstSurveyLocally,
|
|
215092
|
-
recommendedSurveys,
|
|
215093
215389
|
SetupError,
|
|
215094
215390
|
withSetupProjectLock,
|
|
215095
215391
|
BrowserSetupUnavailable,
|
|
@@ -215100,6 +215396,7 @@ export {
|
|
|
215100
215396
|
readSetupFile,
|
|
215101
215397
|
writeSetupFile,
|
|
215102
215398
|
verifySetupFiles,
|
|
215399
|
+
sanitizeSetupDiagnostic,
|
|
215103
215400
|
runSetupExecutor,
|
|
215104
215401
|
detectSetupTerminal,
|
|
215105
215402
|
runBrowserSetup
|