onbuzz 4.9.9 → 4.9.11

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/bin/cli.js CHANGED
@@ -12,14 +12,16 @@
12
12
  * loxia trigger-schedule <id> - Trigger a scheduled task (wakes server if needed)
13
13
  */
14
14
 
15
- import { fileURLToPath } from 'url';
16
15
  import { dirname, join } from 'path';
17
16
  import { spawn } from 'child_process';
18
17
  import { readFileSync } from 'fs';
19
18
  import http from 'http';
20
19
  import { runUpdateCheck } from '../src/utilities/updateNotifier.js';
20
+ import { resolveModuleFilename } from '../src/utilities/esmCjsPath.js';
21
21
 
22
- const __filename = fileURLToPath(import.meta.url);
22
+ // Dual-mode filename — works as native ESM and inside an esbuild
23
+ // --format=cjs bundle. See src/utilities/esmCjsPath.js.
24
+ const __filename = resolveModuleFilename(import.meta.url);
23
25
  const __dirname = dirname(__filename);
24
26
 
25
27
  // Fire the update-notifier check as soon as the process starts. The
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "onbuzz",
3
- "version": "4.9.9",
3
+ "version": "4.9.11",
4
4
  "description": "Loxia OnBuzz - Your AI Fleet",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -673,11 +673,20 @@ class AgentPool {
673
673
  }
674
674
 
675
675
  /**
676
- * Resume agent from persisted state
676
+ * Rehydrate an agent from persisted state on session boot. NOT the
677
+ * pause-toggle (see `resumeAgent(agentId)` below). The two were
678
+ * historically both named `resumeAgent`, which made this one dead
679
+ * code — JS class bodies keep the second definition only, so callers
680
+ * passing an object ended up in the id-based handler and silently got
681
+ * "Agent not found".
682
+ *
683
+ * Callers: agentPool.restoreAgent, which is in turn called from
684
+ * orchestrator's boot-time state restoration path.
685
+ *
677
686
  * @param {Object} agentData - Persisted agent data
678
687
  * @returns {Promise<Object>} Restored agent object
679
688
  */
680
- async resumeAgent(agentData) {
689
+ async rehydrateFromState(agentData) {
681
690
  const agent = {
682
691
  ...agentData,
683
692
  status: agentData.status === 'paused' && this._isPauseExpired(agentData) ? 'active' : agentData.status
@@ -846,12 +855,13 @@ class AgentPool {
846
855
  }
847
856
 
848
857
  /**
849
- * Restore agent from saved state
858
+ * Restore agent from saved state. Thin wrapper around rehydrateFromState
859
+ * kept for the public-API name orchestrator + stateManager still use.
850
860
  * @param {Object} agentState - Saved agent state
851
861
  * @returns {Promise<Object>} Restored agent
852
862
  */
853
863
  async restoreAgent(agentState) {
854
- return await this.resumeAgent(agentState);
864
+ return await this.rehydrateFromState(agentState);
855
865
  }
856
866
 
857
867
  /**
package/src/index.js CHANGED
@@ -9,9 +9,9 @@
9
9
  */
10
10
 
11
11
  import path from 'path';
12
- import { fileURLToPath } from 'url';
13
12
  import { exec } from 'child_process';
14
13
  import { createLogger } from './utilities/logger.js';
14
+ import { resolveModuleFilename } from './utilities/esmCjsPath.js';
15
15
  import { createConfigManager } from './utilities/configManager.js';
16
16
  import Orchestrator from './core/orchestrator.js';
17
17
  import AgentPool from './core/agentPool.js';
@@ -152,7 +152,7 @@ class LoxiaApplication {
152
152
  * @private
153
153
  */
154
154
  async initializeConfig(options) {
155
- const __filename = fileURLToPath(import.meta.url);
155
+ const __filename = resolveModuleFilename(import.meta.url);
156
156
  const __dirname = path.dirname(__filename);
157
157
 
158
158
  const configPaths = [
@@ -1208,8 +1208,8 @@ async function main() {
1208
1208
  return app;
1209
1209
  }
1210
1210
 
1211
- // Start the application if this file is run directly
1212
- const __filename = fileURLToPath(import.meta.url);
1211
+ // Start the application if this file is run directly.
1212
+ const __filename = resolveModuleFilename(import.meta.url);
1213
1213
  if (process.argv[1] === __filename) {
1214
1214
  console.log('🚀 Starting Loxia Autopilot One...');
1215
1215
  main().catch(error => {
@@ -5,9 +5,9 @@
5
5
 
6
6
  import fs from 'fs';
7
7
  import path from 'path';
8
- import { fileURLToPath } from 'url';
8
+ import { resolveModuleFilename } from '../../../utilities/esmCjsPath.js';
9
9
 
10
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const __dirname = path.dirname(resolveModuleFilename(import.meta.url));
11
11
  const LOG_FILE = path.join(__dirname, '../../../../debug-terminal-ui.log');
12
12
 
13
13
  // Clear log file on startup
@@ -14,7 +14,7 @@ import { WebSocketServer } from 'ws';
14
14
  import path from 'path';
15
15
  import { promises as fs, createReadStream } from 'fs';
16
16
  import { execSync, spawn } from 'child_process';
17
- import { fileURLToPath } from 'url';
17
+ import { resolveModuleFilename } from '../utilities/esmCjsPath.js';
18
18
 
19
19
  import {
20
20
  INTERFACE_TYPES,
@@ -64,7 +64,7 @@ import { registerSchedulerRoutes } from './schedulerRoutes.js';
64
64
  import { registerAgentContextRoutes } from './agentContextRoutes.js';
65
65
  import { getMemoryService } from '../services/memoryService.js';
66
66
 
67
- const __filename = fileURLToPath(import.meta.url);
67
+ const __filename = resolveModuleFilename(import.meta.url);
68
68
  const __dirname = path.dirname(__filename);
69
69
 
70
70
  // Self-contained HTML for the /scheduler debug viewer. No external deps;
@@ -14,6 +14,7 @@ import { promises as fs } from 'fs';
14
14
  import path from 'path';
15
15
  import { execSync } from 'child_process';
16
16
  import { getUserDataDir } from '../utilities/userDataDir.js';
17
+ import { resolveModuleFilename } from '../utilities/esmCjsPath.js';
17
18
 
18
19
  // ========================
19
20
  // Lightweight cron parser (no external dependency)
@@ -531,7 +532,7 @@ class ScheduleService {
531
532
  return execSync(which, { encoding: 'utf-8' }).trim().split('\n')[0];
532
533
  } catch {
533
534
  // Fallback to local bin
534
- const __dirname = path.dirname(new URL(import.meta.url).pathname);
535
+ const __dirname = path.dirname(resolveModuleFilename(import.meta.url));
535
536
  const localBin = path.resolve(__dirname, '../../bin/cli.js');
536
537
  return `node "${localBin}"`;
537
538
  }
@@ -13,7 +13,7 @@ import express from 'express';
13
13
  import { createProxyMiddleware } from 'http-proxy-middleware';
14
14
  import { WebSocketServer } from 'ws';
15
15
  import path from 'path';
16
- import { fileURLToPath } from 'url';
16
+ import { resolveModuleFilename } from '../utilities/esmCjsPath.js';
17
17
  import { Transform } from 'stream';
18
18
  import https from 'https';
19
19
  import http from 'http';
@@ -36,7 +36,7 @@ function getBridge() {
36
36
  return bridgeGetter();
37
37
  }
38
38
 
39
- const __filename = fileURLToPath(import.meta.url);
39
+ const __filename = resolveModuleFilename(import.meta.url);
40
40
  const __dirname = path.dirname(__filename);
41
41
 
42
42
  // Service name for registry
@@ -21,7 +21,7 @@
21
21
 
22
22
  import fs from 'fs/promises';
23
23
  import path from 'path';
24
- import { createRequire } from 'module';
24
+ import { resolveLocalRequire } from '../../utilities/esmCjsPath.js';
25
25
 
26
26
  // Themed-presentation system. Opt-in via `theme: '<preset-name>'` on
27
27
  // the spec — when present we route to the new builder for stunning
@@ -35,7 +35,7 @@ import { fillPres } from './pres/edit/fill.js';
35
35
  // `import JSZip from 'jszip'` which jszip (CJS-only) does not satisfy
36
36
  // cleanly under jest's experimental-vm-modules. Loading via createRequire
37
37
  // resolves the CJS build, which is well-behaved in both Node and Jest.
38
- const localRequire = createRequire(import.meta.url);
38
+ const localRequire = resolveLocalRequire(import.meta.url);
39
39
 
40
40
  let pptxgen = null;
41
41
  let JSZip = null;
@@ -20,9 +20,9 @@
20
20
  * Returns { path, size, replaced: {token:count}, unresolved: [...] }.
21
21
  */
22
22
  import fs from 'fs/promises';
23
- import { createRequire } from 'module';
23
+ import { resolveLocalRequire } from '../../../../utilities/esmCjsPath.js';
24
24
 
25
- const localRequire = createRequire(import.meta.url);
25
+ const localRequire = resolveLocalRequire(import.meta.url);
26
26
  let JSZip = null;
27
27
  function loadZip() {
28
28
  if (JSZip) return JSZip;
@@ -10,9 +10,9 @@
10
10
  * Used by the `pres.read` action.
11
11
  */
12
12
  import fs from 'fs/promises';
13
- import { createRequire } from 'module';
13
+ import { resolveLocalRequire } from '../../../../utilities/esmCjsPath.js';
14
14
 
15
- const localRequire = createRequire(import.meta.url);
15
+ const localRequire = resolveLocalRequire(import.meta.url);
16
16
  let JSZip = null;
17
17
  function loadZip() {
18
18
  if (JSZip) return JSZip;
@@ -21,14 +21,14 @@
21
21
  * by the caller in officePres.js.
22
22
  */
23
23
  import fs from 'fs/promises';
24
- import { createRequire } from 'module';
24
+ import { resolveLocalRequire } from '../../../utilities/esmCjsPath.js';
25
25
 
26
26
  import { resolveTheme, listThemes } from './themes/index.js';
27
27
  import { renderArchetype, listArchetypes } from './archetypes/index.js';
28
28
  import { listBackgrounds } from './backgrounds/index.js';
29
29
  import { defineMasters, buildDeckContext, usesChrome } from './master.js';
30
30
 
31
- const localRequire = createRequire(import.meta.url);
31
+ const localRequire = resolveLocalRequire(import.meta.url);
32
32
  let pptxgen = null;
33
33
  function loadPptx() {
34
34
  if (pptxgen) return pptxgen;
@@ -4,10 +4,10 @@
4
4
  */
5
5
 
6
6
  import path from 'path';
7
- import { fileURLToPath } from 'url';
8
7
  import { getSystemRestrictedPaths, getPlatformBlockedExtensions } from './platformUtils.js';
8
+ import { resolveModuleFilename } from './esmCjsPath.js';
9
9
 
10
- const __filename = fileURLToPath(import.meta.url);
10
+ const __filename = resolveModuleFilename(import.meta.url);
11
11
  const __dirname = path.dirname(__filename);
12
12
 
13
13
  // Constants
@@ -20,9 +20,9 @@
20
20
 
21
21
  import { readFileSync } from 'fs';
22
22
  import path from 'path';
23
- import { fileURLToPath } from 'url';
23
+ import { resolveModuleFilename } from './esmCjsPath.js';
24
24
 
25
- const __filename = fileURLToPath(import.meta.url);
25
+ const __filename = resolveModuleFilename(import.meta.url);
26
26
  const __dirname = path.dirname(__filename);
27
27
 
28
28
  let cached = null;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * ESM/CJS dual-mode path + require helpers.
3
+ *
4
+ * Required because we ship the same source two ways:
5
+ * 1. Native ESM via `node bin/cli.js` / `npx loxia` — `import.meta` is
6
+ * a real object and `module`/`require` are not defined.
7
+ * 2. Bundled CJS via `esbuild --format=cjs` for the standalone binary
8
+ * build — `import.meta.url` is empty (esbuild emits a warning and
9
+ * sets it to an empty object), so calling `fileURLToPath` on it
10
+ * throws ERR_INVALID_ARG_TYPE at module load. Meanwhile Node's
11
+ * CJS wrapper provides `module.filename` and `require` directly.
12
+ *
13
+ * `typeof` on an undeclared identifier is the one expression that's
14
+ * safe in both contexts — it returns `'undefined'` without throwing —
15
+ * so we use it to discriminate.
16
+ *
17
+ * Sibling-lookup math note: in the bundle, `module.filename` is the
18
+ * bundled file's path (e.g. `dist-bundle/cli.cjs`), not the original
19
+ * source file's path. That's intentional — pkg's snapshot packages the
20
+ * bundle, not the source tree, so paths derived from `__dirname` need
21
+ * to resolve relative to the bundle.
22
+ */
23
+
24
+ import { fileURLToPath } from 'url';
25
+ import { createRequire } from 'module';
26
+
27
+ /**
28
+ * Pick the right `__filename` for the calling module.
29
+ *
30
+ * @param {string|undefined} metaUrl - pass `import.meta.url` from the call site
31
+ * @returns {string} absolute path of the module's file
32
+ */
33
+ export function resolveModuleFilename(metaUrl) {
34
+ if (typeof require !== 'undefined' && typeof module !== 'undefined' && module.filename) {
35
+ return module.filename;
36
+ }
37
+ return fileURLToPath(metaUrl);
38
+ }
39
+
40
+ /**
41
+ * Pick the right `require` for the calling module.
42
+ *
43
+ * @param {string|undefined} metaUrl - pass `import.meta.url` from the call site
44
+ * @returns {NodeRequire}
45
+ */
46
+ export function resolveLocalRequire(metaUrl) {
47
+ if (typeof require !== 'undefined') {
48
+ return require;
49
+ }
50
+ return createRequire(metaUrl);
51
+ }
@@ -32,7 +32,7 @@
32
32
 
33
33
  import { readFileSync } from 'fs';
34
34
  import { dirname, join } from 'path';
35
- import { fileURLToPath } from 'url';
35
+ import { resolveModuleFilename } from './esmCjsPath.js';
36
36
 
37
37
  /**
38
38
  * Env vars that disable the check. All are case-sensitive string
@@ -65,8 +65,13 @@ export function isUpdateCheckDisabled(env = process.env) {
65
65
  *
66
66
  * @returns {{ name: string, version: string } | null}
67
67
  */
68
+ // Module-load-time default for startDir, in a way that works both as
69
+ // native ESM and inside the esbuild --format=cjs bundle. See
70
+ // src/utilities/esmCjsPath.js.
71
+ const _defaultStartDir = dirname(resolveModuleFilename(import.meta.url));
72
+
68
73
  export function loadPackageJson({
69
- startDir = dirname(fileURLToPath(import.meta.url)),
74
+ startDir = _defaultStartDir,
70
75
  fs = { readFileSync },
71
76
  } = {}) {
72
77
  // Walk up from this file looking for package.json with a `bin`