github-router 0.3.261 → 0.3.269
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{attribution-settings-Bl0HHJQF.js → attribution-settings-B1txv_Lk.js} +4 -4
- package/dist/{attribution-settings-Bl0HHJQF.js.map → attribution-settings-B1txv_Lk.js.map} +1 -1
- package/dist/{auth-I8k2OOvA.js → auth-r-my7efo.js} +3 -3
- package/dist/{auth-I8k2OOvA.js.map → auth-r-my7efo.js.map} +1 -1
- package/dist/browser-bridge/index.js +67 -27
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/{check-usage-SOn7-cWc.js → check-usage-CZr2ZkG0.js} +4 -4
- package/dist/{check-usage-SOn7-cWc.js.map → check-usage-CZr2ZkG0.js.map} +1 -1
- package/dist/{claude-CEaI47j7.js → claude-BjNY0J6e.js} +15 -15
- package/dist/{claude-CEaI47j7.js.map → claude-BjNY0J6e.js.map} +1 -1
- package/dist/{codex-C6Eyz3EV.js → codex-CoRWpkHL.js} +5 -6
- package/dist/{codex-C6Eyz3EV.js.map → codex-CoRWpkHL.js.map} +1 -1
- package/dist/{debug-vshv4nIv.js → debug-CuuxCk_J.js} +2 -2
- package/dist/{debug-vshv4nIv.js.map → debug-CuuxCk_J.js.map} +1 -1
- package/dist/engine-DpVC7HRL.js +2 -0
- package/dist/{exec-DTO2oin0.js → exec-y8C_MU8A.js} +89 -18
- package/dist/exec-y8C_MU8A.js.map +1 -0
- package/dist/{gate-discovery-BnPhH_AC.js → gate-discovery-D-7oua8b.js} +6 -6
- package/dist/{gate-discovery-BnPhH_AC.js.map → gate-discovery-D-7oua8b.js.map} +1 -1
- package/dist/{get-copilot-usage-CYpAsYrM.js → get-copilot-usage-CFEpeA7E.js} +2 -2
- package/dist/{get-copilot-usage-CYpAsYrM.js.map → get-copilot-usage-CFEpeA7E.js.map} +1 -1
- package/dist/{internal-artifact-open-CZGO831M.js → internal-artifact-open-CDqPfegE.js} +2 -2
- package/dist/{internal-artifact-open-CZGO831M.js.map → internal-artifact-open-CDqPfegE.js.map} +1 -1
- package/dist/{internal-plan-review-6gkcOAjT.js → internal-plan-review-CH9qTHoZ.js} +3 -3
- package/dist/{internal-plan-review-6gkcOAjT.js.map → internal-plan-review-CH9qTHoZ.js.map} +1 -1
- package/dist/{internal-prompt-submit-CSJR24-y.js → internal-prompt-submit-Bve1s4z_.js} +5 -5
- package/dist/{internal-prompt-submit-CSJR24-y.js.map → internal-prompt-submit-Bve1s4z_.js.map} +1 -1
- package/dist/{internal-session-bind-DtSBTkQe.js → internal-session-bind-Cc8bMXHK.js} +2 -2
- package/dist/{internal-session-bind-DtSBTkQe.js.map → internal-session-bind-Cc8bMXHK.js.map} +1 -1
- package/dist/{internal-stop-hook-CiflCJO-.js → internal-stop-hook-Db5o9RcZ.js} +6 -6
- package/dist/{internal-stop-hook-CiflCJO-.js.map → internal-stop-hook-Db5o9RcZ.js.map} +1 -1
- package/dist/{internal-stop-review-_1Mqz7eT.js → internal-stop-review-CWE7_QVv.js} +2 -2
- package/dist/{internal-stop-review-_1Mqz7eT.js.map → internal-stop-review-CWE7_QVv.js.map} +1 -1
- package/dist/{lifecycle-DjC9tC1A.js → lifecycle-0XrazT05.js} +2 -2
- package/dist/{lifecycle-DjC9tC1A.js.map → lifecycle-0XrazT05.js.map} +1 -1
- package/dist/lifecycle-2M0IThRr.js +2 -0
- package/dist/{lifecycle-Bd1Fyf4B.js → lifecycle-AgNOtFRv.js} +3 -3
- package/dist/{lifecycle-Bd1Fyf4B.js.map → lifecycle-AgNOtFRv.js.map} +1 -1
- package/dist/lifecycle-C8kFsAj-.js +2 -0
- package/dist/main.js +14 -14
- package/dist/{models-uQgsKNNC.js → models-CJLt4XjP.js} +35 -30
- package/dist/models-CJLt4XjP.js.map +1 -0
- package/dist/{orchestration-BiZviyam.js → orchestration-B_Q3ncXI.js} +3 -3
- package/dist/{orchestration-BiZviyam.js.map → orchestration-B_Q3ncXI.js.map} +1 -1
- package/dist/paths-BbHtQAOs.js +2 -0
- package/dist/{paths-BXrbboAS.js → paths-Bg1_DWhi.js} +3 -3
- package/dist/{paths-BXrbboAS.js.map → paths-Bg1_DWhi.js.map} +1 -1
- package/dist/{peer-mcp-personas-V4AXhm9B.js → peer-mcp-personas-DSbBlgFt.js} +119 -45
- package/dist/peer-mcp-personas-DSbBlgFt.js.map +1 -0
- package/dist/{plan-review-hook-Bo4y1r3j.js → plan-review-hook-BKOcW5s4.js} +3 -3
- package/dist/{plan-review-hook-Bo4y1r3j.js.map → plan-review-hook-BKOcW5s4.js.map} +1 -1
- package/dist/{prompt-submit-hook-BFRFLSk5.js → prompt-submit-hook-F7Zih_au.js} +2 -2
- package/dist/{prompt-submit-hook-BFRFLSk5.js.map → prompt-submit-hook-F7Zih_au.js.map} +1 -1
- package/dist/{provision-BLwsOFCI.js → provision-CA-xwnFu.js} +5 -5
- package/dist/{provision-BLwsOFCI.js.map → provision-CA-xwnFu.js.map} +1 -1
- package/dist/{serve-De-kqWXM.js → serve-DHny4ewF.js} +20 -15
- package/dist/{serve-De-kqWXM.js.map → serve-DHny4ewF.js.map} +1 -1
- package/dist/{server-setup-BeeT8m-w.js → server-setup-Dd293T1O.js} +479 -75
- package/dist/server-setup-Dd293T1O.js.map +1 -0
- package/dist/{start-DEC0M8UH.js → start-P2rmHBkL.js} +3 -3
- package/dist/{start-DEC0M8UH.js.map → start-P2rmHBkL.js.map} +1 -1
- package/dist/{stop-gate-hook-DoYD9Wt8.js → stop-gate-hook-BqpumJtl.js} +12 -7
- package/dist/{stop-gate-hook-DoYD9Wt8.js.map → stop-gate-hook-BqpumJtl.js.map} +1 -1
- package/dist/{stop-gate-policy-CoMKWSsS.js → stop-gate-policy-C0XOBZhB.js} +3 -3
- package/dist/{stop-gate-policy-CoMKWSsS.js.map → stop-gate-policy-C0XOBZhB.js.map} +1 -1
- package/dist/{token-DWknHe9M.js → token-C_q95GF7.js} +124 -14
- package/dist/{token-DWknHe9M.js.map → token-C_q95GF7.js.map} +1 -1
- package/package.json +2 -2
- package/dist/engine-B4Ohhv5i.js +0 -2
- package/dist/exec-DTO2oin0.js.map +0 -1
- package/dist/file-log-reporter-vI8qCFNM.js +0 -158
- package/dist/file-log-reporter-vI8qCFNM.js.map +0 -1
- package/dist/lifecycle-CRTWEbiP.js +0 -2
- package/dist/lifecycle-DUPXAOQS.js +0 -2
- package/dist/models-uQgsKNNC.js.map +0 -1
- package/dist/paths-Dz1WyRJG.js +0 -2
- package/dist/peer-mcp-personas-V4AXhm9B.js.map +0 -1
- package/dist/server-setup-BeeT8m-w.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as PATHS } from "./paths-
|
|
1
|
+
import { t as PATHS } from "./paths-Bg1_DWhi.js";
|
|
2
2
|
import consola from "consola";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
@@ -876,20 +876,46 @@ const cacheCopilotVersion = async () => {
|
|
|
876
876
|
};
|
|
877
877
|
//#endregion
|
|
878
878
|
//#region src/services/github/poll-access-token.ts
|
|
879
|
+
/**
|
|
880
|
+
* Per-attempt cap for a single device-code poll.
|
|
881
|
+
*
|
|
882
|
+
* Deliberately NOT the shared transient-retry layer: a non-OK response here is
|
|
883
|
+
* the EXPECTED steady state (`authorization_pending` until the user finishes in
|
|
884
|
+
* their browser), so retrying it as a transient fault would just hammer GitHub
|
|
885
|
+
* inside a loop that is already a retry loop with its own interval.
|
|
886
|
+
*
|
|
887
|
+
* What was genuinely missing is a bound on a single attempt. Without a signal a
|
|
888
|
+
* hung socket blocks the loop forever: the `expiresAt` check only runs between
|
|
889
|
+
* attempts, so it can never fire while one attempt is stuck. This caps each
|
|
890
|
+
* attempt so the loop keeps ticking and the expiry bound stays real.
|
|
891
|
+
*/
|
|
892
|
+
const POLL_ATTEMPT_TIMEOUT_MS = 3e4;
|
|
879
893
|
async function pollAccessToken(deviceCode, clientId = GITHUB_CLIENT_ID) {
|
|
880
894
|
const sleepDuration = (deviceCode.interval + 1) * 1e3;
|
|
881
895
|
consola.debug(`Polling access token with interval of ${sleepDuration}ms`);
|
|
882
896
|
const expiresAt = Date.now() + deviceCode.expires_in * 1e3;
|
|
897
|
+
let lastFetchError;
|
|
883
898
|
while (Date.now() < expiresAt) {
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
899
|
+
let response;
|
|
900
|
+
try {
|
|
901
|
+
response = await fetch(`${GITHUB_BASE_URL}/login/oauth/access_token`, {
|
|
902
|
+
method: "POST",
|
|
903
|
+
headers: standardHeaders(),
|
|
904
|
+
body: JSON.stringify({
|
|
905
|
+
client_id: clientId,
|
|
906
|
+
device_code: deviceCode.device_code,
|
|
907
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
908
|
+
}),
|
|
909
|
+
signal: AbortSignal.timeout(POLL_ATTEMPT_TIMEOUT_MS)
|
|
910
|
+
});
|
|
911
|
+
} catch (err) {
|
|
912
|
+
lastFetchError = err;
|
|
913
|
+
consola.debug("Access-token poll attempt failed; retrying:", err);
|
|
914
|
+
if (Date.now() >= expiresAt) break;
|
|
915
|
+
await sleep(sleepDuration);
|
|
916
|
+
continue;
|
|
917
|
+
}
|
|
918
|
+
lastFetchError = void 0;
|
|
893
919
|
if (!response.ok) {
|
|
894
920
|
consola.error("Failed to poll access token:", await response.text());
|
|
895
921
|
if (Date.now() >= expiresAt) break;
|
|
@@ -903,23 +929,107 @@ async function pollAccessToken(deviceCode, clientId = GITHUB_CLIENT_ID) {
|
|
|
903
929
|
if (Date.now() >= expiresAt) break;
|
|
904
930
|
await sleep(sleepDuration);
|
|
905
931
|
}
|
|
932
|
+
if (lastFetchError !== void 0) throw new Error("Could not reach GitHub to complete device-code authorization. Check network/proxy/TLS settings and run auth again.", { cause: lastFetchError });
|
|
906
933
|
throw new Error("Device code expired. Please run auth again.");
|
|
907
934
|
}
|
|
908
935
|
//#endregion
|
|
909
936
|
//#region src/lib/token.ts
|
|
910
937
|
const readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, "utf8");
|
|
911
|
-
|
|
938
|
+
/**
|
|
939
|
+
* Backoff for a transient Windows rename failure. On Windows `fs.rename` over
|
|
940
|
+
* an existing destination transiently fails with EPERM / EBUSY / EACCES when
|
|
941
|
+
* anything else holds the target open for a moment (antivirus, the search
|
|
942
|
+
* indexer, a backup agent). Nothing is wrong and the handle closes microseconds
|
|
943
|
+
* later — but without a retry, a scan landing on the wrong millisecond throws
|
|
944
|
+
* out of a credential write and costs the user a re-auth. Same delays as
|
|
945
|
+
* `renameWithRetry` in `~/lib/claude-md-injection`, which documents the
|
|
946
|
+
* underlying behavior at length.
|
|
947
|
+
*/
|
|
948
|
+
const RENAME_RETRY_DELAYS_MS = [
|
|
949
|
+
50,
|
|
950
|
+
200,
|
|
951
|
+
500
|
|
952
|
+
];
|
|
953
|
+
/**
|
|
954
|
+
* Replace a credential file atomically: temp + rename, with bounded retry.
|
|
955
|
+
*
|
|
956
|
+
* A plain `fs.writeFile` truncates the destination before it writes, so a
|
|
957
|
+
* crash, a full disk, or a kill mid-write leaves a truncated token on disk and
|
|
958
|
+
* forces the user through a re-auth. `rename` within the same directory is
|
|
959
|
+
* atomic on both NTFS and POSIX, so a reader sees either the old token or the
|
|
960
|
+
* new one, never a partial.
|
|
961
|
+
*
|
|
962
|
+
* The temp name uses `randomBytes`, not `Math.random()`: this names a file that
|
|
963
|
+
* briefly holds a credential, and a predictable name in a shared directory
|
|
964
|
+
* invites a pre-creation race. Combined with `flag: "wx"` (fail if it exists)
|
|
965
|
+
* the write refuses to follow anything an attacker pre-placed, rather than
|
|
966
|
+
* silently writing the token through a planted symlink.
|
|
967
|
+
*
|
|
968
|
+
* Permissions: the temp file is created 0o600, and `rename` carries that mode
|
|
969
|
+
* with it on POSIX — so the destination's mode is preserved, not weakened.
|
|
970
|
+
* (On Windows `chmod` is a no-op anyway; see `chmodIfPossible` in `~/lib/paths`.
|
|
971
|
+
* Both token files live under `CLAUDE_RUNTIME_DIR`, which is chmod'd 0o700, so
|
|
972
|
+
* directory ACLs are what actually protect them there.)
|
|
973
|
+
*/
|
|
974
|
+
async function writeTokenFileAtomic(filePath, token) {
|
|
975
|
+
const tmp = `${filePath}.${process.pid}.${randomBytes(8).toString("hex")}.tmp`;
|
|
976
|
+
try {
|
|
977
|
+
await fs.writeFile(tmp, token, {
|
|
978
|
+
mode: 384,
|
|
979
|
+
flag: "wx"
|
|
980
|
+
});
|
|
981
|
+
let lastErr;
|
|
982
|
+
let renamed = false;
|
|
983
|
+
for (let attempt = 0; attempt <= RENAME_RETRY_DELAYS_MS.length; attempt++) try {
|
|
984
|
+
await fs.rename(tmp, filePath);
|
|
985
|
+
renamed = true;
|
|
986
|
+
break;
|
|
987
|
+
} catch (err) {
|
|
988
|
+
lastErr = err;
|
|
989
|
+
if (attempt < RENAME_RETRY_DELAYS_MS.length) await new Promise((resolve) => setTimeout(resolve, RENAME_RETRY_DELAYS_MS[attempt]));
|
|
990
|
+
}
|
|
991
|
+
if (!renamed) throw lastErr;
|
|
992
|
+
} catch (err) {
|
|
993
|
+
await fs.unlink(tmp).catch(() => {});
|
|
994
|
+
throw err;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
const writeGithubToken = (token) => writeTokenFileAtomic(PATHS.GITHUB_TOKEN_PATH, token);
|
|
912
998
|
const readGithubAgentToken = () => fs.readFile(PATHS.GITHUB_AGENT_TOKEN_PATH, "utf8");
|
|
913
|
-
const writeGithubAgentToken = (token) =>
|
|
999
|
+
const writeGithubAgentToken = (token) => writeTokenFileAtomic(PATHS.GITHUB_AGENT_TOKEN_PATH, token);
|
|
1000
|
+
/**
|
|
1001
|
+
* Fetch the Copilot token and keep it fresh in the background.
|
|
1002
|
+
*
|
|
1003
|
+
* Returns a disposer that stops the refresh loop. **Long-lived callers**
|
|
1004
|
+
* (`start`/`claude`/`codex`, via `setupAndServe`) can ignore it — the interval
|
|
1005
|
+
* is `unref()`d, so it never holds the event loop open on its own. The one-shot
|
|
1006
|
+
* `models` command calls it, so ownership of the timer is explicit rather than
|
|
1007
|
+
* implied by a runtime flag. (`check-usage` does not call this function at all;
|
|
1008
|
+
* it only needs `setupGitHubToken`.)
|
|
1009
|
+
*
|
|
1010
|
+
* Both halves are load-bearing, for different failure modes. Without the
|
|
1011
|
+
* `unref()`, `github-router models` printed its full correct output and then
|
|
1012
|
+
* hung forever: its success path just returns (only the failure branches call
|
|
1013
|
+
* `process.exit`), and the un-unref'd interval pinned the event loop. Without
|
|
1014
|
+
* the disposer, that fix would depend on a property no caller can see, so the
|
|
1015
|
+
* next one-shot command would inherit the same trap.
|
|
1016
|
+
*/
|
|
914
1017
|
const setupCopilotToken = async () => {
|
|
915
1018
|
const { token, refresh_in } = await getCopilotToken();
|
|
916
1019
|
state.copilotToken = token;
|
|
917
1020
|
consola.debug("GitHub Copilot Token fetched successfully!");
|
|
918
1021
|
if (state.showToken) consola.info("Copilot token:", token);
|
|
919
1022
|
const refreshInterval = Math.max((refresh_in - 60) * 1e3, 1e3);
|
|
920
|
-
setInterval(() => {
|
|
1023
|
+
const handle = setInterval(() => {
|
|
921
1024
|
refreshCopilotToken("interval");
|
|
922
1025
|
}, refreshInterval);
|
|
1026
|
+
handle.unref?.();
|
|
1027
|
+
let stopped = false;
|
|
1028
|
+
return () => {
|
|
1029
|
+
if (stopped) return;
|
|
1030
|
+
stopped = true;
|
|
1031
|
+
clearInterval(handle);
|
|
1032
|
+
};
|
|
923
1033
|
};
|
|
924
1034
|
let inflightRefresh;
|
|
925
1035
|
let lastRefreshSuccess = 0;
|
|
@@ -1072,4 +1182,4 @@ async function warnIfAgentScopesInsufficient() {
|
|
|
1072
1182
|
//#endregion
|
|
1073
1183
|
export { copilotHeaders as C, githubHeaders as D, githubAgentHeaders as E, state as O, copilotBaseUrl as S, githubAgentGraphQLHeaders as T, withTransientRetry as _, cacheCopilotVersion as a, GITHUB_API_BASE_URL as b, filterBetaHeader as c, resolveModel as d, sleep as f, fetchWithTransientRetry as g, isAllowedCopilotHost as h, tryRefreshAndRetry as i, isNullish as l, getGitHubUser as m, setupGitHubAgentToken as n, cacheModels as o, getModels as p, setupGitHubToken as r, cacheVSCodeVersion as s, setupCopilotToken as t, resolveCodexModel as u, HTTPError as v, copilotVersion as w, GITHUB_GRAPHQL_URL as x, forwardError as y };
|
|
1074
1184
|
|
|
1075
|
-
//# sourceMappingURL=token-
|
|
1185
|
+
//# sourceMappingURL=token-C_q95GF7.js.map
|