circle-ir-ai 2.21.0 → 2.22.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/CHANGELOG.md +44 -0
- package/dist/cache/classification-cache.d.ts +27 -2
- package/dist/cache/classification-cache.d.ts.map +1 -1
- package/dist/cache/classification-cache.js +37 -5
- package/dist/cache/classification-cache.js.map +1 -1
- package/dist/llm/batch-classifier.d.ts.map +1 -1
- package/dist/llm/batch-classifier.js +13 -4
- package/dist/llm/batch-classifier.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,50 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.22.0] - 2026-06-30
|
|
9
|
+
|
|
10
|
+
### Added — Cache-key model dimension (cognium-ai#151 P0 spike)
|
|
11
|
+
|
|
12
|
+
`ClassificationCache` now accepts a `modelFingerprint` option (typically
|
|
13
|
+
the output of `getPhaseModelFingerprint(config)` from `src/llm/config.ts`)
|
|
14
|
+
and embeds it as a third component of the cache key alongside the
|
|
15
|
+
content hash and classifier name. This closes the silent cache-poisoning
|
|
16
|
+
hole where switching `LLM_DISCOVERY_MODEL` between scans reused the
|
|
17
|
+
previous model's classifier results.
|
|
18
|
+
|
|
19
|
+
**Wire-through:**
|
|
20
|
+
|
|
21
|
+
- `ClassificationCacheOptions.modelFingerprint?: string` (additive,
|
|
22
|
+
default `''`)
|
|
23
|
+
- `ClassificationCache.getModelFingerprint(): string` (public accessor
|
|
24
|
+
for singleton fingerprint comparison)
|
|
25
|
+
- `getClassificationCache(options)` now resets the singleton when the
|
|
26
|
+
requested fingerprint differs from the cached instance — two scans
|
|
27
|
+
with different per-phase models in the same process get distinct
|
|
28
|
+
caches instead of poisoning each other
|
|
29
|
+
- `BatchClassifier` constructor resolves config first, derives the
|
|
30
|
+
fingerprint via `getPhaseModelFingerprint(config)`, and threads it
|
|
31
|
+
into `getClassificationCache({ enabled, modelFingerprint })`
|
|
32
|
+
|
|
33
|
+
**Back-compat:** when `modelFingerprint` is omitted or empty, the
|
|
34
|
+
key falls through to the prior 2-component shape — bit-identical to
|
|
35
|
+
≤2.21.0. Existing on-disk entries from ≤2.21.0 keep hitting. The
|
|
36
|
+
first scan after wire-through is a cache miss only for the call sites
|
|
37
|
+
that opt into the fingerprint.
|
|
38
|
+
|
|
39
|
+
**Tests:** 8 new tests in `tests/classification-cache.test.ts` cover
|
|
40
|
+
singleton swap-on-fingerprint-change, singleton stability when
|
|
41
|
+
fingerprint identical, default-to-empty back-compat, cross-model entry
|
|
42
|
+
isolation, legacy disk-layout preservation, and empty-vs-explicit
|
|
43
|
+
non-collision. Existing 6 tests in `tests/llm/phase-model-split.test.ts`
|
|
44
|
+
continue to verify the regression coverage on legacy single-model
|
|
45
|
+
behavior + fingerprint shape (acceptance criterion 5). Full suite:
|
|
46
|
+
982 passed | 3 skipped.
|
|
47
|
+
|
|
48
|
+
This is the cache-key half of cognium-ai#151 (acceptance criteria 4 +
|
|
49
|
+
6). Criterion 3 (`meta.json` `perPhase[*].model` telemetry) is
|
|
50
|
+
deferred to the harness side.
|
|
51
|
+
|
|
8
52
|
## [2.21.0] - 2026-06-30
|
|
9
53
|
|
|
10
54
|
### Added — withLLMContext wrap across 23 external chatJSON callsites (closes cognium-ai#149 gap)
|
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Classification Cache
|
|
3
3
|
*
|
|
4
|
-
* Caches LLM classification results by composite key
|
|
4
|
+
* Caches LLM classification results by composite key
|
|
5
|
+
* (content hash + classifier name + per-phase model fingerprint).
|
|
5
6
|
* Optimized for batch classifier workloads with shorter TTL than FileCache.
|
|
6
7
|
*
|
|
7
8
|
* Key differences from FileCache:
|
|
8
|
-
* - Composite key: SHA-256(content + '\0' + classifierName)
|
|
9
|
+
* - Composite key: SHA-256(content + '\0' + classifierName + '\0' + modelFingerprint)
|
|
9
10
|
* - Shorter default TTL (24h vs 7d)
|
|
10
11
|
* - Cache directory: .cognium/cache/
|
|
11
12
|
* - Hit/miss tracking for observability
|
|
13
|
+
*
|
|
14
|
+
* Model dimension (cognium-ai#151 P0 spike):
|
|
15
|
+
* When `modelFingerprint` is supplied (typically via
|
|
16
|
+
* `getPhaseModelFingerprint()` from `../llm/config.ts`) it becomes part
|
|
17
|
+
* of the cache key. This prevents a `gemma3:12b` discovery result from
|
|
18
|
+
* being silently reused when the operator switches to `gpt-4o-mini` for
|
|
19
|
+
* discovery. The fingerprint is the same identity the persistent cache
|
|
20
|
+
* (#158) uses, so call-site cache and S3 cache stay in lockstep.
|
|
21
|
+
*
|
|
22
|
+
* Backward compat: when omitted the key falls through to the prior
|
|
23
|
+
* 2-component shape, so existing callers (and on-disk entries from
|
|
24
|
+
* ≤2.21.0) keep working — the first run after wire-through is a cache
|
|
25
|
+
* miss only for the call sites that opt into the fingerprint.
|
|
12
26
|
*/
|
|
13
27
|
export interface ClassificationCacheOptions {
|
|
14
28
|
/** Cache directory (default: .cognium/cache/ in project root) */
|
|
@@ -17,15 +31,26 @@ export interface ClassificationCacheOptions {
|
|
|
17
31
|
maxAge?: number;
|
|
18
32
|
/** Enable/disable cache (default: true) */
|
|
19
33
|
enabled?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Per-phase model identity for cache namespacing (cognium-ai#151).
|
|
36
|
+
* Typically the output of `getPhaseModelFingerprint(config)` from
|
|
37
|
+
* `../llm/config.ts`. Two scans with different discovery / verification
|
|
38
|
+
* models will produce different cache keys and not poison each other.
|
|
39
|
+
* Defaults to empty string (legacy 2-component key shape).
|
|
40
|
+
*/
|
|
41
|
+
modelFingerprint?: string;
|
|
20
42
|
}
|
|
21
43
|
export declare class ClassificationCache<T = unknown> {
|
|
22
44
|
private cacheDir;
|
|
23
45
|
private maxAge;
|
|
24
46
|
private enabled;
|
|
47
|
+
private modelFingerprint;
|
|
25
48
|
private memoryCache;
|
|
26
49
|
private hits;
|
|
27
50
|
private misses;
|
|
28
51
|
constructor(options?: ClassificationCacheOptions);
|
|
52
|
+
/** Per-phase model identity used in cache key (cognium-ai#151). */
|
|
53
|
+
getModelFingerprint(): string;
|
|
29
54
|
private computeKey;
|
|
30
55
|
private getCachePath;
|
|
31
56
|
private ensureCacheDir;
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAUD,qBAAa,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,GAAE,0BAA+B;IAWpD,mEAAmE;IACnE,mBAAmB,IAAI,MAAM;IAI7B,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,OAAO;IAIf,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAmClD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI;IAwBzD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAIjD,KAAK,IAAI,IAAI;IAeb,KAAK,IAAI;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;CA4BzE;AASD,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,mBAAmB,CAMhG;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Classification Cache
|
|
3
3
|
*
|
|
4
|
-
* Caches LLM classification results by composite key
|
|
4
|
+
* Caches LLM classification results by composite key
|
|
5
|
+
* (content hash + classifier name + per-phase model fingerprint).
|
|
5
6
|
* Optimized for batch classifier workloads with shorter TTL than FileCache.
|
|
6
7
|
*
|
|
7
8
|
* Key differences from FileCache:
|
|
8
|
-
* - Composite key: SHA-256(content + '\0' + classifierName)
|
|
9
|
+
* - Composite key: SHA-256(content + '\0' + classifierName + '\0' + modelFingerprint)
|
|
9
10
|
* - Shorter default TTL (24h vs 7d)
|
|
10
11
|
* - Cache directory: .cognium/cache/
|
|
11
12
|
* - Hit/miss tracking for observability
|
|
13
|
+
*
|
|
14
|
+
* Model dimension (cognium-ai#151 P0 spike):
|
|
15
|
+
* When `modelFingerprint` is supplied (typically via
|
|
16
|
+
* `getPhaseModelFingerprint()` from `../llm/config.ts`) it becomes part
|
|
17
|
+
* of the cache key. This prevents a `gemma3:12b` discovery result from
|
|
18
|
+
* being silently reused when the operator switches to `gpt-4o-mini` for
|
|
19
|
+
* discovery. The fingerprint is the same identity the persistent cache
|
|
20
|
+
* (#158) uses, so call-site cache and S3 cache stay in lockstep.
|
|
21
|
+
*
|
|
22
|
+
* Backward compat: when omitted the key falls through to the prior
|
|
23
|
+
* 2-component shape, so existing callers (and on-disk entries from
|
|
24
|
+
* ≤2.21.0) keep working — the first run after wire-through is a cache
|
|
25
|
+
* miss only for the call sites that opt into the fingerprint.
|
|
12
26
|
*/
|
|
13
27
|
import * as fs from 'fs';
|
|
14
28
|
import * as path from 'path';
|
|
@@ -18,6 +32,7 @@ export class ClassificationCache {
|
|
|
18
32
|
cacheDir;
|
|
19
33
|
maxAge;
|
|
20
34
|
enabled;
|
|
35
|
+
modelFingerprint;
|
|
21
36
|
memoryCache = new Map();
|
|
22
37
|
hits = 0;
|
|
23
38
|
misses = 0;
|
|
@@ -25,12 +40,24 @@ export class ClassificationCache {
|
|
|
25
40
|
this.cacheDir = options.cacheDir || path.join(process.cwd(), '.cognium', 'cache');
|
|
26
41
|
this.maxAge = options.maxAge ?? DEFAULT_MAX_AGE;
|
|
27
42
|
this.enabled = options.enabled ?? true;
|
|
43
|
+
this.modelFingerprint = options.modelFingerprint ?? '';
|
|
28
44
|
if (this.enabled) {
|
|
29
45
|
this.ensureCacheDir();
|
|
30
46
|
}
|
|
31
47
|
}
|
|
48
|
+
/** Per-phase model identity used in cache key (cognium-ai#151). */
|
|
49
|
+
getModelFingerprint() {
|
|
50
|
+
return this.modelFingerprint;
|
|
51
|
+
}
|
|
32
52
|
computeKey(content, classifier) {
|
|
33
|
-
|
|
53
|
+
// 3-component key when fingerprint present (cognium-ai#151). When
|
|
54
|
+
// empty falls through to the prior 2-component shape via the trailing
|
|
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');
|
|
34
61
|
}
|
|
35
62
|
getCachePath(key) {
|
|
36
63
|
const subdir = key.substring(0, 2);
|
|
@@ -147,10 +174,15 @@ export class ClassificationCache {
|
|
|
147
174
|
};
|
|
148
175
|
}
|
|
149
176
|
}
|
|
150
|
-
// Singleton
|
|
177
|
+
// Singleton — keyed on cacheDir + modelFingerprint so two scans with
|
|
178
|
+
// different per-phase models in the same process get distinct caches
|
|
179
|
+
// (cognium-ai#151). Without the fingerprint dimension, switching
|
|
180
|
+
// `LLM_DISCOVERY_MODEL` between scans would silently reuse the first
|
|
181
|
+
// scan's classifier results.
|
|
151
182
|
let classificationCache = null;
|
|
152
183
|
export function getClassificationCache(options) {
|
|
153
|
-
|
|
184
|
+
const wantFingerprint = options?.modelFingerprint ?? '';
|
|
185
|
+
if (!classificationCache || classificationCache.getModelFingerprint() !== wantFingerprint) {
|
|
154
186
|
classificationCache = new ClassificationCache(options);
|
|
155
187
|
}
|
|
156
188
|
return classificationCache;
|
|
@@ -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":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-classifier.d.ts","sourceRoot":"","sources":["../../src/llm/batch-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAS7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMtD,MAAM,WAAW,oBAAoB;IACnC,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3D,iDAAiD;IACjD,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,YAAY,EAAE,CAAC;CACrF;AAMD,MAAM,WAAW,sBAAsB;IACrC,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,KAAK,EAAE;QACL,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAMD,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,eAAe,CAAwB;gBAEnC,OAAO,GAAE,sBAA2B;
|
|
1
|
+
{"version":3,"file":"batch-classifier.d.ts","sourceRoot":"","sources":["../../src/llm/batch-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAS7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMtD,MAAM,WAAW,oBAAoB;IACnC,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3D,iDAAiD;IACjD,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,YAAY,EAAE,CAAC;CACrF;AAMD,MAAM,WAAW,sBAAsB;IACrC,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,KAAK,EAAE;QACL,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAMD,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,eAAe,CAAwB;gBAEnC,OAAO,GAAE,sBAA2B;IA+B1C,QAAQ,CACZ,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,EAC/C,WAAW,EAAE,oBAAoB,EAAE,GAClC,OAAO,CAAC,qBAAqB,CAAC;CAyGlC;AAMD,wBAAsB,aAAa,CACjC,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAC/C,WAAW,EAAE,oBAAoB,EAAE,EACnC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,qBAAqB,CAAC,CAGhC"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - Graceful degradation when LLM not configured
|
|
9
9
|
*/
|
|
10
10
|
import PQueue from 'p-queue';
|
|
11
|
-
import { getDefaultLLMConfig } from './config.js';
|
|
11
|
+
import { getDefaultLLMConfig, getPhaseModelFingerprint } from './config.js';
|
|
12
12
|
import { getAxLLMClient } from './ax-client.js';
|
|
13
13
|
import { serializeToCGS } from './cgs-serializer.js';
|
|
14
14
|
import { withLLMContext } from './debug-context.js';
|
|
@@ -24,21 +24,30 @@ export class BatchClassifier {
|
|
|
24
24
|
circleIRResults;
|
|
25
25
|
constructor(options = {}) {
|
|
26
26
|
this.concurrency = options.concurrency ?? 5;
|
|
27
|
-
this.cache = getClassificationCache({ enabled: options.enableCache ?? true });
|
|
28
27
|
this.useCGS = options.useCGS ?? true;
|
|
29
28
|
this.circleIRResults = options.circleIRResults ?? new Map();
|
|
30
|
-
//
|
|
29
|
+
// Resolve config first so we can derive the per-phase model
|
|
30
|
+
// fingerprint and pass it into the classification cache (cognium-ai#151).
|
|
31
|
+
// Without the fingerprint dimension, switching `LLM_DISCOVERY_MODEL`
|
|
32
|
+
// between scans silently reused the previous model's results.
|
|
33
|
+
let modelFingerprint = '';
|
|
31
34
|
try {
|
|
32
35
|
const config = options.llmConfig
|
|
33
36
|
? { ...getDefaultLLMConfig(), ...options.llmConfig }
|
|
34
37
|
: getDefaultLLMConfig();
|
|
38
|
+
modelFingerprint = getPhaseModelFingerprint(config);
|
|
35
39
|
if (config.apiKey) {
|
|
36
40
|
this.llmClient = getAxLLMClient(config);
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
catch {
|
|
40
|
-
// No LLM available
|
|
44
|
+
// No LLM available; fall through with empty fingerprint (legacy
|
|
45
|
+
// key shape) so any pre-existing on-disk entries still hit.
|
|
41
46
|
}
|
|
47
|
+
this.cache = getClassificationCache({
|
|
48
|
+
enabled: options.enableCache ?? true,
|
|
49
|
+
modelFingerprint,
|
|
50
|
+
});
|
|
42
51
|
}
|
|
43
52
|
async classify(files, classifiers) {
|
|
44
53
|
const classifications = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-classifier.js","sourceRoot":"","sources":["../../src/llm/batch-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,MAAM,MAAM,SAAS,CAAC;AAG7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"batch-classifier.js","sourceRoot":"","sources":["../../src/llm/batch-classifier.ts"],"names":[],"mappings":"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"}
|