@songsid/agend 2.1.8-beta.1 → 2.1.8-beta.3
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/agent-cli.js +9 -0
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +3 -1
- package/dist/agent-endpoint.js +7 -1
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/backend/cli-env-probe-worker.d.ts +1 -0
- package/dist/backend/cli-env-probe-worker.js +25 -0
- package/dist/backend/cli-env-probe-worker.js.map +1 -0
- package/dist/backend/codex.js +15 -1
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/muse.js +10 -1
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +12 -1
- package/dist/backend/types.js +14 -3
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +16 -4
- package/dist/channel/adapters/discord.js +20 -5
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/mcp-tools.js +4 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/daemon.d.ts +31 -0
- package/dist/daemon.js +107 -25
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-context.d.ts +5 -0
- package/dist/fleet-context.js.map +1 -1
- package/dist/fleet-manager.d.ts +47 -11
- package/dist/fleet-manager.js +322 -61
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +45 -0
- package/dist/locale.js +18 -0
- package/dist/locale.js.map +1 -1
- package/dist/outbound-schemas.d.ts +18 -4
- package/dist/outbound-schemas.js +8 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/settings-api.d.ts +6 -8
- package/dist/settings-api.js +9 -4
- package/dist/settings-api.js.map +1 -1
- package/dist/status-emojis.d.ts +19 -0
- package/dist/status-emojis.js.map +1 -1
- package/dist/tool-permissions.js +6 -2
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +9 -0
- package/dist/topic-commands.js +41 -2
- package/dist/topic-commands.js.map +1 -1
- package/dist/ui/settings.html +23 -11
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -906,6 +906,11 @@ export class BlockingProcessDetector {
|
|
|
906
906
|
this.notified = false;
|
|
907
907
|
}
|
|
908
908
|
}
|
|
909
|
+
/** Response types the fleet sends back for tool calls the daemon forwarded. */
|
|
910
|
+
const FLEET_RESPONSE_TYPES = new Set([
|
|
911
|
+
"fleet_schedule_response", "fleet_outbound_response", "fleet_decision_response", "fleet_task_response",
|
|
912
|
+
"fleet_display_name_response", "fleet_description_response", "fleet_persona_emoji_response",
|
|
913
|
+
]);
|
|
909
914
|
export class Daemon extends EventEmitter {
|
|
910
915
|
name;
|
|
911
916
|
config;
|
|
@@ -1506,21 +1511,7 @@ export class Daemon extends EventEmitter {
|
|
|
1506
1511
|
await this.ipcServer.listen();
|
|
1507
1512
|
ipcListening = true;
|
|
1508
1513
|
// Permanent IPC dispatcher: routes responses to pending requests by type+id key
|
|
1509
|
-
this.ipcServer.on("message", (msg) =>
|
|
1510
|
-
const type = msg.type;
|
|
1511
|
-
if (!type)
|
|
1512
|
-
return;
|
|
1513
|
-
// Build lookup key matching the pattern used when registering
|
|
1514
|
-
let key;
|
|
1515
|
-
if ((type === "fleet_schedule_response" || type === "fleet_outbound_response" || type === "fleet_decision_response" || type === "fleet_task_response" || type === "fleet_display_name_response" || type === "fleet_description_response") && msg.fleetRequestId) {
|
|
1516
|
-
key = String(msg.fleetRequestId);
|
|
1517
|
-
}
|
|
1518
|
-
if (key && this.pendingIpcRequests.has(key)) {
|
|
1519
|
-
const handler = this.pendingIpcRequests.get(key);
|
|
1520
|
-
this.pendingIpcRequests.delete(key);
|
|
1521
|
-
handler(msg);
|
|
1522
|
-
}
|
|
1523
|
-
});
|
|
1514
|
+
this.ipcServer.on("message", (msg) => this.routeFleetResponse(msg));
|
|
1524
1515
|
// IPC message relay: when daemon wants to push a channel message to Claude,
|
|
1525
1516
|
// it broadcasts to all IPC clients (the MCP server is one of them).
|
|
1526
1517
|
// When MCP server sends a tool_call, daemon handles it via the messageBus.
|
|
@@ -5045,10 +5036,13 @@ export class Daemon extends EventEmitter {
|
|
|
5045
5036
|
// The pane text comes back with the verdict: a transient that is still
|
|
5046
5037
|
// repainting is still working, and that is the only thing separating a
|
|
5047
5038
|
// slow resume from a wedged one.
|
|
5039
|
+
if (transient)
|
|
5040
|
+
this.resetFooterFallback();
|
|
5048
5041
|
return transient ? { state: "active", transient, pane } : { state: "clear" };
|
|
5049
5042
|
}
|
|
5050
5043
|
catch (err) {
|
|
5051
5044
|
this.logger.debug({ err }, "capture-pane failed during the input-transient probe — pane state unknown");
|
|
5045
|
+
this.resetFooterFallback();
|
|
5052
5046
|
return { state: "unknown" };
|
|
5053
5047
|
}
|
|
5054
5048
|
}
|
|
@@ -5259,13 +5253,77 @@ export class Daemon extends EventEmitter {
|
|
|
5259
5253
|
return !check;
|
|
5260
5254
|
try {
|
|
5261
5255
|
const mode = await this.tmux.getPaneInputMode?.();
|
|
5262
|
-
if (mode !== "raw")
|
|
5256
|
+
if (mode !== "raw") {
|
|
5257
|
+
this.resetFooterFallback();
|
|
5263
5258
|
return false;
|
|
5264
|
-
|
|
5259
|
+
}
|
|
5260
|
+
return this.deliveryInputReadyPane(await this.tmux.capturePane());
|
|
5265
5261
|
}
|
|
5266
5262
|
catch {
|
|
5263
|
+
this.resetFooterFallback();
|
|
5264
|
+
return false;
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
/** Pane text of the current footer-fallback candidate, and since when it has been unchanged. */
|
|
5268
|
+
footerFallbackPaneKey = null;
|
|
5269
|
+
footerFallbackStableSince = 0;
|
|
5270
|
+
/** The launch the candidate was seen in: a new spawn or launch attempt starts over. */
|
|
5271
|
+
footerFallbackEpoch = null;
|
|
5272
|
+
/**
|
|
5273
|
+
* Forget the footer-fallback candidate. Called whenever the pane is seen
|
|
5274
|
+
* outside the candidate state (busy, a dialog, a transient, unreadable) and
|
|
5275
|
+
* on every spawn: "stable for UNKNOWN_LAYOUT_STABLE_MS" must mean this screen,
|
|
5276
|
+
* continuously, not time accumulated across an interruption.
|
|
5277
|
+
*/
|
|
5278
|
+
resetFooterFallback() {
|
|
5279
|
+
this.footerFallbackPaneKey = null;
|
|
5280
|
+
this.footerFallbackEpoch = null;
|
|
5281
|
+
}
|
|
5282
|
+
footerFallbackWarnedGeneration = null;
|
|
5283
|
+
/**
|
|
5284
|
+
* The input-row proof used before a paste (#931/#947), with one fallback
|
|
5285
|
+
* (#1031). Codex sometimes paints an idle composer without its Context
|
|
5286
|
+
* status item even though tui.status_line asks for it: after four fleet
|
|
5287
|
+
* restarts, sol's resumed session showed only `⚠ 2 warnings · f2 to view`.
|
|
5288
|
+
* The proof needs a recognised footer, so the first delivery after each
|
|
5289
|
+
* restart waited 30 minutes, failed, and waited again, for seven hours.
|
|
5290
|
+
*
|
|
5291
|
+
* When the footer is the only thing missing, the #978 structural evidence
|
|
5292
|
+
* stands in for it, all of it required: the backend's own stable-unknown
|
|
5293
|
+
* idle check (an empty live composer; no busy row, esc-to-interrupt row,
|
|
5294
|
+
* queued ↳ input or known picker), no input transient such as the resume
|
|
5295
|
+
* load, and the same screen for UNKNOWN_LAYOUT_STABLE_MS. The raw-tty
|
|
5296
|
+
* requirement stays with the caller.
|
|
5297
|
+
*/
|
|
5298
|
+
deliveryInputReadyPane(pane) {
|
|
5299
|
+
const check = this.backend?.isDeliveryInputReadyPane;
|
|
5300
|
+
if (!check)
|
|
5301
|
+
return true;
|
|
5302
|
+
if (check.call(this.backend, pane)) {
|
|
5303
|
+
this.footerFallbackPaneKey = null;
|
|
5304
|
+
return true;
|
|
5305
|
+
}
|
|
5306
|
+
const stableUnknown = this.backend?.isStableUnknownLayoutIdlePane;
|
|
5307
|
+
if (!stableUnknown?.call(this.backend, pane) || this.inputTransientInPane(pane)) {
|
|
5308
|
+
this.footerFallbackPaneKey = null;
|
|
5309
|
+
return false;
|
|
5310
|
+
}
|
|
5311
|
+
const key = pane.replace(/⋆/gu, "").replace(/[ \t]+$/gmu, "");
|
|
5312
|
+
const epoch = `${this.spawnGeneration}:${this.launchAttempt}`;
|
|
5313
|
+
const now = Date.now();
|
|
5314
|
+
if (key !== this.footerFallbackPaneKey || epoch !== this.footerFallbackEpoch) {
|
|
5315
|
+
this.footerFallbackPaneKey = key;
|
|
5316
|
+
this.footerFallbackEpoch = epoch;
|
|
5317
|
+
this.footerFallbackStableSince = now;
|
|
5318
|
+
return false;
|
|
5319
|
+
}
|
|
5320
|
+
if (now - this.footerFallbackStableSince < UNKNOWN_LAYOUT_STABLE_MS)
|
|
5267
5321
|
return false;
|
|
5322
|
+
if (this.footerFallbackWarnedGeneration !== this.spawnGeneration) {
|
|
5323
|
+
this.footerFallbackWarnedGeneration = this.spawnGeneration;
|
|
5324
|
+
this.logger.warn({ backend: this.backend?.binaryName, stableForMs: now - this.footerFallbackStableSince }, "Idle footer not recognised — delivering on the #978 fallback (stable empty composer, no busy/queued/dialog, raw tty, no transient)");
|
|
5268
5325
|
}
|
|
5326
|
+
return true;
|
|
5269
5327
|
}
|
|
5270
5328
|
/**
|
|
5271
5329
|
* Why a pane is not deliverable matters. "busy" may be handed to a native
|
|
@@ -5275,16 +5333,26 @@ export class Daemon extends EventEmitter {
|
|
|
5275
5333
|
* pane proves nothing. The silence gate comes first and costs no capture.
|
|
5276
5334
|
*/
|
|
5277
5335
|
async paneReadinessForDelivery(windowId) {
|
|
5278
|
-
|
|
5336
|
+
// Each early return below is the pane seen outside the footer-fallback
|
|
5337
|
+
// candidate state, and never reaches deliveryInputReadyPane: reset here.
|
|
5338
|
+
if (!this.isPaneIdleForDelivery(windowId)) {
|
|
5339
|
+
this.resetFooterFallback();
|
|
5279
5340
|
return "busy";
|
|
5341
|
+
}
|
|
5280
5342
|
const probe = await this.probeBlockingDialog();
|
|
5281
|
-
if (probe.state !== "clear")
|
|
5343
|
+
if (probe.state !== "clear") {
|
|
5344
|
+
this.resetFooterFallback();
|
|
5282
5345
|
return probe.state;
|
|
5346
|
+
}
|
|
5283
5347
|
const transient = await this.probeInputTransient();
|
|
5284
|
-
if (transient.state === "active")
|
|
5348
|
+
if (transient.state === "active") {
|
|
5349
|
+
this.resetFooterFallback();
|
|
5285
5350
|
return "transient";
|
|
5286
|
-
|
|
5351
|
+
}
|
|
5352
|
+
if (transient.state === "unknown") {
|
|
5353
|
+
this.resetFooterFallback();
|
|
5287
5354
|
return "unknown";
|
|
5355
|
+
}
|
|
5288
5356
|
if (this.needsStartupInputProof()) {
|
|
5289
5357
|
return await this.hasPositiveDeliveryInput() ? "ready" : "transient";
|
|
5290
5358
|
}
|
|
@@ -5461,7 +5529,7 @@ export class Daemon extends EventEmitter {
|
|
|
5461
5529
|
return "busy";
|
|
5462
5530
|
if (this.backend?.getBusyPattern?.()?.test(pane))
|
|
5463
5531
|
return "busy";
|
|
5464
|
-
if (
|
|
5532
|
+
if (!this.deliveryInputReadyPane(pane))
|
|
5465
5533
|
return "busy";
|
|
5466
5534
|
if (strandedAgendMessageInInput(pane, prompt))
|
|
5467
5535
|
return "stranded";
|
|
@@ -6501,6 +6569,18 @@ export class Daemon extends EventEmitter {
|
|
|
6501
6569
|
}
|
|
6502
6570
|
return undefined;
|
|
6503
6571
|
}
|
|
6572
|
+
/** The fleet's answers to forwarded tool calls: settle the pending request they name. */
|
|
6573
|
+
routeFleetResponse(msg) {
|
|
6574
|
+
const type = msg.type;
|
|
6575
|
+
if (!type || !FLEET_RESPONSE_TYPES.has(type) || !msg.fleetRequestId)
|
|
6576
|
+
return;
|
|
6577
|
+
const key = String(msg.fleetRequestId);
|
|
6578
|
+
const handler = this.pendingIpcRequests.get(key);
|
|
6579
|
+
if (!handler)
|
|
6580
|
+
return;
|
|
6581
|
+
this.pendingIpcRequests.delete(key);
|
|
6582
|
+
handler(msg);
|
|
6583
|
+
}
|
|
6504
6584
|
/**
|
|
6505
6585
|
* Handle a tool call from the MCP server (forwarded by Claude).
|
|
6506
6586
|
* Routes to the channel adapter via MessageBus.
|
|
@@ -6549,9 +6629,11 @@ export class Daemon extends EventEmitter {
|
|
|
6549
6629
|
this.handleReleaseRepo(args, respond);
|
|
6550
6630
|
return;
|
|
6551
6631
|
}
|
|
6552
|
-
if (tool === "set_display_name" || tool === "set_description") {
|
|
6553
|
-
const type = tool === "set_display_name" ? "fleet_set_display_name"
|
|
6554
|
-
|
|
6632
|
+
if (tool === "set_display_name" || tool === "set_description" || tool === "list_emojis" || tool === "set_persona_emoji") {
|
|
6633
|
+
const type = tool === "set_display_name" ? "fleet_set_display_name"
|
|
6634
|
+
: tool === "set_description" ? "fleet_set_description"
|
|
6635
|
+
: tool === "list_emojis" ? "fleet_list_emojis" : "fleet_set_persona_emoji";
|
|
6636
|
+
const fleetReqId = `${tool === "set_display_name" ? "dn" : tool === "set_description" ? "desc" : "emoji"}_${++this.fleetRequestSeq}_${requestId}`;
|
|
6555
6637
|
const timeout = setTimeout(() => {
|
|
6556
6638
|
this.pendingIpcRequests.delete(fleetReqId);
|
|
6557
6639
|
respond(null, `${tool} timed out`);
|