@clankxyz/agent 0.1.3 ā 0.1.4
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/cli.js +33 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1400,11 +1400,13 @@ var ClankAgent = class {
|
|
|
1400
1400
|
console.log(` Output stored: ${storedOutput.blobId.slice(0, 20)}...`);
|
|
1401
1401
|
if (this.keypair && this.suiClient && this.config.packageId) {
|
|
1402
1402
|
try {
|
|
1403
|
+
console.log(` Accepting on-chain...`);
|
|
1404
|
+
await this.acceptTaskOnChain(task.taskId);
|
|
1403
1405
|
console.log(` Submitting on-chain...`);
|
|
1404
1406
|
await this.submitTaskOnChain(task.taskId, storedOutput.blobId);
|
|
1405
1407
|
console.log(` \u2705 Task submitted on-chain: ${task.taskId.slice(0, 16)}`);
|
|
1406
1408
|
} catch (error) {
|
|
1407
|
-
console.error(` \u274C On-chain
|
|
1409
|
+
console.error(` \u274C On-chain transaction failed: ${error}`);
|
|
1408
1410
|
}
|
|
1409
1411
|
} else {
|
|
1410
1412
|
console.log(` \u2705 Task completed (no on-chain key): ${task.taskId.slice(0, 16)}`);
|
|
@@ -1415,6 +1417,36 @@ var ClankAgent = class {
|
|
|
1415
1417
|
markTaskFailed(this.state, task.taskId);
|
|
1416
1418
|
}
|
|
1417
1419
|
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Accept task on-chain (moves from POSTED to IN_PROGRESS)
|
|
1422
|
+
*/
|
|
1423
|
+
async acceptTaskOnChain(taskId) {
|
|
1424
|
+
if (!this.keypair || !this.suiClient || !this.config.packageId) {
|
|
1425
|
+
throw new Error("On-chain signing not configured");
|
|
1426
|
+
}
|
|
1427
|
+
const tx = new Transaction();
|
|
1428
|
+
tx.setGasBudget(1e7);
|
|
1429
|
+
const [zeroCoin] = tx.splitCoins(tx.gas, [0]);
|
|
1430
|
+
tx.moveCall({
|
|
1431
|
+
target: `${this.config.packageId}::task::accept`,
|
|
1432
|
+
arguments: [
|
|
1433
|
+
tx.object(taskId),
|
|
1434
|
+
tx.object(this.config.agentId),
|
|
1435
|
+
zeroCoin,
|
|
1436
|
+
tx.object("0x6")
|
|
1437
|
+
// Clock
|
|
1438
|
+
]
|
|
1439
|
+
});
|
|
1440
|
+
const result = await this.suiClient.signAndExecuteTransaction({
|
|
1441
|
+
transaction: tx,
|
|
1442
|
+
signer: this.keypair,
|
|
1443
|
+
options: { showEffects: true }
|
|
1444
|
+
});
|
|
1445
|
+
if (result.effects?.status?.status !== "success") {
|
|
1446
|
+
throw new Error(`Accept failed: ${result.effects?.status?.error || "unknown"}`);
|
|
1447
|
+
}
|
|
1448
|
+
console.log(` Accept Tx: ${result.digest.slice(0, 15)}...`);
|
|
1449
|
+
}
|
|
1418
1450
|
/**
|
|
1419
1451
|
* Submit task output on-chain
|
|
1420
1452
|
*/
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/state.ts","../src/cli.ts","../src/agent.ts","../src/skills/types.ts","../src/skills/echo.ts","../src/skills/translation.ts","../src/skills/summarization.ts","../src/skills/sentiment.ts","../src/skills/image-generation.ts","../src/skills/code-review.ts","../src/skills/index.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\";\nimport { allSkillHandlers } from \"./skills/index.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 // Register all skill handlers\n for (const handler of allSkillHandlers) {\n agent.registerSkillHandler(handler);\n }\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(` CLANK_API_URL API server URL`);\n console.log(` CLANK_API_KEY API authentication key`);\n console.log(` CLANK_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(` CLANK_NETWORK Network (testnet, mainnet) [default: testnet]`);\n console.log(` CLANK_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(`CLANK_API_URL=http://localhost:3000\nCLANK_API_KEY=ck_your_api_key\nCLANK_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(`CLANK_API_URL=http://localhost:3000\nCLANK_API_KEY=ck_your_api_key\nCLANK_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(`CLANK_API_URL=http://localhost:3000\nCLANK_API_KEY=ck_your_api_key\nCLANK_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 { Ed25519Keypair } from \"@mysten/sui/keypairs/ed25519\";\nimport { SuiClient } from \"@mysten/sui/client\";\nimport { Transaction } from \"@mysten/sui/transactions\";\nimport { decodeSuiPrivateKey } from \"@mysten/sui/cryptography\";\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 // On-chain transaction capabilities\n private keypair?: Ed25519Keypair;\n private suiClient?: SuiClient;\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 // Initialize on-chain transaction capabilities if private key provided\n if (config.privateKey) {\n try {\n const { secretKey } = decodeSuiPrivateKey(config.privateKey);\n this.keypair = Ed25519Keypair.fromSecretKey(secretKey);\n \n const rpcUrl = config.rpcUrl || (config.network === \"mainnet\" \n ? \"https://fullnode.mainnet.sui.io:443\"\n : \"https://fullnode.testnet.sui.io:443\");\n this.suiClient = new SuiClient({ url: rpcUrl });\n \n console.log(` š On-chain signing enabled: ${this.keypair.toSuiAddress().slice(0, 15)}...`);\n } catch (error) {\n console.error(` ā ļø Failed to load private key: ${error}`);\n }\n }\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 ALL our skills\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let allTasks: any[] = [];\n \n for (const skillId of skillIds) {\n const result = await this.client.api.listTasks({\n status: STATUS.POSTED,\n skillId: skillId,\n limit: 10,\n });\n allTasks = [...allTasks, ...result.data];\n }\n \n // Deduplicate by task ID\n const seen = new Set<string>();\n const tasks = allTasks.filter((t) => {\n if (seen.has(t.id)) return false;\n seen.add(t.id);\n return true;\n });\n \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 on-chain if we have signing capability\n if (this.keypair && this.suiClient && this.config.packageId) {\n try {\n console.log(` Submitting on-chain...`);\n await this.submitTaskOnChain(task.taskId, storedOutput.blobId);\n console.log(` ā
Task submitted on-chain: ${task.taskId.slice(0, 16)}`);\n } catch (error) {\n console.error(` ā On-chain submission failed: ${error}`);\n // Still mark as completed locally for retry later\n }\n } else {\n console.log(` ā
Task completed (no on-chain key): ${task.taskId.slice(0, 16)}`);\n }\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 * Submit task output on-chain\n */\n private async submitTaskOnChain(taskId: string, outputRef: string): Promise<void> {\n if (!this.keypair || !this.suiClient || !this.config.packageId) {\n throw new Error(\"On-chain signing not configured\");\n }\n \n // Generate output hash from the output ref\n const outputHash = outputRef; // Use blob ID as hash for simplicity\n \n const tx = new Transaction();\n tx.setGasBudget(10_000_000); // 0.01 SUI gas\n \n // Call task::submit(task, worker, output_ref, output_hash, clock)\n tx.moveCall({\n target: `${this.config.packageId}::task::submit`,\n arguments: [\n tx.object(taskId),\n tx.object(this.config.agentId),\n tx.pure.string(outputRef),\n tx.pure.string(outputHash),\n tx.object(\"0x6\"), // Clock\n ],\n });\n \n const result = await this.suiClient.signAndExecuteTransaction({\n transaction: tx,\n signer: this.keypair,\n options: { showEffects: true },\n });\n \n if (result.effects?.status?.status !== \"success\") {\n throw new Error(`Transaction failed: ${result.effects?.status?.error || \"unknown\"}`);\n }\n \n console.log(` Tx: ${result.digest.slice(0, 15)}...`);\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 type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Translation skill handler - translates text between languages\n *\n * Supports two modes:\n * 1. Mock mode (default): Uses simple word replacement for testing\n * 2. LLM mode: Uses OpenAI API for real translations (requires OPENAI_API_KEY)\n */\n\n// Language codes we support\nconst SUPPORTED_LANGUAGES = [\n \"en\", // English\n \"es\", // Spanish\n \"fr\", // French\n \"de\", // German\n \"it\", // Italian\n \"pt\", // Portuguese\n \"ja\", // Japanese\n \"zh\", // Chinese\n \"ko\", // Korean\n \"ar\", // Arabic\n] as const;\n\ntype LanguageCode = (typeof SUPPORTED_LANGUAGES)[number];\n\ninterface TranslationInput {\n text: string;\n source_language?: LanguageCode;\n target_language: LanguageCode;\n}\n\ninterface TranslationOutput {\n translated_text: string;\n source_language: string;\n target_language: string;\n confidence: number;\n word_count: number;\n processing_time_ms: number;\n mode: \"mock\" | \"llm\";\n}\n\n/**\n * Mock translation - for testing without API keys\n * Simply adds language prefix and reverses words for demo\n */\nfunction mockTranslate(text: string, targetLang: LanguageCode): string {\n const prefixes: Record<LanguageCode, string> = {\n en: \"[EN]\",\n es: \"[ES]\",\n fr: \"[FR]\",\n de: \"[DE]\",\n it: \"[IT]\",\n pt: \"[PT]\",\n ja: \"[JA]\",\n zh: \"[ZH]\",\n ko: \"[KO]\",\n ar: \"[AR]\",\n };\n\n // Simple mock: add prefix and keep text (in real usage, this would be actual translation)\n return `${prefixes[targetLang]} ${text}`;\n}\n\n/**\n * LLM-based translation using OpenAI\n */\nasync function llmTranslate(\n text: string,\n sourceLang: string,\n targetLang: LanguageCode\n): Promise<string> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const languageNames: Record<LanguageCode, string> = {\n en: \"English\",\n es: \"Spanish\",\n fr: \"French\",\n de: \"German\",\n it: \"Italian\",\n pt: \"Portuguese\",\n ja: \"Japanese\",\n zh: \"Chinese\",\n ko: \"Korean\",\n ar: \"Arabic\",\n };\n\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"gpt-4o-mini\",\n messages: [\n {\n role: \"system\",\n content: `You are a professional translator. Translate the following text from ${sourceLang} to ${languageNames[targetLang]}. Only output the translated text, nothing else.`,\n },\n {\n role: \"user\",\n content: text,\n },\n ],\n temperature: 0.3,\n max_tokens: 2048,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${error}`);\n }\n\n const data = await response.json();\n return data.choices[0].message.content.trim();\n}\n\nexport const translationSkillHandler: SkillHandler = {\n name: \"translation\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, skillVersion: string): boolean {\n const name = skillName.toLowerCase();\n return (\n name.includes(\"translat\") ||\n name.includes(\"translate\") ||\n name === \"translation\"\n );\n },\n\n async execute(\n input: object,\n context?: SkillContext\n ): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const { text, source_language, target_language } =\n input as TranslationInput;\n\n // Validate input\n if (!text || typeof text !== \"string\") {\n return {\n success: false,\n error: \"Missing or invalid 'text' field\",\n };\n }\n\n if (!target_language || !SUPPORTED_LANGUAGES.includes(target_language)) {\n return {\n success: false,\n error: `Invalid target_language. Supported: ${SUPPORTED_LANGUAGES.join(\", \")}`,\n };\n }\n\n // Detect source language if not provided (default to English)\n const sourceLang = source_language || \"en\";\n\n // Choose translation mode\n const useLLM = !!process.env.OPENAI_API_KEY;\n let translatedText: string;\n\n if (useLLM) {\n translatedText = await llmTranslate(text, sourceLang, target_language);\n } else {\n // Mock mode for testing\n translatedText = mockTranslate(text, target_language);\n }\n\n const output: TranslationOutput = {\n translated_text: translatedText,\n source_language: sourceLang,\n target_language,\n confidence: useLLM ? 0.95 : 0.5, // Mock has low confidence\n word_count: text.split(/\\s+/).length,\n processing_time_ms: Date.now() - startTime,\n mode: useLLM ? \"llm\" : \"mock\",\n };\n\n return {\n success: true,\n output,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Translation failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { text, target_language } = input as TranslationInput;\n\n if (!text || typeof text !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'text' field\" };\n }\n\n if (text.length > 10000) {\n return { valid: false, error: \"Text too long (max 10000 characters)\" };\n }\n\n if (!target_language) {\n return { valid: false, error: \"Missing 'target_language' field\" };\n }\n\n if (!SUPPORTED_LANGUAGES.includes(target_language as LanguageCode)) {\n return {\n valid: false,\n error: `Unsupported target_language. Use: ${SUPPORTED_LANGUAGES.join(\", \")}`,\n };\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { text } = input as TranslationInput;\n const wordCount = text?.split(/\\s+/).length || 0;\n // Estimate ~50ms per word for LLM, ~10ms per word for mock\n const useLLM = !!process.env.OPENAI_API_KEY;\n return useLLM ? wordCount * 50 + 1000 : wordCount * 10 + 100;\n },\n};\n\n/**\n * Translation skill JSON schemas\n */\nexport const translationInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n text: {\n type: \"string\",\n description: \"Text to translate\",\n maxLength: 10000,\n },\n source_language: {\n type: \"string\",\n enum: SUPPORTED_LANGUAGES,\n description: \"Source language code (auto-detected if not provided)\",\n },\n target_language: {\n type: \"string\",\n enum: SUPPORTED_LANGUAGES,\n description: \"Target language code\",\n },\n },\n required: [\"text\", \"target_language\"],\n};\n\nexport const translationOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n translated_text: { type: \"string\" },\n source_language: { type: \"string\" },\n target_language: { type: \"string\" },\n confidence: { type: \"number\", minimum: 0, maximum: 1 },\n word_count: { type: \"integer\" },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"llm\"] },\n },\n required: [\n \"translated_text\",\n \"source_language\",\n \"target_language\",\n \"confidence\",\n \"word_count\",\n \"processing_time_ms\",\n \"mode\",\n ],\n};\n","import type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Summarization skill handler - summarizes text content\n *\n * Supports two modes:\n * 1. Mock mode (default): Uses extractive summarization (first sentences)\n * 2. LLM mode: Uses OpenAI API for abstractive summarization\n */\n\ntype SummaryLength = \"short\" | \"medium\" | \"long\";\n\ninterface SummarizationInput {\n text: string;\n length?: SummaryLength;\n max_sentences?: number;\n style?: \"bullet\" | \"paragraph\";\n}\n\ninterface SummarizationOutput {\n summary: string;\n original_length: number;\n summary_length: number;\n compression_ratio: number;\n sentence_count: number;\n processing_time_ms: number;\n mode: \"mock\" | \"llm\";\n}\n\n/**\n * Extract first N sentences as mock summary\n */\nfunction mockSummarize(text: string, maxSentences: number): string {\n // Split into sentences (simple approach)\n const sentences = text\n .split(/(?<=[.!?])\\s+/)\n .filter((s) => s.trim().length > 0);\n\n const selectedSentences = sentences.slice(0, maxSentences);\n return selectedSentences.join(\" \");\n}\n\n/**\n * LLM-based summarization using OpenAI\n */\nasync function llmSummarize(\n text: string,\n length: SummaryLength,\n style: \"bullet\" | \"paragraph\"\n): Promise<string> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const lengthInstructions: Record<SummaryLength, string> = {\n short: \"Provide a very brief summary in 1-2 sentences.\",\n medium: \"Provide a concise summary in 3-5 sentences.\",\n long: \"Provide a comprehensive summary covering all main points.\",\n };\n\n const styleInstructions = {\n bullet: \"Format as bullet points.\",\n paragraph: \"Format as flowing prose.\",\n };\n\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"gpt-4o-mini\",\n messages: [\n {\n role: \"system\",\n content: `You are a professional summarizer. ${lengthInstructions[length]} ${styleInstructions[style]} Only output the summary, nothing else.`,\n },\n {\n role: \"user\",\n content: `Summarize this text:\\n\\n${text}`,\n },\n ],\n temperature: 0.3,\n max_tokens: 1024,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${error}`);\n }\n\n const data = await response.json();\n return data.choices[0].message.content.trim();\n}\n\nexport const summarizationSkillHandler: SkillHandler = {\n name: \"summarization\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, skillVersion: string): boolean {\n const name = skillName.toLowerCase();\n return (\n name.includes(\"summar\") ||\n name.includes(\"digest\") ||\n name.includes(\"tldr\") ||\n name === \"summarize\"\n );\n },\n\n async execute(\n input: object,\n context?: SkillContext\n ): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const {\n text,\n length = \"medium\",\n max_sentences,\n style = \"paragraph\",\n } = input as SummarizationInput;\n\n // Validate input\n if (!text || typeof text !== \"string\") {\n return {\n success: false,\n error: \"Missing or invalid 'text' field\",\n };\n }\n\n // Choose summarization mode\n const useLLM = !!process.env.OPENAI_API_KEY;\n let summary: string;\n\n if (useLLM) {\n summary = await llmSummarize(text, length, style);\n } else {\n // Mock mode - extract first sentences based on length\n const sentenceCounts: Record<SummaryLength, number> = {\n short: 2,\n medium: 4,\n long: 8,\n };\n const numSentences = max_sentences || sentenceCounts[length];\n summary = mockSummarize(text, numSentences);\n }\n\n const output: SummarizationOutput = {\n summary,\n original_length: text.length,\n summary_length: summary.length,\n compression_ratio:\n Math.round((1 - summary.length / text.length) * 100) / 100,\n sentence_count: summary.split(/(?<=[.!?])\\s+/).length,\n processing_time_ms: Date.now() - startTime,\n mode: useLLM ? \"llm\" : \"mock\",\n };\n\n return {\n success: true,\n output,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Summarization failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { text, length, style } = input as SummarizationInput;\n\n if (!text || typeof text !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'text' field\" };\n }\n\n if (text.length < 50) {\n return { valid: false, error: \"Text too short (min 50 characters)\" };\n }\n\n if (text.length > 50000) {\n return { valid: false, error: \"Text too long (max 50000 characters)\" };\n }\n\n if (length && ![\"short\", \"medium\", \"long\"].includes(length)) {\n return { valid: false, error: \"Invalid length. Use: short, medium, long\" };\n }\n\n if (style && ![\"bullet\", \"paragraph\"].includes(style)) {\n return { valid: false, error: \"Invalid style. Use: bullet, paragraph\" };\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { text } = input as SummarizationInput;\n const charCount = text?.length || 0;\n // Estimate ~1ms per 10 chars for LLM, ~0.1ms per 10 chars for mock\n const useLLM = !!process.env.OPENAI_API_KEY;\n return useLLM ? charCount / 10 + 2000 : charCount / 100 + 100;\n },\n};\n\n/**\n * Summarization skill JSON schemas\n */\nexport const summarizationInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n text: {\n type: \"string\",\n description: \"Text to summarize\",\n minLength: 50,\n maxLength: 50000,\n },\n length: {\n type: \"string\",\n enum: [\"short\", \"medium\", \"long\"],\n description: \"Desired summary length\",\n default: \"medium\",\n },\n max_sentences: {\n type: \"integer\",\n minimum: 1,\n maximum: 20,\n description: \"Maximum number of sentences (overrides length)\",\n },\n style: {\n type: \"string\",\n enum: [\"bullet\", \"paragraph\"],\n description: \"Output format style\",\n default: \"paragraph\",\n },\n },\n required: [\"text\"],\n};\n\nexport const summarizationOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n summary: { type: \"string\" },\n original_length: { type: \"integer\" },\n summary_length: { type: \"integer\" },\n compression_ratio: { type: \"number\", minimum: 0, maximum: 1 },\n sentence_count: { type: \"integer\" },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"llm\"] },\n },\n required: [\n \"summary\",\n \"original_length\",\n \"summary_length\",\n \"compression_ratio\",\n \"sentence_count\",\n \"processing_time_ms\",\n \"mode\",\n ],\n};\n","import type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Sentiment Analysis skill handler - analyzes text sentiment\n *\n * Supports two modes:\n * 1. Mock mode (default): Uses simple keyword matching\n * 2. LLM mode: Uses OpenAI API for nuanced analysis\n */\n\ntype SentimentLabel = \"positive\" | \"negative\" | \"neutral\" | \"mixed\";\n\ninterface SentimentInput {\n text: string;\n detailed?: boolean;\n}\n\ninterface SentimentOutput {\n sentiment: SentimentLabel;\n confidence: number;\n scores: {\n positive: number;\n negative: number;\n neutral: number;\n };\n keywords?: string[];\n explanation?: string;\n processing_time_ms: number;\n mode: \"mock\" | \"llm\";\n}\n\n// Simple keyword lists for mock mode\nconst POSITIVE_WORDS = new Set([\n \"good\",\n \"great\",\n \"excellent\",\n \"amazing\",\n \"wonderful\",\n \"fantastic\",\n \"love\",\n \"happy\",\n \"best\",\n \"awesome\",\n \"beautiful\",\n \"perfect\",\n \"brilliant\",\n \"superb\",\n \"outstanding\",\n \"pleased\",\n \"delighted\",\n \"enjoy\",\n \"like\",\n \"nice\",\n \"thanks\",\n \"thank\",\n \"helpful\",\n \"recommend\",\n \"satisfied\",\n]);\n\nconst NEGATIVE_WORDS = new Set([\n \"bad\",\n \"terrible\",\n \"awful\",\n \"horrible\",\n \"poor\",\n \"worst\",\n \"hate\",\n \"sad\",\n \"angry\",\n \"disappointing\",\n \"disappointed\",\n \"ugly\",\n \"fail\",\n \"failed\",\n \"broken\",\n \"useless\",\n \"waste\",\n \"problem\",\n \"issue\",\n \"bug\",\n \"error\",\n \"wrong\",\n \"sucks\",\n \"annoying\",\n \"frustrated\",\n]);\n\n/**\n * Mock sentiment analysis using keyword matching\n */\nfunction mockSentimentAnalysis(text: string): {\n sentiment: SentimentLabel;\n scores: { positive: number; negative: number; neutral: number };\n keywords: string[];\n} {\n const words = text.toLowerCase().split(/\\W+/);\n const positiveMatches: string[] = [];\n const negativeMatches: string[] = [];\n\n for (const word of words) {\n if (POSITIVE_WORDS.has(word)) positiveMatches.push(word);\n if (NEGATIVE_WORDS.has(word)) negativeMatches.push(word);\n }\n\n const total = words.length || 1;\n const positiveScore = positiveMatches.length / total;\n const negativeScore = negativeMatches.length / total;\n const neutralScore = 1 - positiveScore - negativeScore;\n\n let sentiment: SentimentLabel;\n if (positiveScore > negativeScore * 2) {\n sentiment = \"positive\";\n } else if (negativeScore > positiveScore * 2) {\n sentiment = \"negative\";\n } else if (positiveScore > 0 && negativeScore > 0) {\n sentiment = \"mixed\";\n } else {\n sentiment = \"neutral\";\n }\n\n return {\n sentiment,\n scores: {\n positive: Math.round(positiveScore * 100) / 100,\n negative: Math.round(negativeScore * 100) / 100,\n neutral: Math.round(neutralScore * 100) / 100,\n },\n keywords: [...positiveMatches, ...negativeMatches],\n };\n}\n\n/**\n * LLM-based sentiment analysis using OpenAI\n */\nasync function llmSentimentAnalysis(\n text: string,\n detailed: boolean\n): Promise<{\n sentiment: SentimentLabel;\n scores: { positive: number; negative: number; neutral: number };\n keywords: string[];\n explanation: string;\n}> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"gpt-4o-mini\",\n messages: [\n {\n role: \"system\",\n content: `You are a sentiment analysis expert. Analyze the sentiment of the given text and respond in JSON format with the following structure:\n{\n \"sentiment\": \"positive\" | \"negative\" | \"neutral\" | \"mixed\",\n \"scores\": { \"positive\": 0.0-1.0, \"negative\": 0.0-1.0, \"neutral\": 0.0-1.0 },\n \"keywords\": [\"list\", \"of\", \"sentiment\", \"keywords\"],\n \"explanation\": \"Brief explanation of the sentiment\"\n}\nOnly output valid JSON, nothing else.`,\n },\n {\n role: \"user\",\n content: text,\n },\n ],\n temperature: 0.1,\n max_tokens: 512,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${error}`);\n }\n\n const data = await response.json();\n const content = data.choices[0].message.content.trim();\n\n try {\n return JSON.parse(content);\n } catch {\n // Fallback if JSON parsing fails\n return {\n sentiment: \"neutral\",\n scores: { positive: 0.33, negative: 0.33, neutral: 0.34 },\n keywords: [],\n explanation: \"Failed to parse LLM response\",\n };\n }\n}\n\nexport const sentimentSkillHandler: SkillHandler = {\n name: \"sentiment\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, skillVersion: string): boolean {\n const name = skillName.toLowerCase();\n return (\n name.includes(\"sentiment\") ||\n name.includes(\"emotion\") ||\n name.includes(\"mood\") ||\n name.includes(\"opinion\")\n );\n },\n\n async execute(\n input: object,\n context?: SkillContext\n ): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const { text, detailed = false } = input as SentimentInput;\n\n // Validate input\n if (!text || typeof text !== \"string\") {\n return {\n success: false,\n error: \"Missing or invalid 'text' field\",\n };\n }\n\n // Choose analysis mode\n const useLLM = !!process.env.OPENAI_API_KEY;\n let result: {\n sentiment: SentimentLabel;\n scores: { positive: number; negative: number; neutral: number };\n keywords: string[];\n explanation?: string;\n };\n\n if (useLLM) {\n result = await llmSentimentAnalysis(text, detailed);\n } else {\n result = mockSentimentAnalysis(text);\n }\n\n // Calculate confidence based on score difference\n const maxScore = Math.max(\n result.scores.positive,\n result.scores.negative,\n result.scores.neutral\n );\n const confidence = useLLM ? Math.min(0.95, maxScore + 0.3) : maxScore;\n\n const output: SentimentOutput = {\n sentiment: result.sentiment,\n confidence: Math.round(confidence * 100) / 100,\n scores: result.scores,\n keywords: detailed ? result.keywords : undefined,\n explanation: detailed ? result.explanation : undefined,\n processing_time_ms: Date.now() - startTime,\n mode: useLLM ? \"llm\" : \"mock\",\n };\n\n return {\n success: true,\n output,\n };\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error ? error.message : \"Sentiment analysis failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { text } = input as SentimentInput;\n\n if (!text || typeof text !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'text' field\" };\n }\n\n if (text.length < 5) {\n return { valid: false, error: \"Text too short (min 5 characters)\" };\n }\n\n if (text.length > 10000) {\n return { valid: false, error: \"Text too long (max 10000 characters)\" };\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { text } = input as SentimentInput;\n const charCount = text?.length || 0;\n const useLLM = !!process.env.OPENAI_API_KEY;\n return useLLM ? charCount / 20 + 1000 : charCount / 100 + 50;\n },\n};\n\n/**\n * Sentiment Analysis skill JSON schemas\n */\nexport const sentimentInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n text: {\n type: \"string\",\n description: \"Text to analyze\",\n minLength: 5,\n maxLength: 10000,\n },\n detailed: {\n type: \"boolean\",\n description: \"Include keywords and explanation\",\n default: false,\n },\n },\n required: [\"text\"],\n};\n\nexport const sentimentOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n sentiment: {\n type: \"string\",\n enum: [\"positive\", \"negative\", \"neutral\", \"mixed\"],\n },\n confidence: { type: \"number\", minimum: 0, maximum: 1 },\n scores: {\n type: \"object\",\n properties: {\n positive: { type: \"number\", minimum: 0, maximum: 1 },\n negative: { type: \"number\", minimum: 0, maximum: 1 },\n neutral: { type: \"number\", minimum: 0, maximum: 1 },\n },\n required: [\"positive\", \"negative\", \"neutral\"],\n },\n keywords: { type: \"array\", items: { type: \"string\" } },\n explanation: { type: \"string\" },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"llm\"] },\n },\n required: [\"sentiment\", \"confidence\", \"scores\", \"processing_time_ms\", \"mode\"],\n};\n","import type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Image Generation Skill Handler\n *\n * Generates images from text prompts using AI models.\n * Supports two modes:\n * 1. Mock mode (default): Returns placeholder images from picsum.photos\n * 2. LLM mode: Uses OpenAI DALL-E API (requires OPENAI_API_KEY)\n */\n\nconst SUPPORTED_STYLES = [\n \"photorealistic\",\n \"digital-art\",\n \"anime\",\n \"oil-painting\",\n \"watercolor\",\n \"sketch\",\n] as const;\n\ntype ImageStyle = (typeof SUPPORTED_STYLES)[number];\n\ninterface ImageGenInput {\n prompt: string;\n negative_prompt?: string;\n style?: ImageStyle;\n width?: number;\n height?: number;\n num_images?: number;\n seed?: number;\n}\n\ninterface GeneratedImage {\n url: string;\n width: number;\n height: number;\n}\n\ninterface ImageGenOutput {\n images: GeneratedImage[];\n prompt: string;\n revised_prompt?: string;\n processing_time_ms: number;\n mode: \"mock\" | \"dalle\";\n model: string;\n seed?: number;\n}\n\n/**\n * Mock image generation - for testing without API keys\n * Returns placeholder images from picsum.photos\n */\nfunction mockGenerateImages(\n prompt: string,\n width: number,\n height: number,\n numImages: number,\n seed?: number\n): GeneratedImage[] {\n return Array.from({ length: numImages }, (_, i) => ({\n url: `https://picsum.photos/seed/${seed ?? Date.now() + i}/${width}/${height}`,\n width,\n height,\n }));\n}\n\n/**\n * DALL-E based image generation\n */\nasync function dalleGenerateImages(\n prompt: string,\n numImages: number,\n size: \"1024x1024\" | \"1792x1024\" | \"1024x1792\"\n): Promise<{ images: GeneratedImage[]; revised_prompt?: string }> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const response = await fetch(\"https://api.openai.com/v1/images/generations\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"dall-e-3\",\n prompt,\n n: numImages,\n size,\n quality: \"standard\",\n response_format: \"url\",\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`DALL-E API error: ${error}`);\n }\n\n const data = await response.json();\n const [width, height] = size.split(\"x\").map(Number);\n\n return {\n images: data.data.map((item: { url: string }) => ({\n url: item.url,\n width,\n height,\n })),\n revised_prompt: data.data[0]?.revised_prompt,\n };\n}\n\nexport const imageGenerationSkillHandler: SkillHandler = {\n name: \"image-generation\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, _skillVersion: string): boolean {\n const normalized = skillName.toLowerCase().replace(/[-_\\s]/g, \"\");\n return (\n normalized === \"imagegeneration\" ||\n normalized === \"imagegen\" ||\n normalized === \"texttoimage\" ||\n normalized === \"dalle\" ||\n normalized === \"stablediffusion\"\n );\n },\n\n async execute(input: object, context?: SkillContext): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const {\n prompt,\n style,\n width = 1024,\n height = 1024,\n num_images = 1,\n seed,\n } = input as ImageGenInput;\n\n // Validate input\n if (!prompt || typeof prompt !== \"string\") {\n return { success: false, error: \"Missing or invalid 'prompt' field\" };\n }\n\n if (prompt.length > 4000) {\n return { success: false, error: \"Prompt too long (max 4000 characters)\" };\n }\n\n if (width < 256 || width > 2048) {\n return { success: false, error: \"Width must be between 256 and 2048\" };\n }\n\n if (height < 256 || height > 2048) {\n return { success: false, error: \"Height must be between 256 and 2048\" };\n }\n\n if (num_images < 1 || num_images > 4) {\n return { success: false, error: \"num_images must be between 1 and 4\" };\n }\n\n // Build enhanced prompt with style\n const enhancedPrompt = style\n ? `${prompt}, ${style} style, high quality, detailed`\n : `${prompt}, high quality, detailed`;\n\n // Choose generation mode\n const useDalle = !!process.env.OPENAI_API_KEY;\n let images: GeneratedImage[];\n let revisedPrompt: string | undefined;\n\n if (useDalle) {\n // Map dimensions to DALL-E sizes\n const dalleSize =\n width > height\n ? \"1792x1024\"\n : height > width\n ? \"1024x1792\"\n : \"1024x1024\";\n\n const result = await dalleGenerateImages(enhancedPrompt, num_images, dalleSize as \"1024x1024\" | \"1792x1024\" | \"1024x1792\");\n images = result.images;\n revisedPrompt = result.revised_prompt;\n } else {\n // Mock mode for testing\n images = mockGenerateImages(prompt, width, height, num_images, seed);\n revisedPrompt = enhancedPrompt;\n }\n\n const output: ImageGenOutput = {\n images,\n prompt,\n revised_prompt: revisedPrompt,\n processing_time_ms: Date.now() - startTime,\n mode: useDalle ? \"dalle\" : \"mock\",\n model: useDalle ? \"dall-e-3\" : \"mock-diffusion-v1\",\n seed: seed ?? Math.floor(Math.random() * 1000000),\n };\n\n return { success: true, output };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Image generation failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { prompt, width, height, num_images, style } = input as ImageGenInput;\n\n if (!prompt || typeof prompt !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'prompt' field\" };\n }\n\n if (prompt.length === 0) {\n return { valid: false, error: \"Prompt cannot be empty\" };\n }\n\n if (prompt.length > 4000) {\n return { valid: false, error: \"Prompt too long (max 4000 characters)\" };\n }\n\n if (width !== undefined && (width < 256 || width > 2048)) {\n return { valid: false, error: \"Width must be between 256 and 2048\" };\n }\n\n if (height !== undefined && (height < 256 || height > 2048)) {\n return { valid: false, error: \"Height must be between 256 and 2048\" };\n }\n\n if (num_images !== undefined && (num_images < 1 || num_images > 4)) {\n return { valid: false, error: \"num_images must be between 1 and 4\" };\n }\n\n if (style !== undefined && !SUPPORTED_STYLES.includes(style)) {\n return {\n valid: false,\n error: `Invalid style. Supported: ${SUPPORTED_STYLES.join(\", \")}`,\n };\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { width = 1024, height = 1024, num_images = 1 } = input as ImageGenInput;\n const useDalle = !!process.env.OPENAI_API_KEY;\n\n if (useDalle) {\n // DALL-E typically takes 10-20 seconds per image\n return num_images * 15000;\n }\n\n // Mock mode is fast\n const resolutionFactor = (width * height) / (1024 * 1024);\n return Math.ceil(500 * resolutionFactor * num_images);\n },\n};\n\n/**\n * Image Generation skill JSON schemas\n */\nexport const imageGenInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n prompt: {\n type: \"string\",\n description: \"Text prompt describing the image to generate\",\n maxLength: 4000,\n },\n negative_prompt: {\n type: \"string\",\n description: \"What to avoid in the image\",\n },\n style: {\n type: \"string\",\n enum: SUPPORTED_STYLES,\n description: \"Art style for the image\",\n },\n width: {\n type: \"integer\",\n minimum: 256,\n maximum: 2048,\n default: 1024,\n description: \"Image width in pixels\",\n },\n height: {\n type: \"integer\",\n minimum: 256,\n maximum: 2048,\n default: 1024,\n description: \"Image height in pixels\",\n },\n num_images: {\n type: \"integer\",\n minimum: 1,\n maximum: 4,\n default: 1,\n description: \"Number of images to generate\",\n },\n seed: {\n type: \"integer\",\n description: \"Random seed for reproducibility\",\n },\n },\n required: [\"prompt\"],\n};\n\nexport const imageGenOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n images: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n url: { type: \"string\", format: \"uri\" },\n width: { type: \"integer\" },\n height: { type: \"integer\" },\n },\n required: [\"url\", \"width\", \"height\"],\n },\n },\n prompt: { type: \"string\" },\n revised_prompt: { type: \"string\" },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"dalle\"] },\n model: { type: \"string\" },\n seed: { type: \"integer\" },\n },\n required: [\"images\", \"prompt\", \"processing_time_ms\", \"mode\", \"model\"],\n};\n\nexport type { ImageGenInput, ImageGenOutput };\n","import type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Code Review Skill Handler\n *\n * Analyzes code for issues, best practices, and improvements.\n * Supports two modes:\n * 1. Mock mode (default): Uses pattern-based static analysis\n * 2. LLM mode: Uses OpenAI API for intelligent code review (requires OPENAI_API_KEY)\n */\n\nconst FOCUS_AREAS = [\n \"security\",\n \"performance\",\n \"readability\",\n \"bugs\",\n \"best-practices\",\n \"typing\",\n] as const;\n\ntype FocusArea = (typeof FOCUS_AREAS)[number];\n\ninterface CodeReviewInput {\n code: string;\n language?: string;\n context?: string;\n focus_areas?: FocusArea[];\n diff_only?: boolean;\n}\n\ninterface Issue {\n severity: \"critical\" | \"warning\" | \"info\" | \"suggestion\";\n line?: number;\n column?: number;\n message: string;\n category: string;\n suggestion?: string;\n code_snippet?: string;\n}\n\ninterface CodeReviewOutput {\n summary: string;\n overall_score: number;\n issues: Issue[];\n suggestions: string[];\n metrics: {\n lines_of_code: number;\n complexity: string;\n maintainability: string;\n };\n processing_time_ms: number;\n mode: \"mock\" | \"llm\";\n language_detected: string;\n issue_count: {\n critical: number;\n warning: number;\n info: number;\n suggestion: number;\n };\n}\n\n// Pattern-based issue detection\nconst ISSUE_PATTERNS = [\n { pattern: /console\\.log/g, message: \"Remove console.log in production\", severity: \"warning\" as const, category: \"best-practices\" },\n { pattern: /TODO|FIXME|HACK/g, message: \"Unresolved TODO/FIXME comment\", severity: \"info\" as const, category: \"maintainability\" },\n { pattern: /==\\s/g, message: \"Use strict equality (===) instead of loose equality (==)\", severity: \"warning\" as const, category: \"best-practices\" },\n { pattern: /var\\s+\\w+/g, message: \"Use const/let instead of var\", severity: \"suggestion\" as const, category: \"best-practices\" },\n { pattern: /:\\s*any\\s*[;,)>]/g, message: \"Avoid using 'any' type - be more specific\", severity: \"warning\" as const, category: \"typing\" },\n { pattern: /eval\\s*\\(/g, message: \"Avoid using eval() - potential security risk\", severity: \"critical\" as const, category: \"security\" },\n { pattern: /innerHTML\\s*=/g, message: \"innerHTML can lead to XSS - use textContent or sanitize\", severity: \"critical\" as const, category: \"security\" },\n { pattern: /password.*=.*[\"']/gi, message: \"Hardcoded password detected\", severity: \"critical\" as const, category: \"security\" },\n { pattern: /function\\s+\\w+\\s*\\([^)]{80,}\\)/g, message: \"Function has too many parameters - consider an options object\", severity: \"suggestion\" as const, category: \"readability\" },\n];\n\nfunction detectLanguage(code: string): string {\n if (code.includes(\"import React\") || code.includes(\"jsx\")) return \"typescript/react\";\n if (code.includes(\"fn \") && code.includes(\"->\")) return \"rust\";\n if (code.includes(\"func \") && code.includes(\":=\")) return \"go\";\n if (code.includes(\"def \") && code.includes(\":\")) return \"python\";\n if (code.includes(\"public class\") || code.includes(\"private void\")) return \"java\";\n if (code.includes(\"module \") && code.includes(\"public entry fun\")) return \"move\";\n if (code.includes(\"function\") || code.includes(\"const \") || code.includes(\"=>\")) return \"typescript\";\n return \"unknown\";\n}\n\nfunction analyzeCode(code: string, focusAreas?: FocusArea[]): Issue[] {\n const issues: Issue[] = [];\n const lines = code.split(\"\\n\");\n\n for (const pattern of ISSUE_PATTERNS) {\n // Skip if focus areas are specified and this category isn't included\n if (focusAreas && focusAreas.length > 0) {\n const categoryMatch = focusAreas.some(\n (area) => pattern.category.toLowerCase().includes(area.toLowerCase())\n );\n if (!categoryMatch) continue;\n }\n\n const matches = code.matchAll(pattern.pattern);\n for (const match of matches) {\n if (match.index === undefined) continue;\n\n // Find line number\n const beforeMatch = code.slice(0, match.index);\n const lineNumber = beforeMatch.split(\"\\n\").length;\n\n issues.push({\n severity: pattern.severity,\n line: lineNumber,\n message: pattern.message,\n category: pattern.category,\n code_snippet: lines[lineNumber - 1]?.trim().slice(0, 80),\n });\n }\n }\n\n return issues;\n}\n\n/**\n * LLM-based code review using OpenAI\n */\nasync function llmCodeReview(\n code: string,\n language: string,\n context?: string\n): Promise<{ summary: string; issues: Issue[]; suggestions: string[] }> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"gpt-4o-mini\",\n messages: [\n {\n role: \"system\",\n content: `You are an expert code reviewer. Analyze the following ${language} code and provide:\n1. A brief summary (1-2 sentences)\n2. A list of issues with severity (critical/warning/info/suggestion), line number if possible, message, and category\n3. General improvement suggestions\n\nRespond in JSON format:\n{\n \"summary\": \"string\",\n \"issues\": [{ \"severity\": \"critical|warning|info|suggestion\", \"line\": number|null, \"message\": \"string\", \"category\": \"string\" }],\n \"suggestions\": [\"string\"]\n}`,\n },\n {\n role: \"user\",\n content: context ? `Context: ${context}\\n\\nCode:\\n${code}` : code,\n },\n ],\n temperature: 0.3,\n max_tokens: 2048,\n response_format: { type: \"json_object\" },\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${error}`);\n }\n\n const data = await response.json();\n return JSON.parse(data.choices[0].message.content);\n}\n\nexport const codeReviewSkillHandler: SkillHandler = {\n name: \"code-review\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, _skillVersion: string): boolean {\n const normalized = skillName.toLowerCase().replace(/[-_\\s]/g, \"\");\n return (\n normalized === \"codereview\" ||\n normalized === \"codeanalysis\" ||\n normalized === \"linting\" ||\n normalized === \"staticanalysis\"\n );\n },\n\n async execute(input: object, context?: SkillContext): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const {\n code,\n language,\n context: codeContext,\n focus_areas,\n } = input as CodeReviewInput;\n\n // Validate input\n if (!code || typeof code !== \"string\") {\n return { success: false, error: \"Missing or invalid 'code' field\" };\n }\n\n if (code.length === 0) {\n return { success: false, error: \"Code cannot be empty\" };\n }\n\n if (code.length > 100000) {\n return { success: false, error: \"Code too long (max 100000 characters)\" };\n }\n\n const detectedLanguage = language || detectLanguage(code);\n const useLLM = !!process.env.OPENAI_API_KEY;\n\n let issues: Issue[];\n let summary: string;\n let suggestions: string[] = [];\n\n if (useLLM) {\n const llmResult = await llmCodeReview(code, detectedLanguage, codeContext);\n summary = llmResult.summary;\n issues = llmResult.issues;\n suggestions = llmResult.suggestions;\n } else {\n // Pattern-based analysis\n issues = analyzeCode(code, focus_areas);\n\n // Generate summary\n if (issues.filter((i) => i.severity === \"critical\").length > 0) {\n summary = `Found ${issues.filter((i) => i.severity === \"critical\").length} critical issue(s) that should be addressed immediately.`;\n } else if (issues.filter((i) => i.severity === \"warning\").length > 0) {\n summary = `Found ${issues.filter((i) => i.severity === \"warning\").length} warning(s) that need attention.`;\n } else if (issues.length === 0) {\n summary = \"No significant issues found. Code looks good!\";\n } else {\n summary = `Found ${issues.length} minor issue(s) and suggestions.`;\n }\n\n // Generate suggestions\n if (code.length > 500 && !code.includes(\"//\") && !code.includes(\"/*\")) {\n suggestions.push(\"Add comments to explain complex logic\");\n }\n if (code.split(\"\\n\").length > 100) {\n suggestions.push(\"Consider splitting large files into smaller modules\");\n }\n }\n\n // Count issues by severity\n const issueCount = {\n critical: issues.filter((i) => i.severity === \"critical\").length,\n warning: issues.filter((i) => i.severity === \"warning\").length,\n info: issues.filter((i) => i.severity === \"info\").length,\n suggestion: issues.filter((i) => i.severity === \"suggestion\").length,\n };\n\n // Calculate score (100 - deductions)\n const deductions =\n issueCount.critical * 20 +\n issueCount.warning * 5 +\n issueCount.info * 1 +\n issueCount.suggestion * 0.5;\n const overallScore = Math.max(0, Math.min(100, Math.round(100 - deductions)));\n\n // Calculate metrics\n const linesOfCode = code.split(\"\\n\").filter((l) => l.trim().length > 0).length;\n const complexity = linesOfCode < 50 ? \"low\" : linesOfCode < 200 ? \"medium\" : \"high\";\n const maintainability =\n overallScore > 80 ? \"excellent\" : overallScore > 60 ? \"good\" : overallScore > 40 ? \"fair\" : \"needs improvement\";\n\n const output: CodeReviewOutput = {\n summary,\n overall_score: overallScore,\n issues,\n suggestions,\n metrics: {\n lines_of_code: linesOfCode,\n complexity,\n maintainability,\n },\n processing_time_ms: Date.now() - startTime,\n mode: useLLM ? \"llm\" : \"mock\",\n language_detected: detectedLanguage,\n issue_count: issueCount,\n };\n\n return { success: true, output };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Code review failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { code, focus_areas } = input as CodeReviewInput;\n\n if (!code || typeof code !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'code' field\" };\n }\n\n if (code.length === 0) {\n return { valid: false, error: \"Code cannot be empty\" };\n }\n\n if (code.length > 100000) {\n return { valid: false, error: \"Code too long (max 100000 characters)\" };\n }\n\n if (focus_areas !== undefined) {\n if (!Array.isArray(focus_areas)) {\n return { valid: false, error: \"focus_areas must be an array\" };\n }\n for (const area of focus_areas) {\n if (!FOCUS_AREAS.includes(area)) {\n return {\n valid: false,\n error: `Invalid focus area: ${area}. Supported: ${FOCUS_AREAS.join(\", \")}`,\n };\n }\n }\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { code } = input as CodeReviewInput;\n const useLLM = !!process.env.OPENAI_API_KEY;\n\n if (!code) return 2000;\n\n if (useLLM) {\n // LLM review takes longer\n return Math.min(30000, 2000 + code.length / 20);\n }\n\n // Pattern-based is fast\n return Math.min(5000, 500 + code.length / 100);\n },\n};\n\n/**\n * Code Review skill JSON schemas\n */\nexport const codeReviewInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n code: {\n type: \"string\",\n description: \"Source code to review\",\n maxLength: 100000,\n },\n language: {\n type: \"string\",\n description: \"Programming language (auto-detected if not provided)\",\n },\n context: {\n type: \"string\",\n description: \"Additional context about the code\",\n },\n focus_areas: {\n type: \"array\",\n items: { type: \"string\", enum: FOCUS_AREAS },\n description: \"Specific areas to focus on\",\n },\n diff_only: {\n type: \"boolean\",\n default: false,\n description: \"Only review changed lines\",\n },\n },\n required: [\"code\"],\n};\n\nexport const codeReviewOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n summary: { type: \"string\" },\n overall_score: { type: \"number\", minimum: 0, maximum: 100 },\n issues: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n severity: { type: \"string\", enum: [\"critical\", \"warning\", \"info\", \"suggestion\"] },\n line: { type: \"integer\" },\n column: { type: \"integer\" },\n message: { type: \"string\" },\n category: { type: \"string\" },\n suggestion: { type: \"string\" },\n code_snippet: { type: \"string\" },\n },\n required: [\"severity\", \"message\", \"category\"],\n },\n },\n suggestions: { type: \"array\", items: { type: \"string\" } },\n metrics: {\n type: \"object\",\n properties: {\n lines_of_code: { type: \"integer\" },\n complexity: { type: \"string\" },\n maintainability: { type: \"string\" },\n },\n },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"llm\"] },\n language_detected: { type: \"string\" },\n issue_count: {\n type: \"object\",\n properties: {\n critical: { type: \"integer\" },\n warning: { type: \"integer\" },\n info: { type: \"integer\" },\n suggestion: { type: \"integer\" },\n },\n },\n },\n required: [\"summary\", \"overall_score\", \"issues\", \"suggestions\", \"metrics\", \"processing_time_ms\", \"mode\"],\n};\n\nexport type { CodeReviewInput, CodeReviewOutput };\n","export * from \"./types.js\";\n\n// Echo skill - simple testing/reference\nexport { echoSkillHandler, echoInputSchema, echoOutputSchema } from \"./echo.js\";\n\n// Translation skill - translates text between languages\nexport {\n translationSkillHandler,\n translationInputSchema,\n translationOutputSchema,\n} from \"./translation.js\";\n\n// Summarization skill - summarizes text content\nexport {\n summarizationSkillHandler,\n summarizationInputSchema,\n summarizationOutputSchema,\n} from \"./summarization.js\";\n\n// Sentiment Analysis skill - analyzes text sentiment\nexport {\n sentimentSkillHandler,\n sentimentInputSchema,\n sentimentOutputSchema,\n} from \"./sentiment.js\";\n\n// Image Generation skill - generates images from prompts\nexport {\n imageGenerationSkillHandler,\n imageGenInputSchema,\n imageGenOutputSchema,\n type ImageGenInput,\n type ImageGenOutput,\n} from \"./image-generation.js\";\n\n// Code Review skill - analyzes code for issues\nexport {\n codeReviewSkillHandler,\n codeReviewInputSchema,\n codeReviewOutputSchema,\n type CodeReviewInput,\n type CodeReviewOutput,\n} from \"./code-review.js\";\n\n// Convenience: All handlers in one array\nimport { echoSkillHandler } from \"./echo.js\";\nimport { translationSkillHandler } from \"./translation.js\";\nimport { summarizationSkillHandler } from \"./summarization.js\";\nimport { sentimentSkillHandler } from \"./sentiment.js\";\nimport { imageGenerationSkillHandler } from \"./image-generation.js\";\nimport { codeReviewSkillHandler } from \"./code-review.js\";\n\nexport const allSkillHandlers = [\n echoSkillHandler,\n translationSkillHandler,\n summarizationSkillHandler,\n sentimentSkillHandler,\n imageGenerationSkillHandler,\n codeReviewSkillHandler,\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 // Private key for on-chain transactions (optional)\n privateKey?: 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.CLANK_API_URL;\n const apiKey = process.env.CLANK_API_KEY;\n const agentId = process.env.CLANK_AGENT_ID;\n\n if (!apiUrl) {\n throw new Error(\"CLANK_API_URL is required\");\n }\n if (!apiKey) {\n throw new Error(\"CLANK_API_KEY is required\");\n }\n if (!agentId) {\n throw new Error(\"CLANK_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.CLANK_NETWORK as Network) ?? \"testnet\",\n rpcUrl: process.env.SUI_RPC_URL,\n packageId: process.env.CLANK_PACKAGE_ID,\n privateKey: process.env.CLANK_PRIVATE_KEY,\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"]}
|
|
1
|
+
{"version":3,"sources":["../src/state.ts","../src/cli.ts","../src/agent.ts","../src/skills/types.ts","../src/skills/echo.ts","../src/skills/translation.ts","../src/skills/summarization.ts","../src/skills/sentiment.ts","../src/skills/image-generation.ts","../src/skills/code-review.ts","../src/skills/index.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\";\nimport { allSkillHandlers } from \"./skills/index.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 // Register all skill handlers\n for (const handler of allSkillHandlers) {\n agent.registerSkillHandler(handler);\n }\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(` CLANK_API_URL API server URL`);\n console.log(` CLANK_API_KEY API authentication key`);\n console.log(` CLANK_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(` CLANK_NETWORK Network (testnet, mainnet) [default: testnet]`);\n console.log(` CLANK_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(`CLANK_API_URL=http://localhost:3000\nCLANK_API_KEY=ck_your_api_key\nCLANK_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(`CLANK_API_URL=http://localhost:3000\nCLANK_API_KEY=ck_your_api_key\nCLANK_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(`CLANK_API_URL=http://localhost:3000\nCLANK_API_KEY=ck_your_api_key\nCLANK_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 { Ed25519Keypair } from \"@mysten/sui/keypairs/ed25519\";\nimport { SuiClient } from \"@mysten/sui/client\";\nimport { Transaction } from \"@mysten/sui/transactions\";\nimport { decodeSuiPrivateKey } from \"@mysten/sui/cryptography\";\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 // On-chain transaction capabilities\n private keypair?: Ed25519Keypair;\n private suiClient?: SuiClient;\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 // Initialize on-chain transaction capabilities if private key provided\n if (config.privateKey) {\n try {\n const { secretKey } = decodeSuiPrivateKey(config.privateKey);\n this.keypair = Ed25519Keypair.fromSecretKey(secretKey);\n \n const rpcUrl = config.rpcUrl || (config.network === \"mainnet\" \n ? \"https://fullnode.mainnet.sui.io:443\"\n : \"https://fullnode.testnet.sui.io:443\");\n this.suiClient = new SuiClient({ url: rpcUrl });\n \n console.log(` š On-chain signing enabled: ${this.keypair.toSuiAddress().slice(0, 15)}...`);\n } catch (error) {\n console.error(` ā ļø Failed to load private key: ${error}`);\n }\n }\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 ALL our skills\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let allTasks: any[] = [];\n \n for (const skillId of skillIds) {\n const result = await this.client.api.listTasks({\n status: STATUS.POSTED,\n skillId: skillId,\n limit: 10,\n });\n allTasks = [...allTasks, ...result.data];\n }\n \n // Deduplicate by task ID\n const seen = new Set<string>();\n const tasks = allTasks.filter((t) => {\n if (seen.has(t.id)) return false;\n seen.add(t.id);\n return true;\n });\n \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 on-chain if we have signing capability\n if (this.keypair && this.suiClient && this.config.packageId) {\n try {\n // First accept on-chain, then submit\n console.log(` Accepting on-chain...`);\n await this.acceptTaskOnChain(task.taskId);\n console.log(` Submitting on-chain...`);\n await this.submitTaskOnChain(task.taskId, storedOutput.blobId);\n console.log(` ā
Task submitted on-chain: ${task.taskId.slice(0, 16)}`);\n } catch (error) {\n console.error(` ā On-chain transaction failed: ${error}`);\n // Still mark as completed locally for retry later\n }\n } else {\n console.log(` ā
Task completed (no on-chain key): ${task.taskId.slice(0, 16)}`);\n }\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 * Accept task on-chain (moves from POSTED to IN_PROGRESS)\n */\n private async acceptTaskOnChain(taskId: string): Promise<void> {\n if (!this.keypair || !this.suiClient || !this.config.packageId) {\n throw new Error(\"On-chain signing not configured\");\n }\n \n const tx = new Transaction();\n tx.setGasBudget(10_000_000); // 0.01 SUI gas\n \n // Create zero-value coin for bond (our skills require 0 bond)\n const [zeroCoin] = tx.splitCoins(tx.gas, [0]);\n \n // Call task::accept(task, worker, bond, clock, ctx)\n tx.moveCall({\n target: `${this.config.packageId}::task::accept`,\n arguments: [\n tx.object(taskId),\n tx.object(this.config.agentId),\n zeroCoin,\n tx.object(\"0x6\"), // Clock\n ],\n });\n \n const result = await this.suiClient.signAndExecuteTransaction({\n transaction: tx,\n signer: this.keypair,\n options: { showEffects: true },\n });\n \n if (result.effects?.status?.status !== \"success\") {\n throw new Error(`Accept failed: ${result.effects?.status?.error || \"unknown\"}`);\n }\n \n console.log(` Accept Tx: ${result.digest.slice(0, 15)}...`);\n }\n \n /**\n * Submit task output on-chain\n */\n private async submitTaskOnChain(taskId: string, outputRef: string): Promise<void> {\n if (!this.keypair || !this.suiClient || !this.config.packageId) {\n throw new Error(\"On-chain signing not configured\");\n }\n \n // Generate output hash from the output ref\n const outputHash = outputRef; // Use blob ID as hash for simplicity\n \n const tx = new Transaction();\n tx.setGasBudget(10_000_000); // 0.01 SUI gas\n \n // Call task::submit(task, worker, output_ref, output_hash, clock)\n tx.moveCall({\n target: `${this.config.packageId}::task::submit`,\n arguments: [\n tx.object(taskId),\n tx.object(this.config.agentId),\n tx.pure.string(outputRef),\n tx.pure.string(outputHash),\n tx.object(\"0x6\"), // Clock\n ],\n });\n \n const result = await this.suiClient.signAndExecuteTransaction({\n transaction: tx,\n signer: this.keypair,\n options: { showEffects: true },\n });\n \n if (result.effects?.status?.status !== \"success\") {\n throw new Error(`Transaction failed: ${result.effects?.status?.error || \"unknown\"}`);\n }\n \n console.log(` Tx: ${result.digest.slice(0, 15)}...`);\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 type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Translation skill handler - translates text between languages\n *\n * Supports two modes:\n * 1. Mock mode (default): Uses simple word replacement for testing\n * 2. LLM mode: Uses OpenAI API for real translations (requires OPENAI_API_KEY)\n */\n\n// Language codes we support\nconst SUPPORTED_LANGUAGES = [\n \"en\", // English\n \"es\", // Spanish\n \"fr\", // French\n \"de\", // German\n \"it\", // Italian\n \"pt\", // Portuguese\n \"ja\", // Japanese\n \"zh\", // Chinese\n \"ko\", // Korean\n \"ar\", // Arabic\n] as const;\n\ntype LanguageCode = (typeof SUPPORTED_LANGUAGES)[number];\n\ninterface TranslationInput {\n text: string;\n source_language?: LanguageCode;\n target_language: LanguageCode;\n}\n\ninterface TranslationOutput {\n translated_text: string;\n source_language: string;\n target_language: string;\n confidence: number;\n word_count: number;\n processing_time_ms: number;\n mode: \"mock\" | \"llm\";\n}\n\n/**\n * Mock translation - for testing without API keys\n * Simply adds language prefix and reverses words for demo\n */\nfunction mockTranslate(text: string, targetLang: LanguageCode): string {\n const prefixes: Record<LanguageCode, string> = {\n en: \"[EN]\",\n es: \"[ES]\",\n fr: \"[FR]\",\n de: \"[DE]\",\n it: \"[IT]\",\n pt: \"[PT]\",\n ja: \"[JA]\",\n zh: \"[ZH]\",\n ko: \"[KO]\",\n ar: \"[AR]\",\n };\n\n // Simple mock: add prefix and keep text (in real usage, this would be actual translation)\n return `${prefixes[targetLang]} ${text}`;\n}\n\n/**\n * LLM-based translation using OpenAI\n */\nasync function llmTranslate(\n text: string,\n sourceLang: string,\n targetLang: LanguageCode\n): Promise<string> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const languageNames: Record<LanguageCode, string> = {\n en: \"English\",\n es: \"Spanish\",\n fr: \"French\",\n de: \"German\",\n it: \"Italian\",\n pt: \"Portuguese\",\n ja: \"Japanese\",\n zh: \"Chinese\",\n ko: \"Korean\",\n ar: \"Arabic\",\n };\n\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"gpt-4o-mini\",\n messages: [\n {\n role: \"system\",\n content: `You are a professional translator. Translate the following text from ${sourceLang} to ${languageNames[targetLang]}. Only output the translated text, nothing else.`,\n },\n {\n role: \"user\",\n content: text,\n },\n ],\n temperature: 0.3,\n max_tokens: 2048,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${error}`);\n }\n\n const data = await response.json();\n return data.choices[0].message.content.trim();\n}\n\nexport const translationSkillHandler: SkillHandler = {\n name: \"translation\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, skillVersion: string): boolean {\n const name = skillName.toLowerCase();\n return (\n name.includes(\"translat\") ||\n name.includes(\"translate\") ||\n name === \"translation\"\n );\n },\n\n async execute(\n input: object,\n context?: SkillContext\n ): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const { text, source_language, target_language } =\n input as TranslationInput;\n\n // Validate input\n if (!text || typeof text !== \"string\") {\n return {\n success: false,\n error: \"Missing or invalid 'text' field\",\n };\n }\n\n if (!target_language || !SUPPORTED_LANGUAGES.includes(target_language)) {\n return {\n success: false,\n error: `Invalid target_language. Supported: ${SUPPORTED_LANGUAGES.join(\", \")}`,\n };\n }\n\n // Detect source language if not provided (default to English)\n const sourceLang = source_language || \"en\";\n\n // Choose translation mode\n const useLLM = !!process.env.OPENAI_API_KEY;\n let translatedText: string;\n\n if (useLLM) {\n translatedText = await llmTranslate(text, sourceLang, target_language);\n } else {\n // Mock mode for testing\n translatedText = mockTranslate(text, target_language);\n }\n\n const output: TranslationOutput = {\n translated_text: translatedText,\n source_language: sourceLang,\n target_language,\n confidence: useLLM ? 0.95 : 0.5, // Mock has low confidence\n word_count: text.split(/\\s+/).length,\n processing_time_ms: Date.now() - startTime,\n mode: useLLM ? \"llm\" : \"mock\",\n };\n\n return {\n success: true,\n output,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Translation failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { text, target_language } = input as TranslationInput;\n\n if (!text || typeof text !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'text' field\" };\n }\n\n if (text.length > 10000) {\n return { valid: false, error: \"Text too long (max 10000 characters)\" };\n }\n\n if (!target_language) {\n return { valid: false, error: \"Missing 'target_language' field\" };\n }\n\n if (!SUPPORTED_LANGUAGES.includes(target_language as LanguageCode)) {\n return {\n valid: false,\n error: `Unsupported target_language. Use: ${SUPPORTED_LANGUAGES.join(\", \")}`,\n };\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { text } = input as TranslationInput;\n const wordCount = text?.split(/\\s+/).length || 0;\n // Estimate ~50ms per word for LLM, ~10ms per word for mock\n const useLLM = !!process.env.OPENAI_API_KEY;\n return useLLM ? wordCount * 50 + 1000 : wordCount * 10 + 100;\n },\n};\n\n/**\n * Translation skill JSON schemas\n */\nexport const translationInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n text: {\n type: \"string\",\n description: \"Text to translate\",\n maxLength: 10000,\n },\n source_language: {\n type: \"string\",\n enum: SUPPORTED_LANGUAGES,\n description: \"Source language code (auto-detected if not provided)\",\n },\n target_language: {\n type: \"string\",\n enum: SUPPORTED_LANGUAGES,\n description: \"Target language code\",\n },\n },\n required: [\"text\", \"target_language\"],\n};\n\nexport const translationOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n translated_text: { type: \"string\" },\n source_language: { type: \"string\" },\n target_language: { type: \"string\" },\n confidence: { type: \"number\", minimum: 0, maximum: 1 },\n word_count: { type: \"integer\" },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"llm\"] },\n },\n required: [\n \"translated_text\",\n \"source_language\",\n \"target_language\",\n \"confidence\",\n \"word_count\",\n \"processing_time_ms\",\n \"mode\",\n ],\n};\n","import type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Summarization skill handler - summarizes text content\n *\n * Supports two modes:\n * 1. Mock mode (default): Uses extractive summarization (first sentences)\n * 2. LLM mode: Uses OpenAI API for abstractive summarization\n */\n\ntype SummaryLength = \"short\" | \"medium\" | \"long\";\n\ninterface SummarizationInput {\n text: string;\n length?: SummaryLength;\n max_sentences?: number;\n style?: \"bullet\" | \"paragraph\";\n}\n\ninterface SummarizationOutput {\n summary: string;\n original_length: number;\n summary_length: number;\n compression_ratio: number;\n sentence_count: number;\n processing_time_ms: number;\n mode: \"mock\" | \"llm\";\n}\n\n/**\n * Extract first N sentences as mock summary\n */\nfunction mockSummarize(text: string, maxSentences: number): string {\n // Split into sentences (simple approach)\n const sentences = text\n .split(/(?<=[.!?])\\s+/)\n .filter((s) => s.trim().length > 0);\n\n const selectedSentences = sentences.slice(0, maxSentences);\n return selectedSentences.join(\" \");\n}\n\n/**\n * LLM-based summarization using OpenAI\n */\nasync function llmSummarize(\n text: string,\n length: SummaryLength,\n style: \"bullet\" | \"paragraph\"\n): Promise<string> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const lengthInstructions: Record<SummaryLength, string> = {\n short: \"Provide a very brief summary in 1-2 sentences.\",\n medium: \"Provide a concise summary in 3-5 sentences.\",\n long: \"Provide a comprehensive summary covering all main points.\",\n };\n\n const styleInstructions = {\n bullet: \"Format as bullet points.\",\n paragraph: \"Format as flowing prose.\",\n };\n\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"gpt-4o-mini\",\n messages: [\n {\n role: \"system\",\n content: `You are a professional summarizer. ${lengthInstructions[length]} ${styleInstructions[style]} Only output the summary, nothing else.`,\n },\n {\n role: \"user\",\n content: `Summarize this text:\\n\\n${text}`,\n },\n ],\n temperature: 0.3,\n max_tokens: 1024,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${error}`);\n }\n\n const data = await response.json();\n return data.choices[0].message.content.trim();\n}\n\nexport const summarizationSkillHandler: SkillHandler = {\n name: \"summarization\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, skillVersion: string): boolean {\n const name = skillName.toLowerCase();\n return (\n name.includes(\"summar\") ||\n name.includes(\"digest\") ||\n name.includes(\"tldr\") ||\n name === \"summarize\"\n );\n },\n\n async execute(\n input: object,\n context?: SkillContext\n ): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const {\n text,\n length = \"medium\",\n max_sentences,\n style = \"paragraph\",\n } = input as SummarizationInput;\n\n // Validate input\n if (!text || typeof text !== \"string\") {\n return {\n success: false,\n error: \"Missing or invalid 'text' field\",\n };\n }\n\n // Choose summarization mode\n const useLLM = !!process.env.OPENAI_API_KEY;\n let summary: string;\n\n if (useLLM) {\n summary = await llmSummarize(text, length, style);\n } else {\n // Mock mode - extract first sentences based on length\n const sentenceCounts: Record<SummaryLength, number> = {\n short: 2,\n medium: 4,\n long: 8,\n };\n const numSentences = max_sentences || sentenceCounts[length];\n summary = mockSummarize(text, numSentences);\n }\n\n const output: SummarizationOutput = {\n summary,\n original_length: text.length,\n summary_length: summary.length,\n compression_ratio:\n Math.round((1 - summary.length / text.length) * 100) / 100,\n sentence_count: summary.split(/(?<=[.!?])\\s+/).length,\n processing_time_ms: Date.now() - startTime,\n mode: useLLM ? \"llm\" : \"mock\",\n };\n\n return {\n success: true,\n output,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Summarization failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { text, length, style } = input as SummarizationInput;\n\n if (!text || typeof text !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'text' field\" };\n }\n\n if (text.length < 50) {\n return { valid: false, error: \"Text too short (min 50 characters)\" };\n }\n\n if (text.length > 50000) {\n return { valid: false, error: \"Text too long (max 50000 characters)\" };\n }\n\n if (length && ![\"short\", \"medium\", \"long\"].includes(length)) {\n return { valid: false, error: \"Invalid length. Use: short, medium, long\" };\n }\n\n if (style && ![\"bullet\", \"paragraph\"].includes(style)) {\n return { valid: false, error: \"Invalid style. Use: bullet, paragraph\" };\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { text } = input as SummarizationInput;\n const charCount = text?.length || 0;\n // Estimate ~1ms per 10 chars for LLM, ~0.1ms per 10 chars for mock\n const useLLM = !!process.env.OPENAI_API_KEY;\n return useLLM ? charCount / 10 + 2000 : charCount / 100 + 100;\n },\n};\n\n/**\n * Summarization skill JSON schemas\n */\nexport const summarizationInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n text: {\n type: \"string\",\n description: \"Text to summarize\",\n minLength: 50,\n maxLength: 50000,\n },\n length: {\n type: \"string\",\n enum: [\"short\", \"medium\", \"long\"],\n description: \"Desired summary length\",\n default: \"medium\",\n },\n max_sentences: {\n type: \"integer\",\n minimum: 1,\n maximum: 20,\n description: \"Maximum number of sentences (overrides length)\",\n },\n style: {\n type: \"string\",\n enum: [\"bullet\", \"paragraph\"],\n description: \"Output format style\",\n default: \"paragraph\",\n },\n },\n required: [\"text\"],\n};\n\nexport const summarizationOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n summary: { type: \"string\" },\n original_length: { type: \"integer\" },\n summary_length: { type: \"integer\" },\n compression_ratio: { type: \"number\", minimum: 0, maximum: 1 },\n sentence_count: { type: \"integer\" },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"llm\"] },\n },\n required: [\n \"summary\",\n \"original_length\",\n \"summary_length\",\n \"compression_ratio\",\n \"sentence_count\",\n \"processing_time_ms\",\n \"mode\",\n ],\n};\n","import type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Sentiment Analysis skill handler - analyzes text sentiment\n *\n * Supports two modes:\n * 1. Mock mode (default): Uses simple keyword matching\n * 2. LLM mode: Uses OpenAI API for nuanced analysis\n */\n\ntype SentimentLabel = \"positive\" | \"negative\" | \"neutral\" | \"mixed\";\n\ninterface SentimentInput {\n text: string;\n detailed?: boolean;\n}\n\ninterface SentimentOutput {\n sentiment: SentimentLabel;\n confidence: number;\n scores: {\n positive: number;\n negative: number;\n neutral: number;\n };\n keywords?: string[];\n explanation?: string;\n processing_time_ms: number;\n mode: \"mock\" | \"llm\";\n}\n\n// Simple keyword lists for mock mode\nconst POSITIVE_WORDS = new Set([\n \"good\",\n \"great\",\n \"excellent\",\n \"amazing\",\n \"wonderful\",\n \"fantastic\",\n \"love\",\n \"happy\",\n \"best\",\n \"awesome\",\n \"beautiful\",\n \"perfect\",\n \"brilliant\",\n \"superb\",\n \"outstanding\",\n \"pleased\",\n \"delighted\",\n \"enjoy\",\n \"like\",\n \"nice\",\n \"thanks\",\n \"thank\",\n \"helpful\",\n \"recommend\",\n \"satisfied\",\n]);\n\nconst NEGATIVE_WORDS = new Set([\n \"bad\",\n \"terrible\",\n \"awful\",\n \"horrible\",\n \"poor\",\n \"worst\",\n \"hate\",\n \"sad\",\n \"angry\",\n \"disappointing\",\n \"disappointed\",\n \"ugly\",\n \"fail\",\n \"failed\",\n \"broken\",\n \"useless\",\n \"waste\",\n \"problem\",\n \"issue\",\n \"bug\",\n \"error\",\n \"wrong\",\n \"sucks\",\n \"annoying\",\n \"frustrated\",\n]);\n\n/**\n * Mock sentiment analysis using keyword matching\n */\nfunction mockSentimentAnalysis(text: string): {\n sentiment: SentimentLabel;\n scores: { positive: number; negative: number; neutral: number };\n keywords: string[];\n} {\n const words = text.toLowerCase().split(/\\W+/);\n const positiveMatches: string[] = [];\n const negativeMatches: string[] = [];\n\n for (const word of words) {\n if (POSITIVE_WORDS.has(word)) positiveMatches.push(word);\n if (NEGATIVE_WORDS.has(word)) negativeMatches.push(word);\n }\n\n const total = words.length || 1;\n const positiveScore = positiveMatches.length / total;\n const negativeScore = negativeMatches.length / total;\n const neutralScore = 1 - positiveScore - negativeScore;\n\n let sentiment: SentimentLabel;\n if (positiveScore > negativeScore * 2) {\n sentiment = \"positive\";\n } else if (negativeScore > positiveScore * 2) {\n sentiment = \"negative\";\n } else if (positiveScore > 0 && negativeScore > 0) {\n sentiment = \"mixed\";\n } else {\n sentiment = \"neutral\";\n }\n\n return {\n sentiment,\n scores: {\n positive: Math.round(positiveScore * 100) / 100,\n negative: Math.round(negativeScore * 100) / 100,\n neutral: Math.round(neutralScore * 100) / 100,\n },\n keywords: [...positiveMatches, ...negativeMatches],\n };\n}\n\n/**\n * LLM-based sentiment analysis using OpenAI\n */\nasync function llmSentimentAnalysis(\n text: string,\n detailed: boolean\n): Promise<{\n sentiment: SentimentLabel;\n scores: { positive: number; negative: number; neutral: number };\n keywords: string[];\n explanation: string;\n}> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"gpt-4o-mini\",\n messages: [\n {\n role: \"system\",\n content: `You are a sentiment analysis expert. Analyze the sentiment of the given text and respond in JSON format with the following structure:\n{\n \"sentiment\": \"positive\" | \"negative\" | \"neutral\" | \"mixed\",\n \"scores\": { \"positive\": 0.0-1.0, \"negative\": 0.0-1.0, \"neutral\": 0.0-1.0 },\n \"keywords\": [\"list\", \"of\", \"sentiment\", \"keywords\"],\n \"explanation\": \"Brief explanation of the sentiment\"\n}\nOnly output valid JSON, nothing else.`,\n },\n {\n role: \"user\",\n content: text,\n },\n ],\n temperature: 0.1,\n max_tokens: 512,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${error}`);\n }\n\n const data = await response.json();\n const content = data.choices[0].message.content.trim();\n\n try {\n return JSON.parse(content);\n } catch {\n // Fallback if JSON parsing fails\n return {\n sentiment: \"neutral\",\n scores: { positive: 0.33, negative: 0.33, neutral: 0.34 },\n keywords: [],\n explanation: \"Failed to parse LLM response\",\n };\n }\n}\n\nexport const sentimentSkillHandler: SkillHandler = {\n name: \"sentiment\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, skillVersion: string): boolean {\n const name = skillName.toLowerCase();\n return (\n name.includes(\"sentiment\") ||\n name.includes(\"emotion\") ||\n name.includes(\"mood\") ||\n name.includes(\"opinion\")\n );\n },\n\n async execute(\n input: object,\n context?: SkillContext\n ): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const { text, detailed = false } = input as SentimentInput;\n\n // Validate input\n if (!text || typeof text !== \"string\") {\n return {\n success: false,\n error: \"Missing or invalid 'text' field\",\n };\n }\n\n // Choose analysis mode\n const useLLM = !!process.env.OPENAI_API_KEY;\n let result: {\n sentiment: SentimentLabel;\n scores: { positive: number; negative: number; neutral: number };\n keywords: string[];\n explanation?: string;\n };\n\n if (useLLM) {\n result = await llmSentimentAnalysis(text, detailed);\n } else {\n result = mockSentimentAnalysis(text);\n }\n\n // Calculate confidence based on score difference\n const maxScore = Math.max(\n result.scores.positive,\n result.scores.negative,\n result.scores.neutral\n );\n const confidence = useLLM ? Math.min(0.95, maxScore + 0.3) : maxScore;\n\n const output: SentimentOutput = {\n sentiment: result.sentiment,\n confidence: Math.round(confidence * 100) / 100,\n scores: result.scores,\n keywords: detailed ? result.keywords : undefined,\n explanation: detailed ? result.explanation : undefined,\n processing_time_ms: Date.now() - startTime,\n mode: useLLM ? \"llm\" : \"mock\",\n };\n\n return {\n success: true,\n output,\n };\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error ? error.message : \"Sentiment analysis failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { text } = input as SentimentInput;\n\n if (!text || typeof text !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'text' field\" };\n }\n\n if (text.length < 5) {\n return { valid: false, error: \"Text too short (min 5 characters)\" };\n }\n\n if (text.length > 10000) {\n return { valid: false, error: \"Text too long (max 10000 characters)\" };\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { text } = input as SentimentInput;\n const charCount = text?.length || 0;\n const useLLM = !!process.env.OPENAI_API_KEY;\n return useLLM ? charCount / 20 + 1000 : charCount / 100 + 50;\n },\n};\n\n/**\n * Sentiment Analysis skill JSON schemas\n */\nexport const sentimentInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n text: {\n type: \"string\",\n description: \"Text to analyze\",\n minLength: 5,\n maxLength: 10000,\n },\n detailed: {\n type: \"boolean\",\n description: \"Include keywords and explanation\",\n default: false,\n },\n },\n required: [\"text\"],\n};\n\nexport const sentimentOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n sentiment: {\n type: \"string\",\n enum: [\"positive\", \"negative\", \"neutral\", \"mixed\"],\n },\n confidence: { type: \"number\", minimum: 0, maximum: 1 },\n scores: {\n type: \"object\",\n properties: {\n positive: { type: \"number\", minimum: 0, maximum: 1 },\n negative: { type: \"number\", minimum: 0, maximum: 1 },\n neutral: { type: \"number\", minimum: 0, maximum: 1 },\n },\n required: [\"positive\", \"negative\", \"neutral\"],\n },\n keywords: { type: \"array\", items: { type: \"string\" } },\n explanation: { type: \"string\" },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"llm\"] },\n },\n required: [\"sentiment\", \"confidence\", \"scores\", \"processing_time_ms\", \"mode\"],\n};\n","import type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Image Generation Skill Handler\n *\n * Generates images from text prompts using AI models.\n * Supports two modes:\n * 1. Mock mode (default): Returns placeholder images from picsum.photos\n * 2. LLM mode: Uses OpenAI DALL-E API (requires OPENAI_API_KEY)\n */\n\nconst SUPPORTED_STYLES = [\n \"photorealistic\",\n \"digital-art\",\n \"anime\",\n \"oil-painting\",\n \"watercolor\",\n \"sketch\",\n] as const;\n\ntype ImageStyle = (typeof SUPPORTED_STYLES)[number];\n\ninterface ImageGenInput {\n prompt: string;\n negative_prompt?: string;\n style?: ImageStyle;\n width?: number;\n height?: number;\n num_images?: number;\n seed?: number;\n}\n\ninterface GeneratedImage {\n url: string;\n width: number;\n height: number;\n}\n\ninterface ImageGenOutput {\n images: GeneratedImage[];\n prompt: string;\n revised_prompt?: string;\n processing_time_ms: number;\n mode: \"mock\" | \"dalle\";\n model: string;\n seed?: number;\n}\n\n/**\n * Mock image generation - for testing without API keys\n * Returns placeholder images from picsum.photos\n */\nfunction mockGenerateImages(\n prompt: string,\n width: number,\n height: number,\n numImages: number,\n seed?: number\n): GeneratedImage[] {\n return Array.from({ length: numImages }, (_, i) => ({\n url: `https://picsum.photos/seed/${seed ?? Date.now() + i}/${width}/${height}`,\n width,\n height,\n }));\n}\n\n/**\n * DALL-E based image generation\n */\nasync function dalleGenerateImages(\n prompt: string,\n numImages: number,\n size: \"1024x1024\" | \"1792x1024\" | \"1024x1792\"\n): Promise<{ images: GeneratedImage[]; revised_prompt?: string }> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const response = await fetch(\"https://api.openai.com/v1/images/generations\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"dall-e-3\",\n prompt,\n n: numImages,\n size,\n quality: \"standard\",\n response_format: \"url\",\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`DALL-E API error: ${error}`);\n }\n\n const data = await response.json();\n const [width, height] = size.split(\"x\").map(Number);\n\n return {\n images: data.data.map((item: { url: string }) => ({\n url: item.url,\n width,\n height,\n })),\n revised_prompt: data.data[0]?.revised_prompt,\n };\n}\n\nexport const imageGenerationSkillHandler: SkillHandler = {\n name: \"image-generation\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, _skillVersion: string): boolean {\n const normalized = skillName.toLowerCase().replace(/[-_\\s]/g, \"\");\n return (\n normalized === \"imagegeneration\" ||\n normalized === \"imagegen\" ||\n normalized === \"texttoimage\" ||\n normalized === \"dalle\" ||\n normalized === \"stablediffusion\"\n );\n },\n\n async execute(input: object, context?: SkillContext): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const {\n prompt,\n style,\n width = 1024,\n height = 1024,\n num_images = 1,\n seed,\n } = input as ImageGenInput;\n\n // Validate input\n if (!prompt || typeof prompt !== \"string\") {\n return { success: false, error: \"Missing or invalid 'prompt' field\" };\n }\n\n if (prompt.length > 4000) {\n return { success: false, error: \"Prompt too long (max 4000 characters)\" };\n }\n\n if (width < 256 || width > 2048) {\n return { success: false, error: \"Width must be between 256 and 2048\" };\n }\n\n if (height < 256 || height > 2048) {\n return { success: false, error: \"Height must be between 256 and 2048\" };\n }\n\n if (num_images < 1 || num_images > 4) {\n return { success: false, error: \"num_images must be between 1 and 4\" };\n }\n\n // Build enhanced prompt with style\n const enhancedPrompt = style\n ? `${prompt}, ${style} style, high quality, detailed`\n : `${prompt}, high quality, detailed`;\n\n // Choose generation mode\n const useDalle = !!process.env.OPENAI_API_KEY;\n let images: GeneratedImage[];\n let revisedPrompt: string | undefined;\n\n if (useDalle) {\n // Map dimensions to DALL-E sizes\n const dalleSize =\n width > height\n ? \"1792x1024\"\n : height > width\n ? \"1024x1792\"\n : \"1024x1024\";\n\n const result = await dalleGenerateImages(enhancedPrompt, num_images, dalleSize as \"1024x1024\" | \"1792x1024\" | \"1024x1792\");\n images = result.images;\n revisedPrompt = result.revised_prompt;\n } else {\n // Mock mode for testing\n images = mockGenerateImages(prompt, width, height, num_images, seed);\n revisedPrompt = enhancedPrompt;\n }\n\n const output: ImageGenOutput = {\n images,\n prompt,\n revised_prompt: revisedPrompt,\n processing_time_ms: Date.now() - startTime,\n mode: useDalle ? \"dalle\" : \"mock\",\n model: useDalle ? \"dall-e-3\" : \"mock-diffusion-v1\",\n seed: seed ?? Math.floor(Math.random() * 1000000),\n };\n\n return { success: true, output };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Image generation failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { prompt, width, height, num_images, style } = input as ImageGenInput;\n\n if (!prompt || typeof prompt !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'prompt' field\" };\n }\n\n if (prompt.length === 0) {\n return { valid: false, error: \"Prompt cannot be empty\" };\n }\n\n if (prompt.length > 4000) {\n return { valid: false, error: \"Prompt too long (max 4000 characters)\" };\n }\n\n if (width !== undefined && (width < 256 || width > 2048)) {\n return { valid: false, error: \"Width must be between 256 and 2048\" };\n }\n\n if (height !== undefined && (height < 256 || height > 2048)) {\n return { valid: false, error: \"Height must be between 256 and 2048\" };\n }\n\n if (num_images !== undefined && (num_images < 1 || num_images > 4)) {\n return { valid: false, error: \"num_images must be between 1 and 4\" };\n }\n\n if (style !== undefined && !SUPPORTED_STYLES.includes(style)) {\n return {\n valid: false,\n error: `Invalid style. Supported: ${SUPPORTED_STYLES.join(\", \")}`,\n };\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { width = 1024, height = 1024, num_images = 1 } = input as ImageGenInput;\n const useDalle = !!process.env.OPENAI_API_KEY;\n\n if (useDalle) {\n // DALL-E typically takes 10-20 seconds per image\n return num_images * 15000;\n }\n\n // Mock mode is fast\n const resolutionFactor = (width * height) / (1024 * 1024);\n return Math.ceil(500 * resolutionFactor * num_images);\n },\n};\n\n/**\n * Image Generation skill JSON schemas\n */\nexport const imageGenInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n prompt: {\n type: \"string\",\n description: \"Text prompt describing the image to generate\",\n maxLength: 4000,\n },\n negative_prompt: {\n type: \"string\",\n description: \"What to avoid in the image\",\n },\n style: {\n type: \"string\",\n enum: SUPPORTED_STYLES,\n description: \"Art style for the image\",\n },\n width: {\n type: \"integer\",\n minimum: 256,\n maximum: 2048,\n default: 1024,\n description: \"Image width in pixels\",\n },\n height: {\n type: \"integer\",\n minimum: 256,\n maximum: 2048,\n default: 1024,\n description: \"Image height in pixels\",\n },\n num_images: {\n type: \"integer\",\n minimum: 1,\n maximum: 4,\n default: 1,\n description: \"Number of images to generate\",\n },\n seed: {\n type: \"integer\",\n description: \"Random seed for reproducibility\",\n },\n },\n required: [\"prompt\"],\n};\n\nexport const imageGenOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n images: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n url: { type: \"string\", format: \"uri\" },\n width: { type: \"integer\" },\n height: { type: \"integer\" },\n },\n required: [\"url\", \"width\", \"height\"],\n },\n },\n prompt: { type: \"string\" },\n revised_prompt: { type: \"string\" },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"dalle\"] },\n model: { type: \"string\" },\n seed: { type: \"integer\" },\n },\n required: [\"images\", \"prompt\", \"processing_time_ms\", \"mode\", \"model\"],\n};\n\nexport type { ImageGenInput, ImageGenOutput };\n","import type { SkillHandler, SkillResult, SkillContext } from \"./types.js\";\n\n/**\n * Code Review Skill Handler\n *\n * Analyzes code for issues, best practices, and improvements.\n * Supports two modes:\n * 1. Mock mode (default): Uses pattern-based static analysis\n * 2. LLM mode: Uses OpenAI API for intelligent code review (requires OPENAI_API_KEY)\n */\n\nconst FOCUS_AREAS = [\n \"security\",\n \"performance\",\n \"readability\",\n \"bugs\",\n \"best-practices\",\n \"typing\",\n] as const;\n\ntype FocusArea = (typeof FOCUS_AREAS)[number];\n\ninterface CodeReviewInput {\n code: string;\n language?: string;\n context?: string;\n focus_areas?: FocusArea[];\n diff_only?: boolean;\n}\n\ninterface Issue {\n severity: \"critical\" | \"warning\" | \"info\" | \"suggestion\";\n line?: number;\n column?: number;\n message: string;\n category: string;\n suggestion?: string;\n code_snippet?: string;\n}\n\ninterface CodeReviewOutput {\n summary: string;\n overall_score: number;\n issues: Issue[];\n suggestions: string[];\n metrics: {\n lines_of_code: number;\n complexity: string;\n maintainability: string;\n };\n processing_time_ms: number;\n mode: \"mock\" | \"llm\";\n language_detected: string;\n issue_count: {\n critical: number;\n warning: number;\n info: number;\n suggestion: number;\n };\n}\n\n// Pattern-based issue detection\nconst ISSUE_PATTERNS = [\n { pattern: /console\\.log/g, message: \"Remove console.log in production\", severity: \"warning\" as const, category: \"best-practices\" },\n { pattern: /TODO|FIXME|HACK/g, message: \"Unresolved TODO/FIXME comment\", severity: \"info\" as const, category: \"maintainability\" },\n { pattern: /==\\s/g, message: \"Use strict equality (===) instead of loose equality (==)\", severity: \"warning\" as const, category: \"best-practices\" },\n { pattern: /var\\s+\\w+/g, message: \"Use const/let instead of var\", severity: \"suggestion\" as const, category: \"best-practices\" },\n { pattern: /:\\s*any\\s*[;,)>]/g, message: \"Avoid using 'any' type - be more specific\", severity: \"warning\" as const, category: \"typing\" },\n { pattern: /eval\\s*\\(/g, message: \"Avoid using eval() - potential security risk\", severity: \"critical\" as const, category: \"security\" },\n { pattern: /innerHTML\\s*=/g, message: \"innerHTML can lead to XSS - use textContent or sanitize\", severity: \"critical\" as const, category: \"security\" },\n { pattern: /password.*=.*[\"']/gi, message: \"Hardcoded password detected\", severity: \"critical\" as const, category: \"security\" },\n { pattern: /function\\s+\\w+\\s*\\([^)]{80,}\\)/g, message: \"Function has too many parameters - consider an options object\", severity: \"suggestion\" as const, category: \"readability\" },\n];\n\nfunction detectLanguage(code: string): string {\n if (code.includes(\"import React\") || code.includes(\"jsx\")) return \"typescript/react\";\n if (code.includes(\"fn \") && code.includes(\"->\")) return \"rust\";\n if (code.includes(\"func \") && code.includes(\":=\")) return \"go\";\n if (code.includes(\"def \") && code.includes(\":\")) return \"python\";\n if (code.includes(\"public class\") || code.includes(\"private void\")) return \"java\";\n if (code.includes(\"module \") && code.includes(\"public entry fun\")) return \"move\";\n if (code.includes(\"function\") || code.includes(\"const \") || code.includes(\"=>\")) return \"typescript\";\n return \"unknown\";\n}\n\nfunction analyzeCode(code: string, focusAreas?: FocusArea[]): Issue[] {\n const issues: Issue[] = [];\n const lines = code.split(\"\\n\");\n\n for (const pattern of ISSUE_PATTERNS) {\n // Skip if focus areas are specified and this category isn't included\n if (focusAreas && focusAreas.length > 0) {\n const categoryMatch = focusAreas.some(\n (area) => pattern.category.toLowerCase().includes(area.toLowerCase())\n );\n if (!categoryMatch) continue;\n }\n\n const matches = code.matchAll(pattern.pattern);\n for (const match of matches) {\n if (match.index === undefined) continue;\n\n // Find line number\n const beforeMatch = code.slice(0, match.index);\n const lineNumber = beforeMatch.split(\"\\n\").length;\n\n issues.push({\n severity: pattern.severity,\n line: lineNumber,\n message: pattern.message,\n category: pattern.category,\n code_snippet: lines[lineNumber - 1]?.trim().slice(0, 80),\n });\n }\n }\n\n return issues;\n}\n\n/**\n * LLM-based code review using OpenAI\n */\nasync function llmCodeReview(\n code: string,\n language: string,\n context?: string\n): Promise<{ summary: string; issues: Issue[]; suggestions: string[] }> {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\"OPENAI_API_KEY not set\");\n }\n\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"gpt-4o-mini\",\n messages: [\n {\n role: \"system\",\n content: `You are an expert code reviewer. Analyze the following ${language} code and provide:\n1. A brief summary (1-2 sentences)\n2. A list of issues with severity (critical/warning/info/suggestion), line number if possible, message, and category\n3. General improvement suggestions\n\nRespond in JSON format:\n{\n \"summary\": \"string\",\n \"issues\": [{ \"severity\": \"critical|warning|info|suggestion\", \"line\": number|null, \"message\": \"string\", \"category\": \"string\" }],\n \"suggestions\": [\"string\"]\n}`,\n },\n {\n role: \"user\",\n content: context ? `Context: ${context}\\n\\nCode:\\n${code}` : code,\n },\n ],\n temperature: 0.3,\n max_tokens: 2048,\n response_format: { type: \"json_object\" },\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${error}`);\n }\n\n const data = await response.json();\n return JSON.parse(data.choices[0].message.content);\n}\n\nexport const codeReviewSkillHandler: SkillHandler = {\n name: \"code-review\",\n version: \"1.0.0\",\n\n canHandle(skillName: string, _skillVersion: string): boolean {\n const normalized = skillName.toLowerCase().replace(/[-_\\s]/g, \"\");\n return (\n normalized === \"codereview\" ||\n normalized === \"codeanalysis\" ||\n normalized === \"linting\" ||\n normalized === \"staticanalysis\"\n );\n },\n\n async execute(input: object, context?: SkillContext): Promise<SkillResult> {\n const startTime = Date.now();\n\n try {\n const {\n code,\n language,\n context: codeContext,\n focus_areas,\n } = input as CodeReviewInput;\n\n // Validate input\n if (!code || typeof code !== \"string\") {\n return { success: false, error: \"Missing or invalid 'code' field\" };\n }\n\n if (code.length === 0) {\n return { success: false, error: \"Code cannot be empty\" };\n }\n\n if (code.length > 100000) {\n return { success: false, error: \"Code too long (max 100000 characters)\" };\n }\n\n const detectedLanguage = language || detectLanguage(code);\n const useLLM = !!process.env.OPENAI_API_KEY;\n\n let issues: Issue[];\n let summary: string;\n let suggestions: string[] = [];\n\n if (useLLM) {\n const llmResult = await llmCodeReview(code, detectedLanguage, codeContext);\n summary = llmResult.summary;\n issues = llmResult.issues;\n suggestions = llmResult.suggestions;\n } else {\n // Pattern-based analysis\n issues = analyzeCode(code, focus_areas);\n\n // Generate summary\n if (issues.filter((i) => i.severity === \"critical\").length > 0) {\n summary = `Found ${issues.filter((i) => i.severity === \"critical\").length} critical issue(s) that should be addressed immediately.`;\n } else if (issues.filter((i) => i.severity === \"warning\").length > 0) {\n summary = `Found ${issues.filter((i) => i.severity === \"warning\").length} warning(s) that need attention.`;\n } else if (issues.length === 0) {\n summary = \"No significant issues found. Code looks good!\";\n } else {\n summary = `Found ${issues.length} minor issue(s) and suggestions.`;\n }\n\n // Generate suggestions\n if (code.length > 500 && !code.includes(\"//\") && !code.includes(\"/*\")) {\n suggestions.push(\"Add comments to explain complex logic\");\n }\n if (code.split(\"\\n\").length > 100) {\n suggestions.push(\"Consider splitting large files into smaller modules\");\n }\n }\n\n // Count issues by severity\n const issueCount = {\n critical: issues.filter((i) => i.severity === \"critical\").length,\n warning: issues.filter((i) => i.severity === \"warning\").length,\n info: issues.filter((i) => i.severity === \"info\").length,\n suggestion: issues.filter((i) => i.severity === \"suggestion\").length,\n };\n\n // Calculate score (100 - deductions)\n const deductions =\n issueCount.critical * 20 +\n issueCount.warning * 5 +\n issueCount.info * 1 +\n issueCount.suggestion * 0.5;\n const overallScore = Math.max(0, Math.min(100, Math.round(100 - deductions)));\n\n // Calculate metrics\n const linesOfCode = code.split(\"\\n\").filter((l) => l.trim().length > 0).length;\n const complexity = linesOfCode < 50 ? \"low\" : linesOfCode < 200 ? \"medium\" : \"high\";\n const maintainability =\n overallScore > 80 ? \"excellent\" : overallScore > 60 ? \"good\" : overallScore > 40 ? \"fair\" : \"needs improvement\";\n\n const output: CodeReviewOutput = {\n summary,\n overall_score: overallScore,\n issues,\n suggestions,\n metrics: {\n lines_of_code: linesOfCode,\n complexity,\n maintainability,\n },\n processing_time_ms: Date.now() - startTime,\n mode: useLLM ? \"llm\" : \"mock\",\n language_detected: detectedLanguage,\n issue_count: issueCount,\n };\n\n return { success: true, output };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Code review failed\",\n };\n }\n },\n\n validateInput(input: object): { valid: boolean; error?: string } {\n const { code, focus_areas } = input as CodeReviewInput;\n\n if (!code || typeof code !== \"string\") {\n return { valid: false, error: \"Missing or invalid 'code' field\" };\n }\n\n if (code.length === 0) {\n return { valid: false, error: \"Code cannot be empty\" };\n }\n\n if (code.length > 100000) {\n return { valid: false, error: \"Code too long (max 100000 characters)\" };\n }\n\n if (focus_areas !== undefined) {\n if (!Array.isArray(focus_areas)) {\n return { valid: false, error: \"focus_areas must be an array\" };\n }\n for (const area of focus_areas) {\n if (!FOCUS_AREAS.includes(area)) {\n return {\n valid: false,\n error: `Invalid focus area: ${area}. Supported: ${FOCUS_AREAS.join(\", \")}`,\n };\n }\n }\n }\n\n return { valid: true };\n },\n\n estimateExecutionTime(input: object): number {\n const { code } = input as CodeReviewInput;\n const useLLM = !!process.env.OPENAI_API_KEY;\n\n if (!code) return 2000;\n\n if (useLLM) {\n // LLM review takes longer\n return Math.min(30000, 2000 + code.length / 20);\n }\n\n // Pattern-based is fast\n return Math.min(5000, 500 + code.length / 100);\n },\n};\n\n/**\n * Code Review skill JSON schemas\n */\nexport const codeReviewInputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n code: {\n type: \"string\",\n description: \"Source code to review\",\n maxLength: 100000,\n },\n language: {\n type: \"string\",\n description: \"Programming language (auto-detected if not provided)\",\n },\n context: {\n type: \"string\",\n description: \"Additional context about the code\",\n },\n focus_areas: {\n type: \"array\",\n items: { type: \"string\", enum: FOCUS_AREAS },\n description: \"Specific areas to focus on\",\n },\n diff_only: {\n type: \"boolean\",\n default: false,\n description: \"Only review changed lines\",\n },\n },\n required: [\"code\"],\n};\n\nexport const codeReviewOutputSchema = {\n $schema: \"http://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties: {\n summary: { type: \"string\" },\n overall_score: { type: \"number\", minimum: 0, maximum: 100 },\n issues: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n severity: { type: \"string\", enum: [\"critical\", \"warning\", \"info\", \"suggestion\"] },\n line: { type: \"integer\" },\n column: { type: \"integer\" },\n message: { type: \"string\" },\n category: { type: \"string\" },\n suggestion: { type: \"string\" },\n code_snippet: { type: \"string\" },\n },\n required: [\"severity\", \"message\", \"category\"],\n },\n },\n suggestions: { type: \"array\", items: { type: \"string\" } },\n metrics: {\n type: \"object\",\n properties: {\n lines_of_code: { type: \"integer\" },\n complexity: { type: \"string\" },\n maintainability: { type: \"string\" },\n },\n },\n processing_time_ms: { type: \"number\" },\n mode: { type: \"string\", enum: [\"mock\", \"llm\"] },\n language_detected: { type: \"string\" },\n issue_count: {\n type: \"object\",\n properties: {\n critical: { type: \"integer\" },\n warning: { type: \"integer\" },\n info: { type: \"integer\" },\n suggestion: { type: \"integer\" },\n },\n },\n },\n required: [\"summary\", \"overall_score\", \"issues\", \"suggestions\", \"metrics\", \"processing_time_ms\", \"mode\"],\n};\n\nexport type { CodeReviewInput, CodeReviewOutput };\n","export * from \"./types.js\";\n\n// Echo skill - simple testing/reference\nexport { echoSkillHandler, echoInputSchema, echoOutputSchema } from \"./echo.js\";\n\n// Translation skill - translates text between languages\nexport {\n translationSkillHandler,\n translationInputSchema,\n translationOutputSchema,\n} from \"./translation.js\";\n\n// Summarization skill - summarizes text content\nexport {\n summarizationSkillHandler,\n summarizationInputSchema,\n summarizationOutputSchema,\n} from \"./summarization.js\";\n\n// Sentiment Analysis skill - analyzes text sentiment\nexport {\n sentimentSkillHandler,\n sentimentInputSchema,\n sentimentOutputSchema,\n} from \"./sentiment.js\";\n\n// Image Generation skill - generates images from prompts\nexport {\n imageGenerationSkillHandler,\n imageGenInputSchema,\n imageGenOutputSchema,\n type ImageGenInput,\n type ImageGenOutput,\n} from \"./image-generation.js\";\n\n// Code Review skill - analyzes code for issues\nexport {\n codeReviewSkillHandler,\n codeReviewInputSchema,\n codeReviewOutputSchema,\n type CodeReviewInput,\n type CodeReviewOutput,\n} from \"./code-review.js\";\n\n// Convenience: All handlers in one array\nimport { echoSkillHandler } from \"./echo.js\";\nimport { translationSkillHandler } from \"./translation.js\";\nimport { summarizationSkillHandler } from \"./summarization.js\";\nimport { sentimentSkillHandler } from \"./sentiment.js\";\nimport { imageGenerationSkillHandler } from \"./image-generation.js\";\nimport { codeReviewSkillHandler } from \"./code-review.js\";\n\nexport const allSkillHandlers = [\n echoSkillHandler,\n translationSkillHandler,\n summarizationSkillHandler,\n sentimentSkillHandler,\n imageGenerationSkillHandler,\n codeReviewSkillHandler,\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 // Private key for on-chain transactions (optional)\n privateKey?: 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.CLANK_API_URL;\n const apiKey = process.env.CLANK_API_KEY;\n const agentId = process.env.CLANK_AGENT_ID;\n\n if (!apiUrl) {\n throw new Error(\"CLANK_API_URL is required\");\n }\n if (!apiKey) {\n throw new Error(\"CLANK_API_KEY is required\");\n }\n if (!agentId) {\n throw new Error(\"CLANK_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.CLANK_NETWORK as Network) ?? \"testnet\",\n rpcUrl: process.env.SUI_RPC_URL,\n packageId: process.env.CLANK_PACKAGE_ID,\n privateKey: process.env.CLANK_PRIVATE_KEY,\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"]}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -487,11 +487,13 @@ var ClankAgent = class {
|
|
|
487
487
|
console.log(` Output stored: ${storedOutput.blobId.slice(0, 20)}...`);
|
|
488
488
|
if (this.keypair && this.suiClient && this.config.packageId) {
|
|
489
489
|
try {
|
|
490
|
+
console.log(` Accepting on-chain...`);
|
|
491
|
+
await this.acceptTaskOnChain(task.taskId);
|
|
490
492
|
console.log(` Submitting on-chain...`);
|
|
491
493
|
await this.submitTaskOnChain(task.taskId, storedOutput.blobId);
|
|
492
494
|
console.log(` \u2705 Task submitted on-chain: ${task.taskId.slice(0, 16)}`);
|
|
493
495
|
} catch (error) {
|
|
494
|
-
console.error(` \u274C On-chain
|
|
496
|
+
console.error(` \u274C On-chain transaction failed: ${error}`);
|
|
495
497
|
}
|
|
496
498
|
} else {
|
|
497
499
|
console.log(` \u2705 Task completed (no on-chain key): ${task.taskId.slice(0, 16)}`);
|
|
@@ -502,6 +504,36 @@ var ClankAgent = class {
|
|
|
502
504
|
markTaskFailed(this.state, task.taskId);
|
|
503
505
|
}
|
|
504
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* Accept task on-chain (moves from POSTED to IN_PROGRESS)
|
|
509
|
+
*/
|
|
510
|
+
async acceptTaskOnChain(taskId) {
|
|
511
|
+
if (!this.keypair || !this.suiClient || !this.config.packageId) {
|
|
512
|
+
throw new Error("On-chain signing not configured");
|
|
513
|
+
}
|
|
514
|
+
const tx = new Transaction();
|
|
515
|
+
tx.setGasBudget(1e7);
|
|
516
|
+
const [zeroCoin] = tx.splitCoins(tx.gas, [0]);
|
|
517
|
+
tx.moveCall({
|
|
518
|
+
target: `${this.config.packageId}::task::accept`,
|
|
519
|
+
arguments: [
|
|
520
|
+
tx.object(taskId),
|
|
521
|
+
tx.object(this.config.agentId),
|
|
522
|
+
zeroCoin,
|
|
523
|
+
tx.object("0x6")
|
|
524
|
+
// Clock
|
|
525
|
+
]
|
|
526
|
+
});
|
|
527
|
+
const result = await this.suiClient.signAndExecuteTransaction({
|
|
528
|
+
transaction: tx,
|
|
529
|
+
signer: this.keypair,
|
|
530
|
+
options: { showEffects: true }
|
|
531
|
+
});
|
|
532
|
+
if (result.effects?.status?.status !== "success") {
|
|
533
|
+
throw new Error(`Accept failed: ${result.effects?.status?.error || "unknown"}`);
|
|
534
|
+
}
|
|
535
|
+
console.log(` Accept Tx: ${result.digest.slice(0, 15)}...`);
|
|
536
|
+
}
|
|
505
537
|
/**
|
|
506
538
|
* Submit task output on-chain
|
|
507
539
|
*/
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent.ts","../src/state.ts","../src/skills/types.ts","../src/skills/echo.ts","../src/config.ts"],"sourcesContent":["import { ClankClient } from \"@clankxyz/sdk\";\nimport { STATUS, VERIFICATION } from \"@clankxyz/shared\";\nimport { Ed25519Keypair } from \"@mysten/sui/keypairs/ed25519\";\nimport { SuiClient } from \"@mysten/sui/client\";\nimport { Transaction } from \"@mysten/sui/transactions\";\nimport { decodeSuiPrivateKey } from \"@mysten/sui/cryptography\";\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 // On-chain transaction capabilities\n private keypair?: Ed25519Keypair;\n private suiClient?: SuiClient;\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 // Initialize on-chain transaction capabilities if private key provided\n if (config.privateKey) {\n try {\n const { secretKey } = decodeSuiPrivateKey(config.privateKey);\n this.keypair = Ed25519Keypair.fromSecretKey(secretKey);\n \n const rpcUrl = config.rpcUrl || (config.network === \"mainnet\" \n ? \"https://fullnode.mainnet.sui.io:443\"\n : \"https://fullnode.testnet.sui.io:443\");\n this.suiClient = new SuiClient({ url: rpcUrl });\n \n console.log(` š On-chain signing enabled: ${this.keypair.toSuiAddress().slice(0, 15)}...`);\n } catch (error) {\n console.error(` ā ļø Failed to load private key: ${error}`);\n }\n }\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 ALL our skills\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let allTasks: any[] = [];\n \n for (const skillId of skillIds) {\n const result = await this.client.api.listTasks({\n status: STATUS.POSTED,\n skillId: skillId,\n limit: 10,\n });\n allTasks = [...allTasks, ...result.data];\n }\n \n // Deduplicate by task ID\n const seen = new Set<string>();\n const tasks = allTasks.filter((t) => {\n if (seen.has(t.id)) return false;\n seen.add(t.id);\n return true;\n });\n \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 on-chain if we have signing capability\n if (this.keypair && this.suiClient && this.config.packageId) {\n try {\n console.log(` Submitting on-chain...`);\n await this.submitTaskOnChain(task.taskId, storedOutput.blobId);\n console.log(` ā
Task submitted on-chain: ${task.taskId.slice(0, 16)}`);\n } catch (error) {\n console.error(` ā On-chain submission failed: ${error}`);\n // Still mark as completed locally for retry later\n }\n } else {\n console.log(` ā
Task completed (no on-chain key): ${task.taskId.slice(0, 16)}`);\n }\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 * Submit task output on-chain\n */\n private async submitTaskOnChain(taskId: string, outputRef: string): Promise<void> {\n if (!this.keypair || !this.suiClient || !this.config.packageId) {\n throw new Error(\"On-chain signing not configured\");\n }\n \n // Generate output hash from the output ref\n const outputHash = outputRef; // Use blob ID as hash for simplicity\n \n const tx = new Transaction();\n tx.setGasBudget(10_000_000); // 0.01 SUI gas\n \n // Call task::submit(task, worker, output_ref, output_hash, clock)\n tx.moveCall({\n target: `${this.config.packageId}::task::submit`,\n arguments: [\n tx.object(taskId),\n tx.object(this.config.agentId),\n tx.pure.string(outputRef),\n tx.pure.string(outputHash),\n tx.object(\"0x6\"), // Clock\n ],\n });\n \n const result = await this.suiClient.signAndExecuteTransaction({\n transaction: tx,\n signer: this.keypair,\n options: { showEffects: true },\n });\n \n if (result.effects?.status?.status !== \"success\") {\n throw new Error(`Transaction failed: ${result.effects?.status?.error || \"unknown\"}`);\n }\n \n console.log(` Tx: ${result.digest.slice(0, 15)}...`);\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","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","/**\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 // Private key for on-chain transactions (optional)\n privateKey?: 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.CLANK_API_URL;\n const apiKey = process.env.CLANK_API_KEY;\n const agentId = process.env.CLANK_AGENT_ID;\n\n if (!apiUrl) {\n throw new Error(\"CLANK_API_URL is required\");\n }\n if (!apiKey) {\n throw new Error(\"CLANK_API_KEY is required\");\n }\n if (!agentId) {\n throw new Error(\"CLANK_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.CLANK_NETWORK as Network) ?? \"testnet\",\n rpcUrl: process.env.SUI_RPC_URL,\n packageId: process.env.CLANK_PACKAGE_ID,\n privateKey: process.env.CLANK_PRIVATE_KEY,\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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/agent.ts","../src/state.ts","../src/skills/types.ts","../src/skills/echo.ts","../src/config.ts"],"sourcesContent":["import { ClankClient } from \"@clankxyz/sdk\";\nimport { STATUS, VERIFICATION } from \"@clankxyz/shared\";\nimport { Ed25519Keypair } from \"@mysten/sui/keypairs/ed25519\";\nimport { SuiClient } from \"@mysten/sui/client\";\nimport { Transaction } from \"@mysten/sui/transactions\";\nimport { decodeSuiPrivateKey } from \"@mysten/sui/cryptography\";\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 // On-chain transaction capabilities\n private keypair?: Ed25519Keypair;\n private suiClient?: SuiClient;\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 // Initialize on-chain transaction capabilities if private key provided\n if (config.privateKey) {\n try {\n const { secretKey } = decodeSuiPrivateKey(config.privateKey);\n this.keypair = Ed25519Keypair.fromSecretKey(secretKey);\n \n const rpcUrl = config.rpcUrl || (config.network === \"mainnet\" \n ? \"https://fullnode.mainnet.sui.io:443\"\n : \"https://fullnode.testnet.sui.io:443\");\n this.suiClient = new SuiClient({ url: rpcUrl });\n \n console.log(` š On-chain signing enabled: ${this.keypair.toSuiAddress().slice(0, 15)}...`);\n } catch (error) {\n console.error(` ā ļø Failed to load private key: ${error}`);\n }\n }\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 ALL our skills\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let allTasks: any[] = [];\n \n for (const skillId of skillIds) {\n const result = await this.client.api.listTasks({\n status: STATUS.POSTED,\n skillId: skillId,\n limit: 10,\n });\n allTasks = [...allTasks, ...result.data];\n }\n \n // Deduplicate by task ID\n const seen = new Set<string>();\n const tasks = allTasks.filter((t) => {\n if (seen.has(t.id)) return false;\n seen.add(t.id);\n return true;\n });\n \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 on-chain if we have signing capability\n if (this.keypair && this.suiClient && this.config.packageId) {\n try {\n // First accept on-chain, then submit\n console.log(` Accepting on-chain...`);\n await this.acceptTaskOnChain(task.taskId);\n console.log(` Submitting on-chain...`);\n await this.submitTaskOnChain(task.taskId, storedOutput.blobId);\n console.log(` ā
Task submitted on-chain: ${task.taskId.slice(0, 16)}`);\n } catch (error) {\n console.error(` ā On-chain transaction failed: ${error}`);\n // Still mark as completed locally for retry later\n }\n } else {\n console.log(` ā
Task completed (no on-chain key): ${task.taskId.slice(0, 16)}`);\n }\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 * Accept task on-chain (moves from POSTED to IN_PROGRESS)\n */\n private async acceptTaskOnChain(taskId: string): Promise<void> {\n if (!this.keypair || !this.suiClient || !this.config.packageId) {\n throw new Error(\"On-chain signing not configured\");\n }\n \n const tx = new Transaction();\n tx.setGasBudget(10_000_000); // 0.01 SUI gas\n \n // Create zero-value coin for bond (our skills require 0 bond)\n const [zeroCoin] = tx.splitCoins(tx.gas, [0]);\n \n // Call task::accept(task, worker, bond, clock, ctx)\n tx.moveCall({\n target: `${this.config.packageId}::task::accept`,\n arguments: [\n tx.object(taskId),\n tx.object(this.config.agentId),\n zeroCoin,\n tx.object(\"0x6\"), // Clock\n ],\n });\n \n const result = await this.suiClient.signAndExecuteTransaction({\n transaction: tx,\n signer: this.keypair,\n options: { showEffects: true },\n });\n \n if (result.effects?.status?.status !== \"success\") {\n throw new Error(`Accept failed: ${result.effects?.status?.error || \"unknown\"}`);\n }\n \n console.log(` Accept Tx: ${result.digest.slice(0, 15)}...`);\n }\n \n /**\n * Submit task output on-chain\n */\n private async submitTaskOnChain(taskId: string, outputRef: string): Promise<void> {\n if (!this.keypair || !this.suiClient || !this.config.packageId) {\n throw new Error(\"On-chain signing not configured\");\n }\n \n // Generate output hash from the output ref\n const outputHash = outputRef; // Use blob ID as hash for simplicity\n \n const tx = new Transaction();\n tx.setGasBudget(10_000_000); // 0.01 SUI gas\n \n // Call task::submit(task, worker, output_ref, output_hash, clock)\n tx.moveCall({\n target: `${this.config.packageId}::task::submit`,\n arguments: [\n tx.object(taskId),\n tx.object(this.config.agentId),\n tx.pure.string(outputRef),\n tx.pure.string(outputHash),\n tx.object(\"0x6\"), // Clock\n ],\n });\n \n const result = await this.suiClient.signAndExecuteTransaction({\n transaction: tx,\n signer: this.keypair,\n options: { showEffects: true },\n });\n \n if (result.effects?.status?.status !== \"success\") {\n throw new Error(`Transaction failed: ${result.effects?.status?.error || \"unknown\"}`);\n }\n \n console.log(` Tx: ${result.digest.slice(0, 15)}...`);\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","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","/**\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 // Private key for on-chain transactions (optional)\n privateKey?: 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.CLANK_API_URL;\n const apiKey = process.env.CLANK_API_KEY;\n const agentId = process.env.CLANK_AGENT_ID;\n\n if (!apiUrl) {\n throw new Error(\"CLANK_API_URL is required\");\n }\n if (!apiKey) {\n throw new Error(\"CLANK_API_KEY is required\");\n }\n if (!agentId) {\n throw new Error(\"CLANK_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.CLANK_NETWORK as Network) ?? \"testnet\",\n rpcUrl: process.env.SUI_RPC_URL,\n packageId: process.env.CLANK_PACKAGE_ID,\n privateKey: process.env.CLANK_PRIVATE_KEY,\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":[]}
|