mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-10 01:39:25 +00:00
fix(agent-core-v2): preserve compaction hook session
This commit is contained in:
parent
65ad6ab5ac
commit
5c076183ac
5 changed files with 31 additions and 9 deletions
|
|
@ -315,6 +315,7 @@ externalHooks --> config #34495E
|
|||
externalHooks --> bootstrap #34495E
|
||||
externalHooks --> plugin #34495E
|
||||
externalHooks --> contextMemory #34495E
|
||||
externalHooks --> session_context #34495E
|
||||
sessionExternalHooks --> session_lifecycle #34495E
|
||||
sessionExternalHooks --> agent_lifecycle #34495E
|
||||
sessionExternalHooks --> config #34495E
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 273 KiB After Width: | Height: | Size: 274 KiB |
|
|
@ -10,8 +10,9 @@
|
|||
* of its own). The requester-side `SubagentStart` / `SubagentStop` hooks are
|
||||
* translated by the Session-scope `SessionExternalHooksService`, which observes
|
||||
* the `agentLifecycle` run slots hosted on `IAgentLifecycleService`. Appends
|
||||
* UserPromptSubmit hook results
|
||||
* and Stop hook continuation prompts through `contextMemory`.
|
||||
* UserPromptSubmit hook results and Stop hook continuation prompts through
|
||||
* `contextMemory`, and passes the current session id from `sessionContext`
|
||||
* into hook runner payloads.
|
||||
*/
|
||||
|
||||
import { IInstantiationService } from '#/_base/di/instantiation';
|
||||
|
|
@ -42,6 +43,7 @@ import type { ToolDidExecuteContext, ToolWillExecuteContext } from '#/agent/tool
|
|||
import { IAgentToolExecutorService } from '#/agent/toolExecutor/toolExecutor';
|
||||
import { IAgentTurnService } from '#/agent/turn/turn';
|
||||
import { toKimiErrorPayload } from '#/errors';
|
||||
import { ISessionContext } from '#/session/sessionContext/sessionContext';
|
||||
|
||||
import { IAgentExternalHooksService } from './externalHooks';
|
||||
import { IExternalHooksRunnerService } from '#/app/externalHooksRunner/externalHooksRunner';
|
||||
|
|
@ -66,6 +68,7 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
@IAgentContextMemoryService private readonly context: IAgentContextMemoryService,
|
||||
@IEventBus private readonly eventBus: IEventBus,
|
||||
@IInstantiationService private readonly instantiation: IInstantiationService,
|
||||
@ISessionContext private readonly sessionContext: ISessionContext,
|
||||
) {
|
||||
super();
|
||||
this.registerListeners();
|
||||
|
|
@ -82,7 +85,12 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
// output), and throwing here would clobber that with a finalize-abort error.
|
||||
// The runner mirrors the legacy fire-and-forget behavior.
|
||||
try {
|
||||
void this.runner.fireAndForgetTrigger(event, { matcherValue, signal, inputData });
|
||||
void this.runner.fireAndForgetTrigger(event, {
|
||||
matcherValue,
|
||||
signal,
|
||||
sessionId: this.sessionContext.sessionId,
|
||||
inputData,
|
||||
});
|
||||
} catch {}
|
||||
}
|
||||
|
||||
|
|
@ -222,6 +230,7 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
const block = await this.runner.triggerBlock('PreToolUse', {
|
||||
matcherValue: ctx.toolCall.name,
|
||||
signal: ctx.signal,
|
||||
sessionId: this.sessionContext.sessionId,
|
||||
inputData: {
|
||||
toolName: ctx.toolCall.name,
|
||||
toolInput,
|
||||
|
|
@ -260,6 +269,7 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
const results = await this.runner.trigger('UserPromptSubmit', {
|
||||
matcherValue: input,
|
||||
signal,
|
||||
sessionId: this.sessionContext.sessionId,
|
||||
inputData: { prompt: input, isSteer: ctx.isSteer },
|
||||
});
|
||||
signal.throwIfAborted();
|
||||
|
|
@ -331,6 +341,7 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
|
||||
const block = await this.runner.triggerBlock('Stop', {
|
||||
signal: ctx.signal,
|
||||
sessionId: this.sessionContext.sessionId,
|
||||
inputData: { stopHookActive: false },
|
||||
});
|
||||
ctx.signal.throwIfAborted();
|
||||
|
|
@ -343,6 +354,7 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter
|
|||
await this.runner.trigger('PreCompact', {
|
||||
matcherValue: ctx.trigger,
|
||||
signal,
|
||||
sessionId: this.sessionContext.sessionId,
|
||||
inputData: {
|
||||
trigger: ctx.trigger,
|
||||
tokenCount: ctx.tokenCount,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { existsSync, mkdtempSync, readFileSync } from 'node:fs';
|
||||
import { existsSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'pathe';
|
||||
|
||||
|
|
@ -511,14 +511,14 @@ describe('FullCompaction', () => {
|
|||
const [pre, post] = readHookPayloads(hookLog);
|
||||
expect(pre).toMatchObject({
|
||||
hook_event_name: 'PreCompact',
|
||||
session_id: 'session-hooks',
|
||||
session_id: 'test-session',
|
||||
cwd: dir,
|
||||
trigger: 'auto',
|
||||
token_count: 39,
|
||||
});
|
||||
expect(post).toMatchObject({
|
||||
hook_event_name: 'PostCompact',
|
||||
session_id: 'session-hooks',
|
||||
session_id: 'test-session',
|
||||
cwd: dir,
|
||||
trigger: 'auto',
|
||||
estimated_token_count: ctx.contextData().tokenCount,
|
||||
|
|
@ -2545,6 +2545,10 @@ function messageText(message: Message | undefined): string {
|
|||
}
|
||||
|
||||
function hookPayloadLoggerCommand(logPath: string): string {
|
||||
// Write the hook script to a file and run it with node, instead of
|
||||
// `node -e <json>`; cmd.exe on Windows mangles the escaped quotes in the
|
||||
// inline form and corrupts the script before it can run.
|
||||
const scriptPath = `${logPath}.cjs`;
|
||||
const script = [
|
||||
"const fs = require('node:fs');",
|
||||
"let input = '';",
|
||||
|
|
@ -2553,7 +2557,8 @@ function hookPayloadLoggerCommand(logPath: string): string {
|
|||
` fs.appendFileSync(${JSON.stringify(logPath)}, JSON.stringify(JSON.parse(input)) + '\\n');`,
|
||||
'});',
|
||||
].join('');
|
||||
return `node -e ${JSON.stringify(script)}`;
|
||||
writeFileSync(scriptPath, script);
|
||||
return `${process.execPath} ${scriptPath}`;
|
||||
}
|
||||
|
||||
function readHookPayloads(logPath: string): Array<Record<string, unknown>> {
|
||||
|
|
|
|||
|
|
@ -576,7 +576,11 @@ function resolveExternalHooksRunner(
|
|||
function isRunnerLike(
|
||||
value: Pick<IExternalHooksRunnerService, 'trigger' | 'triggerBlock' | 'fireAndForgetTrigger'>,
|
||||
): value is IExternalHooksRunnerService {
|
||||
return '_serviceBrand' in value;
|
||||
return (
|
||||
typeof value.trigger === 'function' &&
|
||||
typeof value.triggerBlock === 'function' &&
|
||||
typeof value.fireAndForgetTrigger === 'function'
|
||||
);
|
||||
}
|
||||
|
||||
const noopHookRunner: IExternalHooksRunnerService = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue