* 🐛 fix(python-interpreter): construct the worker as classic, not a module
The worker was constructed with `type: 'module'` while the bundler emits it
as an IIFE, so the declared type never matched the output. It also loads
Pyodide through `importScripts`, and a module worker rejects that call:
TypeError: Failed to execute 'importScripts' on 'WorkerGlobalScope':
Module scripts don't support importScripts().
The failure lands inside `init()`, so nothing surfaces until the interpreter
is first used — construction succeeds and the tool then fails on its first
real call.
Verified end to end in a browser against the built worker: Pyodide loads,
`print("hello from", sys.platform)` writes `hello from emscripten`, and
`6*7` returns 42.
* ✨ feat(build): publish web workers to the public root
`new Worker(url)` only accepts a same-origin script — no CORS header lifts
that, unlike a crossorigin script tag. So once the SPA's assets move to an
asset host, workers are the one thing that has to stay behind, served from
the page's own origin.
The build emits them into `app-workers/`, but `copyDirs` is an allowlist and
did not carry the directory across, so the files reached neither `public/`
nor the asset upload and the emitted URL resolved to nothing.
Copy them to `public/app-workers/` rather than into each SPA directory: the
files are byte-identical across variants, so one path keeps one copy and
gives the origin a single prefix to recognise.
* 🐛 fix(python-interpreter): stop a failed worker from blanking the app
`PythonInterpreter` was built by an IIFE at module scope, so `new Worker`
ran while the module evaluated. That constructor throws synchronously — a
cross-origin script URL and a CSP that forbids workers both do it — and an
exception raised during module evaluation propagates to every importer, so
an unavailable Python interpreter took the whole React tree down with it
instead of disabling one feature.
The consumer was already written for an absent interpreter: it guards on
`typeof Worker` and dereferences with `!`. The module-scope construction
made that intent unreachable, because nothing got far enough to run it.
Construct lazily on first use and treat a throwing constructor as an
unavailable interpreter. The export becomes `getPythonInterpreter()`, since
laziness cannot be expressed through a plain const binding.
* 🐛 fix(python-interpreter): report a blocked interpreter as a failed run
Swallowing the `new Worker` failure handed the caller the same `undefined` a
platform without workers produces, so `ChatCodeInterpreterActionImpl.python`
completed the operation, wrote `JSON.stringify(undefined)` as the message
content and returned true. In the CSP and cross-origin deployments the lazy
construction was written for, every Python tool call reported success without
executing any code.
Remember the construction error and replay it to every caller, and throw from
`pythonService.runPython` when the platform has no worker at all. Both now
reach the existing catch, so the run fails with the platform's own message
instead of a silent empty result.
* ⚡️ perf(chat): load the Python interpreter only when it runs
`chatToolSlice` is assembled into the chat store, so the static import of
`services/python` pulled Comlink, the interpreter package and everything
Pyodide needs into the bundle every chat page loads — for a builtin tool
most sessions never invoke.
Import it at the call site instead. The caller is already async, so the
change is confined to one statement.
* ✨ feat(desktop): implement subscription pages embedding with webview
- Add SubscriptionIframeWrapper component for embedding subscription pages in Electron webview
- Replace compile-time ENABLE_BUSINESS_FEATURES with runtime serverConfigSelectors
- Add useIsCloudActive hook to detect cloud sync status
- Add setupSubscriptionWebviewSession service for webview session management
Resolves LOBE-4589
* ✨ feat: enhance SubscriptionIframeWrapper for improved configuration
- Updated iframe URL to use OFFICIAL_URL for better maintainability.
- Integrated server configuration to conditionally enable business features.
- Cleaned up code by removing commented-out lines and unnecessary eslint suppressions.
This update improves the flexibility and readability of the SubscriptionIframeWrapper component.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat: enhance link interception in SubscriptionIframeWrapper
- Updated the script to intercept both link clicks and window.open calls for better URL handling.
- Added functionality to resolve relative URLs to absolute before logging.
This improvement enhances the tracking of external link interactions within the iframe.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: clean up useIsCloudActive hook
- Removed unnecessary eslint suppressions related to react-hooks rules.
- Improved code readability by eliminating commented-out lines.
This update enhances the clarity and maintainability of the useIsCloudActive hook.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* v2 init
* chore: update eslint suppressions and package dependencies
- Removed several eslint suppressions related to array sorting and reversing from eslint-suppressions.json to clean up the configuration.
- Updated @lobehub/lint package version from 2.0.0-beta.6 to 2.0.0-beta.7 in package.json for improvements and bug fixes.
- Made minor formatting adjustments in vitest.config.mts and various SKILL.md files for better readability and consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: clean up import statements and formatting
- Removed unnecessary whitespace in replaceComponentImports.ts for improved readability.
- Standardized import statements in contextEngineering.ts and createAgentExecutors.ts by adding missing spaces for consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: update eslint suppressions and clean up code formatting
* 🐛 fix: use vi.hoisted for mock variable initialization
Fix TDZ error in persona service test by using vi.hoisted() to ensure
mock variables are available when vi.mock factory runs.
---------
Signed-off-by: Innei <tukon479@gmail.com>