Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Openclaw/scripts/   (KI Agentensystem Version 22©)  Datei vom 26.3.2026 mit Größe 11 kB image not shown  

Quelle  debug-claude-usage.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import { execFileSync } from "node:child_process";
import crypto from "node:crypto";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { normalizeOptionalString } from "../src/shared/string-coerce.ts";

type Args = {
  agentId: string;
  reveal: boolean;
  sessionKey?: string;
};

const mask = (value: string) => {
  const compact = value.trim();
  if (!compact) {
    return "missing";
  }
  const edge = compact.length >= 12 ? 6 : 4;
  return `${compact.slice(0, edge)}…${compact.slice(-edge)}`;
};

const parseArgs = (): Args => {
  const args = process.argv.slice(2);
  let agentId = "main";
  let reveal = false;
  let sessionKey: string | undefined;

  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    if (arg === "--agent" && args[i + 1]) {
      agentId = args[++i].trim() || "main";
      continue;
    }
    if (arg === "--reveal") {
      reveal = true;
      continue;
    }
    if (arg === "--session-key" && args[i + 1]) {
      sessionKey = normalizeOptionalString(args[++i]);
      continue;
    }
  }

  return { agentId, reveal, sessionKey };
};

const loadAuthProfiles = (agentId: string) => {
  const stateRoot = process.env.OPENCLAW_STATE_DIR?.trim() || path.join(os.homedir(), ".openclaw");
  const authPath = path.join(stateRoot, "agents", agentId, "agent", "auth-profiles.json");
  if (!fs.existsSync(authPath)) {
    throw new Error(`Missing: ${authPath}`);
  }
  const store = JSON.parse(fs.readFileSync(authPath, "utf8")) as {
    profiles?: Record<string, { provider?: string; type?: string; token?: string; key?: string }>;
  };
  return { authPath, store };
};

const pickAnthropicTokens = (store: {
  profiles?: Record<string, { provider?: string; type?: string; token?: string; key?: string }>;
}): Array<{ profileId: string; token: string }> => {
  const profiles = store.profiles ?? {};
  const found: Array<{ profileId: string; token: string }> = [];
  for (const [id, cred] of Object.entries(profiles)) {
    if (cred?.provider !== "anthropic") {
      continue;
    }
    const token = cred.type === "token" ? cred.token?.trim() : undefined;
    if (token) {
      found.push({ profileId: id, token });
    }
  }
  return found;
};

const fetchAnthropicOAuthUsage = async (token: string) => {
  const res = await fetch("https://api.anthropic.com/api/oauth/usage", {
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
      "anthropic-version": "2023-06-01",
      "anthropic-beta": "oauth-2025-04-20",
      "User-Agent": "openclaw-debug",
    },
  });
  const text = await res.text();
  return { status: res.status, contentType: res.headers.get("content-type"), text };
};

const readClaudeCliKeychain = (): {
  accessToken: string;
  expiresAt?: number;
  scopes?: string[];
} | null => {
  if (process.platform !== "darwin") {
    return null;
  }
  try {
    const raw = execFileSync(
      "security",
      ["find-generic-password", "-s", "Claude Code-credentials", "-w"],
      { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5000 },
    );
    const parsed = JSON.parse(raw.trim()) as Record<string, unknown>;
    const oauth = parsed?.claudeAiOauth as Record<string, unknown> | undefined;
    if (!oauth || typeof oauth !== "object") {
      return null;
    }
    const accessToken = oauth.accessToken;
    if (typeof accessToken !== "string" || !accessToken.trim()) {
      return null;
    }
    const expiresAt = typeof oauth.expiresAt === "number" ? oauth.expiresAt : undefined;
    const scopes = Array.isArray(oauth.scopes)
      ? oauth.scopes.filter((v): v is string => typeof v === "string")
      : undefined;
    return { accessToken, expiresAt, scopes };
  } catch {
    return null;
  }
};

const chromeServiceNameForPath = (cookiePath: string): string => {
  if (cookiePath.includes("/Arc/")) {
    return "Arc Safe Storage";
  }
  if (cookiePath.includes("/BraveSoftware/")) {
    return "Brave Safe Storage";
  }
  if (cookiePath.includes("/Microsoft Edge/")) {
    return "Microsoft Edge Safe Storage";
  }
  if (cookiePath.includes("/Chromium/")) {
    return "Chromium Safe Storage";
  }
  return "Chrome Safe Storage";
};

const readKeychainPassword = (service: string): string | null => {
  try {
    const out = execFileSync("security", ["find-generic-password", "-w", "-s", service], {
      encoding: "utf8",
      stdio: ["ignore", "pipe", "ignore"],
      timeout: 5000,
    });
    const pw = out.trim();
    return pw ? pw : null;
  } catch {
    return null;
  }
};

const decryptChromeCookieValue = (encrypted: Buffer, service: string): string | null => {
  if (encrypted.length < 4) {
    return null;
  }
  const prefix = encrypted.subarray(0, 3).toString("utf8");
  if (prefix !== "v10" && prefix !== "v11") {
    return null;
  }

  const password = readKeychainPassword(service);
  if (!password) {
    return null;
  }

  const key = crypto.pbkdf2Sync(password, "saltysalt", 1003, 16, "sha1");
  const iv = Buffer.alloc(16, 0x20);
  const data = encrypted.subarray(3);

  try {
    const decipher = crypto.createDecipheriv("aes-128-cbc", key, iv);
    decipher.setAutoPadding(true);
    const decrypted = Buffer.concat([decipher.update(data), decipher.final()]);
    const text = decrypted.toString("utf8").trim();
    return text ? text : null;
  } catch {
    return null;
  }
};

const queryChromeCookieDb = (cookieDb: string): string | null => {
  try {
    const out = execFileSync(
      "sqlite3",
      [
        "-readonly",
        cookieDb,
        `
          SELECT
            COALESCE(NULLIF(value,''), hex(encrypted_value))
          FROM cookies
          WHERE (host_key LIKE '%claude.ai%' OR host_key = '.claude.ai')
            AND name = 'sessionKey'
          LIMIT 1;
        `,
      ],
      { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5000 },
    ).trim();
    if (!out) {
      return null;
    }
    if (out.startsWith("sk-ant-")) {
      return out;
    }
    const hex = out.replace(/[^0-9A-Fa-f]/g, "");
    if (!hex) {
      return null;
    }
    const buf = Buffer.from(hex, "hex");
    const service = chromeServiceNameForPath(cookieDb);
    const decrypted = decryptChromeCookieValue(buf, service);
    return decrypted && decrypted.startsWith("sk-ant-") ? decrypted : null;
  } catch {
    return null;
  }
};

const queryFirefoxCookieDb = (cookieDb: string): string | null => {
  try {
    const out = execFileSync(
      "sqlite3",
      [
        "-readonly",
        cookieDb,
        `
          SELECT value
          FROM moz_cookies
          WHERE (host LIKE '%claude.ai%' OR host = '.claude.ai')
            AND name = 'sessionKey'
          LIMIT 1;
        `,
      ],
      { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5000 },
    ).trim();
    return out && out.startsWith("sk-ant-") ? out : null;
  } catch {
    return null;
  }
};

const findClaudeSessionKey = (): { sessionKey: string; source: string } | null => {
  if (process.platform !== "darwin") {
    return null;
  }

  const firefoxRoot = path.join(
    os.homedir(),
    "Library",
    "Application Support",
    "Firefox",
    "Profiles",
  );
  if (fs.existsSync(firefoxRoot)) {
    for (const entry of fs.readdirSync(firefoxRoot)) {
      const db = path.join(firefoxRoot, entry, "cookies.sqlite");
      if (!fs.existsSync(db)) {
        continue;
      }
      const value = queryFirefoxCookieDb(db);
      if (value) {
        return { sessionKey: value, source: `firefox:${db}` };
      }
    }
  }

  const chromeCandidates = [
    path.join(os.homedir(), "Library", "Application Support", "Google", "Chrome"),
    path.join(os.homedir(), "Library", "Application Support", "Chromium"),
    path.join(os.homedir(), "Library", "Application Support", "Arc"),
    path.join(os.homedir(), "Library", "Application Support", "BraveSoftware", "Brave-Browser"),
    path.join(os.homedir(), "Library", "Application Support", "Microsoft Edge"),
  ];

  for (const root of chromeCandidates) {
    if (!fs.existsSync(root)) {
      continue;
    }
    const profiles = fs
      .readdirSync(root)
      .filter((name) => name === "Default" || name.startsWith("Profile "));
    for (const profile of profiles) {
      const db = path.join(root, profile, "Cookies");
      if (!fs.existsSync(db)) {
        continue;
      }
      const value = queryChromeCookieDb(db);
      if (value) {
        return { sessionKey: value, source: `chromium:${db}` };
      }
    }
  }

  return null;
};

const fetchClaudeWebUsage = async (sessionKey: string) => {
  const headers = {
    Cookie: `sessionKey=${sessionKey}`,
    Accept: "application/json",
    "User-Agent":
      "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
  };
  const orgRes = await fetch("https://claude.ai/api/organizations", { headers });
  const orgText = await orgRes.text();
  if (!orgRes.ok) {
    return { ok: false as const, step: "organizations", status: orgRes.status, body: orgText };
  }
  const orgs = JSON.parse(orgText) as Array<{ uuid?: string }>;
  const orgId = orgs?.[0]?.uuid;
  if (!orgId) {
    return { ok: false as const, step: "organizations", status: 200, body: orgText };
  }

  const usageRes = await fetch(`https://claude.ai/api/organizations/${orgId}/usage`, { headers });
  const usageText = await usageRes.text();
  return usageRes.ok
    ? { ok: true as const, orgId, body: usageText }
    : { ok: false as const, step: "usage", status: usageRes.status, body: usageText };
};

const main = async () => {
  const opts = parseArgs();
  const { authPath, store } = loadAuthProfiles(opts.agentId);
  console.log(`Auth file: ${authPath}`);

  const keychain = readClaudeCliKeychain();
  if (keychain) {
    console.log(
      `Claude Code CLI keychain: accessToken=${opts.reveal ? keychain.accessToken : mask(keychain.accessToken)} scopes=${keychain.scopes?.join(",") ?? "(unknown)"}`,
    );
    const oauth = await fetchAnthropicOAuthUsage(keychain.accessToken);
    console.log(
      `OAuth usage (keychain): HTTP ${oauth.status} (${oauth.contentType ?? "no content-type"})`,
    );
    console.log(oauth.text.slice(0, 200).replace(/\s+/g, " ").trim());
  } else {
    console.log("Claude Code CLI keychain: missing/unreadable");
  }

  const anthropic = pickAnthropicTokens(store);
  if (anthropic.length === 0) {
    console.log("Auth profiles: no Anthropic token profiles found");
  } else {
    for (const entry of anthropic) {
      console.log(
        `Auth profiles: ${entry.profileId} token=${opts.reveal ? entry.token : mask(entry.token)}`,
      );
      const oauth = await fetchAnthropicOAuthUsage(entry.token);
      console.log(
        `OAuth usage (${entry.profileId}): HTTP ${oauth.status} (${oauth.contentType ?? "no content-type"})`,
      );
      console.log(oauth.text.slice(0, 200).replace(/\s+/g, " ").trim());
    }
  }

  const sessionKey =
    opts.sessionKey?.trim() ||
    process.env.CLAUDE_AI_SESSION_KEY?.trim() ||
    process.env.CLAUDE_WEB_SESSION_KEY?.trim() ||
    findClaudeSessionKey()?.sessionKey;
  const source = opts.sessionKey
    ? "--session-key"
    : process.env.CLAUDE_AI_SESSION_KEY || process.env.CLAUDE_WEB_SESSION_KEY
      ? "env"
      : (findClaudeSessionKey()?.source ?? "auto");

  if (!sessionKey) {
    console.log(
      "Claude web: no sessionKey found (try --session-key or export CLAUDE_AI_SESSION_KEY)",
    );
    return;
  }

  console.log(
    `Claude web: sessionKey=${opts.reveal ? sessionKey : mask(sessionKey)} (source: ${source})`,
  );
  const web = await fetchClaudeWebUsage(sessionKey);
  if (!web.ok) {
    console.log(`Claude web: ${web.step} HTTP ${web.status}`);
    console.log(web.body.slice(0, 400).replace(/\s+/g, " ").trim());
    return;
  }
  console.log(`Claude web: org=${web.orgId} OK`);
  console.log(web.body.slice(0, 400).replace(/\s+/g, " ").trim());
};

await main();

¤ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.