MCPcopy Index your code
hub / github.com/BlockRunAI/ClawRouter / cmdPhone

Function cmdPhone

src/cli.ts:380–504  ·  view source on GitHub ↗

* `clawrouter phone ...` — wallet-facing phone CLI. * * All operations POST to the local proxy at `/v1/phone/...` (or `/v1/voice/...`), * which transparently handles x402 payment via the wallet. The CLI just renders * upstream JSON in a human format.

(
  port: number,
  subcommand: "numbers" | "lookup" | "fraud",
  numbersAction: "list" | "buy" | "renew" | "release" | undefined,
  arg: string | undefined,
  areaCode: string | undefined,
)

Source from the content-addressed store, hash-verified

378 * upstream JSON in a human format.
379 */
380async function cmdPhone(
381 port: number,
382 subcommand: "numbers" | "lookup" | "fraud",
383 numbersAction: "list" | "buy" | "renew" | "release" | undefined,
384 arg: string | undefined,
385 areaCode: string | undefined,
386): Promise<void> {
387 const base = `http://127.0.0.1:${port}`;
388
389 async function postJson(path: string, body: unknown): Promise<unknown> {
390 const resp = await fetch(`${base}${path}`, {
391 method: "POST",
392 headers: { "content-type": "application/json" },
393 body: JSON.stringify(body),
394 });
395 const text = await resp.text();
396 if (!resp.ok) {
397 if (resp.status === 402) {
398 throw new Error(
399 `Insufficient wallet balance (HTTP 402). Fund wallet via clawrouter wallet.\n${text}`,
400 );
401 }
402 throw new Error(`HTTP ${resp.status}: ${text}`);
403 }
404 try {
405 return JSON.parse(text);
406 } catch {
407 return text;
408 }
409 }
410
411 function fmtExpiry(expiresAt: string): string {
412 const ms = new Date(expiresAt).getTime();
413 if (!Number.isFinite(ms)) return expiresAt;
414 const days = Math.round((ms - Date.now()) / (1000 * 60 * 60 * 24));
415 const dateStr = new Date(ms).toISOString().split("T")[0];
416 if (days < 0) return `${dateStr} (expired ${-days}d ago)`;
417 if (days <= 2) return `${dateStr} (in ${days}d) ⚠ renew soon`;
418 return `${dateStr} (in ${days}d)`;
419 }
420
421 try {
422 if (subcommand === "numbers") {
423 if (!numbersAction || numbersAction === "list") {
424 const result = (await postJson("/v1/phone/numbers/list", {})) as {
425 numbers?: Array<{ phone_number: string; expires_at: string; country?: string }>;
426 };
427 const numbers = result.numbers ?? [];
428 if (numbers.length === 0) {
429 console.log("\nNo phone numbers owned by this wallet.\n");
430 console.log("Buy one with: clawrouter phone numbers buy US [--area-code 415]\n");
431 return;
432 }
433 console.log(`\nActive numbers (${numbers.length}):\n`);
434 const numWidth = Math.max(...numbers.map((n) => n.phone_number.length), 16);
435 for (const n of numbers) {
436 const country = (n.country ?? "??").padEnd(3);
437 console.log(

Callers 1

mainFunction · 0.85

Calls 2

fmtExpiryFunction · 0.85
postJsonFunction · 0.70

Tested by

no test coverage detected