-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add support for GAME framework (#207)
Add support for GAME framework
- Loading branch information
1 parent
30847af
commit 1bd8b67
Showing
7 changed files
with
336 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
OPENAI_API_KEY= | ||
WALLET_PRIVATE_KEY= | ||
RPC_PROVIDER_URL= | ||
VIRTUALS_GAME_API_KEY= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Vercel AI with viem Example | ||
|
||
## Setup | ||
|
||
Copy the `.env.template` and populate with your values. | ||
|
||
``` | ||
cp .env.template .env | ||
``` | ||
|
||
## Usage | ||
|
||
``` | ||
npx ts-node index.ts | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { | ||
ExecutableGameFunctionResponse, | ||
ExecutableGameFunctionStatus, | ||
GameAgent, | ||
GameFunction, | ||
GameWorker, | ||
} from "@virtuals-protocol/game"; | ||
|
||
import { http } from "viem"; | ||
import { createWalletClient } from "viem"; | ||
import { privateKeyToAccount } from "viem/accounts"; | ||
import { mode } from "viem/chains"; | ||
|
||
import { ToolBase, getTools } from "@goat-sdk/core"; | ||
import { PEPE, USDC, erc20 } from "@goat-sdk/plugin-erc20"; | ||
import { sendETH } from "@goat-sdk/wallet-evm"; | ||
import { viem } from "@goat-sdk/wallet-viem"; | ||
import type { JSONSchemaType } from "ajv"; | ||
import { zodToJsonSchema } from "zod-to-json-schema"; | ||
|
||
require("dotenv").config(); | ||
|
||
const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`); | ||
|
||
const walletClient = createWalletClient({ | ||
account: account, | ||
transport: http(process.env.RPC_PROVIDER_URL), | ||
chain: mode, | ||
}); | ||
|
||
(async () => { | ||
const tools: ToolBase[] = await getTools({ | ||
wallet: viem(walletClient), | ||
plugins: [sendETH(), erc20({ tokens: [USDC, PEPE] })], | ||
}); | ||
|
||
const workerFunctions = tools.map((tool) => { | ||
// biome-ignore lint/suspicious/noExplicitAny: Fix types later | ||
const schema = zodToJsonSchema(tool.parameters as any, { | ||
target: "jsonSchema7", | ||
}) as JSONSchemaType<typeof tool.parameters>; | ||
|
||
const properties = Object.keys(schema.properties); | ||
|
||
const args = properties.map((property) => ({ | ||
name: property, | ||
description: schema.properties[property].description ?? "", | ||
})); | ||
|
||
return new GameFunction({ | ||
name: tool.name, | ||
description: tool.description, | ||
args: args, | ||
executable: async (args) => { | ||
try { | ||
const result = await tool.execute(args); | ||
return new ExecutableGameFunctionResponse( | ||
ExecutableGameFunctionStatus.Done, | ||
JSON.stringify(result), | ||
); | ||
} catch (e) { | ||
return new ExecutableGameFunctionResponse( | ||
ExecutableGameFunctionStatus.Failed, | ||
`Failed to execute tool: ${e}`, | ||
); | ||
} | ||
}, | ||
}); | ||
}); | ||
|
||
const onChainWorker = new GameWorker({ | ||
id: "onchain_worker", | ||
name: "Onchain worker", | ||
description: "Worker that executes onchain actions", | ||
functions: [...workerFunctions], | ||
}); | ||
|
||
const agent = new GameAgent(process.env.VIRTUALS_GAME_API_KEY as string, { | ||
name: "Onchain agent", | ||
goal: "Swap 0.01 USDC to MODE", | ||
description: "An agent that executes onchain actions", | ||
workers: [onChainWorker], | ||
}); | ||
|
||
await agent.init(); | ||
|
||
await agent.run(10, { | ||
verbose: true, | ||
}); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "goat-examples-virtuals-game-viem", | ||
"version": "0.2.7", | ||
"description": "", | ||
"private": true, | ||
"scripts": { | ||
"test": "vitest run --passWithNoTests" | ||
}, | ||
"author": "", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@ai-sdk/openai": "^1.0.4", | ||
"@goat-sdk/adapter-vercel-ai": "workspace:*", | ||
"@goat-sdk/core": "workspace:*", | ||
"@goat-sdk/plugin-erc20": "workspace:*", | ||
"@goat-sdk/wallet-evm": "workspace:*", | ||
"@goat-sdk/plugin-kim": "workspace:*", | ||
"@goat-sdk/wallet-viem": "workspace:*", | ||
"@virtuals-protocol/game": "0.1.4", | ||
"ai": "4.0.27", | ||
"ajv": "8.17.1", | ||
"dotenv": "^16.4.5", | ||
"viem": "2.21.49", | ||
"zod": "catalog:", | ||
"zod-to-json-schema": "3.24.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { | ||
ExecutableGameFunctionResponse, | ||
ExecutableGameFunctionStatus, | ||
GameAgent, | ||
GameFunction, | ||
GameWorker, | ||
} from "@virtuals-protocol/game"; | ||
|
||
import { http } from "viem"; | ||
import { createWalletClient } from "viem"; | ||
import { privateKeyToAccount } from "viem/accounts"; | ||
import { mode } from "viem/chains"; | ||
|
||
import { openai } from "@ai-sdk/openai"; | ||
import { getOnChainTools } from "@goat-sdk/adapter-vercel-ai"; | ||
import { MODE, PEPE, USDC, erc20 } from "@goat-sdk/plugin-erc20"; | ||
import { kim } from "@goat-sdk/plugin-kim"; | ||
import { sendETH } from "@goat-sdk/wallet-evm"; | ||
import { viem } from "@goat-sdk/wallet-viem"; | ||
import { generateText } from "ai"; | ||
|
||
require("dotenv").config(); | ||
|
||
const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`); | ||
|
||
const walletClient = createWalletClient({ | ||
account: account, | ||
transport: http(process.env.RPC_PROVIDER_URL), | ||
chain: mode, | ||
}); | ||
|
||
(async () => { | ||
const tools = await getOnChainTools({ | ||
wallet: viem(walletClient), | ||
plugins: [sendETH(), erc20({ tokens: [USDC, MODE] }), kim()], | ||
}); | ||
|
||
const swap = new GameFunction({ | ||
name: "Swap tokens", | ||
description: "Allows you to swap tokens", | ||
args: [ | ||
{ | ||
name: "from", | ||
description: "The token to swap from", | ||
}, | ||
{ | ||
name: "to", | ||
description: "The token to swap to", | ||
}, | ||
{ | ||
name: "amount", | ||
description: "The amount of tokens to swap", | ||
}, | ||
], | ||
executable: async (args) => { | ||
try { | ||
const result = await generateText({ | ||
model: openai("gpt-4o-mini"), | ||
tools: tools, | ||
maxSteps: 10, | ||
prompt: `Swap tokens using Kim protocol in a single hop: ${JSON.stringify(args)}`, | ||
onStepFinish: (event) => { | ||
console.log(event.toolResults); | ||
}, | ||
}); | ||
return new ExecutableGameFunctionResponse(ExecutableGameFunctionStatus.Done, result.text); | ||
} catch (e) { | ||
return new ExecutableGameFunctionResponse( | ||
ExecutableGameFunctionStatus.Failed, | ||
`Failed to execute tool: ${e}`, | ||
); | ||
} | ||
}, | ||
}); | ||
|
||
const onChainWorker = new GameWorker({ | ||
id: "onchain_worker", | ||
name: "Onchain worker", | ||
description: "Worker that executes onchain actions", | ||
functions: [swap], | ||
}); | ||
|
||
const agent = new GameAgent(process.env.VIRTUALS_GAME_API_KEY as string, { | ||
name: "Onchain agent", | ||
goal: "Swap 0.01 USDC to MODE", | ||
description: "An agent that executes onchain actions", | ||
workers: [onChainWorker], | ||
}); | ||
|
||
await agent.init(); | ||
|
||
await agent.run(10, { | ||
verbose: true, | ||
}); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"extends": "../../../tsconfig.base.json", | ||
"compilerOptions": { | ||
"outDir": "dist" | ||
}, | ||
"include": ["index.ts", "toolCalling.ts"], | ||
"exclude": ["node_modules", "dist"] | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.