diff --git a/package.json b/package.json index 5f2a544e8..be00ed905 100644 --- a/package.json +++ b/package.json @@ -262,6 +262,8 @@ "dev:matrix:nutriphi": "pnpm --filter matrix-nutriphi-bot start:dev", "build:matrix:mana": "pnpm --filter matrix-mana-bot build", "build:matrix:all": "pnpm --filter 'matrix-*-bot' build", + "dev:llm-playground": "pnpm --filter @mana-llm/playground dev", + "build:llm-playground": "pnpm --filter @mana-llm/playground build", "prepare": "husky" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a91421a1c..e967a25c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5199,6 +5199,40 @@ importers: specifier: ^5.9.3 version: 5.9.3 + services/llm-playground: + dependencies: + marked: + specifier: ^17.0.0 + version: 17.0.1 + devDependencies: + '@sveltejs/adapter-node': + specifier: ^5.4.0 + version: 5.4.0(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.44.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.44.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))) + '@sveltejs/kit': + specifier: ^2.47.1 + version: 2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.44.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.44.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + '@sveltejs/vite-plugin-svelte': + specifier: ^6.2.0 + version: 6.2.1(svelte@5.44.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + '@tailwindcss/vite': + specifier: ^4.1.7 + version: 4.1.17(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + svelte: + specifier: ^5.41.0 + version: 5.44.0 + svelte-check: + specifier: ^4.3.3 + version: 4.3.4(picomatch@4.0.3)(svelte@5.44.0)(typescript@5.9.3) + tailwindcss: + specifier: ^4.1.17 + version: 4.1.17 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.1.7 + version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + services/mana-api-gateway: dependencies: '@manacore/shared-nestjs-auth': @@ -5769,6 +5803,40 @@ importers: specifier: ^5.7.3 version: 5.9.3 + services/matrix-chat-bot: + dependencies: + '@nestjs/common': + specifier: ^10.3.0 + version: 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/config': + specifier: ^3.1.1 + version: 3.3.0(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2) + '@nestjs/core': + specifier: ^10.3.0 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@10.4.20)(@nestjs/websockets@10.4.20)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/platform-express': + specifier: ^10.3.0 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.20) + matrix-bot-sdk: + specifier: ^0.7.1 + version: 0.7.1 + reflect-metadata: + specifier: ^0.2.1 + version: 0.2.2 + rxjs: + specifier: ^7.8.1 + version: 7.8.2 + devDependencies: + '@nestjs/cli': + specifier: ^10.3.0 + version: 10.4.9 + '@types/node': + specifier: ^20.10.0 + version: 20.19.25 + typescript: + specifier: ^5.3.0 + version: 5.9.3 + services/matrix-clock-bot: dependencies: '@nestjs/common': @@ -6050,6 +6118,40 @@ importers: specifier: ^5.3.0 version: 5.9.3 + services/matrix-presi-bot: + dependencies: + '@nestjs/common': + specifier: ^10.3.0 + version: 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2) + '@nestjs/config': + specifier: ^3.1.1 + version: 3.3.0(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(rxjs@7.8.2) + '@nestjs/core': + specifier: ^10.3.0 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@10.4.20)(@nestjs/websockets@10.4.20)(encoding@0.1.13)(reflect-metadata@0.1.14)(rxjs@7.8.2) + '@nestjs/platform-express': + specifier: ^10.3.0 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@10.4.20) + matrix-bot-sdk: + specifier: ^0.7.1 + version: 0.7.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.14 + rxjs: + specifier: ^7.8.1 + version: 7.8.2 + devDependencies: + '@nestjs/cli': + specifier: ^10.3.0 + version: 10.4.9 + '@types/node': + specifier: ^20.10.0 + version: 20.19.25 + typescript: + specifier: ^5.3.0 + version: 5.9.3 + services/matrix-project-doc-bot: dependencies: '@aws-sdk/client-s3': @@ -6108,6 +6210,74 @@ importers: specifier: ^5.7.3 version: 5.9.3 + services/matrix-questions-bot: + dependencies: + '@nestjs/common': + specifier: ^10.3.0 + version: 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2) + '@nestjs/config': + specifier: ^3.1.1 + version: 3.3.0(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(rxjs@7.8.2) + '@nestjs/core': + specifier: ^10.3.0 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@10.4.20)(@nestjs/websockets@10.4.20)(encoding@0.1.13)(reflect-metadata@0.1.14)(rxjs@7.8.2) + '@nestjs/platform-express': + specifier: ^10.3.0 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@10.4.20) + matrix-bot-sdk: + specifier: ^0.7.1 + version: 0.7.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.14 + rxjs: + specifier: ^7.8.1 + version: 7.8.2 + devDependencies: + '@nestjs/cli': + specifier: ^10.3.0 + version: 10.4.9 + '@types/node': + specifier: ^20.10.0 + version: 20.19.25 + typescript: + specifier: ^5.3.0 + version: 5.9.3 + + services/matrix-skilltree-bot: + dependencies: + '@nestjs/common': + specifier: ^10.3.0 + version: 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2) + '@nestjs/config': + specifier: ^3.1.1 + version: 3.3.0(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(rxjs@7.8.2) + '@nestjs/core': + specifier: ^10.3.0 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@10.4.20)(@nestjs/websockets@10.4.20)(encoding@0.1.13)(reflect-metadata@0.1.14)(rxjs@7.8.2) + '@nestjs/platform-express': + specifier: ^10.3.0 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@10.4.20) + matrix-bot-sdk: + specifier: ^0.7.1 + version: 0.7.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.14 + rxjs: + specifier: ^7.8.1 + version: 7.8.2 + devDependencies: + '@nestjs/cli': + specifier: ^10.3.0 + version: 10.4.9 + '@types/node': + specifier: ^20.10.0 + version: 20.19.25 + typescript: + specifier: ^5.3.0 + version: 5.9.3 + services/matrix-stats-bot: dependencies: '@nestjs/common': diff --git a/scripts/generate-env.mjs b/scripts/generate-env.mjs index 44050ace0..5eee6ccd1 100644 --- a/scripts/generate-env.mjs +++ b/scripts/generate-env.mjs @@ -634,6 +634,14 @@ const APP_CONFIGS = [ }, }, + // LLM Playground (SvelteKit) + { + path: 'services/llm-playground/.env', + vars: { + PUBLIC_MANA_LLM_URL: (env) => env.MANA_LLM_URL || 'http://localhost:3025', + }, + }, + // Zitare Telegram Bot { path: 'services/telegram-zitare-bot/.env', diff --git a/services/mana-llm/src/config.py b/services/mana-llm/src/config.py index 651e47fef..ac928c692 100644 --- a/services/mana-llm/src/config.py +++ b/services/mana-llm/src/config.py @@ -33,7 +33,7 @@ class Settings(BaseSettings): cache_ttl: int = 3600 # CORS - cors_origins: str = "http://localhost:5173,https://mana.how" + cors_origins: str = "http://localhost:5173,http://localhost:5190,https://mana.how" @property def cors_origins_list(self) -> list[str]: diff --git a/services/mana-llm/src/main.py b/services/mana-llm/src/main.py index 6607807f7..d826ee4bb 100644 --- a/services/mana-llm/src/main.py +++ b/services/mana-llm/src/main.py @@ -120,7 +120,7 @@ async def get_model(model_id: str) -> ModelInfo: # Chat completions endpoint -@app.post("/v1/chat/completions") +@app.post("/v1/chat/completions", response_model=None) async def chat_completions( request: ChatCompletionRequest, http_request: Request, diff --git a/services/mana-llm/src/models/__init__.py b/services/mana-llm/src/models/__init__.py index bb038e64e..1c1785e30 100644 --- a/services/mana-llm/src/models/__init__.py +++ b/services/mana-llm/src/models/__init__.py @@ -4,9 +4,14 @@ from .requests import ChatCompletionRequest, EmbeddingRequest from .responses import ( ChatCompletionResponse, ChatCompletionStreamResponse, + Choice, + DeltaContent, + EmbeddingData, EmbeddingResponse, + MessageResponse, ModelInfo, ModelsResponse, + StreamChoice, Usage, ) @@ -14,9 +19,14 @@ __all__ = [ "ChatCompletionRequest", "ChatCompletionResponse", "ChatCompletionStreamResponse", + "Choice", + "DeltaContent", + "EmbeddingData", "EmbeddingRequest", "EmbeddingResponse", + "MessageResponse", "ModelInfo", "ModelsResponse", + "StreamChoice", "Usage", ] diff --git a/services/mana-llm/src/providers/ollama.py b/services/mana-llm/src/providers/ollama.py index 0a613fe92..a0aed64bc 100644 --- a/services/mana-llm/src/providers/ollama.py +++ b/services/mana-llm/src/providers/ollama.py @@ -220,11 +220,21 @@ class OllamaProvider(LLMProvider): models = [] for model_data in data.get("models", []): name = model_data.get("name", "") + # Parse modified_at datetime string to Unix timestamp + created = None + if modified_at := model_data.get("modified_at"): + try: + from datetime import datetime + # Handle ISO format with timezone + dt = datetime.fromisoformat(modified_at.replace("Z", "+00:00")) + created = int(dt.timestamp()) + except (ValueError, TypeError): + pass models.append( ModelInfo( id=f"ollama/{name}", owned_by="ollama", - created=int(model_data.get("modified_at", 0)) or None, + created=created, ) ) return models