feat(api): add Lovart-style project and agent thread endpoints

Add canva/canda-compatible routes for lightweight project open/save and
agent thread history:
- POST /canva/project/queryProject, saveProject
- POST /canva/agent/queryAgentLastThread, agentThreadList
- GET /canda/chat-history, /canda/thread/status

Canvas save now accepts a compressed SHAKKERDATA:// snapshot payload,
preserves connections, and returns a SaveProject response; blank
successful image nodes are backfilled from generated artifacts. Frontend
designGateway adopts the new save/query flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-08 19:10:08 +08:00
parent ada29cee12
commit 263748af4a
27 changed files with 2045 additions and 114 deletions
+4 -6
View File
@@ -1,5 +1,4 @@
import type { AccountDevice, AuthCodeResponse, AuthOptions, AuthSession, AuthUser, StoredAuthSession } from "@/domain/auth";
import { encodeUploadImage } from "@/infrastructure/imageUploadEncoding";
import { createApiFailure, createNetworkFailure } from "@/infrastructure/userMessages";
const sessionStorageKey = "img-infinite-canvas.auth.session";
@@ -116,7 +115,6 @@ export const authGateway = {
},
async uploadAvatar(file: File) {
const uploadFile = await encodeUploadImage(file);
const upload = await apiRequest<{
uploadUrl: string;
publicUrl: string;
@@ -124,9 +122,9 @@ export const authGateway = {
}>("/api/assets/upload-url", {
method: "POST",
body: JSON.stringify({
fileName: uploadFile.name,
contentType: uploadFile.type || file.type || "application/octet-stream",
size: uploadFile.size
fileName: file.name,
contentType: file.type || "application/octet-stream",
size: file.size
})
});
@@ -134,7 +132,7 @@ export const authGateway = {
await fetch(upload.uploadUrl, {
method: "PUT",
headers: upload.headers,
body: uploadFile
body: file
});
}
return upload.publicUrl;