docs(roadmap): split agent prompts into individual docs for one-liner delegation
New files in coding_agent_prompts/: - TRACK_A_llm_lab_workspace_removal.md (learning_ai_local_llms) - TRACK_B_ollama_client_package.md (learning_ai_common_plat) - TRACK_C_fastify_sse_extend.md (learning_ai_common_plat) - TRACK_D_react_hook_packages.md (learning_ai_common_plat) - TRACK_E_localmemgpt_migrations.md (learning_ai_local_memory_gpt) - README.md with dependency diagram + one-liner table Roadmap delegation section now links to individual docs instead of inline prompts. Point an agent at one file: Read and execute coding_agent_prompts/TRACK_A_*.md
This commit is contained in:
parent
73a70c2f00
commit
a8e0b7c3b0
@ -901,279 +901,35 @@ export function consumeNdjsonStream<T>(
|
|||||||
|
|
||||||
> **5 tracks can run in parallel.** Tracks A–D start immediately. Track E waits for A+B+C.
|
> **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.
|
> Phase 3 is deferred until Phase 1+2 are done and you've evaluated what's missed.
|
||||||
|
>
|
||||||
|
> **Individual prompt docs:** [`coding_agent_prompts/`](./coding_agent_prompts/) — point an agent at one file.
|
||||||
|
|
||||||
### Dependency Diagram
|
### Dependency Diagram
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────┐
|
┌──────────────────────────────────────┐
|
||||||
START ────────►│ Track A: Phase 1 + 2.1 (LLM Lab) │──┐
|
START ────────►│ Track A: LLM Lab cleanup (2.5h) │──┐
|
||||||
│ └─────────────────────────────────────────┘ │
|
│ └──────────────────────────────────────┘ │
|
||||||
│ ┌─────────────────────────────────────────┐ │
|
│ ┌──────────────────────────────────────┐ │
|
||||||
├───────────►│ Track B: 4.1 create ollama-client pkg │──┤
|
├───────────►│ Track B: ollama-client pkg (1 day) │──┤
|
||||||
│ └─────────────────────────────────────────┘ │
|
│ └──────────────────────────────────────┘ │
|
||||||
│ ┌─────────────────────────────────────────┐ │ ┌──────────────────────────────────┐
|
│ ┌──────────────────────────────────────┐ │ ┌─────────────────────────────┐
|
||||||
├───────────►│ Track C: 4.2 extend fastify-sse │──┼──►│ Track E: Migrate LocalMemGPT │
|
├───────────►│ Track C: fastify-sse extend (2h) │──┼──►│ Track E: LocalMemGPT (3h) │
|
||||||
│ └─────────────────────────────────────────┘ │ │ (2.2 + 4.1a + 4.2a) │
|
│ └──────────────────────────────────────┘ │ └─────────────────────────────┘
|
||||||
│ ┌─────────────────────────────────────────┐ │ └──────────────────────────────────┘
|
│ ┌──────────────────────────────────────┐ │
|
||||||
└───────────►│ Track D: 4.3 + 4.4 React hooks │──┘
|
└───────────►│ Track D: React hooks (5h) │──┘
|
||||||
└─────────────────────────────────────────┘
|
└──────────────────────────────────────┘
|
||||||
After Track E → Phase 3 (optional)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Track A — Agent 1: LLM Lab Workspace Removal
|
### Track Summary
|
||||||
|
|
||||||
**Repo:** `learning_ai_local_llms`
|
| Track | Prompt Doc | Repo | One-Liner |
|
||||||
**Can start:** Immediately
|
| ----- | ----------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------ |
|
||||||
**Estimated time:** ~2.5 hours
|
| **A** | [`TRACK_A_llm_lab_workspace_removal.md`](./coding_agent_prompts/TRACK_A_llm_lab_workspace_removal.md) | `learning_ai_local_llms` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_A_llm_lab_workspace_removal.md` |
|
||||||
|
| **B** | [`TRACK_B_ollama_client_package.md`](./coding_agent_prompts/TRACK_B_ollama_client_package.md) | `learning_ai_common_plat` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_B_ollama_client_package.md` |
|
||||||
<details>
|
| **C** | [`TRACK_C_fastify_sse_extend.md`](./coding_agent_prompts/TRACK_C_fastify_sse_extend.md) | `learning_ai_common_plat` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_C_fastify_sse_extend.md` |
|
||||||
<summary>Copy-pastable prompt for Agent 1</summary>
|
| **D** | [`TRACK_D_react_hook_packages.md`](./coding_agent_prompts/TRACK_D_react_hook_packages.md) | `learning_ai_common_plat` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_D_react_hook_packages.md` |
|
||||||
|
| **E** | [`TRACK_E_localmemgpt_migrations.md`](./coding_agent_prompts/TRACK_E_localmemgpt_migrations.md) | `learning_ai_local_memory_gpt` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_E_localmemgpt_migrations.md` |
|
||||||
```
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### Track B — Agent 2: Create `@bytelyst/ollama-client` Package
|
|
||||||
|
|
||||||
**Repo:** `learning_ai_common_plat`
|
|
||||||
**Can start:** Immediately
|
|
||||||
**Estimated time:** ~1 day
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Copy-pastable prompt for Agent 2</summary>
|
|
||||||
|
|
||||||
```
|
|
||||||
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<OllamaStreamChunk>
|
|
||||||
│ ├── 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
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### Track C — Agent 3: Extend `@bytelyst/fastify-sse`
|
|
||||||
|
|
||||||
**Repo:** `learning_ai_common_plat`
|
|
||||||
**Can start:** Immediately
|
|
||||||
**Estimated time:** ~2 hours
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Copy-pastable prompt for Agent 3</summary>
|
|
||||||
|
|
||||||
```
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### Track D — Agent 4: Create React Hook Packages
|
|
||||||
|
|
||||||
**Repo:** `learning_ai_common_plat`
|
|
||||||
**Can start:** Immediately
|
|
||||||
**Estimated time:** ~5 hours
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Copy-pastable prompt for Agent 4</summary>
|
|
||||||
|
|
||||||
```
|
|
||||||
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.
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Copy-pastable prompt for Agent 5</summary>
|
|
||||||
|
|
||||||
```
|
|
||||||
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.
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
34
docs/roadmaps/not-started/coding_agent_prompts/README.md
Normal file
34
docs/roadmaps/not-started/coding_agent_prompts/README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Local AI Consolidation — Agent Prompts
|
||||||
|
|
||||||
|
> Individual prompt docs for the [Local AI Consolidation Roadmap](../LOCAL_AI_CONSOLIDATION_ROADMAP.md).
|
||||||
|
> Point an agent at one file with a one-liner like: `Read and execute <path-to-file>`
|
||||||
|
|
||||||
|
## Parallel Execution
|
||||||
|
|
||||||
|
```
|
||||||
|
Tracks A–D start immediately (no dependencies).
|
||||||
|
Track E starts after A+B+C are done.
|
||||||
|
|
||||||
|
┌──────────────────────────────────────┐
|
||||||
|
START ────────►│ Track A: LLM Lab cleanup (2.5h) │──┐
|
||||||
|
│ └──────────────────────────────────────┘ │
|
||||||
|
│ ┌──────────────────────────────────────┐ │
|
||||||
|
├───────────►│ Track B: ollama-client pkg (1 day) │──┤
|
||||||
|
│ └──────────────────────────────────────┘ │
|
||||||
|
│ ┌──────────────────────────────────────┐ │ ┌─────────────────────────────┐
|
||||||
|
├───────────►│ Track C: fastify-sse extend (2h) │──┼──►│ Track E: LocalMemGPT (3h) │
|
||||||
|
│ └──────────────────────────────────────┘ │ └─────────────────────────────┘
|
||||||
|
│ ┌──────────────────────────────────────┐ │
|
||||||
|
└───────────►│ Track D: React hooks (5h) │──┘
|
||||||
|
└──────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
| File | Repo | One-Liner |
|
||||||
|
| ------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------ |
|
||||||
|
| [TRACK_A](./TRACK_A_llm_lab_workspace_removal.md) | `learning_ai_local_llms` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_A_llm_lab_workspace_removal.md` |
|
||||||
|
| [TRACK_B](./TRACK_B_ollama_client_package.md) | `learning_ai_common_plat` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_B_ollama_client_package.md` |
|
||||||
|
| [TRACK_C](./TRACK_C_fastify_sse_extend.md) | `learning_ai_common_plat` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_C_fastify_sse_extend.md` |
|
||||||
|
| [TRACK_D](./TRACK_D_react_hook_packages.md) | `learning_ai_common_plat` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_D_react_hook_packages.md` |
|
||||||
|
| [TRACK_E](./TRACK_E_localmemgpt_migrations.md) | `learning_ai_local_memory_gpt` | `Read and execute docs/roadmaps/not-started/coding_agent_prompts/TRACK_E_localmemgpt_migrations.md` |
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
# Track A — LLM Lab Workspace Removal
|
||||||
|
|
||||||
|
> **Repo:** `learning_ai_local_llms`
|
||||||
|
> **Can start:** Immediately (no dependencies)
|
||||||
|
> **Estimated time:** ~2.5 hours
|
||||||
|
> **Roadmap:** `../LOCAL_AI_CONSOLIDATION_ROADMAP.md` — read the Execution Checklist and Safety Matrix sections first.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Remove the chat workspace from Local LLM Lab, making Local Memory GPT the single chat surface. Then add a cross-link from Mission Control to LocalMemGPT.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Steps (4 commits)
|
||||||
|
|
||||||
|
### COMMIT 1 — `refactor(dashboard): remove chat workspace — LocalMemGPT is the chat surface`
|
||||||
|
|
||||||
|
1. Run `cd dashboard && pnpm test && pnpm run build` to establish green baseline
|
||||||
|
2. Delete the entire `dashboard/src/app/(workspace)/` directory (22 files: 6 routes + 16 components)
|
||||||
|
3. Delete `dashboard/src/app/api/ollama/title/` directory (1 workspace-only route)
|
||||||
|
4. Delete workspace lib files:
|
||||||
|
- `dashboard/src/app/lib/db.ts`
|
||||||
|
- `dashboard/src/app/lib/agents.ts`
|
||||||
|
- `dashboard/src/app/lib/quick-actions.ts`
|
||||||
|
- `dashboard/src/app/lib/scheduled-tasks.ts`
|
||||||
|
- `dashboard/src/app/lib/cron.ts`
|
||||||
|
- `dashboard/src/app/lib/migrate.ts`
|
||||||
|
5. Trim `types.ts`:
|
||||||
|
- Copy `Attachment` (lines 119–126) and `ModelDefaults` (lines 163–169) into the shared section (after line 77)
|
||||||
|
- Delete everything from line 78 onward (the `// --- v4 Workspace Types ---` comment and below)
|
||||||
|
- **Why:** `router.ts` line 1 does `import type { Attachment, ModelDefaults } from './types'` → used by `api/ollama/chat/route.ts` (Mission Control)
|
||||||
|
6. Delete workspace tests:
|
||||||
|
- `dashboard/src/app/lib/__tests__/agents.test.ts`
|
||||||
|
- `dashboard/src/app/lib/__tests__/cron.test.ts`
|
||||||
|
7. Create `dashboard/src/app/page.tsx` that redirects to `/mission-control`:
|
||||||
|
```tsx
|
||||||
|
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`
|
||||||
|
11. Grep for any remaining imports of deleted files:
|
||||||
|
```bash
|
||||||
|
grep -r 'from.*\(workspace\)\|from.*db\|from.*agents\|from.*quick-actions\|from.*scheduled-tasks\|from.*cron\|from.*migrate' dashboard/src/
|
||||||
|
```
|
||||||
|
|
||||||
|
### COMMIT 2 — `test(e2e): update specs after workspace removal`
|
||||||
|
|
||||||
|
1. Delete `e2e/chat.spec.ts` — tests workspace chat flow
|
||||||
|
2. Update `e2e/health.spec.ts` — remove `Conversation Routes` test that navigates to `/c/test-id`
|
||||||
|
3. Update `e2e/accessibility.spec.ts` — remove `/compare`, `/tts`, `/whisper` from routes array (keep `/`, `/mission-control`)
|
||||||
|
4. Update `e2e/visual-regression.spec.ts` — remove `workspace` and `compare` from ROUTES array (keep `mission-control`)
|
||||||
|
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 chat workspace description, add note pointing to Local Memory GPT for chat
|
||||||
|
3. Update `CLAUDE.md`, `.windsurfrules`, `.cursorrules` — align with new scope
|
||||||
|
|
||||||
|
### COMMIT 4 — `feat(dashboard): add LocalMemGPT cross-link in Mission Control`
|
||||||
|
|
||||||
|
1. Add a "Chat with your models →" card/banner in Mission Control dashboard
|
||||||
|
2. Link to `http://localhost:3070` (LocalMemGPT web default port)
|
||||||
|
3. Make URL configurable via `LOCALMEMGPT_URL` env var (default: `http://localhost:3070`)
|
||||||
|
4. Add `LOCALMEMGPT_URL` to `.env.example`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CRITICAL SAFETY RULES
|
||||||
|
|
||||||
|
**DO NOT delete these API routes** — Mission Control uses all of them:
|
||||||
|
|
||||||
|
- `api/ollama/chat/` — model testing prompt (page.tsx line 719)
|
||||||
|
- `api/ollama/stream/` — model comparison + benchmarks (lines 331, 538)
|
||||||
|
- `api/ollama/logs/` — Ollama log viewer (line 297)
|
||||||
|
- `api/tts/` — TTS engine status panel (line 179)
|
||||||
|
- `api/whisper/` — Whisper status card (line 165)
|
||||||
|
- `api/whisper/transcribe/` — transcription test button (line 313)
|
||||||
|
|
||||||
|
**DO NOT delete these lib files** — all shared:
|
||||||
|
|
||||||
|
- `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`
|
||||||
|
|
||||||
|
**DO NOT delete** `src/components/` — all 6 components are shared by Mission Control.
|
||||||
|
|
||||||
|
**DO NOT delete** `globals.css` — all 319 lines are shared (no workspace-specific tokens).
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
# Track B — Create `@bytelyst/ollama-client` Package
|
||||||
|
|
||||||
|
> **Repo:** `learning_ai_common_plat`
|
||||||
|
> **Can start:** Immediately (no dependencies)
|
||||||
|
> **Estimated time:** ~1 day
|
||||||
|
> **Roadmap:** `../LOCAL_AI_CONSOLIDATION_ROADMAP.md` — sections 4.1, 4.5, 4.6, and 4.7.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Create a new `@bytelyst/ollama-client` package that eliminates ~350 lines of duplicated Ollama API 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<OllamaStreamChunk>
|
||||||
|
│ ├── 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
|
||||||
|
└── vitest.config.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reference Implementations to Consolidate
|
||||||
|
|
||||||
|
Read these files from sibling repos to understand the existing patterns:
|
||||||
|
|
||||||
|
1. **`../learning_ai_local_memory_gpt/backend/src/lib/ollama.ts`** (117 lines)
|
||||||
|
- `listOllamaModels()` — `GET /api/tags`
|
||||||
|
- `checkOllamaHealth()` — `GET /` with timeout
|
||||||
|
- `streamChat()` — `POST /api/chat` with NDJSON response parsing
|
||||||
|
- `getEmbedding()` — `POST /api/embed`
|
||||||
|
|
||||||
|
2. **`../learning_ai_local_llms/dashboard/src/app/lib/ollama-config.ts`** (40 lines)
|
||||||
|
- `OLLAMA_URL` env resolution
|
||||||
|
- WSL2 gateway detection (reads `/etc/resolv.conf` nameserver)
|
||||||
|
|
||||||
|
3. **`../learning_ai_local_llms/dashboard/src/app/api/ollama/route.ts`** (128 lines)
|
||||||
|
- `fetchOllama()` helper wrapper
|
||||||
|
- Model list, pull, delete, show, load, unload operations
|
||||||
|
|
||||||
|
4. **NDJSON stream parsing pattern** (copy-pasted 5+ times across both repos):
|
||||||
|
```ts
|
||||||
|
const reader = res.body.getReader();
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
let buffer = '';
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) break;
|
||||||
|
buffer += decoder.decode(value, { stream: true });
|
||||||
|
const lines = buffer.split('\n');
|
||||||
|
buffer = lines.pop() ?? '';
|
||||||
|
for (const line of lines) {
|
||||||
|
if (!line.trim()) continue;
|
||||||
|
try {
|
||||||
|
yield JSON.parse(line);
|
||||||
|
} catch {
|
||||||
|
/* skip */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Types to Include (section 4.5)
|
||||||
|
|
||||||
|
Canonical `OllamaModel` type — superset of both repos' definitions, matching Ollama's actual API response:
|
||||||
|
|
||||||
|
| Repo | Definition |
|
||||||
|
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| LocalMemGPT `ollama.ts` | `{ name, size, digest, modified_at, details?: { parameter_size, quantization_level, family } }` |
|
||||||
|
| LLM Lab `types.ts` | `{ name, model, modified_at, size, digest, details: { families, family, format, parameter_size, quantization_level } }` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reusable Utilities to Include (section 4.6)
|
||||||
|
|
||||||
|
Extract these from `../learning_ai_local_llms/dashboard/src/app/lib/format.ts` (96 lines):
|
||||||
|
|
||||||
|
| Function | Scope |
|
||||||
|
| ------------------------- | ------------------------------- |
|
||||||
|
| `formatBytes()` | General purpose byte formatting |
|
||||||
|
| `estimateTokens()` | LLM token estimation |
|
||||||
|
| `getModelContextWindow()` | Model context window lookup |
|
||||||
|
| `formatUptime()` | Uptime formatting |
|
||||||
|
|
||||||
|
Leave LLM-Lab-specific functions (`estimateRam`, `checkMemoryFit`, `getModelBadges`) in LLM Lab.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Side Parsers to Include (section 4.7)
|
||||||
|
|
||||||
|
Browser-side stream consumers for Next.js API route clients:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Client-side SSE stream consumer
|
||||||
|
export function consumeSSEStream(
|
||||||
|
response: Response,
|
||||||
|
onData: (data: Record<string, unknown>) => void,
|
||||||
|
onDone: () => void
|
||||||
|
): Promise<void>;
|
||||||
|
|
||||||
|
// Client-side NDJSON stream consumer
|
||||||
|
export function consumeNdjsonStream<T>(
|
||||||
|
response: Response,
|
||||||
|
onChunk: (chunk: T) => void
|
||||||
|
): Promise<void>;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
Follow existing `@bytelyst/*` package patterns:
|
||||||
|
|
||||||
|
- ESM (`"type": "module"`), TypeScript, `exports` field in `package.json`
|
||||||
|
- Extend `../../tsconfig.base.json`
|
||||||
|
- Vitest for tests with `passWithNoTests: true`
|
||||||
|
- `peerDependencies` for heavy deps if any
|
||||||
|
- `workspace:*` for inter-package deps
|
||||||
|
- Build: `tsc` → `dist/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Scope Boundary
|
||||||
|
|
||||||
|
**DO NOT** migrate consumer repos — that happens in Track E. Only create the package, write tests, and publish to Gitea registry.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit
|
||||||
|
|
||||||
|
`feat(ollama-client): shared Ollama API client package`
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
# Track C — Extend `@bytelyst/fastify-sse` with Per-Request Helpers
|
||||||
|
|
||||||
|
> **Repo:** `learning_ai_common_plat`
|
||||||
|
> **Can start:** Immediately (no dependencies)
|
||||||
|
> **Estimated time:** ~2 hours
|
||||||
|
> **Roadmap:** `../LOCAL_AI_CONSOLIDATION_ROADMAP.md` — section 4.2.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Extend the existing `@bytelyst/fastify-sse` package (`packages/fastify-sse/`) with per-request SSE helpers. The package currently only provides `SSEHub` (multi-client broadcast). We need single-request streaming helpers too.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
| Existing | What it does |
|
||||||
|
| -------------------------------- | ------------------------------------------------------------------------------------ |
|
||||||
|
| `@bytelyst/fastify-sse` `SSEHub` | Multi-client broadcast pattern (hub/spoke) — one event pushed to N connected clients |
|
||||||
|
| LocalMemGPT `sse-helpers.ts` | Single-request streaming — one route handler streams SSE to one client |
|
||||||
|
|
||||||
|
The per-request pattern is used by chat streaming and model comparison endpoints.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reference Implementation
|
||||||
|
|
||||||
|
Read `../learning_ai_local_memory_gpt/backend/src/lib/sse-helpers.ts` (26 lines):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
startSSE(reply); // Sets Content-Type: text/event-stream headers, calls reply.hijack()
|
||||||
|
sendSSEData(reply, data); // Writes "data: JSON.stringify(data)\n\n"
|
||||||
|
sendSSEEvent(reply, event, data); // Writes "event: name\ndata: JSON.stringify(data)\n\n"
|
||||||
|
endSSE(reply); // Writes "data: [DONE]\n\n" and ends the stream
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
1. Add a new file: `packages/fastify-sse/src/per-request.ts`
|
||||||
|
- `startSSE(reply: FastifyReply): void`
|
||||||
|
- `sendSSEData(reply: FastifyReply, data: unknown): void`
|
||||||
|
- `sendSSEEvent(reply: FastifyReply, event: string, data: unknown): void`
|
||||||
|
- `endSSE(reply: FastifyReply): void`
|
||||||
|
|
||||||
|
2. Export from `packages/fastify-sse/src/index.ts` alongside existing exports:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export { startSSE, sendSSEData, sendSSEEvent, endSSE } from './per-request.js';
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Add tests: `packages/fastify-sse/src/per-request.test.ts`
|
||||||
|
- Test that `startSSE` sets correct headers and hijacks the reply
|
||||||
|
- Test that `sendSSEData` formats data correctly
|
||||||
|
- Test that `sendSSEEvent` formats named events correctly
|
||||||
|
- Test that `endSSE` sends the `[DONE]` sentinel and ends the stream
|
||||||
|
|
||||||
|
4. Publish updated package to Gitea registry
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- ESM (`"type": "module"`), TypeScript
|
||||||
|
- Fastify 5 types (`FastifyReply`)
|
||||||
|
- Vitest for tests
|
||||||
|
- Don't break existing `SSEHub` / `ssePlugin` exports
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Scope Boundary
|
||||||
|
|
||||||
|
**DO NOT** migrate consumer repos — that happens in Track E. Only add the per-request helpers to the package.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit
|
||||||
|
|
||||||
|
`feat(fastify-sse): add per-request SSE helpers`
|
||||||
@ -0,0 +1,160 @@
|
|||||||
|
# Track D — Create React Hook Packages (`use-theme` + `use-keyboard-shortcuts`)
|
||||||
|
|
||||||
|
> **Repo:** `learning_ai_common_plat`
|
||||||
|
> **Can start:** Immediately (no dependencies)
|
||||||
|
> **Estimated time:** ~5 hours
|
||||||
|
> **Roadmap:** `../LOCAL_AI_CONSOLIDATION_ROADMAP.md` — sections 4.3 and 4.4.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Create TWO new `@bytelyst/*` packages that eliminate ~550 lines of duplicated React hooks across the ecosystem.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Package 1: `packages/use-theme/`
|
||||||
|
|
||||||
|
### Problem
|
||||||
|
|
||||||
|
Near-identical `useTheme()` hook duplicated across **6 web apps** — only the storage key and class-application strategy differ.
|
||||||
|
|
||||||
|
| Repo | File | Storage Key | Lines |
|
||||||
|
| ----------- | ------------------------------------ | ----------- | ----- |
|
||||||
|
| LocalMemGPT | `web/src/lib/use-theme.ts` | `lmg-theme` | 49 |
|
||||||
|
| LLM Lab | `dashboard/src/app/lib/use-theme.ts` | `llm-theme` | 48 |
|
||||||
|
| ChronoMind | `web/src/lib/use-theme.ts` | `cm-theme` | ~50 |
|
||||||
|
| FlowMonk | `web/src/lib/use-theme.ts` | `fm-theme` | ~50 |
|
||||||
|
| NomGap | `web/src/lib/use-theme.ts` | `ng-theme` | ~50 |
|
||||||
|
| ActionTrail | `web/src/lib/use-theme.ts` | `at-theme` | ~50 |
|
||||||
|
|
||||||
|
### Reference Implementations
|
||||||
|
|
||||||
|
Read these two files to understand the pattern:
|
||||||
|
|
||||||
|
- `../learning_ai_local_memory_gpt/web/src/lib/use-theme.ts` (49 lines)
|
||||||
|
- `../learning_ai_local_llms/dashboard/src/app/lib/use-theme.ts` (48 lines)
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export function useTheme(options?: {
|
||||||
|
storageKey?: string; // default: 'theme'
|
||||||
|
attribute?: 'class' | 'data-theme'; // default: 'class'
|
||||||
|
}): {
|
||||||
|
theme: 'light' | 'dark';
|
||||||
|
setTheme: (t: 'light' | 'dark') => void;
|
||||||
|
toggleTheme: () => void;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Package Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
packages/use-theme/
|
||||||
|
├── src/
|
||||||
|
│ ├── index.ts # Public export
|
||||||
|
│ └── use-theme.ts # Hook implementation
|
||||||
|
├── src/__tests__/
|
||||||
|
│ └── use-theme.test.ts # Vitest + @testing-library/react
|
||||||
|
├── package.json
|
||||||
|
├── tsconfig.json
|
||||||
|
└── vitest.config.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- Toggles between light and dark
|
||||||
|
- Persists to localStorage with configurable key
|
||||||
|
- Applies class to `document.documentElement`
|
||||||
|
- Reads initial value from localStorage
|
||||||
|
- Falls back to `'dark'` when no stored value
|
||||||
|
- Supports `data-theme` attribute mode
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
|
||||||
|
`feat(use-theme): shared React theme toggle hook`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Package 2: `packages/use-keyboard-shortcuts/`
|
||||||
|
|
||||||
|
### Problem
|
||||||
|
|
||||||
|
Near-identical `useKeyboardShortcuts()` hook duplicated across **5+ web apps**, each with hardcoded if/else chains.
|
||||||
|
|
||||||
|
| Repo | File |
|
||||||
|
| ----------- | ------------------------------------------------------------ |
|
||||||
|
| LocalMemGPT | `web/src/lib/use-keyboard-shortcuts.ts` (53 lines) |
|
||||||
|
| LLM Lab | `dashboard/src/app/lib/use-keyboard-shortcuts.ts` (57 lines) |
|
||||||
|
| ChronoMind | `web/src/lib/use-keyboard-shortcuts.ts` |
|
||||||
|
| ActionTrail | `web/src/lib/use-keyboard-shortcuts.ts` |
|
||||||
|
| NoteLett | `web/src/lib/use-keyboard-shortcuts.ts` |
|
||||||
|
|
||||||
|
### Reference Implementations
|
||||||
|
|
||||||
|
Read these two files to understand the pattern:
|
||||||
|
|
||||||
|
- `../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)
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export interface ShortcutDef {
|
||||||
|
key: string;
|
||||||
|
meta?: boolean;
|
||||||
|
shift?: boolean;
|
||||||
|
alt?: boolean;
|
||||||
|
handler: () => void;
|
||||||
|
allowInInput?: boolean; // default: false — skip if focus is in input/textarea
|
||||||
|
description?: string; // for help overlay / accessibility
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useKeyboardShortcuts(shortcuts: ShortcutDef[]): void;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Package Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
packages/use-keyboard-shortcuts/
|
||||||
|
├── src/
|
||||||
|
│ ├── index.ts # Public export
|
||||||
|
│ └── use-keyboard-shortcuts.ts # Hook implementation
|
||||||
|
├── src/__tests__/
|
||||||
|
│ └── use-keyboard-shortcuts.test.ts
|
||||||
|
├── package.json
|
||||||
|
├── tsconfig.json
|
||||||
|
└── vitest.config.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- Fires handler on matching key combo
|
||||||
|
- Respects `meta`, `shift`, `alt` modifiers
|
||||||
|
- Skips handler when focus is in `<input>` or `<textarea>` (unless `allowInInput: true`)
|
||||||
|
- Handles multiple shortcuts simultaneously
|
||||||
|
- Cleans up event listener on unmount
|
||||||
|
- Handles empty shortcuts array
|
||||||
|
|
||||||
|
### Commit
|
||||||
|
|
||||||
|
`feat(use-keyboard-shortcuts): shared React keyboard shortcuts hook`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions (both packages)
|
||||||
|
|
||||||
|
- ESM (`"type": "module"`), TypeScript
|
||||||
|
- React 19 as `peerDependency`
|
||||||
|
- Vitest + `@testing-library/react` + `jsdom` for tests
|
||||||
|
- Extend `../../tsconfig.base.json`
|
||||||
|
- `exports` field in `package.json`
|
||||||
|
- Build: `tsc` → `dist/`
|
||||||
|
- Publish to Gitea registry
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Scope Boundary
|
||||||
|
|
||||||
|
**DO NOT** migrate consumer repos yet — migrations can happen as a follow-up ecosystem sweep. Only create the packages, write tests, and publish.
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
# Track E — Migrate LocalMemGPT (Cross-Link + Package Migrations)
|
||||||
|
|
||||||
|
> **Repo:** `learning_ai_local_memory_gpt`
|
||||||
|
> **Can start:** After Tracks A, B, and C are complete
|
||||||
|
> **Estimated time:** ~3 hours
|
||||||
|
> **Roadmap:** `../LOCAL_AI_CONSOLIDATION_ROADMAP.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before starting this track, confirm:
|
||||||
|
|
||||||
|
- [ ] **Track A** complete — LLM Lab workspace removed, cross-link added
|
||||||
|
- [ ] **Track B** complete — `@bytelyst/ollama-client` published to Gitea registry
|
||||||
|
- [ ] **Track C** complete — `@bytelyst/fastify-sse` updated with per-request helpers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 1 — Add LLM Lab Cross-Link
|
||||||
|
|
||||||
|
Add a link from LocalMemGPT to LLM Lab for model management.
|
||||||
|
|
||||||
|
1. Add a "Model Management →" link in the Settings panel (`web/src/components/SettingsPanel.tsx`)
|
||||||
|
2. Link to `http://localhost:3000` (LLM Lab dashboard default port)
|
||||||
|
3. Make URL configurable via `LOCALLLMLAB_URL` env var (default: `http://localhost:3000`)
|
||||||
|
4. Add `LOCALLLMLAB_URL` to `web/.env.example`
|
||||||
|
|
||||||
|
**Commit:** `feat(web): add LLM Lab cross-link in settings`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 2 — Migrate to `@bytelyst/ollama-client`
|
||||||
|
|
||||||
|
Replace the hand-rolled Ollama client with the shared package.
|
||||||
|
|
||||||
|
1. Add `@bytelyst/ollama-client` dependency (from Gitea registry)
|
||||||
|
2. Replace `backend/src/lib/ollama.ts` (117 lines) with imports from the package:
|
||||||
|
|
||||||
|
| Old (lib/ollama.ts) | New (@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 type { OllamaModel } from '@bytelyst/ollama-client'` |
|
||||||
|
|
||||||
|
3. Update all consumers of `lib/ollama.ts` to use new import paths
|
||||||
|
4. Delete `backend/src/lib/ollama.ts`
|
||||||
|
5. Verify: `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
|
||||||
|
|
||||||
|
Replace the hand-rolled SSE helpers with the shared package exports.
|
||||||
|
|
||||||
|
1. Update `@bytelyst/fastify-sse` dependency to latest version (with per-request helpers)
|
||||||
|
2. Replace `backend/src/lib/sse-helpers.ts` (26 lines) with imports:
|
||||||
|
```ts
|
||||||
|
import { startSSE, sendSSEData, sendSSEEvent, endSSE } from '@bytelyst/fastify-sse';
|
||||||
|
```
|
||||||
|
3. Update consumers:
|
||||||
|
- `backend/src/modules/chat/routes.ts`
|
||||||
|
- `backend/src/modules/compare/routes.ts`
|
||||||
|
4. Delete `backend/src/lib/sse-helpers.ts`
|
||||||
|
5. Verify: `cd backend && npm test && npm run typecheck && npm run build`
|
||||||
|
|
||||||
|
**Commit:** `refactor(backend): migrate to @bytelyst/fastify-sse per-request helpers`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
After all 3 tasks, run the full test suite and confirm all ~104 tests pass:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend && npm test && npm run typecheck && npm run build
|
||||||
|
cd ../web && npm run typecheck && npm run build
|
||||||
|
```
|
||||||
Loading…
Reference in New Issue
Block a user