-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
0g plugin dev #1
Changes from 5 commits
c95c2d3
b32a546
b6bad94
17a374b
83343ee
360e66c
fb72dac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "@ai16z/plugin-0g", | ||
"version": "0.0.1", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@ai16z/eliza": "workspace:*", | ||
"tsup": "^8.3.5", | ||
"@0glabs/0g-ts-sdk": "0.2.1", | ||
"ethers": "^6.0.0" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts", | ||
"test": "vitest" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
import { | ||
Action, | ||
HandlerCallback, | ||
IAgentRuntime, | ||
Memory, | ||
State, | ||
ModelClass, | ||
Content, | ||
ActionExample | ||
} from "@ai16z/eliza"; | ||
import { Indexer, ZgFile, getFlowContract } from '@0glabs/0g-ts-sdk'; | ||
import { ethers } from 'ethers'; | ||
import { composeContext } from "@ai16z/eliza"; | ||
import { generateObject } from "@ai16z/eliza"; | ||
import { promises as fs } from 'fs'; | ||
|
||
|
||
const uploadTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. | ||
|
||
Example response: | ||
\`\`\`json | ||
{ | ||
"filePath": null, | ||
"description": "I want to upload a file" | ||
} | ||
\`\`\` | ||
|
||
{{recentMessages}} | ||
|
||
Extract the user's intention to upload a file from the conversation. Users might express this in various ways, such as: | ||
- "I want to upload a file" | ||
- "upload an image" | ||
- "send a photo" | ||
- "upload" | ||
- "let me share a file" | ||
|
||
If the user provides any specific description of the file, include that as well. | ||
|
||
Respond with a JSON markdown block containing only the extracted values.`; | ||
|
||
export interface UploadContent extends Content { | ||
filePath: string; | ||
} | ||
|
||
function isUploadContent( | ||
_runtime: IAgentRuntime, | ||
content: any | ||
): content is UploadContent { | ||
console.log("Content for upload", content); | ||
return ( | ||
typeof content.filePath === "string" | ||
); | ||
} | ||
|
||
export const zgUpload: Action = { | ||
name: "ZG_UPLOAD", | ||
similes: [ | ||
"UPLOAD_FILE_TO_ZG", | ||
"STORE_FILE_ON_ZG", | ||
"SAVE_FILE_TO_ZG", | ||
"UPLOAD_TO_ZERO_GRAVITY", | ||
"STORE_ON_ZERO_GRAVITY", | ||
"SHARE_FILE_ON_ZG", | ||
"PUBLISH_FILE_TO_ZG" | ||
], | ||
description: "Store data using 0G protocol", | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
const zgIndexerRpc = !!runtime.getSetting("ZEROG_INDEXER_RPC"); | ||
const zgEvmRpc = !!runtime.getSetting("ZEROG_EVM_RPC"); | ||
const zgPrivateKey = !!runtime.getSetting("ZEROG_PRIVATE_KEY"); | ||
const flowAddr = !!runtime.getSetting("ZEROG_FLOW_ADDRESS"); | ||
return zgIndexerRpc && zgEvmRpc && zgPrivateKey && flowAddr; | ||
}, | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State, | ||
options: any, | ||
callback: HandlerCallback | ||
) => { | ||
console.log("ZG_UPLOAD action called"); | ||
if (!state) { | ||
state = (await runtime.composeState(message)) as State; | ||
} else { | ||
state = await runtime.updateRecentMessageState(state); | ||
} | ||
|
||
// Compose upload context | ||
const uploadContext = composeContext({ | ||
state, | ||
template: uploadTemplate, | ||
}); | ||
|
||
// Generate upload content | ||
const content = await generateObject({ | ||
runtime, | ||
context: uploadContext, | ||
modelClass: ModelClass.SMALL, | ||
}); | ||
|
||
// Validate upload content | ||
if (!isUploadContent(runtime, content)) { | ||
console.error("Invalid content for UPLOAD action."); | ||
if (callback) { | ||
callback({ | ||
text: "Unable to process 0G upload request. Invalid content provided.", | ||
content: { error: "Invalid upload content" }, | ||
}); | ||
} | ||
return false; | ||
} | ||
|
||
try { | ||
const zgIndexerRpc = runtime.getSetting("ZEROG_INDEXER_RPC"); | ||
const zgEvmRpc = runtime.getSetting("ZEROG_EVM_RPC"); | ||
const zgPrivateKey = runtime.getSetting("ZEROG_PRIVATE_KEY"); | ||
const flowAddr = runtime.getSetting("ZEROG_FLOW_ADDRESS"); | ||
const filePath = content.filePath; | ||
if (!filePath) { | ||
console.error("File path is missing"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return false; | ||
} | ||
|
||
// Check if file exists and is accessible | ||
try { | ||
await fs.access(filePath); | ||
} catch (error) { | ||
console.error(`File ${filePath} does not exist or is not accessible:`, error); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return false; | ||
} | ||
|
||
const file = await ZgFile.fromFilePath(filePath); | ||
var [tree, err] = await file.merkleTree(); | ||
if (err === null) { | ||
console.log("File Root Hash: ", tree.rootHash()); | ||
} else { | ||
console.log("Error getting file root hash: ", err); | ||
return false; | ||
} | ||
|
||
const provider = new ethers.JsonRpcProvider(zgEvmRpc); | ||
const signer = new ethers.Wallet(zgPrivateKey, provider); | ||
const indexer = new Indexer(zgIndexerRpc); | ||
const flowContract = getFlowContract(flowAddr, signer); | ||
|
||
var [tx, err] = await indexer.upload(file, 0, zgEvmRpc, flowContract); | ||
if (err === null) { | ||
console.log("File uploaded successfully, tx: ", tx); | ||
} else { | ||
console.log("Error uploading file: ", err); | ||
return false; | ||
} | ||
|
||
await file.close(); | ||
|
||
} catch (error) { | ||
console.error("Error getting settings for 0G upload:", error); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. space after |
||
} | ||
}, | ||
examples: [[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "upload my resume.pdf file", | ||
action: "ZG_UPLOAD" | ||
} | ||
} | ||
], [ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "can you help me upload this document.docx?", | ||
action: "ZG_UPLOAD" | ||
} | ||
} | ||
], [ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "I need to upload an image file image.png", | ||
action: "ZG_UPLOAD" | ||
} | ||
} | ||
]] as ActionExample[][], | ||
} as Action; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { Plugin } from "@ai16z/eliza"; | ||
import { zgUpload } from "./actions/upload"; | ||
|
||
export const zgPlugin: Plugin = { | ||
name: "ZG", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should the name here be ZeroG or 0G There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
description: "0G Plugin for Eliza", | ||
actions: [zgUpload], | ||
evaluators: [], | ||
providers: [], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "dist", | ||
"rootDir": ".", | ||
"types": ["node"] | ||
}, | ||
"include": ["src"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { defineConfig } from "tsup"; | ||
|
||
export default defineConfig({ | ||
entry: ["src/index.ts"], | ||
outDir: "dist", | ||
sourcemap: true, | ||
clean: true, | ||
format: ["esm"], // Ensure you're targeting CommonJS | ||
external: [ | ||
"@0glabs/0g-ts-sdk", | ||
// Add other modules you want to externalize | ||
], | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ZERO_GRAVITY
vsZG
, let's make it consistentThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Various of similes make the agent smarter?