@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
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**
|
package/dist/agent.d.ts
ADDED
|
@@ -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;
|