capman 0.5.1 → 0.5.3

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/CODEBASE.md +2 -1
  3. package/bin/lib/cmd-demo.js +2 -2
  4. package/dist/cjs/cache.d.ts +4 -1
  5. package/dist/cjs/cache.d.ts.map +1 -1
  6. package/dist/cjs/cache.js +42 -20
  7. package/dist/cjs/cache.js.map +1 -1
  8. package/dist/cjs/engine.d.ts +3 -1
  9. package/dist/cjs/engine.d.ts.map +1 -1
  10. package/dist/cjs/engine.js +103 -34
  11. package/dist/cjs/engine.js.map +1 -1
  12. package/dist/cjs/generator.d.ts.map +1 -1
  13. package/dist/cjs/generator.js +16 -1
  14. package/dist/cjs/generator.js.map +1 -1
  15. package/dist/cjs/index.d.ts +3 -2
  16. package/dist/cjs/index.d.ts.map +1 -1
  17. package/dist/cjs/index.js +3 -1
  18. package/dist/cjs/index.js.map +1 -1
  19. package/dist/cjs/learning.d.ts +20 -11
  20. package/dist/cjs/learning.d.ts.map +1 -1
  21. package/dist/cjs/learning.js +169 -135
  22. package/dist/cjs/learning.js.map +1 -1
  23. package/dist/cjs/matcher.d.ts +4 -1
  24. package/dist/cjs/matcher.d.ts.map +1 -1
  25. package/dist/cjs/matcher.js +33 -13
  26. package/dist/cjs/matcher.js.map +1 -1
  27. package/dist/cjs/parser.js +10 -4
  28. package/dist/cjs/parser.js.map +1 -1
  29. package/dist/cjs/resolver.d.ts +7 -0
  30. package/dist/cjs/resolver.d.ts.map +1 -1
  31. package/dist/cjs/resolver.js +63 -19
  32. package/dist/cjs/resolver.js.map +1 -1
  33. package/dist/cjs/schema.d.ts +106 -14
  34. package/dist/cjs/schema.d.ts.map +1 -1
  35. package/dist/cjs/schema.js +9 -4
  36. package/dist/cjs/schema.js.map +1 -1
  37. package/dist/cjs/types.d.ts +1 -0
  38. package/dist/cjs/types.d.ts.map +1 -1
  39. package/dist/cjs/version.d.ts +1 -1
  40. package/dist/cjs/version.js +1 -1
  41. package/dist/esm/cache.d.ts +4 -1
  42. package/dist/esm/cache.js +42 -20
  43. package/dist/esm/engine.d.ts +3 -1
  44. package/dist/esm/engine.js +104 -35
  45. package/dist/esm/generator.js +16 -1
  46. package/dist/esm/index.d.ts +3 -2
  47. package/dist/esm/index.js +1 -0
  48. package/dist/esm/learning.d.ts +20 -11
  49. package/dist/esm/learning.js +169 -135
  50. package/dist/esm/matcher.d.ts +4 -1
  51. package/dist/esm/matcher.js +31 -12
  52. package/dist/esm/parser.js +10 -4
  53. package/dist/esm/resolver.d.ts +7 -0
  54. package/dist/esm/resolver.js +63 -19
  55. package/dist/esm/schema.d.ts +106 -14
  56. package/dist/esm/schema.js +9 -4
  57. package/dist/esm/types.d.ts +1 -0
  58. package/dist/esm/version.d.ts +1 -1
  59. package/dist/esm/version.js +1 -1
  60. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"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"}
@@ -134,4 +134,5 @@ export interface ExplainResult {
134
134
  resolvedVia: 'keyword' | 'llm';
135
135
  durationMs: number;
136
136
  }
137
+ export type MatchMode = 'cheap' | 'balanced' | 'accurate';
137
138
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.5.1";
1
+ export declare const VERSION = "0.5.3";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // Auto-generated by scripts/version.js — do not edit manually
5
- exports.VERSION = '0.5.1';
5
+ exports.VERSION = '0.5.3';
6
6
  //# sourceMappingURL=version.js.map
@@ -29,10 +29,11 @@ export declare class MemoryCache implements CacheStore {
29
29
  export declare class FileCache implements CacheStore {
30
30
  private filePath;
31
31
  private store;
32
- private loaded;
32
+ private loadPromise;
33
33
  private saveQueue;
34
34
  constructor(filePath?: string);
35
35
  private load;
36
+ private _doLoad;
36
37
  private save;
37
38
  private _doSave;
38
39
  get(key: string, ttlMs?: number): Promise<CacheEntry | null>;
@@ -47,5 +48,7 @@ export declare class ComboCache implements CacheStore {
47
48
  get(key: string, ttlMs?: number): Promise<CacheEntry | null>;
48
49
  set(key: string, result: MatchResult): Promise<void>;
49
50
  clear(): Promise<void>;
51
+ /** Returns the file-side entry count, not total unique entries across both stores.
52
+ * Memory may have additional promoted entries not reflected here. */
50
53
  size(): Promise<number>;
51
54
  }
package/dist/esm/cache.js CHANGED
@@ -66,19 +66,37 @@ const FILE_CACHE_MAX = 2048;
66
66
  export class FileCache {
67
67
  constructor(filePath = '.capman/cache.json') {
68
68
  this.store = new Map();
69
- this.loaded = false;
69
+ this.loadPromise = null;
70
70
  this.saveQueue = Promise.resolve();
71
- this.filePath = path.resolve(process.cwd(), filePath);
71
+ const cwd = process.cwd();
72
+ const resolved = path.resolve(cwd, filePath);
73
+ const allowedPrefix = cwd === '/' ? '/' : cwd + path.sep;
74
+ if (!resolved.startsWith(allowedPrefix)) {
75
+ throw new Error(`FileCache path "${filePath}" resolves outside the working directory.\n` +
76
+ `Resolved: ${resolved}\nAllowed: ${cwd}`);
77
+ }
78
+ this.filePath = resolved;
72
79
  logger.info(`FileCache initialized — writing to: ${this.filePath}`);
73
80
  }
74
- async load() {
75
- if (this.loaded)
76
- return;
81
+ load() {
82
+ if (!this.loadPromise) {
83
+ this.loadPromise = this._doLoad();
84
+ }
85
+ return this.loadPromise;
86
+ }
87
+ async _doLoad() {
77
88
  try {
78
89
  const raw = await fs.promises.readFile(this.filePath, 'utf-8');
79
90
  const parsed = JSON.parse(raw);
80
91
  if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
81
- this.store = new Map(Object.entries(parsed));
92
+ // Normalize keys on load — prevents duplicate entries from older versions,
93
+ // manual edits, or any path that bypassed normalizeQuery() on write.
94
+ // e.g. "Show me articles" and "show me articles" collapse to the same key.
95
+ const normalized = new Map();
96
+ for (const [k, v] of Object.entries(parsed)) {
97
+ normalized.set(normalizeQuery(k), v);
98
+ }
99
+ this.store = normalized;
82
100
  logger.debug(`File cache loaded: ${this.store.size} entries`);
83
101
  }
84
102
  else {
@@ -88,7 +106,6 @@ export class FileCache {
88
106
  catch {
89
107
  // File doesn't exist yet — start fresh
90
108
  }
91
- this.loaded = true;
92
109
  }
93
110
  save() {
94
111
  this.saveQueue = this.saveQueue.then(() => this._doSave());
@@ -98,7 +115,9 @@ export class FileCache {
98
115
  try {
99
116
  const dir = path.dirname(this.filePath);
100
117
  await fs.promises.mkdir(dir, { recursive: true });
101
- await fs.promises.writeFile(this.filePath, JSON.stringify(Object.fromEntries(this.store), null, 2));
118
+ const tmp = `${this.filePath}.tmp`;
119
+ await fs.promises.writeFile(tmp, JSON.stringify(Object.fromEntries(this.store), null, 2));
120
+ await fs.promises.rename(tmp, this.filePath);
102
121
  }
103
122
  catch (err) {
104
123
  logger.warn(`Failed to save file cache to ${this.filePath}: ${err instanceof Error ? err.message : String(err)}`);
@@ -107,20 +126,21 @@ export class FileCache {
107
126
  async get(key, ttlMs) {
108
127
  await this.load();
109
128
  const entry = this.store.get(key);
110
- if (entry) {
111
- if (ttlMs && Date.now() - new Date(entry.cachedAt).getTime() > ttlMs) {
112
- this.store.delete(key);
113
- await this.save();
114
- logger.debug(`Cache entry expired (file): "${key}"`);
115
- return null;
116
- }
117
- entry.hits++;
129
+ if (!entry)
130
+ return null;
131
+ if (ttlMs && Date.now() - new Date(entry.cachedAt).getTime() > ttlMs) {
118
132
  this.store.delete(key);
119
- this.store.set(key, entry);
120
- logger.debug(`Cache hit (file): "${key}"`);
121
- await this.save();
133
+ await this.save(); // eviction must be persisted
134
+ logger.debug(`Cache entry expired (file): "${key}"`);
135
+ return null;
122
136
  }
123
- return entry ?? null;
137
+ entry.hits++;
138
+ this.store.delete(key); // reinsert at end for LRU ordering
139
+ this.store.set(key, entry);
140
+ // hits counter is in-memory only — not saved on read
141
+ // saves only happen on set() and eviction to avoid full file rewrite per request
142
+ logger.debug(`Cache hit (file): "${key}"`);
143
+ return entry;
124
144
  }
125
145
  async set(key, result) {
126
146
  await this.load();
@@ -178,6 +198,8 @@ export class ComboCache {
178
198
  this.file.clear(),
179
199
  ]);
180
200
  }
201
+ /** Returns the file-side entry count, not total unique entries across both stores.
202
+ * Memory may have additional promoted entries not reflected here. */
181
203
  async size() {
182
204
  return this.file.size();
183
205
  }
@@ -3,7 +3,7 @@ import type { LLMMatcherOptions } from './matcher';
3
3
  import type { ResolveOptions, AuthContext } from './resolver';
4
4
  import type { CacheStore } from './cache';
5
5
  import type { LearningStore } from './learning';
6
- import type { MatchMode } from './index';
6
+ import type { MatchMode } from './types';
7
7
  /**
8
8
  * Options for constructing a CapmanEngine instance.
9
9
  *
@@ -93,6 +93,8 @@ export interface EngineResult {
93
93
  trace: ExecutionTrace;
94
94
  }
95
95
  export declare class CapmanEngine {
96
+ /** Maximum allowed query length in characters. Queries exceeding this throw RangeError. */
97
+ static readonly MAX_QUERY_LENGTH = 1000;
96
98
  private manifest;
97
99
  private mode;
98
100
  private llm?;
@@ -1,4 +1,4 @@
1
- import { match as _match, matchWithLLM as _matchWithLLM, resolverToIntent, extractParams, STOPWORDS } from './matcher';
1
+ import { match as _match, matchWithLLM as _matchWithLLM, resolverToIntent, extractParams, STOPWORDS, LLMParseError } from './matcher';
2
2
  import { resolve as _resolve } from './resolver';
3
3
  import { MemoryLearningStore } from './learning';
4
4
  import { logger } from './logger';
@@ -24,7 +24,7 @@ export class CapmanEngine {
24
24
  this.maxLLMCallsPerMinute = options.maxLLMCallsPerMinute ?? 60;
25
25
  this.llmCooldownMs = options.llmCooldownMs ?? 0;
26
26
  this.llmCircuitBreakerThreshold = options.llmCircuitBreakerThreshold ?? 3;
27
- this.llmCircuitBreakerResetMs = options.llmCircuitBreakerResetMs ?? 60000;
27
+ this.llmCircuitBreakerResetMs = options.llmCircuitBreakerResetMs ?? 60_000;
28
28
  // Cache — default MemoryCache (no filesystem writes), or disabled with false
29
29
  // Use FileCache or ComboCache explicitly for persistence across restarts
30
30
  this.cache = options.cache === false
@@ -37,14 +37,22 @@ export class CapmanEngine {
37
37
  : (options.learning ?? new MemoryLearningStore());
38
38
  logger.info(`CapmanEngine initialized — mode: ${this.mode}, cache: ${this.cache ? 'enabled' : 'disabled'}, learning: ${this.learning ? 'enabled' : 'disabled'}`);
39
39
  // ── Manifest version compatibility check ─────────────────────────────────
40
- const manifestMajorMinor = options.manifest.version?.split('.').slice(0, 2).join('.');
41
- const engineMajorMinor = VERSION.split('.').slice(0, 2).join('.');
42
- if (manifestMajorMinor && manifestMajorMinor !== engineMajorMinor) {
43
- // Use console.warn directly — must be visible regardless of logger level
44
- // Default log level is 'silent' so logger.warn would never be seen
45
- console.warn(`[capman] Manifest version "${options.manifest.version}" was generated with a ` +
46
- `different engine version than "${VERSION}". If you experience matching issues, ` +
47
- `regenerate with: npx capman generate`);
40
+ if (options.manifest.version) {
41
+ const SEMVER_RE = /^\d+\.\d+\.\d+$/;
42
+ if (SEMVER_RE.test(options.manifest.version) && SEMVER_RE.test(VERSION)) {
43
+ const [mMaj, mMin] = options.manifest.version.split('.').map(Number);
44
+ const [eMaj, eMin] = VERSION.split('.').map(Number);
45
+ if (mMaj !== eMaj || mMin !== eMin) {
46
+ console.warn(`[capman] Manifest version "${options.manifest.version}" was generated with a ` +
47
+ `different engine version than "${VERSION}". This is usually fine across patch versions. ` +
48
+ `If you experience unexpected matching issues, regenerate with: npx capman generate`);
49
+ }
50
+ }
51
+ else if (options.manifest.version !== VERSION) {
52
+ //console.warn is used instead of logger.warn to avoid the warning being logged to the console
53
+ console.warn(`[capman] Manifest version "${options.manifest.version}" could not be compared ` +
54
+ `to engine version "${VERSION}" — version strings are not valid semver.`);
55
+ }
48
56
  }
49
57
  }
50
58
  /**
@@ -59,6 +67,12 @@ export class CapmanEngine {
59
67
  * console.log(result.resolvedVia) // 'keyword' | 'llm' | 'cache'
60
68
  */
61
69
  async ask(query, overrides = {}) {
70
+ if (!query || typeof query !== 'string') {
71
+ throw new TypeError('query must be a non-empty string');
72
+ }
73
+ if (query.length > CapmanEngine.MAX_QUERY_LENGTH) {
74
+ throw new RangeError(`query exceeds maximum length of ${CapmanEngine.MAX_QUERY_LENGTH} characters`);
75
+ }
62
76
  const start = Date.now();
63
77
  const steps = [];
64
78
  // ── Step 1: Check cache ──────────────────────────────────────────────────
@@ -68,8 +82,20 @@ export class CapmanEngine {
68
82
  const cached = await this.cache.get(queryKey, this.cacheTtlMs ?? undefined);
69
83
  if (cached) {
70
84
  steps.push({ type: 'cache_check', status: 'hit', durationMs: Date.now() - cacheStart, detail: 'Served from cache' });
71
- logger.info(`Cache hit for: "${query}"`);
72
- const resolution = await _resolve(cached.result, cached.result.extractedParams, this.resolveOptions(overrides));
85
+ logger.info(`Cache hit — capability: "${cached.result.capability?.id ?? 'none'}"`);
86
+ logger.debug(`Cache hit for query: "${query}"`);
87
+ // Re-extract params from the current query — never re-use cached params.
88
+ // Cached params belong to the original query (potentially from a different user).
89
+ // e.g. User A: "show orders for john" → cached with { customer: 'john' }
90
+ // User B: "show orders for jane" → must get { customer: 'jane' }, not john's
91
+ const freshParams = cached.result.capability
92
+ ? extractParams(query, cached.result.capability)
93
+ : {};
94
+ const matchWithFreshParams = {
95
+ ...cached.result,
96
+ extractedParams: freshParams,
97
+ };
98
+ const resolution = await _resolve(matchWithFreshParams, freshParams, this.resolveOptions(overrides));
73
99
  const trace = {
74
100
  query,
75
101
  candidates: cached.result.candidates,
@@ -79,13 +105,13 @@ export class CapmanEngine {
79
105
  totalMs: Date.now() - start,
80
106
  };
81
107
  const result = {
82
- match: cached.result,
108
+ match: matchWithFreshParams,
83
109
  resolution,
84
110
  resolvedVia: 'cache',
85
111
  durationMs: Date.now() - start,
86
112
  trace,
87
113
  };
88
- await this.recordLearning(query, cached.result, 'cache');
114
+ await this.recordLearning(query, matchWithFreshParams, 'cache');
89
115
  return result;
90
116
  }
91
117
  steps.push({ type: 'cache_check', status: 'miss', durationMs: Date.now() - cacheStart });
@@ -108,15 +134,7 @@ export class CapmanEngine {
108
134
  detail: `level: ${privacyLevel}`,
109
135
  });
110
136
  }
111
- // ── Step 4: Cache the match result (public capabilities only) ─────────────
112
- // Non-public capabilities are never cached — prevents auth bypass where
113
- // User A's cached match is served to User B without privacy enforcement.
114
- if (this.cache && matchResult.capability
115
- && matchResult.capability.privacy.level === 'public') {
116
- const queryKey = normalizeQuery(query);
117
- await this.cache.set(queryKey, matchResult);
118
- }
119
- // ── Step 5: Resolve ──────────────────────────────────────────────────────
137
+ // ── Step 4: Resolve ──────────────────────────────────────────────────────
120
138
  const resolveStart = Date.now();
121
139
  const resolution = await _resolve(matchResult, matchResult.extractedParams, this.resolveOptions(overrides));
122
140
  steps.push({
@@ -125,6 +143,16 @@ export class CapmanEngine {
125
143
  durationMs: Date.now() - resolveStart,
126
144
  detail: resolution.error ?? `via ${resolution.resolverType}`,
127
145
  });
146
+ // ── Step 5: Cache after successful resolution ────────────────────────────
147
+ // Only cache when resolution succeeded — a failed resolution (network error,
148
+ // auth failure, bad params) must not poison the cache. A cached failed match
149
+ // would cause every subsequent cache hit to attempt the same failing resolution
150
+ // until TTL expires.
151
+ if (this.cache && resolution.success && matchResult.capability
152
+ && matchResult.capability.privacy.level === 'public') {
153
+ const queryKey = normalizeQuery(query);
154
+ await this.cache.set(queryKey, matchResult);
155
+ }
128
156
  // ── Step 6: Build reasoning array ────────────────────────────────────────
129
157
  const reasoning = [];
130
158
  if (matchResult.candidates.length) {
@@ -213,9 +241,21 @@ export class CapmanEngine {
213
241
  * console.log(explanation.candidates)
214
242
  */
215
243
  async explain(query) {
244
+ if (!query || typeof query !== 'string') {
245
+ throw new TypeError('query must be a non-empty string');
246
+ }
247
+ if (query.length > CapmanEngine.MAX_QUERY_LENGTH) {
248
+ throw new RangeError(`query exceeds maximum length of ${CapmanEngine.MAX_QUERY_LENGTH} characters`);
249
+ }
216
250
  const start = Date.now();
217
251
  // ── Match — shared with ask() via _runMatch() ─────────────────────────────
218
252
  let { matchResult, resolvedVia: _resolvedVia } = await this._runMatch(query);
253
+ // explain() never reads from cache — it always runs a fresh match.
254
+ // This assertion catches any future refactor that accidentally adds
255
+ // cache reads to _runMatch() when called from explain().
256
+ if (_resolvedVia === 'cache') {
257
+ throw new Error('Invariant violation: explain() must never resolve via cache');
258
+ }
219
259
  let resolvedVia = _resolvedVia;
220
260
  // ── Apply learning boost (same as ask()) ─────────────────────────────────
221
261
  matchResult = await this.applyBoostToMatchResult(query, matchResult);
@@ -261,12 +301,17 @@ export class CapmanEngine {
261
301
  }
262
302
  reasoning.push(`Resolved via: ${resolvedVia}`);
263
303
  if (matchResult.extractedParams && Object.keys(matchResult.extractedParams).length) {
264
- const params = Object.entries(matchResult.extractedParams)
304
+ const extracted = Object.entries(matchResult.extractedParams)
265
305
  .filter(([, v]) => v !== null)
266
306
  .map(([k, v]) => `${k}=${v}`)
267
307
  .join(', ');
268
- if (params)
269
- reasoning.push(`Would extract params: ${params}`);
308
+ const session = matchResult.capability?.params
309
+ .filter(p => p.source === 'session')
310
+ .map(p => `${p.name}=[from auth]`)
311
+ .join(', ');
312
+ const parts = [extracted, session].filter(Boolean).join(', ');
313
+ if (parts)
314
+ reasoning.push(`Would extract params: ${parts}`);
270
315
  }
271
316
  // ── Build wouldExecute ───────────────────────────────────────────────────
272
317
  const cap = matchResult.capability;
@@ -299,7 +344,7 @@ export class CapmanEngine {
299
344
  let path = endpoint.path;
300
345
  for (const [k, v] of Object.entries(params)) {
301
346
  if (v)
302
- path = path.replace(`{${k}}`, v);
347
+ path = path.replaceAll(`{${k}}`, v);
303
348
  }
304
349
  const base = this.baseUrl ?? '';
305
350
  action = `${endpoint.method} ${base}${path}`;
@@ -308,7 +353,7 @@ export class CapmanEngine {
308
353
  let dest = cap.resolver.destination;
309
354
  for (const [k, v] of Object.entries(params)) {
310
355
  if (v)
311
- dest = dest.replace(`{${k}}`, v);
356
+ dest = dest.replaceAll(`{${k}}`, v);
312
357
  }
313
358
  action = `navigate → ${dest}`;
314
359
  }
@@ -318,12 +363,12 @@ export class CapmanEngine {
318
363
  let path = endpoint.path;
319
364
  for (const [k, v] of Object.entries(params)) {
320
365
  if (v)
321
- path = path.replace(`{${k}}`, v);
366
+ path = path.replaceAll(`{${k}}`, v);
322
367
  }
323
368
  let dest = hybrid.nav.destination;
324
369
  for (const [k, v] of Object.entries(params)) {
325
370
  if (v)
326
- dest = dest.replace(`{${k}}`, v);
371
+ dest = dest.replaceAll(`{${k}}`, v);
327
372
  }
328
373
  const base = this.baseUrl ?? '';
329
374
  action = `${endpoint.method} ${base}${path} + navigate → ${dest}`;
@@ -372,13 +417,13 @@ export class CapmanEngine {
372
417
  }
373
418
  // ── Per-minute rate limit ────────────────────────────────────────────────
374
419
  const windowElapsed = now - this.llmWindowStart;
375
- if (windowElapsed >= 60000) {
420
+ if (windowElapsed >= 60_000) {
376
421
  this.llmCallsThisMinute = 0;
377
422
  this.llmWindowStart = now;
378
423
  }
379
424
  if (this.llmCallsThisMinute >= this.maxLLMCallsPerMinute) {
380
425
  // Recalculate elapsed after possible window reset above
381
- const resetIn = Math.ceil((60000 - (now - this.llmWindowStart)) / 1000);
426
+ const resetIn = Math.ceil((60_000 - (now - this.llmWindowStart)) / 1000);
382
427
  return `rate limit reached (${this.maxLLMCallsPerMinute}/min) — resets in ${Math.max(0, resetIn)}s`;
383
428
  }
384
429
  // Reserve the slot atomically before the call happens
@@ -432,10 +477,21 @@ export class CapmanEngine {
432
477
  matchResult = await _matchWithLLM(query, this.manifest, { llm: this.llm });
433
478
  this.recordLLMSuccess();
434
479
  resolvedVia = 'llm';
480
+ // Merge keyword scores into LLM candidates so boost has real signal for alternatives
481
+ const kwResult = _match(query, this.manifest);
482
+ matchResult = {
483
+ ...matchResult,
484
+ candidates: matchResult.candidates.map(c => ({
485
+ ...c,
486
+ score: c.matched
487
+ ? c.score // keep LLM confidence for winner
488
+ : (kwResult.candidates.find(kc => kc.capabilityId === c.capabilityId)?.score ?? 0),
489
+ })),
490
+ };
435
491
  steps?.push({ type: 'llm_match', status: 'pass', durationMs: Date.now() - t, detail: `confidence: ${matchResult.confidence}%` });
436
492
  }
437
493
  catch (err) {
438
- const isParseError = String(err).startsWith('LLM_PARSE_ERROR');
494
+ const isParseError = err instanceof LLMParseError;
439
495
  if (!isParseError)
440
496
  this.recordLLMFailure();
441
497
  logger.warn(`LLM call failed — falling back to keyword: ${err instanceof Error ? err.message : String(err)}`);
@@ -470,16 +526,27 @@ export class CapmanEngine {
470
526
  matchResult = keywordResult;
471
527
  }
472
528
  else {
473
- logger.info(`Low confidence (${keywordResult.confidence}%) — escalating to LLM`);
529
+ logger.info(`Low keyword confidence (${keywordResult.confidence}%) — escalating to LLM`);
530
+ logger.debug(`Query escalated to LLM: "${query}"`);
474
531
  const t2 = Date.now();
475
532
  try {
476
533
  matchResult = await _matchWithLLM(query, this.manifest, { llm: this.llm });
477
534
  this.recordLLMSuccess();
478
535
  resolvedVia = 'llm';
536
+ // keywordResult already computed above in balanced mode — merge scores
537
+ matchResult = {
538
+ ...matchResult,
539
+ candidates: matchResult.candidates.map(c => ({
540
+ ...c,
541
+ score: c.matched
542
+ ? c.score
543
+ : (keywordResult.candidates.find(kc => kc.capabilityId === c.capabilityId)?.score ?? 0),
544
+ })),
545
+ };
479
546
  steps?.push({ type: 'llm_match', status: 'pass', durationMs: Date.now() - t2, detail: `confidence: ${matchResult.confidence}%` });
480
547
  }
481
548
  catch (err) {
482
- const isParseError = String(err).startsWith('LLM_PARSE_ERROR');
549
+ const isParseError = err instanceof LLMParseError;
483
550
  if (!isParseError)
484
551
  this.recordLLMFailure();
485
552
  logger.warn(`LLM call failed — falling back to keyword: ${err instanceof Error ? err.message : String(err)}`);
@@ -594,3 +661,5 @@ export class CapmanEngine {
594
661
  });
595
662
  }
596
663
  }
664
+ /** Maximum allowed query length in characters. Queries exceeding this throw RangeError. */
665
+ CapmanEngine.MAX_QUERY_LENGTH = 1000;
@@ -37,8 +37,23 @@ export function loadConfig(configPath) {
37
37
  raw = mod.default ?? mod;
38
38
  }
39
39
  catch (err) {
40
+ const code = err.code;
41
+ const message = err instanceof Error ? err.message : String(err);
42
+ // ERR_REQUIRE_ESM — file is an ES module (Node v12–v21)
43
+ // On Node v22+, the error message changed but code remains ERR_REQUIRE_ESM
44
+ // for .mjs files; .js files in ESM packages may show a different message.
45
+ const isESM = code === 'ERR_REQUIRE_ESM' ||
46
+ message.includes('require() of ES Module') ||
47
+ message.includes('must use import to load ES Module');
48
+ if (isESM) {
49
+ throw new Error(`Config file "${resolved}" is an ES module but capman requires CommonJS.\n` +
50
+ `Solutions:\n` +
51
+ ` 1. Rename to capman.config.cjs\n` +
52
+ ` 2. Change to: module.exports = { ... }\n` +
53
+ ` 3. Remove "type": "module" from your package.json`);
54
+ }
40
55
  throw new Error(`Failed to load config at ${resolved}:\n` +
41
- ` ${err instanceof Error ? err.message : String(err)}\n\n` +
56
+ ` ${message}\n\n` +
42
57
  `Check your config file for syntax errors.`);
43
58
  }
44
59
  // Catch invalid config structure
@@ -3,6 +3,7 @@ export type { LogLevel } from './logger';
3
3
  export type { Capability, CapabilityParam, CapmanConfig, Manifest, MatchResult, ExecutionTrace, TraceStep, MatchCandidate, ResolveResult, ApiCallResult, ValidationResult, Resolver, ApiResolver, NavResolver, HybridResolver, PrivacyScope, ResolverType, HttpMethod, ExplainResult, ExplainCandidate, } from './types';
4
4
  export { generate, loadConfig, writeManifest, readManifest, validate, generateStarterConfig, } from './generator';
5
5
  export { match, matchWithLLM, extractParams, } from './matcher';
6
+ export { LLMParseError } from './matcher';
6
7
  export type { LLMMatcherOptions } from './matcher';
7
8
  export { resolve } from './resolver';
8
9
  export type { ResolveOptions, AuthContext } from './resolver';
@@ -14,10 +15,10 @@ export { FileLearningStore, MemoryLearningStore } from './learning';
14
15
  export type { LearningStore, LearningEntry, KeywordStats } from './learning';
15
16
  export { parseOpenAPI } from './parser';
16
17
  export type { ParseResult } from './parser';
17
- import type { Manifest, MatchResult, ResolveResult } from './types';
18
+ import type { Manifest, MatchResult, ResolveResult, MatchMode } from './types';
18
19
  import type { LLMMatcherOptions } from './matcher';
19
20
  import type { ResolveOptions } from './resolver';
20
- export type MatchMode = 'cheap' | 'balanced' | 'accurate';
21
+ export type { MatchMode } from './types';
21
22
  export interface AskOptions extends ResolveOptions {
22
23
  llm?: LLMMatcherOptions['llm'];
23
24
  /**
package/dist/esm/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { setLogLevel } from './logger';
2
2
  export { generate, loadConfig, writeManifest, readManifest, validate, generateStarterConfig, } from './generator';
3
3
  export { match, matchWithLLM, extractParams, } from './matcher';
4
+ export { LLMParseError } from './matcher';
4
5
  export { resolve } from './resolver';
5
6
  // ─── Engine (recommended API) ─────────────────────────────────────────────────
6
7
  export { CapmanEngine } from './engine';
@@ -28,19 +28,31 @@ export interface LearningStore {
28
28
  }>>;
29
29
  /** Returns the live keyword index without rebuilding — O(1) */
30
30
  getIndex(): Promise<Record<string, Record<string, number>>>;
31
+ /**
32
+ * Removes this store from the exit flush registry and flushes any pending data.
33
+ * Call when the store is no longer needed to prevent memory leaks.
34
+ * Must be awaited — final flush is async.
35
+ */
36
+ destroy(): Promise<void>;
31
37
  }
32
38
  export declare class FileLearningStore implements LearningStore {
33
39
  private filePath;
34
40
  private entries;
35
- private loaded;
41
+ private loadPromise;
36
42
  private saveQueue;
37
- private index;
38
- private statsCounter;
43
+ private learningIndex;
44
+ private dirty;
45
+ private saveTimer;
39
46
  constructor(filePath?: string);
40
- private updateIndex;
41
- private subtractFromIndex;
42
- private rebuildIndex;
47
+ flushSync(): void;
48
+ /**
49
+ * Removes this store from the exit flush registry and cancels any pending save timer.
50
+ * Call when the store is no longer needed to prevent memory leaks in long-running servers.
51
+ */
52
+ destroy(): Promise<void>;
43
53
  private load;
54
+ private _doLoad;
55
+ private scheduleSave;
44
56
  private save;
45
57
  private _doSave;
46
58
  record(entry: LearningEntry): Promise<void>;
@@ -54,17 +66,14 @@ export declare class FileLearningStore implements LearningStore {
54
66
  }
55
67
  export declare class MemoryLearningStore implements LearningStore {
56
68
  private entries;
57
- private index;
58
- private statsCounter;
69
+ private learningIndex;
59
70
  record(entry: LearningEntry): Promise<void>;
60
71
  getStats(): Promise<KeywordStats>;
61
72
  getIndex(): Promise<Record<string, Record<string, number>>>;
62
- private updateIndex;
63
- private subtractFromIndex;
64
- private rebuildIndex;
65
73
  getTopCapabilities(limit?: number): Promise<Array<{
66
74
  id: string;
67
75
  hits: number;
68
76
  }>>;
69
77
  clear(): Promise<void>;
78
+ destroy(): Promise<void>;
70
79
  }