// `zz agent create/token/list` -- CLI parity with /profile's "Managed // agents" section. Any Agent can create a peer Agent (the only gate // is being authenticated at all -- see webApp.ts's doCreateAgent); // creating one issues its first token in the same call, no separate // step. Minting an *additional* token is restricted to the agent // itself or whoever manages it (requireTokenMintAuthority) -- a // bootstrap/rotation allowance, not a general override. import { apiFetch } from "../lib/api.js"; // A local, minimal shape matching worker/src/accountsDb.ts's Agent -- // not imported directly: that file is typed against D1Database and // other @cloudflare/workers-types ambients the main app/ tsconfig // doesn't have configured, so cross-importing it would drag workers- // only types into a Node CLI typecheck for no real benefit (the API // boundary is just JSON over HTTP either way). `username` is the only // identifier -- there's no separate internal id anymore (see worker // migration 0006): a human's is their email; a managed agent's chains // off its creator's, e.g. "thoward37@gmail.com[claude]" (see // accountsDb.ts's computeUsername). interface Agent { display_name: string; email: string | null; username: string; created_at: string; created_by: string | null; } interface MintTokenResponse { agent: Agent; token: string; } // `zz work --as ` (and `zz review`/`zz repo submit`) don't need // a token from here at all -- they mint a fresh one on start and // revoke it on exit, using your own `zz login` session's mint // authority (lib/identity.ts). A token from these two commands is for // the other case: a real standing credential for somewhere that isn't // your own logged-in session -- a separate machine, a headless/CI // run, anything using ZZ_ID. function printZzId(username: string, token: string): void { console.log(`For a separate machine or headless run, set: ZZ_ID="${username}:${token}"`); } export async function agentCreate(displayName: string): Promise { const { token, ...agent } = await apiFetch("POST", "/api/agents", { display_name: displayName }); console.log(`Created agent ${agent.username}. Its first token -- copy it now, it won't be shown again:`); console.log(token); console.log(`Issue another with: zz agent token ${agent.username}`); printZzId(agent.username, token); } export async function agentToken(usernameOrId: string): Promise { const { agent, token } = await apiFetch("POST", `/api/agents/${encodeURIComponent(usernameOrId)}/tokens`); console.log(`Token for ${agent.username} -- copy it now, it won't be shown again:`); console.log(token); printZzId(agent.username, token); } export async function agentList(): Promise { const { you, created } = await apiFetch<{ you: Agent; created: Agent[] }>("GET", "/api/agents"); console.log(`${you.username} -- you`); for (const a of created) console.log(`${a.username} -- managed by you`); if (created.length === 0) console.log("(no managed agents yet -- zz agent create )"); }