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

96
src/lib/agent-profile.ts Normal file
View File

@@ -0,0 +1,96 @@
import { hostApiFetch } from '@/lib/host-api';
export type AgentProfileGender = 'male' | 'female' | 'other' | null;
export type AgentProfileRead = {
display_name: string | null;
age: number | null;
gender: AgentProfileGender;
share_age_with_agents: boolean;
share_gender_with_agents: boolean;
analysis_enabled: boolean;
completed: boolean;
version: number;
updated_at: string | null;
};
export type AgentProfileUpdate = {
display_name: string;
age: number | null;
gender: AgentProfileGender;
share_age_with_agents: boolean;
share_gender_with_agents: boolean;
analysis_enabled: boolean;
version: number;
};
type AgentProfileEnvelope = {
success?: boolean;
status?: number;
profile?: AgentProfileRead;
error?: string;
detail?: unknown;
};
export class AgentProfileApiError extends Error {
readonly status: number;
readonly detail: unknown;
constructor(status: number, message: string, detail?: unknown) {
super(message);
this.name = 'AgentProfileApiError';
this.status = status;
this.detail = detail;
}
}
function readDetailMessage(detail: unknown): string | null {
if (typeof detail === 'string' && detail.trim()) return detail.trim();
if (!detail || typeof detail !== 'object' || Array.isArray(detail)) return null;
const record = detail as Record<string, unknown>;
for (const field of ['message', 'error', 'code']) {
const value = record[field];
if (typeof value === 'string' && value.trim()) return value.trim();
}
return null;
}
async function requestAgentProfile(
accessToken: string,
init: RequestInit = {},
): Promise<AgentProfileRead> {
const response = await hostApiFetch<AgentProfileEnvelope>('/api/works/user/agent-profile', {
...init,
headers: {
'X-NianCode-Access-Token': accessToken,
...init.headers,
},
});
if (!response?.success || !response.profile) {
const status = typeof response?.status === 'number' ? response.status : 502;
const detailMessage = readDetailMessage(response?.detail);
throw new AgentProfileApiError(
status,
response?.error || detailMessage || `Agent Profile request failed (${status})`,
response?.detail,
);
}
return response.profile;
}
export function getAgentProfile(accessToken: string): Promise<AgentProfileRead> {
return requestAgentProfile(accessToken);
}
export function putAgentProfile(
accessToken: string,
update: AgentProfileUpdate,
): Promise<AgentProfileRead> {
return requestAgentProfile(accessToken, {
method: 'PUT',
body: JSON.stringify(update),
});
}