@apitap/core 1.7.0 → 1.7.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.
- package/dist/skill/search.d.ts +2 -1
- package/dist/skill/search.js +22 -3
- package/dist/skill/search.js.map +1 -1
- package/package.json +1 -1
- package/src/skill/search.ts +23 -3
package/dist/skill/search.d.ts
CHANGED
|
@@ -9,12 +9,13 @@ export interface SearchResult {
|
|
|
9
9
|
export interface SearchResponse {
|
|
10
10
|
found: boolean;
|
|
11
11
|
results?: SearchResult[];
|
|
12
|
+
summary?: string;
|
|
12
13
|
suggestion?: string;
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
16
|
* Search skill files for endpoints matching a query.
|
|
16
17
|
* Uses the search index for sub-second results.
|
|
17
18
|
* Matches against domain names, endpoint IDs, and endpoint paths.
|
|
18
|
-
* Query terms are matched case-insensitively.
|
|
19
|
+
* Query terms are matched case-insensitively with prefix matching.
|
|
19
20
|
*/
|
|
20
21
|
export declare function searchSkills(query: string, skillsDir?: string): Promise<SearchResponse>;
|
package/dist/skill/search.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
// src/skill/search.ts
|
|
2
2
|
import { ensureIndex } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Check if a search term matches a target string.
|
|
5
|
+
* Supports prefix matching: "payment" matches "payments", "pay" matches "payouts".
|
|
6
|
+
*/
|
|
7
|
+
function termMatches(term, text) {
|
|
8
|
+
// Check if any word in the text starts with the term (prefix match)
|
|
9
|
+
// Split on word boundaries: slashes, hyphens, underscores, dots, spaces
|
|
10
|
+
const words = text.split(/[\s/\-_.]+/);
|
|
11
|
+
for (const word of words) {
|
|
12
|
+
if (word.startsWith(term))
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
// Also check plain substring for multi-word or partial path matches
|
|
16
|
+
return text.includes(term);
|
|
17
|
+
}
|
|
3
18
|
/**
|
|
4
19
|
* Search skill files for endpoints matching a query.
|
|
5
20
|
* Uses the search index for sub-second results.
|
|
6
21
|
* Matches against domain names, endpoint IDs, and endpoint paths.
|
|
7
|
-
* Query terms are matched case-insensitively.
|
|
22
|
+
* Query terms are matched case-insensitively with prefix matching.
|
|
8
23
|
*/
|
|
9
24
|
export async function searchSkills(query, skillsDir) {
|
|
10
25
|
const index = await ensureIndex(skillsDir);
|
|
@@ -17,6 +32,7 @@ export async function searchSkills(query, skillsDir) {
|
|
|
17
32
|
}
|
|
18
33
|
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
19
34
|
const results = [];
|
|
35
|
+
const matchedDomains = new Set();
|
|
20
36
|
for (const [domain, entry] of Object.entries(index.domains)) {
|
|
21
37
|
const domainLower = domain.toLowerCase();
|
|
22
38
|
for (const ep of entry.endpoints) {
|
|
@@ -24,8 +40,9 @@ export async function searchSkills(query, skillsDir) {
|
|
|
24
40
|
const pathLower = ep.path.toLowerCase();
|
|
25
41
|
const methodLower = ep.method.toLowerCase();
|
|
26
42
|
const searchText = `${domainLower} ${endpointIdLower} ${pathLower} ${methodLower}`;
|
|
27
|
-
const allMatch = terms.every(term =>
|
|
43
|
+
const allMatch = terms.every(term => termMatches(term, searchText));
|
|
28
44
|
if (allMatch) {
|
|
45
|
+
matchedDomains.add(domain);
|
|
29
46
|
results.push({
|
|
30
47
|
domain,
|
|
31
48
|
endpointId: ep.id,
|
|
@@ -41,9 +58,11 @@ export async function searchSkills(query, skillsDir) {
|
|
|
41
58
|
const domains = Object.keys(index.domains).join(', ');
|
|
42
59
|
return {
|
|
43
60
|
found: false,
|
|
61
|
+
summary: '0 endpoints across 0 domains',
|
|
44
62
|
suggestion: `No matches for "${query}". Available domains: ${domains}`,
|
|
45
63
|
};
|
|
46
64
|
}
|
|
47
|
-
|
|
65
|
+
const summary = `${results.length} endpoints across ${matchedDomains.size} domain${matchedDomains.size === 1 ? '' : 's'}`;
|
|
66
|
+
return { found: true, results, summary };
|
|
48
67
|
}
|
|
49
68
|
//# sourceMappingURL=search.js.map
|
package/dist/skill/search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/skill/search.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/skill/search.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apitap/core",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Intercept web API traffic during browsing. Generate portable skill files so AI agents can call APIs directly instead of scraping.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/src/skill/search.ts
CHANGED
|
@@ -13,14 +13,30 @@ export interface SearchResult {
|
|
|
13
13
|
export interface SearchResponse {
|
|
14
14
|
found: boolean;
|
|
15
15
|
results?: SearchResult[];
|
|
16
|
+
summary?: string;
|
|
16
17
|
suggestion?: string;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Check if a search term matches a target string.
|
|
22
|
+
* Supports prefix matching: "payment" matches "payments", "pay" matches "payouts".
|
|
23
|
+
*/
|
|
24
|
+
function termMatches(term: string, text: string): boolean {
|
|
25
|
+
// Check if any word in the text starts with the term (prefix match)
|
|
26
|
+
// Split on word boundaries: slashes, hyphens, underscores, dots, spaces
|
|
27
|
+
const words = text.split(/[\s/\-_.]+/);
|
|
28
|
+
for (const word of words) {
|
|
29
|
+
if (word.startsWith(term)) return true;
|
|
30
|
+
}
|
|
31
|
+
// Also check plain substring for multi-word or partial path matches
|
|
32
|
+
return text.includes(term);
|
|
33
|
+
}
|
|
34
|
+
|
|
19
35
|
/**
|
|
20
36
|
* Search skill files for endpoints matching a query.
|
|
21
37
|
* Uses the search index for sub-second results.
|
|
22
38
|
* Matches against domain names, endpoint IDs, and endpoint paths.
|
|
23
|
-
* Query terms are matched case-insensitively.
|
|
39
|
+
* Query terms are matched case-insensitively with prefix matching.
|
|
24
40
|
*/
|
|
25
41
|
export async function searchSkills(
|
|
26
42
|
query: string,
|
|
@@ -38,6 +54,7 @@ export async function searchSkills(
|
|
|
38
54
|
|
|
39
55
|
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
40
56
|
const results: SearchResult[] = [];
|
|
57
|
+
const matchedDomains = new Set<string>();
|
|
41
58
|
|
|
42
59
|
for (const [domain, entry] of Object.entries(index.domains)) {
|
|
43
60
|
const domainLower = domain.toLowerCase();
|
|
@@ -48,9 +65,10 @@ export async function searchSkills(
|
|
|
48
65
|
const methodLower = ep.method.toLowerCase();
|
|
49
66
|
|
|
50
67
|
const searchText = `${domainLower} ${endpointIdLower} ${pathLower} ${methodLower}`;
|
|
51
|
-
const allMatch = terms.every(term =>
|
|
68
|
+
const allMatch = terms.every(term => termMatches(term, searchText));
|
|
52
69
|
|
|
53
70
|
if (allMatch) {
|
|
71
|
+
matchedDomains.add(domain);
|
|
54
72
|
results.push({
|
|
55
73
|
domain,
|
|
56
74
|
endpointId: ep.id,
|
|
@@ -67,9 +85,11 @@ export async function searchSkills(
|
|
|
67
85
|
const domains = Object.keys(index.domains).join(', ');
|
|
68
86
|
return {
|
|
69
87
|
found: false,
|
|
88
|
+
summary: '0 endpoints across 0 domains',
|
|
70
89
|
suggestion: `No matches for "${query}". Available domains: ${domains}`,
|
|
71
90
|
};
|
|
72
91
|
}
|
|
73
92
|
|
|
74
|
-
|
|
93
|
+
const summary = `${results.length} endpoints across ${matchedDomains.size} domain${matchedDomains.size === 1 ? '' : 's'}`;
|
|
94
|
+
return { found: true, results, summary };
|
|
75
95
|
}
|