@songsid/agend 2.1.2-beta.30 → 2.1.2-beta.32
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/daemon.d.ts +20 -0
- package/dist/daemon.js +35 -1
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.d.ts +4 -0
- package/dist/fleet-manager.js +40 -3
- package/dist/fleet-manager.js.map +1 -1
- package/package.json +1 -1
package/dist/fleet-manager.js
CHANGED
|
@@ -87,6 +87,12 @@ const CANCEL_BTN_MAX_RETRIES = 3;
|
|
|
87
87
|
* buttons no clear trigger reached (e.g. a scheduled/HTTP turn that never called
|
|
88
88
|
* reply). 5min (not the old 2s idle-watch) so Thinking isn't misread as idle. */
|
|
89
89
|
const CANCEL_BTN_IDLE_CHECK_INTERVAL_MS = 5 * 60_000;
|
|
90
|
+
/**
|
|
91
|
+
* A queued turn can produce a very short idle edge while the CLI hands off to
|
|
92
|
+
* the next message. Do not retire the cancel button until that edge remains
|
|
93
|
+
* idle for this long; a working/stuck report during the grace cancels it.
|
|
94
|
+
*/
|
|
95
|
+
const CANCEL_BTN_IDLE_RETIRE_GRACE_MS = 2_000;
|
|
90
96
|
/**
|
|
91
97
|
* How long after a reply an instance gets to resume working before its cancel
|
|
92
98
|
* button is retired. A short turn ends with a reply and never works again → the
|
|
@@ -220,6 +226,8 @@ export class FleetManager {
|
|
|
220
226
|
// reply, on cancel, or when a newer button supersedes it for the same
|
|
221
227
|
// instance. Per-button tracking means a failed delete never strands a button.
|
|
222
228
|
cancelButtons = new Map();
|
|
229
|
+
/** Pending idle-edge retirement, one timer per instance. */
|
|
230
|
+
cancelButtonIdleRetireTimers = new Map();
|
|
223
231
|
/** Duplicate-reply suppression across both the MCP and HTTP reply paths. */
|
|
224
232
|
replyDeduper = new ReplyDeduper();
|
|
225
233
|
/** instanceName → what it is doing right now, when the backend can tell us. */
|
|
@@ -624,11 +632,35 @@ export class FleetManager {
|
|
|
624
632
|
// edge into idle, not on every idle heartbeat.
|
|
625
633
|
if (state === "idle" && previous?.state !== "idle") {
|
|
626
634
|
this.enforceWarmCap();
|
|
627
|
-
//
|
|
628
|
-
//
|
|
629
|
-
this.
|
|
635
|
+
// A queued message may turn this edge back into working almost
|
|
636
|
+
// immediately. Give that handoff a short grace before retiring the button.
|
|
637
|
+
this.scheduleIdleButtonRetirement(name);
|
|
638
|
+
}
|
|
639
|
+
else if (state !== "idle") {
|
|
640
|
+
this.cancelIdleButtonRetirement(name);
|
|
630
641
|
}
|
|
631
642
|
}
|
|
643
|
+
cancelIdleButtonRetirement(name) {
|
|
644
|
+
const timer = this.cancelButtonIdleRetireTimers.get(name);
|
|
645
|
+
if (!timer)
|
|
646
|
+
return;
|
|
647
|
+
clearTimeout(timer);
|
|
648
|
+
this.cancelButtonIdleRetireTimers.delete(name);
|
|
649
|
+
}
|
|
650
|
+
scheduleIdleButtonRetirement(name) {
|
|
651
|
+
this.cancelIdleButtonRetirement(name);
|
|
652
|
+
const timer = setTimeout(() => {
|
|
653
|
+
// Ignore a superseded timer even if it was already queued to run.
|
|
654
|
+
if (this.cancelButtonIdleRetireTimers.get(name) !== timer)
|
|
655
|
+
return;
|
|
656
|
+
this.cancelButtonIdleRetireTimers.delete(name);
|
|
657
|
+
if (this.getInstanceExecutionState(name) === "idle") {
|
|
658
|
+
this.retireInstanceButtons(name);
|
|
659
|
+
}
|
|
660
|
+
}, CANCEL_BTN_IDLE_RETIRE_GRACE_MS);
|
|
661
|
+
timer.unref?.();
|
|
662
|
+
this.cancelButtonIdleRetireTimers.set(name, timer);
|
|
663
|
+
}
|
|
632
664
|
cacheInstanceProcessStatus(name, status) {
|
|
633
665
|
if (status === "running") {
|
|
634
666
|
this.instanceProcessStatus.delete(name);
|
|
@@ -636,6 +668,7 @@ export class FleetManager {
|
|
|
636
668
|
}
|
|
637
669
|
if (status !== "crashed" && status !== "stopped")
|
|
638
670
|
return;
|
|
671
|
+
this.cancelIdleButtonRetirement(name);
|
|
639
672
|
this.instanceProcessStatus.set(name, status);
|
|
640
673
|
// Never display the last ready prompt as current execution state after its
|
|
641
674
|
// owning CLI process has exited.
|
|
@@ -980,6 +1013,7 @@ export class FleetManager {
|
|
|
980
1013
|
}
|
|
981
1014
|
async stopInstance(name) {
|
|
982
1015
|
this.failoverActive.delete(name);
|
|
1016
|
+
this.cancelIdleButtonRetirement(name);
|
|
983
1017
|
this.instanceStateCache.delete(name);
|
|
984
1018
|
this.instanceProcessStatus.delete(name);
|
|
985
1019
|
this.lastDeliveryAt.delete(name);
|
|
@@ -6095,6 +6129,9 @@ When users create specialized instances, suggest these configurations:
|
|
|
6095
6129
|
clearInterval(entry.progressTimer);
|
|
6096
6130
|
}
|
|
6097
6131
|
this.cancelButtons.clear();
|
|
6132
|
+
for (const timer of this.cancelButtonIdleRetireTimers.values())
|
|
6133
|
+
clearTimeout(timer);
|
|
6134
|
+
this.cancelButtonIdleRetireTimers.clear();
|
|
6098
6135
|
if (this.topicCleanupTimer) {
|
|
6099
6136
|
clearInterval(this.topicCleanupTimer);
|
|
6100
6137
|
this.topicCleanupTimer = null;
|