@kody-ade/kody-engine 0.4.466 → 0.4.468
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
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.468",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -54,6 +54,7 @@ var init_package = __esm({
|
|
|
54
54
|
"@actions/cache": "^6.0.0",
|
|
55
55
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
56
56
|
"@kody-ade/agency-domain": "0.5.1",
|
|
57
|
+
"@kody-ade/engine-contracts": "0.1.0",
|
|
57
58
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
58
59
|
ajv: "^8.18.0",
|
|
59
60
|
convex: "^1.17.0",
|
|
@@ -14053,6 +14054,11 @@ var init_loopDefinitions = __esm({
|
|
|
14053
14054
|
|
|
14054
14055
|
// src/scripts/dispatchSimpleLoops.ts
|
|
14055
14056
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
14057
|
+
function selectRunnableLoops(loops, now, options) {
|
|
14058
|
+
return loops.filter(
|
|
14059
|
+
(loop) => loop.enabled && loop.trigger.type === "schedule" && (!options.loopId || loop.id === options.loopId) && (options.force || dueSlot(loop, now) !== null)
|
|
14060
|
+
);
|
|
14061
|
+
}
|
|
14056
14062
|
function loopDispatchSlot(loop, now, force, nonce) {
|
|
14057
14063
|
return force ? `manual:${now.toISOString()}:${nonce}` : dueSlot(loop, now);
|
|
14058
14064
|
}
|
|
@@ -14110,9 +14116,11 @@ var init_dispatchSimpleLoops = __esm({
|
|
|
14110
14116
|
if (!tenantId2) throw new Error("Repository identity is required for Loop dispatch");
|
|
14111
14117
|
const now = /* @__PURE__ */ new Date();
|
|
14112
14118
|
const force = ctx.data.jobForce === true;
|
|
14113
|
-
const
|
|
14114
|
-
|
|
14115
|
-
|
|
14119
|
+
const requestedLoopId = typeof ctx.args.loop === "string" ? ctx.args.loop.trim() : "";
|
|
14120
|
+
const due = selectRunnableLoops(listLoopDefinitions(ctx.cwd), now, {
|
|
14121
|
+
force,
|
|
14122
|
+
...requestedLoopId ? { loopId: requestedLoopId } : {}
|
|
14123
|
+
});
|
|
14116
14124
|
process.stdout.write(
|
|
14117
14125
|
`\u2192 kody: Loop scheduler found ${due.length} runnable Loop(s)${force ? " (manual)" : ""}
|
|
14118
14126
|
`
|
|
@@ -25172,63 +25180,15 @@ init_loopDefinitions();
|
|
|
25172
25180
|
init_registry();
|
|
25173
25181
|
|
|
25174
25182
|
// src/run-request.ts
|
|
25175
|
-
|
|
25176
|
-
|
|
25177
|
-
|
|
25178
|
-
|
|
25179
|
-
|
|
25180
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25181
|
-
}
|
|
25182
|
-
function readString(value) {
|
|
25183
|
-
return typeof value === "string" ? value.trim() : "";
|
|
25184
|
-
}
|
|
25185
|
-
function parseTarget(input) {
|
|
25186
|
-
if (!isRecord2(input)) return { error: "runRequest.target must be an object" };
|
|
25187
|
-
const type = readString(input.type);
|
|
25188
|
-
if (!TARGET_TYPES.has(type)) return { error: "runRequest.target.type is invalid" };
|
|
25189
|
-
if (type === "issue") {
|
|
25190
|
-
const id2 = Number(input.id);
|
|
25191
|
-
if (!Number.isInteger(id2) || id2 <= 0) return { error: "runRequest.target.id must be a positive issue number" };
|
|
25192
|
-
return { target: { type, id: id2 } };
|
|
25193
|
-
}
|
|
25194
|
-
const id = readString(input.id);
|
|
25195
|
-
if (!id) return { error: "runRequest.target.id is required" };
|
|
25196
|
-
return { target: { type, id } };
|
|
25197
|
-
}
|
|
25198
|
-
function parseRunRequest(input) {
|
|
25199
|
-
let body = input;
|
|
25200
|
-
if (typeof input === "string") {
|
|
25201
|
-
const raw = input.trim();
|
|
25202
|
-
if (!raw) return { error: `${RUN_REQUEST_ENV} is empty` };
|
|
25203
|
-
try {
|
|
25204
|
-
body = JSON.parse(raw);
|
|
25205
|
-
} catch {
|
|
25206
|
-
return { error: `${RUN_REQUEST_ENV} must be valid JSON` };
|
|
25207
|
-
}
|
|
25208
|
-
}
|
|
25209
|
-
if (!isRecord2(body)) return { error: "runRequest must be an object" };
|
|
25210
|
-
const parsedTarget = parseTarget(body.target);
|
|
25211
|
-
if ("error" in parsedTarget) return parsedTarget;
|
|
25212
|
-
const intent = readString(body.intent);
|
|
25213
|
-
if (!INTENTS.has(intent)) return { error: "runRequest.intent is invalid" };
|
|
25214
|
-
const source = readString(body.source);
|
|
25215
|
-
if (!SOURCES.has(source)) return { error: "runRequest.source is invalid" };
|
|
25216
|
-
if (body.input !== void 0 && !isRecord2(body.input)) {
|
|
25217
|
-
return { error: "runRequest.input must be an object when provided" };
|
|
25218
|
-
}
|
|
25219
|
-
return {
|
|
25220
|
-
request: {
|
|
25221
|
-
target: parsedTarget.target,
|
|
25222
|
-
intent,
|
|
25223
|
-
source,
|
|
25224
|
-
...body.input !== void 0 ? { input: body.input } : {}
|
|
25225
|
-
}
|
|
25226
|
-
};
|
|
25227
|
-
}
|
|
25183
|
+
import {
|
|
25184
|
+
ENGINE_EXECUTION_REQUEST_ENV,
|
|
25185
|
+
parseEngineExecutionRequest
|
|
25186
|
+
} from "@kody-ade/engine-contracts";
|
|
25187
|
+
var RUN_REQUEST_ENV = ENGINE_EXECUTION_REQUEST_ENV;
|
|
25228
25188
|
function readRunRequestFromEnv(env = process.env) {
|
|
25229
25189
|
const raw = env[RUN_REQUEST_ENV];
|
|
25230
25190
|
if (raw == null || raw.trim() === "") return null;
|
|
25231
|
-
return
|
|
25191
|
+
return parseEngineExecutionRequest(raw);
|
|
25232
25192
|
}
|
|
25233
25193
|
|
|
25234
25194
|
// src/kody-cli.ts
|
|
@@ -25306,6 +25266,9 @@ function parseCiArgs(argv) {
|
|
|
25306
25266
|
}
|
|
25307
25267
|
return result;
|
|
25308
25268
|
}
|
|
25269
|
+
function isScheduledActionsWake(env = process.env) {
|
|
25270
|
+
return env.GITHUB_EVENT_NAME === "schedule" || env.GITHUB_ACTIONS === "true" && !env.GITHUB_EVENT_NAME && !env.GITHUB_EVENT_PATH;
|
|
25271
|
+
}
|
|
25309
25272
|
function routeRunRequest(request) {
|
|
25310
25273
|
const { target, intent } = request;
|
|
25311
25274
|
if (target.type === "chat" || target.type === "issue") return { kind: "ignore" };
|
|
@@ -25319,6 +25282,16 @@ function routeRunRequest(request) {
|
|
|
25319
25282
|
cliArgs: { goal: target.id }
|
|
25320
25283
|
};
|
|
25321
25284
|
}
|
|
25285
|
+
if (target.type === "loop") {
|
|
25286
|
+
if (intent !== "run" && intent !== "tick") {
|
|
25287
|
+
return { kind: "error", error: `loop target does not support intent '${intent}'` };
|
|
25288
|
+
}
|
|
25289
|
+
return {
|
|
25290
|
+
kind: "action",
|
|
25291
|
+
action: "loop-scheduler",
|
|
25292
|
+
cliArgs: { loop: target.id }
|
|
25293
|
+
};
|
|
25294
|
+
}
|
|
25322
25295
|
if (target.type === "workflow") {
|
|
25323
25296
|
if (target.id === "scheduled-fanout") {
|
|
25324
25297
|
return { kind: "fanout", force: intent === "run" };
|
|
@@ -25326,7 +25299,8 @@ function routeRunRequest(request) {
|
|
|
25326
25299
|
if (intent !== "run" && intent !== "tick") {
|
|
25327
25300
|
return { kind: "error", error: `workflow target does not support intent '${intent}'` };
|
|
25328
25301
|
}
|
|
25329
|
-
const
|
|
25302
|
+
const requestedRunId = typeof request.input?.runId === "string" ? request.input.runId : request.requestId;
|
|
25303
|
+
const workflowRunId = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/.test(requestedRunId) ? requestedRunId : void 0;
|
|
25330
25304
|
return { kind: "action", action: target.id, cliArgs: {}, ...workflowRunId ? { workflowRunId } : {} };
|
|
25331
25305
|
}
|
|
25332
25306
|
return { kind: "error", error: "unsupported run request target" };
|
|
@@ -25571,6 +25545,7 @@ async function runCi(argv) {
|
|
|
25571
25545
|
}
|
|
25572
25546
|
const autoFallback = !args.issueNumber ? autoDispatch({ config: earlyConfig }) : null;
|
|
25573
25547
|
const eventName = process.env.GITHUB_EVENT_NAME;
|
|
25548
|
+
const scheduledActionsWake = isScheduledActionsWake();
|
|
25574
25549
|
const dispatchEventPath = process.env.GITHUB_EVENT_PATH;
|
|
25575
25550
|
let manualWorkflowDispatch = false;
|
|
25576
25551
|
let forceRunAction = null;
|
|
@@ -25745,7 +25720,7 @@ async function runCi(argv) {
|
|
|
25745
25720
|
if (!args.issueNumber && !autoFallback && runRequestFanOut) {
|
|
25746
25721
|
return runScheduledFanOut(cwd, args, { force: runRequestFanOutForce });
|
|
25747
25722
|
}
|
|
25748
|
-
if (!args.issueNumber && !autoFallback && (
|
|
25723
|
+
if (!args.issueNumber && !autoFallback && (scheduledActionsWake || manualWorkflowDispatch)) {
|
|
25749
25724
|
return runScheduledFanOut(cwd, args, { force: manualWorkflowDispatch });
|
|
25750
25725
|
}
|
|
25751
25726
|
if (!args.issueNumber && !autoFallback && process.env.GITHUB_EVENT_NAME) {
|
|
@@ -27537,10 +27512,12 @@ async function runAgencyLoopTick(deps) {
|
|
|
27537
27512
|
for (const repository of repositories) {
|
|
27538
27513
|
const [owner, repo] = repository.split("/");
|
|
27539
27514
|
try {
|
|
27515
|
+
const jobId = `sched-${owner}-${repo}-${clock()}`;
|
|
27540
27516
|
const result = await deps.claim(owner, repo, {
|
|
27541
|
-
jobId
|
|
27517
|
+
jobId,
|
|
27542
27518
|
repo: repository,
|
|
27543
27519
|
runRequest: {
|
|
27520
|
+
requestId: jobId,
|
|
27544
27521
|
target: { type: "workflow", id: "scheduled-fanout" },
|
|
27545
27522
|
intent: "tick",
|
|
27546
27523
|
source: "schedule"
|
|
@@ -28127,16 +28104,8 @@ function parseClaimRequest(body) {
|
|
|
28127
28104
|
if (!jobId) return { error: "jobId required" };
|
|
28128
28105
|
const repo = typeof b.repo === "string" ? b.repo.trim() : "";
|
|
28129
28106
|
if (!/^[^/\s]+\/[^/\s]+$/.test(repo)) return { error: "repo must be 'owner/name'" };
|
|
28130
|
-
|
|
28131
|
-
const
|
|
28132
|
-
const message = typeof b.message === "string" && b.message.trim() ? b.message.trim() : void 0;
|
|
28133
|
-
const runRequest = b.runRequest !== void 0 ? parseRunRequest(b.runRequest) : synthesizeLegacyClaimRequest({
|
|
28134
|
-
mode,
|
|
28135
|
-
issueNumber: b.issueNumber,
|
|
28136
|
-
sessionId: b.sessionId,
|
|
28137
|
-
action,
|
|
28138
|
-
message
|
|
28139
|
-
});
|
|
28107
|
+
if (b.runRequest === void 0) return { error: "runRequest required" };
|
|
28108
|
+
const runRequest = parseEngineExecutionRequest(b.runRequest);
|
|
28140
28109
|
if ("error" in runRequest) return { error: runRequest.error };
|
|
28141
28110
|
const req = { jobId, repo, runRequest: runRequest.request };
|
|
28142
28111
|
if (req.runRequest.target.type === "issue") {
|
|
@@ -28151,55 +28120,6 @@ function parseClaimRequest(body) {
|
|
|
28151
28120
|
if (typeof b.dashboardUrl === "string" && b.dashboardUrl.trim()) req.dashboardUrl = b.dashboardUrl.trim();
|
|
28152
28121
|
return { req };
|
|
28153
28122
|
}
|
|
28154
|
-
function synthesizeLegacyClaimRequest(input) {
|
|
28155
|
-
if (input.mode === "issue") {
|
|
28156
|
-
const issueNumber = Number(input.issueNumber);
|
|
28157
|
-
if (!Number.isInteger(issueNumber) || issueNumber <= 0) return { error: "issueNumber required for issue mode" };
|
|
28158
|
-
return {
|
|
28159
|
-
request: {
|
|
28160
|
-
target: { type: "issue", id: issueNumber },
|
|
28161
|
-
intent: "run",
|
|
28162
|
-
source: "dashboard"
|
|
28163
|
-
}
|
|
28164
|
-
};
|
|
28165
|
-
}
|
|
28166
|
-
if (input.mode === "interactive") {
|
|
28167
|
-
const sessionId = typeof input.sessionId === "string" ? input.sessionId.trim() : "";
|
|
28168
|
-
if (!sessionId) return { error: "sessionId required for interactive mode" };
|
|
28169
|
-
return {
|
|
28170
|
-
request: {
|
|
28171
|
-
target: { type: "chat", id: sessionId },
|
|
28172
|
-
intent: "continue",
|
|
28173
|
-
source: "dashboard"
|
|
28174
|
-
}
|
|
28175
|
-
};
|
|
28176
|
-
}
|
|
28177
|
-
if (input.action === "goal-manager" && input.message) {
|
|
28178
|
-
return {
|
|
28179
|
-
request: {
|
|
28180
|
-
target: { type: "goal", id: input.message },
|
|
28181
|
-
intent: "manage",
|
|
28182
|
-
source: "dashboard"
|
|
28183
|
-
}
|
|
28184
|
-
};
|
|
28185
|
-
}
|
|
28186
|
-
if (input.action) {
|
|
28187
|
-
return {
|
|
28188
|
-
request: {
|
|
28189
|
-
target: { type: "workflow", id: input.action },
|
|
28190
|
-
intent: "run",
|
|
28191
|
-
source: "dashboard"
|
|
28192
|
-
}
|
|
28193
|
-
};
|
|
28194
|
-
}
|
|
28195
|
-
return {
|
|
28196
|
-
request: {
|
|
28197
|
-
target: { type: "workflow", id: "scheduled-fanout" },
|
|
28198
|
-
intent: "tick",
|
|
28199
|
-
source: "schedule"
|
|
28200
|
-
}
|
|
28201
|
-
};
|
|
28202
|
-
}
|
|
28203
28123
|
async function poolServe() {
|
|
28204
28124
|
const masterRaw = process.env.KODY_MASTER_KEY?.trim();
|
|
28205
28125
|
if (!masterRaw) throw new Error("KODY_MASTER_KEY required for pool-serve");
|
|
@@ -28397,16 +28317,8 @@ function parseJob(body) {
|
|
|
28397
28317
|
if (!/^[^/\s]+\/[^/\s]+$/.test(repo)) return { error: "repo must be 'owner/name'" };
|
|
28398
28318
|
const githubToken = typeof b.githubToken === "string" ? b.githubToken.trim() : "";
|
|
28399
28319
|
if (!githubToken) return { error: "githubToken required" };
|
|
28400
|
-
|
|
28401
|
-
const
|
|
28402
|
-
const mode = b.mode === "interactive" ? "interactive" : b.mode === "scheduled" ? "scheduled" : "issue";
|
|
28403
|
-
const runRequest = b.runRequest !== void 0 ? parseRunRequest(b.runRequest) : synthesizeLegacyRunRequest({
|
|
28404
|
-
mode,
|
|
28405
|
-
issueNumber: b.issueNumber,
|
|
28406
|
-
sessionId: b.sessionId,
|
|
28407
|
-
action,
|
|
28408
|
-
message
|
|
28409
|
-
});
|
|
28320
|
+
if (b.runRequest === void 0) return { error: "runRequest required" };
|
|
28321
|
+
const runRequest = parseEngineExecutionRequest(b.runRequest);
|
|
28410
28322
|
if ("error" in runRequest) return { error: runRequest.error };
|
|
28411
28323
|
const job = { jobId, repo, githubToken, runRequest: runRequest.request };
|
|
28412
28324
|
if (job.runRequest.target.type === "issue") {
|
|
@@ -28425,57 +28337,6 @@ function parseJob(body) {
|
|
|
28425
28337
|
}
|
|
28426
28338
|
return { job };
|
|
28427
28339
|
}
|
|
28428
|
-
function synthesizeLegacyRunRequest(input) {
|
|
28429
|
-
if (input.mode === "issue") {
|
|
28430
|
-
const issueNumber = Number(input.issueNumber);
|
|
28431
|
-
if (!Number.isInteger(issueNumber) || issueNumber <= 0) {
|
|
28432
|
-
return { error: "issueNumber (positive integer) required for issue mode" };
|
|
28433
|
-
}
|
|
28434
|
-
return {
|
|
28435
|
-
request: {
|
|
28436
|
-
target: { type: "issue", id: issueNumber },
|
|
28437
|
-
intent: "run",
|
|
28438
|
-
source: "dashboard"
|
|
28439
|
-
}
|
|
28440
|
-
};
|
|
28441
|
-
}
|
|
28442
|
-
if (input.mode === "interactive") {
|
|
28443
|
-
const sessionId = typeof input.sessionId === "string" ? input.sessionId.trim() : "";
|
|
28444
|
-
if (!sessionId) return { error: "sessionId required for interactive mode" };
|
|
28445
|
-
return {
|
|
28446
|
-
request: {
|
|
28447
|
-
target: { type: "chat", id: sessionId },
|
|
28448
|
-
intent: "continue",
|
|
28449
|
-
source: "dashboard"
|
|
28450
|
-
}
|
|
28451
|
-
};
|
|
28452
|
-
}
|
|
28453
|
-
if (input.action === "goal-manager" && input.message) {
|
|
28454
|
-
return {
|
|
28455
|
-
request: {
|
|
28456
|
-
target: { type: "goal", id: input.message },
|
|
28457
|
-
intent: "manage",
|
|
28458
|
-
source: "dashboard"
|
|
28459
|
-
}
|
|
28460
|
-
};
|
|
28461
|
-
}
|
|
28462
|
-
if (input.action) {
|
|
28463
|
-
return {
|
|
28464
|
-
request: {
|
|
28465
|
-
target: { type: "workflow", id: input.action },
|
|
28466
|
-
intent: "run",
|
|
28467
|
-
source: "dashboard"
|
|
28468
|
-
}
|
|
28469
|
-
};
|
|
28470
|
-
}
|
|
28471
|
-
return {
|
|
28472
|
-
request: {
|
|
28473
|
-
target: { type: "workflow", id: "scheduled-fanout" },
|
|
28474
|
-
intent: "tick",
|
|
28475
|
-
source: "schedule"
|
|
28476
|
-
}
|
|
28477
|
-
};
|
|
28478
|
-
}
|
|
28479
28340
|
async function defaultRunJob(job) {
|
|
28480
28341
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
28481
28342
|
const branch = job.ref ?? "main";
|
|
@@ -28615,7 +28476,7 @@ async function runnerServe() {
|
|
|
28615
28476
|
init_config();
|
|
28616
28477
|
init_litellm();
|
|
28617
28478
|
import { spawn as spawn10 } from "child_process";
|
|
28618
|
-
function
|
|
28479
|
+
function parseTarget(positional) {
|
|
28619
28480
|
if (!Array.isArray(positional) || positional.length === 0) return "none";
|
|
28620
28481
|
const first = String(positional[0]).toLowerCase();
|
|
28621
28482
|
if (first === "vscode" || first === "code") return "vscode";
|
|
@@ -28630,7 +28491,7 @@ function buildProxyEnv(url) {
|
|
|
28630
28491
|
};
|
|
28631
28492
|
}
|
|
28632
28493
|
async function serve(opts) {
|
|
28633
|
-
const target =
|
|
28494
|
+
const target = parseTarget(opts.args);
|
|
28634
28495
|
const model = parseProviderModel(opts.config.agent.model);
|
|
28635
28496
|
const usesProxy = needsLitellmProxy(model);
|
|
28636
28497
|
let handle = null;
|
|
@@ -27,6 +27,14 @@
|
|
|
27
27
|
],
|
|
28
28
|
"postflight": []
|
|
29
29
|
},
|
|
30
|
-
"inputs": [
|
|
30
|
+
"inputs": [
|
|
31
|
+
{
|
|
32
|
+
"name": "loop",
|
|
33
|
+
"flag": "--loop",
|
|
34
|
+
"type": "string",
|
|
35
|
+
"required": false,
|
|
36
|
+
"description": "Optional Loop id to run without dispatching other Loops."
|
|
37
|
+
}
|
|
38
|
+
],
|
|
31
39
|
"name": "loop-scheduler"
|
|
32
40
|
}
|
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.468",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"@actions/cache": "^6.0.0",
|
|
17
17
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
18
18
|
"@kody-ade/agency-domain": "0.5.1",
|
|
19
|
+
"@kody-ade/engine-contracts": "0.1.0",
|
|
19
20
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
20
21
|
"ajv": "^8.18.0",
|
|
21
22
|
"convex": "^1.17.0",
|