Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### 🔧 Bug Fixes

- **providers (muse-spark):** align the Muse Spark Web (Meta AI) cookie copy with the live cookie name. The default session cookie migrated from the retired `abra_sess` to `ecto_1_sess` (`META_AI_DEFAULT_COOKIE`), but the provider form hint and one 401 auth-failure message still told users to paste `abra_sess` — a cookie that no longer exists. Both strings now name `ecto_1_sess`. Regression guard: `tests/unit/muse-spark-cookie-copy-5449.test.ts`. ([#5449](https://github.com/diegosouzapw/OmniRoute/issues/5449))
- **dashboard (provider add):** fix three rough edges in the Add-API-Key / model-import flow reported across the provider-catalog audit. (1) The **Validation Model** and **Account ID** form fields shipped untranslated i18n stub copy (`"Validation Model Id Label"`, `"Account Id Placeholder"`, …) that surfaced verbatim in the modal — replaced with real labels/placeholders/hints in `en.json`. (2) Model import **silently fell back to the cached/local catalog**: the route already returned a `warning` ("API unavailable — using local catalog"), but `useModelImportHandlers` only read `models`/`error` and dropped it, so the user got local models with no indication — the warning is now surfaced as an import log line (new pure helper `extractImportWarning`). (3) The required connection-**name** field defaulted to `""`, which let browser autofill inject garbage (e.g. `wiw`) — it now defaults to `"main"`. Regression guard: `tests/unit/provider-add-ux-i18n-import-warning.test.ts`. ([#5421](https://github.com/diegosouzapw/OmniRoute/issues/5421), [#5428](https://github.com/diegosouzapw/OmniRoute/issues/5428), [#5429](https://github.com/diegosouzapw/OmniRoute/issues/5429), [#5431](https://github.com/diegosouzapw/OmniRoute/issues/5431), [#5435](https://github.com/diegosouzapw/OmniRoute/issues/5435))
- **services (installer):** fix `spawn EINVAL` when installing an embedded service (9Router / CLIProxy) on **Windows + Node.js 24+**. Node 24 stopped letting `child_process.execFile()` run `.cmd` batch files without a shell (nodejs/node#52554), and npm on Windows is `npm.cmd`, so `runNpm()` threw `EINVAL` the moment a user clicked **Install**. `runNpm` now enables `shell` on win32 only. To keep Hard Rule #13 intact under a shell — where the shell, not `execFile`, parses argv — the install `--prefix` (a `DATA_DIR` path that can legitimately contain spaces, e.g. `C:\Users\John Doe\.omniroute\…`) is now passed via the `npm_config_prefix` **environment variable** instead of an argv path, and the user-supplied install `version` is constrained to a dist-tag/semver shape (`SERVICE_VERSION_PATTERN`) at the route boundary so it can never carry shell metacharacters. With the prefix in the environment and the version validated, every remaining argv entry is a static flag. Regression guards: `tests/unit/services/installers/runNpm-shell-5379.test.ts` (+ existing `ninerouter.test.ts` aligned to npm's `npm_config_prefix` env). ([#5379](https://github.com/diegosouzapw/OmniRoute/issues/5379))
- **cli (serve):** restore `dist/tls-options.mjs` to the npm tarball — the opt-in native HTTPS/TLS sidecar (#5361) was copied into the staged `dist/` by the build but then **pruned** by the prepublish allowlist step, so `omniroute serve` crashed on the published 3.8.41 with `ERR_MODULE_NOT_FOUND` (`dist/server-ws.mjs` imports `./tls-options.mjs`). Added `tls-options.mjs` to `APP_STAGING_ALLOWED_EXACT_PATHS` (survives the prune) and `dist/tls-options.mjs` to `PACK_ARTIFACT_REQUIRED_PATHS` (the `check:pack-artifact` gate now fails loudly if it ever vanishes again — same guard pattern as `webdav-handler.mjs`). Regression guards in `tests/unit/pack-artifact-policy.test.ts`. ([#5452](https://github.com/diegosouzapw/OmniRoute/issues/5452))
Expand Down
2 changes: 1 addition & 1 deletion open-sse/executors/muse-spark-web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ function classifyMetaAiError(errorMessage: string | null, content: string) {
if (/authentication required to send messages|login is required|sign in/i.test(combined)) {
return {
status: 401,
message: "Meta AI auth failed — your meta.ai abra_sess cookie may be missing or expired.",
message: "Meta AI auth failed — your meta.ai ecto_1_sess cookie may be missing or expired.",
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/shared/constants/providers/web-cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const WEB_COOKIE_PROVIDERS = {
website: "https://www.meta.ai",
hasFree: true,
freeNote: "Free with login — Meta AI platform with Llama models.",
authHint: "Paste your abra_sess value or full cookie header from meta.ai",
authHint: "Paste your ecto_1_sess value or full cookie header from meta.ai",
},
"claude-web": {
id: "claude-web",
Expand Down
41 changes: 41 additions & 0 deletions tests/unit/muse-spark-cookie-copy-5449.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";

// #5449: Muse Spark Web (Meta AI) migrated its default session cookie from the retired
// `abra_sess` to `ecto_1_sess` (see META_AI_DEFAULT_COOKIE), but two user-facing strings still
// named the old cookie — the provider form hint and one auth-failure message — telling users to
// paste a cookie that no longer exists. These guards keep the copy aligned with the live cookie.

const __dirname = dirname(fileURLToPath(import.meta.url));
const root = join(__dirname, "..", "..");

const webCookie = readFileSync(
join(root, "src", "shared", "constants", "providers", "web-cookie.ts"),
"utf8"
);
const executor = readFileSync(join(root, "open-sse", "executors", "muse-spark-web.ts"), "utf8");

test("provider form hint points at the live ecto_1_sess cookie, not retired abra_sess", () => {
assert.ok(
webCookie.includes("Paste your ecto_1_sess value"),
"muse-spark authHint must name ecto_1_sess"
);
assert.ok(
!webCookie.includes("Paste your abra_sess"),
"muse-spark authHint must not name the retired abra_sess cookie"
);
});

test("auth-failure message names the live ecto_1_sess cookie, not retired abra_sess", () => {
assert.ok(
!executor.includes("meta.ai abra_sess cookie may be missing"),
"the 401 message must not name the retired abra_sess cookie"
);
assert.ok(
executor.includes("meta.ai ecto_1_sess cookie may be missing"),
"the 401 message must name the live ecto_1_sess cookie"
);
});
Loading