285 lines · 9.3 KB
import { z } from "zod";
import { badRequest } from "../../errors";
import { toJsonText } from "../protocol";
import type { McpCaller } from "../protocol";
import { eventJson, eventsUri, repoHub, sessionHub, sessionSubscriber, subscriberOwner } from "../hub-do";
import { normalizeClaimPath } from "../coordination";
import type { Lease } from "../coordination";
import { AGENT_EVENT_TYPES } from "../events";
import { readableEventTypes } from "../event-access";
import { defineTool, repoArgs, scopedRepo } from "./base";

const MAX_CLAIM_KEYS = 100;
const DEFAULT_TTL_SECONDS = 15 * 60;
const MAX_TTL_SECONDS = 4 * 60 * 60;
const MAX_POLL = 100;

/**
 * Claims belong to one token and its token-derived agent name; client-declared names never split or
 * merge holders, so agents sharing one unregistered PAT share its claims.
 */
export function holderKey(caller: McpCaller): string {
  return `${caller.tokenId ?? caller.viewer.id}:${caller.agent.name}`;
}

function leaseJson(lease: Lease, caller: McpCaller) {
  return {
    id: lease.id,
    kind: lease.kind,
    key: lease.key,
    agent: lease.agent,
    user: lease.user,
    note: lease.note,
    mine: lease.holder === holderKey(caller),
    expires_at: lease.expiresAt,
  };
}

const ttl = z.number().int().min(30).max(MAX_TTL_SECONDS).default(DEFAULT_TTL_SECONDS);

const leaseShape = z.object({