feat(scheduler): add types needed for event driven scheduler (#16641)

This commit is contained in:
Abhi
2026-01-14 17:22:44 -05:00
committed by GitHub
parent 7e6817da5b
commit 6021e4c3ba
6 changed files with 98 additions and 22 deletions
+56 -1
View File
@@ -5,6 +5,11 @@
*/
import { type FunctionCall } from '@google/genai';
import type {
ToolConfirmationOutcome,
ToolConfirmationPayload,
} from '../tools/tools.js';
import type { ToolCall } from '../scheduler/types.js';
export enum MessageBusType {
TOOL_CONFIRMATION_REQUEST = 'tool-confirmation-request',
@@ -16,6 +21,12 @@ export enum MessageBusType {
HOOK_EXECUTION_REQUEST = 'hook-execution-request',
HOOK_EXECUTION_RESPONSE = 'hook-execution-response',
HOOK_POLICY_DECISION = 'hook-policy-decision',
TOOL_CALLS_UPDATE = 'tool-calls-update',
}
export interface ToolCallsUpdateMessage {
type: MessageBusType.TOOL_CALLS_UPDATE;
toolCalls: ToolCall[];
}
export interface ToolConfirmationRequest {
@@ -23,12 +34,26 @@ export interface ToolConfirmationRequest {
toolCall: FunctionCall;
correlationId: string;
serverName?: string;
/**
* Optional rich details for the confirmation UI (diffs, counts, etc.)
*/
details?: SerializableConfirmationDetails;
}
export interface ToolConfirmationResponse {
type: MessageBusType.TOOL_CONFIRMATION_RESPONSE;
correlationId: string;
confirmed: boolean;
/**
* The specific outcome selected by the user.
*
* TODO: Make required after migration.
*/
outcome?: ToolConfirmationOutcome;
/**
* Optional payload (e.g., modified content for 'modify_with_editor').
*/
payload?: ToolConfirmationPayload;
/**
* When true, indicates that policy decision was ASK_USER and the tool should
* show its legacy confirmation UI instead of auto-proceeding.
@@ -36,6 +61,35 @@ export interface ToolConfirmationResponse {
requiresUserConfirmation?: boolean;
}
/**
* Data-only versions of ToolCallConfirmationDetails for bus transmission.
*/
export type SerializableConfirmationDetails =
| { type: 'info'; title: string; prompt: string; urls?: string[] }
| {
type: 'edit';
title: string;
fileName: string;
filePath: string;
fileDiff: string;
originalContent: string | null;
newContent: string;
}
| {
type: 'exec';
title: string;
command: string;
rootCommand: string;
rootCommands: string[];
}
| {
type: 'mcp';
title: string;
serverName: string;
toolName: string;
toolDisplayName: string;
};
export interface UpdatePolicy {
type: MessageBusType.UPDATE_POLICY;
toolName: string;
@@ -94,4 +148,5 @@ export type Message =
| UpdatePolicy
| HookExecutionRequest
| HookExecutionResponse
| HookPolicyDecision;
| HookPolicyDecision
| ToolCallsUpdateMessage;
@@ -547,9 +547,9 @@ describe('CoreToolScheduler', () => {
)) as WaitingToolCall;
// Cancel the first tool via its confirmation handler
await awaitingCall.confirmationDetails.onConfirm(
ToolConfirmationOutcome.Cancel,
);
const confirmationDetails =
awaitingCall.confirmationDetails as ToolCallConfirmationDetails;
await confirmationDetails.onConfirm(ToolConfirmationOutcome.Cancel);
abortController.abort(); // User cancelling often involves an abort signal
await vi.waitFor(() => {
@@ -749,7 +749,7 @@ describe('CoreToolScheduler with payload', () => {
if (confirmationDetails) {
const payload: ToolConfirmationPayload = { newContent: 'final version' };
await confirmationDetails.onConfirm(
await (confirmationDetails as ToolCallConfirmationDetails).onConfirm(
ToolConfirmationOutcome.ProceedOnce,
payload,
);
@@ -762,9 +762,9 @@ describe('CoreToolScheduler with payload', () => {
)) as WaitingToolCall;
// Now confirm for real to execute.
await updatedAwaitingCall.confirmationDetails.onConfirm(
ToolConfirmationOutcome.ProceedOnce,
);
await (
updatedAwaitingCall.confirmationDetails as ToolCallConfirmationDetails
).onConfirm(ToolConfirmationOutcome.ProceedOnce);
// Wait for the tool execution to complete
await vi.waitFor(() => {
@@ -897,7 +897,9 @@ describe('CoreToolScheduler edit cancellation', () => {
// Cancel the edit
const confirmationDetails = awaitingCall.confirmationDetails;
if (confirmationDetails) {
await confirmationDetails.onConfirm(ToolConfirmationOutcome.Cancel);
await (confirmationDetails as ToolCallConfirmationDetails).onConfirm(
ToolConfirmationOutcome.Cancel,
);
}
expect(onAllToolCallsComplete).toHaveBeenCalled();
@@ -1447,14 +1449,14 @@ describe('CoreToolScheduler request queueing', () => {
toolCalls.forEach((call) => {
if (call.status === 'awaiting_approval') {
const waitingCall = call;
if (waitingCall.confirmationDetails?.onConfirm) {
const details =
waitingCall.confirmationDetails as ToolCallConfirmationDetails;
if (details?.onConfirm) {
const originalHandler = pendingConfirmations.find(
(h) => h === waitingCall.confirmationDetails.onConfirm,
(h) => h === details.onConfirm,
);
if (!originalHandler) {
pendingConfirmations.push(
waitingCall.confirmationDetails.onConfirm,
);
pendingConfirmations.push(details.onConfirm);
}
}
}
+13 -1
View File
@@ -14,6 +14,7 @@ import type {
} from '../tools/tools.js';
import type { AnsiOutput } from '../utils/terminalSerializer.js';
import type { ToolErrorType } from '../tools/tool-error.js';
import type { SerializableConfirmationDetails } from '../confirmation-bus/types.js';
export interface ToolCallRequestInfo {
callId: string;
@@ -98,7 +99,18 @@ export type WaitingToolCall = {
request: ToolCallRequestInfo;
tool: AnyDeclarativeTool;
invocation: AnyToolInvocation;
confirmationDetails: ToolCallConfirmationDetails;
/**
* Supports both legacy (with callbacks) and new (serializable) details.
* New code should treat this as SerializableConfirmationDetails.
*
* TODO: Remove ToolCallConfirmationDetails and collapse to just
* SerializableConfirmationDetails after migration.
*/
confirmationDetails:
| ToolCallConfirmationDetails
| SerializableConfirmationDetails;
// TODO: Make required after migration.
correlationId?: string;
startTime?: number;
outcome?: ToolConfirmationOutcome;
};