@compilr-dev/cli 0.4.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/README.md +110 -0
- package/dist/agent.d.ts +62 -0
- package/dist/agent.js +317 -0
- package/dist/agents/registry.d.ts +66 -0
- package/dist/agents/registry.js +238 -0
- package/dist/agents/types.d.ts +40 -0
- package/dist/agents/types.js +94 -0
- package/dist/commands/custom-registry.d.ts +69 -0
- package/dist/commands/custom-registry.js +246 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/types.d.ts +31 -0
- package/dist/commands/types.js +26 -0
- package/dist/commands.d.ts +63 -0
- package/dist/commands.js +324 -0
- package/dist/db/index.d.ts +42 -0
- package/dist/db/index.js +146 -0
- package/dist/db/repositories/document-repository.d.ts +63 -0
- package/dist/db/repositories/document-repository.js +184 -0
- package/dist/db/repositories/index.d.ts +9 -0
- package/dist/db/repositories/index.js +6 -0
- package/dist/db/repositories/project-repository.d.ts +132 -0
- package/dist/db/repositories/project-repository.js +337 -0
- package/dist/db/repositories/work-item-repository.d.ts +115 -0
- package/dist/db/repositories/work-item-repository.js +389 -0
- package/dist/db/schema.d.ts +83 -0
- package/dist/db/schema.js +143 -0
- package/dist/debug.d.ts +8 -0
- package/dist/debug.js +48 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +348 -0
- package/dist/index.old.d.ts +7 -0
- package/dist/index.old.js +1014 -0
- package/dist/repl.d.ts +121 -0
- package/dist/repl.js +1878 -0
- package/dist/settings/index.d.ts +80 -0
- package/dist/settings/index.js +195 -0
- package/dist/shared-handlers.d.ts +63 -0
- package/dist/shared-handlers.js +57 -0
- package/dist/slash-autocomplete.d.ts +41 -0
- package/dist/slash-autocomplete.js +638 -0
- package/dist/state.d.ts +75 -0
- package/dist/state.js +130 -0
- package/dist/tabbed-menu.d.ts +11 -0
- package/dist/tabbed-menu.js +328 -0
- package/dist/templates/backlog-md.d.ts +7 -0
- package/dist/templates/backlog-md.js +94 -0
- package/dist/templates/claude-md.d.ts +7 -0
- package/dist/templates/claude-md.js +189 -0
- package/dist/templates/coding-standards.d.ts +7 -0
- package/dist/templates/coding-standards.js +299 -0
- package/dist/templates/compilr-md.d.ts +7 -0
- package/dist/templates/compilr-md.js +189 -0
- package/dist/templates/config-json.d.ts +38 -0
- package/dist/templates/config-json.js +39 -0
- package/dist/templates/gitignore.d.ts +7 -0
- package/dist/templates/gitignore.js +85 -0
- package/dist/templates/index.d.ts +19 -0
- package/dist/templates/index.js +302 -0
- package/dist/templates/package-json.d.ts +7 -0
- package/dist/templates/package-json.js +111 -0
- package/dist/templates/readme-md.d.ts +7 -0
- package/dist/templates/readme-md.js +161 -0
- package/dist/templates/tsconfig.d.ts +7 -0
- package/dist/templates/tsconfig.js +61 -0
- package/dist/templates/types.d.ts +33 -0
- package/dist/templates/types.js +24 -0
- package/dist/test-autocomplete.d.ts +7 -0
- package/dist/test-autocomplete.js +85 -0
- package/dist/test-tabbed-menu.d.ts +7 -0
- package/dist/test-tabbed-menu.js +25 -0
- package/dist/themes/colors.d.ts +49 -0
- package/dist/themes/colors.js +135 -0
- package/dist/themes/index.d.ts +23 -0
- package/dist/themes/index.js +24 -0
- package/dist/themes/registry.d.ts +60 -0
- package/dist/themes/registry.js +195 -0
- package/dist/themes/types.d.ts +82 -0
- package/dist/themes/types.js +7 -0
- package/dist/tool-selector.d.ts +71 -0
- package/dist/tool-selector.js +184 -0
- package/dist/tools/ask-user-simple.d.ts +19 -0
- package/dist/tools/ask-user-simple.js +86 -0
- package/dist/tools/ask-user.d.ts +32 -0
- package/dist/tools/ask-user.js +113 -0
- package/dist/tools/backlog.d.ts +53 -0
- package/dist/tools/backlog.js +709 -0
- package/dist/tools.d.ts +15 -0
- package/dist/tools.js +121 -0
- package/dist/ui/agents-overlay.d.ts +12 -0
- package/dist/ui/agents-overlay.js +501 -0
- package/dist/ui/arch-type-overlay.d.ts +20 -0
- package/dist/ui/arch-type-overlay.js +229 -0
- package/dist/ui/ask-user-overlay.d.ts +26 -0
- package/dist/ui/ask-user-overlay.js +647 -0
- package/dist/ui/ask-user-simple-overlay.d.ts +25 -0
- package/dist/ui/ask-user-simple-overlay.js +242 -0
- package/dist/ui/backlog-overlay.d.ts +17 -0
- package/dist/ui/backlog-overlay.js +786 -0
- package/dist/ui/commands-overlay.d.ts +11 -0
- package/dist/ui/commands-overlay.js +410 -0
- package/dist/ui/config-overlay.d.ts +34 -0
- package/dist/ui/config-overlay.js +977 -0
- package/dist/ui/conversation.d.ts +82 -0
- package/dist/ui/conversation.js +508 -0
- package/dist/ui/diff.d.ts +38 -0
- package/dist/ui/diff.js +182 -0
- package/dist/ui/ephemeral.d.ts +111 -0
- package/dist/ui/ephemeral.js +413 -0
- package/dist/ui/file-autocomplete.d.ts +45 -0
- package/dist/ui/file-autocomplete.js +237 -0
- package/dist/ui/footer.d.ts +153 -0
- package/dist/ui/footer.js +422 -0
- package/dist/ui/index.d.ts +12 -0
- package/dist/ui/index.js +15 -0
- package/dist/ui/init-overlay.d.ts +24 -0
- package/dist/ui/init-overlay.js +525 -0
- package/dist/ui/input-prompt-v2.d.ts +179 -0
- package/dist/ui/input-prompt-v2.js +991 -0
- package/dist/ui/input-prompt.d.ts +97 -0
- package/dist/ui/input-prompt.js +800 -0
- package/dist/ui/iteration-limit-overlay.d.ts +21 -0
- package/dist/ui/iteration-limit-overlay.js +150 -0
- package/dist/ui/keys-overlay.d.ts +14 -0
- package/dist/ui/keys-overlay.js +181 -0
- package/dist/ui/model-warning-overlay.d.ts +30 -0
- package/dist/ui/model-warning-overlay.js +171 -0
- package/dist/ui/overlay-controller.d.ts +25 -0
- package/dist/ui/overlay-controller.js +35 -0
- package/dist/ui/overlays.d.ts +47 -0
- package/dist/ui/overlays.js +627 -0
- package/dist/ui/permission-overlay.d.ts +16 -0
- package/dist/ui/permission-overlay.js +494 -0
- package/dist/ui/terminal.d.ts +117 -0
- package/dist/ui/terminal.js +237 -0
- package/dist/ui/todo-zone.d.ts +112 -0
- package/dist/ui/todo-zone.js +353 -0
- package/dist/ui/tools-overlay.d.ts +26 -0
- package/dist/ui/tools-overlay.js +278 -0
- package/dist/ui/tutorial-overlay.d.ts +10 -0
- package/dist/ui/tutorial-overlay.js +936 -0
- package/dist/ui/types.d.ts +103 -0
- package/dist/ui/types.js +33 -0
- package/dist/utils/credentials.d.ts +55 -0
- package/dist/utils/credentials.js +268 -0
- package/dist/utils/model-tiers.d.ts +37 -0
- package/dist/utils/model-tiers.js +118 -0
- package/dist/utils/project-memory.d.ts +47 -0
- package/dist/utils/project-memory.js +117 -0
- package/dist/utils/project-status.d.ts +56 -0
- package/dist/utils/project-status.js +237 -0
- package/package.json +66 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Registry
|
|
3
|
+
*
|
|
4
|
+
* Load, save, and manage themes.
|
|
5
|
+
* Persistence in ~/.compilr-dev/settings.json
|
|
6
|
+
*/
|
|
7
|
+
import type { Theme, ThemeConfig } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get all available themes
|
|
10
|
+
*/
|
|
11
|
+
export declare function getAllThemes(): Theme[];
|
|
12
|
+
/**
|
|
13
|
+
* Get curated/featured themes
|
|
14
|
+
*/
|
|
15
|
+
export declare function getCuratedThemes(): Theme[];
|
|
16
|
+
/**
|
|
17
|
+
* Get theme by ID
|
|
18
|
+
*/
|
|
19
|
+
export declare function getThemeById(id: string): Theme | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Search themes by name (case-insensitive)
|
|
22
|
+
*/
|
|
23
|
+
export declare function searchThemes(query: string): Theme[];
|
|
24
|
+
/**
|
|
25
|
+
* Filter themes by type
|
|
26
|
+
*/
|
|
27
|
+
export declare function filterThemesByType(type: 'all' | 'dark' | 'light'): Theme[];
|
|
28
|
+
/**
|
|
29
|
+
* Search and filter themes
|
|
30
|
+
*/
|
|
31
|
+
export declare function searchAndFilterThemes(query: string, type: 'all' | 'dark' | 'light'): Theme[];
|
|
32
|
+
/**
|
|
33
|
+
* Get theme count
|
|
34
|
+
*/
|
|
35
|
+
export declare function getThemeCount(): {
|
|
36
|
+
total: number;
|
|
37
|
+
dark: number;
|
|
38
|
+
light: number;
|
|
39
|
+
curated: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Load theme config
|
|
43
|
+
*/
|
|
44
|
+
export declare function loadThemeConfig(): ThemeConfig;
|
|
45
|
+
/**
|
|
46
|
+
* Save theme config
|
|
47
|
+
*/
|
|
48
|
+
export declare function saveThemeConfig(config: ThemeConfig): void;
|
|
49
|
+
/**
|
|
50
|
+
* Get current theme (cached)
|
|
51
|
+
*/
|
|
52
|
+
export declare function getCurrentTheme(): Theme;
|
|
53
|
+
/**
|
|
54
|
+
* Set current theme
|
|
55
|
+
*/
|
|
56
|
+
export declare function setCurrentTheme(themeId: string): Theme;
|
|
57
|
+
/**
|
|
58
|
+
* Clear theme cache (for testing or forced reload)
|
|
59
|
+
*/
|
|
60
|
+
export declare function clearThemeCache(): void;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Registry
|
|
3
|
+
*
|
|
4
|
+
* Load, save, and manage themes.
|
|
5
|
+
* Persistence in ~/.compilr-dev/settings.json
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as os from 'os';
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Constants
|
|
12
|
+
// =============================================================================
|
|
13
|
+
const CONFIG_DIR = path.join(os.homedir(), '.compilr-dev');
|
|
14
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'settings.json');
|
|
15
|
+
const DEFAULT_THEME = 'compilr-dark';
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// Theme Data (loaded once)
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// Load themes from JSON file
|
|
20
|
+
// Resolve path relative to this file's location (works in both src and dist)
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
import { dirname } from 'path';
|
|
23
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
24
|
+
const __dirname = dirname(__filename);
|
|
25
|
+
// Try multiple possible locations for themes.json
|
|
26
|
+
function loadThemes() {
|
|
27
|
+
const possiblePaths = [
|
|
28
|
+
path.join(__dirname, '../data/themes.json'), // dist/themes -> dist/data
|
|
29
|
+
path.join(__dirname, '../../src/data/themes.json'), // dist/themes -> src/data
|
|
30
|
+
path.join(__dirname, '../../data/themes.json'), // src/themes -> data (if running from src)
|
|
31
|
+
];
|
|
32
|
+
for (const themePath of possiblePaths) {
|
|
33
|
+
if (fs.existsSync(themePath)) {
|
|
34
|
+
const data = fs.readFileSync(themePath, 'utf-8');
|
|
35
|
+
return JSON.parse(data);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`themes.json not found. Tried: ${possiblePaths.join(', ')}`);
|
|
39
|
+
}
|
|
40
|
+
const themesData = loadThemes();
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// Theme Query Functions
|
|
43
|
+
// =============================================================================
|
|
44
|
+
/**
|
|
45
|
+
* Get all available themes
|
|
46
|
+
*/
|
|
47
|
+
export function getAllThemes() {
|
|
48
|
+
return themesData;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get curated/featured themes
|
|
52
|
+
*/
|
|
53
|
+
export function getCuratedThemes() {
|
|
54
|
+
return themesData.filter((t) => t.curated);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get theme by ID
|
|
58
|
+
*/
|
|
59
|
+
export function getThemeById(id) {
|
|
60
|
+
return themesData.find((t) => t.id === id);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Search themes by name (case-insensitive)
|
|
64
|
+
*/
|
|
65
|
+
export function searchThemes(query) {
|
|
66
|
+
if (!query.trim())
|
|
67
|
+
return themesData;
|
|
68
|
+
const lower = query.toLowerCase();
|
|
69
|
+
return themesData.filter((t) => t.name.toLowerCase().includes(lower));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Filter themes by type
|
|
73
|
+
*/
|
|
74
|
+
export function filterThemesByType(type) {
|
|
75
|
+
if (type === 'all')
|
|
76
|
+
return themesData;
|
|
77
|
+
return themesData.filter((t) => t.type === type);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Search and filter themes
|
|
81
|
+
*/
|
|
82
|
+
export function searchAndFilterThemes(query, type) {
|
|
83
|
+
let results = themesData;
|
|
84
|
+
// Apply type filter
|
|
85
|
+
if (type !== 'all') {
|
|
86
|
+
results = results.filter((t) => t.type === type);
|
|
87
|
+
}
|
|
88
|
+
// Apply search
|
|
89
|
+
if (query.trim()) {
|
|
90
|
+
const lower = query.toLowerCase();
|
|
91
|
+
results = results.filter((t) => t.name.toLowerCase().includes(lower));
|
|
92
|
+
}
|
|
93
|
+
return results;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get theme count
|
|
97
|
+
*/
|
|
98
|
+
export function getThemeCount() {
|
|
99
|
+
return {
|
|
100
|
+
total: themesData.length,
|
|
101
|
+
dark: themesData.filter((t) => t.type === 'dark').length,
|
|
102
|
+
light: themesData.filter((t) => t.type === 'light').length,
|
|
103
|
+
curated: themesData.filter((t) => t.curated).length,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Load settings from config file
|
|
108
|
+
*/
|
|
109
|
+
function loadSettings() {
|
|
110
|
+
try {
|
|
111
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
112
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
113
|
+
return JSON.parse(data);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Ignore errors, return defaults
|
|
118
|
+
}
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Save settings to config file
|
|
123
|
+
*/
|
|
124
|
+
function saveSettings(settings) {
|
|
125
|
+
try {
|
|
126
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
127
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(settings, null, 2), 'utf-8');
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
console.error('Failed to save settings:', error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Load theme config
|
|
135
|
+
*/
|
|
136
|
+
export function loadThemeConfig() {
|
|
137
|
+
const settings = loadSettings();
|
|
138
|
+
return {
|
|
139
|
+
currentTheme: settings.theme || DEFAULT_THEME,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Save theme config
|
|
144
|
+
*/
|
|
145
|
+
export function saveThemeConfig(config) {
|
|
146
|
+
const settings = loadSettings();
|
|
147
|
+
settings.theme = config.currentTheme;
|
|
148
|
+
saveSettings(settings);
|
|
149
|
+
}
|
|
150
|
+
// =============================================================================
|
|
151
|
+
// Current Theme Management
|
|
152
|
+
// =============================================================================
|
|
153
|
+
// In-memory cache of current theme
|
|
154
|
+
let currentThemeCache = null;
|
|
155
|
+
/**
|
|
156
|
+
* Get current theme (cached)
|
|
157
|
+
*/
|
|
158
|
+
export function getCurrentTheme() {
|
|
159
|
+
if (currentThemeCache) {
|
|
160
|
+
return currentThemeCache;
|
|
161
|
+
}
|
|
162
|
+
const config = loadThemeConfig();
|
|
163
|
+
const theme = getThemeById(config.currentTheme);
|
|
164
|
+
if (theme) {
|
|
165
|
+
currentThemeCache = theme;
|
|
166
|
+
return theme;
|
|
167
|
+
}
|
|
168
|
+
// Fallback to default
|
|
169
|
+
const defaultTheme = getThemeById(DEFAULT_THEME);
|
|
170
|
+
if (defaultTheme) {
|
|
171
|
+
currentThemeCache = defaultTheme;
|
|
172
|
+
return defaultTheme;
|
|
173
|
+
}
|
|
174
|
+
// Ultimate fallback - first theme in list
|
|
175
|
+
currentThemeCache = themesData[0];
|
|
176
|
+
return themesData[0];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Set current theme
|
|
180
|
+
*/
|
|
181
|
+
export function setCurrentTheme(themeId) {
|
|
182
|
+
const theme = getThemeById(themeId);
|
|
183
|
+
if (!theme) {
|
|
184
|
+
throw new Error(`Theme not found: ${themeId}`);
|
|
185
|
+
}
|
|
186
|
+
saveThemeConfig({ currentTheme: themeId });
|
|
187
|
+
currentThemeCache = theme;
|
|
188
|
+
return theme;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Clear theme cache (for testing or forced reload)
|
|
192
|
+
*/
|
|
193
|
+
export function clearThemeCache() {
|
|
194
|
+
currentThemeCache = null;
|
|
195
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the 418-theme system.
|
|
5
|
+
* Themes sourced from Ghostty terminal themes (MIT licensed).
|
|
6
|
+
*/
|
|
7
|
+
export interface Theme {
|
|
8
|
+
/** Unique identifier (e.g., "compilr-dark", "dracula") */
|
|
9
|
+
id: string;
|
|
10
|
+
/** Display name (e.g., "compilr.dev Dark", "Dracula") */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Theme type */
|
|
13
|
+
type: 'dark' | 'light';
|
|
14
|
+
/** Source of the theme (e.g., "custom", "ghostty") */
|
|
15
|
+
source: string;
|
|
16
|
+
/** Theme author */
|
|
17
|
+
author?: string;
|
|
18
|
+
/** Color palette */
|
|
19
|
+
colors: ThemeColors;
|
|
20
|
+
/** Whether this is a curated/featured theme */
|
|
21
|
+
curated?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface ThemeColors {
|
|
24
|
+
/** Background color (e.g., "#0A0A0A") */
|
|
25
|
+
background: string;
|
|
26
|
+
/** Foreground/text color (e.g., "#FAFAFA") */
|
|
27
|
+
foreground: string;
|
|
28
|
+
/** Primary accent color (e.g., "#FF5722") */
|
|
29
|
+
primary: string;
|
|
30
|
+
/** Secondary accent color */
|
|
31
|
+
secondary?: string;
|
|
32
|
+
/** Border color */
|
|
33
|
+
border: string;
|
|
34
|
+
/** Card/panel background color */
|
|
35
|
+
card?: string;
|
|
36
|
+
/** Muted/dim text color */
|
|
37
|
+
muted: string;
|
|
38
|
+
/** Selection highlight color */
|
|
39
|
+
selection: string;
|
|
40
|
+
/** Cursor color */
|
|
41
|
+
cursor: string;
|
|
42
|
+
}
|
|
43
|
+
export interface ThemeConfig {
|
|
44
|
+
/** Currently selected theme ID */
|
|
45
|
+
currentTheme: string;
|
|
46
|
+
}
|
|
47
|
+
export interface ThemeStyleFunctions {
|
|
48
|
+
/** Primary accent color (headers, emphasis) */
|
|
49
|
+
primary: (text: string) => string;
|
|
50
|
+
/** Secondary accent color (links, highlights) */
|
|
51
|
+
secondary: (text: string) => string;
|
|
52
|
+
/** Normal foreground text */
|
|
53
|
+
foreground: (text: string) => string;
|
|
54
|
+
/** Muted/dim text (metadata, hints) */
|
|
55
|
+
muted: (text: string) => string;
|
|
56
|
+
/** Border color */
|
|
57
|
+
border: (text: string) => string;
|
|
58
|
+
/** Background color (for background on text) */
|
|
59
|
+
background: (text: string) => string;
|
|
60
|
+
/** Card/panel background color */
|
|
61
|
+
card: (text: string) => string;
|
|
62
|
+
/** Selection highlight color */
|
|
63
|
+
selection: (text: string) => string;
|
|
64
|
+
/** Cursor color */
|
|
65
|
+
cursor: (text: string) => string;
|
|
66
|
+
/** Success messages (green) */
|
|
67
|
+
success: (text: string) => string;
|
|
68
|
+
/** Warning messages (yellow) */
|
|
69
|
+
warning: (text: string) => string;
|
|
70
|
+
/** Error messages (red) */
|
|
71
|
+
error: (text: string) => string;
|
|
72
|
+
/** Info messages (cyan/blue) */
|
|
73
|
+
info: (text: string) => string;
|
|
74
|
+
/** Bold text in primary color */
|
|
75
|
+
primaryBold: (text: string) => string;
|
|
76
|
+
/** Inverse (swap fg/bg) */
|
|
77
|
+
inverse: (text: string) => string;
|
|
78
|
+
/** Text with selection background */
|
|
79
|
+
selected: (text: string) => string;
|
|
80
|
+
/** Text on card background */
|
|
81
|
+
onCard: (text: string) => string;
|
|
82
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Selector - Category-based tool filtering
|
|
3
|
+
*
|
|
4
|
+
* Reduces token usage by selecting only relevant tools based on user intent.
|
|
5
|
+
* This is a PoC implementation to validate the approach before adding to the library.
|
|
6
|
+
*/
|
|
7
|
+
import type { Tool } from '@compilr-dev/agents';
|
|
8
|
+
/**
|
|
9
|
+
* Tool categories for grouping related tools
|
|
10
|
+
*/
|
|
11
|
+
export declare const TOOL_CATEGORIES: Record<string, string[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Intent detection rules - maps keywords to relevant categories
|
|
14
|
+
*/
|
|
15
|
+
export declare const INTENT_RULES: Array<{
|
|
16
|
+
keywords: string[];
|
|
17
|
+
categories: string[];
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Default tools to always include (core functionality)
|
|
21
|
+
*/
|
|
22
|
+
export declare const CORE_TOOLS: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Select relevant tool names based on user message intent
|
|
25
|
+
*/
|
|
26
|
+
export declare function selectToolNamesByIntent(userMessage: string): string[];
|
|
27
|
+
/**
|
|
28
|
+
* Filter tools array to only include selected tool names
|
|
29
|
+
*/
|
|
30
|
+
export declare function filterTools(allTools: Tool[], selectedNames: string[]): Tool[];
|
|
31
|
+
/**
|
|
32
|
+
* Get a human-readable summary of selected tools
|
|
33
|
+
*/
|
|
34
|
+
export declare function getToolSelectionSummary(selectedNames: string[], totalTools: number): string;
|
|
35
|
+
/**
|
|
36
|
+
* Estimate token savings from tool filtering
|
|
37
|
+
*/
|
|
38
|
+
export declare function estimateTokenSavings(selectedCount: number, totalCount: number, avgTokensPerTool?: number): {
|
|
39
|
+
selected: number;
|
|
40
|
+
total: number;
|
|
41
|
+
saved: number;
|
|
42
|
+
percentage: number;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* ToolSelector class for stateful tool selection
|
|
46
|
+
*/
|
|
47
|
+
export declare class ToolSelector {
|
|
48
|
+
private readonly allTools;
|
|
49
|
+
private readonly toolsByName;
|
|
50
|
+
constructor(tools: Tool[]);
|
|
51
|
+
/**
|
|
52
|
+
* Select tools based on user message
|
|
53
|
+
*/
|
|
54
|
+
select(userMessage: string): Tool[];
|
|
55
|
+
/**
|
|
56
|
+
* Get tools by name
|
|
57
|
+
*/
|
|
58
|
+
getToolsByNames(names: string[]): Tool[];
|
|
59
|
+
/**
|
|
60
|
+
* Get all tools
|
|
61
|
+
*/
|
|
62
|
+
getAll(): Tool[];
|
|
63
|
+
/**
|
|
64
|
+
* Get tool count
|
|
65
|
+
*/
|
|
66
|
+
get count(): number;
|
|
67
|
+
/**
|
|
68
|
+
* Get selection summary for a message
|
|
69
|
+
*/
|
|
70
|
+
getSummary(userMessage: string): string;
|
|
71
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Selector - Category-based tool filtering
|
|
3
|
+
*
|
|
4
|
+
* Reduces token usage by selecting only relevant tools based on user intent.
|
|
5
|
+
* This is a PoC implementation to validate the approach before adding to the library.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Tool categories for grouping related tools
|
|
9
|
+
*/
|
|
10
|
+
export const TOOL_CATEGORIES = {
|
|
11
|
+
file_ops: ['read_file', 'write_file', 'edit', 'glob'],
|
|
12
|
+
shell: ['bash'],
|
|
13
|
+
git: ['git_status', 'git_diff', 'git_log', 'git_commit', 'git_branch'],
|
|
14
|
+
search: ['grep', 'glob'],
|
|
15
|
+
project: ['detect_project', 'find_project_root', 'run_tests', 'run_lint'],
|
|
16
|
+
task_mgmt: ['todo_write', 'todo_read'],
|
|
17
|
+
delegation: ['task'],
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Intent detection rules - maps keywords to relevant categories
|
|
21
|
+
*/
|
|
22
|
+
export const INTENT_RULES = [
|
|
23
|
+
// Git operations
|
|
24
|
+
{
|
|
25
|
+
keywords: ['git', 'commit', 'branch', 'diff', 'status', 'log', 'push', 'pull'],
|
|
26
|
+
categories: ['git'],
|
|
27
|
+
},
|
|
28
|
+
// Search operations
|
|
29
|
+
{
|
|
30
|
+
keywords: ['search', 'find', 'grep', 'look for', 'where is', 'locate'],
|
|
31
|
+
categories: ['search', 'file_ops'],
|
|
32
|
+
},
|
|
33
|
+
// Shell/command operations
|
|
34
|
+
{
|
|
35
|
+
keywords: ['run', 'execute', 'command', 'shell', 'echo', 'npm', 'node'],
|
|
36
|
+
categories: ['shell'],
|
|
37
|
+
},
|
|
38
|
+
// Project operations
|
|
39
|
+
{
|
|
40
|
+
keywords: ['test', 'lint', 'build', 'project', 'framework', 'type of'],
|
|
41
|
+
categories: ['project', 'shell'],
|
|
42
|
+
},
|
|
43
|
+
// File operations
|
|
44
|
+
{
|
|
45
|
+
keywords: ['file', 'read', 'write', 'edit', 'create', 'modify', 'replace', 'content'],
|
|
46
|
+
categories: ['file_ops'],
|
|
47
|
+
},
|
|
48
|
+
// Todo operations
|
|
49
|
+
{
|
|
50
|
+
keywords: ['todo', 'task', 'list', 'add item', 'show todos'],
|
|
51
|
+
categories: ['task_mgmt'],
|
|
52
|
+
},
|
|
53
|
+
// Directory/file listing
|
|
54
|
+
{
|
|
55
|
+
keywords: ['list', 'files', 'directory', 'folder', 'typescript', '*.ts'],
|
|
56
|
+
categories: ['file_ops', 'search'],
|
|
57
|
+
},
|
|
58
|
+
// Delegation / sub-agents
|
|
59
|
+
{
|
|
60
|
+
keywords: [
|
|
61
|
+
'explore',
|
|
62
|
+
'investigate',
|
|
63
|
+
'analyze',
|
|
64
|
+
'review code',
|
|
65
|
+
'code review',
|
|
66
|
+
'security audit',
|
|
67
|
+
'refactor',
|
|
68
|
+
'help me find',
|
|
69
|
+
'search the codebase',
|
|
70
|
+
'look through',
|
|
71
|
+
'scan for',
|
|
72
|
+
'debug',
|
|
73
|
+
'figure out',
|
|
74
|
+
'understand',
|
|
75
|
+
'complex task',
|
|
76
|
+
'multi-step',
|
|
77
|
+
'delegate',
|
|
78
|
+
'sub-agent',
|
|
79
|
+
'agent',
|
|
80
|
+
],
|
|
81
|
+
categories: ['delegation', 'search', 'file_ops'],
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
/**
|
|
85
|
+
* Default tools to always include (core functionality)
|
|
86
|
+
*/
|
|
87
|
+
export const CORE_TOOLS = ['bash', 'read_file'];
|
|
88
|
+
/**
|
|
89
|
+
* Select relevant tool names based on user message intent
|
|
90
|
+
*/
|
|
91
|
+
export function selectToolNamesByIntent(userMessage) {
|
|
92
|
+
const message = userMessage.toLowerCase();
|
|
93
|
+
const selectedCategories = new Set();
|
|
94
|
+
// Match intent rules
|
|
95
|
+
for (const rule of INTENT_RULES) {
|
|
96
|
+
if (rule.keywords.some((kw) => message.includes(kw))) {
|
|
97
|
+
rule.categories.forEach((cat) => selectedCategories.add(cat));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// If no categories matched, use default
|
|
101
|
+
if (selectedCategories.size === 0) {
|
|
102
|
+
return [...CORE_TOOLS];
|
|
103
|
+
}
|
|
104
|
+
// Flatten categories to tool names
|
|
105
|
+
const toolNames = new Set(CORE_TOOLS);
|
|
106
|
+
for (const category of selectedCategories) {
|
|
107
|
+
const tools = TOOL_CATEGORIES[category];
|
|
108
|
+
// Always execute - tools is guaranteed to exist by categoryNames definition
|
|
109
|
+
tools.forEach((t) => toolNames.add(t));
|
|
110
|
+
}
|
|
111
|
+
return Array.from(toolNames);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Filter tools array to only include selected tool names
|
|
115
|
+
*/
|
|
116
|
+
export function filterTools(allTools, selectedNames) {
|
|
117
|
+
const nameSet = new Set(selectedNames);
|
|
118
|
+
return allTools.filter((tool) => nameSet.has(tool.definition.name));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get a human-readable summary of selected tools
|
|
122
|
+
*/
|
|
123
|
+
export function getToolSelectionSummary(selectedNames, totalTools) {
|
|
124
|
+
const savings = Math.round((1 - selectedNames.length / totalTools) * 100);
|
|
125
|
+
return `[Tools: ${String(selectedNames.length)}/${String(totalTools)} selected (${String(savings)}% reduction): ${selectedNames.join(', ')}]`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Estimate token savings from tool filtering
|
|
129
|
+
*/
|
|
130
|
+
export function estimateTokenSavings(selectedCount, totalCount, avgTokensPerTool = 200) {
|
|
131
|
+
const selected = selectedCount * avgTokensPerTool;
|
|
132
|
+
const total = totalCount * avgTokensPerTool;
|
|
133
|
+
const saved = total - selected;
|
|
134
|
+
const percentage = Math.round((saved / total) * 100);
|
|
135
|
+
return { selected, total, saved, percentage };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* ToolSelector class for stateful tool selection
|
|
139
|
+
*/
|
|
140
|
+
export class ToolSelector {
|
|
141
|
+
allTools;
|
|
142
|
+
toolsByName;
|
|
143
|
+
constructor(tools) {
|
|
144
|
+
this.allTools = tools;
|
|
145
|
+
this.toolsByName = new Map();
|
|
146
|
+
for (const tool of tools) {
|
|
147
|
+
this.toolsByName.set(tool.definition.name, tool);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Select tools based on user message
|
|
152
|
+
*/
|
|
153
|
+
select(userMessage) {
|
|
154
|
+
const names = selectToolNamesByIntent(userMessage);
|
|
155
|
+
return this.getToolsByNames(names);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get tools by name
|
|
159
|
+
*/
|
|
160
|
+
getToolsByNames(names) {
|
|
161
|
+
return names
|
|
162
|
+
.map((name) => this.toolsByName.get(name))
|
|
163
|
+
.filter((tool) => tool !== undefined);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get all tools
|
|
167
|
+
*/
|
|
168
|
+
getAll() {
|
|
169
|
+
return this.allTools;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get tool count
|
|
173
|
+
*/
|
|
174
|
+
get count() {
|
|
175
|
+
return this.allTools.length;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get selection summary for a message
|
|
179
|
+
*/
|
|
180
|
+
getSummary(userMessage) {
|
|
181
|
+
const selected = selectToolNamesByIntent(userMessage);
|
|
182
|
+
return getToolSelectionSummary(selected, this.allTools.length);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask User Simple Tool - Single question with flat schema
|
|
3
|
+
*
|
|
4
|
+
* A simplified version of ask_user designed for smaller models.
|
|
5
|
+
* Uses a flat schema (no arrays of objects) that's easier for
|
|
6
|
+
* models like Haiku, Flash, and GPT-4o-mini to generate correctly.
|
|
7
|
+
*
|
|
8
|
+
* Used by /sketch command for quick project outlines.
|
|
9
|
+
*/
|
|
10
|
+
interface AskUserSimpleInput {
|
|
11
|
+
/** The question text */
|
|
12
|
+
question: string;
|
|
13
|
+
/** Predefined options (optional, max 5) */
|
|
14
|
+
options?: string[];
|
|
15
|
+
/** Allow free-text input (default: true) */
|
|
16
|
+
allowCustom?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const askUserSimpleTool: import("@compilr-dev/agents").Tool<AskUserSimpleInput>;
|
|
19
|
+
export {};
|