karajan-code 1.2.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/LICENSE +21 -0
- package/README.md +441 -0
- package/docs/karajan-code-logo-small.png +0 -0
- package/package.json +60 -0
- package/scripts/install.js +898 -0
- package/scripts/install.sh +7 -0
- package/scripts/postinstall.js +117 -0
- package/scripts/setup-multi-instance.sh +150 -0
- package/src/activity-log.js +59 -0
- package/src/agents/aider-agent.js +25 -0
- package/src/agents/availability.js +32 -0
- package/src/agents/base-agent.js +27 -0
- package/src/agents/claude-agent.js +24 -0
- package/src/agents/codex-agent.js +27 -0
- package/src/agents/gemini-agent.js +25 -0
- package/src/agents/index.js +19 -0
- package/src/agents/resolve-bin.js +60 -0
- package/src/cli.js +200 -0
- package/src/commands/code.js +32 -0
- package/src/commands/config.js +74 -0
- package/src/commands/doctor.js +155 -0
- package/src/commands/init.js +181 -0
- package/src/commands/plan.js +67 -0
- package/src/commands/report.js +340 -0
- package/src/commands/resume.js +39 -0
- package/src/commands/review.js +26 -0
- package/src/commands/roles.js +117 -0
- package/src/commands/run.js +91 -0
- package/src/commands/scan.js +18 -0
- package/src/commands/sonar.js +53 -0
- package/src/config.js +322 -0
- package/src/git/automation.js +100 -0
- package/src/mcp/progress.js +69 -0
- package/src/mcp/run-kj.js +87 -0
- package/src/mcp/server-handlers.js +259 -0
- package/src/mcp/server.js +37 -0
- package/src/mcp/tool-arg-normalizers.js +16 -0
- package/src/mcp/tools.js +184 -0
- package/src/orchestrator.js +1277 -0
- package/src/planning-game/adapter.js +105 -0
- package/src/planning-game/client.js +81 -0
- package/src/prompts/coder.js +60 -0
- package/src/prompts/planner.js +26 -0
- package/src/prompts/reviewer.js +45 -0
- package/src/repeat-detector.js +77 -0
- package/src/review/diff-generator.js +22 -0
- package/src/review/parser.js +93 -0
- package/src/review/profiles.js +66 -0
- package/src/review/schema.js +31 -0
- package/src/review/tdd-policy.js +57 -0
- package/src/roles/base-role.js +127 -0
- package/src/roles/coder-role.js +60 -0
- package/src/roles/commiter-role.js +94 -0
- package/src/roles/index.js +12 -0
- package/src/roles/planner-role.js +81 -0
- package/src/roles/refactorer-role.js +66 -0
- package/src/roles/researcher-role.js +134 -0
- package/src/roles/reviewer-role.js +132 -0
- package/src/roles/security-role.js +128 -0
- package/src/roles/solomon-role.js +199 -0
- package/src/roles/sonar-role.js +65 -0
- package/src/roles/tester-role.js +114 -0
- package/src/roles/triage-role.js +128 -0
- package/src/session-store.js +80 -0
- package/src/sonar/api.js +78 -0
- package/src/sonar/enforcer.js +19 -0
- package/src/sonar/manager.js +163 -0
- package/src/sonar/project-key.js +83 -0
- package/src/sonar/scanner.js +267 -0
- package/src/utils/agent-detect.js +32 -0
- package/src/utils/budget.js +123 -0
- package/src/utils/display.js +346 -0
- package/src/utils/events.js +23 -0
- package/src/utils/fs.js +19 -0
- package/src/utils/git.js +101 -0
- package/src/utils/logger.js +86 -0
- package/src/utils/paths.js +18 -0
- package/src/utils/pricing.js +28 -0
- package/src/utils/process.js +67 -0
- package/src/utils/wizard.js +41 -0
- package/templates/coder-rules.md +24 -0
- package/templates/docker-compose.sonar.yml +60 -0
- package/templates/kj.config.yml +82 -0
- package/templates/review-rules.md +11 -0
- package/templates/roles/coder.md +42 -0
- package/templates/roles/commiter.md +44 -0
- package/templates/roles/planner.md +45 -0
- package/templates/roles/refactorer.md +39 -0
- package/templates/roles/researcher.md +37 -0
- package/templates/roles/reviewer-paranoid.md +38 -0
- package/templates/roles/reviewer-relaxed.md +34 -0
- package/templates/roles/reviewer-strict.md +37 -0
- package/templates/roles/reviewer.md +55 -0
- package/templates/roles/security.md +54 -0
- package/templates/roles/solomon.md +106 -0
- package/templates/roles/sonar.md +49 -0
- package/templates/roles/tester.md +41 -0
- package/templates/roles/triage.md +25 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server handler logic.
|
|
3
|
+
* Extracted from server.js for testability.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { EventEmitter } from "node:events";
|
|
7
|
+
import { runKjCommand } from "./run-kj.js";
|
|
8
|
+
import { normalizePlanArgs } from "./tool-arg-normalizers.js";
|
|
9
|
+
import { buildProgressHandler, buildProgressNotifier } from "./progress.js";
|
|
10
|
+
import { runFlow, resumeFlow } from "../orchestrator.js";
|
|
11
|
+
import { loadConfig, applyRunOverrides, validateConfig, resolveRole } from "../config.js";
|
|
12
|
+
import { createLogger } from "../utils/logger.js";
|
|
13
|
+
import { assertAgentsAvailable } from "../agents/availability.js";
|
|
14
|
+
|
|
15
|
+
export function asObject(value) {
|
|
16
|
+
if (value && typeof value === "object") return value;
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function responseText(payload) {
|
|
21
|
+
return {
|
|
22
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function failPayload(message, details = {}) {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
error: message,
|
|
30
|
+
...details
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function classifyError(error) {
|
|
35
|
+
const msg = error?.message || String(error);
|
|
36
|
+
const lower = msg.toLowerCase();
|
|
37
|
+
|
|
38
|
+
if (lower.includes("sonar") && (lower.includes("connect") || lower.includes("econnrefused") || lower.includes("not available") || lower.includes("not running"))) {
|
|
39
|
+
return {
|
|
40
|
+
category: "sonar_unavailable",
|
|
41
|
+
suggestion: "SonarQube is not reachable. Try: kj_init to set up SonarQube, or run 'docker start sonarqube' if already installed. Use --no-sonar to skip SonarQube."
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (lower.includes("401") || lower.includes("unauthorized") || lower.includes("invalid token")) {
|
|
46
|
+
return {
|
|
47
|
+
category: "auth_error",
|
|
48
|
+
suggestion: "Authentication failed. Regenerate the SonarQube token and update it via kj_init or in ~/.karajan/kj.config.yml under sonarqube.token."
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (lower.includes("config") && (lower.includes("missing") || lower.includes("not found") || lower.includes("invalid"))) {
|
|
53
|
+
return {
|
|
54
|
+
category: "config_error",
|
|
55
|
+
suggestion: "Configuration issue detected. Run kj_doctor to diagnose, or kj_init to create a fresh config."
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (lower.includes("missing provider") || lower.includes("not found") && (lower.includes("claude") || lower.includes("codex") || lower.includes("gemini") || lower.includes("aider"))) {
|
|
60
|
+
return {
|
|
61
|
+
category: "agent_missing",
|
|
62
|
+
suggestion: "Required agent CLI not found. Run kj_doctor to check which agents are installed and get installation instructions."
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (lower.includes("timed out") || lower.includes("timeout")) {
|
|
67
|
+
return {
|
|
68
|
+
category: "timeout",
|
|
69
|
+
suggestion: "The operation timed out. Try increasing timeoutMs or maxIterationMinutes. If a scan timed out, check SonarQube health."
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (lower.includes("not a git repository")) {
|
|
74
|
+
return {
|
|
75
|
+
category: "git_error",
|
|
76
|
+
suggestion: "Current directory is not a git repository. Navigate to your project root or initialize git with 'git init'."
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { category: "unknown", suggestion: null };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function enrichedFailPayload(error, toolName) {
|
|
84
|
+
const msg = error?.message || String(error);
|
|
85
|
+
const { category, suggestion } = classifyError(error);
|
|
86
|
+
const payload = {
|
|
87
|
+
ok: false,
|
|
88
|
+
error: msg,
|
|
89
|
+
tool: toolName,
|
|
90
|
+
category
|
|
91
|
+
};
|
|
92
|
+
if (suggestion) payload.suggestion = suggestion;
|
|
93
|
+
return payload;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function buildConfig(options) {
|
|
97
|
+
const { config } = await loadConfig();
|
|
98
|
+
const merged = applyRunOverrides(config, options || {});
|
|
99
|
+
validateConfig(merged, "run");
|
|
100
|
+
return merged;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function buildAskQuestion(server) {
|
|
104
|
+
return async (question) => {
|
|
105
|
+
try {
|
|
106
|
+
const result = await server.elicitInput({
|
|
107
|
+
message: question,
|
|
108
|
+
requestedSchema: {
|
|
109
|
+
type: "object",
|
|
110
|
+
properties: {
|
|
111
|
+
answer: { type: "string", description: "Your response" }
|
|
112
|
+
},
|
|
113
|
+
required: ["answer"]
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return result.action === "accept" ? result.content?.answer || null : null;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export async function handleRunDirect(a, server, extra) {
|
|
124
|
+
const config = await buildConfig(a);
|
|
125
|
+
const logger = createLogger(config.output.log_level, "mcp");
|
|
126
|
+
|
|
127
|
+
const requiredProviders = [
|
|
128
|
+
resolveRole(config, "coder").provider,
|
|
129
|
+
config.reviewer_options?.fallback_reviewer
|
|
130
|
+
];
|
|
131
|
+
if (config.pipeline?.reviewer?.enabled !== false) {
|
|
132
|
+
requiredProviders.push(resolveRole(config, "reviewer").provider);
|
|
133
|
+
}
|
|
134
|
+
if (config.pipeline?.triage?.enabled) requiredProviders.push(resolveRole(config, "triage").provider);
|
|
135
|
+
if (config.pipeline?.planner?.enabled) requiredProviders.push(resolveRole(config, "planner").provider);
|
|
136
|
+
if (config.pipeline?.refactorer?.enabled) requiredProviders.push(resolveRole(config, "refactorer").provider);
|
|
137
|
+
if (config.pipeline?.researcher?.enabled) requiredProviders.push(resolveRole(config, "researcher").provider);
|
|
138
|
+
if (config.pipeline?.tester?.enabled) requiredProviders.push(resolveRole(config, "tester").provider);
|
|
139
|
+
if (config.pipeline?.security?.enabled) requiredProviders.push(resolveRole(config, "security").provider);
|
|
140
|
+
await assertAgentsAvailable(requiredProviders);
|
|
141
|
+
|
|
142
|
+
const emitter = new EventEmitter();
|
|
143
|
+
emitter.on("progress", buildProgressHandler(server));
|
|
144
|
+
const progressNotifier = buildProgressNotifier(extra);
|
|
145
|
+
if (progressNotifier) emitter.on("progress", progressNotifier);
|
|
146
|
+
|
|
147
|
+
const askQuestion = buildAskQuestion(server);
|
|
148
|
+
const result = await runFlow({ task: a.task, config, logger, flags: a, emitter, askQuestion });
|
|
149
|
+
return { ok: !result.paused && (result.approved !== false), ...result };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function handleResumeDirect(a, server, extra) {
|
|
153
|
+
const config = await buildConfig(a);
|
|
154
|
+
const logger = createLogger(config.output.log_level, "mcp");
|
|
155
|
+
|
|
156
|
+
const emitter = new EventEmitter();
|
|
157
|
+
emitter.on("progress", buildProgressHandler(server));
|
|
158
|
+
const progressNotifier = buildProgressNotifier(extra);
|
|
159
|
+
if (progressNotifier) emitter.on("progress", progressNotifier);
|
|
160
|
+
|
|
161
|
+
const askQuestion = buildAskQuestion(server);
|
|
162
|
+
const result = await resumeFlow({
|
|
163
|
+
sessionId: a.sessionId,
|
|
164
|
+
answer: a.answer || null,
|
|
165
|
+
config,
|
|
166
|
+
logger,
|
|
167
|
+
flags: a,
|
|
168
|
+
emitter,
|
|
169
|
+
askQuestion
|
|
170
|
+
});
|
|
171
|
+
return { ok: true, ...result };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export async function handleToolCall(name, args, server, extra) {
|
|
175
|
+
const a = asObject(args);
|
|
176
|
+
|
|
177
|
+
if (name === "kj_init") {
|
|
178
|
+
return runKjCommand({ command: "init", options: a });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (name === "kj_doctor") {
|
|
182
|
+
return runKjCommand({ command: "doctor", options: a });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (name === "kj_config") {
|
|
186
|
+
return runKjCommand({
|
|
187
|
+
command: "config",
|
|
188
|
+
commandArgs: a.json ? ["--json"] : [],
|
|
189
|
+
options: a
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (name === "kj_scan") {
|
|
194
|
+
return runKjCommand({ command: "scan", options: a });
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (name === "kj_roles") {
|
|
198
|
+
const action = a.action || "list";
|
|
199
|
+
const commandArgs = [action];
|
|
200
|
+
if (action === "show" && a.roleName) commandArgs.push(a.roleName);
|
|
201
|
+
return runKjCommand({
|
|
202
|
+
command: "roles",
|
|
203
|
+
commandArgs,
|
|
204
|
+
options: a
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (name === "kj_report") {
|
|
209
|
+
const commandArgs = [];
|
|
210
|
+
if (a.list) commandArgs.push("--list");
|
|
211
|
+
if (a.sessionId) commandArgs.push("--session-id", String(a.sessionId));
|
|
212
|
+
if (a.format) commandArgs.push("--format", String(a.format));
|
|
213
|
+
if (a.trace) commandArgs.push("--trace");
|
|
214
|
+
if (a.currency) commandArgs.push("--currency", String(a.currency));
|
|
215
|
+
return runKjCommand({
|
|
216
|
+
command: "report",
|
|
217
|
+
commandArgs,
|
|
218
|
+
options: a
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (name === "kj_resume") {
|
|
223
|
+
if (!a.sessionId) {
|
|
224
|
+
return failPayload("Missing required field: sessionId");
|
|
225
|
+
}
|
|
226
|
+
return handleResumeDirect(a, server, extra);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (name === "kj_run") {
|
|
230
|
+
if (!a.task) {
|
|
231
|
+
return failPayload("Missing required field: task");
|
|
232
|
+
}
|
|
233
|
+
return handleRunDirect(a, server, extra);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (name === "kj_code") {
|
|
237
|
+
if (!a.task) {
|
|
238
|
+
return failPayload("Missing required field: task");
|
|
239
|
+
}
|
|
240
|
+
return runKjCommand({ command: "code", commandArgs: [a.task], options: a });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (name === "kj_review") {
|
|
244
|
+
if (!a.task) {
|
|
245
|
+
return failPayload("Missing required field: task");
|
|
246
|
+
}
|
|
247
|
+
return runKjCommand({ command: "review", commandArgs: [a.task], options: a });
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (name === "kj_plan") {
|
|
251
|
+
if (!a.task) {
|
|
252
|
+
return failPayload("Missing required field: task");
|
|
253
|
+
}
|
|
254
|
+
const options = normalizePlanArgs(a);
|
|
255
|
+
return runKjCommand({ command: "plan", commandArgs: [a.task], options });
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return failPayload(`Unknown tool: ${name}`);
|
|
259
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { tools } from "./tools.js";
|
|
6
|
+
import { handleToolCall, responseText, enrichedFailPayload } from "./server-handlers.js";
|
|
7
|
+
|
|
8
|
+
const server = new Server(
|
|
9
|
+
{
|
|
10
|
+
name: "karajan-mcp",
|
|
11
|
+
version: "1.0.0"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
capabilities: {
|
|
15
|
+
tools: {},
|
|
16
|
+
logging: {},
|
|
17
|
+
elicitation: {}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
|
|
23
|
+
|
|
24
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
25
|
+
const name = request.params?.name;
|
|
26
|
+
const args = request.params?.arguments || {};
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const result = await handleToolCall(name, args, server, extra);
|
|
30
|
+
return responseText(result);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return responseText(enrichedFailPayload(error, name));
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const transport = new StdioServerTransport();
|
|
37
|
+
await server.connect(transport);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function normalizePlanArgs(args = {}) {
|
|
2
|
+
const normalized = { ...args };
|
|
3
|
+
|
|
4
|
+
if (!normalized.planner && normalized.coder) {
|
|
5
|
+
normalized.planner = normalized.coder;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (!normalized.plannerModel && normalized.coderModel) {
|
|
9
|
+
normalized.plannerModel = normalized.coderModel;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
delete normalized.coder;
|
|
13
|
+
delete normalized.coderModel;
|
|
14
|
+
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
package/src/mcp/tools.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
export const tools = [
|
|
2
|
+
{
|
|
3
|
+
name: "kj_init",
|
|
4
|
+
description: "Initialize karajan-code config, review rules, and SonarQube",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
kjHome: { type: "string", description: "Optional KJ_HOME directory" },
|
|
9
|
+
timeoutMs: { type: "number", description: "Optional command timeout in ms" }
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "kj_doctor",
|
|
15
|
+
description: "Check system dependencies and agent CLIs",
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
kjHome: { type: "string" },
|
|
20
|
+
timeoutMs: { type: "number" }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "kj_config",
|
|
26
|
+
description: "Show kj configuration",
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
json: { type: "boolean" },
|
|
31
|
+
kjHome: { type: "string" }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "kj_scan",
|
|
37
|
+
description: "Run SonarQube scan for current project",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
kjHome: { type: "string" },
|
|
42
|
+
sonarToken: { type: "string" },
|
|
43
|
+
timeoutMs: { type: "number" }
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "kj_run",
|
|
49
|
+
description:
|
|
50
|
+
"Run full coder -> sonar -> reviewer loop. Sends real-time progress notifications via MCP logging. May return paused state with a question if fail-fast is triggered.",
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: "object",
|
|
53
|
+
required: ["task"],
|
|
54
|
+
properties: {
|
|
55
|
+
task: { type: "string", description: "Task description for the coder (can include a Planning Game card ID like KJC-TSK-0042)" },
|
|
56
|
+
pgTask: { type: "string", description: "Planning Game card ID (e.g., KJC-TSK-0042). If provided, fetches full card details as task context and updates card status on completion." },
|
|
57
|
+
pgProject: { type: "string", description: "Planning Game project ID (e.g., 'Karajan Code'). Required when pgTask is used." },
|
|
58
|
+
planner: { type: "string" },
|
|
59
|
+
coder: { type: "string" },
|
|
60
|
+
reviewer: { type: "string" },
|
|
61
|
+
refactorer: { type: "string" },
|
|
62
|
+
plannerModel: { type: "string" },
|
|
63
|
+
coderModel: { type: "string" },
|
|
64
|
+
reviewerModel: { type: "string" },
|
|
65
|
+
refactorerModel: { type: "string" },
|
|
66
|
+
enablePlanner: { type: "boolean" },
|
|
67
|
+
enableReviewer: { type: "boolean" },
|
|
68
|
+
enableRefactorer: { type: "boolean" },
|
|
69
|
+
enableResearcher: { type: "boolean" },
|
|
70
|
+
enableTester: { type: "boolean" },
|
|
71
|
+
enableSecurity: { type: "boolean" },
|
|
72
|
+
enableTriage: { type: "boolean" },
|
|
73
|
+
enableSerena: { type: "boolean" },
|
|
74
|
+
reviewerFallback: { type: "string" },
|
|
75
|
+
reviewerRetries: { type: "number" },
|
|
76
|
+
mode: { type: "string" },
|
|
77
|
+
maxIterations: { type: "number" },
|
|
78
|
+
maxIterationMinutes: { type: "number" },
|
|
79
|
+
maxTotalMinutes: { type: "number" },
|
|
80
|
+
baseBranch: { type: "string" },
|
|
81
|
+
baseRef: { type: "string" },
|
|
82
|
+
methodology: { type: "string", enum: ["tdd", "standard"] },
|
|
83
|
+
autoCommit: { type: "boolean" },
|
|
84
|
+
autoPush: { type: "boolean" },
|
|
85
|
+
autoPr: { type: "boolean" },
|
|
86
|
+
autoRebase: { type: "boolean" },
|
|
87
|
+
branchPrefix: { type: "string" },
|
|
88
|
+
noSonar: { type: "boolean" },
|
|
89
|
+
kjHome: { type: "string" },
|
|
90
|
+
sonarToken: { type: "string" },
|
|
91
|
+
timeoutMs: { type: "number" }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "kj_resume",
|
|
97
|
+
description:
|
|
98
|
+
"Resume a paused session by ID. Provide an answer to the question that caused the pause. Sends real-time progress notifications via MCP logging.",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
required: ["sessionId"],
|
|
102
|
+
properties: {
|
|
103
|
+
sessionId: { type: "string", description: "Session ID to resume" },
|
|
104
|
+
answer: { type: "string", description: "Answer to the question that caused the pause" },
|
|
105
|
+
kjHome: { type: "string" }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "kj_report",
|
|
111
|
+
description: "Read latest or list session reports. Use trace=true for chronological stage-by-stage breakdown with timing and token usage.",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
type: "object",
|
|
114
|
+
properties: {
|
|
115
|
+
list: { type: "boolean" },
|
|
116
|
+
sessionId: { type: "string" },
|
|
117
|
+
format: { type: "string", enum: ["text", "json"] },
|
|
118
|
+
trace: { type: "boolean", description: "Show chronological trace of all pipeline stages" },
|
|
119
|
+
currency: { type: "string", enum: ["usd", "eur"], description: "Display costs in this currency" },
|
|
120
|
+
kjHome: { type: "string" }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "kj_roles",
|
|
126
|
+
description: "List pipeline roles or show the template instructions for a specific role. Use action='list' to see all roles with their provider and status. Use action='show' with roleName to read the .md template.",
|
|
127
|
+
inputSchema: {
|
|
128
|
+
type: "object",
|
|
129
|
+
properties: {
|
|
130
|
+
action: { type: "string", enum: ["list", "show"], description: "Action: list all roles or show a specific role template" },
|
|
131
|
+
roleName: { type: "string", description: "Role name to show (e.g. coder, reviewer, triage, reviewer-paranoid)" },
|
|
132
|
+
kjHome: { type: "string" }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "kj_code",
|
|
138
|
+
description: "Run coder-only mode",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
type: "object",
|
|
141
|
+
required: ["task"],
|
|
142
|
+
properties: {
|
|
143
|
+
task: { type: "string" },
|
|
144
|
+
coder: { type: "string" },
|
|
145
|
+
coderModel: { type: "string" },
|
|
146
|
+
kjHome: { type: "string" },
|
|
147
|
+
timeoutMs: { type: "number" }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "kj_review",
|
|
153
|
+
description: "Run reviewer-only mode against current diff",
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: "object",
|
|
156
|
+
required: ["task"],
|
|
157
|
+
properties: {
|
|
158
|
+
task: { type: "string" },
|
|
159
|
+
reviewer: { type: "string" },
|
|
160
|
+
reviewerModel: { type: "string" },
|
|
161
|
+
baseRef: { type: "string" },
|
|
162
|
+
kjHome: { type: "string" },
|
|
163
|
+
timeoutMs: { type: "number" }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "kj_plan",
|
|
169
|
+
description: "Generate implementation plan for a task",
|
|
170
|
+
inputSchema: {
|
|
171
|
+
type: "object",
|
|
172
|
+
required: ["task"],
|
|
173
|
+
properties: {
|
|
174
|
+
task: { type: "string" },
|
|
175
|
+
planner: { type: "string" },
|
|
176
|
+
plannerModel: { type: "string" },
|
|
177
|
+
coder: { type: "string", description: "Legacy alias for planner" },
|
|
178
|
+
coderModel: { type: "string", description: "Legacy alias for plannerModel" },
|
|
179
|
+
kjHome: { type: "string" },
|
|
180
|
+
timeoutMs: { type: "number" }
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
];
|