From 9db3967fe1e801cd2936a2d846a175e4be0d1d03 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sun, 12 Apr 2026 23:45:30 -0700 Subject: [PATCH] ci: update CI/CD configuration --- .../WINDSURF/.last-refresh.log | 14 +- .../ENV_AUDIT_LYSNRAI.md | 137 ++++++++--------- .../audit-repo-health.md | 140 +++++------------- .../learning_ai_common_plat/gitea-ci.md | 42 ++---- ...ish-outdated-packages-to-gitea-registry.md | 139 +++++++++++++++++ ...utdated-pnpm-packages-to-gitea-registry.md | 139 +++++++++++++++++ .../learning_ai_common_plat/repos.txt | 3 + .../verify-all-backends.md | 6 +- packages/llm-router/src/classifier.ts | 34 ++++- packages/llm-router/src/registry.ts | 3 +- packages/llm-router/src/selector.ts | 7 + packages/llm-router/src/types.ts | 6 +- pnpm-lock.yaml | 45 ++++-- 13 files changed, 488 insertions(+), 227 deletions(-) create mode 100644 __LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/publish-outdated-packages-to-gitea-registry.md create mode 100644 __LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/publish-outdated-pnpm-packages-to-gitea-registry.md diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log index c001720f..95cf354b 100644 --- a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log @@ -1,9 +1,9 @@ -Last refresh: 2026-04-03T06:28:08Z (2026-04-02 23:28:08 PDT) -Cascade conversations: 50 (298M) -Memories: 121 +Last refresh: 2026-04-13T06:13:49Z (2026-04-12 23:13:49 PDT) +Cascade conversations: 50 (421M) +Memories: 130 Implicit context: 20 -Code tracker dirs: 103 -File edit history: 4225 entries -Workspace storage: 37 workspaces +Code tracker dirs: 108 +File edit history: 4591 entries +Workspace storage: 41 workspaces Repo docs: 7 files across 2 repos -Repo workflows: 54 files across 12 repos +Repo workflows: 55 files across 12 repos diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_docs/learning_multimodal_memory_agents/ENV_AUDIT_LYSNRAI.md b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_docs/learning_multimodal_memory_agents/ENV_AUDIT_LYSNRAI.md index 1c3f8265..dae91428 100644 --- a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_docs/learning_multimodal_memory_agents/ENV_AUDIT_LYSNRAI.md +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_docs/learning_multimodal_memory_agents/ENV_AUDIT_LYSNRAI.md @@ -9,17 +9,17 @@ ## 1. Project → Env File Map -| # | Project | Env File | Port | -|---|---------|----------|------| -| 1 | Desktop app (`src/`) | `.env` (root) | — | -| 2 | Backend API (`backend/`) | `backend/.env` | 8000 | -| 3 | Admin Dashboard (`admin-dashboard-web/`) | `admin-dashboard-web/.env.local` | 3001 | -| 4 | User Dashboard (`user-dashboard-web/`) | `user-dashboard-web/.env.local` | 3002 | -| 5 | Tracker Dashboard (`tracker-dashboard-web/`) | `tracker-dashboard-web/.env.local` | 3003 | -| 6 | Billing Service (`services/billing-service/`) | `services/billing-service/.env` | 4002 | -| 7 | Growth Service (`services/growth-service/`) | `services/growth-service/.env` | 4001 | -| 8 | Platform Service (`services/platform-service/`) | `services/platform-service/.env` | 4003 | -| 9 | Tracker Service (`services/tracker-service/`) | `services/tracker-service/.env` | 4004 | +| # | Project | Env File | Port | +| --- | ----------------------------------------------- | ---------------------------------- | ---- | +| 1 | Desktop app (`src/`) | `.env` (root) | — | +| 2 | Backend API (`backend/`) | `backend/.env` | 8000 | +| 3 | Admin Dashboard (`admin-dashboard-web/`) | `admin-dashboard-web/.env.local` | 3001 | +| 4 | User Dashboard (`user-dashboard-web/`) | `user-dashboard-web/.env.local` | 3002 | +| 5 | Tracker Dashboard (`tracker-dashboard-web/`) | `tracker-dashboard-web/.env.local` | 3003 | +| 6 | Billing Service (`services/billing-service/`) | `services/billing-service/.env` | 4002 | +| 7 | Growth Service (`services/growth-service/`) | `services/growth-service/.env` | 4001 | +| 8 | Platform Service (`services/platform-service/`) | `services/platform-service/.env` | 4003 | +| 9 | Tracker Service (`services/tracker-service/`) | `services/tracker-service/.env` | 4004 | --- @@ -36,63 +36,63 @@ grep -rn 'MISSING_ENV_VALUE' --include='.env*' --include='*.env' . | grep -v nod ### 3.1 Root `.env` (Desktop App) -| Variable | Status | Action | -|----------|--------|--------| -| `APPLICATIONINSIGHTS_CONNECTION_STRING` | ❌ Empty | Get from Azure Portal → Application Insights → Overview | -| `ANH_CONNECTION_STRING` | ⚠️ Has `YOUR_KEY_HERE` placeholder | Replace with real SharedAccessKey from Azure Portal → Notification Hubs | +| Variable | Status | Action | +| --------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------- | +| `APPLICATIONINSIGHTS_CONNECTION_STRING` | ❌ Empty | Get from Azure Portal → Application Insights → Overview | +| `ANH_CONNECTION_STRING` | ⚠️ Has `YOUR_KEY_HERE` placeholder | Replace with real SharedAccessKey from Azure Portal → Notification Hubs | ### 3.2 `backend/.env` -| Variable | Status | Action | -|----------|--------|--------| -| `AZURE_EMAIL_CONNECTION_STRING` | ❌ Empty | Get from Azure Portal → Communication Services → Keys | -| `SMTP_HOST` | ❌ Empty | Configure if using SMTP fallback instead of Azure Communication Services | -| `SMTP_USER` | ❌ Empty | Configure if using SMTP fallback | -| `SMTP_PASS` | ❌ Empty | Configure if using SMTP fallback | +| Variable | Status | Action | +| ------------------------------- | -------- | ------------------------------------------------------------------------ | +| `AZURE_EMAIL_CONNECTION_STRING` | ❌ Empty | Get from Azure Portal → Communication Services → Keys | +| `SMTP_HOST` | ❌ Empty | Configure if using SMTP fallback instead of Azure Communication Services | +| `SMTP_USER` | ❌ Empty | Configure if using SMTP fallback | +| `SMTP_PASS` | ❌ Empty | Configure if using SMTP fallback | ### 3.3 `admin-dashboard-web/.env.local` -| Variable | Status | Action | -|----------|--------|--------| -| `NEXT_PUBLIC_POSTHOG_KEY` | ❌ Empty | Get from PostHog → Project Settings (optional — analytics) | +| Variable | Status | Action | +| -------------------------- | -------- | ---------------------------------------------------------- | +| `NEXT_PUBLIC_POSTHOG_KEY` | ❌ Empty | Get from PostHog → Project Settings (optional — analytics) | | `NEXT_PUBLIC_POSTHOG_HOST` | ❌ Empty | Get from PostHog → Project Settings (optional — analytics) | ### 3.4 `user-dashboard-web/.env.local` -| Variable | Status | Action | -|----------|--------|--------| +| Variable | Status | Action | +| -------------------------- | -------- | ------------------------------------------------------------------- | | `ENTERPRISE_EMAIL_DOMAINS` | ❌ Empty | Set comma-separated list of domains that qualify for Enterprise SSO | -| `MICROSOFT_CLIENT_ID` | ❌ Empty | Register app in Azure Portal → Entra ID → App registrations | -| `MICROSOFT_CLIENT_SECRET` | ❌ Empty | Same as above | -| `GOOGLE_CLIENT_ID` | ❌ Empty | Register app in Google Cloud Console → Credentials | -| `GOOGLE_CLIENT_SECRET` | ❌ Empty | Same as above | -| `NEXT_PUBLIC_POSTHOG_KEY` | ❌ Empty | PostHog analytics (optional) | -| `NEXT_PUBLIC_POSTHOG_HOST` | ❌ Empty | PostHog analytics (optional) | +| `MICROSOFT_CLIENT_ID` | ❌ Empty | Register app in Azure Portal → Entra ID → App registrations | +| `MICROSOFT_CLIENT_SECRET` | ❌ Empty | Same as above | +| `GOOGLE_CLIENT_ID` | ❌ Empty | Register app in Google Cloud Console → Credentials | +| `GOOGLE_CLIENT_SECRET` | ❌ Empty | Same as above | +| `NEXT_PUBLIC_POSTHOG_KEY` | ❌ Empty | PostHog analytics (optional) | +| `NEXT_PUBLIC_POSTHOG_HOST` | ❌ Empty | PostHog analytics (optional) | ### 3.5 `tracker-dashboard-web/.env.local` -| Variable | Status | Action | -|----------|--------|--------| -| `NEXT_PUBLIC_POSTHOG_KEY` | ❌ Empty | PostHog analytics (optional) | +| Variable | Status | Action | +| -------------------------- | -------- | ---------------------------- | +| `NEXT_PUBLIC_POSTHOG_KEY` | ❌ Empty | PostHog analytics (optional) | | `NEXT_PUBLIC_POSTHOG_HOST` | ❌ Empty | PostHog analytics (optional) | ### 3.6 `services/growth-service/.env` -| Variable | Status | Action | -|----------|--------|--------| +| Variable | Status | Action | +| --------------------------------- | -------- | ------------------------------------------------------------ | | `WEBHOOK_INVITATION_REDEEMED_URL` | ❌ Empty | Set to backend or platform-service webhook callback endpoint | -| `WEBHOOK_REFERRAL_STATUS_URL` | ❌ Empty | Set to backend or platform-service webhook callback endpoint | +| `WEBHOOK_REFERRAL_STATUS_URL` | ❌ Empty | Set to backend or platform-service webhook callback endpoint | ### 3.7 `services/billing-service/.env` -| Variable | Status | Action | -|----------|--------|--------| +| Variable | Status | Action | +| ------------------ | -------- | --------------------------------------------------------------- | | `PLAN_LIMITS_JSON` | ❌ Empty | Optional — set JSON with per-plan limits if overriding defaults | ### 3.8 `services/platform-service/.env` -| Variable | Status | Action | -|----------|--------|--------| +| Variable | Status | Action | +| ------------------------ | -------- | ------------------------------------------------------------------------ | | `RATE_LIMIT_CONFIG_JSON` | ❌ Empty | Optional — set JSON with per-endpoint rate limits if overriding defaults | ### 3.9 `services/tracker-service/.env` @@ -105,21 +105,21 @@ grep -rn 'MISSING_ENV_VALUE' --include='.env*' --include='*.env' . | grep -v nod These were missing from `.env` files but had known values, so they were filled in: -| Project | Variable | Value Added | -|---------|----------|-------------| -| Root `.env` | `PLATFORM_SERVICE_URL` | `http://localhost:4003` | -| Root `.env` | `LYSNR_API_URL` | `http://localhost:8000` | -| Root `.env` | `LYSNR_ADMIN_URL` | `http://localhost:3001` | -| Root `.env` | `LYSNR_DASHBOARD_URL` | `http://localhost:3002` | -| `backend/.env` | `BILLING_SERVICE_URL` | `http://localhost:4002` | -| `backend/.env` | `PLATFORM_SERVICE_URL` | `http://localhost:4003` | -| `backend/.env` | `CORS_ORIGINS` | Expanded to include all dashboard ports | -| `admin-dashboard-web/.env.local` | `STRIPE_PUBLISHABLE_KEY` | Test key (was missing) | -| `admin-dashboard-web/.env.local` | `STRIPE_WEBHOOK_SECRET` | Test key (was missing) | -| `admin-dashboard-web/.env.local` | `STRIPE_PRICE_PRO` | `price_1Szl2z...` | -| `admin-dashboard-web/.env.local` | `STRIPE_PRICE_ENTERPRISE` | `price_1Szl3D...` | -| `user-dashboard-web/.env.local` | `ENTERPRISE_EMAIL_DOMAINS` | Empty (needs config) | -| `services/billing-service/.env` | `USAGE_WARN_THRESHOLD` | `80` | +| Project | Variable | Value Added | +| -------------------------------- | -------------------------- | --------------------------------------- | +| Root `.env` | `PLATFORM_SERVICE_URL` | `http://localhost:4003` | +| Root `.env` | `LYSNR_API_URL` | `http://localhost:8000` | +| Root `.env` | `LYSNR_ADMIN_URL` | `http://localhost:3001` | +| Root `.env` | `LYSNR_DASHBOARD_URL` | `http://localhost:3002` | +| `backend/.env` | `BILLING_SERVICE_URL` | `http://localhost:4002` | +| `backend/.env` | `PLATFORM_SERVICE_URL` | `http://localhost:4003` | +| `backend/.env` | `CORS_ORIGINS` | Expanded to include all dashboard ports | +| `admin-dashboard-web/.env.local` | `STRIPE_PUBLISHABLE_KEY` | Test key (was missing) | +| `admin-dashboard-web/.env.local` | `STRIPE_WEBHOOK_SECRET` | Test key (was missing) | +| `admin-dashboard-web/.env.local` | `STRIPE_PRICE_PRO` | `price_1Szl2z...` | +| `admin-dashboard-web/.env.local` | `STRIPE_PRICE_ENTERPRISE` | `price_1Szl3D...` | +| `user-dashboard-web/.env.local` | `ENTERPRISE_EMAIL_DOMAINS` | Empty (needs config) | +| `services/billing-service/.env` | `USAGE_WARN_THRESHOLD` | `80` | --- @@ -134,24 +134,27 @@ These were missing from `.env` files but had known values, so they were filled i These values **must be identical** across all services that use them: -| Secret | Used By | -|--------|---------| -| `JWT_SECRET` | All 4 Fastify services + all 3 dashboards + backend | -| `COSMOS_ENDPOINT` | All 4 Fastify services + admin + user dashboards + backend + desktop | -| `COSMOS_KEY` | Same as above | -| `COSMOS_DATABASE` | Same as above (must be `lysnrai`) | -| `STRIPE_SECRET_KEY` | billing-service, growth-service, admin-dashboard, user-dashboard | -| `AZURE_BLOB_*` | platform-service, admin-dashboard, user-dashboard, desktop | +| Secret | Used By | +| ------------------- | -------------------------------------------------------------------- | +| `JWT_SECRET` | All 4 Fastify services + all 3 dashboards + backend | +| `COSMOS_ENDPOINT` | All 4 Fastify services + admin + user dashboards + backend + desktop | +| `COSMOS_KEY` | Same as above | +| `COSMOS_DATABASE` | Same as above (must be `lysnrai`) | +| `STRIPE_SECRET_KEY` | billing-service, growth-service, admin-dashboard, user-dashboard | +| `AZURE_BLOB_*` | platform-service, admin-dashboard, user-dashboard, desktop | --- ## 7. Production Deployment Notes -When deploying to **Vercel** (frontends) + **Railway** (backends): +When deploying to the current stack: + +- **Vercel** for public/front-end surfaces where applicable +- **Azure VM / shared infra** for backend and internal service hosting 1. **JWT_SECRET** — rotate to a new 64-char hex. Must match across ALL services. 2. **CORS_ORIGIN** — set on each Fastify service to restrict to Vercel domains (comma-separated). 3. **Stripe webhook** — create a new webhook in Stripe Dashboard pointing to production URL; update `STRIPE_WEBHOOK_SECRET`. 4. **SSO redirect URIs** — update `MICROSOFT_REDIRECT_URI` and `GOOGLE_REDIRECT_URI` to production Vercel domain. 5. **NEXTAUTH_URL** — set to production Vercel domain for user-dashboard. -6. **Service URLs** — replace all `localhost:*` with Railway public URLs. +6. **Service URLs** — replace all `localhost:*` with the current production API and service URLs. diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/audit-repo-health.md b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/audit-repo-health.md index 5625a79b..dc0078ca 100644 --- a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/audit-repo-health.md +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/audit-repo-health.md @@ -15,20 +15,12 @@ Systematically verify consistency across all ByteLyst product repos. Catches dri ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== packageManager in root package.json ===" -for repo in \ - learning_ai_common_plat \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue + [[ ! -f "$REPOS_DIR/$repo/package.json" ]] && continue printf "%-40s " "$repo:" grep '"packageManager"' "$REPOS_DIR/$repo/package.json" 2>/dev/null || echo "MISSING" -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` Expect: all repos show `"packageManager": "pnpm@10.6.5"`. Fix any MISSING entries. @@ -40,20 +32,12 @@ Expect: all repos show `"packageManager": "pnpm@10.6.5"`. Fix any MISSING entrie ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== node_modules in .gitignore ===" -for repo in \ - learning_ai_common_plat \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue + [[ ! -f "$REPOS_DIR/$repo/.gitignore" ]] && continue printf "%-40s " "$repo:" grep -c 'node_modules' "$REPOS_DIR/$repo/.gitignore" 2>/dev/null || echo "MISSING" -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` Expect: all repos have at least 1 match. Fix any with 0 or MISSING. @@ -65,16 +49,8 @@ Expect: all repos have at least 1 match. Fix any with 0 or MISSING. ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== .dockerignore health ===" -for repo in \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue di="$REPOS_DIR/$repo/.dockerignore" if [ ! -f "$di" ]; then echo "$repo: MISSING .dockerignore" @@ -83,10 +59,10 @@ for repo in \ else echo "$repo: OK" fi -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` -Expect: all OK. Any BUG entries will break Docker builds. +Expect: all OK (repos without .dockerignore are skipped). Any BUG entries will break Docker builds. ## 4. Check stale package-lock.json files @@ -95,19 +71,11 @@ Expect: all OK. Any BUG entries will break Docker builds. ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== Stale package-lock.json ===" -for repo in \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue found=$(find "$REPOS_DIR/$repo" -name "package-lock.json" -not -path "*/node_modules/*" 2>/dev/null) if [ -n "$found" ]; then echo "STALE: $found"; fi -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt echo "(empty = all clean)" ``` @@ -120,17 +88,9 @@ Expect: no output. Remove any stale lockfiles found. ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== Dockerfile base image + NODE_TLS ===" -for repo in \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do - for df in $(git -C "$REPOS_DIR/$repo" ls-files '*/Dockerfile' 2>/dev/null); do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue + for df in $(git -C "$REPOS_DIR/$repo" ls-files '*/Dockerfile' 'Dockerfile' 2>/dev/null); do full="$REPOS_DIR/$repo/$df" base=$(grep -m1 '^FROM' "$full" | awk '{print $2}') tls=$(grep -c 'NODE_TLS_REJECT_UNAUTHORIZED' "$full" 2>/dev/null) @@ -139,7 +99,7 @@ for repo in \ [[ "$tls" == "0" && "$df" != *python* ]] && status="$status WARN:no-NODE_TLS" echo "$repo/$df: base=$base tls=$tls $status" done -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` Expect: all use `node:22-slim`, all have `NODE_TLS` refs > 0. Fix any WARN entries. @@ -151,15 +111,9 @@ Expect: all use `node:22-slim`, all have `NODE_TLS` refs > 0. Fix any WARN entri ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== next.config.ts: transpilePackages + symlinks ===" -for repo in \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_notes \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do - for cfg in $(find "$REPOS_DIR/$repo" -maxdepth 2 -name "next.config.ts" -not -path "*/node_modules/*" 2>/dev/null); do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue + for cfg in $(find "$REPOS_DIR/$repo" -maxdepth 3 -name "next.config.ts" -not -path "*/node_modules/*" 2>/dev/null); do relpath="${cfg#$REPOS_DIR/}" tp=$(grep -c 'transpilePackages' "$cfg") sl=$(grep -c 'symlinks' "$cfg") @@ -168,7 +122,7 @@ for repo in \ [[ "$sl" == "0" ]] && status="$status MISSING:symlinks" echo "$relpath: transpile=$tp symlinks=$sl $status" done -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` Expect: all show transpile>0 and symlinks>0. Fix any MISSING entries. @@ -180,17 +134,10 @@ Expect: all show transpile>0 and symlinks>0. Fix any MISSING entries. ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== pnpm-workspace.yaml includes common-plat ===" -for repo in \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue ws="$REPOS_DIR/$repo/pnpm-workspace.yaml" + [[ ! -f "$ws" ]] && continue if [ ! -f "$ws" ]; then echo "$repo: MISSING pnpm-workspace.yaml" elif grep -q 'common_plat' "$ws"; then @@ -198,10 +145,10 @@ for repo in \ else echo "$repo: MISSING common-plat in workspace" fi -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` -Expect: all OK. Fix any MISSING entries. +Expect: all OK (repos without pnpm-workspace.yaml are skipped). Fix any MISSING entries. ## 8. Check docker-prep.sh uses shared prep-consumer @@ -210,16 +157,8 @@ Expect: all OK. Fix any MISSING entries. ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== docker-prep.sh uses shared prep-consumer ===" -for repo in \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue script="$REPOS_DIR/$repo/scripts/docker-prep.sh" if [ ! -f "$script" ]; then echo "$repo: NO docker-prep.sh" @@ -228,10 +167,10 @@ for repo in \ else echo "$repo: WARN — legacy docker-prep.sh" fi -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` -Expect: all OK. Legacy scripts should be replaced with the shared wrapper. +Expect: all OK (repos without docker-prep.sh are skipped). Legacy scripts should be replaced with the shared wrapper. ## 9. Check verify scripts reference correct package filter names @@ -240,19 +179,12 @@ Expect: all OK. Legacy scripts should be replaced with the shared wrapper. ```bash REPOS_DIR="/Users/sd9235/code/mygh" echo "=== Root verify scripts ===" -for repo in \ - learning_voice_ai_agent \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue + [[ ! -f "$REPOS_DIR/$repo/package.json" ]] && continue printf "%-40s " "$repo:" node -e "const p=require('$REPOS_DIR/$repo/package.json'); console.log(p.scripts?.verify || 'NONE')" 2>/dev/null -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` Review output manually — ensure `--filter` names match actual package names in sub-packages. diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/gitea-ci.md b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/gitea-ci.md index 9d3b234a..30ab2a86 100644 --- a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/gitea-ci.md +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/gitea-ci.md @@ -30,22 +30,14 @@ Each push triggers the `.gitea/workflows/ci.yml` workflow on the local runner. ```bash REPOS_DIR="/Users/sd9235/code/mygh" -for repo in \ - learning_ai_common_plat \ - learning_voice_ai_agent \ - learning_multimodal_memory_agents \ - learning_ai_clock \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_notes \ - learning_ai_flowmonk \ - learning_ai_trails \ - learning_ai_local_memory_gpt; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue + cd "$REPOS_DIR/$repo" 2>/dev/null || continue + # Skip repos without a gitea remote + git remote get-url gitea &>/dev/null || continue echo "=== $repo ===" - cd "$REPOS_DIR/$repo" git push gitea main 2>&1 | tail -2 -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` ## 4. Wait for jobs to process, then check results @@ -54,20 +46,14 @@ Wait ~2 minutes per repo for the runner (capacity=1) to process the queue, then ```bash REPOS_DIR="/Users/sd9235/code/mygh" -for repo in \ - learning_ai_common_plat \ - learning_ai_clock \ - learning_ai_trails \ - learning_ai_flowmonk \ - learning_ai_notes \ - learning_ai_fastgap \ - learning_ai_jarvis_jr \ - learning_ai_peakpulse \ - learning_ai_local_memory_gpt \ - learning_voice_ai_agent \ - learning_multimodal_memory_agents; do +while IFS= read -r repo; do + [[ -z "$repo" || "$repo" =~ ^# ]] && continue + cd "$REPOS_DIR/$repo" 2>/dev/null || continue + git remote get-url gitea &>/dev/null || continue + # Use basename for Gitea API (oss/learning_ai_claw-cowork → learning_ai_claw-cowork) + repo_name=$(basename "$repo") echo "=== $repo ===" - curl -s -u "bytelyst:bytelyst123" "http://localhost:3300/api/v1/repos/bytelyst/$repo/actions/jobs" | python3 -c " + curl -s -u "bytelyst:bytelyst123" "http://localhost:3300/api/v1/repos/bytelyst/$repo_name/actions/jobs" | python3 -c " import sys, json jobs = json.load(sys.stdin).get('jobs', []) if not jobs: @@ -80,7 +66,7 @@ else: icon = '✅' if c == 'success' else '❌' if c == 'failure' else '⏳' print(f' {icon} {c:12} {j[\"name\"]}') " 2>/dev/null -done +done < /Users/sd9235/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt ``` ## 5. (Optional) View logs for a failing job diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/publish-outdated-packages-to-gitea-registry.md b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/publish-outdated-packages-to-gitea-registry.md new file mode 100644 index 00000000..480ff9a0 --- /dev/null +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/publish-outdated-packages-to-gitea-registry.md @@ -0,0 +1,139 @@ +--- +description: Publish only outdated @bytelyst/* packages to the Gitea npm registry +--- + +# Publish Outdated Packages to Gitea Registry + +Detects which `@bytelyst/*` packages in `packages/` have local changes compared to what's published in the Gitea npm registry, and republishes only the outdated ones. + +**Registry (auto-detected via `NETWORK` env var):** + +- `NETWORK=corp` → `http://localhost:3300` (SSH tunnel to Azure VM) +- `NETWORK=home` → `http://:3300` (direct, from `~/.gitea_vm_host` or `gitea.bytelyst.com`) + +**Auth:** `GITEA_NPM_TOKEN` env var (auto-loaded from `~/.gitea_npm_token` by `switch-network.sh`) +**Token scope required:** `read:package` + `write:package` + +--- + +## Prerequisites + +The Gitea NPM token must have **both** `read:package` and `write:package` scopes. +To create/update the token: + +1. Open Gitea token settings: + - **Corp network:** `http://localhost:3300/-/user/settings/applications` + - **Home network:** `http://:3300/-/user/settings/applications` +2. Create a new token with scopes: `read:package`, `write:package` +3. Save it: `echo "" > ~/.gitea_npm_token` +4. Reload shell: `source ~/.zshrc` + +--- + +## Steps + +### 1. Verify prerequisites + +// turbo + +```bash +echo "Token: ${GITEA_NPM_TOKEN:0:5}..." && curl -s -o /dev/null -w "Gitea HTTP: %{http_code}\n" "http://${GITEA_NPM_HOST:-localhost}:3300/" +``` + +### 2. Dry-run: detect outdated packages + +Run the script in `--dry-run` mode first to see which packages need publishing without making any changes. + +// turbo + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && bash scripts/publish-outdated-gitea-packages.sh --dry-run +``` + +Review the output: + +- **UP-TO-DATE** — local content matches registry (no action needed) +- **OUTDATED** — local content differs from registry (will bump patch version + publish) +- **NOT FOUND** — version not in registry (will publish as-is) +- **SKIP** — native SDKs or packages without dist/ + +### 3. Publish outdated packages + +If the dry-run shows outdated packages, run the script without `--dry-run` to publish them. + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && bash scripts/publish-outdated-gitea-packages.sh +``` + +The script will: + +1. Build all packages (`pnpm build`) +2. Compare each package's local content fingerprint against the registry's +3. For outdated packages: auto-bump the patch version (e.g., 0.1.0 -> 0.1.1) and publish +4. For not-found packages: publish as-is (current version) +5. Print which `package.json` files were bumped so you can commit them + +### 4. Commit version bumps + +After publishing, the script reports which `package.json` files had their version bumped. Commit them: + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && git add packages/*/package.json && git commit -m "chore(packages): bump versions for Gitea registry publish" +``` + +### 5. (Optional) Publish a single package + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && bash scripts/publish-outdated-gitea-packages.sh --filter @bytelyst/errors +``` + +### 6. (Optional) Skip the build step + +If you already ran `pnpm build`: + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && bash scripts/publish-outdated-gitea-packages.sh --skip-build +``` + +--- + +## How detection works + +For each package in `packages/`: + +1. `pnpm pack` creates a local tarball +2. Downloads the same version's tarball from the registry +3. Extracts both and computes SHA-256 fingerprints of all file contents +4. If fingerprints differ (or version not in registry) -> marked for publish + +This is metadata-independent (ignores tar timestamps) and catches any source/dist change. + +## Corp proxy handling + +When `NETWORK=corp`, the script automatically: + +- Routes to `http://localhost:3300` (SSH tunnel) instead of the Azure VM +- Unsets all `NPM_CONFIG_*` and `*_proxy` env vars for the `npm publish` command + +On both networks, the script: + +- Strips `publishConfig.registry` from tarballs (avoids hardcoded external domain) +- Runs `npm publish` from `/tmp` (avoids repo `.npmrc` scoped registry override) + +--- + +## Troubleshooting + +| Issue | Fix | +| ----------------------------- | ----------------------------------------------------------------------------------------------------- | +| `GITEA_NPM_TOKEN is required` | Run `source ~/.zshrc` or `export GITEA_NPM_TOKEN=$(cat ~/.gitea_npm_token)` | +| Gitea unreachable | Check if Gitea VM is running. Verify `GITEA_NPM_HOST` resolves | +| E401 on publish | Token needs `write:package` scope. Regenerate at `http://localhost:3300/-/user/settings/applications` | +| All packages show OUTDATED | Normal after first run. Subsequent runs will show UP-TO-DATE for unchanged packages | +| Package has no dist/ | Run `pnpm build` first or don't use `--skip-build` | + +## Script location + +`scripts/publish-outdated-gitea-packages.sh` in `learning_ai_common_plat` + +Run `bash scripts/publish-outdated-gitea-packages.sh --help` for usage. diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/publish-outdated-pnpm-packages-to-gitea-registry.md b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/publish-outdated-pnpm-packages-to-gitea-registry.md new file mode 100644 index 00000000..003646fc --- /dev/null +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/publish-outdated-pnpm-packages-to-gitea-registry.md @@ -0,0 +1,139 @@ +--- +description: Publish only outdated @bytelyst/* pnpm packages to the Gitea npm registry +--- + +# Publish Outdated pnpm Packages to Gitea Registry + +Detects which `@bytelyst/*` pnpm packages in `packages/` have local changes compared to what's published in the Gitea npm registry, and republishes only the outdated ones. + +**Registry (auto-detected via `NETWORK` env var):** + +- `NETWORK=corp` → `http://localhost:3300` (SSH tunnel to Azure VM) +- `NETWORK=home` → `http://:3300` (direct, from `~/.gitea_vm_host` or `gitea.bytelyst.com`) + +**Auth:** `GITEA_NPM_TOKEN` env var (auto-loaded from `~/.gitea_npm_token` by `switch-network.sh`) +**Token scope required:** `read:package` + `write:package` + +--- + +## Prerequisites + +The Gitea NPM token must have **both** `read:package` and `write:package` scopes. +To create/update the token: + +1. Open Gitea token settings: + - **Corp network:** `http://localhost:3300/-/user/settings/applications` + - **Home network:** `http://:3300/-/user/settings/applications` +2. Create a new token with scopes: `read:package`, `write:package` +3. Save it: `echo "" > ~/.gitea_npm_token` +4. Reload shell: `source ~/.zshrc` + +--- + +## Steps + +### 1. Verify prerequisites + +// turbo + +```bash +echo "Token: ${GITEA_NPM_TOKEN:0:5}..." && curl -s -o /dev/null -w "Gitea HTTP: %{http_code}\n" "http://${GITEA_NPM_HOST:-localhost}:3300/" +``` + +### 2. Dry-run: detect outdated packages + +Run the script in `--dry-run` mode first to see which packages need publishing without making any changes. + +// turbo + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && bash scripts/publish-outdated-gitea-packages.sh --dry-run +``` + +Review the output: + +- **UP-TO-DATE** — local content matches registry (no action needed) +- **OUTDATED** — local content differs from registry (will bump patch version + publish) +- **NOT FOUND** — version not in registry (will publish as-is) +- **SKIP** — native SDKs or packages without dist/ + +### 3. Publish outdated packages + +If the dry-run shows outdated packages, run the script without `--dry-run` to publish them. + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && bash scripts/publish-outdated-gitea-packages.sh +``` + +The script will: + +1. Build all packages (`pnpm build`) +2. Compare each package's local content fingerprint against the registry's +3. For outdated packages: auto-bump the patch version (e.g., 0.1.0 -> 0.1.1) and publish +4. For not-found packages: publish as-is (current version) +5. Print which `package.json` files were bumped so you can commit them + +### 4. Commit version bumps + +After publishing, the script reports which `package.json` files had their version bumped. Commit them: + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && git add packages/*/package.json && git commit -m "chore(packages): bump versions for Gitea registry publish" +``` + +### 5. (Optional) Publish a single package + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && bash scripts/publish-outdated-gitea-packages.sh --filter @bytelyst/errors +``` + +### 6. (Optional) Skip the build step + +If you already ran `pnpm build`: + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && bash scripts/publish-outdated-gitea-packages.sh --skip-build +``` + +--- + +## How detection works + +For each package in `packages/`: + +1. `pnpm pack` creates a local tarball +2. Downloads the same version's tarball from the registry +3. Extracts both and computes SHA-256 fingerprints of all file contents +4. If fingerprints differ (or version not in registry) -> marked for publish + +This is metadata-independent (ignores tar timestamps) and catches any source/dist change. + +## Corp proxy handling + +When `NETWORK=corp`, the script automatically: + +- Routes to `http://localhost:3300` (SSH tunnel) instead of the Azure VM +- Unsets all `NPM_CONFIG_*` and `*_proxy` env vars for the `npm publish` command + +On both networks, the script: + +- Strips `publishConfig.registry` from tarballs (avoids hardcoded external domain) +- Runs `npm publish` from `/tmp` (avoids repo `.npmrc` scoped registry override) + +--- + +## Troubleshooting + +| Issue | Fix | +| ----------------------------- | ----------------------------------------------------------------------------------------------------- | +| `GITEA_NPM_TOKEN is required` | Run `source ~/.zshrc` or `export GITEA_NPM_TOKEN=$(cat ~/.gitea_npm_token)` | +| Gitea unreachable | Check if Gitea VM is running. Verify `GITEA_NPM_HOST` resolves | +| E401 on publish | Token needs `write:package` scope. Regenerate at `http://localhost:3300/-/user/settings/applications` | +| All packages show OUTDATED | Normal after first run. Subsequent runs will show UP-TO-DATE for unchanged packages | +| Package has no dist/ | Run `pnpm build` first or don't use `--skip-build` | + +## Script location + +`scripts/publish-outdated-gitea-packages.sh` in `learning_ai_common_plat` + +Run `bash scripts/publish-outdated-gitea-packages.sh --help` for usage. diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/repos.txt b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/repos.txt index 6f0530b6..e7e4e11a 100644 --- a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/repos.txt +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/repos.txt @@ -30,3 +30,6 @@ learning_ai_productivity_web # --- OSS (subdirectory repos under oss/) --- oss/learning_ai_claw-code-oss oss/learning_ai_claw-cowork + +# -- tooling -- +learning_ai_mac_tooling diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/verify-all-backends.md b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/verify-all-backends.md index fdbbd45b..2fac093f 100644 --- a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/verify-all-backends.md +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/repo_workflows/learning_ai_common_plat/verify-all-backends.md @@ -39,7 +39,7 @@ for entry in \ "learning_ai_peakpulse:@peakpulse/backend" \ "learning_voice_ai_agent:@lysnrai/backend" \ "learning_ai_flowmonk:@flowmonk/backend" \ - "learning_ai_notes:@notelett/backend"; do + "learning_ai_efforise:@efforise/backend"; do repo="${entry%%:*}" filter="${entry##*:}" @@ -83,7 +83,9 @@ for entry in \ "learning_ai_clock:web" \ "learning_ai_jarvis_jr:jarvisjr-web" \ "learning_voice_ai_agent:user-dashboard-web" \ - "learning_ai_flowmonk:@flowmonk/web"; do + "learning_ai_flowmonk:@flowmonk/web" \ + "learning_ai_efforise:client" \ + "learning_ai_local_llms:dashboard"; do repo="${entry%%:*}" filter="${entry##*:}" diff --git a/packages/llm-router/src/classifier.ts b/packages/llm-router/src/classifier.ts index b76e8bfb..b8b5c955 100644 --- a/packages/llm-router/src/classifier.ts +++ b/packages/llm-router/src/classifier.ts @@ -53,14 +53,43 @@ function countMatches(text: string, patterns: RegExp[]): number { return count; } +/** + * Check if messages contain image content parts (vision request). + * Handles both string content and multipart content arrays. + */ +function hasImageContent(messages: { role: string; content: string | unknown[] }[]): boolean { + for (const msg of messages) { + if (Array.isArray(msg.content)) { + for (const part of msg.content) { + if ( + typeof part === 'object' && + part !== null && + 'type' in part && + (part as { type: string }).type === 'image_url' + ) { + return true; + } + } + } + } + return false; +} + /** * Classify a prompt into a category based on keyword matching. * No LLM needed — pure regex heuristics. + * Detects vision (image) content and returns 'vision' category when present. */ export function classifyPrompt( - messages: { role: string; content: string }[] + messages: { role: string; content: string | unknown[] }[] ): ClassificationResult { - const fullText = messages.map(m => m.content).join('\n'); + // Check for vision content first — image inputs always classify as 'vision' + if (hasImageContent(messages)) { + const fullText = messages.map(m => (typeof m.content === 'string' ? m.content : '')).join('\n'); + return { category: 'vision', estimatedTokens: estimateTokens(fullText) + 1000 }; + } + + const fullText = messages.map(m => (typeof m.content === 'string' ? m.content : '')).join('\n'); const estimatedTokens = estimateTokens(fullText); const scores: Record = { @@ -69,6 +98,7 @@ export function classifyPrompt( reasoning: countMatches(fullText, REASONING_PATTERNS), creative: countMatches(fullText, CREATIVE_PATTERNS), general: 1, // baseline + vision: 0, }; // Pick highest scoring category diff --git a/packages/llm-router/src/registry.ts b/packages/llm-router/src/registry.ts index cc1f16b8..5c2c7d6b 100644 --- a/packages/llm-router/src/registry.ts +++ b/packages/llm-router/src/registry.ts @@ -24,8 +24,9 @@ export const PAID_PROVIDERS: ProviderConfig[] = [ id: 'gpt-4o', label: 'GPT-4o', contextWindow: 128_000, - strengths: ['general', 'reasoning', 'code', 'creative'], + strengths: ['general', 'reasoning', 'code', 'creative', 'vision'], speedTier: 2, + supportsVision: true, }, ], }, diff --git a/packages/llm-router/src/selector.ts b/packages/llm-router/src/selector.ts index 1d82e9f7..48c38216 100644 --- a/packages/llm-router/src/selector.ts +++ b/packages/llm-router/src/selector.ts @@ -18,6 +18,12 @@ export function createRoundRobinState(): Map { function scoreModel(model: ModelConfig, category: PromptCategory): number { let score = 0; + // Vision requests require vision-capable models + if (category === 'vision') { + if (!model.supportsVision) return -1; // Exclude non-vision models + score += 15; // Strong boost for vision capability + } + // Direct strength match is the strongest signal if (model.strengths.includes(category)) { score += 10; @@ -56,6 +62,7 @@ export function selectCandidates( if (!health.isHealthy(provider.name, model.id)) continue; const score = scoreModel(model, category); + if (score < 0) continue; // Skip incompatible models (e.g. non-vision for vision requests) candidates.push({ provider, model, score }); } } diff --git a/packages/llm-router/src/types.ts b/packages/llm-router/src/types.ts index cc8abee4..48312914 100644 --- a/packages/llm-router/src/types.ts +++ b/packages/llm-router/src/types.ts @@ -11,6 +11,10 @@ export interface ModelConfig { strengths: PromptCategory[]; /** Relative speed tier: 1 = fastest, 3 = slowest */ speedTier: 1 | 2 | 3; + /** Whether the model supports vision (image) inputs */ + supportsVision?: boolean; + /** Whether the model supports text embedding generation */ + supportsEmbedding?: boolean; } export interface ProviderConfig { @@ -32,7 +36,7 @@ export interface ProviderConfig { // ── Prompt Classification ────────────────────────────────────── -export type PromptCategory = 'code' | 'math' | 'reasoning' | 'creative' | 'general'; +export type PromptCategory = 'code' | 'math' | 'reasoning' | 'creative' | 'general' | 'vision'; export interface ClassificationResult { category: PromptCategory; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 26317f8e..660c3717 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -194,7 +194,7 @@ importers: version: 9.39.2(jiti@2.6.1) eslint-config-next: specifier: 16.1.6 - version: 16.1.6(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 16.1.6(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) husky: specifier: ^9.0.0 version: 9.1.7 @@ -291,7 +291,7 @@ importers: version: 9.39.2(jiti@2.6.1) eslint-config-next: specifier: 16.1.6 - version: 16.1.6(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 16.1.6(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) husky: specifier: ^9.0.0 version: 9.1.7 @@ -19570,23 +19570,23 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@3.2.4(msw@2.12.10(@types/node@20.19.33)(typescript@5.9.3))(vite@6.4.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@3.2.4(msw@2.12.10(@types/node@20.19.33)(typescript@5.9.3))(vite@7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.10(@types/node@20.19.33)(typescript@5.9.3) - vite: 6.4.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/mocker@3.2.4(msw@2.12.10(@types/node@22.19.11)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@3.2.4(msw@2.12.10(@types/node@22.19.11)(typescript@5.9.3))(vite@7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.10(@types/node@22.19.11)(typescript@5.9.3) - vite: 6.4.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) '@vitest/mocker@4.0.18(msw@2.12.10(@types/node@20.19.33)(typescript@5.9.3))(vite@7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': dependencies: @@ -20897,7 +20897,7 @@ snapshots: '@next/eslint-plugin-next': 16.1.6 eslint: 9.39.2(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1)) @@ -20920,7 +20920,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 @@ -20935,6 +20935,21 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + get-tsconfig: 4.13.6 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)): dependencies: debug: 3.2.7 @@ -20946,14 +20961,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) eslint: 9.39.2(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -20997,7 +21012,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.2(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -25587,7 +25602,7 @@ snapshots: dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.12.10(@types/node@20.19.33)(typescript@5.9.3))(vite@6.4.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(msw@2.12.10(@types/node@20.19.33)(typescript@5.9.3))(vite@7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -25605,7 +25620,7 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) vite-node: 3.2.4(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: @@ -25631,7 +25646,7 @@ snapshots: dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.12.10(@types/node@22.19.11)(typescript@5.9.3))(vite@6.4.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(msw@2.12.10(@types/node@22.19.11)(typescript@5.9.3))(vite@7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -25649,7 +25664,7 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) vite-node: 3.2.4(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: