@songsid/agend 2.1.8-beta.10 → 2.1.8-beta.11
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/channel/mcp-tools.js +1 -1
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/fleet-manager.d.ts +25 -0
- package/dist/fleet-manager.js +89 -16
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +5 -2
- package/dist/outbound-schemas.d.ts +2 -0
- package/dist/outbound-schemas.js +1 -1
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/status-emojis.d.ts +9 -1
- package/dist/status-emojis.js +11 -1
- package/dist/status-emojis.js.map +1 -1
- package/dist/target-queue-worker.d.ts +67 -0
- package/dist/target-queue-worker.js +76 -0
- package/dist/target-queue-worker.js.map +1 -0
- package/dist/tool-permissions.js +7 -2
- package/dist/tool-permissions.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/ui/settings.html +2 -2
- package/package.json +1 -1
|
@@ -110,7 +110,7 @@ const DEFS = [
|
|
|
110
110
|
["preview_emojis", schemas.PreviewEmojisArgs,
|
|
111
111
|
"Download up to 8 Discord server emojis from list_emojis so you can see them: returns a local image path per emoji to Read before you pick one."],
|
|
112
112
|
["set_persona_emoji", schemas.SetPersonaEmojiArgs,
|
|
113
|
-
"Set your persona emoji: the status stamp (default: delivered) your bot puts on messages it handles, so people can tell you apart from other bots. Validated the way Settings validates it; takes effect on your next stamp."],
|
|
113
|
+
"Set your persona emoji: the status stamp (default: delivered) your bot puts on messages it handles, so people can tell you apart from other bots. Other statuses: received, queued, processing, failed, progress_prefix, and photo / attachment (the stamp on a photo / file your bot saved). Validated the way Settings validates it; takes effect on your next stamp."],
|
|
114
114
|
["set_description", schemas.SetDescriptionArgs,
|
|
115
115
|
"Set your role description. This is injected into your system prompt as your role definition. Takes effect on next session restart."],
|
|
116
116
|
["checkout_repo", schemas.CheckoutRepoArgs,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../../src/channel/mcp-tools.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../../src/channel/mcp-tools.ts"],"names":[],"mappings":"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"}
|
package/dist/fleet-manager.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { ClassicChannelManager } from "./classic-channel-manager.js";
|
|
|
26
26
|
import { type ExplicitInstanceRemoval } from "./instance-removal.js";
|
|
27
27
|
import type { InstanceState } from "./backend/types.js";
|
|
28
28
|
import { WakeCoordinator } from "./wake-coordinator.js";
|
|
29
|
+
import { TargetQueueWorker } from "./target-queue-worker.js";
|
|
29
30
|
import { resolveDeliveryWorkerMode } from "./types.js";
|
|
30
31
|
import { type ConnectionMetadata, type ConnectionBinding, type BindingProbe, type SecretApplyJob, type ProviderSecretApplyJob } from "./connection-secrets.js";
|
|
31
32
|
import { type ProviderSecretStatus } from "./provider-secret-registry.js";
|
|
@@ -130,6 +131,12 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
130
131
|
private deliveryOutboxRecovered;
|
|
131
132
|
/** Phase 2b: wakes paused targets for queued durable work (delivery_worker ≠ off). */
|
|
132
133
|
wakeCoordinator: WakeCoordinator | null;
|
|
134
|
+
/**
|
|
135
|
+
* Phase 2c: targets whose durable lane a TargetQueueWorker owns
|
|
136
|
+
* (delivery_worker: on). Granted and released only in the pump's
|
|
137
|
+
* synchronous section and only while the lane is empty; the pump skips them.
|
|
138
|
+
*/
|
|
139
|
+
readonly queueWorkers: Map<string, TargetQueueWorker>;
|
|
133
140
|
private deliveryPumpScheduled;
|
|
134
141
|
private deliveryPumpRunning;
|
|
135
142
|
private deliveryPumpTimer;
|
|
@@ -383,6 +390,17 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
383
390
|
sweepReplyObligations(now?: Date): void;
|
|
384
391
|
private scheduleDeliveryOutboxPump;
|
|
385
392
|
private runDeliveryOutboxPump;
|
|
393
|
+
/**
|
|
394
|
+
* Phase 2c ownership (design §1.5-A), called synchronously from the pump
|
|
395
|
+
* before its claim loop, so a grant and the pump's own claims cannot
|
|
396
|
+
* interleave. A worker is granted a target's lane only when the target is
|
|
397
|
+
* `on` and its lane is empty: no row in flight in the outbox and no pump
|
|
398
|
+
* dispatch holding it. It gives the lane back only when it is idle and the
|
|
399
|
+
* target is no longer `on` (or has nothing pending). A flag change never
|
|
400
|
+
* takes a lane mid-drain.
|
|
401
|
+
*/
|
|
402
|
+
private reconcileQueueWorkers;
|
|
403
|
+
private createQueueWorker;
|
|
386
404
|
private dispatchDurableDelivery;
|
|
387
405
|
private waitForDurableLaneRelease;
|
|
388
406
|
private spawnConcurrency;
|
|
@@ -1236,6 +1254,13 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
1236
1254
|
* own adapter rather than through reactMessageStatus (classic bots).
|
|
1237
1255
|
*/
|
|
1238
1256
|
private receivedReactionFor;
|
|
1257
|
+
/**
|
|
1258
|
+
* The stamp for an inbound photo / file a classic bot saved (#1080): the
|
|
1259
|
+
* instance's `status_emojis.photo|attachment`, then its connection's, then
|
|
1260
|
+
* the built-in (📸/📎, or 👌/👍 on Telegram — what these paths always stamped).
|
|
1261
|
+
* Anything else a saved attachment can be counts as a file.
|
|
1262
|
+
*/
|
|
1263
|
+
private savedAttachmentReactionFor;
|
|
1239
1264
|
reactMessageStatus(instanceName: string, chatId: string, messageId: string, status: DeliveryStatus, threadId?: string): void;
|
|
1240
1265
|
/**
|
|
1241
1266
|
* Apply a terminal delivery verdict. On Telegram the built-in delivered is
|
package/dist/fleet-manager.js
CHANGED
|
@@ -68,6 +68,7 @@ import { validateFleetConfig } from "./config-validator.js";
|
|
|
68
68
|
import { readLastInboundAt } from "./daemon.js";
|
|
69
69
|
import { clearPausedMarker, readPausedAt, readPauseReason, writePausedMarker } from "./pause-marker.js";
|
|
70
70
|
import { DEFAULT_WARM_OVERFLOW, WakeCoordinator } from "./wake-coordinator.js";
|
|
71
|
+
import { TargetQueueWorker } from "./target-queue-worker.js";
|
|
71
72
|
import { resolveDeliveryWorkerMode } from "./types.js";
|
|
72
73
|
import { isFleetStartCommandLine, readProcessCommandLine, releaseProcessFleetLock } from "./fleet-lock.js";
|
|
73
74
|
import { isSetupComplete, markSetupComplete } from "./setup-marker.js";
|
|
@@ -290,6 +291,12 @@ export class FleetManager {
|
|
|
290
291
|
deliveryOutboxRecovered = false;
|
|
291
292
|
/** Phase 2b: wakes paused targets for queued durable work (delivery_worker ≠ off). */
|
|
292
293
|
wakeCoordinator = null;
|
|
294
|
+
/**
|
|
295
|
+
* Phase 2c: targets whose durable lane a TargetQueueWorker owns
|
|
296
|
+
* (delivery_worker: on). Granted and released only in the pump's
|
|
297
|
+
* synchronous section and only while the lane is empty; the pump skips them.
|
|
298
|
+
*/
|
|
299
|
+
queueWorkers = new Map();
|
|
293
300
|
deliveryPumpScheduled = false;
|
|
294
301
|
deliveryPumpRunning = false;
|
|
295
302
|
deliveryPumpTimer = null;
|
|
@@ -729,11 +736,13 @@ export class FleetManager {
|
|
|
729
736
|
const failure = this.wakeCoordinator?.wakeFailure(target);
|
|
730
737
|
return failure ? `target could not be woken (${failure})` : undefined;
|
|
731
738
|
});
|
|
739
|
+
this.reconcileQueueWorkers(outbox);
|
|
732
740
|
while (this.activeDurableTargets.size < 8) {
|
|
733
741
|
const claimed = outbox.claimNext(this.managerBootId,
|
|
734
742
|
// Phase 2b: a wake_only target is claimed only once it is awake; the
|
|
735
743
|
// wake coordinator, not this pump, wakes it (no claim, no attempt).
|
|
736
|
-
|
|
744
|
+
// Phase 2c: a lane a queue worker owns is never claimed here.
|
|
745
|
+
target => this.queueWorkers.has(target) || this.isInstanceRestarting(target) || this.wakeCoordinator?.blocksClaim(target)
|
|
737
746
|
? null
|
|
738
747
|
: this.daemons.get(target)?.bootId ?? null, this.activeDurableTargets);
|
|
739
748
|
if (!claimed)
|
|
@@ -763,7 +772,67 @@ export class FleetManager {
|
|
|
763
772
|
}
|
|
764
773
|
}
|
|
765
774
|
}
|
|
766
|
-
|
|
775
|
+
/**
|
|
776
|
+
* Phase 2c ownership (design §1.5-A), called synchronously from the pump
|
|
777
|
+
* before its claim loop, so a grant and the pump's own claims cannot
|
|
778
|
+
* interleave. A worker is granted a target's lane only when the target is
|
|
779
|
+
* `on` and its lane is empty: no row in flight in the outbox and no pump
|
|
780
|
+
* dispatch holding it. It gives the lane back only when it is idle and the
|
|
781
|
+
* target is no longer `on` (or has nothing pending). A flag change never
|
|
782
|
+
* takes a lane mid-drain.
|
|
783
|
+
*/
|
|
784
|
+
reconcileQueueWorkers(outbox) {
|
|
785
|
+
const pendingTargets = new Set(outbox.listPending().map(row => row.targetInstance));
|
|
786
|
+
for (const [target, worker] of this.queueWorkers) {
|
|
787
|
+
const keep = this.deliveryWorkerMode(target) === "on" && pendingTargets.has(target);
|
|
788
|
+
if (!keep && !worker.busy && !worker.inFlight)
|
|
789
|
+
this.queueWorkers.delete(target);
|
|
790
|
+
}
|
|
791
|
+
for (const target of pendingTargets) {
|
|
792
|
+
if (this.queueWorkers.has(target) || this.deliveryWorkerMode(target) !== "on")
|
|
793
|
+
continue;
|
|
794
|
+
const laneEmpty = !this.activeDurableTargets.has(target)
|
|
795
|
+
&& outbox.countForTarget(target, ["delivering", "submission_started"]) === 0;
|
|
796
|
+
if (laneEmpty)
|
|
797
|
+
this.queueWorkers.set(target, this.createQueueWorker(target));
|
|
798
|
+
}
|
|
799
|
+
for (const worker of this.queueWorkers.values())
|
|
800
|
+
void worker.drain();
|
|
801
|
+
}
|
|
802
|
+
createQueueWorker(target) {
|
|
803
|
+
const worker = new TargetQueueWorker(target, {
|
|
804
|
+
owns: () => this.queueWorkers.get(target) === worker,
|
|
805
|
+
wanted: () => this.deliveryWorkerMode(target) === "on",
|
|
806
|
+
available: () => !this.shuttingDown && this.deliveryOutbox?.isOpen === true,
|
|
807
|
+
blocked: () => this.isInstanceRestarting(target) || this.wakeCoordinator?.blocksClaim(target) === true,
|
|
808
|
+
daemonBootId: () => this.daemons.get(target)?.bootId ?? null,
|
|
809
|
+
claim: bootId => this.deliveryOutbox?.claimNext(this.managerBootId, candidate => candidate === target ? bootId : null, new Set()),
|
|
810
|
+
tryAcquireBudget: () => {
|
|
811
|
+
if (this.activeDurableTargets.size >= 8)
|
|
812
|
+
return false;
|
|
813
|
+
this.activeDurableTargets.add(target);
|
|
814
|
+
return true;
|
|
815
|
+
},
|
|
816
|
+
releaseBudget: () => { this.activeDurableTargets.delete(target); },
|
|
817
|
+
dispatch: async (claimed) => {
|
|
818
|
+
try {
|
|
819
|
+
await this.dispatchDurableDelivery(claimed, { holdLaneOnTransportError: true });
|
|
820
|
+
}
|
|
821
|
+
finally {
|
|
822
|
+
// The row's state event can fire before the hand-off settles; the
|
|
823
|
+
// pump pass it starts then still sees this worker busy and keeps it
|
|
824
|
+
// as owner. One kick after the dispatch has really settled lets the
|
|
825
|
+
// pump release an owner that is no longer wanted (or claim the next
|
|
826
|
+
// row). The no-claim path never kicks, so no retry hot loop.
|
|
827
|
+
this.scheduleDeliveryOutboxPump();
|
|
828
|
+
}
|
|
829
|
+
},
|
|
830
|
+
kickCoordinator: () => this.wakeCoordinator?.kick(),
|
|
831
|
+
logger: this.logger,
|
|
832
|
+
});
|
|
833
|
+
return worker;
|
|
834
|
+
}
|
|
835
|
+
async dispatchDurableDelivery(claimed, opts = {}) {
|
|
767
836
|
const outbox = this.deliveryOutbox;
|
|
768
837
|
if (!outbox)
|
|
769
838
|
return;
|
|
@@ -817,7 +886,10 @@ export class FleetManager {
|
|
|
817
886
|
catch (err) {
|
|
818
887
|
const latest = outbox.get(claimed.deliveryId);
|
|
819
888
|
const reason = err instanceof Error ? err.message : String(err);
|
|
820
|
-
if (latest?.state === "submission_started") {
|
|
889
|
+
if (opts.holdLaneOnTransportError && (latest?.state === "submission_started" || latest?.state === "reconciliation_pending")) {
|
|
890
|
+
this.logger.warn({ deliveryId: claimed.deliveryId, target, attempt, err: reason }, "Transport failed after the submission began; holding the lane for the daemon's verdict or its generation's reconciliation");
|
|
891
|
+
}
|
|
892
|
+
else if (latest?.state === "submission_started") {
|
|
821
893
|
outbox.complete(claimed.deliveryId, claimed.targetDaemonBootId, claimed.attemptNo, "uncertain", reason);
|
|
822
894
|
}
|
|
823
895
|
else {
|
|
@@ -7462,6 +7534,16 @@ export class FleetManager {
|
|
|
7462
7534
|
const resolved = this.resolveStatusEmojisFor(instanceName, adapterId, adapter);
|
|
7463
7535
|
return reactionForm(resolved.platform, resolved.received);
|
|
7464
7536
|
}
|
|
7537
|
+
/**
|
|
7538
|
+
* The stamp for an inbound photo / file a classic bot saved (#1080): the
|
|
7539
|
+
* instance's `status_emojis.photo|attachment`, then its connection's, then
|
|
7540
|
+
* the built-in (📸/📎, or 👌/👍 on Telegram — what these paths always stamped).
|
|
7541
|
+
* Anything else a saved attachment can be counts as a file.
|
|
7542
|
+
*/
|
|
7543
|
+
savedAttachmentReactionFor(instanceName, adapter, adapterId, kind) {
|
|
7544
|
+
const resolved = this.resolveStatusEmojisFor(instanceName, adapterId, adapter);
|
|
7545
|
+
return reactionForm(resolved.platform, kind === "photo" ? resolved.photo : resolved.attachment);
|
|
7546
|
+
}
|
|
7465
7547
|
reactMessageStatus(instanceName, chatId, messageId, status, threadId) {
|
|
7466
7548
|
// React via the adapter BOUND to this instance — NOT the first discord world.
|
|
7467
7549
|
// Otherwise, in a same-channel/same-guild multi-bot setup, the inbound 👀
|
|
@@ -10579,9 +10661,7 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
|
|
|
10579
10661
|
const reactAdapter = this.worlds.get(msg.adapterId ?? "")?.adapter ?? this.adapter;
|
|
10580
10662
|
const noMentionReactChatId = msg.threadId ?? msg.chatId;
|
|
10581
10663
|
if (reactAdapter && noMentionReactChatId && msg.messageId) {
|
|
10582
|
-
const emoji = msg.
|
|
10583
|
-
? (saved.kind === "photo" ? "👌" : "👍")
|
|
10584
|
-
: (saved.kind === "photo" ? "📸" : "📎");
|
|
10664
|
+
const emoji = this.savedAttachmentReactionFor(instanceName, reactAdapter, msg.adapterId, saved.kind);
|
|
10585
10665
|
reactAdapter.react(noMentionReactChatId, msg.messageId, emoji)
|
|
10586
10666
|
.catch(e => this.logger.debug({ err: e.message }, "Auto-react failed"));
|
|
10587
10667
|
}
|
|
@@ -10612,9 +10692,7 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
|
|
|
10612
10692
|
return;
|
|
10613
10693
|
// Attachments already saved at the top of the collab block.
|
|
10614
10694
|
if (saved && classicAdapter && collabReactChatId && msg.messageId) {
|
|
10615
|
-
const emoji = msg.
|
|
10616
|
-
? (saved.kind === "photo" ? "👌" : "👍")
|
|
10617
|
-
: (saved.kind === "photo" ? "📸" : "📎");
|
|
10695
|
+
const emoji = this.savedAttachmentReactionFor(instanceName, classicAdapter, msg.adapterId, saved.kind);
|
|
10618
10696
|
classicAdapter.react(collabReactChatId, msg.messageId, emoji)
|
|
10619
10697
|
.catch(e => this.logger.debug({ err: e.message }, "Auto-react failed"));
|
|
10620
10698
|
}
|
|
@@ -10662,10 +10740,7 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
|
|
|
10662
10740
|
const reactAdapter = this.worlds.get(msg.adapterId ?? "")?.adapter ?? this.adapter;
|
|
10663
10741
|
const reactChatId = msg.threadId ?? msg.chatId;
|
|
10664
10742
|
if (saved && reactAdapter && reactChatId && msg.messageId) {
|
|
10665
|
-
|
|
10666
|
-
const emoji = msg.source === "telegram"
|
|
10667
|
-
? (saved.kind === "photo" ? "👌" : "👍")
|
|
10668
|
-
: (saved.kind === "photo" ? "📸" : "📎");
|
|
10743
|
+
const emoji = this.savedAttachmentReactionFor(instanceName, reactAdapter, msg.adapterId, saved.kind);
|
|
10669
10744
|
reactAdapter.react(reactChatId, msg.messageId, emoji)
|
|
10670
10745
|
.catch(e => this.logger.debug({ err: e.message }, "Auto-react failed"));
|
|
10671
10746
|
}
|
|
@@ -10711,9 +10786,7 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
|
|
|
10711
10786
|
classicMsgAdapter.react(reactChatId, msg.messageId, this.receivedReactionFor(instanceName, classicMsgAdapter, msg.adapterId))
|
|
10712
10787
|
.catch(e => this.logger.debug({ err: e.message }, "Auto-react failed"));
|
|
10713
10788
|
if (saved) {
|
|
10714
|
-
const savedEmoji = msg.
|
|
10715
|
-
? (saved.kind === "photo" ? "👌" : "👍")
|
|
10716
|
-
: (saved.kind === "photo" ? "📸" : "📎");
|
|
10789
|
+
const savedEmoji = this.savedAttachmentReactionFor(instanceName, classicMsgAdapter, msg.adapterId, saved.kind);
|
|
10717
10790
|
classicMsgAdapter.react(reactChatId, msg.messageId, savedEmoji)
|
|
10718
10791
|
.catch(e => this.logger.debug({ err: e.message }, "Auto-react failed"));
|
|
10719
10792
|
}
|