@schlessera/brain-ui-server 0.16.0 → 0.18.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 +2 -0
- package/dist/agent/backend.d.ts +31 -10
- package/dist/agent/backend.d.ts.map +1 -1
- package/dist/agent/backend.js +86 -26
- package/dist/agent/backend.js.map +1 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +51 -17
- package/dist/app.js.map +1 -1
- package/dist/config/env-core.d.ts +73 -0
- package/dist/config/env-core.d.ts.map +1 -0
- package/dist/config/env-core.js +62 -0
- package/dist/config/env-core.js.map +1 -0
- package/dist/config/env.d.ts +24 -5
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +55 -11
- package/dist/config/env.js.map +1 -1
- package/dist/cron/scheduler.d.ts +17 -0
- package/dist/cron/scheduler.d.ts.map +1 -1
- package/dist/cron/scheduler.js +33 -6
- package/dist/cron/scheduler.js.map +1 -1
- package/dist/db/settings.d.ts +1 -1
- package/dist/db/settings.d.ts.map +1 -1
- package/dist/db/settings.js +2 -2
- package/dist/db/settings.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware/auth.d.ts +5 -0
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +46 -1
- package/dist/middleware/auth.js.map +1 -1
- package/dist/routes/health.d.ts +4 -14
- package/dist/routes/health.d.ts.map +1 -1
- package/dist/routes/health.js +22 -6
- package/dist/routes/health.js.map +1 -1
- package/dist/routes/share.d.ts.map +1 -1
- package/dist/routes/share.js +2 -2
- package/dist/routes/share.js.map +1 -1
- package/dist/voice/keyterm-builder.js +2 -2
- package/dist/voice/keyterm-builder.js.map +1 -1
- package/dist/ws/bridge.d.ts.map +1 -1
- package/dist/ws/bridge.js +36 -4
- package/dist/ws/bridge.js.map +1 -1
- package/dist/ws/clients.d.ts +10 -3
- package/dist/ws/clients.d.ts.map +1 -1
- package/dist/ws/clients.js +16 -4
- package/dist/ws/clients.js.map +1 -1
- package/dist/ws/connection.d.ts +1 -1
- package/dist/ws/connection.d.ts.map +1 -1
- package/dist/ws/connection.js +43 -6
- package/dist/ws/connection.js.map +1 -1
- package/dist/ws/dispatch.d.ts.map +1 -1
- package/dist/ws/dispatch.js +3 -1
- package/dist/ws/dispatch.js.map +1 -1
- package/dist/ws/host.d.ts +36 -0
- package/dist/ws/host.d.ts.map +1 -1
- package/dist/ws/host.js +93 -4
- package/dist/ws/host.js.map +1 -1
- package/dist/ws/run-session.d.ts.map +1 -1
- package/dist/ws/run-session.js +31 -5
- package/dist/ws/run-session.js.map +1 -1
- package/dist/ws/session-catalog.d.ts +2 -1
- package/dist/ws/session-catalog.d.ts.map +1 -1
- package/dist/ws/session-catalog.js +20 -3
- package/dist/ws/session-catalog.js.map +1 -1
- package/dist/ws/turns.d.ts +30 -2
- package/dist/ws/turns.d.ts.map +1 -1
- package/dist/ws/turns.js +13 -0
- package/dist/ws/turns.js.map +1 -1
- package/package.json +7 -6
- package/src/agent/backend.ts +123 -29
- package/src/app.ts +59 -17
- package/src/config/env-core.ts +93 -0
- package/src/config/env.ts +80 -17
- package/src/cron/scheduler.ts +48 -14
- package/src/db/settings.ts +2 -2
- package/src/index.ts +6 -0
- package/src/middleware/auth.ts +50 -1
- package/src/routes/health.ts +22 -6
- package/src/routes/share.ts +11 -7
- package/src/voice/keyterm-builder.ts +2 -2
- package/src/ws/bridge.ts +36 -7
- package/src/ws/clients.ts +24 -6
- package/src/ws/connection.ts +59 -6
- package/src/ws/dispatch.ts +3 -1
- package/src/ws/host.ts +115 -6
- package/src/ws/run-session.ts +36 -8
- package/src/ws/session-catalog.ts +21 -3
- package/src/ws/turns.ts +37 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared core of every package's environment chokepoint — a SYNC-ENFORCED
|
|
3
|
+
* COPY, not a package.
|
|
4
|
+
*
|
|
5
|
+
* This file exists byte-identically as `src/config/env-core.ts` in every
|
|
6
|
+
* package that has an env chokepoint (`src/config/env.ts`), and the root test
|
|
7
|
+
* `tests/env-core-sync.test.ts` fails the build when any copy differs. To
|
|
8
|
+
* change it: edit ONE copy, copy the file verbatim into every package that
|
|
9
|
+
* has one (each `src/config/env-core.ts`), and rerun the sync test.
|
|
10
|
+
*
|
|
11
|
+
* Why a copy and not a `@schlessera/brain-env` package: the repo adds a seam
|
|
12
|
+
* only where a second implementation is plausible (docs/extending/README.md),
|
|
13
|
+
* and a new package for four fields and three small functions would churn the
|
|
14
|
+
* release manifest and every dependent's dependency list. Byte-equality
|
|
15
|
+
* enforced by a test gives the same single-source-of-truth guarantee without
|
|
16
|
+
* the edge. (`scripts/env-docs.ts` imports the canonical copy in
|
|
17
|
+
* `packages/core` directly — it is a root script, not published code.)
|
|
18
|
+
*
|
|
19
|
+
* What belongs here: the descriptor contract the env-docs generator and the
|
|
20
|
+
* env-parity gate consume, the dynamic-read escape hatch, and the boolean
|
|
21
|
+
* parsing helpers. What does NOT belong here: `resolveEnv` — each package's
|
|
22
|
+
* resolver reads its own variables into its own shape and stays in that
|
|
23
|
+
* package's `env.ts`.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Call-time read of a single variable whose name is data (see the package's
|
|
27
|
+
* `DYNAMIC_ENV_READS`) or whose presence gates a feature. Never cache the
|
|
28
|
+
* result at module scope.
|
|
29
|
+
*/
|
|
30
|
+
export function readEnvVar(name, env = process.env) {
|
|
31
|
+
return env[name];
|
|
32
|
+
}
|
|
33
|
+
const TRUTHY_TOKENS = ["1", "true", "on", "yes"];
|
|
34
|
+
const FALSY_TOKENS = ["0", "false", "off", "no"];
|
|
35
|
+
/**
|
|
36
|
+
* The one way a token-valued boolean environment variable is parsed.
|
|
37
|
+
*
|
|
38
|
+
* Truthy: 1 / true / on / yes. Falsy: 0 / false / off / no. Matching is
|
|
39
|
+
* case-insensitive after trimming. Unset, empty, or any unrecognised token
|
|
40
|
+
* returns `defaultValue` — a typo in a flag must never silently flip a
|
|
41
|
+
* behaviour; it falls back to the documented default instead.
|
|
42
|
+
*/
|
|
43
|
+
export function envFlag(value, defaultValue) {
|
|
44
|
+
if (value === undefined)
|
|
45
|
+
return defaultValue;
|
|
46
|
+
const token = value.trim().toLowerCase();
|
|
47
|
+
if (TRUTHY_TOKENS.includes(token))
|
|
48
|
+
return true;
|
|
49
|
+
if (FALSY_TOKENS.includes(token))
|
|
50
|
+
return false;
|
|
51
|
+
return defaultValue;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Presence-based boolean: set to ANY non-empty value means on. This is the
|
|
55
|
+
* `NO_COLOR` convention (https://no-color.org) — `NO_COLOR=0` still disables
|
|
56
|
+
* color — so it must NOT go through `envFlag`. Use only for variables whose
|
|
57
|
+
* documented contract is presence, not a token.
|
|
58
|
+
*/
|
|
59
|
+
export function envPresent(value) {
|
|
60
|
+
return value !== undefined && value !== "";
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=env-core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-core.js","sourceRoot":"","sources":["../../src/config/env-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA8BH;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,IAAY,EACZ,MAAyB,OAAO,CAAC,GAAG;IAEpC,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,aAAa,GAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AACpE,MAAM,YAAY,GAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAEpE;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,YAAqB;IACtE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzC,IAAI,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAyB;IAClD,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,CAAC;AAC7C,CAAC"}
|
package/dist/config/env.d.ts
CHANGED
|
@@ -13,17 +13,26 @@
|
|
|
13
13
|
* env record to the resolver — no global mutation required.
|
|
14
14
|
*/
|
|
15
15
|
import { type Severity } from "../observability/types.js";
|
|
16
|
+
/**
|
|
17
|
+
* The shared descriptor contract (sync-enforced copy in ./env-core.ts),
|
|
18
|
+
* under the name this package has always exported. This package's entries
|
|
19
|
+
* use the `string` arm of `required` for conditionally-required variables
|
|
20
|
+
* (e.g. "AUTH_MODE=password") and `null` for "no default".
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* One environment variable the server reads.
|
|
24
|
+
*
|
|
25
|
+
* Deliberately LOCAL and narrower than env-core's EnvVarSpec: this is the
|
|
26
|
+
* package's published descriptor shape, and widening it to the shared
|
|
27
|
+
* union would be a breaking change for typed consumers of ENV_VARS.
|
|
28
|
+
*/
|
|
16
29
|
export interface EnvVarDescriptor {
|
|
17
|
-
/**
|
|
30
|
+
/** Variable name as it appears in the environment. */
|
|
18
31
|
name: string;
|
|
19
32
|
/** What it controls. */
|
|
20
33
|
description: string;
|
|
21
34
|
/** Human-readable default applied when unset, or null when there is none. */
|
|
22
35
|
default: string | null;
|
|
23
|
-
/**
|
|
24
|
-
* `false` when optional; otherwise a human-readable statement of the
|
|
25
|
-
* condition under which boot fails without it.
|
|
26
|
-
*/
|
|
27
36
|
required: false | string;
|
|
28
37
|
}
|
|
29
38
|
/**
|
|
@@ -58,6 +67,11 @@ export interface WebAuthnConfig {
|
|
|
58
67
|
export interface AgentConfig {
|
|
59
68
|
/** Trimmed, lowercased AGENT_BACKEND; null when unset (defaults to claude). */
|
|
60
69
|
backend: string | null;
|
|
70
|
+
/**
|
|
71
|
+
* Bash-confirmation regex sources; null means "use the backend's defaults".
|
|
72
|
+
* An empty array is a deliberate opt-out and is passed through as such.
|
|
73
|
+
*/
|
|
74
|
+
confirmBashPatterns: string[] | null;
|
|
61
75
|
claudeCodePath: string;
|
|
62
76
|
defaultModel: string;
|
|
63
77
|
/** Raw BRAIN_UI_CLAUDE_PROFILES JSON, parsed lazily by the registry. */
|
|
@@ -82,6 +96,11 @@ export interface ServerConfig {
|
|
|
82
96
|
sourceCommit: string;
|
|
83
97
|
allowedOrigins: string[];
|
|
84
98
|
maxConcurrentSessions: number;
|
|
99
|
+
/**
|
|
100
|
+
* Per-turn timeout in ms (BRAIN_UI_TURN_TIMEOUT_MS), or null to use the
|
|
101
|
+
* WsHost default (10 minutes). An explicit createApp option still wins.
|
|
102
|
+
*/
|
|
103
|
+
turnTimeoutMs: number | null;
|
|
85
104
|
/** Threshold for the console log consumer (BRAIN_UI_LOG_LEVEL). */
|
|
86
105
|
logLevel: Severity;
|
|
87
106
|
/** Inbound WebSocket frame metering, per connection. */
|
package/dist/config/env.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"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"}
|
package/dist/config/env.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { join } from "path";
|
|
16
16
|
import { SEVERITIES } from "../observability/types.js";
|
|
17
|
+
import { envFlag } from "./env-core.js";
|
|
17
18
|
/**
|
|
18
19
|
* Every environment variable this package reads. Order groups by concern.
|
|
19
20
|
* The env-parity gate (G4) asserts this list equals the package's env
|
|
@@ -45,6 +46,18 @@ export const ENV_VARS = [
|
|
|
45
46
|
default: "(empty)",
|
|
46
47
|
required: false,
|
|
47
48
|
},
|
|
49
|
+
{
|
|
50
|
+
name: "BRAIN_UI_CONFIRM_BASH",
|
|
51
|
+
description: "JSON array of regex sources; a Bash command matching any of them raises " +
|
|
52
|
+
"a confirmation card before it runs. Unset uses the shipped defaults " +
|
|
53
|
+
"(brain archive, rm -r, git push --force, git reset --hard, git clean -f, " +
|
|
54
|
+
"git checkout -- ). An empty array [] disables the confirmation. Not a " +
|
|
55
|
+
"security boundary — an agent with Bash can reach the same effect another " +
|
|
56
|
+
"way; it stops a destructive command you did not intend, not one that is " +
|
|
57
|
+
"trying to get past you.",
|
|
58
|
+
default: "the shipped pattern set",
|
|
59
|
+
required: false,
|
|
60
|
+
},
|
|
48
61
|
{
|
|
49
62
|
name: "BRAIN_UI_WS_RATE",
|
|
50
63
|
description: "Sustained inbound WebSocket frames per second per connection. 0 " +
|
|
@@ -85,6 +98,12 @@ export const ENV_VARS = [
|
|
|
85
98
|
default: "3",
|
|
86
99
|
required: false,
|
|
87
100
|
},
|
|
101
|
+
{
|
|
102
|
+
name: "BRAIN_UI_TURN_TIMEOUT_MS",
|
|
103
|
+
description: "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).",
|
|
104
|
+
default: "600000 (10 minutes)",
|
|
105
|
+
required: false,
|
|
106
|
+
},
|
|
88
107
|
// auth
|
|
89
108
|
{
|
|
90
109
|
name: "AUTH_MODE",
|
|
@@ -246,9 +265,6 @@ function list(raw) {
|
|
|
246
265
|
.map((s) => s.trim())
|
|
247
266
|
.filter(Boolean);
|
|
248
267
|
}
|
|
249
|
-
function flag(raw) {
|
|
250
|
-
return raw === "1";
|
|
251
|
-
}
|
|
252
268
|
/**
|
|
253
269
|
* A log threshold, defaulting to INFO.
|
|
254
270
|
*
|
|
@@ -263,6 +279,30 @@ function positiveNumber(raw, fallback) {
|
|
|
263
279
|
const n = Number(raw);
|
|
264
280
|
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
265
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Parse BRAIN_UI_CONFIRM_BASH into pattern sources.
|
|
284
|
+
*
|
|
285
|
+
* Unset or unparseable → null, meaning the backend's shipped defaults. An
|
|
286
|
+
* explicit `[]` is honoured as "no confirmation": disabling the seatbelt is a
|
|
287
|
+
* choice a deployment is allowed to make, and silently re-enabling it would be
|
|
288
|
+
* worse than obeying. Malformed JSON falls back to the defaults rather than
|
|
289
|
+
* throwing — a typo here must not stop the server booting, and the safe
|
|
290
|
+
* direction to fail is "more confirmation", not less.
|
|
291
|
+
*/
|
|
292
|
+
function parseConfirmBash(raw) {
|
|
293
|
+
const text = raw?.trim();
|
|
294
|
+
if (!text)
|
|
295
|
+
return null;
|
|
296
|
+
try {
|
|
297
|
+
const parsed = JSON.parse(text);
|
|
298
|
+
if (!Array.isArray(parsed))
|
|
299
|
+
return null;
|
|
300
|
+
return parsed.filter((p) => typeof p === "string");
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
266
306
|
function parseSeverity(raw) {
|
|
267
307
|
const upper = raw?.trim().toUpperCase();
|
|
268
308
|
return SEVERITIES.includes(upper ?? "")
|
|
@@ -278,10 +318,7 @@ export function resolveServerConfig(env = process.env) {
|
|
|
278
318
|
const brainPath = env.BRAIN_PATH || join(env.HOME || "/root", "brain");
|
|
279
319
|
const rawAuthMode = env.AUTH_MODE?.trim().toLowerCase() || null;
|
|
280
320
|
const validMode = AUTH_MODES.find((mode) => mode === rawAuthMode) ?? null;
|
|
281
|
-
const
|
|
282
|
-
const modelDiscovery = rawDiscovery
|
|
283
|
-
? !(rawDiscovery === "0" || rawDiscovery === "off" || rawDiscovery === "false")
|
|
284
|
-
: env.NODE_ENV !== "test";
|
|
321
|
+
const modelDiscovery = envFlag(env.BRAIN_UI_MODEL_DISCOVERY, env.NODE_ENV !== "test");
|
|
285
322
|
const rawTtl = Number(env.BRAIN_UI_MODEL_TTL_HOURS);
|
|
286
323
|
const ttlHours = Number.isFinite(rawTtl) && rawTtl > 0 ? rawTtl : 24;
|
|
287
324
|
return {
|
|
@@ -291,16 +328,22 @@ export function resolveServerConfig(env = process.env) {
|
|
|
291
328
|
sourceCommit: env.SOURCE_COMMIT ?? "dev",
|
|
292
329
|
allowedOrigins: list(env.ALLOWED_ORIGINS),
|
|
293
330
|
maxConcurrentSessions: Math.max(1, Number(env.MAX_CONCURRENT_SESSIONS) || 3),
|
|
331
|
+
// Positive integer or null — 0, negatives, and garbage all mean "unset",
|
|
332
|
+
// so a typo degrades to the safe default instead of an instant timeout.
|
|
333
|
+
turnTimeoutMs: Number.isFinite(Number(env.BRAIN_UI_TURN_TIMEOUT_MS)) &&
|
|
334
|
+
Number(env.BRAIN_UI_TURN_TIMEOUT_MS) > 0
|
|
335
|
+
? Math.floor(Number(env.BRAIN_UI_TURN_TIMEOUT_MS))
|
|
336
|
+
: null,
|
|
294
337
|
auth: {
|
|
295
338
|
mode: validMode,
|
|
296
339
|
invalidMode: validMode ? null : rawAuthMode,
|
|
297
340
|
passwordHash: env.BRAIN_UI_PASSWORD_HASH || null,
|
|
298
341
|
cookieSecret: env.COOKIE_SECRET || null,
|
|
299
|
-
trustProxy:
|
|
342
|
+
trustProxy: envFlag(env.TRUST_PROXY, false),
|
|
300
343
|
trustProxyHops: Math.max(1, Number(env.TRUST_PROXY_HOPS) || 1),
|
|
301
344
|
proxyAuthHeader: (env.PROXY_AUTH_HEADER || "x-forwarded-user").toLowerCase(),
|
|
302
|
-
dangerouslyDisableAuth:
|
|
303
|
-
allowPassword:
|
|
345
|
+
dangerouslyDisableAuth: envFlag(env.BRAIN_UI_DANGEROUSLY_DISABLE_AUTH, false),
|
|
346
|
+
allowPassword: envFlag(env.BRAIN_UI_ALLOW_PASSWORD, false),
|
|
304
347
|
},
|
|
305
348
|
webauthn: {
|
|
306
349
|
rpName: env.WEBAUTHN_RP_NAME || "Brain UI",
|
|
@@ -308,10 +351,11 @@ export function resolveServerConfig(env = process.env) {
|
|
|
308
351
|
userId: env.WEBAUTHN_USER_ID || "brain-ui-owner",
|
|
309
352
|
rpId: env.WEBAUTHN_RP_ID || null,
|
|
310
353
|
origins: list(env.WEBAUTHN_ORIGINS),
|
|
311
|
-
allowLoopbackOrigin:
|
|
354
|
+
allowLoopbackOrigin: envFlag(env.BRAIN_UI_ALLOW_LOOPBACK_ORIGIN, false),
|
|
312
355
|
},
|
|
313
356
|
agent: {
|
|
314
357
|
backend: env.AGENT_BACKEND?.trim().toLowerCase() || null,
|
|
358
|
+
confirmBashPatterns: parseConfirmBash(env.BRAIN_UI_CONFIRM_BASH),
|
|
315
359
|
claudeCodePath: env.CLAUDE_CODE_PATH || "/usr/local/bin/claude",
|
|
316
360
|
defaultModel: env.BRAIN_UI_CLAUDE_DEFAULT_MODEL?.trim() || "claude-sonnet-4-6",
|
|
317
361
|
profilesJson: env.BRAIN_UI_CLAUDE_PROFILES?.trim() || null,
|
package/dist/config/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,UAAU,EAAiB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"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"}
|
package/dist/cron/scheduler.d.ts
CHANGED
|
@@ -11,6 +11,23 @@ export interface CronScheduler {
|
|
|
11
11
|
}>;
|
|
12
12
|
triggerJob(name: string): Promise<boolean>;
|
|
13
13
|
}
|
|
14
|
+
/** One in-flight job run being recorded into `cron_runs`. */
|
|
15
|
+
export interface CronRunRecord {
|
|
16
|
+
/** Mark the run finished: success without an argument, error with one. */
|
|
17
|
+
finish(error?: string): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Record a job run in the `cron_runs` history that `/api/status` serves
|
|
21
|
+
* (`cronJobs`, via {@link CronScheduler.getCronStatus}).
|
|
22
|
+
*
|
|
23
|
+
* The scheduler in this module only writes the table for its own manual
|
|
24
|
+
* triggers; in the shipped deployment the jobs are executed by the container
|
|
25
|
+
* crontab, whose runs were invisible to `/api/status`. An external scheduler's
|
|
26
|
+
* wrapper calls this before the job and `finish()` after, writing exactly the
|
|
27
|
+
* rows the in-process runner writes. A run whose process died before
|
|
28
|
+
* `finish()` stays in status "running" — itself a signal.
|
|
29
|
+
*/
|
|
30
|
+
export declare function recordCronRun(db: Database, jobName: string): CronRunRecord;
|
|
14
31
|
export declare function createCronScheduler(deps: {
|
|
15
32
|
db: Database;
|
|
16
33
|
brain: BrainClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/cron/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/cron/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAQtD,MAAM,WAAW,aAAa;IAC5B,aAAa,IAAI,KAAK,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC,CAAC;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5C;AAOD,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAqB1E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,EAAE,EAAE,QAAQ,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,6DAA6D;IAC7D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,aAAa,CAuEhB"}
|
package/dist/cron/scheduler.js
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record a job run in the `cron_runs` history that `/api/status` serves
|
|
3
|
+
* (`cronJobs`, via {@link CronScheduler.getCronStatus}).
|
|
4
|
+
*
|
|
5
|
+
* The scheduler in this module only writes the table for its own manual
|
|
6
|
+
* triggers; in the shipped deployment the jobs are executed by the container
|
|
7
|
+
* crontab, whose runs were invisible to `/api/status`. An external scheduler's
|
|
8
|
+
* wrapper calls this before the job and `finish()` after, writing exactly the
|
|
9
|
+
* rows the in-process runner writes. A run whose process died before
|
|
10
|
+
* `finish()` stays in status "running" — itself a signal.
|
|
11
|
+
*/
|
|
12
|
+
export function recordCronRun(db, jobName) {
|
|
13
|
+
const startedAt = Date.now();
|
|
14
|
+
db.prepare("INSERT INTO cron_runs (job_name, started_at, status) VALUES (?, ?, 'running')").run(jobName, startedAt);
|
|
15
|
+
return {
|
|
16
|
+
finish(error) {
|
|
17
|
+
const finishedAt = Date.now();
|
|
18
|
+
const durationMs = finishedAt - startedAt;
|
|
19
|
+
if (error === undefined) {
|
|
20
|
+
db.prepare("UPDATE cron_runs SET status = 'success', finished_at = ?, duration_ms = ? WHERE job_name = ? AND started_at = ?").run(finishedAt, durationMs, jobName, startedAt);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
db.prepare("UPDATE cron_runs SET status = 'error', finished_at = ?, duration_ms = ?, error_message = ? WHERE job_name = ? AND started_at = ?").run(finishedAt, durationMs, error, jobName, startedAt);
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
1
28
|
export function createCronScheduler(deps) {
|
|
2
29
|
const { db, brain, log } = deps;
|
|
3
30
|
const jobs = [
|
|
@@ -17,21 +44,21 @@ export function createCronScheduler(deps) {
|
|
|
17
44
|
];
|
|
18
45
|
async function runJob(job) {
|
|
19
46
|
const startedAt = Date.now();
|
|
20
|
-
|
|
47
|
+
// Same recorder the external-scheduler path uses, so the two can never
|
|
48
|
+
// drift in what a cron_runs row looks like.
|
|
49
|
+
const record = recordCronRun(db, job.name);
|
|
21
50
|
try {
|
|
22
51
|
await job.handler();
|
|
23
|
-
|
|
24
|
-
db.prepare("UPDATE cron_runs SET status = 'success', finished_at = ?, duration_ms = ? WHERE job_name = ? AND started_at = ?").run(Date.now(), durationMs, job.name, startedAt);
|
|
52
|
+
record.finish();
|
|
25
53
|
log?.emit({
|
|
26
54
|
severityText: "INFO",
|
|
27
55
|
body: "job completed",
|
|
28
|
-
attributes: { job: job.name, "duration.ms":
|
|
56
|
+
attributes: { job: job.name, "duration.ms": Date.now() - startedAt },
|
|
29
57
|
});
|
|
30
58
|
}
|
|
31
59
|
catch (err) {
|
|
32
|
-
const durationMs = Date.now() - startedAt;
|
|
33
60
|
const message = err instanceof Error ? err.message : String(err);
|
|
34
|
-
|
|
61
|
+
record.finish(message);
|
|
35
62
|
log?.emit({
|
|
36
63
|
severityText: "ERROR",
|
|
37
64
|
body: "job failed",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/cron/scheduler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/cron/scheduler.ts"],"names":[],"mappings":"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"}
|
package/dist/db/settings.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Database } from "bun:sqlite";
|
|
|
3
3
|
export declare function getSetting<T>(db: Database, key: string, fallback: T, log?: Logger): T;
|
|
4
4
|
export declare function setSetting(db: Database, key: string, value: unknown): void;
|
|
5
5
|
/** Profile ids the user keeps out of the model picker. */
|
|
6
|
-
export declare function getHiddenModelIds(db: Database): string[];
|
|
6
|
+
export declare function getHiddenModelIds(db: Database, log?: Logger): string[];
|
|
7
7
|
/** Replace the hidden set (the client always sends the full list, not a delta). */
|
|
8
8
|
export declare function setHiddenModelIds(db: Database, ids: string[]): void;
|
|
9
9
|
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/db/settings.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,wBAAgB,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAerF;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAK1E;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/db/settings.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,wBAAgB,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAerF;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAK1E;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAItE;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAGnE"}
|
package/dist/db/settings.js
CHANGED
|
@@ -29,8 +29,8 @@ export function setSetting(db, key, value) {
|
|
|
29
29
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`).run(key, JSON.stringify(value), Date.now());
|
|
30
30
|
}
|
|
31
31
|
/** Profile ids the user keeps out of the model picker. */
|
|
32
|
-
export function getHiddenModelIds(db) {
|
|
33
|
-
const value = getSetting(db, HIDDEN_MODELS_KEY, []);
|
|
32
|
+
export function getHiddenModelIds(db, log) {
|
|
33
|
+
const value = getSetting(db, HIDDEN_MODELS_KEY, [], log);
|
|
34
34
|
if (!Array.isArray(value))
|
|
35
35
|
return [];
|
|
36
36
|
return value.filter((id) => typeof id === "string");
|
package/dist/db/settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/db/settings.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,yEAAyE;AACzE,6EAA6E;AAC7E,4EAA4E;AAC5E,8EAA8E;AAC9E,iDAAiD;AAKjD,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAE1C,MAAM,UAAU,UAAU,CAAI,EAAY,EAAE,GAAW,EAAE,QAAW,EAAE,GAAY;IAChF,MAAM,GAAG,GAAG,EAAE;SACX,KAAK,CAAC,0CAA0C,CAAC;SACjD,GAAG,CAAC,GAAG,CAA6B,CAAC;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO,QAAQ,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAM,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,EAAE,IAAI,CAAC;YACR,YAAY,EAAE,MAAM;YACpB,IAAI,EAAE,0CAA0C;YAChD,UAAU,EAAE,EAAE,GAAG,EAAE;SACpB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAY,EAAE,GAAW,EAAE,KAAc;IAClE,EAAE,CAAC,OAAO,CACR;6FACyF,CAC1F,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,iBAAiB,CAAC,EAAY;
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/db/settings.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,yEAAyE;AACzE,6EAA6E;AAC7E,4EAA4E;AAC5E,8EAA8E;AAC9E,iDAAiD;AAKjD,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAE1C,MAAM,UAAU,UAAU,CAAI,EAAY,EAAE,GAAW,EAAE,QAAW,EAAE,GAAY;IAChF,MAAM,GAAG,GAAG,EAAE;SACX,KAAK,CAAC,0CAA0C,CAAC;SACjD,GAAG,CAAC,GAAG,CAA6B,CAAC;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO,QAAQ,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAM,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,EAAE,IAAI,CAAC;YACR,YAAY,EAAE,MAAM;YACpB,IAAI,EAAE,0CAA0C;YAChD,UAAU,EAAE,EAAE,GAAG,EAAE;SACpB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAY,EAAE,GAAW,EAAE,KAAc;IAClE,EAAE,CAAC,OAAO,CACR;6FACyF,CAC1F,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,iBAAiB,CAAC,EAAY,EAAE,GAAY;IAC1D,MAAM,KAAK,GAAG,UAAU,CAAU,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IAClE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC;AACpE,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAAC,EAAY,EAAE,GAAa;IAC3D,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9E,UAAU,CAAC,EAAE,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;AAC5C,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export { createApp, type CreateAppOptions, type BrainUiApp, type AppRenderer, } from "./app.js";
|
|
12
12
|
export { ENV_VARS, resolveServerConfig, type EnvVarDescriptor, type ServerConfig, type AuthConfig, type WebAuthnConfig, type AgentConfig, type VoiceConfig, } from "./config/env.js";
|
|
13
|
-
export { assertBackendResolvable, createBackendRegistry, createStaticBackendRegistry, type BackendRegistry, type ModelDiscoverySource, type ModelDiscoveryState, } from "./agent/backend.js";
|
|
13
|
+
export { assertBackendResolvable, createBackendRegistry, createStaticBackendRegistry, type BackendLogFn, type BackendRegistry, type ModelDiscoverySource, type ModelDiscoveryState, } from "./agent/backend.js";
|
|
14
14
|
export { resolveAuthMode, type AuthMode, type AuthRuntime, } from "./middleware/auth.js";
|
|
15
15
|
export { createUiDb } from "./db/client.js";
|
|
16
16
|
export { openBrainDb, withBrainDb, BrainDbUnavailableError, MIN_BRAIN_SCHEMA_VERSION, } from "./db/brain-db.js";
|
|
@@ -20,6 +20,7 @@ export { handleClientMessage, turnIdMatches, type ConnectionState, } from "./ws/
|
|
|
20
20
|
export { resolveTurnTarget } from "./ws/routing.js";
|
|
21
21
|
export { createSessionCatalog, type SessionCatalog, } from "./ws/session-catalog.js";
|
|
22
22
|
export { createBrainClient, type BrainClient } from "./brain/client.js";
|
|
23
|
+
export { recordCronRun, type CronRunRecord } from "./cron/scheduler.js";
|
|
23
24
|
export { pruneShareStaging, shareStagingRoot } from "./share/staging.js";
|
|
24
25
|
export { createObservability, createRecordingObservability, createSilentObservability, createConsoleLoggerProvider, createRecordingLoggerProvider, createSilentLoggerProvider, createInMemoryMeterProvider, SEVERITIES, severityRank, seriesKey, } from "./observability/index.js";
|
|
25
26
|
export type { Observability, ObservabilityOptions, RecordingObservability, RecordingLoggerProvider, InMemoryMeterProvider, LogReader, LogWriter, MetricsReader, Severity, CapturedLog, LogQuery, MetricPoint, MetricSnapshot, } from "./observability/index.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,UAAU,CAAC;AAIlB,OAAO,EACL,QAAQ,EACR,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,eAAe,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,GACjB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAI5C,OAAO,EACL,WAAW,EACX,WAAW,EACX,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,GACpB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIxE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKzE,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,yBAAyB,EACzB,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC3B,UAAU,EACV,YAAY,EACZ,SAAS,GACV,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,SAAS,EACT,SAAS,EACT,aAAa,EACb,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,aAAa,EACb,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,UAAU,CAAC;AAIlB,OAAO,EACL,QAAQ,EACR,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,eAAe,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,GACjB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAI5C,OAAO,EACL,WAAW,EACX,WAAW,EACX,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,GACpB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKxE,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIxE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKzE,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,yBAAyB,EACzB,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC3B,UAAU,EACV,YAAY,EACZ,SAAS,GACV,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,SAAS,EACT,SAAS,EACT,aAAa,EACb,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,aAAa,EACb,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,4BAA4B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,10 @@ export { createSessionCatalog, } from "./ws/session-catalog.js";
|
|
|
30
30
|
// Brain repo access (spawned CLI wrapper) — useful for embedders that add
|
|
31
31
|
// their own routes on top.
|
|
32
32
|
export { createBrainClient } from "./brain/client.js";
|
|
33
|
+
// Cron run history. Scheduling belongs to the deployment (container crontab);
|
|
34
|
+
// an external scheduler's wrapper records each run here so /api/status's
|
|
35
|
+
// `cronJobs` reflects what actually ran.
|
|
36
|
+
export { recordCronRun } from "./cron/scheduler.js";
|
|
33
37
|
// Share staging: a deployment can sweep expired staging dirs at boot; the
|
|
34
38
|
// intake route also sweeps opportunistically on every share.
|
|
35
39
|
export { pruneShareStaging, shareStagingRoot } from "./share/staging.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,SAAS,GAIV,MAAM,UAAU,CAAC;AAElB,6EAA6E;AAC7E,8EAA8E;AAC9E,OAAO,EACL,QAAQ,EACR,mBAAmB,GAOpB,MAAM,iBAAiB,CAAC;AAEzB,4EAA4E;AAC5E,+BAA+B;AAC/B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,SAAS,GAIV,MAAM,UAAU,CAAC;AAElB,6EAA6E;AAC7E,8EAA8E;AAC9E,OAAO,EACL,QAAQ,EACR,mBAAmB,GAOpB,MAAM,iBAAiB,CAAC;AAEzB,4EAA4E;AAC5E,+BAA+B;AAC/B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,GAK5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,eAAe,GAGhB,MAAM,sBAAsB,CAAC;AAE9B,gEAAgE;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,uEAAuE;AACvE,qBAAqB;AACrB,OAAO,EACL,WAAW,EACX,WAAW,EACX,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAE1B,+CAA+C;AAC/C,OAAO,EAAE,MAAM,EAAsB,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EACL,mBAAmB,EACnB,aAAa,GAEd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,oBAAoB,GAErB,MAAM,yBAAyB,CAAC;AAEjC,0EAA0E;AAC1E,2BAA2B;AAC3B,OAAO,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAExE,8EAA8E;AAC9E,yEAAyE;AACzE,yCAAyC;AACzC,OAAO,EAAE,aAAa,EAAsB,MAAM,qBAAqB,CAAC;AAExE,0EAA0E;AAC1E,6DAA6D;AAC7D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEzE,4EAA4E;AAC5E,+EAA+E;AAC/E,2EAA2E;AAC3E,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,yBAAyB,EACzB,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC3B,UAAU,EACV,YAAY,EACZ,SAAS,GACV,MAAM,0BAA0B,CAAC;AAiBlC,wEAAwE;AACxE,OAAO,EACL,aAAa,EACb,UAAU,GAEX,MAAM,4BAA4B,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Counter } from "@opentelemetry/api";
|
|
1
2
|
import type { Logger } from "@opentelemetry/api-logs";
|
|
2
3
|
import { Hono } from "hono";
|
|
3
4
|
import type { Context, MiddlewareHandler } from "hono";
|
|
@@ -67,5 +68,9 @@ export declare function authRoutes(mode: AuthMode, auth: AuthRuntime, deps?: {
|
|
|
67
68
|
* of WebAuthn concerns.
|
|
68
69
|
*/
|
|
69
70
|
passwordDisabled?: (c: Context) => boolean;
|
|
71
|
+
/** Where login outcomes are reported; absent means silence. */
|
|
72
|
+
log?: Logger;
|
|
73
|
+
/** Failed-login counter — the same `auth.failures` instrument passkeys use. */
|
|
74
|
+
failures?: Counter;
|
|
70
75
|
}): Hono;
|
|
71
76
|
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAEnE,iEAAiE;AACjE,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;CACd;AAID,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAQlC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,QAAQ,CAWzE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAqEtF;AAED,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,GAAG,iBAAiB,CAqC9E;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,CAAC,EAAE,OAAO,EACV,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAID;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrF;AAwCD,8EAA8E;AAC9E,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAUrE;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CACxB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,WAAW,EACjB,IAAI,GAAE;IACJ;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAEnE,iEAAiE;AACjE,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;CACd;AAID,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAQlC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,QAAQ,CAWzE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAqEtF;AAED,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,GAAG,iBAAiB,CAqC9E;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,CAAC,EAAE,OAAO,EACV,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAID;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrF;AAwCD,8EAA8E;AAC9E,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAUrE;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CACxB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,WAAW,EACjB,IAAI,GAAE;IACJ;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC;IAC3C,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACf,GACL,IAAI,CA8FN"}
|
package/dist/middleware/auth.js
CHANGED
|
@@ -214,6 +214,7 @@ export function consumeLoginToken(key, limit) {
|
|
|
214
214
|
/** Login/logout routes. Only functional in `password` mode. */
|
|
215
215
|
export function authRoutes(mode, auth, deps = {}) {
|
|
216
216
|
const app = new Hono();
|
|
217
|
+
const { log, failures } = deps;
|
|
217
218
|
app.post("/auth/login", async (c) => {
|
|
218
219
|
if (mode !== "password") {
|
|
219
220
|
return c.json({ error: "Password login is not enabled" }, 400);
|
|
@@ -222,6 +223,12 @@ export function authRoutes(mode, auth, deps = {}) {
|
|
|
222
223
|
const perIpOk = consumeLoginToken(`ip:${key}`, LOGIN_RATE_LIMIT);
|
|
223
224
|
const globalOk = consumeLoginToken("global", GLOBAL_LOGIN_RATE_LIMIT);
|
|
224
225
|
if (!perIpOk || !globalOk) {
|
|
226
|
+
failures?.add(1, { reason: "rate_limited", method: "password" });
|
|
227
|
+
log?.emit({
|
|
228
|
+
severityText: "WARN",
|
|
229
|
+
body: "login rate limited",
|
|
230
|
+
attributes: { ip: key, limit: perIpOk ? "global" : "ip" },
|
|
231
|
+
});
|
|
225
232
|
return c.json({ error: "Too many attempts. Try again in a minute." }, 429);
|
|
226
233
|
}
|
|
227
234
|
if (deps.passwordDisabled?.(c)) {
|
|
@@ -238,13 +245,51 @@ export function authRoutes(mode, auth, deps = {}) {
|
|
|
238
245
|
}
|
|
239
246
|
const password = typeof body.password === "string" ? body.password : "";
|
|
240
247
|
if (!password || !hash || !secret) {
|
|
248
|
+
failures?.add(1, { reason: "invalid_password", method: "password" });
|
|
249
|
+
log?.emit({
|
|
250
|
+
severityText: "WARN",
|
|
251
|
+
body: "login failed",
|
|
252
|
+
attributes: { ip: key },
|
|
253
|
+
});
|
|
254
|
+
return c.json({ error: "Invalid credentials" }, 401);
|
|
255
|
+
}
|
|
256
|
+
// A verify that THROWS is not a wrong password — it is a hash Bun cannot
|
|
257
|
+
// parse (a corrupt BRAIN_UI_PASSWORD_HASH locks the owner out of every
|
|
258
|
+
// login), and collapsing it into "invalid credentials" hid exactly that.
|
|
259
|
+
let ok = false;
|
|
260
|
+
let verifyError = null;
|
|
261
|
+
try {
|
|
262
|
+
ok = await Bun.password.verify(password, hash);
|
|
263
|
+
}
|
|
264
|
+
catch (err) {
|
|
265
|
+
verifyError = err;
|
|
266
|
+
}
|
|
267
|
+
if (verifyError) {
|
|
268
|
+
failures?.add(1, { reason: "verify_error", method: "password" });
|
|
269
|
+
log?.emit({
|
|
270
|
+
severityText: "ERROR",
|
|
271
|
+
body: "password verification errored — check BRAIN_UI_PASSWORD_HASH",
|
|
272
|
+
attributes: {
|
|
273
|
+
error: verifyError instanceof Error ? verifyError.message : String(verifyError),
|
|
274
|
+
},
|
|
275
|
+
});
|
|
241
276
|
return c.json({ error: "Invalid credentials" }, 401);
|
|
242
277
|
}
|
|
243
|
-
const ok = await Bun.password.verify(password, hash).catch(() => false);
|
|
244
278
|
if (!ok) {
|
|
279
|
+
failures?.add(1, { reason: "invalid_password", method: "password" });
|
|
280
|
+
log?.emit({
|
|
281
|
+
severityText: "WARN",
|
|
282
|
+
body: "login failed",
|
|
283
|
+
attributes: { ip: key },
|
|
284
|
+
});
|
|
245
285
|
return c.json({ error: "Invalid credentials" }, 401);
|
|
246
286
|
}
|
|
247
287
|
await issueSessionCookie(c, auth);
|
|
288
|
+
log?.emit({
|
|
289
|
+
severityText: "INFO",
|
|
290
|
+
body: "login succeeded",
|
|
291
|
+
attributes: { ip: key },
|
|
292
|
+
});
|
|
248
293
|
return c.json({ ok: true });
|
|
249
294
|
});
|
|
250
295
|
app.post("/auth/logout", (c) => {
|