Skip to content
This repository was archived by the owner on Aug 25, 2026. It is now read-only.
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
5 changes: 5 additions & 0 deletions .changeset/interrupt-reminder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": patch
---

Preserve the assistant's partial output when a turn is interrupted with Esc, and remind the model that the previous turn was deliberately interrupted.
5 changes: 5 additions & 0 deletions .changeset/task-output-nonblocking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": patch
---

Remove the blocking `block`/`timeout` wait from the TaskOutput tool so checking a background task can no longer stall the conversation; it now always returns an immediate snapshot, and completion still arrives via automatic notification.
Comment on lines +1 to +5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use a minor changeset for the removed TaskOutput inputs.

Removing block and timeout changes the public tool input contract. A patch release can break callers that still send either field. Change the bump to minor.

As per coding guidelines, .changeset/*.{md,yml,yaml} requires minor when major is not explicitly confirmed and minor is clear.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/task-output-nonblocking.md around lines 1 - 5, Change the
changeset bump for "`@moonshot-ai/kimi-code`" from patch to minor in
task-output-nonblocking.md, reflecting the removed public TaskOutput inputs
while leaving the release note unchanged.

Source: Coding guidelines

2 changes: 1 addition & 1 deletion docs/en/reference/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Background task tools manage tasks started via `Bash`, `Agent`, or `AskUserQuest

**`TaskList`** returns the list of background tasks. Optional parameters: `active_only` (defaults to true; lists only running tasks) and `limit` (defaults to 20; range 1–100).

**`TaskOutput`** returns the status and output of a task given its `task_id`. The inline preview includes at most the most recent 32 KB of content; the full log is saved to disk, and the tool also returns an `output_path` with a suggestion to use `Read` for paginated access. Optional `block` (defaults to false) and `timeout` (seconds to wait; defaults to 30; range 0–3600) parameters allow waiting for the task to complete before returning.
**`TaskOutput`** returns the status and output of a task given its `task_id`. The inline preview includes at most the most recent 32 KB of content; the full log is saved to disk, and the tool also returns an `output_path` with a suggestion to use `Read` for paginated access. The call is always non-blocking — it returns the current snapshot immediately, and task completion is delivered via automatic notification.

**`TaskStop`** accepts a `task_id` and optional `reason` (defaults to `Stopped by TaskStop`). Safe to call on tasks that are already in a terminal state.

Expand Down
2 changes: 1 addition & 1 deletion docs/zh/reference/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ Plan 模式是一种受约束的工作状态:进入后 `Write` 与 `Edit` 只

**`TaskList`** 返回后台任务列表。可选参数 `active_only`(默认 true,仅列出运行中的任务)和 `limit`(默认 20,取值范围 1–100)。

**`TaskOutput`** 根据 `task_id` 返回任务状态与输出。内联预览最多包含最近 32 KB 的内容;完整日志保存在磁盘上,工具会一并返回 `output_path` 并提示通过 `Read` 分页读取。可选 `block`(默认 false)和 `timeout`(等待秒数,默认 30,取值范围 0–3600)参数可用于等待任务完成后再返回。
**`TaskOutput`** 根据 `task_id` 返回任务状态与输出。内联预览最多包含最近 32 KB 的内容;完整日志保存在磁盘上,工具会一并返回 `output_path` 并提示通过 `Read` 分页读取。该调用始终是非阻塞的——立即返回当前快照,任务完成会通过自动通知送达。

**`TaskStop`** 接受 `task_id` 和可选的 `reason`(默认 `Stopped by TaskStop`)。对已处于终止状态的任务也能安全调用。

Expand Down
2 changes: 1 addition & 1 deletion packages/agent-core-v2/docs/state-manifest.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,7 @@ export interface AgentStateSnapshot {
'llmRequester.lastConfigLogSignature': string | undefined;
'llmRequester.mediaDegradedTurns': Set<number>;
'llmRequester.mediaStrippedTurns': Map<number, /* MediaStripSnapshot — packages/agent-core-v2/src/agent/contextProjector/contextProjector.ts */ {
readonly "__@mediaStripSnapshotBrand@2700": undefined;
readonly "__@mediaStripSnapshotBrand": undefined;
}>;
'llmRequester.turnConfigs': Map<number, /* TurnRequestConfig — packages/agent-core-v2/src/agent/llmRequester/llmRequesterService.ts */ {
readonly resolved: /* ProfileModelContext — packages/agent-core-v2/src/agent/profile/profile.ts */ {
Expand Down
161 changes: 115 additions & 46 deletions packages/agent-core-v2/docs/wire-manifest.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,51 +21,53 @@
// owning model offloads inline media to blob storage), cross-reducers
// (foreign models that also reduce this record on dispatch and replay).

// Index (44 record types)
// config.update profile persisted src/agent/profile/profileOps.ts
// context_size.measured contextSize transient src/agent/contextSize/contextSizeOps.ts
// context.append_loop_event contextMemory persisted src/agent/contextMemory/contextOps.ts
// context.append_message contextMemory persisted src/agent/contextMemory/contextOps.ts
// context.apply_compaction contextMemory persisted src/agent/contextMemory/contextOps.ts
// context.clear contextMemory persisted src/agent/contextMemory/contextOps.ts
// context.undo contextMemory persisted src/agent/contextMemory/contextOps.ts
// cron.add cron transient src/session/cron/cronOps.ts
// cron.cursor cron transient src/session/cron/cronOps.ts
// cron.delete cron transient src/session/cron/cronOps.ts
// forked goal persisted src/agent/goal/goalOps.ts
// full_compaction.begin fullCompaction persisted src/agent/fullCompaction/compactionOps.ts
// full_compaction.cancel fullCompaction persisted src/agent/fullCompaction/compactionOps.ts
// full_compaction.complete fullCompaction persisted src/agent/fullCompaction/compactionOps.ts
// goal.clear goal persisted src/agent/goal/goalOps.ts
// goal.create goal persisted src/agent/goal/goalOps.ts
// goal.update goal persisted src/agent/goal/goalOps.ts
// interaction.request interaction persisted src/session/interaction/interactionOps.ts
// interaction.resolved interaction persisted src/session/interaction/interactionOps.ts
// llm.request llm.requestTrace persisted src/agent/llmRequester/llmRequestOps.ts
// llm.tools_snapshot llm.requestTrace persisted src/agent/llmRequester/llmRequestOps.ts
// mcp.tools_discovered mcp.discovery persisted src/agent/mcp/mcpDiscoveryOps.ts
// permission.record_approval_result permissionRules persisted src/agent/permissionRules/permissionRulesOps.ts
// permission.rules.add permissionRules transient src/agent/permissionRules/permissionRulesOps.ts
// permission.set_mode permissionMode persisted src/agent/permissionMode/permissionModeOps.ts
// plan_mode.cancel plan persisted src/agent/plan/planOps.ts
// plan_mode.enter plan persisted src/agent/plan/planOps.ts
// plan_mode.exit plan persisted src/agent/plan/planOps.ts
// plan.revision plan persisted src/agent/plan/planOps.ts
// profile.bind profile persisted src/agent/profile/profileOps.ts
// skill.activate skill transient src/agent/skill/skillOps.ts
// swarm_mode.enter swarm persisted src/agent/swarm/swarmOps.ts
// swarm_mode.exit swarm persisted src/agent/swarm/swarmOps.ts
// task.started task persisted src/agent/task/taskOps.ts
// task.terminated task persisted src/agent/task/taskOps.ts
// tools.register_user_tool userTool persisted src/agent/userTool/userToolOps.ts
// tools.reset_active_tools profile.activeTools persisted src/agent/profile/profileOps.ts
// tools.set_active_tools profile.activeTools persisted src/agent/profile/profileOps.ts
// tools.unregister_user_tool userTool persisted src/agent/userTool/userToolOps.ts
// tools.update_store todo persisted src/session/todo/todoOps.ts
// turn.cancel turn persisted src/agent/loop/turnOps.ts
// turn.prompt turn persisted src/agent/loop/turnOps.ts
// turn.steer turn persisted src/agent/loop/turnOps.ts
// usage.record usage persisted src/agent/usage/usageOps.ts
// Index (46 record types)
// config.update profile persisted src/agent/profile/profileOps.ts
// context_size.measured contextSize transient src/agent/contextSize/contextSizeOps.ts
// context.append_loop_event contextMemory persisted src/agent/contextMemory/contextOps.ts
// context.append_message contextMemory persisted src/agent/contextMemory/contextOps.ts
// context.apply_compaction contextMemory persisted src/agent/contextMemory/contextOps.ts
// context.clear contextMemory persisted src/agent/contextMemory/contextOps.ts
// context.undo contextMemory persisted src/agent/contextMemory/contextOps.ts
// cron.add cron transient src/session/cron/cronOps.ts
// cron.cursor cron transient src/session/cron/cronOps.ts
// cron.delete cron transient src/session/cron/cronOps.ts
// forked goal persisted src/agent/goal/goalOps.ts
// full_compaction.begin fullCompaction persisted src/agent/fullCompaction/compactionOps.ts
// full_compaction.cancel fullCompaction persisted src/agent/fullCompaction/compactionOps.ts
// full_compaction.complete fullCompaction persisted src/agent/fullCompaction/compactionOps.ts
// goal.clear goal persisted src/agent/goal/goalOps.ts
// goal.create goal persisted src/agent/goal/goalOps.ts
// goal.update goal persisted src/agent/goal/goalOps.ts
// interaction.request interaction persisted src/session/interaction/interactionOps.ts
// interaction.resolved interaction persisted src/session/interaction/interactionOps.ts
// interruptionReminder.recorded interruptionReminder persisted src/agent/interruptionReminder/interruptionReminderOps.ts
// llm.request llm.requestTrace persisted src/agent/llmRequester/llmRequestOps.ts
// llm.tools_snapshot llm.requestTrace persisted src/agent/llmRequester/llmRequestOps.ts
// mcp.tools_discovered mcp.discovery persisted src/agent/mcp/mcpDiscoveryOps.ts
// permission.record_approval_result permissionRules persisted src/agent/permissionRules/permissionRulesOps.ts
// permission.rules.add permissionRules transient src/agent/permissionRules/permissionRulesOps.ts
// permission.set_mode permissionMode persisted src/agent/permissionMode/permissionModeOps.ts
// plan_mode.cancel plan persisted src/agent/plan/planOps.ts
// plan_mode.enter plan persisted src/agent/plan/planOps.ts
// plan_mode.exit plan persisted src/agent/plan/planOps.ts
// plan.revision plan persisted src/agent/plan/planOps.ts
// profile.bind profile persisted src/agent/profile/profileOps.ts
// skill.activate skill transient src/agent/skill/skillOps.ts
// swarm_mode.enter swarm persisted src/agent/swarm/swarmOps.ts
// swarm_mode.exit swarm persisted src/agent/swarm/swarmOps.ts
// task.started task persisted src/agent/task/taskOps.ts
// task.terminated task persisted src/agent/task/taskOps.ts
// tools.register_user_tool userTool persisted src/agent/userTool/userToolOps.ts
// tools.reset_active_tools profile.activeTools persisted src/agent/profile/profileOps.ts
// tools.set_active_tools profile.activeTools persisted src/agent/profile/profileOps.ts
// tools.unregister_user_tool userTool persisted src/agent/userTool/userToolOps.ts
// tools.update_store todo persisted src/session/todo/todoOps.ts
// turn.cancel turn persisted src/agent/loop/turnOps.ts
// turn.ended turn persisted src/agent/loop/turnOps.ts
// turn.prompt turn persisted src/agent/loop/turnOps.ts
// turn.steer turn persisted src/agent/loop/turnOps.ts
// usage.record usage persisted src/agent/usage/usageOps.ts

/**
* model: profile · persisted
Expand Down Expand Up @@ -306,6 +308,15 @@ interface InteractionResolvedPayload {
response: any;
}

/**
* model: interruptionReminder · persisted
* owner: src/agent/interruptionReminder/interruptionReminderOps.ts
*/
interface InterruptionReminderRecordedPayload {
_name: 'interruptionReminder.recorded';
turnId: number;
}

/**
* model: llm.requestTrace · persisted
* owner: src/agent/llmRequester/llmRequestOps.ts
Expand Down Expand Up @@ -564,13 +575,69 @@ interface ToolsUpdateStorePayload {
}

/**
* model: turn · persisted
* model: turn · persisted · cross-reducers: interruptionReminder
* owner: src/agent/loop/turnOps.ts
*/
interface TurnCancelPayload {
_name: 'turn.cancel';
turnId?: number;
target?: 'active' | 'queued';
reason?: 'user_cancelled' | 'aborted';
}

/**
* model: turn · persisted
* owner: src/agent/loop/turnOps.ts
*/
interface TurnEndedPayload {
_name: 'turn.ended';
turnId: number;
reason: 'completed' | 'cancelled' | 'failed' | 'blocked';
/** KimiErrorPayload */
error?: {
code: (typeof ErrorCodes)[keyof typeof ErrorCodes];
message: string;
name?: string;
details?: Readonly<Record<string, unknown>>;
retryable: boolean;
cause?: {
code: (typeof ErrorCodes)[keyof typeof ErrorCodes];
message: string;
name?: string;
details?: Readonly<Record<string, unknown>>;
retryable: boolean;
cause?: {
code: (typeof ErrorCodes)[keyof typeof ErrorCodes];
message: string;
name?: string;
details?: Readonly<Record<string, unknown>>;
retryable: boolean;
cause?: {
code: (typeof ErrorCodes)[keyof typeof ErrorCodes];
message: string;
name?: string;
details?: Readonly<Record<string, unknown>>;
retryable: boolean;
cause?: {
code: (typeof ErrorCodes)[keyof typeof ErrorCodes];
message: string;
name?: string;
details?: Readonly<Record<string, unknown>>;
retryable: boolean;
cause?: {
code: ErrorCode;
message: string;
name?: string;
details?: Readonly<Record<string, unknown>>;
retryable: boolean;
cause?: ErrorPayload;
};
};
};
};
};
};
durationMs?: number;
}

/**
Expand Down Expand Up @@ -634,6 +701,7 @@ interface WirePayloadMap {
"goal.update": GoalUpdatePayload;
"interaction.request": InteractionRequestPayload;
"interaction.resolved": InteractionResolvedPayload;
"interruptionReminder.recorded": InterruptionReminderRecordedPayload;
"llm.request": LlmRequestPayload;
"llm.tools_snapshot": LlmToolsSnapshotPayload;
"mcp.tools_discovered": McpToolsDiscoveredPayload;
Expand All @@ -656,6 +724,7 @@ interface WirePayloadMap {
"tools.unregister_user_tool": ToolsUnregisterUserToolPayload;
"tools.update_store": ToolsUpdateStorePayload;
"turn.cancel": TurnCancelPayload;
"turn.ended": TurnEndedPayload;
"turn.prompt": TurnPromptPayload;
"turn.steer": TurnSteerPayload;
"usage.record": UsageRecordPayload;
Expand Down
12 changes: 11 additions & 1 deletion packages/agent-core-v2/scripts/gen-state-manifest.mts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ function tsFieldKey(key: string): string {
return /^[$A-Z_a-z][$\w]*$/.test(key) ? key : JSON.stringify(key);
}

/**
* The checker names a `unique symbol` key `__@<declName>@<globalSymbolId>` —
* the numeric id is a compilation-global counter that shifts with unrelated
* edits, so the manifest renders the stable `__@<declName>` form instead.
*/
function stableSymbolKey(key: string): string {
const match = /^__@(.+)@\d+$/.exec(key);
return match === null ? key : `__@${match[1]}`;
}

// ---------------------------------------------------------------------------
// Static pass — key constants and their register call sites
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -621,7 +631,7 @@ class TypeRenderer {
const propLines = rendered.split('\n');
propLines[propLines.length - 1] += ';';
lines.push(
` ${readonly}${tsFieldKey(prop.getName())}${optional ? '?' : ''}: ${propLines[0]}`,
` ${readonly}${tsFieldKey(stableSymbolKey(prop.getName()))}${optional ? '?' : ''}: ${propLines[0]}`,
...propLines.slice(1).map((line) => ` ${line}`),
);
}
Expand Down
18 changes: 5 additions & 13 deletions packages/agent-core-v2/src/agent/goal/goalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ export class AgentGoalService extends Disposable implements IAgentGoalService {
const state = this.requireState();
const snapshot = this.toSnapshot(state);
if (state.status === 'active' && this.liveTurnId !== undefined) {
this.loopService.cancel(this.liveTurnId);
this.loopService.cancel(this.liveTurnId, abortError('Goal cancelled'));
}
this.clearInternal(actor);
if (actor === 'user') {
Expand Down Expand Up @@ -988,18 +988,10 @@ export class AgentGoalService extends Disposable implements IAgentGoalService {
const pending = this.pendingContinuation;
if (preserveLiveContinuation && pending?.turnId === this.liveTurnId) return;
this.pendingContinuation = undefined;
const aborted =
reason === undefined ? pending?.receipt.abort() : pending?.receipt.abort(reason);
if (
pending !== undefined &&
!aborted &&
pending.turnId !== undefined
) {
if (reason === undefined) {
this.loopService.cancel(pending.turnId);
} else {
this.loopService.cancel(pending.turnId, reason);
}
const cancellation = reason ?? abortError('Goal continuation cancelled');
const aborted = pending?.receipt.abort(cancellation);
if (pending !== undefined && !aborted && pending.turnId !== undefined) {
this.loopService.cancel(pending.turnId, cancellation);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* `interruptionReminder` domain (L4) — user-interruption reminder contract.
*
* Defines the Agent-scoped aspect that records a model-visible reminder after
* a user-cancelled turn. Bound at Agent scope.
*/

import { createDecorator } from '#/_base/di/instantiation';

export interface IAgentInterruptionReminderService {
readonly _serviceBrand: undefined;
}

export const IAgentInterruptionReminderService =
createDecorator<IAgentInterruptionReminderService>('agentInterruptionReminderService');
Loading
Loading