@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
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # @compilr-dev/cli
2
+
3
+ > AI-powered CLI assistant using @compilr-dev/agents
4
+
5
+ ## Overview
6
+
7
+ An AI coding assistant for the terminal, built with the `@compilr-dev/agents` library. Supports multiple LLM providers (Claude, OpenAI, Gemini, Ollama) with streaming output, tool execution, and context management.
8
+
9
+ ## Features
10
+
11
+ - **Multi-LLM Support** - Claude, OpenAI, Gemini, Ollama
12
+ - **Streaming Output** - Real-time response display with cursor positioning
13
+ - **Tool Execution** - File operations, git, code search, project detection
14
+ - **Context Management** - Auto-compaction, LLM summarization, token tracking
15
+ - **Persistent Footer** - Todo list and input prompt always visible
16
+ - **Input Queueing** - Commands queued during agent execution (FIFO)
17
+ - **Permissions** - Interactive approval for dangerous operations
18
+ - **Esc to Cancel** - Immediately abort running agent
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install -g @compilr-dev/cli
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ```bash
29
+ # Start with default provider (Claude)
30
+ compilr
31
+
32
+ # Use a specific provider
33
+ compilr --provider openai --model gpt-4o
34
+ compilr --provider gemini --model gemini-1.5-pro
35
+ compilr --provider ollama --model llama3.1:8b
36
+
37
+ # Verbose mode (show tool filtering)
38
+ compilr --verbose
39
+ ```
40
+
41
+ ## Slash Commands
42
+
43
+ | Command | Description |
44
+ |---------|-------------|
45
+ | `/help` | Show available commands |
46
+ | `/exit` | Exit the CLI |
47
+ | `/clear` | Clear conversation history |
48
+ | `/compact` | Compress context using LLM summarization |
49
+ | `/tools` | List available tools |
50
+ | `/tokens` | Show token usage |
51
+ | `/context` | Show context statistics |
52
+
53
+ ## Requirements
54
+
55
+ - Node.js 18 or higher
56
+ - API key for your chosen provider:
57
+ - `ANTHROPIC_API_KEY` for Claude
58
+ - `OPENAI_API_KEY` for OpenAI
59
+ - `GOOGLE_API_KEY` for Gemini
60
+ - Ollama running locally (no API key needed)
61
+
62
+ ## Development
63
+
64
+ ```bash
65
+ # Clone the repository
66
+ git clone https://github.com/scozzola/compilr-dev-cli.git
67
+ cd compilr-dev-cli
68
+
69
+ # Install dependencies
70
+ npm install
71
+
72
+ # Run in development mode
73
+ npm run dev
74
+
75
+ # Build for production
76
+ npm run build
77
+ ```
78
+
79
+ ## Architecture
80
+
81
+ - **Runtime:** Node.js 18+
82
+ - **Language:** TypeScript
83
+ - **Agent Framework:** @compilr-dev/agents
84
+ - **Coding Tools:** @compilr-dev/agents-coding
85
+ - **UI:** Custom terminal zones (scrolling + persistent footer)
86
+
87
+ ## Documentation
88
+
89
+ Specs in `/workspace/project-docs/00-requirements/compilr-dev-cli/`:
90
+ - `poc-objectives.md` - Original validation objectives
91
+ - `poc-scope.md` - Feature scope
92
+ - `poc-architecture.md` - Technical design
93
+ - `streaming-output-plan.md` - Streaming implementation
94
+ - `theme-system-spec.md` - Theme configuration
95
+ - `config-overlay-spec.md` - Settings system
96
+
97
+ ## License
98
+
99
+ MIT
100
+
101
+ ## Links
102
+
103
+ - [compilr.dev](https://compilr.dev) - Main website
104
+ - [@compilr-dev/agents](https://www.npmjs.com/package/@compilr-dev/agents) - Agent library
105
+ - [@compilr-dev/agents-coding](https://www.npmjs.com/package/@compilr-dev/agents-coding) - Coding tools
106
+ - [GitHub](https://github.com/scozzola/compilr-dev-cli) - Source code
107
+
108
+ ---
109
+
110
+ **Built with @compilr-dev/agents**
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Agent Configuration
3
+ *
4
+ * Creates and configures the Agent instance with
5
+ * ClaudeProvider, OllamaProvider, OpenAIProvider, or GeminiProvider
6
+ * and available tools.
7
+ */
8
+ import { Agent } from '@compilr-dev/agents';
9
+ import type { AgentEvent, PermissionHandler } from '@compilr-dev/agents';
10
+ /**
11
+ * Supported providers
12
+ */
13
+ export type ProviderType = 'claude' | 'ollama' | 'openai' | 'gemini';
14
+ /**
15
+ * Context passed to onIterationLimitReached callback
16
+ */
17
+ export interface IterationLimitContext {
18
+ iteration: number;
19
+ maxIterations: number;
20
+ toolCallCount: number;
21
+ }
22
+ export interface AgentOptions {
23
+ /** Use minimal tools (for basic testing) */
24
+ minimal?: boolean;
25
+ /** Maximum iterations per request */
26
+ maxIterations?: number;
27
+ /** Enable verbose logging */
28
+ verbose?: boolean;
29
+ /** Provider to use: 'claude' (default), 'ollama', 'openai', or 'gemini' */
30
+ provider?: ProviderType;
31
+ /** Model to use (provider-specific) */
32
+ model?: string;
33
+ /** Permission handler for tool approval prompts */
34
+ onPermissionRequest?: PermissionHandler;
35
+ /** Callback for suggested next actions */
36
+ onSuggest?: (event: Extract<AgentEvent, {
37
+ type: 'suggest';
38
+ }>) => void;
39
+ /**
40
+ * Callback invoked when the agent reaches its iteration limit.
41
+ * Return a number to extend the limit by that many iterations,
42
+ * or false to stop execution.
43
+ */
44
+ onIterationLimitReached?: (context: IterationLimitContext) => Promise<number | false>;
45
+ /**
46
+ * Project context from COMPILR.md or CLAUDE.md.
47
+ * This is appended to the system prompt to give the agent project-specific knowledge.
48
+ */
49
+ projectContext?: string;
50
+ }
51
+ /**
52
+ * Get permission info for a tool by name.
53
+ * Returns undefined if the tool doesn't require special permission (always allowed).
54
+ */
55
+ export declare function getToolPermissionInfo(toolName: string): {
56
+ level: 'once' | 'always' | 'session';
57
+ description: string;
58
+ } | undefined;
59
+ /**
60
+ * Creates an Agent instance configured with all tools.
61
+ */
62
+ export declare function createAgent(options?: AgentOptions): Agent;
package/dist/agent.js ADDED
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Agent Configuration
3
+ *
4
+ * Creates and configures the Agent instance with
5
+ * ClaudeProvider, OllamaProvider, OpenAIProvider, or GeminiProvider
6
+ * and available tools.
7
+ */
8
+ import { Agent, ClaudeProvider, OllamaProvider, OpenAIProvider, GeminiProvider, ContextManager, DEFAULT_CONTEXT_CONFIG, createTaskTool, createSuggestTool, defaultAgentTypes, TOOL_SETS, } from '@compilr-dev/agents';
9
+ import { isAutoCompactEnabled } from './settings/index.js';
10
+ import { getApiKey } from './utils/credentials.js';
11
+ import { createToolRegistry, createMinimalToolRegistry } from './tools.js';
12
+ import { getAgentRegistry } from './agents/registry.js';
13
+ const SYSTEM_PROMPT = `You are a helpful coding assistant running in a terminal.
14
+
15
+ AVAILABLE TOOLS (use these exact names - lowercase with underscores):
16
+
17
+ File Operations:
18
+ - read_file: Read contents of a file (parameter: path)
19
+ - write_file: Create or overwrite a file (parameters: path, content)
20
+ - edit: Replace text in a file (parameters: path, old_text, new_text)
21
+ - glob: Find files matching a pattern (parameters: pattern, path)
22
+ - grep: Search file contents with regex (parameters: pattern, path)
23
+
24
+ Shell:
25
+ - bash: Run shell commands (parameter: command)
26
+ For long-running commands (dev servers, watch modes), use run_in_background=true
27
+ - bash_output: Get output from a background shell (parameter: shell_id)
28
+ - kill_shell: Terminate a background shell (parameter: shell_id)
29
+
30
+ BACKGROUND PROCESSES:
31
+ When running commands that don't exit (like npm run dev, npm start, watch commands):
32
+ 1. Use bash with run_in_background=true to start the process
33
+ 2. The tool returns a shell_id you can use to monitor or kill the process
34
+ 3. Use bash_output with the shell_id to check output/status
35
+ 4. Use kill_shell with the shell_id to stop the process when done
36
+
37
+ Example: Starting a dev server
38
+ bash(command="npm run dev", run_in_background=true) → returns shell_id
39
+ bash_output(shell_id="...") → check if server started
40
+ kill_shell(shell_id="...") → stop when done
41
+
42
+ Git:
43
+ - git_status: Show working tree status
44
+ - git_diff: Show file differences
45
+ - git_log: Show commit history (parameter: limit)
46
+ - git_commit: Create a commit (parameters: message, files)
47
+ - git_branch: List or manage branches
48
+
49
+ Project Analysis:
50
+ - detect_project: Detect project type and framework
51
+ - find_project_root: Find the root directory of the project
52
+ - run_tests: Run project test suite
53
+ - run_lint: Run project linter
54
+
55
+ Task Management:
56
+ - todo_write: Add/update todo items (parameters: todos array)
57
+ - todo_read: View current todo list
58
+
59
+ Next Action Suggestions:
60
+ - suggest: Suggest a next action to the user (parameters: action, reason)
61
+ The suggestion appears as ghost text in the input prompt (user presses Tab to accept).
62
+
63
+ IMPORTANT: Always use 'suggest' after completing a task or answering a question.
64
+ This is a mandatory part of your response workflow, not optional.
65
+
66
+ When to suggest:
67
+ - After ANY tool-based task → suggest verifying, testing, or next logical step
68
+ - After answering a question → suggest a follow-up to explore
69
+ - After explaining something → suggest trying it out or diving deeper
70
+ - When your reply ends with a question → suggest an answer option
71
+
72
+ Good suggestions are short commands or actions: "run npm test", "commit the changes",
73
+ "show me the API endpoints", "explain the error in more detail"
74
+
75
+ Sub-agents (via task tool):
76
+ - task: Spawn a specialized sub-agent for complex, multi-step tasks
77
+ Parameters: description (3-5 words), prompt (detailed task), subagent_type
78
+ Built-in types:
79
+ - explore: Fast codebase search and navigation
80
+ - code-review: Review code for bugs and best practices
81
+ - plan: Break down complex tasks into steps
82
+ - debug: Investigate and fix issues
83
+ - test-runner: Run and analyze tests
84
+ - refactor: Safe code refactoring
85
+ - security-audit: Scan for vulnerabilities
86
+ - doc-lookup: Search documentation
87
+ - general: General-purpose multi-step tasks
88
+ Custom agents may also be available (check /agents command).
89
+
90
+ IMPORTANT RULES:
91
+ 1. Tool names are lowercase with underscores - use them exactly as shown
92
+ 2. If unsure which tool to use, pick the closest match from the list
93
+ 3. For simple questions (math, facts), answer directly without tools
94
+ 4. After calling a tool, you MUST respond with the result to the user - never end silently
95
+ 5. Use the task tool to delegate complex tasks to specialized sub-agents
96
+
97
+ Current working directory: ${process.cwd()}`;
98
+ /**
99
+ * Default permission rules for potentially dangerous operations
100
+ * Note: Tool names are lowercase (bash, write_file, edit, git_commit)
101
+ */
102
+ const DEFAULT_PERMISSION_RULES = [
103
+ // File writes need approval each time (user can see diff before approving)
104
+ { toolName: 'write_file', level: 'once', description: 'Write/create files' },
105
+ { toolName: 'edit', level: 'once', description: 'Edit file contents' },
106
+ // Git operations that modify state
107
+ { toolName: 'git_commit', level: 'once', description: 'Create git commit' },
108
+ { toolName: 'git_branch', level: 'once', description: 'Create/delete git branches' },
109
+ // Shell commands need approval each time
110
+ { toolName: 'bash', level: 'once', description: 'Execute shell command' },
111
+ // Project runners (can have side effects)
112
+ { toolName: 'run_tests', level: 'once', description: 'Run test suite' },
113
+ { toolName: 'run_lint', level: 'once', description: 'Run linter (may auto-fix)' },
114
+ // Local file modifications
115
+ { toolName: 'backlog_write', level: 'once', description: 'Modify backlog file' },
116
+ ];
117
+ /**
118
+ * Get permission info for a tool by name.
119
+ * Returns undefined if the tool doesn't require special permission (always allowed).
120
+ */
121
+ export function getToolPermissionInfo(toolName) {
122
+ const rule = DEFAULT_PERMISSION_RULES.find(r => r.toolName === toolName);
123
+ if (rule) {
124
+ return {
125
+ level: rule.level,
126
+ description: rule.description ?? 'Requires approval',
127
+ };
128
+ }
129
+ return undefined;
130
+ }
131
+ /**
132
+ * Merges built-in agent types with custom agents from registry.
133
+ * Custom agents get safe read-only tools by default.
134
+ */
135
+ function getMergedAgentTypes() {
136
+ const registry = getAgentRegistry();
137
+ const customAgents = registry.getCustomAgents();
138
+ // Start with default agent types (library now has correct tool names)
139
+ const mergedTypes = { ...defaultAgentTypes };
140
+ // Add custom agents from registry
141
+ for (const agent of customAgents) {
142
+ mergedTypes[agent.name] = {
143
+ description: agent.description,
144
+ systemPrompt: agent.systemPrompt,
145
+ defaultModel: agent.model === 'inherit' ? undefined : agent.model,
146
+ // Safe read-only tools for custom agents (using library's TOOL_SETS)
147
+ // Type assertion needed because TOOL_SETS typing might not be exported correctly
148
+ allowedTools: Array.isArray(TOOL_SETS.READ_ONLY) ? [...(TOOL_SETS.READ_ONLY)] : [],
149
+ maxIterations: 10,
150
+ contextMode: 'inherit-summary',
151
+ };
152
+ }
153
+ return mergedTypes;
154
+ }
155
+ /**
156
+ * Creates the appropriate LLM provider based on configuration.
157
+ */
158
+ function createProvider(options) {
159
+ const providerType = options.provider ?? 'claude';
160
+ switch (providerType) {
161
+ case 'ollama': {
162
+ const model = options.model ?? 'llama3.1';
163
+ console.log(`Using Ollama provider with model: ${model}`);
164
+ const provider = new OllamaProvider({
165
+ model,
166
+ baseUrl: process.env.OLLAMA_BASE_URL ?? 'http://localhost:11434',
167
+ });
168
+ return provider;
169
+ }
170
+ case 'openai': {
171
+ const apiKey = getApiKey('openai');
172
+ if (!apiKey) {
173
+ throw new Error('OpenAI API key not found.\n' +
174
+ 'Run /keys to set it, or: export OPENAI_API_KEY=sk-...');
175
+ }
176
+ const model = options.model ?? 'gpt-4o';
177
+ console.log(`Using OpenAI provider with model: ${model}`);
178
+ const provider = new OpenAIProvider({ apiKey, model });
179
+ return provider;
180
+ }
181
+ case 'gemini': {
182
+ const apiKey = getApiKey('google');
183
+ if (!apiKey) {
184
+ throw new Error('Google AI API key not found.\n' +
185
+ 'Run /keys to set it, or: export GOOGLE_API_KEY=AI...');
186
+ }
187
+ const model = options.model ?? 'gemini-2.0-flash';
188
+ console.log(`Using Gemini provider with model: ${model}`);
189
+ const provider = new GeminiProvider({ apiKey, model });
190
+ return provider;
191
+ }
192
+ case 'claude':
193
+ default: {
194
+ const apiKey = getApiKey('anthropic');
195
+ if (!apiKey) {
196
+ throw new Error('Anthropic API key not found.\n' +
197
+ 'Run /keys to set it, or: export ANTHROPIC_API_KEY=sk-ant-...\n' +
198
+ 'Or use --provider ollama for local models.');
199
+ }
200
+ const model = options.model ?? 'claude-sonnet-4-20250514';
201
+ console.log(`Using Claude provider with model: ${model}`);
202
+ return new ClaudeProvider({ apiKey, model });
203
+ }
204
+ }
205
+ }
206
+ /**
207
+ * Returns the context window limit for each provider.
208
+ */
209
+ function getProviderContextLimit(provider) {
210
+ switch (provider) {
211
+ case 'gemini':
212
+ return 1000000; // 1M tokens
213
+ case 'claude':
214
+ return 200000; // 200K tokens
215
+ case 'openai':
216
+ return 128000; // 128K tokens
217
+ case 'ollama':
218
+ return 32000; // Conservative default for local models
219
+ default:
220
+ return 200000;
221
+ }
222
+ }
223
+ /**
224
+ * Creates an Agent instance configured with all tools.
225
+ */
226
+ export function createAgent(options = {}) {
227
+ const provider = createProvider(options);
228
+ // Create context manager with provider-appropriate limits
229
+ // Uses library defaults: compact at 50%, summarize at 90%, emergency at 95%
230
+ // Auto-compact can be disabled via settings (requires restart)
231
+ const autoCompact = isAutoCompactEnabled();
232
+ const contextManager = new ContextManager({
233
+ provider,
234
+ config: {
235
+ maxContextTokens: getProviderContextLimit(options.provider),
236
+ // If auto-compact disabled, set threshold to 100% (never triggers)
237
+ compaction: autoCompact
238
+ ? DEFAULT_CONTEXT_CONFIG.compaction
239
+ : {
240
+ ...DEFAULT_CONTEXT_CONFIG.compaction,
241
+ triggerThreshold: 1.0, // Never auto-trigger
242
+ triggerInterval: Number.MAX_SAFE_INTEGER, // Never interval-trigger
243
+ },
244
+ },
245
+ });
246
+ // Create event handler for verbose mode
247
+ const onEvent = options.verbose
248
+ ? (event) => {
249
+ if (event.type === 'tool_start') {
250
+ console.log(`\n[Tool: ${event.name}] Starting...`);
251
+ }
252
+ else if (event.type === 'tool_end') {
253
+ console.log(`[Tool: ${event.name}] Done`);
254
+ }
255
+ }
256
+ : undefined;
257
+ // Build system prompt with optional project context
258
+ const systemPrompt = options.projectContext
259
+ ? `${SYSTEM_PROMPT}\n\n---\n\n## Project Context\n\nThe following is project-specific context loaded from COMPILR.md:\n\n${options.projectContext}`
260
+ : SYSTEM_PROMPT;
261
+ const agent = new Agent({
262
+ provider,
263
+ systemPrompt,
264
+ maxIterations: options.maxIterations ?? 50,
265
+ onEvent,
266
+ contextManager,
267
+ // Set tool timeout to 2 minutes (default is 30s which is too short for complex operations)
268
+ // Sub-agents inherit this timeout from the parent agent
269
+ toolTimeoutMs: 120000,
270
+ // Enable file tracking for context restoration hints
271
+ enableFileTracking: true,
272
+ // Enable permissions if handler is provided
273
+ permissions: options.onPermissionRequest
274
+ ? {
275
+ enabled: true,
276
+ defaultLevel: 'always', // Allow tools by default, unless specified in rules
277
+ rules: DEFAULT_PERMISSION_RULES,
278
+ onPermissionRequest: options.onPermissionRequest,
279
+ }
280
+ : undefined,
281
+ // Iteration limit handler - asks user if they want to continue
282
+ onIterationLimitReached: options.onIterationLimitReached,
283
+ });
284
+ // Register tools using registerTools method
285
+ const tools = options.minimal
286
+ ? createMinimalToolRegistry()
287
+ : createToolRegistry();
288
+ // Type assertion needed for tool registry compatibility
289
+ agent.registerTools(tools);
290
+ // Register Task tool for sub-agent spawning (only in full mode)
291
+ if (!options.minimal) {
292
+ const taskTool = createTaskTool({
293
+ parentAgent: agent,
294
+ agentTypes: getMergedAgentTypes(),
295
+ enableEventStreaming: true,
296
+ defaultTimeout: 120000, // 2 minutes for subagent operations
297
+ onSpawn: (agentType, description) => {
298
+ if (options.verbose) {
299
+ console.log(`\n[Sub-agent] Spawning ${agentType}: ${description}`);
300
+ }
301
+ },
302
+ onComplete: (agentType, result) => {
303
+ if (options.verbose) {
304
+ console.log(`[Sub-agent] ${agentType} completed (${String(result.iterations)} iterations)`);
305
+ }
306
+ },
307
+ });
308
+ // Type assertion needed for task tool compatibility
309
+ agent.registerTool(taskTool);
310
+ // Register Suggest tool for next action suggestions
311
+ const suggestTool = createSuggestTool({
312
+ onSuggest: options.onSuggest,
313
+ });
314
+ agent.registerTool(suggestTool);
315
+ }
316
+ return agent;
317
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Agent Registry
3
+ *
4
+ * Handles loading, saving, and managing agent definitions.
5
+ * Loads from both project (.compilr-dev/agents/) and user (~/.compilr-dev/agents/) directories.
6
+ */
7
+ import { AgentDefinition, AgentModel } from './types.js';
8
+ export declare class AgentRegistry {
9
+ private readonly projectDir;
10
+ private readonly userDir;
11
+ private customAgents;
12
+ constructor(projectRoot?: string);
13
+ /**
14
+ * Load all custom agents from project and user directories
15
+ */
16
+ load(): void;
17
+ /**
18
+ * Get all built-in agents
19
+ */
20
+ getBuiltinAgents(): AgentDefinition[];
21
+ /**
22
+ * Get all custom agents
23
+ */
24
+ getCustomAgents(): AgentDefinition[];
25
+ /**
26
+ * Get all agents (built-in + custom)
27
+ */
28
+ getAllAgents(): AgentDefinition[];
29
+ /**
30
+ * Get an agent by name
31
+ */
32
+ getAgent(name: string): AgentDefinition | undefined;
33
+ /**
34
+ * Check if an agent name exists
35
+ */
36
+ hasAgent(name: string): boolean;
37
+ /**
38
+ * Save a new custom agent
39
+ */
40
+ saveAgent(agent: {
41
+ name: string;
42
+ description: string;
43
+ model: AgentModel;
44
+ systemPrompt: string;
45
+ }, location: 'project' | 'personal'): string;
46
+ /**
47
+ * Delete a custom agent
48
+ */
49
+ deleteAgent(name: string): boolean;
50
+ /**
51
+ * Get the project agents directory
52
+ */
53
+ getProjectDir(): string;
54
+ /**
55
+ * Get the user agents directory
56
+ */
57
+ getUserDir(): string;
58
+ }
59
+ /**
60
+ * Get the global agent registry instance
61
+ */
62
+ export declare function getAgentRegistry(): AgentRegistry;
63
+ /**
64
+ * Reset the registry (for testing)
65
+ */
66
+ export declare function resetAgentRegistry(): void;