@songsid/agend 2.1.5 → 2.1.6-beta.1
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/backend/codex.d.ts +16 -0
- package/dist/backend/codex.js +50 -0
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/types.d.ts +13 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/daemon.d.ts +15 -0
- package/dist/daemon.js +130 -15
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.d.ts +8 -0
- package/dist/fleet-manager.js +74 -0
- package/dist/fleet-manager.js.map +1 -1
- package/package.json +1 -1
package/dist/fleet-manager.d.ts
CHANGED
|
@@ -181,6 +181,10 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
181
181
|
private instanceIdleWaiters;
|
|
182
182
|
private lastInboundUser;
|
|
183
183
|
private cancelButtons;
|
|
184
|
+
/** Latest publication generation per instance. Late results from older
|
|
185
|
+
* generations are retired without touching the current button. */
|
|
186
|
+
private cancelButtonPublications;
|
|
187
|
+
private nextCancelButtonPublicationGeneration;
|
|
184
188
|
/** Pending idle-edge retirement, one timer per instance. */
|
|
185
189
|
private cancelButtonIdleRetireTimers;
|
|
186
190
|
/** Duplicate-reply suppression across both the MCP and HTTP reply paths. */
|
|
@@ -1056,6 +1060,10 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
1056
1060
|
*/
|
|
1057
1061
|
private handleCancelClick;
|
|
1058
1062
|
private hasCancelButton;
|
|
1063
|
+
private beginCancelButtonPublication;
|
|
1064
|
+
/** Remember a clear/cancel/idle decision that arrived before notifyAlert
|
|
1065
|
+
* returned a message id. `expected` fences an idle timer to its generation. */
|
|
1066
|
+
private markCancelButtonPublicationForRetirement;
|
|
1059
1067
|
sendCancelButton(instanceName: string, correlationId?: string, preserveProgress?: boolean): Promise<void>;
|
|
1060
1068
|
/**
|
|
1061
1069
|
* The cancel button's text for a given elapsed time.
|
package/dist/fleet-manager.js
CHANGED
|
@@ -383,6 +383,10 @@ export class FleetManager {
|
|
|
383
383
|
// reply, on cancel, or when a newer button supersedes it for the same
|
|
384
384
|
// instance. Per-button tracking means a failed delete never strands a button.
|
|
385
385
|
cancelButtons = new Map();
|
|
386
|
+
/** Latest publication generation per instance. Late results from older
|
|
387
|
+
* generations are retired without touching the current button. */
|
|
388
|
+
cancelButtonPublications = new Map();
|
|
389
|
+
nextCancelButtonPublicationGeneration = 0;
|
|
386
390
|
/** Pending idle-edge retirement, one timer per instance. */
|
|
387
391
|
cancelButtonIdleRetireTimers = new Map();
|
|
388
392
|
/** Duplicate-reply suppression across both the MCP and HTTP reply paths. */
|
|
@@ -1181,12 +1185,17 @@ export class FleetManager {
|
|
|
1181
1185
|
}
|
|
1182
1186
|
scheduleIdleButtonRetirement(name) {
|
|
1183
1187
|
this.cancelIdleButtonRetirement(name);
|
|
1188
|
+
// Bind this edge to the publication that was current when idle was
|
|
1189
|
+
// observed. A later inbound may start a new generation before this timer
|
|
1190
|
+
// fires; the old edge must not mark that newer button for retirement.
|
|
1191
|
+
const publication = this.cancelButtonPublications.get(name);
|
|
1184
1192
|
const timer = setTimeout(() => {
|
|
1185
1193
|
// Ignore a superseded timer even if it was already queued to run.
|
|
1186
1194
|
if (this.cancelButtonIdleRetireTimers.get(name) !== timer)
|
|
1187
1195
|
return;
|
|
1188
1196
|
this.cancelButtonIdleRetireTimers.delete(name);
|
|
1189
1197
|
if (this.getInstanceExecutionState(name) === "idle") {
|
|
1198
|
+
this.markCancelButtonPublicationForRetirement(name, publication);
|
|
1190
1199
|
this.retireInstanceButtons(name);
|
|
1191
1200
|
}
|
|
1192
1201
|
}, CANCEL_BTN_IDLE_RETIRE_GRACE_MS);
|
|
@@ -7098,6 +7107,30 @@ export class FleetManager {
|
|
|
7098
7107
|
}
|
|
7099
7108
|
return false;
|
|
7100
7109
|
}
|
|
7110
|
+
beginCancelButtonPublication(instanceName, correlationId) {
|
|
7111
|
+
// A new handoff supersedes any idle timer left by the previous turn. If the
|
|
7112
|
+
// instance is still idle after this publication, the post-await level check
|
|
7113
|
+
// below starts a fresh grace period for this generation.
|
|
7114
|
+
this.cancelIdleButtonRetirement(instanceName);
|
|
7115
|
+
const publication = {
|
|
7116
|
+
generation: ++this.nextCancelButtonPublicationGeneration,
|
|
7117
|
+
correlationId,
|
|
7118
|
+
inFlight: true,
|
|
7119
|
+
retirePending: false,
|
|
7120
|
+
};
|
|
7121
|
+
this.cancelButtonPublications.set(instanceName, publication);
|
|
7122
|
+
return publication;
|
|
7123
|
+
}
|
|
7124
|
+
/** Remember a clear/cancel/idle decision that arrived before notifyAlert
|
|
7125
|
+
* returned a message id. `expected` fences an idle timer to its generation. */
|
|
7126
|
+
markCancelButtonPublicationForRetirement(instanceName, expected) {
|
|
7127
|
+
const publication = this.cancelButtonPublications.get(instanceName);
|
|
7128
|
+
if (!publication?.inFlight)
|
|
7129
|
+
return;
|
|
7130
|
+
if (expected && publication !== expected)
|
|
7131
|
+
return;
|
|
7132
|
+
publication.retirePending = true;
|
|
7133
|
+
}
|
|
7101
7134
|
async sendCancelButton(instanceName, correlationId, preserveProgress = false) {
|
|
7102
7135
|
// Post first, retire after (see the tail of this method). Retiring up front
|
|
7103
7136
|
// meant that from the delete until the new message came back — a chat API
|
|
@@ -7136,6 +7169,7 @@ export class FleetManager {
|
|
|
7136
7169
|
this.logger.warn({ instanceName, topicId, groupId }, "Cannot address cancel button (no chat id resolved)");
|
|
7137
7170
|
return;
|
|
7138
7171
|
}
|
|
7172
|
+
const publication = this.beginCancelButtonPublication(instanceName, correlationId);
|
|
7139
7173
|
try {
|
|
7140
7174
|
const sent = await adapter.notifyAlert(chatId, {
|
|
7141
7175
|
type: "cancel",
|
|
@@ -7143,6 +7177,7 @@ export class FleetManager {
|
|
|
7143
7177
|
message: "👀 處理中…",
|
|
7144
7178
|
choices: [{ id: `cancel:${instanceName}`, label: t("cancel.button") }],
|
|
7145
7179
|
}, threadId ? { threadId } : undefined);
|
|
7180
|
+
publication.inFlight = false;
|
|
7146
7181
|
const entry = {
|
|
7147
7182
|
instanceName,
|
|
7148
7183
|
adapterId,
|
|
@@ -7164,6 +7199,16 @@ export class FleetManager {
|
|
|
7164
7199
|
// empty even if the daemon's reset broadcast is still in flight.
|
|
7165
7200
|
toolProgress: preserveProgress ? this.instanceProgress.get(instanceName) : undefined,
|
|
7166
7201
|
};
|
|
7202
|
+
// A newer send started while this API call was pending. Track this late
|
|
7203
|
+
// message just long enough for the normal bounded delete/retry machinery
|
|
7204
|
+
// to remove it; critically, do not sweep the newer generation.
|
|
7205
|
+
if (this.cancelButtonPublications.get(instanceName) !== publication) {
|
|
7206
|
+
this.cancelButtons.set(sent.messageId, entry);
|
|
7207
|
+
this.persistCancelButtons();
|
|
7208
|
+
this.logger.debug({ instanceName, messageId: sent.messageId, generation: publication.generation }, "Retiring superseded cancel-button publication");
|
|
7209
|
+
this.retireButton(entry);
|
|
7210
|
+
return;
|
|
7211
|
+
}
|
|
7167
7212
|
this.startProgressTicker(entry);
|
|
7168
7213
|
// Idle-check backstop: every 5min, if the instance is idle, retire the
|
|
7169
7214
|
// button. Covers turns that end without hitting a clear trigger (reply /
|
|
@@ -7200,8 +7245,30 @@ export class FleetManager {
|
|
|
7200
7245
|
}
|
|
7201
7246
|
this.persistCancelButtons();
|
|
7202
7247
|
this.logger.info({ instanceName, messageId: sent.messageId }, "Cancel button sent");
|
|
7248
|
+
// Retirement is normally edge-triggered, but the edge (or an explicit
|
|
7249
|
+
// reply/cancel clear) may have happened while notifyAlert was in flight.
|
|
7250
|
+
// Reconcile the level after publication so a late button cannot resurrect
|
|
7251
|
+
// on an already-idle instance. Preserve the existing two-second grace:
|
|
7252
|
+
// a working transition cancels this timer just as it does for a normal
|
|
7253
|
+
// idle edge.
|
|
7254
|
+
if (publication.retirePending) {
|
|
7255
|
+
this.retireButton(entry);
|
|
7256
|
+
}
|
|
7257
|
+
else if (this.getInstanceExecutionState(instanceName) === "idle") {
|
|
7258
|
+
this.scheduleIdleButtonRetirement(instanceName);
|
|
7259
|
+
}
|
|
7203
7260
|
}
|
|
7204
7261
|
catch (e) {
|
|
7262
|
+
if (this.cancelButtonPublications.get(instanceName) === publication) {
|
|
7263
|
+
this.cancelButtonPublications.delete(instanceName);
|
|
7264
|
+
// beginCancelButtonPublication cancelled the previous turn's idle
|
|
7265
|
+
// timer so it could not act on this generation. If the provider POST
|
|
7266
|
+
// failed while the instance remained idle, restore that retirement
|
|
7267
|
+
// opportunity for any older button still on screen.
|
|
7268
|
+
if (this.getInstanceExecutionState(instanceName) === "idle") {
|
|
7269
|
+
this.scheduleIdleButtonRetirement(instanceName);
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7205
7272
|
this.logger.warn({ err: e.message, instanceName }, "Failed to send cancel button");
|
|
7206
7273
|
}
|
|
7207
7274
|
}
|
|
@@ -7554,6 +7621,7 @@ export class FleetManager {
|
|
|
7554
7621
|
}
|
|
7555
7622
|
/** Retire all cancel buttons for an instance — on reply or cancel. */
|
|
7556
7623
|
clearCancelButton(instanceName) {
|
|
7624
|
+
this.markCancelButtonPublicationForRetirement(instanceName);
|
|
7557
7625
|
this.retireInstanceButtons(instanceName);
|
|
7558
7626
|
}
|
|
7559
7627
|
/** Retire the cross-instance button matching a delegate→report correlation id.
|
|
@@ -7562,6 +7630,11 @@ export class FleetManager {
|
|
|
7562
7630
|
clearCancelButtonByCorrelation(correlationId) {
|
|
7563
7631
|
if (!correlationId)
|
|
7564
7632
|
return;
|
|
7633
|
+
for (const [instanceName, publication] of this.cancelButtonPublications) {
|
|
7634
|
+
if (publication.inFlight && publication.correlationId === correlationId) {
|
|
7635
|
+
this.markCancelButtonPublicationForRetirement(instanceName, publication);
|
|
7636
|
+
}
|
|
7637
|
+
}
|
|
7565
7638
|
for (const e of [...this.cancelButtons.values()]) {
|
|
7566
7639
|
if (e.correlationId === correlationId)
|
|
7567
7640
|
this.retireButton(e);
|
|
@@ -10299,6 +10372,7 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
|
|
|
10299
10372
|
clearInterval(entry.progressTimer);
|
|
10300
10373
|
}
|
|
10301
10374
|
this.cancelButtons.clear();
|
|
10375
|
+
this.cancelButtonPublications.clear();
|
|
10302
10376
|
for (const timer of this.cancelButtonIdleRetireTimers.values())
|
|
10303
10377
|
clearTimeout(timer);
|
|
10304
10378
|
this.cancelButtonIdleRetireTimers.clear();
|