Back to the feed

Codex 重置卡查看工具:检查 ChatGPT 邀请奖励与可用次数

#Chatgpt

检查 ChatGPT Codex 邀请活动是否仍有重置卡奖励,查看 rate_limit_reset_credits 可用次数和过期时间,避免继续尝试已失效的邀请流程。

The briefing

快速结论

  • 当前 Codex 邀请活动主体已经结束,有入口不代表还能拿到重置卡。
  • 这个网页工具适合检查账户里的 rate_limit_reset_credits、可用数量和过期时间。
  • 如果你搜索“Codex 重置卡”或“ChatGPT invite rewards”,先确认奖励接口仍返回可用次数,再决定是否继续操作。
  • 后续如果 OpenAI 恢复邀请奖励,这里会继续更新可用入口和注意事项。

#0. Chrome插件可以使用~ codex-referral-extension.zip

效果如下: image

如果不想用插件,可以按下面的方法。

1. 在网页登录Chatgpt

2. 使用F12 控制台输入以下命令

(async () => {
  const PANEL_ID = "codex-referral-panel";
  const REFERRAL_KEY = "codex_referral_persistent_invite";
  const API_BASE = "/backend-api";

document.getElementById(PANEL_ID)?.remove();

if (location.hostname !== "chatgpt.com") {
    throw new Error("请先打开 https://chatgpt.com,再在该页面的 F12 Console 中运行。");
  }

const panel = document.createElement("section");
  panel.id = PANEL_ID;
  panel.innerHTML = `
    <style>
      #${PANEL_ID} {
        position: fixed;
        z-index: 2147483647;
        right: 20px;
        bottom: 20px;
        width: min(820px, calc(100vw - 32px));
        max-height: calc(100vh - 40px);
        color: #171717;
        background: #fff;
        border: 1px solid #d4d4d4;
        border-radius: 8px;
        box-shadow: 0 16px 48px rgba(0, 0, 0, .22);
        font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
          "Segoe UI", sans-serif;
        overflow: hidden;
      }
      #${PANEL_ID} * { box-sizing: border-box; }
      #${PANEL_ID} header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 14px 16px;
        color: #fff;
        background: #171717;
      }
      #${PANEL_ID} h2 {
        margin: 0;
        font-size: 15px;
        font-weight: 650;
        letter-spacing: 0;
      }
      #${PANEL_ID} .close {
        width: 28px;
        height: 28px;
        padding: 0;
        color: #fff;
        background: transparent;
        border: 0;
        font-size: 20px;
        cursor: pointer;
      }
      #${PANEL_ID} .body {
        max-height: calc(100vh - 96px);
        padding: 16px;
        overflow: auto;
      }
      #${PANEL_ID} .summary {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8px;
        margin-bottom: 14px;
      }
      #${PANEL_ID} .metric {
        padding: 9px 10px;
        background: #f5f5f5;
        border: 1px solid #e5e5e5;
        border-radius: 6px;
      }
      #${PANEL_ID} .metric span {
        display: block;
        color: #737373;
        font-size: 12px;
      }
      #${PANEL_ID} .metric strong {
        display: block;
        margin-top: 2px;
        font-size: 14px;
        overflow-wrap: anywhere;
      }
      #${PANEL_ID} .section-title {
        margin: 14px 0 8px;
        font-size: 13px;
        font-weight: 700;
      }
      #${PANEL_ID} .table-wrap {
        max-height: 210px;
        margin-bottom: 14px;
        overflow: auto;
        border: 1px solid #e5e5e5;
        border-radius: 6px;
      }
      #${PANEL_ID} table {
        width: 100%;
        min-width: 680px;
        border-collapse: collapse;
        background: #fff;
      }
      #${PANEL_ID} th,
      #${PANEL_ID} td {
        padding: 8px 9px;
        border-bottom: 1px solid #f0f0f0;
        text-align: left;
        vertical-align: top;
        font-size: 12px;
      }
      #${PANEL_ID} th {
        position: sticky;
        top: 0;
        z-index: 1;
        color: #525252;
        background: #fafafa;
        font-weight: 700;
      }
      #${PANEL_ID} td {
        color: #262626;
        overflow-wrap: anywhere;
      }
      #${PANEL_ID} a {
        color: #2563eb;
        text-decoration: none;
      }
      #${PANEL_ID} a:hover { text-decoration: underline; }
      #${PANEL_ID} .empty {
        color: #737373;
        text-align: center;
      }
      #${PANEL_ID} label {
        display: block;
        margin-bottom: 6px;
        font-weight: 600;
      }
      #${PANEL_ID} input {
        width: 100%;
        height: 40px;
        padding: 0 11px;
        color: #171717;
        background: #fff;
        border: 1px solid #a3a3a3;
        border-radius: 6px;
        outline: none;
      }
      #${PANEL_ID} input:focus {
        border-color: #171717;
        box-shadow: 0 0 0 2px rgba(23, 23, 23, .12);
      }
      #${PANEL_ID} .actions {
        display: flex;
        gap: 8px;
        margin-top: 10px;
      }
      #${PANEL_ID} button.action {
        height: 38px;
        padding: 0 13px;
        border: 1px solid #a3a3a3;
        border-radius: 6px;
        background: #fff;
        cursor: pointer;
        font-weight: 600;
      }
      #${PANEL_ID} button.primary {
        flex: 1;
        color: #fff;
        background: #171717;
        border-color: #171717;
      }
      #${PANEL_ID} button:disabled {
        cursor: not-allowed;
        opacity: .5;
      }
      #${PANEL_ID} .status {
        min-height: 72px;
        max-height: 220px;
        margin: 14px 0 0;
        padding: 12px;
        overflow: auto;
        overflow-wrap: anywhere;
        color: #262626;
        background: #fafafa;
        border: 1px solid #e5e5e5;
        border-left: 4px solid #a3a3a3;
        border-radius: 6px;
      }
      #${PANEL_ID} .status.ok {
        color: #14532d;
        background: #f0fdf4;
        border-color: #bbf7d0;
        border-left-color: #16a34a;
      }
      #${PANEL_ID} .status.error {
        color: #7f1d1d;
        background: #fef2f2;
        border-color: #fecaca;
        border-left-color: #dc2626;
      }
      #${PANEL_ID} .status.warn {
        color: #713f12;
        background: #fffbeb;
        border-color: #fde68a;
        border-left-color: #f59e0b;
      }
      #${PANEL_ID} .status-title {
        margin: 0 0 6px;
        font-size: 14px;
        font-weight: 750;
      }
      #${PANEL_ID} .status-line {
        margin-top: 3px;
        font-size: 13px;
        line-height: 1.45;
      }
    </style>
    <header>
      <h2>Codex 邀请检查与发送</h2>
      <button class="close" title="关闭" aria-label="关闭">×</button>
    </header>
    <div class="body">
      <div class="summary">
        <div class="metric"><span>网页当前套餐</span><strong data-field="plan">读取中</strong></div>
        <div class="metric"><span>可邀请次数</span><strong data-field="quota">读取中</strong></div>
        <div class="metric"><span>重置卡</span><strong data-field="credits">读取中</strong></div>
        <div class="metric"><span>账号 ID</span><strong data-field="account">读取中</strong></div>
      </div>
      <div class="section-title">已发送邀请明细</div>
      <div class="table-wrap">
        <table>
          <thead>
            <tr>
              <th>邮箱</th>
              <th>状态</th>
              <th>过期时间</th>
              <th>奖励</th>
              <th>邀请链接</th>
            </tr>
          </thead>
          <tbody data-field="referrals">
            <tr><td class="empty" colspan="5">读取中</td></tr>
          </tbody>
        </table>
      </div>
      <div class="section-title">我获得的重置卡奖励</div>
      <div class="table-wrap">
        <table>
          <thead>
            <tr>
              <th>来源</th>
              <th>状态</th>
              <th>领取时间</th>
              <th>过期时间</th>
              <th>使用时间</th>
            </tr>
          </thead>
          <tbody data-field="reward-credits">
            <tr><td class="empty" colspan="5">读取中</td></tr>
          </tbody>
        </table>
      </div>
      <label for="codex-referral-email">受邀邮箱</label>
      <input id="codex-referral-email" type="email" autocomplete="off"
        placeholder="[email protected]">
      <div class="actions">
        <button class="action" data-action="refresh">刷新状态</button>
        <button class="action primary" data-action="send" disabled>发送邀请</button>
      </div>
      <div class="status">正在读取当前网页会话…</div>
    </div>
  `;
  document.body.appendChild(panel);

const $ = (selector) => panel.querySelector(selector);
  const planEl = $('[data-field="plan"]');
  const quotaEl = $('[data-field="quota"]');
  const creditsEl = $('[data-field="credits"]');
  const accountEl = $('[data-field="account"]');
  const referralsEl = $('[data-field="referrals"]');
  const rewardCreditsEl = $('[data-field="reward-credits"]');
  const emailEl = $("#codex-referral-email");
  const refreshButton = $('[data-action="refresh"]');
  const sendButton = $('[data-action="send"]');
  const statusEl = $(".status");

let token = "";
  let accountId = "";
  let busy = false;
  let inviteQuotaRemaining = 0;

const setStatus = (message, type = "") => {
    statusEl.className = `status ${type}`.trim();
    statusEl.replaceChildren();

const lines = Array.isArray(message) ? message : String(message ?? "").split("\n");
    const title = lines.shift() || "";

const titleEl = document.createElement("div");
    titleEl.className = "status-title";
    titleEl.textContent = title;
    statusEl.appendChild(titleEl);

for (const line of lines.filter(Boolean)) {
      const lineEl = document.createElement("div");
      lineEl.className = "status-line";
      lineEl.textContent = line;
      statusEl.appendChild(lineEl);
    }
  };

const setBusy = (value) => {
    busy = value;
    refreshButton.disabled = value;
    emailEl.disabled = value;
    sendButton.disabled = value || !token || !accountId;
  };

const formatTime = (iso) => {
    if (!iso) return "";
    return new Intl.DateTimeFormat("zh-CN", {
      timeZone: "Asia/Shanghai",
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      hour12: false,
    })
      .format(new Date(iso))
      .replace(/\//g, "-");
  };

const grantText = (grants) => {
    if (!Array.isArray(grants) || grants.length === 0) return "";
    return grants
      .map((grant) => {
        const who = grant.recipient === "referrer" ? "邀请人" : "被邀请人";
        const type =
          grant.grant_type === "rate_limit_reset_credit" ? "重置卡" : grant.grant_type;
        return `${who} +${grant.amount ?? 1} ${type}`;
      })
      .join(";");
  };

const creditSourceText = (credit) => {
    const title = credit?.title || "";
    const description = credit?.description || "";
    const profile = credit?.profile_user_id || "";
    const text = `${title} ${description} ${profile}`.toLowerCase();

if (/codex team|thanks for using codex|official|官方/.test(text)) {
      return "官方免费赠送";
    }
    return description || title || profile || credit?.reset_type || "未知来源";
  };

const creditUseTime = (credit) => {
    if (credit?.redeemed_at) return formatTime(credit.redeemed_at);
    if (credit?.redeem_started_at) return `兑换中:${formatTime(credit.redeem_started_at)}`;
    return "";
  };

const appendCell = (row, text, className = "") => {
    const cell = document.createElement("td");
    cell.textContent = text ?? "";
    if (className) cell.className = className;
    row.appendChild(cell);
    return cell;
  };

const renderTableMessage = (tbody, colspan, message, className = "empty") => {
    tbody.replaceChildren();
    const row = document.createElement("tr");
    appendCell(row, message, className).colSpan = colspan;
    tbody.appendChild(row);
  };

const renderReferrals = (items) => {
    referralsEl.replaceChildren();

if (!Array.isArray(items) || items.length === 0) {
      renderTableMessage(referralsEl, 5, "还没有已发送邀请记录");
      return;
    }

for (const item of items) {
      const row = document.createElement("tr");
      appendCell(row, item.email || "");
      appendCell(row, item.status || "");
      appendCell(row, formatTime(item.expires_at));
      appendCell(row, grantText(item.grants));

const linkCell = document.createElement("td");
      if (item.referral_link) {
        const link = document.createElement("a");
        link.href = item.referral_link;
        link.target = "_blank";
        link.rel = "noreferrer";
        link.textContent = "打开";
        linkCell.appendChild(link);
      } else {
        linkCell.textContent = "";
      }
      row.appendChild(linkCell);
      referralsEl.appendChild(row);
    }
  };

const renderRewardCredits = (credits) => {
    rewardCreditsEl.replaceChildren();

if (!Array.isArray(credits) || credits.length === 0) {
      renderTableMessage(rewardCreditsEl, 5, "还没有重置卡奖励记录");
      return;
    }

for (const credit of credits) {
      const row = document.createElement("tr");
      appendCell(row, creditSourceText(credit));
      appendCell(row, credit.status || "");
      appendCell(row, formatTime(credit.granted_at));
      appendCell(row, formatTime(credit.expires_at));
      appendCell(row, creditUseTime(credit));
      rewardCreditsEl.appendChild(row);
    }
  };

const parseResponse = async (response) => {
    const contentType = response.headers.get("content-type") || "";
    const text = await response.text();
    if (contentType.includes("application/json")) {
      try {
        return text ? JSON.parse(text) : null;
      } catch {
        return { detail: "服务器返回了无法解析的 JSON", raw: text.slice(0, 500) };
      }
    }
    return {
      detail: text
        ? `服务器返回非 JSON 内容:${text.slice(0, 300)}`
      : "服务器没有返回内容",
    };
  };

const readableValue = (value) => {
    if (value === null || value === undefined || value === "") return "";
    if (typeof value === "string") return value;
    if (typeof value === "number" || typeof value === "boolean") return String(value);
    if (Array.isArray(value)) return value.map(readableValue).filter(Boolean).join(", ");

const lines = [];
    if (value.message) lines.push(String(value.message));
    if (value.failed_emails?.length) {
      lines.push(`失败邮箱:${value.failed_emails.join(", ")}`);
    }
    if (value.code) lines.push(`错误代码:${value.code}`);
    if (value.error) {
      const errorText = readableValue(value.error);
      if (errorText) lines.push(`错误:${errorText}`);
    }
    if (value.ineligible_reason) {
      const reasonText = readableValue(value.ineligible_reason);
      if (reasonText) lines.push(`不符合原因:${reasonText}`);
    }
    if (value.ineligible_reason_code) {
      lines.push(`不符合原因代码:${value.ineligible_reason_code}`);
    }
    if (value.detail && value.detail !== value) {
      const detailText = readableValue(value.detail);
      if (detailText) lines.push(detailText);
    }

const unique = [...new Set(lines.filter(Boolean))];
    return unique.length ? unique.join("\n") : JSON.stringify(value, null, 2);
  };

const responseDetail = (data, fallback = "") =>
    readableValue(data?.detail) ||
    readableValue(data?.message) ||
    (typeof data === "string" ? data : "") ||
    fallback;

const responsePayload = (data) =>
    data?.detail && typeof data.detail === "object" ? data.detail : data || {};

const responseMessage = (data, fallback = "") => {
    const payload = responsePayload(data);
    return payload.message || data?.message || responseDetail(data, fallback);
  };

const failedEmails = (data) => {
    const payload = responsePayload(data);
    return Array.isArray(payload.failed_emails) ? payload.failed_emails : [];
  };

const inviteResultTitle = (ok, message) => {
    if (ok) return "邀请发送成功";
    if (/cannot be referred/i.test(message)) return "该邮箱暂时不能被邀请";
    return "邀请没有发送成功";
  };

const api = async (path, options = {}, useAccount = true) => {
    const response = await fetch(`${API_BASE}${path}`, {
      ...options,
      credentials: "include",
      headers: {
        accept: "application/json",
        authorization: `Bearer ${token}`,
        ...(useAccount && accountId ? { "chatgpt-account-id": accountId } : {}),
        ...(options.body ? { "content-type": "application/json" } : {}),
        ...(options.headers || {}),
      },
    });
    return {
      ok: response.ok,
      status: response.status,
      data: await parseResponse(response),
    };
  };

const getSession = async () => {
    const response = await fetch("/api/auth/session", {
      credentials: "include",
      headers: { accept: "application/json" },
    });
    const session = await parseResponse(response);
    token = session?.accessToken || session?.access_token || "";
    if (!response.ok || !token) {
      throw new Error("网页会话中没有 Access Token。请确认当前 chatgpt.com 页面已登录,然后刷新页面重试。");
    }
  };

const selectAccount = async () => {
    const result = await api("/wham/accounts/check", {}, false);
    if (!result.ok) {
      throw new Error(`读取账号失败:${responseDetail(result.data, "请刷新页面后重试")}`.trim());
    }

accountId =
      result.data?.default_account_id ||
      result.data?.account_ordering?.[0] ||
      result.data?.accounts?.[0]?.id ||
      "";

if (!accountId) {
      throw new Error("服务器没有返回可用的 ChatGPT 账号 ID。");
    }
  };

const refresh = async (message = "正在刷新当前网页账号状态…") => {
    setBusy(true);
    setStatus(message);
    try {
      await getSession();
      await selectAccount();

const [usage, rules, referrals, resetCredits, frontendEligibility] = await Promise.all([
        api("/wham/usage"),
        api(`/wham/referrals/eligibility_rules?referral_key=${encodeURIComponent(REFERRAL_KEY)}`),
        api(`/wham/referrals?referral_key=${encodeURIComponent(REFERRAL_KEY)}`),
        api("/wham/rate-limit-reset-credits"),
        api(`/referrals/invite/eligibility?referral_key=${encodeURIComponent(REFERRAL_KEY)}`),
      ]);

const failures = [];

if (usage.ok) {
        planEl.textContent = usage.data?.plan_type || "未知";
      } else {
        planEl.textContent = "读取失败";
        failures.push(`套餐:${responseDetail(usage.data, "请稍后重试")}`);
      }

const frame = rules.ok ? rules.data?.time_frame_rules?.[0] || {} : {};
      const sent = Number(frame.invites_sent);
      const total = Number(frame.invites_total);
      const remaining =
        Number.isFinite(sent) && Number.isFinite(total) ? Math.max(0, total - sent) : null;

if (rules.ok) {
        inviteQuotaRemaining = remaining === null ? 0 : remaining;
        quotaEl.textContent =
          remaining === null ? "0 次" : `${remaining} 次(已用 ${sent}/${total})`;
      } else {
        inviteQuotaRemaining = 0;
        quotaEl.textContent = "0 次";
        failures.push("可邀请次数:额度接口不可用,按 0 处理");
      }

if (resetCredits.ok) {
        const availableCredits =
          resetCredits.data?.available_count ??
          usage.data?.rate_limit_reset_credits?.available_count ??
          "未知";
        const totalEarnedCredits = resetCredits.data?.total_earned_count;

creditsEl.textContent =
          totalEarnedCredits === undefined
            ? `${availableCredits}`
            : `可用 ${availableCredits},奖励 ${totalEarnedCredits}`;
        renderRewardCredits(resetCredits.data?.credits || []);
      } else {
        const fallbackCredits = usage.ok
          ? usage.data?.rate_limit_reset_credits?.available_count
          : undefined;
        creditsEl.textContent =
          fallbackCredits === undefined ? "读取失败" : `可用 ${fallbackCredits}`;
        renderTableMessage(
          rewardCreditsEl,
          5,
          `重置卡奖励读取失败:${responseDetail(resetCredits.data, "请稍后重试")}`,
        );
        failures.push(`重置卡奖励:${responseDetail(resetCredits.data, "请稍后重试")}`);
      }

accountEl.textContent = accountId;

if (referrals.ok) {
        renderReferrals(referrals.data?.items || []);
      } else {
        renderTableMessage(
          referralsEl,
          5,
          `邀请明细读取失败:${responseDetail(referrals.data, "请稍后重试")}`,
        );
        failures.push(`邀请明细:${responseDetail(referrals.data, "请稍后重试")}`);
      }

console.log("Codex 邀请状态:", {
        plan_type: usage.ok ? usage.data?.plan_type : null,
        reset_cards_available: resetCredits.ok
          ? resetCredits.data?.available_count
          : usage.data?.rate_limit_reset_credits?.available_count,
        reset_cards_total_earned: resetCredits.ok ? resetCredits.data?.total_earned_count : null,
        invites_sent: frame.invites_sent,
        invites_total: frame.invites_total,
        invite_remaining: remaining,
        effective_invite_remaining: inviteQuotaRemaining,
        time_frame: frame.time_frame,
        account_id: accountId,
        partial_failures: failures,
      });
      if (referrals.ok) {
        console.table(
          (referrals.data?.items || []).map((item, index) => ({
            index: index + 1,
            email: item.email,
            status: item.status,
            expires_at: formatTime(item.expires_at),
            referral_id: item.referral_id,
            grants: grantText(item.grants),
            referral_link: item.referral_link,
          })),
        );
      }
      if (resetCredits.ok) {
        console.table(
          (resetCredits.data?.credits || []).map((credit, index) => ({
            index: index + 1,
            source: creditSourceText(credit),
            status: credit.status,
            granted_at: formatTime(credit.granted_at),
            expires_at: formatTime(credit.expires_at),
            used_at: creditUseTime(credit),
            profile_user_id: credit.profile_user_id,
            credit_id: credit.id,
          })),
        );
      }

const eligibilityLine =
        frontendEligibility.ok && frontendEligibility.data?.should_show !== false
          ? "网页入口:当前可显示"
          : "网页入口:当前未显示,面板仍可按接口结果操作";
      const successCount = [usage, rules, referrals, resetCredits].filter((r) => r.ok).length;
      const statusTitle =
        failures.length === 0
          ? "状态读取完成。"
          : successCount > 0
            ? "状态已部分读取。"
            : "状态读取失败。";
      const referralCountText = referrals.ok
        ? `${referrals.data?.items?.length ?? 0} 条`
        : "不可用";
      const rewardCountText = resetCredits.ok
        ? `${resetCredits.data?.credits?.length ?? 0} 条`
        : "不可用";

setStatus(
        [
          statusTitle,
          `套餐:${planEl.textContent}`,
          `可邀请:${quotaEl.textContent}`,
          `重置卡:${creditsEl.textContent}`,
          `邀请明细:${referralCountText}`,
          `奖励明细:${rewardCountText}`,
          eligibilityLine,
          ...failures.map((failure) => `未读取:${failure}`),
        ].join("\n"),
        failures.length === 0 ? "ok" : successCount > 0 ? "warn" : "error",
      );
    } catch (error) {
      token = "";
      accountId = "";
      inviteQuotaRemaining = 0;
      planEl.textContent = "读取失败";
      quotaEl.textContent = "读取失败";
      creditsEl.textContent = "读取失败";
      accountEl.textContent = "读取失败";
      renderReferrals([]);
      renderRewardCredits([]);
      setStatus(error instanceof Error ? error.message : String(error), "error");
    } finally {
      setBusy(false);
    }
  };

const sendInvite = async () => {
    if (busy) return;

const email = emailEl.value.trim();
    if (!emailEl.checkValidity() || !email) {
      emailEl.reportValidity();
      return;
    }

const confirmed = window.confirm(
      `确认使用当前网页账号发送 1 次 Codex 邀请?\n\n收件邮箱:${email}\n账号 ID:${accountId}`,
    );
    if (!confirmed) return;

setBusy(true);
    setStatus(`正在向 ${email} 发送邀请…`);
    try {
      // 发送前重新读取网页会话,避免使用已经过期的 Token。
      await getSession();
      await selectAccount();

const result = await api("/wham/referrals/invite", {
        method: "POST",
        body: JSON.stringify({
          referral_key: REFERRAL_KEY,
          emails: [email],
        }),
      });

const invite =
        result.data?.invites?.[0] ||
        result.data?.items?.[0] ||
        result.data?.referral ||
        result.data ||
        {};

const detail = responseMessage(
        result.data,
        result.ok ? "服务器已接受邀请请求" : "服务器拒绝了邀请请求",
      );
      const failed = failedEmails(result.data);
      const resultTitle = inviteResultTitle(result.ok, detail);
      const resultLines = result.ok
        ? [
            invite.email ? `邮箱:${invite.email}` : "",
            invite.referral_id ? `Referral ID:${invite.referral_id}` : "",
            invite.invite_url || invite.referral_link
              ? `邀请链接:${invite.invite_url || invite.referral_link}`
              : "",
            "已自动刷新邀请额度和明细。",
          ]
        : [
            failed.length ? `邮箱:${failed.join(", ")}` : `邮箱:${email}`,
            `结果:${detail}`,
            "邀请没有发出,当前邮箱不会出现在已发送邀请列表。",
          ];

const statusMessage = [resultTitle, ...resultLines.filter(Boolean)].join("\n");
      setStatus(statusMessage, result.ok ? "ok" : "error");

console.log("Codex 邀请响应:", {
        http_status: result.status,
        ok: result.ok,
        response: result.data,
      });

if (result.ok) {
        await refresh("发送成功,正在重新读取邀请额度…");
        setStatus(statusMessage, "ok");
      }
    } catch (error) {
      setStatus(error instanceof Error ? error.message : String(error), "error");
    } finally {
      setBusy(false);
    }
  };

$(".close").addEventListener("click", () => panel.remove());
  refreshButton.addEventListener("click", () => refresh());
  sendButton.addEventListener("click", sendInvite);

await refresh();
})();

效果如下: image

Is this still live?

Community signal
39 reports