836de5b597
Fetch and clean each search result's page body (bounded by size, concurrency, and a configurable MaxPageContentRunes), store it on the new ResearchResult.Content field, and surface those excerpts in agent memory so the model reasons over real page text rather than snippets alone. Promotes golang.org/x/net to a direct dependency for HTML parsing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
297 lines
7.1 KiB
Markdown
297 lines
7.1 KiB
Markdown
# img-infinite-canvas API
|
|
|
|
Base path: `/api`
|
|
|
|
## Health
|
|
|
|
`GET /api/health`
|
|
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"service": "img_infinite_canvas-api",
|
|
"time": "2026-07-04T03:20:00Z"
|
|
}
|
|
```
|
|
|
|
## Dashboard
|
|
|
|
`GET /api/dashboard`
|
|
|
|
Returns credits, quick actions, recent projects, and inspiration items for the Moteva-style home screen.
|
|
|
|
## Auth
|
|
|
|
Global mode is enabled in `etc/config.yaml`. Email verification codes are stored through the cache abstraction for 10 minutes; with `Cache.Driver: redis`, the code only lives in Redis until TTL or successful consumption.
|
|
|
|
SMTP is configured under `Auth.Email`:
|
|
|
|
```yaml
|
|
Auth:
|
|
Turnstile:
|
|
Enabled: true
|
|
SiteKey: 1x00000000000000000000AA
|
|
SecretKey: 1x0000000000000000000000000000000AA
|
|
SecretKeyEnv: TURNSTILE_SECRET_KEY
|
|
SiteVerifyURL: https://challenges.cloudflare.com/turnstile/v0/siteverify
|
|
TimeoutSeconds: 5
|
|
Email:
|
|
Driver: smtp # none|smtp
|
|
Host: smtp.example.com
|
|
Port: 587
|
|
Username: user@example.com
|
|
Password: app-password
|
|
FromName: hello
|
|
FromEmail: hello@example.com
|
|
BrandName: Moteva
|
|
UseTLS: false
|
|
StartTLS: true
|
|
TimeoutSeconds: 10
|
|
```
|
|
|
|
When `Auth.Turnstile.Enabled` is `false`, `/api/auth/options` returns `turnstile.enabled=false`; the frontend hides the Cloudflare Turnstile widget and sends email-code requests without a Turnstile token. When enabled, the frontend must submit `turnstileToken`, and the API validates it before creating or emailing a verification code.
|
|
|
|
`POST /api/auth/global/email-code`
|
|
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"turnstileToken": "client-widget-token"
|
|
}
|
|
```
|
|
|
|
Development response includes an email preview so the frontend can render the same verification flow without a mail provider:
|
|
|
|
```json
|
|
{
|
|
"target": "user@example.com",
|
|
"expiresIn": 600,
|
|
"devCode": "263081",
|
|
"email": {
|
|
"fromName": "hello",
|
|
"fromEmail": "hello@auth.moteva.local",
|
|
"toEmail": "user@example.com",
|
|
"subject": "Welcome to Moteva!",
|
|
"code": "263081"
|
|
}
|
|
}
|
|
```
|
|
|
|
`POST /api/auth/global/email-login`
|
|
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"code": "263081"
|
|
}
|
|
```
|
|
|
|
Returns an authenticated session with `accessToken`, `refreshToken`, and the user profile. Project creation, generation, upload, save, and deletion require this login token.
|
|
|
|
`POST /api/auth/global/google-login`
|
|
|
|
```json
|
|
{
|
|
"idToken": "google-id-token"
|
|
}
|
|
```
|
|
|
|
`POST /api/auth/china/wechat-login`
|
|
|
|
First QR callback:
|
|
|
|
```json
|
|
{
|
|
"code": "wechat-oauth-code",
|
|
"state": "signed-state"
|
|
}
|
|
```
|
|
|
|
If the WeChat identity is already bound to a phone number, the response is authenticated. If not, the response has `status: "phone_binding_required"` and a short-lived `bindingToken`.
|
|
|
|
Phone binding step:
|
|
|
|
```json
|
|
{
|
|
"bindingToken": "signed-binding-token",
|
|
"phone": "13800138000",
|
|
"countryCode": "+86",
|
|
"smsCode": "123456"
|
|
}
|
|
```
|
|
|
|
After binding succeeds, later QR logins use only `code` and `state`.
|
|
|
|
## Account
|
|
|
|
All account endpoints require the bearer token returned by login. Account profile state is owned by the auth module and persisted in PostgreSQL or the configured in-memory store.
|
|
|
|
`GET /api/account/profile`
|
|
|
|
Returns the current authenticated user.
|
|
|
|
`PATCH /api/account/profile`
|
|
|
|
```json
|
|
{
|
|
"name": "Xu Liang",
|
|
"avatarUrl": "https://cdn.example.com/avatar.webp"
|
|
}
|
|
```
|
|
|
|
Updates account display name and avatar URL. The frontend uploads avatar files through `/api/assets/upload-url` first, then stores the returned public URL on the profile.
|
|
|
|
`GET /api/account/devices`
|
|
|
|
Returns the current local web session. This version does not maintain a multi-device session registry yet, so the current device is read-only and cannot be removed.
|
|
|
|
`DELETE /api/account/devices`
|
|
|
|
Removes non-current devices when a future server-side session registry exists. In the current local-only implementation, it returns `{"removed": 0}`.
|
|
|
|
`POST /api/account/logout`
|
|
|
|
Records a logout request server-side and returns `{"removed": 0}`. The frontend then clears its local access token and cookies.
|
|
|
|
## Projects
|
|
|
|
`GET /api/projects`
|
|
|
|
Returns all project summaries, sorted by `updatedAt` descending.
|
|
|
|
`POST /api/projects`
|
|
|
|
```json
|
|
{
|
|
"title": "still day 官网",
|
|
"prompt": "为 still day 品牌服装独立站设计官网视觉方向",
|
|
"imageModel": "gpt-image-2",
|
|
"imageSize": "1024x1024",
|
|
"enableWebSearch": true
|
|
}
|
|
```
|
|
|
|
`enableWebSearch` only opens the web-search capability. The agent model still decides per request whether search is actually needed; if it is not needed, no web-search step is recorded. When search runs, result titles, URLs, snippets, and cleaned page-content excerpts are stored for the agent.
|
|
|
|
`GET /api/projects/:id`
|
|
|
|
Returns the full project, including viewport, nodes, connections, and agent messages.
|
|
|
|
`PATCH /api/projects/:id/title`
|
|
|
|
```json
|
|
{
|
|
"title": "夏季活动主视觉"
|
|
}
|
|
```
|
|
|
|
Renames the infinite canvas project and updates `updatedAt`.
|
|
|
|
`DELETE /api/projects/:id`
|
|
|
|
Deletes the project record. PostgreSQL cascades canvas nodes, chat messages, history, and connections; after the database delete succeeds, image assets referenced by the canvas and generated-file history are queued for asynchronous OSS deletion.
|
|
|
|
## Agent Chat
|
|
|
|
`POST /api/projects/:id/agent/chat`
|
|
|
|
```json
|
|
{
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"contents": [{ "type": "text", "text": "继续优化首页首屏,但保留品牌色" }]
|
|
}
|
|
],
|
|
"enableWebSearch": false,
|
|
"imageModel": "gpt-image-2",
|
|
"imageSize": "1024x1024",
|
|
"mode": "design"
|
|
}
|
|
```
|
|
|
|
The harness builds short memory from the current turn, recent messages, and visible canvas state, and long memory from durable project decisions, prior artifacts, and previous research records with page-content excerpts. Image titles and assistant language are generated from the request context instead of fixed model labels.
|
|
|
|
## Generate
|
|
|
|
`POST /api/projects/:id/generate`
|
|
|
|
```json
|
|
{
|
|
"prompt": "继续扩展产品详情页模块",
|
|
"mode": "design"
|
|
}
|
|
```
|
|
|
|
Returns the updated project, the assistant message, and generated nodes.
|
|
|
|
The generation path uses the configured design agent runner. The default is the `sky-valley/pi` Go agent adapter, with local desktop/MCP agent behavior disabled.
|
|
|
|
## Chat History Replay
|
|
|
|
`GET /api/projects/:id/history`
|
|
|
|
Returns replayable assistant/user chat history for the project.
|
|
|
|
```json
|
|
{
|
|
"projectId": "project-id",
|
|
"messages": []
|
|
}
|
|
```
|
|
|
|
## Save Canvas
|
|
|
|
`PATCH /api/projects/:id/canvas`
|
|
|
|
```json
|
|
{
|
|
"viewport": { "x": 420, "y": 260, "k": 0.72 },
|
|
"nodes": [],
|
|
"connections": []
|
|
}
|
|
```
|
|
|
|
Saves canvas layout changes. The frontend uses this after dragging or zooming.
|
|
|
|
When a canvas image node disappears from the saved node list, its backing OSS asset is queued for asynchronous deletion after the canvas save succeeds.
|
|
|
|
## Image Asset Upload
|
|
|
|
`POST /api/assets/upload-url`
|
|
|
|
```json
|
|
{
|
|
"fileName": "reference.png",
|
|
"contentType": "image/png",
|
|
"size": 123456
|
|
}
|
|
```
|
|
|
|
Returns a signed upload URL for the configured storage backend.
|
|
|
|
Supported drivers:
|
|
|
|
- `memory`
|
|
- `minio`
|
|
- `s3` / `aws`
|
|
- `r2`
|
|
- `aliyun`
|
|
|
|
## Errors
|
|
|
|
JSON error response:
|
|
|
|
```json
|
|
{
|
|
"error": "project not found",
|
|
"code": 404
|
|
}
|
|
```
|
|
|
|
Common status codes:
|
|
|
|
- `400`: invalid input
|
|
- `404`: project not found
|
|
- `500`: internal server error
|