@wrongstack/webui-server 0.301.0 → 0.302.2
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/index.js +436 -187
- package/dist/server/connections-health-route.d.ts +2 -2
- package/dist/server/conversation-operations.d.ts +9 -4
- package/dist/server/embedded-host-adapters.d.ts +7 -5
- package/dist/server/embedded-lifecycle.d.ts +17 -2
- package/dist/server/entry.js +615 -143
- package/dist/server/index.d.ts +1 -1
- package/dist/server/instance-registry.d.ts +51 -2
- package/dist/server/kanban-routes.d.ts +8 -0
- package/dist/server/kanban-supervisor.d.ts +1 -1
- package/dist/server/lifecycle.d.ts +7 -0
- package/dist/server/message-dispatcher.d.ts +10 -0
- package/dist/server/server-runtime.d.ts +8 -1
- package/dist/server/session-handlers.d.ts +3 -2
- package/dist/server/standalone-session-identity.d.ts +10 -2
- package/package.json +11 -11
package/dist/server/index.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export { type HostRouteHandlers, handleHostRoute } from './host-routes.js';
|
|
|
42
42
|
export { clearAnalyticsBuffer, getAnalyticsBuffer, handleApiAnalyticsGet, handleApiAnalyticsPost, handleApiAnalyticsSummary, } from './http-server/analytics-handler.js';
|
|
43
43
|
export type { CreateHttpServerOptions } from './http-server.js';
|
|
44
44
|
export { buildCspHeader, createHttpServer, decodeSessionId, injectWsConfig, isInsideDist, } from './http-server.js';
|
|
45
|
-
export { defaultBaseDir, formatInstances, isPidAlive, listInstances, registerInstance, registryPath, unregisterInstance, type WebUIInstanceRecord, } from './instance-registry.js';
|
|
45
|
+
export { defaultBaseDir, formatInstances, isPidAlive, joinSessionRegistryWithWebUIInstances, listInstances, registerInstance, registryPath, unregisterInstance, type WebUIInstanceAuthInfo, type WebUIInstanceRecord, type WebUIInstanceRole, type WebUISessionAttachCandidate, type WebUISessionAttachDegradedReason, type WebUISessionAttachEndpoint, } from './instance-registry.js';
|
|
46
46
|
export { handleIntrospectionRoute, type IntrospectionRouteContext, } from './introspection-routes.js';
|
|
47
47
|
export { handleKanbanTaskDispatch, type KanbanDispatchContext, type KanbanDispatchResult, type KanbanTaskDispatcher, parseResolvedDispatchRoute, type ResolvedDispatchRoute, } from './kanban-dispatch.js';
|
|
48
48
|
export { handleKanbanHostRoute, type KanbanHostRouteHandlers } from './kanban-host-routes.js';
|
|
@@ -18,12 +18,20 @@
|
|
|
18
18
|
* - **Best-effort**: a failure to read/write the registry must NEVER take the
|
|
19
19
|
* server down. Callers wrap these in `.catch()`.
|
|
20
20
|
*/
|
|
21
|
+
import type { SessionRegistryEntry, SessionLiveStatus } from '@wrongstack/core/storage';
|
|
22
|
+
export type WebUIInstanceRole = 'standalone' | 'parent-shell' | 'session-child';
|
|
23
|
+
export interface WebUIInstanceAuthInfo {
|
|
24
|
+
/** How a same-user parent/sibling process can authenticate to this endpoint. */
|
|
25
|
+
scheme: 'registry-token' | 'cookie-bootstrap' | 'none';
|
|
26
|
+
/** Whether the record has a usable token in `authToken`. */
|
|
27
|
+
tokenPresent: boolean;
|
|
28
|
+
}
|
|
21
29
|
/** One running WebUI / SimpleUI process. */
|
|
22
30
|
export interface WebUIInstanceRecord {
|
|
23
31
|
/** OS process id — also the liveness key. */
|
|
24
32
|
pid: number;
|
|
25
|
-
/** Surface kind — 'webui' or 'simpleui'. */
|
|
26
|
-
surface: 'webui' | 'simpleui';
|
|
33
|
+
/** Surface kind — 'webui' or 'simpleui'. Additional strings are tolerated for new surfaces. */
|
|
34
|
+
surface: 'webui' | 'simpleui' | string;
|
|
27
35
|
/** Port serving both HTTP and WebSocket. */
|
|
28
36
|
httpPort: number;
|
|
29
37
|
/** Bind host (e.g. 127.0.0.1 or 0.0.0.0). */
|
|
@@ -57,7 +65,48 @@ export interface WebUIInstanceRecord {
|
|
|
57
65
|
* Optional so an older record (or a surface that has no token) still parses.
|
|
58
66
|
*/
|
|
59
67
|
authToken?: string | undefined;
|
|
68
|
+
/** Runtime role. Missing means the legacy standalone WebUI/SimpleUI role. */
|
|
69
|
+
role?: WebUIInstanceRole | undefined;
|
|
70
|
+
/** Live session owned by this endpoint when `role === 'session-child'`. */
|
|
71
|
+
sessionId?: string | undefined;
|
|
72
|
+
/** Parent shell process identity, when this endpoint was spawned by a parent. */
|
|
73
|
+
parentPid?: number | undefined;
|
|
74
|
+
parentShellId?: string | undefined;
|
|
75
|
+
/** Stable child runtime id, distinct from the session id. */
|
|
76
|
+
runtimeId?: string | undefined;
|
|
77
|
+
/** Whether a parent shell should treat this endpoint as attachable. */
|
|
78
|
+
attachable?: boolean | undefined;
|
|
79
|
+
/** Descriptive auth metadata; the same-user token remains in `authToken`. */
|
|
80
|
+
auth?: WebUIInstanceAuthInfo | undefined;
|
|
81
|
+
/** Health/protocol hints for future parent shells. */
|
|
82
|
+
lastReadyAt?: string | undefined;
|
|
83
|
+
protocolVersion?: number | undefined;
|
|
84
|
+
capabilities?: string[] | undefined;
|
|
85
|
+
}
|
|
86
|
+
export interface WebUISessionAttachEndpoint {
|
|
87
|
+
host: string;
|
|
88
|
+
httpPort: number;
|
|
89
|
+
url: string;
|
|
90
|
+
authToken?: string | undefined;
|
|
91
|
+
}
|
|
92
|
+
export type WebUISessionAttachDegradedReason = 'live-session-no-webui-endpoint' | 'endpoint-owner-mismatch' | 'endpoint-missing-session-id' | 'endpoint-session-mismatch' | 'endpoint-not-session-child' | 'endpoint-not-attachable' | 'session-not-live';
|
|
93
|
+
export interface WebUISessionAttachCandidate {
|
|
94
|
+
sessionId: string;
|
|
95
|
+
projectRoot: string;
|
|
96
|
+
workingDir: string;
|
|
97
|
+
sessionPid: number;
|
|
98
|
+
status: SessionLiveStatus;
|
|
99
|
+
instance?: WebUIInstanceRecord | undefined;
|
|
100
|
+
endpoint?: WebUISessionAttachEndpoint | undefined;
|
|
101
|
+
attachable: boolean;
|
|
102
|
+
degradedReason?: WebUISessionAttachDegradedReason | undefined;
|
|
60
103
|
}
|
|
104
|
+
export declare function joinSessionRegistryWithWebUIInstances(input: {
|
|
105
|
+
sessions: SessionRegistryEntry[];
|
|
106
|
+
instances: WebUIInstanceRecord[];
|
|
107
|
+
projectRoot?: string | undefined;
|
|
108
|
+
projectSlug?: string | undefined;
|
|
109
|
+
}): WebUISessionAttachCandidate[];
|
|
61
110
|
/** Default wstack home dir (`~/.wrongstack`). Callers may override the base. */
|
|
62
111
|
export declare function defaultBaseDir(): string;
|
|
63
112
|
/** Resolve the registry file path for a given base dir. */
|
|
@@ -2,6 +2,7 @@ import type { Context } from '@wrongstack/core/agent';
|
|
|
2
2
|
import type { WebSocket } from 'ws';
|
|
3
3
|
import type { WSClientMessage, WSServerMessage } from './types.js';
|
|
4
4
|
import { type KanbanTaskDispatcher } from './kanban-dispatch.js';
|
|
5
|
+
import type { KanbanSupervisor } from './kanban-supervisor.js';
|
|
5
6
|
export { KANBAN_CLIENT_MESSAGE_TYPES } from './kanban-route-protocol.js';
|
|
6
7
|
export { paginateKanbanBoards, type KanbanBoardPage } from './kanban-route-pagination.js';
|
|
7
8
|
export interface KanbanRouteContext {
|
|
@@ -9,6 +10,13 @@ export interface KanbanRouteContext {
|
|
|
9
10
|
context?: Context | undefined;
|
|
10
11
|
broadcast?: ((msg: WSServerMessage) => void) | undefined;
|
|
11
12
|
dispatchTask?: KanbanTaskDispatcher | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Background supervisor (if enabled). When present, the `kanban.supervisor.audit`
|
|
15
|
+
* and `kanban.supervisor.status` routes delegate to its in-process audit cycle
|
|
16
|
+
* instead of running a second reconcile/health/recover chain — preventing the
|
|
17
|
+
* double-audit that happens when both paths refresh the same board concurrently.
|
|
18
|
+
*/
|
|
19
|
+
supervisor?: KanbanSupervisor | undefined;
|
|
12
20
|
}
|
|
13
21
|
export declare function handleKanbanRoute(ws: WebSocket, msg: WSClientMessage, ctx: KanbanRouteContext): Promise<boolean>;
|
|
14
22
|
//# sourceMappingURL=kanban-routes.d.ts.map
|
|
@@ -25,7 +25,7 @@ export interface KanbanSupervisorDispatchOptions {
|
|
|
25
25
|
}) => void | Promise<void>) | undefined;
|
|
26
26
|
}
|
|
27
27
|
export interface KanbanSupervisorDeps {
|
|
28
|
-
projectRoot: string;
|
|
28
|
+
projectRoot: string | (() => string);
|
|
29
29
|
broadcast: (message: {
|
|
30
30
|
type: string;
|
|
31
31
|
payload: unknown;
|
|
@@ -38,6 +38,13 @@ export interface LifecycleResources {
|
|
|
38
38
|
* logged, never thrown — cleanup must not block a clean shutdown.
|
|
39
39
|
*/
|
|
40
40
|
onShutdown?: (() => Promise<void> | void) | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Fires **before** any HTTP/WS servers close. Use this for cleanup that must
|
|
43
|
+
* finish while the network is still up — e.g. telling a Kanban supervisor
|
|
44
|
+
* to flush its periodic tick so no in-flight `kanban.*` broadcast races a
|
|
45
|
+
* `WebSocketServer.close()`.
|
|
46
|
+
*/
|
|
47
|
+
onPreShutdown?: (() => Promise<void> | void) | undefined;
|
|
41
48
|
/** Output sink. Defaults to `console.log`. */
|
|
42
49
|
log?: ((msg: string) => void) | undefined;
|
|
43
50
|
/** Process exit. Defaults to `process.exit`. Injectable for tests. */
|
|
@@ -29,6 +29,9 @@ import type { ConnectedClient, WSClientMessage } from './types.js';
|
|
|
29
29
|
interface RunLockControl {
|
|
30
30
|
get(): AbortController | null;
|
|
31
31
|
set(ctrl: AbortController | null): void;
|
|
32
|
+
/** Session ID that owns the active run, or null when idle. */
|
|
33
|
+
getSession(): string | null;
|
|
34
|
+
setSession(id: string | null): void;
|
|
32
35
|
}
|
|
33
36
|
interface MessageDispatcherOptions {
|
|
34
37
|
state: WebuiMutableState;
|
|
@@ -47,6 +50,13 @@ interface MessageDispatcherOptions {
|
|
|
47
50
|
runLock: RunLockControl;
|
|
48
51
|
/** Pending permission confirmations — tool.confirm_result resolves one. */
|
|
49
52
|
pendingConfirms: Map<string, PendingConfirm>;
|
|
53
|
+
/**
|
|
54
|
+
* Caller-supplied register hook. The dispatcher calls this **once** during
|
|
55
|
+
* construction to hand its disposer to the caller. The caller is
|
|
56
|
+
* responsible for invoking the registered disposer during its own shutdown
|
|
57
|
+
* — the dispatcher itself never invokes the disposer.
|
|
58
|
+
*/
|
|
59
|
+
onDispose?: ((disposer: () => void) => void) | undefined;
|
|
50
60
|
}
|
|
51
61
|
/**
|
|
52
62
|
* Build the inbound message dispatcher. Mirrors the `handleMessage` closure
|
|
@@ -110,8 +110,15 @@ interface ShutdownDeps {
|
|
|
110
110
|
flushSession: () => Promise<void>;
|
|
111
111
|
clients: () => IterableIterator<WebSocket>;
|
|
112
112
|
servers: Array<import('node:http').Server | WebSocketServer>;
|
|
113
|
+
/**
|
|
114
|
+
* Fires **before** any HTTP/WS servers close. Use this for cleanup that must
|
|
115
|
+
* finish while the network is still up — e.g. telling a Kanban supervisor
|
|
116
|
+
* to flush its periodic tick so no in-flight `kanban.*` broadcast races a
|
|
117
|
+
* `WebSocketServer.close()`.
|
|
118
|
+
*/
|
|
119
|
+
onPreShutdown?: () => Promise<void> | void;
|
|
113
120
|
onShutdown: () => Promise<void> | void;
|
|
114
121
|
}
|
|
115
|
-
export declare function registerShutdown(deps: ShutdownDeps): void;
|
|
122
|
+
export declare function registerShutdown(deps: ShutdownDeps): () => void;
|
|
116
123
|
export {};
|
|
117
124
|
//# sourceMappingURL=server-runtime.d.ts.map
|
|
@@ -80,8 +80,9 @@ export interface SessionHandlersContext {
|
|
|
80
80
|
* swapped. Without this, a run started in the previous session keeps
|
|
81
81
|
* streaming/tool-calling in the background after session.new/resume.
|
|
82
82
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
/** When sessionId is provided, abort only that session's run; otherwise abort all. */
|
|
84
|
+
abortActiveRun?: ((sessionId?: string) => void) | undefined;
|
|
85
|
+
isRunActive?: ((sessionId?: string) => boolean) | undefined;
|
|
85
86
|
sessionStartPayload: (overrides?: Record<string, unknown>) => Promise<SessionStartPayload>;
|
|
86
87
|
}
|
|
87
88
|
export declare function createSessionHandlers(ctx: SessionHandlersContext): SessionRouteHandlers;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EventBus } from '@wrongstack/core/kernel';
|
|
2
|
-
import { AgentStatusTracker,
|
|
2
|
+
import { AgentStatusTracker, getSessionRegistry } from '@wrongstack/core/storage';
|
|
3
3
|
import type { Config, Logger } from '@wrongstack/core/types';
|
|
4
4
|
export interface StandaloneSessionIdentityPaths {
|
|
5
5
|
globalRoot: string;
|
|
@@ -13,10 +13,17 @@ export interface StandaloneSessionIdentityOptions {
|
|
|
13
13
|
paths: StandaloneSessionIdentityPaths;
|
|
14
14
|
workingDir: string;
|
|
15
15
|
initialSessionId: string;
|
|
16
|
-
sessionRegistry?:
|
|
16
|
+
sessionRegistry?: SessionIdentityRegistry | undefined;
|
|
17
17
|
/** Test/embedding escape hatch; production defaults to enabled. */
|
|
18
18
|
enableHqTelemetry?: boolean | undefined;
|
|
19
19
|
}
|
|
20
|
+
interface SessionIdentityRegistry {
|
|
21
|
+
register(entry: Parameters<ReturnType<typeof getSessionRegistry>['register']>[0]): Promise<void>;
|
|
22
|
+
updateAgents(agents: Parameters<ReturnType<typeof getSessionRegistry>['updateAgents']>[0]): Promise<void>;
|
|
23
|
+
markClosing(): Promise<void>;
|
|
24
|
+
unregister(): Promise<void>;
|
|
25
|
+
reserveResume?: ReturnType<typeof getSessionRegistry>['reserveResume'] | undefined;
|
|
26
|
+
}
|
|
20
27
|
export interface SessionIdentityTarget {
|
|
21
28
|
projectSlug: string;
|
|
22
29
|
projectRoot: string;
|
|
@@ -37,4 +44,5 @@ export interface StandaloneSessionIdentityLifecycle {
|
|
|
37
44
|
* external surface is fail-soft, while identity selection itself stays live.
|
|
38
45
|
*/
|
|
39
46
|
export declare function createStandaloneSessionIdentityLifecycle(opts: StandaloneSessionIdentityOptions): Promise<StandaloneSessionIdentityLifecycle>;
|
|
47
|
+
export {};
|
|
40
48
|
//# sourceMappingURL=standalone-session-identity.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/webui-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.302.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack WebUI HTTP/WebSocket server module — extracted from @wrongstack/webui in PR #243/244 to remove the CLI -> @wrongstack/webui/server cross-package edge (audit §3.1.1). Pure backend: HTTP routes, WebSocket handlers, MCP tool wrappers, HTML serving. The web frontend lives in @wrongstack/webui; this package is the standalone server it can run on.",
|
|
6
6
|
"keywords": [
|
|
@@ -40,16 +40,16 @@
|
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"ws": "^8.21.1",
|
|
43
|
-
"@wrongstack/core": "0.
|
|
44
|
-
"@wrongstack/
|
|
45
|
-
"@wrongstack/mcp": "0.
|
|
46
|
-
"@wrongstack/
|
|
47
|
-
"@wrongstack/
|
|
48
|
-
"@wrongstack/sage": "0.
|
|
49
|
-
"@wrongstack/
|
|
50
|
-
"@wrongstack/runtime": "0.
|
|
51
|
-
"@wrongstack/
|
|
52
|
-
"@wrongstack/tools": "0.
|
|
43
|
+
"@wrongstack/core": "0.302.2",
|
|
44
|
+
"@wrongstack/sdd": "0.302.2",
|
|
45
|
+
"@wrongstack/mcp": "0.302.2",
|
|
46
|
+
"@wrongstack/providers": "0.302.2",
|
|
47
|
+
"@wrongstack/kanban": "0.302.2",
|
|
48
|
+
"@wrongstack/sage": "0.302.2",
|
|
49
|
+
"@wrongstack/requirement-intake": "0.302.2",
|
|
50
|
+
"@wrongstack/runtime": "0.302.2",
|
|
51
|
+
"@wrongstack/techstack": "0.302.2",
|
|
52
|
+
"@wrongstack/tools": "0.302.2"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^26.1.2",
|