@songsid/agend 2.1.0-beta.23 → 2.1.0-beta.4
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 +0 -1
- package/README.zh-TW.md +1 -2
- package/dist/access-path.js +3 -3
- package/dist/access-path.js.map +1 -1
- package/dist/agent-endpoint.d.ts +0 -8
- package/dist/agent-endpoint.js +8 -36
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/backend/antigravity.js +2 -3
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/factory.js +1 -5
- package/dist/backend/factory.js.map +1 -1
- package/dist/backend/kiro.js +2 -3
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +2 -12
- package/dist/backend/types.js +0 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +0 -20
- package/dist/channel/adapters/discord.js +11 -69
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.js +1 -4
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/classic-channel-manager.d.ts +1 -6
- package/dist/classic-channel-manager.js +3 -26
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +4 -48
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +1 -50
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +1 -3
- package/dist/config.js +1 -13
- package/dist/config.js.map +1 -1
- package/dist/context-guardian.d.ts +0 -2
- package/dist/context-guardian.js +2 -10
- package/dist/context-guardian.js.map +1 -1
- package/dist/daemon-entry.js +1 -2
- package/dist/daemon-entry.js.map +1 -1
- package/dist/daemon.d.ts +1 -25
- package/dist/daemon.js +30 -156
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-context.d.ts +0 -1
- package/dist/fleet-manager.d.ts +5 -30
- package/dist/fleet-manager.js +106 -312
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -1
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +0 -1
- package/dist/instance-lifecycle.d.ts +1 -2
- package/dist/instance-lifecycle.js +4 -15
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/locale.js +0 -2
- package/dist/locale.js.map +1 -1
- package/dist/logger.d.ts +0 -6
- package/dist/logger.js +9 -28
- package/dist/logger.js.map +1 -1
- package/dist/outbound-handlers.d.ts +0 -3
- package/dist/outbound-handlers.js +0 -25
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +1 -2
- package/dist/outbound-schemas.js +1 -1
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/settings-api.d.ts +2 -17
- package/dist/settings-api.js +8 -105
- package/dist/settings-api.js.map +1 -1
- package/dist/setup-wizard.js +0 -8
- package/dist/setup-wizard.js.map +1 -1
- package/dist/statusline-watcher.d.ts +1 -1
- package/dist/statusline-watcher.js +2 -3
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/tmux-manager.d.ts +1 -1
- package/dist/tmux-manager.js.map +1 -1
- package/dist/topic-commands.d.ts +1 -14
- package/dist/topic-commands.js +23 -89
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-monitor.js +0 -2
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/types.d.ts +1 -16
- package/dist/ui/dashboard.html +2 -2
- package/dist/ui/settings.html +40 -251
- package/dist/web-api.d.ts +0 -1
- package/dist/web-api.js +15 -24
- package/dist/web-api.js.map +1 -1
- package/package.json +1 -2
- package/dist/backend/grok.d.ts +0 -51
- package/dist/backend/grok.js +0 -280
- package/dist/backend/grok.js.map +0 -1
package/dist/config.js
CHANGED
|
@@ -40,7 +40,7 @@ export const DEFAULT_DAILY_SUMMARY = {
|
|
|
40
40
|
minute: 0,
|
|
41
41
|
};
|
|
42
42
|
export const DEFAULT_INSTANCE_CONFIG = {
|
|
43
|
-
auto_pause_after:
|
|
43
|
+
auto_pause_after: 10080, // default: 1 week (10080 minutes = 60 * 24 * 7)
|
|
44
44
|
restart_policy: {
|
|
45
45
|
max_retries: 10,
|
|
46
46
|
backoff: "exponential",
|
|
@@ -117,16 +117,4 @@ export function loadFleetConfig(configPath) {
|
|
|
117
117
|
health_port: parsed.health_port,
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
|
-
/** Read the user-authored config without applying defaults or normalization. */
|
|
121
|
-
export function loadRawFleetConfig(configPath) {
|
|
122
|
-
if (!existsSync(configPath))
|
|
123
|
-
return {};
|
|
124
|
-
const raw = readFileSync(configPath, "utf-8");
|
|
125
|
-
// Match loadFleetConfig(): preserve platform IDs that exceed MAX_SAFE_INTEGER.
|
|
126
|
-
const safeRaw = raw.replace(/(?<=:\s+|[-]\s+)(\d{16,})(?=\s*$)/gm, (_, d) => `"${d}"`);
|
|
127
|
-
const parsed = yaml.load(safeRaw);
|
|
128
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
129
|
-
? parsed
|
|
130
|
-
: {};
|
|
131
|
-
}
|
|
132
120
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGlF,SAAS,gBAAgB,CAAmB,MAAS,EAAE,MAAkB;IACvE,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAA6B,CAAC;IACxD,MAAM,YAAY,GAAG,MAAiC,CAAC;IAEvD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,IACE,SAAS,KAAK,IAAI;YAClB,OAAO,SAAS,KAAK,QAAQ;YAC7B,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACzB,OAAO,SAAS,KAAK,QAAQ;YAC7B,SAAS,KAAK,IAAI;YAClB,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EACzB,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAC5B,SAAmB,EACnB,SAA4B,CAC7B,CAAC;QACJ,CAAC;aAAM,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,MAAsB,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,kBAAkB,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAoB;IACjD,eAAe,EAAE,CAAC,EAAE,eAAe;IACnC,kBAAkB,EAAE,EAAE;IACtB,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ;CAC3D,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAuB;IACvD,OAAO,EAAE,IAAI;IACb,eAAe,EAAE,EAAE;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAuB;IACvD,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,CAAC;CACV,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAA8C;IAChF,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,8 +18,6 @@ export declare class ContextGuardian extends EventEmitter {
|
|
|
18
18
|
private logger;
|
|
19
19
|
private statusFilePath;
|
|
20
20
|
private consecutiveReadFailures;
|
|
21
|
-
private watching;
|
|
22
|
-
private readonly onStatusFileChange;
|
|
23
21
|
constructor(_config: GuardianConfig, logger: Logger, statusFilePath: string);
|
|
24
22
|
startWatching(): void;
|
|
25
23
|
private readAndCheck;
|
package/dist/context-guardian.js
CHANGED
|
@@ -16,8 +16,6 @@ export class ContextGuardian extends EventEmitter {
|
|
|
16
16
|
logger;
|
|
17
17
|
statusFilePath;
|
|
18
18
|
consecutiveReadFailures = 0;
|
|
19
|
-
watching = false;
|
|
20
|
-
onStatusFileChange = () => this.readAndCheck();
|
|
21
19
|
constructor(_config, logger, statusFilePath) {
|
|
22
20
|
super();
|
|
23
21
|
this._config = _config;
|
|
@@ -25,11 +23,8 @@ export class ContextGuardian extends EventEmitter {
|
|
|
25
23
|
this.statusFilePath = statusFilePath;
|
|
26
24
|
}
|
|
27
25
|
startWatching() {
|
|
28
|
-
if (this.watching)
|
|
29
|
-
return;
|
|
30
|
-
this.watching = true;
|
|
31
26
|
this.logger.debug({ path: this.statusFilePath }, "Watching status line file");
|
|
32
|
-
watchFile(this.statusFilePath, { interval: 2000 }, this.
|
|
27
|
+
watchFile(this.statusFilePath, { interval: 2000 }, () => this.readAndCheck());
|
|
33
28
|
}
|
|
34
29
|
readAndCheck() {
|
|
35
30
|
try {
|
|
@@ -72,10 +67,7 @@ export class ContextGuardian extends EventEmitter {
|
|
|
72
67
|
}
|
|
73
68
|
}
|
|
74
69
|
stop() {
|
|
75
|
-
|
|
76
|
-
return;
|
|
77
|
-
unwatchFile(this.statusFilePath, this.onStatusFileChange);
|
|
78
|
-
this.watching = false;
|
|
70
|
+
unwatchFile(this.statusFilePath);
|
|
79
71
|
}
|
|
80
72
|
}
|
|
81
73
|
//# sourceMappingURL=context-guardian.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-guardian.js","sourceRoot":"","sources":["../src/context-guardian.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAM3E;;;;;;;;;;GAUG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;
|
|
1
|
+
{"version":3,"file":"context-guardian.js","sourceRoot":"","sources":["../src/context-guardian.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon-entry.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Daemon } from "./daemon.js";
|
|
2
|
-
import { createLogger } from "./logger.js";
|
|
3
2
|
const args = process.argv.slice(2);
|
|
4
3
|
function getArg(name) {
|
|
5
4
|
const idx = args.indexOf(name);
|
|
@@ -16,7 +15,7 @@ catch (err) {
|
|
|
16
15
|
process.exit(1);
|
|
17
16
|
}
|
|
18
17
|
const topicMode = args.includes("--topic-mode");
|
|
19
|
-
const daemon = new Daemon(name, config, instanceDir, topicMode
|
|
18
|
+
const daemon = new Daemon(name, config, instanceDir, topicMode);
|
|
20
19
|
daemon.start().catch((err) => {
|
|
21
20
|
console.error("Daemon failed:", err);
|
|
22
21
|
process.exit(1);
|
package/dist/daemon-entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-entry.js","sourceRoot":"","sources":["../src/daemon-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"daemon-entry.js","sourceRoot":"","sources":["../src/daemon-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,SAAS,MAAM,CAAC,IAAY;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAClC,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAC7C,IAAI,MAAsB,CAAC;AAC3B,IAAI,CAAC;IACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAC1C,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CAAC,kCAAmC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AAChD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;AAEhE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC3B,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;IAC1B,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;AACF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC"}
|
package/dist/daemon.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
2
|
import type { InstanceConfig, RotationSnapshot } from "./types.js";
|
|
3
|
-
import type { Logger } from "./logger.js";
|
|
4
3
|
import { MessageBus } from "./channel/message-bus.js";
|
|
5
4
|
import type { CliBackend, InstanceState, InstanceStateSnapshot } from "./backend/types.js";
|
|
6
5
|
import { HangDetector } from "./hang-detector.js";
|
|
@@ -39,20 +38,6 @@ export declare class PaneStateMachine {
|
|
|
39
38
|
observe(pane: string, now?: number): InstanceStateSnapshot;
|
|
40
39
|
snapshot(now?: number): InstanceStateSnapshot;
|
|
41
40
|
}
|
|
42
|
-
/** Tracks whether an inbound arrived after the most recent confirmed idle prompt. */
|
|
43
|
-
export declare class PendingWorkTracker {
|
|
44
|
-
private lastInboundAt;
|
|
45
|
-
private lastIdleAt;
|
|
46
|
-
private sequence;
|
|
47
|
-
private lastInboundOrder;
|
|
48
|
-
private lastIdleOrder;
|
|
49
|
-
constructor(now?: number);
|
|
50
|
-
recordInbound(now?: number): void;
|
|
51
|
-
recordIdle(now?: number): void;
|
|
52
|
-
hasPendingWork(): boolean;
|
|
53
|
-
}
|
|
54
|
-
/** Redact likely credentials and control sequences before pane text reaches logs. */
|
|
55
|
-
export declare function sanitizePaneTail(pane: string, lineCount?: number): string[];
|
|
56
41
|
export declare class Daemon extends EventEmitter {
|
|
57
42
|
private name;
|
|
58
43
|
private config;
|
|
@@ -72,7 +57,6 @@ export declare class Daemon extends EventEmitter {
|
|
|
72
57
|
private pendingIpcRequests;
|
|
73
58
|
private lastChatId;
|
|
74
59
|
private lastThreadId;
|
|
75
|
-
private lastAdapterId;
|
|
76
60
|
private pendingAckMessage;
|
|
77
61
|
private toolStatusMessageId;
|
|
78
62
|
private toolStatusLines;
|
|
@@ -97,7 +81,6 @@ export declare class Daemon extends EventEmitter {
|
|
|
97
81
|
private hangDetector;
|
|
98
82
|
private instanceState;
|
|
99
83
|
private instanceStateMachine;
|
|
100
|
-
private pendingWork;
|
|
101
84
|
private instanceStateMonitorTimer;
|
|
102
85
|
private statePollInFlight;
|
|
103
86
|
private autoPauseController;
|
|
@@ -116,8 +99,6 @@ export declare class Daemon extends EventEmitter {
|
|
|
116
99
|
private lastBuiltInstructions;
|
|
117
100
|
private pasteQueueDepth;
|
|
118
101
|
private errorMonitorTimer;
|
|
119
|
-
/** Prevent in-flight monitor callbacks from re-arming after a pause. */
|
|
120
|
-
private runtimeMonitorsFrozen;
|
|
121
102
|
private errorWaitingForRecovery;
|
|
122
103
|
private errorDetectedAt;
|
|
123
104
|
/** Whether this instance is in an abnormal error state (auto-pause is normal). */
|
|
@@ -133,7 +114,7 @@ export declare class Daemon extends EventEmitter {
|
|
|
133
114
|
private static ERROR_COOLDOWN_MS;
|
|
134
115
|
private lastErrorCount;
|
|
135
116
|
private lastDetectedErrorType;
|
|
136
|
-
constructor(name: string, config: InstanceConfig, instanceDir: string, topicMode?: boolean, backend?: CliBackend | undefined, controlClient?: TmuxControlClient | undefined
|
|
117
|
+
constructor(name: string, config: InstanceConfig, instanceDir: string, topicMode?: boolean, backend?: CliBackend | undefined, controlClient?: TmuxControlClient | undefined);
|
|
137
118
|
start(): Promise<void>;
|
|
138
119
|
private startHealthCheck;
|
|
139
120
|
/**
|
|
@@ -161,11 +142,6 @@ export declare class Daemon extends EventEmitter {
|
|
|
161
142
|
/** Respawn the CLI in the preserved window and block until its prompt is ready. */
|
|
162
143
|
wake(timeoutMs?: number): Promise<void>;
|
|
163
144
|
private startInstanceStateMonitor;
|
|
164
|
-
private handleStuckTransition;
|
|
165
|
-
/** Stop every runtime poller/watcher while preserving IPC and daemon state. */
|
|
166
|
-
private freezeRuntimeMonitors;
|
|
167
|
-
/** Restore the same monitor objects after wake without adding event listeners. */
|
|
168
|
-
private resumeRuntimeMonitors;
|
|
169
145
|
getMessageBus(): MessageBus;
|
|
170
146
|
private summarizeTool;
|
|
171
147
|
private addToolStatus;
|
package/dist/daemon.js
CHANGED
|
@@ -3,6 +3,7 @@ import { mkdirSync, writeFileSync, readFileSync, existsSync, unlinkSync, rmSync,
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { createHash, randomBytes } from "node:crypto";
|
|
5
5
|
import { EventEmitter } from "node:events";
|
|
6
|
+
import { createLogger } from "./logger.js";
|
|
6
7
|
import { TmuxManager } from "./tmux-manager.js";
|
|
7
8
|
import { TranscriptMonitor } from "./transcript-monitor.js";
|
|
8
9
|
import { ContextGuardian } from "./context-guardian.js";
|
|
@@ -114,55 +115,6 @@ export class PaneStateMachine {
|
|
|
114
115
|
};
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
|
-
/** Tracks whether an inbound arrived after the most recent confirmed idle prompt. */
|
|
118
|
-
export class PendingWorkTracker {
|
|
119
|
-
lastInboundAt = 0;
|
|
120
|
-
lastIdleAt;
|
|
121
|
-
sequence = 0;
|
|
122
|
-
lastInboundOrder = 0;
|
|
123
|
-
lastIdleOrder = 0;
|
|
124
|
-
constructor(now = Date.now()) {
|
|
125
|
-
this.lastIdleAt = now;
|
|
126
|
-
}
|
|
127
|
-
recordInbound(now = Date.now()) {
|
|
128
|
-
this.lastInboundAt = now;
|
|
129
|
-
this.lastInboundOrder = ++this.sequence;
|
|
130
|
-
}
|
|
131
|
-
recordIdle(now = Date.now()) {
|
|
132
|
-
// An async pane poll can finish after a newer inbound. Do not let its stale
|
|
133
|
-
// observation clear work which had not arrived when the pane was captured.
|
|
134
|
-
if (now < this.lastInboundAt)
|
|
135
|
-
return;
|
|
136
|
-
this.lastIdleAt = now;
|
|
137
|
-
this.lastIdleOrder = ++this.sequence;
|
|
138
|
-
}
|
|
139
|
-
hasPendingWork() {
|
|
140
|
-
return this.lastInboundOrder > this.lastIdleOrder;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
/** Redact likely credentials and control sequences before pane text reaches logs. */
|
|
144
|
-
export function sanitizePaneTail(pane, lineCount = 5) {
|
|
145
|
-
const secretAssignment = /\b(token|secret|password|passwd|api[_-]?key|authorization)\b\s*[:=]\s*\S+/gi;
|
|
146
|
-
const bearer = /\bBearer\s+\S+/gi;
|
|
147
|
-
const knownToken = /\b(?:sk-[A-Za-z0-9_-]+|ghp_[A-Za-z0-9]+|github_pat_[A-Za-z0-9_]+|AKIA[A-Z0-9]{16})\b/g;
|
|
148
|
-
const jwt = /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g;
|
|
149
|
-
const opaqueSecret = /\b[A-Za-z0-9_+/=-]{32,}\b/g;
|
|
150
|
-
const lines = pane
|
|
151
|
-
.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "")
|
|
152
|
-
.split(/\r?\n/);
|
|
153
|
-
while (lines.length > 0 && /^\s*$/.test(lines[lines.length - 1]))
|
|
154
|
-
lines.pop();
|
|
155
|
-
return lines
|
|
156
|
-
.slice(-lineCount)
|
|
157
|
-
.map(line => line
|
|
158
|
-
.replace(bearer, "Bearer [REDACTED]")
|
|
159
|
-
.replace(secretAssignment, "$1=[REDACTED]")
|
|
160
|
-
.replace(knownToken, "[REDACTED]")
|
|
161
|
-
.replace(jwt, "[REDACTED]")
|
|
162
|
-
.replace(opaqueSecret, "[REDACTED]")
|
|
163
|
-
.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "")
|
|
164
|
-
.slice(0, 200));
|
|
165
|
-
}
|
|
166
118
|
export class Daemon extends EventEmitter {
|
|
167
119
|
name;
|
|
168
120
|
config;
|
|
@@ -183,7 +135,6 @@ export class Daemon extends EventEmitter {
|
|
|
183
135
|
// Track chatId/threadId from inbound messages for automatic outbound routing
|
|
184
136
|
lastChatId;
|
|
185
137
|
lastThreadId;
|
|
186
|
-
lastAdapterId;
|
|
187
138
|
// Pending ack: react 🫡 on first transcript activity after receiving a message
|
|
188
139
|
pendingAckMessage = null;
|
|
189
140
|
// Tool status tracking for channel adapter
|
|
@@ -213,7 +164,6 @@ export class Daemon extends EventEmitter {
|
|
|
213
164
|
hangDetector = null;
|
|
214
165
|
instanceState = "idle";
|
|
215
166
|
instanceStateMachine = null;
|
|
216
|
-
pendingWork = new PendingWorkTracker();
|
|
217
167
|
instanceStateMonitorTimer = null;
|
|
218
168
|
statePollInFlight = false;
|
|
219
169
|
autoPauseController;
|
|
@@ -239,8 +189,6 @@ export class Daemon extends EventEmitter {
|
|
|
239
189
|
pasteQueueDepth = 0;
|
|
240
190
|
// PTY error pattern monitoring
|
|
241
191
|
errorMonitorTimer = null;
|
|
242
|
-
/** Prevent in-flight monitor callbacks from re-arming after a pause. */
|
|
243
|
-
runtimeMonitorsFrozen = false;
|
|
244
192
|
errorWaitingForRecovery = false; // true = error detected, waiting for ready pattern
|
|
245
193
|
errorDetectedAt = 0;
|
|
246
194
|
/** Whether this instance is in an abnormal error state (auto-pause is normal). */
|
|
@@ -267,7 +215,7 @@ export class Daemon extends EventEmitter {
|
|
|
267
215
|
// still registers as new (prevents the old hash-dedup's permanent suppression).
|
|
268
216
|
lastErrorCount = new Map();
|
|
269
217
|
lastDetectedErrorType = null;
|
|
270
|
-
constructor(name, config, instanceDir, topicMode = false, backend, controlClient
|
|
218
|
+
constructor(name, config, instanceDir, topicMode = false, backend, controlClient) {
|
|
271
219
|
super();
|
|
272
220
|
this.name = name;
|
|
273
221
|
this.config = config;
|
|
@@ -275,13 +223,11 @@ export class Daemon extends EventEmitter {
|
|
|
275
223
|
this.topicMode = topicMode;
|
|
276
224
|
this.backend = backend;
|
|
277
225
|
this.controlClient = controlClient;
|
|
278
|
-
|
|
279
|
-
throw new Error("Daemon requires a shared root logger");
|
|
280
|
-
this.logger = rootLogger.child({ instance: name }, { level: config.log_level });
|
|
226
|
+
this.logger = createLogger(config.log_level);
|
|
281
227
|
this.tmuxSessionName = getTmuxSession();
|
|
282
228
|
this.messageBus = new MessageBus();
|
|
283
229
|
this.messageBus.setLogger(this.logger);
|
|
284
|
-
const autoPauseMinutes = typeof config.auto_pause_after === "number" ? config.auto_pause_after :
|
|
230
|
+
const autoPauseMinutes = typeof config.auto_pause_after === "number" ? config.auto_pause_after : 10080; // default: 1 week
|
|
285
231
|
this.autoPauseController = new AutoPauseController(Math.max(0, autoPauseMinutes) * 60_000);
|
|
286
232
|
}
|
|
287
233
|
async start() {
|
|
@@ -317,7 +263,6 @@ export class Daemon extends EventEmitter {
|
|
|
317
263
|
if (saved.chatId) {
|
|
318
264
|
this.lastChatId = saved.chatId;
|
|
319
265
|
this.lastThreadId = saved.threadId || undefined;
|
|
320
|
-
this.lastAdapterId = saved.adapterId || undefined;
|
|
321
266
|
}
|
|
322
267
|
}
|
|
323
268
|
}
|
|
@@ -576,18 +521,11 @@ export class Daemon extends EventEmitter {
|
|
|
576
521
|
this.logger.info(`${this.name} ready`);
|
|
577
522
|
}
|
|
578
523
|
startHealthCheck() {
|
|
579
|
-
if (this.runtimeMonitorsFrozen || this.healthCheckTimer)
|
|
580
|
-
return;
|
|
581
524
|
const { max_retries, backoff, reset_after } = this.config.restart_policy;
|
|
582
525
|
if (max_retries <= 0)
|
|
583
526
|
return; // restart disabled
|
|
584
527
|
const scheduleNext = () => {
|
|
585
|
-
if (this.runtimeMonitorsFrozen || this.healthCheckTimer)
|
|
586
|
-
return;
|
|
587
528
|
this.healthCheckTimer = setTimeout(async () => {
|
|
588
|
-
this.healthCheckTimer = null;
|
|
589
|
-
if (this.runtimeMonitorsFrozen)
|
|
590
|
-
return;
|
|
591
529
|
// Instance directory removed externally (e.g. `rm -rf ~/.agend/instances/<name>`).
|
|
592
530
|
// Stop the loop permanently — otherwise every tick triggers a respawn, whose
|
|
593
531
|
// writeRotationSnapshot fails with ENOENT and gets caught as "Failed to respawn",
|
|
@@ -838,8 +776,6 @@ export class Daemon extends EventEmitter {
|
|
|
838
776
|
* (ready pattern visible), it goes back to monitoring for new errors.
|
|
839
777
|
*/
|
|
840
778
|
startErrorMonitor() {
|
|
841
|
-
if (this.runtimeMonitorsFrozen || this.errorMonitorTimer)
|
|
842
|
-
return;
|
|
843
779
|
const patterns = this.backend?.getErrorPatterns?.() ?? [];
|
|
844
780
|
const dialogs = this.backend?.getRuntimeDialogs?.() ?? [];
|
|
845
781
|
if (!patterns.length && !dialogs.length)
|
|
@@ -959,13 +895,26 @@ export class Daemon extends EventEmitter {
|
|
|
959
895
|
}
|
|
960
896
|
async stop() {
|
|
961
897
|
this.logger.info("Stopping daemon instance");
|
|
962
|
-
this.
|
|
898
|
+
if (this.healthCheckTimer) {
|
|
899
|
+
clearTimeout(this.healthCheckTimer);
|
|
900
|
+
this.healthCheckTimer = null;
|
|
901
|
+
}
|
|
902
|
+
if (this.errorMonitorTimer) {
|
|
903
|
+
clearInterval(this.errorMonitorTimer);
|
|
904
|
+
this.errorMonitorTimer = null;
|
|
905
|
+
}
|
|
906
|
+
if (this.instanceStateMonitorTimer) {
|
|
907
|
+
clearInterval(this.instanceStateMonitorTimer);
|
|
908
|
+
this.instanceStateMonitorTimer = null;
|
|
909
|
+
}
|
|
963
910
|
if (this.toolStatusDebounce) {
|
|
964
911
|
clearTimeout(this.toolStatusDebounce);
|
|
965
912
|
this.toolStatusDebounce = null;
|
|
966
913
|
}
|
|
967
914
|
this.pendingIpcRequests.clear();
|
|
968
915
|
this.hangDetector?.stop();
|
|
916
|
+
this.transcriptMonitor?.stop();
|
|
917
|
+
this.guardian?.stop();
|
|
969
918
|
if (this.adapter)
|
|
970
919
|
await this.adapter.stop();
|
|
971
920
|
// Notify MCP servers of graceful shutdown (prevents reconnect attempts)
|
|
@@ -977,19 +926,12 @@ export class Daemon extends EventEmitter {
|
|
|
977
926
|
this.healthCheckPaused = true;
|
|
978
927
|
let killed = false;
|
|
979
928
|
const quitCmd = this.backend?.getQuitCommand();
|
|
980
|
-
const quitKey = this.backend?.getQuitKey?.();
|
|
981
929
|
if (quitCmd) {
|
|
982
930
|
await this.tmux.sendKeys(quitCmd);
|
|
983
931
|
// Delay before Enter to prevent tmux server race when multiple
|
|
984
932
|
// instances stop in parallel (same pattern as pasteText).
|
|
985
933
|
await new Promise(r => setTimeout(r, 150));
|
|
986
934
|
await this.tmux.sendSpecialKey("Enter");
|
|
987
|
-
}
|
|
988
|
-
else if (quitKey) {
|
|
989
|
-
// Some CLIs quit via a key chord (e.g. grok Ctrl+Q), not a typed command.
|
|
990
|
-
await this.tmux.sendSpecialKey(quitKey);
|
|
991
|
-
}
|
|
992
|
-
if (quitCmd || quitKey) {
|
|
993
935
|
// Wait up to 3s for graceful exit, polling every 200ms. A healthy CLI
|
|
994
936
|
// exits within ~1s; a longer wait just delays the force-kill fallback.
|
|
995
937
|
for (let i = 0; i < 15; i++) {
|
|
@@ -1065,22 +1007,14 @@ export class Daemon extends EventEmitter {
|
|
|
1065
1007
|
}
|
|
1066
1008
|
this.pauseWakeState = "pausing";
|
|
1067
1009
|
this.healthCheckPaused = true;
|
|
1068
|
-
this.freezeRuntimeMonitors();
|
|
1069
1010
|
const transition = (async () => {
|
|
1070
1011
|
try {
|
|
1071
1012
|
this.saveSessionId();
|
|
1072
1013
|
const quitCmd = this.backend?.getQuitCommand();
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
await new Promise(r => setTimeout(r, 150));
|
|
1078
|
-
await this.tmux.sendSpecialKey("Enter");
|
|
1079
|
-
}
|
|
1080
|
-
else if (quitKey) {
|
|
1081
|
-
// Key-chord quit (e.g. grok Ctrl+Q) — no typed command to send.
|
|
1082
|
-
await this.tmux.sendSpecialKey(quitKey);
|
|
1083
|
-
}
|
|
1014
|
+
if (quitCmd && this.tmux) {
|
|
1015
|
+
await this.tmux.sendKeys(quitCmd);
|
|
1016
|
+
await new Promise(r => setTimeout(r, 150));
|
|
1017
|
+
await this.tmux.sendSpecialKey("Enter");
|
|
1084
1018
|
}
|
|
1085
1019
|
let exited = false;
|
|
1086
1020
|
for (let i = 0; i < 15; i++) {
|
|
@@ -1119,7 +1053,6 @@ export class Daemon extends EventEmitter {
|
|
|
1119
1053
|
this.pauseWakeState = "active";
|
|
1120
1054
|
this.healthCheckPaused = false;
|
|
1121
1055
|
this.pauseRequested = false;
|
|
1122
|
-
this.resumeRuntimeMonitors();
|
|
1123
1056
|
throw err;
|
|
1124
1057
|
}
|
|
1125
1058
|
})();
|
|
@@ -1172,7 +1105,6 @@ export class Daemon extends EventEmitter {
|
|
|
1172
1105
|
}
|
|
1173
1106
|
catch { }
|
|
1174
1107
|
this.transcriptMonitor?.resetOffset();
|
|
1175
|
-
this.resumeRuntimeMonitors();
|
|
1176
1108
|
this.logger.info("Instance auto-woke");
|
|
1177
1109
|
this.ipcServer?.broadcast({
|
|
1178
1110
|
type: "instance_state", instanceName: this.name, state: this.instanceState, pausedAt: null,
|
|
@@ -1192,7 +1124,7 @@ export class Daemon extends EventEmitter {
|
|
|
1192
1124
|
}
|
|
1193
1125
|
}
|
|
1194
1126
|
startInstanceStateMonitor() {
|
|
1195
|
-
if (
|
|
1127
|
+
if (!this.tmux || !this.backend || this.instanceStateMonitorTimer)
|
|
1196
1128
|
return;
|
|
1197
1129
|
const rawConfig = this.config.hang_detector;
|
|
1198
1130
|
const timeoutMinutes = rawConfig?.timeout_minutes;
|
|
@@ -1202,8 +1134,7 @@ export class Daemon extends EventEmitter {
|
|
|
1202
1134
|
const pollIntervalMs = typeof rawConfig?.poll_interval_ms === "number" && rawConfig.poll_interval_ms > 0
|
|
1203
1135
|
? rawConfig.poll_interval_ms
|
|
1204
1136
|
: DEFAULT_STATE_POLL_INTERVAL_MS;
|
|
1205
|
-
|
|
1206
|
-
this.instanceStateMachine = new PaneStateMachine(readyPattern, stuckTimeoutMs);
|
|
1137
|
+
this.instanceStateMachine = new PaneStateMachine(this.backend.getReadyPattern(), stuckTimeoutMs);
|
|
1207
1138
|
const poll = async () => {
|
|
1208
1139
|
if (!this.tmux || this.spawning || this.statePollInFlight)
|
|
1209
1140
|
return;
|
|
@@ -1216,11 +1147,6 @@ export class Daemon extends EventEmitter {
|
|
|
1216
1147
|
const previous = this.instanceState;
|
|
1217
1148
|
const snapshot = this.instanceStateMachine.observe(pane);
|
|
1218
1149
|
this.instanceState = snapshot.state;
|
|
1219
|
-
// Only a transition back to idle completes pending work. Repeated idle
|
|
1220
|
-
// polls between enqueue and paste must not clear a newly-recorded inbound.
|
|
1221
|
-
if (snapshot.state === "idle" && previous !== "idle") {
|
|
1222
|
-
this.pendingWork.recordIdle(snapshot.observedAt);
|
|
1223
|
-
}
|
|
1224
1150
|
if (snapshot.state !== previous) {
|
|
1225
1151
|
this.logger.info({
|
|
1226
1152
|
previousState: previous,
|
|
@@ -1232,7 +1158,7 @@ export class Daemon extends EventEmitter {
|
|
|
1232
1158
|
// Emit exactly once per transition into stuck. Further notifications
|
|
1233
1159
|
// require observable progress (working) or a ready prompt (idle) first.
|
|
1234
1160
|
if (snapshot.state === "stuck") {
|
|
1235
|
-
this.
|
|
1161
|
+
this.hangDetector?.emit("hang");
|
|
1236
1162
|
}
|
|
1237
1163
|
}
|
|
1238
1164
|
if (snapshot.state !== "idle")
|
|
@@ -1254,54 +1180,6 @@ export class Daemon extends EventEmitter {
|
|
|
1254
1180
|
void poll();
|
|
1255
1181
|
this.instanceStateMonitorTimer = setInterval(() => { void poll(); }, pollIntervalMs);
|
|
1256
1182
|
}
|
|
1257
|
-
handleStuckTransition(pane, snapshot, readyPattern) {
|
|
1258
|
-
const deterministicReadyPattern = new RegExp(readyPattern.source, readyPattern.flags.replace(/[gy]/g, ""));
|
|
1259
|
-
const diagnostic = {
|
|
1260
|
-
backend: this.backend?.binaryName ?? this.config.backend ?? "unknown",
|
|
1261
|
-
paneTail: sanitizePaneTail(pane),
|
|
1262
|
-
readyPattern: readyPattern.toString(),
|
|
1263
|
-
readyMatched: deterministicReadyPattern.test(pane),
|
|
1264
|
-
unchangedForMs: snapshot.unchangedForMs,
|
|
1265
|
-
pendingWork: this.pendingWork.hasPendingWork(),
|
|
1266
|
-
};
|
|
1267
|
-
if (!diagnostic.pendingWork) {
|
|
1268
|
-
this.logger.debug(diagnostic, "Suppressing stuck notification without pending work");
|
|
1269
|
-
return;
|
|
1270
|
-
}
|
|
1271
|
-
this.logger.warn(diagnostic, "Instance pane stuck with pending work");
|
|
1272
|
-
this.hangDetector?.emit("hang", { unchangedForMs: snapshot.unchangedForMs });
|
|
1273
|
-
}
|
|
1274
|
-
/** Stop every runtime poller/watcher while preserving IPC and daemon state. */
|
|
1275
|
-
freezeRuntimeMonitors() {
|
|
1276
|
-
this.runtimeMonitorsFrozen = true;
|
|
1277
|
-
if (this.healthCheckTimer) {
|
|
1278
|
-
clearTimeout(this.healthCheckTimer);
|
|
1279
|
-
this.healthCheckTimer = null;
|
|
1280
|
-
}
|
|
1281
|
-
if (this.errorMonitorTimer) {
|
|
1282
|
-
clearInterval(this.errorMonitorTimer);
|
|
1283
|
-
this.errorMonitorTimer = null;
|
|
1284
|
-
}
|
|
1285
|
-
if (this.instanceStateMonitorTimer) {
|
|
1286
|
-
clearInterval(this.instanceStateMonitorTimer);
|
|
1287
|
-
this.instanceStateMonitorTimer = null;
|
|
1288
|
-
}
|
|
1289
|
-
this.transcriptMonitor?.stop();
|
|
1290
|
-
this.guardian?.stop();
|
|
1291
|
-
}
|
|
1292
|
-
/** Restore the same monitor objects after wake without adding event listeners. */
|
|
1293
|
-
resumeRuntimeMonitors() {
|
|
1294
|
-
if (!this.runtimeMonitorsFrozen)
|
|
1295
|
-
return;
|
|
1296
|
-
this.runtimeMonitorsFrozen = false;
|
|
1297
|
-
this.startHealthCheck();
|
|
1298
|
-
if (!this.config.lightweight) {
|
|
1299
|
-
this.transcriptMonitor?.startPolling();
|
|
1300
|
-
this.guardian?.startWatching();
|
|
1301
|
-
this.startErrorMonitor();
|
|
1302
|
-
}
|
|
1303
|
-
this.startInstanceStateMonitor();
|
|
1304
|
-
}
|
|
1305
1183
|
getMessageBus() {
|
|
1306
1184
|
return this.messageBus;
|
|
1307
1185
|
}
|
|
@@ -1380,13 +1258,12 @@ export class Daemon extends EventEmitter {
|
|
|
1380
1258
|
// Remember (and persist) the reply target. Only real channel messages have a
|
|
1381
1259
|
// non-empty chat_id; cross-instance messages have chat_id="" and must NOT
|
|
1382
1260
|
// overwrite it (their reply would otherwise go nowhere).
|
|
1383
|
-
this.updateLastChat(meta.chat_id, meta.thread_id
|
|
1261
|
+
this.updateLastChat(meta.chat_id, meta.thread_id);
|
|
1384
1262
|
if (this.pendingInstructionsUpdate) {
|
|
1385
1263
|
writeFileSync(join(this.instanceDir, "prev-instructions"), this.pendingInstructionsUpdate);
|
|
1386
1264
|
this.pendingInstructionsUpdate = undefined;
|
|
1387
1265
|
}
|
|
1388
1266
|
this.hangDetector?.recordInbound();
|
|
1389
|
-
this.pendingWork.recordInbound();
|
|
1390
1267
|
// v3: record user messages for rotation snapshot
|
|
1391
1268
|
this.recordRecentUserMessage(content, meta);
|
|
1392
1269
|
// Format message with metadata prefix for the agent
|
|
@@ -2153,17 +2030,14 @@ export class Daemon extends EventEmitter {
|
|
|
2153
2030
|
* messages) so it never overwrites a real channel target. Persisted to
|
|
2154
2031
|
* last-chat.json so the reply target survives a restart (see start()).
|
|
2155
2032
|
*/
|
|
2156
|
-
updateLastChat(chatId, threadId
|
|
2033
|
+
updateLastChat(chatId, threadId) {
|
|
2157
2034
|
if (!chatId)
|
|
2158
2035
|
return;
|
|
2159
2036
|
this.lastChatId = chatId;
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
this.lastThreadId = threadId || undefined;
|
|
2163
|
-
if (adapterId)
|
|
2164
|
-
this.lastAdapterId = adapterId;
|
|
2037
|
+
if (threadId)
|
|
2038
|
+
this.lastThreadId = threadId;
|
|
2165
2039
|
try {
|
|
2166
|
-
writeFileSync(join(this.instanceDir, "last-chat.json"), JSON.stringify({ chatId: this.lastChatId, threadId: this.lastThreadId
|
|
2040
|
+
writeFileSync(join(this.instanceDir, "last-chat.json"), JSON.stringify({ chatId: this.lastChatId, threadId: this.lastThreadId }));
|
|
2167
2041
|
}
|
|
2168
2042
|
catch { /* best effort */ }
|
|
2169
2043
|
}
|