@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.
Files changed (152) hide show
  1. package/README.md +110 -0
  2. package/dist/agent.d.ts +62 -0
  3. package/dist/agent.js +317 -0
  4. package/dist/agents/registry.d.ts +66 -0
  5. package/dist/agents/registry.js +238 -0
  6. package/dist/agents/types.d.ts +40 -0
  7. package/dist/agents/types.js +94 -0
  8. package/dist/commands/custom-registry.d.ts +69 -0
  9. package/dist/commands/custom-registry.js +246 -0
  10. package/dist/commands/index.d.ts +7 -0
  11. package/dist/commands/index.js +7 -0
  12. package/dist/commands/types.d.ts +31 -0
  13. package/dist/commands/types.js +26 -0
  14. package/dist/commands.d.ts +63 -0
  15. package/dist/commands.js +324 -0
  16. package/dist/db/index.d.ts +42 -0
  17. package/dist/db/index.js +146 -0
  18. package/dist/db/repositories/document-repository.d.ts +63 -0
  19. package/dist/db/repositories/document-repository.js +184 -0
  20. package/dist/db/repositories/index.d.ts +9 -0
  21. package/dist/db/repositories/index.js +6 -0
  22. package/dist/db/repositories/project-repository.d.ts +132 -0
  23. package/dist/db/repositories/project-repository.js +337 -0
  24. package/dist/db/repositories/work-item-repository.d.ts +115 -0
  25. package/dist/db/repositories/work-item-repository.js +389 -0
  26. package/dist/db/schema.d.ts +83 -0
  27. package/dist/db/schema.js +143 -0
  28. package/dist/debug.d.ts +8 -0
  29. package/dist/debug.js +48 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +348 -0
  32. package/dist/index.old.d.ts +7 -0
  33. package/dist/index.old.js +1014 -0
  34. package/dist/repl.d.ts +121 -0
  35. package/dist/repl.js +1878 -0
  36. package/dist/settings/index.d.ts +80 -0
  37. package/dist/settings/index.js +195 -0
  38. package/dist/shared-handlers.d.ts +63 -0
  39. package/dist/shared-handlers.js +57 -0
  40. package/dist/slash-autocomplete.d.ts +41 -0
  41. package/dist/slash-autocomplete.js +638 -0
  42. package/dist/state.d.ts +75 -0
  43. package/dist/state.js +130 -0
  44. package/dist/tabbed-menu.d.ts +11 -0
  45. package/dist/tabbed-menu.js +328 -0
  46. package/dist/templates/backlog-md.d.ts +7 -0
  47. package/dist/templates/backlog-md.js +94 -0
  48. package/dist/templates/claude-md.d.ts +7 -0
  49. package/dist/templates/claude-md.js +189 -0
  50. package/dist/templates/coding-standards.d.ts +7 -0
  51. package/dist/templates/coding-standards.js +299 -0
  52. package/dist/templates/compilr-md.d.ts +7 -0
  53. package/dist/templates/compilr-md.js +189 -0
  54. package/dist/templates/config-json.d.ts +38 -0
  55. package/dist/templates/config-json.js +39 -0
  56. package/dist/templates/gitignore.d.ts +7 -0
  57. package/dist/templates/gitignore.js +85 -0
  58. package/dist/templates/index.d.ts +19 -0
  59. package/dist/templates/index.js +302 -0
  60. package/dist/templates/package-json.d.ts +7 -0
  61. package/dist/templates/package-json.js +111 -0
  62. package/dist/templates/readme-md.d.ts +7 -0
  63. package/dist/templates/readme-md.js +161 -0
  64. package/dist/templates/tsconfig.d.ts +7 -0
  65. package/dist/templates/tsconfig.js +61 -0
  66. package/dist/templates/types.d.ts +33 -0
  67. package/dist/templates/types.js +24 -0
  68. package/dist/test-autocomplete.d.ts +7 -0
  69. package/dist/test-autocomplete.js +85 -0
  70. package/dist/test-tabbed-menu.d.ts +7 -0
  71. package/dist/test-tabbed-menu.js +25 -0
  72. package/dist/themes/colors.d.ts +49 -0
  73. package/dist/themes/colors.js +135 -0
  74. package/dist/themes/index.d.ts +23 -0
  75. package/dist/themes/index.js +24 -0
  76. package/dist/themes/registry.d.ts +60 -0
  77. package/dist/themes/registry.js +195 -0
  78. package/dist/themes/types.d.ts +82 -0
  79. package/dist/themes/types.js +7 -0
  80. package/dist/tool-selector.d.ts +71 -0
  81. package/dist/tool-selector.js +184 -0
  82. package/dist/tools/ask-user-simple.d.ts +19 -0
  83. package/dist/tools/ask-user-simple.js +86 -0
  84. package/dist/tools/ask-user.d.ts +32 -0
  85. package/dist/tools/ask-user.js +113 -0
  86. package/dist/tools/backlog.d.ts +53 -0
  87. package/dist/tools/backlog.js +709 -0
  88. package/dist/tools.d.ts +15 -0
  89. package/dist/tools.js +121 -0
  90. package/dist/ui/agents-overlay.d.ts +12 -0
  91. package/dist/ui/agents-overlay.js +501 -0
  92. package/dist/ui/arch-type-overlay.d.ts +20 -0
  93. package/dist/ui/arch-type-overlay.js +229 -0
  94. package/dist/ui/ask-user-overlay.d.ts +26 -0
  95. package/dist/ui/ask-user-overlay.js +647 -0
  96. package/dist/ui/ask-user-simple-overlay.d.ts +25 -0
  97. package/dist/ui/ask-user-simple-overlay.js +242 -0
  98. package/dist/ui/backlog-overlay.d.ts +17 -0
  99. package/dist/ui/backlog-overlay.js +786 -0
  100. package/dist/ui/commands-overlay.d.ts +11 -0
  101. package/dist/ui/commands-overlay.js +410 -0
  102. package/dist/ui/config-overlay.d.ts +34 -0
  103. package/dist/ui/config-overlay.js +977 -0
  104. package/dist/ui/conversation.d.ts +82 -0
  105. package/dist/ui/conversation.js +508 -0
  106. package/dist/ui/diff.d.ts +38 -0
  107. package/dist/ui/diff.js +182 -0
  108. package/dist/ui/ephemeral.d.ts +111 -0
  109. package/dist/ui/ephemeral.js +413 -0
  110. package/dist/ui/file-autocomplete.d.ts +45 -0
  111. package/dist/ui/file-autocomplete.js +237 -0
  112. package/dist/ui/footer.d.ts +153 -0
  113. package/dist/ui/footer.js +422 -0
  114. package/dist/ui/index.d.ts +12 -0
  115. package/dist/ui/index.js +15 -0
  116. package/dist/ui/init-overlay.d.ts +24 -0
  117. package/dist/ui/init-overlay.js +525 -0
  118. package/dist/ui/input-prompt-v2.d.ts +179 -0
  119. package/dist/ui/input-prompt-v2.js +991 -0
  120. package/dist/ui/input-prompt.d.ts +97 -0
  121. package/dist/ui/input-prompt.js +800 -0
  122. package/dist/ui/iteration-limit-overlay.d.ts +21 -0
  123. package/dist/ui/iteration-limit-overlay.js +150 -0
  124. package/dist/ui/keys-overlay.d.ts +14 -0
  125. package/dist/ui/keys-overlay.js +181 -0
  126. package/dist/ui/model-warning-overlay.d.ts +30 -0
  127. package/dist/ui/model-warning-overlay.js +171 -0
  128. package/dist/ui/overlay-controller.d.ts +25 -0
  129. package/dist/ui/overlay-controller.js +35 -0
  130. package/dist/ui/overlays.d.ts +47 -0
  131. package/dist/ui/overlays.js +627 -0
  132. package/dist/ui/permission-overlay.d.ts +16 -0
  133. package/dist/ui/permission-overlay.js +494 -0
  134. package/dist/ui/terminal.d.ts +117 -0
  135. package/dist/ui/terminal.js +237 -0
  136. package/dist/ui/todo-zone.d.ts +112 -0
  137. package/dist/ui/todo-zone.js +353 -0
  138. package/dist/ui/tools-overlay.d.ts +26 -0
  139. package/dist/ui/tools-overlay.js +278 -0
  140. package/dist/ui/tutorial-overlay.d.ts +10 -0
  141. package/dist/ui/tutorial-overlay.js +936 -0
  142. package/dist/ui/types.d.ts +103 -0
  143. package/dist/ui/types.js +33 -0
  144. package/dist/utils/credentials.d.ts +55 -0
  145. package/dist/utils/credentials.js +268 -0
  146. package/dist/utils/model-tiers.d.ts +37 -0
  147. package/dist/utils/model-tiers.js +118 -0
  148. package/dist/utils/project-memory.d.ts +47 -0
  149. package/dist/utils/project-memory.js +117 -0
  150. package/dist/utils/project-status.d.ts +56 -0
  151. package/dist/utils/project-status.js +237 -0
  152. 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,7 @@
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 {};
@@ -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 {};