Add missing sessionStart hook properties (#311109)

This commit is contained in:
Paul
2026-04-22 22:46:24 +00:00
committed by GitHub
parent 17f555f7bd
commit d4da5f2a62
3 changed files with 26 additions and 5 deletions
@@ -196,6 +196,11 @@ export abstract class ToolCallingLoop<TOptions extends IToolCallingLoopOptions =
return this.options.conversation.getLatestTurn();
}
protected get agentName(): string | undefined {
return (this.options.request as { subAgentName?: string }).subAgentName
?? (this.options.request as { participant?: string }).participant;
}
constructor(
protected readonly options: TOptions,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@@ -685,6 +690,8 @@ export abstract class ToolCallingLoop<TOptions extends IToolCallingLoopOptions =
if (isFirstTurn) {
const startHookResult = await this.executeSessionStartHook({
source: 'new',
model: this.options.request.model?.id ?? 'unknown',
agent_type: this.agentName,
}, sessionId, outputStream, token);
if (startHookResult.additionalContext) {
this.additionalHookContext = startHookResult.additionalContext;
@@ -701,9 +708,7 @@ export abstract class ToolCallingLoop<TOptions extends IToolCallingLoopOptions =
}
public async run(outputStream: ChatResponseStream | undefined, token: CancellationToken): Promise<IToolCallLoopResult> {
const agentName = (this.options.request as { subAgentName?: string }).subAgentName
?? (this.options.request as { participant?: string }).participant
?? 'GitHub Copilot Chat';
const agentName = this.agentName ?? 'GitHub Copilot Chat';
// Extract custom mode name for debug logging (kept separate from agentName to avoid metric cardinality)
const modeInstructions = (this.options.request as { modeInstructions2?: { name?: string; isBuiltin?: boolean } }).modeInstructions2;
@@ -197,7 +197,10 @@ describe('ToolCallingLoop SessionStart hook', () => {
describe('SessionStart hook execution conditions', () => {
it('should execute SessionStart hook on the first turn of regular sessions', async () => {
const conversation = createTestConversation(1); // First turn
const request = createMockChatRequest();
const request = createMockChatRequest({
model: { id: 'test-model-id' } as ChatRequest['model'],
participant: 'test-agent',
} as unknown as Partial<ChatRequest>);
const loop = instantiationService.createInstance(
TestToolCallingLoop,
@@ -216,7 +219,12 @@ describe('ToolCallingLoop SessionStart hook', () => {
const sessionStartCalls = mockChatHookService.getCallsForHook('SessionStart');
expect(sessionStartCalls).toHaveLength(1);
expect((sessionStartCalls[0].input as SessionStartHookInput).source).toBe('new');
const input = sessionStartCalls[0].input as SessionStartHookInput;
expect(input).toMatchObject({
source: 'new',
model: 'test-model-id',
agent_type: 'test-agent',
});
});
it('should NOT execute SessionStart hook on subsequent turns', async () => {
@@ -172,6 +172,14 @@ export interface SessionStartHookInput {
* The source of the session start. Always "new".
*/
readonly source: 'new';
/**
* The model identifier (e.g. "claude-sonnet-4-6").
*/
readonly model: string;
/**
* The agent or mode name, if applicable.
*/
readonly agent_type?: string;
}
/**