@daomar/agentfleet 2.0.0
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/LICENSE +21 -0
- package/README.md +310 -0
- package/README.zh-CN.md +310 -0
- package/assets/icon.png +0 -0
- package/assets/icon.svg +51 -0
- package/assets/og-image.svg +57 -0
- package/assets/paypal-donation.png +0 -0
- package/assets/wechat-donation.jpg +0 -0
- package/dist/cli.js +86 -0
- package/dist/commands/install.js +68 -0
- package/dist/commands/run.js +136 -0
- package/dist/commands/status.js +215 -0
- package/dist/commands/stop.js +37 -0
- package/dist/commands/submit.js +72 -0
- package/dist/commands/uninstall.js +41 -0
- package/dist/locales/en-US.json +162 -0
- package/dist/locales/zh-CN.json +162 -0
- package/dist/services/agent-executor.js +143 -0
- package/dist/services/auto-start.js +41 -0
- package/dist/services/bootstrap.js +24 -0
- package/dist/services/daemon.js +192 -0
- package/dist/services/i18n.js +150 -0
- package/dist/services/logger.js +99 -0
- package/dist/services/macos-auto-start.js +126 -0
- package/dist/services/onedrive-detector.js +158 -0
- package/dist/services/provider-selection.js +132 -0
- package/dist/services/result-writer.js +85 -0
- package/dist/services/setup.js +219 -0
- package/dist/services/shortcut.js +159 -0
- package/dist/services/task-watcher.js +199 -0
- package/dist/services/version-checker.js +93 -0
- package/dist/services/windows-service.js +125 -0
- package/dist/types/index.js +12 -0
- package/package.json +59 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DaemonService = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const child_process_1 = require("child_process");
|
|
41
|
+
class DaemonService {
|
|
42
|
+
constructor(deps = {}) {
|
|
43
|
+
this.deps = deps;
|
|
44
|
+
const home = deps.homedir ?? os.homedir();
|
|
45
|
+
this.agentfleetDir = path.join(home, '.agentfleet');
|
|
46
|
+
this.pidPath = path.join(this.agentfleetDir, 'agentfleet.pid');
|
|
47
|
+
this.defaultLogPath = path.join(this.agentfleetDir, 'agentfleet.log');
|
|
48
|
+
}
|
|
49
|
+
getPidPath() {
|
|
50
|
+
return this.pidPath;
|
|
51
|
+
}
|
|
52
|
+
getDefaultLogPath() {
|
|
53
|
+
return this.defaultLogPath;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Write the current process PID to the PID file.
|
|
57
|
+
*/
|
|
58
|
+
writePid(pid) {
|
|
59
|
+
if (!fs.existsSync(this.agentfleetDir)) {
|
|
60
|
+
fs.mkdirSync(this.agentfleetDir, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
fs.writeFileSync(this.pidPath, String(pid), 'utf-8');
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Read the PID from the PID file, or null if it doesn't exist.
|
|
66
|
+
*/
|
|
67
|
+
readPid() {
|
|
68
|
+
try {
|
|
69
|
+
if (!fs.existsSync(this.pidPath))
|
|
70
|
+
return null;
|
|
71
|
+
const content = fs.readFileSync(this.pidPath, 'utf-8').trim();
|
|
72
|
+
const pid = parseInt(content, 10);
|
|
73
|
+
return isNaN(pid) ? null : pid;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Remove the PID file.
|
|
81
|
+
*/
|
|
82
|
+
removePid() {
|
|
83
|
+
try {
|
|
84
|
+
if (fs.existsSync(this.pidPath)) {
|
|
85
|
+
fs.unlinkSync(this.pidPath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// ignore cleanup errors
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if a process with the given PID is still running.
|
|
94
|
+
*/
|
|
95
|
+
isRunning(pid) {
|
|
96
|
+
if (this.deps.killCheck) {
|
|
97
|
+
return this.deps.killCheck(pid);
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
process.kill(pid, 0);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if another daemon instance is already running.
|
|
109
|
+
* Returns the existing PID if running, null otherwise.
|
|
110
|
+
* Cleans up stale PID files automatically.
|
|
111
|
+
*/
|
|
112
|
+
checkExistingDaemon() {
|
|
113
|
+
const pid = this.readPid();
|
|
114
|
+
if (pid === null)
|
|
115
|
+
return null;
|
|
116
|
+
if (this.isRunning(pid)) {
|
|
117
|
+
return pid;
|
|
118
|
+
}
|
|
119
|
+
// Stale PID file — clean up
|
|
120
|
+
this.removePid();
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Spawn the current process as a detached daemon child.
|
|
125
|
+
* Returns the child PID.
|
|
126
|
+
*/
|
|
127
|
+
spawnDetached(originalArgs, logFilePath) {
|
|
128
|
+
const logPath = logFilePath ?? this.defaultLogPath;
|
|
129
|
+
const logDir = path.dirname(logPath);
|
|
130
|
+
if (!fs.existsSync(logDir)) {
|
|
131
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
132
|
+
}
|
|
133
|
+
// Build child args: remove --daemon, add --_daemon-child, pass --log-file
|
|
134
|
+
const childArgs = this.buildChildArgs(originalArgs, logPath);
|
|
135
|
+
const execPath = this.deps.execPath ?? process.execPath;
|
|
136
|
+
if (os.platform() === 'win32' && !this.deps.spawnFn) {
|
|
137
|
+
// On Windows, use PowerShell Start-Process -WindowStyle Hidden to avoid console flash
|
|
138
|
+
const argsStr = childArgs.map(a => `'${a.replace(/'/g, "''")}'`).join(',');
|
|
139
|
+
const psCmd = `Start-Process -FilePath '${execPath}' -ArgumentList ${argsStr} -WindowStyle Hidden -PassThru | Select-Object -ExpandProperty Id`;
|
|
140
|
+
const pidStr = (0, child_process_1.execSync)(`powershell -NoProfile -Command "${psCmd}"`, {
|
|
141
|
+
encoding: 'utf-8',
|
|
142
|
+
windowsHide: true,
|
|
143
|
+
}).trim();
|
|
144
|
+
return parseInt(pidStr, 10);
|
|
145
|
+
}
|
|
146
|
+
// Non-Windows or test: use spawn with detached
|
|
147
|
+
const logFd = fs.openSync(logPath, 'a');
|
|
148
|
+
const spawnFn = this.deps.spawnFn ?? child_process_1.spawn;
|
|
149
|
+
const child = spawnFn(execPath, childArgs, {
|
|
150
|
+
detached: true,
|
|
151
|
+
stdio: ['ignore', logFd, logFd],
|
|
152
|
+
env: process.env,
|
|
153
|
+
windowsHide: true,
|
|
154
|
+
});
|
|
155
|
+
child.unref();
|
|
156
|
+
const childPid = child.pid;
|
|
157
|
+
// Close the fd in the parent
|
|
158
|
+
fs.closeSync(logFd);
|
|
159
|
+
return childPid;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Build arguments for the daemon child process.
|
|
163
|
+
* Removes --daemon, adds --_daemon-child and --log-file.
|
|
164
|
+
*/
|
|
165
|
+
buildChildArgs(originalArgs, logFilePath) {
|
|
166
|
+
// originalArgs is typically process.argv.slice(1) to skip the node executable
|
|
167
|
+
const filtered = [];
|
|
168
|
+
let skipNext = false;
|
|
169
|
+
for (let i = 0; i < originalArgs.length; i++) {
|
|
170
|
+
if (skipNext) {
|
|
171
|
+
skipNext = false;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const arg = originalArgs[i];
|
|
175
|
+
if (arg === '--daemon' || arg === '-d')
|
|
176
|
+
continue;
|
|
177
|
+
if (arg === '--log-file') {
|
|
178
|
+
skipNext = true; // skip the value too
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (arg.startsWith('--log-file='))
|
|
182
|
+
continue;
|
|
183
|
+
filtered.push(arg);
|
|
184
|
+
}
|
|
185
|
+
// Add the internal flag and log-file
|
|
186
|
+
filtered.push('--_daemon-child');
|
|
187
|
+
filtered.push('--log-file', logFilePath);
|
|
188
|
+
return filtered;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
exports.DaemonService = DaemonService;
|
|
192
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getLocale = exports.formatRelativeTime = exports.formatDate = exports.t = void 0;
|
|
37
|
+
exports.detectLocale = detectLocale;
|
|
38
|
+
exports.createI18n = createI18n;
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const SUPPORTED_LOCALES = ['en-US', 'zh-CN'];
|
|
42
|
+
/**
|
|
43
|
+
* Load a message catalog JSON file for the given locale.
|
|
44
|
+
*/
|
|
45
|
+
function loadCatalog(locale) {
|
|
46
|
+
// Try loading from dist/locales/ first (npm package), then from src/locales/ (development)
|
|
47
|
+
const distPath = path.join(__dirname, '..', 'locales', `${locale}.json`);
|
|
48
|
+
const srcPath = path.join(__dirname, '..', '..', 'src', 'locales', `${locale}.json`);
|
|
49
|
+
let catalogPath = distPath;
|
|
50
|
+
if (!fs.existsSync(distPath)) {
|
|
51
|
+
catalogPath = srcPath;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const content = fs.readFileSync(catalogPath, 'utf-8');
|
|
55
|
+
return JSON.parse(content);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Detect the user's preferred locale.
|
|
63
|
+
*
|
|
64
|
+
* Precedence:
|
|
65
|
+
* 1. AGENTFLEET_LANG environment variable
|
|
66
|
+
* 2. OS display language via Intl.DateTimeFormat
|
|
67
|
+
* 3. Falls back to en-US
|
|
68
|
+
*
|
|
69
|
+
* Any zh-* locale maps to zh-CN; everything else maps to en-US.
|
|
70
|
+
*/
|
|
71
|
+
function detectLocale() {
|
|
72
|
+
// 1. Check AGENTFLEET_LANG env var
|
|
73
|
+
const envLang = process.env.AGENTFLEET_LANG;
|
|
74
|
+
if (envLang) {
|
|
75
|
+
return mapLocale(envLang);
|
|
76
|
+
}
|
|
77
|
+
// 2. Check OS display language via Intl
|
|
78
|
+
try {
|
|
79
|
+
const osLocale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
80
|
+
return mapLocale(osLocale);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Intl not available
|
|
84
|
+
}
|
|
85
|
+
// 3. Default
|
|
86
|
+
return 'en-US';
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Map a locale string to a supported locale.
|
|
90
|
+
* Any zh-* maps to zh-CN; everything else maps to en-US.
|
|
91
|
+
*/
|
|
92
|
+
function mapLocale(locale) {
|
|
93
|
+
if (locale.startsWith('zh')) {
|
|
94
|
+
return 'zh-CN';
|
|
95
|
+
}
|
|
96
|
+
return 'en-US';
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create an i18n instance for the given locale.
|
|
100
|
+
*/
|
|
101
|
+
function createI18n(locale) {
|
|
102
|
+
const messages = loadCatalog(locale);
|
|
103
|
+
const fallback = locale !== 'en-US' ? loadCatalog('en-US') : {};
|
|
104
|
+
function t(key, params) {
|
|
105
|
+
let msg = messages[key] ?? fallback[key] ?? key;
|
|
106
|
+
if (params) {
|
|
107
|
+
for (const [k, v] of Object.entries(params)) {
|
|
108
|
+
msg = msg.replace(`{${k}}`, String(v));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return msg;
|
|
112
|
+
}
|
|
113
|
+
function formatDate(date) {
|
|
114
|
+
return new Intl.DateTimeFormat(locale, {
|
|
115
|
+
year: 'numeric',
|
|
116
|
+
month: 'short',
|
|
117
|
+
day: 'numeric',
|
|
118
|
+
hour: '2-digit',
|
|
119
|
+
minute: '2-digit',
|
|
120
|
+
}).format(new Date(date));
|
|
121
|
+
}
|
|
122
|
+
function formatRelativeTime(date) {
|
|
123
|
+
const seconds = Math.round((Date.now() - new Date(date).getTime()) / 1000);
|
|
124
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
|
|
125
|
+
if (seconds < 60)
|
|
126
|
+
return rtf.format(-seconds, 'second');
|
|
127
|
+
if (seconds < 3600)
|
|
128
|
+
return rtf.format(-Math.round(seconds / 60), 'minute');
|
|
129
|
+
if (seconds < 86400)
|
|
130
|
+
return rtf.format(-Math.round(seconds / 3600), 'hour');
|
|
131
|
+
return rtf.format(-Math.round(seconds / 86400), 'day');
|
|
132
|
+
}
|
|
133
|
+
function getLocale() {
|
|
134
|
+
return locale;
|
|
135
|
+
}
|
|
136
|
+
return { t, formatDate, formatRelativeTime, getLocale };
|
|
137
|
+
}
|
|
138
|
+
// --- Singleton instance ---
|
|
139
|
+
// Initialized with detected locale on first import.
|
|
140
|
+
const _locale = detectLocale();
|
|
141
|
+
const _instance = createI18n(_locale);
|
|
142
|
+
/** Translate a message key using the auto-detected locale. */
|
|
143
|
+
exports.t = _instance.t;
|
|
144
|
+
/** Format a date using the auto-detected locale. */
|
|
145
|
+
exports.formatDate = _instance.formatDate;
|
|
146
|
+
/** Format a relative time using the auto-detected locale. */
|
|
147
|
+
exports.formatRelativeTime = _instance.formatRelativeTime;
|
|
148
|
+
/** Get the current locale. */
|
|
149
|
+
exports.getLocale = _instance.getLocale;
|
|
150
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Logger = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
class Logger {
|
|
40
|
+
constructor() {
|
|
41
|
+
this.logStream = null;
|
|
42
|
+
this.originalLog = null;
|
|
43
|
+
this.originalError = null;
|
|
44
|
+
this.originalWarn = null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Set up logging to a file. Redirects console.log, console.error, and console.warn
|
|
48
|
+
* to write timestamped entries to the specified file.
|
|
49
|
+
*/
|
|
50
|
+
setup(logFilePath) {
|
|
51
|
+
const logDir = path.dirname(logFilePath);
|
|
52
|
+
if (!fs.existsSync(logDir)) {
|
|
53
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
this.logStream = fs.createWriteStream(logFilePath, { flags: 'a' });
|
|
56
|
+
this.originalLog = console.log;
|
|
57
|
+
this.originalError = console.error;
|
|
58
|
+
this.originalWarn = console.warn;
|
|
59
|
+
console.log = (...args) => {
|
|
60
|
+
this.writeEntry('INFO', args);
|
|
61
|
+
};
|
|
62
|
+
console.error = (...args) => {
|
|
63
|
+
this.writeEntry('ERROR', args);
|
|
64
|
+
};
|
|
65
|
+
console.warn = (...args) => {
|
|
66
|
+
this.writeEntry('WARN', args);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Restore original console methods and close the log stream.
|
|
71
|
+
*/
|
|
72
|
+
restore() {
|
|
73
|
+
if (this.originalLog) {
|
|
74
|
+
console.log = this.originalLog;
|
|
75
|
+
this.originalLog = null;
|
|
76
|
+
}
|
|
77
|
+
if (this.originalError) {
|
|
78
|
+
console.error = this.originalError;
|
|
79
|
+
this.originalError = null;
|
|
80
|
+
}
|
|
81
|
+
if (this.originalWarn) {
|
|
82
|
+
console.warn = this.originalWarn;
|
|
83
|
+
this.originalWarn = null;
|
|
84
|
+
}
|
|
85
|
+
if (this.logStream) {
|
|
86
|
+
this.logStream.end();
|
|
87
|
+
this.logStream = null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
writeEntry(level, args) {
|
|
91
|
+
if (!this.logStream)
|
|
92
|
+
return;
|
|
93
|
+
const timestamp = new Date().toISOString();
|
|
94
|
+
const message = args.map(a => (typeof a === 'string' ? a : JSON.stringify(a))).join(' ');
|
|
95
|
+
this.logStream.write(`${timestamp} [${level}] ${message}\n`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.Logger = Logger;
|
|
99
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LaunchAgentManager = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const child_process_1 = require("child_process");
|
|
41
|
+
const LABEL = 'dev.daomar.agentfleet';
|
|
42
|
+
class LaunchAgentManager {
|
|
43
|
+
constructor(deps = {}) {
|
|
44
|
+
this.deps = deps;
|
|
45
|
+
const home = deps.homedir ?? os.homedir();
|
|
46
|
+
this.launchAgentsDir = path.join(home, 'Library', 'LaunchAgents');
|
|
47
|
+
this.plistPath = path.join(this.launchAgentsDir, `${LABEL}.plist`);
|
|
48
|
+
this.uid = deps.uid ?? process.getuid?.() ?? 0;
|
|
49
|
+
}
|
|
50
|
+
isSupported() {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
getName() {
|
|
54
|
+
return LABEL;
|
|
55
|
+
}
|
|
56
|
+
queryState() {
|
|
57
|
+
return fs.existsSync(this.plistPath) ? 'installed' : 'not-installed';
|
|
58
|
+
}
|
|
59
|
+
install() {
|
|
60
|
+
if (!fs.existsSync(this.launchAgentsDir)) {
|
|
61
|
+
fs.mkdirSync(this.launchAgentsDir, { recursive: true });
|
|
62
|
+
}
|
|
63
|
+
fs.writeFileSync(this.plistPath, this.buildPlist(), 'utf-8');
|
|
64
|
+
this.start();
|
|
65
|
+
}
|
|
66
|
+
uninstall() {
|
|
67
|
+
try {
|
|
68
|
+
this.exec(`launchctl bootout gui/${this.uid}/${LABEL}`);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Ignore bootout failures when the agent is not currently loaded.
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
if (fs.existsSync(this.plistPath)) {
|
|
75
|
+
fs.unlinkSync(this.plistPath);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// ignore cleanup errors
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
start() {
|
|
83
|
+
try {
|
|
84
|
+
this.exec(`launchctl bootstrap gui/${this.uid} "${this.plistPath}"`);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Ignore bootstrap failures when the agent is already loaded.
|
|
88
|
+
}
|
|
89
|
+
this.exec(`launchctl kickstart -k gui/${this.uid}/${LABEL}`);
|
|
90
|
+
}
|
|
91
|
+
exec(cmd) {
|
|
92
|
+
const execFn = this.deps.execSyncFn ?? ((command, opts) => (0, child_process_1.execSync)(command, {
|
|
93
|
+
encoding: 'utf-8',
|
|
94
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
95
|
+
...opts,
|
|
96
|
+
}));
|
|
97
|
+
return execFn(cmd);
|
|
98
|
+
}
|
|
99
|
+
buildPlist() {
|
|
100
|
+
return [
|
|
101
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
102
|
+
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
|
103
|
+
'<plist version="1.0">',
|
|
104
|
+
'<dict>',
|
|
105
|
+
' <key>Label</key>',
|
|
106
|
+
` <string>${LABEL}</string>`,
|
|
107
|
+
' <key>ProgramArguments</key>',
|
|
108
|
+
' <array>',
|
|
109
|
+
' <string>npx</string>',
|
|
110
|
+
' <string>-y</string>',
|
|
111
|
+
' <string>@daomar/agentfleet</string>',
|
|
112
|
+
' <string>run</string>',
|
|
113
|
+
' <string>-d</string>',
|
|
114
|
+
' </array>',
|
|
115
|
+
' <key>RunAtLoad</key>',
|
|
116
|
+
' <true/>',
|
|
117
|
+
' <key>KeepAlive</key>',
|
|
118
|
+
' <false/>',
|
|
119
|
+
'</dict>',
|
|
120
|
+
'</plist>',
|
|
121
|
+
'',
|
|
122
|
+
].join('\n');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.LaunchAgentManager = LaunchAgentManager;
|
|
126
|
+
//# sourceMappingURL=macos-auto-start.js.map
|