instar 1.3.272 → 1.3.274
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +70 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/MachinePoolRegistry.d.ts +3 -0
- package/dist/core/MachinePoolRegistry.d.ts.map +1 -1
- package/dist/core/MachinePoolRegistry.js +1 -0
- package/dist/core/MachinePoolRegistry.js.map +1 -1
- package/dist/core/PlacementExecutor.d.ts.map +1 -1
- package/dist/core/PlacementExecutor.js +28 -6
- package/dist/core/PlacementExecutor.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +26 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +7 -3
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/types.d.ts +21 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts +19 -0
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +57 -0
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +2 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +20 -20
- package/src/scaffold/templates.ts +2 -0
- package/upgrades/1.3.273.md +52 -0
- package/upgrades/1.3.274.md +47 -0
- package/upgrades/side-effects/post-transfer-session-closeout.md +116 -0
- package/upgrades/side-effects/quota-aware-placement.md +99 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4SH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqxDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4SH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqxDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgjRtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
|
package/dist/commands/server.js
CHANGED
|
@@ -8640,6 +8640,27 @@ export async function startServer(options) {
|
|
|
8640
8640
|
// child (CPU-flat) from a working one, so an idle MCP child no longer
|
|
8641
8641
|
// holds an otherwise-reapable session hostage under host load.
|
|
8642
8642
|
descendantCpuSeconds: (s) => sessionManager.descendantCpuSeconds(s),
|
|
8643
|
+
// Post-transfer closeout (2026-06-05): the OTHER machine that owns this
|
|
8644
|
+
// topic per the session-pool ownership registry, as a display identifier
|
|
8645
|
+
// (nickname when resolvable). Late-binds the pool objects — they are
|
|
8646
|
+
// constructed AFTER the reaper in this function; until the mesh block
|
|
8647
|
+
// wires them (and on single-machine installs forever) this returns null
|
|
8648
|
+
// and the rule is inert. try/catch also absorbs the TDZ window.
|
|
8649
|
+
topicOwnerElsewhere: (topicId) => {
|
|
8650
|
+
try {
|
|
8651
|
+
const reg = sessionOwnershipRegistry;
|
|
8652
|
+
const self = _meshSelfId;
|
|
8653
|
+
if (!reg || !self)
|
|
8654
|
+
return null;
|
|
8655
|
+
const owner = reg.ownerOf(String(topicId));
|
|
8656
|
+
if (!owner || owner === self)
|
|
8657
|
+
return null;
|
|
8658
|
+
return machinePoolRegistry?.getCapacity(owner)?.nickname ?? owner;
|
|
8659
|
+
}
|
|
8660
|
+
catch {
|
|
8661
|
+
return null; /* @silent-fallback-ok — pool not wired yet → rule inert */
|
|
8662
|
+
}
|
|
8663
|
+
},
|
|
8643
8664
|
audit: reaperAuditSink(config.stateDir),
|
|
8644
8665
|
},
|
|
8645
8666
|
// developmentAgent gate (standard_development_agent_dark_feature_gate):
|
|
@@ -9039,12 +9060,39 @@ export async function startServer(options) {
|
|
|
9039
9060
|
poolIdMgr.recordSelfHardware(poolSelfId, poolMod.captureHardware());
|
|
9040
9061
|
}
|
|
9041
9062
|
catch { /* best-effort hardware self-attest */ }
|
|
9063
|
+
// Quota-aware placement (2026-06-05): self-report whether a NEW
|
|
9064
|
+
// session on THIS machine could work right now. Blocked = a provider
|
|
9065
|
+
// block is in effect (blockedUntil in the future) or the 5-hour
|
|
9066
|
+
// window is exhausted (>= 95%, the same bar QuotaTracker.canRunJob
|
|
9067
|
+
// uses to block all spawns). Sourced from THIS machine's own
|
|
9068
|
+
// QuotaTracker — never another machine's file (the gemini
|
|
9069
|
+
// quota-conflation lesson). Absent/unreadable state = not blocked.
|
|
9070
|
+
const selfQuotaState = () => {
|
|
9071
|
+
try {
|
|
9072
|
+
const q = quotaTracker?.getState();
|
|
9073
|
+
if (!q)
|
|
9074
|
+
return undefined;
|
|
9075
|
+
const blockActive = !!q.blockedUntil && Date.parse(q.blockedUntil) > Date.now();
|
|
9076
|
+
const fiveHourExhausted = (q.fiveHourPercent ?? 0) >= 95;
|
|
9077
|
+
if (!blockActive && !fiveHourExhausted)
|
|
9078
|
+
return { blocked: false };
|
|
9079
|
+
return {
|
|
9080
|
+
blocked: true,
|
|
9081
|
+
blockedUntil: q.blockedUntil,
|
|
9082
|
+
reason: q.blockReason ?? (fiveHourExhausted ? `5-hour window at ${q.fiveHourPercent}%` : 'provider block'),
|
|
9083
|
+
};
|
|
9084
|
+
}
|
|
9085
|
+
catch {
|
|
9086
|
+
return undefined; /* unknown ≠ blocked */
|
|
9087
|
+
}
|
|
9088
|
+
};
|
|
9042
9089
|
const refreshPool = () => {
|
|
9043
9090
|
try {
|
|
9044
9091
|
machinePoolRegistry.recordHeartbeat({
|
|
9045
9092
|
machineId: poolSelfId,
|
|
9046
9093
|
selfReportedLastSeen: new Date().toISOString(),
|
|
9047
9094
|
loadAvg: osMod.loadavg()[0],
|
|
9095
|
+
quotaState: selfQuotaState(),
|
|
9048
9096
|
});
|
|
9049
9097
|
const hbApi = machineHeartbeat?.api;
|
|
9050
9098
|
if (hbApi) {
|
|
@@ -9626,6 +9674,28 @@ export async function startServer(options) {
|
|
|
9626
9674
|
}
|
|
9627
9675
|
}
|
|
9628
9676
|
catch { /* best-effort; route() re-places regardless once the owner is cleared */ }
|
|
9677
|
+
// ── Post-transfer closeout, immediate half (2026-06-05) ───────
|
|
9678
|
+
// The user's explicit move means this machine's topic session is
|
|
9679
|
+
// now a leftover — left running it does duplicate work alongside
|
|
9680
|
+
// the target machine's session. Close it NOW (origin 'operator':
|
|
9681
|
+
// this executes the user's direct command, arrived through the
|
|
9682
|
+
// authed Telegram pipeline; disposition 'recovery-bounce' keeps
|
|
9683
|
+
// the §P3 notifier silent — the user already got the "Moving…"
|
|
9684
|
+
// reply, and the conversation continues on the target). Protected
|
|
9685
|
+
// sessions are never auto-closed (skipped here AND vetoed in the
|
|
9686
|
+
// reaper sweeper that backstops non-explicit move paths).
|
|
9687
|
+
if (plan.action === 'transfer' && target !== meshSelfId) {
|
|
9688
|
+
try {
|
|
9689
|
+
const tmuxName = telegram?.getSessionForTopic(topicId);
|
|
9690
|
+
const rec = tmuxName ? sessionManager.listRunningSessions().find((s) => s.tmuxSession === tmuxName) : undefined;
|
|
9691
|
+
if (rec && !sessionManager.getProtectedSessions().includes(rec.tmuxSession)) {
|
|
9692
|
+
void sessionManager.terminateSession(rec.id, `topic ${topicId} moved to ${cmd.nickname} (user-commanded transfer) — closing the leftover local session`, { origin: 'operator', disposition: 'recovery-bounce' }).then((r) => {
|
|
9693
|
+
console.log(pc.dim(` [session-pool] post-transfer closeout: ${rec.tmuxSession} → ${r.terminated ? 'closed' : `skipped (${r.skipped})`}`));
|
|
9694
|
+
});
|
|
9695
|
+
}
|
|
9696
|
+
}
|
|
9697
|
+
catch { /* @silent-fallback-ok — the reaper's topic-moved sweeper backstops this */ }
|
|
9698
|
+
}
|
|
9629
9699
|
await telegram?.sendToTopic(topicId, plan.action === 'noop'
|
|
9630
9700
|
? (plan.detail === 'already-on-target'
|
|
9631
9701
|
? `This conversation is already running on ${cmd.nickname} — nothing to move.`
|