├── .env.example ├── .gitignore ├── LICENSE ├── README.md ├── agent.ts ├── package.json ├── pnpm-lock.yaml └── tools ├── math.ts ├── prices.ts └── safe.ts /.env.example: -------------------------------------------------------------------------------- 1 | AGENT_PRIVATE_KEY="0x..." 2 | AGENT_ADDRESS="0x..." 3 | 4 | # Optional: 5 | OPENAI_API_KEY="sk-..." 6 | LANGCHAIN_API_KEY="lsv2_..." 7 | LANGCHAIN_CALLBACKS_BACKGROUND="true" 8 | LANGCHAIN_TRACING_V2="true" 9 | LANGCHAIN_PROJECT="Safe Agent Tutorial" 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Safe Dev Space 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to build an AI agent with Safe and LangChain 2 | 3 | This example repo shows how to create an AI agent with capabilities to interact with your Safe. Please read [Create an AI agent that can interact with your Safe](https://docs.safe.global/home/ai-agent-setup) to see how this app was created. 4 | 5 | ## What you’ll need 6 | 7 | **Prerequisite knowledge:** You will need some basic familiarity with the [LangChain framework](https://www.langchain.com/langchain) and [Node.js](https://nodejs.org/en). 8 | 9 | Before progressing with the tutorial, please make sure you have: 10 | 11 | - Installed and opened `ollama`. This tutorial will run [`mistral-nemo`](https://ollama.com/library/mistral-nemo) (minimum 16GB RAM & 8GB disk space required), but feel free to explore [other models](https://ollama.com/library); 12 | - Set up a wallet for your agent with some Sepolia test funds to pay for the transactions, for example with [Metamask](https://metamask.io/); 13 | - (Optional) If you wish to use OpenAI models instead (or another provider), you will need to create an account on their website and get an API key; 14 | - (Optional) Set up an account on [LangSmith](https://smith.langchain.com/) for agent observability & monitoring. 15 | 16 | ## Getting Started 17 | 18 | To install this example application, run the following commands: 19 | 20 | ```bash 21 | git clone https://github.com/5afe/safe-ai-agent-tutorial.git 22 | cd safe-ai-agent-tutorial 23 | pnpm i 24 | ``` 25 | 26 | This will get a copy of the project installed locally. Now, create a file named `.env.local` at the root of your project, and add your private key and address key to it: 27 | 28 | ```bash 29 | cp .env.example .env.local 30 | ``` 31 | 32 | Run the agent locally with the following command: 33 | 34 | ```bash 35 | pnpm start 36 | ``` 37 | 38 | See the resulting output in your terminal. You should see the agent interacting with your Safe. For more information on what is going on under the hood, set up an account on [LangSmith](https://smith.langchain.com/) and monitor your agent's activity. 39 | 40 | ## Help 41 | 42 | Please post any questions on [Stack Exchange](https://ethereum.stackexchange.com/questions/tagged/safe-core) with the `safe-core` tag. 43 | 44 | ## License 45 | 46 | MIT, see [LICENSE](LICENSE). 47 | -------------------------------------------------------------------------------- /agent.ts: -------------------------------------------------------------------------------- 1 | import { ChatOllama } from "@langchain/ollama"; 2 | // import { ChatOpenAI } from "@langchain/openai"; 3 | import { MemorySaver } from "@langchain/langgraph"; 4 | import { HumanMessage } from "@langchain/core/messages"; 5 | import { createReactAgent } from "@langchain/langgraph/prebuilt"; 6 | import { tool } from "@langchain/core/tools"; 7 | 8 | import { 9 | deployNewSafe, 10 | deployNewSafeMetadata, 11 | getEthBalance, 12 | getEthBalanceMetadata, 13 | } from "./tools/safe"; 14 | import { getEthPriceUsd, getEthPriceUsdMetadata } from "./tools/prices"; 15 | import { multiply, multiplyMetadata } from "./tools/math"; 16 | 17 | const main = async () => { 18 | // Define the tools for the agent to use 19 | const agentTools = [ 20 | tool(getEthBalance, getEthBalanceMetadata), 21 | tool(getEthPriceUsd, getEthPriceUsdMetadata), 22 | tool(multiply, multiplyMetadata), 23 | tool(deployNewSafe, deployNewSafeMetadata), 24 | ]; 25 | 26 | // Initialize the agent with a model running locally: 27 | const agentModel = new ChatOllama({ model: "mistral-nemo" }); // Feel free to try different models. For the full list: https://ollama.com/search?c=tools 28 | 29 | // Or if your prefer using OpenAI (you will need to provide an OPENAI_API_KEY in the .env file.): 30 | // const agentModel = new ChatOpenAI({ temperature: 0, model: "o3-mini" }); 31 | 32 | const agentCheckpointer = new MemorySaver(); // Initialize memory to persist state between graph runs 33 | 34 | const agent = createReactAgent({ 35 | llm: agentModel, 36 | tools: agentTools, 37 | checkpointSaver: agentCheckpointer, 38 | }); 39 | 40 | // Let's chat! 41 | const agentFinalState = await agent.invoke( 42 | { 43 | messages: [ 44 | new HumanMessage( 45 | "what is the current balance of the Safe Multisig at the address 0x220866B1A2219f40e72f5c628B65D54268cA3A9D on chain id 1? Please answer in ETH and its total value in USD." 46 | ), 47 | ], 48 | }, 49 | { configurable: { thread_id: "42" } } 50 | ); 51 | 52 | console.log( 53 | agentFinalState.messages[agentFinalState.messages.length - 1].content 54 | ); 55 | 56 | // You can continue the conversation by adding more messages: 57 | // const agentNextState = await agent.invoke( 58 | // { 59 | // messages: [ 60 | // new HumanMessage("Could you deploy a new Safe multisig on Sepolia?"), 61 | // ], 62 | // }, 63 | // { configurable: { thread_id: "42" } } 64 | // ); 65 | 66 | // console.log("--- Prompt #2 ---"); 67 | // console.log( 68 | // agentNextState.messages[agentNextState.messages.length - 1].content 69 | // ); 70 | }; 71 | 72 | main(); 73 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "pnpm tsx --env-file=.env agent.ts" 4 | }, 5 | "dependencies": { 6 | "@langchain/core": "^0.3.37", 7 | "@langchain/langgraph": "^0.2.44", 8 | "@langchain/ollama": "^0.1.5", 9 | "@safe-global/protocol-kit": "^5.2.1", 10 | "tsx": "^4.19.2", 11 | "viem": "^2.22.23", 12 | "zod": "^3.24.1" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "^22.13.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@langchain/core': 12 | specifier: ^0.3.37 13 | version: 0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)) 14 | '@langchain/langgraph': 15 | specifier: ^0.2.44 16 | version: 0.2.44(@langchain/core@0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1))) 17 | '@langchain/ollama': 18 | specifier: ^0.1.5 19 | version: 0.1.5(@langchain/core@0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1))) 20 | '@safe-global/protocol-kit': 21 | specifier: ^5.2.1 22 | version: 5.2.1(typescript@5.7.3)(zod@3.24.1) 23 | tsx: 24 | specifier: ^4.19.2 25 | version: 4.19.2 26 | viem: 27 | specifier: ^2.22.23 28 | version: 2.22.23(typescript@5.7.3)(zod@3.24.1) 29 | zod: 30 | specifier: ^3.24.1 31 | version: 3.24.1 32 | devDependencies: 33 | '@types/node': 34 | specifier: ^22.13.1 35 | version: 22.13.1 36 | 37 | packages: 38 | 39 | '@adraffy/ens-normalize@1.11.0': 40 | resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} 41 | 42 | '@cfworker/json-schema@4.1.1': 43 | resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} 44 | 45 | '@esbuild/aix-ppc64@0.23.1': 46 | resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} 47 | engines: {node: '>=18'} 48 | cpu: [ppc64] 49 | os: [aix] 50 | 51 | '@esbuild/android-arm64@0.23.1': 52 | resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} 53 | engines: {node: '>=18'} 54 | cpu: [arm64] 55 | os: [android] 56 | 57 | '@esbuild/android-arm@0.23.1': 58 | resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} 59 | engines: {node: '>=18'} 60 | cpu: [arm] 61 | os: [android] 62 | 63 | '@esbuild/android-x64@0.23.1': 64 | resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} 65 | engines: {node: '>=18'} 66 | cpu: [x64] 67 | os: [android] 68 | 69 | '@esbuild/darwin-arm64@0.23.1': 70 | resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} 71 | engines: {node: '>=18'} 72 | cpu: [arm64] 73 | os: [darwin] 74 | 75 | '@esbuild/darwin-x64@0.23.1': 76 | resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} 77 | engines: {node: '>=18'} 78 | cpu: [x64] 79 | os: [darwin] 80 | 81 | '@esbuild/freebsd-arm64@0.23.1': 82 | resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} 83 | engines: {node: '>=18'} 84 | cpu: [arm64] 85 | os: [freebsd] 86 | 87 | '@esbuild/freebsd-x64@0.23.1': 88 | resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} 89 | engines: {node: '>=18'} 90 | cpu: [x64] 91 | os: [freebsd] 92 | 93 | '@esbuild/linux-arm64@0.23.1': 94 | resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} 95 | engines: {node: '>=18'} 96 | cpu: [arm64] 97 | os: [linux] 98 | 99 | '@esbuild/linux-arm@0.23.1': 100 | resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} 101 | engines: {node: '>=18'} 102 | cpu: [arm] 103 | os: [linux] 104 | 105 | '@esbuild/linux-ia32@0.23.1': 106 | resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} 107 | engines: {node: '>=18'} 108 | cpu: [ia32] 109 | os: [linux] 110 | 111 | '@esbuild/linux-loong64@0.23.1': 112 | resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} 113 | engines: {node: '>=18'} 114 | cpu: [loong64] 115 | os: [linux] 116 | 117 | '@esbuild/linux-mips64el@0.23.1': 118 | resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} 119 | engines: {node: '>=18'} 120 | cpu: [mips64el] 121 | os: [linux] 122 | 123 | '@esbuild/linux-ppc64@0.23.1': 124 | resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} 125 | engines: {node: '>=18'} 126 | cpu: [ppc64] 127 | os: [linux] 128 | 129 | '@esbuild/linux-riscv64@0.23.1': 130 | resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} 131 | engines: {node: '>=18'} 132 | cpu: [riscv64] 133 | os: [linux] 134 | 135 | '@esbuild/linux-s390x@0.23.1': 136 | resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} 137 | engines: {node: '>=18'} 138 | cpu: [s390x] 139 | os: [linux] 140 | 141 | '@esbuild/linux-x64@0.23.1': 142 | resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} 143 | engines: {node: '>=18'} 144 | cpu: [x64] 145 | os: [linux] 146 | 147 | '@esbuild/netbsd-x64@0.23.1': 148 | resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} 149 | engines: {node: '>=18'} 150 | cpu: [x64] 151 | os: [netbsd] 152 | 153 | '@esbuild/openbsd-arm64@0.23.1': 154 | resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} 155 | engines: {node: '>=18'} 156 | cpu: [arm64] 157 | os: [openbsd] 158 | 159 | '@esbuild/openbsd-x64@0.23.1': 160 | resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} 161 | engines: {node: '>=18'} 162 | cpu: [x64] 163 | os: [openbsd] 164 | 165 | '@esbuild/sunos-x64@0.23.1': 166 | resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} 167 | engines: {node: '>=18'} 168 | cpu: [x64] 169 | os: [sunos] 170 | 171 | '@esbuild/win32-arm64@0.23.1': 172 | resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} 173 | engines: {node: '>=18'} 174 | cpu: [arm64] 175 | os: [win32] 176 | 177 | '@esbuild/win32-ia32@0.23.1': 178 | resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} 179 | engines: {node: '>=18'} 180 | cpu: [ia32] 181 | os: [win32] 182 | 183 | '@esbuild/win32-x64@0.23.1': 184 | resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} 185 | engines: {node: '>=18'} 186 | cpu: [x64] 187 | os: [win32] 188 | 189 | '@langchain/core@0.3.37': 190 | resolution: {integrity: sha512-LFk9GqHxcyCFx0oXvCBP7vDZIOUHYzzNU7JR+2ofIMnfkBLzcCKzBLySQDfPtd13PrpGHkaeOeLq8H1Tqi9lSw==} 191 | engines: {node: '>=18'} 192 | 193 | '@langchain/langgraph-checkpoint@0.0.15': 194 | resolution: {integrity: sha512-AiJkvsYHqNbCh1Tx823qs2lf2qRqeB4EAMejirOk8gkpPszAGYua5c3niKYkcKR2tU8Snhrmj7Gm9HKZSFOXyw==} 195 | engines: {node: '>=18'} 196 | peerDependencies: 197 | '@langchain/core': '>=0.2.31 <0.4.0' 198 | 199 | '@langchain/langgraph-sdk@0.0.36': 200 | resolution: {integrity: sha512-KkAZM0uXBaMcD/dpGTBppOhbvNX6gz+Y1zFAC898OblegFkSvICrkd0oRQ5Ro/GWK/NAoDymnMUDXeZDdUkSuw==} 201 | 202 | '@langchain/langgraph@0.2.44': 203 | resolution: {integrity: sha512-CR9LB7sytdx0Ink56qVUPorDo5gW5m7iOU2ypu1OYA4l5aIrT4xGvHCwrGH9RE80pb/d0FglVUkEgEfuvSDbmw==} 204 | engines: {node: '>=18'} 205 | peerDependencies: 206 | '@langchain/core': '>=0.2.36 <0.3.0 || >=0.3.9 < 0.4.0' 207 | 208 | '@langchain/ollama@0.1.5': 209 | resolution: {integrity: sha512-S2tF94uIJtXavekKg10LvTV+jIelOIrubaCnje8BopfiNOVcnzsSulUL4JH0wvdxMZq0vbE4/i9RwC2q9ivOmA==} 210 | engines: {node: '>=18'} 211 | peerDependencies: 212 | '@langchain/core': '>=0.2.21 <0.4.0' 213 | 214 | '@noble/curves@1.8.1': 215 | resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} 216 | engines: {node: ^14.21.3 || >=16} 217 | 218 | '@noble/hashes@1.7.1': 219 | resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} 220 | engines: {node: ^14.21.3 || >=16} 221 | 222 | '@peculiar/asn1-schema@2.3.15': 223 | resolution: {integrity: sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==} 224 | 225 | '@safe-global/protocol-kit@5.2.1': 226 | resolution: {integrity: sha512-7jY+p2+GQU9FPKMMgHDr32gPC/1BKtYVzvQHniZuPSJVcb26E0CBwZb7IUyRiUd+kJN8OF13zRFbhQdH99Akhw==} 227 | 228 | '@safe-global/safe-deployments@1.37.27': 229 | resolution: {integrity: sha512-0r/BzntT/XUPlca11obF1Zog1m8jLSGVbb97FqxnjaEzqWf+N7dBwAYJ9Voq3e7hlqpcVLMh3O6VDAf4y+5ndg==} 230 | 231 | '@safe-global/safe-modules-deployments@2.2.5': 232 | resolution: {integrity: sha512-rkKqj6gGKokjBX2JshH1EwjPkzFD14oOk2vY3LSxKhpkQyjdqxcj+OlWkjzpi613HzCtxY0mHgMiyLID7nzueA==} 233 | 234 | '@safe-global/types-kit@1.0.2': 235 | resolution: {integrity: sha512-KiRlU1nlWuj4Qr+nLxgO/yRpJamVUOonnAkLrSMrzfGwXcfLWXJJtoD9sv/pvTIHMWSOlzgkrc1KXqY3K68SGg==} 236 | 237 | '@scure/base@1.2.4': 238 | resolution: {integrity: sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==} 239 | 240 | '@scure/bip32@1.6.2': 241 | resolution: {integrity: sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==} 242 | 243 | '@scure/bip39@1.5.4': 244 | resolution: {integrity: sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==} 245 | 246 | '@types/json-schema@7.0.15': 247 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 248 | 249 | '@types/node-fetch@2.6.12': 250 | resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} 251 | 252 | '@types/node@18.19.75': 253 | resolution: {integrity: sha512-UIksWtThob6ZVSyxcOqCLOUNg/dyO1Qvx4McgeuhrEtHTLFTf7BBhEazaE4K806FGTPtzd/2sE90qn4fVr7cyw==} 254 | 255 | '@types/node@22.13.1': 256 | resolution: {integrity: sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==} 257 | 258 | '@types/retry@0.12.0': 259 | resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} 260 | 261 | '@types/uuid@10.0.0': 262 | resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} 263 | 264 | abitype@1.0.8: 265 | resolution: {integrity: sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==} 266 | peerDependencies: 267 | typescript: '>=5.0.4' 268 | zod: ^3 >=3.22.0 269 | peerDependenciesMeta: 270 | typescript: 271 | optional: true 272 | zod: 273 | optional: true 274 | 275 | abort-controller@3.0.0: 276 | resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} 277 | engines: {node: '>=6.5'} 278 | 279 | agentkeepalive@4.6.0: 280 | resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} 281 | engines: {node: '>= 8.0.0'} 282 | 283 | ansi-styles@4.3.0: 284 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 285 | engines: {node: '>=8'} 286 | 287 | ansi-styles@5.2.0: 288 | resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} 289 | engines: {node: '>=10'} 290 | 291 | asn1js@3.0.5: 292 | resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==} 293 | engines: {node: '>=12.0.0'} 294 | 295 | asynckit@0.4.0: 296 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 297 | 298 | base64-js@1.5.1: 299 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 300 | 301 | camelcase@6.3.0: 302 | resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} 303 | engines: {node: '>=10'} 304 | 305 | chalk@4.1.2: 306 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 307 | engines: {node: '>=10'} 308 | 309 | color-convert@2.0.1: 310 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 311 | engines: {node: '>=7.0.0'} 312 | 313 | color-name@1.1.4: 314 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 315 | 316 | combined-stream@1.0.8: 317 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 318 | engines: {node: '>= 0.8'} 319 | 320 | console-table-printer@2.12.1: 321 | resolution: {integrity: sha512-wKGOQRRvdnd89pCeH96e2Fn4wkbenSP6LMHfjfyNLMbGuHEFbMqQNuxXqd0oXG9caIOQ1FTvc5Uijp9/4jujnQ==} 322 | 323 | decamelize@1.2.0: 324 | resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} 325 | engines: {node: '>=0.10.0'} 326 | 327 | delayed-stream@1.0.0: 328 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 329 | engines: {node: '>=0.4.0'} 330 | 331 | encoding@0.1.13: 332 | resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} 333 | 334 | esbuild@0.23.1: 335 | resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} 336 | engines: {node: '>=18'} 337 | hasBin: true 338 | 339 | event-target-shim@5.0.1: 340 | resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} 341 | engines: {node: '>=6'} 342 | 343 | eventemitter3@4.0.7: 344 | resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} 345 | 346 | eventemitter3@5.0.1: 347 | resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} 348 | 349 | form-data-encoder@1.7.2: 350 | resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} 351 | 352 | form-data@4.0.1: 353 | resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} 354 | engines: {node: '>= 6'} 355 | 356 | formdata-node@4.4.1: 357 | resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} 358 | engines: {node: '>= 12.20'} 359 | 360 | fsevents@2.3.3: 361 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 362 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 363 | os: [darwin] 364 | 365 | get-tsconfig@4.10.0: 366 | resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} 367 | 368 | has-flag@4.0.0: 369 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 370 | engines: {node: '>=8'} 371 | 372 | humanize-ms@1.2.1: 373 | resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} 374 | 375 | iconv-lite@0.6.3: 376 | resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} 377 | engines: {node: '>=0.10.0'} 378 | 379 | isows@1.0.6: 380 | resolution: {integrity: sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==} 381 | peerDependencies: 382 | ws: '*' 383 | 384 | js-tiktoken@1.0.18: 385 | resolution: {integrity: sha512-hFYx4xYf6URgcttcGvGuOBJhTxPYZ2R5eIesqCaNRJmYH8sNmsfTeWg4yu//7u1VD/qIUkgKJTpGom9oHXmB4g==} 386 | 387 | langsmith@0.3.4: 388 | resolution: {integrity: sha512-Klyy7HtOEh3RqQsKStUfVwE8NMrLCp1+ng50ddeEjJyF5WI+LsgBDIpJGRVjmgNbNeX+rGnUk0kBKIU5gZjVFQ==} 389 | peerDependencies: 390 | openai: '*' 391 | peerDependenciesMeta: 392 | openai: 393 | optional: true 394 | 395 | mime-db@1.52.0: 396 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 397 | engines: {node: '>= 0.6'} 398 | 399 | mime-types@2.1.35: 400 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 401 | engines: {node: '>= 0.6'} 402 | 403 | ms@2.1.3: 404 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 405 | 406 | mustache@4.2.0: 407 | resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} 408 | hasBin: true 409 | 410 | node-domexception@1.0.0: 411 | resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} 412 | engines: {node: '>=10.5.0'} 413 | 414 | node-fetch@2.7.0: 415 | resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} 416 | engines: {node: 4.x || >=6.0.0} 417 | peerDependencies: 418 | encoding: ^0.1.0 419 | peerDependenciesMeta: 420 | encoding: 421 | optional: true 422 | 423 | ollama@0.5.12: 424 | resolution: {integrity: sha512-flVH1fn1c9NF7VV3bW9kSu0E+bYc40b4DxL/gS2Debhao35osJFRDiPOj9sIWTMvcyj78Paw1OuhfIe7uhDWfQ==} 425 | 426 | openai@4.82.0: 427 | resolution: {integrity: sha512-1bTxOVGZuVGsKKUWbh3BEwX1QxIXUftJv+9COhhGGVDTFwiaOd4gWsMynF2ewj1mg6by3/O+U8+EEHpWRdPaJg==} 428 | hasBin: true 429 | peerDependencies: 430 | ws: ^8.18.0 431 | zod: ^3.23.8 432 | peerDependenciesMeta: 433 | ws: 434 | optional: true 435 | zod: 436 | optional: true 437 | 438 | ox@0.6.7: 439 | resolution: {integrity: sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==} 440 | peerDependencies: 441 | typescript: '>=5.4.0' 442 | peerDependenciesMeta: 443 | typescript: 444 | optional: true 445 | 446 | p-finally@1.0.0: 447 | resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} 448 | engines: {node: '>=4'} 449 | 450 | p-queue@6.6.2: 451 | resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} 452 | engines: {node: '>=8'} 453 | 454 | p-retry@4.6.2: 455 | resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} 456 | engines: {node: '>=8'} 457 | 458 | p-timeout@3.2.0: 459 | resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} 460 | engines: {node: '>=8'} 461 | 462 | pvtsutils@1.3.6: 463 | resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} 464 | 465 | pvutils@1.1.3: 466 | resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==} 467 | engines: {node: '>=6.0.0'} 468 | 469 | resolve-pkg-maps@1.0.0: 470 | resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 471 | 472 | retry@0.13.1: 473 | resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} 474 | engines: {node: '>= 4'} 475 | 476 | safer-buffer@2.1.2: 477 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 478 | 479 | semver@7.7.1: 480 | resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 481 | engines: {node: '>=10'} 482 | hasBin: true 483 | 484 | simple-wcswidth@1.0.1: 485 | resolution: {integrity: sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg==} 486 | 487 | supports-color@7.2.0: 488 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 489 | engines: {node: '>=8'} 490 | 491 | tr46@0.0.3: 492 | resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 493 | 494 | tslib@2.8.1: 495 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 496 | 497 | tsx@4.19.2: 498 | resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} 499 | engines: {node: '>=18.0.0'} 500 | hasBin: true 501 | 502 | typescript@5.7.3: 503 | resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} 504 | engines: {node: '>=14.17'} 505 | hasBin: true 506 | 507 | undici-types@5.26.5: 508 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} 509 | 510 | undici-types@6.20.0: 511 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} 512 | 513 | uuid@10.0.0: 514 | resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} 515 | hasBin: true 516 | 517 | uuid@9.0.1: 518 | resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} 519 | hasBin: true 520 | 521 | viem@2.22.23: 522 | resolution: {integrity: sha512-MheOu+joowphTCfCgdQ9BGU/z1IeHa6/ZIYNVc6KTwDklj671YS87cGv5kRCSU0vAfzN+5wjWyIffM8000KGkQ==} 523 | peerDependencies: 524 | typescript: '>=5.0.4' 525 | peerDependenciesMeta: 526 | typescript: 527 | optional: true 528 | 529 | web-streams-polyfill@4.0.0-beta.3: 530 | resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} 531 | engines: {node: '>= 14'} 532 | 533 | webidl-conversions@3.0.1: 534 | resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 535 | 536 | whatwg-fetch@3.6.20: 537 | resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} 538 | 539 | whatwg-url@5.0.0: 540 | resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} 541 | 542 | ws@8.18.0: 543 | resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} 544 | engines: {node: '>=10.0.0'} 545 | peerDependencies: 546 | bufferutil: ^4.0.1 547 | utf-8-validate: '>=5.0.2' 548 | peerDependenciesMeta: 549 | bufferutil: 550 | optional: true 551 | utf-8-validate: 552 | optional: true 553 | 554 | zod-to-json-schema@3.24.1: 555 | resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==} 556 | peerDependencies: 557 | zod: ^3.24.1 558 | 559 | zod@3.24.1: 560 | resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} 561 | 562 | snapshots: 563 | 564 | '@adraffy/ens-normalize@1.11.0': {} 565 | 566 | '@cfworker/json-schema@4.1.1': {} 567 | 568 | '@esbuild/aix-ppc64@0.23.1': 569 | optional: true 570 | 571 | '@esbuild/android-arm64@0.23.1': 572 | optional: true 573 | 574 | '@esbuild/android-arm@0.23.1': 575 | optional: true 576 | 577 | '@esbuild/android-x64@0.23.1': 578 | optional: true 579 | 580 | '@esbuild/darwin-arm64@0.23.1': 581 | optional: true 582 | 583 | '@esbuild/darwin-x64@0.23.1': 584 | optional: true 585 | 586 | '@esbuild/freebsd-arm64@0.23.1': 587 | optional: true 588 | 589 | '@esbuild/freebsd-x64@0.23.1': 590 | optional: true 591 | 592 | '@esbuild/linux-arm64@0.23.1': 593 | optional: true 594 | 595 | '@esbuild/linux-arm@0.23.1': 596 | optional: true 597 | 598 | '@esbuild/linux-ia32@0.23.1': 599 | optional: true 600 | 601 | '@esbuild/linux-loong64@0.23.1': 602 | optional: true 603 | 604 | '@esbuild/linux-mips64el@0.23.1': 605 | optional: true 606 | 607 | '@esbuild/linux-ppc64@0.23.1': 608 | optional: true 609 | 610 | '@esbuild/linux-riscv64@0.23.1': 611 | optional: true 612 | 613 | '@esbuild/linux-s390x@0.23.1': 614 | optional: true 615 | 616 | '@esbuild/linux-x64@0.23.1': 617 | optional: true 618 | 619 | '@esbuild/netbsd-x64@0.23.1': 620 | optional: true 621 | 622 | '@esbuild/openbsd-arm64@0.23.1': 623 | optional: true 624 | 625 | '@esbuild/openbsd-x64@0.23.1': 626 | optional: true 627 | 628 | '@esbuild/sunos-x64@0.23.1': 629 | optional: true 630 | 631 | '@esbuild/win32-arm64@0.23.1': 632 | optional: true 633 | 634 | '@esbuild/win32-ia32@0.23.1': 635 | optional: true 636 | 637 | '@esbuild/win32-x64@0.23.1': 638 | optional: true 639 | 640 | '@langchain/core@0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1))': 641 | dependencies: 642 | '@cfworker/json-schema': 4.1.1 643 | ansi-styles: 5.2.0 644 | camelcase: 6.3.0 645 | decamelize: 1.2.0 646 | js-tiktoken: 1.0.18 647 | langsmith: 0.3.4(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)) 648 | mustache: 4.2.0 649 | p-queue: 6.6.2 650 | p-retry: 4.6.2 651 | uuid: 10.0.0 652 | zod: 3.24.1 653 | zod-to-json-schema: 3.24.1(zod@3.24.1) 654 | transitivePeerDependencies: 655 | - openai 656 | 657 | '@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)))': 658 | dependencies: 659 | '@langchain/core': 0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)) 660 | uuid: 10.0.0 661 | 662 | '@langchain/langgraph-sdk@0.0.36': 663 | dependencies: 664 | '@types/json-schema': 7.0.15 665 | p-queue: 6.6.2 666 | p-retry: 4.6.2 667 | uuid: 9.0.1 668 | 669 | '@langchain/langgraph@0.2.44(@langchain/core@0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)))': 670 | dependencies: 671 | '@langchain/core': 0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)) 672 | '@langchain/langgraph-checkpoint': 0.0.15(@langchain/core@0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1))) 673 | '@langchain/langgraph-sdk': 0.0.36 674 | uuid: 10.0.0 675 | zod: 3.24.1 676 | 677 | '@langchain/ollama@0.1.5(@langchain/core@0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)))': 678 | dependencies: 679 | '@langchain/core': 0.3.37(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)) 680 | ollama: 0.5.12 681 | uuid: 10.0.0 682 | 683 | '@noble/curves@1.8.1': 684 | dependencies: 685 | '@noble/hashes': 1.7.1 686 | 687 | '@noble/hashes@1.7.1': {} 688 | 689 | '@peculiar/asn1-schema@2.3.15': 690 | dependencies: 691 | asn1js: 3.0.5 692 | pvtsutils: 1.3.6 693 | tslib: 2.8.1 694 | optional: true 695 | 696 | '@safe-global/protocol-kit@5.2.1(typescript@5.7.3)(zod@3.24.1)': 697 | dependencies: 698 | '@safe-global/safe-deployments': 1.37.27 699 | '@safe-global/safe-modules-deployments': 2.2.5 700 | '@safe-global/types-kit': 1.0.2(typescript@5.7.3)(zod@3.24.1) 701 | abitype: 1.0.8(typescript@5.7.3)(zod@3.24.1) 702 | semver: 7.7.1 703 | viem: 2.22.23(typescript@5.7.3)(zod@3.24.1) 704 | optionalDependencies: 705 | '@noble/curves': 1.8.1 706 | '@peculiar/asn1-schema': 2.3.15 707 | transitivePeerDependencies: 708 | - bufferutil 709 | - typescript 710 | - utf-8-validate 711 | - zod 712 | 713 | '@safe-global/safe-deployments@1.37.27': 714 | dependencies: 715 | semver: 7.7.1 716 | 717 | '@safe-global/safe-modules-deployments@2.2.5': {} 718 | 719 | '@safe-global/types-kit@1.0.2(typescript@5.7.3)(zod@3.24.1)': 720 | dependencies: 721 | abitype: 1.0.8(typescript@5.7.3)(zod@3.24.1) 722 | transitivePeerDependencies: 723 | - typescript 724 | - zod 725 | 726 | '@scure/base@1.2.4': {} 727 | 728 | '@scure/bip32@1.6.2': 729 | dependencies: 730 | '@noble/curves': 1.8.1 731 | '@noble/hashes': 1.7.1 732 | '@scure/base': 1.2.4 733 | 734 | '@scure/bip39@1.5.4': 735 | dependencies: 736 | '@noble/hashes': 1.7.1 737 | '@scure/base': 1.2.4 738 | 739 | '@types/json-schema@7.0.15': {} 740 | 741 | '@types/node-fetch@2.6.12': 742 | dependencies: 743 | '@types/node': 22.13.1 744 | form-data: 4.0.1 745 | optional: true 746 | 747 | '@types/node@18.19.75': 748 | dependencies: 749 | undici-types: 5.26.5 750 | optional: true 751 | 752 | '@types/node@22.13.1': 753 | dependencies: 754 | undici-types: 6.20.0 755 | 756 | '@types/retry@0.12.0': {} 757 | 758 | '@types/uuid@10.0.0': {} 759 | 760 | abitype@1.0.8(typescript@5.7.3)(zod@3.24.1): 761 | optionalDependencies: 762 | typescript: 5.7.3 763 | zod: 3.24.1 764 | 765 | abort-controller@3.0.0: 766 | dependencies: 767 | event-target-shim: 5.0.1 768 | optional: true 769 | 770 | agentkeepalive@4.6.0: 771 | dependencies: 772 | humanize-ms: 1.2.1 773 | optional: true 774 | 775 | ansi-styles@4.3.0: 776 | dependencies: 777 | color-convert: 2.0.1 778 | 779 | ansi-styles@5.2.0: {} 780 | 781 | asn1js@3.0.5: 782 | dependencies: 783 | pvtsutils: 1.3.6 784 | pvutils: 1.1.3 785 | tslib: 2.8.1 786 | optional: true 787 | 788 | asynckit@0.4.0: 789 | optional: true 790 | 791 | base64-js@1.5.1: {} 792 | 793 | camelcase@6.3.0: {} 794 | 795 | chalk@4.1.2: 796 | dependencies: 797 | ansi-styles: 4.3.0 798 | supports-color: 7.2.0 799 | 800 | color-convert@2.0.1: 801 | dependencies: 802 | color-name: 1.1.4 803 | 804 | color-name@1.1.4: {} 805 | 806 | combined-stream@1.0.8: 807 | dependencies: 808 | delayed-stream: 1.0.0 809 | optional: true 810 | 811 | console-table-printer@2.12.1: 812 | dependencies: 813 | simple-wcswidth: 1.0.1 814 | 815 | decamelize@1.2.0: {} 816 | 817 | delayed-stream@1.0.0: 818 | optional: true 819 | 820 | encoding@0.1.13: 821 | dependencies: 822 | iconv-lite: 0.6.3 823 | optional: true 824 | 825 | esbuild@0.23.1: 826 | optionalDependencies: 827 | '@esbuild/aix-ppc64': 0.23.1 828 | '@esbuild/android-arm': 0.23.1 829 | '@esbuild/android-arm64': 0.23.1 830 | '@esbuild/android-x64': 0.23.1 831 | '@esbuild/darwin-arm64': 0.23.1 832 | '@esbuild/darwin-x64': 0.23.1 833 | '@esbuild/freebsd-arm64': 0.23.1 834 | '@esbuild/freebsd-x64': 0.23.1 835 | '@esbuild/linux-arm': 0.23.1 836 | '@esbuild/linux-arm64': 0.23.1 837 | '@esbuild/linux-ia32': 0.23.1 838 | '@esbuild/linux-loong64': 0.23.1 839 | '@esbuild/linux-mips64el': 0.23.1 840 | '@esbuild/linux-ppc64': 0.23.1 841 | '@esbuild/linux-riscv64': 0.23.1 842 | '@esbuild/linux-s390x': 0.23.1 843 | '@esbuild/linux-x64': 0.23.1 844 | '@esbuild/netbsd-x64': 0.23.1 845 | '@esbuild/openbsd-arm64': 0.23.1 846 | '@esbuild/openbsd-x64': 0.23.1 847 | '@esbuild/sunos-x64': 0.23.1 848 | '@esbuild/win32-arm64': 0.23.1 849 | '@esbuild/win32-ia32': 0.23.1 850 | '@esbuild/win32-x64': 0.23.1 851 | 852 | event-target-shim@5.0.1: 853 | optional: true 854 | 855 | eventemitter3@4.0.7: {} 856 | 857 | eventemitter3@5.0.1: {} 858 | 859 | form-data-encoder@1.7.2: 860 | optional: true 861 | 862 | form-data@4.0.1: 863 | dependencies: 864 | asynckit: 0.4.0 865 | combined-stream: 1.0.8 866 | mime-types: 2.1.35 867 | optional: true 868 | 869 | formdata-node@4.4.1: 870 | dependencies: 871 | node-domexception: 1.0.0 872 | web-streams-polyfill: 4.0.0-beta.3 873 | optional: true 874 | 875 | fsevents@2.3.3: 876 | optional: true 877 | 878 | get-tsconfig@4.10.0: 879 | dependencies: 880 | resolve-pkg-maps: 1.0.0 881 | 882 | has-flag@4.0.0: {} 883 | 884 | humanize-ms@1.2.1: 885 | dependencies: 886 | ms: 2.1.3 887 | optional: true 888 | 889 | iconv-lite@0.6.3: 890 | dependencies: 891 | safer-buffer: 2.1.2 892 | optional: true 893 | 894 | isows@1.0.6(ws@8.18.0): 895 | dependencies: 896 | ws: 8.18.0 897 | 898 | js-tiktoken@1.0.18: 899 | dependencies: 900 | base64-js: 1.5.1 901 | 902 | langsmith@0.3.4(openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1)): 903 | dependencies: 904 | '@types/uuid': 10.0.0 905 | chalk: 4.1.2 906 | console-table-printer: 2.12.1 907 | p-queue: 6.6.2 908 | p-retry: 4.6.2 909 | semver: 7.7.1 910 | uuid: 10.0.0 911 | optionalDependencies: 912 | openai: 4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1) 913 | 914 | mime-db@1.52.0: 915 | optional: true 916 | 917 | mime-types@2.1.35: 918 | dependencies: 919 | mime-db: 1.52.0 920 | optional: true 921 | 922 | ms@2.1.3: 923 | optional: true 924 | 925 | mustache@4.2.0: {} 926 | 927 | node-domexception@1.0.0: 928 | optional: true 929 | 930 | node-fetch@2.7.0(encoding@0.1.13): 931 | dependencies: 932 | whatwg-url: 5.0.0 933 | optionalDependencies: 934 | encoding: 0.1.13 935 | optional: true 936 | 937 | ollama@0.5.12: 938 | dependencies: 939 | whatwg-fetch: 3.6.20 940 | 941 | openai@4.82.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.1): 942 | dependencies: 943 | '@types/node': 18.19.75 944 | '@types/node-fetch': 2.6.12 945 | abort-controller: 3.0.0 946 | agentkeepalive: 4.6.0 947 | form-data-encoder: 1.7.2 948 | formdata-node: 4.4.1 949 | node-fetch: 2.7.0(encoding@0.1.13) 950 | optionalDependencies: 951 | ws: 8.18.0 952 | zod: 3.24.1 953 | transitivePeerDependencies: 954 | - encoding 955 | optional: true 956 | 957 | ox@0.6.7(typescript@5.7.3)(zod@3.24.1): 958 | dependencies: 959 | '@adraffy/ens-normalize': 1.11.0 960 | '@noble/curves': 1.8.1 961 | '@noble/hashes': 1.7.1 962 | '@scure/bip32': 1.6.2 963 | '@scure/bip39': 1.5.4 964 | abitype: 1.0.8(typescript@5.7.3)(zod@3.24.1) 965 | eventemitter3: 5.0.1 966 | optionalDependencies: 967 | typescript: 5.7.3 968 | transitivePeerDependencies: 969 | - zod 970 | 971 | p-finally@1.0.0: {} 972 | 973 | p-queue@6.6.2: 974 | dependencies: 975 | eventemitter3: 4.0.7 976 | p-timeout: 3.2.0 977 | 978 | p-retry@4.6.2: 979 | dependencies: 980 | '@types/retry': 0.12.0 981 | retry: 0.13.1 982 | 983 | p-timeout@3.2.0: 984 | dependencies: 985 | p-finally: 1.0.0 986 | 987 | pvtsutils@1.3.6: 988 | dependencies: 989 | tslib: 2.8.1 990 | optional: true 991 | 992 | pvutils@1.1.3: 993 | optional: true 994 | 995 | resolve-pkg-maps@1.0.0: {} 996 | 997 | retry@0.13.1: {} 998 | 999 | safer-buffer@2.1.2: 1000 | optional: true 1001 | 1002 | semver@7.7.1: {} 1003 | 1004 | simple-wcswidth@1.0.1: {} 1005 | 1006 | supports-color@7.2.0: 1007 | dependencies: 1008 | has-flag: 4.0.0 1009 | 1010 | tr46@0.0.3: 1011 | optional: true 1012 | 1013 | tslib@2.8.1: 1014 | optional: true 1015 | 1016 | tsx@4.19.2: 1017 | dependencies: 1018 | esbuild: 0.23.1 1019 | get-tsconfig: 4.10.0 1020 | optionalDependencies: 1021 | fsevents: 2.3.3 1022 | 1023 | typescript@5.7.3: 1024 | optional: true 1025 | 1026 | undici-types@5.26.5: 1027 | optional: true 1028 | 1029 | undici-types@6.20.0: {} 1030 | 1031 | uuid@10.0.0: {} 1032 | 1033 | uuid@9.0.1: {} 1034 | 1035 | viem@2.22.23(typescript@5.7.3)(zod@3.24.1): 1036 | dependencies: 1037 | '@noble/curves': 1.8.1 1038 | '@noble/hashes': 1.7.1 1039 | '@scure/bip32': 1.6.2 1040 | '@scure/bip39': 1.5.4 1041 | abitype: 1.0.8(typescript@5.7.3)(zod@3.24.1) 1042 | isows: 1.0.6(ws@8.18.0) 1043 | ox: 0.6.7(typescript@5.7.3)(zod@3.24.1) 1044 | ws: 8.18.0 1045 | optionalDependencies: 1046 | typescript: 5.7.3 1047 | transitivePeerDependencies: 1048 | - bufferutil 1049 | - utf-8-validate 1050 | - zod 1051 | 1052 | web-streams-polyfill@4.0.0-beta.3: 1053 | optional: true 1054 | 1055 | webidl-conversions@3.0.1: 1056 | optional: true 1057 | 1058 | whatwg-fetch@3.6.20: {} 1059 | 1060 | whatwg-url@5.0.0: 1061 | dependencies: 1062 | tr46: 0.0.3 1063 | webidl-conversions: 3.0.1 1064 | optional: true 1065 | 1066 | ws@8.18.0: {} 1067 | 1068 | zod-to-json-schema@3.24.1(zod@3.24.1): 1069 | dependencies: 1070 | zod: 3.24.1 1071 | 1072 | zod@3.24.1: {} 1073 | -------------------------------------------------------------------------------- /tools/math.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const multiply = ({ a, b }: { a: number; b: number }): string => { 4 | return `The result of ${a} multiplied by ${b} is ${a * b}.`; 5 | }; 6 | 7 | export const multiplyMetadata = { 8 | name: "multiply", 9 | description: "Call when you need to multiply two numbers together.", 10 | schema: z.object({ 11 | a: z.number(), 12 | b: z.number(), 13 | }), 14 | }; 15 | -------------------------------------------------------------------------------- /tools/prices.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const getEthPriceUsd = async (): Promise => { 4 | const fetchedPrice = await fetch( 5 | "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd", 6 | { 7 | method: "GET", 8 | headers: { 9 | "Content-Type": "application/json", 10 | }, 11 | } 12 | ).catch((error) => { 13 | throw new Error("Error fetching data from the tx service:" + error); 14 | }); 15 | 16 | const ethPriceData = await fetchedPrice.json(); 17 | const ethPriceUsd = ethPriceData?.ethereum?.usd; 18 | 19 | return `The price of 1ETH is ${ethPriceUsd.toLocaleString("en-US")}USD at today's prices.`; 20 | }; 21 | 22 | export const getEthPriceUsdMetadata = { 23 | name: "getEthPriceUsd", 24 | description: 25 | "Call to get the price of ETH in USD.", 26 | schema: z.object({}), 27 | }; 28 | -------------------------------------------------------------------------------- /tools/safe.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import Safe from "@safe-global/protocol-kit"; 3 | import { createPublicClient, formatEther, http } from "viem"; 4 | import { sepolia } from "viem/chains"; 5 | 6 | export const getEthBalance = async ({ address, chainId }) => { 7 | if (chainId !== "1") throw new Error("Chain ID not supported."); 8 | if (!address.startsWith("0x") || address.length !== 42) { 9 | throw new Error("Invalid address."); 10 | } 11 | 12 | const fetchedEthBalance = await fetch( 13 | `https://safe-transaction-mainnet.safe.global/api/v1/safes/${address}/balances/`, 14 | { 15 | method: "GET", 16 | headers: { 17 | "Content-Type": "application/json", 18 | }, 19 | } 20 | ).catch((error) => { 21 | throw new Error("Error fetching data from the tx service:" + error); 22 | }); 23 | 24 | const ethBalanceData = await fetchedEthBalance.json(); 25 | const weiBalance = ethBalanceData.find( 26 | (element) => element?.tokenAddress === null && element?.token === null 27 | )?.balance; 28 | const ethBalance = formatEther(weiBalance); // Convert from wei to eth 29 | 30 | return `The current balance of the Safe Multisig at address ${address} is ${ethBalance} ETH.`; 31 | }; 32 | 33 | export const deployNewSafe = async () => { 34 | const saltNonce = Math.trunc(Math.random() * 10 ** 10).toString(); // Random 10-digit integer 35 | const protocolKit = await Safe.init({ 36 | provider: "https://rpc.ankr.com/eth_sepolia", 37 | signer: process.env.AGENT_PRIVATE_KEY, 38 | predictedSafe: { 39 | safeAccountConfig: { 40 | owners: [process.env.AGENT_ADDRESS as string], 41 | threshold: 1, 42 | }, 43 | safeDeploymentConfig: { 44 | saltNonce, 45 | }, 46 | }, 47 | }); 48 | 49 | const safeAddress = await protocolKit.getAddress(); 50 | 51 | const deploymentTransaction = 52 | await protocolKit.createSafeDeploymentTransaction(); 53 | 54 | const safeClient = await protocolKit.getSafeProvider().getExternalSigner(); 55 | 56 | const transactionHash = await safeClient?.sendTransaction({ 57 | to: deploymentTransaction.to, 58 | value: BigInt(deploymentTransaction.value), 59 | data: deploymentTransaction.data as `0x${string}`, 60 | chain: sepolia, 61 | }); 62 | 63 | const publicClient = createPublicClient({ 64 | chain: sepolia, 65 | transport: http(), 66 | }); 67 | 68 | await publicClient?.waitForTransactionReceipt({ 69 | hash: transactionHash as `0x${string}`, 70 | }); 71 | 72 | return `A new Safe multisig was successfully deployed on Sepolia. You can see it live at https://app.safe.global/home?safe=sep:${safeAddress}. The saltNonce used was ${saltNonce}.`; 73 | }; 74 | 75 | export const getEthBalanceMetadata = { 76 | name: "getEthBalance", 77 | description: 78 | "Call to get the balance in ETH of a Safe Multisig for a given address and chain ID.", 79 | schema: z.object({ 80 | address: z.string(), 81 | chainId: z.enum(["1"]), 82 | }), 83 | }; 84 | 85 | export const deployNewSafeMetadata = { 86 | name: "deployNewSafe", 87 | description: "Call to deploy a new 1-1 Safe Multisig on Sepolia.", 88 | schema: z.object({}), 89 | }; 90 | --------------------------------------------------------------------------------