Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/app/repo/agent_task.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,21 @@ describe("AgentTaskRunRepo", () => {

it("appendRun 超过 MAX_RUNS_PER_TASK 时裁剪最老记录", async () => {
const taskId = "task-ring";
for (let i = 0; i < 105; i++) {
// 预填 500 条数据(最新在前),避免逐条 append 超时
const prefilled: AgentTaskRun[] = [];
for (let i = 499; i >= 0; i--) {
prefilled.push(makeRun({ id: `rr-${i}`, taskId, starttime: i }));
}
await (repo as any).writeJsonFile(`${taskId}.json`, prefilled);

// 再 append 5 条(id rr-500 ~ rr-504),触发裁剪
for (let i = 500; i < 505; i++) {
await repo.appendRun(makeRun({ id: `rr-${i}`, taskId, starttime: i }));
}
const runs = await repo.listRuns(taskId, 200);
expect(runs.length).toBe(100);
const runs = await repo.listRuns(taskId, 600);
expect(runs.length).toBe(500);
// 最新的在前,最老 5 条被裁剪掉(rr-0 ~ rr-4)
expect(runs[0].id).toBe("rr-104");
expect(runs[99].id).toBe("rr-5");
expect(runs[0].id).toBe("rr-504");
expect(runs[499].id).toBe("rr-5");
});
});
2 changes: 1 addition & 1 deletion src/app/repo/agent_task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class AgentTaskRepo extends Repo<AgentTask> {
}
}

const MAX_RUNS_PER_TASK = 100;
const MAX_RUNS_PER_TASK = 500;

export class AgentTaskRunRepo extends OPFSRepo {
constructor() {
Expand Down
106 changes: 0 additions & 106 deletions src/app/repo/sub_agent_context.test.ts

This file was deleted.

55 changes: 0 additions & 55 deletions src/app/repo/sub_agent_context.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/app/service/agent/core/system_prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ The sub-agent starts fresh — it has zero context from this conversation. Brief
- **Launch multiple agents concurrently** whenever possible — call \`agent\` multiple times **in the same response**.
- Sub-agent results are not visible to the user. Summarize the results for the user after sub-agents complete.
- Sub-agents share the parent's task list — they can call \`update_task\` to report progress.
- To continue a previously completed sub-agent, use the \`to\` parameter with the agentId.
### When NOT to Use
Expand Down
7 changes: 2 additions & 5 deletions src/app/service/agent/core/tools/sub_agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ describe("sub_agent", () => {
prompt: "Search for X",
description: "Searching X",
type: undefined,
to: undefined,
});
expect(result).toContain("[agentId: test-id]");
expect(result).toContain("Sub-agent result");
Expand All @@ -30,20 +29,18 @@ describe("sub_agent", () => {
prompt: "Do something",
description: "Sub-agent task",
type: undefined,
to: undefined,
});
});

it("should pass type and to parameters", async () => {
it("should pass type parameter", async () => {
const mockRunSubAgent = vi.fn().mockResolvedValue({ agentId: "id3", result: "ok" });
const { executor } = createSubAgentTool({ runSubAgent: mockRunSubAgent });

await executor.execute({ prompt: "Research X", type: "researcher", to: "prev-agent-id" });
await executor.execute({ prompt: "Research X", type: "researcher" });
expect(mockRunSubAgent).toHaveBeenCalledWith({
prompt: "Research X",
description: "Sub-agent task",
type: "researcher",
to: "prev-agent-id",
});
});

Expand Down
16 changes: 4 additions & 12 deletions src/app/service/agent/core/tools/sub_agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export type SubAgentRunOptions = {
prompt: string;
description: string;
type?: string;
to?: string; // 延续已有子代理
tabId?: number; // 父代理传递的标签页上下文
};

Expand All @@ -26,30 +25,24 @@ const SUB_AGENT_TYPE_NAMES = Object.keys(SUB_AGENT_TYPES);
export const SUB_AGENT_DEFINITION: ToolDefinition = {
name: "agent",
description:
"Launch a sub-agent to handle a subtask autonomously. Sub-agents run in their own conversation context. Use the `type` parameter to select a specialized sub-agent, or use `to` to continue a previous sub-agent with follow-up instructions.",
"Launch a sub-agent to handle a subtask autonomously. Sub-agents run in their own conversation context. Use the `type` parameter to select a specialized sub-agent.",
parameters: {
type: "object",
properties: {
prompt: {
type: "string",
description: "The task description or follow-up message for the sub-agent. Be specific about what you need.",
description: "The task description for the sub-agent. Be specific about what you need.",
},
description: {
type: "string",
description:
"A short (3-5 word) description of what the sub-agent will do, shown in the UI. Optional when resuming a previous sub-agent via `to`.",
description: "A short (3-5 word) description of what the sub-agent will do, shown in the UI.",
},
type: {
type: "string",
enum: SUB_AGENT_TYPE_NAMES,
description:
"Sub-agent type. 'researcher' (web search/fetch, page reading — read-only, no DOM interaction), 'page_operator' (browser tab interaction, DOM manipulation, page automation), 'general' (all tools, default). Choose the most specific type for better results.",
},
to: {
type: "string",
description:
"agentId of a previously completed sub-agent. Sends a follow-up message while preserving the sub-agent's full conversation context.",
},
tab_id: {
type: "number",
description:
Expand All @@ -71,10 +64,9 @@ export function createSubAgentTool(params: {
const prompt = requireString(args, "prompt");
const description = (args.description as string) || "Sub-agent task";
const type = args.type as string | undefined;
const to = args.to as string | undefined;
const tabId = args.tab_id as number | undefined;

const result = await params.runSubAgent({ prompt, description, type, to, tabId });
const result = await params.runSubAgent({ prompt, description, type, tabId });

// 返回结构化结果,附带子代理执行详情用于持久化
const content = `[agentId: ${result.agentId}]\n\n${result.result}`;
Expand Down
2 changes: 1 addition & 1 deletion src/app/service/agent/service_worker/chat_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ export class ChatService {
// Sub-agent
const subAgentTool = createSubAgentTool({
runSubAgent: (options: SubAgentRunOptions) => {
const agentId = options.to || uuidv4();
const agentId = uuidv4();
const typeConfig = resolveSubAgentType(options.type);
// 组合父信号和类型配置的超时信号
const subSignal = AbortSignal.any([abortController.signal, AbortSignal.timeout(typeConfig.timeoutMs)]);
Expand Down
Loading
Loading