124 lines · 4.8 KB
import { all, first, run } from "../db";
import { randomId } from "../crypto";
import { badRequest, conflict, notFoundError } from "../errors";
import { assertBelowCap } from "../limits";
import { hasPermission, loadRepo, repoPermission } from "../repos";
import { MCP_AUDIENCE, parseTokenPermissions } from "../token-scope";
import type { TokenPermissions } from "../token-scope";
import type { Viewer } from "~/lib/types";
import { mintFineGrainedToken } from "./grants";
import type { MintedToken } from "./grants";

const MAX_AGENTS_PER_USER = 50;
const MAX_TOKEN_REPOS = 50;
const DAY_MS = 24 * 60 * 60 * 1000;
export const MAX_AGENT_TOKEN_DAYS = 366;
export const AGENT_NAME = /^[A-Za-z0-9][A-Za-z0-9 ._-]{0,63}$/;

export type AgentSummary = {
  id: string;
  name: string;
  description: string | null;
  createdAt: number;
  tokens: number;
};

export async function listAgents(userId: string): Promise<AgentSummary[]> {
  const rows = await all<{ id: string; name: string; description: string | null; created_at: number; tokens: number }>(
    `SELECT a.id, a.name, a.description, a.created_at,
       (SELECT COUNT(*) FROM mcp_token_agents m JOIN access_tokens t ON t.id = m.token_id
        WHERE m.agent_id = a.id AND (t.expires_at IS NULL OR t.expires_at > ?2)) AS tokens
     FROM agents a WHERE a.owner_id = ?1 ORDER BY a.name`,
    userId,
    Date.now(),
  );
  return rows.map((row) => ({
    id: row.id,
    name: row.name,
    description: row.description,
    createdAt: row.created_at,
    tokens: row.tokens,