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.
- package/CHANGELOG.md +57 -0
- package/CODEBASE.md +2 -1
- package/bin/lib/cmd-demo.js +2 -2
- package/dist/cjs/cache.d.ts +4 -1
- package/dist/cjs/cache.d.ts.map +1 -1
- package/dist/cjs/cache.js +42 -20
- package/dist/cjs/cache.js.map +1 -1
- package/dist/cjs/engine.d.ts +3 -1
- package/dist/cjs/engine.d.ts.map +1 -1
- package/dist/cjs/engine.js +103 -34
- package/dist/cjs/engine.js.map +1 -1
- package/dist/cjs/generator.d.ts.map +1 -1
- package/dist/cjs/generator.js +16 -1
- package/dist/cjs/generator.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/learning.d.ts +20 -11
- package/dist/cjs/learning.d.ts.map +1 -1
- package/dist/cjs/learning.js +169 -135
- package/dist/cjs/learning.js.map +1 -1
- package/dist/cjs/matcher.d.ts +4 -1
- package/dist/cjs/matcher.d.ts.map +1 -1
- package/dist/cjs/matcher.js +33 -13
- package/dist/cjs/matcher.js.map +1 -1
- package/dist/cjs/parser.js +10 -4
- package/dist/cjs/parser.js.map +1 -1
- package/dist/cjs/resolver.d.ts +7 -0
- package/dist/cjs/resolver.d.ts.map +1 -1
- package/dist/cjs/resolver.js +63 -19
- package/dist/cjs/resolver.js.map +1 -1
- package/dist/cjs/schema.d.ts +106 -14
- package/dist/cjs/schema.d.ts.map +1 -1
- package/dist/cjs/schema.js +9 -4
- package/dist/cjs/schema.js.map +1 -1
- package/dist/cjs/types.d.ts +1 -0
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/cache.d.ts +4 -1
- package/dist/esm/cache.js +42 -20
- package/dist/esm/engine.d.ts +3 -1
- package/dist/esm/engine.js +104 -35
- package/dist/esm/generator.js +16 -1
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +1 -0
- package/dist/esm/learning.d.ts +20 -11
- package/dist/esm/learning.js +169 -135
- package/dist/esm/matcher.d.ts +4 -1
- package/dist/esm/matcher.js +31 -12
- package/dist/esm/parser.js +10 -4
- package/dist/esm/resolver.d.ts +7 -0
- package/dist/esm/resolver.js +63 -19
- package/dist/esm/schema.d.ts +106 -14
- package/dist/esm/schema.js +9 -4
- package/dist/esm/types.d.ts +1 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +1 -1
package/dist/cjs/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/types.d.ts
CHANGED
package/dist/cjs/types.d.ts.map
CHANGED
|
@@ -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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"}
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.5.
|
|
1
|
+
export declare const VERSION = "0.5.3";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/cjs/version.js
CHANGED
package/dist/esm/cache.d.ts
CHANGED
|
@@ -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
|
|
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.
|
|
69
|
+
this.loadPromise = null;
|
|
70
70
|
this.saveQueue = Promise.resolve();
|
|
71
|
-
|
|
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
|
-
|
|
75
|
-
if (this.
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
112
|
-
|
|
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.
|
|
120
|
-
logger.debug(`Cache
|
|
121
|
-
|
|
133
|
+
await this.save(); // eviction must be persisted
|
|
134
|
+
logger.debug(`Cache entry expired (file): "${key}"`);
|
|
135
|
+
return null;
|
|
122
136
|
}
|
|
123
|
-
|
|
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
|
}
|
package/dist/esm/engine.d.ts
CHANGED
|
@@ -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 './
|
|
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?;
|
package/dist/esm/engine.js
CHANGED
|
@@ -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 ??
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
72
|
-
|
|
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:
|
|
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,
|
|
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:
|
|
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
|
|
304
|
+
const extracted = Object.entries(matchResult.extractedParams)
|
|
265
305
|
.filter(([, v]) => v !== null)
|
|
266
306
|
.map(([k, v]) => `${k}=${v}`)
|
|
267
307
|
.join(', ');
|
|
268
|
-
|
|
269
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 >=
|
|
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((
|
|
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 =
|
|
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 =
|
|
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;
|
package/dist/esm/generator.js
CHANGED
|
@@ -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
|
-
` ${
|
|
56
|
+
` ${message}\n\n` +
|
|
42
57
|
`Check your config file for syntax errors.`);
|
|
43
58
|
}
|
|
44
59
|
// Catch invalid config structure
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -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
|
|
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';
|
package/dist/esm/learning.d.ts
CHANGED
|
@@ -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
|
|
41
|
+
private loadPromise;
|
|
36
42
|
private saveQueue;
|
|
37
|
-
private
|
|
38
|
-
private
|
|
43
|
+
private learningIndex;
|
|
44
|
+
private dirty;
|
|
45
|
+
private saveTimer;
|
|
39
46
|
constructor(filePath?: string);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
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
|
}
|