@kody-ade/kody-engine 0.4.213 → 0.4.214-live.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/dist/bin/kody.js +193 -118
- 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.214-live.0",
|
|
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",
|
|
@@ -7232,6 +7232,9 @@ function parseFlatYaml(text) {
|
|
|
7232
7232
|
} else if (key === "tools") {
|
|
7233
7233
|
const names = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
7234
7234
|
if (names.length > 0) out.tools = names;
|
|
7235
|
+
} else if (key === "executables") {
|
|
7236
|
+
const names = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
7237
|
+
if (names.length > 0) out.executables = names;
|
|
7235
7238
|
}
|
|
7236
7239
|
}
|
|
7237
7240
|
return out;
|
|
@@ -7665,6 +7668,119 @@ var init_jobState = __esm({
|
|
|
7665
7668
|
}
|
|
7666
7669
|
});
|
|
7667
7670
|
|
|
7671
|
+
// src/scripts/planTaskJobs.ts
|
|
7672
|
+
function parseTaskJobSpecs(body) {
|
|
7673
|
+
const match = body.match(new RegExp(`<!--\\s*${TASK_JOBS_MARKER}\\s*([\\s\\S]*?)-->`));
|
|
7674
|
+
if (!match) return [];
|
|
7675
|
+
let parsed;
|
|
7676
|
+
try {
|
|
7677
|
+
parsed = JSON.parse(match[1].trim());
|
|
7678
|
+
} catch (err) {
|
|
7679
|
+
throw new Error(`task job plan is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
7680
|
+
}
|
|
7681
|
+
if (!Array.isArray(parsed)) throw new Error("task job plan must be a JSON array");
|
|
7682
|
+
return parsed.map((entry, index) => normalizeSpec(entry, index));
|
|
7683
|
+
}
|
|
7684
|
+
function taskJobSpecToJob(spec, issueNumber) {
|
|
7685
|
+
const cliArgs = spec.cliArgs ?? { issue: issueNumber };
|
|
7686
|
+
const target = typeof spec.target === "number" ? spec.target : targetFromCliArgs(cliArgs) ?? issueNumber;
|
|
7687
|
+
return {
|
|
7688
|
+
duty: spec.duty,
|
|
7689
|
+
executable: spec.executable,
|
|
7690
|
+
why: spec.reason,
|
|
7691
|
+
persona: spec.persona ?? spec.staff,
|
|
7692
|
+
schedule: spec.schedule,
|
|
7693
|
+
target,
|
|
7694
|
+
cliArgs,
|
|
7695
|
+
flavor: spec.flavor ?? "instant"
|
|
7696
|
+
};
|
|
7697
|
+
}
|
|
7698
|
+
function normalizeSpec(input, index) {
|
|
7699
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
7700
|
+
throw new Error(`task job plan entry ${index} must be an object`);
|
|
7701
|
+
}
|
|
7702
|
+
const raw = input;
|
|
7703
|
+
const executable = typeof raw.executable === "string" ? raw.executable.trim() : "";
|
|
7704
|
+
if (!/^[a-z][a-z0-9-]*$/.test(executable)) {
|
|
7705
|
+
throw new Error(`task job plan entry ${index} must have a valid executable`);
|
|
7706
|
+
}
|
|
7707
|
+
const cliArgs = raw.cliArgs;
|
|
7708
|
+
if (cliArgs !== void 0 && (!cliArgs || typeof cliArgs !== "object" || Array.isArray(cliArgs))) {
|
|
7709
|
+
throw new Error(`task job plan entry ${index} cliArgs must be an object`);
|
|
7710
|
+
}
|
|
7711
|
+
const flavor = raw.flavor;
|
|
7712
|
+
if (flavor !== void 0 && flavor !== "instant" && flavor !== "scheduled") {
|
|
7713
|
+
throw new Error(`task job plan entry ${index} flavor must be "instant" or "scheduled"`);
|
|
7714
|
+
}
|
|
7715
|
+
return {
|
|
7716
|
+
executable,
|
|
7717
|
+
...typeof raw.duty === "string" && raw.duty.trim() ? { duty: raw.duty.trim() } : {},
|
|
7718
|
+
...typeof raw.reason === "string" && raw.reason.trim() ? { reason: raw.reason.trim() } : {},
|
|
7719
|
+
...typeof raw.staff === "string" && raw.staff.trim() ? { staff: raw.staff.trim() } : {},
|
|
7720
|
+
...typeof raw.persona === "string" && raw.persona.trim() ? { persona: raw.persona.trim() } : {},
|
|
7721
|
+
...cliArgs ? { cliArgs } : {},
|
|
7722
|
+
...typeof raw.target === "number" && Number.isFinite(raw.target) ? { target: raw.target } : {},
|
|
7723
|
+
...flavor === "instant" || flavor === "scheduled" ? { flavor } : {},
|
|
7724
|
+
...typeof raw.schedule === "string" && raw.schedule.trim() ? { schedule: raw.schedule.trim() } : {}
|
|
7725
|
+
};
|
|
7726
|
+
}
|
|
7727
|
+
function jobToPlannedTaskJob(job) {
|
|
7728
|
+
return {
|
|
7729
|
+
id: stableJobKey(job),
|
|
7730
|
+
executable: job.executable ?? job.duty ?? "unknown",
|
|
7731
|
+
...job.duty ? { duty: job.duty } : {},
|
|
7732
|
+
...job.persona ? { staff: job.persona } : {},
|
|
7733
|
+
...job.flavor ? { flavor: job.flavor } : {},
|
|
7734
|
+
...job.schedule ? { schedule: job.schedule } : {},
|
|
7735
|
+
...typeof job.target === "number" ? { target: job.target } : {},
|
|
7736
|
+
...job.why ? { reason: job.why } : {}
|
|
7737
|
+
};
|
|
7738
|
+
}
|
|
7739
|
+
function assertUniqueJobIds(planned) {
|
|
7740
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7741
|
+
for (const job of planned) {
|
|
7742
|
+
if (seen.has(job.id)) throw new Error(`duplicate planned task job id: ${job.id}`);
|
|
7743
|
+
seen.add(job.id);
|
|
7744
|
+
}
|
|
7745
|
+
}
|
|
7746
|
+
var TASK_JOBS_MARKER, planTaskJobs;
|
|
7747
|
+
var init_planTaskJobs = __esm({
|
|
7748
|
+
"src/scripts/planTaskJobs.ts"() {
|
|
7749
|
+
"use strict";
|
|
7750
|
+
init_jobIdentity();
|
|
7751
|
+
init_state();
|
|
7752
|
+
TASK_JOBS_MARKER = "kody:task-jobs:v1";
|
|
7753
|
+
planTaskJobs = async (ctx) => {
|
|
7754
|
+
const issueNumber = ctx.args.issue;
|
|
7755
|
+
if (!issueNumber) {
|
|
7756
|
+
ctx.skipAgent = true;
|
|
7757
|
+
ctx.output.exitCode = 64;
|
|
7758
|
+
ctx.output.reason = "planTaskJobs requires --issue";
|
|
7759
|
+
return;
|
|
7760
|
+
}
|
|
7761
|
+
const issue = ctx.data.issue;
|
|
7762
|
+
const specs = parseTaskJobSpecs(issue?.body ?? "");
|
|
7763
|
+
if (specs.length === 0) {
|
|
7764
|
+
ctx.skipAgent = true;
|
|
7765
|
+
ctx.output.exitCode = 64;
|
|
7766
|
+
ctx.output.reason = `no ${TASK_JOBS_MARKER} block found on issue #${issueNumber}`;
|
|
7767
|
+
return;
|
|
7768
|
+
}
|
|
7769
|
+
const jobs = specs.map((spec) => taskJobSpecToJob(spec, issueNumber));
|
|
7770
|
+
const planned = jobs.map(jobToPlannedTaskJob);
|
|
7771
|
+
assertUniqueJobIds(planned);
|
|
7772
|
+
const prior = ctx.data.taskState ?? emptyState();
|
|
7773
|
+
const next = upsertTaskJobs(prior, planned, (/* @__PURE__ */ new Date()).toISOString());
|
|
7774
|
+
ctx.data.taskState = next;
|
|
7775
|
+
ctx.data.plannedTaskJobs = jobs;
|
|
7776
|
+
ctx.data.plannedTaskJobIds = planned.map((job) => job.id);
|
|
7777
|
+
const target = ctx.data.commentTargetType;
|
|
7778
|
+
const number = ctx.data.commentTargetNumber;
|
|
7779
|
+
if (target && number) writeTaskState(target, number, next, ctx.cwd);
|
|
7780
|
+
};
|
|
7781
|
+
}
|
|
7782
|
+
});
|
|
7783
|
+
|
|
7668
7784
|
// src/scripts/dispatchDutyFileTicks.ts
|
|
7669
7785
|
import * as fs29 from "fs";
|
|
7670
7786
|
import * as path26 from "path";
|
|
@@ -7708,14 +7824,43 @@ function formatAgo(ms) {
|
|
|
7708
7824
|
const day = Math.round(hr / 24);
|
|
7709
7825
|
return `${day}d`;
|
|
7710
7826
|
}
|
|
7711
|
-
function
|
|
7827
|
+
function readJobFile(cwd, jobsDir, slug) {
|
|
7712
7828
|
try {
|
|
7713
7829
|
const raw = fs29.readFileSync(path26.join(cwd, jobsDir, `${slug}.md`), "utf-8");
|
|
7714
|
-
return splitFrontmatter2(raw)
|
|
7830
|
+
return splitFrontmatter2(raw);
|
|
7715
7831
|
} catch {
|
|
7716
|
-
return {};
|
|
7832
|
+
return { frontmatter: {}, body: "" };
|
|
7717
7833
|
}
|
|
7718
7834
|
}
|
|
7835
|
+
function createDutyTaskIssue(opts) {
|
|
7836
|
+
const title = `Duty ${opts.slug} - multi-executable task`;
|
|
7837
|
+
const body = buildDutyTaskIssueBody(opts.slug, opts.body, opts.frontmatter);
|
|
7838
|
+
const out = gh(["issue", "create", "--title", title, "--body-file", "-"], { input: body, cwd: opts.cwd });
|
|
7839
|
+
const url = out.split("\n").map((line) => line.trim()).filter(Boolean).pop() ?? "";
|
|
7840
|
+
const match = url.match(/\/issues\/(\d+)\b/);
|
|
7841
|
+
if (!match) throw new Error(`gh issue create returned unexpected output: ${out}`);
|
|
7842
|
+
return { number: Number(match[1]), url };
|
|
7843
|
+
}
|
|
7844
|
+
function buildDutyTaskIssueBody(slug, dutyBody, frontmatter) {
|
|
7845
|
+
const specs = (frontmatter.executables ?? []).map((executable) => ({
|
|
7846
|
+
executable,
|
|
7847
|
+
duty: slug,
|
|
7848
|
+
...frontmatter.staff ? { staff: frontmatter.staff } : {},
|
|
7849
|
+
reason: `Duty \`${slug}\` slice for \`${executable}\`.`,
|
|
7850
|
+
flavor: "scheduled",
|
|
7851
|
+
...frontmatter.every ? { schedule: frontmatter.every } : {}
|
|
7852
|
+
}));
|
|
7853
|
+
return [
|
|
7854
|
+
`# Duty task: ${slug}`,
|
|
7855
|
+
"",
|
|
7856
|
+
dutyBody.trim() || "(no duty body)",
|
|
7857
|
+
"",
|
|
7858
|
+
`<!-- ${TASK_JOBS_MARKER}`,
|
|
7859
|
+
JSON.stringify(specs, null, 2),
|
|
7860
|
+
"-->",
|
|
7861
|
+
""
|
|
7862
|
+
].join("\n");
|
|
7863
|
+
}
|
|
7719
7864
|
function listJobSlugs(absDir) {
|
|
7720
7865
|
if (!fs29.existsSync(absDir)) return [];
|
|
7721
7866
|
let entries;
|
|
@@ -7736,10 +7881,14 @@ function listFolderDutySlugs(absDir) {
|
|
|
7736
7881
|
}
|
|
7737
7882
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => fs29.existsSync(path26.join(absDir, e.name, "profile.json"))).map((e) => e.name).sort();
|
|
7738
7883
|
}
|
|
7739
|
-
async function stampFired(backend, slug, now) {
|
|
7884
|
+
async function stampFired(backend, slug, now, task) {
|
|
7740
7885
|
try {
|
|
7741
7886
|
const loaded = await backend.load(slug);
|
|
7742
|
-
const nextData = {
|
|
7887
|
+
const nextData = {
|
|
7888
|
+
...loaded.state.data ?? {},
|
|
7889
|
+
lastFiredAt: new Date(now).toISOString(),
|
|
7890
|
+
...task ? { lastTaskIssue: task.number, lastTaskUrl: task.url } : {}
|
|
7891
|
+
};
|
|
7743
7892
|
await backend.save(loaded, { ...loaded.state, data: nextData });
|
|
7744
7893
|
} catch (err) {
|
|
7745
7894
|
process.stderr.write(`[jobs] failed to stamp lastFiredAt for ${slug}: ${String(err)}
|
|
@@ -7750,10 +7899,12 @@ var dispatchDutyFileTicks;
|
|
|
7750
7899
|
var init_dispatchDutyFileTicks = __esm({
|
|
7751
7900
|
"src/scripts/dispatchDutyFileTicks.ts"() {
|
|
7752
7901
|
"use strict";
|
|
7902
|
+
init_issue();
|
|
7753
7903
|
init_job();
|
|
7754
7904
|
init_profile();
|
|
7755
7905
|
init_jobFrontmatter();
|
|
7756
7906
|
init_jobState();
|
|
7907
|
+
init_planTaskJobs();
|
|
7757
7908
|
dispatchDutyFileTicks = async (ctx, _profile, args) => {
|
|
7758
7909
|
ctx.skipAgent = true;
|
|
7759
7910
|
const targetExecutable = String(args?.targetExecutable ?? "");
|
|
@@ -7837,7 +7988,8 @@ var init_dispatchDutyFileTicks = __esm({
|
|
|
7837
7988
|
results.push({ slug, exitCode: 0, skipped: true, reason: "handled as folder-duty" });
|
|
7838
7989
|
continue;
|
|
7839
7990
|
}
|
|
7840
|
-
const
|
|
7991
|
+
const dutyFile = readJobFile(ctx.cwd, jobsDir, slug);
|
|
7992
|
+
const frontmatter = dutyFile.frontmatter;
|
|
7841
7993
|
if (frontmatter.disabled === true) {
|
|
7842
7994
|
process.stdout.write(`[jobs] \u23ED skip ${slug}: disabled in frontmatter
|
|
7843
7995
|
`);
|
|
@@ -7857,6 +8009,40 @@ var init_dispatchDutyFileTicks = __esm({
|
|
|
7857
8009
|
results.push({ slug, exitCode: 0, skipped: true, reason: decision.reason });
|
|
7858
8010
|
continue;
|
|
7859
8011
|
}
|
|
8012
|
+
if (frontmatter.executables && frontmatter.executables.length > 0) {
|
|
8013
|
+
try {
|
|
8014
|
+
const task = createDutyTaskIssue({
|
|
8015
|
+
slug,
|
|
8016
|
+
body: dutyFile.body,
|
|
8017
|
+
frontmatter,
|
|
8018
|
+
cwd: ctx.cwd
|
|
8019
|
+
});
|
|
8020
|
+
await stampFired(backend, slug, now, task);
|
|
8021
|
+
process.stdout.write(`[jobs] \u2192 run ${slug} multi-executable task #${task.number} (task-jobs)
|
|
8022
|
+
`);
|
|
8023
|
+
const out = await runJob(
|
|
8024
|
+
mintScheduledJob({
|
|
8025
|
+
duty: slug,
|
|
8026
|
+
executable: "task-jobs",
|
|
8027
|
+
schedule: frontmatter.every,
|
|
8028
|
+
persona: frontmatter.staff,
|
|
8029
|
+
cliArgs: { issue: task.number }
|
|
8030
|
+
}),
|
|
8031
|
+
{ cwd: ctx.cwd, config: ctx.config, verbose: ctx.verbose, quiet: ctx.quiet }
|
|
8032
|
+
);
|
|
8033
|
+
results.push({ slug, exitCode: out.exitCode, reason: out.reason });
|
|
8034
|
+
if (out.exitCode !== 0) {
|
|
8035
|
+
process.stderr.write(`[jobs] task ${slug} failed (exit ${out.exitCode}): ${out.reason ?? ""}
|
|
8036
|
+
`);
|
|
8037
|
+
}
|
|
8038
|
+
} catch (err) {
|
|
8039
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
8040
|
+
process.stderr.write(`[jobs] task ${slug} crashed: ${msg}
|
|
8041
|
+
`);
|
|
8042
|
+
results.push({ slug, exitCode: 99, reason: msg });
|
|
8043
|
+
}
|
|
8044
|
+
continue;
|
|
8045
|
+
}
|
|
7860
8046
|
const slugTarget = frontmatter.tickScript ? scriptedExecutable : targetExecutable;
|
|
7861
8047
|
process.stdout.write(`[jobs] \u2192 tick ${slug} (${slugTarget})
|
|
7862
8048
|
`);
|
|
@@ -10684,117 +10870,6 @@ var init_persistFlowState = __esm({
|
|
|
10684
10870
|
}
|
|
10685
10871
|
});
|
|
10686
10872
|
|
|
10687
|
-
// src/scripts/planTaskJobs.ts
|
|
10688
|
-
function parseTaskJobSpecs(body) {
|
|
10689
|
-
const match = body.match(new RegExp(`<!--\\s*${TASK_JOBS_MARKER}\\s*([\\s\\S]*?)-->`));
|
|
10690
|
-
if (!match) return [];
|
|
10691
|
-
let parsed;
|
|
10692
|
-
try {
|
|
10693
|
-
parsed = JSON.parse(match[1].trim());
|
|
10694
|
-
} catch (err) {
|
|
10695
|
-
throw new Error(`task job plan is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
10696
|
-
}
|
|
10697
|
-
if (!Array.isArray(parsed)) throw new Error("task job plan must be a JSON array");
|
|
10698
|
-
return parsed.map((entry, index) => normalizeSpec(entry, index));
|
|
10699
|
-
}
|
|
10700
|
-
function taskJobSpecToJob(spec, issueNumber) {
|
|
10701
|
-
const cliArgs = spec.cliArgs ?? { issue: issueNumber };
|
|
10702
|
-
const target = typeof spec.target === "number" ? spec.target : targetFromCliArgs(cliArgs) ?? issueNumber;
|
|
10703
|
-
return {
|
|
10704
|
-
executable: spec.executable,
|
|
10705
|
-
why: spec.reason,
|
|
10706
|
-
persona: spec.persona ?? spec.staff,
|
|
10707
|
-
schedule: spec.schedule,
|
|
10708
|
-
target,
|
|
10709
|
-
cliArgs,
|
|
10710
|
-
flavor: spec.flavor ?? "instant"
|
|
10711
|
-
};
|
|
10712
|
-
}
|
|
10713
|
-
function normalizeSpec(input, index) {
|
|
10714
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
10715
|
-
throw new Error(`task job plan entry ${index} must be an object`);
|
|
10716
|
-
}
|
|
10717
|
-
const raw = input;
|
|
10718
|
-
const executable = typeof raw.executable === "string" ? raw.executable.trim() : "";
|
|
10719
|
-
if (!/^[a-z][a-z0-9-]*$/.test(executable)) {
|
|
10720
|
-
throw new Error(`task job plan entry ${index} must have a valid executable`);
|
|
10721
|
-
}
|
|
10722
|
-
const cliArgs = raw.cliArgs;
|
|
10723
|
-
if (cliArgs !== void 0 && (!cliArgs || typeof cliArgs !== "object" || Array.isArray(cliArgs))) {
|
|
10724
|
-
throw new Error(`task job plan entry ${index} cliArgs must be an object`);
|
|
10725
|
-
}
|
|
10726
|
-
const flavor = raw.flavor;
|
|
10727
|
-
if (flavor !== void 0 && flavor !== "instant" && flavor !== "scheduled") {
|
|
10728
|
-
throw new Error(`task job plan entry ${index} flavor must be "instant" or "scheduled"`);
|
|
10729
|
-
}
|
|
10730
|
-
return {
|
|
10731
|
-
executable,
|
|
10732
|
-
...typeof raw.reason === "string" && raw.reason.trim() ? { reason: raw.reason.trim() } : {},
|
|
10733
|
-
...typeof raw.staff === "string" && raw.staff.trim() ? { staff: raw.staff.trim() } : {},
|
|
10734
|
-
...typeof raw.persona === "string" && raw.persona.trim() ? { persona: raw.persona.trim() } : {},
|
|
10735
|
-
...cliArgs ? { cliArgs } : {},
|
|
10736
|
-
...typeof raw.target === "number" && Number.isFinite(raw.target) ? { target: raw.target } : {},
|
|
10737
|
-
...flavor === "instant" || flavor === "scheduled" ? { flavor } : {},
|
|
10738
|
-
...typeof raw.schedule === "string" && raw.schedule.trim() ? { schedule: raw.schedule.trim() } : {}
|
|
10739
|
-
};
|
|
10740
|
-
}
|
|
10741
|
-
function jobToPlannedTaskJob(job) {
|
|
10742
|
-
return {
|
|
10743
|
-
id: stableJobKey(job),
|
|
10744
|
-
executable: job.executable ?? job.duty ?? "unknown",
|
|
10745
|
-
...job.duty ? { duty: job.duty } : {},
|
|
10746
|
-
...job.persona ? { staff: job.persona } : {},
|
|
10747
|
-
...job.flavor ? { flavor: job.flavor } : {},
|
|
10748
|
-
...job.schedule ? { schedule: job.schedule } : {},
|
|
10749
|
-
...typeof job.target === "number" ? { target: job.target } : {},
|
|
10750
|
-
...job.why ? { reason: job.why } : {}
|
|
10751
|
-
};
|
|
10752
|
-
}
|
|
10753
|
-
function assertUniqueJobIds(planned) {
|
|
10754
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10755
|
-
for (const job of planned) {
|
|
10756
|
-
if (seen.has(job.id)) throw new Error(`duplicate planned task job id: ${job.id}`);
|
|
10757
|
-
seen.add(job.id);
|
|
10758
|
-
}
|
|
10759
|
-
}
|
|
10760
|
-
var TASK_JOBS_MARKER, planTaskJobs;
|
|
10761
|
-
var init_planTaskJobs = __esm({
|
|
10762
|
-
"src/scripts/planTaskJobs.ts"() {
|
|
10763
|
-
"use strict";
|
|
10764
|
-
init_jobIdentity();
|
|
10765
|
-
init_state();
|
|
10766
|
-
TASK_JOBS_MARKER = "kody:task-jobs:v1";
|
|
10767
|
-
planTaskJobs = async (ctx) => {
|
|
10768
|
-
const issueNumber = ctx.args.issue;
|
|
10769
|
-
if (!issueNumber) {
|
|
10770
|
-
ctx.skipAgent = true;
|
|
10771
|
-
ctx.output.exitCode = 64;
|
|
10772
|
-
ctx.output.reason = "planTaskJobs requires --issue";
|
|
10773
|
-
return;
|
|
10774
|
-
}
|
|
10775
|
-
const issue = ctx.data.issue;
|
|
10776
|
-
const specs = parseTaskJobSpecs(issue?.body ?? "");
|
|
10777
|
-
if (specs.length === 0) {
|
|
10778
|
-
ctx.skipAgent = true;
|
|
10779
|
-
ctx.output.exitCode = 64;
|
|
10780
|
-
ctx.output.reason = `no ${TASK_JOBS_MARKER} block found on issue #${issueNumber}`;
|
|
10781
|
-
return;
|
|
10782
|
-
}
|
|
10783
|
-
const jobs = specs.map((spec) => taskJobSpecToJob(spec, issueNumber));
|
|
10784
|
-
const planned = jobs.map(jobToPlannedTaskJob);
|
|
10785
|
-
assertUniqueJobIds(planned);
|
|
10786
|
-
const prior = ctx.data.taskState ?? emptyState();
|
|
10787
|
-
const next = upsertTaskJobs(prior, planned, (/* @__PURE__ */ new Date()).toISOString());
|
|
10788
|
-
ctx.data.taskState = next;
|
|
10789
|
-
ctx.data.plannedTaskJobs = jobs;
|
|
10790
|
-
ctx.data.plannedTaskJobIds = planned.map((job) => job.id);
|
|
10791
|
-
const target = ctx.data.commentTargetType;
|
|
10792
|
-
const number = ctx.data.commentTargetNumber;
|
|
10793
|
-
if (target && number) writeTaskState(target, number, next, ctx.cwd);
|
|
10794
|
-
};
|
|
10795
|
-
}
|
|
10796
|
-
});
|
|
10797
|
-
|
|
10798
10873
|
// src/scripts/postAgentSummaryComment.ts
|
|
10799
10874
|
function postAgentSummaryComment(ctx, opts = {}) {
|
|
10800
10875
|
if (!ctx.data.agentDone) return;
|
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.214-live.0",
|
|
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",
|