@userreason/wizard 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +95 -0
  2. package/dist/agent-note.js +7 -6
  3. package/dist/agent-skill.js +6 -5
  4. package/dist/analytics.js +9 -0
  5. package/dist/bin.js +222 -51
  6. package/dist/chunk-4INLEQE2.js +196 -0
  7. package/dist/{chunk-GGARVSPT.js → chunk-7AAH6C4L.js} +9198 -5670
  8. package/dist/{chunk-ULHKVBPD.js → chunk-7O7H3PIM.js} +7 -7
  9. package/dist/chunk-CSZW2ULJ.js +152 -0
  10. package/dist/{chunk-3RDJORRS.js → chunk-DMXUXEQI.js} +1 -1
  11. package/dist/{chunk-SJVLAYGG.js → chunk-EVNEX5N5.js} +8 -1
  12. package/dist/chunk-KF37D5WL.js +44 -0
  13. package/dist/{chunk-5SC2K42Q.js → chunk-LEJFE4U5.js} +2 -2
  14. package/dist/{chunk-OEGNGGZ2.js → chunk-NMHTFC5Q.js} +10 -3
  15. package/dist/{chunk-6CJ4ANMN.js → chunk-NNPYUATH.js} +1 -1
  16. package/dist/chunk-PJQOSDYS.js +50 -0
  17. package/dist/chunk-Q5U5UOQN.js +288 -0
  18. package/dist/{chunk-5Z5J6PY5.js → chunk-SB3AYQWG.js} +6 -6
  19. package/dist/{chunk-YMSGDC4B.js → chunk-TOID3NYP.js} +40 -11
  20. package/dist/{chunk-JD5U4U26.js → chunk-TRBSH5G7.js} +6 -6
  21. package/dist/{chunk-ZGZOBW2B.js → chunk-XASPGFYK.js} +3 -3
  22. package/dist/{chunk-HACTNBV3.js → chunk-XPFKXLIZ.js} +3 -3
  23. package/dist/chunk-ZHJV247H.js +31 -0
  24. package/dist/cli-access.js +3 -3
  25. package/dist/connection.js +2 -2
  26. package/dist/first-survey.js +11 -0
  27. package/dist/footer.js +17 -0
  28. package/dist/global-cli.js +6 -5
  29. package/dist/install-diagnostics.js +9 -0
  30. package/dist/integrate.js +5 -4
  31. package/dist/project.js +8 -3
  32. package/dist/registry.js +5 -3
  33. package/dist/setup-flow.js +25 -0
  34. package/dist/setup.js +33 -0
  35. package/dist/skills/userreason/SKILL.md +43 -0
  36. package/dist/skills/userreason/references/management.md +6 -0
  37. package/dist/startup.js +2 -2
  38. package/dist/state.js +6 -5
  39. package/dist/ui.js +2 -2
  40. package/package.json +1 -2
@@ -1,16 +1,16 @@
1
1
  import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
2
- import {
3
- Cancelled
4
- } from "./chunk-SJVLAYGG.js";
5
2
  import {
6
3
  initializationPath
7
- } from "./chunk-5SC2K42Q.js";
4
+ } from "./chunk-LEJFE4U5.js";
8
5
  import {
9
6
  cliCommand
10
- } from "./chunk-YMSGDC4B.js";
7
+ } from "./chunk-TOID3NYP.js";
8
+ import {
9
+ Cancelled
10
+ } from "./chunk-EVNEX5N5.js";
11
11
  import {
12
12
  packageProfile
13
- } from "./chunk-GGARVSPT.js";
13
+ } from "./chunk-7AAH6C4L.js";
14
14
 
15
15
  // src/agent-note.ts
16
16
  import { constants } from "node:fs";
@@ -152,7 +152,7 @@ ${plan.snippet}` : plan.snippet,
152
152
  terminal.success(`User feedback note ${plan.replacement ? "updated in" : "added to"} ${plan.file}`);
153
153
  return { status: plan.replacement ? "updated" : "added", file: plan.file };
154
154
  } catch (error) {
155
- if (error instanceof Cancelled) return { status: "declined" };
155
+ if (error instanceof Cancelled) return { status: "declined", reason: "user_cancelled" };
156
156
  terminal.warn("Installation is complete. The optional user feedback note could not be added; the guidance file needs review.");
157
157
  return { status: "failed", reason: "guidance_file_needs_review" };
158
158
  }
@@ -0,0 +1,152 @@
1
+ import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
2
+ import {
3
+ connectSetup,
4
+ resumeSetup,
5
+ runSetup
6
+ } from "./chunk-Q5U5UOQN.js";
7
+ import {
8
+ clean,
9
+ openBrowser
10
+ } from "./chunk-EVNEX5N5.js";
11
+ import {
12
+ BrowserSetupUnavailable
13
+ } from "./chunk-7AAH6C4L.js";
14
+
15
+ // src/setup-flow.ts
16
+ var shell = (value) => /^[A-Za-z0-9_./:@=-]+$/.test(value) ? value : `'${value.replace(/'/g, `'"'"'`)}'`;
17
+ var registryArgs = (profile) => profile?.kind === "local-development" ? ["--prefer-online", `--registry=${profile.registry}`, `--@userreason:registry=${profile.registry}`] : [];
18
+ function setupSampleCommand(setupId, apiOrigin, cliVersion, profile) {
19
+ return ["npx", "-y", ...registryArgs(profile), `@userreason/cli@${cliVersion}`, "setup", "sample", "--setup", setupId, "--api-url", apiOrigin, "--directory", ".", "--json"].map(shell).join(" ");
20
+ }
21
+ function setupResumeCommand(setupId, apiOrigin, version, profile) {
22
+ return ["npx", "-y", ...registryArgs(profile), `@userreason/wizard@${version}`, "--resume-setup", setupId, "--api-url", apiOrigin, "--directory", "."].map(shell).join(" ");
23
+ }
24
+ var setupManualGuidance = {
25
+ install_packages: "Review the project dependency and registry settings, install compatible @userreason/js and @userreason/cli versions with the project package manager, then rerun setup. See https://docs.userreason.com/get-started/quickstart/.",
26
+ initialize_sdk: "Identify the existing browser entry and initialize UserReason once with the selected site\u2019s public ID, preserving any existing initialization. See https://docs.userreason.com/sdk/initialization/.",
27
+ install_skill: "Review the existing agent guidance and merge the UserReason skill manually from the installed @userreason/cli skills/userreason directory. Preserve your existing edits and do not overwrite a customized skill.",
28
+ insert_footer: "Identify the intended existing site footer and manually add a Powered by UserReason link to https://userreason.com/. Preserve its content and layout; resolve ambiguous placement before editing."
29
+ };
30
+ function setupSummary(session) {
31
+ return {
32
+ setup_id: session.setup_id,
33
+ phase: session.phase,
34
+ workspace_id: session.workspace_id,
35
+ site_id: session.site_id,
36
+ local_operations: session.commands.map((command) => ({ kind: command.kind, status: command.status, code: command.result?.code ?? null })),
37
+ manual_steps: session.local_plan?.manual_steps ?? [],
38
+ source: session.source?.status ?? "not_started",
39
+ drafts: session.draft_outcomes.map((draft) => ({ candidate_id: draft.candidate_id, prompt_id: draft.prompt_id, status: draft.status, revision: draft.revision })),
40
+ sample: session.sample.status,
41
+ cli_access: "not_requested"
42
+ };
43
+ }
44
+ async function runBrowserWizard(input) {
45
+ const { terminal, project, apiOrigin, signal } = input;
46
+ let connected;
47
+ try {
48
+ connected = input.resumeId ? await resumeSetup(apiOrigin, input.resumeId, project, { signal, measurementDisabled: input.measurementDisabled }) : await connectSetup(apiOrigin, project, async (url, code) => {
49
+ terminal.block("Continue in your browser", [url, `Verification code: ${code}`, input.development ? "Choose your workspace, site and installation options in the browser." : "Review the project, local changes and source permissions there."]);
50
+ if (!input.noOpen && !await openBrowser(url)) terminal.info("Open the link above to continue.");
51
+ }, {
52
+ signal,
53
+ browserOrigin: input.browserOrigin,
54
+ automaticSetup: input.development,
55
+ measurementDisabled: input.measurementDisabled,
56
+ ...input.development ? { launcher: { wizard_version: input.version, api_origin: apiOrigin, ...input.profile.kind === "local-development" ? { registry: input.profile.registry } : {} } } : {}
57
+ });
58
+ } catch (error) {
59
+ if (!input.resumeId && error instanceof BrowserSetupUnavailable) return false;
60
+ throw error;
61
+ }
62
+ const resume = setupResumeCommand(connected.client.identity.setup_id, apiOrigin, input.version, input.profile);
63
+ terminal.block("Setup connected", [`Setup: ${connected.client.identity.setup_id}`, "Keep this terminal open while you complete setup in the browser.", `To reconnect from this project: ${resume}`]);
64
+ let status = "", displayedPacket = "";
65
+ const shownManual = /* @__PURE__ */ new Set();
66
+ try {
67
+ const automaticSetup = connected.session.capabilities.onboarding_v2 === true;
68
+ const result = await runSetup(connected.client, project, {
69
+ signal,
70
+ automaticSetup,
71
+ onOperationError({ kind, message, receiptPath }) {
72
+ terminal.block(`${kind === "install_packages" ? "Package installation" : kind.replaceAll("_", " ")} failed`, [
73
+ ...message.split("\n").map(clean),
74
+ `Local diagnostic receipt: ${receiptPath}`,
75
+ "The detailed error stays on this computer; the browser receives only the operation status."
76
+ ]);
77
+ },
78
+ onSession(session) {
79
+ for (const step of session.local_plan?.manual_steps ?? []) {
80
+ const key = `${step.kind}:${step.code}`;
81
+ if (shownManual.has(key)) continue;
82
+ shownManual.add(key);
83
+ terminal.block(`Manual step: ${step.kind}`, [setupManualGuidance[step.kind]]);
84
+ }
85
+ const next = `${session.phase}:${session.source?.status ?? ""}:${session.sample.status}`;
86
+ if (next === status) return;
87
+ status = next;
88
+ const messages = {
89
+ configuring: "Choose the workspace, site and installation options in the browser.",
90
+ awaiting_local_approval: automaticSetup ? "Choose your setup options in the browser." : "Review and approve the exact local changes in the browser.",
91
+ applying: "Applying browser-approved local changes.",
92
+ ready_for_recommendations: !session.capabilities.source_review ? session.commands.some((command) => ["failed", "manual", "outcome_unknown"].includes(command.status)) ? "Setup needs attention. Check the error above and review the results in the browser." : session.capabilities.sample_read ? "Finish setup or try the optional agent check in the browser." : "Finish setup in the browser." : !automaticSetup && session.source?.status === "pending" ? "Review source files and provider details in the browser before any source upload." : "Continue with recommendations or skip that step in the browser.",
93
+ analyzing: automaticSetup ? "Preparing survey suggestions from your project." : "Analyzing the source packet approved in the browser.",
94
+ selecting_drafts: "Review recommendations and select drafts in the browser.",
95
+ creating_drafts: "Creating only the drafts selected in the browser.",
96
+ agent_test: session.sample.status === "received" ? "Simulated sample received. Finish or skip in the browser." : "Complete or skip the optional agent test in the browser.",
97
+ complete: "Browser setup completed.",
98
+ cancelled: "Browser setup cancelled. Applied changes and created drafts are listed below.",
99
+ expired: "Browser setup expired. Applied changes and created drafts are listed below."
100
+ };
101
+ terminal.info(messages[session.phase]);
102
+ },
103
+ onSourceIssue(code) {
104
+ if (automaticSetup) {
105
+ terminal.warn(`Survey suggestions need attention (${clean(code)}). Retry in the browser or continue without suggestions.`);
106
+ return;
107
+ }
108
+ terminal.warn(`Source analysis needs review (${clean(code)}). Check the browser status, then retry source review or skip it. Changed local source requires fresh approval.`);
109
+ },
110
+ onSourcePrepared(packet) {
111
+ if (automaticSetup) return;
112
+ if (displayedPacket === packet.manifest.packet_digest) return;
113
+ displayedPacket = packet.manifest.packet_digest;
114
+ terminal.block("Local source review", [
115
+ "The exact bounded excerpts below stay local until you approve this packet and its providers in the browser.",
116
+ `Packet SHA-256: ${packet.manifest.packet_digest}`,
117
+ ...packet.evidence.flatMap((item) => [`${clean(item.path)}:${item.start_line}-${item.end_line} (file SHA-256 ${item.file_hash})`, ...item.excerpt.split("\n").map((line) => `> ${clean(line)}`)]),
118
+ `Omitted files: ${packet.manifest.omitted_files}. Truncated: ${packet.manifest.truncated ? "yes" : "no"}. Git history is excluded.`
119
+ ]);
120
+ },
121
+ onSample(session) {
122
+ terminal.block("Try your agent", ["Ask: What do UserReason dummy respondents think?", "Tell your agent to read this setup\u2019s simulated sample, using:", setupSampleCommand(session.setup_id, apiOrigin, input.profile.cliVersion, input.profile), "This is example data. It does not read production responses or grant ongoing CLI access."]);
123
+ }
124
+ });
125
+ const summary = setupSummary(result);
126
+ const needsAttention = result.commands.some((command) => ["failed", "manual", "outcome_unknown"].includes(command.status));
127
+ terminal.block("Setup result", [
128
+ `Status: ${result.phase}${needsAttention ? " (installation needs attention)" : ""}`,
129
+ ...summary.local_operations.map((operation) => `${operation.kind}: ${operation.status}${operation.code ? ` (${operation.code})` : ""}`),
130
+ ...summary.manual_steps.map((step) => `${step.kind}: manual (${step.code})`),
131
+ ...summary.drafts.map((draft) => `Draft ${draft.prompt_id}: ${draft.status}${draft.revision ? ` (revision ${draft.revision})` : ""}`),
132
+ `Simulated sample: ${summary.sample}`,
133
+ "Ongoing CLI access was not requested. Use a separate `userreason login --open` when you want to authorize it."
134
+ ]);
135
+ if (input.json) process.stdout.write(`${JSON.stringify(summary)}
136
+ `);
137
+ if (result.phase === "cancelled") process.exitCode = 130;
138
+ else if (result.phase !== "complete" || needsAttention) process.exitCode = 1;
139
+ return true;
140
+ } catch (error) {
141
+ terminal.info(`Resume from this project: ${resume}`);
142
+ throw error;
143
+ }
144
+ }
145
+
146
+ export {
147
+ setupSampleCommand,
148
+ setupResumeCommand,
149
+ setupManualGuidance,
150
+ setupSummary,
151
+ runBrowserWizard
152
+ };
@@ -4,7 +4,7 @@ import {
4
4
  object,
5
5
  string,
6
6
  uuid
7
- } from "./chunk-GGARVSPT.js";
7
+ } from "./chunk-7AAH6C4L.js";
8
8
 
9
9
  // src/connection.ts
10
10
  import { createHash, randomBytes } from "node:crypto";
@@ -7,7 +7,7 @@ import {
7
7
  plainLine,
8
8
  stripAnsi,
9
9
  textWidth
10
- } from "./chunk-GGARVSPT.js";
10
+ } from "./chunk-7AAH6C4L.js";
11
11
  import {
12
12
  __commonJS,
13
13
  __toESM
@@ -1235,6 +1235,7 @@ function approvalProgressMessage(progress) {
1235
1235
  var Cancelled = class extends Error {
1236
1236
  constructor() {
1237
1237
  super("Installation cancelled.");
1238
+ this.name = "Cancelled";
1238
1239
  }
1239
1240
  };
1240
1241
  var clean = (value) => value.replace(/\r\n?/g, "\n").replace(/\t/g, " ").replace(/[\x00-\x09\x0b-\x1f\x7f-\x9f]/g, "");
@@ -1279,6 +1280,7 @@ var Terminal = class {
1279
1280
  constructor(interactive, json, options = {}) {
1280
1281
  this.interactive = interactive;
1281
1282
  this.json = json;
1283
+ this.onCancel = options.onCancel;
1282
1284
  this.kit = createUiKit({ level: detectColorLevel({ stream: process.stdout, off: options.color === false }) });
1283
1285
  }
1284
1286
  interactive;
@@ -1288,6 +1290,7 @@ var Terminal = class {
1288
1290
  cancelState = "nothing was written";
1289
1291
  /** True after output that leaves no guide line behind, so the next event adds one. */
1290
1292
  gap = false;
1293
+ onCancel;
1291
1294
  header(options) {
1292
1295
  const lines = this.kit.header({ ...options, trademark: this.interactive });
1293
1296
  if (this.interactive) for (const line of lines) process.stdout.write(cleanStyled(line) + "\n");
@@ -1373,6 +1376,10 @@ var Terminal = class {
1373
1376
  cancelled(afterSpinner = false) {
1374
1377
  if (this.interactive && afterSpinner) process.stdout.write("\n");
1375
1378
  this.error(`Cancelled ${this.kit.c.muted(`${this.kit.S.dot} ${this.cancelState}`)}`);
1379
+ if (this.onCancel) {
1380
+ this.onCancel();
1381
+ return;
1382
+ }
1376
1383
  process.exit(130);
1377
1384
  }
1378
1385
  async text(message, initialValue, validate) {
@@ -0,0 +1,44 @@
1
+ import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
2
+ import {
3
+ TELEMETRY_REASONS,
4
+ ToolTelemetry
5
+ } from "./chunk-7AAH6C4L.js";
6
+
7
+ // src/analytics.ts
8
+ var WizardAnalytics = class extends ToolTelemetry {
9
+ starts = /* @__PURE__ */ new Map();
10
+ begin(step) {
11
+ this.starts.set(step, performance.now());
12
+ this.step(step, "started");
13
+ }
14
+ end(step, phase = "completed") {
15
+ const start = this.starts.get(step);
16
+ this.step(step, phase, start === void 0 ? {} : { duration_ms: performance.now() - start });
17
+ this.starts.delete(step);
18
+ }
19
+ async measure(step, operation, phase = "applied") {
20
+ const start = performance.now();
21
+ this.begin(step);
22
+ await this.checkpoint();
23
+ try {
24
+ const value = await operation();
25
+ const result = value && typeof value === "object" ? value : void 0;
26
+ const outcome = result?.reason === "user_cancelled" ? "cancelled" : result?.status === "already_present" ? "already_present" : result?.status === "declined" ? "declined" : result?.status === "skipped" ? "skipped" : result?.status === "failed" ? "failed" : phase;
27
+ const reason = result?.reason && TELEMETRY_REASONS.includes(result.reason) ? result.reason : result?.reason?.includes("review") ? "validation_failed" : result?.reason?.includes("preserved") || result?.reason === "existing_feedback_section" ? "existing_content_preserved" : outcome === "failed" ? "operation_failed" : outcome === "skipped" ? "unsupported" : void 0;
28
+ this.step(step, outcome, { duration_ms: performance.now() - start, ...reason ? { reason } : {}, ...result?.file === "AGENTS.md" || result?.file === "CLAUDE.md" ? { guidance_file: result.file } : {} });
29
+ this.starts.delete(step);
30
+ return value;
31
+ } catch (error) {
32
+ this.step(step, error instanceof Error && error.name === "Cancelled" ? "cancelled" : "failed", { duration_ms: performance.now() - start, reason: error instanceof Error && error.name === "Cancelled" ? "user_cancelled" : "operation_failed" });
33
+ this.starts.delete(step);
34
+ throw error;
35
+ }
36
+ }
37
+ finish(cancelled = false, failed = false) {
38
+ for (const step of [...this.starts.keys()].reverse()) this.end(step, cancelled ? "cancelled" : failed ? "failed" : "completed");
39
+ }
40
+ };
41
+
42
+ export {
43
+ WizardAnalytics
44
+ };
@@ -3,10 +3,10 @@ import {
3
3
  DEFAULT_API,
4
4
  initializationSource,
5
5
  integrationSource
6
- } from "./chunk-YMSGDC4B.js";
6
+ } from "./chunk-TOID3NYP.js";
7
7
  import {
8
8
  require_typescript
9
- } from "./chunk-GGARVSPT.js";
9
+ } from "./chunk-7AAH6C4L.js";
10
10
  import {
11
11
  __toESM
12
12
  } from "./chunk-WL3NOIM6.js";
@@ -7342,8 +7342,8 @@ import { lstat, readFile, open } from "node:fs/promises";
7342
7342
  import { join } from "node:path";
7343
7343
  import { execFile } from "node:child_process";
7344
7344
  import { promisify } from "node:util";
7345
- async function configurePackageRegistry(project, profile) {
7346
- if (profile.kind !== "local-development") return;
7345
+ async function planPackageRegistry(project, profile) {
7346
+ if (profile.kind !== "local-development") return null;
7347
7347
  const modernYarn = project.packageManager === "yarn" && (project.yarnMajor ?? 1) >= 2;
7348
7348
  const path = join(project.directory, modernYarn ? ".yarnrc.yml" : ".npmrc");
7349
7349
  let before = "", metadata;
@@ -7382,7 +7382,13 @@ async function configurePackageRegistry(project, profile) {
7382
7382
  after = configured === profile.registry ? before : `${before}${before && !before.endsWith("\n") ? "\n" : ""}${line}
7383
7383
  `;
7384
7384
  }
7385
- if (after === before) return;
7385
+ return { path, before: metadata ? before : null, after };
7386
+ }
7387
+ async function configurePackageRegistry(project, profile) {
7388
+ const plan = await planPackageRegistry(project, profile);
7389
+ if (!plan || plan.after === plan.before) return;
7390
+ const { path, after } = plan, before = plan.before ?? "";
7391
+ const metadata = plan.before === null ? null : await lstat(path);
7386
7392
  const handle = await open(path, metadata ? constants.O_WRONLY | (constants.O_NOFOLLOW ?? 0) : "wx", 420);
7387
7393
  try {
7388
7394
  if (metadata) {
@@ -7399,5 +7405,6 @@ async function configurePackageRegistry(project, profile) {
7399
7405
 
7400
7406
  export {
7401
7407
  require_dist,
7408
+ planPackageRegistry,
7402
7409
  configurePackageRegistry
7403
7410
  };
@@ -1,7 +1,7 @@
1
1
  import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
2
2
  import {
3
3
  currentPackageProfile
4
- } from "./chunk-GGARVSPT.js";
4
+ } from "./chunk-7AAH6C4L.js";
5
5
 
6
6
  // src/startup.ts
7
7
  import { readFile } from "node:fs/promises";
@@ -0,0 +1,50 @@
1
+ import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
2
+ import {
3
+ sanitizeSetupDiagnostic
4
+ } from "./chunk-7AAH6C4L.js";
5
+
6
+ // src/install-diagnostics.ts
7
+ import { readFile, readdir, stat } from "node:fs/promises";
8
+ import { homedir } from "node:os";
9
+ import { join } from "node:path";
10
+ async function installFailureDetails(directory, cache, output) {
11
+ const secrets = [], missing = /* @__PURE__ */ new Set();
12
+ for (const path of /* @__PURE__ */ new Set([join(directory, ".npmrc"), process.env.npm_config_userconfig ?? process.env.NPM_CONFIG_USERCONFIG ?? join(homedir(), ".npmrc")])) {
13
+ try {
14
+ if ((await stat(path)).size > 1e6) continue;
15
+ for (const line of (await readFile(path, "utf8")).split(/\r?\n/)) {
16
+ const match = /^\s*[^=]*(?:_authToken|_auth|_password)\s*=\s*(.+)$/i.exec(line);
17
+ if (!match) continue;
18
+ const value = match[1].trim();
19
+ const variable = /^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(value);
20
+ if (variable) {
21
+ if (!process.env[variable[1]]) missing.add(variable[1]);
22
+ } else secrets.push(value);
23
+ }
24
+ } catch {
25
+ }
26
+ }
27
+ const requests = /* @__PURE__ */ new Set();
28
+ if (cache) try {
29
+ const folder = join(cache, "_logs");
30
+ for (const name of (await readdir(folder)).filter((name2) => name2.endsWith("-debug-0.log")).sort().slice(-3)) {
31
+ const path = join(folder, name);
32
+ if ((await stat(path)).size > 2e6) continue;
33
+ for (const line of (await readFile(path, "utf8")).split("\n")) {
34
+ const match = /\bhttp fetch (GET|POST|PUT) ([45]\d\d) (https?:\/\/\S+)/.exec(line);
35
+ if (match && requests.size < 12) requests.add(`${match[2]} ${match[1]} ${match[3]}`);
36
+ }
37
+ }
38
+ } catch {
39
+ }
40
+ const lines = output.split(/\r?\n/).filter((line) => !/complete log of this run|npm notice/.test(line)).slice(-45);
41
+ return sanitizeSetupDiagnostic([
42
+ ...requests,
43
+ ...lines,
44
+ ...[...missing].map((name) => `Authentication variable ${name} is not set in the wizard process.`)
45
+ ].join("\n"), secrets);
46
+ }
47
+
48
+ export {
49
+ installFailureDetails
50
+ };