circle-ir-ai 2.26.0 → 2.28.1
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/CHANGELOG.md +205 -0
- package/dist/agents/mastra/workflow.d.ts +15 -0
- package/dist/agents/mastra/workflow.d.ts.map +1 -1
- package/dist/agents/mastra/workflow.js +33 -12
- package/dist/agents/mastra/workflow.js.map +1 -1
- package/dist/cache/backend.d.ts +104 -0
- package/dist/cache/backend.d.ts.map +1 -0
- package/dist/cache/backend.js +35 -0
- package/dist/cache/backend.js.map +1 -0
- package/dist/cache/backends/index.d.ts +44 -0
- package/dist/cache/backends/index.d.ts.map +1 -0
- package/dist/cache/backends/index.js +84 -0
- package/dist/cache/backends/index.js.map +1 -0
- package/dist/cache/backends/layout.d.ts +31 -0
- package/dist/cache/backends/layout.d.ts.map +1 -0
- package/dist/cache/backends/layout.js +46 -0
- package/dist/cache/backends/layout.js.map +1 -0
- package/dist/cache/backends/local-fs.d.ts +34 -0
- package/dist/cache/backends/local-fs.d.ts.map +1 -0
- package/dist/cache/backends/local-fs.js +113 -0
- package/dist/cache/backends/local-fs.js.map +1 -0
- package/dist/cache/backends/memory.d.ts +24 -0
- package/dist/cache/backends/memory.d.ts.map +1 -0
- package/dist/cache/backends/memory.js +38 -0
- package/dist/cache/backends/memory.js.map +1 -0
- package/dist/cache/backends/r2.d.ts +51 -0
- package/dist/cache/backends/r2.d.ts.map +1 -0
- package/dist/cache/backends/r2.js +114 -0
- package/dist/cache/backends/r2.js.map +1 -0
- package/dist/cache/classification-cache.d.ts +90 -34
- package/dist/cache/classification-cache.d.ts.map +1 -1
- package/dist/cache/classification-cache.js +131 -106
- package/dist/cache/classification-cache.js.map +1 -1
- package/dist/cache/coordinate.d.ts +59 -0
- package/dist/cache/coordinate.d.ts.map +1 -0
- package/dist/cache/coordinate.js +240 -0
- package/dist/cache/coordinate.js.map +1 -0
- package/dist/cache/discovery-cache.d.ts +40 -36
- package/dist/cache/discovery-cache.d.ts.map +1 -1
- package/dist/cache/discovery-cache.js +50 -42
- package/dist/cache/discovery-cache.js.map +1 -1
- package/dist/cache/index.d.ts +4 -0
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +2 -0
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/tree-cache.d.ts +48 -53
- package/dist/cache/tree-cache.d.ts.map +1 -1
- package/dist/cache/tree-cache.js +87 -72
- package/dist/cache/tree-cache.js.map +1 -1
- package/dist/cache/verify-cache.d.ts +26 -21
- package/dist/cache/verify-cache.d.ts.map +1 -1
- package/dist/cache/verify-cache.js +37 -29
- package/dist/cache/verify-cache.js.map +1 -1
- package/dist/llm/batch-classifier.d.ts.map +1 -1
- package/dist/llm/batch-classifier.js +3 -2
- package/dist/llm/batch-classifier.js.map +1 -1
- package/dist/llm/config.d.ts +34 -8
- package/dist/llm/config.d.ts.map +1 -1
- package/dist/llm/config.js +52 -12
- package/dist/llm/config.js.map +1 -1
- package/dist/llm/discovery.d.ts.map +1 -1
- package/dist/llm/discovery.js +52 -6
- package/dist/llm/discovery.js.map +1 -1
- package/dist/llm/verification.d.ts.map +1 -1
- package/dist/llm/verification.js +51 -9
- package/dist/llm/verification.js.map +1 -1
- package/dist/security-scan/scanner.d.ts +15 -0
- package/dist/security-scan/scanner.d.ts.map +1 -1
- package/dist/security-scan/scanner.js +34 -0
- package/dist/security-scan/scanner.js.map +1 -1
- package/package.json +3 -2
|
@@ -2,69 +2,125 @@
|
|
|
2
2
|
* Classification Cache
|
|
3
3
|
*
|
|
4
4
|
* Caches LLM classification results by composite key
|
|
5
|
-
* (content hash + classifier name + per-phase model fingerprint
|
|
6
|
-
*
|
|
5
|
+
* (schemaVer + content hash + classifier name + per-phase model fingerprint
|
|
6
|
+
* + optional coordinate hash-prefix).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* - Hit/miss tracking for observability
|
|
8
|
+
* Storage is delegated to a `CacheBackend` (cognium-ai#158). Default
|
|
9
|
+
* = `LocalFSBackend`. Selecting `LLM_CACHE_BACKEND=r2` swaps to Cloudflare
|
|
10
|
+
* R2 transparently so two runners on different machines share the same
|
|
11
|
+
* cache.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
13
|
+
* # Round 2 (2.28.0) key shape
|
|
14
|
+
*
|
|
15
|
+
* sha256(
|
|
16
|
+
* 'cic:v2' // SCHEMA_VER — bump on breaking key changes
|
|
17
|
+
* + '\0' + namespace // 'tree' | 'verify' | 'discovery'
|
|
18
|
+
* + '\0' + classifier
|
|
19
|
+
* + '\0' + content
|
|
20
|
+
* + '\0' + modelFingerprint // per-phase, see ../llm/config.ts
|
|
21
|
+
* + '\0' + coordinateHashPrefix // empty for non-tree, or _unowned
|
|
22
|
+
* )
|
|
23
|
+
*
|
|
24
|
+
* Why `namespace` is in the hash:
|
|
25
|
+
* So a tree-cache entry can never collide with a verify-cache entry
|
|
26
|
+
* even if a future caller happens to choose the same classifier name.
|
|
27
|
+
*
|
|
28
|
+
* Why `coordinate` is in the hash (when present):
|
|
29
|
+
* So `commons-lang3@3.12.0` and `commons-lang3@3.13.0` produce
|
|
30
|
+
* different SHAs for the same byte-identical file (we WANT them
|
|
31
|
+
* distinct because the surrounding rules / version-conditioned
|
|
32
|
+
* profile could differ). The coordinate is also reflected in the
|
|
33
|
+
* backend path layout — see `./backends/layout.ts` — so the cache
|
|
34
|
+
* is browseable in R2 dashboard by package.
|
|
21
35
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
36
|
+
* Model dimension (cognium-ai#151 P0 spike):
|
|
37
|
+
* `modelFingerprint` is the per-phase identity from
|
|
38
|
+
* `getDiscoveryModelFingerprint()` / `getVerifyModelFingerprint()` /
|
|
39
|
+
* `getComponentModelFingerprint()` in `../llm/config.ts`. Each cache
|
|
40
|
+
* instance uses the fingerprint scoped to its phase so swapping the
|
|
41
|
+
* discovery model doesn't invalidate verify results and vice versa
|
|
42
|
+
* (#158 D2).
|
|
43
|
+
*/
|
|
44
|
+
import type { CacheBackend, CacheNamespace } from './backend.js';
|
|
45
|
+
import type { PackageCoordinate } from './coordinate.js';
|
|
46
|
+
/**
|
|
47
|
+
* Wire-format version. Bump on every breaking change to the key composition
|
|
48
|
+
* OR the on-disk envelope shape. Operators rolling back to an older
|
|
49
|
+
* circle-ir-ai will see misses against newer SCHEMA_VER entries and
|
|
50
|
+
* re-populate cleanly.
|
|
26
51
|
*/
|
|
52
|
+
export declare const SCHEMA_VER = "cic:v2";
|
|
27
53
|
export interface ClassificationCacheOptions {
|
|
28
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Logical cache namespace. Determines backend path layout AND whether
|
|
56
|
+
* the cache participates in the coordinate-aware tree layout.
|
|
57
|
+
*
|
|
58
|
+
* Defaults to `'classifier'` for generic LLM classification callers
|
|
59
|
+
* (batch-classifier, trust passes) that don't care about the namespace
|
|
60
|
+
* dimension. The three SAST caches (`tree-cache.ts`, `verify-cache.ts`,
|
|
61
|
+
* `discovery-cache.ts`) always pass their own namespace explicitly.
|
|
62
|
+
*/
|
|
63
|
+
namespace?: CacheNamespace;
|
|
64
|
+
/** Cache directory (default: .cognium/cache/ in project root). For
|
|
65
|
+
* non-fs backends this is interpreted as a sub-prefix only. */
|
|
29
66
|
cacheDir?: string;
|
|
30
67
|
/** Maximum age of entries in ms (default: 24h) */
|
|
31
68
|
maxAge?: number;
|
|
32
69
|
/** Enable/disable cache (default: true) */
|
|
33
70
|
enabled?: boolean;
|
|
34
71
|
/**
|
|
35
|
-
* Per-phase model identity for cache namespacing (cognium-ai#151).
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* Defaults to empty string (legacy 2-component key shape).
|
|
72
|
+
* Per-phase model identity for cache namespacing (cognium-ai#151 / #158 D2).
|
|
73
|
+
* Tree-cache passes the discovery+verify joint fingerprint; verify-cache
|
|
74
|
+
* passes the verify-only fingerprint; discovery-cache passes the
|
|
75
|
+
* discovery-only fingerprint. See `../llm/config.ts`.
|
|
40
76
|
*/
|
|
41
77
|
modelFingerprint?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Override the backend instance (tests). When omitted we build one
|
|
80
|
+
* via `makeBackend(cacheDir, namespace)` based on `LLM_CACHE_BACKEND` env.
|
|
81
|
+
*/
|
|
82
|
+
backend?: CacheBackend;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Per-get/set call extras. `coordinate` is honored only for the
|
|
86
|
+
* `tree` namespace; passing it elsewhere is a no-op so callers don't
|
|
87
|
+
* have to branch.
|
|
88
|
+
*/
|
|
89
|
+
export interface CacheCallOptions {
|
|
90
|
+
coordinate?: PackageCoordinate;
|
|
42
91
|
}
|
|
43
92
|
export declare class ClassificationCache<T = unknown> {
|
|
93
|
+
private namespace;
|
|
44
94
|
private cacheDir;
|
|
45
95
|
private maxAge;
|
|
46
96
|
private enabled;
|
|
47
97
|
private modelFingerprint;
|
|
98
|
+
private backend;
|
|
48
99
|
private memoryCache;
|
|
49
100
|
private hits;
|
|
50
101
|
private misses;
|
|
51
102
|
constructor(options?: ClassificationCacheOptions);
|
|
52
103
|
/** Per-phase model identity used in cache key (cognium-ai#151). */
|
|
53
104
|
getModelFingerprint(): string;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
105
|
+
/** Backend kind identifier (`local-fs` | `memory` | `r2`). Observability. */
|
|
106
|
+
getBackendKind(): string;
|
|
107
|
+
/** Logical namespace (`tree` | `verify` | `discovery`). Observability. */
|
|
108
|
+
getNamespace(): CacheNamespace;
|
|
109
|
+
private computeDigest;
|
|
110
|
+
private toCacheKey;
|
|
57
111
|
private isValid;
|
|
58
|
-
get(content: string, classifier: string): T | null
|
|
59
|
-
set(content: string, classifier: string, result: T): void
|
|
60
|
-
has(content: string, classifier: string): boolean
|
|
61
|
-
clear(): void
|
|
62
|
-
stats(): {
|
|
112
|
+
get(content: string, classifier: string, opts?: CacheCallOptions): Promise<T | null>;
|
|
113
|
+
set(content: string, classifier: string, result: T, opts?: CacheCallOptions): Promise<void>;
|
|
114
|
+
has(content: string, classifier: string, opts?: CacheCallOptions): Promise<boolean>;
|
|
115
|
+
clear(): Promise<void>;
|
|
116
|
+
stats(): Promise<{
|
|
117
|
+
namespace: CacheNamespace;
|
|
63
118
|
memoryEntries: number;
|
|
64
119
|
diskEntries: number;
|
|
65
120
|
hitRate: number;
|
|
66
|
-
|
|
121
|
+
backend: string;
|
|
122
|
+
}>;
|
|
67
123
|
}
|
|
68
|
-
export declare function getClassificationCache(options?: ClassificationCacheOptions): ClassificationCache
|
|
124
|
+
export declare function getClassificationCache<T = unknown>(options?: ClassificationCacheOptions): ClassificationCache<T>;
|
|
69
125
|
export declare function resetClassificationCache(): void;
|
|
70
126
|
//# sourceMappingURL=classification-cache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classification-cache.d.ts","sourceRoot":"","sources":["../../src/cache/classification-cache.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"classification-cache.d.ts","sourceRoot":"","sources":["../../src/cache/classification-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAY,cAAc,EAAE,MAAM,cAAc,CAAC;AAE3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGzD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,WAAW,CAAC;AAEnC,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;oEACgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAWD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAED,qBAAa,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,GAAE,0BAA+B;IASpD,mEAAmE;IACnE,mBAAmB,IAAI,MAAM;IAI7B,6EAA6E;IAC7E,cAAc,IAAI,MAAM;IAIxB,0EAA0E;IAC1E,YAAY,IAAI,cAAc;IAI9B,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,OAAO;IAKT,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAqCpF,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB3F,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAInF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,KAAK,IAAI,OAAO,CAAC;QACrB,SAAS,EAAE,cAAc,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CAcH;AASD,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,GAAE,0BAA+B,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAUpH;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -2,192 +2,217 @@
|
|
|
2
2
|
* Classification Cache
|
|
3
3
|
*
|
|
4
4
|
* Caches LLM classification results by composite key
|
|
5
|
-
* (content hash + classifier name + per-phase model fingerprint
|
|
6
|
-
*
|
|
5
|
+
* (schemaVer + content hash + classifier name + per-phase model fingerprint
|
|
6
|
+
* + optional coordinate hash-prefix).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* - Hit/miss tracking for observability
|
|
8
|
+
* Storage is delegated to a `CacheBackend` (cognium-ai#158). Default
|
|
9
|
+
* = `LocalFSBackend`. Selecting `LLM_CACHE_BACKEND=r2` swaps to Cloudflare
|
|
10
|
+
* R2 transparently so two runners on different machines share the same
|
|
11
|
+
* cache.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
13
|
+
* # Round 2 (2.28.0) key shape
|
|
14
|
+
*
|
|
15
|
+
* sha256(
|
|
16
|
+
* 'cic:v2' // SCHEMA_VER — bump on breaking key changes
|
|
17
|
+
* + '\0' + namespace // 'tree' | 'verify' | 'discovery'
|
|
18
|
+
* + '\0' + classifier
|
|
19
|
+
* + '\0' + content
|
|
20
|
+
* + '\0' + modelFingerprint // per-phase, see ../llm/config.ts
|
|
21
|
+
* + '\0' + coordinateHashPrefix // empty for non-tree, or _unowned
|
|
22
|
+
* )
|
|
23
|
+
*
|
|
24
|
+
* Why `namespace` is in the hash:
|
|
25
|
+
* So a tree-cache entry can never collide with a verify-cache entry
|
|
26
|
+
* even if a future caller happens to choose the same classifier name.
|
|
21
27
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
28
|
+
* Why `coordinate` is in the hash (when present):
|
|
29
|
+
* So `commons-lang3@3.12.0` and `commons-lang3@3.13.0` produce
|
|
30
|
+
* different SHAs for the same byte-identical file (we WANT them
|
|
31
|
+
* distinct because the surrounding rules / version-conditioned
|
|
32
|
+
* profile could differ). The coordinate is also reflected in the
|
|
33
|
+
* backend path layout — see `./backends/layout.ts` — so the cache
|
|
34
|
+
* is browseable in R2 dashboard by package.
|
|
35
|
+
*
|
|
36
|
+
* Model dimension (cognium-ai#151 P0 spike):
|
|
37
|
+
* `modelFingerprint` is the per-phase identity from
|
|
38
|
+
* `getDiscoveryModelFingerprint()` / `getVerifyModelFingerprint()` /
|
|
39
|
+
* `getComponentModelFingerprint()` in `../llm/config.ts`. Each cache
|
|
40
|
+
* instance uses the fingerprint scoped to its phase so swapping the
|
|
41
|
+
* discovery model doesn't invalidate verify results and vice versa
|
|
42
|
+
* (#158 D2).
|
|
26
43
|
*/
|
|
27
|
-
import * as fs from 'fs';
|
|
28
44
|
import * as path from 'path';
|
|
29
45
|
import * as crypto from 'crypto';
|
|
46
|
+
import { makeBackend } from './backends/index.js';
|
|
47
|
+
import { coordinateSegments } from './coordinate.js';
|
|
48
|
+
/**
|
|
49
|
+
* Wire-format version. Bump on every breaking change to the key composition
|
|
50
|
+
* OR the on-disk envelope shape. Operators rolling back to an older
|
|
51
|
+
* circle-ir-ai will see misses against newer SCHEMA_VER entries and
|
|
52
|
+
* re-populate cleanly.
|
|
53
|
+
*/
|
|
54
|
+
export const SCHEMA_VER = 'cic:v2';
|
|
30
55
|
const DEFAULT_MAX_AGE = 24 * 60 * 60 * 1000; // 24 hours
|
|
31
56
|
export class ClassificationCache {
|
|
57
|
+
namespace;
|
|
32
58
|
cacheDir;
|
|
33
59
|
maxAge;
|
|
34
60
|
enabled;
|
|
35
61
|
modelFingerprint;
|
|
62
|
+
backend;
|
|
36
63
|
memoryCache = new Map();
|
|
37
64
|
hits = 0;
|
|
38
65
|
misses = 0;
|
|
39
66
|
constructor(options = {}) {
|
|
67
|
+
this.namespace = options.namespace ?? 'classifier';
|
|
40
68
|
this.cacheDir = options.cacheDir || path.join(process.cwd(), '.cognium', 'cache');
|
|
41
69
|
this.maxAge = options.maxAge ?? DEFAULT_MAX_AGE;
|
|
42
70
|
this.enabled = options.enabled ?? true;
|
|
43
71
|
this.modelFingerprint = options.modelFingerprint ?? '';
|
|
44
|
-
|
|
45
|
-
this.ensureCacheDir();
|
|
46
|
-
}
|
|
72
|
+
this.backend = options.backend ?? makeBackend(this.cacheDir, this.namespace);
|
|
47
73
|
}
|
|
48
74
|
/** Per-phase model identity used in cache key (cognium-ai#151). */
|
|
49
75
|
getModelFingerprint() {
|
|
50
76
|
return this.modelFingerprint;
|
|
51
77
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// `'\0' + ''` collapse — bit-identical to ≤2.21.0 only when no
|
|
56
|
-
// fingerprint is supplied at all, which is the back-compat path.
|
|
57
|
-
const parts = this.modelFingerprint
|
|
58
|
-
? content + '\0' + classifier + '\0' + this.modelFingerprint
|
|
59
|
-
: content + '\0' + classifier;
|
|
60
|
-
return crypto.createHash('sha256').update(parts).digest('hex');
|
|
78
|
+
/** Backend kind identifier (`local-fs` | `memory` | `r2`). Observability. */
|
|
79
|
+
getBackendKind() {
|
|
80
|
+
return this.backend.kind;
|
|
61
81
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
82
|
+
/** Logical namespace (`tree` | `verify` | `discovery`). Observability. */
|
|
83
|
+
getNamespace() {
|
|
84
|
+
return this.namespace;
|
|
65
85
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
86
|
+
computeDigest(content, classifier, coordinate) {
|
|
87
|
+
// Coordinate hash-prefix only applies to the `tree` namespace.
|
|
88
|
+
// Including it in the digest (not just the path) is what guarantees
|
|
89
|
+
// a fileSHA collision across packages still produces distinct keys.
|
|
90
|
+
const coordPart = (this.namespace === 'tree' && coordinate)
|
|
91
|
+
? coordinateSegments(coordinate).hashPrefix
|
|
92
|
+
: '';
|
|
93
|
+
const parts = SCHEMA_VER
|
|
94
|
+
+ '\0' + this.namespace
|
|
95
|
+
+ '\0' + classifier
|
|
96
|
+
+ '\0' + content
|
|
97
|
+
+ '\0' + this.modelFingerprint
|
|
98
|
+
+ '\0' + coordPart;
|
|
99
|
+
return crypto.createHash('sha256').update(parts).digest('hex');
|
|
100
|
+
}
|
|
101
|
+
toCacheKey(digest, coordinate) {
|
|
102
|
+
const key = { namespace: this.namespace, digest };
|
|
103
|
+
if (this.namespace === 'tree' && coordinate) {
|
|
104
|
+
key.coordinate = coordinate;
|
|
69
105
|
}
|
|
106
|
+
return key;
|
|
70
107
|
}
|
|
71
108
|
isValid(entry) {
|
|
109
|
+
if (entry.schemaVer !== SCHEMA_VER)
|
|
110
|
+
return false;
|
|
72
111
|
return (Date.now() - entry.timestamp) <= this.maxAge;
|
|
73
112
|
}
|
|
74
|
-
get(content, classifier) {
|
|
113
|
+
async get(content, classifier, opts) {
|
|
75
114
|
if (!this.enabled)
|
|
76
115
|
return null;
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
116
|
+
const digest = this.computeDigest(content, classifier, opts?.coordinate);
|
|
117
|
+
const cacheKey = this.toCacheKey(digest, opts?.coordinate);
|
|
118
|
+
// Memory cache (process-local hot path)
|
|
119
|
+
const memEntry = this.memoryCache.get(digest);
|
|
80
120
|
if (memEntry && this.isValid(memEntry)) {
|
|
81
121
|
this.hits++;
|
|
82
122
|
return memEntry.result;
|
|
83
123
|
}
|
|
84
|
-
//
|
|
85
|
-
const cachePath = this.getCachePath(key);
|
|
124
|
+
// Backend (disk / R2 / etc.)
|
|
86
125
|
try {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const entry = JSON.parse(
|
|
126
|
+
const raw = await this.backend.get(cacheKey);
|
|
127
|
+
if (raw !== null) {
|
|
128
|
+
const entry = JSON.parse(raw);
|
|
90
129
|
if (this.isValid(entry)) {
|
|
91
|
-
this.memoryCache.set(
|
|
130
|
+
this.memoryCache.set(digest, entry);
|
|
92
131
|
this.hits++;
|
|
93
132
|
return entry.result;
|
|
94
133
|
}
|
|
95
|
-
|
|
96
|
-
|
|
134
|
+
// Stale OR schemaVer-mismatch — drop. We don't await the deletion
|
|
135
|
+
// to keep the read path fast.
|
|
136
|
+
if (this.backend.delete) {
|
|
137
|
+
void this.backend.delete(cacheKey);
|
|
97
138
|
}
|
|
98
139
|
}
|
|
99
140
|
}
|
|
100
141
|
catch {
|
|
101
|
-
//
|
|
142
|
+
// Decode / I/O error: treat as miss.
|
|
102
143
|
}
|
|
103
144
|
this.misses++;
|
|
104
145
|
return null;
|
|
105
146
|
}
|
|
106
|
-
set(content, classifier, result) {
|
|
147
|
+
async set(content, classifier, result, opts) {
|
|
107
148
|
if (!this.enabled)
|
|
108
149
|
return;
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
150
|
+
const digest = this.computeDigest(content, classifier, opts?.coordinate);
|
|
151
|
+
const cacheKey = this.toCacheKey(digest, opts?.coordinate);
|
|
152
|
+
const entry = {
|
|
153
|
+
schemaVer: SCHEMA_VER,
|
|
154
|
+
key: digest,
|
|
155
|
+
timestamp: Date.now(),
|
|
156
|
+
result,
|
|
157
|
+
};
|
|
158
|
+
this.memoryCache.set(digest, entry);
|
|
117
159
|
try {
|
|
118
|
-
|
|
119
|
-
fs.mkdirSync(cacheSubdir, { recursive: true });
|
|
120
|
-
}
|
|
121
|
-
fs.writeFileSync(tmpPath, JSON.stringify(entry));
|
|
122
|
-
fs.renameSync(tmpPath, cachePath);
|
|
160
|
+
await this.backend.set(cacheKey, JSON.stringify(entry));
|
|
123
161
|
}
|
|
124
162
|
catch {
|
|
125
|
-
|
|
126
|
-
fs.unlinkSync(tmpPath);
|
|
127
|
-
}
|
|
128
|
-
catch { /* ignore */ }
|
|
163
|
+
// Cache write is best-effort; never fail the caller.
|
|
129
164
|
}
|
|
130
165
|
}
|
|
131
|
-
has(content, classifier) {
|
|
132
|
-
return this.get(content, classifier) !== null;
|
|
166
|
+
async has(content, classifier, opts) {
|
|
167
|
+
return (await this.get(content, classifier, opts)) !== null;
|
|
133
168
|
}
|
|
134
|
-
clear() {
|
|
169
|
+
async clear() {
|
|
135
170
|
this.memoryCache.clear();
|
|
136
171
|
this.hits = 0;
|
|
137
172
|
this.misses = 0;
|
|
138
|
-
if (
|
|
173
|
+
if (this.backend.clear) {
|
|
139
174
|
try {
|
|
140
|
-
|
|
141
|
-
this.ensureCacheDir();
|
|
142
|
-
}
|
|
143
|
-
catch {
|
|
144
|
-
// Ignore errors
|
|
175
|
+
await this.backend.clear();
|
|
145
176
|
}
|
|
177
|
+
catch { /* ignore */ }
|
|
146
178
|
}
|
|
147
179
|
}
|
|
148
|
-
stats() {
|
|
180
|
+
async stats() {
|
|
149
181
|
let diskEntries = 0;
|
|
150
|
-
if (
|
|
182
|
+
if (this.backend.count) {
|
|
151
183
|
try {
|
|
152
|
-
|
|
153
|
-
for (const subdir of subdirs) {
|
|
154
|
-
const subdirPath = path.join(this.cacheDir, subdir);
|
|
155
|
-
try {
|
|
156
|
-
if (fs.statSync(subdirPath).isDirectory()) {
|
|
157
|
-
diskEntries += fs.readdirSync(subdirPath).length;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
// Skip unreadable subdirs
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
// Ignore
|
|
184
|
+
diskEntries = await this.backend.count();
|
|
167
185
|
}
|
|
186
|
+
catch { /* ignore */ }
|
|
168
187
|
}
|
|
169
188
|
const total = this.hits + this.misses;
|
|
170
189
|
return {
|
|
190
|
+
namespace: this.namespace,
|
|
171
191
|
memoryEntries: this.memoryCache.size,
|
|
172
192
|
diskEntries,
|
|
173
193
|
hitRate: total > 0 ? this.hits / total : 0,
|
|
194
|
+
backend: this.backend.kind,
|
|
174
195
|
};
|
|
175
196
|
}
|
|
176
197
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
export function getClassificationCache(options) {
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Singleton table — keyed on (namespace, modelFingerprint) so two scans
|
|
200
|
+
* with different per-phase models in the same process get distinct
|
|
201
|
+
* caches (cognium-ai#151).
|
|
202
|
+
*/
|
|
203
|
+
const singletons = new Map();
|
|
204
|
+
export function getClassificationCache(options = {}) {
|
|
205
|
+
const fp = options.modelFingerprint ?? '';
|
|
206
|
+
const namespace = options.namespace ?? 'classifier';
|
|
207
|
+
const slot = `${namespace}\0${fp}`;
|
|
208
|
+
let existing = singletons.get(slot);
|
|
209
|
+
if (!existing) {
|
|
210
|
+
existing = new ClassificationCache(options);
|
|
211
|
+
singletons.set(slot, existing);
|
|
187
212
|
}
|
|
188
|
-
return
|
|
213
|
+
return existing;
|
|
189
214
|
}
|
|
190
215
|
export function resetClassificationCache() {
|
|
191
|
-
|
|
216
|
+
singletons.clear();
|
|
192
217
|
}
|
|
193
218
|
//# sourceMappingURL=classification-cache.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classification-cache.js","sourceRoot":"","sources":["../../src/cache/classification-cache.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"classification-cache.js","sourceRoot":"","sources":["../../src/cache/classification-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC;AAyCnC,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AAWxD,MAAM,OAAO,mBAAmB;IACtB,SAAS,CAAiB;IAC1B,QAAQ,CAAS;IACjB,MAAM,CAAS;IACf,OAAO,CAAU;IACjB,gBAAgB,CAAS;IACzB,OAAO,CAAe;IACtB,WAAW,GAA+B,IAAI,GAAG,EAAE,CAAC;IACpD,IAAI,GAAG,CAAC,CAAC;IACT,MAAM,GAAG,CAAC,CAAC;IAEnB,YAAY,UAAsC,EAAE;QAClD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,YAAY,CAAC;QACnD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAClF,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,eAAe,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC;QACvC,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC;QACvD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/E,CAAC;IAED,mEAAmE;IACnE,mBAAmB;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,6EAA6E;IAC7E,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,0EAA0E;IAC1E,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEO,aAAa,CACnB,OAAe,EACf,UAAkB,EAClB,UAAyC;QAEzC,+DAA+D;QAC/D,oEAAoE;QACpE,oEAAoE;QACpE,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,UAAU,CAAC;YACzD,CAAC,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,UAAU;YAC3C,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,KAAK,GACT,UAAU;cACR,IAAI,GAAG,IAAI,CAAC,SAAS;cACrB,IAAI,GAAG,UAAU;cACjB,IAAI,GAAG,OAAO;cACd,IAAI,GAAG,IAAI,CAAC,gBAAgB;cAC5B,IAAI,GAAG,SAAS,CAAC;QACrB,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IAEO,UAAU,CAChB,MAAc,EACd,UAAyC;QAEzC,MAAM,GAAG,GAAa,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAC5D,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,UAAU,EAAE,CAAC;YAC5C,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC;QAC9B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,OAAO,CAAC,KAAoB;QAClC,IAAI,KAAK,CAAC,SAAS,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,UAAkB,EAAE,IAAuB;QACpE,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAE/B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAE3D,wCAAwC;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,QAAQ,CAAC,MAAM,CAAC;QACzB,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;gBAC/C,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACxB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBACpC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACZ,OAAO,KAAK,CAAC,MAAM,CAAC;gBACtB,CAAC;gBACD,kEAAkE;gBAClE,8BAA8B;gBAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;oBACxB,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qCAAqC;QACvC,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,UAAkB,EAAE,MAAS,EAAE,IAAuB;QAC/E,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAkB;YAC3B,SAAS,EAAE,UAAU;YACrB,GAAG,EAAE,MAAM;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,MAAM;SACP,CAAC;QAEF,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,UAAkB,EAAE,IAAuB;QACpE,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC;gBAAC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QAOT,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC;gBAAC,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;QACtC,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,aAAa,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI;YACpC,WAAW;YACX,OAAO,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC1C,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;SAC3B,CAAC;IACJ,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,GAA8C,IAAI,GAAG,EAAE,CAAC;AAExE,MAAM,UAAU,sBAAsB,CAAc,UAAsC,EAAE;IAC1F,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC;IAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,YAAY,CAAC;IACpD,MAAM,IAAI,GAAG,GAAG,SAAS,KAAK,EAAE,EAAE,CAAC;IACnC,IAAI,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,IAAI,mBAAmB,CAAI,OAAO,CAAiC,CAAC;QAC/E,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,QAAkC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,UAAU,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package coordinate detection for cache path layout.
|
|
3
|
+
*
|
|
4
|
+
* The tree-cache backend (R2 / local-fs) uses the coordinate to build a
|
|
5
|
+
* package-aware key layout:
|
|
6
|
+
*
|
|
7
|
+
* tree/<ecosystem>/<name>@<version>/<4hex>/<sha>.json (published coords)
|
|
8
|
+
* tree/_local/<name>@<version>/<4hex>/<sha>.json (repo-root manifest)
|
|
9
|
+
* tree/_unowned/<4hex>/<sha>.json (no coordinate)
|
|
10
|
+
*
|
|
11
|
+
* Coordinate is resolved ONCE per scan from the repo root. We deliberately
|
|
12
|
+
* keep the extractor minimal (only manifest files we can parse with zero
|
|
13
|
+
* deps) so it can be folded into hot paths without measurable overhead.
|
|
14
|
+
*
|
|
15
|
+
* What's intentionally *not* in scope here:
|
|
16
|
+
* - per-file coordinate from `node_modules/<pkg>/...` paths (deferred until
|
|
17
|
+
* we actually scan transitive deps)
|
|
18
|
+
* - lockfile-derived coordinates
|
|
19
|
+
* - Maven `<artifactId>` resolution from a multi-module reactor
|
|
20
|
+
*
|
|
21
|
+
* For the first-party github sweep use case, every file in a repo shares
|
|
22
|
+
* the same coordinate (or falls through to `_unowned`), which is exactly
|
|
23
|
+
* what we want for cross-runner cache sharing.
|
|
24
|
+
*/
|
|
25
|
+
export type Ecosystem = 'npm' | 'maven' | 'pypi' | 'cargo' | 'go' | '_local' | '_unowned';
|
|
26
|
+
export interface PackageCoordinate {
|
|
27
|
+
ecosystem: Ecosystem;
|
|
28
|
+
/** Package name in its ecosystem's canonical form (lower-case, normalized). */
|
|
29
|
+
name: string;
|
|
30
|
+
/** Resolved version string, or `'HEAD'` for `_local`. */
|
|
31
|
+
version: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The sentinel coordinate emitted when the repo has no detectable manifest.
|
|
35
|
+
*
|
|
36
|
+
* Tree-cache content still gets cached, just under `_unowned/<4hex>/<sha>`.
|
|
37
|
+
* Re-using the singleton means the path layout is constant for un-coord'd
|
|
38
|
+
* scans and avoids per-file object allocation.
|
|
39
|
+
*/
|
|
40
|
+
export declare const UNOWNED: PackageCoordinate;
|
|
41
|
+
/**
|
|
42
|
+
* Render the coordinate as a stable path prefix and a stable hash prefix.
|
|
43
|
+
*
|
|
44
|
+
* `pathSegment` is what the backend uses to build the R2 / local-fs key.
|
|
45
|
+
* `hashPrefix` is what cache-key composers fold into the content hash so
|
|
46
|
+
* the SHA itself encodes the coordinate (no collision across packages).
|
|
47
|
+
*/
|
|
48
|
+
export declare function coordinateSegments(c: PackageCoordinate): {
|
|
49
|
+
pathSegment: string;
|
|
50
|
+
hashPrefix: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Detect a package coordinate from the repo root manifest files.
|
|
54
|
+
*
|
|
55
|
+
* Synchronous because it runs once per scan at scanner entry and the
|
|
56
|
+
* disk reads are tiny (`package.json` / `pom.xml`).
|
|
57
|
+
*/
|
|
58
|
+
export declare function detectCoordinate(repoRoot: string): PackageCoordinate;
|
|
59
|
+
//# sourceMappingURL=coordinate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinate.d.ts","sourceRoot":"","sources":["../../src/cache/coordinate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE1F,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,EAAE,iBAIpB,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,iBAAiB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CASpG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAwFpE"}
|