Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
48ace61
fix(barrel): migrate src/app/ off the localDb barrel to direct db imp…
jonlwheat2-gif Aug 29, 2026
06eb091
fix(barrel): migrate src/lib/ off the localDb barrel to direct db imp…
jonlwheat2-gif Aug 29, 2026
7d8c365
fix(barrel): migrate open-sse, src/shared, src/sse, src/models, src/d…
jonlwheat2-gif Aug 29, 2026
f02e6d8
fix(barrel): delete the src/lib/localDb barrel now every consumer use…
jonlwheat2-gif Aug 29, 2026
2b8d3a8
fix(radar): restore D12 public boundary (#12057)
diegosouzapw Aug 29, 2026
6c33ef0
fix(tests): update quota-key-models route test to assert new direct i…
jonlwheat2-gif Aug 29, 2026
1115395
fix(barrel): repair Phase 5 CI gates after deleting the localDb barre…
jonlwheat2-gif Aug 29, 2026
3b00535
feat(guardrails): enforce video transcript provenance, budgets and re…
diegosouzapw Aug 29, 2026
60dc242
feat(video): derive embedded subtitle provenance in the protected bro…
diegosouzapw Aug 29, 2026
ef66896
test(video): freeze FU-07/FU-09 promotion-evidence manifest, aggregat…
diegosouzapw Aug 29, 2026
f30e5b2
feat(video): connect tenant-bound drill-down lifecycle and multiresol…
diegosouzapw Aug 29, 2026
e8b2cd2
docs(video): clarify Video Bridge transcript provenance is caller-dec…
diegosouzapw Aug 29, 2026
5fcd39b
feat(video): orchestrate Audio Bridge STT with one-download budgets (…
diegosouzapw Aug 29, 2026
36b7920
refactor(video): extract a Video Bridge pipeline with explicit ports …
diegosouzapw Aug 29, 2026
55e33f3
fix(sse): default crash-guard logger to console.warn, not console (#1…
HouMinXi Aug 29, 2026
5698769
fix(cli): support --base-url alongside --endpoint in nodes subcommand…
HouMinXi Aug 29, 2026
d3420d2
fix(admission): exclude reclaimable page cache from the cgroup pressu…
HouMinXi Aug 29, 2026
38e2baa
fix(resilience): clear persisted LKGP pin on target exhaustion and sk…
HouMinXi Aug 29, 2026
aa861a8
fix(barrel): migrate src/app/ off the @/lib/localDb barrel import (#1…
jonlwheat2-gif Aug 30, 2026
2463781
fix(barrel): migrate src/lib/ off the localDb barrel to direct db imp…
jonlwheat2-gif Aug 30, 2026
38a2966
URGENT fix(build): route ChatGPT Web MCP bundle through runBuildTool …
jonlwheat2-gif Aug 30, 2026
4e11887
fix(barrel): migrate open-sse, src/shared, src/sse, src/models, src/d…
jonlwheat2-gif Aug 30, 2026
fb34c87
resync #12055 onto updated release/v3.8.51 (incl. clearStaleLKGP barr…
diegosouzapw Aug 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 3 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,7 @@ When creating _any_ validation tests or one-off logic scripts, default to `scrip
### Database

- **Always** go through `src/lib/db/` domain modules — **never** write raw SQL in routes or handlers
- **Never** add logic to `src/lib/localDb.ts` (re-export layer only)
- **Never** barrel-import from `localDb.ts` — import specific `db/` modules instead
- **Never** barrel-import from `localDb.ts` — import specific `src/lib/db/*` modules
- DB singleton: `getDbInstance()` from `src/lib/db/core.ts` (WAL journaling)
- Migrations: `src/lib/db/migrations/` — versioned SQL files, idempotent, run in transactions

Expand Down Expand Up @@ -355,8 +354,7 @@ Documentation must describe verified behavior, not plausible behavior.
1. Create `src/lib/db/yourModule.ts` — import `getDbInstance` from `./core.ts`
2. Export CRUD functions for your domain table(s)
3. Add migration in `src/lib/db/migrations/` if new tables needed
4. Re-export from `src/lib/localDb.ts` (add to the re-export list only)
5. Write tests
4. Write tests

### Adding a New MCP Tool

Expand Down Expand Up @@ -668,7 +666,7 @@ the stale-enforcement added in Fase 6A.3.
## Hard Rules

1. Never commit secrets or credentials
2. Never add logic to `localDb.ts`
2. Never barrel-import from `localDb.ts` — import specific `src/lib/db/*` modules
3. Never use `eval()` / `new Function()` / implied eval
4. Never commit directly to `main`
5. Never write raw SQL in routes — use `src/lib/db/` modules
Expand Down
110 changes: 99 additions & 11 deletions bin/cli/commands/nodes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,80 @@ function parseHeader(kv) {
return { name: kv.slice(0, eq), value: kv.slice(eq + 1) };
}

function getRootCommand(cmd) {
let curr = cmd;
while (curr.parent) curr = curr.parent;
return curr;
}

function resolveNodeEndpoint(opts, cmd) {
if (opts.endpoint) {
return { endpoint: opts.endpoint, apiFetchOpts: cmd.optsWithGlobals() };
}
if (opts.nodeUrl) {
return { endpoint: opts.nodeUrl, apiFetchOpts: cmd.optsWithGlobals() };
}

// Check if --base-url, --endpoint, or --node-url was explicitly passed after the subcommand
const root = getRootCommand(cmd);
const rawArgs = root.rawArgs || process.argv;
const cmdName = cmd.name();

let subArgsStart = -1;
for (let i = 0; i < rawArgs.length - 1; i++) {
if (rawArgs[i] === "nodes" || rawArgs[i] === "provider-nodes") {
if (rawArgs[i + 1] === cmdName) {
subArgsStart = i + 2;
break;
}
}
}

let explicitSubcommandBaseUrl = undefined;
let serverBaseUrl = undefined;

if (subArgsStart !== -1) {
const preArgs = rawArgs.slice(0, subArgsStart);
for (let i = 0; i < preArgs.length; i++) {
if (preArgs[i] === "--base-url" && i + 1 < preArgs.length) {
serverBaseUrl = preArgs[i + 1];
} else if (preArgs[i].startsWith("--base-url=")) {
serverBaseUrl = preArgs[i].slice("--base-url=".length);
}
}

const subArgs = rawArgs.slice(subArgsStart);
for (let i = 0; i < subArgs.length; i++) {
const arg = subArgs[i];
if (
(arg === "--base-url" || arg === "--endpoint" || arg === "--node-url") &&
i + 1 < subArgs.length
) {
explicitSubcommandBaseUrl = subArgs[i + 1];
} else if (
arg.startsWith("--base-url=") ||
arg.startsWith("--endpoint=") ||
arg.startsWith("--node-url=")
) {
explicitSubcommandBaseUrl = arg.slice(arg.indexOf("=") + 1);
}
}
}

if (explicitSubcommandBaseUrl !== undefined) {
const globals = cmd.optsWithGlobals?.() ?? {};
const apiFetchOpts = { ...globals };
if (serverBaseUrl) {
apiFetchOpts.baseUrl = serverBaseUrl;
} else {
delete apiFetchOpts.baseUrl;
}
return { endpoint: explicitSubcommandBaseUrl, apiFetchOpts };
}

return { endpoint: undefined, apiFetchOpts: cmd.optsWithGlobals() };
}

const nodeSchema = [
{ key: "id", header: "Node ID", width: 22 },
{ key: "provider", header: "Provider", width: 16 },
Expand Down Expand Up @@ -70,7 +144,8 @@ export function registerNodes(program) {
nodes
.command("add")
.requiredOption("--provider <p>", t("nodes.add.provider"))
.requiredOption("--endpoint <url>", t("nodes.add.baseUrl"))
.option("--endpoint <url>", t("nodes.add.baseUrl"))
.option("--base-url <url>", t("nodes.add.baseUrl"))
.option("--name <n>", t("nodes.add.name"))
.option("--weight <w>", t("nodes.add.weight"), parseInt, 100)
.option("--region <r>", t("nodes.add.region"))
Expand All @@ -81,50 +156,57 @@ export function registerNodes(program) {
[]
)
.action(async (opts, cmd) => {
const { endpoint, apiFetchOpts } = resolveNodeEndpoint(opts, cmd);
if (!endpoint) {
process.stderr.write(`error: required option '--endpoint <url>' or '--base-url <url>' not specified\n`);
process.exit(1);
}
const body = {
provider: opts.provider,
baseUrl: opts.endpoint,
baseUrl: endpoint,
name: opts.name,
weight: opts.weight,
region: opts.region,
enabled: true,
headers: opts.authHeader?.length ? opts.authHeader : undefined,
};
const res = await apiFetch("/api/provider-nodes", {
...cmd.optsWithGlobals(),
...apiFetchOpts,
method: "POST",
body,
});
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
emit(await res.json(), cmd.optsWithGlobals());
emit(await res.json(), apiFetchOpts);
});

nodes
.command("update <nodeId>")
.option("--endpoint <url>", t("nodes.update.baseUrl"))
.option("--base-url <url>", t("nodes.update.baseUrl"))
.option("--name <n>", t("nodes.update.name"))
.option("--weight <w>", t("nodes.update.weight"), parseInt)
.option("--region <r>", t("nodes.update.region"))
.option("--enabled <b>", t("nodes.update.enabled"), (v) => v === "true")
.action(async (id, opts, cmd) => {
const { endpoint, apiFetchOpts } = resolveNodeEndpoint(opts, cmd);
const body = {};
if (opts.endpoint !== undefined) body.baseUrl = opts.endpoint;
if (endpoint !== undefined) body.baseUrl = endpoint;
for (const k of ["name", "weight", "region", "enabled"]) {
if (opts[k] !== undefined) body[k] = opts[k];
}
const res = await apiFetch(`/api/provider-nodes/${id}`, {
...cmd.optsWithGlobals(),
...apiFetchOpts,
method: "PUT",
body,
});
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
emit(await res.json(), cmd.optsWithGlobals());
emit(await res.json(), apiFetchOpts);
});

nodes
Expand All @@ -145,19 +227,25 @@ export function registerNodes(program) {

nodes
.command("validate")
.requiredOption("--endpoint <url>", t("nodes.validate.baseUrl"))
.option("--endpoint <url>", t("nodes.validate.baseUrl"))
.option("--base-url <url>", t("nodes.validate.baseUrl"))
.requiredOption("--provider <p>", t("nodes.validate.provider"))
.action(async (opts, cmd) => {
const { endpoint, apiFetchOpts } = resolveNodeEndpoint(opts, cmd);
if (!endpoint) {
process.stderr.write(`error: required option '--endpoint <url>' or '--base-url <url>' not specified\n`);
process.exit(1);
}
const res = await apiFetch("/api/provider-nodes/validate", {
...cmd.optsWithGlobals(),
...apiFetchOpts,
method: "POST",
body: { baseUrl: opts.endpoint, provider: opts.provider },
body: { baseUrl: endpoint, provider: opts.provider },
});
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
emit(await res.json(), cmd.optsWithGlobals());
emit(await res.json(), apiFetchOpts);
});

nodes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(guardrails):** enforce a bounded, deterministic contract for Video Bridge transcripts — 256 cues, 4096 input code units and 4 KiB UTF-8 per cue, 64 KiB total text, malformed-Unicode rejection, focus-window scoping, cross-source reconciliation with contributing-source metadata, and a structural provenance trust boundary so caller JSON can never self-assert `embedded`/`audio-bridge` provenance ([#11652](https://github.com/diegosouzapw/OmniRoute/issues/11652))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(video):** orchestrate optional Video Bridge audio extraction and Audio Bridge STT behind a dual opt-in (operator setting AND per-request signal) — a new loopback-only broker `mode=audio` operation shares the frame path's exact process queue, deadline, AbortSignal, and byte budgets to extract a bounded mono 16 kHz PCM WAV from the same already-downloaded video, then reuses the existing Audio Bridge transcription boundary; provider segment timing is preserved when available and marked coarse otherwise, and every failure degrades to a visual-only-safe partial instead of throwing (#11654).
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- Add a tenant-bound Video Bridge drill-down lifecycle on top of the existing secure cache
substrate: opaque hashed handles (never raw session/video identifiers), preview/standard/detail
multiresolution variants resampled on read, response pagination capped at 8 frames and 32 MiB,
and a new authenticated `/api/v1/video-bridge/drilldown` consumer route that stays disabled for
remote access by default and denies cross-key access with the same response as a nonexistent
handle (no existence oracle).
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **test(video):** Add the Video Bridge FU-07/FU-09 promotion-evidence harness (#11656) — a frozen Zod manifest schema covering the 8 required scenario kinds (static scenes, rapid cuts, late facts, fades, blur, small text, close events, visual prompt injection) with a minimum of 3 repetitions per case, deterministic declarative fixture recipes (`videoBridgePromotionFixtures.ts`), a pure medians/p95 metrics aggregator, a pure FU-07/FU-09 promotion-verdict evaluator applying the ticket's exact thresholds (missing token usage always holds), a digest-only persistence layer that never retains raw media or raw model responses, and a versioned per-model promotion allowlist shipped empty with every model defaulting to `hold`. The FU-07/FU-09 promotion verdicts themselves remain HOLD — they require a real evidence run against real models on VPS 192.168.0.15.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(video bridge):** "embedded" transcript provenance can now be legitimately earned instead of merely asserted — a bounded, allowlisted (`mov_text`/`subrip`/`webvtt`) subtitle probe runs through the loopback-only Video Bridge broker (at most 2 streams, 10s subdeadline bounded by the request deadline, 256 KiB output, 4096-code-unit lines), normalized through a bounded, ReDoS-safe WebVTT parser and Zod-validated end to end. The adapter always resolves to an explicit `success`/`absent`/`transient_failure` outcome — a subtitle failure never breaks the visual description path, and only a fingerprint-verified broker response (never a caller-declared label) can produce embedded cues (#11659).
1 change: 1 addition & 0 deletions changelog.d/fixes/11704-prepublish-npx-cmd-win32.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(build):** `prepublish.ts` bundles the ChatGPT Web (Codex) MCP bridge through `runBuildTool()` instead of spawning `npx.cmd` raw, fixing the build crash on Node ≥ 20/Windows where `.cmd` shims cannot be spawned without a shell (EINVAL) ([#11704](https://github.com/diegosouzapw/OmniRoute/issues/11704))
1 change: 1 addition & 0 deletions changelog.d/fixes/11911-lkgp-stale-pin-exhaustion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(resilience):** clear persisted LKGP pins when a target suffers connection/provider exhaustion or is skipped before dispatch due to cooldown/exhaustion/unavailability, preventing subsequent requests from repeatedly prioritizing known-dead providers ([#11911](https://github.com/diegosouzapw/OmniRoute/issues/11911)).
1 change: 1 addition & 0 deletions changelog.d/fixes/11999-cli-nodes-base-url-shadowing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(cli):** support `--base-url` alongside `--endpoint` in `omniroute nodes add`, `update`, and `validate` subcommands to prevent global `--base-url` shadowing issues ([#11999](https://github.com/diegosouzapw/OmniRoute/issues/11999)).
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **refactor(video bridge):** extract per-video acquisition, whole-result caching, description, and metrics/abort/cleanup out of `VideoBridgeGuardrail.preCall` into a `processVideoPart` seam in a new `videoBridgePipeline.ts`, behind explicit `VideoMediaBrokerPort`, `VideoAudioTranscriptionPort`, and `VideoDrilldownPort` boundaries; `preCall` now only handles request traversal, policy, and response aggregation. The Video tab's FFmpeg/ffprobe runtime status is now an explicit `unknown` / `restricted` / `unavailable` / `available` state instead of a nullable boolean pair, fixing a case where an in-flight or failed probe was mislabeled as "install FFmpeg" ([#11657](https://github.com/diegosouzapw/OmniRoute/issues/11657)).
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- **docs(video):** clarify that the Video Bridge transcript `source` field (`client`,
`embedded`, `audio-bridge`) is presently caller-declared and not yet server-verified —
OmniRoute enforces the enum shape but does not cryptographically confirm that an
`embedded`/`audio-bridge` label came from a server-owned extraction
([#11661](https://github.com/diegosouzapw/OmniRoute/issues/11661)).
Loading
Loading