






















@@ -1700,7 +1700,7 @@ async function p12OpenAiLiveProof() {
17001700return "OpenAI model auth probe consumed API key through plugin-managed auth-profile SecretRef";
17011701}
170217021703-async function runPtySecretsConfigurePreset(envCtx) {
1703+async function runPtySecretsConfigurePreset(envCtx, options = {}) {
17041704const { spawn } = await import("@lydell/node-pty");
17051705const command = await resolveOpenClawCommand(
17061706["secrets", "configure", "--providers-only", "--apply", "--yes", "--allow-exec", "--json"],
@@ -1715,16 +1715,39 @@ async function runPtySecretsConfigurePreset(envCtx) {
17151715});
17161716const output = createOutputCapture("secrets configure stdout");
17171717let phase = "providers-menu";
1718+const keyTimers = new Set();
1719+const clearKeyTimers = () => {
1720+for (const keyTimer of keyTimers) {
1721+clearTimeout(keyTimer);
1722+}
1723+keyTimers.clear();
1724+};
17181725const sendKeys = (keys) => {
17191726keys.forEach((key, index) => {
1720-setTimeout(() => child.write(key), index * 80);
1727+const keyTimer = setTimeout(() => {
1728+keyTimers.delete(keyTimer);
1729+child.write(key);
1730+}, index * 80);
1731+keyTimers.add(keyTimer);
17211732});
17221733};
17231734return await new Promise((resolve, reject) => {
1735+let timedOut = false;
1736+let forceKillAt;
1737+let forceKillTimer;
1738+const timeoutMs = options.timeoutMs ?? 60000;
1739+const timeoutKillGraceMs = options.timeoutKillGraceMs ?? COMMAND_TIMEOUT_KILL_GRACE_MS;
17241740const timer = setTimeout(() => {
1725-child.kill();
1726-reject(new Error(`secrets configure preset timed out: ${scrub(output.text())}`));
1727-}, 60000);
1741+timedOut = true;
1742+signalPtyProcessTree(child, "SIGHUP");
1743+forceKillAt = Date.now() + timeoutKillGraceMs;
1744+forceKillTimer = setTimeout(() => {
1745+forceKillTimer = undefined;
1746+forceKillAt = undefined;
1747+signalPtyProcessTree(child, "SIGKILL");
1748+}, timeoutKillGraceMs);
1749+forceKillTimer.unref?.();
1750+}, timeoutMs);
17281751child.onData((data) => {
17291752output.append(data);
17301753const outputText = output.text();
@@ -1746,6 +1769,20 @@ async function runPtySecretsConfigurePreset(envCtx) {
17461769});
17471770child.onExit(({ exitCode }) => {
17481771clearTimeout(timer);
1772+clearKeyTimers();
1773+if (timedOut) {
1774+void finishTimedOutPtyProcessTree(child, {
1775+ forceKillAt,
1776+ forceKillTimer,
1777+ timeoutKillGraceMs,
1778+}).finally(() =>
1779+reject(new Error(`secrets configure preset timed out: ${scrub(output.text())}`)),
1780+);
1781+return;
1782+}
1783+if (forceKillTimer) {
1784+clearTimeout(forceKillTimer);
1785+}
17491786if (exitCode !== 0) {
17501787reject(new Error(`secrets configure preset failed (${exitCode}): ${scrub(output.text())}`));
17511788return;
@@ -1755,6 +1792,57 @@ async function runPtySecretsConfigurePreset(envCtx) {
17551792});
17561793}
175717941795+async function finishTimedOutPtyProcessTree(
1796+child,
1797+{ forceKillAt, forceKillTimer, timeoutKillGraceMs },
1798+) {
1799+const graceRemainingMs =
1800+forceKillAt === undefined ? timeoutKillGraceMs : Math.max(0, forceKillAt - Date.now());
1801+if (graceRemainingMs > 0) {
1802+await waitForPtyProcessTreeExit(child, graceRemainingMs);
1803+}
1804+if (forceKillTimer) {
1805+clearTimeout(forceKillTimer);
1806+}
1807+if (ptyProcessTreeIsAlive(child)) {
1808+signalPtyProcessTree(child, "SIGKILL");
1809+}
1810+await waitForPtyProcessTreeExit(child, timeoutKillGraceMs);
1811+}
1812+1813+function ptyProcessTreeIsAlive(child) {
1814+if (process.platform === "win32" || typeof child.pid !== "number") {
1815+return false;
1816+}
1817+try {
1818+process.kill(-child.pid, 0);
1819+return true;
1820+} catch (error) {
1821+return error?.code === "EPERM";
1822+}
1823+}
1824+1825+async function waitForPtyProcessTreeExit(child, timeoutMs) {
1826+const started = Date.now();
1827+while (Date.now() - started < timeoutMs) {
1828+if (!ptyProcessTreeIsAlive(child)) {
1829+return true;
1830+}
1831+await delay(50);
1832+}
1833+return !ptyProcessTreeIsAlive(child);
1834+}
1835+1836+function signalPtyProcessTree(child, signal) {
1837+if (process.platform !== "win32" && typeof child.pid === "number") {
1838+try {
1839+process.kill(-child.pid, signal);
1840+return;
1841+} catch {}
1842+}
1843+child.kill(signal);
1844+}
1845+17581846async function p13SecretsConfigurePreset() {
17591847await withProofEnv("p13", async (envCtx) => {
17601848const port = await allocatePort();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。