@songsid/agend 2.1.2-beta.31 → 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/fleet-manager.d.ts
CHANGED
|
@@ -100,6 +100,8 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
100
100
|
private instanceIdleWaiters;
|
|
101
101
|
private lastInboundUser;
|
|
102
102
|
private cancelButtons;
|
|
103
|
+
/** Pending idle-edge retirement, one timer per instance. */
|
|
104
|
+
private cancelButtonIdleRetireTimers;
|
|
103
105
|
/** Duplicate-reply suppression across both the MCP and HTTP reply paths. */
|
|
104
106
|
readonly replyDeduper: ReplyDeduper;
|
|
105
107
|
/** instanceName → what it is doing right now, when the backend can tell us. */
|
|
@@ -231,6 +233,8 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
231
233
|
getInstanceExecutionState(name: string): InstanceState | null;
|
|
232
234
|
isClassicInstance(name: string): boolean;
|
|
233
235
|
private cacheInstanceExecutionState;
|
|
236
|
+
private cancelIdleButtonRetirement;
|
|
237
|
+
private scheduleIdleButtonRetirement;
|
|
234
238
|
private cacheInstanceProcessStatus;
|
|
235
239
|
/**
|
|
236
240
|
* Fleet-wide warm cap: if more than `defaults.warm_cap` instances are running,
|
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;
|