-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
feat: dad jokes #2092
feat: dad jokes #2092
Changes from all commits
5e9d315
f84e526
0dd9d8d
89ba69f
e29c1b0
e659ad7
6147001
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Dad Joke Plugin for Eliza | ||
|
||
Ask for a dad joke! | ||
|
||
This plugin was solely made for resarech and learning purposes. Feel free to use this as reference! Happy coding ☕️ | ||
|
||
## Contributing | ||
|
||
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details. | ||
|
||
## License | ||
|
||
Built by [@pann0x](https://twitter.com/pann0x) on X. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "@elizaos/plugin-dad-joke", | ||
"version": "0.1.0", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"type": "module", | ||
"scripts": { | ||
"build": "tsup --format esm --dts", | ||
"dev": "tsc -w", | ||
"lint": "eslint src --ext .ts" | ||
}, | ||
"author": "pann0x", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@ai16z/client-direct": "0.1.6-alpha.4", | ||
"@ai16z/eliza": "0.1.6-alpha.4", | ||
"@ai16z/plugin-0g": "0.1.6-alpha.4", | ||
"dotenv": "^16.4.7" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import {Action, IAgentRuntime, Memory, State} from "@ai16z/eliza"; | ||
import { dadJokeActionContent, dadJokeData } from "./types.ts"; | ||
import { dadJokeProvider } from "./provider.ts"; | ||
|
||
export const getDadJokeAction: Action = { | ||
name: "GET_DAD_JOKE", | ||
description: "Retrieves a random dad joke", | ||
similes: [ | ||
"DAD_JOKE", | ||
"JOKE", | ||
], | ||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Tell me a dad joke", | ||
} as dadJokeActionContent, | ||
}, | ||
{ | ||
user: "{{agentName}}", | ||
content: { | ||
text: "Why couldn't the bicycle stand up by itself? It was two tired.", | ||
action: "GET_DAD_JOKE", | ||
}, | ||
}, | ||
|
||
], | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "You got any dad jokes?", | ||
} as dadJokeActionContent, | ||
}, | ||
{ | ||
user: "{{agentName}}", | ||
content: { | ||
text: "What do you call a fake noodle? An impasta.", | ||
action: "GET_DAD_JOKE", | ||
}, | ||
}, | ||
], | ||
], | ||
|
||
validate: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state?: State, | ||
): Promise<boolean> => { | ||
try { | ||
const content = message.content as dadJokeActionContent; | ||
return ( | ||
typeof content.text === "string" && | ||
content.text.toLowerCase().includes("joke") | ||
); | ||
} catch { | ||
return false; | ||
} | ||
}, | ||
|
||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state?: State, | ||
): Promise<dadJokeData> => { | ||
try { | ||
const response = await dadJokeProvider.get(runtime, message, state); | ||
if (!response.success) { | ||
throw new Error(response.error); | ||
} | ||
|
||
return response.data; | ||
} catch (error) { | ||
throw new Error(error instanceof Error ? error.message : "Failed to retrieve dad joke"); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { Evaluator, IAgentRuntime, Memory, State } from "@ai16z/eliza"; | ||
import { dadJokeEvalContent, dadJokeEvalResponse } from "./types.ts"; | ||
|
||
//the evaluator for dad jokes | ||
//validates the response to ensure it is a dad joke | ||
export const dadJokeEvaluator: Evaluator = { | ||
name: "DAD_JOKE_EVALUATOR", | ||
description: "Validates dad joke responses", | ||
similes: [ | ||
"DAD_JOKE_CHECKER", | ||
"JOKE_VALIDATOR", | ||
"DAD_JOKE_RESPONSE_VALIDATOR", | ||
], | ||
examples: [ | ||
{ | ||
context: "Validating complete dad joke response", | ||
messages: [ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "When does a joke become a dad joke? When the punchline becomes apparent.", | ||
}, | ||
}, | ||
], | ||
outcome: "When it becomes a groan-up.", | ||
}, | ||
], | ||
validate: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state?: State, | ||
): Promise<boolean> => { | ||
try { | ||
const content = message.content as dadJokeEvalContent; | ||
return typeof content.text === "string"; | ||
} catch { | ||
return false; | ||
} | ||
}, | ||
|
||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state?: State, | ||
): Promise<dadJokeEvalResponse> => { | ||
try { | ||
const content = message.content as dadJokeEvalContent; | ||
const text = content.text.toLowerCase(); | ||
|
||
//checks for the word "joke" in the response | ||
if (!text.includes("joke")) { | ||
return { | ||
success: false, | ||
response: "Response does not contain the word 'joke'", | ||
}; | ||
} | ||
|
||
return { | ||
success: true, | ||
response: "Dad joke response is valid", | ||
}; | ||
|
||
} catch { | ||
return { | ||
success: false, | ||
response: "Failed to validate dad joke response", | ||
}; | ||
} | ||
}, | ||
alwaysRun: true, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Plugin } from "@ai16z/eliza"; | ||
import { dadJokeProvider, initializeDadJokeProvider } from "./provider.ts"; | ||
import { dadJokeEvaluator } from "./evaluator.ts"; | ||
import { dadJokeConfig } from "./types.ts"; | ||
import { getDadJokeAction } from "./action.ts"; | ||
|
||
export const dadJokePlugin: Plugin = { | ||
name: "Dad Joke", | ||
description: "Dad Joke Plugin for Eliza", | ||
actions: [ | ||
getDadJokeAction | ||
], | ||
providers: [dadJokeProvider], | ||
evaluators: [dadJokeEvaluator], | ||
//rest of the plugin | ||
} | ||
|
||
export const initializeDadJoke = (config: dadJokeConfig): void => { | ||
initializeDadJokeProvider(config); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { IAgentRuntime, Memory, State, Provider } from "@ai16z/eliza"; | ||
import { dadJokeProviderResponse, dadJokeData, dadJokeConfig} from "./types.ts"; | ||
|
||
let providerConfig: dadJokeConfig; | ||
|
||
export const dadJokeProvider: Provider = { | ||
get: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state?: State, | ||
): Promise<dadJokeProviderResponse> => { | ||
try { | ||
if (!providerConfig?.provider?.baseUrl) { | ||
throw new Error("Dad Joke API url is required"); | ||
} | ||
|
||
const baseUrl = | ||
providerConfig.provider.baseUrl || | ||
"https://icanhazdadjoke.com"; | ||
Comment on lines
+13
to
+19
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. There appears to be contradictory logic in the URL handling. The code first checks that
This will make the intended behavior more clear and eliminate unreachable code paths. Spotted by Graphite Reviewer |
||
|
||
// Fetch dad joke | ||
const response = await fetch(baseUrl, { | ||
headers: { | ||
Accept: "application/json", | ||
}, | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(`API request failed: ${response.statusText}`); | ||
} | ||
|
||
const data = await response.json(); | ||
|
||
// Transform API response to dadJokeData | ||
const dadJokeData: dadJokeData = { | ||
joke: data.joke, | ||
}; | ||
|
||
return { | ||
success: true, | ||
data: dadJokeData, | ||
}; | ||
} catch (error) { | ||
return { | ||
success: false, | ||
error: error instanceof Error ? error.message : "Failed to retrieve dad joke", | ||
}; | ||
} | ||
} | ||
} | ||
|
||
export const initializeDadJokeProvider = (config: dadJokeConfig): void => { | ||
providerConfig = config; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Content } from '@ai16z/eliza'; | ||
|
||
export interface dadJokeConfig { | ||
provider: { | ||
apiKey: string; | ||
baseUrl?: string; | ||
options?: string; | ||
}; | ||
} | ||
Comment on lines
+3
to
+9
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. The Spotted by Graphite Reviewer |
||
|
||
export interface dadJokeData { | ||
joke: string; | ||
//image?: ; | ||
} | ||
|
||
export interface dadJokeActionContent extends Content { | ||
text: string; | ||
} | ||
|
||
export interface dadJokeEvalContent extends Content { | ||
text: string; | ||
} | ||
|
||
export interface dadJokeEvalResponse { | ||
success: boolean; | ||
response: string; | ||
} | ||
|
||
export interface dadJokeProviderResponse { | ||
success: boolean; | ||
data?: dadJokeData; | ||
error?: string; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"extends": "../core/tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "dist", | ||
"rootDir": "./src" | ||
}, | ||
"include": [ | ||
"src" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
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: [ | ||
"dotenv", // Externalize dotenv to prevent bundling | ||
"fs", // Externalize fs to use Node.js built-in module | ||
"path", // Externalize other built-ins if necessary | ||
"@reflink/reflink", | ||
"@node-llama-cpp", | ||
"https", | ||
"http", | ||
"agentkeepalive", | ||
// 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.
The example outcome appears to be mismatched with the setup joke. The setup asks "When does a joke become a dad joke? When the punchline becomes apparent" but the outcome shows "When it becomes a groan-up". For consistency, the outcome should be
"When the punchline becomes apparent"
to match the setup joke's punchline.Spotted by Graphite Reviewer
Is this helpful? React 👍 or 👎 to let us know.