indieclaw-agent 1.1.1 → 1.1.3

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.
Files changed (2) hide show
  1. package/index.js +81 -23
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -210,6 +210,7 @@ function handleFsDelete(ws, { id, path: filePath }) {
210
210
  // --- System Stats ---
211
211
  function handleSystemStats(ws, { id }) {
212
212
  const platform = os.platform();
213
+ const mem = platform === 'darwin' ? getDarwinMemory() : getLinuxMemory();
213
214
  const stats = {
214
215
  hostname: os.hostname(),
215
216
  platform,
@@ -220,17 +221,61 @@ function handleSystemStats(ws, { id }) {
220
221
  cores: os.cpus().length,
221
222
  usage: getCpuUsage(platform),
222
223
  },
223
- memory: {
224
- total: os.totalmem(),
225
- free: os.freemem(),
226
- used: os.totalmem() - os.freemem(),
227
- usagePercent: Math.round(((os.totalmem() - os.freemem()) / os.totalmem()) * 100),
228
- },
224
+ memory: mem,
229
225
  disk: getDiskUsage(platform),
230
226
  };
231
227
  reply(ws, id, stats);
232
228
  }
233
229
 
230
+ function getDarwinMemory() {
231
+ const total = os.totalmem();
232
+ try {
233
+ const out = execSync('vm_stat', { timeout: 3000 }).toString();
234
+ const pageMatch = out.match(/page size of (\d+) bytes/);
235
+ const pageSize = pageMatch ? parseInt(pageMatch[1], 10) : 16384;
236
+
237
+ const val = (key) => {
238
+ const m = out.match(new RegExp(key + ':\\s+(\\d+)'));
239
+ return m ? parseInt(m[1], 10) : 0;
240
+ };
241
+
242
+ const wired = val('Pages wired down');
243
+ const active = val('Pages active');
244
+ const compressed = val('Pages occupied by compressor');
245
+ const purgeable = val('Pages purgeable');
246
+
247
+ // Used = wired + active (minus purgeable) + compressed — matches Activity Monitor
248
+ const used = (wired + active - purgeable + compressed) * pageSize;
249
+ const free = total - used;
250
+ return {
251
+ total,
252
+ free: Math.max(free, 0),
253
+ used: Math.min(used, total),
254
+ usagePercent: Math.round((Math.min(used, total) / total) * 100),
255
+ };
256
+ } catch {
257
+ // Fallback to Node.js (inaccurate on macOS but better than nothing)
258
+ const free = os.freemem();
259
+ return {
260
+ total,
261
+ free,
262
+ used: total - free,
263
+ usagePercent: Math.round(((total - free) / total) * 100),
264
+ };
265
+ }
266
+ }
267
+
268
+ function getLinuxMemory() {
269
+ const total = os.totalmem();
270
+ const free = os.freemem();
271
+ return {
272
+ total,
273
+ free,
274
+ used: total - free,
275
+ usagePercent: Math.round(((total - free) / total) * 100),
276
+ };
277
+ }
278
+
234
279
  function getCpuUsage(platform) {
235
280
  try {
236
281
  if (platform === 'linux') {
@@ -251,23 +296,32 @@ function getCpuUsage(platform) {
251
296
 
252
297
  function getDiskUsage(platform) {
253
298
  try {
254
- const cmd = platform === 'darwin' ? 'df -k /' : 'df -k / --output=source,size,used,avail,pcent,target';
255
- const out = execSync(cmd, { timeout: 5000 }).toString();
256
- const lines = out.trim().split('\n').slice(1);
257
- return lines.map((line) => {
258
- const parts = line.trim().split(/\s+/);
259
- if (platform === 'darwin') {
260
- // macOS df: Filesystem 512-blocks Used Available Capacity ...
261
- // df -k gives 1K-blocks
299
+ if (platform === 'darwin') {
300
+ // macOS APFS: "Used" column only shows one volume's data
301
+ // Calculate used = total - available for accurate results
302
+ const out = execSync('df -k /', { timeout: 5000 }).toString();
303
+ const lines = out.trim().split('\n').slice(1);
304
+ return lines.map((line) => {
305
+ const parts = line.trim().split(/\s+/);
306
+ // Columns: Filesystem 1K-blocks Used Available Capacity iused ifree %iused Mounted
307
+ const total = parseInt(parts[1], 10) * 1024;
308
+ const available = parseInt(parts[3], 10) * 1024;
309
+ const used = total - available;
262
310
  return {
263
311
  filesystem: parts[0],
264
- mount: parts[8] || parts[5] || '/',
265
- total: parseInt(parts[1], 10) * 1024,
266
- used: parseInt(parts[2], 10) * 1024,
267
- available: parseInt(parts[3], 10) * 1024,
268
- usagePercent: parseInt(parts[4], 10),
312
+ mount: parts[8] || '/',
313
+ total,
314
+ used,
315
+ available,
316
+ usagePercent: Math.round((used / total) * 100),
269
317
  };
270
- }
318
+ });
319
+ }
320
+ // Linux
321
+ const out = execSync('df -k / --output=source,size,used,avail,pcent,target', { timeout: 5000 }).toString();
322
+ const lines = out.trim().split('\n').slice(1);
323
+ return lines.map((line) => {
324
+ const parts = line.trim().split(/\s+/);
271
325
  return {
272
326
  filesystem: parts[0],
273
327
  total: parseInt(parts[1], 10) * 1024,
@@ -489,11 +543,15 @@ function handleTerminalStart(ws, { id }) {
489
543
  }
490
544
  }
491
545
 
492
- // Fallback: child_process.spawn
546
+ // Fallback: use script(1) to allocate a real PTY
493
547
  const { spawn } = require('child_process');
494
- const proc = spawn(shell, ['-i'], {
548
+ const scriptArgs = os.platform() === 'darwin'
549
+ ? ['-q', '/dev/null', shell]
550
+ : ['-q', '-c', shell, '/dev/null'];
551
+
552
+ const proc = spawn('script', scriptArgs, {
495
553
  cwd: os.homedir(),
496
- env: { ...process.env, TERM: 'dumb' },
554
+ env: { ...process.env, TERM: 'xterm-256color' },
497
555
  stdio: ['pipe', 'pipe', 'pipe'],
498
556
  });
499
557
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "indieclaw-agent",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Manage your server from your phone. Agent for the IndieClaw mobile app.",
5
5
  "main": "index.js",
6
6
  "bin": {