完成 Editor Agent Mock Agent P1 收尾
接入 Web Project 契约、SpacetimeDB 表与 api-server 控制面 新增 Mock Agent、静态构建 runner 与独立预览网关 补齐 /editor/agent 前端页面、服务客户端和 SSE 订阅 修复 sandbox 预览资源跨域加载并补充并发保护 接入本地 dev 预览端口漂移与服务身份初始化 更新 P1 技术方案、验收清单和 Hermes 共享记忆
This commit is contained in:
139
src/services/web-project/webProjectClient.ts
Normal file
139
src/services/web-project/webProjectClient.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import type {
|
||||
MockAgentTurnResponse,
|
||||
WebProject,
|
||||
WebProjectPatch,
|
||||
WebProjectPreviewBuild,
|
||||
WebProjectResponse,
|
||||
WebProjectSnapshot,
|
||||
WebProjectSnapshotResponse,
|
||||
} from '../../../packages/shared/src/contracts/webProject';
|
||||
import { requestJson, type ApiRequestOptions } from '../apiClient';
|
||||
|
||||
const WEB_PROJECT_CREATION_API_BASE = '/api/creation/web-project/projects';
|
||||
const WEB_PROJECT_RUNTIME_API_BASE = '/api/runtime/web-project';
|
||||
|
||||
const WEB_PROJECT_REQUEST_OPTIONS = {
|
||||
clearAuthOnUnauthorized: false,
|
||||
notifyAuthStateChange: false,
|
||||
} satisfies ApiRequestOptions;
|
||||
|
||||
type WebProjectPreviewBuildResponse = {
|
||||
build: WebProjectPreviewBuild;
|
||||
};
|
||||
|
||||
function jsonRequest(method: 'POST' | 'PATCH', body: Record<string, unknown>) {
|
||||
return {
|
||||
method,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
}
|
||||
|
||||
function projectUrl(projectId: string) {
|
||||
return `${WEB_PROJECT_CREATION_API_BASE}/${encodeURIComponent(projectId)}`;
|
||||
}
|
||||
|
||||
export async function createWebProject(input: { title?: string } = {}) {
|
||||
const response = await requestJson<WebProjectResponse>(
|
||||
WEB_PROJECT_CREATION_API_BASE,
|
||||
jsonRequest('POST', { title: input.title }),
|
||||
'创建 Web 工程失败',
|
||||
WEB_PROJECT_REQUEST_OPTIONS,
|
||||
);
|
||||
return response.project;
|
||||
}
|
||||
|
||||
export async function loadWebProject(projectId: string) {
|
||||
const response = await requestJson<WebProjectResponse>(
|
||||
projectUrl(projectId),
|
||||
{ method: 'GET' },
|
||||
'读取 Web 工程失败',
|
||||
WEB_PROJECT_REQUEST_OPTIONS,
|
||||
);
|
||||
return response.project;
|
||||
}
|
||||
|
||||
export async function loadActiveWebProjectSnapshot(projectId: string) {
|
||||
const response = await requestJson<WebProjectSnapshotResponse>(
|
||||
`${projectUrl(projectId)}/snapshot`,
|
||||
{ method: 'GET' },
|
||||
'读取 Web 工程快照失败',
|
||||
WEB_PROJECT_REQUEST_OPTIONS,
|
||||
);
|
||||
return response.snapshot;
|
||||
}
|
||||
|
||||
export async function saveWebProjectFiles(
|
||||
projectId: string,
|
||||
input: {
|
||||
patch: WebProjectPatch;
|
||||
baseSnapshotId: string;
|
||||
summary?: string;
|
||||
},
|
||||
) {
|
||||
const response = await requestJson<WebProjectSnapshotResponse>(
|
||||
`${projectUrl(projectId)}/files`,
|
||||
jsonRequest('PATCH', {
|
||||
patch: input.patch,
|
||||
baseSnapshotId: input.baseSnapshotId,
|
||||
summary: input.summary,
|
||||
}),
|
||||
'保存 Web 工程文件失败',
|
||||
WEB_PROJECT_REQUEST_OPTIONS,
|
||||
);
|
||||
return response.snapshot;
|
||||
}
|
||||
|
||||
export async function submitMockAgentTurn(
|
||||
projectId: string,
|
||||
input: {
|
||||
prompt: string;
|
||||
baseSnapshotId: string;
|
||||
},
|
||||
) {
|
||||
return requestJson<MockAgentTurnResponse>(
|
||||
`${projectUrl(projectId)}/mock-agent-turns`,
|
||||
jsonRequest('POST', {
|
||||
prompt: input.prompt,
|
||||
baseSnapshotId: input.baseSnapshotId,
|
||||
}),
|
||||
'提交 Mock Agent 指令失败',
|
||||
WEB_PROJECT_REQUEST_OPTIONS,
|
||||
);
|
||||
}
|
||||
|
||||
export async function createWebProjectPreviewBuild(
|
||||
projectId: string,
|
||||
input: { snapshotId?: string } = {},
|
||||
) {
|
||||
const response = await requestJson<WebProjectPreviewBuildResponse>(
|
||||
`${WEB_PROJECT_RUNTIME_API_BASE}/projects/${encodeURIComponent(projectId)}/preview-builds`,
|
||||
jsonRequest('POST', { snapshotId: input.snapshotId }),
|
||||
'创建 Web 工程预览构建失败',
|
||||
WEB_PROJECT_REQUEST_OPTIONS,
|
||||
);
|
||||
return response.build;
|
||||
}
|
||||
|
||||
export async function loadWebProjectPreviewBuild(jobId: string) {
|
||||
const response = await requestJson<WebProjectPreviewBuildResponse>(
|
||||
`${WEB_PROJECT_RUNTIME_API_BASE}/preview-builds/${encodeURIComponent(jobId)}`,
|
||||
{ method: 'GET' },
|
||||
'读取 Web 工程预览构建失败',
|
||||
WEB_PROJECT_REQUEST_OPTIONS,
|
||||
);
|
||||
return response.build;
|
||||
}
|
||||
|
||||
export type WebProjectClientSnapshotBundle = {
|
||||
project: WebProject;
|
||||
snapshot: WebProjectSnapshot;
|
||||
};
|
||||
|
||||
export async function createWebProjectWithSnapshot(
|
||||
input: { title?: string } = {},
|
||||
): Promise<WebProjectClientSnapshotBundle> {
|
||||
const project = await createWebProject(input);
|
||||
const snapshot = await loadActiveWebProjectSnapshot(project.projectId);
|
||||
return { project, snapshot };
|
||||
}
|
||||
Reference in New Issue
Block a user