Files
Elydora-Open-Source/sdks/go/cmd/elydora/plugins/opencode.go
T
雷电芽衣 bc6983a62e chore(oss): audit the server package and resync the SDK mirrors
Split the 657-line operation service into eor, submit, and verify
modules, add the AGENT_REVOKED and KEY_RETIRED codes the Backend already
emits, and condense every multi-line comment. Mirror Node, Python, and
Go at 2.1.0 with the deep-health 503, non-idempotent retry, rotation
grace, and path-encoding fixes. Document which routes and response
fields the self-hosted server does not provide.

Claude-Session: https://claude.ai/code/session_01Agoc9bRVE9KL7mmWtey9Vq
2026-09-03 20:48:20 -04:00

186 lines
5.0 KiB
Go

package plugins
import (
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"strconv"
)
var openCodeScriptPathPattern = regexp.MustCompile(`(?m)^const (GUARD_SCRIPT_PATH|HOOK_SCRIPT_PATH) = (".*");$`)
// OpenCodePlugin writes ~/.config/opencode/plugins/elydora-audit.mjs.
type OpenCodePlugin struct{}
func (p *OpenCodePlugin) configPath() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("resolve home directory: %w", err)
}
return filepath.Join(home, ".config", "opencode", "plugins", "elydora-audit.mjs"), nil
}
func (p *OpenCodePlugin) Install(config InstallConfig) error {
scriptPath, err := hookScriptPath(config.AgentID)
if err != nil {
return err
}
if config.HookScript != "" {
scriptPath = config.HookScript
}
if err := GenerateHookScript(scriptPath, config); err != nil {
return fmt.Errorf("generate hook script: %w", err)
}
guardPath := config.GuardScriptPath
if guardPath == "" {
guardPath, err = guardScriptPath(config.AgentID)
if err != nil {
return err
}
}
pluginFile, err := p.configPath()
if err != nil {
return err
}
dir := filepath.Dir(pluginFile)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("create directory %s: %w", dir, err)
}
content := buildOpenCodePlugin(scriptPath, guardPath)
if err := os.WriteFile(pluginFile, []byte(content), 0644); err != nil {
return fmt.Errorf("write %s: %w", pluginFile, err)
}
fmt.Printf("Installed Elydora hook for OpenCode at %s\n", pluginFile)
return nil
}
func buildOpenCodePlugin(scriptPath, guardPath string) string {
return fmt.Sprintf(`// Elydora audit plugin for OpenCode. Generated by the Elydora CLI; do not edit.
import { spawn, spawnSync } from 'node:child_process';
const GUARD_SCRIPT_PATH = %q;
const HOOK_SCRIPT_PATH = %q;
export const ElydoraAuditPlugin = async () => ({
"tool.execute.before": async () => {
const result = spawnSync('node', [GUARD_SCRIPT_PATH], {
timeout: 5000,
stdio: ['pipe', 'ignore', 'pipe'],
});
if (result.error) {
throw new Error('Elydora guard failed: ' + result.error.message);
}
if (result.status !== 0) {
const message = result.stderr?.toString().trim() || 'Elydora guard blocked tool execution.';
throw new Error(message);
}
},
"tool.execute.after": async (input) => {
const event = JSON.stringify({
tool_name: input?.tool || 'unknown',
tool_input: input?.args || {},
session_id: input?.sessionID || 'unknown',
});
const child = spawn('node', [HOOK_SCRIPT_PATH], {
detached: true,
stdio: ['pipe', 'ignore', 'ignore'],
});
child.on('error', (error) => {
console.error('[elydora] audit hook failed:', error.message);
});
child.stdin.end(event);
child.unref();
},
});
`, guardPath, scriptPath)
}
func (p *OpenCodePlugin) Uninstall(agentID string) error {
pluginFile, err := p.configPath()
if err != nil {
return err
}
if err := os.Remove(pluginFile); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("remove %s: %w", pluginFile, err)
}
if agentID != "" {
if err := removeAgentScripts(agentID); err != nil {
return err
}
}
fmt.Println("Uninstalled Elydora hook for OpenCode.")
return nil
}
func openCodeScriptPaths(data []byte, pluginFile string) (string, string, error) {
paths := map[string]string{}
for _, match := range openCodeScriptPathPattern.FindAllSubmatch(data, -1) {
value, err := strconv.Unquote(string(match[2]))
if err != nil {
return "", "", fmt.Errorf(
"OpenCode plugin at %s has an invalid %s: %w", pluginFile, match[1], err,
)
}
paths[string(match[1])] = value
}
guardPath, hasGuard := paths["GUARD_SCRIPT_PATH"]
hookPath, hasHook := paths["HOOK_SCRIPT_PATH"]
if !hasGuard || !hasHook {
return "", "", fmt.Errorf("OpenCode plugin at %s has no Elydora script paths", pluginFile)
}
return guardPath, hookPath, nil
}
func (p *OpenCodePlugin) Status() (PluginStatus, error) {
pluginFile, err := p.configPath()
if err != nil {
return PluginStatus{}, err
}
status := PluginStatus{
AgentName: "opencode",
DisplayName: "OpenCode",
ConfigPath: pluginFile,
}
data, err := os.ReadFile(pluginFile)
if errors.Is(err, os.ErrNotExist) {
return status, nil
}
if err != nil {
return status, fmt.Errorf("read %s: %w", pluginFile, err)
}
status.HookConfigured = true
guardPath, hookPath, err := openCodeScriptPaths(data, pluginFile)
if err != nil {
return status, err
}
guard, err := resolveManagedScript(guardPath, "guard.js")
if err != nil {
return status, err
}
audit, err := resolveManagedScript(hookPath, "hook.js")
if err != nil {
return status, err
}
if guard == nil || audit == nil || !sameManagedAgentID(guard.agentID, audit.agentID) {
return status, nil
}
status.HookScriptExists, err = managedRuntimePresent(managedRuntimeContract{
agentID: guard.agentID, guardPath: guard.scriptPath, auditPath: audit.scriptPath,
}, "opencode")
if err != nil {
return status, err
}
status.Installed = status.HookScriptExists
return status, nil
}