mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-10 01:39:25 +00:00
fix: route external hook context writes through context ops
This commit is contained in:
parent
c1debee32b
commit
7d44096be3
2 changed files with 14 additions and 26 deletions
|
|
@ -6,7 +6,7 @@
|
|||
* (`toolExecutor`, `permissionGate`, `prompt`, `turn`, `loop`, `fullCompaction`, and
|
||||
* `task`) and translates those minimal contexts into the configured external
|
||||
* HookEngine events. Appends UserPromptSubmit hook results and Stop hook
|
||||
* continuation prompts through `contextMemory`. The `SubagentStart` /
|
||||
* continuation prompts through `contextOps`. The `SubagentStart` /
|
||||
* `SubagentStop` pair is the one
|
||||
* exception: the `agentLifecycle` tool wrapper has no hook service of its own,
|
||||
* so `mirrorAgentRun` invokes `runAgentTaskStart` / `notifyAgentTaskStop` on
|
||||
|
|
@ -19,7 +19,8 @@ import { LifecycleScope, registerScopedService } from '#/_base/di/scope';
|
|||
import { isUserCancellation } from '#/_base/utils/abort';
|
||||
import { isPlainRecord } from '#/_base/utils/canonical-args';
|
||||
import { IAgentTaskService, type AgentTaskNotificationContext } from '#/agent/task';
|
||||
import { IAgentContextMemoryService, USER_PROMPT_ORIGIN } from '#/agent/contextMemory';
|
||||
import { USER_PROMPT_ORIGIN } from '#/agent/contextMemory';
|
||||
import { IAgentContextOpsService } from '#/agent/contextOps';
|
||||
import {
|
||||
IAgentFullCompactionService,
|
||||
type FullCompactionDidCompactContext,
|
||||
|
|
@ -87,7 +88,7 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
|
||||
constructor(
|
||||
private readonly options: ExternalHooksServiceOptions = {},
|
||||
@IAgentContextMemoryService private readonly context: IAgentContextMemoryService,
|
||||
@IAgentContextOpsService private readonly contextOps: IAgentContextOpsService,
|
||||
@IAgentRecordService private readonly record: IAgentRecordService,
|
||||
@IInstantiationService private readonly instantiation: IInstantiationService,
|
||||
@IConfigService private readonly config: IConfigService,
|
||||
|
|
@ -224,12 +225,12 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
const reason = await this.runStop(ctx);
|
||||
if (reason !== undefined) {
|
||||
this.stopHookContinuationUsed = true;
|
||||
this.context.splice(this.context.get().length, 0, [{
|
||||
this.contextOps.append({
|
||||
role: 'user',
|
||||
content: [{ type: 'text', text: reason }],
|
||||
toolCalls: [],
|
||||
origin: { kind: 'system_trigger', name: 'stop_hook' },
|
||||
}]);
|
||||
});
|
||||
ctx.continue = true;
|
||||
return;
|
||||
}
|
||||
|
|
@ -321,12 +322,12 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
|
||||
const block = renderUserPromptHookBlockResult(results);
|
||||
if (block !== undefined) {
|
||||
this.context.splice(this.context.get().length, 0, [{
|
||||
this.contextOps.append({
|
||||
role: 'assistant',
|
||||
content: [{ type: 'text', text: block.text }],
|
||||
toolCalls: [],
|
||||
origin: { kind: 'hook_result', event: block.event, blocked: true },
|
||||
}]);
|
||||
});
|
||||
this.record.signal({
|
||||
type: 'hook.result',
|
||||
hookEvent: block.event,
|
||||
|
|
@ -338,12 +339,12 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
|
||||
const append = renderUserPromptHookResult(results);
|
||||
if (append !== undefined) {
|
||||
this.context.splice(this.context.get().length, 0, [{
|
||||
this.contextOps.append({
|
||||
role: 'user',
|
||||
content: [{ type: 'text', text: append.text }],
|
||||
toolCalls: [],
|
||||
origin: { kind: 'hook_result', event: append.event },
|
||||
}]);
|
||||
});
|
||||
this.record.signal({
|
||||
type: 'hook.result',
|
||||
hookEvent: append.event,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import {
|
|||
} from '#/_base/di/test';
|
||||
import { Event } from '#/_base/event';
|
||||
import { emptyUsage } from '#/app/llmProtocol/kosong';
|
||||
import { IAgentContextMemoryService, type ContextMessage } from '#/agent/contextMemory';
|
||||
import { IAgentContextMemoryService } from '#/agent/contextMemory';
|
||||
import { AgentContextOpsService, IAgentContextOpsService } from '#/agent/contextOps';
|
||||
import { IAgentTaskService } from '#/agent/task';
|
||||
import {
|
||||
AgentExternalHooksService,
|
||||
|
|
@ -33,7 +34,7 @@ import { IPluginService } from '#/app/plugin';
|
|||
import { createHooks } from '#/hooks';
|
||||
|
||||
import { stubBootstrap } from '../bootstrap/stubs';
|
||||
import { stubRecord } from '../contextMemory/stubs';
|
||||
import { stubContextMemory, stubRecord } from '../contextMemory/stubs';
|
||||
import { stubLoopWithHooks, stubToolExecutor, stubTurnWithHooks } from '../turn/stubs';
|
||||
|
||||
function nodeCommand(source: string): string {
|
||||
|
|
@ -71,21 +72,6 @@ function makeAfterStep(signal: AbortSignal): TurnAfterStepContext {
|
|||
};
|
||||
}
|
||||
|
||||
function stubContextMemory(): IAgentContextMemoryService & {
|
||||
readonly messages: readonly ContextMessage[];
|
||||
} {
|
||||
const messages: ContextMessage[] = [];
|
||||
return {
|
||||
_serviceBrand: undefined,
|
||||
get: () => [...messages],
|
||||
splice: (start, deleteCount, inserted) => {
|
||||
messages.splice(start, deleteCount, ...inserted);
|
||||
},
|
||||
hooks: createHooks(['onSpliced']) as IAgentContextMemoryService['hooks'],
|
||||
messages,
|
||||
};
|
||||
}
|
||||
|
||||
describe('HookEngine integration', () => {
|
||||
it('blocks a dangerous Bash command and allows a safe one via a PreToolUse script hook', async () => {
|
||||
const engine = new HookEngine([
|
||||
|
|
@ -159,6 +145,7 @@ describe('HookEngine integration', () => {
|
|||
reg.definePartialInstance(IConfigService, {});
|
||||
reg.definePartialInstance(IPluginService, {});
|
||||
reg.defineInstance(IAgentContextMemoryService, context);
|
||||
reg.define(IAgentContextOpsService, AgentContextOpsService);
|
||||
reg.defineInstance(IAgentRecordService, stubRecord());
|
||||
reg.defineInstance(IAgentLoopService, loop);
|
||||
reg.definePartialInstance(IAgentPromptService, {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue