add-skill-kit 3.2.2 → 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/bin/lib/commands/install.js +67 -45
- package/lib/agent-cli/README.md +21 -0
- package/lib/agent-cli/bin/ag-smart.js +158 -0
- 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 +11 -6
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backup UI - Interactive backup and restore
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import { createBackup, listBackups, restoreBackup, pruneBackups } from "../backup.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Interactive backup/restore menu
|
|
10
|
+
*/
|
|
11
|
+
export async function runBackupUI() {
|
|
12
|
+
p.intro("Backup & Restore (Press ESC to return)");
|
|
13
|
+
|
|
14
|
+
while (true) {
|
|
15
|
+
|
|
16
|
+
const action = await p.select({
|
|
17
|
+
message: "What would you like to do?",
|
|
18
|
+
options: [
|
|
19
|
+
{ value: "create", label: "💾 Create Backup", hint: "Save current lessons & settings" },
|
|
20
|
+
{ value: "restore", label: "♻️ Restore Backup", hint: "Recover from previous backup" },
|
|
21
|
+
{ value: "list", label: "📋 List Backups", hint: "View available backups" },
|
|
22
|
+
{ value: "prune", label: "🗑️ Prune Old", hint: "Keep only last 5 backups" },
|
|
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 "create": {
|
|
33
|
+
const result = createBackup();
|
|
34
|
+
if (result) {
|
|
35
|
+
p.note(
|
|
36
|
+
`Backup created:\n${pc.dim(result.path)}`,
|
|
37
|
+
pc.green("Success")
|
|
38
|
+
);
|
|
39
|
+
break; // Continue to show menu again
|
|
40
|
+
} else {
|
|
41
|
+
p.note("Failed to create backup", pc.red("Error"));
|
|
42
|
+
}
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
case "restore": {
|
|
47
|
+
const backups = listBackups();
|
|
48
|
+
if (backups.length === 0) {
|
|
49
|
+
p.note("No backups found", "Info");
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const selected = await p.select({
|
|
54
|
+
message: "Select backup to restore:",
|
|
55
|
+
options: backups.map(b => ({
|
|
56
|
+
value: b.path,
|
|
57
|
+
label: b.name,
|
|
58
|
+
hint: b.date.toLocaleString()
|
|
59
|
+
}))
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (p.isCancel(selected)) break;
|
|
63
|
+
|
|
64
|
+
const confirm = await p.confirm({
|
|
65
|
+
message: "Restore this backup? Current data will be overwritten."
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (confirm) {
|
|
69
|
+
const success = restoreBackup(selected);
|
|
70
|
+
if (success) {
|
|
71
|
+
p.note("Backup restored successfully", pc.green("Success"));
|
|
72
|
+
} else {
|
|
73
|
+
p.note("Failed to restore backup", pc.red("Error"));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
case "list": {
|
|
80
|
+
const backups = listBackups();
|
|
81
|
+
if (backups.length === 0) {
|
|
82
|
+
p.note("No backups found", "Info");
|
|
83
|
+
} else {
|
|
84
|
+
const list = backups.map(b =>
|
|
85
|
+
`• ${b.name}\n ${pc.dim(b.date.toLocaleString())}`
|
|
86
|
+
).join("\n\n");
|
|
87
|
+
p.note(list, `${backups.length} Backup(s)`);
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
case "prune": {
|
|
93
|
+
const confirm = await p.confirm({
|
|
94
|
+
message: "Delete old backups, keep only last 5?"
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
if (confirm) {
|
|
98
|
+
pruneBackups(5);
|
|
99
|
+
p.note("Old backups pruned", pc.green("Done"));
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export default runBackupUI;
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clack UI Helpers - Agent Skill Kit
|
|
3
|
+
* Reusable UI patterns for consistent CLI experience
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as p from '@clack/prompts';
|
|
7
|
+
import color from 'picocolors';
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// COLOR SCHEME
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
export const theme = {
|
|
14
|
+
// Primary colors
|
|
15
|
+
primary: color.cyan,
|
|
16
|
+
success: color.green,
|
|
17
|
+
error: color.red,
|
|
18
|
+
warning: color.yellow,
|
|
19
|
+
info: color.blue,
|
|
20
|
+
|
|
21
|
+
// Text styles
|
|
22
|
+
dim: color.dim,
|
|
23
|
+
bold: color.bold,
|
|
24
|
+
|
|
25
|
+
// Brand color
|
|
26
|
+
brand: (text) => color.bgCyan(color.black(text)),
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// INTRO & OUTRO
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Show branded intro banner
|
|
35
|
+
* @param {string} title - Title text to display
|
|
36
|
+
*/
|
|
37
|
+
export function showIntro(title) {
|
|
38
|
+
console.clear();
|
|
39
|
+
p.intro(theme.brand(` ${title} `));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Show success outro
|
|
44
|
+
* @param {string} message - Success message
|
|
45
|
+
*/
|
|
46
|
+
export function showSuccess(message) {
|
|
47
|
+
p.outro(theme.success(`✓ ${message}`));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Show error outro
|
|
52
|
+
* @param {string} message - Error message
|
|
53
|
+
*/
|
|
54
|
+
export function showError(message) {
|
|
55
|
+
p.outro(theme.error(`✗ ${message}`));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Show info outro
|
|
60
|
+
* @param {string} message - Info message
|
|
61
|
+
*/
|
|
62
|
+
export function showInfo(message) {
|
|
63
|
+
p.outro(theme.info(message));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// MENUS
|
|
68
|
+
// ============================================================================
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Show main action menu with Exit option
|
|
72
|
+
* @param {Object} options
|
|
73
|
+
* @param {string} options.message - Menu message
|
|
74
|
+
* @param {Array} options.items - Menu items {value, label, hint?}
|
|
75
|
+
* @param {boolean} options.includeExit - Include Exit option (default: true)
|
|
76
|
+
* @param {boolean} options.allowCancel - Allow ESC to return to parent (default: true)
|
|
77
|
+
* @returns {Promise<string|null>} Selected value or null if cancelled
|
|
78
|
+
*/
|
|
79
|
+
export async function showActionMenu({ message, items, includeExit = true, allowCancel = true }) {
|
|
80
|
+
const menuItems = [...items];
|
|
81
|
+
|
|
82
|
+
if (includeExit) {
|
|
83
|
+
menuItems.push({ value: 'exit', label: 'Exit', hint: 'Close CLI' });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const selected = await p.select({
|
|
87
|
+
message,
|
|
88
|
+
options: menuItems,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Handle cancel - return null to let parent decide
|
|
92
|
+
if (p.isCancel(selected)) {
|
|
93
|
+
if (allowCancel) {
|
|
94
|
+
return null; // Let parent handle navigation
|
|
95
|
+
} else {
|
|
96
|
+
p.cancel('Operation cancelled.');
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Handle explicit exit
|
|
102
|
+
if (selected === 'exit') {
|
|
103
|
+
p.cancel('Goodbye! 👋');
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return selected;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Show confirmation prompt
|
|
112
|
+
* @param {string} message - Confirmation message
|
|
113
|
+
* @param {boolean} initialValue - Default value
|
|
114
|
+
* @returns {Promise<boolean>}
|
|
115
|
+
*/
|
|
116
|
+
export async function confirm(message, initialValue = false) {
|
|
117
|
+
const result = await p.confirm({
|
|
118
|
+
message,
|
|
119
|
+
initialValue,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (p.isCancel(result)) {
|
|
123
|
+
p.cancel('Operation cancelled.');
|
|
124
|
+
process.exit(0);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ============================================================================
|
|
131
|
+
// INPUTS
|
|
132
|
+
// ============================================================================
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get text input with validation
|
|
136
|
+
* @param {Object} options
|
|
137
|
+
* @param {string} options.message - Input message
|
|
138
|
+
* @param {string} options.placeholder - Placeholder text
|
|
139
|
+
* @param {Function} options.validate - Validation function
|
|
140
|
+
* @returns {Promise<string>}
|
|
141
|
+
*/
|
|
142
|
+
export async function textInput({ message, placeholder = '', validate }) {
|
|
143
|
+
const result = await p.text({
|
|
144
|
+
message,
|
|
145
|
+
placeholder,
|
|
146
|
+
validate,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (p.isCancel(result)) {
|
|
150
|
+
p.cancel('Operation cancelled.');
|
|
151
|
+
process.exit(0);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ============================================================================
|
|
158
|
+
// PROGRESS
|
|
159
|
+
// ============================================================================
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Create and manage a spinner
|
|
163
|
+
* @param {string} message - Initial message
|
|
164
|
+
* @returns {Object} Spinner instance with update/stop methods
|
|
165
|
+
*/
|
|
166
|
+
export function createSpinner(message) {
|
|
167
|
+
const spinner = p.spinner();
|
|
168
|
+
spinner.start(message);
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
update: (msg) => {
|
|
172
|
+
spinner.message(msg);
|
|
173
|
+
},
|
|
174
|
+
stop: (msg) => {
|
|
175
|
+
spinner.stop(msg);
|
|
176
|
+
},
|
|
177
|
+
stopSuccess: (msg) => {
|
|
178
|
+
spinner.stop(theme.success(`✓ ${msg}`));
|
|
179
|
+
},
|
|
180
|
+
stopError: (msg) => {
|
|
181
|
+
spinner.stop(theme.error(`✗ ${msg}`));
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ============================================================================
|
|
187
|
+
// NOTES & INFO BOXES
|
|
188
|
+
// ============================================================================
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Show info note box
|
|
192
|
+
* @param {string} content - Note content
|
|
193
|
+
* @param {string} title - Note title (optional)
|
|
194
|
+
*/
|
|
195
|
+
export function showNote(content, title = '') {
|
|
196
|
+
p.note(content, title);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Show success note
|
|
201
|
+
* @param {string} content - Note content
|
|
202
|
+
* @param {string} title - Note title
|
|
203
|
+
*/
|
|
204
|
+
export function showSuccessNote(content, title = '✓ Success') {
|
|
205
|
+
p.note(content, theme.success(title));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Show error note
|
|
210
|
+
* @param {string} content - Note content
|
|
211
|
+
* @param {string} title - Note title
|
|
212
|
+
*/
|
|
213
|
+
export function showErrorNote(content, title = '✗ Error') {
|
|
214
|
+
p.note(content, theme.error(title));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Show info note with cyan title
|
|
219
|
+
* @param {string} content - Note content
|
|
220
|
+
* @param {string} title - Note title
|
|
221
|
+
*/
|
|
222
|
+
export function showInfoNote(content, title) {
|
|
223
|
+
p.note(content, theme.primary(title));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ============================================================================
|
|
227
|
+
// RESULTS
|
|
228
|
+
// ============================================================================
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Format results for display
|
|
232
|
+
* @param {Object} results - Results object
|
|
233
|
+
* @returns {string} Formatted string
|
|
234
|
+
*/
|
|
235
|
+
export function formatResults(results) {
|
|
236
|
+
const lines = [];
|
|
237
|
+
|
|
238
|
+
if (results.success !== undefined) {
|
|
239
|
+
const icon = results.success ? theme.success('✓') : theme.error('✗');
|
|
240
|
+
lines.push(`${icon} ${results.message || ''}`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (results.details) {
|
|
244
|
+
lines.push('');
|
|
245
|
+
lines.push(theme.dim('Details:'));
|
|
246
|
+
Object.entries(results.details).forEach(([key, value]) => {
|
|
247
|
+
lines.push(` ${key}: ${theme.primary(value)}`);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (results.errors && results.errors.length > 0) {
|
|
252
|
+
lines.push('');
|
|
253
|
+
lines.push(theme.error('Errors:'));
|
|
254
|
+
results.errors.forEach(err => {
|
|
255
|
+
lines.push(` ${theme.error('•')} ${err}`);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return lines.join('\n');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ============================================================================
|
|
263
|
+
// NEXT STEPS
|
|
264
|
+
// ============================================================================
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Show next steps guide
|
|
268
|
+
* @param {Array<string>} steps - Array of step descriptions
|
|
269
|
+
*/
|
|
270
|
+
export function showNextSteps(steps) {
|
|
271
|
+
const content = steps
|
|
272
|
+
.map((step, i) => `${theme.primary(`${i + 1}.`)} ${step}`)
|
|
273
|
+
.join('\n');
|
|
274
|
+
|
|
275
|
+
showInfoNote(content, 'Next Steps');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ============================================================================
|
|
279
|
+
// UTILITIES
|
|
280
|
+
// ============================================================================
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Check if value is cancelled
|
|
284
|
+
* @param {*} value - Value to check
|
|
285
|
+
* @returns {boolean}
|
|
286
|
+
*/
|
|
287
|
+
export function isCancelled(value) {
|
|
288
|
+
return p.isCancel(value);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Handle cancellation
|
|
293
|
+
*/
|
|
294
|
+
export function handleCancel() {
|
|
295
|
+
p.cancel('Operation cancelled.');
|
|
296
|
+
process.exit(0);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export default {
|
|
300
|
+
theme,
|
|
301
|
+
showIntro,
|
|
302
|
+
showSuccess,
|
|
303
|
+
showError,
|
|
304
|
+
showInfo,
|
|
305
|
+
showActionMenu,
|
|
306
|
+
confirm,
|
|
307
|
+
textInput,
|
|
308
|
+
createSpinner,
|
|
309
|
+
showNote,
|
|
310
|
+
showSuccessNote,
|
|
311
|
+
showErrorNote,
|
|
312
|
+
showInfoNote,
|
|
313
|
+
formatResults,
|
|
314
|
+
showNextSteps,
|
|
315
|
+
isCancelled,
|
|
316
|
+
handleCancel,
|
|
317
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common UI helpers for Clack-based CLI
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import { loadKnowledge } from "../recall.js";
|
|
6
|
+
import { VERSION } from "../config.js";
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// CLACK SYMBOLS (no emoji for consistency)
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
export const ICONS = {
|
|
13
|
+
brain: "◆",
|
|
14
|
+
learn: "◆",
|
|
15
|
+
recall: "◇",
|
|
16
|
+
stats: "▣",
|
|
17
|
+
success: "✓",
|
|
18
|
+
error: "✖",
|
|
19
|
+
warning: "⚠",
|
|
20
|
+
info: "●"
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// SHARED FUNCTIONS
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Show app header
|
|
29
|
+
*/
|
|
30
|
+
export function showHeader() {
|
|
31
|
+
p.intro(`${ICONS.brain} Agent Skill Kit v${VERSION}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Show outro message
|
|
36
|
+
* @param {string} message
|
|
37
|
+
*/
|
|
38
|
+
export function showSuccess(message) {
|
|
39
|
+
p.outro(`${ICONS.success} ${message}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Show error and exit
|
|
44
|
+
* @param {string} message
|
|
45
|
+
*/
|
|
46
|
+
export function showError(message) {
|
|
47
|
+
p.cancel(`${ICONS.error} ${message}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Handle user cancellation (CTRL+C)
|
|
53
|
+
* @param {any} value
|
|
54
|
+
*/
|
|
55
|
+
export function handleCancel(value) {
|
|
56
|
+
if (p.isCancel(value)) {
|
|
57
|
+
p.cancel("Operation cancelled.");
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get knowledge base with error handling
|
|
64
|
+
* @returns {object}
|
|
65
|
+
*/
|
|
66
|
+
export function getKnowledge() {
|
|
67
|
+
try {
|
|
68
|
+
return loadKnowledge();
|
|
69
|
+
} catch (e) {
|
|
70
|
+
showError("Failed to load knowledge base");
|
|
71
|
+
return { lessons: [] };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Format horizontal line
|
|
77
|
+
* @param {number} width
|
|
78
|
+
*/
|
|
79
|
+
export function line(width = 50) {
|
|
80
|
+
return "─".repeat(width);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { p, VERSION };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Completion UI - Shell completion setup
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import os from "os";
|
|
9
|
+
import {
|
|
10
|
+
getCompletionScript,
|
|
11
|
+
detectShell,
|
|
12
|
+
generatePowerShellCompletion,
|
|
13
|
+
generateBashCompletion,
|
|
14
|
+
generateZshCompletion
|
|
15
|
+
} from "../completion.js";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Interactive completion setup
|
|
19
|
+
*/
|
|
20
|
+
export async function runCompletionUI() {
|
|
21
|
+
p.intro("Shell Completion (Press ESC to exit)");
|
|
22
|
+
|
|
23
|
+
const action = await p.select({
|
|
24
|
+
message: "What would you like to do?",
|
|
25
|
+
options: [
|
|
26
|
+
{ value: "install", label: "Install", hint: "Add shell completions" },
|
|
27
|
+
{ value: "uninstall", label: "Uninstall", hint: "Remove completions" },
|
|
28
|
+
{ value: "back", label: "← Back", hint: "Return to main menu" }
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (p.isCancel(action) || action === "back") {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const shell = await p.select({
|
|
37
|
+
message: "Select shell:",
|
|
38
|
+
options: [
|
|
39
|
+
{ value: "powershell", label: "PowerShell", hint: "Windows default" },
|
|
40
|
+
{ value: "bash", label: "Bash", hint: "Linux/macOS" },
|
|
41
|
+
{ value: "zsh", label: "Zsh", hint: "macOS default" }
|
|
42
|
+
],
|
|
43
|
+
initialValue: detectedShell
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (p.isCancel(shell)) return;
|
|
47
|
+
|
|
48
|
+
const { script } = getCompletionScript(shell);
|
|
49
|
+
|
|
50
|
+
if (action === "show") {
|
|
51
|
+
console.log("\n" + pc.dim("─".repeat(50)));
|
|
52
|
+
console.log(script);
|
|
53
|
+
console.log(pc.dim("─".repeat(50)) + "\n");
|
|
54
|
+
|
|
55
|
+
p.note(
|
|
56
|
+
`Copy the script above and add to your shell profile:\n` +
|
|
57
|
+
`• PowerShell: $PROFILE\n` +
|
|
58
|
+
`• Bash: ~/.bashrc\n` +
|
|
59
|
+
`• Zsh: ~/.zshrc`,
|
|
60
|
+
"Instructions"
|
|
61
|
+
);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (action === "install") {
|
|
66
|
+
const confirm = await p.confirm({
|
|
67
|
+
message: `Install completion for ${shell}?`
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (!confirm) return;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
let profilePath;
|
|
74
|
+
|
|
75
|
+
switch (shell) {
|
|
76
|
+
case "powershell": {
|
|
77
|
+
// Get PowerShell profile path
|
|
78
|
+
const psProfile = process.env.USERPROFILE
|
|
79
|
+
? path.join(process.env.USERPROFILE, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1")
|
|
80
|
+
: path.join(os.homedir(), "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
81
|
+
|
|
82
|
+
profilePath = psProfile;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case "bash":
|
|
86
|
+
profilePath = path.join(os.homedir(), ".bashrc");
|
|
87
|
+
break;
|
|
88
|
+
case "zsh":
|
|
89
|
+
profilePath = path.join(os.homedir(), ".zshrc");
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Ensure directory exists
|
|
94
|
+
fs.mkdirSync(path.dirname(profilePath), { recursive: true });
|
|
95
|
+
|
|
96
|
+
// Check if already installed
|
|
97
|
+
const existing = fs.existsSync(profilePath)
|
|
98
|
+
? fs.readFileSync(profilePath, "utf8")
|
|
99
|
+
: "";
|
|
100
|
+
|
|
101
|
+
if (existing.includes("Agent Skill Kit")) {
|
|
102
|
+
p.note("Completion already installed!", pc.yellow("Skipped"));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Append to profile
|
|
107
|
+
fs.appendFileSync(profilePath, "\n" + script);
|
|
108
|
+
|
|
109
|
+
p.note(
|
|
110
|
+
`Completion installed to:\n${pc.cyan(profilePath)}\n\n` +
|
|
111
|
+
`Restart your terminal or run:\n` +
|
|
112
|
+
(shell === "powershell" ? `. $PROFILE` : `source ${profilePath}`),
|
|
113
|
+
pc.green("Installed")
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
} catch (e) {
|
|
117
|
+
p.note(
|
|
118
|
+
`Could not install automatically.\nError: ${e.message}\n\n` +
|
|
119
|
+
`Please manually add the script to your shell profile.`,
|
|
120
|
+
pc.red("Error")
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export default runCompletionUI;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Select Component - Using @clack/prompts native select
|
|
3
|
+
* This fixes the Windows terminal rendering issues with @clack/core
|
|
4
|
+
*/
|
|
5
|
+
import * as p from "@clack/prompts";
|
|
6
|
+
import pc from "picocolors";
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// CUSTOM ICONS
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
const ITEM_ICONS = {
|
|
13
|
+
routing: "◆",
|
|
14
|
+
learn: "◆",
|
|
15
|
+
recall: "◇",
|
|
16
|
+
stats: "▣",
|
|
17
|
+
settings: "◇",
|
|
18
|
+
backup: "◇",
|
|
19
|
+
export: "◇",
|
|
20
|
+
proposals: "◇",
|
|
21
|
+
completion: "◇",
|
|
22
|
+
init: "◇",
|
|
23
|
+
exit: "×"
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const ITEM_COLORS = {
|
|
27
|
+
routing: pc.cyan,
|
|
28
|
+
learn: pc.green,
|
|
29
|
+
recall: pc.blue,
|
|
30
|
+
stats: pc.yellow,
|
|
31
|
+
settings: pc.cyan,
|
|
32
|
+
backup: pc.gray,
|
|
33
|
+
export: pc.gray,
|
|
34
|
+
proposals: pc.yellow,
|
|
35
|
+
completion: pc.gray,
|
|
36
|
+
init: pc.green,
|
|
37
|
+
exit: pc.red
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// CUSTOM SELECT - Using native @clack/prompts
|
|
42
|
+
// ============================================================================
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Custom select with icons - uses native clack select to fix Windows rendering
|
|
46
|
+
* @param {object} config
|
|
47
|
+
* @returns {Promise<string|symbol>}
|
|
48
|
+
*/
|
|
49
|
+
export async function customSelect(config) {
|
|
50
|
+
const { message, items } = config;
|
|
51
|
+
|
|
52
|
+
// Transform items to clack format - clean labels without icons
|
|
53
|
+
const options = items.map((item) => ({
|
|
54
|
+
value: item.value,
|
|
55
|
+
label: item.label,
|
|
56
|
+
hint: item.hint
|
|
57
|
+
}));
|
|
58
|
+
|
|
59
|
+
const result = await p.select({
|
|
60
|
+
message,
|
|
61
|
+
options,
|
|
62
|
+
initialValue: items[0]?.value
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { ITEM_ICONS, ITEM_COLORS, pc };
|
|
69
|
+
export { isCancel } from "@clack/prompts";
|