StickerRequestTool.tsx
1 import { z } from 'zod' 2 import React from 'react' 3 import { Text } from 'ink' 4 import { Tool, ToolUseContext } from '../../Tool.js' 5 import { DESCRIPTION, PROMPT } from './prompt.js' 6 import { 7 StickerRequestForm, 8 FormData, 9 } from '../../components/StickerRequestForm.js' 10 import { checkGate, logEvent } from '../../services/statsig.js' 11 import { getTheme } from '../../utils/theme.js' 12 13 const stickerRequestSchema = z.object({ 14 trigger: z.string(), 15 }) 16 17 export const StickerRequestTool: Tool = { 18 name: 'StickerRequest', 19 userFacingName: () => 'Stickers', 20 description: async () => DESCRIPTION, 21 inputSchema: stickerRequestSchema, 22 isEnabled: async () => { 23 const enabled = await checkGate('tengu_sticker_easter_egg') 24 return enabled 25 }, 26 isReadOnly: () => false, 27 needsPermissions: () => false, 28 prompt: async () => PROMPT, 29 30 async *call(_, context: ToolUseContext) { 31 // Log form entry event 32 logEvent('sticker_request_form_opened', {}) 33 34 // Create a promise to track form completion and status 35 let resolveForm: (success: boolean) => void 36 const formComplete = new Promise<boolean>(resolve => { 37 resolveForm = success => resolve(success) 38 }) 39 40 context.setToolJSX?.({ 41 jsx: ( 42 <StickerRequestForm 43 onSubmit={(formData: FormData) => { 44 // Log successful completion with form data 45 logEvent('sticker_request_form_completed', { 46 has_address: Boolean(formData.address1).toString(), 47 has_optional_address: Boolean(formData.address2).toString(), 48 }) 49 resolveForm(true) 50 context.setToolJSX?.(null) // Clear the JSX 51 }} 52 onClose={() => { 53 // Log form cancellation 54 logEvent('sticker_request_form_cancelled', {}) 55 resolveForm(false) 56 context.setToolJSX?.(null) // Clear the JSX 57 }} 58 /> 59 ), 60 shouldHidePromptInput: true, 61 }) 62 63 // Wait for form completion and get status 64 const success = await formComplete 65 66 if (!success) { 67 context.abortController.abort() 68 throw new Error('Sticker request cancelled') 69 } 70 71 // Return success message 72 yield { 73 type: 'result', 74 resultForAssistant: 75 'Sticker request completed! Please tell the user that they will receive stickers in the mail if they have submitted the form!', 76 data: { success }, 77 } 78 }, 79 80 renderToolUseMessage(_input) { 81 return '' 82 }, 83 84 renderToolUseRejectedMessage: _input => ( 85 <Text> 86 ⎿ 87 <Text color={getTheme().error}>No (Sticker request cancelled)</Text> 88 </Text> 89 ), 90 91 renderResultForAssistant: (content: string) => content, 92 }