Skip to content

Commit

Permalink
Merge pull request #37 from daydreamsai/updates
Browse files Browse the repository at this point in the history
fix: Updates
  • Loading branch information
ponderingdemocritus authored Jan 24, 2025
2 parents 44d0b9e + 274db30 commit df92352
Show file tree
Hide file tree
Showing 26 changed files with 648 additions and 333 deletions.
234 changes: 234 additions & 0 deletions examples/example-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/**
* Example demonstrating a Twitter bot using the Daydreams package.
* This bot can:
* - Monitor Twitter mentions and auto-reply
* - Generate autonomous thoughts and tweet them
* - Maintain conversation memory using ChromaDB
* - Process inputs through a character-based personality
*/

import { Orchestrator } from "../packages/core/src/core/orchestrator";
import { HandlerRole } from "../packages/core/src/core/types";
import { RoomManager } from "../packages/core/src/core/room-manager";
import { ChromaVectorDB } from "../packages/core/src/core/vector-db";
import { Processor } from "../packages/core/src/core/processor";
import { LLMClient } from "../packages/core/src/core/llm-client";
import { LogLevel } from "../packages/core/src/core/types";
import chalk from "chalk";
import { defaultCharacter } from "../packages/core/src/core/character";
import { Consciousness } from "../packages/core/src/core/consciousness";
import { z } from "zod";
import readline from "readline";

async function main() {
const loglevel = LogLevel.INFO;
// Initialize core dependencies
const vectorDb = new ChromaVectorDB("twitter_agent", {
chromaUrl: "http://localhost:8000",
logLevel: loglevel,
});

await vectorDb.purge(); // Clear previous session data

const roomManager = new RoomManager(vectorDb);

const llmClient = new LLMClient({
model: "anthropic/claude-3-5-sonnet-latest", // Using a known supported model
temperature: 0.3,
});

// Initialize processor with default character personality
const processor = new Processor(
vectorDb,
llmClient,
defaultCharacter,
loglevel
);

// Initialize core system
const orchestrator = new Orchestrator(roomManager, vectorDb, processor, {
level: loglevel,
enableColors: true,
enableTimestamp: true,
});

// Initialize autonomous thought generation
const consciousness = new Consciousness(llmClient, roomManager, {
intervalMs: 300000, // Think every 5 minutes
minConfidence: 0.7,
logLevel: loglevel,
});

orchestrator.registerIOHandler({
name: "fetchGithubIssues",
role: HandlerRole.ACTION,
schema: z.object({
repo: z.string(),
}),
handler: async (payload) => {
// 1. Fetch some info from GitHub
// 2. Return the fetched data so it can be processed as "new input"
// to the next step in the chain.
const { repo } = payload as { repo: string };
const response = await fetch(
`https://api.github.com/repos/${repo}/issues`
);
const issues = await response.json();
// The data returned here is fed back into the Orchestrator's chain flow.
return issues;
},
});

orchestrator.registerIOHandler({
name: "universalApiCall",
role: HandlerRole.ACTION,
// The agent must fill out these fields to make a valid request
schema: z
.object({
method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
url: z.string().url(),
headers: z.record(z.string()).optional(),
body: z.union([z.string(), z.record(z.any())]).optional(),
})
.describe(
"Use this to fetch data from an API. It should include the method, url, headers, and body."
),
handler: async (payload) => {
const { method, url, headers, body } = payload as {
method: string;
url: string;
headers?: Record<string, string>;
body?: any;
};

// Make the HTTP call
const response = await fetch(url, {
method,
headers: {
"Content-Type": "application/json",
...headers,
},
body: body ? JSON.stringify(body) : undefined,
});

// Return JSON or text
let responseData;
try {
responseData = await response.json();
} catch {
responseData = await response.text();
}

// Return the result so the agent can process it further
return {
status: response.status,
statusText: response.statusText,
data: responseData,
};
},
});

orchestrator.registerIOHandler({
name: "user_chat",
role: HandlerRole.INPUT,
// This schema describes what a user message looks like
schema: z.object({
content: z.string(),
userId: z.string().optional(),
}),
// For "on-demand" input handlers, the `handler()` can be a no-op.
// We'll call it manually with data, so we don't need an interval.
handler: async (payload) => {
// We simply return the payload so the Orchestrator can process it
return payload;
},
});

orchestrator.registerIOHandler({
name: "ui_chat_reply",
role: HandlerRole.OUTPUT,
schema: z.object({
userId: z.string().optional(),
message: z.string(),
}),
handler: async (payload) => {
const { userId, message } = payload as {
userId?: string;
message: string;
};

// In a real app, you might push this to a WebSocket, or store it in a DB,
// or just log it to the console:
console.log(`Reply to user ${userId ?? "??"}: ${message}`);

// No need to return anything if it's a final "output"
},
});

// Set up readline interface
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

// Function to prompt for user input
const promptUser = () => {
rl.question(
'Enter your message (or "exit" to quit): ',
async (userMessage) => {
if (userMessage.toLowerCase() === "exit") {
rl.close();
process.exit(0);
}

// Dispatch the message
const userId = "console-user";
const outputs: any = await orchestrator.dispatchToInput("user_chat", {
content: userMessage,
userId,
});

// Now `outputs` is an array of suggestions with role=output that got triggered
if (outputs && outputs.length > 0) {
for (const out of outputs) {
if (out.name === "ui_chat_reply") {
// Our "ui_chat_reply" handler data has { userId, message }
console.log(chalk.green(`AI says: ${out.data.message}`));
}
}
}

// Continue prompting
promptUser();
}
);
};

// Start the prompt loop
console.log(chalk.cyan("🤖 Bot is now running and monitoring Twitter..."));
console.log(chalk.cyan("You can type messages in the console."));
console.log(chalk.cyan('Type "exit" to quit'));
promptUser();

// Handle graceful shutdown
process.on("SIGINT", async () => {
console.log(chalk.yellow("\n\nShutting down..."));

// Clean up resources
await consciousness.stop();
orchestrator.removeIOHandler("twitter_mentions");
orchestrator.removeIOHandler("consciousness_thoughts");
orchestrator.removeIOHandler("twitter_reply");
orchestrator.removeIOHandler("twitter_thought");
rl.close();

console.log(chalk.green("✅ Shutdown complete"));
process.exit(0);
});
}

// Run the example
main().catch((error) => {
console.error(chalk.red("Fatal error:"), error);
process.exit(1);
});
2 changes: 1 addition & 1 deletion examples/example-goal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import * as readline from "readline";
import chalk from "chalk";

import { ChromaVectorDB } from "../packages/core/src/core/vector-db";
import { GoalStatus, LogLevel } from "../packages/core/src/types";
import { GoalStatus, LogLevel } from "../packages/core/src/core/types";
import { fetchGraphQL } from "../packages/core/src/core/providers";
import { StarknetChain } from "../packages/core/src/core/chains/starknet";
import { z } from "zod";
Expand Down
28 changes: 19 additions & 9 deletions examples/example-twitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@
*/

import { Orchestrator } from "../packages/core/src/core/orchestrator";
import { TwitterClient } from "../packages/core/src/io/twitter";
import { HandlerRole } from "../packages/core/src/core/types";
import { TwitterClient } from "../packages/core/src/core/io/twitter";
import { RoomManager } from "../packages/core/src/core/room-manager";
import { ChromaVectorDB } from "../packages/core/src/core/vector-db";
import { Processor } from "../packages/core/src/core/processor";
import { LLMClient } from "../packages/core/src/core/llm-client";
import { env } from "../packages/core/src/core/env";
import { LogLevel } from "../packages/core/src/types";
import { LogLevel } from "../packages/core/src/core/types";
import chalk from "chalk";
import { defaultCharacter } from "../packages/core/src/core/character";
import { Consciousness } from "../packages/core/src/core/consciousness";
import { z } from "zod";
import readline from "readline";

async function main() {
const loglevel = LogLevel.INFO;
Expand Down Expand Up @@ -69,10 +71,10 @@ async function main() {
logLevel: loglevel,
});

// Register input handler for Twitter mentions
// Register input handler for Twitter mentions
core.registerIOHandler({
name: "twitter_mentions",
role: "input",
role: HandlerRole.INPUT,
handler: async () => {
console.log(chalk.blue("🔍 Checking Twitter mentions..."));
// Create a static mentions input handler
Expand All @@ -97,7 +99,7 @@ async function main() {
// Register input handler for autonomous thoughts
core.registerIOHandler({
name: "consciousness_thoughts",
role: "input",
role: HandlerRole.INPUT,
handler: async () => {
console.log(chalk.blue("🧠 Generating thoughts..."));
const thought = await consciousness.start();
Expand All @@ -120,7 +122,7 @@ async function main() {
// Register output handler for posting thoughts to Twitter
core.registerIOHandler({
name: "twitter_thought",
role: "output",
role: HandlerRole.OUTPUT,
handler: async (data: unknown) => {
const thoughtData = data as { content: string };

Expand All @@ -142,7 +144,7 @@ async function main() {
// Register output handler for Twitter replies
core.registerIOHandler({
name: "twitter_reply",
role: "output",
role: HandlerRole.OUTPUT,
handler: async (data: unknown) => {
const tweetData = data as { content: string; inReplyTo: string };

Expand All @@ -161,9 +163,16 @@ async function main() {
),
});

// Start monitoring
// Set up readline interface
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

// Start the prompt loop
console.log(chalk.cyan("🤖 Bot is now running and monitoring Twitter..."));
console.log(chalk.cyan("Press Ctrl+C to stop"));
console.log(chalk.cyan("You can type messages in the console."));
console.log(chalk.cyan('Type "exit" to quit'));

// Handle graceful shutdown
process.on("SIGINT", async () => {
Expand All @@ -175,6 +184,7 @@ async function main() {
core.removeIOHandler("consciousness_thoughts");
core.removeIOHandler("twitter_reply");
core.removeIOHandler("twitter_thought");
rl.close();

console.log(chalk.green("✅ Shutdown complete"));
process.exit(0);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"goal": "bun run examples/example-goal.ts",
"task": "bun run examples/example-basic.ts",
"twitter": "bun run examples/example-twitter.ts",
"api": "bun run examples/example-api.ts",
"test": "bun run packages/core",
"build": "pnpm --dir packages/core run build",
"release": "pnpm build && pnpm prettier && npx lerna publish --no-private --force-publish",
Expand Down
9 changes: 5 additions & 4 deletions packages/core/src/core/chain-of-thought.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import type {
Goal,
HorizonType,
RefinedGoal,
} from "../types";
VectorDB,
Output,
} from "./types";
import { Logger } from "./logger";
import { EventEmitter } from "events";
import { GoalManager } from "./goal-manager";
import { StepManager, type Step, type StepType } from "./step-manager";
import { LogLevel } from "../types";

import {
calculateImportance,
determineEmotions,
Expand All @@ -19,10 +21,9 @@ import {
injectTags,
} from "./utils";
import Ajv from "ajv";
import type { VectorDB } from "../types";
import { zodToJsonSchema } from "zod-to-json-schema";
import { z } from "zod";
import type { Output } from "../types";
import { LogLevel } from "./types";

const ajv = new Ajv();

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/core/chains/evm.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ethers } from "ethers";
import type { IChain } from "../../types";
import type { IChain } from "../types";

/**
* Configuration options for initializing an EVM chain connection
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/core/chains/solana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import type { IChain } from "../../types";
import type { IChain } from "../types";
import bs58 from "bs58";

export interface SolanaChainConfig {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/core/chains/starknet.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RpcProvider, Account, type Call, CallData } from "starknet";
import type { IChain } from "../../types";
import type { IChain } from "../types";

/**
* Configuration options for initializing a Starknet chain connection
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/core/character.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Character } from "../types";
import type { Character } from "./types";

// Example character configuration
export const defaultCharacter: Character = {
Expand Down
Loading

0 comments on commit df92352

Please sign in to comment.