karajan-code 4.1.5 → 4.1.6
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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { BaseAgent } from "./base-agent.js";
|
|
2
|
+
import { resolveBin } from "./resolve-bin.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* GitHub Copilot CLI (@github/copilot, binary `copilot`) — KJC-TSK-0666.
|
|
6
|
+
* The seventh built-in agent, and the user-chosen third AI for solomon
|
|
7
|
+
* arbitration (gemini tier retired, Qwen OAuth free tier discontinued).
|
|
8
|
+
*
|
|
9
|
+
* Verified live against copilot 1.0.73:
|
|
10
|
+
* - `-p <prompt>` runs non-interactive; copilot has NO stdin prompt channel
|
|
11
|
+
* (stdin is treated as context, spawning an agentic run) — so the prompt
|
|
12
|
+
* travels as an argument. Same documented E2BIG limit as claude-agent
|
|
13
|
+
* (KJC-BUG-0121) for multi-hundred-KB diffs.
|
|
14
|
+
* - `--output-format json` emits JSONL; the final text lives in the
|
|
15
|
+
* `assistant.message` event's `data.content`, run metadata in `result`.
|
|
16
|
+
* - Default model routing is automatic and varies per run (haiku, gpt-5-mini
|
|
17
|
+
* observed) — pin it per role via `roles.<role>.model` when neutrality
|
|
18
|
+
* matters (e.g. a gemini-family model for solomon).
|
|
19
|
+
*/
|
|
20
|
+
export class CopilotAgent extends BaseAgent {
|
|
21
|
+
async runTask(task) {
|
|
22
|
+
// Coder mode IS an agentic run: file edits and shell need permissions.
|
|
23
|
+
return this._exec(task, this.getRoleModel(task.role || "coder"), ["--allow-all-tools"]);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async reviewTask(task) {
|
|
27
|
+
// Review/arbitration answers from the prompt alone — no tool grants, and
|
|
28
|
+
// an explicit no-tools instruction so copilot never stalls waiting for
|
|
29
|
+
// an approval that headless mode cannot give.
|
|
30
|
+
return this._exec(
|
|
31
|
+
{ ...task, prompt: `Do NOT use any tools. Answer directly from this prompt only.\n\n${task.prompt}` },
|
|
32
|
+
this.getRoleModel(task.role || "reviewer"),
|
|
33
|
+
[],
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async _exec(task, model, extraArgs) {
|
|
38
|
+
const args = ["-p", task.prompt, "--output-format", "json", "--no-color", ...extraArgs];
|
|
39
|
+
if (model) args.push("--model", model);
|
|
40
|
+
const res = await this.runCommand(resolveBin("copilot"), args, {
|
|
41
|
+
onOutput: task.onOutput,
|
|
42
|
+
silenceTimeoutMs: task.silenceTimeoutMs,
|
|
43
|
+
timeout: task.timeoutMs
|
|
44
|
+
});
|
|
45
|
+
const output = extractCopilotOutput(res.stdout);
|
|
46
|
+
return { ok: res.exitCode === 0, output: output ?? res.stdout, error: res.stderr, exitCode: res.exitCode };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Last `assistant.message` content from copilot's JSONL stream (null if none). */
|
|
51
|
+
export function extractCopilotOutput(stdout) {
|
|
52
|
+
if (!stdout) return null;
|
|
53
|
+
let content = null;
|
|
54
|
+
for (const line of stdout.split("\n")) {
|
|
55
|
+
const t = line.trim();
|
|
56
|
+
if (!t.startsWith("{")) continue;
|
|
57
|
+
try {
|
|
58
|
+
const obj = JSON.parse(t);
|
|
59
|
+
if (obj?.type === "assistant.message" && typeof obj?.data?.content === "string") {
|
|
60
|
+
content = obj.data.content;
|
|
61
|
+
}
|
|
62
|
+
} catch { /* non-JSON noise between events */ }
|
|
63
|
+
}
|
|
64
|
+
return content;
|
|
65
|
+
}
|
package/src/agents/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { GeminiAgent } from "./gemini-agent.js";
|
|
|
4
4
|
import { AiderAgent } from "./aider-agent.js";
|
|
5
5
|
import { OpenCodeAgent } from "./opencode-agent.js";
|
|
6
6
|
import { QwenAgent } from "./qwen-agent.js";
|
|
7
|
+
import { CopilotAgent } from "./copilot-agent.js";
|
|
7
8
|
|
|
8
9
|
const agentRegistry = new Map();
|
|
9
10
|
|
|
@@ -51,3 +52,4 @@ registerAgent("gemini", GeminiAgent, { bin: "gemini", installUrl: "https://githu
|
|
|
51
52
|
registerAgent("aider", AiderAgent, { bin: "aider", installUrl: "https://aider.chat/docs/install.html" });
|
|
52
53
|
registerAgent("opencode", OpenCodeAgent, { bin: "opencode", installUrl: "https://opencode.ai" });
|
|
53
54
|
registerAgent("qwen", QwenAgent, { bin: "qwen", installUrl: "https://github.com/QwenLM/qwen-code" });
|
|
55
|
+
registerAgent("copilot", CopilotAgent, { bin: "copilot", installUrl: "https://docs.github.com/copilot/how-tos/use-copilot-agents/use-copilot-cli" });
|
|
@@ -8,7 +8,8 @@ const KNOWN_AGENTS = [
|
|
|
8
8
|
{ name: "gemini", install: getInstallCommand("gemini") },
|
|
9
9
|
{ name: "aider", install: getInstallCommand("aider") },
|
|
10
10
|
{ name: "opencode", install: getInstallCommand("opencode") },
|
|
11
|
-
{ name: "qwen", install: getInstallCommand("qwen") }
|
|
11
|
+
{ name: "qwen", install: getInstallCommand("qwen") },
|
|
12
|
+
{ name: "copilot", install: getInstallCommand("copilot") }
|
|
12
13
|
];
|
|
13
14
|
|
|
14
15
|
export async function checkBinary(name, versionArg = "--version") {
|
package/src/utils/os-detect.js
CHANGED
|
@@ -56,6 +56,11 @@ const INSTALL_COMMANDS = {
|
|
|
56
56
|
linux: "npm install -g @qwen-code/qwen-code",
|
|
57
57
|
windows: "npm install -g @qwen-code/qwen-code"
|
|
58
58
|
},
|
|
59
|
+
copilot: {
|
|
60
|
+
macos: "npm install -g @github/copilot",
|
|
61
|
+
linux: "npm install -g @github/copilot",
|
|
62
|
+
windows: "npm install -g @github/copilot"
|
|
63
|
+
},
|
|
59
64
|
docker: {
|
|
60
65
|
macos: "brew install --cask docker",
|
|
61
66
|
linux: "sudo apt install docker.io docker-compose-v2 (or see https://docs.docker.com/engine/install/)",
|