/ src / tools / MemoryWriteTool / MemoryWriteTool.tsx
MemoryWriteTool.tsx
 1  import { mkdirSync, writeFileSync } from 'fs'
 2  import { Box, Text } from 'ink'
 3  import { dirname, join } from 'path'
 4  import * as React from 'react'
 5  import { z } from 'zod'
 6  import { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage.js'
 7  import { Tool } from '../../Tool.js'
 8  import { MEMORY_DIR } from '../../utils/env.js'
 9  import { DESCRIPTION, PROMPT } from './prompt.js'
10  
11  const inputSchema = z.strictObject({
12    file_path: z.string().describe('Path to the memory file to write'),
13    content: z.string().describe('Content to write to the file'),
14  })
15  
16  export const MemoryWriteTool = {
17    name: 'MemoryWrite',
18    async description() {
19      return DESCRIPTION
20    },
21    async prompt() {
22      return PROMPT
23    },
24    inputSchema,
25    userFacingName() {
26      return 'Write Memory'
27    },
28    async isEnabled() {
29      // TODO: Use a statsig gate
30      // TODO: Figure out how to do that without regressing app startup perf
31      return false
32    },
33    isReadOnly() {
34      return false
35    },
36    needsPermissions() {
37      return false
38    },
39    renderResultForAssistant(content) {
40      return content
41    },
42    renderToolUseMessage(input) {
43      return Object.entries(input)
44        .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
45        .join(', ')
46    },
47    renderToolUseRejectedMessage() {
48      return <FallbackToolUseRejectedMessage />
49    },
50    renderToolResultMessage() {
51      return (
52        <Box justifyContent="space-between" overflowX="hidden" width="100%">
53          <Box flexDirection="row">
54            <Text>{'  '}⎿ Updated memory</Text>
55          </Box>
56        </Box>
57      )
58    },
59    async validateInput({ file_path }) {
60      const fullPath = join(MEMORY_DIR, file_path)
61      if (!fullPath.startsWith(MEMORY_DIR)) {
62        return { result: false, message: 'Invalid memory file path' }
63      }
64      return { result: true }
65    },
66    async *call({ file_path, content }) {
67      const fullPath = join(MEMORY_DIR, file_path)
68      mkdirSync(dirname(fullPath), { recursive: true })
69      writeFileSync(fullPath, content, 'utf-8')
70      yield {
71        type: 'result',
72        data: 'Saved',
73        resultForAssistant: 'Saved',
74      }
75    },
76  } satisfies Tool<typeof inputSchema, string>