omnigateway 0.15.3 → 0.15.4
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.
- package/README.md +90 -6
- package/bin/omni.js +218 -190
- package/gateway.js +390 -338
- package/package.json +1 -1
- package/public/assets/_app-kgxk7ake.js +1 -0
- package/public/assets/_app.accounts-3jabfvcs.js +1 -0
- package/public/assets/_app.console-y69399jc.js +1 -0
- package/public/assets/_app.database-r5kg3838.js +1 -0
- package/public/assets/_app.index-22awhb38.js +1 -0
- package/public/assets/_app.keys-7vh81n1w.js +1 -0
- package/public/assets/_app.logs-rssv5a6z.js +1 -0
- package/public/assets/_app.models-82m2f0kr.js +1 -0
- package/public/assets/_app.plugins.$pluginId-e4xva5tz.js +1 -0
- package/public/assets/_app.settings-fqzg7wnn.js +1 -0
- package/public/assets/_app.usage-32vje0s7.js +1 -0
- package/public/assets/client-d3mjj5ey.js +1 -0
- package/public/assets/index-0j7sghrn.js +2 -0
- package/public/assets/index-4dz4bgrb.js +2 -0
- package/public/assets/index-85cnhw3e.js +2 -0
- package/public/assets/index-8bewp9z1.js +6 -0
- package/public/assets/index-938qd7p2.js +2 -0
- package/public/assets/index-d09hs7ex.js +2 -0
- package/public/assets/index-d0t1fj1y.js +2 -0
- package/public/assets/index-dq2f7yk0.js +2 -0
- package/public/assets/index-f7t0kve8.js +2 -0
- package/public/assets/index-fcew0gga.js +2 -0
- package/public/assets/index-h3nb7n4d.css +1 -0
- package/public/assets/index-hk28xepa.js +2 -0
- package/public/assets/index-nnpqs2w6.js +2 -0
- package/public/assets/index-p9vbm21a.js +46 -0
- package/public/assets/index-sbe0ydnc.js +2 -0
- package/public/assets/index-t1cs42r4.js +2 -0
- package/public/assets/index-v31xha7b.js +2 -0
- package/public/assets/index-wjqdtafp.js +2 -0
- package/public/assets/index-xdyjb1an.js +2 -0
- package/public/assets/index-z7c4qz9d.js +54 -0
- package/public/assets/index-zkt5p0qd.js +2 -0
- package/public/assets/login-p97b96t9.js +1 -0
- package/public/index.html +5 -13
- package/public/shared/chunks/react-e7vf2dk6.js +2 -0
- package/public/shared/chunks/react-mv7wrde1.js +2 -0
- package/public/shared/chunks/react-ybbhws22.js +2 -0
- package/public/shared/chunks/react-z0w6knjn.js +2 -0
- package/public/shared/dashboard-sdk.js +1 -1
- package/public/shared/jsx-runtime.js +1 -1
- package/public/shared/react-dom-client.js +9 -9
- package/public/shared/react-dom.js +1 -1
- package/public/shared/react-query.js +1 -1
- package/public/shared/react.js +1 -1
- package/public/shared/styled-components.js +5 -6
- package/public/assets/Chip-B2iXmJJC.js +0 -37
- package/public/assets/CopyValue-CWSTp4v8.js +0 -27
- package/public/assets/Field-CUEEy19T.js +0 -60
- package/public/assets/Lamp-CL0i4yaa.js +0 -26
- package/public/assets/Meter-stpt3vQu.js +0 -14
- package/public/assets/Panel-CsovmtxF.js +0 -225
- package/public/assets/Rack-1lijWt5h.js +0 -483
- package/public/assets/Readout-DlT5oxGO.js +0 -31
- package/public/assets/RequestTable-uRTmuPwB.js +0 -93
- package/public/assets/Select-C0c13SKD.js +0 -141
- package/public/assets/SummaryDeck-DnQnRmQ8.js +0 -15
- package/public/assets/Table-CVDZ69Zx.js +0 -38
- package/public/assets/Toggle-BvVa_jla.js +0 -39
- package/public/assets/TokenBreakdown-B8cSaOOr.js +0 -32
- package/public/assets/WindowChart-CaPUJ4GJ.js +0 -11
- package/public/assets/_app-CSru2YTE.js +0 -1
- package/public/assets/_app.accounts-DmJhe6QV.js +0 -70
- package/public/assets/_app.console-DQlcBpSu.js +0 -24
- package/public/assets/_app.database-DoDu8HOG.js +0 -24
- package/public/assets/_app.index-BEeD4XSS.js +0 -67
- package/public/assets/_app.keys-MXvgkBUB.js +0 -120
- package/public/assets/_app.logs-CjUjeVHg.js +0 -46
- package/public/assets/_app.models-mNIL-1oS.js +0 -148
- package/public/assets/_app.plugins._pluginId-CsJXQg6X.js +0 -20
- package/public/assets/_app.settings-CYMwWA8D.js +0 -88
- package/public/assets/_app.usage-Dd33vB8x.js +0 -78
- package/public/assets/chevron-right-ocqzquMZ.js +0 -1
- package/public/assets/client-KUNw8ZtZ.js +0 -48
- package/public/assets/index-B9izdV6t.js +0 -14
- package/public/assets/index-Co2s5xMk.css +0 -1
- package/public/assets/limits-iRyDMg04.js +0 -1
- package/public/assets/login-DrbTJF6e.js +0 -45
- package/public/assets/plus-D_lvSfDL.js +0 -1
- package/public/assets/preload-helper-1xe0b53X.js +0 -1
- package/public/assets/reasons-Du1OBWAM.js +0 -1
- package/public/assets/rotate-ccw-CwTftDdz.js +0 -1
- package/public/assets/shared-HVgLEGgl.js +0 -77
- package/public/assets/trash-CmuxOGpN.js +0 -1
- package/public/shared/chunks/jsx-runtime-CznXPbDH.js +0 -1
- package/public/shared/chunks/react-DK6rpPfu.js +0 -1
- package/public/shared/chunks/react-dom-Wr82bmbV.js +0 -1
- package/public/shared/chunks/rolldown-runtime-CbXtAM7H.js +0 -1
- /package/public/assets/{archivo-latin-ext-standard-normal-7khWdh9v.woff2 → archivo-latin-ext-standard-normal-5717f37059660ca5.woff2} +0 -0
- /package/public/assets/{archivo-latin-standard-normal-DY7AcnAa.woff2 → archivo-latin-standard-normal-e3a28eade21a900c.woff2} +0 -0
- /package/public/assets/{archivo-vietnamese-standard-normal-rJmnGBSt.woff2 → archivo-vietnamese-standard-normal-332e6f66de84927c.woff2} +0 -0
- /package/public/assets/{spline-sans-mono-latin-ext-wght-normal-Dh0aNLWd.woff2 → spline-sans-mono-latin-ext-wght-normal-0ca9a3989044d1f9.woff2} +0 -0
- /package/public/assets/{spline-sans-mono-latin-wght-normal-DlaB5ohX.woff2 → spline-sans-mono-latin-wght-normal-46b7dcafe3e51dbe.woff2} +0 -0
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ boundary, and the background loops.
|
|
|
81
81
|
|
|
82
82
|
## Requirements
|
|
83
83
|
|
|
84
|
-
- [Bun](https://bun.sh/) 1.4 or later. Bun is the runtime, not just the
|
|
84
|
+
- [Bun](https://bun.sh/) 1.4.4 or later. Bun is the runtime, not just the
|
|
85
85
|
installer, so a Node-only machine cannot run OmniGateway.
|
|
86
86
|
- A directory that persists, for the SQLite database.
|
|
87
87
|
- At least one Anthropic, OpenAI, Kimi Coding, Kilo, or xAI account to connect.
|
|
@@ -216,8 +216,12 @@ omni keys guardrail <id> --clear
|
|
|
216
216
|
The classifier sees the request's system prompt and the last few messages a human
|
|
217
217
|
wrote (`guardrailHistoryTurns`, default 3, 1..10), oldest first, and judges the
|
|
218
218
|
newest in their light — so "continue" after a forbidden ask is judged as that
|
|
219
|
-
ask. It
|
|
220
|
-
|
|
219
|
+
ask. It also sees the text of the tool results that came back after the oldest of
|
|
220
|
+
those messages (capped at 16,000 characters, newest first), as data the client
|
|
221
|
+
received. It never sees images, files, tool-call arguments, or assistant replies,
|
|
222
|
+
and only a plain `ALLOW` lets the request through. Tool output can sway the
|
|
223
|
+
verdict either way — a fetched page can talk the classifier round or push it to
|
|
224
|
+
refuse legitimate work — and an agent pays one classifier call per tool turn. A deny is refused as `CONTENT_FILTER` (400); a
|
|
221
225
|
classifier that times out (`guardrailTimeoutMs`, default 10s), errors, or answers
|
|
222
226
|
anything else refuses as `UPSTREAM` (502), and a key with a policy while
|
|
223
227
|
`guardrailModel` is unset refuses as `INTERNAL` (500): **it fails closed**.
|
|
@@ -225,7 +229,7 @@ Streaming requests receive the same refusals as in-stream errors. The refusal
|
|
|
225
229
|
messages are fixed; the classifier's words never reach the client. Each check is
|
|
226
230
|
its own request row under the key, tagged `guardrail:classifier` and charged to
|
|
227
231
|
it, and verdicts are cached for an hour per key, policy, model and judged text,
|
|
228
|
-
so
|
|
232
|
+
so a repeated request is judged once, though each new tool turn is a new one. The key holder sees
|
|
229
233
|
the policy and those rows on their client dashboard. A key without a policy is
|
|
230
234
|
never judged and pays nothing. `omni doctor` warns when keys carry a policy and
|
|
231
235
|
nothing can judge them.
|
|
@@ -233,10 +237,80 @@ nothing can judge them.
|
|
|
233
237
|
**This is a guardrail, not a security boundary.** It stops ordinary misuse, not a
|
|
234
238
|
client set on getting past it — by talking the classifier round, spreading a
|
|
235
239
|
request over more messages than the window holds, leaving it out of the history
|
|
236
|
-
it sends,
|
|
240
|
+
it sends, hiding it in images, or planting text in tool output the classifier
|
|
241
|
+
reads. **Rolling back** to
|
|
237
242
|
a build without usage policies ignores them: every key's requests are served
|
|
238
243
|
unjudged until you upgrade again.
|
|
239
244
|
|
|
245
|
+
A key can also be set to **route confidential requests to a local model**. A
|
|
246
|
+
classifier running on your own infrastructure reads what the request carries; if
|
|
247
|
+
anything in it is confidential, the request is served by a model you host instead
|
|
248
|
+
of the one the client asked for. It is active only when the global switch
|
|
249
|
+
`smartRouterEnabled` **and** the key's flag are both on:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
omni settings set smartRouterClassifierModel local-judge # a virtual model, every target a custom endpoint
|
|
253
|
+
omni settings set smartRouterLocalModel local-llm # same rule
|
|
254
|
+
omni settings set smartRouterEnabled true
|
|
255
|
+
omni keys smart-routing <id> --on # or: omni keys create --smart-routing
|
|
256
|
+
omni keys smart-routing <id> --off
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Both models must be configured virtual models whose every target is the `custom`
|
|
260
|
+
provider, and the gateway re-checks that at the moment of each send, so a model
|
|
261
|
+
edited later cannot quietly start pointing at an external provider. Anything
|
|
262
|
+
else is refused, never routed externally. `smartRouterPolicy` says what
|
|
263
|
+
"confidential" means (personal data, credentials, salaries and HR records,
|
|
264
|
+
customer records, non-public financials, documents marked internal, by default;
|
|
265
|
+
editable on the console's Settings screen, which can reset it) and
|
|
266
|
+
`smartRouterTimeoutMs` bounds each classifier call (default 10s, 1..60000).
|
|
267
|
+
|
|
268
|
+
Everything the request carries is judged — system and mid-conversation system
|
|
269
|
+
turns, user and assistant text, thinking, tool-call arguments, tool results, tool
|
|
270
|
+
names, descriptions and input schemas, citations, the text inside provider-native
|
|
271
|
+
blocks (a text document, a search result, an MCP result, a shell output) and
|
|
272
|
+
pass-through vendor fields — not just the newest message, because a client
|
|
273
|
+
resends the whole conversation. Only images, files and base64 payloads are not
|
|
274
|
+
judged. The text is split into segments of up to
|
|
275
|
+
8,000 characters, each judged `PUBLIC` or `CONFIDENTIAL` by the local classifier,
|
|
276
|
+
at most four at a time. Verdicts are cached for an hour per classifier, policy
|
|
277
|
+
and segment, so a conversation that grows is judged only on what is new; failures
|
|
278
|
+
are not cached. A request with more than 64 segments still to judge goes local
|
|
279
|
+
without being judged.
|
|
280
|
+
|
|
281
|
+
| Outcome | Result | Row tag |
|
|
282
|
+
| --- | --- | --- |
|
|
283
|
+
| everything public | served by the model the client asked for | `smart-router:public` |
|
|
284
|
+
| anything confidential | served by `smartRouterLocalModel` | `smart-router:local` |
|
|
285
|
+
| more than 64 segments still to judge | served by `smartRouterLocalModel`, not judged | `smart-router:local`, `smart-router:oversize` |
|
|
286
|
+
| asked for a local-only model already | served as asked, not judged | `smart-router:already-local` |
|
|
287
|
+
| classifier timeout, error, or unreadable reply | refused, `UPSTREAM` (502) | `smart-router:unavailable` |
|
|
288
|
+
| either model unset, unresolved, or not local-only | refused, `INTERNAL` (500) | `smart-router:unconfigured` |
|
|
289
|
+
|
|
290
|
+
**It fails closed and never falls back to an external provider**: if the local
|
|
291
|
+
model itself fails, the client gets that failure. A confidential request the local
|
|
292
|
+
model cannot serve is refused with `NO_CANDIDATES` (503) rather than sent out — one
|
|
293
|
+
carrying provider-native content (an Anthropic `search_result` or `document`, a
|
|
294
|
+
server-tool result) or provider-defined tools (`web_search`, `bash`, …), which only
|
|
295
|
+
that provider can accept, or tools or images the local model lacks. The row still
|
|
296
|
+
carries `smart-router:local`. Each check is its own request
|
|
297
|
+
row under the key, tagged `smart-router:classifier` and charged to it. When a
|
|
298
|
+
key also has a usage policy, smart routing runs first, and a request that goes
|
|
299
|
+
local has its policy judged by the smart-router classifier, never by
|
|
300
|
+
`guardrailModel`. `omni doctor` has a "smart routing" row; the console's
|
|
301
|
+
Settings screen warns under each model picker when the model is unset (switch
|
|
302
|
+
on), does not resolve, or is not local-only, and the Keys board says when
|
|
303
|
+
flagged keys' requests are refused or unscreened. The client
|
|
304
|
+
dashboard shows "Confidential routing: on/off" for the key. The client-visible
|
|
305
|
+
signals are in [docs/client-api.md](docs/client-api.md#confidential-routing).
|
|
306
|
+
|
|
307
|
+
**This reduces leaks of ordinary confidential content; it is not a security
|
|
308
|
+
boundary.** It does not stop deliberate evasion (encoding, splitting a secret
|
|
309
|
+
across messages, prompt injection aimed at the classifier), confidential content
|
|
310
|
+
inside images or files, or a classifier that simply misses. **Rolling back** to a
|
|
311
|
+
build without it ignores the flag and sends every request to the external
|
|
312
|
+
provider (it fails open) until you upgrade again.
|
|
313
|
+
|
|
240
314
|
Now use it:
|
|
241
315
|
|
|
242
316
|
```bash
|
|
@@ -463,7 +537,7 @@ Worth knowing before you deploy it:
|
|
|
463
537
|
classifier calls instead; these remain billed as token usage. See
|
|
464
538
|
[Anthropic's notice guide](https://code.claude.com/docs/en/auto-mode-classifier-billing).
|
|
465
539
|
- **An OpenAI OAuth (ChatGPT) target presents itself as Codex, and answers like
|
|
466
|
-
it.** Requests on that leg
|
|
540
|
+
it.** Requests on that leg follow Codex 0.165.0's captured TUI shape, which
|
|
467
541
|
changes model behaviour for every client routed there, Claude Code included:
|
|
468
542
|
one tool call per turn (`parallel_tool_calls: false`), terser answers
|
|
469
543
|
(`text.verbosity: "low"`), and a request that names no reasoning effort —
|
|
@@ -559,6 +633,10 @@ conventions, [docs/adding-a-provider.md](docs/adding-a-provider.md) for the
|
|
|
559
633
|
provider checklist, and `docs/superpowers/specs/` for the design documents
|
|
560
634
|
behind each feature.
|
|
561
635
|
|
|
636
|
+
The checkout pins Bun 1.4.4 for local builds, CI, and releases. See the
|
|
637
|
+
[Bun built-ins audit](docs/bun-builtins-audit.md) for native-tool migrations and
|
|
638
|
+
compatibility boundaries.
|
|
639
|
+
|
|
562
640
|
```bash
|
|
563
641
|
git clone https://github.com/harismawan/omnigateway.git
|
|
564
642
|
cd omnigateway
|
|
@@ -568,5 +646,11 @@ bun run build:dashboard # the gateway serves this build
|
|
|
568
646
|
bun run dev # gateway on 9000, with file watching
|
|
569
647
|
```
|
|
570
648
|
|
|
649
|
+
For dashboard development, run `bun run dev:dashboard` in another terminal
|
|
650
|
+
(port 5173, API/health proxied to 9000). Bun rebuilds after source changes and
|
|
651
|
+
reloads the page; component state resets, with no React Fast Refresh.
|
|
652
|
+
`bun run --cwd apps/dashboard preview` serves an existing build on port 4173.
|
|
653
|
+
Both commands accept `--host`, `--port` and `--upstream` options.
|
|
654
|
+
|
|
571
655
|
Releases are published to npm from a `v*` tag, with provenance attesting which
|
|
572
656
|
commit produced them.
|