@userreason/wizard 0.3.1 → 0.3.3
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
CHANGED
|
@@ -36,7 +36,7 @@ terminal. The [first survey guide](https://docs.userreason.com/get-started/first
|
|
|
36
36
|
walks through creating and publishing a survey. Installing the SDK does not
|
|
37
37
|
publish a survey.
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Onboarding opens in the browser by default in production and development (`--dev`).
|
|
40
40
|
Survey suggestions and the Agent test step are paused in production and development.
|
|
41
41
|
Setup does not prepare or upload application source for recommendations, and it
|
|
42
42
|
neither offers nor creates suggested drafts. The terminal flow skips the
|
|
@@ -178,7 +178,8 @@ package builds. With a published package, select the development API:
|
|
|
178
178
|
npx -y @userreason/wizard@latest --dev
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
-
Production
|
|
181
|
+
Production and development both use browser setup by default. `--browser-setup`
|
|
182
|
+
remains an optional explicit alias. Compatible builds also support:
|
|
182
183
|
|
|
183
184
|
```sh
|
|
184
185
|
npx -y @userreason/wizard@latest --browser-setup
|
|
@@ -196,10 +197,11 @@ creating a session or local effects.
|
|
|
196
197
|
Malformed protocol data and already-started setups never fall back silently.
|
|
197
198
|
Server rollout flags remain off by default; publication is a separate release.
|
|
198
199
|
|
|
199
|
-
The browser owns workspace/site selection, optional choices,
|
|
200
|
+
The browser owns workspace/site selection, optional choices, installation options,
|
|
200
201
|
finish and cancellation. Source analysis, suggested drafts and the Agent test
|
|
201
202
|
remain implemented but are hidden and skipped while their rollout flags are off. The local runner executes only approved typed effects
|
|
202
|
-
using the separate owner-only setup capability.
|
|
203
|
+
using the separate owner-only setup capability. Press **Continue** on the setup
|
|
204
|
+
options to begin installation; there is no separate local-change review screen. It does not read or replace
|
|
203
205
|
normal CLI credentials. Stopping the local process leaves the setup resumable;
|
|
204
206
|
cancelling in the browser does not undo completed edits or delete created drafts.
|
|
205
207
|
Terminal results list verified, failed and manual outcomes separately.
|
|
@@ -220,11 +222,11 @@ skill never grants ongoing CLI access. Authorize continuing access separately
|
|
|
220
222
|
with `userreason login --open` when wanted. Standalone CLI survey tools remain
|
|
221
223
|
available outside onboarding.
|
|
222
224
|
|
|
223
|
-
The production profile for wizard 0.3.
|
|
225
|
+
The production profile for wizard 0.3.3 selects `@userreason/js@0.5.3` and
|
|
224
226
|
`@userreason/cli@0.2.1`. New installs use those exact versions; an installed
|
|
225
227
|
stable patch in the same release line is reused. Earlier SDK 0.4 and CLI 0.1
|
|
226
|
-
releases are upgraded when installation is selected. Browser setup
|
|
227
|
-
|
|
228
|
+
releases are upgraded when installation is selected. Browser setup is the default and requires a server advertising the capability.
|
|
229
|
+
Use `--terminal-setup` for the terminal flow.
|
|
228
230
|
|
|
229
231
|
Browser-guided installation prints package-manager failures in the connected
|
|
230
232
|
terminal, including failed registry requests when npm provides them. Diagnostic
|
package/dist/bin.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
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);
|
|
3
3
|
import {
|
|
4
4
|
runBrowserWizard
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FWEZ2ZWN.js";
|
|
6
6
|
import {
|
|
7
7
|
clearInstallation,
|
|
8
8
|
resolveInstallation,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
beginFirstSurveyPreparation,
|
|
27
27
|
offerFirstSurvey
|
|
28
28
|
} from "./chunk-ZHJV247H.js";
|
|
29
|
-
import "./chunk-
|
|
29
|
+
import "./chunk-5EAHX5BX.js";
|
|
30
30
|
import "./chunk-4INLEQE2.js";
|
|
31
31
|
import {
|
|
32
32
|
offerAgentSkill,
|
|
@@ -97,7 +97,7 @@ var help = `UserReason installation wizard
|
|
|
97
97
|
|
|
98
98
|
userreason-wizard [--directory PATH] [--origin URL]
|
|
99
99
|
|
|
100
|
-
--browser-setup (browser-guided setup; default for
|
|
100
|
+
--browser-setup (browser-guided setup; default for onboarding)
|
|
101
101
|
--terminal-setup (use terminal onboarding instead)
|
|
102
102
|
--resume-setup UUID (resume this project's saved browser setup)
|
|
103
103
|
--browser-origin ORIGIN (trusted dashboard origin for a custom API)
|
|
@@ -214,7 +214,7 @@ async function main() {
|
|
|
214
214
|
if (values["resume-setup"]) uuid(values["resume-setup"], "Setup ID");
|
|
215
215
|
const terminalFlags = ["refresh", "dry-run", "install", "skip-install", "integrate", "skip-integrate", "agent-note", "skip-agent-note", "agent-skill", "skip-agent-skill", "global-cli", "skip-global-cli", "cli-access", "skip-cli-access", "workspace", "workspace-name", "site", "site-name", "origin", "environment", "force", "diff", "session-only", "client-id", "credential-store"];
|
|
216
216
|
const hasTerminalFlags = terminalFlags.some((key) => values[key] !== void 0 && values[key] !== false);
|
|
217
|
-
const browserMode = explicitBrowserMode ||
|
|
217
|
+
const browserMode = explicitBrowserMode || !values["terminal-setup"] && !hasTerminalFlags && !values.yes && !values.json;
|
|
218
218
|
if (values["browser-origin"]) {
|
|
219
219
|
if (!browserMode) throw new Error("--browser-origin requires browser setup");
|
|
220
220
|
apiUrl(values["browser-origin"], "Browser origin");
|
|
@@ -41,8 +41,9 @@ import {
|
|
|
41
41
|
import { basename } from "node:path";
|
|
42
42
|
|
|
43
43
|
// src/setup-plan.ts
|
|
44
|
-
import { randomUUID } from "node:crypto";
|
|
45
|
-
import {
|
|
44
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
45
|
+
import { constants } from "node:fs";
|
|
46
|
+
import { lstat, open, readdir } from "node:fs/promises";
|
|
46
47
|
import { join, relative } from "node:path";
|
|
47
48
|
var relativeName = (project, path) => relative(project.directory, path).replaceAll("\\", "/");
|
|
48
49
|
var metadata = (files) => files.map((file2) => ({ path: file2.path, before_hash: file2.before === null ? null : setupHash(file2.before), after_hash: setupHash(file2.after) }));
|
|
@@ -170,10 +171,27 @@ async function prepare(project, session, profile, config, operations = [], manua
|
|
|
170
171
|
}
|
|
171
172
|
return { wire: { project_fingerprint: session.project_fingerprint, choices_digest: setupDigest(session.choices), effects: operations.map((item) => item.effect), ...manual.length ? { manual_steps: manual } : {} }, operations };
|
|
172
173
|
}
|
|
173
|
-
async function
|
|
174
|
+
async function snapshotFile(path, expected, signal) {
|
|
175
|
+
const handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
176
|
+
try {
|
|
177
|
+
const before = await handle.stat();
|
|
178
|
+
if (!before.isFile() || before.dev !== expected.dev || before.ino !== expected.ino)
|
|
179
|
+
throw new SetupError("setup_files_changed", "A project file changed while checking package installation.");
|
|
180
|
+
const hash = createHash("sha256");
|
|
181
|
+
for await (const chunk of handle.createReadStream({ autoClose: false, signal })) hash.update(chunk);
|
|
182
|
+
const after = await handle.stat();
|
|
183
|
+
if (before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs)
|
|
184
|
+
throw new SetupError("setup_files_changed", "A project file changed while checking package installation.");
|
|
185
|
+
return hash.digest("hex");
|
|
186
|
+
} finally {
|
|
187
|
+
await handle.close();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function snapshot(project, signal) {
|
|
174
191
|
const result = {}, stack = [""];
|
|
175
|
-
let entries = 0
|
|
192
|
+
let entries = 0;
|
|
176
193
|
while (stack.length) {
|
|
194
|
+
signal.throwIfAborted();
|
|
177
195
|
const folder = stack.pop();
|
|
178
196
|
for (const entry of await readdir(join(project.directory, folder), { withFileTypes: true })) {
|
|
179
197
|
if (++entries > 2e4) throw new SetupError("setup_files_changed", "Project scanning exceeds the bounded review budget.");
|
|
@@ -185,11 +203,7 @@ async function snapshot(project) {
|
|
|
185
203
|
continue;
|
|
186
204
|
}
|
|
187
205
|
if (info.isDirectory()) stack.push(path);
|
|
188
|
-
else if (info.isFile())
|
|
189
|
-
bytes += info.size;
|
|
190
|
-
if (info.size > 2e7 || bytes > 64e6) throw new SetupError("setup_files_changed", "Project scanning exceeds the bounded byte budget.");
|
|
191
|
-
result[path] = setupHash(await readFile(join(project.directory, path)));
|
|
192
|
-
}
|
|
206
|
+
else if (info.isFile()) result[path] = await snapshotFile(join(project.directory, path), info, signal);
|
|
193
207
|
}
|
|
194
208
|
}
|
|
195
209
|
return result;
|
|
@@ -224,7 +238,7 @@ function setupRuntime(project, apiOrigin, selectedProfile = packageProfile()) {
|
|
|
224
238
|
}
|
|
225
239
|
if (operation.effect.package_manager !== current.packageManager) throw new SetupError("setup_command_mismatch", "The package manager differs from the reviewed command.");
|
|
226
240
|
for (const item of operation.effect.packages) if (item.version !== (item.name === "@userreason/js" ? profile.sdkVersion : profile.cliVersion)) throw new SetupError("setup_package_version", "The approved package version differs from this local package profile.");
|
|
227
|
-
const before = await snapshot(project);
|
|
241
|
+
const before = await snapshot(project, signal);
|
|
228
242
|
for (const file2 of operation.files.filter((file3) => file3.path !== "package.json")) await writeSetupFile(project.directory, file2);
|
|
229
243
|
for (const item of operation.effect.packages) {
|
|
230
244
|
signal.throwIfAborted();
|
|
@@ -234,7 +248,7 @@ function setupRuntime(project, apiOrigin, selectedProfile = packageProfile()) {
|
|
|
234
248
|
const actual = await readSetupFile(project.directory, manifest.path);
|
|
235
249
|
if (!actual || setupDigest(JSON.parse(actual)) !== setupDigest(JSON.parse(manifest.after))) throw new Error("The package manager made unexpected manifest changes");
|
|
236
250
|
await writeSetupFile(project.directory, { ...manifest, before: actual });
|
|
237
|
-
const after = await snapshot(project), allowed = /* @__PURE__ */ new Set([...operation.files.map((file2) => file2.path), ...(operation.effect.managed_outputs ?? []).map((file2) => file2.path)]);
|
|
251
|
+
const after = await snapshot(project, signal), allowed = /* @__PURE__ */ new Set([...operation.files.map((file2) => file2.path), ...(operation.effect.managed_outputs ?? []).map((file2) => file2.path)]);
|
|
238
252
|
for (const path of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) if (!allowed.has(path) && before[path] !== after[path]) throw new Error("The package manager changed an unreviewed project file");
|
|
239
253
|
return "verified";
|
|
240
254
|
},
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
connectSetup,
|
|
4
4
|
resumeSetup,
|
|
5
5
|
runSetup
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-5EAHX5BX.js";
|
|
7
7
|
import {
|
|
8
8
|
clean,
|
|
9
9
|
openBrowser
|
|
@@ -46,14 +46,14 @@ async function runBrowserWizard(input) {
|
|
|
46
46
|
let connected;
|
|
47
47
|
try {
|
|
48
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}`,
|
|
49
|
+
terminal.block("Continue in your browser", [url, `Verification code: ${code}`, "Choose your workspace, site and installation options in the browser."]);
|
|
50
50
|
if (!input.noOpen && !await openBrowser(url)) terminal.info("Open the link above to continue.");
|
|
51
51
|
}, {
|
|
52
52
|
signal,
|
|
53
53
|
browserOrigin: input.browserOrigin,
|
|
54
|
-
automaticSetup:
|
|
54
|
+
automaticSetup: true,
|
|
55
55
|
measurementDisabled: input.measurementDisabled,
|
|
56
|
-
|
|
56
|
+
launcher: { wizard_version: input.version, api_origin: apiOrigin, ...input.profile.kind === "local-development" ? { registry: input.profile.registry } : {} }
|
|
57
57
|
});
|
|
58
58
|
} catch (error) {
|
|
59
59
|
if (!input.resumeId && error instanceof BrowserSetupUnavailable) return false;
|
package/dist/setup-flow.js
CHANGED
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
setupResumeCommand,
|
|
6
6
|
setupSampleCommand,
|
|
7
7
|
setupSummary
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-FWEZ2ZWN.js";
|
|
9
|
+
import "./chunk-5EAHX5BX.js";
|
|
10
10
|
import "./chunk-4INLEQE2.js";
|
|
11
11
|
import "./chunk-SB3AYQWG.js";
|
|
12
12
|
import "./chunk-LEJFE4U5.js";
|
package/dist/setup.js
CHANGED