capman 0.5.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/bin/lib/cmd-generate.js +156 -12
- package/bin/lib/cmd-help.js +3 -0
- package/dist/cjs/engine.d.ts +53 -1
- package/dist/cjs/engine.d.ts.map +1 -1
- package/dist/cjs/engine.js +219 -9
- package/dist/cjs/engine.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -0
- 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.map +1 -1
- package/dist/cjs/learning.js +12 -18
- package/dist/cjs/learning.js.map +1 -1
- package/dist/cjs/matcher.d.ts +55 -0
- package/dist/cjs/matcher.d.ts.map +1 -1
- package/dist/cjs/matcher.js +267 -31
- package/dist/cjs/matcher.js.map +1 -1
- package/dist/cjs/schema.d.ts +46 -28
- package/dist/cjs/schema.d.ts.map +1 -1
- package/dist/cjs/schema.js +1 -0
- package/dist/cjs/schema.js.map +1 -1
- package/dist/cjs/types.d.ts +7 -1
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/esm/engine.d.ts +53 -1
- package/dist/esm/engine.js +220 -10
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/learning.js +13 -19
- package/dist/esm/matcher.d.ts +55 -0
- package/dist/esm/matcher.js +261 -31
- package/dist/esm/schema.d.ts +46 -28
- package/dist/esm/schema.js +1 -0
- package/dist/esm/types.d.ts +7 -1
- package/package.json +1 -1
package/dist/esm/matcher.js
CHANGED
|
@@ -18,40 +18,226 @@ export const STOPWORDS = new Set([
|
|
|
18
18
|
'it', 'its', 'how', 'when', 'where', 'who', 'which', 'all',
|
|
19
19
|
'just', 'some', 'any', 'there', 'their', 'them', 'they',
|
|
20
20
|
]);
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
// ─── Type Patterns ────────────────────────────────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Regex patterns for common param types.
|
|
24
|
+
* Used when a CapabilityParam has `pattern` set to a named type.
|
|
25
|
+
*/
|
|
26
|
+
export const TYPE_PATTERNS = {
|
|
27
|
+
email: /\b[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}\b/,
|
|
28
|
+
date: /\b\d{4}-\d{2}-\d{2}\b|\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\w*\s+\d{1,2}\b/i,
|
|
29
|
+
orderId: /\b[A-Z]{2,}-?\d{4,}\b|\b\d{6,}\b/,
|
|
30
|
+
url: /https?:\/\/[^\s]+/,
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Extracts a value from a query using an example template pattern.
|
|
34
|
+
* e.g. template "order {orderId}", query "track order 12345" → "12345"
|
|
35
|
+
* e.g. template "booking {ref}", query "cancel booking ABC-001" → "ABC-001"
|
|
36
|
+
*/
|
|
37
|
+
function extractFromTemplate(query, template, paramName) {
|
|
38
|
+
// Split template on {paramName} to get prefix and suffix
|
|
39
|
+
const placeholder = `{${paramName}}`;
|
|
40
|
+
const idx = template.indexOf(placeholder);
|
|
41
|
+
if (idx === -1)
|
|
42
|
+
return null;
|
|
43
|
+
const prefix = template.slice(0, idx).trim().toLowerCase();
|
|
44
|
+
const suffix = template.slice(idx + placeholder.length).trim().toLowerCase();
|
|
45
|
+
const q = query.toLowerCase();
|
|
46
|
+
if (prefix) {
|
|
47
|
+
const prefixIdx = q.indexOf(prefix);
|
|
48
|
+
if (prefixIdx === -1)
|
|
49
|
+
return null;
|
|
50
|
+
const after = query.slice(prefixIdx + prefix.length).trim();
|
|
51
|
+
const tokens = after.split(/\s+/).filter(t => t.length > 0);
|
|
52
|
+
if (!tokens.length)
|
|
53
|
+
return null;
|
|
54
|
+
// If there's a suffix, find it and take what's between
|
|
55
|
+
if (suffix) {
|
|
56
|
+
const suffixIdx = after.toLowerCase().indexOf(suffix);
|
|
57
|
+
if (suffixIdx > 0) {
|
|
58
|
+
return after.slice(0, suffixIdx).trim().split(/\s+/)[0] ?? null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return tokens[0].replace(/[^a-zA-Z0-9\-_.@]/g, '') || null;
|
|
62
|
+
}
|
|
63
|
+
// Prefix is empty — placeholder is at start of template e.g. "{email} unsubscribe"
|
|
64
|
+
if (!prefix) {
|
|
65
|
+
if (suffix) {
|
|
66
|
+
// Find suffix in query — take what comes before it
|
|
67
|
+
const suffixIdx = query.toLowerCase().indexOf(suffix);
|
|
68
|
+
if (suffixIdx > 0) {
|
|
69
|
+
return query.slice(0, suffixIdx).trim().split(/\s+/).pop()
|
|
70
|
+
?.replace(/[^a-zA-Z0-9\-_.@]/g, '') || null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// No prefix, no suffix — template is just "{paramName}"; take last meaningful word
|
|
74
|
+
const words = query.trim().split(/\s+/);
|
|
75
|
+
return words[words.length - 1]?.replace(/[^a-zA-Z0-9\-_.@]/g, '') || null;
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
// ─── Stem cache ───────────────────────────────────────────────────────────────
|
|
80
|
+
// Each word stemmed exactly once per process — O(1) on repeat lookups.
|
|
81
|
+
// Module-level — persists for the process lifetime. Vocabulary in production
|
|
82
|
+
// is finite (capability names + user query vocabulary) so growth is bounded
|
|
83
|
+
// in practice. In test environments with synthetic random strings, this may
|
|
84
|
+
// grow larger but remains functionally harmless.
|
|
85
|
+
const stemCache = new Map();
|
|
86
|
+
/**
|
|
87
|
+
* Simplified suffix-stripping stemmer — 10 most common English morphological
|
|
88
|
+
* patterns covering ~80% of benefit at ~25% the complexity of Porter stemmer.
|
|
89
|
+
* Applied symmetrically to both query words and capability index words.
|
|
90
|
+
*/
|
|
91
|
+
export function stem(word) {
|
|
92
|
+
const cached = stemCache.get(word);
|
|
93
|
+
if (cached !== undefined)
|
|
94
|
+
return cached;
|
|
95
|
+
let s = word;
|
|
96
|
+
if (s.length > 7 && s.endsWith('ation'))
|
|
97
|
+
s = s.slice(0, -5); // cancellation → cancell
|
|
98
|
+
else if (s.length > 6 && s.endsWith('tion'))
|
|
99
|
+
s = s.slice(0, -4); // completion → comple
|
|
100
|
+
else if (s.length > 6 && s.endsWith('ing'))
|
|
101
|
+
s = s.slice(0, -3); // tracking → track
|
|
102
|
+
else if (s.length > 6 && s.endsWith('ity'))
|
|
103
|
+
s = s.slice(0, -3); // availability → availabil
|
|
104
|
+
else if (s.length > 5 && s.endsWith('ion'))
|
|
105
|
+
s = s.slice(0, -3); // version → vers
|
|
106
|
+
else if (s.length > 6 && s.endsWith('est'))
|
|
107
|
+
s = s.slice(0, -3); // fastest → fast
|
|
108
|
+
else if (s.length > 4 && s.endsWith('er'))
|
|
109
|
+
s = s.slice(0, -2); // tracker → track
|
|
110
|
+
else if (s.length > 4 && s.endsWith('ed'))
|
|
111
|
+
s = s.slice(0, -2); // ordered → order
|
|
112
|
+
else if (s.length > 4 && s.endsWith('ly'))
|
|
113
|
+
s = s.slice(0, -2); // quickly → quick
|
|
114
|
+
else if (s.length > 4 && s.endsWith('es'))
|
|
115
|
+
s = s.slice(0, -2); // fetches → fetch
|
|
116
|
+
else if (s.length > 3 && s.endsWith('s') &&
|
|
117
|
+
!s.endsWith('ss'))
|
|
118
|
+
s = s.slice(0, -1); // orders → order
|
|
119
|
+
stemCache.set(word, s);
|
|
120
|
+
return s;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Shared tokenizer — used by scorer, learning index, and boost system.
|
|
124
|
+
* Applies stopword filtering AND stemming symmetrically.
|
|
125
|
+
* Any site that tokenizes text for matching MUST use this function
|
|
126
|
+
* to avoid silent mismatches between query and index tokens.
|
|
127
|
+
*/
|
|
128
|
+
export function tokenize(text) {
|
|
129
|
+
return text
|
|
130
|
+
.toLowerCase()
|
|
131
|
+
.split(/\W+/)
|
|
132
|
+
.filter(w => w.length > 2 && !STOPWORDS.has(w))
|
|
133
|
+
.map(stem);
|
|
134
|
+
}
|
|
135
|
+
/** Build a BM25 index over all capabilities. Call once at manifest load. */
|
|
136
|
+
export function buildBM25Index(capabilities) {
|
|
137
|
+
const N = capabilities.length;
|
|
138
|
+
if (N === 0)
|
|
139
|
+
return { df: {}, avgdl: { examples: 0, description: 0, name: 0 }, N: 0, bigrams: {}, };
|
|
140
|
+
const df = {};
|
|
141
|
+
let totalExLen = 0;
|
|
142
|
+
let totalDescLen = 0;
|
|
143
|
+
let totalNameLen = 0;
|
|
144
|
+
for (const cap of capabilities) {
|
|
145
|
+
const exTokens = tokenize((cap.examples ?? []).join(' '));
|
|
146
|
+
const descTokens = tokenize(cap.description);
|
|
147
|
+
const nameTokens = tokenize(cap.name);
|
|
148
|
+
totalExLen += exTokens.length;
|
|
149
|
+
totalDescLen += descTokens.length;
|
|
150
|
+
totalNameLen += nameTokens.length;
|
|
151
|
+
// Count document frequency — each term counted once per capability
|
|
152
|
+
const seen = new Set();
|
|
153
|
+
for (const t of [...exTokens, ...descTokens, ...nameTokens]) {
|
|
154
|
+
if (!seen.has(t)) {
|
|
155
|
+
df[t] = (df[t] ?? 0) + 1;
|
|
156
|
+
seen.add(t);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Build bigram sets per capability — examples field only
|
|
161
|
+
// Clean bigrams only: post-stopword, post-stem tokens
|
|
162
|
+
const bigrams = {};
|
|
163
|
+
for (const cap of capabilities) {
|
|
164
|
+
const set = new Set();
|
|
165
|
+
for (const example of cap.examples ?? []) {
|
|
166
|
+
for (const bg of extractBigrams(tokenize(example)))
|
|
167
|
+
set.add(bg);
|
|
168
|
+
}
|
|
169
|
+
bigrams[cap.id] = set;
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
df,
|
|
173
|
+
avgdl: {
|
|
174
|
+
examples: totalExLen / N,
|
|
175
|
+
description: totalDescLen / N,
|
|
176
|
+
name: totalNameLen / N,
|
|
177
|
+
},
|
|
178
|
+
N,
|
|
179
|
+
bigrams,
|
|
180
|
+
};
|
|
23
181
|
}
|
|
24
|
-
|
|
182
|
+
/**
|
|
183
|
+
* BM25 scoring with field weights.
|
|
184
|
+
* k1 = 1.5 (TF saturation), b = 0.75 (length normalization)
|
|
185
|
+
* Field weights: examples 0.6, description 0.3, name 0.1
|
|
186
|
+
*/
|
|
187
|
+
export function scoreCapability(qWordSet, cap, index, k1 = 1.5, b = 0.75) {
|
|
188
|
+
if (index.N === 0)
|
|
189
|
+
return 0;
|
|
190
|
+
const score = bm25Field(qWordSet, tokenize((cap.examples ?? []).join(' ')), index, 'examples', k1, b) * 0.6
|
|
191
|
+
+ bm25Field(qWordSet, tokenize(cap.description), index, 'description', k1, b) * 0.3
|
|
192
|
+
+ bm25Field(qWordSet, tokenize(cap.name), index, 'name', k1, b) * 0.1;
|
|
193
|
+
return score;
|
|
194
|
+
}
|
|
195
|
+
function bm25Field(queryTerms, fieldTokens, index, field, k1, b) {
|
|
196
|
+
if (fieldTokens.length === 0)
|
|
197
|
+
return 0;
|
|
198
|
+
const avgdl = index.avgdl[field] || 1;
|
|
199
|
+
const dl = fieldTokens.length;
|
|
200
|
+
const tf = new Map();
|
|
201
|
+
for (const t of fieldTokens) {
|
|
202
|
+
tf.set(t, (tf.get(t) ?? 0) + 1);
|
|
203
|
+
}
|
|
25
204
|
let score = 0;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// Taking Math.max means quality of examples matters, not quantity.
|
|
30
|
-
let bestExampleScore = 0;
|
|
31
|
-
for (const example of cap.examples ?? []) {
|
|
32
|
-
const exWords = filterStopwords(example.toLowerCase().split(/\s+/));
|
|
33
|
-
if (exWords.length === 0)
|
|
205
|
+
for (const term of queryTerms) {
|
|
206
|
+
const termTf = tf.get(term) ?? 0;
|
|
207
|
+
if (termTf === 0)
|
|
34
208
|
continue;
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
209
|
+
const df = index.df[term] ?? 0;
|
|
210
|
+
const idf = Math.log((index.N - df + 0.5) / (df + 0.5) + 1);
|
|
211
|
+
const tfNorm = (termTf * (k1 + 1)) / (termTf + k1 * (1 - b + b * (dl / avgdl)));
|
|
212
|
+
score += idf * tfNorm;
|
|
38
213
|
}
|
|
39
|
-
score
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
214
|
+
return score;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Extracts bigrams from a token array as "token1__token2" strings.
|
|
218
|
+
* Input must already be post-stopword and post-stem (use tokenize() first).
|
|
219
|
+
*/
|
|
220
|
+
export function extractBigrams(tokens) {
|
|
221
|
+
const bigrams = new Set();
|
|
222
|
+
for (let i = 0; i < tokens.length - 1; i++) {
|
|
223
|
+
bigrams.add(`${tokens[i]}__${tokens[i + 1]}`);
|
|
47
224
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
225
|
+
return bigrams;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Returns a fixed bonus in normalized points (0–15), applied after BM25 normalization.
|
|
229
|
+
* 5 points per matching bigram, saturates at 3 bigrams (15 points).
|
|
230
|
+
* Fixed point value regardless of manifest size — ceiling-independent.
|
|
231
|
+
*/
|
|
232
|
+
function bigramBonus(queryBigrams, capBigrams) {
|
|
233
|
+
if (queryBigrams.size === 0 || capBigrams.size === 0)
|
|
234
|
+
return 0;
|
|
235
|
+
let overlap = 0;
|
|
236
|
+
for (const bigram of queryBigrams) {
|
|
237
|
+
if (capBigrams.has(bigram))
|
|
238
|
+
overlap++;
|
|
53
239
|
}
|
|
54
|
-
return Math.min(
|
|
240
|
+
return Math.min(overlap * 5, 15); // normalized points — 3 bigrams saturate at 15
|
|
55
241
|
}
|
|
56
242
|
export function resolverToIntent(cap) {
|
|
57
243
|
const t = cap.resolver.type;
|
|
@@ -68,7 +254,7 @@ export function resolverToIntent(cap) {
|
|
|
68
254
|
* capability field values before injection into the system prompt.
|
|
69
255
|
* Removes control characters, newlines, and delimiter-like sequences.
|
|
70
256
|
*/
|
|
71
|
-
function sanitizeForPrompt(value, maxLen) {
|
|
257
|
+
export function sanitizeForPrompt(value, maxLen) {
|
|
72
258
|
return value
|
|
73
259
|
.replace(/[\r\n\t]/g, ' ') // newlines → space
|
|
74
260
|
.replace(/---+/g, '—') // horizontal rules → em dash
|
|
@@ -104,6 +290,26 @@ export function extractParams(query, cap) {
|
|
|
104
290
|
result[param.name] = null;
|
|
105
291
|
continue;
|
|
106
292
|
}
|
|
293
|
+
// ── Pattern extraction (highest priority) ─────────────────────────────
|
|
294
|
+
if (param.pattern) {
|
|
295
|
+
const namedPattern = TYPE_PATTERNS[param.pattern];
|
|
296
|
+
if (namedPattern) {
|
|
297
|
+
// Named type pattern — match regex directly against full query
|
|
298
|
+
const match = query.match(namedPattern);
|
|
299
|
+
if (match) {
|
|
300
|
+
result[param.name] = match[0];
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else if (param.pattern.includes(`{${param.name}}`)) {
|
|
305
|
+
// Example template — positional extraction
|
|
306
|
+
const extracted = extractFromTemplate(query, param.pattern, param.name);
|
|
307
|
+
if (extracted) {
|
|
308
|
+
result[param.name] = extracted;
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
107
313
|
// Try to extract value after known keywords
|
|
108
314
|
// e.g. "profile for johndoe" → johndoe
|
|
109
315
|
// "articles by jane" → jane
|
|
@@ -225,10 +431,34 @@ export function match(query, manifest, options = {}) {
|
|
|
225
431
|
}
|
|
226
432
|
// ── Score all capabilities ────────────────────────────────────────────────
|
|
227
433
|
// Build qWordSet once — O(1) lookups instead of O(n) Array.includes per word
|
|
228
|
-
const
|
|
434
|
+
const qTokens = tokenize(query);
|
|
435
|
+
const qWordSet = new Set(qTokens);
|
|
436
|
+
// Build query bigrams for phrase bonus
|
|
437
|
+
const qBigrams = extractBigrams(qTokens);
|
|
438
|
+
// Build BM25 index for this manifest — O(capabilities × tokens)
|
|
439
|
+
// In CapmanEngine this is pre-built; for direct match() calls it's built per-call
|
|
440
|
+
const bm25Index = options.bm25Index ?? buildBM25Index(manifest.capabilities);
|
|
441
|
+
const k1 = options.bm25K1 ?? 1.5;
|
|
442
|
+
const b = options.bm25B ?? 0.75;
|
|
443
|
+
// Calibrate ceiling — max self-score for normalization
|
|
444
|
+
const ceiling = options.bm25Ceiling ?? (() => {
|
|
445
|
+
let max = 0;
|
|
446
|
+
for (const cap of manifest.capabilities) {
|
|
447
|
+
if (!cap.examples?.length)
|
|
448
|
+
continue;
|
|
449
|
+
const selfWords = new Set(tokenize(cap.examples[0]));
|
|
450
|
+
const raw = scoreCapability(selfWords, cap, bm25Index, k1, b);
|
|
451
|
+
if (raw > max)
|
|
452
|
+
max = raw;
|
|
453
|
+
}
|
|
454
|
+
return max > 0 ? max : 100;
|
|
455
|
+
})();
|
|
229
456
|
const allScores = [];
|
|
230
457
|
for (const cap of manifest.capabilities) {
|
|
231
|
-
const
|
|
458
|
+
const rawBM25 = scoreCapability(qWordSet, cap, bm25Index, k1, b);
|
|
459
|
+
const bm25Score = Math.min(100, Math.round((rawBM25 / ceiling) * 100));
|
|
460
|
+
const bonusPoints = bigramBonus(qBigrams, bm25Index.bigrams[cap.id] ?? new Set());
|
|
461
|
+
const keywordScore = Math.min(100, bm25Score + bonusPoints);
|
|
232
462
|
const fuzzyScore = fuzzyScoreMap.get(cap.id) ?? 0;
|
|
233
463
|
const via = fuzzyScore > keywordScore ? 'fuzzy' : 'keyword';
|
|
234
464
|
const score = Math.min(100, Math.round(Math.max(keywordScore, fuzzyScore)));
|
package/dist/esm/schema.d.ts
CHANGED
|
@@ -13,18 +13,21 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
13
13
|
required: z.ZodBoolean;
|
|
14
14
|
source: z.ZodEnum<["user_query", "session"]>;
|
|
15
15
|
default: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
16
|
+
pattern: z.ZodOptional<z.ZodString>;
|
|
16
17
|
}, "strip", z.ZodTypeAny, {
|
|
17
18
|
name: string;
|
|
18
|
-
required: boolean;
|
|
19
19
|
description: string;
|
|
20
|
+
required: boolean;
|
|
20
21
|
source: "user_query" | "session";
|
|
21
22
|
default?: string | number | boolean | undefined;
|
|
23
|
+
pattern?: string | undefined;
|
|
22
24
|
}, {
|
|
23
25
|
name: string;
|
|
24
|
-
required: boolean;
|
|
25
26
|
description: string;
|
|
27
|
+
required: boolean;
|
|
26
28
|
source: "user_query" | "session";
|
|
27
29
|
default?: string | number | boolean | undefined;
|
|
30
|
+
pattern?: string | undefined;
|
|
28
31
|
}>, "many">;
|
|
29
32
|
returns: z.ZodArray<z.ZodString, "many">;
|
|
30
33
|
resolver: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
@@ -147,14 +150,15 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
147
150
|
}, "strip", z.ZodTypeAny, {
|
|
148
151
|
name: string;
|
|
149
152
|
id: string;
|
|
153
|
+
description: string;
|
|
150
154
|
params: {
|
|
151
155
|
name: string;
|
|
152
|
-
required: boolean;
|
|
153
156
|
description: string;
|
|
157
|
+
required: boolean;
|
|
154
158
|
source: "user_query" | "session";
|
|
155
159
|
default?: string | number | boolean | undefined;
|
|
160
|
+
pattern?: string | undefined;
|
|
156
161
|
}[];
|
|
157
|
-
description: string;
|
|
158
162
|
returns: string[];
|
|
159
163
|
resolver: {
|
|
160
164
|
type: "api";
|
|
@@ -189,14 +193,15 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
189
193
|
}, {
|
|
190
194
|
name: string;
|
|
191
195
|
id: string;
|
|
196
|
+
description: string;
|
|
192
197
|
params: {
|
|
193
198
|
name: string;
|
|
194
|
-
required: boolean;
|
|
195
199
|
description: string;
|
|
200
|
+
required: boolean;
|
|
196
201
|
source: "user_query" | "session";
|
|
197
202
|
default?: string | number | boolean | undefined;
|
|
203
|
+
pattern?: string | undefined;
|
|
198
204
|
}[];
|
|
199
|
-
description: string;
|
|
200
205
|
returns: string[];
|
|
201
206
|
resolver: {
|
|
202
207
|
type: "api";
|
|
@@ -231,14 +236,15 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
231
236
|
}>, "many">, {
|
|
232
237
|
name: string;
|
|
233
238
|
id: string;
|
|
239
|
+
description: string;
|
|
234
240
|
params: {
|
|
235
241
|
name: string;
|
|
236
|
-
required: boolean;
|
|
237
242
|
description: string;
|
|
243
|
+
required: boolean;
|
|
238
244
|
source: "user_query" | "session";
|
|
239
245
|
default?: string | number | boolean | undefined;
|
|
246
|
+
pattern?: string | undefined;
|
|
240
247
|
}[];
|
|
241
|
-
description: string;
|
|
242
248
|
returns: string[];
|
|
243
249
|
resolver: {
|
|
244
250
|
type: "api";
|
|
@@ -273,14 +279,15 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
273
279
|
}[], {
|
|
274
280
|
name: string;
|
|
275
281
|
id: string;
|
|
282
|
+
description: string;
|
|
276
283
|
params: {
|
|
277
284
|
name: string;
|
|
278
|
-
required: boolean;
|
|
279
285
|
description: string;
|
|
286
|
+
required: boolean;
|
|
280
287
|
source: "user_query" | "session";
|
|
281
288
|
default?: string | number | boolean | undefined;
|
|
289
|
+
pattern?: string | undefined;
|
|
282
290
|
}[];
|
|
283
|
-
description: string;
|
|
284
291
|
returns: string[];
|
|
285
292
|
resolver: {
|
|
286
293
|
type: "api";
|
|
@@ -318,14 +325,15 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
318
325
|
capabilities: {
|
|
319
326
|
name: string;
|
|
320
327
|
id: string;
|
|
328
|
+
description: string;
|
|
321
329
|
params: {
|
|
322
330
|
name: string;
|
|
323
|
-
required: boolean;
|
|
324
331
|
description: string;
|
|
332
|
+
required: boolean;
|
|
325
333
|
source: "user_query" | "session";
|
|
326
334
|
default?: string | number | boolean | undefined;
|
|
335
|
+
pattern?: string | undefined;
|
|
327
336
|
}[];
|
|
328
|
-
description: string;
|
|
329
337
|
returns: string[];
|
|
330
338
|
resolver: {
|
|
331
339
|
type: "api";
|
|
@@ -364,14 +372,15 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
364
372
|
capabilities: {
|
|
365
373
|
name: string;
|
|
366
374
|
id: string;
|
|
375
|
+
description: string;
|
|
367
376
|
params: {
|
|
368
377
|
name: string;
|
|
369
|
-
required: boolean;
|
|
370
378
|
description: string;
|
|
379
|
+
required: boolean;
|
|
371
380
|
source: "user_query" | "session";
|
|
372
381
|
default?: string | number | boolean | undefined;
|
|
382
|
+
pattern?: string | undefined;
|
|
373
383
|
}[];
|
|
374
|
-
description: string;
|
|
375
384
|
returns: string[];
|
|
376
385
|
resolver: {
|
|
377
386
|
type: "api";
|
|
@@ -410,14 +419,15 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
410
419
|
capabilities: {
|
|
411
420
|
name: string;
|
|
412
421
|
id: string;
|
|
422
|
+
description: string;
|
|
413
423
|
params: {
|
|
414
424
|
name: string;
|
|
415
|
-
required: boolean;
|
|
416
425
|
description: string;
|
|
426
|
+
required: boolean;
|
|
417
427
|
source: "user_query" | "session";
|
|
418
428
|
default?: string | number | boolean | undefined;
|
|
429
|
+
pattern?: string | undefined;
|
|
419
430
|
}[];
|
|
420
|
-
description: string;
|
|
421
431
|
returns: string[];
|
|
422
432
|
resolver: {
|
|
423
433
|
type: "api";
|
|
@@ -456,14 +466,15 @@ export declare const CapmanConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
456
466
|
capabilities: {
|
|
457
467
|
name: string;
|
|
458
468
|
id: string;
|
|
469
|
+
description: string;
|
|
459
470
|
params: {
|
|
460
471
|
name: string;
|
|
461
|
-
required: boolean;
|
|
462
472
|
description: string;
|
|
473
|
+
required: boolean;
|
|
463
474
|
source: "user_query" | "session";
|
|
464
475
|
default?: string | number | boolean | undefined;
|
|
476
|
+
pattern?: string | undefined;
|
|
465
477
|
}[];
|
|
466
|
-
description: string;
|
|
467
478
|
returns: string[];
|
|
468
479
|
resolver: {
|
|
469
480
|
type: "api";
|
|
@@ -513,18 +524,21 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
513
524
|
required: z.ZodBoolean;
|
|
514
525
|
source: z.ZodEnum<["user_query", "session"]>;
|
|
515
526
|
default: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
527
|
+
pattern: z.ZodOptional<z.ZodString>;
|
|
516
528
|
}, "strip", z.ZodTypeAny, {
|
|
517
529
|
name: string;
|
|
518
|
-
required: boolean;
|
|
519
530
|
description: string;
|
|
531
|
+
required: boolean;
|
|
520
532
|
source: "user_query" | "session";
|
|
521
533
|
default?: string | number | boolean | undefined;
|
|
534
|
+
pattern?: string | undefined;
|
|
522
535
|
}, {
|
|
523
536
|
name: string;
|
|
524
|
-
required: boolean;
|
|
525
537
|
description: string;
|
|
538
|
+
required: boolean;
|
|
526
539
|
source: "user_query" | "session";
|
|
527
540
|
default?: string | number | boolean | undefined;
|
|
541
|
+
pattern?: string | undefined;
|
|
528
542
|
}>, "many">;
|
|
529
543
|
returns: z.ZodArray<z.ZodString, "many">;
|
|
530
544
|
resolver: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
@@ -647,14 +661,15 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
647
661
|
}, "strip", z.ZodTypeAny, {
|
|
648
662
|
name: string;
|
|
649
663
|
id: string;
|
|
664
|
+
description: string;
|
|
650
665
|
params: {
|
|
651
666
|
name: string;
|
|
652
|
-
required: boolean;
|
|
653
667
|
description: string;
|
|
668
|
+
required: boolean;
|
|
654
669
|
source: "user_query" | "session";
|
|
655
670
|
default?: string | number | boolean | undefined;
|
|
671
|
+
pattern?: string | undefined;
|
|
656
672
|
}[];
|
|
657
|
-
description: string;
|
|
658
673
|
returns: string[];
|
|
659
674
|
resolver: {
|
|
660
675
|
type: "api";
|
|
@@ -689,14 +704,15 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
689
704
|
}, {
|
|
690
705
|
name: string;
|
|
691
706
|
id: string;
|
|
707
|
+
description: string;
|
|
692
708
|
params: {
|
|
693
709
|
name: string;
|
|
694
|
-
required: boolean;
|
|
695
710
|
description: string;
|
|
711
|
+
required: boolean;
|
|
696
712
|
source: "user_query" | "session";
|
|
697
713
|
default?: string | number | boolean | undefined;
|
|
714
|
+
pattern?: string | undefined;
|
|
698
715
|
}[];
|
|
699
|
-
description: string;
|
|
700
716
|
returns: string[];
|
|
701
717
|
resolver: {
|
|
702
718
|
type: "api";
|
|
@@ -735,14 +751,15 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
735
751
|
capabilities: {
|
|
736
752
|
name: string;
|
|
737
753
|
id: string;
|
|
754
|
+
description: string;
|
|
738
755
|
params: {
|
|
739
756
|
name: string;
|
|
740
|
-
required: boolean;
|
|
741
757
|
description: string;
|
|
758
|
+
required: boolean;
|
|
742
759
|
source: "user_query" | "session";
|
|
743
760
|
default?: string | number | boolean | undefined;
|
|
761
|
+
pattern?: string | undefined;
|
|
744
762
|
}[];
|
|
745
|
-
description: string;
|
|
746
763
|
returns: string[];
|
|
747
764
|
resolver: {
|
|
748
765
|
type: "api";
|
|
@@ -782,14 +799,15 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
782
799
|
capabilities: {
|
|
783
800
|
name: string;
|
|
784
801
|
id: string;
|
|
802
|
+
description: string;
|
|
785
803
|
params: {
|
|
786
804
|
name: string;
|
|
787
|
-
required: boolean;
|
|
788
805
|
description: string;
|
|
806
|
+
required: boolean;
|
|
789
807
|
source: "user_query" | "session";
|
|
790
808
|
default?: string | number | boolean | undefined;
|
|
809
|
+
pattern?: string | undefined;
|
|
791
810
|
}[];
|
|
792
|
-
description: string;
|
|
793
811
|
returns: string[];
|
|
794
812
|
resolver: {
|
|
795
813
|
type: "api";
|
package/dist/esm/schema.js
CHANGED
|
@@ -6,6 +6,7 @@ const CapabilityParamSchema = z.object({
|
|
|
6
6
|
required: z.boolean(),
|
|
7
7
|
source: z.enum(['user_query', 'session']),
|
|
8
8
|
default: z.union([z.string(), z.number(), z.boolean()]).optional(),
|
|
9
|
+
pattern: z.string().optional(),
|
|
9
10
|
});
|
|
10
11
|
// ─── Resolver Schemas ─────────────────────────────────────────────────────────
|
|
11
12
|
const ApiResolverSchema = z.object({
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -5,7 +5,13 @@ export interface CapabilityParam {
|
|
|
5
5
|
description: string;
|
|
6
6
|
required: boolean;
|
|
7
7
|
source: 'user_query' | 'session';
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Optional extraction hint. Either a named type or an example template.
|
|
10
|
+
* Named types: 'email' | 'date' | 'orderId' | 'url'
|
|
11
|
+
* Example template: "order {paramName}" — extracts token after "order"
|
|
12
|
+
* When provided, pattern matching runs before keyword heuristics.
|
|
13
|
+
*/
|
|
14
|
+
pattern?: string;
|
|
9
15
|
}
|
|
10
16
|
export interface ApiResolver {
|
|
11
17
|
type: 'api';
|
package/package.json
CHANGED