fraim-hub 2.0.279 → 2.0.280

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.
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveBundledAssetPath = resolveBundledAssetPath;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ /**
10
+ * Resolves a bundled asset that ships at a different relative depth depending on how the
11
+ * Hub is launched (`npx fraim-hub` unpacked, `npm run hub:desktop`, or a packaged app).
12
+ *
13
+ * Checks, in order: relative to the current working directory, then relative to
14
+ * `moduleDir` (pass `__dirname` from the caller) two and three levels up - the depths
15
+ * `dist/src/ai-hub/` sits at relative to a package root. Returns the first path that
16
+ * exists on disk, or null if none do, so callers can fall back rather than crash on a
17
+ * packaging gap.
18
+ *
19
+ * No Electron import here on purpose: `electron` resolves to a plain path string outside
20
+ * an Electron process, so anything that touches it can only run inside one. Keeping this
21
+ * resolution logic Electron-free is what makes it unit-testable with plain `node:test`.
22
+ */
23
+ function resolveBundledAssetPath(relativePath, moduleDir, cwd = process.cwd()) {
24
+ const candidates = [
25
+ path_1.default.resolve(cwd, relativePath),
26
+ path_1.default.resolve(moduleDir, '..', '..', relativePath),
27
+ path_1.default.resolve(moduleDir, '..', '..', '..', relativePath),
28
+ ];
29
+ return candidates.find((c) => fs_1.default.existsSync(c)) ?? null;
30
+ }
@@ -15,6 +15,7 @@ const project_fraim_paths_1 = require("../core/utils/project-fraim-paths");
15
15
  const version_utils_1 = require("../cli/utils/version-utils");
16
16
  const hub_runtime_file_1 = require("./hub-runtime-file");
17
17
  const window_open_decision_1 = require("./window-open-decision");
18
+ const bundled_asset_resolver_1 = require("./bundled-asset-resolver");
18
19
  // ---------------------------------------------------------------------------
19
20
  // State
20
21
  // ---------------------------------------------------------------------------
@@ -61,19 +62,22 @@ function applyUserDataOverride() {
61
62
  electron_1.app.setPath('userData', userDataDir);
62
63
  }
63
64
  // ---------------------------------------------------------------------------
64
- // Tray icon resolution prefers bundled icon, falls back to a 1×1 empty image
65
- // so the app never crashes if assets aren't present.
65
+ // App icon — the FRAIM logo (#1329), used for the window/taskbar/dock icon
66
+ // and, downscaled, the system tray. Falls back to Electron's own default
67
+ // (window/dock) or an empty image (tray) so a packaging gap never crashes
68
+ // the app. Path resolution itself lives in bundled-asset-resolver.ts, which
69
+ // has no Electron import and so can be unit-tested directly.
66
70
  // ---------------------------------------------------------------------------
71
+ const APP_ICON_RELATIVE_PATH = 'public/ai-hub/fraim-icon.png';
72
+ function resolveAppIcon() {
73
+ const iconPath = (0, bundled_asset_resolver_1.resolveBundledAssetPath)(APP_ICON_RELATIVE_PATH, __dirname);
74
+ return iconPath ? electron_1.nativeImage.createFromPath(iconPath) : null;
75
+ }
67
76
  function resolveTrayIcon() {
68
- const candidates = [
69
- path_1.default.resolve(process.cwd(), 'extensions/office-word/icon-64.png'),
70
- path_1.default.resolve(__dirname, '..', '..', 'extensions/office-word/icon-64.png'),
71
- path_1.default.resolve(__dirname, '..', '..', '..', 'extensions/office-word/icon-64.png'),
72
- ];
73
- for (const c of candidates) {
74
- if (fs_1.default.existsSync(c))
75
- return electron_1.nativeImage.createFromPath(c).resize({ width: 16, height: 16 });
76
- }
77
+ const iconPath = (0, bundled_asset_resolver_1.resolveBundledAssetPath)(APP_ICON_RELATIVE_PATH, __dirname)
78
+ ?? (0, bundled_asset_resolver_1.resolveBundledAssetPath)('extensions/office-word/icon-64.png', __dirname);
79
+ if (iconPath)
80
+ return electron_1.nativeImage.createFromPath(iconPath).resize({ width: 16, height: 16 });
77
81
  return electron_1.nativeImage.createEmpty();
78
82
  }
79
83
  // ---------------------------------------------------------------------------
@@ -210,6 +214,7 @@ async function createWindow(url, runtimeId = process.env.FRAIM_HUB_RUNTIME_ID ||
210
214
  const isWin = process.platform === 'win32';
211
215
  mainWindow = new electron_1.BrowserWindow({
212
216
  title: displayName(runtimeId),
217
+ icon: resolveAppIcon() ?? undefined,
213
218
  width,
214
219
  height,
215
220
  minWidth: 1200,
@@ -407,6 +412,14 @@ async function bootstrap() {
407
412
  });
408
413
  await electron_1.app.whenReady();
409
414
  electron_1.app.setName(displayName(options.runtimeId));
415
+ // macOS reads the dock icon from the app bundle once packaged, but an
416
+ // unpackaged `npm run hub:desktop` / `npx fraim-hub` run shows Electron's
417
+ // own icon there unless we set it explicitly (#1329).
418
+ if (process.platform === 'darwin') {
419
+ const dockIcon = resolveAppIcon();
420
+ if (dockIcon)
421
+ electron_1.app.dock?.setIcon(dockIcon);
422
+ }
410
423
  // First-launch housekeeping (idempotent, fast on subsequent runs)
411
424
  ensureLoginItem();
412
425
  configureAutoUpdater();
@@ -2858,7 +2858,9 @@ class AiHubServer {
2858
2858
  // first event so the ref is always on disk within the same synchronous
2859
2859
  // turn. Subsequent events use the normal debounced path.
2860
2860
  if (ref.eventCount === 1) {
2861
- this.persistRunConversationNow(run, run.conversationId || run.id);
2861
+ // Issue #1009: a delegated child's first raw event must not steal the
2862
+ // active board slot from its parent/orchestrator conversation.
2863
+ this.persistRunConversationNow(run, run.managedByRunId ? undefined : (run.conversationId || run.id));
2862
2864
  }
2863
2865
  }
2864
2866
  catch (error) {
@@ -3043,7 +3045,11 @@ class AiHubServer {
3043
3045
  const run = this.runRegistry.get(runId);
3044
3046
  if (!run)
3045
3047
  return;
3046
- this.persistRunConversationNow(run, activeId ?? run.conversationId ?? run.id);
3048
+ // Issue #1009: a delegated child run finishing or parking must not steal the
3049
+ // active board slot from its parent/orchestrator conversation. Only a
3050
+ // standalone (non-delegated) run's own finalize should claim activeId.
3051
+ const resolvedActiveId = run.managedByRunId ? undefined : (activeId ?? run.conversationId ?? run.id);
3052
+ this.persistRunConversationNow(run, resolvedActiveId);
3047
3053
  console.info('[ai-hub] hub.conversation_projection.finalized', {
3048
3054
  conversationId: run.conversationId || run.id,
3049
3055
  runId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim-hub",
3
- "version": "2.0.279",
3
+ "version": "2.0.280",
4
4
  "description": "FRAIM Hub local companion package.",
5
5
  "bin": {
6
6
  "fraim-hub": "bin/fraim-hub.js",
@@ -135,6 +135,7 @@
135
135
  "repo": "FRAIM"
136
136
  },
137
137
  "win": {
138
+ "icon": "build/icon.ico",
138
139
  "target": [
139
140
  "nsis",
140
141
  "portable"
@@ -146,6 +147,7 @@
146
147
  "allowToChangeInstallationDirectory": true
147
148
  },
148
149
  "mac": {
150
+ "icon": "build/icon.icns",
149
151
  "target": [
150
152
  "dmg",
151
153
  "zip"
@@ -154,6 +156,7 @@
154
156
  "gatekeeperAssess": false
155
157
  },
156
158
  "linux": {
159
+ "icon": "build/icon.png",
157
160
  "target": [
158
161
  "AppImage",
159
162
  "deb"
@@ -176,7 +179,7 @@
176
179
  "electron-updater": "^6.8.9",
177
180
  "express": "^5.2.1",
178
181
  "extract-zip": "^2.0.1",
179
- "fraim": "2.0.279",
182
+ "fraim": "2.0.280",
180
183
  "mongodb": "^7.0.0",
181
184
  "node-cron": "4.2.1",
182
185
  "node-edge-tts": "^1.2.10",
Binary file