@juspay/neurolink 13.8.13 → 13.8.15
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/CHANGELOG.md +2 -2
- package/dist/browser/neurolink.min.js +422 -422
- package/dist/cli/utils/serverUtils.d.ts +4 -0
- package/dist/cli/utils/serverUtils.js +5 -1
- package/dist/server/abstract/baseServerAdapter.d.ts +30 -1
- package/dist/server/abstract/baseServerAdapter.js +71 -0
- package/dist/server/adapters/expressAdapter.js +5 -0
- package/dist/server/adapters/fastifyAdapter.d.ts +1 -0
- package/dist/server/adapters/fastifyAdapter.js +16 -3
- package/dist/server/adapters/honoAdapter.d.ts +6 -0
- package/dist/server/adapters/honoAdapter.js +67 -16
- package/dist/server/adapters/koaAdapter.js +5 -0
- package/dist/server/middleware/auth.js +3 -0
- package/dist/server/routes/agentRoutes.d.ts +42 -1
- package/dist/server/routes/agentRoutes.js +140 -31
- package/dist/server/routes/codexProxyRoutes.js +65 -6
- package/dist/server/routes/index.d.ts +9 -0
- package/dist/server/routes/index.js +15 -1
- package/dist/server/utils/carriedContextMark.d.ts +28 -0
- package/dist/server/utils/carriedContextMark.js +32 -0
- package/dist/types/proxy.d.ts +4 -0
- package/dist/types/server.d.ts +140 -2
- package/docs-site/static/search-index.json +8 -6
- package/package.json +4 -2
package/dist/types/server.d.ts
CHANGED
|
@@ -40,6 +40,41 @@ export type ServerAdapterConfig = {
|
|
|
40
40
|
redaction?: RedactionConfig;
|
|
41
41
|
/** Shutdown configuration for graceful shutdown behavior */
|
|
42
42
|
shutdown?: ShutdownConfig;
|
|
43
|
+
/**
|
|
44
|
+
* Carry what middleware sets on its context (`ctx.user`, `ctx.session`,
|
|
45
|
+
* `ctx.metadata`, `ctx.abortSignal` and `ctx.abortController`) to later
|
|
46
|
+
* middleware and to the route handler, on every built-in adapter (default:
|
|
47
|
+
* `false`). It does not apply to a context you build yourself: a custom
|
|
48
|
+
* adapter, or a route handler called directly, can supply a context that
|
|
49
|
+
* already has `ctx.user` set.
|
|
50
|
+
*
|
|
51
|
+
* Off, each adapter propagates context as it always did. Express, Fastify
|
|
52
|
+
* and Koa build a fresh context for every middleware step and for the
|
|
53
|
+
* handler and carry only `responseHeaders`; Hono shares one context between
|
|
54
|
+
* the steps and the handler only when the caller sent its own
|
|
55
|
+
* `X-Request-ID`. So a role guard, a permission guard or a rate-limit
|
|
56
|
+
* `keyGenerator` registered after authentication sees `ctx.user` only on
|
|
57
|
+
* that Hono request shape: on Express, Fastify and Koa, and on Hono without
|
|
58
|
+
* a caller `X-Request-ID`, the user never reaches it and the guard refuses
|
|
59
|
+
* everyone.
|
|
60
|
+
*
|
|
61
|
+
* On, the user and the rest reach later middleware and the handler on every
|
|
62
|
+
* built-in adapter. Set it when guards or key generators depend on `ctx.user`.
|
|
63
|
+
* `registerAllRoutes()` turns it on for the server by itself when called with
|
|
64
|
+
* `perUserAuth`, which needs the user in the handler. A caller that builds
|
|
65
|
+
* the agent routes with `createAgentRoutes(basePath, { perUserAuth: true })`
|
|
66
|
+
* and registers them itself must set this on the server: with it off, such a
|
|
67
|
+
* request has a user only on Hono when the client sent its own
|
|
68
|
+
* `X-Request-ID`, and every other request runs as anonymous (no `userId`, no
|
|
69
|
+
* session).
|
|
70
|
+
*
|
|
71
|
+
* The agent routes' warning about a body naming another user is raised only
|
|
72
|
+
* with this on. With it off, a handler that does receive `ctx.user` (Hono
|
|
73
|
+
* when the caller sent its own `X-Request-ID`) takes the user from it and
|
|
74
|
+
* ignores the body's `userId`, so nothing is named over it; every other
|
|
75
|
+
* request reaches the handler without a `ctx.user` to compare against.
|
|
76
|
+
*/
|
|
77
|
+
carryMiddlewareState?: boolean;
|
|
43
78
|
};
|
|
44
79
|
/**
|
|
45
80
|
* Required server adapter configuration (with defaults applied)
|
|
@@ -58,6 +93,7 @@ export type RequiredServerAdapterConfig = {
|
|
|
58
93
|
disableBuiltInHealth: boolean;
|
|
59
94
|
redaction?: RequiredRedactionConfig;
|
|
60
95
|
shutdown: RequiredShutdownConfig;
|
|
96
|
+
carryMiddlewareState: boolean;
|
|
61
97
|
};
|
|
62
98
|
/**
|
|
63
99
|
* CORS configuration
|
|
@@ -256,6 +292,12 @@ export type ServerContext = {
|
|
|
256
292
|
/** Redaction configuration (for stream redaction support) */
|
|
257
293
|
redaction?: RedactionConfig;
|
|
258
294
|
};
|
|
295
|
+
/**
|
|
296
|
+
* What middleware sets on its context that later middleware and the route
|
|
297
|
+
* handler must see. Adapters build a fresh context for every step, so this is
|
|
298
|
+
* what they carry between steps in the framework's per-request storage.
|
|
299
|
+
*/
|
|
300
|
+
export type ServerCarriedContext = Pick<ServerContext, "user" | "session" | "metadata" | "abortSignal" | "abortController">;
|
|
259
301
|
/**
|
|
260
302
|
* Server response object
|
|
261
303
|
*/
|
|
@@ -471,6 +513,50 @@ export type ServerAgentRouteOptions = {
|
|
|
471
513
|
* file or download that would overflow it stops mid-transfer.
|
|
472
514
|
*/
|
|
473
515
|
maxInputTotalBytes?: number;
|
|
516
|
+
/**
|
|
517
|
+
* For a caller of `createAgentRoutes()` itself; with `registerAllRoutes()` /
|
|
518
|
+
* `createAllRoutes()` use `CreateRoutesOptions.perUserAuth` instead. The
|
|
519
|
+
* routes can only take identity from `ctx.user` if the server hands it to
|
|
520
|
+
* the handler, so a caller that registers them itself with this option must
|
|
521
|
+
* create the server with `carryMiddlewareState: true`; `registerAllRoutes()`
|
|
522
|
+
* does that for the server by itself. With `carryMiddlewareState` off, such a request has
|
|
523
|
+
* a user only on Hono when the client sent its own `X-Request-ID` (Hono then
|
|
524
|
+
* hands the handler the middleware's context regardless); every other request
|
|
525
|
+
* runs as anonymous, with no `userId` and no session.
|
|
526
|
+
*
|
|
527
|
+
* Set to `true` when the authentication middleware identifies individual
|
|
528
|
+
* people (one credential per person). The agent routes then take `userId`
|
|
529
|
+
* and the session only from the authenticated user (`ctx.user`,
|
|
530
|
+
* `ctx.session`) and ignore the request body's, on every adapter and for
|
|
531
|
+
* every request, so a caller cannot act as someone else. A request with no
|
|
532
|
+
* authenticated user gets no `userId` and no session, so with optional
|
|
533
|
+
* authentication anonymous callers never share a conversation. Any truthy
|
|
534
|
+
* value turns it on.
|
|
535
|
+
*
|
|
536
|
+
* **A server with per-person authentication must set this.** Left at the
|
|
537
|
+
* default (`false`) identity resolves as it always has: requests choose
|
|
538
|
+
* `userId` and `sessionId` in the body, so any authenticated caller can name
|
|
539
|
+
* another person there and act as them. The one exception is Hono, where a
|
|
540
|
+
* request whose client sent its own `X-Request-ID` header reaches the
|
|
541
|
+
* handler with the middleware's context, and an authenticated `ctx.user`
|
|
542
|
+
* (and `ctx.session`) wins over the body, as before, and so does it on a
|
|
543
|
+
* context the built-in adapters did not build (your own adapter, a handler
|
|
544
|
+
* called directly). Only this flag, with `carryMiddlewareState` on, makes the agent routes take
|
|
545
|
+
* the user from `ctx.user`, and ignore the body's `userId`, on every
|
|
546
|
+
* built-in adapter and every request. When the server carries middleware state
|
|
547
|
+
* the routes log one warning per instance the first time a request served
|
|
548
|
+
* from the body names a different `userId` than a `ctx.user` that is not
|
|
549
|
+
* marked `shared: true`; the body's `userId` is still used. With `carryMiddlewareState`
|
|
550
|
+
* off the handler has no `ctx.user` on such a request, so there is nothing to
|
|
551
|
+
* compare and no warning.
|
|
552
|
+
*
|
|
553
|
+
* Leave it unset for no authentication or one shared API key, such as
|
|
554
|
+
* `neurolink serve` with `NEUROLINK_SERVER_API_KEY`: a shared key names no
|
|
555
|
+
* person, so requests choose `userId` and `sessionId` in the body. Middleware
|
|
556
|
+
* for a shared key should set `shared: true` on the `AuthenticatedUser` it
|
|
557
|
+
* returns, which keeps the warning quiet (the CLI's key middleware does).
|
|
558
|
+
*/
|
|
559
|
+
perUserAuth?: boolean;
|
|
474
560
|
};
|
|
475
561
|
/**
|
|
476
562
|
* The route options plus the one thing that belongs to a single call:
|
|
@@ -762,6 +848,15 @@ export type WebSocketRequestId = string | number;
|
|
|
762
848
|
*/
|
|
763
849
|
export type AuthenticatedUser = {
|
|
764
850
|
id: string;
|
|
851
|
+
/**
|
|
852
|
+
* `true` when this identity stands for every holder of one credential, such
|
|
853
|
+
* as a shared API key, rather than for one person. The agent routes then do
|
|
854
|
+
* not warn when a request names a different `userId` in its body: with a
|
|
855
|
+
* shared key every caller is one trust domain and the body is how callers
|
|
856
|
+
* keep separate conversation memory. Middleware that sets one fixed user for
|
|
857
|
+
* everyone holding a key should set this; per-person middleware should not.
|
|
858
|
+
*/
|
|
859
|
+
shared?: boolean;
|
|
765
860
|
email?: string;
|
|
766
861
|
name?: string;
|
|
767
862
|
roles?: string[];
|
|
@@ -1073,6 +1168,12 @@ export type AuthResult = {
|
|
|
1073
1168
|
email?: string;
|
|
1074
1169
|
/** User roles (optional) */
|
|
1075
1170
|
roles?: string[];
|
|
1171
|
+
/**
|
|
1172
|
+
* `true` when this identity stands for every holder of one credential, such
|
|
1173
|
+
* as a shared API key, rather than one person. Carried to `ctx.user.shared`;
|
|
1174
|
+
* see `AuthenticatedUser.shared`.
|
|
1175
|
+
*/
|
|
1176
|
+
shared?: boolean;
|
|
1076
1177
|
/** Additional user data */
|
|
1077
1178
|
metadata?: Record<string, unknown>;
|
|
1078
1179
|
};
|
|
@@ -1174,9 +1275,46 @@ export type CreateRoutesOptions = {
|
|
|
1174
1275
|
/**
|
|
1175
1276
|
* Options for the agent routes (`POST <basePath>/agent/execute` and
|
|
1176
1277
|
* `/agent/stream`): where local-path attachments may be read from, and how
|
|
1177
|
-
* large an attachment may be.
|
|
1278
|
+
* large an attachment may be. Whose identity the routes trust is decided by
|
|
1279
|
+
* the top-level `perUserAuth`, which is why it is not accepted here.
|
|
1280
|
+
*/
|
|
1281
|
+
agent?: Omit<ServerAgentRouteOptions, "perUserAuth">;
|
|
1282
|
+
/**
|
|
1283
|
+
* Set to `true` when the authentication middleware identifies individual
|
|
1284
|
+
* people (one credential per person). The agent routes then take `userId`
|
|
1285
|
+
* and the session only from the authenticated user and ignore the request
|
|
1286
|
+
* body's, on every adapter and for every request; a request with no
|
|
1287
|
+
* authenticated user gets neither. Any truthy value turns it on.
|
|
1288
|
+
*
|
|
1289
|
+
* **A server with per-person authentication must set this.** Left at the
|
|
1290
|
+
* default (`false`) requests choose `userId` and `sessionId` in the body, so
|
|
1291
|
+
* any authenticated caller can name another person there and act as them.
|
|
1292
|
+
* The one exception is Hono, where a request whose client sent its own
|
|
1293
|
+
* `X-Request-ID` header reaches the handler with the middleware's context and
|
|
1294
|
+
* an authenticated `ctx.user` wins over the body, as before, and so on a
|
|
1295
|
+
* context the built-in adapters did not build (your own adapter, a handler
|
|
1296
|
+
* called directly); only this flag, with `carryMiddlewareState` on, makes the agent routes take
|
|
1297
|
+
* the user from `ctx.user` everywhere. When the server carries middleware state, the first time a
|
|
1298
|
+
* request served from the body names a different `userId` than its
|
|
1299
|
+
* `ctx.user`, the routes log a warning (once per instance); with `carryMiddlewareState`
|
|
1300
|
+
* off the handler has no `ctx.user` to compare, and there is no warning.
|
|
1301
|
+
* Leave it unset for no authentication or one shared
|
|
1302
|
+
* API key, such as `neurolink serve` with `NEUROLINK_SERVER_API_KEY`:
|
|
1303
|
+
* requests choose `userId` and `sessionId` in the body. Middleware for a
|
|
1304
|
+
* shared key should set `shared: true` on the `AuthenticatedUser` it
|
|
1305
|
+
* returns, which keeps the warning quiet.
|
|
1306
|
+
*
|
|
1307
|
+
* This is the one switch for a server built with `registerAllRoutes` /
|
|
1308
|
+
* `createAllRoutes`: every route group that scopes by identity reads it from
|
|
1309
|
+
* here, so it cannot be set for the agent routes alone. `registerAllRoutes`
|
|
1310
|
+
* also turns on the server's `carryMiddlewareState` when this is set, since
|
|
1311
|
+
* the routes need the user in the handler; `createAllRoutes` returns route
|
|
1312
|
+
* groups only, so a caller that registers them itself must create the server
|
|
1313
|
+
* with `carryMiddlewareState: true`; with `carryMiddlewareState` off, a `perUserAuth`
|
|
1314
|
+
* request has a user only on Hono when the client sent its own
|
|
1315
|
+
* `X-Request-ID`, and every other request runs as anonymous.
|
|
1178
1316
|
*/
|
|
1179
|
-
|
|
1317
|
+
perUserAuth?: boolean;
|
|
1180
1318
|
};
|
|
1181
1319
|
/** Options for `createTranscribeRoutes()`. */
|
|
1182
1320
|
/**
|
|
@@ -2672,13 +2672,13 @@
|
|
|
2672
2672
|
{"objectID":"2c1717347ebf0ec18b9aa2738c5628682d4318c893427fdc5267caed3fe54845","title":"3. Client auto-configuration","url":"/docs/features/codex-proxy-support#3-client-auto-configuration","content":"When neurolink proxy start runs (non-dev), it configures the Codex CLI the same way it configures Claude Code and OpenCode. It appends a marker-delimited block to ~/.codex/config.toml:\n\nYour original model_provider value is snapshotted to ~/.neurolink/codex-proxy-snapshot.json and restored on shutdown, so the edit is fully reversible even if the proxy crashes. The managed block is delimited by markers and removed cleanly on clear. If ~/.codex/config.toml doesn't exist, the step is skipped silently.\n\nRestart Codex after starting the proxy for it to pick up the new provider.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"3. Client auto-configuration","lvl3":""}},
|
|
2673
2673
|
{"objectID":"404cd8f6d8542fc84651326cf0b252e7c3c3098678409fecaf8c2ff1559906fd","title":"4. Quota and routing","url":"/docs/features/codex-proxy-support#4-quota-and-routing","content":"Codex reports two rate-limit windows — primary (short) and secondary (weekly) — which map onto the shared AccountQuota model as the session and weekly fields respectively. That means Codex reuses the existing cooldown, persistence, and display code rather than duplicating it.\n\nAccount ordering is fill-first and quota-aware:\nAccounts on cooldown sort last.\nWithin the same cooldown state, accounts with a rejected unified quota sort after accounts without known rejection, even when their session usage is low or unknown.\nWithin each group, accounts with no session quota measurement sort first — they get probed so they become comparable, rather than being starved.\nOtherwise, least session utilization first. Rejected accounts remain eligible after preferred accounts so stale rejection evidence cannot permanently prevent a recovery probe.\n\nCooldown reasons map to the shared vocabulary: a rejected weekly window cools until its real reset (weekly), a rejected primary window until its reset (session), and a plain burst limit gets a bounded transient cooldown (60 s floor, 15 min ceiling).\n\nQuota and cooldown state are keyed by the full codex: account key, so a Codex account and an Anthropic account that share a bare label never collide.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"4. Quota and routing","lvl3":""}},
|
|
2674
2674
|
{"objectID":"acb592d28fcb90659fa175ac4f0d1e73cfb535d0aac2b63a101f0722e538eff7","title":"5. Response headers","url":"/docs/features/codex-proxy-support#5-response-headers","content":"A response served by the Codex pool carries these attribution headers. A\nresponse served by the outbound fallback\ncarries only x-neurolink-served-by: the account, attempt and quota headers\ndescribe a Codex account, and none served that turn.\n\n| Header | Meaning |\n| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| x-neurolink-account | Which pooled account served the request |\n| x-neurolink-account-type | Always codex-oauth |\n| x-neurolink-served-by | codex, or codex-outbound-fallback:anthropic / codex-outbound-fallback:vertex when the outbound fallback served the turn |\n| x-neurolink-attempt | Which attempt succeeded (1 = first account tried) |\n| x-neurolink-quota-source | live when the backend reported quota, else none |\n| x-neurolink-quota-session-left-pct | Remaining primary-window headroom |\n| x-neurolink-quota-weekly-left-pct | Canonical remaining","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"5. Response headers","lvl3":""}},
|
|
2675
|
-
{"objectID":"2b17d62c4d9cb65067100d6a90003bee2dce2bc06ede425f25f0b761aade359a","title":"6. Error handling","url":"/docs/features/codex-proxy-support#6-error-handling","content":"| Condition
|
|
2675
|
+
{"objectID":"2b17d62c4d9cb65067100d6a90003bee2dce2bc06ede425f25f0b761aade359a","title":"6. Error handling","url":"/docs/features/codex-proxy-support#6-error-handling","content":"| Condition | Behaviour |\n| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| No Codex accounts configured | 401 with a message pointing at neurolink auth login codex |\n| All accounts cooling | Terminal response.failed SSE event (200, retry-after computed from the soonest recovery) instead of a bare 429, so the CLI shows a real error instead of \"Reconnecting...\" |\n| All accounts auth-cooling | The same terminal event with code server_error instead of insufficient_quota (every account is parked by an auth failure), so it is not reported as spent quota |\n| 401 / 403 from upstream | One forced token refresh and a retry; a second rejection parks the account for 60 s and rotates; a failed refresh disables the account until re-login |\n| 401 / 403 with a request-refusal code | The request ends on that account with no refresh, cooldown or rotation: a policy code answers 403, an invalid-request code keeps the upstream status (see below) |\n| 429 | Cool the account per its reported window, then rotate |\n| 5xx / network | Rotate to the next account |","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"6. Error handling","lvl3":""}},
|
|
2676
2676
|
{"objectID":"9b1627d0fcff6a9e292b7f794fb47e62eb3da6b9c633e308da2b1de08a83368d","title":"7. Implementation map","url":"/docs/features/codex-proxy-support#7-implementation-map","content":"| File | Role |\n| ------------------------------------------- | ----------------------------------------------------------------------------------------- |\n| src/lib/types/codex.ts | Codex auth-file, token, and rate-limit types |\n| src/lib/auth/codexOAuth.ts | Endpoints/constants, auth.json import, token refresh, JWT decode, account-id resolution |\n| src/lib/proxy/codexAccountUsage.ts | Account enumeration, usage fetch, quota normalisation, header parsing |\n| src/lib/server/routes/codexProxyRoutes.ts | The pool engine: load → order → forward → rotate |\n| src/cli/commands/auth.ts | auth login codex, Codex rows in auth list --refresh |\n| src/cli/commands/proxy.ts | Route registration, /backend-api/* request tracking, ~/.codex/config.toml management |\n\nThe Anthropic engine in claudeProxyRoutes.ts is untouched. The Codex engine is deliberately leaner: it does pre-commit rotation but not the full transient-retry-budget or admission-lease machinery.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"7. Implementation map","lvl3":""}},
|
|
2677
2677
|
{"objectID":"c90a5222434bc717385c13b9e9f9cb865d3ce71ed7a58c077a7b5241def7d086","title":"8. Caveats","url":"/docs/features/codex-proxy-support#8-caveats","content":"Model ids matter. The ChatGPT backend rejects models that aren't available to Codex-with-a-ChatGPT-account (e.g. gpt-5-codex returns a 400). Use the model your Codex config already uses.\nTerms of service. Pooling multiple personal ChatGPT subscriptions through one client fingerprint is the kind of pattern subscription anti-abuse systems are built to detect. The originator, installation_id, user-agent, and turn-metadata headers are all correlatable. Pooling your own accounts is materially different from sharing across people — weigh the account-ban risk accordingly.\nNative browser login is not implemented. The verified path is importing an existing codex login credential. The OAuth constants (authorize URL, PKCE, scopes) are present in codexOAuth.ts for a future native flow.\nQuota-aware ordering is unverified against the live backend. The usage endpoint and the rate-limit header shape were reconstructed from a capture, not confirmed end to end. If either is wrong, fetchCodexAccountUsage returns no quota, x-neurolink-quota-source reads none, and ordering degenerates to insertion order while every 429 falls back to the 15-minute transient cooldown. Rotation still works; it is simply not quota-aware. Verify with neurolink auth list --refresh — a codex usage … error line per account means the quota path is not live.\nSSE usage-limit signals are not acted on. Only an HTTP 429 triggers a cooldown and rotation. A 200 response whose SSE stream carries usage_limit_reached (or the workspace-credit variants) is relayed to the client untouched, so the account is neither cooled nor rotated away from. HTTP-level exhaustion is handled; in-stream exhaustion is not.\nClient fingerprint is forwarded verbatim. The proxy replaces the caller's credentials but does not regenerate originator, installation_id, session-id, or turn metadata per account, so every pooled account shares the client's fingerprint. This is what makes the terms-of-service point above concrete.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"8. Caveats","lvl3":""}},
|
|
2678
2678
|
{"objectID":"607b92eb2c3b89a57438267a92b6212e616ad0dd106cb1c1a6bd0514c3446cd2","title":"Model discovery","url":"/docs/features/codex-proxy-support#model-discovery","content":"The Codex CLI refreshes its model list on every invocation:\n\nThe proxy relays that upstream to chatgpt.com/backend-api/codex/models using a\npooled account, forwarding the CLI's own query parameters.\n\nIt relays rather than synthesises, unlike the Claude and OpenAI /v1/models\nroutes, which build their lists locally from the model router. Which Codex\nmodels an account can reach is a property of that account — plan tier, rollout\nstate — not something this proxy knows, so a locally-built list would be a guess\nthat reads as authoritative.\n\nTwo details matter to anyone touching it:\nclient_version is required upstream. Omit it and ChatGPT answers 400\n with a pydantic Field required on ('query', 'client_version'). The query\n is rebuilt from ctx.query; ctx.path carries no query string, and reading it\n from there drops the parameter silently.\nDiscovery is side-effect free. No cooldown is recorded and no quota is\n consumed, so the once-per-invocation refresh cannot influence routing for real\n traffic. A cooling account is still allowed to answer it — being rate-limited\n for completions does not make an account unable to say which models exist.\n\nBefore this route existed the request 404'd, and the CLI printed\nfailed to refresh available models: unexpected status 404 Not Found on every\nrun before silently falling back to a default model — quietly ignoring the model\nthe user had configured.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"Model discovery","lvl3":""}},
|
|
2679
2679
|
{"objectID":"6d2395f1bb843928fffc947203d5d331fb549bb7d9403adfa777e676578b4d18","title":"Status: implemented, default OFF, request-shape verified only — see \"Live validation\" below","url":"/docs/features/codex-proxy-support#status-implemented-default-off-request-shape-verified-only-see-live-validation-below","content":"Sections 1-8 above cover the inbound direction: a Codex CLI request served\nby the Codex/ChatGPT pool engine. This section covers the opposite direction —\na native Codex /backend-api/codex/responses request that, when every Codex\naccount is exhausted or otherwise ineligible, is translated into an\nAnthropic Messages request and served by either the Anthropic OAuth pool (via\nan in-process loopback, no extra network hop to this same proxy) or a\nVertex-Claude passthrough account, then translated back into the Codex\nResponses wire shape the CLI expects. It is a third direction alongside the\ntwo-engine matrix in the rest of this document, not a replacement for either.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"Status: implemented, default OFF, request-shape verified only — see \"Live validation\" below","lvl3":""}},
|
|
2680
2680
|
{"objectID":"3c2f324de0830846bbdce959aabe14903475260a2adfabf478b669fef52ac726","title":"9.1 Enabling it","url":"/docs/features/codex-proxy-support#91-enabling-it","content":"The kill switch defaults to off. Nothing changes for an existing Codex\npool setup until you opt in:\n\nor via environment variable, which overrides the YAML key:\n\ncodex-outbound-fallback-targets is required (non-empty) for the fallback to\never fire — the kill switch alone is not enough. provider must be anthropic\nor vertex; up to 8 targets are accepted and validated at config-load time.\nWith the flag off, or with no targets configured, an exhausted Codex request\nbehaves exactly as it did before this feature existed: the same terminal\nresponse.failed SSE / 401 behaviour documented in section 6 above, byte-\nfor-byte.\n\nThe anthropic target needs the CLI proxy's in-process loopback. Dispatch\nto an anthropic target goes through an in-process loopback\n(127.0.0.1:<loopbackPort> plus an unforgeable internalDispatch marker, see\n§9.3) rather than a second network hop, and only neurolink proxy start (the\nCLI proxy command) wires that loopback through today. createAllRoutes /\nregisterAllRoutes — the generic SDK route surface in\nsrc/lib/server/routes/index.ts, used when embedding the proxy routes in your\nown server — does not thread loopbackPort/internalDispatch into\ncreateCodexProxyRoutes, so enabling this feature there with an anthropic\ntarget configured cannot actually dispatch: route creation logs one warning\nand every such request falls through to the normal Codex-exhaustion behaviour\nin section 6, indistinguishable on the wire from the feature being off. A\nvertex target has no such gap — it dispatches over executeVertexAnthropicFallback\nregardless of which route surface created the routes. If you need the\nanthropic target from the SDK route surface, run the CLI proxy alongside\nyour server, or wait for loopbackPort/internalDispatch to be threaded\nthrough CreateRoutesOptions (not yet implemented — see the doc comments on\ncreateAllRoutes and CreateRoutesOptions.runtimeConfigProvider).","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.1 Enabling it","lvl3":""}},
|
|
2681
|
-
{"objectID":"d20a853143464660ecb4669832c8c0d5e24292564bc7ea9161354afda9a39223","title":"9.2 When it triggers","url":"/docs/features/codex-proxy-support#92-when-it-triggers","content":"attemptCodexOutboundFallback (module-private in codexProxyRoutes.ts) is\nconsulted only after every Codex account has been tried and failed, and only\nwhen all of the following hold, in this order — any one failing gate means\n\"not attempted\", and the request falls through to the normal Codex-exhaustion\nbehaviour in section 6:\nThe inbound request is not itself already a fallback leg (see loop\n prevention below).\nruntimeConfigProvider is configured (the proxy is running with the\n runtime-config feature enabled at all).\nclassifyCodexOutboundFailure judges the failure itself eligible — a total\n function, not a heuristic guess, over the terminal Codex failure class.\nThe kill switch (codexOutboundFallbackEnabled) is on.\ncodexOutboundFallbackTargets is non-empty.\nThe native Codex request body parses (parseCodexNativeRequest) — a\n request the translator cannot even parse is never a candidate.\n\nWhen the account loop runs out, the last attempt decides eligibility. A\n401/403 across the whole pool is a Codex credential failure and falls back, as\ndo 429 and 5xx. A content-policy or invalid-request error code\n(classifyProxyFailureCode), or any other 4xx, rejects the request itself and\nis returned unchanged.\n\nThe Anthropic loopback has a 5-minute timeout that covers the connection until\nits response headers arrive. After that the stream runs as long as the turn\ndoes; a client disconnect still ends it.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.2 When it triggers","lvl3":""}},
|
|
2681
|
+
{"objectID":"d20a853143464660ecb4669832c8c0d5e24292564bc7ea9161354afda9a39223","title":"9.2 When it triggers","url":"/docs/features/codex-proxy-support#92-when-it-triggers","content":"attemptCodexOutboundFallback (module-private in codexProxyRoutes.ts) is\nconsulted only after every Codex account has been tried and failed, and only\nwhen all of the following hold, in this order — any one failing gate means\n\"not attempted\", and the request falls through to the normal Codex-exhaustion\nbehaviour in section 6:\nThe inbound request is not itself already a fallback leg (see loop\n prevention below).\nruntimeConfigProvider is configured (the proxy is running with the\n runtime-config feature enabled at all).\nclassifyCodexOutboundFailure judges the failure itself eligible — a total\n function, not a heuristic guess, over the terminal Codex failure class.\nThe kill switch (codexOutboundFallbackEnabled) is on.\ncodexOutboundFallbackTargets is non-empty.\nThe native Codex request body parses (parseCodexNativeRequest) — a\n request the translator cannot even parse is never a candidate.\n\nWhen the account loop runs out, the last attempt decides eligibility. A\n401/403 across the whole pool is a Codex credential failure and falls back, as\ndo 429 and 5xx. A content-policy or invalid-request error code\n(classifyProxyFailureCode), or any other 4xx, rejects the request itself and\nis returned unchanged. A pre-stream 401/403 carrying such a code never reaches\nthis point: the pool ends the request on the account that received it (see\nsection 6).\n\nThe Anthropic loopback has a 5-minute timeout that covers the connection until\nits response headers arrive. After that the stream runs as long as the turn\ndoes; a client disconnect still ends it.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.2 When it triggers","lvl3":""}},
|
|
2682
2682
|
{"objectID":"63d9622db4658e47ba8122e511162860b322d42d2b741a5c76611250fe670550","title":"9.3 Loop prevention","url":"/docs/features/codex-proxy-support#93-loop-prevention","content":"Two independent guards, so a defect in one does not remove the bound:\nMarker guard. The moment every gate above has passed and a real\n dispatch attempt is about to begin, codexProxyRoutes.ts sets\n ctx.metadata[\"neurolink.codexOutboundFallbackAttempted\"] = true on the\n request context. Gate 1 above checks this same key, so a request that has\n already crossed engines once can never be offered a second outbound-fallback\n attempt within the same client request. This is a single flag, not a\n per-target counter, because at most one crossing is ever allowed regardless\n of how many of the internal dispatch call sites reach this function.\nDepth counter (defense-in-depth). ctx.metadata[\"neurolink.fallbackHopDepth\"]\n is incremented on every engine crossing (never on a same-engine account\n rotation) and checked against MAX_ENGINE_CROSSINGS = 1, independent of the\n marker check above. The invariant this enforces: the ordered sequence of\n engines serving any one client request has length ≤ 2 with no repeat — only\n [codex], [anthropic], [codex,anthropic], [anthropic,codex] are\n possible. A leg that is itself already an inner fallback of the other engine\n can never itself fall outbound again.\n\nA request that reaches this point already carrying a forged\ncodexOutboundFallbackAttempted-shaped marker from outside is not trusted —\nthe key lives on the server-side request context (ctx.metadata), not on\nanything the client can set on the wire, so there is no client-controlled way\nto spoof past gate 1.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.3 Loop prevention","lvl3":""}},
|
|
2683
2683
|
{"objectID":"21189de88d4ffef1c2a4bbd0420442de71fe8d9fd6b9f6278867e39602e075c6","title":"9.4 What gets translated","url":"/docs/features/codex-proxy-support#94-what-gets-translated","content":"Request translation (src/lib/proxy/codexOutboundFallback.ts):\nCodex additional_tools namespaces (functions, collaboration, …) are\n flattened into one Claude tools array, preserving declaration order —\n namespace order, then tool order within each namespace — never regrouped or\n resorted by tool kind.\nA tool's kind (function vs custom) is read from the tool declaration's\n own type field, never inferred from which namespace it was declared under.\nFunction-tool JSON Schemas are dereferenced with inlineJsonSchema: plain,\n resolvable $ref/$defs (draft-07 definitions and 2020-12 $defs) are\n flattened into the inline schema and the pointer keys stripped entirely.\n A genuinely circular $ref degrades to {type: \"object\"} and is counted\n under the circular_ref_flattened degrade reason (see metrics below); a\n plain non-circular $ref is not.\nGrammar/custom tools (Lark grammar, regex format) have no JSON Schema\n equivalent, so they are wrapped as a single {input: string} parameter, with\n the response mapped back to a custom_tool_call item. This is lossy and\n explicitly flagged in code, and is the shipped behavior — see \"Sign-off\n status\" below.\nReasoning effort (minimal/low/medium/high/xhigh/max on the Codex\n side) maps to an Anthropic thinking budget via mapCodexReasoningToThinking:\n low→4096, medium→8192, high→16384, xhigh→24576, max→32768, clamped to\n [1024, max_tokens - 1024]. Thinking is left off when tool_choice is\n forced, or when the immediately preceding assistant turn called a tool.\nA non-object function_call_output/custom_tool_call_output argument falls\n back to {input: raw} in the translated history rather than failing the\n translation.\n\nResponse translation (codexResponsesFormat.ts / codexToAnthropicFallback.ts)\nconverts the Claude response — including SSE streaming — back into the Codex\nResponses wire shape the CLI expects, so a client cannot tell, from the wire\nalone, that its request was served by a different engine underneath.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.4 What gets translated","lvl3":""}},
|
|
2684
2684
|
{"objectID":"4a8c83d10dbaa054203c48c374f7aed2688cb58670135943b0b2c6cd358cf129","title":"9.5 Accounting","url":"/docs/features/codex-proxy-support#95-accounting","content":"A translated request is billed and recorded exactly like any other proxied\nrequest on the serving engine — the same OTel usage record, cache/reasoning\nbuckets, and cost estimate described in Usage accounting\n(section 1) apply, attributed to the Anthropic or Vertex account that actually\nserved it, not to a Codex account. There is no separate \"fallback\" ledger; look\nat the served-by account's own usage.\n\nThe Codex route's final record names what served the turn: provider,\nmodel, account and accountType are the Claude target's, and\nrequestedModel stays the Codex model the client asked for. With the Anthropic\ntarget, the loopback's own /v1/messages record owns the usage, and the Codex\nrecord points to it through usageOwnerRequestId, so the call is counted once.\nWith Vertex there is no child record, so the Codex record carries the usage and\nis priced from the Vertex table.\n\nThe translated request marks its stable prefix with a 1-hour cache TTL. 1-hour\nwrites (usage.cache_creation.ephemeral_1h_input_tokens) are recorded as\ncacheCreation1hTokens, a subset of the cache-write total, and priced at 2x\nbase input, Anthropic's 1-hour rate on every Claude model. The rest of the\ncache writes keep the 5-minute rate (1.25x).\n\nThe token/cost metrics carry an origin attribute (ProxyRequestOrigin:\n\"native\" | \"codex-fallback\"), but only when it is not \"native\" — a\nplain Codex or Claude request emits the exact same label set it always has,\nwith no origin key at all, so existing dashboards and alerts over these\nmetrics are unaffected. Only a request actually served by this outbound-fallback\npath carries origin=\"codex-fallback\", set via\ntracer.setRequestOrigin(\"codex-fallback\") once a target has been dispatched\nand will serve the turn (both the Anthropic-loopback and Vertex targets); a\nrequest whose every target fails keeps \"native\".","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.5 Accounting","lvl3":""}},
|
|
@@ -7640,7 +7640,7 @@
|
|
|
7640
7640
|
{"objectID":"ad29fcad00b9d73eacff3f9ca6c0adb18b19c60ff1e6f3aa93b80e38865394a9","title":"createServer(neurolink, options?)","url":"/docs/guides/server-adapters/api-reference#createserverneurolink-options","content":"Convenience function that creates a server adapter from a NeuroLink instance.","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"createServer(neurolink, options?)","lvl3":""}},
|
|
7641
7641
|
{"objectID":"8cc46647ccb6a0e9d912da7efa7b1827b1c6e4ef762dbb5b88baa676d6841a8a","title":"ServerAdapterFactory","url":"/docs/guides/server-adapters/api-reference#serveradapterfactory","content":"Static factory class for creating adapters. Supports dynamic imports so unused frameworks are never bundled.\n\n| Method | Signature | Description |\n| ------------------------- | ---------------------------------------------------------------------- | --------------------------------- |\n| create | (options: ServerAdapterFactoryOptions) => Promise<BaseServerAdapter> | Create adapter by framework name |\n| createHono | (neurolink, config?) => Promise<BaseServerAdapter> | Shortcut for Hono |\n| createExpress | (neurolink, config?) => Promise<BaseServerAdapter> | Shortcut for Express |\n| createFastify | (neurolink, config?) => Promise<BaseServerAdapter> | Shortcut for Fastify |\n| createKoa | (neurolink, config?) => Promise<BaseServerAdapter> | Shortcut for Koa |\n| registerAdapter | (framework, adapterClass) => void | Register a custom adapter class |\n| isSupported | (framework: string) => boolean | Check if a framework is supported |\n| getSupportedFrameworks | () => Array<{framework, status, description}> | List all supported frameworks |\n| getRecommendedFramework | () => ServerFramework | Returns \"hono\" |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ServerAdapterFactory","lvl3":""}},
|
|
7642
7642
|
{"objectID":"84823b5000a24fb8b2d82aead2e94a037d9bdea5be7ed0587f8feb198974d1c7","title":"BaseServerAdapter","url":"/docs/guides/server-adapters/api-reference#baseserveradapter","content":"Abstract base class that all framework adapters extend. Extends EventEmitter.\n\n| Method | Signature | Description |\n| -------------------------- | -------------------------------------------- | --------------------------------------------- |\n| initialize | () => Promise<void> | Initialize routes, middleware, framework |\n| start | () => Promise<void> | Start listening (abstract) |\n| stop | () => Promise<void> | Stop server with graceful shutdown (abstract) |\n| registerRoute | (route: RouteDefinition) => void | Register a single route |\n| registerRouteGroup | (group: RouteGroup) => void | Register a route group with prefix |\n| registerMiddleware | (middleware: MiddlewareDefinition) => void | Register middleware |\n| getStatus | () => ServerStatus | Get running status, uptime, route count |\n| listRoutes | () => RouteDefinition[] | List all registered routes |\n| getConfig | () => RequiredServerAdapterConfig | Get resolved configuration |\n| getLifecycleState | () => ServerLifecycleState | Get current lifecycle state |\n| getActiveConnectionCount | () => number | Number of active connections |\n| getFrameworkInstance | () => unknown | Get underlying framework instance (abstract) |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"BaseServerAdapter","lvl3":""}},
|
|
7643
|
-
{"objectID":"8147853e8b9b9e7fc31c0480161f56665f741cd53ccbeb50aeed5c67242ed3b3","title":"ServerAdapterConfig","url":"/docs/guides/server-adapters/api-reference#serveradapterconfig","content":"All fields are optional; defaults are applied by the base class.\n\n| Field | Type | Default | Description |\n| ---------------------- | ------------------ | ------------------------ | --------------------------------- |\n| port | number | 3000 | Server port |\n| host | string | \"0.0.0.0\" | Server host |\n| basePath | string | \"/api\" | Base path for all routes |\n| cors | CORSConfig | enabled, origins [\"*\"] | CORS settings |\n| rateLimit | RateLimitConfig | enabled, 100 req/15 min | Rate limiting |\n| bodyParser | BodyParserConfig | enabled, 10 MB limit | Body parsing |\n| logging | LoggingConfig | enabled, level \"info\" | Request logging |\n| timeout | number | 30000 | Request timeout (ms) |\n| enableMetrics | boolean | true | Expose /api/metrics |\n| enableSwagger | boolean | false | Enable OpenAPI docs |\n| disableBuiltInHealth | boolean | false | Skip built-in /health, /ready |\n| redaction | RedactionConfig | disabled | Stream redaction settings |\n| shutdown | ShutdownConfig | 30s shutdown, 15s drain | Graceful shutdown behavior |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ServerAdapterConfig","lvl3":""}},
|
|
7643
|
+
{"objectID":"8147853e8b9b9e7fc31c0480161f56665f741cd53ccbeb50aeed5c67242ed3b3","title":"ServerAdapterConfig","url":"/docs/guides/server-adapters/api-reference#serveradapterconfig","content":"All fields are optional; defaults are applied by the base class.\n\n| Field | Type | Default | Description |\n| ---------------------- | ------------------ | ------------------------ | --------------------------------- |\n| port | number | 3000 | Server port |\n| host | string | \"0.0.0.0\" | Server host |\n| basePath | string | \"/api\" | Base path for all routes |\n| cors | CORSConfig | enabled, origins [\"*\"] | CORS settings |\n| rateLimit | RateLimitConfig | enabled, 100 req/15 min | Rate limiting |\n| bodyParser | BodyParserConfig | enabled, 10 MB limit | Body parsing |\n| logging | LoggingConfig | enabled, level \"info\" | Request logging |\n| timeout | number | 30000 | Request timeout (ms) |\n| enableMetrics | boolean | true | Expose /api/metrics |\n| enableSwagger | boolean | false | Enable OpenAPI docs |\n| disableBuiltInHealth | boolean | false | Skip built-in /health, /ready |\n| redaction | RedactionConfig | disabled | Stream redaction settings |\n| shutdown | ShutdownConfig | 30s shutdown, 15s drain | Graceful shutdown behavior |\n| carryMiddlewareState | boolean | false | Carry middleware state (opt-in) |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ServerAdapterConfig","lvl3":""}},
|
|
7644
7644
|
{"objectID":"b9b51bfed21ee76f61c6b63bb94df2c91a354520e27a7b4bd1a18092fd42fe93","title":"ShutdownConfig","url":"/docs/guides/server-adapters/api-reference#shutdownconfig","content":"| Field | Type | Default | Description |\n| --------------------------- | --------- | ------- | ----------------------------- |\n| gracefulShutdownTimeoutMs | number | 30000 | Max time for entire shutdown |\n| drainTimeoutMs | number | 15000 | Max time to drain connections |\n| forceClose | boolean | true | Force-close after timeout |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ShutdownConfig","lvl3":""}},
|
|
7645
7645
|
{"objectID":"20dfcebcadaaeeffe2c27254dd2d227fabc2307718987ac56dba6ec74ce8deaa","title":"Server Lifecycle States","url":"/docs/guides/server-adapters/api-reference#server-lifecycle-states","content":"\"uninitialized\" | \"initializing\" | \"initialized\" | \"starting\" | \"running\" | \"draining\" | \"stopping\" | \"stopped\" | \"error\"","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Server Lifecycle States","lvl3":""}},
|
|
7646
7646
|
{"objectID":"b4f54c24b5274a577a9050cb268ff0e8254297ba5f2c865ca5343f9b8d9b2ca9","title":"Events (ServerAdapterEvents)","url":"/docs/guides/server-adapters/api-reference#events-serveradapterevents","content":"| Event | Payload |\n| ------------- | ------------------------------------------------ |\n| initialized | { config, routeCount, middlewareCount } |\n| started | { port, host, timestamp } |\n| stopped | { uptime, timestamp } |\n| request | { requestId, method, path, timestamp } |\n| response | { requestId, statusCode, duration, timestamp } |\n| error | { requestId?, error, timestamp } |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Events (ServerAdapterEvents)","lvl3":""}},
|
|
@@ -7719,7 +7719,7 @@
|
|
|
7719
7719
|
{"objectID":"1aba31d0169a6255c13c0834ddf34f5e433ad08bd11d3f4f8d77e52d2aac5178","title":"Route and Middleware Types","url":"/docs/guides/server-adapters/api-reference#route-and-middleware-types","content":"| Type | Description |\n| ---------------------- | ----------------------------------------------------------------------------------- |\n| HttpMethod | \"GET\" \\| \"POST\" \\| \"PUT\" \\| \"DELETE\" \\| \"PATCH\" \\| \"OPTIONS\" |\n| RouteDefinition | Full route definition |\n| RouteGroup | Group of routes with prefix and optional middleware |\n| RouteHandler<T> | (ctx: ServerContext) => Promise<T \\| ServerResponse<T> \\| AsyncIterable<unknown>> |\n| MiddlewareDefinition | Middleware definition with name, order, handler, paths |\n| MiddlewareHandler | (ctx, next) => Promise<unknown> |\n| CreateRoutesOptions | Options for createAllRoutes |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Route and Middleware Types","lvl3":""}},
|
|
7720
7720
|
{"objectID":"a4daff1325a8b89a05cc217c671de5a359fdcd820d52991fdedf7265940eb257","title":"Factory Types","url":"/docs/guides/server-adapters/api-reference#factory-types","content":"| Type | Description |\n| ----------------------------- | ------------------------------------------- |\n| ServerFramework | \"hono\" \\| \"express\" \\| \"fastify\" \\| \"koa\" |\n| ServerAdapterFactoryOptions | { framework, neurolink, config? } |\n| ServerStatus | Server status snapshot |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Factory Types","lvl3":""}},
|
|
7721
7721
|
{"objectID":"4f2b202faec0c6c8bdbf6913438e0809776d019ac03be6082db1cd3a6cc9cc20","title":"Streaming Types","url":"/docs/guides/server-adapters/api-reference#streaming-types","content":"| Type | Description |\n| ---------------------------------------------------- | --------------------------------- |\n| DataStreamWriter | Writer interface for data streams |\n| DataStreamEventType | Event type union |\n| DataStreamEvent | Base event |\n| TextStartEvent / TextDeltaEvent / TextEndEvent | Text streaming events |\n| ToolCallEvent / ToolResultEvent | Tool events |\n| DataEvent / ErrorEvent / FinishEvent | Utility events |\n| DataStreamWriterConfig | Writer factory config |\n| DataStreamResponseConfig | Response factory config |\n| SSEEventOptions | SSE formatting options |\n| SSEWriteOptions | SSE write options |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Streaming Types","lvl3":""}},
|
|
7722
|
-
{"objectID":"f3b123615ba16d79e4f558be441599b7fa3adb19657e4f75e3035e79ba7c936a","title":"WebSocket Types","url":"/docs/guides/server-adapters/api-reference#websocket-types","content":"| Type | Description |\n| ---------------------- | --------------------------------------------------------------------- |\n| WebSocketConfig | WebSocket server settings |\n| WebSocketConnection | Connection object |\n| WebSocketHandler | Event handler interface (onOpen, onMessage, onClose, onError) |\n| WebSocketMessage | Message object |\n| WebSocketMessageType | \"text\" \\| \"binary\" \\| \"ping\" \\| \"pong\" \\| \"close\" |\n| WebSocketAuthConfig | Auth config for WebSocket (same shape as AuthConfig from types) |\n| AuthenticatedUser | User object
|
|
7722
|
+
{"objectID":"f3b123615ba16d79e4f558be441599b7fa3adb19657e4f75e3035e79ba7c936a","title":"WebSocket Types","url":"/docs/guides/server-adapters/api-reference#websocket-types","content":"| Type | Description |\n| ---------------------- | --------------------------------------------------------------------- |\n| WebSocketConfig | WebSocket server settings |\n| WebSocketConnection | Connection object |\n| WebSocketHandler | Event handler interface (onOpen, onMessage, onClose, onError) |\n| WebSocketMessage | Message object |\n| WebSocketMessageType | \"text\" \\| \"binary\" \\| \"ping\" \\| \"pong\" \\| \"close\" |\n| WebSocketAuthConfig | Auth config for WebSocket (same shape as AuthConfig from types) |\n| AuthenticatedUser | User object: id, shared, email, name, roles, permissions, metadata |\n| AuthStrategy | \"bearer\" \\| \"apiKey\" \\| \"basic\" \\| \"custom\" \\| \"none\" |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"WebSocket Types","lvl3":""}},
|
|
7723
7723
|
{"objectID":"75ac5dd684dae3c078a954801e7d8c39e4a7ab6eefb4c4e13140af491da67cd3","title":"Error Types","url":"/docs/guides/server-adapters/api-reference#error-types","content":"| Type | Description |\n| ---------------------------- | ------------------------------------- |\n| ErrorCategoryType | Error category union |\n| ErrorSeverityType | Error severity union |\n| ServerAdapterErrorCodeType | Error code union |\n| ServerAdapterErrorContext | Context object for error construction |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Error Types","lvl3":""}},
|
|
7724
7724
|
{"objectID":"9930ededc5ccfc16a496b95cde993bfd1fdff5dae26b819e6e6a7b11de933418","title":"ErrorCategory","url":"/docs/guides/server-adapters/api-reference#errorcategory","content":"ErrorCategory","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ErrorCategory","lvl3":""}},
|
|
7725
7725
|
{"objectID":"81be0bf7c25a87d9ade845c9461d764b1851de541c9182f00c87b86d6d98e4d2","title":"ErrorSeverity","url":"/docs/guides/server-adapters/api-reference#errorseverity","content":"ErrorSeverity","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ErrorSeverity","lvl3":""}},
|
|
@@ -7993,7 +7993,7 @@
|
|
|
7993
7993
|
{"objectID":"20b4b9bfe4f6987d7c88692d17430396985fe8533056d76bd16efcc0af7c8e74","title":"Custom Rate Limit Store (Redis)","url":"/docs/guides/server-adapters/middleware#custom-rate-limit-store-redis","content":"Custom Rate Limit Store (Redis)","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Custom Rate Limit Store (Redis)","lvl3":""}},
|
|
7994
7994
|
{"objectID":"7826f375db586c8004183275c0715b410e96f673701874419ba565b6ff3dd214","title":"When to Use","url":"/docs/guides/server-adapters/middleware#when-to-use-9","content":"API abuse prevention\nFair usage enforcement\nCost control for expensive operations\nProtection against DDoS attacks","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"When to Use","lvl3":""}},
|
|
7995
7995
|
{"objectID":"ce6af8a97b716420a9742ad3d965d5cb0aa5912e3d52d961814c83e9e1abaa19","title":"Authentication Middleware","url":"/docs/guides/server-adapters/middleware#authentication-middleware","content":"Provides flexible authentication support with multiple strategies.","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Authentication Middleware","lvl3":""}},
|
|
7996
|
-
{"objectID":"39ede52482e2c4efd166bd94c8fa1ea4a6957b2528e2bca5c058208e4f293b81","title":"Configuration","url":"/docs/guides/server-adapters/middleware#configuration-8","content":"
|
|
7996
|
+
{"objectID":"39ede52482e2c4efd166bd94c8fa1ea4a6957b2528e2bca5c058208e4f293b81","title":"Configuration","url":"/docs/guides/server-adapters/middleware#configuration-8","content":"The authenticated user is set on ctx.user. On the built-in adapters (Hono,\nExpress, Fastify and Koa) it reaches later middleware and the route handler on\nevery request only when the server is created with carryMiddlewareState: true.\nBy default Express, Fastify and Koa, and Hono when the client sent no\nX-Request-ID of its own, hand each middleware step and the handler a fresh\ncontext, so a role guard registered after authentication refuses everyone there;\nonly Hono with a client X-Request-ID shares the context. The option does not\napply to a context you build yourself: a custom adapter, or a route handler you\ncall directly, can supply a context that already has ctx.user set. See\nCarrying middleware state\nin the security guide. Whether the agent routes treat ctx.user as the caller is\na separate choice: see perUserAuth in the\nsecurity guide.","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Configuration","lvl3":""}},
|
|
7997
7997
|
{"objectID":"51fb1cc8c6e28634044df5ad09ea7250e2d1520cade26f2996bf81c174b30aa9","title":"Usage","url":"/docs/guides/server-adapters/middleware#usage-10","content":"Usage","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Usage","lvl3":""}},
|
|
7998
7998
|
{"objectID":"dc019f0ad08d89054d4f68945d6855bbc6d74da0b3f8082e35f56fa5f731ec51","title":"Headers Read","url":"/docs/guides/server-adapters/middleware#headers-read","content":"| Header | Auth Type | Description |\n| --------------- | ------------- | ------------------------------------ |\n| Authorization | bearer, basic | Bearer <token> or Basic <base64> |\n| X-API-Key | api-key | Raw API key value |","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Headers Read","lvl3":""}},
|
|
7999
7999
|
{"objectID":"43776c9da774387f221eb7918931d5a4a59b42c949ef248c30c7afb5512ee7ea","title":"Dev Playground Support","url":"/docs/guides/server-adapters/middleware#dev-playground-support","content":"Requests with an X-NeuroLink-Dev-Playground: true (or X-NeuroLink-Playground: true) header bypass authentication and receive a default developer user context (id: \"playground\", roles: [\"developer\"]), but only when NODE_ENV is exactly development. The variable is read on every request.\n\nWith NODE_ENV unset, production, test, staging or any other value, the header is ignored and the request must carry a valid credential. The bypass is therefore off by default in a deployment that never sets NODE_ENV. Pass skipDevPlayground: false to refuse the header even in development.","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Dev Playground Support","lvl3":""}},
|
|
@@ -8011,13 +8011,15 @@
|
|
|
8011
8011
|
{"objectID":"75f9986be54ffb5b39930d9b1514e6a696e982fe41bbc2a600033e3254bad57b","title":"When to Use","url":"/docs/guides/server-adapters/middleware#when-to-use-12","content":"Expensive operations (database queries, AI generation)\nFrequently requested static data\nRate limit budget optimization\nReducing latency for repeated requests","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"When to Use","lvl3":""}},
|
|
8012
8012
|
{"objectID":"3e522465420d38d5c0e20166dfc374452a7c8366d592ff2cf3a9cb9afadc3b7d","title":"Composing Middleware","url":"/docs/guides/server-adapters/middleware#composing-middleware","content":"Middleware are executed in order based on their order property. Here's a recommended production setup:","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Composing Middleware","lvl3":""}},
|
|
8013
8013
|
{"objectID":"293ec2d6d2933e2f370ee73b87ee9684f64143acd21d8bbb5e7e48640ec0d2bb","title":"Next Steps","url":"/docs/guides/server-adapters/middleware#next-steps","content":"Configuration Reference - Full server configuration options\nSecurity Best Practices - Authentication and authorization patterns\nDeployment Guide - Production deployment strategies\nExpress Adapter - Express-specific middleware integration\nFastify Adapter - Fastify-specific hooks and plugins","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Next Steps","lvl3":""}},
|
|
8014
|
-
{"objectID":"3f8ed2c1cc0b9c59fe231fb08fe10302270284784b912664350299fe0a5de458","title":"Security Best Practices","url":"/docs/guides/server-adapters/security","content":"Security Best Practices\n\nProtect your AI APIs with comprehensive security measures\n\nThis guide covers authentication, authorization, rate limiting, and other security best practices for deploying NeuroLink server adapters in production.\n\nAuthentication\n\nNeuroLink server adapters support multiple authentication strategies out of the box.\n\nBearer Token Authentication\n\nBearer tokens (JWT, OAuth tokens) are the most common authentication method for APIs:\n\nAPI Key Authentication\n\nFor service-to-service communication or simple API access:\n\nBasic Authentication\n\nFor simple username/password authentication:\n\nCustom Authentication\n\nFor OAuth 2.0, OIDC, or custom schemes:\n\
|
|
8014
|
+
{"objectID":"3f8ed2c1cc0b9c59fe231fb08fe10302270284784b912664350299fe0a5de458","title":"Security Best Practices","url":"/docs/guides/server-adapters/security","content":"Security Best Practices\n\nProtect your AI APIs with comprehensive security measures\n\nThis guide covers authentication, authorization, rate limiting, and other security best practices for deploying NeuroLink server adapters in production.\n\nAuthentication\n\nNeuroLink server adapters support multiple authentication strategies out of the box.\n\nBearer Token Authentication\n\nBearer tokens (JWT, OAuth tokens) are the most common authentication method for APIs:\n\nAPI Key Authentication\n\nFor service-to-service communication or simple API access:\n\nBasic Authentication\n\nFor simple username/password authentication:\n\nCustom Authentication\n\nFor OAuth 2.0, OIDC, or custom schemes:\n\nCarrying middleware state to guards and handlers (carryMiddlewareState)\n\nAuthentication middleware sets ctx.user. On the built-in adapters, whether the\nmiddleware that runs after it, and the route handler, see it depends on the\nadapter and on carryMiddlewareState, which is off by default: each adapter\nthen propagates context as it always did. Express, Fastify and Koa build a fresh\ncontext for every middleware step and for the handler and carry only the\nresponse headers; Hono shares one context between the steps and the handler only\nwhen the client sent its own X-Request-ID.\n\nThe option does not apply to a context you build yourself: a custom adapter, or a\nroute handler you call directly, can supply a context that already has ctx.user\nset.\n\nSo by default a role guard (createRoleMiddleware) registered after\ncreateAuthMiddleware sees the user on one request shape only. Measured: it\nanswers 401 to every request on Express, Fastify and Koa, and on Hono without a\nclient X-Request-ID, even for a user holding the required role, and a\nrate-limit keyGenerator reads ctx.user as undefined there. Set the option on\nthe server to carry ctx.user, ctx.session, ctx.metadata and the abort\nsignal to later middleware and the handler on every built-in adapter:\n\nWith it on, the role guard admits a user holding the role (200) and refuses one\nwithout it (403), and a keyGenerator sees ctx.user, on every built-in adapter. A key\ngenerator that keys on the user id then does what it says, so make it ignore a\nshared identity (ctx.user.shared), or every holder of one API key falls into a\nsingle bucket; the rate-limit examples below do. Turning the option on does not\nchange whose identity the agent routes trust, and registerAllRoutes turns it\non by itself when given perUserAuth, as the next section says.\n\nWho the agent routes treat as the user (perUserAuth)\n\nWhether the agent routes (/agent/execute, /agent/stream, and the skill\nmutation routes' requestedBy) trust ctx.user as a person is a separate\nchoice from whether the server carries it: a single shared API key sets the same\nctx.user for every caller, and taking it as the user would give every client\none userId and no conversation memory.\n\nSo without an opt-in the agent routes resolve identity as they always have:\nOn Express, Fastify and Koa, and on Hono when the client sent no\n X-Request-ID, userId and sessionId come from the request body.\n ctx.user and ctx.session are ignored (they are not in the handler's\n context at all unless the server carries middleware state), and the skill\n routes use the body's requestedBy.\nOn Hono, when the client sent its own X-Request-ID header, an authenticated\n ctx.user wins over the body (and ctx.session over the body's\n sessionId), as it did before. Hono kept the middleware's context under that\n header, so the handler found it. That is the only built-in combination where\n the default ever guarded userId.\nA context the built-in adapters did not hand the carry to keeps the same\n rule, an authenticated ctx.user wins: an adapter you wrote that sets\n ctx.user itself, or a route handler you call directly with a context you\n built (a test harness, for one).\n\nSet perUserAuth: true when your middleware identifies individual people (one\ncredential per person). Only this option, with carryMiddlewareState on, makes the agent routes take\nthe user from ctx.user, and ignore the body's userId, on every built-in\nadapter and for every request:\n\nregisterAllRoutes also turns on carryMiddlewareState for the server, because\nthe routes can only take identity from ctx.user if the adapter hands it to the\nhandler. With carryMiddlewareState on, a perUserAuth request that your middleware\nauthenticated reaches the handler with that user on every built-in adapter. A\nrequest that no middleware authenticated (optional authentication) runs as\nanonymous, with no userId and no session.\n\nIf you register the agent routes yourself with\ncreateAgentRoutes(\"/api\", { perUserAuth: true }), create the server with\ncarryMiddlewareState: true. Without it, whether a perUserAuth request has a\nuser depends on the adapter and the request:\nHono, when the client sent its own X-Request-ID header: an authenticated\n request has its user and session. Hono hands the handler the middleware's context for such\n a request whether or not carryM","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"","lvl3":""}},
|
|
8015
8015
|
{"objectID":"7cdb3cd74c088f4b197de4db297c2eb3b47c353b41ce1a84ed2e12548147b408","title":"Security Best Practices","url":"/docs/guides/server-adapters/security#security-best-practices","content":"Protect your AI APIs with comprehensive security measures\n\nThis guide covers authentication, authorization, rate limiting, and other security best practices for deploying NeuroLink server adapters in production.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Security Best Practices","lvl3":""}},
|
|
8016
8016
|
{"objectID":"7165b0d19a27c31d8ca81ea15e5a79ad56fd20234c80f3c955a1c579a669e84f","title":"Authentication","url":"/docs/guides/server-adapters/security#authentication","content":"NeuroLink server adapters support multiple authentication strategies out of the box.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Authentication","lvl3":""}},
|
|
8017
8017
|
{"objectID":"9b83e309c15f0ef505257e6ef1750da7d26183f6b598bcd24996ad199df910cc","title":"Bearer Token Authentication","url":"/docs/guides/server-adapters/security#bearer-token-authentication","content":"Bearer tokens (JWT, OAuth tokens) are the most common authentication method for APIs:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Bearer Token Authentication","lvl3":""}},
|
|
8018
8018
|
{"objectID":"9447de8730cba3e8d7100e35f3edc53f5d838fed4aab12473ba0d154a63ee127","title":"API Key Authentication","url":"/docs/guides/server-adapters/security#api-key-authentication","content":"For service-to-service communication or simple API access:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"API Key Authentication","lvl3":""}},
|
|
8019
8019
|
{"objectID":"55486c9aed152083800f7142accdefaf2750be560161e53b51e4e7f076e78783","title":"Basic Authentication","url":"/docs/guides/server-adapters/security#basic-authentication","content":"For simple username/password authentication:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Basic Authentication","lvl3":""}},
|
|
8020
8020
|
{"objectID":"3975b5affef7749530f0c88db91dccfe9ae500ea616d9ae756de09c501e74e09","title":"Custom Authentication","url":"/docs/guides/server-adapters/security#custom-authentication","content":"For OAuth 2.0, OIDC, or custom schemes:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Custom Authentication","lvl3":""}},
|
|
8021
|
+
{"objectID":"6c5ba88d8c7484db5bcd476fabfca5763fad609f689edee826a37f9360219610","title":"Carrying middleware state to guards and handlers (carryMiddlewareState)","url":"/docs/guides/server-adapters/security#carrying-middleware-state-to-guards-and-handlers-carrymiddlewarestate","content":"Authentication middleware sets ctx.user. On the built-in adapters, whether the\nmiddleware that runs after it, and the route handler, see it depends on the\nadapter and on carryMiddlewareState, which is off by default: each adapter\nthen propagates context as it always did. Express, Fastify and Koa build a fresh\ncontext for every middleware step and for the handler and carry only the\nresponse headers; Hono shares one context between the steps and the handler only\nwhen the client sent its own X-Request-ID.\n\nThe option does not apply to a context you build yourself: a custom adapter, or a\nroute handler you call directly, can supply a context that already has ctx.user\nset.\n\nSo by default a role guard (createRoleMiddleware) registered after\ncreateAuthMiddleware sees the user on one request shape only. Measured: it\nanswers 401 to every request on Express, Fastify and Koa, and on Hono without a\nclient X-Request-ID, even for a user holding the required role, and a\nrate-limit keyGenerator reads ctx.user as undefined there. Set the option on\nthe server to carry ctx.user, ctx.session, ctx.metadata and the abort\nsignal to later middleware and the handler on every built-in adapter:\n\nWith it on, the role guard admits a user holding the role (200) and refuses one\nwithout it (403), and a keyGenerator sees ctx.user, on every built-in adapter. A key\ngenerator that keys on the user id then does what it says, so make it ignore a\nshared identity (ctx.user.shared), or every holder of one API key falls into a\nsingle bucket; the rate-limit examples below do. Turning the option on does not\nchange whose identity the agent routes trust, and registerAllRoutes turns it\non by itself when given perUserAuth, as the next section says.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Carrying middleware state to guards and handlers (carryMiddlewareState)","lvl3":""}},
|
|
8022
|
+
{"objectID":"f4407e53fe643ff19343687ebdafae3eaf56adc6a7cafc61834a490cc90bffd1","title":"Who the agent routes treat as the user (perUserAuth)","url":"/docs/guides/server-adapters/security#who-the-agent-routes-treat-as-the-user-peruserauth","content":"Whether the agent routes (/agent/execute, /agent/stream, and the skill\nmutation routes' requestedBy) trust ctx.user as a person is a separate\nchoice from whether the server carries it: a single shared API key sets the same\nctx.user for every caller, and taking it as the user would give every client\none userId and no conversation memory.\n\nSo without an opt-in the agent routes resolve identity as they always have:\nOn Express, Fastify and Koa, and on Hono when the client sent no\n X-Request-ID, userId and sessionId come from the request body.\n ctx.user and ctx.session are ignored (they are not in the handler's\n context at all unless the server carries middleware state), and the skill\n routes use the body's requestedBy.\nOn Hono, when the client sent its own X-Request-ID header, an authenticated\n ctx.user wins over the body (and ctx.session over the body's\n sessionId), as it did before. Hono kept the middleware's context under that\n header, so the handler found it. That is the only built-in combination where\n the default ever guarded userId.\nA context the built-in adapters did not hand the carry to keeps the same\n rule, an authenticated ctx.user wins: an adapter you wrote that sets\n ctx.user itself, or a route handler you call directly with a context you\n built (a test harness, for one).\n\nSet perUserAuth: true when your middleware identifies individual people (one\ncredential per person). Only this option, with carryMiddlewareState on, makes the agent routes take\nthe user from ctx.user, and ignore the body's userId, on every built-in\nadapter and for every request:\n\nregisterAllRoutes also turns on carryMiddlewareState for the server, because\nthe routes can only take identity from ctx.user if the adapter hands it to the\nhandler. With carryMiddlewareState on, a perUserAuth request that your middleware\nauthenticated reaches the handler with that user on every built-in adapter.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Who the agent routes treat as the user (perUserAuth)","lvl3":""}},
|
|
8021
8023
|
{"objectID":"0eb6912fafa8a4ab0aa683215da36521df010f267a7e6fa07e5b36117285fbd7","title":"Skip Paths Configuration","url":"/docs/guides/server-adapters/security#skip-paths-configuration","content":"Certain endpoints should bypass authentication:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Skip Paths Configuration","lvl3":""}},
|
|
8022
8024
|
{"objectID":"9e51a77be4d03e43ee3f36b8d0011c07bc65e43fe63401529fc309117cc8f14d","title":"Rate Limiting","url":"/docs/guides/server-adapters/security#rate-limiting","content":"Protect your API from abuse with configurable rate limiting.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Rate Limiting","lvl3":""}},
|
|
8023
8025
|
{"objectID":"c6e767ba1ce5b5628ab9d303d199a6fb4947a70e2e43358a5d7f89a96534c74e","title":"Basic Configuration","url":"/docs/guides/server-adapters/security#basic-configuration","content":"Basic Configuration","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Basic Configuration","lvl3":""}},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "13.8.
|
|
4
|
-
"packageManager": "pnpm@10.
|
|
3
|
+
"version": "13.8.15",
|
|
4
|
+
"packageManager": "pnpm@10.28.2",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Juspay Technologies",
|
|
@@ -214,6 +214,7 @@
|
|
|
214
214
|
"test:server-boundaries": "pnpm exec tsx test/continuous-test-suite-server-boundaries.ts",
|
|
215
215
|
"test:agent-input-guard": "pnpm exec tsx test/continuous-test-suite-agent-input-guard.ts",
|
|
216
216
|
"test:body-limits": "pnpm exec tsx test/continuous-test-suite-body-limits.ts",
|
|
217
|
+
"test:adapter-request-context": "pnpm exec tsx test/continuous-test-suite-adapter-request-context.ts",
|
|
217
218
|
"test:websocket-agent-handler": "pnpm exec tsx test/continuous-test-suite-websocket-agent-handler.ts",
|
|
218
219
|
"test:tool-reliability": "pnpm exec tsx test/continuous-test-suite-tool-reliability.ts",
|
|
219
220
|
"test:video-abort": "pnpm exec tsx test/continuous-test-suite-video-abort.ts",
|
|
@@ -242,6 +243,7 @@
|
|
|
242
243
|
"test:proxy-telemetry": "pnpm exec tsx test/continuous-test-suite-proxy-telemetry.ts",
|
|
243
244
|
"test:proxy-restart": "pnpm exec tsx test/continuous-test-suite-proxy-restart.ts",
|
|
244
245
|
"test:proxy-image-input": "pnpm exec tsx test/continuous-test-suite-proxy-image-input.ts",
|
|
246
|
+
"test:proxy-codex-policy-refusal": "pnpm exec tsx test/continuous-test-suite-proxy-codex-policy-refusal.ts",
|
|
245
247
|
"test:codex": "pnpm exec tsx test/continuous-test-suite-codex.ts",
|
|
246
248
|
"test:bugfixes": "pnpm exec tsx test/continuous-test-suite-bugfixes.ts",
|
|
247
249
|
"test:json-e2e": "pnpm exec tsx test/continuous-test-suite-json-e2e.ts",
|