ThinkTool.tsx
1 import { z } from 'zod' 2 import React from 'react' 3 import { Text } from 'ink' 4 import { Tool } from '../../Tool.js' 5 import { DESCRIPTION, PROMPT } from './prompt.js' 6 import { getTheme } from '../../utils/theme.js' 7 import { MessageResponse } from '../../components/MessageResponse.js' 8 import { checkGate, logEvent } from '../../services/statsig.js' 9 import { USE_BEDROCK, USE_VERTEX } from '../../utils/model.js' 10 11 const thinkToolSchema = z.object({ 12 thought: z.string().describe('Your thoughts.'), 13 }) 14 15 export const ThinkTool = { 16 name: 'Think', 17 userFacingName: () => 'Think', 18 description: async () => DESCRIPTION, 19 inputSchema: thinkToolSchema, 20 isEnabled: async () => 21 Boolean(process.env.THINK_TOOL) && (await checkGate('tengu_think_tool')), 22 isReadOnly: () => true, 23 needsPermissions: () => false, 24 prompt: async () => PROMPT, 25 26 async *call(input, { messageId }) { 27 logEvent('tengu_thinking', { 28 messageId, 29 thoughtLength: input.thought.length.toString(), 30 method: 'tool', 31 provider: USE_BEDROCK ? 'bedrock' : USE_VERTEX ? 'vertex' : '1p', 32 }) 33 34 yield { 35 type: 'result', 36 resultForAssistant: 'Your thought has been logged.', 37 data: { thought: input.thought }, 38 } 39 }, 40 41 // This is never called -- it's special-cased in AssistantToolUseMessage 42 renderToolUseMessage(input) { 43 return input.thought 44 }, 45 46 renderToolUseRejectedMessage() { 47 return ( 48 <MessageResponse> 49 <Text color={getTheme().error}>Thought cancelled</Text> 50 </MessageResponse> 51 ) 52 }, 53 54 renderResultForAssistant: () => 'Your thought has been logged.', 55 } satisfies Tool<typeof thinkToolSchema>