@kudo-dev/sdk 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/agent/start.ts","../../src/agent/agent.ts","../../src/agent/log.ts","../../src/agent/agent-id.ts","../../src/abi/registries.ts","../../src/networks.ts","../../src/agent/config.ts","../../src/agent/jobs.ts","../../src/agent/prompts.ts","../../src/agent/paths.ts","../../src/agent/server/index.ts","../../src/agent/server/http.ts","../../src/agent/server/handlers.ts","../../src/agent/skills.ts","../../src/errors.ts","../../src/dstack.ts","../../src/agent/tee.ts"],"sourcesContent":["/**\n * startAgent: everything needed to run a Kudo agent.\n *\n * Starts the HTTP endpoint and the scheduled jobs, and stops both cleanly when\n * asked. The agent supplies who it is (its system prompt) and anything beyond\n * the defaults (extra skills, its own task prompts, its job schedule); the\n * chain, the key and the API key come from the environment (see .env.example).\n *\n * SHUTDOWN_GRACE_SECONDS how long a run may finish in on shutdown (default 120)\n */\nimport { existsSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { runAgent, type AgentSession } from \"./agent.js\";\nimport { prepareAgentIdFile, resolveAgentId, syncAgentId } from \"./agent-id.js\";\nimport { requireEnvironment, warnIfTwitterIncomplete } from \"./config.js\";\nimport { exclusive, resolveJobs, startJobs, whenRunsIdle, type AgentJob, type JobSpec } from \"./jobs.js\";\nimport { loadPrompt, loadSystemPrompt, type TextSource } from \"./prompts.js\";\nimport { startServer } from \"./server/index.js\";\nimport { SKILLS_DIR } from \"./paths.js\";\nimport { assembleSkills, type SkillRef } from \"./skills.js\";\nimport { resolveTeeIdentity } from \"./tee.js\";\n\nexport interface AgentOptions {\n /** Who this agent is: the text, or a path / file: URL to it (e.g. `new URL(\"./system.md\", import.meta.url)`). */\n systemPrompt: TextSource;\n /**\n * Skills beyond the defaults (`kudo`, `kudo-runtime`, `twitter`): the name of\n * one this package ships (`chain-forensics`, `kudo-validation`) or a path /\n * file: URL to a skill folder of your own.\n */\n skills?: SkillRef[];\n /**\n * Scheduled jobs by name, each `{ interval, prompt? }`: seconds between runs\n * and the task prompt (text, a path or a file: URL). A job without a prompt\n * runs the bundled one of its name (`take-work`, `settle-due`). Default\n * `{ \"settle-due\": { interval: 300 } }`; JOBS overrides the schedule.\n */\n jobs?: Record<string, AgentJob>;\n /** HTTP port. Default PORT, else 3000. */\n port?: number;\n /** Claude model id. Default `claude-opus-5`. */\n model?: string;\n /** Working directory for the agent's shell. Default: the system prompt file's folder, else the current one. */\n cwd?: string;\n}\n\n/**\n * Must stay below the orchestrator's stop grace period, or the process is\n * SIGKILLed first and the graceful path never runs.\n */\nconst SHUTDOWN_GRACE_MS = Number(process.env.SHUTDOWN_GRACE_SECONDS?.trim() || 120) * 1000;\n\n/**\n * Resolves the Phala app id and puts it in the environment, where the agent\n * picks it up and registers it as `teeId` metadata on its ERC-8004 identity.\n */\nasync function announceTee(): Promise<void> {\n const tee = await resolveTeeIdentity();\n\n if (!tee) {\n console.log(\"no TEE app id — running without attestation\");\n return;\n }\n\n process.env.TEE_ID = tee.teeId;\n process.env.TEE_TRUST_URL = tee.trustCenterUrl;\n process.env.TEE_ID_SOURCE = tee.source;\n\n if (tee.source === \"dstack\") {\n console.log(`attestation: ${tee.trustCenterUrl}`);\n return;\n }\n\n // A mocked id resolves to a real report for somebody else's app. Say so, or\n // a local run reads exactly like an attested one.\n console.log(`TEE_ID set by hand: ${tee.trustCenterUrl}`);\n console.log(\" that report is NOT this process — local stand-in, attests nothing\");\n}\n\nfunction defaultCwd(source: TextSource): string {\n if (source instanceof URL) return dirname(fileURLToPath(source));\n // A one-line string naming an existing file is a path (as prompts.ts reads it).\n if (!source.includes(\"\\n\") && existsSync(source)) return dirname(resolve(source));\n return process.cwd();\n}\n\n/** The fixed parts of a run: system prompt, skills, working directory, model. */\nexport async function createSession(options: AgentOptions): Promise<AgentSession> {\n const skills = await assembleSkills(options.skills);\n return {\n systemPrompt: await loadSystemPrompt(options.systemPrompt),\n skills,\n cwd: resolve(options.cwd ?? defaultCwd(options.systemPrompt)),\n model: options.model ?? \"claude-opus-5\",\n };\n}\n\n/** Starts the agent: the HTTP endpoint and its scheduled jobs. Resolves once both are running. */\nexport async function startAgent(options: AgentOptions): Promise<void> {\n requireEnvironment();\n warnIfTwitterIncomplete();\n // AGENT_ID comes from the registry, never from the environment (agent-id.ts).\n await resolveAgentId();\n await announceTee();\n // The kudo skill's sponsored-send script, which every write tries first.\n process.env.KUDO_SPONSORED_SEND = join(SKILLS_DIR, \"kudo\", \"sponsored-send.mjs\");\n\n const session = await createSession(options);\n console.log(`skills: ${session.skills.names.join(\", \")}`);\n\n const jobs = resolveJobs(options.jobs);\n // Fail now, not at the first tick, if a job has no prompt to run.\n for (const job of jobs) await loadPrompt(job.name, job.prompt);\n\n // Where a new agent writes its id after registering; every run starts from it.\n await prepareAgentIdFile();\n const beforeRun = async () => {\n const recorded = await syncAgentId();\n if (recorded) console.log(`AGENT_ID ${recorded}, as the agent recorded it after registering`);\n };\n\n // Through the same lock as the jobs: a message run signs from the same key.\n const run = (prompt: string) =>\n exclusive(async () => {\n await beforeRun();\n return runAgent(prompt, session, \"message\");\n });\n // Read on every run, so an edited prompt file takes effect at the next tick.\n const runJob = async (job: JobSpec) => {\n await beforeRun();\n return runAgent(await loadPrompt(job.name, job.prompt), session, job.name);\n };\n\n const server = startServer(run, options.port);\n const scheduled = startJobs(jobs, runJob);\n\n let shuttingDown = false;\n\n /**\n * Stop accepting work, then let any run in flight finish rather than being\n * killed between a payment and its attestation — but not forever.\n */\n function shutdown(): void {\n if (shuttingDown) {\n console.log(\"second signal — exiting now\");\n process.exit(130);\n }\n shuttingDown = true;\n\n console.log(`shutting down (up to ${SHUTDOWN_GRACE_MS / 1000}s for the current run)`);\n server.close();\n scheduled.stop();\n\n // .unref() so a pending timer cannot keep the process alive on its own.\n const deadline = new Promise<\"timeout\">((resolveTimeout) =>\n setTimeout(() => resolveTimeout(\"timeout\"), SHUTDOWN_GRACE_MS).unref(),\n );\n\n // Jobs, and any /message run in flight or already queued behind the lock.\n const idle = Promise.all([scheduled.whenIdle(), whenRunsIdle()]);\n void Promise.race([idle, deadline]).then((outcome) => {\n if (outcome === \"timeout\") console.error(\"run did not finish in time — exiting anyway\");\n process.exit(0);\n });\n }\n\n process.on(\"SIGTERM\", shutdown); // orchestrator stopping the container\n process.on(\"SIGINT\", shutdown); // Ctrl-C\n}\n","/**\n * The agent.\n *\n * One function: give it a prompt, get its answer back. There are no custom\n * tools — it works the way a person would at a shell, with `cast` for the chain\n * and `node` to sign X API requests. What it knows lives in its skills (see\n * skills.ts) and its system prompt (see prompts.ts).\n */\nimport {\n query,\n type Options,\n type SDKAssistantMessage,\n type SDKMessage,\n type SDKResultMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\nimport { clip, limits, runLog, type RunLog } from \"./log.js\";\nimport type { SkillPlugin } from \"./skills.js\";\n\n/** What one agent runs with, fixed at startup. */\nexport interface AgentSession {\n /** common.md followed by the agent's own system prompt. */\n systemPrompt: string;\n /** The plugin holding exactly this agent's skills. */\n skills: SkillPlugin;\n /** Working directory for the shell: the agent's own folder. */\n cwd: string;\n /** Claude model id. */\n model: string;\n}\n\n/** Keeps a long run alive through slow RPC calls and a flaky network. */\nconst RESILIENCE_ENV = {\n API_TIMEOUT_MS: \"120000\",\n CLAUDE_CODE_MAX_RETRIES: \"2\",\n CLAUDE_ENABLE_STREAM_WATCHDOG: \"1\",\n CLAUDE_STREAM_IDLE_TIMEOUT_MS: \"300000\",\n};\n\nfunction agentOptions(session: AgentSession, log: RunLog): Options {\n return {\n model: session.model,\n systemPrompt: session.systemPrompt,\n cwd: session.cwd,\n\n // Skills come only from the plugin assembled for this agent (skills.ts),\n // and no project or user settings are read, so nothing else on the machine\n // changes what the agent knows.\n settingSources: [],\n plugins: [{ type: \"local\", path: session.skills.path }],\n skills: session.skills.names,\n\n // The shell is the whole tool surface.\n //\n // `allowedTools` is an auto-approve list, not a filter: on its own it still\n // leaves every other built-in tool, and any connector on the API key's\n // account, advertised to the model. Denying them explicitly takes the tool\n // list from 23 entries to Bash and Skill, so what the agent can do matches\n // what this file says it can do — which is the claim the TEE attestation\n // is supposed to stand behind.\n allowedTools: [\"Bash\"],\n disallowedTools: [\n \"Read\",\n \"Write\",\n \"Edit\",\n \"WebFetch\",\n \"WebSearch\",\n \"mcp__*\", // connectors inherited from the account behind ANTHROPIC_API_KEY\n \"Task\",\n \"Artifact\",\n \"ArtifactComments\",\n \"ArtifactData\",\n \"CronCreate\",\n \"CronDelete\",\n \"CronList\",\n \"DesignSync\",\n \"EnterWorktree\",\n \"ExitWorktree\",\n \"ListAgents\",\n \"Monitor\",\n \"NotebookEdit\",\n \"PushNotification\",\n \"RemoteTrigger\",\n \"ReportFindings\",\n \"ScheduleWakeup\",\n \"SendMessage\",\n \"TaskStop\",\n \"ToolSearch\",\n \"Workflow\",\n ],\n\n // Nobody is at the keyboard, so deny anything not pre-approved.\n permissionMode: \"dontAsk\",\n\n maxTurns: 40,\n\n env: { ...process.env, ...RESILIENCE_ENV },\n\n // Claude Code's own diagnostics: API errors, retries, a failed plugin load.\n stderr: (data) => {\n for (const line of data.split(\"\\n\")) if (line.trim()) log.error(`stderr: ${clip(line, limits.MAX_OUTPUT)}`);\n },\n };\n}\n\n/** The prose of one assistant turn. Tool calls and thinking are not included. */\nfunction proseOf(message: SDKAssistantMessage): string {\n return message.message.content\n .filter((block) => block.type === \"text\")\n .map((block) => block.text)\n .join(\"\");\n}\n\nexport class AgentRunError extends Error {}\n\n/** The text of a tool result, which the SDK gives as a string or as content blocks. */\nfunction resultText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .map((block) => (block && typeof block === \"object\" && \"text\" in block ? String(block.text) : \"\"))\n .join(\"\");\n}\n\n/**\n * Logs one message from the run: each command or skill the agent starts, the\n * output of any that fails, and (at debug) everything else.\n */\nfunction logMessage(message: SDKMessage, log: RunLog, commands: Map<string, string>): void {\n if (message.type === \"system\" && message.subtype === \"init\") {\n log.debug(`session ${message.session_id}, model ${message.model}, tools ${message.tools.join(\", \")}`);\n return;\n }\n\n if (message.type === \"assistant\") {\n for (const block of message.message.content) {\n if (block.type === \"text\" && block.text.trim()) log.debug(`says: ${clip(block.text, limits.MAX_OUTPUT)}`);\n if (block.type !== \"tool_use\") continue;\n const input = (block.input ?? {}) as Record<string, unknown>;\n const what =\n block.name === \"Bash\"\n ? `$ ${clip(String(input.command ?? \"\"), limits.MAX_COMMAND)}`\n : block.name === \"Skill\"\n ? `skill ${String(input.skill ?? input.command ?? \"\")}`\n : `${block.name} ${clip(JSON.stringify(input), limits.MAX_COMMAND)}`;\n commands.set(block.id, what);\n log.info(what);\n }\n return;\n }\n\n if (message.type === \"user\" && Array.isArray(message.message.content)) {\n for (const block of message.message.content) {\n if (typeof block !== \"object\" || block.type !== \"tool_result\") continue;\n const output = clip(resultText(block.content), limits.MAX_OUTPUT);\n const what = commands.get(block.tool_use_id) ?? block.tool_use_id;\n if (block.is_error) log.error(`failed: ${what}\\n${output}`);\n else log.debug(`output of ${what}\\n${output}`);\n }\n }\n}\n\n/** The run's closing line, and an error for anything but success. */\nfunction finish(result: SDKResultMessage, log: RunLog): AgentRunError | undefined {\n const stats = `${(result.duration_ms / 1000).toFixed(1)}s, ${result.num_turns} turns, $${result.total_cost_usd.toFixed(4)}`;\n for (const denial of result.permission_denials ?? []) {\n log.error(`denied tool ${denial.tool_name}: ${clip(JSON.stringify(denial.tool_input), limits.MAX_COMMAND)}`);\n }\n if (result.subtype === \"success\") {\n log.info(`done (${stats})`);\n return undefined;\n }\n const errors = result.errors?.length ? `: ${result.errors.join(\"; \")}` : \"\";\n log.error(`ended ${result.subtype} (${stats})${errors}`);\n return new AgentRunError(`Agent run ended: ${result.subtype}${errors}`);\n}\n\n/**\n * Runs one task to completion and returns everything the agent said.\n * `label` names what started it (a job's name, or `message`) in the log.\n *\n * Throws AgentRunError if the run did not finish — callers decide whether that\n * is a 500 or a logged line.\n */\nexport async function runAgent(prompt: string, session: AgentSession, label = \"run\"): Promise<string> {\n const log = runLog(label);\n const options = agentOptions(session, log);\n const said: string[] = [];\n const commands = new Map<string, string>();\n\n log.info(`started: ${clip(prompt.split(\"\\n\")[0] ?? \"\", 120)}`);\n try {\n for await (const message of query({ prompt, options })) {\n logMessage(message, log, commands);\n if (message.type === \"assistant\") said.push(proseOf(message));\n if (message.type === \"result\") {\n const error = finish(message, log);\n if (error) throw error;\n return said.join(\"\").trim();\n }\n }\n } catch (error) {\n if (!(error instanceof AgentRunError)) {\n log.error(`crashed: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`);\n }\n throw error;\n }\n\n log.error(\"ended without a result\");\n throw new AgentRunError(\"Agent run ended without a result.\");\n}\n","/**\n * Logging for agent runs, written so a failed run can be diagnosed from the\n * log alone: which job or message started it, every command the agent ran,\n * the output of any that failed, and how the run ended.\n *\n * LOG_LEVEL=info (default) runs, commands, skills, failures, outcomes\n * LOG_LEVEL=debug also every command's output and what the agent said\n *\n * Every line passes through `redact`, because a failed `cast` call repeats\n * its whole command line, `--private-key` included.\n */\nimport { randomBytes } from \"node:crypto\";\n\n/** Environment variables whose values must never reach a log. */\nconst SECRETS = [\n \"PRIVATE_KEY\",\n \"ANTHROPIC_API_KEY\",\n \"TWITTER_API_KEY\",\n \"TWITTER_API_SECRET_KEY\",\n \"TWITTER_ACCESS_TOKEN\",\n \"TWITTER_ACCESS_TOKEN_SECRET\",\n] as const;\n\n/** Output kept per command; enough for an error message, not a whole receipt. */\nconst MAX_OUTPUT = 1500;\nconst MAX_COMMAND = 400;\n\nexport const debugEnabled = (env: NodeJS.ProcessEnv = process.env) => env.LOG_LEVEL?.trim().toLowerCase() === \"debug\";\n\n/** Replaces every secret's value (with or without a 0x prefix) by its name. */\nexport function redact(text: string, env: NodeJS.ProcessEnv = process.env): string {\n let out = text;\n for (const name of SECRETS) {\n const value = env[name]?.trim();\n if (!value || value.length < 8) continue;\n const forms = new Set([value, value.replace(/^0x/i, \"\")]);\n for (const form of forms) if (form.length >= 8) out = out.split(form).join(`[${name}]`);\n }\n return out;\n}\n\nexport function clip(text: string, max: number): string {\n const flat = text.trim();\n return flat.length <= max ? flat : `${flat.slice(0, max)}… (${flat.length - max} more chars)`;\n}\n\nconst time = () => new Date().toISOString().slice(11, 19);\n\nexport interface RunLog {\n info(message: string): void;\n error(message: string): void;\n debug(message: string): void;\n}\n\n/** A logger for one run: every line carries the time, the run's id and what started it. */\nexport function runLog(label: string): RunLog {\n const tag = `[${label} ${randomBytes(3).toString(\"hex\")}]`;\n const line = (message: string) => `${time()} ${tag} ${redact(message)}`;\n return {\n info: (message) => console.log(line(message)),\n error: (message) => console.error(line(message)),\n debug: (message) => {\n if (debugEnabled()) console.log(line(message));\n },\n };\n}\n\nexport const limits = { MAX_OUTPUT, MAX_COMMAND };\n","/**\n * The agent's ERC-8004 id, which the runtime sets as AGENT_ID. Nobody sets it\n * by hand: a value already in the environment is discarded.\n *\n * At startup the runtime reads the registry's `Registered` events for this\n * agent's wallet and sets AGENT_ID from them.\n * A new agent has none, so AGENT_ID stays empty. At its first run the agent\n * registers and writes the new id to KUDO_AGENT_ID_FILE, and\n * before every run the runtime sets AGENT_ID from that file.\n *\n * Every shell the agent runs is a fresh child of this process, so the file is\n * how the agent hands the id back.\n */\nimport { mkdtemp, readFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { createPublicClient, getAbiItem, http, type Address, type PublicClient } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nimport { identityRegistryAbi } from \"../abi/registries.js\";\nimport { networks } from \"../networks.js\";\n\nconst ID = /^\\d+$/;\n\n/**\n * The id this wallet registered, from the registry's `Registered` events, or\n * undefined if it never registered one it still owns. Walks back from the\n * latest block one RPC-sized window at a time, and takes the most recent\n * registration it still owns. Throws if the RPC fails, so a lookup error is\n * never mistaken for \"no identity\", which would lead to registering twice.\n */\nexport async function findRegisteredAgentId(\n client: PublicClient,\n registry: Address,\n owner: Address,\n maxLogRange: bigint = networks.robinhood.maxLogRange,\n): Promise<bigint | undefined> {\n const balance = await client.readContract({\n address: registry,\n abi: identityRegistryAbi,\n functionName: \"balanceOf\",\n args: [owner],\n });\n if (balance === 0n) return undefined;\n\n const registered = getAbiItem({ abi: identityRegistryAbi, name: \"Registered\" });\n let to = await client.getBlockNumber();\n for (;;) {\n const from = to >= maxLogRange ? to - maxLogRange + 1n : 0n;\n const logs = await client.getLogs({ address: registry, event: registered, args: { owner }, fromBlock: from, toBlock: to });\n // Newest first: an id may since have been transferred away.\n for (const log of logs.reverse()) {\n const id = log.args.agentId;\n if (id === undefined) continue;\n const current = await client.readContract({\n address: registry,\n abi: identityRegistryAbi,\n functionName: \"ownerOf\",\n args: [id],\n });\n if (current.toLowerCase() === owner.toLowerCase()) return id;\n }\n if (from === 0n) return undefined;\n to = from - 1n;\n }\n}\n\n/** Sets AGENT_ID from this wallet's `Registered` events, discarding any value already set. */\nexport async function resolveAgentId(env: NodeJS.ProcessEnv = process.env): Promise<void> {\n delete env.AGENT_ID;\n const owner = privateKeyToAccount(env.PRIVATE_KEY!.trim() as `0x${string}`).address;\n const client = createPublicClient({ transport: http(env.RPC_URL!.trim()) });\n const id = await findRegisteredAgentId(client, env.IDENTITY_REGISTRY!.trim() as Address, owner);\n\n if (id === undefined) {\n console.log(`no ERC-8004 identity registered by ${owner} — the agent registers one at its first run`);\n return;\n }\n env.AGENT_ID = id.toString();\n console.log(`AGENT_ID ${env.AGENT_ID}, registered by ${owner}`);\n}\n\n/** Creates the empty file a new agent writes its id to, and names it in KUDO_AGENT_ID_FILE. */\nexport async function prepareAgentIdFile(env: NodeJS.ProcessEnv = process.env): Promise<string> {\n const file = join(await mkdtemp(join(tmpdir(), \"kudo-agent-id-\")), \"agent-id\");\n env.KUDO_AGENT_ID_FILE = file;\n return file;\n}\n\n/**\n * Sets AGENT_ID from the id the agent wrote after registering, if it wrote\n * one. Returns the id when it changed AGENT_ID, so the change can be logged.\n */\nexport async function syncAgentId(env: NodeJS.ProcessEnv = process.env): Promise<string | undefined> {\n const file = env.KUDO_AGENT_ID_FILE;\n if (!file) return undefined;\n\n let recorded: string;\n try {\n recorded = (await readFile(file, \"utf8\")).trim();\n } catch {\n return undefined; // nothing written yet\n }\n if (!ID.test(recorded)) {\n if (recorded) console.error(`Ignoring ${file}: \"${recorded.slice(0, 40)}\" is not an agent id.`);\n return undefined;\n }\n\n const previous = env.AGENT_ID?.trim();\n env.AGENT_ID = recorded;\n return previous === recorded ? undefined : recorded;\n}\n","/**\n * The parts of the ERC-8004 registries Kudo uses.\n *\n * The Identity Registry is ERC-721 but not Enumerable: there is no\n * `tokenOfOwnerByIndex` and no reverse lookup, so the only route from a wallet\n * to its ids is the `Registered` event filtered on its indexed `owner`.\n */\nexport const identityRegistryAbi = [\n {\n type: \"function\",\n name: \"register\",\n inputs: [\n { name: \"agentURI\", type: \"string\" },\n {\n name: \"metadata\",\n type: \"tuple[]\",\n components: [\n { name: \"metadataKey\", type: \"string\" },\n { name: \"metadataValue\", type: \"bytes\" },\n ],\n },\n ],\n outputs: [{ name: \"agentId\", type: \"uint256\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"setMetadata\",\n inputs: [\n { name: \"agentId\", type: \"uint256\" },\n { name: \"key\", type: \"string\" },\n { name: \"value\", type: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"getMetadata\",\n inputs: [\n { name: \"agentId\", type: \"uint256\" },\n { name: \"key\", type: \"string\" },\n ],\n outputs: [{ name: \"\", type: \"bytes\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"ownerOf\",\n inputs: [{ name: \"tokenId\", type: \"uint256\" }],\n outputs: [{ name: \"\", type: \"address\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"balanceOf\",\n inputs: [{ name: \"owner\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"tokenURI\",\n inputs: [{ name: \"tokenId\", type: \"uint256\" }],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"event\",\n name: \"Registered\",\n inputs: [\n { name: \"agentId\", type: \"uint256\", indexed: true },\n { name: \"agentURI\", type: \"string\", indexed: false },\n { name: \"owner\", type: \"address\", indexed: true },\n ],\n anonymous: false,\n },\n {\n type: \"event\",\n name: \"Transfer\",\n inputs: [\n { name: \"from\", type: \"address\", indexed: true },\n { name: \"to\", type: \"address\", indexed: true },\n { name: \"tokenId\", type: \"uint256\", indexed: true },\n ],\n anonymous: false,\n },\n] as const;\n\n/** The two reads a reputation summary needs. `getSummary` refuses an empty client list. */\nexport const reputationRegistryAbi = [\n {\n type: \"function\",\n name: \"getClients\",\n inputs: [{ name: \"agentId\", type: \"uint256\" }],\n outputs: [{ name: \"\", type: \"address[]\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"getSummary\",\n inputs: [\n { name: \"agentId\", type: \"uint256\" },\n { name: \"clientAddresses\", type: \"address[]\" },\n { name: \"tag1\", type: \"string\" },\n { name: \"tag2\", type: \"string\" },\n ],\n outputs: [\n { name: \"count\", type: \"uint64\" },\n { name: \"summaryValue\", type: \"int128\" },\n { name: \"summaryValueDecimals\", type: \"uint8\" },\n ],\n stateMutability: \"view\",\n },\n] as const;\n","import { defineChain, type Address, type Chain } from \"viem\";\n\n/**\n * Everything the SDK needs to know about one deployment.\n *\n * `statuses` is the contract's status enum in order: the current contract's\n * `0` is Minted. Only the current mainnet contract is listed; older Kudo\n * deployments (mainnet 0xc269…, testnet 0x7021…) use a different enum and\n * are not supported.\n */\nexport interface KudoNetwork {\n key: string;\n chain: Chain;\n kudo: Address;\n usdg: Address;\n identityRegistry: Address;\n reputationRegistry?: Address;\n statuses: readonly CovenantStatus[];\n /** Where a covenant card can be opened, `{id}` replaced. */\n covenantUrl?: string;\n explorerUrl: string;\n /** Widest block range the RPC accepts in one `eth_getLogs`. */\n maxLogRange: bigint;\n}\n\nexport type CovenantStatus = \"MINTED\" | \"IN_PROGRESS\" | \"COMPLETED\" | \"FAILED\";\n\nexport const robinhood: Chain = defineChain({\n id: 4663,\n name: \"Robinhood Chain\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n rpcUrls: { default: { http: [\"https://rpc.mainnet.chain.robinhood.com\"] } },\n blockExplorers: {\n default: { name: \"Blockscout\", url: \"https://robinhoodchain.blockscout.com\" },\n },\n contracts: {\n multicall3: { address: \"0xca11bde05977b3631167028862be2a173976ca11\" },\n },\n});\n\nexport const networks = {\n /** Robinhood Chain mainnet, where app.kudo.archi reads and writes. */\n robinhood: {\n key: \"robinhood\",\n chain: robinhood,\n kudo: \"0x1930D0FEaB14b024353bF22adE03Db989aD640C7\",\n usdg: \"0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168\",\n identityRegistry: \"0x8004A169FB4a3325136EB29fA0ceB6D2e539a432\",\n reputationRegistry: \"0x8004BAa17C55a88189AE136b182e5fdA19dE9b63\",\n statuses: [\"MINTED\", \"IN_PROGRESS\", \"COMPLETED\", \"FAILED\"],\n covenantUrl: \"https://app.kudo.archi/share/{id}\",\n explorerUrl: \"https://robinhoodchain.blockscout.com\",\n maxLogRange: 10_000_000n,\n },\n} as const satisfies Record<string, KudoNetwork>;\n\nexport type NetworkKey = keyof typeof networks;\n\n/** Resolves a key or a full config, with any field overridden. */\nexport function resolveNetwork(\n network: NetworkKey | KudoNetwork = \"robinhood\",\n overrides: Partial<KudoNetwork> = {},\n): KudoNetwork {\n const base = typeof network === \"string\" ? networks[network] : network;\n if (!base) {\n throw new Error(\n `Unknown Kudo network \"${String(network)}\". Known: ${Object.keys(networks).join(\", \")}`,\n );\n }\n return { ...base, ...overrides };\n}\n","/** Environment checks, run once at startup so failures are loud and early. */\n\nconst REQUIRED = [\n \"ANTHROPIC_API_KEY\",\n \"PRIVATE_KEY\",\n \"RPC_URL\",\n \"KUDO\",\n \"IDENTITY_REGISTRY\",\n] as const;\n\nconst TWITTER = [\n \"TWITTER_API_KEY\",\n \"TWITTER_API_SECRET_KEY\",\n \"TWITTER_ACCESS_TOKEN\",\n \"TWITTER_ACCESS_TOKEN_SECRET\",\n \"TWITTER_HANDLE\",\n] as const;\n\nconst unset = (keys: readonly string[]) =>\n keys.filter((key) => !process.env[key]?.trim());\n\n/** Exits if the agent cannot run at all. */\nexport function requireEnvironment(): void {\n const missing = unset(REQUIRED);\n if (missing.length === 0) return;\n\n console.error(`Missing required environment variables: ${missing.join(\", \")}`);\n console.error(\"See .env.example in @kudo-dev/sdk.\");\n process.exit(1);\n}\n\n/**\n * Warns about a half-configured X account rather than exiting: most prompts\n * never tweet. All five or none — with some set, requests go out unsigned and\n * X answers 403 \"Authenticating with Unknown\", which reads like a permissions\n * problem and is not.\n */\nexport function warnIfTwitterIncomplete(): void {\n const missing = unset(TWITTER);\n if (missing.length === 0 || missing.length === TWITTER.length) return;\n\n console.error(\n `Warning: X credentials are partially set (missing ${missing.join(\", \")}). ` +\n \"Posting will fail with 403 Unsupported Authentication.\",\n );\n}\n","/**\n * Scheduled jobs.\n *\n * A job is one task prompt on one interval. An agent runs as many as it has\n * work of different kinds — Shinichi takes work on one tick and settles what\n * he owes on another — and each prompt stays focused on a single job rather\n * than growing branches for everything the agent might need to do.\n *\n * The agent passes its jobs to startAgent, each a name with an interval and,\n * optionally, its prompt; without one, the bundled prompt of that name is used.\n * Two environment variables override the schedule, so a deployment can change\n * it without a new image:\n *\n * JOBS comma-separated <name>:<seconds>, e.g. \"take-work:280,settle-due:310\"\n * TICK_INTERVAL_SECONDS 0 runs no jobs at all (something else owns this agent's work)\n *\n * A job JOBS names keeps the prompt the agent gave it.\n */\nimport { redact } from \"./log.js\";\nimport type { TextSource } from \"./prompts.js\";\n\n/** One scheduled job, as an agent passes it to startAgent. */\nexport interface AgentJob {\n /** Seconds between runs, at least ten. */\n interval: number;\n /** The task prompt: text, a path or a file: URL. Default: the bundled prompt of the job's name. */\n prompt?: TextSource;\n}\n\nconst DEFAULT_JOBS: Record<string, AgentJob> = { \"settle-due\": { interval: 300 } };\nconst MIN_INTERVAL_SECONDS = 10;\n\nexport interface JobSpec {\n name: string;\n intervalSeconds: number;\n /** The job's own prompt; undefined means the bundled one named `name`. */\n prompt?: TextSource;\n}\n\nexport interface Jobs {\n stop(): void;\n /** Resolves once every run in flight has finished. */\n whenIdle(): Promise<void>;\n}\n\nconst log = (job: string, message: string) =>\n console.log(`${new Date().toISOString().slice(11, 19)} ${job}: ${redact(message)}`);\n\nfunction spec(name: string, seconds: number, prompt: TextSource | undefined, source: string): JobSpec {\n if (!name || !Number.isFinite(seconds) || seconds < MIN_INTERVAL_SECONDS) {\n throw new Error(`${source}: \"${name}:${seconds}\" is not <name>:<seconds> with seconds >= ${MIN_INTERVAL_SECONDS}.`);\n }\n return prompt === undefined ? { name, intervalSeconds: seconds } : { name, intervalSeconds: seconds, prompt };\n}\n\n/** The jobs to run: JOBS if set, none if TICK_INTERVAL_SECONDS is 0, else the agent's own. */\nexport function resolveJobs(\n own: Record<string, AgentJob> | undefined,\n env: NodeJS.ProcessEnv = process.env,\n): JobSpec[] {\n const raw = env.JOBS?.trim();\n if (raw) {\n return raw\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean)\n .map((entry) => {\n const [name = \"\", seconds = \"\"] = entry.split(\":\").map((part) => part.trim());\n return spec(name, Number(seconds), own?.[name]?.prompt, \"JOBS\");\n });\n }\n if (env.TICK_INTERVAL_SECONDS?.trim() === \"0\") return [];\n return Object.entries(own ?? DEFAULT_JOBS).map(([name, job]) => spec(name, Number(job?.interval), job?.prompt, \"jobs\"));\n}\n\n/**\n * One agent run at a time, across every job in this process.\n *\n * Jobs keep separate schedules but share one key, and two runs signing from it\n * at once produce a nonce error that loses both transactions. Rather than\n * coordinating schedules so they never coincide — which they eventually would\n * anyway — a run waits for whatever is already going.\n */\nlet lock: Promise<void> = Promise.resolve();\n\nexport function exclusive<T>(work: () => Promise<T>): Promise<T> {\n const next = lock.then(work, work);\n lock = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n}\n\n/** Resolves once every run started or queued through `exclusive` so far has finished. */\nexport function whenRunsIdle(): Promise<void> {\n return lock;\n}\n\n/** Runs one job on its interval until stopped. `run` does one round of it. */\nfunction startJob(job: JobSpec, run: (job: JobSpec) => Promise<string>): Jobs {\n let running = true;\n let inFlight: Promise<unknown> = Promise.resolve();\n\n async function once(): Promise<void> {\n try {\n const answer = await exclusive(() => run(job));\n log(job.name, answer || \"(no response)\");\n } catch (error) {\n // A failed run costs one round, not the schedule.\n log(job.name, `failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n async function loop(): Promise<void> {\n log(job.name, `every ${job.intervalSeconds}s`);\n while (running) {\n inFlight = once();\n await inFlight;\n\n // Interruptible, so stopping does not sit out the whole interval.\n const until = Date.now() + job.intervalSeconds * 1000;\n while (running && Date.now() < until) {\n await new Promise((r) => setTimeout(r, Math.min(1000, until - Date.now())));\n }\n }\n log(job.name, \"stopped\");\n }\n\n const finished = loop();\n\n return {\n stop() {\n running = false;\n },\n async whenIdle() {\n await inFlight;\n await finished;\n },\n };\n}\n\n/** Starts every job and returns a handle covering all of them. */\nexport function startJobs(jobs: JobSpec[], run: (job: JobSpec) => Promise<string>): Jobs {\n if (jobs.length === 0) {\n console.log(\"no scheduled jobs — something else owns this agent's work\");\n return { stop() {}, async whenIdle() {} };\n }\n\n const started = jobs.map((job) => startJob(job, run));\n\n return {\n stop: () => started.forEach((job) => job.stop()),\n whenIdle: async () => {\n await Promise.all(started.map((job) => job.whenIdle()));\n },\n };\n}\n","/**\n * Prompts live on disk as plain text, so an operational instruction is a file\n * in version control rather than a string buried in code.\n *\n * The system prompt is assembled from two parts:\n *\n * prompts/common.md (this package) what every Kudo agent is told - the\n * covenant model, the honesty rules, how to work at\n * the shell\n * the agent's own who this one is, and nothing else - passed to\n * system prompt startAgent as `systemPrompt`\n *\n * A job's task prompt is the one the agent gave that job, else this package's\n * prompt of the same name (take-work, settle-due). A prompt that only one agent\n * should run is given only by that agent, so another agent configured to run\n * it fails at startup rather than attempting something it has no business\n * doing — `validate` belongs to the validator, who alone holds the evaluator\n * role.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { PROMPTS_DIR } from \"./paths.js\";\n\nconst SAFE_NAME = /^[a-z0-9][a-z0-9-]*$/i;\n/** `./x`, `../x`, `/x`, or a single word ending in .md or .txt. */\nconst LOOKS_LIKE_PATH = /^(\\.{1,2}\\/|\\/)\\S*$|^\\S+\\.(md|txt)$/i;\n\n/** Text, or a path / file: URL to read it from. */\nexport type TextSource = string | URL;\n\nasync function read(source: TextSource): Promise<string> {\n if (source instanceof URL) return readFile(fileURLToPath(source), \"utf8\");\n // A one-line string naming an existing file is a path; anything else is the text itself.\n if (!source.includes(\"\\n\") && existsSync(source)) return readFile(source, \"utf8\");\n // One that looks like a path but names no file is a typo, not a prompt.\n if (!source.includes(\"\\n\") && LOOKS_LIKE_PATH.test(source.trim())) {\n throw new Error(`Prompt file ${source} does not exist.`);\n }\n return source;\n}\n\n/**\n * The agent's standing instructions: the shared base, then its character.\n *\n * Order matters. The character comes last so that where the two touch - voice,\n * register, what it will and will not claim - the specific one is what the\n * model read most recently.\n */\nexport async function loadSystemPrompt(character: TextSource): Promise<string> {\n const common = await readFile(join(PROMPTS_DIR, \"common.md\"), \"utf8\");\n return `${common.trim()}\\n\\n---\\n\\n${(await read(character)).trim()}`;\n}\n\n/** Task prompts this package ships. */\nexport async function bundledPrompts(): Promise<string[]> {\n return (await readdir(PROMPTS_DIR))\n .filter((f) => f.endsWith(\".txt\"))\n .map((f) => f.replace(/\\.txt$/, \"\"))\n .sort();\n}\n\n/** A job's task prompt: its own if it has one, else this package's prompt of that name. */\nexport async function loadPrompt(name: string, own?: TextSource): Promise<string> {\n if (own !== undefined) return (await read(own)).trim();\n if (!SAFE_NAME.test(name)) {\n throw new Error(`Invalid prompt name \"${name}\" — use letters, digits and dashes.`);\n }\n try {\n return (await readFile(join(PROMPTS_DIR, `${name}.txt`), \"utf8\")).trim();\n } catch {\n throw new Error(\n `Job \"${name}\" has no prompt and none is bundled under that name. Give it a \\`prompt\\`, or use one of: ${(await bundledPrompts()).join(\", \")}.`,\n );\n }\n}\n","/**\n * Where the SDK package's own files are: the bundled task prompts and skills.\n *\n * The code runs from src/ in the workspace and from dist/ once published, so\n * walk up to the package's own package.json rather than assume a depth.\n */\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction findPackageDir(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (;;) {\n const manifest = join(dir, \"package.json\");\n if (existsSync(manifest)) {\n const { name } = JSON.parse(readFileSync(manifest, \"utf8\")) as { name?: string };\n if (name === \"@kudo-dev/sdk\") return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) throw new Error(\"Cannot find the @kudo-dev/sdk package directory.\");\n dir = parent;\n }\n}\n\nexport const PACKAGE_DIR = findPackageDir();\n/** common.md and the task prompts every agent can run. */\nexport const PROMPTS_DIR = join(PACKAGE_DIR, \"prompts\");\n/** The skills this package ships, one folder each. */\nexport const SKILLS_DIR = join(PACKAGE_DIR, \"skills\");\n","/**\n * The HTTP endpoint.\n *\n * POST /message {\"message\": \"...\"} -> {\"response\": \"...\"}\n * GET /identity name, agentId and where to verify the TEE\n * GET /health\n *\n * port startAgent's `port`, else PORT, else 3000\n */\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\n\nimport { health, identity, message, notFound } from \"./handlers.js\";\n\nconst DEFAULT_PORT = 3000;\n\nexport interface RunningServer {\n port: number;\n /** Stops accepting new connections. Requests in flight are left to finish. */\n close(): void;\n}\n\n/** Starts the endpoint. `run` does one agent run for POST /message. */\nexport function startServer(run: (prompt: string) => Promise<string>, port?: number): RunningServer {\n const listenOn = port ?? Number(process.env.PORT?.trim() || DEFAULT_PORT);\n\n const routes = [\n { method: \"GET\", path: \"/health\", handle: health },\n { method: \"GET\", path: \"/identity\", handle: identity },\n {\n method: \"POST\",\n path: \"/message\",\n handle: (request: IncomingMessage, response: ServerResponse) => message(request, response, run),\n },\n ];\n\n function route(request: IncomingMessage, response: ServerResponse): void {\n const match = routes.find(\n (candidate) => candidate.method === request.method && candidate.path === request.url,\n );\n // Handlers may be async; nothing awaits them, so an unhandled rejection\n // would be invisible. Each handler owns its own error reporting.\n void (match ? match.handle(request, response) : notFound(request, response));\n }\n\n const server = createServer(route);\n server.listen(listenOn, () => console.log(`listening on :${listenOn}`));\n\n return {\n port: listenOn,\n close: () => server.close(),\n };\n}\n","/** Small helpers over node:http, so the handlers stay about behaviour. */\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\n/** Caps a request body so a stray upload cannot exhaust memory. */\nconst MAX_BODY_BYTES = 64 * 1024;\n\nexport function sendJson(response: ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body);\n response.writeHead(status, {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": Buffer.byteLength(payload),\n });\n response.end(payload);\n}\n\nexport async function readBody(request: IncomingMessage): Promise<string> {\n const chunks: Buffer[] = [];\n let size = 0;\n\n for await (const chunk of request) {\n size += (chunk as Buffer).length;\n if (size > MAX_BODY_BYTES) throw new Error(\"Request body too large.\");\n chunks.push(chunk as Buffer);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\n/**\n * Removes the socket timeouts for this exchange.\n *\n * One agent run can take minutes — it may be sending transactions and waiting\n * on receipts — and the default timeouts would close the connection first.\n */\nexport function allowLongRun(request: IncomingMessage, response: ServerResponse): void {\n request.setTimeout(0);\n response.setTimeout(0);\n}\n","/** What each endpoint does. */\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport { AgentRunError } from \"../agent.js\";\nimport { redact } from \"../log.js\";\nimport { allowLongRun, readBody, sendJson } from \"./http.js\";\n\nexport function health(_request: IncomingMessage, response: ServerResponse): void {\n sendJson(response, 200, { ok: true });\n}\n\n/**\n * GET /identity — who this agent is and where its attestation can be checked.\n *\n * `attestation` is null outside a TEE. Note that this answer comes from the\n * agent itself, so it is a pointer, not proof: the Trust Center page is where\n * the claim is actually checked, independently of us.\n */\nexport function identity(_request: IncomingMessage, response: ServerResponse): void {\n sendJson(response, 200, {\n name: process.env.AGENT_NAME?.trim() || null,\n agentId: process.env.AGENT_ID?.trim() || null,\n teeId: process.env.TEE_ID?.trim() || null,\n attestation: process.env.TEE_TRUST_URL?.trim() || null,\n // False for a hand-set TEE_ID: the report exists, but describes another app.\n attested: process.env.TEE_ID_SOURCE?.trim() === \"dstack\",\n });\n}\n\nexport function notFound(_request: IncomingMessage, response: ServerResponse): void {\n sendJson(response, 404, { error: \"Not found. Try POST /message, GET /identity or GET /health.\" });\n}\n\n/** POST /message {\"message\": \"...\"} -> {\"response\": \"...\"}. `run` does one agent run. */\nexport async function message(\n request: IncomingMessage,\n response: ServerResponse,\n run: (prompt: string) => Promise<string>,\n): Promise<void> {\n let body: unknown;\n try {\n body = JSON.parse(await readBody(request));\n } catch (error) {\n return sendJson(response, 400, {\n error: error instanceof Error ? error.message : \"Invalid JSON body.\",\n });\n }\n\n const text = (body as { message?: unknown } | null)?.message;\n if (typeof text !== \"string\" || !text.trim()) {\n return sendJson(response, 400, { error: 'Body must be {\"message\": \"<text>\"}.' });\n }\n\n try {\n allowLongRun(request, response);\n sendJson(response, 200, { response: redact(await run(text.trim())) });\n } catch (error) {\n const reason = redact(error instanceof Error ? error.message : String(error));\n console.error(`POST /message failed: ${reason}`);\n\n // A run that started and ended badly is the agent's failure (502); anything\n // else is ours (500).\n sendJson(response, error instanceof AgentRunError ? 502 : 500, { error: reason });\n }\n}\n","/**\n * The skills an agent is given.\n *\n * Every agent gets `kudo` (the public skill: every contract call),\n * `kudo-runtime` (this runtime's environment, USDG payments, tweet legs) and\n * `twitter`. An agent adds more by name — a skill this package ships, such as\n * `kudo-validation` or `chain-forensics` — or by path, for a skill folder of\n * its own.\n *\n * The Agent SDK loads skills from a plugin directory. Rather than hand it every\n * skill this package ships and filter afterwards, the runtime assembles a\n * plugin holding exactly this agent's skills, so a skill it was not given is\n * never loaded at all: `kudo-validation` describes closing covenants, which\n * only the evaluator can do, and handing it to a trader would describe a power\n * it does not have.\n */\nimport { existsSync } from \"node:fs\";\nimport { mkdir, mkdtemp, readdir, symlink, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { basename, isAbsolute, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { SKILLS_DIR } from \"./paths.js\";\n\nexport const DEFAULT_SKILLS = [\"kudo\", \"kudo-runtime\", \"twitter\"];\n\n/** Plugin name; the SDK lists its skills as `kudo:<skill>`. */\nconst PLUGIN_NAME = \"kudo\";\n\n/** A bundled skill's name, or a path (or file: URL) to a skill folder with a SKILL.md. */\nexport type SkillRef = string | URL;\n\n/** Skills this package ships. */\nexport async function bundledSkills(): Promise<string[]> {\n const entries = await readdir(SKILLS_DIR, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => e.name).sort();\n}\n\nfunction resolveSkill(ref: SkillRef): { name: string; dir: string } {\n const isPath = ref instanceof URL || isAbsolute(ref) || ref.startsWith(\".\");\n const dir = ref instanceof URL ? fileURLToPath(ref) : isPath ? resolve(ref) : join(SKILLS_DIR, ref);\n if (!existsSync(join(dir, \"SKILL.md\"))) {\n throw new Error(\n isPath\n ? `Skill folder ${dir} has no SKILL.md.`\n : `No bundled skill \"${ref}\". Bundled: see ${SKILLS_DIR}, or pass a path to your own skill folder.`,\n );\n }\n return { name: basename(dir), dir };\n}\n\nexport interface SkillPlugin {\n /** The plugin directory to pass to the Agent SDK. */\n path: string;\n /** The skills' names as the SDK lists them, `kudo:<skill>`. */\n names: string[];\n}\n\n/** Builds the plugin holding the defaults plus `extra`, in a fresh temp directory. */\nexport async function assembleSkills(extra: SkillRef[] = []): Promise<SkillPlugin> {\n const skills = new Map<string, string>();\n for (const ref of [...DEFAULT_SKILLS, ...extra]) {\n const { name, dir } = resolveSkill(ref);\n const existing = skills.get(name);\n if (existing && existing !== dir) throw new Error(`Two skills are named \"${name}\": ${existing} and ${dir}.`);\n skills.set(name, dir);\n }\n\n const root = await mkdtemp(join(tmpdir(), \"kudo-agent-skills-\"));\n await mkdir(join(root, \".claude-plugin\"));\n await writeFile(\n join(root, \".claude-plugin\", \"plugin.json\"),\n JSON.stringify({ name: PLUGIN_NAME, description: \"Kudo agent skills\", version: \"0.0.0\" }),\n );\n await mkdir(join(root, \"skills\"));\n for (const [name, dir] of skills) await symlink(dir, join(root, \"skills\", name), \"dir\");\n\n return { path: root, names: [...skills.keys()].map((name) => `${PLUGIN_NAME}:${name}`) };\n}\n","import { BaseError, ContractFunctionRevertedError, type Hex } from \"viem\";\n\n/**\n * Revert selectors seen on Kudo deployments, with what each means in practice.\n * Matched by selector because not every error is in the ABI the SDK carries.\n */\nexport const REVERTS: Record<string, { name: string; hint: string }> = {\n \"0x468381ac\": {\n name: \"NotAuthorizedForAgent\",\n hint: \"The sending wallet does not control that ERC-8004 agent id. Mint under an id this wallet owns (see findAgentIds / registerAgent).\",\n },\n \"0xef67f5d8\": {\n name: \"AccessForbidden\",\n hint: \"The caller is not allowed: on mint the wallet lacks AGENT_ROLE (only when mint access control is on); on linkProof the caller is not the covenant's agentWallet.\",\n },\n \"0xe2517d3f\": {\n name: \"AccessControlUnauthorizedAccount\",\n hint: \"An onlyRole function refused this account. Closing a covenant is the Evaluator's job, not the agent's.\",\n },\n \"0x613970e0\": {\n name: \"InvalidParameter\",\n hint: \"The contract rejected an argument, such as an empty string or a zero address.\",\n },\n \"0x356680b7\": {\n name: \"InsufficientFunds\",\n hint: \"The wallet does not hold enough of the token for this transfer.\",\n },\n \"0xe450d38c\": {\n name: \"ERC20InsufficientBalance\",\n hint: \"The wallet does not hold enough of this token for the transfer.\",\n },\n \"0xf480469b\": {\n name: \"ConditionIsNotMet\",\n hint: \"This selector belongs to an older Kudo deployment. You are probably pointing at the wrong contract.\",\n },\n};\n\nexport type KudoErrorCode =\n | \"NO_WALLET\"\n | \"INVALID_INPUT\"\n | \"NOT_AGENT_OWNER\"\n | \"ALREADY_MET\"\n | \"ASK_NOT_MET\"\n | \"ALREADY_PROVEN\"\n | \"NOT_PROMISER\"\n | \"ALREADY_REGISTERED\"\n | \"REVERTED\"\n | \"TX_FAILED\"\n | \"TIMEOUT\"\n | \"NOT_FOUND\";\n\nexport class KudoError extends Error {\n readonly code: KudoErrorCode;\n readonly revert?: { selector?: Hex; name?: string; hint?: string };\n\n constructor(\n code: KudoErrorCode,\n message: string,\n options: { cause?: unknown; revert?: KudoError[\"revert\"] } = {},\n ) {\n super(message, { cause: options.cause });\n this.name = \"KudoError\";\n this.code = code;\n this.revert = options.revert;\n }\n}\n\n/** Turns a viem error into a KudoError that names the revert and what to do about it. */\nexport function toKudoError(error: unknown, action: string): KudoError {\n if (error instanceof KudoError) return error;\n\n let selector: Hex | undefined;\n let name: string | undefined;\n\n if (error instanceof BaseError) {\n const reverted = error.walk((e) => e instanceof ContractFunctionRevertedError);\n if (reverted instanceof ContractFunctionRevertedError) {\n name = reverted.data?.errorName;\n selector = reverted.signature ?? (reverted.raw?.slice(0, 10) as Hex | undefined);\n } else {\n // A raw eth_call (as in simulate) surfaces the revert bytes as `data`\n // on a RawContractError somewhere down the cause chain.\n const raw = error.walk((e) => typeof (e as { data?: unknown }).data === \"string\") as\n | { data?: string }\n | null;\n if (raw?.data && /^0x[0-9a-fA-F]{8}/.test(raw.data)) selector = raw.data.slice(0, 10) as Hex;\n }\n }\n\n const text = error instanceof Error ? error.message : String(error);\n if (!selector) {\n selector = Object.keys(REVERTS).find((s) => text.toLowerCase().includes(s)) as\n | Hex\n | undefined;\n }\n\n const known = selector ? REVERTS[selector.toLowerCase()] : undefined;\n name = name ?? known?.name;\n\n if (name || selector) {\n return new KudoError(\n \"REVERTED\",\n `${action} reverted${name ? ` with ${name}` : \"\"}${known ? `: ${known.hint}` : \".\"}`,\n { cause: error, revert: { selector, name, hint: known?.hint } },\n );\n }\n\n const short = error instanceof BaseError ? error.shortMessage : text;\n return new KudoError(\"TX_FAILED\", `${action} failed: ${short}`, { cause: error });\n}\n","/**\n * Phala dstack: the guest agent inside a TEE (confidential VM) serves key\n * derivation and app info over a Unix socket.\n *\n * A key from dstack is derived from the app's identity inside the enclave, so\n * it never exists outside it and is the same on every restart of the same app.\n * Node only: it talks HTTP over a Unix socket.\n */\nimport { KudoError } from \"./errors.js\";\n\nexport const DSTACK_SOCKET = \"/var/run/dstack.sock\";\n/** The key path the Kudo skill uses, so every integration derives the same wallet. */\nexport const DSTACK_KEY_PATH = \"kudo/agent\";\n\nexport interface DstackOptions {\n /** Default /var/run/dstack.sock. */\n socket?: string;\n timeoutMs?: number;\n}\n\nasync function call<T>(path: string, body: unknown, options: DstackOptions): Promise<T> {\n const { request } = await import(\"node:http\");\n const socketPath = options.socket ?? DSTACK_SOCKET;\n return new Promise<T>((resolve, reject) => {\n const payload = body === undefined ? undefined : JSON.stringify(body);\n const req = request(\n {\n socketPath,\n path,\n method: payload ? \"POST\" : \"GET\",\n headers: payload ? { \"content-type\": \"application/json\", \"content-length\": Buffer.byteLength(payload) } : {},\n timeout: options.timeoutMs ?? 5000,\n },\n (res) => {\n const chunks: Buffer[] = [];\n res.on(\"data\", (c: Buffer) => chunks.push(c));\n res.on(\"end\", () => {\n if (res.statusCode !== 200) return reject(new KudoError(\"NOT_FOUND\", `dstack ${path} returned ${res.statusCode}.`));\n try {\n resolve(JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as T);\n } catch {\n reject(new KudoError(\"NOT_FOUND\", `dstack ${path} did not return JSON.`));\n }\n });\n },\n );\n req.on(\"timeout\", () => req.destroy(new Error(\"timed out\")));\n req.on(\"error\", (e) =>\n reject(new KudoError(\"NOT_FOUND\", `Cannot reach dstack at ${socketPath} (${e.message}). Is this running in a Phala TEE?`)),\n );\n req.end(payload);\n });\n}\n\n/** Derives this app's secp256k1 key from dstack. Never log the result. */\nexport async function dstackPrivateKey(path = DSTACK_KEY_PATH, options: DstackOptions = {}): Promise<`0x${string}`> {\n const { key } = await call<{ key?: string }>(\"/GetKey\", { path, purpose: \"signing\" }, options);\n const hex = (key ?? \"\").replace(/^0x/i, \"\");\n if (!/^[0-9a-fA-F]{64}$/.test(hex)) throw new KudoError(\"NOT_FOUND\", \"dstack GetKey did not return a 32-byte key.\");\n return `0x${hex}`;\n}\n\n/** The Phala app id (bare lowercase hex), the id a Trust Center report is published under. */\nexport async function dstackAppId(options: DstackOptions = {}): Promise<string> {\n const { app_id } = await call<{ app_id?: string }>(\"/Info\", undefined, options);\n if (!app_id) throw new KudoError(\"NOT_FOUND\", \"dstack Info returned no app_id.\");\n return app_id.replace(/^0x/i, \"\").toLowerCase();\n}\n","/**\n * Where this agent is running.\n *\n * On Phala, dstack exposes a Unix socket inside the confidential VM. Its Info\n * endpoint returns the app id — the same string Phala's Trust Center uses in\n * its report URL. Publishing that id as identity metadata hands a counterparty\n * a page where they can check the hardware attestation, the OS image and the\n * compose file themselves, instead of taking our word for any of it.\n *\n * Outside a TEE there is no app id. That is not an error: the agent runs\n * locally with no attestation to offer, and says as much.\n */\nimport { dstackAppId } from \"../dstack.js\";\n\nconst TRUST_CENTER = \"https://trust.phala.com/app\";\nconst INFO_TIMEOUT_MS = 2000;\n\nexport interface TeeIdentity {\n /** Phala app id, bare lowercase hex. */\n teeId: string;\n /** Trust Center report for that app id. */\n trustCenterUrl: string;\n /**\n * `dstack` means the enclave told us its own id, so the report describes this\n * process. `environment` means a human put the id there — it names some other\n * app, and attests nothing about this run.\n */\n source: \"dstack\" | \"environment\";\n}\n\n/** Trust Center paths carry bare hex; dstack and block explorers use `0x`. */\nfunction bareHex(appId: string): string {\n return appId.trim().replace(/^0x/i, \"\").toLowerCase();\n}\n\nasync function appIdFromDstack(): Promise<string | undefined> {\n try {\n return await dstackAppId({ timeoutMs: INFO_TIMEOUT_MS });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n console.log(`no dstack socket (${reason}) — looking at the environment instead`);\n return undefined;\n }\n}\n\n/**\n * The app id from dstack, or from the environment when we are not in a CVM.\n *\n * `DSTACK_APP_ID` is set by Phala's own pre-launch script; `TEE_ID` is ours,\n * for pointing a local run at an already-deployed app's report.\n */\nexport async function resolveTeeIdentity(): Promise<TeeIdentity | undefined> {\n const attested = await appIdFromDstack();\n const appId =\n attested || process.env.DSTACK_APP_ID?.trim() || process.env.TEE_ID?.trim();\n\n if (!appId) return undefined;\n\n const teeId = bareHex(appId);\n return {\n teeId,\n trustCenterUrl: `${TRUST_CENTER}/${teeId}`,\n source: attested ? \"dstack\" : \"environment\",\n };\n}\n"],"mappings":"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","names":["existsSync","dirname","join","resolve","fileURLToPath","message","log","message","log","message","existsSync","readFile","join","fileURLToPath","join","readFile","fileURLToPath","existsSync","join","existsSync","mkdtemp","readdir","tmpdir","join","fileURLToPath","readdir","fileURLToPath","join","existsSync","mkdtemp","tmpdir","message","resolve","dirname","fileURLToPath","existsSync","resolve","join"]}