From 6c2e0eace8eb9955be6c632a18f89b1a28f1a9a9 Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Mon, 9 Feb 2026 01:32:22 -0800 Subject: [PATCH] fix: update opencode-ecc plugin for SDK v1.1.53 and refresh README stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) - Add .js extensions to relative imports for NodeNext module resolution - Update README star count (42K+) and contributor count (24) --- .opencode/plugins/ecc-hooks.ts | 47 ++++++++++++++++--------------- .opencode/plugins/index.ts | 4 +-- .opencode/tools/check-coverage.ts | 8 +++--- .opencode/tools/run-tests.ts | 6 ++-- .opencode/tools/security-audit.ts | 4 +-- README.md | 2 +- 6 files changed, 37 insertions(+), 34 deletions(-) diff --git a/.opencode/plugins/ecc-hooks.ts b/.opencode/plugins/ecc-hooks.ts index b64ffae..50d23bf 100644 --- a/.opencode/plugins/ecc-hooks.ts +++ b/.opencode/plugins/ecc-hooks.ts @@ -13,18 +13,21 @@ * - SessionEnd → session.deleted */ -import type { PluginContext } from "@opencode-ai/plugin" +import type { PluginInput } from "@opencode-ai/plugin" export const ECCHooksPlugin = async ({ - project, client, $, directory, worktree, -}: PluginContext) => { +}: PluginInput) => { // Track files edited in current session for console.log audit const editedFiles = new Set() + // 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 { /** * Prettier Auto-Format Hook @@ -41,7 +44,7 @@ export const ECCHooksPlugin = async ({ if (event.path.match(/\.(ts|tsx|js|jsx)$/)) { try { await $`prettier --write ${event.path} 2>/dev/null` - client.app.log("info", `[ECC] Formatted: ${event.path}`) + log("info", `[ECC] Formatted: ${event.path}`) } catch { // 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() if (result.trim()) { const lines = result.trim().split("\n").length - client.app.log( + log( "warn", `[ECC] console.log found in ${event.path} (${lines} occurrence${lines > 1 ? "s" : ""})` ) @@ -82,21 +85,21 @@ export const ECCHooksPlugin = async ({ ) { try { await $`npx tsc --noEmit 2>&1` - client.app.log("info", "[ECC] TypeScript check passed") + log("info", "[ECC] TypeScript check passed") } catch (error: unknown) { const err = error as { stdout?: string } - client.app.log("warn", "[ECC] TypeScript errors detected:") + log("warn", "[ECC] TypeScript errors detected:") if (err.stdout) { // Log first few errors 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 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.args?.toString().includes("git push") ) { - client.app.log( + log( "info", "[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("CONTRIBUTING") ) { - client.app.log( + log( "warn", `[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(/^go\s+(build|test|run)/) ) { - client.app.log( + log( "info", "[ECC] Long-running command detected - consider using background execution" ) @@ -166,13 +169,13 @@ export const ECCHooksPlugin = async ({ * Action: Loads context and displays welcome message */ "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 try { const hasClaudeMd = await $`test -f ${worktree}/CLAUDE.md && echo "yes"`.text() 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 { // No CLAUDE.md found @@ -189,7 +192,7 @@ export const ECCHooksPlugin = async ({ "session.idle": async () => { 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 const filesWithConsoleLogs: string[] = [] @@ -210,16 +213,16 @@ export const ECCHooksPlugin = async ({ } if (totalConsoleLogCount > 0) { - client.app.log( + log( "warn", `[ECC] Audit: ${totalConsoleLogCount} console.log statement(s) in ${filesWithConsoleLogs.length} file(s)` ) 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 { - 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) @@ -241,7 +244,7 @@ export const ECCHooksPlugin = async ({ * Action: Final cleanup and state saving */ "session.deleted": async () => { - client.app.log("info", "[ECC] Session ended - cleaning up") + log("info", "[ECC] Session ended - cleaning up") editedFiles.clear() }, @@ -266,7 +269,7 @@ export const ECCHooksPlugin = async ({ * Action: Logs for audit trail */ "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 total = event.todos.length if (total > 0) { - client.app.log("info", `[ECC] Progress: ${completed}/${total} tasks completed`) + log("info", `[ECC] Progress: ${completed}/${total} tasks completed`) } }, } diff --git a/.opencode/plugins/index.ts b/.opencode/plugins/index.ts index d19a91f..ca58596 100644 --- a/.opencode/plugins/index.ts +++ b/.opencode/plugins/index.ts @@ -6,7 +6,7 @@ * 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 -export * from "./ecc-hooks" +export * from "./ecc-hooks.js" diff --git a/.opencode/tools/check-coverage.ts b/.opencode/tools/check-coverage.ts index 00690ed..6465cb6 100644 --- a/.opencode/tools/check-coverage.ts +++ b/.opencode/tools/check-coverage.ts @@ -5,7 +5,7 @@ * 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 fs from "fs" @@ -58,13 +58,13 @@ export default tool({ } if (!coverageData) { - return { + return JSON.stringify({ success: false, error: "No coverage report found", suggestion: "Run tests with coverage first: npm test -- --coverage", searchedPaths: coveragePaths, - } + }) } const passed = coverageData.total.percentage >= threshold @@ -96,7 +96,7 @@ export default tool({ .join("\n")}` } - return result + return JSON.stringify(result) }, }) diff --git a/.opencode/tools/run-tests.ts b/.opencode/tools/run-tests.ts index ad74e58..3b17c90 100644 --- a/.opencode/tools/run-tests.ts +++ b/.opencode/tools/run-tests.ts @@ -5,7 +5,7 @@ * 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 fs from "fs" @@ -82,7 +82,7 @@ export default tool({ const command = cmd.join(" ") - return { + return JSON.stringify({ command, packageManager, testFramework, @@ -93,7 +93,7 @@ export default tool({ updateSnapshots: updateSnapshots || false, }, instructions: `Run this command to execute tests:\n\n${command}`, - } + }) }, }) diff --git a/.opencode/tools/security-audit.ts b/.opencode/tools/security-audit.ts index d587fb3..8f450f2 100644 --- a/.opencode/tools/security-audit.ts +++ b/.opencode/tools/security-audit.ts @@ -8,7 +8,7 @@ * 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 fs from "fs" @@ -102,7 +102,7 @@ export default tool({ // Generate recommendations results.recommendations = generateRecommendations(results) - return results + return JSON.stringify(results) }, }) diff --git a/README.md b/README.md index e2d9f72..3522144 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ![Java](https://img.shields.io/badge/-Java-ED8B00?logo=openjdk&logoColor=white) ![Markdown](https://img.shields.io/badge/-Markdown-000000?logo=markdown&logoColor=white) -> **41K+ stars** | **5K+ forks** | **22 contributors** | **6 languages supported** +> **42K+ stars** | **5K+ forks** | **24 contributors** | **6 languages supported** ---