@winmatrix/daemon 0.2.7 → 1.0.4
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/package.json +3 -3
- package/dist/core/AgentProcessManager.d.ts +0 -92
- package/dist/core/AgentProcessManager.d.ts.map +0 -1
- package/dist/core/AgentProcessManager.js +0 -323
- package/dist/core/AgentProcessManager.js.map +0 -1
- package/dist/core/ConfigLoader.d.ts +0 -94
- package/dist/core/ConfigLoader.d.ts.map +0 -1
- package/dist/core/ConfigLoader.js +0 -245
- package/dist/core/ConfigLoader.js.map +0 -1
- package/dist/core/DaemonFileLogger.d.ts +0 -34
- package/dist/core/DaemonFileLogger.d.ts.map +0 -1
- package/dist/core/DaemonFileLogger.js +0 -192
- package/dist/core/DaemonFileLogger.js.map +0 -1
- package/dist/core/DaemonLifecycle.d.ts +0 -22
- package/dist/core/DaemonLifecycle.d.ts.map +0 -1
- package/dist/core/DaemonLifecycle.js +0 -156
- package/dist/core/DaemonLifecycle.js.map +0 -1
- package/dist/core/DiagnosticsServer.d.ts +0 -28
- package/dist/core/DiagnosticsServer.d.ts.map +0 -1
- package/dist/core/DiagnosticsServer.js +0 -155
- package/dist/core/DiagnosticsServer.js.map +0 -1
- package/dist/core/InstallationId.d.ts +0 -14
- package/dist/core/InstallationId.d.ts.map +0 -1
- package/dist/core/InstallationId.js +0 -50
- package/dist/core/InstallationId.js.map +0 -1
- package/dist/core/RuntimeAvailabilityReporter.d.ts +0 -27
- package/dist/core/RuntimeAvailabilityReporter.d.ts.map +0 -1
- package/dist/core/RuntimeAvailabilityReporter.js +0 -79
- package/dist/core/RuntimeAvailabilityReporter.js.map +0 -1
- package/dist/core/WorkspaceScanner.d.ts +0 -45
- package/dist/core/WorkspaceScanner.d.ts.map +0 -1
- package/dist/core/WorkspaceScanner.js +0 -166
- package/dist/core/WorkspaceScanner.js.map +0 -1
- package/dist/index.d.ts +0 -16
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -238
- package/dist/index.js.map +0 -1
- package/dist/wrapper/AgentProcessManager.d.ts +0 -80
- package/dist/wrapper/AgentProcessManager.d.ts.map +0 -1
- package/dist/wrapper/AgentProcessManager.js +0 -474
- package/dist/wrapper/AgentProcessManager.js.map +0 -1
- package/dist/wrapper/AgentWrapper.d.ts +0 -7
- package/dist/wrapper/AgentWrapper.d.ts.map +0 -1
- package/dist/wrapper/AgentWrapper.js +0 -229
- package/dist/wrapper/AgentWrapper.js.map +0 -1
- package/dist/wrapper/claudeCommand.d.ts +0 -2
- package/dist/wrapper/claudeCommand.d.ts.map +0 -1
- package/dist/wrapper/claudeCommand.js +0 -2
- package/dist/wrapper/claudeCommand.js.map +0 -1
- package/dist/wrapper/supportedAgentTypes.d.ts +0 -7
- package/dist/wrapper/supportedAgentTypes.d.ts.map +0 -1
- package/dist/wrapper/supportedAgentTypes.js +0 -6
- package/dist/wrapper/supportedAgentTypes.js.map +0 -1
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Daemon 运维:首次目录/init、按 PID 平滑重启。
|
|
3
|
-
*/
|
|
4
|
-
import { spawn } from 'node:child_process';
|
|
5
|
-
import { existsSync, writeFileSync, readFileSync, unlinkSync, chmodSync, mkdirSync, } from 'node:fs';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
import { homedir } from 'node:os';
|
|
8
|
-
import { fileURLToPath } from 'node:url';
|
|
9
|
-
import { getOrCreateInstallationId } from './InstallationId.js';
|
|
10
|
-
import { DaemonFileLogger, pruneOldDaemonLogs } from './DaemonFileLogger.js';
|
|
11
|
-
import { DEFAULT_DAEMON_PUBLIC_BASE_URL, DEFAULT_DAEMON_SERVER_URL, getDaemonConfigFilePath, mergeDaemonSetupConfigToDisk, normalizeDaemonServerUrl, parseCliArgs, loadDaemonJson, } from './ConfigLoader.js';
|
|
12
|
-
const DAEMON_HOME = path.join(homedir(), '.winmatrix');
|
|
13
|
-
const PID_FILENAME = 'daemon.pid';
|
|
14
|
-
function getPidFilePath() {
|
|
15
|
-
return path.join(DAEMON_HOME, PID_FILENAME);
|
|
16
|
-
}
|
|
17
|
-
function isProbablyOurDaemonPid(pid) {
|
|
18
|
-
return Number.isInteger(pid) && pid > 0;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* 守护进程主循环开始时写入(供 restart 查找)。
|
|
22
|
-
*/
|
|
23
|
-
export function writeDaemonPidFile() {
|
|
24
|
-
if (!existsSync(DAEMON_HOME)) {
|
|
25
|
-
mkdirSync(DAEMON_HOME, { recursive: true, mode: 0o700 });
|
|
26
|
-
chmodSync(DAEMON_HOME, 0o700);
|
|
27
|
-
}
|
|
28
|
-
writeFileSync(getPidFilePath(), String(process.pid), { encoding: 'utf-8', mode: 0o600 });
|
|
29
|
-
chmodSync(getPidFilePath(), 0o600);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* 退出时删除 PID 文件。
|
|
33
|
-
*/
|
|
34
|
-
export function clearDaemonPidFile() {
|
|
35
|
-
try {
|
|
36
|
-
if (existsSync(getPidFilePath())) {
|
|
37
|
-
const raw = readFileSync(getPidFilePath(), 'utf-8').trim();
|
|
38
|
-
if (raw === String(process.pid)) {
|
|
39
|
-
unlinkSync(getPidFilePath());
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
/* ignore */
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function readExistingPid() {
|
|
48
|
-
try {
|
|
49
|
-
if (!existsSync(getPidFilePath()))
|
|
50
|
-
return null;
|
|
51
|
-
const n = Number.parseInt(readFileSync(getPidFilePath(), 'utf-8').trim(), 10);
|
|
52
|
-
return isProbablyOurDaemonPid(n) ? n : null;
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function sleep(ms) {
|
|
59
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
60
|
-
}
|
|
61
|
-
function resolveEntryScriptPath() {
|
|
62
|
-
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
63
|
-
return path.join(here, '..', 'index.js');
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* 创建 ~/.winmatrix、installation、logs;写入或合并 daemon.json(serverUrl / computerToken)。
|
|
67
|
-
* 可选:`winmatrix-daemon setup [--server <ws-url>] [--token <wmc_...>]`
|
|
68
|
-
*/
|
|
69
|
-
export function runSetup(setupArgv) {
|
|
70
|
-
getOrCreateInstallationId();
|
|
71
|
-
new DaemonFileLogger();
|
|
72
|
-
pruneOldDaemonLogs();
|
|
73
|
-
const args = parseCliArgs(setupArgv);
|
|
74
|
-
const file = loadDaemonJson();
|
|
75
|
-
const serverUrl = normalizeDaemonServerUrl(args.server ?? file.serverUrl ?? DEFAULT_DAEMON_SERVER_URL);
|
|
76
|
-
const tokenArg = typeof args.token === 'string' ? args.token.trim() : '';
|
|
77
|
-
mergeDaemonSetupConfigToDisk({ serverUrl, computerToken: tokenArg });
|
|
78
|
-
const cfgPath = getDaemonConfigFilePath();
|
|
79
|
-
console.log(`[daemon] setup: wrote ${cfgPath}`);
|
|
80
|
-
console.log('[daemon] setup: done.');
|
|
81
|
-
if (tokenArg.length === 0) {
|
|
82
|
-
console.log('[daemon] Tip: add Computer token with winmatrix-daemon setup --token wmc_... or edit computerToken in daemon.json');
|
|
83
|
-
}
|
|
84
|
-
console.log('[daemon] Then: winmatrix-daemon or winmatrix-daemon restart');
|
|
85
|
-
console.log('[daemon] Local UI: http://127.0.0.1:18767/ (daemon running)');
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* 向旧进程发 SIGTERM,再后台拉起新进程(参数为 restart 之后的 argv)。
|
|
89
|
-
*/
|
|
90
|
-
export async function runRestart(forwardArgv) {
|
|
91
|
-
const oldPid = readExistingPid();
|
|
92
|
-
if (oldPid !== null) {
|
|
93
|
-
try {
|
|
94
|
-
process.kill(oldPid, 'SIGTERM');
|
|
95
|
-
console.log(`[daemon] restart: sent SIGTERM to pid ${oldPid}`);
|
|
96
|
-
for (let i = 0; i < 50; i++) {
|
|
97
|
-
try {
|
|
98
|
-
process.kill(oldPid, 0);
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
await sleep(100);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
catch (e) {
|
|
107
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
108
|
-
console.log(`[daemon] restart: no process for pid ${oldPid} (${msg}), starting fresh`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
console.log('[daemon] restart: no pid file (daemon was not running or first start)');
|
|
113
|
-
}
|
|
114
|
-
const entry = resolveEntryScriptPath();
|
|
115
|
-
if (!existsSync(entry)) {
|
|
116
|
-
console.error(`[daemon] restart: entry not found: ${entry}`);
|
|
117
|
-
console.error('[daemon] restart: run from built package (npm run build in clients/daemon)');
|
|
118
|
-
process.exitCode = 1;
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
const child = spawn(process.execPath, [entry, ...forwardArgv], {
|
|
122
|
-
detached: true,
|
|
123
|
-
stdio: 'ignore',
|
|
124
|
-
env: process.env,
|
|
125
|
-
});
|
|
126
|
-
child.unref();
|
|
127
|
-
console.log(`[daemon] restart: started new daemon (child pid ${child.pid ?? '?'})`);
|
|
128
|
-
}
|
|
129
|
-
export function printCliHelp(daemonVersion) {
|
|
130
|
-
console.log(`WinMatrix Daemon ${daemonVersion}`);
|
|
131
|
-
console.log(`
|
|
132
|
-
Usage:
|
|
133
|
-
winmatrix-daemon [options] Run daemon (foreground)
|
|
134
|
-
winmatrix-daemon setup [options] Create ~/.winmatrix + write/merge daemon.json
|
|
135
|
-
winmatrix-daemon restart [options] SIGTERM old daemon (from pid file), start again with options
|
|
136
|
-
winmatrix-daemon help This help
|
|
137
|
-
|
|
138
|
-
Options (setup / run / restart):
|
|
139
|
-
--server <server-url> Server base URL or External Agent WebSocket URL
|
|
140
|
-
--token <wmc_...> Computer registration token (overrides env + daemon.json)
|
|
141
|
-
--persist-token After resolving token (CLI or env), save serverUrl + computerToken to daemon.json
|
|
142
|
-
|
|
143
|
-
Environment:
|
|
144
|
-
WINMATRIX_TOKEN Computer token (wmc_...)
|
|
145
|
-
WINMATRIX_DAEMON_DIAG_* Local diagnostics HTTP (see DiagnosticsServer)
|
|
146
|
-
|
|
147
|
-
Config file:
|
|
148
|
-
~/.winmatrix/daemon.json serverUrl, optional computerToken (read on each start; chmod 600)
|
|
149
|
-
|
|
150
|
-
Typical:
|
|
151
|
-
winmatrix-daemon setup --token wmc_...
|
|
152
|
-
winmatrix-daemon setup --token wmc_... --server ${DEFAULT_DAEMON_PUBLIC_BASE_URL}
|
|
153
|
-
winmatrix-daemon restart
|
|
154
|
-
`);
|
|
155
|
-
}
|
|
156
|
-
//# sourceMappingURL=DaemonLifecycle.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DaemonLifecycle.js","sourceRoot":"","sources":["../../src/core/DaemonLifecycle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EACL,UAAU,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,uBAAuB,EACvB,4BAA4B,EAC5B,wBAAwB,EACxB,YAAY,EACZ,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACvD,MAAM,YAAY,GAAG,YAAY,CAAC;AAElC,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,sBAAsB,CAAC,GAAW;IACzC,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,SAAS,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IACD,aAAa,CAAC,cAAc,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzF,SAAS,CAAC,cAAc,EAAE,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3D,IAAI,GAAG,KAAK,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC;AAED,SAAS,eAAe;IACtB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9E,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,sBAAsB;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,SAAmB;IAC1C,yBAAyB,EAAE,CAAC;IAC5B,IAAI,gBAAgB,EAAE,CAAC;IACvB,kBAAkB,EAAE,CAAC;IAErB,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,wBAAwB,CACxC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,yBAAyB,CAC3D,CAAC;IACF,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEzE,4BAA4B,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC;IAErE,MAAM,OAAO,GAAG,uBAAuB,EAAE,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,qHAAqH,CAAC,CAAC;IACrI,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;AAC7E,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAqB;IACpD,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,yCAAyC,MAAM,EAAE,CAAC,CAAC;YAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,IAAI,CAAC;oBACH,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAC1B,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM;gBACR,CAAC;gBACD,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,wCAAwC,MAAM,KAAK,GAAG,mBAAmB,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,KAAK,GAAG,sBAAsB,EAAE,CAAC;IACvC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;QAC5F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE;QAC7D,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,mDAAmD,KAAK,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,aAAqB;IAChD,OAAO,CAAC,GAAG,CAAC,oBAAoB,aAAa,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;oDAqBsC,8BAA8B;;CAEjF,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 本机只读诊断 HTTP 服务(默认 127.0.0.1:18767):状态、子 Agent、最近日志。
|
|
3
|
-
* 不鉴权 — 仅回环,切勿 bind 到 0.0.0.0。
|
|
4
|
-
*/
|
|
5
|
-
import http from 'node:http';
|
|
6
|
-
import type { DaemonFileLogger } from './DaemonFileLogger.js';
|
|
7
|
-
import type { AgentProcessManager } from './AgentProcessManager.js';
|
|
8
|
-
export interface DaemonDiagnosticsContext {
|
|
9
|
-
version: string;
|
|
10
|
-
installationId: string;
|
|
11
|
-
/** 已脱敏 */
|
|
12
|
-
serverUrl: string;
|
|
13
|
-
computerState: string | null;
|
|
14
|
-
computerId: string | null;
|
|
15
|
-
uptimeSec: number;
|
|
16
|
-
}
|
|
17
|
-
export declare function startDiagnosticsServer(options: {
|
|
18
|
-
fileLogger: DaemonFileLogger;
|
|
19
|
-
agentManager: AgentProcessManager;
|
|
20
|
-
getContext: () => DaemonDiagnosticsContext;
|
|
21
|
-
onRescanProfiles?: () => Promise<{
|
|
22
|
-
ok: boolean;
|
|
23
|
-
error?: string;
|
|
24
|
-
}>;
|
|
25
|
-
host?: string;
|
|
26
|
-
port?: number;
|
|
27
|
-
}): http.Server;
|
|
28
|
-
//# sourceMappingURL=DiagnosticsServer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DiagnosticsServer.d.ts","sourceRoot":"","sources":["../../src/core/DiagnosticsServer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAKpE,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU;IACV,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAoFD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,UAAU,EAAE,gBAAgB,CAAC;IAC7B,YAAY,EAAE,mBAAmB,CAAC;IAClC,UAAU,EAAE,MAAM,wBAAwB,CAAC;IAC3C,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAAC,MAAM,CAqEd"}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 本机只读诊断 HTTP 服务(默认 127.0.0.1:18767):状态、子 Agent、最近日志。
|
|
3
|
-
* 不鉴权 — 仅回环,切勿 bind 到 0.0.0.0。
|
|
4
|
-
*/
|
|
5
|
-
import http from 'node:http';
|
|
6
|
-
const DEFAULT_HOST = '127.0.0.1';
|
|
7
|
-
const DEFAULT_PORT = 18767;
|
|
8
|
-
function json(res, code, body) {
|
|
9
|
-
const payload = JSON.stringify(body);
|
|
10
|
-
res.writeHead(code, {
|
|
11
|
-
'Content-Type': 'application/json; charset=utf-8',
|
|
12
|
-
'Cache-Control': 'no-store',
|
|
13
|
-
});
|
|
14
|
-
res.end(payload);
|
|
15
|
-
}
|
|
16
|
-
function htmlDashboard() {
|
|
17
|
-
return `<!DOCTYPE html>
|
|
18
|
-
<html lang="zh-CN">
|
|
19
|
-
<head>
|
|
20
|
-
<meta charset="utf-8" />
|
|
21
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
22
|
-
<title>WinMatrix Daemon</title>
|
|
23
|
-
<style>
|
|
24
|
-
body { font-family: system-ui, sans-serif; margin: 16px; background: #0f1419; color: #e6edf3; }
|
|
25
|
-
h1 { font-size: 1.1rem; }
|
|
26
|
-
pre { background: #161b22; padding: 12px; overflow: auto; max-height: 420px; border-radius: 6px; font-size: 12px; line-height: 1.4; }
|
|
27
|
-
section { margin-bottom: 20px; }
|
|
28
|
-
.muted { color: #8b949e; font-size: 13px; }
|
|
29
|
-
a { color: #58a6ff; }
|
|
30
|
-
code { background: #21262d; padding: 2px 6px; border-radius: 4px; }
|
|
31
|
-
</style>
|
|
32
|
-
</head>
|
|
33
|
-
<body>
|
|
34
|
-
<h1>WinMatrix Daemon 本机诊断</h1>
|
|
35
|
-
<p class="muted">仅监听 127.0.0.1;API:<code>/api/status</code> <code>/api/agents</code> <code>/api/tasks</code> <code>/api/logs</code> <code>POST /api/rescan-profiles</code></p>
|
|
36
|
-
<p><button id="rescanBtn" style="padding:6px 14px;cursor:pointer;">刷新技能</button> <span id="rescanMsg" style="margin-left:8px;font-size:13px;"></span></p>
|
|
37
|
-
<section>
|
|
38
|
-
<h2>状态</h2>
|
|
39
|
-
<pre id="status">加载中…</pre>
|
|
40
|
-
</section>
|
|
41
|
-
<section>
|
|
42
|
-
<h2>子 Agent</h2>
|
|
43
|
-
<pre id="agents">加载中…</pre>
|
|
44
|
-
</section>
|
|
45
|
-
<section>
|
|
46
|
-
<h2>近期任务</h2>
|
|
47
|
-
<p class="muted">仅在<strong>本子 Agent WebSocket</strong>收到服务端 <code>task.assign</code> 并由适配器执行时写入(进程内存)。OpenClaw 工作站 HTTP / <code>openclaw_chat</code> 工具、或未绑定到此 Daemon 上「子 Agent」注册 ID 的对话不会出现在此处;重启 Daemon 后会清空。</p>
|
|
48
|
-
<pre id="tasks">加载中…</pre>
|
|
49
|
-
</section>
|
|
50
|
-
<section>
|
|
51
|
-
<h2>最近日志</h2>
|
|
52
|
-
<pre id="logs">加载中…</pre>
|
|
53
|
-
</section>
|
|
54
|
-
<script>
|
|
55
|
-
async function load() {
|
|
56
|
-
const [st, ag, tk, lg] = await Promise.all([
|
|
57
|
-
fetch('/api/status').then(r => r.json()),
|
|
58
|
-
fetch('/api/agents').then(r => r.json()),
|
|
59
|
-
fetch('/api/tasks').then(r => r.json()),
|
|
60
|
-
fetch('/api/logs?lines=200').then(r => r.json()),
|
|
61
|
-
]);
|
|
62
|
-
document.getElementById('status').textContent = JSON.stringify(st.data ?? st, null, 2);
|
|
63
|
-
document.getElementById('agents').textContent = JSON.stringify(ag.data ?? ag, null, 2);
|
|
64
|
-
document.getElementById('tasks').textContent = JSON.stringify(tk.data ?? tk, null, 2);
|
|
65
|
-
document.getElementById('logs').textContent = ((lg.data && lg.data.lines) || []).join(String.fromCharCode(10));
|
|
66
|
-
}
|
|
67
|
-
document.getElementById('rescanBtn').onclick = async function() {
|
|
68
|
-
const btn = document.getElementById('rescanBtn');
|
|
69
|
-
const msg = document.getElementById('rescanMsg');
|
|
70
|
-
btn.disabled = true;
|
|
71
|
-
msg.textContent = '扫描中...';
|
|
72
|
-
try {
|
|
73
|
-
const r = await fetch('/api/rescan-profiles', { method: 'POST' });
|
|
74
|
-
const j = await r.json();
|
|
75
|
-
msg.textContent = j.success ? '已刷新并上报' : ('失败: ' + (j.error || '未知错误'));
|
|
76
|
-
} catch(e) {
|
|
77
|
-
msg.textContent = '请求失败: ' + e.message;
|
|
78
|
-
} finally {
|
|
79
|
-
btn.disabled = false;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
load();
|
|
83
|
-
setInterval(load, 8000);
|
|
84
|
-
</script>
|
|
85
|
-
</body>
|
|
86
|
-
</html>`;
|
|
87
|
-
}
|
|
88
|
-
export function startDiagnosticsServer(options) {
|
|
89
|
-
const host = options.host ?? process.env.WINMATRIX_DAEMON_DIAG_HOST ?? DEFAULT_HOST;
|
|
90
|
-
const port = Number(process.env.WINMATRIX_DAEMON_DIAG_PORT ?? options.port ?? DEFAULT_PORT);
|
|
91
|
-
const server = http.createServer((req, res) => {
|
|
92
|
-
const url = new URL(req.url ?? '/', `http://${host}`);
|
|
93
|
-
try {
|
|
94
|
-
if (req.method === 'GET' && url.pathname === '/') {
|
|
95
|
-
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
96
|
-
res.end(htmlDashboard());
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
if (req.method === 'GET' && url.pathname === '/api/status') {
|
|
100
|
-
json(res, 200, { success: true, data: options.getContext() });
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (req.method === 'GET' && url.pathname === '/api/agents') {
|
|
104
|
-
json(res, 200, {
|
|
105
|
-
success: true,
|
|
106
|
-
data: options.agentManager.listAgents(),
|
|
107
|
-
});
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
if (req.method === 'GET' && url.pathname === '/api/tasks') {
|
|
111
|
-
json(res, 200, {
|
|
112
|
-
success: true,
|
|
113
|
-
data: options.agentManager.getRecentTaskEvents(),
|
|
114
|
-
});
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
if (req.method === 'GET' && url.pathname === '/api/logs') {
|
|
118
|
-
const lines = Math.min(2000, Math.max(1, Number(url.searchParams.get('lines')) || 200));
|
|
119
|
-
json(res, 200, {
|
|
120
|
-
success: true,
|
|
121
|
-
data: {
|
|
122
|
-
logDir: options.fileLogger.getLogDirectory(),
|
|
123
|
-
lines: options.fileLogger.getRecentLines(lines),
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
if (req.method === 'POST' && url.pathname === '/api/rescan-profiles') {
|
|
129
|
-
if (options.onRescanProfiles) {
|
|
130
|
-
options.onRescanProfiles().then((result) => {
|
|
131
|
-
json(res, result.ok ? 200 : 500, { success: result.ok, data: result.ok ? null : undefined, error: result.error });
|
|
132
|
-
}).catch((e) => {
|
|
133
|
-
json(res, 500, { success: false, error: e instanceof Error ? e.message : String(e) });
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
json(res, 501, { success: false, error: 'Profile rescan not configured' });
|
|
138
|
-
}
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
json(res, 404, { success: false, error: 'Not found' });
|
|
142
|
-
}
|
|
143
|
-
catch (e) {
|
|
144
|
-
json(res, 500, { success: false, error: e instanceof Error ? e.message : String(e) });
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
server.listen(port, host, () => {
|
|
148
|
-
console.log(`[daemon] Diagnostics UI http://${host}:${port}/`);
|
|
149
|
-
});
|
|
150
|
-
server.on('error', (err) => {
|
|
151
|
-
console.error(`[daemon] Diagnostics server error: ${err instanceof Error ? err.message : String(err)}`);
|
|
152
|
-
});
|
|
153
|
-
return server;
|
|
154
|
-
}
|
|
155
|
-
//# sourceMappingURL=DiagnosticsServer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DiagnosticsServer.js","sourceRoot":"","sources":["../../src/core/DiagnosticsServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WinMatrix Daemon - Installation ID
|
|
3
|
-
*
|
|
4
|
-
* Generates a unique installation UUID on first run and persists it to
|
|
5
|
-
* ~/.winmatrix/installation (0600). The ~/.winmatrix directory is created
|
|
6
|
-
* with 0700 permissions. On subsequent runs, the existing ID is read back.
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Get the persisted installation ID, or generate and persist a new one.
|
|
10
|
-
* The ~/.winmatrix directory is created with 0700 if it doesn't exist.
|
|
11
|
-
* The installation file is written with 0600 permissions.
|
|
12
|
-
*/
|
|
13
|
-
export declare function getOrCreateInstallationId(): string;
|
|
14
|
-
//# sourceMappingURL=InstallationId.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"InstallationId.d.ts","sourceRoot":"","sources":["../../src/core/InstallationId.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiCH;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAelD"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WinMatrix Daemon - Installation ID
|
|
3
|
-
*
|
|
4
|
-
* Generates a unique installation UUID on first run and persists it to
|
|
5
|
-
* ~/.winmatrix/installation (0600). The ~/.winmatrix directory is created
|
|
6
|
-
* with 0700 permissions. On subsequent runs, the existing ID is read back.
|
|
7
|
-
*/
|
|
8
|
-
import { randomUUID } from 'node:crypto';
|
|
9
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from 'node:fs';
|
|
10
|
-
import { homedir } from 'node:os';
|
|
11
|
-
import path from 'node:path';
|
|
12
|
-
/* ── Constants ── */
|
|
13
|
-
const DAEMON_HOME_DIR = '.winmatrix';
|
|
14
|
-
const INSTALLATION_FILE = 'installation';
|
|
15
|
-
/* ── Helpers ── */
|
|
16
|
-
function getDaemonHome() {
|
|
17
|
-
return path.join(homedir(), DAEMON_HOME_DIR);
|
|
18
|
-
}
|
|
19
|
-
function getInstallationPath() {
|
|
20
|
-
return path.join(getDaemonHome(), INSTALLATION_FILE);
|
|
21
|
-
}
|
|
22
|
-
function ensureDaemonHome() {
|
|
23
|
-
const dir = getDaemonHome();
|
|
24
|
-
if (!existsSync(dir)) {
|
|
25
|
-
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
26
|
-
// Explicit chmod to guarantee 0700 regardless of umask
|
|
27
|
-
chmodSync(dir, 0o700);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
/* ── Public API ── */
|
|
31
|
-
/**
|
|
32
|
-
* Get the persisted installation ID, or generate and persist a new one.
|
|
33
|
-
* The ~/.winmatrix directory is created with 0700 if it doesn't exist.
|
|
34
|
-
* The installation file is written with 0600 permissions.
|
|
35
|
-
*/
|
|
36
|
-
export function getOrCreateInstallationId() {
|
|
37
|
-
ensureDaemonHome();
|
|
38
|
-
const filePath = getInstallationPath();
|
|
39
|
-
if (existsSync(filePath)) {
|
|
40
|
-
const id = readFileSync(filePath, 'utf-8').trim();
|
|
41
|
-
if (id.length > 0) {
|
|
42
|
-
return id;
|
|
43
|
-
}
|
|
44
|
-
// File exists but is empty — regenerate
|
|
45
|
-
}
|
|
46
|
-
const id = randomUUID();
|
|
47
|
-
writeFileSync(filePath, id, { mode: 0o600 });
|
|
48
|
-
return id;
|
|
49
|
-
}
|
|
50
|
-
//# sourceMappingURL=InstallationId.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"InstallationId.js","sourceRoot":"","sources":["../../src/core/InstallationId.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,qBAAqB;AAErB,MAAM,eAAe,GAAG,YAAY,CAAC;AACrC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,mBAAmB;AAEnB,SAAS,aAAa;IACpB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,iBAAiB,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACjD,uDAAuD;QACvD,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,sBAAsB;AAEtB;;;;GAIG;AACH,MAAM,UAAU,yBAAyB;IACvC,gBAAgB,EAAE,CAAC;IACnB,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;IAEvC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,wCAAwC;IAC1C,CAAC;IAED,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,aAAa,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7C,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WinMatrix Daemon - Runtime Availability Reporter
|
|
3
|
-
*
|
|
4
|
-
* Periodically re-detects runtime availability every 5 minutes and reports
|
|
5
|
-
* status changes to the WinMatrix server via the `runtime.availability` WebSocket event.
|
|
6
|
-
* Only sends events when reachability actually changes (edge-triggered).
|
|
7
|
-
*/
|
|
8
|
-
import type { DaemonClient } from '@winmatrix/agent-sdk';
|
|
9
|
-
export interface RuntimeAvailabilityEvent {
|
|
10
|
-
name: string;
|
|
11
|
-
available: boolean;
|
|
12
|
-
checkedAt: string;
|
|
13
|
-
error?: string;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Start periodic runtime availability monitoring.
|
|
17
|
-
*
|
|
18
|
-
* Every `intervalMs` the daemon re-detects all runtimes and sends
|
|
19
|
-
* `runtime.availability` events only for those whose availability
|
|
20
|
-
* has changed since the last check.
|
|
21
|
-
*
|
|
22
|
-
* @returns A stop function that clears the interval timer.
|
|
23
|
-
*/
|
|
24
|
-
export declare function startRuntimeAvailabilityReporter(client: DaemonClient, options?: {
|
|
25
|
-
intervalMs?: number;
|
|
26
|
-
}): () => void;
|
|
27
|
-
//# sourceMappingURL=RuntimeAvailabilityReporter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RuntimeAvailabilityReporter.d.ts","sourceRoot":"","sources":["../../src/core/RuntimeAvailabilityReporter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIzD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD;;;;;;;;GAQG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC,MAAM,IAAI,CAkDZ"}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WinMatrix Daemon - Runtime Availability Reporter
|
|
3
|
-
*
|
|
4
|
-
* Periodically re-detects runtime availability every 5 minutes and reports
|
|
5
|
-
* status changes to the WinMatrix server via the `runtime.availability` WebSocket event.
|
|
6
|
-
* Only sends events when reachability actually changes (edge-triggered).
|
|
7
|
-
*/
|
|
8
|
-
import { detectRuntimes } from '@winmatrix/agent-sdk';
|
|
9
|
-
/* ── Constants ── */
|
|
10
|
-
const DEFAULT_INTERVAL_MS = 5 * 60 * 1000;
|
|
11
|
-
/* ── Helpers ── */
|
|
12
|
-
function runtimeToKey(r) {
|
|
13
|
-
return r.name;
|
|
14
|
-
}
|
|
15
|
-
function buildAvailabilityEvent(r) {
|
|
16
|
-
return {
|
|
17
|
-
name: r.name,
|
|
18
|
-
available: r.available,
|
|
19
|
-
checkedAt: new Date().toISOString(),
|
|
20
|
-
...(r.available ? {} : { error: `Runtime '${r.name}' is not available` }),
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
/* ── Public API ── */
|
|
24
|
-
/**
|
|
25
|
-
* Start periodic runtime availability monitoring.
|
|
26
|
-
*
|
|
27
|
-
* Every `intervalMs` the daemon re-detects all runtimes and sends
|
|
28
|
-
* `runtime.availability` events only for those whose availability
|
|
29
|
-
* has changed since the last check.
|
|
30
|
-
*
|
|
31
|
-
* @returns A stop function that clears the interval timer.
|
|
32
|
-
*/
|
|
33
|
-
export function startRuntimeAvailabilityReporter(client, options) {
|
|
34
|
-
const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
35
|
-
const lastState = new Map();
|
|
36
|
-
let stopped = false;
|
|
37
|
-
const sendEvent = (event) => {
|
|
38
|
-
if (stopped)
|
|
39
|
-
return;
|
|
40
|
-
if (client.getState() !== 'registered')
|
|
41
|
-
return;
|
|
42
|
-
try {
|
|
43
|
-
client.sendFrame({
|
|
44
|
-
type: 'event',
|
|
45
|
-
event: 'runtime.availability',
|
|
46
|
-
payload: event,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
// Ignore send errors — will retry next interval
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
const tick = () => {
|
|
54
|
-
if (stopped)
|
|
55
|
-
return;
|
|
56
|
-
if (client.getState() !== 'registered')
|
|
57
|
-
return;
|
|
58
|
-
const runtimes = detectRuntimes();
|
|
59
|
-
for (const runtime of runtimes) {
|
|
60
|
-
const key = runtimeToKey(runtime);
|
|
61
|
-
const previous = lastState.get(key);
|
|
62
|
-
if (previous !== runtime.available) {
|
|
63
|
-
lastState.set(key, runtime.available);
|
|
64
|
-
sendEvent(buildAvailabilityEvent(runtime));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
// Run immediately on start to establish baseline
|
|
69
|
-
const runtimes = detectRuntimes();
|
|
70
|
-
for (const runtime of runtimes) {
|
|
71
|
-
lastState.set(runtimeToKey(runtime), runtime.available);
|
|
72
|
-
}
|
|
73
|
-
const timer = setInterval(tick, intervalMs);
|
|
74
|
-
return () => {
|
|
75
|
-
stopped = true;
|
|
76
|
-
clearInterval(timer);
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
//# sourceMappingURL=RuntimeAvailabilityReporter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RuntimeAvailabilityReporter.js","sourceRoot":"","sources":["../../src/core/RuntimeAvailabilityReporter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAgB,MAAM,sBAAsB,CAAC;AAYpE,qBAAqB;AAErB,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE1C,mBAAmB;AAEnB,SAAS,YAAY,CAAC,CAAU;IAC9B,OAAO,CAAC,CAAC,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,sBAAsB,CAAC,CAAU;IACxC,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,IAAI,oBAAoB,EAAE,CAAC;KAC1E,CAAC;AACJ,CAAC;AAED,sBAAsB;AAEtB;;;;;;;;GAQG;AACH,MAAM,UAAU,gCAAgC,CAC9C,MAAoB,EACpB,OAAiC;IAEjC,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,mBAAmB,CAAC;IAE9D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC7C,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,SAAS,GAAG,CAAC,KAA+B,EAAQ,EAAE;QAC1D,IAAI,OAAO;YAAE,OAAO;QACpB,IAAI,MAAM,CAAC,QAAQ,EAAE,KAAK,YAAY;YAAE,OAAO;QAE/C,IAAI,CAAC;YACH,MAAM,CAAC,SAAS,CAAC;gBACf,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,sBAAsB;gBAC7B,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,gDAAgD;QAClD,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,IAAI,OAAO;YAAE,OAAO;QACpB,IAAI,MAAM,CAAC,QAAQ,EAAE,KAAK,YAAY;YAAE,OAAO;QAE/C,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAElC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YAClC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEpC,IAAI,QAAQ,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;gBACnC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;gBACtC,SAAS,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,iDAAiD;IACjD,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAClC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAE5C,OAAO,GAAG,EAAE;QACV,OAAO,GAAG,IAAI,CAAC;QACf,aAAa,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WorkspaceScanner - 扫描 workDir 获取项目元数据
|
|
3
|
-
*
|
|
4
|
-
* 在 Agent 注册成功后调用,将扫描结果通过 Daemon WS 上报至 Server。
|
|
5
|
-
* 安全约束:不上报绝对路径、文件内容、环境变量、含凭据的 Git remote。
|
|
6
|
-
*/
|
|
7
|
-
interface TechStack {
|
|
8
|
-
[key: string]: string;
|
|
9
|
-
}
|
|
10
|
-
interface WorkspaceInfo {
|
|
11
|
-
pathSummary: string;
|
|
12
|
-
gitRemote?: string;
|
|
13
|
-
gitBranch?: string;
|
|
14
|
-
techStack?: TechStack;
|
|
15
|
-
scripts?: Record<string, string>;
|
|
16
|
-
installedCli?: string[];
|
|
17
|
-
}
|
|
18
|
-
interface RuntimeInfo {
|
|
19
|
-
version?: string;
|
|
20
|
-
available: boolean;
|
|
21
|
-
}
|
|
22
|
-
export interface WorkspaceReportPayload {
|
|
23
|
-
agentId: string;
|
|
24
|
-
workdir?: WorkspaceInfo;
|
|
25
|
-
runtimes?: Record<string, RuntimeInfo>;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* 扫描指定工作目录,提取项目元数据。
|
|
29
|
-
* 所有 git/which 调用均带 5s 超时,失败不影响整体结果。
|
|
30
|
-
*/
|
|
31
|
-
export declare function scanWorkDir(workDir: string): Promise<WorkspaceInfo>;
|
|
32
|
-
/**
|
|
33
|
-
* 脱敏 Git remote URL:
|
|
34
|
-
* - HTTPS: 移除 userinfo(用户名:密码@)
|
|
35
|
-
* - SSH: 保持原样(git@host:org/repo)
|
|
36
|
-
* - 仅保留 host/org/repo
|
|
37
|
-
*/
|
|
38
|
-
export declare function sanitizeGitRemote(remote: string): string;
|
|
39
|
-
/**
|
|
40
|
-
* 检测运行时可用的运行时版本信息。
|
|
41
|
-
* 基于 agentType 选择性检测,避免不必要的磁盘扫描。
|
|
42
|
-
*/
|
|
43
|
-
export declare function detectRuntimeInfo(runtimeBinary: string): Promise<RuntimeInfo>;
|
|
44
|
-
export {};
|
|
45
|
-
//# sourceMappingURL=WorkspaceScanner.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WorkspaceScanner.d.ts","sourceRoot":"","sources":["../../src/core/WorkspaceScanner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,UAAU,SAAS;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,UAAU,aAAa;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACxC;AAQD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA2HzE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAaxD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAQnF"}
|