67 lines
5.0 KiB
Markdown
67 lines
5.0 KiB
Markdown
# AI Course Assistant Implementation Plan
|
|||
|
|
|
||
|
|
## Scope Lock (v1)
|
||
|
|
|
||
|
|
1. AI assistant is teacher-only (course team members; not students).
|
||
|
|
2. Agent executes via API (no local-only execution).
|
||
|
|
3. All actions are org/course-scoped; no cross-org access.
|
||
|
|
4. Self-hosted: assistant not available; hide UI and block agent routes.
|
||
|
|
5. Chat lives in a right sidebar (Sheet) from the course header.
|
||
|
|
6. Supported intents: update lesson text, generate questions from text, draft lesson; exercise tagging TBD (clarify org tags vs template tags).
|
||
|
|
|
||
|
|
## Delivery Phases
|
||
|
|
|
||
|
|
1. Phase A: Package + types + self-host gate
|
||
|
|
2. Phase B: Agent API routes + permission checks
|
||
|
|
3. Phase C: Chat UI + header button
|
||
|
|
4. Phase D: LLM integration + intent execution
|
||
|
|
5. Phase E: Polish (quick actions, context, rate limits)
|
||
|
|
|
||
|
|
## Ticket Breakdown
|
||
|
|
|
||
|
|
| ID | Area | Task | Key Files | Dependencies | Done When |
|
||
|
|
| --- | --- | --- | --- | --- | --- |
|
||
|
|
| AI-A1 | Package | Create `packages/ai-assistant` with types (Message, Intent, Response) | `packages/ai-assistant/src/types.ts` | None | Package builds; types exportable |
|
||
|
|
| AI-A2 | Package | Add optional API client for agent chat | `packages/ai-assistant/src/client.ts` | AI-A1 | Client can call agent endpoints (or dashboard uses RPC directly) |
|
||
|
|
| AI-A3 | Dashboard | Add `isAiAssistantAvailable` util (false when `PUBLIC_IS_SELFHOSTED`) | `apps/dashboard/src/lib/utils/ai-assistant.ts` | None | Util returns bool; hide button when self-hosted |
|
||
|
|
| AI-B1 | API | Add agent validation schemas (chat payload, intent payloads) | `packages/utils/src/validation/agent/` | None | Zod schemas for chat + intents |
|
||
|
|
| AI-B2 | API | Add agent routes under `/course/:courseId/agent`; do not register or return 403 when self-hosted | `apps/api/src/routes/course/agent.ts` | AI-B1 | `POST /chat`, `POST /execute` (or combined); blocked when `PUBLIC_IS_SELFHOSTED` |
|
||
|
|
| AI-B3 | API | Apply auth + courseTeamMember middleware to agent routes | `apps/api/src/routes/course/agent.ts` | AI-B2 | Unauthorized users get 403 |
|
||
|
|
| AI-B4 | API | Add agent service: parse message → intent → call lesson/exercise services | `apps/api/src/services/agent.ts` | AI-B2 | Service orchestrates intents; returns structured response |
|
||
|
|
| AI-B5 | API | Verify org/course scoping in every agent mutation | `apps/api/src/services/agent.ts` | AI-B4 | Cross-org requests rejected |
|
||
|
|
| AI-C1 | Dashboard | Add AI Assistant button to course header | `apps/dashboard/src/lib/features/course/components/course-header.svelte` | AI-A3 | Button visible when `isAiAssistantAvailable` and teacher |
|
||
|
|
| AI-C2 | Dashboard | Add right Sheet with chat UI (message list + input) | `apps/dashboard/src/lib/features/ai-assistant/ai-assistant-sheet.svelte` | AI-C1 | Sheet opens from button; placeholder chat |
|
||
|
|
| AI-C3 | Dashboard | Create AI assistant feature module (store, API class) | `apps/dashboard/src/lib/features/ai-assistant/` | AI-A1 | API class calls agent endpoint; store holds messages |
|
||
|
|
| AI-C4 | Dashboard | Wire chat input → API → message display | `apps/dashboard/src/lib/features/ai-assistant/` | AI-C3, AI-B2 | User can send message; response shows in chat |
|
||
|
|
| AI-D1 | API | Integrate LLM provider (OpenAI/Anthropic) for chat completion | `apps/api/src/services/agent.ts` | AI-B4 | Agent can generate text from user message |
|
||
|
|
| AI-D2 | API | Implement intent: update lesson text | Agent service + lessonLanguage service | AI-D1 | "Update this text..." → `updateLessonLanguageService` |
|
||
|
|
| AI-D3 | API | Implement intent: generate N questions from text | Agent service | AI-D1 | Returns generated questions as text; user copies or we add create flow later |
|
||
|
|
| AI-D4 | API | Implement intent: draft lesson | Agent service + `createLesson` | AI-D1 | Creates draft lesson; returns lesson ID for navigation |
|
||
|
|
| AI-D5 | API | Clarify and implement exercise tagging intent | Agent service + tag/course APIs | AI-D1 | Semantic clarified in PRD; implement |
|
||
|
|
| AI-E1 | Copy | Add i18n keys for AI assistant UI | `apps/dashboard/src/lib/utils/translations/en.json` | AI-C2 | No hardcoded strings |
|
||
|
|
| AI-E2 | API | Add rate limiting for agent endpoints | Middleware or route-level | AI-B2 | Prevents abuse; configurable limit |
|
||
|
|
| AI-E3 | Tests | Add auth/role tests for agent routes | API tests | AI-B3 | Unauthorized/student requests return 403 |
|
||
|
|
|
||
|
|
## API Contract (Target)
|
||
|
|
|
||
|
|
### Agent Chat
|
||
|
|
|
||
|
|
- `POST /course/:courseId/agent/chat`
|
||
|
|
- Body: `{ message: string, context?: { lessonId?, exerciseId? } }`
|
||
|
|
- Response: `{ success: true, data: { message: string, intent?: string, actions?: [...] } }`
|
||
|
|
- Auth: `authMiddleware`, `courseTeamMemberMiddleware`
|
||
|
|
|
||
|
|
### Optional Structured Execute
|
||
|
|
|
||
|
|
- `POST /course/:courseId/agent/execute`
|
||
|
|
- Body: `{ intent: string, payload: Record<string, unknown> }`
|
||
|
|
- For tool-calling or explicit intent execution (e.g. from LLM tool use)
|
||
|
|
- Auth: same as above
|
||
|
|
|
||
|
|
## Open Items Before Implementation
|
||
|
|
|
||
|
|
1. LLM provider choice (OpenAI vs Anthropic vs configurable).
|
||
|
|
2. Streaming: v1 non-streaming vs SSE streaming.
|
||
|
|
3. Exercise tagging semantics (org course tags vs exercise template tags).
|
||
|
|
4. Draft lesson: create immediately vs return text for paste.
|