Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
433 changes: 340 additions & 93 deletions dashboard/src/lib/components/views/ChatView.svelte

Large diffs are not rendered by default.

28 changes: 26 additions & 2 deletions dashboard/src/lib/sse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
*
* Issue #37
* Issue #85: Added tool_call event handling
* Issue #106 Phase B: Added planner_message event handling
*/

import { connection } from '$lib/stores/connection.svelte.js';
import { agentsStore } from '$lib/stores/agents.svelte.js';
import { tasksStore } from '$lib/stores/tasks.svelte.js';
import { memoryStore } from '$lib/stores/memory.svelte.js';
import type { SSEEventType, ToolCallEvent } from '$lib/types/api.js';
import { plannerStore } from '$lib/stores/planner.svelte.js';
import type { SSEEventType, ToolCallEvent, PlannerMessageEvent } from '$lib/types/api.js';

/** Backoff config */
const INITIAL_DELAY_MS = 1000;
Expand Down Expand Up @@ -54,6 +56,21 @@ function isToolCallEvent(payload: Record<string, unknown>): payload is ToolCallE
);
}

/**
* Type guard for PlannerMessageEvent payloads.
* Issue #106 Phase B. Validates all required fields including
* the warnings array (CodeRabbit fix #2).
*/
function isPlannerMessageEvent(payload: Record<string, unknown>): payload is PlannerMessageEvent {
return (
typeof payload.session_id === 'string' &&
typeof payload.message === 'string' &&
typeof payload.ready === 'boolean' &&
Array.isArray(payload.warnings) &&
(payload.warnings as unknown[]).every((w) => typeof w === 'string')
);
}

/**
* Route an SSE event to the appropriate store handler.
*/
Expand Down Expand Up @@ -89,6 +106,12 @@ function dispatch(eventType: SSEEventType, payload: Record<string, unknown>) {
}
break;

case 'planner_message':
if (isPlannerMessageEvent(payload)) {
plannerStore.handleSSE(payload);
}
break;

case 'log_line':
// Log lines are consumed by the BottomPanel directly.
// For now, dispatch a custom DOM event that components can listen to.
Expand Down Expand Up @@ -163,7 +186,8 @@ function connect() {
'task_complete',
'memory_added',
'log_line',
'tool_call'
'tool_call',
'planner_message'
];

for (const type of eventTypes) {
Expand Down
4 changes: 4 additions & 0 deletions dashboard/src/lib/stores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Issue #38: initAllStores() + destroyAllStores()
* Issue #51: Removed mock mode — always live
* Issue #106: Added workspacesStore
* Issue #106 Phase B: Added plannerStore
*/

export { agentsStore } from './agents.svelte.js';
Expand All @@ -13,12 +14,14 @@ export { memoryStore } from './memory.svelte.js';
export { prsStore } from './prs.svelte.js';
export { connection } from './connection.svelte.js';
export { workspacesStore } from './workspaces.svelte.js';
export { plannerStore } from './planner.svelte.js';

import { agentsStore } from './agents.svelte.js';
import { tasksStore } from './tasks.svelte.js';
import { memoryStore } from './memory.svelte.js';
import { prsStore } from './prs.svelte.js';
import { workspacesStore } from './workspaces.svelte.js';
import { plannerStore } from './planner.svelte.js';

/**
* Kick off initial data fetch for all stores.
Expand Down Expand Up @@ -48,4 +51,5 @@ export function destroyAllStores(): void {
memoryStore.reset();
prsStore.reset();
workspacesStore.reset();
plannerStore.reset();
}
Loading
Loading