@kody-ade/kody-engine-lite 0.1.59 → 0.1.61

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/README.md CHANGED
@@ -138,23 +138,19 @@ Comment on any GitHub issue:
138
138
 
139
139
  ### Switch to a different model (optional)
140
140
 
141
- Add `litellm-config.yaml` to route all tiers through MiniMax (or any LLM):
142
-
143
- ```yaml
144
- # litellm-config.yaml
145
- model_list:
146
- - model_name: claude-haiku-4-5-20251001
147
- litellm_params:
148
- model: minimax/MiniMax-M2.7-highspeed
149
- api_key: os.environ/MINIMAX_API_KEY
150
- ```
141
+ Set the `provider` field in `kody.config.json` Kody auto-generates the LiteLLM config, starts the proxy, and routes all stages through your provider:
151
142
 
152
143
  ```json
153
- // kody.config.json — add litellmUrl
154
- { "agent": { "litellmUrl": "http://localhost:4000" } }
144
+ // kody.config.json — use MiniMax (or any LLM)
145
+ { "agent": { "provider": "minimax" } }
146
+ ```
147
+
148
+ Add the provider's API key to `.env`:
149
+ ```
150
+ MINIMAX_API_KEY=your-key-here
155
151
  ```
156
152
 
157
- Kody auto-starts the proxy and loads API keys from `.env`. [Full LiteLLM guide →](docs/LITELLM.md)
153
+ That's it. Kody auto-starts the LiteLLM proxy and loads API keys from `.env`. For advanced routing (different models per tier, custom config), add a `litellm-config.yaml`. [Full LiteLLM guide →](docs/LITELLM.md)
158
154
 
159
155
  ## Commands
160
156
 
@@ -167,16 +163,18 @@ Kody auto-starts the proxy and loads API keys from `.env`. [Full LiteLLM guide
167
163
  | `@kody fix` | Re-run from build stage. Write feedback in the comment body — it gets injected into the build prompt |
168
164
  | `@kody rerun` | Resume from the failed or paused stage |
169
165
  | `@kody rerun --from <stage>` | Resume from a specific stage |
166
+ | `@kody bootstrap` | Regenerate project memory and step files |
170
167
 
171
168
  ### CLI
172
169
 
173
170
  ```bash
171
+ kody-engine-lite init [--force] # Setup repo: workflow, config, memory, step files
172
+ kody-engine-lite bootstrap # Regenerate memory + step files (runs in GH Actions)
174
173
  kody-engine-lite run --issue-number 42 --local --cwd ./project
175
174
  kody-engine-lite run --task "Add retry utility" --local
176
175
  kody-engine-lite fix --issue-number 42 --feedback "Use middleware pattern"
177
176
  kody-engine-lite rerun --issue-number 42 --from verify
178
177
  kody-engine-lite status --task-id 42-260327-102254
179
- kody-engine-lite init [--force]
180
178
  ```
181
179
 
182
180
  ## Key Features
package/dist/bin/cli.js CHANGED
@@ -114,17 +114,15 @@ function createRunners(config) {
114
114
  if (config.agent.runners && Object.keys(config.agent.runners).length > 0) {
115
115
  const runners = {};
116
116
  for (const [name, runnerConfig] of Object.entries(config.agent.runners)) {
117
- const factory2 = RUNNER_FACTORIES[runnerConfig.type];
118
- if (factory2) {
119
- runners[name] = factory2();
117
+ const factory = RUNNER_FACTORIES[runnerConfig.type];
118
+ if (factory) {
119
+ runners[name] = factory();
120
120
  }
121
121
  }
122
122
  return runners;
123
123
  }
124
- const runnerType = config.agent.runner ?? "claude-code";
125
- const factory = RUNNER_FACTORIES[runnerType];
126
124
  const defaultName = config.agent.defaultRunner ?? "claude";
127
- return { [defaultName]: factory ? factory() : createClaudeCodeRunner() };
125
+ return { [defaultName]: createClaudeCodeRunner() };
128
126
  }
129
127
  var SIGKILL_GRACE_MS, STDERR_TAIL_CHARS, RUNNER_FACTORIES;
130
128
  var init_agent_runner = __esm({
@@ -253,12 +251,10 @@ var init_logger = __esm({
253
251
  import * as fs from "fs";
254
252
  import * as path from "path";
255
253
  function needsLitellmProxy(config) {
256
- if (config.agent.litellmUrl) return true;
257
- if (config.agent.provider && config.agent.provider !== "anthropic") return true;
258
- return false;
254
+ return !!(config.agent.provider && config.agent.provider !== "anthropic");
259
255
  }
260
- function getLitellmUrl(config) {
261
- return config.agent.litellmUrl ?? LITELLM_DEFAULT_URL;
256
+ function getLitellmUrl() {
257
+ return LITELLM_DEFAULT_URL;
262
258
  }
263
259
  function providerApiKeyEnvVar(provider) {
264
260
  return `${provider.toUpperCase()}_API_KEY`;
@@ -277,7 +273,6 @@ function getProjectConfig() {
277
273
  quality: { ...DEFAULT_CONFIG.quality, ...raw.quality },
278
274
  git: { ...DEFAULT_CONFIG.git, ...raw.git },
279
275
  github: { ...DEFAULT_CONFIG.github, ...raw.github },
280
- paths: { ...DEFAULT_CONFIG.paths, ...raw.paths },
281
276
  agent: { ...DEFAULT_CONFIG.agent, ...raw.agent },
282
277
  contextTiers: raw.contextTiers ? { ...DEFAULT_CONFIG.contextTiers, ...raw.contextTiers } : DEFAULT_CONFIG.contextTiers
283
278
  };
@@ -300,7 +295,6 @@ var init_config = __esm({
300
295
  typecheck: "pnpm -s tsc --noEmit",
301
296
  lint: "pnpm -s lint",
302
297
  lintFix: "pnpm lint:fix",
303
- format: "pnpm -s format:check",
304
298
  formatFix: "pnpm format:fix",
305
299
  testUnit: "pnpm -s test"
306
300
  },
@@ -311,12 +305,7 @@ var init_config = __esm({
311
305
  owner: "",
312
306
  repo: ""
313
307
  },
314
- paths: {
315
- taskDir: ".kody/tasks"
316
- },
317
308
  agent: {
318
- runner: "claude-code",
319
- defaultRunner: "claude",
320
309
  modelMap: { cheap: "haiku", mid: "sonnet", strong: "opus" }
321
310
  },
322
311
  contextTiers: {
@@ -1238,8 +1227,8 @@ ${prompt}` : prompt;
1238
1227
  }
1239
1228
  function resolveModel(modelTier, stageName) {
1240
1229
  const config = getProjectConfig();
1241
- if (config.agent.usePerStageRouting && stageName) {
1242
- return stageName;
1230
+ if (config.agent.provider && config.agent.provider !== "anthropic") {
1231
+ return DEFAULT_MODEL_MAP[modelTier] ?? "sonnet";
1243
1232
  }
1244
1233
  const mapped = config.agent.modelMap[modelTier];
1245
1234
  if (mapped) return mapped;
@@ -1369,7 +1358,7 @@ async function executeAgentStage(ctx, def) {
1369
1358
  logger.info(` runner=${runnerName} model=${model} timeout=${def.timeout / 1e3}s`);
1370
1359
  const extraEnv = {};
1371
1360
  if (needsLitellmProxy(config)) {
1372
- extraEnv.ANTHROPIC_BASE_URL = getLitellmUrl(config);
1361
+ extraEnv.ANTHROPIC_BASE_URL = getLitellmUrl();
1373
1362
  }
1374
1363
  const sessions = ctx.sessions ?? {};
1375
1364
  const sessionInfo = getSessionInfo(def.name, sessions);
@@ -1748,8 +1737,8 @@ async function executeVerifyWithAutofix(ctx, def) {
1748
1737
  const defaultRunner = getRunnerForStage(ctx, "taskify");
1749
1738
  const diagConfig = getProjectConfig();
1750
1739
  const diagEnv = {};
1751
- if (diagConfig.agent.litellmUrl) {
1752
- diagEnv.ANTHROPIC_BASE_URL = diagConfig.agent.litellmUrl;
1740
+ if (needsLitellmProxy(diagConfig)) {
1741
+ diagEnv.ANTHROPIC_BASE_URL = getLitellmUrl();
1753
1742
  }
1754
1743
  const diagnosis = await diagnoseFailure(
1755
1744
  "verify",
@@ -2534,8 +2523,8 @@ ${previousText}
2534
2523
  const model = resolveModel("cheap");
2535
2524
  const config = getProjectConfig();
2536
2525
  const extraEnv = {};
2537
- if (config.agent.litellmUrl) {
2538
- extraEnv.ANTHROPIC_BASE_URL = config.agent.litellmUrl;
2526
+ if (needsLitellmProxy(config)) {
2527
+ extraEnv.ANTHROPIC_BASE_URL = getLitellmUrl();
2539
2528
  }
2540
2529
  const result = await runner.run("retrospective", prompt, model, 3e4, "", {
2541
2530
  cwd: ctx.projectDir,
@@ -3271,7 +3260,7 @@ import * as fs21 from "fs";
3271
3260
  import * as path20 from "path";
3272
3261
  async function ensureLitellmProxy(config, projectDir) {
3273
3262
  if (!needsLitellmProxy(config)) return null;
3274
- const litellmUrl = getLitellmUrl(config);
3263
+ const litellmUrl = getLitellmUrl();
3275
3264
  const proxyRunning = await checkLitellmHealth(litellmUrl);
3276
3265
  let litellmProcess = null;
3277
3266
  if (!proxyRunning) {
@@ -3767,16 +3756,13 @@ function buildConfig(cwd, basic) {
3767
3756
  typecheck: find("typecheck", "type-check") || (pkg.devDependencies?.typescript ? `${basic.pm} tsc --noEmit` : ""),
3768
3757
  lint: find("lint"),
3769
3758
  lintFix: find("lint:fix", "lint-fix"),
3770
- format: find("format:check"),
3771
3759
  formatFix: find("format", "format:fix"),
3772
3760
  testUnit: find("test:unit", "test", "test:ci")
3773
3761
  },
3774
3762
  git: { defaultBranch: basic.defaultBranch },
3775
3763
  github: { owner: basic.owner, repo: basic.repo },
3776
- paths: { taskDir: ".kody/tasks" },
3777
3764
  agent: {
3778
- runner: "claude-code",
3779
- defaultRunner: "claude",
3765
+ provider: "anthropic",
3780
3766
  modelMap: { cheap: "haiku", mid: "sonnet", strong: "opus" }
3781
3767
  }
3782
3768
  };
@@ -3855,55 +3841,8 @@ function initCommand(opts) {
3855
3841
  console.log(` \u2717 ${c.name} \u2014 ${c.fix}`);
3856
3842
  }
3857
3843
  }
3858
- const labels = [
3859
- { name: "kody:planning", color: "c5def5", description: "Kody is analyzing and planning" },
3860
- { name: "kody:building", color: "0e8a16", description: "Kody is building code" },
3861
- { name: "kody:review", color: "fbca04", description: "Kody is reviewing code" },
3862
- { name: "kody:done", color: "0e8a16", description: "Kody completed successfully" },
3863
- { name: "kody:failed", color: "d93f0b", description: "Kody pipeline failed" },
3864
- { name: "kody:waiting", color: "fef2c0", description: "Kody is waiting for answers" },
3865
- { name: "kody:low", color: "bfdadc", description: "Low complexity \u2014 skip plan/review" },
3866
- { name: "kody:medium", color: "c5def5", description: "Medium complexity \u2014 skip review-fix" },
3867
- { name: "kody:high", color: "d4c5f9", description: "High complexity \u2014 full pipeline" },
3868
- { name: "kody:feature", color: "0e8a16", description: "New feature" },
3869
- { name: "kody:bugfix", color: "d93f0b", description: "Bug fix" },
3870
- { name: "kody:refactor", color: "fbca04", description: "Code refactoring" },
3871
- { name: "kody:docs", color: "0075ca", description: "Documentation" },
3872
- { name: "kody:chore", color: "e4e669", description: "Maintenance task" }
3873
- ];
3874
3844
  console.log("\n\u2500\u2500 Labels \u2500\u2500");
3875
- for (const label of labels) {
3876
- try {
3877
- execFileSync11("gh", [
3878
- "label",
3879
- "create",
3880
- label.name,
3881
- "--repo",
3882
- repoSlug,
3883
- "--color",
3884
- label.color,
3885
- "--description",
3886
- label.description,
3887
- "--force"
3888
- ], {
3889
- encoding: "utf-8",
3890
- timeout: 1e4,
3891
- stdio: ["pipe", "pipe", "pipe"]
3892
- });
3893
- console.log(` \u2713 ${label.name}`);
3894
- } catch {
3895
- try {
3896
- execFileSync11("gh", ["label", "list", "--repo", repoSlug, "--search", label.name], {
3897
- encoding: "utf-8",
3898
- timeout: 1e4,
3899
- stdio: ["pipe", "pipe", "pipe"]
3900
- });
3901
- console.log(` \u25CB ${label.name} (exists)`);
3902
- } catch {
3903
- console.log(` \u2717 ${label.name} \u2014 failed to create`);
3904
- }
3905
- }
3906
- }
3845
+ console.log(" \u25CB Labels will be created automatically during bootstrap");
3907
3846
  }
3908
3847
  console.log("\n\u2500\u2500 Config \u2500\u2500");
3909
3848
  if (fs22.existsSync(configDest)) {
@@ -4292,6 +4231,76 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4292
4231
  }
4293
4232
  }
4294
4233
  console.log(` \u2713 Generated ${stepCount} step files in .kody/steps/`);
4234
+ console.log("\n\u2500\u2500 Labels \u2500\u2500");
4235
+ try {
4236
+ let repoSlug = "";
4237
+ try {
4238
+ const configPath = path21.join(cwd, "kody.config.json");
4239
+ if (fs22.existsSync(configPath)) {
4240
+ const config = JSON.parse(fs22.readFileSync(configPath, "utf-8"));
4241
+ if (config.github?.owner && config.github?.repo) {
4242
+ repoSlug = `${config.github.owner}/${config.github.repo}`;
4243
+ }
4244
+ }
4245
+ } catch {
4246
+ }
4247
+ if (repoSlug) {
4248
+ const labels = [
4249
+ { name: "kody:planning", color: "c5def5", description: "Kody is analyzing and planning" },
4250
+ { name: "kody:building", color: "0e8a16", description: "Kody is building code" },
4251
+ { name: "kody:review", color: "fbca04", description: "Kody is reviewing code" },
4252
+ { name: "kody:done", color: "0e8a16", description: "Kody completed successfully" },
4253
+ { name: "kody:failed", color: "d93f0b", description: "Kody pipeline failed" },
4254
+ { name: "kody:waiting", color: "fef2c0", description: "Kody is waiting for answers" },
4255
+ { name: "kody:low", color: "bfdadc", description: "Low complexity \u2014 skip plan/review" },
4256
+ { name: "kody:medium", color: "c5def5", description: "Medium complexity \u2014 skip review-fix" },
4257
+ { name: "kody:high", color: "d4c5f9", description: "High complexity \u2014 full pipeline" },
4258
+ { name: "kody:feature", color: "0e8a16", description: "New feature" },
4259
+ { name: "kody:bugfix", color: "d93f0b", description: "Bug fix" },
4260
+ { name: "kody:refactor", color: "fbca04", description: "Code refactoring" },
4261
+ { name: "kody:docs", color: "0075ca", description: "Documentation" },
4262
+ { name: "kody:chore", color: "e4e669", description: "Maintenance task" }
4263
+ ];
4264
+ for (const label of labels) {
4265
+ try {
4266
+ execFileSync11("gh", [
4267
+ "label",
4268
+ "create",
4269
+ label.name,
4270
+ "--repo",
4271
+ repoSlug,
4272
+ "--color",
4273
+ label.color,
4274
+ "--description",
4275
+ label.description,
4276
+ "--force"
4277
+ ], {
4278
+ cwd,
4279
+ encoding: "utf-8",
4280
+ timeout: 1e4,
4281
+ stdio: ["pipe", "pipe", "pipe"]
4282
+ });
4283
+ console.log(` \u2713 ${label.name}`);
4284
+ } catch {
4285
+ try {
4286
+ execFileSync11("gh", ["label", "list", "--repo", repoSlug, "--search", label.name], {
4287
+ cwd,
4288
+ encoding: "utf-8",
4289
+ timeout: 1e4,
4290
+ stdio: ["pipe", "pipe", "pipe"]
4291
+ });
4292
+ console.log(` \u25CB ${label.name} (exists)`);
4293
+ } catch {
4294
+ console.log(` \u2717 ${label.name} \u2014 failed to create`);
4295
+ }
4296
+ }
4297
+ }
4298
+ } else {
4299
+ console.log(" \u25CB Skipped \u2014 could not determine repo from kody.config.json");
4300
+ }
4301
+ } catch {
4302
+ console.log(" \u25CB Label creation skipped");
4303
+ }
4295
4304
  console.log("\n\u2500\u2500 Git \u2500\u2500");
4296
4305
  const filesToCommit = [
4297
4306
  ".kody/memory/architecture.md",
@@ -23,11 +23,6 @@
23
23
  "description": "Auto-fix lint command, run when verify fails (e.g., 'pnpm lint:fix')",
24
24
  "default": ""
25
25
  },
26
- "format": {
27
- "type": "string",
28
- "description": "Format check command (e.g., 'pnpm format:check'). Empty to skip.",
29
- "default": ""
30
- },
31
26
  "formatFix": {
32
27
  "type": "string",
33
28
  "description": "Auto-fix format command, run when verify fails (e.g., 'pnpm format')",
@@ -49,14 +44,6 @@
49
44
  "type": "string",
50
45
  "description": "Default branch for PR base and branch syncing (e.g., 'main', 'dev')",
51
46
  "default": "dev"
52
- },
53
- "userEmail": {
54
- "type": "string",
55
- "description": "Git user email for CI commits (optional, defaults to github-actions bot)"
56
- },
57
- "userName": {
58
- "type": "string",
59
- "description": "Git user name for CI commits (optional, defaults to github-actions bot)"
60
47
  }
61
48
  },
62
49
  "additionalProperties": false
@@ -76,50 +63,27 @@
76
63
  },
77
64
  "additionalProperties": false
78
65
  },
79
- "paths": {
80
- "type": "object",
81
- "description": "File path configuration",
82
- "properties": {
83
- "taskDir": {
84
- "type": "string",
85
- "description": "Directory for pipeline artifacts and state (committed to branch)",
86
- "default": ".kody/tasks"
87
- }
88
- },
89
- "additionalProperties": false
90
- },
91
66
  "agent": {
92
67
  "type": "object",
93
68
  "description": "Agent execution configuration",
94
69
  "properties": {
95
- "runner": {
96
- "type": "string",
97
- "description": "Agent runner type",
98
- "enum": ["claude-code"],
99
- "default": "claude-code"
100
- },
101
- "defaultRunner": {
102
- "type": "string",
103
- "description": "Name of the default runner to use",
104
- "default": "claude"
105
- },
106
70
  "modelMap": {
107
71
  "type": "object",
108
- "description": "Maps model tiers to actual model names. Use LiteLLM aliases when litellmUrl is set.",
72
+ "description": "Maps model tiers to actual model names. When provider is set, values should be the provider's model names.",
109
73
  "properties": {
110
74
  "cheap": {
111
75
  "type": "string",
112
- "description": "Fast/cheap model for taskify stage (e.g., 'haiku' or LiteLLM alias)",
76
+ "description": "Fast/cheap model for taskify stage (e.g., 'haiku' or provider model name)",
113
77
  "default": "haiku"
114
78
  },
115
79
  "mid": {
116
80
  "type": "string",
117
- "description": "Mid-tier model for build, review-fix, autofix (e.g., 'sonnet' or LiteLLM alias)",
81
+ "description": "Mid-tier model for build, review-fix, autofix (e.g., 'sonnet' or provider model name)",
118
82
  "default": "sonnet"
119
83
  },
120
84
  "strong": {
121
85
  "type": "string",
122
- "description": "Strongest model for plan, review — deep reasoning (e.g., 'opus' or LiteLLM alias)",
86
+ "description": "Strongest model for plan, review — deep reasoning (e.g., 'opus' or provider model name)",
123
87
  "default": "opus"
124
88
  }
125
89
  },
@@ -130,15 +94,10 @@
130
94
  "description": "LLM provider name. When set (and not 'anthropic'), engine auto-starts LiteLLM proxy and routes model calls to this provider. modelMap values should be the provider's model names.",
131
95
  "examples": ["anthropic", "minimax", "openai", "google"]
132
96
  },
133
- "litellmUrl": {
97
+ "defaultRunner": {
134
98
  "type": "string",
135
- "description": "(Deprecated) Use 'provider' instead. LiteLLM proxy URL for manual setup.",
136
- "examples": ["http://localhost:4000"]
137
- },
138
- "usePerStageRouting": {
139
- "type": "boolean",
140
- "description": "When true, uses stage name as the LiteLLM model alias instead of modelMap tier",
141
- "default": false
99
+ "description": "Name of the default runner when multiple runners are configured (advanced)",
100
+ "default": "claude"
142
101
  },
143
102
  "runners": {
144
103
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "description": "Autonomous SDLC pipeline: Kody orchestration + Claude Code + LiteLLM",
5
5
  "license": "MIT",
6
6
  "type": "module",