import "../chunk-PZ5AY32C.js";

// src/delegated-tools/token.ts
var DEFAULT_PREFIX = "dtt_";
function base64urlEncode(input) {
  const bytes = typeof input === "string" ? new TextEncoder().encode(input) : input;
  let binary = "";
  for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
function base64urlDecodeToString(input) {
  try {
    const padded = input.replace(/-/g, "+").replace(/_/g, "/");
    const binary = atob(padded);
    const bytes = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
    return new TextDecoder().decode(bytes);
  } catch {
    return null;
  }
}
async function sign(payload, secret) {
  const enc = new TextEncoder();
  const key = await crypto.subtle.importKey("raw", enc.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
  const sig = await crypto.subtle.sign("HMAC", key, enc.encode(payload));
  return base64urlEncode(new Uint8Array(sig));
}
function timingSafeEqual(a, b) {
  if (a.length !== b.length) return false;
  let diff = 0;
  for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
  return diff === 0;
}
async function mintDelegatedToolToken(input) {
  const secret = input.secret?.trim();
  if (!secret) return void 0;
  const prefix = input.prefix ?? DEFAULT_PREFIX;
  const now = input.now ?? Date.now();
  const claims = {
    workspaceId: input.workspaceId,
    allowedTools: input.allowedTools,
    expiresAt: now + input.ttlSeconds * 1e3
  };
  const payload = base64urlEncode(JSON.stringify(claims));
  const signature = await sign(payload, secret);
  return `${prefix}${payload}.${signature}`;
}
async function verifyDelegatedToolToken(token, opts) {
  const secret = opts.secret?.trim();
  const prefix = opts.prefix ?? DEFAULT_PREFIX;
  if (!secret || !token.startsWith(prefix)) return null;
  const body = token.slice(prefix.length);
  const dot = body.indexOf(".");
  if (dot <= 0) return null;
  const payload = body.slice(0, dot);
  const signature = body.slice(dot + 1);
  if (!payload || !signature) return null;
  const expected = await sign(payload, secret);
  if (!timingSafeEqual(signature, expected)) return null;
  const json = base64urlDecodeToString(payload);
  if (json === null) return null;
  let claims;
  try {
    claims = JSON.parse(json);
  } catch {
    return null;
  }
  if (!claims || typeof claims !== "object") return null;
  const record = claims;
  if (typeof record.workspaceId !== "string" || !record.workspaceId) return null;
  if (typeof record.expiresAt !== "number" || !Number.isFinite(record.expiresAt)) return null;
  if (!Array.isArray(record.allowedTools) || !record.allowedTools.every((tool) => typeof tool === "string")) return null;
  const now = opts.now ?? Date.now();
  if (record.expiresAt <= now) return null;
  return {
    workspaceId: record.workspaceId,
    allowedTools: record.allowedTools,
    expiresAt: record.expiresAt
  };
}

// src/delegated-tools/handler.ts
var DelegatedToolInvocationError = class extends Error {
  code;
  data;
  constructor(message, options = {}) {
    super(message);
    this.name = "DelegatedToolInvocationError";
    this.code = options.code ?? -32e3;
    this.data = options.data;
  }
};
var PROTOCOL_VERSION = "2024-11-05";
function normalizeId(id) {
  return typeof id === "string" || typeof id === "number" ? id : null;
}
function rpcResult(id, result) {
  return { jsonrpc: "2.0", id: normalizeId(id), result };
}
function rpcError(id, code, message, data) {
  return {
    jsonrpc: "2.0",
    id: normalizeId(id),
    error: data === void 0 ? { code, message } : { code, message, data }
  };
}
function extractBearer(authorization) {
  return authorization?.match(/^Bearer\s+(.+)$/i)?.[1];
}
async function handleDelegatedToolCall(body, authorization, seams) {
  const id = body.id ?? null;
  const method = typeof body.method === "string" ? body.method : "";
  const bearer = extractBearer(authorization);
  const claims = bearer ? await seams.verifyToken(bearer) : null;
  if (!claims) return rpcError(id, -32001, "Unauthorized");
  if (method === "initialize") {
    const info = seams.serverInfo ?? { name: "delegated-tools", version: "1" };
    return rpcResult(id, {
      protocolVersion: PROTOCOL_VERSION,
      capabilities: { tools: {} },
      serverInfo: info
    });
  }
  if (method === "tools/list") {
    const tools = [];
    for (const name of claims.allowedTools) {
      const tool = await seams.resolveTool(claims.workspaceId, name);
      if (!tool) continue;
      if (!await seams.isIntegrationConnected(claims.workspaceId, tool)) continue;
      tools.push({
        name: tool.name,
        description: tool.description,
        inputSchema: tool.inputSchema ?? { type: "object" }
      });
    }
    return rpcResult(id, { tools });
  }
  if (method === "tools/call") {
    const params = body.params ?? {};
    const name = typeof params.name === "string" ? params.name : "";
    const args = params.arguments && typeof params.arguments === "object" && !Array.isArray(params.arguments) ? params.arguments : {};
    if (!name) return rpcError(id, -32602, "Missing tool name");
    if (!claims.allowedTools.includes(name)) {
      return rpcError(id, -32602, `Tool not delegated to this session: ${name}`);
    }
    const tool = await seams.resolveTool(claims.workspaceId, name);
    if (!tool) return rpcError(id, -32602, `Tool not available for workspace: ${name}`);
    if (!await seams.isIntegrationConnected(claims.workspaceId, tool)) {
      return rpcError(id, -32602, `Integration not connected for tool: ${name}`);
    }
    try {
      const result = await tool.invoke(args);
      return rpcResult(id, result);
    } catch (err) {
      if (err instanceof DelegatedToolInvocationError) {
        return rpcError(id, err.code, err.message, err.data);
      }
      return rpcError(id, -32e3, err instanceof Error ? err.message : "Tool invocation failed");
    }
  }
  return rpcError(id, -32601, `Method not found: ${method || "(none)"}`);
}
async function handleDelegatedToolRequest(request, seams) {
  if (request.method !== "POST") {
    return Response.json({ error: "Method not allowed" }, { status: 405 });
  }
  let body;
  try {
    body = await request.json();
  } catch {
    return Response.json(rpcError(null, -32700, "Parse error"));
  }
  const response = await handleDelegatedToolCall(body, request.headers.get("authorization"), seams);
  if (response.error?.code === -32001) {
    return Response.json(response, { status: 401 });
  }
  return Response.json(response);
}

// src/delegated-tools/lease.ts
async function issueDelegatedToolLease(input) {
  const now = input.now ?? Date.now();
  const token = await mintDelegatedToolToken({
    workspaceId: input.workspaceId,
    allowedTools: input.allowedTools,
    ttlSeconds: input.ttlSeconds,
    secret: input.secret,
    prefix: input.prefix,
    now
  });
  if (!token) return null;
  return {
    token,
    allowedTools: input.allowedTools,
    expiresAt: now + input.ttlSeconds * 1e3,
    callbackUrl: input.callbackUrl
  };
}
export {
  DelegatedToolInvocationError,
  handleDelegatedToolCall,
  handleDelegatedToolRequest,
  issueDelegatedToolLease,
  mintDelegatedToolToken,
  verifyDelegatedToolToken
};
//# sourceMappingURL=index.js.map