Last updated: 2026-06-13
See also: ARCHITECTURE_OVERVIEW.md (AI agent deep-dive), docs/labs/README.md
flowchart TD
subgraph clients [Clients]
Web["Web Client (Vue 3)"]
Desktop["Desktop (Electron)"]
Teams["M365 / Teams"]
end
subgraph backend [Backend - AdonisJS]
API["REST API / Controllers"]
Mgr["Managers"]
Svc["Services"]
Agent["AI Agent Layer"]
MCP["MCP Service"]
end
subgraph data [Data & External]
DB[("PostgreSQL / PGlite / SQLite")]
VS["Vector Store (OpenAI / Azure)"]
Blob["Azure Blob / Drive Providers"]
LLM["LLM Providers"]
Ext["SaaS APIs via MCP"]
end
subgraph async [Async]
AF["Azure Functions"]
SB["Service Bus"]
end
Web -->|REST / SSE| API
Desktop -->|REST + IPC| API
Teams --> API
API --> Mgr --> Svc
API --> Agent
Agent --> MCP --> Ext
Svc --> DB
Svc --> VS
Svc --> Blob
Agent --> LLM
AF --> SB --> API
AdonisJS follows a consistent layering convention:
| Layer | Location | Responsibility |
|---|---|---|
| Routes | start/routes.ts |
HTTP mapping, lazy controller imports |
| Controllers | app/controllers/ |
Request validation, auth context, HTTP responses |
| Managers | app/managers/ |
Domain logic, orchestration across models |
| Services | app/services/ |
Cross-cutting, integrations, AI, storage |
| Models | app/models/ |
Lucid ORM entities |
| Providers | app/providers/ |
Boot-time initialization |
| Validators | app/validators/ |
VineJS request schemas |
| Config | config/ |
JSON catalogs + TypeScript config modules |
Path aliases (from socius_backend/package.json):
#controllers/* #services/* #models/* #managers/* #labs/*
Entry point: app/services/ai/agent_service.ts
User prompt
→ AgentService.processAgentRequest()
→ LangChain agent / LangGraph state machine
→ ToolRegistry (50+ tools)
→ Orchestrators (ChatOrchestrator, DocQAOrchestrator, AIOrchestrator)
→ StreamManager (SSE to client)
| Category | Examples | Path |
|---|---|---|
| Content | content_create, content_read, content_update |
app/services/ai/agent/tools/content/ |
| Document CRUD | Legacy + new content tools | tools/ |
| Stakeholder | Review, simulation | tools/stakeholder/ |
| MCP | Per-server LangChain wrappers | agent/mcp/MCPToolManager.ts |
| Skills | fetch_skill |
tools/FetchSkillTool.ts |
| Vector | vectorStoreSearchTool |
tools/ |
| Orchestrator | Use case |
|---|---|
ChatOrchestrator |
General project chat |
DocQAOrchestrator |
Document Q&A with conversation history |
AIOrchestrator |
Directive / scheduled execution |
Prompt composition: PromptComposer, PromptManager
main.ts
→ Vuetify theme (Hypermat)
→ Pinia stores
→ Vue Router (lazy routes + lab routes)
→ App.vue
WorkSpaceLayout
→ Project tree / document viewer / ChatInterface
→ Pinia: projectModule, chatModule, docModule, streamingModule
| Area | Path | Notes |
|---|---|---|
| Views | src/views/ |
Page-level routes |
| Components | src/components/ |
~254 Vue SFCs, domain-grouped |
| Composables | src/composables/ |
Shared reactive logic |
| Store | src/store/ |
13 Pinia modules |
| Auth | src/auth/ |
MSAL, M365 SSO |
| Labs | src/labs/ |
Experimental UI surfaces |
Alias: @/ → src/
Dev proxy: Vite forwards /api → localhost:3333
Electron shell loads the hosted web client URL. Adds:
| Module | Path | Role |
|---|---|---|
| Local MCP | src/main/local-mcp.ts |
Bundled + subprocess + HTTP MCP |
| OAuth | src/main/oauth.ts |
Desktop token refresh |
| IPC | src/main/ipc.ts |
Renderer ↔ main bridge |
| CLI | src/main/cli/dotted-mcp.ts |
Bundled MCP server shell |
Local MCP URLs use dotted:// or dotted-local:// schemes proxied through backend.
erDiagram
User ||--o{ Project : owns
Tenant ||--o{ Project : scopes
Project ||--o{ Doc : contains
Project ||--o{ Stakeholder : has
Project ||--o{ McpServer : connects
Project ||--o{ Directive : schedules
Doc ||--o{ DocHistory : versions
User ||--o{ Subscription : billing
Tenant ||--o{ TenantDomain : domains
Key model files: Project.ts, Doc.ts, Stakeholder.ts, McpServer.ts, Directive.ts, Subscription.ts, Tenant.ts
Documents are file-backed (not primarily in DB body column):
- Upload → temp storage
DocManagerpersists to blob/local storage- MIME type determines viewer (TipTap HTML, Univer spreadsheet, Excalidraw, proto iframe)
- Vector store indexes for semantic search
- Version history via
DocumentVersionService
Conversation history stored as JSON files with INTERMEDIATE lifecycle tag.
config/mcp_servers.json (catalog)
→ McpServerCatalog / CatalogRegistry
→ User/tenant MCPServer records (OAuth tokens)
→ McpService (connect, list tools, call)
→ MCPToolManager (LangChain StructuredTool wrappers)
→ Agent tool selection
Built-in MCP server implementations: app/services/mcp_servers/ (Jira, Slack, Gmail, Teams, etc.)
External agents connect via Dotted's hosted MCP connector (rollup + assistant tools at workspace level; project-scoped tokens expose fuller surface).
Labs live in app/labs/<slug>/ + src/labs/<slug>/. One door rule:
Lab code → DottedPlatformService (only allowed core import)
ESLint enforces boundary in socius_backend/eslint.config.js. Exception: Azure Function triggers must live in azure_functions/ package.
.github/workflows/deploy.yml:
- Backend: unit, functional, e2e tests; ai_e2e on label
- Self-hosted deploy to Azure
- Frontend: Cypress on Chrome
| Deviation | Details | Status |
|---|---|---|
| Dual UI frameworks | Vuetify 3 + PrimeVue 4 coexist | Documented in ui-rules |
| React in Vue app | Excalidraw embed requires React | Vite alias dedupes instance |
| Vector store vs direct context | NEW_APPROACHES.md proposes replacement |
Proposal only; vector store still active |
| Labs Azure Functions | Triggers outside lab tree | Documented exception |
| Package naming | Backend "hello-world", frontend "socious_web_client" |
Legacy scaffold typos |
| Customer content in monorepo | customers/gaia/ blueprints |
Intentional for delivery |