@kody-ade/kody-engine 0.4.271 → 0.4.273
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/dist/bin/kody.js +262 -21
- package/package.json +1 -1
package/dist/bin/kody.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "@kody-ade/kody-engine",
|
|
18
|
-
version: "0.4.
|
|
18
|
+
version: "0.4.273",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -2146,15 +2146,7 @@ function dispatchWorkflow(workflowFile, capability, issueNumber, repoSlug) {
|
|
|
2146
2146
|
}
|
|
2147
2147
|
}
|
|
2148
2148
|
try {
|
|
2149
|
-
gh([
|
|
2150
|
-
"workflow",
|
|
2151
|
-
"run",
|
|
2152
|
-
workflowFile,
|
|
2153
|
-
"-f",
|
|
2154
|
-
`capability=${capability}`,
|
|
2155
|
-
"-f",
|
|
2156
|
-
`issue_number=${issueNumber}`
|
|
2157
|
-
]);
|
|
2149
|
+
gh(["workflow", "run", workflowFile, "-f", `capability=${capability}`, "-f", `issue_number=${issueNumber}`]);
|
|
2158
2150
|
return { ok: true };
|
|
2159
2151
|
} catch (err) {
|
|
2160
2152
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
@@ -2189,6 +2181,132 @@ function isDispatchGated(capability, mode) {
|
|
|
2189
2181
|
function trustRefusal(capabilitySlug) {
|
|
2190
2182
|
return `Not dispatched: capability \`${capabilitySlug ?? "?"}\` is in ASK mode (not trusted for autonomy). Do NOT retry the dispatch. Instead notify the operator (use recommend_to_operator, or rely on the tracking issue that already @-mentions them), then submit_state. To let this capability act on its own, grant it Auto on the dashboard Trust page.`;
|
|
2191
2183
|
}
|
|
2184
|
+
function dashboardBaseUrl() {
|
|
2185
|
+
const raw = process.env.KODY_CMS_DASHBOARD_URL?.trim() || process.env.KODY_DASHBOARD_URL?.trim() || process.env.DASHBOARD_URL?.trim() || "";
|
|
2186
|
+
if (!raw) return null;
|
|
2187
|
+
try {
|
|
2188
|
+
const parsed = new URL(raw);
|
|
2189
|
+
return parsed.origin;
|
|
2190
|
+
} catch {
|
|
2191
|
+
return null;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
function dashboardCmsToken() {
|
|
2195
|
+
return process.env.KODY_CMS_TOKEN?.trim() || process.env.KODY_DASHBOARD_TOKEN?.trim() || process.env.KODY_TOKEN?.trim() || process.env.GH_TOKEN?.trim() || process.env.GITHUB_TOKEN?.trim() || process.env.GH_PAT?.trim() || null;
|
|
2196
|
+
}
|
|
2197
|
+
function cmsHeaders(opts) {
|
|
2198
|
+
const token = dashboardCmsToken();
|
|
2199
|
+
const [owner, repo] = opts.repoSlug.split("/");
|
|
2200
|
+
if (!token) {
|
|
2201
|
+
return {
|
|
2202
|
+
ok: false,
|
|
2203
|
+
error: "missing_cms_token",
|
|
2204
|
+
message: "Set KODY_CMS_TOKEN, KODY_DASHBOARD_TOKEN, KODY_TOKEN, GH_TOKEN, GITHUB_TOKEN, or GH_PAT."
|
|
2205
|
+
};
|
|
2206
|
+
}
|
|
2207
|
+
if (!owner || !repo) {
|
|
2208
|
+
return { ok: false, error: "invalid_repo", message: `Invalid repo slug: ${opts.repoSlug}` };
|
|
2209
|
+
}
|
|
2210
|
+
return {
|
|
2211
|
+
ok: true,
|
|
2212
|
+
headers: {
|
|
2213
|
+
"Content-Type": "application/json",
|
|
2214
|
+
"x-kody-token": token,
|
|
2215
|
+
"x-kody-owner": owner,
|
|
2216
|
+
"x-kody-repo": repo
|
|
2217
|
+
}
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
async function callDashboardCms(opts, path49, init = {}) {
|
|
2221
|
+
const baseUrl = dashboardBaseUrl();
|
|
2222
|
+
if (!baseUrl) {
|
|
2223
|
+
return {
|
|
2224
|
+
ok: false,
|
|
2225
|
+
error: "missing_dashboard_url",
|
|
2226
|
+
message: "Set KODY_CMS_DASHBOARD_URL or KODY_DASHBOARD_URL to the Dashboard origin."
|
|
2227
|
+
};
|
|
2228
|
+
}
|
|
2229
|
+
const headerResult = cmsHeaders(opts);
|
|
2230
|
+
if (!headerResult.ok) return headerResult;
|
|
2231
|
+
try {
|
|
2232
|
+
const res = await fetch(`${baseUrl}${path49}`, {
|
|
2233
|
+
...init,
|
|
2234
|
+
headers: {
|
|
2235
|
+
...headerResult.headers,
|
|
2236
|
+
...init.headers
|
|
2237
|
+
}
|
|
2238
|
+
});
|
|
2239
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
2240
|
+
const data = contentType.includes("application/json") ? await res.json().catch(() => null) : await res.text().catch(() => "");
|
|
2241
|
+
if (!res.ok) {
|
|
2242
|
+
return {
|
|
2243
|
+
ok: false,
|
|
2244
|
+
status: res.status,
|
|
2245
|
+
error: stringFieldFromRecord(data, "error") ?? "cms_request_failed",
|
|
2246
|
+
message: stringFieldFromRecord(data, "message") ?? `Dashboard CMS request failed with ${res.status}.`,
|
|
2247
|
+
data
|
|
2248
|
+
};
|
|
2249
|
+
}
|
|
2250
|
+
return { ok: true, status: res.status, data };
|
|
2251
|
+
} catch (err) {
|
|
2252
|
+
return {
|
|
2253
|
+
ok: false,
|
|
2254
|
+
error: "cms_request_error",
|
|
2255
|
+
message: err instanceof Error ? err.message : String(err)
|
|
2256
|
+
};
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
function cmsToolResponse(result) {
|
|
2260
|
+
return {
|
|
2261
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
2262
|
+
...result.ok ? {} : { isError: true }
|
|
2263
|
+
};
|
|
2264
|
+
}
|
|
2265
|
+
function assertCmsWriteAllowed(opts) {
|
|
2266
|
+
if (isDispatchGated(opts.capabilitySlug, readCapabilityTrustMode(opts.state, opts.repoSlug, opts.capabilitySlug))) {
|
|
2267
|
+
return trustRefusal(opts.capabilitySlug);
|
|
2268
|
+
}
|
|
2269
|
+
return null;
|
|
2270
|
+
}
|
|
2271
|
+
function cmsQuery(args) {
|
|
2272
|
+
const params = new URLSearchParams();
|
|
2273
|
+
const q = stringArg(args.q);
|
|
2274
|
+
if (q) params.set("q", q);
|
|
2275
|
+
const limit = numberArg(args.limit);
|
|
2276
|
+
if (limit !== void 0) params.set("limit", String(limit));
|
|
2277
|
+
const offset = numberArg(args.offset);
|
|
2278
|
+
if (offset !== void 0) params.set("offset", String(offset));
|
|
2279
|
+
if (args.filters && typeof args.filters === "object" && !Array.isArray(args.filters)) {
|
|
2280
|
+
params.set("filters", JSON.stringify(args.filters));
|
|
2281
|
+
}
|
|
2282
|
+
if (Array.isArray(args.sort)) {
|
|
2283
|
+
const sort = args.sort.flatMap((entry) => {
|
|
2284
|
+
if (!entry || typeof entry !== "object") return [];
|
|
2285
|
+
const field = stringArg(entry.field);
|
|
2286
|
+
if (!field) return [];
|
|
2287
|
+
const direction = entry.direction === "asc" ? "asc" : "desc";
|
|
2288
|
+
return [`${field}:${direction}`];
|
|
2289
|
+
}).join(",");
|
|
2290
|
+
if (sort) params.set("sort", sort);
|
|
2291
|
+
}
|
|
2292
|
+
const value = params.toString();
|
|
2293
|
+
return value ? `?${value}` : "";
|
|
2294
|
+
}
|
|
2295
|
+
function stringArg(value) {
|
|
2296
|
+
return typeof value === "string" ? value.trim() : "";
|
|
2297
|
+
}
|
|
2298
|
+
function numberArg(value) {
|
|
2299
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
2300
|
+
const n = Number(value);
|
|
2301
|
+
return Number.isFinite(n) ? n : void 0;
|
|
2302
|
+
}
|
|
2303
|
+
function documentArg(value) {
|
|
2304
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
2305
|
+
return value;
|
|
2306
|
+
}
|
|
2307
|
+
function stringFieldFromRecord(value, field) {
|
|
2308
|
+
return value && typeof value === "object" && !Array.isArray(value) && typeof value[field] === "string" ? String(value[field]) : void 0;
|
|
2309
|
+
}
|
|
2192
2310
|
function capabilityToolDefinitions(opts) {
|
|
2193
2311
|
const workflowFile = opts.workflowFile ?? "kody.yml";
|
|
2194
2312
|
const listTool = {
|
|
@@ -2337,10 +2455,7 @@ function capabilityToolDefinitions(opts) {
|
|
|
2337
2455
|
handler: async (args) => {
|
|
2338
2456
|
const capability = String(args.capability ?? args.executable ?? "");
|
|
2339
2457
|
const issueNumber = Number(args.issueNumber);
|
|
2340
|
-
if (isDispatchGated(
|
|
2341
|
-
capability,
|
|
2342
|
-
readCapabilityTrustMode(opts.state, opts.repoSlug, opts.capabilitySlug)
|
|
2343
|
-
)) {
|
|
2458
|
+
if (isDispatchGated(capability, readCapabilityTrustMode(opts.state, opts.repoSlug, opts.capabilitySlug))) {
|
|
2344
2459
|
return { content: [{ type: "text", text: trustRefusal(opts.capabilitySlug) }] };
|
|
2345
2460
|
}
|
|
2346
2461
|
const result = dispatchWorkflow(workflowFile, capability, issueNumber, opts.repoSlug);
|
|
@@ -2348,6 +2463,86 @@ function capabilityToolDefinitions(opts) {
|
|
|
2348
2463
|
return { content: [{ type: "text", text }] };
|
|
2349
2464
|
}
|
|
2350
2465
|
};
|
|
2466
|
+
const cmsListCollectionsTool = {
|
|
2467
|
+
name: "cms_list_collections",
|
|
2468
|
+
description: "List configured Dashboard CMS collections and their supported operations. Read-only.",
|
|
2469
|
+
inputSchema: {},
|
|
2470
|
+
handler: async () => cmsToolResponse(await callDashboardCms(opts, "/api/kody/cms"))
|
|
2471
|
+
};
|
|
2472
|
+
const cmsListDocumentsTool = {
|
|
2473
|
+
name: "cms_list_documents",
|
|
2474
|
+
description: "List or search Dashboard CMS documents from one configured collection. Read-only.",
|
|
2475
|
+
inputSchema: {
|
|
2476
|
+
collection: z2.string().min(1).describe("CMS collection name."),
|
|
2477
|
+
q: z2.string().optional().describe("Optional search query."),
|
|
2478
|
+
filters: z2.record(z2.string(), z2.unknown()).optional().describe("Optional filter object keyed by field."),
|
|
2479
|
+
sort: z2.array(
|
|
2480
|
+
z2.object({
|
|
2481
|
+
field: z2.string().min(1),
|
|
2482
|
+
direction: z2.enum(["asc", "desc"]).default("desc")
|
|
2483
|
+
})
|
|
2484
|
+
).optional(),
|
|
2485
|
+
limit: z2.number().int().min(1).max(100).optional(),
|
|
2486
|
+
offset: z2.number().int().min(0).optional()
|
|
2487
|
+
},
|
|
2488
|
+
handler: async (args) => {
|
|
2489
|
+
const collection = encodeURIComponent(stringArg(args.collection));
|
|
2490
|
+
return cmsToolResponse(await callDashboardCms(opts, `/api/kody/cms/${collection}${cmsQuery(args)}`));
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2493
|
+
const cmsGetDocumentTool = {
|
|
2494
|
+
name: "cms_get_document",
|
|
2495
|
+
description: "Get one Dashboard CMS document by collection and id. Read-only.",
|
|
2496
|
+
inputSchema: {
|
|
2497
|
+
collection: z2.string().min(1).describe("CMS collection name."),
|
|
2498
|
+
id: z2.string().min(1).describe("Document id.")
|
|
2499
|
+
},
|
|
2500
|
+
handler: async (args) => {
|
|
2501
|
+
const collection = encodeURIComponent(stringArg(args.collection));
|
|
2502
|
+
const id = encodeURIComponent(stringArg(args.id));
|
|
2503
|
+
return cmsToolResponse(await callDashboardCms(opts, `/api/kody/cms/${collection}/${id}`));
|
|
2504
|
+
}
|
|
2505
|
+
};
|
|
2506
|
+
const cmsCreateDocumentTool = {
|
|
2507
|
+
name: "cms_create_document",
|
|
2508
|
+
description: "Create one Dashboard CMS document when the capability is trusted and the CMS collection allows create.",
|
|
2509
|
+
inputSchema: {
|
|
2510
|
+
collection: z2.string().min(1).describe("CMS collection name."),
|
|
2511
|
+
data: z2.record(z2.string(), z2.unknown()).describe("Document fields to create.")
|
|
2512
|
+
},
|
|
2513
|
+
handler: async (args) => {
|
|
2514
|
+
const refusal = assertCmsWriteAllowed(opts);
|
|
2515
|
+
if (refusal) return { content: [{ type: "text", text: refusal }] };
|
|
2516
|
+
const collection = encodeURIComponent(stringArg(args.collection));
|
|
2517
|
+
return cmsToolResponse(
|
|
2518
|
+
await callDashboardCms(opts, `/api/kody/cms/${collection}`, {
|
|
2519
|
+
method: "POST",
|
|
2520
|
+
body: JSON.stringify(documentArg(args.data))
|
|
2521
|
+
})
|
|
2522
|
+
);
|
|
2523
|
+
}
|
|
2524
|
+
};
|
|
2525
|
+
const cmsUpdateDocumentTool = {
|
|
2526
|
+
name: "cms_update_document",
|
|
2527
|
+
description: "Update one Dashboard CMS document when the capability is trusted and the CMS collection allows update.",
|
|
2528
|
+
inputSchema: {
|
|
2529
|
+
collection: z2.string().min(1).describe("CMS collection name."),
|
|
2530
|
+
id: z2.string().min(1).describe("Document id."),
|
|
2531
|
+
data: z2.record(z2.string(), z2.unknown()).describe("Partial document fields to update.")
|
|
2532
|
+
},
|
|
2533
|
+
handler: async (args) => {
|
|
2534
|
+
const refusal = assertCmsWriteAllowed(opts);
|
|
2535
|
+
if (refusal) return { content: [{ type: "text", text: refusal }] };
|
|
2536
|
+
const collection = encodeURIComponent(stringArg(args.collection));
|
|
2537
|
+
const id = encodeURIComponent(stringArg(args.id));
|
|
2538
|
+
return cmsToolResponse(
|
|
2539
|
+
await callDashboardCms(opts, `/api/kody/cms/${collection}/${id}`, {
|
|
2540
|
+
method: "PATCH",
|
|
2541
|
+
body: JSON.stringify(documentArg(args.data))
|
|
2542
|
+
})
|
|
2543
|
+
);
|
|
2544
|
+
}
|
|
2545
|
+
};
|
|
2351
2546
|
return [
|
|
2352
2547
|
listTool,
|
|
2353
2548
|
syncTool,
|
|
@@ -2359,7 +2554,12 @@ function capabilityToolDefinitions(opts) {
|
|
|
2359
2554
|
readThreadTool,
|
|
2360
2555
|
ensureIssueTool,
|
|
2361
2556
|
ensureCommentTool,
|
|
2362
|
-
dispatchTool
|
|
2557
|
+
dispatchTool,
|
|
2558
|
+
cmsListCollectionsTool,
|
|
2559
|
+
cmsListDocumentsTool,
|
|
2560
|
+
cmsGetDocumentTool,
|
|
2561
|
+
cmsCreateDocumentTool,
|
|
2562
|
+
cmsUpdateDocumentTool
|
|
2363
2563
|
];
|
|
2364
2564
|
}
|
|
2365
2565
|
function buildCapabilityMcpServer(opts) {
|
|
@@ -2406,7 +2606,12 @@ var init_capabilityMcp = __esm({
|
|
|
2406
2606
|
"read_thread",
|
|
2407
2607
|
"ensure_issue",
|
|
2408
2608
|
"ensure_comment",
|
|
2409
|
-
"dispatch_workflow"
|
|
2609
|
+
"dispatch_workflow",
|
|
2610
|
+
"cms_list_collections",
|
|
2611
|
+
"cms_list_documents",
|
|
2612
|
+
"cms_get_document",
|
|
2613
|
+
"cms_create_document",
|
|
2614
|
+
"cms_update_document"
|
|
2410
2615
|
];
|
|
2411
2616
|
}
|
|
2412
2617
|
});
|
|
@@ -19470,7 +19675,15 @@ async function runCi(argv) {
|
|
|
19470
19675
|
let manualWorkflowDispatch = false;
|
|
19471
19676
|
let forceRunAction = null;
|
|
19472
19677
|
let forceRunCliArgs = {};
|
|
19473
|
-
|
|
19678
|
+
const envForceAction = (process.env.KODY_FORCE_ACTION ?? "").trim();
|
|
19679
|
+
const envForceMessage = (process.env.KODY_FORCE_MESSAGE ?? "").trim();
|
|
19680
|
+
if (!args.issueNumber && !autoFallback && envForceAction) {
|
|
19681
|
+
forceRunAction = envForceAction;
|
|
19682
|
+
if (envForceAction === "goal-manager" && envForceMessage) {
|
|
19683
|
+
forceRunCliArgs = { goal: envForceMessage };
|
|
19684
|
+
}
|
|
19685
|
+
}
|
|
19686
|
+
if (!args.issueNumber && !autoFallback && !forceRunAction && eventName === "workflow_dispatch" && dispatchEventPath && fs45.existsSync(dispatchEventPath)) {
|
|
19474
19687
|
try {
|
|
19475
19688
|
const evt = JSON.parse(fs45.readFileSync(dispatchEventPath, "utf-8"));
|
|
19476
19689
|
const issueInput = parseInt(String(evt?.inputs?.issue_number ?? ""), 10);
|
|
@@ -22241,6 +22454,9 @@ function parseJob(body) {
|
|
|
22241
22454
|
}
|
|
22242
22455
|
if (typeof b.ref === "string" && b.ref.trim()) job.ref = b.ref.trim();
|
|
22243
22456
|
if (typeof b.model === "string" && b.model.trim()) job.model = b.model.trim();
|
|
22457
|
+
if (typeof b.reasoningEffort === "string" && b.reasoningEffort.trim()) job.reasoningEffort = b.reasoningEffort.trim();
|
|
22458
|
+
if (typeof b.action === "string" && b.action.trim()) job.action = b.action.trim();
|
|
22459
|
+
if (typeof b.message === "string" && b.message.trim()) job.message = b.message.trim();
|
|
22244
22460
|
if (typeof b.sessionId === "string" && b.sessionId.trim()) job.sessionId = b.sessionId.trim();
|
|
22245
22461
|
if (typeof b.dashboardUrl === "string" && b.dashboardUrl.trim()) job.dashboardUrl = b.dashboardUrl.trim();
|
|
22246
22462
|
if (b.allSecrets && (typeof b.allSecrets === "object" || typeof b.allSecrets === "string")) {
|
|
@@ -22257,14 +22473,18 @@ async function defaultRunJob(job) {
|
|
|
22257
22473
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
22258
22474
|
const interactive = job.mode === "interactive";
|
|
22259
22475
|
const scheduled = job.mode === "scheduled";
|
|
22476
|
+
const runMode = interactive ? "interactive" : scheduled ? "scheduled" : "issue";
|
|
22260
22477
|
const childEnv = {
|
|
22261
22478
|
...process.env,
|
|
22262
22479
|
REPO: job.repo,
|
|
22263
22480
|
REF: branch,
|
|
22264
22481
|
GITHUB_TOKEN: job.githubToken,
|
|
22482
|
+
KODY_RUN_MODE: runMode,
|
|
22265
22483
|
// Scheduled mode drives the engine down the same path GitHub Actions' cron
|
|
22266
22484
|
// takes (runScheduledFanOut → due capabilities/goals). Bare `kody` routes on this.
|
|
22267
22485
|
...scheduled ? { GITHUB_EVENT_NAME: "schedule" } : {},
|
|
22486
|
+
...job.action ? { KODY_FORCE_ACTION: job.action } : {},
|
|
22487
|
+
...job.message ? { KODY_FORCE_MESSAGE: job.message } : {},
|
|
22268
22488
|
// GITHUB_REPOSITORY + GH_TOKEN are normally injected by GitHub Actions.
|
|
22269
22489
|
// The engine's interactive mode needs GITHUB_REPOSITORY to resolve the
|
|
22270
22490
|
// configured state repo and persist chat.ready / events (the durable signal
|
|
@@ -22272,13 +22492,14 @@ async function defaultRunJob(job) {
|
|
|
22272
22492
|
// and the session never appears "ready". GH_TOKEN auths the `gh` CLI.
|
|
22273
22493
|
GITHUB_REPOSITORY: job.repo,
|
|
22274
22494
|
GH_TOKEN: job.githubToken,
|
|
22275
|
-
// Issue mode
|
|
22276
|
-
//
|
|
22495
|
+
// Issue mode carries ISSUE_NUMBER. Interactive mode leaves it empty and
|
|
22496
|
+
// sets SESSION_ID so the engine boots a chat session.
|
|
22277
22497
|
ISSUE_NUMBER: interactive || scheduled ? "" : String(job.issueNumber),
|
|
22278
22498
|
ALL_SECRETS: allSecrets,
|
|
22279
22499
|
SESSION_ID: job.sessionId ?? "",
|
|
22280
22500
|
DASHBOARD_URL: job.dashboardUrl ?? "",
|
|
22281
22501
|
MODEL: job.model ?? "",
|
|
22502
|
+
REASONING_EFFORT: job.reasoningEffort ?? "",
|
|
22282
22503
|
...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
|
|
22283
22504
|
...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
|
|
22284
22505
|
};
|
|
@@ -22304,11 +22525,10 @@ async function defaultRunJob(job) {
|
|
|
22304
22525
|
const authorEmail = process.env.GIT_AUTHOR_EMAIL ?? "kody-bot@users.noreply.github.com";
|
|
22305
22526
|
await run("git", ["config", "user.name", authorName], workdir);
|
|
22306
22527
|
await run("git", ["config", "user.email", authorEmail], workdir);
|
|
22307
|
-
const runArgs = interactive || scheduled ? [] : ["run", "--issue", String(job.issueNumber)];
|
|
22308
22528
|
const jobDesc = interactive ? `interactive session ${job.sessionId}` : scheduled ? "scheduled fan-out" : `running issue #${job.issueNumber}`;
|
|
22309
22529
|
process.stdout.write(`[runner-serve] job ${job.jobId}: ${jobDesc}
|
|
22310
22530
|
`);
|
|
22311
|
-
const runCode = await run("kody",
|
|
22531
|
+
const runCode = await run("kody", [], workdir);
|
|
22312
22532
|
process.stdout.write(`[runner-serve] job ${job.jobId}: finished (exit ${runCode})
|
|
22313
22533
|
`);
|
|
22314
22534
|
process.exit(runCode);
|
|
@@ -22698,6 +22918,25 @@ function formatMs(ms) {
|
|
|
22698
22918
|
}
|
|
22699
22919
|
|
|
22700
22920
|
// src/entry.ts
|
|
22921
|
+
function envRunMode(env = process.env) {
|
|
22922
|
+
const result = { command: "help", errors: [] };
|
|
22923
|
+
const mode = (env.KODY_RUN_MODE ?? "").trim().toLowerCase();
|
|
22924
|
+
if (!mode) return null;
|
|
22925
|
+
if (mode === "chat" || mode === "interactive") {
|
|
22926
|
+
return { ...result, command: "chat", chatArgv: [] };
|
|
22927
|
+
}
|
|
22928
|
+
if (mode === "ci" || mode === "scheduled" || mode === "manual") {
|
|
22929
|
+
return { ...result, command: "ci", ciArgv: [] };
|
|
22930
|
+
}
|
|
22931
|
+
if (mode === "issue") {
|
|
22932
|
+
const issue = (env.ISSUE_NUMBER ?? "").trim();
|
|
22933
|
+
if (!issue) {
|
|
22934
|
+
return { ...result, errors: ["KODY_RUN_MODE=issue requires ISSUE_NUMBER"] };
|
|
22935
|
+
}
|
|
22936
|
+
return { ...result, command: "ci", ciArgv: ["--issue", issue] };
|
|
22937
|
+
}
|
|
22938
|
+
return { ...result, errors: [`unknown KODY_RUN_MODE: ${mode}`] };
|
|
22939
|
+
}
|
|
22701
22940
|
var HELP_TEXT = `kody-engine \u2014 single-session autonomous engineer
|
|
22702
22941
|
|
|
22703
22942
|
Usage:
|
|
@@ -22734,6 +22973,8 @@ Exit codes:
|
|
|
22734
22973
|
function parseArgs(argv) {
|
|
22735
22974
|
const result = { command: "help", errors: [] };
|
|
22736
22975
|
if (argv.length === 0) {
|
|
22976
|
+
const mode = envRunMode();
|
|
22977
|
+
if (mode) return mode;
|
|
22737
22978
|
if (process.env.SESSION_ID) return { ...result, command: "chat", chatArgv: [] };
|
|
22738
22979
|
if (process.env.GITHUB_EVENT_NAME) return { ...result, command: "ci", ciArgv: [] };
|
|
22739
22980
|
return result;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.273",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|