merge: maestro/tsk_zacmwH3chZpG [tsk_zacmwH3chZpG]
This commit is contained in:
+17
-3
@@ -7,6 +7,7 @@ import type { TaskStatus } from '../model/status.js';
|
||||
import type { Project, Autonomy } from '../model/types.js';
|
||||
import { syncProject, hasTodoJson } from '../sync/todo-sync.js';
|
||||
import { resolvedExecutorModels } from '../executor/models.js';
|
||||
import { classifyComplexity, type ClassifierFn } from '../executor/classify.js';
|
||||
import { mergeBranch } from '../executor/merge.js';
|
||||
import { git, removeWorktree } from '../executor/worktree.js';
|
||||
import { resolveLogo, LOGO_MIME } from './logo.js';
|
||||
@@ -24,6 +25,8 @@ export interface ApiOptions {
|
||||
logger?: boolean;
|
||||
/** Claude 订阅额度查询(测试注入;默认直连 OAuth usage API,60s 缓存) */
|
||||
getUsage?: () => Promise<UsageInfo | null>;
|
||||
/** AUTO 复杂度分类器(测试注入;默认 classifyComplexity,用 sonnet 起一次轻量调用) */
|
||||
classify?: ClassifierFn;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,6 +35,7 @@ export interface ApiOptions {
|
||||
*/
|
||||
export function buildServer(opts: ApiOptions): FastifyInstance {
|
||||
const { store } = opts;
|
||||
const classify = opts.classify ?? ((title, description, cwd) => classifyComplexity(title, description, { cwd }));
|
||||
const app = Fastify({ logger: opts.logger ?? false });
|
||||
|
||||
// Store 错误 → 400(业务校验),其余 → 500
|
||||
@@ -156,13 +160,23 @@ export function buildServer(opts: ApiOptions): FastifyInstance {
|
||||
const { id } = req.params as { id: string };
|
||||
const b = req.body as Record<string, unknown>;
|
||||
if (!b?.title) throw new StoreError('title 必填');
|
||||
if (!isComplexity(b.complexity)) throw new StoreError('complexity 必须是 hard|medium|easy');
|
||||
return store.createTask({
|
||||
projectId: id, title: String(b.title), complexity: b.complexity as Complexity,
|
||||
// 'auto' = 由模型判定:先以 medium 落库占位,建任务后异步回填(不阻塞返回)
|
||||
const auto = b.complexity === 'auto';
|
||||
if (!auto && !isComplexity(b.complexity)) throw new StoreError('complexity 必须是 auto|hard|medium|easy');
|
||||
const task = store.createTask({
|
||||
projectId: id, title: String(b.title), complexity: auto ? 'medium' : (b.complexity as Complexity),
|
||||
parentId: b.parentId ? String(b.parentId) : null,
|
||||
priority: b.priority === undefined ? undefined : Number(b.priority),
|
||||
deps: Array.isArray(b.deps) ? (b.deps as string[]) : undefined,
|
||||
});
|
||||
if (auto) {
|
||||
// 异步分类回填:classifyComplexity 自身永不抛错(失败兜底 medium),外层再兜一层防御
|
||||
const cwd = store.getProject(id)?.repoPath ?? process.cwd();
|
||||
void classify(task.title, undefined, cwd)
|
||||
.then(({ complexity, reason }) => store.applyAutoComplexity(task.id, complexity, reason))
|
||||
.catch((e: unknown) => app.log.error(`任务 ${task.id} AUTO 复杂度分类失败(保留占位 medium):${(e as Error).message}`));
|
||||
}
|
||||
return task;
|
||||
});
|
||||
|
||||
app.get('/api/tasks/:id', (req) => {
|
||||
|
||||
Reference in New Issue
Block a user