@songsid/agend 2.1.4-beta.32 → 2.1.4-beta.34
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/adapters/discord.js +9 -7
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/ipc-bridge.d.ts +2 -1
- package/dist/channel/ipc-bridge.js +33 -4
- package/dist/channel/ipc-bridge.js.map +1 -1
- package/dist/channel/mcp-server.js +11 -2
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/config-validator.js +4 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/daemon.d.ts +7 -0
- package/dist/daemon.js +62 -44
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.js +37 -9
- package/dist/fleet-manager.js.map +1 -1
- package/dist/reply-dedup.d.ts +7 -8
- package/dist/reply-dedup.js +0 -0
- package/dist/reply-dedup.js.map +1 -1
- package/dist/ui/settings.html +82 -11
- package/package.json +2 -2
package/dist/fleet-manager.js
CHANGED
|
@@ -3932,8 +3932,6 @@ export class FleetManager {
|
|
|
3932
3932
|
}
|
|
3933
3933
|
/** Handle outbound tool calls from a daemon instance */
|
|
3934
3934
|
async handleOutboundFromInstance(instanceName, msg) {
|
|
3935
|
-
if (this.worlds.size === 0)
|
|
3936
|
-
return;
|
|
3937
3935
|
this.touchActivity(instanceName);
|
|
3938
3936
|
this.setTopicIcon(instanceName, "green");
|
|
3939
3937
|
const tool = msg.tool;
|
|
@@ -3943,13 +3941,21 @@ export class FleetManager {
|
|
|
3943
3941
|
const senderSessionName = msg.senderSessionName;
|
|
3944
3942
|
const respond = (result, error) => {
|
|
3945
3943
|
const ipc = this.instanceIpcClients.get(instanceName);
|
|
3944
|
+
let sent = false;
|
|
3946
3945
|
if (fleetRequestId) {
|
|
3947
|
-
ipc?.send({ type: "fleet_outbound_response", fleetRequestId, result, error });
|
|
3946
|
+
sent = ipc?.send({ type: "fleet_outbound_response", fleetRequestId, result, error }) ?? false;
|
|
3948
3947
|
}
|
|
3949
3948
|
else {
|
|
3950
|
-
ipc?.send({ type: "fleet_outbound_response", requestId, result, error });
|
|
3949
|
+
sent = ipc?.send({ type: "fleet_outbound_response", requestId, result, error }) ?? false;
|
|
3950
|
+
}
|
|
3951
|
+
if (!sent) {
|
|
3952
|
+
this.logger.warn({ instanceName, tool, requestId, fleetRequestId, error }, "Fleet outbound result could not be returned — instance IPC is disconnected");
|
|
3951
3953
|
}
|
|
3952
3954
|
};
|
|
3955
|
+
if (this.worlds.size === 0) {
|
|
3956
|
+
respond(null, "Channel adapters are not ready — retry shortly");
|
|
3957
|
+
return;
|
|
3958
|
+
}
|
|
3953
3959
|
// Resolve threadId: use sender's topic_id if sender is a known fleet instance,
|
|
3954
3960
|
// fall back to general topic if sender is unknown, or IPC owner if no sender.
|
|
3955
3961
|
const senderInstanceName = senderSessionName && this.fleetConfig?.instances[senderSessionName]
|
|
@@ -3994,17 +4000,30 @@ export class FleetManager {
|
|
|
3994
4000
|
if (tool === "reply") {
|
|
3995
4001
|
const ticket = this.replyDeduper.begin(instanceName, String(args.text ?? ""), Array.isArray(args.files) ? args.files : []);
|
|
3996
4002
|
if (ticket.duplicate) {
|
|
3997
|
-
this.logger.info({ instanceName }, "
|
|
4003
|
+
this.logger.info({ instanceName }, "Concurrent duplicate reply joined — awaiting the original send's outcome");
|
|
3998
4004
|
ticket.subscribe(respond);
|
|
3999
4005
|
return;
|
|
4000
4006
|
}
|
|
4001
4007
|
const original = respond;
|
|
4002
4008
|
const respondAndRecord = (result, error) => {
|
|
4003
4009
|
ticket.complete(result, error);
|
|
4010
|
+
// Return the platform outcome first. Bookkeeping below must never turn
|
|
4011
|
+
// a confirmed Discord/Telegram POST into a tool error if a secondary
|
|
4012
|
+
// log/button side effect happens to throw.
|
|
4004
4013
|
original(result, error);
|
|
4014
|
+
// The adapter resolves only after the platform POST returns. Keep
|
|
4015
|
+
// outward-facing logs/cancel state on the same confirmation boundary:
|
|
4016
|
+
// a routed-but-failed reply is not a delivered reply.
|
|
4017
|
+
if (!error && result != null) {
|
|
4018
|
+
try {
|
|
4019
|
+
this.afterReplyRouted(instanceName, args, senderSessionName);
|
|
4020
|
+
}
|
|
4021
|
+
catch (err) {
|
|
4022
|
+
this.logger.warn({ err, instanceName }, "Reply delivered but post-delivery bookkeeping failed");
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4005
4025
|
};
|
|
4006
4026
|
if (routeToolCall(outAdapter, tool, args, threadId, respondAndRecord)) {
|
|
4007
|
-
this.afterReplyRouted(instanceName, args, senderSessionName);
|
|
4008
4027
|
return;
|
|
4009
4028
|
}
|
|
4010
4029
|
// routeToolCall knows "reply"; not handling it means the world changed.
|
|
@@ -9224,9 +9243,10 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
|
|
|
9224
9243
|
const lastActivity = inst.classic
|
|
9225
9244
|
? Math.max(persistedInboundAt ?? 0, readClassicLastActivityAt(this.dataDir, inst.name) ?? 0) || null
|
|
9226
9245
|
: (persistedInboundAt ?? this.lastActivityMs(inst.name)) || null;
|
|
9227
|
-
const backend = inst.
|
|
9228
|
-
|
|
9229
|
-
|
|
9246
|
+
const backend = this.backendNameForInstance(inst.name);
|
|
9247
|
+
const resolvedModel = this.resolveInstanceModel(inst.name);
|
|
9248
|
+
const effortStrategy = this.effortStrategyFor(inst.name);
|
|
9249
|
+
const resolvedEffort = this.resolveInstanceEffort(inst.name);
|
|
9230
9250
|
// Find claimed tasks for this instance
|
|
9231
9251
|
let currentTask = null;
|
|
9232
9252
|
try {
|
|
@@ -9241,6 +9261,14 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
|
|
|
9241
9261
|
...inst,
|
|
9242
9262
|
description: config?.description ?? ("classicName" in inst ? inst.classicName : null),
|
|
9243
9263
|
backend,
|
|
9264
|
+
// Settings renders these runtime-effective values rather than the
|
|
9265
|
+
// sparse user-authored YAML. `auto` means the supported CLI is
|
|
9266
|
+
// using its own effort default; null is reserved for unsupported.
|
|
9267
|
+
model: resolvedModel.model,
|
|
9268
|
+
model_display: resolvedModel.display,
|
|
9269
|
+
model_source: resolvedModel.source,
|
|
9270
|
+
effort: effortStrategy === "unsupported" ? null : (resolvedEffort.effort ?? "auto"),
|
|
9271
|
+
effort_supported: effortStrategy !== "unsupported",
|
|
9244
9272
|
tool_set: config?.tool_set ?? "full",
|
|
9245
9273
|
general_topic: config?.general_topic ?? false,
|
|
9246
9274
|
// User activity is persisted by the daemon, so both the board and
|