opencode-zombie-monitor 1.0.0 → 1.0.2
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/assets/russia-heart.png +0 -0
- package/assets/russia-heart.webp +0 -0
- package/index.mjs +27 -23
- package/package.json +1 -1
package/assets/russia-heart.png
CHANGED
|
Binary file
|
package/assets/russia-heart.webp
CHANGED
|
Binary file
|
package/index.mjs
CHANGED
|
@@ -18,29 +18,32 @@ const getLang = () => {
|
|
|
18
18
|
return "en"
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
// Format memory size
|
|
22
|
+
const formatMB = (mb) => mb >= 1024 ? `${(mb / 1024).toFixed(1)}GB` : `${Math.round(mb)}MB`
|
|
23
|
+
|
|
21
24
|
// Localized messages
|
|
22
25
|
const i18n = {
|
|
23
26
|
en: {
|
|
24
|
-
killed: (n) => `🧟 Killed ${n} zombie opencode process${n > 1 ? "es" : ""} | Freed
|
|
25
|
-
found: (n) => `🧟 ${n} zombie opencode process${n > 1 ? "es" : ""} |
|
|
26
|
-
status: (zombies, total) => zombies > 0
|
|
27
|
-
? `🧟 ${zombies} zombie${zombies > 1 ? "s" : ""} of ${total} process${total > 1 ? "es" : ""} |
|
|
27
|
+
killed: (n, mb) => `🧟 Killed ${n} zombie opencode process${n > 1 ? "es" : ""} | Freed ${formatMB(mb)} RAM`,
|
|
28
|
+
found: (n, mb) => `🧟 ${n} zombie opencode process${n > 1 ? "es" : ""} | ${formatMB(mb)} RAM | Fix: oc-kill-zombies`,
|
|
29
|
+
status: (zombies, total, mb) => zombies > 0
|
|
30
|
+
? `🧟 ${zombies} zombie${zombies > 1 ? "s" : ""} of ${total} process${total > 1 ? "es" : ""} | ${formatMB(mb)} RAM | Fix: oc-kill-zombies`
|
|
28
31
|
: `✅ ${total} process${total > 1 ? "es" : ""}, no zombies`,
|
|
29
32
|
commandDesc: "Check zombie opencode processes"
|
|
30
33
|
},
|
|
31
34
|
ru: {
|
|
32
|
-
killed: (n) => `🧟 Убито ${n} зомби-процессов opencode | Освобождено
|
|
33
|
-
found: (n) => `🧟 ${n} зомби-процессов opencode |
|
|
34
|
-
status: (zombies, total) => zombies > 0
|
|
35
|
-
? `🧟 ${zombies} зомби из ${total} процессов |
|
|
35
|
+
killed: (n, mb) => `🧟 Убито ${n} зомби-процессов opencode | Освобождено ${formatMB(mb)} RAM`,
|
|
36
|
+
found: (n, mb) => `🧟 ${n} зомби-процессов opencode | ${formatMB(mb)} RAM | Fix: oc-kill-zombies`,
|
|
37
|
+
status: (zombies, total, mb) => zombies > 0
|
|
38
|
+
? `🧟 ${zombies} зомби из ${total} процессов | ${formatMB(mb)} RAM | Fix: oc-kill-zombies`
|
|
36
39
|
: `✅ ${total} процессов, зомби нет`,
|
|
37
40
|
commandDesc: "Проверить зомби-процессы opencode"
|
|
38
41
|
},
|
|
39
42
|
zh: {
|
|
40
|
-
killed: (n) => `🧟 已击杀 ${n} 个僵尸 opencode 进程 | 释放
|
|
41
|
-
found: (n) => `🧟 发现 ${n} 个僵尸 opencode 进程 |
|
|
42
|
-
status: (zombies, total) => zombies > 0
|
|
43
|
-
? `🧟 ${total} 个进程中有 ${zombies} 个僵尸 |
|
|
43
|
+
killed: (n, mb) => `🧟 已击杀 ${n} 个僵尸 opencode 进程 | 释放 ${formatMB(mb)} 内存`,
|
|
44
|
+
found: (n, mb) => `🧟 发现 ${n} 个僵尸 opencode 进程 | ${formatMB(mb)} 内存 | 修复: oc-kill-zombies`,
|
|
45
|
+
status: (zombies, total, mb) => zombies > 0
|
|
46
|
+
? `🧟 ${total} 个进程中有 ${zombies} 个僵尸 | ${formatMB(mb)} 内存 | 修复: oc-kill-zombies`
|
|
44
47
|
: `✅ ${total} 个进程,没有僵尸`,
|
|
45
48
|
commandDesc: "检查僵尸 opencode 进程"
|
|
46
49
|
}
|
|
@@ -48,15 +51,16 @@ const i18n = {
|
|
|
48
51
|
|
|
49
52
|
const t = i18n[getLang()]
|
|
50
53
|
|
|
51
|
-
//
|
|
52
|
-
const
|
|
54
|
+
// Get zombie count and their total memory (RSS in MB)
|
|
55
|
+
const getZombieStats = async () => {
|
|
53
56
|
try {
|
|
54
|
-
// macOS: TTY = "??" | Linux: TTY = "?"
|
|
55
57
|
const ttyPattern = isMac ? '??' : '?'
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
// $6 = RSS in KB on both macOS and Linux
|
|
59
|
+
const { stdout } = await execAsync(`ps aux | grep "[o]pencode" | grep -v "opencode/" | awk '$7 == "${ttyPattern}" {count++; mem+=$6} END {print count+0, mem/1024}'`)
|
|
60
|
+
const [count, mb] = stdout.trim().split(/\s+/)
|
|
61
|
+
return { count: parseInt(count) || 0, mb: parseFloat(mb) || 0 }
|
|
58
62
|
} catch {
|
|
59
|
-
return 0
|
|
63
|
+
return { count: 0, mb: 0 }
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
|
|
@@ -119,13 +123,13 @@ export const ZombieMonitor = async ({ client }) => {
|
|
|
119
123
|
const sessionId = getSessionIdFromMessages(output.messages)
|
|
120
124
|
if (!sessionId) return
|
|
121
125
|
|
|
122
|
-
const zombies = await
|
|
126
|
+
const { count: zombies, mb } = await getZombieStats()
|
|
123
127
|
|
|
124
128
|
// Auto-kill if zombies >= threshold
|
|
125
129
|
if (zombies >= AUTO_KILL_THRESHOLD) {
|
|
126
130
|
await killZombies()
|
|
127
131
|
try {
|
|
128
|
-
await sendNotification(client, sessionId, t.killed(zombies))
|
|
132
|
+
await sendNotification(client, sessionId, t.killed(zombies, mb))
|
|
129
133
|
} catch (e) {}
|
|
130
134
|
lastNotifiedCount = 0
|
|
131
135
|
}
|
|
@@ -133,7 +137,7 @@ export const ZombieMonitor = async ({ client }) => {
|
|
|
133
137
|
else if (zombies > 0 && zombies > lastNotifiedCount) {
|
|
134
138
|
lastNotifiedCount = zombies
|
|
135
139
|
try {
|
|
136
|
-
await sendNotification(client, sessionId, t.found(zombies))
|
|
140
|
+
await sendNotification(client, sessionId, t.found(zombies, mb))
|
|
137
141
|
} catch (e) {}
|
|
138
142
|
} else if (zombies === 0) {
|
|
139
143
|
lastNotifiedCount = 0
|
|
@@ -143,10 +147,10 @@ export const ZombieMonitor = async ({ client }) => {
|
|
|
143
147
|
"command.execute.before": async (input) => {
|
|
144
148
|
if (input.command !== "zombies") return
|
|
145
149
|
|
|
146
|
-
const zombies = await
|
|
150
|
+
const { count: zombies, mb } = await getZombieStats()
|
|
147
151
|
const total = await getTotalCount()
|
|
148
152
|
|
|
149
|
-
await sendNotification(client, input.sessionID, t.status(zombies, total))
|
|
153
|
+
await sendNotification(client, input.sessionID, t.status(zombies, total, mb))
|
|
150
154
|
throw new Error("__ZOMBIES_HANDLED__")
|
|
151
155
|
}
|
|
152
156
|
}
|
package/package.json
CHANGED