clean code

This commit is contained in:
CrazyBoyM 2025-09-18 17:20:19 +08:00
parent 59dce97350
commit 61a8ce0d22
26 changed files with 93 additions and 91 deletions

View File

@ -1,6 +1,6 @@
# AGENTS.md # AGENTS.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. This file provides guidance to Kode automation agents (including those compatible with Claude Code's `.claude` ecosystem) when working with code in this repository.
## Development Commands ## Development Commands
@ -46,7 +46,7 @@ SKIP_BUNDLED_CHECK=true npm publish
## High-Level Architecture ## High-Level Architecture
### Core System Design ### Core System Design
Kode implements a **three-layer parallel architecture** inspired by Claude Code: Kode implements a **three-layer parallel architecture** refined for fast iteration across terminal workflows while remaining compatible with the Claude Code agent ecosystem:
1. **User Interaction Layer** (`src/screens/REPL.tsx`) 1. **User Interaction Layer** (`src/screens/REPL.tsx`)
- Interactive terminal interface using Ink (React for CLI) - Interactive terminal interface using Ink (React for CLI)
@ -74,9 +74,9 @@ Kode implements a **three-layer parallel architecture** inspired by Claude Code:
### Agent System (`src/utils/agentLoader.ts`) ### Agent System (`src/utils/agentLoader.ts`)
**Dynamic Agent Configuration Loading** with 5-tier priority system: **Dynamic Agent Configuration Loading** with 5-tier priority system:
1. Built-in (code-embedded) 1. Built-in (code-embedded)
2. `~/.claude/agents/` (Claude user) 2. `~/.claude/agents/` (Claude Code user directory compatibility)
3. `~/.kode/agents/` (Kode user) 3. `~/.kode/agents/` (Kode user)
4. `./.claude/agents/` (Claude project) 4. `./.claude/agents/` (Claude Code project directory compatibility)
5. `./.kode/agents/` (Kode project) 5. `./.kode/agents/` (Kode project)
Agents are defined as markdown files with YAML frontmatter: Agents are defined as markdown files with YAML frontmatter:
@ -99,7 +99,7 @@ Each tool follows a consistent pattern in `src/tools/[ToolName]/`:
- Permission-aware execution - Permission-aware execution
### Service Layer ### Service Layer
- **Claude Service** (`src/services/claude.ts`): Primary AI model interface - **Anthropic Service** (`src/services/claude.ts`): Claude API integration
- **OpenAI Service** (`src/services/openai.ts`): OpenAI-compatible models - **OpenAI Service** (`src/services/openai.ts`): OpenAI-compatible models
- **Model Adapter Factory** (`src/services/modelAdapterFactory.ts`): Unified model interface - **Model Adapter Factory** (`src/services/modelAdapterFactory.ts`): Unified model interface
- **MCP Client** (`src/services/mcpClient.ts`): Model Context Protocol for tool extensions - **MCP Client** (`src/services/mcpClient.ts`): Model Context Protocol for tool extensions
@ -204,4 +204,4 @@ const description = typeof tool.description === 'function'
1. Create `.md` file with proper YAML frontmatter 1. Create `.md` file with proper YAML frontmatter
2. Place in appropriate directory based on scope 2. Place in appropriate directory based on scope
3. Test with `/agents` command 3. Test with `/agents` command
4. Verify tool permissions work correctly 4. Verify tool permissions work correctly

View File

@ -1,6 +1,6 @@
# CLAUDE.md # CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. This file provides guidance to Kode automation agents (including those compatible with Claude Code's `.claude` ecosystem) when working with code in this repository.
## Development Commands ## Development Commands
@ -46,7 +46,7 @@ SKIP_BUNDLED_CHECK=true npm publish
## High-Level Architecture ## High-Level Architecture
### Core System Design ### Core System Design
Kode implements a **three-layer parallel architecture** inspired by Claude Code: Kode implements a **three-layer parallel architecture** refined for fast iteration across terminal workflows while remaining compatible with the Claude Code agent ecosystem:
1. **User Interaction Layer** (`src/screens/REPL.tsx`) 1. **User Interaction Layer** (`src/screens/REPL.tsx`)
- Interactive terminal interface using Ink (React for CLI) - Interactive terminal interface using Ink (React for CLI)
@ -74,9 +74,9 @@ Kode implements a **three-layer parallel architecture** inspired by Claude Code:
### Agent System (`src/utils/agentLoader.ts`) ### Agent System (`src/utils/agentLoader.ts`)
**Dynamic Agent Configuration Loading** with 5-tier priority system: **Dynamic Agent Configuration Loading** with 5-tier priority system:
1. Built-in (code-embedded) 1. Built-in (code-embedded)
2. `~/.claude/agents/` (Claude user) 2. `~/.claude/agents/` (Claude Code user directory compatibility)
3. `~/.kode/agents/` (Kode user) 3. `~/.kode/agents/` (Kode user)
4. `./.claude/agents/` (Claude project) 4. `./.claude/agents/` (Claude Code project directory compatibility)
5. `./.kode/agents/` (Kode project) 5. `./.kode/agents/` (Kode project)
Agents are defined as markdown files with YAML frontmatter: Agents are defined as markdown files with YAML frontmatter:
@ -99,7 +99,7 @@ Each tool follows a consistent pattern in `src/tools/[ToolName]/`:
- Permission-aware execution - Permission-aware execution
### Service Layer ### Service Layer
- **Claude Service** (`src/services/claude.ts`): Primary AI model interface - **Anthropic Service** (`src/services/claude.ts`): Claude API integration
- **OpenAI Service** (`src/services/openai.ts`): OpenAI-compatible models - **OpenAI Service** (`src/services/openai.ts`): OpenAI-compatible models
- **Model Adapter Factory** (`src/services/modelAdapterFactory.ts`): Unified model interface - **Model Adapter Factory** (`src/services/modelAdapterFactory.ts`): Unified model interface
- **MCP Client** (`src/services/mcpClient.ts`): Model Context Protocol for tool extensions - **MCP Client** (`src/services/mcpClient.ts`): Model Context Protocol for tool extensions
@ -204,4 +204,4 @@ const description = typeof tool.description === 'function'
1. Create `.md` file with proper YAML frontmatter 1. Create `.md` file with proper YAML frontmatter
2. Place in appropriate directory based on scope 2. Place in appropriate directory based on scope
3. Test with `/agents` command 3. Test with `/agents` command
4. Verify tool permissions work correctly 4. Verify tool permissions work correctly

View File

@ -30,17 +30,17 @@ This change reflects our belief that the future of software development is colla
### Full Compatibility with Multiple Standards ### Full Compatibility with Multiple Standards
- ✅ **AGENTS.md** - Native support for the OpenAI-initiated standard format - ✅ **AGENTS.md** - Native support for the OpenAI-initiated standard format
- ✅ **CLAUDE.md** - Full backward compatibility with Claude Code configurations - ✅ **CLAUDE.md** - Full backward compatibility with Claude Code `.claude` configurations
- ✅ **Subagent System** - Advanced agent delegation and task orchestration - ✅ **Subagent System** - Advanced agent delegation and task orchestration
- ✅ **Cross-platform** - Works with 20+ AI models and providers - ✅ **Cross-platform** - Works with 20+ AI models and providers
Use `# Your documentation request` to generate and maintain your AGENTS.md file automatically, while maintaining full compatibility with existing Claude Code workflows. Use `# Your documentation request` to generate and maintain your AGENTS.md file automatically, while preserving compatibility with existing `.claude` workflows.
## Overview ## Overview
Kode is a powerful AI assistant that lives in your terminal. It can understand your codebase, edit files, run commands, and handle entire workflows for you. Kode is a powerful AI assistant that lives in your terminal. It can understand your codebase, edit files, run commands, and handle entire workflows for you.
> **⚠️ Security Notice**: Kode runs in YOLO mode by default (equivalent to Claude's `--dangerously-skip-permissions` flag), bypassing all permission checks for maximum productivity. YOLO mode is recommended only for trusted, secure environments when working on non-critical projects. If you're working with important files or using models of questionable capability, we strongly recommend using `kode --safe` to enable permission checks and manual approval for all operations. > **⚠️ Security Notice**: Kode runs in YOLO mode by default (equivalent to Claude Code's `--dangerously-skip-permissions` flag), bypassing all permission checks for maximum productivity. YOLO mode is recommended only for trusted, secure environments when working on non-critical projects. If you're working with important files or using models of questionable capability, we strongly recommend using `kode --safe` to enable permission checks and manual approval for all operations.
> >
> **📊 Model Performance**: For optimal performance, we recommend using newer, more capable models designed for autonomous task completion. Avoid older Q&A-focused models like GPT-4o or Gemini 2.5 Pro, which are optimized for answering questions rather than sustained independent task execution. Choose models specifically trained for agentic workflows and extended reasoning capabilities. > **📊 Model Performance**: For optimal performance, we recommend using newer, more capable models designed for autonomous task completion. Avoid older Q&A-focused models like GPT-4o or Gemini 2.5 Pro, which are optimized for answering questions rather than sustained independent task execution. Choose models specifically trained for agentic workflows and extended reasoning capabilities.

View File

@ -23,7 +23,7 @@
Kode 是一个强大的 AI 助手,运行在你的终端中。它能理解你的代码库、编辑文件、运行命令,并为你处理整个开发工作流。 Kode 是一个强大的 AI 助手,运行在你的终端中。它能理解你的代码库、编辑文件、运行命令,并为你处理整个开发工作流。
> **⚠️ 安全提示**Kode 默认以 YOLO 模式运行(等同于 Claude 的 `--dangerously-skip-permissions` 标志跳过所有权限检查以获得最大生产力。YOLO 模式仅建议在安全可信的环境中处理非重要项目时使用。如果您正在处理重要文件或使用能力存疑的模型,我们强烈建议使用 `kode --safe` 启用权限检查和手动审批所有操作。 > **⚠️ 安全提示**Kode 默认以 YOLO 模式运行(等同于 Claude Code `--dangerously-skip-permissions` 标志跳过所有权限检查以获得最大生产力。YOLO 模式仅建议在安全可信的环境中处理非重要项目时使用。如果您正在处理重要文件或使用能力存疑的模型,我们强烈建议使用 `kode --safe` 启用权限检查和手动审批所有操作。
> >
> **📊 模型性能建议**:为获得最佳体验,建议使用专为自主任务完成设计的新一代强大模型。避免使用 GPT-4o、Gemini 2.5 Pro 等较老的问答型模型,它们主要针对回答问题进行优化,而非持续的独立任务执行。请选择专门训练用于智能体工作流和扩展推理能力的模型。 > **📊 模型性能建议**:为获得最佳体验,建议使用专为自主任务完成设计的新一代强大模型。避免使用 GPT-4o、Gemini 2.5 Pro 等较老的问答型模型,它们主要针对回答问题进行优化,而非持续的独立任务执行。请选择专门训练用于智能体工作流和扩展推理能力的模型。

View File

@ -74,8 +74,8 @@ Agents can be defined at five levels with priority order (later overrides earlie
- Provided with Kode - Provided with Kode
- Cannot be modified - Cannot be modified
2. **Claude User** (`~/.claude/agents/`) 2. **.claude User (Claude Code)** (`~/.claude/agents/`)
- Claude Code compatible user-level agents - Compatibility with Claude Code user directories
- Personal agents available across all projects - Personal agents available across all projects
3. **Kode User** (`~/.kode/agents/`) 3. **Kode User** (`~/.kode/agents/`)
@ -83,8 +83,8 @@ Agents can be defined at five levels with priority order (later overrides earlie
- Overrides Claude user agents with same name - Overrides Claude user agents with same name
- Create with `/agents` command or manually - Create with `/agents` command or manually
4. **Claude Project** (`./.claude/agents/`) 4. **.claude Project (Claude Code)** (`./.claude/agents/`)
- Claude Code compatible project-specific agents - Compatibility with Claude Code project directories
- Overrides user-level agents - Overrides user-level agents
5. **Kode Project** (`./.kode/agents/`) 5. **Kode Project** (`./.kode/agents/`)
@ -227,4 +227,4 @@ Planned improvements:
- Performance metrics per agent - Performance metrics per agent
- Agent composition (agents using other agents) - Agent composition (agents using other agents)
- Cloud-based agent sharing - Cloud-based agent sharing
- Agent versioning and rollback - Agent versioning and rollback

View File

@ -20,7 +20,7 @@ import { randomUUID } from 'crypto'
const execAsync = promisify(exec) const execAsync = promisify(exec)
// Core constants aligned with Claude Code architecture // Core constants aligned with the Claude Code agent architecture
const AGENT_LOCATIONS = { const AGENT_LOCATIONS = {
USER: "user", USER: "user",
PROJECT: "project", PROJECT: "project",
@ -324,7 +324,7 @@ function validateAgentConfig(config: Partial<CreateState>, existingAgents: Agent
} }
} }
// File system operations with Claude Code alignment // File system operations retained for Claude Code parity
function getAgentDirectory(location: AgentLocation): string { function getAgentDirectory(location: AgentLocation): string {
if (location === AGENT_LOCATIONS.BUILT_IN || location === AGENT_LOCATIONS.ALL) { if (location === AGENT_LOCATIONS.BUILT_IN || location === AGENT_LOCATIONS.ALL) {
throw new Error(`Cannot get directory path for ${location} agents`) throw new Error(`Cannot get directory path for ${location} agents`)
@ -545,7 +545,7 @@ async function updateAgent(
writeFileSync(filePath, content, { encoding: 'utf-8', flag: 'w' }) writeFileSync(filePath, content, { encoding: 'utf-8', flag: 'w' })
} }
// Enhanced UI Components with Claude Code alignment // Enhanced UI components retained for Claude Code parity
interface HeaderProps { interface HeaderProps {
title: string title: string
@ -1574,7 +1574,7 @@ function AgentListView({
<Box marginBottom={1}> <Box marginBottom={1}>
<Text bold color={theme.primary}>💭 What are agents?</Text> <Text bold color={theme.primary}>💭 What are agents?</Text>
</Box> </Box>
<Text>Specialized AI assistants that Claude can delegate to for specific tasks.</Text> <Text>Specialized AI assistants that Kode can delegate to for specific tasks, compatible with Claude Code `.claude` agent packs.</Text>
<Text>Each agent has its own context, prompt, and tools.</Text> <Text>Each agent has its own context, prompt, and tools.</Text>
<Box marginTop={1} marginBottom={1}> <Box marginTop={1} marginBottom={1}>

View File

@ -1,5 +1,5 @@
import type { Command } from '../commands' import type { Command } from '../commands'
import { markProjectOnboardingComplete } from '../ProjectOnboarding' import { markProjectOnboardingComplete } from '../components/ProjectOnboarding'
import { PROJECT_FILE } from '../constants/product' import { PROJECT_FILE } from '../constants/product'
const command = { const command = {
type: 'prompt', type: 'prompt',

View File

@ -5,7 +5,7 @@ import chalk from 'chalk'
import { getTheme } from '../utils/theme' import { getTheme } from '../utils/theme'
import { env } from '../utils/env' import { env } from '../utils/env'
import { getGlobalConfig, saveGlobalConfig } from '../utils/config' import { getGlobalConfig, saveGlobalConfig } from '../utils/config'
import { markProjectOnboardingComplete } from '../ProjectOnboarding' import { markProjectOnboardingComplete } from '../components/ProjectOnboarding'
import { readFileSync, writeFileSync } from 'fs' import { readFileSync, writeFileSync } from 'fs'
import { join } from 'path' import { join } from 'path'
import { safeParseJSON } from '../utils/json' import { safeParseJSON } from '../utils/json'

View File

@ -175,10 +175,10 @@ export function Help({
Custom commands loaded from: Custom commands loaded from:
</Text> </Text>
<Text color={theme.secondaryText}> <Text color={theme.secondaryText}>
{getCustomCommandDirectories().userClaude} (user: prefix) {getCustomCommandDirectories().userClaude} (Claude `.claude` user scope)
</Text> </Text>
<Text color={theme.secondaryText}> <Text color={theme.secondaryText}>
{getCustomCommandDirectories().projectClaude} (project: prefix) {getCustomCommandDirectories().projectClaude} (Claude `.claude` project scope)
</Text> </Text>
<Text color={theme.secondaryText}> <Text color={theme.secondaryText}>
Use /refresh-commands to reload after changes Use /refresh-commands to reload after changes
@ -190,10 +190,10 @@ export function Help({
Create custom commands by adding .md files to: Create custom commands by adding .md files to:
</Text> </Text>
<Text color={theme.secondaryText}> <Text color={theme.secondaryText}>
{getCustomCommandDirectories().userClaude} (user: prefix) {getCustomCommandDirectories().userClaude} (Claude `.claude` user scope)
</Text> </Text>
<Text color={theme.secondaryText}> <Text color={theme.secondaryText}>
{getCustomCommandDirectories().projectClaude} (project: prefix) {getCustomCommandDirectories().projectClaude} (Claude `.claude` project scope)
</Text> </Text>
<Text color={theme.secondaryText}> <Text color={theme.secondaryText}>
Use /refresh-commands to reload after creation Use /refresh-commands to reload after creation

View File

@ -18,7 +18,7 @@ interface InvalidConfigDialogProps {
} }
/** /**
* Dialog shown when the Claude config file contains invalid JSON * Dialog shown when the Kode config file contains invalid JSON
*/ */
function InvalidConfigDialog({ function InvalidConfigDialog({
filePath, filePath,

View File

@ -6,17 +6,17 @@ import {
getGlobalConfig, getGlobalConfig,
saveCurrentProjectConfig, saveCurrentProjectConfig,
saveGlobalConfig, saveGlobalConfig,
} from './utils/config.js' } from '../utils/config.js'
import { existsSync } from 'fs' import { existsSync } from 'fs'
import { join } from 'path' import { join } from 'path'
import { homedir } from 'os' import { homedir } from 'os'
import terminalSetup from './commands/terminalSetup' import terminalSetup from '../commands/terminalSetup'
import { getTheme } from './utils/theme' import { getTheme } from '../utils/theme'
import { RELEASE_NOTES } from './constants/releaseNotes' import { RELEASE_NOTES } from '../constants/releaseNotes'
import { gt } from 'semver' import { gt } from 'semver'
import { isDirEmpty } from './utils/file' import { isDirEmpty } from '../utils/file'
import { MACRO } from './constants/macros' import { MACRO } from '../constants/macros'
import { PROJECT_FILE, PRODUCT_NAME } from './constants/product' import { PROJECT_FILE, PRODUCT_NAME } from '../constants/product'
// Function to mark onboarding as complete // Function to mark onboarding as complete
export function markProjectOnboardingComplete(): void { export function markProjectOnboardingComplete(): void {
@ -74,9 +74,9 @@ export default function ProjectOnboarding({
// Load what we need for onboarding // Load what we need for onboarding
// NOTE: This whole component is statically rendered Once // NOTE: This whole component is statically rendered Once
const hasClaudeMd = existsSync(join(workspaceDir, PROJECT_FILE)) const workspaceHasProjectGuide = existsSync(join(workspaceDir, PROJECT_FILE))
const isWorkspaceDirEmpty = isDirEmpty(workspaceDir) const isWorkspaceDirEmpty = isDirEmpty(workspaceDir)
const needsClaudeMd = !hasClaudeMd && !isWorkspaceDirEmpty const shouldRecommendProjectGuide = !workspaceHasProjectGuide && !isWorkspaceDirEmpty
const showTerminalTip = const showTerminalTip =
terminalSetup.isEnabled && !getGlobalConfig().shiftEnterKeyBindingInstalled terminalSetup.isEnabled && !getGlobalConfig().shiftEnterKeyBindingInstalled
@ -106,9 +106,9 @@ export default function ProjectOnboarding({
</React.Fragment>, </React.Fragment>,
) )
} }
if (needsClaudeMd) { if (shouldRecommendProjectGuide) {
items.push( items.push(
<React.Fragment key="claudemd"> <React.Fragment key="projectGuide">
{/* @ts-expect-error - OrderedList.Item children prop issue */} {/* @ts-expect-error - OrderedList.Item children prop issue */}
<OrderedList.Item> <OrderedList.Item>
<Text color={theme.secondaryText}> <Text color={theme.secondaryText}>

View File

@ -308,7 +308,7 @@ function PromptInput({
addToHistory(mode === 'koding' ? `#${input}` : input) addToHistory(mode === 'koding' ? `#${input}` : input)
onInputChange('') onInputChange('')
// Create additional context to inform Claude this is for KODING.md // Create additional context to inform the assistant this is for KODING.md
const kodingContext = const kodingContext =
'The user is using Koding mode. Format your response as a comprehensive, well-structured document suitable for adding to AGENTS.md. Use proper markdown formatting with headings, lists, code blocks, etc. The response should be complete and ready to add to AGENTS.md documentation.' 'The user is using Koding mode. Format your response as a comprehensive, well-structured document suitable for adding to AGENTS.md. Use proper markdown formatting with headings, lists, code blocks, etc. The response should be complete and ready to add to AGENTS.md documentation.'
@ -354,8 +354,8 @@ function PromptInput({
if (messages.length) { if (messages.length) {
await onQuery(messages) await onQuery(messages)
// After query completes, the last message should be Claude's response // After query completes, the last message should be the assistant's response
// We'll set up a one-time listener to capture and save Claude's response // We'll set up a one-time listener to capture and save that response
// This will be handled by the REPL component or message handler // This will be handled by the REPL component or message handler
} }
@ -524,7 +524,7 @@ function PromptInput({
onShowMessageSelector() onShowMessageSelector()
} }
// Shift+Tab for mode cycling (matching original Claude Code implementation) // Shift+Tab for mode cycling (retains legacy keyboard behavior)
if (key.shift && key.tab) { if (key.shift && key.tab) {
cycleMode() cycleMode()
return true // Explicitly handled return true // Explicitly handled

View File

@ -74,7 +74,7 @@ export function AssistantTextMessage({
} }
switch (text) { switch (text) {
// Local JSX commands don't need a response, but we still want Claude to see them // Local JSX commands don't need a response, but we still want the assistant to see them
// Tool results render their own interrupt messages // Tool results render their own interrupt messages
case NO_RESPONSE_REQUESTED: case NO_RESPONSE_REQUESTED:
case INTERRUPT_MESSAGE_FOR_TOOL_USE: case INTERRUPT_MESSAGE_FOR_TOOL_USE:

View File

@ -5,7 +5,7 @@ const pkg = require('../../package.json')
export const MACRO = { export const MACRO = {
VERSION: pkg.version, VERSION: pkg.version,
README_URL: 'https://docs.anthropic.com/s/claude-code', README_URL: 'https://github.com/shareAI-lab/kode#readme',
PACKAGE_URL: '@shareai-lab/kode', PACKAGE_URL: '@shareai-lab/kode',
ISSUES_EXPLAINER: 'report the issue at https://github.com/shareAI-lab/kode/issues', ISSUES_EXPLAINER: 'report the issue at https://github.com/shareAI-lab/kode/issues',
} }

View File

@ -19,7 +19,8 @@ import { lastX } from './utils/generators'
import { getGitEmail } from './utils/user' import { getGitEmail } from './utils/user'
import { PROJECT_FILE } from './constants/product' import { PROJECT_FILE } from './constants/product'
/** /**
* Find all AGENTS.md and CLAUDE.md files in the current working directory * Locate AGENTS.md and CLAUDE.md files for backward compatibility with
* existing documentation workflows.
*/ */
export async function getClaudeFiles(): Promise<string | null> { export async function getClaudeFiles(): Promise<string | null> {
const abortController = new AbortController() const abortController = new AbortController()

View File

@ -377,7 +377,6 @@ ${commandList}`,
), ),
getClients(), getClients(),
]) ])
// logStartup()
const inputPrompt = [prompt, stdinContent].filter(Boolean).join('\n') const inputPrompt = [prompt, stdinContent].filter(Boolean).join('\n')
if (print) { if (print) {
if (!inputPrompt) { if (!inputPrompt) {
@ -1291,7 +1290,6 @@ ${commandList}`,
loadLogList(CACHE_PATHS.messages()), loadLogList(CACHE_PATHS.messages()),
getClients(), getClients(),
]) ])
// logStartup()
// If a specific conversation is requested, load and resume it directly // If a specific conversation is requested, load and resume it directly
if (identifier !== undefined) { if (identifier !== undefined) {
@ -1393,7 +1391,7 @@ ${commandList}`,
})() })()
}) })
// claude context (TODO: deprecate) // legacy context (TODO: deprecate)
const context = program const context = program
.command('context') .command('context')
.description( .description(

View File

@ -2,7 +2,7 @@ import { ToolUseBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'
import { Box, Newline, Static, Text } from 'ink' import { Box, Newline, Static, Text } from 'ink'
import ProjectOnboarding, { import ProjectOnboarding, {
markProjectOnboardingComplete, markProjectOnboardingComplete,
} from '../ProjectOnboarding.js' } from '../components/ProjectOnboarding.js'
import { CostThresholdDialog } from '../components/CostThresholdDialog' import { CostThresholdDialog } from '../components/CostThresholdDialog'
import * as React from 'react' import * as React from 'react'
import { useEffect, useMemo, useRef, useState, useCallback } from 'react' import { useEffect, useMemo, useRef, useState, useCallback } from 'react'
@ -337,7 +337,7 @@ export function REPL({
setMessages(oldMessages => [...oldMessages, ...newMessages]) setMessages(oldMessages => [...oldMessages, ...newMessages])
// Mark onboarding as complete when any user message is sent to Claude // Mark onboarding as complete when any user message is sent to the assistant
markProjectOnboardingComplete() markProjectOnboardingComplete()
// The last message is an assistant message if the user input was a bash command, // The last message is an assistant message if the user input was a bash command,

View File

@ -148,9 +148,9 @@ class KodeContextManager {
// 在调试模式下记录加载结果 // 在调试模式下记录加载结果
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
console.log( debugLogger.info('KODE_CONTEXT_LOADED', {
`[KodeContext] Loaded ${this.projectDocsCache.length} characters from project docs`, characters: this.projectDocsCache.length,
) })
} }
} catch (error) { } catch (error) {
console.warn('[KodeContext] Failed to load project docs:', error) console.warn('[KodeContext] Failed to load project docs:', error)
@ -1212,7 +1212,7 @@ export function formatSystemPromptWithContext(
agentId?: string, agentId?: string,
skipContextReminders = false, // Parameter kept for API compatibility but not used anymore skipContextReminders = false, // Parameter kept for API compatibility but not used anymore
): { systemPrompt: string[]; reminders: string } { ): { systemPrompt: string[]; reminders: string } {
// 构建增强的系统提示 - 对齐官方 Claude Code 直接注入方式 // 构建增强的系统提示,保持与原先直接注入方式的兼容
const enhancedPrompt = [...systemPrompt] const enhancedPrompt = [...systemPrompt]
let reminders = '' let reminders = ''
@ -1759,7 +1759,10 @@ function getAssistantMessageFromError(error: unknown): AssistantMessage {
} }
if (error instanceof Error) { if (error instanceof Error) {
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
console.log(error) debugLogger.error('ANTHROPIC_API_ERROR', {
message: error.message,
stack: error.stack,
})
} }
return createAssistantAPIErrorMessage( return createAssistantAPIErrorMessage(
`${API_ERROR_MESSAGE_PREFIX}: ${error.message}`, `${API_ERROR_MESSAGE_PREFIX}: ${error.message}`,

View File

@ -136,7 +136,6 @@ export async function resolveFileReferences(content: string): Promise<string> {
function validateAllowedTools(allowedTools: string[] | undefined): boolean { function validateAllowedTools(allowedTools: string[] | undefined): boolean {
// Log allowed tools for debugging and future integration // Log allowed tools for debugging and future integration
if (allowedTools && allowedTools.length > 0) { if (allowedTools && allowedTools.length > 0) {
console.log('Command allowed tools:', allowedTools)
// TODO: Integrate with src/permissions.ts tool permission system // TODO: Integrate with src/permissions.ts tool permission system
// TODO: Connect to Tool.tsx needsPermissions() mechanism // TODO: Connect to Tool.tsx needsPermissions() mechanism
} }
@ -147,8 +146,8 @@ function validateAllowedTools(allowedTools: string[] | undefined): boolean {
* Frontmatter configuration for custom commands * Frontmatter configuration for custom commands
* *
* This interface defines the YAML frontmatter structure that can be used * This interface defines the YAML frontmatter structure that can be used
* to configure custom commands. It follows the same pattern as Claude Desktop's * to configure custom commands. It mirrors the Claude Desktop custom command
* custom command system but with additional fields for enhanced functionality. * system for compatibility while adding Kode-specific enhancements.
*/ */
export interface CustomCommandFrontmatter { export interface CustomCommandFrontmatter {
/** Display name for the command (overrides filename-based naming) */ /** Display name for the command (overrides filename-based naming) */
@ -436,10 +435,10 @@ function createCustomCommand(
async getPromptForCommand(args: string): Promise<MessageParam[]> { async getPromptForCommand(args: string): Promise<MessageParam[]> {
let prompt = content.trim() let prompt = content.trim()
// Process argument substitution following Claude Code conventions // Process argument substitution following legacy conventions
// This supports both the official $ARGUMENTS format and legacy {arg} format // This supports both the official $ARGUMENTS format and legacy {arg} format
// Step 1: Handle $ARGUMENTS placeholder (official Claude Code format) // Step 1: Handle $ARGUMENTS placeholder (legacy command format)
if (prompt.includes('$ARGUMENTS')) { if (prompt.includes('$ARGUMENTS')) {
prompt = prompt.replace(/\$ARGUMENTS/g, args || '') prompt = prompt.replace(/\$ARGUMENTS/g, args || '')
} }
@ -650,9 +649,6 @@ export const loadCustomCommands = memoize(
*/ */
export const reloadCustomCommands = (): void => { export const reloadCustomCommands = (): void => {
loadCustomCommands.cache.clear() loadCustomCommands.cache.clear()
console.log(
'Custom commands cache cleared. Commands will be reloaded on next use.',
)
} }
/** /**

View File

@ -9,6 +9,7 @@ import { getAvailableAgentTypes } from '../utils/agentLoader'
import { existsSync } from 'fs' import { existsSync } from 'fs'
import { resolve } from 'path' import { resolve } from 'path'
import { getCwd } from '../utils/state' import { getCwd } from '../utils/state'
import { debug as debugLogger } from '../utils/debugLogger'
export interface MentionContext { export interface MentionContext {
type: 'agent' | 'file' type: 'agent' | 'file'
@ -159,10 +160,10 @@ class MentionProcessorService {
// Log cache refresh for debugging mention resolution issues // Log cache refresh for debugging mention resolution issues
if (agents.length !== previousCacheSize) { if (agents.length !== previousCacheSize) {
console.log('[MentionProcessor] Agent cache refreshed:', { debugLogger.info('MENTION_PROCESSOR_CACHE_REFRESHED', {
agentCount: agents.length, agentCount: agents.length,
previousCacheSize, previousCacheSize,
cacheAge: now - this.lastAgentCheck cacheAge: now - this.lastAgentCheck,
}) })
} }
} catch (error) { } catch (error) {
@ -232,17 +233,17 @@ class MentionProcessorService {
} }
// Debug log for mention event emission tracking // Debug log for mention event emission tracking
console.log('[MentionProcessor] Emitted mention event:', { debugLogger.info('MENTION_PROCESSOR_EVENT_EMITTED', {
type: isAskModel ? 'ask-model' : 'agent', type: isAskModel ? 'ask-model' : 'agent',
mention, mention,
agentType: isAskModel ? undefined : agentType agentType: isAskModel ? undefined : agentType,
}) })
} catch (error) { } catch (error) {
console.error('[MentionProcessor] Failed to emit mention event:', { debugLogger.error('MENTION_PROCESSOR_EVENT_FAILED', {
mention, mention,
agentType, agentType,
isAskModel, isAskModel,
error: error instanceof Error ? error.message : error error: error instanceof Error ? error.message : error,
}) })
} }
} }
@ -270,4 +271,4 @@ export const processMentions = (input: string) =>
* Clear mention processor caches * Clear mention processor caches
*/ */
export const clearMentionCache = () => export const clearMentionCache = () =>
mentionProcessor.clearCache() mentionProcessor.clearCache()

View File

@ -55,12 +55,12 @@ const inputSchema = z.object({
export const TaskTool = { export const TaskTool = {
async prompt({ safeMode }) { async prompt({ safeMode }) {
// Match original Claude Code - prompt returns full agent descriptions // Ensure agent prompts remain compatible with Claude Code `.claude` agent packs
return await getPrompt(safeMode) return await getPrompt(safeMode)
}, },
name: TOOL_NAME, name: TOOL_NAME,
async description() { async description() {
// Match original Claude Code exactly - simple description // Ensure metadata stays compatible with Claude Code `.claude` agent packs
return "Launch a new task" return "Launch a new task"
}, },
inputSchema, inputSchema,

View File

@ -18,7 +18,7 @@ export async function getTaskTools(safeMode: boolean): Promise<Tool[]> {
} }
export async function getPrompt(safeMode: boolean): Promise<string> { export async function getPrompt(safeMode: boolean): Promise<string> {
// Extracted directly from original Claude Code obfuscated source // Maintain compatibility with Claude Code `.claude` agent descriptions
const agents = await getActiveAgents() const agents = await getActiveAgents()
// Format exactly as in original: (Tools: tool1, tool2) // Format exactly as in original: (Tools: tool1, tool2)
@ -29,7 +29,7 @@ export async function getPrompt(safeMode: boolean): Promise<string> {
return `- ${agent.agentType}: ${agent.whenToUse} (Tools: ${toolsStr})` return `- ${agent.agentType}: ${agent.whenToUse} (Tools: ${toolsStr})`
}).join('\n') }).join('\n')
// 100% exact copy from original Claude Code source // Keep the wording aligned so shared `.claude` agent packs behave identically
return `Launch a new agent to handle complex, multi-step tasks autonomously. return `Launch a new agent to handle complex, multi-step tasks autonomously.
Available agent types and the tools they have access to: Available agent types and the tools they have access to:

View File

@ -1,4 +1,4 @@
// Permission mode types based on original Claude Code implementation // Permission mode types retained for compatibility with earlier agent implementations
export type PermissionMode = export type PermissionMode =
| 'default' | 'default'
| 'acceptEdits' | 'acceptEdits'
@ -35,7 +35,7 @@ export interface ModeConfig {
} }
} }
// Mode configuration based on original Claude Code // Mode configuration preserved for Claude Code parity
export const MODE_CONFIGS: Record<PermissionMode, ModeConfig> = { export const MODE_CONFIGS: Record<PermissionMode, ModeConfig> = {
default: { default: {
name: 'default', name: 'default',
@ -100,7 +100,7 @@ export const MODE_CONFIGS: Record<PermissionMode, ModeConfig> = {
}, },
} }
// Mode cycling function (based on original yg2 function) // Mode cycling function preserved from the Claude Code workflow
export function getNextPermissionMode( export function getNextPermissionMode(
currentMode: PermissionMode, currentMode: PermissionMode,
isBypassAvailable: boolean = true, isBypassAvailable: boolean = true,

View File

@ -1,4 +1,5 @@
import wrapAnsi from 'wrap-ansi' import wrapAnsi from 'wrap-ansi'
import { debug as debugLogger } from './debugLogger'
type WrappedText = string[] type WrappedText = string[]
type Position = { type Position = {
@ -320,11 +321,12 @@ export class MeasuredText {
// For non-blank lines // For non-blank lines
const startOffset = this.text.indexOf(text, searchOffset) const startOffset = this.text.indexOf(text, searchOffset)
if (startOffset === -1) { if (startOffset === -1) {
console.log('Debug: Failed to find wrapped line in original text') debugLogger.error('CURSOR_WRAP_MISMATCH', {
console.log('Debug: Current text:', text) currentText: text,
console.log('Debug: Full original text:', this.text) originalText: this.text,
console.log('Debug: Search offset:', searchOffset) searchOffset,
console.log('Debug: Wrapped text:', wrappedText) wrappedText,
})
throw new Error('Failed to find wrapped line in original text') throw new Error('Failed to find wrapped line in original text')
} }

View File

@ -1,7 +1,8 @@
/** /**
* Agent configuration loader * Agent configuration loader
* Loads agent configurations from markdown files with YAML frontmatter * Loads agent configurations from markdown files with YAML frontmatter.
* Following Claude Code's agent system architecture * Maintains compatibility with Claude Code `.claude` agent directories while
* prioritizing Kode-specific overrides.
*/ */
import { existsSync, readFileSync, readdirSync, statSync, watch, FSWatcher } from 'fs' import { existsSync, readFileSync, readdirSync, statSync, watch, FSWatcher } from 'fs'
@ -231,7 +232,7 @@ let watchers: FSWatcher[] = []
export async function startAgentWatcher(onChange?: () => void): Promise<void> { export async function startAgentWatcher(onChange?: () => void): Promise<void> {
await stopAgentWatcher() // Clean up any existing watchers await stopAgentWatcher() // Clean up any existing watchers
// Watch both .claude and .kode directories // Watch both Claude (.claude) and native (.kode) directories
const userClaudeDir = join(homedir(), '.claude', 'agents') const userClaudeDir = join(homedir(), '.claude', 'agents')
const userKodeDir = join(homedir(), '.kode', 'agents') const userKodeDir = join(homedir(), '.kode', 'agents')
const projectClaudeDir = join(getCwd(), '.claude', 'agents') const projectClaudeDir = join(getCwd(), '.claude', 'agents')

View File

@ -22,7 +22,7 @@ type Props = {
verbose?: boolean verbose?: boolean
} }
// Sends a single prompt to the Claude API and returns the response. // Sends a single prompt to the Anthropic Messages API and returns the response.
// Assumes that claude is being used non-interactively -- will not // Assumes that claude is being used non-interactively -- will not
// ask the user for permissions or further input. // ask the user for permissions or further input.
export async function ask({ export async function ask({