@kody-ade/kody-engine 0.4.216 → 0.4.218
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 +65 -11
- 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.218",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -17831,6 +17831,7 @@ var PoolManager = class {
|
|
|
17831
17831
|
}
|
|
17832
17832
|
deps;
|
|
17833
17833
|
free = [];
|
|
17834
|
+
claimed = /* @__PURE__ */ new Set();
|
|
17834
17835
|
booting = 0;
|
|
17835
17836
|
claimsInFlight = 0;
|
|
17836
17837
|
refilling = false;
|
|
@@ -17847,16 +17848,15 @@ var PoolManager = class {
|
|
|
17847
17848
|
}
|
|
17848
17849
|
/**
|
|
17849
17850
|
* Resize the warm target at runtime (per-repo, sourced from the repo's vault
|
|
17850
|
-
* POOL_MIN). Raising it warms
|
|
17851
|
-
*
|
|
17852
|
-
* never force-killed. No-op when unchanged or given a bad value.
|
|
17851
|
+
* POOL_MIN). Raising it warms immediately; lowering it prunes idle surplus
|
|
17852
|
+
* warm machines. No-op when unchanged or given a bad value.
|
|
17853
17853
|
*/
|
|
17854
17854
|
setMin(min) {
|
|
17855
17855
|
if (!Number.isInteger(min) || min < 0) return;
|
|
17856
17856
|
if (min === this.deps.config.min) return;
|
|
17857
17857
|
this.deps.config.min = min;
|
|
17858
17858
|
this.log(`min set to ${min}`);
|
|
17859
|
-
void this.
|
|
17859
|
+
void this.rebalance("setMin");
|
|
17860
17860
|
}
|
|
17861
17861
|
/**
|
|
17862
17862
|
* Adopt existing pooled machines on owner (re)start: suspended ones become
|
|
@@ -17865,12 +17865,17 @@ var PoolManager = class {
|
|
|
17865
17865
|
async reconcile() {
|
|
17866
17866
|
const machines = await this.deps.fly.listPooled(this.deps.config.repoTag);
|
|
17867
17867
|
this.free = [];
|
|
17868
|
+
const surplus = [];
|
|
17868
17869
|
for (const m of machines) {
|
|
17869
|
-
if ((m
|
|
17870
|
+
if (!isSuspendedWithIp(m)) continue;
|
|
17871
|
+
if (this.warmCapacity() < this.deps.config.min) {
|
|
17870
17872
|
this.free.push({ id: m.id, privateIp: m.private_ip });
|
|
17873
|
+
} else {
|
|
17874
|
+
surplus.push(m.id);
|
|
17871
17875
|
}
|
|
17872
17876
|
}
|
|
17873
|
-
|
|
17877
|
+
const destroyed = await this.destroySurplus(surplus);
|
|
17878
|
+
this.log(`reconcile: adopted ${this.free.length} suspended machine(s), destroyed ${destroyed} surplus`);
|
|
17874
17879
|
await this.refill();
|
|
17875
17880
|
}
|
|
17876
17881
|
/**
|
|
@@ -17887,6 +17892,7 @@ var PoolManager = class {
|
|
|
17887
17892
|
const machine = this.free.shift();
|
|
17888
17893
|
if (!machine) break;
|
|
17889
17894
|
this.claimsInFlight++;
|
|
17895
|
+
this.claimed.add(machine.id);
|
|
17890
17896
|
try {
|
|
17891
17897
|
await this.deps.fly.start(machine.id);
|
|
17892
17898
|
const healthy = await this.deps.fly.waitHealthy(this.baseUrl(machine), {
|
|
@@ -17913,6 +17919,7 @@ var PoolManager = class {
|
|
|
17913
17919
|
await this.safeDestroy(machine.id);
|
|
17914
17920
|
lastReason = errMsg2(err);
|
|
17915
17921
|
} finally {
|
|
17922
|
+
this.claimed.delete(machine.id);
|
|
17916
17923
|
this.claimsInFlight--;
|
|
17917
17924
|
}
|
|
17918
17925
|
}
|
|
@@ -17940,16 +17947,24 @@ var PoolManager = class {
|
|
|
17940
17947
|
const before = this.free.length;
|
|
17941
17948
|
this.free = this.free.filter((f) => liveIds.has(f.id));
|
|
17942
17949
|
const pruned = before - this.free.length;
|
|
17943
|
-
const
|
|
17950
|
+
const destroyedTracked = await this.trimFreeSurplus("resync");
|
|
17951
|
+
const tracked = /* @__PURE__ */ new Set([...this.free.map((f) => f.id), ...this.claimed]);
|
|
17944
17952
|
let adopted = 0;
|
|
17953
|
+
const surplus = [];
|
|
17945
17954
|
for (const m of machines) {
|
|
17946
|
-
if ((m
|
|
17955
|
+
if (!isSuspendedWithIp(m) || tracked.has(m.id)) continue;
|
|
17956
|
+
if (this.warmCapacity() < this.deps.config.min) {
|
|
17947
17957
|
this.free.push({ id: m.id, privateIp: m.private_ip });
|
|
17958
|
+
tracked.add(m.id);
|
|
17948
17959
|
adopted++;
|
|
17960
|
+
} else if (this.booting === 0) {
|
|
17961
|
+
surplus.push(m.id);
|
|
17949
17962
|
}
|
|
17950
17963
|
}
|
|
17951
|
-
|
|
17952
|
-
|
|
17964
|
+
const destroyedSurplus = await this.destroySurplus(surplus);
|
|
17965
|
+
const destroyed = destroyedTracked + destroyedSurplus;
|
|
17966
|
+
if (pruned > 0 || adopted > 0 || destroyed > 0) {
|
|
17967
|
+
this.log(`resync: pruned ${pruned} stale, adopted ${adopted}, destroyed ${destroyed} surplus (free=${this.free.length})`);
|
|
17953
17968
|
}
|
|
17954
17969
|
await this.refill();
|
|
17955
17970
|
}
|
|
@@ -18004,11 +18019,37 @@ var PoolManager = class {
|
|
|
18004
18019
|
baseUrl(m) {
|
|
18005
18020
|
return `http://[${m.privateIp}]:${this.deps.config.port}`;
|
|
18006
18021
|
}
|
|
18022
|
+
warmCapacity() {
|
|
18023
|
+
return this.free.length + this.booting;
|
|
18024
|
+
}
|
|
18025
|
+
async rebalance(reason) {
|
|
18026
|
+
await this.trimFreeSurplus(reason);
|
|
18027
|
+
await this.refill();
|
|
18028
|
+
}
|
|
18029
|
+
async trimFreeSurplus(reason) {
|
|
18030
|
+
const surplus = [];
|
|
18031
|
+
while (this.free.length > this.deps.config.min) {
|
|
18032
|
+
const machine = this.free.pop();
|
|
18033
|
+
if (machine) surplus.push(machine.id);
|
|
18034
|
+
}
|
|
18035
|
+
const destroyed = await this.destroySurplus(surplus);
|
|
18036
|
+
if (destroyed > 0) this.log(`${reason}: destroyed ${destroyed} surplus free machine(s)`);
|
|
18037
|
+
return destroyed;
|
|
18038
|
+
}
|
|
18039
|
+
async destroySurplus(ids) {
|
|
18040
|
+
let destroyed = 0;
|
|
18041
|
+
for (const id of ids) {
|
|
18042
|
+
if (await this.safeDestroy(id)) destroyed++;
|
|
18043
|
+
}
|
|
18044
|
+
return destroyed;
|
|
18045
|
+
}
|
|
18007
18046
|
async safeDestroy(id) {
|
|
18008
18047
|
try {
|
|
18009
18048
|
await this.deps.fly.destroy(id);
|
|
18049
|
+
return true;
|
|
18010
18050
|
} catch (err) {
|
|
18011
18051
|
this.log(`destroy ${id} failed: ${errMsg2(err)}`);
|
|
18052
|
+
return false;
|
|
18012
18053
|
}
|
|
18013
18054
|
}
|
|
18014
18055
|
};
|
|
@@ -18027,6 +18068,9 @@ async function defaultPostRun(m, job, cfg) {
|
|
|
18027
18068
|
function errMsg2(err) {
|
|
18028
18069
|
return err instanceof Error ? err.message : String(err);
|
|
18029
18070
|
}
|
|
18071
|
+
function isSuspendedWithIp(m) {
|
|
18072
|
+
return (m.state === "suspended" || m.state === "suspending") && !!m.private_ip;
|
|
18073
|
+
}
|
|
18030
18074
|
|
|
18031
18075
|
// src/pool/vault.ts
|
|
18032
18076
|
import { createDecipheriv as createDecipheriv2 } from "crypto";
|
|
@@ -18126,6 +18170,7 @@ var PoolRegistry = class {
|
|
|
18126
18170
|
}
|
|
18127
18171
|
cfg;
|
|
18128
18172
|
pools = /* @__PURE__ */ new Map();
|
|
18173
|
+
poolCreates = /* @__PURE__ */ new Map();
|
|
18129
18174
|
resolveFlyToken;
|
|
18130
18175
|
resolvePoolMin;
|
|
18131
18176
|
log;
|
|
@@ -18137,6 +18182,15 @@ var PoolRegistry = class {
|
|
|
18137
18182
|
const repoTag = this.key(owner, repo);
|
|
18138
18183
|
const existing = this.pools.get(repoTag);
|
|
18139
18184
|
if (existing) return existing;
|
|
18185
|
+
const pending = this.poolCreates.get(repoTag);
|
|
18186
|
+
if (pending) return pending;
|
|
18187
|
+
const creating = this.createPool(owner, repo, repoTag).finally(() => {
|
|
18188
|
+
this.poolCreates.delete(repoTag);
|
|
18189
|
+
});
|
|
18190
|
+
this.poolCreates.set(repoTag, creating);
|
|
18191
|
+
return creating;
|
|
18192
|
+
}
|
|
18193
|
+
async createPool(owner, repo, repoTag) {
|
|
18140
18194
|
let flyToken;
|
|
18141
18195
|
try {
|
|
18142
18196
|
flyToken = await this.resolveFlyToken(owner, repo);
|
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.218",
|
|
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",
|