diff --git a/docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md b/docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md index 522992f3..b4705fe0 100644 --- a/docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md +++ b/docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md @@ -897,6 +897,286 @@ export function consumeNdjsonStream( --- +## Agent Delegation — Parallel Execution + +> **5 tracks can run in parallel.** Tracks A–D start immediately. Track E waits for A+B+C. +> Phase 3 is deferred until Phase 1+2 are done and you've evaluated what's missed. + +### Dependency Diagram + +``` + ┌─────────────────────────────────────────┐ + START ────────►│ Track A: Phase 1 + 2.1 (LLM Lab) │──┐ + │ └─────────────────────────────────────────┘ │ + │ ┌─────────────────────────────────────────┐ │ + ├───────────►│ Track B: 4.1 create ollama-client pkg │──┤ + │ └─────────────────────────────────────────┘ │ + │ ┌─────────────────────────────────────────┐ │ ┌──────────────────────────────────┐ + ├───────────►│ Track C: 4.2 extend fastify-sse │──┼──►│ Track E: Migrate LocalMemGPT │ + │ └─────────────────────────────────────────┘ │ │ (2.2 + 4.1a + 4.2a) │ + │ ┌─────────────────────────────────────────┐ │ └──────────────────────────────────┘ + └───────────►│ Track D: 4.3 + 4.4 React hooks │──┘ + └─────────────────────────────────────────┘ + After Track E → Phase 3 (optional) +``` + +### Track A — Agent 1: LLM Lab Workspace Removal + +**Repo:** `learning_ai_local_llms` +**Can start:** Immediately +**Estimated time:** ~2.5 hours + +
+Copy-pastable prompt for Agent 1 + +``` +Read the consolidation roadmap at ../learning_ai_common_plat/docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md — specifically the Execution Checklist and Safety Matrix sections. + +Execute Phase 1 + Phase 2.1 in the learning_ai_local_llms repo. This removes the chat workspace from Local LLM Lab, making Local Memory GPT the single chat surface. + +Steps (3 commits): + +COMMIT 1 — refactor(dashboard): remove chat workspace +1. Run `cd dashboard && pnpm test && pnpm run build` to establish green baseline +2. Delete the entire `dashboard/src/app/(workspace)/` directory (22 files) +3. Delete `dashboard/src/app/api/ollama/title/` directory (1 workspace-only route) +4. Delete workspace lib files: db.ts, agents.ts, quick-actions.ts, scheduled-tasks.ts, cron.ts, migrate.ts +5. Trim types.ts: move Attachment (lines 119-126) and ModelDefaults (lines 163-169) into the shared section (after line 77), then delete everything from line 78 onward (the "// --- v4 Workspace Types ---" comment and below) +6. Delete workspace tests: __tests__/agents.test.ts, __tests__/cron.test.ts +7. Create dashboard/src/app/page.tsx that redirects to /mission-control: + import { redirect } from 'next/navigation'; + export default function Home() { redirect('/mission-control'); } +8. Remove npm deps from dashboard/package.json: idb, cron-parser, fuse.js +9. Run pnpm install to update lockfile +10. Verify: pnpm run typecheck && pnpm test && pnpm run build + +CRITICAL SAFETY RULES: +- DO NOT delete api/ollama/chat/, api/ollama/stream/, api/ollama/logs/, api/tts/, api/whisper/, api/whisper/transcribe/ — Mission Control uses all of these +- DO NOT delete lib/router.ts, lib/format.ts, lib/ollama-config.ts, lib/llm-router.ts, lib/product-config.ts, lib/use-theme.ts, lib/use-keyboard-shortcuts.ts — all shared +- DO NOT delete src/components/ — shared by Mission Control +- Verify: grep for any remaining imports of deleted files after cleanup + +COMMIT 2 — test(e2e): update specs after workspace removal +1. Delete e2e/chat.spec.ts +2. Update e2e/health.spec.ts — remove /c/test-id test +3. Update e2e/accessibility.spec.ts — remove /compare, /tts, /whisper from routes array +4. Update e2e/visual-regression.spec.ts — remove workspace and compare from ROUTES +5. Update e2e/navigation.spec.ts — / now redirects to /mission-control +6. Update e2e/models.spec.ts — / now redirects + +COMMIT 3 — docs: update agent docs after workspace removal +1. Update AGENTS.md — remove workspace references, update repo layout, adjust test count +2. Update README.md — remove workspace description, add note pointing to Local Memory GPT +3. Update CLAUDE.md, .windsurfrules, .cursorrules — align with new scope + +PHASE 2.1 — feat(dashboard): add LocalMemGPT cross-link in Mission Control +1. Add a "Chat with your models →" card/banner in Mission Control linking to http://localhost:3070 +2. Make URL configurable via LOCALMEMGPT_URL env var (default: http://localhost:3070) +3. Add LOCALMEMGPT_URL to .env.example +``` + +
+ +### Track B — Agent 2: Create `@bytelyst/ollama-client` Package + +**Repo:** `learning_ai_common_plat` +**Can start:** Immediately +**Estimated time:** ~1 day + +
+Copy-pastable prompt for Agent 2 + +``` +Read the consolidation roadmap at docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md — specifically sections 4.1, 4.5, 4.6, and 4.7. + +Create a new @bytelyst/ollama-client package in packages/ollama-client/ in the learning_ai_common_plat repo. This is a shared Ollama API client that eliminates ~350 lines of duplicated code across learning_ai_local_llms and learning_ai_local_memory_gpt. + +Package structure: + packages/ollama-client/ + ├── src/ + │ ├── index.ts # Public exports + │ ├── config.ts # resolveOllamaUrl(env) — OLLAMA_URL/OLLAMA_HOST + WSL2 gateway detection + │ ├── client.ts # OllamaClient class: tags, ps, show, pull, load, unload, delete, version + │ ├── stream.ts # streamChat(), streamGenerate() — AsyncGenerator + │ ├── embed.ts # getEmbedding() + │ ├── health.ts # checkHealth() with timeout + │ ├── ndjson.ts # parseNdjsonStream() — reusable NDJSON async generator (server + client) + │ ├── types.ts # OllamaModel, OllamaChatMessage, OllamaStreamChunk, OllamaEmbedding + │ └── client-parsers.ts # consumeSSEStream(), consumeNdjsonStream() — browser-side stream consumers + ├── package.json + └── tsconfig.json + +Reference implementations to consolidate: +- learning_ai_local_memory_gpt/backend/src/lib/ollama.ts (117 lines) — listOllamaModels, checkOllamaHealth, streamChat, getEmbedding +- learning_ai_local_llms/dashboard/src/app/lib/ollama-config.ts (40 lines) — OLLAMA_URL config + WSL2 detection +- learning_ai_local_llms/dashboard/src/app/api/ollama/route.ts (128 lines) — fetchOllama wrapper +- NDJSON stream parsing pattern copy-pasted 5+ times across both repos + +Also extract reusable utilities (section 4.6): +- formatBytes() — general purpose byte formatting +- estimateTokens() — LLM token estimation +- getModelContextWindow() — model context window lookup +- formatUptime() — uptime formatting + +Canonical OllamaModel type (section 4.5) — match Ollama's actual API response, superset of both repos' definitions. + +Follow existing @bytelyst/* package conventions: +- ESM ("type": "module"), TypeScript, exports field in package.json +- Extend ../../tsconfig.base.json +- Vitest for tests +- peerDependencies for heavy deps if any + +DO NOT migrate consumer repos — that happens in Track E. Only create the package + tests + publish to Gitea registry. + +COMMIT: feat(ollama-client): shared Ollama API client package +``` + +
+ +### Track C — Agent 3: Extend `@bytelyst/fastify-sse` + +**Repo:** `learning_ai_common_plat` +**Can start:** Immediately +**Estimated time:** ~2 hours + +
+Copy-pastable prompt for Agent 3 + +``` +Read the consolidation roadmap at docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md — specifically section 4.2. + +Extend the existing @bytelyst/fastify-sse package (packages/fastify-sse/) with per-request SSE helpers. The package currently only has SSEHub (multi-client broadcast). We need single-request streaming helpers too. + +Reference implementation to absorb: +- learning_ai_local_memory_gpt/backend/src/lib/sse-helpers.ts (26 lines): + - startSSE(reply) — sets headers, calls reply.hijack() + - sendSSEData(reply, data) — writes "data: JSON\n\n" + - sendSSEEvent(reply, event, data) — writes "event: name\ndata: JSON\n\n" + - endSSE(reply) — writes "[DONE]" and ends stream + +Add a new file: packages/fastify-sse/src/per-request.ts +Export from index.ts alongside existing SSEHub + ssePlugin exports. +Add tests in packages/fastify-sse/src/per-request.test.ts. +Publish updated package to Gitea registry. + +DO NOT migrate consumer repos — that happens in Track E. + +COMMIT: feat(fastify-sse): add per-request SSE helpers +``` + +
+ +### Track D — Agent 4: Create React Hook Packages + +**Repo:** `learning_ai_common_plat` +**Can start:** Immediately +**Estimated time:** ~5 hours + +
+Copy-pastable prompt for Agent 4 + +``` +Read the consolidation roadmap at docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md — specifically sections 4.3 and 4.4. + +Create TWO new @bytelyst/* packages: + +PACKAGE 1: packages/use-theme/ +A configurable React useTheme() hook. Currently duplicated across 6 web apps with only the storage key differing. + +Reference implementations: +- learning_ai_local_memory_gpt/web/src/lib/use-theme.ts (49 lines, key: "lmg-theme") +- learning_ai_local_llms/dashboard/src/app/lib/use-theme.ts (48 lines, key: "llm-theme") +- Also in: ChronoMind, FlowMonk, NomGap, ActionTrail (all ~50 lines each) + +API: + export function useTheme(options?: { + storageKey?: string; // default: 'theme' + attribute?: 'class' | 'data-theme'; // default: 'class' + }): { theme: 'light' | 'dark'; setTheme: (t: 'light' | 'dark') => void; toggleTheme: () => void } + +COMMIT: feat(use-theme): shared React theme toggle hook + +PACKAGE 2: packages/use-keyboard-shortcuts/ +A data-driven React useKeyboardShortcuts() hook. Currently duplicated across 5+ web apps with hardcoded if/else chains. + +Reference implementations: +- learning_ai_local_memory_gpt/web/src/lib/use-keyboard-shortcuts.ts (53 lines) +- learning_ai_local_llms/dashboard/src/app/lib/use-keyboard-shortcuts.ts (57 lines) +- Also in: ChronoMind, ActionTrail, NoteLett + +API: + interface ShortcutDef { + key: string; + meta?: boolean; + shift?: boolean; + alt?: boolean; + handler: () => void; + allowInInput?: boolean; + description?: string; + } + export function useKeyboardShortcuts(shortcuts: ShortcutDef[]): void + +COMMIT: feat(use-keyboard-shortcuts): shared React keyboard shortcuts hook + +For both packages: +- ESM ("type": "module"), TypeScript, React as peerDependency +- Vitest + @testing-library/react for tests +- Extend ../../tsconfig.base.json +- Publish to Gitea registry + +DO NOT migrate consumer repos yet — migrations can happen as a follow-up sweep. +``` + +
+ +### Track E — Agent 5: Migrate LocalMemGPT (after A+B+C complete) + +**Repo:** `learning_ai_local_memory_gpt` +**Can start:** After Tracks A, B, and C are complete +**Estimated time:** ~3 hours + +
+Copy-pastable prompt for Agent 5 + +``` +Read the consolidation roadmap at ../learning_ai_common_plat/docs/roadmaps/not-started/LOCAL_AI_CONSOLIDATION_ROADMAP.md. + +Execute 3 migrations in the learning_ai_local_memory_gpt repo: + +TASK 1 — Phase 2.2: Add LLM Lab cross-link +1. Add a "Model Management →" link in the Settings panel (web/src/components/SettingsPanel.tsx) +2. Link to http://localhost:3000 (LLM Lab dashboard) +3. Make URL configurable via LOCALLLMLAB_URL env var (default: http://localhost:3000) +4. Add LOCALLLMLAB_URL to .env.example +COMMIT: feat(web): add LLM Lab cross-link in settings + +TASK 2 — Migrate to @bytelyst/ollama-client +1. Add @bytelyst/ollama-client dependency (from Gitea registry) +2. Replace backend/src/lib/ollama.ts (117 lines) with imports from @bytelyst/ollama-client: + - listOllamaModels → import { listModels } from '@bytelyst/ollama-client' + - checkOllamaHealth → import { checkHealth } from '@bytelyst/ollama-client' + - streamChat → import { streamChat } from '@bytelyst/ollama-client' + - getEmbedding → import { getEmbedding } from '@bytelyst/ollama-client' + - OllamaModel type → import { OllamaModel } from '@bytelyst/ollama-client' +3. Update all consumers of lib/ollama.ts to use new imports +4. Run: cd backend && npm test && npm run typecheck && npm run build +COMMIT: refactor(backend): migrate to @bytelyst/ollama-client + +TASK 3 — Migrate to @bytelyst/fastify-sse per-request helpers +1. Replace backend/src/lib/sse-helpers.ts (26 lines) with imports from @bytelyst/fastify-sse: + - import { startSSE, sendSSEData, sendSSEEvent, endSSE } from '@bytelyst/fastify-sse' +2. Update chat/routes.ts and compare/routes.ts to use new imports +3. Delete lib/sse-helpers.ts +4. Run: cd backend && npm test && npm run typecheck && npm run build +COMMIT: refactor(backend): migrate to @bytelyst/fastify-sse per-request helpers + +Verify all ~104 tests still pass after each migration. +``` + +
+ +--- + ## Open Questions 1. ~~**TTS/Whisper in Mission Control:**~~ **[F13] RESOLVED.** Mission Control uses `api/whisper` (status), `api/whisper/transcribe` (test), `api/tts` (engine status), `api/ollama/chat` (model testing), `api/ollama/stream` (benchmarks/compare), `api/ollama/logs` (log viewer). All 6 routes are kept.