@ls-stack/agent-eval 0.42.2 → 0.45.0
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/{app-DPamBr5R.mjs → app-BZmhhSFZ.mjs} +10 -4
- package/dist/apps/web/dist/assets/index-BU3IqUso.css +1 -0
- package/dist/apps/web/dist/assets/index-am2Knit6.js +140 -0
- package/dist/apps/web/dist/index.html +2 -2
- package/dist/bin.mjs +1 -1
- package/dist/{cli-BeJCJMQo.mjs → cli-vdJYkEVk.mjs} +28 -5
- package/dist/index.d.mts +368 -75
- package/dist/index.mjs +3 -3
- package/dist/runChild.mjs +1 -1
- package/dist/{runOrchestration-OVUFw1fL.mjs → runOrchestration-BFdxG9ws.mjs} +259 -250
- package/dist/{runner-BJQq7cpd.mjs → runner--aH0jO4Z.mjs} +1 -1
- package/dist/{runner-B1KygirW.mjs → runner-DJWn_7p0.mjs} +2 -2
- package/dist/{src-D7_xKo7h.mjs → src-BRqs3kSA.mjs} +2 -2
- package/package.json +3 -3
- package/skills/agent-eval/SKILL.md +14 -12
- package/dist/apps/web/dist/assets/index-DH0qYD76.js +0 -140
- package/dist/apps/web/dist/assets/index-eFM9VIsz.css +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as getCurrentScope, B as deserializeCacheValue, F as evalSpan, G as readManualInputFile, H as serializeCacheValue, I as evalTracer, J as appendToEvalOutput, K as evalExpect, L as hashCacheKey, Lt as getEvalRegistry, M as z, N as buildTraceTree, P as captureEvalSpanError, Q as evalTime, R as hashCacheKeySync, U as repoFile, V as serializeCacheRecording, W as manualInputFileValueSchema, X as evalAssert, Z as evalLog, _t as extractLlmCalls, at as nextEvalId, ct as runInExistingEvalScope, dt as startEvalBackgroundJob, et as getEvalCaseInput, gt as extractApiCalls, ht as extractCacheHits, it as mergeEvalOutput, lt as setEvalOutput, mt as extractCacheEntries, nt as isInEvalScope, ot as runInEvalRuntimeScope, q as EvalAssertionError, st as runInEvalScope, tt as incrementEvalOutput, ut as setScopeCacheContext, vt as simulateLlmCallCost, xt as getNestedAttribute, yt as simulateTokenAllocation, z as deserializeCacheRecording } from "./runOrchestration-
|
|
2
|
-
import { a as materializeManualInputFiles, i as isManualInputFileValue, n as createRunner, o as stageManualInputFile, r as cleanupStagedManualInputFiles, s as stageManualInputFileFromPath, t as runCli } from "./cli-
|
|
3
|
-
import { n as matchesEvalTags, t as defineEval } from "./src-
|
|
1
|
+
import { $ as getCurrentScope, B as deserializeCacheValue, F as evalSpan, G as readManualInputFile, H as serializeCacheValue, I as evalTracer, J as appendToEvalOutput, K as evalExpect, L as hashCacheKey, Lt as getEvalRegistry, M as z, N as buildTraceTree, P as captureEvalSpanError, Q as evalTime, R as hashCacheKeySync, U as repoFile, V as serializeCacheRecording, W as manualInputFileValueSchema, X as evalAssert, Z as evalLog, _t as extractLlmCalls, at as nextEvalId, ct as runInExistingEvalScope, dt as startEvalBackgroundJob, et as getEvalCaseInput, gt as extractApiCalls, ht as extractCacheHits, it as mergeEvalOutput, lt as setEvalOutput, mt as extractCacheEntries, nt as isInEvalScope, ot as runInEvalRuntimeScope, q as EvalAssertionError, st as runInEvalScope, tt as incrementEvalOutput, ut as setScopeCacheContext, vt as simulateLlmCallCost, xt as getNestedAttribute, yt as simulateTokenAllocation, z as deserializeCacheRecording } from "./runOrchestration-BFdxG9ws.mjs";
|
|
2
|
+
import { a as materializeManualInputFiles, i as isManualInputFileValue, n as createRunner, o as stageManualInputFile, r as cleanupStagedManualInputFiles, s as stageManualInputFileFromPath, t as runCli } from "./cli-vdJYkEVk.mjs";
|
|
3
|
+
import { n as matchesEvalTags, t as defineEval } from "./src-BRqs3kSA.mjs";
|
|
4
4
|
export { EvalAssertionError, appendToEvalOutput, buildTraceTree, captureEvalSpanError, cleanupStagedManualInputFiles, createRunner, defineEval, deserializeCacheRecording, deserializeCacheValue, evalAssert, evalExpect, evalLog, evalSpan, evalTime, evalTracer, extractApiCalls, extractCacheEntries, extractCacheHits, extractLlmCalls, getCurrentScope, getEvalCaseInput, getEvalRegistry, getNestedAttribute, hashCacheKey, hashCacheKeySync, incrementEvalOutput, isInEvalScope, isManualInputFileValue, manualInputFileValueSchema, matchesEvalTags, materializeManualInputFiles, mergeEvalOutput, nextEvalId, readManualInputFile, repoFile, runCli, runInEvalRuntimeScope, runInEvalScope, runInExistingEvalScope, serializeCacheRecording, serializeCacheValue, setEvalOutput, setScopeCacheContext, simulateLlmCallCost, simulateTokenAllocation, stageManualInputFile, stageManualInputFileFromPath, startEvalBackgroundJob, z };
|
package/dist/runChild.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as buildEvalKey, D as loadConfig, Dt as runSummarySchema, Et as runManifestSchema, Ft as columnDefSchema, Mt as evalStatsConfigSchema, Nt as manualInputDescriptorSchema, Pt as evalChartsConfigSchema, T as parseEvalDiscovery, Y as configureEvalRunLogs, ft as createRunRequestSchema, h as persistRunState, j as createFsCacheStore, r as getTargetEvals$1, t as executeRun } from "./runOrchestration-
|
|
1
|
+
import { At as buildEvalKey, D as loadConfig, Dt as runSummarySchema, Et as runManifestSchema, Ft as columnDefSchema, Mt as evalStatsConfigSchema, Nt as manualInputDescriptorSchema, Pt as evalChartsConfigSchema, T as parseEvalDiscovery, Y as configureEvalRunLogs, ft as createRunRequestSchema, h as persistRunState, j as createFsCacheStore, r as getTargetEvals$1, t as executeRun } from "./runOrchestration-BFdxG9ws.mjs";
|
|
2
2
|
import { z } from "zod/v4";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { relative } from "node:path";
|
|
@@ -4,8 +4,8 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
4
4
|
import { z, z as z$1 } from "zod/v4";
|
|
5
5
|
import dayjs from "dayjs";
|
|
6
6
|
import { Blob as Blob$1, Buffer as Buffer$1, File as File$1 } from "node:buffer";
|
|
7
|
-
import { mkdir, readFile, readdir, rename, rm,
|
|
8
|
-
import { dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
7
|
+
import { mkdir, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
|
|
8
|
+
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
9
9
|
import { createHash, randomUUID } from "node:crypto";
|
|
10
10
|
import { getCompositeKey } from "@ls-stack/utils/getCompositeKey";
|
|
11
11
|
import { existsSync } from "node:fs";
|
|
@@ -344,7 +344,12 @@ const cacheEntrySchema = z.object({
|
|
|
344
344
|
storedAt: z.string(),
|
|
345
345
|
recording: cacheRecordingSchema
|
|
346
346
|
});
|
|
347
|
-
/**
|
|
347
|
+
/**
|
|
348
|
+
* Debug-only raw key metadata stored outside the reusable cache entry.
|
|
349
|
+
*
|
|
350
|
+
* Debug entries mirror the serialized cache entry so inspecting one debug file
|
|
351
|
+
* shows both the authored raw key and the persisted payload for that key.
|
|
352
|
+
*/
|
|
348
353
|
const cacheDebugKeyEntrySchema = z.object({
|
|
349
354
|
version: z.literal(1),
|
|
350
355
|
key: z.string(),
|
|
@@ -352,17 +357,16 @@ const cacheDebugKeyEntrySchema = z.object({
|
|
|
352
357
|
operationType: cacheOperationTypeSchema,
|
|
353
358
|
operationName: z.string(),
|
|
354
359
|
storedAt: z.string(),
|
|
355
|
-
rawKey: z.unknown()
|
|
360
|
+
rawKey: z.unknown(),
|
|
361
|
+
entry: cacheEntrySchema
|
|
356
362
|
});
|
|
357
363
|
cacheEntrySchema.extend({ debugKey: cacheDebugKeyEntrySchema.optional() });
|
|
358
|
-
|
|
359
|
-
const cacheFileSchema = z.object({
|
|
364
|
+
z.object({
|
|
360
365
|
version: z.literal(1),
|
|
361
366
|
owner: z.string(),
|
|
362
367
|
entries: z.record(z.string(), cacheEntrySchema)
|
|
363
368
|
});
|
|
364
|
-
|
|
365
|
-
const cacheDebugKeyFileSchema = z.object({
|
|
369
|
+
z.object({
|
|
366
370
|
version: z.literal(1),
|
|
367
371
|
owner: z.string(),
|
|
368
372
|
entries: z.record(z.string(), cacheDebugKeyEntrySchema)
|
|
@@ -4176,7 +4180,7 @@ function createTraceCache(generateSpanId) {
|
|
|
4176
4180
|
if (!scope) return await fn();
|
|
4177
4181
|
const cacheCtx = scope.cacheContext;
|
|
4178
4182
|
if (cacheCtx === void 0 || scope.replayingDepth > 0) return await fn();
|
|
4179
|
-
const namespace = info.namespace ?? `${cacheCtx.evalId}
|
|
4183
|
+
const namespace = info.namespace ?? `${cacheCtx.evalId}.${info.name}`;
|
|
4180
4184
|
const keyHash = await hashCacheKey({
|
|
4181
4185
|
namespace,
|
|
4182
4186
|
key: info.key
|
|
@@ -4835,12 +4839,14 @@ const cacheSerializationMarker = "__aecs";
|
|
|
4835
4839
|
const supportedCacheSerializationPrefix = "v1:";
|
|
4836
4840
|
const externalJsonCacheSerializationMarker = "v1:ExternalJson";
|
|
4837
4841
|
const externalJsonBlobExtension = ".json.br";
|
|
4842
|
+
const cacheEntryExtension = ".json.br";
|
|
4843
|
+
const debugEntryExtension = ".json";
|
|
4838
4844
|
/**
|
|
4839
4845
|
* Create a filesystem-backed cache adapter rooted at `<workspaceRoot>/<dir>`.
|
|
4840
4846
|
*
|
|
4841
|
-
* Cache entries are
|
|
4842
|
-
*
|
|
4843
|
-
*
|
|
4847
|
+
* Cache entries are stored as one Brotli-compressed JSON file per entry, nested
|
|
4848
|
+
* under a sanitized namespace directory. Debug sidecars mirror one key per file
|
|
4849
|
+
* and include the authored raw key plus the serialized cache entry.
|
|
4844
4850
|
*/
|
|
4845
4851
|
function createFsCacheStore(options) {
|
|
4846
4852
|
const cacheDir = resolve(options.workspaceRoot, options.dir ?? ".agent-evals/cache");
|
|
@@ -4860,76 +4866,64 @@ function createFsCacheStore(options) {
|
|
|
4860
4866
|
return blobDir;
|
|
4861
4867
|
},
|
|
4862
4868
|
async lookup(namespace, keyHash) {
|
|
4863
|
-
const entry =
|
|
4869
|
+
const entry = await readCacheEntry(cacheDir, namespace, keyHash);
|
|
4864
4870
|
return entry === null ? null : await materializeExternalJsonCacheEntry(entry, externalJsonStore);
|
|
4865
4871
|
},
|
|
4866
4872
|
async lookupWithDebug(namespace, keyHash) {
|
|
4867
|
-
const
|
|
4868
|
-
|
|
4869
|
-
const entry =
|
|
4870
|
-
|
|
4871
|
-
const debugKey = (await readDebugKeyFile(debugDir, owner))?.entries[keyHash];
|
|
4873
|
+
const rawEntry = await readCacheEntry(cacheDir, namespace, keyHash);
|
|
4874
|
+
if (rawEntry === null) return null;
|
|
4875
|
+
const entry = await materializeExternalJsonCacheEntry(rawEntry, externalJsonStore);
|
|
4876
|
+
const debugKey = await readDebugEntry(debugDir, namespace, keyHash);
|
|
4872
4877
|
const deserializedEntry = {
|
|
4873
4878
|
...entry,
|
|
4874
4879
|
recording: deserializeCacheRecording(entry.recording)
|
|
4875
4880
|
};
|
|
4876
|
-
return debugKey ===
|
|
4881
|
+
return debugKey === null ? deserializedEntry : {
|
|
4877
4882
|
...deserializedEntry,
|
|
4878
4883
|
debugKey
|
|
4879
4884
|
};
|
|
4880
4885
|
},
|
|
4881
4886
|
async write(entry, debugKey) {
|
|
4882
|
-
const
|
|
4883
|
-
|
|
4884
|
-
await mkdir(cacheDir, { recursive: true });
|
|
4885
|
-
await withCacheFileLock(filePath, async () => {
|
|
4886
|
-
await writeCacheFile(cacheDir, {
|
|
4887
|
-
version: 1,
|
|
4888
|
-
owner,
|
|
4889
|
-
entries: pruneEntries({
|
|
4890
|
-
...(await readCacheFile(cacheDir, owner))?.entries ?? {},
|
|
4891
|
-
[entry.key]: entry
|
|
4892
|
-
}, entry.namespace, maxEntriesForNamespace(entry.namespace, defaultMaxEntries, options.maxEntriesByNamespace), entry.key)
|
|
4893
|
-
});
|
|
4894
|
-
});
|
|
4895
|
-
await pruneExternalJsonBlobs(cacheDir, blobDir);
|
|
4887
|
+
const maxEntries = maxEntriesForNamespace(entry.namespace, defaultMaxEntries, options.maxEntriesByNamespace);
|
|
4888
|
+
await withCacheFileLock(namespaceLockPath(cacheDir, entry.namespace), () => writeCompressedCacheEntry(cacheDir, entry));
|
|
4896
4889
|
if (debugKey !== void 0) {
|
|
4897
4890
|
if ((await resultify(() => writeDebugKeyEntry({
|
|
4898
4891
|
debugDir,
|
|
4899
4892
|
entry,
|
|
4900
|
-
debugKey
|
|
4901
|
-
maxEntries: maxEntriesForNamespace(entry.namespace, defaultMaxEntries, options.maxEntriesByNamespace)
|
|
4893
|
+
debugKey
|
|
4902
4894
|
}))).error) await resultify(() => clearDebugEntries(debugDir, {
|
|
4903
4895
|
namespace: entry.namespace,
|
|
4904
4896
|
key: entry.key
|
|
4905
4897
|
}));
|
|
4906
4898
|
}
|
|
4899
|
+
await pruneEntriesForNamespace({
|
|
4900
|
+
cacheDir,
|
|
4901
|
+
debugDir,
|
|
4902
|
+
namespace: entry.namespace,
|
|
4903
|
+
maxEntries,
|
|
4904
|
+
protectedKey: entry.key
|
|
4905
|
+
});
|
|
4906
|
+
await pruneExternalJsonBlobs(cacheDir, blobDir);
|
|
4907
4907
|
},
|
|
4908
4908
|
async list() {
|
|
4909
|
-
|
|
4910
|
-
const files = await readdir(cacheDir);
|
|
4909
|
+
const files = await listCacheEntryFiles(cacheDir);
|
|
4911
4910
|
const items = [];
|
|
4912
|
-
for (const
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
const
|
|
4916
|
-
|
|
4917
|
-
const
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
spanKind: entry.spanKind,
|
|
4929
|
-
storedAt: entry.storedAt,
|
|
4930
|
-
sizeBytes: Buffer.byteLength(JSON.stringify(entry), "utf8")
|
|
4931
|
-
});
|
|
4932
|
-
}
|
|
4911
|
+
for (const filePath of files) {
|
|
4912
|
+
const fileEntry = await readCacheEntryFilePath(filePath);
|
|
4913
|
+
if (fileEntry === null || !entryMatchesPath(filePath, fileEntry.entry)) continue;
|
|
4914
|
+
const entry = fileEntry.entry;
|
|
4915
|
+
const operationType = entry.operationType ?? "span";
|
|
4916
|
+
const operationName = entry.operationName ?? entry.spanName ?? entry.namespace;
|
|
4917
|
+
items.push({
|
|
4918
|
+
key: entry.key,
|
|
4919
|
+
namespace: entry.namespace,
|
|
4920
|
+
operationType,
|
|
4921
|
+
operationName,
|
|
4922
|
+
spanName: entry.spanName,
|
|
4923
|
+
spanKind: entry.spanKind,
|
|
4924
|
+
storedAt: entry.storedAt,
|
|
4925
|
+
sizeBytes: fileEntry.sizeBytes
|
|
4926
|
+
});
|
|
4933
4927
|
}
|
|
4934
4928
|
items.sort((a, b) => a.storedAt < b.storedAt ? 1 : -1);
|
|
4935
4929
|
return items;
|
|
@@ -4951,41 +4945,12 @@ function createFsCacheStore(options) {
|
|
|
4951
4945
|
return;
|
|
4952
4946
|
}
|
|
4953
4947
|
if (filter.namespace !== void 0) {
|
|
4954
|
-
|
|
4955
|
-
const filePath = ownerPath(cacheDir, owner);
|
|
4956
|
-
if (existsSync(cacheDir)) await withCacheFileLock(filePath, async () => {
|
|
4957
|
-
const cacheFile = await readCacheFile(cacheDir, owner);
|
|
4958
|
-
if (cacheFile === null) return;
|
|
4959
|
-
await writeOrRemoveCacheFile(cacheDir, {
|
|
4960
|
-
version: 1,
|
|
4961
|
-
owner,
|
|
4962
|
-
entries: Object.fromEntries(Object.entries(cacheFile.entries).filter(([key, entry]) => {
|
|
4963
|
-
if (filter.key !== void 0) return key !== filter.key;
|
|
4964
|
-
return entry.namespace !== filter.namespace;
|
|
4965
|
-
}))
|
|
4966
|
-
});
|
|
4967
|
-
});
|
|
4948
|
+
await clearCacheEntries(cacheDir, filter);
|
|
4968
4949
|
await clearDebugEntries(debugDir, filter);
|
|
4969
4950
|
await pruneExternalJsonBlobs(cacheDir, blobDir);
|
|
4970
4951
|
return;
|
|
4971
4952
|
}
|
|
4972
|
-
|
|
4973
|
-
const files = await readdir(cacheDir);
|
|
4974
|
-
for (const fileName of files) {
|
|
4975
|
-
if (!fileName.endsWith(".json")) continue;
|
|
4976
|
-
const filePath = join(cacheDir, fileName);
|
|
4977
|
-
await withCacheFileLock(filePath, async () => {
|
|
4978
|
-
const cacheFile = await readCacheFilePath(filePath);
|
|
4979
|
-
if (cacheFile === null) return;
|
|
4980
|
-
const entries = Object.fromEntries(Object.entries(cacheFile.entries).filter(([key]) => key !== filter.key));
|
|
4981
|
-
await writeOrRemoveCacheFile(cacheDir, {
|
|
4982
|
-
version: 1,
|
|
4983
|
-
owner: cacheFile.owner,
|
|
4984
|
-
entries
|
|
4985
|
-
});
|
|
4986
|
-
});
|
|
4987
|
-
}
|
|
4988
|
-
}
|
|
4953
|
+
await clearCacheEntries(cacheDir, filter);
|
|
4989
4954
|
await clearDebugEntries(debugDir, filter);
|
|
4990
4955
|
await pruneExternalJsonBlobs(cacheDir, blobDir);
|
|
4991
4956
|
}
|
|
@@ -5030,19 +4995,185 @@ function maxEntriesForNamespace(namespace, defaultMaxEntries, maxEntriesByNamesp
|
|
|
5030
4995
|
const namespaceMaxEntries = maxEntriesByNamespace?.[namespace];
|
|
5031
4996
|
return namespaceMaxEntries === void 0 ? defaultMaxEntries : normalizeMaxEntries(namespaceMaxEntries, defaultMaxEntries);
|
|
5032
4997
|
}
|
|
5033
|
-
function ownerFromNamespace(namespace) {
|
|
5034
|
-
const [owner] = namespace.split("__");
|
|
5035
|
-
return owner === void 0 || owner.length === 0 ? namespace : owner;
|
|
5036
|
-
}
|
|
5037
|
-
function ownerPath(cacheDir, owner) {
|
|
5038
|
-
return join(cacheDir, `${sanitizeSegment$1(owner)}.json`);
|
|
5039
|
-
}
|
|
5040
4998
|
function toPendingKey(namespace, keyHash) {
|
|
5041
4999
|
return `${namespace}::${keyHash}`;
|
|
5042
5000
|
}
|
|
5043
5001
|
function sanitizeSegment$1(segment) {
|
|
5044
5002
|
return segment.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
5045
5003
|
}
|
|
5004
|
+
function namespaceDirPath(rootDir, namespace) {
|
|
5005
|
+
return join(rootDir, sanitizeSegment$1(namespace));
|
|
5006
|
+
}
|
|
5007
|
+
function namespaceLockPath(rootDir, namespace) {
|
|
5008
|
+
return join(rootDir, `${sanitizeSegment$1(namespace)}.namespace`);
|
|
5009
|
+
}
|
|
5010
|
+
function cacheEntryPath(cacheDir, namespace, key) {
|
|
5011
|
+
return entryPath({
|
|
5012
|
+
rootDir: cacheDir,
|
|
5013
|
+
namespace,
|
|
5014
|
+
key,
|
|
5015
|
+
extension: cacheEntryExtension
|
|
5016
|
+
});
|
|
5017
|
+
}
|
|
5018
|
+
function debugEntryPath(debugDir, namespace, key) {
|
|
5019
|
+
return entryPath({
|
|
5020
|
+
rootDir: debugDir,
|
|
5021
|
+
namespace,
|
|
5022
|
+
key,
|
|
5023
|
+
extension: debugEntryExtension
|
|
5024
|
+
});
|
|
5025
|
+
}
|
|
5026
|
+
function entryPath(params) {
|
|
5027
|
+
const namespaceDir = resolve(namespaceDirPath(params.rootDir, params.namespace));
|
|
5028
|
+
const filePath = resolve(namespaceDir, `${params.key}${params.extension}`);
|
|
5029
|
+
if (filePath !== namespaceDir && !filePath.startsWith(`${namespaceDir}${sep}`)) throw new Error(`Cache entry key escapes namespace directory: ${params.key}`);
|
|
5030
|
+
return filePath;
|
|
5031
|
+
}
|
|
5032
|
+
async function readCacheEntry(cacheDir, namespace, key) {
|
|
5033
|
+
return (await readCacheEntryFilePath(cacheEntryPath(cacheDir, namespace, key), {
|
|
5034
|
+
namespace,
|
|
5035
|
+
key
|
|
5036
|
+
}))?.entry ?? null;
|
|
5037
|
+
}
|
|
5038
|
+
async function readCacheEntryFilePath(filePath, expected) {
|
|
5039
|
+
if (!existsSync(filePath)) return null;
|
|
5040
|
+
const compressedResult = await resultify(() => readFile(filePath));
|
|
5041
|
+
if (compressedResult.error) return null;
|
|
5042
|
+
const rawResult = resultify(() => brotliDecompressSync(compressedResult.value).toString("utf8"));
|
|
5043
|
+
if (rawResult.error) return null;
|
|
5044
|
+
const json = safeJsonParse(rawResult.value);
|
|
5045
|
+
if (json === null) return null;
|
|
5046
|
+
const parsed = cacheEntrySchema.safeParse(json);
|
|
5047
|
+
if (!parsed.success) return null;
|
|
5048
|
+
const entry = parsed.data;
|
|
5049
|
+
if (!usesSupportedCacheSerialization(entry.recording)) return null;
|
|
5050
|
+
if (expected !== void 0 && (entry.namespace !== expected.namespace || entry.key !== expected.key)) return null;
|
|
5051
|
+
return {
|
|
5052
|
+
entry,
|
|
5053
|
+
sizeBytes: compressedResult.value.byteLength
|
|
5054
|
+
};
|
|
5055
|
+
}
|
|
5056
|
+
async function writeCompressedCacheEntry(cacheDir, entry) {
|
|
5057
|
+
const filePath = cacheEntryPath(cacheDir, entry.namespace, entry.key);
|
|
5058
|
+
const rawJson = JSON.stringify(entry);
|
|
5059
|
+
await writeAtomicFile(filePath, brotliCompressSync(Buffer.from(rawJson, "utf8")));
|
|
5060
|
+
}
|
|
5061
|
+
async function readDebugEntry(debugDir, namespace, key) {
|
|
5062
|
+
return readDebugEntryFilePath(debugEntryPath(debugDir, namespace, key), {
|
|
5063
|
+
namespace,
|
|
5064
|
+
key
|
|
5065
|
+
});
|
|
5066
|
+
}
|
|
5067
|
+
async function readDebugEntryFilePath(filePath, expected) {
|
|
5068
|
+
if (!existsSync(filePath)) return null;
|
|
5069
|
+
const rawResult = await resultify(() => readFile(filePath, "utf8"));
|
|
5070
|
+
if (rawResult.error) return null;
|
|
5071
|
+
const json = safeJsonParse(rawResult.value);
|
|
5072
|
+
if (json === null) return null;
|
|
5073
|
+
const parsed = cacheDebugKeyEntrySchema.safeParse(json);
|
|
5074
|
+
if (!parsed.success) return null;
|
|
5075
|
+
const entry = parsed.data;
|
|
5076
|
+
if (entry.entry.namespace !== entry.namespace || entry.entry.key !== entry.key || !usesSupportedCacheSerialization(entry.entry.recording)) return null;
|
|
5077
|
+
if (expected !== void 0 && (entry.namespace !== expected.namespace || entry.key !== expected.key)) return null;
|
|
5078
|
+
return entry;
|
|
5079
|
+
}
|
|
5080
|
+
async function writeDebugKeyEntry(params) {
|
|
5081
|
+
const { debugDir, entry, debugKey } = params;
|
|
5082
|
+
const debugEntry = {
|
|
5083
|
+
version: 1,
|
|
5084
|
+
key: entry.key,
|
|
5085
|
+
namespace: entry.namespace,
|
|
5086
|
+
operationType: debugKey.operationType,
|
|
5087
|
+
operationName: debugKey.operationName,
|
|
5088
|
+
storedAt: entry.storedAt,
|
|
5089
|
+
rawKey: debugKey.rawKey,
|
|
5090
|
+
entry
|
|
5091
|
+
};
|
|
5092
|
+
await withCacheFileLock(namespaceLockPath(debugDir, entry.namespace), () => writePrettyDebugEntry(debugDir, debugEntry));
|
|
5093
|
+
}
|
|
5094
|
+
async function writePrettyDebugEntry(debugDir, entry) {
|
|
5095
|
+
await writeAtomicFile(debugEntryPath(debugDir, entry.namespace, entry.key), JSON.stringify(entry, null, 2));
|
|
5096
|
+
}
|
|
5097
|
+
async function writeAtomicFile(filePath, contents) {
|
|
5098
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
5099
|
+
const tmpPath = `${filePath}.${process.pid.toString()}.${randomUUID()}.tmp`;
|
|
5100
|
+
await writeFile(tmpPath, contents);
|
|
5101
|
+
await rename(tmpPath, filePath);
|
|
5102
|
+
}
|
|
5103
|
+
async function clearCacheEntries(cacheDir, filter) {
|
|
5104
|
+
const files = filter.namespace === void 0 ? await listCacheEntryFiles(cacheDir) : await listCacheEntryFiles(namespaceDirPath(cacheDir, filter.namespace));
|
|
5105
|
+
for (const filePath of files) {
|
|
5106
|
+
const fileEntry = await readCacheEntryFilePath(filePath);
|
|
5107
|
+
if (fileEntry === null) continue;
|
|
5108
|
+
const entry = fileEntry.entry;
|
|
5109
|
+
if (!entryMatchesFilter(entry, filter)) continue;
|
|
5110
|
+
await withCacheFileLock(namespaceLockPath(cacheDir, entry.namespace), () => rm(filePath, { force: true }));
|
|
5111
|
+
}
|
|
5112
|
+
if (filter.namespace !== void 0) await removeDirIfEmpty(namespaceDirPath(cacheDir, filter.namespace));
|
|
5113
|
+
}
|
|
5114
|
+
async function clearDebugEntries(debugDir, filter) {
|
|
5115
|
+
const files = filter.namespace === void 0 ? await listDebugEntryFiles(debugDir) : await listDebugEntryFiles(namespaceDirPath(debugDir, filter.namespace));
|
|
5116
|
+
for (const filePath of files) {
|
|
5117
|
+
const entry = await readDebugEntryFilePath(filePath);
|
|
5118
|
+
if (entry === null || !entryMatchesFilter(entry, filter)) continue;
|
|
5119
|
+
await withCacheFileLock(namespaceLockPath(debugDir, entry.namespace), () => rm(filePath, { force: true }));
|
|
5120
|
+
}
|
|
5121
|
+
if (filter.namespace !== void 0) await removeDirIfEmpty(namespaceDirPath(debugDir, filter.namespace));
|
|
5122
|
+
}
|
|
5123
|
+
function entryMatchesFilter(entry, filter) {
|
|
5124
|
+
if (filter.namespace !== void 0 && entry.namespace !== filter.namespace) return false;
|
|
5125
|
+
return filter.key === void 0 || entry.key === filter.key;
|
|
5126
|
+
}
|
|
5127
|
+
async function pruneEntriesForNamespace(params) {
|
|
5128
|
+
const { cacheDir, debugDir, namespace, maxEntries, protectedKey } = params;
|
|
5129
|
+
await withCacheFileLock(namespaceLockPath(cacheDir, namespace), async () => {
|
|
5130
|
+
const keptKeys = await pruneCacheEntriesForNamespace(cacheDir, namespace, maxEntries, protectedKey);
|
|
5131
|
+
await withCacheFileLock(namespaceLockPath(debugDir, namespace), () => pruneDebugEntriesForNamespace(debugDir, namespace, keptKeys));
|
|
5132
|
+
});
|
|
5133
|
+
}
|
|
5134
|
+
async function pruneCacheEntriesForNamespace(cacheDir, namespace, maxEntries, protectedKey) {
|
|
5135
|
+
const entries = await listCacheEntriesForNamespace(cacheDir, namespace);
|
|
5136
|
+
const sorted = entries.toSorted((a, b) => a.entry.storedAt < b.entry.storedAt ? 1 : -1);
|
|
5137
|
+
const keptKeys = /* @__PURE__ */ new Set();
|
|
5138
|
+
const protectedEntry = entries.find((item) => item.entry.key === protectedKey);
|
|
5139
|
+
if (protectedEntry !== void 0) keptKeys.add(protectedEntry.entry.key);
|
|
5140
|
+
for (const item of sorted) {
|
|
5141
|
+
if (keptKeys.size >= maxEntries) break;
|
|
5142
|
+
keptKeys.add(item.entry.key);
|
|
5143
|
+
}
|
|
5144
|
+
for (const item of entries) if (!keptKeys.has(item.entry.key)) await rm(item.filePath, { force: true });
|
|
5145
|
+
await removeDirIfEmpty(namespaceDirPath(cacheDir, namespace));
|
|
5146
|
+
return keptKeys;
|
|
5147
|
+
}
|
|
5148
|
+
async function pruneDebugEntriesForNamespace(debugDir, namespace, keptKeys) {
|
|
5149
|
+
const files = await listDebugEntryFiles(namespaceDirPath(debugDir, namespace));
|
|
5150
|
+
for (const filePath of files) {
|
|
5151
|
+
const entry = await readDebugEntryFilePath(filePath);
|
|
5152
|
+
if (entry !== null && entry.namespace === namespace && !keptKeys.has(entry.key)) await rm(filePath, { force: true });
|
|
5153
|
+
}
|
|
5154
|
+
await removeDirIfEmpty(namespaceDirPath(debugDir, namespace));
|
|
5155
|
+
}
|
|
5156
|
+
async function listCacheEntriesForNamespace(cacheDir, namespace) {
|
|
5157
|
+
const files = await listCacheEntryFiles(namespaceDirPath(cacheDir, namespace));
|
|
5158
|
+
const entries = [];
|
|
5159
|
+
for (const filePath of files) {
|
|
5160
|
+
const fileEntry = await readCacheEntryFilePath(filePath);
|
|
5161
|
+
if (fileEntry !== null && fileEntry.entry.namespace === namespace && entryMatchesPath(filePath, fileEntry.entry)) entries.push({
|
|
5162
|
+
filePath,
|
|
5163
|
+
entry: fileEntry.entry
|
|
5164
|
+
});
|
|
5165
|
+
}
|
|
5166
|
+
return entries;
|
|
5167
|
+
}
|
|
5168
|
+
function entryMatchesPath(filePath, entry) {
|
|
5169
|
+
return basename(filePath) === `${entry.key}${cacheEntryExtension}` && basename(dirname(filePath)) === sanitizeSegment$1(entry.namespace);
|
|
5170
|
+
}
|
|
5171
|
+
function usesSupportedCacheSerialization(value) {
|
|
5172
|
+
if (Array.isArray(value)) return value.every(usesSupportedCacheSerialization);
|
|
5173
|
+
if (!isRecordLike(value)) return true;
|
|
5174
|
+
if (Object.hasOwn(value, cacheSerializationMarker) && (typeof value[cacheSerializationMarker] !== "string" || !value[cacheSerializationMarker].startsWith(supportedCacheSerializationPrefix))) return false;
|
|
5175
|
+
return Object.values(value).every(usesSupportedCacheSerialization);
|
|
5176
|
+
}
|
|
5046
5177
|
function createExternalJsonBlobStore(blobDir) {
|
|
5047
5178
|
return {
|
|
5048
5179
|
async write(rawJson) {
|
|
@@ -5051,12 +5182,7 @@ function createExternalJsonBlobStore(blobDir) {
|
|
|
5051
5182
|
const path = externalJsonBlobPath(hash);
|
|
5052
5183
|
const compressed = brotliCompressSync(rawBytes);
|
|
5053
5184
|
const filePath = resolveStorePath(blobDir, path);
|
|
5054
|
-
if (!existsSync(filePath))
|
|
5055
|
-
await mkdir(dirname(filePath), { recursive: true });
|
|
5056
|
-
const tmpPath = `${filePath}.${process.pid.toString()}.tmp`;
|
|
5057
|
-
await writeFile(tmpPath, compressed);
|
|
5058
|
-
await rename(tmpPath, filePath);
|
|
5059
|
-
}
|
|
5185
|
+
if (!existsSync(filePath)) await writeAtomicFile(filePath, compressed);
|
|
5060
5186
|
return {
|
|
5061
5187
|
compressedLength: compressed.byteLength,
|
|
5062
5188
|
hash,
|
|
@@ -5097,13 +5223,10 @@ async function pruneExternalJsonBlobs(cacheDir, blobDir) {
|
|
|
5097
5223
|
}
|
|
5098
5224
|
async function collectReferencedExternalJsonBlobPaths(cacheDir) {
|
|
5099
5225
|
const paths = /* @__PURE__ */ new Set();
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
const cacheFile = await readCacheFilePath(join(cacheDir, fileName));
|
|
5105
|
-
if (cacheFile === null) continue;
|
|
5106
|
-
collectExternalJsonBlobPaths(cacheFile, paths);
|
|
5226
|
+
for (const filePath of await listCacheEntryFiles(cacheDir)) {
|
|
5227
|
+
const fileEntry = await readCacheEntryFilePath(filePath);
|
|
5228
|
+
if (fileEntry === null || !entryMatchesPath(filePath, fileEntry.entry)) continue;
|
|
5229
|
+
collectExternalJsonBlobPaths(fileEntry.entry, paths);
|
|
5107
5230
|
}
|
|
5108
5231
|
return paths;
|
|
5109
5232
|
}
|
|
@@ -5122,8 +5245,9 @@ async function listExternalJsonBlobPaths(blobDir) {
|
|
|
5122
5245
|
return paths;
|
|
5123
5246
|
}
|
|
5124
5247
|
async function collectExternalJsonBlobFilePaths(root, dir, paths) {
|
|
5125
|
-
const
|
|
5126
|
-
|
|
5248
|
+
const entriesResult = await resultify(() => readdir(dir, { withFileTypes: true }));
|
|
5249
|
+
if (entriesResult.error) return;
|
|
5250
|
+
for (const entry of entriesResult.value) {
|
|
5127
5251
|
const path = join(dir, entry.name);
|
|
5128
5252
|
if (entry.isDirectory()) {
|
|
5129
5253
|
await collectExternalJsonBlobFilePaths(root, path, paths);
|
|
@@ -5132,153 +5256,38 @@ async function collectExternalJsonBlobFilePaths(root, dir, paths) {
|
|
|
5132
5256
|
if (entry.isFile() && entry.name.endsWith(externalJsonBlobExtension)) paths.push(relative(root, path));
|
|
5133
5257
|
}
|
|
5134
5258
|
}
|
|
5135
|
-
async function
|
|
5136
|
-
return
|
|
5259
|
+
async function listCacheEntryFiles(rootDir) {
|
|
5260
|
+
return listFilesWithExtension(rootDir, cacheEntryExtension);
|
|
5137
5261
|
}
|
|
5138
|
-
async function
|
|
5139
|
-
|
|
5140
|
-
const rawResult = await resultify(() => readFile(filePath, "utf-8"));
|
|
5141
|
-
if (rawResult.error) return null;
|
|
5142
|
-
const json = safeJsonParse(rawResult.value);
|
|
5143
|
-
if (json === null) return null;
|
|
5144
|
-
const parsed = cacheFileSchema.safeParse(json);
|
|
5145
|
-
if (!parsed.success) return null;
|
|
5146
|
-
return {
|
|
5147
|
-
...parsed.data,
|
|
5148
|
-
entries: Object.fromEntries(Object.entries(parsed.data.entries).filter(([, entry]) => usesSupportedCacheSerialization(entry.recording)))
|
|
5149
|
-
};
|
|
5150
|
-
}
|
|
5151
|
-
function usesSupportedCacheSerialization(value) {
|
|
5152
|
-
if (Array.isArray(value)) return value.every(usesSupportedCacheSerialization);
|
|
5153
|
-
if (!isRecordLike(value)) return true;
|
|
5154
|
-
if (Object.hasOwn(value, cacheSerializationMarker) && (typeof value[cacheSerializationMarker] !== "string" || !value[cacheSerializationMarker].startsWith(supportedCacheSerializationPrefix))) return false;
|
|
5155
|
-
return Object.values(value).every(usesSupportedCacheSerialization);
|
|
5262
|
+
async function listDebugEntryFiles(rootDir) {
|
|
5263
|
+
return listFilesWithExtension(rootDir, debugEntryExtension);
|
|
5156
5264
|
}
|
|
5157
|
-
async function
|
|
5158
|
-
if (
|
|
5159
|
-
|
|
5160
|
-
|
|
5265
|
+
async function listFilesWithExtension(rootDir, extension) {
|
|
5266
|
+
if (!existsSync(rootDir)) return [];
|
|
5267
|
+
const entriesResult = await resultify(() => readdir(rootDir, { withFileTypes: true }));
|
|
5268
|
+
if (entriesResult.error) return [];
|
|
5269
|
+
const files = [];
|
|
5270
|
+
for (const entry of entriesResult.value) {
|
|
5271
|
+
const filePath = join(rootDir, entry.name);
|
|
5272
|
+
if (entry.isDirectory()) {
|
|
5273
|
+
files.push(...await listFilesWithExtension(filePath, extension));
|
|
5274
|
+
continue;
|
|
5275
|
+
}
|
|
5276
|
+
if (entry.isFile() && entry.name.endsWith(extension)) files.push(filePath);
|
|
5161
5277
|
}
|
|
5162
|
-
|
|
5163
|
-
}
|
|
5164
|
-
async function writeCacheFile(cacheDir, cacheFile) {
|
|
5165
|
-
await mkdir(cacheDir, { recursive: true });
|
|
5166
|
-
const filePath = ownerPath(cacheDir, cacheFile.owner);
|
|
5167
|
-
const tmpPath = `${filePath}.${process.pid.toString()}.tmp`;
|
|
5168
|
-
await writeFile(tmpPath, JSON.stringify(cacheFile, null, 2));
|
|
5169
|
-
await rename(tmpPath, filePath);
|
|
5170
|
-
}
|
|
5171
|
-
async function readDebugKeyFile(debugDir, owner) {
|
|
5172
|
-
return readDebugKeyFilePath(ownerPath(debugDir, owner));
|
|
5278
|
+
return files;
|
|
5173
5279
|
}
|
|
5174
|
-
async function
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
const parsed = cacheDebugKeyFileSchema.safeParse(json);
|
|
5181
|
-
if (!parsed.success) return null;
|
|
5182
|
-
return parsed.data;
|
|
5183
|
-
}
|
|
5184
|
-
async function writeDebugKeyEntry(params) {
|
|
5185
|
-
const { debugDir, entry, debugKey, maxEntries } = params;
|
|
5186
|
-
const owner = ownerFromNamespace(entry.namespace);
|
|
5187
|
-
const filePath = ownerPath(debugDir, owner);
|
|
5188
|
-
await mkdir(debugDir, { recursive: true });
|
|
5189
|
-
await withCacheFileLock(filePath, async () => {
|
|
5190
|
-
const entries = (await readDebugKeyFile(debugDir, owner))?.entries ?? {};
|
|
5191
|
-
const debugEntry = {
|
|
5192
|
-
version: 1,
|
|
5193
|
-
key: entry.key,
|
|
5194
|
-
namespace: entry.namespace,
|
|
5195
|
-
operationType: debugKey.operationType,
|
|
5196
|
-
operationName: debugKey.operationName,
|
|
5197
|
-
storedAt: entry.storedAt,
|
|
5198
|
-
rawKey: debugKey.rawKey
|
|
5199
|
-
};
|
|
5200
|
-
await writeDebugKeyFile(debugDir, {
|
|
5201
|
-
version: 1,
|
|
5202
|
-
owner,
|
|
5203
|
-
entries: pruneDebugKeyEntries({
|
|
5204
|
-
...entries,
|
|
5205
|
-
[entry.key]: debugEntry
|
|
5206
|
-
}, entry.namespace, maxEntries, entry.key)
|
|
5207
|
-
});
|
|
5280
|
+
async function removeDirIfEmpty(dirPath) {
|
|
5281
|
+
const entriesResult = await resultify(() => readdir(dirPath));
|
|
5282
|
+
if (entriesResult.error || entriesResult.value.length > 0) return;
|
|
5283
|
+
await rm(dirPath, {
|
|
5284
|
+
recursive: true,
|
|
5285
|
+
force: true
|
|
5208
5286
|
});
|
|
5209
5287
|
}
|
|
5210
|
-
async function clearDebugEntries(debugDir, filter) {
|
|
5211
|
-
if (!existsSync(debugDir)) return;
|
|
5212
|
-
if (filter.namespace !== void 0) {
|
|
5213
|
-
const owner = ownerFromNamespace(filter.namespace);
|
|
5214
|
-
await withCacheFileLock(ownerPath(debugDir, owner), async () => {
|
|
5215
|
-
const debugFile = await readDebugKeyFile(debugDir, owner);
|
|
5216
|
-
if (debugFile === null) return;
|
|
5217
|
-
await writeOrRemoveDebugKeyFile(debugDir, {
|
|
5218
|
-
version: 1,
|
|
5219
|
-
owner,
|
|
5220
|
-
entries: Object.fromEntries(Object.entries(debugFile.entries).filter(([key, entry]) => {
|
|
5221
|
-
if (filter.key !== void 0) return key !== filter.key;
|
|
5222
|
-
return entry.namespace !== filter.namespace;
|
|
5223
|
-
}))
|
|
5224
|
-
});
|
|
5225
|
-
});
|
|
5226
|
-
return;
|
|
5227
|
-
}
|
|
5228
|
-
const files = await readdir(debugDir);
|
|
5229
|
-
for (const fileName of files) {
|
|
5230
|
-
if (!fileName.endsWith(".json")) continue;
|
|
5231
|
-
const filePath = join(debugDir, fileName);
|
|
5232
|
-
await withCacheFileLock(filePath, async () => {
|
|
5233
|
-
const debugFile = await readDebugKeyFilePath(filePath);
|
|
5234
|
-
if (debugFile === null) return;
|
|
5235
|
-
const entries = Object.fromEntries(Object.entries(debugFile.entries).filter(([key]) => key !== filter.key));
|
|
5236
|
-
await writeOrRemoveDebugKeyFile(debugDir, {
|
|
5237
|
-
version: 1,
|
|
5238
|
-
owner: debugFile.owner,
|
|
5239
|
-
entries
|
|
5240
|
-
});
|
|
5241
|
-
});
|
|
5242
|
-
}
|
|
5243
|
-
}
|
|
5244
|
-
async function writeOrRemoveDebugKeyFile(debugDir, debugFile) {
|
|
5245
|
-
if (Object.keys(debugFile.entries).length === 0) {
|
|
5246
|
-
await rm(ownerPath(debugDir, debugFile.owner), { force: true });
|
|
5247
|
-
return;
|
|
5248
|
-
}
|
|
5249
|
-
await writeDebugKeyFile(debugDir, debugFile);
|
|
5250
|
-
}
|
|
5251
|
-
async function writeDebugKeyFile(debugDir, debugFile) {
|
|
5252
|
-
await mkdir(debugDir, { recursive: true });
|
|
5253
|
-
const filePath = ownerPath(debugDir, debugFile.owner);
|
|
5254
|
-
const tmpPath = `${filePath}.${process.pid.toString()}.tmp`;
|
|
5255
|
-
await writeFile(tmpPath, JSON.stringify(debugFile, null, 2));
|
|
5256
|
-
await rename(tmpPath, filePath);
|
|
5257
|
-
}
|
|
5258
|
-
function pruneEntries(entries, namespace, maxEntries, protectedKey) {
|
|
5259
|
-
const sorted = Object.values(entries).filter((entry) => entry.namespace === namespace).toSorted((a, b) => a.storedAt < b.storedAt ? 1 : -1);
|
|
5260
|
-
const kept = /* @__PURE__ */ new Map();
|
|
5261
|
-
const protectedEntry = entries[protectedKey];
|
|
5262
|
-
if (protectedEntry?.namespace === namespace) kept.set(protectedEntry.key, protectedEntry);
|
|
5263
|
-
for (const entry of sorted) {
|
|
5264
|
-
if (kept.size >= maxEntries) break;
|
|
5265
|
-
kept.set(entry.key, entry);
|
|
5266
|
-
}
|
|
5267
|
-
return Object.fromEntries(Object.values(entries).filter((entry) => entry.namespace !== namespace || kept.has(entry.key)).toSorted((a, b) => a.key < b.key ? -1 : 1).map((entry) => [entry.key, entry]));
|
|
5268
|
-
}
|
|
5269
|
-
function pruneDebugKeyEntries(entries, namespace, maxEntries, protectedKey) {
|
|
5270
|
-
const sorted = Object.values(entries).filter((entry) => entry.namespace === namespace).toSorted((a, b) => a.storedAt < b.storedAt ? 1 : -1);
|
|
5271
|
-
const kept = /* @__PURE__ */ new Map();
|
|
5272
|
-
const protectedEntry = entries[protectedKey];
|
|
5273
|
-
if (protectedEntry?.namespace === namespace) kept.set(protectedEntry.key, protectedEntry);
|
|
5274
|
-
for (const entry of sorted) {
|
|
5275
|
-
if (kept.size >= maxEntries) break;
|
|
5276
|
-
kept.set(entry.key, entry);
|
|
5277
|
-
}
|
|
5278
|
-
return Object.fromEntries(Object.values(entries).filter((entry) => entry.namespace !== namespace || kept.has(entry.key)).toSorted((a, b) => a.key < b.key ? -1 : 1).map((entry) => [entry.key, entry]));
|
|
5279
|
-
}
|
|
5280
5288
|
async function withCacheFileLock(filePath, fn) {
|
|
5281
5289
|
const lockPath = `${filePath}.lock`;
|
|
5290
|
+
await mkdir(dirname(lockPath), { recursive: true });
|
|
5282
5291
|
await acquireLock(lockPath);
|
|
5283
5292
|
const result = await resultify(fn);
|
|
5284
5293
|
await rm(lockPath, {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as initRunner, t as getRunnerInstance } from "./runner-
|
|
1
|
+
import { n as initRunner, t as getRunnerInstance } from "./runner-DJWn_7p0.mjs";
|
|
2
2
|
export { getRunnerInstance, initRunner };
|