local-operator-ui 0.24.4 → 0.24.6

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 (2) hide show
  1. package/out/main/index.js +29 -1
  2. package/package.json +5 -4
package/out/main/index.js CHANGED
@@ -4798,6 +4798,12 @@ function isLegacyManagedCommand(command, support) {
4798
4798
  (candidate) => legacy.some((path2) => candidate.includes(`${path2}/`)) || LEGACY_BUNDLE_PYTHON_PATH.test(candidate)
4799
4799
  );
4800
4800
  }
4801
+ const NOTIFICATIONS_ENV = "LOCAL_OPERATOR_NO_NOTIFICATIONS";
4802
+ function resolveNotificationLaunch(env) {
4803
+ const value = env[NOTIFICATIONS_ENV];
4804
+ if (value === void 0) return {};
4805
+ return { [NOTIFICATIONS_ENV]: value === "" ? "1" : value };
4806
+ }
4801
4807
  const PACKAGED_VENV_DIR_NAME = "local-operator-venv";
4802
4808
  const DEV_VENV_DIR_NAME = "local-operator-venv-dev";
4803
4809
  const NO_SELECTION_DIR_NAME = "no-environment-selected";
@@ -5506,6 +5512,12 @@ class BackendServiceManager {
5506
5512
  * CPython writes `__pycache__/*.pyc` beside the sources it imports, those
5507
5513
  * sources are inside the code-sealed `.app`, and every such write breaks the
5508
5514
  * signature ShipIt validates before an in-place update.
5515
+ *
5516
+ * The notification kill switch joins it here for the same reason, one level
5517
+ * further out: the environment this returns is also where a `.env` folded
5518
+ * over the launch, or a shell rc merged over that, would otherwise be the
5519
+ * one that decides whether the backend this app spawns can banner the
5520
+ * operator (see the comment on that entry, and `./notification-launch`).
5509
5521
  */
5510
5522
  backendSpawnEnv() {
5511
5523
  return {
@@ -5514,7 +5526,23 @@ class BackendServiceManager {
5514
5526
  // can never inherit a stale one from the shell environment. `start()`
5515
5527
  // mints it before it can reach a spawn site, so the `??` only satisfies
5516
5528
  // the field's nullable seed from `process.env`.
5517
- LOCAL_OPERATOR_DESKTOP_TOKEN: this.desktopToken ?? void 0
5529
+ LOCAL_OPERATOR_DESKTOP_TOKEN: this.desktopToken ?? void 0,
5530
+ /*
5531
+ * LAST, and from `launchEnv` rather than from `this.shellEnv`: the
5532
+ * notification kill switch is a fact about the LAUNCH, and `shellEnv`
5533
+ * is where that fact can be lost twice over. `backend/config.ts` folds
5534
+ * a `.env` from the working directory with dotenv `override: true`
5535
+ * AFTER the launch, and `loadMacOSEnvironment` merges the operator's
5536
+ * own shell rc on top of that - so a file or an rc can replace the
5537
+ * value `pnpm app:headless` set, and the empty shape it leaves behind
5538
+ * reads as ENABLED in the backend, which is the incident back.
5539
+ * Applying it here, at the point the environment is handed to the
5540
+ * spawn, is what the python bytecode prefix above already does for the
5541
+ * same reason: structural, so no spawn path and no fold order can miss
5542
+ * it. See `./notification-launch` for the three cases and why an
5543
+ * unstated key is left alone.
5544
+ */
5545
+ ...resolveNotificationLaunch(launchEnv)
5518
5546
  };
5519
5547
  }
5520
5548
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-operator-ui",
3
- "version": "0.24.4",
3
+ "version": "0.24.6",
4
4
  "productName": "Local Operator",
5
5
  "description": "User interface for AI agent assistants that run Python code safely on your device through an intuitive chat interface. Supports local and cloud LLM models with built-in security features.",
6
6
  "main": "./out/main/index.js",
@@ -50,9 +50,10 @@
50
50
  },
51
51
  "scripts": {
52
52
  "start": "electron-vite preview",
53
- "app:headless": "LOCAL_OPERATOR_UI_WINDOW_MODE=headless electron .",
53
+ "app:headless": "LOCAL_OPERATOR_NO_NOTIFICATIONS=1 LOCAL_OPERATOR_UI_WINDOW_MODE=headless electron .",
54
+ "//app:headless": "The agent-driven launch, so it carries the notification kill switch (scripts/notifications-off.mjs). `headless` silences this app's OWN banner and cannot reach the backend's: the app spawns a backend, and that backend's parked-gate announcement ends at `osascript` on macOS, whose banner lands in the operator's real Notification Center attributed to Script Editor. `pnpm start` and `pnpm dev` are a person's own app at their own screen and keep their banners.",
54
55
  "dev": "npx dotenv-cli -e .env -- bash -c 'export $(grep -v '^#' .env | xargs) && electron-vite dev'",
55
- "dev:headless": "LOCAL_OPERATOR_UI_WINDOW_MODE=headless pnpm dev",
56
+ "dev:headless": "LOCAL_OPERATOR_NO_NOTIFICATIONS=1 LOCAL_OPERATOR_UI_WINDOW_MODE=headless pnpm dev",
56
57
  "build": "electron-vite build",
57
58
  "//prebuild": "The build compiles main/preload to V8 bytecode for the pinned Electron, so it needs a real node_modules/electron/dist before electron-vite runs. Since Electron 42 nothing fetches that during an install except our own postinstall, so this hook covers the trees that hook cannot reach (--ignore-scripts, or a dist/ removed by hand) and fails the build by name instead of letting it die inside the bytecode step with an ENOENT. build:npm needs no runtime: it deliberately emits plain JS (LOCAL_OPERATOR_UI_NO_BYTECODE=true).",
58
59
  "prebuild": "node ./bin/ensure-electron.js",
@@ -70,7 +71,7 @@
70
71
  "check-types:renderer": "tsc --noEmit -p tsconfig.app.json",
71
72
  "check-types": "pnpm run check-types:main && pnpm run check-types:renderer",
72
73
  "test:session-cookies": "node scripts/session-cookie-electron.test.mjs",
73
- "test:desktop": "node scripts/run-desktop-tests.mjs scripts/slash-token.test.mjs scripts/slash-rank.test.mjs scripts/slash-submit.test.mjs scripts/slash-contract.test.mjs scripts/slash-row-format.test.mjs scripts/owned-serve-lifecycle.test.mjs scripts/linux-sandbox.test.mjs scripts/capture-evidence.test.mjs scripts/desktop-contract.test.mjs scripts/transcript-reducer.test.mjs scripts/transcript-paging.test.mjs scripts/provider-state.test.mjs scripts/stale-agent.test.mjs scripts/desktop-renderer-transport.test.mjs scripts/desktop-proxy.test.mjs scripts/session-stream-token.test.mjs scripts/session-load-recovery.test.mjs scripts/provider-grid-error-copy.test.mjs scripts/settings-time-to-error.test.mjs scripts/backend-error-surfaces.test.mjs scripts/canonical-chat.test.mjs scripts/stale-caption.test.mjs scripts/desktop-watch-lease.test.mjs scripts/session-switch.test.mjs scripts/chat-search.test.mjs scripts/run-detail-model.test.mjs scripts/subagent-pulse.test.mjs scripts/chat-title.test.mjs scripts/clear-search.test.mjs scripts/tool-row.test.mjs scripts/attachment-url.test.mjs scripts/desktop-notifier.test.mjs scripts/launch-session.test.mjs scripts/desktop-feed.test.mjs scripts/viewer-record.test.mjs scripts/desktop-stream.test.mjs scripts/python-bytecode-cache.test.mjs scripts/update-affirmation.test.mjs scripts/update-robustness.test.mjs scripts/prune-python-resource.test.mjs scripts/managed-python.test.mjs scripts/usage-view.test.mjs scripts/usage-container.test.mjs scripts/session-status.test.mjs scripts/composer-readings.test.mjs scripts/composer-tabs.test.mjs scripts/ask-options.test.mjs scripts/window-mode.test.mjs scripts/evidence-manifest.test.mjs scripts/canonical-notice.test.mjs scripts/evidence-run-guard.test.mjs scripts/desktop-test-concurrency.test.mjs scripts/run-desktop-tests.test.mjs scripts/mcp-foreign-config-origin.test.mjs scripts/mentioned-files.test.mjs scripts/picker-feedback.test.mjs scripts/panel-chart-motion.test.mjs scripts/panel-info-credentials.test.mjs scripts/warm-session.test.mjs scripts/submit-latency.test.mjs scripts/completion-view-ack.test.mjs scripts/echo-delivery.test.mjs scripts/check-runtime-deps.test.mjs scripts/new-chat-row.test.mjs scripts/new-chat-row-evidence.test.mjs scripts/reconnect-page-gap.test.mjs scripts/browser-host.test.mjs scripts/check-vendored.test.mjs scripts/chat-session-status.test.mjs scripts/draft-selection.test.mjs scripts/toast-lifetime.test.mjs scripts/storybook-query-fixture.test.mjs scripts/mcp-list-query.test.mjs scripts/mcp-target-resolution.test.mjs scripts/mcp-auth-surface.test.mjs scripts/mcp-failure-routing.test.mjs scripts/daemon-discovery.test.mjs scripts/daemon-health-state.test.mjs scripts/daemon-observation.test.mjs scripts/session-cookies.test.mjs scripts/move-session.test.mjs scripts/frontend-replace.test.mjs scripts/browser-chrome.test.mjs scripts/dev-driver-gate.test.mjs scripts/logger-log-dir.test.mjs scripts/draft-splash.test.mjs scripts/suggestion-stack.test.mjs scripts/suggestion-stack-react.test.mjs",
74
+ "test:desktop": "node scripts/run-desktop-tests.mjs scripts/slash-token.test.mjs scripts/slash-rank.test.mjs scripts/slash-submit.test.mjs scripts/slash-contract.test.mjs scripts/slash-row-format.test.mjs scripts/owned-serve-lifecycle.test.mjs scripts/linux-sandbox.test.mjs scripts/capture-evidence.test.mjs scripts/desktop-contract.test.mjs scripts/transcript-reducer.test.mjs scripts/transcript-paging.test.mjs scripts/provider-state.test.mjs scripts/stale-agent.test.mjs scripts/desktop-renderer-transport.test.mjs scripts/desktop-proxy.test.mjs scripts/session-stream-token.test.mjs scripts/session-load-recovery.test.mjs scripts/provider-grid-error-copy.test.mjs scripts/settings-time-to-error.test.mjs scripts/backend-error-surfaces.test.mjs scripts/canonical-chat.test.mjs scripts/stale-caption.test.mjs scripts/desktop-watch-lease.test.mjs scripts/session-switch.test.mjs scripts/chat-search.test.mjs scripts/run-detail-model.test.mjs scripts/subagent-pulse.test.mjs scripts/chat-title.test.mjs scripts/clear-search.test.mjs scripts/tool-row.test.mjs scripts/attachment-url.test.mjs scripts/desktop-notifier.test.mjs scripts/launch-session.test.mjs scripts/desktop-feed.test.mjs scripts/viewer-record.test.mjs scripts/desktop-stream.test.mjs scripts/python-bytecode-cache.test.mjs scripts/update-affirmation.test.mjs scripts/update-robustness.test.mjs scripts/prune-python-resource.test.mjs scripts/managed-python.test.mjs scripts/usage-view.test.mjs scripts/usage-container.test.mjs scripts/session-status.test.mjs scripts/composer-readings.test.mjs scripts/composer-tabs.test.mjs scripts/ask-options.test.mjs scripts/window-mode.test.mjs scripts/evidence-manifest.test.mjs scripts/canonical-notice.test.mjs scripts/evidence-run-guard.test.mjs scripts/desktop-test-concurrency.test.mjs scripts/run-desktop-tests.test.mjs scripts/mcp-foreign-config-origin.test.mjs scripts/mentioned-files.test.mjs scripts/picker-feedback.test.mjs scripts/panel-chart-motion.test.mjs scripts/panel-info-credentials.test.mjs scripts/warm-session.test.mjs scripts/submit-latency.test.mjs scripts/completion-view-ack.test.mjs scripts/echo-delivery.test.mjs scripts/check-runtime-deps.test.mjs scripts/new-chat-row.test.mjs scripts/new-chat-row-evidence.test.mjs scripts/reconnect-page-gap.test.mjs scripts/browser-host.test.mjs scripts/check-vendored.test.mjs scripts/chat-session-status.test.mjs scripts/draft-selection.test.mjs scripts/toast-lifetime.test.mjs scripts/storybook-query-fixture.test.mjs scripts/mcp-list-query.test.mjs scripts/mcp-target-resolution.test.mjs scripts/mcp-auth-surface.test.mjs scripts/mcp-failure-routing.test.mjs scripts/daemon-discovery.test.mjs scripts/daemon-health-state.test.mjs scripts/daemon-observation.test.mjs scripts/session-cookies.test.mjs scripts/move-session.test.mjs scripts/frontend-replace.test.mjs scripts/browser-chrome.test.mjs scripts/dev-driver-gate.test.mjs scripts/logger-log-dir.test.mjs scripts/draft-splash.test.mjs scripts/suggestion-stack.test.mjs scripts/suggestion-stack-react.test.mjs scripts/notifications-off.test.mjs scripts/notification-launch.test.mjs scripts/notification-spawn-sites.test.mjs",
74
75
  "check-themes": "node scripts/generate-theme-css.mjs --check && node scripts/contrast-contract.mjs",
75
76
  "check-vendored": "node scripts/check-vendored.mjs",
76
77
  "check-evidence": "node scripts/check-evidence.mjs",