scenri 0.10.1 → 0.10.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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.10.3](https://github.com/tonygorb/Scenri/compare/v0.10.2...v0.10.3) (2026-09-18)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * look for npm without freezing the server ([db1bde3](https://github.com/tonygorb/Scenri/commit/db1bde3e1450353bd0f62c7ecf2a2796ea2af75d))
9
+ * look for npm without freezing the server ([cec4b03](https://github.com/tonygorb/Scenri/commit/cec4b0327f2dd4f1846e9c9192926876db851ada))
10
+
11
+ ## [0.10.2](https://github.com/tonygorb/Scenri/compare/v0.10.1...v0.10.2) (2026-09-17)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * opening a presenter draft no longer asks a question it takes back ([5605309](https://github.com/tonygorb/Scenri/commit/56053095cf15be7fe021b32060056f33039ee403))
17
+ * opening a presenter draft no longer asks a question it takes back ([6d7f11a](https://github.com/tonygorb/Scenri/commit/6d7f11ada52d8dafa6100f804f85dc2735645868))
18
+ * the transcript keeps the wait once the draft is here too ([d2ad4a0](https://github.com/tonygorb/Scenri/commit/d2ad4a02d0aa57a2ad800283e822ffdf21f5d171))
19
+
3
20
  ## [0.10.1](https://github.com/tonygorb/Scenri/compare/v0.10.0...v0.10.1) (2026-09-16)
4
21
 
5
22
 
@@ -1,5 +1,5 @@
1
1
  import { stagingDir, versionsDir, isValidVersionDir, pruneStaged, entryOf } from './chunk-4MAFHYAD.js';
2
- import { spawnSync, spawn } from 'child_process';
2
+ import { spawn, execFile } from 'child_process';
3
3
  import { existsSync, rmSync, mkdirSync, readFileSync, renameSync } from 'fs';
4
4
  import { join, dirname } from 'path';
5
5
 
@@ -122,37 +122,46 @@ function createUpdateChecker(deps) {
122
122
  }
123
123
  };
124
124
  }
125
- function findNpm(opts = {}) {
125
+ async function findNpm(opts = {}) {
126
126
  const env = opts.env ?? process.env;
127
127
  const platform = opts.platform ?? process.platform;
128
- const canRun = opts.canRun ?? ((argv) => {
129
- try {
130
- return spawnSync(argv[0], [...argv.slice(1), "--version"], { stdio: "ignore", timeout: 1e4 }).status === 0;
131
- } catch {
132
- return false;
133
- }
134
- });
135
- if (platform !== "win32" && canRun(["npm"])) return ["npm"];
128
+ const canRun = opts.canRun ?? answersVersion;
129
+ if (platform !== "win32" && await canRun(["npm"])) return ["npm"];
136
130
  const ep = env.npm_execpath?.replace(/npx-cli\.js$/, "npm-cli.js");
137
- if (ep && /npm-cli\.js$/.test(ep) && canRun([process.execPath, ep])) return [process.execPath, ep];
131
+ if (ep && /npm-cli\.js$/.test(ep) && await canRun([process.execPath, ep])) return [process.execPath, ep];
138
132
  if (platform === "win32") {
139
- const cli = windowsNpmCli();
140
- if (cli && canRun([process.execPath, cli])) return [process.execPath, cli];
133
+ const cli = await windowsNpmCli();
134
+ if (cli && await canRun([process.execPath, cli])) return [process.execPath, cli];
141
135
  }
142
136
  return null;
143
137
  }
138
+ function answersVersion(argv) {
139
+ return new Promise((resolve) => {
140
+ try {
141
+ const child = spawn(argv[0], [...argv.slice(1), "--version"], { stdio: "ignore", timeout: 1e4 });
142
+ child.on("error", () => resolve(false));
143
+ child.on("exit", (code) => resolve(code === 0));
144
+ } catch {
145
+ resolve(false);
146
+ }
147
+ });
148
+ }
144
149
  function windowsNpmCli() {
145
- try {
146
- const out = spawnSync("where", ["npm"], { encoding: "utf8", timeout: 1e4 });
147
- if (out.status !== 0 || !out.stdout) return null;
148
- for (const line of out.stdout.split(/\r?\n/)) {
149
- if (!/npm(\.cmd)?$/i.test(line.trim())) continue;
150
- const cli = join(dirname(line.trim()), "node_modules", "npm", "bin", "npm-cli.js");
151
- if (existsSync(cli)) return cli;
150
+ return new Promise((resolve) => {
151
+ try {
152
+ execFile("where", ["npm"], { encoding: "utf8", timeout: 1e4 }, (err, stdout) => {
153
+ if (err || !stdout) return resolve(null);
154
+ for (const line of stdout.split(/\r?\n/)) {
155
+ if (!/npm(\.cmd)?$/i.test(line.trim())) continue;
156
+ const cli = join(dirname(line.trim()), "node_modules", "npm", "bin", "npm-cli.js");
157
+ if (existsSync(cli)) return resolve(cli);
158
+ }
159
+ resolve(null);
160
+ });
161
+ } catch {
162
+ resolve(null);
152
163
  }
153
- } catch {
154
- }
155
- return null;
164
+ });
156
165
  }
157
166
  function run(argv) {
158
167
  return new Promise((resolve) => {
@@ -181,7 +190,7 @@ async function runVerify(entry) {
181
190
  }
182
191
  async function stageVersion(deps) {
183
192
  const env = deps.env ?? process.env;
184
- const npmArgv = deps.npmArgv !== void 0 ? deps.npmArgv : findNpm({ env });
193
+ const npmArgv = deps.npmArgv !== void 0 ? deps.npmArgv : await findNpm({ env });
185
194
  if (!npmArgv) {
186
195
  return { ok: false, reason: "no-npm", detail: "npm is not reachable from this process" };
187
196
  }
@@ -247,5 +256,5 @@ async function stageVersion(deps) {
247
256
  }
248
257
 
249
258
  export { classify, createUpdateChecker, fetchDistTagLatest, findNpm, isReleaseTriplet, stageVersion };
250
- //# sourceMappingURL=chunk-FYQ5BAFA.js.map
251
- //# sourceMappingURL=chunk-FYQ5BAFA.js.map
259
+ //# sourceMappingURL=chunk-YK37H6DM.js.map
260
+ //# sourceMappingURL=chunk-YK37H6DM.js.map
@@ -1,4 +1,4 @@
1
- import { stageVersion, fetchDistTagLatest, findNpm } from './chunk-FYQ5BAFA.js';
1
+ import { stageVersion, fetchDistTagLatest, findNpm } from './chunk-YK37H6DM.js';
2
2
  import { readMeta } from './chunk-Y3ZPBPLP.js';
3
3
  import { defaultHome, newestStaged, compareSemver } from './chunk-4MAFHYAD.js';
4
4
 
@@ -41,7 +41,7 @@ async function runUpdateCommand(opts) {
41
41
  console.log(` ${latest} is available. Stage it with: scenri update`);
42
42
  return 0;
43
43
  }
44
- if (!findNpm()) {
44
+ if (!await findNpm()) {
45
45
  console.error(" npm is not reachable from here, so nothing can be downloaded.");
46
46
  console.error(" Run the newest version directly with: npx scenri@latest");
47
47
  console.error(" (or install Node.js with npm and try again)");
@@ -63,5 +63,5 @@ async function runUpdateCommand(opts) {
63
63
  }
64
64
 
65
65
  export { runUpdateCommand };
66
- //# sourceMappingURL=cli-KSKENGIR.js.map
67
- //# sourceMappingURL=cli-KSKENGIR.js.map
66
+ //# sourceMappingURL=cli-VBJGIJI4.js.map
67
+ //# sourceMappingURL=cli-VBJGIJI4.js.map
package/dist/index.js CHANGED
@@ -81,7 +81,7 @@ try {
81
81
  await (await import('./serve.js')).serve();
82
82
  break;
83
83
  case "update": {
84
- const { runUpdateCommand } = await import('./cli-KSKENGIR.js');
84
+ const { runUpdateCommand } = await import('./cli-VBJGIJI4.js');
85
85
  process.exit(await runUpdateCommand(command));
86
86
  break;
87
87
  }
package/dist/serve.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createUpdateChecker, classify, isReleaseTriplet, findNpm, stageVersion } from './chunk-FYQ5BAFA.js';
1
+ import { createUpdateChecker, classify, findNpm, isReleaseTriplet, stageVersion } from './chunk-YK37H6DM.js';
2
2
  import { shouldAdoptRunning, anotherScenriLines, portBusyLines } from './chunk-CMLJGPYC.js';
3
3
  import { SchemaTooNewError, createCore, BUDGET_EXHAUSTED, SpendCapError, EDIT_REFERENCE_ROLE_DIRECTIVE, REFERENCE_ROLE_DIRECTIVE, ratioLabel, searchTerms, termMatches, budgetSize, SCHEMA_VERSION, ASPECT_TOLERANCE } from './chunk-UUYMUOZQ.js';
4
4
  import { detectInstallKind } from './chunk-PAIAXRAC.js';
@@ -11703,6 +11703,26 @@ function registerImageRoutes(app, deps) {
11703
11703
 
11704
11704
  // src/release/notes.data.ts
11705
11705
  var RELEASES = [
11706
+ {
11707
+ version: "0.10.3",
11708
+ date: "2026-09-18",
11709
+ sections: [
11710
+ {
11711
+ heading: "Fixes",
11712
+ body: "Scenri no longer stops answering for a moment right after the studio opens, while it checks whether one-click updates can run here. On Windows that pause could last several seconds, long enough for a second click on the desktop icon to start Scenri again instead of opening the one already running."
11713
+ }
11714
+ ]
11715
+ },
11716
+ {
11717
+ version: "0.10.2",
11718
+ date: "2026-09-17",
11719
+ sections: [
11720
+ {
11721
+ heading: "Presenters",
11722
+ body: "Opening a saved presenter draft goes straight to where the conversation left off, instead of briefly asking who you are making and then taking the question back."
11723
+ }
11724
+ ]
11725
+ },
11706
11726
  {
11707
11727
  version: "0.10.1",
11708
11728
  date: "2026-09-16",
@@ -12520,14 +12540,22 @@ function registerUpdateRoutes(app, deps) {
12520
12540
  return applyState;
12521
12541
  };
12522
12542
  const REQUIRED_PROTOCOL = 1;
12523
- let npmProbe = null;
12543
+ let npmFound = false;
12544
+ let npmAsked = null;
12545
+ const npmKnown = () => {
12546
+ if (runtime.installKind === "dev" || !runtime.supervised || deps.stageImpl) return Promise.resolve();
12547
+ npmAsked ??= findNpm().then((argv) => {
12548
+ npmFound = argv !== null;
12549
+ }).catch(() => {
12550
+ });
12551
+ return npmAsked;
12552
+ };
12524
12553
  const blockReason = () => {
12525
12554
  if (runtime.installKind === "dev") return "dev";
12526
12555
  if (!runtime.supervised) return "unsupervised";
12527
12556
  if ((runtime.launcherProtocol ?? 1) < REQUIRED_PROTOCOL) return "launcher-too-old";
12528
12557
  if (deps.stageImpl) return null;
12529
- npmProbe ??= findNpm() !== null;
12530
- return npmProbe ? null : "no-npm";
12558
+ return npmFound ? null : "no-npm";
12531
12559
  };
12532
12560
  const startStaging = (target) => {
12533
12561
  applyState = { phase: "staging", version: target, error: null };
@@ -12555,12 +12583,13 @@ function registerUpdateRoutes(app, deps) {
12555
12583
  };
12556
12584
  updates.onResult(maybeAutoStage);
12557
12585
  const bootLook = setTimeout(() => {
12558
- updates.check().then(maybeAutoStage).catch(() => {
12586
+ npmKnown().then(() => updates.check()).then(maybeAutoStage).catch(() => {
12559
12587
  });
12560
12588
  }, deps.bootLookMs ?? 15e3);
12561
12589
  bootLook.unref();
12562
12590
  app.addHook("onClose", async () => clearTimeout(bootLook));
12563
12591
  const updateStatus = async (force = false) => {
12592
+ await npmKnown();
12564
12593
  const r = await updates.check(force);
12565
12594
  const kind = r.latest ? classify(meta.version, r.latest) : null;
12566
12595
  const apply = effectiveApply();
@@ -12591,6 +12620,7 @@ function registerUpdateRoutes(app, deps) {
12591
12620
  if (busy > 0) {
12592
12621
  return reply.status(409).send({ error: `work is still running (${busy} task${busy === 1 ? "" : "s"})` });
12593
12622
  }
12623
+ await npmKnown();
12594
12624
  const block = blockReason();
12595
12625
  if (block)
12596
12626
  return reply.status(409).send({ error: `one-click update cannot run here (${block})`, blockReason: block });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scenri",
3
- "version": "0.10.1",
3
+ "version": "0.10.3",
4
4
  "author": "Tony Gorb <hello@scenri.co>",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",