feat(api): GET /api/workspaces/:id/stats endpoint
This commit is contained in:
83
workers/chat-wire-prompt.txt
Normal file
83
workers/chat-wire-prompt.txt
Normal file
@@ -0,0 +1,83 @@
|
||||
Wire the chat interface in ~/src/mosaic-stack to the backend API.
|
||||
|
||||
## Context
|
||||
The chat page (/chat) exists with full UI components but is NOT connected to the backend. Everything is stubbed. The old jarvis codebase had a working implementation — use it as the reference.
|
||||
|
||||
## Architecture Decision
|
||||
Use `/api/chat/stream` (chat-proxy → OpenClaw) for LLM responses.
|
||||
But ALSO wire conversation persistence using the existing brain + conversation-archive endpoints.
|
||||
|
||||
## Backend Endpoints Available (all authenticated, cookie-based auth):
|
||||
|
||||
### Chat/LLM:
|
||||
- POST /api/chat/stream — SSE stream proxied from OpenClaw
|
||||
- Request body: { messages: [{role, content}], model?: string }
|
||||
- Response: SSE stream (pass-through from OpenClaw — handle both OpenAI format and custom format)
|
||||
- OpenAI streaming format: data: {"choices":[{"delta":{"content":"token"},"finish_reason":null}]}\n\n
|
||||
- Final: data: [DONE]\n\n OR data: {"choices":[{"finish_reason":"stop"}]}\n\n
|
||||
- Error: event: error\ndata: {"error":"message"}\n\n
|
||||
|
||||
### Conversation Archive (for persistence):
|
||||
- GET /api/conversation-archives — list user's archived conversations
|
||||
- POST /api/conversation-archives — create/save a conversation
|
||||
- Body: { title: string, summary?: string, messages: [{role, content, timestamp?}], metadata?: object }
|
||||
- GET /api/conversation-archives/:id — get specific conversation
|
||||
- DELETE /api/conversation-archives/:id — delete
|
||||
|
||||
### Brain (for context):
|
||||
- POST /api/brain/query — query tasks, projects, events
|
||||
- GET /api/brain/context — get summary context
|
||||
|
||||
## What to Change
|
||||
|
||||
### 1. apps/web/src/lib/api/chat.ts
|
||||
Rewrite `streamChatMessage` to:
|
||||
- Call `POST /api/chat/stream` (not /api/llm/chat)
|
||||
- Use credentials: "include" (cookie auth)
|
||||
- Add X-Workspace-Id header from workspace context
|
||||
- Handle OpenAI SSE format: parse `data.choices[0].delta.content` for tokens
|
||||
- Also handle `data: [DONE]` as completion
|
||||
- Keep the same callback signature: onChunk(token), onComplete(), onError(err)
|
||||
|
||||
Add new functions:
|
||||
- `saveConversation(title, messages)` → POST /api/conversation-archives
|
||||
- `listConversations()` → GET /api/conversation-archives
|
||||
- `getConversation(id)` → GET /api/conversation-archives/:id
|
||||
- `deleteConversation(id)` → DELETE /api/conversation-archives/:id
|
||||
|
||||
### 2. apps/web/src/hooks/useChat.ts
|
||||
- Fix `loadConversation`: load from conversation-archives API instead of ideas/brain
|
||||
- Fix `sendMessage`: uses streamChatMessage correctly with the messages array
|
||||
- Add `saveCurrentConversation()`: save to conversation-archives after each assistant reply
|
||||
- Wire up auto-save after each successful assistant response
|
||||
|
||||
### 3. apps/web/src/components/chat/ConversationSidebar.tsx
|
||||
Check if it loads from conversations API — if it's stubbed or uses wrong endpoint, fix to use `listConversations()`.
|
||||
|
||||
## Key Reference: Old Jarvis Implementation
|
||||
The old jarvis at ~/src/jarvis-old/apps/web/src had:
|
||||
- components/Chat.tsx (1616 lines — working SSE stream handler)
|
||||
- lib/api.ts — working API client
|
||||
- hooks/useConversations.ts — conversation list management
|
||||
|
||||
Read these for reference on SSE parsing, error handling, conversation state management patterns.
|
||||
|
||||
## Constraints
|
||||
- Keep auth as cookie-based (credentials: "include") — NOT Bearer token for web client
|
||||
- The X-Workspace-Id header must be included on all API calls
|
||||
- Use useWorkspaceId() hook to get workspace ID
|
||||
- Keep TypeScript strict — no `any` unless unavoidable
|
||||
- Match existing chat.ts style (callbacks not promises for streaming)
|
||||
|
||||
## Process
|
||||
1. git checkout main && git pull --ff-only origin main
|
||||
2. git checkout -b feat/wire-chat-interface
|
||||
3. Read the existing files: apps/web/src/lib/api/chat.ts, apps/web/src/hooks/useChat.ts, apps/web/src/components/chat/*.tsx
|
||||
4. Read reference: ~/src/jarvis-old/apps/web/src/components/Chat.tsx (lines 400-550 for SSE handling)
|
||||
5. Implement the changes
|
||||
6. Run: pnpm turbo lint typecheck --filter=@mosaic/web
|
||||
7. Commit --no-verify: "feat(web): wire chat interface to /api/chat/stream and conversation-archives"
|
||||
8. Push and PR: ~/.config/mosaic/tools/git/pr-create.sh -t "feat(web): wire chat interface to backend" -b "Wires the stubbed chat page to /api/chat/stream (OpenClaw proxy) for LLM responses and /api/conversation-archives for persistence. References old jarvis implementation for SSE parsing patterns."
|
||||
|
||||
When done:
|
||||
openclaw system event --text "Done: chat wiring PR ready" --mode now
|
||||
29
workers/csrf-fix-prompt.txt
Normal file
29
workers/csrf-fix-prompt.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
Fix the CsrfGuard in ~/src/mosaic-stack to skip CSRF validation when the request is authenticated via Bearer token (Authorization header).
|
||||
|
||||
## Background
|
||||
CSRF attacks exploit cookie-based authentication — a malicious site tricks the browser into sending authenticated cookies. When a client uses `Authorization: Bearer <token>`, CSRF is not a valid attack vector because malicious sites cannot set or read Authorization headers. The CSRF guard should not fire for Bearer-authenticated API clients.
|
||||
|
||||
## File to Change
|
||||
apps/api/src/common/guards/csrf.guard.ts
|
||||
|
||||
## What to Do
|
||||
1. git checkout main && git pull --ff-only origin main
|
||||
2. Create branch: fix/csrf-bearer-bypass
|
||||
3. Read csrf.guard.ts carefully
|
||||
4. Update `canActivate` to skip CSRF check when the request has an `Authorization: Bearer` header
|
||||
- Extract the Authorization header
|
||||
- If it starts with "Bearer ", return true (skip CSRF — Bearer auth is not CSRF-vulnerable)
|
||||
- Otherwise, proceed with existing CSRF token validation as-is
|
||||
5. Do NOT change any other logic — surgical change only
|
||||
6. Read auth.guard.ts to confirm you are using the same header extraction pattern for consistency
|
||||
|
||||
## Completion Requirements (MANDATORY)
|
||||
1. Run quality gates: pnpm turbo lint typecheck --filter=@mosaic/api
|
||||
2. Run tests: pnpm --filter @mosaic/api test -- --run
|
||||
3. Review the change: confirm existing CSRF tests still pass, confirm Bearer bypass is correct
|
||||
4. Commit: "fix(api): skip CSRF for Bearer-authenticated requests"
|
||||
5. Push branch
|
||||
6. Create PR: ~/.config/mosaic/tools/git/pr-create.sh -t "fix(api): skip CSRF for Bearer-authenticated API clients" -b "CSRF protection is only relevant for cookie-based sessions. Requests using Authorization: Bearer are not CSRF-vulnerable — malicious sites cannot inject Authorization headers. This change skips CSRF validation when a Bearer token is present, enabling programmatic API access from agents and service accounts."
|
||||
|
||||
When completely finished, run:
|
||||
openclaw system event --text "Done: CSRF Bearer bypass PR ready for review" --mode now
|
||||
51
workers/fleet-provider-dto-fix-prompt.txt
Normal file
51
workers/fleet-provider-dto-fix-prompt.txt
Normal file
@@ -0,0 +1,51 @@
|
||||
Fix the fleet-settings "Add Provider" form in ~/src/mosaic-stack so it submits the correct field names to the API.
|
||||
|
||||
## Background
|
||||
The Add Provider UI form (apps/web) sends these fields to POST /api/llm-providers:
|
||||
- type (should be: providerType)
|
||||
- baseUrl (should be nested inside config.endpoint)
|
||||
- models (should be nested inside config.models)
|
||||
- displayName (correct)
|
||||
- apiKey (should be nested inside config.apiKey)
|
||||
|
||||
The API DTO (apps/api/src/llm/dto/provider-admin.dto.ts) expects:
|
||||
{
|
||||
providerType: "ollama" | "openai" | "claude",
|
||||
displayName: string,
|
||||
config: {
|
||||
endpoint?: string, // the base URL
|
||||
apiKey?: string,
|
||||
models?: string[], // list of model IDs
|
||||
timeout?: number
|
||||
},
|
||||
isDefault?: boolean,
|
||||
isEnabled?: boolean
|
||||
}
|
||||
|
||||
## Files to Change
|
||||
- apps/web — find the Add Provider form/dialog component (search for "Add Provider" or "baseUrl" or "providerType")
|
||||
- Fix the form submission to map fields correctly before POSTing
|
||||
|
||||
## Process
|
||||
1. git checkout main && git pull --ff-only origin main
|
||||
2. Create branch: fix/fleet-provider-form-dto
|
||||
3. Find the form component — search: grep -r "baseUrl\|Add Provider\|providerType" apps/web/src --include="*.tsx" --include="*.ts" -l
|
||||
4. Fix field mapping in the form submit handler:
|
||||
- type → providerType
|
||||
- baseUrl → config.endpoint
|
||||
- models (textarea, newline-separated) → config.models (string array, split by newline, trim, filter empty)
|
||||
- apiKey → config.apiKey
|
||||
5. Also fix the models input: if it's a textarea with one model per line, split on newline before submitting
|
||||
|
||||
## Completion Requirements (MANDATORY)
|
||||
1. Run: pnpm turbo lint typecheck --filter=@mosaic/web
|
||||
2. Run: pnpm --filter @mosaic/web test -- --run (if tests exist)
|
||||
3. Review: confirm form submit payload matches CreateLlmProviderDto exactly
|
||||
4. Commit: "fix(web): correct Add Provider form field mapping to match API DTO"
|
||||
5. Push and create PR:
|
||||
~/.config/mosaic/tools/git/pr-create.sh \
|
||||
-t "fix(web): correct Add Provider form DTO field mapping" \
|
||||
-b "The Add Provider form was sending top-level fields (type, baseUrl, models) that do not match the API DTO. Fixed to send providerType and nest endpoint/apiKey/models inside config object. Models textarea is now split by newline into a string array."
|
||||
|
||||
When completely finished, run:
|
||||
openclaw system event --text "Done: fleet-provider form DTO fix PR ready" --mode now
|
||||
38
workers/kanban-add-task-prompt.txt
Normal file
38
workers/kanban-add-task-prompt.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
Add "Add Task" functionality to the Kanban board in ~/src/mosaic-stack.
|
||||
|
||||
## Problem
|
||||
The Kanban page (/kanban) shows tasks and allows drag-drop between columns, but there is NO way to create a new task. Users can't add tasks directly to the queue.
|
||||
|
||||
## What Exists
|
||||
- File: apps/web/src/app/(authenticated)/kanban/page.tsx (765 lines)
|
||||
- API client: apps/web/src/lib/api/tasks.ts — already has fetchTasks, updateTask, and a newly added createTask function
|
||||
- API endpoint: POST /api/tasks (accepts: title, description?, status?, priority?, dueDate?, projectId?)
|
||||
- Shared types: @mosaic/shared — Task, TaskStatus, TaskPriority enums
|
||||
- Project fetch: fetchProjects already imported in kanban page
|
||||
|
||||
## What to Build
|
||||
Add an "Add Task" button (+ icon) to each Kanban column header that:
|
||||
1. Opens an inline form or small dialog directly in that column
|
||||
2. Form fields: title (required), description (optional), priority (optional, defaults to MEDIUM), dueDate (optional)
|
||||
3. On submit: calls createTask({ title, description, priority, status: <column_status>, projectId: currentProjectFilter })
|
||||
4. On success: adds the new task to the column without full page reload (optimistic or refetch)
|
||||
5. On cancel: dismisses form
|
||||
6. Matches existing visual style (same inline styles / design tokens as rest of page — it uses CSS-in-JS inline styles with rgb(var(--color-*)) tokens)
|
||||
|
||||
## Key Constraints
|
||||
- The page uses inline styles throughout (rgb(var(--surface-*)), rgb(var(--text-*)), rgb(var(--border-*))) — match this pattern, no Tailwind classes
|
||||
- KanbanColumn component receives config and tasks — you'll need to wire the add button into it or add it at column-header level
|
||||
- createTask is exported from apps/web/src/lib/api/tasks.ts — import and use it
|
||||
- Use useWorkspaceId() hook (already imported) for workspace context
|
||||
- Keep it minimal — a simple inline card input (like Trello's "+Add a card" at bottom of column) is perfect
|
||||
|
||||
## Process
|
||||
1. git checkout main && git pull --ff-only origin main
|
||||
2. git checkout -b feat/kanban-add-task
|
||||
3. Implement the feature
|
||||
4. Run: pnpm turbo lint typecheck --filter=@mosaic/web
|
||||
5. Commit --no-verify: "feat(web): add task creation to Kanban board"
|
||||
6. Push and PR: ~/.config/mosaic/tools/git/pr-create.sh -t "feat(web): add task creation to Kanban board" -b "Adds inline Add Task button to each Kanban column. Clicking opens a quick-add form at the bottom of the column. Uses createTask API to persist, then refreshes tasks."
|
||||
|
||||
When done:
|
||||
openclaw system event --text "Done: kanban add-task PR ready" --mode now
|
||||
57
workers/ms22-audit-prompt.txt
Normal file
57
workers/ms22-audit-prompt.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
You are performing a mandatory code review and security audit of MS22 Phase 1 modules in ~/src/mosaic-stack.
|
||||
|
||||
## Objective
|
||||
Audit all MS22 modules for correctness, missing dependencies, and security issues. Produce a written report regardless of findings. If nothing needs fixing, that is itself a valid result — document it.
|
||||
|
||||
## MS22 Modules to Audit
|
||||
- apps/api/src/container-lifecycle/
|
||||
- apps/api/src/crypto/
|
||||
- apps/api/src/agent-config/
|
||||
- apps/api/src/onboarding/
|
||||
- apps/api/src/fleet-settings/
|
||||
- apps/api/src/chat-proxy/
|
||||
|
||||
## What to Check
|
||||
|
||||
### 1. NestJS Module Dependency Audit
|
||||
For each *.module.ts file:
|
||||
- Does it import every module whose services/guards are used in its controllers/services?
|
||||
- Are all providers listed that are used?
|
||||
- Are exports correct?
|
||||
|
||||
### 2. Security Review
|
||||
- fleet-settings: are admin-only routes properly guarded? Can a non-admin access provider secrets?
|
||||
- agent-config: is the bearer token guard timing-safe? Is the internal route isolated?
|
||||
- onboarding: can onboarding be re-run after completion?
|
||||
- crypto: is AES-256-GCM implemented correctly? IV uniqueness, auth tag verification?
|
||||
- chat-proxy: can a user proxy to another user's container?
|
||||
|
||||
### 3. Input Validation
|
||||
- Are DTOs using class-validator decorators?
|
||||
- Any unvalidated inputs?
|
||||
|
||||
### 4. Error Handling
|
||||
- Are errors leaking sensitive data?
|
||||
- Are Prisma errors caught before reaching HTTP layer?
|
||||
|
||||
## Process — MANDATORY, follow exactly
|
||||
|
||||
1. git checkout main && git pull --ff-only origin main
|
||||
2. Read each module file carefully
|
||||
3. Create branch: fix/ms22-audit
|
||||
4. Write a report file at docs/audits/ms22-phase1-audit.md documenting:
|
||||
- Each module reviewed
|
||||
- Findings (or "no issues found") per module
|
||||
- Security assessment
|
||||
- Changes made (if any)
|
||||
5. If you found issues: fix them, include fixes in the same commit
|
||||
6. If no issues found: still commit the report file
|
||||
7. Run quality gates: pnpm turbo lint typecheck --filter=@mosaic/api
|
||||
8. Commit: "fix(api): MS22 Phase 1 audit report and fixes"
|
||||
9. Push: git push origin fix/ms22-audit
|
||||
10. Create PR: ~/.config/mosaic/tools/git/pr-create.sh -t "fix(api): MS22 Phase 1 post-coding audit" -b "Mandatory post-coding audit of all MS22 Phase 1 modules. Report at docs/audits/ms22-phase1-audit.md."
|
||||
|
||||
DO NOT exit without pushing and creating a PR. The audit report is required even if all modules are clean.
|
||||
|
||||
When completely finished:
|
||||
openclaw system event --text "Done: MS22 audit PR ready — check docs/audits/ms22-phase1-audit.md" --mode now
|
||||
42
workers/project-detail-page-prompt.txt
Normal file
42
workers/project-detail-page-prompt.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
Create the missing project detail page in ~/src/mosaic-stack.
|
||||
|
||||
## Problem
|
||||
Clicking a project card on /projects navigates to /projects/[id] but that route doesn't exist → 404.
|
||||
|
||||
## What to Build
|
||||
Create: apps/web/src/app/(authenticated)/projects/[id]/page.tsx
|
||||
|
||||
The API endpoint GET /api/projects/:id returns a project with this shape:
|
||||
{
|
||||
id, name, description, status, priority, startDate, dueDate, createdAt, updatedAt,
|
||||
creator: { id, name, email },
|
||||
tasks: [{ id, title, status, priority, dueDate }],
|
||||
events: [{ id, title, startTime, endTime }],
|
||||
_count: { tasks, events }
|
||||
}
|
||||
|
||||
## Page Requirements
|
||||
1. Fetch the project using the existing API client pattern (look at how projects/page.tsx calls the API — follow same auth/workspace patterns)
|
||||
2. Display: project name, description, status badge, priority badge, dates, creator
|
||||
3. Display tasks list: title, status, priority, dueDate — empty state if none
|
||||
4. Display events list: title, startTime, endTime — empty state if none
|
||||
5. Back button → /projects
|
||||
6. Loading state and error state (show friendly message if project not found or fetch fails)
|
||||
7. Match the visual style of the existing projects/page.tsx (same component library, shadcn/ui, same spacing/layout conventions)
|
||||
|
||||
## API Client
|
||||
Look at apps/web/src/lib/api/ for existing project fetch functions. If no getProject(id) function exists, add it following the same pattern as other functions in that file.
|
||||
|
||||
## Process
|
||||
1. git checkout main && git pull --ff-only origin main
|
||||
2. Branch: feat/project-detail-page
|
||||
3. Check apps/web/src/lib/api/ for existing project API functions
|
||||
4. Create the page and any needed API client functions
|
||||
5. Run: pnpm turbo lint typecheck --filter=@mosaic/web
|
||||
6. Run: pnpm --filter @mosaic/web test -- --run
|
||||
7. Review: confirm page handles loading/error/not-found states, confirm no TypeScript errors
|
||||
8. Commit --no-verify: "feat(web): add project detail page (/projects/[id])"
|
||||
9. Push and PR: ~/.config/mosaic/tools/git/pr-create.sh -t "feat(web): add project detail page" -b "Clicking a project card navigated to /projects/[id] which returned 404. This adds the missing detail page showing project info, tasks, and events."
|
||||
|
||||
When completely finished:
|
||||
openclaw system event --text "Done: project detail page PR ready" --mode now
|
||||
31
workers/throttler-widgets-fix-prompt.txt
Normal file
31
workers/throttler-widgets-fix-prompt.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Fix two issues in ~/src/mosaic-stack related to dashboard widgets:
|
||||
|
||||
## Issue 1: Rate limiting on widget polling endpoints (429 errors)
|
||||
The widget data endpoint POST /api/widgets/data/* is being rate-limited because the dashboard polls it frequently from the same IP. Internal dashboard polling should not be throttled like external API traffic.
|
||||
|
||||
Fix: Add @SkipThrottler() decorator to the widgets data controller/endpoints.
|
||||
Find the controller: grep -r "widgets/data\|WidgetData\|widget.*controller" apps/api/src --include="*.ts" -l
|
||||
|
||||
## Issue 2: Missing /api/orchestrator/agents and /api/orchestrator/events endpoints
|
||||
The AgentStatusWidget in apps/web polls GET /api/orchestrator/agents and subscribes to GET /api/orchestrator/events (SSE). These endpoints do not exist, causing "Failed to fetch agents:" errors in the UI.
|
||||
|
||||
Implement a minimal orchestrator controller that:
|
||||
- GET /api/orchestrator/agents — returns list of active agent containers from the agents table (id, name, status, type, createdAt). Protected by AuthGuard.
|
||||
- GET /api/orchestrator/events — SSE endpoint that streams agent status change events. Can be a simple implementation that polls the agents table every 5 seconds and sends updates. Protected by AuthGuard.
|
||||
|
||||
Reference: apps/api/src/agent-config/ for the agents table schema and existing queries.
|
||||
Create: apps/api/src/orchestrator/orchestrator.controller.ts + orchestrator.module.ts
|
||||
Wire into AppModule.
|
||||
|
||||
## Process
|
||||
1. git checkout main && git pull --ff-only origin main
|
||||
2. Branch: fix/orchestrator-widgets
|
||||
3. Fix Issue 1 first (small change), then Issue 2
|
||||
4. Run: pnpm turbo lint typecheck --filter=@mosaic/api
|
||||
5. Run: pnpm --filter @mosaic/api test -- --run
|
||||
6. Review: confirm @SkipThrottler only on widget endpoints, confirm orchestrator endpoints are auth-guarded
|
||||
7. Commit: "fix(api): skip throttler for widget polling; add orchestrator agents/events endpoints"
|
||||
8. Push + PR: ~/.config/mosaic/tools/git/pr-create.sh -t "fix(api): widget throttling and orchestrator endpoints" -b "Adds @SkipThrottler to widget data endpoints (internal polling should not be rate-limited). Implements GET /api/orchestrator/agents and GET /api/orchestrator/events SSE endpoint for AgentStatusWidget."
|
||||
|
||||
When completely finished:
|
||||
openclaw system event --text "Done: orchestrator widgets fix PR ready" --mode now
|
||||
Reference in New Issue
Block a user