1. Y-Log 上报 optDetail 前缀 B1-CM助手 → CM助手-全量(全量替换 44 个前端文件 + 文档) 2. 知识库入库 nodeName 改为只取 md5(标题).md(去掉时间戳),同一篇 md 每次入库一致,避免重复记录 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
120 lines
3.0 KiB
TypeScript
120 lines
3.0 KiB
TypeScript
import { getNoteApiBaseURL } from "@/core/config";
|
|
import { OptType, writeYLog } from "@/core/log/y-log";
|
|
|
|
import {
|
|
ensureNoteAuth,
|
|
getNoteAuthorizationHeader,
|
|
getStoredNoteAuth,
|
|
} from "./auth";
|
|
|
|
export type { NoteAuth } from "./auth";
|
|
|
|
export interface SearchSpace {
|
|
created_at: string;
|
|
id: number;
|
|
name: string;
|
|
description: string;
|
|
user_id: string;
|
|
citations_enabled: boolean;
|
|
qna_custom_instructions: string;
|
|
summary: string | null;
|
|
avatar_url: string | null;
|
|
sources_limit: number;
|
|
sources_used: number;
|
|
is_shared: boolean;
|
|
is_owner: boolean;
|
|
owner_email: string | null;
|
|
member_count?: number;
|
|
source_count?: number;
|
|
membership_role?: string;
|
|
}
|
|
|
|
export interface ListSearchSpacesQuery {
|
|
owned_only?: boolean;
|
|
limit?: number;
|
|
order_by?: string;
|
|
}
|
|
|
|
export interface CreateSearchSpaceInput {
|
|
name: string;
|
|
description?: string;
|
|
citations_enabled?: boolean;
|
|
}
|
|
|
|
export async function noteApiFetch(
|
|
path: string,
|
|
init: RequestInit = {},
|
|
): Promise<Response> {
|
|
const auth = getStoredNoteAuth() ?? (await ensureNoteAuth());
|
|
|
|
const headers = new Headers(init.headers);
|
|
headers.set("Authorization", getNoteAuthorizationHeader(auth));
|
|
|
|
return fetch(`${getNoteApiBaseURL()}${path}`, {
|
|
...init,
|
|
headers,
|
|
});
|
|
}
|
|
|
|
export async function createSearchSpace(
|
|
input: CreateSearchSpaceInput,
|
|
): Promise<SearchSpace> {
|
|
await ensureNoteAuth();
|
|
|
|
const response = await noteApiFetch("/api/v1/searchspaces", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
name: input.name,
|
|
description: input.description ?? "",
|
|
citations_enabled: input.citations_enabled ?? true,
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`创建笔记失败: ${response.status} ${response.statusText}`);
|
|
}
|
|
|
|
const result = (await response.json()) as SearchSpace;
|
|
writeYLog({
|
|
optType: OptType.create,
|
|
optDetail: "CM助手-全量-笔记-新建笔记空间",
|
|
url: "/api/v1/searchspaces",
|
|
reqParam: { name: input.name, description: input.description ?? "" },
|
|
returnParam: { id: result.id, name: result.name },
|
|
});
|
|
return result;
|
|
}
|
|
|
|
export async function listSearchSpaces(
|
|
query: ListSearchSpacesQuery = {},
|
|
): Promise<SearchSpace[]> {
|
|
await ensureNoteAuth();
|
|
|
|
const params = new URLSearchParams({
|
|
owned_only: String(query.owned_only ?? true),
|
|
limit: String(query.limit ?? 1000),
|
|
order_by: query.order_by ?? "created_at",
|
|
});
|
|
|
|
const path = `/api/v1/searchspaces?${params.toString()}`;
|
|
const response = await noteApiFetch(path, { method: "GET" });
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`获取笔记列表失败: ${response.status} ${response.statusText}`);
|
|
}
|
|
|
|
const data: unknown = await response.json();
|
|
const list = Array.isArray(data) ? (data as SearchSpace[]) : [];
|
|
writeYLog({
|
|
optType: OptType.search,
|
|
optDetail: "CM助手-全量-笔记-查询笔记空间列表",
|
|
url: path,
|
|
reqParam: query,
|
|
returnParam: { count: list.length },
|
|
});
|
|
return list;
|
|
}
|