mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-10-13 08:22:22 +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 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 & {
|
export type GitBookIntegrationTool = AIToolDefinition & {
|
||||||
/**
|
/**
|
||||||
* Confirmation action to be displayed to the user before executing the tool.
|
* 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?: {
|
confirmation?:
|
||||||
icon?: IconName;
|
| GitBookIntegrationToolConfirmation
|
||||||
label: string;
|
| ((input: object) => GitBookIntegrationToolConfirmation);
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback when the tool is executed.
|
* Callback when the tool is executed.
|
||||||
|
|||||||
@@ -1,17 +1,32 @@
|
|||||||
import type { AIToolCallResult, AIToolDefinition } from '@gitbook/api';
|
import type { AIToolCallResult, AIToolDefinition } from '@gitbook/api';
|
||||||
import type { IconName } from '@gitbook/icons';
|
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.
|
* Custom tool definition to be passed to the AI assistant.
|
||||||
*/
|
*/
|
||||||
export type GitBookToolDefinition = AIToolDefinition & {
|
export type GitBookToolDefinition = AIToolDefinition & {
|
||||||
/**
|
/**
|
||||||
* Confirmation action to be displayed to the user before executing the tool.
|
* 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?: {
|
confirmation?: GitBookToolConfirmation | ((input: object) => GitBookToolConfirmation);
|
||||||
icon?: IconName;
|
|
||||||
label: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback when the tool is executed.
|
* Callback when the tool is executed.
|
||||||
|
|||||||
@@ -16,6 +16,13 @@ export const ConfirmControlDef = createAIControl({
|
|||||||
description:
|
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.',
|
'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({
|
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
|
icon: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
@@ -29,10 +36,13 @@ export const ConfirmControlDef = createAIControl({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function ConfirmControl(props: GetAIControlProps<typeof ConfirmControlDef>) {
|
function ConfirmControl(props: GetAIControlProps<typeof ConfirmControlDef>) {
|
||||||
const { label, icon, onSubmit } = props;
|
const { label, icon, context, onSubmit } = props;
|
||||||
const language = useLanguage();
|
const language = useLanguage();
|
||||||
return (
|
return (
|
||||||
<AIToolContainer className="flex w-full flex-col gap-2">
|
<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
|
<Button
|
||||||
data-testid="ai-chat-tool-confirm-cancel"
|
data-testid="ai-chat-tool-confirm-cancel"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
@@ -434,6 +434,18 @@ export function AIChatProvider(props: {
|
|||||||
|
|
||||||
const confirmation = 'confirmation' in toolDef && toolDef.confirmation;
|
const confirmation = 'confirmation' in toolDef && toolDef.confirmation;
|
||||||
if (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) => ({
|
globalState.setState((state) => ({
|
||||||
...state,
|
...state,
|
||||||
control: ConfirmControlDef.createControl({
|
control: ConfirmControlDef.createControl({
|
||||||
@@ -442,8 +454,9 @@ export function AIChatProvider(props: {
|
|||||||
toolCallId: event.toolCallId,
|
toolCallId: event.toolCallId,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
label: confirmation.label,
|
label: resolvedConfirmation.label,
|
||||||
icon: confirmation.icon,
|
icon: resolvedConfirmation.icon,
|
||||||
|
context: supportingContext,
|
||||||
},
|
},
|
||||||
language,
|
language,
|
||||||
send: async (result) => {
|
send: async (result) => {
|
||||||
@@ -462,7 +475,7 @@ export function AIChatProvider(props: {
|
|||||||
text: tString(
|
text: tString(
|
||||||
language,
|
language,
|
||||||
'tool_call_skipped',
|
'tool_call_skipped',
|
||||||
confirmation.label
|
resolvedConfirmation.label
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user