#!/usr/bin/env bun import type { Command } from '../src/index.ts'; import { run } from '../src/index.ts'; import { createSkillClient } from '../src/auth-cli.ts'; const SKILL_NAME = 'my-skill'; // TODO: replace with actual skill name function printUsage(): void { console.error(`Usage: bun scripts/run.ts [--api-base=] [args...] [--dry-run] Commands: run Config: ~/.openclaw/.env (CLIENT_KEY) `); } async function reportHook( hookUrl: string, hookToken: string | undefined, payload: object, ): Promise { const headers: Record = { 'Content-Type': 'application/json' }; if (hookToken) headers['Authorization'] = `Bearer ${hookToken}`; await fetch(hookUrl, { method: 'POST', headers, body: JSON.stringify(payload) }); } async function main(): Promise { const positionals: string[] = []; let dryRun = false; for (const arg of process.argv.slice(2)) { if (arg === '--dry-run') { dryRun = true; } else if (arg.startsWith('--api-base=')) { process.env.API_BASE = arg.slice('--api-base='.length).trim(); } else if (arg === '-h' || arg === '--help') { printUsage(); process.exit(0); } else { positionals.push(arg); } } if (positionals.length < 1) { printUsage(); process.exit(1); } const command = positionals[0] as Command; // Exchange CLIENT_KEY for session — gives us hookUrl for telemetry let hookUrl: string | undefined; let hookToken: string | undefined; try { const client = createSkillClient({ dryRun }); const session = await client.session(); hookUrl = session.hookUrl; hookToken = session.hookToken; } catch { // Auth failure is non-fatal for telemetry; skill still runs } const startMs = Date.now(); let result: Awaited>; try { result = await run(command, positionals.slice(1), dryRun); } catch (err) { const error = err instanceof Error ? err.message : String(err); const failed = { status: 'failed' as const, command, dryRun, error }; console.log(JSON.stringify(failed, null, 2)); if (hookUrl && !dryRun) { reportHook(hookUrl, hookToken, { skill: SKILL_NAME, command, status: 'failed', durationMs: Date.now() - startMs, error, }).catch(() => {}); } process.exit(1); } console.log(JSON.stringify(result, null, 2)); // Fire-and-forget telemetry — never delays output if (hookUrl && !dryRun) { reportHook(hookUrl, hookToken, { skill: SKILL_NAME, command, status: result.status, durationMs: Date.now() - startMs, error: (result as any).error, }).catch(() => {}); } } main().catch((err) => { console.error(JSON.stringify({ status: 'failed', error: err instanceof Error ? err.message : String(err) }, null, 2)); process.exit(1); });