add-skill-kit 3.2.3 → 3.2.5
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/README.md +1 -1
- package/bin/lib/commands/help.js +0 -4
- package/bin/lib/commands/install.js +90 -9
- package/bin/lib/ui.js +1 -1
- package/lib/agent-cli/__tests__/adaptive_engine.test.js +190 -0
- package/lib/agent-cli/__tests__/integration/cross_script.test.js +222 -0
- package/lib/agent-cli/__tests__/integration/full_cycle.test.js +230 -0
- package/lib/agent-cli/__tests__/pattern_analyzer.test.js +173 -0
- package/lib/agent-cli/__tests__/pre_execution_check.test.js +167 -0
- package/lib/agent-cli/__tests__/skill_injector.test.js +191 -0
- package/lib/agent-cli/bin/agent.js +191 -0
- package/lib/agent-cli/dashboard/dashboard_server.js +340 -0
- package/lib/agent-cli/dashboard/index.html +538 -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 +227 -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 +222 -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 +199 -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/agent-cli/scripts/adaptive_engine.js +381 -0
- package/lib/agent-cli/scripts/dashboard_server.js +224 -0
- package/lib/agent-cli/scripts/error_sensor.js +565 -0
- package/lib/agent-cli/scripts/learn_from_failure.js +225 -0
- package/lib/agent-cli/scripts/pattern_analyzer.js +781 -0
- package/lib/agent-cli/scripts/pre_execution_check.js +623 -0
- package/lib/agent-cli/scripts/rule_sharing.js +374 -0
- package/lib/agent-cli/scripts/skill_injector.js +387 -0
- package/lib/agent-cli/scripts/success_sensor.js +500 -0
- package/lib/agent-cli/scripts/user_correction_sensor.js +426 -0
- package/lib/agent-cli/services/auto-learn-service.js +247 -0
- package/lib/agent-cli/src/MIGRATION.md +418 -0
- package/lib/agent-cli/src/README.md +367 -0
- package/lib/agent-cli/src/core/evolution/evolution-signal.js +42 -0
- package/lib/agent-cli/src/core/evolution/index.js +17 -0
- package/lib/agent-cli/src/core/evolution/review-gate.js +40 -0
- package/lib/agent-cli/src/core/evolution/signal-detector.js +137 -0
- package/lib/agent-cli/src/core/evolution/signal-queue.js +79 -0
- package/lib/agent-cli/src/core/evolution/threshold-checker.js +79 -0
- package/lib/agent-cli/src/core/index.js +15 -0
- package/lib/agent-cli/src/core/learning/cognitive-enhancer.js +282 -0
- package/lib/agent-cli/src/core/learning/index.js +12 -0
- package/lib/agent-cli/src/core/learning/lesson-synthesizer.js +83 -0
- package/lib/agent-cli/src/core/scanning/index.js +14 -0
- package/lib/agent-cli/src/data/index.js +13 -0
- package/lib/agent-cli/src/data/repositories/index.js +8 -0
- package/lib/agent-cli/src/data/repositories/lesson-repository.js +130 -0
- package/lib/agent-cli/src/data/repositories/signal-repository.js +119 -0
- package/lib/agent-cli/src/data/storage/index.js +8 -0
- package/lib/agent-cli/src/data/storage/json-storage.js +64 -0
- package/lib/agent-cli/src/data/storage/yaml-storage.js +66 -0
- package/lib/agent-cli/src/infrastructure/index.js +13 -0
- package/lib/agent-cli/src/presentation/formatters/skill-formatter.js +232 -0
- package/lib/agent-cli/src/services/export-service.js +162 -0
- package/lib/agent-cli/src/services/index.js +13 -0
- package/lib/agent-cli/src/services/learning-service.js +99 -0
- package/lib/agent-cli/types/index.d.ts +343 -0
- package/lib/agent-cli/utils/benchmark.js +269 -0
- package/lib/agent-cli/utils/logger.js +303 -0
- package/lib/agent-cli/utils/ml_patterns.js +300 -0
- package/lib/agent-cli/utils/recovery.js +312 -0
- package/lib/agent-cli/utils/telemetry.js +290 -0
- package/lib/agentskillskit-cli/README.md +21 -0
- package/{node_modules/agentskillskit-cli/bin → lib/agentskillskit-cli}/ag-smart.js +15 -15
- package/lib/agentskillskit-cli/package.json +51 -0
- package/package.json +19 -9
- /package/bin/{cli.js → kit.js} +0 -0
- /package/{node_modules/agentskillskit-cli → lib/agent-cli}/README.md +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lessons UI - View and manage learned lessons
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import { loadKnowledge, saveKnowledge } from "../recall.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Format relative time (e.g., "2 days ago")
|
|
10
|
+
*/
|
|
11
|
+
function formatRelativeTime(date) {
|
|
12
|
+
const now = new Date();
|
|
13
|
+
const diffMs = now - date;
|
|
14
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
15
|
+
|
|
16
|
+
if (diffDays === 0) return 'today';
|
|
17
|
+
if (diffDays === 1) return 'yesterday';
|
|
18
|
+
if (diffDays < 7) return `${diffDays} days ago`;
|
|
19
|
+
if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`;
|
|
20
|
+
if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`;
|
|
21
|
+
return `${Math.floor(diffDays / 365)} years ago`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Interactive lessons viewer
|
|
26
|
+
*/
|
|
27
|
+
export async function runLessonsUI() {
|
|
28
|
+
p.intro("Lessons Manager (Press ESC to exit)");
|
|
29
|
+
|
|
30
|
+
while (true) {
|
|
31
|
+
const db = loadKnowledge();
|
|
32
|
+
|
|
33
|
+
if (!db.lessons || db.lessons.length === 0) {
|
|
34
|
+
p.note("No lessons learned yet.\n\nUse Learn to add patterns.", "Lessons");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Build menu items from lessons with readable titles
|
|
39
|
+
const items = db.lessons.map(lesson => {
|
|
40
|
+
// Use message as title (human-readable)
|
|
41
|
+
const title = lesson.message.substring(0, 60);
|
|
42
|
+
|
|
43
|
+
// Visual differentiation: mistakes vs improvements
|
|
44
|
+
let icon, colorFn;
|
|
45
|
+
if (lesson.type === 'mistake') {
|
|
46
|
+
// Mistakes: red circle
|
|
47
|
+
icon = "🔴";
|
|
48
|
+
colorFn = pc.red;
|
|
49
|
+
} else if (lesson.type === 'improvement') {
|
|
50
|
+
// Improvements: green circle
|
|
51
|
+
icon = "🟢";
|
|
52
|
+
colorFn = pc.green;
|
|
53
|
+
} else {
|
|
54
|
+
// Fallback: severity-based
|
|
55
|
+
icon = lesson.severity === "ERROR" ? "🔴" : "⚠️";
|
|
56
|
+
colorFn = lesson.severity === "ERROR" ? pc.red : pc.yellow;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
value: lesson.id,
|
|
61
|
+
label: `${icon} ${title}${lesson.message.length > 60 ? '...' : ''}`, // Added double space
|
|
62
|
+
hint: `${lesson.hitCount || 0} hits`
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
items.push({ value: "back", label: "← Back", hint: "Return to main menu" });
|
|
67
|
+
|
|
68
|
+
const selected = await p.select({
|
|
69
|
+
message: `${db.lessons.length} lesson(s) available:`,
|
|
70
|
+
options: items
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (p.isCancel(selected) || selected === "back") {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Find and display the selected lesson
|
|
78
|
+
const lesson = db.lessons.find(l => l.id === selected);
|
|
79
|
+
if (!lesson) continue;
|
|
80
|
+
|
|
81
|
+
// Determine lesson type and icon
|
|
82
|
+
const isMistake = lesson.severity && (lesson.severity === "ERROR" || lesson.severity === "WARNING");
|
|
83
|
+
const typeIcon = isMistake ? "❌" : "📝";
|
|
84
|
+
const typeLabel = isMistake ? "Mistake" : "Improvement";
|
|
85
|
+
const typeColor = isMistake ? pc.red : pc.green;
|
|
86
|
+
|
|
87
|
+
// Build user-friendly display
|
|
88
|
+
console.log(`\n${'─'.repeat(60)}`);
|
|
89
|
+
console.log(`${typeIcon} ${pc.bold(lesson.id)} ${pc.dim('│')} ${typeColor(typeLabel)}`);
|
|
90
|
+
console.log(`${'─'.repeat(60)}\n`);
|
|
91
|
+
|
|
92
|
+
// Main message (plain English)
|
|
93
|
+
console.log(pc.bold(lesson.message || 'No description'));
|
|
94
|
+
console.log('');
|
|
95
|
+
|
|
96
|
+
// Example code (if pattern suggests code)
|
|
97
|
+
if (lesson.pattern && !lesson.pattern.includes('TODO')) {
|
|
98
|
+
console.log(pc.dim('Pattern:'));
|
|
99
|
+
console.log(pc.yellow(` ${lesson.pattern}`));
|
|
100
|
+
console.log('');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Recommendation
|
|
104
|
+
if (lesson.recommendation) {
|
|
105
|
+
console.log(pc.dim('Recommendation:'));
|
|
106
|
+
console.log(pc.cyan(` ${lesson.recommendation}`));
|
|
107
|
+
console.log('');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Metrics in single line
|
|
111
|
+
const hits = lesson.hitCount || lesson.appliedCount || 0;
|
|
112
|
+
const dateStr = lesson.addedAt
|
|
113
|
+
? formatRelativeTime(new Date(lesson.addedAt))
|
|
114
|
+
: 'Unknown';
|
|
115
|
+
|
|
116
|
+
console.log(
|
|
117
|
+
`${pc.green('✓')} Applied ${pc.bold(hits)} times ${pc.dim('│')} ` +
|
|
118
|
+
`Added ${pc.dim(dateStr)} ${pc.dim('│')} ` +
|
|
119
|
+
`${pc.dim(lesson.category || 'general')}`
|
|
120
|
+
);
|
|
121
|
+
console.log(`\n${'─'.repeat(60)}\n`);
|
|
122
|
+
|
|
123
|
+
// Actions
|
|
124
|
+
const action = await p.select({
|
|
125
|
+
message: "What would you like to do?",
|
|
126
|
+
options: [
|
|
127
|
+
{ value: "back", label: "← Back", hint: "Return to list" },
|
|
128
|
+
{ value: "delete", label: "Delete lesson", hint: "Remove this lesson" }
|
|
129
|
+
]
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (p.isCancel(action) || action === "back") continue;
|
|
133
|
+
|
|
134
|
+
if (action === "delete") {
|
|
135
|
+
const confirm = await p.confirm({
|
|
136
|
+
message: `Delete lesson ${lesson.id}?`
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
if (confirm) {
|
|
140
|
+
db.lessons = db.lessons.filter(l => l.id !== lesson.id);
|
|
141
|
+
saveKnowledge(db);
|
|
142
|
+
p.log.success(`Deleted ${lesson.id}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export default runLessonsUI;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pretty output formatting for Agent Skill Kit
|
|
3
|
+
* Creates branded, friendly CLI messages
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import pc from "picocolors";
|
|
7
|
+
import boxen from "boxen";
|
|
8
|
+
import { VERSION } from "../config.js";
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// BRANDING
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
/** Brand colors using picocolors */
|
|
15
|
+
const brand = {
|
|
16
|
+
primary: pc.cyan,
|
|
17
|
+
success: pc.green,
|
|
18
|
+
warning: pc.yellow,
|
|
19
|
+
error: pc.red,
|
|
20
|
+
dim: pc.dim,
|
|
21
|
+
bold: pc.bold
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** Simple ASCII logo */
|
|
25
|
+
const LOGO = `
|
|
26
|
+
╭─────────────────────────╮
|
|
27
|
+
│ 🧠 Agent Skill Kit │
|
|
28
|
+
│ v${VERSION} │
|
|
29
|
+
╰─────────────────────────╯
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// MESSAGE FORMATTERS
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Show branded header
|
|
38
|
+
*/
|
|
39
|
+
export function showBrandHeader() {
|
|
40
|
+
console.log(brand.primary(LOGO));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create a nice box message
|
|
45
|
+
* @param {string} message - Message content
|
|
46
|
+
* @param {object} options - Box options
|
|
47
|
+
*/
|
|
48
|
+
export function box(message, options = {}) {
|
|
49
|
+
return "\n" + boxen(message, {
|
|
50
|
+
padding: { top: 0, bottom: 0, left: 1, right: 1 },
|
|
51
|
+
margin: { top: 0, bottom: 1, left: 0, right: 0 },
|
|
52
|
+
borderStyle: "round",
|
|
53
|
+
borderColor: "cyan",
|
|
54
|
+
...options
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Format success message
|
|
60
|
+
* @param {string} message
|
|
61
|
+
*/
|
|
62
|
+
export function success(message) {
|
|
63
|
+
console.log(`${brand.success("✓")} ${message}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Format error message
|
|
68
|
+
* @param {string} message
|
|
69
|
+
*/
|
|
70
|
+
export function error(message) {
|
|
71
|
+
console.log(`${brand.error("✗")} ${message}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Format warning message
|
|
76
|
+
* @param {string} message
|
|
77
|
+
*/
|
|
78
|
+
export function warning(message) {
|
|
79
|
+
console.log(`${brand.warning("!")} ${message}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Format info message
|
|
84
|
+
* @param {string} message
|
|
85
|
+
*/
|
|
86
|
+
export function info(message) {
|
|
87
|
+
console.log(`${brand.dim("›")} ${message}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Show scan summary in a nice format
|
|
92
|
+
* @param {object} stats - { filesScanned, ignored, violations, errors, warnings }
|
|
93
|
+
*/
|
|
94
|
+
export function showScanSummary(stats) {
|
|
95
|
+
const lines = [];
|
|
96
|
+
|
|
97
|
+
if (stats.filesScanned !== undefined) {
|
|
98
|
+
lines.push(` ${brand.success("✓")} ${stats.filesScanned} file(s) scanned`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (stats.ignored > 0) {
|
|
102
|
+
lines.push(` ${brand.dim("›")} ${stats.ignored} paths ignored`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (stats.violations === 0) {
|
|
106
|
+
lines.push(` ${brand.success("✓")} No violations found`);
|
|
107
|
+
} else {
|
|
108
|
+
lines.push(` ${brand.error("✗")} ${stats.violations} violation(s)`);
|
|
109
|
+
if (stats.errors > 0) {
|
|
110
|
+
lines.push(` ${brand.error(`${stats.errors} error(s)`)}`);
|
|
111
|
+
}
|
|
112
|
+
if (stats.warnings > 0) {
|
|
113
|
+
lines.push(` ${brand.warning(`${stats.warnings} warning(s)`)}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log(lines.join("\n"));
|
|
118
|
+
|
|
119
|
+
// Final message with spacing
|
|
120
|
+
if (stats.violations === 0) {
|
|
121
|
+
console.log(`\n ${brand.success(brand.bold("All clear!"))} Your code looks great. 🎉\n`);
|
|
122
|
+
} else {
|
|
123
|
+
console.log(`\n ${brand.warning("Review the issues above before committing.")}\n`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Show a friendly completion message
|
|
129
|
+
* @param {string} action - What was completed
|
|
130
|
+
*/
|
|
131
|
+
export function done(action) {
|
|
132
|
+
console.log(`\n${brand.success("Done!")} ${action}\n`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export default {
|
|
136
|
+
showBrandHeader,
|
|
137
|
+
box,
|
|
138
|
+
success,
|
|
139
|
+
error,
|
|
140
|
+
warning,
|
|
141
|
+
info,
|
|
142
|
+
showScanSummary,
|
|
143
|
+
done,
|
|
144
|
+
brand
|
|
145
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proposals UI - Review and apply AI agent proposals
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import {
|
|
7
|
+
getQualifyingLessons,
|
|
8
|
+
dismissProposal,
|
|
9
|
+
generateProposalMarkdown,
|
|
10
|
+
countPendingProposals
|
|
11
|
+
} from "../proposals.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Interactive proposals menu
|
|
15
|
+
*/
|
|
16
|
+
export async function runProposalsUI() {
|
|
17
|
+
p.intro("Skill Proposals (Press ESC to exit)");
|
|
18
|
+
|
|
19
|
+
while (true) {
|
|
20
|
+
const qualifying = getQualifyingLessons();
|
|
21
|
+
|
|
22
|
+
if (qualifying.length === 0) {
|
|
23
|
+
p.note(
|
|
24
|
+
"No lessons have reached the threshold yet.\nKeep using recall to track patterns!",
|
|
25
|
+
"No Proposals"
|
|
26
|
+
);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Build menu items
|
|
31
|
+
const items = qualifying.map(({ lesson }) => ({
|
|
32
|
+
value: lesson.id,
|
|
33
|
+
label: `[${lesson.id}] ${lesson.message.substring(0, 40)}...`,
|
|
34
|
+
hint: `${lesson.hitCount} hits`
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
items.push({ value: "back", label: "← Back", hint: "Return to main menu" });
|
|
38
|
+
|
|
39
|
+
const selected = await p.select({
|
|
40
|
+
message: "Select a proposal to view:",
|
|
41
|
+
options: items
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (p.isCancel(selected) || selected === "back") {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Find the selected lesson
|
|
49
|
+
const found = qualifying.find(q => q.lesson.id === selected);
|
|
50
|
+
if (!found) continue;
|
|
51
|
+
|
|
52
|
+
// Show proposal
|
|
53
|
+
const markdown = generateProposalMarkdown(found.lesson);
|
|
54
|
+
|
|
55
|
+
console.log("\n" + pc.cyan("─".repeat(60)));
|
|
56
|
+
console.log(markdown);
|
|
57
|
+
console.log(pc.cyan("─".repeat(60)) + "\n");
|
|
58
|
+
|
|
59
|
+
// Actions
|
|
60
|
+
const action = await p.select({
|
|
61
|
+
message: "What would you like to do?",
|
|
62
|
+
options: [
|
|
63
|
+
{ value: "copy", label: "Copy to clipboard", hint: "Ready to paste to AI agent" },
|
|
64
|
+
{ value: "dismiss", label: "Dismiss", hint: "Don't show this again" },
|
|
65
|
+
{ value: "back", label: "← Back", hint: "Return to proposals" }
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (p.isCancel(action) || action === "back") continue;
|
|
70
|
+
|
|
71
|
+
switch (action) {
|
|
72
|
+
case "copy": {
|
|
73
|
+
// Use clipboardy for cross-platform clipboard
|
|
74
|
+
try {
|
|
75
|
+
const clipboard = await import("clipboardy");
|
|
76
|
+
await clipboard.default.write(markdown);
|
|
77
|
+
p.note("Proposal copied! Paste to your AI agent.", pc.green("Copied"));
|
|
78
|
+
} catch (e) {
|
|
79
|
+
p.note(`Could not copy automatically.\nPlease copy the text above manually.`, pc.yellow("Manual Copy"));
|
|
80
|
+
}
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
case "dismiss": {
|
|
85
|
+
const confirm = await p.confirm({
|
|
86
|
+
message: "Dismiss this proposal? It won't appear again."
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (confirm) {
|
|
90
|
+
dismissProposal(found.lesson.id);
|
|
91
|
+
p.note("Proposal dismissed.", pc.dim("✓"));
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export default runProposalsUI;
|