mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 21:53:28 +08:00
feat: deliver v1.8.0 harness reliability and parity updates
This commit is contained in:
@@ -1,66 +1,68 @@
|
||||
/**
|
||||
* ECC Custom Tool: Format Code
|
||||
*
|
||||
* Language-aware code formatter that auto-detects the project's formatter.
|
||||
* Supports: Biome/Prettier (JS/TS), Black (Python), gofmt (Go), rustfmt (Rust)
|
||||
* Returns the formatter command that should be run for a given file.
|
||||
* This avoids shell execution assumptions while still giving precise guidance.
|
||||
*/
|
||||
|
||||
import { tool } from "@opencode-ai/plugin"
|
||||
import { z } from "zod"
|
||||
import { tool } from "@opencode-ai/plugin/tool"
|
||||
import * as path from "path"
|
||||
import * as fs from "fs"
|
||||
|
||||
type Formatter = "biome" | "prettier" | "black" | "gofmt" | "rustfmt"
|
||||
|
||||
export default tool({
|
||||
name: "format-code",
|
||||
description: "Format a file using the project's configured formatter. Auto-detects Biome, Prettier, Black, gofmt, or rustfmt.",
|
||||
parameters: z.object({
|
||||
filePath: z.string().describe("Path to the file to format"),
|
||||
formatter: z.string().optional().describe("Override formatter: biome, prettier, black, gofmt, rustfmt (default: auto-detect)"),
|
||||
}),
|
||||
execute: async ({ filePath, formatter }, { $ }) => {
|
||||
const ext = filePath.split(".").pop()?.toLowerCase() || ""
|
||||
|
||||
// Auto-detect formatter based on file extension and config files
|
||||
let detected = formatter
|
||||
if (!detected) {
|
||||
if (["ts", "tsx", "js", "jsx", "json", "css", "scss"].includes(ext)) {
|
||||
// Check for Biome first, then Prettier
|
||||
try {
|
||||
await $`test -f biome.json || test -f biome.jsonc`
|
||||
detected = "biome"
|
||||
} catch {
|
||||
detected = "prettier"
|
||||
}
|
||||
} else if (["py", "pyi"].includes(ext)) {
|
||||
detected = "black"
|
||||
} else if (ext === "go") {
|
||||
detected = "gofmt"
|
||||
} else if (ext === "rs") {
|
||||
detected = "rustfmt"
|
||||
}
|
||||
}
|
||||
description:
|
||||
"Detect formatter for a file and return the exact command to run (Biome, Prettier, Black, gofmt, rustfmt).",
|
||||
args: {
|
||||
filePath: tool.schema.string().describe("Path to the file to format"),
|
||||
formatter: tool.schema
|
||||
.enum(["biome", "prettier", "black", "gofmt", "rustfmt"])
|
||||
.optional()
|
||||
.describe("Optional formatter override"),
|
||||
},
|
||||
async execute(args, context) {
|
||||
const cwd = context.worktree || context.directory
|
||||
const ext = args.filePath.split(".").pop()?.toLowerCase() || ""
|
||||
const detected = args.formatter || detectFormatter(cwd, ext)
|
||||
|
||||
if (!detected) {
|
||||
return { formatted: false, message: `No formatter detected for .${ext} files` }
|
||||
return JSON.stringify({
|
||||
success: false,
|
||||
message: `No formatter detected for .${ext} files`,
|
||||
})
|
||||
}
|
||||
|
||||
const commands: Record<string, string> = {
|
||||
biome: `npx @biomejs/biome format --write ${filePath}`,
|
||||
prettier: `npx prettier --write ${filePath}`,
|
||||
black: `black ${filePath}`,
|
||||
gofmt: `gofmt -w ${filePath}`,
|
||||
rustfmt: `rustfmt ${filePath}`,
|
||||
}
|
||||
|
||||
const cmd = commands[detected]
|
||||
if (!cmd) {
|
||||
return { formatted: false, message: `Unknown formatter: ${detected}` }
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await $`${cmd}`.text()
|
||||
return { formatted: true, formatter: detected, output: result }
|
||||
} catch (error: unknown) {
|
||||
const err = error as { stderr?: string }
|
||||
return { formatted: false, formatter: detected, error: err.stderr || "Format failed" }
|
||||
}
|
||||
const command = buildFormatterCommand(detected, args.filePath)
|
||||
return JSON.stringify({
|
||||
success: true,
|
||||
formatter: detected,
|
||||
command,
|
||||
instructions: `Run this command:\n\n${command}`,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
function detectFormatter(cwd: string, ext: string): Formatter | null {
|
||||
if (["ts", "tsx", "js", "jsx", "json", "css", "scss", "md", "yaml", "yml"].includes(ext)) {
|
||||
if (fs.existsSync(path.join(cwd, "biome.json")) || fs.existsSync(path.join(cwd, "biome.jsonc"))) {
|
||||
return "biome"
|
||||
}
|
||||
return "prettier"
|
||||
}
|
||||
if (["py", "pyi"].includes(ext)) return "black"
|
||||
if (ext === "go") return "gofmt"
|
||||
if (ext === "rs") return "rustfmt"
|
||||
return null
|
||||
}
|
||||
|
||||
function buildFormatterCommand(formatter: Formatter, filePath: string): string {
|
||||
const commands: Record<Formatter, string> = {
|
||||
biome: `npx @biomejs/biome format --write ${filePath}`,
|
||||
prettier: `npx prettier --write ${filePath}`,
|
||||
black: `black ${filePath}`,
|
||||
gofmt: `gofmt -w ${filePath}`,
|
||||
rustfmt: `rustfmt ${filePath}`,
|
||||
}
|
||||
return commands[formatter]
|
||||
}
|
||||
|
||||
@@ -1,56 +1,54 @@
|
||||
/**
|
||||
* ECC Custom Tool: Git Summary
|
||||
*
|
||||
* Provides a comprehensive git status including branch info, status,
|
||||
* recent log, and diff against base branch.
|
||||
* Returns branch/status/log/diff details for the active repository.
|
||||
*/
|
||||
|
||||
import { tool } from "@opencode-ai/plugin"
|
||||
import { z } from "zod"
|
||||
import { tool } from "@opencode-ai/plugin/tool"
|
||||
import { execSync } from "child_process"
|
||||
|
||||
export default tool({
|
||||
name: "git-summary",
|
||||
description: "Get comprehensive git summary: branch, status, recent log, and diff against base branch.",
|
||||
parameters: z.object({
|
||||
depth: z.number().optional().describe("Number of recent commits to show (default: 5)"),
|
||||
includeDiff: z.boolean().optional().describe("Include diff against base branch (default: true)"),
|
||||
baseBranch: z.string().optional().describe("Base branch for comparison (default: main)"),
|
||||
}),
|
||||
execute: async ({ depth = 5, includeDiff = true, baseBranch = "main" }, { $ }) => {
|
||||
const results: Record<string, string> = {}
|
||||
description:
|
||||
"Generate git summary with branch, status, recent commits, and optional diff stats.",
|
||||
args: {
|
||||
depth: tool.schema
|
||||
.number()
|
||||
.optional()
|
||||
.describe("Number of recent commits to include (default: 5)"),
|
||||
includeDiff: tool.schema
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe("Include diff stats against base branch (default: true)"),
|
||||
baseBranch: tool.schema
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Base branch for diff comparison (default: main)"),
|
||||
},
|
||||
async execute(args, context) {
|
||||
const cwd = context.worktree || context.directory
|
||||
const depth = args.depth ?? 5
|
||||
const includeDiff = args.includeDiff ?? true
|
||||
const baseBranch = args.baseBranch ?? "main"
|
||||
|
||||
try {
|
||||
results.branch = (await $`git branch --show-current`.text()).trim()
|
||||
} catch {
|
||||
results.branch = "unknown"
|
||||
}
|
||||
|
||||
try {
|
||||
results.status = (await $`git status --short`.text()).trim()
|
||||
} catch {
|
||||
results.status = "unable to get status"
|
||||
}
|
||||
|
||||
try {
|
||||
results.log = (await $`git log --oneline -${depth}`.text()).trim()
|
||||
} catch {
|
||||
results.log = "unable to get log"
|
||||
const result: Record<string, string> = {
|
||||
branch: run("git branch --show-current", cwd) || "unknown",
|
||||
status: run("git status --short", cwd) || "clean",
|
||||
log: run(`git log --oneline -${depth}`, cwd) || "no commits found",
|
||||
}
|
||||
|
||||
if (includeDiff) {
|
||||
try {
|
||||
results.stagedDiff = (await $`git diff --cached --stat`.text()).trim()
|
||||
} catch {
|
||||
results.stagedDiff = ""
|
||||
}
|
||||
|
||||
try {
|
||||
results.branchDiff = (await $`git diff ${baseBranch}...HEAD --stat`.text()).trim()
|
||||
} catch {
|
||||
results.branchDiff = `unable to diff against ${baseBranch}`
|
||||
}
|
||||
result.stagedDiff = run("git diff --cached --stat", cwd) || ""
|
||||
result.branchDiff = run(`git diff ${baseBranch}...HEAD --stat`, cwd) || `unable to diff against ${baseBranch}`
|
||||
}
|
||||
|
||||
return results
|
||||
return JSON.stringify(result)
|
||||
},
|
||||
})
|
||||
|
||||
function run(command: string, cwd: string): string {
|
||||
try {
|
||||
return execSync(command, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).trim()
|
||||
} catch {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,74 +1,85 @@
|
||||
/**
|
||||
* ECC Custom Tool: Lint Check
|
||||
*
|
||||
* Multi-language linter that auto-detects the project's linting tool.
|
||||
* Supports: ESLint/Biome (JS/TS), Pylint/Ruff (Python), golangci-lint (Go)
|
||||
* Detects the appropriate linter and returns a runnable lint command.
|
||||
*/
|
||||
|
||||
import { tool } from "@opencode-ai/plugin"
|
||||
import { z } from "zod"
|
||||
import { tool } from "@opencode-ai/plugin/tool"
|
||||
import * as path from "path"
|
||||
import * as fs from "fs"
|
||||
|
||||
type Linter = "biome" | "eslint" | "ruff" | "pylint" | "golangci-lint"
|
||||
|
||||
export default tool({
|
||||
name: "lint-check",
|
||||
description: "Run linter on files or directories. Auto-detects ESLint, Biome, Ruff, Pylint, or golangci-lint.",
|
||||
parameters: z.object({
|
||||
target: z.string().optional().describe("File or directory to lint (default: current directory)"),
|
||||
fix: z.boolean().optional().describe("Auto-fix issues if supported (default: false)"),
|
||||
linter: z.string().optional().describe("Override linter: eslint, biome, ruff, pylint, golangci-lint (default: auto-detect)"),
|
||||
}),
|
||||
execute: async ({ target = ".", fix = false, linter }, { $ }) => {
|
||||
// Auto-detect linter
|
||||
let detected = linter
|
||||
if (!detected) {
|
||||
try {
|
||||
await $`test -f biome.json || test -f biome.jsonc`
|
||||
detected = "biome"
|
||||
} catch {
|
||||
try {
|
||||
await $`test -f .eslintrc.json || test -f .eslintrc.js || test -f .eslintrc.cjs || test -f eslint.config.js || test -f eslint.config.mjs`
|
||||
detected = "eslint"
|
||||
} catch {
|
||||
try {
|
||||
await $`test -f pyproject.toml && grep -q "ruff" pyproject.toml`
|
||||
detected = "ruff"
|
||||
} catch {
|
||||
try {
|
||||
await $`test -f .golangci.yml || test -f .golangci.yaml`
|
||||
detected = "golangci-lint"
|
||||
} catch {
|
||||
// Fall back based on file extensions in target
|
||||
detected = "eslint"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
description:
|
||||
"Detect linter for a target path and return command for check/fix runs.",
|
||||
args: {
|
||||
target: tool.schema
|
||||
.string()
|
||||
.optional()
|
||||
.describe("File or directory to lint (default: current directory)"),
|
||||
fix: tool.schema
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe("Enable auto-fix mode"),
|
||||
linter: tool.schema
|
||||
.enum(["biome", "eslint", "ruff", "pylint", "golangci-lint"])
|
||||
.optional()
|
||||
.describe("Optional linter override"),
|
||||
},
|
||||
async execute(args, context) {
|
||||
const cwd = context.worktree || context.directory
|
||||
const target = args.target || "."
|
||||
const fix = args.fix ?? false
|
||||
const detected = args.linter || detectLinter(cwd)
|
||||
|
||||
const fixFlag = fix ? " --fix" : ""
|
||||
const commands: Record<string, string> = {
|
||||
biome: `npx @biomejs/biome lint${fix ? " --write" : ""} ${target}`,
|
||||
eslint: `npx eslint${fixFlag} ${target}`,
|
||||
ruff: `ruff check${fixFlag} ${target}`,
|
||||
pylint: `pylint ${target}`,
|
||||
"golangci-lint": `golangci-lint run${fixFlag} ${target}`,
|
||||
}
|
||||
|
||||
const cmd = commands[detected]
|
||||
if (!cmd) {
|
||||
return { success: false, message: `Unknown linter: ${detected}` }
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await $`${cmd}`.text()
|
||||
return { success: true, linter: detected, output: result, issues: 0 }
|
||||
} catch (error: unknown) {
|
||||
const err = error as { stdout?: string; stderr?: string }
|
||||
return {
|
||||
success: false,
|
||||
linter: detected,
|
||||
output: err.stdout || "",
|
||||
errors: err.stderr || "",
|
||||
}
|
||||
}
|
||||
const command = buildLintCommand(detected, target, fix)
|
||||
return JSON.stringify({
|
||||
success: true,
|
||||
linter: detected,
|
||||
command,
|
||||
instructions: `Run this command:\n\n${command}`,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
function detectLinter(cwd: string): Linter {
|
||||
if (fs.existsSync(path.join(cwd, "biome.json")) || fs.existsSync(path.join(cwd, "biome.jsonc"))) {
|
||||
return "biome"
|
||||
}
|
||||
|
||||
const eslintConfigs = [
|
||||
".eslintrc.json",
|
||||
".eslintrc.js",
|
||||
".eslintrc.cjs",
|
||||
"eslint.config.js",
|
||||
"eslint.config.mjs",
|
||||
]
|
||||
if (eslintConfigs.some((name) => fs.existsSync(path.join(cwd, name)))) {
|
||||
return "eslint"
|
||||
}
|
||||
|
||||
const pyprojectPath = path.join(cwd, "pyproject.toml")
|
||||
if (fs.existsSync(pyprojectPath)) {
|
||||
try {
|
||||
const content = fs.readFileSync(pyprojectPath, "utf-8")
|
||||
if (content.includes("ruff")) return "ruff"
|
||||
} catch {
|
||||
// ignore read errors and keep fallback logic
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.existsSync(path.join(cwd, ".golangci.yml")) || fs.existsSync(path.join(cwd, ".golangci.yaml"))) {
|
||||
return "golangci-lint"
|
||||
}
|
||||
|
||||
return "eslint"
|
||||
}
|
||||
|
||||
function buildLintCommand(linter: Linter, target: string, fix: boolean): string {
|
||||
if (linter === "biome") return `npx @biomejs/biome lint${fix ? " --write" : ""} ${target}`
|
||||
if (linter === "eslint") return `npx eslint${fix ? " --fix" : ""} ${target}`
|
||||
if (linter === "ruff") return `ruff check${fix ? " --fix" : ""} ${target}`
|
||||
if (linter === "pylint") return `pylint ${target}`
|
||||
return `golangci-lint run ${target}`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user