@kody-ade/kody-engine 0.4.596 → 0.4.597
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 +97 -22
- 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.597",
|
|
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",
|
|
@@ -4228,7 +4228,7 @@ async function runAgent(opts) {
|
|
|
4228
4228
|
}
|
|
4229
4229
|
try {
|
|
4230
4230
|
const queryOptions = {
|
|
4231
|
-
model: opts.litellmUrl ? litellmModelGroup(opts.model) : opts.model.model,
|
|
4231
|
+
model: opts.litellmUrl ? opts.litellmModelGroupOverride ?? litellmModelGroup(opts.model) : opts.model.model,
|
|
4232
4232
|
cwd: opts.cwd,
|
|
4233
4233
|
// Fresh array (never mutate the shared DEFAULT_ALLOWED_TOOLS const) so
|
|
4234
4234
|
// opt-in tools like fetch_repo can be appended below.
|
|
@@ -7850,6 +7850,43 @@ function generateLitellmConfigYaml(model) {
|
|
|
7850
7850
|
]);
|
|
7851
7851
|
return ["model_list:", ...modelEntries, "", "litellm_settings:", " drop_params: true", ""].join("\n");
|
|
7852
7852
|
}
|
|
7853
|
+
function modelEntry(modelName, model) {
|
|
7854
|
+
const apiKeyVar = model.apiKeyEnvVar ?? providerApiKeyEnvVar(model.provider);
|
|
7855
|
+
const litellmProvider = model.litellmProvider ?? model.provider;
|
|
7856
|
+
return [
|
|
7857
|
+
` - model_name: ${modelName}`,
|
|
7858
|
+
` litellm_params:`,
|
|
7859
|
+
` model: ${litellmProvider}/${model.model}`,
|
|
7860
|
+
` api_key: os.environ/${apiKeyVar}`,
|
|
7861
|
+
...model.baseURL ? [` api_base: ${model.baseURL}`] : []
|
|
7862
|
+
];
|
|
7863
|
+
}
|
|
7864
|
+
function generateAutomaticLitellmConfigYaml(models) {
|
|
7865
|
+
if (models.length < 2) throw new Error("Automatic LiteLLM requires at least two models");
|
|
7866
|
+
const groups = models.map((_, index) => `kody-automatic-${index}`);
|
|
7867
|
+
const entries = models.flatMap((model, index) => modelEntry(groups[index], model));
|
|
7868
|
+
for (const alias of CLAUDE_CODE_PROXY_MODEL_ALIASES) entries.push(...modelEntry(alias, models[0]));
|
|
7869
|
+
const fallbackSources = [groups[0], ...CLAUDE_CODE_PROXY_MODEL_ALIASES, ...groups.slice(1, -1)];
|
|
7870
|
+
const fallbacks = fallbackSources.map((source) => {
|
|
7871
|
+
const sourceIndex = source.startsWith("kody-automatic-") ? Number(source.slice("kody-automatic-".length)) : 0;
|
|
7872
|
+
return ` - ${source}: [${groups.slice(sourceIndex + 1).join(", ")}]`;
|
|
7873
|
+
});
|
|
7874
|
+
return [
|
|
7875
|
+
"model_list:",
|
|
7876
|
+
...entries,
|
|
7877
|
+
"",
|
|
7878
|
+
"litellm_settings:",
|
|
7879
|
+
" drop_params: true",
|
|
7880
|
+
"",
|
|
7881
|
+
"router_settings:",
|
|
7882
|
+
" num_retries: 0",
|
|
7883
|
+
" allowed_fails: 0",
|
|
7884
|
+
" disable_cooldowns: true",
|
|
7885
|
+
" fallbacks:",
|
|
7886
|
+
...fallbacks,
|
|
7887
|
+
""
|
|
7888
|
+
].join("\n");
|
|
7889
|
+
}
|
|
7853
7890
|
function litellmModelGroups(model) {
|
|
7854
7891
|
const primary = litellmModelGroup(model);
|
|
7855
7892
|
return Array.from(/* @__PURE__ */ new Set([primary, ...CLAUDE_CODE_PROXY_MODEL_ALIASES]));
|
|
@@ -7922,9 +7959,29 @@ function resolveLitellmCommand() {
|
|
|
7922
7959
|
}
|
|
7923
7960
|
async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL, runtimeEnvironment = {}) {
|
|
7924
7961
|
if (!needsLitellmProxy(model)) return null;
|
|
7962
|
+
return startLitellmProxy({
|
|
7963
|
+
projectDir,
|
|
7964
|
+
url,
|
|
7965
|
+
runtimeEnvironment,
|
|
7966
|
+
configYaml: generateLitellmConfigYaml(model),
|
|
7967
|
+
requiredModelGroups: litellmModelGroups(model)
|
|
7968
|
+
});
|
|
7969
|
+
}
|
|
7970
|
+
async function startAutomaticLitellm(models, projectDir, runtimeEnvironment = {}, url = LITELLM_DEFAULT_URL) {
|
|
7971
|
+
const handle = await startLitellmProxy({
|
|
7972
|
+
projectDir,
|
|
7973
|
+
url,
|
|
7974
|
+
runtimeEnvironment,
|
|
7975
|
+
configYaml: generateAutomaticLitellmConfigYaml(models),
|
|
7976
|
+
requiredModelGroups: [AUTOMATIC_LITELLM_MODEL_GROUP, ...CLAUDE_CODE_PROXY_MODEL_ALIASES]
|
|
7977
|
+
});
|
|
7978
|
+
return { ...handle, modelGroup: AUTOMATIC_LITELLM_MODEL_GROUP };
|
|
7979
|
+
}
|
|
7980
|
+
async function startLitellmProxy(input) {
|
|
7981
|
+
const { projectDir, runtimeEnvironment } = input;
|
|
7925
7982
|
const cmd = resolveLitellmCommand();
|
|
7926
|
-
let activeUrl = url.replace(/\/+$/, "");
|
|
7927
|
-
const modelGroups =
|
|
7983
|
+
let activeUrl = input.url.replace(/\/+$/, "");
|
|
7984
|
+
const modelGroups = input.requiredModelGroups;
|
|
7928
7985
|
const childEnv = stripBlockingEnv({
|
|
7929
7986
|
...process.env,
|
|
7930
7987
|
...readDotenvApiKeys(projectDir),
|
|
@@ -7936,7 +7993,7 @@ async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL
|
|
|
7936
7993
|
const portMatch = activeUrl.match(/:(\d+)/);
|
|
7937
7994
|
const port = portMatch ? portMatch[1] : "4000";
|
|
7938
7995
|
const configPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
|
|
7939
|
-
fs28.writeFileSync(configPath,
|
|
7996
|
+
fs28.writeFileSync(configPath, input.configYaml);
|
|
7940
7997
|
const args = ["--config", configPath, "--port", port];
|
|
7941
7998
|
const nextLogPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
|
|
7942
7999
|
const outFd = fs28.openSync(nextLogPath, "w");
|
|
@@ -8062,7 +8119,7 @@ function stripBlockingEnv(env) {
|
|
|
8062
8119
|
delete out.AI_BASE_URL;
|
|
8063
8120
|
return out;
|
|
8064
8121
|
}
|
|
8065
|
-
var LITELLM_PIP_PACKAGES, DEFAULT_LITELLM_STARTUP_TIMEOUT_SEC, LITELLM_HEALTH_POLL_INTERVAL_MS, CLAUDE_CODE_PROXY_MODEL_ALIASES;
|
|
8122
|
+
var LITELLM_PIP_PACKAGES, DEFAULT_LITELLM_STARTUP_TIMEOUT_SEC, LITELLM_HEALTH_POLL_INTERVAL_MS, CLAUDE_CODE_PROXY_MODEL_ALIASES, AUTOMATIC_LITELLM_MODEL_GROUP;
|
|
8066
8123
|
var init_litellm = __esm({
|
|
8067
8124
|
"src/litellm.ts"() {
|
|
8068
8125
|
"use strict";
|
|
@@ -8071,6 +8128,7 @@ var init_litellm = __esm({
|
|
|
8071
8128
|
DEFAULT_LITELLM_STARTUP_TIMEOUT_SEC = 150;
|
|
8072
8129
|
LITELLM_HEALTH_POLL_INTERVAL_MS = 2e3;
|
|
8073
8130
|
CLAUDE_CODE_PROXY_MODEL_ALIASES = ["claude-haiku-4-5-20251001", "haiku"];
|
|
8131
|
+
AUTOMATIC_LITELLM_MODEL_GROUP = "kody-automatic-0";
|
|
8074
8132
|
}
|
|
8075
8133
|
});
|
|
8076
8134
|
|
|
@@ -22454,6 +22512,19 @@ async function runImplementation(profileName, input) {
|
|
|
22454
22512
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
22455
22513
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
22456
22514
|
const agents = loadSubagents(profile);
|
|
22515
|
+
if (modelSpec === "automatic") {
|
|
22516
|
+
const automaticEnvironment = {};
|
|
22517
|
+
for (const candidate of modelCandidates) {
|
|
22518
|
+
const resolved2 = await resolveRuntimeModelEnvironment(candidate, ctx);
|
|
22519
|
+
Object.assign(automaticEnvironment, resolved2.environment);
|
|
22520
|
+
for (const warning of resolved2.warnings) process.stderr.write(`\u26A0 ${warning}
|
|
22521
|
+
`);
|
|
22522
|
+
}
|
|
22523
|
+
const lm = await startAutomaticLitellm(modelCandidates, input.cwd, automaticEnvironment);
|
|
22524
|
+
activeLiteLLM.add(lm);
|
|
22525
|
+
const result = await invokeModel(modelCandidates[0], lm, automaticEnvironment, lm.modelGroup);
|
|
22526
|
+
return result;
|
|
22527
|
+
}
|
|
22457
22528
|
let finalResult;
|
|
22458
22529
|
for (let candidateIndex = 0; candidateIndex < modelCandidates.length; candidateIndex++) {
|
|
22459
22530
|
const candidate = modelCandidates[candidateIndex];
|
|
@@ -22473,7 +22544,24 @@ async function runImplementation(profileName, input) {
|
|
|
22473
22544
|
}
|
|
22474
22545
|
ctx.data.jobModelProvider = candidate.provider;
|
|
22475
22546
|
ctx.data.jobModelName = candidate.model;
|
|
22476
|
-
const result = await
|
|
22547
|
+
const result = await invokeModel(candidate, lm, runtimeModelEnvironment);
|
|
22548
|
+
finalResult = result;
|
|
22549
|
+
const next = modelCandidates[candidateIndex + 1];
|
|
22550
|
+
if (!next || result.outcome !== "failed" || result.outcomeKind !== "rate_limit" || result.safeToReplay !== true) {
|
|
22551
|
+
return result;
|
|
22552
|
+
}
|
|
22553
|
+
process.stderr.write(
|
|
22554
|
+
`[kody agent] ${candidate.spec ?? candidate.model} is rate limited; continuing with ${next.spec ?? next.model}
|
|
22555
|
+
`
|
|
22556
|
+
);
|
|
22557
|
+
if (lm) {
|
|
22558
|
+
lm.kill();
|
|
22559
|
+
activeLiteLLM.delete(lm);
|
|
22560
|
+
}
|
|
22561
|
+
}
|
|
22562
|
+
return finalResult;
|
|
22563
|
+
async function invokeModel(candidate, lm, runtimeModelEnvironment, litellmModelGroupOverride) {
|
|
22564
|
+
return runAgent({
|
|
22477
22565
|
prompt,
|
|
22478
22566
|
model: candidate,
|
|
22479
22567
|
cwd: input.cwd,
|
|
@@ -22482,6 +22570,7 @@ async function runImplementation(profileName, input) {
|
|
|
22482
22570
|
...runtimeModelEnvironment
|
|
22483
22571
|
},
|
|
22484
22572
|
litellmUrl: lm?.url ?? null,
|
|
22573
|
+
litellmModelGroupOverride,
|
|
22485
22574
|
// On a connection drop mid-run, restart the (possibly crashed) proxy
|
|
22486
22575
|
// before the agent retries. No-op for direct-Anthropic runs (lm null).
|
|
22487
22576
|
ensureBackend: lm ? () => lm.ensureHealthy().then(() => void 0) : void 0,
|
|
@@ -22491,7 +22580,7 @@ async function runImplementation(profileName, input) {
|
|
|
22491
22580
|
verbose: input.verbose,
|
|
22492
22581
|
quiet: input.quiet,
|
|
22493
22582
|
abortController: input.abortController,
|
|
22494
|
-
stopOnRateLimit:
|
|
22583
|
+
stopOnRateLimit: false,
|
|
22495
22584
|
deadlineAtMs: input.deadlineAtMs,
|
|
22496
22585
|
ndjsonDir,
|
|
22497
22586
|
additionalDirectories: agentTaskArtifacts ? [agentTaskArtifacts.absDir] : void 0,
|
|
@@ -22541,21 +22630,7 @@ async function runImplementation(profileName, input) {
|
|
|
22541
22630
|
schema: ctx.data.capabilityOutputSchema
|
|
22542
22631
|
} : void 0
|
|
22543
22632
|
});
|
|
22544
|
-
finalResult = result;
|
|
22545
|
-
const next = modelCandidates[candidateIndex + 1];
|
|
22546
|
-
if (!next || result.outcome !== "failed" || result.outcomeKind !== "rate_limit" || result.safeToReplay !== true) {
|
|
22547
|
-
return result;
|
|
22548
|
-
}
|
|
22549
|
-
process.stderr.write(
|
|
22550
|
-
`[kody agent] ${candidate.spec ?? candidate.model} is rate limited; continuing with ${next.spec ?? next.model}
|
|
22551
|
-
`
|
|
22552
|
-
);
|
|
22553
|
-
if (lm) {
|
|
22554
|
-
lm.kill();
|
|
22555
|
-
activeLiteLLM.delete(lm);
|
|
22556
|
-
}
|
|
22557
22633
|
}
|
|
22558
|
-
return finalResult;
|
|
22559
22634
|
};
|
|
22560
22635
|
ctx.data.__invokeAgent = invokeAgent;
|
|
22561
22636
|
const cc = profile.claudeCode;
|
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.597",
|
|
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",
|