@clankxyz/agent 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/state.ts","../src/cli.ts","../src/agent.ts","../src/skills/types.ts","../src/skills/echo.ts","../src/config.ts"],"sourcesContent":["import { readFile, writeFile } from \"fs/promises\";\nimport { existsSync } from \"fs\";\n\n/**\n * Active task being processed by the agent\n */\nexport interface ActiveTask {\n taskId: string;\n skillId: string;\n skillName: string;\n status: number;\n paymentAmountMist: string;\n workerBondAmount: string;\n inputPayloadRef: string;\n expectedOutputHash?: string;\n acceptedAt: number;\n expiresAt: number;\n}\n\n/**\n * Registered skill that this agent can handle\n */\nexport interface RegisteredSkill {\n skillId: string;\n name: string;\n version: string;\n verificationType: number;\n basePriceMist: string;\n workerBondMist: string;\n}\n\n/**\n * Pending task created by the agent (requester mode)\n */\nexport interface PendingTask {\n taskId: string;\n skillId: string;\n skillName: string;\n status: number;\n paymentAmountMist: string;\n workerBondAmount: string;\n inputPayloadRef: string;\n expectedOutputHash?: string;\n createdAt: number;\n expiresAt: number;\n workerId?: string;\n outputPayloadRef?: string;\n submittedAt?: number;\n}\n\n/**\n * Agent state that is persisted to disk\n */\nexport interface AgentState {\n // Active tasks being processed (worker mode)\n activeTasks: ActiveTask[];\n\n // Pending tasks awaiting completion (requester mode)\n pendingTasks: PendingTask[];\n\n // Skills this agent is registered to handle\n skills: RegisteredSkill[];\n\n // Statistics (worker)\n stats: {\n tasksAccepted: number;\n tasksCompleted: number;\n tasksFailed: number;\n totalEarnedMist: string;\n lastHeartbeat: number;\n startedAt: number;\n };\n\n // Statistics (requester)\n requesterStats: {\n tasksCreated: number;\n tasksSettled: number;\n tasksExpired: number;\n totalSpentMist: string;\n };\n\n // Agent identity\n agentId: string;\n}\n\n/**\n * Create initial empty state\n */\nexport function createInitialState(agentId: string): AgentState {\n return {\n activeTasks: [],\n pendingTasks: [],\n skills: [],\n stats: {\n tasksAccepted: 0,\n tasksCompleted: 0,\n tasksFailed: 0,\n totalEarnedMist: \"0\",\n lastHeartbeat: 0,\n startedAt: Date.now(),\n },\n requesterStats: {\n tasksCreated: 0,\n tasksSettled: 0,\n tasksExpired: 0,\n totalSpentMist: \"0\",\n },\n agentId,\n };\n}\n\n/**\n * Load state from file\n */\nexport async function loadState(\n filePath: string,\n agentId: string\n): Promise<AgentState> {\n if (!existsSync(filePath)) {\n console.log(`šŸ“ No state file found, creating new state`);\n return createInitialState(agentId);\n }\n\n try {\n const data = await readFile(filePath, \"utf-8\");\n const state = JSON.parse(data) as AgentState;\n\n // Validate agent ID matches\n if (state.agentId !== agentId) {\n console.warn(`⚠ State file agent ID mismatch, creating new state`);\n return createInitialState(agentId);\n }\n\n console.log(`šŸ“ Loaded state: ${state.activeTasks.length} active tasks`);\n return state;\n } catch (error) {\n console.warn(`⚠ Failed to load state file: ${error}`);\n return createInitialState(agentId);\n }\n}\n\n/**\n * Save state to file\n */\nexport async function saveState(\n filePath: string,\n state: AgentState\n): Promise<void> {\n try {\n await writeFile(filePath, JSON.stringify(state, null, 2));\n } catch (error) {\n console.error(`āŒ Failed to save state: ${error}`);\n }\n}\n\n/**\n * Add active task to state\n */\nexport function addActiveTask(state: AgentState, task: ActiveTask): void {\n // Check if task already exists\n const existing = state.activeTasks.find((t) => t.taskId === task.taskId);\n if (!existing) {\n state.activeTasks.push(task);\n state.stats.tasksAccepted++;\n }\n}\n\n/**\n * Remove active task from state\n */\nexport function removeActiveTask(state: AgentState, taskId: string): void {\n state.activeTasks = state.activeTasks.filter((t) => t.taskId !== taskId);\n}\n\n/**\n * Update task in state\n */\nexport function updateActiveTask(\n state: AgentState,\n taskId: string,\n updates: Partial<ActiveTask>\n): void {\n const task = state.activeTasks.find((t) => t.taskId === taskId);\n if (task) {\n Object.assign(task, updates);\n }\n}\n\n/**\n * Mark task as completed\n */\nexport function markTaskCompleted(\n state: AgentState,\n taskId: string,\n earnedMist: string\n): void {\n removeActiveTask(state, taskId);\n state.stats.tasksCompleted++;\n state.stats.totalEarnedMist = (\n BigInt(state.stats.totalEarnedMist) + BigInt(earnedMist)\n ).toString();\n}\n\n/**\n * Mark task as failed\n */\nexport function markTaskFailed(state: AgentState, taskId: string): void {\n removeActiveTask(state, taskId);\n state.stats.tasksFailed++;\n}\n\n// === Requester Mode State Functions ===\n\n/**\n * Add pending task to state (requester mode)\n */\nexport function addPendingTask(state: AgentState, task: PendingTask): void {\n const existing = state.pendingTasks.find((t) => t.taskId === task.taskId);\n if (!existing) {\n state.pendingTasks.push(task);\n state.requesterStats.tasksCreated++;\n }\n}\n\n/**\n * Remove pending task from state\n */\nexport function removePendingTask(state: AgentState, taskId: string): void {\n state.pendingTasks = state.pendingTasks.filter((t) => t.taskId !== taskId);\n}\n\n/**\n * Update pending task in state\n */\nexport function updatePendingTask(\n state: AgentState,\n taskId: string,\n updates: Partial<PendingTask>\n): void {\n const task = state.pendingTasks.find((t) => t.taskId === taskId);\n if (task) {\n Object.assign(task, updates);\n }\n}\n\n/**\n * Mark pending task as settled\n */\nexport function markPendingSettled(\n state: AgentState,\n taskId: string,\n spentMist: string\n): void {\n removePendingTask(state, taskId);\n state.requesterStats.tasksSettled++;\n state.requesterStats.totalSpentMist = (\n BigInt(state.requesterStats.totalSpentMist) + BigInt(spentMist)\n ).toString();\n}\n\n/**\n * Mark pending task as expired\n */\nexport function markPendingExpired(state: AgentState, taskId: string): void {\n removePendingTask(state, taskId);\n state.requesterStats.tasksExpired++;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { ClankAgent } from \"./agent.js\";\nimport { loadConfig, validateConfig } from \"./config.js\";\n\nconst program = new Command();\n\n// Banner\nconst banner = chalk.cyan(`\n ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā•— ā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—\n ā•šā•ā•ā–ˆā–ˆā•”ā•ā•ā•ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā–ˆā–ˆā•‘ ā–ˆā–ˆā•”ā•ā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā•šā•ā•ā–ˆā–ˆā•”ā•ā•ā•\n ā–ˆā–ˆā•‘ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā• ā–ˆā–ˆā•”ā–ˆā–ˆā•— ā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•‘ \n ā–ˆā–ˆā•‘ ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•‘ā•šā•ā•ā•ā•ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā–ˆā–ˆā•— ā–ˆā–ˆā•‘ā•šā–ˆā–ˆā•—ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā• ā–ˆā–ˆā•‘ \n ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•—ā–ˆā–ˆā•‘ ā•šā–ˆā–ˆā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•‘ \n ā•šā•ā• ā•šā•ā• ā•šā•ā•ā•šā•ā•ā•ā•ā•ā•ā•ā•šā•ā• ā•šā•ā•ā•šā•ā• ā•šā•ā•ā•ā•ā•šā•ā•ā•ā•ā•ā•ā• ā•šā•ā• \n ${chalk.gray(\"Reference Agent v0.4.0\")}\n`);\n\nprogram\n .name(\"clank-agent\")\n .description(\"Clank Reference Agent - Worker and Requester modes\")\n .version(\"0.4.0\")\n .addHelpText(\"beforeAll\", banner);\n\n// Start command\nprogram\n .command(\"start\")\n .description(\"Start the agent\")\n .action(async () => {\n console.log(banner);\n\n try {\n // Load and validate config\n const config = loadConfig();\n validateConfig(config);\n\n // Create and start agent\n const agent = new ClankAgent(config);\n\n // Handle shutdown signals\n const shutdown = async () => {\n await agent.stop();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Start the agent\n await agent.start();\n\n // Keep running\n await new Promise(() => {});\n } catch (error) {\n console.error(chalk.red(`\\nāŒ Failed to start agent: ${error}`));\n process.exit(1);\n }\n });\n\n// Status command\nprogram\n .command(\"status\")\n .description(\"Show agent status (requires running agent)\")\n .action(async () => {\n console.log(banner);\n\n try {\n const config = loadConfig();\n\n console.log(chalk.bold(\"\\nAgent Configuration:\\n\"));\n console.log(` Agent ID: ${config.agentId}`);\n console.log(` Mode: ${chalk.cyan(config.mode.toUpperCase())}`);\n console.log(` API URL: ${config.apiUrl}`);\n console.log(` Network: ${config.network}`);\n console.log(` State File: ${config.stateFilePath}`);\n console.log(` Heartbeat: ${config.heartbeatIntervalMs / 1000}s`);\n\n if (config.mode === \"worker\" || config.mode === \"hybrid\") {\n console.log(chalk.bold(\"\\nWorker Settings:\\n\"));\n console.log(` Max Tasks: ${config.maxConcurrentTasks}`);\n console.log(` Min Payment: $${Number(config.minPaymentThreshold) / 1_000_000}`);\n console.log(` Skills: ${config.skillIds.length} configured`);\n }\n\n if (config.mode === \"requester\" || config.mode === \"hybrid\") {\n console.log(chalk.bold(\"\\nRequester Settings:\\n\"));\n console.log(` Max Pending: ${config.maxPendingTasks}`);\n console.log(` Auto Confirm: ${config.autoConfirmDeterministic}`);\n console.log(` Task Timeout: ${config.taskTimeoutMs / 1000 / 60} minutes`);\n }\n\n // Load state file if exists\n const { loadState } = await import(\"./state.js\");\n const state = await loadState(config.stateFilePath, config.agentId);\n\n if (config.mode === \"worker\" || config.mode === \"hybrid\") {\n console.log(chalk.bold(\"\\nWorker Stats:\\n\"));\n console.log(` Active Tasks: ${state.activeTasks.length}`);\n console.log(` Registered Skills: ${state.skills.length}`);\n console.log(` Tasks Accepted: ${state.stats.tasksAccepted}`);\n console.log(` Tasks Completed: ${state.stats.tasksCompleted}`);\n console.log(` Tasks Failed: ${state.stats.tasksFailed}`);\n console.log(` Total Earned: ${Number(BigInt(state.stats.totalEarnedMist)) / 1_000_000_000} SUI`);\n }\n\n if (config.mode === \"requester\" || config.mode === \"hybrid\") {\n console.log(chalk.bold(\"\\nRequester Stats:\\n\"));\n console.log(` Pending Tasks: ${state.pendingTasks.length}`);\n console.log(` Tasks Created: ${state.requesterStats.tasksCreated}`);\n console.log(` Tasks Settled: ${state.requesterStats.tasksSettled}`);\n console.log(` Tasks Expired: ${state.requesterStats.tasksExpired}`);\n console.log(` Total Spent: ${Number(BigInt(state.requesterStats.totalSpentMist)) / 1_000_000_000} SUI`);\n }\n\n if (state.stats.lastHeartbeat > 0) {\n const lastHeartbeat = new Date(state.stats.lastHeartbeat).toISOString();\n const ago = Math.floor((Date.now() - state.stats.lastHeartbeat) / 1000);\n console.log(chalk.bold(\"\\nLast Activity:\\n\"));\n console.log(` Last Heartbeat: ${lastHeartbeat} (${ago}s ago)`);\n }\n\n if (state.activeTasks.length > 0) {\n console.log(chalk.bold(\"\\nActive Tasks (Worker):\\n\"));\n for (const task of state.activeTasks) {\n const remaining = Math.floor((task.expiresAt - Date.now()) / 1000 / 60);\n console.log(` - ${task.taskId.slice(0, 20)}...`);\n console.log(` Skill: ${task.skillName}, Payment: ${Number(BigInt(task.paymentAmountMist)) / 1_000_000_000} SUI`);\n console.log(` Expires in: ${remaining} minutes`);\n }\n }\n\n if (state.pendingTasks.length > 0) {\n console.log(chalk.bold(\"\\nPending Tasks (Requester):\\n\"));\n for (const task of state.pendingTasks) {\n const remaining = Math.floor((task.expiresAt - Date.now()) / 1000 / 60);\n console.log(` - ${task.taskId.slice(0, 20)}...`);\n console.log(` Skill: ${task.skillName}, Status: ${task.status}`);\n console.log(` Expires in: ${remaining} minutes`);\n }\n }\n\n console.log();\n } catch (error) {\n console.error(chalk.red(`\\nāŒ Failed to get status: ${error}`));\n process.exit(1);\n }\n });\n\n// Config command\nprogram\n .command(\"config\")\n .description(\"Show required environment variables\")\n .action(() => {\n console.log(banner);\n\n console.log(chalk.bold(\"\\nRequired Environment Variables:\\n\"));\n console.log(` TASKNET_API_URL API server URL`);\n console.log(` TASKNET_API_KEY API authentication key`);\n console.log(` TASKNET_AGENT_ID Your agent's on-chain ID`);\n\n console.log(chalk.bold(\"\\nAgent Mode:\\n\"));\n console.log(` AGENT_MODE Agent mode: worker, requester, or hybrid [default: worker]`);\n\n console.log(chalk.bold(\"\\nNetwork Configuration:\\n\"));\n console.log(` TASKNET_NETWORK Network (testnet, mainnet) [default: testnet]`);\n console.log(` TASKNET_PACKAGE_ID Clank contract package ID`);\n console.log(` SUI_RPC_URL Sui RPC endpoint`);\n console.log(` WALRUS_AGGREGATOR_URL Walrus aggregator URL`);\n console.log(` WALRUS_PUBLISHER_URL Walrus publisher URL`);\n\n console.log(chalk.bold(\"\\nWorker Mode Settings:\\n\"));\n console.log(` SKILL_IDS Comma-separated skill IDs to handle`);\n console.log(` MAX_CONCURRENT_TASKS Maximum parallel tasks [default: 5]`);\n console.log(` MIN_PAYMENT_THRESHOLD Minimum payment in MIST [default: 1000000000]`);\n console.log(` MIN_EXECUTION_TIME_MS Minimum time before expiry [default: 1800000]`);\n\n console.log(chalk.bold(\"\\nRequester Mode Settings:\\n\"));\n console.log(` MAX_PENDING_TASKS Maximum pending tasks [default: 20]`);\n console.log(` AUTO_CONFIRM_DETERMINISTIC Auto-confirm deterministic tasks [default: true]`);\n console.log(` TASK_TIMEOUT_MS Default task timeout [default: 3600000]`);\n\n console.log(chalk.bold(\"\\nGeneral Settings:\\n\"));\n console.log(` HEARTBEAT_INTERVAL_MS Heartbeat interval [default: 60000]`);\n console.log(` STATE_FILE_PATH State persistence file [default: .agent-state.json]`);\n\n console.log(chalk.bold(\"\\nExample .env file (Worker Mode):\\n\"));\n console.log(chalk.gray(`TASKNET_API_URL=http://localhost:3000\nTASKNET_API_KEY=ck_your_api_key\nTASKNET_AGENT_ID=0x1234...\nAGENT_MODE=worker\nSKILL_IDS=echo-skill\n`));\n\n console.log(chalk.bold(\"Example .env file (Requester Mode):\\n\"));\n console.log(chalk.gray(`TASKNET_API_URL=http://localhost:3000\nTASKNET_API_KEY=ck_your_api_key\nTASKNET_AGENT_ID=0x1234...\nAGENT_MODE=requester\nAUTO_CONFIRM_DETERMINISTIC=true\n`));\n\n console.log(chalk.bold(\"Example .env file (Hybrid Mode):\\n\"));\n console.log(chalk.gray(`TASKNET_API_URL=http://localhost:3000\nTASKNET_API_KEY=ck_your_api_key\nTASKNET_AGENT_ID=0x1234...\nAGENT_MODE=hybrid\nSKILL_IDS=echo-skill\nMAX_PENDING_TASKS=10\n`));\n\n console.log();\n });\n\nprogram.parse();\n","import { ClankClient } from \"@clankxyz/sdk\";\nimport { STATUS, VERIFICATION } from \"@clankxyz/shared\";\nimport type { AgentConfig } from \"./config.js\";\nimport type { AgentState, ActiveTask, PendingTask } from \"./state.js\";\nimport {\n loadState,\n saveState,\n addActiveTask,\n removeActiveTask,\n markTaskCompleted,\n markTaskFailed,\n addPendingTask,\n updatePendingTask,\n markPendingSettled,\n markPendingExpired,\n} from \"./state.js\";\nimport { SkillRegistry, echoSkillHandler } from \"./skills/index.js\";\n\n/**\n * Task creation request for requester mode\n */\nexport interface CreateTaskRequest {\n skillId: string;\n input: object;\n paymentAmountMist: bigint;\n expiresInMs?: number;\n expectedOutputHash?: string;\n}\n\n/**\n * Clank Reference Agent\n *\n * A reference implementation of an autonomous agent that:\n * - Worker Mode: Polls for tasks, accepts, executes, and submits\n * - Requester Mode: Creates tasks, monitors progress, confirms/rejects\n * - Hybrid Mode: Both worker and requester capabilities\n * - Persists state for crash recovery\n */\nexport class ClankAgent {\n private client: ClankClient;\n private config: AgentConfig;\n private state!: AgentState;\n private skillRegistry: SkillRegistry;\n private running = false;\n private heartbeatTimer?: ReturnType<typeof setInterval>;\n\n // Queue for tasks to create in requester mode\n private taskCreationQueue: CreateTaskRequest[] = [];\n\n constructor(config: AgentConfig) {\n this.config = config;\n\n // Initialize SDK client\n this.client = new ClankClient({\n apiUrl: config.apiUrl,\n apiKey: config.apiKey,\n network: config.network,\n rpcUrl: config.rpcUrl,\n packageId: config.packageId,\n walrusAggregator: config.walrusAggregator,\n walrusPublisher: config.walrusPublisher,\n agentId: config.agentId,\n });\n\n // Initialize skill registry\n this.skillRegistry = new SkillRegistry();\n\n // Register default handlers\n this.skillRegistry.register(echoSkillHandler);\n }\n\n /**\n * Register a custom skill handler\n */\n registerSkillHandler(handler: typeof echoSkillHandler): void {\n this.skillRegistry.register(handler);\n }\n\n /**\n * Start the agent\n */\n async start(): Promise<void> {\n console.log(`\\nšŸ¤– Clank Agent starting...`);\n console.log(` Agent ID: ${this.config.agentId}`);\n console.log(` Mode: ${this.config.mode.toUpperCase()}`);\n console.log(` API URL: ${this.config.apiUrl}`);\n console.log(` Network: ${this.config.network}`);\n if (this.config.mode === \"worker\" || this.config.mode === \"hybrid\") {\n console.log(` Skills: ${this.config.skillIds.length} configured`);\n console.log(` Max concurrent: ${this.config.maxConcurrentTasks}`);\n }\n if (this.config.mode === \"requester\" || this.config.mode === \"hybrid\") {\n console.log(` Max pending: ${this.config.maxPendingTasks}`);\n console.log(` Auto-confirm deterministic: ${this.config.autoConfirmDeterministic}`);\n }\n console.log(` Heartbeat: ${this.config.heartbeatIntervalMs}ms\\n`);\n\n // Load persisted state\n this.state = await loadState(\n this.config.stateFilePath,\n this.config.agentId\n );\n\n // Refresh skills list from API (for worker/hybrid)\n if (this.config.mode === \"worker\" || this.config.mode === \"hybrid\") {\n await this.refreshSkills();\n await this.recoverActiveTasks();\n }\n\n // Recover pending tasks (for requester/hybrid)\n if (this.config.mode === \"requester\" || this.config.mode === \"hybrid\") {\n await this.recoverPendingTasks();\n }\n\n // Mark as running\n this.running = true;\n\n // Start heartbeat loop\n await this.heartbeat();\n\n this.heartbeatTimer = setInterval(\n () => this.heartbeat().catch(console.error),\n this.config.heartbeatIntervalMs\n );\n\n console.log(`\\nāœ… Agent is now running`);\n console.log(` Press Ctrl+C to stop\\n`);\n }\n\n /**\n * Stop the agent gracefully\n */\n async stop(): Promise<void> {\n console.log(`\\nšŸ›‘ Stopping agent...`);\n this.running = false;\n\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n }\n\n // Save final state\n await saveState(this.config.stateFilePath, this.state);\n\n console.log(` State saved`);\n console.log(` Active tasks: ${this.state.activeTasks.length}`);\n console.log(`āœ… Agent stopped\\n`);\n }\n\n /**\n * Main heartbeat loop\n */\n private async heartbeat(): Promise<void> {\n const now = Date.now();\n this.state.stats.lastHeartbeat = now;\n\n console.log(`\\nšŸ’“ Heartbeat at ${new Date().toISOString()}`);\n\n try {\n // Worker mode: poll and process tasks\n if (this.config.mode === \"worker\" || this.config.mode === \"hybrid\") {\n console.log(` [WORKER] Active tasks: ${this.state.activeTasks.length}/${this.config.maxConcurrentTasks}`);\n await this.pollForTasks();\n await this.processActiveTasks();\n }\n\n // Requester mode: create and monitor tasks\n if (this.config.mode === \"requester\" || this.config.mode === \"hybrid\") {\n console.log(` [REQUESTER] Pending tasks: ${this.state.pendingTasks.length}/${this.config.maxPendingTasks}`);\n await this.processTaskCreationQueue();\n await this.monitorPendingTasks();\n }\n\n // Save state\n await saveState(this.config.stateFilePath, this.state);\n } catch (error) {\n console.error(`āŒ Heartbeat error: ${error}`);\n }\n }\n\n /**\n * Poll for available tasks\n */\n private async pollForTasks(): Promise<void> {\n // Check if we can accept more tasks\n if (this.state.activeTasks.length >= this.config.maxConcurrentTasks) {\n console.log(` šŸ“‹ At max capacity, skipping poll`);\n return;\n }\n\n // Get skills we can handle\n const skillIds = this.state.skills.map((s) => s.skillId);\n if (skillIds.length === 0) {\n console.log(` šŸ“‹ No skills registered, skipping poll`);\n return;\n }\n\n console.log(` šŸ“‹ Polling for tasks...`);\n\n try {\n // Poll for POSTED tasks for our skills\n const result = await this.client.api.listTasks({\n status: STATUS.POSTED,\n skillId: skillIds[0], // API only supports one skill filter currently\n limit: 10,\n });\n\n const tasks = result.data;\n console.log(` šŸ“‹ Found ${tasks.length} available tasks`);\n\n for (const task of tasks) {\n if (!this.running) break;\n if (this.state.activeTasks.length >= this.config.maxConcurrentTasks) break;\n\n // Check if we can handle this skill\n const skill = this.state.skills.find((s) => s.skillId === task.skill.id);\n if (!skill) continue;\n\n // Check if handler exists\n if (!this.skillRegistry.canHandle(skill.name, skill.version)) {\n console.log(` ā­ No handler for ${skill.name}@${skill.version}`);\n continue;\n }\n\n // Check minimum payment\n if (BigInt(task.payment_amount_mist) < this.config.minPaymentThreshold) {\n console.log(` ā­ Payment too low: ${task.payment_amount_mist}`);\n continue;\n }\n\n // Check deadline\n const expiresAt = new Date(task.expires_at).getTime();\n if (expiresAt - Date.now() < this.config.minExecutionTimeMs) {\n console.log(` ā­ Not enough time: ${task.id}`);\n continue;\n }\n\n // Try to accept this task\n await this.acceptTask(task, skill);\n }\n } catch (error) {\n console.error(` āŒ Poll error: ${error}`);\n }\n }\n\n /**\n * Accept a task\n */\n private async acceptTask(\n task: { id: string; payment_amount_mist: string; worker_bond_amount: string; expires_at: string },\n skill: { skillId: string; name: string }\n ): Promise<void> {\n console.log(`\\n šŸŽÆ Accepting task ${task.id.slice(0, 16)}...`);\n\n try {\n // Get full task details\n const fullTask = await this.client.api.getTask(task.id);\n\n // Add to active tasks (optimistic)\n const activeTask: ActiveTask = {\n taskId: task.id,\n skillId: skill.skillId,\n skillName: skill.name,\n status: STATUS.IN_PROGRESS,\n paymentAmountMist: task.payment_amount_mist,\n workerBondAmount: task.worker_bond_amount,\n inputPayloadRef: fullTask.input_payload_ref,\n expectedOutputHash: fullTask.expected_output_hash,\n acceptedAt: Date.now(),\n expiresAt: new Date(task.expires_at).getTime(),\n };\n\n addActiveTask(this.state, activeTask);\n console.log(` āœ… Task accepted: ${task.id.slice(0, 16)}`);\n\n // Note: In a full implementation, we would:\n // 1. Call reserve() on-chain\n // 2. Call accept() with bond\n // For now, we simulate with API-only flow\n\n } catch (error) {\n console.error(` āŒ Failed to accept task: ${error}`);\n }\n }\n\n /**\n * Process active tasks\n */\n private async processActiveTasks(): Promise<void> {\n const now = Date.now();\n\n for (const task of [...this.state.activeTasks]) {\n if (!this.running) break;\n\n try {\n // Check if expired\n if (task.expiresAt <= now) {\n console.log(` ā° Task expired: ${task.taskId.slice(0, 16)}`);\n markTaskFailed(this.state, task.taskId);\n continue;\n }\n\n // Check if still in progress\n if (task.status !== STATUS.IN_PROGRESS) {\n continue;\n }\n\n // Execute the skill\n await this.executeTask(task);\n } catch (error) {\n console.error(` āŒ Task processing error: ${error}`);\n }\n }\n }\n\n /**\n * Execute a task\n */\n private async executeTask(task: ActiveTask): Promise<void> {\n console.log(`\\n āš™ļø Executing task ${task.taskId.slice(0, 16)}...`);\n console.log(` Skill: ${task.skillName}`);\n\n try {\n // Find handler\n const handler = this.skillRegistry.findHandler(task.skillName, \"1.0.0\");\n if (!handler) {\n console.error(` āŒ No handler for ${task.skillName}`);\n markTaskFailed(this.state, task.taskId);\n return;\n }\n\n // Fetch input from Walrus\n let input: object;\n try {\n input = await this.client.walrus.getJson(task.inputPayloadRef);\n console.log(` Input fetched from Walrus`);\n } catch (error) {\n console.error(` āŒ Failed to fetch input: ${error}`);\n markTaskFailed(this.state, task.taskId);\n return;\n }\n\n // Validate input\n if (handler.validateInput) {\n const validation = handler.validateInput(input);\n if (!validation.valid) {\n console.error(` āŒ Input validation failed: ${validation.error}`);\n markTaskFailed(this.state, task.taskId);\n return;\n }\n }\n\n // Execute handler\n const result = await handler.execute(input, {\n taskId: task.taskId,\n skillId: task.skillId,\n skillName: task.skillName,\n skillVersion: \"1.0.0\",\n paymentAmountMist: BigInt(task.paymentAmountMist),\n expiresAt: task.expiresAt,\n });\n\n if (!result.success || !result.output) {\n console.error(` āŒ Handler failed: ${result.error}`);\n markTaskFailed(this.state, task.taskId);\n return;\n }\n\n console.log(` Handler executed successfully`);\n\n // Store output in Walrus\n const storedOutput = await this.client.walrus.storeJson(result.output);\n console.log(` Output stored: ${storedOutput.blobId.slice(0, 20)}...`);\n\n // Submit output\n // Note: In full implementation, we would call submit() on-chain\n console.log(` āœ… Task completed: ${task.taskId.slice(0, 16)}`);\n\n // Mark as completed\n markTaskCompleted(this.state, task.taskId, task.paymentAmountMist);\n\n } catch (error) {\n console.error(` āŒ Execution error: ${error}`);\n markTaskFailed(this.state, task.taskId);\n }\n }\n\n /**\n * Refresh skills list from API\n */\n private async refreshSkills(): Promise<void> {\n console.log(` šŸ“š Refreshing skills...`);\n\n try {\n const agent = await this.client.api.getAgent(this.config.agentId);\n\n this.state.skills = agent.skills.map((s) => ({\n skillId: s.id,\n name: s.name,\n version: s.version,\n verificationType: s.verification_type,\n basePriceMist: s.base_price_mist,\n workerBondMist: \"0\", // Not in API response\n }));\n\n console.log(` šŸ“š Found ${this.state.skills.length} skills`);\n\n // Also use configured skill IDs\n for (const skillId of this.config.skillIds) {\n if (!this.state.skills.find((s) => s.skillId === skillId)) {\n // Try to fetch skill details\n try {\n const skill = await this.client.api.getSkill(skillId);\n this.state.skills.push({\n skillId: skill.id,\n name: skill.name,\n version: skill.version,\n verificationType: skill.verification_type,\n basePriceMist: skill.base_price_mist,\n workerBondMist: skill.worker_bond_mist,\n });\n } catch {\n console.warn(` ⚠ Could not fetch skill ${skillId}`);\n }\n }\n }\n } catch (error) {\n console.error(` āŒ Failed to refresh skills: ${error}`);\n }\n }\n\n /**\n * Recover active tasks after restart\n */\n private async recoverActiveTasks(): Promise<void> {\n if (this.state.activeTasks.length === 0) {\n return;\n }\n\n console.log(` šŸ”„ Recovering ${this.state.activeTasks.length} active tasks...`);\n\n const now = Date.now();\n const tasksToRemove: string[] = [];\n\n for (const task of this.state.activeTasks) {\n // Remove expired tasks\n if (task.expiresAt <= now) {\n console.log(` ā° Removing expired task: ${task.taskId.slice(0, 16)}`);\n tasksToRemove.push(task.taskId);\n continue;\n }\n\n // Verify task is still valid\n try {\n const fullTask = await this.client.api.getTask(task.taskId);\n\n // Check if task is still in progress\n if (\n fullTask.status !== STATUS.IN_PROGRESS &&\n fullTask.status !== STATUS.ACCEPTED\n ) {\n console.log(` āŒ Task no longer active: ${task.taskId.slice(0, 16)}`);\n tasksToRemove.push(task.taskId);\n }\n } catch {\n // Task may have been settled or cancelled\n console.log(` āŒ Task not found: ${task.taskId.slice(0, 16)}`);\n tasksToRemove.push(task.taskId);\n }\n }\n\n // Remove invalid tasks\n for (const taskId of tasksToRemove) {\n removeActiveTask(this.state, taskId);\n }\n\n console.log(` šŸ”„ Recovery complete: ${this.state.activeTasks.length} active tasks`);\n }\n\n /**\n * Get current stats\n */\n getStats() {\n return {\n worker: {\n ...this.state.stats,\n activeTasks: this.state.activeTasks.length,\n registeredSkills: this.state.skills.length,\n },\n requester: {\n ...this.state.requesterStats,\n pendingTasks: this.state.pendingTasks.length,\n queuedTasks: this.taskCreationQueue.length,\n },\n };\n }\n\n /**\n * Get the SDK client\n */\n getClient(): ClankClient {\n return this.client;\n }\n\n // === Requester Mode Methods ===\n\n /**\n * Queue a task for creation (requester mode)\n */\n queueTask(request: CreateTaskRequest): void {\n if (this.config.mode === \"worker\") {\n throw new Error(\"Cannot create tasks in worker mode\");\n }\n\n if (this.state.pendingTasks.length >= this.config.maxPendingTasks) {\n throw new Error(\"Maximum pending tasks reached\");\n }\n\n this.taskCreationQueue.push(request);\n console.log(` šŸ“¤ Task queued for creation (skill: ${request.skillId})`);\n }\n\n /**\n * Process task creation queue\n */\n private async processTaskCreationQueue(): Promise<void> {\n while (this.taskCreationQueue.length > 0 && this.running) {\n if (this.state.pendingTasks.length >= this.config.maxPendingTasks) {\n console.log(` šŸ“¤ Max pending tasks reached, pausing creation`);\n break;\n }\n\n const request = this.taskCreationQueue.shift()!;\n await this.createTask(request);\n }\n }\n\n /**\n * Create a task on-chain (requester mode)\n */\n private async createTask(request: CreateTaskRequest): Promise<void> {\n console.log(`\\n šŸ“ Creating task for skill ${request.skillId.slice(0, 16)}...`);\n\n try {\n // Get skill details\n const skill = await this.client.api.getSkill(request.skillId);\n\n // Store input in Walrus\n const storedInput = await this.client.walrus.storeJson(request.input);\n console.log(` Input stored: ${storedInput.blobId.slice(0, 20)}...`);\n\n // Calculate expiry\n const expiresInMs = request.expiresInMs ?? this.config.taskTimeoutMs;\n const expiresAt = Date.now() + expiresInMs;\n\n // Create task via API\n // Note: In full implementation, this would be an on-chain transaction\n const now = Date.now();\n const taskId = `task_${now}_${Math.random().toString(36).slice(2, 10)}`;\n\n // Add to pending tasks\n const pendingTask: PendingTask = {\n taskId,\n skillId: request.skillId,\n skillName: skill.name,\n status: STATUS.POSTED,\n paymentAmountMist: request.paymentAmountMist.toString(),\n workerBondAmount: skill.worker_bond_mist,\n inputPayloadRef: storedInput.blobId,\n expectedOutputHash: request.expectedOutputHash,\n createdAt: now,\n expiresAt,\n };\n\n addPendingTask(this.state, pendingTask);\n console.log(` āœ… Task created: ${taskId.slice(0, 16)}`);\n\n } catch (error) {\n console.error(` āŒ Failed to create task: ${error}`);\n // Re-queue for retry? For now, just log\n }\n }\n\n /**\n * Monitor pending tasks and process submissions\n */\n private async monitorPendingTasks(): Promise<void> {\n const now = Date.now();\n\n for (const task of [...this.state.pendingTasks]) {\n if (!this.running) break;\n\n try {\n // Check if expired\n if (task.expiresAt <= now) {\n console.log(` ā° Task expired: ${task.taskId.slice(0, 16)}`);\n markPendingExpired(this.state, task.taskId);\n continue;\n }\n\n // Fetch current status from API\n // Note: In production, we'd use the on-chain task ID\n // For now, simulate status checks\n\n // Process based on status\n if (task.status === STATUS.SUBMITTED && task.outputPayloadRef) {\n await this.processSubmittedTask(task);\n }\n\n } catch (error) {\n console.error(` āŒ Error monitoring task ${task.taskId.slice(0, 16)}: ${error}`);\n }\n }\n }\n\n /**\n * Process a submitted task (verify output and confirm/reject)\n */\n private async processSubmittedTask(task: PendingTask): Promise<void> {\n console.log(`\\n šŸ” Processing submitted task ${task.taskId.slice(0, 16)}...`);\n\n if (!task.outputPayloadRef) {\n console.log(` ⚠ No output payload reference`);\n return;\n }\n\n try {\n // Fetch output from Walrus\n const output = await this.client.walrus.getJson(task.outputPayloadRef);\n console.log(` Output fetched from Walrus`);\n\n // Get skill to check verification type\n const skill = await this.client.api.getSkill(task.skillId);\n \n // Determine if we should auto-confirm\n let shouldConfirm = false;\n\n if (skill.verification_type === VERIFICATION.DETERMINISTIC) {\n // Deterministic: verify hash matches\n if (this.config.autoConfirmDeterministic) {\n if (task.expectedOutputHash) {\n // In production, compute hash and compare\n // For now, assume it matches\n console.log(` Deterministic verification passed`);\n shouldConfirm = true;\n } else {\n console.log(` No expected hash, auto-confirming deterministic task`);\n shouldConfirm = true;\n }\n }\n } else if (skill.verification_type === VERIFICATION.TIME_BOUND) {\n // Time-bound: auto-settle after deadline\n console.log(` Time-bound task, waiting for deadline`);\n } else {\n // RequesterConfirm: need manual confirmation\n console.log(` Awaiting manual confirmation for task`);\n // In a real agent, this would emit an event or call a callback\n }\n\n if (shouldConfirm) {\n await this.confirmTask(task);\n }\n\n } catch (error) {\n console.error(` āŒ Failed to process submitted task: ${error}`);\n }\n }\n\n /**\n * Confirm a submitted task (release payment to worker)\n */\n async confirmTask(task: PendingTask): Promise<void> {\n console.log(` āœ… Confirming task ${task.taskId.slice(0, 16)}...`);\n\n try {\n // Note: In full implementation, call confirm() on-chain\n // For now, simulate confirmation\n\n markPendingSettled(this.state, task.taskId, task.paymentAmountMist);\n console.log(` āœ… Task confirmed and settled`);\n\n } catch (error) {\n console.error(` āŒ Failed to confirm task: ${error}`);\n }\n }\n\n /**\n * Reject a submitted task (return payment, slash worker bond)\n */\n async rejectTask(task: PendingTask, reason: string): Promise<void> {\n console.log(` āŒ Rejecting task ${task.taskId.slice(0, 16)}...`);\n console.log(` Reason: ${reason}`);\n\n try {\n // Note: In full implementation, call reject() on-chain\n // For now, simulate rejection\n\n markPendingExpired(this.state, task.taskId);\n console.log(` āŒ Task rejected`);\n\n } catch (error) {\n console.error(` āŒ Failed to reject task: ${error}`);\n }\n }\n\n /**\n * Get pending task by ID\n */\n getPendingTask(taskId: string): PendingTask | undefined {\n return this.state.pendingTasks.find((t) => t.taskId === taskId);\n }\n\n /**\n * Get all pending tasks\n */\n getPendingTasks(): PendingTask[] {\n return [...this.state.pendingTasks];\n }\n\n /**\n * Recover pending tasks after restart\n */\n private async recoverPendingTasks(): Promise<void> {\n if (this.state.pendingTasks.length === 0) {\n return;\n }\n\n console.log(` šŸ”„ Recovering ${this.state.pendingTasks.length} pending tasks...`);\n\n const now = Date.now();\n const tasksToRemove: string[] = [];\n\n for (const task of this.state.pendingTasks) {\n // Remove expired tasks\n if (task.expiresAt <= now) {\n console.log(` ā° Removing expired pending task: ${task.taskId.slice(0, 16)}`);\n tasksToRemove.push(task.taskId);\n this.state.requesterStats.tasksExpired++;\n continue;\n }\n\n // In production, verify task still exists on-chain\n }\n\n // Remove invalid tasks\n this.state.pendingTasks = this.state.pendingTasks.filter(\n (t) => !tasksToRemove.includes(t.taskId)\n );\n\n console.log(` šŸ”„ Recovery complete: ${this.state.pendingTasks.length} pending tasks`);\n }\n}\n","/**\n * Result of skill execution\n */\nexport interface SkillResult {\n success: boolean;\n output?: object;\n error?: string;\n}\n\n/**\n * Skill handler interface - implement this for each skill\n */\nexport interface SkillHandler {\n /** Handler name */\n name: string;\n\n /** Handler version */\n version: string;\n\n /**\n * Check if this handler can process the given skill\n */\n canHandle(skillName: string, skillVersion: string): boolean;\n\n /**\n * Execute the skill with the given input\n */\n execute(input: object, context?: SkillContext): Promise<SkillResult>;\n\n /**\n * Validate the input before processing\n */\n validateInput?(input: object): { valid: boolean; error?: string };\n\n /**\n * Estimate execution time in milliseconds\n */\n estimateExecutionTime?(input: object): number;\n}\n\n/**\n * Context provided to skill handlers\n */\nexport interface SkillContext {\n taskId: string;\n skillId: string;\n skillName: string;\n skillVersion: string;\n paymentAmountMist: bigint;\n expiresAt: number;\n}\n\n/**\n * Skill registry for managing available handlers\n */\nexport class SkillRegistry {\n private handlers: SkillHandler[] = [];\n\n /**\n * Register a skill handler\n */\n register(handler: SkillHandler): void {\n // Check for duplicates\n const existing = this.handlers.find(\n (h) => h.name === handler.name && h.version === handler.version\n );\n if (existing) {\n console.warn(`⚠ Handler ${handler.name}@${handler.version} already registered`);\n return;\n }\n\n this.handlers.push(handler);\n console.log(`šŸ“¦ Registered handler: ${handler.name}@${handler.version}`);\n }\n\n /**\n * Find a handler for the given skill\n */\n findHandler(skillName: string, skillVersion: string): SkillHandler | undefined {\n return this.handlers.find((h) => h.canHandle(skillName, skillVersion));\n }\n\n /**\n * Get all registered handlers\n */\n getHandlers(): SkillHandler[] {\n return [...this.handlers];\n }\n\n /**\n * Check if any handler can process the skill\n */\n canHandle(skillName: string, skillVersion: string): boolean {\n return this.findHandler(skillName, skillVersion) !== undefined;\n }\n}\n","import type { SkillHandler, SkillResult } from \"./types.js\";\n\n/**\n * Echo skill handler - simply echoes back the input with metadata\n *\n * This is a reference implementation for testing the task flow.\n */\nexport const echoSkillHandler: SkillHandler = {\n name: \"echo\",\n version: \"1.0.0\",\n\n /**\n * Check if this handler can process the given skill\n */\n canHandle(skillName: string, skillVersion: string): boolean {\n return (\n skillName.toLowerCase().includes(\"echo\") ||\n skillName.toLowerCase().includes(\"test\")\n );\n },\n\n /**\n * Process the input and return the output\n */\n async execute(input: object): Promise<SkillResult> {\n const now = Date.now();\n\n // Simulate some processing time (100-500ms)\n await new Promise((resolve) =>\n setTimeout(resolve, 100 + Math.random() * 400)\n );\n\n // Return the echoed input with metadata\n const output = {\n echo: input,\n metadata: {\n processedAt: now,\n processingTimeMs: Date.now() - now,\n handler: \"echo-skill-v1\",\n version: \"1.0.0\",\n },\n };\n\n return {\n success: true,\n output,\n };\n },\n\n /**\n * Validate the input before processing\n */\n validateInput(input: object): { valid: boolean; error?: string } {\n // Echo skill accepts any input\n if (input === null || input === undefined) {\n return { valid: false, error: \"Input cannot be null or undefined\" };\n }\n return { valid: true };\n },\n};\n\n/**\n * Echo skill JSON schema\n */\nexport const echoInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n description: \"Echo skill input - any JSON object\",\n additionalProperties: true,\n};\n\nexport const echoOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n echo: {\n description: \"The echoed input\",\n },\n metadata: {\n type: \"object\",\n properties: {\n processedAt: { type: \"number\" },\n processingTimeMs: { type: \"number\" },\n handler: { type: \"string\" },\n version: { type: \"string\" },\n },\n required: [\"processedAt\", \"processingTimeMs\", \"handler\", \"version\"],\n },\n },\n required: [\"echo\", \"metadata\"],\n};\n","import \"dotenv/config\";\nimport type { Network } from \"@clankxyz/shared\";\n\n/**\n * Agent mode: worker executes tasks, requester creates and monitors tasks\n */\nexport type AgentMode = \"worker\" | \"requester\" | \"hybrid\";\n\n/**\n * Agent configuration loaded from environment variables\n */\nexport interface AgentConfig {\n // API configuration\n apiUrl: string;\n apiKey: string;\n\n // Agent identity\n agentId: string;\n\n // Agent mode\n mode: AgentMode;\n\n // Network configuration\n network: Network;\n rpcUrl?: string;\n packageId?: string;\n\n // Walrus configuration\n walrusAggregator?: string;\n walrusPublisher?: string;\n\n // Worker behavior\n maxConcurrentTasks: number;\n minPaymentThreshold: bigint;\n minExecutionTimeMs: number;\n heartbeatIntervalMs: number;\n pollIntervalMs: number;\n\n // Requester behavior\n maxPendingTasks: number;\n autoConfirmDeterministic: boolean;\n taskTimeoutMs: number;\n\n // Skills this agent can handle (worker mode)\n skillIds: string[];\n\n // State persistence\n stateFilePath: string;\n\n // Webhook server (optional)\n webhookPort?: number;\n webhookSecret?: string;\n}\n\n/**\n * Load configuration from environment variables\n */\nexport function loadConfig(): AgentConfig {\n const apiUrl = process.env.TASKNET_API_URL;\n const apiKey = process.env.TASKNET_API_KEY;\n const agentId = process.env.TASKNET_AGENT_ID;\n\n if (!apiUrl) {\n throw new Error(\"TASKNET_API_URL is required\");\n }\n if (!apiKey) {\n throw new Error(\"TASKNET_API_KEY is required\");\n }\n if (!agentId) {\n throw new Error(\"TASKNET_AGENT_ID is required\");\n }\n\n return {\n // API configuration\n apiUrl,\n apiKey,\n agentId,\n\n // Agent mode\n mode: (process.env.AGENT_MODE as AgentMode) ?? \"worker\",\n\n // Network configuration\n network: (process.env.TASKNET_NETWORK as Network) ?? \"testnet\",\n rpcUrl: process.env.SUI_RPC_URL,\n packageId: process.env.TASKNET_PACKAGE_ID,\n\n // Walrus configuration\n walrusAggregator: process.env.WALRUS_AGGREGATOR_URL,\n walrusPublisher: process.env.WALRUS_PUBLISHER_URL,\n\n // Worker behavior\n maxConcurrentTasks: parseInt(process.env.MAX_CONCURRENT_TASKS ?? \"5\", 10),\n minPaymentThreshold: BigInt(process.env.MIN_PAYMENT_THRESHOLD ?? \"10000000\"), // $10\n minExecutionTimeMs: parseInt(process.env.MIN_EXECUTION_TIME_MS ?? \"1800000\", 10), // 30 min\n heartbeatIntervalMs: parseInt(process.env.HEARTBEAT_INTERVAL_MS ?? \"60000\", 10), // 1 min\n pollIntervalMs: parseInt(process.env.POLL_INTERVAL_MS ?? \"30000\", 10), // 30 sec\n\n // Requester behavior\n maxPendingTasks: parseInt(process.env.MAX_PENDING_TASKS ?? \"20\", 10),\n autoConfirmDeterministic: process.env.AUTO_CONFIRM_DETERMINISTIC !== \"false\",\n taskTimeoutMs: parseInt(process.env.TASK_TIMEOUT_MS ?? \"3600000\", 10), // 1 hour\n\n // Skills\n skillIds: process.env.SKILL_IDS?.split(\",\").filter(Boolean) ?? [],\n\n // State persistence\n stateFilePath: process.env.STATE_FILE_PATH ?? \"./.agent-state.json\",\n\n // Webhook server\n webhookPort: process.env.WEBHOOK_PORT\n ? parseInt(process.env.WEBHOOK_PORT, 10)\n : undefined,\n webhookSecret: process.env.WEBHOOK_SECRET,\n };\n}\n\n/**\n * Validate configuration\n */\nexport function validateConfig(config: AgentConfig): void {\n if (config.mode === \"worker\" || config.mode === \"hybrid\") {\n if (config.skillIds.length === 0) {\n console.warn(\"⚠ No skill IDs configured. Agent will not accept any tasks.\");\n }\n\n if (config.maxConcurrentTasks < 1) {\n throw new Error(\"maxConcurrentTasks must be at least 1\");\n }\n }\n\n if (config.mode === \"requester\" || config.mode === \"hybrid\") {\n if (config.maxPendingTasks < 1) {\n throw new Error(\"maxPendingTasks must be at least 1\");\n }\n }\n\n if (config.heartbeatIntervalMs < 10000) {\n console.warn(\"⚠ Heartbeat interval < 10s may cause rate limiting\");\n }\n\n if (![\"worker\", \"requester\", \"hybrid\"].includes(config.mode)) {\n throw new Error(`Invalid AGENT_MODE: ${config.mode}. Must be worker, requester, or hybrid`);\n }\n}\n"],"mappings":"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","names":["loadState"]}
@@ -0,0 +1,406 @@
1
+ import { ClankClient } from '@clankxyz/sdk';
2
+ import { Network } from '@clankxyz/shared';
3
+
4
+ /**
5
+ * Agent mode: worker executes tasks, requester creates and monitors tasks
6
+ */
7
+ type AgentMode = "worker" | "requester" | "hybrid";
8
+ /**
9
+ * Agent configuration loaded from environment variables
10
+ */
11
+ interface AgentConfig {
12
+ apiUrl: string;
13
+ apiKey: string;
14
+ agentId: string;
15
+ mode: AgentMode;
16
+ network: Network;
17
+ rpcUrl?: string;
18
+ packageId?: string;
19
+ walrusAggregator?: string;
20
+ walrusPublisher?: string;
21
+ maxConcurrentTasks: number;
22
+ minPaymentThreshold: bigint;
23
+ minExecutionTimeMs: number;
24
+ heartbeatIntervalMs: number;
25
+ pollIntervalMs: number;
26
+ maxPendingTasks: number;
27
+ autoConfirmDeterministic: boolean;
28
+ taskTimeoutMs: number;
29
+ skillIds: string[];
30
+ stateFilePath: string;
31
+ webhookPort?: number;
32
+ webhookSecret?: string;
33
+ }
34
+ /**
35
+ * Load configuration from environment variables
36
+ */
37
+ declare function loadConfig(): AgentConfig;
38
+ /**
39
+ * Validate configuration
40
+ */
41
+ declare function validateConfig(config: AgentConfig): void;
42
+
43
+ /**
44
+ * Active task being processed by the agent
45
+ */
46
+ interface ActiveTask {
47
+ taskId: string;
48
+ skillId: string;
49
+ skillName: string;
50
+ status: number;
51
+ paymentAmountMist: string;
52
+ workerBondAmount: string;
53
+ inputPayloadRef: string;
54
+ expectedOutputHash?: string;
55
+ acceptedAt: number;
56
+ expiresAt: number;
57
+ }
58
+ /**
59
+ * Registered skill that this agent can handle
60
+ */
61
+ interface RegisteredSkill {
62
+ skillId: string;
63
+ name: string;
64
+ version: string;
65
+ verificationType: number;
66
+ basePriceMist: string;
67
+ workerBondMist: string;
68
+ }
69
+ /**
70
+ * Pending task created by the agent (requester mode)
71
+ */
72
+ interface PendingTask {
73
+ taskId: string;
74
+ skillId: string;
75
+ skillName: string;
76
+ status: number;
77
+ paymentAmountMist: string;
78
+ workerBondAmount: string;
79
+ inputPayloadRef: string;
80
+ expectedOutputHash?: string;
81
+ createdAt: number;
82
+ expiresAt: number;
83
+ workerId?: string;
84
+ outputPayloadRef?: string;
85
+ submittedAt?: number;
86
+ }
87
+ /**
88
+ * Agent state that is persisted to disk
89
+ */
90
+ interface AgentState {
91
+ activeTasks: ActiveTask[];
92
+ pendingTasks: PendingTask[];
93
+ skills: RegisteredSkill[];
94
+ stats: {
95
+ tasksAccepted: number;
96
+ tasksCompleted: number;
97
+ tasksFailed: number;
98
+ totalEarnedMist: string;
99
+ lastHeartbeat: number;
100
+ startedAt: number;
101
+ };
102
+ requesterStats: {
103
+ tasksCreated: number;
104
+ tasksSettled: number;
105
+ tasksExpired: number;
106
+ totalSpentMist: string;
107
+ };
108
+ agentId: string;
109
+ }
110
+ /**
111
+ * Create initial empty state
112
+ */
113
+ declare function createInitialState(agentId: string): AgentState;
114
+ /**
115
+ * Load state from file
116
+ */
117
+ declare function loadState(filePath: string, agentId: string): Promise<AgentState>;
118
+ /**
119
+ * Save state to file
120
+ */
121
+ declare function saveState(filePath: string, state: AgentState): Promise<void>;
122
+ /**
123
+ * Add active task to state
124
+ */
125
+ declare function addActiveTask(state: AgentState, task: ActiveTask): void;
126
+ /**
127
+ * Remove active task from state
128
+ */
129
+ declare function removeActiveTask(state: AgentState, taskId: string): void;
130
+ /**
131
+ * Mark task as completed
132
+ */
133
+ declare function markTaskCompleted(state: AgentState, taskId: string, earnedMist: string): void;
134
+ /**
135
+ * Mark task as failed
136
+ */
137
+ declare function markTaskFailed(state: AgentState, taskId: string): void;
138
+ /**
139
+ * Add pending task to state (requester mode)
140
+ */
141
+ declare function addPendingTask(state: AgentState, task: PendingTask): void;
142
+ /**
143
+ * Update pending task in state
144
+ */
145
+ declare function updatePendingTask(state: AgentState, taskId: string, updates: Partial<PendingTask>): void;
146
+ /**
147
+ * Mark pending task as settled
148
+ */
149
+ declare function markPendingSettled(state: AgentState, taskId: string, spentMist: string): void;
150
+ /**
151
+ * Mark pending task as expired
152
+ */
153
+ declare function markPendingExpired(state: AgentState, taskId: string): void;
154
+
155
+ /**
156
+ * Result of skill execution
157
+ */
158
+ interface SkillResult {
159
+ success: boolean;
160
+ output?: object;
161
+ error?: string;
162
+ }
163
+ /**
164
+ * Skill handler interface - implement this for each skill
165
+ */
166
+ interface SkillHandler {
167
+ /** Handler name */
168
+ name: string;
169
+ /** Handler version */
170
+ version: string;
171
+ /**
172
+ * Check if this handler can process the given skill
173
+ */
174
+ canHandle(skillName: string, skillVersion: string): boolean;
175
+ /**
176
+ * Execute the skill with the given input
177
+ */
178
+ execute(input: object, context?: SkillContext): Promise<SkillResult>;
179
+ /**
180
+ * Validate the input before processing
181
+ */
182
+ validateInput?(input: object): {
183
+ valid: boolean;
184
+ error?: string;
185
+ };
186
+ /**
187
+ * Estimate execution time in milliseconds
188
+ */
189
+ estimateExecutionTime?(input: object): number;
190
+ }
191
+ /**
192
+ * Context provided to skill handlers
193
+ */
194
+ interface SkillContext {
195
+ taskId: string;
196
+ skillId: string;
197
+ skillName: string;
198
+ skillVersion: string;
199
+ paymentAmountMist: bigint;
200
+ expiresAt: number;
201
+ }
202
+ /**
203
+ * Skill registry for managing available handlers
204
+ */
205
+ declare class SkillRegistry {
206
+ private handlers;
207
+ /**
208
+ * Register a skill handler
209
+ */
210
+ register(handler: SkillHandler): void;
211
+ /**
212
+ * Find a handler for the given skill
213
+ */
214
+ findHandler(skillName: string, skillVersion: string): SkillHandler | undefined;
215
+ /**
216
+ * Get all registered handlers
217
+ */
218
+ getHandlers(): SkillHandler[];
219
+ /**
220
+ * Check if any handler can process the skill
221
+ */
222
+ canHandle(skillName: string, skillVersion: string): boolean;
223
+ }
224
+
225
+ /**
226
+ * Echo skill handler - simply echoes back the input with metadata
227
+ *
228
+ * This is a reference implementation for testing the task flow.
229
+ */
230
+ declare const echoSkillHandler: SkillHandler;
231
+ /**
232
+ * Echo skill JSON schema
233
+ */
234
+ declare const echoInputSchema: {
235
+ $schema: string;
236
+ type: string;
237
+ description: string;
238
+ additionalProperties: boolean;
239
+ };
240
+ declare const echoOutputSchema: {
241
+ $schema: string;
242
+ type: string;
243
+ properties: {
244
+ echo: {
245
+ description: string;
246
+ };
247
+ metadata: {
248
+ type: string;
249
+ properties: {
250
+ processedAt: {
251
+ type: string;
252
+ };
253
+ processingTimeMs: {
254
+ type: string;
255
+ };
256
+ handler: {
257
+ type: string;
258
+ };
259
+ version: {
260
+ type: string;
261
+ };
262
+ };
263
+ required: string[];
264
+ };
265
+ };
266
+ required: string[];
267
+ };
268
+
269
+ /**
270
+ * Task creation request for requester mode
271
+ */
272
+ interface CreateTaskRequest {
273
+ skillId: string;
274
+ input: object;
275
+ paymentAmountMist: bigint;
276
+ expiresInMs?: number;
277
+ expectedOutputHash?: string;
278
+ }
279
+ /**
280
+ * Clank Reference Agent
281
+ *
282
+ * A reference implementation of an autonomous agent that:
283
+ * - Worker Mode: Polls for tasks, accepts, executes, and submits
284
+ * - Requester Mode: Creates tasks, monitors progress, confirms/rejects
285
+ * - Hybrid Mode: Both worker and requester capabilities
286
+ * - Persists state for crash recovery
287
+ */
288
+ declare class ClankAgent {
289
+ private client;
290
+ private config;
291
+ private state;
292
+ private skillRegistry;
293
+ private running;
294
+ private heartbeatTimer?;
295
+ private taskCreationQueue;
296
+ constructor(config: AgentConfig);
297
+ /**
298
+ * Register a custom skill handler
299
+ */
300
+ registerSkillHandler(handler: typeof echoSkillHandler): void;
301
+ /**
302
+ * Start the agent
303
+ */
304
+ start(): Promise<void>;
305
+ /**
306
+ * Stop the agent gracefully
307
+ */
308
+ stop(): Promise<void>;
309
+ /**
310
+ * Main heartbeat loop
311
+ */
312
+ private heartbeat;
313
+ /**
314
+ * Poll for available tasks
315
+ */
316
+ private pollForTasks;
317
+ /**
318
+ * Accept a task
319
+ */
320
+ private acceptTask;
321
+ /**
322
+ * Process active tasks
323
+ */
324
+ private processActiveTasks;
325
+ /**
326
+ * Execute a task
327
+ */
328
+ private executeTask;
329
+ /**
330
+ * Refresh skills list from API
331
+ */
332
+ private refreshSkills;
333
+ /**
334
+ * Recover active tasks after restart
335
+ */
336
+ private recoverActiveTasks;
337
+ /**
338
+ * Get current stats
339
+ */
340
+ getStats(): {
341
+ worker: {
342
+ activeTasks: number;
343
+ registeredSkills: number;
344
+ tasksAccepted: number;
345
+ tasksCompleted: number;
346
+ tasksFailed: number;
347
+ totalEarnedMist: string;
348
+ lastHeartbeat: number;
349
+ startedAt: number;
350
+ };
351
+ requester: {
352
+ pendingTasks: number;
353
+ queuedTasks: number;
354
+ tasksCreated: number;
355
+ tasksSettled: number;
356
+ tasksExpired: number;
357
+ totalSpentMist: string;
358
+ };
359
+ };
360
+ /**
361
+ * Get the SDK client
362
+ */
363
+ getClient(): ClankClient;
364
+ /**
365
+ * Queue a task for creation (requester mode)
366
+ */
367
+ queueTask(request: CreateTaskRequest): void;
368
+ /**
369
+ * Process task creation queue
370
+ */
371
+ private processTaskCreationQueue;
372
+ /**
373
+ * Create a task on-chain (requester mode)
374
+ */
375
+ private createTask;
376
+ /**
377
+ * Monitor pending tasks and process submissions
378
+ */
379
+ private monitorPendingTasks;
380
+ /**
381
+ * Process a submitted task (verify output and confirm/reject)
382
+ */
383
+ private processSubmittedTask;
384
+ /**
385
+ * Confirm a submitted task (release payment to worker)
386
+ */
387
+ confirmTask(task: PendingTask): Promise<void>;
388
+ /**
389
+ * Reject a submitted task (return payment, slash worker bond)
390
+ */
391
+ rejectTask(task: PendingTask, reason: string): Promise<void>;
392
+ /**
393
+ * Get pending task by ID
394
+ */
395
+ getPendingTask(taskId: string): PendingTask | undefined;
396
+ /**
397
+ * Get all pending tasks
398
+ */
399
+ getPendingTasks(): PendingTask[];
400
+ /**
401
+ * Recover pending tasks after restart
402
+ */
403
+ private recoverPendingTasks;
404
+ }
405
+
406
+ export { type ActiveTask, type AgentConfig, type AgentMode, type AgentState, ClankAgent, type CreateTaskRequest, type PendingTask, type RegisteredSkill, type SkillContext, type SkillHandler, SkillRegistry, type SkillResult, addActiveTask, addPendingTask, createInitialState, echoInputSchema, echoOutputSchema, echoSkillHandler, loadConfig, loadState, markPendingExpired, markPendingSettled, markTaskCompleted, markTaskFailed, removeActiveTask, saveState, updatePendingTask, validateConfig };