app/cli/commands/ask-claim.ts
zzmq.dev@gmail.com/zz / app / cli / commands / ask-claim.ts
@ 08379230
Download
Ladder Summary
- file The file implements the `zz ask claim` CLI command, which lets a human contributor claim an existing Ask in a repository, creates a new work Lane for that Ask, and prints the Lane ID for subsequent submission. It exports the `AskClaimOptions` interface and the async `askClaim(slug, askId, opts)` function that resolves the user’s identity, calls remote tools to verify the Ask, claim it, and propose a new Lane.
// `zz ask claim <owner/repo> <ask-id>`: the human-contributor
// counterpart to agent/scriptedWork.ts's own claim step
// (runContributorWorkAsk's `ask_claim` call) -- claims an Ask by hand,
// then opens a new Lane for the work ("my workstream", in the demo's
// own words), directly in the same repo (no sharding/forking -- that's
// the remote-autonomous-agent path's own thing, not this one, since a
// human doing this by hand clones and commits straight into the repo
// they were granted access to). Prints the new Lane's id, since
// `zz repo submit` needs it next.
import { resolveIdentity, releaseIdentity } from "../lib/identity.js";
import { setActiveToken } from "../lib/api.js";
import { callRemoteTool } from "../lib/remoteTools.js";
import type { AskEntry, Lane } from "../../engine/types.js";
export interface AskClaimOptions {
/** Which Lane the ask lives in -- defaults to "_repo", where `zz repo ask` always posts. */
lane?: string;
/** --as <name>: claim as a managed agent instead of yourself -- see WorkOptions.as (work.ts) / lib/identity.ts for the full resolution order. */
as?: string;
}
export async function askClaim(slug: string, askId: string, opts: AskClaimOptions): Promise<void> {
const identity = await resolveIdentity(opts.as);
setActiveToken(identity.token);
let cleanedUp = false;
const cleanup = async (): Promise<void> => {
if (cleanedUp) return;
cleanedUp = true;
await releaseIdentity(identity);
};
process.on("SIGINT", () => void cleanup().then(() => process.exit(0)));
process.on("SIGTERM", () => void cleanup().then(() => process.exit(0)));
try {
const laneId = opts.lane ?? "_repo";
const lane = (await callRemoteTool(slug, "lane_get", { lane_id: laneId })) as Lane | null;
if (!lane) throw new Error(`no such lane "${laneId}" in ${slug}`);
const theAsk = lane.history.find((e): e is AskEntry => e.type === "ASK" && e.id === askId);
if (!theAsk) throw new Error(`no such ask "${askId}" in ${slug}/${laneId}`);
const description = (theAsk.payload as { description?: string } | undefined)?.description ?? JSON.stringify(theAsk.payload);
await callRemoteTool(slug, "ask_claim", { lane_id: laneId, ask_id: askId, actor: identity.username });
const workLane = (await callRemoteTool(slug, "lane_propose", {
name: description.slice(0, 60),
objective: description,
scope: ["**"],
actor: identity.username,
origin_lane: laneId,
})) as Lane;
console.log(`Claimed ${askId} and opened Lane ${workLane.id} for it.`);
console.log(`Next: do the work, \`git add\` it, then \`zz repo submit ${slug} ${workLane.id} ${askId}\`.`);
} finally {
await cleanup();
}
}