capman 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,7 +48,7 @@ async function resolve(matchResult, params = {}, options = {}) {
48
48
  const enrichedParams = { ...params };
49
49
  if (options.auth?.userId) {
50
50
  for (const param of capability.params) {
51
- if (param.source === 'session' && options.auth.userId) {
51
+ if (param.source === 'session') {
52
52
  enrichedParams[param.name] = options.auth.userId;
53
53
  logger_1.logger.debug(`Injected session param "${param.name}" = "${options.auth.userId}"`);
54
54
  }
@@ -91,78 +91,82 @@ async function resolve(matchResult, params = {}, options = {}) {
91
91
  }
92
92
  async function resolveApi(resolver, params, options) {
93
93
  const startTime = Date.now();
94
+ const retries = options.retries ?? 0;
95
+ const timeoutMs = options.timeoutMs ?? 5000;
94
96
  const apiCalls = resolver.endpoints.map(endpoint => ({
95
97
  method: endpoint.method,
96
98
  url: buildUrl(options.baseUrl ?? '', endpoint.path, params),
97
99
  params,
98
100
  }));
99
101
  if (options.dryRun) {
100
- return {
101
- success: true,
102
- resolverType: 'api',
103
- apiCalls,
104
- durationMs: Date.now() - startTime,
105
- };
102
+ return { success: true, resolverType: 'api', apiCalls, durationMs: Date.now() - startTime };
106
103
  }
107
104
  const fetchFn = options.fetch ?? globalThis.fetch;
108
105
  if (!fetchFn) {
109
106
  return {
110
- success: true,
111
- resolverType: 'api',
112
- apiCalls,
107
+ success: true, resolverType: 'api', apiCalls,
113
108
  durationMs: Date.now() - startTime,
114
109
  error: 'No fetch available — returning call plan only',
115
110
  };
116
111
  }
112
+ // ── Fetch with retry + timeout (iterative — no recursion) ────────────────
113
+ async function fetchWithRetry(call) {
114
+ let lastErr;
115
+ for (let attempt = 0; attempt <= retries; attempt++) {
116
+ const controller = new AbortController();
117
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
118
+ try {
119
+ const res = await fetchFn(call.url, {
120
+ method: call.method,
121
+ headers: options.headers ?? {},
122
+ signal: controller.signal,
123
+ body: ['POST', 'PUT', 'PATCH'].includes(call.method)
124
+ ? JSON.stringify(call.params)
125
+ : undefined,
126
+ });
127
+ clearTimeout(timer);
128
+ return res;
129
+ }
130
+ catch (err) {
131
+ clearTimeout(timer);
132
+ lastErr = err;
133
+ const isTimeout = err instanceof Error && err.name === 'AbortError';
134
+ if (attempt < retries) {
135
+ logger_1.logger.warn(`Request failed (attempt ${attempt + 1}/${retries + 1}) — retrying: ${isTimeout ? 'timeout' : err}`);
136
+ }
137
+ else {
138
+ throw isTimeout ? new Error(`Request timed out after ${timeoutMs}ms`) : err;
139
+ }
140
+ }
141
+ }
142
+ throw lastErr;
143
+ }
117
144
  try {
118
- const responses = await Promise.all(apiCalls.map(c => fetchFn(c.url, {
119
- method: c.method,
120
- headers: options.headers ?? {},
121
- body: ['POST', 'PUT', 'PATCH'].includes(c.method)
122
- ? JSON.stringify(c.params)
123
- : undefined,
124
- })));
125
- // Check for HTTP errors
145
+ const responses = await Promise.all(apiCalls.map(c => fetchWithRetry(c)));
126
146
  const failedIdx = responses.findIndex(r => !r.ok);
127
147
  if (failedIdx !== -1) {
128
148
  const failed = responses[failedIdx];
129
149
  return {
130
- success: false,
131
- resolverType: 'api',
132
- apiCalls,
150
+ success: false, resolverType: 'api', apiCalls,
133
151
  durationMs: Date.now() - startTime,
134
152
  error: `API request failed: ${failed.status} ${failed.statusText}`,
135
153
  };
136
154
  }
137
- // Parse response bodies
138
155
  const enrichedCalls = await Promise.all(responses.map(async (res, i) => {
139
156
  let data = undefined;
140
157
  try {
141
158
  const text = await res.text();
142
159
  data = text ? JSON.parse(text) : undefined;
143
160
  }
144
- catch {
145
- // Non-JSON response leave data undefined
146
- }
147
- return {
148
- ...apiCalls[i],
149
- status: res.status,
150
- data,
151
- };
161
+ catch { /* non-JSON response */ }
162
+ return { ...apiCalls[i], status: res.status, data };
152
163
  }));
153
164
  logger_1.logger.debug(`API calls completed in ${Date.now() - startTime}ms`);
154
- return {
155
- success: true,
156
- resolverType: 'api',
157
- apiCalls: enrichedCalls,
158
- durationMs: Date.now() - startTime,
159
- };
165
+ return { success: true, resolverType: 'api', apiCalls: enrichedCalls, durationMs: Date.now() - startTime };
160
166
  }
161
167
  catch (err) {
162
168
  return {
163
- success: false,
164
- resolverType: 'api',
165
- apiCalls,
169
+ success: false, resolverType: 'api', apiCalls,
166
170
  durationMs: Date.now() - startTime,
167
171
  error: err instanceof Error ? err.message : String(err),
168
172
  };
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":";;AAuDA,0BA2EC;AAlID,qCAAiC;AA0BjC,SAAS,YAAY,CACnB,UAAwC,EACxC,IAAkB;IAElB,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAA;IAEtC,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAEnC,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,CAAC;YAC3B,OAAO,eAAe,UAAU,CAAC,EAAE,iDAAiD,CAAA;QACtF,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,CAAC;YAC3B,OAAO,eAAe,UAAU,CAAC,EAAE,4CAA4C,CAAA;QACjF,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1B,OAAO,eAAe,UAAU,CAAC,EAAE,wCAAwC,IAAI,CAAC,IAAI,IAAI,MAAM,GAAG,CAAA;QACnG,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAGM,KAAK,UAAU,OAAO,CAC3B,WAAwB,EACxB,SAAkC,EAAE,EACpC,UAA0B,EAAE;IAE5B,MAAM,EAAE,UAAU,EAAE,GAAG,WAAW,CAAA;IAElC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,eAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAA;QAC1D,OAAO;YACL,OAAO,EAAE,KAAK;YACd,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,wCAAwC;SAChD,CAAA;IACH,CAAC;IAED,4EAA4E;IAC5E,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3D,IAAI,YAAY,EAAE,CAAC;QACjB,eAAM,CAAC,IAAI,CAAC,yBAAyB,YAAY,EAAE,CAAC,CAAA;QACpD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,YAAY;SACpB,CAAA;IACH,CAAC;IAED,6EAA6E;IAC7E,iEAAiE;IACjE,MAAM,cAAc,GAAG,EAAE,GAAG,MAAM,EAAE,CAAA;IACpC,IAAI,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACzB,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC/B,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAA;gBAChD,eAAM,CAAC,KAAK,CAAC,2BAA2B,KAAK,CAAC,IAAI,QAAQ,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;YACnF,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAA;IACpC,eAAM,CAAC,IAAI,CAAC,yBAAyB,UAAU,CAAC,EAAE,SAAS,QAAQ,CAAC,IAAI,WAAW,CAAC,CAAA;IACpF,eAAM,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACjD,eAAM,CAAC,KAAK,CAAC,oBAAoB,OAAO,CAAC,OAAO,WAAW,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAE5E,IAAI,CAAC;QACH,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;YACtB,KAAK,KAAK;gBACR,OAAO,MAAM,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,CAAA;YAE5D,KAAK,KAAK;gBACR,OAAO,UAAU,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;YAE7C,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,eAAM,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAA;gBACjE,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBAC/C,UAAU,CAAC,QAAQ,CAAC,GAAkB,EAAE,cAAc,EAAE,OAAO,CAAC;oBAChE,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAkB,EAAE,cAAc,CAAC,CAAC;iBACzE,CAAC,CAAA;gBACF,OAAO;oBACL,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,OAAO;oBAC/C,YAAY,EAAE,QAAQ;oBACtB,QAAQ,EAAE,SAAS,CAAC,QAAQ;oBAC5B,SAAS,EAAE,SAAS,CAAC,SAAS;oBAC9B,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,KAAK;iBAC1C,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,eAAM,CAAC,KAAK,CAAC,0BAA0B,UAAU,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,CAAA;QAChE,OAAO;YACL,OAAO,EAAE,KAAK;YACd,YAAY,EAAE,QAAQ,CAAC,IAAI;YAC3B,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAA;IACH,CAAC;AACH,CAAC;AAGD,KAAK,UAAU,UAAU,CACvB,QAAiD,EACjD,MAA+B,EAC/B,OAAuB;IAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAC5B,MAAM,OAAO,GAAK,OAAO,CAAC,OAAO,IAAK,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAA;IAE3C,MAAM,QAAQ,GAAoB,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAC3D,MAAM;KACP,CAAC,CAAC,CAAA;IAEH,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;IAC7F,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAA;IACjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ;YAC5C,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,KAAK,EAAE,+CAA+C;SACvD,CAAA;IACH,CAAC;IAED,4EAA4E;IAC5E,KAAK,UAAU,cAAc,CAAC,IAAmB;QAC/C,IAAI,OAAgB,CAAA;QACpB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;YACpD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;YACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAA;YAC7D,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;oBAClC,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;oBAC9B,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;wBAClD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;wBAC7B,CAAC,CAAC,SAAS;iBACd,CAAC,CAAA;gBACF,YAAY,CAAC,KAAK,CAAC,CAAA;gBACnB,OAAO,GAAG,CAAA;YACZ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,YAAY,CAAC,KAAK,CAAC,CAAA;gBACnB,OAAO,GAAG,GAAG,CAAA;gBACb,MAAM,SAAS,GAAG,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,CAAA;gBACnE,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;oBACtB,eAAM,CAAC,IAAI,CAAC,2BAA2B,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,iBAAiB,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;gBAClH,CAAC;qBAAM,CAAC;oBACN,MAAM,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,2BAA2B,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;gBAC7E,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,OAAO,CAAA;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAEzE,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACjD,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;YACnC,OAAO;gBACL,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ;gBAC7C,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;gBAClC,KAAK,EAAE,uBAAuB,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,EAAE;aACnE,CAAA;QACH,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,GAAG,CACrC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;YAC7B,IAAI,IAAI,GAAY,SAAS,CAAA;YAC7B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;gBAC7B,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;YAC5C,CAAC;YAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC;YACnC,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAA;QACrD,CAAC,CAAC,CACH,CAAA;QAED,eAAM,CAAC,KAAK,CAAC,0BAA0B,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,CAAC,CAAA;QAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;IAE5G,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ;YAC7C,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAA;IACH,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CACjB,QAAiD,EACjD,MAA+B;IAE/B,IAAI,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;IACtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;IAC9D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAA;AACvE,CAAC;AAED,SAAS,QAAQ,CACf,OAAe,EACf,OAAe,EACf,MAA+B;IAE/B,IAAI,QAAQ,GAAG,OAAO,CAAA;IACtB,MAAM,MAAM,GAA4B,EAAE,CAAA;IAE1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YAClC,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC5E,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACrB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAA;IACvD,MAAM,EAAE,GAAK,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAChC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC;SAChD,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,IAAI,CAAC,GAAG,CAAC,CAAA;IAEZ,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AACpC,CAAC"}
@@ -57,6 +57,8 @@ export interface MatchResult {
57
57
  intent: 'navigation' | 'retrieval' | 'hybrid' | 'out_of_scope';
58
58
  extractedParams: Record<string, string | null>;
59
59
  reasoning: string;
60
+ /** All scored candidates — always present after match() */
61
+ candidates: MatchCandidate[];
60
62
  }
61
63
  export interface ApiCallResult {
62
64
  method: string;
@@ -81,4 +83,28 @@ export interface ValidationResult {
81
83
  errors: string[];
82
84
  warnings: string[];
83
85
  }
86
+ export interface MatchCandidate {
87
+ capabilityId: string;
88
+ score: number;
89
+ matched: boolean;
90
+ }
91
+ export interface TraceStep {
92
+ type: 'cache_check' | 'keyword_match' | 'llm_match' | 'privacy_check' | 'resolve';
93
+ status: 'hit' | 'miss' | 'pass' | 'fail' | 'skip';
94
+ durationMs: number;
95
+ detail?: string;
96
+ }
97
+ export interface ExecutionTrace {
98
+ query: string;
99
+ /** All capabilities scored — not just the winner */
100
+ candidates: MatchCandidate[];
101
+ /** Why the winning capability was selected */
102
+ reasoning: string[];
103
+ /** Step-by-step execution breakdown */
104
+ steps: TraceStep[];
105
+ /** Which matcher was used */
106
+ resolvedVia: 'cache' | 'keyword' | 'llm';
107
+ /** Total duration */
108
+ totalMs: number;
109
+ }
84
110
  //# 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.3.0";
1
+ export declare const VERSION = "0.4.1";
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.3.0';
5
+ exports.VERSION = '0.4.1';
6
6
  //# sourceMappingURL=version.js.map
package/dist/esm/cache.js CHANGED
@@ -2,40 +2,57 @@ import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { logger } from './logger';
4
4
  // ─── Normalize query for cache key ────────────────────────────────────────────
5
- function normalizeQuery(query) {
5
+ export function normalizeQuery(query) {
6
6
  return query.toLowerCase().trim().replace(/\s+/g, ' ');
7
7
  }
8
+ /**
9
+ * Build a smarter cache key based on matched capability + extracted params.
10
+ * Two different queries that resolve to the same capability with the same params
11
+ * will share a cache entry — dramatically improving hit rate.
12
+ * Falls back to normalized query if no capability matched.
13
+ */
14
+ export function buildCacheKey(query, capabilityId, extractedParams) {
15
+ if (!capabilityId)
16
+ return `query:${normalizeQuery(query)}`;
17
+ const paramStr = Object.entries(extractedParams)
18
+ .filter(([, v]) => v !== null)
19
+ .sort(([a], [b]) => a.localeCompare(b))
20
+ .map(([k, v]) => `${k}=${v}`)
21
+ .join('&');
22
+ return `cap:${capabilityId}${paramStr ? `:${paramStr}` : ''}`;
23
+ }
8
24
  // ─── Memory Cache ─────────────────────────────────────────────────────────────
25
+ const MEMORY_CACHE_MAX = 512;
9
26
  export class MemoryCache {
10
27
  constructor() {
11
28
  this.store = new Map();
12
29
  }
13
- async get(query) {
14
- const key = normalizeQuery(query);
30
+ async get(key) {
15
31
  const entry = this.store.get(key);
16
32
  if (entry) {
17
33
  entry.hits++;
18
- logger.debug(`Cache hit (memory): "${query}"`);
34
+ logger.debug(`Cache hit (memory): "${key}"`);
19
35
  return entry;
20
36
  }
21
37
  return null;
22
38
  }
23
- async set(query, result) {
24
- const key = normalizeQuery(query);
39
+ async set(key, result) {
40
+ if (this.store.size >= MEMORY_CACHE_MAX) {
41
+ const oldest = this.store.keys().next().value;
42
+ if (oldest !== undefined)
43
+ this.store.delete(oldest);
44
+ logger.debug(`Cache evicted oldest entry (max size ${MEMORY_CACHE_MAX} reached)`);
45
+ }
25
46
  this.store.set(key, {
26
- query,
47
+ query: key,
27
48
  result,
28
49
  cachedAt: new Date().toISOString(),
29
50
  hits: 0,
30
51
  });
31
- logger.debug(`Cache set (memory): "${query}"`);
32
- }
33
- async clear() {
34
- this.store.clear();
35
- }
36
- async size() {
37
- return this.store.size;
52
+ logger.debug(`Cache set (memory): "${key}"`);
38
53
  }
54
+ async clear() { this.store.clear(); }
55
+ async size() { return this.store.size; }
39
56
  }
40
57
  // ─── File Cache ───────────────────────────────────────────────────────────────
41
58
  export class FileCache {
@@ -43,63 +60,58 @@ export class FileCache {
43
60
  this.store = new Map();
44
61
  this.loaded = false;
45
62
  this.filePath = path.resolve(process.cwd(), filePath);
63
+ logger.info(`FileCache initialized — writing to: ${this.filePath}`);
46
64
  }
47
- load() {
65
+ async load() {
48
66
  if (this.loaded)
49
67
  return;
50
68
  try {
51
- if (fs.existsSync(this.filePath)) {
52
- const raw = JSON.parse(fs.readFileSync(this.filePath, 'utf-8'));
53
- this.store = new Map(Object.entries(raw));
54
- logger.debug(`File cache loaded: ${this.store.size} entries`);
55
- }
69
+ const raw = await fs.promises.readFile(this.filePath, 'utf-8');
70
+ this.store = new Map(Object.entries(JSON.parse(raw)));
71
+ logger.debug(`File cache loaded: ${this.store.size} entries`);
56
72
  }
57
73
  catch {
58
- logger.warn(`Failed to load file cache at ${this.filePath}`);
74
+ // File doesn't exist yet start fresh
59
75
  }
60
76
  this.loaded = true;
61
77
  }
62
- save() {
78
+ async save() {
63
79
  try {
64
80
  const dir = path.dirname(this.filePath);
65
- if (!fs.existsSync(dir))
66
- fs.mkdirSync(dir, { recursive: true });
67
- const obj = Object.fromEntries(this.store);
68
- fs.writeFileSync(this.filePath, JSON.stringify(obj, null, 2));
81
+ await fs.promises.mkdir(dir, { recursive: true });
82
+ await fs.promises.writeFile(this.filePath, JSON.stringify(Object.fromEntries(this.store), null, 2));
69
83
  }
70
84
  catch {
71
85
  logger.warn(`Failed to save file cache to ${this.filePath}`);
72
86
  }
73
87
  }
74
- async get(query) {
75
- this.load();
76
- const key = normalizeQuery(query);
88
+ async get(key) {
89
+ await this.load();
77
90
  const entry = this.store.get(key);
78
91
  if (entry) {
79
92
  entry.hits++;
80
- logger.debug(`Cache hit (file): "${query}"`);
93
+ logger.debug(`Cache hit (file): "${key}"`);
81
94
  return entry;
82
95
  }
83
96
  return null;
84
97
  }
85
- async set(query, result) {
86
- this.load();
87
- const key = normalizeQuery(query);
98
+ async set(key, result) {
99
+ await this.load();
88
100
  this.store.set(key, {
89
- query,
101
+ query: key,
90
102
  result,
91
103
  cachedAt: new Date().toISOString(),
92
104
  hits: 0,
93
105
  });
94
- this.save();
95
- logger.debug(`Cache set (file): "${query}"`);
106
+ await this.save();
107
+ logger.debug(`Cache set (file): "${key}"`);
96
108
  }
97
109
  async clear() {
98
110
  this.store.clear();
99
- this.save();
111
+ await this.save();
100
112
  }
101
113
  async size() {
102
- this.load();
114
+ await this.load();
103
115
  return this.store.size;
104
116
  }
105
117
  }
@@ -109,24 +121,22 @@ export class ComboCache {
109
121
  this.memory = new MemoryCache();
110
122
  this.file = new FileCache(filePath);
111
123
  }
112
- async get(query) {
113
- // Memory first fastest
114
- const memHit = await this.memory.get(query);
124
+ async get(key) {
125
+ const memHit = await this.memory.get(key);
115
126
  if (memHit)
116
127
  return memHit;
117
- // File fallback persists across restarts
118
- const fileHit = await this.file.get(query);
128
+ const fileHit = await this.file.get(key);
119
129
  if (fileHit) {
120
- // Promote to memory for next time
121
- await this.memory.set(query, fileHit.result);
130
+ await this.memory.set(key, fileHit.result);
131
+ logger.debug(`Cache promoted to memory: "${key}"`);
122
132
  return fileHit;
123
133
  }
124
134
  return null;
125
135
  }
126
- async set(query, result) {
136
+ async set(key, result) {
127
137
  await Promise.all([
128
- this.memory.set(query, result),
129
- this.file.set(query, result),
138
+ this.memory.set(key, result),
139
+ this.file.set(key, result),
130
140
  ]);
131
141
  }
132
142
  async clear() {
@@ -1,8 +1,8 @@
1
1
  import { match as _match, matchWithLLM as _matchWithLLM } from './matcher';
2
2
  import { resolve as _resolve } from './resolver';
3
- import { ComboCache } from './cache';
4
- import { FileLearningStore } from './learning';
3
+ import { MemoryLearningStore } from './learning';
5
4
  import { logger } from './logger';
5
+ import { MemoryCache, normalizeQuery } from './cache';
6
6
  // ─── CapmanEngine ─────────────────────────────────────────────────────────────
7
7
  export class CapmanEngine {
8
8
  constructor(options) {
@@ -13,14 +13,16 @@ export class CapmanEngine {
13
13
  this.auth = options.auth;
14
14
  this.headers = options.headers;
15
15
  this.threshold = options.threshold ?? 50;
16
- // Cache — default ComboCache, or disabled with false
16
+ // Cache — default MemoryCache (no filesystem writes), or disabled with false
17
+ // Use FileCache or ComboCache explicitly for persistence across restarts
17
18
  this.cache = options.cache === false
18
19
  ? null
19
- : (options.cache ?? new ComboCache());
20
- // Learning — default FileLearningStore, or disabled with false
20
+ : (options.cache ?? new MemoryCache());
21
+ // Learning — default MemoryLearningStore (no filesystem writes), or disabled with false
22
+ // Use FileLearningStore explicitly for persistence across restarts
21
23
  this.learning = options.learning === false
22
24
  ? null
23
- : (options.learning ?? new FileLearningStore());
25
+ : (options.learning ?? new MemoryLearningStore());
24
26
  logger.info(`CapmanEngine initialized — mode: ${this.mode}, cache: ${this.cache ? 'enabled' : 'disabled'}, learning: ${this.learning ? 'enabled' : 'disabled'}`);
25
27
  }
26
28
  /**
@@ -36,68 +38,147 @@ export class CapmanEngine {
36
38
  */
37
39
  async ask(query, overrides = {}) {
38
40
  const start = Date.now();
41
+ const steps = [];
42
+ let resolvedVia = 'keyword';
39
43
  // ── Step 1: Check cache ──────────────────────────────────────────────────
44
+ const cacheStart = Date.now();
40
45
  if (this.cache) {
41
- const cached = await this.cache.get(query);
46
+ const queryKey = normalizeQuery(query);
47
+ const cached = await this.cache.get(queryKey);
42
48
  if (cached) {
49
+ steps.push({ type: 'cache_check', status: 'hit', durationMs: Date.now() - cacheStart, detail: 'Served from cache' });
43
50
  logger.info(`Cache hit for: "${query}"`);
44
51
  const resolution = await _resolve(cached.result, cached.result.extractedParams, this.resolveOptions(overrides));
52
+ const trace = {
53
+ query,
54
+ candidates: cached.result.candidates ?? [],
55
+ reasoning: [`Served from cache (original: ${cached.result.reasoning})`],
56
+ steps,
57
+ resolvedVia: 'cache',
58
+ totalMs: Date.now() - start,
59
+ };
45
60
  const result = {
46
61
  match: cached.result,
47
62
  resolution,
48
63
  resolvedVia: 'cache',
49
64
  durationMs: Date.now() - start,
65
+ trace,
50
66
  };
51
67
  await this.recordLearning(query, cached.result, 'cache');
52
68
  return result;
53
69
  }
70
+ steps.push({ type: 'cache_check', status: 'miss', durationMs: Date.now() - cacheStart });
71
+ }
72
+ else {
73
+ steps.push({ type: 'cache_check', status: 'skip', durationMs: 0, detail: 'Cache disabled' });
54
74
  }
55
75
  // ── Step 2: Match ────────────────────────────────────────────────────────
56
76
  let matchResult;
57
- let resolvedVia = 'keyword';
58
77
  switch (this.mode) {
59
78
  case 'cheap': {
79
+ const t = Date.now();
60
80
  matchResult = _match(query, this.manifest);
81
+ steps.push({ type: 'keyword_match', status: 'pass', durationMs: Date.now() - t, detail: `confidence: ${matchResult.confidence}%` });
61
82
  break;
62
83
  }
63
84
  case 'accurate': {
64
85
  if (this.llm) {
86
+ const t = Date.now();
65
87
  matchResult = await _matchWithLLM(query, this.manifest, { llm: this.llm });
66
88
  resolvedVia = 'llm';
89
+ steps.push({ type: 'llm_match', status: 'pass', durationMs: Date.now() - t, detail: `confidence: ${matchResult.confidence}%` });
67
90
  }
68
91
  else {
69
92
  logger.warn('accurate mode requires llm — falling back to keyword');
93
+ const t = Date.now();
70
94
  matchResult = _match(query, this.manifest);
95
+ steps.push({ type: 'keyword_match', status: 'pass', durationMs: Date.now() - t, detail: 'llm not provided, used keyword' });
71
96
  }
72
97
  break;
73
98
  }
74
99
  case 'balanced':
75
100
  default: {
101
+ const t1 = Date.now();
76
102
  const keywordResult = _match(query, this.manifest);
103
+ steps.push({ type: 'keyword_match', status: 'pass', durationMs: Date.now() - t1, detail: `confidence: ${keywordResult.confidence}%` });
77
104
  if (keywordResult.confidence >= this.threshold || !this.llm) {
78
105
  matchResult = keywordResult;
79
106
  }
80
107
  else {
81
108
  logger.info(`Low confidence (${keywordResult.confidence}%) — escalating to LLM`);
109
+ const t2 = Date.now();
82
110
  matchResult = await _matchWithLLM(query, this.manifest, { llm: this.llm });
83
111
  resolvedVia = 'llm';
112
+ steps.push({ type: 'llm_match', status: 'pass', durationMs: Date.now() - t2, detail: `confidence: ${matchResult.confidence}%` });
84
113
  }
85
114
  break;
86
115
  }
87
116
  }
88
- // ── Step 3: Cache the match result ───────────────────────────────────────
117
+ // ── Step 3: Privacy check ────────────────────────────────────────────────
118
+ if (matchResult.capability) {
119
+ const privacyLevel = matchResult.capability.privacy.level;
120
+ steps.push({
121
+ type: 'privacy_check',
122
+ status: 'pass',
123
+ durationMs: 0,
124
+ detail: `level: ${privacyLevel}`,
125
+ });
126
+ }
127
+ // ── Step 4: Cache the match result ───────────────────────────────────────
89
128
  if (this.cache && matchResult.capability) {
90
- await this.cache.set(query, matchResult);
129
+ const queryKey = normalizeQuery(query);
130
+ await this.cache.set(queryKey, matchResult);
91
131
  }
92
- // ── Step 4: Resolve ──────────────────────────────────────────────────────
132
+ // ── Step 5: Resolve ──────────────────────────────────────────────────────
133
+ const resolveStart = Date.now();
93
134
  const resolution = await _resolve(matchResult, matchResult.extractedParams, this.resolveOptions(overrides));
94
- // ── Step 5: Record learning ──────────────────────────────────────────────
135
+ steps.push({
136
+ type: 'resolve',
137
+ status: resolution.success ? 'pass' : 'fail',
138
+ durationMs: Date.now() - resolveStart,
139
+ detail: resolution.error ?? `via ${resolution.resolverType}`,
140
+ });
141
+ // ── Step 6: Build reasoning array ────────────────────────────────────────
142
+ const reasoning = [];
143
+ if (matchResult.candidates?.length) {
144
+ const winner = matchResult.candidates.find(c => c.matched);
145
+ const rejected = matchResult.candidates
146
+ .filter(c => !c.matched && c.score > 0)
147
+ .sort((a, b) => b.score - a.score)
148
+ .slice(0, 3);
149
+ if (winner) {
150
+ reasoning.push(`Matched "${winner.capabilityId}" with ${winner.score}% confidence`);
151
+ }
152
+ if (rejected.length) {
153
+ reasoning.push(`Rejected: ${rejected.map(r => `${r.capabilityId} (${r.score}%)`).join(', ')}`);
154
+ }
155
+ reasoning.push(`Resolved via: ${resolvedVia}`);
156
+ if (matchResult.extractedParams && Object.keys(matchResult.extractedParams).length) {
157
+ const params = Object.entries(matchResult.extractedParams)
158
+ .map(([k, v]) => `${k}=${v}`)
159
+ .join(', ');
160
+ reasoning.push(`Extracted params: ${params}`);
161
+ }
162
+ }
163
+ else {
164
+ reasoning.push(matchResult.reasoning);
165
+ }
166
+ // ── Step 7: Record learning ──────────────────────────────────────────────
95
167
  await this.recordLearning(query, matchResult, resolvedVia);
168
+ const trace = {
169
+ query,
170
+ candidates: matchResult.candidates ?? [],
171
+ reasoning,
172
+ steps,
173
+ resolvedVia,
174
+ totalMs: Date.now() - start,
175
+ };
96
176
  return {
97
177
  match: matchResult,
98
178
  resolution,
99
179
  resolvedVia,
100
180
  durationMs: Date.now() - start,
181
+ trace,
101
182
  };
102
183
  }
103
184
  /**
@@ -8,7 +8,7 @@ export function generate(config) {
8
8
  version: VERSION,
9
9
  app: config.app,
10
10
  generatedAt: new Date().toISOString(),
11
- capabilities: config.capabilities,
11
+ capabilities: config.capabilities.map(cap => ({ ...cap, params: [...cap.params] })),
12
12
  };
13
13
  }
14
14
  export function loadConfig(configPath) {