Initial commit

This commit is contained in:
xggz
2026-03-06 22:56:13 +08:00
commit 54d1097b41
273 changed files with 92457 additions and 0 deletions

View File

@@ -0,0 +1,231 @@
const EXACT_TOOL_NAME_ALIASES: Record<string, string> = {
shell_command: "bash",
"functions.shell_command": "bash",
exec_command: "exec_command",
"functions.exec_command": "exec_command",
"functions.read": "read",
"functions.edit": "edit",
"functions.write": "write",
"functions.apply_patch": "apply_patch",
change: "edit",
"functions.change": "edit",
changes: "edit",
write_stdin: "bash",
read_file: "read",
read_text_file: "read",
readfile: "read",
"read file": "read",
edit_file: "edit",
update_file: "edit",
write_file: "write",
mcp__acp__read: "read",
mcp__acp__edit: "edit",
mcp__acp__write: "write",
todowrite: "todowrite",
todo_write: "todowrite",
task_update: "taskupdate",
task_create: "taskcreate",
task_list: "tasklist",
enter_plan_mode: "enterplanmode",
exit_plan_mode: "exitplanmode",
web_fetch: "webfetch",
web_search: "websearch",
context7_query_docs: "context7_query-docs",
context7_resolve_library_id: "context7_resolve-library-id",
execute: "bash",
search: "grep",
fetch: "webfetch",
think: "task",
switch_mode: "switch_mode",
other: "tool",
}
function canonicalizeToolName(input: string): string {
return input
.trim()
.toLowerCase()
.replace(/[().]/g, "_")
.replace(/[\s-]+/g, "_")
}
function inferFromFreeformName(input: string): string | null {
const normalized = input.trim().toLowerCase()
if (!normalized) return null
if (
/\b(?:shell|bash|exec(?:ute)?)\s*[_-]?(?:command|cmd)?\b/.test(normalized)
)
return "bash"
if (/apply\s*[_-]?patch/.test(normalized)) return "apply_patch"
if (/^change(?:$|[\s:/_-])/.test(normalized)) return "edit"
if (/^read(?:$|[\s:/-])/.test(normalized)) return "read"
if (/^edit(?:$|[\s:/-])/.test(normalized)) return "edit"
if (/^write(?:$|[\s:/-])/.test(normalized)) return "write"
if (/^grep(?:\b|[_\s:-])/.test(normalized)) return "grep"
if (/^glob(?:\b|[_\s:-])/.test(normalized)) return "glob"
if (/^webfetch(?:\b|[_\s:-])/.test(normalized)) return "webfetch"
if (/^websearch(?:\b|[_\s:-])/.test(normalized)) return "websearch"
if (/^todowrite(?:\b|[_\s:-])/.test(normalized)) return "todowrite"
if (/^taskupdate(?:\b|[_\s:-])/.test(normalized)) return "taskupdate"
if (/^taskcreate(?:\b|[_\s:-])/.test(normalized)) return "taskcreate"
if (/^tasklist(?:\b|[_\s:-])/.test(normalized)) return "tasklist"
if (/^task(?:\b|[_\s:-])/.test(normalized)) return "task"
return null
}
function extractToolNameFromLiveCallTitle(input: string): string | null {
const match = input.match(
/^[:'"`“”‘’\s]*([a-z0-9_.-]+)(?:\s*[:])?\s*call[\w-]*['"`“”‘’\s]*$/i
)
return match?.[1] ?? null
}
function tryParseInputObject(rawInput: string | null | undefined) {
if (!rawInput) return null
try {
const parsed = JSON.parse(rawInput)
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
return null
}
return parsed as Record<string, unknown>
} catch {
return null
}
}
function hasAnyKey(obj: Record<string, unknown>, keys: string[]): boolean {
return keys.some(
(key) => key in obj && obj[key] !== null && obj[key] !== undefined
)
}
function inferFromInput(
rawInput: string | null | undefined,
kind: string | null | undefined,
title: string | null | undefined
): string | null {
if (!rawInput) return null
const normalizedKind = normalizeToolName(kind ?? "")
const normalizedTitle = normalizeToolName(title ?? "")
if (rawInput.includes("*** Begin Patch")) {
return "apply_patch"
}
const trimmed = rawInput.trim()
if (
trimmed.length > 0 &&
!trimmed.startsWith("{") &&
!trimmed.startsWith("[") &&
(normalizedKind === "bash" ||
normalizedKind === "exec_command" ||
normalizedKind === "tool" ||
normalizedTitle === "bash" ||
normalizedTitle === "exec_command")
) {
return "bash"
}
const parsed = tryParseInputObject(rawInput)
if (!parsed) return null
if (
hasAnyKey(parsed, [
"command",
"cmd",
"script",
"args",
"argv",
"command_args",
])
)
return "bash"
if (hasAnyKey(parsed, ["old_string", "new_string", "replace_all"]))
return "edit"
if (hasAnyKey(parsed, ["changes"])) return "edit"
if (hasAnyKey(parsed, ["todos"])) return "todowrite"
if (hasAnyKey(parsed, ["query"])) return "websearch"
if (hasAnyKey(parsed, ["url"])) return "webfetch"
const hasPattern = hasAnyKey(parsed, ["pattern"])
const hasGlob = hasAnyKey(parsed, ["glob"])
if (hasPattern) return hasGlob ? "glob" : "grep"
if (hasGlob) return "glob"
if (hasAnyKey(parsed, ["subagent_type", "taskId", "task_id", "subject"])) {
return "task"
}
const hasPath = hasAnyKey(parsed, ["file_path", "notebook_path", "path"])
if (hasPath) {
if (
normalizedKind === "read" ||
normalizedKind === "edit" ||
normalizedKind === "write" ||
normalizedKind === "delete" ||
normalizedKind === "move"
) {
return normalizedKind
}
if (
normalizedTitle === "read" ||
normalizedTitle === "edit" ||
normalizedTitle === "write"
) {
return normalizedTitle
}
if (
hasAnyKey(parsed, ["content", "new_source", "cell_type", "edit_mode"])
) {
return "write"
}
return "read"
}
return null
}
export function normalizeToolName(toolName: string): string {
const trimmed = toolName
.trim()
.replace(/^[:'"`“”‘’\s]+/, "")
.replace(/['"`“”‘’\s]+$/, "")
if (!trimmed) return "tool"
const exact = EXACT_TOOL_NAME_ALIASES[trimmed.toLowerCase()]
if (exact) return exact
const canonical = canonicalizeToolName(trimmed)
const alias = EXACT_TOOL_NAME_ALIASES[canonical]
if (alias) return alias
const freeform = inferFromFreeformName(trimmed)
if (freeform) return freeform
const liveTitleToolName = extractToolNameFromLiveCallTitle(trimmed)
if (liveTitleToolName) {
const fromLiveTitle = normalizeToolName(liveTitleToolName)
if (fromLiveTitle !== "tool") return fromLiveTitle
}
return trimmed
}
export function inferLiveToolName(params: {
title?: string | null
kind?: string | null
rawInput?: string | null
}): string {
const byInput = inferFromInput(params.rawInput, params.kind, params.title)
if (byInput) return byInput
const byTitle = normalizeToolName(params.title ?? "")
if (byTitle !== "tool") return byTitle
const byKind = normalizeToolName(params.kind ?? "")
if (byKind !== "tool") return byKind
return "tool"
}