Skip to content

Commit

Permalink
Merge branch 'develop' into feat-adapter-qdrant
Browse files Browse the repository at this point in the history
  • Loading branch information
oxf71 authored Jan 17, 2025
2 parents 48ce6f4 + c4d173d commit 048931f
Show file tree
Hide file tree
Showing 13 changed files with 542 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ COINBASE_GENERATED_WALLET_ID= # Not your address but the wallet ID from ge
COINBASE_GENERATED_WALLET_HEX_SEED= # Not your address but the wallet hex seed from generating a wallet through the plugin and calling export
COINBASE_NOTIFICATION_URI= # For webhook plugin the uri you want to send the webhook to for dummy ones use https://webhook.site

# Coinbase AgentKit
COINBASE_AGENT_KIT_NETWORK= # defaults to 'base-sepolia'
CDP_API_KEY_NAME=
CDP_API_KEY_PRIVATE_KEY=

# Coinbase Charity Configuration
IS_CHARITABLE=false # Set to true to enable charity donations
CHARITY_ADDRESS_BASE=0x1234567890123456789012345678901234567890
Expand Down
17 changes: 12 additions & 5 deletions .github/workflows/smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,24 @@ on:
jobs:
smoke-tests:
runs-on: ubuntu-latest
container:
image: node:23-bullseye
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v3
- name: Cache pnpm
uses: actions/cache@v4
with:
version: 9.15.0
path: |
~/.pnpm-store
**/node_modules
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-

- uses: actions/setup-node@v4
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
node-version: "23.3.0"
cache: "pnpm"
version: 9.15.0

- name: Run smoke tests
run: pnpm run smokeTests
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ tsup.config.bundled_*.mjs
.turbo
.cursorrules
.pnpm-store
instructions.md
wallet_data.txt

coverage
.eslintcache
Expand Down
1 change: 1 addition & 0 deletions agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@elizaos/core": "workspace:*",
"@elizaos/plugin-0g": "workspace:*",
"@elizaos/plugin-abstract": "workspace:*",
"@elizaos/plugin-agentkit": "workspace:*",
"@elizaos/plugin-aptos": "workspace:*",
"@elizaos/plugin-birdeye": "workspace:*",
"@elizaos/plugin-coingecko": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion client/src/lib/info.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version": "0.1.8+build.1"}
{"version": "0.1.9-alpha.1"}
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"
}
}
178 changes: 178 additions & 0 deletions packages/plugin-agentkit/src/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
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,
}: GetAgentKitActionsParams): Promise<Action[]> {
const agentkit = await getClient();
const cdpToolkit = new CdpToolkit(agentkit);
const tools = cdpToolkit.getTools();
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();
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: [],
}));
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,
});
}
Loading

0 comments on commit 048931f

Please sign in to comment.