@songsid/agend 2.1.3-beta.6 → 2.1.3-beta.8
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/LICENSE +21 -0
- package/README.md +2 -2
- package/README.zh-TW.md +2 -2
- package/dist/backend/opencode.js +2 -4
- package/dist/backend/opencode.js.map +1 -1
- package/dist/cli.js +9 -10
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts +1 -9
- package/dist/daemon.js +37 -62
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.d.ts +0 -2
- package/dist/fleet-manager.js +0 -31
- package/dist/fleet-manager.js.map +1 -1
- package/dist/quickstart.js +4 -2
- package/dist/quickstart.js.map +1 -1
- package/dist/setup-wizard.d.ts +4 -2
- package/dist/setup-wizard.js +2 -2
- package/dist/setup-wizard.js.map +1 -1
- package/dist/tmux-control.js +8 -1
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-manager.d.ts +3 -0
- package/dist/tmux-manager.js +11 -1
- package/dist/tmux-manager.js.map +1 -1
- package/dist/ui/dashboard.html +5 -4
- package/dist/web-api.js +2 -2
- package/dist/web-api.js.map +1 -1
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -614,12 +614,8 @@ export class Daemon extends EventEmitter {
|
|
|
614
614
|
lastAdapterId;
|
|
615
615
|
// Pending ack: react 🫡 on first transcript activity after receiving a message
|
|
616
616
|
pendingAckMessage = null;
|
|
617
|
-
// Tool status tracking for channel adapter
|
|
618
617
|
/** Last activity published to the fleet manager; null when nothing is running. */
|
|
619
618
|
currentActivity = null;
|
|
620
|
-
toolStatusMessageId = null;
|
|
621
|
-
toolStatusLines = [];
|
|
622
|
-
toolStatusDebounce = null;
|
|
623
619
|
// Session identity: map IPC socket → sessionName (from mcp_ready)
|
|
624
620
|
socketSessionNames = new Map();
|
|
625
621
|
// Crash recovery
|
|
@@ -940,10 +936,6 @@ export class Daemon extends EventEmitter {
|
|
|
940
936
|
this.logger.error({ err: err.message }, "Wake failed for scheduled delivery");
|
|
941
937
|
});
|
|
942
938
|
}
|
|
943
|
-
else if (msg.type === "fleet_tool_status_ack") {
|
|
944
|
-
// Fleet manager sent us the messageId for our tool status message
|
|
945
|
-
this.toolStatusMessageId = msg.messageId;
|
|
946
|
-
}
|
|
947
939
|
else if (msg.type === "query_instance_state") {
|
|
948
940
|
const snapshot = this.getInstanceStateSnapshot();
|
|
949
941
|
this.ipcServer?.send(socket, {
|
|
@@ -1779,10 +1771,6 @@ export class Daemon extends EventEmitter {
|
|
|
1779
1771
|
async stop() {
|
|
1780
1772
|
this.logger.info("Stopping daemon instance");
|
|
1781
1773
|
this.freezeRuntimeMonitors();
|
|
1782
|
-
if (this.toolStatusDebounce) {
|
|
1783
|
-
clearTimeout(this.toolStatusDebounce);
|
|
1784
|
-
this.toolStatusDebounce = null;
|
|
1785
|
-
}
|
|
1786
1774
|
this.pendingIpcRequests.clear();
|
|
1787
1775
|
if (this.adapter)
|
|
1788
1776
|
await this.adapter.stop();
|
|
@@ -2440,45 +2428,6 @@ export class Daemon extends EventEmitter {
|
|
|
2440
2428
|
return ""; // skip channel tools
|
|
2441
2429
|
return name;
|
|
2442
2430
|
}
|
|
2443
|
-
addToolStatus(name, input, state) {
|
|
2444
|
-
const summary = this.summarizeTool(name, input);
|
|
2445
|
-
if (!summary)
|
|
2446
|
-
return; // skip empty (e.g., channel tools)
|
|
2447
|
-
if (state === "running") {
|
|
2448
|
-
this.toolStatusLines.push(`⏳ ${summary}`);
|
|
2449
|
-
}
|
|
2450
|
-
else {
|
|
2451
|
-
// Mark the last matching tool as done
|
|
2452
|
-
for (let i = this.toolStatusLines.length - 1; i >= 0; i--) {
|
|
2453
|
-
if (this.toolStatusLines[i].includes(name) && this.toolStatusLines[i].startsWith("⏳")) {
|
|
2454
|
-
this.toolStatusLines[i] = this.toolStatusLines[i].replace("⏳", "✅");
|
|
2455
|
-
break;
|
|
2456
|
-
}
|
|
2457
|
-
}
|
|
2458
|
-
}
|
|
2459
|
-
this.debouncedSendToolStatus();
|
|
2460
|
-
}
|
|
2461
|
-
/** Debounce tool status updates to avoid channel rate limits */
|
|
2462
|
-
debouncedSendToolStatus() {
|
|
2463
|
-
if (this.toolStatusDebounce)
|
|
2464
|
-
clearTimeout(this.toolStatusDebounce);
|
|
2465
|
-
this.toolStatusDebounce = setTimeout(() => this.sendToolStatus(), 500);
|
|
2466
|
-
}
|
|
2467
|
-
sendToolStatus() {
|
|
2468
|
-
const text = this.toolStatusLines.join("\n");
|
|
2469
|
-
if (!text)
|
|
2470
|
-
return;
|
|
2471
|
-
this.ipcServer?.broadcast({
|
|
2472
|
-
type: "fleet_tool_status",
|
|
2473
|
-
instanceName: this.name,
|
|
2474
|
-
text,
|
|
2475
|
-
editMessageId: this.toolStatusMessageId,
|
|
2476
|
-
});
|
|
2477
|
-
}
|
|
2478
|
-
/** Called by fleet manager when tool status message is sent (returns messageId) */
|
|
2479
|
-
setToolStatusMessageId(messageId) {
|
|
2480
|
-
this.toolStatusMessageId = messageId;
|
|
2481
|
-
}
|
|
2482
2431
|
/**
|
|
2483
2432
|
* Push an inbound channel message to a specific MCP session.
|
|
2484
2433
|
* If targetSession is provided, only send to the matching socket.
|
|
@@ -2656,6 +2605,16 @@ export class Daemon extends EventEmitter {
|
|
|
2656
2605
|
* precisely so the lock's scope is visible at the call site rather than being
|
|
2657
2606
|
* an invariant maintained by comments.
|
|
2658
2607
|
*/
|
|
2608
|
+
async sendDeliveryEnter(phase) {
|
|
2609
|
+
const sent = await this.tmux.sendSpecialKey("Enter");
|
|
2610
|
+
if (!sent) {
|
|
2611
|
+
this.logger.error({
|
|
2612
|
+
phase,
|
|
2613
|
+
tmuxError: this.tmux.getLastSendSpecialKeyError() ?? "unknown tmux send-keys failure",
|
|
2614
|
+
}, "tmux send-keys Enter failed during message delivery");
|
|
2615
|
+
}
|
|
2616
|
+
return sent;
|
|
2617
|
+
}
|
|
2659
2618
|
async writeMessageToPane(formatted, initialWindowId, handingOffToNativeQueue, status) {
|
|
2660
2619
|
let windowId = initialWindowId;
|
|
2661
2620
|
// Bug A: paste with backoff. Transient failures are usually a stale window id
|
|
@@ -2693,7 +2652,11 @@ export class Daemon extends EventEmitter {
|
|
|
2693
2652
|
settle = { settleMs: fallbackMs, observedPostPasteOutput: false, capHit: false, usedFallback: true };
|
|
2694
2653
|
}
|
|
2695
2654
|
let enterAt = Date.now();
|
|
2696
|
-
await this.
|
|
2655
|
+
if (!(await this.sendDeliveryEnter("initial-submit"))) {
|
|
2656
|
+
if (status)
|
|
2657
|
+
this.emit("message_failed", status); // ❌
|
|
2658
|
+
return false;
|
|
2659
|
+
}
|
|
2697
2660
|
// Kiro's legacy TUI can swallow Enter while it is still processing a large
|
|
2698
2661
|
// paste — not only during the post-ready redraw (#479): on slower hosts it
|
|
2699
2662
|
// happens on ordinary deliveries too (v2.1.2 stable, WSL2 + tmux 3.4).
|
|
@@ -2709,10 +2672,12 @@ export class Daemon extends EventEmitter {
|
|
|
2709
2672
|
let enterRetry = false;
|
|
2710
2673
|
if (this.backend?.requiresDeliveryEnterRetry?.() === true) {
|
|
2711
2674
|
await new Promise(r => setTimeout(r, 1_000));
|
|
2712
|
-
|
|
2713
|
-
await this.
|
|
2714
|
-
|
|
2715
|
-
|
|
2675
|
+
const retryAt = Date.now();
|
|
2676
|
+
if (await this.sendDeliveryEnter("queue-less-defensive-retry")) {
|
|
2677
|
+
enterAt = retryAt;
|
|
2678
|
+
enterRetry = true;
|
|
2679
|
+
this.logger.debug("Sent defensive Enter retry (queue-less TUI can swallow the first)");
|
|
2680
|
+
}
|
|
2716
2681
|
}
|
|
2717
2682
|
this.logger.debug({
|
|
2718
2683
|
observedPostPasteOutput: settle.observedPostPasteOutput,
|
|
@@ -2748,13 +2713,21 @@ export class Daemon extends EventEmitter {
|
|
|
2748
2713
|
}
|
|
2749
2714
|
await new Promise(r => setTimeout(r, NORMAL_ENTER_SETTLE_MS));
|
|
2750
2715
|
const retryAt = Date.now();
|
|
2751
|
-
await this.
|
|
2716
|
+
if (!(await this.sendDeliveryEnter("native-queue-idle-redelivery"))) {
|
|
2717
|
+
if (status)
|
|
2718
|
+
this.emit("message_failed", status); // ❌
|
|
2719
|
+
return false;
|
|
2720
|
+
}
|
|
2752
2721
|
if (windowId && this.controlClient) {
|
|
2753
2722
|
let becameBusy = await this.confirmBusyAfterEnter(windowId, retryAt);
|
|
2754
2723
|
if (!becameBusy) {
|
|
2755
2724
|
this.logger.warn("No idle→busy after idle-gated redelivery — re-sending Enter once");
|
|
2756
2725
|
const retry2At = Date.now();
|
|
2757
|
-
await this.
|
|
2726
|
+
if (!(await this.sendDeliveryEnter("native-queue-idle-redelivery-retry"))) {
|
|
2727
|
+
if (status)
|
|
2728
|
+
this.emit("message_failed", status); // ❌
|
|
2729
|
+
return false;
|
|
2730
|
+
}
|
|
2758
2731
|
becameBusy = await this.confirmBusyAfterEnter(windowId, retry2At);
|
|
2759
2732
|
}
|
|
2760
2733
|
if (becameBusy) {
|
|
@@ -2778,7 +2751,11 @@ export class Daemon extends EventEmitter {
|
|
|
2778
2751
|
if (!becameBusy) {
|
|
2779
2752
|
this.logger.warn("No idle→busy transition after Enter — re-sending Enter once");
|
|
2780
2753
|
const retryAt = Date.now();
|
|
2781
|
-
await this.
|
|
2754
|
+
if (!(await this.sendDeliveryEnter("idle-to-busy-retry"))) {
|
|
2755
|
+
if (status)
|
|
2756
|
+
this.emit("message_failed", status); // ❌
|
|
2757
|
+
return false;
|
|
2758
|
+
}
|
|
2782
2759
|
becameBusy = await this.confirmBusyAfterEnter(windowId, retryAt);
|
|
2783
2760
|
}
|
|
2784
2761
|
if (becameBusy) {
|
|
@@ -2799,7 +2776,7 @@ export class Daemon extends EventEmitter {
|
|
|
2799
2776
|
else {
|
|
2800
2777
|
// No control client to observe output: fall back to the legacy double-Enter.
|
|
2801
2778
|
await new Promise(r => setTimeout(r, 1000));
|
|
2802
|
-
await this.
|
|
2779
|
+
await this.sendDeliveryEnter("unobserved-defensive-retry");
|
|
2803
2780
|
if (status)
|
|
2804
2781
|
this.emit("message_confirmed", status); // ✅ (best-effort)
|
|
2805
2782
|
}
|
|
@@ -3367,8 +3344,6 @@ export class Daemon extends EventEmitter {
|
|
|
3367
3344
|
this.beginSpawn();
|
|
3368
3345
|
let resumedSuccessfully = false;
|
|
3369
3346
|
try {
|
|
3370
|
-
this.toolStatusLines = [];
|
|
3371
|
-
this.toolStatusMessageId = null;
|
|
3372
3347
|
if (!this.backend) {
|
|
3373
3348
|
throw new Error("No backend configured — cannot spawn CLI window");
|
|
3374
3349
|
}
|