capman 0.5.2 → 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 +28 -0
- package/CODEBASE.md +2 -1
- package/dist/cjs/cache.d.ts +2 -1
- package/dist/cjs/cache.d.ts.map +1 -1
- package/dist/cjs/cache.js +11 -6
- package/dist/cjs/cache.js.map +1 -1
- package/dist/cjs/engine.d.ts.map +1 -1
- package/dist/cjs/engine.js +35 -17
- 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/learning.d.ts +20 -10
- package/dist/cjs/learning.d.ts.map +1 -1
- package/dist/cjs/learning.js +146 -129
- package/dist/cjs/learning.js.map +1 -1
- package/dist/cjs/matcher.d.ts.map +1 -1
- package/dist/cjs/matcher.js +2 -1
- package/dist/cjs/matcher.js.map +1 -1
- package/dist/cjs/parser.js +8 -2
- 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 +47 -23
- package/dist/cjs/resolver.js.map +1 -1
- package/dist/cjs/schema.d.ts +93 -1
- package/dist/cjs/schema.d.ts.map +1 -1
- package/dist/cjs/schema.js +5 -2
- package/dist/cjs/schema.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/cache.d.ts +2 -1
- package/dist/esm/cache.js +11 -6
- package/dist/esm/engine.js +35 -17
- package/dist/esm/generator.js +16 -1
- package/dist/esm/learning.d.ts +20 -10
- package/dist/esm/learning.js +146 -129
- package/dist/esm/matcher.js +2 -1
- package/dist/esm/parser.js +8 -2
- package/dist/esm/resolver.d.ts +7 -0
- package/dist/esm/resolver.js +47 -23
- package/dist/esm/schema.d.ts +93 -1
- package/dist/esm/schema.js +5 -2
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +1 -1
package/dist/cjs/resolver.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolve = resolve;
|
|
4
4
|
const logger_1 = require("./logger");
|
|
5
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
6
|
+
const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
|
|
5
7
|
function redactParams(params) {
|
|
6
8
|
return Object.fromEntries(Object.entries(params).map(([k, v]) => [k, v != null ? '[REDACTED]' : 'null']));
|
|
7
9
|
}
|
|
@@ -52,12 +54,8 @@ async function resolve(matchResult, params = {}, options = {}) {
|
|
|
52
54
|
// they must never leak into the query string as ?user_id=xyz
|
|
53
55
|
const enrichedParams = { ...params };
|
|
54
56
|
if (options.auth?.userId !== undefined && options.auth.userId !== '') {
|
|
55
|
-
const resolver = capability.resolver;
|
|
56
|
-
const pathTemplate = resolver.type === 'api' ? resolver.endpoints.map(e => e.path).join('') :
|
|
57
|
-
resolver.type === 'hybrid' ? resolver.api.endpoints.map(e => e.path).join('') :
|
|
58
|
-
resolver.type === 'nav' ? resolver.destination : '';
|
|
59
57
|
for (const param of capability.params) {
|
|
60
|
-
if (param.source === 'session'
|
|
58
|
+
if (param.source === 'session') {
|
|
61
59
|
enrichedParams[param.name] = options.auth.userId;
|
|
62
60
|
logger_1.logger.debug(`Injected session param "${param.name}" (value redacted)`);
|
|
63
61
|
}
|
|
@@ -68,15 +66,18 @@ async function resolve(matchResult, params = {}, options = {}) {
|
|
|
68
66
|
logger_1.logger.debug(`Params: ${JSON.stringify(redactParams(params))}`);
|
|
69
67
|
logger_1.logger.debug(`Options: baseUrl=${options.baseUrl} dryRun=${options.dryRun}`);
|
|
70
68
|
try {
|
|
69
|
+
const sessionParamNames = new Set(capability.params
|
|
70
|
+
.filter(p => p.source === 'session')
|
|
71
|
+
.map(p => p.name));
|
|
71
72
|
switch (resolver.type) {
|
|
72
73
|
case 'api':
|
|
73
|
-
return await resolveApi(resolver, enrichedParams, options);
|
|
74
|
+
return await resolveApi(resolver, enrichedParams, options, sessionParamNames);
|
|
74
75
|
case 'nav':
|
|
75
76
|
return resolveNav(resolver, enrichedParams);
|
|
76
77
|
case 'hybrid': {
|
|
77
78
|
logger_1.logger.debug('Hybrid resolver — running API and nav in parallel');
|
|
78
79
|
const [apiResult, navResult] = await Promise.all([
|
|
79
|
-
resolveApi(resolver.api, enrichedParams, options),
|
|
80
|
+
resolveApi(resolver.api, enrichedParams, options, sessionParamNames),
|
|
80
81
|
Promise.resolve(resolveNav(resolver.nav, enrichedParams)),
|
|
81
82
|
]);
|
|
82
83
|
return {
|
|
@@ -112,15 +113,26 @@ async function resolve(matchResult, params = {}, options = {}) {
|
|
|
112
113
|
* For capabilities where ordering or rollback matters, define separate capabilities
|
|
113
114
|
* with single endpoints and orchestrate them at the application layer.
|
|
114
115
|
*/
|
|
115
|
-
async function resolveApi(resolver, params, options) {
|
|
116
|
+
async function resolveApi(resolver, params, options, sessionParamNames = new Set()) {
|
|
116
117
|
const startTime = Date.now();
|
|
117
118
|
const retries = options.retries ?? 0;
|
|
118
119
|
const timeoutMs = options.timeoutMs ?? 5000;
|
|
119
|
-
const apiCalls = resolver.endpoints.map(endpoint =>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
const apiCalls = resolver.endpoints.map(endpoint => {
|
|
121
|
+
// Build per-endpoint params — only inject session params if this
|
|
122
|
+
// specific endpoint has the placeholder. Prevents userId leaking
|
|
123
|
+
// as ?user_id=xyz on endpoints that don't use it in their path.
|
|
124
|
+
const endpointParams = { ...params };
|
|
125
|
+
for (const name of sessionParamNames) {
|
|
126
|
+
if (!endpoint.path.includes(`{${name}}`)) {
|
|
127
|
+
delete endpointParams[name]; // strip session param — not in this endpoint's path
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
method: endpoint.method,
|
|
132
|
+
url: buildUrl(options.baseUrl ?? '', endpoint.path, endpointParams),
|
|
133
|
+
params: Object.fromEntries(Object.entries(endpointParams).filter(([, v]) => v !== null && v !== undefined)),
|
|
134
|
+
};
|
|
135
|
+
});
|
|
124
136
|
if (options.dryRun) {
|
|
125
137
|
return { success: true, resolverType: 'api', apiCalls, durationMs: Date.now() - startTime };
|
|
126
138
|
}
|
|
@@ -133,9 +145,14 @@ async function resolveApi(resolver, params, options) {
|
|
|
133
145
|
};
|
|
134
146
|
}
|
|
135
147
|
// ── Fetch with retry + timeout (iterative — no recursion) ────────────────
|
|
148
|
+
// Only retry safe/idempotent methods — retrying POST/PUT/PATCH/DELETE
|
|
149
|
+
// can cause duplicate side effects (e.g. duplicate orders, double charges).
|
|
136
150
|
async function fetchWithRetry(call) {
|
|
151
|
+
const effectiveRetries = (options.retryAllMethods || SAFE_METHODS.has(call.method))
|
|
152
|
+
? retries
|
|
153
|
+
: 0;
|
|
137
154
|
let lastErr;
|
|
138
|
-
for (let attempt = 0; attempt <=
|
|
155
|
+
for (let attempt = 0; attempt <= effectiveRetries; attempt++) {
|
|
139
156
|
const controller = new AbortController();
|
|
140
157
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
141
158
|
try {
|
|
@@ -154,8 +171,8 @@ async function resolveApi(resolver, params, options) {
|
|
|
154
171
|
clearTimeout(timer);
|
|
155
172
|
lastErr = err;
|
|
156
173
|
const isTimeout = err instanceof Error && err.name === 'AbortError';
|
|
157
|
-
if (attempt <
|
|
158
|
-
logger_1.logger.warn(`Request failed (attempt ${attempt + 1}/${
|
|
174
|
+
if (attempt < effectiveRetries) {
|
|
175
|
+
logger_1.logger.warn(`Request failed (attempt ${attempt + 1}/${effectiveRetries + 1}) — retrying: ${isTimeout ? 'timeout' : err}`);
|
|
159
176
|
}
|
|
160
177
|
else {
|
|
161
178
|
throw isTimeout ? new Error(`Request timed out after ${timeoutMs}ms`) : err;
|
|
@@ -212,12 +229,17 @@ function resolveNav(resolver, params) {
|
|
|
212
229
|
}
|
|
213
230
|
return { success: true, resolverType: 'nav', navTarget: destination };
|
|
214
231
|
}
|
|
215
|
-
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
|
|
220
|
-
|
|
232
|
+
function validateApiPathParam(key, value) {
|
|
233
|
+
// Prevent path traversal via unencoded slashes — encodeURIComponent does not
|
|
234
|
+
// encode '/' so a value like '../../admin' would traverse the path hierarchy.
|
|
235
|
+
// This mirrors the allowlist validation already applied in resolveNav().
|
|
236
|
+
if (!/^[a-zA-Z0-9_\-.:@]+$/.test(value)) {
|
|
237
|
+
throw new Error(`API path param "${key}" contains invalid characters: "${value}". ` +
|
|
238
|
+
`Only alphanumeric, hyphens, underscores, dots, colons, and @ are allowed.`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Both buildUrl (API) and resolveNav (nav) validate path param values against
|
|
242
|
+
// an allowlist before substitution — prevents path traversal via unencoded slashes.
|
|
221
243
|
function buildUrl(baseUrl, urlPath, params) {
|
|
222
244
|
let resolved = urlPath;
|
|
223
245
|
const unused = {};
|
|
@@ -225,7 +247,9 @@ function buildUrl(baseUrl, urlPath, params) {
|
|
|
225
247
|
if (value === null || value === undefined)
|
|
226
248
|
continue; // never write null into URLs
|
|
227
249
|
if (resolved.includes(`{${key}}`)) {
|
|
228
|
-
|
|
250
|
+
const str = String(value);
|
|
251
|
+
validateApiPathParam(key, str);
|
|
252
|
+
resolved = resolved.replaceAll(`{${key}}`, encodeURIComponent(str));
|
|
229
253
|
}
|
|
230
254
|
else {
|
|
231
255
|
unused[key] = value;
|
package/dist/cjs/resolver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/schema.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export declare const CapmanConfigSchema: z.ZodObject<{
|
|
2
|
+
export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
3
3
|
app: z.ZodString;
|
|
4
4
|
baseUrl: z.ZodOptional<z.ZodString>;
|
|
5
5
|
capabilities: z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
@@ -405,6 +405,98 @@ export declare const CapmanConfigSchema: z.ZodObject<{
|
|
|
405
405
|
examples?: string[] | undefined;
|
|
406
406
|
}[];
|
|
407
407
|
baseUrl?: string | undefined;
|
|
408
|
+
}>, {
|
|
409
|
+
app: string;
|
|
410
|
+
capabilities: {
|
|
411
|
+
name: string;
|
|
412
|
+
id: string;
|
|
413
|
+
params: {
|
|
414
|
+
name: string;
|
|
415
|
+
required: boolean;
|
|
416
|
+
description: string;
|
|
417
|
+
source: "user_query" | "session" | "context" | "static";
|
|
418
|
+
default?: string | number | boolean | undefined;
|
|
419
|
+
}[];
|
|
420
|
+
description: string;
|
|
421
|
+
returns: string[];
|
|
422
|
+
resolver: {
|
|
423
|
+
type: "api";
|
|
424
|
+
endpoints: {
|
|
425
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
426
|
+
path: string;
|
|
427
|
+
params?: string[] | undefined;
|
|
428
|
+
}[];
|
|
429
|
+
} | {
|
|
430
|
+
type: "nav";
|
|
431
|
+
destination: string;
|
|
432
|
+
hint?: string | undefined;
|
|
433
|
+
} | {
|
|
434
|
+
type: "hybrid";
|
|
435
|
+
api: {
|
|
436
|
+
endpoints: {
|
|
437
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
438
|
+
path: string;
|
|
439
|
+
params?: string[] | undefined;
|
|
440
|
+
}[];
|
|
441
|
+
};
|
|
442
|
+
nav: {
|
|
443
|
+
destination: string;
|
|
444
|
+
hint?: string | undefined;
|
|
445
|
+
};
|
|
446
|
+
};
|
|
447
|
+
privacy: {
|
|
448
|
+
level: "public" | "user_owned" | "admin";
|
|
449
|
+
note?: string | undefined;
|
|
450
|
+
};
|
|
451
|
+
examples?: string[] | undefined;
|
|
452
|
+
}[];
|
|
453
|
+
baseUrl?: string | undefined;
|
|
454
|
+
}, {
|
|
455
|
+
app: string;
|
|
456
|
+
capabilities: {
|
|
457
|
+
name: string;
|
|
458
|
+
id: string;
|
|
459
|
+
params: {
|
|
460
|
+
name: string;
|
|
461
|
+
required: boolean;
|
|
462
|
+
description: string;
|
|
463
|
+
source: "user_query" | "session" | "context" | "static";
|
|
464
|
+
default?: string | number | boolean | undefined;
|
|
465
|
+
}[];
|
|
466
|
+
description: string;
|
|
467
|
+
returns: string[];
|
|
468
|
+
resolver: {
|
|
469
|
+
type: "api";
|
|
470
|
+
endpoints: {
|
|
471
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
472
|
+
path: string;
|
|
473
|
+
params?: string[] | undefined;
|
|
474
|
+
}[];
|
|
475
|
+
} | {
|
|
476
|
+
type: "nav";
|
|
477
|
+
destination: string;
|
|
478
|
+
hint?: string | undefined;
|
|
479
|
+
} | {
|
|
480
|
+
type: "hybrid";
|
|
481
|
+
api: {
|
|
482
|
+
endpoints: {
|
|
483
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
484
|
+
path: string;
|
|
485
|
+
params?: string[] | undefined;
|
|
486
|
+
}[];
|
|
487
|
+
};
|
|
488
|
+
nav: {
|
|
489
|
+
destination: string;
|
|
490
|
+
hint?: string | undefined;
|
|
491
|
+
};
|
|
492
|
+
};
|
|
493
|
+
privacy: {
|
|
494
|
+
level: "public" | "user_owned" | "admin";
|
|
495
|
+
note?: string | undefined;
|
|
496
|
+
};
|
|
497
|
+
examples?: string[] | undefined;
|
|
498
|
+
}[];
|
|
499
|
+
baseUrl?: string | undefined;
|
|
408
500
|
}>;
|
|
409
501
|
export declare const ManifestSchema: z.ZodObject<{
|
|
410
502
|
version: z.ZodString;
|
package/dist/cjs/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA2EvB,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA2EvB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiB9B,CAAA;AAID,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKzB,CAAA;AAIF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,mBAAmB,CAQnE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,mBAAmB,CAQvE"}
|
package/dist/cjs/schema.js
CHANGED
|
@@ -67,11 +67,14 @@ const CapabilitySchema = zod_1.z.object({
|
|
|
67
67
|
// ─── Config Schema ────────────────────────────────────────────────────────────
|
|
68
68
|
exports.CapmanConfigSchema = zod_1.z.object({
|
|
69
69
|
app: zod_1.z.string().min(1, 'app name is required'),
|
|
70
|
-
baseUrl: zod_1.z.string().url(
|
|
70
|
+
baseUrl: zod_1.z.string().url().optional(),
|
|
71
71
|
capabilities: zod_1.z.array(CapabilitySchema)
|
|
72
72
|
.min(1, 'at least one capability is required')
|
|
73
73
|
.refine(caps => new Set(caps.map(c => c.id)).size === caps.length, 'capability ids must be unique'),
|
|
74
|
-
})
|
|
74
|
+
}).refine(cfg => {
|
|
75
|
+
const needsBaseUrl = cfg.capabilities.some(c => c.resolver.type === 'api' || c.resolver.type === 'hybrid');
|
|
76
|
+
return !needsBaseUrl || !!cfg.baseUrl;
|
|
77
|
+
}, { message: 'baseUrl is required when any capability uses an api or hybrid resolver' });
|
|
75
78
|
// ─── Manifest Schema ──────────────────────────────────────────────────────────
|
|
76
79
|
exports.ManifestSchema = zod_1.z.object({
|
|
77
80
|
version: zod_1.z.string(),
|
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/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>;
|
package/dist/esm/cache.js
CHANGED
|
@@ -66,7 +66,7 @@ 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
72
|
const resolved = path.resolve(cwd, filePath);
|
|
@@ -78,9 +78,13 @@ export class FileCache {
|
|
|
78
78
|
this.filePath = resolved;
|
|
79
79
|
logger.info(`FileCache initialized — writing to: ${this.filePath}`);
|
|
80
80
|
}
|
|
81
|
-
|
|
82
|
-
if (this.
|
|
83
|
-
|
|
81
|
+
load() {
|
|
82
|
+
if (!this.loadPromise) {
|
|
83
|
+
this.loadPromise = this._doLoad();
|
|
84
|
+
}
|
|
85
|
+
return this.loadPromise;
|
|
86
|
+
}
|
|
87
|
+
async _doLoad() {
|
|
84
88
|
try {
|
|
85
89
|
const raw = await fs.promises.readFile(this.filePath, 'utf-8');
|
|
86
90
|
const parsed = JSON.parse(raw);
|
|
@@ -102,7 +106,6 @@ export class FileCache {
|
|
|
102
106
|
catch {
|
|
103
107
|
// File doesn't exist yet — start fresh
|
|
104
108
|
}
|
|
105
|
-
this.loaded = true;
|
|
106
109
|
}
|
|
107
110
|
save() {
|
|
108
111
|
this.saveQueue = this.saveQueue.then(() => this._doSave());
|
|
@@ -112,7 +115,9 @@ export class FileCache {
|
|
|
112
115
|
try {
|
|
113
116
|
const dir = path.dirname(this.filePath);
|
|
114
117
|
await fs.promises.mkdir(dir, { recursive: true });
|
|
115
|
-
|
|
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);
|
|
116
121
|
}
|
|
117
122
|
catch (err) {
|
|
118
123
|
logger.warn(`Failed to save file cache to ${this.filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
package/dist/esm/engine.js
CHANGED
|
@@ -38,12 +38,20 @@ export class CapmanEngine {
|
|
|
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
40
|
if (options.manifest.version) {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
`
|
|
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.`);
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
57
|
}
|
|
@@ -74,7 +82,8 @@ export class CapmanEngine {
|
|
|
74
82
|
const cached = await this.cache.get(queryKey, this.cacheTtlMs ?? undefined);
|
|
75
83
|
if (cached) {
|
|
76
84
|
steps.push({ type: 'cache_check', status: 'hit', durationMs: Date.now() - cacheStart, detail: 'Served from cache' });
|
|
77
|
-
logger.info(`Cache hit
|
|
85
|
+
logger.info(`Cache hit — capability: "${cached.result.capability?.id ?? 'none'}"`);
|
|
86
|
+
logger.debug(`Cache hit for query: "${query}"`);
|
|
78
87
|
// Re-extract params from the current query — never re-use cached params.
|
|
79
88
|
// Cached params belong to the original query (potentially from a different user).
|
|
80
89
|
// e.g. User A: "show orders for john" → cached with { customer: 'john' }
|
|
@@ -125,15 +134,7 @@ export class CapmanEngine {
|
|
|
125
134
|
detail: `level: ${privacyLevel}`,
|
|
126
135
|
});
|
|
127
136
|
}
|
|
128
|
-
// ── Step 4:
|
|
129
|
-
// Non-public capabilities are never cached — prevents auth bypass where
|
|
130
|
-
// User A's cached match is served to User B without privacy enforcement.
|
|
131
|
-
if (this.cache && matchResult.capability
|
|
132
|
-
&& matchResult.capability.privacy.level === 'public') {
|
|
133
|
-
const queryKey = normalizeQuery(query);
|
|
134
|
-
await this.cache.set(queryKey, matchResult);
|
|
135
|
-
}
|
|
136
|
-
// ── Step 5: Resolve ──────────────────────────────────────────────────────
|
|
137
|
+
// ── Step 4: Resolve ──────────────────────────────────────────────────────
|
|
137
138
|
const resolveStart = Date.now();
|
|
138
139
|
const resolution = await _resolve(matchResult, matchResult.extractedParams, this.resolveOptions(overrides));
|
|
139
140
|
steps.push({
|
|
@@ -142,6 +143,16 @@ export class CapmanEngine {
|
|
|
142
143
|
durationMs: Date.now() - resolveStart,
|
|
143
144
|
detail: resolution.error ?? `via ${resolution.resolverType}`,
|
|
144
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
|
+
}
|
|
145
156
|
// ── Step 6: Build reasoning array ────────────────────────────────────────
|
|
146
157
|
const reasoning = [];
|
|
147
158
|
if (matchResult.candidates.length) {
|
|
@@ -239,6 +250,12 @@ export class CapmanEngine {
|
|
|
239
250
|
const start = Date.now();
|
|
240
251
|
// ── Match — shared with ask() via _runMatch() ─────────────────────────────
|
|
241
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
|
+
}
|
|
242
259
|
let resolvedVia = _resolvedVia;
|
|
243
260
|
// ── Apply learning boost (same as ask()) ─────────────────────────────────
|
|
244
261
|
matchResult = await this.applyBoostToMatchResult(query, matchResult);
|
|
@@ -509,7 +526,8 @@ export class CapmanEngine {
|
|
|
509
526
|
matchResult = keywordResult;
|
|
510
527
|
}
|
|
511
528
|
else {
|
|
512
|
-
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}"`);
|
|
513
531
|
const t2 = Date.now();
|
|
514
532
|
try {
|
|
515
533
|
matchResult = await _matchWithLLM(query, this.manifest, { llm: this.llm });
|
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/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,16 +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
73
|
getTopCapabilities(limit?: number): Promise<Array<{
|
|
65
74
|
id: string;
|
|
66
75
|
hits: number;
|
|
67
76
|
}>>;
|
|
68
77
|
clear(): Promise<void>;
|
|
78
|
+
destroy(): Promise<void>;
|
|
69
79
|
}
|