Files
codex/app/codex_account.js
T
jiantw83 68c78e6736
CI / Release Tag Version (pull_request) Successful in 4s
CI / Codex (pull_request) Successful in 13s
refactor(codex_account): 改用 Node.js 實作帳號查詢
2026-06-29 09:53:07 +00:00

123 lines
2.7 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// 透過 codex app-server 的 JSON-RPC account/read 取得目前登入帳號的 email。
//
// 這是 TUI `/status` Account 欄位的程式化來源,不解析本地 OAuth token
// 而是由 codex 自身回報登入帳號。將 email 印到 stdout(取不到時印空字串)。
const { spawn } = require("node:child_process");
const readline = require("node:readline");
const timeoutSeconds = Number(process.argv[2] ?? "25");
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds < 0) {
console.error("timeout_seconds must be a non-negative number.");
process.exit(2);
}
function sendJson(processHandle, message) {
try {
processHandle.stdin.write(`${JSON.stringify(message)}\n`);
} catch {
return false;
}
return true;
}
async function readAccountEmail() {
const processHandle = spawn("codex", ["app-server"], {
stdio: ["pipe", "pipe", "ignore"],
});
let settled = false;
let timer;
const cleanup = () => {
if (!processHandle.killed) {
processHandle.kill();
}
};
process.once("exit", cleanup);
process.once("SIGINT", () => {
cleanup();
process.exit(130);
});
process.once("SIGTERM", () => {
cleanup();
process.exit(143);
});
return await new Promise((resolve) => {
const done = (email = "") => {
if (settled) {
return;
}
settled = true;
clearTimeout(timer);
cleanup();
resolve(email);
};
timer = setTimeout(() => done(""), timeoutSeconds * 1000);
processHandle.once("error", () => done(""));
processHandle.once("exit", () => done(""));
processHandle.stdin.once("error", () => done(""));
const lines = readline.createInterface({
input: processHandle.stdout,
crlfDelay: Infinity,
});
lines.on("line", (line) => {
let message;
try {
message = JSON.parse(line);
} catch {
return;
}
if (message.id !== 2) {
return;
}
const email = message?.result?.account?.email;
done(typeof email === "string" ? email : "");
});
const messages = [
{
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: { clientInfo: { name: "ci", version: "1.0" } },
},
{
jsonrpc: "2.0",
method: "initialized",
params: {},
},
{
jsonrpc: "2.0",
id: 2,
method: "account/read",
params: {},
},
];
for (const message of messages) {
if (!sendJson(processHandle, message)) {
done("");
break;
}
}
});
}
readAccountEmail()
.then((email) => {
process.stdout.write(`${email}\n`);
})
.catch(() => {
process.stdout.write("\n");
});