mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-12 05:48:57 +00:00
Add supporting context to AI tool confirmation dialogs (#4422)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@gitbook/browser-types": patch
|
||||
"@gitbook/embed": patch
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Add an optional `context` property (string, up to 512 characters) to the `confirmation` of custom AI tools, shown above the confirmation dialog to help the user understand what they are approving or rejecting. The `confirmation` can now also be a function that receives the AI-provided input and returns the confirmation, so the context can be derived dynamically from the arguments the tool is about to run with. Available both to integrations (`GitBookIntegrationTool`) and to embed consumers (`GitBookToolDefinition`).
|
||||
@@ -5,14 +5,28 @@ export type GitBookIntegrationEvent = 'load' | 'unload';
|
||||
|
||||
export type GitBookIntegrationEventCallback = (...args: any[]) => void;
|
||||
|
||||
export type GitBookIntegrationToolConfirmation = {
|
||||
icon?: IconName;
|
||||
label: string;
|
||||
|
||||
/**
|
||||
* Supporting context displayed to the user above the confirmation dialog,
|
||||
* to help them understand what they are approving or rejecting.
|
||||
* Limited to 512 characters.
|
||||
*/
|
||||
context?: string;
|
||||
};
|
||||
|
||||
export type GitBookIntegrationTool = AIToolDefinition & {
|
||||
/**
|
||||
* Confirmation action to be displayed to the user before executing the tool.
|
||||
* Provide a static object, or a function that receives the input provided by
|
||||
* the AI assistant and returns the confirmation — useful to display dynamic
|
||||
* context based on the arguments the tool is about to be executed with.
|
||||
*/
|
||||
confirmation?: {
|
||||
icon?: IconName;
|
||||
label: string;
|
||||
};
|
||||
confirmation?:
|
||||
| GitBookIntegrationToolConfirmation
|
||||
| ((input: object) => GitBookIntegrationToolConfirmation);
|
||||
|
||||
/**
|
||||
* Callback when the tool is executed.
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
import type { AIToolCallResult, AIToolDefinition } from '@gitbook/api';
|
||||
import type { IconName } from '@gitbook/icons';
|
||||
|
||||
/**
|
||||
* Confirmation action to be displayed to the user before executing a tool.
|
||||
*/
|
||||
export type GitBookToolConfirmation = {
|
||||
icon?: IconName;
|
||||
label: string;
|
||||
|
||||
/**
|
||||
* Supporting context displayed to the user above the confirmation dialog,
|
||||
* to help them understand what they are approving or rejecting.
|
||||
* Limited to 512 characters.
|
||||
*/
|
||||
context?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom tool definition to be passed to the AI assistant.
|
||||
*/
|
||||
export type GitBookToolDefinition = AIToolDefinition & {
|
||||
/**
|
||||
* Confirmation action to be displayed to the user before executing the tool.
|
||||
* Provide a static object, or a function that receives the input provided by
|
||||
* the AI assistant and returns the confirmation — useful to display dynamic
|
||||
* context based on the arguments the tool is about to be executed with.
|
||||
*/
|
||||
confirmation?: {
|
||||
icon?: IconName;
|
||||
label: string;
|
||||
};
|
||||
confirmation?: GitBookToolConfirmation | ((input: object) => GitBookToolConfirmation);
|
||||
|
||||
/**
|
||||
* Callback when the tool is executed.
|
||||
|
||||
@@ -16,6 +16,13 @@ export const ConfirmControlDef = createAIControl({
|
||||
description:
|
||||
'Display a confirmation prompt to the user (Confirm / Cancel) to approve or abort a pending action. Use this when an operation is irreversible, sensitive, or should only proceed with explicit user consent. Returns either a `confirmed` or `cancelled` result based on the user’s click.',
|
||||
inputSchema: z.object({
|
||||
context: z
|
||||
.string()
|
||||
.max(512)
|
||||
.optional()
|
||||
.describe(
|
||||
'Supporting context shown above the prompt to help the user understand what they are approving or rejecting.'
|
||||
),
|
||||
icon: z
|
||||
.string()
|
||||
.optional()
|
||||
@@ -29,10 +36,13 @@ export const ConfirmControlDef = createAIControl({
|
||||
});
|
||||
|
||||
function ConfirmControl(props: GetAIControlProps<typeof ConfirmControlDef>) {
|
||||
const { label, icon, onSubmit } = props;
|
||||
const { label, icon, context, onSubmit } = props;
|
||||
const language = useLanguage();
|
||||
return (
|
||||
<AIToolContainer className="flex w-full flex-col gap-2">
|
||||
{context ? (
|
||||
<p className="whitespace-pre-line px-2 pt-1 text-sm text-tint">{context}</p>
|
||||
) : null}
|
||||
<Button
|
||||
data-testid="ai-chat-tool-confirm-cancel"
|
||||
onClick={() => {
|
||||
|
||||
@@ -434,6 +434,18 @@ export function AIChatProvider(props: {
|
||||
|
||||
const confirmation = 'confirmation' in toolDef && toolDef.confirmation;
|
||||
if (confirmation) {
|
||||
// The confirmation can be a static object or a function that
|
||||
// derives it from the AI-provided input (e.g. dynamic context).
|
||||
// The function call is awaited because, for embed-registered
|
||||
// tools, it arrives as an async proxy over the postMessage channel.
|
||||
const resolvedConfirmation =
|
||||
typeof confirmation === 'function'
|
||||
? await confirmation(event.toolCall.input)
|
||||
: confirmation;
|
||||
const supportingContext =
|
||||
typeof resolvedConfirmation.context === 'string'
|
||||
? resolvedConfirmation.context.slice(0, 512)
|
||||
: undefined;
|
||||
globalState.setState((state) => ({
|
||||
...state,
|
||||
control: ConfirmControlDef.createControl({
|
||||
@@ -442,8 +454,9 @@ export function AIChatProvider(props: {
|
||||
toolCallId: event.toolCallId,
|
||||
},
|
||||
input: {
|
||||
label: confirmation.label,
|
||||
icon: confirmation.icon,
|
||||
label: resolvedConfirmation.label,
|
||||
icon: resolvedConfirmation.icon,
|
||||
context: supportingContext,
|
||||
},
|
||||
language,
|
||||
send: async (result) => {
|
||||
@@ -462,7 +475,7 @@ export function AIChatProvider(props: {
|
||||
text: tString(
|
||||
language,
|
||||
'tool_call_skipped',
|
||||
confirmation.label
|
||||
resolvedConfirmation.label
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user