@runcore-sh/runcore 0.1.9 → 0.1.10
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/dist/cli.js +232 -11
- package/dist/cli.js.map +1 -1
- package/dist/files/deep-index.d.ts +59 -0
- package/dist/files/deep-index.d.ts.map +1 -0
- package/dist/files/deep-index.js +337 -0
- package/dist/files/deep-index.js.map +1 -0
- package/dist/files/import.d.ts +44 -0
- package/dist/files/import.d.ts.map +1 -0
- package/dist/files/import.js +213 -0
- package/dist/files/import.js.map +1 -0
- package/dist/files/index-local.d.ts +37 -0
- package/dist/files/index-local.d.ts.map +1 -0
- package/dist/files/index-local.js +198 -0
- package/dist/files/index-local.js.map +1 -0
- package/dist/nerve/state.d.ts +1 -1
- package/dist/nerve/state.d.ts.map +1 -1
- package/dist/nerve/state.js +1 -1
- package/dist/nerve/state.js.map +1 -1
- package/dist/posture/engine.d.ts +41 -0
- package/dist/posture/engine.d.ts.map +1 -0
- package/dist/posture/engine.js +217 -0
- package/dist/posture/engine.js.map +1 -0
- package/dist/posture/index.d.ts +11 -0
- package/dist/posture/index.d.ts.map +1 -0
- package/dist/posture/index.js +10 -0
- package/dist/posture/index.js.map +1 -0
- package/dist/posture/middleware.d.ts +30 -0
- package/dist/posture/middleware.d.ts.map +1 -0
- package/dist/posture/middleware.js +92 -0
- package/dist/posture/middleware.js.map +1 -0
- package/dist/posture/types.d.ts +61 -0
- package/dist/posture/types.d.ts.map +1 -0
- package/dist/posture/types.js +48 -0
- package/dist/posture/types.js.map +1 -0
- package/dist/server.d.ts +3 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +191 -45
- package/dist/server.js.map +1 -1
- package/dist/tier/bond.d.ts +51 -0
- package/dist/tier/bond.d.ts.map +1 -0
- package/dist/tier/bond.js +154 -0
- package/dist/tier/bond.js.map +1 -0
- package/dist/tier/freeze.d.ts +21 -0
- package/dist/tier/freeze.d.ts.map +1 -0
- package/dist/tier/freeze.js +73 -0
- package/dist/tier/freeze.js.map +1 -0
- package/dist/tier/gate.d.ts +11 -0
- package/dist/tier/gate.d.ts.map +1 -0
- package/dist/tier/gate.js +25 -0
- package/dist/tier/gate.js.map +1 -0
- package/dist/tier/heartbeat.d.ts +22 -0
- package/dist/tier/heartbeat.d.ts.map +1 -0
- package/dist/tier/heartbeat.js +128 -0
- package/dist/tier/heartbeat.js.map +1 -0
- package/dist/tier/token.d.ts +22 -0
- package/dist/tier/token.d.ts.map +1 -0
- package/dist/tier/token.js +100 -0
- package/dist/tier/token.js.map +1 -0
- package/dist/tier/types.d.ts +44 -0
- package/dist/tier/types.d.ts.map +1 -0
- package/dist/tier/types.js +61 -0
- package/dist/tier/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Posture middleware — gates routes by current UI surface level
|
|
3
|
+
* and records interaction signals for intent accumulation.
|
|
4
|
+
*
|
|
5
|
+
* Routes return 404 (not 403) when posture is below threshold.
|
|
6
|
+
* The surface doesn't exist yet — it's not forbidden, it's not assembled.
|
|
7
|
+
*/
|
|
8
|
+
import type { MiddlewareHandler } from "hono";
|
|
9
|
+
import type { PostureSurface } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Middleware: record every API interaction as a signal.
|
|
12
|
+
* Mounted early — runs for all /api/* routes.
|
|
13
|
+
*/
|
|
14
|
+
export declare function postureTracker(): MiddlewareHandler;
|
|
15
|
+
/**
|
|
16
|
+
* Middleware: record page views (HTML page loads).
|
|
17
|
+
* Mounted on page routes like /board, /ops, /observatory, etc.
|
|
18
|
+
*/
|
|
19
|
+
export declare function pageViewTracker(pageName: string): MiddlewareHandler;
|
|
20
|
+
/**
|
|
21
|
+
* Require a minimum posture level for a route group.
|
|
22
|
+
* Returns 404 if the surface isn't assembled yet.
|
|
23
|
+
*/
|
|
24
|
+
export declare function requireSurface(surface: keyof PostureSurface): MiddlewareHandler;
|
|
25
|
+
/**
|
|
26
|
+
* Add posture info to API responses via header.
|
|
27
|
+
* Clients use this to know what to render.
|
|
28
|
+
*/
|
|
29
|
+
export declare function postureHeader(): MiddlewareHandler;
|
|
30
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/posture/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,CAsClD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CASnE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,cAAc,GAAG,iBAAiB,CAO/E;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,iBAAiB,CAMjD"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Posture middleware — gates routes by current UI surface level
|
|
3
|
+
* and records interaction signals for intent accumulation.
|
|
4
|
+
*
|
|
5
|
+
* Routes return 404 (not 403) when posture is below threshold.
|
|
6
|
+
* The surface doesn't exist yet — it's not forbidden, it's not assembled.
|
|
7
|
+
*/
|
|
8
|
+
import { hasSurface, recordInteraction, getSurface } from "./engine.js";
|
|
9
|
+
/**
|
|
10
|
+
* Middleware: record every API interaction as a signal.
|
|
11
|
+
* Mounted early — runs for all /api/* routes.
|
|
12
|
+
*/
|
|
13
|
+
export function postureTracker() {
|
|
14
|
+
return async (c, next) => {
|
|
15
|
+
const path = c.req.path;
|
|
16
|
+
// Classify the interaction
|
|
17
|
+
let surface = "chat";
|
|
18
|
+
let detail;
|
|
19
|
+
if (path.startsWith("/api/nerve") || path.startsWith("/api/pulse")) {
|
|
20
|
+
surface = "pulse";
|
|
21
|
+
}
|
|
22
|
+
else if (path.startsWith("/api/board")) {
|
|
23
|
+
surface = "pages";
|
|
24
|
+
detail = "board";
|
|
25
|
+
}
|
|
26
|
+
else if (path.startsWith("/api/ops")) {
|
|
27
|
+
surface = "pages";
|
|
28
|
+
detail = "ops";
|
|
29
|
+
}
|
|
30
|
+
else if (path.startsWith("/api/agents")) {
|
|
31
|
+
surface = "agents";
|
|
32
|
+
}
|
|
33
|
+
else if (path.startsWith("/api/settings") || path.startsWith("/api/admin")) {
|
|
34
|
+
surface = "settings";
|
|
35
|
+
}
|
|
36
|
+
else if (path.startsWith("/api/open-loops") || path.startsWith("/api/insights") || path.startsWith("/api/metrics")) {
|
|
37
|
+
surface = "pages";
|
|
38
|
+
detail = "observatory";
|
|
39
|
+
}
|
|
40
|
+
else if (path.startsWith("/api/chat")) {
|
|
41
|
+
surface = "chat";
|
|
42
|
+
}
|
|
43
|
+
else if (path.startsWith("/api/browse") || path.startsWith("/api/search")) {
|
|
44
|
+
surface = "pages";
|
|
45
|
+
detail = "browser";
|
|
46
|
+
}
|
|
47
|
+
recordInteraction({
|
|
48
|
+
timestamp: new Date().toISOString(),
|
|
49
|
+
surface,
|
|
50
|
+
detail,
|
|
51
|
+
});
|
|
52
|
+
await next();
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Middleware: record page views (HTML page loads).
|
|
57
|
+
* Mounted on page routes like /board, /ops, /observatory, etc.
|
|
58
|
+
*/
|
|
59
|
+
export function pageViewTracker(pageName) {
|
|
60
|
+
return async (c, next) => {
|
|
61
|
+
recordInteraction({
|
|
62
|
+
timestamp: new Date().toISOString(),
|
|
63
|
+
surface: "page-view",
|
|
64
|
+
detail: pageName,
|
|
65
|
+
});
|
|
66
|
+
await next();
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Require a minimum posture level for a route group.
|
|
71
|
+
* Returns 404 if the surface isn't assembled yet.
|
|
72
|
+
*/
|
|
73
|
+
export function requireSurface(surface) {
|
|
74
|
+
return async (c, next) => {
|
|
75
|
+
if (!hasSurface(surface)) {
|
|
76
|
+
return c.json({ error: "not_available", posture: "surface not assembled" }, 404);
|
|
77
|
+
}
|
|
78
|
+
await next();
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Add posture info to API responses via header.
|
|
83
|
+
* Clients use this to know what to render.
|
|
84
|
+
*/
|
|
85
|
+
export function postureHeader() {
|
|
86
|
+
return async (c, next) => {
|
|
87
|
+
await next();
|
|
88
|
+
const surface = getSurface();
|
|
89
|
+
c.header("X-Posture-Surface", JSON.stringify(surface));
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/posture/middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Posture — how much UI surface assembles around the user.
|
|
3
|
+
*
|
|
4
|
+
* Three modes:
|
|
5
|
+
* - silent: No UI. Core works in background. Reaches out via chat/SMS/email.
|
|
6
|
+
* - pulse: Three dots only. Tap for drill-down. Zero-to-one interaction.
|
|
7
|
+
* - board: Full visibility. Threads, agents, memory, operations.
|
|
8
|
+
*
|
|
9
|
+
* Posture is orthogonal to tier (capabilities) and bonding (trust).
|
|
10
|
+
* A BYOK user might be silent. A Spawn user might only want pulse.
|
|
11
|
+
* UI is a symptom of unresolved autonomy — buttons exist because
|
|
12
|
+
* Core couldn't handle it alone yet.
|
|
13
|
+
*
|
|
14
|
+
* Posture is observed, not configured. Intent accumulation drives transitions.
|
|
15
|
+
* The system records interaction patterns and adapts surface area.
|
|
16
|
+
*/
|
|
17
|
+
export type PostureName = "silent" | "pulse" | "board";
|
|
18
|
+
export declare const POSTURE_LEVEL: Record<PostureName, number>;
|
|
19
|
+
/** What UI surfaces are available at each posture. */
|
|
20
|
+
export interface PostureSurface {
|
|
21
|
+
/** Chat channel (always available — the minimum) */
|
|
22
|
+
chat: boolean;
|
|
23
|
+
/** Three-dot pulse strip */
|
|
24
|
+
pulse: boolean;
|
|
25
|
+
/** Drill-down panels when tapping dots */
|
|
26
|
+
drilldown: boolean;
|
|
27
|
+
/** Full page views: observatory, ops, board, library, etc. */
|
|
28
|
+
pages: boolean;
|
|
29
|
+
/** Agent task management UI */
|
|
30
|
+
agents: boolean;
|
|
31
|
+
/** Settings/configuration UI */
|
|
32
|
+
settings: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare const POSTURE_SURFACE: Record<PostureName, PostureSurface>;
|
|
35
|
+
/**
|
|
36
|
+
* An interaction signal — recorded every time the user does something.
|
|
37
|
+
* Intent accumulation uses these to decide posture transitions.
|
|
38
|
+
*/
|
|
39
|
+
export interface InteractionSignal {
|
|
40
|
+
timestamp: string;
|
|
41
|
+
/** What surface the user touched */
|
|
42
|
+
surface: keyof PostureSurface | "page-view";
|
|
43
|
+
/** Specific detail — page name, dot tapped, etc. */
|
|
44
|
+
detail?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Posture state — persisted in brain/settings.json alongside other settings.
|
|
48
|
+
*/
|
|
49
|
+
export interface PostureState {
|
|
50
|
+
/** Current posture */
|
|
51
|
+
current: PostureName;
|
|
52
|
+
/** When the posture last changed */
|
|
53
|
+
changedAt: string;
|
|
54
|
+
/** Whether the user explicitly set this (locks auto-transition) */
|
|
55
|
+
pinned: boolean;
|
|
56
|
+
/** Interaction count per surface in the current window */
|
|
57
|
+
interactions: Record<string, number>;
|
|
58
|
+
/** When the interaction window started */
|
|
59
|
+
windowStart: string;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/posture/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAEvD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAIrD,CAAC;AAEF,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,IAAI,EAAE,OAAO,CAAC;IACd,4BAA4B;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAC;IACf,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,gCAAgC;IAChC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,cAAc,CAyB/D,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,OAAO,EAAE,MAAM,cAAc,GAAG,WAAW,CAAC;IAC5C,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sBAAsB;IACtB,OAAO,EAAE,WAAW,CAAC;IACrB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,MAAM,EAAE,OAAO,CAAC;IAChB,0DAA0D;IAC1D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Posture — how much UI surface assembles around the user.
|
|
3
|
+
*
|
|
4
|
+
* Three modes:
|
|
5
|
+
* - silent: No UI. Core works in background. Reaches out via chat/SMS/email.
|
|
6
|
+
* - pulse: Three dots only. Tap for drill-down. Zero-to-one interaction.
|
|
7
|
+
* - board: Full visibility. Threads, agents, memory, operations.
|
|
8
|
+
*
|
|
9
|
+
* Posture is orthogonal to tier (capabilities) and bonding (trust).
|
|
10
|
+
* A BYOK user might be silent. A Spawn user might only want pulse.
|
|
11
|
+
* UI is a symptom of unresolved autonomy — buttons exist because
|
|
12
|
+
* Core couldn't handle it alone yet.
|
|
13
|
+
*
|
|
14
|
+
* Posture is observed, not configured. Intent accumulation drives transitions.
|
|
15
|
+
* The system records interaction patterns and adapts surface area.
|
|
16
|
+
*/
|
|
17
|
+
export const POSTURE_LEVEL = {
|
|
18
|
+
silent: 0,
|
|
19
|
+
pulse: 1,
|
|
20
|
+
board: 2,
|
|
21
|
+
};
|
|
22
|
+
export const POSTURE_SURFACE = {
|
|
23
|
+
silent: {
|
|
24
|
+
chat: true,
|
|
25
|
+
pulse: false,
|
|
26
|
+
drilldown: false,
|
|
27
|
+
pages: false,
|
|
28
|
+
agents: false,
|
|
29
|
+
settings: false,
|
|
30
|
+
},
|
|
31
|
+
pulse: {
|
|
32
|
+
chat: true,
|
|
33
|
+
pulse: true,
|
|
34
|
+
drilldown: true,
|
|
35
|
+
pages: false,
|
|
36
|
+
agents: false,
|
|
37
|
+
settings: false,
|
|
38
|
+
},
|
|
39
|
+
board: {
|
|
40
|
+
chat: true,
|
|
41
|
+
pulse: true,
|
|
42
|
+
drilldown: true,
|
|
43
|
+
pages: true,
|
|
44
|
+
agents: true,
|
|
45
|
+
settings: true,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/posture/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,MAAM,CAAC,MAAM,aAAa,GAAgC;IACxD,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACT,CAAC;AAkBF,MAAM,CAAC,MAAM,eAAe,GAAwC;IAClE,MAAM,EAAE;QACN,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,KAAK;KAChB;IACD,KAAK,EAAE;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,KAAK;KAChB;IACD,KAAK,EAAE;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;KACf;CACF,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* Hono app: serves static UI, handles pairing/auth, streams chat via Ollama (local) or OpenRouter (cloud).
|
|
4
4
|
*/
|
|
5
5
|
export declare function getStartupToken(): string | null;
|
|
6
|
-
declare function start(
|
|
6
|
+
declare function start(opts?: {
|
|
7
|
+
tier?: import("./tier/types.js").TierName;
|
|
8
|
+
}): Promise<void>;
|
|
7
9
|
/** Returns the port the server is actually listening on (resolves port 0). */
|
|
8
10
|
export declare function getActualPort(): number;
|
|
9
11
|
export { start };
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuTH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuTH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AA2gKD,iBAAe,KAAK,CAAC,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,iBAAiB,EAAE,QAAQ,CAAA;CAAE,iBAghBxE;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -406,6 +406,11 @@ app.use("/api/*", async (c, next) => {
|
|
|
406
406
|
}
|
|
407
407
|
return generalLimiter(c, next);
|
|
408
408
|
});
|
|
409
|
+
// --- Posture middleware (intent accumulation + surface gating) ---
|
|
410
|
+
// Track all API interactions for posture engine
|
|
411
|
+
app.use("/api/*", postureTracker());
|
|
412
|
+
// Attach posture surface header to all responses
|
|
413
|
+
app.use("/api/*", postureHeader());
|
|
409
414
|
// --- Webhook initialization (batch registration + config + admin routes) ---
|
|
410
415
|
const webhookInitStart = performance.now();
|
|
411
416
|
// Phase 1: Batch-register all webhook providers (deferred from module imports to avoid
|
|
@@ -2438,6 +2443,10 @@ function issuesToCardPayload(issues) {
|
|
|
2438
2443
|
};
|
|
2439
2444
|
});
|
|
2440
2445
|
}
|
|
2446
|
+
// Board API — gated to board posture
|
|
2447
|
+
app.use("/api/board/*", requireSurface("pages"));
|
|
2448
|
+
app.use("/api/ops/*", requireSurface("pages"));
|
|
2449
|
+
app.use("/api/agents/*", requireSurface("agents"));
|
|
2441
2450
|
// Board status: is a provider configured, and who is the user?
|
|
2442
2451
|
app.get("/api/board/status", async (c) => {
|
|
2443
2452
|
const board = getBoardProvider();
|
|
@@ -3244,33 +3253,29 @@ app.get("/api/help/context", async (c) => {
|
|
|
3244
3253
|
changelog,
|
|
3245
3254
|
});
|
|
3246
3255
|
});
|
|
3247
|
-
// --- Ops dashboard routes (
|
|
3248
|
-
//
|
|
3249
|
-
app.get("/observatory", async (c) => {
|
|
3256
|
+
// --- Ops dashboard routes (posture-gated: board level) ---
|
|
3257
|
+
// Board-level pages — only assembled when user has shown intent for full visibility
|
|
3258
|
+
app.get("/observatory", requireSurface("pages"), async (c) => {
|
|
3250
3259
|
const html = await serveHtmlTemplate(join(PKG_ROOT, "public", "observatory.html"));
|
|
3251
3260
|
return c.html(html);
|
|
3252
3261
|
});
|
|
3253
|
-
|
|
3254
|
-
app.get("/ops", async (c) => {
|
|
3262
|
+
app.get("/ops", requireSurface("pages"), async (c) => {
|
|
3255
3263
|
const html = await serveHtmlTemplate(join(PKG_ROOT, "public", "ops.html"));
|
|
3256
3264
|
return c.html(html);
|
|
3257
3265
|
});
|
|
3258
|
-
|
|
3259
|
-
app.get("/board", async (c) => {
|
|
3266
|
+
app.get("/board", requireSurface("pages"), async (c) => {
|
|
3260
3267
|
const html = await serveHtmlTemplate(join(PKG_ROOT, "public", "board.html"));
|
|
3261
3268
|
return c.html(html);
|
|
3262
3269
|
});
|
|
3263
|
-
|
|
3264
|
-
app.get("/library", async (c) => {
|
|
3270
|
+
app.get("/library", requireSurface("pages"), async (c) => {
|
|
3265
3271
|
const html = await serveHtmlTemplate(join(PKG_ROOT, "public", "library.html"));
|
|
3266
3272
|
return c.html(html);
|
|
3267
3273
|
});
|
|
3268
|
-
|
|
3269
|
-
app.get("/browser", async (c) => {
|
|
3274
|
+
app.get("/browser", requireSurface("pages"), async (c) => {
|
|
3270
3275
|
const html = await serveHtmlTemplate(join(PKG_ROOT, "public", "browser.html"));
|
|
3271
3276
|
return c.html(html);
|
|
3272
3277
|
});
|
|
3273
|
-
//
|
|
3278
|
+
// Registry is always available — it's the entry point
|
|
3274
3279
|
app.get("/registry", async (c) => {
|
|
3275
3280
|
const html = await serveHtmlTemplate(join(PKG_ROOT, "public", "registry.html"));
|
|
3276
3281
|
return c.html(html);
|
|
@@ -3689,6 +3694,30 @@ app.delete("/api/ops/projects/:id", async (c) => {
|
|
|
3689
3694
|
return c.json({ error: "Project not found" }, 404);
|
|
3690
3695
|
return c.json({ ok: true });
|
|
3691
3696
|
});
|
|
3697
|
+
// --- Posture API (UI surface assembly) ---
|
|
3698
|
+
app.get("/api/posture", (c) => {
|
|
3699
|
+
return c.json({
|
|
3700
|
+
posture: getPosture(),
|
|
3701
|
+
surface: getSurface(),
|
|
3702
|
+
state: getPostureState(),
|
|
3703
|
+
});
|
|
3704
|
+
});
|
|
3705
|
+
app.put("/api/posture", async (c) => {
|
|
3706
|
+
const body = await c.req.json();
|
|
3707
|
+
if (body.posture && ["silent", "pulse", "board"].includes(body.posture)) {
|
|
3708
|
+
if (body.pinned !== false) {
|
|
3709
|
+
pinPosture(body.posture);
|
|
3710
|
+
}
|
|
3711
|
+
else {
|
|
3712
|
+
pinPosture(body.posture);
|
|
3713
|
+
unpinPosture();
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3716
|
+
else if (body.pinned === false) {
|
|
3717
|
+
unpinPosture();
|
|
3718
|
+
}
|
|
3719
|
+
return c.json({ posture: getPosture(), surface: getSurface(), state: getPostureState() });
|
|
3720
|
+
});
|
|
3692
3721
|
// --- Pulse (nervous system) endpoint ---
|
|
3693
3722
|
app.get("/api/pulse/status", (c) => {
|
|
3694
3723
|
const integrator = getPressureIntegrator();
|
|
@@ -3707,6 +3736,8 @@ app.get("/api/pulse/history", (c) => {
|
|
|
3707
3736
|
// --- Nerve API (three-dot goo) ---
|
|
3708
3737
|
import { getNerveState } from "./nerve/state.js";
|
|
3709
3738
|
import { initPush, getVapidPublicKey, addSubscription, checkAndNotify, startPushMonitor, stopPushMonitor } from "./nerve/push.js";
|
|
3739
|
+
import { loadPosture, startDecayTimer, getPosture, getPostureState, getSurface, pinPosture, unpinPosture, } from "./posture/engine.js";
|
|
3740
|
+
import { postureTracker, requireSurface, postureHeader } from "./posture/middleware.js";
|
|
3710
3741
|
// State endpoint — three dots
|
|
3711
3742
|
app.get("/api/nerve/state", async (c) => {
|
|
3712
3743
|
const state = await getNerveState();
|
|
@@ -4781,8 +4812,111 @@ app.post("/api/chat", async (c) => {
|
|
|
4781
4812
|
});
|
|
4782
4813
|
});
|
|
4783
4814
|
});
|
|
4815
|
+
// --- Freeze endpoint (operator clicks freeze link) ---
|
|
4816
|
+
app.post("/api/freeze", async (c) => {
|
|
4817
|
+
const body = await c.req.json().catch(() => null);
|
|
4818
|
+
if (!body?.signal)
|
|
4819
|
+
return c.json({ error: "Missing freeze signal" }, 400);
|
|
4820
|
+
const { freeze, isFrozen } = await import("./tier/freeze.js");
|
|
4821
|
+
if (isFrozen())
|
|
4822
|
+
return c.json({ error: "Already frozen" }, 409);
|
|
4823
|
+
await freeze(body.signal, process.cwd());
|
|
4824
|
+
return c.json({ status: "frozen", message: "All agents dormant." });
|
|
4825
|
+
});
|
|
4826
|
+
app.post("/api/thaw", async (c) => {
|
|
4827
|
+
const { thaw } = await import("./tier/freeze.js");
|
|
4828
|
+
await thaw(process.cwd());
|
|
4829
|
+
return c.json({ status: "thawed", message: "Operations resuming." });
|
|
4830
|
+
});
|
|
4831
|
+
app.get("/api/freeze/status", async (c) => {
|
|
4832
|
+
const { isFrozen, getFreezeSignal } = await import("./tier/freeze.js");
|
|
4833
|
+
return c.json({ frozen: isFrozen(), signal: getFreezeSignal() });
|
|
4834
|
+
});
|
|
4835
|
+
// --- Brain import API ---
|
|
4836
|
+
app.post("/api/import/folder", async (c) => {
|
|
4837
|
+
const body = await c.req.json();
|
|
4838
|
+
if (!body.paths || !Array.isArray(body.paths) || body.paths.length === 0) {
|
|
4839
|
+
return c.json({ error: "paths[] required" }, 400);
|
|
4840
|
+
}
|
|
4841
|
+
const { resolve } = await import("node:path");
|
|
4842
|
+
const { importToBrain } = await import("./files/import.js");
|
|
4843
|
+
const result = await importToBrain({
|
|
4844
|
+
sources: body.paths.map(p => resolve(p)),
|
|
4845
|
+
brainRoot: process.cwd(),
|
|
4846
|
+
dryRun: body.dryRun ?? false,
|
|
4847
|
+
});
|
|
4848
|
+
// After import: fast pass → deep pass (both background, chained)
|
|
4849
|
+
if (!body.dryRun && result.imported > 0) {
|
|
4850
|
+
import("./files/index-local.js").then(({ indexImportedFiles }) => {
|
|
4851
|
+
indexImportedFiles({ localOnly: true })
|
|
4852
|
+
.then(() => import("./files/deep-index.js"))
|
|
4853
|
+
.then(({ runDeepIndex }) => runDeepIndex())
|
|
4854
|
+
.catch(() => { });
|
|
4855
|
+
});
|
|
4856
|
+
}
|
|
4857
|
+
return c.json(result);
|
|
4858
|
+
});
|
|
4859
|
+
app.post("/api/import/index", async (c) => {
|
|
4860
|
+
const { indexImportedFiles } = await import("./files/index-local.js");
|
|
4861
|
+
const result = await indexImportedFiles({ localOnly: true });
|
|
4862
|
+
// After fast pass, kick off deep index in background
|
|
4863
|
+
import("./files/deep-index.js").then(({ runDeepIndex }) => {
|
|
4864
|
+
runDeepIndex().catch(() => { });
|
|
4865
|
+
});
|
|
4866
|
+
return c.json(result);
|
|
4867
|
+
});
|
|
4868
|
+
app.post("/api/import/deep-index", async (c) => {
|
|
4869
|
+
const { runDeepIndex } = await import("./files/deep-index.js");
|
|
4870
|
+
const result = await runDeepIndex();
|
|
4871
|
+
return c.json(result);
|
|
4872
|
+
});
|
|
4873
|
+
app.get("/api/import/deep-index/progress", async (c) => {
|
|
4874
|
+
const { getDeepIndexProgress } = await import("./files/deep-index.js");
|
|
4875
|
+
return c.json(getDeepIndexProgress());
|
|
4876
|
+
});
|
|
4877
|
+
app.get("/api/import/deep-index/results", async (c) => {
|
|
4878
|
+
const { readFile: rf } = await import("node:fs/promises");
|
|
4879
|
+
const { join: jp } = await import("node:path");
|
|
4880
|
+
try {
|
|
4881
|
+
const raw = await rf(jp(process.cwd(), "brain", ".core", "deep-index.json"), "utf-8");
|
|
4882
|
+
return c.json(JSON.parse(raw));
|
|
4883
|
+
}
|
|
4884
|
+
catch {
|
|
4885
|
+
return c.json({ entities: [], themes: [], crossRefs: [], flags: [], deepIndexed: [] });
|
|
4886
|
+
}
|
|
4887
|
+
});
|
|
4888
|
+
app.post("/api/import/files", async (c) => {
|
|
4889
|
+
const formData = await c.req.formData();
|
|
4890
|
+
const files = formData.getAll("files");
|
|
4891
|
+
if (files.length === 0)
|
|
4892
|
+
return c.json({ error: "No files provided" }, 400);
|
|
4893
|
+
const { mkdir: mkdirFs, writeFile: writeFs } = await import("node:fs/promises");
|
|
4894
|
+
const { join: joinPath } = await import("node:path");
|
|
4895
|
+
const ingestDir = joinPath(process.cwd(), "ingest");
|
|
4896
|
+
await mkdirFs(ingestDir, { recursive: true });
|
|
4897
|
+
const saved = [];
|
|
4898
|
+
for (const file of files) {
|
|
4899
|
+
if (!file.name)
|
|
4900
|
+
continue;
|
|
4901
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
4902
|
+
const dest = joinPath(ingestDir, file.name);
|
|
4903
|
+
await writeFs(dest, buffer);
|
|
4904
|
+
saved.push(file.name);
|
|
4905
|
+
}
|
|
4906
|
+
// Process the ingest folder immediately
|
|
4907
|
+
const { processIngestFolder } = await import("./files/ingest-folder.js");
|
|
4908
|
+
const ingestedDir = joinPath(process.cwd(), "ingested");
|
|
4909
|
+
const result = await processIngestFolder(ingestDir, ingestedDir);
|
|
4910
|
+
return c.json({
|
|
4911
|
+
saved: saved.length,
|
|
4912
|
+
files: saved,
|
|
4913
|
+
ingested: result.newFiles,
|
|
4914
|
+
});
|
|
4915
|
+
});
|
|
4784
4916
|
// --- Startup ---
|
|
4785
|
-
async function start() {
|
|
4917
|
+
async function start(opts) {
|
|
4918
|
+
const tier = opts?.tier ?? "byok";
|
|
4919
|
+
const tierGate = await import("./tier/gate.js");
|
|
4786
4920
|
// Initialize instance name before anything else
|
|
4787
4921
|
initInstanceName();
|
|
4788
4922
|
// Initialize OpenTelemetry tracing (must be early, before instrumented code)
|
|
@@ -4793,6 +4927,9 @@ async function start() {
|
|
|
4793
4927
|
});
|
|
4794
4928
|
// Load settings (airplane mode, model selection)
|
|
4795
4929
|
const settings = await loadSettings();
|
|
4930
|
+
// Initialize posture system (UI surface assembly)
|
|
4931
|
+
await loadPosture();
|
|
4932
|
+
startDecayTimer();
|
|
4796
4933
|
// Install fetch guard before any routes or outbound calls
|
|
4797
4934
|
installFetchGuard();
|
|
4798
4935
|
// Initialize PrivacyMembrane for reversible redaction
|
|
@@ -4963,17 +5100,24 @@ async function start() {
|
|
|
4963
5100
|
logActivity({ source: "agent", summary: `Continuation error: ${msg}` });
|
|
4964
5101
|
}
|
|
4965
5102
|
});
|
|
4966
|
-
// Initialize
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
5103
|
+
// Initialize agent spawning — tier >= spawn only
|
|
5104
|
+
if (tierGate.canSpawn(tier)) {
|
|
5105
|
+
// Initialize instance manager (GC, health checks, load balancing)
|
|
5106
|
+
instanceManager = new AgentInstanceManager(runtime);
|
|
5107
|
+
await instanceManager.init();
|
|
5108
|
+
// Initialize agent pool (circuit breakers, isolation, resource management)
|
|
5109
|
+
agentPool = AgentPool.fromExisting(runtime, instanceManager);
|
|
5110
|
+
setAgentPool(agentPool);
|
|
5111
|
+
// Initialize workflow engine for multi-agent coordination
|
|
5112
|
+
workflowEngine = new WorkflowEngine(agentPool);
|
|
5113
|
+
await workflowEngine.loadAllDefinitions().catch((err) => {
|
|
5114
|
+
log.warn("Failed to load workflow definitions", { error: err instanceof Error ? err.message : String(err) });
|
|
5115
|
+
});
|
|
5116
|
+
log.info(`Agent spawning enabled (tier: ${tier})`);
|
|
5117
|
+
}
|
|
5118
|
+
else {
|
|
5119
|
+
log.info(`Agent spawning disabled (tier: ${tier} — requires spawn tier)`);
|
|
5120
|
+
}
|
|
4977
5121
|
// --- Register component health checks (after all systems initialized) ---
|
|
4978
5122
|
// Queue store: can we read the JSONL file?
|
|
4979
5123
|
health.register("queue", queueStoreCheck(() => queueProvider.getStore()), { critical: false });
|
|
@@ -4997,25 +5141,27 @@ async function start() {
|
|
|
4997
5141
|
recovery.start();
|
|
4998
5142
|
// Start alert evaluation loop (evaluates every 30s)
|
|
4999
5143
|
alertManager.start();
|
|
5000
|
-
// Wire notification channels —
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5144
|
+
// Wire notification channels — tier >= byok only (requires BYOK API keys)
|
|
5145
|
+
if (tierGate.canAlert(tier)) {
|
|
5146
|
+
const resendKey = process.env.RESEND_API_KEY;
|
|
5147
|
+
if (resendKey) {
|
|
5148
|
+
alertDispatcher.add(new EmailChannel({
|
|
5149
|
+
endpoint: "https://api.resend.com/emails",
|
|
5150
|
+
apiKey: resendKey,
|
|
5151
|
+
from: `${getInstanceName()} <${getAlertEmailFrom()}>`,
|
|
5152
|
+
to: [resolveEnv("ALERT_EMAIL_TO") ?? ""].filter(Boolean),
|
|
5153
|
+
}));
|
|
5154
|
+
log.info("Alert channel: email (Resend)");
|
|
5155
|
+
}
|
|
5156
|
+
if (process.env.TWILIO_ACCOUNT_SID) {
|
|
5157
|
+
alertDispatcher.add(new PhoneChannel());
|
|
5158
|
+
log.info("Alert channel: phone (Twilio voice)");
|
|
5159
|
+
}
|
|
5160
|
+
alertManager.updateNotifications([
|
|
5161
|
+
{ channel: "email", minSeverity: "warning" },
|
|
5162
|
+
{ channel: "phone", minSeverity: "critical" },
|
|
5163
|
+
]);
|
|
5164
|
+
}
|
|
5019
5165
|
// Start credit monitoring (checks every 5 min, configurable via CORE_CREDIT_CHECK_INTERVAL_MS)
|
|
5020
5166
|
startCreditMonitor(health, alertManager);
|
|
5021
5167
|
// Avatar sidecar launches in background — slow (model loading) but non-blocking
|
|
@@ -5238,8 +5384,8 @@ async function start() {
|
|
|
5238
5384
|
});
|
|
5239
5385
|
}
|
|
5240
5386
|
catch { /* ok */ }
|
|
5241
|
-
// Announce on LAN if mesh.lanAnnounce is enabled
|
|
5242
|
-
if (getMeshConfig().lanAnnounce) {
|
|
5387
|
+
// Announce on LAN if mesh.lanAnnounce is enabled AND tier >= byok
|
|
5388
|
+
if (tierGate.canMesh(tier) && getMeshConfig().lanAnnounce) {
|
|
5243
5389
|
try {
|
|
5244
5390
|
startMdns(actualPort);
|
|
5245
5391
|
}
|