repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources15d ago| #1 | #!/usr/bin/env node |
| #2 | |
| #3 | import chalk from 'chalk'; |
| #4 | import { |
| #5 | buildAgentMetadata, |
| #6 | formatAgentError, |
| #7 | inferNetwork, |
| #8 | mintRegisteredAgent, |
| #9 | readRegisteredAgent, |
| #10 | type AgentServiceInput, |
| #11 | } from './metaplex-agent.js'; |
| #12 | |
| #13 | type Args = Record<string, string | boolean | string[]>; |
| #14 | |
| #15 | function parseArgs(argv: string[]): { command: string; args: Args } { |
| #16 | const [command = 'help', ...rest] = argv; |
| #17 | const args: Args = {}; |
| #18 | |
| #19 | for (let i = 0; i < rest.length; i++) { |
| #20 | const token = rest[i]!; |
| #21 | if (!token.startsWith('--')) continue; |
| #22 | const key = token.slice(2); |
| #23 | const next = rest[i + 1]; |
| #24 | const value = !next || next.startsWith('--') ? true : (i++, next); |
| #25 | if (args[key] === undefined) { |
| #26 | args[key] = value; |
| #27 | } else if (Array.isArray(args[key])) { |
| #28 | (args[key] as string[]).push(String(value)); |
| #29 | } else { |
| #30 | args[key] = [String(args[key]), String(value)]; |
| #31 | } |
| #32 | } |
| #33 | |
| #34 | return { command, args }; |
| #35 | } |
| #36 | |
| #37 | function str(args: Args, key: string): string | undefined { |
| #38 | const value = args[key]; |
| #39 | return typeof value === 'string' ? value : undefined; |
| #40 | } |
| #41 | |
| #42 | function bool(args: Args, key: string): boolean { |
| #43 | return args[key] === true || args[key] === 'true'; |
| #44 | } |
| #45 | |
| #46 | function list(args: Args, key: string): string[] { |
| #47 | const value = args[key]; |
| #48 | if (!value) return []; |
| #49 | return Array.isArray(value) ? value : [String(value)]; |
| #50 | } |
| #51 | |
| #52 | function parseServices(values: string[]): AgentServiceInput[] { |
| #53 | return values.map((value) => { |
| #54 | const [name, endpoint, version] = value.split('='); |
| #55 | if (!name || !endpoint) { |
| #56 | throw new Error(`Invalid --service "${value}". Use name=https://endpoint[/path]`); |
| #57 | } |
| #58 | return { name, endpoint, version }; |
| #59 | }); |
| #60 | } |
| #61 | |
| #62 | function requireArg(args: Args, key: string): string { |
| #63 | const value = str(args, key); |
| #64 | if (!value) throw new Error(`Missing required --${key}`); |
| #65 | return value; |
| #66 | } |
| #67 | |
| #68 | function usage(): void { |
| #69 | process.stdout.write(`${chalk.cyanBright.bold('clawd-agent')}\n\n`); |
| #70 | process.stdout.write('Mint and inspect Metaplex Agent Registry identities.\n\n'); |
| #71 | process.stdout.write(`${chalk.white.bold('Commands')}\n`); |
| #72 | process.stdout.write(' mint Mint a new MPL Core asset and register Agent Identity in one call\n'); |
| #73 | process.stdout.write(' mint-free Ask the hosted Clawd gateway to gaslessly mint a registered agent\n'); |
| #74 | process.stdout.write(' read Read a registered agent and derive its PDA wallet\n'); |
| #75 | process.stdout.write(' metadata Generate EIP-8004 agent registration JSON\n\n'); |
| #76 | process.stdout.write(`${chalk.white.bold('Mint example')}\n`); |
| #77 | process.stdout.write(' clawd-agent mint --network devnet --keypair ~/.config/solana/id.json \\\n'); |
| #78 | process.stdout.write(' --name "My AI Agent" --uri https://example.com/agent-nft.json \\\n'); |
| #79 | process.stdout.write(' --description "Autonomous Solana agent" --service MCP=https://example.com/mcp --yes\n\n'); |
| #80 | process.stdout.write(`${chalk.white.bold('Hosted free mint example')}\n`); |
| #81 | process.stdout.write(' clawd-agent mint-free --network devnet --owner <YOUR_SOLANA_PUBKEY> \\\n'); |
| #82 | process.stdout.write(' --name "My AI Agent" --uri https://example.com/agent-nft.json \\\n'); |
| #83 | process.stdout.write(' --description "Autonomous Solana agent" --service MCP=https://example.com/mcp\n\n'); |
| #84 | } |
| #85 | |
| #86 | async function main(): Promise<void> { |
| #87 | const { command, args } = parseArgs(process.argv.slice(2)); |
| #88 | |
| #89 | if (command === 'help' || command === '--help' || command === '-h') { |
| #90 | usage(); |
| #91 | return; |
| #92 | } |
| #93 | |
| #94 | if (command === 'metadata') { |
| #95 | const metadata = buildAgentMetadata({ |
| #96 | name: requireArg(args, 'name'), |
| #97 | description: requireArg(args, 'description'), |
| #98 | image: str(args, 'image'), |
| #99 | services: parseServices(list(args, 'service')), |
| #100 | supportedTrust: list(args, 'trust'), |
| #101 | x402Support: !bool(args, 'no-x402'), |
| #102 | }); |
| #103 | process.stdout.write(`${JSON.stringify(metadata, null, 2)}\n`); |
| #104 | return; |
| #105 | } |
| #106 | |
| #107 | if (command === 'read') { |
| #108 | const network = inferNetwork(str(args, 'network') ?? 'devnet'); |
| #109 | const result = await readRegisteredAgent({ |
| #110 | assetAddress: requireArg(args, 'asset'), |
| #111 | rpcUrl: str(args, 'rpc'), |
| #112 | network, |
| #113 | }); |
| #114 | process.stdout.write(`${JSON.stringify(result, null, 2)}\n`); |
| #115 | return; |
| #116 | } |
| #117 | |
| #118 | if (command === 'mint') { |
| #119 | const network = inferNetwork(str(args, 'network') ?? 'devnet'); |
| #120 | if (network === 'solana-mainnet' && !bool(args, 'yes')) { |
| #121 | throw new Error('Mainnet mint requires --yes. Devnet is the default for first runs.'); |
| #122 | } |
| #123 | if (!bool(args, 'yes')) { |
| #124 | throw new Error('Minting creates a real on-chain agent. Pass --yes to submit the transaction.'); |
| #125 | } |
| #126 | |
| #127 | const result = await mintRegisteredAgent({ |
| #128 | keypairPath: requireArg(args, 'keypair'), |
| #129 | rpcUrl: str(args, 'rpc'), |
| #130 | network, |
| #131 | name: requireArg(args, 'name'), |
| #132 | uri: requireArg(args, 'uri'), |
| #133 | description: requireArg(args, 'description'), |
| #134 | image: str(args, 'image'), |
| #135 | services: parseServices(list(args, 'service')), |
| #136 | supportedTrust: list(args, 'trust'), |
| #137 | x402Support: !bool(args, 'no-x402'), |
| #138 | baseUrl: str(args, 'api-base-url'), |
| #139 | }); |
| #140 | process.stdout.write(`${JSON.stringify(result, null, 2)}\n`); |
| #141 | return; |
| #142 | } |
| #143 | |
| #144 | if (command === 'mint-free') { |
| #145 | const network = str(args, 'network') ?? 'devnet'; |
| #146 | if (network === 'mainnet' && !bool(args, 'yes')) { |
| #147 | throw new Error('Mainnet hosted mint requires --yes.'); |
| #148 | } |
| #149 | const gateway = str(args, 'gateway') ?? 'https://clawd-agent-gateway.fly.dev'; |
| #150 | const response = await fetch(`${gateway.replace(/\/$/, '')}/api/mint/agent/registered`, { |
| #151 | method: 'POST', |
| #152 | headers: { 'Content-Type': 'application/json' }, |
| #153 | body: JSON.stringify({ |
| #154 | network, |
| #155 | ownerPubkey: requireArg(args, 'owner'), |
| #156 | name: requireArg(args, 'name'), |
| #157 | metadataUri: requireArg(args, 'uri'), |
| #158 | description: requireArg(args, 'description'), |
| #159 | services: parseServices(list(args, 'service')), |
| #160 | confirm_mainnet: bool(args, 'yes'), |
| #161 | }), |
| #162 | }); |
| #163 | const payload = await response.json() as unknown; |
| #164 | if (!response.ok) { |
| #165 | throw new Error(JSON.stringify(payload, null, 2)); |
| #166 | } |
| #167 | process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`); |
| #168 | return; |
| #169 | } |
| #170 | |
| #171 | throw new Error(`Unknown command "${command}"`); |
| #172 | } |
| #173 | |
| #174 | main().catch((err) => { |
| #175 | process.stderr.write(`${chalk.red('error:')} ${formatAgentError(err)}\n`); |
| #176 | process.exit(1); |
| #177 | }); |
| #178 |