mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
fix: update opencode-ecc plugin for SDK v1.1.53 and refresh README stats
- Fix PluginContext → PluginInput type rename in @opencode-ai/plugin - Import tool from @opencode-ai/plugin/tool subpath (fixes broken barrel export) - Update client.app.log() calls to use new options-object API signature - Stringify tool execute return values (SDK now requires Promise<string>) - Add .js extensions to relative imports for NodeNext module resolution - Update README star count (42K+) and contributor count (24)
This commit is contained in:
@@ -13,18 +13,21 @@
|
|||||||
* - SessionEnd → session.deleted
|
* - SessionEnd → session.deleted
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { PluginContext } from "@opencode-ai/plugin"
|
import type { PluginInput } from "@opencode-ai/plugin"
|
||||||
|
|
||||||
export const ECCHooksPlugin = async ({
|
export const ECCHooksPlugin = async ({
|
||||||
project,
|
|
||||||
client,
|
client,
|
||||||
$,
|
$,
|
||||||
directory,
|
directory,
|
||||||
worktree,
|
worktree,
|
||||||
}: PluginContext) => {
|
}: PluginInput) => {
|
||||||
// Track files edited in current session for console.log audit
|
// Track files edited in current session for console.log audit
|
||||||
const editedFiles = new Set<string>()
|
const editedFiles = new Set<string>()
|
||||||
|
|
||||||
|
// Helper to call the SDK's log API with correct signature
|
||||||
|
const log = (level: "debug" | "info" | "warn" | "error", message: string) =>
|
||||||
|
client.app.log({ body: { service: "ecc", level, message } })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
* Prettier Auto-Format Hook
|
* Prettier Auto-Format Hook
|
||||||
@@ -41,7 +44,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
if (event.path.match(/\.(ts|tsx|js|jsx)$/)) {
|
if (event.path.match(/\.(ts|tsx|js|jsx)$/)) {
|
||||||
try {
|
try {
|
||||||
await $`prettier --write ${event.path} 2>/dev/null`
|
await $`prettier --write ${event.path} 2>/dev/null`
|
||||||
client.app.log("info", `[ECC] Formatted: ${event.path}`)
|
log("info", `[ECC] Formatted: ${event.path}`)
|
||||||
} catch {
|
} catch {
|
||||||
// Prettier not installed or failed - silently continue
|
// Prettier not installed or failed - silently continue
|
||||||
}
|
}
|
||||||
@@ -53,7 +56,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
const result = await $`grep -n "console\\.log" ${event.path} 2>/dev/null`.text()
|
const result = await $`grep -n "console\\.log" ${event.path} 2>/dev/null`.text()
|
||||||
if (result.trim()) {
|
if (result.trim()) {
|
||||||
const lines = result.trim().split("\n").length
|
const lines = result.trim().split("\n").length
|
||||||
client.app.log(
|
log(
|
||||||
"warn",
|
"warn",
|
||||||
`[ECC] console.log found in ${event.path} (${lines} occurrence${lines > 1 ? "s" : ""})`
|
`[ECC] console.log found in ${event.path} (${lines} occurrence${lines > 1 ? "s" : ""})`
|
||||||
)
|
)
|
||||||
@@ -82,21 +85,21 @@ export const ECCHooksPlugin = async ({
|
|||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
await $`npx tsc --noEmit 2>&1`
|
await $`npx tsc --noEmit 2>&1`
|
||||||
client.app.log("info", "[ECC] TypeScript check passed")
|
log("info", "[ECC] TypeScript check passed")
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const err = error as { stdout?: string }
|
const err = error as { stdout?: string }
|
||||||
client.app.log("warn", "[ECC] TypeScript errors detected:")
|
log("warn", "[ECC] TypeScript errors detected:")
|
||||||
if (err.stdout) {
|
if (err.stdout) {
|
||||||
// Log first few errors
|
// Log first few errors
|
||||||
const errors = err.stdout.split("\n").slice(0, 5)
|
const errors = err.stdout.split("\n").slice(0, 5)
|
||||||
errors.forEach((line: string) => client.app.log("warn", ` ${line}`))
|
errors.forEach((line: string) => log("warn", ` ${line}`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PR creation logging
|
// PR creation logging
|
||||||
if (input.tool === "bash" && input.args?.toString().includes("gh pr create")) {
|
if (input.tool === "bash" && input.args?.toString().includes("gh pr create")) {
|
||||||
client.app.log("info", "[ECC] PR created - check GitHub Actions status")
|
log("info", "[ECC] PR created - check GitHub Actions status")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -115,7 +118,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
input.tool === "bash" &&
|
input.tool === "bash" &&
|
||||||
input.args?.toString().includes("git push")
|
input.args?.toString().includes("git push")
|
||||||
) {
|
) {
|
||||||
client.app.log(
|
log(
|
||||||
"info",
|
"info",
|
||||||
"[ECC] Remember to review changes before pushing: git diff origin/main...HEAD"
|
"[ECC] Remember to review changes before pushing: git diff origin/main...HEAD"
|
||||||
)
|
)
|
||||||
@@ -135,7 +138,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
!filePath.includes("LICENSE") &&
|
!filePath.includes("LICENSE") &&
|
||||||
!filePath.includes("CONTRIBUTING")
|
!filePath.includes("CONTRIBUTING")
|
||||||
) {
|
) {
|
||||||
client.app.log(
|
log(
|
||||||
"warn",
|
"warn",
|
||||||
`[ECC] Creating ${filePath} - consider if this documentation is necessary`
|
`[ECC] Creating ${filePath} - consider if this documentation is necessary`
|
||||||
)
|
)
|
||||||
@@ -150,7 +153,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
cmd.match(/^cargo\s+(build|test|run)/) ||
|
cmd.match(/^cargo\s+(build|test|run)/) ||
|
||||||
cmd.match(/^go\s+(build|test|run)/)
|
cmd.match(/^go\s+(build|test|run)/)
|
||||||
) {
|
) {
|
||||||
client.app.log(
|
log(
|
||||||
"info",
|
"info",
|
||||||
"[ECC] Long-running command detected - consider using background execution"
|
"[ECC] Long-running command detected - consider using background execution"
|
||||||
)
|
)
|
||||||
@@ -166,13 +169,13 @@ export const ECCHooksPlugin = async ({
|
|||||||
* Action: Loads context and displays welcome message
|
* Action: Loads context and displays welcome message
|
||||||
*/
|
*/
|
||||||
"session.created": async () => {
|
"session.created": async () => {
|
||||||
client.app.log("info", "[ECC] Session started - Everything Claude Code hooks active")
|
log("info", "[ECC] Session started - Everything Claude Code hooks active")
|
||||||
|
|
||||||
// Check for project-specific context files
|
// Check for project-specific context files
|
||||||
try {
|
try {
|
||||||
const hasClaudeMd = await $`test -f ${worktree}/CLAUDE.md && echo "yes"`.text()
|
const hasClaudeMd = await $`test -f ${worktree}/CLAUDE.md && echo "yes"`.text()
|
||||||
if (hasClaudeMd.trim() === "yes") {
|
if (hasClaudeMd.trim() === "yes") {
|
||||||
client.app.log("info", "[ECC] Found CLAUDE.md - loading project context")
|
log("info", "[ECC] Found CLAUDE.md - loading project context")
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// No CLAUDE.md found
|
// No CLAUDE.md found
|
||||||
@@ -189,7 +192,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
"session.idle": async () => {
|
"session.idle": async () => {
|
||||||
if (editedFiles.size === 0) return
|
if (editedFiles.size === 0) return
|
||||||
|
|
||||||
client.app.log("info", "[ECC] Session idle - running console.log audit")
|
log("info", "[ECC] Session idle - running console.log audit")
|
||||||
|
|
||||||
let totalConsoleLogCount = 0
|
let totalConsoleLogCount = 0
|
||||||
const filesWithConsoleLogs: string[] = []
|
const filesWithConsoleLogs: string[] = []
|
||||||
@@ -210,16 +213,16 @@ export const ECCHooksPlugin = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (totalConsoleLogCount > 0) {
|
if (totalConsoleLogCount > 0) {
|
||||||
client.app.log(
|
log(
|
||||||
"warn",
|
"warn",
|
||||||
`[ECC] Audit: ${totalConsoleLogCount} console.log statement(s) in ${filesWithConsoleLogs.length} file(s)`
|
`[ECC] Audit: ${totalConsoleLogCount} console.log statement(s) in ${filesWithConsoleLogs.length} file(s)`
|
||||||
)
|
)
|
||||||
filesWithConsoleLogs.forEach((f) =>
|
filesWithConsoleLogs.forEach((f) =>
|
||||||
client.app.log("warn", ` - ${f}`)
|
log("warn", ` - ${f}`)
|
||||||
)
|
)
|
||||||
client.app.log("warn", "[ECC] Remove console.log statements before committing")
|
log("warn", "[ECC] Remove console.log statements before committing")
|
||||||
} else {
|
} else {
|
||||||
client.app.log("info", "[ECC] Audit passed: No console.log statements found")
|
log("info", "[ECC] Audit passed: No console.log statements found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Desktop notification (macOS)
|
// Desktop notification (macOS)
|
||||||
@@ -241,7 +244,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
* Action: Final cleanup and state saving
|
* Action: Final cleanup and state saving
|
||||||
*/
|
*/
|
||||||
"session.deleted": async () => {
|
"session.deleted": async () => {
|
||||||
client.app.log("info", "[ECC] Session ended - cleaning up")
|
log("info", "[ECC] Session ended - cleaning up")
|
||||||
editedFiles.clear()
|
editedFiles.clear()
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -266,7 +269,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
* Action: Logs for audit trail
|
* Action: Logs for audit trail
|
||||||
*/
|
*/
|
||||||
"permission.asked": async (event: { tool: string; args: unknown }) => {
|
"permission.asked": async (event: { tool: string; args: unknown }) => {
|
||||||
client.app.log("info", `[ECC] Permission requested for: ${event.tool}`)
|
log("info", `[ECC] Permission requested for: ${event.tool}`)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,7 +283,7 @@ export const ECCHooksPlugin = async ({
|
|||||||
const completed = event.todos.filter((t) => t.done).length
|
const completed = event.todos.filter((t) => t.done).length
|
||||||
const total = event.todos.length
|
const total = event.todos.length
|
||||||
if (total > 0) {
|
if (total > 0) {
|
||||||
client.app.log("info", `[ECC] Progress: ${completed}/${total} tasks completed`)
|
log("info", `[ECC] Progress: ${completed}/${total} tasks completed`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* while taking advantage of OpenCode's more sophisticated 20+ event types.
|
* while taking advantage of OpenCode's more sophisticated 20+ event types.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export { ECCHooksPlugin, default } from "./ecc-hooks"
|
export { ECCHooksPlugin, default } from "./ecc-hooks.js"
|
||||||
|
|
||||||
// Re-export for named imports
|
// Re-export for named imports
|
||||||
export * from "./ecc-hooks"
|
export * from "./ecc-hooks.js"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Supports common coverage report formats.
|
* Supports common coverage report formats.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { tool } from "@opencode-ai/plugin"
|
import { tool } from "@opencode-ai/plugin/tool"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as fs from "fs"
|
import * as fs from "fs"
|
||||||
|
|
||||||
@@ -58,13 +58,13 @@ export default tool({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!coverageData) {
|
if (!coverageData) {
|
||||||
return {
|
return JSON.stringify({
|
||||||
success: false,
|
success: false,
|
||||||
error: "No coverage report found",
|
error: "No coverage report found",
|
||||||
suggestion:
|
suggestion:
|
||||||
"Run tests with coverage first: npm test -- --coverage",
|
"Run tests with coverage first: npm test -- --coverage",
|
||||||
searchedPaths: coveragePaths,
|
searchedPaths: coveragePaths,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const passed = coverageData.total.percentage >= threshold
|
const passed = coverageData.total.percentage >= threshold
|
||||||
@@ -96,7 +96,7 @@ export default tool({
|
|||||||
.join("\n")}`
|
.join("\n")}`
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return JSON.stringify(result)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Automatically detects the package manager and test framework.
|
* Automatically detects the package manager and test framework.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { tool } from "@opencode-ai/plugin"
|
import { tool } from "@opencode-ai/plugin/tool"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as fs from "fs"
|
import * as fs from "fs"
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ export default tool({
|
|||||||
|
|
||||||
const command = cmd.join(" ")
|
const command = cmd.join(" ")
|
||||||
|
|
||||||
return {
|
return JSON.stringify({
|
||||||
command,
|
command,
|
||||||
packageManager,
|
packageManager,
|
||||||
testFramework,
|
testFramework,
|
||||||
@@ -93,7 +93,7 @@ export default tool({
|
|||||||
updateSnapshots: updateSnapshots || false,
|
updateSnapshots: updateSnapshots || false,
|
||||||
},
|
},
|
||||||
instructions: `Run this command to execute tests:\n\n${command}`,
|
instructions: `Run this command to execute tests:\n\n${command}`,
|
||||||
}
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
* The regex patterns below are used to DETECT potential issues in user code.
|
* The regex patterns below are used to DETECT potential issues in user code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { tool } from "@opencode-ai/plugin"
|
import { tool } from "@opencode-ai/plugin/tool"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as fs from "fs"
|
import * as fs from "fs"
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ export default tool({
|
|||||||
// Generate recommendations
|
// Generate recommendations
|
||||||
results.recommendations = generateRecommendations(results)
|
results.recommendations = generateRecommendations(results)
|
||||||
|
|
||||||
return results
|
return JSON.stringify(results)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||

|

|
||||||

|

|
||||||
|
|
||||||
> **41K+ stars** | **5K+ forks** | **22 contributors** | **6 languages supported**
|
> **42K+ stars** | **5K+ forks** | **24 contributors** | **6 languages supported**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user