Compare commits

...

15 Commits

Author SHA1 Message Date
Jarvis
31008ef7ff fix: update Gitea org references from mosaic/ to mosaicstack/
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
- Update all package.json repo URLs (mosaic/mosaic-stack → mosaicstack/mosaic-stack)
- Update npm registry URLs (/api/packages/mosaic/npm → /api/packages/mosaicstack/npm)
- Update woodpecker publish destinations
- Update tools/install.sh registry and repo base URLs
2026-04-04 22:31:20 -05:00
621ab260c0 fix(mosaic): resumable gateway install + prominent admin token (#393)
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/manual/publish Pipeline failed
ci/woodpecker/manual/ci Pipeline failed
2026-04-05 03:19:07 +00:00
2b1840214e Merge pull request 'fix: rename @mosaic/* packages to @mosaicstack/*' (#392) from fix/rename-mosaic-scope-391 into main
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 03:11:55 +00:00
Jarvis
5cfccc2ead fix(mosaic): remove unused hasUpdate variable in formatAllPackagesTable
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Fixes lint error:
@typescript-eslint/no-unused-vars on hasUpdate
2026-04-04 22:01:01 -05:00
Jarvis
774b76447d fix: rename all packages from @mosaic/* to @mosaicstack/*
Some checks failed
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
- Updated all package.json name fields and dependency references
- Updated all TypeScript/JavaScript imports
- Updated .woodpecker/publish.yml filters and registry paths
- Updated tools/install.sh scope default
- Updated .npmrc registry paths (worktree + host)
- Enhanced update-checker.ts with checkForAllUpdates() multi-package support
- Updated CLI update command to show table of all packages
- Added KNOWN_PACKAGES, formatAllPackagesTable, getInstallAllCommand
- Marked checkForUpdate() with @deprecated JSDoc

Closes #391
2026-04-04 21:43:23 -05:00
80994bdc8e fix(packages): bump db/memory/queue for PGlite + adapter factories (#389)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 02:20:23 +00:00
2e31626f87 fix: simplify updater to @mosaic/mosaic only, add explicit tea repo/login flags (#388)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 02:09:23 +00:00
255ba46a4d fix(packages): republish @mosaic/config and bump dependents (#386)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 01:56:57 +00:00
10285933a0 fix: retarget updater to @mosaic/mosaic (#384)
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 01:52:30 +00:00
543388e18b fix(mosaic): resolve framework scripts via import.meta.url (#385)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Fixes #383 — resolveTool now uses fileURLToPath(import.meta.url). Adds package.json/framework subpath exports. Bumps @mosaic/mosaic to 0.0.18.
2026-04-05 01:41:46 +00:00
07a1f5d594 Merge pull request 'feat(mosaic): merge @mosaic/cli into @mosaic/mosaic' (#381) from fix/merge-cli-into-mosaic into main
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 01:11:33 +00:00
Jarvis
c6fc090c98 feat(mosaic): merge @mosaic/cli into @mosaic/mosaic
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
@mosaic/mosaic is now the single package providing both:
- 'mosaic' binary (CLI: yolo, coord, prdy, tui, gateway, etc.)
- 'mosaic-wizard' binary (installation wizard)

Changes:
- Move packages/cli/src/* into packages/mosaic/src/
- Convert dynamic @mosaic/mosaic imports to static relative imports
- Add CLI deps (ink, react, socket.io-client, @mosaic/config) to mosaic
- Add jsx: react-jsx to mosaic's tsconfig
- Exclude packages/cli from workspace (pnpm-workspace.yaml)
- Update install.sh to install @mosaic/mosaic instead of @mosaic/cli
- Bump version to 0.0.17

This eliminates the circular dependency between @mosaic/cli and
@mosaic/mosaic that was blocking the build graph.
2026-04-04 20:07:27 -05:00
9723b6b948 chore: bump @mosaic/cli and @mosaic/mosaic to 0.0.16 (#379)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 00:52:09 +00:00
c0d0fd44b7 refactor(storage): replace better-sqlite3 with PGlite adapter (#378)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 21:58:14 +00:00
30c0fb1308 fix: remediate npm deprecation warnings in @mosaic/gateway 0.0.3 (#377)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 21:03:54 +00:00
236 changed files with 9076 additions and 2004 deletions

2
.npmrc
View File

@@ -1 +1 @@
@mosaic:registry=https://git.mosaicstack.dev/api/packages/mosaic/npm/
@mosaicstack:registry=https://git.mosaicstack.dev/api/packages/mosaicstack/npm/

View File

@@ -59,7 +59,7 @@ steps:
sleep 1
done
# Run migrations (DATABASE_URL is set in environment above)
- pnpm --filter @mosaic/db run db:migrate
- pnpm --filter @mosaicstack/db run db:migrate
# Run all tests
- pnpm test
depends_on:

View File

@@ -33,13 +33,13 @@ steps:
- *enable_pnpm
# Configure auth for Gitea npm registry
- |
echo "//git.mosaicstack.dev/api/packages/mosaic/npm/:_authToken=$NPM_TOKEN" > ~/.npmrc
echo "@mosaic:registry=https://git.mosaicstack.dev/api/packages/mosaic/npm/" >> ~/.npmrc
echo "//git.mosaicstack.dev/api/packages/mosaicstack/npm/:_authToken=$NPM_TOKEN" > ~/.npmrc
echo "@mosaicstack:registry=https://git.mosaicstack.dev/api/packages/mosaicstack/npm/" >> ~/.npmrc
# Publish non-private packages to Gitea (--no-git-checks skips dirty/branch checks in CI)
# --filter excludes web (private)
- >
pnpm --filter "@mosaic/*"
--filter "!@mosaic/web"
pnpm --filter "@mosaicstack/*"
--filter "!@mosaicstack/web"
publish --no-git-checks --access public
|| echo "[publish] Some packages may already exist at this version — continuing"
depends_on:
@@ -74,12 +74,12 @@ steps:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"git.mosaicstack.dev\":{\"username\":\"$REGISTRY_USER\",\"password\":\"$REGISTRY_PASS\"}}}" > /kaniko/.docker/config.json
- |
DESTINATIONS="--destination git.mosaicstack.dev/mosaic/mosaic-stack/gateway:sha-${CI_COMMIT_SHA:0:7}"
DESTINATIONS="--destination git.mosaicstack.dev/mosaicstack/mosaic-stack/gateway:sha-${CI_COMMIT_SHA:0:7}"
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
DESTINATIONS="$DESTINATIONS --destination git.mosaicstack.dev/mosaic/mosaic-stack/gateway:latest"
DESTINATIONS="$DESTINATIONS --destination git.mosaicstack.dev/mosaicstack/mosaic-stack/gateway:latest"
fi
if [ -n "$CI_COMMIT_TAG" ]; then
DESTINATIONS="$DESTINATIONS --destination git.mosaicstack.dev/mosaic/mosaic-stack/gateway:$CI_COMMIT_TAG"
DESTINATIONS="$DESTINATIONS --destination git.mosaicstack.dev/mosaicstack/mosaic-stack/gateway:$CI_COMMIT_TAG"
fi
/kaniko/executor --context . --dockerfile docker/gateway.Dockerfile $DESTINATIONS
depends_on:
@@ -99,12 +99,12 @@ steps:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"git.mosaicstack.dev\":{\"username\":\"$REGISTRY_USER\",\"password\":\"$REGISTRY_PASS\"}}}" > /kaniko/.docker/config.json
- |
DESTINATIONS="--destination git.mosaicstack.dev/mosaic/mosaic-stack/web:sha-${CI_COMMIT_SHA:0:7}"
DESTINATIONS="--destination git.mosaicstack.dev/mosaicstack/mosaic-stack/web:sha-${CI_COMMIT_SHA:0:7}"
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
DESTINATIONS="$DESTINATIONS --destination git.mosaicstack.dev/mosaic/mosaic-stack/web:latest"
DESTINATIONS="$DESTINATIONS --destination git.mosaicstack.dev/mosaicstack/mosaic-stack/web:latest"
fi
if [ -n "$CI_COMMIT_TAG" ]; then
DESTINATIONS="$DESTINATIONS --destination git.mosaicstack.dev/mosaic/mosaic-stack/web:$CI_COMMIT_TAG"
DESTINATIONS="$DESTINATIONS --destination git.mosaicstack.dev/mosaicstack/mosaic-stack/web:$CI_COMMIT_TAG"
fi
/kaniko/executor --context . --dockerfile docker/web.Dockerfile $DESTINATIONS
depends_on:

View File

@@ -21,10 +21,10 @@ Mosaic Stack is a self-hosted, multi-user AI agent platform. TypeScript monorepo
| `apps/web` | Next.js dashboard | React 19, Tailwind |
| `packages/types` | Shared TypeScript contracts | class-validator |
| `packages/db` | Drizzle ORM schema + migrations | drizzle-orm, postgres |
| `packages/auth` | BetterAuth configuration | better-auth, @mosaic/db |
| `packages/brain` | Data layer (PG-backed) | @mosaic/db |
| `packages/auth` | BetterAuth configuration | better-auth, @mosaicstack/db |
| `packages/brain` | Data layer (PG-backed) | @mosaicstack/db |
| `packages/queue` | Valkey task queue + MCP | ioredis |
| `packages/coord` | Mission coordination | @mosaic/queue |
| `packages/coord` | Mission coordination | @mosaicstack/queue |
| `packages/cli` | Unified CLI + Pi TUI | Ink, Pi SDK |
| `plugins/discord` | Discord channel plugin | discord.js |
| `plugins/telegram` | Telegram channel plugin | Telegraf |
@@ -33,9 +33,9 @@ Mosaic Stack is a self-hosted, multi-user AI agent platform. TypeScript monorepo
1. Gateway is the single API surface — all clients connect through it
2. Pi SDK is ESM-only — gateway and CLI must use ESM
3. Socket.IO typed events defined in `@mosaic/types` enforce compile-time contracts
3. Socket.IO typed events defined in `@mosaicstack/types` enforce compile-time contracts
4. OTEL auto-instrumentation loads before NestJS bootstrap
5. BetterAuth manages auth tables; schema defined in `@mosaic/db`
5. BetterAuth manages auth tables; schema defined in `@mosaicstack/db`
6. Docker Compose provides PG (5433), Valkey (6380), OTEL Collector (4317/4318), Jaeger (16686)
7. Explicit `@Inject()` decorators required in NestJS (tsx/esbuild doesn't emit decorator metadata)

View File

@@ -26,13 +26,13 @@ pnpm test # Vitest (all packages)
pnpm build # Build all packages
# Database
pnpm --filter @mosaic/db db:push # Push schema to PG (dev)
pnpm --filter @mosaic/db db:generate # Generate migrations
pnpm --filter @mosaic/db db:migrate # Run migrations
pnpm --filter @mosaicstack/db db:push # Push schema to PG (dev)
pnpm --filter @mosaicstack/db db:generate # Generate migrations
pnpm --filter @mosaicstack/db db:migrate # Run migrations
# Dev
docker compose up -d # Start PG, Valkey, OTEL, Jaeger
pnpm --filter @mosaic/gateway exec tsx src/main.ts # Start gateway
pnpm --filter @mosaicstack/gateway exec tsx src/main.ts # Start gateway
```
## Conventions

View File

@@ -12,10 +12,10 @@ bash <(curl -fsSL https://git.mosaicstack.dev/mosaic/mosaic-stack/raw/branch/mai
This installs both components:
| Component | What | Where |
| --------------- | ----------------------------------------------------- | -------------------- |
| **Framework** | Bash launcher, guides, runtime configs, tools, skills | `~/.config/mosaic/` |
| **@mosaic/cli** | TUI, gateway client, wizard, auto-updater | `~/.npm-global/bin/` |
| Component | What | Where |
| -------------------- | ----------------------------------------------------- | -------------------- |
| **Framework** | Bash launcher, guides, runtime configs, tools, skills | `~/.config/mosaic/` |
| **@mosaicstack/cli** | TUI, gateway client, wizard, auto-updater | `~/.npm-global/bin/` |
After install, set up your agent identity:
@@ -26,7 +26,7 @@ mosaic init # Interactive wizard
### Requirements
- Node.js ≥ 20
- npm (for global @mosaic/cli install)
- npm (for global @mosaicstack/cli install)
- One or more runtimes: [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Codex](https://github.com/openai/codex), [OpenCode](https://opencode.ai), or [Pi](https://github.com/mariozechner/pi-coding-agent)
## Usage
@@ -86,7 +86,7 @@ docker compose up -d
pnpm install
# Run migrations
pnpm --filter @mosaic/db run db:migrate
pnpm --filter @mosaicstack/db run db:migrate
# Start all services in dev mode
pnpm dev
@@ -163,7 +163,7 @@ mosaic-stack/
- **Gateway is the single API surface** — all clients (TUI, web, Discord, Telegram) connect through it
- **ESM everywhere** — `"type": "module"`, `.js` extensions in imports, NodeNext resolution
- **Socket.IO typed events** — defined in `@mosaic/types`, enforced at compile time
- **Socket.IO typed events** — defined in `@mosaicstack/types`, enforced at compile time
- **OTEL auto-instrumentation** — loads before NestJS bootstrap
- **Explicit `@Inject()` decorators** — required since tsx/esbuild doesn't emit decorator metadata

View File

@@ -1,9 +1,9 @@
{
"name": "@mosaic/gateway",
"version": "0.0.2",
"name": "@mosaicstack/gateway",
"version": "0.0.6",
"repository": {
"type": "git",
"url": "https://git.mosaicstack.dev/mosaic/mosaic-stack.git",
"url": "https://git.mosaicstack.dev/mosaicstack/mosaic-stack.git",
"directory": "apps/gateway"
},
"type": "module",
@@ -15,7 +15,7 @@
"dist"
],
"publishConfig": {
"registry": "https://git.mosaicstack.dev/api/packages/mosaic/npm/",
"registry": "https://git.mosaicstack.dev/api/packages/mosaicstack/npm/",
"access": "public"
},
"scripts": {
@@ -28,28 +28,28 @@
"dependencies": {
"@anthropic-ai/sdk": "^0.80.0",
"@fastify/helmet": "^13.0.2",
"@mariozechner/pi-ai": "~0.57.1",
"@mariozechner/pi-coding-agent": "~0.57.1",
"@mariozechner/pi-ai": "^0.65.0",
"@mariozechner/pi-coding-agent": "^0.65.0",
"@modelcontextprotocol/sdk": "^1.27.1",
"@mosaic/auth": "workspace:^",
"@mosaic/brain": "workspace:^",
"@mosaic/config": "workspace:^",
"@mosaic/coord": "workspace:^",
"@mosaic/db": "workspace:^",
"@mosaic/discord-plugin": "workspace:^",
"@mosaic/log": "workspace:^",
"@mosaic/memory": "workspace:^",
"@mosaic/queue": "workspace:^",
"@mosaic/storage": "workspace:^",
"@mosaic/telegram-plugin": "workspace:^",
"@mosaic/types": "workspace:^",
"@mosaicstack/auth": "workspace:^",
"@mosaicstack/brain": "workspace:^",
"@mosaicstack/config": "workspace:^",
"@mosaicstack/coord": "workspace:^",
"@mosaicstack/db": "workspace:^",
"@mosaicstack/discord-plugin": "workspace:^",
"@mosaicstack/log": "workspace:^",
"@mosaicstack/memory": "workspace:^",
"@mosaicstack/queue": "workspace:^",
"@mosaicstack/storage": "workspace:^",
"@mosaicstack/telegram-plugin": "workspace:^",
"@mosaicstack/types": "workspace:^",
"@nestjs/common": "^11.0.0",
"@nestjs/core": "^11.0.0",
"@nestjs/platform-fastify": "^11.0.0",
"@nestjs/platform-socket.io": "^11.0.0",
"@nestjs/throttler": "^6.5.0",
"@nestjs/websockets": "^11.0.0",
"@opentelemetry/auto-instrumentations-node": "^0.71.0",
"@opentelemetry/auto-instrumentations-node": "^0.72.0",
"@opentelemetry/exporter-metrics-otlp-http": "^0.213.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.213.0",
"@opentelemetry/resources": "^2.6.0",

View File

@@ -12,7 +12,7 @@ import { BadRequestException, NotFoundException } from '@nestjs/common';
import { describe, expect, it, vi, beforeEach } from 'vitest';
import type { ConversationHistoryMessage } from '../agent/agent.service.js';
import { ConversationsController } from '../conversations/conversations.controller.js';
import type { Message } from '@mosaic/brain';
import type { Message } from '@mosaicstack/brain';
// ---------------------------------------------------------------------------
// Shared test data

View File

@@ -18,13 +18,13 @@
*/
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
import { createDb } from '@mosaic/db';
import { createConversationsRepo } from '@mosaic/brain';
import { createAgentsRepo } from '@mosaic/brain';
import { createPreferencesRepo, createInsightsRepo } from '@mosaic/memory';
import { users, conversations, messages, agents, preferences, insights } from '@mosaic/db';
import { eq } from '@mosaic/db';
import type { DbHandle } from '@mosaic/db';
import { createDb } from '@mosaicstack/db';
import { createConversationsRepo } from '@mosaicstack/brain';
import { createAgentsRepo } from '@mosaicstack/brain';
import { createPreferencesRepo, createInsightsRepo } from '@mosaicstack/memory';
import { users, conversations, messages, agents, preferences, insights } from '@mosaicstack/db';
import { eq } from '@mosaicstack/db';
import type { DbHandle } from '@mosaicstack/db';
// ─── Fixed IDs so the afterAll cleanup is deterministic ──────────────────────

View File

@@ -1,6 +1,6 @@
import { Controller, Get, Inject, UseGuards } from '@nestjs/common';
import { sql, type Db } from '@mosaic/db';
import { createQueue } from '@mosaic/queue';
import { sql, type Db } from '@mosaicstack/db';
import { createQueue } from '@mosaicstack/queue';
import { DB } from '../database/database.module.js';
import { AgentService } from '../agent/agent.service.js';
import { ProviderService } from '../agent/provider.service.js';

View File

@@ -11,7 +11,7 @@ import {
UseGuards,
} from '@nestjs/common';
import { randomBytes, createHash } from 'node:crypto';
import { eq, type Db, adminTokens } from '@mosaic/db';
import { eq, type Db, adminTokens } from '@mosaicstack/db';
import { v4 as uuid } from 'uuid';
import { DB } from '../database/database.module.js';
import { AdminGuard } from './admin.guard.js';

View File

@@ -13,8 +13,8 @@ import {
Post,
UseGuards,
} from '@nestjs/common';
import { eq, type Db, users as usersTable } from '@mosaic/db';
import type { Auth } from '@mosaic/auth';
import { eq, type Db, users as usersTable } from '@mosaicstack/db';
import type { Auth } from '@mosaicstack/auth';
import { AUTH } from '../auth/auth.tokens.js';
import { DB } from '../database/database.module.js';
import { AdminGuard } from './admin.guard.js';

View File

@@ -8,9 +8,9 @@ import {
} from '@nestjs/common';
import { createHash } from 'node:crypto';
import { fromNodeHeaders } from 'better-auth/node';
import type { Auth } from '@mosaic/auth';
import type { Db } from '@mosaic/db';
import { eq, adminTokens, users as usersTable } from '@mosaic/db';
import type { Auth } from '@mosaicstack/auth';
import type { Db } from '@mosaicstack/db';
import { eq, adminTokens, users as usersTable } from '@mosaicstack/db';
import type { FastifyRequest } from 'fastify';
import { AUTH } from '../auth/auth.tokens.js';
import { DB } from '../database/database.module.js';

View File

@@ -8,8 +8,8 @@ import {
Post,
} from '@nestjs/common';
import { randomBytes, createHash } from 'node:crypto';
import { count, eq, type Db, users as usersTable, adminTokens } from '@mosaic/db';
import type { Auth } from '@mosaic/auth';
import { count, eq, type Db, users as usersTable, adminTokens } from '@mosaicstack/db';
import type { Auth } from '@mosaicstack/auth';
import { v4 as uuid } from 'uuid';
import { AUTH } from '../auth/auth.tokens.js';
import { DB } from '../database/database.module.js';

View File

@@ -62,7 +62,7 @@ function restoreEnv(saved: Map<EnvKey, string | undefined>): void {
}
function makeRegistry(): ModelRegistry {
return new ModelRegistry(AuthStorage.inMemory());
return ModelRegistry.inMemory(AuthStorage.inMemory());
}
// ---------------------------------------------------------------------------

View File

@@ -1,6 +1,6 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { RoutingService } from '../routing.service.js';
import type { ModelInfo } from '@mosaic/types';
import type { ModelInfo } from '@mosaicstack/types';
const mockModels: ModelInfo[] = [
{

View File

@@ -7,7 +7,7 @@ import type {
IProviderAdapter,
ModelInfo,
ProviderHealth,
} from '@mosaic/types';
} from '@mosaicstack/types';
/**
* Anthropic provider adapter.

View File

@@ -6,7 +6,7 @@ import type {
IProviderAdapter,
ModelInfo,
ProviderHealth,
} from '@mosaic/types';
} from '@mosaicstack/types';
/** Embedding models that Ollama ships with out of the box */
const OLLAMA_EMBEDDING_MODELS: ReadonlyArray<{

View File

@@ -7,7 +7,7 @@ import type {
IProviderAdapter,
ModelInfo,
ProviderHealth,
} from '@mosaic/types';
} from '@mosaicstack/types';
/**
* OpenAI provider adapter.

View File

@@ -6,7 +6,7 @@ import type {
IProviderAdapter,
ModelInfo,
ProviderHealth,
} from '@mosaic/types';
} from '@mosaicstack/types';
const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';

View File

@@ -6,7 +6,7 @@ import type {
IProviderAdapter,
ModelInfo,
ProviderHealth,
} from '@mosaic/types';
} from '@mosaicstack/types';
import { getModelCapability } from '../model-capabilities.js';
/**

View File

@@ -13,7 +13,7 @@ import {
Post,
UseGuards,
} from '@nestjs/common';
import type { Brain } from '@mosaic/brain';
import type { Brain } from '@mosaicstack/brain';
import { BRAIN } from '../brain/brain.tokens.js';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';

View File

@@ -7,8 +7,8 @@ import {
type AgentSessionEvent,
type ToolDefinition,
} from '@mariozechner/pi-coding-agent';
import type { Brain } from '@mosaic/brain';
import type { Memory } from '@mosaic/memory';
import type { Brain } from '@mosaicstack/brain';
import type { Memory } from '@mosaicstack/memory';
import { BRAIN } from '../brain/brain.tokens.js';
import { MEMORY } from '../memory/memory.tokens.js';
import { EmbeddingService } from '../memory/embedding.service.js';

View File

@@ -1,4 +1,4 @@
import type { ModelCapability } from '@mosaic/types';
import type { ModelCapability } from '@mosaicstack/types';
/**
* Comprehensive capability matrix for all target models.

View File

@@ -1,7 +1,7 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';
import type { Db } from '@mosaic/db';
import { providerCredentials, eq, and } from '@mosaic/db';
import type { Db } from '@mosaicstack/db';
import { providerCredentials, eq, and } from '@mosaicstack/db';
import { DB } from '../database/database.module.js';
import type { ProviderCredentialSummaryDto } from './provider-credentials.dto.js';

View File

@@ -14,7 +14,7 @@ import type {
ModelInfo,
ProviderHealth,
ProviderInfo,
} from '@mosaic/types';
} from '@mosaicstack/types';
import {
AnthropicAdapter,
OllamaAdapter,
@@ -67,7 +67,7 @@ export class ProviderService implements OnModuleInit, OnModuleDestroy {
async onModuleInit(): Promise<void> {
const authStorage = AuthStorage.inMemory();
this.registry = new ModelRegistry(authStorage);
this.registry = ModelRegistry.inMemory(authStorage);
// Build the default set of adapters that rely on the registry
this.adapters = [

View File

@@ -1,5 +1,5 @@
import { Body, Controller, Delete, Get, Inject, Param, Post, UseGuards } from '@nestjs/common';
import type { RoutingCriteria } from '@mosaic/types';
import type { RoutingCriteria } from '@mosaicstack/types';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';
import { ProviderService } from './provider.service.js';

View File

@@ -1,6 +1,6 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import type { ModelInfo } from '@mosaic/types';
import type { RoutingCriteria, RoutingResult, CostTier } from '@mosaic/types';
import type { ModelInfo } from '@mosaicstack/types';
import type { RoutingCriteria, RoutingResult, CostTier } from '@mosaicstack/types';
import { ProviderService } from './provider.service.js';
/** Per-million-token cost thresholds for tier classification */

View File

@@ -1,5 +1,5 @@
import { Inject, Injectable, Logger, type OnModuleInit } from '@nestjs/common';
import { routingRules, type Db, sql } from '@mosaic/db';
import { routingRules, type Db, sql } from '@mosaicstack/db';
import { DB } from '../../database/database.module.js';
import type { RoutingCondition, RoutingAction } from './routing.types.js';

View File

@@ -1,5 +1,5 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import { routingRules, type Db, and, asc, eq, or } from '@mosaic/db';
import { routingRules, type Db, and, asc, eq, or } from '@mosaicstack/db';
import { DB } from '../../database/database.module.js';
import { ProviderService } from '../provider.service.js';
import { classifyTask } from './task-classifier.js';

View File

@@ -13,7 +13,7 @@ import {
Post,
UseGuards,
} from '@nestjs/common';
import { routingRules, type Db, and, asc, eq, or, inArray } from '@mosaic/db';
import { routingRules, type Db, and, asc, eq, or, inArray } from '@mosaicstack/db';
import { DB } from '../../database/database.module.js';
import { AuthGuard } from '../../auth/auth.guard.js';
import { CurrentUser } from '../../auth/current-user.decorator.js';

View File

@@ -1,7 +1,7 @@
/**
* Routing engine types — M4-002 (condition types) and M4-003 (action types).
*
* These types are re-exported from `@mosaic/types` for shared use across packages.
* These types are re-exported from `@mosaicstack/types` for shared use across packages.
*/
// ─── Classification primitives ───────────────────────────────────────────────
@@ -23,7 +23,7 @@ export type Domain = 'frontend' | 'backend' | 'devops' | 'docs' | 'general';
/**
* Cost tier for model selection.
* Extends the existing `CostTier` in `@mosaic/types` with `local` for self-hosted models.
* Extends the existing `CostTier` in `@mosaicstack/types` with `local` for self-hosted models.
*/
export type CostTier = 'cheap' | 'standard' | 'premium' | 'local';

View File

@@ -1,6 +1,6 @@
import { Type } from '@sinclair/typebox';
import type { ToolDefinition } from '@mariozechner/pi-coding-agent';
import type { Brain } from '@mosaic/brain';
import type { Brain } from '@mosaicstack/brain';
export function createBrainTools(brain: Brain): ToolDefinition[] {
const listProjects: ToolDefinition = {

View File

@@ -1,7 +1,7 @@
import { Type } from '@sinclair/typebox';
import type { ToolDefinition } from '@mariozechner/pi-coding-agent';
import type { Memory } from '@mosaic/memory';
import type { EmbeddingProvider } from '@mosaic/memory';
import type { Memory } from '@mosaicstack/memory';
import type { EmbeddingProvider } from '@mosaicstack/memory';
/**
* Create memory tools bound to the session's authenticated userId.

View File

@@ -1,6 +1,6 @@
import type { IncomingMessage, ServerResponse } from 'node:http';
import { toNodeHandler } from 'better-auth/node';
import type { Auth } from '@mosaic/auth';
import type { Auth } from '@mosaicstack/auth';
import type { NestFastifyApplication } from '@nestjs/platform-fastify';
import { AUTH } from './auth.tokens.js';

View File

@@ -6,7 +6,7 @@ import {
UnauthorizedException,
} from '@nestjs/common';
import { fromNodeHeaders } from 'better-auth/node';
import type { Auth } from '@mosaic/auth';
import type { Auth } from '@mosaicstack/auth';
import type { FastifyRequest } from 'fastify';
import { AUTH } from './auth.tokens.js';

View File

@@ -1,6 +1,6 @@
import { Global, Module } from '@nestjs/common';
import { createAuth, type Auth } from '@mosaic/auth';
import type { Db } from '@mosaic/db';
import { createAuth, type Auth } from '@mosaicstack/auth';
import type { Db } from '@mosaicstack/db';
import { DB } from '../database/database.module.js';
import { AUTH } from './auth.tokens.js';
import { SsoController } from './sso.controller.js';

View File

@@ -1,5 +1,5 @@
import { Controller, Get } from '@nestjs/common';
import { buildSsoDiscovery, type SsoProviderDiscovery } from '@mosaic/auth';
import { buildSsoDiscovery, type SsoProviderDiscovery } from '@mosaicstack/auth';
@Controller('api/sso/providers')
export class SsoController {

View File

@@ -1,6 +1,6 @@
import { Global, Module } from '@nestjs/common';
import { createBrain, type Brain } from '@mosaic/brain';
import type { Db } from '@mosaic/db';
import { createBrain, type Brain } from '@mosaicstack/brain';
import type { Db } from '@mosaicstack/db';
import { DB } from '../database/database.module.js';
import { BRAIN } from './brain.tokens.js';

View File

@@ -11,15 +11,15 @@ import {
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import type { AgentSessionEvent } from '@mariozechner/pi-coding-agent';
import type { Auth } from '@mosaic/auth';
import type { Brain } from '@mosaic/brain';
import type { Auth } from '@mosaicstack/auth';
import type { Brain } from '@mosaicstack/brain';
import type {
SetThinkingPayload,
SlashCommandPayload,
SystemReloadPayload,
RoutingDecisionInfo,
AbortPayload,
} from '@mosaic/types';
} from '@mosaicstack/types';
import { AgentService, type ConversationHistoryMessage } from '../agent/agent.service.js';
import { AUTH } from '../auth/auth.tokens.js';
import { BRAIN } from '../brain/brain.tokens.js';

View File

@@ -1,6 +1,6 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { CommandExecutorService } from './command-executor.service.js';
import type { SlashCommandPayload } from '@mosaic/types';
import type { SlashCommandPayload } from '@mosaicstack/types';
// Minimal mock implementations
const mockRegistry = {

View File

@@ -1,7 +1,7 @@
import { forwardRef, Inject, Injectable, Logger, Optional } from '@nestjs/common';
import type { QueueHandle } from '@mosaic/queue';
import type { Brain } from '@mosaic/brain';
import type { SlashCommandPayload, SlashCommandResultPayload } from '@mosaic/types';
import type { QueueHandle } from '@mosaicstack/queue';
import type { Brain } from '@mosaicstack/brain';
import type { SlashCommandPayload, SlashCommandResultPayload } from '@mosaicstack/types';
import { AgentService } from '../agent/agent.service.js';
import { ChatGateway } from '../chat/chat.gateway.js';
import { SessionGCService } from '../gc/session-gc.service.js';

View File

@@ -1,6 +1,6 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { CommandRegistryService } from './command-registry.service.js';
import type { CommandDef } from '@mosaic/types';
import type { CommandDef } from '@mosaicstack/types';
const mockCmd: CommandDef = {
name: 'test',

View File

@@ -1,5 +1,5 @@
import { Injectable, type OnModuleInit } from '@nestjs/common';
import type { CommandDef, CommandManifest } from '@mosaic/types';
import type { CommandDef, CommandManifest } from '@mosaicstack/types';
@Injectable()
export class CommandRegistryService implements OnModuleInit {

View File

@@ -13,7 +13,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { CommandRegistryService } from './command-registry.service.js';
import { CommandExecutorService } from './command-executor.service.js';
import type { SlashCommandPayload } from '@mosaic/types';
import type { SlashCommandPayload } from '@mosaicstack/types';
// ─── Mocks ───────────────────────────────────────────────────────────────────

View File

@@ -1,5 +1,5 @@
import { forwardRef, Inject, Module, type OnApplicationShutdown } from '@nestjs/common';
import { createQueue, type QueueHandle } from '@mosaic/queue';
import { createQueue, type QueueHandle } from '@mosaicstack/queue';
import { ChatModule } from '../chat/chat.module.js';
import { GCModule } from '../gc/gc.module.js';
import { ReloadModule } from '../reload/reload.module.js';

View File

@@ -1,5 +1,5 @@
import { Global, Module } from '@nestjs/common';
import { loadConfig, type MosaicConfig } from '@mosaic/config';
import { loadConfig, type MosaicConfig } from '@mosaicstack/config';
export const MOSAIC_CONFIG = 'MOSAIC_CONFIG';

View File

@@ -15,7 +15,7 @@ import {
Query,
UseGuards,
} from '@nestjs/common';
import type { Brain } from '@mosaic/brain';
import type { Brain } from '@mosaicstack/brain';
import { BRAIN } from '../brain/brain.tokens.js';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';

View File

@@ -8,7 +8,7 @@ import {
type MissionStatusSummary,
type MissionTask,
type TaskDetail,
} from '@mosaic/coord';
} from '@mosaicstack/coord';
import { promises as fs } from 'node:fs';
import path from 'node:path';

View File

@@ -2,9 +2,9 @@ import { mkdirSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { Global, Inject, Module, type OnApplicationShutdown } from '@nestjs/common';
import { createDb, createPgliteDb, type Db, type DbHandle } from '@mosaic/db';
import { createStorageAdapter, type StorageAdapter } from '@mosaic/storage';
import type { MosaicConfig } from '@mosaic/config';
import { createDb, createPgliteDb, type Db, type DbHandle } from '@mosaicstack/db';
import { createStorageAdapter, type StorageAdapter } from '@mosaicstack/storage';
import type { MosaicConfig } from '@mosaicstack/config';
import { MOSAIC_CONFIG } from '../config/config.module.js';
export const DB_HANDLE = 'DB_HANDLE';

View File

@@ -1,5 +1,5 @@
import { Module, type OnApplicationShutdown, Inject } from '@nestjs/common';
import { createQueue, type QueueHandle } from '@mosaic/queue';
import { createQueue, type QueueHandle } from '@mosaicstack/queue';
import { SessionGCService } from './session-gc.service.js';
import { REDIS } from './gc.tokens.js';

View File

@@ -1,7 +1,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Logger } from '@nestjs/common';
import type { QueueHandle } from '@mosaic/queue';
import type { LogService } from '@mosaic/log';
import type { QueueHandle } from '@mosaicstack/queue';
import type { LogService } from '@mosaicstack/log';
import { SessionGCService } from './session-gc.service.js';
type MockRedis = {

View File

@@ -1,6 +1,6 @@
import { Inject, Injectable, Logger, type OnModuleInit } from '@nestjs/common';
import type { QueueHandle } from '@mosaic/queue';
import type { LogService } from '@mosaic/log';
import type { QueueHandle } from '@mosaicstack/queue';
import type { LogService } from '@mosaicstack/log';
import { LOG_SERVICE } from '../log/log.tokens.js';
import { REDIS } from './gc.tokens.js';

View File

@@ -1,5 +1,5 @@
import { Body, Controller, Get, Inject, Param, Post, Query, UseGuards } from '@nestjs/common';
import type { LogService } from '@mosaic/log';
import type { LogService } from '@mosaicstack/log';
import { LOG_SERVICE } from './log.tokens.js';
import { AuthGuard } from '../auth/auth.guard.js';
import type { IngestLogDto, QueryLogsDto } from './log.dto.js';

View File

@@ -1,6 +1,6 @@
import { Global, Module } from '@nestjs/common';
import { createLogService, type LogService } from '@mosaic/log';
import type { Db } from '@mosaic/db';
import { createLogService, type LogService } from '@mosaicstack/log';
import type { Db } from '@mosaicstack/db';
import { DB } from '../database/database.module.js';
import { LOG_SERVICE } from './log.tokens.js';
import { LogController } from './log.controller.js';

View File

@@ -1,11 +1,11 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import type { LogService } from '@mosaic/log';
import type { Memory } from '@mosaic/memory';
import type { LogService } from '@mosaicstack/log';
import type { Memory } from '@mosaicstack/memory';
import { LOG_SERVICE } from './log.tokens.js';
import { MEMORY } from '../memory/memory.tokens.js';
import { EmbeddingService } from '../memory/embedding.service.js';
import type { Db } from '@mosaic/db';
import { sql, summarizationJobs } from '@mosaic/db';
import type { Db } from '@mosaicstack/db';
import { sql, summarizationJobs } from '@mosaicstack/db';
import { DB } from '../database/database.module.js';
const SUMMARIZATION_PROMPT = `You are a knowledge extraction assistant. Given the following agent interaction logs, extract the key decisions, learnings, and patterns. Output a concise summary (2-4 sentences) that captures the most important information for future reference. Focus on actionable insights, not raw events.

View File

@@ -19,7 +19,7 @@ import { NestFactory } from '@nestjs/core';
import { Logger, ValidationPipe } from '@nestjs/common';
import { FastifyAdapter, type NestFastifyApplication } from '@nestjs/platform-fastify';
import helmet from '@fastify/helmet';
import { listSsoStartupWarnings } from '@mosaic/auth';
import { listSsoStartupWarnings } from '@mosaicstack/auth';
import { AppModule } from './app.module.js';
import { mountAuthHandler } from './auth/auth.controller.js';
import { mountMcpHandler } from './mcp/mcp.controller.js';

View File

@@ -1,7 +1,7 @@
import type { IncomingMessage, ServerResponse } from 'node:http';
import { Logger } from '@nestjs/common';
import { fromNodeHeaders } from 'better-auth/node';
import type { Auth } from '@mosaic/auth';
import type { Auth } from '@mosaicstack/auth';
import type { NestFastifyApplication } from '@nestjs/platform-fastify';
import type { McpService } from './mcp.service.js';
import { AUTH } from '../auth/auth.tokens.js';

View File

@@ -3,8 +3,8 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { randomUUID } from 'node:crypto';
import { z } from 'zod';
import type { Brain } from '@mosaic/brain';
import type { Memory } from '@mosaic/memory';
import type { Brain } from '@mosaicstack/brain';
import type { Memory } from '@mosaicstack/memory';
import { BRAIN } from '../brain/brain.tokens.js';
import { MEMORY } from '../memory/memory.tokens.js';
import { EmbeddingService } from '../memory/embedding.service.js';

View File

@@ -1,5 +1,5 @@
import { Injectable, Logger } from '@nestjs/common';
import type { EmbeddingProvider } from '@mosaic/memory';
import type { EmbeddingProvider } from '@mosaicstack/memory';
// ---------------------------------------------------------------------------
// Environment-driven configuration

View File

@@ -12,7 +12,7 @@ import {
Query,
UseGuards,
} from '@nestjs/common';
import type { Memory } from '@mosaic/memory';
import type { Memory } from '@mosaicstack/memory';
import { MEMORY } from './memory.tokens.js';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';

View File

@@ -5,10 +5,10 @@ import {
createMemoryAdapter,
type MemoryAdapter,
type MemoryConfig,
} from '@mosaic/memory';
import type { Db } from '@mosaic/db';
import type { StorageAdapter } from '@mosaic/storage';
import type { MosaicConfig } from '@mosaic/config';
} from '@mosaicstack/memory';
import type { Db } from '@mosaicstack/db';
import type { StorageAdapter } from '@mosaicstack/storage';
import type { MosaicConfig } from '@mosaicstack/config';
import { MOSAIC_CONFIG } from '../config/config.module.js';
import { DB, STORAGE_ADAPTER } from '../database/database.module.js';
import { MEMORY } from './memory.tokens.js';

View File

@@ -12,7 +12,7 @@ import {
Post,
UseGuards,
} from '@nestjs/common';
import type { Brain } from '@mosaic/brain';
import type { Brain } from '@mosaicstack/brain';
import { BRAIN } from '../brain/brain.tokens.js';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';

View File

@@ -6,8 +6,8 @@ import {
type OnModuleDestroy,
type OnModuleInit,
} from '@nestjs/common';
import { DiscordPlugin } from '@mosaic/discord-plugin';
import { TelegramPlugin } from '@mosaic/telegram-plugin';
import { DiscordPlugin } from '@mosaicstack/discord-plugin';
import { TelegramPlugin } from '@mosaicstack/telegram-plugin';
import { PluginService } from './plugin.service.js';
import type { IChannelPlugin } from './plugin.interface.js';
import { PLUGIN_REGISTRY } from './plugin.tokens.js';

View File

@@ -1,6 +1,6 @@
import { describe, it, expect, vi } from 'vitest';
import { PreferencesService, PLATFORM_DEFAULTS, IMMUTABLE_KEYS } from './preferences.service.js';
import type { Db } from '@mosaic/db';
import type { Db } from '@mosaicstack/db';
/**
* Build a mock Drizzle DB where the select chain supports:

View File

@@ -1,5 +1,5 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import { eq, and, sql, type Db, preferences as preferencesTable } from '@mosaic/db';
import { eq, and, sql, type Db, preferences as preferencesTable } from '@mosaicstack/db';
import { DB } from '../database/database.module.js';
export const PLATFORM_DEFAULTS: Record<string, unknown> = {

View File

@@ -1,5 +1,5 @@
import { Injectable, Logger } from '@nestjs/common';
import { createQueue, type QueueHandle } from '@mosaic/queue';
import { createQueue, type QueueHandle } from '@mosaicstack/queue';
const SESSION_SYSTEM_KEY = (sessionId: string) => `mosaic:session:${sessionId}:system`;
const SESSION_SYSTEM_FRAGMENTS_KEY = (sessionId: string) =>

View File

@@ -13,7 +13,7 @@ import {
Post,
UseGuards,
} from '@nestjs/common';
import type { Brain } from '@mosaic/brain';
import type { Brain } from '@mosaicstack/brain';
import { BRAIN } from '../brain/brain.tokens.js';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';

View File

@@ -1,6 +1,6 @@
import { Global, Module } from '@nestjs/common';
import { createQueueAdapter, type QueueAdapter } from '@mosaic/queue';
import type { MosaicConfig } from '@mosaic/config';
import { createQueueAdapter, type QueueAdapter } from '@mosaicstack/queue';
import type { MosaicConfig } from '@mosaicstack/config';
import { MOSAIC_CONFIG } from '../config/config.module.js';
import { QueueService } from './queue.service.js';

View File

@@ -7,7 +7,7 @@ import {
type OnModuleDestroy,
} from '@nestjs/common';
import { Queue, Worker, type Job, type ConnectionOptions } from 'bullmq';
import type { LogService } from '@mosaic/log';
import type { LogService } from '@mosaicstack/log';
import { LOG_SERVICE } from '../log/log.tokens.js';
import type { JobDto, JobStatus } from './queue-admin.dto.js';

View File

@@ -1,5 +1,5 @@
import { Controller, HttpCode, HttpStatus, Inject, Post, UseGuards } from '@nestjs/common';
import type { SystemReloadPayload } from '@mosaic/types';
import type { SystemReloadPayload } from '@mosaicstack/types';
import { AdminGuard } from '../admin/admin.guard.js';
import { ChatGateway } from '../chat/chat.gateway.js';
import { ReloadService } from './reload.service.js';

View File

@@ -5,7 +5,7 @@ import {
type OnApplicationBootstrap,
type OnApplicationShutdown,
} from '@nestjs/common';
import type { SystemReloadPayload } from '@mosaic/types';
import type { SystemReloadPayload } from '@mosaicstack/types';
import { CommandRegistryService } from '../commands/command-registry.service.js';
import { isMosaicPlugin } from './mosaic-plugin.interface.js';

View File

@@ -1,5 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
import { eq, type Db, skills } from '@mosaic/db';
import { eq, type Db, skills } from '@mosaicstack/db';
import { DB } from '../database/database.module.js';
type Skill = typeof skills.$inferSelect;

View File

@@ -14,7 +14,7 @@ import {
Query,
UseGuards,
} from '@nestjs/common';
import type { Brain } from '@mosaic/brain';
import type { Brain } from '@mosaicstack/brain';
import { BRAIN } from '../brain/brain.tokens.js';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';

View File

@@ -1,5 +1,5 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import type { Brain } from '@mosaic/brain';
import type { Brain } from '@mosaicstack/brain';
import { BRAIN } from '../brain/brain.tokens.js';
import { PluginService } from '../plugin/plugin.service.js';
import { WorkspaceService } from './workspace.service.js';

View File

@@ -1,5 +1,5 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import { eq, and, type Db, teams, teamMembers, projects } from '@mosaic/db';
import { eq, and, type Db, teams, teamMembers, projects } from '@mosaicstack/db';
import { DB } from '../database/database.module.js';
@Injectable()

View File

@@ -4,15 +4,15 @@
"rootDir": "../..",
"baseUrl": ".",
"paths": {
"@mosaic/auth": ["../../packages/auth/src/index.ts"],
"@mosaic/brain": ["../../packages/brain/src/index.ts"],
"@mosaic/coord": ["../../packages/coord/src/index.ts"],
"@mosaic/db": ["../../packages/db/src/index.ts"],
"@mosaic/log": ["../../packages/log/src/index.ts"],
"@mosaic/memory": ["../../packages/memory/src/index.ts"],
"@mosaic/types": ["../../packages/types/src/index.ts"],
"@mosaic/discord-plugin": ["../../plugins/discord/src/index.ts"],
"@mosaic/telegram-plugin": ["../../plugins/telegram/src/index.ts"]
"@mosaicstack/auth": ["../../packages/auth/src/index.ts"],
"@mosaicstack/brain": ["../../packages/brain/src/index.ts"],
"@mosaicstack/coord": ["../../packages/coord/src/index.ts"],
"@mosaicstack/db": ["../../packages/db/src/index.ts"],
"@mosaicstack/log": ["../../packages/log/src/index.ts"],
"@mosaicstack/memory": ["../../packages/memory/src/index.ts"],
"@mosaicstack/types": ["../../packages/types/src/index.ts"],
"@mosaicstack/discord-plugin": ["../../plugins/discord/src/index.ts"],
"@mosaicstack/telegram-plugin": ["../../plugins/telegram/src/index.ts"]
}
}
}

View File

@@ -2,7 +2,7 @@ import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'standalone',
transpilePackages: ['@mosaic/design-tokens'],
transpilePackages: ['@mosaicstack/design-tokens'],
// Enable gzip/brotli compression for all responses.
compress: true,

View File

@@ -1,5 +1,5 @@
{
"name": "@mosaic/web",
"name": "@mosaicstack/web",
"version": "0.0.2",
"private": true,
"scripts": {
@@ -12,7 +12,7 @@
"start": "next start"
},
"dependencies": {
"@mosaic/design-tokens": "workspace:^",
"@mosaicstack/design-tokens": "workspace:^",
"better-auth": "^1.5.5",
"clsx": "^2.1.0",
"next": "^16.0.0",

View File

@@ -7,7 +7,7 @@ import { defineConfig, devices } from '@playwright/test';
* - Next.js web app running on http://localhost:3000
* - NestJS gateway running on http://localhost:14242
*
* Run with: pnpm --filter @mosaic/web test:e2e
* Run with: pnpm --filter @mosaicstack/web test:e2e
*/
export default defineConfig({
testDir: './e2e',

View File

@@ -153,7 +153,7 @@ for any `<Image>` components added in the future.
```bash
# Run the DB migration (requires a live DB)
pnpm --filter @mosaic/db exec drizzle-kit migrate
pnpm --filter @mosaicstack/db exec drizzle-kit migrate
# Or, in Docker/Swarm — migrations run automatically on gateway startup
# via runMigrations() in packages/db/src/migrate.ts

View File

@@ -57,7 +57,7 @@ Multi-panel layout with keyboard navigation.
- **Ink 5** (React for CLI) — already in deps
- **Component architecture** — break monolithic `app.tsx` into composable components
- **Typed Socket.IO events** — leverage `@mosaic/types` `ServerToClientEvents` / `ClientToServerEvents`
- **Typed Socket.IO events** — leverage `@mosaicstack/types` `ServerToClientEvents` / `ClientToServerEvents`
- **Local state only** (Wave 1) — cwd/branch read from `process.cwd()` and `git` at startup
- **Gateway metadata** (future) — extend socket handshake or add REST endpoint for model info, token usage

View File

@@ -8,7 +8,7 @@
- **Best-Guess Mode:** true
- Repo (target): `git.mosaicstack.dev/mosaic/mosaic-stack`
- Baseline: `~/src/jarvis-old` (jarvis v0.2.0)
- Package source: `~/src/mosaic-mono-v0` (@mosaic/\* packages)
- Package source: `~/src/mosaic-mono-v0` (@mosaicstack/\* packages)
- Agent harness: [pi](https://github.com/badlogic/pi-mono) (v0.57.1)
- Remote control reference: [OpenClaw](https://github.com/openclaw/openclaw) (upstream, canonical)
@@ -16,7 +16,7 @@
## Problem Statement
Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and Next.js frontend. It handles chat, projects, tasks, and LLM routing but lacks orchestration depth, agent coordination, shared memory, and remote access. The Mosaic framework (`~/.config/mosaic`) provides agent guides, shell-based orchestration tools, and quality rails — but these are loose scripts, not an integrated platform. The `@mosaic/*` packages in mosaic-mono-v0 began consolidating these into TypeScript packages (brain, queue, coord, cli, prdy, quality-rails) but have no UI, no auth, and no agent runtime integration.
Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and Next.js frontend. It handles chat, projects, tasks, and LLM routing but lacks orchestration depth, agent coordination, shared memory, and remote access. The Mosaic framework (`~/.config/mosaic`) provides agent guides, shell-based orchestration tools, and quality rails — but these are loose scripts, not an integrated platform. The `@mosaicstack/*` packages in mosaic-mono-v0 began consolidating these into TypeScript packages (brain, queue, coord, cli, prdy, quality-rails) but have no UI, no auth, and no agent runtime integration.
**The gap:** Three codebases with overlapping concerns, no unified runtime, no remote control surface (Discord/Telegram), no gateway orchestrator, and a Python backend that doesn't align with the target TypeScript-everywhere stack.
@@ -32,7 +32,7 @@ Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and
4. **Gateway orchestrator** — Central routing layer that dispatches tasks to appropriate agents based on capability, cost, and context
5. **Shared memory** — PostgreSQL canonical store + vector DB for semantic search + tiered log summarization to prevent context creep
6. **Multi-user with SSO** — BetterAuth with Authentik/WorkOS/Keycloak SSO, RBAC for family/team/business use
7. **Full @mosaic/\* package integration** — brain, queue, coord, mosaic, prdy, quality-rails, cli all integrated
7. **Full @mosaicstack/\* package integration** — brain, queue, coord, mosaic, prdy, quality-rails, cli all integrated
8. **Extensible** — MCP capability, skill import interface, plugin architecture for LLM providers and remote channels
---
@@ -44,7 +44,7 @@ Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and
1. Chat/conversation UI (web) — carry forward from jarvis-old, rewrite frontend to work with new backend
2. Pi TUI integration — terminal-based agent interaction using Pi SDK
3. Web dashboard — settings, task management, projects, PRDs, missions, agent status
4. Gateway orchestrator (`@mosaic/gateway`) — central dispatch for agent tasks with routing logic
4. Gateway orchestrator (`@mosaicstack/gateway`) — central dispatch for agent tasks with routing logic
5. Task management — CRUD, kanban, mission-scoped tasks, dependency tracking
6. Project management — projects, milestones, PRDs linked to missions
7. Shared memory system — learned preferences, behaviors, defaults; tiered storage with summarization
@@ -55,13 +55,13 @@ Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and
12. Agent routing — task-based model/provider selection (cost/capability matrix)
13. MCP capability — server and client, tool registration
14. Skill import interface — browse, install, manage agent skills
15. `@mosaic/brain` — structured data layer (migrated to PG + vector DB backend)
16. `@mosaic/queue` — Valkey-backed task queue with MCP tools
17. `@mosaic/coord` — mission coordination engine
18. `@mosaic/mosaic` — install wizard / bootstrap
19. `@mosaic/prdy` — PRD wizard
20. `@mosaic/quality-rails` — code quality scaffolder
21. `@mosaic/cli` — unified `mosaic` CLI
15. `@mosaicstack/brain` — structured data layer (migrated to PG + vector DB backend)
16. `@mosaicstack/queue` — Valkey-backed task queue with MCP tools
17. `@mosaicstack/coord` — mission coordination engine
18. `@mosaicstack/mosaic` — install wizard / bootstrap
19. `@mosaicstack/prdy` — PRD wizard
20. `@mosaicstack/quality-rails` — code quality scaffolder
21. `@mosaicstack/cli` — unified `mosaic` CLI
22. Docker Compose deployment + bare-metal capability
23. Agent log service — ingest, parse, tier, summarize agent interaction logs
@@ -94,14 +94,14 @@ Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and
│ └──────────────┴───────┬───────┴────────────────┘ │
│ │ │
│ ┌─────────▼──────────┐ │
│ │ @mosaic/gateway │ ← Central Orchestrator│
│ │ @mosaicstack/gateway │ ← Central Orchestrator│
│ │ (NestJS+Fastify) │ │
│ └────┬────┬────┬─────┘ │
│ │ │ │ │
│ ┌──────────────┤ │ ├──────────────┐ │
│ │ │ │ │ │ │
│ ┌───────▼──────┐ ┌────▼────▼──┐ │ ┌───────────▼────────┐ │
│ │ @mosaic/brain│ │ @mosaic/ │ │ │ Agent Pool │ │
│ │ @mosaicstack/brain│ │ @mosaicstack/ │ │ │ Agent Pool │ │
│ │ (Data Layer) │ │ queue │ │ │ (Pi SDK sessions) │ │
│ └───────┬──────┘ └────────────┘ │ │ - Anthropic │ │
│ │ │ │ - Codex │ │
@@ -111,12 +111,12 @@ Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and
│ └──────────────┴───────────┘ │ │ - llama.cpp │ │
│ │ └────────────────────┘ │
│ ┌─────────────▼──────┐ │
│ │ @mosaic/coord │ │
│ │ @mosaicstack/coord │ │
│ │ Mission lifecycle │ │
│ └────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ @mosaic/cli │ │ @mosaic/prdy │ │ @mosaic/ │ │
│ │ @mosaicstack/cli │ │ @mosaicstack/prdy │ │ @mosaicstack/ │ │
│ │ │ │ │ │ quality-rails │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
│ │
@@ -130,20 +130,20 @@ Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and
| Layer | Technology | Rationale |
| ------------------ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| **Web Frontend** | Next.js 16 + React 19 + Tailwind CSS | SSR, RSC; design tokens from @mosaic/design-tokens (mosaic-stack-website) |
| **Web Frontend** | Next.js 16 + React 19 + Tailwind CSS | SSR, RSC; design tokens from @mosaicstack/design-tokens (mosaic-stack-website) |
| **API / Gateway** | NestJS + Fastify adapter | Module system, DI, guards/interceptors for complex gateway; Fastify performance underneath |
| **Agent Runtime** | Pi SDK (embedded) | Extensible harness with tools, skills, session management |
| **TUI** | Pi interactive mode | Native terminal agent interaction |
| **Auth** | BetterAuth + SSO adapters | Multi-user RBAC with Authentik/WorkOS/Keycloak |
| **Database** | PostgreSQL 17 + pgvector | Canonical store; pgvector for embedding search |
| **Vector DB** | pgvector + VectorStore interface | pgvector for v0.1.0; `VectorStore` abstraction in @mosaic/memory makes Qdrant a drop-in later |
| **Cache / Queue** | Valkey 8 | Redis-compatible; proven in @mosaic/queue |
| **Vector DB** | pgvector + VectorStore interface | pgvector for v0.1.0; `VectorStore` abstraction in @mosaicstack/memory makes Qdrant a drop-in later |
| **Cache / Queue** | Valkey 8 | Redis-compatible; proven in @mosaicstack/queue |
| **ORM** | Drizzle ORM | TypeScript-native, lightweight, good migration story |
| **Validation** | Zod | Already used across @mosaic/\* packages |
| **Validation** | Zod | Already used across @mosaicstack/\* packages |
| **Build** | pnpm workspaces + Turborepo | Proven in both jarvis-old and mosaic-mono-v0 |
| **Testing** | Vitest + Playwright | Unit/integration via Vitest, E2E via Playwright |
| **Remote Control** | Discord.js + Telegraf | Inspired by OpenClaw plugin architecture |
| **MCP** | @modelcontextprotocol/sdk | Already used in @mosaic/brain and @mosaic/queue |
| **MCP** | @modelcontextprotocol/sdk | Already used in @mosaicstack/brain and @mosaicstack/queue |
| **Container** | Docker Compose | Self-hosted; bare-metal also supported |
| **CI** | Woodpecker CI | Existing infrastructure at git.mosaicstack.dev |
| **Observability** | OpenTelemetry + SigNoz | Wide-event logging from day one; OTEL auto-instrumentation for NestJS/PG/HTTP; SigNoz as all-in-one backend |
@@ -158,12 +158,12 @@ The jarvis-old FastAPI backend is not carried forward as code. Its domain logic
Instead of a custom LLM provider abstraction (jarvis-old's `BaseLLMProvider`), Pi SDK manages agent sessions. Pi handles model selection, tool calling, context management, and compaction. The gateway dispatches work to Pi sessions configured with appropriate providers.
**AD-3: Gateway as the central nervous system (NestJS + Fastify adapter)**
`@mosaic/gateway` is the single API surface. The web app, TUI, Discord, and Telegram all talk to the gateway. The gateway routes to brain (data), queue (coordination), agent pool (LLM work), and coord (mission lifecycle). This replaces the direct FastAPI-to-DB pattern from jarvis-old.
`@mosaicstack/gateway` is the single API surface. The web app, TUI, Discord, and Telegram all talk to the gateway. The gateway routes to brain (data), queue (coordination), agent pool (LLM work), and coord (mission lifecycle). This replaces the direct FastAPI-to-DB pattern from jarvis-old.
NestJS was chosen over raw Fastify because the gateway is inherently complex — it hosts channel plugins, agent pool management, routing engine, WebSocket hub, MCP server, auth middleware, and integrates brain, queue, memory, and log services. NestJS provides the module system, dependency injection, guards, and interceptors needed to organize this cleanly. NestJS uses Fastify as its HTTP adapter, so Fastify's performance is preserved. This also aligns with the stated stack preference in USER.md ("NestJS API + Next.js web"). @mosaic/brain's existing Fastify code migrates naturally into a NestJS module with Fastify adapter.
NestJS was chosen over raw Fastify because the gateway is inherently complex — it hosts channel plugins, agent pool management, routing engine, WebSocket hub, MCP server, auth middleware, and integrates brain, queue, memory, and log services. NestJS provides the module system, dependency injection, guards, and interceptors needed to organize this cleanly. NestJS uses Fastify as its HTTP adapter, so Fastify's performance is preserved. This also aligns with the stated stack preference in USER.md ("NestJS API + Next.js web"). @mosaicstack/brain's existing Fastify code migrates naturally into a NestJS module with Fastify adapter.
**AD-4: Brain migrates from JSON files to PostgreSQL**
`@mosaic/brain` currently uses a JSON file store. For Mosaic Stack, brain's data model (tasks, projects, events, agents, missions, tickets) moves to PostgreSQL via Drizzle ORM. Brain's REST + MCP interface is preserved — only the storage backend changes.
`@mosaicstack/brain` currently uses a JSON file store. For Mosaic Stack, brain's data model (tasks, projects, events, agents, missions, tickets) moves to PostgreSQL via Drizzle ORM. Brain's REST + MCP interface is preserved — only the storage backend changes.
**AD-5: Tiered memory with summarization**
Agent interaction logs are ingested into a log service. Raw logs are stored short-term. A summarization pipeline (using a cheap LLM) periodically compresses logs into structured insights stored in the vector DB. This prevents unbounded log growth while preserving searchable context.
@@ -189,8 +189,8 @@ The gateway includes a cron scheduler for recurring tasks: log summarization run
**AD-12: Web search tool (DuckDuckGo MCP)**
Agent sessions include a web search tool for information retrieval. DuckDuckGo via MCP server is the primary option (privacy-respecting, no API key required). Falls back to other search MCP providers if configured. Registered as a standard MCP tool available to all agent sessions.
**AD-13: Design system from @mosaic/design-tokens**
The web dashboard uses the Mosaic Stack design system established in `mosaic-stack-website`. The `@mosaic/design-tokens` package provides CSS custom properties, Tailwind preset, and TS color/font/radius exports. Dark theme default with light theme support. Fonts: Outfit (sans), Fira Code (mono). Color palette: deep blue-grays with blue/purple/teal accents.
**AD-13: Design system from @mosaicstack/design-tokens**
The web dashboard uses the Mosaic Stack design system established in `mosaic-stack-website`. The `@mosaicstack/design-tokens` package provides CSS custom properties, Tailwind preset, and TS color/font/radius exports. Dark theme default with light theme support. Fonts: Outfit (sans), Fira Code (mono). Color palette: deep blue-grays with blue/purple/teal accents.
**AD-14: Multi-tier deployment readiness**
Code is structured assuming eventual multi-node deployment with dedicated roles (gateway nodes, agent worker nodes, brain/DB nodes). Packages communicate via well-defined APIs (HTTP/WS/MCP), not in-process calls where avoidable. Service boundaries are clean: gateway is stateless (state in PG/Valkey), agent pool can scale independently, brain is a separate service. v0.1.0 runs single-node; the architecture doesn't fight horizontal scaling later.
@@ -205,25 +205,25 @@ Code is structured assuming eventual multi-node deployment with dedicated roles
mosaic-mono-v1/
├── apps/
│ ├── web/ Next.js 16 web dashboard
│ └── gateway/ @mosaic/gateway — NestJS API + WebSocket
│ └── gateway/ @mosaicstack/gateway — NestJS API + WebSocket
├── packages/
│ ├── types/ @mosaic/types — shared type contracts
│ ├── brain/ @mosaic/brain — data layer (PG-backed)
│ ├── queue/ @mosaic/queue — Valkey task queue + MCP
│ ├── coord/ @mosaic/coord — mission coordination
│ ├── mosaic/ @mosaic/mosaic — install wizard
│ ├── prdy/ @mosaic/prdy — PRD wizard
│ ├── quality-rails/ @mosaic/quality-rails — code quality scaffolder
│ ├── cli/ @mosaic/cli — unified CLI
│ ├── auth/ @mosaic/auth — BetterAuth config + SSO adapters
│ ├── db/ @mosaic/db — Drizzle schema, migrations, connection
│ ├── agent/ @mosaic/agent — Pi SDK integration, agent pool manager
│ ├── memory/ @mosaic/memory — tiered memory + summarization service
│ ├── log/ @mosaic/log — agent log ingest + processing
│ └── design-tokens/ @mosaic/design-tokens — CSS vars, Tailwind preset, colors
│ ├── types/ @mosaicstack/types — shared type contracts
│ ├── brain/ @mosaicstack/brain — data layer (PG-backed)
│ ├── queue/ @mosaicstack/queue — Valkey task queue + MCP
│ ├── coord/ @mosaicstack/coord — mission coordination
│ ├── mosaic/ @mosaicstack/mosaic — install wizard
│ ├── prdy/ @mosaicstack/prdy — PRD wizard
│ ├── quality-rails/ @mosaicstack/quality-rails — code quality scaffolder
│ ├── cli/ @mosaicstack/cli — unified CLI
│ ├── auth/ @mosaicstack/auth — BetterAuth config + SSO adapters
│ ├── db/ @mosaicstack/db — Drizzle schema, migrations, connection
│ ├── agent/ @mosaicstack/agent — Pi SDK integration, agent pool manager
│ ├── memory/ @mosaicstack/memory — tiered memory + summarization service
│ ├── log/ @mosaicstack/log — agent log ingest + processing
│ └── design-tokens/ @mosaicstack/design-tokens — CSS vars, Tailwind preset, colors
├── plugins/
│ ├── discord/ @mosaic/discord-plugin — Discord channel
│ └── telegram/ @mosaic/telegram-plugin — Telegram channel
│ ├── discord/ @mosaicstack/discord-plugin — Discord channel
│ └── telegram/ @mosaicstack/telegram-plugin — Telegram channel
├── docker/
│ ├── gateway.Dockerfile
│ ├── web.Dockerfile
@@ -244,7 +244,7 @@ mosaic-mono-v1/
### Package Responsibilities
#### `apps/gateway` — @mosaic/gateway (NEW — critical path)
#### `apps/gateway` — @mosaicstack/gateway (NEW — critical path)
The central nervous system. All clients connect here. Built with NestJS (Fastify adapter).
@@ -303,7 +303,7 @@ Carried forward from jarvis-old with significant refactoring.
- User management (admin RBAC panel)
- Auth pages (login, SSO redirect, registration)
#### `packages/types` — @mosaic/types
#### `packages/types` — @mosaicstack/types
Migrated from mosaic-mono-v0. Extended with:
@@ -313,7 +313,7 @@ Migrated from mosaic-mono-v0. Extended with:
- Memory types (preference, insight, summary)
- Plugin channel types (Discord, Telegram message mapping)
#### `packages/brain` — @mosaic/brain
#### `packages/brain` — @mosaicstack/brain
Migrated from mosaic-mono-v0. **Storage backend changes from JSON to PostgreSQL.**
@@ -324,7 +324,7 @@ Migrated from mosaic-mono-v0. **Storage backend changes from JSON to PostgreSQL.
- New: computed endpoints (today, stale, stats, search, audit) run against PG
- New: appreciation collection preserved for family use
#### `packages/queue` — @mosaic/queue
#### `packages/queue` — @mosaicstack/queue
Migrated from mosaic-mono-v0 with minimal changes.
@@ -332,7 +332,7 @@ Migrated from mosaic-mono-v0 with minimal changes.
- MCP server with 8 tools
- Used by gateway for agent task dispatch and coordination
#### `packages/coord` — @mosaic/coord
#### `packages/coord` — @mosaicstack/coord
Migrated from mosaic-mono-v0.
@@ -342,7 +342,7 @@ Migrated from mosaic-mono-v0.
- Continuation prompt generation
- Integration with gateway for mission-driven orchestration
#### `packages/db` — @mosaic/db (NEW)
#### `packages/db` — @mosaicstack/db (NEW)
Shared database package.
@@ -351,7 +351,7 @@ Shared database package.
- Connection pool configuration
- Shared by gateway, brain, auth, memory
#### `packages/auth` — @mosaic/auth (NEW)
#### `packages/auth` — @mosaicstack/auth (NEW)
Authentication and authorization.
@@ -361,7 +361,7 @@ Authentication and authorization.
- API key generation for brain/MCP access
- Session management middleware
#### `packages/agent` — @mosaic/agent (NEW — critical path)
#### `packages/agent` — @mosaicstack/agent (NEW — critical path)
Pi SDK integration layer.
@@ -372,7 +372,7 @@ Pi SDK integration layer.
- Skill management — loads and configures Pi skills for agent sessions
- Session lifecycle — create, monitor, complete, fail, timeout
#### `packages/memory` — @mosaic/memory (NEW)
#### `packages/memory` — @mosaicstack/memory (NEW)
Tiered memory system.
@@ -382,7 +382,7 @@ Tiered memory system.
- Summarization pipeline — compress raw logs into structured insights
- Memory API — used by gateway and agent sessions
#### `packages/log` — @mosaic/log (NEW)
#### `packages/log` — @mosaicstack/log (NEW)
Agent log service.
@@ -392,7 +392,7 @@ Agent log service.
- Summarization trigger — invokes cheap LLM to compress aging logs
- Retention policy — configurable TTLs per tier
#### `packages/mosaic` — @mosaic/mosaic
#### `packages/mosaic` — @mosaicstack/mosaic
Migrated from mosaic-mono-v0, updated for v1.
@@ -400,7 +400,7 @@ Migrated from mosaic-mono-v0, updated for v1.
- Detects existing installations, offers upgrade path
- Configures `~/.config/mosaic/` with guides, tools, runtime configs
#### `packages/prdy` — @mosaic/prdy
#### `packages/prdy` — @mosaicstack/prdy
Migrated from mosaic-mono-v0.
@@ -408,7 +408,7 @@ Migrated from mosaic-mono-v0.
- Template-based PRD creation with Zod validation
- CLI integration via `mosaic prdy`
#### `packages/quality-rails` — @mosaic/quality-rails
#### `packages/quality-rails` — @mosaicstack/quality-rails
Migrated from mosaic-mono-v0.
@@ -416,15 +416,15 @@ Migrated from mosaic-mono-v0.
- Generates ESLint, tsconfig, Woodpecker, husky, lint-staged configs
- Supports project types: monorepo, typescript-node, nextjs
#### `packages/cli` — @mosaic/cli
#### `packages/cli` — @mosaicstack/cli
Migrated from mosaic-mono-v0, extended.
- Unified `mosaic` binary
- Subcommands: `mosaic coord`, `mosaic prdy`, `mosaic queue`, `mosaic quality`, `mosaic gateway`, `mosaic brain`
- Plugin discovery for installed @mosaic/\* packages
- Plugin discovery for installed @mosaicstack/\* packages
#### `plugins/discord` — @mosaic/discord-plugin (NEW — high priority)
#### `plugins/discord` — @mosaicstack/discord-plugin (NEW — high priority)
Discord remote control channel. Architecture inspired by OpenClaw (https://github.com/openclaw/openclaw).
@@ -436,7 +436,7 @@ Discord remote control channel. Architecture inspired by OpenClaw (https://githu
- Bot pairing and permission management (Discord user → Mosaic user mapping)
- DM support for private conversations
#### `plugins/telegram` — @mosaic/telegram-plugin (NEW)
#### `plugins/telegram` — @mosaicstack/telegram-plugin (NEW)
Telegram remote control channel.
@@ -547,7 +547,7 @@ Telegram remote control channel.
- WebSocket hub — real-time updates for chat, agent status, notifications
- Rate limiting and request validation
### FR-3: Agent Pool (@mosaic/agent)
### FR-3: Agent Pool (@mosaicstack/agent)
- Manage concurrent Pi SDK sessions
- Provider configuration: API key management, endpoint URLs, model lists
@@ -582,7 +582,7 @@ Telegram remote control channel.
- Mission CRUD (linked to project and PRD)
- Mission tasks with phases, dependencies, ordering
- Mission summary with computed progress
- Mission coordination via @mosaic/coord
- Mission coordination via @mosaicstack/coord
- Active mission dashboard in web UI
### FR-7: Memory System
@@ -844,7 +844,7 @@ Telegram remote control channel.
- [ ] Database migrations run automatically on first start
- [ ] `.env.example` documents all required configuration
### AC-11: @mosaic/\* Packages
### AC-11: @mosaicstack/\* Packages
- [ ] All 7 migrated packages build, pass tests, and integrate with gateway
- [ ] `mosaic` CLI provides subcommands for each package
@@ -870,7 +870,7 @@ Telegram remote control channel.
| Risk | Likelihood | Impact | Mitigation |
| -------------------------------------------------- | ---------- | ------ | ---------------------------------------------------------------------------------------- |
| Pi SDK API instability (pre-1.0) | Medium | High | Pin version, abstract behind @mosaic/agent interface |
| Pi SDK API instability (pre-1.0) | Medium | High | Pin version, abstract behind @mosaicstack/agent interface |
| Brain PG migration complexity | Medium | Medium | Preserve Brain REST/MCP API contract; only storage changes |
| Discord plugin complexity (OpenClaw has ~60 files) | Medium | Medium | Start minimal (DM + mention in channel), single-guild only; expand iteratively post-beta |
| LLM provider subscription auth varies by provider | Medium | Medium | Abstract behind provider interface; implement per-provider adapters |
@@ -882,7 +882,7 @@ Telegram remote control channel.
| # | Question | Priority | Status |
| --- | ------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1 | Pi SDK version to pin for v0.1.0? | High | ✅ Resolved — Pin `@mariozechner/pi-coding-agent@~0.57.1` (current stable). Abstract behind `@mosaic/agent` interface to insulate from breaking changes. Bump deliberately after testing. |
| 1 | Pi SDK version to pin for v0.1.0? | High | ✅ Resolved — Pin `@mariozechner/pi-coding-agent@~0.57.1` (current stable). Abstract behind `@mosaicstack/agent` interface to insulate from breaking changes. Bump deliberately after testing. |
| 2 | Authentik vs WorkOS vs Keycloak — which SSO provider to implement first? | Medium | ✅ Resolved — Authentik first (already in Jason's infrastructure) |
| 3 | Vector DB: pgvector sufficient or need Qdrant from the start? | Medium | ✅ Resolved — pgvector with VectorStore interface abstraction. Qdrant drops in later if needed. |
| 4 | Summarization LLM: which model for log compression? | Medium | ✅ Resolved — Haiku-tier default with structured output guardrails, configurable via routing engine. |
@@ -910,9 +910,9 @@ All work is **alpha** (< 0.1.0) until Jason approves 0.1.0 beta release.
### Phase 0: Foundation (v0.0.1)
- Scaffold monorepo (pnpm + turbo + tsconfig + eslint + vitest)
- `@mosaic/types` — migrate and extend from v0
- `@mosaic/db` — Drizzle schema, PG connection, migrations
- `@mosaic/auth` — BetterAuth setup with email/password
- `@mosaicstack/types` — migrate and extend from v0
- `@mosaicstack/db` — Drizzle schema, PG connection, migrations
- `@mosaicstack/auth` — BetterAuth setup with email/password
- OTEL foundation — `@opentelemetry/sdk-node` setup, SigNoz in docker-compose, trace propagation wired
- Docker Compose (PG 17 + Valkey + SigNoz)
- CI pipeline (Woodpecker)
@@ -921,19 +921,19 @@ All work is **alpha** (< 0.1.0) until Jason approves 0.1.0 beta release.
### Phase 1: Core API (v0.0.2)
- `apps/gateway` — NestJS server (Fastify adapter), auth middleware, health endpoints
- `@mosaic/brain` — migrate from v0, swap JSON store for PG via @mosaic/db
- `@mosaic/queue` — migrate from v0 (minimal changes)
- `@mosaicstack/brain` — migrate from v0, swap JSON store for PG via @mosaicstack/db
- `@mosaicstack/queue` — migrate from v0 (minimal changes)
- Gateway routes: conversations, tasks, projects, missions
- WebSocket server for chat streaming
- Basic agent dispatch (single provider, no routing)
### Phase 2: Agent Layer (v0.0.3)
- `@mosaic/agent` — Pi SDK integration, agent pool manager
- `@mosaicstack/agent` — Pi SDK integration, agent pool manager
- Multi-provider support (Anthropic + Ollama minimum)
- Agent routing engine (cost/capability matrix)
- Tool registration (brain, queue, memory tools injected into agent sessions)
- `@mosaic/coord` — migrate from v0, integrate with gateway
- `@mosaicstack/coord` — migrate from v0, integrate with gateway
### Phase 3: Web Dashboard (v0.0.4)
@@ -946,25 +946,25 @@ All work is **alpha** (< 0.1.0) until Jason approves 0.1.0 beta release.
### Phase 4: Memory & Intelligence (v0.0.5)
- `@mosaic/memory` — preference store, insight store, semantic search
- `@mosaic/log` — log ingest, parsing, tiered storage
- `@mosaicstack/memory` — preference store, insight store, semantic search
- `@mosaicstack/log` — log ingest, parsing, tiered storage
- Summarization pipeline
- Memory integration into agent sessions
- Skill management interface (web UI + CLI)
### Phase 5: Remote Control (v0.0.6)
- `@mosaic/discord-plugin` — Discord channel plugin
- `@mosaic/telegram-plugin` — Telegram channel plugin
- `@mosaicstack/discord-plugin` — Discord channel plugin
- `@mosaicstack/telegram-plugin` — Telegram channel plugin
- Plugin host in gateway
- SSO configuration (Authentik)
### Phase 6: CLI & Tools (v0.0.7)
- `@mosaic/cli` — unified CLI with all subcommands
- `@mosaic/prdy` — migrate from v0
- `@mosaic/quality-rails` — migrate from v0
- `@mosaic/mosaic` — install wizard updated for v1
- `@mosaicstack/cli` — unified CLI with all subcommands
- `@mosaicstack/prdy` — migrate from v0
- `@mosaicstack/quality-rails` — migrate from v0
- `@mosaicstack/mosaic` — install wizard updated for v1
- Pi TUI integration (`mosaic tui`)
### Phase 7: Polish & Beta (v0.0.8 → v0.1.0)
@@ -982,11 +982,11 @@ All work is **alpha** (< 0.1.0) until Jason approves 0.1.0 beta release.
## Assumptions
1. RESOLVED: **pgvector is sufficient** for semantic search at v0.1.0 scale (personal/family/team = thousands to low hundreds-of-thousands of vectors). `@mosaic/memory` defines a `VectorStore` interface with pgvector as the default adapter. The interface boundary makes Qdrant a drop-in migration if PG resource contention or scale demands it later. Zero additional infrastructure for v0.1.0. Rationale: Reduces ops burden; pgvector HNSW indexes are fast at this scale; interface abstraction costs almost nothing now.
1. RESOLVED: **pgvector is sufficient** for semantic search at v0.1.0 scale (personal/family/team = thousands to low hundreds-of-thousands of vectors). `@mosaicstack/memory` defines a `VectorStore` interface with pgvector as the default adapter. The interface boundary makes Qdrant a drop-in migration if PG resource contention or scale demands it later. Zero additional infrastructure for v0.1.0. Rationale: Reduces ops burden; pgvector HNSW indexes are fast at this scale; interface abstraction costs almost nothing now.
2. RESOLVED: **Authentik is the first SSO provider** — confirmed, already running in Jason's infrastructure. WorkOS and Keycloak adapters follow in Phase 7.
3. RESOLVED: **NestJS with Fastify adapter for the gateway.** The gateway's complexity (plugin host, agent pool, routing engine, WebSocket hub, MCP server, auth, brain/queue/memory/log integration) warrants NestJS's module system, DI, and guards. Fastify performance preserved via adapter. Aligns with USER.md stated stack ("NestJS API + Next.js web"). @mosaic/brain's Fastify code migrates into a NestJS module.
3. RESOLVED: **NestJS with Fastify adapter for the gateway.** The gateway's complexity (plugin host, agent pool, routing engine, WebSocket hub, MCP server, auth, brain/queue/memory/log integration) warrants NestJS's module system, DI, and guards. Fastify performance preserved via adapter. Aligns with USER.md stated stack ("NestJS API + Next.js web"). @mosaicstack/brain's Fastify code migrates into a NestJS module.
4. RESOLVED: **OpenTelemetry from Phase 0.** Wide-event logging is required from the start. OTEL auto-instrumentation for NestJS/PG/HTTP via `@opentelemetry/sdk-node`. SigNoz as the all-in-one OTEL backend (single Docker service). Every significant operation emits structured events with rich context. Custom spans for agent dispatch, routing decisions, memory writes. Rationale: Retrofitting observability is painful; baking it in from day one means consistent instrumentation across all services.
@@ -1002,4 +1002,4 @@ All work is **alpha** (< 0.1.0) until Jason approves 0.1.0 beta release.
10. ASSUMPTION: **Conversations and messages get their own PG tables** (not stored in brain's entity model). They follow a chat-specific schema with proper foreign keys to users and projects. Rationale: Chat has different access patterns (streaming, pagination, search) than brain entities.
11. RESOLVED: **Pi handles all target LLM providers natively.** Anthropic, OpenAI/Codex, Z.ai, Ollama, LM Studio, and llama.cpp are all supported via Pi's built-in providers or `models.json` configuration with `openai-completions` API type. No custom provider adapters needed in @mosaic/agent — only configuration management.
11. RESOLVED: **Pi handles all target LLM providers natively.** Anthropic, OpenAI/Codex, Z.ai, Ollama, LM Studio, and llama.cpp are all supported via Pi's built-in providers or `models.json` configuration with `openai-completions` API type. No custom provider adapters needed in @mosaicstack/agent — only configuration management.

View File

@@ -108,4 +108,4 @@ The web login page renders provider buttons from `NEXT_PUBLIC_*_ENABLED` flags.
## Failure mode
Provider config is optional, but partial config is rejected at startup. If any provider-specific env var is present without the full required set, `@mosaic/auth` throws a bootstrap error with the missing keys instead of silently registering a broken provider.
Provider config is optional, but partial config is rejected at startup. If any provider-specific env var is present without the full required set, `@mosaicstack/auth` throws a bootstrap error with the missing keys instead of silently registering a broken provider.

View File

@@ -91,7 +91,7 @@ packages/cli/src/tui/
```bash
cd /home/jwoltje/src/mosaic-mono-v1-worktrees/tui-improvements
pnpm --filter @mosaic/cli exec tsx src/cli.ts tui
pnpm --filter @mosaicstack/cli exec tsx src/cli.ts tui
# or after build:
node packages/cli/dist/cli.js tui --gateway http://localhost:14242
```
@@ -99,7 +99,7 @@ node packages/cli/dist/cli.js tui --gateway http://localhost:14242
### Quality Gates
```bash
pnpm --filter @mosaic/cli typecheck && pnpm --filter @mosaic/cli lint
pnpm --filter @mosaic/gateway typecheck && pnpm --filter @mosaic/gateway lint
pnpm --filter @mosaic/types typecheck
pnpm --filter @mosaicstack/cli typecheck && pnpm --filter @mosaicstack/cli lint
pnpm --filter @mosaicstack/gateway typecheck && pnpm --filter @mosaicstack/gateway lint
pnpm --filter @mosaicstack/types typecheck
```

View File

@@ -12,9 +12,9 @@
| SA-P1-002 | done | sonnet | Define StorageAdapter interface in packages/storage/src/types.ts | 3K |
| SA-P1-003 | done | sonnet | Define MemoryAdapter interface in packages/memory/src/types.ts | 3K |
| SA-P1-004 | done | sonnet | Create adapter factory pattern + config types | 3K |
| SA-P2-001 | done | sonnet | Refactor @mosaic/queue: wrap ioredis as BullMQ adapter | 3K |
| SA-P2-002 | done | sonnet | Create @mosaic/storage: wrap Drizzle as Postgres adapter | 6K |
| SA-P2-003 | done | sonnet | Refactor @mosaic/memory: extract pgvector adapter | 4K |
| SA-P2-001 | done | sonnet | Refactor @mosaicstack/queue: wrap ioredis as BullMQ adapter | 3K |
| SA-P2-002 | done | sonnet | Create @mosaicstack/storage: wrap Drizzle as Postgres adapter | 6K |
| SA-P2-003 | done | sonnet | Refactor @mosaicstack/memory: extract pgvector adapter | 4K |
| SA-P2-004 | done | sonnet | Update gateway modules to use factories + DI tokens | 5K |
| SA-P2-005 | done | opus | Verify Phase 2: all tests pass, typecheck clean | — |
| SA-P3-001 | done | sonnet | Implement local queue adapter: JSON file persistence | 5K |

View File

@@ -12,9 +12,9 @@ context: Agents coupled directly to infrastructure backends, bypassing intended
Current packages are **direct adapters**, not **middleware**:
| Package | Current State | Intended Design |
|---------|---------------|-----------------|
| `@mosaic/queue` | `ioredis` hardcoded | Interface → BullMQ OR local-files |
| `@mosaic/db` | Drizzle + Postgres hardcoded | Interface → Postgres OR SQLite OR JSON/MD |
| `@mosaic/memory` | pgvector required | Interface → pgvector OR sqlite-vec OR keyword-search |
| `@mosaicstack/queue` | `ioredis` hardcoded | Interface → BullMQ OR local-files |
| `@mosaicstack/db` | Drizzle + Postgres hardcoded | Interface → Postgres OR SQLite OR JSON/MD |
| `@mosaicstack/memory` | pgvector required | Interface → pgvector OR sqlite-vec OR keyword-search |
## The gateway and TUI import these packages directly, which means they they're coupled to specific infrastructure. Users cannot run Mosaic Stack without Postgres + Valkey.
@@ -46,15 +46,15 @@ The gateway imports the interface, not the backend. At startup it reads config a
```typescript
// What should have happened:
gateway/queue.service.ts @mosaic/queue (interface) queue.adapter.ts
gateway/queue.service.ts @mosaicstack/queue (interface) queue.adapter.ts
// What actually happened:
gateway/queue.service.ts @mosaic/queue ioredis (hardcoded)
gateway/queue.service.ts @mosaicstack/queue ioredis (hardcoded)
```
## The Current State Analysis
### `@mosaic/queue` (packages/queue/src/queue.ts)
### `@mosaicstack/queue` (packages/queue/src/queue.ts)
```typescript
import Redis from 'ioredis'; // ← Direct import of backend
@@ -68,7 +68,7 @@ export function createQueue(config?: QueueConfig): QueueHandle {
**Problem:** `ioredis` is imported in the package, not the adapter interface. Consumers cannot swap backends.
### `@mosaic/db` (packages/db/src/client.ts)
### `@mosaicstack/db` (packages/db/src/client.ts)
```typescript
import { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js';
@@ -84,10 +84,10 @@ export function createDb(url?: string): DbHandle {
**Problem:** Drizzle + Postgres is hardcoded. No SQLite, JSON, or file-based options.
### `@mosaic/memory` (packages/memory/src/memory.ts)
### `@mosaicstack/memory` (packages/memory/src/memory.ts)
```typescript
import type { Db } from '@mosaic/db'; // ← Depends on Drizzle/PG
import type { Db } from '@mosaicstack/db'; // ← Depends on Drizzle/PG
export function createMemory(db: Db): Memory {
return {
@@ -97,7 +97,7 @@ export function createMemory(db: Db): Memory {
}
```
**Problem:** Memory package is tightly coupled to `@mosaic/db` (which is Postgres-only). No alternative storage backends.
**Problem:** Memory package is tightly coupled to `@mosaicstack/db` (which is Postgres-only). No alternative storage backends.
## The Target Interfaces
@@ -361,7 +361,7 @@ Automated equivalent to Claude Code's "Dream: Memory Consolidation" cycle
**Implementation:**
```typescript
// In @mosaic/dream (new package)
// In @mosaicstack/dream (new package)
export async function runDreamCycle(config: DreamConfig): Promise<DreamResult> {
const memory = await loadMemoryAdapter(config.storage);
@@ -420,7 +420,7 @@ export async function runDreamCycle(config: DreamConfig): Promise<DreamResult> {
2. Move Drizzle logic to `packages/storage/src/adapters/postgres.ts`
3. Create SQLite adapter in `packages/storage/src/adapters/sqlite.ts`
4. Update gateway to use storage factory
5. Deprecate direct `@mosaic/db` imports
5. Deprecate direct `@mosaicstack/db` imports
#### 2.3 Memory Refactor
@@ -488,7 +488,7 @@ packages/
│ │ ├── types.ts # StorageAdapter interface
│ │ ├── index.ts # Factory function
│ │ └── adapters/
│ │ ├── postgres.ts # MOVED from @mosaic/db
│ │ ├── postgres.ts # MOVED from @mosaicstack/db
│ │ ├── sqlite.ts # NEW: SQLite adapter
│ │ └── files.ts # NEW: JSON/MD adapter
│ └── package.json
@@ -530,9 +530,9 @@ packages/
## Breaking Changes
1. **`@mosaic/db`** → **`@mosaic/storage`** (with migration guide)
2. Direct `ioredis` imports → Use `@mosaic/queue` factory
3. Direct `pgvector` queries → Use `@mosaic/memory` factory
1. **`@mosaicstack/db`** → **`@mosaicstack/storage`** (with migration guide)
2. Direct `ioredis` imports → Use `@mosaicstack/queue` factory
3. Direct `pgvector` queries → Use `@mosaicstack/memory` factory
4. Gateway startup now requires storage config (defaults to local)
## Non-Breaking Migration Path

View File

@@ -61,7 +61,7 @@ pnpm install
### 4. Initialize the database
```bash
pnpm --filter @mosaic/db db:migrate
pnpm --filter @mosaicstack/db db:migrate
```
### 5. Build all packages
@@ -73,7 +73,7 @@ pnpm build
### 6. Start the gateway
```bash
pnpm --filter @mosaic/gateway dev
pnpm --filter @mosaicstack/gateway dev
```
Or for production (after build):
@@ -86,10 +86,10 @@ node apps/gateway/dist/main.js
```bash
# Development
pnpm --filter @mosaic/web dev
pnpm --filter @mosaicstack/web dev
# Production (after build)
pnpm --filter @mosaic/web start
pnpm --filter @mosaicstack/web start
```
The web app runs on port `3000` by default.
@@ -157,7 +157,7 @@ pnpm build
### Step 5 — Run database migrations
```bash
pnpm --filter @mosaic/db db:migrate
pnpm --filter @mosaicstack/db db:migrate
```
### Step 6 — Start the gateway

View File

@@ -129,7 +129,7 @@ The gateway loads `.env` from the monorepo root via `dotenv` at startup
### 4. Push the Database Schema
```bash
pnpm --filter @mosaic/db db:push
pnpm --filter @mosaicstack/db db:push
```
This applies the Drizzle schema directly to the database (development only; use
@@ -138,7 +138,7 @@ migrations in production).
### 5. Start the Gateway
```bash
pnpm --filter @mosaic/gateway exec tsx src/main.ts
pnpm --filter @mosaicstack/gateway exec tsx src/main.ts
```
The gateway starts on port `14242` by default.
@@ -146,7 +146,7 @@ The gateway starts on port `14242` by default.
### 6. Start the Web App
```bash
pnpm --filter @mosaic/web dev
pnpm --filter @mosaicstack/web dev
```
The web app starts on port `3000` by default.
@@ -359,7 +359,7 @@ The `insights` table uses a `vector(1536)` column (pgvector) for semantic search
Apply schema changes directly to the dev database (no migration files created):
```bash
pnpm --filter @mosaic/db db:push
pnpm --filter @mosaicstack/db db:push
```
### Generating Migrations
@@ -367,7 +367,7 @@ pnpm --filter @mosaic/db db:push
For production-safe, versioned changes:
```bash
pnpm --filter @mosaic/db db:generate
pnpm --filter @mosaicstack/db db:generate
```
This creates a new SQL migration file in `packages/db/drizzle/`.
@@ -375,7 +375,7 @@ This creates a new SQL migration file in `packages/db/drizzle/`.
### Running Migrations
```bash
pnpm --filter @mosaic/db db:migrate
pnpm --filter @mosaicstack/db db:migrate
```
### Drizzle Config
@@ -387,8 +387,8 @@ directory are defined there.
1. Add the table definition to `packages/db/src/schema.ts`.
2. Export it from `packages/db/src/index.ts`.
3. Run `pnpm --filter @mosaic/db db:push` (dev) or
`pnpm --filter @mosaic/db db:generate && pnpm --filter @mosaic/db db:migrate`
3. Run `pnpm --filter @mosaicstack/db db:push` (dev) or
`pnpm --filter @mosaicstack/db db:generate && pnpm --filter @mosaicstack/db db:migrate`
(production).
---

View File

@@ -160,11 +160,11 @@ The `mosaic` CLI provides a terminal interface to the same gateway API.
### Installation
The CLI ships as part of the `@mosaic/cli` package:
The CLI ships as part of the `@mosaicstack/cli` package:
```bash
# From the monorepo root
pnpm --filter @mosaic/cli build
pnpm --filter @mosaicstack/cli build
node packages/cli/dist/cli.js --help
```

View File

@@ -23,7 +23,7 @@
**Step 2: Run test to verify it fails**
Run: `pnpm --filter @mosaic/gateway test -- src/chat/__tests__/chat-security.test.ts src/__tests__/resource-ownership.test.ts`
Run: `pnpm --filter @mosaicstack/gateway test -- src/chat/__tests__/chat-security.test.ts src/__tests__/resource-ownership.test.ts`
Expected: FAIL on current DTO/helper mismatch.
@@ -56,7 +56,7 @@ Run the same command and require green.
**Step 3: Run targeted tests**
Run: `pnpm --filter @mosaic/gateway test -- src/chat/__tests__/chat-security.test.ts src/__tests__/resource-ownership.test.ts`
Run: `pnpm --filter @mosaicstack/gateway test -- src/chat/__tests__/chat-security.test.ts src/__tests__/resource-ownership.test.ts`
Expected: PASS.

View File

@@ -26,7 +26,7 @@ This plan establishes the foundational architecture for these systems.
4. **Hot reload** — soft-restart the gateway to load new plugins/skills/commands without dropping connections
5. **Local primitives** — baseline commands that work even when disconnected from the gateway
6. **Workspaces** — structured, git-backed, per-user/per-project filesystem layout with chroot isolation
7. **Task orchestration** — unified `@mosaic/queue` layer bridging PG, workspace files, and Valkey for agent task assignment
7. **Task orchestration** — unified `@mosaicstack/queue` layer bridging PG, workspace files, and Valkey for agent task assignment
8. **Session garbage collection** — three-tier GC (session, sweep, full cold-start) across Valkey, PG, and filesystem
---
@@ -220,7 +220,7 @@ Without `onUnload`, hot-reload is impossible — would leak listeners, duplicate
---
## Type Contracts (`@mosaic/types`)
## Type Contracts (`@mosaicstack/types`)
### CommandDef — Gateway Command Manifest Entry
@@ -407,7 +407,7 @@ The condensation step is a lightweight LLM call (cheap model, small context) tha
### Using Existing Queue Package
The `@mosaic/queue` package already provides `createQueue()` returning an ioredis handle on `redis://localhost:6380`. The `/system` storage will use the same Valkey instance directly via the redis handle — no queue semantics needed, just `SET`/`GET`/`DEL`/`EXPIRE`.
The `@mosaicstack/queue` package already provides `createQueue()` returning an ioredis handle on `redis://localhost:6380`. The `/system` storage will use the same Valkey instance directly via the redis handle — no queue semantics needed, just `SET`/`GET`/`DEL`/`EXPIRE`.
---
@@ -415,7 +415,7 @@ The `@mosaic/queue` package already provides `createQueue()` returning an ioredi
### Storage
Postgres via `@mosaic/db`. The `preferences` table already exists in `packages/db/src/schema.ts` with the right shape:
Postgres via `@mosaicstack/db`. The `preferences` table already exists in `packages/db/src/schema.ts` with the right shape:
```typescript
// Existing schema — already has category + key + value JSONB
@@ -620,7 +620,7 @@ Aliases are resolved in `findCommand()` before manifest lookup.
### Phase 1: Types + Local Command Parsing (no gateway changes)
1. Add `CommandDef`, `CommandManifest`, new socket events to `@mosaic/types`
1. Add `CommandDef`, `CommandManifest`, new socket events to `@mosaicstack/types`
2. Add `parseSlashCommand()` utility to `packages/cli`
3. Add `role: 'system'` to `Message` type, render system messages in `MessageList`
4. Implement local-only commands: `/help`, `/stop`, `/cost`, `/status` (local state only)
@@ -639,7 +639,7 @@ Aliases are resolved in `findCommand()` before manifest lookup.
### Phase 3: Preferences & System Overrides
1. Create `user_preferences` table in `@mosaic/db`, Drizzle schema + migration
1. Create `user_preferences` table in `@mosaicstack/db`, Drizzle schema + migration
2. Create `PreferencesService` in gateway — CRUD + defaults + enforcement logic
3. Implement `/preferences` command (REST-executed)
4. Implement `/system` command — Valkey storage, session-scoped
@@ -1159,7 +1159,7 @@ Additional tool sets needed for workspace workflows:
- **Docker/Portainer tools** — container management, deployment
- These are registered as additional `ToolDefinition[]` sets, same pattern as existing tools
`@mosaic/prdy` already provides the PRD wizard tooling — the workspace structure gives it a canonical output location (`docs/PRD-<name>.md`).
`@mosaicstack/prdy` already provides the PRD wizard tooling — the workspace structure gives it a canonical output location (`docs/PRD-<name>.md`).
### Task Queue & Orchestration
@@ -1167,19 +1167,19 @@ Additional tool sets needed for workspace workflows:
There are currently two parallel systems for task management:
1. **`@mosaic/coord`** (file-based) — missions stored as `mission.json`, tasks in `TASKS.md`, file locks, session tracking, subprocess spawning. Built for single-machine orchestrator pattern.
1. **`@mosaicstack/coord`** (file-based) — missions stored as `mission.json`, tasks in `TASKS.md`, file locks, session tracking, subprocess spawning. Built for single-machine orchestrator pattern.
2. **PG tables** (`tasks`, `mission_tasks`, `missions`) — DB-backed CRUD with status, priority, assignee, project/mission FKs. Exposed via REST API and Brain repos.
These are not connected. `@mosaic/coord` reads/writes files. The DB tables are managed via MissionsController. An agent using `coord_mission_status` gets file-based data; the dashboard shows DB data.
These are not connected. `@mosaicstack/coord` reads/writes files. The DB tables are managed via MissionsController. An agent using `coord_mission_status` gets file-based data; the dashboard shows DB data.
#### Vision: `@mosaic/queue` as the Unified Task Layer
#### Vision: `@mosaicstack/queue` as the Unified Task Layer
`@mosaic/queue` becomes the task orchestration service — not just a Valkey queue primitive, but the coordinator between agents, DB, and workspace files:
`@mosaicstack/queue` becomes the task orchestration service — not just a Valkey queue primitive, but the coordinator between agents, DB, and workspace files:
```
┌──────────────────────────────────────────────┐
│ @mosaic/queue │
│ @mosaicstack/queue │
│ (Task Orchestration Service) │
│ │
│ ┌─────────────────┐ ┌──────────────────┐ │
@@ -1217,21 +1217,21 @@ These are not connected. `@mosaic/coord` reads/writes files. The DB tables are m
6. Agent completes → updates status via queue service → PG updated + file synced + lock released
7. Gateway/orchestrator monitors progress, assigns next based on dependencies
**Flatfile fallback:** If no PG configured, queue service writes to flatfiles in workspace (JSON task manifests). Preserves the `@mosaic/coord` file-based pattern for single-machine, no-DB deployments.
**Flatfile fallback:** If no PG configured, queue service writes to flatfiles in workspace (JSON task manifests). Preserves the `@mosaicstack/coord` file-based pattern for single-machine, no-DB deployments.
**What this replaces:**
- `@mosaic/coord`'s file-only task tracking → unified DB+file via queue service
- `@mosaicstack/coord`'s file-only task tracking → unified DB+file via queue service
- Direct PG CRUD for task status → routed through queue service for consistency
- Manual task assignment → queue-based distribution with agent claiming
**What this preserves:**
- `TASKS.md` file format — still the agent-readable working copy
- Mission structure from `@mosaic/coord` — creation, milestones, sessions
- `@mosaic/prdy` PRD workflow — writes to `docs/`, syncs metadata to DB
- Mission structure from `@mosaicstack/coord` — creation, milestones, sessions
- `@mosaicstack/prdy` PRD workflow — writes to `docs/`, syncs metadata to DB
> **Note:** This is a significant refactor of `@mosaic/coord` + `@mosaic/queue`. Warrants its own dedicated plan alongside the Gatekeeper plan.
> **Note:** This is a significant refactor of `@mosaicstack/coord` + `@mosaicstack/queue`. Warrants its own dedicated plan alongside the Gatekeeper plan.
### Chroot Agent Sandboxing
@@ -1271,7 +1271,7 @@ The following topics are significant enough to warrant their own dedicated plan
| Plan | Stub File | Scope |
| -------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------- |
| **Gatekeeper Service** | `docs/plans/gatekeeper-service.md` | PR review/merge agent, quality gates, CI integration, trust boundary design |
| **Task Queue Unification** | `docs/plans/task-queue-unification.md` | `@mosaic/queue` refactor, `@mosaic/coord` consolidation, DB+file sync, flatfile fallback |
| **Task Queue Unification** | `docs/plans/task-queue-unification.md` | `@mosaicstack/queue` refactor, `@mosaicstack/coord` consolidation, DB+file sync, flatfile fallback |
| **Chroot Sandboxing** | `docs/plans/chroot-sandboxing.md` | Chroot environment provisioning, capability management, Docker integration, namespace alternatives |
---
@@ -1447,7 +1447,7 @@ TUI requests fresh commands:manifest (reflects new provider availability)
### Implementation Notes
- Gateway stores poll state in Valkey: `mosaic:auth:poll:<pollToken>` with 5-min TTL
- `clipboardy` used for clipboard write in TUI (add as dep to `@mosaic/cli` if not already present)
- `clipboardy` used for clipboard write in TUI (add as dep to `@mosaicstack/cli` if not already present)
- On success, gateway emits a fresh `commands:manifest` via socket (reflects provider now connected)
---
@@ -1463,8 +1463,8 @@ mutable: boolean('mutable').notNull().default(true),
Generate and apply:
```bash
pnpm --filter @mosaic/db db:generate # generates migration SQL
pnpm --filter @mosaic/db db:migrate # applies to PG
pnpm --filter @mosaicstack/db db:generate # generates migration SQL
pnpm --filter @mosaicstack/db db:migrate # applies to PG
```
Platform enforcement keys (seeded with `mutable = false` by gateway `PreferencesService.onModuleInit()`):

View File

@@ -6,7 +6,7 @@
**Architecture:** The TUI gains a sidebar panel for conversation management (list/create/switch) fetched via REST from the gateway. A `useConversations` hook manages REST calls. A `useScrollableViewport` hook wraps the message list with virtual viewport logic. An app-level focus/mode state machine (`useAppMode`) controls which panel receives input. All new socket events for conversation listing use the existing REST API (`GET /api/conversations`).
**Tech Stack:** Ink 5, React 18, socket.io-client, fetch (for REST), @mosaic/types
**Tech Stack:** Ink 5, React 18, socket.io-client, fetch (for REST), @mosaicstack/types
---
@@ -125,7 +125,7 @@ export function useViewport(opts: UseViewportOptions): UseViewportReturn {
**Step 2: Typecheck**
Run: `pnpm --filter @mosaic/cli typecheck`
Run: `pnpm --filter @mosaicstack/cli typecheck`
Expected: PASS
**Step 3: Commit**
@@ -195,7 +195,7 @@ Note: Ink's `useInput` key object supports `pageUp`, `pageDown`. For Home/End, c
**Step 3: Typecheck and lint**
Run: `pnpm --filter @mosaic/cli typecheck && pnpm --filter @mosaic/cli lint`
Run: `pnpm --filter @mosaicstack/cli typecheck && pnpm --filter @mosaicstack/cli lint`
Expected: PASS
**Step 4: Commit**
@@ -354,7 +354,7 @@ export function useConversations(opts: UseConversationsOptions): UseConversation
**Step 2: Typecheck**
Run: `pnpm --filter @mosaic/cli typecheck`
Run: `pnpm --filter @mosaicstack/cli typecheck`
Expected: PASS
**Step 3: Commit**
@@ -415,7 +415,7 @@ export function useAppMode(): UseAppModeReturn {
**Step 2: Typecheck**
Run: `pnpm --filter @mosaic/cli typecheck`
Run: `pnpm --filter @mosaicstack/cli typecheck`
Expected: PASS
**Step 3: Commit**
@@ -555,7 +555,7 @@ export function Sidebar({
**Step 2: Typecheck**
Run: `pnpm --filter @mosaic/cli typecheck`
Run: `pnpm --filter @mosaicstack/cli typecheck`
Expected: PASS
**Step 3: Commit**
@@ -636,7 +636,7 @@ const clearMessages = useCallback(() => {
**Step 3: Typecheck and lint**
Run: `pnpm --filter @mosaic/cli typecheck && pnpm --filter @mosaic/cli lint`
Run: `pnpm --filter @mosaicstack/cli typecheck && pnpm --filter @mosaicstack/cli lint`
Expected: PASS
**Step 4: Commit**
@@ -739,7 +739,7 @@ In `bottom-bar.tsx`, add a hints line above the status lines (or integrate into
**Step 3: Typecheck and lint**
Run: `pnpm --filter @mosaic/cli typecheck && pnpm --filter @mosaic/cli lint`
Run: `pnpm --filter @mosaicstack/cli typecheck && pnpm --filter @mosaicstack/cli lint`
Expected: PASS
**Step 4: Commit**
@@ -919,7 +919,7 @@ In `message-list.tsx`:
**Step 2: Typecheck and lint**
Run: `pnpm --filter @mosaic/cli typecheck && pnpm --filter @mosaic/cli lint`
Run: `pnpm --filter @mosaicstack/cli typecheck && pnpm --filter @mosaicstack/cli lint`
Expected: PASS
**Step 3: Commit**
@@ -940,8 +940,8 @@ git commit -m "feat(cli): wire message search with highlight and viewport scroll
**Step 1: Full typecheck across all affected packages**
```bash
pnpm --filter @mosaic/cli typecheck && pnpm --filter @mosaic/cli lint
pnpm --filter @mosaic/types typecheck
pnpm --filter @mosaicstack/cli typecheck && pnpm --filter @mosaicstack/cli lint
pnpm --filter @mosaicstack/types typecheck
```
Expected: All PASS
@@ -951,7 +951,7 @@ Expected: All PASS
```bash
cd /home/jwoltje/src/mosaic-mono-v1-worktrees/tui-improvements
docker compose up -d
pnpm --filter @mosaic/cli exec tsx src/cli.ts tui
pnpm --filter @mosaicstack/cli exec tsx src/cli.ts tui
```
Verify:

View File

@@ -1,4 +1,4 @@
# Task Queue Unification — @mosaic/queue as Unified Orchestration Layer
# Task Queue Unification — @mosaicstack/queue as Unified Orchestration Layer
> **Status:** Stub — deferred. Referenced from `2026-03-15-agent-platform-architecture.md` (Task Queue & Orchestration section).
> Implement after Workspaces (P8-015) is complete. Requires workspace file structure to be in place.
@@ -12,7 +12,7 @@
Two disconnected task systems exist:
1. **`@mosaic/coord`** — file-based missions (`mission.json`, `TASKS.md`), file locks, subprocess spawning. Single-machine orchestrator pattern.
1. **`@mosaicstack/coord`** — file-based missions (`mission.json`, `TASKS.md`), file locks, subprocess spawning. Single-machine orchestrator pattern.
2. **PG tables** (`tasks`, `mission_tasks`, `missions`) — DB-backed CRUD, REST API, Brain repos.
An agent using `coord_mission_status` gets file data. The dashboard shows DB data. They are never in sync.
@@ -21,22 +21,22 @@ An agent using `coord_mission_status` gets file data. The dashboard shows DB dat
## Vision
`@mosaic/queue` becomes the unified task orchestration service bridging PG, workspace files, and Valkey:
`@mosaicstack/queue` becomes the unified task orchestration service bridging PG, workspace files, and Valkey:
- DB is source of truth for structured state (status, assignees, timestamps)
- Workspace files (`TASKS.md`, PRDs) are working copies for agent interaction
- Valkey handles real-time assignment queues and agent claim locks
- Flatfile fallback for no-DB single-machine deployments (preserves `@mosaic/coord` pattern)
- Flatfile fallback for no-DB single-machine deployments (preserves `@mosaicstack/coord` pattern)
---
## Scope (To Be Designed)
- [ ] `@mosaic/queue` refactor — elevate from ioredis primitive to task orchestration service
- [ ] `@mosaicstack/queue` refactor — elevate from ioredis primitive to task orchestration service
- [ ] DB ↔ file sync layer — writes to PG propagate to `TASKS.md`; file edits by agents sync back
- [ ] Task assignment queue — Valkey-backed RPUSH/BLPOP for agent task claiming
- [ ] Agent claim locks — `mosaic:queue:project:{id}:lock:{taskId}` with TTL
- [ ] `@mosaic/coord` consolidation — file-based ops ported into queue service; `@mosaic/coord` becomes thin adapter or deprecated
- [ ] `@mosaicstack/coord` consolidation — file-based ops ported into queue service; `@mosaicstack/coord` becomes thin adapter or deprecated
- [ ] Flatfile fallback — queue service writes JSON manifests when PG unavailable
- [ ] Status pub/sub — real-time task status updates via Valkey pub/sub
- [ ] Dependency resolution — block task assignment until dependencies are met
@@ -56,5 +56,5 @@ An agent using `coord_mission_status` gets file data. The dashboard shows DB dat
## References
- Original design context: `docs/plans/2026-03-15-agent-platform-architecture.md` → "Task Queue & Orchestration" section
- Current `@mosaic/coord` implementation: `packages/coord/src/`
- Current `@mosaic/queue` implementation: `packages/queue/src/`
- Current `@mosaicstack/coord` implementation: `packages/coord/src/`
- Current `@mosaicstack/queue` implementation: `packages/queue/src/`

View File

@@ -18,7 +18,7 @@
| Command | Result | Evidence |
| --- | --- | --- |
| `pnpm --filter @mosaic/gateway test -- src/chat/__tests__/chat-security.test.ts src/__tests__/resource-ownership.test.ts` | pass | 3 test files passed, 20 tests passed |
| `pnpm --filter @mosaicstack/gateway test -- src/chat/__tests__/chat-security.test.ts src/__tests__/resource-ownership.test.ts` | pass | 3 test files passed, 20 tests passed |
| `pnpm typecheck` | pass | turbo completed 18/18 package typecheck tasks |
| `pnpm lint` | pass | turbo completed 18/18 package lint tasks |
| `pnpm format:check` | pass | `All matched files use Prettier code style!` |

View File

@@ -302,7 +302,7 @@ a fully open-source, self-contained AI development pipeline
framework. The Forge pipeline, MACP protocol, and credential
resolver together form a complete agentic development system.
Packaged correctly, this could be published as
@mosaic/forge + @mosaic/macp — reusable by any team building
@mosaicstack/forge + @mosaicstack/macp — reusable by any team building
AI-native development workflows. The mosaic-stack repo becomes
a reference implementation. Other organizations adopt the
protocol. MACP becomes a standard.
@@ -335,7 +335,7 @@ runtime; packages/forge becomes the brain. These should be
designed as separable concerns from the start.
DEFERRED OPPORTUNITIES:
- Publish @mosaic/forge to npm (after consolidation stabilizes)
- Publish @mosaicstack/forge to npm (after consolidation stabilizes)
- MACP as an open protocol spec with multiple implementations
- Forge pipeline as a configurable product (enterprise personas,
custom stage sequences, SLA-based gate configuration)
@@ -539,7 +539,7 @@ is listed in WP2's scope (`learning_capture.py` + `learning_recall.py`).
If OpenBrain's interface is undefined, why is it in WP2 either?
Cut it from both WP2 and WP1. Make it a separate brief.
To the Moonshot: The "publish @mosaic/forge to npm" idea is
To the Moonshot: The "publish @mosaicstack/forge to npm" idea is
premature. Publishing a package externally means committing to
a public API and semver guarantees. Mosaic's pipeline is
actively evolving. Publishing now creates external consumers
@@ -1223,7 +1223,7 @@ consideration. They are NOT in scope for this consolidation.
memory capture/recall. Requires a standalone brief once
the interface is defined. High long-term value.
- @mosaic/forge external publication: After the consolidated
- @mosaicstack/forge external publication: After the consolidated
package stabilizes, evaluate publishing as an open-source
framework. Requires API freeze and semver commitment.

View File

@@ -0,0 +1,54 @@
# Scratchpad — issue #387 updater simplification + Gitea wrapper repo context
- Objective: simplify updater behavior to `@mosaicstack/mosaic` only, and fix Gitea wrapper scripts so merge/CI/issue operations work reliably when tea needs explicit repo/login context.
- Scope:
- `packages/mosaic/src/runtime/update-checker.ts`
- `packages/mosaic/__tests__/update-checker.test.ts`
- any package metadata/version bumps needed
- repo-source git wrappers under `packages/mosaic/framework/tools/git/`
- Constraints:
- Jason approved breaking changes; legacy `@mosaicstack/cli` support is out of scope.
- Keep changes focused and mergeable.
- Acceptance:
- updater only targets `@mosaicstack/mosaic`
- wrapper path works on Gitea in this environment without manual repo guessing
- PR merges squash-only after green CI
## Progress
### 2026-04-04
#### Update Checker Simplification (DONE)
- Removed `LEGACY_PKG`, `INSTALLED_PACKAGE_ORDER` constants — only `PKG = '@mosaicstack/mosaic'` remains
- `getInstalledVersion()` — removed loop over multiple packages, only checks `@mosaicstack/mosaic`
- `getLatestVersion()` — removed `installedPackage` parameter and candidate iteration; single query for `@mosaicstack/mosaic`
- `checkForUpdate()` — removed `currentPackage`-based cache key comparison; cache is now package-agnostic
- `RegistryCache` — removed `currentPackage` and `targetPackage` fields
- `formatUpdateNotice()` — removed `targetChanged` branch (package migration notice no longer relevant)
- All legacy fallback/compatibility logic removed
#### Test Updates (DONE)
- Removed legacy `@mosaicstack/cli` fallback test
- Removed cache cross-contamination test (was testing legacy→modern package transition)
- Added `does not query legacy @mosaicstack/cli package` test — asserts no `@mosaicstack/cli` npm commands are issued
- Added `returns empty result when package is not installed` test
- All 8 tests pass ✅
#### Gitea Wrapper Fixes (DONE)
- `pr-merge.sh`:
- Added `OWNER=$(get_repo_owner)` / `REPO=$(get_repo_name)` before case block
- tea merge command now includes `--repo $OWNER/$REPO --login ${GITEA_LOGIN:-mosaicstack}`
- `issue-close.sh`:
- Added `OWNER=$(get_repo_owner)` / `REPO=$(get_repo_name)` after detect_platform
- Both `tea issue comment` and `tea issue close` now include `--repo "$OWNER/$REPO" --login "${GITEA_LOGIN:-mosaicstack}"`
- `pr-ci-wait.sh`: No changes needed — uses curl API calls (not tea), already passes owner/repo correctly
- `detect-platform.sh`: No changes needed — provides the `get_repo_owner`/`get_repo_name` functions used by wrappers
#### Verification
- `vitest run` — 8/8 tests pass
- `tsc --noEmit` — no errors in update-checker.ts (pre-existing workspace dep errors unrelated)
- `eslint` — clean, no warnings

View File

@@ -10,15 +10,15 @@
- 2026-03-13: session started in worktree; loading gateway/plugin package context.
- 2026-03-13: implemented initial plugin module, service, interface, and AppModule wiring; pending verification.
- 2026-03-13: added `@mosaic/discord-plugin` as a gateway workspace dependency and regenerated `pnpm-lock.yaml`.
- 2026-03-13: added `@mosaicstack/discord-plugin` as a gateway workspace dependency and regenerated `pnpm-lock.yaml`.
- 2026-03-13: built gateway dependency chain so workspace packages exported `dist/*` for clean TypeScript resolution in this fresh worktree.
- 2026-03-13: verification complete.
## Verification
- `pnpm --filter @mosaic/gateway... build`
- `pnpm --filter @mosaic/gateway typecheck`
- `pnpm --filter @mosaic/gateway lint`
- `pnpm --filter @mosaicstack/gateway... build`
- `pnpm --filter @mosaicstack/gateway typecheck`
- `pnpm --filter @mosaicstack/gateway lint`
- `pnpm format:check`
- `pnpm typecheck`
- `pnpm lint`

View File

@@ -21,7 +21,7 @@
- `pnpm typecheck`
- `pnpm format:check`
- `docker compose up -d`
- `pnpm --filter @mosaic/db db:push`
- `pnpm --filter @mosaicstack/db db:push`
- `pnpm test`
- `pnpm build`
- Manual review of `.woodpecker/ci.yml` diff: publish steps are main-only, depend on `build`, and use secret-backed registry auth plus dual tags.

View File

@@ -0,0 +1,47 @@
# Gateway Install UX Fixes — 2026-04-04
## Context
User hit two publish-drift bugs on `mosaic gateway install` (fixed in #386 and
#389). On top of those, the install UX itself has three concrete problems:
1. Admin API token is generated by the bootstrap step and saved to
`~/.config/mosaic/gateway/meta.json`, but never shown to the user. There is
no way to retrieve it without reading the file or running `mosaic gateway
config` afterward.
2. When install crashes mid-way (e.g. daemon fails to become healthy), the
next run of `mosaic gateway install` prompts "Reinstall? [y/N]". Saying N
aborts, leaving the user with a half-configured install and no clear path
forward. There is no resume path.
3. Health-check failure only prints "Check logs: mosaic gateway logs" — forcing
the user to run another command to see the actual error.
## Goal
Make `mosaic gateway install` a single end-to-end, resumable command that shows
the admin token on creation and surfaces errors inline.
## Plan
- `install.ts`: detect partial state (meta exists, no admin token, daemon not
running) and skip already-completed phases instead of aborting.
- `install.ts`: add a prominent "Admin API Token" banner printed right after
bootstrap succeeds. Include copy-now warning.
- `install.ts`: on health-check timeout, read the tail of `LOG_FILE` and print
the last ~30 non-empty lines before returning.
- Keep `mosaic gateway config` as-is (view/edit env vars); this is not the
setup wizard.
- No new commands. No new flags yet.
## Out of scope
- Readline/stdin piping fragility (pre-existing, not related to user complaint).
- Refactor to a phased state machine (overkill for three targeted fixes).
## Verification
- Typecheck, lint, format (mandatory gates).
- Manual end-to-end: fresh install → confirm token displayed.
- Manual resume: delete daemon.pid mid-install → re-run → confirm it resumes.
- Manual failure: point ENV_FILE port to a used port → re-run → confirm log
tail is printed.

Some files were not shown because too many files have changed in this diff Show More