uicontract 0.1.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/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/bin/uic.d.ts +9 -0
- package/dist/bin/uic.d.ts.map +1 -0
- package/dist/bin/uic.js +87 -0
- package/dist/bin/uic.js.map +1 -0
- package/dist/commands/annotate.d.ts +21 -0
- package/dist/commands/annotate.d.ts.map +1 -0
- package/dist/commands/annotate.js +236 -0
- package/dist/commands/annotate.js.map +1 -0
- package/dist/commands/describe.d.ts +19 -0
- package/dist/commands/describe.d.ts.map +1 -0
- package/dist/commands/describe.js +146 -0
- package/dist/commands/describe.js.map +1 -0
- package/dist/commands/diff.d.ts +57 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +404 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/find.d.ts +34 -0
- package/dist/commands/find.d.ts.map +1 -0
- package/dist/commands/find.js +229 -0
- package/dist/commands/find.js.map +1 -0
- package/dist/commands/index.d.ts +18 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +11 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/list.d.ts +23 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +238 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/name.d.ts +21 -0
- package/dist/commands/name.d.ts.map +1 -0
- package/dist/commands/name.js +154 -0
- package/dist/commands/name.js.map +1 -0
- package/dist/commands/scan.d.ts +32 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +294 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/fuzzy-match.d.ts +45 -0
- package/dist/fuzzy-match.d.ts.map +1 -0
- package/dist/fuzzy-match.js +134 -0
- package/dist/fuzzy-match.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fuzzy string matching utilities for the `uic find` command.
|
|
3
|
+
*
|
|
4
|
+
* Implements Levenshtein distance and word-level fuzzy matching so that
|
|
5
|
+
* queries such as "pase subscribtion" can find "pause-subscription".
|
|
6
|
+
*
|
|
7
|
+
* No external dependencies -- everything is computed inline.
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Levenshtein distance
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* Compute the Levenshtein edit distance between two strings.
|
|
14
|
+
* Uses a single-row dynamic-programming approach (O(min(a,b)) space).
|
|
15
|
+
*/
|
|
16
|
+
export function levenshtein(a, b) {
|
|
17
|
+
if (a === b)
|
|
18
|
+
return 0;
|
|
19
|
+
if (a.length === 0)
|
|
20
|
+
return b.length;
|
|
21
|
+
if (b.length === 0)
|
|
22
|
+
return a.length;
|
|
23
|
+
// Ensure `a` is the shorter string so the row array is small.
|
|
24
|
+
if (a.length > b.length) {
|
|
25
|
+
[a, b] = [b, a];
|
|
26
|
+
}
|
|
27
|
+
const aLen = a.length;
|
|
28
|
+
const bLen = b.length;
|
|
29
|
+
// Previous row of distances (indices 0..aLen).
|
|
30
|
+
const row = Array.from({ length: aLen + 1 }, (_, i) => i);
|
|
31
|
+
for (let j = 1; j <= bLen; j++) {
|
|
32
|
+
let prev = j;
|
|
33
|
+
for (let i = 1; i <= aLen; i++) {
|
|
34
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
35
|
+
const rowPrev = row[i];
|
|
36
|
+
const rowCurr = row[i - 1];
|
|
37
|
+
const val = Math.min(rowPrev + 1, prev + 1, rowCurr + cost);
|
|
38
|
+
row[i - 1] = prev;
|
|
39
|
+
prev = val;
|
|
40
|
+
}
|
|
41
|
+
row[aLen] = prev;
|
|
42
|
+
}
|
|
43
|
+
return row[aLen];
|
|
44
|
+
}
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Tokenisation helpers
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
/**
|
|
49
|
+
* Split a string into lowercase tokens. Handles camelCase, PascalCase,
|
|
50
|
+
* kebab-case, snake_case, dot.separated, and slash/separated paths.
|
|
51
|
+
*
|
|
52
|
+
* Examples:
|
|
53
|
+
* "handlePauseSubscription" => ["handle", "pause", "subscription"]
|
|
54
|
+
* "pause-subscription" => ["pause", "subscription"]
|
|
55
|
+
* "settings.billing" => ["settings", "billing"]
|
|
56
|
+
*/
|
|
57
|
+
export function tokenize(str) {
|
|
58
|
+
const spaced = str.replace(/([a-z])([A-Z])/g, '$1 $2');
|
|
59
|
+
return spaced
|
|
60
|
+
.split(/[\s\-_./\\:]+/)
|
|
61
|
+
.map((t) => t.toLowerCase())
|
|
62
|
+
.filter((t) => t.length > 0);
|
|
63
|
+
}
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Scoring
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
const PERFECT_SCORE = 1.0;
|
|
68
|
+
const DEFAULT_THRESHOLD = 0.3;
|
|
69
|
+
/**
|
|
70
|
+
* Compute a similarity score (0..1) between two individual tokens.
|
|
71
|
+
* 1.0 = identical, 0.0 = completely different.
|
|
72
|
+
*/
|
|
73
|
+
function tokenSimilarity(a, b) {
|
|
74
|
+
if (a === b)
|
|
75
|
+
return PERFECT_SCORE;
|
|
76
|
+
if (a.includes(b) || b.includes(a)) {
|
|
77
|
+
const longer = Math.max(a.length, b.length);
|
|
78
|
+
const shorter = Math.min(a.length, b.length);
|
|
79
|
+
return 0.8 + 0.2 * (shorter / longer);
|
|
80
|
+
}
|
|
81
|
+
const maxLen = Math.max(a.length, b.length);
|
|
82
|
+
if (maxLen === 0)
|
|
83
|
+
return PERFECT_SCORE;
|
|
84
|
+
const dist = levenshtein(a, b);
|
|
85
|
+
return 1 - dist / maxLen;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Score how well a query matches a single target field.
|
|
89
|
+
*
|
|
90
|
+
* Strategy:
|
|
91
|
+
* 1. Exact substring match on the raw field => high score.
|
|
92
|
+
* 2. Tokenise both query and field, then find the best token-level
|
|
93
|
+
* alignment (each query token matched to the best field token).
|
|
94
|
+
*
|
|
95
|
+
* Returns a score in [0, 1]. Higher is better.
|
|
96
|
+
*/
|
|
97
|
+
export function scoreField(query, field) {
|
|
98
|
+
const qLower = query.toLowerCase();
|
|
99
|
+
const fLower = field.toLowerCase();
|
|
100
|
+
if (fLower.includes(qLower)) {
|
|
101
|
+
return 0.9 + 0.1 * (qLower.length / fLower.length);
|
|
102
|
+
}
|
|
103
|
+
const qTokens = tokenize(query);
|
|
104
|
+
const fTokens = tokenize(field);
|
|
105
|
+
if (qTokens.length === 0 || fTokens.length === 0)
|
|
106
|
+
return 0;
|
|
107
|
+
let totalSim = 0;
|
|
108
|
+
for (const qt of qTokens) {
|
|
109
|
+
let bestSim = 0;
|
|
110
|
+
for (const ft of fTokens) {
|
|
111
|
+
const sim = tokenSimilarity(qt, ft);
|
|
112
|
+
if (sim > bestSim)
|
|
113
|
+
bestSim = sim;
|
|
114
|
+
}
|
|
115
|
+
totalSim += bestSim;
|
|
116
|
+
}
|
|
117
|
+
return (totalSim / qTokens.length) * 0.85;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Score a set of fields against a search query using fuzzy matching.
|
|
121
|
+
* Returns the best score across all fields and whether it exceeds the threshold.
|
|
122
|
+
*/
|
|
123
|
+
export function fuzzyMatchElement(fields, query, threshold = DEFAULT_THRESHOLD) {
|
|
124
|
+
let bestScore = 0;
|
|
125
|
+
for (const field of fields) {
|
|
126
|
+
if (field === null)
|
|
127
|
+
continue;
|
|
128
|
+
const s = scoreField(query, field);
|
|
129
|
+
if (s > bestScore)
|
|
130
|
+
bestScore = s;
|
|
131
|
+
}
|
|
132
|
+
return { score: bestScore, matches: bestScore >= threshold };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=fuzzy-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fuzzy-match.js","sourceRoot":"","sources":["../src/fuzzy-match.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "uicontract",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI tool that makes web app UIs machine-readable for AI agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "UIC Contributors",
|
|
8
|
+
"homepage": "https://github.com/sherifkozman/uicontract",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/sherifkozman/uicontract.git",
|
|
12
|
+
"directory": "packages/cli"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/sherifkozman/uicontract/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"uic",
|
|
19
|
+
"ui-contracts",
|
|
20
|
+
"cli",
|
|
21
|
+
"agent-id",
|
|
22
|
+
"data-agent-id",
|
|
23
|
+
"manifest",
|
|
24
|
+
"accessibility",
|
|
25
|
+
"testing",
|
|
26
|
+
"automation"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"bin": {
|
|
40
|
+
"uicontract": "./dist/bin/uic.js"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist",
|
|
47
|
+
"LICENSE",
|
|
48
|
+
"README.md"
|
|
49
|
+
],
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@uicontract/parser-react": "0.1.0",
|
|
52
|
+
"@uicontract/core": "0.1.0",
|
|
53
|
+
"@uicontract/parser-vue": "0.1.0",
|
|
54
|
+
"@uicontract/namer": "0.1.0",
|
|
55
|
+
"@uicontract/annotator": "0.1.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsc -b",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"typecheck": "tsc --noEmit",
|
|
61
|
+
"lint": "eslint src"
|
|
62
|
+
}
|
|
63
|
+
}
|