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 | /** |
| #2 | * OpenClawd SDK Introspection |
| #3 | * |
| #4 | * Reads package metadata from the monorepo packages without importing them |
| #5 | * at runtime (avoids dependency resolution issues). Also probes the |
| #6 | * agentwallet vault directory for wallet addresses. |
| #7 | */ |
| #8 | |
| #9 | import { readFile, readdir } from 'node:fs/promises'; |
| #10 | import { existsSync } from 'node:fs'; |
| #11 | import { homedir } from 'node:os'; |
| #12 | import { dirname, join, resolve } from 'node:path'; |
| #13 | import { fileURLToPath } from 'node:url'; |
| #14 | |
| #15 | // ─── Known SDK constants (inline to avoid circular deps) ───────────────────── |
| #16 | |
| #17 | export const CLAWD_MINT = '8cHzQHUS2s2h8TzCmfqPKYiM4dSt4roa3n7MyRLApump'; |
| #18 | export const CLAWD_PROTOCOL_PROGRAM = 'CLAWDpRoToCoLv1pRoGRaM111111111111111111111'; |
| #19 | export const DBC_PROGRAM = 'dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN'; |
| #20 | export const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; |
| #21 | export const TOKEN_2022_PROGRAM = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'; |
| #22 | |
| #23 | // ─── Package registry ───────────────────────────────────────────────────────── |
| #24 | |
| #25 | export interface PackageInfo { |
| #26 | alias: string; |
| #27 | name: string; |
| #28 | version: string; |
| #29 | description: string; |
| #30 | status: 'ok' | 'missing' | 'no-dist'; |
| #31 | hasDist: boolean; |
| #32 | binaries: string[]; |
| #33 | path: string; |
| #34 | } |
| #35 | |
| #36 | const TUI_SRC_DIR = dirname(fileURLToPath(import.meta.url)); |
| #37 | const REPO_ROOT = resolve(TUI_SRC_DIR, '../..'); |
| #38 | |
| #39 | const PACKAGE_DIRS: Record<string, string> = { |
| #40 | clawd: 'packages/clawd', |
| #41 | 'clawd-sdk': 'packages/clawd-sdk', |
| #42 | 'clawd-perps': 'packages/clawd-perps', |
| #43 | 'clawd-wallet': 'packages/clawd-wallet', |
| #44 | agentwallet: 'packages/agentwallet', |
| #45 | 'cli-standalone': 'packages/cli-standalone', |
| #46 | 'x402-client': 'x402/sdk', |
| #47 | }; |
| #48 | |
| #49 | const SDK_NPM_PACKAGES = [ |
| #50 | '@openclawdsolana/clawd-tui', |
| #51 | '@openclawdsolana/clawd', |
| #52 | '@openclawdsolana/clawd-sdk', |
| #53 | '@openclawdsolana/clawd-standalone', |
| #54 | 'x402.wtf', |
| #55 | '@openclawdsolana/clawd-wallet', |
| #56 | 'clawd-automaton', |
| #57 | 'x402agent-nanoclawd-cli', |
| #58 | '@openclawdsolana/clawd-perps', |
| #59 | ]; |
| #60 | |
| #61 | async function loadLocalPackage(alias: string, dir: string): Promise<PackageInfo> { |
| #62 | const pkgDir = join(REPO_ROOT, dir); |
| #63 | const pkgJson = join(pkgDir, 'package.json'); |
| #64 | const missing: PackageInfo = { alias, name: alias, version: '-', description: 'not found', status: 'missing', hasDist: false, binaries: [], path: pkgDir }; |
| #65 | if (!existsSync(pkgJson)) return missing; |
| #66 | try { |
| #67 | const raw = JSON.parse(await readFile(pkgJson, 'utf8')) as { name?: string; version?: string; description?: string; bin?: Record<string, string> }; |
| #68 | const hasDist = existsSync(join(pkgDir, 'dist')); |
| #69 | return { alias, name: raw.name ?? alias, version: raw.version ?? '?', description: (raw.description ?? '').slice(0, 72), status: hasDist ? 'ok' : 'no-dist', hasDist, binaries: raw.bin ? Object.keys(raw.bin) : [], path: pkgDir }; |
| #70 | } catch { |
| #71 | return { ...missing, version: '?', description: 'read error' }; |
| #72 | } |
| #73 | } |
| #74 | |
| #75 | async function loadNpmPackage(name: string): Promise<PackageInfo> { |
| #76 | const pkgDir = join(REPO_ROOT, 'sdk', 'node_modules', name); |
| #77 | const pkgJson = join(pkgDir, 'package.json'); |
| #78 | const alias = `npm:${name}`; |
| #79 | const missing: PackageInfo = { alias, name, version: '-', description: 'not installed in sdk/node_modules', status: 'missing', hasDist: false, binaries: [], path: pkgDir }; |
| #80 | if (!existsSync(pkgJson)) return missing; |
| #81 | try { |
| #82 | const raw = JSON.parse(await readFile(pkgJson, 'utf8')) as { version?: string; description?: string; bin?: string | Record<string, string> }; |
| #83 | const hasDist = existsSync(join(pkgDir, 'dist')); |
| #84 | const binaries = typeof raw.bin === 'string' ? [name.split('/').pop() ?? name] : Object.keys(raw.bin ?? {}); |
| #85 | const binTargets = typeof raw.bin === 'string' ? [raw.bin] : Object.values(raw.bin ?? {}); |
| #86 | const hasBinTargets = binTargets.length > 0 && binTargets.every(t => existsSync(join(pkgDir, t))); |
| #87 | return { alias, name, version: raw.version ?? '?', description: (raw.description ?? 'sdk npm dependency').slice(0, 72), status: hasDist || binaries.length === 0 || hasBinTargets ? 'ok' : 'no-dist', hasDist, binaries, path: pkgDir }; |
| #88 | } catch { |
| #89 | return { ...missing, version: '?', description: 'read error' }; |
| #90 | } |
| #91 | } |
| #92 | |
| #93 | export async function loadPackageInfo(): Promise<PackageInfo[]> { |
| #94 | const local = await Promise.all(Object.entries(PACKAGE_DIRS).map(([alias, dir]) => loadLocalPackage(alias, dir))); |
| #95 | const npm = await Promise.all(SDK_NPM_PACKAGES.map(name => loadNpmPackage(name))); |
| #96 | return [...local, ...npm]; |
| #97 | } |
| #98 | |
| #99 | // ─── Wallet vault reader ────────────────────────────────────────────────────── |
| #100 | |
| #101 | export interface VaultWallet { |
| #102 | id: string; |
| #103 | label: string; |
| #104 | chainType: string; |
| #105 | address: string; |
| #106 | paused: boolean; |
| #107 | createdAt: string; |
| #108 | } |
| #109 | |
| #110 | export interface VaultInfo { |
| #111 | available: boolean; |
| #112 | path: string; |
| #113 | wallets: VaultWallet[]; |
| #114 | error?: string; |
| #115 | } |
| #116 | |
| #117 | export async function readVaultInfo(): Promise<VaultInfo> { |
| #118 | const vaultPath = process.env.VAULT_PATH ?? join(homedir(), '.agentwallet', 'vault'); |
| #119 | |
| #120 | if (!existsSync(vaultPath)) { |
| #121 | return { available: false, path: vaultPath, wallets: [], error: 'Vault directory not found' }; |
| #122 | } |
| #123 | |
| #124 | try { |
| #125 | const files = await readdir(vaultPath); |
| #126 | const jsonFiles = files.filter(f => f.endsWith('.json') && f !== 'index.json'); |
| #127 | const wallets: VaultWallet[] = []; |
| #128 | |
| #129 | for (const file of jsonFiles.slice(0, 20)) { |
| #130 | try { |
| #131 | const raw = JSON.parse(await readFile(join(vaultPath, file), 'utf8')) as { |
| #132 | id?: string; |
| #133 | label?: string; |
| #134 | chainType?: string; |
| #135 | address?: string; |
| #136 | paused?: boolean; |
| #137 | createdAt?: string; |
| #138 | }; |
| #139 | if (raw.address) { |
| #140 | wallets.push({ |
| #141 | id: raw.id ?? file, |
| #142 | label: raw.label ?? 'unnamed', |
| #143 | chainType: raw.chainType ?? 'solana', |
| #144 | address: raw.address, |
| #145 | paused: raw.paused ?? false, |
| #146 | createdAt: raw.createdAt ?? '', |
| #147 | }); |
| #148 | } |
| #149 | } catch { |
| #150 | // skip malformed entries |
| #151 | } |
| #152 | } |
| #153 | |
| #154 | return { available: true, path: vaultPath, wallets }; |
| #155 | } catch (e) { |
| #156 | return { available: false, path: vaultPath, wallets: [], error: String(e) }; |
| #157 | } |
| #158 | } |
| #159 | |
| #160 | // ─── Env variable probe ─────────────────────────────────────────────────────── |
| #161 | |
| #162 | export interface EnvProbe { |
| #163 | key: string; |
| #164 | label: string; |
| #165 | set: boolean; |
| #166 | preview?: string; |
| #167 | } |
| #168 | |
| #169 | export function probeEnv(): EnvProbe[] { |
| #170 | const vars: Array<[string, string]> = [ |
| #171 | ['SOLANA_RPC_URL', 'RPC endpoint'], |
| #172 | ['HELIUS_API_KEY', 'Helius API key'], |
| #173 | ['CLAWD_PERPS_WALLET', 'Perps wallet key'], |
| #174 | ['CLAWD_PERPS_API_URL', 'Perps API URL'], |
| #175 | ['VAULT_PASSPHRASE', 'Vault passphrase'], |
| #176 | ['OPENAI_API_KEY', 'OpenAI API key'], |
| #177 | ['ANTHROPIC_API_KEY', 'Anthropic API key'], |
| #178 | ['OPENROUTER_API_KEY', 'OpenRouter API key'], |
| #179 | ['OPENROUTER_MODEL', 'OpenRouter model (e.g. x-ai/grok-build-0.1)'], |
| #180 | ['LIVE_TRADING', 'Live trading flag'], |
| #181 | ['OPERATOR_CONFIRMED', 'Operator confirmed'], |
| #182 | ['BAGS_API_KEY', 'Bags.fm API key'], |
| #183 | ['TELEGRAM_BOT_TOKEN', 'Telegram bot token'], |
| #184 | ['X402_DEV_KEY', 'x402 developer key'], |
| #185 | ['X402_API_KEY', 'x402 API key'], |
| #186 | ]; |
| #187 | |
| #188 | return vars.map(([key, label]) => { |
| #189 | const val = process.env[key]; |
| #190 | const set = val !== undefined && val !== ''; |
| #191 | let preview: string | undefined; |
| #192 | if (set && val) { |
| #193 | if (key.toLowerCase().includes('key') || key.toLowerCase().includes('passphrase') || key.toLowerCase().includes('wallet')) { |
| #194 | preview = `${val.slice(0, 4)}…${val.slice(-4)}`; |
| #195 | } else { |
| #196 | preview = `${val.slice(0, 24)}${val.length > 24 ? '…' : ''}`; |
| #197 | } |
| #198 | } |
| #199 | return { key, label, set, preview }; |
| #200 | }); |
| #201 | } |
| #202 | |
| #203 | export function shortAddress(address: string, edge = 6): string { |
| #204 | if (address.length <= edge * 2 + 1) return address; |
| #205 | return `${address.slice(0, edge)}...${address.slice(-edge)}`; |
| #206 | } |
| #207 |