mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-10 01:39:25 +00:00
feat: use fixed 30-minute subagent timeout (#470)
This commit is contained in:
parent
bbcf6170a4
commit
aa610e247d
15 changed files with 88 additions and 92 deletions
6
.changeset/subagent-timeout-resume.md
Normal file
6
.changeset/subagent-timeout-resume.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
"@moonshot-ai/agent-core": minor
|
||||
"@moonshot-ai/kimi-code": minor
|
||||
---
|
||||
|
||||
Use a fixed 30-minute timeout for subagents and show concise resume instructions when they time out.
|
||||
|
|
@ -50,7 +50,6 @@ reserved_context_size = 50000
|
|||
[background]
|
||||
max_running_tasks = 4
|
||||
keep_alive_on_exit = false
|
||||
agent_task_timeout_s = 900
|
||||
|
||||
[experimental]
|
||||
goal_command = false
|
||||
|
|
@ -167,13 +166,12 @@ You can also switch models temporarily without touching the config file — by s
|
|||
|
||||
## `background`
|
||||
|
||||
`background` controls the concurrency and timeout behavior of background tasks (launched via the `Bash` tool or the `Agent` tool's `run_in_background=true` parameter).
|
||||
`background` controls the concurrency behavior of background tasks (launched via the `Bash` tool or the `Agent` tool's `run_in_background=true` parameter).
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `max_running_tasks` | `integer` | — | Maximum number of background tasks running concurrently |
|
||||
| `keep_alive_on_exit` | `boolean` | `true` | Whether to keep still-running background tasks when the session closes. Set to `false` to request that all background tasks stop before the process exits |
|
||||
| `agent_task_timeout_s` | `integer` | — | Maximum runtime in seconds for background Agent tasks |
|
||||
|
||||
`keep_alive_on_exit` can be overridden by the `KIMI_CODE_BACKGROUND_KEEP_ALIVE_ON_EXIT` environment variable, which takes higher priority than `config.toml`.
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ Collaboration tools handle inter-Agent coordination, user interaction, and Skill
|
|||
| `AskUserQuestion` | Auto-allow | Ask the user a question to gather structured input |
|
||||
| `Skill` | Auto-allow | Invoke a registered inline Skill |
|
||||
|
||||
**`Agent`** delegates a subtask to a sub-Agent. Required parameters: `prompt` (complete task description) and `description` (a 3–5 word short summary). Optional parameters: `subagent_type` (defaults to `coder`), `resume` (ID of an existing Agent to resume; mutually exclusive with `subagent_type`), `run_in_background` (defaults to false), and `timeout` (30–3600 seconds). In foreground mode the parent Agent waits for the sub-Agent to complete before continuing; in background mode a task ID is returned immediately and the result is automatically delivered back to the main Agent via a synthetic User message when done. See [Agent & Sub-Agents](../customization/agents.md) for details.
|
||||
**`Agent`** delegates a subtask to a sub-Agent. Required parameters: `prompt` (complete task description) and `description` (a 3–5 word short summary). Optional parameters: `subagent_type` (defaults to `coder`), `resume` (ID of an existing Agent to resume; mutually exclusive with `subagent_type`), and `run_in_background` (defaults to false). Agent tasks have a fixed 30-minute timeout. In foreground mode the parent Agent waits for the sub-Agent to complete before continuing; in background mode a task ID is returned immediately and the result is automatically delivered back to the main Agent via a synthetic User message when done. See [Agent & Sub-Agents](../customization/agents.md) for details.
|
||||
|
||||
**`AskUserQuestion`** asks the user a structured multiple-choice question — useful for disambiguation or option selection. The `questions` parameter accepts 1–4 questions; each question requires `question` (ending with `?`), `options` (2–4 choices, each with a `label` and `description`), and optional `header` (max 12 characters) and `multi_select` (defaults to false). An "Other" option is appended automatically. Setting `background` to true starts a background question task and returns a task ID immediately. When the host does not support interactive questioning, a failure message is returned and the Agent should ask the user directly in a text reply instead.
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ reserved_context_size = 50000
|
|||
[background]
|
||||
max_running_tasks = 4
|
||||
keep_alive_on_exit = false
|
||||
agent_task_timeout_s = 900
|
||||
|
||||
[experimental]
|
||||
goal_command = false
|
||||
|
|
@ -167,13 +166,12 @@ max_context_size = 1047576
|
|||
|
||||
## `background`
|
||||
|
||||
`background` 控制后台任务(通过 `Bash` 工具或 `Agent` 工具的 `run_in_background=true` 参数启动)的并发数和超时行为。
|
||||
`background` 控制后台任务(通过 `Bash` 工具或 `Agent` 工具的 `run_in_background=true` 参数启动)的并发数。
|
||||
|
||||
| 字段 | 类型 | 默认值 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `max_running_tasks` | `integer` | — | 同时运行的最大后台任务数 |
|
||||
| `keep_alive_on_exit` | `boolean` | `true` | 会话关闭时是否保留仍在运行的后台任务。设为 `false` 时,进程退出前会请求停止所有后台任务 |
|
||||
| `agent_task_timeout_s` | `integer` | — | 后台 Agent 任务的最长运行时间(秒) |
|
||||
|
||||
`keep_alive_on_exit` 可被环境变量 `KIMI_CODE_BACKGROUND_KEEP_ALIVE_ON_EXIT` 覆盖,优先级高于配置文件。
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ Plan 模式是一种受约束的工作状态:进入后 `Write` 与 `Edit` 只
|
|||
| `AskUserQuestion` | 自动放行 | 向用户提问以获取结构化输入 |
|
||||
| `Skill` | 自动放行 | 调用已注册的 inline Skill |
|
||||
|
||||
**`Agent`** 将子任务委托给子 Agent 执行。必填参数:`prompt`(完整任务描述)和 `description`(3–5 个词的简短说明)。可选参数:`subagent_type`(默认 `coder`)、`resume`(恢复已有 Agent 的 ID,与 `subagent_type` 互斥)、`run_in_background`(默认 false)和 `timeout`(30–3600 秒)。前台模式下父 Agent 等待子 Agent 完成再继续;后台模式立即返回任务 ID,完成时通过合成 User 消息自动回到主 Agent。子 Agent 体系细节见 [Agent 与子 Agent](../customization/agents.md)。
|
||||
**`Agent`** 将子任务委托给子 Agent 执行。必填参数:`prompt`(完整任务描述)和 `description`(3–5 个词的简短说明)。可选参数:`subagent_type`(默认 `coder`)、`resume`(恢复已有 Agent 的 ID,与 `subagent_type` 互斥)和 `run_in_background`(默认 false)。Agent 任务使用固定 30 分钟超时。前台模式下父 Agent 等待子 Agent 完成再继续;后台模式立即返回任务 ID,完成时通过合成 User 消息自动回到主 Agent。子 Agent 体系细节见 [Agent 与子 Agent](../customization/agents.md)。
|
||||
|
||||
**`AskUserQuestion`** 以结构化多选题的形式向用户提问,适用于需要消歧或选择方案的场景。`questions` 参数接受 1–4 道题,每道题需提供 `question`(以 `?` 结尾)、`options`(2–4 个选项,每项含 `label` 和 `description`)以及可选的 `header`(最多 12 字符)和 `multi_select`(默认 false)。系统自动附加"其他"选项。`background` 为 true 时启动后台问题任务并立即返回任务 ID。宿主未实现交互式提问能力时返回失败提示,Agent 应改为在文本回复中直接提问。
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ export const BackgroundConfigSchema = z.object({
|
|||
maxRunningTasks: z.number().int().min(1).optional(),
|
||||
keepAliveOnExit: z.boolean().optional(),
|
||||
killGracePeriodMs: z.number().int().min(0).optional(),
|
||||
agentTaskTimeoutS: z.number().int().min(1).optional(),
|
||||
printWaitCeilingS: z.number().int().min(1).optional(),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -456,11 +456,6 @@ export class Session {
|
|||
});
|
||||
}
|
||||
|
||||
private backgroundTaskTimeoutMs(): number | undefined {
|
||||
const timeoutS = this.options.background?.agentTaskTimeoutS;
|
||||
return timeoutS === undefined ? undefined : timeoutS * 1000;
|
||||
}
|
||||
|
||||
private refreshAgentBuiltinTools(): void {
|
||||
for (const agent of this.readyAgents()) {
|
||||
if (!agent.config.hasProvider) continue;
|
||||
|
|
@ -488,8 +483,7 @@ export class Session {
|
|||
rpc: proxyWithExtraPayload(this.rpc, { agentId: id }),
|
||||
modelProvider: this.options.providerManager,
|
||||
hookEngine: config.hookEngine ?? this.hookEngine,
|
||||
subagentHost:
|
||||
config.subagentHost ?? new SessionSubagentHost(this, id, this.backgroundTaskTimeoutMs()),
|
||||
subagentHost: config.subagentHost ?? new SessionSubagentHost(this, id),
|
||||
mcp: this.mcp,
|
||||
goals: this.goals,
|
||||
permission: this.permissionOptions(parentAgentId, config.permission),
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ export class SessionSubagentHost {
|
|||
constructor(
|
||||
private readonly session: Session,
|
||||
private readonly ownerAgentId: string,
|
||||
readonly backgroundTaskTimeoutMs?: number | undefined,
|
||||
) {}
|
||||
|
||||
async spawn(profileName: string, options: RunSubagentOptions): Promise<SubagentHandle> {
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
When `run_in_background=true`, the subagent runs detached from this turn. The completion arrives in a later turn as a synthetic user-role message containing its result — you do not need to poll, sleep, or check on its progress. Continue with other work or respond to the user. Never fabricate or predict what the result will say.
|
||||
|
||||
For a background task, when `timeout` is omitted it falls back to the operator-configured background timeout, if one is set. If the operator has not configured a background timeout, an omitted `timeout` means the task runs with no time limit.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ Writing the prompt:
|
|||
Usage notes:
|
||||
- When the task continues earlier work a subagent already did, prefer resuming that agent (pass its `resume` id) over spawning a fresh instance — the resumed agent keeps its prior context.
|
||||
- A subagent's result is only visible to you, not to the user. When the user needs to see what a subagent produced, summarize the relevant parts yourself in your own reply.
|
||||
- Subagents use a fixed 30-minute timeout. If one times out, resume the same agent instead of starting over.
|
||||
|
||||
When NOT to use Agent: skip delegation for trivial work you can do directly — reading a file whose path you already know, searching a small known set of files, or any task that takes only a step or two. Delegation has a context-handoff cost; it pays off only when the task is substantial enough to outweigh it.
|
||||
|
||||
Once a subagent is running, leave that scope to it: do not redo its searches or reads in parallel, and do not abandon it midway and finish the job manually. Both undo the context savings the delegation was meant to buy.
|
||||
Once a subagent is running, leave that scope to it: do not redo its searches or reads in parallel, and do not abandon it midway and finish the job manually. Both undo the context savings the delegation was meant to buy.
|
||||
|
|
|
|||
|
|
@ -76,15 +76,6 @@ export const AgentToolInputSchema = z.preprocess(
|
|||
.describe(
|
||||
'If true, return immediately without waiting for completion. Prefer false unless the task can run independently and there is a clear benefit to not waiting.',
|
||||
),
|
||||
timeout: z
|
||||
.number()
|
||||
.int()
|
||||
.min(30)
|
||||
.max(3600)
|
||||
.optional()
|
||||
.describe(
|
||||
'Timeout in seconds for the agent task (min 30s, max 3600s / 1hr). When omitted, a foreground task runs until completion with no timeout. The agent is stopped if it exceeds this limit.',
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
@ -108,6 +99,9 @@ export type AgentToolOutput = z.infer<typeof AgentToolOutputSchema>;
|
|||
|
||||
const BACKGROUND_AGENT_UNAVAILABLE =
|
||||
'Background agent execution is not available for this agent because TaskList, TaskOutput, and TaskStop are not enabled.';
|
||||
const AGENT_TIMEOUT_SECONDS = 30 * 60;
|
||||
const AGENT_TIMEOUT_MS = AGENT_TIMEOUT_SECONDS * 1000;
|
||||
const AGENT_TIMEOUT_DESCRIPTION = '30 minutes';
|
||||
|
||||
// ── AgentTool class ──────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -191,11 +185,8 @@ export class AgentTool implements BuiltinTool<AgentToolInput> {
|
|||
}
|
||||
}
|
||||
const backgroundController = runInBackground ? new AbortController() : undefined;
|
||||
const timeoutMs = args.timeout === undefined ? undefined : args.timeout * 1000;
|
||||
foregroundDeadline =
|
||||
!runInBackground && timeoutMs !== undefined
|
||||
? createDeadlineAbortSignal(signal, timeoutMs)
|
||||
: undefined;
|
||||
!runInBackground ? createDeadlineAbortSignal(signal, AGENT_TIMEOUT_MS) : undefined;
|
||||
|
||||
const options = {
|
||||
parentToolCallId: toolCallId,
|
||||
|
|
@ -231,7 +222,7 @@ export class AgentTool implements BuiltinTool<AgentToolInput> {
|
|||
try {
|
||||
taskId = this.backgroundManager!.registerTask(
|
||||
new AgentBackgroundTask(handle.completion, args.description, {
|
||||
timeoutMs: timeoutMs ?? this.subagentHost.backgroundTaskTimeoutMs,
|
||||
timeoutMs: AGENT_TIMEOUT_MS,
|
||||
agentId: handle.agentId,
|
||||
subagentType: handle.profileName,
|
||||
abort: () => {
|
||||
|
|
@ -281,8 +272,9 @@ export class AgentTool implements BuiltinTool<AgentToolInput> {
|
|||
return { output: lines.join('\n') };
|
||||
} catch (error) {
|
||||
let message: string;
|
||||
if (foregroundDeadline?.timedOut() === true && args.timeout !== undefined) {
|
||||
message = `Agent timed out after ${args.timeout}s.`;
|
||||
const timedOut = foregroundDeadline?.timedOut() === true;
|
||||
if (timedOut) {
|
||||
message = `Agent timed out after ${AGENT_TIMEOUT_DESCRIPTION}.`;
|
||||
} else if (isUserCancellation(signal.reason)) {
|
||||
message =
|
||||
'The user manually interrupted this subagent (and any sibling agents launched alongside it). This was a deliberate user action, not a system error, a timeout, or a capacity/concurrency limit. Do not retry automatically or speculate about why it failed — wait for the user\'s next instruction.';
|
||||
|
|
@ -298,12 +290,17 @@ export class AgentTool implements BuiltinTool<AgentToolInput> {
|
|||
'',
|
||||
`subagent error: ${message}`,
|
||||
];
|
||||
if (timedOut) {
|
||||
lines.push(
|
||||
`resume_hint: Continue with Agent(resume="${handle.agentId}", prompt="continue"). Use agent_id only; do not set subagent_type. The subagent retains its prior context; redo any unfinished tool call if its result was lost.`,
|
||||
);
|
||||
}
|
||||
return { output: lines.join('\n'), isError: true };
|
||||
}
|
||||
} catch (error) {
|
||||
let message: string;
|
||||
if (foregroundDeadline?.timedOut() === true && args.timeout !== undefined) {
|
||||
message = `Agent timed out after ${args.timeout}s.`;
|
||||
if (foregroundDeadline?.timedOut() === true) {
|
||||
message = `Agent timed out after ${AGENT_TIMEOUT_DESCRIPTION}.`;
|
||||
} else if (isUserCancellation(signal.reason)) {
|
||||
message =
|
||||
'The user manually interrupted this subagent (and any sibling agents launched alongside it). This was a deliberate user action, not a system error, a timeout, or a capacity/concurrency limit. Do not retry automatically or speculate about why it failed — wait for the user\'s next instruction.';
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@ compaction_trigger_ratio = 0.85
|
|||
max_running_tasks = 4
|
||||
keep_alive_on_exit = false
|
||||
kill_grace_period_ms = 2000
|
||||
agent_task_timeout_s = 900
|
||||
print_wait_ceiling_s = 3600
|
||||
|
||||
[[hooks]]
|
||||
|
|
@ -173,7 +172,12 @@ describe('harness config TOML loader', () => {
|
|||
reservedContextSize: 50000,
|
||||
compactionTriggerRatio: 0.85,
|
||||
});
|
||||
expect(config.background?.agentTaskTimeoutS).toBe(900);
|
||||
expect(config.background).toMatchObject({
|
||||
maxRunningTasks: 4,
|
||||
keepAliveOnExit: false,
|
||||
killGracePeriodMs: 2000,
|
||||
printWaitCeilingS: 3600,
|
||||
});
|
||||
expect(config.hooks).toEqual([
|
||||
{
|
||||
event: 'PreToolUse',
|
||||
|
|
|
|||
|
|
@ -92,33 +92,21 @@ describe('AgentTool', () => {
|
|||
expect(properties['run_in_background']?.description).toContain('false');
|
||||
});
|
||||
|
||||
it('does not mention background-only timeout details in the timeout description', () => {
|
||||
it('does not expose a timeout parameter in the JSON schema', () => {
|
||||
const host = mockSubagentHost({ spawn: vi.fn() });
|
||||
const tool = new AgentTool(host);
|
||||
const properties = (
|
||||
tool.parameters as {
|
||||
properties: Record<string, { description?: string }>;
|
||||
}
|
||||
).properties;
|
||||
const properties = (tool.parameters as { properties: Record<string, unknown> }).properties;
|
||||
|
||||
const timeoutDescription = properties['timeout']?.description ?? '';
|
||||
// #5: the background default-timeout note is kept out of the static
|
||||
// describe — it would mislead in the background-disabled variant
|
||||
expect(timeoutDescription).not.toContain('Background');
|
||||
expect(timeoutDescription).not.toContain('15min');
|
||||
expect(properties).not.toHaveProperty('timeout');
|
||||
});
|
||||
|
||||
it('explains background timeout fallback in the background-enabled description without claiming a 15min default', () => {
|
||||
it('explains the fixed background subagent timeout', () => {
|
||||
const host = mockSubagentHost({ spawn: vi.fn() });
|
||||
const tool = new AgentTool(host, createBackgroundManager().manager);
|
||||
|
||||
// #5: the background-enabled variant describes the real timeout fallback —
|
||||
// an omitted timeout falls back to the operator-configured background
|
||||
// timeout, or no time limit when the operator configured none — and must
|
||||
// never claim an incorrect "15min default".
|
||||
expect(tool.description).toContain('operator-configured background timeout');
|
||||
expect(tool.description).toContain('no time limit');
|
||||
expect(tool.description).not.toContain('15min');
|
||||
expect(tool.description).toContain('fixed 30-minute timeout');
|
||||
expect(tool.description).not.toContain('operator-configured background timeout');
|
||||
expect(tool.description).not.toContain('no time limit');
|
||||
});
|
||||
|
||||
it('does not expose a model parameter in the JSON schema', () => {
|
||||
|
|
@ -219,13 +207,16 @@ describe('AgentTool', () => {
|
|||
}),
|
||||
);
|
||||
|
||||
expect(host.spawn).toHaveBeenCalledWith('explore', {
|
||||
parentToolCallId: 'call_agent',
|
||||
prompt: 'Investigate',
|
||||
description: 'Find cause',
|
||||
runInBackground: false,
|
||||
signal,
|
||||
});
|
||||
expect(host.spawn).toHaveBeenCalledWith(
|
||||
'explore',
|
||||
expect.objectContaining({
|
||||
parentToolCallId: 'call_agent',
|
||||
prompt: 'Investigate',
|
||||
description: 'Find cause',
|
||||
runInBackground: false,
|
||||
signal: expect.any(AbortSignal),
|
||||
}),
|
||||
);
|
||||
expect(result.output).toContain('agent_id: agent-child');
|
||||
expect(result.output).toContain('actual_subagent_type: explore');
|
||||
expect(result.output).toContain('child result');
|
||||
|
|
@ -279,13 +270,16 @@ describe('AgentTool', () => {
|
|||
);
|
||||
|
||||
expect(host.spawn).not.toHaveBeenCalled();
|
||||
expect(host.resume).toHaveBeenCalledWith('agent-existing', {
|
||||
parentToolCallId: 'call_agent',
|
||||
prompt: 'Continue',
|
||||
description: 'Continue work',
|
||||
runInBackground: false,
|
||||
signal,
|
||||
});
|
||||
expect(host.resume).toHaveBeenCalledWith(
|
||||
'agent-existing',
|
||||
expect.objectContaining({
|
||||
parentToolCallId: 'call_agent',
|
||||
prompt: 'Continue',
|
||||
description: 'Continue work',
|
||||
runInBackground: false,
|
||||
signal: expect.any(AbortSignal),
|
||||
}),
|
||||
);
|
||||
expect(result.output).toContain('agent_id: agent-existing');
|
||||
expect(result.output).toContain('actual_subagent_type: explore');
|
||||
expect(result.output).toContain('resumed result');
|
||||
|
|
@ -375,13 +369,16 @@ describe('AgentTool', () => {
|
|||
);
|
||||
|
||||
expect(host.spawn).not.toHaveBeenCalled();
|
||||
expect(host.resume).toHaveBeenCalledWith('agent-existing', {
|
||||
parentToolCallId: 'call_agent',
|
||||
prompt: 'Continue',
|
||||
description: 'Continue work',
|
||||
runInBackground: false,
|
||||
signal,
|
||||
});
|
||||
expect(host.resume).toHaveBeenCalledWith(
|
||||
'agent-existing',
|
||||
expect.objectContaining({
|
||||
parentToolCallId: 'call_agent',
|
||||
prompt: 'Continue',
|
||||
description: 'Continue work',
|
||||
runInBackground: false,
|
||||
signal: expect.any(AbortSignal),
|
||||
}),
|
||||
);
|
||||
expect(result.output).toContain('actual_subagent_type: explore');
|
||||
});
|
||||
|
||||
|
|
@ -445,6 +442,7 @@ describe('AgentTool', () => {
|
|||
expect(background.getTask(taskId!)).toMatchObject({
|
||||
status: 'running',
|
||||
description: 'Find cause',
|
||||
timeoutMs: 30 * 60 * 1000,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -736,17 +734,20 @@ describe('AgentTool', () => {
|
|||
context({
|
||||
prompt: 'Investigate',
|
||||
description: 'Find cause',
|
||||
timeout: 30,
|
||||
}),
|
||||
);
|
||||
await vi.advanceTimersByTimeAsync(30_000);
|
||||
await vi.advanceTimersByTimeAsync(30 * 60 * 1000);
|
||||
const result = await resultPromise;
|
||||
|
||||
expect(result).toMatchObject({ isError: true });
|
||||
expect(result.output).toContain('agent_id: agent-child');
|
||||
expect(result.output).toContain('actual_subagent_type: coder');
|
||||
expect(result.output).toContain('status: failed');
|
||||
expect(result.output).toContain('subagent error: Agent timed out after 30s.');
|
||||
expect(result.output).toContain('subagent error: Agent timed out after 30 minutes.');
|
||||
expect(result.output).toContain('resume_hint:');
|
||||
expect(result.output).toContain('Agent(resume="agent-child", prompt="continue")');
|
||||
expect(result.output).toContain('do not set subagent_type');
|
||||
expect(result.output).toContain('retains its prior context');
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,13 +277,16 @@ describe('current builtin collaboration tools', () => {
|
|||
});
|
||||
|
||||
const result = await executeTool(tool, context(input, 'call_agent'));
|
||||
expect(host.spawn).toHaveBeenCalledWith('coder', {
|
||||
parentToolCallId: 'call_agent',
|
||||
prompt: 'Investigate',
|
||||
description: 'Find cause',
|
||||
runInBackground: false,
|
||||
signal,
|
||||
});
|
||||
expect(host.spawn).toHaveBeenCalledWith(
|
||||
'coder',
|
||||
expect.objectContaining({
|
||||
parentToolCallId: 'call_agent',
|
||||
prompt: 'Investigate',
|
||||
description: 'Find cause',
|
||||
runInBackground: false,
|
||||
signal: expect.any(AbortSignal),
|
||||
}),
|
||||
);
|
||||
expect(result.output).toContain('child result');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ compaction_trigger_ratio = 0.85
|
|||
max_running_tasks = 4
|
||||
keep_alive_on_exit = false
|
||||
kill_grace_period_ms = 2000
|
||||
agent_task_timeout_s = 900
|
||||
print_wait_ceiling_s = 3600
|
||||
|
||||
[services.moonshot_search]
|
||||
|
|
@ -154,7 +153,6 @@ max_context_size = "large"
|
|||
maxRunningTasks: 4,
|
||||
keepAliveOnExit: false,
|
||||
killGracePeriodMs: 2000,
|
||||
agentTaskTimeoutS: 900,
|
||||
printWaitCeilingS: 3600,
|
||||
});
|
||||
expect(config.services?.moonshotSearch?.customHeaders).toEqual({ 'X-Search': '1' });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue