@mobility42/myai
v0.1.25
Published
Windows MyAI desktop app with local Docker service packaging.
Readme
Windows MyAI desktop app with local Docker service packaging.
| Goal | File | |------|------| | Understand purpose | README.md | | First-run WSL/Docker setup flow | docs/environment-bootstrap.md | | Service package structure | docs/service-packages.md | | Product generation engine | tools/product-generator/README.md | | UI renderer system | packages/ui-renderer/README.md | | Streaming task contract | docs/streaming-task-contract.md | | Docker deployment stability | docs/docker-deployment-stability.md | | Author a service | docs/service-authoring.md | | LNB container lifecycle | docs/lnb-container-lifecycle.md | | Service delete/reset rules | docs/service-delete-reset.md | | Package build and upload | docs/packaging.md | | MSI upgrade rules | docs/msi-upgrade.md | | macOS test installer | docs/mac-installation.md | | Verification | docs/verification.md | | External PC testing | docs/external-pc-testing.md |
Requirements
- Windows 11
- .NET 8 SDK or later
- Microsoft Edge WebView2 Runtime
- Docker Desktop with Docker CLI and Docker Compose plugin
- pnpm for Market workspace tasks
Turbo Cache
Turbo is configured for local workspace task orchestration. Remote cache is not connected yet; future CI setup must document the remote cache provider, token source, and cache invalidation policy before enabling it.
Product Generator
The first-stage product generator creates scaffold service packages from product definitions:
pnpm generate-product --definition ./examples/video-generate-wan22.json
pnpm package-product --definition ./examples/video-generate-wan22.json
pnpm validate-product --definition ./examples/video-generate-wan22.jsonThe command resolves ./examples/* to tools/product-generator/src/examples/* and writes scaffold files under ServicePackages/{serviceId}.
UI Renderer System
Service packages must include ui.schema.json. The service origin serves the renderer shell and schema, then the renderer posts to same-origin service APIs and displays results through output.mapping. The renderer runtime is shared by generated service packages and chat-lms-runtime.
The renderer browser shell is built once by @my-ai/ui-renderer into packages/ui-renderer/dist-shell/ as browser.html plus assets/. Service packaging copies that shell into each zip and records the version in service.json.runtime.renderer and manifest.json; service-specific renderer builds and market-*.zip artifacts are not valid outputs.
Background Task Runtime
AI generation must not depend on the service page staying mounted. Services should return a taskId immediately, keep generation in a background queue, and expose task status/result endpoints. The shared renderer registers started tasks with the Windows host through WebView2, and the app stores them in %LOCALAPPDATA%\MyAI\runtime\tasks.json while polling outside the page lifecycle. LNB service names show active task counts, for example ??⑤㈇留???諛댁뎽 (1).
Service runtimes persist task history under /data/tasks/ when using @my-ai/service-runtime. On service restart, completed history is kept and unfinished restored tasks are marked failed instead of silently disappearing.
Run
npm CLI 실행
npx @mobility42/myai@mobility42/myai npm 패키지는 작은 CLI 런처만 포함합니다. Windows self-contained WPF 런타임, MyAI.exe, .NET DLL, WPF DLL, WebView2 DLL, runtime/*, node_modules, src/*는 npm 패키지에 포함하지 않습니다.
CLI는 GitHub Release 최신 버전을 조회하고 myai-win-x64-{version}.zip을 다운로드한 뒤 %LOCALAPPDATA%\Mobility42\MyAI\runtime\win-x64에 설치합니다. 설치된 버전이 최신 Release 버전과 같으면 다시 다운로드하지 않고 기존 MyAI.exe를 실행합니다.
기본 GitHub Release URL 형식:
https://github.com/hyej8155/myai/releases/latest/download/myai-win-x64-0.1.14.zip다른 GitHub 저장소를 사용할 때는 MYAI_GITHUB_REPOSITORY=owner/repo 환경 변수로 지정합니다.
캐시된 npx 설치를 다시 검증하기 전에는 npx 캐시를 정리합니다.
Remove-Item "$env:LOCALAPPDATA\npm-cache\_npx" -Recurse -Forcenpm CLI 실행에는 사용자 PC의 .NET SDK, MSI 설치, GitHub 방문, 추가 설정이 필요하지 않습니다.
npm 공식 레지스트리 설치
npm install @mobility42/myai또는 pnpm을 사용할 수 있습니다.
pnpm add @mobility42/myai내부 Verdaccio 설치
pnpm add @neurondev/myai --registry=https://verdaccio.mobility42.ionpm 패키지 빌드
npm 배포 전에는 CLI와 GitHub Release용 Windows 런타임 zip을 생성합니다.
pnpm build이 명령은 npm 패키지용 dist/cli.js와 GitHub Release 업로드용 artifacts/releases/myai-win-x64-{version}.zip을 생성합니다. npm 패키지에는 dist/cli.js, README.md, package.json만 포함합니다.
???뮞 ??쎈뻬
dotnet restore .\MyAI.sln
dotnet build .\MyAI.sln
dotnet run --project .\MyAI.csproj??뺥돩?????뮞??
test:service??My AI ?袁⑷퍥 ????쎈뻬 野꺜筌앹빘???袁⑤빍??TripoSR 3D ??뺥돩????쇳뒄/??쎈뻬 ?紐낆넎??癰귢쑴臾??낅빍?? 筌욊낯????쎈뻬?????뮉 筌뤿굞??怨몄뵥 筌뤿굝議???????몃빍??
pnpm run test:triposr-3dRuntime Configuration
Runtime-specific values must not be hardcoded in C# code. The launcher reads the Market URL in this order:
MYAI_MARKET_BASE_URLenvironment variable- Repository or executable-adjacent
.envfile withMYAI_MARKET_BASE_URL=... - Built-in default
https://myai-market.mobility42.io
The only supported Market URL key is MYAI_MARKET_BASE_URL:
MYAI_MARKET_BASE_URL=https://myai-market.mobility42.ioDo not configure Market URL in appsettings.json and do not use marketBaseUrl. The packaged default Market URL is https://myai-market.mobility42.io. Do not hardcode localhost:10000 in app code. On macOS, localhost means the Mac itself, not the Windows development PC running the Market container.
Market Docker
$env:MYAI_DATA_DIR="$env:LOCALAPPDATA\MyAI\data"
docker compose -p myai up -d --build
Invoke-WebRequest -UseBasicParsing http://localhost:10000/healthThe root docker-compose.yml is the orchestration entry point. Market container assets live under Market/docker/. Docker services must be started through the root compose file unless a module compose file is being validated. Runtime data is mounted from %LOCALAPPDATA%\MyAI\data on Windows and ~/Library/Application Support/MyAI/data on macOS.
Google OAuth
Windows 런처는 Google OAuth를 외부 브라우저에서 시작하고, 앱이 로그인 시도마다 임시 loopback callback 서버를 엽니다. Redirect URI는 http://127.0.0.1:{port}/ 형식이며, 요청마다 생성한 state 값을 Google authorize URL과 콜백에서 검증합니다.
콜백 서버는 브라우저의 /favicon.ico 같은 부가 요청을 무시하고 유효한 / 콜백만 처리합니다. 로그인 로그에는 다음 형식의 OAuth 상태가 남아야 합니다.
[OAuth] Listening on http://127.0.0.1:51318/
[OAuth] Authorize redirect_uri=http://127.0.0.1:51318/
[OAuth] Callback received path=/ state=valid
[OAuth] Callback authorization code=...
[OAuth] Code exchange redirect_uri=http://127.0.0.1:51318/
[OAuth] Token endpoint=https://oauth2.googleapis.com/token
[OAuth] Token request grant_type=authorization_code
[OAuth] Ignored request path=/favicon.ico
[OAuth] Completed and listener closedToken exchange 실패 시에는 Google 응답 본문을 숨기지 않고 로그와 브라우저 실패 화면에 표시합니다. 실패 로그에는 HTTP 상태, 원본 응답 JSON, error, error_description, authorize 요청의 redirect_uri, token 요청의 redirect_uri가 함께 남아야 하며 두 redirect URI는 http://127.0.0.1:{port}/ 형식으로 완전히 같아야 합니다. 현재 loopback OAuth 흐름은 PKCE를 사용하지 않으므로 code_verifier=<not used>로 기록합니다.
Market 서버는 Google OAuth 시작/콜백을 직접 처리하지 않습니다. 로그인과 로그아웃 실행 버튼은 Windows LNB 하단에만 두며, Market 본문과 Market WebView는 로그인 상태만 읽기 전용으로 표시합니다. /api/auth/google/start와 /api/auth/google/callback은 desktop app 흐름을 안내하는 비활성 endpoint로 유지합니다.
Market Service Catalog
Market UI is a launcher-owned surface. Opening http://localhost:10000 or the configured Market URL in a standalone browser shows an app-only notice and does not bind login, upload, download, refresh, or delete actions. The usable Market UI requires the My AI desktop app WebView host. Static service catalog and package download calls also require X-MyAI-Host: desktop-app, which the launcher and hosted Market WebView set automatically.
The Windows/macOS launcher Market page uses the authenticated uploaded-service catalog:
$body = @{ email = "[email protected]" } | ConvertTo-Json
$login = Invoke-RestMethod -Method Post -Uri http://localhost:10000/api/auth/login -ContentType application/json -Body $body
Invoke-RestMethod -Headers @{ Authorization = "Bearer $($login.token)" } http://localhost:10000/api/market/servicesAdmin uploads are stored in the Market DB and are listed from GET /api/market/services. Package downloads use each returned packageUrl, normally /api/market/services/{serviceId}/download. The Windows launcher uses the static GET /api/services catalog as the official installable baseline, overlays matching uploaded entries when available, and excludes fish-speech-v15 until its upload package is fixed.
The Market server also exposes a static install catalog for launcher/API compatibility checks:
Invoke-WebRequest -UseBasicParsing -Headers @{ "X-MyAI-Host" = "desktop-app" } http://localhost:10000/api/services
Invoke-WebRequest -UseBasicParsing -Headers @{ "X-MyAI-Host" = "desktop-app" } http://localhost:10000/api/services/triposr-3d/download -OutFile triposr-3d.zipGET /api/services is the static catalog module. It serves official service packages from artifacts/{serviceId}.zip; fish-speech-v15 is excluded from this catalog until its upload package is fixed.
Market Card Layout
The Windows launcher Market page presents services as AI features, not model inventory. Services are grouped by functional category such as ????, ????嶺뚯솘?, ??⑤㈇留?, ?????, ?????, and 3D. Cards show the feature name, short description, recommended computer spec, engine, and install state by default.
The Market page also exposes category filters as horizontally scrollable capsule tabs. Tab labels show the category name and service count. ?熬곣뫕?? shows every service grouped by category, while category tabs such as ????, ????嶺뚯솘?, and `??⑤㈇留? show only the matching cards without the category header.
Model and runtime details are stored in service.json engine metadata and returned by the Market API for diagnostics and packaging. The launcher keeps engine, runtime, and install contract fields out of the main Market card UI.
The Market header includes a refresh button next to the title. It reloads GET /api/market/services without leaving the Market page and is disabled while the catalog is loading.
Docker Naming
All MyAI containers use the single Docker Compose project myai, so Docker Desktop shows one myai group with child services such as market, video-generate-wan22, video-generate-wan22-comfyui, and qwen3-tts. Do not set fixed container_name values in compose files; Docker Compose default names avoid reinstall, update, parallel test, and orphan conflicts.
| Service | Compose project | Compose service |
|---------|-----------------|-----------------|
| Market | myai | market |
| Wan2.2 Video | myai | video-generate-wan22 |
| Wan2.2 ComfyUI | myai | video-generate-wan22-comfyui |
| Qwen3 TTS | myai | qwen3-tts |
| Image Generate | myai | flux-image-generate |
| Image Edit | myai | flux-image-edit |
New service packages must set name: myai in docker-compose.yml and runtime.composeProjectName: myai in service.json. Stop/delete/restart logic must use docker compose -p myai -f {composeFile} with the target compose service name. --remove-orphans is not a default cleanup option because independently installed services share the same Compose project.
Containers already created under older service-scoped projects keep their old Docker Compose labels until they are stopped and recreated. The launcher uses myai for new operations after this update.
Service Packages
The app loads installed service definitions from %LOCALAPPDATA%\MyAI\config\installed-services.json.
The current file shape is { "services": [...] }. Startup and install flows also tolerate an older top-level array shape, empty files, and invalid JSON. Invalid JSON is moved aside as installed-services.invalid-YYYYMMDDHHMMSS.json and treated as an empty install list so the launcher can continue opening.
Deleting a service must remove its Docker containers, volumes, service images, installed package folder, launcher caches, and WebView origin storage. Reinstalling the same service must behave like a first install. See docs/service-delete-reset.md.
Services contains C# launcher service code only. Deployable service packages live under ServicePackages, and the project copies those package files to the build output.
Package build scripts live inside their owning module:
ServicePackages/ace-step-music/build-package.ps1
ServicePackages/flux-image-generate/build-package.ps1
ServicePackages/flux-image-edit/build-package.ps1
ServicePackages/chat-lms-runtime/build-packages.ps1
ServicePackages/chat-lms-tinyllama/build-package.ps1
ServicePackages/chat-lms-phi3/build-package.ps1
ServicePackages/chat-lms-gemma/build-package.ps1
ServicePackages/qwen3-tts/build-package.ps1
ServicePackages/video-generate-wan22/build-package.ps1
scripts/package-triposr-3d.ps1Generated packages are written directly under artifacts:
artifacts/chat-lms-tinyllama.zip
artifacts/chat-lms-phi3.zip
artifacts/chat-lms-gemma.zip
artifacts/flux-image-generate.zip
artifacts/flux-image-edit.zip
artifacts/ace-step-music.zip
artifacts/qwen3-tts.zip
artifacts/triposr-3d.zip
artifacts/video-generate-wan22.zipEach zip must include docker-compose.yml, service.json, ui.schema.json, manifest.json, and a renderer shell containing browser.html plus assets/. Packaging reports are written to tests/reports/packaging/.
Verification
dotnet build .\MyAI.sln
docker compose -f .\ServicePackages\chat-lms-tinyllama\docker-compose.yml configSee docs/verification.md for the full checklist.
Full local verification, including Market health/login, diagnostic upload, MSI build, and macOS publish checks:
.\scripts\verify-all.ps1 -Version 0.1.0macOS DMG files must be created on a Mac because DMG packaging uses hdiutil:
.\installer\build-dmg.ps1 -Runtime osx-arm64 -Version 0.1.0