@schlessera/brain-ui-server 0.33.0 → 0.34.0
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 +12 -0
- package/dist/agent/backend.d.ts +17 -219
- package/dist/agent/backend.d.ts.map +1 -1
- package/dist/agent/backend.js +212 -471
- package/dist/agent/backend.js.map +1 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +2 -1
- package/dist/app.js.map +1 -1
- package/dist/bin/brain-ui-cron.d.ts +1 -1
- package/dist/bin/brain-ui-cron.d.ts.map +1 -1
- package/dist/bin/brain-ui-cron.js +24 -7
- package/dist/bin/brain-ui-cron.js.map +1 -1
- package/dist/brain/client.js +2 -2
- package/dist/brain/client.js.map +1 -1
- package/dist/config/env.d.ts +18 -15
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +33 -13
- package/dist/config/env.js.map +1 -1
- package/dist/cron/emit.d.ts +5 -3
- package/dist/cron/emit.d.ts.map +1 -1
- package/dist/cron/emit.js +31 -12
- package/dist/cron/emit.js.map +1 -1
- package/dist/middleware/origin.d.ts.map +1 -1
- package/dist/middleware/origin.js +22 -1
- package/dist/middleware/origin.js.map +1 -1
- package/dist/routes/brain.js +2 -2
- package/dist/routes/brain.js.map +1 -1
- package/dist/routes/pi-auth.d.ts.map +1 -1
- package/dist/routes/pi-auth.js +14 -6
- package/dist/routes/pi-auth.js.map +1 -1
- package/dist/routes/web-search.d.ts.map +1 -1
- package/dist/routes/web-search.js +12 -8
- package/dist/routes/web-search.js.map +1 -1
- package/package.json +3 -3
- package/src/agent/backend.ts +281 -793
- package/src/app.ts +2 -1
- package/src/bin/brain-ui-cron.ts +32 -6
- package/src/brain/client.ts +2 -2
- package/src/config/env.ts +69 -17
- package/src/cron/emit.ts +42 -10
- package/src/middleware/origin.ts +21 -1
- package/src/routes/brain.ts +2 -2
- package/src/routes/pi-auth.ts +13 -8
- package/src/routes/web-search.ts +12 -10
package/README.md
CHANGED
|
@@ -156,6 +156,17 @@ brain repository.
|
|
|
156
156
|
server-side hidden set (`PUT /api/models/hidden`) and a manual
|
|
157
157
|
`POST /api/models/refresh`. `/api/providers` serves the same roster minus the
|
|
158
158
|
hidden entries; hidden profiles still resolve for sessions pinned to them.
|
|
159
|
+
- **Backend registry** — iterates `BackendModule` descriptors
|
|
160
|
+
(`@schlessera/brain-ui-sdk/server`) rather than knowing any backend by name.
|
|
161
|
+
Each backend owns its own profile parsing, billing rule, settings hooks and
|
|
162
|
+
optional model source. `AGENT_BACKEND` selects among the FIRST-PARTY ids only
|
|
163
|
+
(`claude`, `pi`) — it is not a package specifier, and there is no runtime
|
|
164
|
+
discovery. A third-party backend is imported and passed by value:
|
|
165
|
+
`createApp({ registry: createStaticBackendRegistry({ ... }) })`, which keeps
|
|
166
|
+
the descriptor's hooks and model source. See
|
|
167
|
+
[docs/extending/agent-backends.md](../../docs/extending/agent-backends.md).
|
|
168
|
+
A session whose stored `backend_id` names a backend this deployment does not
|
|
169
|
+
have fails explicitly instead of silently running on the default.
|
|
159
170
|
|
|
160
171
|
## Environment
|
|
161
172
|
|
|
@@ -185,6 +196,7 @@ Every variable this package reads, and what happens when it is unset.
|
|
|
185
196
|
| `BRAIN_UI_PRICING_DISCOVERY` | Remote model-pricing refresh (LiteLLM + OpenRouter catalogs); "0"/"off"/"false" disables, and runs then roll up with unknown effective cost. Defaults ON, except under a test runner (NODE_ENV=test) where it defaults OFF. | on (off under NODE_ENV=test) |
|
|
186
197
|
| `BRAIN_UI_PRICING_TTL_HOURS` | How long a fetched model-pricing table stays fresh, in hours. | 24 |
|
|
187
198
|
| `BRAIN_UI_SKILLS_GITHUB_TOKEN` | GitHub token used when installing skills from a private repository (Settings → Skills) — typically read-only Contents on the skill repos. Falls back to GITHUB_TOKEN. | $GITHUB_TOKEN |
|
|
199
|
+
| `BRAIN_UI_SUBPROCESS_ENV_EXTRA` | Comma-separated environment variable names to admit to every child audience when an operator integration needs a variable outside the shipped allowlist. Names are trimmed; malformed entries are ignored; the control variable itself is never forwarded. | (empty) |
|
|
188
200
|
| `BRAIN_UI_TURN_TIMEOUT_MS` | Hard per-turn timeout in ms; the host aborts a turn that runs past it. Raise for agent-heavy research work (e.g. 1800000 for 30 minutes). | 600000 (10 minutes) |
|
|
189
201
|
| `BRAIN_UI_WS_BURST` | Inbound WebSocket frames absorbable in one burst before the sustained rate applies. Opening the app legitimately fires several at once. | 60 |
|
|
190
202
|
| `BRAIN_UI_WS_MAX_CONNECTIONS` | Maximum number of WebSocket connections accepted by one server process. | 32 |
|
package/dist/agent/backend.d.ts
CHANGED
|
@@ -1,258 +1,56 @@
|
|
|
1
1
|
import type { Logger } from "@opentelemetry/api-logs";
|
|
2
|
-
import type { AgentConfig } from "../config/env.js";
|
|
3
2
|
import type { BillingMode, ProviderInfo } from "@schlessera/brain-ui-sdk";
|
|
4
|
-
import type { AgentBackend, BackendCapabilities } from "@schlessera/brain-ui-sdk/server";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* tests install fakes by constructing a registry, not by mutating a module.
|
|
10
|
-
*
|
|
11
|
-
* BOTH backend packages are optional peers loaded lazily (the same
|
|
12
|
-
* dynamic-import path): a deployment installs the one its AGENT_BACKEND
|
|
13
|
-
* names, and the other never has to be present — at runtime AND at
|
|
14
|
-
* type-check time (see the structural mirrors below).
|
|
15
|
-
*
|
|
16
|
-
* The old five hardcoded personal inference profiles are gone: the Claude
|
|
17
|
-
* backend ships the single "claude" default, and additional Anthropic-compatible
|
|
18
|
-
* endpoints are declared via the BRAIN_UI_CLAUDE_PROFILES env var (documented in
|
|
19
|
-
* .env.example) rather than in code.
|
|
20
|
-
*/
|
|
21
|
-
/**
|
|
22
|
-
* Mirror of the backends' `BackendLogFn` — the minimal log seam a backend
|
|
23
|
-
* accepts. A callback rather than a Logger so the backend packages carry no
|
|
24
|
-
* telemetry dependency; {@link toBackendLog} adapts the registry's Logger.
|
|
25
|
-
*/
|
|
26
|
-
export type BackendLogFn = (level: "debug" | "info" | "warn" | "error", message: string, attrs?: Record<string, string | number | boolean>) => void;
|
|
27
|
-
/** Mirror of the Claude package's `InferenceProfileInput` (declarative shape). */
|
|
28
|
-
export interface ClaudeProfileInput {
|
|
29
|
-
id: string;
|
|
30
|
-
label: string;
|
|
31
|
-
vendor?: string;
|
|
32
|
-
/** Model id. Undefined = the SDK/CLI default model. */
|
|
33
|
-
model?: string;
|
|
34
|
-
/** Anthropic-compatible endpoint. */
|
|
35
|
-
baseUrl?: string;
|
|
36
|
-
/** Name of the env var holding a bearer token. */
|
|
37
|
-
authTokenEnv?: string;
|
|
38
|
-
/** Name of the env var holding an x-api-key. */
|
|
39
|
-
apiKeyEnv?: string;
|
|
40
|
-
/** Remap the CLI's model-alias envs to `model`. Requires `model`. */
|
|
41
|
-
modelAliases?: boolean;
|
|
42
|
-
allowedTools?: string[];
|
|
43
|
-
/** Context window in tokens, when known. Presentation only. */
|
|
44
|
-
contextWindow?: number;
|
|
45
|
-
/** Where this profile came from. Presentation only. */
|
|
46
|
-
source?: "builtin" | "declared" | "discovered";
|
|
47
|
-
}
|
|
48
|
-
/** Reasoning levels pi accepts (mirror of pi-agent-core's `ThinkingLevel`). */
|
|
49
|
-
export declare const PI_THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
50
|
-
export type PiThinkingLevel = (typeof PI_THINKING_LEVELS)[number];
|
|
51
|
-
/** Mirror of the pi package's `PiProfile` (declarative shape). */
|
|
52
|
-
export interface PiProfileInput {
|
|
53
|
-
id: string;
|
|
54
|
-
label: string;
|
|
55
|
-
/** pi provider id, e.g. "openai-codex", "anthropic", "google". */
|
|
56
|
-
vendor: string;
|
|
57
|
-
/** pi model id within the vendor, e.g. "gpt-5.6-sol". */
|
|
58
|
-
model: string;
|
|
59
|
-
/** Reasoning level for new sessions; pi clamps to the model's capability. */
|
|
60
|
-
thinkingLevel?: PiThinkingLevel;
|
|
61
|
-
}
|
|
62
|
-
/** Mirror of the Claude package's resolved `InferenceProfile`. */
|
|
63
|
-
export interface ClaudeProfile {
|
|
64
|
-
id: string;
|
|
65
|
-
label: string;
|
|
66
|
-
vendor?: string;
|
|
67
|
-
model?: string;
|
|
68
|
-
allowedTools?: string[];
|
|
69
|
-
contextWindow?: number;
|
|
70
|
-
source?: "builtin" | "declared" | "discovered";
|
|
71
|
-
/** Env vars that must be present (non-empty) for this profile to be usable. */
|
|
72
|
-
requiredEnvKeys: string[];
|
|
73
|
-
/** Environment overrides merged over the host environment. */
|
|
74
|
-
buildEnv: () => Record<string, string>;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* The slice of the lazily-required Claude module this registry drives. The
|
|
78
|
-
* real module carries more (and looser-optional) options; assignability is
|
|
79
|
-
* asserted in tests/declaration-surface.test.ts.
|
|
80
|
-
*/
|
|
81
|
-
export interface ClaudeBackendModule {
|
|
82
|
-
createClaudeBackend: (options: {
|
|
83
|
-
brainPath: string;
|
|
84
|
-
claudeCodePath?: string;
|
|
85
|
-
profiles?: ClaudeProfile[] | (() => ClaudeProfile[]);
|
|
86
|
-
confirmBashPatterns?: readonly string[];
|
|
87
|
-
log?: BackendLogFn;
|
|
88
|
-
}) => AgentBackend;
|
|
89
|
-
createModelSource: (options: {
|
|
90
|
-
brainPath: string;
|
|
91
|
-
ttlMs?: number;
|
|
92
|
-
enabled?: boolean;
|
|
93
|
-
}) => ClaudeModelSource;
|
|
94
|
-
defineProfiles: (inputs: ClaudeProfileInput[]) => ClaudeProfile[];
|
|
95
|
-
}
|
|
96
|
-
/** Discovery source as the registry internals see it: the public slice + list(). */
|
|
97
|
-
export interface ClaudeModelSource extends ModelDiscoverySource {
|
|
98
|
-
list: () => ClaudeProfileInput[];
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Discovery freshness, as exposed on the public registry surface.
|
|
102
|
-
*
|
|
103
|
-
* `list()` is omitted on purpose — it returns Claude profile inputs, only the
|
|
104
|
-
* registry internals consume it (see {@link ClaudeModelSource}), and exposing
|
|
105
|
-
* it would put those types on every consumer's plate for no reader.
|
|
106
|
-
*/
|
|
107
|
-
export interface ModelDiscoveryState {
|
|
108
|
-
enabled: boolean;
|
|
109
|
-
/** When discovery last succeeded; null when it never has. */
|
|
110
|
-
refreshedAt: number | null;
|
|
111
|
-
/** The cached result is older than the TTL (or absent). */
|
|
112
|
-
stale: boolean;
|
|
113
|
-
/** Last discovery failure, if the current list is served despite one. */
|
|
114
|
-
error?: string;
|
|
115
|
-
}
|
|
116
|
-
/** The slice of the Claude backend's discovery source the routes consume. */
|
|
117
|
-
export interface ModelDiscoverySource {
|
|
118
|
-
state(): ModelDiscoveryState;
|
|
119
|
-
/** Refresh if stale. Awaits only when there is nothing cached to serve. */
|
|
120
|
-
ensureFresh(): Promise<void>;
|
|
121
|
-
/** Force a refresh regardless of TTL. Rejects on failure. */
|
|
122
|
-
refresh(): Promise<void>;
|
|
123
|
-
}
|
|
3
|
+
import type { AgentBackend, BackendCapabilities, BackendModelSource, BackendModelSourceState, BackendModule, ResolvedBackendModule } from "@schlessera/brain-ui-sdk/server";
|
|
4
|
+
import type { AgentConfig } from "../config/env.js";
|
|
5
|
+
export type { BackendLogFn } from "@schlessera/brain-ui-sdk/server";
|
|
6
|
+
export type ModelDiscoverySource = BackendModelSource;
|
|
7
|
+
export type ModelDiscoveryState = BackendModelSourceState;
|
|
124
8
|
export interface BackendRegistryOptions {
|
|
125
|
-
/** Where the brain repo lives (handed to every backend). */
|
|
126
9
|
brainPath: string;
|
|
127
|
-
/** Resolved agent configuration (AGENT_BACKEND, profiles, discovery...). */
|
|
128
10
|
agent: AgentConfig;
|
|
129
|
-
/**
|
|
130
|
-
* Profile ids the user keeps out of the model picker (from the app's
|
|
131
|
-
* settings table). Presentation only — a hidden profile still resolves for
|
|
132
|
-
* sessions pinned to it. Defaults to "nothing hidden".
|
|
133
|
-
*/
|
|
134
11
|
getHiddenModelIds?: () => string[];
|
|
135
|
-
/**
|
|
136
|
-
* Settings-stored default profile id (Settings → Models). Null/absent =
|
|
137
|
-
* auto (a connected subscription-auth profile, else the default backend's
|
|
138
|
-
* own default).
|
|
139
|
-
*/
|
|
140
12
|
getDefaultModelId?: () => string | null;
|
|
141
|
-
/**
|
|
142
|
-
* User-managed OpenRouter model ids (from the app's settings table), added
|
|
143
|
-
* to the Claude roster as declared OpenRouter profiles at runtime.
|
|
144
|
-
*/
|
|
145
13
|
getCustomOpenRouterModels?: () => string[];
|
|
146
|
-
|
|
147
|
-
* Per-profile reasoning-effort overrides (from the app's settings table),
|
|
148
|
-
* applied over the pi roster's configured levels at read time — no rebuild
|
|
149
|
-
* or redeploy needed.
|
|
150
|
-
*/
|
|
151
|
-
getThinkingOverrides?: () => Record<string, PiThinkingLevel>;
|
|
152
|
-
/**
|
|
153
|
-
* Per-profile billing-mode overrides (from the app's settings table).
|
|
154
|
-
* Consulted LAST: an override wins over both the declared-credential rule
|
|
155
|
-
* and the ambient predicate. Defaults to "no overrides".
|
|
156
|
-
*/
|
|
14
|
+
getThinkingOverrides?: () => Record<string, string>;
|
|
157
15
|
getBillingOverrides?: () => Record<string, BillingMode>;
|
|
158
|
-
/**
|
|
159
|
-
* Where the registry and its backends report. Adapted to the backends'
|
|
160
|
-
* minimal callback ({@link BackendLogFn}) before crossing the package
|
|
161
|
-
* boundary. Absent means silence.
|
|
162
|
-
*/
|
|
163
16
|
log?: Logger;
|
|
164
17
|
}
|
|
165
18
|
export interface BackendRegistry {
|
|
166
|
-
/** All configured backends, with the default backend first. */
|
|
167
19
|
getBackends(): Promise<AgentBackend[]>;
|
|
168
|
-
/** Find a configured backend by its stable id. */
|
|
169
20
|
getBackendById(id: string): Promise<AgentBackend | undefined>;
|
|
170
|
-
/** The default backend used for new and legacy sessions. */
|
|
171
21
|
getDefaultBackend(): Promise<AgentBackend>;
|
|
172
|
-
/** The stable id of the default backend. */
|
|
173
22
|
getDefaultBackendId(): Promise<string>;
|
|
174
|
-
/** Resolve the backend that owns a globally unique profile id. */
|
|
175
23
|
getBackendForProfile(profileId: string): Promise<AgentBackend | undefined>;
|
|
176
|
-
/**
|
|
24
|
+
/** Null/empty is a legacy session; an unknown non-empty id is an error. */
|
|
177
25
|
getBackendForSession(backendId: string | null | undefined): Promise<AgentBackend>;
|
|
178
|
-
/**
|
|
179
|
-
* Every available profile, tagged with its owning backend id and (when the
|
|
180
|
-
* registry can classify it) its resolved `billingMode` — settings override
|
|
181
|
-
* applied last. Hidden profiles are omitted by default (this feeds the
|
|
182
|
-
* picker); the settings screen passes `includeHidden` to render the full
|
|
183
|
-
* catalog.
|
|
184
|
-
*/
|
|
185
26
|
listAllProviders(options?: {
|
|
186
27
|
includeHidden?: boolean;
|
|
187
28
|
}): Promise<ProviderInfo[]>;
|
|
188
|
-
/**
|
|
189
|
-
* The profile new sessions and host-initiated turns (shares, actions)
|
|
190
|
-
* default to when the client named none, or null for "the default
|
|
191
|
-
* backend's own default". Resolution: the Settings-stored default model
|
|
192
|
-
* (when it still exists on the roster) wins; otherwise AUTO — a
|
|
193
|
-
* subscription-auth profile (pi vendor "openai-codex") that is on the
|
|
194
|
-
* roster, not hidden, and whose account is actually connected. The
|
|
195
|
-
* resolved profile is also listed FIRST by `listAllProviders`, so a fresh
|
|
196
|
-
* client's picker lands on it.
|
|
197
|
-
*/
|
|
198
29
|
getPreferredProfileId(): Promise<string | null>;
|
|
199
|
-
/** Per-backend capability metadata exposed by the providers route. */
|
|
200
30
|
getBackendsInfo(): Promise<Record<string, {
|
|
201
31
|
id: string;
|
|
202
32
|
capabilities: BackendCapabilities;
|
|
203
33
|
}>>;
|
|
204
|
-
/**
|
|
205
|
-
* The Claude backend's discovery source, once the registry is built. Null
|
|
206
|
-
* when discovery is disabled or the deployment runs a different backend.
|
|
207
|
-
*/
|
|
208
34
|
getModelSource(): Promise<ModelDiscoverySource | null>;
|
|
209
|
-
/** Drop the profile memo so the next read reflects a refresh or settings change. */
|
|
210
35
|
invalidateProfiles(): void;
|
|
211
36
|
}
|
|
212
|
-
/**
|
|
213
|
-
* Load an optional backend package, mapping ONLY "the backend package itself
|
|
214
|
-
* is not installed" to the actionable install hint. Everything else — the
|
|
215
|
-
* backend missing one of its OWN transitive deps, a syntax error, a throwing
|
|
216
|
-
* top-level — is a different failure whose original error IS the diagnostic,
|
|
217
|
-
* so it is rethrown untouched. The distinction rides on ERR_MODULE_NOT_FOUND
|
|
218
|
-
* naming the specifier it failed on: a transitive miss names the transitive
|
|
219
|
-
* dep, not the backend, and must not read as "backend not installed".
|
|
220
|
-
*
|
|
221
|
-
* `await import()` rather than `createRequire()(...)`: the backend packages
|
|
222
|
-
* are ESM, and a CJS require of them under plain Node dies with
|
|
223
|
-
* ERR_REQUIRE_ESM — which the old blanket catch then reported as "not
|
|
224
|
-
* installed" on a machine where the package was sitting right there.
|
|
225
|
-
*
|
|
226
|
-
* The `importer` parameter exists for tests (simulating absent or broken
|
|
227
|
-
* packages); production callers pass nothing.
|
|
228
|
-
*/
|
|
229
37
|
export declare function loadBackendModule(key: "claude" | "pi", importer?: (specifier: string) => Promise<unknown>): Promise<unknown>;
|
|
38
|
+
/** Load and structurally validate the one descriptor exported by a backend package. */
|
|
39
|
+
export declare function loadBackendDescriptor(key: "claude" | "pi", importer?: (specifier: string) => Promise<unknown>): Promise<BackendModule>;
|
|
230
40
|
/**
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* Ids Claude's side of the picker uses or can mint later ("default",
|
|
237
|
-
* "claude", "claude-*" — discovery canonicalizes every Anthropic model to a
|
|
238
|
-
* claude-* alias) are rejected, as is any collision with an id declared in
|
|
239
|
-
* BRAIN_UI_CLAUDE_PROFILES — a cross-backend collision otherwise surfaces as
|
|
240
|
-
* a 500 on first request. Claude's own JSON is parsed leniently here: when it
|
|
241
|
-
* is malformed, the Claude loader raises its own (more precise) boot error.
|
|
41
|
+
* Boot guard. It resolves active optional backend packages and synchronously
|
|
42
|
+
* loads their descriptors so backend-owned profile validation finishes before
|
|
43
|
+
* the application can report healthy. Inactive rosters are supplied as raw
|
|
44
|
+
* collision data without loading or strictly parsing their packages. Backend
|
|
45
|
+
* construction and model discovery remain lazy in the registry.
|
|
242
46
|
*/
|
|
243
|
-
export declare function
|
|
244
|
-
export declare function assertBackendResolvable(agent: AgentConfig, resolve?: (specifier: string) => void): void;
|
|
47
|
+
export declare function assertBackendResolvable(agent: AgentConfig, resolve?: (specifier: string) => void, load?: (specifier: string) => unknown): void;
|
|
245
48
|
export declare function createBackendRegistry(options: BackendRegistryOptions): BackendRegistry;
|
|
246
|
-
|
|
247
|
-
* A registry over an explicit backend list — the seam tests (and embedders
|
|
248
|
-
* with their own backend wiring) use instead of mutating module state. Takes
|
|
249
|
-
* the same optional hidden-ids reader so visibility behavior matches
|
|
250
|
-
* production.
|
|
251
|
-
*/
|
|
252
|
-
export declare function createStaticBackendRegistry(backends: AgentBackend[], defaultBackendId?: string, options?: {
|
|
49
|
+
export declare function createStaticBackendRegistry(entries: Array<AgentBackend | ResolvedBackendModule>, defaultBackendId?: string, options?: {
|
|
253
50
|
getHiddenModelIds?: () => string[];
|
|
254
51
|
getDefaultModelId?: () => string | null;
|
|
255
52
|
getBillingOverrides?: () => Record<string, BillingMode>;
|
|
53
|
+
modelSource?: BackendModelSource | null;
|
|
256
54
|
log?: Logger;
|
|
257
55
|
}): BackendRegistry;
|
|
258
56
|
//# sourceMappingURL=backend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/agent/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/agent/backend.ts"],"names":[],"mappings":"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"}
|