AI App Installation and Service Deployment Progress API
This document describes manual AI App installation, device-side service deployment, streaming progress, and the API interface to query the latest deployment status using serviceId.
For integration and testing workflows, refer to the deployment progress testing documentation in the project repository.
1. Basic Conventions
- AI Pod external domain:
https://<subdomain>.<box-domain> subdomainis derived from the app'slzc-manifest.yml; currently defaults toaibox-domainis prioritized by fetching fromlzc-cli box default; if unavailable, defaults to13gxg.heiyu.space
Platform-side API base path:
https://<subdomain>.<box-domain>/backend/aiappshttps://<subdomain>.<box-domain>/backend/services
Device-side API base path:
http://<device-ip>:<device-port>/v1/service
2. Manual AI App Installation
2.1 POST /backend/aiapps/install/stream
Purpose:
- Upload an AI App ZIP file
- Complete registration
- If the package includes deployable services, continue triggering device deployment. The new resource export service paths are
agxorin/docker-compose.yml,thor/docker-compose.yml. Fallback to legacyai-pod-service/docker-compose.ymlif missing. - Return installation progress via SSE.
Request:
- Method:
POST - Content-Type:
multipart/form-data - Required fields:
file
Response:
- Content-Type:
text/event-stream - Event name:
progress
Event structure:
{
"stage": "pulling",
"status": "downloading",
"progress": 37,
"message": "registry.lazycat.cloud/demo/app:latest: Downloading",
"pkgId": "demo-app",
"serviceId": "demo-app",
"currentImage": "registry.lazycat.cloud/demo/app:latest",
"currentLayer": "sha256:abcd",
"current": 5242880,
"total": 10485760,
"error": ""
}Note:
- During the local package processing phase, status messages such as
upload_saved,unzipping,validating, andregisteringare still sent. - The
progresstoken in these phases is fixed to0and is not counted in the installation progress bar. - Actual progress in installation occurs during the service deployment phase:
pulling:0-80starting:85waiting:95completed:100failed: retain progress prior to failure
- If the AI App has no deployable services, it directly returns:
stage=completedprogress=100message=installed without deployable service
Typical return:
event:progress
data:{"stage":"registering","progress":0,"message":"registering ai app","pkgId":"demo-app"}
event:progress
data:{"stage":"pulling","status":"downloading","progress":31,"message":"registry.lazycat.cloud/demo/app:latest: Downloading","pkgId":"demo-app","serviceId":"demo-app","currentImage":"registry.lazycat.cloud/demo/app:latest","currentLayer":"sha256:abcd","current":5242880,"total":10485760}
event:progress
data:{"stage":"starting","status":"starting","progress":85,"message":"starting service","pkgId":"demo-app","serviceId":"demo-app"}
event:progress
data:{"stage":"waiting","status":"waiting","progress":95,"message":"waiting for service health","pkgId":"demo-app","serviceId":"demo-app"}
event:progress
data:{"stage":"completed","status":"complete","progress":100,"message":"service deployed","pkgId":"demo-app","serviceId":"demo-app"}Failure example:
event:progress
data:{"stage":"failed","status":"error","progress":42,"message":"pull images failed","pkgId":"demo-app","serviceId":"demo-app","error":"pull access denied"}2.2 DELETE /backend/aiapps/apps/:pkgId
Purpose:
- Delete a manually installed AI App
- Remove the corresponding service directory, cache directory, and container image
Return:
{"removed":true,"pkgId":"demo-app"}2.3 GET /backend/aiapps/apps
Purpose:
- List the current AI App entries
2.4 GET /backend/aiapps/installed/:pkgId
Purpose:
- Check if a specified
pkgIdhas been registered to the AI App store
Return:
{"installed":true}3. Platform-side Service Interfaces
3.1 GET /backend/services/progress?serialNumber=<sn>&serviceId=<serviceId>
Purpose:
- Query the most recent deployment progress of a specified service on a device
- Suitable for automatic deployment scenarios, or for manual installation with interruption and subsequent recovery
Return structure:
{
"serviceId": "demo-app",
"stage": "pulling",
"status": "extracting",
"progress": 56,
"message": "registry.lazycat.cloud/demo/app:latest: Extracting",
"currentImage": "registry.lazycat.cloud/demo/app:latest",
"currentLayer": "sha256:abcd",
"current": 7340032,
"total": 10485760,
"startedAt": 1742880000,
"updatedAt": 1742880012,
"finishedAt": 0,
"error": ""
}Idle state return:
{
"serviceId": "demo-app",
"stage": "idle",
"progress": 0,
"message": "deployment not started"
}3.2 Existing Platform-side Interfaces
GET /backend/services/list?serialNumber=<sn>GET /backend/services/start?serialNumber=<sn>&serviceId=<serviceId>GET /backend/services/stop?serialNumber=<sn>&serviceId=<serviceId>GET /backend/services/delete?serialNumber=<sn>&serviceId=<serviceId>GET /backend/services/log?serialNumber=<sn>&serviceId=<serviceId>
Note:
startis a synchronous trigger and does not return streaming progress.- Automatic deployment and
startboth continuously update the latest deployment status ofserviceId. - For real-time progress, prefer using the AI App installation stream or the device-side
/service/start/stream.
4. Device-side Service Interfaces
4.1 POST /v1/service/start
Purpose:
- Triggers a one-time synchronous deployment.
- The system internally updates the latest deployment status.
Request Fields:
file: service zipserviceIddirOverWrite:true|falseforceRecreate:true|falseextraEnv[KEY]=VALUE: optional
4.2 POST /v1/service/start/stream
Purpose:
- Trigger a streaming deployment
- Shares the same underlying deployment logic as
/v1/service/start - Adds SSE-based progress feedback
Response:
- Content-Type:
text/event-stream - Event name:
progress - Data structure matches
backend.ServiceDeployStatus
4.3 GET /v1/service/progress?serviceId=<serviceId>
Purpose:
- Query the latest deployment status of the service
4.4 GET /v1/service/log?serviceId=<serviceId>
Purpose:
- Continuously monitor service logs
4.5 GET /v1/service/installed
Purpose:
- View the currently installed services on the device along with
docker-compose.ymlsummary information
5. Semantic Meaning of Deployment Progress
Unified status fields:
stage: High-level stagestatus: Fine-grained statusprogress: 0–100message: Human-readable message
Current stage definitions:
| stage | progress | Meaning |
|---|---|---|
idle | 0 | No deployment records available |
prepare | 0 | Start deployment: prepare directory, unzip, write .env |
pulling | 0-80 | Pull the compose container image |
starting | 85 | Execute docker-compose up -d --wait |
waiting | 95 | Container has been started, waiting for health check or --wait to complete |
completed | 100 | Deployment successful |
failed | Keep current value | Deployment failed. Error details see error. |
pulling.status Currently possible:
preparepreparingwaitingdownloadingdownload_completeextractingverifyingalready_existscomplete
Explanation:
- The percentage for
pullingcomes from the structured byte progress of Docker EngineImagePull, no longer relying ondocker-compose pullPTY text. - In multi-image scenarios, the overall
0-80progress is calculated by averaging the weights of individual images. startingandwaitingare currently phase-based progress indicators and are not precise container-level percentages.- The system retains only the most recent deployment status for each
serviceId.
6. Call Examples
6.1 Manually installing an AI App and monitoring streaming progress
curl --no-buffer \
-F "file=@./demo-app.zip" \
"https://ai.13gxg.heiyu.space/backend/aiapps/install/stream"6.2 Query the recent deployment status of a specific service
curl \
"https://ai.13gxg.heiyu.space/backend/services/progress?serialNumber=<sn>&serviceId=demo-app"6.3 Directly Call Device-Side Stream Deployment Interface
curl --no-buffer \
-F "file=@./demo-app-service.zip" \
-F "serviceId=demo-app" \
-F "dirOverWrite=true" \
"http://<device-ip>:<device-port>/v1/service/start/stream"6.4 Directly Call the Device-side Deployment Status Query Interface
curl "http://<device-ip>:<device-port>/v1/service/progress?serviceId=demo-app"7. ZIP Structure Requirements
AI App ZIP supports both resource export structure and legacy manual installation structure.
7.1 Resource Export Structure
Recommended structure:
demo-app/
└── resources/
└── aipod/
└── demo-app/
├── package.yml
├── lzc-manifest.yml
├── icon.png
├── config/
│ └── aipod.yml
├── agxorin/
│ └── docker-compose.yml
├── thor/
│ └── docker-compose.yml
└── extensions/
└── extension.zipAfter platform installation, the AIApp resource is expanded to:
/lzcapp/run/resources/aipod/<package-id>/Service selection rules:
- Thor devices prioritize
thor/docker-compose.yml - All other devices default to
agxorin/docker-compose.yml - When model-specific compose is missing, fallback to legacy
ai-pod-service/docker-compose.yml
Plugin selection rules:
- Prefer
extensions/*.zip|*.crx - Fall back to legacy
browser-extensions/extension.zipif missing
7.2 Legacy Manual Installation Structure
Legacy manual installation ZIP remains compatible:
demo-app/
└── pkg/
├── manifest.yml
├── icon.png
├── extension.zip
└── ai-pod-service/
└── docker-compose.ymlDevice-side service zip structure:
demo-app/
├── docker-compose.yml
└── ...AI App Rules:
- The ZIP file containing resource export must contain exactly one AIApp resource root directory and be parsable to extract only one such root.
- Legacy manual installation ZIP files must contain exactly one
pkg/manifest.yml. - The legacy manual installation service path is
pkg/ai-pod-service/docker-compose.yml. - The new resource export service paths are
agxorin/docker-compose.yml,thor/docker-compose.yml, or fallback toai-pod-service/docker-compose.yml. - The compose file must include a resolvable Traefik
Host(...)label for platform identification of AI host and startup loading status.
8. Compatibility Notes
- Automatic deployment, manual installation with streaming deployment, and platform-side
startinterface all share the same underlying deployment logic and the same state repository. - During manual installation, the AI App SSE directly passes through the device-side deployment progress.
- During automatic deployment, no SSE is returned; the caller should query the latest deployment status via
serviceId. - The
pkg/ai-pod-service/docker-compose.ymlin legacy ZIP files is only used as a compatibility path for manual installation and is not the sole service format for the new resource export.