add-skill-kit 3.2.3 → 3.2.4
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/lib/agent-cli/lib/audit.js +154 -0
- package/lib/agent-cli/lib/audit.test.js +100 -0
- package/lib/agent-cli/lib/auto-learn.js +319 -0
- package/lib/agent-cli/lib/auto_preview.py +148 -0
- package/lib/agent-cli/lib/backup.js +138 -0
- package/lib/agent-cli/lib/backup.test.js +78 -0
- package/lib/agent-cli/lib/checklist.py +222 -0
- package/lib/agent-cli/lib/cognitive-lesson.js +476 -0
- package/lib/agent-cli/lib/completion.js +149 -0
- package/lib/agent-cli/lib/config.js +35 -0
- package/lib/agent-cli/lib/eslint-fix.js +238 -0
- package/lib/agent-cli/lib/evolution-signal.js +215 -0
- package/lib/agent-cli/lib/export.js +86 -0
- package/lib/agent-cli/lib/export.test.js +65 -0
- package/lib/agent-cli/lib/fix.js +337 -0
- package/lib/agent-cli/lib/fix.test.js +80 -0
- package/lib/agent-cli/lib/gemini-export.js +83 -0
- package/lib/agent-cli/lib/generate-registry.js +42 -0
- package/lib/agent-cli/lib/hooks/install-hooks.js +152 -0
- package/lib/agent-cli/lib/hooks/lint-learn.js +172 -0
- package/lib/agent-cli/lib/ignore.js +116 -0
- package/lib/agent-cli/lib/ignore.test.js +58 -0
- package/lib/agent-cli/lib/init.js +124 -0
- package/lib/agent-cli/lib/learn.js +255 -0
- package/lib/agent-cli/lib/learn.test.js +70 -0
- package/lib/agent-cli/lib/migrate-to-v4.js +322 -0
- package/lib/agent-cli/lib/proposals.js +199 -0
- package/lib/agent-cli/lib/proposals.test.js +56 -0
- package/lib/agent-cli/lib/recall.js +820 -0
- package/lib/agent-cli/lib/recall.test.js +107 -0
- package/lib/agent-cli/lib/selfevolution-bridge.js +167 -0
- package/lib/agent-cli/lib/session_manager.py +120 -0
- package/lib/agent-cli/lib/settings.js +203 -0
- package/lib/agent-cli/lib/skill-learn.js +296 -0
- package/lib/agent-cli/lib/stats.js +132 -0
- package/lib/agent-cli/lib/stats.test.js +94 -0
- package/lib/agent-cli/lib/types.js +33 -0
- package/lib/agent-cli/lib/ui/audit-ui.js +146 -0
- package/lib/agent-cli/lib/ui/backup-ui.js +107 -0
- package/lib/agent-cli/lib/ui/clack-helpers.js +317 -0
- package/lib/agent-cli/lib/ui/common.js +83 -0
- package/lib/agent-cli/lib/ui/completion-ui.js +126 -0
- package/lib/agent-cli/lib/ui/custom-select.js +69 -0
- package/lib/agent-cli/lib/ui/dashboard-ui.js +123 -0
- package/lib/agent-cli/lib/ui/evolution-signals-ui.js +107 -0
- package/lib/agent-cli/lib/ui/export-ui.js +94 -0
- package/lib/agent-cli/lib/ui/fix-all-ui.js +191 -0
- package/lib/agent-cli/lib/ui/help-ui.js +49 -0
- package/lib/agent-cli/lib/ui/index.js +169 -0
- package/lib/agent-cli/lib/ui/init-ui.js +56 -0
- package/lib/agent-cli/lib/ui/knowledge-ui.js +55 -0
- package/lib/agent-cli/lib/ui/learn-ui.js +706 -0
- package/lib/agent-cli/lib/ui/lessons-ui.js +148 -0
- package/lib/agent-cli/lib/ui/pretty.js +145 -0
- package/lib/agent-cli/lib/ui/proposals-ui.js +99 -0
- package/lib/agent-cli/lib/ui/recall-ui.js +342 -0
- package/lib/agent-cli/lib/ui/routing-demo.js +79 -0
- package/lib/agent-cli/lib/ui/routing-ui.js +325 -0
- package/lib/agent-cli/lib/ui/settings-ui.js +381 -0
- package/lib/agent-cli/lib/ui/stats-ui.js +123 -0
- package/lib/agent-cli/lib/ui/watch-ui.js +236 -0
- package/lib/agent-cli/lib/verify_all.py +327 -0
- package/lib/agent-cli/lib/watcher.js +181 -0
- package/lib/agent-cli/lib/watcher.test.js +85 -0
- package/lib/agent-cli/package.json +51 -0
- package/lib/agentskillskit-cli/README.md +21 -0
- package/lib/agentskillskit-cli/ag-smart.js +158 -0
- package/lib/agentskillskit-cli/package.json +51 -0
- package/package.json +10 -6
- /package/{node_modules/agentskillskit-cli → lib/agent-cli}/README.md +0 -0
- /package/{node_modules/agentskillskit-cli → lib/agent-cli}/bin/ag-smart.js +0 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard UI - Launch Auto-Learn Dashboard in browser
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import { spawn, exec } from "child_process";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
import http from "http";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Find an available port
|
|
12
|
+
*/
|
|
13
|
+
async function findAvailablePort(startPort = 3030) {
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
const server = http.createServer();
|
|
16
|
+
server.listen(startPort, () => {
|
|
17
|
+
server.close(() => resolve(startPort));
|
|
18
|
+
});
|
|
19
|
+
server.on("error", () => {
|
|
20
|
+
resolve(findAvailablePort(startPort + 1));
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Find dashboard server script
|
|
27
|
+
*/
|
|
28
|
+
function findDashboardScript() {
|
|
29
|
+
const possiblePaths = [
|
|
30
|
+
path.join(process.cwd(), ".agent", "skills", "auto-learner", "scripts", "dashboard_server.js"),
|
|
31
|
+
path.join(process.cwd(), ".agent", "agentskillskit", ".agent", "skills", "auto-learner", "scripts", "dashboard_server.js")
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
for (const p of possiblePaths) {
|
|
35
|
+
if (fs.existsSync(p)) {
|
|
36
|
+
return p;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Open URL in default browser
|
|
44
|
+
*/
|
|
45
|
+
function openBrowser(url) {
|
|
46
|
+
const platform = process.platform;
|
|
47
|
+
let command;
|
|
48
|
+
|
|
49
|
+
if (platform === "win32") {
|
|
50
|
+
command = `start "" "${url}"`;
|
|
51
|
+
} else if (platform === "darwin") {
|
|
52
|
+
command = `open "${url}"`;
|
|
53
|
+
} else {
|
|
54
|
+
command = `xdg-open "${url}"`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exec(command, (err) => {
|
|
58
|
+
if (err) {
|
|
59
|
+
p.log.warn(`Could not open browser automatically. Visit: ${url}`);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Run Dashboard UI
|
|
66
|
+
*/
|
|
67
|
+
export async function runDashboardUI() {
|
|
68
|
+
const spinner = p.spinner();
|
|
69
|
+
|
|
70
|
+
// Find dashboard script
|
|
71
|
+
const scriptPath = findDashboardScript();
|
|
72
|
+
|
|
73
|
+
if (!scriptPath) {
|
|
74
|
+
p.log.error("Dashboard script not found!");
|
|
75
|
+
p.log.info("Install auto-learner skill first or check .agent/skills/auto-learner/scripts/");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Find available port
|
|
80
|
+
spinner.start("Finding available port...");
|
|
81
|
+
const port = await findAvailablePort(3030);
|
|
82
|
+
spinner.stop(`Using port ${port}`);
|
|
83
|
+
|
|
84
|
+
// Start dashboard server
|
|
85
|
+
spinner.start("Starting dashboard server...");
|
|
86
|
+
|
|
87
|
+
const child = spawn("node", [scriptPath, "--port", String(port)], {
|
|
88
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
89
|
+
detached: false
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Wait for server to start
|
|
93
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
94
|
+
|
|
95
|
+
spinner.stop("Dashboard server started!");
|
|
96
|
+
|
|
97
|
+
const url = `http://localhost:${port}`;
|
|
98
|
+
|
|
99
|
+
// Open browser
|
|
100
|
+
p.log.success(`Dashboard running at: ${url}`);
|
|
101
|
+
openBrowser(url);
|
|
102
|
+
|
|
103
|
+
p.log.info("Dashboard opened in browser");
|
|
104
|
+
p.note(`Server running on port ${port}\nPress Ctrl+C in terminal to stop`, "📊 Auto-Learn Dashboard");
|
|
105
|
+
|
|
106
|
+
// Keep server running and wait for user
|
|
107
|
+
const action = await p.select({
|
|
108
|
+
message: "Dashboard is running. What would you like to do?",
|
|
109
|
+
options: [
|
|
110
|
+
{ value: "keep", label: "🏠 Back to menu", hint: "Keep server running" },
|
|
111
|
+
{ value: "stop", label: "🛑 Stop server", hint: "Shutdown dashboard" }
|
|
112
|
+
]
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (action === "stop" || p.isCancel(action)) {
|
|
116
|
+
child.kill();
|
|
117
|
+
p.log.info("Dashboard server stopped");
|
|
118
|
+
} else {
|
|
119
|
+
p.log.info(`Dashboard still running at ${url}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export default runDashboardUI;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evolution Signals UI - View and manage pending evolution signals
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import { signalQueue, getEvolutionStats, reviewGate } from "../evolution-signal.js";
|
|
7
|
+
import { loadKnowledge } from "../recall.js";
|
|
8
|
+
import { loadSettings } from "../settings.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Show pending evolution signals
|
|
12
|
+
*/
|
|
13
|
+
export async function runEvolutionSignalsUI() {
|
|
14
|
+
p.intro("📡 Evolution Signals");
|
|
15
|
+
|
|
16
|
+
const pending = signalQueue.getPending();
|
|
17
|
+
const stats = getEvolutionStats();
|
|
18
|
+
|
|
19
|
+
// Show summary
|
|
20
|
+
p.note(
|
|
21
|
+
`Pending: ${pc.yellow(stats.pending)}\n` +
|
|
22
|
+
`Approved: ${pc.green(stats.approved)}\n` +
|
|
23
|
+
`Rejected: ${pc.red(stats.rejected)}\n` +
|
|
24
|
+
`Executed: ${pc.cyan(stats.executed)}`,
|
|
25
|
+
"📊 Signal Queue Status"
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
if (pending.length === 0) {
|
|
29
|
+
p.note(pc.dim("No pending evolution signals"), "✅ All Clear");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Load lessons for context
|
|
34
|
+
const db = loadKnowledge();
|
|
35
|
+
const settings = loadSettings();
|
|
36
|
+
|
|
37
|
+
// Display pending signals with details
|
|
38
|
+
const signalChoices = pending.map(signal => {
|
|
39
|
+
const lesson = db.lessons.find(l => l.id === signal.lessonId);
|
|
40
|
+
const lessonName = lesson ? lesson.id : signal.lessonId;
|
|
41
|
+
const gate = reviewGate(signal, {
|
|
42
|
+
autoUpdating: settings.autoUpdating,
|
|
43
|
+
confidenceThreshold: 0.8
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
value: signal.id,
|
|
48
|
+
label: `${pc.yellow('●')} ${lessonName}`,
|
|
49
|
+
hint: `${signal.reason} · confidence: ${(signal.confidence * 100).toFixed(0)}% ${gate.shouldAuto ? pc.green('(auto-eligible)') : pc.dim('(review)')}`
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const action = await p.select({
|
|
54
|
+
message: "Pending Evolution Signals",
|
|
55
|
+
options: [
|
|
56
|
+
...signalChoices,
|
|
57
|
+
{ value: "back", label: "← Back" }
|
|
58
|
+
]
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (p.isCancel(action) || action === "back") {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Show signal details
|
|
66
|
+
const signal = pending.find(s => s.id === action);
|
|
67
|
+
if (!signal) return;
|
|
68
|
+
|
|
69
|
+
const lesson = db.lessons.find(l => l.id === signal.lessonId);
|
|
70
|
+
|
|
71
|
+
p.note(
|
|
72
|
+
`${pc.bold('Lesson:')} ${signal.lessonId}\n` +
|
|
73
|
+
`${pc.bold('Reason:')} ${signal.reason}\n` +
|
|
74
|
+
`${pc.bold('Confidence:')} ${(signal.confidence * 100).toFixed(0)}%\n` +
|
|
75
|
+
`${pc.bold('Created:')} ${new Date(signal.createdAt).toLocaleString()}\n\n` +
|
|
76
|
+
`${pc.bold('Current Stats:')}\n` +
|
|
77
|
+
` Hit Count: ${lesson?.hitCount || 0}\n` +
|
|
78
|
+
` Maturity: ${lesson?.cognitive?.maturity || 'unknown'}\n` +
|
|
79
|
+
` Intent: ${lesson?.intent || 'unknown'}\n\n` +
|
|
80
|
+
`${pc.bold('Metadata:')}\n` +
|
|
81
|
+
` Trigger: ${signal.metadata.triggerEvent}\n` +
|
|
82
|
+
` File: ${signal.metadata.file || 'N/A'}`,
|
|
83
|
+
"🔍 Signal Details"
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
// Action options
|
|
87
|
+
const signalAction = await p.select({
|
|
88
|
+
message: "What would you like to do?",
|
|
89
|
+
options: [
|
|
90
|
+
{ value: "approve", label: "✅ Approve", hint: "Mark for evolution" },
|
|
91
|
+
{ value: "reject", label: "❌ Reject", hint: "Dismiss this signal" },
|
|
92
|
+
{ value: "back", label: "← Back" }
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (p.isCancel(signalAction) || signalAction === "back") {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (signalAction === "approve") {
|
|
101
|
+
signalQueue.approve(signal.id);
|
|
102
|
+
p.note(pc.green(`✅ Signal approved for [${signal.lessonId}]`));
|
|
103
|
+
} else if (signalAction === "reject") {
|
|
104
|
+
signalQueue.reject(signal.id);
|
|
105
|
+
p.note(pc.red(`❌ Signal rejected for [${signal.lessonId}]`));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export/Import UI - Share settings between projects
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { cwd } from "../config.js";
|
|
8
|
+
import { exportData, importData } from "../export.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Interactive export/import menu
|
|
12
|
+
*/
|
|
13
|
+
export async function runExportUI() {
|
|
14
|
+
p.intro("Export & Import (Press ESC to exit)");
|
|
15
|
+
|
|
16
|
+
while (true) {
|
|
17
|
+
|
|
18
|
+
const action = await p.select({
|
|
19
|
+
message: "What would you like to do?",
|
|
20
|
+
options: [
|
|
21
|
+
{ value: "export", label: "Export", hint: "Export lessons to file" },
|
|
22
|
+
{ value: "import", label: "Import", hint: "Import lessons from file" },
|
|
23
|
+
{ value: "back", label: "← Back", hint: "Return to main menu" }
|
|
24
|
+
]
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (p.isCancel(action) || action === "back") {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (action) {
|
|
32
|
+
case "export": {
|
|
33
|
+
const filename = await p.text({
|
|
34
|
+
message: "Export filename:",
|
|
35
|
+
placeholder: "agent-skills-export.json",
|
|
36
|
+
initialValue: "agent-skills-export.json"
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (p.isCancel(filename)) break;
|
|
40
|
+
|
|
41
|
+
const outputPath = path.join(cwd, filename);
|
|
42
|
+
const success = exportData(outputPath);
|
|
43
|
+
|
|
44
|
+
if (success) {
|
|
45
|
+
p.note(
|
|
46
|
+
`Exported to:\n${pc.dim(outputPath)}`,
|
|
47
|
+
pc.green("Success")
|
|
48
|
+
);
|
|
49
|
+
} else {
|
|
50
|
+
p.note("Failed to export", pc.red("Error"));
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
case "import": {
|
|
56
|
+
const filename = await p.text({
|
|
57
|
+
message: "Import filename:",
|
|
58
|
+
placeholder: "agent-skills-export.json",
|
|
59
|
+
validate: (v) => {
|
|
60
|
+
if (!v) return "Filename required";
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (p.isCancel(filename)) break;
|
|
65
|
+
|
|
66
|
+
const mode = await p.select({
|
|
67
|
+
message: "Import mode:",
|
|
68
|
+
options: [
|
|
69
|
+
{ value: "merge", label: "Merge", hint: "Add new, keep existing" },
|
|
70
|
+
{ value: "replace", label: "Replace", hint: "Overwrite all data" }
|
|
71
|
+
]
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (p.isCancel(mode)) break;
|
|
75
|
+
|
|
76
|
+
const inputPath = path.join(cwd, filename);
|
|
77
|
+
const result = importData(inputPath, mode);
|
|
78
|
+
|
|
79
|
+
if (result.success) {
|
|
80
|
+
p.note(
|
|
81
|
+
`Imported ${result.lessonsCount} lesson(s)\n` +
|
|
82
|
+
`Settings: ${result.hasSettings ? "Yes" : "No"}`,
|
|
83
|
+
pc.green("Success")
|
|
84
|
+
);
|
|
85
|
+
} else {
|
|
86
|
+
p.note("Failed to import. Check file exists and is valid JSON.", pc.red("Error"));
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default runExportUI;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fix All UI - Agent Coding Handoff (Smart Version)
|
|
3
|
+
* Instead of brittle regex auto-fix, generates AI-friendly prompts
|
|
4
|
+
*/
|
|
5
|
+
import * as p from "@clack/prompts";
|
|
6
|
+
import pc from "picocolors";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import { execSync } from "child_process";
|
|
10
|
+
import { showIntro, createSpinner, showSuccessNote, showErrorNote, theme } from "./clack-helpers.js";
|
|
11
|
+
import { loadMostRecentScan, loadScanResult } from "../recall.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Fix All UI - Generate Agent handoff prompts
|
|
15
|
+
*/
|
|
16
|
+
export async function runFixAllUI(scanId = null) {
|
|
17
|
+
showIntro('🔧 Fix All - Agent Handoff');
|
|
18
|
+
|
|
19
|
+
// 1. Get scan results
|
|
20
|
+
let scanResult;
|
|
21
|
+
const spinner = createSpinner('Loading scan results...');
|
|
22
|
+
|
|
23
|
+
if (!scanId) {
|
|
24
|
+
scanResult = loadMostRecentScan();
|
|
25
|
+
} else {
|
|
26
|
+
scanResult = loadScanResult(scanId);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
spinner.stop();
|
|
30
|
+
|
|
31
|
+
if (!scanResult) {
|
|
32
|
+
showErrorNote(
|
|
33
|
+
'No scan results found.\\n\\n' +
|
|
34
|
+
'Run "Scan All" first to generate scan data.',
|
|
35
|
+
'✗ No Scan Results'
|
|
36
|
+
);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 2. Show summary
|
|
41
|
+
console.log(`\\n${theme.primary(scanResult.totalIssues)} violations found\\n`);
|
|
42
|
+
|
|
43
|
+
// 3. Offer handoff options
|
|
44
|
+
const choice = await p.select({
|
|
45
|
+
message: "How would you like to fix these violations?",
|
|
46
|
+
options: [
|
|
47
|
+
{ value: "agent", label: "🤖 Hand off to Agent", hint: "Generate AI fix request" },
|
|
48
|
+
{ value: "skip", label: "← Skip", hint: "Return to menu" }
|
|
49
|
+
]
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (p.isCancel(choice) || choice === "skip") {
|
|
53
|
+
p.cancel('Cancelled');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 4. Generate fix prompt
|
|
58
|
+
const fixPrompt = generateAgentFixPrompt(scanResult);
|
|
59
|
+
|
|
60
|
+
// 5. Ask where to send
|
|
61
|
+
const outputChoice = await p.select({
|
|
62
|
+
message: "Where to send the fix request?",
|
|
63
|
+
options: [
|
|
64
|
+
{ value: "clipboard", label: "📋 Copy to Clipboard", hint: "Paste into AI chat" },
|
|
65
|
+
{ value: "file", label: "💾 Save to File", hint: ".agent/fix-request.md" },
|
|
66
|
+
{ value: "both", label: "✨ Both", hint: "Copy and save" }
|
|
67
|
+
]
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (p.isCancel(outputChoice)) {
|
|
71
|
+
p.cancel('Cancelled');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 6. Execute handoff
|
|
76
|
+
let copied = false;
|
|
77
|
+
let saved = false;
|
|
78
|
+
|
|
79
|
+
if (outputChoice === "clipboard" || outputChoice === "both") {
|
|
80
|
+
copied = copyToClipboard(fixPrompt);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (outputChoice === "file" || outputChoice === "both") {
|
|
84
|
+
saved = saveFixRequest(fixPrompt);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 7. Show success
|
|
88
|
+
let message = '';
|
|
89
|
+
if (copied && saved) {
|
|
90
|
+
message = '✓ Copied to clipboard\\n✓ Saved to .agent/fix-request.md\\n\\nPaste into your AI coding assistant!';
|
|
91
|
+
} else if (copied) {
|
|
92
|
+
message = '✓ Copied to clipboard\\n\\nPaste into your AI coding assistant!';
|
|
93
|
+
} else if (saved) {
|
|
94
|
+
message = '✓ Saved to .agent/fix-request.md\\n\\nOpen file and copy into your AI coding assistant!';
|
|
95
|
+
} else {
|
|
96
|
+
message = 'Failed to copy or save. Check console for errors.';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
p.note(message, '🎉 Fix Request Ready');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Generate AI-friendly fix prompt from scan results
|
|
104
|
+
*/
|
|
105
|
+
function generateAgentFixPrompt(scanResult) {
|
|
106
|
+
// Group by file
|
|
107
|
+
const byFile = {};
|
|
108
|
+
scanResult.issues.forEach(issue => {
|
|
109
|
+
const file = path.relative(process.cwd(), issue.file);
|
|
110
|
+
if (!byFile[file]) byFile[file] = [];
|
|
111
|
+
byFile[file].push(issue);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const fileList = Object.entries(byFile).sort((a, b) => b[1].length - a[1].length);
|
|
115
|
+
|
|
116
|
+
let prompt = '# Code Violation Fix Request\\n\\n## Summary\\n';
|
|
117
|
+
prompt += `- **Total violations**: ${scanResult.totalIssues}\\n`;
|
|
118
|
+
prompt += `- **Files affected**: ${fileList.length}\\n`;
|
|
119
|
+
prompt += `- **Errors**: ${scanResult.summary.errors}\\n`;
|
|
120
|
+
prompt += `- **Warnings**: ${scanResult.summary.warnings}\\n\\n`;
|
|
121
|
+
prompt += '## Violations by File\\n\\n';
|
|
122
|
+
|
|
123
|
+
fileList.forEach(([file, issues]) => {
|
|
124
|
+
prompt += `### 📁 \`${file}\`\\n\\n`;
|
|
125
|
+
issues.forEach(issue => {
|
|
126
|
+
const icon = issue.severity === 'ERROR' ? '🔴' : '⚠️';
|
|
127
|
+
prompt += `${icon} **Line ${issue.line}** - ${issue.severity}\\n`;
|
|
128
|
+
prompt += `- **Issue**: ${issue.message}\\n`;
|
|
129
|
+
if (issue.pattern) {
|
|
130
|
+
prompt += `- **Pattern**: \`${issue.pattern}\`\\n`;
|
|
131
|
+
}
|
|
132
|
+
prompt += '\\n';
|
|
133
|
+
});
|
|
134
|
+
prompt += '\\n';
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
prompt += '## Instructions\\n\\n';
|
|
138
|
+
prompt += 'Please fix all violations following these guidelines:\\n\\n';
|
|
139
|
+
prompt += '1. **Understand Context**: Read the entire file before making changes\\n';
|
|
140
|
+
prompt += '2. **Fix Correctly**: Address the root cause, not just the symptom\\n';
|
|
141
|
+
prompt += '3. **Maintain Style**: Keep existing code style and formatting\\n';
|
|
142
|
+
prompt += '4. **Test Changes**: Ensure no functionality is broken\\n';
|
|
143
|
+
prompt += '5. **Verify**: Check that all violations are resolved\\n\\n';
|
|
144
|
+
prompt += '**Important**: Some violations may be false positives. Use your judgment and skip if the code is actually correct.\\n\\n';
|
|
145
|
+
prompt += 'Ready to proceed with fixing these violations?\\n';
|
|
146
|
+
|
|
147
|
+
return prompt;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Copy text to clipboard (cross-platform)
|
|
152
|
+
*/
|
|
153
|
+
function copyToClipboard(text) {
|
|
154
|
+
try {
|
|
155
|
+
if (process.platform === 'win32') {
|
|
156
|
+
execSync('clip', { input: text });
|
|
157
|
+
return true;
|
|
158
|
+
} else if (process.platform === 'darwin') {
|
|
159
|
+
execSync('pbcopy', { input: text });
|
|
160
|
+
return true;
|
|
161
|
+
} else {
|
|
162
|
+
execSync('xclip -selection clipboard', { input: text });
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
} catch (e) {
|
|
166
|
+
console.error(`Clipboard error: ${e.message}`);
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Save fix request to file
|
|
173
|
+
*/
|
|
174
|
+
function saveFixRequest(text) {
|
|
175
|
+
try {
|
|
176
|
+
const fixRequestPath = path.join('.agent', 'fix-request.md');
|
|
177
|
+
const dir = path.dirname(fixRequestPath);
|
|
178
|
+
|
|
179
|
+
if (!fs.existsSync(dir)) {
|
|
180
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
fs.writeFileSync(fixRequestPath, text, 'utf8');
|
|
184
|
+
return true;
|
|
185
|
+
} catch (e) {
|
|
186
|
+
console.error(`Save error: ${e.message}`);
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export default runFixAllUI;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Help/Guide UI - Compact Visual Guide
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Show compact visual guide (fits in one screen)
|
|
9
|
+
*/
|
|
10
|
+
export async function runHelpUI() {
|
|
11
|
+
// Clear terminal và reset cursor về top-left
|
|
12
|
+
process.stdout.write('\x1Bc'); // Full terminal reset
|
|
13
|
+
|
|
14
|
+
p.intro(pc.cyan("📖 Agent Skill Kit - Quick Guide"));
|
|
15
|
+
|
|
16
|
+
console.log(`
|
|
17
|
+
${pc.bold(pc.yellow("🎯 HOW IT WORKS"))}
|
|
18
|
+
${pc.green("Write Code")} → ${pc.yellow("Agent Scans")} → ${pc.blue("Learns Patterns")} → ${pc.magenta("Auto Warns")}
|
|
19
|
+
|
|
20
|
+
${pc.bold(pc.yellow("🔧 MENU OPTIONS"))}
|
|
21
|
+
${pc.cyan("🔎 Scan All")} - Check violations + option to auto-fix
|
|
22
|
+
${pc.cyan("📝 Learn")} - Teach agent new patterns (manual mode only)
|
|
23
|
+
${pc.cyan("📚 Knowledge")} - View lessons & review pending patterns
|
|
24
|
+
${pc.cyan("📊 Stats")} - Project metrics & insights
|
|
25
|
+
${pc.cyan("⚙️ Settings")} - Configure auto-learning, API keys
|
|
26
|
+
${pc.cyan("💾 Backup")} - Manage knowledge backups
|
|
27
|
+
|
|
28
|
+
${pc.bold(pc.yellow("🚀 QUICK START"))}
|
|
29
|
+
${pc.bold("1.")} ${pc.cyan("Scan All")} ${pc.dim("→ See current violations")}
|
|
30
|
+
${pc.bold("2.")} ${pc.cyan("Fix All")} ${pc.dim("→ Auto-fix simple issues")}
|
|
31
|
+
${pc.bold("3.")} ${pc.cyan("Knowledge")} ${pc.dim("→ Review what agent learned")}
|
|
32
|
+
|
|
33
|
+
${pc.green("✓")} Agent learns from your code automatically
|
|
34
|
+
${pc.green("✓")} All fixes are backed up safely
|
|
35
|
+
${pc.green("✓")} The more you use it, the smarter it gets!
|
|
36
|
+
`);
|
|
37
|
+
|
|
38
|
+
// User selects next action
|
|
39
|
+
const action = await p.select({
|
|
40
|
+
message: "What's next?",
|
|
41
|
+
options: [
|
|
42
|
+
{ value: "back", label: "← Back to Main Menu" }
|
|
43
|
+
]
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (!p.isCancel(action)) {
|
|
47
|
+
p.outro(pc.cyan("👋 Returning to menu"));
|
|
48
|
+
}
|
|
49
|
+
}
|