@wrongstack/webui-server 0.295.0 → 0.296.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 +16915 -13874
- package/dist/index.js.map +4 -4
- package/dist/protocol/client-conversation.d.ts +1 -1
- package/dist/protocol/client-conversation.d.ts.map +1 -1
- package/dist/protocol/client-integrations.d.ts +1 -1
- package/dist/protocol/client-integrations.d.ts.map +1 -1
- package/dist/protocol/client-operations.d.ts +2 -2
- package/dist/protocol/client-operations.d.ts.map +1 -1
- package/dist/protocol/client-workspace.d.ts +1 -1
- package/dist/protocol/client-workspace.d.ts.map +1 -1
- package/dist/protocol/index.d.ts +1 -0
- package/dist/protocol/index.d.ts.map +1 -1
- package/dist/protocol/index.js +64 -1
- package/dist/protocol/index.js.map +3 -3
- package/dist/protocol/projections.d.ts +2 -0
- package/dist/protocol/projections.d.ts.map +1 -1
- package/dist/protocol/registry.d.ts +2 -2
- package/dist/protocol/registry.d.ts.map +1 -1
- package/dist/protocol/replay-payload.d.ts +41 -0
- package/dist/protocol/replay-payload.d.ts.map +1 -0
- package/dist/protocol/server-conversation.d.ts +1 -1
- package/dist/protocol/server-conversation.d.ts.map +1 -1
- package/dist/protocol/server-integrations.d.ts +1 -1
- package/dist/protocol/server-integrations.d.ts.map +1 -1
- package/dist/protocol/server-operations.d.ts +1 -1
- package/dist/protocol/server-operations.d.ts.map +1 -1
- package/dist/protocol/server-workspace.d.ts +2 -2
- package/dist/protocol/server-workspace.d.ts.map +1 -1
- package/dist/protocol/version.d.ts +5 -1
- package/dist/protocol/version.d.ts.map +1 -1
- package/dist/server/agent-roster-handlers.d.ts +36 -1
- package/dist/server/agent-roster-handlers.d.ts.map +1 -1
- package/dist/server/backend-services.d.ts.map +1 -1
- package/dist/server/brain-handlers.d.ts.map +1 -1
- package/dist/server/chronicle-routes.d.ts +2 -3
- package/dist/server/chronicle-routes.d.ts.map +1 -1
- package/dist/server/client-presence.d.ts +2 -2
- package/dist/server/client-presence.d.ts.map +1 -1
- package/dist/server/codebase-index-server-control.d.ts +15 -0
- package/dist/server/codebase-index-server-control.d.ts.map +1 -0
- package/dist/server/codebase-indexing.d.ts.map +1 -1
- package/dist/server/codemap-cache.d.ts +14 -0
- package/dist/server/codemap-cache.d.ts.map +1 -0
- package/dist/server/codemap-handlers.d.ts +5 -6
- package/dist/server/codemap-handlers.d.ts.map +1 -1
- package/dist/server/collaboration-ws-handler.d.ts.map +1 -1
- package/dist/server/connection-handler.d.ts +9 -1
- package/dist/server/connection-handler.d.ts.map +1 -1
- package/dist/server/connection-lifecycle.d.ts +76 -0
- package/dist/server/connection-lifecycle.d.ts.map +1 -1
- package/dist/server/connections-health-route.d.ts +46 -0
- package/dist/server/connections-health-route.d.ts.map +1 -0
- package/dist/server/context-editor.d.ts +114 -0
- package/dist/server/context-editor.d.ts.map +1 -0
- package/dist/server/context-meta.d.ts.map +1 -1
- package/dist/server/conversation-operations.d.ts.map +1 -1
- package/dist/server/deadcode-handlers.d.ts +8 -0
- package/dist/server/deadcode-handlers.d.ts.map +1 -0
- package/dist/server/embedded-host-adapters.d.ts +11 -1
- package/dist/server/embedded-host-adapters.d.ts.map +1 -1
- package/dist/server/embedded-lifecycle.d.ts.map +1 -1
- package/dist/server/embedded-message-router.d.ts +4 -0
- package/dist/server/embedded-message-router.d.ts.map +1 -1
- package/dist/server/entry.js +14952 -12161
- package/dist/server/entry.js.map +4 -4
- package/dist/server/goal-routes.d.ts +2 -2
- package/dist/server/goal-routes.d.ts.map +1 -1
- package/dist/server/goal-ws-handler.d.ts +20 -1
- package/dist/server/goal-ws-handler.d.ts.map +1 -1
- package/dist/server/handlers.js +0 -1
- package/dist/server/handlers.js.map +2 -2
- package/dist/server/http-server/api-handlers.d.ts +1 -1
- package/dist/server/http-server/api-handlers.d.ts.map +1 -1
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/index.d.ts +6 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/kanban-board-watcher.d.ts +10 -0
- package/dist/server/kanban-board-watcher.d.ts.map +1 -0
- package/dist/server/kanban-daemon-subscriber.d.ts +3 -0
- package/dist/server/kanban-daemon-subscriber.d.ts.map +1 -0
- package/dist/server/kanban-decomposition-routes.d.ts +10 -0
- package/dist/server/kanban-decomposition-routes.d.ts.map +1 -0
- package/dist/server/kanban-dispatch.d.ts +1 -0
- package/dist/server/kanban-dispatch.d.ts.map +1 -1
- package/dist/server/kanban-route-helpers.d.ts +17 -0
- package/dist/server/kanban-route-helpers.d.ts.map +1 -0
- package/dist/server/kanban-route-pagination.d.ts +16 -0
- package/dist/server/kanban-route-pagination.d.ts.map +1 -0
- package/dist/server/kanban-route-protocol.d.ts +2 -0
- package/dist/server/kanban-route-protocol.d.ts.map +1 -0
- package/dist/server/kanban-routes.d.ts +2 -15
- package/dist/server/kanban-routes.d.ts.map +1 -1
- package/dist/server/kanban-run-mirror.d.ts.map +1 -1
- package/dist/server/kanban-supervisor.d.ts.map +1 -1
- package/dist/server/kanban-task-routes.d.ts +10 -0
- package/dist/server/kanban-task-routes.d.ts.map +1 -0
- package/dist/server/mailbox-handlers.d.ts +3 -3
- package/dist/server/mailbox-handlers.d.ts.map +1 -1
- package/dist/server/message-dispatcher.d.ts.map +1 -1
- package/dist/server/mode-handlers.d.ts +4 -6
- package/dist/server/mode-handlers.d.ts.map +1 -1
- package/dist/server/model-catalog-search.d.ts +17 -0
- package/dist/server/model-catalog-search.d.ts.map +1 -0
- package/dist/server/model-operations.d.ts +2 -0
- package/dist/server/model-operations.d.ts.map +1 -1
- package/dist/server/network-info.d.ts +50 -0
- package/dist/server/network-info.d.ts.map +1 -0
- package/dist/server/pre-context-services.d.ts +1 -1
- package/dist/server/pre-context-services.d.ts.map +1 -1
- package/dist/server/pref-helpers.d.ts +7 -7
- package/dist/server/pref-helpers.d.ts.map +1 -1
- package/dist/server/project-handlers.d.ts +3 -2
- package/dist/server/project-handlers.d.ts.map +1 -1
- package/dist/server/provider-handlers.d.ts +10 -0
- package/dist/server/provider-handlers.d.ts.map +1 -1
- package/dist/server/provider-keys.d.ts +2 -0
- package/dist/server/provider-keys.d.ts.map +1 -1
- package/dist/server/provider-routes.d.ts +9 -0
- package/dist/server/provider-routes.d.ts.map +1 -1
- package/dist/server/routes.d.ts +8 -3
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/sdd-board-ws-handler.d.ts.map +1 -1
- package/dist/server/sdd-wizard-wiring.d.ts +17 -1
- package/dist/server/sdd-wizard-wiring.d.ts.map +1 -1
- package/dist/server/sdd-wizard-ws-handler.d.ts +41 -8
- package/dist/server/sdd-wizard-ws-handler.d.ts.map +1 -1
- package/dist/server/session-handlers.d.ts +13 -3
- package/dist/server/session-handlers.d.ts.map +1 -1
- package/dist/server/session-history.d.ts +3 -0
- package/dist/server/session-history.d.ts.map +1 -1
- package/dist/server/session-routes.d.ts +3 -0
- package/dist/server/session-routes.d.ts.map +1 -1
- package/dist/server/setup-events-core-watchers.d.ts +15 -0
- package/dist/server/setup-events-core-watchers.d.ts.map +1 -0
- package/dist/server/setup-events-fleet-broadcaster.d.ts +15 -0
- package/dist/server/setup-events-fleet-broadcaster.d.ts.map +1 -0
- package/dist/server/setup-events-provider-handlers.d.ts +19 -0
- package/dist/server/setup-events-provider-handlers.d.ts.map +1 -0
- package/dist/server/setup-events-session-helpers.d.ts +10 -0
- package/dist/server/setup-events-session-helpers.d.ts.map +1 -0
- package/dist/server/setup-events-status-watcher.d.ts +15 -0
- package/dist/server/setup-events-status-watcher.d.ts.map +1 -0
- package/dist/server/setup-events-watcher.d.ts +3 -0
- package/dist/server/setup-events-watcher.d.ts.map +1 -1
- package/dist/server/setup-events.d.ts +1 -1
- package/dist/server/setup-events.d.ts.map +1 -1
- package/dist/server/skills-handlers.d.ts.map +1 -1
- package/dist/server/standalone-session-identity.d.ts +10 -6
- package/dist/server/standalone-session-identity.d.ts.map +1 -1
- package/dist/server/start-webui.d.ts.map +1 -1
- package/dist/server/types.d.ts +2 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/ws-auth.d.ts.map +1 -1
- package/dist/server/ws-payload-preferences.d.ts +13 -0
- package/dist/server/ws-payload-preferences.d.ts.map +1 -0
- package/dist/server/ws-payload-validation.d.ts +2 -5
- package/dist/server/ws-payload-validation.d.ts.map +1 -1
- package/package.json +10 -10
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { WebSocket } from 'ws';
|
|
2
2
|
import type { WSClientMessage } from './types.js';
|
|
3
3
|
export interface GoalRouteHandlers {
|
|
4
|
-
handleMessage: (msg: {
|
|
4
|
+
handleMessage: (ws: WebSocket, msg: {
|
|
5
5
|
type: string;
|
|
6
6
|
payload?: Record<string, unknown>;
|
|
7
7
|
}) => Promise<void>;
|
|
8
8
|
}
|
|
9
|
-
export declare function handleGoalRoute(
|
|
9
|
+
export declare function handleGoalRoute(ws: WebSocket, msg: WSClientMessage, handlers: GoalRouteHandlers): Promise<boolean>;
|
|
10
10
|
//# sourceMappingURL=goal-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-routes.d.ts","sourceRoot":"","sources":["../../src/server/goal-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"goal-routes.d.ts","sourceRoot":"","sources":["../../src/server/goal-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3G;AAED,wBAAsB,eAAe,CACnC,EAAE,EAAE,SAAS,EACb,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAIlB"}
|
|
@@ -39,6 +39,12 @@ export declare class GoalWebSocketHandler {
|
|
|
39
39
|
private broadcastInterval;
|
|
40
40
|
/** Aborts in-flight task agents AND the planning turn when the run is stopped. */
|
|
41
41
|
private abort;
|
|
42
|
+
/** Per-assessment AbortController so a newer assessment can abort the prior
|
|
43
|
+
* LLM call instead of waiting for it to finish (frees the Agent's single-flight
|
|
44
|
+
* guard sooner). */
|
|
45
|
+
private assessAbort;
|
|
46
|
+
/** Monotonically increasing seq for stale-assessment detection. */
|
|
47
|
+
private assessSeq;
|
|
42
48
|
/** Set the instant a stop/clear/revert is requested, so a planning turn that
|
|
43
49
|
* resolves afterwards never launches the orchestrator (the abort alone can't
|
|
44
50
|
* cover the window between the LLM call resolving and the orchestrator start). */
|
|
@@ -60,7 +66,15 @@ export declare class GoalWebSocketHandler {
|
|
|
60
66
|
*/
|
|
61
67
|
onBoardState?: ((graphId: string, state: Record<string, unknown>) => void) | undefined);
|
|
62
68
|
addClient(ws: WebSocket): void;
|
|
63
|
-
handleMessage(msg: GoalWSMessage): Promise<void>;
|
|
69
|
+
handleMessage(ws: WebSocket, msg: GoalWSMessage): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Assess a goal prompt for duration realism. Runs a lightweight LLM call
|
|
72
|
+
* (faster than planPhases) and returns the structured assessment to the
|
|
73
|
+
* requesting client so the UI can warn about unrealistic durations before
|
|
74
|
+
* the user submits the goal for planning. Sends only to the originating
|
|
75
|
+
* client (unicast) and echoes the client's `seq` for response correlation.
|
|
76
|
+
*/
|
|
77
|
+
private handleAssess;
|
|
64
78
|
private handleStart;
|
|
65
79
|
/**
|
|
66
80
|
* Halt the run NOW — at any phase. Sets `stopping` (so a planning turn that
|
|
@@ -90,6 +104,11 @@ export declare class GoalWebSocketHandler {
|
|
|
90
104
|
* uninterruptible). */
|
|
91
105
|
private planPhases;
|
|
92
106
|
private executeTaskWithAgent;
|
|
107
|
+
/**
|
|
108
|
+
* Run a lightweight chimera-style review of a completed task's output.
|
|
109
|
+
* Fire-and-forget: runs in the background and logs the review summary.
|
|
110
|
+
*/
|
|
111
|
+
private runChimeraReview;
|
|
93
112
|
/** Persist + broadcast after an interactive board mutation. */
|
|
94
113
|
private afterBoardMutation;
|
|
95
114
|
private handleTaskStatusChange;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-ws-handler.d.ts","sourceRoot":"","sources":["../../src/server/goal-ws-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"goal-ws-handler.d.ts","sourceRoot":"","sources":["../../src/server/goal-ws-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAiBpC,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA2CrD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,oBAAoB;IA2B7B,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,MAAM,CAAC;IACf,OAAO,CAAC,WAAW,CAAC;IACpB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY,CAAC;IAvCvB,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,iBAAiB,CAA+C;IACxE,kFAAkF;IAClF,OAAO,CAAC,KAAK,CAAgC;IAC7C;;yBAEqB;IACrB,OAAO,CAAC,WAAW,CAAgC;IACnD,mEAAmE;IACnE,OAAO,CAAC,SAAS,CAAK;IACtB;;uFAEmF;IACnF,OAAO,CAAC,QAAQ,CAAS;IACzB,2EAA2E;IAC3E,OAAO,CAAC,SAAS,CAAgC;IACjD;oFACgF;IAChF,OAAO,CAAC,OAAO,CAAgD;IAC/D,wEAAwE;IACxE,OAAO,CAAC,aAAa,CAAqB;IAE1C,YACU,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EACR,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,EAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS;IACxC;;;;;;OAMG;IACK,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,EAG/F;IAED,SAAS,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAS7B;IAEK,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA4GpE;IAED;;;;;;OAMG;YACW,YAAY;YAmEZ,WAAW;IAsLzB;;;;;OAKG;YACW,UAAU;IAWxB;;;;OAIG;YACW,WAAW;IAYzB;;;;;OAKG;YACW,YAAY;IAsB1B,4EAA4E;IAC5E,OAAO,CAAC,aAAa;IAUrB;;;4BAGwB;YACV,UAAU;YA2BV,oBAAoB;IA+BlC;;;OAGG;YACW,gBAAgB;IA0C9B,+DAA+D;IAC/D,OAAO,CAAC,kBAAkB;YAKZ,sBAAsB;IAcpC,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,UAAU;IAwGlB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,IAAI;CAGb"}
|
package/dist/server/handlers.js
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
} from "@wrongstack/core/storage";
|
|
13
13
|
|
|
14
14
|
// src/server/ws-payload-validation.ts
|
|
15
|
-
import { FORBIDDEN_PROTO_KEYS } from "@wrongstack/core/utils";
|
|
16
15
|
function isRecord(value) {
|
|
17
16
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18
17
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/server/handlers/worklist-handlers.ts", "../../src/server/ws-payload-validation.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n addPlanItem,\n emptyPlan,\n getPlanTemplate,\n loadPlan,\n loadTasks,\n mutatePlan,\n mutateTasks,\n savePlan,\n setPlanItemStatus,\n} from '@wrongstack/core/storage';\nimport type { TodoItem } from '@wrongstack/core/agent';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from '../types.js';\nimport { validatePlanTemplateUsePayload } from '../ws-payload-validation.js';\n\nexport interface WorklistContext {\n context: {\n todos: TodoItem[];\n meta: Record<string, unknown>;\n session: { id: string } | null;\n };\n send: (ws: WebSocket, msg: WSServerMessage) => void;\n broadcast: (msg: WSServerMessage) => void;\n replaceTodos?: ((todos: TodoItem[]) => void) | undefined;\n}\n\nexport interface WorklistMessage {\n type: string;\n payload?: unknown;\n}\n\nfunction sendResult(ctx: WorklistContext, ws: WebSocket, success: boolean, message: string): void {\n ctx.send(ws, { type: 'key.operation_result', payload: { success, message } });\n}\n\nfunction currentSessionId(ctx: WorklistContext): string {\n return ctx.context.session?.id ?? '';\n}\n\nfunction sessionPayload<T extends Record<string, unknown>>(\n ctx: WorklistContext,\n payload: T,\n): T & { sessionId: string } {\n const provided = payload['sessionId'];\n const sessionId =\n typeof provided === 'string' && provided.length > 0 ? provided : currentSessionId(ctx);\n return { ...payload, sessionId };\n}\n\nfunction planPathOf(ctx: WorklistContext): string | undefined {\n const value = ctx.context.meta['plan.path'];\n return typeof value === 'string' && value ? value : undefined;\n}\n\nfunction taskPathOf(ctx: WorklistContext): string | undefined {\n const value = ctx.context.meta['task.path'];\n return typeof value === 'string' && value ? value : undefined;\n}\n\nexport function handleTodosGet(ctx: WorklistContext, ws: WebSocket): void {\n ctx.send(ws, {\n type: 'todos.updated',\n payload: sessionPayload(ctx, { todos: [...ctx.context.todos] }),\n });\n}\n\nexport function handleTodosClear(ctx: WorklistContext, ws: WebSocket): void {\n ctx.replaceTodos?.([]);\n sendResult(ctx, ws, true, 'Todos cleared');\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: [] }) });\n}\n\nexport function handleTodosRemove(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { id?: string | undefined; index?: number | undefined } | undefined,\n): void {\n if (!payload) {\n sendResult(ctx, ws, false, 'Missing id or index');\n return;\n }\n const todos = ctx.context.todos;\n let targetIndex = -1;\n if (typeof payload.id === 'string') {\n targetIndex = todos.findIndex((todo) => todo.id === payload.id);\n } else if (typeof payload.index === 'number' && payload.index > 0) {\n targetIndex = payload.index - 1;\n }\n const removed = todos[targetIndex];\n if (targetIndex < 0 || !removed) {\n sendResult(ctx, ws, false, 'Todo not found');\n return;\n }\n const next = [...todos.slice(0, targetIndex), ...todos.slice(targetIndex + 1)];\n ctx.replaceTodos?.(next);\n sendResult(ctx, ws, true, `Removed: ${removed.content}`);\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: next }) });\n}\n\nexport function handleTodoUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { id: string; status?: TodoItem['status'] | undefined; activeForm?: string | undefined },\n): void {\n const index = ctx.context.todos.findIndex((todo) => todo.id === payload.id);\n const existing = ctx.context.todos[index];\n if (index === -1 || !existing) {\n sendResult(ctx, ws, false, 'Todo not found');\n return;\n }\n const next = [...ctx.context.todos];\n next[index] = {\n ...existing,\n status: payload.status ?? existing.status,\n activeForm: payload.activeForm !== undefined ? payload.activeForm : existing.activeForm,\n };\n ctx.replaceTodos?.(next);\n sendResult(ctx, ws, true, `Todo \"${existing.content}\" updated`);\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: next }) });\n}\n\nexport async function handleTasksGet(ctx: WorklistContext, ws: WebSocket): Promise<void> {\n const taskPath = taskPathOf(ctx);\n if (!taskPath) {\n ctx.send(ws, {\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: [], error: 'Task storage not configured.' }),\n });\n return;\n }\n try {\n const file = await loadTasks(taskPath);\n ctx.send(ws, {\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: file?.tasks ?? [] }),\n });\n } catch {\n ctx.send(ws, { type: 'tasks.updated', payload: sessionPayload(ctx, { tasks: [] }) });\n }\n}\n\nexport async function handleTaskUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: {\n id: string;\n status: 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\n },\n): Promise<void> {\n const taskPath = taskPathOf(ctx);\n if (!taskPath) {\n sendResult(ctx, ws, false, 'Task storage not configured.');\n return;\n }\n try {\n const file = await mutateTasks(taskPath, currentSessionId(ctx), async (tasks) => {\n const task = tasks.tasks.find((candidate) => candidate.id === payload.id);\n if (!task) return tasks;\n task.status = payload.status;\n task.updatedAt = new Date().toISOString();\n return tasks;\n });\n sendResult(ctx, ws, true, `Task status updated to \"${payload.status}\".`);\n ctx.broadcast({\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: file.tasks }),\n });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handlePlanGet(ctx: WorklistContext, ws: WebSocket): Promise<void> {\n const planPath = planPathOf(ctx);\n const emptySnapshot = () => ({\n version: 1,\n sessionId: currentSessionId(ctx),\n updatedAt: new Date().toISOString(),\n items: [],\n });\n if (!planPath) {\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, {\n plan: null,\n error: 'Plan storage is not configured for this session.',\n }),\n });\n return;\n }\n try {\n const plan = await loadPlan(planPath);\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, { plan: plan ?? emptySnapshot() }),\n });\n } catch {\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, { plan: emptySnapshot() }),\n });\n }\n}\n\nexport async function handlePlanTemplateUse(\n ctx: WorklistContext,\n ws: WebSocket,\n template: string,\n): Promise<void> {\n const planPath = planPathOf(ctx);\n if (!planPath) {\n sendResult(ctx, ws, false, 'Plan storage is not configured for this session.');\n return;\n }\n try {\n const templateDefinition = getPlanTemplate(template);\n if (!templateDefinition) {\n sendResult(ctx, ws, false, `Unknown template \"${template}\".`);\n return;\n }\n let plan = (await loadPlan(planPath)) ?? emptyPlan(currentSessionId(ctx));\n for (const item of templateDefinition.items) {\n ({ plan } = addPlanItem(plan, item.title, item.details));\n }\n await savePlan(planPath, plan);\n sendResult(\n ctx,\n ws,\n true,\n `Applied template \"${templateDefinition.name}\" \u2014 ${templateDefinition.items.length} items added.`,\n );\n ctx.broadcast({ type: 'plan.updated', payload: sessionPayload(ctx, { plan }) });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handlePlanItemUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { target: string; status: 'open' | 'in_progress' | 'done' },\n): Promise<void> {\n const planPath = planPathOf(ctx);\n if (!planPath) {\n sendResult(ctx, ws, false, 'Plan storage is not configured for this session.');\n return;\n }\n try {\n let changed = false;\n const plan = await mutatePlan(planPath, currentSessionId(ctx), async (currentPlan) => {\n const before = currentPlan.updatedAt;\n const next = setPlanItemStatus(currentPlan, payload.target, payload.status);\n changed = next.updatedAt !== before;\n return next;\n });\n if (!changed) {\n sendResult(ctx, ws, false, `No plan item matched \"${payload.target}\".`);\n return;\n }\n sendResult(ctx, ws, true, `Plan item status updated to \"${payload.status}\".`);\n ctx.broadcast({ type: 'plan.updated', payload: sessionPayload(ctx, { plan }) });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handleWorklistMessage(\n ctx: WorklistContext,\n ws: WebSocket,\n message: WorklistMessage,\n): Promise<void> {\n switch (message.type) {\n case 'todos.get':\n handleTodosGet(ctx, ws);\n return;\n case 'todos.clear':\n handleTodosClear(ctx, ws);\n return;\n case 'todos.remove':\n handleTodosRemove(ctx, ws, message.payload as { id?: string; index?: number } | undefined);\n return;\n case 'todo.update':\n handleTodoUpdate(\n ctx,\n ws,\n message.payload as {\n id: string;\n status?: TodoItem['status'];\n activeForm?: string;\n },\n );\n return;\n case 'tasks.get':\n await handleTasksGet(ctx, ws);\n return;\n case 'task.update':\n await handleTaskUpdate(\n ctx,\n ws,\n message.payload as {\n id: string;\n status: 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\n },\n );\n return;\n case 'plan.get':\n await handlePlanGet(ctx, ws);\n return;\n case 'plan.template_use': {\n const parsed = validatePlanTemplateUsePayload(message.payload);\n if (!parsed.ok) {\n sendResult(ctx, ws, false, parsed.message);\n return;\n }\n await handlePlanTemplateUse(ctx, ws, parsed.value.template);\n return;\n }\n case 'plan.item.update':\n await handlePlanItemUpdate(\n ctx,\n ws,\n message.payload as { target: string; status: 'open' | 'in_progress' | 'done' },\n );\n }\n}\n", "import { FORBIDDEN_PROTO_KEYS } from '@wrongstack/core/utils';\n\ntype PayloadValidationResult<T> = { ok: true; value: T } | { ok: false; message: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\ninterface ModelSwitchPayload {\n provider: string;\n model: string;\n}\n\nexport function validateModelSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ModelSwitchPayload> {\n if (!isRecord(payload)) {\n return {\n ok: false,\n message: 'model.switch payload must be an object with string provider and model',\n };\n }\n const provider = payload['provider'];\n const model = payload['model'];\n if (typeof provider !== 'string' || provider.trim().length === 0) {\n return { ok: false, message: 'model.switch payload.provider must be a non-empty string' };\n }\n if (typeof model !== 'string' || model.trim().length === 0) {\n return { ok: false, message: 'model.switch payload.model must be a non-empty string' };\n }\n return { ok: true, value: { provider, model } };\n}\n\ninterface PrefsUpdatePayload {\n prefs: Record<string, unknown>;\n}\n\nconst AUTONOMY_VALUES = new Set(['off', 'suggest', 'auto', 'eternal', 'eternal-parallel']);\n\ninterface MailboxMessagesPayload {\n limit?: number;\n agentId?: string;\n unreadOnly?: boolean;\n incompleteOnly?: boolean;\n}\n\nexport function validateMailboxMessagesPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxMessagesPayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.messages payload must be an object when provided' };\n }\n const limit = payload['limit'];\n const agentId = payload['agentId'];\n const unreadOnly = payload['unreadOnly'];\n const incompleteOnly = payload['incompleteOnly'];\n if (limit !== undefined && (typeof limit !== 'number' || !Number.isFinite(limit) || limit < 1)) {\n return {\n ok: false,\n message: 'mailbox.messages payload.limit must be a positive number when provided',\n };\n }\n if (agentId !== undefined && typeof agentId !== 'string') {\n return {\n ok: false,\n message: 'mailbox.messages payload.agentId must be a string when provided',\n };\n }\n if (unreadOnly !== undefined && typeof unreadOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.messages payload.unreadOnly must be a boolean when provided',\n };\n }\n if (incompleteOnly !== undefined && typeof incompleteOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.messages payload.incompleteOnly must be a boolean when provided',\n };\n }\n return {\n ok: true,\n value: {\n ...(limit !== undefined ? { limit: limit as number } : {}),\n ...(agentId !== undefined ? { agentId: agentId as string } : {}),\n ...(unreadOnly !== undefined ? { unreadOnly: unreadOnly as boolean } : {}),\n ...(incompleteOnly !== undefined ? { incompleteOnly: incompleteOnly as boolean } : {}),\n },\n };\n}\n\ninterface MailboxAgentsPayload {\n onlineOnly?: boolean;\n}\n\nconst MAILBOX_SEND_TYPES = new Set([\n 'note',\n 'ask',\n 'assign',\n 'steer',\n 'btw',\n 'broadcast',\n 'status',\n 'result',\n 'review',\n]);\n\nexport interface MailboxSendPayload {\n requestId: string;\n to: string;\n type: 'note' | 'ask' | 'assign' | 'steer' | 'btw' | 'broadcast' | 'status' | 'result' | 'review';\n audience: 'all' | 'leaders';\n subject: string;\n body: string;\n priority: 'low' | 'normal' | 'high';\n replyTo?: string | undefined;\n}\n\nexport function validateMailboxSendPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxSendPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.send payload must be an object' };\n }\n const requestId = payload['requestId'];\n const rawTo = payload['to'];\n const rawType = payload['type'];\n const rawAudience = payload['audience'];\n const rawSubject = payload['subject'];\n const rawBody = payload['body'];\n const rawPriority = payload['priority'];\n const rawReplyTo = payload['replyTo'];\n\n if (typeof requestId !== 'string' || requestId.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.requestId must be a non-empty string' };\n }\n if (typeof rawTo !== 'string' || rawTo.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.to must be a non-empty string' };\n }\n if (typeof rawType !== 'string' || !MAILBOX_SEND_TYPES.has(rawType)) {\n return {\n ok: false,\n message: 'mailbox.send payload.type must be a supported non-control message type',\n };\n }\n if (rawAudience !== 'all' && rawAudience !== 'leaders') {\n return { ok: false, message: 'mailbox.send payload.audience must be all or leaders' };\n }\n if (typeof rawSubject !== 'string' || rawSubject.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.subject must be a non-empty string' };\n }\n if (typeof rawBody !== 'string' || rawBody.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.body must be a non-empty string' };\n }\n if (rawPriority !== 'low' && rawPriority !== 'normal' && rawPriority !== 'high') {\n return { ok: false, message: 'mailbox.send payload.priority must be low, normal, or high' };\n }\n if (rawReplyTo !== undefined && typeof rawReplyTo !== 'string') {\n return { ok: false, message: 'mailbox.send payload.replyTo must be a string when provided' };\n }\n\n const type = rawType as MailboxSendPayload['type'];\n const to = type === 'broadcast' ? '*' : rawTo.trim();\n if ((type === 'assign' || type === 'steer') && (to === '*' || to.toLowerCase() === 'all')) {\n return {\n ok: false,\n message: `mailbox.send payload.type ${type} requires a specific recipient`,\n };\n }\n\n return {\n ok: true,\n value: {\n requestId: requestId.trim(),\n to,\n type,\n audience: rawAudience,\n subject: rawSubject.trim(),\n body: rawBody.trim(),\n priority: rawPriority,\n ...(rawReplyTo !== undefined ? { replyTo: rawReplyTo } : {}),\n },\n };\n}\n\nexport function validateMailboxAgentsPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxAgentsPayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.agents payload must be an object when provided' };\n }\n const onlineOnly = payload['onlineOnly'];\n if (onlineOnly !== undefined && typeof onlineOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.agents payload.onlineOnly must be a boolean when provided',\n };\n }\n return {\n ok: true,\n value: { ...(onlineOnly !== undefined ? { onlineOnly: onlineOnly as boolean } : {}) },\n };\n}\n\ninterface MailboxPurgePayload {\n completedMaxAgeMs?: number;\n incompleteMaxAgeMs?: number;\n}\n\nexport function validateMailboxPurgePayload(\n payload: unknown,\n): PayloadValidationResult<MailboxPurgePayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.purge payload must be an object when provided' };\n }\n const completedMaxAgeMs = payload['completedMaxAgeMs'];\n const incompleteMaxAgeMs = payload['incompleteMaxAgeMs'];\n if (\n completedMaxAgeMs !== undefined &&\n (typeof completedMaxAgeMs !== 'number' ||\n !Number.isFinite(completedMaxAgeMs) ||\n completedMaxAgeMs < 0)\n ) {\n return {\n ok: false,\n message:\n 'mailbox.purge payload.completedMaxAgeMs must be a non-negative number when provided',\n };\n }\n if (\n incompleteMaxAgeMs !== undefined &&\n (typeof incompleteMaxAgeMs !== 'number' ||\n !Number.isFinite(incompleteMaxAgeMs) ||\n incompleteMaxAgeMs < 0)\n ) {\n return {\n ok: false,\n message:\n 'mailbox.purge payload.incompleteMaxAgeMs must be a non-negative number when provided',\n };\n }\n return {\n ok: true,\n value: {\n ...(completedMaxAgeMs !== undefined\n ? { completedMaxAgeMs: completedMaxAgeMs as number }\n : {}),\n ...(incompleteMaxAgeMs !== undefined\n ? { incompleteMaxAgeMs: incompleteMaxAgeMs as number }\n : {}),\n },\n };\n}\n\ninterface BrainRiskPayload {\n level: string;\n}\n\nconst BRAIN_RISK_VALUES = new Set(['off', 'low', 'medium', 'high', 'all']);\n\nexport function validateBrainRiskPayload(\n payload: unknown,\n): PayloadValidationResult<BrainRiskPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.risk payload must be an object with string level' };\n }\n const level = payload['level'];\n if (typeof level !== 'string' || !BRAIN_RISK_VALUES.has(level)) {\n return {\n ok: false,\n message: 'brain.risk payload.level must be one of off, low, medium, high, all',\n };\n }\n return { ok: true, value: { level } };\n}\n\ninterface BrainAskPayload {\n question: string;\n}\n\nexport function validateBrainAskPayload(\n payload: unknown,\n): PayloadValidationResult<BrainAskPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.ask payload must be an object with string question' };\n }\n const question = payload['question'];\n if (typeof question !== 'string' || question.trim().length === 0) {\n return { ok: false, message: 'brain.ask payload.question must be a non-empty string' };\n }\n return { ok: true, value: { question: question.trim() } };\n}\n\ninterface BrainConfigSetPayload {\n patch: Record<string, unknown>;\n}\n\nexport function validateBrainConfigSetPayload(\n payload: unknown,\n): PayloadValidationResult<BrainConfigSetPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.config.set payload must be an object with a patch object' };\n }\n const patch = payload['patch'];\n if (!isRecord(patch)) {\n // Field-level validation happens in BrainRuntime.apply(), which throws\n // BEFORE any live state changes \u2014 this only guards the envelope shape.\n return { ok: false, message: 'brain.config.set payload.patch must be an object' };\n }\n return { ok: true, value: { patch } };\n}\n\ninterface AutonomySwitchPayload {\n mode: string;\n}\n\nexport function validateAutonomySwitchPayload(\n payload: unknown,\n): PayloadValidationResult<AutonomySwitchPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'autonomy.switch payload must be an object with string mode' };\n }\n const mode = payload['mode'];\n if (typeof mode !== 'string' || !AUTONOMY_VALUES.has(mode)) {\n return { ok: false, message: 'autonomy.switch payload.mode must be a valid autonomy mode' };\n }\n return { ok: true, value: { mode } };\n}\n\ninterface PlanTemplateUsePayload {\n template: string;\n}\n\nexport function validatePlanTemplateUsePayload(\n payload: unknown,\n): PayloadValidationResult<PlanTemplateUsePayload> {\n if (!isRecord(payload)) {\n return {\n ok: false,\n message: 'plan.template_use payload must be an object with string template',\n };\n }\n const template = payload['template'];\n if (typeof template !== 'string' || template.trim().length === 0) {\n return { ok: false, message: 'plan.template_use payload.template must be a non-empty string' };\n }\n return { ok: true, value: { template } };\n}\nconst CONTEXT_STRATEGY_VALUES = new Set(['hybrid', 'intelligent', 'selective']);\nconst CONTEXT_MODE_VALUES = new Set(['balanced', 'frugal', 'deep', 'archival']);\nconst TOKEN_SAVING_TIER_VALUES = new Set(['off', 'minimal', 'light', 'medium', 'aggressive']);\nconst ENHANCE_LANGUAGE_VALUES = new Set(['original', 'english']);\nconst LOG_LEVEL_VALUES = new Set(['debug', 'info', 'warn', 'error']);\nconst AUDIT_LEVEL_VALUES = new Set(['minimal', 'standard', 'full']);\nconst REASONING_MODE_VALUES = new Set(['auto', 'on', 'off']);\nconst REASONING_EFFORT_VALUES = new Set([\n 'none',\n 'minimal',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n 'max',\n]);\nconst CACHE_TTL_VALUES = new Set(['default', '5m', '1h']);\n\nconst BOOLEAN_PREF_KEYS = new Set([\n 'yolo',\n 'chime',\n 'confirmExit',\n 'nextPrediction',\n 'titleAnimation',\n 'enhanceEnabled',\n 'featureMcp',\n 'featurePlugins',\n 'featureMemory',\n 'featureSkills',\n 'featureModelsRegistry',\n 'indexOnStart',\n 'contextAutoCompact',\n 'tgSessionEnd',\n 'tgDelegate',\n 'reasoningPreserve',\n 'hqEnabled',\n 'hqRawContent',\n 'fallbackAuto',\n 'favoriteModelsOnly',\n 'modelAvailabilitySchedule',\n 'breakerEnabled',\n 'debugStream',\n // Chimera + auto-review master toggles\n 'chimeraEnabled',\n 'autoReviewEnabled',\n 'showModelReasoning',\n]);\n\n/** Keys whose value must be an array of strings (e.g. an ordered model list). */\nconst STRING_ARRAY_PREF_KEYS = new Set([\n 'fallbackModels',\n 'favoriteModels',\n // Auto-review explicit fallback chain (derived when fallbackProfile is unset;\n // surfaced for visibility/override).\n 'autoReviewFallbackModels',\n]);\nconst STRING_ARRAY_RECORD_PREF_KEYS = new Set(['fallbackProfiles']);\nconst MODEL_MATRIX_PREF_KEYS = new Set(['modelMatrix']);\n// Object of booleans, e.g. { 'plugin-name': true }. Parity with the embedded\n// server, which accepts `pluginsEnabled` and persists it to\n// extensions.<name>.enabled \u2014 the standalone server rejected it as unknown.\nconst BOOLEAN_RECORD_PREF_KEYS = new Set(['pluginsEnabled']);\n\nconst NUMBER_PREF_KEYS = new Set([\n 'autonomyDelayMs',\n 'autoProceedMaxIterations',\n 'maxIterations',\n 'maxConcurrent',\n 'enhanceDelayMs',\n 'tgLongToolMs',\n 'breakerAutoKillResetMs',\n // Chimera + auto-review numeric knobs\n 'chimeraMaxFiles',\n 'autoReviewDebounceMs',\n 'autoReviewMaxFilesPerBatch',\n 'autoReviewMaxConcurrentReviews',\n]);\n\nconst STRING_PREF_KEYS = new Set([\n 'hqUrl',\n 'hqToken',\n 'uiLocale',\n 'thinkingWord',\n 'refinerProvider',\n 'refinerModel',\n 'refinerFallbackProfile',\n // Chimera + auto-review override strings\n 'chimeraProvider',\n 'chimeraModel',\n 'autoReviewProvider',\n 'autoReviewModel',\n 'autoReviewFallbackProfile',\n]);\n\nconst ENUM_PREF_KEYS: Record<string, Set<string>> = {\n autonomy: AUTONOMY_VALUES,\n contextStrategy: CONTEXT_STRATEGY_VALUES,\n contextMode: CONTEXT_MODE_VALUES,\n tokenSavingTier: TOKEN_SAVING_TIER_VALUES,\n enhanceLanguage: ENHANCE_LANGUAGE_VALUES,\n logLevel: LOG_LEVEL_VALUES,\n auditLevel: AUDIT_LEVEL_VALUES,\n reasoningMode: REASONING_MODE_VALUES,\n reasoningEffort: REASONING_EFFORT_VALUES,\n cacheTtl: CACHE_TTL_VALUES,\n statuslineMode: new Set(['minimum', 'detailed', 'no-color']),\n animationStyle: new Set(['rainbow', 'wave', 'pulse', 'dots', 'breathe', 'cycle']),\n fsAccess: new Set(['unrestricted', 'project']),\n // Chimera autoFix + auto-review cascade threshold\n chimeraAutoFix: new Set(['off', 'ask', 'auto']),\n autoReviewCascadeOn: new Set(['off', 'critical', 'high']),\n fleetChatVerbosity: new Set(['off', 'full']),\n};\n\nfunction validateModelRuntimeValue(\n modelRuntime: Record<string, unknown>,\n path: string,\n): string | null {\n const reasoning = modelRuntime['reasoning'];\n if (reasoning !== undefined) {\n if (!isRecord(reasoning)) return `${path}.reasoning must be an object when provided`;\n const mode = reasoning['mode'];\n const effort = reasoning['effort'];\n const preserve = reasoning['preserve'];\n if (mode !== undefined && (typeof mode !== 'string' || !REASONING_MODE_VALUES.has(mode))) {\n return `${path}.reasoning.mode must be one of: ${Array.from(REASONING_MODE_VALUES).join(', ')}`;\n }\n if (\n effort !== undefined &&\n (typeof effort !== 'string' || !REASONING_EFFORT_VALUES.has(effort))\n ) {\n return `${path}.reasoning.effort must be one of: ${Array.from(REASONING_EFFORT_VALUES).join(', ')}`;\n }\n if (preserve !== undefined && typeof preserve !== 'boolean') {\n return `${path}.reasoning.preserve must be a boolean when provided`;\n }\n }\n\n const cache = modelRuntime['cache'];\n if (cache !== undefined) {\n if (!isRecord(cache)) return `${path}.cache must be an object when provided`;\n const ttl = cache['ttl'];\n if (\n ttl !== undefined &&\n (typeof ttl !== 'string' || !CACHE_TTL_VALUES.has(ttl) || ttl === 'default')\n ) {\n return `${path}.cache.ttl must be one of: 5m, 1h`;\n }\n }\n\n const parameters = modelRuntime['parameters'];\n if (parameters !== undefined && !isRecord(parameters)) {\n return `${path}.parameters must be an object when provided`;\n }\n\n return null;\n}\n\nfunction validatePreferenceValue(key: string, value: unknown): string | null {\n if (BOOLEAN_PREF_KEYS.has(key)) {\n return typeof value === 'boolean' ? null : `prefs.update payload.${key} must be a boolean`;\n }\n if (NUMBER_PREF_KEYS.has(key)) {\n return typeof value === 'number' && Number.isFinite(value)\n ? null\n : `prefs.update payload.${key} must be a finite number`;\n }\n if (STRING_PREF_KEYS.has(key)) {\n return typeof value === 'string' ? null : `prefs.update payload.${key} must be a string`;\n }\n if (STRING_ARRAY_PREF_KEYS.has(key)) {\n return Array.isArray(value) && value.every((v) => typeof v === 'string')\n ? null\n : `prefs.update payload.${key} must be an array of strings`;\n }\n if (STRING_ARRAY_RECORD_PREF_KEYS.has(key)) {\n return isRecord(value) &&\n Object.values(value).every(\n (v) => Array.isArray(v) && v.every((item) => typeof item === 'string'),\n )\n ? null\n : `prefs.update payload.${key} must be an object of string arrays`;\n }\n if (BOOLEAN_RECORD_PREF_KEYS.has(key)) {\n if (!isRecord(value) || !Object.values(value).every((v) => typeof v === 'boolean')) {\n return `prefs.update payload.${key} must be an object of booleans`;\n }\n // The KEYS here are plugin names that get used as property keys downstream\n // (extensions.<name>.enabled), so they must be checked too \u2014 validating\n // only the values let `{\"__proto__\": true}` through to a write that\n // polluted Object.prototype. The persist layer guards as well; this\n // rejects loudly instead of silently dropping the entry.\n const badKey = Object.keys(value).find((k) => FORBIDDEN_PROTO_KEYS.has(k));\n if (badKey) {\n return `prefs.update payload.${key} contains a forbidden key: ${badKey}`;\n }\n return null;\n }\n if (MODEL_MATRIX_PREF_KEYS.has(key)) {\n if (!isRecord(value)) return `prefs.update payload.${key} must be an object`;\n for (const entry of Object.values(value)) {\n if (!isRecord(entry)) return `prefs.update payload.${key} entries must be objects`;\n const provider = entry['provider'];\n const model = entry['model'];\n const fallbackProfile = entry['fallbackProfile'];\n const modelRuntime = entry['modelRuntime'];\n if (provider !== undefined && typeof provider !== 'string') {\n return `prefs.update payload.${key}.provider must be a string when provided`;\n }\n if (model !== undefined && typeof model !== 'string') {\n return `prefs.update payload.${key}.model must be a string when provided`;\n }\n if (fallbackProfile !== undefined && typeof fallbackProfile !== 'string') {\n return `prefs.update payload.${key}.fallbackProfile must be a string when provided`;\n }\n if (modelRuntime !== undefined && !isRecord(modelRuntime)) {\n return `prefs.update payload.${key}.modelRuntime must be an object when provided`;\n }\n if (isRecord(modelRuntime)) {\n const runtimeError = validateModelRuntimeValue(\n modelRuntime,\n `prefs.update payload.${key}.modelRuntime`,\n );\n if (runtimeError) return runtimeError;\n }\n if (model === undefined && fallbackProfile === undefined && modelRuntime === undefined) {\n return `prefs.update payload.${key} entries require model, fallbackProfile, or modelRuntime`;\n }\n }\n return null;\n }\n const allowed = ENUM_PREF_KEYS[key];\n if (allowed) {\n return typeof value === 'string' && allowed.has(value)\n ? null\n : `prefs.update payload.${key} must be one of: ${Array.from(allowed).join(', ')}`;\n }\n return `prefs.update payload contains unknown preference key: ${key}`;\n}\n\nexport function validatePrefsUpdatePayload(\n payload: unknown,\n): PayloadValidationResult<PrefsUpdatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'prefs.update payload must be an object' };\n }\n for (const [key, value] of Object.entries(payload)) {\n const error = validatePreferenceValue(key, value);\n if (error) return { ok: false, message: error };\n }\n return { ok: true, value: { prefs: payload } };\n}\n\ninterface SkillsCreatePayload {\n name: string;\n description: string;\n scope: 'project' | 'global';\n}\n\nexport function validateSkillsCreatePayload(\n payload: unknown,\n): PayloadValidationResult<SkillsCreatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'skills.create payload must be an object' };\n }\n const name = payload['name'];\n const description = payload['description'];\n const scope = payload['scope'];\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'Skill name is required' };\n }\n if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(name.trim())) {\n return { ok: false, message: 'Skill name must be kebab-case (e.g. my-new-skill)' };\n }\n if (typeof description !== 'string' || description.trim().length === 0) {\n return { ok: false, message: 'Description/trigger is required' };\n }\n if (scope !== 'project' && scope !== 'global') {\n return { ok: false, message: 'skills.create payload.scope must be project or global' };\n }\n return { ok: true, value: { name, description, scope } };\n}\n\ninterface SkillsEditPayload {\n name: string;\n body: string;\n}\n\nexport function validateSkillsEditPayload(\n payload: unknown,\n): PayloadValidationResult<SkillsEditPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'skills.edit payload must be an object' };\n }\n const name = payload['name'];\n const body = payload['body'];\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'Skill name is required' };\n }\n if (typeof body !== 'string' || body.length === 0) {\n return { ok: false, message: 'Skill body is required' };\n }\n return { ok: true, value: { name, body } };\n}\n\ninterface ProcessKillPayload {\n pid: number;\n}\n\nexport function validateProcessKillPayload(\n payload: unknown,\n): PayloadValidationResult<ProcessKillPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'process.kill payload must be an object with numeric pid' };\n }\n const pid = payload['pid'];\n if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0) {\n return { ok: false, message: 'process.kill payload.pid must be a positive integer' };\n }\n return { ok: true, value: { pid } };\n}\n\ninterface WorkingDirSetPayload {\n path: string;\n}\n\nexport function validateWorkingDirSetPayload(\n payload: unknown,\n): PayloadValidationResult<WorkingDirSetPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'working_dir.set payload must be an object with string path' };\n }\n const newPath = payload['path'];\n if (typeof newPath !== 'string' || newPath.trim().length === 0) {\n return { ok: false, message: 'working_dir.set payload.path must be a non-empty string' };\n }\n return { ok: true, value: { path: newPath } };\n}\n\ninterface ModeSwitchPayload {\n id: string;\n}\n\nexport function validateModeSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ModeSwitchPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'mode.switch payload must be an object with string id' };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'mode.switch payload.id must be a non-empty string' };\n }\n return { ok: true, value: { id } };\n}\n\ninterface ContextModeIdPayload {\n id: string;\n}\n\nfunction validateContextModeIdPayload(\n payload: unknown,\n type: 'context.mode.switch' | 'context.mode.delete',\n): PayloadValidationResult<ContextModeIdPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: `${type} payload must be an object with string id` };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: `${type} payload.id must be a non-empty string` };\n }\n return { ok: true, value: { id } };\n}\n\nexport function validateContextModeSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeIdPayload> {\n return validateContextModeIdPayload(payload, 'context.mode.switch');\n}\n\nexport function validateContextModeDeletePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeIdPayload> {\n return validateContextModeIdPayload(payload, 'context.mode.delete');\n}\n\ninterface ContextModeCreatePayload {\n id: string;\n name: string;\n description: string;\n thresholds: { warn: number; soft: number; hard: number };\n preserveK: number;\n eliseThreshold: number;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nexport function validateContextModeCreatePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeCreatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'context.mode.create payload must be an object' };\n }\n const id = payload['id'];\n const name = payload['name'];\n const description = payload['description'];\n const thresholds = payload['thresholds'];\n const preserveK = payload['preserveK'];\n const eliseThreshold = payload['eliseThreshold'];\n\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'context.mode.create payload.id must be a non-empty string' };\n }\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'context.mode.create payload.name must be a non-empty string' };\n }\n if (typeof description !== 'string') {\n return { ok: false, message: 'context.mode.create payload.description must be a string' };\n }\n if (!isRecord(thresholds)) {\n return {\n ok: false,\n message:\n 'context.mode.create payload.thresholds must be an object with warn/soft/hard numbers',\n };\n }\n if (\n !isFiniteNumber(thresholds['warn']) ||\n !isFiniteNumber(thresholds['soft']) ||\n !isFiniteNumber(thresholds['hard'])\n ) {\n return {\n ok: false,\n message: 'context.mode.create payload.thresholds.warn/soft/hard must be finite numbers',\n };\n }\n if (!isFiniteNumber(preserveK)) {\n return { ok: false, message: 'context.mode.create payload.preserveK must be a finite number' };\n }\n if (!isFiniteNumber(eliseThreshold)) {\n return {\n ok: false,\n message: 'context.mode.create payload.eliseThreshold must be a finite number',\n };\n }\n return {\n ok: true,\n value: {\n id,\n name,\n description,\n thresholds: { warn: thresholds['warn'], soft: thresholds['soft'], hard: thresholds['hard'] },\n preserveK,\n eliseThreshold,\n },\n };\n}\n\ninterface ContextModeUpdatePayload {\n id: string;\n name?: string;\n description?: string;\n thresholds?: { warn?: number; soft?: number; hard?: number };\n preserveK?: number;\n eliseThreshold?: number;\n}\n\nexport function validateContextModeUpdatePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeUpdatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'context.mode.update payload must be an object' };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'context.mode.update payload.id must be a non-empty string' };\n }\n\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return {\n ok: false,\n message: 'context.mode.update payload.name must be a string when provided',\n };\n }\n\n const description = payload['description'];\n if (description !== undefined && typeof description !== 'string') {\n return {\n ok: false,\n message: 'context.mode.update payload.description must be a string when provided',\n };\n }\n\n const thresholds = payload['thresholds'];\n let validatedThresholds: ContextModeUpdatePayload['thresholds'];\n if (thresholds !== undefined) {\n if (!isRecord(thresholds)) {\n return {\n ok: false,\n message: 'context.mode.update payload.thresholds must be an object when provided',\n };\n }\n for (const key of ['warn', 'soft', 'hard'] as const) {\n const val = thresholds[key];\n if (val !== undefined && !isFiniteNumber(val)) {\n return {\n ok: false,\n message: `context.mode.update payload.thresholds.${key} must be a finite number when provided`,\n };\n }\n }\n validatedThresholds = {\n ...(typeof thresholds['warn'] === 'number' ? { warn: thresholds['warn'] } : {}),\n ...(typeof thresholds['soft'] === 'number' ? { soft: thresholds['soft'] } : {}),\n ...(typeof thresholds['hard'] === 'number' ? { hard: thresholds['hard'] } : {}),\n };\n }\n\n const preserveK = payload['preserveK'];\n if (preserveK !== undefined && !isFiniteNumber(preserveK)) {\n return {\n ok: false,\n message: 'context.mode.update payload.preserveK must be a finite number when provided',\n };\n }\n\n const eliseThreshold = payload['eliseThreshold'];\n if (eliseThreshold !== undefined && !isFiniteNumber(eliseThreshold)) {\n return {\n ok: false,\n message: 'context.mode.update payload.eliseThreshold must be a finite number when provided',\n };\n }\n\n return {\n ok: true,\n value: {\n id,\n ...(typeof name === 'string' ? { name } : {}),\n ...(typeof description === 'string' ? { description } : {}),\n ...(validatedThresholds !== undefined ? { thresholds: validatedThresholds } : {}),\n ...(typeof preserveK === 'number' ? { preserveK } : {}),\n ...(typeof eliseThreshold === 'number' ? { eliseThreshold } : {}),\n },\n };\n}\n\ninterface ShellOpenPayload {\n path: string;\n target?: 'file' | 'terminal';\n}\n\nexport function validateShellOpenPayload(\n payload: unknown,\n): PayloadValidationResult<ShellOpenPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'shell.open payload must be an object with string path' };\n }\n const path = payload['path'];\n if (typeof path !== 'string' || path.trim().length === 0) {\n return { ok: false, message: 'shell.open payload.path must be a non-empty string' };\n }\n const target = payload['target'];\n if (target !== undefined && target !== 'file' && target !== 'terminal') {\n return {\n ok: false,\n message: 'shell.open payload.target must be \"file\" or \"terminal\" when provided',\n };\n }\n return {\n ok: true,\n value: {\n path,\n ...(target !== undefined ? { target: target as 'file' | 'terminal' } : {}),\n },\n };\n}\n\ninterface GitDiffPayload {\n path: string;\n}\n\nexport function validateGitDiffPayload(payload: unknown): PayloadValidationResult<GitDiffPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'git.diff payload must be an object' };\n }\n const path = payload['path'];\n if (path === undefined || path === null) {\n return { ok: true, value: { path: '' } };\n }\n if (typeof path !== 'string') {\n return { ok: false, message: 'git.diff payload.path must be a string when provided' };\n }\n return { ok: true, value: { path } };\n}\n\ninterface ProjectsAddPayload {\n root: string;\n name?: string;\n}\n\nexport function validateProjectsAddPayload(\n payload: unknown,\n): PayloadValidationResult<ProjectsAddPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'projects.add payload must be an object with string root' };\n }\n const root = payload['root'];\n if (typeof root !== 'string' || root.trim().length === 0) {\n return { ok: false, message: 'projects.add payload.root must be a non-empty string' };\n }\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return { ok: false, message: 'projects.add payload.name must be a string when provided' };\n }\n return {\n ok: true,\n value: { root, ...(typeof name === 'string' ? { name } : {}) },\n };\n}\n\ninterface ProjectsSelectPayload {\n root: string;\n name?: string;\n}\n\nexport function validateProjectsSelectPayload(\n payload: unknown,\n): PayloadValidationResult<ProjectsSelectPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'projects.select payload must be an object with string root' };\n }\n const root = payload['root'];\n if (typeof root !== 'string' || root.trim().length === 0) {\n return { ok: false, message: 'projects.select payload.root must be a non-empty string' };\n }\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return { ok: false, message: 'projects.select payload.name must be a string when provided' };\n }\n return {\n ok: true,\n value: { root, ...(typeof name === 'string' ? { name } : {}) },\n };\n}\n"],
|
|
5
|
-
"mappings": ";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;
|
|
4
|
+
"sourcesContent": ["import {\n addPlanItem,\n emptyPlan,\n getPlanTemplate,\n loadPlan,\n loadTasks,\n mutatePlan,\n mutateTasks,\n savePlan,\n setPlanItemStatus,\n} from '@wrongstack/core/storage';\nimport type { TodoItem } from '@wrongstack/core/agent';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from '../types.js';\nimport { validatePlanTemplateUsePayload } from '../ws-payload-validation.js';\n\nexport interface WorklistContext {\n context: {\n todos: TodoItem[];\n meta: Record<string, unknown>;\n session: { id: string } | null;\n };\n send: (ws: WebSocket, msg: WSServerMessage) => void;\n broadcast: (msg: WSServerMessage) => void;\n replaceTodos?: ((todos: TodoItem[]) => void) | undefined;\n}\n\nexport interface WorklistMessage {\n type: string;\n payload?: unknown;\n}\n\nfunction sendResult(ctx: WorklistContext, ws: WebSocket, success: boolean, message: string): void {\n ctx.send(ws, { type: 'key.operation_result', payload: { success, message } });\n}\n\nfunction currentSessionId(ctx: WorklistContext): string {\n return ctx.context.session?.id ?? '';\n}\n\nfunction sessionPayload<T extends Record<string, unknown>>(\n ctx: WorklistContext,\n payload: T,\n): T & { sessionId: string } {\n const provided = payload['sessionId'];\n const sessionId =\n typeof provided === 'string' && provided.length > 0 ? provided : currentSessionId(ctx);\n return { ...payload, sessionId };\n}\n\nfunction planPathOf(ctx: WorklistContext): string | undefined {\n const value = ctx.context.meta['plan.path'];\n return typeof value === 'string' && value ? value : undefined;\n}\n\nfunction taskPathOf(ctx: WorklistContext): string | undefined {\n const value = ctx.context.meta['task.path'];\n return typeof value === 'string' && value ? value : undefined;\n}\n\nexport function handleTodosGet(ctx: WorklistContext, ws: WebSocket): void {\n ctx.send(ws, {\n type: 'todos.updated',\n payload: sessionPayload(ctx, { todos: [...ctx.context.todos] }),\n });\n}\n\nexport function handleTodosClear(ctx: WorklistContext, ws: WebSocket): void {\n ctx.replaceTodos?.([]);\n sendResult(ctx, ws, true, 'Todos cleared');\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: [] }) });\n}\n\nexport function handleTodosRemove(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { id?: string | undefined; index?: number | undefined } | undefined,\n): void {\n if (!payload) {\n sendResult(ctx, ws, false, 'Missing id or index');\n return;\n }\n const todos = ctx.context.todos;\n let targetIndex = -1;\n if (typeof payload.id === 'string') {\n targetIndex = todos.findIndex((todo) => todo.id === payload.id);\n } else if (typeof payload.index === 'number' && payload.index > 0) {\n targetIndex = payload.index - 1;\n }\n const removed = todos[targetIndex];\n if (targetIndex < 0 || !removed) {\n sendResult(ctx, ws, false, 'Todo not found');\n return;\n }\n const next = [...todos.slice(0, targetIndex), ...todos.slice(targetIndex + 1)];\n ctx.replaceTodos?.(next);\n sendResult(ctx, ws, true, `Removed: ${removed.content}`);\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: next }) });\n}\n\nexport function handleTodoUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { id: string; status?: TodoItem['status'] | undefined; activeForm?: string | undefined },\n): void {\n const index = ctx.context.todos.findIndex((todo) => todo.id === payload.id);\n const existing = ctx.context.todos[index];\n if (index === -1 || !existing) {\n sendResult(ctx, ws, false, 'Todo not found');\n return;\n }\n const next = [...ctx.context.todos];\n next[index] = {\n ...existing,\n status: payload.status ?? existing.status,\n activeForm: payload.activeForm !== undefined ? payload.activeForm : existing.activeForm,\n };\n ctx.replaceTodos?.(next);\n sendResult(ctx, ws, true, `Todo \"${existing.content}\" updated`);\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: next }) });\n}\n\nexport async function handleTasksGet(ctx: WorklistContext, ws: WebSocket): Promise<void> {\n const taskPath = taskPathOf(ctx);\n if (!taskPath) {\n ctx.send(ws, {\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: [], error: 'Task storage not configured.' }),\n });\n return;\n }\n try {\n const file = await loadTasks(taskPath);\n ctx.send(ws, {\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: file?.tasks ?? [] }),\n });\n } catch {\n ctx.send(ws, { type: 'tasks.updated', payload: sessionPayload(ctx, { tasks: [] }) });\n }\n}\n\nexport async function handleTaskUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: {\n id: string;\n status: 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\n },\n): Promise<void> {\n const taskPath = taskPathOf(ctx);\n if (!taskPath) {\n sendResult(ctx, ws, false, 'Task storage not configured.');\n return;\n }\n try {\n const file = await mutateTasks(taskPath, currentSessionId(ctx), async (tasks) => {\n const task = tasks.tasks.find((candidate) => candidate.id === payload.id);\n if (!task) return tasks;\n task.status = payload.status;\n task.updatedAt = new Date().toISOString();\n return tasks;\n });\n sendResult(ctx, ws, true, `Task status updated to \"${payload.status}\".`);\n ctx.broadcast({\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: file.tasks }),\n });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handlePlanGet(ctx: WorklistContext, ws: WebSocket): Promise<void> {\n const planPath = planPathOf(ctx);\n const emptySnapshot = () => ({\n version: 1,\n sessionId: currentSessionId(ctx),\n updatedAt: new Date().toISOString(),\n items: [],\n });\n if (!planPath) {\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, {\n plan: null,\n error: 'Plan storage is not configured for this session.',\n }),\n });\n return;\n }\n try {\n const plan = await loadPlan(planPath);\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, { plan: plan ?? emptySnapshot() }),\n });\n } catch {\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, { plan: emptySnapshot() }),\n });\n }\n}\n\nexport async function handlePlanTemplateUse(\n ctx: WorklistContext,\n ws: WebSocket,\n template: string,\n): Promise<void> {\n const planPath = planPathOf(ctx);\n if (!planPath) {\n sendResult(ctx, ws, false, 'Plan storage is not configured for this session.');\n return;\n }\n try {\n const templateDefinition = getPlanTemplate(template);\n if (!templateDefinition) {\n sendResult(ctx, ws, false, `Unknown template \"${template}\".`);\n return;\n }\n let plan = (await loadPlan(planPath)) ?? emptyPlan(currentSessionId(ctx));\n for (const item of templateDefinition.items) {\n ({ plan } = addPlanItem(plan, item.title, item.details));\n }\n await savePlan(planPath, plan);\n sendResult(\n ctx,\n ws,\n true,\n `Applied template \"${templateDefinition.name}\" \u2014 ${templateDefinition.items.length} items added.`,\n );\n ctx.broadcast({ type: 'plan.updated', payload: sessionPayload(ctx, { plan }) });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handlePlanItemUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { target: string; status: 'open' | 'in_progress' | 'done' },\n): Promise<void> {\n const planPath = planPathOf(ctx);\n if (!planPath) {\n sendResult(ctx, ws, false, 'Plan storage is not configured for this session.');\n return;\n }\n try {\n let changed = false;\n const plan = await mutatePlan(planPath, currentSessionId(ctx), async (currentPlan) => {\n const before = currentPlan.updatedAt;\n const next = setPlanItemStatus(currentPlan, payload.target, payload.status);\n changed = next.updatedAt !== before;\n return next;\n });\n if (!changed) {\n sendResult(ctx, ws, false, `No plan item matched \"${payload.target}\".`);\n return;\n }\n sendResult(ctx, ws, true, `Plan item status updated to \"${payload.status}\".`);\n ctx.broadcast({ type: 'plan.updated', payload: sessionPayload(ctx, { plan }) });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handleWorklistMessage(\n ctx: WorklistContext,\n ws: WebSocket,\n message: WorklistMessage,\n): Promise<void> {\n switch (message.type) {\n case 'todos.get':\n handleTodosGet(ctx, ws);\n return;\n case 'todos.clear':\n handleTodosClear(ctx, ws);\n return;\n case 'todos.remove':\n handleTodosRemove(ctx, ws, message.payload as { id?: string; index?: number } | undefined);\n return;\n case 'todo.update':\n handleTodoUpdate(\n ctx,\n ws,\n message.payload as {\n id: string;\n status?: TodoItem['status'];\n activeForm?: string;\n },\n );\n return;\n case 'tasks.get':\n await handleTasksGet(ctx, ws);\n return;\n case 'task.update':\n await handleTaskUpdate(\n ctx,\n ws,\n message.payload as {\n id: string;\n status: 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\n },\n );\n return;\n case 'plan.get':\n await handlePlanGet(ctx, ws);\n return;\n case 'plan.template_use': {\n const parsed = validatePlanTemplateUsePayload(message.payload);\n if (!parsed.ok) {\n sendResult(ctx, ws, false, parsed.message);\n return;\n }\n await handlePlanTemplateUse(ctx, ws, parsed.value.template);\n return;\n }\n case 'plan.item.update':\n await handlePlanItemUpdate(\n ctx,\n ws,\n message.payload as { target: string; status: 'open' | 'in_progress' | 'done' },\n );\n }\n}\n", "export { validatePrefsUpdatePayload } from './ws-payload-preferences.js';\n\ntype PayloadValidationResult<T> = { ok: true; value: T } | { ok: false; message: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\ninterface ModelSwitchPayload {\n provider: string;\n model: string;\n requestId?: string | undefined;\n}\n\nexport function validateModelSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ModelSwitchPayload> {\n if (!isRecord(payload)) {\n return {\n ok: false,\n message: 'model.switch payload must be an object with string provider and model',\n };\n }\n const provider = payload['provider'];\n const model = payload['model'];\n const requestId = payload['requestId'];\n if (typeof provider !== 'string' || provider.trim().length === 0) {\n return { ok: false, message: 'model.switch payload.provider must be a non-empty string' };\n }\n if (typeof model !== 'string' || model.trim().length === 0) {\n return { ok: false, message: 'model.switch payload.model must be a non-empty string' };\n }\n if (requestId !== undefined && (typeof requestId !== 'string' || requestId.trim().length === 0)) {\n return { ok: false, message: 'model.switch payload.requestId must be a non-empty string' };\n }\n return {\n ok: true,\n value: {\n provider: provider.trim(),\n model: model.trim(),\n ...(typeof requestId === 'string' ? { requestId: requestId.trim() } : {}),\n },\n };\n}\n\nconst AUTONOMY_VALUES = new Set(['off', 'suggest', 'auto', 'eternal', 'eternal-parallel']);\n\ninterface MailboxMessagesPayload {\n limit?: number;\n agentId?: string;\n unreadOnly?: boolean;\n incompleteOnly?: boolean;\n}\n\nexport function validateMailboxMessagesPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxMessagesPayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.messages payload must be an object when provided' };\n }\n const limit = payload['limit'];\n const agentId = payload['agentId'];\n const unreadOnly = payload['unreadOnly'];\n const incompleteOnly = payload['incompleteOnly'];\n if (limit !== undefined && (typeof limit !== 'number' || !Number.isFinite(limit) || limit < 1)) {\n return {\n ok: false,\n message: 'mailbox.messages payload.limit must be a positive number when provided',\n };\n }\n if (agentId !== undefined && typeof agentId !== 'string') {\n return {\n ok: false,\n message: 'mailbox.messages payload.agentId must be a string when provided',\n };\n }\n if (unreadOnly !== undefined && typeof unreadOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.messages payload.unreadOnly must be a boolean when provided',\n };\n }\n if (incompleteOnly !== undefined && typeof incompleteOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.messages payload.incompleteOnly must be a boolean when provided',\n };\n }\n return {\n ok: true,\n value: {\n ...(limit !== undefined ? { limit: limit as number } : {}),\n ...(agentId !== undefined ? { agentId: agentId as string } : {}),\n ...(unreadOnly !== undefined ? { unreadOnly: unreadOnly as boolean } : {}),\n ...(incompleteOnly !== undefined ? { incompleteOnly: incompleteOnly as boolean } : {}),\n },\n };\n}\n\ninterface MailboxAgentsPayload {\n onlineOnly?: boolean;\n}\n\nconst MAILBOX_SEND_TYPES = new Set([\n 'note',\n 'ask',\n 'assign',\n 'steer',\n 'btw',\n 'broadcast',\n 'status',\n 'result',\n 'review',\n]);\n\nexport interface MailboxSendPayload {\n requestId: string;\n to: string;\n type: 'note' | 'ask' | 'assign' | 'steer' | 'btw' | 'broadcast' | 'status' | 'result' | 'review';\n audience: 'all' | 'leaders';\n subject: string;\n body: string;\n priority: 'low' | 'normal' | 'high';\n replyTo?: string | undefined;\n}\n\nexport function validateMailboxSendPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxSendPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.send payload must be an object' };\n }\n const requestId = payload['requestId'];\n const rawTo = payload['to'];\n const rawType = payload['type'];\n const rawAudience = payload['audience'];\n const rawSubject = payload['subject'];\n const rawBody = payload['body'];\n const rawPriority = payload['priority'];\n const rawReplyTo = payload['replyTo'];\n\n if (typeof requestId !== 'string' || requestId.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.requestId must be a non-empty string' };\n }\n if (typeof rawTo !== 'string' || rawTo.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.to must be a non-empty string' };\n }\n if (typeof rawType !== 'string' || !MAILBOX_SEND_TYPES.has(rawType)) {\n return {\n ok: false,\n message: 'mailbox.send payload.type must be a supported non-control message type',\n };\n }\n if (rawAudience !== 'all' && rawAudience !== 'leaders') {\n return { ok: false, message: 'mailbox.send payload.audience must be all or leaders' };\n }\n if (typeof rawSubject !== 'string' || rawSubject.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.subject must be a non-empty string' };\n }\n if (typeof rawBody !== 'string' || rawBody.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.body must be a non-empty string' };\n }\n if (rawPriority !== 'low' && rawPriority !== 'normal' && rawPriority !== 'high') {\n return { ok: false, message: 'mailbox.send payload.priority must be low, normal, or high' };\n }\n if (rawReplyTo !== undefined && typeof rawReplyTo !== 'string') {\n return { ok: false, message: 'mailbox.send payload.replyTo must be a string when provided' };\n }\n\n const type = rawType as MailboxSendPayload['type'];\n const to = type === 'broadcast' ? '*' : rawTo.trim();\n if ((type === 'assign' || type === 'steer') && (to === '*' || to.toLowerCase() === 'all')) {\n return {\n ok: false,\n message: `mailbox.send payload.type ${type} requires a specific recipient`,\n };\n }\n\n return {\n ok: true,\n value: {\n requestId: requestId.trim(),\n to,\n type,\n audience: rawAudience,\n subject: rawSubject.trim(),\n body: rawBody.trim(),\n priority: rawPriority,\n ...(rawReplyTo !== undefined ? { replyTo: rawReplyTo } : {}),\n },\n };\n}\n\nexport function validateMailboxAgentsPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxAgentsPayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.agents payload must be an object when provided' };\n }\n const onlineOnly = payload['onlineOnly'];\n if (onlineOnly !== undefined && typeof onlineOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.agents payload.onlineOnly must be a boolean when provided',\n };\n }\n return {\n ok: true,\n value: { ...(onlineOnly !== undefined ? { onlineOnly: onlineOnly as boolean } : {}) },\n };\n}\n\ninterface MailboxPurgePayload {\n completedMaxAgeMs?: number;\n incompleteMaxAgeMs?: number;\n}\n\nexport function validateMailboxPurgePayload(\n payload: unknown,\n): PayloadValidationResult<MailboxPurgePayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.purge payload must be an object when provided' };\n }\n const completedMaxAgeMs = payload['completedMaxAgeMs'];\n const incompleteMaxAgeMs = payload['incompleteMaxAgeMs'];\n if (\n completedMaxAgeMs !== undefined &&\n (typeof completedMaxAgeMs !== 'number' ||\n !Number.isFinite(completedMaxAgeMs) ||\n completedMaxAgeMs < 0)\n ) {\n return {\n ok: false,\n message:\n 'mailbox.purge payload.completedMaxAgeMs must be a non-negative number when provided',\n };\n }\n if (\n incompleteMaxAgeMs !== undefined &&\n (typeof incompleteMaxAgeMs !== 'number' ||\n !Number.isFinite(incompleteMaxAgeMs) ||\n incompleteMaxAgeMs < 0)\n ) {\n return {\n ok: false,\n message:\n 'mailbox.purge payload.incompleteMaxAgeMs must be a non-negative number when provided',\n };\n }\n return {\n ok: true,\n value: {\n ...(completedMaxAgeMs !== undefined\n ? { completedMaxAgeMs: completedMaxAgeMs as number }\n : {}),\n ...(incompleteMaxAgeMs !== undefined\n ? { incompleteMaxAgeMs: incompleteMaxAgeMs as number }\n : {}),\n },\n };\n}\n\ninterface BrainRiskPayload {\n level: string;\n}\n\nconst BRAIN_RISK_VALUES = new Set(['off', 'low', 'medium', 'high', 'all']);\n\nexport function validateBrainRiskPayload(\n payload: unknown,\n): PayloadValidationResult<BrainRiskPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.risk payload must be an object with string level' };\n }\n const level = payload['level'];\n if (typeof level !== 'string' || !BRAIN_RISK_VALUES.has(level)) {\n return {\n ok: false,\n message: 'brain.risk payload.level must be one of off, low, medium, high, all',\n };\n }\n return { ok: true, value: { level } };\n}\n\ninterface BrainAskPayload {\n question: string;\n}\n\nexport function validateBrainAskPayload(\n payload: unknown,\n): PayloadValidationResult<BrainAskPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.ask payload must be an object with string question' };\n }\n const question = payload['question'];\n if (typeof question !== 'string' || question.trim().length === 0) {\n return { ok: false, message: 'brain.ask payload.question must be a non-empty string' };\n }\n return { ok: true, value: { question: question.trim() } };\n}\n\ninterface BrainConfigSetPayload {\n patch: Record<string, unknown>;\n}\n\nexport function validateBrainConfigSetPayload(\n payload: unknown,\n): PayloadValidationResult<BrainConfigSetPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.config.set payload must be an object with a patch object' };\n }\n const patch = payload['patch'];\n if (!isRecord(patch)) {\n // Field-level validation happens in BrainRuntime.apply(), which throws\n // BEFORE any live state changes \u2014 this only guards the envelope shape.\n return { ok: false, message: 'brain.config.set payload.patch must be an object' };\n }\n return { ok: true, value: { patch } };\n}\n\ninterface AutonomySwitchPayload {\n mode: string;\n}\n\nexport function validateAutonomySwitchPayload(\n payload: unknown,\n): PayloadValidationResult<AutonomySwitchPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'autonomy.switch payload must be an object with string mode' };\n }\n const mode = payload['mode'];\n if (typeof mode !== 'string' || !AUTONOMY_VALUES.has(mode)) {\n return { ok: false, message: 'autonomy.switch payload.mode must be a valid autonomy mode' };\n }\n return { ok: true, value: { mode } };\n}\n\ninterface PlanTemplateUsePayload {\n template: string;\n}\n\nexport function validatePlanTemplateUsePayload(\n payload: unknown,\n): PayloadValidationResult<PlanTemplateUsePayload> {\n if (!isRecord(payload)) {\n return {\n ok: false,\n message: 'plan.template_use payload must be an object with string template',\n };\n }\n const template = payload['template'];\n if (typeof template !== 'string' || template.trim().length === 0) {\n return { ok: false, message: 'plan.template_use payload.template must be a non-empty string' };\n }\n return { ok: true, value: { template } };\n}\ninterface SkillsCreatePayload {\n name: string;\n description: string;\n scope: 'project' | 'global';\n}\n\nexport function validateSkillsCreatePayload(\n payload: unknown,\n): PayloadValidationResult<SkillsCreatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'skills.create payload must be an object' };\n }\n const name = payload['name'];\n const description = payload['description'];\n const scope = payload['scope'];\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'Skill name is required' };\n }\n if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(name.trim())) {\n return { ok: false, message: 'Skill name must be kebab-case (e.g. my-new-skill)' };\n }\n if (typeof description !== 'string' || description.trim().length === 0) {\n return { ok: false, message: 'Description/trigger is required' };\n }\n if (scope !== 'project' && scope !== 'global') {\n return { ok: false, message: 'skills.create payload.scope must be project or global' };\n }\n return { ok: true, value: { name, description, scope } };\n}\n\ninterface SkillsEditPayload {\n name: string;\n body: string;\n}\n\nexport function validateSkillsEditPayload(\n payload: unknown,\n): PayloadValidationResult<SkillsEditPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'skills.edit payload must be an object' };\n }\n const name = payload['name'];\n const body = payload['body'];\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'Skill name is required' };\n }\n if (typeof body !== 'string' || body.length === 0) {\n return { ok: false, message: 'Skill body is required' };\n }\n return { ok: true, value: { name, body } };\n}\n\ninterface ProcessKillPayload {\n pid: number;\n}\n\nexport function validateProcessKillPayload(\n payload: unknown,\n): PayloadValidationResult<ProcessKillPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'process.kill payload must be an object with numeric pid' };\n }\n const pid = payload['pid'];\n if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0) {\n return { ok: false, message: 'process.kill payload.pid must be a positive integer' };\n }\n return { ok: true, value: { pid } };\n}\n\ninterface WorkingDirSetPayload {\n path: string;\n}\n\nexport function validateWorkingDirSetPayload(\n payload: unknown,\n): PayloadValidationResult<WorkingDirSetPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'working_dir.set payload must be an object with string path' };\n }\n const newPath = payload['path'];\n if (typeof newPath !== 'string' || newPath.trim().length === 0) {\n return { ok: false, message: 'working_dir.set payload.path must be a non-empty string' };\n }\n return { ok: true, value: { path: newPath } };\n}\n\ninterface ModeSwitchPayload {\n id: string;\n}\n\nexport function validateModeSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ModeSwitchPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'mode.switch payload must be an object with string id' };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'mode.switch payload.id must be a non-empty string' };\n }\n return { ok: true, value: { id } };\n}\n\ninterface ContextModeIdPayload {\n id: string;\n}\n\nfunction validateContextModeIdPayload(\n payload: unknown,\n type: 'context.mode.switch' | 'context.mode.delete',\n): PayloadValidationResult<ContextModeIdPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: `${type} payload must be an object with string id` };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: `${type} payload.id must be a non-empty string` };\n }\n return { ok: true, value: { id } };\n}\n\nexport function validateContextModeSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeIdPayload> {\n return validateContextModeIdPayload(payload, 'context.mode.switch');\n}\n\nexport function validateContextModeDeletePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeIdPayload> {\n return validateContextModeIdPayload(payload, 'context.mode.delete');\n}\n\ninterface ContextModeCreatePayload {\n id: string;\n name: string;\n description: string;\n thresholds: { warn: number; soft: number; hard: number };\n preserveK: number;\n eliseThreshold: number;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nexport function validateContextModeCreatePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeCreatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'context.mode.create payload must be an object' };\n }\n const id = payload['id'];\n const name = payload['name'];\n const description = payload['description'];\n const thresholds = payload['thresholds'];\n const preserveK = payload['preserveK'];\n const eliseThreshold = payload['eliseThreshold'];\n\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'context.mode.create payload.id must be a non-empty string' };\n }\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'context.mode.create payload.name must be a non-empty string' };\n }\n if (typeof description !== 'string') {\n return { ok: false, message: 'context.mode.create payload.description must be a string' };\n }\n if (!isRecord(thresholds)) {\n return {\n ok: false,\n message:\n 'context.mode.create payload.thresholds must be an object with warn/soft/hard numbers',\n };\n }\n if (\n !isFiniteNumber(thresholds['warn']) ||\n !isFiniteNumber(thresholds['soft']) ||\n !isFiniteNumber(thresholds['hard'])\n ) {\n return {\n ok: false,\n message: 'context.mode.create payload.thresholds.warn/soft/hard must be finite numbers',\n };\n }\n if (!isFiniteNumber(preserveK)) {\n return { ok: false, message: 'context.mode.create payload.preserveK must be a finite number' };\n }\n if (!isFiniteNumber(eliseThreshold)) {\n return {\n ok: false,\n message: 'context.mode.create payload.eliseThreshold must be a finite number',\n };\n }\n return {\n ok: true,\n value: {\n id,\n name,\n description,\n thresholds: { warn: thresholds['warn'], soft: thresholds['soft'], hard: thresholds['hard'] },\n preserveK,\n eliseThreshold,\n },\n };\n}\n\ninterface ContextModeUpdatePayload {\n id: string;\n name?: string;\n description?: string;\n thresholds?: { warn?: number; soft?: number; hard?: number };\n preserveK?: number;\n eliseThreshold?: number;\n}\n\nexport function validateContextModeUpdatePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeUpdatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'context.mode.update payload must be an object' };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'context.mode.update payload.id must be a non-empty string' };\n }\n\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return {\n ok: false,\n message: 'context.mode.update payload.name must be a string when provided',\n };\n }\n\n const description = payload['description'];\n if (description !== undefined && typeof description !== 'string') {\n return {\n ok: false,\n message: 'context.mode.update payload.description must be a string when provided',\n };\n }\n\n const thresholds = payload['thresholds'];\n let validatedThresholds: ContextModeUpdatePayload['thresholds'];\n if (thresholds !== undefined) {\n if (!isRecord(thresholds)) {\n return {\n ok: false,\n message: 'context.mode.update payload.thresholds must be an object when provided',\n };\n }\n for (const key of ['warn', 'soft', 'hard'] as const) {\n const val = thresholds[key];\n if (val !== undefined && !isFiniteNumber(val)) {\n return {\n ok: false,\n message: `context.mode.update payload.thresholds.${key} must be a finite number when provided`,\n };\n }\n }\n validatedThresholds = {\n ...(typeof thresholds['warn'] === 'number' ? { warn: thresholds['warn'] } : {}),\n ...(typeof thresholds['soft'] === 'number' ? { soft: thresholds['soft'] } : {}),\n ...(typeof thresholds['hard'] === 'number' ? { hard: thresholds['hard'] } : {}),\n };\n }\n\n const preserveK = payload['preserveK'];\n if (preserveK !== undefined && !isFiniteNumber(preserveK)) {\n return {\n ok: false,\n message: 'context.mode.update payload.preserveK must be a finite number when provided',\n };\n }\n\n const eliseThreshold = payload['eliseThreshold'];\n if (eliseThreshold !== undefined && !isFiniteNumber(eliseThreshold)) {\n return {\n ok: false,\n message: 'context.mode.update payload.eliseThreshold must be a finite number when provided',\n };\n }\n\n return {\n ok: true,\n value: {\n id,\n ...(typeof name === 'string' ? { name } : {}),\n ...(typeof description === 'string' ? { description } : {}),\n ...(validatedThresholds !== undefined ? { thresholds: validatedThresholds } : {}),\n ...(typeof preserveK === 'number' ? { preserveK } : {}),\n ...(typeof eliseThreshold === 'number' ? { eliseThreshold } : {}),\n },\n };\n}\n\ninterface ShellOpenPayload {\n path: string;\n target?: 'file' | 'terminal';\n}\n\nexport function validateShellOpenPayload(\n payload: unknown,\n): PayloadValidationResult<ShellOpenPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'shell.open payload must be an object with string path' };\n }\n const path = payload['path'];\n if (typeof path !== 'string' || path.trim().length === 0) {\n return { ok: false, message: 'shell.open payload.path must be a non-empty string' };\n }\n const target = payload['target'];\n if (target !== undefined && target !== 'file' && target !== 'terminal') {\n return {\n ok: false,\n message: 'shell.open payload.target must be \"file\" or \"terminal\" when provided',\n };\n }\n return {\n ok: true,\n value: {\n path,\n ...(target !== undefined ? { target: target as 'file' | 'terminal' } : {}),\n },\n };\n}\n\ninterface GitDiffPayload {\n path: string;\n}\n\nexport function validateGitDiffPayload(payload: unknown): PayloadValidationResult<GitDiffPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'git.diff payload must be an object' };\n }\n const path = payload['path'];\n if (path === undefined || path === null) {\n return { ok: true, value: { path: '' } };\n }\n if (typeof path !== 'string') {\n return { ok: false, message: 'git.diff payload.path must be a string when provided' };\n }\n return { ok: true, value: { path } };\n}\n\ninterface ProjectsAddPayload {\n root: string;\n name?: string;\n}\n\nexport function validateProjectsAddPayload(\n payload: unknown,\n): PayloadValidationResult<ProjectsAddPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'projects.add payload must be an object with string root' };\n }\n const root = payload['root'];\n if (typeof root !== 'string' || root.trim().length === 0) {\n return { ok: false, message: 'projects.add payload.root must be a non-empty string' };\n }\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return { ok: false, message: 'projects.add payload.name must be a string when provided' };\n }\n return {\n ok: true,\n value: { root, ...(typeof name === 'string' ? { name } : {}) },\n };\n}\n\ninterface ProjectsSelectPayload {\n root: string;\n name?: string;\n}\n\nexport function validateProjectsSelectPayload(\n payload: unknown,\n): PayloadValidationResult<ProjectsSelectPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'projects.select payload must be an object with string root' };\n }\n const root = payload['root'];\n if (typeof root !== 'string' || root.trim().length === 0) {\n return { ok: false, message: 'projects.select payload.root must be a non-empty string' };\n }\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return { ok: false, message: 'projects.select payload.name must be a string when provided' };\n }\n return {\n ok: true,\n value: { root, ...(typeof name === 'string' ? { name } : {}) },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* http-server.ts to keep the static-serve/routing concern separate from the
|
|
4
4
|
* (substantial) Fleet-HQ session/mailbox API. Every handler is a pure,
|
|
5
5
|
* param-based function: it takes the Node req/res plus the globalRoot and reads
|
|
6
|
-
* the cross-process SessionRegistry /
|
|
6
|
+
* the cross-process SessionRegistry / project mailbox via dynamic core imports.
|
|
7
7
|
* createHttpServer() in http-server.ts dispatches to these.
|
|
8
8
|
*/
|
|
9
9
|
import type * as http from 'node:http';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-handlers.d.ts","sourceRoot":"","sources":["../../../src/server/http-server/api-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAEvC,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,IAAI,CAAC,CAwCf;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAqCf;AAoJD,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAwBD,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA2Ef;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAwDf;AAED;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"api-handlers.d.ts","sourceRoot":"","sources":["../../../src/server/http-server/api-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAEvC,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,IAAI,CAAC,CAwCf;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAqCf;AAoJD,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAwBD,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA2Ef;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAwDf;AAED;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,IAAI,CAAC,CAkFf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../../src/server/http-server.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../../src/server/http-server.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAwBlC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAWL,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAQjC,MAAM,WAAW,uBAAuB;IACtC,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,kFAAkF;IAClF,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC;;;OAGG;IACH,cAAc,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAChD;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACvC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACjE;;;;;OAKG;IACH,MAAM,CAAC,EACH,CAAC,MAAM;QAAE,QAAQ,EAAE,OAAO,wBAAwB,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,GAC1F,SAAS,CAAC;IACd,4EAA4E;IAC5E,uBAAuB,CAAC,EAAE,OAAO,yBAAyB,EAAE,oBAAoB,CAAC,yBAAyB,CAAC,CAAC;CAC7G;AAoBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,MAAM,CAU/F;AAkED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,CAAC,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,CA4BR;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAIxE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMvD;AAmBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI,CAAC,MAAM,CA8f3E"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export { type AutonomyRouteHandlers, createAutonomyRouteHandlers, handleAutonomy
|
|
|
12
12
|
export { bootConfig, patchConfig } from './boot.js';
|
|
13
13
|
export type { BrainRouteHandlers } from './brain-routes.js';
|
|
14
14
|
export { handleBrainRoute } from './brain-routes.js';
|
|
15
|
-
export { type ChronicleRouteContext,
|
|
15
|
+
export { type ChronicleRouteContext, handleChronicleRoute, } from './chronicle-routes.js';
|
|
16
16
|
export { type ClientTransportRouteHandlers, handleClientTransportRoute, } from './client-transport-routes.js';
|
|
17
17
|
export { setupWebUICodebaseIndexing } from './codebase-indexing.js';
|
|
18
18
|
export { type CodeMapFileTarget, type CodeMapOperation, extractCodeMapFileTargets, normalizeCodeMapFileTarget, } from './codemap-telemetry.js';
|
|
@@ -22,7 +22,9 @@ export { type CompletionRouteHandlers, handleCompletionRoute } from './completio
|
|
|
22
22
|
export { type ContentRouteContext, handleContentRoute } from './content-routes.js';
|
|
23
23
|
export { type ConversationRouteHandlers, handleConversationRoute, } from './conversation-routes.js';
|
|
24
24
|
export { createConversationOperations, type ConversationOperationsContext, type ConversationRunControl, } from './conversation-operations.js';
|
|
25
|
+
export { applyContextEditorProposal, buildContextEditorSnapshot, contextEditorRevision, validateContextEditorMessages, validateContextEditorProposal, type ContextEditorAppliedResult, type ContextEditorBlock, type ContextEditorConflict, type ContextEditorDiagnostics, type ContextEditorMessage, type ContextEditorMetrics, type ContextEditorRepairPreview, type ContextEditorSnapshot, type ContextEditorValidationError, type ContextEditorValidationResult, type ContextEditorWarning, } from './context-editor.js';
|
|
25
26
|
export { createConnectionLifecycle, type ConnectionLifecycleOptions, } from './connection-lifecycle.js';
|
|
27
|
+
export { collectConnectionsHealth, type ConnectionHealthService, type ConnectionsHealthContext, type ConnectionsHealthReport, handleConnectionsHealthRoute, } from './connections-health-route.js';
|
|
26
28
|
export { type CustomContextMode, type CustomModeStore, createCustomModeStore, } from './custom-context-modes.js';
|
|
27
29
|
export { type DesignContext, handleDesignList, handleDesignMaterialize, handleDesignSet, handleDesignState, handleDesignSwap, handleDesignTune, handleDesignUse, handleDesignVerify, } from './design-handlers.js';
|
|
28
30
|
export { createEternalSubscription, type EternalBroadcast, type EternalSubscribe, type EternalSubscription, } from './eternal-iteration-broadcast.js';
|
|
@@ -45,7 +47,8 @@ export { handleIntrospectionRoute, type IntrospectionRouteContext, } from './int
|
|
|
45
47
|
export { handleKanbanTaskDispatch, type KanbanDispatchContext, type KanbanDispatchResult, type KanbanTaskDispatcher, parseResolvedDispatchRoute, type ResolvedDispatchRoute, } from './kanban-dispatch.js';
|
|
46
48
|
export { handleKanbanHostRoute, type KanbanHostRouteHandlers } from './kanban-host-routes.js';
|
|
47
49
|
export type { KanbanBoardPage, KanbanRouteContext } from './kanban-routes.js';
|
|
48
|
-
export { handleKanbanRoute, paginateKanbanBoards } from './kanban-routes.js';
|
|
50
|
+
export { handleKanbanRoute, KANBAN_CLIENT_MESSAGE_TYPES, paginateKanbanBoards, } from './kanban-routes.js';
|
|
51
|
+
export { watchKanbanBoards } from './kanban-board-watcher.js';
|
|
49
52
|
export { createShutdown, registerShutdownHandlers } from './lifecycle.js';
|
|
50
53
|
export { handleConfigDoctor, type ConfigDoctorDeps, } from './config-doctor.js';
|
|
51
54
|
export { getMailboxForDeps, handleMailboxAgents, handleMailboxClear, handleMailboxCompact, handleMailboxMessages, handleMailboxPurge, type MailboxHandlerDeps, } from './mailbox-handlers.js';
|
|
@@ -121,5 +124,6 @@ export { WorktreeWebSocketHandler } from './worktree-ws-handler.js';
|
|
|
121
124
|
export { extractToken, extractTokenFromCookie, hostHeaderOk, isLoopbackBind, isLoopbackHostname, isWildcardBind, tokenMatches, type VerifyClientInput, verifyClient, } from './ws-auth.js';
|
|
122
125
|
export { validateAutonomySwitchPayload, validateBrainAskPayload, validateBrainRiskPayload, validateContextModeCreatePayload, validateContextModeDeletePayload, validateContextModeSwitchPayload, validateContextModeUpdatePayload, validateGitDiffPayload, validateMailboxAgentsPayload, validateMailboxMessagesPayload, validateMailboxPurgePayload, validateModelSwitchPayload, validateModeSwitchPayload, validatePlanTemplateUsePayload, validatePrefsUpdatePayload, validateProcessKillPayload, validateProjectsAddPayload, validateProjectsSelectPayload, validateShellOpenPayload, validateSkillsCreatePayload, validateSkillsEditPayload, validateWorkingDirSetPayload, } from './ws-payload-validation.js';
|
|
123
126
|
export { broadcast, buildWebUIAccessUrl, envFlag, errMessage, generateAuthToken, hostForBrowserUrl, resolveAuthToken, send, sendResult, } from './ws-utils.js';
|
|
127
|
+
export { formatExternalAccessUrls, getExternalAddresses, type NetworkAddress } from './network-info.js';
|
|
124
128
|
export { createZipBuffer, readZipEntries, type ZipEntryInput } from './zip.js';
|
|
125
129
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,KAAK,qBAAqB,EAC1B,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACL,KAAK,qBAAqB,EAC1B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility alias for the old file-watcher entry point.
|
|
3
|
+
*
|
|
4
|
+
* Kanban is now server-owned SQLite, so liveness comes from daemon events and
|
|
5
|
+
* board reloads travel through IPC. Keep this export for downstream callers
|
|
6
|
+
* without allowing a filesystem watcher to reintroduce a second data path.
|
|
7
|
+
*/
|
|
8
|
+
import type { WSServerMessage } from './types.js';
|
|
9
|
+
export declare function watchKanbanBoards(projectRoot: string, broadcastMessage: (message: WSServerMessage) => void): () => void;
|
|
10
|
+
//# sourceMappingURL=kanban-board-watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kanban-board-watcher.d.ts","sourceRoot":"","sources":["../../src/server/kanban-board-watcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GACnD,MAAM,IAAI,CAEZ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kanban-daemon-subscriber.d.ts","sourceRoot":"","sources":["../../src/server/kanban-daemon-subscriber.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GACnD,MAAM,IAAI,CAuEZ"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Context } from '@wrongstack/core/agent';
|
|
2
|
+
import type { WebSocket } from 'ws';
|
|
3
|
+
import type { WSServerMessage } from './types.js';
|
|
4
|
+
export interface KanbanDecompositionRouteContext {
|
|
5
|
+
projectRoot: string;
|
|
6
|
+
context?: Context | undefined;
|
|
7
|
+
broadcast?: ((msg: WSServerMessage) => void) | undefined;
|
|
8
|
+
}
|
|
9
|
+
export declare function handleKanbanDecompositionRoute(ws: WebSocket, type: string, payload: Record<string, unknown> | undefined, ctx: KanbanDecompositionRouteContext): Promise<boolean>;
|
|
10
|
+
//# sourceMappingURL=kanban-decomposition-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kanban-decomposition-routes.d.ts","sourceRoot":"","sources":["../../src/server/kanban-decomposition-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAStD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,WAAW,+BAA+B;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC1D;AAED,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC5C,GAAG,EAAE,+BAA+B,GACnC,OAAO,CAAC,OAAO,CAAC,CAYlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kanban-dispatch.d.ts","sourceRoot":"","sources":["../../src/server/kanban-dispatch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"kanban-dispatch.d.ts","sourceRoot":"","sources":["../../src/server/kanban-dispatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAStD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,MAAM,oBAAoB,GAAG,CACjC,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE;IACL,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACpD,OAAO,CAAC,EACJ;QACE,MAAM,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KACxF,GACD,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAC/E,KACE,OAAO,CAAC,MAAM,CAAC,CAAC;AAErB,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC7D,YAAY,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACjD;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAajF;AAsBD,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,SAAS,EACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC5C,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,IAAI,CAAC,CAmRf"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Context } from '@wrongstack/core/agent';
|
|
2
|
+
import type { KanbanBoard, KanbanEventContext, KanbanTask } from '@wrongstack/kanban';
|
|
3
|
+
import type { WebSocket } from 'ws';
|
|
4
|
+
import type { WSServerMessage } from './types.js';
|
|
5
|
+
export interface KanbanRouteHelperContext {
|
|
6
|
+
projectRoot: string;
|
|
7
|
+
context?: Context | undefined;
|
|
8
|
+
broadcast?: ((msg: WSServerMessage) => void) | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare function syncSessionSource(ctx: KanbanRouteHelperContext, task: KanbanTask, remove?: boolean): Promise<void>;
|
|
11
|
+
export declare function ok(ws: WebSocket, type: string, data?: unknown): void;
|
|
12
|
+
export declare function fail(ws: WebSocket, type: string, message: string): void;
|
|
13
|
+
export declare function has(payload: Record<string, unknown> | undefined, key: string): boolean;
|
|
14
|
+
export declare function activityContext(ctx: KanbanRouteHelperContext, actor?: string, note?: string): KanbanEventContext;
|
|
15
|
+
export declare function touchTaskPresence(ctx: KanbanRouteHelperContext, boardId: string, taskId: string): Promise<KanbanBoard | null>;
|
|
16
|
+
export declare function findTask(tasks: KanbanTask[], taskId: string): KanbanTask | undefined;
|
|
17
|
+
//# sourceMappingURL=kanban-route-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kanban-route-helpers.d.ts","sourceRoot":"","sources":["../../src/server/kanban-route-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC1D;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,UAAU,EAChB,MAAM,UAAQ,GACb,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAgB,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEpE;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEvE;AAED,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAEtF;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,wBAAwB,EAC7B,KAAK,CAAC,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACZ,kBAAkB,CAOpB;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,wBAAwB,EAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAc7B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAEpF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { KanbanBoardSummary } from '@wrongstack/kanban';
|
|
2
|
+
export interface KanbanBoardPage {
|
|
3
|
+
items: KanbanBoardSummary[];
|
|
4
|
+
total: number;
|
|
5
|
+
page: number;
|
|
6
|
+
pageSize: number;
|
|
7
|
+
totalPages: number;
|
|
8
|
+
activeTotal: number;
|
|
9
|
+
orphanedTotal: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function paginateKanbanBoards(boards: KanbanBoardSummary[], input: {
|
|
12
|
+
page: number;
|
|
13
|
+
pageSize: number;
|
|
14
|
+
activeSessionIds?: readonly string[] | undefined;
|
|
15
|
+
}): KanbanBoardPage;
|
|
16
|
+
//# sourceMappingURL=kanban-route-pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kanban-route-pagination.d.ts","sourceRoot":"","sources":["../../src/server/kanban-route-pagination.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,kBAAkB,EAAE,EAC5B,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CAAE,GAC1F,eAAe,CA0BjB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const KANBAN_CLIENT_MESSAGE_TYPES: readonly ['kanban.capabilities', 'kanban.column.add', 'kanban.column.remove', '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'];
|
|
2
|
+
//# sourceMappingURL=kanban-route-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kanban-route-protocol.d.ts","sourceRoot":"","sources":["../../src/server/kanban-route-protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,YACtC,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,8BAA8B,EAC9B,6BAA6B,EAC7B,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,EACtB,0BAA0B,EAC1B,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,EACxB,2BAA2B,EAC3B,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,EACvB,eAAe,CACP,CAAC"}
|
|
@@ -1,27 +1,14 @@
|
|
|
1
1
|
import type { Context } from '@wrongstack/core/agent';
|
|
2
|
-
import { type KanbanBoardSummary } from '@wrongstack/kanban';
|
|
3
2
|
import type { WebSocket } from 'ws';
|
|
4
3
|
import type { WSClientMessage, WSServerMessage } from './types.js';
|
|
5
4
|
import { type KanbanTaskDispatcher } from './kanban-dispatch.js';
|
|
5
|
+
export { KANBAN_CLIENT_MESSAGE_TYPES } from './kanban-route-protocol.js';
|
|
6
|
+
export { paginateKanbanBoards, type KanbanBoardPage } from './kanban-route-pagination.js';
|
|
6
7
|
export interface KanbanRouteContext {
|
|
7
8
|
projectRoot: string;
|
|
8
9
|
context?: Context | undefined;
|
|
9
10
|
broadcast?: ((msg: WSServerMessage) => void) | undefined;
|
|
10
11
|
dispatchTask?: KanbanTaskDispatcher | undefined;
|
|
11
12
|
}
|
|
12
|
-
export interface KanbanBoardPage {
|
|
13
|
-
items: KanbanBoardSummary[];
|
|
14
|
-
total: number;
|
|
15
|
-
page: number;
|
|
16
|
-
pageSize: number;
|
|
17
|
-
totalPages: number;
|
|
18
|
-
activeTotal: number;
|
|
19
|
-
orphanedTotal: number;
|
|
20
|
-
}
|
|
21
|
-
export declare function paginateKanbanBoards(boards: KanbanBoardSummary[], input: {
|
|
22
|
-
page: number;
|
|
23
|
-
pageSize: number;
|
|
24
|
-
activeSessionIds?: readonly string[] | undefined;
|
|
25
|
-
}): KanbanBoardPage;
|
|
26
13
|
export declare function handleKanbanRoute(ws: WebSocket, msg: WSClientMessage, ctx: KanbanRouteContext): Promise<boolean>;
|
|
27
14
|
//# sourceMappingURL=kanban-routes.d.ts.map
|