@wrongstack/webui-server 0.302.2 → 0.305.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/dist/index.js +661 -340
- package/dist/protocol/client-integrations.d.ts +1 -1
- package/dist/protocol/index.js +2 -0
- package/dist/protocol/registry.d.ts +2 -2
- package/dist/protocol/server-integrations.d.ts +1 -1
- package/dist/server/agent-roster-handlers.d.ts +7 -6
- package/dist/server/backend-services.d.ts +5 -0
- package/dist/server/codemap-cache.d.ts +13 -1
- package/dist/server/entry.js +637 -336
- package/dist/server/handlers/worklist-handlers.d.ts +23 -4
- package/dist/server/handlers.js +126 -23
- package/dist/server/kanban-contract-routes.d.ts +8 -0
- package/dist/server/kanban-route-protocol.d.ts +1 -1
- package/dist/server/kanban-routes.d.ts +2 -2
- package/dist/server/memory-handlers.d.ts +6 -0
- package/dist/server/mode-handlers.d.ts +2 -2
- package/dist/server/pre-context-services.d.ts +1 -1
- package/dist/server/server-runtime.d.ts +14 -2
- package/dist/server/setup-events-status-watcher.d.ts +1 -1
- package/dist/server/ws-utils.d.ts +1 -1
- package/package.json +11 -11
|
@@ -12,22 +12,41 @@ export interface WorklistContext {
|
|
|
12
12
|
send: (ws: WebSocket, msg: WSServerMessage) => void;
|
|
13
13
|
broadcast: (msg: WSServerMessage) => void;
|
|
14
14
|
replaceTodos?: ((todos: TodoItem[]) => void) | undefined;
|
|
15
|
+
mutateTodos?: ((todos: TodoItem[]) => Promise<{
|
|
16
|
+
todos: TodoItem[];
|
|
17
|
+
warnings?: string[] | undefined;
|
|
18
|
+
}>) | undefined;
|
|
19
|
+
mutateTaskStatus?: ((id: string, status: 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed') => Promise<{
|
|
20
|
+
ok: boolean;
|
|
21
|
+
message: string;
|
|
22
|
+
}>) | undefined;
|
|
23
|
+
mutatePlan?: ((operation: {
|
|
24
|
+
action: 'template_use';
|
|
25
|
+
template: string;
|
|
26
|
+
} | {
|
|
27
|
+
action: 'status';
|
|
28
|
+
target: string;
|
|
29
|
+
status: 'open' | 'in_progress' | 'done';
|
|
30
|
+
}) => Promise<{
|
|
31
|
+
ok: boolean;
|
|
32
|
+
message: string;
|
|
33
|
+
}>) | undefined;
|
|
15
34
|
}
|
|
16
35
|
export interface WorklistMessage {
|
|
17
36
|
type: string;
|
|
18
37
|
payload?: unknown;
|
|
19
38
|
}
|
|
20
39
|
export declare function handleTodosGet(ctx: WorklistContext, ws: WebSocket): void;
|
|
21
|
-
export declare function handleTodosClear(ctx: WorklistContext, ws: WebSocket): void
|
|
40
|
+
export declare function handleTodosClear(ctx: WorklistContext, ws: WebSocket): Promise<void>;
|
|
22
41
|
export declare function handleTodosRemove(ctx: WorklistContext, ws: WebSocket, payload: {
|
|
23
42
|
id?: string | undefined;
|
|
24
43
|
index?: number | undefined;
|
|
25
|
-
} | undefined): void
|
|
44
|
+
} | undefined): Promise<void>;
|
|
26
45
|
export declare function handleTodoUpdate(ctx: WorklistContext, ws: WebSocket, payload: {
|
|
27
|
-
id
|
|
46
|
+
id?: string | undefined;
|
|
28
47
|
status?: TodoItem['status'] | undefined;
|
|
29
48
|
activeForm?: string | undefined;
|
|
30
|
-
}): void
|
|
49
|
+
} | undefined): Promise<void>;
|
|
31
50
|
export declare function handleTasksGet(ctx: WorklistContext, ws: WebSocket): Promise<void>;
|
|
32
51
|
export declare function handleTaskUpdate(ctx: WorklistContext, ws: WebSocket, payload: {
|
|
33
52
|
id: string;
|
package/dist/server/handlers.js
CHANGED
|
@@ -55,12 +55,34 @@ function handleTodosGet(ctx, ws) {
|
|
|
55
55
|
payload: sessionPayload(ctx, { todos: [...ctx.context.todos] })
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
|
-
function
|
|
59
|
-
ctx.
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
async function commitTodos(ctx, todos) {
|
|
59
|
+
if (ctx.mutateTodos) {
|
|
60
|
+
const result = await ctx.mutateTodos(todos);
|
|
61
|
+
return { todos: result.todos, warnings: result.warnings ?? [] };
|
|
62
|
+
}
|
|
63
|
+
ctx.replaceTodos?.(todos);
|
|
64
|
+
return { todos: [...todos], warnings: [] };
|
|
65
|
+
}
|
|
66
|
+
function managedProjectionMessage() {
|
|
67
|
+
return "Kanban-bound todos are task projections. Change or remove the task from Kanban.";
|
|
62
68
|
}
|
|
63
|
-
function
|
|
69
|
+
async function handleTodosClear(ctx, ws) {
|
|
70
|
+
if (ctx.context.todos.some((todo) => todo.kanbanBoardId && todo.kanbanTaskId)) {
|
|
71
|
+
sendResult(ctx, ws, false, managedProjectionMessage());
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const result = await commitTodos(ctx, []);
|
|
76
|
+
sendResult(ctx, ws, true, "Todos cleared");
|
|
77
|
+
ctx.broadcast({
|
|
78
|
+
type: "todos.updated",
|
|
79
|
+
payload: sessionPayload(ctx, { todos: result.todos })
|
|
80
|
+
});
|
|
81
|
+
} catch (error) {
|
|
82
|
+
sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function handleTodosRemove(ctx, ws, payload) {
|
|
64
86
|
if (!payload) {
|
|
65
87
|
sendResult(ctx, ws, false, "Missing id or index");
|
|
66
88
|
return;
|
|
@@ -77,12 +99,27 @@ function handleTodosRemove(ctx, ws, payload) {
|
|
|
77
99
|
sendResult(ctx, ws, false, "Todo not found");
|
|
78
100
|
return;
|
|
79
101
|
}
|
|
102
|
+
if (removed.kanbanBoardId && removed.kanbanTaskId) {
|
|
103
|
+
sendResult(ctx, ws, false, managedProjectionMessage());
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
80
106
|
const next = [...todos.slice(0, targetIndex), ...todos.slice(targetIndex + 1)];
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
107
|
+
try {
|
|
108
|
+
const result = await commitTodos(ctx, next);
|
|
109
|
+
sendResult(ctx, ws, true, `Removed: ${removed.content}`);
|
|
110
|
+
ctx.broadcast({
|
|
111
|
+
type: "todos.updated",
|
|
112
|
+
payload: sessionPayload(ctx, { todos: result.todos })
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));
|
|
116
|
+
}
|
|
84
117
|
}
|
|
85
|
-
function handleTodoUpdate(ctx, ws, payload) {
|
|
118
|
+
async function handleTodoUpdate(ctx, ws, payload) {
|
|
119
|
+
if (!payload || typeof payload.id !== "string" || payload.status !== void 0 && payload.status !== "pending" && payload.status !== "in_progress" && payload.status !== "completed" || payload.activeForm !== void 0 && typeof payload.activeForm !== "string") {
|
|
120
|
+
sendResult(ctx, ws, false, "Invalid todo update payload");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
86
123
|
const index = ctx.context.todos.findIndex((todo) => todo.id === payload.id);
|
|
87
124
|
const existing = ctx.context.todos[index];
|
|
88
125
|
if (index === -1 || !existing) {
|
|
@@ -95,9 +132,25 @@ function handleTodoUpdate(ctx, ws, payload) {
|
|
|
95
132
|
status: payload.status ?? existing.status,
|
|
96
133
|
activeForm: payload.activeForm !== void 0 ? payload.activeForm : existing.activeForm
|
|
97
134
|
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
135
|
+
try {
|
|
136
|
+
const result = await commitTodos(ctx, next);
|
|
137
|
+
const projected = result.todos.find((todo) => todo.id === existing.id);
|
|
138
|
+
const requestedStatus = payload.status ?? existing.status;
|
|
139
|
+
const projectionRejected = Boolean(existing.kanbanBoardId && existing.kanbanTaskId) && projected?.status !== requestedStatus;
|
|
140
|
+
const warning = result.warnings[0];
|
|
141
|
+
sendResult(
|
|
142
|
+
ctx,
|
|
143
|
+
ws,
|
|
144
|
+
!projectionRejected,
|
|
145
|
+
projectionRejected ? warning ?? `Kanban kept "${existing.content}" at ${projected?.status ?? "its current state"}.` : warning ? `Todo "${existing.content}" updated. ${warning}` : `Todo "${existing.content}" updated`
|
|
146
|
+
);
|
|
147
|
+
ctx.broadcast({
|
|
148
|
+
type: "todos.updated",
|
|
149
|
+
payload: sessionPayload(ctx, { todos: result.todos })
|
|
150
|
+
});
|
|
151
|
+
} catch (error) {
|
|
152
|
+
sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));
|
|
153
|
+
}
|
|
101
154
|
}
|
|
102
155
|
async function handleTasksGet(ctx, ws) {
|
|
103
156
|
const taskPath = taskPathOf(ctx);
|
|
@@ -125,14 +178,32 @@ async function handleTaskUpdate(ctx, ws, payload) {
|
|
|
125
178
|
return;
|
|
126
179
|
}
|
|
127
180
|
try {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
181
|
+
let file;
|
|
182
|
+
if (ctx.mutateTaskStatus) {
|
|
183
|
+
const result = await ctx.mutateTaskStatus(payload.id, payload.status);
|
|
184
|
+
if (!result.ok) {
|
|
185
|
+
sendResult(ctx, ws, false, result.message);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
file = await loadTasks(taskPath);
|
|
189
|
+
if (!file) throw new Error("Task mutation succeeded but its persisted snapshot is missing.");
|
|
190
|
+
sendResult(ctx, ws, true, result.message);
|
|
191
|
+
} else {
|
|
192
|
+
let matched = false;
|
|
193
|
+
file = await mutateTasks(taskPath, currentSessionId(ctx), async (tasks) => {
|
|
194
|
+
const task = tasks.tasks.find((candidate) => candidate.id === payload.id);
|
|
195
|
+
if (!task) return tasks;
|
|
196
|
+
matched = true;
|
|
197
|
+
task.status = payload.status;
|
|
198
|
+
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
199
|
+
return tasks;
|
|
200
|
+
});
|
|
201
|
+
if (!matched) {
|
|
202
|
+
sendResult(ctx, ws, false, `Task "${payload.id}" not found.`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
sendResult(ctx, ws, true, `Task status updated to "${payload.status}".`);
|
|
206
|
+
}
|
|
136
207
|
ctx.broadcast({
|
|
137
208
|
type: "tasks.updated",
|
|
138
209
|
payload: sessionPayload(ctx, { tasks: file.tasks })
|
|
@@ -179,6 +250,18 @@ async function handlePlanTemplateUse(ctx, ws, template) {
|
|
|
179
250
|
return;
|
|
180
251
|
}
|
|
181
252
|
try {
|
|
253
|
+
if (ctx.mutatePlan) {
|
|
254
|
+
const result = await ctx.mutatePlan({ action: "template_use", template });
|
|
255
|
+
if (!result.ok) {
|
|
256
|
+
sendResult(ctx, ws, false, result.message);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const plan2 = await loadPlan(planPath);
|
|
260
|
+
if (!plan2) throw new Error("Plan mutation succeeded but its persisted snapshot is missing.");
|
|
261
|
+
sendResult(ctx, ws, true, result.message);
|
|
262
|
+
ctx.broadcast({ type: "plan.updated", payload: sessionPayload(ctx, { plan: plan2 }) });
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
182
265
|
const templateDefinition = getPlanTemplate(template);
|
|
183
266
|
if (!templateDefinition) {
|
|
184
267
|
sendResult(ctx, ws, false, `Unknown template "${template}".`);
|
|
@@ -207,6 +290,22 @@ async function handlePlanItemUpdate(ctx, ws, payload) {
|
|
|
207
290
|
return;
|
|
208
291
|
}
|
|
209
292
|
try {
|
|
293
|
+
if (ctx.mutatePlan) {
|
|
294
|
+
const result = await ctx.mutatePlan({
|
|
295
|
+
action: "status",
|
|
296
|
+
target: payload.target,
|
|
297
|
+
status: payload.status
|
|
298
|
+
});
|
|
299
|
+
if (!result.ok) {
|
|
300
|
+
sendResult(ctx, ws, false, result.message);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const plan2 = await loadPlan(planPath);
|
|
304
|
+
if (!plan2) throw new Error("Plan mutation succeeded but its persisted snapshot is missing.");
|
|
305
|
+
sendResult(ctx, ws, true, result.message);
|
|
306
|
+
ctx.broadcast({ type: "plan.updated", payload: sessionPayload(ctx, { plan: plan2 }) });
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
210
309
|
let changed = false;
|
|
211
310
|
const plan = await mutatePlan(planPath, currentSessionId(ctx), async (currentPlan) => {
|
|
212
311
|
const before = currentPlan.updatedAt;
|
|
@@ -230,13 +329,17 @@ async function handleWorklistMessage(ctx, ws, message) {
|
|
|
230
329
|
handleTodosGet(ctx, ws);
|
|
231
330
|
return;
|
|
232
331
|
case "todos.clear":
|
|
233
|
-
handleTodosClear(ctx, ws);
|
|
332
|
+
await handleTodosClear(ctx, ws);
|
|
234
333
|
return;
|
|
235
334
|
case "todos.remove":
|
|
236
|
-
handleTodosRemove(
|
|
335
|
+
await handleTodosRemove(
|
|
336
|
+
ctx,
|
|
337
|
+
ws,
|
|
338
|
+
message.payload
|
|
339
|
+
);
|
|
237
340
|
return;
|
|
238
341
|
case "todo.update":
|
|
239
|
-
handleTodoUpdate(
|
|
342
|
+
await handleTodoUpdate(
|
|
240
343
|
ctx,
|
|
241
344
|
ws,
|
|
242
345
|
message.payload
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WebSocket } from 'ws';
|
|
2
|
+
import type { WSServerMessage } from './types.js';
|
|
3
|
+
export interface KanbanContractRouteContext {
|
|
4
|
+
projectRoot: string;
|
|
5
|
+
broadcast?: ((msg: WSServerMessage) => void) | undefined;
|
|
6
|
+
}
|
|
7
|
+
export declare function handleKanbanContractRoute(ws: WebSocket, type: string, payload: Record<string, unknown> | undefined, ctx: KanbanContractRouteContext): Promise<boolean>;
|
|
8
|
+
//# sourceMappingURL=kanban-contract-routes.d.ts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const KANBAN_CLIENT_MESSAGE_TYPES: readonly ['kanban.capabilities', 'kanban.
|
|
1
|
+
export declare const KANBAN_CLIENT_MESSAGE_TYPES: readonly ['kanban.capabilities', 'kanban.contract.configure', 'kanban.contract.edge.add', 'kanban.contract.edge.remove', 'kanban.contract.get', 'kanban.contract.node.remove', 'kanban.contract.node.upsert', 'kanban.create', 'kanban.decomposition.approve', 'kanban.decomposition.reject', 'kanban.delete', 'kanban.duplicate', 'kanban.generate', 'kanban.get', 'kanban.health', 'kanban.list', 'kanban.snapshot', 'kanban.supervisor.audit', 'kanban.supervisor.status', 'kanban.task.activity', 'kanban.task.activity.add', 'kanban.task.add', 'kanban.task.assign', 'kanban.task.chain', 'kanban.task.chain.get', 'kanban.task.check.add', 'kanban.task.check.update', 'kanban.task.claim', 'kanban.task.copy', 'kanban.task.dispatch', 'kanban.task.get', 'kanban.task.merge', 'kanban.task.metric.add', 'kanban.task.metric.update', 'kanban.task.move', 'kanban.task.note.add', 'kanban.task.ready', 'kanban.task.release', 'kanban.task.remove', 'kanban.task.split', 'kanban.task.transfer', 'kanban.task.transition', 'kanban.task.update', 'kanban.task.verify', 'kanban.taskgraph.export', 'kanban.taskgraph.sync', 'kanban.update', 'kanban.workbench'];
|
|
2
2
|
//# sourceMappingURL=kanban-route-protocol.d.ts.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Context } from '@wrongstack/core/agent';
|
|
2
2
|
import type { WebSocket } from 'ws';
|
|
3
|
-
import type { WSClientMessage, WSServerMessage } from './types.js';
|
|
4
3
|
import { type KanbanTaskDispatcher } from './kanban-dispatch.js';
|
|
5
4
|
import type { KanbanSupervisor } from './kanban-supervisor.js';
|
|
5
|
+
import type { WSClientMessage, WSServerMessage } from './types.js';
|
|
6
|
+
export { type KanbanBoardPage, paginateKanbanBoards } from './kanban-route-pagination.js';
|
|
6
7
|
export { KANBAN_CLIENT_MESSAGE_TYPES } from './kanban-route-protocol.js';
|
|
7
|
-
export { paginateKanbanBoards, type KanbanBoardPage } from './kanban-route-pagination.js';
|
|
8
8
|
export interface KanbanRouteContext {
|
|
9
9
|
projectRoot: string;
|
|
10
10
|
context?: Context | undefined;
|
|
@@ -90,6 +90,12 @@ export declare function handleSageDelete(ws: WebSocket, msg: unknown, memoryStor
|
|
|
90
90
|
* - otherwise returns the freshly-restored memory
|
|
91
91
|
*/
|
|
92
92
|
export declare function handleSageRecover(ws: WebSocket, msg: unknown, memoryStore: MemoryPort): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* List review-queue candidates (hygiene / triage proposals).
|
|
95
|
+
* Request: { type: 'memory.sage.listCandidates', payload?: { includeResolved?: boolean } }
|
|
96
|
+
* Response: { type: 'memory.sage.listCandidates', payload: { candidates } }
|
|
97
|
+
*/
|
|
98
|
+
export declare function handleSageListCandidates(ws: WebSocket, msg: unknown, memoryStore: MemoryPort): Promise<void>;
|
|
93
99
|
/**
|
|
94
100
|
* Resolve a pending hygiene review candidate (PR #1).
|
|
95
101
|
* Request: { type: 'memory.sage.candidateResolve', payload: { candidateId, action: 'accept'|'reject', reason? } }
|
|
@@ -26,8 +26,8 @@ export interface ModeHandlersContext {
|
|
|
26
26
|
modelCapabilities: ModelCapabilities;
|
|
27
27
|
context: Context;
|
|
28
28
|
toolRegistry: ToolRegistry;
|
|
29
|
-
config: Pick<Config, 'provider' | 'model' | 'systemPrompt'>;
|
|
30
|
-
getConfig?: () => Pick<Config, 'provider' | 'model' | 'systemPrompt'>;
|
|
29
|
+
config: Pick<Config, 'provider' | 'model' | 'systemPrompt' | 'features'>;
|
|
30
|
+
getConfig?: () => Pick<Config, 'provider' | 'model' | 'systemPrompt' | 'features'>;
|
|
31
31
|
projectRoot: string;
|
|
32
32
|
globalRoot: string;
|
|
33
33
|
clients: Map<WebSocket, ConnectedClient>;
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { Context } from '@wrongstack/core/agent';
|
|
23
23
|
import { DefaultPromptLoader, DefaultSkillLoader } from '@wrongstack/core/execution';
|
|
24
|
-
import { type Container, EventBus } from '@wrongstack/core/kernel';
|
|
25
24
|
import { DefaultTokenCounter } from '@wrongstack/core/infrastructure';
|
|
25
|
+
import { type Container, EventBus } from '@wrongstack/core/kernel';
|
|
26
26
|
import { DefaultModeStore } from '@wrongstack/core/models';
|
|
27
27
|
import { ProviderRegistry, ToolRegistry } from '@wrongstack/core/registry';
|
|
28
28
|
import { SkillInstaller } from '@wrongstack/core/skills';
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server lifecycle helpers for the standalone WebUI server.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1e of the god-module split: the port resolution, WS auth/server
|
|
5
|
+
* creation, event arming, session-start payload builder, HTTP server
|
|
6
|
+
* startup, and graceful shutdown registration all moved here from
|
|
7
|
+
* `start-webui.ts` so the orchestrator reads as connect-the-dots.
|
|
8
|
+
*
|
|
9
|
+
* Each function is a pure construction step — no behaviour change. The
|
|
10
|
+
* WS/HTTP/shutdown wiring that used to be inline (~370 lines) now lives
|
|
11
|
+
* behind four focused entry points.
|
|
12
|
+
*/
|
|
1
13
|
import type { Config, ModelsRegistry } from '@wrongstack/core/types';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
14
|
+
import { type WebSocket, WebSocketServer } from 'ws';
|
|
15
|
+
import { type FileWatcherMetrics, setupEvents } from './setup-events.js';
|
|
4
16
|
import type { ConnectedClient } from './types.js';
|
|
5
17
|
interface ResolvedPorts {
|
|
6
18
|
wsHost: string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { EventName, Listener } from '@wrongstack/core/kernel';
|
|
2
2
|
import type { WstackPaths } from '@wrongstack/core/utils';
|
|
3
3
|
import type { WebSocket } from 'ws';
|
|
4
|
-
import type { ConnectedClient, WSServerMessage } from './types.js';
|
|
5
4
|
import { type FileWatcherMetrics } from './setup-events-watcher.js';
|
|
5
|
+
import type { ConnectedClient, WSServerMessage } from './types.js';
|
|
6
6
|
export interface SetupEventsStatusWatcherDeps {
|
|
7
7
|
wpaths?: WstackPaths | undefined;
|
|
8
8
|
watcherMetrics?: FileWatcherMetrics | undefined;
|
|
@@ -7,7 +7,7 @@ export declare const WEBUI_WS_MAX_BUFFERED_BYTES: number;
|
|
|
7
7
|
* A socket above the cap cannot be trusted to catch up: keeping it alive would
|
|
8
8
|
* let `ws` retain every subsequent broadcast in memory.
|
|
9
9
|
*/
|
|
10
|
-
export declare function sendSerialized(ws: WebSocket, data: string): boolean;
|
|
10
|
+
export declare function sendSerialized(ws: WebSocket, data: string, frameBytes?: number): boolean;
|
|
11
11
|
/**
|
|
12
12
|
* Send a JSON message to a single WebSocket client.
|
|
13
13
|
* No-op when the socket is not in OPEN state (disconnected / closing).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/webui-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.305.0",
|
|
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/
|
|
44
|
-
"@wrongstack/
|
|
45
|
-
"@wrongstack/
|
|
46
|
-
"@wrongstack/
|
|
47
|
-
"@wrongstack/
|
|
48
|
-
"@wrongstack/
|
|
49
|
-
"@wrongstack/
|
|
50
|
-
"@wrongstack/
|
|
51
|
-
"@wrongstack/
|
|
52
|
-
"@wrongstack/
|
|
43
|
+
"@wrongstack/runtime": "0.305.0",
|
|
44
|
+
"@wrongstack/mcp": "0.305.0",
|
|
45
|
+
"@wrongstack/providers": "0.305.0",
|
|
46
|
+
"@wrongstack/kanban": "0.305.0",
|
|
47
|
+
"@wrongstack/core": "0.305.0",
|
|
48
|
+
"@wrongstack/requirement-intake": "0.305.0",
|
|
49
|
+
"@wrongstack/techstack": "0.305.0",
|
|
50
|
+
"@wrongstack/sage": "0.305.0",
|
|
51
|
+
"@wrongstack/tools": "0.305.0",
|
|
52
|
+
"@wrongstack/sdd": "0.305.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^26.1.2",
|