Terminal-based AI coding agent with interactive TUI for autonomous code generation.
Features: - Interactive TUI with React/Ink - Autonomous agent with tool calls (bash, read, write, edit, glob, grep) - Permission system with pattern-based rules - Session management with auto-compaction - Dual providers: GitHub Copilot and Ollama - MCP server integration - Todo panel and theme system - Streaming responses - GitHub-compatible project context
This commit is contained in:
5
src/constants/agent.ts
Normal file
5
src/constants/agent.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Agent constants
|
||||
*/
|
||||
|
||||
export const MAX_ITERATIONS = 50;
|
||||
23
src/constants/auto-scroll.ts
Normal file
23
src/constants/auto-scroll.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Auto-Scroll Constants
|
||||
*
|
||||
* Constants for auto-scroll behavior in the TUI
|
||||
*/
|
||||
|
||||
/** Distance from bottom (in lines) to consider "at bottom" */
|
||||
export const BOTTOM_THRESHOLD = 3;
|
||||
|
||||
/** Settling time after operations complete (ms) */
|
||||
export const SETTLE_TIMEOUT_MS = 300;
|
||||
|
||||
/** Timeout for marking auto-scroll events (ms) */
|
||||
export const AUTO_SCROLL_MARK_TIMEOUT_MS = 250;
|
||||
|
||||
/** Default scroll lines per keyboard event */
|
||||
export const KEYBOARD_SCROLL_LINES = 3;
|
||||
|
||||
/** Default scroll lines per page event */
|
||||
export const PAGE_SCROLL_LINES = 10;
|
||||
|
||||
/** Mouse scroll lines per wheel event */
|
||||
export const MOUSE_SCROLL_LINES = 3;
|
||||
103
src/constants/banner.ts
Normal file
103
src/constants/banner.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Banner constants for CodeTyper CLI
|
||||
*/
|
||||
|
||||
// ASCII art for "codetyper" using block characters
|
||||
export const BANNER_LINES = [
|
||||
" __ __ ",
|
||||
" _______ _____/ /__ / /___ ______ ___ _____ ",
|
||||
" / ___/ / / / _ \\/ _ \\/ __/ / / / __ \\/ _ \\/ ___/ ",
|
||||
"/ /__/ /_/ / __/ __/ /_/ /_/ / /_/ / __/ / ",
|
||||
"\\___/\\____/\\___/\\___/\\__/\\__, / .___/\\___/_/ ",
|
||||
" /____/_/ ",
|
||||
] as const;
|
||||
|
||||
// Alternative minimal banner
|
||||
export const BANNER_MINIMAL = [
|
||||
"╭───────────────────────────────────────╮",
|
||||
"│ ▄▀▀ ▄▀▄ █▀▄ ██▀ ▀█▀ ▀▄▀ █▀▄ ██▀ █▀▄ │",
|
||||
"│ ▀▄▄ ▀▄▀ █▄▀ █▄▄ █ █ █▀ █▄▄ █▀▄ │",
|
||||
"╰───────────────────────────────────────╯",
|
||||
] as const;
|
||||
|
||||
// Block-style banner (similar to opencode)
|
||||
export const BANNER_BLOCKS = [
|
||||
"█▀▀ █▀█ █▀▄ █▀▀ ▀█▀ █▄█ █▀█ █▀▀ █▀█",
|
||||
"█ █ █ █ █ █▀▀ █ █ █▀▀ █▀▀ █▀▄",
|
||||
"▀▀▀ ▀▀▀ ▀▀ ▀▀▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀",
|
||||
] as const;
|
||||
|
||||
// Gradient colors for banner (cyan to blue)
|
||||
export const GRADIENT_COLORS = [
|
||||
"\x1b[96m", // Bright cyan
|
||||
"\x1b[36m", // Cyan
|
||||
"\x1b[94m", // Bright blue
|
||||
"\x1b[34m", // Blue
|
||||
"\x1b[95m", // Bright magenta
|
||||
"\x1b[35m", // Magenta
|
||||
] as const;
|
||||
|
||||
// Banner style to lines mapping
|
||||
export const BANNER_STYLE_MAP: Record<string, readonly string[]> = {
|
||||
default: BANNER_LINES,
|
||||
minimal: BANNER_MINIMAL,
|
||||
blocks: BANNER_BLOCKS,
|
||||
} as const;
|
||||
|
||||
// Large ASCII art banner
|
||||
export const BANNER = `
|
||||
,gggg, _,gggggg,_ ,gggggggggggg, ,ggggggg, ,ggggggggggggggg ,ggg, gg ,ggggggggggg, ,ggggggg, ,ggggggggggg,
|
||||
,88"""Y8b, ,d8P""d8P"Y8b, dP"""88""""""Y8b, ,dP"""""""Y8bdP""""""88"""""""dP""Y8a 88 dP"""88""""""Y8, ,dP"""""""Y8bdP"""88""""""Y8,
|
||||
d8" \`Y8,d8' Y8 "8b,dPYb, 88 \`8b, d8' a Y8Yb,_ 88 Yb, \`88 88 Yb, 88 \`8b d8' a Y8Yb, 88 \`8b
|
||||
d8' 8b d8d8' \`Ybaaad88P' \`" 88 \`8b 88 "Y8P' \`"" 88 \`" 88 88 \`" 88 ,8P 88 "Y8P' \`" 88 ,8P
|
||||
,8I "Y88P'8P \`"""Y8 88 Y8 \`8baaaa 88 88 88 88aaaad8P" \`8baaaa 88aaaad8P"
|
||||
I8' 8b d8 88 d8,d8P"""" 88 88 88 88""""" ,d8P"""" 88""""Yb,
|
||||
d8 Y8, ,8P 88 ,8Pd8" 88 88 ,88 88 d8" 88 "8b
|
||||
Y8, \`Y8, ,8P' 88 ,8P'Y8, gg, 88 Y8b,___,d888 88 Y8, 88 \`8i
|
||||
\`Yba,,_____, \`Y8b,,__,,d8P' 88______,dP' \`Yba,,_____, "Yb,,8P "Y88888P"88, 88 \`Yba,,_____, 88 Yb,
|
||||
\`"Y8888888 \`"Y8888P"' 888888888P" \`"Y8888888 "Y8P' ,ad8888 88 \`"Y8888888 88 Y8
|
||||
d8P" 88
|
||||
,d8' 88
|
||||
d8' 88
|
||||
88 88
|
||||
Y8,_ _,88
|
||||
"Y888P"
|
||||
`;
|
||||
|
||||
// Welcome message with help information
|
||||
export const WELCOME_MESSAGE = `
|
||||
🤖 CodeTyper AI Agent - Autonomous Code Generation Assistant
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Default Provider: GitHub Copilot (gpt-4)
|
||||
|
||||
Getting Started:
|
||||
codetyper chat Start interactive chat
|
||||
codetyper run "your task" Execute autonomous task
|
||||
codetyper classify "prompt" Analyze intent
|
||||
codetyper config show View configuration
|
||||
|
||||
Commands:
|
||||
chat Interactive REPL session
|
||||
run <task> Execute task autonomously
|
||||
classify <prompt> Classify user intent
|
||||
plan <intent> Generate execution plan
|
||||
validate <plan> Validate plan safety
|
||||
config Manage configuration
|
||||
serve Start JSON-RPC server
|
||||
|
||||
Options:
|
||||
--help, -h Show help
|
||||
--version, -V Show version
|
||||
|
||||
Chat Commands:
|
||||
/help Show help
|
||||
/models View available LLM providers
|
||||
/provider Switch LLM provider
|
||||
/files List context files
|
||||
/clear Clear conversation
|
||||
/exit Exit chat
|
||||
|
||||
💡 Tip: Use 'codetyper chat' then '/models' to see all available providers
|
||||
📖 Docs: Run 'codetyper --help <command>' for detailed information
|
||||
`;
|
||||
30
src/constants/bash.ts
Normal file
30
src/constants/bash.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Bash tool constants
|
||||
*/
|
||||
|
||||
export const BASH_DEFAULTS = {
|
||||
MAX_OUTPUT_LENGTH: 30000,
|
||||
TIMEOUT: 120000,
|
||||
KILL_DELAY: 1000,
|
||||
} as const;
|
||||
|
||||
export const BASH_SIGNALS = {
|
||||
TERMINATE: "SIGTERM",
|
||||
KILL: "SIGKILL",
|
||||
} as const;
|
||||
|
||||
export const BASH_MESSAGES = {
|
||||
PERMISSION_DENIED: "Permission denied by user",
|
||||
TIMED_OUT: (timeout: number) => `Command timed out after ${timeout}ms`,
|
||||
ABORTED: "Command aborted",
|
||||
EXIT_CODE: (code: number) => `Command exited with code ${code}`,
|
||||
TRUNCATED: "\n\n... (truncated)",
|
||||
} as const;
|
||||
|
||||
export const BASH_DESCRIPTION = `Execute a shell command. Use this tool to run commands like git, npm, mkdir, etc.
|
||||
|
||||
Guidelines:
|
||||
- Always provide a clear description of what the command does
|
||||
- Use absolute paths when possible
|
||||
- Be careful with destructive commands (rm, etc.)
|
||||
- Commands that modify the filesystem will require user approval`;
|
||||
20
src/constants/bashPatterns.ts
Normal file
20
src/constants/bashPatterns.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/** Quiet bash commands - read-only exploration operations */
|
||||
export const QUIET_BASH_PATTERNS = [
|
||||
/^ls\b/,
|
||||
/^cat\b/,
|
||||
/^head\b/,
|
||||
/^tail\b/,
|
||||
/^find\b/,
|
||||
/^grep\b/,
|
||||
/^rg\b/,
|
||||
/^fd\b/,
|
||||
/^tree\b/,
|
||||
/^pwd\b/,
|
||||
/^echo\b/,
|
||||
/^which\b/,
|
||||
/^file\b/,
|
||||
/^stat\b/,
|
||||
/^wc\b/,
|
||||
/^du\b/,
|
||||
/^df\b/,
|
||||
];
|
||||
106
src/constants/chat-service.ts
Normal file
106
src/constants/chat-service.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Chat service constants
|
||||
*/
|
||||
|
||||
export const CHAT_TRUNCATE_DEFAULTS = {
|
||||
MAX_LINES: 10,
|
||||
MAX_LENGTH: 500,
|
||||
} as const;
|
||||
|
||||
export const FILE_SIZE_LIMITS = {
|
||||
MAX_CONTEXT_FILE_SIZE: 100000,
|
||||
} as const;
|
||||
|
||||
export const DIFF_PATTERNS = [
|
||||
/@@\s*-\d+/m,
|
||||
/---\s+[ab]?\//m,
|
||||
/\+\+\+\s+[ab]?\//m,
|
||||
] as const;
|
||||
|
||||
export const GLOB_IGNORE_PATTERNS = [
|
||||
"**/node_modules/**",
|
||||
"**/.git/**",
|
||||
] as const;
|
||||
|
||||
export const CHAT_MESSAGES = {
|
||||
CONVERSATION_CLEARED: "Conversation cleared",
|
||||
SESSION_SAVED: "Session saved",
|
||||
LEARNING_SAVED: (scope: string) => `Learning saved (${scope})`,
|
||||
LEARNING_SKIPPED: "Learning skipped",
|
||||
NO_LEARNINGS:
|
||||
"No learnings saved yet. Use /remember to save learnings about your project.",
|
||||
NO_CONVERSATION:
|
||||
"No conversation to create learning from. Start a conversation first.",
|
||||
NO_LEARNINGS_DETECTED:
|
||||
'No learnings detected from the last exchange. Try being more explicit about preferences (e.g., "always use TypeScript", "prefer functional style").',
|
||||
UNKNOWN_COMMAND: (cmd: string) => `Unknown command: ${cmd}`,
|
||||
FILE_NOT_FOUND: (pattern: string) => `File not found: ${pattern}`,
|
||||
FILE_TOO_LARGE: (name: string, size: number) =>
|
||||
`File too large: ${name} (${Math.round(size / 1024)}KB)`,
|
||||
FILE_IS_BINARY: (name: string) => `Cannot add binary file: ${name}`,
|
||||
FILE_ADDED: (name: string) => `Added to context: ${name}`,
|
||||
FILE_ADD_FAILED: (error: unknown) => `Failed to add file: ${error}`,
|
||||
FILE_READ_FAILED: (error: unknown) => `Failed to read file: ${error}`,
|
||||
ANALYZE_FILES: "Analyze the files I've added to the context.",
|
||||
GITHUB_ISSUES_FOUND: (count: number, issues: string) =>
|
||||
`Found ${count} GitHub issue(s): ${issues}`,
|
||||
COMPACTION_STARTING: "Summarizing conversation history...",
|
||||
COMPACTION_CONTINUING: "Continuing with your request...",
|
||||
} as const;
|
||||
|
||||
export const AUTH_MESSAGES = {
|
||||
ALREADY_LOGGED_IN: "Already logged in. Use /logout first to re-authenticate.",
|
||||
AUTH_SUCCESS: "Successfully authenticated with GitHub Copilot!",
|
||||
AUTH_FAILED: (error: string) => `Authentication failed: ${error}`,
|
||||
AUTH_START_FAILED: (error: string) =>
|
||||
`Failed to start authentication: ${error}`,
|
||||
LOGGED_OUT:
|
||||
"Logged out from GitHub Copilot. Run /login to authenticate again.",
|
||||
NOT_LOGGED_IN: "Not logged in. Run /login to authenticate.",
|
||||
NO_LOGIN_REQUIRED: (provider: string) =>
|
||||
`Provider ${provider} doesn't require login.`,
|
||||
NO_LOGOUT_SUPPORT: (provider: string) =>
|
||||
`Provider ${provider} doesn't support logout.`,
|
||||
OLLAMA_NO_AUTH: "Ollama is a local provider - no authentication required.",
|
||||
COPILOT_AUTH_INSTRUCTIONS: (uri: string, code: string) =>
|
||||
`To authenticate with GitHub Copilot:\n\n1. Open: ${uri}\n2. Enter code: ${code}\n\nWaiting for authentication...`,
|
||||
LOGGED_IN_AS: (login: string, name?: string) =>
|
||||
`Logged in as: ${login}${name ? ` (${name})` : ""}`,
|
||||
} as const;
|
||||
|
||||
export const MODEL_MESSAGES = {
|
||||
MODEL_AUTO: "Model set to auto - the provider will choose the best model.",
|
||||
MODEL_CHANGED: (model: string) => `Model changed to: ${model}`,
|
||||
} as const;
|
||||
|
||||
// Re-export HELP_TEXT from prompts for backward compatibility
|
||||
export { HELP_TEXT } from "@prompts/ui/help";
|
||||
|
||||
export const LEARNING_CONFIDENCE_THRESHOLD = 0.7;
|
||||
export const MAX_LEARNINGS_DISPLAY = 20;
|
||||
|
||||
export type CommandName =
|
||||
| "help"
|
||||
| "h"
|
||||
| "clear"
|
||||
| "c"
|
||||
| "save"
|
||||
| "s"
|
||||
| "context"
|
||||
| "usage"
|
||||
| "u"
|
||||
| "model"
|
||||
| "models"
|
||||
| "agent"
|
||||
| "a"
|
||||
| "theme"
|
||||
| "mcp"
|
||||
| "mode"
|
||||
| "whoami"
|
||||
| "login"
|
||||
| "logout"
|
||||
| "provider"
|
||||
| "p"
|
||||
| "status"
|
||||
| "remember"
|
||||
| "learnings";
|
||||
85
src/constants/command-suggestion.ts
Normal file
85
src/constants/command-suggestion.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Command suggestion constants
|
||||
*/
|
||||
|
||||
import type { SuggestionPriority } from "@/types/command-suggestion";
|
||||
|
||||
export const PROJECT_FILES = {
|
||||
PACKAGE_JSON: "package.json",
|
||||
YARN_LOCK: "yarn.lock",
|
||||
PNPM_LOCK: "pnpm-lock.yaml",
|
||||
BUN_LOCK: "bun.lockb",
|
||||
CARGO_TOML: "Cargo.toml",
|
||||
GO_MOD: "go.mod",
|
||||
PYPROJECT: "pyproject.toml",
|
||||
REQUIREMENTS: "requirements.txt",
|
||||
MAKEFILE: "Makefile",
|
||||
DOCKERFILE: "Dockerfile",
|
||||
} as const;
|
||||
|
||||
export const PRIORITY_ORDER: Record<SuggestionPriority, number> = {
|
||||
high: 0,
|
||||
medium: 1,
|
||||
low: 2,
|
||||
};
|
||||
|
||||
export const PRIORITY_ICONS: Record<SuggestionPriority, string> = {
|
||||
high: "⚡",
|
||||
medium: "→",
|
||||
low: "·",
|
||||
};
|
||||
|
||||
export const FILE_PATTERNS = {
|
||||
PACKAGE_JSON: /package\.json$/,
|
||||
TSCONFIG: /tsconfig.*\.json$/,
|
||||
SOURCE_FILES: /\.(ts|tsx|js|jsx)$/,
|
||||
CARGO_TOML: /Cargo\.toml$/,
|
||||
GO_MOD: /go\.mod$/,
|
||||
PYTHON_DEPS: /requirements.*\.txt$|pyproject\.toml$/,
|
||||
DOCKER: /Dockerfile$|docker-compose.*\.ya?ml$/,
|
||||
MAKEFILE: /Makefile$/,
|
||||
MIGRATIONS: /migrations?\/.*\.(sql|ts|js)$/,
|
||||
ENV_EXAMPLE: /\.env\.example$|\.env\.sample$/,
|
||||
LINTER_CONFIG: /\.eslintrc|\.prettierrc|eslint\.config|prettier\.config/,
|
||||
TEST_FILE: /\.test\.|\.spec\.|__tests__/,
|
||||
} as const;
|
||||
|
||||
export const CONTENT_PATTERNS = {
|
||||
DEPENDENCIES: /\"dependencies\"/,
|
||||
DEV_DEPENDENCIES: /\"devDependencies\"/,
|
||||
PEER_DEPENDENCIES: /\"peerDependencies\"/,
|
||||
} as const;
|
||||
|
||||
export const SUGGESTION_MESSAGES = {
|
||||
INSTALL_DEPS: "Install dependencies",
|
||||
REBUILD_PROJECT: "Rebuild the project",
|
||||
RUN_TESTS: "Run tests",
|
||||
START_DEV: "Start development server",
|
||||
BUILD_RUST: "Build the Rust project",
|
||||
TIDY_GO: "Tidy Go modules",
|
||||
INSTALL_PYTHON_EDITABLE: "Install Python package in editable mode",
|
||||
INSTALL_PYTHON_DEPS: "Install Python dependencies",
|
||||
DOCKER_COMPOSE_BUILD: "Rebuild and start Docker containers",
|
||||
DOCKER_BUILD: "Rebuild Docker image",
|
||||
RUN_MAKE: "Run make",
|
||||
RUN_MIGRATE: "Run database migrations",
|
||||
CREATE_ENV: "Create local .env file",
|
||||
RUN_LINT: "Run linter to check for issues",
|
||||
} as const;
|
||||
|
||||
export const SUGGESTION_REASONS = {
|
||||
PACKAGE_JSON_MODIFIED: "package.json was modified",
|
||||
TSCONFIG_CHANGED: "TypeScript configuration changed",
|
||||
TEST_FILE_MODIFIED: "Test file was modified",
|
||||
SOURCE_FILE_MODIFIED: "Source file was modified",
|
||||
CARGO_MODIFIED: "Cargo.toml was modified",
|
||||
GO_MOD_MODIFIED: "go.mod was modified",
|
||||
PYTHON_DEPS_CHANGED: "Python dependencies changed",
|
||||
REQUIREMENTS_MODIFIED: "requirements.txt was modified",
|
||||
DOCKER_COMPOSE_CHANGED: "Docker Compose configuration changed",
|
||||
DOCKERFILE_MODIFIED: "Dockerfile was modified",
|
||||
MAKEFILE_MODIFIED: "Makefile was modified",
|
||||
MIGRATION_MODIFIED: "Migration file was added or modified",
|
||||
ENV_TEMPLATE_MODIFIED: "Environment template was modified",
|
||||
LINTER_CONFIG_CHANGED: "Linter configuration changed",
|
||||
} as const;
|
||||
114
src/constants/components.ts
Normal file
114
src/constants/components.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* UI component constants
|
||||
*/
|
||||
|
||||
// Box drawing characters
|
||||
export const BoxChars = {
|
||||
// Single line
|
||||
single: {
|
||||
topLeft: "┌",
|
||||
topRight: "┐",
|
||||
bottomLeft: "└",
|
||||
bottomRight: "┘",
|
||||
horizontal: "─",
|
||||
vertical: "│",
|
||||
leftT: "├",
|
||||
rightT: "┤",
|
||||
topT: "┬",
|
||||
bottomT: "┴",
|
||||
cross: "┼",
|
||||
},
|
||||
// Double line
|
||||
double: {
|
||||
topLeft: "╔",
|
||||
topRight: "╗",
|
||||
bottomLeft: "╚",
|
||||
bottomRight: "╝",
|
||||
horizontal: "═",
|
||||
vertical: "║",
|
||||
leftT: "╠",
|
||||
rightT: "╣",
|
||||
topT: "╦",
|
||||
bottomT: "╩",
|
||||
cross: "╬",
|
||||
},
|
||||
// Rounded
|
||||
rounded: {
|
||||
topLeft: "╭",
|
||||
topRight: "╮",
|
||||
bottomLeft: "╰",
|
||||
bottomRight: "╯",
|
||||
horizontal: "─",
|
||||
vertical: "│",
|
||||
leftT: "├",
|
||||
rightT: "┤",
|
||||
topT: "┬",
|
||||
bottomT: "┴",
|
||||
cross: "┼",
|
||||
},
|
||||
// Bold
|
||||
bold: {
|
||||
topLeft: "┏",
|
||||
topRight: "┓",
|
||||
bottomLeft: "┗",
|
||||
bottomRight: "┛",
|
||||
horizontal: "━",
|
||||
vertical: "┃",
|
||||
leftT: "┣",
|
||||
rightT: "┫",
|
||||
topT: "┳",
|
||||
bottomT: "┻",
|
||||
cross: "╋",
|
||||
},
|
||||
} as const;
|
||||
|
||||
// Default box options
|
||||
export const BOX_DEFAULTS = {
|
||||
style: "rounded" as const,
|
||||
padding: 1,
|
||||
align: "left" as const,
|
||||
} as const;
|
||||
|
||||
// Tool icon mapping
|
||||
export const TOOL_ICONS = {
|
||||
bash: "bash",
|
||||
read: "read",
|
||||
write: "write",
|
||||
edit: "edit",
|
||||
default: "default",
|
||||
} as const;
|
||||
|
||||
// State color mapping
|
||||
export const STATE_COLORS = {
|
||||
pending: "DIM",
|
||||
running: "primary",
|
||||
success: "success",
|
||||
error: "error",
|
||||
} as const;
|
||||
|
||||
// Role configuration for message display
|
||||
export const ROLE_CONFIG = {
|
||||
user: { label: "You", colorKey: "primary" },
|
||||
assistant: { label: "CodeTyper", colorKey: "success" },
|
||||
system: { label: "System", colorKey: "textMuted" },
|
||||
tool: { label: "Tool", colorKey: "warning" },
|
||||
} as const;
|
||||
|
||||
// Status indicator configuration
|
||||
export const STATUS_INDICATORS = {
|
||||
success: { iconKey: "success", colorKey: "success" },
|
||||
error: { iconKey: "error", colorKey: "error" },
|
||||
warning: { iconKey: "warning", colorKey: "warning" },
|
||||
info: { iconKey: "info", colorKey: "info" },
|
||||
pending: { iconKey: "pending", colorKey: "textMuted" },
|
||||
running: { iconKey: "running", colorKey: "primary" },
|
||||
} as const;
|
||||
|
||||
// Tool call icon configuration
|
||||
export const TOOL_CALL_ICONS = {
|
||||
bash: { iconKey: "bash", colorKey: "warning" },
|
||||
read: { iconKey: "read", colorKey: "info" },
|
||||
write: { iconKey: "write", colorKey: "success" },
|
||||
edit: { iconKey: "edit", colorKey: "primary" },
|
||||
default: { iconKey: "gear", colorKey: "textMuted" },
|
||||
} as const;
|
||||
213
src/constants/copilot.ts
Normal file
213
src/constants/copilot.ts
Normal file
@@ -0,0 +1,213 @@
|
||||
import type { ProviderModel, ProviderName } from "@/types/providers";
|
||||
|
||||
// Provider identification
|
||||
export const COPILOT_PROVIDER_NAME: ProviderName = "copilot";
|
||||
export const COPILOT_DISPLAY_NAME = "GitHub Copilot";
|
||||
|
||||
// GitHub Copilot API endpoints
|
||||
export const COPILOT_AUTH_URL =
|
||||
"https://api.github.com/copilot_internal/v2/token";
|
||||
export const COPILOT_MODELS_URL = "https://api.githubcopilot.com/models";
|
||||
|
||||
// GitHub OAuth endpoints for device flow
|
||||
export const GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98";
|
||||
export const GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
|
||||
export const GITHUB_ACCESS_TOKEN_URL =
|
||||
"https://github.com/login/oauth/access_token";
|
||||
|
||||
// Cache and retry configuration
|
||||
export const COPILOT_MODELS_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
||||
export const COPILOT_MAX_RETRIES = 3;
|
||||
export const COPILOT_INITIAL_RETRY_DELAY = 1000; // 1 second
|
||||
|
||||
// Default model
|
||||
export const COPILOT_DEFAULT_MODEL = "gpt-5-mini";
|
||||
|
||||
// Unlimited fallback model (used when quota is exceeded)
|
||||
export const COPILOT_UNLIMITED_MODEL = "gpt-4o";
|
||||
|
||||
// Copilot messages
|
||||
export const COPILOT_MESSAGES = {
|
||||
QUOTA_EXCEEDED_SWITCHING: (from: string, to: string) =>
|
||||
`Quota exceeded for ${from}. Switching to unlimited model: ${to}`,
|
||||
MODEL_SWITCHED: (from: string, to: string) =>
|
||||
`Model switched: ${from} → ${to} (quota exceeded)`,
|
||||
FORMAT_MULTIPLIER: (multiplier: number) =>
|
||||
multiplier === 0 ? "Unlimited" : `${multiplier}x`,
|
||||
} as const;
|
||||
|
||||
// Model cost multipliers from GitHub Copilot
|
||||
// 0x = Unlimited (no premium request usage)
|
||||
// Lower multiplier = cheaper, Higher multiplier = more expensive
|
||||
export const MODEL_COST_MULTIPLIERS: Record<string, number> = {
|
||||
// Unlimited models (0x)
|
||||
"gpt-4o": 0,
|
||||
"gpt-4o-mini": 0,
|
||||
"gpt-5-mini": 0,
|
||||
"grok-code-fast-1": 0,
|
||||
"raptor-mini": 0,
|
||||
|
||||
// Low cost models (0.33x)
|
||||
"claude-haiku-4.5": 0.33,
|
||||
"gemini-3-flash-preview": 0.33,
|
||||
"gpt-5.1-codex-mini-preview": 0.33,
|
||||
|
||||
// Standard cost models (1.0x)
|
||||
"claude-sonnet-4": 1.0,
|
||||
"claude-sonnet-4.5": 1.0,
|
||||
"gemini-2.5-pro": 1.0,
|
||||
"gemini-3-pro-preview": 1.0,
|
||||
"gpt-4.1": 1.0,
|
||||
"gpt-5": 1.0,
|
||||
"gpt-5-codex-preview": 1.0,
|
||||
"gpt-5.1": 1.0,
|
||||
"gpt-5.1-codex": 1.0,
|
||||
"gpt-5.1-codex-max": 1.0,
|
||||
"gpt-5.2": 1.0,
|
||||
"gpt-5.2-codex": 1.0,
|
||||
|
||||
// Premium models (3.0x)
|
||||
"claude-opus-4.5": 3.0,
|
||||
};
|
||||
|
||||
// Models that are unlimited (0x cost multiplier)
|
||||
export const UNLIMITED_MODELS = new Set([
|
||||
"gpt-4o",
|
||||
"gpt-4o-mini",
|
||||
"gpt-5-mini",
|
||||
"grok-code-fast-1",
|
||||
"raptor-mini",
|
||||
]);
|
||||
|
||||
// Model context sizes (input tokens, output tokens)
|
||||
export interface ModelContextSize {
|
||||
input: number;
|
||||
output: number;
|
||||
}
|
||||
|
||||
export const MODEL_CONTEXT_SIZES: Record<string, ModelContextSize> = {
|
||||
// Claude models
|
||||
"claude-haiku-4.5": { input: 128000, output: 16000 },
|
||||
"claude-opus-4.5": { input: 128000, output: 16000 },
|
||||
"claude-sonnet-4": { input: 128000, output: 16000 },
|
||||
"claude-sonnet-4.5": { input: 128000, output: 16000 },
|
||||
|
||||
// Gemini models
|
||||
"gemini-2.5-pro": { input: 109000, output: 64000 },
|
||||
"gemini-3-flash-preview": { input: 109000, output: 64000 },
|
||||
"gemini-3-pro-preview": { input: 109000, output: 64000 },
|
||||
|
||||
// GPT-4 models
|
||||
"gpt-4.1": { input: 111000, output: 16000 },
|
||||
"gpt-4o": { input: 64000, output: 4000 },
|
||||
|
||||
// GPT-5 models
|
||||
"gpt-5": { input: 128000, output: 128000 },
|
||||
"gpt-5-mini": { input: 128000, output: 64000 },
|
||||
"gpt-5-codex-preview": { input: 128000, output: 128000 },
|
||||
"gpt-5.1": { input: 128000, output: 64000 },
|
||||
"gpt-5.1-codex": { input: 128000, output: 128000 },
|
||||
"gpt-5.1-codex-max": { input: 128000, output: 128000 },
|
||||
"gpt-5.1-codex-mini-preview": { input: 128000, output: 128000 },
|
||||
"gpt-5.2": { input: 128000, output: 64000 },
|
||||
"gpt-5.2-codex": { input: 272000, output: 128000 },
|
||||
|
||||
// Other models
|
||||
"grok-code-fast-1": { input: 109000, output: 64000 },
|
||||
"raptor-mini": { input: 200000, output: 64000 },
|
||||
};
|
||||
|
||||
// Default context size for unknown models
|
||||
export const DEFAULT_CONTEXT_SIZE: ModelContextSize = {
|
||||
input: 128000,
|
||||
output: 16000,
|
||||
};
|
||||
|
||||
// Get context size for a model
|
||||
export const getModelContextSize = (modelId: string): ModelContextSize =>
|
||||
MODEL_CONTEXT_SIZES[modelId] ?? DEFAULT_CONTEXT_SIZE;
|
||||
|
||||
// Fallback models when API is unavailable
|
||||
export const COPILOT_FALLBACK_MODELS: ProviderModel[] = [
|
||||
{
|
||||
id: "gpt-4o",
|
||||
name: "GPT-4o",
|
||||
maxTokens: 4000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 0,
|
||||
isUnlimited: true,
|
||||
},
|
||||
{
|
||||
id: "gpt-5-mini",
|
||||
name: "GPT-5 mini",
|
||||
maxTokens: 64000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 0,
|
||||
isUnlimited: true,
|
||||
},
|
||||
{
|
||||
id: "claude-sonnet-4",
|
||||
name: "Claude Sonnet 4",
|
||||
maxTokens: 16000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 1.0,
|
||||
isUnlimited: false,
|
||||
},
|
||||
{
|
||||
id: "claude-sonnet-4.5",
|
||||
name: "Claude Sonnet 4.5",
|
||||
maxTokens: 16000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 1.0,
|
||||
isUnlimited: false,
|
||||
},
|
||||
{
|
||||
id: "claude-opus-4.5",
|
||||
name: "Claude Opus 4.5",
|
||||
maxTokens: 16000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 3.0,
|
||||
isUnlimited: false,
|
||||
},
|
||||
{
|
||||
id: "gpt-4.1",
|
||||
name: "GPT-4.1",
|
||||
maxTokens: 16000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 1.0,
|
||||
isUnlimited: false,
|
||||
},
|
||||
{
|
||||
id: "gpt-5",
|
||||
name: "GPT-5",
|
||||
maxTokens: 128000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 1.0,
|
||||
isUnlimited: false,
|
||||
},
|
||||
{
|
||||
id: "gemini-2.5-pro",
|
||||
name: "Gemini 2.5 Pro",
|
||||
maxTokens: 64000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 1.0,
|
||||
isUnlimited: false,
|
||||
},
|
||||
{
|
||||
id: "grok-code-fast-1",
|
||||
name: "Grok Code Fast 1",
|
||||
maxTokens: 64000,
|
||||
supportsTools: true,
|
||||
supportsStreaming: true,
|
||||
costMultiplier: 0,
|
||||
isUnlimited: true,
|
||||
},
|
||||
];
|
||||
42
src/constants/dashboard.ts
Normal file
42
src/constants/dashboard.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Dashboard Constants
|
||||
*/
|
||||
|
||||
export const DASHBOARD_TITLE = "CodeTyper";
|
||||
|
||||
export const DASHBOARD_LAYOUT = {
|
||||
DEFAULT_WIDTH: 120,
|
||||
CONTENT_HEIGHT: 15,
|
||||
LEFT_COLUMN_RATIO: 0.35,
|
||||
PADDING: 3,
|
||||
} as const;
|
||||
|
||||
export const DASHBOARD_LOGO = [
|
||||
" ██████╗███████╗",
|
||||
" ██╔════╝██╔════╝",
|
||||
" ██║ ███████╗",
|
||||
" ██║ ╚════██║",
|
||||
" ╚██████╗███████║",
|
||||
" ╚═════╝╚══════╝",
|
||||
] as const;
|
||||
|
||||
export const DASHBOARD_COMMANDS = [
|
||||
{ command: "codetyper chat", description: "Start interactive chat" },
|
||||
{ command: "codetyper run <task>", description: "Execute autonomous task" },
|
||||
{ command: "/help", description: "Show all commands in chat" },
|
||||
] as const;
|
||||
|
||||
export const DASHBOARD_QUICK_COMMANDS = [
|
||||
{ command: "codetyper chat", description: "Start interactive chat" },
|
||||
{ command: "codetyper run", description: "Execute autonomous task" },
|
||||
{ command: "codetyper --help", description: "Show all commands" },
|
||||
] as const;
|
||||
|
||||
export const DASHBOARD_BORDER = {
|
||||
TOP_LEFT: "╭",
|
||||
TOP_RIGHT: "╮",
|
||||
BOTTOM_LEFT: "╰",
|
||||
BOTTOM_RIGHT: "╯",
|
||||
HORIZONTAL: "─",
|
||||
VERTICAL: "│",
|
||||
} as const;
|
||||
13
src/constants/diff.ts
Normal file
13
src/constants/diff.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Diff utility constants
|
||||
*/
|
||||
|
||||
// Default context lines for hunks
|
||||
export const DIFF_CONTEXT_LINES = 3;
|
||||
|
||||
// Line type prefixes
|
||||
export const LINE_PREFIXES = {
|
||||
add: "+",
|
||||
remove: "-",
|
||||
context: " ",
|
||||
} as const;
|
||||
25
src/constants/edit.ts
Normal file
25
src/constants/edit.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Edit tool constants
|
||||
*/
|
||||
|
||||
export const EDIT_MESSAGES = {
|
||||
NOT_FOUND:
|
||||
"Could not find the text to replace. Make sure old_string matches exactly.",
|
||||
MULTIPLE_OCCURRENCES: (count: number) =>
|
||||
`old_string appears ${count} times. Use replace_all=true or provide more context to make it unique.`,
|
||||
PERMISSION_DENIED: "Permission denied by user",
|
||||
} as const;
|
||||
|
||||
export const EDIT_TITLES = {
|
||||
FAILED: (path: string) => `Edit failed: ${path}`,
|
||||
CANCELLED: (path: string) => `Edit cancelled: ${path}`,
|
||||
SUCCESS: (path: string) => `Edited: ${path}`,
|
||||
EDITING: (name: string) => `Editing ${name}`,
|
||||
} as const;
|
||||
|
||||
export const EDIT_DESCRIPTION = `Edit a file by replacing specific text. The old_string must match exactly.
|
||||
|
||||
Guidelines:
|
||||
- old_string must be unique in the file (or use replace_all)
|
||||
- Preserve indentation exactly as it appears in the file
|
||||
- Requires user approval for edits`;
|
||||
30
src/constants/embeddings.ts
Normal file
30
src/constants/embeddings.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Embedding Constants
|
||||
*
|
||||
* Configuration for semantic learning retrieval
|
||||
*/
|
||||
|
||||
export const EMBEDDING_DEFAULTS = {
|
||||
MODEL: "nomic-embed-text",
|
||||
FALLBACK_MODEL: "all-minilm",
|
||||
DIMENSIONS: 768,
|
||||
} as const;
|
||||
|
||||
export const EMBEDDING_ENDPOINTS = {
|
||||
EMBED: "/api/embed",
|
||||
} as const;
|
||||
|
||||
export const EMBEDDING_TIMEOUTS = {
|
||||
EMBED: 30000,
|
||||
} as const;
|
||||
|
||||
export const EMBEDDING_SEARCH = {
|
||||
TOP_K: 10,
|
||||
MIN_SIMILARITY: 0.3,
|
||||
CACHE_TTL_MS: 300000, // 5 minutes
|
||||
} as const;
|
||||
|
||||
export const EMBEDDING_STORAGE = {
|
||||
INDEX_FILE: "embeddings.json",
|
||||
VERSION: 1,
|
||||
} as const;
|
||||
123
src/constants/file-picker.ts
Normal file
123
src/constants/file-picker.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* File Picker constants
|
||||
*/
|
||||
|
||||
export const IGNORED_PATTERNS = [
|
||||
// Version control
|
||||
".git",
|
||||
".svn",
|
||||
".hg",
|
||||
// AI/Code assistants
|
||||
".claude",
|
||||
".coder",
|
||||
".codetyper",
|
||||
".cursor",
|
||||
".copilot",
|
||||
".aider",
|
||||
// Build outputs / binaries
|
||||
"node_modules",
|
||||
"dist",
|
||||
"build",
|
||||
"bin",
|
||||
"obj",
|
||||
"target",
|
||||
".next",
|
||||
".nuxt",
|
||||
".output",
|
||||
"out",
|
||||
// Cache directories
|
||||
".cache",
|
||||
".turbo",
|
||||
".parcel-cache",
|
||||
".vite",
|
||||
// Test/Coverage
|
||||
"coverage",
|
||||
".nyc_output",
|
||||
// Python
|
||||
"__pycache__",
|
||||
".venv",
|
||||
"venv",
|
||||
".env",
|
||||
// OS files
|
||||
".DS_Store",
|
||||
"thumbs.db",
|
||||
// IDE/Editor
|
||||
".idea",
|
||||
".vscode",
|
||||
// Misc
|
||||
".terraform",
|
||||
".serverless",
|
||||
] as const;
|
||||
|
||||
export const BINARY_EXTENSIONS = [
|
||||
// Executables
|
||||
".exe",
|
||||
".dll",
|
||||
".so",
|
||||
".dylib",
|
||||
".bin",
|
||||
".app",
|
||||
// Images
|
||||
".png",
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".gif",
|
||||
".bmp",
|
||||
".ico",
|
||||
".webp",
|
||||
".svg",
|
||||
".tiff",
|
||||
// Audio/Video
|
||||
".mp3",
|
||||
".mp4",
|
||||
".wav",
|
||||
".avi",
|
||||
".mov",
|
||||
".mkv",
|
||||
".flac",
|
||||
".ogg",
|
||||
// Archives
|
||||
".zip",
|
||||
".tar",
|
||||
".gz",
|
||||
".rar",
|
||||
".7z",
|
||||
".bz2",
|
||||
// Documents
|
||||
".pdf",
|
||||
".doc",
|
||||
".docx",
|
||||
".xls",
|
||||
".xlsx",
|
||||
".ppt",
|
||||
".pptx",
|
||||
// Fonts
|
||||
".ttf",
|
||||
".otf",
|
||||
".woff",
|
||||
".woff2",
|
||||
".eot",
|
||||
// Database
|
||||
".db",
|
||||
".sqlite",
|
||||
".sqlite3",
|
||||
// Other binary
|
||||
".pyc",
|
||||
".pyo",
|
||||
".class",
|
||||
".o",
|
||||
".a",
|
||||
".lib",
|
||||
".node",
|
||||
".wasm",
|
||||
] as const;
|
||||
|
||||
export type BinaryExtension = (typeof BINARY_EXTENSIONS)[number];
|
||||
|
||||
export type IgnoredPattern = (typeof IGNORED_PATTERNS)[number];
|
||||
|
||||
export const FILE_PICKER_DEFAULTS = {
|
||||
MAX_DEPTH: 2,
|
||||
MAX_RESULTS: 15,
|
||||
INITIAL_DEPTH: 0,
|
||||
} as const;
|
||||
2
src/constants/files.ts
Normal file
2
src/constants/files.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// File-related constants
|
||||
// MAX_FILE_SIZE, etc.
|
||||
1
src/constants/general.ts
Normal file
1
src/constants/general.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const PROVIDER_NAME_COPILOT = "copilot";
|
||||
31
src/constants/github-issue.ts
Normal file
31
src/constants/github-issue.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* GitHub Issue constants
|
||||
*/
|
||||
|
||||
export const ISSUE_PATTERNS = [
|
||||
/\bissue\s*#?(\d+)\b/gi,
|
||||
/\bfix\s+#(\d+)\b/gi,
|
||||
/\bclose\s+#(\d+)\b/gi,
|
||||
/\bresolve\s+#(\d+)\b/gi,
|
||||
/(?<!\w)#(\d+)(?!\w)/g,
|
||||
] as const;
|
||||
|
||||
export const GITHUB_ISSUE_DEFAULTS = {
|
||||
MAX_ISSUE_NUMBER: 100000,
|
||||
MIN_ISSUE_NUMBER: 1,
|
||||
} as const;
|
||||
|
||||
export const GITHUB_ISSUE_MESSAGES = {
|
||||
CONTEXT_HEADER: "The user is referencing the following GitHub issue(s):",
|
||||
SECTION_SEPARATOR: "\n\n---\n\n",
|
||||
USER_REQUEST_PREFIX: "User request: ",
|
||||
UNKNOWN_AUTHOR: "unknown",
|
||||
} as const;
|
||||
|
||||
export const GH_CLI_COMMANDS = {
|
||||
GET_REMOTE_URL: "git remote get-url origin 2>/dev/null",
|
||||
VIEW_ISSUE: (issueNumber: number) =>
|
||||
`gh issue view ${issueNumber} --json number,title,state,body,author,labels,url 2>/dev/null`,
|
||||
} as const;
|
||||
|
||||
export const GITHUB_REMOTE_IDENTIFIER = "github.com";
|
||||
58
src/constants/glob.ts
Normal file
58
src/constants/glob.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Glob tool constants
|
||||
*/
|
||||
|
||||
export const GLOB_DEFAULTS = {
|
||||
DOT: false,
|
||||
ONLY_FILES: true,
|
||||
ONLY_DIRECTORIES: false,
|
||||
} as const;
|
||||
|
||||
export const GLOB_IGNORE_PATTERNS = [
|
||||
// Version control
|
||||
"**/.git/**",
|
||||
"**/.svn/**",
|
||||
"**/.hg/**",
|
||||
// AI/Code assistants
|
||||
"**/.claude/**",
|
||||
"**/.coder/**",
|
||||
"**/.codetyper/**",
|
||||
"**/.cursor/**",
|
||||
"**/.copilot/**",
|
||||
"**/.aider/**",
|
||||
// Build outputs / binaries
|
||||
"**/node_modules/**",
|
||||
"**/dist/**",
|
||||
"**/build/**",
|
||||
"**/bin/**",
|
||||
"**/obj/**",
|
||||
"**/target/**",
|
||||
"**/.next/**",
|
||||
"**/.nuxt/**",
|
||||
"**/.output/**",
|
||||
"**/out/**",
|
||||
// Cache directories
|
||||
"**/.cache/**",
|
||||
"**/.turbo/**",
|
||||
"**/.parcel-cache/**",
|
||||
"**/.vite/**",
|
||||
// Test/Coverage
|
||||
"**/coverage/**",
|
||||
"**/.nyc_output/**",
|
||||
// Python
|
||||
"**/__pycache__/**",
|
||||
"**/.venv/**",
|
||||
"**/venv/**",
|
||||
"**/.env/**",
|
||||
// IDE/Editor
|
||||
"**/.idea/**",
|
||||
"**/.vscode/**",
|
||||
// Misc
|
||||
"**/.terraform/**",
|
||||
"**/.serverless/**",
|
||||
] as const;
|
||||
|
||||
export const GLOB_MESSAGES = {
|
||||
FAILED: (error: unknown) => `Glob failed: ${error}`,
|
||||
LIST_FAILED: (error: unknown) => `List failed: ${error}`,
|
||||
} as const;
|
||||
28
src/constants/grep.ts
Normal file
28
src/constants/grep.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Grep tool constants
|
||||
*/
|
||||
|
||||
export const GREP_DEFAULTS = {
|
||||
MAX_RESULTS: 100,
|
||||
DEFAULT_PATTERN: "**/*",
|
||||
NO_MATCHES_EXIT_CODE: 1,
|
||||
} as const;
|
||||
|
||||
export const GREP_IGNORE_PATTERNS = [
|
||||
"**/node_modules/**",
|
||||
"**/.git/**",
|
||||
"**/dist/**",
|
||||
"**/build/**",
|
||||
"**/.next/**",
|
||||
] as const;
|
||||
|
||||
export const GREP_MESSAGES = {
|
||||
NO_MATCHES: "No matches found",
|
||||
SEARCH_FAILED: (error: unknown) => `Search failed: ${error}`,
|
||||
RIPGREP_FAILED: (message: string) => `ripgrep failed: ${message}`,
|
||||
} as const;
|
||||
|
||||
export const GREP_COMMANDS = {
|
||||
RIPGREP: (pattern: string, directory: string) =>
|
||||
`rg --line-number --no-heading "${pattern}" "${directory}"`,
|
||||
} as const;
|
||||
45
src/constants/handlers.ts
Normal file
45
src/constants/handlers.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Constants for command handlers
|
||||
*/
|
||||
|
||||
import type { ConfigKey, ConfigAction } from "@/types/handlers";
|
||||
import type { Provider } from "@/types/index";
|
||||
|
||||
export const VALID_CONFIG_KEYS: readonly ConfigKey[] = [
|
||||
"provider",
|
||||
"model",
|
||||
"maxIterations",
|
||||
"timeout",
|
||||
] as const;
|
||||
|
||||
export const VALID_PROVIDERS: readonly Provider[] = [
|
||||
"copilot",
|
||||
"ollama",
|
||||
] as const;
|
||||
|
||||
export const VALID_CONFIG_ACTIONS: readonly ConfigAction[] = [
|
||||
"show",
|
||||
"path",
|
||||
"set",
|
||||
] as const;
|
||||
|
||||
export const CONFIG_VALIDATION = {
|
||||
MIN_TIMEOUT_MS: 1000,
|
||||
MIN_ITERATIONS: 1,
|
||||
} as const;
|
||||
|
||||
export const INTENT_KEYWORDS = {
|
||||
fix: ["fix", "bug"],
|
||||
test: ["test", "spec"],
|
||||
refactor: ["refactor", "improve"],
|
||||
code: ["add", "implement"],
|
||||
document: ["document", "comment"],
|
||||
} as const;
|
||||
|
||||
export const CLASSIFICATION_CONFIDENCE = {
|
||||
HIGH: 0.9,
|
||||
MEDIUM: 0.85,
|
||||
DEFAULT: 0.8,
|
||||
LOW: 0.75,
|
||||
THRESHOLD: 0.7,
|
||||
} as const;
|
||||
20
src/constants/help-commands.ts
Normal file
20
src/constants/help-commands.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export const HELP_COMMANDS: [string, string][] = [
|
||||
["/help, /h", "Show this help message"],
|
||||
["/clear, /c", "Clear conversation history"],
|
||||
["/files, /f", "List files in context"],
|
||||
["/remove <file>, /rm", "Remove file from context"],
|
||||
["/context", "Show current context size"],
|
||||
["/compact", "Compact conversation history"],
|
||||
["/history", "Show conversation history"],
|
||||
["/models, /m", "Show available models"],
|
||||
["/model <name>", "Switch to a different model"],
|
||||
["/providers, /p", "Show all providers status"],
|
||||
["/provider <name>", "Switch to a different provider"],
|
||||
["/agent, /a", "Select agent"],
|
||||
["/usage, /u", "Show token usage statistics"],
|
||||
["/mcp [cmd]", "MCP server status/connect/disconnect/tools"],
|
||||
["/session", "Show current session info"],
|
||||
["/sessions", "List all saved sessions"],
|
||||
["/save, /s", "Save current session"],
|
||||
["/exit, /quit, /q", "Exit chat"],
|
||||
];
|
||||
35
src/constants/home-screen.ts
Normal file
35
src/constants/home-screen.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Home Screen Constants
|
||||
* Constants for the welcome/home screen TUI layout
|
||||
*/
|
||||
|
||||
/** Layout constants for home screen */
|
||||
export const HOME_LAYOUT = {
|
||||
maxWidth: 75,
|
||||
topPadding: 3,
|
||||
bottomPadding: 2,
|
||||
horizontalPadding: 2,
|
||||
logoGap: 1,
|
||||
} as const;
|
||||
|
||||
/** Input placeholders shown in the prompt box */
|
||||
export const PLACEHOLDERS = [
|
||||
"Fix a TODO in the codebase",
|
||||
"What is the tech stack of this project?",
|
||||
"Fix broken tests",
|
||||
"Explain how this function works",
|
||||
"Refactor this code for readability",
|
||||
"Add error handling to this function",
|
||||
];
|
||||
|
||||
/** Keyboard hints displayed below the prompt box */
|
||||
export const KEYBOARD_HINTS = {
|
||||
agents: { key: "tab", label: "agents" },
|
||||
commands: { key: "ctrl+p", label: "commands" },
|
||||
} as const;
|
||||
|
||||
/** MCP status indicators */
|
||||
export const MCP_INDICATORS = {
|
||||
connected: "⊙",
|
||||
error: "⊙",
|
||||
} as const;
|
||||
4
src/constants/home.ts
Normal file
4
src/constants/home.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const HOME_VARS = {
|
||||
title: "Welcome to CodeTyper - Your AI Coding Assistant",
|
||||
subTitle: "Type a prompt below to start a new session",
|
||||
};
|
||||
30
src/constants/input-editor.ts
Normal file
30
src/constants/input-editor.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Input editor constants
|
||||
*/
|
||||
|
||||
// Default prompts
|
||||
export const INPUT_EDITOR_DEFAULTS = {
|
||||
prompt: "\x1b[36m> \x1b[0m",
|
||||
continuationPrompt: "\x1b[90m│ \x1b[0m",
|
||||
} as const;
|
||||
|
||||
// ANSI escape sequences
|
||||
export const ANSI = {
|
||||
hideCursor: "\x1b[?25l",
|
||||
showCursor: "\x1b[?25h",
|
||||
clearLine: "\x1b[2K",
|
||||
moveUp: (n: number) => `\x1b[${n}A`,
|
||||
moveDown: (n: number) => `\x1b[${n}B`,
|
||||
moveRight: (n: number) => `\x1b[${n}C`,
|
||||
carriageReturn: "\r",
|
||||
} as const;
|
||||
|
||||
// Special key sequences for Alt+Enter
|
||||
export const ALT_ENTER_SEQUENCES = ["\x1b\r", "\x1b\n"] as const;
|
||||
|
||||
// Pasted text styling
|
||||
export const PASTE_STYLE = {
|
||||
// Gray/dim style for pasted text placeholder
|
||||
start: "\x1b[90m",
|
||||
end: "\x1b[0m",
|
||||
} as const;
|
||||
96
src/constants/learning.ts
Normal file
96
src/constants/learning.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Learning Service constants
|
||||
*/
|
||||
|
||||
import type { LearningCategory } from "@/types/learning";
|
||||
|
||||
export const LEARNING_PATTERNS = [
|
||||
// User preferences
|
||||
/always use (\w+)/i,
|
||||
/prefer (\w+) over (\w+)/i,
|
||||
/use (\.\w+) files?/i,
|
||||
/don't use (\w+)/i,
|
||||
/never use (\w+)/i,
|
||||
/code in (\w+)/i,
|
||||
/write in (\w+)/i,
|
||||
|
||||
// Project structure
|
||||
/put .+ in (.+) directory/i,
|
||||
/files? should be in (.+)/i,
|
||||
/follow (.+) pattern/i,
|
||||
/use (.+) architecture/i,
|
||||
|
||||
// Coding style
|
||||
/use (.+) naming convention/i,
|
||||
/follow (.+) style/i,
|
||||
/indent with (\w+)/i,
|
||||
/use (single|double) quotes/i,
|
||||
|
||||
// Testing
|
||||
/use (.+) for testing/i,
|
||||
/tests? should (.+)/i,
|
||||
|
||||
// Dependencies
|
||||
/use (.+) library/i,
|
||||
/prefer (.+) package/i,
|
||||
] as const;
|
||||
|
||||
export const LEARNING_KEYWORDS = [
|
||||
"always",
|
||||
"never",
|
||||
"prefer",
|
||||
"convention",
|
||||
"standard",
|
||||
"pattern",
|
||||
"rule",
|
||||
"style",
|
||||
"remember",
|
||||
"important",
|
||||
"must",
|
||||
"should",
|
||||
] as const;
|
||||
|
||||
export const ACKNOWLEDGMENT_PATTERNS = [
|
||||
/i('ll| will) (use|follow|apply) (.+)/i,
|
||||
/using (.+) as (you|per your) (requested|preference)/i,
|
||||
/following (.+) (convention|pattern|style)/i,
|
||||
/noted.+ (will|going to) (.+)/i,
|
||||
] as const;
|
||||
|
||||
export const ACKNOWLEDGMENT_PHRASES = [
|
||||
"i understand",
|
||||
"got it",
|
||||
"noted",
|
||||
] as const;
|
||||
|
||||
export const LEARNING_DEFAULTS = {
|
||||
BASE_PATTERN_CONFIDENCE: 0.7,
|
||||
BASE_KEYWORD_CONFIDENCE: 0.5,
|
||||
KEYWORD_CONFIDENCE_INCREMENT: 0.1,
|
||||
ACKNOWLEDGMENT_CONFIDENCE: 0.8,
|
||||
CONFIDENCE_BOOST: 0.2,
|
||||
MAX_CONFIDENCE: 1.0,
|
||||
MIN_KEYWORDS_FOR_LEARNING: 2,
|
||||
MAX_CONTENT_LENGTH: 80,
|
||||
TRUNCATE_LENGTH: 77,
|
||||
MAX_SLICE_LENGTH: 100,
|
||||
} as const;
|
||||
|
||||
export const LEARNING_CONTEXTS = {
|
||||
USER_PREFERENCE: "User preference",
|
||||
CONVENTION_IDENTIFIED: "Convention identified",
|
||||
MULTIPLE_INDICATORS: "Multiple preference indicators",
|
||||
CONVENTION_CONFIRMED: "Convention confirmed by assistant",
|
||||
PREFERENCE_ACKNOWLEDGED: "Preference acknowledged by assistant",
|
||||
} as const;
|
||||
|
||||
export const CATEGORY_PATTERNS: Record<string, LearningCategory> = {
|
||||
prefer: "preference",
|
||||
use: "preference",
|
||||
directory: "architecture",
|
||||
architecture: "architecture",
|
||||
style: "style",
|
||||
naming: "style",
|
||||
indent: "style",
|
||||
test: "testing",
|
||||
};
|
||||
28
src/constants/login.ts
Normal file
28
src/constants/login.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Login flow constants and messages
|
||||
*/
|
||||
|
||||
export const LOGIN_MESSAGES = {
|
||||
COPILOT_ALREADY_CONFIGURED: "✓ Copilot is already configured and working!",
|
||||
COPILOT_STARTING_AUTH: "\nStarting GitHub device flow authentication...\n",
|
||||
COPILOT_AUTH_INSTRUCTIONS: "To authenticate with GitHub Copilot:\n",
|
||||
COPILOT_WAITING: "Waiting for authentication (press Ctrl+C to cancel)...\n",
|
||||
COPILOT_SUCCESS: "\n✓ GitHub Copilot authenticated successfully!",
|
||||
OLLAMA_SUCCESS: "\n✓ Connected to Ollama!",
|
||||
OLLAMA_NO_MODELS: "\nNo models found. Pull a model with: ollama pull <model>",
|
||||
AVAILABLE_MODELS: "\nAvailable models:",
|
||||
VALIDATION_FAILED: "\n✗ Validation failed:",
|
||||
AUTH_FAILED: "\n✗ Authentication failed:",
|
||||
CONNECTION_FAILED: "\n✗ Failed to connect:",
|
||||
UNKNOWN_PROVIDER: "Unknown provider:",
|
||||
} as const;
|
||||
|
||||
export const LOGIN_PROMPTS = {
|
||||
RECONFIGURE: "Do you want to re-authenticate?",
|
||||
OLLAMA_HOST: "Ollama host URL:",
|
||||
} as const;
|
||||
|
||||
export const AUTH_STEP_PREFIXES = {
|
||||
OPEN_URL: " 1. Open:",
|
||||
ENTER_CODE: " 2. Enter code:",
|
||||
} as const;
|
||||
41
src/constants/mouse-handler.ts
Normal file
41
src/constants/mouse-handler.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Mouse Handler Constants
|
||||
*
|
||||
* Constants for terminal mouse event handling
|
||||
*/
|
||||
|
||||
// Mouse event button codes for SGR encoding
|
||||
export const MOUSE_WHEEL_CODES = {
|
||||
UP: 64,
|
||||
DOWN: 65,
|
||||
} as const;
|
||||
|
||||
// Default scroll lines per wheel event
|
||||
export const MOUSE_SCROLL_LINES = 3;
|
||||
|
||||
// SGR mouse sequence pattern: \x1b[<Cb;Cx;Cy(M|m)
|
||||
export const SGR_MOUSE_REGEX = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
|
||||
|
||||
// X10 mouse sequence pattern: \x1b[M followed by 3 bytes
|
||||
export const X10_MOUSE_REGEX = /\x1b\[M[\x20-\xff]{3}/g;
|
||||
|
||||
// Partial/incomplete sequence patterns for cleanup
|
||||
export const PARTIAL_SGR_REGEX = /\x1b\[<[\d;]*$/;
|
||||
export const PARTIAL_X10_REGEX = /\x1b\[M.{0,2}$/;
|
||||
|
||||
// Mouse tracking escape sequences
|
||||
export const MOUSE_TRACKING_SEQUENCES = {
|
||||
ENABLE_BUTTON: "\x1b[?1000h",
|
||||
ENABLE_SGR: "\x1b[?1006h",
|
||||
DISABLE_SGR: "\x1b[?1006l",
|
||||
DISABLE_BUTTON: "\x1b[?1000l",
|
||||
} as const;
|
||||
|
||||
// Scroll direction type
|
||||
export type MouseScrollDirection = "up" | "down";
|
||||
|
||||
// Button code to scroll direction mapping
|
||||
export const MOUSE_BUTTON_TO_SCROLL: Record<number, MouseScrollDirection> = {
|
||||
[MOUSE_WHEEL_CODES.UP]: "up",
|
||||
[MOUSE_WHEEL_CODES.DOWN]: "down",
|
||||
} as const;
|
||||
38
src/constants/mouse-scroll.ts
Normal file
38
src/constants/mouse-scroll.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Mouse Scroll Constants
|
||||
*
|
||||
* Terminal escape sequences for mouse mode handling
|
||||
*/
|
||||
|
||||
// Mouse mode enable/disable escape sequences
|
||||
export const MOUSE_ESCAPE_SEQUENCES = {
|
||||
ENABLE: "\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h",
|
||||
DISABLE: "\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l",
|
||||
} as const;
|
||||
|
||||
// Mouse button codes
|
||||
export const MOUSE_BUTTON_CODES = {
|
||||
SGR_SCROLL_UP: 64,
|
||||
SGR_SCROLL_DOWN: 65,
|
||||
X10_SCROLL_UP: 96, // 32 + 64
|
||||
X10_SCROLL_DOWN: 97, // 32 + 65
|
||||
} as const;
|
||||
|
||||
// SGR mouse mode regex pattern
|
||||
export const SGR_MOUSE_PATTERN = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/;
|
||||
|
||||
// X10/Normal mouse mode prefix
|
||||
export const X10_MOUSE_PREFIX = "\x1b[M";
|
||||
export const X10_MIN_LENGTH = 6;
|
||||
export const X10_BUTTON_OFFSET = 3;
|
||||
|
||||
// Scroll direction type
|
||||
export type ScrollDirection = "up" | "down";
|
||||
|
||||
// Mouse button to scroll direction mapping
|
||||
export const MOUSE_BUTTON_TO_DIRECTION: Record<number, ScrollDirection> = {
|
||||
[MOUSE_BUTTON_CODES.SGR_SCROLL_UP]: "up",
|
||||
[MOUSE_BUTTON_CODES.SGR_SCROLL_DOWN]: "down",
|
||||
[MOUSE_BUTTON_CODES.X10_SCROLL_UP]: "up",
|
||||
[MOUSE_BUTTON_CODES.X10_SCROLL_DOWN]: "down",
|
||||
} as const;
|
||||
32
src/constants/ollama.ts
Normal file
32
src/constants/ollama.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Ollama provider constants
|
||||
*/
|
||||
|
||||
export const OLLAMA_PROVIDER_NAME = "ollama" as const;
|
||||
export const OLLAMA_DISPLAY_NAME = "Ollama (Local)";
|
||||
|
||||
export const OLLAMA_DEFAULTS = {
|
||||
BASE_URL: "http://localhost:11434",
|
||||
MODEL: "deepseek-coder:6.7b",
|
||||
} as const;
|
||||
|
||||
export const OLLAMA_ENDPOINTS = {
|
||||
TAGS: "/api/tags",
|
||||
CHAT: "/api/chat",
|
||||
PULL: "/api/pull",
|
||||
} as const;
|
||||
|
||||
export const OLLAMA_TIMEOUTS = {
|
||||
VALIDATION: 5000,
|
||||
CHAT: 120000,
|
||||
} as const;
|
||||
|
||||
export const OLLAMA_CHAT_OPTIONS = {
|
||||
DEFAULT_TEMPERATURE: 0.3,
|
||||
DEFAULT_MAX_TOKENS: 4096,
|
||||
} as const;
|
||||
|
||||
export const OLLAMA_ERRORS = {
|
||||
NOT_RUNNING: (baseUrl: string) =>
|
||||
`Ollama not running at ${baseUrl}. Start it with: ollama serve`,
|
||||
} as const;
|
||||
12
src/constants/paste.ts
Normal file
12
src/constants/paste.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Constants for paste virtual text feature
|
||||
*/
|
||||
|
||||
/** Minimum number of lines to trigger paste summary */
|
||||
export const PASTE_LINE_THRESHOLD = 3;
|
||||
|
||||
/** Minimum character count to trigger paste summary */
|
||||
export const PASTE_CHAR_THRESHOLD = 150;
|
||||
|
||||
/** Format for paste placeholder display */
|
||||
export const PASTE_PLACEHOLDER_FORMAT = "[Pasted ~{lineCount} lines]";
|
||||
96
src/constants/paths.ts
Normal file
96
src/constants/paths.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* XDG-compliant storage paths
|
||||
*
|
||||
* Follows the XDG Base Directory Specification:
|
||||
* - XDG_CONFIG_HOME: User configuration (~/.config)
|
||||
* - XDG_DATA_HOME: User data (~/.local/share)
|
||||
* - XDG_CACHE_HOME: Cache data (~/.cache)
|
||||
* - XDG_STATE_HOME: State data (~/.local/state)
|
||||
*
|
||||
* See: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
*/
|
||||
|
||||
import { homedir } from "os";
|
||||
import { join } from "path";
|
||||
|
||||
const APP_NAME = "codetyper";
|
||||
|
||||
/**
|
||||
* XDG base directories with fallbacks
|
||||
*/
|
||||
export const XDG = {
|
||||
config: process.env.XDG_CONFIG_HOME || join(homedir(), ".config"),
|
||||
data: process.env.XDG_DATA_HOME || join(homedir(), ".local", "share"),
|
||||
cache: process.env.XDG_CACHE_HOME || join(homedir(), ".cache"),
|
||||
state: process.env.XDG_STATE_HOME || join(homedir(), ".local", "state"),
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Application directories
|
||||
*/
|
||||
export const DIRS = {
|
||||
/** Configuration directory (~/.config/codetyper) */
|
||||
config: join(XDG.config, APP_NAME),
|
||||
|
||||
/** Data directory (~/.local/share/codetyper) */
|
||||
data: join(XDG.data, APP_NAME),
|
||||
|
||||
/** Cache directory (~/.cache/codetyper) */
|
||||
cache: join(XDG.cache, APP_NAME),
|
||||
|
||||
/** State directory (~/.local/state/codetyper) */
|
||||
state: join(XDG.state, APP_NAME),
|
||||
|
||||
/** Sessions directory (~/.local/share/codetyper/sessions) */
|
||||
sessions: join(XDG.data, APP_NAME, "sessions"),
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Application files
|
||||
*/
|
||||
export const FILES = {
|
||||
/** Main configuration file */
|
||||
config: join(DIRS.config, "config.json"),
|
||||
|
||||
/** Keybindings configuration */
|
||||
keybindings: join(DIRS.config, "keybindings.json"),
|
||||
|
||||
/** Provider credentials (stored in data, not config) */
|
||||
credentials: join(DIRS.data, "credentials.json"),
|
||||
|
||||
/** Command history */
|
||||
history: join(DIRS.data, "history.json"),
|
||||
|
||||
/** Models cache */
|
||||
modelsCache: join(DIRS.cache, "models.json"),
|
||||
|
||||
/** Frecency cache for file/command suggestions */
|
||||
frecency: join(DIRS.cache, "frecency.json"),
|
||||
|
||||
/** Key-value state storage */
|
||||
kvStore: join(DIRS.state, "kv.json"),
|
||||
|
||||
/** Global settings (permissions, etc.) */
|
||||
settings: join(DIRS.config, "settings.json"),
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Local project config directory name
|
||||
*/
|
||||
export const LOCAL_CONFIG_DIR = ".codetyper";
|
||||
|
||||
export const IGNORE_FOLDERS = [
|
||||
"**/node_modules/**",
|
||||
"**/.git/**",
|
||||
"**/.codetyper/**",
|
||||
"**/.vscode/**",
|
||||
"**/.idea/**",
|
||||
"**/__pycache__/**",
|
||||
"**/.DS_Store/**",
|
||||
"**/dist/**",
|
||||
"**/build/**",
|
||||
"**/out/**",
|
||||
"**/.next/**",
|
||||
"**/.nuxt/**",
|
||||
"**/venv/**",
|
||||
];
|
||||
1
src/constants/patterns.ts
Normal file
1
src/constants/patterns.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const FILE_REFERENCE_PATTERN = /@(?:"([^"]+)"|'([^']+)'|(\S+))/g;
|
||||
127
src/constants/provider-quality.ts
Normal file
127
src/constants/provider-quality.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import type { TaskType } from "@/types/provider-quality";
|
||||
|
||||
export const QUALITY_THRESHOLDS = {
|
||||
HIGH: 0.85,
|
||||
MEDIUM: 0.6,
|
||||
LOW: 0.4,
|
||||
INITIAL: 0.5,
|
||||
} as const;
|
||||
|
||||
export const SCORE_ADJUSTMENTS = {
|
||||
APPROVAL: 0.05,
|
||||
CORRECTION: -0.08,
|
||||
USER_REJECTION: -0.15,
|
||||
MINOR_ISSUE: -0.02,
|
||||
MAJOR_ISSUE: -0.05,
|
||||
} as const;
|
||||
|
||||
export const TASK_TYPE_PATTERNS: Record<TaskType, RegExp[]> = {
|
||||
code_generation: [
|
||||
/create\s+(a\s+)?function/i,
|
||||
/write\s+(a\s+)?code/i,
|
||||
/implement/i,
|
||||
/generate\s+(a\s+)?/i,
|
||||
/add\s+(a\s+)?(new\s+)?feature/i,
|
||||
/build\s+(a\s+)?/i,
|
||||
],
|
||||
refactoring: [
|
||||
/refactor/i,
|
||||
/clean\s*up/i,
|
||||
/restructure/i,
|
||||
/reorganize/i,
|
||||
/simplify/i,
|
||||
/improve\s+(the\s+)?code/i,
|
||||
],
|
||||
bug_fix: [
|
||||
/fix/i,
|
||||
/bug/i,
|
||||
/error/i,
|
||||
/issue/i,
|
||||
/not\s+working/i,
|
||||
/broken/i,
|
||||
/problem/i,
|
||||
/debug/i,
|
||||
],
|
||||
documentation: [
|
||||
/document/i,
|
||||
/comment/i,
|
||||
/readme/i,
|
||||
/explain\s+.*\s+code/i,
|
||||
/add\s+.*\s+docs/i,
|
||||
/jsdoc/i,
|
||||
/tsdoc/i,
|
||||
],
|
||||
testing: [
|
||||
/test/i,
|
||||
/spec/i,
|
||||
/unit\s+test/i,
|
||||
/integration/i,
|
||||
/coverage/i,
|
||||
/mock/i,
|
||||
],
|
||||
explanation: [
|
||||
/explain/i,
|
||||
/what\s+(does|is)/i,
|
||||
/how\s+(does|do)/i,
|
||||
/why/i,
|
||||
/understand/i,
|
||||
/clarify/i,
|
||||
],
|
||||
review: [
|
||||
/review/i,
|
||||
/check/i,
|
||||
/evaluate/i,
|
||||
/assess/i,
|
||||
/audit/i,
|
||||
/pr\s+review/i,
|
||||
],
|
||||
general: [],
|
||||
};
|
||||
|
||||
export const NEGATIVE_FEEDBACK_PATTERNS = [
|
||||
/fix\s+this/i,
|
||||
/that'?s?\s+(wrong|incorrect)/i,
|
||||
/not\s+(good|right|correct|working)/i,
|
||||
/doesn'?t?\s+work/i,
|
||||
/incorrect/i,
|
||||
/broken/i,
|
||||
/bad\s+(code|response)/i,
|
||||
/try\s+again/i,
|
||||
/redo/i,
|
||||
/wrong/i,
|
||||
];
|
||||
|
||||
export const POSITIVE_FEEDBACK_PATTERNS = [
|
||||
/thanks/i,
|
||||
/thank\s+you/i,
|
||||
/perfect/i,
|
||||
/great/i,
|
||||
/works/i,
|
||||
/good\s+(job|work)/i,
|
||||
/excellent/i,
|
||||
/awesome/i,
|
||||
/exactly/i,
|
||||
];
|
||||
|
||||
export const DEFAULT_QUALITY_SCORES: Record<TaskType, number> = {
|
||||
code_generation: QUALITY_THRESHOLDS.INITIAL,
|
||||
refactoring: QUALITY_THRESHOLDS.INITIAL,
|
||||
bug_fix: QUALITY_THRESHOLDS.INITIAL,
|
||||
documentation: QUALITY_THRESHOLDS.INITIAL,
|
||||
testing: QUALITY_THRESHOLDS.INITIAL,
|
||||
explanation: QUALITY_THRESHOLDS.INITIAL,
|
||||
review: QUALITY_THRESHOLDS.INITIAL,
|
||||
general: QUALITY_THRESHOLDS.INITIAL,
|
||||
};
|
||||
|
||||
export const PROVIDER_IDS = {
|
||||
OLLAMA: "ollama",
|
||||
COPILOT: "copilot",
|
||||
} as const;
|
||||
|
||||
export const CASCADE_CONFIG = {
|
||||
MIN_AUDIT_THRESHOLD: QUALITY_THRESHOLDS.HIGH,
|
||||
MAX_SKIP_THRESHOLD: QUALITY_THRESHOLDS.LOW,
|
||||
DECAY_RATE: 0.01,
|
||||
DECAY_INTERVAL_MS: 7 * 24 * 60 * 60 * 1000, // 1 week
|
||||
} as const;
|
||||
22
src/constants/providers.ts
Normal file
22
src/constants/providers.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Provider constants
|
||||
*/
|
||||
|
||||
import type { ProviderInfoRegistry } from "@/types/providers";
|
||||
|
||||
export const PROVIDER_INFO: ProviderInfoRegistry = {
|
||||
copilot: {
|
||||
envVar: "GitHub OAuth via device flow",
|
||||
description: "GitHub Copilot - authenticate via GitHub device flow",
|
||||
},
|
||||
ollama: {
|
||||
envVar: "OLLAMA_HOST (default: http://localhost:11434)",
|
||||
description: "Local Ollama models - no API key needed",
|
||||
},
|
||||
};
|
||||
|
||||
export const DEFAULT_OLLAMA_HOST = "http://localhost:11434";
|
||||
|
||||
export const CREDENTIALS_FILE_MODE = 0o600;
|
||||
|
||||
export const MAX_MODELS_DISPLAY = 10;
|
||||
29
src/constants/read.ts
Normal file
29
src/constants/read.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Read tool constants
|
||||
*/
|
||||
|
||||
export const READ_DEFAULTS = {
|
||||
MAX_LINES: 2000,
|
||||
MAX_LINE_LENGTH: 2000,
|
||||
MAX_BYTES: 100000,
|
||||
LINE_NUMBER_PAD: 6,
|
||||
} as const;
|
||||
|
||||
export const READ_MESSAGES = {
|
||||
PERMISSION_DENIED: "Permission denied by user",
|
||||
} as const;
|
||||
|
||||
export const READ_TITLES = {
|
||||
DENIED: (path: string) => `Read denied: ${path}`,
|
||||
FAILED: (path: string) => `Read failed: ${path}`,
|
||||
READING: (name: string) => `Reading ${name}`,
|
||||
DIRECTORY: (path: string) => `Listed directory: ${path}`,
|
||||
} as const;
|
||||
|
||||
export const READ_DESCRIPTION = `Read the contents of a file. Returns the file content with line numbers.
|
||||
|
||||
Guidelines:
|
||||
- Use absolute paths
|
||||
- By default reads up to 2000 lines
|
||||
- Long lines are truncated at 2000 characters
|
||||
- Use offset and limit for large files`;
|
||||
250
src/constants/reasoning.ts
Normal file
250
src/constants/reasoning.ts
Normal file
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* Configuration constants for the Reasoning Control Layer
|
||||
* All tunable parameters in one place
|
||||
*/
|
||||
|
||||
import type {
|
||||
EntityType,
|
||||
MemoryItemType,
|
||||
ValidationCheckType,
|
||||
} from "@/types/reasoning";
|
||||
|
||||
// =============================================================================
|
||||
// QUALITY EVALUATION THRESHOLDS
|
||||
// =============================================================================
|
||||
|
||||
export const QUALITY_THRESHOLDS = {
|
||||
ACCEPT: 0.7,
|
||||
RETRY: 0.4,
|
||||
ESCALATE: 0.2,
|
||||
} as const;
|
||||
|
||||
export const QUALITY_WEIGHTS = {
|
||||
structural: 0.3,
|
||||
relevance: 0.25,
|
||||
completeness: 0.25,
|
||||
coherence: 0.2,
|
||||
} as const;
|
||||
|
||||
export const STRUCTURAL_CHECK_WEIGHTS = {
|
||||
parseSucceeds: 0.4,
|
||||
hasExpectedFormat: 0.3,
|
||||
withinLengthBounds: 0.15,
|
||||
noMalformedBlocks: 0.15,
|
||||
} as const;
|
||||
|
||||
// =============================================================================
|
||||
// HALLUCINATION DETECTION PATTERNS
|
||||
// =============================================================================
|
||||
|
||||
export const HALLUCINATION_PATTERNS: RegExp[] = [
|
||||
/I don't have access to .* but/i,
|
||||
/I cannot .* however/i,
|
||||
/assuming .* exists/i,
|
||||
/\[placeholder\]/i,
|
||||
/TODO:.*implement/i,
|
||||
/file:\/\/\/[a-z]:/i,
|
||||
/I'll need to .* first, but/i,
|
||||
/I'm not able to verify/i,
|
||||
/hypothetically/i,
|
||||
/in theory/i,
|
||||
];
|
||||
|
||||
export const CONTRADICTION_PATTERNS: RegExp[] = [
|
||||
/but actually|actually, no/i,
|
||||
/wait,? (?:no|I was wrong)/i,
|
||||
/on second thought/i,
|
||||
/correction:/i,
|
||||
/I misspoke/i,
|
||||
];
|
||||
|
||||
export const INCOMPLETE_STATEMENT_PATTERNS: RegExp[] = [
|
||||
/\.{3,}$/,
|
||||
/\s+$/,
|
||||
/(?:and|or|but|if|when|while)\s*$/i,
|
||||
];
|
||||
|
||||
// =============================================================================
|
||||
// RETRY POLICY LIMITS
|
||||
// =============================================================================
|
||||
|
||||
export const RETRY_LIMITS = {
|
||||
maxTotalAttempts: 12,
|
||||
maxPerTier: 2,
|
||||
maxTimeMs: 60000,
|
||||
} as const;
|
||||
|
||||
export const RETRY_TIER_ORDER = [
|
||||
"INITIAL",
|
||||
"RETRY_SAME",
|
||||
"RETRY_SIMPLIFIED",
|
||||
"RETRY_DECOMPOSED",
|
||||
"RETRY_ALTERNATIVE",
|
||||
"EXHAUSTED",
|
||||
] as const;
|
||||
|
||||
// =============================================================================
|
||||
// CONTEXT COMPRESSION SETTINGS
|
||||
// =============================================================================
|
||||
|
||||
export const COMPRESSION_THRESHOLDS = {
|
||||
COMPRESS_AT: 0.8,
|
||||
MINIMAL_AT: 0.95,
|
||||
} as const;
|
||||
|
||||
export const COMPRESSION_LIMITS = {
|
||||
maxToolResultTokens: 1000,
|
||||
truncateHeadTokens: 500,
|
||||
truncateTailTokens: 500,
|
||||
maxCodeBlockLines: 30,
|
||||
keepCodeHeadLines: 10,
|
||||
keepCodeTailLines: 5,
|
||||
maxMessageAge: 10,
|
||||
preserveRecentMessages: 3,
|
||||
} as const;
|
||||
|
||||
// =============================================================================
|
||||
// MEMORY SELECTION SETTINGS
|
||||
// =============================================================================
|
||||
|
||||
export const MEMORY_WEIGHTS = {
|
||||
keywordOverlap: 0.25,
|
||||
entityOverlap: 0.25,
|
||||
recency: 0.2,
|
||||
causalLink: 0.15,
|
||||
pathOverlap: 0.1,
|
||||
typeBonus: 0.05,
|
||||
} as const;
|
||||
|
||||
export const RECENCY_HALF_LIFE_MINUTES = 30;
|
||||
|
||||
export const RELEVANCE_THRESHOLD = 0.15;
|
||||
|
||||
export const MEMORY_TYPE_BONUSES: Record<MemoryItemType, number> = {
|
||||
ERROR: 0.8,
|
||||
DECISION: 0.6,
|
||||
TOOL_RESULT: 0.4,
|
||||
FILE_CONTENT: 0.3,
|
||||
CONVERSATION: 0.2,
|
||||
};
|
||||
|
||||
export const MANDATORY_MEMORY_AGE_THRESHOLD = 3;
|
||||
export const ERROR_MEMORY_AGE_THRESHOLD = 10;
|
||||
|
||||
// =============================================================================
|
||||
// TERMINATION DETECTION SETTINGS
|
||||
// =============================================================================
|
||||
|
||||
export const CONFIDENCE_THRESHOLDS = {
|
||||
CONFIRMED_COMPLETE: 0.85,
|
||||
POTENTIALLY_COMPLETE: 0.5,
|
||||
} as const;
|
||||
|
||||
export const VALIDATION_TIMEOUT_MS = 60000;
|
||||
export const VALIDATION_RETRY_COUNT = 1;
|
||||
|
||||
export const COMPLETION_SIGNAL_PATTERNS: Array<{
|
||||
type: "MODEL_STATEMENT";
|
||||
patterns: RegExp[];
|
||||
confidence: number;
|
||||
}> = [
|
||||
{
|
||||
type: "MODEL_STATEMENT",
|
||||
patterns: [
|
||||
/^(?:I've|I have) (?:completed|finished|done)/i,
|
||||
/^(?:The|Your) (?:task|request|change) (?:is|has been) (?:complete|done)/i,
|
||||
/^All (?:changes|modifications) (?:have been|are) (?:made|applied)/i,
|
||||
/^(?:Done|Finished|Complete)[.!]?$/i,
|
||||
/successfully (?:created|modified|updated|deleted)/i,
|
||||
],
|
||||
confidence: 0.3,
|
||||
},
|
||||
];
|
||||
|
||||
export const TOOL_SUCCESS_CONFIDENCE = 0.5;
|
||||
export const OUTPUT_PRESENT_CONFIDENCE = 0.7;
|
||||
export const NO_PENDING_ACTIONS_CONFIDENCE = 0.4;
|
||||
|
||||
export const VALIDATION_CHECK_CONFIGS: Record<
|
||||
ValidationCheckType,
|
||||
{
|
||||
required: boolean;
|
||||
timeout: number;
|
||||
}
|
||||
> = {
|
||||
FILE_EXISTS: { required: true, timeout: 5000 },
|
||||
SYNTAX_VALID: { required: true, timeout: 10000 },
|
||||
DIFF_NONEMPTY: { required: true, timeout: 5000 },
|
||||
TESTS_PASS: { required: false, timeout: 60000 },
|
||||
SCHEMA_VALID: { required: false, timeout: 5000 },
|
||||
NO_REGRESSIONS: { required: false, timeout: 30000 },
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// ENTITY EXTRACTION PATTERNS
|
||||
// =============================================================================
|
||||
|
||||
export const ENTITY_PATTERNS: Record<EntityType, RegExp> = {
|
||||
FILE: /(?:^|\s|["'`])([\w\-./]+\.[a-z]{1,4})(?:\s|$|:|[()\[\]"'`])/gm,
|
||||
FUNCTION: /(?:function|def|fn|func|const|let|var)\s+(\w+)\s*[=(]/g,
|
||||
VARIABLE: /(?:const|let|var|val)\s+(\w+)\s*[=:]/g,
|
||||
CLASS: /(?:class|struct|interface|type|enum)\s+(\w+)/g,
|
||||
URL: /https?:\/\/[^\s<>"']+/g,
|
||||
ERROR_CODE: /(?:error|err|E|errno)\s*[:=]?\s*(\d{3,5})/gi,
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// TOKEN ESTIMATION
|
||||
// =============================================================================
|
||||
|
||||
export const TOKENS_PER_CHAR_ESTIMATE = 0.25;
|
||||
export const DEFAULT_TOKEN_BUDGET = 8000;
|
||||
|
||||
// Default max context (used when model is unknown or "auto")
|
||||
export const DEFAULT_MAX_CONTEXT_TOKENS = 128000;
|
||||
|
||||
// Compaction trigger percentage (compact at 80% of context limit)
|
||||
export const COMPACTION_TRIGGER_PERCENT = 0.8;
|
||||
|
||||
// =============================================================================
|
||||
// PRESERVATION PRIORITIES
|
||||
// =============================================================================
|
||||
|
||||
export const PRESERVATION_PRIORITIES = {
|
||||
CONTEXT_FILE: 1.0,
|
||||
IMAGE: 1.0,
|
||||
RECENT_MESSAGE: 0.8,
|
||||
ERROR: 0.7,
|
||||
DECISION: 0.6,
|
||||
TOOL_RESULT: 0.4,
|
||||
OLD_MESSAGE: 0.2,
|
||||
} as const;
|
||||
|
||||
export type PreservationPriority =
|
||||
(typeof PRESERVATION_PRIORITIES)[keyof typeof PRESERVATION_PRIORITIES];
|
||||
|
||||
// =============================================================================
|
||||
// TASK DECOMPOSITION PATTERNS
|
||||
// =============================================================================
|
||||
|
||||
export const TASK_SEGMENT_PATTERNS: RegExp[] = [
|
||||
/first,?\s+(.+?)\.\s*then,?\s+(.+)/i,
|
||||
/(.+?)\s+and\s+(?:also|then)\s+(.+)/i,
|
||||
/step\s*\d+[:.]\s*(.+)/gi,
|
||||
/\d+[.)]\s*(.+)/gm,
|
||||
/[-•]\s*(.+)/gm,
|
||||
];
|
||||
|
||||
// =============================================================================
|
||||
// EXECUTION PHASE TIMEOUTS
|
||||
// =============================================================================
|
||||
|
||||
export const PHASE_TIMEOUTS: Record<string, number> = {
|
||||
CONTEXT_PREPARATION: 5000,
|
||||
LLM_INTERACTION: 120000,
|
||||
QUALITY_EVALUATION: 1000,
|
||||
RETRY_DECISION: 500,
|
||||
EXECUTION: 300000,
|
||||
TERMINATION_CHECK: 1000,
|
||||
VALIDATION: 60000,
|
||||
};
|
||||
78
src/constants/rules.ts
Normal file
78
src/constants/rules.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Constants for project rules loading
|
||||
*/
|
||||
|
||||
/** Locations to search for general rules file */
|
||||
export const GENERAL_RULES_PATHS = [
|
||||
"rules.md",
|
||||
"RULES.md",
|
||||
".rules.md",
|
||||
"codetyper.rules.md",
|
||||
".codetyper/rules.md",
|
||||
".github/copilot-instructions.md",
|
||||
".github/INSTRUCTIONS.md",
|
||||
".github/instructions.md",
|
||||
] as const;
|
||||
|
||||
/** Directories to search for categorized rules */
|
||||
export const RULES_DIRECTORIES = [
|
||||
"rules",
|
||||
".rules",
|
||||
".codetyper/rules",
|
||||
".github",
|
||||
] as const;
|
||||
|
||||
/** Well-known MCP categories */
|
||||
export const MCP_CATEGORIES = [
|
||||
"figma",
|
||||
"browser",
|
||||
"github",
|
||||
"gitlab",
|
||||
"slack",
|
||||
"notion",
|
||||
"linear",
|
||||
"jira",
|
||||
"confluence",
|
||||
"google-docs",
|
||||
"google-sheets",
|
||||
"airtable",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mongodb",
|
||||
"redis",
|
||||
"docker",
|
||||
"kubernetes",
|
||||
"aws",
|
||||
"gcp",
|
||||
"azure",
|
||||
"vercel",
|
||||
"netlify",
|
||||
"supabase",
|
||||
"firebase",
|
||||
] as const;
|
||||
|
||||
/** Well-known tool categories */
|
||||
export const TOOL_CATEGORIES = [
|
||||
"bash",
|
||||
"read",
|
||||
"write",
|
||||
"edit",
|
||||
"search",
|
||||
"git",
|
||||
] as const;
|
||||
|
||||
/** Rule types for categorization */
|
||||
export const RULE_TYPES = ["mcp", "tool", "custom"] as const;
|
||||
|
||||
/** Section titles for formatted rules */
|
||||
export const RULES_SECTION_TITLES = {
|
||||
mcp: "MCP Integration Rules",
|
||||
tool: "Tool Usage Rules",
|
||||
custom: "Additional Rules",
|
||||
} as const;
|
||||
|
||||
/** Prompt templates for rules */
|
||||
export const RULES_PROMPT_TEMPLATES = {
|
||||
PROJECT_RULES_HEADER:
|
||||
"## Project Rules\n\nThe following rules are specific to this project and must be followed:\n\n",
|
||||
} as const;
|
||||
61
src/constants/runner.ts
Normal file
61
src/constants/runner.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Runner constants for task execution
|
||||
*/
|
||||
|
||||
import type { StepIconMap } from "@/types/runner";
|
||||
|
||||
export const RUNNER_DELAYS = {
|
||||
DISCOVERY: 1500,
|
||||
PLANNING: 1000,
|
||||
STEP_EXECUTION: 1000,
|
||||
} as const;
|
||||
|
||||
export const STEP_ICONS: StepIconMap = {
|
||||
read: "📖",
|
||||
edit: "✏️",
|
||||
create: "📝",
|
||||
delete: "🗑️",
|
||||
execute: "⚙️",
|
||||
} as const;
|
||||
|
||||
export const DEFAULT_STEP_ICON = "📌";
|
||||
|
||||
export const DEFAULT_FILE = "src/index.ts";
|
||||
|
||||
export const RUNNER_MESSAGES = {
|
||||
DISCOVERY_START: "Discovery phase: Analyzing codebase...",
|
||||
DISCOVERY_COMPLETE: "Discovery complete",
|
||||
PLANNING_START: "Planning phase: Creating execution plan...",
|
||||
DRY_RUN_INFO: "Dry run mode - plan generated but not executed",
|
||||
EXECUTION_CANCELLED: "Execution cancelled by user",
|
||||
TASK_COMPLETE: "Task completed successfully!",
|
||||
TASK_FAILED: "Task failed",
|
||||
TASK_REQUIRED: "Task description is required",
|
||||
CONFIRM_EXECUTE: "\nExecute this plan?",
|
||||
} as const;
|
||||
|
||||
export const MOCK_STEPS = {
|
||||
READ: {
|
||||
id: "step_1",
|
||||
type: "read" as const,
|
||||
description: "Read existing files to understand context",
|
||||
tool: "view",
|
||||
},
|
||||
EDIT: {
|
||||
id: "step_2",
|
||||
type: "edit" as const,
|
||||
description: "Apply necessary changes",
|
||||
dependencies: ["step_1"],
|
||||
tool: "edit",
|
||||
},
|
||||
EXECUTE: {
|
||||
id: "step_3",
|
||||
type: "execute" as const,
|
||||
description: "Verify changes work correctly",
|
||||
dependencies: ["step_2"],
|
||||
tool: "bash",
|
||||
args: { command: "npm test" },
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const ESTIMATED_TIME_PER_STEP = 5;
|
||||
6
src/constants/serve.ts
Normal file
6
src/constants/serve.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const SERVER_INFO = `JSON-RPC server mode for Neovim integration.
|
||||
|
||||
This will start the agent in server mode, listening for
|
||||
commands over stdin/stdout using the JSON-RPC protocol.
|
||||
|
||||
Press Ctrl+C to stop the server.`;
|
||||
78
src/constants/spinner.ts
Normal file
78
src/constants/spinner.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Spinner animation constants
|
||||
*/
|
||||
|
||||
// Spinner frame sets
|
||||
export const Spinners = {
|
||||
dots: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
|
||||
line: ["-", "\\", "|", "/"],
|
||||
circle: ["◐", "◓", "◑", "◒"],
|
||||
arrow: ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"],
|
||||
bounce: ["⠁", "⠂", "⠄", "⠂"],
|
||||
bars: [
|
||||
"▏",
|
||||
"▎",
|
||||
"▍",
|
||||
"▌",
|
||||
"▋",
|
||||
"▊",
|
||||
"▉",
|
||||
"█",
|
||||
"▉",
|
||||
"▊",
|
||||
"▋",
|
||||
"▌",
|
||||
"▍",
|
||||
"▎",
|
||||
"▏",
|
||||
],
|
||||
pulse: ["█", "▓", "▒", "░", "▒", "▓"],
|
||||
blocks: ["▖", "▘", "▝", "▗"],
|
||||
clock: [
|
||||
"🕐",
|
||||
"🕑",
|
||||
"🕒",
|
||||
"🕓",
|
||||
"🕔",
|
||||
"🕕",
|
||||
"🕖",
|
||||
"🕗",
|
||||
"🕘",
|
||||
"🕙",
|
||||
"🕚",
|
||||
"🕛",
|
||||
],
|
||||
moon: ["🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"],
|
||||
braille: ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"],
|
||||
scanner: [
|
||||
"[ ]",
|
||||
"[= ]",
|
||||
"[== ]",
|
||||
"[=== ]",
|
||||
"[ ===]",
|
||||
"[ ==]",
|
||||
"[ =]",
|
||||
"[ ]",
|
||||
],
|
||||
} as const;
|
||||
|
||||
// Default spinner configuration
|
||||
export const SPINNER_DEFAULTS = {
|
||||
type: "dots" as const,
|
||||
interval: 80,
|
||||
text: "Loading...",
|
||||
} as const;
|
||||
|
||||
// Scanner spinner defaults
|
||||
export const SCANNER_DEFAULTS = {
|
||||
width: 10,
|
||||
interval: 60,
|
||||
char: "█",
|
||||
} as const;
|
||||
|
||||
// Progress bar defaults
|
||||
export const PROGRESS_BAR_DEFAULTS = {
|
||||
width: 30,
|
||||
filledChar: "█",
|
||||
emptyChar: "░",
|
||||
} as const;
|
||||
238
src/constants/status-messages.ts
Normal file
238
src/constants/status-messages.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Whimsical status messages for different operations
|
||||
*/
|
||||
|
||||
// General thinking messages
|
||||
export const THINKING_MESSAGES = [
|
||||
"Pondering",
|
||||
"Contemplating",
|
||||
"Cogitating",
|
||||
"Ruminating",
|
||||
"Deliberating",
|
||||
"Musing",
|
||||
"Brainstorming",
|
||||
"Noodling",
|
||||
"Percolating",
|
||||
"Synthesizing",
|
||||
"Ideating",
|
||||
"Mulling it over",
|
||||
"Connecting dots",
|
||||
"Brewing thoughts",
|
||||
"Hatching ideas",
|
||||
] as const;
|
||||
|
||||
// Tool-specific messages
|
||||
export const BASH_MESSAGES = [
|
||||
"Executing",
|
||||
"Running",
|
||||
"Invoking",
|
||||
"Launching",
|
||||
"Firing up",
|
||||
"Spinning up",
|
||||
"Kickstarting",
|
||||
] as const;
|
||||
|
||||
export const READ_MESSAGES = [
|
||||
"Reading",
|
||||
"Scanning",
|
||||
"Perusing",
|
||||
"Examining",
|
||||
"Inspecting",
|
||||
"Analyzing",
|
||||
"Studying",
|
||||
"Digesting",
|
||||
] as const;
|
||||
|
||||
export const WRITE_MESSAGES = [
|
||||
"Writing",
|
||||
"Crafting",
|
||||
"Composing",
|
||||
"Authoring",
|
||||
"Scribing",
|
||||
"Generating",
|
||||
"Creating",
|
||||
"Materializing",
|
||||
] as const;
|
||||
|
||||
export const EDIT_MESSAGES = [
|
||||
"Editing",
|
||||
"Refining",
|
||||
"Polishing",
|
||||
"Tweaking",
|
||||
"Adjusting",
|
||||
"Massaging",
|
||||
"Tuning",
|
||||
"Perfecting",
|
||||
] as const;
|
||||
|
||||
export const GLOB_MESSAGES = [
|
||||
"Searching",
|
||||
"Hunting",
|
||||
"Scouring",
|
||||
"Exploring",
|
||||
"Traversing",
|
||||
"Scanning",
|
||||
] as const;
|
||||
|
||||
export const GREP_MESSAGES = [
|
||||
"Grepping",
|
||||
"Searching",
|
||||
"Pattern matching",
|
||||
"Filtering",
|
||||
"Sifting through",
|
||||
] as const;
|
||||
|
||||
export const TOOL_MESSAGES: Record<string, readonly string[]> = {
|
||||
bash: BASH_MESSAGES,
|
||||
read: READ_MESSAGES,
|
||||
write: WRITE_MESSAGES,
|
||||
edit: EDIT_MESSAGES,
|
||||
glob: GLOB_MESSAGES,
|
||||
grep: GREP_MESSAGES,
|
||||
};
|
||||
|
||||
// Fallback messages for unknown tools
|
||||
export const GENERIC_TOOL_MESSAGES = [
|
||||
"Processing",
|
||||
"Working on",
|
||||
"Handling",
|
||||
"Tackling",
|
||||
"Attending to",
|
||||
"Taking care of",
|
||||
] as const;
|
||||
|
||||
// Fun filler words that can be combined
|
||||
export const FILLER_ACTIONS = [
|
||||
"Flibbertigibbeting",
|
||||
"Discombobulating",
|
||||
"Recalibrating",
|
||||
"Defenestrating bugs",
|
||||
"Wrangling bits",
|
||||
"Herding electrons",
|
||||
"Caffeinating",
|
||||
"Quantum entangling",
|
||||
"Reverse engineering gravity",
|
||||
"Consulting the oracle",
|
||||
"Aligning chakras",
|
||||
"Summoning expertise",
|
||||
"Channeling wisdom",
|
||||
"Marshalling resources",
|
||||
"Orchestrating magic",
|
||||
] as const;
|
||||
|
||||
// Messages for specific file types
|
||||
export const FILE_TYPE_MESSAGES: Record<string, string[]> = {
|
||||
ts: ["TypeScripting", "Type-checking", "Transpiling thoughts"],
|
||||
tsx: ["Rendering components", "JSX-ing", "Reactifying"],
|
||||
js: ["JavaScripting", "Interpreting"],
|
||||
json: ["Parsing JSON", "Structuring data"],
|
||||
md: ["Marking down", "Documenting"],
|
||||
css: ["Styling", "Beautifying"],
|
||||
html: ["Marking up", "Structuring"],
|
||||
py: ["Pythoning", "Slithering through code"],
|
||||
rs: ["Rusting", "Borrowing safely"],
|
||||
go: ["Going", "Goroutining"],
|
||||
sql: ["Querying", "Selecting wisdom"],
|
||||
yaml: ["YAMLing", "Indenting carefully"],
|
||||
toml: ["TOMLing", "Configuring"],
|
||||
sh: ["Shelling", "Bashing"],
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a random message from an array
|
||||
*/
|
||||
function randomFrom<T>(arr: readonly T[]): T {
|
||||
return arr[Math.floor(Math.random() * arr.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a thinking message
|
||||
*/
|
||||
export function getThinkingMessage(): string {
|
||||
// 20% chance of a fun filler message
|
||||
if (Math.random() < 0.2) {
|
||||
return `✻ ${randomFrom(FILLER_ACTIONS)}…`;
|
||||
}
|
||||
return `✻ ${randomFrom(THINKING_MESSAGES)}…`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a tool execution message based on tool name and optional file path
|
||||
*/
|
||||
export function getToolMessage(toolName: string, filePath?: string): string {
|
||||
// Check for file-type specific messages
|
||||
if (filePath) {
|
||||
const ext = filePath.split(".").pop()?.toLowerCase();
|
||||
if (ext && FILE_TYPE_MESSAGES[ext]) {
|
||||
return `✻ ${randomFrom(FILE_TYPE_MESSAGES[ext])}…`;
|
||||
}
|
||||
}
|
||||
|
||||
// Get tool-specific messages
|
||||
const messages = TOOL_MESSAGES[toolName] || GENERIC_TOOL_MESSAGES;
|
||||
return `✻ ${randomFrom(messages)}…`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a contextual message based on what's happening
|
||||
*/
|
||||
export function getContextualMessage(context: {
|
||||
mode: "thinking" | "tool_execution";
|
||||
toolName?: string;
|
||||
filePath?: string;
|
||||
description?: string;
|
||||
}): string {
|
||||
if (context.mode === "thinking") {
|
||||
return getThinkingMessage();
|
||||
}
|
||||
|
||||
if (context.toolName) {
|
||||
return getToolMessage(context.toolName, context.filePath);
|
||||
}
|
||||
|
||||
return `✻ ${randomFrom(GENERIC_TOOL_MESSAGES)}…`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Status message rotator - cycles through messages at intervals
|
||||
*/
|
||||
export class StatusMessageRotator {
|
||||
private intervalId: ReturnType<typeof setInterval> | null = null;
|
||||
private currentMode: "thinking" | "tool_execution" = "thinking";
|
||||
private toolContext: { name?: string; path?: string } = {};
|
||||
|
||||
start(onMessage: (message: string) => void, intervalMs = 3000): void {
|
||||
this.stop();
|
||||
|
||||
// Emit initial message
|
||||
onMessage(this.getMessage());
|
||||
|
||||
// Rotate messages
|
||||
this.intervalId = setInterval(() => {
|
||||
onMessage(this.getMessage());
|
||||
}, intervalMs);
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
setMode(mode: "thinking" | "tool_execution"): void {
|
||||
this.currentMode = mode;
|
||||
}
|
||||
|
||||
setToolContext(name?: string, path?: string): void {
|
||||
this.toolContext = { name, path };
|
||||
}
|
||||
|
||||
private getMessage(): string {
|
||||
return getContextualMessage({
|
||||
mode: this.currentMode,
|
||||
toolName: this.toolContext.name,
|
||||
filePath: this.toolContext.path,
|
||||
});
|
||||
}
|
||||
}
|
||||
95
src/constants/styles.ts
Normal file
95
src/constants/styles.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* ANSI color styles constants for terminal output
|
||||
*/
|
||||
|
||||
// ANSI escape codes
|
||||
export const Style = {
|
||||
// Reset
|
||||
RESET: "\x1b[0m",
|
||||
|
||||
// Text styles
|
||||
BOLD: "\x1b[1m",
|
||||
DIM: "\x1b[2m",
|
||||
ITALIC: "\x1b[3m",
|
||||
UNDERLINE: "\x1b[4m",
|
||||
|
||||
// Colors
|
||||
BLACK: "\x1b[30m",
|
||||
RED: "\x1b[31m",
|
||||
GREEN: "\x1b[32m",
|
||||
YELLOW: "\x1b[33m",
|
||||
BLUE: "\x1b[34m",
|
||||
MAGENTA: "\x1b[35m",
|
||||
CYAN: "\x1b[36m",
|
||||
WHITE: "\x1b[37m",
|
||||
GRAY: "\x1b[90m",
|
||||
|
||||
// Bright colors
|
||||
BRIGHT_RED: "\x1b[91m",
|
||||
BRIGHT_GREEN: "\x1b[92m",
|
||||
BRIGHT_YELLOW: "\x1b[93m",
|
||||
BRIGHT_BLUE: "\x1b[94m",
|
||||
BRIGHT_MAGENTA: "\x1b[95m",
|
||||
BRIGHT_CYAN: "\x1b[96m",
|
||||
BRIGHT_WHITE: "\x1b[97m",
|
||||
|
||||
// Background colors
|
||||
BG_BLACK: "\x1b[40m",
|
||||
BG_RED: "\x1b[41m",
|
||||
BG_GREEN: "\x1b[42m",
|
||||
BG_YELLOW: "\x1b[43m",
|
||||
BG_BLUE: "\x1b[44m",
|
||||
BG_MAGENTA: "\x1b[45m",
|
||||
BG_CYAN: "\x1b[46m",
|
||||
BG_WHITE: "\x1b[47m",
|
||||
} as const;
|
||||
|
||||
// Semantic colors
|
||||
export const Theme = {
|
||||
primary: Style.BRIGHT_CYAN,
|
||||
secondary: Style.BRIGHT_MAGENTA,
|
||||
accent: Style.BRIGHT_BLUE,
|
||||
success: Style.BRIGHT_GREEN,
|
||||
warning: Style.BRIGHT_YELLOW,
|
||||
error: Style.BRIGHT_RED,
|
||||
info: Style.BRIGHT_BLUE,
|
||||
text: Style.WHITE,
|
||||
textMuted: Style.GRAY,
|
||||
textDim: Style.DIM,
|
||||
} as const;
|
||||
|
||||
// Icons
|
||||
export const Icons = {
|
||||
// Status
|
||||
success: "\u2714", // ✔
|
||||
error: "\u2718", // ✘
|
||||
warning: "\u26A0", // ⚠
|
||||
info: "\u2139", // ℹ
|
||||
pending: "\u25CB", // ○
|
||||
running: "\u25CF", // ●
|
||||
|
||||
// Actions
|
||||
arrow: "\u2192", // →
|
||||
arrowLeft: "\u2190", // ←
|
||||
arrowUp: "\u2191", // ↑
|
||||
arrowDown: "\u2193", // ↓
|
||||
|
||||
// Tools
|
||||
bash: "$",
|
||||
read: "\u2192", // →
|
||||
write: "\u2190", // ←
|
||||
edit: "\u270E", // ✎
|
||||
search: "\u2731", // ✱
|
||||
|
||||
// Misc
|
||||
bullet: "\u2022", // •
|
||||
dot: "\u00B7", // ·
|
||||
star: "\u2605", // ★
|
||||
sparkle: "\u2728", // ✨
|
||||
lightning: "\u26A1", // ⚡
|
||||
gear: "\u2699", // ⚙
|
||||
key: "\u1F511", // 🔑
|
||||
lock: "\u1F512", // 🔒
|
||||
folder: "\u1F4C1", // 📁
|
||||
file: "\u1F4C4", // 📄
|
||||
} as const;
|
||||
170
src/constants/syntax-highlight.ts
Normal file
170
src/constants/syntax-highlight.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Syntax highlighting constants
|
||||
*/
|
||||
|
||||
/** Map file extensions to highlight.js language identifiers */
|
||||
export const EXTENSION_TO_LANGUAGE: Record<string, string> = {
|
||||
// JavaScript/TypeScript
|
||||
".js": "javascript",
|
||||
".jsx": "javascript",
|
||||
".ts": "typescript",
|
||||
".tsx": "typescript",
|
||||
".mjs": "javascript",
|
||||
".cjs": "javascript",
|
||||
|
||||
// Web
|
||||
".html": "html",
|
||||
".htm": "html",
|
||||
".css": "css",
|
||||
".scss": "scss",
|
||||
".sass": "scss",
|
||||
".less": "less",
|
||||
".vue": "vue",
|
||||
".svelte": "svelte",
|
||||
|
||||
// Data formats
|
||||
".json": "json",
|
||||
".yaml": "yaml",
|
||||
".yml": "yaml",
|
||||
".toml": "toml",
|
||||
".xml": "xml",
|
||||
".csv": "plaintext",
|
||||
|
||||
// Systems programming
|
||||
".c": "c",
|
||||
".h": "c",
|
||||
".cpp": "cpp",
|
||||
".cc": "cpp",
|
||||
".cxx": "cpp",
|
||||
".hpp": "cpp",
|
||||
".rs": "rust",
|
||||
".go": "go",
|
||||
".zig": "zig",
|
||||
|
||||
// JVM languages
|
||||
".java": "java",
|
||||
".kt": "kotlin",
|
||||
".kts": "kotlin",
|
||||
".scala": "scala",
|
||||
".groovy": "groovy",
|
||||
".gradle": "groovy",
|
||||
|
||||
// .NET languages
|
||||
".cs": "csharp",
|
||||
".fs": "fsharp",
|
||||
".vb": "vbnet",
|
||||
|
||||
// Scripting
|
||||
".py": "python",
|
||||
".rb": "ruby",
|
||||
".php": "php",
|
||||
".pl": "perl",
|
||||
".lua": "lua",
|
||||
".r": "r",
|
||||
".R": "r",
|
||||
|
||||
// Shell
|
||||
".sh": "bash",
|
||||
".bash": "bash",
|
||||
".zsh": "bash",
|
||||
".fish": "fish",
|
||||
".ps1": "powershell",
|
||||
".psm1": "powershell",
|
||||
".bat": "batch",
|
||||
".cmd": "batch",
|
||||
|
||||
// Config files
|
||||
".conf": "nginx",
|
||||
".ini": "ini",
|
||||
".env": "bash",
|
||||
".dockerfile": "dockerfile",
|
||||
".gitignore": "plaintext",
|
||||
".editorconfig": "ini",
|
||||
|
||||
// Documentation
|
||||
".md": "markdown",
|
||||
".markdown": "markdown",
|
||||
".rst": "plaintext",
|
||||
".txt": "plaintext",
|
||||
|
||||
// Database
|
||||
".sql": "sql",
|
||||
".prisma": "prisma",
|
||||
|
||||
// Mobile
|
||||
".swift": "swift",
|
||||
".m": "objectivec",
|
||||
".mm": "objectivec",
|
||||
".dart": "dart",
|
||||
|
||||
// Other
|
||||
".ex": "elixir",
|
||||
".exs": "elixir",
|
||||
".erl": "erlang",
|
||||
".hrl": "erlang",
|
||||
".hs": "haskell",
|
||||
".clj": "clojure",
|
||||
".cljs": "clojure",
|
||||
".elm": "elm",
|
||||
".nim": "nim",
|
||||
".v": "v",
|
||||
".asm": "x86asm",
|
||||
".s": "x86asm",
|
||||
".wasm": "wasm",
|
||||
".graphql": "graphql",
|
||||
".gql": "graphql",
|
||||
".tf": "hcl",
|
||||
".hcl": "hcl",
|
||||
".nix": "nix",
|
||||
".proto": "protobuf",
|
||||
} as const;
|
||||
|
||||
/** Special filename mappings */
|
||||
export const FILENAME_TO_LANGUAGE: Record<string, string> = {
|
||||
Dockerfile: "dockerfile",
|
||||
Makefile: "makefile",
|
||||
"CMakeLists.txt": "cmake",
|
||||
Gemfile: "ruby",
|
||||
Rakefile: "ruby",
|
||||
Vagrantfile: "ruby",
|
||||
Brewfile: "ruby",
|
||||
".bashrc": "bash",
|
||||
".zshrc": "bash",
|
||||
".bash_profile": "bash",
|
||||
".profile": "bash",
|
||||
"package.json": "json",
|
||||
"tsconfig.json": "json",
|
||||
"jsconfig.json": "json",
|
||||
".prettierrc": "json",
|
||||
".eslintrc": "json",
|
||||
"nginx.conf": "nginx",
|
||||
"docker-compose.yml": "yaml",
|
||||
"docker-compose.yaml": "yaml",
|
||||
} as const;
|
||||
|
||||
/** Human-readable language display names */
|
||||
export const LANGUAGE_DISPLAY_NAMES: Record<string, string> = {
|
||||
javascript: "JavaScript",
|
||||
typescript: "TypeScript",
|
||||
python: "Python",
|
||||
java: "Java",
|
||||
cpp: "C++",
|
||||
csharp: "C#",
|
||||
go: "Go",
|
||||
rust: "Rust",
|
||||
ruby: "Ruby",
|
||||
php: "PHP",
|
||||
swift: "Swift",
|
||||
kotlin: "Kotlin",
|
||||
scala: "Scala",
|
||||
html: "HTML",
|
||||
css: "CSS",
|
||||
scss: "SCSS",
|
||||
json: "JSON",
|
||||
yaml: "YAML",
|
||||
markdown: "Markdown",
|
||||
bash: "Bash",
|
||||
sql: "SQL",
|
||||
dockerfile: "Dockerfile",
|
||||
graphql: "GraphQL",
|
||||
} as const;
|
||||
9
src/constants/terminal.ts
Normal file
9
src/constants/terminal.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Mouse tracking disable sequence (all modes)
|
||||
*/
|
||||
export const DISABLE_MOUSE_TRACKING =
|
||||
"\x1b[?1006l" + // SGR Mouse Mode
|
||||
"\x1b[?1015l" + // urxvt Mouse Mode
|
||||
"\x1b[?1003l" + // All mouse events (motion)
|
||||
"\x1b[?1002l" + // Button event mouse tracking
|
||||
"\x1b[?1000l"; // Normal tracking mode
|
||||
834
src/constants/themes.ts
Normal file
834
src/constants/themes.ts
Normal file
@@ -0,0 +1,834 @@
|
||||
/**
|
||||
* Built-in Theme Definitions
|
||||
*
|
||||
* Provides pre-configured color themes for the TUI
|
||||
*/
|
||||
|
||||
import type { Theme, ThemeColors } from "@/types/theme";
|
||||
|
||||
const DEFAULT_COLORS: ThemeColors = {
|
||||
primary: "#00ffff",
|
||||
secondary: "#0088ff",
|
||||
accent: "#ff00ff",
|
||||
|
||||
success: "#00ff00",
|
||||
error: "#ff0000",
|
||||
warning: "#ffff00",
|
||||
info: "#00ffff",
|
||||
|
||||
text: "#ffffff",
|
||||
textDim: "#808080",
|
||||
textMuted: "#666666",
|
||||
|
||||
background: "#0a0a0a",
|
||||
backgroundPanel: "#141414",
|
||||
backgroundElement: "#1e1e1e",
|
||||
|
||||
border: "#808080",
|
||||
borderFocus: "#00ffff",
|
||||
borderWarning: "#ffff00",
|
||||
borderModal: "#ff00ff",
|
||||
|
||||
bgHighlight: "#00ffff",
|
||||
bgCursor: "#00ffff",
|
||||
bgAdded: "#00ff88",
|
||||
bgRemoved: "#ff4444",
|
||||
|
||||
diffAdded: "#00ff00",
|
||||
diffRemoved: "#ff0000",
|
||||
diffContext: "#808080",
|
||||
diffHeader: "#ffffff",
|
||||
diffHunk: "#00ffff",
|
||||
|
||||
roleUser: "#00ffff",
|
||||
roleAssistant: "#00ff00",
|
||||
roleSystem: "#ffff00",
|
||||
roleTool: "#ffff00",
|
||||
|
||||
modeIdle: "#00ff00",
|
||||
modeEditing: "#00ffff",
|
||||
modeThinking: "#ff00ff",
|
||||
modeToolExecution: "#ffff00",
|
||||
modePermission: "#ffff00",
|
||||
|
||||
toolPending: "#808080",
|
||||
toolRunning: "#ffff00",
|
||||
toolSuccess: "#00ff00",
|
||||
toolError: "#ff0000",
|
||||
|
||||
headerGradient: ["#00ffff", "#00dddd", "#0088ff"],
|
||||
};
|
||||
|
||||
const DRACULA_COLORS: ThemeColors = {
|
||||
primary: "#bd93f9",
|
||||
secondary: "#6272a4",
|
||||
accent: "#ff79c6",
|
||||
|
||||
success: "#50fa7b",
|
||||
error: "#ff5555",
|
||||
warning: "#f1fa8c",
|
||||
info: "#8be9fd",
|
||||
|
||||
text: "#f8f8f2",
|
||||
textDim: "#6272a4",
|
||||
textMuted: "#44475a",
|
||||
|
||||
background: "#282a36",
|
||||
backgroundPanel: "#21222c",
|
||||
backgroundElement: "#343746",
|
||||
|
||||
border: "#44475a",
|
||||
borderFocus: "#bd93f9",
|
||||
borderWarning: "#f1fa8c",
|
||||
borderModal: "#ff79c6",
|
||||
|
||||
bgHighlight: "#44475a",
|
||||
bgCursor: "#bd93f9",
|
||||
bgAdded: "#50fa7b",
|
||||
bgRemoved: "#ff5555",
|
||||
|
||||
diffAdded: "#50fa7b",
|
||||
diffRemoved: "#ff5555",
|
||||
diffContext: "#6272a4",
|
||||
diffHeader: "#f8f8f2",
|
||||
diffHunk: "#8be9fd",
|
||||
|
||||
roleUser: "#8be9fd",
|
||||
roleAssistant: "#50fa7b",
|
||||
roleSystem: "#f1fa8c",
|
||||
roleTool: "#ffb86c",
|
||||
|
||||
modeIdle: "#50fa7b",
|
||||
modeEditing: "#8be9fd",
|
||||
modeThinking: "#bd93f9",
|
||||
modeToolExecution: "#f1fa8c",
|
||||
modePermission: "#ffb86c",
|
||||
|
||||
toolPending: "#6272a4",
|
||||
toolRunning: "#f1fa8c",
|
||||
toolSuccess: "#50fa7b",
|
||||
toolError: "#ff5555",
|
||||
|
||||
headerGradient: ["#bd93f9", "#ff79c6", "#8be9fd"],
|
||||
};
|
||||
|
||||
const NORD_COLORS: ThemeColors = {
|
||||
primary: "#88c0d0",
|
||||
secondary: "#5e81ac",
|
||||
accent: "#b48ead",
|
||||
|
||||
success: "#a3be8c",
|
||||
error: "#bf616a",
|
||||
warning: "#ebcb8b",
|
||||
info: "#88c0d0",
|
||||
|
||||
text: "#eceff4",
|
||||
textDim: "#4c566a",
|
||||
textMuted: "#3b4252",
|
||||
|
||||
background: "#2e3440",
|
||||
backgroundPanel: "#3b4252",
|
||||
backgroundElement: "#434c5e",
|
||||
|
||||
border: "#3b4252",
|
||||
borderFocus: "#88c0d0",
|
||||
borderWarning: "#ebcb8b",
|
||||
borderModal: "#b48ead",
|
||||
|
||||
bgHighlight: "#3b4252",
|
||||
bgCursor: "#88c0d0",
|
||||
bgAdded: "#a3be8c",
|
||||
bgRemoved: "#bf616a",
|
||||
|
||||
diffAdded: "#a3be8c",
|
||||
diffRemoved: "#bf616a",
|
||||
diffContext: "#4c566a",
|
||||
diffHeader: "#eceff4",
|
||||
diffHunk: "#81a1c1",
|
||||
|
||||
roleUser: "#88c0d0",
|
||||
roleAssistant: "#a3be8c",
|
||||
roleSystem: "#ebcb8b",
|
||||
roleTool: "#d08770",
|
||||
|
||||
modeIdle: "#a3be8c",
|
||||
modeEditing: "#88c0d0",
|
||||
modeThinking: "#b48ead",
|
||||
modeToolExecution: "#ebcb8b",
|
||||
modePermission: "#d08770",
|
||||
|
||||
toolPending: "#4c566a",
|
||||
toolRunning: "#ebcb8b",
|
||||
toolSuccess: "#a3be8c",
|
||||
toolError: "#bf616a",
|
||||
|
||||
headerGradient: ["#88c0d0", "#81a1c1", "#5e81ac"],
|
||||
};
|
||||
|
||||
const TOKYO_NIGHT_COLORS: ThemeColors = {
|
||||
primary: "#7aa2f7",
|
||||
secondary: "#565f89",
|
||||
accent: "#bb9af7",
|
||||
|
||||
success: "#9ece6a",
|
||||
error: "#f7768e",
|
||||
warning: "#e0af68",
|
||||
info: "#7dcfff",
|
||||
|
||||
text: "#c0caf5",
|
||||
textDim: "#565f89",
|
||||
textMuted: "#414868",
|
||||
|
||||
background: "#1a1b26",
|
||||
backgroundPanel: "#16161e",
|
||||
backgroundElement: "#24283b",
|
||||
|
||||
border: "#414868",
|
||||
borderFocus: "#7aa2f7",
|
||||
borderWarning: "#e0af68",
|
||||
borderModal: "#bb9af7",
|
||||
|
||||
bgHighlight: "#414868",
|
||||
bgCursor: "#7aa2f7",
|
||||
bgAdded: "#9ece6a",
|
||||
bgRemoved: "#f7768e",
|
||||
|
||||
diffAdded: "#9ece6a",
|
||||
diffRemoved: "#f7768e",
|
||||
diffContext: "#565f89",
|
||||
diffHeader: "#c0caf5",
|
||||
diffHunk: "#7dcfff",
|
||||
|
||||
roleUser: "#7dcfff",
|
||||
roleAssistant: "#9ece6a",
|
||||
roleSystem: "#e0af68",
|
||||
roleTool: "#ff9e64",
|
||||
|
||||
modeIdle: "#9ece6a",
|
||||
modeEditing: "#7aa2f7",
|
||||
modeThinking: "#bb9af7",
|
||||
modeToolExecution: "#e0af68",
|
||||
modePermission: "#ff9e64",
|
||||
|
||||
toolPending: "#565f89",
|
||||
toolRunning: "#e0af68",
|
||||
toolSuccess: "#9ece6a",
|
||||
toolError: "#f7768e",
|
||||
|
||||
headerGradient: ["#7aa2f7", "#bb9af7", "#7dcfff"],
|
||||
};
|
||||
|
||||
const GRUVBOX_COLORS: ThemeColors = {
|
||||
primary: "#83a598",
|
||||
secondary: "#458588",
|
||||
accent: "#d3869b",
|
||||
|
||||
success: "#b8bb26",
|
||||
error: "#fb4934",
|
||||
warning: "#fabd2f",
|
||||
info: "#83a598",
|
||||
|
||||
text: "#ebdbb2",
|
||||
textDim: "#665c54",
|
||||
textMuted: "#504945",
|
||||
|
||||
background: "#282828",
|
||||
backgroundPanel: "#1d2021",
|
||||
backgroundElement: "#3c3836",
|
||||
|
||||
border: "#504945",
|
||||
borderFocus: "#83a598",
|
||||
borderWarning: "#fabd2f",
|
||||
borderModal: "#d3869b",
|
||||
|
||||
bgHighlight: "#504945",
|
||||
bgCursor: "#83a598",
|
||||
bgAdded: "#b8bb26",
|
||||
bgRemoved: "#fb4934",
|
||||
|
||||
diffAdded: "#b8bb26",
|
||||
diffRemoved: "#fb4934",
|
||||
diffContext: "#665c54",
|
||||
diffHeader: "#ebdbb2",
|
||||
diffHunk: "#8ec07c",
|
||||
|
||||
roleUser: "#83a598",
|
||||
roleAssistant: "#b8bb26",
|
||||
roleSystem: "#fabd2f",
|
||||
roleTool: "#fe8019",
|
||||
|
||||
modeIdle: "#b8bb26",
|
||||
modeEditing: "#83a598",
|
||||
modeThinking: "#d3869b",
|
||||
modeToolExecution: "#fabd2f",
|
||||
modePermission: "#fe8019",
|
||||
|
||||
toolPending: "#665c54",
|
||||
toolRunning: "#fabd2f",
|
||||
toolSuccess: "#b8bb26",
|
||||
toolError: "#fb4934",
|
||||
|
||||
headerGradient: ["#b8bb26", "#83a598", "#fabd2f"],
|
||||
};
|
||||
|
||||
const MONOKAI_COLORS: ThemeColors = {
|
||||
primary: "#66d9ef",
|
||||
secondary: "#ae81ff",
|
||||
accent: "#f92672",
|
||||
|
||||
success: "#a6e22e",
|
||||
error: "#f92672",
|
||||
warning: "#e6db74",
|
||||
info: "#66d9ef",
|
||||
|
||||
text: "#f8f8f2",
|
||||
textDim: "#75715e",
|
||||
textMuted: "#49483e",
|
||||
|
||||
background: "#272822",
|
||||
backgroundPanel: "#1e1f1c",
|
||||
backgroundElement: "#3e3d32",
|
||||
|
||||
border: "#49483e",
|
||||
borderFocus: "#66d9ef",
|
||||
borderWarning: "#e6db74",
|
||||
borderModal: "#ae81ff",
|
||||
|
||||
bgHighlight: "#49483e",
|
||||
bgCursor: "#66d9ef",
|
||||
bgAdded: "#a6e22e",
|
||||
bgRemoved: "#f92672",
|
||||
|
||||
diffAdded: "#a6e22e",
|
||||
diffRemoved: "#f92672",
|
||||
diffContext: "#75715e",
|
||||
diffHeader: "#f8f8f2",
|
||||
diffHunk: "#66d9ef",
|
||||
|
||||
roleUser: "#66d9ef",
|
||||
roleAssistant: "#a6e22e",
|
||||
roleSystem: "#e6db74",
|
||||
roleTool: "#fd971f",
|
||||
|
||||
modeIdle: "#a6e22e",
|
||||
modeEditing: "#66d9ef",
|
||||
modeThinking: "#ae81ff",
|
||||
modeToolExecution: "#e6db74",
|
||||
modePermission: "#fd971f",
|
||||
|
||||
toolPending: "#75715e",
|
||||
toolRunning: "#e6db74",
|
||||
toolSuccess: "#a6e22e",
|
||||
toolError: "#f92672",
|
||||
|
||||
headerGradient: ["#a6e22e", "#66d9ef", "#ae81ff"],
|
||||
};
|
||||
|
||||
const CATPPUCCIN_COLORS: ThemeColors = {
|
||||
primary: "#89b4fa",
|
||||
secondary: "#74c7ec",
|
||||
accent: "#cba6f7",
|
||||
|
||||
success: "#a6e3a1",
|
||||
error: "#f38ba8",
|
||||
warning: "#f9e2af",
|
||||
info: "#89dceb",
|
||||
|
||||
text: "#cdd6f4",
|
||||
textDim: "#6c7086",
|
||||
textMuted: "#45475a",
|
||||
|
||||
background: "#1e1e2e",
|
||||
backgroundPanel: "#181825",
|
||||
backgroundElement: "#313244",
|
||||
|
||||
border: "#45475a",
|
||||
borderFocus: "#89b4fa",
|
||||
borderWarning: "#f9e2af",
|
||||
borderModal: "#cba6f7",
|
||||
|
||||
bgHighlight: "#45475a",
|
||||
bgCursor: "#89b4fa",
|
||||
bgAdded: "#a6e3a1",
|
||||
bgRemoved: "#f38ba8",
|
||||
|
||||
diffAdded: "#a6e3a1",
|
||||
diffRemoved: "#f38ba8",
|
||||
diffContext: "#6c7086",
|
||||
diffHeader: "#cdd6f4",
|
||||
diffHunk: "#89dceb",
|
||||
|
||||
roleUser: "#89dceb",
|
||||
roleAssistant: "#a6e3a1",
|
||||
roleSystem: "#f9e2af",
|
||||
roleTool: "#fab387",
|
||||
|
||||
modeIdle: "#a6e3a1",
|
||||
modeEditing: "#89b4fa",
|
||||
modeThinking: "#cba6f7",
|
||||
modeToolExecution: "#f9e2af",
|
||||
modePermission: "#fab387",
|
||||
|
||||
toolPending: "#6c7086",
|
||||
toolRunning: "#f9e2af",
|
||||
toolSuccess: "#a6e3a1",
|
||||
toolError: "#f38ba8",
|
||||
|
||||
headerGradient: ["#89b4fa", "#cba6f7", "#f5c2e7"],
|
||||
};
|
||||
|
||||
const ONE_DARK_COLORS: ThemeColors = {
|
||||
primary: "#61afef",
|
||||
secondary: "#528bff",
|
||||
accent: "#c678dd",
|
||||
|
||||
success: "#98c379",
|
||||
error: "#e06c75",
|
||||
warning: "#e5c07b",
|
||||
info: "#56b6c2",
|
||||
|
||||
text: "#abb2bf",
|
||||
textDim: "#5c6370",
|
||||
textMuted: "#3e4451",
|
||||
|
||||
background: "#282c34",
|
||||
backgroundPanel: "#21252b",
|
||||
backgroundElement: "#2c323c",
|
||||
|
||||
border: "#3e4451",
|
||||
borderFocus: "#61afef",
|
||||
borderWarning: "#e5c07b",
|
||||
borderModal: "#c678dd",
|
||||
|
||||
bgHighlight: "#3e4451",
|
||||
bgCursor: "#61afef",
|
||||
bgAdded: "#98c379",
|
||||
bgRemoved: "#e06c75",
|
||||
|
||||
diffAdded: "#98c379",
|
||||
diffRemoved: "#e06c75",
|
||||
diffContext: "#5c6370",
|
||||
diffHeader: "#abb2bf",
|
||||
diffHunk: "#56b6c2",
|
||||
|
||||
roleUser: "#56b6c2",
|
||||
roleAssistant: "#98c379",
|
||||
roleSystem: "#e5c07b",
|
||||
roleTool: "#d19a66",
|
||||
|
||||
modeIdle: "#98c379",
|
||||
modeEditing: "#61afef",
|
||||
modeThinking: "#c678dd",
|
||||
modeToolExecution: "#e5c07b",
|
||||
modePermission: "#d19a66",
|
||||
|
||||
toolPending: "#5c6370",
|
||||
toolRunning: "#e5c07b",
|
||||
toolSuccess: "#98c379",
|
||||
toolError: "#e06c75",
|
||||
|
||||
headerGradient: ["#61afef", "#c678dd", "#56b6c2"],
|
||||
};
|
||||
|
||||
const SOLARIZED_DARK_COLORS: ThemeColors = {
|
||||
primary: "#268bd2",
|
||||
secondary: "#2aa198",
|
||||
accent: "#6c71c4",
|
||||
|
||||
success: "#859900",
|
||||
error: "#dc322f",
|
||||
warning: "#b58900",
|
||||
info: "#2aa198",
|
||||
|
||||
text: "#839496",
|
||||
textDim: "#586e75",
|
||||
textMuted: "#073642",
|
||||
|
||||
background: "#002b36",
|
||||
backgroundPanel: "#001f27",
|
||||
backgroundElement: "#073642",
|
||||
|
||||
border: "#073642",
|
||||
borderFocus: "#268bd2",
|
||||
borderWarning: "#b58900",
|
||||
borderModal: "#6c71c4",
|
||||
|
||||
bgHighlight: "#073642",
|
||||
bgCursor: "#268bd2",
|
||||
bgAdded: "#859900",
|
||||
bgRemoved: "#dc322f",
|
||||
|
||||
diffAdded: "#859900",
|
||||
diffRemoved: "#dc322f",
|
||||
diffContext: "#586e75",
|
||||
diffHeader: "#93a1a1",
|
||||
diffHunk: "#2aa198",
|
||||
|
||||
roleUser: "#2aa198",
|
||||
roleAssistant: "#859900",
|
||||
roleSystem: "#b58900",
|
||||
roleTool: "#cb4b16",
|
||||
|
||||
modeIdle: "#859900",
|
||||
modeEditing: "#268bd2",
|
||||
modeThinking: "#6c71c4",
|
||||
modeToolExecution: "#b58900",
|
||||
modePermission: "#cb4b16",
|
||||
|
||||
toolPending: "#586e75",
|
||||
toolRunning: "#b58900",
|
||||
toolSuccess: "#859900",
|
||||
toolError: "#dc322f",
|
||||
|
||||
headerGradient: ["#268bd2", "#2aa198", "#859900"],
|
||||
};
|
||||
|
||||
const GITHUB_DARK_COLORS: ThemeColors = {
|
||||
primary: "#58a6ff",
|
||||
secondary: "#388bfd",
|
||||
accent: "#a371f7",
|
||||
|
||||
success: "#3fb950",
|
||||
error: "#f85149",
|
||||
warning: "#d29922",
|
||||
info: "#58a6ff",
|
||||
|
||||
text: "#c9d1d9",
|
||||
textDim: "#8b949e",
|
||||
textMuted: "#484f58",
|
||||
|
||||
background: "#0d1117",
|
||||
backgroundPanel: "#010409",
|
||||
backgroundElement: "#161b22",
|
||||
|
||||
border: "#30363d",
|
||||
borderFocus: "#58a6ff",
|
||||
borderWarning: "#d29922",
|
||||
borderModal: "#a371f7",
|
||||
|
||||
bgHighlight: "#161b22",
|
||||
bgCursor: "#58a6ff",
|
||||
bgAdded: "#238636",
|
||||
bgRemoved: "#da3633",
|
||||
|
||||
diffAdded: "#3fb950",
|
||||
diffRemoved: "#f85149",
|
||||
diffContext: "#8b949e",
|
||||
diffHeader: "#c9d1d9",
|
||||
diffHunk: "#58a6ff",
|
||||
|
||||
roleUser: "#58a6ff",
|
||||
roleAssistant: "#3fb950",
|
||||
roleSystem: "#d29922",
|
||||
roleTool: "#f0883e",
|
||||
|
||||
modeIdle: "#3fb950",
|
||||
modeEditing: "#58a6ff",
|
||||
modeThinking: "#a371f7",
|
||||
modeToolExecution: "#d29922",
|
||||
modePermission: "#f0883e",
|
||||
|
||||
toolPending: "#8b949e",
|
||||
toolRunning: "#d29922",
|
||||
toolSuccess: "#3fb950",
|
||||
toolError: "#f85149",
|
||||
|
||||
headerGradient: ["#58a6ff", "#a371f7", "#3fb950"],
|
||||
};
|
||||
|
||||
const ROSE_PINE_COLORS: ThemeColors = {
|
||||
primary: "#c4a7e7",
|
||||
secondary: "#9ccfd8",
|
||||
accent: "#ebbcba",
|
||||
|
||||
success: "#31748f",
|
||||
error: "#eb6f92",
|
||||
warning: "#f6c177",
|
||||
info: "#9ccfd8",
|
||||
|
||||
text: "#e0def4",
|
||||
textDim: "#6e6a86",
|
||||
textMuted: "#26233a",
|
||||
|
||||
background: "#191724",
|
||||
backgroundPanel: "#1f1d2e",
|
||||
backgroundElement: "#26233a",
|
||||
|
||||
border: "#26233a",
|
||||
borderFocus: "#c4a7e7",
|
||||
borderWarning: "#f6c177",
|
||||
borderModal: "#ebbcba",
|
||||
|
||||
bgHighlight: "#21202e",
|
||||
bgCursor: "#c4a7e7",
|
||||
bgAdded: "#31748f",
|
||||
bgRemoved: "#eb6f92",
|
||||
|
||||
diffAdded: "#31748f",
|
||||
diffRemoved: "#eb6f92",
|
||||
diffContext: "#6e6a86",
|
||||
diffHeader: "#e0def4",
|
||||
diffHunk: "#9ccfd8",
|
||||
|
||||
roleUser: "#9ccfd8",
|
||||
roleAssistant: "#31748f",
|
||||
roleSystem: "#f6c177",
|
||||
roleTool: "#ebbcba",
|
||||
|
||||
modeIdle: "#31748f",
|
||||
modeEditing: "#c4a7e7",
|
||||
modeThinking: "#ebbcba",
|
||||
modeToolExecution: "#f6c177",
|
||||
modePermission: "#eb6f92",
|
||||
|
||||
toolPending: "#6e6a86",
|
||||
toolRunning: "#f6c177",
|
||||
toolSuccess: "#31748f",
|
||||
toolError: "#eb6f92",
|
||||
|
||||
headerGradient: ["#c4a7e7", "#ebbcba", "#9ccfd8"],
|
||||
};
|
||||
|
||||
const KANAGAWA_COLORS: ThemeColors = {
|
||||
primary: "#7e9cd8",
|
||||
secondary: "#7fb4ca",
|
||||
accent: "#957fb8",
|
||||
|
||||
success: "#98bb6c",
|
||||
error: "#c34043",
|
||||
warning: "#dca561",
|
||||
info: "#7fb4ca",
|
||||
|
||||
text: "#dcd7ba",
|
||||
textDim: "#727169",
|
||||
textMuted: "#363646",
|
||||
|
||||
background: "#1f1f28",
|
||||
backgroundPanel: "#181820",
|
||||
backgroundElement: "#2a2a37",
|
||||
|
||||
border: "#363646",
|
||||
borderFocus: "#7e9cd8",
|
||||
borderWarning: "#dca561",
|
||||
borderModal: "#957fb8",
|
||||
|
||||
bgHighlight: "#2a2a37",
|
||||
bgCursor: "#7e9cd8",
|
||||
bgAdded: "#76946a",
|
||||
bgRemoved: "#c34043",
|
||||
|
||||
diffAdded: "#98bb6c",
|
||||
diffRemoved: "#c34043",
|
||||
diffContext: "#727169",
|
||||
diffHeader: "#dcd7ba",
|
||||
diffHunk: "#7fb4ca",
|
||||
|
||||
roleUser: "#7fb4ca",
|
||||
roleAssistant: "#98bb6c",
|
||||
roleSystem: "#dca561",
|
||||
roleTool: "#ffa066",
|
||||
|
||||
modeIdle: "#98bb6c",
|
||||
modeEditing: "#7e9cd8",
|
||||
modeThinking: "#957fb8",
|
||||
modeToolExecution: "#dca561",
|
||||
modePermission: "#ffa066",
|
||||
|
||||
toolPending: "#727169",
|
||||
toolRunning: "#dca561",
|
||||
toolSuccess: "#98bb6c",
|
||||
toolError: "#c34043",
|
||||
|
||||
headerGradient: ["#7e9cd8", "#957fb8", "#7fb4ca"],
|
||||
};
|
||||
|
||||
const AYU_DARK_COLORS: ThemeColors = {
|
||||
primary: "#39bae6",
|
||||
secondary: "#59c2ff",
|
||||
accent: "#d2a6ff",
|
||||
|
||||
success: "#7fd962",
|
||||
error: "#f07178",
|
||||
warning: "#ffb454",
|
||||
info: "#59c2ff",
|
||||
|
||||
text: "#bfbdb6",
|
||||
textDim: "#636e78",
|
||||
textMuted: "#232834",
|
||||
|
||||
background: "#0a0e14",
|
||||
backgroundPanel: "#0d1016",
|
||||
backgroundElement: "#1a1f29",
|
||||
|
||||
border: "#232834",
|
||||
borderFocus: "#39bae6",
|
||||
borderWarning: "#ffb454",
|
||||
borderModal: "#d2a6ff",
|
||||
|
||||
bgHighlight: "#1a1f29",
|
||||
bgCursor: "#39bae6",
|
||||
bgAdded: "#7fd962",
|
||||
bgRemoved: "#f07178",
|
||||
|
||||
diffAdded: "#7fd962",
|
||||
diffRemoved: "#f07178",
|
||||
diffContext: "#636e78",
|
||||
diffHeader: "#bfbdb6",
|
||||
diffHunk: "#59c2ff",
|
||||
|
||||
roleUser: "#59c2ff",
|
||||
roleAssistant: "#7fd962",
|
||||
roleSystem: "#ffb454",
|
||||
roleTool: "#ff8f40",
|
||||
|
||||
modeIdle: "#7fd962",
|
||||
modeEditing: "#39bae6",
|
||||
modeThinking: "#d2a6ff",
|
||||
modeToolExecution: "#ffb454",
|
||||
modePermission: "#ff8f40",
|
||||
|
||||
toolPending: "#636e78",
|
||||
toolRunning: "#ffb454",
|
||||
toolSuccess: "#7fd962",
|
||||
toolError: "#f07178",
|
||||
|
||||
headerGradient: ["#39bae6", "#d2a6ff", "#7fd962"],
|
||||
};
|
||||
|
||||
const CARGDEV_CYBERPUNK_COLORS: ThemeColors = {
|
||||
primary: "#8be9fd",
|
||||
secondary: "#bd93f9",
|
||||
accent: "#ff79c6",
|
||||
|
||||
success: "#50fa7b",
|
||||
error: "#ff5555",
|
||||
warning: "#ffb86c",
|
||||
info: "#8be9fd",
|
||||
|
||||
text: "#e0e0e0",
|
||||
textDim: "#666666",
|
||||
textMuted: "#44475a",
|
||||
|
||||
background: "#0d1926",
|
||||
backgroundPanel: "#071018",
|
||||
backgroundElement: "#112233",
|
||||
|
||||
border: "#003b46",
|
||||
borderFocus: "#8be9fd",
|
||||
borderWarning: "#ffb86c",
|
||||
borderModal: "#ff79c6",
|
||||
|
||||
bgHighlight: "#112233",
|
||||
bgCursor: "#ff79c6",
|
||||
bgAdded: "#50fa7b",
|
||||
bgRemoved: "#ff5555",
|
||||
|
||||
diffAdded: "#50fa7b",
|
||||
diffRemoved: "#ff5555",
|
||||
diffContext: "#666666",
|
||||
diffHeader: "#f8f8f2",
|
||||
diffHunk: "#8be9fd",
|
||||
|
||||
roleUser: "#8be9fd",
|
||||
roleAssistant: "#50fa7b",
|
||||
roleSystem: "#ffb86c",
|
||||
roleTool: "#bd93f9",
|
||||
|
||||
modeIdle: "#50fa7b",
|
||||
modeEditing: "#8be9fd",
|
||||
modeThinking: "#ff79c6",
|
||||
modeToolExecution: "#ffb86c",
|
||||
modePermission: "#bd93f9",
|
||||
|
||||
toolPending: "#666666",
|
||||
toolRunning: "#ffb86c",
|
||||
toolSuccess: "#50fa7b",
|
||||
toolError: "#ff5555",
|
||||
|
||||
headerGradient: ["#ff79c6", "#bd93f9", "#8be9fd"],
|
||||
};
|
||||
|
||||
export const THEMES: Record<string, Theme> = {
|
||||
default: {
|
||||
name: "default",
|
||||
displayName: "Default",
|
||||
colors: DEFAULT_COLORS,
|
||||
},
|
||||
dracula: {
|
||||
name: "dracula",
|
||||
displayName: "Dracula",
|
||||
colors: DRACULA_COLORS,
|
||||
},
|
||||
nord: {
|
||||
name: "nord",
|
||||
displayName: "Nord",
|
||||
colors: NORD_COLORS,
|
||||
},
|
||||
"tokyo-night": {
|
||||
name: "tokyo-night",
|
||||
displayName: "Tokyo Night",
|
||||
colors: TOKYO_NIGHT_COLORS,
|
||||
},
|
||||
gruvbox: {
|
||||
name: "gruvbox",
|
||||
displayName: "Gruvbox",
|
||||
colors: GRUVBOX_COLORS,
|
||||
},
|
||||
monokai: {
|
||||
name: "monokai",
|
||||
displayName: "Monokai",
|
||||
colors: MONOKAI_COLORS,
|
||||
},
|
||||
catppuccin: {
|
||||
name: "catppuccin",
|
||||
displayName: "Catppuccin Mocha",
|
||||
colors: CATPPUCCIN_COLORS,
|
||||
},
|
||||
"one-dark": {
|
||||
name: "one-dark",
|
||||
displayName: "One Dark",
|
||||
colors: ONE_DARK_COLORS,
|
||||
},
|
||||
"solarized-dark": {
|
||||
name: "solarized-dark",
|
||||
displayName: "Solarized Dark",
|
||||
colors: SOLARIZED_DARK_COLORS,
|
||||
},
|
||||
"github-dark": {
|
||||
name: "github-dark",
|
||||
displayName: "GitHub Dark",
|
||||
colors: GITHUB_DARK_COLORS,
|
||||
},
|
||||
"rose-pine": {
|
||||
name: "rose-pine",
|
||||
displayName: "Rosé Pine",
|
||||
colors: ROSE_PINE_COLORS,
|
||||
},
|
||||
kanagawa: {
|
||||
name: "kanagawa",
|
||||
displayName: "Kanagawa",
|
||||
colors: KANAGAWA_COLORS,
|
||||
},
|
||||
"ayu-dark": {
|
||||
name: "ayu-dark",
|
||||
displayName: "Ayu Dark",
|
||||
colors: AYU_DARK_COLORS,
|
||||
},
|
||||
"cargdev-cyberpunk": {
|
||||
name: "cargdev-cyberpunk",
|
||||
displayName: "Cargdev Cyberpunk",
|
||||
colors: CARGDEV_CYBERPUNK_COLORS,
|
||||
},
|
||||
};
|
||||
|
||||
export const THEME_NAMES = Object.keys(THEMES);
|
||||
|
||||
export const DEFAULT_THEME = "default";
|
||||
|
||||
export const getTheme = (name: string): Theme => {
|
||||
return THEMES[name] ?? THEMES[DEFAULT_THEME];
|
||||
};
|
||||
|
||||
export const getThemeNames = (): string[] => {
|
||||
return THEME_NAMES;
|
||||
};
|
||||
50
src/constants/tips.ts
Normal file
50
src/constants/tips.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Tips and shortcuts constants for CodeTyper CLI
|
||||
*/
|
||||
|
||||
// Tips with {highlight}text{/highlight} markers
|
||||
export const TIPS = [
|
||||
"Type {highlight}@filename{/highlight} to add a file to context",
|
||||
"Use {highlight}/help{/highlight} to see all available commands",
|
||||
"Press {highlight}/clear{/highlight} to start a fresh conversation",
|
||||
"Use {highlight}--yes{/highlight} or {highlight}-y{/highlight} to auto-approve all commands",
|
||||
"Add {highlight}--verbose{/highlight} to see detailed tool execution",
|
||||
"Use {highlight}/models{/highlight} to see available models",
|
||||
"Type {highlight}/provider{/highlight} to switch LLM providers",
|
||||
"Files are automatically added to context with {highlight}@src/*.ts{/highlight} globs",
|
||||
"Use {highlight}/save{/highlight} to save your session",
|
||||
"Resume sessions with {highlight}-r{/highlight} or {highlight}--resume{/highlight}",
|
||||
"Use {highlight}-c{/highlight} to continue your last session",
|
||||
"Print mode {highlight}-p{/highlight} outputs response and exits",
|
||||
"Permission patterns like {highlight}Bash(git:*){/highlight} auto-approve commands",
|
||||
"Use {highlight}codetyper permissions ls{/highlight} to see allowed patterns",
|
||||
"Add {highlight}Bash(npm install:*){/highlight} to allow npm install globally",
|
||||
"Project settings are in {highlight}.codetyper/settings.json{/highlight}",
|
||||
"Global settings are in {highlight}~/.codetyper/settings.json{/highlight}",
|
||||
"Use {highlight}/context{/highlight} to check conversation size",
|
||||
"Use {highlight}/compact{/highlight} to reduce context size",
|
||||
"Commands like {highlight}ls{/highlight} and {highlight}cat{/highlight} are auto-approved",
|
||||
"Use {highlight}/exit{/highlight} or {highlight}/quit{/highlight} to end the session",
|
||||
"The agent can create folders with {highlight}mkdir{/highlight}",
|
||||
"The agent can install packages with {highlight}npm install{/highlight}",
|
||||
'Use {highlight}@"file with spaces"{/highlight} for files with spaces',
|
||||
"The read tool shows file content with line numbers",
|
||||
"The edit tool replaces exact text matches",
|
||||
"The write tool creates files and directories",
|
||||
"Use {highlight}/history{/highlight} to see past messages",
|
||||
"Session rules persist until you exit",
|
||||
"Project rules persist across sessions in this directory",
|
||||
"Global rules apply everywhere",
|
||||
] as const;
|
||||
|
||||
// Keyboard shortcuts
|
||||
export const SHORTCUTS = [
|
||||
{ key: "Ctrl+C", description: "Cancel current operation / Exit" },
|
||||
{ key: "/help", description: "Show help" },
|
||||
{ key: "/clear", description: "Clear conversation" },
|
||||
{ key: "/exit", description: "Exit chat" },
|
||||
{ key: "@file", description: "Add file to context" },
|
||||
] as const;
|
||||
|
||||
// Highlight regex pattern
|
||||
export const TIP_HIGHLIGHT_REGEX = /\{highlight\}(.*?)\{\/highlight\}/g;
|
||||
13
src/constants/tools.ts
Normal file
13
src/constants/tools.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Tool system constants
|
||||
*/
|
||||
|
||||
export const SCHEMA_SKIP_KEYS = ["$schema"] as const;
|
||||
|
||||
export const SCHEMA_SKIP_VALUES: Record<string, unknown> = {
|
||||
additionalProperties: false,
|
||||
} as const;
|
||||
|
||||
export type SchemaSkipKey = (typeof SCHEMA_SKIP_KEYS)[number];
|
||||
|
||||
export const TOOL_NAMES = ["read", "glob", "grep"];
|
||||
256
src/constants/tui-components.ts
Normal file
256
src/constants/tui-components.ts
Normal file
@@ -0,0 +1,256 @@
|
||||
/**
|
||||
* TUI Component Constants
|
||||
*
|
||||
* Constants used by TUI components extracted for modularity
|
||||
*/
|
||||
|
||||
import type { SelectOption, SlashCommand } from "@/types/tui";
|
||||
|
||||
// ============================================================================
|
||||
// Header Constants
|
||||
// ============================================================================
|
||||
|
||||
export const TUI_BANNER = [
|
||||
"█▀▀ █▀█ █▀▄ █▀▀ ▀█▀ █▄█ █▀█ █▀▀ █▀█",
|
||||
"█ █ █ █ █ █▀▀ █ █ █▀▀ █▀▀ █▀▄",
|
||||
"▀▀▀ ▀▀▀ ▀▀ ▀▀▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀",
|
||||
] as const;
|
||||
|
||||
export const HEADER_GRADIENT_COLORS = [
|
||||
"cyanBright",
|
||||
"cyan",
|
||||
"blueBright",
|
||||
] as const;
|
||||
|
||||
export type HeaderGradientColor = (typeof HEADER_GRADIENT_COLORS)[number];
|
||||
|
||||
// ============================================================================
|
||||
// Status Bar Mode Display Constants
|
||||
// ============================================================================
|
||||
|
||||
export type ModeDisplayConfig = {
|
||||
readonly text: string;
|
||||
readonly color: "green" | "cyan" | "magenta" | "yellow";
|
||||
};
|
||||
|
||||
export const MODE_DISPLAY_CONFIG: Record<string, ModeDisplayConfig> = {
|
||||
idle: { text: "Ready", color: "green" },
|
||||
editing: { text: "Editing", color: "cyan" },
|
||||
thinking: { text: "✻ Thinking…", color: "magenta" },
|
||||
tool_execution: { text: "✻ Running tool…", color: "yellow" },
|
||||
permission_prompt: { text: "Awaiting permission", color: "yellow" },
|
||||
command_menu: { text: "Command Menu", color: "cyan" },
|
||||
model_select: { text: "Select Model", color: "magenta" },
|
||||
agent_select: { text: "Select Agent", color: "magenta" },
|
||||
theme_select: { text: "Select Theme", color: "magenta" },
|
||||
mcp_select: { text: "MCP Servers", color: "magenta" },
|
||||
mode_select: { text: "Select Mode", color: "magenta" },
|
||||
provider_select: { text: "Select Provider", color: "magenta" },
|
||||
learning_prompt: { text: "Save Learning?", color: "cyan" },
|
||||
} as const;
|
||||
|
||||
export const DEFAULT_MODE_DISPLAY: ModeDisplayConfig = {
|
||||
text: "Ready",
|
||||
color: "green",
|
||||
} as const;
|
||||
|
||||
// ============================================================================
|
||||
// Log Panel Constants
|
||||
// ============================================================================
|
||||
|
||||
export const LOG_ENTRY_EXTRA_LINES = {
|
||||
user: 2,
|
||||
assistant: 2,
|
||||
tool: 1,
|
||||
toolWithDiff: 10,
|
||||
default: 1,
|
||||
} as const;
|
||||
|
||||
export const TOOL_STATUS_ICONS = {
|
||||
pending: "○",
|
||||
running: "◐",
|
||||
success: "✓",
|
||||
error: "✗",
|
||||
} as const;
|
||||
|
||||
export const TOOL_STATUS_COLORS = {
|
||||
pending: "gray",
|
||||
running: "yellow",
|
||||
success: "green",
|
||||
error: "red",
|
||||
} as const;
|
||||
|
||||
export type ToolStatusColor =
|
||||
(typeof TOOL_STATUS_COLORS)[keyof typeof TOOL_STATUS_COLORS];
|
||||
|
||||
export const THINKING_SPINNER_FRAMES = [
|
||||
"⠋",
|
||||
"⠙",
|
||||
"⠹",
|
||||
"⠸",
|
||||
"⠼",
|
||||
"⠴",
|
||||
"⠦",
|
||||
"⠧",
|
||||
"⠇",
|
||||
"⠏",
|
||||
] as const;
|
||||
|
||||
export const THINKING_SPINNER_INTERVAL = 80;
|
||||
|
||||
export const LOG_PANEL_RESERVED_HEIGHT = 15;
|
||||
export const LOG_PANEL_MIN_HEIGHT = 5;
|
||||
export const LOG_PANEL_DEFAULT_TERMINAL_HEIGHT = 24;
|
||||
|
||||
// ============================================================================
|
||||
// Permission Modal Constants
|
||||
// ============================================================================
|
||||
|
||||
export const PERMISSION_OPTIONS: SelectOption[] = [
|
||||
{
|
||||
key: "y",
|
||||
label: "Yes (once)",
|
||||
value: "once",
|
||||
description: "Allow this command only",
|
||||
},
|
||||
{
|
||||
key: "s",
|
||||
label: "Yes (session)",
|
||||
value: "session",
|
||||
description: "Allow pattern for this session",
|
||||
},
|
||||
{
|
||||
key: "l",
|
||||
label: "Yes (project)",
|
||||
value: "local",
|
||||
description: "Allow pattern for this project",
|
||||
},
|
||||
{
|
||||
key: "g",
|
||||
label: "Yes (global)",
|
||||
value: "global",
|
||||
description: "Allow pattern everywhere",
|
||||
},
|
||||
{
|
||||
key: "n",
|
||||
label: "No",
|
||||
value: "deny",
|
||||
description: "Deny this command",
|
||||
},
|
||||
];
|
||||
|
||||
export const PERMISSION_TYPE_LABELS = {
|
||||
bash: "Execute command",
|
||||
read: "Read file",
|
||||
write: "Write file",
|
||||
edit: "Edit file",
|
||||
} as const;
|
||||
|
||||
// ============================================================================
|
||||
// Command Menu Constants
|
||||
// ============================================================================
|
||||
|
||||
export const SLASH_COMMANDS: SlashCommand[] = [
|
||||
// General commands
|
||||
{ name: "help", description: "Show available commands", category: "general" },
|
||||
{
|
||||
name: "clear",
|
||||
description: "Clear conversation history",
|
||||
category: "general",
|
||||
},
|
||||
{ name: "exit", description: "Exit the chat", category: "general" },
|
||||
|
||||
// Session commands
|
||||
{ name: "save", description: "Save current session", category: "session" },
|
||||
{
|
||||
name: "context",
|
||||
description: "Show context information",
|
||||
category: "session",
|
||||
},
|
||||
{
|
||||
name: "usage",
|
||||
description: "Show token usage statistics",
|
||||
category: "session",
|
||||
},
|
||||
{
|
||||
name: "remember",
|
||||
description: "Save a learning about the project",
|
||||
category: "session",
|
||||
},
|
||||
{
|
||||
name: "learnings",
|
||||
description: "Show saved learnings",
|
||||
category: "session",
|
||||
},
|
||||
|
||||
// Settings commands
|
||||
{ name: "model", description: "Select AI model", category: "settings" },
|
||||
{ name: "agent", description: "Select agent", category: "settings" },
|
||||
{ name: "mode", description: "Switch interaction mode", category: "settings" },
|
||||
{
|
||||
name: "provider",
|
||||
description: "Switch LLM provider",
|
||||
category: "settings",
|
||||
},
|
||||
{
|
||||
name: "status",
|
||||
description: "Show provider status",
|
||||
category: "settings",
|
||||
},
|
||||
{ name: "theme", description: "Change color theme", category: "settings" },
|
||||
{ name: "mcp", description: "Manage MCP servers", category: "settings" },
|
||||
|
||||
// Account commands
|
||||
{
|
||||
name: "whoami",
|
||||
description: "Show logged in account",
|
||||
category: "account",
|
||||
},
|
||||
{
|
||||
name: "login",
|
||||
description: "Authenticate with provider",
|
||||
category: "account",
|
||||
},
|
||||
{
|
||||
name: "logout",
|
||||
description: "Sign out from provider",
|
||||
category: "account",
|
||||
},
|
||||
];
|
||||
|
||||
export const COMMAND_CATEGORIES = [
|
||||
"general",
|
||||
"session",
|
||||
"settings",
|
||||
"account",
|
||||
] as const;
|
||||
|
||||
export type CommandCategory = (typeof COMMAND_CATEGORIES)[number];
|
||||
|
||||
// ============================================================================
|
||||
// Learning Modal Constants
|
||||
// ============================================================================
|
||||
|
||||
export const LEARNING_OPTIONS: SelectOption[] = [
|
||||
{
|
||||
key: "y",
|
||||
label: "Yes (project)",
|
||||
value: "local",
|
||||
description: "Save for this project",
|
||||
},
|
||||
{
|
||||
key: "g",
|
||||
label: "Yes (global)",
|
||||
value: "global",
|
||||
description: "Save for all projects",
|
||||
},
|
||||
{
|
||||
key: "n",
|
||||
label: "No",
|
||||
value: "skip",
|
||||
description: "Skip this learning",
|
||||
},
|
||||
];
|
||||
|
||||
export const LEARNING_CONTENT_MAX_LENGTH = 100;
|
||||
export const LEARNING_TRUNCATION_SUFFIX = "...";
|
||||
41
src/constants/ui.ts
Normal file
41
src/constants/ui.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* UI Constants
|
||||
*/
|
||||
|
||||
// Keyboard hints displayed in status bar
|
||||
export const STATUS_HINTS = {
|
||||
INTERRUPT: "ctrl+c to interrupt",
|
||||
INTERRUPT_CONFIRM: "ctrl+c again to confirm",
|
||||
TOGGLE_TODOS: "ctrl+t to hide todos",
|
||||
TOGGLE_TODOS_SHOW: "ctrl+t to show todos",
|
||||
} as const;
|
||||
|
||||
// Time formatting
|
||||
export const TIME_UNITS = {
|
||||
SECOND: 1000,
|
||||
MINUTE: 60 * 1000,
|
||||
HOUR: 60 * 60 * 1000,
|
||||
} as const;
|
||||
|
||||
// Token display formatting
|
||||
export const TOKEN_DISPLAY = {
|
||||
K_THRESHOLD: 1000,
|
||||
DECIMALS: 1,
|
||||
} as const;
|
||||
|
||||
// Status bar separator
|
||||
export const STATUS_SEPARATOR = " · ";
|
||||
|
||||
// Interrupt timeout (ms) - time before interrupt pending resets
|
||||
export const INTERRUPT_TIMEOUT = 2000;
|
||||
|
||||
// Terminal escape sequences for fullscreen mode
|
||||
export const TERMINAL_SEQUENCES = {
|
||||
ENTER_ALTERNATE_SCREEN: "\x1b[?1049h",
|
||||
LEAVE_ALTERNATE_SCREEN: "\x1b[?1049l",
|
||||
CLEAR_SCREEN: "\x1b[2J",
|
||||
CLEAR_SCROLLBACK: "\x1b[3J",
|
||||
CURSOR_HOME: "\x1b[H",
|
||||
HIDE_CURSOR: "\x1b[?25l",
|
||||
SHOW_CURSOR: "\x1b[?25h",
|
||||
} as const;
|
||||
11
src/constants/view.ts
Normal file
11
src/constants/view.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* View tool constants
|
||||
*/
|
||||
|
||||
export const VIEW_MESSAGES = {
|
||||
FAILED: (error: unknown) => `Failed to read file: ${error}`,
|
||||
} as const;
|
||||
|
||||
export const VIEW_DEFAULTS = {
|
||||
START_LINE: 1,
|
||||
} as const;
|
||||
24
src/constants/write.ts
Normal file
24
src/constants/write.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Write tool constants
|
||||
*/
|
||||
|
||||
export const WRITE_MESSAGES = {
|
||||
PERMISSION_DENIED: "Permission denied by user",
|
||||
} as const;
|
||||
|
||||
export const WRITE_TITLES = {
|
||||
CANCELLED: (path: string) => `Write cancelled: ${path}`,
|
||||
FAILED: (path: string) => `Write failed: ${path}`,
|
||||
WRITING: (name: string) => `Writing ${name}`,
|
||||
OVERWROTE: (path: string) => `Overwrote: ${path}`,
|
||||
CREATED: (path: string) => `Created: ${path}`,
|
||||
OVERWRITE_DESC: (path: string) => `Overwrite file: ${path}`,
|
||||
CREATE_DESC: (path: string) => `Create file: ${path}`,
|
||||
} as const;
|
||||
|
||||
export const WRITE_DESCRIPTION = `Write content to a file. Creates the file if it doesn't exist, or overwrites if it does.
|
||||
|
||||
Guidelines:
|
||||
- Use absolute paths
|
||||
- Parent directories will be created automatically
|
||||
- Requires user approval for file writes`;
|
||||
Reference in New Issue
Block a user