feat: 完善两阶段 Agent 自进化 Pipeline、Skills 与 Benchmark (#129)

This commit is contained in:
Jingzhe Xu
2026-07-30 15:59:58 +08:00
committed by GitHub
parent 3bd0a7208a
commit 081fe2d172
34 changed files with 2093 additions and 763 deletions
+22 -15
View File
@@ -55,6 +55,7 @@ import { toastError } from "../../components/ui/toast";
import { useVersionInfo } from "../../lib/use-version-info";
import { ChatInput } from "./chat-input";
import { buildSkillsMessage } from "./skill-use";
import { EXAMPLE_TASKS, type ExampleTask, type ExampleTaskId } from "./example-tasks";
import { clearDraft, draftKey, loadDraft, saveDraft } from "./draft-cache";
import type { DraftCache } from "./draft-cache";
import { sameModelRef } from "../models/model-grouping";
@@ -88,18 +89,6 @@ function saveAppliedRouteKey(field: RouteStateField, key: string): void {
}
}
/**
* Example tasks on the draft screen, in display order (game card first, LoL music player,
* then the RAG build). Copy lives in S.chat.exampleTasks[id]; skills are pinned via a
* `[use_skills]` block — only those the selected Agent actually has installed are included,
* so the block never references a skill the agent can't read.
*/
const EXAMPLE_TASKS: { id: "game" | "lol" | "rag"; skills: string[] }[] = [
{ id: "game", skills: ["web-design"] },
{ id: "lol", skills: ["web-design"] },
{ id: "rag", skills: ["penguin-sdk", "web-design"] },
];
export function DraftView({
projectId,
models,
@@ -415,9 +404,9 @@ export function DraftView({
// busy id drives the clicked card's spinner; the shared in-flight guard and all failure
// handling live in onSend). keepDraft: an example never consumes the composer text, so a
// typed-but-unsent draft must survive. The selected model / Workspace / approval mode apply as-is.
const [exampleBusy, setExampleBusy] = useState<"game" | "lol" | "rag" | null>(null);
const [exampleBusy, setExampleBusy] = useState<ExampleTaskId | null>(null);
const runExample = useCallback(
async (task: (typeof EXAMPLE_TASKS)[number]) => {
async (task: ExampleTask) => {
if (exampleBusy !== null) return;
setExampleBusy(task.id);
try {
@@ -517,7 +506,25 @@ export function DraftView({
className="group flex min-w-0 items-center gap-3 rounded-xl border border-gray-200 bg-white px-4 py-3 text-left transition-colors duration-150 hover:border-gray-300 disabled:cursor-default disabled:opacity-60 dark:border-gray-800 dark:bg-gray-900 dark:hover:border-gray-700"
>
{/* 24×24 line icons (gamepad / music note / sparkle), consistent with the icon convention */}
{task.id === "lol" ? (
{task.id === "agentBenchmarkBuild" || task.id === "agentOptimization" ? (
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
className="shrink-0 text-brand-500 dark:text-brand-400"
aria-hidden
>
<path
d="M7 7h8a4 4 0 0 1 4 4v1M17 5l2 2-2 2M17 17H9a4 4 0 0 1-4-4v-1M7 19l-2-2 2-2"
strokeWidth="1.7"
strokeLinecap="round"
strokeLinejoin="round"
/>
<circle cx="12" cy="12" r="2" strokeWidth="1.7" />
</svg>
) : task.id === "lol" ? (
<svg
width="20"
height="20"
@@ -0,0 +1,17 @@
/**
* Draft-screen example cards in display order.
*
* Copy and full prompts live in the active locale dictionary at
* `S.chat.exampleTasks[id]`. Skills listed here are pinned only when the
* selected Agent has them installed; an empty list sends the prompt unchanged.
*/
export const EXAMPLE_TASKS = [
{ id: "game", skills: ["web-design"] },
{ id: "lol", skills: ["web-design"] },
{ id: "rag", skills: ["penguin-sdk", "web-design"] },
{ id: "agentBenchmarkBuild", skills: [] },
{ id: "agentOptimization", skills: [] },
] as const;
export type ExampleTask = (typeof EXAMPLE_TASKS)[number];
export type ExampleTaskId = ExampleTask["id"];