From fcb70a62f6e9bd3a12056d06cf2ae2acab91c9f9 Mon Sep 17 00:00:00 2001 From: Cheelax Date: Fri, 24 Jan 2025 15:45:21 +0100 Subject: [PATCH 01/12] Update core exports and package name --- .vscode/settings.json | 8 + clients/example-ui/package.json | 2 +- clients/example-ui/src/App.tsx | 108 +++--- clients/example-ui/src/main.tsx | 18 +- clients/example-ui/tsconfig.json | 37 +- clients/example-ui/tsconfig.node.json | 34 +- examples/example-zidle.ts | 485 ++++++++++++++++++++++++++ packages/core/package.json | 103 +++--- packages/core/src/core/vector-db.ts | 8 +- packages/core/src/index.ts | 5 +- 10 files changed, 653 insertions(+), 155 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 examples/example-zidle.ts diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..f4a39090 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "editor.formatOnSave": true, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "prettier.singleQuote": false, + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/clients/example-ui/package.json b/clients/example-ui/package.json index 892ffe5a..521e6f4a 100644 --- a/clients/example-ui/package.json +++ b/clients/example-ui/package.json @@ -27,7 +27,7 @@ "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", "three": "^0.172.0", - "@daydreamsai/core": "workspace:*" + "@daydreams/core": "workspace:*" }, "devDependencies": { "@eslint/js": "^9.17.0", diff --git a/clients/example-ui/src/App.tsx b/clients/example-ui/src/App.tsx index 15204dfc..94706780 100644 --- a/clients/example-ui/src/App.tsx +++ b/clients/example-ui/src/App.tsx @@ -1,72 +1,70 @@ import { AppSidebar } from "@/components/app-sidebar"; import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, - BreadcrumbPage, - BreadcrumbSeparator, + Breadcrumb, + BreadcrumbItem, + BreadcrumbLink, + BreadcrumbList, } from "@/components/ui/breadcrumb"; import { Separator } from "@/components/ui/separator"; import { - SidebarInset, - SidebarProvider, - SidebarTrigger, + SidebarInset, + SidebarProvider, + SidebarTrigger, } from "@/components/ui/sidebar"; import { useState } from "react"; +//import { ChatBox } from "@/components/chat/chatbox"; +//import { useZidle } from "./hooks/use-zidle"; function App() { - const [message, setMessage] = useState(""); + const [message, setMessage] = useState(""); + //const { messages, sendMessage } = useZidle(); - const handleSubmit = () => { - // Handle message submission here - console.log("Message submitted:", message); - setMessage(""); // Clear input after submit - }; + const handleSubmit = async () => { + if (!message.trim()) return; - return ( - - - -
-
- - - - - - Home - - {/* + const content = message; + console.log(content); + setMessage(""); // Clear input + //await sendMessage(content); + }; + + return ( + + + +
+
+ + + + + + + Home + + + {/* Data Fetching */} - - -
-
-
-
-
- setMessage(e.target.value)} - placeholder="Type your message here..." - className="flex-1 px-4 py-2 rounded-lg border border-border bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" - /> - -
-
-
-
-
- ); +
+
+
+
+
+ {/* setMessage(e.target.value)} + /> */} +
+
+
+ ); } export default App; diff --git a/clients/example-ui/src/main.tsx b/clients/example-ui/src/main.tsx index bef5202a..1e008043 100644 --- a/clients/example-ui/src/main.tsx +++ b/clients/example-ui/src/main.tsx @@ -1,10 +1,10 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.tsx' +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./index.css"; +import App from "./App.tsx"; -createRoot(document.getElementById('root')!).render( - - - , -) +createRoot(document.getElementById("root")!).render( + + + +); diff --git a/clients/example-ui/tsconfig.json b/clients/example-ui/tsconfig.json index fec8c8e5..eee3470a 100644 --- a/clients/example-ui/tsconfig.json +++ b/clients/example-ui/tsconfig.json @@ -1,13 +1,28 @@ { - "files": [], - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ], - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - } - } + "compilerOptions": { + "target": "es5", + "useDefineForClassFields": true, + "lib": ["dom", "dom.iterable", "esnext"], + "module": "esnext", + "skipLibCheck": true, + "moduleResolution": "node", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/clients/example-ui/tsconfig.node.json b/clients/example-ui/tsconfig.node.json index 81d9d2d8..26063d85 100644 --- a/clients/example-ui/tsconfig.node.json +++ b/clients/example-ui/tsconfig.node.json @@ -1,28 +1,10 @@ { - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "target": "ES2022", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true, - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["vite.config.ts"] + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] } diff --git a/examples/example-zidle.ts b/examples/example-zidle.ts new file mode 100644 index 00000000..10cadea1 --- /dev/null +++ b/examples/example-zidle.ts @@ -0,0 +1,485 @@ +import { LLMClient } from "../packages/core/src/core/llm-client"; +import { ChainOfThought } from "../packages/core/src/core/chain-of-thought"; +import { PROVIDER_GUIDE, ZIDLE_CONTEXT } from "./zidle/zidle"; +import chalk from "chalk"; +import { JSONSchemaType } from "ajv"; +import { ChromaVectorDB } from "../packages/core/src/core/vector-db"; +import { GoalStatus, LogLevel } from "../packages/core/src/types"; +import { z } from "zod"; +import { StarknetChain } from "../packages/core/src/core/chains/starknet"; +import { fetchGraphQL } from "../packages/core/src/core/providers"; +import { env } from "../packages/core/src/core/env"; +import readline from "readline"; + +/** + * Helper function to get user input from CLI + */ +async function getCliInput(prompt: string): Promise { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + formatDialog("zIdle", prompt); + return new Promise((resolve) => { + rl.question(chalk.green("\n๐Ÿ‘ค You: "), (answer) => { + rl.close(); + resolve(answer); + }); + }); +} + +/** + * Helper function to format goal status with colored icons + */ +function printGoalStatus(status: GoalStatus): string { + const colors: Record = { + pending: chalk.yellow("โณ PENDING"), + active: chalk.blue("โ–ถ๏ธ ACTIVE"), + completed: chalk.green("โœ… COMPLETED"), + failed: chalk.red("โŒ FAILED"), + ready: chalk.cyan("๐ŸŽฏ READY"), + blocked: chalk.red("๐Ÿšซ BLOCKED"), + }; + return colors[status] || status; +} + +// Add a helper function to format console messages as dialog +function formatDialog( + speaker: "zIdle" | "user" | "system", + message: string +): void { + switch (speaker) { + case "zIdle": + console.log(chalk.blue(`\n๐Ÿค– zIdle: ${message}`)); + break; + case "user": + console.log(chalk.green(`\n๐Ÿ‘ค You: ${message}`)); + break; + case "system": + console.log(chalk.gray(`\n๐Ÿ”ง System: ${message}`)); + break; + } +} + +async function main() { + // Initialize LLM client + const llmClient = new LLMClient({ + model: "anthropic/claude-3-5-sonnet-latest", //"deepseek/deepseek-r1", //"anthropic/claude-3.5-haiku-20241022:beta" + }); + + const memory = new ChromaVectorDB("agent_memory", { + chromaUrl: "http://localhost:8000", + logLevel: LogLevel.WARN, + }); + await memory.purge(); // Clear previous session data + + const starknetChain = new StarknetChain({ + rpcUrl: env.STARKNET_RPC_URL, + address: env.STARKNET_ADDRESS, + privateKey: env.STARKNET_PRIVATE_KEY, + }); + + // Load initial context documents + await memory.storeDocument({ + title: "Game Rules", + content: ZIDLE_CONTEXT, + category: "rules", + tags: ["game-mechanics", "rules"], + lastUpdated: new Date(), + }); + + await memory.storeDocument({ + title: "Provider Guide", + content: PROVIDER_GUIDE, + category: "actions", + tags: ["actions", "provider-guide"], + lastUpdated: new Date(), + }); + + // Initialize the main reasoning engine + const dreams = new ChainOfThought( + llmClient, + memory, + { + worldState: ZIDLE_CONTEXT, + providerContext: PROVIDER_GUIDE, + }, + { logLevel: LogLevel.DEBUG } + ); + + dreams.registerOutput({ + name: "EXECUTE_READ", + handler: async (data: any) => { + const result = await starknetChain.read(data.payload); + return `Transaction: ${JSON.stringify(result, null, 2)}`; + }, + schema: z + .object({ + contractAddress: z + .string() + .describe("The address of the contract to read from"), + entrypoint: z + .string() + .describe("The entrypoint to call on the contract"), + calldata: z + .array(z.union([z.number(), z.string()])) + .describe("The calldata to pass to the entrypoint"), + }) + .describe( + "The payload to use to call, never include slashes or comments" + ), + }); + + dreams.registerOutput({ + name: "EXECUTE_TRANSACTION", + handler: async (data: any) => { + const result = await starknetChain.write(data.payload); + return `Transaction: ${JSON.stringify(result, null, 2)}`; + }, + schema: z + .object({ + contractAddress: z + .string() + .describe( + "The address of the contract to execute the transaction on" + ), + entrypoint: z + .string() + .describe("The entrypoint to call on the contract"), + calldata: z + .array(z.union([z.number(), z.string()])) + .describe("The calldata to pass to the entrypoint"), + }) + .describe( + "The payload to execute the transaction, never include slashes or comments" + ), + }); + + dreams.registerOutput({ + name: "GRAPHQL_FETCH", + handler: async (data: any) => { + console.log("[GRAPHQL_FETCH handler] data", data); + const { query, variables } = data.payload ?? {}; + const result = await fetchGraphQL( + env.GRAPHQL_URL + "/graphql", + query, + variables + ); + const resultStr = [ + `query: ${query}`, + `result: ${JSON.stringify(result, null, 2)}`, + ].join("\n\n"); + return `GraphQL data fetched successfully: ${resultStr}`; + }, + schema: z + .object({ + query: z + .string() + .describe( + `query ZidleMinerModels { zidleMinerModels(where: { token_id: "0x10" }) {totalCount edges { node { resource_type xp } } } }` + ), + }) + .describe( + "The payload to fetch data from the zIdle GraphQL API, never include slashes or comments" + ), + }); + + // Set up event logging + + // Thought process events + dreams.on("step", (step) => { + if (step.type === "system") { + formatDialog("system", step.content); + } else { + formatDialog("zIdle", `Thinking: ${step.content}`); + } + }); + + // Uncomment to log token usage + // llmClient.on("trace:tokens", ({ input, output }) => { + // console.log("\n๐Ÿ’ก Tokens used:", { input, output }); + // }); + + // Action execution events + dreams.on("action:start", (action) => { + formatDialog("zIdle", `I'm going to ${action.type}...`); + }); + + dreams.on("action:complete", ({ action, result }) => { + formatDialog("zIdle", `I've completed ${action.type}. Result: ${result}`); + }); + + dreams.on("action:error", ({ action, error }) => { + formatDialog("system", `Failed to ${action.type}: ${error}`); + }); + + // Thinking process events + dreams.on("think:start", ({ query }) => { + console.log("\n๐Ÿง  Starting to think about:", query); + }); + + dreams.on("think:complete", ({ query }) => { + console.log("\n๐ŸŽ‰ Finished thinking about:", query); + }); + + dreams.on("think:timeout", ({ query }) => { + console.log("\nโฐ Thinking timed out for:", query); + }); + + dreams.on("think:error", ({ query, error }) => { + console.log("\n๐Ÿ’ฅ Error while thinking about:", query, error); + }); + + // Goal management events + dreams.on("goal:created", ({ id, description }) => { + console.log(chalk.cyan("\n๐ŸŽฏ New goal created:"), { + id, + description, + }); + }); + + dreams.on("goal:updated", ({ id, status }) => { + console.log(chalk.yellow("\n๐Ÿ“ Goal status updated:"), { + id, + status: printGoalStatus(status), + }); + }); + + dreams.on("goal:completed", ({ id, result }) => { + console.log(chalk.green("\nโœจ Goal completed:"), { + id, + result, + }); + }); + + dreams.on("goal:failed", ({ id, error }) => { + console.log(chalk.red("\n๐Ÿ’ฅ Goal failed:"), { + id, + error: error instanceof Error ? error.message : String(error), + }); + }); + + // Memory management events + dreams.on("memory:experience_stored", ({ experience }) => { + console.log(chalk.blue("\n๐Ÿ’พ New experience stored:"), { + action: experience.action, + outcome: experience.outcome, + importance: experience.importance, + timestamp: experience.timestamp, + }); + + if (experience.emotions?.length) { + console.log( + chalk.blue("๐Ÿ˜Š Emotional context:"), + experience.emotions.join(", ") + ); + } + }); + + dreams.on("memory:knowledge_stored", ({ document }) => { + console.log(chalk.magenta("\n๐Ÿ“š New knowledge documented:"), { + title: document.title, + category: document.category, + tags: document.tags, + lastUpdated: document.lastUpdated, + }); + console.log(chalk.magenta("๐Ÿ“ Content:"), document.content); + }); + + dreams.on("memory:experience_retrieved", ({ experiences }) => { + console.log(chalk.yellow("\n๐Ÿ” Relevant past experiences found:")); + experiences.forEach((exp, index) => { + console.log(chalk.yellow(`\n${index + 1}. Previous Experience:`)); + console.log(` Action: ${exp.action}`); + console.log(` Outcome: ${exp.outcome}`); + console.log(` Importance: ${exp.importance || "N/A"}`); + if (exp.emotions?.length) { + console.log(` Emotions: ${exp.emotions.join(", ")}`); + } + }); + }); + + dreams.on("memory:knowledge_retrieved", ({ documents }) => { + console.log(chalk.green("\n๐Ÿ“– Relevant knowledge retrieved:")); + documents.forEach((doc, index) => { + console.log(chalk.green(`\n${index + 1}. Knowledge Entry:`)); + console.log(` Title: ${doc.title}`); + console.log(` Category: ${doc.category}`); + console.log(` Tags: ${doc.tags.join(", ")}`); + console.log(` Content: ${doc.content}`); + }); + }); + + // Start the AI agent + /*try { + console.log(chalk.cyan("\n๐Ÿค– Starting zIdle AI agent...")); + + // Initial analysis + const result = await dreams.think( + "First Goal: Get NFT token ID before proceeding with any other actions. When this goal is done you can start mining resources efficiently to maximize XP gain" + ); + + console.log(chalk.green("\nโœจ Initial analysis completed!")); + console.log("Strategy:", result); + + // Continue monitoring and adjusting strategy + setInterval(async () => { + await dreams.think( + "Review current progress and adjust farming strategy if needed. Consider resource levels, XP gains, and whether we should switch resources." + ); + }, 5 * 60 * 1000); // Check every 5 minutes + } catch (error) { + console.error(chalk.red("Error running AI agent:"), error); + }*/ + + // Handle shutdown + process.on("SIGINT", async () => { + console.log(chalk.yellow("\nShutting down zIdle AI agent...")); + process.exit(0); + }); + + // Main interaction loop + const main_goal = + "Mine resources (wood and mineral) efficiently to maximize XP gain"; + while (true) { + try { + // Plan and execute goals + console.log(chalk.cyan("\n๐Ÿค” Planning strategy for goal...")); + await dreams.decomposeObjectiveIntoGoals(main_goal); + + console.log(chalk.cyan("\n๐ŸŽฏ Executing goals...")); + + const stats = { + completed: 0, + failed: 0, + total: 0, + }; + + // Execute goals until completion + while (true) { + const readyGoals = dreams.goalManager.getReadyGoals(); + console.log("-------------------- readyGoals", readyGoals); + const activeGoals = dreams.goalManager + .getGoalsByHorizon("short") + .filter((g) => g.status === "active"); + const pendingGoals = dreams.goalManager + .getGoalsByHorizon("short") + .filter((g) => g.status === "pending"); + console.log("-------------------- activeGoals", activeGoals); + console.log("-------------------- pendingGoals", pendingGoals); + + // Status update + console.log(chalk.cyan("\n๐Ÿ“Š Current Progress:")); + console.log(`Ready goals: ${readyGoals.length}`); + console.log(`Active goals: ${activeGoals.length}`); + console.log(`Pending goals: ${pendingGoals.length}`); + console.log(`Completed: ${stats.completed}`); + console.log(`Failed: ${stats.failed}`); + + // Check if all goals are complete + if ( + readyGoals.length === 0 && + activeGoals.length === 0 && + pendingGoals.length === 0 + ) { + console.log(chalk.green("\nโœจ All goals completed!")); + break; + } + + // Handle blocked goals + if (readyGoals.length === 0 && activeGoals.length === 0) { + console.log( + chalk.yellow( + "\nโš ๏ธ No ready or active goals, but some goals are pending:" + ) + ); + pendingGoals.forEach((goal) => { + const blockingGoals = dreams.goalManager.getBlockingGoals(goal.id); + console.log(chalk.yellow(`\n๐Ÿ“Œ Pending Goal: ${goal.description}`)); + console.log( + chalk.yellow(` Blocked by: ${blockingGoals.length} goals`) + ); + blockingGoals.forEach((blocking) => { + console.log( + chalk.yellow( + ` - ${blocking.description} (${blocking.status})` + ) + ); + }); + }); + break; + } + + // Execute next goal + try { + await dreams.processHighestPriorityGoal(); + stats.completed++; + } catch (error) { + console.error(chalk.red("\nโŒ Goal execution failed:"), error); + stats.failed++; + + // Ask to continue + const shouldContinue = await getCliInput( + chalk.yellow("\nContinue executing remaining goals? (y/n): ") + ); + + if (shouldContinue.toLowerCase() !== "y") { + console.log(chalk.yellow("Stopping goal execution.")); + break; + } + } + + stats.total++; + } + + // Learning summary + console.log(chalk.cyan("\n๐Ÿ“Š Learning Summary:")); + + const recentExperiences = await dreams.memory.getRecentEpisodes(5); + console.log(chalk.blue("\n๐Ÿ”„ Recent Experiences:")); + recentExperiences.forEach((exp, index) => { + console.log(chalk.blue(`\n${index + 1}. Experience:`)); + console.log(` Action: ${exp.action}`); + console.log(` Outcome: ${exp.outcome}`); + console.log(` Importance: ${exp.importance || "N/A"}`); + }); + + const relevantDocs = await dreams.memory.findSimilarDocuments( + main_goal, + 3 + ); + console.log(chalk.magenta("\n๐Ÿ“š Accumulated Knowledge:")); + relevantDocs.forEach((doc, index) => { + console.log(chalk.magenta(`\n${index + 1}. Knowledge Entry:`)); + console.log(` Title: ${doc.title}`); + console.log(` Category: ${doc.category}`); + console.log(` Tags: ${doc.tags.join(", ")}`); + }); + + // Final execution summary + console.log(chalk.cyan("\n๐Ÿ“Š Final Execution Summary:")); + console.log(chalk.green(`โœ… Completed Goals: ${stats.completed}`)); + console.log(chalk.red(`โŒ Failed Goals: ${stats.failed}`)); + console.log( + chalk.blue( + `๐Ÿ“ˆ Success Rate: ${Math.round( + (stats.completed / stats.total) * 100 + )}%` + ) + ); + console.log( + chalk.yellow( + `๐Ÿง  Learning Progress: ${recentExperiences.length} new experiences, ${relevantDocs.length} relevant knowledge entries` + ) + ); + } catch (error) { + console.error(chalk.red("Error processing goal:"), error); + } + } +} + +main().catch((error) => { + console.error(chalk.red("Fatal error:"), error); + process.exit(1); +}); diff --git a/packages/core/package.json b/packages/core/package.json index 0560ebff..3e998026 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,51 +1,58 @@ { - "name": "@daydreamsai/core", - "module": "index.ts", - "version": "0.0.1", - "type": "module", - "devDependencies": { - "@types/bun": "latest" - }, - "scripts": { - "start": "bun run src/main.ts", - "test": "vitest", - "build": "tsup --dts-resolve" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "dependencies": { - "@ai-sdk/amazon-bedrock": "^1.1.1", - "@ai-sdk/anthropic": "^1.1.1", - "@ai-sdk/azure": "^1.1.1", - "@ai-sdk/cerebras": "^0.1.1", - "@ai-sdk/cohere": "^1.1.1", - "@ai-sdk/deepinfra": "^0.1.1", - "@ai-sdk/deepseek": "^0.1.1", - "@ai-sdk/fireworks": "^0.1.1", - "@ai-sdk/google": "^1.1.1", - "@ai-sdk/google-vertex": "^2.1.1", - "@ai-sdk/groq": "^1.1.1", - "@ai-sdk/mistral": "^1.1.1", - "@ai-sdk/openai": "^1.1.1", - "@ai-sdk/togetherai": "^0.1.1", - "@ai-sdk/xai": "^1.1.1", - "@langchain/core": "^0.3.33", - "@langchain/textsplitters": "^0.1.0", - "@openrouter/ai-sdk-provider": "^0.0.6", - "@solana/web3.js": "^1.98.0", - "agent-twitter-client": "^0.0.16", - "ai": "^4.1.0", - "ajv": "^8.17.1", - "bs58": "^6.0.0", - "chromadb": "^1.9.4", - "chromadb-default-embed": "^2.13.2", - "ethers": "^6.13.5", - "openai": "^4.76.0", - "starknet": "^6.11.0", - "tsup": "^8.3.5", - "vitest": "^2.1.8", - "zod": "^3.24.1", - "zod-to-json-schema": "^3.24.1" + "name": "@daydreams/core", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "type": "module", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" } + }, + "files": [ + "dist" + ], + "devDependencies": { + "@types/bun": "latest" + }, + "scripts": { + "start": "bun run src/main.ts", + "test": "vitest", + "build": "tsup" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@ai-sdk/amazon-bedrock": "^1.1.1", + "@ai-sdk/anthropic": "^1.1.1", + "@ai-sdk/azure": "^1.1.1", + "@ai-sdk/cerebras": "^0.1.1", + "@ai-sdk/cohere": "^1.1.1", + "@ai-sdk/deepinfra": "^0.1.1", + "@ai-sdk/deepseek": "^0.1.1", + "@ai-sdk/fireworks": "^0.1.1", + "@ai-sdk/google": "^1.1.1", + "@ai-sdk/google-vertex": "^2.1.1", + "@ai-sdk/groq": "^1.1.1", + "@ai-sdk/mistral": "^1.1.1", + "@ai-sdk/openai": "^1.1.1", + "@ai-sdk/togetherai": "^0.1.1", + "@ai-sdk/xai": "^1.1.1", + "@openrouter/ai-sdk-provider": "^0.0.6", + "@solana/web3.js": "^1.98.0", + "agent-twitter-client": "^0.0.16", + "ai": "^4.1.0", + "ajv": "^8.17.1", + "bs58": "^6.0.0", + "chromadb": "^1.9.4", + "chromadb-default-embed": "^2.13.2", + "ethers": "^6.13.5", + "openai": "^4.76.0", + "starknet": "^6.11.0", + "tsup": "^8.3.5", + "vitest": "^2.1.8", + "zod": "^3.24.1", + "zod-to-json-schema": "^3.24.1" + } } diff --git a/packages/core/src/core/vector-db.ts b/packages/core/src/core/vector-db.ts index cb51f261..d3527c2a 100644 --- a/packages/core/src/core/vector-db.ts +++ b/packages/core/src/core/vector-db.ts @@ -27,10 +27,10 @@ export class ChromaVectorDB implements VectorDB { static readonly EPISODIC_COLLECTION = "episodic_memory"; static readonly DOCUMENTATION_COLLECTION = "documentation"; - private client: ChromaClient; - private embedder: OpenAIEmbeddingFunction; - private logger: Logger; - private collectionName: string; + public client: ChromaClient; + private embedder: OpenAIEmbeddingFunction; + private logger: Logger; + private collectionName: string; constructor( collectionName = "memories", diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 8d119dee..bf449663 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1 +1,4 @@ -export * from "./core"; +export * from "./core/llm-client"; +export * from "./core/chain-of-thought"; +export * from "./core/utils"; +//export * from "./core/vector-db"; From 5d8142cbca7596ea32b145fd16e85d9231722a2c Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 20:12:50 +0100 Subject: [PATCH 02/12] add server example + chatlist in ui --- clients/example-ui/src/App.tsx | 135 +++++++----- .../src/components/message-list.tsx | 80 +++++++ .../example-ui/src/hooks/use-daydreams.tsx | 59 +++++ examples/example-server.ts | 207 ++++++++++++++++++ package.json | 1 + packages/core/package.json | 126 ++++------- 6 files changed, 466 insertions(+), 142 deletions(-) create mode 100644 clients/example-ui/src/components/message-list.tsx create mode 100644 clients/example-ui/src/hooks/use-daydreams.tsx create mode 100644 examples/example-server.ts diff --git a/clients/example-ui/src/App.tsx b/clients/example-ui/src/App.tsx index 94706780..e37637bc 100644 --- a/clients/example-ui/src/App.tsx +++ b/clients/example-ui/src/App.tsx @@ -1,70 +1,93 @@ +import { useState, useEffect } from "react"; +import { MessagesList } from "@/components/message-list"; +import { useDaydreamsWs } from "@/hooks/use-daydreams"; import { AppSidebar } from "@/components/app-sidebar"; import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, + Breadcrumb, + BreadcrumbItem, + BreadcrumbLink, + BreadcrumbList, } from "@/components/ui/breadcrumb"; import { Separator } from "@/components/ui/separator"; import { - SidebarInset, - SidebarProvider, - SidebarTrigger, + SidebarInset, + SidebarProvider, + SidebarTrigger, } from "@/components/ui/sidebar"; -import { useState } from "react"; -//import { ChatBox } from "@/components/chat/chatbox"; -//import { useZidle } from "./hooks/use-zidle"; + +interface MessageType { + type: "user" | "assistant" | "system" | "error" | "other"; + message?: string; + error?: string; +} function App() { - const [message, setMessage] = useState(""); - //const { messages, sendMessage } = useZidle(); + const [message, setMessage] = useState(""); + const [allMessages, setAllMessages] = useState([]); + const { messages, sendGoal } = useDaydreamsWs(); + useEffect(() => { + if (messages.length === 0) return; + const lastMessage = messages[messages.length - 1]; + setAllMessages((prev) => { + if (prev.length > 0 && JSON.stringify(prev[prev.length - 1]) === JSON.stringify(lastMessage)) { + return prev; + } + return [...prev, lastMessage]; + }); + }, [messages]); + + + const handleSubmit = () => { + if (!message.trim()) return; + setAllMessages((prev) => [ + ...prev, + { type: "user", message: message }, + ]); + sendGoal(message); + setMessage(""); + }; - const handleSubmit = async () => { - if (!message.trim()) return; + return ( + + + +
+
+ + + + + + Home + + + +
+
- const content = message; - console.log(content); - setMessage(""); // Clear input - //await sendMessage(content); - }; +
+
+ setMessage(e.target.value)} + /> + +
- return ( - - - -
-
- - - - - - - Home - - - {/* - - Data Fetching - */} - - -
-
-
- {/* setMessage(e.target.value)} - /> */} -
-
-
- ); + {/* Affichage des messages via MessageList */} + +
+
+
+ ); } export default App; diff --git a/clients/example-ui/src/components/message-list.tsx b/clients/example-ui/src/components/message-list.tsx new file mode 100644 index 00000000..b3140525 --- /dev/null +++ b/clients/example-ui/src/components/message-list.tsx @@ -0,0 +1,80 @@ +import * as React from "react"; + +interface MessageType { + type: "user" | "assistant" | "system" | "error" | "other" | "welcome" | "info"; + message?: string; + error?: string; +} + +interface MessagesListProps { + messages: MessageType[]; + message: string; + setMessage: (message: string) => void; +} + +export function MessagesList({ messages }: MessagesListProps) { + + return ( +
+ {messages.map((msg, i) => { + let containerClass = "flex items-start"; + let bubbleClass = + "max-w-[70%] rounded-2xl p-4 text-sm shadow-md transition-all duration-200 hover:shadow-lg"; + + + switch (msg.type) { + case "user": + containerClass += " justify-end"; + bubbleClass += + " bg-gradient-to-r from-blue-500 to-blue-600 text-white mr-2 self-end hover:from-blue-600 hover:to-blue-700"; + break; + + case "assistant": + containerClass += " justify-start"; + bubbleClass += + " bg-gradient-to-r from-gray-100 to-gray-200 text-gray-900 ml-2 self-start border border-gray-200 hover:border-gray-300"; + break; + + case "system": + containerClass += " justify-center"; + bubbleClass += " bg-gradient-to-r from-yellow-50 to-yellow-100 text-yellow-900 border border-yellow-200 hover:border-yellow-300"; + break; + + case "error": + containerClass += " justify-center"; + bubbleClass += " bg-gradient-to-r from-red-50 to-red-100 text-red-700 font-semibold border border-red-200 hover:border-red-300"; + break; + + case "welcome": + containerClass += " justify-center"; + bubbleClass += " bg-gradient-to-r from-green-50 to-green-100 text-green-800 border border-green-200 hover:border-green-300"; + break; + + case "info": + containerClass += " justify-center"; + bubbleClass += " bg-gradient-to-r from-blue-50 to-blue-100 text-blue-800 border border-blue-200 hover:border-blue-300"; + break; + + default: + containerClass += " justify-start"; + bubbleClass += " bg-gradient-to-r from-gray-100 to-gray-200 text-gray-900 ml-2 border border-gray-200"; + } + + return ( +
+
+ + {msg.type !== "user" && msg.type !== "assistant" && ( +
+ {msg.type} +
+ )} + {msg.message &&
{msg.message}
} + {msg.error &&
{msg.error}
} +
+
+ ); + })} +
+ ); +} \ No newline at end of file diff --git a/clients/example-ui/src/hooks/use-daydreams.tsx b/clients/example-ui/src/hooks/use-daydreams.tsx new file mode 100644 index 00000000..9068d8fb --- /dev/null +++ b/clients/example-ui/src/hooks/use-daydreams.tsx @@ -0,0 +1,59 @@ + +import { useEffect, useRef, useState } from "react"; + +interface ServerMessage { + type: string; + message?: string; + error?: string; +} + +export function useDaydreamsWs() { + const [messages, setMessages] = useState([]); + const wsRef = useRef(null); + + useEffect(() => { + const ws = new WebSocket("ws://localhost:8080"); + wsRef.current = ws; + + ws.onopen = () => { + console.log("โœ… Connected to Daydreams WebSocket!"); + }; + + ws.onmessage = (event) => { + try { + const data = JSON.parse(event.data) as ServerMessage; + setMessages((prev) => [...prev, data]); + } catch (err) { + console.error("Failed to parse WebSocket message:", event.data); + } + }; + + ws.onerror = (error) => { + console.error("WebSocket error:", error); + }; + + ws.onclose = () => { + console.log("โŒ Disconnected from Daydreams WebSocket."); + }; + + return () => { + ws.close(); + }; + }, []); + + const sendGoal = (goal: string) => { + if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) { + console.warn("WebSocket is not open. Cannot send goal:", goal); + return; + } + + setMessages((prev) => [...prev, { type: "user", message: goal }]); + + wsRef.current.send(JSON.stringify({ goal })); + }; + + return { + messages, + sendGoal, + }; +} diff --git a/examples/example-server.ts b/examples/example-server.ts new file mode 100644 index 00000000..b4affd5c --- /dev/null +++ b/examples/example-server.ts @@ -0,0 +1,207 @@ +import { WebSocketServer, WebSocket } from "ws"; +import chalk from "chalk"; +import { z } from "zod"; + +// ---- Import your internal classes and functions here ---- +import { LLMClient } from "../packages/core/src/core/llm-client"; +import { ChainOfThought } from "../packages/core/src/core/chain-of-thought"; +import { ChromaVectorDB } from "../packages/core/src/core/vector-db"; +import { StarknetChain } from "../packages/core/src/core/chains/starknet"; +import { env } from "../packages/core/src/core/env"; +import { fetchGraphQL } from "../packages/core/src/core/providers"; + +import { + GoalStatus, + LogLevel +} from "../packages/core/src/core/types"; + +// ------------------------------------------------------ +// 1) CREATE DAYDREAMS AGENT +// ------------------------------------------------------ +function createDaydreamsAgent() { + // 1.1. LLM Initialization + const llmClient = new LLMClient({ + model: "anthropic/claude-3-5-sonnet-latest", + }); + + // 1.2. Starknet blockchain initialization + const starknetChain = new StarknetChain({ + rpcUrl: env.STARKNET_RPC_URL, + address: env.STARKNET_ADDRESS, + privateKey: env.STARKNET_PRIVATE_KEY, + }); + + // 1.3. Vector memory initialization + const memory = new ChromaVectorDB("agent_memory"); + + // 1.4. Main reasoning engine + const dreams = new ChainOfThought( + llmClient, + memory, + { worldState: "You are a helpful assistant." }, + { logLevel: LogLevel.DEBUG } + ); + + // 1.5. Load initial context into memory + (async () => { + // For demonstration, we purge the database so we start clean each run + await memory.purge(); + })().catch(console.error); + + // 1.6. Register actions that the agent can perform + dreams.registerOutput({ + name: "EXECUTE_TRANSACTION", + handler: async (data: any) => { + const result = await starknetChain.write(data.payload); + return `Transaction executed successfully: ${JSON.stringify(result, null, 2)}`; + }, + schema: z + .any() + .describe( + "Payload to execute the transaction, never include slashes or comments" + ), + }); + + dreams.registerOutput({ + name: "GRAPHQL_FETCH", + handler: async (data: any) => { + const { query, variables } = data.payload ?? {}; + const result = await fetchGraphQL( + env.GRAPHQL_URL + "/graphql", + query, + variables + ); + const resultStr = [ + `query: ${query}`, + `result: ${JSON.stringify(result, null, 2)}`, + ].join("\n\n"); + return `GraphQL data fetched successfully: ${resultStr}`; + }, + schema: z + .any() + .describe( + "Payload to fetch data from the Eternum GraphQL API, never include slashes/comments" + ), + }); + + // 1.7. Optionally register event handlers + dreams.on("goal:created", ({ id, description }) => { + console.log(chalk.cyan("[WS] New goal created:"), { id, description }); + }); + + // Return the main instance that we will use later + return dreams; +} + +// Create a single โ€œglobalโ€ instance (or one per connection if you prefer isolation) +const dreams = createDaydreamsAgent(); + +// ------------------------------------------------------ +// 2) WEBSOCKET SERVER +// ------------------------------------------------------ +const wss = new WebSocketServer({ port: 8080 }); +console.log(chalk.green("[WS] WebSocket server listening on ws://localhost:8080")); + +/** + * Helper function to send JSON messages to a client. + */ +function sendJSON(ws: WebSocket, data: unknown) { + ws.send(JSON.stringify(data)); +} + +wss.on("connection", (ws) => { + console.log(chalk.blue("[WS] New client connected.")); + + // Send a welcome message to the client + sendJSON(ws, { + type: "welcome", + message: "Welcome to Daydreams WebSocket server!", + }); + + // Handle incoming messages (each message can represent a new goal) + ws.on("message", async (rawData) => { + try { + const dataString = rawData.toString(); + console.log(chalk.magenta("[WS] Received message:"), dataString); + + // We assume the client sends JSON such as: { "goal": "some string" } + const parsed = JSON.parse(dataString); + const userGoal = parsed.goal; + + if (!userGoal || typeof userGoal !== "string") { + throw new Error("Invalid goal format. Expected { goal: string }"); + } + + // 2.1) Plan the goal with Daydreams + sendJSON(ws, { + type: "info", + message: "Planning strategy for goal: " + userGoal, + }); + + await dreams.decomposeObjectiveIntoGoals(userGoal); + + // 2.2) Execute goals until there are no more โ€œreadyโ€ goals + const stats = { completed: 0, failed: 0, total: 0 }; + + while (true) { + const readyGoals = dreams.goalManager.getReadyGoals(); + const activeGoals = dreams.goalManager + .getGoalsByHorizon("short") + .filter((g) => g.status === "active"); + const pendingGoals = dreams.goalManager + .getGoalsByHorizon("short") + .filter((g) => g.status === "pending"); + + // Check if all goals are completed + if ( + readyGoals.length === 0 && + activeGoals.length === 0 && + pendingGoals.length === 0 + ) { + sendJSON(ws, { + type: "info", + message: "All goals completed!", + }); + break; + } + + // Check if we are blocked + if (readyGoals.length === 0 && activeGoals.length === 0) { + sendJSON(ws, { + type: "warn", + message: "No ready or active goals, but some goals are pending. Possibly blocked.", + }); + break; + } + + // Execute the next ready goal + try { + await dreams.processHighestPriorityGoal(); + stats.completed++; + } catch (err) { + console.error("[WS] Goal execution failed:", err); + stats.failed++; + break; // For simplicity, we stop here + } + stats.total++; + } + + // Send a final summary to the client + sendJSON(ws, { + type: "summary", + message: `Goal execution done. Completed: ${stats.completed}, Failed: ${stats.failed}, Total: ${stats.total}.`, + }); + } catch (error) { + console.error(chalk.red("[WS] Error processing message:"), error); + sendJSON(ws, { + type: "error", + error: (error as Error).message || String(error), + }); + } + }); + + // If the client closes the connection + ws.on("close", () => { + console.log(chalk.yellow("[WS] Client disconnected.")); + }); +}); diff --git a/package.json b/package.json index db91cf4b..b99e9ed7 100644 --- a/package.json +++ b/package.json @@ -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", + "server": "bun run examples/example-server.ts", "api": "bun run examples/example-api.ts", "test": "bun run packages/core", "build": "pnpm --dir packages/core run build", diff --git a/packages/core/package.json b/packages/core/package.json index 04f5b6c4..b14ec13d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,99 +1,53 @@ { - "name": "@daydreamsai/core", + "name": "@daydreams/core", "module": "index.ts", "version": "0.0.2", "type": "module", "devDependencies": { - "@types/bun": "latest" + "@types/bun": "latest" }, "scripts": { - "start": "bun run src/main.ts", - "test": "vitest", - "build": "tsup --dts-resolve" + "start": "bun run src/main.ts", + "test": "vitest", + "build": "tsup --dts-resolve" }, "peerDependencies": { - "typescript": "^5.0.0" + "typescript": "^5.0.0" }, "dependencies": { - "@ai-sdk/amazon-bedrock": "^1.1.1", - "@ai-sdk/anthropic": "^1.1.1", - "@ai-sdk/azure": "^1.1.1", - "@ai-sdk/cerebras": "^0.1.1", - "@ai-sdk/cohere": "^1.1.1", - "@ai-sdk/deepinfra": "^0.1.1", - "@ai-sdk/deepseek": "^0.1.1", - "@ai-sdk/fireworks": "^0.1.1", - "@ai-sdk/google": "^1.1.1", - "@ai-sdk/google-vertex": "^2.1.1", - "@ai-sdk/groq": "^1.1.1", - "@ai-sdk/mistral": "^1.1.1", - "@ai-sdk/openai": "^1.1.1", - "@ai-sdk/togetherai": "^0.1.1", - "@ai-sdk/xai": "^1.1.1", - "@langchain/core": "^0.3.33", - "@langchain/textsplitters": "^0.1.0", - "@openrouter/ai-sdk-provider": "^0.0.6", - "@solana/web3.js": "^1.98.0", - "agent-twitter-client": "^0.0.16", - "ai": "^4.1.0", - "ajv": "^8.17.1", - "bs58": "^6.0.0", - "chromadb": "^1.9.4", - "chromadb-default-embed": "^2.13.2", - "ethers": "^6.13.5", - "mongodb": "^6.12.0", - "openai": "^4.76.0", - "starknet": "^6.11.0", - "tsup": "^8.3.5", - "vitest": "^2.1.8", - "zod": "^3.24.1", - "zod-to-json-schema": "^3.24.1" + "@ai-sdk/amazon-bedrock": "^1.1.1", + "@ai-sdk/anthropic": "^1.1.1", + "@ai-sdk/azure": "^1.1.1", + "@ai-sdk/cerebras": "^0.1.1", + "@ai-sdk/cohere": "^1.1.1", + "@ai-sdk/deepinfra": "^0.1.1", + "@ai-sdk/deepseek": "^0.1.1", + "@ai-sdk/fireworks": "^0.1.1", + "@ai-sdk/google": "^1.1.1", + "@ai-sdk/google-vertex": "^2.1.1", + "@ai-sdk/groq": "^1.1.1", + "@ai-sdk/mistral": "^1.1.1", + "@ai-sdk/openai": "^1.1.1", + "@ai-sdk/togetherai": "^0.1.1", + "@ai-sdk/xai": "^1.1.1", + "@langchain/core": "^0.3.33", + "@langchain/textsplitters": "^0.1.0", + "@openrouter/ai-sdk-provider": "^0.0.6", + "@solana/web3.js": "^1.98.0", + "agent-twitter-client": "^0.0.16", + "ai": "^4.1.0", + "ajv": "^8.17.1", + "bs58": "^6.0.0", + "chromadb": "^1.9.4", + "chromadb-default-embed": "^2.13.2", + "ethers": "^6.13.5", + "mongodb": "^6.12.0", + "openai": "^4.76.0", + "starknet": "^6.11.0", + "tsup": "^8.3.5", + "vitest": "^2.1.8", + "zod": "^3.24.1", + "zod-to-json-schema": "^3.24.1" } - }, - "files": [ - "dist" - ], - "devDependencies": { - "@types/bun": "latest" - }, - "scripts": { - "start": "bun run src/main.ts", - "test": "vitest", - "build": "tsup" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "dependencies": { - "@ai-sdk/amazon-bedrock": "^1.1.1", - "@ai-sdk/anthropic": "^1.1.1", - "@ai-sdk/azure": "^1.1.1", - "@ai-sdk/cerebras": "^0.1.1", - "@ai-sdk/cohere": "^1.1.1", - "@ai-sdk/deepinfra": "^0.1.1", - "@ai-sdk/deepseek": "^0.1.1", - "@ai-sdk/fireworks": "^0.1.1", - "@ai-sdk/google": "^1.1.1", - "@ai-sdk/google-vertex": "^2.1.1", - "@ai-sdk/groq": "^1.1.1", - "@ai-sdk/mistral": "^1.1.1", - "@ai-sdk/openai": "^1.1.1", - "@ai-sdk/togetherai": "^0.1.1", - "@ai-sdk/xai": "^1.1.1", - "@openrouter/ai-sdk-provider": "^0.0.6", - "@solana/web3.js": "^1.98.0", - "agent-twitter-client": "^0.0.16", - "ai": "^4.1.0", - "ajv": "^8.17.1", - "bs58": "^6.0.0", - "chromadb": "^1.9.4", - "chromadb-default-embed": "^2.13.2", - "ethers": "^6.13.5", - "openai": "^4.76.0", - "starknet": "^6.11.0", - "tsup": "^8.3.5", - "vitest": "^2.1.8", - "zod": "^3.24.1", - "zod-to-json-schema": "^3.24.1" } -} + \ No newline at end of file From ca0094d8a42b7060a10be55003de870b2f4b5062 Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 20:14:19 +0100 Subject: [PATCH 03/12] cleanup --- clients/example-ui/src/App.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/clients/example-ui/src/App.tsx b/clients/example-ui/src/App.tsx index e37637bc..8bdc3ef0 100644 --- a/clients/example-ui/src/App.tsx +++ b/clients/example-ui/src/App.tsx @@ -81,8 +81,6 @@ function App() { Send - - {/* Affichage des messages via MessageList */} From 252b325ff4b880dd712ec51af381894e99d59411 Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 20:18:06 +0100 Subject: [PATCH 04/12] fix rename --- clients/example-ui/package.json | 2 +- packages/core/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/example-ui/package.json b/clients/example-ui/package.json index 521e6f4a..892ffe5a 100644 --- a/clients/example-ui/package.json +++ b/clients/example-ui/package.json @@ -27,7 +27,7 @@ "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", "three": "^0.172.0", - "@daydreams/core": "workspace:*" + "@daydreamsai/core": "workspace:*" }, "devDependencies": { "@eslint/js": "^9.17.0", diff --git a/packages/core/package.json b/packages/core/package.json index b14ec13d..10742d69 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,5 +1,5 @@ { - "name": "@daydreams/core", + "name": "@daydreamsai/core", "module": "index.ts", "version": "0.0.2", "type": "module", From 49634ffff5a1758cd4f22971094803a489c06df4 Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 20:27:58 +0100 Subject: [PATCH 05/12] improve style --- clients/example-ui/src/App.tsx | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/clients/example-ui/src/App.tsx b/clients/example-ui/src/App.tsx index 8bdc3ef0..2023525b 100644 --- a/clients/example-ui/src/App.tsx +++ b/clients/example-ui/src/App.tsx @@ -66,20 +66,22 @@ function App() {
-
- setMessage(e.target.value)} - /> - +
+
+ setMessage(e.target.value)} + placeholder="Type your message here..." + className="flex-1 px-4 py-2 rounded-lg border border-border bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" + /> + +
From 14e7fffcdcdd7a29f04f262c69c9c3ec4bfe8dbf Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 20:45:30 +0100 Subject: [PATCH 06/12] rollback tsconfig --- clients/example-ui/tsconfig.json | 37 ++++++++------------------- clients/example-ui/tsconfig.node.json | 28 +++++++++++++++----- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/clients/example-ui/tsconfig.json b/clients/example-ui/tsconfig.json index eee3470a..15f98aa9 100644 --- a/clients/example-ui/tsconfig.json +++ b/clients/example-ui/tsconfig.json @@ -1,28 +1,13 @@ { + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ], "compilerOptions": { - "target": "es5", - "useDefineForClassFields": true, - "lib": ["dom", "dom.iterable", "esnext"], - "module": "esnext", - "skipLibCheck": true, - "moduleResolution": "node", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "allowJs": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - } - }, - "references": [{ "path": "./tsconfig.node.json" }] -} + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } + } \ No newline at end of file diff --git a/clients/example-ui/tsconfig.node.json b/clients/example-ui/tsconfig.node.json index 26063d85..cff63589 100644 --- a/clients/example-ui/tsconfig.node.json +++ b/clients/example-ui/tsconfig.node.json @@ -1,10 +1,26 @@ { "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } }, "include": ["vite.config.ts"] -} +} \ No newline at end of file From 84fec48334b4596d0c164a397a3e481aa6fbc17e Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 20:48:35 +0100 Subject: [PATCH 07/12] rollback --- packages/core/src/core/vector-db.ts | 2 +- packages/core/src/index.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/core/src/core/vector-db.ts b/packages/core/src/core/vector-db.ts index 210b1dbb..c4c18daf 100644 --- a/packages/core/src/core/vector-db.ts +++ b/packages/core/src/core/vector-db.ts @@ -27,7 +27,7 @@ export class ChromaVectorDB implements VectorDB { static readonly EPISODIC_COLLECTION = "episodic_memory"; static readonly DOCUMENTATION_COLLECTION = "documentation"; - public client: ChromaClient; + private client: ChromaClient; private embedder: OpenAIEmbeddingFunction; private logger: Logger; private collectionName: string; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index bf449663..8d119dee 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,4 +1 @@ -export * from "./core/llm-client"; -export * from "./core/chain-of-thought"; -export * from "./core/utils"; -//export * from "./core/vector-db"; +export * from "./core"; From 806f8cd020b5f39235142d85e6b4708a07526b87 Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 21:27:22 +0100 Subject: [PATCH 08/12] update server + improve chat --- clients/example-ui/src/App.tsx | 33 ++- .../src/components/message-list.tsx | 80 +++++-- examples/example-server.ts | 207 ++++++++---------- 3 files changed, 170 insertions(+), 150 deletions(-) diff --git a/clients/example-ui/src/App.tsx b/clients/example-ui/src/App.tsx index 2023525b..c6802638 100644 --- a/clients/example-ui/src/App.tsx +++ b/clients/example-ui/src/App.tsx @@ -25,10 +25,13 @@ function App() { const [message, setMessage] = useState(""); const [allMessages, setAllMessages] = useState([]); const { messages, sendGoal } = useDaydreamsWs(); + + // Synchronise les messages du hook dans allMessages useEffect(() => { if (messages.length === 0) return; const lastMessage = messages[messages.length - 1]; setAllMessages((prev) => { + // On รฉvite les doublons si le dernier message est identique if (prev.length > 0 && JSON.stringify(prev[prev.length - 1]) === JSON.stringify(lastMessage)) { return prev; } @@ -36,7 +39,6 @@ function App() { }); }, [messages]); - const handleSubmit = () => { if (!message.trim()) return; setAllMessages((prev) => [ @@ -51,6 +53,7 @@ function App() { + {/* Header */}
@@ -65,25 +68,39 @@ function App() {
-
-
-
+ {/* Main content area */} +
+ {/* Zone conversation */} +
+ {/* Liste des messages */} +
+ +
+ + {/* Barre d'input en bas */} +
setMessage(e.target.value)} - placeholder="Type your message here..." - className="flex-1 px-4 py-2 rounded-lg border border-border bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" + onKeyDown={(e) => { + if (e.key === "Enter") { + handleSubmit(); + } + }} + placeholder="Type your message..." + className="flex-1 px-4 py-2 rounded-lg border border-border bg-background text-foreground + focus:outline-none focus:ring-2 focus:ring-primary" />
-
diff --git a/clients/example-ui/src/components/message-list.tsx b/clients/example-ui/src/components/message-list.tsx index b3140525..9d6ca27a 100644 --- a/clients/example-ui/src/components/message-list.tsx +++ b/clients/example-ui/src/components/message-list.tsx @@ -8,73 +8,111 @@ interface MessageType { interface MessagesListProps { messages: MessageType[]; - message: string; - setMessage: (message: string) => void; } export function MessagesList({ messages }: MessagesListProps) { - return (
{messages.map((msg, i) => { - let containerClass = "flex items-start"; - let bubbleClass = - "max-w-[70%] rounded-2xl p-4 text-sm shadow-md transition-all duration-200 hover:shadow-lg"; + const baseBubble = ` + relative + rounded-2xl + p-4 + text-sm + shadow-md + transition-all + duration-200 + max-w-[80%] + whitespace-pre-wrap + break-words + `; + let containerClass = "flex items-start"; + let bubbleClass = baseBubble; switch (msg.type) { case "user": containerClass += " justify-end"; - bubbleClass += - " bg-gradient-to-r from-blue-500 to-blue-600 text-white mr-2 self-end hover:from-blue-600 hover:to-blue-700"; + bubbleClass += ` + bg-gradient-to-r from-blue-600 to-blue-500 text-white mr-2 + self-end hover:brightness-110 + `; break; case "assistant": containerClass += " justify-start"; - bubbleClass += - " bg-gradient-to-r from-gray-100 to-gray-200 text-gray-900 ml-2 self-start border border-gray-200 hover:border-gray-300"; + bubbleClass += ` + bg-gradient-to-r from-gray-100 to-gray-200 text-gray-900 ml-2 + border border-gray-300 + hover:brightness-95 + `; break; case "system": containerClass += " justify-center"; - bubbleClass += " bg-gradient-to-r from-yellow-50 to-yellow-100 text-yellow-900 border border-yellow-200 hover:border-yellow-300"; + bubbleClass += ` + bg-gradient-to-r from-yellow-50 to-yellow-100 text-yellow-900 + border border-yellow-200 hover:brightness-105 + `; break; case "error": containerClass += " justify-center"; - bubbleClass += " bg-gradient-to-r from-red-50 to-red-100 text-red-700 font-semibold border border-red-200 hover:border-red-300"; + bubbleClass += ` + bg-gradient-to-r from-red-50 to-red-100 text-red-700 font-semibold + border border-red-200 hover:brightness-105 + `; break; case "welcome": containerClass += " justify-center"; - bubbleClass += " bg-gradient-to-r from-green-50 to-green-100 text-green-800 border border-green-200 hover:border-green-300"; + bubbleClass += ` + bg-gradient-to-r from-green-50 to-green-100 text-green-800 + border border-green-200 hover:brightness-105 + `; break; case "info": containerClass += " justify-center"; - bubbleClass += " bg-gradient-to-r from-blue-50 to-blue-100 text-blue-800 border border-blue-200 hover:border-blue-300"; + bubbleClass += ` + bg-gradient-to-r from-blue-50 to-blue-100 text-blue-800 + border border-blue-200 hover:brightness-105 + `; break; default: containerClass += " justify-start"; - bubbleClass += " bg-gradient-to-r from-gray-100 to-gray-200 text-gray-900 ml-2 border border-gray-200"; + bubbleClass += ` + bg-gradient-to-r from-gray-100 to-gray-200 text-gray-900 ml-2 + border border-gray-300 + `; } return (
-
- +
+ {/* Affiche le type si ce nโ€™est pas un user/assistant classique */} {msg.type !== "user" && msg.type !== "assistant" && ( -
+
{msg.type}
)} - {msg.message &&
{msg.message}
} - {msg.error &&
{msg.error}
} + + {msg.message && ( +
+ {msg.message} +
+ )} + + {msg.error && ( +
+ {msg.error} +
+ )}
); })}
); -} \ No newline at end of file +} diff --git a/examples/example-server.ts b/examples/example-server.ts index b4affd5c..8602acc9 100644 --- a/examples/example-server.ts +++ b/examples/example-server.ts @@ -9,6 +9,11 @@ import { ChromaVectorDB } from "../packages/core/src/core/vector-db"; import { StarknetChain } from "../packages/core/src/core/chains/starknet"; import { env } from "../packages/core/src/core/env"; import { fetchGraphQL } from "../packages/core/src/core/providers"; +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 { MessageProcessor } from "../packages/core/src/core/processors/message-processor"; +import { defaultCharacter } from "../packages/core/src/core/character"; import { GoalStatus, @@ -19,82 +24,78 @@ import { // 1) CREATE DAYDREAMS AGENT // ------------------------------------------------------ function createDaydreamsAgent() { + const loglevel = LogLevel.INFO; + // 1.1. LLM Initialization const llmClient = new LLMClient({ model: "anthropic/claude-3-5-sonnet-latest", + temperature: 0.3, }); - // 1.2. Starknet blockchain initialization - const starknetChain = new StarknetChain({ - rpcUrl: env.STARKNET_RPC_URL, - address: env.STARKNET_ADDRESS, - privateKey: env.STARKNET_PRIVATE_KEY, + // 1.2. Vector memory initialization + const vectorDb = new ChromaVectorDB("agent_memory", { + chromaUrl: "http://localhost:8000", + logLevel: loglevel, }); - // 1.3. Vector memory initialization - const memory = new ChromaVectorDB("agent_memory"); + // 1.3. Room manager initialization + const roomManager = new RoomManager(vectorDb); - // 1.4. Main reasoning engine - const dreams = new ChainOfThought( + // 1.4. Initialize processor with default character + const processor = new MessageProcessor( llmClient, - memory, - { worldState: "You are a helpful assistant." }, - { logLevel: LogLevel.DEBUG } + defaultCharacter, + loglevel ); - // 1.5. Load initial context into memory - (async () => { - // For demonstration, we purge the database so we start clean each run - await memory.purge(); - })().catch(console.error); - - // 1.6. Register actions that the agent can perform - dreams.registerOutput({ - name: "EXECUTE_TRANSACTION", - handler: async (data: any) => { - const result = await starknetChain.write(data.payload); - return `Transaction executed successfully: ${JSON.stringify(result, null, 2)}`; - }, - schema: z - .any() - .describe( - "Payload to execute the transaction, never include slashes or comments" - ), - }); + // 1.5. Initialize core system + const orchestrator = new Orchestrator( + roomManager, + vectorDb, + [processor], + null, // No scheduled tasks for this example + { + level: loglevel, + enableColors: true, + enableTimestamp: true, + } + ); - dreams.registerOutput({ - name: "GRAPHQL_FETCH", - handler: async (data: any) => { - const { query, variables } = data.payload ?? {}; - const result = await fetchGraphQL( - env.GRAPHQL_URL + "/graphql", - query, - variables - ); - const resultStr = [ - `query: ${query}`, - `result: ${JSON.stringify(result, null, 2)}`, - ].join("\n\n"); - return `GraphQL data fetched successfully: ${resultStr}`; + // 1.6. Register handlers + orchestrator.registerIOHandler({ + name: "user_chat", + role: HandlerRole.INPUT, + schema: z.object({ + content: z.string(), + userId: z.string().optional(), + }), + handler: async (payload) => { + return payload; }, - schema: z - .any() - .describe( - "Payload to fetch data from the Eternum GraphQL API, never include slashes/comments" - ), }); - // 1.7. Optionally register event handlers - dreams.on("goal:created", ({ id, description }) => { - console.log(chalk.cyan("[WS] New goal created:"), { id, description }); + orchestrator.registerIOHandler({ + name: "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; + }; + console.log(`Reply to user ${userId ?? "??"}: ${message}`); + }, }); - // Return the main instance that we will use later - return dreams; + // Return the orchestrator instance + return orchestrator; } -// Create a single โ€œglobalโ€ instance (or one per connection if you prefer isolation) -const dreams = createDaydreamsAgent(); +// Create a single "global" instance +const orchestrator = createDaydreamsAgent(); // ------------------------------------------------------ // 2) WEBSOCKET SERVER @@ -102,9 +103,6 @@ const dreams = createDaydreamsAgent(); const wss = new WebSocketServer({ port: 8080 }); console.log(chalk.green("[WS] WebSocket server listening on ws://localhost:8080")); -/** - * Helper function to send JSON messages to a client. - */ function sendJSON(ws: WebSocket, data: unknown) { ws.send(JSON.stringify(data)); } @@ -112,85 +110,41 @@ function sendJSON(ws: WebSocket, data: unknown) { wss.on("connection", (ws) => { console.log(chalk.blue("[WS] New client connected.")); - // Send a welcome message to the client sendJSON(ws, { type: "welcome", message: "Welcome to Daydreams WebSocket server!", }); - // Handle incoming messages (each message can represent a new goal) ws.on("message", async (rawData) => { try { const dataString = rawData.toString(); console.log(chalk.magenta("[WS] Received message:"), dataString); - // We assume the client sends JSON such as: { "goal": "some string" } const parsed = JSON.parse(dataString); - const userGoal = parsed.goal; + const userMessage = parsed.goal; - if (!userGoal || typeof userGoal !== "string") { - throw new Error("Invalid goal format. Expected { goal: string }"); + if (!userMessage || typeof userMessage !== "string") { + throw new Error("Invalid message format. Expected { message: string }"); } - // 2.1) Plan the goal with Daydreams - sendJSON(ws, { - type: "info", - message: "Planning strategy for goal: " + userGoal, + // Process the message using the orchestrator + const outputs = await orchestrator.dispatchToInput("user_chat", { + content: userMessage, + userId: "ws-user", }); - await dreams.decomposeObjectiveIntoGoals(userGoal); - - // 2.2) Execute goals until there are no more โ€œreadyโ€ goals - const stats = { completed: 0, failed: 0, total: 0 }; - - while (true) { - const readyGoals = dreams.goalManager.getReadyGoals(); - const activeGoals = dreams.goalManager - .getGoalsByHorizon("short") - .filter((g) => g.status === "active"); - const pendingGoals = dreams.goalManager - .getGoalsByHorizon("short") - .filter((g) => g.status === "pending"); - - // Check if all goals are completed - if ( - readyGoals.length === 0 && - activeGoals.length === 0 && - pendingGoals.length === 0 - ) { - sendJSON(ws, { - type: "info", - message: "All goals completed!", - }); - break; - } - - // Check if we are blocked - if (readyGoals.length === 0 && activeGoals.length === 0) { - sendJSON(ws, { - type: "warn", - message: "No ready or active goals, but some goals are pending. Possibly blocked.", - }); - break; + // Send responses back through WebSocket + if (outputs && outputs.length > 0) { + for (const out of outputs) { + if (out.name === "chat_reply") { + sendJSON(ws, { + type: "response", + message: out.data.message, + }); + } } - - // Execute the next ready goal - try { - await dreams.processHighestPriorityGoal(); - stats.completed++; - } catch (err) { - console.error("[WS] Goal execution failed:", err); - stats.failed++; - break; // For simplicity, we stop here - } - stats.total++; } - // Send a final summary to the client - sendJSON(ws, { - type: "summary", - message: `Goal execution done. Completed: ${stats.completed}, Failed: ${stats.failed}, Total: ${stats.total}.`, - }); } catch (error) { console.error(chalk.red("[WS] Error processing message:"), error); sendJSON(ws, { @@ -200,8 +154,19 @@ wss.on("connection", (ws) => { } }); - // If the client closes the connection ws.on("close", () => { console.log(chalk.yellow("[WS] Client disconnected.")); }); }); + +// Handle graceful shutdown +process.on("SIGINT", async () => { + console.log(chalk.yellow("\n\nShutting down...")); + + // Close WebSocket server + wss.close(() => { + console.log(chalk.green("โœ… WebSocket server closed")); + }); + + process.exit(0); +}); From cb6f8cdfcffd57ed601448d4f7acce6dd3d59a77 Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 21:33:54 +0100 Subject: [PATCH 09/12] update readme --- clients/example-ui/README.md | 6 ++++++ package.json | 1 + 2 files changed, 7 insertions(+) diff --git a/clients/example-ui/README.md b/clients/example-ui/README.md index 74872fd4..c5b498bc 100644 --- a/clients/example-ui/README.md +++ b/clients/example-ui/README.md @@ -7,6 +7,12 @@ Currently, two official plugins are available: - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +## Chat with your Agent + +1. Run the server: `pnpm run server` +2. Run the UI: `pnpm run ui` +3. Start chatting with your agent! + ## Expanding the ESLint configuration If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: diff --git a/package.json b/package.json index b99e9ed7..3e8395f4 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "twitter": "bun run examples/example-twitter.ts", "server": "bun run examples/example-server.ts", "api": "bun run examples/example-api.ts", + "ui": "pnpm --dir clients/example-ui run dev", "test": "bun run packages/core", "build": "pnpm --dir packages/core run build", "release": "pnpm build && pnpm prettier && npx lerna publish --no-private --force-publish", From 2af99bdf0407a13ccb92a09c341ad0204ee43c6a Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 21:38:15 +0100 Subject: [PATCH 10/12] remove example zidle --- examples/example-zidle.ts | 485 -------------------------------------- 1 file changed, 485 deletions(-) delete mode 100644 examples/example-zidle.ts diff --git a/examples/example-zidle.ts b/examples/example-zidle.ts deleted file mode 100644 index 10cadea1..00000000 --- a/examples/example-zidle.ts +++ /dev/null @@ -1,485 +0,0 @@ -import { LLMClient } from "../packages/core/src/core/llm-client"; -import { ChainOfThought } from "../packages/core/src/core/chain-of-thought"; -import { PROVIDER_GUIDE, ZIDLE_CONTEXT } from "./zidle/zidle"; -import chalk from "chalk"; -import { JSONSchemaType } from "ajv"; -import { ChromaVectorDB } from "../packages/core/src/core/vector-db"; -import { GoalStatus, LogLevel } from "../packages/core/src/types"; -import { z } from "zod"; -import { StarknetChain } from "../packages/core/src/core/chains/starknet"; -import { fetchGraphQL } from "../packages/core/src/core/providers"; -import { env } from "../packages/core/src/core/env"; -import readline from "readline"; - -/** - * Helper function to get user input from CLI - */ -async function getCliInput(prompt: string): Promise { - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - }); - - formatDialog("zIdle", prompt); - return new Promise((resolve) => { - rl.question(chalk.green("\n๐Ÿ‘ค You: "), (answer) => { - rl.close(); - resolve(answer); - }); - }); -} - -/** - * Helper function to format goal status with colored icons - */ -function printGoalStatus(status: GoalStatus): string { - const colors: Record = { - pending: chalk.yellow("โณ PENDING"), - active: chalk.blue("โ–ถ๏ธ ACTIVE"), - completed: chalk.green("โœ… COMPLETED"), - failed: chalk.red("โŒ FAILED"), - ready: chalk.cyan("๐ŸŽฏ READY"), - blocked: chalk.red("๐Ÿšซ BLOCKED"), - }; - return colors[status] || status; -} - -// Add a helper function to format console messages as dialog -function formatDialog( - speaker: "zIdle" | "user" | "system", - message: string -): void { - switch (speaker) { - case "zIdle": - console.log(chalk.blue(`\n๐Ÿค– zIdle: ${message}`)); - break; - case "user": - console.log(chalk.green(`\n๐Ÿ‘ค You: ${message}`)); - break; - case "system": - console.log(chalk.gray(`\n๐Ÿ”ง System: ${message}`)); - break; - } -} - -async function main() { - // Initialize LLM client - const llmClient = new LLMClient({ - model: "anthropic/claude-3-5-sonnet-latest", //"deepseek/deepseek-r1", //"anthropic/claude-3.5-haiku-20241022:beta" - }); - - const memory = new ChromaVectorDB("agent_memory", { - chromaUrl: "http://localhost:8000", - logLevel: LogLevel.WARN, - }); - await memory.purge(); // Clear previous session data - - const starknetChain = new StarknetChain({ - rpcUrl: env.STARKNET_RPC_URL, - address: env.STARKNET_ADDRESS, - privateKey: env.STARKNET_PRIVATE_KEY, - }); - - // Load initial context documents - await memory.storeDocument({ - title: "Game Rules", - content: ZIDLE_CONTEXT, - category: "rules", - tags: ["game-mechanics", "rules"], - lastUpdated: new Date(), - }); - - await memory.storeDocument({ - title: "Provider Guide", - content: PROVIDER_GUIDE, - category: "actions", - tags: ["actions", "provider-guide"], - lastUpdated: new Date(), - }); - - // Initialize the main reasoning engine - const dreams = new ChainOfThought( - llmClient, - memory, - { - worldState: ZIDLE_CONTEXT, - providerContext: PROVIDER_GUIDE, - }, - { logLevel: LogLevel.DEBUG } - ); - - dreams.registerOutput({ - name: "EXECUTE_READ", - handler: async (data: any) => { - const result = await starknetChain.read(data.payload); - return `Transaction: ${JSON.stringify(result, null, 2)}`; - }, - schema: z - .object({ - contractAddress: z - .string() - .describe("The address of the contract to read from"), - entrypoint: z - .string() - .describe("The entrypoint to call on the contract"), - calldata: z - .array(z.union([z.number(), z.string()])) - .describe("The calldata to pass to the entrypoint"), - }) - .describe( - "The payload to use to call, never include slashes or comments" - ), - }); - - dreams.registerOutput({ - name: "EXECUTE_TRANSACTION", - handler: async (data: any) => { - const result = await starknetChain.write(data.payload); - return `Transaction: ${JSON.stringify(result, null, 2)}`; - }, - schema: z - .object({ - contractAddress: z - .string() - .describe( - "The address of the contract to execute the transaction on" - ), - entrypoint: z - .string() - .describe("The entrypoint to call on the contract"), - calldata: z - .array(z.union([z.number(), z.string()])) - .describe("The calldata to pass to the entrypoint"), - }) - .describe( - "The payload to execute the transaction, never include slashes or comments" - ), - }); - - dreams.registerOutput({ - name: "GRAPHQL_FETCH", - handler: async (data: any) => { - console.log("[GRAPHQL_FETCH handler] data", data); - const { query, variables } = data.payload ?? {}; - const result = await fetchGraphQL( - env.GRAPHQL_URL + "/graphql", - query, - variables - ); - const resultStr = [ - `query: ${query}`, - `result: ${JSON.stringify(result, null, 2)}`, - ].join("\n\n"); - return `GraphQL data fetched successfully: ${resultStr}`; - }, - schema: z - .object({ - query: z - .string() - .describe( - `query ZidleMinerModels { zidleMinerModels(where: { token_id: "0x10" }) {totalCount edges { node { resource_type xp } } } }` - ), - }) - .describe( - "The payload to fetch data from the zIdle GraphQL API, never include slashes or comments" - ), - }); - - // Set up event logging - - // Thought process events - dreams.on("step", (step) => { - if (step.type === "system") { - formatDialog("system", step.content); - } else { - formatDialog("zIdle", `Thinking: ${step.content}`); - } - }); - - // Uncomment to log token usage - // llmClient.on("trace:tokens", ({ input, output }) => { - // console.log("\n๐Ÿ’ก Tokens used:", { input, output }); - // }); - - // Action execution events - dreams.on("action:start", (action) => { - formatDialog("zIdle", `I'm going to ${action.type}...`); - }); - - dreams.on("action:complete", ({ action, result }) => { - formatDialog("zIdle", `I've completed ${action.type}. Result: ${result}`); - }); - - dreams.on("action:error", ({ action, error }) => { - formatDialog("system", `Failed to ${action.type}: ${error}`); - }); - - // Thinking process events - dreams.on("think:start", ({ query }) => { - console.log("\n๐Ÿง  Starting to think about:", query); - }); - - dreams.on("think:complete", ({ query }) => { - console.log("\n๐ŸŽ‰ Finished thinking about:", query); - }); - - dreams.on("think:timeout", ({ query }) => { - console.log("\nโฐ Thinking timed out for:", query); - }); - - dreams.on("think:error", ({ query, error }) => { - console.log("\n๐Ÿ’ฅ Error while thinking about:", query, error); - }); - - // Goal management events - dreams.on("goal:created", ({ id, description }) => { - console.log(chalk.cyan("\n๐ŸŽฏ New goal created:"), { - id, - description, - }); - }); - - dreams.on("goal:updated", ({ id, status }) => { - console.log(chalk.yellow("\n๐Ÿ“ Goal status updated:"), { - id, - status: printGoalStatus(status), - }); - }); - - dreams.on("goal:completed", ({ id, result }) => { - console.log(chalk.green("\nโœจ Goal completed:"), { - id, - result, - }); - }); - - dreams.on("goal:failed", ({ id, error }) => { - console.log(chalk.red("\n๐Ÿ’ฅ Goal failed:"), { - id, - error: error instanceof Error ? error.message : String(error), - }); - }); - - // Memory management events - dreams.on("memory:experience_stored", ({ experience }) => { - console.log(chalk.blue("\n๐Ÿ’พ New experience stored:"), { - action: experience.action, - outcome: experience.outcome, - importance: experience.importance, - timestamp: experience.timestamp, - }); - - if (experience.emotions?.length) { - console.log( - chalk.blue("๐Ÿ˜Š Emotional context:"), - experience.emotions.join(", ") - ); - } - }); - - dreams.on("memory:knowledge_stored", ({ document }) => { - console.log(chalk.magenta("\n๐Ÿ“š New knowledge documented:"), { - title: document.title, - category: document.category, - tags: document.tags, - lastUpdated: document.lastUpdated, - }); - console.log(chalk.magenta("๐Ÿ“ Content:"), document.content); - }); - - dreams.on("memory:experience_retrieved", ({ experiences }) => { - console.log(chalk.yellow("\n๐Ÿ” Relevant past experiences found:")); - experiences.forEach((exp, index) => { - console.log(chalk.yellow(`\n${index + 1}. Previous Experience:`)); - console.log(` Action: ${exp.action}`); - console.log(` Outcome: ${exp.outcome}`); - console.log(` Importance: ${exp.importance || "N/A"}`); - if (exp.emotions?.length) { - console.log(` Emotions: ${exp.emotions.join(", ")}`); - } - }); - }); - - dreams.on("memory:knowledge_retrieved", ({ documents }) => { - console.log(chalk.green("\n๐Ÿ“– Relevant knowledge retrieved:")); - documents.forEach((doc, index) => { - console.log(chalk.green(`\n${index + 1}. Knowledge Entry:`)); - console.log(` Title: ${doc.title}`); - console.log(` Category: ${doc.category}`); - console.log(` Tags: ${doc.tags.join(", ")}`); - console.log(` Content: ${doc.content}`); - }); - }); - - // Start the AI agent - /*try { - console.log(chalk.cyan("\n๐Ÿค– Starting zIdle AI agent...")); - - // Initial analysis - const result = await dreams.think( - "First Goal: Get NFT token ID before proceeding with any other actions. When this goal is done you can start mining resources efficiently to maximize XP gain" - ); - - console.log(chalk.green("\nโœจ Initial analysis completed!")); - console.log("Strategy:", result); - - // Continue monitoring and adjusting strategy - setInterval(async () => { - await dreams.think( - "Review current progress and adjust farming strategy if needed. Consider resource levels, XP gains, and whether we should switch resources." - ); - }, 5 * 60 * 1000); // Check every 5 minutes - } catch (error) { - console.error(chalk.red("Error running AI agent:"), error); - }*/ - - // Handle shutdown - process.on("SIGINT", async () => { - console.log(chalk.yellow("\nShutting down zIdle AI agent...")); - process.exit(0); - }); - - // Main interaction loop - const main_goal = - "Mine resources (wood and mineral) efficiently to maximize XP gain"; - while (true) { - try { - // Plan and execute goals - console.log(chalk.cyan("\n๐Ÿค” Planning strategy for goal...")); - await dreams.decomposeObjectiveIntoGoals(main_goal); - - console.log(chalk.cyan("\n๐ŸŽฏ Executing goals...")); - - const stats = { - completed: 0, - failed: 0, - total: 0, - }; - - // Execute goals until completion - while (true) { - const readyGoals = dreams.goalManager.getReadyGoals(); - console.log("-------------------- readyGoals", readyGoals); - const activeGoals = dreams.goalManager - .getGoalsByHorizon("short") - .filter((g) => g.status === "active"); - const pendingGoals = dreams.goalManager - .getGoalsByHorizon("short") - .filter((g) => g.status === "pending"); - console.log("-------------------- activeGoals", activeGoals); - console.log("-------------------- pendingGoals", pendingGoals); - - // Status update - console.log(chalk.cyan("\n๐Ÿ“Š Current Progress:")); - console.log(`Ready goals: ${readyGoals.length}`); - console.log(`Active goals: ${activeGoals.length}`); - console.log(`Pending goals: ${pendingGoals.length}`); - console.log(`Completed: ${stats.completed}`); - console.log(`Failed: ${stats.failed}`); - - // Check if all goals are complete - if ( - readyGoals.length === 0 && - activeGoals.length === 0 && - pendingGoals.length === 0 - ) { - console.log(chalk.green("\nโœจ All goals completed!")); - break; - } - - // Handle blocked goals - if (readyGoals.length === 0 && activeGoals.length === 0) { - console.log( - chalk.yellow( - "\nโš ๏ธ No ready or active goals, but some goals are pending:" - ) - ); - pendingGoals.forEach((goal) => { - const blockingGoals = dreams.goalManager.getBlockingGoals(goal.id); - console.log(chalk.yellow(`\n๐Ÿ“Œ Pending Goal: ${goal.description}`)); - console.log( - chalk.yellow(` Blocked by: ${blockingGoals.length} goals`) - ); - blockingGoals.forEach((blocking) => { - console.log( - chalk.yellow( - ` - ${blocking.description} (${blocking.status})` - ) - ); - }); - }); - break; - } - - // Execute next goal - try { - await dreams.processHighestPriorityGoal(); - stats.completed++; - } catch (error) { - console.error(chalk.red("\nโŒ Goal execution failed:"), error); - stats.failed++; - - // Ask to continue - const shouldContinue = await getCliInput( - chalk.yellow("\nContinue executing remaining goals? (y/n): ") - ); - - if (shouldContinue.toLowerCase() !== "y") { - console.log(chalk.yellow("Stopping goal execution.")); - break; - } - } - - stats.total++; - } - - // Learning summary - console.log(chalk.cyan("\n๐Ÿ“Š Learning Summary:")); - - const recentExperiences = await dreams.memory.getRecentEpisodes(5); - console.log(chalk.blue("\n๐Ÿ”„ Recent Experiences:")); - recentExperiences.forEach((exp, index) => { - console.log(chalk.blue(`\n${index + 1}. Experience:`)); - console.log(` Action: ${exp.action}`); - console.log(` Outcome: ${exp.outcome}`); - console.log(` Importance: ${exp.importance || "N/A"}`); - }); - - const relevantDocs = await dreams.memory.findSimilarDocuments( - main_goal, - 3 - ); - console.log(chalk.magenta("\n๐Ÿ“š Accumulated Knowledge:")); - relevantDocs.forEach((doc, index) => { - console.log(chalk.magenta(`\n${index + 1}. Knowledge Entry:`)); - console.log(` Title: ${doc.title}`); - console.log(` Category: ${doc.category}`); - console.log(` Tags: ${doc.tags.join(", ")}`); - }); - - // Final execution summary - console.log(chalk.cyan("\n๐Ÿ“Š Final Execution Summary:")); - console.log(chalk.green(`โœ… Completed Goals: ${stats.completed}`)); - console.log(chalk.red(`โŒ Failed Goals: ${stats.failed}`)); - console.log( - chalk.blue( - `๐Ÿ“ˆ Success Rate: ${Math.round( - (stats.completed / stats.total) * 100 - )}%` - ) - ); - console.log( - chalk.yellow( - `๐Ÿง  Learning Progress: ${recentExperiences.length} new experiences, ${relevantDocs.length} relevant knowledge entries` - ) - ); - } catch (error) { - console.error(chalk.red("Error processing goal:"), error); - } - } -} - -main().catch((error) => { - console.error(chalk.red("Fatal error:"), error); - process.exit(1); -}); From 3435dda6e6bc33e3bab7a146cf3e308edb348bec Mon Sep 17 00:00:00 2001 From: Cheelax Date: Sat, 25 Jan 2025 22:02:28 +0100 Subject: [PATCH 11/12] env var and gitignore --- .gitignore | 21 +++++++++++++++++++++ clients/example-ui/.env.example | 1 + clients/example-ui/.env.production | 1 + packages/core/src/core/env.ts | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 clients/example-ui/.env.example create mode 100644 clients/example-ui/.env.production diff --git a/.gitignore b/.gitignore index 03142b77..658b5f56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,17 @@ # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore +# VSCode settings +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local history for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix # Logs @@ -177,3 +190,11 @@ dist # Logs logs/app-*.log + +# Environment files +.env +.env.local +.env.*.local + +# But keep examples +!.env.example diff --git a/clients/example-ui/.env.example b/clients/example-ui/.env.example new file mode 100644 index 00000000..71f45ed7 --- /dev/null +++ b/clients/example-ui/.env.example @@ -0,0 +1 @@ +VITE_WEBSOCKET_URL=ws://localhost:8080 \ No newline at end of file diff --git a/clients/example-ui/.env.production b/clients/example-ui/.env.production new file mode 100644 index 00000000..65f87ad8 --- /dev/null +++ b/clients/example-ui/.env.production @@ -0,0 +1 @@ +VITE_WEBSOCKET_URL=wss://your-production-url.com \ No newline at end of file diff --git a/packages/core/src/core/env.ts b/packages/core/src/core/env.ts index f1275929..43796e83 100644 --- a/packages/core/src/core/env.ts +++ b/packages/core/src/core/env.ts @@ -11,9 +11,9 @@ const envSchema = z.object({ STARKNET_PRIVATE_KEY: z.string(), OPENROUTER_API_KEY: z.string(), GRAPHQL_URL: z.string(), + WEBSOCKET_URL: z.string().default("ws://localhost:8080"), DRY_RUN: z .preprocess((val) => val === "1" || val === "true", z.boolean()) .default(true), }); - export const env = envSchema.parse(process.env); From f0e0bc614c681b75570b219ce9416415a0dd1775 Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Sun, 26 Jan 2025 18:24:04 +1100 Subject: [PATCH 12/12] styles --- clients/example-ui/src/App.tsx | 184 ++++++++++-------- .../example-ui/src/components/app-sidebar.tsx | 135 ++++++------- .../example-ui/src/components/mode-toggle.tsx | 37 ++++ .../src/components/theme-provider.tsx | 74 +++++++ clients/example-ui/src/index.css | 98 +++++----- 5 files changed, 326 insertions(+), 202 deletions(-) create mode 100644 clients/example-ui/src/components/mode-toggle.tsx create mode 100644 clients/example-ui/src/components/theme-provider.tsx diff --git a/clients/example-ui/src/App.tsx b/clients/example-ui/src/App.tsx index c6802638..c59a0c33 100644 --- a/clients/example-ui/src/App.tsx +++ b/clients/example-ui/src/App.tsx @@ -3,108 +3,120 @@ import { MessagesList } from "@/components/message-list"; import { useDaydreamsWs } from "@/hooks/use-daydreams"; import { AppSidebar } from "@/components/app-sidebar"; import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, + Breadcrumb, + BreadcrumbItem, + BreadcrumbLink, + BreadcrumbList, } from "@/components/ui/breadcrumb"; import { Separator } from "@/components/ui/separator"; import { - SidebarInset, - SidebarProvider, - SidebarTrigger, + SidebarInset, + SidebarProvider, + SidebarTrigger, } from "@/components/ui/sidebar"; +import { ThemeProvider } from "@/components/theme-provider"; +import { ModeToggle } from "./components/mode-toggle"; + interface MessageType { - type: "user" | "assistant" | "system" | "error" | "other"; - message?: string; - error?: string; + type: "user" | "assistant" | "system" | "error" | "other"; + message?: string; + error?: string; } function App() { - const [message, setMessage] = useState(""); - const [allMessages, setAllMessages] = useState([]); - const { messages, sendGoal } = useDaydreamsWs(); + const [message, setMessage] = useState(""); + const [allMessages, setAllMessages] = useState([]); + const { messages, sendGoal } = useDaydreamsWs(); - // Synchronise les messages du hook dans allMessages - useEffect(() => { - if (messages.length === 0) return; - const lastMessage = messages[messages.length - 1]; - setAllMessages((prev) => { - // On รฉvite les doublons si le dernier message est identique - if (prev.length > 0 && JSON.stringify(prev[prev.length - 1]) === JSON.stringify(lastMessage)) { - return prev; - } - return [...prev, lastMessage]; - }); - }, [messages]); + // Synchronise les messages du hook dans allMessages + useEffect(() => { + if (messages.length === 0) return; + const lastMessage = messages[messages.length - 1]; + setAllMessages((prev: any) => { + // On รฉvite les doublons si le dernier message est identique + if ( + prev.length > 0 && + JSON.stringify(prev[prev.length - 1]) === + JSON.stringify(lastMessage) + ) { + return prev; + } + return [...prev, lastMessage]; + }); + }, [messages]); - const handleSubmit = () => { - if (!message.trim()) return; - setAllMessages((prev) => [ - ...prev, - { type: "user", message: message }, - ]); - sendGoal(message); - setMessage(""); - }; + const handleSubmit = () => { + if (!message.trim()) return; + setAllMessages((prev) => [...prev, { type: "user", message: message }]); + sendGoal(message); + setMessage(""); + }; - return ( - - - - {/* Header */} -
-
- - - - - - Home - - - -
-
+ return ( + + + + + {/* Header */} +
+
+ + + + + + + + Home + + + + +
+
- {/* Main content area */} -
- {/* Zone conversation */} -
- {/* Liste des messages */} -
- -
+ {/* Main content area */} +
+ {/* Zone conversation */} +
+ {/* Liste des messages */} +
+ +
- {/* Barre d'input en bas */} -
- setMessage(e.target.value)} - onKeyDown={(e) => { - if (e.key === "Enter") { - handleSubmit(); - } - }} - placeholder="Type your message..." - className="flex-1 px-4 py-2 rounded-lg border border-border bg-background text-foreground + {/* Barre d'input en bas */} +
+ setMessage(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter") { + handleSubmit(); + } + }} + placeholder="Type your message..." + className="flex-1 px-4 py-2 rounded-lg border border-border bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" - /> - -
-
-
- - - ); + > + Send + +
+
+
+
+
+
+ ); } export default App; diff --git a/clients/example-ui/src/components/app-sidebar.tsx b/clients/example-ui/src/components/app-sidebar.tsx index 01bc103f..b5d8d5eb 100644 --- a/clients/example-ui/src/components/app-sidebar.tsx +++ b/clients/example-ui/src/components/app-sidebar.tsx @@ -5,85 +5,86 @@ import { NavProjects } from "@/components/nav-projects"; import { NavUser } from "@/components/nav-user"; import { TeamSwitcher } from "@/components/team-switcher"; import { - Sidebar, - SidebarContent, - SidebarFooter, - SidebarHeader, - SidebarRail, + Sidebar, + SidebarContent, + SidebarFooter, + SidebarHeader, + SidebarRail, } from "@/components/ui/sidebar"; +import { ModeToggle } from "./mode-toggle"; // This is sample data. const data = { - user: { - name: "sleever", - email: "m@sleever.ai", - avatar: "/avatars/shadcn.jpg", - }, - teams: [ - { - name: "sleever", - logo: Bot, - plan: "Enterprise", + user: { + name: "sleever", + email: "m@sleever.ai", + avatar: "/avatars/shadcn.jpg", }, - ], - navMain: [ - { - title: "Agents", - url: "#", - icon: Bot, - isActive: true, - items: [ + teams: [ { - title: "My Agents", - url: "#", + name: "sleever", + logo: Bot, + plan: "Enterprise", }, + ], + navMain: [ { - title: "Create Agent", - url: "#", + title: "Agents", + url: "#", + icon: Bot, + isActive: true, + items: [ + { + title: "My Agents", + url: "#", + }, + { + title: "Create Agent", + url: "#", + }, + { + title: "Settings", + url: "#", + }, + ], }, { - title: "Settings", - url: "#", + title: "Chats", + url: "#", + icon: MessageSquare, + items: [ + { + title: "History", + url: "#", + }, + { + title: "Saved", + url: "#", + }, + { + title: "Settings", + url: "#", + }, + ], }, - ], - }, - { - title: "Chats", - url: "#", - icon: MessageSquare, - items: [ - { - title: "History", - url: "#", - }, - { - title: "Saved", - url: "#", - }, - { - title: "Settings", - url: "#", - }, - ], - }, - ], - projects: [], + ], + projects: [], }; export function AppSidebar({ ...props }: React.ComponentProps) { - return ( - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + ); } diff --git a/clients/example-ui/src/components/mode-toggle.tsx b/clients/example-ui/src/components/mode-toggle.tsx new file mode 100644 index 00000000..d9c8679f --- /dev/null +++ b/clients/example-ui/src/components/mode-toggle.tsx @@ -0,0 +1,37 @@ +import { Moon, Sun } from "lucide-react"; + +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { useTheme } from "@/components/theme-provider"; + +export function ModeToggle() { + const { setTheme } = useTheme(); + + return ( + + + + + + setTheme("light")}> + Light + + setTheme("dark")}> + Dark + + setTheme("system")}> + System + + + + ); +} diff --git a/clients/example-ui/src/components/theme-provider.tsx b/clients/example-ui/src/components/theme-provider.tsx new file mode 100644 index 00000000..68f919f5 --- /dev/null +++ b/clients/example-ui/src/components/theme-provider.tsx @@ -0,0 +1,74 @@ +import { createContext, useContext, useEffect, useState } from "react"; + +type Theme = "dark" | "light" | "system"; + +type ThemeProviderProps = { + children: React.ReactNode; + defaultTheme?: Theme; + storageKey?: string; +}; + +type ThemeProviderState = { + theme: Theme; + setTheme: (theme: Theme) => void; +}; + +const initialState: ThemeProviderState = { + theme: "system", + setTheme: () => null, +}; + +const ThemeProviderContext = createContext(initialState); + +export function ThemeProvider({ + children, + defaultTheme = "system", + storageKey = "vite-ui-theme", + ...props +}: ThemeProviderProps) { + const [theme, setTheme] = useState( + () => (localStorage.getItem(storageKey) as Theme) || defaultTheme + ); + + useEffect(() => { + const root = window.document.documentElement; + + root.classList.remove("light", "dark"); + + if (theme === "system") { + const systemTheme = window.matchMedia( + "(prefers-color-scheme: dark)" + ).matches + ? "dark" + : "light"; + + root.classList.add(systemTheme); + return; + } + + root.classList.add(theme); + }, [theme]); + + const value = { + theme, + setTheme: (theme: Theme) => { + localStorage.setItem(storageKey, theme); + setTheme(theme); + }, + }; + + return ( + + {children} + + ); +} + +export const useTheme = () => { + const context = useContext(ThemeProviderContext); + + if (context === undefined) + throw new Error("useTheme must be used within a ThemeProvider"); + + return context; +}; diff --git a/clients/example-ui/src/index.css b/clients/example-ui/src/index.css index 8cb7bc2f..184fefbc 100644 --- a/clients/example-ui/src/index.css +++ b/clients/example-ui/src/index.css @@ -4,72 +4,72 @@ @layer base { :root { --background: 0 0% 100%; - --foreground: 240 10% 3.9%; + --foreground: 20 14.3% 4.1%; --card: 0 0% 100%; - --card-foreground: 240 10% 3.9%; + --card-foreground: 20 14.3% 4.1%; --popover: 0 0% 100%; - --popover-foreground: 240 10% 3.9%; - --primary: 240 5.9% 10%; - --primary-foreground: 0 0% 98%; - --secondary: 240 4.8% 95.9%; - --secondary-foreground: 240 5.9% 10%; - --muted: 240 4.8% 95.9%; - --muted-foreground: 240 3.8% 46.1%; - --accent: 240 4.8% 95.9%; - --accent-foreground: 240 5.9% 10%; + --popover-foreground: 20 14.3% 4.1%; + --primary: 47.9 95.8% 53.1%; + --primary-foreground: 26 83.3% 14.1%; + --secondary: 60 4.8% 95.9%; + --secondary-foreground: 24 9.8% 10%; + --muted: 60 4.8% 95.9%; + --muted-foreground: 25 5.3% 44.7%; + --accent: 60 4.8% 95.9%; + --accent-foreground: 24 9.8% 10%; --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 240 5.9% 90%; - --input: 240 5.9% 90%; - --ring: 240 5.9% 10%; + --destructive-foreground: 60 9.1% 97.8%; + --border: 20 5.9% 90%; + --input: 20 5.9% 90%; + --ring: 20 14.3% 4.1%; --radius: 0rem; --chart-1: 12 76% 61%; --chart-2: 173 58% 39%; --chart-3: 197 37% 24%; --chart-4: 43 74% 66%; --chart-5: 27 87% 67%; - --sidebar-background: 240 4.8% 95.9%; - --sidebar-foreground: 240 5.9% 10%; - --sidebar-primary: 240 5.9% 10%; - --sidebar-primary-foreground: 0 0% 98%; - --sidebar-accent: 240 4.8% 95.9%; - --sidebar-accent-foreground: 240 5.9% 10%; - --sidebar-border: 240 5.9% 90%; - --sidebar-ring: 240 5.9% 10%; + --sidebar-background: 0 0% 100%; + --sidebar-foreground: 20 14.3% 4.1%; + --sidebar-primary: 47.9 95.8% 53.1%; + --sidebar-primary-foreground: 26 83.3% 14.1%; + --sidebar-accent: 60 4.8% 95.9%; + --sidebar-accent-foreground: 24 9.8% 10%; + --sidebar-border: 20 5.9% 90%; + --sidebar-ring: 20 14.3% 4.1%; } .dark { - --background: 240 10% 3.9%; - --foreground: 0 0% 98%; - --card: 240 10% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 240 10% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 240 5.9% 10%; - --secondary: 240 3.7% 15.9%; - --secondary-foreground: 0 0% 98%; - --muted: 240 3.7% 15.9%; - --muted-foreground: 240 5% 64.9%; - --accent: 240 3.7% 15.9%; - --accent-foreground: 0 0% 98%; + --background: 20 14.3% 4.1%; + --foreground: 60 9.1% 97.8%; + --card: 20 14.3% 4.1%; + --card-foreground: 60 9.1% 97.8%; + --popover: 20 14.3% 4.1%; + --popover-foreground: 60 9.1% 97.8%; + --primary: 47.9 95.8% 53.1%; + --primary-foreground: 26 83.3% 14.1%; + --secondary: 12 6.5% 15.1%; + --secondary-foreground: 60 9.1% 97.8%; + --muted: 12 6.5% 15.1%; + --muted-foreground: 24 5.4% 63.9%; + --accent: 12 6.5% 15.1%; + --accent-foreground: 60 9.1% 97.8%; --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - --border: 240 3.7% 15.9%; - --input: 240 3.7% 15.9%; - --ring: 240 4.9% 83.9%; + --destructive-foreground: 60 9.1% 97.8%; + --border: 12 6.5% 15.1%; + --input: 12 6.5% 15.1%; + --ring: 35.5 91.7% 32.9%; --chart-1: 220 70% 50%; --chart-2: 160 60% 45%; --chart-3: 30 80% 55%; --chart-4: 280 65% 60%; --chart-5: 340 75% 55%; - --sidebar-background: 240 3.7% 15.9%; - --sidebar-foreground: 0 0% 98%; - --sidebar-primary: 0 0% 98%; - --sidebar-primary-foreground: 240 5.9% 10%; - --sidebar-accent: 240 3.7% 15.9%; - --sidebar-accent-foreground: 0 0% 98%; - --sidebar-border: 240 3.7% 15.9%; - --sidebar-ring: 240 4.9% 83.9%; + --sidebar-background: 20 14.3% 4.1%; + --sidebar-foreground: 60 9.1% 97.8%; + --sidebar-primary: 47.9 95.8% 53.1%; + --sidebar-primary-foreground: 26 83.3% 14.1%; + --sidebar-accent: 12 6.5% 15.1%; + --sidebar-accent-foreground: 60 9.1% 97.8%; + --sidebar-border: 12 6.5% 15.1%; + --sidebar-ring: 35.5 91.7% 32.9%; } } @layer base {