@kody-ade/kody-engine 0.4.119 → 0.4.121

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 CHANGED
@@ -880,7 +880,7 @@ var init_loadPriorArt = __esm({
880
880
  // package.json
881
881
  var package_default = {
882
882
  name: "@kody-ade/kody-engine",
883
- version: "0.4.119",
883
+ version: "0.4.121",
884
884
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
885
885
  license: "MIT",
886
886
  type: "module",
@@ -900,7 +900,7 @@ var package_default = {
900
900
  build: "tsup && node scripts/copy-assets.cjs",
901
901
  "check:modularity": "tsx scripts/check-script-modularity.ts",
902
902
  pretest: "pnpm check:modularity",
903
- test: "vitest run tests/unit tests/int --no-coverage",
903
+ test: "vitest run tests/unit tests/int --coverage",
904
904
  "test:e2e": "vitest run tests/e2e --no-coverage",
905
905
  "test:all": "vitest run tests --no-coverage",
906
906
  typecheck: "tsc --noEmit",
@@ -917,6 +917,7 @@ var package_default = {
917
917
  devDependencies: {
918
918
  "@biomejs/biome": "^2.4.12",
919
919
  "@types/node": "^22.5.4",
920
+ "@vitest/coverage-v8": "^4.1.4",
920
921
  tsup: "^8.5.1",
921
922
  tsx: "^4.21.0",
922
923
  typescript: "~5.7.0",
@@ -4727,6 +4728,13 @@ async function defaultRunJob(job) {
4727
4728
  REPO: job.repo,
4728
4729
  REF: branch,
4729
4730
  GITHUB_TOKEN: job.githubToken,
4731
+ // GITHUB_REPOSITORY + GH_TOKEN are normally injected by GitHub Actions.
4732
+ // The engine's interactive mode needs GITHUB_REPOSITORY to persist
4733
+ // chat.ready / events to .kody/events via the Contents API (the durable
4734
+ // signal the dashboard polls for readiness) — without it commitTurn bails
4735
+ // and the session never appears "ready". GH_TOKEN auths the `gh` CLI.
4736
+ GITHUB_REPOSITORY: job.repo,
4737
+ GH_TOKEN: job.githubToken,
4730
4738
  // Issue mode bakes ISSUE_NUMBER → `kody run --issue N`. Interactive mode
4731
4739
  // leaves it empty and sets SESSION_ID so the engine boots a chat session.
4732
4740
  ISSUE_NUMBER: interactive ? "" : String(job.issueNumber),
@@ -4986,6 +4994,19 @@ var PoolManager = class {
4986
4994
  total: this.free.length + this.booting + this.claimsInFlight
4987
4995
  };
4988
4996
  }
4997
+ /**
4998
+ * Resize the warm target at runtime (per-repo, sourced from the repo's vault
4999
+ * POOL_MIN). Raising it warms up immediately via refill; lowering it just
5000
+ * stops topping up — surplus machines drain as they're claimed/auto-destroyed,
5001
+ * never force-killed. No-op when unchanged or given a bad value.
5002
+ */
5003
+ setMin(min) {
5004
+ if (!Number.isInteger(min) || min < 0) return;
5005
+ if (min === this.deps.config.min) return;
5006
+ this.deps.config.min = min;
5007
+ this.log(`min set to ${min}`);
5008
+ void this.refill();
5009
+ }
4989
5010
  /**
4990
5011
  * Adopt existing pooled machines on owner (re)start: suspended ones become
4991
5012
  * free; anything else is left to finish/auto-destroy. Then refill to `min`.
@@ -5222,6 +5243,14 @@ async function readRepoSecrets(opts) {
5222
5243
  }
5223
5244
 
5224
5245
  // src/pool/registry.ts
5246
+ var POOL_MIN_VAULT_KEY = "POOL_MIN";
5247
+ var POOL_MIN_MAX = 10;
5248
+ function parsePoolMin(raw, dflt) {
5249
+ if (raw == null || raw.trim() === "") return dflt;
5250
+ const n = Number(raw);
5251
+ if (!Number.isInteger(n) || n < 0) return dflt;
5252
+ return Math.min(n, POOL_MIN_MAX);
5253
+ }
5225
5254
  var PoolRegistry = class {
5226
5255
  constructor(cfg) {
5227
5256
  this.cfg = cfg;
@@ -5234,10 +5263,21 @@ var PoolRegistry = class {
5234
5263
  repo,
5235
5264
  name: "FLY_API_TOKEN"
5236
5265
  }));
5266
+ this.resolvePoolMin = cfg.resolvePoolMin ?? (async (owner, repo) => parsePoolMin(
5267
+ await readRepoSecret({
5268
+ githubToken: cfg.githubToken,
5269
+ masterKey: cfg.masterKey,
5270
+ owner,
5271
+ repo,
5272
+ name: POOL_MIN_VAULT_KEY
5273
+ }),
5274
+ cfg.base.min
5275
+ ));
5237
5276
  }
5238
5277
  cfg;
5239
5278
  pools = /* @__PURE__ */ new Map();
5240
5279
  resolveFlyToken;
5280
+ resolvePoolMin;
5241
5281
  log;
5242
5282
  key(owner, repo) {
5243
5283
  return `${owner}/${repo}`.toLowerCase();
@@ -5258,10 +5298,16 @@ var PoolRegistry = class {
5258
5298
  this.log(`registry: ${repoTag} has no FLY_API_TOKEN \u2014 no pool`);
5259
5299
  return null;
5260
5300
  }
5301
+ let min = this.cfg.base.min;
5302
+ try {
5303
+ min = await this.resolvePoolMin(owner, repo);
5304
+ } catch (err) {
5305
+ this.log(`registry: pool-min read failed for ${repoTag}, using default ${min}: ${err instanceof Error ? err.message : String(err)}`);
5306
+ }
5261
5307
  const fly = new FlyClient({ token: flyToken, app: this.cfg.base.app });
5262
5308
  const pm = new PoolManager({
5263
5309
  fly,
5264
- config: { ...this.cfg.base, repoTag },
5310
+ config: { ...this.cfg.base, repoTag, min },
5265
5311
  log: (m) => this.log(`[${repoTag}] ${m}`)
5266
5312
  });
5267
5313
  this.pools.set(repoTag, pm);
@@ -5279,7 +5325,10 @@ var PoolRegistry = class {
5279
5325
  owner,
5280
5326
  repo
5281
5327
  });
5282
- allSecrets = Object.fromEntries(Object.entries(vault).filter(([k]) => k !== "FLY_API_TOKEN"));
5328
+ pm.setMin(parsePoolMin(vault[POOL_MIN_VAULT_KEY], this.cfg.base.min));
5329
+ allSecrets = Object.fromEntries(
5330
+ Object.entries(vault).filter(([k]) => k !== "FLY_API_TOKEN" && k !== POOL_MIN_VAULT_KEY)
5331
+ );
5283
5332
  } catch (err) {
5284
5333
  this.log(`[${this.key(owner, repo)}] vault secrets read failed: ${err instanceof Error ? err.message : String(err)}`);
5285
5334
  }
@@ -5303,9 +5352,17 @@ var PoolRegistry = class {
5303
5352
  status(owner, repo) {
5304
5353
  return this.pools.get(this.key(owner, repo))?.status() ?? null;
5305
5354
  }
5306
- /** Resync every active repo pool (periodic self-heal). */
5355
+ /** Resync every active repo pool (periodic self-heal). Also re-reads each
5356
+ * repo's POOL_MIN from its vault so a dashboard resize warms up/drains within
5357
+ * one tick — no owner restart needed. */
5307
5358
  async resyncAll() {
5308
5359
  for (const [repoTag, pm] of this.pools) {
5360
+ const [owner, repo] = repoTag.split("/");
5361
+ try {
5362
+ pm.setMin(await this.resolvePoolMin(owner, repo));
5363
+ } catch (err) {
5364
+ this.log(`[${repoTag}] pool-min refresh: ${err instanceof Error ? err.message : String(err)}`);
5365
+ }
5309
5366
  await pm.resync().catch((err) => this.log(`[${repoTag}] resync: ${err instanceof Error ? err.message : String(err)}`));
5310
5367
  }
5311
5368
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -404,6 +404,22 @@
404
404
  },
405
405
  "additionalProperties": false
406
406
  },
407
+ "access": {
408
+ "type": "object",
409
+ "description": "Who may trigger kody via an @kody comment. Gates on the GitHub comment.author_association already present on the issue_comment event (no API call, no read:org token).",
410
+ "properties": {
411
+ "allowedAssociations": {
412
+ "type": "array",
413
+ "items": {
414
+ "type": "string",
415
+ "enum": ["OWNER", "MEMBER", "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIME_CONTRIBUTOR", "FIRST_TIMER", "MANNEQUIN", "NONE"]
416
+ },
417
+ "description": "Allowlist of author_association values permitted to trigger kody. OMIT this key for the secure default — only the team (OWNER, MEMBER, COLLABORATOR) may trigger; public drive-by comments are silently ignored. A non-empty list overrides which associations are allowed. An explicit empty list ([]) DISABLES the gate (anyone may trigger). MEMBER applies only to org-owned repos; on a user-owned repo the owner is OWNER and invited people are COLLABORATOR.",
418
+ "default": ["OWNER", "MEMBER", "COLLABORATOR"]
419
+ }
420
+ },
421
+ "additionalProperties": false
422
+ },
407
423
  "qa": {
408
424
  "type": "object",
409
425
  "description": "qa-engineer defaults. Used by the resolveQaUrl preflight when no explicit --url is passed and no $PREVIEW_URL env var is set.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.119",
3
+ "version": "0.4.121",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,6 +12,23 @@
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
+ "build": "tsup && node scripts/copy-assets.cjs",
21
+ "check:modularity": "tsx scripts/check-script-modularity.ts",
22
+ "pretest": "pnpm check:modularity",
23
+ "test": "vitest run tests/unit tests/int --coverage",
24
+ "test:e2e": "vitest run tests/e2e --no-coverage",
25
+ "test:all": "vitest run tests --no-coverage",
26
+ "typecheck": "tsc --noEmit",
27
+ "lint": "biome check",
28
+ "lint:fix": "biome check --write",
29
+ "format": "biome format --write",
30
+ "prepublishOnly": "pnpm build"
31
+ },
15
32
  "dependencies": {
16
33
  "@actions/cache": "^6.0.0",
17
34
  "@anthropic-ai/claude-agent-sdk": "0.2.119",
@@ -20,6 +37,7 @@
20
37
  "devDependencies": {
21
38
  "@biomejs/biome": "^2.4.12",
22
39
  "@types/node": "^22.5.4",
40
+ "@vitest/coverage-v8": "^4.1.4",
23
41
  "tsup": "^8.5.1",
24
42
  "tsx": "^4.21.0",
25
43
  "typescript": "~5.7.0",
@@ -33,21 +51,5 @@
33
51
  "url": "git+https://github.com/aharonyaircohen/kody-engine.git"
34
52
  },
35
53
  "homepage": "https://github.com/aharonyaircohen/kody-engine",
36
- "bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
37
- "scripts": {
38
- "kody:run": "tsx bin/kody.ts",
39
- "serve": "tsx bin/kody.ts serve",
40
- "serve:vscode": "tsx bin/kody.ts serve vscode",
41
- "serve:claude": "tsx bin/kody.ts serve claude",
42
- "build": "tsup && node scripts/copy-assets.cjs",
43
- "check:modularity": "tsx scripts/check-script-modularity.ts",
44
- "pretest": "pnpm check:modularity",
45
- "test": "vitest run tests/unit tests/int --no-coverage",
46
- "test:e2e": "vitest run tests/e2e --no-coverage",
47
- "test:all": "vitest run tests --no-coverage",
48
- "typecheck": "tsc --noEmit",
49
- "lint": "biome check",
50
- "lint:fix": "biome check --write",
51
- "format": "biome format --write"
52
- }
53
- }
54
+ "bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
55
+ }
@@ -90,4 +90,4 @@ jobs:
90
90
  INIT_MESSAGE: ${{ inputs.message }}
91
91
  MODEL: ${{ inputs.model }}
92
92
  DASHBOARD_URL: ${{ inputs.dashboardUrl }}
93
- run: npx -y -p @kody-ade/kody-engine@0.4.119 kody-engine
93
+ run: npx -y -p @kody-ade/kody-engine@0.4.120 kody-engine