@vertaaux/cli 0.2.2 → 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/LICENSE +21 -0
- package/README.md +58 -2
- package/dist/auth/device-flow.d.ts.map +1 -1
- package/dist/auth/device-flow.js +46 -14
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +167 -8
- package/dist/commands/client.d.ts +14 -0
- package/dist/commands/client.d.ts.map +1 -0
- package/dist/commands/client.js +362 -0
- package/dist/commands/compare.d.ts +20 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +335 -0
- package/dist/commands/doc.d.ts +18 -0
- package/dist/commands/doc.d.ts.map +1 -0
- package/dist/commands/doc.js +161 -0
- package/dist/commands/download.d.ts.map +1 -1
- package/dist/commands/download.js +9 -8
- package/dist/commands/drift.d.ts +15 -0
- package/dist/commands/drift.d.ts.map +1 -0
- package/dist/commands/drift.js +309 -0
- package/dist/commands/explain.d.ts +14 -33
- package/dist/commands/explain.d.ts.map +1 -1
- package/dist/commands/explain.js +277 -179
- package/dist/commands/fix-plan.d.ts +15 -0
- package/dist/commands/fix-plan.d.ts.map +1 -0
- package/dist/commands/fix-plan.js +182 -0
- package/dist/commands/patch-review.d.ts +14 -0
- package/dist/commands/patch-review.d.ts.map +1 -0
- package/dist/commands/patch-review.js +200 -0
- package/dist/commands/protect.d.ts +16 -0
- package/dist/commands/protect.d.ts.map +1 -0
- package/dist/commands/protect.js +323 -0
- package/dist/commands/release-notes.d.ts +17 -0
- package/dist/commands/release-notes.d.ts.map +1 -0
- package/dist/commands/release-notes.js +145 -0
- package/dist/commands/report.d.ts +15 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +214 -0
- package/dist/commands/suggest.d.ts +18 -0
- package/dist/commands/suggest.d.ts.map +1 -0
- package/dist/commands/suggest.js +152 -0
- package/dist/commands/triage.d.ts +17 -0
- package/dist/commands/triage.d.ts.map +1 -0
- package/dist/commands/triage.js +205 -0
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +8 -7
- package/dist/index.js +62 -25
- package/dist/output/formats.d.ts.map +1 -1
- package/dist/output/formats.js +18 -2
- package/dist/output/human.d.ts +1 -10
- package/dist/output/human.d.ts.map +1 -1
- package/dist/output/human.js +26 -98
- package/dist/policy/sync.d.ts +67 -0
- package/dist/policy/sync.d.ts.map +1 -0
- package/dist/policy/sync.js +147 -0
- package/dist/prompts/command-catalog.d.ts +46 -0
- package/dist/prompts/command-catalog.d.ts.map +1 -0
- package/dist/prompts/command-catalog.js +187 -0
- package/dist/ui/spinner.d.ts +10 -35
- package/dist/ui/spinner.d.ts.map +1 -1
- package/dist/ui/spinner.js +11 -58
- package/dist/ui/table.d.ts +1 -18
- package/dist/ui/table.d.ts.map +1 -1
- package/dist/ui/table.js +56 -163
- package/dist/utils/ai-error.d.ts +48 -0
- package/dist/utils/ai-error.d.ts.map +1 -0
- package/dist/utils/ai-error.js +190 -0
- package/dist/utils/detect-env.d.ts +6 -8
- package/dist/utils/detect-env.d.ts.map +1 -1
- package/dist/utils/detect-env.js +6 -25
- package/dist/utils/stdin.d.ts +50 -0
- package/dist/utils/stdin.d.ts.map +1 -0
- package/dist/utils/stdin.js +93 -0
- package/package.json +11 -7
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy push/pull sync module for VertaaUX CLI.
|
|
3
|
+
*
|
|
4
|
+
* Provides bidirectional sync between local policy files and the server API.
|
|
5
|
+
* Uses the established CLI API patterns (resolveApiBase, getApiKey, apiRequest).
|
|
6
|
+
*
|
|
7
|
+
* Implements POL-10: Policy push/pull sync.
|
|
8
|
+
*/
|
|
9
|
+
import { resolveApiBase, getApiKey, apiRequest } from "../utils/client.js";
|
|
10
|
+
/**
|
|
11
|
+
* Build sync config from CLI config and environment.
|
|
12
|
+
* Uses the established CLI pattern: resolveApiBase + getApiKey.
|
|
13
|
+
*/
|
|
14
|
+
export function buildSyncConfig(cliConfig) {
|
|
15
|
+
return {
|
|
16
|
+
apiBase: resolveApiBase(undefined, undefined),
|
|
17
|
+
apiKey: getApiKey(cliConfig?.apiKey),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Push a local policy file to the server.
|
|
22
|
+
*
|
|
23
|
+
* If a policy with the given name already exists, updates it (with optional
|
|
24
|
+
* optimistic locking via expectedVersion). Otherwise creates a new policy.
|
|
25
|
+
*
|
|
26
|
+
* @param policy - The policy content to push
|
|
27
|
+
* @param config - API connection config
|
|
28
|
+
* @param options - Push options (name, description, force, etc.)
|
|
29
|
+
* @returns Push result with success status, policy ID, and version
|
|
30
|
+
*/
|
|
31
|
+
export async function pushPolicy(policy, config, options) {
|
|
32
|
+
try {
|
|
33
|
+
// First, try to find existing policy by name
|
|
34
|
+
const listData = await apiRequest(config.apiBase, "/policies", { method: "GET" }, config.apiKey);
|
|
35
|
+
const existing = listData.policies?.find((p) => p.name === options.name);
|
|
36
|
+
if (existing) {
|
|
37
|
+
// Update existing policy
|
|
38
|
+
const body = {
|
|
39
|
+
content: policy,
|
|
40
|
+
changeMessage: options.changeMessage || "Pushed from CLI",
|
|
41
|
+
};
|
|
42
|
+
if (options.expectedVersion && !options.force) {
|
|
43
|
+
body.expectedVersion = options.expectedVersion;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const updated = await apiRequest(config.apiBase, `/policies/${existing.id}`, { method: "PUT", body }, config.apiKey);
|
|
47
|
+
return {
|
|
48
|
+
success: true,
|
|
49
|
+
policyId: existing.id,
|
|
50
|
+
version: updated.latestVersion || 0,
|
|
51
|
+
created: false,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
56
|
+
if (message.includes("409")) {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
policyId: existing.id,
|
|
60
|
+
version: existing.latestVersion || 0,
|
|
61
|
+
created: false,
|
|
62
|
+
error: "Policy has been modified on server. Pull latest first, or use --force.",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Create new policy
|
|
70
|
+
const created = await apiRequest(config.apiBase, "/policies", {
|
|
71
|
+
method: "POST",
|
|
72
|
+
body: {
|
|
73
|
+
name: options.name,
|
|
74
|
+
description: options.description,
|
|
75
|
+
content: policy,
|
|
76
|
+
},
|
|
77
|
+
}, config.apiKey);
|
|
78
|
+
return {
|
|
79
|
+
success: true,
|
|
80
|
+
policyId: created.id || "",
|
|
81
|
+
version: 1,
|
|
82
|
+
created: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
policyId: "",
|
|
90
|
+
version: 0,
|
|
91
|
+
created: false,
|
|
92
|
+
error: err instanceof Error ? err.message : String(err),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Pull a policy from the server.
|
|
98
|
+
*
|
|
99
|
+
* Finds the policy by ID, name, or defaults to the default/first policy.
|
|
100
|
+
* Returns the full policy content for writing to a local file.
|
|
101
|
+
*
|
|
102
|
+
* @param config - API connection config
|
|
103
|
+
* @param options - Pull options (policyId or policyName)
|
|
104
|
+
* @returns Pull result with policy content and metadata
|
|
105
|
+
*/
|
|
106
|
+
export async function pullPolicy(config, options) {
|
|
107
|
+
try {
|
|
108
|
+
let policyId = options.policyId;
|
|
109
|
+
// If no ID, find by name or get default
|
|
110
|
+
if (!policyId) {
|
|
111
|
+
const listData = await apiRequest(config.apiBase, "/policies", { method: "GET" }, config.apiKey);
|
|
112
|
+
if (options.policyName) {
|
|
113
|
+
const found = listData.policies?.find((p) => p.name === options.policyName);
|
|
114
|
+
if (!found) {
|
|
115
|
+
return {
|
|
116
|
+
success: false,
|
|
117
|
+
error: `Policy "${options.policyName}" not found on server`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
policyId = found.id;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const defaultPolicy = listData.policies?.find((p) => p.isDefault);
|
|
124
|
+
const target = defaultPolicy || listData.policies?.[0];
|
|
125
|
+
if (!target) {
|
|
126
|
+
return { success: false, error: "No policies found on server" };
|
|
127
|
+
}
|
|
128
|
+
policyId = target.id;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Fetch full policy with content
|
|
132
|
+
const data = await apiRequest(config.apiBase, `/policies/${policyId}`, { method: "GET" }, config.apiKey);
|
|
133
|
+
return {
|
|
134
|
+
success: true,
|
|
135
|
+
policy: data.content,
|
|
136
|
+
policyId: data.id || policyId,
|
|
137
|
+
version: data.latestVersion,
|
|
138
|
+
name: data.name,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
error: err instanceof Error ? err.message : String(err),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command catalog for the `suggest` command.
|
|
3
|
+
*
|
|
4
|
+
* Maps natural-language intents to exact CLI commands.
|
|
5
|
+
* Used for local fuzzy matching before falling back to LLM API.
|
|
6
|
+
*/
|
|
7
|
+
export interface CatalogEntry {
|
|
8
|
+
/** Exact CLI command to run */
|
|
9
|
+
command: string;
|
|
10
|
+
/** Short explanation of what the command does */
|
|
11
|
+
description: string;
|
|
12
|
+
/** Keywords that trigger this entry */
|
|
13
|
+
keywords: string[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Full command catalog for VertaaUX CLI.
|
|
17
|
+
*
|
|
18
|
+
* Each entry has keywords that are matched against user intent
|
|
19
|
+
* using simple substring/word-overlap scoring.
|
|
20
|
+
*/
|
|
21
|
+
export declare const COMMAND_CATALOG: CatalogEntry[];
|
|
22
|
+
/**
|
|
23
|
+
* Score a catalog entry against user intent.
|
|
24
|
+
*
|
|
25
|
+
* Uses a combined scoring approach:
|
|
26
|
+
* - Each exact keyword match earns 1 point (multi-word keywords earn 2)
|
|
27
|
+
* - Partial word overlap earns fractional points
|
|
28
|
+
* - Final score = matchPoints / max(totalWeight, 3) to avoid penalizing
|
|
29
|
+
* entries with many keywords when only a few match.
|
|
30
|
+
*
|
|
31
|
+
* Returns a number between 0 and 1 where higher = better match.
|
|
32
|
+
*/
|
|
33
|
+
export declare function scoreMatch(intent: string, entry: CatalogEntry): number;
|
|
34
|
+
/**
|
|
35
|
+
* Find the best matching command(s) for a user intent.
|
|
36
|
+
*
|
|
37
|
+
* @param intent - Natural language intent from the user
|
|
38
|
+
* @param threshold - Minimum score to include (0-1)
|
|
39
|
+
* @param maxResults - Maximum number of results to return
|
|
40
|
+
* @returns Sorted matches with scores
|
|
41
|
+
*/
|
|
42
|
+
export declare function findMatches(intent: string, threshold?: number, maxResults?: number): Array<{
|
|
43
|
+
entry: CatalogEntry;
|
|
44
|
+
score: number;
|
|
45
|
+
}>;
|
|
46
|
+
//# sourceMappingURL=command-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-catalog.d.ts","sourceRoot":"","sources":["../../src/prompts/command-catalog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,YAAY,EAwIzC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAuBtE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,SAAS,SAAM,EACf,UAAU,SAAI,GACb,KAAK,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAU/C"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command catalog for the `suggest` command.
|
|
3
|
+
*
|
|
4
|
+
* Maps natural-language intents to exact CLI commands.
|
|
5
|
+
* Used for local fuzzy matching before falling back to LLM API.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Full command catalog for VertaaUX CLI.
|
|
9
|
+
*
|
|
10
|
+
* Each entry has keywords that are matched against user intent
|
|
11
|
+
* using simple substring/word-overlap scoring.
|
|
12
|
+
*/
|
|
13
|
+
export const COMMAND_CATALOG = [
|
|
14
|
+
// --- Audit Commands ---
|
|
15
|
+
{
|
|
16
|
+
command: "vertaa audit <url> --wait",
|
|
17
|
+
description: "Run a UX audit on a URL and wait for results",
|
|
18
|
+
keywords: ["audit", "scan", "check", "test", "run", "url", "website", "page", "site"],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
command: "vertaa audit <url> --mode standard --wait",
|
|
22
|
+
description: "Run a standard-depth audit (more thorough than basic)",
|
|
23
|
+
keywords: ["standard", "thorough", "detailed", "full", "deep scan"],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
command: "vertaa audit <url> --mode deep --wait",
|
|
27
|
+
description: "Run a deep audit with maximum coverage",
|
|
28
|
+
keywords: ["deep", "comprehensive", "maximum", "everything", "all checks"],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
command: "vertaa audit <url> --wait --json",
|
|
32
|
+
description: "Run an audit and output JSON for piping to other commands",
|
|
33
|
+
keywords: ["json", "pipe", "machine", "ci", "scripting", "output json", "structured"],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
command: "vertaa audit <url> --wait --fail-on-score 80",
|
|
37
|
+
description: "Run audit and fail CI if score is below 80",
|
|
38
|
+
keywords: ["ci", "gate", "fail", "threshold", "score", "pipeline", "quality gate"],
|
|
39
|
+
},
|
|
40
|
+
// --- Accessibility ---
|
|
41
|
+
{
|
|
42
|
+
command: "vertaa a11y <url> --wait",
|
|
43
|
+
description: "Run accessibility-focused audit",
|
|
44
|
+
keywords: ["accessibility", "a11y", "wcag", "aria", "screen reader", "accessible"],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
command: "vertaa audit <url> --wait --json | vertaa explain",
|
|
48
|
+
description: "Audit a site and get an AI explanation of findings",
|
|
49
|
+
keywords: ["explain", "understand", "what", "why", "summary", "meaning"],
|
|
50
|
+
},
|
|
51
|
+
// --- Contrast & Color ---
|
|
52
|
+
{
|
|
53
|
+
command: "vertaa audit <url> --wait --json | vertaa triage",
|
|
54
|
+
description: "Audit and prioritize findings by severity",
|
|
55
|
+
keywords: ["contrast", "color", "triage", "prioritize", "priority", "important", "critical", "p0"],
|
|
56
|
+
},
|
|
57
|
+
// --- Compare ---
|
|
58
|
+
{
|
|
59
|
+
command: "vertaa compare <urlA> <urlB> --wait",
|
|
60
|
+
description: "Compare UX audits of two URLs",
|
|
61
|
+
keywords: ["compare", "diff", "versus", "vs", "difference", "before after", "regression"],
|
|
62
|
+
},
|
|
63
|
+
// --- Explain ---
|
|
64
|
+
{
|
|
65
|
+
command: "vertaa explain <finding-id> --job <job-id>",
|
|
66
|
+
description: "Show detailed evidence for a specific finding",
|
|
67
|
+
keywords: ["explain", "finding", "evidence", "detail", "issue", "specific"],
|
|
68
|
+
},
|
|
69
|
+
// --- Triage ---
|
|
70
|
+
{
|
|
71
|
+
command: "vertaa audit <url> --wait --json | vertaa triage",
|
|
72
|
+
description: "Prioritize audit findings into P0/P1/P2 buckets with effort estimates",
|
|
73
|
+
keywords: ["triage", "prioritize", "priority", "bucket", "effort", "plan", "what first"],
|
|
74
|
+
},
|
|
75
|
+
// --- Fix ---
|
|
76
|
+
{
|
|
77
|
+
command: "vertaa fix <jobId> --issue <id> --file-content \"...\"",
|
|
78
|
+
description: "Generate an auto-fix patch for a specific issue",
|
|
79
|
+
keywords: ["fix", "patch", "auto-fix", "repair", "resolve", "remediate"],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
command: "vertaa fix-all <jobId> --file-content \"...\"",
|
|
83
|
+
description: "Generate fix patches for all issues in an audit",
|
|
84
|
+
keywords: ["fix all", "batch", "all issues", "bulk fix"],
|
|
85
|
+
},
|
|
86
|
+
// --- Diff ---
|
|
87
|
+
{
|
|
88
|
+
command: "vertaa diff --job-a <id> --job-b <id>",
|
|
89
|
+
description: "Compare two audit jobs to see what changed",
|
|
90
|
+
keywords: ["diff", "delta", "change", "compare jobs", "what changed"],
|
|
91
|
+
},
|
|
92
|
+
// --- Baseline ---
|
|
93
|
+
{
|
|
94
|
+
command: "vertaa baseline save",
|
|
95
|
+
description: "Save current audit results as a baseline for future comparison",
|
|
96
|
+
keywords: ["baseline", "save", "snapshot", "reference", "lock"],
|
|
97
|
+
},
|
|
98
|
+
// --- Policy ---
|
|
99
|
+
{
|
|
100
|
+
command: "vertaa policy show",
|
|
101
|
+
description: "Show the current audit policy configuration",
|
|
102
|
+
keywords: ["policy", "rules", "config", "configuration", "show policy"],
|
|
103
|
+
},
|
|
104
|
+
// --- Init & Setup ---
|
|
105
|
+
{
|
|
106
|
+
command: "vertaa init",
|
|
107
|
+
description: "Initialize a new VertaaUX project with configuration file",
|
|
108
|
+
keywords: ["init", "setup", "start", "new", "configure", "initialize", "create config"],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
command: "vertaa login",
|
|
112
|
+
description: "Authenticate with VertaaUX API",
|
|
113
|
+
keywords: ["login", "auth", "authenticate", "sign in", "connect", "api key"],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
command: "vertaa doctor",
|
|
117
|
+
description: "Run diagnostics on CLI configuration and connectivity",
|
|
118
|
+
keywords: ["doctor", "diagnostic", "health", "check", "debug", "troubleshoot", "problem"],
|
|
119
|
+
},
|
|
120
|
+
// --- Comment ---
|
|
121
|
+
{
|
|
122
|
+
command: "vertaa comment --job <id> --github-pr <number>",
|
|
123
|
+
description: "Post audit results as a GitHub PR comment",
|
|
124
|
+
keywords: ["comment", "pr", "pull request", "github", "gitlab", "post"],
|
|
125
|
+
},
|
|
126
|
+
// --- Upload/Download ---
|
|
127
|
+
{
|
|
128
|
+
command: "vertaa upload --file baseline.json",
|
|
129
|
+
description: "Upload a baseline file to the VertaaUX API",
|
|
130
|
+
keywords: ["upload", "push", "send"],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
command: "vertaa download --job <id> --output results.json",
|
|
134
|
+
description: "Download audit results to a local file",
|
|
135
|
+
keywords: ["download", "pull", "fetch", "get", "save results"],
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
/**
|
|
139
|
+
* Score a catalog entry against user intent.
|
|
140
|
+
*
|
|
141
|
+
* Uses a combined scoring approach:
|
|
142
|
+
* - Each exact keyword match earns 1 point (multi-word keywords earn 2)
|
|
143
|
+
* - Partial word overlap earns fractional points
|
|
144
|
+
* - Final score = matchPoints / max(totalWeight, 3) to avoid penalizing
|
|
145
|
+
* entries with many keywords when only a few match.
|
|
146
|
+
*
|
|
147
|
+
* Returns a number between 0 and 1 where higher = better match.
|
|
148
|
+
*/
|
|
149
|
+
export function scoreMatch(intent, entry) {
|
|
150
|
+
const lower = intent.toLowerCase();
|
|
151
|
+
const words = lower.split(/\s+/).filter(Boolean);
|
|
152
|
+
let matchPoints = 0;
|
|
153
|
+
for (const keyword of entry.keywords) {
|
|
154
|
+
const kw = keyword.toLowerCase();
|
|
155
|
+
const weight = kw.includes(" ") ? 2 : 1;
|
|
156
|
+
if (lower.includes(kw)) {
|
|
157
|
+
matchPoints += weight;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Partial word overlap
|
|
161
|
+
const kwWords = kw.split(/\s+/);
|
|
162
|
+
const overlap = kwWords.filter((w) => words.includes(w)).length / kwWords.length;
|
|
163
|
+
matchPoints += weight * overlap * 0.5;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Normalize: divide by a minimum of 3 so that 1 exact match = 0.33 (above threshold)
|
|
167
|
+
const normalizer = Math.max(entry.keywords.length, 3);
|
|
168
|
+
return normalizer > 0 ? Math.min(matchPoints / normalizer, 1) : 0;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Find the best matching command(s) for a user intent.
|
|
172
|
+
*
|
|
173
|
+
* @param intent - Natural language intent from the user
|
|
174
|
+
* @param threshold - Minimum score to include (0-1)
|
|
175
|
+
* @param maxResults - Maximum number of results to return
|
|
176
|
+
* @returns Sorted matches with scores
|
|
177
|
+
*/
|
|
178
|
+
export function findMatches(intent, threshold = 0.1, maxResults = 3) {
|
|
179
|
+
const scored = COMMAND_CATALOG.map((entry) => ({
|
|
180
|
+
entry,
|
|
181
|
+
score: scoreMatch(intent, entry),
|
|
182
|
+
}));
|
|
183
|
+
return scored
|
|
184
|
+
.filter((m) => m.score >= threshold)
|
|
185
|
+
.sort((a, b) => b.score - a.score)
|
|
186
|
+
.slice(0, maxResults);
|
|
187
|
+
}
|
package/dist/ui/spinner.d.ts
CHANGED
|
@@ -1,61 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Progress spinner wrapper for CLI.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Delegates to @vertaaux/tui for consistent terminal rendering.
|
|
5
|
+
* Writes ONLY to stderr — never pollutes stdout.
|
|
6
6
|
*/
|
|
7
|
-
import { type
|
|
8
|
-
export
|
|
9
|
-
/** Initial text to display */
|
|
10
|
-
text: string;
|
|
11
|
-
/** Color for the spinner (default: brand lime) */
|
|
12
|
-
color?: string;
|
|
13
|
-
}
|
|
7
|
+
import { type SpinnerInstance } from "@vertaaux/tui";
|
|
8
|
+
export type { SpinnerInstance };
|
|
14
9
|
/**
|
|
15
10
|
* Create a new spinner instance.
|
|
16
11
|
*
|
|
17
12
|
* Spinner only displays in TTY mode. In non-TTY environments,
|
|
18
13
|
* returns a no-op spinner that still tracks state.
|
|
19
|
-
*
|
|
20
|
-
* @param text - Initial text to display next to spinner
|
|
21
|
-
* @returns An ora spinner instance
|
|
22
14
|
*/
|
|
23
|
-
export declare function createSpinner(text: string):
|
|
15
|
+
export declare function createSpinner(text: string): SpinnerInstance;
|
|
24
16
|
/**
|
|
25
17
|
* Update spinner text with optional progress indicator.
|
|
26
|
-
*
|
|
27
|
-
* @param spinner - The spinner instance to update
|
|
28
|
-
* @param text - New text to display
|
|
29
|
-
* @param current - Current progress count (optional)
|
|
30
|
-
* @param total - Total items count (optional)
|
|
31
18
|
*/
|
|
32
|
-
export declare function updateSpinner(spinner:
|
|
19
|
+
export declare function updateSpinner(spinner: SpinnerInstance, text: string, current?: number, total?: number): void;
|
|
33
20
|
/**
|
|
34
21
|
* Complete spinner with success state.
|
|
35
|
-
*
|
|
36
|
-
* @param spinner - The spinner instance
|
|
37
|
-
* @param text - Success message to display
|
|
38
22
|
*/
|
|
39
|
-
export declare function succeedSpinner(spinner:
|
|
23
|
+
export declare function succeedSpinner(spinner: SpinnerInstance, text: string): void;
|
|
40
24
|
/**
|
|
41
25
|
* Complete spinner with failure state.
|
|
42
|
-
*
|
|
43
|
-
* @param spinner - The spinner instance
|
|
44
|
-
* @param text - Failure message to display
|
|
45
26
|
*/
|
|
46
|
-
export declare function failSpinner(spinner:
|
|
27
|
+
export declare function failSpinner(spinner: SpinnerInstance, text: string): void;
|
|
47
28
|
/**
|
|
48
29
|
* Complete spinner with warning state.
|
|
49
|
-
*
|
|
50
|
-
* @param spinner - The spinner instance
|
|
51
|
-
* @param text - Warning message to display
|
|
52
30
|
*/
|
|
53
|
-
export declare function warnSpinner(spinner:
|
|
31
|
+
export declare function warnSpinner(spinner: SpinnerInstance, text: string): void;
|
|
54
32
|
/**
|
|
55
33
|
* Complete spinner with info state.
|
|
56
|
-
*
|
|
57
|
-
* @param spinner - The spinner instance
|
|
58
|
-
* @param text - Info message to display
|
|
59
34
|
*/
|
|
60
|
-
export declare function infoSpinner(spinner:
|
|
35
|
+
export declare function infoSpinner(spinner: SpinnerInstance, text: string): void;
|
|
61
36
|
//# sourceMappingURL=spinner.d.ts.map
|
package/dist/ui/spinner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAE3D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAQN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAExE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAExE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAExE"}
|
package/dist/ui/spinner.js
CHANGED
|
@@ -1,101 +1,54 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Progress spinner wrapper for CLI.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Delegates to @vertaaux/tui for consistent terminal rendering.
|
|
5
|
+
* Writes ONLY to stderr — never pollutes stdout.
|
|
6
6
|
*/
|
|
7
|
-
import
|
|
8
|
-
import chalk from "chalk";
|
|
9
|
-
import { isTTY, shouldUseColor } from "../utils/detect-env.js";
|
|
10
|
-
// Spinner style - classic dots for clean look
|
|
11
|
-
const SPINNER_STYLE = {
|
|
12
|
-
frames: ["\u2807", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"],
|
|
13
|
-
interval: 80,
|
|
14
|
-
};
|
|
15
|
-
// Brand color for spinner
|
|
16
|
-
const BRAND_COLOR = "#78FFB4";
|
|
7
|
+
import { createSpinner as tuiCreateSpinner, } from "@vertaaux/tui";
|
|
17
8
|
/**
|
|
18
9
|
* Create a new spinner instance.
|
|
19
10
|
*
|
|
20
11
|
* Spinner only displays in TTY mode. In non-TTY environments,
|
|
21
12
|
* returns a no-op spinner that still tracks state.
|
|
22
|
-
*
|
|
23
|
-
* @param text - Initial text to display next to spinner
|
|
24
|
-
* @returns An ora spinner instance
|
|
25
13
|
*/
|
|
26
14
|
export function createSpinner(text) {
|
|
27
|
-
|
|
28
|
-
const spinner = ora({
|
|
29
|
-
text,
|
|
30
|
-
spinner: SPINNER_STYLE,
|
|
31
|
-
color: "cyan",
|
|
32
|
-
isEnabled: isTTY(),
|
|
33
|
-
stream: process.stderr, // Write to stderr to avoid mixing with command output
|
|
34
|
-
});
|
|
35
|
-
// Apply brand color if colors are enabled
|
|
36
|
-
if (useColor) {
|
|
37
|
-
spinner.color = "cyan";
|
|
38
|
-
}
|
|
39
|
-
return spinner;
|
|
15
|
+
return tuiCreateSpinner(text);
|
|
40
16
|
}
|
|
41
17
|
/**
|
|
42
18
|
* Update spinner text with optional progress indicator.
|
|
43
|
-
*
|
|
44
|
-
* @param spinner - The spinner instance to update
|
|
45
|
-
* @param text - New text to display
|
|
46
|
-
* @param current - Current progress count (optional)
|
|
47
|
-
* @param total - Total items count (optional)
|
|
48
19
|
*/
|
|
49
20
|
export function updateSpinner(spinner, text, current, total) {
|
|
50
21
|
if (current !== undefined && total !== undefined) {
|
|
51
|
-
|
|
52
|
-
? chalk.dim(`(${current}/${total})`)
|
|
53
|
-
: `(${current}/${total})`;
|
|
54
|
-
spinner.text = `${text} ${progress}`;
|
|
22
|
+
spinner.setText(`${text} (${current}/${total})`);
|
|
55
23
|
}
|
|
56
24
|
else if (current !== undefined) {
|
|
57
|
-
|
|
58
|
-
? chalk.dim(`(${current})`)
|
|
59
|
-
: `(${current})`;
|
|
60
|
-
spinner.text = `${text} ${progress}`;
|
|
25
|
+
spinner.setText(`${text} (${current})`);
|
|
61
26
|
}
|
|
62
27
|
else {
|
|
63
|
-
spinner.text
|
|
28
|
+
spinner.setText(text);
|
|
64
29
|
}
|
|
65
30
|
}
|
|
66
31
|
/**
|
|
67
32
|
* Complete spinner with success state.
|
|
68
|
-
*
|
|
69
|
-
* @param spinner - The spinner instance
|
|
70
|
-
* @param text - Success message to display
|
|
71
33
|
*/
|
|
72
34
|
export function succeedSpinner(spinner, text) {
|
|
73
|
-
spinner.succeed(
|
|
35
|
+
spinner.succeed(text);
|
|
74
36
|
}
|
|
75
37
|
/**
|
|
76
38
|
* Complete spinner with failure state.
|
|
77
|
-
*
|
|
78
|
-
* @param spinner - The spinner instance
|
|
79
|
-
* @param text - Failure message to display
|
|
80
39
|
*/
|
|
81
40
|
export function failSpinner(spinner, text) {
|
|
82
|
-
spinner.fail(
|
|
41
|
+
spinner.fail(text);
|
|
83
42
|
}
|
|
84
43
|
/**
|
|
85
44
|
* Complete spinner with warning state.
|
|
86
|
-
*
|
|
87
|
-
* @param spinner - The spinner instance
|
|
88
|
-
* @param text - Warning message to display
|
|
89
45
|
*/
|
|
90
46
|
export function warnSpinner(spinner, text) {
|
|
91
|
-
spinner.warn(
|
|
47
|
+
spinner.warn(text);
|
|
92
48
|
}
|
|
93
49
|
/**
|
|
94
50
|
* Complete spinner with info state.
|
|
95
|
-
*
|
|
96
|
-
* @param spinner - The spinner instance
|
|
97
|
-
* @param text - Info message to display
|
|
98
51
|
*/
|
|
99
52
|
export function infoSpinner(spinner, text) {
|
|
100
|
-
spinner.info(
|
|
53
|
+
spinner.info(text);
|
|
101
54
|
}
|
package/dist/ui/table.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Table formatting utilities for CLI output.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Delegates to @vertaaux/tui for consistent rendering with severity-based coloring.
|
|
5
5
|
* Respects terminal width and provides truncation for long content.
|
|
6
6
|
*/
|
|
7
7
|
export interface Issue {
|
|
@@ -33,31 +33,14 @@ export declare function groupBySeverity(issues: Issue[]): Map<string, Issue[]>;
|
|
|
33
33
|
export declare function groupByCategory(issues: Issue[]): Map<string, Issue[]>;
|
|
34
34
|
/**
|
|
35
35
|
* Format issues into a table string.
|
|
36
|
-
*
|
|
37
|
-
* Columns: Severity | ID | Description | Selector (optional)
|
|
38
|
-
* Issues are sorted by severity (critical -> info).
|
|
39
|
-
*
|
|
40
|
-
* @param issues - Array of issues to format
|
|
41
|
-
* @param options - Formatting options
|
|
42
|
-
* @returns Formatted table string
|
|
43
36
|
*/
|
|
44
37
|
export declare function formatIssuesTable(issues: Issue[], options?: FormatTableOptions): string;
|
|
45
|
-
export interface Score {
|
|
46
|
-
category: string;
|
|
47
|
-
score: number;
|
|
48
|
-
}
|
|
49
38
|
/**
|
|
50
39
|
* Format scores into a table string.
|
|
51
|
-
*
|
|
52
|
-
* @param scores - Object mapping category names to scores
|
|
53
|
-
* @returns Formatted table string
|
|
54
40
|
*/
|
|
55
41
|
export declare function formatScoresTable(scores: Record<string, number | unknown>): string;
|
|
56
42
|
/**
|
|
57
43
|
* Format a summary line showing issue counts by severity.
|
|
58
|
-
*
|
|
59
|
-
* @param issues - Array of issues
|
|
60
|
-
* @returns Summary string like "3 critical, 5 serious, 12 minor issues"
|
|
61
44
|
*/
|
|
62
45
|
export declare function formatIssueSummary(issues: Issue[]): string;
|
|
63
46
|
//# sourceMappingURL=table.d.ts.map
|
package/dist/ui/table.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/ui/table.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/ui/table.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,MAAM,WAAW,KAAK;IACpB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,2CAA2C;IAC3C,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAaD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CASrE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CASrE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,KAAK,EAAE,EACf,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAuCR;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,MAAM,CA2BlF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CA4B1D"}
|