token-goat 2.9.29 → 2.9.30
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/README.md +34 -40
- package/SECURITY.md +28 -10
- package/THIRD_PARTY_NOTICES.md +40 -3
- package/dist/native/linux-arm64/tg-hook +0 -0
- package/dist/native/linux-x64/tg-hook +0 -0
- package/dist/ort-wasm-simd-threaded.mjs +59 -0
- package/dist/token-goat-chunk-3CHUNJ2O.mjs +53 -0
- package/dist/token-goat-chunk-3Z5S4KGM.mjs +918 -0
- package/dist/token-goat-chunk-4FVIAHSI.mjs +211 -0
- package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-4JJS54TR.mjs} +4 -3
- package/dist/token-goat-chunk-4LCCNRTG.mjs +313 -0
- package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-54K3EUV3.mjs} +1 -1
- package/dist/token-goat-chunk-56EIMS3E.mjs +159 -0
- package/dist/token-goat-chunk-5BCIJXMO.mjs +609 -0
- package/dist/token-goat-chunk-5KDMCMF2.mjs +362 -0
- package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
- package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
- package/dist/{token-goat-chunk-GLXRTTLE.mjs → token-goat-chunk-64FBPDTK.mjs} +12 -8
- package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-664RTTUV.mjs} +28 -15
- package/dist/token-goat-chunk-67TQJ76B.mjs +57 -0
- package/dist/token-goat-chunk-6QMAS7AB.mjs +42 -0
- package/dist/token-goat-chunk-7BXSNBY5.mjs +253 -0
- package/dist/{token-goat-chunk-IVWI2OCK.mjs → token-goat-chunk-7F2UBPD3.mjs} +40 -11
- package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7IN2MKDS.mjs} +682 -501
- package/dist/token-goat-chunk-7NADEDKJ.mjs +124 -0
- package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-A3CK6N5Z.mjs} +618 -72
- package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-AFLYLHDH.mjs} +44 -31
- package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
- package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-APGZXSPS.mjs} +39 -146
- package/dist/{token-goat-chunk-D4ETHJD6.mjs → token-goat-chunk-ARDNEC2U.mjs} +9 -7
- package/dist/token-goat-chunk-ATCPY7EQ.mjs +134 -0
- package/dist/token-goat-chunk-B2RZZCSS.mjs +354 -0
- package/dist/{token-goat-chunk-BGYOZ6DO.mjs → token-goat-chunk-B45VMIIH.mjs} +6 -7
- package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
- package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-C63JQV5K.mjs} +45 -6
- package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-COBQGL5S.mjs} +2661 -2440
- package/dist/token-goat-chunk-COTXZHTS.mjs +39 -0
- package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-CYCEYAEO.mjs} +76 -16
- package/dist/token-goat-chunk-CZ3LUXYZ.mjs +4115 -0
- package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-DZX2YDPT.mjs} +2 -1
- package/dist/token-goat-chunk-E3OQX2XT.mjs +824 -0
- package/dist/token-goat-chunk-EFHMMIGP.mjs +68 -0
- package/dist/token-goat-chunk-ETBHVDB6.mjs +328 -0
- package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
- package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
- package/dist/{token-goat-chunk-RTMVLHWX.mjs → token-goat-chunk-FBNQNSJK.mjs} +2555 -5127
- package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
- package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-FZ3NEW5O.mjs} +33 -19
- package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
- package/dist/{token-goat-chunk-DNRPXHYH.mjs → token-goat-chunk-GFBSN7BD.mjs} +29 -401
- package/dist/{token-goat-chunk-XYWPOSCN.mjs → token-goat-chunk-GOLEOXZP.mjs} +763 -211
- package/dist/token-goat-chunk-H2K3QP6H.mjs +24 -0
- package/dist/token-goat-chunk-H2PHHGM5.mjs +188 -0
- package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
- package/dist/token-goat-chunk-HG45AF2B.mjs +2228 -0
- package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-HOJLCGDP.mjs} +12965 -11748
- package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-HYBFA5X3.mjs} +118 -19
- package/dist/token-goat-chunk-IVALLT3S.mjs +48 -0
- package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-IVKIZWAB.mjs} +3 -3
- package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-JB6QN6VF.mjs} +6 -4
- package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-JDHE26RP.mjs} +10 -3
- package/dist/{token-goat-chunk-FTP4U4QA.mjs → token-goat-chunk-JDU3EXSU.mjs} +12 -11
- package/dist/token-goat-chunk-JDWCRD6M.mjs +253 -0
- package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-JN4XMLSD.mjs} +5 -1
- package/dist/token-goat-chunk-JTQQGXZH.mjs +733 -0
- package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
- package/dist/token-goat-chunk-KQNZDCBD.mjs +47 -0
- package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-KWPNJBDH.mjs} +27 -3
- package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-LOBGHXPB.mjs} +30 -8
- package/dist/token-goat-chunk-MKPF4CL5.mjs +37 -0
- package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
- package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-N2NMER56.mjs} +25 -15
- package/dist/token-goat-chunk-NYKZLXMK.mjs +218 -0
- package/dist/token-goat-chunk-OJBNYTJP.mjs +3087 -0
- package/dist/token-goat-chunk-P4QMM4WK.mjs +295 -0
- package/dist/token-goat-chunk-PD5VKH46.mjs +184 -0
- package/dist/token-goat-chunk-PEPTHRFF.mjs +129 -0
- package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-PU7V3FD6.mjs} +8721 -11104
- package/dist/token-goat-chunk-PY533T7F.mjs +46 -0
- package/dist/token-goat-chunk-Q5VTGRH7.mjs +761 -0
- package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-QCLDAQTS.mjs} +31 -20
- package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-QSBRTGM2.mjs} +9 -2
- package/dist/{token-goat-chunk-VZQEWRVH.mjs → token-goat-chunk-RC35RBUL.mjs} +4 -4
- package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-RHXKCZX3.mjs} +873 -504
- package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-RZRTDST7.mjs} +17 -7
- package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-SJHWVNDQ.mjs} +15 -21
- package/dist/token-goat-chunk-SMVRN2HU.mjs +188 -0
- package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-SQSSNQPE.mjs} +2295 -1718
- package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-T4FK7VOV.mjs} +2 -2
- package/dist/token-goat-chunk-U4N3BN2W.mjs +92 -0
- package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
- package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-UQ5UK2T7.mjs} +15 -4
- package/dist/token-goat-chunk-USILZ3T3.mjs +53 -0
- package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-VES7EL7O.mjs} +7 -1
- package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-VL3YIFHZ.mjs} +389 -14
- package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-VPBBTSJR.mjs} +356 -129
- package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-W3QCJS6G.mjs} +10 -2
- package/dist/{token-goat-chunk-LZNBQTDK.mjs → token-goat-chunk-WY3L4DVT.mjs} +11 -7
- package/dist/token-goat-chunk-XKI4SEMX.mjs +66 -0
- package/dist/token-goat-chunk-XU4P6Z24.mjs +133 -0
- package/dist/{token-goat-chunk-H5J3C56Q.mjs → token-goat-chunk-Y776AENC.mjs} +112 -26
- package/dist/token-goat-chunk-YARZFCZS.mjs +359 -0
- package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-Z44YO3QZ.mjs} +4 -0
- package/dist/token-goat-chunk-Z57YODA2.mjs +35 -0
- package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-ZCDTCVIS.mjs} +48 -29
- package/dist/token-goat-chunk-ZEJVMUQH.mjs +48 -0
- package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
- package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
- package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-ZQSJMO2R.mjs} +338 -170
- package/dist/token-goat-hook-client.cjs +87 -23
- package/dist/token-goat-hook-client.mjs +3 -3
- package/dist/token-goat-hook.mjs +46 -30
- package/dist/token-goat.core.mjs +6 -6
- package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
- package/docs/cli.md +80 -46
- package/docs/install.md +47 -14
- package/docs/security.md +7 -7
- package/package.json +17 -7
- package/scripts/verify-native-dist.mjs +386 -0
- package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
- package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
- package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
- package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
- package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
- package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
- package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
- package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
- package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
- package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
- package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
- package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
|
@@ -3,7 +3,13 @@ const require = __cjsRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
queryCsv,
|
|
5
5
|
quoteCsvCell
|
|
6
|
-
} from "./token-goat-chunk-
|
|
6
|
+
} from "./token-goat-chunk-N2NMER56.mjs";
|
|
7
|
+
import {
|
|
8
|
+
redactSecrets
|
|
9
|
+
} from "./token-goat-chunk-4FVIAHSI.mjs";
|
|
10
|
+
import {
|
|
11
|
+
loadConfig
|
|
12
|
+
} from "./token-goat-chunk-7IN2MKDS.mjs";
|
|
7
13
|
import {
|
|
8
14
|
NotAnOfficeDocumentError,
|
|
9
15
|
assertOoxmlWithinDeadline,
|
|
@@ -12,13 +18,13 @@ import {
|
|
|
12
18
|
ooxmlWorkDeadline,
|
|
13
19
|
parseOoxmlPart,
|
|
14
20
|
readOoxmlZip
|
|
15
|
-
} from "./token-goat-chunk-
|
|
16
|
-
import {
|
|
17
|
-
displaySafeText
|
|
18
|
-
} from "./token-goat-chunk-NMTKNYGF.mjs";
|
|
21
|
+
} from "./token-goat-chunk-IVKIZWAB.mjs";
|
|
19
22
|
import {
|
|
20
23
|
DocumentRefusedError
|
|
21
24
|
} from "./token-goat-chunk-Y4AFKTHK.mjs";
|
|
25
|
+
import {
|
|
26
|
+
displaySafeText
|
|
27
|
+
} from "./token-goat-chunk-FNFBKLRD.mjs";
|
|
22
28
|
import {
|
|
23
29
|
init_define_import_meta_env
|
|
24
30
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -562,14 +568,18 @@ async function xlsxColumns(filePath, sheetName, sampleLimit = 100) {
|
|
|
562
568
|
columns: colSummaries
|
|
563
569
|
};
|
|
564
570
|
}
|
|
565
|
-
function formatXlsxColumns(result) {
|
|
571
|
+
function formatXlsxColumns(result, config = loadConfig()) {
|
|
566
572
|
if (result.columns.length === 0) return `Sheet "${displaySafeText(result.sheetName)}" is empty`;
|
|
573
|
+
const clip = (v) => {
|
|
574
|
+
const safe = redactSecrets(v, config).text;
|
|
575
|
+
return safe.length > 30 ? safe.slice(0, 27) + "..." : safe;
|
|
576
|
+
};
|
|
567
577
|
const lines = [
|
|
568
578
|
`Sheet: ${displaySafeText(result.sheetName)} (${result.totalSheetRows} data rows, ${result.columns.length} columns; sampled first ${result.sampleRows} rows)`
|
|
569
579
|
];
|
|
570
580
|
for (const c of result.columns) {
|
|
571
581
|
const pct = result.sampleRows > 0 ? Math.round(c.nonEmptyRows / c.sampleRows * 100) : 0;
|
|
572
|
-
const samples = c.sampleValues.length > 0 ? ` (e.g. ${c.sampleValues.map((v) => JSON.stringify(
|
|
582
|
+
const samples = c.sampleValues.length > 0 ? ` (e.g. ${c.sampleValues.map((v) => JSON.stringify(clip(v))).join(", ")})` : " (all empty)";
|
|
573
583
|
lines.push(` ${c.letter.padEnd(4)} ${displaySafeText(c.name).padEnd(25)} ${c.nonEmptyRows}/${c.sampleRows} (${pct}%)${samples}`);
|
|
574
584
|
}
|
|
575
585
|
return lines.join("\n");
|
|
@@ -2,24 +2,17 @@ import { createRequire as __cjsRequire } from 'node:module';
|
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
estimateTokensFromLength
|
|
5
|
-
} from "./token-goat-chunk-
|
|
5
|
+
} from "./token-goat-chunk-JB6QN6VF.mjs";
|
|
6
|
+
import {
|
|
7
|
+
matchRestOfLine
|
|
8
|
+
} from "./token-goat-chunk-EVMZJ27Z.mjs";
|
|
6
9
|
import {
|
|
7
10
|
displaySafeText
|
|
8
|
-
} from "./token-goat-chunk-
|
|
11
|
+
} from "./token-goat-chunk-FNFBKLRD.mjs";
|
|
9
12
|
import {
|
|
10
13
|
init_define_import_meta_env
|
|
11
14
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
12
15
|
|
|
13
|
-
// src/claude_config_dir.ts
|
|
14
|
-
init_define_import_meta_env();
|
|
15
|
-
import * as os from "node:os";
|
|
16
|
-
import * as path from "node:path";
|
|
17
|
-
function claudeConfigDir(homeDir = os.homedir()) {
|
|
18
|
-
const override = process.env["CLAUDE_CONFIG_DIR"];
|
|
19
|
-
if (override !== void 0 && override !== "") return override;
|
|
20
|
-
return path.join(homeDir, ".claude");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
16
|
// src/resident_context.ts
|
|
24
17
|
init_define_import_meta_env();
|
|
25
18
|
import * as fs from "node:fs";
|
|
@@ -59,14 +52,16 @@ function messageText(message) {
|
|
|
59
52
|
return out;
|
|
60
53
|
}
|
|
61
54
|
function skillNameFromBody(text) {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
const dirAt = /^Base directory for this skill:/m.exec(text);
|
|
56
|
+
const dir = dirAt === null ? null : matchRestOfLine(text, dirAt.index + dirAt[0].length, 0);
|
|
57
|
+
if (dir !== null) {
|
|
58
|
+
const segments = dir.split(/[\\/]/).filter((s) => s.length > 0);
|
|
65
59
|
const last = segments[segments.length - 1];
|
|
66
60
|
if (last !== void 0 && last.length > 0) return last;
|
|
67
61
|
}
|
|
68
|
-
const
|
|
69
|
-
|
|
62
|
+
const hashAt = /^#(?=\s)/m.exec(text);
|
|
63
|
+
const heading = hashAt === null ? null : matchRestOfLine(text, hashAt.index + 1, 1);
|
|
64
|
+
if (heading !== null && heading.length > 0) return heading;
|
|
70
65
|
return null;
|
|
71
66
|
}
|
|
72
67
|
function readTaskList(attachment, bytes) {
|
|
@@ -111,9 +106,9 @@ function collectInvokedSkills(acc, record) {
|
|
|
111
106
|
function skillName(skill) {
|
|
112
107
|
const name = skill["name"];
|
|
113
108
|
if (typeof name === "string" && name.trim() !== "") return name.trim();
|
|
114
|
-
const
|
|
115
|
-
if (typeof
|
|
116
|
-
const segments =
|
|
109
|
+
const path = skill["path"];
|
|
110
|
+
if (typeof path !== "string") return null;
|
|
111
|
+
const segments = path.split(/[\\/]/).filter((part) => part !== "");
|
|
117
112
|
const last = segments[segments.length - 1];
|
|
118
113
|
return last === void 0 || last === "" ? null : last;
|
|
119
114
|
}
|
|
@@ -225,7 +220,6 @@ function accumulateResidentLines(lines) {
|
|
|
225
220
|
}
|
|
226
221
|
|
|
227
222
|
export {
|
|
228
|
-
claudeConfigDir,
|
|
229
223
|
createResidentContextStats,
|
|
230
224
|
accumulateResidentLine,
|
|
231
225
|
summarizeResidentContext,
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
|
+
const require = __cjsRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
LOCK_WAIT_MS_HARDENED,
|
|
5
|
+
atomicWriteText,
|
|
6
|
+
ensureDirSync,
|
|
7
|
+
withFileLock
|
|
8
|
+
} from "./token-goat-chunk-GOLEOXZP.mjs";
|
|
9
|
+
import {
|
|
10
|
+
dataDir
|
|
11
|
+
} from "./token-goat-chunk-VES7EL7O.mjs";
|
|
12
|
+
import {
|
|
13
|
+
init_define_import_meta_env
|
|
14
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
15
|
+
|
|
16
|
+
// src/model_download_gate.ts
|
|
17
|
+
init_define_import_meta_env();
|
|
18
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
19
|
+
import * as fs from "node:fs";
|
|
20
|
+
import * as path from "node:path";
|
|
21
|
+
var MODEL_DOWNLOAD_HOST = "huggingface.co";
|
|
22
|
+
var RUNTIME_DOWNLOAD_HOST = "registry.npmjs.org";
|
|
23
|
+
var FIRST_HOLD_MS = 10 * 60 * 1e3;
|
|
24
|
+
var MAX_HOLD_MS = 60 * 60 * 1e3;
|
|
25
|
+
var CONSECUTIVE_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
26
|
+
var CLOCK_SKEW_MS = 60 * 1e3;
|
|
27
|
+
var DownloadFailedError = class extends Error {
|
|
28
|
+
failedAt;
|
|
29
|
+
url;
|
|
30
|
+
constructor(message, url, failedAt, cause) {
|
|
31
|
+
super(message, cause === void 0 ? void 0 : { cause });
|
|
32
|
+
this.name = "DownloadFailedError";
|
|
33
|
+
this.url = url;
|
|
34
|
+
this.failedAt = failedAt;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var DownloadCooldownError = class extends Error {
|
|
38
|
+
failedAt;
|
|
39
|
+
retryAt;
|
|
40
|
+
lastMessage;
|
|
41
|
+
url;
|
|
42
|
+
constructor(url, cooldown, now = Date.now()) {
|
|
43
|
+
super(`Not downloading ${url} yet: the last try, ${formatAgo(now - cooldown.at)} ago, failed with ${cooldown.message}. It is tried again automatically after ${new Date(cooldown.retryAt).toLocaleTimeString()}.`);
|
|
44
|
+
this.name = "DownloadCooldownError";
|
|
45
|
+
this.url = url;
|
|
46
|
+
this.failedAt = cooldown.at;
|
|
47
|
+
this.retryAt = cooldown.retryAt;
|
|
48
|
+
this.lastMessage = cooldown.message;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
function downloadFailureRecordPath() {
|
|
52
|
+
return path.join(dataDir(), "models", "download-failures.json");
|
|
53
|
+
}
|
|
54
|
+
function downloadHoldMs(failures) {
|
|
55
|
+
return Math.min(FIRST_HOLD_MS * 2 ** Math.max(0, failures - 1), MAX_HOLD_MS);
|
|
56
|
+
}
|
|
57
|
+
function hostOf(hostOrUrl) {
|
|
58
|
+
if (!hostOrUrl.includes("://")) return hostOrUrl.toLowerCase();
|
|
59
|
+
try {
|
|
60
|
+
return new URL(hostOrUrl).host.toLowerCase();
|
|
61
|
+
} catch {
|
|
62
|
+
return hostOrUrl.toLowerCase();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function isFailure(value) {
|
|
66
|
+
if (value === null || typeof value !== "object") return false;
|
|
67
|
+
const v = value;
|
|
68
|
+
return typeof v["url"] === "string" && typeof v["message"] === "string" && Number.isFinite(v["at"]) && Number.isInteger(v["failures"]) && v["failures"] >= 1;
|
|
69
|
+
}
|
|
70
|
+
function readRecord() {
|
|
71
|
+
let parsed;
|
|
72
|
+
try {
|
|
73
|
+
parsed = JSON.parse(fs.readFileSync(downloadFailureRecordPath(), "utf-8"));
|
|
74
|
+
} catch {
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
78
|
+
const out = {};
|
|
79
|
+
for (const [host, entry] of Object.entries(parsed)) if (isFailure(entry)) out[host] = entry;
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
function writeRecord(record) {
|
|
83
|
+
const file = downloadFailureRecordPath();
|
|
84
|
+
if (Object.keys(record).length === 0) fs.rmSync(file, { force: true });
|
|
85
|
+
else atomicWriteText(file, `${JSON.stringify(record, null, 2)}
|
|
86
|
+
`);
|
|
87
|
+
}
|
|
88
|
+
function lastDownloadFailure(hostOrUrl = MODEL_DOWNLOAD_HOST) {
|
|
89
|
+
return readRecord()[hostOf(hostOrUrl)] ?? null;
|
|
90
|
+
}
|
|
91
|
+
function activeDownloadCooldown(hostOrUrl = MODEL_DOWNLOAD_HOST, now = Date.now()) {
|
|
92
|
+
const host = hostOf(hostOrUrl);
|
|
93
|
+
const last = lastDownloadFailure(host);
|
|
94
|
+
if (!last || last.at > now + CLOCK_SKEW_MS) return null;
|
|
95
|
+
const retryAt = last.at + downloadHoldMs(last.failures);
|
|
96
|
+
return now < retryAt ? { ...last, host, retryAt } : null;
|
|
97
|
+
}
|
|
98
|
+
function updateRecord(mutate, now) {
|
|
99
|
+
const file = downloadFailureRecordPath();
|
|
100
|
+
const run = () => {
|
|
101
|
+
const record = readRecord();
|
|
102
|
+
for (const [host, entry] of Object.entries(record)) if (now - entry.at >= CONSECUTIVE_WINDOW_MS) delete record[host];
|
|
103
|
+
const value = mutate(record, now);
|
|
104
|
+
writeRecord(record);
|
|
105
|
+
return { value };
|
|
106
|
+
};
|
|
107
|
+
try {
|
|
108
|
+
ensureDirSync(path.dirname(file));
|
|
109
|
+
} catch {
|
|
110
|
+
}
|
|
111
|
+
return (withFileLock(`${file}.lock`, run, { waitMs: LOCK_WAIT_MS_HARDENED }) ?? run()).value;
|
|
112
|
+
}
|
|
113
|
+
function recordDownloadFailure(url, err, now = Date.now(), startedAt) {
|
|
114
|
+
const host = hostOf(url);
|
|
115
|
+
const message = typeof err === "string" ? err : describeCause(err);
|
|
116
|
+
return updateRecord((record) => {
|
|
117
|
+
const prev = record[host];
|
|
118
|
+
const known = prev !== void 0 && prev.at <= now + CLOCK_SKEW_MS && now - prev.at < CONSECUTIVE_WINDOW_MS;
|
|
119
|
+
const sameOutage = known && startedAt !== void 0 && prev.at >= startedAt;
|
|
120
|
+
const entry = { url, message, at: now, failures: !known ? 1 : sameOutage ? prev.failures : prev.failures + 1 };
|
|
121
|
+
record[host] = entry;
|
|
122
|
+
return entry;
|
|
123
|
+
}, now);
|
|
124
|
+
}
|
|
125
|
+
function clearDownloadFailure(url) {
|
|
126
|
+
const host = hostOf(url);
|
|
127
|
+
if (!(host in readRecord())) return;
|
|
128
|
+
updateRecord((record) => delete record[host], Date.now());
|
|
129
|
+
}
|
|
130
|
+
function detailOf(value) {
|
|
131
|
+
if (value instanceof AggregateError && value.errors.length > 0 && value.message === "") return detailOf(value.errors[0]);
|
|
132
|
+
if (value instanceof Error) return value.message !== "" ? value.message : String(value.code ?? value.name);
|
|
133
|
+
if (value !== null && typeof value === "object") return String(value.code ?? "");
|
|
134
|
+
return value === void 0 ? "" : String(value);
|
|
135
|
+
}
|
|
136
|
+
function describeCause(err) {
|
|
137
|
+
const head = detailOf(err);
|
|
138
|
+
const extra = [];
|
|
139
|
+
let seen = head;
|
|
140
|
+
let cursor = err instanceof Error ? err.cause : void 0;
|
|
141
|
+
for (let depth = 0; cursor !== void 0 && cursor !== null && depth < 5; depth++) {
|
|
142
|
+
const detail = detailOf(cursor);
|
|
143
|
+
if (detail !== "" && !seen.includes(detail)) {
|
|
144
|
+
extra.push(detail);
|
|
145
|
+
seen += ` ${detail}`;
|
|
146
|
+
}
|
|
147
|
+
cursor = cursor instanceof Error ? cursor.cause : void 0;
|
|
148
|
+
}
|
|
149
|
+
return extra.length > 0 ? `${head} (${extra.join("; ")})` : head;
|
|
150
|
+
}
|
|
151
|
+
function failedAtOf(err) {
|
|
152
|
+
let cursor = err;
|
|
153
|
+
for (let depth = 0; cursor !== null && typeof cursor === "object" && depth < 5; depth++) {
|
|
154
|
+
const at = cursor.failedAt;
|
|
155
|
+
if (typeof at === "number") return at;
|
|
156
|
+
cursor = cursor.cause;
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
function formatAgo(ms) {
|
|
161
|
+
const minutes = Math.max(0, Math.round(ms / 6e4));
|
|
162
|
+
if (minutes < 1) return "moments";
|
|
163
|
+
return minutes === 1 ? "1 minute" : `${minutes} minutes`;
|
|
164
|
+
}
|
|
165
|
+
var explicit = new AsyncLocalStorage();
|
|
166
|
+
function withExplicitDownload(fn) {
|
|
167
|
+
return explicit.run(true, fn);
|
|
168
|
+
}
|
|
169
|
+
function isExplicitDownload() {
|
|
170
|
+
return explicit.getStore() === true;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export {
|
|
174
|
+
MODEL_DOWNLOAD_HOST,
|
|
175
|
+
RUNTIME_DOWNLOAD_HOST,
|
|
176
|
+
DownloadFailedError,
|
|
177
|
+
DownloadCooldownError,
|
|
178
|
+
downloadFailureRecordPath,
|
|
179
|
+
downloadHoldMs,
|
|
180
|
+
lastDownloadFailure,
|
|
181
|
+
activeDownloadCooldown,
|
|
182
|
+
recordDownloadFailure,
|
|
183
|
+
clearDownloadFailure,
|
|
184
|
+
describeCause,
|
|
185
|
+
failedAtOf,
|
|
186
|
+
withExplicitDownload,
|
|
187
|
+
isExplicitDownload
|
|
188
|
+
};
|