@kody-ade/kody-engine 0.4.449 → 0.4.451
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 +60 -53
- package/package.json +1 -1
package/dist/bin/kody.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "@kody-ade/kody-engine",
|
|
18
|
-
version: "0.4.
|
|
18
|
+
version: "0.4.451",
|
|
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",
|
|
@@ -1104,7 +1104,7 @@ function cmsHeaders(opts) {
|
|
|
1104
1104
|
}
|
|
1105
1105
|
};
|
|
1106
1106
|
}
|
|
1107
|
-
async function callDashboardCms(opts,
|
|
1107
|
+
async function callDashboardCms(opts, path53, init = {}) {
|
|
1108
1108
|
const baseUrl = dashboardBaseUrl(opts);
|
|
1109
1109
|
if (!baseUrl) {
|
|
1110
1110
|
return {
|
|
@@ -1116,7 +1116,7 @@ async function callDashboardCms(opts, path54, init = {}) {
|
|
|
1116
1116
|
const headerResult = cmsHeaders(opts);
|
|
1117
1117
|
if (!headerResult.ok) return headerResult;
|
|
1118
1118
|
try {
|
|
1119
|
-
const res = await fetch(`${baseUrl}${
|
|
1119
|
+
const res = await fetch(`${baseUrl}${path53}`, {
|
|
1120
1120
|
...init,
|
|
1121
1121
|
headers: {
|
|
1122
1122
|
...headerResult.headers,
|
|
@@ -1188,8 +1188,8 @@ function documentArg(value) {
|
|
|
1188
1188
|
function normalizeCmsDocumentIdInput(input) {
|
|
1189
1189
|
const trimmed = stripWrappingQuotes(input.trim());
|
|
1190
1190
|
const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? trimmed;
|
|
1191
|
-
const
|
|
1192
|
-
return
|
|
1191
|
+
const path53 = parseDocumentPath(withoutQuery);
|
|
1192
|
+
return path53 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
|
|
1193
1193
|
}
|
|
1194
1194
|
function stripWrappingQuotes(value) {
|
|
1195
1195
|
let current = value;
|
|
@@ -1200,9 +1200,9 @@ function stripWrappingQuotes(value) {
|
|
|
1200
1200
|
}
|
|
1201
1201
|
}
|
|
1202
1202
|
function parseDocumentPath(value) {
|
|
1203
|
-
const
|
|
1204
|
-
if (!
|
|
1205
|
-
const parts =
|
|
1203
|
+
const path53 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
|
|
1204
|
+
if (!path53?.includes("/content/entries/")) return null;
|
|
1205
|
+
const parts = path53.split("/").filter(Boolean).map(decodePathPart);
|
|
1206
1206
|
const entriesIndex = parts.findIndex((part, index) => part === "content" && parts[index + 1] === "entries");
|
|
1207
1207
|
const idPart = parts[entriesIndex + 3];
|
|
1208
1208
|
if (!idPart || idPart === "new") return null;
|
|
@@ -8097,9 +8097,9 @@ import * as fs27 from "fs";
|
|
|
8097
8097
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
8098
8098
|
const logs = goalRunLogs(data);
|
|
8099
8099
|
const existing = logs[goalId];
|
|
8100
|
-
const
|
|
8100
|
+
const path53 = existing?.path ?? goalRunLogPath(goalId, data);
|
|
8101
8101
|
logs[goalId] = {
|
|
8102
|
-
path:
|
|
8102
|
+
path: path53,
|
|
8103
8103
|
events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
|
|
8104
8104
|
};
|
|
8105
8105
|
}
|
|
@@ -9050,11 +9050,11 @@ function validateWorkflow(value, options = {}) {
|
|
|
9050
9050
|
function formatWorkflowValidationIssues(issues) {
|
|
9051
9051
|
return issues.map((entry) => `${entry.path}: ${entry.message}`);
|
|
9052
9052
|
}
|
|
9053
|
-
function validateDataMatch(value,
|
|
9053
|
+
function validateDataMatch(value, path53, issues, capabilityOutputs) {
|
|
9054
9054
|
if (value === void 0) return;
|
|
9055
9055
|
const match = asRecord2(value);
|
|
9056
9056
|
if (!match || Object.keys(match).length === 0) {
|
|
9057
|
-
issue(issues, "invalid_condition",
|
|
9057
|
+
issue(issues, "invalid_condition", path53, "workflow condition must contain at least one match");
|
|
9058
9058
|
return;
|
|
9059
9059
|
}
|
|
9060
9060
|
for (const [field, expected] of Object.entries(match)) {
|
|
@@ -9062,7 +9062,7 @@ function validateDataMatch(value, path54, issues, capabilityOutputs) {
|
|
|
9062
9062
|
issue(
|
|
9063
9063
|
issues,
|
|
9064
9064
|
"invalid_data_path",
|
|
9065
|
-
`${
|
|
9065
|
+
`${path53}.${field}`,
|
|
9066
9066
|
`workflow condition must read from facts, evidence, artifacts, result, workflow, or lastOutcome`
|
|
9067
9067
|
);
|
|
9068
9068
|
}
|
|
@@ -9070,12 +9070,12 @@ function validateDataMatch(value, path54, issues, capabilityOutputs) {
|
|
|
9070
9070
|
issue(
|
|
9071
9071
|
issues,
|
|
9072
9072
|
"undeclared_result_path",
|
|
9073
|
-
`${
|
|
9073
|
+
`${path53}.${field}`,
|
|
9074
9074
|
`workflow condition reads ${field}, but the source capability does not declare it`
|
|
9075
9075
|
);
|
|
9076
9076
|
}
|
|
9077
9077
|
if (!isComparable(expected)) {
|
|
9078
|
-
issue(issues, "invalid_condition_value", `${
|
|
9078
|
+
issue(issues, "invalid_condition_value", `${path53}.${field}`, "workflow condition value must be a JSON scalar");
|
|
9079
9079
|
}
|
|
9080
9080
|
}
|
|
9081
9081
|
}
|
|
@@ -9099,8 +9099,8 @@ function isJsonValue(value) {
|
|
|
9099
9099
|
if (!value || typeof value !== "object") return false;
|
|
9100
9100
|
return Object.values(value).every(isJsonValue);
|
|
9101
9101
|
}
|
|
9102
|
-
function issue(issues, code,
|
|
9103
|
-
issues.push({ code, path:
|
|
9102
|
+
function issue(issues, code, path53, message) {
|
|
9103
|
+
issues.push({ code, path: path53, message });
|
|
9104
9104
|
}
|
|
9105
9105
|
var SAFE_NAME, SAFE_STEP_ID, SAFE_DATA_PATH, SUPPORTED_STEP_FIELDS, SUPPORTED_TRANSITION_FIELDS;
|
|
9106
9106
|
var init_workflowValidation = __esm({
|
|
@@ -9365,15 +9365,15 @@ var init_backendStateBackend = __esm({
|
|
|
9365
9365
|
this.jobsDir = opts.jobsDir.replace(/\/+$/, "");
|
|
9366
9366
|
}
|
|
9367
9367
|
async load(slug) {
|
|
9368
|
-
const
|
|
9368
|
+
const path53 = stateFilePath(this.jobsDir, slug);
|
|
9369
9369
|
const loaded = await createStateBackendFromEnv().get(this.tenantId, `capabilities/${slug}`, "job-state");
|
|
9370
9370
|
if (!loaded) {
|
|
9371
|
-
return { path:
|
|
9371
|
+
return { path: path53, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
9372
9372
|
}
|
|
9373
9373
|
if (!isStateEnvelope(loaded.doc)) {
|
|
9374
9374
|
throw new Error(`BackendStateBackend: capabilities/${slug} is not a StateEnvelope`);
|
|
9375
9375
|
}
|
|
9376
|
-
return { path:
|
|
9376
|
+
return { path: path53, handle: loaded.updatedAt, state: loaded.doc, created: false };
|
|
9377
9377
|
}
|
|
9378
9378
|
async save(loaded, next) {
|
|
9379
9379
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) return false;
|
|
@@ -13851,7 +13851,7 @@ function normalizeLoopDefinition(value) {
|
|
|
13851
13851
|
}
|
|
13852
13852
|
function readLoopDefinition(cwd, id) {
|
|
13853
13853
|
if (!ID.test(id)) return null;
|
|
13854
|
-
const roots =
|
|
13854
|
+
const roots = loopRoots(cwd);
|
|
13855
13855
|
for (const root of roots) {
|
|
13856
13856
|
const filePath = path34.join(root, "loops", id, "loop.json");
|
|
13857
13857
|
if (!fs36.existsSync(filePath)) continue;
|
|
@@ -13872,7 +13872,7 @@ function readLoopDefinition(cwd, id) {
|
|
|
13872
13872
|
return null;
|
|
13873
13873
|
}
|
|
13874
13874
|
function listLoopDefinitions(cwd) {
|
|
13875
|
-
const roots =
|
|
13875
|
+
const roots = loopRoots(cwd);
|
|
13876
13876
|
const byId = /* @__PURE__ */ new Map();
|
|
13877
13877
|
for (const root of roots.reverse()) {
|
|
13878
13878
|
const loopsDir = path34.join(root, "loops");
|
|
@@ -13892,6 +13892,13 @@ function listLoopDefinitions(cwd) {
|
|
|
13892
13892
|
}
|
|
13893
13893
|
return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
13894
13894
|
}
|
|
13895
|
+
function loopRoots(cwd) {
|
|
13896
|
+
return [
|
|
13897
|
+
path34.join(cwd, ".kody-engine", "runtime"),
|
|
13898
|
+
path34.join(cwd, ".kody-engine", "definitions"),
|
|
13899
|
+
definitionsRoot(cwd)
|
|
13900
|
+
].filter((root, index, roots) => roots.indexOf(root) === index);
|
|
13901
|
+
}
|
|
13895
13902
|
function normalizeTrigger(raw) {
|
|
13896
13903
|
if (raw.type === "manual" && Object.keys(raw).length === 1) return { type: "manual" };
|
|
13897
13904
|
if (raw.type === "schedule" && typeof raw.every === "string" && /^\d+[mhd]$/.test(raw.every)) {
|
|
@@ -15535,13 +15542,13 @@ var init_loadSimpleCapability = __esm({
|
|
|
15535
15542
|
function isCompanyIntentId(value) {
|
|
15536
15543
|
return SLUG_RE2.test(value);
|
|
15537
15544
|
}
|
|
15538
|
-
function normalizeCompanyIntent(
|
|
15545
|
+
function normalizeCompanyIntent(path53, raw) {
|
|
15539
15546
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
15540
|
-
throw new Error(`${
|
|
15547
|
+
throw new Error(`${path53}: intent must be JSON object`);
|
|
15541
15548
|
}
|
|
15542
15549
|
const input = raw;
|
|
15543
15550
|
const id = stringField4(input.id);
|
|
15544
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${
|
|
15551
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path53}: invalid intent id`);
|
|
15545
15552
|
const createdAt = stringField4(input.createdAt) || nowIso();
|
|
15546
15553
|
const updatedAt = stringField4(input.updatedAt) || createdAt;
|
|
15547
15554
|
const description = stringField4(input.description);
|
|
@@ -16688,19 +16695,19 @@ function parseAgencyModelProposal(raw) {
|
|
|
16688
16695
|
function normalizeBundleFiles(bundle) {
|
|
16689
16696
|
const seen = /* @__PURE__ */ new Set();
|
|
16690
16697
|
return bundle.files.map((file, index) => {
|
|
16691
|
-
const
|
|
16692
|
-
const parts =
|
|
16693
|
-
if (!
|
|
16698
|
+
const path53 = file.path.replace(/^\/+/, "");
|
|
16699
|
+
const parts = path53.split("/");
|
|
16700
|
+
if (!path53 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
|
|
16694
16701
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is unsafe`);
|
|
16695
16702
|
}
|
|
16696
16703
|
if (!/^(agents\/[^/]+\.md|capabilities\/[^/]+\/.+|goals\/(?:templates\/)?[^/]+\/.+|workflows\/[^/]+\.json)$/.test(
|
|
16697
|
-
|
|
16704
|
+
path53
|
|
16698
16705
|
)) {
|
|
16699
16706
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is not a supported definition path`);
|
|
16700
16707
|
}
|
|
16701
|
-
if (seen.has(
|
|
16702
|
-
seen.add(
|
|
16703
|
-
return { path:
|
|
16708
|
+
if (seen.has(path53)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path53}`);
|
|
16709
|
+
seen.add(path53);
|
|
16710
|
+
return { path: path53, content: file.content.replace(/\r\n?/g, "\n") };
|
|
16704
16711
|
});
|
|
16705
16712
|
}
|
|
16706
16713
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
@@ -17987,9 +17994,9 @@ function latestResult(raw, agentResult) {
|
|
|
17987
17994
|
function recordField4(value) {
|
|
17988
17995
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
17989
17996
|
}
|
|
17990
|
-
function resolveDotted(root,
|
|
17991
|
-
if (!
|
|
17992
|
-
return
|
|
17997
|
+
function resolveDotted(root, path53) {
|
|
17998
|
+
if (!path53) return void 0;
|
|
17999
|
+
return path53.split(".").reduce((value, key) => recordField4(value)?.[key], root);
|
|
17993
18000
|
}
|
|
17994
18001
|
function stringValue5(value) {
|
|
17995
18002
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -22257,7 +22264,6 @@ __export(job_exports, {
|
|
|
22257
22264
|
stableJobKey: () => stableJobKey,
|
|
22258
22265
|
validateJob: () => validateJob
|
|
22259
22266
|
});
|
|
22260
|
-
import * as path49 from "path";
|
|
22261
22267
|
function newJobId(flavor) {
|
|
22262
22268
|
localJobSeq += 1;
|
|
22263
22269
|
const runId = process.env.GITHUB_RUN_ID;
|
|
@@ -22777,11 +22783,11 @@ function selectWorkflowTransition(step, data, counts) {
|
|
|
22777
22783
|
}
|
|
22778
22784
|
function workflowResultConditionPaths(transitions) {
|
|
22779
22785
|
return transitions.flatMap(
|
|
22780
|
-
(transition) => Object.keys(transition.when ?? {}).filter((
|
|
22786
|
+
(transition) => Object.keys(transition.when ?? {}).filter((path53) => path53.startsWith("result."))
|
|
22781
22787
|
);
|
|
22782
22788
|
}
|
|
22783
22789
|
function conditionMatches(condition, context) {
|
|
22784
|
-
return Object.entries(condition).every(([
|
|
22790
|
+
return Object.entries(condition).every(([path53, expected]) => valueMatches(resolveDottedPath2(context, path53), expected));
|
|
22785
22791
|
}
|
|
22786
22792
|
function withWorkflowBoundaryEval(capability, result) {
|
|
22787
22793
|
const capabilityKind = capability.config.capabilityKind;
|
|
@@ -22965,7 +22971,7 @@ function loadCapabilityContext(slug, cwd) {
|
|
|
22965
22971
|
return resolveCapabilityFolder(slug, hydratedCapabilitiesRoot(cwd));
|
|
22966
22972
|
}
|
|
22967
22973
|
function hydratedCapabilitiesRoot(cwd) {
|
|
22968
|
-
return
|
|
22974
|
+
return capabilitiesRoot(cwd);
|
|
22969
22975
|
}
|
|
22970
22976
|
function loadWorkflowContext(slug, base) {
|
|
22971
22977
|
if (!slug || !isWorkflowDefinitionId(slug)) return null;
|
|
@@ -23003,6 +23009,7 @@ var init_job = __esm({
|
|
|
23003
23009
|
"use strict";
|
|
23004
23010
|
init_agencyBoundaryEval();
|
|
23005
23011
|
init_capabilityFolders();
|
|
23012
|
+
init_definition_paths();
|
|
23006
23013
|
init_executor();
|
|
23007
23014
|
init_registry();
|
|
23008
23015
|
init_runIndex();
|
|
@@ -23131,7 +23138,7 @@ function translateOpenAISseToBrain(opts) {
|
|
|
23131
23138
|
|
|
23132
23139
|
// src/servers/brain-serve.ts
|
|
23133
23140
|
import { createServer as createServer2 } from "http";
|
|
23134
|
-
import * as
|
|
23141
|
+
import * as path51 from "path";
|
|
23135
23142
|
|
|
23136
23143
|
// src/chat/loop.ts
|
|
23137
23144
|
init_agent();
|
|
@@ -24306,7 +24313,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
|
|
|
24306
24313
|
// src/kody-cli.ts
|
|
24307
24314
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
24308
24315
|
import * as fs51 from "fs";
|
|
24309
|
-
import * as
|
|
24316
|
+
import * as path49 from "path";
|
|
24310
24317
|
|
|
24311
24318
|
// src/app-auth.ts
|
|
24312
24319
|
import { createSign } from "crypto";
|
|
@@ -25120,9 +25127,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
25120
25127
|
return void 0;
|
|
25121
25128
|
}
|
|
25122
25129
|
function detectPackageManager2(cwd) {
|
|
25123
|
-
if (fs51.existsSync(
|
|
25124
|
-
if (fs51.existsSync(
|
|
25125
|
-
if (fs51.existsSync(
|
|
25130
|
+
if (fs51.existsSync(path49.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
25131
|
+
if (fs51.existsSync(path49.join(cwd, "yarn.lock"))) return "yarn";
|
|
25132
|
+
if (fs51.existsSync(path49.join(cwd, "bun.lockb"))) return "bun";
|
|
25126
25133
|
return "npm";
|
|
25127
25134
|
}
|
|
25128
25135
|
function shouldChainScheduledWatch(match) {
|
|
@@ -25245,7 +25252,7 @@ async function runCi(argv) {
|
|
|
25245
25252
|
return 0;
|
|
25246
25253
|
}
|
|
25247
25254
|
const args = parseCiArgs(argv);
|
|
25248
|
-
const cwd = args.cwd ?
|
|
25255
|
+
const cwd = args.cwd ? path49.resolve(args.cwd) : process.cwd();
|
|
25249
25256
|
try {
|
|
25250
25257
|
const n = unpackAllSecrets();
|
|
25251
25258
|
if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
|
|
@@ -25717,7 +25724,7 @@ init_repoWorkspace();
|
|
|
25717
25724
|
// src/scripts/brainTurnLog.ts
|
|
25718
25725
|
init_runtimePaths();
|
|
25719
25726
|
import * as fs52 from "fs";
|
|
25720
|
-
import * as
|
|
25727
|
+
import * as path50 from "path";
|
|
25721
25728
|
import posixPath4 from "path/posix";
|
|
25722
25729
|
var live = /* @__PURE__ */ new Map();
|
|
25723
25730
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -25764,7 +25771,7 @@ function beginTurn(dir, chatId) {
|
|
|
25764
25771
|
};
|
|
25765
25772
|
live.set(chatId, state);
|
|
25766
25773
|
const p = brainEventsFilePath(dir, chatId);
|
|
25767
|
-
fs52.mkdirSync(
|
|
25774
|
+
fs52.mkdirSync(path50.dirname(p), { recursive: true });
|
|
25768
25775
|
return (event) => {
|
|
25769
25776
|
state.seq += 1;
|
|
25770
25777
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
@@ -26201,7 +26208,7 @@ function buildServer(opts) {
|
|
|
26201
26208
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
26202
26209
|
const createStore = opts.createStore ?? createSessionStore;
|
|
26203
26210
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
26204
|
-
const reposRoot = opts.reposRoot ??
|
|
26211
|
+
const reposRoot = opts.reposRoot ?? path51.join(path51.dirname(path51.resolve(opts.cwd)), "repos");
|
|
26205
26212
|
return createServer2(async (req, res) => {
|
|
26206
26213
|
if (!req.method || !req.url) {
|
|
26207
26214
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -26805,7 +26812,7 @@ async function loadConfigSafe() {
|
|
|
26805
26812
|
}
|
|
26806
26813
|
|
|
26807
26814
|
// src/chat-cli.ts
|
|
26808
|
-
import * as
|
|
26815
|
+
import * as path52 from "path";
|
|
26809
26816
|
|
|
26810
26817
|
// src/chat/inbox.ts
|
|
26811
26818
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
@@ -27086,7 +27093,7 @@ async function runChat(argv) {
|
|
|
27086
27093
|
${CHAT_HELP}`);
|
|
27087
27094
|
return 64;
|
|
27088
27095
|
}
|
|
27089
|
-
const cwd = args.cwd ?
|
|
27096
|
+
const cwd = args.cwd ? path52.resolve(args.cwd) : process.cwd();
|
|
27090
27097
|
const sessionId = args.sessionId;
|
|
27091
27098
|
const runRequest = readRunRequestFromEnv();
|
|
27092
27099
|
if (runRequest && "request" in runRequest) {
|
|
@@ -27276,8 +27283,8 @@ var FlyClient = class {
|
|
|
27276
27283
|
get fetch() {
|
|
27277
27284
|
return this.opts.fetchImpl ?? fetch;
|
|
27278
27285
|
}
|
|
27279
|
-
async call(
|
|
27280
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
27286
|
+
async call(path53, init = {}) {
|
|
27287
|
+
const res = await this.fetch(`${FLY_API_BASE}${path53}`, {
|
|
27281
27288
|
method: init.method ?? "GET",
|
|
27282
27289
|
headers: {
|
|
27283
27290
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -27288,7 +27295,7 @@ var FlyClient = class {
|
|
|
27288
27295
|
if (res.status === 404 && init.allow404) return null;
|
|
27289
27296
|
if (!res.ok) {
|
|
27290
27297
|
const text2 = await res.text().catch(() => "");
|
|
27291
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
27298
|
+
throw new Error(`Fly API ${res.status} on ${path53}: ${text2.slice(0, 200) || res.statusText}`);
|
|
27292
27299
|
}
|
|
27293
27300
|
if (res.status === 204) return null;
|
|
27294
27301
|
const raw = await res.text();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.451",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|