@kody-ade/kody-engine 0.4.467 → 0.4.469
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.469",
|
|
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
|
|
@@ -25322,6 +25282,16 @@ function routeRunRequest(request) {
|
|
|
25322
25282
|
cliArgs: { goal: target.id }
|
|
25323
25283
|
};
|
|
25324
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
|
+
}
|
|
25325
25295
|
if (target.type === "workflow") {
|
|
25326
25296
|
if (target.id === "scheduled-fanout") {
|
|
25327
25297
|
return { kind: "fanout", force: intent === "run" };
|
|
@@ -25329,7 +25299,8 @@ function routeRunRequest(request) {
|
|
|
25329
25299
|
if (intent !== "run" && intent !== "tick") {
|
|
25330
25300
|
return { kind: "error", error: `workflow target does not support intent '${intent}'` };
|
|
25331
25301
|
}
|
|
25332
|
-
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;
|
|
25333
25304
|
return { kind: "action", action: target.id, cliArgs: {}, ...workflowRunId ? { workflowRunId } : {} };
|
|
25334
25305
|
}
|
|
25335
25306
|
return { kind: "error", error: "unsupported run request target" };
|
|
@@ -25590,6 +25561,7 @@ async function runCi(argv) {
|
|
|
25590
25561
|
}
|
|
25591
25562
|
if (parsedRunRequest && "request" in parsedRunRequest) {
|
|
25592
25563
|
}
|
|
25564
|
+
const explicitLoopRequest = parsedRunRequest && "request" in parsedRunRequest && parsedRunRequest.request.target.type === "loop";
|
|
25593
25565
|
if (!args.issueNumber && !autoFallback && parsedRunRequest && "request" in parsedRunRequest) {
|
|
25594
25566
|
const route = routeRunRequest(parsedRunRequest.request);
|
|
25595
25567
|
if (route.kind === "error") {
|
|
@@ -25660,11 +25632,11 @@ async function runCi(argv) {
|
|
|
25660
25632
|
cliArgs: directExecution.cliArgs,
|
|
25661
25633
|
source: "project-folder"
|
|
25662
25634
|
} : null);
|
|
25663
|
-
const workflowRoute = manualGoalManager || capabilityRoute || !readWorkflowDefinition(config, cwd, forceRunAction) ? void 0 : {
|
|
25635
|
+
const workflowRoute = manualGoalManager || capabilityRoute || explicitLoopRequest || !readWorkflowDefinition(config, cwd, forceRunAction) ? void 0 : {
|
|
25664
25636
|
workflow: forceRunAction,
|
|
25665
25637
|
cliArgs: {}
|
|
25666
25638
|
};
|
|
25667
|
-
const loop = manualGoalManager || capabilityRoute || workflowRoute ? null : readLoopDefinition(cwd, forceRunAction);
|
|
25639
|
+
const loop = manualGoalManager || capabilityRoute || workflowRoute || explicitLoopRequest ? null : readLoopDefinition(cwd, forceRunAction);
|
|
25668
25640
|
const loopRoute = loop ? loop.target.kind === "workflow" ? { workflow: loop.target.id, cliArgs: loop.input } : { capability: loop.target.id, action: loop.target.id, cliArgs: loop.input } : void 0;
|
|
25669
25641
|
const scheduledWatchRoute = manualGoalManager || capabilityRoute || workflowRoute || loopRoute ? void 0 : dispatchScheduledWatches({ force: true, cwd }).find(
|
|
25670
25642
|
(match) => match.action === forceRunAction || match.capability === forceRunAction || match.implementation === forceRunAction
|
|
@@ -27541,10 +27513,12 @@ async function runAgencyLoopTick(deps) {
|
|
|
27541
27513
|
for (const repository of repositories) {
|
|
27542
27514
|
const [owner, repo] = repository.split("/");
|
|
27543
27515
|
try {
|
|
27516
|
+
const jobId = `sched-${owner}-${repo}-${clock()}`;
|
|
27544
27517
|
const result = await deps.claim(owner, repo, {
|
|
27545
|
-
jobId
|
|
27518
|
+
jobId,
|
|
27546
27519
|
repo: repository,
|
|
27547
27520
|
runRequest: {
|
|
27521
|
+
requestId: jobId,
|
|
27548
27522
|
target: { type: "workflow", id: "scheduled-fanout" },
|
|
27549
27523
|
intent: "tick",
|
|
27550
27524
|
source: "schedule"
|
|
@@ -28131,16 +28105,8 @@ function parseClaimRequest(body) {
|
|
|
28131
28105
|
if (!jobId) return { error: "jobId required" };
|
|
28132
28106
|
const repo = typeof b.repo === "string" ? b.repo.trim() : "";
|
|
28133
28107
|
if (!/^[^/\s]+\/[^/\s]+$/.test(repo)) return { error: "repo must be 'owner/name'" };
|
|
28134
|
-
|
|
28135
|
-
const
|
|
28136
|
-
const message = typeof b.message === "string" && b.message.trim() ? b.message.trim() : void 0;
|
|
28137
|
-
const runRequest = b.runRequest !== void 0 ? parseRunRequest(b.runRequest) : synthesizeLegacyClaimRequest({
|
|
28138
|
-
mode,
|
|
28139
|
-
issueNumber: b.issueNumber,
|
|
28140
|
-
sessionId: b.sessionId,
|
|
28141
|
-
action,
|
|
28142
|
-
message
|
|
28143
|
-
});
|
|
28108
|
+
if (b.runRequest === void 0) return { error: "runRequest required" };
|
|
28109
|
+
const runRequest = parseEngineExecutionRequest(b.runRequest);
|
|
28144
28110
|
if ("error" in runRequest) return { error: runRequest.error };
|
|
28145
28111
|
const req = { jobId, repo, runRequest: runRequest.request };
|
|
28146
28112
|
if (req.runRequest.target.type === "issue") {
|
|
@@ -28155,55 +28121,6 @@ function parseClaimRequest(body) {
|
|
|
28155
28121
|
if (typeof b.dashboardUrl === "string" && b.dashboardUrl.trim()) req.dashboardUrl = b.dashboardUrl.trim();
|
|
28156
28122
|
return { req };
|
|
28157
28123
|
}
|
|
28158
|
-
function synthesizeLegacyClaimRequest(input) {
|
|
28159
|
-
if (input.mode === "issue") {
|
|
28160
|
-
const issueNumber = Number(input.issueNumber);
|
|
28161
|
-
if (!Number.isInteger(issueNumber) || issueNumber <= 0) return { error: "issueNumber required for issue mode" };
|
|
28162
|
-
return {
|
|
28163
|
-
request: {
|
|
28164
|
-
target: { type: "issue", id: issueNumber },
|
|
28165
|
-
intent: "run",
|
|
28166
|
-
source: "dashboard"
|
|
28167
|
-
}
|
|
28168
|
-
};
|
|
28169
|
-
}
|
|
28170
|
-
if (input.mode === "interactive") {
|
|
28171
|
-
const sessionId = typeof input.sessionId === "string" ? input.sessionId.trim() : "";
|
|
28172
|
-
if (!sessionId) return { error: "sessionId required for interactive mode" };
|
|
28173
|
-
return {
|
|
28174
|
-
request: {
|
|
28175
|
-
target: { type: "chat", id: sessionId },
|
|
28176
|
-
intent: "continue",
|
|
28177
|
-
source: "dashboard"
|
|
28178
|
-
}
|
|
28179
|
-
};
|
|
28180
|
-
}
|
|
28181
|
-
if (input.action === "goal-manager" && input.message) {
|
|
28182
|
-
return {
|
|
28183
|
-
request: {
|
|
28184
|
-
target: { type: "goal", id: input.message },
|
|
28185
|
-
intent: "manage",
|
|
28186
|
-
source: "dashboard"
|
|
28187
|
-
}
|
|
28188
|
-
};
|
|
28189
|
-
}
|
|
28190
|
-
if (input.action) {
|
|
28191
|
-
return {
|
|
28192
|
-
request: {
|
|
28193
|
-
target: { type: "workflow", id: input.action },
|
|
28194
|
-
intent: "run",
|
|
28195
|
-
source: "dashboard"
|
|
28196
|
-
}
|
|
28197
|
-
};
|
|
28198
|
-
}
|
|
28199
|
-
return {
|
|
28200
|
-
request: {
|
|
28201
|
-
target: { type: "workflow", id: "scheduled-fanout" },
|
|
28202
|
-
intent: "tick",
|
|
28203
|
-
source: "schedule"
|
|
28204
|
-
}
|
|
28205
|
-
};
|
|
28206
|
-
}
|
|
28207
28124
|
async function poolServe() {
|
|
28208
28125
|
const masterRaw = process.env.KODY_MASTER_KEY?.trim();
|
|
28209
28126
|
if (!masterRaw) throw new Error("KODY_MASTER_KEY required for pool-serve");
|
|
@@ -28401,16 +28318,8 @@ function parseJob(body) {
|
|
|
28401
28318
|
if (!/^[^/\s]+\/[^/\s]+$/.test(repo)) return { error: "repo must be 'owner/name'" };
|
|
28402
28319
|
const githubToken = typeof b.githubToken === "string" ? b.githubToken.trim() : "";
|
|
28403
28320
|
if (!githubToken) return { error: "githubToken required" };
|
|
28404
|
-
|
|
28405
|
-
const
|
|
28406
|
-
const mode = b.mode === "interactive" ? "interactive" : b.mode === "scheduled" ? "scheduled" : "issue";
|
|
28407
|
-
const runRequest = b.runRequest !== void 0 ? parseRunRequest(b.runRequest) : synthesizeLegacyRunRequest({
|
|
28408
|
-
mode,
|
|
28409
|
-
issueNumber: b.issueNumber,
|
|
28410
|
-
sessionId: b.sessionId,
|
|
28411
|
-
action,
|
|
28412
|
-
message
|
|
28413
|
-
});
|
|
28321
|
+
if (b.runRequest === void 0) return { error: "runRequest required" };
|
|
28322
|
+
const runRequest = parseEngineExecutionRequest(b.runRequest);
|
|
28414
28323
|
if ("error" in runRequest) return { error: runRequest.error };
|
|
28415
28324
|
const job = { jobId, repo, githubToken, runRequest: runRequest.request };
|
|
28416
28325
|
if (job.runRequest.target.type === "issue") {
|
|
@@ -28429,57 +28338,6 @@ function parseJob(body) {
|
|
|
28429
28338
|
}
|
|
28430
28339
|
return { job };
|
|
28431
28340
|
}
|
|
28432
|
-
function synthesizeLegacyRunRequest(input) {
|
|
28433
|
-
if (input.mode === "issue") {
|
|
28434
|
-
const issueNumber = Number(input.issueNumber);
|
|
28435
|
-
if (!Number.isInteger(issueNumber) || issueNumber <= 0) {
|
|
28436
|
-
return { error: "issueNumber (positive integer) required for issue mode" };
|
|
28437
|
-
}
|
|
28438
|
-
return {
|
|
28439
|
-
request: {
|
|
28440
|
-
target: { type: "issue", id: issueNumber },
|
|
28441
|
-
intent: "run",
|
|
28442
|
-
source: "dashboard"
|
|
28443
|
-
}
|
|
28444
|
-
};
|
|
28445
|
-
}
|
|
28446
|
-
if (input.mode === "interactive") {
|
|
28447
|
-
const sessionId = typeof input.sessionId === "string" ? input.sessionId.trim() : "";
|
|
28448
|
-
if (!sessionId) return { error: "sessionId required for interactive mode" };
|
|
28449
|
-
return {
|
|
28450
|
-
request: {
|
|
28451
|
-
target: { type: "chat", id: sessionId },
|
|
28452
|
-
intent: "continue",
|
|
28453
|
-
source: "dashboard"
|
|
28454
|
-
}
|
|
28455
|
-
};
|
|
28456
|
-
}
|
|
28457
|
-
if (input.action === "goal-manager" && input.message) {
|
|
28458
|
-
return {
|
|
28459
|
-
request: {
|
|
28460
|
-
target: { type: "goal", id: input.message },
|
|
28461
|
-
intent: "manage",
|
|
28462
|
-
source: "dashboard"
|
|
28463
|
-
}
|
|
28464
|
-
};
|
|
28465
|
-
}
|
|
28466
|
-
if (input.action) {
|
|
28467
|
-
return {
|
|
28468
|
-
request: {
|
|
28469
|
-
target: { type: "workflow", id: input.action },
|
|
28470
|
-
intent: "run",
|
|
28471
|
-
source: "dashboard"
|
|
28472
|
-
}
|
|
28473
|
-
};
|
|
28474
|
-
}
|
|
28475
|
-
return {
|
|
28476
|
-
request: {
|
|
28477
|
-
target: { type: "workflow", id: "scheduled-fanout" },
|
|
28478
|
-
intent: "tick",
|
|
28479
|
-
source: "schedule"
|
|
28480
|
-
}
|
|
28481
|
-
};
|
|
28482
|
-
}
|
|
28483
28341
|
async function defaultRunJob(job) {
|
|
28484
28342
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
28485
28343
|
const branch = job.ref ?? "main";
|
|
@@ -28619,7 +28477,7 @@ async function runnerServe() {
|
|
|
28619
28477
|
init_config();
|
|
28620
28478
|
init_litellm();
|
|
28621
28479
|
import { spawn as spawn10 } from "child_process";
|
|
28622
|
-
function
|
|
28480
|
+
function parseTarget(positional) {
|
|
28623
28481
|
if (!Array.isArray(positional) || positional.length === 0) return "none";
|
|
28624
28482
|
const first = String(positional[0]).toLowerCase();
|
|
28625
28483
|
if (first === "vscode" || first === "code") return "vscode";
|
|
@@ -28634,7 +28492,7 @@ function buildProxyEnv(url) {
|
|
|
28634
28492
|
};
|
|
28635
28493
|
}
|
|
28636
28494
|
async function serve(opts) {
|
|
28637
|
-
const target =
|
|
28495
|
+
const target = parseTarget(opts.args);
|
|
28638
28496
|
const model = parseProviderModel(opts.config.agent.model);
|
|
28639
28497
|
const usesProxy = needsLitellmProxy(model);
|
|
28640
28498
|
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.469",
|
|
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",
|