Makelore 2.0 initial clean snapshot

This commit is contained in:
inman
2026-07-29 17:22:35 +08:00
commit b8ca3f8eea
694 changed files with 139782 additions and 0 deletions

146
src/lib/image-workspace.ts Normal file
View File

@@ -0,0 +1,146 @@
import { AppError } from '@/lib/error-model';
import { hostApiFetch } from '@/lib/host-api';
import {
IMAGE_WORKSPACE_UNAVAILABLE_CODE,
IMAGE_WORKSPACE_UNAVAILABLE_MESSAGE,
type ImageWorkspaceImage,
type ImageWorkspaceReferenceUploadInput,
type ImageWorkspaceReferenceUploadResult,
type ImageWorkspaceSendMessageInput,
type ImageWorkspaceSnapshot,
} from '../../shared/image-workspace';
const IMAGE_WORKSPACE_API_PATH = '/api/works/image-workspace';
type ImageWorkspaceEnvelope = {
success?: boolean;
status?: number;
code?: string;
error?: string;
workspace?: ImageWorkspaceSnapshot;
reference?: ImageWorkspaceImage;
};
export const IMAGE_WORKSPACE_CREATE_PROJECT_EVENT = 'niancode:image-workspace:create-project';
export class ImageWorkspaceApiError extends Error {
readonly status: number;
readonly code: string;
constructor(status: number, code: string, message: string) {
super(message);
this.name = 'ImageWorkspaceApiError';
this.status = status;
this.code = code;
}
}
function getErrorStatus(error: unknown): number {
if (error instanceof AppError && typeof error.details?.status === 'number') {
return error.details.status;
}
return 502;
}
async function requestImageWorkspace(
accessToken: string | null | undefined,
path: string,
init: RequestInit = {},
): Promise<ImageWorkspaceSnapshot> {
const headers = accessToken?.trim()
? { 'X-NianCode-Access-Token': accessToken.trim(), ...init.headers }
: init.headers;
let response: ImageWorkspaceEnvelope;
try {
response = await hostApiFetch<ImageWorkspaceEnvelope>(path, {
...init,
...(headers ? { headers } : {}),
});
} catch (error) {
const status = getErrorStatus(error);
throw new ImageWorkspaceApiError(
status,
status === 501 ? IMAGE_WORKSPACE_UNAVAILABLE_CODE : 'IMAGE_WORKSPACE_REQUEST_FAILED',
error instanceof Error ? error.message : IMAGE_WORKSPACE_UNAVAILABLE_MESSAGE,
);
}
if (!response.success || !response.workspace) {
throw new ImageWorkspaceApiError(
response.status ?? 502,
response.code ?? 'IMAGE_WORKSPACE_REQUEST_FAILED',
response.error ?? '创作空间请求失败',
);
}
return response.workspace;
}
export function fetchImageWorkspace(accessToken?: string | null): Promise<ImageWorkspaceSnapshot> {
return requestImageWorkspace(accessToken, IMAGE_WORKSPACE_API_PATH);
}
export function createImageWorkspaceProject(
accessToken: string | null | undefined,
name: string,
): Promise<ImageWorkspaceSnapshot> {
return requestImageWorkspace(accessToken, `${IMAGE_WORKSPACE_API_PATH}/projects`, {
method: 'POST',
body: JSON.stringify({ name: name.trim() }),
});
}
export function addImageWorkspaceAgent(
accessToken: string | null | undefined,
projectId: string,
): Promise<ImageWorkspaceSnapshot> {
return requestImageWorkspace(
accessToken,
`${IMAGE_WORKSPACE_API_PATH}/projects/${encodeURIComponent(projectId)}/agents`,
{ method: 'POST', body: JSON.stringify({}) },
);
}
export function sendImageWorkspaceMessage(
accessToken: string | null | undefined,
input: ImageWorkspaceSendMessageInput,
): Promise<ImageWorkspaceSnapshot> {
return requestImageWorkspace(
accessToken,
`${IMAGE_WORKSPACE_API_PATH}/projects/${encodeURIComponent(input.projectId)}/messages`,
{ method: 'POST', body: JSON.stringify(input) },
);
}
export function uploadImageWorkspaceReference(
accessToken: string | null | undefined,
input: ImageWorkspaceReferenceUploadInput,
): Promise<ImageWorkspaceReferenceUploadResult> {
const headers = accessToken?.trim()
? { 'X-NianCode-Access-Token': accessToken.trim() }
: undefined;
return hostApiFetch<ImageWorkspaceEnvelope>(
`${IMAGE_WORKSPACE_API_PATH}/projects/${encodeURIComponent(input.projectId)}/references`,
{
method: 'POST',
...(headers ? { headers } : {}),
body: JSON.stringify(input),
},
).then((response) => {
if (!response.success || !response.workspace || !response.reference) {
throw new ImageWorkspaceApiError(
response.status ?? 502,
response.code ?? 'IMAGE_WORKSPACE_REQUEST_FAILED',
response.error ?? '参考图上传失败',
);
}
return { workspace: response.workspace, reference: response.reference };
}).catch((error: unknown) => {
if (error instanceof ImageWorkspaceApiError) throw error;
const status = getErrorStatus(error);
throw new ImageWorkspaceApiError(
status,
status === 501 ? IMAGE_WORKSPACE_UNAVAILABLE_CODE : 'IMAGE_WORKSPACE_REQUEST_FAILED',
error instanceof Error ? error.message : IMAGE_WORKSPACE_UNAVAILABLE_MESSAGE,
);
});
}