@kody-ade/kody-engine 0.4.550 → 0.4.552
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 +242 -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.552",
|
|
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,67 @@ 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.permissionMode = "default";
|
|
18018
|
+
profile.claudeCode.maxTurns = Math.min(profile.claudeCode.maxTurns ?? 50, 50);
|
|
18019
|
+
}
|
|
17959
18020
|
if (!profile.claudeCode.tools.includes("mcp__playwright")) {
|
|
17960
18021
|
profile.claudeCode.tools = [...profile.claudeCode.tools, "mcp__playwright"];
|
|
17961
18022
|
}
|
|
17962
18023
|
if (!profile.claudeCode.mcpServers.some(({ name }) => name === PLAYWRIGHT_SERVER.name)) {
|
|
17963
|
-
profile.claudeCode.mcpServers = [...profile.claudeCode.mcpServers,
|
|
18024
|
+
profile.claudeCode.mcpServers = [...profile.claudeCode.mcpServers, server];
|
|
17964
18025
|
}
|
|
17965
18026
|
}
|
|
17966
18027
|
function appendPrompt(ctx, section) {
|
|
@@ -17972,6 +18033,7 @@ var init_prepareSimpleCapabilityRuntime = __esm({
|
|
|
17972
18033
|
"src/scripts/prepareSimpleCapabilityRuntime.ts"() {
|
|
17973
18034
|
"use strict";
|
|
17974
18035
|
init_loadQaContext();
|
|
18036
|
+
init_runtimeSecrets();
|
|
17975
18037
|
PLAYWRIGHT_SERVER = {
|
|
17976
18038
|
name: "playwright",
|
|
17977
18039
|
command: "npx",
|
|
@@ -17980,19 +18042,36 @@ var init_prepareSimpleCapabilityRuntime = __esm({
|
|
|
17980
18042
|
prepareSimpleCapabilityRuntime = async (ctx, profile) => {
|
|
17981
18043
|
const requirements = requirementsFrom(ctx);
|
|
17982
18044
|
if (!requirements.browser) return;
|
|
17983
|
-
configureBrowser(profile);
|
|
17984
|
-
if (
|
|
17985
|
-
|
|
17986
|
-
|
|
17987
|
-
|
|
17988
|
-
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
17992
|
-
|
|
17993
|
-
|
|
17994
|
-
|
|
17995
|
-
|
|
18045
|
+
configureBrowser(ctx, profile, requirements);
|
|
18046
|
+
if (requirements.qaCredentials) {
|
|
18047
|
+
await loadQaContext(ctx, profile);
|
|
18048
|
+
appendPrompt(
|
|
18049
|
+
ctx,
|
|
18050
|
+
[
|
|
18051
|
+
"## QA authentication",
|
|
18052
|
+
"",
|
|
18053
|
+
String(ctx.data.qaAuthBlock ?? ""),
|
|
18054
|
+
"",
|
|
18055
|
+
"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."
|
|
18056
|
+
].join("\n")
|
|
18057
|
+
);
|
|
18058
|
+
}
|
|
18059
|
+
if (requirements.githubTestToken) {
|
|
18060
|
+
const token = await resolveRuntimeSecret("E2E_GITHUB_TOKEN", ctx);
|
|
18061
|
+
appendPrompt(
|
|
18062
|
+
ctx,
|
|
18063
|
+
token.value ? [
|
|
18064
|
+
"## Protected GitHub test login",
|
|
18065
|
+
"",
|
|
18066
|
+
`A protected GitHub test token is available: \`${token.value}\``,
|
|
18067
|
+
"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."
|
|
18068
|
+
].join("\n") : [
|
|
18069
|
+
"## Protected GitHub test login",
|
|
18070
|
+
"",
|
|
18071
|
+
"E2E_GITHUB_TOKEN is not configured. If this Quality Scenario requires GitHub token authentication, return a blocked result."
|
|
18072
|
+
].join("\n")
|
|
18073
|
+
);
|
|
18074
|
+
}
|
|
17996
18075
|
};
|
|
17997
18076
|
}
|
|
17998
18077
|
});
|
|
@@ -18279,9 +18358,9 @@ function latestResult(raw, agentResult) {
|
|
|
18279
18358
|
function recordField4(value) {
|
|
18280
18359
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
18281
18360
|
}
|
|
18282
|
-
function resolveDotted(root,
|
|
18283
|
-
if (!
|
|
18284
|
-
return
|
|
18361
|
+
function resolveDotted(root, path54) {
|
|
18362
|
+
if (!path54) return void 0;
|
|
18363
|
+
return path54.split(".").reduce((value, key) => recordField4(value)?.[key], root);
|
|
18285
18364
|
}
|
|
18286
18365
|
function stringValue5(value) {
|
|
18287
18366
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -19123,7 +19202,7 @@ var init_previewBuildHelpers = __esm({
|
|
|
19123
19202
|
// src/scripts/previewBuildRun.ts
|
|
19124
19203
|
import { spawn as spawn5 } from "child_process";
|
|
19125
19204
|
async function runCmd(cmd, args, opts = {}) {
|
|
19126
|
-
await new Promise((
|
|
19205
|
+
await new Promise((resolve20, reject) => {
|
|
19127
19206
|
const child = spawn5(cmd, args, {
|
|
19128
19207
|
cwd: opts.cwd,
|
|
19129
19208
|
env: { ...process.env, ...opts.env ?? {} },
|
|
@@ -19135,7 +19214,7 @@ async function runCmd(cmd, args, opts = {}) {
|
|
|
19135
19214
|
}
|
|
19136
19215
|
child.on("error", reject);
|
|
19137
19216
|
child.on("close", (code) => {
|
|
19138
|
-
if (code === 0)
|
|
19217
|
+
if (code === 0) resolve20();
|
|
19139
19218
|
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
19140
19219
|
});
|
|
19141
19220
|
});
|
|
@@ -19207,12 +19286,12 @@ fi
|
|
|
19207
19286
|
|
|
19208
19287
|
// src/scripts/runPreviewBuild.ts
|
|
19209
19288
|
import { copyFile, writeFile } from "fs/promises";
|
|
19210
|
-
import * as
|
|
19289
|
+
import * as path44 from "path";
|
|
19211
19290
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
19212
19291
|
function bundledDockerfilePath(mode) {
|
|
19213
|
-
const here =
|
|
19292
|
+
const here = path44.dirname(fileURLToPath2(import.meta.url));
|
|
19214
19293
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
19215
|
-
return
|
|
19294
|
+
return path44.join(here, "preview-build-templates", file);
|
|
19216
19295
|
}
|
|
19217
19296
|
function required(name) {
|
|
19218
19297
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -19447,10 +19526,10 @@ var init_runPreviewBuild = __esm({
|
|
|
19447
19526
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
19448
19527
|
if (Object.keys(buildEnv).length > 0) {
|
|
19449
19528
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
19450
|
-
await writeFile(
|
|
19529
|
+
await writeFile(path44.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
19451
19530
|
`, "utf8");
|
|
19452
19531
|
}
|
|
19453
|
-
const consumerDockerfile =
|
|
19532
|
+
const consumerDockerfile = path44.join(ctx.cwd, "Dockerfile.preview");
|
|
19454
19533
|
const { stat } = await import("fs/promises");
|
|
19455
19534
|
let hasConsumerDockerfile = false;
|
|
19456
19535
|
try {
|
|
@@ -19635,7 +19714,7 @@ var init_tickShellRunner = __esm({
|
|
|
19635
19714
|
|
|
19636
19715
|
// src/scripts/runScheduledImplementationTick.ts
|
|
19637
19716
|
import * as fs47 from "fs";
|
|
19638
|
-
import * as
|
|
19717
|
+
import * as path45 from "path";
|
|
19639
19718
|
var runScheduledImplementationTick;
|
|
19640
19719
|
var init_runScheduledImplementationTick = __esm({
|
|
19641
19720
|
"src/scripts/runScheduledImplementationTick.ts"() {
|
|
@@ -19656,13 +19735,13 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
19656
19735
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
19657
19736
|
return;
|
|
19658
19737
|
}
|
|
19659
|
-
const capability = resolveCapabilityFolder(slug,
|
|
19738
|
+
const capability = resolveCapabilityFolder(slug, path45.resolve(ctx.cwd, jobsDir));
|
|
19660
19739
|
if (!capability) {
|
|
19661
19740
|
ctx.output.exitCode = 99;
|
|
19662
19741
|
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
|
|
19663
19742
|
return;
|
|
19664
19743
|
}
|
|
19665
|
-
const shellPath =
|
|
19744
|
+
const shellPath = path45.join(profile.dir, shell);
|
|
19666
19745
|
if (!fs47.existsSync(shellPath)) {
|
|
19667
19746
|
ctx.output.exitCode = 99;
|
|
19668
19747
|
ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
@@ -19781,7 +19860,7 @@ var init_runSimpleCapabilityScript = __esm({
|
|
|
19781
19860
|
|
|
19782
19861
|
// src/scripts/runTickScript.ts
|
|
19783
19862
|
import * as fs49 from "fs";
|
|
19784
|
-
import * as
|
|
19863
|
+
import * as path46 from "path";
|
|
19785
19864
|
var runTickScript;
|
|
19786
19865
|
var init_runTickScript = __esm({
|
|
19787
19866
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -19801,10 +19880,10 @@ var init_runTickScript = __esm({
|
|
|
19801
19880
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
19802
19881
|
return;
|
|
19803
19882
|
}
|
|
19804
|
-
const capability = readCapabilityFolder(
|
|
19883
|
+
const capability = readCapabilityFolder(path46.resolve(ctx.cwd, jobsDir), slug);
|
|
19805
19884
|
if (!capability) {
|
|
19806
19885
|
ctx.output.exitCode = 99;
|
|
19807
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
19886
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path46.resolve(ctx.cwd, jobsDir, slug)}`;
|
|
19808
19887
|
return;
|
|
19809
19888
|
}
|
|
19810
19889
|
const tickScript = capability.config.tickScript;
|
|
@@ -19813,7 +19892,7 @@ var init_runTickScript = __esm({
|
|
|
19813
19892
|
ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
19814
19893
|
return;
|
|
19815
19894
|
}
|
|
19816
|
-
const scriptPath =
|
|
19895
|
+
const scriptPath = path46.isAbsolute(tickScript) ? tickScript : path46.join(ctx.cwd, tickScript);
|
|
19817
19896
|
if (!fs49.existsSync(scriptPath)) {
|
|
19818
19897
|
ctx.output.exitCode = 99;
|
|
19819
19898
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
@@ -20096,7 +20175,7 @@ var init_syncFlow = __esm({
|
|
|
20096
20175
|
});
|
|
20097
20176
|
|
|
20098
20177
|
// src/scripts/validateAgencyModelProposal.ts
|
|
20099
|
-
import * as
|
|
20178
|
+
import * as path47 from "path";
|
|
20100
20179
|
function validateModelBundle(bundle, expectedKind, options = {}) {
|
|
20101
20180
|
const failures = [];
|
|
20102
20181
|
validateOneModel(bundle.model, bundle.files, "model", true, failures, expectedKind, options);
|
|
@@ -20414,7 +20493,7 @@ var init_validateAgencyModelProposal = __esm({
|
|
|
20414
20493
|
const bundle = parseAgencyModelProposal(raw);
|
|
20415
20494
|
const expectedKind = readExpectedModelKind(args);
|
|
20416
20495
|
const failures = validateModelBundle(bundle, expectedKind, {
|
|
20417
|
-
capabilityRoot:
|
|
20496
|
+
capabilityRoot: path47.join(ctx.cwd, ".kody", "capabilities")
|
|
20418
20497
|
});
|
|
20419
20498
|
if (failures.length > 0) {
|
|
20420
20499
|
throw new Error(`validateAgencyModelProposal: ${failures.join("; ")}`);
|
|
@@ -20477,7 +20556,7 @@ function stripAnsi2(s) {
|
|
|
20477
20556
|
return s.replace(ANSI_RE2, "");
|
|
20478
20557
|
}
|
|
20479
20558
|
function runCommand2(command, cwd) {
|
|
20480
|
-
return new Promise((
|
|
20559
|
+
return new Promise((resolve20) => {
|
|
20481
20560
|
const child = spawn6(command, {
|
|
20482
20561
|
cwd,
|
|
20483
20562
|
shell: true,
|
|
@@ -20504,11 +20583,11 @@ function runCommand2(command, cwd) {
|
|
|
20504
20583
|
}, TEST_TIMEOUT_MS);
|
|
20505
20584
|
child.on("exit", (code) => {
|
|
20506
20585
|
clearTimeout(timer);
|
|
20507
|
-
|
|
20586
|
+
resolve20({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
|
|
20508
20587
|
});
|
|
20509
20588
|
child.on("error", (err) => {
|
|
20510
20589
|
clearTimeout(timer);
|
|
20511
|
-
|
|
20590
|
+
resolve20({ exitCode: -1, output: err.message });
|
|
20512
20591
|
});
|
|
20513
20592
|
});
|
|
20514
20593
|
}
|
|
@@ -20914,21 +20993,21 @@ function lineStream(stream) {
|
|
|
20914
20993
|
tryDeliver();
|
|
20915
20994
|
});
|
|
20916
20995
|
return {
|
|
20917
|
-
next: (timeoutMs) => new Promise((
|
|
20996
|
+
next: (timeoutMs) => new Promise((resolve20) => {
|
|
20918
20997
|
if (queue.length > 0) {
|
|
20919
|
-
|
|
20998
|
+
resolve20(queue.shift());
|
|
20920
20999
|
return;
|
|
20921
21000
|
}
|
|
20922
21001
|
if (ended) {
|
|
20923
|
-
|
|
21002
|
+
resolve20(null);
|
|
20924
21003
|
return;
|
|
20925
21004
|
}
|
|
20926
|
-
waiter =
|
|
21005
|
+
waiter = resolve20;
|
|
20927
21006
|
const t = setTimeout(
|
|
20928
21007
|
() => {
|
|
20929
|
-
if (waiter ===
|
|
21008
|
+
if (waiter === resolve20) {
|
|
20930
21009
|
waiter = null;
|
|
20931
|
-
|
|
21010
|
+
resolve20(null);
|
|
20932
21011
|
}
|
|
20933
21012
|
},
|
|
20934
21013
|
Math.max(0, timeoutMs)
|
|
@@ -21330,15 +21409,15 @@ var init_scripts = __esm({
|
|
|
21330
21409
|
|
|
21331
21410
|
// src/stateWorkspace.ts
|
|
21332
21411
|
import * as fs51 from "fs";
|
|
21333
|
-
import * as
|
|
21412
|
+
import * as path48 from "path";
|
|
21334
21413
|
function tenantId(config) {
|
|
21335
21414
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
21336
21415
|
const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
|
|
21337
21416
|
return owner && repo ? `${owner}/${repo}` : null;
|
|
21338
21417
|
}
|
|
21339
21418
|
function writeRuntimeFile(cwd, relativePath, content) {
|
|
21340
|
-
const target =
|
|
21341
|
-
fs51.mkdirSync(
|
|
21419
|
+
const target = path48.join(cwd, RUNTIME_ROOT, relativePath);
|
|
21420
|
+
fs51.mkdirSync(path48.dirname(target), { recursive: true });
|
|
21342
21421
|
fs51.writeFileSync(target, content, "utf8");
|
|
21343
21422
|
}
|
|
21344
21423
|
function record(value) {
|
|
@@ -21404,10 +21483,10 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
|
|
|
21404
21483
|
throw new Error("Kody backend access is required for runtime workspace documents");
|
|
21405
21484
|
return;
|
|
21406
21485
|
}
|
|
21407
|
-
const key = `${
|
|
21486
|
+
const key = `${path48.resolve(cwd)}|${tenant}`;
|
|
21408
21487
|
if (hydratedWorkspaces.has(key)) return;
|
|
21409
21488
|
const backend = backendOverride ?? createStateBackendFromEnv();
|
|
21410
|
-
const root =
|
|
21489
|
+
const root = path48.join(cwd, RUNTIME_ROOT);
|
|
21411
21490
|
fs51.rmSync(root, { recursive: true, force: true });
|
|
21412
21491
|
await Promise.all([
|
|
21413
21492
|
hydratePrefix(backend, tenant, cwd, "context:"),
|
|
@@ -21424,7 +21503,7 @@ var init_stateWorkspace = __esm({
|
|
|
21424
21503
|
"src/stateWorkspace.ts"() {
|
|
21425
21504
|
"use strict";
|
|
21426
21505
|
init_state_backend();
|
|
21427
|
-
RUNTIME_ROOT =
|
|
21506
|
+
RUNTIME_ROOT = path48.join(".kody-engine", "runtime");
|
|
21428
21507
|
hydratedWorkspaces = /* @__PURE__ */ new Set();
|
|
21429
21508
|
}
|
|
21430
21509
|
});
|
|
@@ -21497,7 +21576,7 @@ var init_tools = __esm({
|
|
|
21497
21576
|
import { spawn as spawn8 } from "child_process";
|
|
21498
21577
|
import * as fs52 from "fs";
|
|
21499
21578
|
import * as os8 from "os";
|
|
21500
|
-
import * as
|
|
21579
|
+
import * as path49 from "path";
|
|
21501
21580
|
function isMutatingPostflight(scriptName) {
|
|
21502
21581
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
21503
21582
|
}
|
|
@@ -21749,7 +21828,7 @@ async function runImplementation(profileName, input) {
|
|
|
21749
21828
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
21750
21829
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
21751
21830
|
const invokeAgent = async (prompt) => {
|
|
21752
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
21831
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path49.isAbsolute(p) ? p : path49.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
21753
21832
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
21754
21833
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
21755
21834
|
const agents = loadSubagents(profile);
|
|
@@ -22225,13 +22304,13 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
22225
22304
|
function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
22226
22305
|
const found = resolveImplementation(profileName, getRuntimeProfileRootsForCwd(cwd));
|
|
22227
22306
|
if (found) return found;
|
|
22228
|
-
const here =
|
|
22307
|
+
const here = path49.dirname(new URL(import.meta.url).pathname);
|
|
22229
22308
|
const candidates = [
|
|
22230
|
-
|
|
22309
|
+
path49.join(here, "implementations", profileName, "profile.json"),
|
|
22231
22310
|
// same-dir sibling (dev)
|
|
22232
|
-
|
|
22311
|
+
path49.join(here, "..", "implementations", profileName, "profile.json"),
|
|
22233
22312
|
// up one (prod: dist/bin → dist/implementations)
|
|
22234
|
-
|
|
22313
|
+
path49.join(here, "..", "src", "implementations", profileName, "profile.json")
|
|
22235
22314
|
// fallback
|
|
22236
22315
|
];
|
|
22237
22316
|
for (const c of candidates) {
|
|
@@ -22350,7 +22429,7 @@ function resolveShellTimeoutMs(entry) {
|
|
|
22350
22429
|
}
|
|
22351
22430
|
async function runShellEntry(entry, ctx, profile) {
|
|
22352
22431
|
const shellName = entry.shell;
|
|
22353
|
-
const shellPath =
|
|
22432
|
+
const shellPath = path49.join(profile.dir, shellName);
|
|
22354
22433
|
if (!fs52.existsSync(shellPath)) {
|
|
22355
22434
|
ctx.skipAgent = true;
|
|
22356
22435
|
ctx.output.exitCode = 99;
|
|
@@ -22358,7 +22437,7 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
22358
22437
|
return;
|
|
22359
22438
|
}
|
|
22360
22439
|
const positional = entry.with ? Object.values(entry.with).map((v) => String(v)) : [];
|
|
22361
|
-
const outputFile =
|
|
22440
|
+
const outputFile = path49.join(
|
|
22362
22441
|
os8.tmpdir(),
|
|
22363
22442
|
`kody-shell-output-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
22364
22443
|
);
|
|
@@ -22388,14 +22467,14 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
22388
22467
|
let killTimer;
|
|
22389
22468
|
let escalateTimer;
|
|
22390
22469
|
const result = await new Promise(
|
|
22391
|
-
(
|
|
22470
|
+
(resolve20) => {
|
|
22392
22471
|
let settled = false;
|
|
22393
22472
|
const settle = (code, signal, spawnErr) => {
|
|
22394
22473
|
if (settled) return;
|
|
22395
22474
|
settled = true;
|
|
22396
22475
|
if (killTimer) clearTimeout(killTimer);
|
|
22397
22476
|
if (escalateTimer) clearTimeout(escalateTimer);
|
|
22398
|
-
|
|
22477
|
+
resolve20({ code, signal, spawnErr });
|
|
22399
22478
|
};
|
|
22400
22479
|
child.on("error", (err) => settle(null, null, err));
|
|
22401
22480
|
child.on("close", (code, signal) => settle(code, signal));
|
|
@@ -23283,11 +23362,11 @@ function exhaustedWorkflowTransitions(step, data, counts) {
|
|
|
23283
23362
|
}
|
|
23284
23363
|
function workflowResultConditionPaths(transitions) {
|
|
23285
23364
|
return transitions.flatMap(
|
|
23286
|
-
(transition) => Object.keys(transition.when ?? {}).filter((
|
|
23365
|
+
(transition) => Object.keys(transition.when ?? {}).filter((path54) => path54.startsWith("result."))
|
|
23287
23366
|
);
|
|
23288
23367
|
}
|
|
23289
23368
|
function conditionMatches(condition, context) {
|
|
23290
|
-
return Object.entries(condition).every(([
|
|
23369
|
+
return Object.entries(condition).every(([path54, expected]) => valueMatches(resolveDottedPath2(context, path54), expected));
|
|
23291
23370
|
}
|
|
23292
23371
|
function withWorkflowBoundaryEval(capability, result) {
|
|
23293
23372
|
const capabilityKind = capability.config.capabilityKind;
|
|
@@ -23724,7 +23803,7 @@ function translateOpenAISseToBrain(opts) {
|
|
|
23724
23803
|
|
|
23725
23804
|
// src/servers/brain-serve.ts
|
|
23726
23805
|
import { createServer as createServer2 } from "http";
|
|
23727
|
-
import * as
|
|
23806
|
+
import * as path52 from "path";
|
|
23728
23807
|
|
|
23729
23808
|
// src/chat/loop.ts
|
|
23730
23809
|
init_agent();
|
|
@@ -23878,9 +23957,9 @@ var CodexAppServerClient = class {
|
|
|
23878
23957
|
await this.request("thread/resume", { threadId });
|
|
23879
23958
|
}
|
|
23880
23959
|
async runTurn(args) {
|
|
23881
|
-
await new Promise((
|
|
23960
|
+
await new Promise((resolve20, reject) => {
|
|
23882
23961
|
this.process.turnWaiters.set(args.threadId, {
|
|
23883
|
-
resolve:
|
|
23962
|
+
resolve: resolve20,
|
|
23884
23963
|
reject,
|
|
23885
23964
|
onNotification: args.onNotification,
|
|
23886
23965
|
queue: Promise.resolve()
|
|
@@ -23897,8 +23976,8 @@ var CodexAppServerClient = class {
|
|
|
23897
23976
|
}
|
|
23898
23977
|
request(method, params) {
|
|
23899
23978
|
const id = this.process.nextId++;
|
|
23900
|
-
return new Promise((
|
|
23901
|
-
this.process.pending.set(id, { resolve:
|
|
23979
|
+
return new Promise((resolve20, reject) => {
|
|
23980
|
+
this.process.pending.set(id, { resolve: resolve20, reject });
|
|
23902
23981
|
this.process.child.stdin.write(`${JSON.stringify({ method, id, params })}
|
|
23903
23982
|
`);
|
|
23904
23983
|
});
|
|
@@ -24965,7 +25044,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
|
|
|
24965
25044
|
// src/kody-cli.ts
|
|
24966
25045
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
24967
25046
|
import * as fs53 from "fs";
|
|
24968
|
-
import * as
|
|
25047
|
+
import * as path50 from "path";
|
|
24969
25048
|
|
|
24970
25049
|
// src/app-auth.ts
|
|
24971
25050
|
import { createSign } from "crypto";
|
|
@@ -25767,9 +25846,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
25767
25846
|
return void 0;
|
|
25768
25847
|
}
|
|
25769
25848
|
function detectPackageManager2(cwd) {
|
|
25770
|
-
if (fs53.existsSync(
|
|
25771
|
-
if (fs53.existsSync(
|
|
25772
|
-
if (fs53.existsSync(
|
|
25849
|
+
if (fs53.existsSync(path50.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
25850
|
+
if (fs53.existsSync(path50.join(cwd, "yarn.lock"))) return "yarn";
|
|
25851
|
+
if (fs53.existsSync(path50.join(cwd, "bun.lockb"))) return "bun";
|
|
25773
25852
|
return "npm";
|
|
25774
25853
|
}
|
|
25775
25854
|
function shouldChainScheduledWatch(match) {
|
|
@@ -25902,7 +25981,7 @@ async function runCi(argv) {
|
|
|
25902
25981
|
return 0;
|
|
25903
25982
|
}
|
|
25904
25983
|
const args = parseCiArgs(argv);
|
|
25905
|
-
const cwd = args.cwd ?
|
|
25984
|
+
const cwd = args.cwd ? path50.resolve(args.cwd) : process.cwd();
|
|
25906
25985
|
try {
|
|
25907
25986
|
const n = unpackAllSecrets();
|
|
25908
25987
|
if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
|
|
@@ -26386,7 +26465,7 @@ init_repoWorkspace();
|
|
|
26386
26465
|
// src/scripts/brainTurnLog.ts
|
|
26387
26466
|
init_runtimePaths();
|
|
26388
26467
|
import * as fs54 from "fs";
|
|
26389
|
-
import * as
|
|
26468
|
+
import * as path51 from "path";
|
|
26390
26469
|
import posixPath4 from "path/posix";
|
|
26391
26470
|
var live = /* @__PURE__ */ new Map();
|
|
26392
26471
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -26433,7 +26512,7 @@ function beginTurn(dir, chatId) {
|
|
|
26433
26512
|
};
|
|
26434
26513
|
live.set(chatId, state);
|
|
26435
26514
|
const p = brainEventsFilePath(dir, chatId);
|
|
26436
|
-
fs54.mkdirSync(
|
|
26515
|
+
fs54.mkdirSync(path51.dirname(p), { recursive: true });
|
|
26437
26516
|
return (event) => {
|
|
26438
26517
|
state.seq += 1;
|
|
26439
26518
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
@@ -26571,17 +26650,17 @@ function authOk(req, expected) {
|
|
|
26571
26650
|
return false;
|
|
26572
26651
|
}
|
|
26573
26652
|
function readJsonBody(req) {
|
|
26574
|
-
return new Promise((
|
|
26653
|
+
return new Promise((resolve20, reject) => {
|
|
26575
26654
|
const chunks = [];
|
|
26576
26655
|
req.on("data", (c) => chunks.push(c));
|
|
26577
26656
|
req.on("end", () => {
|
|
26578
26657
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
26579
26658
|
if (!raw.trim()) {
|
|
26580
|
-
|
|
26659
|
+
resolve20({});
|
|
26581
26660
|
return;
|
|
26582
26661
|
}
|
|
26583
26662
|
try {
|
|
26584
|
-
|
|
26663
|
+
resolve20(JSON.parse(raw));
|
|
26585
26664
|
} catch (err) {
|
|
26586
26665
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
26587
26666
|
}
|
|
@@ -26873,7 +26952,7 @@ function buildServer(opts) {
|
|
|
26873
26952
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
26874
26953
|
const createStore = opts.createStore ?? createSessionStore;
|
|
26875
26954
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
26876
|
-
const reposRoot = opts.reposRoot ??
|
|
26955
|
+
const reposRoot = opts.reposRoot ?? path52.join(path52.dirname(path52.resolve(opts.cwd)), "repos");
|
|
26877
26956
|
return createServer2(async (req, res) => {
|
|
26878
26957
|
if (!req.method || !req.url) {
|
|
26879
26958
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -26954,11 +27033,11 @@ async function brainServe(opts) {
|
|
|
26954
27033
|
litellmUrl,
|
|
26955
27034
|
driver
|
|
26956
27035
|
});
|
|
26957
|
-
await new Promise((
|
|
27036
|
+
await new Promise((resolve20) => {
|
|
26958
27037
|
server.listen(port, "0.0.0.0", () => {
|
|
26959
27038
|
process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
|
|
26960
27039
|
`);
|
|
26961
|
-
|
|
27040
|
+
resolve20();
|
|
26962
27041
|
});
|
|
26963
27042
|
});
|
|
26964
27043
|
const shutdown = (signal) => {
|
|
@@ -27213,14 +27292,14 @@ async function startBrainProxy(opts) {
|
|
|
27213
27292
|
const { httpServer, handler } = buildBrainProxy(opts);
|
|
27214
27293
|
const port = opts.port ?? 0;
|
|
27215
27294
|
const host = opts.host ?? "127.0.0.1";
|
|
27216
|
-
await new Promise((
|
|
27295
|
+
await new Promise((resolve20) => httpServer.listen(port, host, () => resolve20()));
|
|
27217
27296
|
const addr = httpServer.address();
|
|
27218
27297
|
return {
|
|
27219
27298
|
httpServer,
|
|
27220
27299
|
port: addr.port,
|
|
27221
27300
|
url: `http://${host}:${addr.port}`,
|
|
27222
|
-
stop: () => new Promise((
|
|
27223
|
-
httpServer.close(() =>
|
|
27301
|
+
stop: () => new Promise((resolve20) => {
|
|
27302
|
+
httpServer.close(() => resolve20());
|
|
27224
27303
|
}),
|
|
27225
27304
|
handler
|
|
27226
27305
|
};
|
|
@@ -27370,23 +27449,23 @@ function buildMcpHttpServer(opts) {
|
|
|
27370
27449
|
httpServer,
|
|
27371
27450
|
routes,
|
|
27372
27451
|
port,
|
|
27373
|
-
stop: () => new Promise((
|
|
27452
|
+
stop: () => new Promise((resolve20) => {
|
|
27374
27453
|
let pending = transports.size;
|
|
27375
27454
|
if (pending === 0) {
|
|
27376
|
-
httpServer.close(() =>
|
|
27455
|
+
httpServer.close(() => resolve20());
|
|
27377
27456
|
return;
|
|
27378
27457
|
}
|
|
27379
27458
|
for (const transport of transports.values()) {
|
|
27380
27459
|
void transport.close().finally(() => {
|
|
27381
27460
|
pending--;
|
|
27382
|
-
if (pending === 0) httpServer.close(() =>
|
|
27461
|
+
if (pending === 0) httpServer.close(() => resolve20());
|
|
27383
27462
|
});
|
|
27384
27463
|
}
|
|
27385
27464
|
})
|
|
27386
27465
|
};
|
|
27387
27466
|
}
|
|
27388
27467
|
function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
27389
|
-
return new Promise((
|
|
27468
|
+
return new Promise((resolve20, reject) => {
|
|
27390
27469
|
server.httpServer.once("error", reject);
|
|
27391
27470
|
server.httpServer.listen(server.port, host, () => {
|
|
27392
27471
|
server.httpServer.off("error", reject);
|
|
@@ -27394,7 +27473,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
|
27394
27473
|
if (addr && typeof addr === "object") {
|
|
27395
27474
|
server.port = addr.port;
|
|
27396
27475
|
}
|
|
27397
|
-
|
|
27476
|
+
resolve20();
|
|
27398
27477
|
});
|
|
27399
27478
|
});
|
|
27400
27479
|
}
|
|
@@ -27477,7 +27556,7 @@ async function loadConfigSafe() {
|
|
|
27477
27556
|
}
|
|
27478
27557
|
|
|
27479
27558
|
// src/chat-cli.ts
|
|
27480
|
-
import * as
|
|
27559
|
+
import * as path53 from "path";
|
|
27481
27560
|
|
|
27482
27561
|
// src/chat/inbox.ts
|
|
27483
27562
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
@@ -27544,7 +27623,7 @@ async function waitForNextUserMessage(opts) {
|
|
|
27544
27623
|
}
|
|
27545
27624
|
}
|
|
27546
27625
|
function sleep3(ms) {
|
|
27547
|
-
return new Promise((
|
|
27626
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
27548
27627
|
}
|
|
27549
27628
|
function currentBranch(cwd) {
|
|
27550
27629
|
try {
|
|
@@ -27768,7 +27847,7 @@ async function runChat(argv) {
|
|
|
27768
27847
|
${CHAT_HELP}`);
|
|
27769
27848
|
return 64;
|
|
27770
27849
|
}
|
|
27771
|
-
const cwd = args.cwd ?
|
|
27850
|
+
const cwd = args.cwd ? path53.resolve(args.cwd) : process.cwd();
|
|
27772
27851
|
const sessionId = args.sessionId;
|
|
27773
27852
|
const runRequest = readRunRequestFromEnv();
|
|
27774
27853
|
if (runRequest && "request" in runRequest) {
|
|
@@ -27964,8 +28043,8 @@ var FlyClient = class {
|
|
|
27964
28043
|
get fetch() {
|
|
27965
28044
|
return this.opts.fetchImpl ?? fetch;
|
|
27966
28045
|
}
|
|
27967
|
-
async call(
|
|
27968
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
28046
|
+
async call(path54, init = {}) {
|
|
28047
|
+
const res = await this.fetch(`${FLY_API_BASE}${path54}`, {
|
|
27969
28048
|
method: init.method ?? "GET",
|
|
27970
28049
|
headers: {
|
|
27971
28050
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -27976,7 +28055,7 @@ var FlyClient = class {
|
|
|
27976
28055
|
if (res.status === 404 && init.allow404) return null;
|
|
27977
28056
|
if (!res.ok) {
|
|
27978
28057
|
const text2 = await res.text().catch(() => "");
|
|
27979
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
28058
|
+
throw new Error(`Fly API ${res.status} on ${path54}: ${text2.slice(0, 200) || res.statusText}`);
|
|
27980
28059
|
}
|
|
27981
28060
|
if (res.status === 204) return null;
|
|
27982
28061
|
const raw = await res.text();
|
|
@@ -28489,14 +28568,14 @@ function sendJson2(res, status, body) {
|
|
|
28489
28568
|
res.end(JSON.stringify(body));
|
|
28490
28569
|
}
|
|
28491
28570
|
function readJsonBody2(req) {
|
|
28492
|
-
return new Promise((
|
|
28571
|
+
return new Promise((resolve20, reject) => {
|
|
28493
28572
|
const chunks = [];
|
|
28494
28573
|
req.on("data", (c) => chunks.push(c));
|
|
28495
28574
|
req.on("end", () => {
|
|
28496
28575
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
28497
|
-
if (!raw.trim()) return
|
|
28576
|
+
if (!raw.trim()) return resolve20({});
|
|
28498
28577
|
try {
|
|
28499
|
-
|
|
28578
|
+
resolve20(JSON.parse(raw));
|
|
28500
28579
|
} catch (err) {
|
|
28501
28580
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
28502
28581
|
}
|
|
@@ -28650,10 +28729,10 @@ async function poolServe() {
|
|
|
28650
28729
|
}
|
|
28651
28730
|
});
|
|
28652
28731
|
const apiHost = process.env.POOL_API_HOST ?? "::";
|
|
28653
|
-
await new Promise((
|
|
28732
|
+
await new Promise((resolve20) => {
|
|
28654
28733
|
server.listen(apiPort, apiHost, () => {
|
|
28655
28734
|
log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
|
|
28656
|
-
|
|
28735
|
+
resolve20();
|
|
28657
28736
|
});
|
|
28658
28737
|
});
|
|
28659
28738
|
if (loopTickEnabled) void runLoopTick();
|
|
@@ -28693,17 +28772,17 @@ function authOk2(req, expected) {
|
|
|
28693
28772
|
return false;
|
|
28694
28773
|
}
|
|
28695
28774
|
function readJsonBody3(req) {
|
|
28696
|
-
return new Promise((
|
|
28775
|
+
return new Promise((resolve20, reject) => {
|
|
28697
28776
|
const chunks = [];
|
|
28698
28777
|
req.on("data", (c) => chunks.push(c));
|
|
28699
28778
|
req.on("end", () => {
|
|
28700
28779
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
28701
28780
|
if (!raw.trim()) {
|
|
28702
|
-
|
|
28781
|
+
resolve20({});
|
|
28703
28782
|
return;
|
|
28704
28783
|
}
|
|
28705
28784
|
try {
|
|
28706
|
-
|
|
28785
|
+
resolve20(JSON.parse(raw));
|
|
28707
28786
|
} catch (err) {
|
|
28708
28787
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
28709
28788
|
}
|
|
@@ -28778,13 +28857,13 @@ async function defaultRunJob(job) {
|
|
|
28778
28857
|
...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
|
|
28779
28858
|
...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
|
|
28780
28859
|
};
|
|
28781
|
-
const run = (cmd, args, cwd) => new Promise((
|
|
28860
|
+
const run = (cmd, args, cwd) => new Promise((resolve20) => {
|
|
28782
28861
|
const child = spawn9(cmd, args, { stdio: "inherit", env: childEnv, cwd });
|
|
28783
|
-
child.on("exit", (code) =>
|
|
28862
|
+
child.on("exit", (code) => resolve20(code ?? 0));
|
|
28784
28863
|
child.on("error", (err) => {
|
|
28785
28864
|
process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
|
|
28786
28865
|
`);
|
|
28787
|
-
|
|
28866
|
+
resolve20(1);
|
|
28788
28867
|
});
|
|
28789
28868
|
});
|
|
28790
28869
|
process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
|
|
@@ -28860,11 +28939,11 @@ async function runnerServe() {
|
|
|
28860
28939
|
const port = Number(process.env.PORT ?? DEFAULT_PORT2);
|
|
28861
28940
|
const server = buildServer2({ apiKey });
|
|
28862
28941
|
const host = process.env.RUNNER_HOST ?? "::";
|
|
28863
|
-
await new Promise((
|
|
28942
|
+
await new Promise((resolve20) => {
|
|
28864
28943
|
server.listen(port, host, () => {
|
|
28865
28944
|
process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
|
|
28866
28945
|
`);
|
|
28867
|
-
|
|
28946
|
+
resolve20();
|
|
28868
28947
|
});
|
|
28869
28948
|
});
|
|
28870
28949
|
const shutdown = (signal) => {
|
|
@@ -28933,14 +29012,14 @@ async function serve(opts) {
|
|
|
28933
29012
|
`);
|
|
28934
29013
|
const args = ["--dangerously-skip-permissions", "--model", model.model];
|
|
28935
29014
|
const child = spawn10("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
|
|
28936
|
-
const exitCode = await new Promise((
|
|
28937
|
-
child.on("exit", (code) =>
|
|
29015
|
+
const exitCode = await new Promise((resolve20) => {
|
|
29016
|
+
child.on("exit", (code) => resolve20(code ?? 0));
|
|
28938
29017
|
child.on("error", (err) => {
|
|
28939
29018
|
process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
|
|
28940
29019
|
`);
|
|
28941
29020
|
process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
|
|
28942
29021
|
`);
|
|
28943
|
-
|
|
29022
|
+
resolve20(1);
|
|
28944
29023
|
});
|
|
28945
29024
|
});
|
|
28946
29025
|
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.552",
|
|
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
|
+
}
|