@songsid/agend 2.1.0 → 2.1.1-beta.10
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/README.md +1 -0
- package/README.zh-TW.md +1 -0
- package/dist/agent-cli-instructions.md +9 -0
- package/dist/backend/antigravity.d.ts +4 -1
- package/dist/backend/antigravity.js +15 -2
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/codex.d.ts +1 -0
- package/dist/backend/codex.js +30 -2
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/grok.d.ts +1 -0
- package/dist/backend/grok.js +8 -1
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +7 -0
- package/dist/backend/kiro.js +15 -6
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +11 -6
- package/dist/backend/types.js +48 -4
- package/dist/backend/types.js.map +1 -1
- package/dist/cli.js +16 -8
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +18 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +11 -0
- package/dist/daemon.js +56 -32
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-context.d.ts +2 -0
- package/dist/fleet-manager.d.ts +25 -2
- package/dist/fleet-manager.js +127 -22
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/tui-effort/SKILL.md +115 -0
- package/dist/instance-lifecycle.d.ts +8 -0
- package/dist/instance-lifecycle.js +57 -4
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.js +10 -3
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +2 -0
- package/dist/locale.js.map +1 -1
- package/dist/sd-notify.d.ts +18 -0
- package/dist/sd-notify.js +41 -2
- package/dist/sd-notify.js.map +1 -1
- package/dist/service-installer.d.ts +7 -0
- package/dist/service-installer.js +43 -3
- package/dist/service-installer.js.map +1 -1
- package/dist/tmux-control.js +7 -1
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-manager.d.ts +16 -1
- package/dist/tmux-manager.js +69 -3
- package/dist/tmux-manager.js.map +1 -1
- package/dist/topic-commands.js +6 -2
- package/dist/topic-commands.js.map +1 -1
- package/dist/types.d.ts +13 -0
- package/dist/ui/view.html +170 -33
- package/dist/update-check.d.ts +22 -0
- package/dist/update-check.js +44 -0
- package/dist/update-check.js.map +1 -0
- package/dist/view-api.d.ts +7 -0
- package/dist/view-api.js +56 -12
- package/dist/view-api.js.map +1 -1
- package/package.json +1 -1
- package/templates/systemd.service.ejs +9 -1
- package/dist/fleet-system-prompt.d.ts +0 -11
- package/dist/fleet-system-prompt.js +0 -61
- package/dist/fleet-system-prompt.js.map +0 -1
package/dist/daemon.d.ts
CHANGED
|
@@ -198,12 +198,23 @@ export declare class Daemon extends EventEmitter {
|
|
|
198
198
|
private startErrorMonitor;
|
|
199
199
|
/** Evaluate one pane snapshot. Kept synchronous so state-machine edges are unit-testable. */
|
|
200
200
|
private evaluateErrorPatterns;
|
|
201
|
+
/**
|
|
202
|
+
* Notification text for a detected pattern. `formatMessage` patterns build it
|
|
203
|
+
* from the match so the user gets the specifics (e.g. which period and what
|
|
204
|
+
* percentage remains) instead of a generic "running low".
|
|
205
|
+
*
|
|
206
|
+
* Uses the LAST match in the pane: an older warning may still be scrolled up
|
|
207
|
+
* (10% earlier, 5% now), and the newest one is the one worth reporting.
|
|
208
|
+
*/
|
|
209
|
+
private resolveErrorMessage;
|
|
201
210
|
/**
|
|
202
211
|
* Interrupt the CLI's current generation (cancel button / `/cancel`).
|
|
203
212
|
* Direct tmux key event (not a paste) so it registers as the interrupt key.
|
|
204
213
|
* kiro-cli interrupts on Ctrl+C; the others (claude-code, codex, …) on Escape.
|
|
205
214
|
*/
|
|
206
215
|
sendEscape(): Promise<void>;
|
|
216
|
+
/** Send the backend-specific graceful quit command/key sequence. */
|
|
217
|
+
private sendQuitSequence;
|
|
207
218
|
stop(): Promise<void>;
|
|
208
219
|
getHangDetector(): HangDetector | null;
|
|
209
220
|
getInstanceState(): InstanceState | "paused";
|
package/dist/daemon.js
CHANGED
|
@@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
import { createHash, randomBytes } from "node:crypto";
|
|
5
5
|
import { EventEmitter } from "node:events";
|
|
6
6
|
import { clearPausedMarker, writePausedMarker } from "./pause-marker.js";
|
|
7
|
-
import { TmuxManager } from "./tmux-manager.js";
|
|
7
|
+
import { TmuxManager, resolveTmuxLogicalSize } from "./tmux-manager.js";
|
|
8
8
|
import { TranscriptMonitor } from "./transcript-monitor.js";
|
|
9
9
|
import { ContextGuardian } from "./context-guardian.js";
|
|
10
10
|
import { IpcServer } from "./channel/ipc-bridge.js";
|
|
@@ -543,7 +543,7 @@ export class Daemon extends EventEmitter {
|
|
|
543
543
|
});
|
|
544
544
|
// 2. Tmux — ensure session, create window if not alive
|
|
545
545
|
await TmuxManager.ensureSession(this.tmuxSessionName);
|
|
546
|
-
this.tmux = new TmuxManager(this.tmuxSessionName, "");
|
|
546
|
+
this.tmux = new TmuxManager(this.tmuxSessionName, "", resolveTmuxLogicalSize(this.config.terminal));
|
|
547
547
|
// Strategy A: always start fresh Claude window (MCP server has no reconnection)
|
|
548
548
|
// Kill any existing window from previous run
|
|
549
549
|
const windowIdFile = join(this.instanceDir, "window-id");
|
|
@@ -1101,11 +1101,35 @@ export class Daemon extends EventEmitter {
|
|
|
1101
1101
|
this.lastErrorNotifiedAt.set(key, now);
|
|
1102
1102
|
if (ep.action === "failover")
|
|
1103
1103
|
this.lastFailoverAt = now;
|
|
1104
|
-
|
|
1105
|
-
this.
|
|
1104
|
+
const message = this.resolveErrorMessage(pane, ep);
|
|
1105
|
+
this.logger.warn({ errorType: ep.type, action: ep.action }, `PTY error detected: ${message}`);
|
|
1106
|
+
this.emit("pty_error", { name: this.name, ...ep, message });
|
|
1106
1107
|
break; // Only handle first unsuppressed new error per scan
|
|
1107
1108
|
}
|
|
1108
1109
|
}
|
|
1110
|
+
/**
|
|
1111
|
+
* Notification text for a detected pattern. `formatMessage` patterns build it
|
|
1112
|
+
* from the match so the user gets the specifics (e.g. which period and what
|
|
1113
|
+
* percentage remains) instead of a generic "running low".
|
|
1114
|
+
*
|
|
1115
|
+
* Uses the LAST match in the pane: an older warning may still be scrolled up
|
|
1116
|
+
* (10% earlier, 5% now), and the newest one is the one worth reporting.
|
|
1117
|
+
*/
|
|
1118
|
+
resolveErrorMessage(pane, ep) {
|
|
1119
|
+
if (!ep.formatMessage)
|
|
1120
|
+
return ep.message;
|
|
1121
|
+
try {
|
|
1122
|
+
const flags = ep.pattern.flags.includes("g") ? ep.pattern.flags : ep.pattern.flags + "g";
|
|
1123
|
+
const matches = [...pane.matchAll(new RegExp(ep.pattern.source, flags))];
|
|
1124
|
+
const last = matches[matches.length - 1];
|
|
1125
|
+
return last ? ep.formatMessage(last) : ep.message;
|
|
1126
|
+
}
|
|
1127
|
+
catch (err) {
|
|
1128
|
+
// A bad formatter must not swallow the notification entirely.
|
|
1129
|
+
this.logger.debug({ err, errorType: ep.type }, "formatMessage failed — using static message");
|
|
1130
|
+
return ep.message;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1109
1133
|
/**
|
|
1110
1134
|
* Interrupt the CLI's current generation (cancel button / `/cancel`).
|
|
1111
1135
|
* Direct tmux key event (not a paste) so it registers as the interrupt key.
|
|
@@ -1115,6 +1139,30 @@ export class Daemon extends EventEmitter {
|
|
|
1115
1139
|
const cancelKey = this.backend?.getCancelKey() ?? "Escape";
|
|
1116
1140
|
await this.tmux?.sendSpecialKey(cancelKey);
|
|
1117
1141
|
}
|
|
1142
|
+
/** Send the backend-specific graceful quit command/key sequence. */
|
|
1143
|
+
async sendQuitSequence() {
|
|
1144
|
+
if (!this.tmux || !this.backend)
|
|
1145
|
+
return false;
|
|
1146
|
+
const quitCmd = this.backend.getQuitCommand();
|
|
1147
|
+
const quitKey = this.backend.getQuitKey?.();
|
|
1148
|
+
if (quitCmd) {
|
|
1149
|
+
await this.tmux.sendKeys(quitCmd);
|
|
1150
|
+
// Delay before Enter to prevent tmux server races when instances stop in
|
|
1151
|
+
// parallel (same pattern as pasteText).
|
|
1152
|
+
await new Promise(r => setTimeout(r, 150));
|
|
1153
|
+
await this.tmux.sendSpecialKey("Enter");
|
|
1154
|
+
return true;
|
|
1155
|
+
}
|
|
1156
|
+
if (!quitKey)
|
|
1157
|
+
return false;
|
|
1158
|
+
const presses = Math.max(1, Math.floor(this.backend.getQuitKeyPresses?.() ?? 1));
|
|
1159
|
+
for (let i = 0; i < presses; i++) {
|
|
1160
|
+
await this.tmux.sendSpecialKey(quitKey);
|
|
1161
|
+
if (i + 1 < presses)
|
|
1162
|
+
await new Promise(r => setTimeout(r, 250));
|
|
1163
|
+
}
|
|
1164
|
+
return true;
|
|
1165
|
+
}
|
|
1118
1166
|
async stop() {
|
|
1119
1167
|
this.logger.info("Stopping daemon instance");
|
|
1120
1168
|
this.freezeRuntimeMonitors();
|
|
@@ -1134,20 +1182,8 @@ export class Daemon extends EventEmitter {
|
|
|
1134
1182
|
this.saveSessionId();
|
|
1135
1183
|
this.healthCheckPaused = true;
|
|
1136
1184
|
let killed = false;
|
|
1137
|
-
const
|
|
1138
|
-
|
|
1139
|
-
if (quitCmd) {
|
|
1140
|
-
await this.tmux.sendKeys(quitCmd);
|
|
1141
|
-
// Delay before Enter to prevent tmux server race when multiple
|
|
1142
|
-
// instances stop in parallel (same pattern as pasteText).
|
|
1143
|
-
await new Promise(r => setTimeout(r, 150));
|
|
1144
|
-
await this.tmux.sendSpecialKey("Enter");
|
|
1145
|
-
}
|
|
1146
|
-
else if (quitKey) {
|
|
1147
|
-
// Some CLIs quit via a key chord (e.g. grok Ctrl+Q), not a typed command.
|
|
1148
|
-
await this.tmux.sendSpecialKey(quitKey);
|
|
1149
|
-
}
|
|
1150
|
-
if (quitCmd || quitKey) {
|
|
1185
|
+
const quitSent = await this.sendQuitSequence();
|
|
1186
|
+
if (quitSent) {
|
|
1151
1187
|
// Wait up to 3s for graceful exit, polling every 200ms. A healthy CLI
|
|
1152
1188
|
// exits within ~1s; a longer wait just delays the force-kill fallback.
|
|
1153
1189
|
for (let i = 0; i < 15; i++) {
|
|
@@ -1223,19 +1259,7 @@ export class Daemon extends EventEmitter {
|
|
|
1223
1259
|
const transition = (async () => {
|
|
1224
1260
|
try {
|
|
1225
1261
|
this.saveSessionId();
|
|
1226
|
-
|
|
1227
|
-
const quitKey = this.backend?.getQuitKey?.();
|
|
1228
|
-
if (this.tmux) {
|
|
1229
|
-
if (quitCmd) {
|
|
1230
|
-
await this.tmux.sendKeys(quitCmd);
|
|
1231
|
-
await new Promise(r => setTimeout(r, 150));
|
|
1232
|
-
await this.tmux.sendSpecialKey("Enter");
|
|
1233
|
-
}
|
|
1234
|
-
else if (quitKey) {
|
|
1235
|
-
// Key-chord quit (e.g. grok Ctrl+Q) — no typed command to send.
|
|
1236
|
-
await this.tmux.sendSpecialKey(quitKey);
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1262
|
+
await this.sendQuitSequence();
|
|
1239
1263
|
let exited = false;
|
|
1240
1264
|
for (let i = 0; i < 15; i++) {
|
|
1241
1265
|
await new Promise(r => setTimeout(r, 200));
|
|
@@ -1818,7 +1842,7 @@ export class Daemon extends EventEmitter {
|
|
|
1818
1842
|
const match = windows.find(w => w.name === this.name);
|
|
1819
1843
|
if (!match)
|
|
1820
1844
|
return undefined;
|
|
1821
|
-
this.tmux = new TmuxManager(this.tmuxSessionName, match.id);
|
|
1845
|
+
this.tmux = new TmuxManager(this.tmuxSessionName, match.id, resolveTmuxLogicalSize(this.config.terminal));
|
|
1822
1846
|
writeFileSync(join(this.instanceDir, "window-id"), match.id);
|
|
1823
1847
|
await this.controlClient?.registerWindow(match.id);
|
|
1824
1848
|
this.bindInstanceStateOutputListener(match.id);
|