mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-22 08:15:53 +00:00
feat: 工具层及 mcp 大重构 (#252)
* feat: 第一版大重构 * fix: 修复类型问题 * chore: 更新版本到 1.3.2 * Add brave as alternative WebSearchTool * fix: 修正顺序 * fix: 修复对穷鬼模式的 auto dream 和 session memory 越过 * feat: 穷鬼模式去除 session-summary * feat: 创建 builtin-tools 包,搬运所有工具实现 将 src/tools/ 下的全部 60 个工具目录迁移至 packages/builtin-tools/src/tools/, 内部导入路径已更新为 src/ alias 模式。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: 更新 src/ 中所有工具引用至 builtin-tools 包,删除 src/tools/ - src/tools.ts 及 178 个 src/ 文件的 import 路径从 ./tools/ 改为 builtin-tools/tools/ - 删除 src/tools/ 整个目录(已迁移至 packages/builtin-tools/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: 添加 builtin-tools 路径别名至 tsconfig,更新 bun.lock - tsconfig.json 新增 builtin-tools/* 和 builtin-tools 路径映射 - 新增 packages/builtin-tools/src 至 include Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: 为 builtin-tools、mcp-client、agent-tools 添加 @claude-code-best 作用域前缀 所有包名及 import 路径统一添加 @claude-code-best/ 前缀: - builtin-tools → @claude-code-best/builtin-tools - mcp-client → @claude-code-best/mcp-client - agent-tools → @claude-code-best/agent-tools Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: 修复 node 环境没有 bun 的问题 --------- Co-authored-by: Eric-Guo <eric.guocz@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
89
packages/builtin-tools/src/tools/REPLTool/REPLTool.ts
Normal file
89
packages/builtin-tools/src/tools/REPLTool/REPLTool.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { z } from 'zod/v4'
|
||||
import type { ToolResultBlockParam } from 'src/Tool.js'
|
||||
import { buildTool } from 'src/Tool.js'
|
||||
import { lazySchema } from 'src/utils/lazySchema.js'
|
||||
import { REPL_TOOL_NAME } from './constants.js'
|
||||
|
||||
const inputSchema = lazySchema(() =>
|
||||
z.strictObject({
|
||||
code: z
|
||||
.string()
|
||||
.describe(
|
||||
'The code to execute in the REPL. Can call any primitive tool (Read, Write, Edit, Glob, Grep, Bash, NotebookEdit, Agent) via their APIs.',
|
||||
),
|
||||
}),
|
||||
)
|
||||
type InputSchema = ReturnType<typeof inputSchema>
|
||||
type REPLInput = z.infer<InputSchema>
|
||||
|
||||
type REPLOutput = { result: string; tool_calls: number }
|
||||
|
||||
export const REPLTool = buildTool({
|
||||
name: REPL_TOOL_NAME,
|
||||
searchHint: 'repl execute batch code read write edit glob grep bash',
|
||||
maxResultSizeChars: 100_000,
|
||||
strict: true,
|
||||
|
||||
get inputSchema(): InputSchema {
|
||||
return inputSchema()
|
||||
},
|
||||
|
||||
async description() {
|
||||
return 'Execute code in the REPL environment with access to all primitive tools'
|
||||
},
|
||||
async prompt() {
|
||||
return `Execute code in the REPL — a sandboxed environment with direct access to primitive tools (Read, Write, Edit, Glob, Grep, Bash, NotebookEdit, Agent).
|
||||
|
||||
When REPL mode is active, primitive tools are only accessible through this tool. Use REPL for:
|
||||
- Batch operations across many files
|
||||
- Complex multi-step file transformations
|
||||
- Operations that benefit from programmatic control flow
|
||||
- Combining search results with edits in a single turn
|
||||
|
||||
The REPL runs in a VM context with tool APIs available as functions. Results from each tool call are collected and returned together.`
|
||||
},
|
||||
|
||||
isConcurrencySafe() {
|
||||
return false
|
||||
},
|
||||
isReadOnly() {
|
||||
return false
|
||||
},
|
||||
isTransparentWrapper() {
|
||||
return true
|
||||
},
|
||||
|
||||
userFacingName() {
|
||||
return REPL_TOOL_NAME
|
||||
},
|
||||
|
||||
renderToolUseMessage(input: Partial<REPLInput>) {
|
||||
const code = input.code ?? ''
|
||||
const preview = code.length > 80 ? code.slice(0, 77) + '...' : code
|
||||
return `REPL: ${preview}`
|
||||
},
|
||||
|
||||
mapToolResultToToolResultBlockParam(
|
||||
content: REPLOutput,
|
||||
toolUseID: string,
|
||||
): ToolResultBlockParam {
|
||||
return {
|
||||
tool_use_id: toolUseID,
|
||||
type: 'tool_result',
|
||||
content: content.result,
|
||||
}
|
||||
},
|
||||
|
||||
async call(_input: REPLInput) {
|
||||
// REPL execution engine is provided by the ant-native runtime.
|
||||
// This stub satisfies the tool interface; the actual VM dispatch
|
||||
// is wired in the ant build. Without the ant runtime, REPL is
|
||||
// not available and callers should be informed.
|
||||
return {
|
||||
data: {
|
||||
result: 'Error: REPL tool is not available in this build. The REPL execution engine requires the ant-native runtime.',
|
||||
tool_calls: 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
46
packages/builtin-tools/src/tools/REPLTool/constants.ts
Normal file
46
packages/builtin-tools/src/tools/REPLTool/constants.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { isEnvDefinedFalsy, isEnvTruthy } from 'src/utils/envUtils.js'
|
||||
import { AGENT_TOOL_NAME } from '../AgentTool/constants.js'
|
||||
import { BASH_TOOL_NAME } from '../BashTool/toolName.js'
|
||||
import { FILE_EDIT_TOOL_NAME } from '../FileEditTool/constants.js'
|
||||
import { FILE_READ_TOOL_NAME } from '../FileReadTool/prompt.js'
|
||||
import { FILE_WRITE_TOOL_NAME } from '../FileWriteTool/prompt.js'
|
||||
import { GLOB_TOOL_NAME } from '../GlobTool/prompt.js'
|
||||
import { GREP_TOOL_NAME } from '../GrepTool/prompt.js'
|
||||
import { NOTEBOOK_EDIT_TOOL_NAME } from '../NotebookEditTool/constants.js'
|
||||
|
||||
export const REPL_TOOL_NAME = 'REPL'
|
||||
|
||||
/**
|
||||
* REPL mode is default-on for ants in the interactive CLI (opt out with
|
||||
* CLAUDE_CODE_REPL=0). The legacy CLAUDE_REPL_MODE=1 also forces it on.
|
||||
*
|
||||
* SDK entrypoints (sdk-ts, sdk-py, sdk-cli) are NOT defaulted on — SDK
|
||||
* consumers script direct tool calls (Bash, Read, etc.) and REPL mode
|
||||
* hides those tools. USER_TYPE is a build-time --define, so the ant-native
|
||||
* binary would otherwise force REPL mode on every SDK subprocess regardless
|
||||
* of the env the caller passes.
|
||||
*/
|
||||
export function isReplModeEnabled(): boolean {
|
||||
if (isEnvDefinedFalsy(process.env.CLAUDE_CODE_REPL)) return false
|
||||
if (isEnvTruthy(process.env.CLAUDE_REPL_MODE)) return true
|
||||
return (
|
||||
process.env.USER_TYPE === 'ant' &&
|
||||
process.env.CLAUDE_CODE_ENTRYPOINT === 'cli'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Tools that are only accessible via REPL when REPL mode is enabled.
|
||||
* When REPL mode is on, these tools are hidden from Claude's direct use,
|
||||
* forcing Claude to use REPL for batch operations.
|
||||
*/
|
||||
export const REPL_ONLY_TOOLS = new Set([
|
||||
FILE_READ_TOOL_NAME,
|
||||
FILE_WRITE_TOOL_NAME,
|
||||
FILE_EDIT_TOOL_NAME,
|
||||
GLOB_TOOL_NAME,
|
||||
GREP_TOOL_NAME,
|
||||
BASH_TOOL_NAME,
|
||||
NOTEBOOK_EDIT_TOOL_NAME,
|
||||
AGENT_TOOL_NAME,
|
||||
])
|
||||
39
packages/builtin-tools/src/tools/REPLTool/primitiveTools.ts
Normal file
39
packages/builtin-tools/src/tools/REPLTool/primitiveTools.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { Tool } from 'src/Tool.js'
|
||||
import { AgentTool } from '../AgentTool/AgentTool.js'
|
||||
import { BashTool } from '../BashTool/BashTool.js'
|
||||
import { FileEditTool } from '../FileEditTool/FileEditTool.js'
|
||||
import { FileReadTool } from '../FileReadTool/FileReadTool.js'
|
||||
import { FileWriteTool } from '../FileWriteTool/FileWriteTool.js'
|
||||
import { GlobTool } from '../GlobTool/GlobTool.js'
|
||||
import { GrepTool } from '../GrepTool/GrepTool.js'
|
||||
import { NotebookEditTool } from '../NotebookEditTool/NotebookEditTool.js'
|
||||
|
||||
let _primitiveTools: readonly Tool[] | undefined
|
||||
|
||||
/**
|
||||
* Primitive tools hidden from direct model use when REPL mode is on
|
||||
* (REPL_ONLY_TOOLS) but still accessible inside the REPL VM context.
|
||||
* Exported so display-side code (collapseReadSearch, renderers) can
|
||||
* classify/render virtual messages for these tools even when they're
|
||||
* absent from the filtered execution tools list.
|
||||
*
|
||||
* Lazy getter — the import chain collapseReadSearch.ts → primitiveTools.ts
|
||||
* → FileReadTool.tsx → ... loops back through the tool registry, so a
|
||||
* top-level const hits "Cannot access before initialization". Deferring
|
||||
* to call time avoids the TDZ.
|
||||
*
|
||||
* Referenced directly rather than via getAllBaseTools() because that
|
||||
* excludes Glob/Grep when hasEmbeddedSearchTools() is true.
|
||||
*/
|
||||
export function getReplPrimitiveTools(): readonly Tool[] {
|
||||
return (_primitiveTools ??= [
|
||||
FileReadTool,
|
||||
FileWriteTool,
|
||||
FileEditTool,
|
||||
GlobTool,
|
||||
GrepTool,
|
||||
BashTool,
|
||||
NotebookEditTool,
|
||||
AgentTool,
|
||||
])
|
||||
}
|
||||
Reference in New Issue
Block a user