Merge tag 'v0.3.4'

This commit is contained in:
pphua committed 2026-08-25 12:18:24 +08:00
commit 48e85b33d6
33 files changed
+1456 -120

No files matched your search

+10 -2
View File
@@ -12,10 +12,12 @@ import type {
AgentTrigger,
Asset,
Audit,
BatchCategoryItem,
BatchControlItem,
ChatAttachment,
CommandRecord,
Company,
CompanyScopeMutation,
CompanyScopeRule,
Conversation,
ConvTokenSummary,
@@ -218,6 +220,12 @@ export const api = {
deleteTaskCategory: (id: number) => del<{ deleted: number }>(`/task-categories/${id}`),
updateTaskCategory: (taskId: string, categoryId?: number) =>
patch<Task>(`/tasks/${taskId}/category`, { category_id: categoryId ?? null }),
// categoryId 省略/undefined = 移出分类(后端收到 null)
updateTasksCategory: (taskIds: string[], categoryId?: number) =>
post<{ items: BatchCategoryItem[]; category: TaskCategory | null }>("/tasks/category/batch", {
task_ids: taskIds,
category_id: categoryId ?? null,
}),
taskTemplates: () => get<{ templates: TaskTemplate[] }>("/task-templates").then((r) => arr(r.templates)),
createTaskTemplate: (input: Pick<TaskTemplate, "name" | "description" | "goal">) =>
post<TaskTemplate>("/task-templates", input),
@@ -388,12 +396,12 @@ export const api = {
},
),
addCompanyScope: (id: number, scope: CompanyScopeRule[], reason = "") =>
post<{ added: number; skipped: number; invalid: number; errors?: string[] }>(`/companies/${id}/scope`, {
post<CompanyScopeMutation>(`/companies/${id}/scope`, {
scope,
reason,
}),
updateCompanyScope: (id: number, scope: CompanyScopeRule[], reason = "") =>
post<{ added: number; skipped: number; invalid: number; errors?: string[] }>(`/companies/${id}/scope`, {
post<CompanyScopeMutation>(`/companies/${id}/scope`, {
scope,
reason,
reset: true,
+19
View File
@@ -356,6 +356,25 @@ function route(m: string, path: string, seg: string[], q: URLSearchParams, b: Re
}
return { deleted: categoryID };
}
if (path === "/tasks/category/batch" && m === "POST") {
const requested = Array.isArray(b.task_ids) ? b.task_ids.map(String) : [];
const taskIDs = [...new Set(requested)];
if (taskIDs.length === 0 || taskIDs.length > 100) throw new Error("task_ids 数量必须为 1-100");
const categoryID = typeof b.category_id === "number" ? b.category_id : undefined;
const category = categoryID === undefined ? undefined : mockTaskCategories.find((item) => item.id === categoryID);
if (categoryID !== undefined && !category) throw new Error("任务分类不存在");
const items = taskIDs.map((id) => {
const task = mockTasks.find((item) => item.id === id);
if (!task) return { id, ok: false, error: "task not found" };
task.category_id = category?.id;
task.category_name = category?.name;
return { id, ok: true };
});
return {
items,
category: category ? mockTaskCategorySnapshot().find((item) => item.id === category.id) : null,
};
}
if (seg[0] === "tasks" && seg[2] === "category" && seg.length === 3 && m === "PATCH") {
const task = mockTasks.find((item) => item.id === seg[1]);
if (!task) throw new Error("任务不存在");
+17
View File
@@ -298,6 +298,16 @@ export interface CompanyScopeRule {
value: string;
}
// 资产范围写入的结果。errors 是本次提交里不合法的行;warnings 是与本次提交无关、
// 但会让归属结果不符合预期的既有数据问题(如 ip 字段存了主机名的资产)。
export interface CompanyScopeMutation {
added: number;
skipped: number;
invalid: number;
errors?: string[];
warnings?: string[];
}
// 公司资产范围规则的一条(归属唯一真值来源)。
export interface ScopeRow {
id: number;
@@ -624,6 +634,13 @@ export interface BatchControlItem {
error?: string;
}
// 批量改分类的逐任务结果。失败只可能是任务已被删除,分类本身的写入是原子的。
export interface BatchCategoryItem {
id: string;
ok: boolean;
error?: string;
}
// Whole-task (all agents) token aggregate.
export interface TokenTotal {
input_tokens: number;