feat: component wiring integration — orphan cleanup, Memory page, WS handlers
Memory page: Added REST endpoints (routes/memory.ts, 3 GETs: list/daily/dreams), React route in App.tsx, nav link in ProjectSidebar (Brain icon). Orphan components wired: KeyboardShortcutsDialog (? key in AppShell), McpResponseDisplay (MCP tool results in ToolCallLine), CacheShapeBadge (StatsLine in MessageBubble). MessageBoundary + MessageListErrorBoundary confirmed already wired in MarkdownRenderer/MessageList. Dead code cleanup: useDraftPersistence integrated into ChatInput (localStorage draft save/restore/clear on send). message-parts barrel made canonical — MessageBubble imports from it; StatsLine updated with CacheShapeBadge parity. api.settings.inference typed wrapper added; InferenceSettings raw fetch replaced. WS frame handlers: reasoning_delta (accumulates like delta), tool_trace_start, tool_trace_finish, collision_warning, agent_message acknowledged in useSessionStream. CollisionWarningEvent + AgentMessageEvent added to sessionEvents union. Forwarding in useCoderUserEvents. reasoning_delta + collision_warning added to web WsFrame type. useSidebar default case fixes pre-existing fallthrough error. Workflow engine: services/workflow/index.ts documented as experimental; coder flow-runner (apps/coder/src/services/flow-runner.ts) is canonical. Verification: web type-check clean, server build clean, 627 tests pass.
This commit is contained in:
@@ -21,6 +21,7 @@ import { registerSkillsRoutes } from './routes/skills.js';
|
||||
import { registerTraceRoutes } from './routes/traces.js';
|
||||
import { registerToolsRoutes } from './routes/tools.js';
|
||||
import { registerAnalyticsRoutes } from './routes/analytics.js';
|
||||
import { registerMemoryRoutes } from './routes/memory.js';
|
||||
|
||||
import { registerInferenceSettingsRoutes } from './routes/inference-settings.js';
|
||||
import { createInferenceRunner, runInferenceWithModel } from './services/inference/index.js';
|
||||
@@ -155,6 +156,7 @@ async function main() {
|
||||
hasActiveInference: (chatId) => inference.hasActive(chatId),
|
||||
});
|
||||
registerTraceRoutes(app, sql);
|
||||
registerMemoryRoutes(app, sql);
|
||||
registerToolsRoutes(app, sql);
|
||||
registerAnalyticsRoutes(app, sql);
|
||||
registerInferenceSettingsRoutes(app);
|
||||
|
||||
91
apps/server/src/routes/memory.ts
Normal file
91
apps/server/src/routes/memory.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
import type { Sql } from '../db.js';
|
||||
|
||||
// ── Row types matching memory_entries table columns ───────────────────────
|
||||
// These mirror the frontend types in apps/web/src/api/types.ts.
|
||||
|
||||
interface MemoryEntryRow {
|
||||
id: string;
|
||||
topic: string;
|
||||
title: string;
|
||||
content: string;
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
interface DailyMemoryEntryRow extends MemoryEntryRow {
|
||||
date: string;
|
||||
}
|
||||
|
||||
interface DreamEntryRow {
|
||||
date: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export function registerMemoryRoutes(app: FastifyInstance, sql: Sql): void {
|
||||
// GET /api/memory?project_id=<id> — topic-based memory entries
|
||||
app.get<{ Querystring: { project_id?: string } }>(
|
||||
'/api/memory',
|
||||
async (req) => {
|
||||
const projectId = req.query.project_id
|
||||
if (!projectId) {
|
||||
return { entries: [] }
|
||||
}
|
||||
|
||||
const rows = await sql<MemoryEntryRow[]>`
|
||||
SELECT id, topic, title, content, COALESCE(tags, ARRAY[]::text[]) AS tags
|
||||
FROM memory_entries
|
||||
WHERE project_id = ${projectId}
|
||||
AND date IS NULL
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
return { entries: rows }
|
||||
},
|
||||
)
|
||||
|
||||
// GET /api/memory/daily?project_id=<id> — daily log entries
|
||||
app.get<{ Querystring: { project_id?: string } }>(
|
||||
'/api/memory/daily',
|
||||
async (req) => {
|
||||
const projectId = req.query.project_id
|
||||
if (!projectId) {
|
||||
return { entries: [] }
|
||||
}
|
||||
|
||||
const rows = await sql<DailyMemoryEntryRow[]>`
|
||||
SELECT
|
||||
id, topic, title, content,
|
||||
COALESCE(tags, ARRAY[]::text[]) AS tags,
|
||||
date::text AS date
|
||||
FROM memory_entries
|
||||
WHERE project_id = ${projectId}
|
||||
AND date IS NOT NULL
|
||||
AND mood IS NULL
|
||||
ORDER BY date DESC, created_at DESC
|
||||
`
|
||||
|
||||
return { entries: rows }
|
||||
},
|
||||
)
|
||||
|
||||
// GET /api/memory/dreams?project_id=<id> — dream consolidation diaries
|
||||
app.get<{ Querystring: { project_id?: string } }>(
|
||||
'/api/memory/dreams',
|
||||
async (req) => {
|
||||
const projectId = req.query.project_id
|
||||
if (!projectId) {
|
||||
return { entries: [] }
|
||||
}
|
||||
|
||||
const rows = await sql<DreamEntryRow[]>`
|
||||
SELECT date::text AS date, content
|
||||
FROM memory_entries
|
||||
WHERE project_id = ${projectId}
|
||||
AND mood IS NOT NULL
|
||||
ORDER BY date DESC, created_at DESC
|
||||
`
|
||||
|
||||
return { entries: rows }
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,35 @@
|
||||
// v2.8.0: Dynamic Workflow Engine — public surface.
|
||||
//
|
||||
// ## Status: experimental / intentionally decoupled from the coder flow-runner
|
||||
//
|
||||
// This module is an in-process multi-agent orchestrator that creates BooChat
|
||||
// sessions+chats and dispatches inference via the native `runInference`
|
||||
// pipeline. It is NOT currently wired into the server (`apps/server/src/index.ts`)
|
||||
// — no routes import it, no service initialises it, and the server has no
|
||||
// `projectRoot`/`projectId` concept at startup. All code is preserved for future
|
||||
// evaluation but is not in use.
|
||||
//
|
||||
// ## Relationship to the coder flow-runner
|
||||
//
|
||||
// The canonical orchestrator implementation lives at:
|
||||
// `apps/coder/src/services/flow-runner.ts` (1102 lines, actively wired)
|
||||
//
|
||||
// The two modules serve different dispatch strategies:
|
||||
//
|
||||
// | Dimension | Server WorkflowManager (this) | Coder flow-runner |
|
||||
// |-------------------|-----------------------------------|------------------------------------|
|
||||
// | Dispatch | In-process via `runInference` | Task rows → external agent binary |
|
||||
// | Agent target | BooChat native inference | qwen via PTY (--approval-mode plan)|
|
||||
// | Session model | Per-agent BooChat sessions+chats | Per-step synthetic sessions |
|
||||
// | Persistence | In-memory (Map<runId, state>) | DB-backed (flow_runs/flow_steps) |
|
||||
// | Lifecycle | Polling loop + AbortController | Dispatcher hook (onTaskTerminal) |
|
||||
// | Status | Experimental, not wired | Active, production |
|
||||
//
|
||||
// These two engines are NOT competitors — they are alternative approaches for
|
||||
// different dispatch surfaces. Use the coder flow-runner for the current
|
||||
// orchestrator; revisit this module if in-process BooChat-native multi-agent
|
||||
// orchestration becomes a requirement.
|
||||
//
|
||||
// Re-exports all types and classes from the workflow sub-modules so consumers
|
||||
// import from a single entry point:
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user