The dialog plugin's init script replaces window.alert and window.confirm
with async IPC. Its confirm calls a command the plugin removed in 2.7.0,
and a synchronous confirm() reads the returned Promise as yes, so
extensions ran confirmed actions without asking. Register the plugin
without that script: every webview already provides native synchronous
dialogs, and on iOS and macOS our WKUIDelegate bridge now handles the
main frame too. File pickers and Rust message dialogs still use the
plugin, and no dialog:allow-message grant is needed.
Remove the wrapper once the plugin stops overriding native dialogs or
offers an opt-out.
Fixes#334
Validation: pnpm run check; native alert/confirm/prompt in a macOS dev build.
Unrouted same-origin /api requests passed through to the asset protocol,
which answers any missing path with 200 index.html in production while the
dev server answers 404/405. Upstream features read that as success:
MovingUI presets looked saved but were lost, Office/Fandom probes looked
available, and Stable Diffusion failed to load with Horde/OpenRouter.
Claim /api/* in the router so unimplemented endpoints, for any method, get
the dispatcher's standard Unsupported endpoint 404 in dev and production
alike, with the message as statusText for upstream toasts. Drop the stubs
that only dodged the fallback (/api/search/*, Edge TTS plugin, SpeechT5)
and the interceptors' unreachable second fallback.
Name fields from text-only title spans and help links as "Docs" plus their title. Select2 forwards field names and the current value to its focused elements and accepts script clicks; sampler lists share drag and move buttons; icon checkboxes share a focus ring.
Restore saved values after their final constraints through one numeric entry point and report out-of-range adjustments once per operation. Secret operations reject on failure and leave notification to their callers.
NovelAI fills missing mirostat fields with LR 0.2 / Tau 4 from the bundled Erato-Dragonfruit preset, a named preset's values rather than a NovelAI default.
Validation: pnpm run check
Bring OpenHarmony onto the contract Android and iOS already follow.
ArkUI lays the Web out in the safe area, ArkWeb's RESIZE_CONTENT
shrinks the layout viewport by the docked keyboard's overlap, and an
app-owned window-layout plugin publishes window snapshots and draws
wallpaper strips behind the system bars.
- Share the window-layout plugin transport between Android and OHOS.
- Drop the remaining OHOS branches in Rust and the frontend.
- Rotate with the sensor, within the system rotation lock.
The ability and plugins-workspace pins point at the Darkatse forks
until LeenHawk/openharmony-ability#1 and LeenHawk/plugins-workspace#1
merge.
Consume system bars, cutouts and docked keyboards in Android and iOS,
then let web content use the resulting viewport. Publish window wallpaper
strips through one shared background path.
Remove the old CSS and IME compensation layers, update layout ABI v2,
and keep the matching documentation and behavior tests together.
Android long-press saving now covers cross-origin images that the page
cannot read because of CORS. Like a browser's "Save image", the host
downloads remote http(s) sources into staging, while sources the page
owns are still read in their window. Both end in deliver_staged_file,
so the save panel, result and feedback are the same on every Android
version, with no storage permission.
- stage_file_from_url downloads through ContentService, which already
owns the URL rule for external imports.
- Compare origins with window.origin. srcdoc and about:blank frames
report location.origin as "null", which misrouted their same-origin
images and skipped their a[download] links.
- fetch_to_file returns the response Content-Type, so a remote image
without an extension in its URL is named from its type.
- Keep a path segment that is not valid percent-encoding as written,
so names like "100%.png" no longer make the save fail.
- File exports call staging and delivery commands through the host
safeInvoke, so failures show the backend message instead of a
generic one.
This replaces the original DownloadManager approach in #324.
Co-authored-by: Darkatse <39111369+Darkatse@users.noreply.github.com>
Centralize file picking, staging and delivery across platforms, with explicit cancellation outcomes and source ownership.
Remove superseded platform bridges and redundant tests, and document the shared contract and platform differences.
Validation: pnpm run check; Android aarch64 cargo check; 117 host tests.
* feat: add experimental OpenHarmony application build
* build(ohos): isolate experimental NAPI dependencies
* ci(ohos): build in this repository with public toolchain image
* ci: run existing checks for OHOS adaptation
* fix(ohos): generate QuickJS bindings for the OHOS target
* fix(ohos): use private caches and exclude desktop migration logs
* feat(ohos): restore native plugins and trusted endpoint confirmation
* ci(ohos): verify native plugin integration with existing checks
* chore(ohos): remove completed one-off validation workflow
* fix(ohos): clean dependency warnings and enable HAP LTO
* fix(ohos): retain shared plugin callbacks for the native bridge
* refactor(ohos): keep the native project and align the framework baseline
* fix(ohos): pin frame authorization and name the launcher entry
* fix(ohos): bind native builds and HAP packaging to the selected ABI
* fix(ohos): pin ordered Tauri bridge initialization
* fix(ohos): compress native libraries in HAP packages
* refactor(ohos): simplify HAP builds and Canary publishing
Build Rust once through the OHOS CLI and derive HAP versions from its merged
configuration. Replace the demo with the application page and remove generated
configuration writes, CMake scaffolding, and redundant preparation steps.
Keep ARM64 HAPs optional for Canary, report unsupported dev-log exports clearly,
and document the current build and host contracts.
Validated with pnpm run check, a local x86_64 HAP build and simulator smoke checks,
and Windows notification smoke checks.
---------
Co-authored-by: Darkatse <39111369+Darkatse@users.noreply.github.com>
Derive platform and shell kind in Rust and inject them before WebView scripts.
Replace frontend UA guesses and pass host facts and IPC budgets to adapters.
Keep chat width in the frontend, preserve iOS policy initialization, and
restore the mobile third-party resource limit. Align docs and test fixtures.
* test(storage): build extension store assertion path component-wise
The assertion joined one forward-slash literal, which Windows keeps verbatim, so the expected path mixed separators while entry_path() builds the real one with per-component joins. The resulting strings never matched and the test failed on every Windows run. Join the same components the production path uses so the comparison holds on all platforms.
* feat(android): save images from the WebView long-press menu
Long-pressing an <img> inside the app offered no way to keep it. Add a host-side context menu that routes every source through one rule: if the system downloader can reach the URL, hand it over, otherwise let the page read the bytes.
DownloadManager can only fetch real network locations, so blob:, data: and the app's own loopback origin all go through the page instead. App assets are fetched relatively to stay same-origin. The bytes are published through the existing AndroidPublicDownloadJsBridge, so the MediaStore transaction, the Android 10+ gate and the staging cleanup are reused rather than reimplemented. No new dependency and no build.gradle.kts change.
The installer takes an application context and owns its own Toast and DownloadManager lookups, keeping MainActivity to a single construction and one install call.
Failures surface as a toast instead of staying in logcat, including page-side fetch errors reported back over the bridge.
* refactor(android): save long-pressed images through the download bridge
Android WebView offers no image context menu, and a native
OnCreateContextMenuListener consumes the long press before the page can
claim it. Supply the missing contextmenu default action in the download
bridge instead: it honors preventDefault(), asks for confirmation, reads
the image in its own window and exports through downloadBlobWithRuntime,
so Android 8-9 keep the SAF fallback and feedback stays localized.
Remove the native installer and its DownloadManager and base64 paths.
---------
Co-authored-by: Darkatse <39111369+Darkatse@users.noreply.github.com>
Preserve world-info JSON bytes through bounded commit sessions shared with chat. Centralize save ordering, failure propagation, and update events.
Remove obsolete protocol plumbing and preserve invoke headers under the performance HUD.
Validation: pnpm run check.
Route full saves and metadata updates through one bounded commit protocol,
with session-owned staging and atomic publication that preserves message bytes.
Simplify behavioral coverage and keep documentation focused on core contracts.
Capture Agent inputs after extension hooks and share MacroEnv across prompt and request templates. Remove frozen macro emulation while preserving live extension behavior.
Simplify live data reads and browser test discovery; document the public context APIs.
Validation: pnpm run check.
Centralize header, BOM and record validation across chat read and write paths. Preserve header-only validation for full commits and byte-exact metadata bodies.
Consolidate repository behavior tests and keep documentation focused on shared contracts.
Register WebView tools through a dedicated provider with shared tool selection, naming, and result handling. Keep extension availability independent from saved profile selections.
Clarify model-facing feedback and consolidate behavioral tests and architecture documentation.
Add standalone sessions with a shared profile, continuous JSONL history, and persistent work/tmp directories. Reuse frontend preset assembly and the existing model/tool loop with explicit Chat and Session targets.
Validation: pnpm run check
Document skill mounts, prompt catalogs and migration boundaries. Retain the JavaScript capability and kit references while removing obsolete executor details.
Move database ownership, blocking IO and TQL binding into tt-adapter-triviumdb
and upgrade the native engine to 0.8.8. Preserve the plugin API capabilities
with awaited open, numeric IDs and explicit shared-namespace lifecycle.
Coordinate archive IO with database maintenance and restore each namespace
as a complete file group. Keep behavior tests for persistence, parameter
binding, transactions and recovery instead of per-method forwarding tests.
Validated with pnpm run check and tauri-pilot against the macOS app using
the real data root; temporary test namespaces were removed afterward.
Add a disabled-by-default setting with reload semantics and localized help. Document the cold representation, ownership, and save compatibility contracts.
`saveMetadata()` used to delegate to a full chat save, so every metadata
write re-serialized and re-transmitted the whole history. It now
persists only the header's `chat_metadata` through a new
`commit_chat_metadata` command. storage-core rewrites the header inside
the existing path mutation lock and copies the body byte for byte in one
blocking task; JS and IPC work is proportional to the header.
The header writer is shared with `metadata.setExtension()`, which now
also invalidates the character memory cache. Metadata saves stay in the
chat save queue, do not cancel a pending full save, and recover an
integrity conflict with a forced full save inside the same queue task.
New group chats publish their initial header before greeting hooks run,
so metadata written by those hooks is kept.
This narrows the SillyTavern 1.18.0 semantics: message edits need an
explicit full save. The change is documented in ChatPayload.md §3.1 and
the frontend contracts.
First-party saves no longer round-trip through the local fetch
interceptor, which serialized the whole request and parsed it back into
a second object graph before the commit session ever saw it. Character
and group saves, branches, checkpoints, solo-to-group conversion and
rename rewrites now call the transport directly.
The commit facade snapshots every record as JSON text before its first
await, so mutations during transfer cannot tear the saved file, and it
classifies the host's integrity rejection into a typed error that both
the save paths and the compatibility routes branch on. The integrity
overwrite prompt is shared by character and group saves.
`/api/chats/save` and `/api/chats/group/save` remain for extensions.