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.
Files changed (41) hide show
  1. package/bin/capman.js +151 -5
  2. package/dist/cjs/cache.d.ts +42 -0
  3. package/dist/cjs/cache.d.ts.map +1 -0
  4. package/dist/cjs/cache.js +181 -0
  5. package/dist/cjs/cache.js.map +1 -0
  6. package/dist/cjs/engine.d.ts +82 -0
  7. package/dist/cjs/engine.d.ts.map +1 -0
  8. package/dist/cjs/engine.js +154 -0
  9. package/dist/cjs/engine.js.map +1 -0
  10. package/dist/cjs/generator.js +2 -1
  11. package/dist/cjs/generator.js.map +1 -1
  12. package/dist/cjs/index.d.ts +7 -1
  13. package/dist/cjs/index.d.ts.map +1 -1
  14. package/dist/cjs/index.js +13 -1
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/learning.d.ts +56 -0
  17. package/dist/cjs/learning.d.ts.map +1 -0
  18. package/dist/cjs/learning.js +184 -0
  19. package/dist/cjs/learning.js.map +1 -0
  20. package/dist/cjs/matcher.d.ts.map +1 -1
  21. package/dist/cjs/matcher.js +27 -5
  22. package/dist/cjs/matcher.js.map +1 -1
  23. package/dist/cjs/resolver.d.ts.map +1 -1
  24. package/dist/cjs/resolver.js +36 -4
  25. package/dist/cjs/resolver.js.map +1 -1
  26. package/dist/cjs/schema.d.ts +10 -10
  27. package/dist/cjs/types.d.ts +12 -5
  28. package/dist/cjs/types.d.ts.map +1 -1
  29. package/dist/cjs/version.d.ts +2 -0
  30. package/dist/cjs/version.d.ts.map +1 -0
  31. package/dist/cjs/version.js +6 -0
  32. package/dist/cjs/version.js.map +1 -0
  33. package/dist/esm/cache.js +141 -0
  34. package/dist/esm/engine.js +149 -0
  35. package/dist/esm/generator.js +2 -1
  36. package/dist/esm/index.js +6 -0
  37. package/dist/esm/learning.js +145 -0
  38. package/dist/esm/matcher.js +27 -5
  39. package/dist/esm/resolver.js +36 -4
  40. package/dist/esm/version.js +2 -0
  41. package/package.json +18 -12
@@ -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
- `to `, `from `, `with `,
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 keywords) {
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
- const token = after.split(/\s+/)[0];
90
- if (token && token.length > 1) {
91
- extracted = token.replace(/[^a-zA-Z0-9-_@.]/g, '');
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
  }
@@ -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 { success: true, resolverType: 'api', apiCalls };
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 failed = responses.find(r => !r.ok);
117
- if (failed) {
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
- return { success: true, resolverType: 'api', apiCalls };
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
  }
@@ -0,0 +1,2 @@
1
+ // Auto-generated by scripts/version.js — do not edit manually
2
+ export const VERSION = '0.3.0';
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "capman",
3
- "version": "0.2.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": "./dist/esm/index.js",
11
- "require": "./dist/cjs/index.js",
12
- "types": "./dist/cjs/index.d.ts"
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
- "build:cjs": "tsc --project tsconfig.json",
26
- "build:esm": "tsc --project tsconfig.esm.json",
27
- "build": "pnpm run build:cjs && pnpm run build:esm",
28
- "dev": "tsc --watch",
29
- "example": "tsx examples/basic.ts",
30
- "validate": "node bin/capman.js validate",
31
- "inspect": "node bin/capman.js inspect",
32
- "test": "vitest run"
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",