@adhdev/daemon-core 0.9.82-rc.66 → 0.9.82-rc.68
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/dist/index.d.ts +1 -1
- package/dist/index.js +747 -591
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +748 -593
- package/dist/index.mjs.map +1 -1
- package/dist/installer.d.ts +1 -4
- package/dist/launch.d.ts +1 -1
- package/dist/logging/async-batch-writer.d.ts +10 -0
- package/dist/mesh/beads-db.d.ts +18 -0
- package/dist/mesh/mesh-work-queue.d.ts +4 -0
- package/dist/status/reporter.d.ts +2 -0
- package/package.json +3 -1
- package/src/cli-adapters/provider-cli-shared.ts +18 -10
- package/src/commands/mesh-coordinator.ts +13 -143
- package/src/commands/router.ts +5 -3
- package/src/detection/ide-detector.ts +26 -16
- package/src/index.ts +1 -1
- package/src/installer.d.ts +1 -1
- package/src/installer.ts +8 -6
- package/src/launch.d.ts +1 -1
- package/src/launch.ts +37 -28
- package/src/logging/async-batch-writer.ts +55 -0
- package/src/logging/logger.ts +2 -1
- package/src/mesh/beads-db.ts +163 -0
- package/src/mesh/mesh-ledger.ts +1 -1
- package/src/mesh/mesh-work-queue.ts +23 -41
- package/src/providers/ide-provider-instance.ts +17 -3
- package/src/providers/provider-loader.ts +10 -4
- package/src/providers/version-archive.ts +38 -20
- package/src/status/reporter.ts +15 -0
- package/src/system/host-memory.ts +29 -12
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import * as os from 'os';
|
|
15
|
-
|
|
15
|
+
// Removed execSync import
|
|
16
16
|
import { platform } from 'os';
|
|
17
17
|
import type { ProviderLoader } from './provider-loader.js';
|
|
18
18
|
import type { ProviderModule } from './contracts.js';
|
|
@@ -117,22 +117,40 @@ export class VersionArchive {
|
|
|
117
117
|
|
|
118
118
|
// ─── Version Detection ──────────────────────────────
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
import { exec } from 'child_process';
|
|
121
|
+
|
|
122
|
+
async function runCommand(cmd: string, timeout = 10000): Promise<string | null> {
|
|
123
|
+
return new Promise((resolve) => {
|
|
124
|
+
exec(cmd, {
|
|
123
125
|
encoding: 'utf-8',
|
|
124
126
|
timeout,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
127
|
+
}, (error, stdout) => {
|
|
128
|
+
if (error) return resolve(null);
|
|
129
|
+
resolve(stdout.trim());
|
|
130
|
+
});
|
|
131
|
+
});
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
function findBinary(name: string): string | null {
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
135
|
+
const isWin = platform() === 'win32';
|
|
136
|
+
const paths = (process.env.PATH || '').split(isWin ? ';' : ':');
|
|
137
|
+
const exes = isWin ? ['.exe', '.cmd', '.bat', ''] : [''];
|
|
138
|
+
|
|
139
|
+
for (const p of paths) {
|
|
140
|
+
if (!p) continue;
|
|
141
|
+
for (const ext of exes) {
|
|
142
|
+
const fullPath = path.join(p, name + ext);
|
|
143
|
+
try {
|
|
144
|
+
if (fs.existsSync(fullPath)) {
|
|
145
|
+
const stat = fs.statSync(fullPath);
|
|
146
|
+
if (stat.isFile() && (isWin || (stat.mode & 0o111))) {
|
|
147
|
+
return fullPath;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} catch { }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
136
154
|
}
|
|
137
155
|
|
|
138
156
|
/** Extract version string from CLI output */
|
|
@@ -162,16 +180,16 @@ function getPlatformVersionCommand(
|
|
|
162
180
|
return undefined;
|
|
163
181
|
}
|
|
164
182
|
|
|
165
|
-
function getVersion(binary: string, versionCommand?: string): string | null {
|
|
183
|
+
async function getVersion(binary: string, versionCommand?: string): Promise<string | null> {
|
|
166
184
|
// Custom version command from provider.json
|
|
167
185
|
if (versionCommand) {
|
|
168
|
-
const raw = runCommand(versionCommand);
|
|
186
|
+
const raw = await runCommand(versionCommand);
|
|
169
187
|
return raw ? parseVersion(raw) : null;
|
|
170
188
|
}
|
|
171
189
|
|
|
172
190
|
// Default: try --version, then -V, then -v
|
|
173
191
|
for (const flag of ['--version', '-V', '-v']) {
|
|
174
|
-
const raw = runCommand(`"${binary}" ${flag}`);
|
|
192
|
+
const raw = await runCommand(`"${binary}" ${flag}`);
|
|
175
193
|
if (raw && raw.length < 500) return parseVersion(raw);
|
|
176
194
|
}
|
|
177
195
|
return null;
|
|
@@ -191,11 +209,11 @@ function checkPathExists(paths: string[]): string | null {
|
|
|
191
209
|
}
|
|
192
210
|
|
|
193
211
|
/** macOS: Get app version from Info.plist */
|
|
194
|
-
function getMacAppVersion(appPath: string): string | null {
|
|
212
|
+
async function getMacAppVersion(appPath: string): Promise<string | null> {
|
|
195
213
|
if (platform() !== 'darwin' || !appPath.endsWith('.app')) return null;
|
|
196
214
|
const plistPath = path.join(appPath, 'Contents', 'Info.plist');
|
|
197
215
|
if (!fs.existsSync(plistPath)) return null;
|
|
198
|
-
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
216
|
+
const raw = await runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
199
217
|
return raw || null;
|
|
200
218
|
}
|
|
201
219
|
|
|
@@ -242,10 +260,10 @@ export async function detectAllVersions(
|
|
|
242
260
|
|
|
243
261
|
// Version: try CLI first, then plist
|
|
244
262
|
if (resolvedBin) {
|
|
245
|
-
info.version = getVersion(resolvedBin, versionCommand);
|
|
263
|
+
info.version = await getVersion(resolvedBin, versionCommand);
|
|
246
264
|
}
|
|
247
265
|
if (!info.version && appPath) {
|
|
248
|
-
info.version = getMacAppVersion(appPath);
|
|
266
|
+
info.version = await getMacAppVersion(appPath);
|
|
249
267
|
}
|
|
250
268
|
|
|
251
269
|
} else if (provider.category === 'cli' || provider.category === 'acp') {
|
|
@@ -256,7 +274,7 @@ export async function detectAllVersions(
|
|
|
256
274
|
info.binary = binPath || null;
|
|
257
275
|
|
|
258
276
|
if (binPath) {
|
|
259
|
-
info.version = getVersion(binPath, versionCommand);
|
|
277
|
+
info.version = await getVersion(binPath, versionCommand);
|
|
260
278
|
}
|
|
261
279
|
|
|
262
280
|
} else if (provider.category === 'extension') {
|
package/src/status/reporter.ts
CHANGED
|
@@ -51,6 +51,8 @@ export class DaemonStatusReporter {
|
|
|
51
51
|
private lastStatusSentAt = 0;
|
|
52
52
|
private statusPendingThrottle = false;
|
|
53
53
|
private lastP2PStatusHash = '';
|
|
54
|
+
private lastP2PStatusSentAt: number = 0;
|
|
55
|
+
private p2pDebounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
54
56
|
private lastServerStatusHash = '';
|
|
55
57
|
private lastStatusSummary = '';
|
|
56
58
|
|
|
@@ -355,7 +357,20 @@ export class DaemonStatusReporter {
|
|
|
355
357
|
: { ...hashTarget, sessions };
|
|
356
358
|
const h = this.simpleHash(JSON.stringify(hashPayload));
|
|
357
359
|
if (h !== this.lastP2PStatusHash) {
|
|
360
|
+
const now = Date.now();
|
|
361
|
+
// Rate limit: max 1 per 500ms
|
|
362
|
+
if (this.lastP2PStatusSentAt && now - this.lastP2PStatusSentAt < 500) {
|
|
363
|
+
if (!this.p2pDebounceTimer) {
|
|
364
|
+
this.p2pDebounceTimer = setTimeout(() => {
|
|
365
|
+
this.p2pDebounceTimer = null;
|
|
366
|
+
this.sendUnifiedStatusReport({ reason: 'p2p_debounce' });
|
|
367
|
+
}, 500);
|
|
368
|
+
}
|
|
369
|
+
return false; // Dropped for now, but will trigger later
|
|
370
|
+
}
|
|
371
|
+
|
|
358
372
|
this.lastP2PStatusHash = h;
|
|
373
|
+
this.lastP2PStatusSentAt = now;
|
|
359
374
|
this.deps.p2p?.sendStatus(payload);
|
|
360
375
|
return true;
|
|
361
376
|
}
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import * as os from 'os';
|
|
14
|
-
import {
|
|
14
|
+
import { exec } from 'child_process';
|
|
15
|
+
import { promisify } from 'util';
|
|
16
|
+
|
|
17
|
+
const execAsync = promisify(exec);
|
|
15
18
|
|
|
16
19
|
export interface HostMemorySnapshot {
|
|
17
20
|
totalMem: number;
|
|
@@ -21,19 +24,22 @@ export interface HostMemorySnapshot {
|
|
|
21
24
|
availableMem: number;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
let cachedDarwinAvail: number | null = null;
|
|
28
|
+
let darwinMemoryInterval: NodeJS.Timeout | null = null;
|
|
29
|
+
|
|
30
|
+
async function updateDarwinMemoryCache() {
|
|
31
|
+
if (os.platform() !== 'darwin') return;
|
|
26
32
|
try {
|
|
27
|
-
const
|
|
33
|
+
const { stdout } = await execAsync('vm_stat', {
|
|
28
34
|
encoding: 'utf-8',
|
|
29
35
|
timeout: 4000,
|
|
30
36
|
maxBuffer: 256 * 1024,
|
|
31
37
|
});
|
|
32
|
-
const pageSizeMatch =
|
|
38
|
+
const pageSizeMatch = stdout.match(/page size of (\d+)\s*bytes/i);
|
|
33
39
|
const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 4096;
|
|
34
40
|
|
|
35
41
|
const counts: Record<string, number> = {};
|
|
36
|
-
for (const line of
|
|
42
|
+
for (const line of stdout.split('\n')) {
|
|
37
43
|
const m = line.match(/^\s*Pages\s+([^:]+):\s+([\d,]+)\s*\.?/);
|
|
38
44
|
if (!m) continue;
|
|
39
45
|
const key = m[1].trim().toLowerCase().replace(/\s+/g, '_');
|
|
@@ -49,17 +55,28 @@ function parseDarwinAvailableBytes(totalMem: number): number | null {
|
|
|
49
55
|
|
|
50
56
|
const availPages = free + inactive + speculative + purgeable + fileBacked;
|
|
51
57
|
const bytes = availPages * pageSize;
|
|
52
|
-
|
|
53
|
-
return Math.min(bytes, totalMem);
|
|
58
|
+
cachedDarwinAvail = Number.isFinite(bytes) && bytes >= 0 ? Math.min(bytes, os.totalmem()) : null;
|
|
54
59
|
} catch {
|
|
55
|
-
|
|
60
|
+
// silently fallback
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
export function getHostMemorySnapshot(): HostMemorySnapshot {
|
|
65
|
+
if (os.platform() === 'darwin' && !darwinMemoryInterval) {
|
|
66
|
+
updateDarwinMemoryCache();
|
|
67
|
+
darwinMemoryInterval = setInterval(updateDarwinMemoryCache, 3000);
|
|
68
|
+
darwinMemoryInterval.unref();
|
|
69
|
+
}
|
|
70
|
+
|
|
60
71
|
const totalMem = os.totalmem();
|
|
61
72
|
const freeMem = os.freemem();
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
73
|
+
const availableMem = os.platform() === 'darwin'
|
|
74
|
+
? (cachedDarwinAvail ?? freeMem)
|
|
75
|
+
: freeMem;
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
totalMem,
|
|
79
|
+
freeMem,
|
|
80
|
+
availableMem,
|
|
81
|
+
};
|
|
65
82
|
}
|