@kody-ade/kody-engine 0.4.595 → 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 -23
- 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",
|
|
@@ -4180,7 +4180,6 @@ async function runAgent(opts) {
|
|
|
4180
4180
|
env.ANTHROPIC_BASE_URL = opts.litellmUrl;
|
|
4181
4181
|
env.ANTHROPIC_API_KEY = getAnthropicApiKeyOrDummy();
|
|
4182
4182
|
}
|
|
4183
|
-
if (opts.stopOnRateLimit) env.CLAUDE_CODE_MAX_RETRIES = "0";
|
|
4184
4183
|
const startedAt = Date.now();
|
|
4185
4184
|
const turnTimeoutMs = resolveTurnTimeoutMs(opts);
|
|
4186
4185
|
const completionGuard = typeof opts.deadlineAtMs === "number" ? createCompletionToolGuard(
|
|
@@ -4229,7 +4228,7 @@ async function runAgent(opts) {
|
|
|
4229
4228
|
}
|
|
4230
4229
|
try {
|
|
4231
4230
|
const queryOptions = {
|
|
4232
|
-
model: opts.litellmUrl ? litellmModelGroup(opts.model) : opts.model.model,
|
|
4231
|
+
model: opts.litellmUrl ? opts.litellmModelGroupOverride ?? litellmModelGroup(opts.model) : opts.model.model,
|
|
4233
4232
|
cwd: opts.cwd,
|
|
4234
4233
|
// Fresh array (never mutate the shared DEFAULT_ALLOWED_TOOLS const) so
|
|
4235
4234
|
// opt-in tools like fetch_repo can be appended below.
|
|
@@ -7851,6 +7850,43 @@ function generateLitellmConfigYaml(model) {
|
|
|
7851
7850
|
]);
|
|
7852
7851
|
return ["model_list:", ...modelEntries, "", "litellm_settings:", " drop_params: true", ""].join("\n");
|
|
7853
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
|
+
}
|
|
7854
7890
|
function litellmModelGroups(model) {
|
|
7855
7891
|
const primary = litellmModelGroup(model);
|
|
7856
7892
|
return Array.from(/* @__PURE__ */ new Set([primary, ...CLAUDE_CODE_PROXY_MODEL_ALIASES]));
|
|
@@ -7923,9 +7959,29 @@ function resolveLitellmCommand() {
|
|
|
7923
7959
|
}
|
|
7924
7960
|
async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL, runtimeEnvironment = {}) {
|
|
7925
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;
|
|
7926
7982
|
const cmd = resolveLitellmCommand();
|
|
7927
|
-
let activeUrl = url.replace(/\/+$/, "");
|
|
7928
|
-
const modelGroups =
|
|
7983
|
+
let activeUrl = input.url.replace(/\/+$/, "");
|
|
7984
|
+
const modelGroups = input.requiredModelGroups;
|
|
7929
7985
|
const childEnv = stripBlockingEnv({
|
|
7930
7986
|
...process.env,
|
|
7931
7987
|
...readDotenvApiKeys(projectDir),
|
|
@@ -7937,7 +7993,7 @@ async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL
|
|
|
7937
7993
|
const portMatch = activeUrl.match(/:(\d+)/);
|
|
7938
7994
|
const port = portMatch ? portMatch[1] : "4000";
|
|
7939
7995
|
const configPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
|
|
7940
|
-
fs28.writeFileSync(configPath,
|
|
7996
|
+
fs28.writeFileSync(configPath, input.configYaml);
|
|
7941
7997
|
const args = ["--config", configPath, "--port", port];
|
|
7942
7998
|
const nextLogPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
|
|
7943
7999
|
const outFd = fs28.openSync(nextLogPath, "w");
|
|
@@ -8063,7 +8119,7 @@ function stripBlockingEnv(env) {
|
|
|
8063
8119
|
delete out.AI_BASE_URL;
|
|
8064
8120
|
return out;
|
|
8065
8121
|
}
|
|
8066
|
-
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;
|
|
8067
8123
|
var init_litellm = __esm({
|
|
8068
8124
|
"src/litellm.ts"() {
|
|
8069
8125
|
"use strict";
|
|
@@ -8072,6 +8128,7 @@ var init_litellm = __esm({
|
|
|
8072
8128
|
DEFAULT_LITELLM_STARTUP_TIMEOUT_SEC = 150;
|
|
8073
8129
|
LITELLM_HEALTH_POLL_INTERVAL_MS = 2e3;
|
|
8074
8130
|
CLAUDE_CODE_PROXY_MODEL_ALIASES = ["claude-haiku-4-5-20251001", "haiku"];
|
|
8131
|
+
AUTOMATIC_LITELLM_MODEL_GROUP = "kody-automatic-0";
|
|
8075
8132
|
}
|
|
8076
8133
|
});
|
|
8077
8134
|
|
|
@@ -22455,6 +22512,19 @@ async function runImplementation(profileName, input) {
|
|
|
22455
22512
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
22456
22513
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
22457
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
|
+
}
|
|
22458
22528
|
let finalResult;
|
|
22459
22529
|
for (let candidateIndex = 0; candidateIndex < modelCandidates.length; candidateIndex++) {
|
|
22460
22530
|
const candidate = modelCandidates[candidateIndex];
|
|
@@ -22474,7 +22544,24 @@ async function runImplementation(profileName, input) {
|
|
|
22474
22544
|
}
|
|
22475
22545
|
ctx.data.jobModelProvider = candidate.provider;
|
|
22476
22546
|
ctx.data.jobModelName = candidate.model;
|
|
22477
|
-
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({
|
|
22478
22565
|
prompt,
|
|
22479
22566
|
model: candidate,
|
|
22480
22567
|
cwd: input.cwd,
|
|
@@ -22483,6 +22570,7 @@ async function runImplementation(profileName, input) {
|
|
|
22483
22570
|
...runtimeModelEnvironment
|
|
22484
22571
|
},
|
|
22485
22572
|
litellmUrl: lm?.url ?? null,
|
|
22573
|
+
litellmModelGroupOverride,
|
|
22486
22574
|
// On a connection drop mid-run, restart the (possibly crashed) proxy
|
|
22487
22575
|
// before the agent retries. No-op for direct-Anthropic runs (lm null).
|
|
22488
22576
|
ensureBackend: lm ? () => lm.ensureHealthy().then(() => void 0) : void 0,
|
|
@@ -22492,7 +22580,7 @@ async function runImplementation(profileName, input) {
|
|
|
22492
22580
|
verbose: input.verbose,
|
|
22493
22581
|
quiet: input.quiet,
|
|
22494
22582
|
abortController: input.abortController,
|
|
22495
|
-
stopOnRateLimit:
|
|
22583
|
+
stopOnRateLimit: false,
|
|
22496
22584
|
deadlineAtMs: input.deadlineAtMs,
|
|
22497
22585
|
ndjsonDir,
|
|
22498
22586
|
additionalDirectories: agentTaskArtifacts ? [agentTaskArtifacts.absDir] : void 0,
|
|
@@ -22542,21 +22630,7 @@ async function runImplementation(profileName, input) {
|
|
|
22542
22630
|
schema: ctx.data.capabilityOutputSchema
|
|
22543
22631
|
} : void 0
|
|
22544
22632
|
});
|
|
22545
|
-
finalResult = result;
|
|
22546
|
-
const next = modelCandidates[candidateIndex + 1];
|
|
22547
|
-
if (!next || result.outcome !== "failed" || result.outcomeKind !== "rate_limit" || result.safeToReplay !== true) {
|
|
22548
|
-
return result;
|
|
22549
|
-
}
|
|
22550
|
-
process.stderr.write(
|
|
22551
|
-
`[kody agent] ${candidate.spec ?? candidate.model} is rate limited; continuing with ${next.spec ?? next.model}
|
|
22552
|
-
`
|
|
22553
|
-
);
|
|
22554
|
-
if (lm) {
|
|
22555
|
-
lm.kill();
|
|
22556
|
-
activeLiteLLM.delete(lm);
|
|
22557
|
-
}
|
|
22558
22633
|
}
|
|
22559
|
-
return finalResult;
|
|
22560
22634
|
};
|
|
22561
22635
|
ctx.data.__invokeAgent = invokeAgent;
|
|
22562
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",
|