feat(hooks): Support explicit stop and block execution control in model hooks (#15947)

Co-authored-by: matt korwel <matt.korwel@gmail.com>
This commit is contained in:
Sandy Tao
2026-01-09 13:36:27 +08:00
committed by GitHub
parent 18dd399cb5
commit e1e3efc9d0
7 changed files with 517 additions and 65 deletions
+4 -32
View File
@@ -319,45 +319,17 @@ describe('Hook Output Classes', () => {
expect(output.getModifiedResponse()).toBeUndefined();
});
it('getModifiedResponse should return a synthetic stop response if shouldStopExecution is true', () => {
it('getModifiedResponse should return undefined if shouldStopExecution is true', () => {
const output = new AfterModelHookOutput({
continue: false,
stopReason: 'stopped by hook',
});
const expectedResponse: LLMResponse = {
candidates: [
{
content: {
role: 'model',
parts: ['stopped by hook'],
},
finishReason: 'STOP',
},
],
};
expect(output.getModifiedResponse()).toEqual(expectedResponse);
expect(defaultHookTranslator.fromHookLLMResponse).toHaveBeenCalledWith(
expectedResponse,
);
expect(output.getModifiedResponse()).toBeUndefined();
});
it('getModifiedResponse should return a synthetic stop response with default reason if shouldStopExecution is true and no stopReason', () => {
it('getModifiedResponse should return undefined if shouldStopExecution is true and no stopReason', () => {
const output = new AfterModelHookOutput({ continue: false });
const expectedResponse: LLMResponse = {
candidates: [
{
content: {
role: 'model',
parts: ['No reason provided'],
},
finishReason: 'STOP',
},
],
};
expect(output.getModifiedResponse()).toEqual(expectedResponse);
expect(defaultHookTranslator.fromHookLLMResponse).toHaveBeenCalledWith(
expectedResponse,
);
expect(output.getModifiedResponse()).toBeUndefined();
});
});
});
-16
View File
@@ -353,22 +353,6 @@ export class AfterModelHookOutput extends DefaultHookOutput {
}
}
// If hook wants to stop execution, create a synthetic stop response
if (this.shouldStopExecution()) {
const stopResponse: LLMResponse = {
candidates: [
{
content: {
role: 'model',
parts: [this.getEffectiveReason() || 'Execution stopped by hook'],
},
finishReason: 'STOP',
},
],
};
return defaultHookTranslator.fromHookLLMResponse(stopResponse);
}
return undefined;
}
}