@dmsdc-ai/aigentry-devkit 0.1.9 → 0.1.11
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/install.ps1
CHANGED
|
@@ -46,30 +46,8 @@ if (-not $npmCmd) {
|
|
|
46
46
|
if (Get-Command tmux -ErrorAction SilentlyContinue) {
|
|
47
47
|
Write-Info "tmux found (deliberation monitor can run in tmux)"
|
|
48
48
|
} else {
|
|
49
|
-
Write-
|
|
50
|
-
|
|
51
|
-
if (Get-Command choco -ErrorAction SilentlyContinue) {
|
|
52
|
-
try {
|
|
53
|
-
choco install tmux -y | Out-Null
|
|
54
|
-
$tmuxInstalled = $true
|
|
55
|
-
} catch {}
|
|
56
|
-
} elseif (Get-Command scoop -ErrorAction SilentlyContinue) {
|
|
57
|
-
try {
|
|
58
|
-
scoop install tmux | Out-Null
|
|
59
|
-
$tmuxInstalled = $true
|
|
60
|
-
} catch {}
|
|
61
|
-
} elseif (Get-Command winget -ErrorAction SilentlyContinue) {
|
|
62
|
-
try {
|
|
63
|
-
winget install tmux --accept-source-agreements --accept-package-agreements | Out-Null
|
|
64
|
-
$tmuxInstalled = $true
|
|
65
|
-
} catch {}
|
|
66
|
-
}
|
|
67
|
-
if ($tmuxInstalled) {
|
|
68
|
-
Write-Info "tmux installed successfully"
|
|
69
|
-
} else {
|
|
70
|
-
Write-Warn "tmux not installed. Install manually via choco/scoop/winget, or use WSL."
|
|
71
|
-
Write-Warn "Deliberation monitor auto-window is disabled."
|
|
72
|
-
}
|
|
49
|
+
Write-Warn "tmux is not natively available on Windows. Deliberation monitor auto-window is disabled."
|
|
50
|
+
Write-Warn "This does not affect deliberation functionality. tmux is optional (macOS/Linux only)."
|
|
73
51
|
}
|
|
74
52
|
|
|
75
53
|
if (Get-Command claude -ErrorAction SilentlyContinue) {
|
|
@@ -1337,6 +1337,7 @@ function archiveState(state) {
|
|
|
1337
1337
|
|
|
1338
1338
|
const TMUX_SESSION = "deliberation";
|
|
1339
1339
|
const MONITOR_SCRIPT = path.join(HOME, ".local", "lib", "mcp-deliberation", "session-monitor.sh");
|
|
1340
|
+
const MONITOR_SCRIPT_WIN = path.join(HOME, ".local", "lib", "mcp-deliberation", "session-monitor-win.js");
|
|
1340
1341
|
|
|
1341
1342
|
function tmuxWindowName(sessionId) {
|
|
1342
1343
|
// tmux 윈도우 이름은 짧게 (마지막 부분 제거하고 20자)
|
|
@@ -1368,6 +1369,10 @@ function buildMonitorCommand(sessionId, project) {
|
|
|
1368
1369
|
return `${shell} ${shellQuote(MONITOR_SCRIPT)} ${shellQuote(sessionId)} ${shellQuote(project)}`;
|
|
1369
1370
|
}
|
|
1370
1371
|
|
|
1372
|
+
function buildMonitorCommandWindows(sessionId, project) {
|
|
1373
|
+
return `node "${MONITOR_SCRIPT_WIN}" "${sessionId}" "${project}"`;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1371
1376
|
function hasTmuxSession(name) {
|
|
1372
1377
|
try {
|
|
1373
1378
|
execFileSync("tmux", ["has-session", "-t", name], { stdio: "ignore", windowsHide: true });
|
|
@@ -1499,28 +1504,40 @@ function openPhysicalTerminal(sessionId) {
|
|
|
1499
1504
|
}
|
|
1500
1505
|
|
|
1501
1506
|
if (process.platform === "win32") {
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1507
|
+
// Windows: monitor is launched directly by spawnMonitorTerminal (no tmux)
|
|
1508
|
+
// Physical terminal opening is handled there, so just return success
|
|
1509
|
+
return { opened: true, windowIds: [] };
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
return { opened: false, windowIds: [] };
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
function spawnMonitorTerminal(sessionId) {
|
|
1516
|
+
// Windows: use Windows Terminal or PowerShell directly (no tmux needed)
|
|
1517
|
+
if (process.platform === "win32") {
|
|
1518
|
+
const project = getProjectSlug();
|
|
1519
|
+
const monitorCmd = buildMonitorCommandWindows(sessionId, project);
|
|
1520
|
+
|
|
1521
|
+
// Try Windows Terminal (wt.exe)
|
|
1522
|
+
if (commandExistsInPath("wt") || commandExistsInPath("wt.exe")) {
|
|
1523
|
+
if (tryExecFile("wt", ["new-tab", "--title", "Deliberation Monitor", "cmd", "/c", monitorCmd])) {
|
|
1524
|
+
return true;
|
|
1525
|
+
}
|
|
1506
1526
|
}
|
|
1507
1527
|
|
|
1508
|
-
|
|
1509
|
-
|
|
1528
|
+
// Fallback: new PowerShell window
|
|
1529
|
+
const shell = ["pwsh.exe", "pwsh", "powershell.exe", "powershell"].find(c => commandExistsInPath(c));
|
|
1510
1530
|
if (shell) {
|
|
1511
|
-
const
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
if (tryExecFile(shell, ["-NoProfile", "-Command", script])) {
|
|
1515
|
-
return { opened: true, windowIds: [] };
|
|
1531
|
+
const escaped = monitorCmd.replace(/'/g, "''");
|
|
1532
|
+
if (tryExecFile(shell, ["-NoProfile", "-Command", `Start-Process cmd -ArgumentList '/c','${escaped}'`])) {
|
|
1533
|
+
return true;
|
|
1516
1534
|
}
|
|
1517
1535
|
}
|
|
1518
|
-
}
|
|
1519
1536
|
|
|
1520
|
-
|
|
1521
|
-
}
|
|
1537
|
+
return false;
|
|
1538
|
+
}
|
|
1522
1539
|
|
|
1523
|
-
|
|
1540
|
+
// macOS/Linux: use tmux (existing logic)
|
|
1524
1541
|
if (!commandExistsInPath("tmux")) {
|
|
1525
1542
|
return false;
|
|
1526
1543
|
}
|
|
@@ -1682,22 +1699,24 @@ function closePhysicalTerminal(windowId) {
|
|
|
1682
1699
|
}
|
|
1683
1700
|
|
|
1684
1701
|
function closeMonitorTerminal(sessionId, terminalWindowIds = []) {
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
windowsHide: true,
|
|
1690
|
-
});
|
|
1691
|
-
} catch { /* ignore */ }
|
|
1692
|
-
|
|
1693
|
-
try {
|
|
1694
|
-
if (tmuxWindowCount(TMUX_SESSION) === 0) {
|
|
1695
|
-
execFileSync("tmux", ["kill-session", "-t", TMUX_SESSION], {
|
|
1702
|
+
if (process.platform !== "win32") {
|
|
1703
|
+
const winName = tmuxWindowName(sessionId);
|
|
1704
|
+
try {
|
|
1705
|
+
execFileSync("tmux", ["kill-window", "-t", `${TMUX_SESSION}:${winName}`], {
|
|
1696
1706
|
stdio: "ignore",
|
|
1697
1707
|
windowsHide: true,
|
|
1698
1708
|
});
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1709
|
+
} catch { /* ignore */ }
|
|
1710
|
+
|
|
1711
|
+
try {
|
|
1712
|
+
if (tmuxWindowCount(TMUX_SESSION) === 0) {
|
|
1713
|
+
execFileSync("tmux", ["kill-session", "-t", TMUX_SESSION], {
|
|
1714
|
+
stdio: "ignore",
|
|
1715
|
+
windowsHide: true,
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
} catch { /* ignore */ }
|
|
1719
|
+
}
|
|
1701
1720
|
|
|
1702
1721
|
for (const windowId of terminalWindowIds) {
|
|
1703
1722
|
closePhysicalTerminal(windowId);
|
|
@@ -1987,11 +2006,18 @@ server.tool(
|
|
|
1987
2006
|
});
|
|
1988
2007
|
state.monitor_terminal_window_ids = terminalWindowIds;
|
|
1989
2008
|
}
|
|
2009
|
+
const isWin = process.platform === "win32";
|
|
1990
2010
|
const terminalMsg = !tmuxOpened
|
|
1991
|
-
?
|
|
2011
|
+
? isWin
|
|
2012
|
+
? `\n⚠️ Windows Terminal을 찾을 수 없어 모니터 터미널 미생성`
|
|
2013
|
+
: `\n⚠️ tmux를 찾을 수 없어 모니터 터미널 미생성`
|
|
1992
2014
|
: physicalOpened
|
|
1993
|
-
?
|
|
1994
|
-
|
|
2015
|
+
? isWin
|
|
2016
|
+
? `\n🖥️ 모니터 터미널 오픈됨 (Windows Terminal)`
|
|
2017
|
+
: `\n🖥️ 모니터 터미널 오픈됨: tmux attach -t ${TMUX_SESSION}`
|
|
2018
|
+
: isWin
|
|
2019
|
+
? `\n⚠️ 모니터 터미널 자동 오픈 실패`
|
|
2020
|
+
: `\n⚠️ tmux 윈도우는 생성됐지만 외부 터미널 자동 오픈 실패. 수동 실행: tmux attach -t ${TMUX_SESSION}`;
|
|
1995
2021
|
const manualNotDetected = hasManualSpeakers
|
|
1996
2022
|
? speakerOrder.filter(s => !candidateSnapshot.candidates.some(c => c.speaker === s))
|
|
1997
2023
|
: [];
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// Usage: node session-monitor-win.js <sessionId> <project>
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
|
|
8
|
+
const sessionId = process.argv[2];
|
|
9
|
+
const project = process.argv[3] || "default";
|
|
10
|
+
|
|
11
|
+
if (!sessionId) {
|
|
12
|
+
console.error("Usage: node session-monitor-win.js <sessionId> <project>");
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const HOME = process.env.HOME || process.env.USERPROFILE || "";
|
|
17
|
+
const stateDir = path.join(HOME, ".local", "state", "mcp-deliberation", project);
|
|
18
|
+
const stateFile = path.join(stateDir, `${sessionId}.json`);
|
|
19
|
+
|
|
20
|
+
const BOLD = "\x1b[1m";
|
|
21
|
+
const CYAN = "\x1b[36m";
|
|
22
|
+
const GREEN = "\x1b[32m";
|
|
23
|
+
const YELLOW = "\x1b[33m";
|
|
24
|
+
const DIM = "\x1b[2m";
|
|
25
|
+
const NC = "\x1b[0m";
|
|
26
|
+
|
|
27
|
+
let prevData = "";
|
|
28
|
+
|
|
29
|
+
function render() {
|
|
30
|
+
let raw;
|
|
31
|
+
try {
|
|
32
|
+
raw = fs.readFileSync(stateFile, "utf-8");
|
|
33
|
+
} catch {
|
|
34
|
+
return; // file not ready yet
|
|
35
|
+
}
|
|
36
|
+
if (raw === prevData) return;
|
|
37
|
+
prevData = raw;
|
|
38
|
+
|
|
39
|
+
let state;
|
|
40
|
+
try {
|
|
41
|
+
state = JSON.parse(raw);
|
|
42
|
+
} catch {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.clear();
|
|
47
|
+
console.log(`${BOLD}${CYAN}╔═══════════════════════════════════════╗${NC}`);
|
|
48
|
+
console.log(`${BOLD}${CYAN}║ Deliberation Monitor ║${NC}`);
|
|
49
|
+
console.log(`${BOLD}${CYAN}╚═══════════════════════════════════════╝${NC}`);
|
|
50
|
+
console.log();
|
|
51
|
+
console.log(`${BOLD}Topic:${NC} ${state.topic || "(none)"}`);
|
|
52
|
+
console.log(`${BOLD}Round:${NC} ${state.current_round || "?"}/${state.max_rounds || "?"}`);
|
|
53
|
+
console.log(`${BOLD}Speaker:${NC} ${YELLOW}${state.current_speaker || "(waiting)"}${NC}`);
|
|
54
|
+
console.log(`${BOLD}Speakers:${NC} ${(state.speakers || []).join(", ")}`);
|
|
55
|
+
console.log();
|
|
56
|
+
console.log(`${DIM}${"─".repeat(50)}${NC}`);
|
|
57
|
+
console.log();
|
|
58
|
+
|
|
59
|
+
const log = Array.isArray(state.log) ? state.log : [];
|
|
60
|
+
const recent = log.slice(-10);
|
|
61
|
+
for (const entry of recent) {
|
|
62
|
+
const speaker = entry.speaker || "unknown";
|
|
63
|
+
const content = String(entry.content || "").slice(0, 300);
|
|
64
|
+
const round = entry.round != null ? ` (R${entry.round})` : "";
|
|
65
|
+
console.log(`${GREEN}[${speaker}]${NC}${DIM}${round}${NC}`);
|
|
66
|
+
console.log(content);
|
|
67
|
+
console.log();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (recent.length === 0) {
|
|
71
|
+
console.log(`${DIM}(No messages yet. Waiting for first turn...)${NC}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log(`${DIM}${"─".repeat(50)}${NC}`);
|
|
75
|
+
console.log(`${DIM}Auto-refresh every 2s | Session: ${sessionId} | Ctrl+C to close${NC}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Initial render
|
|
79
|
+
render();
|
|
80
|
+
|
|
81
|
+
// Poll every 2 seconds
|
|
82
|
+
const interval = setInterval(render, 2000);
|
|
83
|
+
|
|
84
|
+
// Graceful shutdown
|
|
85
|
+
process.on("SIGINT", () => {
|
|
86
|
+
clearInterval(interval);
|
|
87
|
+
console.log(`\n${DIM}Monitor closed.${NC}`);
|
|
88
|
+
process.exit(0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
process.on("SIGTERM", () => {
|
|
92
|
+
clearInterval(interval);
|
|
93
|
+
process.exit(0);
|
|
94
|
+
});
|