mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-26 02:59:37 +00:00
335015d9e2
Closes the two gaps found smoke-testing the local stack: an empty gallery (zero media_files rows, media URLs hardcoded to the remote r2.dev bucket) and generation flows that could not complete (omni_gen calls providers synchronously in the handler, so dummy keys meant a 500 after billing; the webapp blocked submits earlier anyway because signup grants no wallet). Backend (all development-only): - CDN_BASE_URL env override in cdn_link.rs (host-only, validated loudly; precedence over the compiled-in hosts for every domain/env) and a dev-gated actix-files mount serving LOCAL_MEDIA_ROOT/media at /media, mirroring the public bucket layout - media URLs in API responses resolve against the backend itself - DEV_FAKE_GENERATION flag on ServerState (easyenv bool, forced off outside Development): the omni_gen image/video pipelines skip the external provider call and return a synthetic Fal enqueue (external id fake_<uuid>), so billing, prompt insert, and the pending generic_inference_jobs row all stay real - dev_fake_generation_resolver_thread: polls pending fake_ jobs (new runtime-query list_pending_fake_generation_jobs in mysql_queries) and after DEV_FAKE_GENERATION_RESOLVE_SECS (default 6s) marks them complete_success with a media_files row backed by a test_data asset copied under LOCAL_MEDIA_ROOT (mp4 results get -thumb.jpg/-thumb.gif siblings since the thumbnail job never runs locally), or complete_failure via the existing simulate_artcraft_failure prompt triggers (category word supported, e.g. "simulate_artcraft_failure face_not_detected") Bootstrap/seeds (PS + bash kept in lockstep): - seed_demo_user seeds an artcraft wallet (DEMO_CREDITS, default 100k banked + ledger rows; idempotent top-up) - signup creates no wallet and the webapp gates generate on balance, which is why submits went nowhere - seed_demo_user also seeds 6 gallery images (test_data jpgs) with objects under .devstack/media in the exact bucket fan-out layout - fixed the already-exists detection in seed_demo_user: create_account returns error_type, not error_code, so re-runs died on UsernameTaken - generated secrets env gains DEV_FAKE_GENERATION/CDN_BASE_URL/ LOCAL_MEDIA_ROOT (appended to existing files on bootstrap re-runs); stale "providers are only contacted by workers" comments corrected - doctor checks wallet balance, media rows, and the new secrets keys Docs: dev_setup_local_stack.md documents the new flags, corrects the sync-provider-call and upload-500 claims, updates the seams table and verification checklist; storyteller_web CLAUDE.md video model examples fixed (seedance_2p0_fast_g -> seedance_2p0_fast). Verified E2E on this machine: gallery lists 8 items on localhost URLs; image and video submits go pending ~6s then complete with locally-served results (mp4 + gif preview 200); failure trigger yields complete_failure with category face_not_detected; credits genuinely deducted (100000 -> 99932); doctor 0 failures / 0 warnings.
172 lines
6.9 KiB
PowerShell
172 lines
6.9 KiB
PowerShell
# Diagnose the local dev stack on Windows: checks every prerequisite the
|
|
# bootstrap sets up and reports PASS / WARN / FAIL per item.
|
|
#
|
|
# FAIL = the stack cannot work until fixed (exit code 1).
|
|
# WARN = optional or run-time-only (e.g. backend not currently running).
|
|
param()
|
|
|
|
. (Join-Path $PSScriptRoot "common.ps1")
|
|
$ErrorActionPreference = "Continue"
|
|
|
|
$script:Failures = 0
|
|
$script:Warnings = 0
|
|
|
|
function Pass([string]$Message) { Write-Host " PASS $Message" }
|
|
function Fail([string]$Message) { Write-Host " FAIL $Message" -ForegroundColor Red; $script:Failures++ }
|
|
function WarnCheck([string]$Message) { Write-Host " WARN $Message" -ForegroundColor Yellow; $script:Warnings++ }
|
|
|
|
Write-Host "Dev stack doctor ($RootDir)"
|
|
Write-Host ""
|
|
Write-Host "--- Toolchains ---"
|
|
|
|
Add-SessionPath @((Join-Path $env:USERPROFILE ".cargo\bin"))
|
|
Add-MySqlClientToSession
|
|
# Freshly-installed build tools may not be on this session's PATH yet.
|
|
Add-BuildToolsToSession
|
|
|
|
if (Get-Command cargo -ErrorAction SilentlyContinue) {
|
|
Pass "rust: $(rustc --version)"
|
|
} else {
|
|
Fail "rust: cargo not on PATH (winget install Rustlang.Rustup)"
|
|
}
|
|
|
|
if (Get-Command diesel -ErrorAction SilentlyContinue) {
|
|
$dv = Invoke-Native "diesel --version"
|
|
if ($LASTEXITCODE -eq 0) { Pass "diesel_cli: $dv" }
|
|
else { Fail "diesel_cli: present but broken (libmysql.dll missing from PATH? re-run bootstrap)" }
|
|
} else {
|
|
Fail "diesel_cli: not installed (bootstrap installs it against the portable MySQL client lib)"
|
|
}
|
|
|
|
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
$nodeMajor = [int]((node --version) -replace '^v(\d+).*', '$1')
|
|
if ($nodeMajor -ge 20) { Pass "node: $(node --version) (>= 20 required by Nx 21 / Vite 6)" }
|
|
else { Fail "node: $(node --version) is too old - Node 20+ required" }
|
|
} else {
|
|
Fail "node: not installed (Node 20+ required for the frontend)"
|
|
}
|
|
|
|
foreach ($tool in @("cmake", "perl", "nasm", "clang")) {
|
|
if (Get-Command $tool -ErrorAction SilentlyContinue) {
|
|
Pass "${tool}: found"
|
|
} else {
|
|
WarnCheck "${tool}: not on PATH (needed to COMPILE the backend; bootstrap offers winget installs)"
|
|
}
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "--- Services (portable, under .devstack\) ---"
|
|
|
|
if (Test-Path (Join-Path $MySqlBaseDir "bin\mysqld.exe")) {
|
|
Pass "mysql: portable install present ($MySqlVersion)"
|
|
} elseif (Test-TcpPort 3306) {
|
|
WarnCheck "mysql: no portable install, but something serves port 3306 (external server assumed)"
|
|
} else {
|
|
Fail "mysql: not installed (run bootstrap_dev_stack.ps1)"
|
|
}
|
|
|
|
if (Test-TcpPort 3306) {
|
|
if (Test-MySqlApp) {
|
|
Pass "mysql: reachable as '$DevMySqlUser' on database '$DevMySqlDb'"
|
|
|
|
$migrationDirs = (Get-ChildItem -Directory (Join-Path $RootDir "_database\sql\migrations")).Count
|
|
$applied = Get-MySqlCount "SELECT COUNT(*) FROM __diesel_schema_migrations"
|
|
if (($applied -ge $migrationDirs) -and ($applied -gt 0)) {
|
|
Pass "migrations: $applied applied ($migrationDirs in _database\sql\migrations)"
|
|
} elseif ($applied -gt 0) {
|
|
Fail "migrations: only $applied/$migrationDirs applied - run 'diesel migration run'"
|
|
} else {
|
|
Fail "migrations: none applied - run 'diesel migration run' (or re-run bootstrap)"
|
|
}
|
|
|
|
$roleCount = Get-MySqlCount "SELECT COUNT(*) FROM user_roles"
|
|
if ($roleCount -ge 3) {
|
|
Pass "seed: user_roles has $roleCount rows (user/mod/admin present)"
|
|
} else {
|
|
Fail "seed: user_roles has $roleCount rows - account creation needs the 'user' role (re-run bootstrap)"
|
|
}
|
|
|
|
$badgeCount = Get-MySqlCount "SELECT COUNT(*) FROM badges"
|
|
if ($badgeCount -gt 0) { Pass "seed: badges has $badgeCount rows" }
|
|
else { WarnCheck "seed: badges table is empty (cosmetic; re-run bootstrap to fill)" }
|
|
|
|
$demoCount = Get-MySqlCount "SELECT COUNT(*) FROM users WHERE username='$DemoUsername'"
|
|
if ($demoCount -gt 0) { Pass "demo user: '$DemoUsername' exists" }
|
|
else { WarnCheck "demo user: '$DemoUsername' not created yet (seed_demo_user.ps1, backend must be running)" }
|
|
|
|
if ($demoCount -gt 0) {
|
|
$credits = Get-MySqlCount "SELECT COALESCE(MAX(banked_credits + monthly_credits), 0) FROM wallets WHERE wallet_namespace='artcraft' AND owner_user_token=(SELECT token FROM users WHERE username='$DemoUsername')"
|
|
if ($credits -gt 0) { Pass "demo wallet: '$DemoUsername' has $credits credits" }
|
|
else { WarnCheck "demo wallet: '$DemoUsername' has no credits - generation flows are blocked (re-run seed_demo_user.ps1)" }
|
|
|
|
$mediaCount = Get-MySqlCount "SELECT COUNT(*) FROM media_files WHERE maybe_creator_user_token=(SELECT token FROM users WHERE username='$DemoUsername')"
|
|
if ($mediaCount -gt 0) { Pass "demo media: '$DemoUsername' has $mediaCount media rows" }
|
|
else { WarnCheck "demo media: gallery is empty (re-run seed_demo_user.ps1)" }
|
|
}
|
|
} else {
|
|
Fail "mysql: port 3306 is up but '$DevMySqlUser' cannot access '$DevMySqlDb' (re-run bootstrap provisioning)"
|
|
}
|
|
} else {
|
|
Fail "mysql: nothing listening on 3306 (start_dev_services.ps1)"
|
|
}
|
|
|
|
if (Test-Redis) {
|
|
Pass "redis: PONG"
|
|
} elseif (Test-TcpPort 6379) {
|
|
WarnCheck "redis: port 6379 open but redis-cli not found to verify"
|
|
} else {
|
|
Fail "redis: not reachable on 6379 (the backend's r2d2 pool connects eagerly at boot; start_dev_services.ps1)"
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "--- Backend ---"
|
|
|
|
if (Test-Path $SecretsEnvFile) {
|
|
Pass "secrets env: storyteller-web.development-secrets.env exists"
|
|
|
|
$secretsContent = Get-Content $SecretsEnvFile -Raw
|
|
if ($secretsContent -match '(?m)^\s*LOCAL_MEDIA_ROOT=') {
|
|
Pass "secrets env: fully-local dev stack keys present (DEV_FAKE_GENERATION, CDN_BASE_URL, LOCAL_MEDIA_ROOT)"
|
|
} else {
|
|
WarnCheck "secrets env: fully-local dev stack keys missing - generation/gallery use remote CDN and real providers (re-run bootstrap to append)"
|
|
}
|
|
} else {
|
|
Fail "secrets env: missing - the server aborts at boot on ~19 required vars (re-run bootstrap)"
|
|
}
|
|
|
|
if ((Test-Path (Join-Path $RootDir "target\debug\storyteller-web.exe")) -or
|
|
(Test-Path (Join-Path $RootDir "target\release\storyteller-web.exe"))) {
|
|
Pass "binary: storyteller-web.exe is built"
|
|
} else {
|
|
WarnCheck "binary: storyteller-web not built yet (bootstrap builds it; cargo run builds on demand)"
|
|
}
|
|
|
|
if (Test-Backend) {
|
|
Pass "server: $DevBackendUrl/_status responds"
|
|
} else {
|
|
WarnCheck "server: not running (run_backend_dev.ps1)"
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "--- Frontend ---"
|
|
|
|
if (Test-Path (Join-Path $RootDir "frontend\node_modules")) {
|
|
Pass "frontend: node_modules present"
|
|
} else {
|
|
WarnCheck "frontend: node_modules missing (cd frontend; npm install)"
|
|
}
|
|
|
|
if ((Test-Path (Join-Path $RootDir "frontend\pnpm-lock.yaml")) -or
|
|
(Test-Path (Join-Path $RootDir "frontend\node_modules\.pnpm"))) {
|
|
Fail "frontend: stale pnpm artifacts detected (see frontend/README.md - the workspace uses npm)"
|
|
} else {
|
|
Pass "frontend: no stale pnpm artifacts"
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Summary: $Failures failure(s), $Warnings warning(s)."
|
|
if ($Failures -gt 0) {
|
|
Write-Host "Fix failures with: .\script\bootstrap\windows\bootstrap_dev_stack.ps1 (safe to re-run)"
|
|
exit 1
|
|
}
|