@kody-ade/kody-engine 0.4.550 → 0.4.551
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 +241 -163
- package/dist/runtime-services/goal-scheduler/scheduler.sh +0 -0
- package/package.json +26 -27
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.551",
|
|
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",
|
|
@@ -989,7 +989,7 @@ function buildVerifyEnv(source = process.env) {
|
|
|
989
989
|
return env;
|
|
990
990
|
}
|
|
991
991
|
function runCommand(command, cwd) {
|
|
992
|
-
return new Promise((
|
|
992
|
+
return new Promise((resolve20) => {
|
|
993
993
|
const start = Date.now();
|
|
994
994
|
const child = spawn(command, {
|
|
995
995
|
cwd,
|
|
@@ -1018,11 +1018,11 @@ function runCommand(command, cwd) {
|
|
|
1018
1018
|
child.on("exit", (code) => {
|
|
1019
1019
|
clearTimeout(timer);
|
|
1020
1020
|
const tail = Buffer.concat(buffers).toString("utf-8").slice(-TAIL_CHARS);
|
|
1021
|
-
|
|
1021
|
+
resolve20({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
|
|
1022
1022
|
});
|
|
1023
1023
|
child.on("error", (err) => {
|
|
1024
1024
|
clearTimeout(timer);
|
|
1025
|
-
|
|
1025
|
+
resolve20({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
|
|
1026
1026
|
});
|
|
1027
1027
|
});
|
|
1028
1028
|
}
|
|
@@ -1331,7 +1331,7 @@ function cmsHeaders(opts) {
|
|
|
1331
1331
|
}
|
|
1332
1332
|
};
|
|
1333
1333
|
}
|
|
1334
|
-
async function callDashboardCms(opts,
|
|
1334
|
+
async function callDashboardCms(opts, path54, init = {}) {
|
|
1335
1335
|
const baseUrl = dashboardBaseUrl(opts);
|
|
1336
1336
|
if (!baseUrl) {
|
|
1337
1337
|
return {
|
|
@@ -1343,7 +1343,7 @@ async function callDashboardCms(opts, path53, init = {}) {
|
|
|
1343
1343
|
const headerResult = cmsHeaders(opts);
|
|
1344
1344
|
if (!headerResult.ok) return headerResult;
|
|
1345
1345
|
try {
|
|
1346
|
-
const res = await fetch(`${baseUrl}${
|
|
1346
|
+
const res = await fetch(`${baseUrl}${path54}`, {
|
|
1347
1347
|
...init,
|
|
1348
1348
|
headers: {
|
|
1349
1349
|
...headerResult.headers,
|
|
@@ -1415,8 +1415,8 @@ function documentArg(value) {
|
|
|
1415
1415
|
function normalizeCmsDocumentIdInput(input) {
|
|
1416
1416
|
const trimmed = stripWrappingQuotes(input.trim());
|
|
1417
1417
|
const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? trimmed;
|
|
1418
|
-
const
|
|
1419
|
-
return
|
|
1418
|
+
const path54 = parseDocumentPath(withoutQuery);
|
|
1419
|
+
return path54 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
|
|
1420
1420
|
}
|
|
1421
1421
|
function stripWrappingQuotes(value) {
|
|
1422
1422
|
let current = value;
|
|
@@ -1427,9 +1427,9 @@ function stripWrappingQuotes(value) {
|
|
|
1427
1427
|
}
|
|
1428
1428
|
}
|
|
1429
1429
|
function parseDocumentPath(value) {
|
|
1430
|
-
const
|
|
1431
|
-
if (!
|
|
1432
|
-
const parts =
|
|
1430
|
+
const path54 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
|
|
1431
|
+
if (!path54?.includes("/content/entries/")) return null;
|
|
1432
|
+
const parts = path54.split("/").filter(Boolean).map(decodePathPart);
|
|
1433
1433
|
const entriesIndex = parts.findIndex((part, index) => part === "content" && parts[index + 1] === "entries");
|
|
1434
1434
|
const idPart = parts[entriesIndex + 3];
|
|
1435
1435
|
if (!idPart || idPart === "new") return null;
|
|
@@ -1997,7 +1997,9 @@ function parseCapabilityContract(raw) {
|
|
|
1997
1997
|
function parseCapabilityRequirements(raw) {
|
|
1998
1998
|
if (raw === void 0) return void 0;
|
|
1999
1999
|
if (!isPlainObject(raw)) throw new Error("contract.json requirements must be an object");
|
|
2000
|
-
const unsupported = Object.keys(raw).filter(
|
|
2000
|
+
const unsupported = Object.keys(raw).filter(
|
|
2001
|
+
(key) => key !== "browser" && key !== "qaCredentials" && key !== "githubTestToken" && key !== "browserOnly"
|
|
2002
|
+
);
|
|
2001
2003
|
if (unsupported.length > 0) {
|
|
2002
2004
|
throw new Error(`contract.json requirements contains unsupported fields: ${unsupported.join(", ")}`);
|
|
2003
2005
|
}
|
|
@@ -2007,12 +2009,20 @@ function parseCapabilityRequirements(raw) {
|
|
|
2007
2009
|
if (raw.qaCredentials !== void 0 && typeof raw.qaCredentials !== "boolean") {
|
|
2008
2010
|
throw new Error("contract.json requirements.qaCredentials must be boolean");
|
|
2009
2011
|
}
|
|
2010
|
-
if (raw.
|
|
2011
|
-
throw new Error("contract.json requirements.
|
|
2012
|
+
if (raw.githubTestToken !== void 0 && typeof raw.githubTestToken !== "boolean") {
|
|
2013
|
+
throw new Error("contract.json requirements.githubTestToken must be boolean");
|
|
2014
|
+
}
|
|
2015
|
+
if (raw.browserOnly !== void 0 && typeof raw.browserOnly !== "boolean") {
|
|
2016
|
+
throw new Error("contract.json requirements.browserOnly must be boolean");
|
|
2017
|
+
}
|
|
2018
|
+
if ((raw.qaCredentials === true || raw.githubTestToken === true || raw.browserOnly === true) && raw.browser !== true) {
|
|
2019
|
+
throw new Error("contract.json authentication requirements require browser");
|
|
2012
2020
|
}
|
|
2013
2021
|
const requirements = {
|
|
2014
2022
|
...raw.browser === true ? { browser: true } : {},
|
|
2015
|
-
...raw.qaCredentials === true ? { qaCredentials: true } : {}
|
|
2023
|
+
...raw.qaCredentials === true ? { qaCredentials: true } : {},
|
|
2024
|
+
...raw.githubTestToken === true ? { githubTestToken: true } : {},
|
|
2025
|
+
...raw.browserOnly === true ? { browserOnly: true } : {}
|
|
2016
2026
|
};
|
|
2017
2027
|
return Object.keys(requirements).length > 0 ? requirements : void 0;
|
|
2018
2028
|
}
|
|
@@ -2027,8 +2037,8 @@ function isRegularFile(filePath) {
|
|
|
2027
2037
|
function schemaPropertyPaths(schema, prefix) {
|
|
2028
2038
|
const properties = isPlainObject(schema.properties) ? schema.properties : {};
|
|
2029
2039
|
return Object.entries(properties).flatMap(([name, property]) => {
|
|
2030
|
-
const
|
|
2031
|
-
return isPlainObject(property) ? [
|
|
2040
|
+
const path54 = `${prefix}.${name}`;
|
|
2041
|
+
return isPlainObject(property) ? [path54, ...schemaPropertyPaths(property, path54)] : [path54];
|
|
2032
2042
|
});
|
|
2033
2043
|
}
|
|
2034
2044
|
function parseCapabilityBody(raw, slug) {
|
|
@@ -3620,7 +3630,7 @@ var init_repoWorkspace = __esm({
|
|
|
3620
3630
|
defaultCloneRepo = (repo, token, dir) => {
|
|
3621
3631
|
fs9.mkdirSync(path10.dirname(dir), { recursive: true });
|
|
3622
3632
|
const clone = buildCloneProcess(repo, token);
|
|
3623
|
-
return new Promise((
|
|
3633
|
+
return new Promise((resolve20, reject) => {
|
|
3624
3634
|
const child = spawn2("git", ["clone", "--depth=1", clone.url, dir], {
|
|
3625
3635
|
env: clone.env,
|
|
3626
3636
|
stdio: "inherit"
|
|
@@ -3640,7 +3650,7 @@ var init_repoWorkspace = __esm({
|
|
|
3640
3650
|
}
|
|
3641
3651
|
} catch {
|
|
3642
3652
|
}
|
|
3643
|
-
|
|
3653
|
+
resolve20();
|
|
3644
3654
|
});
|
|
3645
3655
|
child.on("error", reject);
|
|
3646
3656
|
});
|
|
@@ -3971,10 +3981,10 @@ async function runAgent(opts) {
|
|
|
3971
3981
|
let timer;
|
|
3972
3982
|
let next;
|
|
3973
3983
|
if (turnTimeoutMs > 0) {
|
|
3974
|
-
const timeoutPromise = new Promise((
|
|
3984
|
+
const timeoutPromise = new Promise((resolve20) => {
|
|
3975
3985
|
timer = setTimeout(() => {
|
|
3976
3986
|
timedOut = true;
|
|
3977
|
-
|
|
3987
|
+
resolve20({ done: true, value: void 0 });
|
|
3978
3988
|
}, turnTimeoutMs);
|
|
3979
3989
|
});
|
|
3980
3990
|
next = await Promise.race([nextPromise, timeoutPromise]);
|
|
@@ -3990,7 +4000,7 @@ async function runAgent(opts) {
|
|
|
3990
4000
|
try {
|
|
3991
4001
|
await Promise.race([
|
|
3992
4002
|
iterator.return(void 0).catch(() => void 0),
|
|
3993
|
-
new Promise((
|
|
4003
|
+
new Promise((resolve20) => setTimeout(resolve20, 1e4).unref())
|
|
3994
4004
|
]);
|
|
3995
4005
|
} catch {
|
|
3996
4006
|
}
|
|
@@ -4614,15 +4624,15 @@ function validateWorkflow(value, options = {}) {
|
|
|
4614
4624
|
}
|
|
4615
4625
|
return issues;
|
|
4616
4626
|
}
|
|
4617
|
-
function validateInputBindings(value,
|
|
4627
|
+
function validateInputBindings(value, path54, issues, declaredInputs) {
|
|
4618
4628
|
if (value === void 0) return;
|
|
4619
4629
|
const bindings = asRecord(value);
|
|
4620
4630
|
if (!bindings || Object.keys(bindings).length === 0) {
|
|
4621
|
-
issue(issues, "invalid_inputs",
|
|
4631
|
+
issue(issues, "invalid_inputs", path54, "workflow step inputs must contain at least one named mapping");
|
|
4622
4632
|
return;
|
|
4623
4633
|
}
|
|
4624
4634
|
for (const [name, value2] of Object.entries(bindings)) {
|
|
4625
|
-
const bindingPath = `${
|
|
4635
|
+
const bindingPath = `${path54}.${name}`;
|
|
4626
4636
|
if (!/^[A-Za-z_][A-Za-z0-9_-]*$/.test(name)) {
|
|
4627
4637
|
issue(issues, "invalid_input_name", bindingPath, `workflow input name ${name} is invalid`);
|
|
4628
4638
|
}
|
|
@@ -4641,7 +4651,7 @@ function validateInputBindings(value, path53, issues, declaredInputs) {
|
|
|
4641
4651
|
}
|
|
4642
4652
|
}
|
|
4643
4653
|
}
|
|
4644
|
-
function validateInputBindingSources(value,
|
|
4654
|
+
function validateInputBindingSources(value, path54, issues, capabilitiesByStep, capabilityOutputs) {
|
|
4645
4655
|
const bindings = asRecord(value);
|
|
4646
4656
|
if (!bindings) return;
|
|
4647
4657
|
for (const [name, rawBinding] of Object.entries(bindings)) {
|
|
@@ -4654,7 +4664,7 @@ function validateInputBindingSources(value, path53, issues, capabilitiesByStep,
|
|
|
4654
4664
|
issue(
|
|
4655
4665
|
issues,
|
|
4656
4666
|
"missing_input_step",
|
|
4657
|
-
`${
|
|
4667
|
+
`${path54}.${name}.from`,
|
|
4658
4668
|
`workflow input mapping references missing step ${sourceStep ?? "<none>"}`
|
|
4659
4669
|
);
|
|
4660
4670
|
continue;
|
|
@@ -4665,7 +4675,7 @@ function validateInputBindingSources(value, path53, issues, capabilitiesByStep,
|
|
|
4665
4675
|
issue(
|
|
4666
4676
|
issues,
|
|
4667
4677
|
"undeclared_step_output",
|
|
4668
|
-
`${
|
|
4678
|
+
`${path54}.${name}.from`,
|
|
4669
4679
|
`workflow input mapping reads ${outputPath}, but step ${sourceStep} does not declare it`
|
|
4670
4680
|
);
|
|
4671
4681
|
}
|
|
@@ -4674,11 +4684,11 @@ function validateInputBindingSources(value, path53, issues, capabilitiesByStep,
|
|
|
4674
4684
|
function formatWorkflowValidationIssues(issues) {
|
|
4675
4685
|
return issues.map((entry) => `${entry.path}: ${entry.message}`);
|
|
4676
4686
|
}
|
|
4677
|
-
function validateDataMatch(value,
|
|
4687
|
+
function validateDataMatch(value, path54, issues, capabilityOutputs) {
|
|
4678
4688
|
if (value === void 0) return;
|
|
4679
4689
|
const match = asRecord(value);
|
|
4680
4690
|
if (!match || Object.keys(match).length === 0) {
|
|
4681
|
-
issue(issues, "invalid_condition",
|
|
4691
|
+
issue(issues, "invalid_condition", path54, "workflow condition must contain at least one match");
|
|
4682
4692
|
return;
|
|
4683
4693
|
}
|
|
4684
4694
|
for (const [field, expected] of Object.entries(match)) {
|
|
@@ -4686,7 +4696,7 @@ function validateDataMatch(value, path53, issues, capabilityOutputs) {
|
|
|
4686
4696
|
issue(
|
|
4687
4697
|
issues,
|
|
4688
4698
|
"invalid_data_path",
|
|
4689
|
-
`${
|
|
4699
|
+
`${path54}.${field}`,
|
|
4690
4700
|
`workflow condition must read from facts, evidence, artifacts, result, workflow, or lastOutcome`
|
|
4691
4701
|
);
|
|
4692
4702
|
}
|
|
@@ -4694,12 +4704,12 @@ function validateDataMatch(value, path53, issues, capabilityOutputs) {
|
|
|
4694
4704
|
issue(
|
|
4695
4705
|
issues,
|
|
4696
4706
|
"undeclared_result_path",
|
|
4697
|
-
`${
|
|
4707
|
+
`${path54}.${field}`,
|
|
4698
4708
|
`workflow condition reads ${field}, but the source capability does not declare it`
|
|
4699
4709
|
);
|
|
4700
4710
|
}
|
|
4701
4711
|
if (!isComparable(expected)) {
|
|
4702
|
-
issue(issues, "invalid_condition_value", `${
|
|
4712
|
+
issue(issues, "invalid_condition_value", `${path54}.${field}`, "workflow condition value must be a JSON scalar");
|
|
4703
4713
|
}
|
|
4704
4714
|
}
|
|
4705
4715
|
}
|
|
@@ -4723,8 +4733,8 @@ function isJsonValue(value) {
|
|
|
4723
4733
|
if (!value || typeof value !== "object") return false;
|
|
4724
4734
|
return Object.values(value).every(isJsonValue);
|
|
4725
4735
|
}
|
|
4726
|
-
function issue(issues, code,
|
|
4727
|
-
issues.push({ code, path:
|
|
4736
|
+
function issue(issues, code, path54, message) {
|
|
4737
|
+
issues.push({ code, path: path54, message });
|
|
4728
4738
|
}
|
|
4729
4739
|
var SAFE_NAME, SAFE_STEP_ID, SAFE_DATA_PATH, SAFE_INPUT_SOURCE, SUPPORTED_STEP_FIELDS, SUPPORTED_TRANSITION_FIELDS;
|
|
4730
4740
|
var init_workflowValidation = __esm({
|
|
@@ -7600,11 +7610,11 @@ async function nextAvailableLitellmUrl(url) {
|
|
|
7600
7610
|
throw new Error(`no free LiteLLM port found after ${startPort}`);
|
|
7601
7611
|
}
|
|
7602
7612
|
function canListen(port, host) {
|
|
7603
|
-
return new Promise((
|
|
7613
|
+
return new Promise((resolve20) => {
|
|
7604
7614
|
const server = net.createServer();
|
|
7605
|
-
server.once("error", () =>
|
|
7615
|
+
server.once("error", () => resolve20(false));
|
|
7606
7616
|
server.once("listening", () => {
|
|
7607
|
-
server.close(() =>
|
|
7617
|
+
server.close(() => resolve20(true));
|
|
7608
7618
|
});
|
|
7609
7619
|
server.listen(port, host);
|
|
7610
7620
|
});
|
|
@@ -9027,9 +9037,9 @@ import * as fs28 from "fs";
|
|
|
9027
9037
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
9028
9038
|
const logs = goalRunLogs(data);
|
|
9029
9039
|
const existing = logs[goalId];
|
|
9030
|
-
const
|
|
9040
|
+
const path54 = existing?.path ?? goalRunLogPath(goalId, data);
|
|
9031
9041
|
logs[goalId] = {
|
|
9032
|
-
path:
|
|
9042
|
+
path: path54,
|
|
9033
9043
|
events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
|
|
9034
9044
|
};
|
|
9035
9045
|
}
|
|
@@ -9906,15 +9916,15 @@ var init_backendStateBackend = __esm({
|
|
|
9906
9916
|
this.jobsDir = opts.jobsDir.replace(/\/+$/, "");
|
|
9907
9917
|
}
|
|
9908
9918
|
async load(slug) {
|
|
9909
|
-
const
|
|
9919
|
+
const path54 = stateFilePath(this.jobsDir, slug);
|
|
9910
9920
|
const loaded = await createStateBackendFromEnv().get(this.tenantId, `capabilities/${slug}`, "job-state");
|
|
9911
9921
|
if (!loaded) {
|
|
9912
|
-
return { path:
|
|
9922
|
+
return { path: path54, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
9913
9923
|
}
|
|
9914
9924
|
if (!isStateEnvelope(loaded.doc)) {
|
|
9915
9925
|
throw new Error(`BackendStateBackend: capabilities/${slug} is not a StateEnvelope`);
|
|
9916
9926
|
}
|
|
9917
|
-
return { path:
|
|
9927
|
+
return { path: path54, handle: loaded.updatedAt, state: loaded.doc, created: false };
|
|
9918
9928
|
}
|
|
9919
9929
|
async save(loaded, next) {
|
|
9920
9930
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) return false;
|
|
@@ -15343,13 +15353,13 @@ var init_loadCapabilityState = __esm({
|
|
|
15343
15353
|
function isCompanyIntentId(value) {
|
|
15344
15354
|
return SLUG_RE2.test(value);
|
|
15345
15355
|
}
|
|
15346
|
-
function normalizeCompanyIntent(
|
|
15356
|
+
function normalizeCompanyIntent(path54, raw) {
|
|
15347
15357
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
15348
|
-
throw new Error(`${
|
|
15358
|
+
throw new Error(`${path54}: intent must be JSON object`);
|
|
15349
15359
|
}
|
|
15350
15360
|
const input = raw;
|
|
15351
15361
|
const id = stringField4(input.id);
|
|
15352
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${
|
|
15362
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path54}: invalid intent id`);
|
|
15353
15363
|
const createdAt = stringField4(input.createdAt) || nowIso();
|
|
15354
15364
|
const updatedAt = stringField4(input.updatedAt) || createdAt;
|
|
15355
15365
|
const description = stringField4(input.description);
|
|
@@ -15511,7 +15521,7 @@ function retryDelaysMs() {
|
|
|
15511
15521
|
}
|
|
15512
15522
|
function sleep(ms) {
|
|
15513
15523
|
if (ms <= 0) return Promise.resolve();
|
|
15514
|
-
return new Promise((
|
|
15524
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
15515
15525
|
}
|
|
15516
15526
|
async function fetchGoalStateWithRetry(config, goalId, cwd) {
|
|
15517
15527
|
let state = await fetchGoalStateAsync(config, goalId, cwd);
|
|
@@ -16528,19 +16538,19 @@ function parseAgencyModelProposal(raw) {
|
|
|
16528
16538
|
function normalizeBundleFiles(bundle) {
|
|
16529
16539
|
const seen = /* @__PURE__ */ new Set();
|
|
16530
16540
|
return bundle.files.map((file, index) => {
|
|
16531
|
-
const
|
|
16532
|
-
const parts =
|
|
16533
|
-
if (!
|
|
16541
|
+
const path54 = file.path.replace(/^\/+/, "");
|
|
16542
|
+
const parts = path54.split("/");
|
|
16543
|
+
if (!path54 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
|
|
16534
16544
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is unsafe`);
|
|
16535
16545
|
}
|
|
16536
16546
|
if (!/^(agents\/[^/]+\.md|capabilities\/[^/]+\/.+|goals\/(?:templates\/)?[^/]+\/.+|workflows\/[^/]+\.json)$/.test(
|
|
16537
|
-
|
|
16547
|
+
path54
|
|
16538
16548
|
)) {
|
|
16539
16549
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is not a supported definition path`);
|
|
16540
16550
|
}
|
|
16541
|
-
if (seen.has(
|
|
16542
|
-
seen.add(
|
|
16543
|
-
return { path:
|
|
16551
|
+
if (seen.has(path54)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path54}`);
|
|
16552
|
+
seen.add(path54);
|
|
16553
|
+
return { path: path54, content: file.content.replace(/\r\n?/g, "\n") };
|
|
16544
16554
|
});
|
|
16545
16555
|
}
|
|
16546
16556
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
@@ -17951,16 +17961,66 @@ var init_prepareCapabilityDelivery = __esm({
|
|
|
17951
17961
|
});
|
|
17952
17962
|
|
|
17953
17963
|
// src/scripts/prepareSimpleCapabilityRuntime.ts
|
|
17964
|
+
import { isIP } from "net";
|
|
17965
|
+
import * as path43 from "path";
|
|
17954
17966
|
function requirementsFrom(ctx) {
|
|
17955
17967
|
const raw = ctx.data.capabilityRequirements;
|
|
17956
17968
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
17957
17969
|
}
|
|
17958
|
-
function
|
|
17970
|
+
function isPrivateTargetHost(hostname) {
|
|
17971
|
+
const host = hostname.toLowerCase();
|
|
17972
|
+
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local")) return true;
|
|
17973
|
+
if (isIP(host) === 4) {
|
|
17974
|
+
const [a, b] = host.split(".").map(Number);
|
|
17975
|
+
return a === 10 || a === 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168;
|
|
17976
|
+
}
|
|
17977
|
+
if (isIP(host) === 6) {
|
|
17978
|
+
return host === "::1" || host.startsWith("fc") || host.startsWith("fd") || host.startsWith("fe8");
|
|
17979
|
+
}
|
|
17980
|
+
return false;
|
|
17981
|
+
}
|
|
17982
|
+
function browserRuntime(ctx, requirements) {
|
|
17983
|
+
if (!requirements.browserOnly) return PLAYWRIGHT_SERVER;
|
|
17984
|
+
const input = ctx.data.capabilityInput;
|
|
17985
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
17986
|
+
throw new Error("Restricted browser capability requires object input");
|
|
17987
|
+
}
|
|
17988
|
+
const targetUrl = input.targetUrl;
|
|
17989
|
+
const qualityRunId = input.qualityRunId;
|
|
17990
|
+
let origin = "";
|
|
17991
|
+
try {
|
|
17992
|
+
const parsed = new URL(typeof targetUrl === "string" ? targetUrl : "");
|
|
17993
|
+
if (parsed.protocol === "https:" && !parsed.username && !parsed.password && !isPrivateTargetHost(parsed.hostname)) {
|
|
17994
|
+
origin = parsed.origin;
|
|
17995
|
+
}
|
|
17996
|
+
} catch {
|
|
17997
|
+
}
|
|
17998
|
+
if (!origin) throw new Error("Restricted browser capability requires a public HTTPS targetUrl");
|
|
17999
|
+
if (typeof qualityRunId !== "string" || !/^[A-Za-z0-9_-]{1,200}$/.test(qualityRunId)) {
|
|
18000
|
+
throw new Error("Restricted browser capability requires a valid qualityRunId");
|
|
18001
|
+
}
|
|
18002
|
+
return {
|
|
18003
|
+
...PLAYWRIGHT_SERVER,
|
|
18004
|
+
args: [
|
|
18005
|
+
...PLAYWRIGHT_SERVER.args,
|
|
18006
|
+
"--allowed-origins",
|
|
18007
|
+
origin,
|
|
18008
|
+
"--output-dir",
|
|
18009
|
+
path43.resolve(ctx.cwd, "test-results", "quality-runs", qualityRunId)
|
|
18010
|
+
]
|
|
18011
|
+
};
|
|
18012
|
+
}
|
|
18013
|
+
function configureBrowser(ctx, profile, requirements) {
|
|
18014
|
+
const server = browserRuntime(ctx, requirements);
|
|
18015
|
+
if (requirements.browserOnly) {
|
|
18016
|
+
profile.claudeCode.tools = ["Write"];
|
|
18017
|
+
profile.claudeCode.maxTurns = Math.min(profile.claudeCode.maxTurns ?? 50, 50);
|
|
18018
|
+
}
|
|
17959
18019
|
if (!profile.claudeCode.tools.includes("mcp__playwright")) {
|
|
17960
18020
|
profile.claudeCode.tools = [...profile.claudeCode.tools, "mcp__playwright"];
|
|
17961
18021
|
}
|
|
17962
18022
|
if (!profile.claudeCode.mcpServers.some(({ name }) => name === PLAYWRIGHT_SERVER.name)) {
|
|
17963
|
-
profile.claudeCode.mcpServers = [...profile.claudeCode.mcpServers,
|
|
18023
|
+
profile.claudeCode.mcpServers = [...profile.claudeCode.mcpServers, server];
|
|
17964
18024
|
}
|
|
17965
18025
|
}
|
|
17966
18026
|
function appendPrompt(ctx, section) {
|
|
@@ -17972,6 +18032,7 @@ var init_prepareSimpleCapabilityRuntime = __esm({
|
|
|
17972
18032
|
"src/scripts/prepareSimpleCapabilityRuntime.ts"() {
|
|
17973
18033
|
"use strict";
|
|
17974
18034
|
init_loadQaContext();
|
|
18035
|
+
init_runtimeSecrets();
|
|
17975
18036
|
PLAYWRIGHT_SERVER = {
|
|
17976
18037
|
name: "playwright",
|
|
17977
18038
|
command: "npx",
|
|
@@ -17980,19 +18041,36 @@ var init_prepareSimpleCapabilityRuntime = __esm({
|
|
|
17980
18041
|
prepareSimpleCapabilityRuntime = async (ctx, profile) => {
|
|
17981
18042
|
const requirements = requirementsFrom(ctx);
|
|
17982
18043
|
if (!requirements.browser) return;
|
|
17983
|
-
configureBrowser(profile);
|
|
17984
|
-
if (
|
|
17985
|
-
|
|
17986
|
-
|
|
17987
|
-
|
|
17988
|
-
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
17992
|
-
|
|
17993
|
-
|
|
17994
|
-
|
|
17995
|
-
|
|
18044
|
+
configureBrowser(ctx, profile, requirements);
|
|
18045
|
+
if (requirements.qaCredentials) {
|
|
18046
|
+
await loadQaContext(ctx, profile);
|
|
18047
|
+
appendPrompt(
|
|
18048
|
+
ctx,
|
|
18049
|
+
[
|
|
18050
|
+
"## QA authentication",
|
|
18051
|
+
"",
|
|
18052
|
+
String(ctx.data.qaAuthBlock ?? ""),
|
|
18053
|
+
"",
|
|
18054
|
+
"If the changed surface requires authentication and the credentials are missing or the login is rejected, return a blocked result with a safe explanation. Do not include usernames, passwords, tokens, or other credential values in the result."
|
|
18055
|
+
].join("\n")
|
|
18056
|
+
);
|
|
18057
|
+
}
|
|
18058
|
+
if (requirements.githubTestToken) {
|
|
18059
|
+
const token = await resolveRuntimeSecret("E2E_GITHUB_TOKEN", ctx);
|
|
18060
|
+
appendPrompt(
|
|
18061
|
+
ctx,
|
|
18062
|
+
token.value ? [
|
|
18063
|
+
"## Protected GitHub test login",
|
|
18064
|
+
"",
|
|
18065
|
+
`A protected GitHub test token is available: \`${token.value}\``,
|
|
18066
|
+
"Use it only if the target application asks for a GitHub personal access token; never include the token in screenshots, output, logs, files, or messages."
|
|
18067
|
+
].join("\n") : [
|
|
18068
|
+
"## Protected GitHub test login",
|
|
18069
|
+
"",
|
|
18070
|
+
"E2E_GITHUB_TOKEN is not configured. If this Quality Scenario requires GitHub token authentication, return a blocked result."
|
|
18071
|
+
].join("\n")
|
|
18072
|
+
);
|
|
18073
|
+
}
|
|
17996
18074
|
};
|
|
17997
18075
|
}
|
|
17998
18076
|
});
|
|
@@ -18279,9 +18357,9 @@ function latestResult(raw, agentResult) {
|
|
|
18279
18357
|
function recordField4(value) {
|
|
18280
18358
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
18281
18359
|
}
|
|
18282
|
-
function resolveDotted(root,
|
|
18283
|
-
if (!
|
|
18284
|
-
return
|
|
18360
|
+
function resolveDotted(root, path54) {
|
|
18361
|
+
if (!path54) return void 0;
|
|
18362
|
+
return path54.split(".").reduce((value, key) => recordField4(value)?.[key], root);
|
|
18285
18363
|
}
|
|
18286
18364
|
function stringValue5(value) {
|
|
18287
18365
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -19123,7 +19201,7 @@ var init_previewBuildHelpers = __esm({
|
|
|
19123
19201
|
// src/scripts/previewBuildRun.ts
|
|
19124
19202
|
import { spawn as spawn5 } from "child_process";
|
|
19125
19203
|
async function runCmd(cmd, args, opts = {}) {
|
|
19126
|
-
await new Promise((
|
|
19204
|
+
await new Promise((resolve20, reject) => {
|
|
19127
19205
|
const child = spawn5(cmd, args, {
|
|
19128
19206
|
cwd: opts.cwd,
|
|
19129
19207
|
env: { ...process.env, ...opts.env ?? {} },
|
|
@@ -19135,7 +19213,7 @@ async function runCmd(cmd, args, opts = {}) {
|
|
|
19135
19213
|
}
|
|
19136
19214
|
child.on("error", reject);
|
|
19137
19215
|
child.on("close", (code) => {
|
|
19138
|
-
if (code === 0)
|
|
19216
|
+
if (code === 0) resolve20();
|
|
19139
19217
|
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
19140
19218
|
});
|
|
19141
19219
|
});
|
|
@@ -19207,12 +19285,12 @@ fi
|
|
|
19207
19285
|
|
|
19208
19286
|
// src/scripts/runPreviewBuild.ts
|
|
19209
19287
|
import { copyFile, writeFile } from "fs/promises";
|
|
19210
|
-
import * as
|
|
19288
|
+
import * as path44 from "path";
|
|
19211
19289
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
19212
19290
|
function bundledDockerfilePath(mode) {
|
|
19213
|
-
const here =
|
|
19291
|
+
const here = path44.dirname(fileURLToPath2(import.meta.url));
|
|
19214
19292
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
19215
|
-
return
|
|
19293
|
+
return path44.join(here, "preview-build-templates", file);
|
|
19216
19294
|
}
|
|
19217
19295
|
function required(name) {
|
|
19218
19296
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -19447,10 +19525,10 @@ var init_runPreviewBuild = __esm({
|
|
|
19447
19525
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
19448
19526
|
if (Object.keys(buildEnv).length > 0) {
|
|
19449
19527
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
19450
|
-
await writeFile(
|
|
19528
|
+
await writeFile(path44.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
19451
19529
|
`, "utf8");
|
|
19452
19530
|
}
|
|
19453
|
-
const consumerDockerfile =
|
|
19531
|
+
const consumerDockerfile = path44.join(ctx.cwd, "Dockerfile.preview");
|
|
19454
19532
|
const { stat } = await import("fs/promises");
|
|
19455
19533
|
let hasConsumerDockerfile = false;
|
|
19456
19534
|
try {
|
|
@@ -19635,7 +19713,7 @@ var init_tickShellRunner = __esm({
|
|
|
19635
19713
|
|
|
19636
19714
|
// src/scripts/runScheduledImplementationTick.ts
|
|
19637
19715
|
import * as fs47 from "fs";
|
|
19638
|
-
import * as
|
|
19716
|
+
import * as path45 from "path";
|
|
19639
19717
|
var runScheduledImplementationTick;
|
|
19640
19718
|
var init_runScheduledImplementationTick = __esm({
|
|
19641
19719
|
"src/scripts/runScheduledImplementationTick.ts"() {
|
|
@@ -19656,13 +19734,13 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
19656
19734
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
19657
19735
|
return;
|
|
19658
19736
|
}
|
|
19659
|
-
const capability = resolveCapabilityFolder(slug,
|
|
19737
|
+
const capability = resolveCapabilityFolder(slug, path45.resolve(ctx.cwd, jobsDir));
|
|
19660
19738
|
if (!capability) {
|
|
19661
19739
|
ctx.output.exitCode = 99;
|
|
19662
19740
|
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
|
|
19663
19741
|
return;
|
|
19664
19742
|
}
|
|
19665
|
-
const shellPath =
|
|
19743
|
+
const shellPath = path45.join(profile.dir, shell);
|
|
19666
19744
|
if (!fs47.existsSync(shellPath)) {
|
|
19667
19745
|
ctx.output.exitCode = 99;
|
|
19668
19746
|
ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
@@ -19781,7 +19859,7 @@ var init_runSimpleCapabilityScript = __esm({
|
|
|
19781
19859
|
|
|
19782
19860
|
// src/scripts/runTickScript.ts
|
|
19783
19861
|
import * as fs49 from "fs";
|
|
19784
|
-
import * as
|
|
19862
|
+
import * as path46 from "path";
|
|
19785
19863
|
var runTickScript;
|
|
19786
19864
|
var init_runTickScript = __esm({
|
|
19787
19865
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -19801,10 +19879,10 @@ var init_runTickScript = __esm({
|
|
|
19801
19879
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
19802
19880
|
return;
|
|
19803
19881
|
}
|
|
19804
|
-
const capability = readCapabilityFolder(
|
|
19882
|
+
const capability = readCapabilityFolder(path46.resolve(ctx.cwd, jobsDir), slug);
|
|
19805
19883
|
if (!capability) {
|
|
19806
19884
|
ctx.output.exitCode = 99;
|
|
19807
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
19885
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path46.resolve(ctx.cwd, jobsDir, slug)}`;
|
|
19808
19886
|
return;
|
|
19809
19887
|
}
|
|
19810
19888
|
const tickScript = capability.config.tickScript;
|
|
@@ -19813,7 +19891,7 @@ var init_runTickScript = __esm({
|
|
|
19813
19891
|
ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
19814
19892
|
return;
|
|
19815
19893
|
}
|
|
19816
|
-
const scriptPath =
|
|
19894
|
+
const scriptPath = path46.isAbsolute(tickScript) ? tickScript : path46.join(ctx.cwd, tickScript);
|
|
19817
19895
|
if (!fs49.existsSync(scriptPath)) {
|
|
19818
19896
|
ctx.output.exitCode = 99;
|
|
19819
19897
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
@@ -20096,7 +20174,7 @@ var init_syncFlow = __esm({
|
|
|
20096
20174
|
});
|
|
20097
20175
|
|
|
20098
20176
|
// src/scripts/validateAgencyModelProposal.ts
|
|
20099
|
-
import * as
|
|
20177
|
+
import * as path47 from "path";
|
|
20100
20178
|
function validateModelBundle(bundle, expectedKind, options = {}) {
|
|
20101
20179
|
const failures = [];
|
|
20102
20180
|
validateOneModel(bundle.model, bundle.files, "model", true, failures, expectedKind, options);
|
|
@@ -20414,7 +20492,7 @@ var init_validateAgencyModelProposal = __esm({
|
|
|
20414
20492
|
const bundle = parseAgencyModelProposal(raw);
|
|
20415
20493
|
const expectedKind = readExpectedModelKind(args);
|
|
20416
20494
|
const failures = validateModelBundle(bundle, expectedKind, {
|
|
20417
|
-
capabilityRoot:
|
|
20495
|
+
capabilityRoot: path47.join(ctx.cwd, ".kody", "capabilities")
|
|
20418
20496
|
});
|
|
20419
20497
|
if (failures.length > 0) {
|
|
20420
20498
|
throw new Error(`validateAgencyModelProposal: ${failures.join("; ")}`);
|
|
@@ -20477,7 +20555,7 @@ function stripAnsi2(s) {
|
|
|
20477
20555
|
return s.replace(ANSI_RE2, "");
|
|
20478
20556
|
}
|
|
20479
20557
|
function runCommand2(command, cwd) {
|
|
20480
|
-
return new Promise((
|
|
20558
|
+
return new Promise((resolve20) => {
|
|
20481
20559
|
const child = spawn6(command, {
|
|
20482
20560
|
cwd,
|
|
20483
20561
|
shell: true,
|
|
@@ -20504,11 +20582,11 @@ function runCommand2(command, cwd) {
|
|
|
20504
20582
|
}, TEST_TIMEOUT_MS);
|
|
20505
20583
|
child.on("exit", (code) => {
|
|
20506
20584
|
clearTimeout(timer);
|
|
20507
|
-
|
|
20585
|
+
resolve20({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
|
|
20508
20586
|
});
|
|
20509
20587
|
child.on("error", (err) => {
|
|
20510
20588
|
clearTimeout(timer);
|
|
20511
|
-
|
|
20589
|
+
resolve20({ exitCode: -1, output: err.message });
|
|
20512
20590
|
});
|
|
20513
20591
|
});
|
|
20514
20592
|
}
|
|
@@ -20914,21 +20992,21 @@ function lineStream(stream) {
|
|
|
20914
20992
|
tryDeliver();
|
|
20915
20993
|
});
|
|
20916
20994
|
return {
|
|
20917
|
-
next: (timeoutMs) => new Promise((
|
|
20995
|
+
next: (timeoutMs) => new Promise((resolve20) => {
|
|
20918
20996
|
if (queue.length > 0) {
|
|
20919
|
-
|
|
20997
|
+
resolve20(queue.shift());
|
|
20920
20998
|
return;
|
|
20921
20999
|
}
|
|
20922
21000
|
if (ended) {
|
|
20923
|
-
|
|
21001
|
+
resolve20(null);
|
|
20924
21002
|
return;
|
|
20925
21003
|
}
|
|
20926
|
-
waiter =
|
|
21004
|
+
waiter = resolve20;
|
|
20927
21005
|
const t = setTimeout(
|
|
20928
21006
|
() => {
|
|
20929
|
-
if (waiter ===
|
|
21007
|
+
if (waiter === resolve20) {
|
|
20930
21008
|
waiter = null;
|
|
20931
|
-
|
|
21009
|
+
resolve20(null);
|
|
20932
21010
|
}
|
|
20933
21011
|
},
|
|
20934
21012
|
Math.max(0, timeoutMs)
|
|
@@ -21330,15 +21408,15 @@ var init_scripts = __esm({
|
|
|
21330
21408
|
|
|
21331
21409
|
// src/stateWorkspace.ts
|
|
21332
21410
|
import * as fs51 from "fs";
|
|
21333
|
-
import * as
|
|
21411
|
+
import * as path48 from "path";
|
|
21334
21412
|
function tenantId(config) {
|
|
21335
21413
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
21336
21414
|
const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
|
|
21337
21415
|
return owner && repo ? `${owner}/${repo}` : null;
|
|
21338
21416
|
}
|
|
21339
21417
|
function writeRuntimeFile(cwd, relativePath, content) {
|
|
21340
|
-
const target =
|
|
21341
|
-
fs51.mkdirSync(
|
|
21418
|
+
const target = path48.join(cwd, RUNTIME_ROOT, relativePath);
|
|
21419
|
+
fs51.mkdirSync(path48.dirname(target), { recursive: true });
|
|
21342
21420
|
fs51.writeFileSync(target, content, "utf8");
|
|
21343
21421
|
}
|
|
21344
21422
|
function record(value) {
|
|
@@ -21404,10 +21482,10 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
|
|
|
21404
21482
|
throw new Error("Kody backend access is required for runtime workspace documents");
|
|
21405
21483
|
return;
|
|
21406
21484
|
}
|
|
21407
|
-
const key = `${
|
|
21485
|
+
const key = `${path48.resolve(cwd)}|${tenant}`;
|
|
21408
21486
|
if (hydratedWorkspaces.has(key)) return;
|
|
21409
21487
|
const backend = backendOverride ?? createStateBackendFromEnv();
|
|
21410
|
-
const root =
|
|
21488
|
+
const root = path48.join(cwd, RUNTIME_ROOT);
|
|
21411
21489
|
fs51.rmSync(root, { recursive: true, force: true });
|
|
21412
21490
|
await Promise.all([
|
|
21413
21491
|
hydratePrefix(backend, tenant, cwd, "context:"),
|
|
@@ -21424,7 +21502,7 @@ var init_stateWorkspace = __esm({
|
|
|
21424
21502
|
"src/stateWorkspace.ts"() {
|
|
21425
21503
|
"use strict";
|
|
21426
21504
|
init_state_backend();
|
|
21427
|
-
RUNTIME_ROOT =
|
|
21505
|
+
RUNTIME_ROOT = path48.join(".kody-engine", "runtime");
|
|
21428
21506
|
hydratedWorkspaces = /* @__PURE__ */ new Set();
|
|
21429
21507
|
}
|
|
21430
21508
|
});
|
|
@@ -21497,7 +21575,7 @@ var init_tools = __esm({
|
|
|
21497
21575
|
import { spawn as spawn8 } from "child_process";
|
|
21498
21576
|
import * as fs52 from "fs";
|
|
21499
21577
|
import * as os8 from "os";
|
|
21500
|
-
import * as
|
|
21578
|
+
import * as path49 from "path";
|
|
21501
21579
|
function isMutatingPostflight(scriptName) {
|
|
21502
21580
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
21503
21581
|
}
|
|
@@ -21749,7 +21827,7 @@ async function runImplementation(profileName, input) {
|
|
|
21749
21827
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
21750
21828
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
21751
21829
|
const invokeAgent = async (prompt) => {
|
|
21752
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
21830
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path49.isAbsolute(p) ? p : path49.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
21753
21831
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
21754
21832
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
21755
21833
|
const agents = loadSubagents(profile);
|
|
@@ -22225,13 +22303,13 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
22225
22303
|
function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
22226
22304
|
const found = resolveImplementation(profileName, getRuntimeProfileRootsForCwd(cwd));
|
|
22227
22305
|
if (found) return found;
|
|
22228
|
-
const here =
|
|
22306
|
+
const here = path49.dirname(new URL(import.meta.url).pathname);
|
|
22229
22307
|
const candidates = [
|
|
22230
|
-
|
|
22308
|
+
path49.join(here, "implementations", profileName, "profile.json"),
|
|
22231
22309
|
// same-dir sibling (dev)
|
|
22232
|
-
|
|
22310
|
+
path49.join(here, "..", "implementations", profileName, "profile.json"),
|
|
22233
22311
|
// up one (prod: dist/bin → dist/implementations)
|
|
22234
|
-
|
|
22312
|
+
path49.join(here, "..", "src", "implementations", profileName, "profile.json")
|
|
22235
22313
|
// fallback
|
|
22236
22314
|
];
|
|
22237
22315
|
for (const c of candidates) {
|
|
@@ -22350,7 +22428,7 @@ function resolveShellTimeoutMs(entry) {
|
|
|
22350
22428
|
}
|
|
22351
22429
|
async function runShellEntry(entry, ctx, profile) {
|
|
22352
22430
|
const shellName = entry.shell;
|
|
22353
|
-
const shellPath =
|
|
22431
|
+
const shellPath = path49.join(profile.dir, shellName);
|
|
22354
22432
|
if (!fs52.existsSync(shellPath)) {
|
|
22355
22433
|
ctx.skipAgent = true;
|
|
22356
22434
|
ctx.output.exitCode = 99;
|
|
@@ -22358,7 +22436,7 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
22358
22436
|
return;
|
|
22359
22437
|
}
|
|
22360
22438
|
const positional = entry.with ? Object.values(entry.with).map((v) => String(v)) : [];
|
|
22361
|
-
const outputFile =
|
|
22439
|
+
const outputFile = path49.join(
|
|
22362
22440
|
os8.tmpdir(),
|
|
22363
22441
|
`kody-shell-output-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
22364
22442
|
);
|
|
@@ -22388,14 +22466,14 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
22388
22466
|
let killTimer;
|
|
22389
22467
|
let escalateTimer;
|
|
22390
22468
|
const result = await new Promise(
|
|
22391
|
-
(
|
|
22469
|
+
(resolve20) => {
|
|
22392
22470
|
let settled = false;
|
|
22393
22471
|
const settle = (code, signal, spawnErr) => {
|
|
22394
22472
|
if (settled) return;
|
|
22395
22473
|
settled = true;
|
|
22396
22474
|
if (killTimer) clearTimeout(killTimer);
|
|
22397
22475
|
if (escalateTimer) clearTimeout(escalateTimer);
|
|
22398
|
-
|
|
22476
|
+
resolve20({ code, signal, spawnErr });
|
|
22399
22477
|
};
|
|
22400
22478
|
child.on("error", (err) => settle(null, null, err));
|
|
22401
22479
|
child.on("close", (code, signal) => settle(code, signal));
|
|
@@ -23283,11 +23361,11 @@ function exhaustedWorkflowTransitions(step, data, counts) {
|
|
|
23283
23361
|
}
|
|
23284
23362
|
function workflowResultConditionPaths(transitions) {
|
|
23285
23363
|
return transitions.flatMap(
|
|
23286
|
-
(transition) => Object.keys(transition.when ?? {}).filter((
|
|
23364
|
+
(transition) => Object.keys(transition.when ?? {}).filter((path54) => path54.startsWith("result."))
|
|
23287
23365
|
);
|
|
23288
23366
|
}
|
|
23289
23367
|
function conditionMatches(condition, context) {
|
|
23290
|
-
return Object.entries(condition).every(([
|
|
23368
|
+
return Object.entries(condition).every(([path54, expected]) => valueMatches(resolveDottedPath2(context, path54), expected));
|
|
23291
23369
|
}
|
|
23292
23370
|
function withWorkflowBoundaryEval(capability, result) {
|
|
23293
23371
|
const capabilityKind = capability.config.capabilityKind;
|
|
@@ -23724,7 +23802,7 @@ function translateOpenAISseToBrain(opts) {
|
|
|
23724
23802
|
|
|
23725
23803
|
// src/servers/brain-serve.ts
|
|
23726
23804
|
import { createServer as createServer2 } from "http";
|
|
23727
|
-
import * as
|
|
23805
|
+
import * as path52 from "path";
|
|
23728
23806
|
|
|
23729
23807
|
// src/chat/loop.ts
|
|
23730
23808
|
init_agent();
|
|
@@ -23878,9 +23956,9 @@ var CodexAppServerClient = class {
|
|
|
23878
23956
|
await this.request("thread/resume", { threadId });
|
|
23879
23957
|
}
|
|
23880
23958
|
async runTurn(args) {
|
|
23881
|
-
await new Promise((
|
|
23959
|
+
await new Promise((resolve20, reject) => {
|
|
23882
23960
|
this.process.turnWaiters.set(args.threadId, {
|
|
23883
|
-
resolve:
|
|
23961
|
+
resolve: resolve20,
|
|
23884
23962
|
reject,
|
|
23885
23963
|
onNotification: args.onNotification,
|
|
23886
23964
|
queue: Promise.resolve()
|
|
@@ -23897,8 +23975,8 @@ var CodexAppServerClient = class {
|
|
|
23897
23975
|
}
|
|
23898
23976
|
request(method, params) {
|
|
23899
23977
|
const id = this.process.nextId++;
|
|
23900
|
-
return new Promise((
|
|
23901
|
-
this.process.pending.set(id, { resolve:
|
|
23978
|
+
return new Promise((resolve20, reject) => {
|
|
23979
|
+
this.process.pending.set(id, { resolve: resolve20, reject });
|
|
23902
23980
|
this.process.child.stdin.write(`${JSON.stringify({ method, id, params })}
|
|
23903
23981
|
`);
|
|
23904
23982
|
});
|
|
@@ -24965,7 +25043,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
|
|
|
24965
25043
|
// src/kody-cli.ts
|
|
24966
25044
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
24967
25045
|
import * as fs53 from "fs";
|
|
24968
|
-
import * as
|
|
25046
|
+
import * as path50 from "path";
|
|
24969
25047
|
|
|
24970
25048
|
// src/app-auth.ts
|
|
24971
25049
|
import { createSign } from "crypto";
|
|
@@ -25767,9 +25845,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
25767
25845
|
return void 0;
|
|
25768
25846
|
}
|
|
25769
25847
|
function detectPackageManager2(cwd) {
|
|
25770
|
-
if (fs53.existsSync(
|
|
25771
|
-
if (fs53.existsSync(
|
|
25772
|
-
if (fs53.existsSync(
|
|
25848
|
+
if (fs53.existsSync(path50.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
25849
|
+
if (fs53.existsSync(path50.join(cwd, "yarn.lock"))) return "yarn";
|
|
25850
|
+
if (fs53.existsSync(path50.join(cwd, "bun.lockb"))) return "bun";
|
|
25773
25851
|
return "npm";
|
|
25774
25852
|
}
|
|
25775
25853
|
function shouldChainScheduledWatch(match) {
|
|
@@ -25902,7 +25980,7 @@ async function runCi(argv) {
|
|
|
25902
25980
|
return 0;
|
|
25903
25981
|
}
|
|
25904
25982
|
const args = parseCiArgs(argv);
|
|
25905
|
-
const cwd = args.cwd ?
|
|
25983
|
+
const cwd = args.cwd ? path50.resolve(args.cwd) : process.cwd();
|
|
25906
25984
|
try {
|
|
25907
25985
|
const n = unpackAllSecrets();
|
|
25908
25986
|
if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
|
|
@@ -26386,7 +26464,7 @@ init_repoWorkspace();
|
|
|
26386
26464
|
// src/scripts/brainTurnLog.ts
|
|
26387
26465
|
init_runtimePaths();
|
|
26388
26466
|
import * as fs54 from "fs";
|
|
26389
|
-
import * as
|
|
26467
|
+
import * as path51 from "path";
|
|
26390
26468
|
import posixPath4 from "path/posix";
|
|
26391
26469
|
var live = /* @__PURE__ */ new Map();
|
|
26392
26470
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -26433,7 +26511,7 @@ function beginTurn(dir, chatId) {
|
|
|
26433
26511
|
};
|
|
26434
26512
|
live.set(chatId, state);
|
|
26435
26513
|
const p = brainEventsFilePath(dir, chatId);
|
|
26436
|
-
fs54.mkdirSync(
|
|
26514
|
+
fs54.mkdirSync(path51.dirname(p), { recursive: true });
|
|
26437
26515
|
return (event) => {
|
|
26438
26516
|
state.seq += 1;
|
|
26439
26517
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
@@ -26571,17 +26649,17 @@ function authOk(req, expected) {
|
|
|
26571
26649
|
return false;
|
|
26572
26650
|
}
|
|
26573
26651
|
function readJsonBody(req) {
|
|
26574
|
-
return new Promise((
|
|
26652
|
+
return new Promise((resolve20, reject) => {
|
|
26575
26653
|
const chunks = [];
|
|
26576
26654
|
req.on("data", (c) => chunks.push(c));
|
|
26577
26655
|
req.on("end", () => {
|
|
26578
26656
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
26579
26657
|
if (!raw.trim()) {
|
|
26580
|
-
|
|
26658
|
+
resolve20({});
|
|
26581
26659
|
return;
|
|
26582
26660
|
}
|
|
26583
26661
|
try {
|
|
26584
|
-
|
|
26662
|
+
resolve20(JSON.parse(raw));
|
|
26585
26663
|
} catch (err) {
|
|
26586
26664
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
26587
26665
|
}
|
|
@@ -26873,7 +26951,7 @@ function buildServer(opts) {
|
|
|
26873
26951
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
26874
26952
|
const createStore = opts.createStore ?? createSessionStore;
|
|
26875
26953
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
26876
|
-
const reposRoot = opts.reposRoot ??
|
|
26954
|
+
const reposRoot = opts.reposRoot ?? path52.join(path52.dirname(path52.resolve(opts.cwd)), "repos");
|
|
26877
26955
|
return createServer2(async (req, res) => {
|
|
26878
26956
|
if (!req.method || !req.url) {
|
|
26879
26957
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -26954,11 +27032,11 @@ async function brainServe(opts) {
|
|
|
26954
27032
|
litellmUrl,
|
|
26955
27033
|
driver
|
|
26956
27034
|
});
|
|
26957
|
-
await new Promise((
|
|
27035
|
+
await new Promise((resolve20) => {
|
|
26958
27036
|
server.listen(port, "0.0.0.0", () => {
|
|
26959
27037
|
process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
|
|
26960
27038
|
`);
|
|
26961
|
-
|
|
27039
|
+
resolve20();
|
|
26962
27040
|
});
|
|
26963
27041
|
});
|
|
26964
27042
|
const shutdown = (signal) => {
|
|
@@ -27213,14 +27291,14 @@ async function startBrainProxy(opts) {
|
|
|
27213
27291
|
const { httpServer, handler } = buildBrainProxy(opts);
|
|
27214
27292
|
const port = opts.port ?? 0;
|
|
27215
27293
|
const host = opts.host ?? "127.0.0.1";
|
|
27216
|
-
await new Promise((
|
|
27294
|
+
await new Promise((resolve20) => httpServer.listen(port, host, () => resolve20()));
|
|
27217
27295
|
const addr = httpServer.address();
|
|
27218
27296
|
return {
|
|
27219
27297
|
httpServer,
|
|
27220
27298
|
port: addr.port,
|
|
27221
27299
|
url: `http://${host}:${addr.port}`,
|
|
27222
|
-
stop: () => new Promise((
|
|
27223
|
-
httpServer.close(() =>
|
|
27300
|
+
stop: () => new Promise((resolve20) => {
|
|
27301
|
+
httpServer.close(() => resolve20());
|
|
27224
27302
|
}),
|
|
27225
27303
|
handler
|
|
27226
27304
|
};
|
|
@@ -27370,23 +27448,23 @@ function buildMcpHttpServer(opts) {
|
|
|
27370
27448
|
httpServer,
|
|
27371
27449
|
routes,
|
|
27372
27450
|
port,
|
|
27373
|
-
stop: () => new Promise((
|
|
27451
|
+
stop: () => new Promise((resolve20) => {
|
|
27374
27452
|
let pending = transports.size;
|
|
27375
27453
|
if (pending === 0) {
|
|
27376
|
-
httpServer.close(() =>
|
|
27454
|
+
httpServer.close(() => resolve20());
|
|
27377
27455
|
return;
|
|
27378
27456
|
}
|
|
27379
27457
|
for (const transport of transports.values()) {
|
|
27380
27458
|
void transport.close().finally(() => {
|
|
27381
27459
|
pending--;
|
|
27382
|
-
if (pending === 0) httpServer.close(() =>
|
|
27460
|
+
if (pending === 0) httpServer.close(() => resolve20());
|
|
27383
27461
|
});
|
|
27384
27462
|
}
|
|
27385
27463
|
})
|
|
27386
27464
|
};
|
|
27387
27465
|
}
|
|
27388
27466
|
function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
27389
|
-
return new Promise((
|
|
27467
|
+
return new Promise((resolve20, reject) => {
|
|
27390
27468
|
server.httpServer.once("error", reject);
|
|
27391
27469
|
server.httpServer.listen(server.port, host, () => {
|
|
27392
27470
|
server.httpServer.off("error", reject);
|
|
@@ -27394,7 +27472,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
|
27394
27472
|
if (addr && typeof addr === "object") {
|
|
27395
27473
|
server.port = addr.port;
|
|
27396
27474
|
}
|
|
27397
|
-
|
|
27475
|
+
resolve20();
|
|
27398
27476
|
});
|
|
27399
27477
|
});
|
|
27400
27478
|
}
|
|
@@ -27477,7 +27555,7 @@ async function loadConfigSafe() {
|
|
|
27477
27555
|
}
|
|
27478
27556
|
|
|
27479
27557
|
// src/chat-cli.ts
|
|
27480
|
-
import * as
|
|
27558
|
+
import * as path53 from "path";
|
|
27481
27559
|
|
|
27482
27560
|
// src/chat/inbox.ts
|
|
27483
27561
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
@@ -27544,7 +27622,7 @@ async function waitForNextUserMessage(opts) {
|
|
|
27544
27622
|
}
|
|
27545
27623
|
}
|
|
27546
27624
|
function sleep3(ms) {
|
|
27547
|
-
return new Promise((
|
|
27625
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
27548
27626
|
}
|
|
27549
27627
|
function currentBranch(cwd) {
|
|
27550
27628
|
try {
|
|
@@ -27768,7 +27846,7 @@ async function runChat(argv) {
|
|
|
27768
27846
|
${CHAT_HELP}`);
|
|
27769
27847
|
return 64;
|
|
27770
27848
|
}
|
|
27771
|
-
const cwd = args.cwd ?
|
|
27849
|
+
const cwd = args.cwd ? path53.resolve(args.cwd) : process.cwd();
|
|
27772
27850
|
const sessionId = args.sessionId;
|
|
27773
27851
|
const runRequest = readRunRequestFromEnv();
|
|
27774
27852
|
if (runRequest && "request" in runRequest) {
|
|
@@ -27964,8 +28042,8 @@ var FlyClient = class {
|
|
|
27964
28042
|
get fetch() {
|
|
27965
28043
|
return this.opts.fetchImpl ?? fetch;
|
|
27966
28044
|
}
|
|
27967
|
-
async call(
|
|
27968
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
28045
|
+
async call(path54, init = {}) {
|
|
28046
|
+
const res = await this.fetch(`${FLY_API_BASE}${path54}`, {
|
|
27969
28047
|
method: init.method ?? "GET",
|
|
27970
28048
|
headers: {
|
|
27971
28049
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -27976,7 +28054,7 @@ var FlyClient = class {
|
|
|
27976
28054
|
if (res.status === 404 && init.allow404) return null;
|
|
27977
28055
|
if (!res.ok) {
|
|
27978
28056
|
const text2 = await res.text().catch(() => "");
|
|
27979
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
28057
|
+
throw new Error(`Fly API ${res.status} on ${path54}: ${text2.slice(0, 200) || res.statusText}`);
|
|
27980
28058
|
}
|
|
27981
28059
|
if (res.status === 204) return null;
|
|
27982
28060
|
const raw = await res.text();
|
|
@@ -28489,14 +28567,14 @@ function sendJson2(res, status, body) {
|
|
|
28489
28567
|
res.end(JSON.stringify(body));
|
|
28490
28568
|
}
|
|
28491
28569
|
function readJsonBody2(req) {
|
|
28492
|
-
return new Promise((
|
|
28570
|
+
return new Promise((resolve20, reject) => {
|
|
28493
28571
|
const chunks = [];
|
|
28494
28572
|
req.on("data", (c) => chunks.push(c));
|
|
28495
28573
|
req.on("end", () => {
|
|
28496
28574
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
28497
|
-
if (!raw.trim()) return
|
|
28575
|
+
if (!raw.trim()) return resolve20({});
|
|
28498
28576
|
try {
|
|
28499
|
-
|
|
28577
|
+
resolve20(JSON.parse(raw));
|
|
28500
28578
|
} catch (err) {
|
|
28501
28579
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
28502
28580
|
}
|
|
@@ -28650,10 +28728,10 @@ async function poolServe() {
|
|
|
28650
28728
|
}
|
|
28651
28729
|
});
|
|
28652
28730
|
const apiHost = process.env.POOL_API_HOST ?? "::";
|
|
28653
|
-
await new Promise((
|
|
28731
|
+
await new Promise((resolve20) => {
|
|
28654
28732
|
server.listen(apiPort, apiHost, () => {
|
|
28655
28733
|
log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
|
|
28656
|
-
|
|
28734
|
+
resolve20();
|
|
28657
28735
|
});
|
|
28658
28736
|
});
|
|
28659
28737
|
if (loopTickEnabled) void runLoopTick();
|
|
@@ -28693,17 +28771,17 @@ function authOk2(req, expected) {
|
|
|
28693
28771
|
return false;
|
|
28694
28772
|
}
|
|
28695
28773
|
function readJsonBody3(req) {
|
|
28696
|
-
return new Promise((
|
|
28774
|
+
return new Promise((resolve20, reject) => {
|
|
28697
28775
|
const chunks = [];
|
|
28698
28776
|
req.on("data", (c) => chunks.push(c));
|
|
28699
28777
|
req.on("end", () => {
|
|
28700
28778
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
28701
28779
|
if (!raw.trim()) {
|
|
28702
|
-
|
|
28780
|
+
resolve20({});
|
|
28703
28781
|
return;
|
|
28704
28782
|
}
|
|
28705
28783
|
try {
|
|
28706
|
-
|
|
28784
|
+
resolve20(JSON.parse(raw));
|
|
28707
28785
|
} catch (err) {
|
|
28708
28786
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
28709
28787
|
}
|
|
@@ -28778,13 +28856,13 @@ async function defaultRunJob(job) {
|
|
|
28778
28856
|
...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
|
|
28779
28857
|
...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
|
|
28780
28858
|
};
|
|
28781
|
-
const run = (cmd, args, cwd) => new Promise((
|
|
28859
|
+
const run = (cmd, args, cwd) => new Promise((resolve20) => {
|
|
28782
28860
|
const child = spawn9(cmd, args, { stdio: "inherit", env: childEnv, cwd });
|
|
28783
|
-
child.on("exit", (code) =>
|
|
28861
|
+
child.on("exit", (code) => resolve20(code ?? 0));
|
|
28784
28862
|
child.on("error", (err) => {
|
|
28785
28863
|
process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
|
|
28786
28864
|
`);
|
|
28787
|
-
|
|
28865
|
+
resolve20(1);
|
|
28788
28866
|
});
|
|
28789
28867
|
});
|
|
28790
28868
|
process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
|
|
@@ -28860,11 +28938,11 @@ async function runnerServe() {
|
|
|
28860
28938
|
const port = Number(process.env.PORT ?? DEFAULT_PORT2);
|
|
28861
28939
|
const server = buildServer2({ apiKey });
|
|
28862
28940
|
const host = process.env.RUNNER_HOST ?? "::";
|
|
28863
|
-
await new Promise((
|
|
28941
|
+
await new Promise((resolve20) => {
|
|
28864
28942
|
server.listen(port, host, () => {
|
|
28865
28943
|
process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
|
|
28866
28944
|
`);
|
|
28867
|
-
|
|
28945
|
+
resolve20();
|
|
28868
28946
|
});
|
|
28869
28947
|
});
|
|
28870
28948
|
const shutdown = (signal) => {
|
|
@@ -28933,14 +29011,14 @@ async function serve(opts) {
|
|
|
28933
29011
|
`);
|
|
28934
29012
|
const args = ["--dangerously-skip-permissions", "--model", model.model];
|
|
28935
29013
|
const child = spawn10("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
|
|
28936
|
-
const exitCode = await new Promise((
|
|
28937
|
-
child.on("exit", (code) =>
|
|
29014
|
+
const exitCode = await new Promise((resolve20) => {
|
|
29015
|
+
child.on("exit", (code) => resolve20(code ?? 0));
|
|
28938
29016
|
child.on("error", (err) => {
|
|
28939
29017
|
process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
|
|
28940
29018
|
`);
|
|
28941
29019
|
process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
|
|
28942
29020
|
`);
|
|
28943
|
-
|
|
29021
|
+
resolve20(1);
|
|
28944
29022
|
});
|
|
28945
29023
|
});
|
|
28946
29024
|
killProxy();
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "kody
|
|
3
|
+
"version": "0.4.551",
|
|
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",
|
|
7
7
|
"bin": {
|
|
@@ -12,29 +12,6 @@
|
|
|
12
12
|
"templates",
|
|
13
13
|
"kody.config.schema.json"
|
|
14
14
|
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"kody:run": "tsx bin/kody.ts",
|
|
17
|
-
"serve": "tsx bin/kody.ts serve",
|
|
18
|
-
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
19
|
-
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
20
|
-
"clean:dist": "node scripts/clean-dist.cjs",
|
|
21
|
-
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
22
|
-
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
23
|
-
"pretest": "pnpm check:modularity",
|
|
24
|
-
"test": "vitest run tests/unit tests/int --coverage",
|
|
25
|
-
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
26
|
-
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
27
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
28
|
-
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
29
|
-
"test:all": "vitest run tests --no-coverage",
|
|
30
|
-
"typecheck": "tsc --noEmit",
|
|
31
|
-
"lint": "biome check",
|
|
32
|
-
"lint:fix": "biome check --write",
|
|
33
|
-
"format": "biome format --write",
|
|
34
|
-
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
35
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
36
|
-
"prepublishOnly": "pnpm typecheck && pnpm test:runtime-services && pnpm build && pnpm verify:package"
|
|
37
|
-
},
|
|
38
15
|
"dependencies": {
|
|
39
16
|
"@actions/cache": "^6.0.0",
|
|
40
17
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -61,5 +38,27 @@
|
|
|
61
38
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
62
39
|
},
|
|
63
40
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
64
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
65
|
-
|
|
41
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"kody:run": "tsx bin/kody.ts",
|
|
44
|
+
"serve": "tsx bin/kody.ts serve",
|
|
45
|
+
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
46
|
+
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
47
|
+
"clean:dist": "node scripts/clean-dist.cjs",
|
|
48
|
+
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
49
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
50
|
+
"pretest": "pnpm check:modularity",
|
|
51
|
+
"test": "vitest run tests/unit tests/int --coverage",
|
|
52
|
+
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
53
|
+
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
54
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
55
|
+
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
56
|
+
"test:all": "vitest run tests --no-coverage",
|
|
57
|
+
"typecheck": "tsc --noEmit",
|
|
58
|
+
"lint": "biome check",
|
|
59
|
+
"lint:fix": "biome check --write",
|
|
60
|
+
"format": "biome format --write",
|
|
61
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
62
|
+
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
|
|
63
|
+
}
|
|
64
|
+
}
|