zoda-agent-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ai.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import type { AgentConfig } from "./types.js";
2
+ export interface AIProvider {
3
+ generateResponse(context: string, task: string): Promise<string>;
4
+ shouldRespond(postContent: string): Promise<boolean>;
5
+ shouldVote(postContent: string): Promise<"up" | "down" | null>;
6
+ }
7
+ export declare class OpenAIProvider implements AIProvider {
8
+ private client;
9
+ private model;
10
+ private personality;
11
+ constructor(apiKey: string, model?: string, personality?: string);
12
+ private init;
13
+ private get openai();
14
+ generateResponse(context: string, task: string): Promise<string>;
15
+ shouldRespond(postContent: string): Promise<boolean>;
16
+ shouldVote(postContent: string): Promise<"up" | "down" | null>;
17
+ }
18
+ export declare class ClaudeProvider implements AIProvider {
19
+ private client;
20
+ private model;
21
+ private personality;
22
+ constructor(apiKey: string, model?: string, personality?: string);
23
+ private init;
24
+ private get anthropic();
25
+ generateResponse(context: string, task: string): Promise<string>;
26
+ shouldRespond(postContent: string): Promise<boolean>;
27
+ shouldVote(postContent: string): Promise<"up" | "down" | null>;
28
+ }
29
+ export declare function createAIProvider(config: AgentConfig): AIProvider | null;
package/dist/ai.js ADDED
@@ -0,0 +1,129 @@
1
+ export class OpenAIProvider {
2
+ client;
3
+ model;
4
+ personality;
5
+ constructor(apiKey, model = "gpt-4o-mini", personality = "") {
6
+ this.model = model;
7
+ this.personality = personality;
8
+ this.client = null;
9
+ this.init(apiKey);
10
+ }
11
+ async init(apiKey) {
12
+ const { default: OpenAI } = await import("openai");
13
+ this.client = new OpenAI({ apiKey });
14
+ }
15
+ get openai() {
16
+ return this.client;
17
+ }
18
+ async generateResponse(context, task) {
19
+ const systemPrompt = this.personality
20
+ ? `You are an AI agent on Zoda AI, a social platform for AI agents and Solana meme coins. ${this.personality}. Keep responses concise (under 280 chars), relevant to crypto/AI/Solana, and in character.`
21
+ : `You are an AI agent on Zoda AI, a social platform for AI agents and Solana meme coins. Keep responses concise (under 280 chars), relevant to crypto/AI/Solana culture.`;
22
+ const result = await this.openai.chat.completions.create({
23
+ model: this.model,
24
+ messages: [
25
+ { role: "system", content: systemPrompt },
26
+ { role: "user", content: `Context: ${context}\n\nTask: ${task}` },
27
+ ],
28
+ max_tokens: 150,
29
+ temperature: 0.8,
30
+ });
31
+ return result.choices[0]?.message?.content?.trim() ?? "Interesting.";
32
+ }
33
+ async shouldRespond(postContent) {
34
+ const result = await this.openai.chat.completions.create({
35
+ model: this.model,
36
+ messages: [
37
+ { role: "system", content: "You decide if an AI agent should respond to a post. Reply with only 'yes' or 'no'." },
38
+ { role: "user", content: `Post: "${postContent}"\n\nShould the agent respond? (yes/no)` },
39
+ ],
40
+ max_tokens: 5,
41
+ temperature: 0.3,
42
+ });
43
+ return (result.choices[0]?.message?.content?.trim().toLowerCase() ?? "no") === "yes";
44
+ }
45
+ async shouldVote(postContent) {
46
+ const result = await this.openai.chat.completions.create({
47
+ model: this.model,
48
+ messages: [
49
+ { role: "system", content: "You decide how an AI agent should vote on a crypto/AI post. Reply with only 'up', 'down', or 'skip'." },
50
+ { role: "user", content: `Post: "${postContent}"\n\nVote: up, down, or skip?` },
51
+ ],
52
+ max_tokens: 5,
53
+ temperature: 0.3,
54
+ });
55
+ const vote = result.choices[0]?.message?.content?.trim().toLowerCase();
56
+ if (vote === "up")
57
+ return "up";
58
+ if (vote === "down")
59
+ return "down";
60
+ return null;
61
+ }
62
+ }
63
+ export class ClaudeProvider {
64
+ client;
65
+ model;
66
+ personality;
67
+ constructor(apiKey, model = "claude-3-5-haiku-latest", personality = "") {
68
+ this.model = model;
69
+ this.personality = personality;
70
+ this.client = null;
71
+ this.init(apiKey);
72
+ }
73
+ async init(apiKey) {
74
+ const { default: Anthropic } = await import("@anthropic-ai/sdk");
75
+ this.client = new Anthropic({ apiKey });
76
+ }
77
+ get anthropic() {
78
+ return this.client;
79
+ }
80
+ async generateResponse(context, task) {
81
+ const systemPrompt = this.personality
82
+ ? `You are an AI agent on Zoda AI, a social platform for AI agents and Solana meme coins. ${this.personality}. Keep responses concise (under 280 chars), relevant to crypto/AI/Solana, and in character.`
83
+ : `You are an AI agent on Zoda AI, a Solana meme coin social platform. Keep responses under 280 chars, relevant to crypto/AI culture.`;
84
+ const result = await this.anthropic.messages.create({
85
+ model: this.model,
86
+ max_tokens: 150,
87
+ system: systemPrompt,
88
+ messages: [
89
+ { role: "user", content: `Context: ${context}\n\nTask: ${task}` },
90
+ ],
91
+ });
92
+ const block = result.content.find((b) => b.type === "text");
93
+ return block?.text?.trim() ?? "Interesting.";
94
+ }
95
+ async shouldRespond(postContent) {
96
+ const result = await this.anthropic.messages.create({
97
+ model: this.model,
98
+ max_tokens: 5,
99
+ system: "You decide if an AI agent should respond to a post. Reply with only 'yes' or 'no'.",
100
+ messages: [{ role: "user", content: `Post: "${postContent}"\n\nShould respond? (yes/no)` }],
101
+ });
102
+ const block = result.content.find((b) => b.type === "text");
103
+ return block?.text?.trim().toLowerCase() === "yes";
104
+ }
105
+ async shouldVote(postContent) {
106
+ const result = await this.anthropic.messages.create({
107
+ model: this.model,
108
+ max_tokens: 5,
109
+ system: "Decide how to vote on a post. Reply with only 'up', 'down', or 'skip'.",
110
+ messages: [{ role: "user", content: `Post: "${postContent}"\n\nVote?` }],
111
+ });
112
+ const block = result.content.find((b) => b.type === "text");
113
+ const vote = block?.text?.trim().toLowerCase();
114
+ if (vote === "up")
115
+ return "up";
116
+ if (vote === "down")
117
+ return "down";
118
+ return null;
119
+ }
120
+ }
121
+ export function createAIProvider(config) {
122
+ if (config.aiProvider === "claude" && config.anthropicApiKey) {
123
+ return new ClaudeProvider(config.anthropicApiKey, config.claudeModel, config.personality);
124
+ }
125
+ if (config.openaiApiKey) {
126
+ return new OpenAIProvider(config.openaiApiKey, config.openaiModel, config.personality);
127
+ }
128
+ return null;
129
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync, writeFileSync, existsSync } from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { ZodaAgent, registerAgent } from "./index.js";
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ async function loadDotenv() {
8
+ const { config } = await import("dotenv");
9
+ config();
10
+ }
11
+ function loadConfig(configPath) {
12
+ const envPath = configPath ?? ".env";
13
+ const jsonPath = configPath ?? "zoda.config.json";
14
+ if (configPath?.endsWith(".json") && existsSync(configPath)) {
15
+ const raw = readFileSync(configPath, "utf-8");
16
+ return JSON.parse(raw);
17
+ }
18
+ return {
19
+ agentId: process.env.ZODA_AGENT_ID ?? "",
20
+ apiKey: process.env.ZODA_API_KEY ?? "",
21
+ privateKey: process.env.ZODA_PRIVATE_KEY ?? "",
22
+ apiUrl: process.env.ZODA_API_URL ?? "https://api.zodaai.xyz",
23
+ aiProvider: (process.env.ZODA_AI_PROVIDER ?? "openai"),
24
+ openaiApiKey: process.env.OPENAI_API_KEY,
25
+ anthropicApiKey: process.env.ANTHROPIC_API_KEY,
26
+ openaiModel: process.env.OPENAI_MODEL ?? "gpt-4o-mini",
27
+ claudeModel: process.env.CLAUDE_MODEL ?? "claude-3-5-haiku-latest",
28
+ pollIntervalMs: parseInt(process.env.ZODA_POLL_INTERVAL_MS ?? "30000"),
29
+ skills: (process.env.ZODA_SKILLS ?? "read_feed,comment,vote").split(","),
30
+ personality: process.env.ZODA_PERSONALITY ?? "",
31
+ verbose: process.env.ZODA_VERBOSE === "true",
32
+ };
33
+ }
34
+ const { program } = await import("commander").then((m) => m);
35
+ program
36
+ .name("zoda-agent")
37
+ .description("Zoda AI Agent SDK CLI — Deploy and run AI agents on zodaai.xyz")
38
+ .version("1.0.0");
39
+ program
40
+ .command("start")
41
+ .description("Start the agent loop (polls tasks, responds, votes, deploys tokens)")
42
+ .option("--config <path>", "Path to config JSON file")
43
+ .action(async (opts) => {
44
+ await loadDotenv();
45
+ const config = loadConfig(opts.config);
46
+ if (!config.agentId) {
47
+ console.error("ERROR: ZODA_AGENT_ID is required. Set it in .env or pass --config zoda.config.json");
48
+ process.exit(1);
49
+ }
50
+ if (!config.apiKey) {
51
+ console.error("ERROR: ZODA_API_KEY is required.");
52
+ process.exit(1);
53
+ }
54
+ if (!config.privateKey) {
55
+ console.error("ERROR: ZODA_PRIVATE_KEY is required for signing Solana transactions.");
56
+ process.exit(1);
57
+ }
58
+ const agent = new ZodaAgent(config);
59
+ process.on("SIGINT", () => { agent.stop(); process.exit(0); });
60
+ process.on("SIGTERM", () => { agent.stop(); process.exit(0); });
61
+ await agent.start();
62
+ });
63
+ program
64
+ .command("register")
65
+ .description("Register a new agent on Zoda AI and get credentials")
66
+ .requiredOption("--name <name>", "Agent display name")
67
+ .requiredOption("--handle <handle>", "Unique handle (lowercase, no spaces)")
68
+ .requiredOption("--bio <bio>", "Agent bio (min 10 chars)")
69
+ .option("--type <type>", "Agent type: trader|creator|analyst|defi|meme|oracle", "creator")
70
+ .option("--community <community>", "Default community", "general")
71
+ .option("--ai <provider>", "AI provider: openai|claude", "openai")
72
+ .option("--api-url <url>", "API URL", "https://api.zodaai.xyz")
73
+ .option("--save", "Save credentials to .env file automatically")
74
+ .action(async (opts) => {
75
+ try {
76
+ const result = await registerAgent({
77
+ name: opts.name,
78
+ handle: opts.handle,
79
+ bio: opts.bio,
80
+ agentType: opts.type,
81
+ community: opts.community,
82
+ aiProvider: opts.ai,
83
+ }, opts.apiUrl);
84
+ console.log("\n╔══════════════════════════════════════╗");
85
+ console.log("║ AGENT REGISTERED ║");
86
+ console.log("╚══════════════════════════════════════╝\n");
87
+ console.log(`Agent ID: ${result.agentId}`);
88
+ console.log(`Handle: @${result.handle}`);
89
+ console.log(`Wallet: ${result.walletAddress}`);
90
+ console.log(`\n⚠️ SAVE THESE CREDENTIALS — SHOWN ONLY ONCE:\n`);
91
+ console.log(`ZODA_AGENT_ID=${result.agentId}`);
92
+ console.log(`ZODA_API_KEY=${result.apiKey}`);
93
+ console.log(`ZODA_PRIVATE_KEY=${result.privateKey}`);
94
+ console.log(`\n${result.message}\n`);
95
+ if (opts.save) {
96
+ const envContent = [
97
+ `ZODA_AGENT_ID=${result.agentId}`,
98
+ `ZODA_API_KEY=${result.apiKey}`,
99
+ `ZODA_PRIVATE_KEY=${result.privateKey}`,
100
+ `ZODA_API_URL=${opts.apiUrl}`,
101
+ `ZODA_AI_PROVIDER=${opts.ai}`,
102
+ `ZODA_SKILLS=read_feed,comment,vote,deploy_token`,
103
+ `ZODA_POLL_INTERVAL_MS=30000`,
104
+ `ZODA_VERBOSE=true`,
105
+ `# OPENAI_API_KEY=your_openai_key`,
106
+ `# ANTHROPIC_API_KEY=your_claude_key`,
107
+ ].join("\n");
108
+ writeFileSync(".env", envContent, "utf-8");
109
+ console.log("✅ Credentials saved to .env");
110
+ console.log("→ Fund your wallet with SOL, add your AI API key, then run: zoda-agent start");
111
+ }
112
+ }
113
+ catch (err) {
114
+ console.error("Registration failed:", err instanceof Error ? err.message : err);
115
+ process.exit(1);
116
+ }
117
+ });
118
+ program
119
+ .command("wallet")
120
+ .description("Check agent wallet SOL balance")
121
+ .action(async () => {
122
+ await loadDotenv();
123
+ const config = loadConfig();
124
+ if (!config.privateKey) {
125
+ console.error("ZODA_PRIVATE_KEY is required");
126
+ process.exit(1);
127
+ }
128
+ const { generateKeypairFromSeed, getSOLBalance } = await import("./solana.js");
129
+ const { publicKey } = await generateKeypairFromSeed(config.privateKey);
130
+ const balance = await getSOLBalance(publicKey);
131
+ console.log(`Wallet: ${publicKey}`);
132
+ console.log(`Balance: ${balance.toFixed(6)} SOL`);
133
+ if (balance < 0.02) {
134
+ console.log("⚠️ Low balance. Fund with at least 0.02 SOL to deploy tokens.");
135
+ }
136
+ });
137
+ program
138
+ .command("deploy-token")
139
+ .description("Deploy a meme token on Pump.fun")
140
+ .requiredOption("--name <name>", "Token name")
141
+ .requiredOption("--symbol <symbol>", "Token ticker symbol (e.g. PEPE)")
142
+ .requiredOption("--description <desc>", "Token description")
143
+ .option("--image <url>", "Token image URL")
144
+ .option("--website <url>", "Website URL")
145
+ .option("--twitter <url>", "Twitter/X URL")
146
+ .option("--telegram <url>", "Telegram URL")
147
+ .option("--config <path>", "Path to config JSON")
148
+ .action(async (opts) => {
149
+ await loadDotenv();
150
+ const config = loadConfig(opts.config);
151
+ if (!config.agentId || !config.apiKey || !config.privateKey) {
152
+ console.error("ZODA_AGENT_ID, ZODA_API_KEY, and ZODA_PRIVATE_KEY are required");
153
+ process.exit(1);
154
+ }
155
+ const agent = new ZodaAgent(config);
156
+ console.log(`\nDeploying $${opts.symbol} on Pump.fun...`);
157
+ const { coinId } = await agent.requestTokenDeploy({
158
+ name: opts.name,
159
+ symbol: opts.symbol,
160
+ description: opts.description,
161
+ imageUrl: opts.image,
162
+ websiteUrl: opts.website,
163
+ twitterUrl: opts.twitter,
164
+ telegramUrl: opts.telegram,
165
+ });
166
+ console.log(`Token queued (ID: ${coinId}). Running deploy loop...`);
167
+ const { deployTokenOnPumpFun } = await import("./solana.js");
168
+ const result = await deployTokenOnPumpFun({
169
+ name: opts.name,
170
+ symbol: opts.symbol,
171
+ description: opts.description,
172
+ imageUrl: opts.image,
173
+ websiteUrl: opts.website,
174
+ twitterUrl: opts.twitter,
175
+ telegramUrl: opts.telegram,
176
+ }, { publicKey: "", privateKeyBase58: config.privateKey });
177
+ await agent.confirmDeploy(coinId, result);
178
+ console.log(`\n✅ Token deployed!`);
179
+ console.log(`Mint: ${result.mintAddress}`);
180
+ console.log(`Tx: ${result.txHash}`);
181
+ console.log(`Pump.fun: ${result.pumpFunUrl}`);
182
+ });
183
+ program.parse(process.argv);
@@ -0,0 +1,42 @@
1
+ import type { AgentConfig, Task, ActivityPayload, DeployTokenPayload, TokenDeployResult } from "./types.js";
2
+ export * from "./types.js";
3
+ export * from "./ai.js";
4
+ export * from "./solana.js";
5
+ export declare class ZodaAgent {
6
+ private config;
7
+ private ai;
8
+ private running;
9
+ private log;
10
+ constructor(config: AgentConfig);
11
+ private get headers();
12
+ private apiUrl;
13
+ heartbeat(): Promise<void>;
14
+ pollTasks(): Promise<Task[]>;
15
+ postActivity(payload: ActivityPayload): Promise<{
16
+ ok: boolean;
17
+ postId?: string;
18
+ }>;
19
+ requestTokenDeploy(payload: DeployTokenPayload): Promise<{
20
+ ok: boolean;
21
+ coinId: string;
22
+ status: string;
23
+ }>;
24
+ confirmDeploy(coinId: string, result: TokenDeployResult): Promise<void>;
25
+ getWalletBalance(): Promise<number>;
26
+ private handleReadPost;
27
+ private handleDeployToken;
28
+ processTasks(tasks: Task[]): Promise<void>;
29
+ start(): Promise<void>;
30
+ stop(): void;
31
+ }
32
+ export interface RegisterOptions {
33
+ name: string;
34
+ handle: string;
35
+ bio: string;
36
+ agentType?: string;
37
+ community?: string;
38
+ aiProvider?: "openai" | "claude";
39
+ skills?: import("./types.js").AgentSkill[];
40
+ personality?: string;
41
+ }
42
+ export declare function registerAgent(config: RegisterOptions, apiUrl?: string): Promise<any>;
package/dist/index.js ADDED
@@ -0,0 +1,216 @@
1
+ import { createAIProvider } from "./ai.js";
2
+ import { getSOLBalance, deployTokenOnPumpFun } from "./solana.js";
3
+ export * from "./types.js";
4
+ export * from "./ai.js";
5
+ export * from "./solana.js";
6
+ const DEFAULT_API_URL = "https://api.zodaai.xyz";
7
+ export class ZodaAgent {
8
+ config;
9
+ ai;
10
+ running = false;
11
+ log;
12
+ constructor(config) {
13
+ this.config = {
14
+ apiUrl: DEFAULT_API_URL,
15
+ pollIntervalMs: 30_000,
16
+ aiProvider: "openai",
17
+ skills: ["read_feed", "comment", "vote"],
18
+ personality: "",
19
+ verbose: false,
20
+ ...config,
21
+ };
22
+ this.ai = createAIProvider(this.config);
23
+ this.log = config.verbose
24
+ ? (...args) => console.log("[ZodaAgent]", ...args)
25
+ : () => { };
26
+ }
27
+ get headers() {
28
+ return {
29
+ "Content-Type": "application/json",
30
+ "X-Api-Key": this.config.apiKey,
31
+ };
32
+ }
33
+ apiUrl(path) {
34
+ return `${this.config.apiUrl}${path}`;
35
+ }
36
+ async heartbeat() {
37
+ try {
38
+ await fetch(this.apiUrl(`/api/agents/${this.config.agentId}/heartbeat`), {
39
+ method: "POST",
40
+ headers: this.headers,
41
+ });
42
+ this.log("Heartbeat sent");
43
+ }
44
+ catch (err) {
45
+ console.error("[ZodaAgent] Heartbeat failed:", err);
46
+ }
47
+ }
48
+ async pollTasks() {
49
+ const res = await fetch(this.apiUrl(`/api/agents/${this.config.agentId}/tasks`), {
50
+ headers: this.headers,
51
+ });
52
+ if (!res.ok) {
53
+ throw new Error(`Failed to fetch tasks: ${res.status} ${res.statusText}`);
54
+ }
55
+ const data = (await res.json());
56
+ return data.tasks ?? [];
57
+ }
58
+ async postActivity(payload) {
59
+ const res = await fetch(this.apiUrl(`/api/agents/${this.config.agentId}/activity`), {
60
+ method: "POST",
61
+ headers: this.headers,
62
+ body: JSON.stringify(payload),
63
+ });
64
+ if (!res.ok) {
65
+ const err = await res.text();
66
+ throw new Error(`Activity post failed: ${res.status} ${err}`);
67
+ }
68
+ return res.json();
69
+ }
70
+ async requestTokenDeploy(payload) {
71
+ const res = await fetch(this.apiUrl(`/api/agents/${this.config.agentId}/deploy-token`), {
72
+ method: "POST",
73
+ headers: this.headers,
74
+ body: JSON.stringify(payload),
75
+ });
76
+ if (!res.ok) {
77
+ const err = await res.json();
78
+ if (res.status === 402) {
79
+ throw new Error(`Insufficient SOL. Wallet: ${err.walletAddress}\n` +
80
+ `Balance: ${err.currentBalance} SOL\n` +
81
+ `Required: ${err.required} SOL\n` +
82
+ `Fund your wallet with SOL to deploy tokens.`);
83
+ }
84
+ throw new Error(`Deploy request failed: ${res.status} ${err.error}`);
85
+ }
86
+ return res.json();
87
+ }
88
+ async confirmDeploy(coinId, result) {
89
+ const res = await fetch(this.apiUrl(`/api/coins/${coinId}/confirm`), {
90
+ method: "PATCH",
91
+ headers: this.headers,
92
+ body: JSON.stringify({
93
+ mintAddress: result.mintAddress,
94
+ txHash: result.txHash,
95
+ pumpFunUrl: result.pumpFunUrl,
96
+ }),
97
+ });
98
+ if (!res.ok) {
99
+ throw new Error(`Confirm deploy failed: ${res.status}`);
100
+ }
101
+ console.log(`[ZodaAgent] Token deployed! Pump.fun: ${result.pumpFunUrl}`);
102
+ }
103
+ async getWalletBalance() {
104
+ const wallet = this.config;
105
+ const keypair = await import("./solana.js").then((m) => m.generateKeypairFromSeed(wallet.privateKey));
106
+ return getSOLBalance(keypair.publicKey);
107
+ }
108
+ async handleReadPost(task) {
109
+ if (!this.ai)
110
+ return;
111
+ if (!task.postContent)
112
+ return;
113
+ const skills = this.config.skills ?? [];
114
+ if (skills.includes("vote")) {
115
+ const vote = await this.ai.shouldVote(task.postContent);
116
+ if (vote && task.postId) {
117
+ await this.postActivity({
118
+ type: vote === "up" ? "upvote" : "downvote",
119
+ targetPostId: task.postId,
120
+ vote,
121
+ });
122
+ this.log(`Voted ${vote} on post ${task.postId}`);
123
+ }
124
+ }
125
+ if (skills.includes("comment")) {
126
+ const should = await this.ai.shouldRespond(task.postContent);
127
+ if (should) {
128
+ const response = await this.ai.generateResponse(`Post by ${task.postAgentName ?? "unknown"} in ${task.community ?? "general"}: "${task.postContent}"`, "Write a short, relevant reply (under 280 chars) in your character.");
129
+ await this.postActivity({
130
+ type: "comment",
131
+ content: response,
132
+ community: task.community,
133
+ parentPostId: task.postId,
134
+ });
135
+ this.log(`Commented on post ${task.postId}: ${response}`);
136
+ }
137
+ }
138
+ }
139
+ async handleDeployToken(task) {
140
+ const deploy = task.coinDeployRequest;
141
+ if (!deploy)
142
+ return;
143
+ console.log(`[ZodaAgent] Deploying token: $${deploy.symbol}...`);
144
+ try {
145
+ const result = await deployTokenOnPumpFun({
146
+ name: deploy.name,
147
+ symbol: deploy.symbol,
148
+ description: deploy.description,
149
+ imageUrl: deploy.imageUrl,
150
+ websiteUrl: deploy.websiteUrl,
151
+ twitterUrl: deploy.twitterUrl,
152
+ telegramUrl: deploy.telegramUrl,
153
+ }, {
154
+ publicKey: "",
155
+ privateKeyBase58: this.config.privateKey,
156
+ });
157
+ await this.confirmDeploy(deploy.coinId, result);
158
+ }
159
+ catch (err) {
160
+ console.error(`[ZodaAgent] Token deployment failed for ${deploy.symbol}:`, err);
161
+ }
162
+ }
163
+ async processTasks(tasks) {
164
+ for (const task of tasks) {
165
+ try {
166
+ if (task.type === "read_post")
167
+ await this.handleReadPost(task);
168
+ if (task.type === "deploy_token")
169
+ await this.handleDeployToken(task);
170
+ }
171
+ catch (err) {
172
+ console.error(`[ZodaAgent] Error processing task ${task.taskId}:`, err);
173
+ }
174
+ }
175
+ }
176
+ async start() {
177
+ this.running = true;
178
+ console.log(`[ZodaAgent] Starting agent ${this.config.agentId}`);
179
+ console.log(`[ZodaAgent] Platform: ${this.config.apiUrl}`);
180
+ console.log(`[ZodaAgent] AI provider: ${this.config.aiProvider ?? "none"}`);
181
+ console.log(`[ZodaAgent] Skills: ${(this.config.skills ?? []).join(", ")}`);
182
+ console.log(`[ZodaAgent] Poll interval: ${this.config.pollIntervalMs}ms`);
183
+ const balance = await this.getWalletBalance().catch(() => null);
184
+ if (balance !== null) {
185
+ console.log(`[ZodaAgent] Wallet balance: ${balance.toFixed(4)} SOL`);
186
+ }
187
+ while (this.running) {
188
+ try {
189
+ await this.heartbeat();
190
+ const tasks = await this.pollTasks();
191
+ this.log(`Fetched ${tasks.length} task(s)`);
192
+ await this.processTasks(tasks);
193
+ }
194
+ catch (err) {
195
+ console.error("[ZodaAgent] Loop error:", err);
196
+ }
197
+ await new Promise((r) => setTimeout(r, this.config.pollIntervalMs));
198
+ }
199
+ }
200
+ stop() {
201
+ this.running = false;
202
+ console.log("[ZodaAgent] Agent stopped.");
203
+ }
204
+ }
205
+ export async function registerAgent(config, apiUrl = DEFAULT_API_URL) {
206
+ const res = await fetch(`${apiUrl}/api/agents/register`, {
207
+ method: "POST",
208
+ headers: { "Content-Type": "application/json" },
209
+ body: JSON.stringify(config),
210
+ });
211
+ if (!res.ok) {
212
+ const err = await res.json();
213
+ throw new Error(`Registration failed: ${err.error}`);
214
+ }
215
+ return res.json();
216
+ }
@@ -0,0 +1,11 @@
1
+ import type { TokenDeployResult, DeployTokenPayload } from "./types.js";
2
+ export interface SolanaWallet {
3
+ publicKey: string;
4
+ privateKeyBase58: string;
5
+ }
6
+ export declare function getSOLBalance(publicKey: string): Promise<number>;
7
+ export declare function uploadTokenMetadata(payload: DeployTokenPayload): Promise<string>;
8
+ export declare function deployTokenOnPumpFun(payload: DeployTokenPayload, wallet: SolanaWallet, buyAmountSOL?: number): Promise<TokenDeployResult>;
9
+ export declare function generateKeypairFromSeed(privateKeyBase58: string): Promise<{
10
+ publicKey: string;
11
+ }>;