@suzuke/agend 1.0.0 → 1.1.0
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 +50 -528
- package/README.zh-TW.md +49 -474
- package/dist/channel/adapters/discord.js +1 -1
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/factory.js +2 -2
- package/dist/channel/factory.js.map +1 -1
- package/dist/channel/mcp-tools.js +3 -3
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts +14 -2
- package/dist/daemon.js +119 -46
- package/dist/daemon.js.map +1 -1
- package/dist/export-import.js +2 -2
- package/dist/export-import.js.map +1 -1
- package/dist/fleet-manager.d.ts +1 -0
- package/dist/fleet-manager.js +15 -9
- package/dist/fleet-manager.js.map +1 -1
- package/dist/setup-wizard.js +2 -2
- package/dist/setup-wizard.js.map +1 -1
- package/dist/tmux-control.d.ts +49 -0
- package/dist/tmux-control.js +184 -0
- package/dist/tmux-control.js.map +1 -0
- package/dist/tmux-manager.js +3 -2
- package/dist/tmux-manager.js.map +1 -1
- package/package.json +3 -5
- package/dist/approval/approval-server.d.ts +0 -30
- package/dist/approval/approval-server.js +0 -156
- package/dist/approval/approval-server.js.map +0 -1
- package/dist/approval/tmux-prompt-detector.d.ts +0 -34
- package/dist/approval/tmux-prompt-detector.js +0 -264
- package/dist/approval/tmux-prompt-detector.js.map +0 -1
- package/dist/backend/approval-strategy.d.ts +0 -14
- package/dist/backend/approval-strategy.js +0 -2
- package/dist/backend/approval-strategy.js.map +0 -1
- package/dist/backend/hook-based-approval.d.ts +0 -20
- package/dist/backend/hook-based-approval.js +0 -41
- package/dist/backend/hook-based-approval.js.map +0 -1
- package/dist/container-manager.d.ts +0 -24
- package/dist/container-manager.js +0 -148
- package/dist/container-manager.js.map +0 -1
- package/dist/db.d.ts +0 -10
- package/dist/db.js +0 -43
- package/dist/db.js.map +0 -1
- package/dist/install-recorder.d.ts +0 -30
- package/dist/install-recorder.js +0 -159
- package/dist/install-recorder.js.map +0 -1
- package/dist/meeting/orchestrator.d.ts +0 -30
- package/dist/meeting/orchestrator.js +0 -355
- package/dist/meeting/orchestrator.js.map +0 -1
- package/dist/meeting/prompt-builder.d.ts +0 -12
- package/dist/meeting/prompt-builder.js +0 -96
- package/dist/meeting/prompt-builder.js.map +0 -1
- package/dist/meeting/role-assigner.d.ts +0 -2
- package/dist/meeting/role-assigner.js +0 -25
- package/dist/meeting/role-assigner.js.map +0 -1
- package/dist/meeting/types.d.ts +0 -21
- package/dist/meeting/types.js +0 -2
- package/dist/meeting/types.js.map +0 -1
- package/dist/meeting-manager.d.ts +0 -10
- package/dist/meeting-manager.js +0 -38
- package/dist/meeting-manager.js.map +0 -1
- package/dist/memory-layer.d.ts +0 -13
- package/dist/memory-layer.js +0 -44
- package/dist/memory-layer.js.map +0 -1
- package/dist/plugin/agend/.mcp.json +0 -9
- package/dist/plugin/ccd-channel/.claude-plugin/plugin.json +0 -5
- package/dist/plugin/ccd-channel/.mcp.json +0 -9
- package/dist/process-manager.d.ts +0 -31
- package/dist/process-manager.js +0 -264
- package/dist/process-manager.js.map +0 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { spawn, execFile } from "node:child_process";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import { createInterface } from "node:readline";
|
|
4
|
+
function execTmux(args) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
execFile("tmux", args, (err, stdout) => {
|
|
7
|
+
if (err)
|
|
8
|
+
reject(err);
|
|
9
|
+
else
|
|
10
|
+
resolve(stdout.trim());
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Persistent tmux control mode client that monitors %output events
|
|
16
|
+
* to detect per-pane idle state. One instance per tmux session.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* const ctrl = new TmuxControlClient("agend", 2000, logger);
|
|
20
|
+
* ctrl.start();
|
|
21
|
+
* await ctrl.waitForIdle("@5"); // wait until window @5 is idle
|
|
22
|
+
* tmux.pasteText(msg);
|
|
23
|
+
*/
|
|
24
|
+
export class TmuxControlClient extends EventEmitter {
|
|
25
|
+
sessionName;
|
|
26
|
+
silenceMs;
|
|
27
|
+
logger;
|
|
28
|
+
proc = null;
|
|
29
|
+
rl = null;
|
|
30
|
+
lastOutputAt = new Map(); // paneId → timestamp
|
|
31
|
+
paneToWindow = new Map(); // paneId → windowId
|
|
32
|
+
stopped = false;
|
|
33
|
+
reconnectTimer = null;
|
|
34
|
+
constructor(sessionName, silenceMs = 2000, logger) {
|
|
35
|
+
super();
|
|
36
|
+
this.sessionName = sessionName;
|
|
37
|
+
this.silenceMs = silenceMs;
|
|
38
|
+
this.logger = logger;
|
|
39
|
+
}
|
|
40
|
+
start() {
|
|
41
|
+
this.stopped = false;
|
|
42
|
+
this.connect();
|
|
43
|
+
}
|
|
44
|
+
// PLACEHOLDER_REST
|
|
45
|
+
stop() {
|
|
46
|
+
this.stopped = true;
|
|
47
|
+
if (this.reconnectTimer) {
|
|
48
|
+
clearTimeout(this.reconnectTimer);
|
|
49
|
+
this.reconnectTimer = null;
|
|
50
|
+
}
|
|
51
|
+
this.cleanup();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Register a window so we can track its pane's output.
|
|
55
|
+
* Call this after createWindow().
|
|
56
|
+
*/
|
|
57
|
+
async registerWindow(windowId) {
|
|
58
|
+
try {
|
|
59
|
+
const paneId = await execTmux([
|
|
60
|
+
"list-panes", "-t", `${this.sessionName}:${windowId}`,
|
|
61
|
+
"-F", "#{pane_id}",
|
|
62
|
+
]);
|
|
63
|
+
if (paneId) {
|
|
64
|
+
this.paneToWindow.set(paneId, windowId);
|
|
65
|
+
this.logger?.debug({ windowId, paneId }, "Registered window→pane mapping");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
this.logger?.debug({ windowId }, "Failed to resolve pane ID for window");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Unregister a window (call on killWindow) */
|
|
73
|
+
unregisterWindow(windowId) {
|
|
74
|
+
for (const [pane, win] of this.paneToWindow) {
|
|
75
|
+
if (win === windowId) {
|
|
76
|
+
this.paneToWindow.delete(pane);
|
|
77
|
+
this.lastOutputAt.delete(pane);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Check if a window's pane has been silent for at least silenceMs */
|
|
83
|
+
isIdle(windowId) {
|
|
84
|
+
const paneId = this.windowToPaneId(windowId);
|
|
85
|
+
if (!paneId)
|
|
86
|
+
return true; // unknown window = assume idle
|
|
87
|
+
const last = this.lastOutputAt.get(paneId);
|
|
88
|
+
if (last == null)
|
|
89
|
+
return true;
|
|
90
|
+
return Date.now() - last >= this.silenceMs;
|
|
91
|
+
}
|
|
92
|
+
// PLACEHOLDER_WAIT
|
|
93
|
+
/**
|
|
94
|
+
* Wait until a window's pane is idle (no output for silenceMs).
|
|
95
|
+
* Returns true if idle detected, false if timeout reached.
|
|
96
|
+
*/
|
|
97
|
+
waitForIdle(windowId, timeoutMs = 30_000) {
|
|
98
|
+
if (this.isIdle(windowId))
|
|
99
|
+
return Promise.resolve(true);
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
const check = setInterval(() => {
|
|
102
|
+
if (this.isIdle(windowId)) {
|
|
103
|
+
clearInterval(check);
|
|
104
|
+
clearTimeout(timer);
|
|
105
|
+
resolve(true);
|
|
106
|
+
}
|
|
107
|
+
}, 200);
|
|
108
|
+
const timer = setTimeout(() => {
|
|
109
|
+
clearInterval(check);
|
|
110
|
+
this.logger?.warn({ windowId, timeoutMs }, "waitForIdle timed out — forcing delivery");
|
|
111
|
+
resolve(false);
|
|
112
|
+
}, timeoutMs);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Wait until a window's pane produces any output.
|
|
117
|
+
* Used to verify CLI startup — if no output within timeout, CLI likely failed.
|
|
118
|
+
*/
|
|
119
|
+
waitForOutput(windowId, timeoutMs = 15_000) {
|
|
120
|
+
const paneId = this.windowToPaneId(windowId);
|
|
121
|
+
// If already has output recorded, it's alive
|
|
122
|
+
if (paneId && this.lastOutputAt.has(paneId))
|
|
123
|
+
return Promise.resolve(true);
|
|
124
|
+
return new Promise((resolve) => {
|
|
125
|
+
const check = setInterval(() => {
|
|
126
|
+
const pid = this.windowToPaneId(windowId);
|
|
127
|
+
if (pid && this.lastOutputAt.has(pid)) {
|
|
128
|
+
clearInterval(check);
|
|
129
|
+
clearTimeout(timer);
|
|
130
|
+
resolve(true);
|
|
131
|
+
}
|
|
132
|
+
}, 300);
|
|
133
|
+
const timer = setTimeout(() => {
|
|
134
|
+
clearInterval(check);
|
|
135
|
+
resolve(false);
|
|
136
|
+
}, timeoutMs);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
windowToPaneId(windowId) {
|
|
140
|
+
for (const [pane, win] of this.paneToWindow) {
|
|
141
|
+
if (win === windowId)
|
|
142
|
+
return pane;
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
connect() {
|
|
147
|
+
if (this.stopped)
|
|
148
|
+
return;
|
|
149
|
+
this.proc = spawn("tmux", ["-C", "attach", "-t", this.sessionName, "-r"], {
|
|
150
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
151
|
+
});
|
|
152
|
+
this.rl = createInterface({ input: this.proc.stdout });
|
|
153
|
+
this.rl.on("line", (line) => this.parseLine(line));
|
|
154
|
+
this.proc.on("close", () => {
|
|
155
|
+
this.cleanup();
|
|
156
|
+
if (!this.stopped) {
|
|
157
|
+
this.logger?.debug("Control mode disconnected — reconnecting in 2s");
|
|
158
|
+
this.reconnectTimer = setTimeout(() => this.connect(), 2000);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
this.proc.on("error", (err) => {
|
|
162
|
+
this.logger?.warn({ err: err.message }, "Control mode spawn error");
|
|
163
|
+
});
|
|
164
|
+
this.logger?.debug("tmux control mode connected");
|
|
165
|
+
}
|
|
166
|
+
parseLine(line) {
|
|
167
|
+
if (line.startsWith("%output ")) {
|
|
168
|
+
const match = line.match(/^%output (%\d+) /);
|
|
169
|
+
if (match) {
|
|
170
|
+
this.lastOutputAt.set(match[1], Date.now());
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
cleanup() {
|
|
175
|
+
this.rl?.close();
|
|
176
|
+
this.rl = null;
|
|
177
|
+
if (this.proc && !this.proc.killed) {
|
|
178
|
+
this.proc.stdin?.write("detach\n");
|
|
179
|
+
this.proc.kill();
|
|
180
|
+
}
|
|
181
|
+
this.proc = null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=tmux-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux-control.js","sourceRoot":"","sources":["../src/tmux-control.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAqB,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAkB,MAAM,eAAe,CAAC;AAGhE,SAAS,QAAQ,CAAC,IAAc;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;gBAChB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IASvC;IACA;IACA;IAVF,IAAI,GAAwB,IAAI,CAAC;IACjC,EAAE,GAAqB,IAAI,CAAC;IAC5B,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,qBAAqB;IAC/D,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAE,oBAAoB;IAC/D,OAAO,GAAG,KAAK,CAAC;IAChB,cAAc,GAAyC,IAAI,CAAC;IAEpE,YACU,WAAmB,EACnB,YAAoB,IAAI,EACxB,MAAe;QAEvB,KAAK,EAAE,CAAC;QAJA,gBAAW,GAAX,WAAW,CAAQ;QACnB,cAAS,GAAT,SAAS,CAAe;QACxB,WAAM,GAAN,MAAM,CAAS;IAGzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,mBAAmB;IAEnB,IAAI;QACF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC;gBAC5B,YAAY,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,QAAQ,EAAE;gBACrD,IAAI,EAAE,YAAY;aACnB,CAAC,CAAC;YACH,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACxC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,gCAAgC,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,sCAAsC,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,gBAAgB,CAAC,QAAgB;QAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5C,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACrB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC/B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC/B,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,MAAM,CAAC,QAAgB;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,CAAC,+BAA+B;QACzD,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QAC9B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC;IAC7C,CAAC;IAED,mBAAmB;IAEnB;;;OAGG;IACH,WAAW,CAAC,QAAgB,EAAE,SAAS,GAAG,MAAM;QAC9C,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAExD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;gBAC7B,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1B,aAAa,CAAC,KAAK,CAAC,CAAC;oBACrB,YAAY,CAAC,KAAK,CAAC,CAAC;oBACpB,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC,EAAE,GAAG,CAAC,CAAC;YAER,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,0CAA0C,CAAC,CAAC;gBACvF,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EAAE,SAAS,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,QAAgB,EAAE,SAAS,GAAG,MAAM;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC7C,6CAA6C;QAC7C,IAAI,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE1E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;gBAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAC1C,IAAI,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtC,aAAa,CAAC,KAAK,CAAC,CAAC;oBACrB,YAAY,CAAC,KAAK,CAAC,CAAC;oBACpB,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC,EAAE,GAAG,CAAC,CAAC;YAER,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EAAE,SAAS,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,cAAc,CAAC,QAAgB;QACrC,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5C,IAAI,GAAG,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;QACpC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,OAAO;QACb,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAEzB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE;YACxE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,MAAO,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAEnD,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACzB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,gDAAgD,CAAC,CAAC;gBACrE,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC5B,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAG,GAAa,CAAC,OAAO,EAAE,EAAE,0BAA0B,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACpD,CAAC;IAEO,SAAS,CAAC,IAAY;QAC5B,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAC7C,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;QACjB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACf,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
package/dist/tmux-manager.js
CHANGED
|
@@ -102,8 +102,9 @@ export class TmuxManager {
|
|
|
102
102
|
async pasteText(text) {
|
|
103
103
|
try {
|
|
104
104
|
const target = `${this.sessionName}:${this.windowId}`;
|
|
105
|
-
|
|
106
|
-
await exec("tmux", ["
|
|
105
|
+
const bufName = `paste-${this.windowId}-${Date.now()}`;
|
|
106
|
+
await exec("tmux", ["set-buffer", "-b", bufName, "--", text]);
|
|
107
|
+
await exec("tmux", ["paste-buffer", "-d", "-b", bufName, "-t", target, "-p"]);
|
|
107
108
|
// Small delay to let TUI process the bracketed paste before sending Enter
|
|
108
109
|
await new Promise(r => setTimeout(r, 200));
|
|
109
110
|
await exec("tmux", ["send-keys", "-t", target, "Enter"]);
|
package/dist/tmux-manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tmux-manager.js","sourceRoot":"","sources":["../src/tmux-manager.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"tmux-manager.js","sourceRoot":"","sources":["../src/tmux-manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suzuke/agend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Multi-agent fleet daemon — run any coding CLI (Claude, Gemini, Codex, OpenCode) from Telegram",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"agend": "./dist/cli.js"
|
|
8
|
-
"ccd": "./dist/cli.js"
|
|
7
|
+
"agend": "./dist/cli.js"
|
|
9
8
|
},
|
|
10
9
|
"scripts": {
|
|
11
10
|
"build": "tsc",
|
|
@@ -52,8 +51,7 @@
|
|
|
52
51
|
"grammy": "^1.41.1",
|
|
53
52
|
"js-yaml": "^4.1.1",
|
|
54
53
|
"pino": "^10.3.1",
|
|
55
|
-
"pino-pretty": "^13.1.3"
|
|
56
|
-
"zod": "^4.3.6"
|
|
54
|
+
"pino-pretty": "^13.1.3"
|
|
57
55
|
},
|
|
58
56
|
"devDependencies": {
|
|
59
57
|
"@types/better-sqlite3": "^7.6.13",
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { MessageBus } from "../channel/message-bus.js";
|
|
2
|
-
import type { IpcServer } from "../channel/ipc-bridge.js";
|
|
3
|
-
interface ApprovalOptions {
|
|
4
|
-
messageBus: MessageBus;
|
|
5
|
-
port: number;
|
|
6
|
-
/** In topic mode, approval is forwarded via IPC to fleet manager */
|
|
7
|
-
ipcServer?: IpcServer | null;
|
|
8
|
-
topicMode?: boolean;
|
|
9
|
-
/** Instance name — so fleet manager knows which topic to send approval to */
|
|
10
|
-
instanceName?: string;
|
|
11
|
-
}
|
|
12
|
-
export declare class ApprovalServer {
|
|
13
|
-
private server;
|
|
14
|
-
private messageBus;
|
|
15
|
-
private port;
|
|
16
|
-
private ipcServer;
|
|
17
|
-
private topicMode;
|
|
18
|
-
private instanceName;
|
|
19
|
-
private token;
|
|
20
|
-
constructor(opts: ApprovalOptions);
|
|
21
|
-
getToken(): string;
|
|
22
|
-
start(): Promise<number>;
|
|
23
|
-
private requestApproval;
|
|
24
|
-
/** DM mode: use messageBus directly (adapter is registered on this daemon) */
|
|
25
|
-
private requestApprovalViaBus;
|
|
26
|
-
/** Topic mode: forward approval request to fleet manager via IPC */
|
|
27
|
-
private requestApprovalViaIpc;
|
|
28
|
-
stop(): Promise<void>;
|
|
29
|
-
}
|
|
30
|
-
export {};
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { createServer } from "node:http";
|
|
2
|
-
import { randomBytes } from "node:crypto";
|
|
3
|
-
const DANGER_PATTERNS = [
|
|
4
|
-
/\brm\b/, // any file deletion
|
|
5
|
-
/\bgit\s+push\b/, // any push (not just --force)
|
|
6
|
-
/\bgit\s+reset\b/, // any reset
|
|
7
|
-
/\bgit\s+clean\b/, // any clean
|
|
8
|
-
/\bgit\s+checkout\s+\./, // discard changes
|
|
9
|
-
/\bgit\s+restore\b/, // discard changes
|
|
10
|
-
/\bmv\b/, // move/rename files
|
|
11
|
-
/\bdd\b/,
|
|
12
|
-
/\bmkfs\b/,
|
|
13
|
-
/\bsudo\b/,
|
|
14
|
-
/\bchmod\b/,
|
|
15
|
-
/\bchown\b/,
|
|
16
|
-
/\bkill\b/,
|
|
17
|
-
/\bpkill\b/,
|
|
18
|
-
/(?<!\d)>\s*\/(?:etc|usr|var|bin|sbin|lib|opt|root|System|Library)\b/, // redirect to system paths (not /tmp, not 2>/dev/null)
|
|
19
|
-
/(?:\/usr)?\/s?bin\/(rm|chmod|chown|mkfs|dd)\b/, // full path variants
|
|
20
|
-
/\b(?:command|env|builtin)\s+(rm|chmod|chown|sudo)\b/, // command wrappers
|
|
21
|
-
/\$\(.*\b(rm|dd|mkfs)\b/, // command substitution with dangerous commands
|
|
22
|
-
];
|
|
23
|
-
function isSafeTool(toolName) {
|
|
24
|
-
if (toolName === "Bash" || toolName.startsWith("Bash("))
|
|
25
|
-
return false;
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
function isDangerousCommand(command) {
|
|
29
|
-
return DANGER_PATTERNS.some(pattern => pattern.test(command));
|
|
30
|
-
}
|
|
31
|
-
const APPROVAL_TIMEOUT_MS = 120_000;
|
|
32
|
-
export class ApprovalServer {
|
|
33
|
-
server = null;
|
|
34
|
-
messageBus;
|
|
35
|
-
port;
|
|
36
|
-
ipcServer;
|
|
37
|
-
topicMode;
|
|
38
|
-
instanceName;
|
|
39
|
-
token;
|
|
40
|
-
constructor(opts) {
|
|
41
|
-
this.messageBus = opts.messageBus;
|
|
42
|
-
this.port = opts.port;
|
|
43
|
-
this.ipcServer = opts.ipcServer ?? null;
|
|
44
|
-
this.topicMode = opts.topicMode ?? false;
|
|
45
|
-
this.instanceName = opts.instanceName ?? "";
|
|
46
|
-
this.token = randomBytes(32).toString("hex");
|
|
47
|
-
}
|
|
48
|
-
getToken() {
|
|
49
|
-
return this.token;
|
|
50
|
-
}
|
|
51
|
-
async start() {
|
|
52
|
-
return new Promise((resolve, reject) => {
|
|
53
|
-
this.server = createServer(async (req, res) => {
|
|
54
|
-
if (req.headers.authorization !== `Bearer ${this.token}`) {
|
|
55
|
-
res.writeHead(401);
|
|
56
|
-
res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
if (req.method !== "POST" || req.url !== "/approve") {
|
|
60
|
-
res.writeHead(404);
|
|
61
|
-
res.end(JSON.stringify({ error: "Not found" }));
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
let body = "";
|
|
65
|
-
req.on("data", (chunk) => { body += chunk; });
|
|
66
|
-
req.on("end", async () => {
|
|
67
|
-
try {
|
|
68
|
-
const { tool_name, tool_input } = JSON.parse(body);
|
|
69
|
-
let permissionDecision;
|
|
70
|
-
let permissionDecisionReason;
|
|
71
|
-
if (tool_name === "Bash" && typeof tool_input?.command === "string" && isDangerousCommand(tool_input.command)) {
|
|
72
|
-
// Dangerous Bash commands → require human approval
|
|
73
|
-
const prompt = `⚠️ ${tool_name}\n\`\`\`\n${tool_input.command}\n\`\`\``;
|
|
74
|
-
const decision = await this.requestApproval(prompt);
|
|
75
|
-
permissionDecision = decision;
|
|
76
|
-
permissionDecisionReason = decision === "allow"
|
|
77
|
-
? "approved by user"
|
|
78
|
-
: "denied by user";
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
// Everything else (all tools + normal Bash) → auto-allow
|
|
82
|
-
permissionDecision = "allow";
|
|
83
|
-
}
|
|
84
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
85
|
-
res.end(JSON.stringify({
|
|
86
|
-
hookSpecificOutput: {
|
|
87
|
-
hookEventName: "PreToolUse",
|
|
88
|
-
permissionDecision,
|
|
89
|
-
...(permissionDecisionReason ? { permissionDecisionReason } : {}),
|
|
90
|
-
},
|
|
91
|
-
}));
|
|
92
|
-
}
|
|
93
|
-
catch (err) {
|
|
94
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
95
|
-
res.end(JSON.stringify({ error: "Bad request" }));
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
this.server.on("error", reject);
|
|
100
|
-
this.server.listen(this.port, "127.0.0.1", () => {
|
|
101
|
-
const address = this.server.address();
|
|
102
|
-
const actualPort = typeof address === "object" && address !== null ? address.port : this.port;
|
|
103
|
-
resolve(actualPort);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
requestApproval(prompt) {
|
|
108
|
-
if (this.topicMode && this.ipcServer) {
|
|
109
|
-
return this.requestApprovalViaIpc(prompt);
|
|
110
|
-
}
|
|
111
|
-
return this.requestApprovalViaBus(prompt);
|
|
112
|
-
}
|
|
113
|
-
/** DM mode: use messageBus directly (adapter is registered on this daemon) */
|
|
114
|
-
async requestApprovalViaBus(prompt) {
|
|
115
|
-
const result = await this.messageBus.requestApproval(prompt);
|
|
116
|
-
return result.decision === "deny" ? "deny" : "allow";
|
|
117
|
-
}
|
|
118
|
-
/** Topic mode: forward approval request to fleet manager via IPC */
|
|
119
|
-
requestApprovalViaIpc(prompt) {
|
|
120
|
-
return new Promise((resolve) => {
|
|
121
|
-
const approvalId = `approval-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
122
|
-
const timeout = setTimeout(() => {
|
|
123
|
-
cleanup();
|
|
124
|
-
resolve("deny");
|
|
125
|
-
}, APPROVAL_TIMEOUT_MS);
|
|
126
|
-
const onMessage = (msg) => {
|
|
127
|
-
if (msg.type === "fleet_approval_response" && msg.approvalId === approvalId) {
|
|
128
|
-
cleanup();
|
|
129
|
-
resolve(msg.decision === "deny" ? "deny" : "allow");
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
const cleanup = () => {
|
|
133
|
-
clearTimeout(timeout);
|
|
134
|
-
this.ipcServer?.removeListener("message", onMessage);
|
|
135
|
-
};
|
|
136
|
-
this.ipcServer?.on("message", onMessage);
|
|
137
|
-
this.ipcServer?.broadcast({
|
|
138
|
-
type: "fleet_approval_request",
|
|
139
|
-
approvalId,
|
|
140
|
-
instanceName: this.instanceName,
|
|
141
|
-
prompt,
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
async stop() {
|
|
146
|
-
return new Promise((resolve) => {
|
|
147
|
-
if (!this.server) {
|
|
148
|
-
resolve();
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
this.server.close(() => resolve());
|
|
152
|
-
this.server = null;
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
//# sourceMappingURL=approval-server.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"approval-server.js","sourceRoot":"","sources":["../../src/approval/approval-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { TmuxManager } from "../tmux-manager.js";
|
|
2
|
-
import type { ApprovalResponse } from "../channel/types.js";
|
|
3
|
-
export type PromptType = "permission" | "settings_error" | "dev_channels" | "mcp_trust" | "file_creation" | "unknown";
|
|
4
|
-
/** Detect whether text contains a Claude Code interactive prompt */
|
|
5
|
-
export declare function detectInteractivePrompt(text: string): boolean;
|
|
6
|
-
/** Classify a detected prompt to determine handling strategy */
|
|
7
|
-
export declare function classifyPrompt(text: string): PromptType;
|
|
8
|
-
export declare function detectPermissionPrompt(text: string): boolean;
|
|
9
|
-
/**
|
|
10
|
-
* Extract tool name from Claude Code permission prompt text.
|
|
11
|
-
* Returns the permission-format tool name (e.g. "mcp__puppeteer__puppeteer_navigate").
|
|
12
|
-
*/
|
|
13
|
-
export declare function extractToolPattern(text: string): string | null;
|
|
14
|
-
/** Build a clean prompt message for Telegram display */
|
|
15
|
-
export declare function formatPromptForDisplay(text: string): string;
|
|
16
|
-
export declare function loadToolAllowlist(instanceDir: string): string[];
|
|
17
|
-
export declare function saveToolToAllowlist(instanceDir: string, pattern: string): void;
|
|
18
|
-
export declare class TmuxPromptDetector {
|
|
19
|
-
private outputLogPath;
|
|
20
|
-
private tmux;
|
|
21
|
-
private approvalFn;
|
|
22
|
-
private logger;
|
|
23
|
-
private instanceDir?;
|
|
24
|
-
private pollTimer;
|
|
25
|
-
private byteOffset;
|
|
26
|
-
private pendingApproval;
|
|
27
|
-
constructor(outputLogPath: string, tmux: TmuxManager, approvalFn: (prompt: string) => Promise<ApprovalResponse>, logger: {
|
|
28
|
-
info(...args: any[]): void;
|
|
29
|
-
warn(...args: any[]): void;
|
|
30
|
-
error(...args: any[]): void;
|
|
31
|
-
}, instanceDir?: string | undefined);
|
|
32
|
-
startPolling(intervalMs?: number): void;
|
|
33
|
-
stop(): void;
|
|
34
|
-
}
|