karajan-code 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karajan-code",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "Local multi-agent coding orchestrator with TDD, SonarQube, and code review pipeline",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0",
@@ -2,6 +2,7 @@ import { ClaudeAgent } from "./claude-agent.js";
2
2
  import { CodexAgent } from "./codex-agent.js";
3
3
  import { GeminiAgent } from "./gemini-agent.js";
4
4
  import { AiderAgent } from "./aider-agent.js";
5
+ import { OpenCodeAgent } from "./opencode-agent.js";
5
6
 
6
7
  const agentRegistry = new Map();
7
8
 
@@ -38,3 +39,4 @@ registerAgent("claude", ClaudeAgent, { bin: "claude", installUrl: "https://docs.
38
39
  registerAgent("codex", CodexAgent, { bin: "codex", installUrl: "https://developers.openai.com/codex/cli" });
39
40
  registerAgent("gemini", GeminiAgent, { bin: "gemini", installUrl: "https://github.com/google-gemini/gemini-cli" });
40
41
  registerAgent("aider", AiderAgent, { bin: "aider", installUrl: "https://aider.chat/docs/install.html" });
42
+ registerAgent("opencode", OpenCodeAgent, { bin: "opencode", installUrl: "https://opencode.ai" });
@@ -60,3 +60,4 @@ registerModel("gemini", { provider: "google", pricing: { input_per_million: 1.25
60
60
  registerModel("gemini/pro", { provider: "google", pricing: { input_per_million: 1.25, output_per_million: 5 } });
61
61
  registerModel("gemini/flash", { provider: "google", pricing: { input_per_million: 0.075, output_per_million: 0.3 } });
62
62
  registerModel("aider", { provider: "aider", pricing: { input_per_million: 3, output_per_million: 15 } });
63
+ registerModel("opencode", { provider: "opencode", pricing: { input_per_million: 0, output_per_million: 0 } });
@@ -0,0 +1,33 @@
1
+ import { BaseAgent } from "./base-agent.js";
2
+ import { runCommand } from "../utils/process.js";
3
+ import { resolveBin } from "./resolve-bin.js";
4
+
5
+ export class OpenCodeAgent extends BaseAgent {
6
+ async runTask(task) {
7
+ const role = task.role || "coder";
8
+ const args = ["run"];
9
+ const model = this.getRoleModel(role);
10
+ if (model) args.push("--model", model);
11
+ args.push(task.prompt);
12
+ const res = await runCommand(resolveBin("opencode"), args, {
13
+ onOutput: task.onOutput,
14
+ silenceTimeoutMs: task.silenceTimeoutMs,
15
+ timeout: task.timeoutMs
16
+ });
17
+ return { ok: res.exitCode === 0, output: res.stdout, error: res.stderr, exitCode: res.exitCode };
18
+ }
19
+
20
+ async reviewTask(task) {
21
+ const role = task.role || "reviewer";
22
+ const args = ["run", "--format", "json"];
23
+ const model = this.getRoleModel(role);
24
+ if (model) args.push("--model", model);
25
+ args.push(task.prompt);
26
+ const res = await runCommand(resolveBin("opencode"), args, {
27
+ onOutput: task.onOutput,
28
+ silenceTimeoutMs: task.silenceTimeoutMs,
29
+ timeout: task.timeoutMs
30
+ });
31
+ return { ok: res.exitCode === 0, output: res.stdout, error: res.stderr, exitCode: res.exitCode };
32
+ }
33
+ }
@@ -5,7 +5,8 @@ const KNOWN_AGENTS = [
5
5
  { name: "claude", install: "npm install -g @anthropic-ai/claude-code" },
6
6
  { name: "codex", install: "npm install -g @openai/codex" },
7
7
  { name: "gemini", install: "npm install -g @anthropic-ai/gemini-code (or check Gemini CLI docs)" },
8
- { name: "aider", install: "pip install aider-chat" }
8
+ { name: "aider", install: "pip install aider-chat" },
9
+ { name: "opencode", install: "curl -fsSL https://opencode.ai/install | bash (or see https://opencode.ai)" }
9
10
  ];
10
11
 
11
12
  export async function checkBinary(name, versionArg = "--version") {