Skip to content

Commit

Permalink
Merge pull request #5 from sweetmantech/sweets/agentkit
Browse files Browse the repository at this point in the history
I add files for plugin-agentkit
  • Loading branch information
sweetmantech authored Jan 14, 2025
2 parents d55c86c + 116606e commit 3252d84
Show file tree
Hide file tree
Showing 9 changed files with 502 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ tsup.config.bundled_*.mjs
.turbo
.cursorrules
.pnpm-store
instructions.md

coverage
.eslintcache
Expand Down
123 changes: 123 additions & 0 deletions packages/plugin-agentkit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# @elizaos/plugin-agentkit

AgentKit plugin for Eliza that enables interaction with CDP AgentKit tools for NFT and token management.

## Setup

1. Install dependencies:

```bash
pnpm install
```

2. Configure environment variables:

```env
CDP_API_KEY_NAME=your_key_name
CDP_API_KEY_PRIVATE_KEY=your_private_key
```

3. Add the plugin to your character configuration:

```json
{
"plugins": ["@ai16z/plugin-agentkit"],
"settings": {
"secrets": {
"CDP_API_KEY_NAME": "your_key_name",
"CDP_API_KEY_PRIVATE_KEY": "your_private_key",
"networkId": "base-sepolia"
}
}
}
```

## Available Tools

The plugin provides access to the following CDP AgentKit tools:

- `GET_WALLET_DETAILS`: Get wallet information
- `DEPLOY_NFT`: Deploy a new NFT collection
- `DEPLOY_TOKEN`: Deploy a new token
- `GET_BALANCE`: Check token or NFT balance
- `MINT_NFT`: Mint NFTs from a collection
- `REGISTER_BASENAME`: Register a basename for NFTs
- `REQUEST_FAUCET_FUNDS`: Request testnet funds
- `TRADE`: Execute trades
- `TRANSFER`: Transfer tokens or NFTs
- `WOW_BUY_TOKEN`: Buy WOW tokens
- `WOW_SELL_TOKEN`: Sell WOW tokens
- `WOW_CREATE_TOKEN`: Create new WOW tokens

## Usage Examples

1. Get wallet details:

```
Can you show me my wallet details?
```

2. Deploy an NFT collection:

```
Deploy a new NFT collection called "Music NFTs" with symbol "MUSIC"
```

3. Create a token:

```
Create a new WOW token called "Artist Token" with symbol "ART"
```

4. Check balance:

```
What's my current balance?
```

## Development

1. Build the plugin:

```bash
pnpm build
```

2. Run in development mode:

```bash
pnpm dev
```

## Dependencies

- @elizaos/core
- @coinbase/cdp-agentkit-core
- @coinbase/cdp-langchain
- @langchain/core

## Network Support

The plugin currently supports the following networks:

- Base Sepolia (default)
- Base Mainnet

Configure the network using the `networkId` setting in your character configuration.

## Troubleshooting

1. If tools are not being triggered:

- Verify CDP API key configuration
- Check network settings
- Ensure character configuration includes the plugin

2. Common errors:
- "Cannot find package": Make sure dependencies are installed
- "API key not found": Check environment variables
- "Network error": Verify network configuration

## License

MIT
18 changes: 18 additions & 0 deletions packages/plugin-agentkit/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@elizaos/plugin-agentkit",
"version": "0.0.1",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",
"dependencies": {
"@elizaos/core": "workspace:*",
"@coinbase/cdp-agentkit-core": "^0.0.10",
"@coinbase/cdp-langchain": "^0.0.11",
"@langchain/core": "^0.3.27",
"tsup": "8.3.5"
},
"scripts": {
"build": "tsup --format esm --dts",
"dev": "tsup --format esm --dts --watch"
}
}
183 changes: 183 additions & 0 deletions packages/plugin-agentkit/src/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import {
type Action,
generateText,
type HandlerCallback,
type IAgentRuntime,
type Memory,
ModelClass,
type State,
composeContext,
generateObject,
} from "@elizaos/core";
import { CdpAgentkit } from "@coinbase/cdp-agentkit-core";
import { CdpToolkit, type Tool } from "@coinbase/cdp-langchain";

type GetAgentKitActionsParams = {
getClient: () => Promise<CdpAgentkit>;
config?: {
networkId?: string;
};
};

/**
* Get all AgentKit actions
*/
export async function getAgentKitActions({
getClient,
config,
}: GetAgentKitActionsParams): Promise<Action[]> {
const agentkit = await getClient();
const cdpToolkit = new CdpToolkit(agentkit);
const tools = cdpToolkit.getTools();
console.log("SWEETMAN------------------------");

const actions = tools.map((tool: Tool) => ({
name: tool.name.toUpperCase(),
description: tool.description,
similes: [],
validate: async () => true,
handler: async (
runtime: IAgentRuntime,
message: Memory,
state: State | undefined,
options?: Record<string, unknown>,
callback?: HandlerCallback
): Promise<boolean> => {
try {
const client = await getClient();
console.log("SWEETMAN CLIENT------------------------", client);
let currentState =
state ?? (await runtime.composeState(message));
currentState =
await runtime.updateRecentMessageState(currentState);

const parameterContext = composeParameterContext(
tool,
currentState
);
const parameters = await generateParameters(
runtime,
parameterContext,
tool
);

const result = await executeToolAction(
tool,
parameters,
client
);

const responseContext = composeResponseContext(
tool,
result,
currentState
);
const response = await generateResponse(
runtime,
responseContext
);

callback?.({ text: response, content: result });
return true;
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : String(error);
callback?.({
text: `Error executing action ${tool.name}: ${errorMessage}`,
content: { error: errorMessage },
});
return false;
}
},
examples: [],
}));
console.log("SWEETMAN ACTIONS------------------------", actions);
return actions;
}

async function executeToolAction(
tool: Tool,
parameters: any,
client: CdpAgentkit
): Promise<unknown> {
const toolkit = new CdpToolkit(client);
const tools = toolkit.getTools();
const selectedTool = tools.find((t) => t.name === tool.name);

if (!selectedTool) {
throw new Error(`Tool ${tool.name} not found`);
}

return await selectedTool.call(parameters);
}

function composeParameterContext(tool: any, state: State): string {
const contextTemplate = `{{recentMessages}}
Given the recent messages, extract the following information for the action "${tool.name}":
${tool.description}
`;
return composeContext({ state, template: contextTemplate });
}

async function generateParameters(
runtime: IAgentRuntime,
context: string,
tool: Tool
): Promise<unknown> {
const { object } = await generateObject({
runtime,
context,
modelClass: ModelClass.LARGE,
schema: tool.schema,
});

return object;
}

function composeResponseContext(
tool: Tool,
result: unknown,
state: State
): string {
const responseTemplate = `
# Action Examples
{{actionExamples}}
# Knowledge
{{knowledge}}
# Task: Generate dialog and actions for the character {{agentName}}.
About {{agentName}}:
{{bio}}
{{lore}}
{{providers}}
{{attachments}}
# Capabilities
Note that {{agentName}} is capable of reading/seeing/hearing various forms of media, including images, videos, audio, plaintext and PDFs. Recent attachments have been included above under the "Attachments" section.
The action "${tool.name}" was executed successfully.
Here is the result:
${JSON.stringify(result)}
{{actions}}
Respond to the message knowing that the action was successful and these were the previous messages:
{{recentMessages}}
`;
return composeContext({ state, template: responseTemplate });
}

async function generateResponse(
runtime: IAgentRuntime,
context: string
): Promise<string> {
return generateText({
runtime,
context,
modelClass: ModelClass.LARGE,
});
}
19 changes: 19 additions & 0 deletions packages/plugin-agentkit/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Plugin } from "@elizaos/core";
import { walletProvider, getClient } from "./provider";
import { getAgentKitActions } from "./actions";

export const agentKitPlugin: Plugin = {
name: "[AgentKit] Integration",
description: "AgentKit integration plugin",
providers: [walletProvider],
evaluators: [],
services: [],
actions: await getAgentKitActions({
getClient,
config: {
networkId: "base-sepolia",
},
}),
};

export default agentKitPlugin;
22 changes: 22 additions & 0 deletions packages/plugin-agentkit/src/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { type Provider, type IAgentRuntime } from "@elizaos/core";
import { CdpAgentkit } from "@coinbase/cdp-agentkit-core";

export async function getClient(): Promise<CdpAgentkit> {
const config = {
networkId: "base-sepolia",
};
return await CdpAgentkit.configureWithWallet(config);
}

export const walletProvider: Provider = {
async get(runtime: IAgentRuntime): Promise<string | null> {
try {
const client = await getClient();
const address = (await (client as any).wallet.addresses)[0].id;
return `AgentKit Wallet Address: ${address}`;
} catch (error) {
console.error("Error in AgentKit provider:", error);
return null;
}
},
};
9 changes: 9 additions & 0 deletions packages/plugin-agentkit/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "../core/tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "./src",
"declaration": true
},
"include": ["src"]
}
Loading

0 comments on commit 3252d84

Please sign in to comment.