capman 0.2.0 → 0.3.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/bin/capman.js +151 -5
- package/dist/cjs/cache.d.ts +42 -0
- package/dist/cjs/cache.d.ts.map +1 -0
- package/dist/cjs/cache.js +181 -0
- package/dist/cjs/cache.js.map +1 -0
- package/dist/cjs/engine.d.ts +82 -0
- package/dist/cjs/engine.d.ts.map +1 -0
- package/dist/cjs/engine.js +154 -0
- package/dist/cjs/engine.js.map +1 -0
- package/dist/cjs/generator.js +2 -1
- package/dist/cjs/generator.js.map +1 -1
- package/dist/cjs/index.d.ts +7 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +13 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/learning.d.ts +56 -0
- package/dist/cjs/learning.d.ts.map +1 -0
- package/dist/cjs/learning.js +184 -0
- package/dist/cjs/learning.js.map +1 -0
- package/dist/cjs/matcher.d.ts.map +1 -1
- package/dist/cjs/matcher.js +27 -5
- package/dist/cjs/matcher.js.map +1 -1
- package/dist/cjs/resolver.d.ts.map +1 -1
- package/dist/cjs/resolver.js +36 -4
- package/dist/cjs/resolver.js.map +1 -1
- package/dist/cjs/schema.d.ts +10 -10
- package/dist/cjs/types.d.ts +12 -5
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/version.d.ts +2 -0
- package/dist/cjs/version.d.ts.map +1 -0
- package/dist/cjs/version.js +6 -0
- package/dist/cjs/version.js.map +1 -0
- package/dist/esm/cache.js +141 -0
- package/dist/esm/engine.js +149 -0
- package/dist/esm/generator.js +2 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/learning.js +145 -0
- package/dist/esm/matcher.js +27 -5
- package/dist/esm/resolver.js +36 -4
- package/dist/esm/version.js +2 -0
- package/package.json +18 -12
package/dist/esm/matcher.js
CHANGED
|
@@ -76,19 +76,41 @@ function extractParams(query, cap) {
|
|
|
76
76
|
// e.g. "profile for johndoe" → johndoe
|
|
77
77
|
// "articles by jane" → jane
|
|
78
78
|
// "tag javascript" → javascript
|
|
79
|
+
// Use param name and description as hints for what to look for
|
|
80
|
+
const paramHints = [param.name, ...param.description.toLowerCase().split(/\s+/)]
|
|
81
|
+
.filter(w => w.length > 2);
|
|
82
|
+
// Try keyword-based extraction first
|
|
79
83
|
const keywords = [
|
|
80
84
|
`for `, `by `, `about `, `named `, `called `,
|
|
81
85
|
`tag `, `user `, `author `, `slug `, `id `,
|
|
82
|
-
`
|
|
86
|
+
`from `, `with `,
|
|
83
87
|
];
|
|
88
|
+
// For nav params — look for destination after navigation verbs
|
|
89
|
+
const navKeywords = [`to `, `open `, `show `];
|
|
90
|
+
const isNavParam = param.name === 'destination' ||
|
|
91
|
+
param.description.toLowerCase().includes('screen') ||
|
|
92
|
+
param.description.toLowerCase().includes('page');
|
|
93
|
+
const activeKeywords = isNavParam
|
|
94
|
+
? [...navKeywords, ...keywords]
|
|
95
|
+
: keywords;
|
|
84
96
|
let extracted = null;
|
|
85
|
-
for (const kw of
|
|
97
|
+
for (const kw of activeKeywords) {
|
|
86
98
|
const idx = q.indexOf(kw);
|
|
87
99
|
if (idx !== -1) {
|
|
88
100
|
const after = query.slice(idx + kw.length).trim();
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
101
|
+
// Get remaining words, filter stopwords, take first meaningful one
|
|
102
|
+
const tokens = after.split(/\s+/)
|
|
103
|
+
.map(t => t.replace(/[^a-zA-Z0-9-_@.]/g, ''))
|
|
104
|
+
.filter(t => t.length > 1 && !STOPWORDS.has(t.toLowerCase()));
|
|
105
|
+
if (tokens.length > 0) {
|
|
106
|
+
// For IDs and numbers — single token is correct
|
|
107
|
+
const isIdParam = param.name === 'id' ||
|
|
108
|
+
param.name.endsWith('_id') ||
|
|
109
|
+
param.name.endsWith('Id') ||
|
|
110
|
+
/^\s*\w+\s+id\b/i.test(param.description) ||
|
|
111
|
+
/^id\b/i.test(param.description);
|
|
112
|
+
// For names, products, destinations — grab multi-word phrase
|
|
113
|
+
extracted = (isIdParam || isNavParam) ? tokens[0] : tokens.join('-').toLowerCase();
|
|
92
114
|
break;
|
|
93
115
|
}
|
|
94
116
|
}
|
package/dist/esm/resolver.js
CHANGED
|
@@ -87,13 +87,19 @@ export async function resolve(matchResult, params = {}, options = {}) {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
async function resolveApi(resolver, params, options) {
|
|
90
|
+
const startTime = Date.now();
|
|
90
91
|
const apiCalls = resolver.endpoints.map(endpoint => ({
|
|
91
92
|
method: endpoint.method,
|
|
92
93
|
url: buildUrl(options.baseUrl ?? '', endpoint.path, params),
|
|
93
94
|
params,
|
|
94
95
|
}));
|
|
95
96
|
if (options.dryRun) {
|
|
96
|
-
return {
|
|
97
|
+
return {
|
|
98
|
+
success: true,
|
|
99
|
+
resolverType: 'api',
|
|
100
|
+
apiCalls,
|
|
101
|
+
durationMs: Date.now() - startTime,
|
|
102
|
+
};
|
|
97
103
|
}
|
|
98
104
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
99
105
|
if (!fetchFn) {
|
|
@@ -101,6 +107,7 @@ async function resolveApi(resolver, params, options) {
|
|
|
101
107
|
success: true,
|
|
102
108
|
resolverType: 'api',
|
|
103
109
|
apiCalls,
|
|
110
|
+
durationMs: Date.now() - startTime,
|
|
104
111
|
error: 'No fetch available — returning call plan only',
|
|
105
112
|
};
|
|
106
113
|
}
|
|
@@ -113,22 +120,47 @@ async function resolveApi(resolver, params, options) {
|
|
|
113
120
|
: undefined,
|
|
114
121
|
})));
|
|
115
122
|
// Check for HTTP errors
|
|
116
|
-
const
|
|
117
|
-
if (
|
|
123
|
+
const failedIdx = responses.findIndex(r => !r.ok);
|
|
124
|
+
if (failedIdx !== -1) {
|
|
125
|
+
const failed = responses[failedIdx];
|
|
118
126
|
return {
|
|
119
127
|
success: false,
|
|
120
128
|
resolverType: 'api',
|
|
121
129
|
apiCalls,
|
|
130
|
+
durationMs: Date.now() - startTime,
|
|
122
131
|
error: `API request failed: ${failed.status} ${failed.statusText}`,
|
|
123
132
|
};
|
|
124
133
|
}
|
|
125
|
-
|
|
134
|
+
// Parse response bodies
|
|
135
|
+
const enrichedCalls = await Promise.all(responses.map(async (res, i) => {
|
|
136
|
+
let data = undefined;
|
|
137
|
+
try {
|
|
138
|
+
const text = await res.text();
|
|
139
|
+
data = text ? JSON.parse(text) : undefined;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Non-JSON response — leave data undefined
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
...apiCalls[i],
|
|
146
|
+
status: res.status,
|
|
147
|
+
data,
|
|
148
|
+
};
|
|
149
|
+
}));
|
|
150
|
+
logger.debug(`API calls completed in ${Date.now() - startTime}ms`);
|
|
151
|
+
return {
|
|
152
|
+
success: true,
|
|
153
|
+
resolverType: 'api',
|
|
154
|
+
apiCalls: enrichedCalls,
|
|
155
|
+
durationMs: Date.now() - startTime,
|
|
156
|
+
};
|
|
126
157
|
}
|
|
127
158
|
catch (err) {
|
|
128
159
|
return {
|
|
129
160
|
success: false,
|
|
130
161
|
resolverType: 'api',
|
|
131
162
|
apiCalls,
|
|
163
|
+
durationMs: Date.now() - startTime,
|
|
132
164
|
error: err instanceof Error ? err.message : String(err),
|
|
133
165
|
};
|
|
134
166
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capman",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Capability Manifest Engine — let AI agents interact with your app without navigating the UI",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
7
7
|
"types": "./dist/cjs/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"import":
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/cjs/index.d.ts",
|
|
12
|
+
"default": "./dist/esm/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/cjs/index.d.ts",
|
|
16
|
+
"default": "./dist/cjs/index.js"
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
},
|
|
15
20
|
"bin": {
|
|
@@ -22,14 +27,15 @@
|
|
|
22
27
|
"CONTRIBUTING.md"
|
|
23
28
|
],
|
|
24
29
|
"scripts": {
|
|
25
|
-
"
|
|
26
|
-
"build:
|
|
27
|
-
"build":
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
30
|
+
"prebuild": "node scripts/version.js",
|
|
31
|
+
"build:cjs": "tsc --project tsconfig.json",
|
|
32
|
+
"build:esm": "tsc --project tsconfig.esm.json",
|
|
33
|
+
"build": "pnpm run build:cjs && pnpm run build:esm",
|
|
34
|
+
"dev": "tsc --watch",
|
|
35
|
+
"example": "tsx examples/basic.ts",
|
|
36
|
+
"validate": "node bin/capman.js validate",
|
|
37
|
+
"inspect": "node bin/capman.js inspect",
|
|
38
|
+
"test": "vitest run"
|
|
33
39
|
},
|
|
34
40
|
"keywords": [
|
|
35
41
|
"ai",
|