@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.
@@ -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