This commit is contained in:
608
docs/ux-refactor/_inventory/backend-routes.md
Normal file
608
docs/ux-refactor/_inventory/backend-routes.md
Normal file
@@ -0,0 +1,608 @@
|
||||
# Backend Route Inventory — Waggle OS UX Refactor
|
||||
|
||||
> **Purpose.** Source-grounded inventory of every existing **local Fastify sidecar** endpoint, plus a
|
||||
> cross-reference of every **PRD §16 target endpoint** against the current backend. This is the contract
|
||||
> reference for the in-place incremental refactor (LOCKED execution model): we reuse the existing sidecar
|
||||
> surface and add/extend only the net-new endpoints the PRD names.
|
||||
>
|
||||
> **Method.** Primary source = the audited backend-map (`docs/backend-map/sections/03a–03g`, 65/65 local
|
||||
> routes documented, ~96% overall coverage per `docs/backend-map/AUDIT.md`). Spot-verified against
|
||||
> `packages/server/src/local/routes/*.ts` for every PRD-critical path (grep/read).
|
||||
>
|
||||
> **Scope note.** Everything below is the **Local Sidecar** (`packages/server/src/local/index.ts` →
|
||||
> `buildLocalServer()`, default loopback `:3333`, flat `/api/*`, Bearer session-token + same-origin
|
||||
> guards). The desktop frontend talks ONLY to this server. A separate **Cloud server**
|
||||
> (`packages/server/src/routes/*.ts`, Clerk-JWT, `:3100`) exists for SaaS/team deployments — its
|
||||
> `/api/agents`, `/api/jobs`, `/api/scout`, `/api/suggestions` routes are **NOT** in the sidecar and are
|
||||
> flagged explicitly where they collide with PRD paths. **KVARK** has no Fastify routes (in-process
|
||||
> `KvarkClient` only).
|
||||
|
||||
---
|
||||
|
||||
## Part 1 — Existing Local Sidecar Endpoints (by domain)
|
||||
|
||||
All paths are relative to the sidecar base (`http://127.0.0.1:3333`). Source files are under
|
||||
`packages/server/src/local/routes/`. SSE/streaming and non-JSON responses are noted.
|
||||
|
||||
### 1.1 Chat / Agent execution / Sessions (`03a`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| POST | `/api/chat` | `chat.ts` | The chat turn — **SSE** stream (token/step/tool/approval_required/done/error). Largest route (~1.7k LOC). |
|
||||
| DELETE | `/api/chat/history` | `chat.ts` | Clear a session's in-RAM state (`?session=`). Does NOT delete on-disk `.jsonl`. |
|
||||
| GET | `/api/history` | `agent.ts` | Load a session's messages (RAM-first then disk). |
|
||||
| GET | `/api/agent/status` | `agent.ts` | Agent + cost snapshot. |
|
||||
| GET | `/api/agent/cost` | `agent.ts` | Detailed cost breakdown (string summary). |
|
||||
| POST | `/api/agent/cost/reset` | `agent.ts` | No-op cost reset stub. |
|
||||
| GET | `/api/agent/model` | `agent.ts` | Current model. |
|
||||
| PUT | `/api/agent/model` | `agent.ts` | Switch model (`{ model }`). |
|
||||
| GET | `/api/agents/active` | `agent.ts` | Sub-agent orchestrator state (`{ workers, active }`). |
|
||||
| POST | `/api/commands/execute` | `commands.ts` | Run a slash command out-of-band (subset of CommandContext). |
|
||||
| POST | `/api/agent/run` | `agent-run.ts` | One-shot structured retrieval — **SSE** (distinct events from `/api/chat`). |
|
||||
| GET | `/api/workspaces/:workspaceId/sessions` | `sessions.ts` | List sessions (`?hideEmpty=`). |
|
||||
| GET | `/api/workspaces/:workspaceId/sessions/search` | `sessions.ts` | Full-text session search (`?q=&limit=`). |
|
||||
| GET | `/api/workspaces/:workspaceId/sessions/:sessionId/export` | `sessions.ts` | Export one session as Markdown. |
|
||||
| GET | `/api/workspaces/:workspaceId/sessions/:sessionId/timeline` | `sessions.ts` | Tool-event timeline. |
|
||||
| POST | `/api/workspaces/:workspaceId/sessions` | `sessions.ts` | Create a session. |
|
||||
| PATCH | `/api/sessions/:sessionId` | `sessions.ts` | Rename a session. |
|
||||
| DELETE | `/api/sessions/:sessionId` | `sessions.ts` | Delete a session's `.jsonl`. |
|
||||
| GET | `/api/sessions/:sessionId/summary` | `sessions.ts` | Structured post-session summary. |
|
||||
| GET | `/api/agent-groups` | `agent-groups.ts` | List multi-agent group configs. |
|
||||
| POST | `/api/agent-groups` | `agent-groups.ts` | Create a group. |
|
||||
| PATCH | `/api/agent-groups/:id` | `agent-groups.ts` | Update a group. |
|
||||
| DELETE | `/api/agent-groups/:id` | `agent-groups.ts` | Delete a group. |
|
||||
| POST | `/api/agent-groups/:id/run` | `agent-groups.ts` | **Placeholder** — returns a queued stub, does NOT execute. |
|
||||
|
||||
### 1.2 Approvals (`03a` / `03e`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| POST | `/api/approval/:requestId` | `approval.ts` | Approve/deny a paused tool (`{ approved, always? }`). |
|
||||
| GET | `/api/approval/pending` | `approval.ts` | List paused approvals (reconnect/recovery). |
|
||||
| GET | `/api/approval/grants` | `approval.ts` | List persistent "always allow" grants. |
|
||||
| DELETE | `/api/approval/grants/:id` | `approval.ts` | Revoke one grant. |
|
||||
| POST | `/api/approval/grants/clear` | `approval.ts` | Wipe all grants. |
|
||||
|
||||
### 1.3 Memory / Knowledge graph (`03b`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/memory/search` | `memory.ts` | Full-text frame search across personal + workspace minds. |
|
||||
| GET | `/api/memory/frames` | `memory.ts` | List recent frames (Memory tab initial load). |
|
||||
| POST | `/api/memory/frames` | `memory.ts` | Save a frame (optional entity extraction). |
|
||||
| PUT | `/api/memory/frames/:id` | `memory.ts` | Edit a frame's content/importance. |
|
||||
| PATCH | `/api/memory/frames/:id/access` | `memory.ts` | Increment `access_count`. |
|
||||
| DELETE | `/api/memory/frames/:id` | `memory.ts` | Delete a frame. |
|
||||
| GET | `/api/memory/stats` | `memory.ts` | Frame/entity/relation counts. |
|
||||
| GET | `/api/memory/graph` | `knowledge.ts` | Read entities + relations (`?scope=all\|personal\|current`). No write/CRUD route. |
|
||||
|
||||
### 1.4 Wiki compiler (`03b`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/wiki/pages` | `wiki.ts` | List compiled page metadata. |
|
||||
| GET | `/api/wiki/pages/:slug` | `wiki.ts` | One page's metadata. |
|
||||
| GET | `/api/wiki/pages/:slug/content` | `wiki.ts` | Full markdown content of a page. |
|
||||
| POST | `/api/wiki/compile` | `wiki.ts` | Trigger compilation (503 if no real embedder). |
|
||||
| GET | `/api/wiki/health` | `wiki.ts` | Compilation health report (503 if no real embedder). |
|
||||
| GET | `/api/wiki/watermark` | `wiki.ts` | Current compilation watermark/state. |
|
||||
| POST | `/api/wiki/export/obsidian` | `wiki.ts` | Write all pages to an Obsidian-vault dir. |
|
||||
| POST | `/api/wiki/export/notion` | `wiki.ts` | Push pages to Notion (needs `notion-wiki-token` vault secret). |
|
||||
|
||||
### 1.5 Harvest (external AI export ingestion) (`03b`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| POST | `/api/harvest/preview` | `harvest.ts` | Parse an export, show what would import (no save). |
|
||||
| POST | `/api/harvest/commit` | `harvest.ts` | Full pipeline: save → cognify → wiki recompile. |
|
||||
| GET | `/api/harvest/sources` | `harvest.ts` | List registered harvest sources. |
|
||||
| POST | `/api/harvest/sources` | `harvest.ts` | Register/update a source. |
|
||||
| DELETE | `/api/harvest/sources/:source` | `harvest.ts` | Remove a source. |
|
||||
| PATCH | `/api/harvest/sources/:source` | `harvest.ts` | Toggle auto-sync/interval. |
|
||||
| GET | `/api/harvest/progress` | `harvest.ts` | **SSE** import progress stream. |
|
||||
| GET | `/api/harvest/runs` | `harvest.ts` | List recent harvest runs. |
|
||||
| GET | `/api/harvest/runs/latest-interrupted` | `harvest.ts` | Latest resumable run. |
|
||||
| POST | `/api/harvest/runs/:id/abandon` | `harvest.ts` | Discard an interrupted run. |
|
||||
| POST | `/api/harvest/extract-identity` | `harvest.ts` | LLM-extract identity facts from recent frames. |
|
||||
| POST | `/api/harvest/scan-claude-code` | `harvest.ts` | Scan local `~/.claude` for Claude Code history. |
|
||||
|
||||
### 1.6 Legacy import / File ingestion / Identity / Documents / Erasure (`03b`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| POST | `/api/import/preview` | `import.ts` | Legacy ChatGPT/Claude export preview. |
|
||||
| POST | `/api/import/commit` | `import.ts` | Legacy import + save to personal memory. |
|
||||
| POST | `/api/ingest` | `ingest.ts` | Base64 file ingestion (images/pdf/docx/pptx/xlsx/csv/code/zip) → LLM text + frames. |
|
||||
| GET | `/api/identity` | `identity.ts` | Read the structured identity record (upsert table). |
|
||||
| POST | `/api/identity` | `identity.ts` | Create/update identity record. |
|
||||
| GET | `/api/mind/identity` | `mind.ts` | Rendered identity **context string**. |
|
||||
| GET | `/api/mind/awareness` | `mind.ts` | Awareness state context. |
|
||||
| GET | `/api/mind/skills` | `mind.ts` | Loaded skills list. |
|
||||
| GET | `/api/workspaces/:id/documents` | `documents.ts` | List tracked document versions. |
|
||||
| POST | `/api/workspaces/:id/documents` | `documents.ts` | Register a new document version. |
|
||||
| GET | `/api/workspaces/:id/documents/:name/versions` | `documents.ts` | List versions of one document. |
|
||||
| POST | `/api/data/erase` | `data-erase.ts` | GDPR erasure (double-confirm; wipes at next startup). |
|
||||
| POST | `/api/export` | `export.ts` | Generate + download a ZIP of all user data. |
|
||||
|
||||
### 1.7 Workspaces / Templates / Storage / Files / Tasks / Pins (`03c` + `04`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/workspaces` | `workspaces.ts` | List workspaces (`?group=&teamId=`). |
|
||||
| POST | `/api/workspaces` | `workspaces.ts` | Create a workspace (tier `workspaceLimit`). |
|
||||
| GET | `/api/workspaces/:id` | `workspaces.ts` | Get one workspace. |
|
||||
| GET | `/api/workspaces/:id/context` | `workspaces.ts` | "Workspace Now" catch-up block (summary/threads/prompts/state). |
|
||||
| GET | `/api/workspaces/:id/files` | `workspaces.ts` | List ingested/registered files (file registry, newest first). |
|
||||
| PUT | `/api/workspaces/:id` | `workspaces.ts` | Update workspace (full). |
|
||||
| PATCH | `/api/workspaces/:id` | `workspaces.ts` | Partial update (`personaId:null` clears). |
|
||||
| DELETE | `/api/workspaces/:id` | `workspaces.ts` | Delete workspace + mind DB. |
|
||||
| GET | `/api/workspaces/:id/export` | `workspaces.ts` | Export workspace (`?format=briefing`→md, else JSON). |
|
||||
| GET | `/api/workspaces/:id/cost` | `workspaces.ts` | Per-workspace spend vs budget + 7-day history. |
|
||||
| GET | `/api/workspaces/:id/storage` | `workspaces.ts` | Virtual/linked storage stats. |
|
||||
| GET | `/api/workspaces/:id/storage/files` | `workspaces.ts` | List files in workspace storage. |
|
||||
| GET | `/api/workspaces/:id/storage/read` | `workspaces.ts` | Read a file (`?path=`, `?raw=`). |
|
||||
| POST | `/api/workspaces/:id/storage/write` | `workspaces.ts` | Write a file. |
|
||||
| DELETE | `/api/workspaces/:id/storage/delete` | `workspaces.ts` | Delete a file. |
|
||||
| GET | `/api/workspace-templates` | `workspace-templates.ts` | List 15 built-in + user templates. |
|
||||
| POST | `/api/workspace-templates` | `workspace-templates.ts` | Create a custom template. |
|
||||
| PUT | `/api/workspace-templates/:id` | `workspace-templates.ts` | Update a custom template (403 if built-in). |
|
||||
| DELETE | `/api/workspace-templates/:id` | `workspace-templates.ts` | Delete a custom template (403 if built-in). |
|
||||
| POST | `/api/workspace-templates/generate` | `workspace-templates.ts` | AI-generate a template config. |
|
||||
| GET | `/api/workspaces/:workspaceId/files/list` | `files.ts` | List managed files in a workspace storage dir (`?path=`). |
|
||||
| POST | `/api/workspaces/:workspaceId/files/upload` | `files.ts` | Upload a file into workspace storage. |
|
||||
| GET | `/api/workspaces/:workspaceId/files/download` | `files.ts` | Download a file (`?path=`). |
|
||||
| POST | `/api/workspaces/:workspaceId/files/mkdir` | `files.ts` | Create a directory. |
|
||||
| POST | `/api/workspaces/:workspaceId/files/delete` | `files.ts` | Delete a file/dir. |
|
||||
| POST | `/api/workspaces/:workspaceId/files/move` | `files.ts` | Move a file. |
|
||||
| POST | `/api/workspaces/:workspaceId/files/copy` | `files.ts` | Copy a file. |
|
||||
| GET | `/api/tasks` | `tasks.ts` | List tasks across workspaces. |
|
||||
| GET | `/api/workspaces/:id/tasks` | `tasks.ts` | List tasks for a workspace. |
|
||||
| POST | `/api/workspaces/:id/tasks` | `tasks.ts` | Create a task. |
|
||||
| PATCH | `/api/workspaces/:id/tasks/:taskId` | `tasks.ts` | Update a task. |
|
||||
| DELETE | `/api/workspaces/:id/tasks/:taskId` | `tasks.ts` | Delete a task. |
|
||||
| GET | `/api/workspaces/:id/pins` | `pins.ts` | List pinned messages. |
|
||||
| POST | `/api/workspaces/:id/pins` | `pins.ts` | Add a pin. |
|
||||
| PATCH | `/api/workspaces/:id/pins/:pinId` | `pins.ts` | Update pin status/label. |
|
||||
| DELETE | `/api/workspaces/:id/pins/:pinId` | `pins.ts` | Remove a pin. |
|
||||
|
||||
### 1.8 Team / RBAC (`03c`)
|
||||
|
||||
> Two prefixes: `/api/team/*` = remote-server proxy (local fallbacks when disconnected); `/api/teams/*` = local CRUD (always works, `teams.db`).
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| POST | `/api/team/connect` | `team.ts` | Connect to remote team server. **Tier: TEAMS.** |
|
||||
| POST | `/api/team/disconnect` | `team.ts` | Clear team-server config. |
|
||||
| GET | `/api/team/status` | `team.ts` | Connection status. |
|
||||
| GET | `/api/team/teams` | `team.ts` | List teams from remote server. |
|
||||
| GET | `/api/team/members` | `team.ts` | List members (remote or local fallback). |
|
||||
| GET | `/api/team/presence` | `team.ts` | Presence (`?workspaceId=`). |
|
||||
| GET | `/api/team/activity` | `team.ts` | Recent activity from remote. |
|
||||
| GET | `/api/team/messages` | `team.ts` | Recent WaggleDance messages. |
|
||||
| GET | `/api/team/governance/permissions` | `team.ts` | Effective capability permissions. **Tier: ENTERPRISE.** |
|
||||
| GET | `/api/team/memory/search` | `team.ts` | Search team memory frames. |
|
||||
| POST | `/api/teams` | `team.ts` | Create a local team. |
|
||||
| GET | `/api/teams` | `team.ts` | List teams the local user belongs to. |
|
||||
| GET | `/api/teams/:id` | `team.ts` | Team detail + members + workspaces. |
|
||||
| PUT | `/api/teams/:id` | `team.ts` | Update team (owner/admin). |
|
||||
| DELETE | `/api/teams/:id` | `team.ts` | Delete team (owner only). |
|
||||
| POST | `/api/teams/:id/members` | `team.ts` | Add/invite member (owner/admin). |
|
||||
| PUT | `/api/teams/:id/members/:userId` | `team.ts` | Change member role (owner only). |
|
||||
| PATCH | `/api/teams/:id/members/:userId` | `team.ts` | Change member role (owner/admin). |
|
||||
| DELETE | `/api/teams/:id/members/:userId` | `team.ts` | Remove member. |
|
||||
| GET | `/api/teams/:id/activity` | `team.ts` | Aggregated audit events across team workspaces. |
|
||||
|
||||
### 1.9 Personas / Settings / Tier / Profile (`03c`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/personas` | `personas.ts` | List persona catalog. |
|
||||
| POST | `/api/personas` | `personas.ts` | Create custom persona. **Tier: PRO.** |
|
||||
| PATCH | `/api/personas/:id` | `personas.ts` | Update custom persona. |
|
||||
| POST | `/api/personas/generate` | `personas.ts` | AI-generate a persona. **Tier: PRO.** |
|
||||
| DELETE | `/api/personas/:id` | `personas.ts` | Delete custom persona. |
|
||||
| GET | `/api/settings` | `settings.ts` | Read config (keys masked). |
|
||||
| PUT | `/api/settings` | `settings.ts` | Update models/budgets/providers. |
|
||||
| PATCH | `/api/settings` | `settings.ts` | Partial merge (non-provider). |
|
||||
| POST | `/api/settings/test-key` | `settings.ts` | Validate API-key format (no network). |
|
||||
| POST | `/api/settings/probe-provider` | `settings.ts` | Live-probe a STORED provider key by id (F3). |
|
||||
| GET | `/api/settings/permissions` | `settings.ts` | Read autonomy/gates/overrides. |
|
||||
| PUT | `/api/settings/permissions` | `settings.ts` | Save permission settings. |
|
||||
| GET | `/api/tier` | `settings.ts` | **Authoritative tier source** (effective tier, trial, capabilities). |
|
||||
| PATCH | `/api/tier` | `settings.ts` | Dev tier override (fail-closed). |
|
||||
| POST | `/api/tier/start-trial` | `settings.ts` | Start the 15-day TRIAL. |
|
||||
| GET | `/api/cloud-sync` | `settings.ts` | Cloud-sync status. |
|
||||
| POST | `/api/cloud-sync/toggle` | `settings.ts` | Toggle cloud sync. **Tier: TEAMS.** |
|
||||
| GET | `/api/admin/overview` | `settings.ts` | Admin dashboard data. **Tier: TEAMS.** |
|
||||
| GET | `/api/admin/audit-export` | `settings.ts` | Export audit log. **Tier: TEAMS.** |
|
||||
| GET | `/api/profile` | `profile.ts` | Full user profile. |
|
||||
| PUT | `/api/profile` | `profile.ts` | Partial-merge profile update. |
|
||||
| POST | `/api/profile/analyze-style` | `profile.ts` | LLM-analyze writing sample. |
|
||||
| POST | `/api/profile/analyze-brand` | `profile.ts` | LLM-extract brand colors/fonts. |
|
||||
| GET | `/api/profile/style` | `profile.ts` | Writing-style summary. |
|
||||
| GET | `/api/profile/brand` | `profile.ts` | Brand profile. |
|
||||
| POST | `/api/profile/research` | `profile.ts` | LLM-research user/company → bio. |
|
||||
|
||||
### 1.10 Marketplace / Skills / Plugins / Connectors / Tools (`03d`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/marketplace/search` | `marketplace.ts` | FTS5 + faceted catalog search. |
|
||||
| GET | `/api/marketplace/packs` | `marketplace.ts` | List capability packs. |
|
||||
| GET | `/api/marketplace/packs/:slug` | `marketplace.ts` | Pack detail + packages. |
|
||||
| GET | `/api/marketplace/enterprise-packs` | `marketplace.ts` | KVARK-gated packs. **Tier: ENTERPRISE.** |
|
||||
| POST | `/api/marketplace/install` | `marketplace.ts` | Install a package (SecurityGate). **Tier: PRO.** |
|
||||
| POST | `/api/marketplace/uninstall` | `marketplace.ts` | Uninstall a package. |
|
||||
| GET | `/api/marketplace/installed` | `marketplace.ts` | List installed packages. |
|
||||
| POST | `/api/marketplace/security-check` | `marketplace.ts` | Scan a package without installing. |
|
||||
| GET | `/api/marketplace/sources` | `marketplace.ts` | List marketplace sources. |
|
||||
| POST | `/api/marketplace/sources` | `marketplace.ts` | Add a user source + sync. |
|
||||
| DELETE | `/api/marketplace/sources/:id` | `marketplace.ts` | Remove a user source. |
|
||||
| GET | `/api/marketplace/categories` | `marketplace.ts` | Category taxonomy. |
|
||||
| POST | `/api/marketplace/sync` | `marketplace.ts` | Manual catalog sync. |
|
||||
| GET | `/api/marketplace/security-status` | `marketplace.ts` | Scanner availability + scan counts. |
|
||||
| POST | `/api/marketplace/publish` | `marketplace.ts` | Publish a local skill to the catalog. **Tier: PRO.** |
|
||||
| GET | `/api/skills/starter-pack/catalog` | `skills.ts` | Browse starter skills with state. |
|
||||
| POST | `/api/skills/starter-pack` | `skills.ts` | Install all starter skills. |
|
||||
| POST | `/api/skills/starter-pack/:id` | `skills.ts` | Install ONE starter skill. |
|
||||
| GET | `/api/skills/capability-packs/catalog` | `skills.ts` | List capability packs with states. |
|
||||
| POST | `/api/skills/capability-packs/:id` | `skills.ts` | Install all skills in a pack. |
|
||||
| GET | `/api/skills` | `skills.ts` | List installed skills. |
|
||||
| GET | `/api/skills/suggestions` | `skills.ts` | Contextual skill recommendations. |
|
||||
| GET | `/api/skills/:name` | `skills.ts` | Full skill content. |
|
||||
| POST | `/api/skills` | `skills.ts` | Create skill from raw `{ name, content }`. |
|
||||
| POST | `/api/skills/create` | `skills.ts` | Create skill from structured template. |
|
||||
| PUT | `/api/skills/:name` | `skills.ts` | Update skill content. |
|
||||
| DELETE | `/api/skills/:name` | `skills.ts` | Delete skill. |
|
||||
| GET | `/api/skills/hash-status` | `skills.ts` | Which skills changed on disk. |
|
||||
| POST | `/api/skills/test` | `skills.ts` | Sandbox/dry-run a skill (prompt injection preview). |
|
||||
| GET | `/api/audit/installs` | `skills.ts` | Recent install audit trail. |
|
||||
| GET | `/api/plugins` | `skills.ts` | List installed plugins. |
|
||||
| POST | `/api/plugins/install` | `skills.ts` | Install a plugin from a local dir. |
|
||||
| DELETE | `/api/plugins/:name` | `skills.ts` | Uninstall a plugin. |
|
||||
| GET | `/api/plugins/:name/tools` | `skills.ts` | List a plugin's tools + impl status. |
|
||||
| GET | `/api/plugins/:name/tools/:toolName` | `skills.ts` | Get one tool's impl file. |
|
||||
| PUT | `/api/plugins/:name/tools/:toolName` | `skills.ts` | Write a tool impl file. |
|
||||
| DELETE | `/api/plugins/:name/tools/:toolName` | `skills.ts` | Delete a tool impl file. |
|
||||
| POST | `/api/plugins/:name/tools` | `skills.ts` | Declare a new tool in the manifest. |
|
||||
| GET | `/api/hooks` | `skills.ts` | List `pre:tool` deny rules. |
|
||||
| POST | `/api/hooks` | `skills.ts` | Add a deny rule. |
|
||||
| DELETE | `/api/hooks/:index` | `skills.ts` | Remove a rule by index. |
|
||||
| GET | `/api/connectors` | `connectors.ts` | List all connector definitions. |
|
||||
| GET | `/api/connectors/:id/health` | `connectors.ts` | Live health probe. |
|
||||
| POST | `/api/connectors/:id/connect` | `connectors.ts` | Store credentials + re-init connector. |
|
||||
| POST | `/api/connectors/:id/disconnect` | `connectors.ts` | Remove credential + sub-keys. |
|
||||
| GET | `/api/tools/detect` | `tools.ts` | Scan machine for supported AI tools (AI-OS). |
|
||||
| POST | `/api/tools/launch` | `tools.ts` | Spawn a tool with workspace env. |
|
||||
| GET | `/api/tools/processes` | `tools.ts` | List tracked running processes. |
|
||||
| POST | `/api/tools/kill` | `tools.ts` | Kill a tracked PID. |
|
||||
| POST | `/api/tools/hooks` | `tools.ts` | Run hive-mind hook install/verify/uninstall. |
|
||||
| GET | `/api/oauth/providers` | `oauth.ts` | List OAuth providers + token status. |
|
||||
| GET | `/api/oauth/:provider/authorize` | `oauth.ts` | Build + redirect to provider OAuth URL. |
|
||||
| GET | `/api/oauth/:provider/callback` | `oauth.ts` | Exchange code → token (HTML response). |
|
||||
| GET | `/api/vault` | `vault.ts` | List secrets (no values) + suggestions. |
|
||||
| POST | `/api/vault` | `vault.ts` | Add/update a secret. |
|
||||
| DELETE | `/api/vault/:name` | `vault.ts` | Delete a secret. |
|
||||
| POST | `/api/vault/:name/reveal` | `vault.ts` | Decrypt + return value (local-origin only). |
|
||||
| GET | `/api/providers` | `providers.ts` | LLM + search providers, models, key status. |
|
||||
|
||||
> **Dev-only (not a production contract):** `marketplace-dev.ts` registers `/_dev/marketplace/{search,security-check,packs,health}` behind env `WAGGLE_DEV_MARKETPLACE=1`. Excluded from PRD cross-reference.
|
||||
|
||||
### 1.11 Evolution / Feedback / Telemetry / Compliance / Cost / Capabilities (`03e`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/evolution/runs` | `evolution.ts` | List evolution runs. |
|
||||
| GET | `/api/evolution/runs/:uuid` | `evolution.ts` | Single run detail. |
|
||||
| POST | `/api/evolution/runs/:uuid/accept` | `evolution.ts` | Accept + deploy a run. |
|
||||
| POST | `/api/evolution/runs/:uuid/reject` | `evolution.ts` | Reject a run. |
|
||||
| GET | `/api/evolution/targets` | `evolution.ts` | Enumerate evolvable targets. |
|
||||
| GET | `/api/evolution/baseline` | `evolution.ts` | Current baseline text for a target. |
|
||||
| POST | `/api/evolution/run` | `evolution.ts` | Trigger a real run (JSON or **SSE**). |
|
||||
| GET | `/api/evolution/status` | `evolution.ts` | Aggregate status counts. |
|
||||
| POST | `/api/feedback` | `feedback.ts` | Record thumbs up/down on a message. |
|
||||
| GET | `/api/feedback/stats` | `feedback.ts` | Improvement stats + trend. |
|
||||
| GET | `/api/telemetry/summary` | `telemetry.ts` | Local telemetry summary. |
|
||||
| GET | `/api/telemetry/events` | `telemetry.ts` | Query telemetry events. |
|
||||
| DELETE | `/api/telemetry/events` | `telemetry.ts` | Clear all telemetry events. |
|
||||
| GET | `/api/telemetry/status` | `telemetry.ts` | Telemetry enabled flag + count. |
|
||||
| POST | `/api/telemetry/toggle` | `telemetry.ts` | Enable/disable telemetry. |
|
||||
| POST | `/api/telemetry/track` | `telemetry.ts` | Record a single event (frontend). |
|
||||
| GET | `/api/compliance/status` | `compliance.ts` | EU AI Act per-article status. |
|
||||
| POST | `/api/compliance/export` | `compliance.ts` | Generate audit report (JSON). |
|
||||
| POST | `/api/compliance/export-pdf` | `compliance.ts` | Generate audit report (PDF binary). |
|
||||
| GET | `/api/compliance/interactions` | `compliance.ts` | List recorded AI interactions. |
|
||||
| POST | `/api/compliance/interactions` | `compliance.ts` | Record an AI interaction. |
|
||||
| GET | `/api/compliance/models` | `compliance.ts` | Model inventory for a date range. |
|
||||
| GET | `/api/compliance/templates` | `compliance.ts` | List compliance report templates. |
|
||||
| GET | `/api/compliance/templates/:id` | `compliance.ts` | Get one template. |
|
||||
| POST | `/api/compliance/templates` | `compliance.ts` | Create a template. |
|
||||
| PATCH | `/api/compliance/templates/:id` | `compliance.ts` | Update a template. |
|
||||
| DELETE | `/api/compliance/templates/:id` | `compliance.ts` | Delete a template. |
|
||||
| GET | `/api/cost/summary` | `cost.ts` | Cost dashboard (today/week/all-time + budget). |
|
||||
| GET | `/api/cost/by-workspace` | `cost.ts` | Per-workspace cost. **Tier: TEAMS.** |
|
||||
| GET | `/api/costs` | `cost.ts` | Alias → `/api/cost/summary`. |
|
||||
| GET | `/api/capabilities/status` | `capabilities.ts` | Plugins/MCP/skills/tools/commands/hooks/workflows status. |
|
||||
| POST | `/api/capabilities/plugins/:name/enable` | `capabilities.ts` | Enable a plugin. |
|
||||
| POST | `/api/capabilities/plugins/:name/disable` | `capabilities.ts` | Disable a plugin. |
|
||||
|
||||
### 1.12 Workflows (`03e`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/workflows` | `workflows.ts` | List built-in + custom workflow templates. |
|
||||
| POST | `/api/workflows` | `workflows.ts` | Create a custom workflow template. |
|
||||
| DELETE | `/api/workflows/:name` | `workflows.ts` | Delete a custom workflow template. |
|
||||
|
||||
### 1.13 Real-time / Ops (`03f`)
|
||||
|
||||
| Method | Path | Route file | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/waggle/signals` | `waggle-signals.ts` | List recent WaggleDance UI signals. |
|
||||
| POST | `/api/waggle/signals` | `waggle-signals.ts` | Publish a UI signal. |
|
||||
| PATCH | `/api/waggle/signals/:id/ack` | `waggle-signals.ts` | Acknowledge a signal. |
|
||||
| GET | `/api/waggle/stream` | `waggle-signals.ts` | **SSE** signal stream. |
|
||||
| POST | `/api/waggle-dance/signal` | `waggle-dance.ts` | v2 protocol bus: dispatch a signal. |
|
||||
| GET | `/api/waggle-dance/signals` | `waggle-dance.ts` | v2 ring-buffer snapshot. |
|
||||
| GET | `/api/events` | `events.ts` | Paginated audit-event listing. |
|
||||
| GET | `/api/events/stats` | `events.ts` | Audit aggregates. |
|
||||
| GET | `/api/events/stream` | `events.ts` | **SSE** live audit events. |
|
||||
| POST | `/api/cron` | `cron.ts` | Create a cron schedule. |
|
||||
| GET | `/api/cron` | `cron.ts` | List schedules. |
|
||||
| GET | `/api/cron/:id` | `cron.ts` | Get one schedule. |
|
||||
| PATCH | `/api/cron/:id` | `cron.ts` | Update a schedule. |
|
||||
| DELETE | `/api/cron/:id` | `cron.ts` | Delete a schedule. |
|
||||
| POST | `/api/cron/:id/trigger` | `cron.ts` | Manually run now (auto-enables). |
|
||||
| GET | `/api/cron/:id/history` | `notifications.ts` | Cron execution history. |
|
||||
| GET | `/api/notifications/stream` | `notifications.ts` | **SSE** notifications + subagent status. |
|
||||
| GET | `/api/notifications` | `notifications.ts` | List persisted notifications. |
|
||||
| POST | `/api/notifications/:id/read` | `notifications.ts` | Mark one read. |
|
||||
| GET | `/api/notifications/history` | `notifications.ts` | List (alias, limit 100). |
|
||||
| PATCH | `/api/notifications/:id/read` | `notifications.ts` | Mark one read (PATCH). |
|
||||
| POST | `/api/notifications/read-all` | `notifications.ts` | Mark all read. |
|
||||
| GET | `/api/offline/status` | `offline.ts` | Offline state. |
|
||||
| POST | `/api/offline/queue` | `offline.ts` | Queue a message. |
|
||||
| GET | `/api/offline/queue` | `offline.ts` | List queued messages. |
|
||||
| DELETE | `/api/offline/queue/:id` | `offline.ts` | Remove one queued message. |
|
||||
| DELETE | `/api/offline/queue` | `offline.ts` | Clear all queued messages. |
|
||||
| POST | `/api/backup` | `backup.ts` | Build + stream encrypted backup archive. |
|
||||
| POST | `/api/restore` | `backup.ts` | Restore from an archive (`preview?`). |
|
||||
| GET | `/api/backup/metadata` | `backup.ts` | Last backup info. |
|
||||
| GET | `/api/fleet` | `fleet.ts` | List active workspace sessions (Mission Control). |
|
||||
| POST | `/api/fleet/spawn` | `fleet.ts` | Spawn a new agent session. |
|
||||
| POST | `/api/fleet/:workspaceId/pause` | `fleet.ts` | Pause a session. |
|
||||
| POST | `/api/fleet/:workspaceId/resume` | `fleet.ts` | Resume a session. |
|
||||
| POST | `/api/fleet/:workspaceId/kill` | `fleet.ts` | Abort + close a session. |
|
||||
| GET | `/api/litellm/status` | `litellm.ts` | LiteLLM router status. |
|
||||
| POST | `/api/litellm/restart` | `litellm.ts` | Restart the router. |
|
||||
| GET | `/api/litellm/models` | `litellm.ts` | Available model IDs. |
|
||||
| GET | `/api/litellm/pricing` | `litellm.ts` | Static per-model pricing. |
|
||||
| GET | `/api/local-inference/hardware` | `local-inference.ts` | Detect GPU/RAM/CPU. |
|
||||
| GET | `/api/local-inference/models` | `local-inference.ts` | Recommend models that fit. |
|
||||
| GET | `/api/local-inference/status` | `local-inference.ts` | Ollama/vLLM availability. |
|
||||
| POST | `/api/local-inference/pull` | `local-inference.ts` | Pull a model via Ollama. |
|
||||
| GET | `/v1/health/liveliness` | `anthropic-proxy.ts` | Built-in proxy health. |
|
||||
| POST | `/v1/chat/completions` | `anthropic-proxy.ts` | OpenAI-compatible Anthropic proxy (**SSE** when `stream`). |
|
||||
| GET | `/api/browse/local` | `browse.ts` | List directories (local-only). |
|
||||
| POST | `/api/browse/local/mkdir` | `browse.ts` | Create a directory (local-only). |
|
||||
| GET | `/api/browser-ext/health` | `browser-ext.ts` | Browser-extension health check. |
|
||||
| GET | `/api/telegram/status` | `telegram.ts` | Telegram config status. |
|
||||
| POST | `/api/telegram/config` | `telegram.ts` | Save Telegram creds. |
|
||||
| POST | `/api/telegram/test` | `telegram.ts` | Send a test message. |
|
||||
| POST | `/api/telegram/send` | `telegram.ts` | Send arbitrary text. |
|
||||
| GET | `/api/weaver/status` | `weaver.ts` | Weaver subsystem status. |
|
||||
| POST | `/api/weaver/trigger` | `weaver.ts` | Trigger a Weaver run. |
|
||||
|
||||
### 1.14 Bootstrap / Stripe billing / WebSocket (`03g`)
|
||||
|
||||
| Method | Path | Source | Purpose |
|
||||
|---|---|---|---|
|
||||
| GET | `/health` | `local/index.ts` (inline) | Health probe (auth-exempt). |
|
||||
| GET | `/api/auth/session-token` | `local/index.ts` (inline) | Bootstrap session token (same-origin, auth-exempt). |
|
||||
| GET | `/api/debug/logs` | `local/index.ts` (inline) | Support bundle (same-origin). |
|
||||
| GET | `/api/docs` | `local/index.ts` (inline) | Auto-generated route/OpenAPI listing. |
|
||||
| GET | `/ws` | `local/index.ts` (inline) | WebSocket event-bus relay (`?token=`). |
|
||||
| GET | `/*` | `local/index.ts` (inline) | SPA fallback (serves `index.html`). |
|
||||
| POST | `/api/stripe/create-checkout-session` | `stripe/` (`stripeRoutes`) | Start Stripe checkout (PRO/TEAMS). |
|
||||
| POST | `/api/stripe/webhook` | `stripe/` | Stripe webhook (raw body, signature-verified). |
|
||||
| POST | `/api/stripe/sync` | `stripe/` | Poll-fallback payment confirmation. |
|
||||
| POST | `/api/stripe/create-portal-session` | `stripe/` | Stripe billing portal. **Tier: PRO.** |
|
||||
|
||||
---
|
||||
|
||||
## Part 2 — PRD §16 Target Endpoints → Cross-Reference
|
||||
|
||||
Status legend:
|
||||
- **EXISTS** — a sidecar route already serves this exact (or path-equivalent) contract.
|
||||
- **PARTIAL** — closest current capability exists but path/shape/semantics differ; the refactor extends/aliases rather than builds net-new.
|
||||
- **MISSING** — no sidecar route provides this; net-new backend work required.
|
||||
|
||||
> Verification: every MISSING row was grep-confirmed absent from `packages/server/src/local/routes/*.ts`
|
||||
> (`/api/share`, `/api/home`, `/api/quick-capture`, `/api/command`, `/api/artifacts`, `/api/automations`,
|
||||
> `/api/mcps`, `/api/agents/:id/{run,pause,traces}`, `/api/skills/:id/{install,test}`,
|
||||
> `/api/memory/merge`, `/api/memory/:id/archive`, `/api/connectors/:id/{sync,revoke}` — **0 matches**).
|
||||
|
||||
### 16.1 Home
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/home/briefing` | **MISSING** | No `/api/home/*` route. Data is assemblable from `GET /api/workspaces/:id/context` (greeting/summary/threads/pendingTasks/upcomingSchedules) + `GET /api/cost/summary`, but no Home aggregation endpoint exists. Net-new. |
|
||||
| `POST /api/quick-capture` | **PARTIAL** | No `/api/quick-capture`. Closest: `POST /api/memory/frames` (`memory.ts`) writes a frame directly. Quick-capture = thin wrapper (default personal mind + `source`); extend rather than build new substrate. |
|
||||
| `GET /api/home/overnight` | **MISSING** | No overnight-digest route. Inputs exist (`GET /api/events`, `GET /api/notifications`, `GET /api/cron/:id/history`) but no aggregation endpoint. Net-new. |
|
||||
|
||||
### 16.2 Workspaces
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/workspaces` | **EXISTS** | `workspaces.ts`. |
|
||||
| `POST /api/workspaces` | **EXISTS** | `workspaces.ts`. |
|
||||
| `GET /api/workspaces/:id` | **EXISTS** | `workspaces.ts`. |
|
||||
| `PATCH /api/workspaces/:id` | **EXISTS** | `workspaces.ts` (also `PUT`). |
|
||||
| `GET /api/workspaces/:id/state` | **PARTIAL** | No `/state` route. `GET /api/workspaces/:id/context` returns `workspaceState` as a sub-object. Either alias `/state` to that sub-object or add a thin route. |
|
||||
| `GET /api/workspaces/:id/context` | **EXISTS** | `workspaces.ts` — the "Workspace Now" catch-up block. |
|
||||
| `GET /api/workspaces/:id/activity` | **PARTIAL** | No per-workspace `/activity`. Closest: `GET /api/events?workspaceId=` (`events.ts`) and `GET /api/teams/:id/activity`. Add a thin `/activity` alias over the audit-event query. |
|
||||
|
||||
### 16.3 Command Center
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/command/search?q=` | **MISSING** | No `/api/command/*`. Note `commands.ts` is `/api/commands/execute` (slash-command exec, different shape). PRD's "command palette" search needs net-new (federate over workspaces/memory/skills/sessions). |
|
||||
| `POST /api/command/execute` | **PARTIAL** | `POST /api/commands/execute` exists (note **plural** `commands`) but only runs slash commands with a subset CommandContext; PRD's generic command-palette execute is broader. Reuse/rename + extend. |
|
||||
| `GET /api/command/recent` | **MISSING** | No recent-commands surface. Net-new (or derive client-side from session history). |
|
||||
| `GET /api/command/suggestions` | **MISSING** | No command-suggestions route. Closest analog is `GET /api/skills/suggestions` (different domain). Net-new. |
|
||||
|
||||
### 16.4 Memory
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/memory` | **PARTIAL** | List is `GET /api/memory/frames`; search is `GET /api/memory/search`. PRD's bare `/api/memory` maps to `/frames` (alias or accept both). |
|
||||
| `GET /api/memory/:id` | **MISSING** | No single-frame GET. Frames are addressable for PUT/PATCH/DELETE (`/api/memory/frames/:id`) but there is no `GET .../frames/:id`. Add a thin read route. |
|
||||
| `POST /api/memory` | **PARTIAL** | `POST /api/memory/frames` exists. PRD bare path = alias of `/frames`. |
|
||||
| `PATCH /api/memory/:id` | **PARTIAL** | `PUT /api/memory/frames/:id` edits content/importance (PRD uses `PATCH`; semantics match). Accept `PATCH` + bare path or alias. |
|
||||
| `POST /api/memory/:id/archive` | **MISSING** | No archive action. `importance: 'deprecated'` exists as a value but no archive endpoint; closest mutation is `PUT /api/memory/frames/:id`. Net-new (or model archive as an importance/status edit). |
|
||||
| `DELETE /api/memory/:id` | **PARTIAL** | `DELETE /api/memory/frames/:id` exists; PRD uses the bare `:id` path. Alias. |
|
||||
| `POST /api/memory/merge` | **MISSING** | No frame-merge route. Net-new (dedup/merge of duplicate frames). |
|
||||
| `GET /api/memory/graph` | **EXISTS** | `knowledge.ts`. |
|
||||
|
||||
### 16.5 Harvest
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `POST /api/harvest/preview` | **EXISTS** | `harvest.ts`. |
|
||||
| `POST /api/harvest/commit` | **EXISTS** | `harvest.ts`. |
|
||||
| `GET /api/harvest/sources` | **EXISTS** | `harvest.ts`. |
|
||||
| `POST /api/harvest/sources/:id/sync` | **PARTIAL** | No per-source `/sync` action. Sources are registered/toggled via `POST /api/harvest/sources`, `PATCH /api/harvest/sources/:source` (auto-sync config); the actual sync happens through `POST /api/harvest/commit`. Add a thin per-source `/sync` that resolves the source + calls commit. Note PRD uses `:id`; current sources are keyed by `:source` name. |
|
||||
|
||||
### 16.6 Artifacts
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/artifacts` | **PARTIAL** | No `/api/artifacts` domain. Closest substrates: workspace file registry `GET /api/workspaces/:id/files` (`workspaces.ts`), managed files `GET /api/workspaces/:workspaceId/files/list` (`files.ts`), and document versions `GET /api/workspaces/:id/documents` (`documents.ts`). PRD "artifacts" = a new unified abstraction over these; needs a net-new aggregation layer reusing the existing stores. |
|
||||
| `POST /api/artifacts` | **PARTIAL** | Closest writes: `POST /api/ingest`, `POST /api/workspaces/:workspaceId/files/upload`, `POST /api/workspaces/:id/documents`. New artifact-create endpoint needed. |
|
||||
| `GET /api/artifacts/:id` | **MISSING** | No artifact-by-id read. Net-new. |
|
||||
| `PATCH /api/artifacts/:id` | **MISSING** | No artifact update. Net-new. |
|
||||
| `DELETE /api/artifacts/:id` | **PARTIAL** | Closest: `POST /api/workspaces/:workspaceId/files/delete`, `DELETE /api/workspaces/:id/storage/delete`. New artifact-delete endpoint needed. |
|
||||
| `GET /api/artifacts/search-related?q=` | **MISSING** | No related-artifact search. Net-new (could lean on memory/wiki search internally). |
|
||||
|
||||
### 16.7 Agents
|
||||
|
||||
> **Naming collision:** PRD's `/api/agents/*` (CRUD + run/pause/traces) matches the **Cloud** server's
|
||||
> Clerk-gated `routes/agents.ts` (`/api/agents`, `/api/agents/:id`, etc.) — **NOT** the sidecar. The
|
||||
> sidecar's agent surface is `/api/agent/*` (singular: status/cost/model) + `/api/agents/active` +
|
||||
> `/api/agent-groups/*` + `/api/fleet/*`. So in the desktop (sidecar) context, the PRD §16.7 agent CRUD
|
||||
> is **MISSING** locally even though a Clerk-gated cloud analog exists.
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/agents` | **MISSING (sidecar)** | Sidecar has `GET /api/agents/active` (live orchestrator state) only. Persona catalog `GET /api/personas` + groups `GET /api/agent-groups` are the closest "agent definitions". Cloud `GET /api/agents` (Clerk) is a separate server. |
|
||||
| `POST /api/agents` | **MISSING (sidecar)** | No sidecar agent-create. Closest: `POST /api/personas` (custom persona) / `POST /api/agent-groups`. Cloud-only `POST /api/agents` exists (Clerk). |
|
||||
| `GET /api/agents/:id` | **MISSING** | No sidecar agent-by-id. Net-new (or map onto persona/group id). |
|
||||
| `PATCH /api/agents/:id` | **MISSING** | No sidecar route. Closest: `PATCH /api/personas/:id` / `PATCH /api/agent-groups/:id`. |
|
||||
| `POST /api/agents/:id/run` | **PARTIAL** | No per-agent `/run`. Closest run paths: `POST /api/fleet/spawn` (`{ task, persona?, model? }` — real execution), `POST /api/agent/run` (one-shot retrieval SSE), `POST /api/agent-groups/:id/run` (placeholder stub). Wire `/agents/:id/run` onto fleet-spawn. |
|
||||
| `POST /api/agents/:id/pause` | **PARTIAL** | No per-agent `/pause`. Closest: `POST /api/fleet/:workspaceId/pause`. Map agent→session and reuse. |
|
||||
| `GET /api/agents/:id/traces` | **PARTIAL** | No per-agent `/traces`. Closest: session timeline `GET /api/workspaces/:wid/sessions/:sid/timeline` and the execution-trace store (no dedicated HTTP listing). Add a `/traces` route reading the trace store. |
|
||||
|
||||
### 16.8 Skills
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/skills` | **EXISTS** | `skills.ts`. |
|
||||
| `POST /api/skills` | **EXISTS** | `skills.ts` (raw create; also `POST /api/skills/create` structured). |
|
||||
| `PATCH /api/skills/:id` | **PARTIAL** | Update is `PUT /api/skills/:name` (keyed by **name**, method `PUT`). PRD uses `PATCH` + `:id`. Accept `PATCH` / alias name↔id. |
|
||||
| `POST /api/skills/:id/test` | **PARTIAL** | Test exists but as `POST /api/skills/test` (body-driven, not per-id path). Add `:id` path variant or pass via body. |
|
||||
| `POST /api/skills/:id/install` | **PARTIAL** | No per-skill `/install` by arbitrary id. Closest installs: `POST /api/skills/starter-pack/:id`, `POST /api/skills/capability-packs/:id`, and marketplace `POST /api/marketplace/install`. Add a unified `/skills/:id/install` that dispatches by source. |
|
||||
|
||||
### 16.9 Connectors / MCPs / Marketplace
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/connectors` | **EXISTS** | `connectors.ts`. |
|
||||
| `POST /api/connectors/:id/connect` | **EXISTS** | `connectors.ts`. |
|
||||
| `POST /api/connectors/:id/sync` | **MISSING** | No connector `/sync` action. Net-new (re-fetch from connected service). |
|
||||
| `POST /api/connectors/:id/revoke` | **PARTIAL** | Closest: `POST /api/connectors/:id/disconnect` (removes vault creds + sub-keys). Same intent, different verb. Alias `/revoke` → disconnect or add. |
|
||||
| `GET /api/mcps` | **PARTIAL** | No `/api/mcps`. MCP servers surface inside `GET /api/capabilities/status` (`mcpServers[]`); MCP catalog lives in `@waggle/shared` `mcp-catalog.ts` (no dedicated HTTP route). Net-new dedicated MCP listing endpoint (or extract from capabilities/status + catalog). |
|
||||
| `POST /api/mcps/install` | **PARTIAL** | No `/api/mcps/install`. MCP servers are installed via the marketplace path (`POST /api/marketplace/install`) and plugin install (`POST /api/plugins/install`). Add an MCP-specific install or route through marketplace. |
|
||||
| `POST /api/mcps/:id/test` | **MISSING** | No MCP test/health route. Closest analog: `GET /api/connectors/:id/health`. Net-new for MCP. |
|
||||
| `POST /api/mcps/:id/revoke` | **MISSING** | No MCP revoke/uninstall by id. Closest: `DELETE /api/plugins/:name`. Net-new for MCP. |
|
||||
| `GET /api/marketplace` | **PARTIAL** | Marketplace listing is `GET /api/marketplace/search` (+ `/packs`, `/installed`, `/categories`). PRD's bare `/api/marketplace` = alias of `/search` (default params). |
|
||||
| `POST /api/marketplace/install` | **EXISTS** | `marketplace.ts` (**Tier: PRO**, SecurityGate). |
|
||||
|
||||
### 16.10 Automations
|
||||
|
||||
> **No `/api/automations/*` routes exist.** The underlying capability is **cron** (`cron.ts`,
|
||||
> `/api/cron/*`), which provides full CRUD + trigger + history. "Automations" = a rename/extension of cron.
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/automations` | **PARTIAL** | Maps to `GET /api/cron` (`cron.ts`). Rename/alias the cron surface as "automations". |
|
||||
| `POST /api/automations` | **PARTIAL** | Maps to `POST /api/cron`. |
|
||||
| `PATCH /api/automations/:id` | **PARTIAL** | Maps to `PATCH /api/cron/:id`. |
|
||||
| `POST /api/automations/:id/run` | **PARTIAL** | Maps to `POST /api/cron/:id/trigger` (auto-enables + runs). |
|
||||
| `POST /api/automations/:id/pause` | **PARTIAL** | No `/pause`; equivalent is `PATCH /api/cron/:id { enabled: false }`. Add a thin `/pause` or use the enabled flag. |
|
||||
| `GET /api/automations/:id/logs` | **PARTIAL** | Maps to `GET /api/cron/:id/history` (in `notifications.ts`). |
|
||||
|
||||
### 16.11 Team / RBAC
|
||||
|
||||
| PRD endpoint | Status | Current path / note |
|
||||
|---|---|---|
|
||||
| `GET /api/teams/:id` | **EXISTS** | `team.ts` (local CRUD; returns members + workspaces). |
|
||||
| `POST /api/teams/:id/invite` | **PARTIAL** | Invite is `POST /api/teams/:id/members` (`{ userId?, email?, displayName?, role? }`). Same intent, different path name. Alias `/invite` → `/members`. |
|
||||
| `PATCH /api/teams/:id/members/:memberId` | **EXISTS** | `team.ts` — `PATCH /api/teams/:id/members/:userId` (PRD's `:memberId` == `:userId`). Also `PUT` variant. |
|
||||
| `GET /api/teams/:id/audit` | **PARTIAL** | Closest: `GET /api/teams/:id/activity` (aggregated audit events across team workspaces) and `GET /api/events`. Alias `/audit` → `/activity` or add. |
|
||||
| `POST /api/share` | **MISSING** | No `/api/share` route anywhere in the repo (grep-confirmed). Sharing is implicit via team workspaces + `teamId` linkage; no explicit share endpoint. Net-new. |
|
||||
|
||||
---
|
||||
|
||||
## Part 3 — Summary Counts
|
||||
|
||||
### Existing local sidecar endpoints (Part 1)
|
||||
|
||||
| Domain group | Count |
|
||||
|---|---|
|
||||
| Chat / Agent exec / Sessions (`03a`) | 23 |
|
||||
| Approvals (`03a`/`03e`) | 5 |
|
||||
| Memory + Knowledge graph (`03b`) | 8 |
|
||||
| Wiki (`03b`) | 8 |
|
||||
| Harvest (`03b`) | 12 |
|
||||
| Import / Ingest / Identity / Mind / Documents / Erase / Export (`03b`) | 13 |
|
||||
| Workspaces / Templates / Storage / Files / Tasks / Pins (`03c`+`04`) | 38 |
|
||||
| Team / RBAC (`03c`) | 20 |
|
||||
| Personas / Settings / Tier / Profile (`03c`) | 26 |
|
||||
| Marketplace / Skills / Plugins / Connectors / Tools / OAuth / Vault / Providers (`03d`) | 56 |
|
||||
| Evolution / Feedback / Telemetry / Compliance / Cost / Capabilities (`03e`) | 31 |
|
||||
| Workflows (`03e`) | 3 |
|
||||
| Real-time / Ops (`03f`) | 60 |
|
||||
| Bootstrap / Stripe / WebSocket (`03g`) | 10 |
|
||||
| **Total existing local sidecar endpoints** | **313** |
|
||||
|
||||
> Aligns with the backend-map domain overview (~294 endpoints across 7 domains in `06-api-domains.md`;
|
||||
> this inventory additionally counts inline bootstrap routes, the `/v1/*` proxy, weaver/tasks/files, and
|
||||
> tier-gated billing routes individually). Dev-only `/_dev/marketplace/*` (4 routes, env-gated) and the
|
||||
> separate Clerk-gated **Cloud** server routes are excluded.
|
||||
|
||||
### PRD §16 target endpoints (Part 2)
|
||||
|
||||
| Section | Total | EXISTS | PARTIAL | MISSING |
|
||||
|---|---|---|---|---|
|
||||
| 16.1 Home | 3 | 0 | 1 | 2 |
|
||||
| 16.2 Workspaces | 7 | 5 | 2 | 0 |
|
||||
| 16.3 Command Center | 4 | 0 | 1 | 3 |
|
||||
| 16.4 Memory | 8 | 2 | 4 | 2 |
|
||||
| 16.5 Harvest | 4 | 3 | 1 | 0 |
|
||||
| 16.6 Artifacts | 6 | 0 | 3 | 3 |
|
||||
| 16.7 Agents | 7 | 0 | 3 | 4 |
|
||||
| 16.8 Skills | 5 | 2 | 3 | 0 |
|
||||
| 16.9 Connectors/MCPs/Marketplace | 10 | 2 | 4 | 4 |
|
||||
| 16.10 Automations | 6 | 0 | 6 | 0 |
|
||||
| 16.11 Team/RBAC | 5 | 2 | 2 | 1 |
|
||||
| **Total** | **65** | **16** | **30** | **19** |
|
||||
|
||||
**Headline:** Of 65 PRD §16 target endpoints, **16 EXIST** as-is, **30 are PARTIAL** (closest current
|
||||
path exists — refactor extends/aliases over the existing substrate), and **19 are MISSING** (net-new
|
||||
backend work). The MISSING set clusters in three net-new domains the PRD invents — **Home** (briefing/
|
||||
overnight), **Command Center** (palette search/recent/suggestions), and **Artifacts** (unified
|
||||
file/document/output abstraction) — plus **MCP-specific** management (test/revoke), **memory merge/
|
||||
archive/by-id**, **per-agent run/traces**, and **`/api/share`**. None require a new data store: every
|
||||
MISSING endpoint can be built over existing substrates (memory frames, file registry, document versions,
|
||||
cron, audit events, execution traces, capabilities/status), consistent with the LOCKED in-place
|
||||
incremental-refactor model.
|
||||
380
docs/ux-refactor/_inventory/frontend.md
Normal file
380
docs/ux-refactor/_inventory/frontend.md
Normal file
@@ -0,0 +1,380 @@
|
||||
# Frontend Inventory — `apps/web/src`
|
||||
|
||||
> Baseline for the Waggle OS UX-refactor planning track. Enumerates the current
|
||||
> web frontend so all downstream planners share one ground-truth map.
|
||||
> Every entry is grounded in source under `D:/Projects/waggle-os/apps/web/src`.
|
||||
> Execution model is locked as an **in-place incremental refactor** of this code —
|
||||
> this is the surface that gets extended, not replaced.
|
||||
|
||||
Entry point chain: `main.tsx` → `App.tsx` (`ServiceProvider` → `QueryClientProvider`
|
||||
→ `TooltipProvider` → `BrowserRouter`) → `pages/Index.tsx` (route `/`) →
|
||||
`BootScreen` then `Desktop`. There is **no react-router-based navigation between
|
||||
apps** — routing is a single `/` page; all "navigation" is window management
|
||||
inside `Desktop.tsx`.
|
||||
|
||||
---
|
||||
|
||||
## (a) App shells, overlays, and OS-level components
|
||||
|
||||
### `components/os/apps/*` — per-app window content (26 top-level + 3 sub-dirs)
|
||||
|
||||
| File | 1-line role |
|
||||
|---|---|
|
||||
| `ChatApp.tsx` | Core chat surface: message list + block rendering + composer + autonomy picker + persona header. The product's primary work surface. |
|
||||
| `ChatWindowInstance.tsx` | Per-window wrapper around `ChatApp` — owns session selection, model selector, autonomy state, WorkspaceBriefing home screen; one instance per chat window. |
|
||||
| `DashboardApp.tsx` | "Home" / Workspaces grid — lists workspaces, select/create, opens chat per workspace. Mapped to dock key `home`. |
|
||||
| `MemoryApp.tsx` | Memory hub with 6 tabs: Timeline (frames), Graph (KG), Harvest (import other-AI convos), Weaver (distillation), Wiki (compiled pages), Evolution (self-evolving prompts). |
|
||||
| `FilesApp.tsx` | File-manager layout shell (FileTree + FilePreview + FileActions + FileUploadZone). |
|
||||
| `FilesAppTabs.tsx` | P16 three-tab wrapper around `FilesApp` — Virtual / Local / Team storage; remounts FilesApp per storageType. This is what `Desktop` renders for `files`. |
|
||||
| `AgentsApp.tsx` | "Personas" manager — list/create/edit personas + agent groups; uses `agents/` subcomponents. |
|
||||
| `ConnectorsApp.tsx` | Connectors manager with 2 tabs: Services (native connectors w/ status+actions) and MCP Servers (catalog). |
|
||||
| `CapabilitiesApp.tsx` | "Skills & Apps" — starter packs, capability packs, and a Marketplace packs section (marketplace is folded in here, not a separate dock entry). |
|
||||
| `MarketplaceApp.tsx` | Standalone marketplace browser (search/install/uninstall packages). Registered in `Desktop` appConfig as `marketplace` but no dock entry points at it (CapabilitiesApp hosts the surface). |
|
||||
| `CockpitApp.tsx` | "Command Center" — system health, agent activity, cost/usage tiles; hosts `cockpit/ComplianceDashboard`. |
|
||||
| `MissionControlApp.tsx` | Fleet/spawn overview + AI-tool inventory tile; "Spawn Agent" entry point. |
|
||||
| `RoomApp.tsx` | The Room canvas — live sub-agent tiles across all workspaces via `useRoomState` SSE. |
|
||||
| `WaggleDanceApp.tsx` | Multi-agent coordination signal feed (discovery/handoff/insight/alert/coordination) with detail pane + ack. |
|
||||
| `EventsApp.tsx` | Agent event/log stream (think/tool_call/tool_result/response/error/spawn) with filter + autoscroll + abort. |
|
||||
| `TimelineApp.tsx` | Per-workspace chronological timeline of tool/model/cost events (`GET /api/events`). |
|
||||
| `TelemetryApp.tsx` | "Usage & Telemetry" — token/cost/tool-call totals, telemetry enable/clear. |
|
||||
| `ScheduledJobsApp.tsx` | Cron jobs manager (list/create/update/delete/trigger). |
|
||||
| `ApprovalsApp.tsx` | Approvals inbox (Phase B.3) — Pending requests tab + grants tab; same backend as inline chat approvals. |
|
||||
| `BackupApp.tsx` | Backup & Restore — backup metadata, create/restore; 404 treated as "no backups yet". |
|
||||
| `SettingsApp.tsx` | Settings shell with 8 tabs: General, Models, Billing, Permissions, Team, Backup, Enterprise, Advanced. |
|
||||
| `VaultApp.tsx` | Secret vault — Secrets tab (add/delete keys) + additional tab(s). |
|
||||
| `UserProfileApp.tsx` | "My Profile" — identity questionnaire, writing-style analysis, brand extraction, research (tabbed). |
|
||||
| `VoiceApp.tsx` | Voice interaction surface (speech recognition / TTS). |
|
||||
| `TeamGovernanceApp.tsx` | Team Governance panel (Teams-tier; roles/permissions surface). |
|
||||
| `LauncherApp.tsx` | AI-OS tool launcher dock surface — detect/install-hooks/launch external AI tools (claude-code/cursor/claude-desktop launch cohort; codex/hermes/openclaw stubbed). |
|
||||
|
||||
Sub-directories under `apps/`:
|
||||
- `agents/` — `AgentCard.tsx`, `AgentDetail.tsx`, `CreateAgentForm.tsx`, `CreateGroupForm.tsx`, `GroupCard.tsx`, `GroupExecutionPanel.tsx` (Personas/agent-group UI parts).
|
||||
- `chat-blocks/` — `BlockRenderer.tsx`, `ModelSwitchBlock.tsx`, `StepBlock.tsx`, `ToolUseBlock.tsx` (renders the `ContentBlock` union inside chat messages).
|
||||
- `cockpit/` — `ComplianceDashboard.tsx`.
|
||||
- `connectors/` — `BrandTile.tsx`, `McpServerCard.tsx`.
|
||||
- `files/` — `FileActions.tsx`, `FilePreview.tsx`, `FileTree.tsx`, `FileUploadZone.tsx`, `SyntaxPreview.tsx`, `WorkspaceRail.tsx`.
|
||||
- `memory/` — `EvolutionTab.tsx`, `WeaverPanel.tsx`, `WikiTab.tsx`.
|
||||
|
||||
### `components/os/overlays/*` — modals, drawers, switchers (14)
|
||||
|
||||
| File | 1-line role |
|
||||
|---|---|
|
||||
| `OnboardingWizard.tsx` | First-launch wizard (rendered as full-screen early-return from `Desktop` when `!onboardingState.completed`); uses `onboarding/` step components. |
|
||||
| `OnboardingTooltips.tsx` | Post-wizard "Tour" overlay (4 slides: commands, dock, memory, closing). |
|
||||
| `LoginBriefing.tsx` | Session-start "I remember…" briefing — memory highlights + cross-workspace catch-up with workspace links. |
|
||||
| `GlobalSearch.tsx` | Ctrl+K command palette + global search; navigates commands/workspaces/memory. |
|
||||
| `PersonaSwitcher.tsx` | Persona picker (two-tier: universal modes + workspace specialists; hover tagline/bestFor/wontDo). Operates on focused chat window's persona or patches workspace. |
|
||||
| `WorkspaceSwitcher.tsx` | Workspace quick-switcher list (filters E2E/test artefact names). |
|
||||
| `SpawnAgentDialog.tsx` | Spawn a sub-agent (task + persona + model + parent workspace). |
|
||||
| `CreateWorkspaceDialog.tsx` | New-workspace dialog (name/group/persona/template). |
|
||||
| `NotificationInbox.tsx` | Notifications drawer (mark read / mark all read). |
|
||||
| `KeyboardShortcutsHelp.tsx` | Keyboard shortcuts cheat-sheet modal. |
|
||||
| `ContextRail.tsx` | Right-side rail showing full context for a clicked frame/entity (Phase C.1). Exports `ContextRailTarget`. |
|
||||
| `UpgradeModal.tsx` | Upgrade/start-trial modal; calls `startTrial` / `createCheckoutSession`. |
|
||||
| `TrialExpiredModal.tsx` | Trial-expired blocking modal → upgrade. |
|
||||
| `EraseDataDialog.tsx` | GDPR Art. 17 erasure confirmation (3-state); triggered from Settings → General. |
|
||||
|
||||
Sub-directory `overlays/onboarding/`: `WelcomeStep.tsx`, `TierStep.tsx`, `ApiKeyStep.tsx`, `ReadyStep.tsx`.
|
||||
|
||||
### `components/os/*.tsx` — shell/runtime + shared OS components (12)
|
||||
|
||||
| File | 1-line role |
|
||||
|---|---|
|
||||
| `Desktop.tsx` | **Root OS shell.** Wires all domain hooks + window manager + overlays; holds `appConfig` (title/icon/pos/size per appId) and `renderAppContent` (the appId→component switch). |
|
||||
| `Dock.tsx` | Bottom dock — renders tier-filtered `DockEntry[]`, zone-parent flyouts (via `DockTray`), open/minimized indicators, Spawn Agent button, Waggle badge. |
|
||||
| `DockTray.tsx` | Portal-to-body flyout popover for a dock zone-parent's children. |
|
||||
| `AppWindow.tsx` | Draggable/resizable/snappable/maximizable window chrome (title bar, min/max/close, edge+corner resize, left/right/top snap, position persistence). |
|
||||
| `StatusBar.tsx` | Top bar — logo, workspace name, focused-window label, model, memory-frame trophy count, dev tokens/cost, trial badge, Search button, notifications bell, offline indicator, clock. |
|
||||
| `BootScreen.tsx` | Animated boot splash (5 phases, click/key to skip); shown before `Desktop`. |
|
||||
| `ErrorBoundary.tsx` | App-level error boundary (`AppErrorBoundary`) wrapping each window's content + the whole app. |
|
||||
| `ContextMenu.tsx` | Generic right-click context menu primitive (used by MemoryApp frames etc.). |
|
||||
| `LockedFeature.tsx` | Tier-gated "locked" overlay/badge for features above the user's plan. |
|
||||
| `ModelSelector.tsx` | Reusable model picker (Settings/Onboarding/workspace-create/spawn); fetches via `useProviders`. |
|
||||
| `ModelPilotCard.tsx` | 3-lane model fallback visualizer (Primary → Fallback → Budget Saver). |
|
||||
| `WorkspaceBriefing.tsx` | ChatApp "home screen" when no messages — greeting/memories/decisions/tasks/suggested prompts from `GET /api/workspaces/:id/context`. |
|
||||
|
||||
---
|
||||
|
||||
## (b) Shell / runtime — how the window manager, dock, and nav work
|
||||
|
||||
**There is no per-app route.** The window manager is `hooks/useWindowManager.ts`,
|
||||
consumed by `Desktop.tsx`. App opening is keyed by `AppId`, **not** by URL.
|
||||
|
||||
### Window manager (`useWindowManager(workspaces, { defaultAutonomy })`)
|
||||
- State: `windows: WindowState[]` (persisted to `localStorage` key
|
||||
`waggle-window-state-v1`, version-gated), `focusedInstanceId`, z-index counter,
|
||||
cascade counter.
|
||||
- `WindowState` fields: `instanceId`, `appId`, `workspaceId?`, `workspaceName?`,
|
||||
`personaId?`/`personaLabel?`, `templateLabel?`, `initialMessage?`,
|
||||
`autonomyLevel?`/`autonomyExpiresAt?`, `zIndex`, `minimized`, `cascadeOffset`.
|
||||
- **How apps open by appId:** `openApp(id: AppId)` — for non-chat apps it reuses an
|
||||
existing window of that appId (focus + un-minimize) or pushes a new `WindowState`;
|
||||
for chat it always allows multiples. `openChatForWorkspace(workspaceId, name?,
|
||||
personaOverride?, initialMessage?)` — reuses the workspace's existing chat window
|
||||
unless a `personaOverride` is given (deliberate second specialist); seeds per-window
|
||||
persona + inherited `defaultAutonomy`.
|
||||
- Per-window controls: `setWindowPersona`, `setWindowAutonomy` (TTL auto-revert every
|
||||
10 s), `closeApp`, `minimizeApp`, `focusWindow`, `cycleWindowFocus` (Ctrl+`),
|
||||
`closeTopWindow`, `minimizeTopWindow`, `getWindowTitle`.
|
||||
- Reconciliation: migrates restored chat windows off the `local-default` placeholder
|
||||
onto the first real workspace; never deletes windows for missing workspaces.
|
||||
- Derived: `openAppIds`, `minimizedAppIds` (drive dock indicators).
|
||||
|
||||
### How `Desktop` renders a window
|
||||
`appConfig: Record<string, {title, icon, pos, size}>` keyed by appId provides chrome
|
||||
defaults. `renderAppContent(win: WindowState)` is a `switch (win.appId)` mapping each
|
||||
appId to its component with props. Position resolved via `getSavedPosition(appId)`
|
||||
(from `lib/window-positions.ts`) or `computeCascadePosition` (from
|
||||
`lib/window-cascade.ts`). Cross-component `waggle:open-app` CustomEvent lets any
|
||||
surface raise a window.
|
||||
|
||||
### Dock + nav (`Dock.tsx` + `lib/dock-tiers.ts`)
|
||||
- `getDockForTier(tier: UserTier, billingTier: BillingTier)` returns a
|
||||
`DockEntry[]`, recursively filtered by `minBillingTier`.
|
||||
- `DockEntry.type` ∈ `'app' | 'zone-parent' | 'separator'`. Zone-parents
|
||||
(`Ops`, `Extend`) open a `DockTray` flyout of child apps.
|
||||
- `TIER_DOCK_CONFIG` defines docks per `UserTier` (`simple`/`professional`/`power`/
|
||||
`admin`; power===admin===`POWER_CONFIG`). `UserTier` is the **UI density tier**
|
||||
(from onboarding), distinct from the billing tier.
|
||||
- Clicking a dock app calls `onOpenApp(id)` → `Desktop` routes `chat` to
|
||||
`openChatForWorkspace`, everything else to `openApp`.
|
||||
|
||||
### The two app-id unions (IMPORTANT for the refactor)
|
||||
- **`AppId`** (canonical, in `lib/dock-tiers.ts`, re-exported from `Dock.tsx`) — 27
|
||||
ids: `chat, dashboard, memory, events, capabilities, connectors, cockpit,
|
||||
mission-control, settings, vault, profile, terminal, calculator, notes,
|
||||
waggle-dance, files, agents, scheduled-jobs, marketplace, voice, room, approvals,
|
||||
timeline, backup, telemetry, governance, launcher`. (`terminal`/`calculator`/`notes`
|
||||
are declared but have **no app component / appConfig entry** — dead ids.)
|
||||
- **`AppView`** (legacy, in `lib/types.ts`) — only 8 ids: `chat, dashboard, memory,
|
||||
events, capabilities, cockpit, mission-control, settings`. **Stale/partial union,
|
||||
superseded by `AppId`.** Not used by the window manager. Flag for cleanup.
|
||||
|
||||
### Keyboard shortcuts (`hooks/useKeyboardShortcuts.ts`, wired in `Desktop`)
|
||||
`onOpenApp`, `onToggleGlobalSearch` (Ctrl+K), `onTogglePersonaSwitcher`,
|
||||
`onToggleWorkspaceSwitcher`, `onToggleKeyboardHelp`, `onCloseTopWindow`,
|
||||
`onMinimizeTopWindow`, `onNewChatWindow`; plus Ctrl+` window cycle in the WM itself.
|
||||
|
||||
---
|
||||
|
||||
## (c) Data layer — adapter singleton, ServiceProvider, domain hooks
|
||||
|
||||
### `lib/adapter.ts` — `LocalAdapter` singleton (exported `adapter`)
|
||||
The single HTTP/SSE gateway to the Fastify sidecar. All `fetch` go through
|
||||
`adapter.fetch(path, init)` (adds base URL, auth token, content-type, 403/tier
|
||||
handling). Base URL resolved from `getServerUrl()`. Full method → endpoint map
|
||||
(grounded in line numbers in `adapter.ts`):
|
||||
|
||||
**Connection / system:** `connect()` (`/api/auth/session-token`, health),
|
||||
`setServerUrl`/`getServerUrl`, `fetch`, `getSystemHealth` (`/api/health` via
|
||||
`connect`), `connectWebSocket`.
|
||||
|
||||
**Workspaces / templates:** `getWorkspaces` `GET /api/workspaces`; `createWorkspace`
|
||||
`POST /api/workspaces`; `updateWorkspace` `PUT /api/workspaces/:id`; `patchWorkspace`
|
||||
`PATCH /api/workspaces/:id`; `deleteWorkspace` `DELETE`; `getWorkspaceContext`
|
||||
`GET /api/workspaces/:id/context`; `getWorkspaceFiles` `…/files`; `getWorkspaceTemplates`
|
||||
`GET /api/workspace-templates`; `createWorkspaceTemplate`/`updateWorkspaceTemplate`/
|
||||
`deleteWorkspaceTemplate`; `generateTemplateFromPrompt` `…/generate`.
|
||||
|
||||
**Files / browse:** `browseLocal` `GET /api/browse/local`; `browseLocalMkdir`;
|
||||
`listFiles` `…/files/list`; `uploadFile` `…/files/upload`; `downloadFile`;
|
||||
`createDirectory` `…/files/mkdir`; `deleteFile`; `moveFile`; `copyFile`.
|
||||
|
||||
**Chat / sessions / history:** `sendMessage` (async generator over SSE) `POST /api/chat`;
|
||||
`abortAgent` `POST /api/agent/abort`; `clearHistory` `DELETE /api/chat/history`;
|
||||
`getHistory` `GET /api/history`; `getSessions` `…/sessions`; `createSession`;
|
||||
`renameSession`; `deleteSession`; `searchSessions` `…/sessions/search`;
|
||||
`exportSession` `…/sessions/:id/export`.
|
||||
|
||||
**Memory / KG / identity:** `getMemoryFrames` `GET /api/memory/frames`; `addMemoryFrame`;
|
||||
`updateMemoryFrame`; `deleteMemoryFrame`; `incrementFrameAccess` `…/frames/:id/access`;
|
||||
`searchMemory` `GET /api/memory/search`; `searchTeamMemory` `/api/team/memory/search`;
|
||||
`getKnowledgeGraph` `GET /api/memory/graph`; `getMemoryStats` `/api/memory/stats`;
|
||||
`getIdentity` `/api/identity`; `getMindIdentity`/`getMindAwareness`/`getMindSkills`
|
||||
`/api/mind/*`.
|
||||
|
||||
**Agent / models / providers:** `getEvents` `GET /api/events`; `getTimeline` `/api/events`;
|
||||
`subscribeEvents` SSE `/api/events/stream`; `getEventStats` `/api/events/stats`;
|
||||
`getAgentStatus` `/api/agent/status`; `getAgentCost` `/api/agent/cost`; `setModel`/`getModel`
|
||||
`/api/agent/model`; `getModels` `/api/litellm/models`; `getProviders` `/api/providers`;
|
||||
`getLiteLLMStatus` `/api/litellm/status`; `getModelPricing` `/api/litellm/pricing`;
|
||||
`getLocalInferenceHardware`/`-Models`/`-Status`/`pullLocalModel` `/api/local-inference/*`.
|
||||
|
||||
**Skills / capabilities / marketplace:** `getSkills` `/api/skills`; `createSkill`;
|
||||
`getStarterPacks` `/api/skills/starter-pack/catalog`; `getCapabilityPacks`
|
||||
`/api/skills/capability-packs/catalog`; `installPack` `/api/skills/starter-pack/:id`;
|
||||
`getCapabilitiesStatus`/`getCapabilityStatus` `/api/capabilities/status`;
|
||||
`getMarketplacePacks` `/api/marketplace/packs`; `searchMarketplace`/`getMarketplaceInstalled`/
|
||||
`installMarketplacePackage`/`uninstallMarketplacePackage`/`installMarketplacePack`/
|
||||
`uninstallMarketplacePack` `/api/marketplace/*`.
|
||||
|
||||
**Fleet / agents / groups / jobs:** `getFleet` `/api/fleet`; `fleetAction`
|
||||
`/api/fleet/:ws/:action`; `spawnAgent` `/api/fleet/spawn`; `getPersonas`/`createPersona`/
|
||||
`deletePersona`/`updatePersona`/`generatePersona` `/api/personas*`; `getAgentGroups`/
|
||||
`createAgentGroup`/`deleteAgentGroup`/`updateAgentGroup`/`runAgentGroup` `/api/agent-groups*`;
|
||||
`getJobStatus` `/api/jobs/:id`; `cancelJob` `…/cancel`.
|
||||
|
||||
**Cron:** `getCronJobs`/`createCronJob`/`updateCronJob`/`deleteCronJob`/`triggerCronJob`
|
||||
`/api/cron*`.
|
||||
|
||||
**Notifications / approvals:** `subscribeNotifications` SSE `/api/notifications/stream`;
|
||||
`getNotificationHistory`; `markNotificationRead`; `markAllNotificationsRead`;
|
||||
`getPendingApprovals` `/api/approval/pending`; `respondApproval` `/api/approval/:id`;
|
||||
`getApprovalGrants`/`revokeApprovalGrant`/`clearApprovalGrants` `/api/approval/grants*`;
|
||||
`subscribeSubagentStatus` (SSE, drives Room); `subscribeHarvestProgress`.
|
||||
|
||||
**Settings / permissions / keys:** `getSettings`/`saveSettings` `/api/settings`;
|
||||
`getPermissions`/`savePermissions` `/api/settings/permissions`; `testApiKey`
|
||||
`/api/settings/test-key`.
|
||||
|
||||
**Connectors / vault / profile:** `getConnectors` `/api/connectors`; `getConnectorHealth`;
|
||||
`connectConnector`/`disconnectConnector`; `getVault`/`addVaultSecret`/`deleteVaultSecret`
|
||||
`/api/vault*`; `getProfile`/`updateProfile`/`analyzeWritingStyle`/`analyzeBrand`/
|
||||
`researchProfile` `/api/profile*`.
|
||||
|
||||
**Team:** `teamConnect`/`teamDisconnect`/`getTeamStatus`/`getTeamMembers`/`getTeamActivity`/
|
||||
`getTeamMessages` `/api/team/*`.
|
||||
|
||||
**Costs / telemetry:** `getCosts` `/api/costs`; `getCostByWorkspace`; `getCostSummary`
|
||||
`/api/cost/summary`; `getTelemetryStatus`/`toggleTelemetry`/`clearTelemetry`/`trackTelemetry`
|
||||
`/api/telemetry/*`.
|
||||
|
||||
**Billing / tier / data:** `syncStripeCheckout` `/api/stripe/sync`; `createCheckoutSession`
|
||||
`/api/stripe/create-checkout-session`; `createPortalSession`; `getTier` `/api/tier`;
|
||||
`startTrial` `/api/tier/start-trial`; `eraseData` `/api/data/erase`.
|
||||
|
||||
**Harvest / import:** `importPreview`/`importCommit` `/api/import/*`;
|
||||
`harvestPreview`/`harvestCommit` `/api/harvest/*`; `getHarvestSources`; `scanClaudeCode`
|
||||
`/api/harvest/scan-claude-code`; `extractHarvestIdentity`; `getLatestInterruptedHarvestRun`;
|
||||
`resumeHarvestRun`; `abandonHarvestRun`; `removeHarvestSource`; `toggleHarvestAutoSync`.
|
||||
|
||||
**Wiki:** `getWikiPages`/`getWikiPage`/`getWikiPageContent`/`compileWiki`/`getWikiHealth`/
|
||||
`getWikiWatermark`/`exportWikiToObsidian`/`exportWikiToNotion` `/api/wiki/*`.
|
||||
|
||||
**Compliance:** `getComplianceStatus`/`exportComplianceReportPdf`/`exportComplianceReport`/
|
||||
`getComplianceInteractions`/`getComplianceModels`/`listComplianceTemplates`/
|
||||
`createComplianceTemplate`/`updateComplianceTemplate`/`deleteComplianceTemplate` `/api/compliance/*`.
|
||||
|
||||
**Misc:** `getWeaverStatus` `/api/weaver/status`; `getAuditInstalls` `/api/audit/installs`;
|
||||
`ingestFile` `/api/ingest`; `executeCommand` `/api/commands/execute`;
|
||||
`getPins`/`addPin`/`removePin` `/api/workspaces/:id/pins*`; `getDocuments`/`getDocumentVersions`
|
||||
`…/documents*`; `submitFeedback` `/api/feedback`; `getWaggleSignals`/`publishWaggleSignal`/
|
||||
`acknowledgeWaggleSignal` `/api/waggle/signals*`; `subscribeWaggleDance` SSE `/api/waggle/stream`;
|
||||
AI-OS tools: `detectTools` `/api/tools/detect`, `launchTool` `/api/tools/launch`,
|
||||
`getToolProcesses` `/api/tools/processes`, `killTool` `/api/tools/kill`, `manageHooks`
|
||||
`/api/tools/hooks`.
|
||||
|
||||
### `providers/ServiceProvider.tsx`
|
||||
The only React provider for the adapter. Calls `adapter.connect()` on mount, exposes
|
||||
`{ adapter, connected, connecting, error, reconnect }` via `useService()`. Note: most
|
||||
hooks import `adapter` **directly** rather than via `useService` — context is mainly
|
||||
for connection status.
|
||||
|
||||
### Domain hooks (`hooks/*`) — name → adapter methods / endpoints
|
||||
|
||||
| Hook | Returns / role | Adapter methods used |
|
||||
|---|---|---|
|
||||
| `useWorkspaces` | workspaces, activeWorkspace(Id), select/create/delete/patch, refresh | `getWorkspaces`, `createWorkspace`, `deleteWorkspace`, `patchWorkspace` |
|
||||
| `useChat({workspaceId,sessionId,persona,autonomy})` | messages, isLoading, sendMessage, clearHistory, pendingApproval, approveAction | `getHistory`, `sendMessage` (SSE), `clearHistory`, `respondApproval` |
|
||||
| `useSessions` | sessions, activeSessionId, create/delete/rename | `getSessions`, `createSession`, `deleteSession`, `renameSession` |
|
||||
| `useMemory` | filtered frames, selectedFrame, filters, add/edit/delete/incrementAccess, stats | `getMemoryFrames`, `searchMemory`, `getMemoryStats`, `addMemoryFrame`, `updateMemoryFrame`, `deleteMemoryFrame`, `incrementFrameAccess` |
|
||||
| `useKnowledgeGraph` | nodes, edges, scope (current/personal/all), refresh | `getKnowledgeGraph` |
|
||||
| `useEvents` | steps, filter, autoScroll | `getEvents`, `subscribeEvents` (SSE) |
|
||||
| `useAgentStatus` | model/tokens/cost/isActive/offline (polled, backoff) | `getAgentStatus` |
|
||||
| `useNotifications` | notifications, unreadCount, markRead, markAllRead | `getNotificationHistory`, `subscribeNotifications` (SSE), `markNotificationRead`, `markAllNotificationsRead` |
|
||||
| `useWaggleDance` | signals (filtered), allSignals, publish, acknowledge, refresh | `getWaggleSignals`, `subscribeWaggleDance` (SSE), `publishWaggleSignal`, `acknowledgeWaggleSignal` |
|
||||
| `useRoomState` | per-workspace live/recent sub-agent map, totalLive | `subscribeSubagentStatus` (SSE) → `lib/room-state-reducer.ts` |
|
||||
| `useProviders` | providers, models, search providers, available/active models | `getProviders` |
|
||||
| `useBilling` | tier, refreshTier, syncAfterCheckout, startCheckout, openPortal | `getTier`, `syncStripeCheckout`, `createCheckoutSession`, `createPortalSession` |
|
||||
| `useFeatureGate` | planTier, isEnabled(feature), gate(feature) | (none; reads `useOnboarding` + `lib/feature-gates`) |
|
||||
| `useOnboarding` | onboarding state (localStorage `waggle:onboarding`), update/complete/reset/replayTour | `getWorkspaces` (returning-user auto-complete) + tauri-bindings |
|
||||
| `useOverlayState` | all overlay open/close flags + toggles | (none; pure UI state) |
|
||||
| `useWindowManager` | window list + all window ops (see §b) | (none; localStorage only) |
|
||||
| `useEvents`/`useSessions`/`useMemory` etc. are workspace-scoped | | |
|
||||
| `useKeyboardShortcuts` | binds global hotkeys to callbacks | (none) |
|
||||
| `useDockLabels`, `useDockNudge` | dock label visibility + milestone nudges | (none / local) |
|
||||
| `useDeveloperMode`, `useIsLightTheme`, `useOfflineStatus`, `useContainerWidth`, `useFocusTrap`, `use-mobile`, `use-toast` | UI/utility hooks | (none) |
|
||||
|
||||
`lib/` also holds many **pure helper + state modules** (most with co-located `.test.ts`):
|
||||
`brain-health`, `briefing-highlights`, `browse-breadcrumbs`, `chat-header-layout`,
|
||||
`context-rail-fetch`, `cron-presets`, `dedupe-packs`, `dock-labels`, `dock-nudge`,
|
||||
`feature-gates`, `fetch-utils`, `fuzzy-match`, `login-briefing(-brag)`,
|
||||
`memory-recall-toast`, `modal-drag`, `onboarding-skip`, `onboarding-tier-filter`,
|
||||
`persona-tier`, `persona-tooltip`, `persona-display`, `personas`, `posthog`, `providers`,
|
||||
`render-markdown`, `room-state-reducer`, `settings-tier-filter`, `shape-selection`,
|
||||
`skill-pack-display`, `skill-recommendations`, `spawn-agent-helpers`, `status-bar-focus`,
|
||||
`suggested-actions`, `tauri-bindings`, `timeline-events`, `tiers`, `utils`,
|
||||
`waggle-signals`, `window-cascade`, `window-positions`, `workspace-briefing-state`,
|
||||
`workspace-groups`, `kg-export`, `launcher-prompt-args`, `context-menu-index`,
|
||||
`decode-entities`.
|
||||
|
||||
---
|
||||
|
||||
## (d) `lib/types.ts` — exported types
|
||||
|
||||
Type aliases / unions: `AppView` (legacy 8-id, stale — see §b), `StorageType`,
|
||||
`TemplateCategory`, `ContentBlock` (union).
|
||||
|
||||
Interfaces: `StorageConfig`, `Workspace`, `FileEntry`, `WorkspaceTemplate`,
|
||||
`WorkspaceContext`, `ChatMessage`, `ToolExecution`, `ApprovalRequest`, `MemoryFrame`,
|
||||
`AgentStep`, `TimelineEvent`, `TextContentBlock`, `StepContentBlock`,
|
||||
`ToolUseContentBlock`, `ModelSwitchContentBlock`, `ErrorContentBlock`, `Session`,
|
||||
`SkillPack`, `FleetSession`, `CronJob`, `Notification`, `AgentStatus`, `Persona`
|
||||
(incl. `tagline`/`bestFor`/`wontDo`/`isReadOnly`), `SystemHealth`, `Connector`,
|
||||
`StreamEvent`, `Settings`, `KGNode`, `KGEdge`, `ModelPricing`, `WaggleSignal`.
|
||||
|
||||
Notable type sources **outside** `types.ts`: `AppId`/`UserTier`/`BillingTier`/
|
||||
`DockEntry` in `lib/dock-tiers.ts`; `WindowState`/`AutonomyLevel` in
|
||||
`hooks/useWindowManager.ts`; `OnboardingState` in `hooks/useOnboarding.ts`;
|
||||
`PlanTier`/`FeatureGate` in `lib/feature-gates.ts`; `Provider`/`ProviderModel`/
|
||||
`SearchProvider` in `hooks/useProviders.ts`; `RoomAgent`/`WorkspaceAgents` in
|
||||
`lib/room-state-reducer.ts`; `ContextRailTarget` in `overlays/ContextRail.tsx`.
|
||||
|
||||
---
|
||||
|
||||
## (e) Design-system primitives — `components/ui/*` (shadcn/ui, ~50)
|
||||
|
||||
Standard shadcn/ui set: `accordion, alert, alert-dialog, aspect-ratio, avatar, badge,
|
||||
breadcrumb, button, calendar, card, carousel, chart, checkbox, collapsible, command,
|
||||
context-menu, dialog, drawer, dropdown-menu, form, hover-card, input, input-otp, label,
|
||||
menubar, navigation-menu, pagination, popover, progress, radio-group, resizable,
|
||||
scroll-area, select, separator, sheet, sidebar, skeleton, slider, sonner, switch, table,
|
||||
tabs, textarea, toast, toaster, toggle, toggle-group, tooltip`. Waggle-specific addition:
|
||||
`hint-tooltip.tsx` (`HintTooltip`, used across StatusBar/AppWindow). Toast plumbing
|
||||
duplicated in both `components/ui/use-toast.ts` and `hooks/use-toast.ts`. Theming via
|
||||
`waggle-theme.css` + `index.css` (Hive DS semantic tokens: honey/hive-950/accent;
|
||||
`data-theme` on `<html>` toggles dark/light, observed by `Desktop`). Also
|
||||
`components/NavLink.tsx` (single router NavLink, near-unused given single-route app).
|
||||
|
||||
---
|
||||
|
||||
## (f) Current apps → new IA buckets (PRD §10)
|
||||
|
||||
PRD IA layers: Global, Work (10.2), Intelligence (10.3), Extend (10.4), Team (10.5),
|
||||
System (10.6). Mapping the existing apps/surfaces to the locked Work / Intelligence /
|
||||
Extend / Team / System buckets:
|
||||
|
||||
| Bucket (PRD) | Existing apps / surfaces |
|
||||
|---|---|
|
||||
| **Global** (cross-cutting) | `GlobalSearch` (Ctrl+K), `NotificationInbox`, `StatusBar`, `Dock`, `BootScreen`, `LoginBriefing`, `OnboardingWizard`/`Tooltips`. |
|
||||
| **Work** | `DashboardApp` (Home Cockpit/Workspaces), `ChatApp`/`ChatWindowInstance` + `WorkspaceBriefing` (Sessions), `MemoryApp` (Memory: Timeline/Graph/Harvest/Weaver/Wiki), `FilesApp(Tabs)` (Artifacts), `TimelineApp`, `EventsApp` (session/agent activity), `WorkspaceSwitcher`/`CreateWorkspaceDialog`. |
|
||||
| **Intelligence** | `AgentsApp` (+`agents/` + `PersonaSwitcher` + `SpawnAgentDialog`) = Agents; `CapabilitiesApp` (Skills); `ScheduledJobsApp` (Automations); `RoomApp` + `MissionControlApp` + `WaggleDanceApp` (multi-agent orchestration); `MemoryApp → Evolution tab` (traces/evolutions); `ApprovalsApp` (agent governance/decisions). |
|
||||
| **Extend** | `ConnectorsApp` (Connectors + MCP catalog), `MarketplaceApp` + `CapabilitiesApp` marketplace section (Marketplace), `LauncherApp` (External tools), `ModelSelector`/`ModelPilotCard` + Settings→Models (Models). |
|
||||
| **Team** | `TeamGovernanceApp` (members/roles), `searchTeamMemory` surface (shared memory), Settings→Team tab, `CockpitApp → ComplianceDashboard` (activity/audit). |
|
||||
| **System** | `SettingsApp` (8 tabs: General/Models/Billing/Permissions/Team/Backup/Enterprise/Advanced), `VaultApp` (Security/secrets), `UserProfileApp` (Profile), `BackupApp` (Backup/restore + data), `TelemetryApp` (usage), `EraseDataDialog` (data deletion), `UpgradeModal`/`TrialExpiredModal` (Billing/plan). |
|
||||
|
||||
**Refactor-relevant observations** (grounded, for downstream planners):
|
||||
- The product is a **single-route windowed desktop**, not a navigable app. The new IA's
|
||||
Work/Intelligence/Extend/Team/System "layers" must be expressed through the existing
|
||||
**dock zones** (`dock-tiers.ts` `zone-parent` model) + window manager, not new routes.
|
||||
- **Dual app-id union drift**: `AppId` (27, canonical) vs `AppView` (8, stale in
|
||||
`types.ts`). The refactor should consolidate on `AppId`; `AppView` and the dead ids
|
||||
`terminal`/`calculator`/`notes` are cleanup candidates.
|
||||
- **Marketplace is doubly represented** (standalone `MarketplaceApp` with no dock entry +
|
||||
a section inside `CapabilitiesApp`) — IA cleanup point.
|
||||
- **`UserTier` (UI density: simple/professional/power/admin) ≠ `BillingTier`
|
||||
(FREE/TRIAL/PRO/TEAMS/ENTERPRISE) ≠ `PlanTier` (solo/teams/business/enterprise in
|
||||
feature-gates).** Three overlapping tier vocabularies the new IA gating will have to
|
||||
reconcile.
|
||||
- Adapter is a fat single file (`lib/adapter.ts`, ~1930 lines, ~150 methods) and is the
|
||||
one contract surface to the sidecar — new PRD §16 endpoints get added here.
|
||||
286
docs/ux-refactor/_inventory/substrate-types.md
Normal file
286
docs/ux-refactor/_inventory/substrate-types.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# Substrate & Types Inventory — UX Refactor
|
||||
|
||||
> Source-grounded inventory for the Waggle OS UX-refactor plan. Every claim cites a real file
|
||||
> path (and line where load-bearing). Execution model is **in-place incremental refactor** of the
|
||||
> existing substrate, not a rebuild. PRD = `docs/Waggle_OS_UX_Refactor_Master_Handoff_Package/Waggle_OS_UX_Refactor_PRD.md`.
|
||||
|
||||
---
|
||||
|
||||
## (a) WorkspaceConfig — current fields vs PRD §15.3 `WorkspaceConfigV2`
|
||||
|
||||
**Current type:** `WorkspaceConfig` in `packages/hive-mind-core/src/workspace-manager.ts:5-58`
|
||||
(the persisted `workspace.json` shape; CRUD via `WorkspaceManager.create/list/get/update/delete`,
|
||||
same file `:124-244`). The frontend mirror is `Workspace` in `apps/web/src/lib/types.ts:22-40`
|
||||
(a DIFFERENT, lossy shape — see delta in §(e)).
|
||||
|
||||
PRD §15.3 target: `WorkspaceConfigV2` (PRD lines 961-985).
|
||||
|
||||
| PRD V2 field | Present in current `WorkspaceConfig`? | Notes / source |
|
||||
|---|---|---|
|
||||
| `id` | ✅ present | `:6` |
|
||||
| `name` | ✅ present | `:7` |
|
||||
| `description` | ❌ **MISSING** | not in config; would be new persisted field |
|
||||
| `type` (`WorkspaceType`) | ❌ **MISSING** | no workspace-type concept; only `group` (free string) + `templateId` exist (`:8`, `:15`) |
|
||||
| `group` | ✅ present | `:8` |
|
||||
| `icon` | ✅ present | `:9` |
|
||||
| `status` (`active`/`paused`/`archived`) | ❌ **MISSING** | no lifecycle status field anywhere in config |
|
||||
| `model` | ✅ present | `:10` |
|
||||
| `personaId` | ✅ present | `:13` |
|
||||
| `templateId` | ✅ present | `:15` |
|
||||
| `tools` | ✅ present | `:16` |
|
||||
| `skills` | ✅ present | `:17` |
|
||||
| `agentIds` | ❌ **MISSING** | no agent-membership array on workspace |
|
||||
| `connectorIds` | ❌ **MISSING** | connectors are global (`/api/connectors`), not workspace-scoped in config |
|
||||
| `mcpIds` | ❌ **MISSING** | MCPs tracked via `install_audit` / marketplace, not on workspace config |
|
||||
| `storageType` | ✅ present | `:22` (`'virtual' \| 'local' \| 'team'`) — matches V2 exactly |
|
||||
| `storagePath` | ✅ present | `:24` |
|
||||
| `teamId` | ✅ present | `:31` |
|
||||
| `teamRole` (`owner/admin/member/viewer`) | ✅ present | `:35` — matches V2 union exactly |
|
||||
| `riskLevel` (`minimal/limited/high-risk/unacceptable`) | ✅ present | `:55` (`AIActRiskLevel`, defined `:3`) — matches V2 union exactly |
|
||||
| `created` | ✅ present | `:27` (ISO string) |
|
||||
| `updatedAt` | ❌ **MISSING** | `update()` overwrites `workspace.json` but stamps NO `updatedAt` (`:222-234`). Only `riskClassifiedAt` is auto-stamped on risk change (`:226-229`). |
|
||||
| `lastActiveAt` | ❌ **MISSING** | not persisted. Frontend `Workspace.lastActive` (`apps/web/src/lib/types.ts:32`) is DERIVED at read time from session-file mtimes / frame `created_at` (see `workspace-context.ts:375-387` legacy path), never written back to config. |
|
||||
|
||||
**Extra current fields NOT in PRD V2 (keep — do not drop):** `personality` (`:11`),
|
||||
`team` (legacy nullable string, `:18`), `storageConfig` (`:26`), `teamServerUrl`/`teamUserId`
|
||||
(`:33`,`:37`), `budget` (`:41`), `tone` (`:45`), `optimizationEnabled`/`optimizationBudget`
|
||||
(`:49`,`:51`), `riskClassifiedAt` (`:57`).
|
||||
|
||||
**Migration verdict:** All 7 missing V2 fields (`description`, `type`, `status`, `agentIds`,
|
||||
`connectorIds`, `mcpIds`, `updatedAt`, `lastActiveAt`) live in a JSON file (`workspace.json`),
|
||||
NOT in SQLite — so there is **no DB migration**. They are pure additive optional fields on the
|
||||
`WorkspaceConfig` interface + `CreateWorkspaceOptions` (`workspace-manager.ts:60-95`), plus two
|
||||
write-side touches: stamp `updatedAt` in `update()` (`:222`) and stamp `lastActiveAt` from the
|
||||
agent loop / chat route. `type` and `status` need defaults for the ~existing workspaces
|
||||
(`type` derivable from `templateId`/`group`; `status` defaults `'active'`).
|
||||
|
||||
---
|
||||
|
||||
## (b) Workspace-state builder outputs vs Home Cockpit + Workspace Desktop needs
|
||||
|
||||
**Builders (two layers):**
|
||||
- `buildWorkspaceState()` → `WorkspaceState` — `packages/server/src/local/workspace-state.ts:234-311`.
|
||||
Outputs (interface `:38-55`): `active`, `openQuestions`, `pending`, `blocked`, `completed`,
|
||||
`stale`, `recentDecisions`, `nextActions`. Each is `StateItem[]` (`:30-36`:
|
||||
`content / freshness('fresh'|'aging'|'stale') / source('memory'|'session'|'awareness') /
|
||||
sourceId / dateLastTouched`), except `nextActions: string[]`.
|
||||
- `buildWorkspaceNowBlock()` → `WorkspaceNowBlock` — `packages/server/src/local/routes/workspace-context.ts:191-404`.
|
||||
Wraps `WorkspaceState` for backward-compat (`:14-29`): `workspaceName`, `summary`,
|
||||
`recentDecisions[]`, `activeThreads[]`, `progressItems[]`, `nextActions[]`, `greeting`,
|
||||
`pendingTasks[]`, `upcomingSchedules[]`, plus the raw `structuredState`.
|
||||
|
||||
**Data sources:** memory frames (`memory_frames`, via `MindDB`), session JSONL logs
|
||||
(`extractProgressItems`/`extractOpenQuestions`/`classifyThreads` from `routes/sessions.js`,
|
||||
imported `workspace-state.ts:16-23`), awareness layer (`awareness` table,
|
||||
`extractAwarenessItems` `:122-138`), and cron schedules (`buildUpcomingSchedules`
|
||||
`workspace-context.ts:169-187`). Freshness is timestamp-derived, not type-derived (`:63-72`).
|
||||
|
||||
### Coverage vs PRD §12.1 Home Cockpit (PRD lines 384-393)
|
||||
|
||||
| Home Cockpit FR | Backed by current builder? | Gap |
|
||||
|---|---|---|
|
||||
| Greeting + name + date/time | Partial — `greeting` exists (`buildTimeAwareGreeting` `workspace-context.ts:119-152`) | Greeting is workspace-scoped + time/inactivity-based; carries NO user name (identity name lives in `identity` table, not threaded in). Home is cross-workspace; builder is single-workspace. |
|
||||
| Active/recent workspaces ranked by recency+priority | ❌ **MISSING** | Builder is **per-workspace**. No cross-workspace ranking aggregator exists. Home needs a NEW `GET /api/home/briefing` that fans out over `WorkspaceManager.list()` and ranks. |
|
||||
| Overnight summary (memories consolidated, artifacts created, automations completed, failures) | ❌ **MISSING** | No "overnight"/time-windowed delta. `completed` exists but is session-derived, not a since-last-login diff. No artifact or automation counters. PRD §16.1 `GET /api/home/overnight` is net-new. |
|
||||
| Upcoming meetings/events/tasks | Partial | `upcomingSchedules` (cron only, `:169-187`) + `pendingTasks` (`:158-163`). No calendar/meeting source. |
|
||||
| Suggested next actions | ✅ present | `nextActions` (`deriveNextActions` `workspace-state.ts:182-218`) — but per-workspace, not blended cross-workspace. |
|
||||
| Quick capture (note/task/link/file) | ❌ **MISSING** | No capture endpoint. PRD §16.1 `POST /api/quick-capture` is net-new (can write to `memory_frames` + `awareness`). |
|
||||
|
||||
### Coverage vs PRD §12.2 Workspace Desktop (PRD lines 423-429)
|
||||
|
||||
| Workspace Desktop need | Backed? | Gap |
|
||||
|---|---|---|
|
||||
| Header: name, **type**, **status**, team/avatars, share | Partial | name/team present; `type`+`status` are the missing `WorkspaceConfigV2` fields (§a). |
|
||||
| Tabs: Overview/Chat/Research/Artifacts/Memory/Tasks/Timeline/Settings | Partial | Overview = `WorkspaceState`; Memory = `/api/memory/frames`; Timeline = `ai_interactions`/`execution_traces`; **Artifacts has no backing entity at all** (see §e). Tasks ≈ `pending`/`blocked` StateItems + `awareness` (no first-class task store locally). |
|
||||
| Canvas widgets: chat, key artifacts, tasks, memory highlights, research, recent activity | Partial | memory highlights = `recentDecisions`/frames; recent activity = `active`/`activeThreads`; **artifacts widget unbacked**; "research overview" unbacked. |
|
||||
| Right panel: info, members, last activity, quick actions | Partial | last activity derivable; members from `/api/team/members`; "last activity" needs `lastActiveAt` (§a missing). |
|
||||
| Status bar: agents running, automations active, MCPs connected | Partial | agents via `/api/fleet`; MCPs connected derivable from `install_audit`/connectors; automations = cron. No single aggregate. |
|
||||
|
||||
**Verdict:** The per-workspace builder is a strong seed for **Workspace Desktop Overview** and
|
||||
maps cleanly to `GET /api/workspaces/:id/state` (PRD §16.2 — note: route does NOT exist yet;
|
||||
only `/api/workspaces/:id/context` exists, `workspaces.ts:311`). **Home Cockpit needs a NEW
|
||||
cross-workspace aggregation layer** (`/api/home/briefing`, `/api/home/overnight`,
|
||||
`/api/quick-capture` — all net-new) that fans the existing single-workspace builder over
|
||||
`WorkspaceManager.list()` and adds overnight-delta + quick-capture write paths.
|
||||
|
||||
---
|
||||
|
||||
## (c) Mind schema tables & Memory provenance/confidence (PRD §15.4)
|
||||
|
||||
**Schema:** `packages/hive-mind-core/src/mind/schema.ts` (`SCHEMA_VERSION = '1'`, `:1`). Tables:
|
||||
`meta`, `identity` (`:11`), `awareness` (`:24`), `sessions` (`:35`), **`memory_frames`** (`:47`),
|
||||
`memory_frames_fts` (`:68`), `memory_frames_vec` (vec0 1024-d, `VEC_TABLE_SQL :261`),
|
||||
`knowledge_entities` (`:75`), `knowledge_relations` (`:88`), `improvement_signals` (`:103`),
|
||||
`install_audit` (`:119`), `procedures` (`:141`), `ai_interactions` (`:155`),
|
||||
`execution_traces` (`:199`), `evolution_runs` (`:220`), `harvest_sources` (`:246`).
|
||||
|
||||
**`memory_frames` columns** (`:47-62`): `id, frame_type('I'|'P'|'B'), gop_id, t, base_frame_id,
|
||||
content, importance(critical/important/normal/temporary/deprecated), source(user_stated/
|
||||
tool_verified/agent_inferred/import/system), access_count, created_at, last_accessed`.
|
||||
TS mirror: `MemoryFrame` in `mind/frames.ts:23-35` (note: `FrameSource` union in TS `:21` is
|
||||
WIDER — adds `personal/workspace/team_sync` — than the DB CHECK; a latent drift).
|
||||
|
||||
### PRD §15.4 field-by-field (PRD lines 990-1013)
|
||||
|
||||
| PRD memory field | Backing in `memory_frames`? | Gap / where it fits |
|
||||
|---|---|---|
|
||||
| `id` | ✅ `id` | — |
|
||||
| `kind` (`fact/decision/task/preference/strategy/learning/goal/entity`) | ❌ **MISSING** | Only `frame_type` (I/P/B) exists — an orthogonal axis. PRD `MemoryKind` is currently DERIVED heuristically (LIKE-matching content for "decision" in `workspace-state.ts:82-111`). Needs a `kind` column OR metadata. |
|
||||
| `title` | ❌ **MISSING** | Frames are content-only; title is synthesized from first line (`workspace-state.ts:97-101`). |
|
||||
| `content` | ✅ `content` | — |
|
||||
| `scope` (`personal/workspace/team/organization`) | ⚠️ **IMPLICIT** | Not a column. Scope is encoded by WHICH `.mind` file the frame lives in (personal.mind vs workspace.mind), surfaced as `_mind` tag in the API (`memory.ts:200,209`). No `team`/`organization` scope on a single frame. |
|
||||
| `workspaceId` | ⚠️ **IMPLICIT** | Per-file, not per-row (frames live in that workspace's `.mind`). |
|
||||
| `teamId` | ❌ **MISSING** | team frames are a separate sync path; no `teamId` on frame. |
|
||||
| `source` (origin label) | ✅ `source` | `:56` — but enum is provenance-CLASS (`user_stated`/`import`/...), not a source id/url. |
|
||||
| `sourceId` | ❌ **MISSING** | Harvest provenance is embedded as a text prefix `[hm session:… src:…]` in `content` (`frames.ts:51-62`, `stripHmPrefix`), NOT a structured column. |
|
||||
| `sourceUrl/path` | ❌ **MISSING** | Same — only in the text prefix / not structured. (`harvest_sources.source_path` exists at source-level `:251`, not per-frame.) |
|
||||
| `confidence` (0-100) | ❌ **MISSING on frames** | NO confidence column on `memory_frames`. (Confidence DOES exist on `knowledge_relations.confidence REAL` `:93` — graph edges only.) Closest frame proxy is `importance` (categorical) + `source` (trust class). |
|
||||
| `importance` | ✅ `importance` | `:54` — categorical, not numeric. |
|
||||
| `evidence[]` | ❌ **MISSING** | No evidence list. Could map to FTS hits / `base_frame_id` lineage (`:52`) / related entities, but no first-class field. |
|
||||
| `tags[]` | ❌ **MISSING** | No tags column. |
|
||||
| `relatedMemoryIds[]` | ⚠️ Partial | `base_frame_id` (`:52`) gives I→P lineage only; no general relation. |
|
||||
| `relatedArtifactIds[]` | ❌ **MISSING** | No artifact entity exists (§e). |
|
||||
| `createdAt` | ✅ `created_at` | — |
|
||||
| `updatedAt` | ❌ **MISSING** | Frames are append-only (P-frames supersede); `last_accessed` (`:60`) is access-time, not edit-time. |
|
||||
| `lastAccessedAt` | ✅ `last_accessed` | `:60` |
|
||||
| `status` | ⚠️ Partial | `importance='deprecated'` (`:55`) ≈ archived/deprecated; no explicit `active/conflict/trash` status. PRD §12.4 Memory tabs need Active/Trash + conflict/low-confidence states (PRD 498,504-513). |
|
||||
|
||||
### Metadata vs migration verdict
|
||||
|
||||
**Critical:** `memory_frames` has **NO `metadata` column** (unlike `awareness.metadata`,
|
||||
`knowledge_entities.properties`, `knowledge_relations.properties`, `improvement_signals.metadata`,
|
||||
`evolution_runs.artifacts_json` — all of which have a JSON blob). PRD §15.4's "use `metadata`
|
||||
initially" assumes a metadata column that does not exist on frames today.
|
||||
|
||||
The migration runner already does idempotent additive `ADD COLUMN` on `memory_frames`
|
||||
(it added `source` — `mind/db.ts:116-124`, pattern: `pragma_table_info` guard + `ALTER TABLE …
|
||||
ADD COLUMN`). So the lowest-risk path is one migration adding a single nullable
|
||||
`metadata TEXT NOT NULL DEFAULT '{}'` column to `memory_frames`, storing
|
||||
`{kind, title, scope, sourceId, sourceUrl, confidence, tags, evidence, relatedMemoryIds, status}`
|
||||
as JSON. This avoids touching the FTS/vec virtual tables and the IPB scoring logic.
|
||||
PRD §15.4 itself endorses metadata-first, explicit-fields-later (PRD line 1013). If
|
||||
`confidence` becomes a primary query/filter axis (PRD §12.4 "filter by confidence",
|
||||
"low-confidence surfaced for review"), promote `confidence REAL` to a real column in a later
|
||||
migration (precedent: same ADD-COLUMN pattern) so it's indexable.
|
||||
|
||||
---
|
||||
|
||||
## (d) install-audit — capabilities for Extend governance
|
||||
|
||||
**Store:** `InstallAuditStore` in `packages/core/src/install-audit.ts` (operates on `.mind`).
|
||||
DDL duplicated in two places that MUST stay in sync (`install-audit.ts:54-74` and
|
||||
`schema.ts:119-138` — comment warns of prior drift crash, `schema.ts:122-126`).
|
||||
|
||||
**Audit entry shape** (`InstallAuditEntry` `:24-37`):
|
||||
`id, timestamp, capability_name, capability_type, source, version, risk_level, trust_source,
|
||||
approval_class, action, initiator, detail`.
|
||||
|
||||
**Enums (governance-relevant):**
|
||||
- `AuditCapabilityType` (`:22`): `native | skill | plugin | mcp | connector | marketplace` —
|
||||
covers the entire PRD Extend layer (Connectors/MCPs/Marketplace/Skills).
|
||||
- `AuditAction` (`:15`): `proposed | approved | installed | rejected | failed | blocked`.
|
||||
- `AuditTrustSource` (`:17-19`): `builtin | starter_pack | local_user | third_party_verified |
|
||||
third_party_unverified | unknown | security-gate`.
|
||||
- `AuditApprovalClass` (`:20`): `standard | elevated | critical | blocked`.
|
||||
- `AuditInitiator` (`:21`): `agent | user | system`.
|
||||
- `AuditRiskLevel` (TS `:16`): `low | medium | high | critical`.
|
||||
|
||||
**Read API (in-store, not yet HTTP):** `getByCapability()` (`:125`), `getByAction()` (`:132`),
|
||||
`getRecent(limit)` (`:139`), `getAll()` (`:146`).
|
||||
|
||||
**Write path (live):** the marketplace install route calls `fastify.auditStore.record(...)` on
|
||||
every SecurityGate verdict (CRITICAL→403, HIGH gated, MEDIUM/LOW logged) —
|
||||
`packages/server/src/local/routes/marketplace.ts:224-319`. So an audit trail is already being
|
||||
written for installs.
|
||||
|
||||
**Gaps for Extend governance UI:**
|
||||
1. **No HTTP endpoint surfaces the audit trail.** `getRecent`/`getByCapability` have no route
|
||||
(grep over `packages/server/src/local/routes` finds writes only). The Extend governance view
|
||||
(who installed what, when, risk, trust, approval) needs a NEW read route, e.g.
|
||||
`GET /api/extend/audit` — there is no PRD §16 endpoint for this; it's an implied addition
|
||||
to §16.9.
|
||||
2. **`risk_level` enum drift (latent bug, not session-induced).** TS `AuditRiskLevel` includes
|
||||
`'critical'` (`install-audit.ts:16`) but BOTH DDL CHECK constraints only allow
|
||||
`('low','medium','high')` (`install-audit.ts:65` and `schema.ts:130`). A `record()` with
|
||||
`riskLevel:'critical'` would throw a CHECK violation. The marketplace route sidesteps this by
|
||||
mapping CRITICAL severity to `riskLevel:'high'` + `approvalClass:'blocked'` — but any future
|
||||
caller passing `'critical'` crashes. Flag for the plan.
|
||||
3. **Audit is per-`.mind` (per-workspace).** Governance across all installs (the Extend layer is
|
||||
global) requires either querying personal.mind or aggregating — confirm which `.mind` the
|
||||
`auditStore` decorator binds to.
|
||||
|
||||
---
|
||||
|
||||
## (e) Frontend types delta vs PRD §15.2-15.6
|
||||
|
||||
**Frontend types:** `apps/web/src/lib/types.ts`. Shared/server types: `packages/shared/src/types.ts`.
|
||||
|
||||
### PRD §15.2 target literal unions (PRD 944-954) — NONE currently exist in frontend
|
||||
|
||||
| PRD union | In `apps/web/src/lib/types.ts`? | Closest existing |
|
||||
|---|---|---|
|
||||
| `WorkspaceType` | ❌ **MISSING** | none |
|
||||
| `Scope` (`personal/workspace/team/organization`) | ❌ **MISSING** | `_mind` informal tag only |
|
||||
| `Confidence` (0-100) | ❌ **MISSING** | `MemoryFrame.importance: number` (`:124`) — different axis |
|
||||
| `MemoryKind` | ❌ **MISSING** | `MemoryFrame.type` (`:120`: `fact/event/insight/decision/task/entity`) — OVERLAPS but mismatched (FE has `event`/`insight`; PRD has `preference`/`strategy`/`learning`/`goal`) |
|
||||
| `ArtifactKind` | ❌ **MISSING** | none — no Artifact type at all |
|
||||
| `AgentType` | ❌ **MISSING** | none (`AgentDef` in shared has no `type`) |
|
||||
| `AutonomyLevel` | ❌ **MISSING** | none in FE types (autonomy exists conceptually in agent runtime) |
|
||||
| `ExtensionType` | ❌ **MISSING** | none |
|
||||
|
||||
### §15.2 Frontend `Workspace` (types.ts:22-40) vs `WorkspaceConfigV2`
|
||||
|
||||
The FE `Workspace` is a **lossy projection** distinct from the persisted `WorkspaceConfig`:
|
||||
has `persona` (string, vs config `personaId`), `hue`/`memoryCount`/`sessionCount`/`lastActive`/
|
||||
`health`/`budget{used,limit}`/`shared` (DERIVED display fields, not persisted), but LACKS
|
||||
`type`, `status`, `description`, `agentIds`, `connectorIds`, `mcpIds`, `updatedAt`. To reach V2
|
||||
the FE type needs the same 7 additions as §(a) plus alignment of `persona`→`personaId`.
|
||||
|
||||
### §15.4 Memory — FE `MemoryFrame` (types.ts:118-127)
|
||||
|
||||
FE shape: `id, type(MemoryKind-ish), title, content, importance(number), timestamp, workspaceId,
|
||||
metadata?`. Closer to PRD than the DB row (it HAS `title`, `metadata`, `workspaceId`), but
|
||||
MISSING: `kind` (uses `type`), `scope`, `teamId`, `source`, `sourceId`, `sourceUrl`, `confidence`,
|
||||
`evidence[]`, `tags[]`, `relatedMemoryIds[]`, `relatedArtifactIds[]`, `status`, `updatedAt`,
|
||||
`lastAccessedAt`. Note the FE `MemoryFrame` does NOT match what `/api/memory/frames` returns
|
||||
(server returns the raw DB row shape + `_mind`, normalized via `normalizeFrame`,
|
||||
`memory.ts:230`) — a real FE/BE contract mismatch to reconcile.
|
||||
|
||||
### §15.5 Agents — `AgentDef` (`packages/shared/src/types.ts:36-47`)
|
||||
|
||||
Has: `id, userId, teamId, name, role, systemPrompt, model, tools, config, createdAt`.
|
||||
MISSING vs PRD §15.5: `type(AgentType)`, `goal`, `description`, `personaId`, `autonomyLevel`,
|
||||
`workspaceIds`, `memoryScopes`, `skillIds`, `connectorIds`, `mcpIds`, `permissions`, `status`,
|
||||
`lastRunAt`, `successRate`. (`successRate` partially exists on `procedures.success_rate`
|
||||
`schema.ts:147` and per-trace outcome in `execution_traces` `schema.ts:206` — derivable.)
|
||||
FE also has a thin `Persona` (`types.ts:256-272`) and `AgentStatus` (`:249-254`) but no
|
||||
full Agent entity.
|
||||
|
||||
### §15.6 Artifacts — **NO backing entity anywhere**
|
||||
|
||||
- No `Artifact` type in `apps/web/src/lib/types.ts` (closest is `FileEntry` `:42-50`:
|
||||
`name/path/type/size/mimeType/modifiedAt/createdAt` — a raw filesystem entry, not an outcome
|
||||
object with relations).
|
||||
- No artifacts table in `schema.ts`. No `/api/artifacts*` routes (PRD §16.6 is entirely net-new).
|
||||
- ALL of PRD §15.6 (`kind, status, previewUrl, relatedMemoryIds, relatedSessionIds,
|
||||
relatedTaskIds, relatedAgentIds`, etc.) is greenfield. This is the single largest entity gap.
|
||||
|
||||
---
|
||||
|
||||
## Cross-cutting: API contract delta (PRD §16 vs live routes)
|
||||
|
||||
Grounded against `packages/server/src/local/routes/*`:
|
||||
|
||||
- **Exists, reusable:** `GET /api/workspaces` (`workspaces.ts:101`), `POST /api/workspaces`
|
||||
(`:135`), `GET /api/workspaces/:id/context` (`:311`); `/api/memory/frames` GET/POST/PATCH/DELETE
|
||||
(`memory.ts:188,237,448,551`), `/api/memory/search` (`:120`), `/api/memory/stats` (`:391`);
|
||||
`/api/harvest/preview|commit|sources` (`harvest.ts:221,243,538`); marketplace + connectors +
|
||||
personas + compliance + fleet + workflows routes.
|
||||
- **PRD §16 endpoints that DO NOT EXIST (net-new):** `/api/home/briefing`, `/api/quick-capture`,
|
||||
`/api/home/overnight` (§16.1); `/api/workspaces/:id/state`, `/api/workspaces/:id/activity`
|
||||
(§16.2 — only `/context` exists); `/api/command/*` (§16.3); the PRD's `/api/memory` (current is
|
||||
`/api/memory/frames`), `/api/memory/merge`, `/api/memory/graph`, `/api/memory/:id/archive`
|
||||
(§16.4); ALL `/api/artifacts/*` (§16.6); `/api/agents/*` CRUD+run (§16.7); most `/api/skills/*`
|
||||
and `/api/automations/*`; and the missing **install-audit read route** for Extend governance (§d).
|
||||
|
||||
These are the full-stack hooks the plan must scope (locked SCOPE: net-new + extended backend APIs).
|
||||
Reference in New Issue
Block a user