@kody-ade/kody-engine 0.4.67 → 0.4.69
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 +83 -175
- package/dist/executables/ui-review/profile.json +0 -1
- package/package.json +3 -1
package/dist/bin/kody.js
CHANGED
|
@@ -864,7 +864,7 @@ var init_loadPriorArt = __esm({
|
|
|
864
864
|
// package.json
|
|
865
865
|
var package_default = {
|
|
866
866
|
name: "@kody-ade/kody-engine",
|
|
867
|
-
version: "0.4.
|
|
867
|
+
version: "0.4.69",
|
|
868
868
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
869
869
|
license: "MIT",
|
|
870
870
|
type: "module",
|
|
@@ -879,6 +879,8 @@ var package_default = {
|
|
|
879
879
|
scripts: {
|
|
880
880
|
kody: "tsx bin/kody.ts",
|
|
881
881
|
build: "tsup && node scripts/copy-assets.cjs",
|
|
882
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
883
|
+
pretest: "pnpm check:modularity",
|
|
882
884
|
test: "vitest run tests/unit tests/int --no-coverage",
|
|
883
885
|
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
884
886
|
"test:all": "vitest run tests --no-coverage",
|
|
@@ -1410,6 +1412,48 @@ async function runAgent(opts) {
|
|
|
1410
1412
|
if (line) process.stdout.write(`${line}
|
|
1411
1413
|
`);
|
|
1412
1414
|
const m = msg;
|
|
1415
|
+
if (opts.onProgress) {
|
|
1416
|
+
const blocks = m.message?.content ?? [];
|
|
1417
|
+
for (const block of blocks) {
|
|
1418
|
+
try {
|
|
1419
|
+
if (block.type === "thinking") {
|
|
1420
|
+
const t = block.thinking;
|
|
1421
|
+
if (typeof t === "string" && t.length > 0) {
|
|
1422
|
+
await opts.onProgress({ kind: "thinking", thinking: t });
|
|
1423
|
+
}
|
|
1424
|
+
} else if (block.type === "tool_use") {
|
|
1425
|
+
const b = block;
|
|
1426
|
+
await opts.onProgress({
|
|
1427
|
+
kind: "tool_use",
|
|
1428
|
+
name: b.name ?? "tool",
|
|
1429
|
+
input: b.input,
|
|
1430
|
+
id: b.id
|
|
1431
|
+
});
|
|
1432
|
+
} else if (block.type === "tool_result") {
|
|
1433
|
+
const b = block;
|
|
1434
|
+
const content = typeof b.content === "string" ? b.content : (() => {
|
|
1435
|
+
try {
|
|
1436
|
+
return JSON.stringify(b.content);
|
|
1437
|
+
} catch {
|
|
1438
|
+
return "";
|
|
1439
|
+
}
|
|
1440
|
+
})();
|
|
1441
|
+
await opts.onProgress({
|
|
1442
|
+
kind: "tool_result",
|
|
1443
|
+
toolUseId: b.tool_use_id,
|
|
1444
|
+
content,
|
|
1445
|
+
isError: b.is_error
|
|
1446
|
+
});
|
|
1447
|
+
} else if (block.type === "text") {
|
|
1448
|
+
const b = block;
|
|
1449
|
+
if (typeof b.text === "string" && b.text.length > 0) {
|
|
1450
|
+
await opts.onProgress({ kind: "text", text: b.text });
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
} catch {
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1413
1457
|
const usage = m.usage;
|
|
1414
1458
|
if (usage && typeof usage === "object") {
|
|
1415
1459
|
const i = Number(usage.input_tokens ?? 0);
|
|
@@ -1596,6 +1640,7 @@ async function runChatTurn(opts) {
|
|
|
1596
1640
|
}
|
|
1597
1641
|
const systemPrompt = opts.systemPrompt ?? CHAT_SYSTEM_PROMPT;
|
|
1598
1642
|
const prompt = buildPrompt(turns);
|
|
1643
|
+
let progressSeq = 0;
|
|
1599
1644
|
const invoke = opts.invokeAgent ?? ((p) => runAgent({
|
|
1600
1645
|
prompt: p,
|
|
1601
1646
|
model: opts.model,
|
|
@@ -1603,7 +1648,29 @@ async function runChatTurn(opts) {
|
|
|
1603
1648
|
litellmUrl: opts.litellmUrl,
|
|
1604
1649
|
verbose: opts.verbose,
|
|
1605
1650
|
quiet: opts.quiet,
|
|
1606
|
-
systemPromptAppend: systemPrompt
|
|
1651
|
+
systemPromptAppend: systemPrompt,
|
|
1652
|
+
onProgress: async (ev) => {
|
|
1653
|
+
progressSeq += 1;
|
|
1654
|
+
if (ev.kind === "thinking") {
|
|
1655
|
+
await emit(opts.sink, "chat.thinking", opts.sessionId, `think-${progressSeq}`, {
|
|
1656
|
+
text: ev.thinking
|
|
1657
|
+
});
|
|
1658
|
+
} else if (ev.kind === "tool_use") {
|
|
1659
|
+
await emit(opts.sink, "chat.tool", opts.sessionId, `tool-${progressSeq}`, {
|
|
1660
|
+
phase: "use",
|
|
1661
|
+
id: ev.id,
|
|
1662
|
+
name: ev.name,
|
|
1663
|
+
input: ev.input ?? {}
|
|
1664
|
+
});
|
|
1665
|
+
} else if (ev.kind === "tool_result") {
|
|
1666
|
+
await emit(opts.sink, "chat.tool", opts.sessionId, `tool-${progressSeq}`, {
|
|
1667
|
+
phase: "result",
|
|
1668
|
+
toolUseId: ev.toolUseId,
|
|
1669
|
+
content: ev.content,
|
|
1670
|
+
isError: ev.isError === true
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1607
1674
|
}));
|
|
1608
1675
|
let result;
|
|
1609
1676
|
try {
|
|
@@ -2328,7 +2395,7 @@ function coerceBare(spec, value) {
|
|
|
2328
2395
|
init_issue();
|
|
2329
2396
|
|
|
2330
2397
|
// src/executor.ts
|
|
2331
|
-
import { execFileSync as execFileSync29, spawn as
|
|
2398
|
+
import { execFileSync as execFileSync29, spawn as spawn5 } from "child_process";
|
|
2332
2399
|
import * as fs31 from "fs";
|
|
2333
2400
|
import * as path29 from "path";
|
|
2334
2401
|
init_events();
|
|
@@ -9038,164 +9105,6 @@ function postKodyComment(target, issueNumber, state, next, cwd) {
|
|
|
9038
9105
|
}
|
|
9039
9106
|
}
|
|
9040
9107
|
|
|
9041
|
-
// src/scripts/startLocalServer.ts
|
|
9042
|
-
import { spawn as spawn3 } from "child_process";
|
|
9043
|
-
import { existsSync as existsSync26, readFileSync as readFileSync24 } from "fs";
|
|
9044
|
-
import { join as join27 } from "path";
|
|
9045
|
-
var READY_TIMEOUT_MS = 12e4;
|
|
9046
|
-
var READY_POLL_MS = 1e3;
|
|
9047
|
-
var INSTALL_TIMEOUT_MS = 3e5;
|
|
9048
|
-
var FETCH_TIMEOUT_MS = 2e3;
|
|
9049
|
-
var DEFAULT_PORT = 3e3;
|
|
9050
|
-
var startLocalServer = async (ctx) => {
|
|
9051
|
-
if (urlAlreadyResolved(ctx)) {
|
|
9052
|
-
process.stderr.write("[kody startLocalServer] preview URL already set \u2014 skipping\n");
|
|
9053
|
-
return;
|
|
9054
|
-
}
|
|
9055
|
-
const pkg = readPackageJson(ctx.cwd);
|
|
9056
|
-
if (!pkg) return;
|
|
9057
|
-
const scriptName = pickScript(pkg.scripts);
|
|
9058
|
-
if (!scriptName) {
|
|
9059
|
-
process.stderr.write("[kody startLocalServer] no dev/start script in package.json \u2014 skipping\n");
|
|
9060
|
-
return;
|
|
9061
|
-
}
|
|
9062
|
-
const pm = detectPackageManager2(ctx.cwd);
|
|
9063
|
-
const port = pickPort();
|
|
9064
|
-
await ensureDependenciesInstalled(pm, ctx.cwd);
|
|
9065
|
-
const url = `http://localhost:${port}`;
|
|
9066
|
-
process.stderr.write(`[kody startLocalServer] spawning '${pm} run ${scriptName}' on ${url}
|
|
9067
|
-
`);
|
|
9068
|
-
const child = spawnServer(pm, scriptName, port, ctx.cwd);
|
|
9069
|
-
registerProcessCleanup(child);
|
|
9070
|
-
const ready = await waitForReady(url, READY_TIMEOUT_MS);
|
|
9071
|
-
if (!ready) {
|
|
9072
|
-
safeKill(child);
|
|
9073
|
-
throw new Error(
|
|
9074
|
-
`startLocalServer: dev server at ${url} did not become reachable within ${READY_TIMEOUT_MS}ms`
|
|
9075
|
-
);
|
|
9076
|
-
}
|
|
9077
|
-
process.env.PREVIEW_URL = url;
|
|
9078
|
-
ctx.data.qaServerPid = child.pid;
|
|
9079
|
-
ctx.data.qaServerScript = scriptName;
|
|
9080
|
-
process.stderr.write(`[kody startLocalServer] ready: ${url}
|
|
9081
|
-
`);
|
|
9082
|
-
};
|
|
9083
|
-
function urlAlreadyResolved(ctx) {
|
|
9084
|
-
const fromFlag = typeof ctx.args.previewUrl === "string" ? ctx.args.previewUrl.trim() : "";
|
|
9085
|
-
if (fromFlag.length > 0) return true;
|
|
9086
|
-
const fromEnv = (process.env.PREVIEW_URL ?? "").trim();
|
|
9087
|
-
return fromEnv.length > 0;
|
|
9088
|
-
}
|
|
9089
|
-
function readPackageJson(cwd) {
|
|
9090
|
-
const path32 = join27(cwd, "package.json");
|
|
9091
|
-
if (!existsSync26(path32)) {
|
|
9092
|
-
process.stderr.write("[kody startLocalServer] no package.json \u2014 skipping\n");
|
|
9093
|
-
return null;
|
|
9094
|
-
}
|
|
9095
|
-
try {
|
|
9096
|
-
const raw = JSON.parse(readFileSync24(path32, "utf8"));
|
|
9097
|
-
return { scripts: raw.scripts ?? {} };
|
|
9098
|
-
} catch (err) {
|
|
9099
|
-
process.stderr.write(
|
|
9100
|
-
`[kody startLocalServer] could not parse package.json: ${err.message}
|
|
9101
|
-
`
|
|
9102
|
-
);
|
|
9103
|
-
return null;
|
|
9104
|
-
}
|
|
9105
|
-
}
|
|
9106
|
-
function pickScript(scripts) {
|
|
9107
|
-
if (typeof scripts.dev === "string" && scripts.dev.length > 0) return "dev";
|
|
9108
|
-
if (typeof scripts.start === "string" && scripts.start.length > 0) return "start";
|
|
9109
|
-
return null;
|
|
9110
|
-
}
|
|
9111
|
-
function detectPackageManager2(cwd) {
|
|
9112
|
-
if (existsSync26(join27(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
9113
|
-
if (existsSync26(join27(cwd, "yarn.lock"))) return "yarn";
|
|
9114
|
-
return "npm";
|
|
9115
|
-
}
|
|
9116
|
-
function pickPort() {
|
|
9117
|
-
const fromEnv = Number((process.env.PREVIEW_PORT ?? "").trim());
|
|
9118
|
-
if (Number.isInteger(fromEnv) && fromEnv > 0) return fromEnv;
|
|
9119
|
-
return DEFAULT_PORT;
|
|
9120
|
-
}
|
|
9121
|
-
async function ensureDependenciesInstalled(pm, cwd) {
|
|
9122
|
-
if (existsSync26(join27(cwd, "node_modules"))) return;
|
|
9123
|
-
process.stderr.write(`[kody startLocalServer] installing dependencies via ${pm}
|
|
9124
|
-
`);
|
|
9125
|
-
await runOnce(pm, installArgs(pm), cwd, INSTALL_TIMEOUT_MS);
|
|
9126
|
-
}
|
|
9127
|
-
function installArgs(pm) {
|
|
9128
|
-
if (pm === "pnpm") return ["install", "--frozen-lockfile"];
|
|
9129
|
-
if (pm === "yarn") return ["install", "--frozen-lockfile"];
|
|
9130
|
-
return ["ci"];
|
|
9131
|
-
}
|
|
9132
|
-
function spawnServer(pm, scriptName, port, cwd) {
|
|
9133
|
-
const child = spawn3(pm, ["run", scriptName], {
|
|
9134
|
-
cwd,
|
|
9135
|
-
env: { ...process.env, PORT: String(port), NODE_ENV: "development" },
|
|
9136
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
9137
|
-
detached: false
|
|
9138
|
-
});
|
|
9139
|
-
child.stdout?.on("data", (b) => process.stderr.write(`[qa-server] ${b.toString("utf8")}`));
|
|
9140
|
-
child.stderr?.on("data", (b) => process.stderr.write(`[qa-server] ${b.toString("utf8")}`));
|
|
9141
|
-
return child;
|
|
9142
|
-
}
|
|
9143
|
-
function registerProcessCleanup(child) {
|
|
9144
|
-
const cleanup = () => safeKill(child);
|
|
9145
|
-
process.on("exit", cleanup);
|
|
9146
|
-
process.on("SIGINT", cleanup);
|
|
9147
|
-
process.on("SIGTERM", cleanup);
|
|
9148
|
-
}
|
|
9149
|
-
function safeKill(child) {
|
|
9150
|
-
try {
|
|
9151
|
-
child.kill("SIGTERM");
|
|
9152
|
-
} catch {
|
|
9153
|
-
}
|
|
9154
|
-
}
|
|
9155
|
-
async function runOnce(cmd, args, cwd, timeoutMs) {
|
|
9156
|
-
await new Promise((resolve4, reject) => {
|
|
9157
|
-
const c = spawn3(cmd, args, { cwd, stdio: "inherit" });
|
|
9158
|
-
const timer = setTimeout(() => {
|
|
9159
|
-
try {
|
|
9160
|
-
c.kill("SIGKILL");
|
|
9161
|
-
} catch {
|
|
9162
|
-
}
|
|
9163
|
-
reject(new Error(`${cmd} ${args.join(" ")} timed out after ${timeoutMs}ms`));
|
|
9164
|
-
}, timeoutMs);
|
|
9165
|
-
c.on("exit", (code) => {
|
|
9166
|
-
clearTimeout(timer);
|
|
9167
|
-
if (code === 0) {
|
|
9168
|
-
resolve4();
|
|
9169
|
-
return;
|
|
9170
|
-
}
|
|
9171
|
-
reject(new Error(`${cmd} ${args.join(" ")} exited with code ${code}`));
|
|
9172
|
-
});
|
|
9173
|
-
c.on("error", (err) => {
|
|
9174
|
-
clearTimeout(timer);
|
|
9175
|
-
reject(err);
|
|
9176
|
-
});
|
|
9177
|
-
});
|
|
9178
|
-
}
|
|
9179
|
-
async function waitForReady(url, timeoutMs) {
|
|
9180
|
-
const deadline = Date.now() + timeoutMs;
|
|
9181
|
-
while (Date.now() < deadline) {
|
|
9182
|
-
if (await probe(url)) return true;
|
|
9183
|
-
await sleep2(READY_POLL_MS);
|
|
9184
|
-
}
|
|
9185
|
-
return false;
|
|
9186
|
-
}
|
|
9187
|
-
async function probe(url) {
|
|
9188
|
-
try {
|
|
9189
|
-
const res = await fetch(url, { method: "GET", signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
|
|
9190
|
-
return res.status < 500;
|
|
9191
|
-
} catch {
|
|
9192
|
-
return false;
|
|
9193
|
-
}
|
|
9194
|
-
}
|
|
9195
|
-
function sleep2(ms) {
|
|
9196
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
9197
|
-
}
|
|
9198
|
-
|
|
9199
9108
|
// src/scripts/syncFlow.ts
|
|
9200
9109
|
import { execFileSync as execFileSync26 } from "child_process";
|
|
9201
9110
|
init_issue();
|
|
@@ -9326,7 +9235,7 @@ var verify = async (ctx) => {
|
|
|
9326
9235
|
};
|
|
9327
9236
|
|
|
9328
9237
|
// src/scripts/verifyReproFails.ts
|
|
9329
|
-
import { spawn as
|
|
9238
|
+
import { spawn as spawn3 } from "child_process";
|
|
9330
9239
|
var TEST_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
9331
9240
|
var TAIL_CHARS2 = 8e3;
|
|
9332
9241
|
var ANSI_RE2 = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
@@ -9395,7 +9304,7 @@ function stripAnsi2(s) {
|
|
|
9395
9304
|
}
|
|
9396
9305
|
function runCommand2(command, cwd) {
|
|
9397
9306
|
return new Promise((resolve4) => {
|
|
9398
|
-
const child =
|
|
9307
|
+
const child = spawn3(command, {
|
|
9399
9308
|
cwd,
|
|
9400
9309
|
shell: true,
|
|
9401
9310
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1", CI: process.env.CI ?? "1" },
|
|
@@ -9458,17 +9367,17 @@ var waitForCi = async (ctx, _profile, _agentResult, args) => {
|
|
|
9458
9367
|
return;
|
|
9459
9368
|
}
|
|
9460
9369
|
const fixCiAttempts = state?.core.attempts?.["fix-ci"] ?? 0;
|
|
9461
|
-
await
|
|
9370
|
+
await sleep2(initialWaitSeconds * 1e3);
|
|
9462
9371
|
const deadline = Date.now() + timeoutMinutes * 6e4;
|
|
9463
9372
|
let lastSummary = "";
|
|
9464
9373
|
while (Date.now() < deadline) {
|
|
9465
9374
|
const rows = fetchChecks(prNumber, ctx.cwd);
|
|
9466
9375
|
if (rows === null) {
|
|
9467
|
-
await
|
|
9376
|
+
await sleep2(pollSeconds * 1e3);
|
|
9468
9377
|
continue;
|
|
9469
9378
|
}
|
|
9470
9379
|
if (rows.length === 0) {
|
|
9471
|
-
await
|
|
9380
|
+
await sleep2(pollSeconds * 1e3);
|
|
9472
9381
|
continue;
|
|
9473
9382
|
}
|
|
9474
9383
|
const summary = summarize(rows);
|
|
@@ -9511,7 +9420,7 @@ var waitForCi = async (ctx, _profile, _agentResult, args) => {
|
|
|
9511
9420
|
tryPostPr7(prNumber, `\u2705 kody waitForCi: all ${rows.length} checks green on PR #${prNumber}`, ctx.cwd);
|
|
9512
9421
|
return;
|
|
9513
9422
|
}
|
|
9514
|
-
await
|
|
9423
|
+
await sleep2(pollSeconds * 1e3);
|
|
9515
9424
|
}
|
|
9516
9425
|
ctx.data.action = mkAction("CI_TIMEOUT", {
|
|
9517
9426
|
reason: `CI did not complete within ${timeoutMinutes} minutes`,
|
|
@@ -9563,12 +9472,12 @@ function tryPostPr7(prNumber, body, cwd) {
|
|
|
9563
9472
|
} catch {
|
|
9564
9473
|
}
|
|
9565
9474
|
}
|
|
9566
|
-
function
|
|
9475
|
+
function sleep2(ms) {
|
|
9567
9476
|
return new Promise((res) => setTimeout(res, ms));
|
|
9568
9477
|
}
|
|
9569
9478
|
|
|
9570
9479
|
// src/scripts/warmupMcp.ts
|
|
9571
|
-
import { spawn as
|
|
9480
|
+
import { spawn as spawn4 } from "child_process";
|
|
9572
9481
|
var PER_SERVER_TIMEOUT_MS = 6e4;
|
|
9573
9482
|
var PER_REQUEST_TIMEOUT_MS = 2e4;
|
|
9574
9483
|
var warmupMcp = async (_ctx, profile) => {
|
|
@@ -9590,7 +9499,7 @@ var warmupMcp = async (_ctx, profile) => {
|
|
|
9590
9499
|
}
|
|
9591
9500
|
};
|
|
9592
9501
|
async function warmupOne(command, args, env) {
|
|
9593
|
-
const child =
|
|
9502
|
+
const child = spawn4(command, args, {
|
|
9594
9503
|
stdio: ["pipe", "pipe", "pipe"],
|
|
9595
9504
|
env: env ? { ...process.env, ...env } : process.env
|
|
9596
9505
|
});
|
|
@@ -9830,7 +9739,6 @@ var preflightScripts = {
|
|
|
9830
9739
|
buildSyntheticPlugin,
|
|
9831
9740
|
resolveArtifacts,
|
|
9832
9741
|
discoverQaContext,
|
|
9833
|
-
startLocalServer,
|
|
9834
9742
|
resolvePreviewUrl,
|
|
9835
9743
|
resolveQaUrl,
|
|
9836
9744
|
composePrompt,
|
|
@@ -10353,7 +10261,7 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
10353
10261
|
env[`KODY_CFG_${k}`] = v;
|
|
10354
10262
|
}
|
|
10355
10263
|
const timeoutMs = resolveShellTimeoutMs(entry);
|
|
10356
|
-
const child =
|
|
10264
|
+
const child = spawn5("bash", [shellPath, ...positional], {
|
|
10357
10265
|
cwd: ctx.cwd,
|
|
10358
10266
|
env,
|
|
10359
10267
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -10816,7 +10724,7 @@ function resolveAuthToken(env = process.env) {
|
|
|
10816
10724
|
if (token && !env.GH_TOKEN) env.GH_TOKEN = token;
|
|
10817
10725
|
return token;
|
|
10818
10726
|
}
|
|
10819
|
-
function
|
|
10727
|
+
function detectPackageManager2(cwd) {
|
|
10820
10728
|
if (fs32.existsSync(path30.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
10821
10729
|
if (fs32.existsSync(path30.join(cwd, "yarn.lock"))) return "yarn";
|
|
10822
10730
|
if (fs32.existsSync(path30.join(cwd, "bun.lockb"))) return "bun";
|
|
@@ -11018,7 +10926,7 @@ ${CI_HELP}`);
|
|
|
11018
10926
|
`);
|
|
11019
10927
|
resolveAuthToken();
|
|
11020
10928
|
reactToTriggerComment(cwd);
|
|
11021
|
-
const pm = args.packageManager ??
|
|
10929
|
+
const pm = args.packageManager ?? detectPackageManager2(cwd);
|
|
11022
10930
|
process.stdout.write(`\u2192 kody: package manager = ${pm}
|
|
11023
10931
|
`);
|
|
11024
10932
|
if (!args.skipInstall) {
|
|
@@ -11090,7 +10998,7 @@ async function runScheduledFanOut(cwd, args, opts) {
|
|
|
11090
10998
|
if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
|
|
11091
10999
|
`);
|
|
11092
11000
|
resolveAuthToken();
|
|
11093
|
-
const pm = args.packageManager ??
|
|
11001
|
+
const pm = args.packageManager ?? detectPackageManager2(cwd);
|
|
11094
11002
|
process.stdout.write(`\u2192 kody: package manager = ${pm}
|
|
11095
11003
|
`);
|
|
11096
11004
|
if (!args.skipInstall) {
|
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.69",
|
|
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",
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"kody": "tsx bin/kody.ts",
|
|
17
17
|
"build": "tsup && node scripts/copy-assets.cjs",
|
|
18
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
19
|
+
"pretest": "pnpm check:modularity",
|
|
18
20
|
"test": "vitest run tests/unit tests/int --no-coverage",
|
|
19
21
|
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
20
22
|
"test:all": "vitest run tests --no-coverage",
|