@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
package/assets/icon.svg
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="76" y1="64" x2="436" y2="452" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#1A2422"/>
|
|
5
|
+
<stop offset="0.58" stop-color="#111817"/>
|
|
6
|
+
<stop offset="1" stop-color="#0B1112"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<radialGradient id="glow" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(388 112) rotate(141.76) scale(232.819)">
|
|
9
|
+
<stop stop-color="#F5B35D" stop-opacity="0.38"/>
|
|
10
|
+
<stop offset="1" stop-color="#F5B35D" stop-opacity="0"/>
|
|
11
|
+
</radialGradient>
|
|
12
|
+
<linearGradient id="fleet" x1="146" y1="338" x2="374" y2="158" gradientUnits="userSpaceOnUse">
|
|
13
|
+
<stop stop-color="#D24C2A"/>
|
|
14
|
+
<stop offset="0.58" stop-color="#E7773A"/>
|
|
15
|
+
<stop offset="1" stop-color="#F5B35D"/>
|
|
16
|
+
</linearGradient>
|
|
17
|
+
<linearGradient id="trail" x1="118" y1="366" x2="345" y2="208" gradientUnits="userSpaceOnUse">
|
|
18
|
+
<stop stop-color="#7EA996" stop-opacity="0.08"/>
|
|
19
|
+
<stop offset="0.5" stop-color="#C5E1D2" stop-opacity="0.35"/>
|
|
20
|
+
<stop offset="1" stop-color="#F7EAD1" stop-opacity="0.75"/>
|
|
21
|
+
</linearGradient>
|
|
22
|
+
</defs>
|
|
23
|
+
|
|
24
|
+
<rect x="28" y="28" width="456" height="456" rx="126" fill="url(#bg)"/>
|
|
25
|
+
<rect x="40" y="40" width="432" height="432" rx="114" stroke="#F7EAD1" stroke-opacity="0.1" stroke-width="2"/>
|
|
26
|
+
<circle cx="388" cy="112" r="176" fill="url(#glow)"/>
|
|
27
|
+
|
|
28
|
+
<g stroke-linecap="round" fill="none">
|
|
29
|
+
<path d="M122 354C176 350 226 322 270 274C308 234 346 204 388 178" stroke="url(#trail)" stroke-width="18"/>
|
|
30
|
+
<path d="M122 392C182 386 236 354 286 306C320 274 354 246 392 224" stroke="#7EA996" stroke-opacity="0.22" stroke-width="10"/>
|
|
31
|
+
<path d="M120 316C168 312 210 286 250 244C290 202 326 176 366 152" stroke="#F7EAD1" stroke-opacity="0.18" stroke-width="6"/>
|
|
32
|
+
</g>
|
|
33
|
+
|
|
34
|
+
<g transform="translate(180 332) rotate(-24)">
|
|
35
|
+
<path d="M-52 0L0 -44L98 0L0 44L-18 0Z" fill="url(#fleet)"/>
|
|
36
|
+
<path d="M2 -18L44 0L2 18L20 0Z" fill="#F7EAD1" fill-opacity="0.88"/>
|
|
37
|
+
<circle cx="-66" cy="0" r="10" fill="#7EA996"/>
|
|
38
|
+
</g>
|
|
39
|
+
|
|
40
|
+
<g transform="translate(256 256) rotate(-24)">
|
|
41
|
+
<path d="M-64 0L0 -54L122 0L0 54L-22 0Z" fill="url(#fleet)"/>
|
|
42
|
+
<path d="M4 -22L56 0L4 22L26 0Z" fill="#F7EAD1" fill-opacity="0.9"/>
|
|
43
|
+
<circle cx="-82" cy="0" r="12" fill="#7EA996"/>
|
|
44
|
+
</g>
|
|
45
|
+
|
|
46
|
+
<g transform="translate(336 178) rotate(-24)">
|
|
47
|
+
<path d="M-74 0L0 -62L138 0L0 62L-24 0Z" fill="url(#fleet)"/>
|
|
48
|
+
<path d="M6 -24L64 0L6 24L30 0Z" fill="#F7EAD1" fill-opacity="0.92"/>
|
|
49
|
+
<circle cx="-94" cy="0" r="14" fill="#7EA996"/>
|
|
50
|
+
</g>
|
|
51
|
+
</svg>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<svg width="1200" height="630" viewBox="0 0 1200 630" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="92" y1="58" x2="1094" y2="612" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#1A2422"/>
|
|
5
|
+
<stop offset="0.55" stop-color="#111817"/>
|
|
6
|
+
<stop offset="1" stop-color="#0B1112"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<radialGradient id="sun" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(934 122) rotate(145.655) scale(394.372 288.847)">
|
|
9
|
+
<stop stop-color="#F5B35D" stop-opacity="0.32"/>
|
|
10
|
+
<stop offset="1" stop-color="#F5B35D" stop-opacity="0"/>
|
|
11
|
+
</radialGradient>
|
|
12
|
+
<linearGradient id="fleet" x1="180" y1="414" x2="518" y2="156" gradientUnits="userSpaceOnUse">
|
|
13
|
+
<stop stop-color="#D24C2A"/>
|
|
14
|
+
<stop offset="0.58" stop-color="#E7773A"/>
|
|
15
|
+
<stop offset="1" stop-color="#F5B35D"/>
|
|
16
|
+
</linearGradient>
|
|
17
|
+
<linearGradient id="trail" x1="154" y1="458" x2="512" y2="220" gradientUnits="userSpaceOnUse">
|
|
18
|
+
<stop stop-color="#7EA996" stop-opacity="0.08"/>
|
|
19
|
+
<stop offset="0.5" stop-color="#C5E1D2" stop-opacity="0.35"/>
|
|
20
|
+
<stop offset="1" stop-color="#F7EAD1" stop-opacity="0.75"/>
|
|
21
|
+
</linearGradient>
|
|
22
|
+
</defs>
|
|
23
|
+
|
|
24
|
+
<rect width="1200" height="630" rx="36" fill="url(#bg)"/>
|
|
25
|
+
<rect x="28" y="28" width="1144" height="574" rx="24" stroke="#F7EAD1" stroke-opacity="0.1" stroke-width="2"/>
|
|
26
|
+
<circle cx="934" cy="122" r="260" fill="url(#sun)"/>
|
|
27
|
+
|
|
28
|
+
<g stroke-linecap="round" fill="none">
|
|
29
|
+
<path d="M150 456C232 448 302 404 366 340C424 282 482 238 548 200" stroke="url(#trail)" stroke-width="24"/>
|
|
30
|
+
<path d="M152 518C242 510 322 464 394 394C444 346 496 306 556 272" stroke="#7EA996" stroke-opacity="0.22" stroke-width="14"/>
|
|
31
|
+
<path d="M146 400C214 394 274 358 334 296C392 236 446 196 506 160" stroke="#F7EAD1" stroke-opacity="0.18" stroke-width="8"/>
|
|
32
|
+
</g>
|
|
33
|
+
|
|
34
|
+
<g transform="translate(242 420) rotate(-24)">
|
|
35
|
+
<path d="M-74 0L0 -62L138 0L0 62L-24 0Z" fill="url(#fleet)"/>
|
|
36
|
+
<path d="M6 -24L64 0L6 24L30 0Z" fill="#F7EAD1" fill-opacity="0.92"/>
|
|
37
|
+
<circle cx="-94" cy="0" r="14" fill="#7EA996"/>
|
|
38
|
+
</g>
|
|
39
|
+
|
|
40
|
+
<g transform="translate(354 330) rotate(-24)">
|
|
41
|
+
<path d="M-92 0L0 -76L172 0L0 76L-30 0Z" fill="url(#fleet)"/>
|
|
42
|
+
<path d="M8 -30L80 0L8 30L38 0Z" fill="#F7EAD1" fill-opacity="0.92"/>
|
|
43
|
+
<circle cx="-116" cy="0" r="18" fill="#7EA996"/>
|
|
44
|
+
</g>
|
|
45
|
+
|
|
46
|
+
<g transform="translate(482 228) rotate(-24)">
|
|
47
|
+
<path d="M-112 0L0 -94L210 0L0 94L-36 0Z" fill="url(#fleet)"/>
|
|
48
|
+
<path d="M10 -38L98 0L10 38L46 0Z" fill="#F7EAD1" fill-opacity="0.94"/>
|
|
49
|
+
<circle cx="-140" cy="0" r="22" fill="#7EA996"/>
|
|
50
|
+
</g>
|
|
51
|
+
|
|
52
|
+
<text x="620" y="210" fill="#7EA996" font-family="Georgia, 'Times New Roman', serif" font-size="30" letter-spacing="7">DAOMAR PRODUCT</text>
|
|
53
|
+
<text x="620" y="308" fill="#F7EAD1" font-family="Georgia, 'Times New Roman', serif" font-size="94" font-weight="700">AgentFleet</text>
|
|
54
|
+
<text x="620" y="380" fill="#F5B35D" font-family="Georgia, 'Times New Roman', serif" font-size="38">Distributed agent orchestration</text>
|
|
55
|
+
<text x="620" y="432" fill="#D8DDDA" font-family="Georgia, 'Times New Roman', serif" font-size="28">Without a control plane.</text>
|
|
56
|
+
<text x="620" y="512" fill="#C5E1D2" font-family="Georgia, 'Times New Roman', serif" font-size="26">agentfleet.daomar.dev</text>
|
|
57
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.getShortcutResult = getShortcutResult;
|
|
5
|
+
const commander_1 = require("commander");
|
|
6
|
+
const run_1 = require("./commands/run");
|
|
7
|
+
const submit_1 = require("./commands/submit");
|
|
8
|
+
const status_1 = require("./commands/status");
|
|
9
|
+
const stop_1 = require("./commands/stop");
|
|
10
|
+
const install_1 = require("./commands/install");
|
|
11
|
+
const uninstall_1 = require("./commands/uninstall");
|
|
12
|
+
const version_checker_1 = require("./services/version-checker");
|
|
13
|
+
const i18n_1 = require("./services/i18n");
|
|
14
|
+
const shortcut_1 = require("./services/shortcut");
|
|
15
|
+
const packageJson = require('../package.json');
|
|
16
|
+
const program = new commander_1.Command();
|
|
17
|
+
// Run shortcut registration (non-blocking, errors silently caught)
|
|
18
|
+
let shortcutResult;
|
|
19
|
+
try {
|
|
20
|
+
const shortcutService = new shortcut_1.ShortcutService();
|
|
21
|
+
shortcutResult = shortcutService.ensureShortcut();
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// silently ignore
|
|
25
|
+
}
|
|
26
|
+
// Export for use by run/install commands
|
|
27
|
+
function getShortcutResult() {
|
|
28
|
+
return shortcutResult;
|
|
29
|
+
}
|
|
30
|
+
program
|
|
31
|
+
.name('agentfleet')
|
|
32
|
+
.description((0, i18n_1.t)('cli.description'))
|
|
33
|
+
.version(packageJson.version);
|
|
34
|
+
program
|
|
35
|
+
.command('run')
|
|
36
|
+
.description((0, i18n_1.t)('cli.run_description'))
|
|
37
|
+
.option('--poll-interval <seconds>', (0, i18n_1.t)('cli.run_option_poll'), '10')
|
|
38
|
+
.option('--concurrency <number>', (0, i18n_1.t)('cli.run_option_concurrency'), '1')
|
|
39
|
+
.option('-d, --daemon', (0, i18n_1.t)('cli.run_option_daemon'))
|
|
40
|
+
.option('--log-file <path>', (0, i18n_1.t)('cli.run_option_log_file'))
|
|
41
|
+
.addOption(new commander_1.Option('--_daemon-child').hideHelp())
|
|
42
|
+
.action(run_1.runCommand);
|
|
43
|
+
program
|
|
44
|
+
.command('submit')
|
|
45
|
+
.description((0, i18n_1.t)('cli.submit_description'))
|
|
46
|
+
.requiredOption('--prompt <text>', (0, i18n_1.t)('cli.submit_option_prompt'))
|
|
47
|
+
.option('--title <text>', (0, i18n_1.t)('cli.submit_option_title'))
|
|
48
|
+
.option('--working-dir <path>', (0, i18n_1.t)('cli.submit_option_working_dir'), process.cwd())
|
|
49
|
+
.option('--agent <command>', (0, i18n_1.t)('cli.submit_option_agent'))
|
|
50
|
+
.action(submit_1.submitCommand);
|
|
51
|
+
program
|
|
52
|
+
.command('status [taskId]')
|
|
53
|
+
.description((0, i18n_1.t)('cli.status_description'))
|
|
54
|
+
.action(status_1.statusCommand);
|
|
55
|
+
program
|
|
56
|
+
.command('stop')
|
|
57
|
+
.description((0, i18n_1.t)('cli.stop_description'))
|
|
58
|
+
.action(stop_1.stopCommand);
|
|
59
|
+
program
|
|
60
|
+
.command('install')
|
|
61
|
+
.description((0, i18n_1.t)('cli.install_description'))
|
|
62
|
+
.action(install_1.installCommand);
|
|
63
|
+
program
|
|
64
|
+
.command('uninstall')
|
|
65
|
+
.description((0, i18n_1.t)('cli.uninstall_description'))
|
|
66
|
+
.action(uninstall_1.uninstallCommand);
|
|
67
|
+
// Version check in help output (async fetch before parse)
|
|
68
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
69
|
+
const checker = new version_checker_1.VersionChecker();
|
|
70
|
+
checker.checkVersion().then((info) => {
|
|
71
|
+
if (info.latest && info.updateAvailable) {
|
|
72
|
+
program.addHelpText('beforeAll', `š¦ ${(0, i18n_1.t)('cli.version_update_available', { current: info.current, latest: info.latest })}\n`);
|
|
73
|
+
}
|
|
74
|
+
else if (info.latest) {
|
|
75
|
+
program.addHelpText('beforeAll', `š¦ ${(0, i18n_1.t)('cli.version_latest', { current: info.current })}\n`);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
program.addHelpText('beforeAll', `š¦ ${(0, i18n_1.t)('cli.version_current', { current: info.current })}\n`);
|
|
79
|
+
}
|
|
80
|
+
program.parse();
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
program.parse();
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.installCommand = installCommand;
|
|
4
|
+
const auto_start_1 = require("../services/auto-start");
|
|
5
|
+
const daemon_1 = require("../services/daemon");
|
|
6
|
+
const i18n_1 = require("../services/i18n");
|
|
7
|
+
function installCommand(_options, _cmdObj, dependencies = {}) {
|
|
8
|
+
const autoStartManager = dependencies.autoStartManager ?? (0, auto_start_1.createAutoStartManager)();
|
|
9
|
+
const daemonService = dependencies.daemonService ?? new daemon_1.DaemonService();
|
|
10
|
+
const exit = dependencies.exit ?? ((code) => process.exit(code));
|
|
11
|
+
if (!autoStartManager.isSupported()) {
|
|
12
|
+
console.error(`ā ${(0, i18n_1.t)('autostart.unsupported', { platform: process.platform })}`);
|
|
13
|
+
return exit(1);
|
|
14
|
+
}
|
|
15
|
+
// Check for running instance (any mode)
|
|
16
|
+
const existingPid = daemonService.checkExistingDaemon();
|
|
17
|
+
if (existingPid !== null) {
|
|
18
|
+
const taskState = autoStartManager.queryState();
|
|
19
|
+
if (taskState === 'installed') {
|
|
20
|
+
console.log(`ā¹ļø ${(0, i18n_1.t)('install.already_installed_running')}`);
|
|
21
|
+
console.log(` ${(0, i18n_1.t)('install.pid', { pid: existingPid })}`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.error(`ā ${(0, i18n_1.t)('install.already_running', { pid: existingPid })}`);
|
|
25
|
+
return exit(1);
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const taskState = autoStartManager.queryState();
|
|
30
|
+
try {
|
|
31
|
+
if (taskState !== 'installed') {
|
|
32
|
+
autoStartManager.install();
|
|
33
|
+
console.log(`ā
${(0, i18n_1.t)('install.installed')}`);
|
|
34
|
+
console.log(` ${(0, i18n_1.t)('install.task_name', { name: autoStartManager.getName() })}`);
|
|
35
|
+
console.log(` ${(0, i18n_1.t)('install.auto_start_hint')}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
console.log(`ā¹ļø ${(0, i18n_1.t)('install.already_installed')}`);
|
|
39
|
+
}
|
|
40
|
+
// Start the task immediately
|
|
41
|
+
console.log(`š ${(0, i18n_1.t)('install.starting')}`);
|
|
42
|
+
autoStartManager.start();
|
|
43
|
+
// Wait a moment for the daemon to write its PID
|
|
44
|
+
setTimeout(() => {
|
|
45
|
+
const pid = daemonService.readPid();
|
|
46
|
+
if (pid !== null) {
|
|
47
|
+
console.log(`š¢ ${(0, i18n_1.t)('install.started', { pid })}`);
|
|
48
|
+
}
|
|
49
|
+
// Show submit hint
|
|
50
|
+
const getShortcutFn = dependencies.getShortcutResult ?? (() => {
|
|
51
|
+
try {
|
|
52
|
+
return require('../cli').getShortcutResult();
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const shortcut = getShortcutFn();
|
|
59
|
+
const cmd = shortcut?.shortcutAvailable ? 'agentfleet' : 'npx -y @daomar/agentfleet';
|
|
60
|
+
console.log(`\nš” ${(0, i18n_1.t)('install.submit_hint', { command: cmd })}\n`);
|
|
61
|
+
}, 3000);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.error(`ā ${(0, i18n_1.t)('install.failed', { message: err.message })}`);
|
|
65
|
+
return exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runCommand = runCommand;
|
|
4
|
+
const setup_1 = require("../services/setup");
|
|
5
|
+
const task_watcher_1 = require("../services/task-watcher");
|
|
6
|
+
const agent_executor_1 = require("../services/agent-executor");
|
|
7
|
+
const result_writer_1 = require("../services/result-writer");
|
|
8
|
+
const daemon_1 = require("../services/daemon");
|
|
9
|
+
const auto_start_1 = require("../services/auto-start");
|
|
10
|
+
const logger_1 = require("../services/logger");
|
|
11
|
+
const bootstrap_1 = require("../services/bootstrap");
|
|
12
|
+
const i18n_1 = require("../services/i18n");
|
|
13
|
+
async function runCommand(options, dependencies = {}) {
|
|
14
|
+
const exit = dependencies.exit ?? ((code) => process.exit(code));
|
|
15
|
+
const daemonService = dependencies.daemonService ?? new daemon_1.DaemonService();
|
|
16
|
+
const autoStartManager = dependencies.autoStartManager ?? (0, auto_start_1.createAutoStartManager)();
|
|
17
|
+
// Skip auto-start check when running as daemon child
|
|
18
|
+
if (!options._daemonChild) {
|
|
19
|
+
const taskState = autoStartManager.queryState();
|
|
20
|
+
if (taskState === 'installed') {
|
|
21
|
+
const existingPid = daemonService.checkExistingDaemon();
|
|
22
|
+
if (existingPid !== null) {
|
|
23
|
+
console.log(`ā¹ļø ${(0, i18n_1.t)('run.scheduled_task_running', { pid: existingPid })}`);
|
|
24
|
+
console.log(` ${(0, i18n_1.t)('run.scheduled_task_hint')}`);
|
|
25
|
+
exit(0);
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
// Auto-start installed but not running ā start through the platform registration
|
|
29
|
+
console.log(`ā¹ļø ${(0, i18n_1.t)('run.scheduled_task_starting')}`);
|
|
30
|
+
autoStartManager.start();
|
|
31
|
+
exit(0);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Single-instance guard: check for an already-running AgentFleet process
|
|
36
|
+
const existingPid = daemonService.checkExistingDaemon();
|
|
37
|
+
if (existingPid !== null) {
|
|
38
|
+
console.error(`ā ${(0, i18n_1.t)('run.already_running', { pid: existingPid })}`);
|
|
39
|
+
exit(1);
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
// Daemon mode: spawn a detached child and exit the parent
|
|
43
|
+
if (options.daemon) {
|
|
44
|
+
const argv = dependencies.processArgv ?? process.argv.slice(1);
|
|
45
|
+
const logFile = options.logFile ?? daemonService.getDefaultLogPath();
|
|
46
|
+
const childPid = daemonService.spawnDetached(argv, logFile);
|
|
47
|
+
console.log(`šøļø ${(0, i18n_1.t)('run.daemon_started', { pid: childPid })}`);
|
|
48
|
+
console.log(` ${(0, i18n_1.t)('run.daemon_log_file', { path: logFile })}`);
|
|
49
|
+
console.log(` ${(0, i18n_1.t)('run.daemon_pid_file', { path: daemonService.getPidPath() })}`);
|
|
50
|
+
exit(0);
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
// Daemon child mode: set up logging
|
|
54
|
+
const isDaemonChild = options._daemonChild ?? false;
|
|
55
|
+
let logger;
|
|
56
|
+
if (isDaemonChild) {
|
|
57
|
+
logger = dependencies.logger ?? new logger_1.Logger();
|
|
58
|
+
if (options.logFile) {
|
|
59
|
+
logger.setup(options.logFile);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Write PID file for all run modes (foreground + daemon child)
|
|
63
|
+
daemonService.writePid(process.pid);
|
|
64
|
+
console.log(`šøļø ${(0, i18n_1.t)('run.starting')}\n`);
|
|
65
|
+
const setup = dependencies.setup ?? new setup_1.SetupService();
|
|
66
|
+
let config;
|
|
67
|
+
try {
|
|
68
|
+
const bootstrapFn = dependencies.bootstrapFn ?? (() => (0, bootstrap_1.bootstrap)({ setup: setup }));
|
|
69
|
+
config = await bootstrapFn();
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
console.error(`\nā ${(0, i18n_1.t)('run.error', { message: err.message })}`);
|
|
73
|
+
daemonService.removePid();
|
|
74
|
+
if (logger)
|
|
75
|
+
logger.restore();
|
|
76
|
+
exit(1);
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
// Apply CLI overrides
|
|
80
|
+
config.pollIntervalSeconds = parseInt(options.pollInterval, 10) || config.pollIntervalSeconds;
|
|
81
|
+
config.maxConcurrency = parseInt(options.concurrency, 10) || config.maxConcurrency;
|
|
82
|
+
// Create services
|
|
83
|
+
const executor = dependencies.createExecutor ? dependencies.createExecutor(config) : new agent_executor_1.AgentExecutor(config);
|
|
84
|
+
const writer = dependencies.createWriter ? dependencies.createWriter(setup.getOutputDir()) : new result_writer_1.ResultWriter(setup.getOutputDir());
|
|
85
|
+
const watcher = dependencies.createWatcher
|
|
86
|
+
? dependencies.createWatcher(setup.getTasksDir(), setup.getProcessedPath(), config.pollIntervalSeconds)
|
|
87
|
+
: new task_watcher_1.TaskWatcher(setup.getTasksDir(), setup.getProcessedPath(), config.pollIntervalSeconds);
|
|
88
|
+
// Wire up task handler
|
|
89
|
+
watcher.onTask(async (task, _filePath) => {
|
|
90
|
+
try {
|
|
91
|
+
const result = await executor.execute(task);
|
|
92
|
+
writer.write(result);
|
|
93
|
+
watcher.markProcessed(task.id);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
console.error(`ā ${(0, i18n_1.t)('run.task_error', { taskId: task.id, message: err.message })}`);
|
|
97
|
+
watcher.markProcessed(task.id);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
// Start watching
|
|
101
|
+
await watcher.start();
|
|
102
|
+
console.log(`\nš¢ ${(0, i18n_1.t)('run.running_on', { hostname: config.hostname })}`);
|
|
103
|
+
console.log(` ${(0, i18n_1.t)('run.concurrency', { value: config.maxConcurrency })}`);
|
|
104
|
+
console.log(` ${(0, i18n_1.t)('run.poll_interval', { value: config.pollIntervalSeconds })}`);
|
|
105
|
+
if (!isDaemonChild) {
|
|
106
|
+
console.log(` ${(0, i18n_1.t)('run.press_ctrl_c')}\n`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
console.log(` ${(0, i18n_1.t)('run.running_as_daemon', { pid: process.pid })}\n`);
|
|
110
|
+
}
|
|
111
|
+
// Show submit hint
|
|
112
|
+
const getShortcutFn = dependencies.getShortcutResult ?? (() => {
|
|
113
|
+
try {
|
|
114
|
+
return require('../cli').getShortcutResult();
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
const shortcut = getShortcutFn();
|
|
121
|
+
const cmd = shortcut?.shortcutAvailable ? 'agentfleet' : 'npx -y @daomar/agentfleet';
|
|
122
|
+
console.log(`š” ${(0, i18n_1.t)('run.submit_hint', { command: cmd })}\n`);
|
|
123
|
+
// Handle graceful shutdown
|
|
124
|
+
const shutdown = async () => {
|
|
125
|
+
console.log(`\n${(0, i18n_1.t)('run.shutting_down')}`);
|
|
126
|
+
await watcher.stop();
|
|
127
|
+
daemonService.removePid();
|
|
128
|
+
if (logger)
|
|
129
|
+
logger.restore();
|
|
130
|
+
exit(0);
|
|
131
|
+
};
|
|
132
|
+
const registerSignal = dependencies.registerSignal ?? ((signal, handler) => process.on(signal, handler));
|
|
133
|
+
registerSignal('SIGINT', shutdown);
|
|
134
|
+
registerSignal('SIGTERM', shutdown);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1,215 @@
|
|
|
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.statusCommand = statusCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const setup_1 = require("../services/setup");
|
|
40
|
+
const daemon_1 = require("../services/daemon");
|
|
41
|
+
const auto_start_1 = require("../services/auto-start");
|
|
42
|
+
const version_checker_1 = require("../services/version-checker");
|
|
43
|
+
const bootstrap_1 = require("../services/bootstrap");
|
|
44
|
+
const i18n_1 = require("../services/i18n");
|
|
45
|
+
async function statusCommand(taskId, _cmdObj, dependencies = {}) {
|
|
46
|
+
const setup = dependencies.setup ?? new setup_1.SetupService();
|
|
47
|
+
const daemonService = dependencies.daemonService ?? new daemon_1.DaemonService();
|
|
48
|
+
const autoStartManager = dependencies.autoStartManager ?? (0, auto_start_1.createAutoStartManager)();
|
|
49
|
+
const versionChecker = dependencies.versionChecker ?? new version_checker_1.VersionChecker();
|
|
50
|
+
await (dependencies.bootstrapFn ?? bootstrap_1.bootstrap)({ setup });
|
|
51
|
+
const tasksDir = setup.getTasksDir();
|
|
52
|
+
const outputDir = setup.getOutputDir();
|
|
53
|
+
// Show version info
|
|
54
|
+
await showVersionInfo(versionChecker);
|
|
55
|
+
// Show running process info
|
|
56
|
+
showProcessInfo(daemonService, autoStartManager);
|
|
57
|
+
if (taskId) {
|
|
58
|
+
showTaskDetail(taskId, tasksDir, outputDir);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
showAllTasks(tasksDir, outputDir);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function showProcessInfo(daemonService, autoStartManager) {
|
|
65
|
+
const taskState = autoStartManager.queryState();
|
|
66
|
+
const pid = daemonService.readPid();
|
|
67
|
+
const autoStart = taskState === 'installed';
|
|
68
|
+
if (pid !== null && daemonService.isRunning(pid)) {
|
|
69
|
+
console.log(`š¢ ${(0, i18n_1.t)('status.running', { pid })}`);
|
|
70
|
+
if (autoStart) {
|
|
71
|
+
console.log(` ${(0, i18n_1.t)('status.mode_auto_start')}`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const logPath = daemonService.getDefaultLogPath();
|
|
75
|
+
const hasLogFile = fs.existsSync(logPath);
|
|
76
|
+
console.log(` ${hasLogFile ? (0, i18n_1.t)('status.mode_daemon') : (0, i18n_1.t)('status.mode_foreground')}`);
|
|
77
|
+
if (hasLogFile) {
|
|
78
|
+
console.log(` ${(0, i18n_1.t)('status.log_file', { path: logPath })}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
console.log(` ${(0, i18n_1.t)('status.pid_file', { path: daemonService.getPidPath() })}`);
|
|
82
|
+
console.log();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (autoStart) {
|
|
86
|
+
console.log(`āŖ ${(0, i18n_1.t)('status.auto_start_not_running')}`);
|
|
87
|
+
console.log(` ${(0, i18n_1.t)('status.auto_start_hint')}\n`);
|
|
88
|
+
if (pid !== null)
|
|
89
|
+
daemonService.removePid();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
console.log(`āŖ ${(0, i18n_1.t)('status.not_running')}\n`);
|
|
93
|
+
if (pid !== null)
|
|
94
|
+
daemonService.removePid();
|
|
95
|
+
}
|
|
96
|
+
async function showVersionInfo(versionChecker) {
|
|
97
|
+
const info = await versionChecker.checkVersion();
|
|
98
|
+
if (info.latest && info.updateAvailable) {
|
|
99
|
+
console.log(`š¦ ${(0, i18n_1.t)('status.version_update', { current: info.current, latest: info.latest })}`);
|
|
100
|
+
}
|
|
101
|
+
else if (info.latest) {
|
|
102
|
+
console.log(`š¦ ${(0, i18n_1.t)('status.version_latest', { current: info.current })}`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.log(`š¦ ${(0, i18n_1.t)('status.version_current', { current: info.current })}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function showAllTasks(tasksDir, outputDir) {
|
|
109
|
+
const taskFiles = fs.readdirSync(tasksDir).filter(f => f.endsWith('.json'));
|
|
110
|
+
if (taskFiles.length === 0) {
|
|
111
|
+
console.log((0, i18n_1.t)('status.no_tasks'));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
console.log(`\nš ${(0, i18n_1.t)('status.tasks_header', { count: taskFiles.length })}\n`);
|
|
115
|
+
console.log(padRight((0, i18n_1.t)('status.col_id'), 36) + padRight((0, i18n_1.t)('status.col_title'), 30) + padRight((0, i18n_1.t)('status.col_status'), 12) + (0, i18n_1.t)('status.col_results'));
|
|
116
|
+
console.log('ā'.repeat(90));
|
|
117
|
+
for (const file of taskFiles) {
|
|
118
|
+
try {
|
|
119
|
+
const content = fs.readFileSync(path.join(tasksDir, file), 'utf-8');
|
|
120
|
+
const task = JSON.parse(content);
|
|
121
|
+
// Check for results
|
|
122
|
+
const taskOutputDir = path.join(outputDir, task.id);
|
|
123
|
+
let resultCount = 0;
|
|
124
|
+
let machines = [];
|
|
125
|
+
if (fs.existsSync(taskOutputDir)) {
|
|
126
|
+
const resultFiles = fs.readdirSync(taskOutputDir).filter(f => f.endsWith('-result.json'));
|
|
127
|
+
resultCount = resultFiles.length;
|
|
128
|
+
machines = resultFiles.map(f => f.replace('-result.json', ''));
|
|
129
|
+
}
|
|
130
|
+
const status = resultCount > 0 ? (0, i18n_1.t)('status.status_done', { count: resultCount }) : (0, i18n_1.t)('status.status_pending');
|
|
131
|
+
const machineStr = machines.length > 0 ? machines.join(', ') : '-';
|
|
132
|
+
console.log(padRight(task.id, 36) +
|
|
133
|
+
padRight(task.title || (0, i18n_1.t)('status.untitled'), 30) +
|
|
134
|
+
padRight(status, 12) +
|
|
135
|
+
machineStr);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
console.log(padRight(file, 36) + (0, i18n_1.t)('status.error_reading'));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
console.log();
|
|
142
|
+
}
|
|
143
|
+
function showTaskDetail(taskId, tasksDir, outputDir) {
|
|
144
|
+
// Find task file
|
|
145
|
+
const taskFiles = fs.readdirSync(tasksDir).filter(f => f.endsWith('.json'));
|
|
146
|
+
let task = null;
|
|
147
|
+
for (const file of taskFiles) {
|
|
148
|
+
try {
|
|
149
|
+
const content = fs.readFileSync(path.join(tasksDir, file), 'utf-8');
|
|
150
|
+
const parsed = JSON.parse(content);
|
|
151
|
+
if (parsed.id === taskId) {
|
|
152
|
+
task = parsed;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch { /* skip */ }
|
|
157
|
+
}
|
|
158
|
+
if (!task) {
|
|
159
|
+
console.error(`ā ${(0, i18n_1.t)('status.task_not_found', { taskId })}`);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
console.log(`\nš ${(0, i18n_1.t)('status.task_header', { taskId: task.id })}`);
|
|
163
|
+
console.log(` ${(0, i18n_1.t)('status.task_title', { title: task.title || (0, i18n_1.t)('status.task_title_none') })}`);
|
|
164
|
+
console.log(` ${(0, i18n_1.t)('status.task_prompt', { prompt: task.prompt })}`);
|
|
165
|
+
console.log(` ${(0, i18n_1.t)('status.task_working_dir', { path: task.workingDirectory || (0, i18n_1.t)('status.task_default') })}`);
|
|
166
|
+
console.log(` ${(0, i18n_1.t)('status.task_agent', { agent: task.command || (0, i18n_1.t)('status.task_default') })}`);
|
|
167
|
+
console.log(` ${(0, i18n_1.t)('status.task_created', { date: task.createdAt ? (0, i18n_1.formatDate)(task.createdAt) : (0, i18n_1.t)('status.task_unknown') })}`);
|
|
168
|
+
console.log(` ${(0, i18n_1.t)('status.task_created_by', { hostname: task.createdBy || (0, i18n_1.t)('status.task_unknown') })}`);
|
|
169
|
+
// Show results
|
|
170
|
+
const taskOutputDir = path.join(outputDir, task.id);
|
|
171
|
+
if (fs.existsSync(taskOutputDir)) {
|
|
172
|
+
const resultFiles = fs.readdirSync(taskOutputDir).filter(f => f.endsWith('-result.json'));
|
|
173
|
+
if (resultFiles.length > 0) {
|
|
174
|
+
console.log(`\nš ${(0, i18n_1.t)('status.results_header', { count: resultFiles.length })}\n`);
|
|
175
|
+
for (const resultFile of resultFiles) {
|
|
176
|
+
try {
|
|
177
|
+
const content = fs.readFileSync(path.join(taskOutputDir, resultFile), 'utf-8');
|
|
178
|
+
const result = JSON.parse(content);
|
|
179
|
+
const icon = result.status === 'completed' ? 'ā
' : result.status === 'timeout' ? 'ā°' : 'ā';
|
|
180
|
+
console.log(` ${icon} ${result.hostname}`);
|
|
181
|
+
console.log(` ${(0, i18n_1.t)('status.result_status', { status: result.status, exitCode: result.exitCode })}`);
|
|
182
|
+
console.log(` ${(0, i18n_1.t)('status.result_started', { date: (0, i18n_1.formatDate)(result.startedAt) })}`);
|
|
183
|
+
console.log(` ${(0, i18n_1.t)('status.result_completed', { date: (0, i18n_1.formatDate)(result.completedAt) })}`);
|
|
184
|
+
if (result.error)
|
|
185
|
+
console.log(` ${(0, i18n_1.t)('status.result_error', { error: result.error })}`);
|
|
186
|
+
}
|
|
187
|
+
catch { /* skip */ }
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// List all output files
|
|
191
|
+
const allFiles = fs.readdirSync(taskOutputDir);
|
|
192
|
+
if (allFiles.length > 0) {
|
|
193
|
+
console.log(`\nš ${(0, i18n_1.t)('status.output_files')}`);
|
|
194
|
+
for (const f of allFiles) {
|
|
195
|
+
const stats = fs.statSync(path.join(taskOutputDir, f));
|
|
196
|
+
console.log(` ${f} (${formatBytes(stats.size)})`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
console.log(`\n ${(0, i18n_1.t)('status.no_results')}`);
|
|
202
|
+
}
|
|
203
|
+
console.log();
|
|
204
|
+
}
|
|
205
|
+
function padRight(str, len) {
|
|
206
|
+
return str.length >= len ? str.substring(0, len - 1) + ' ' : str + ' '.repeat(len - str.length);
|
|
207
|
+
}
|
|
208
|
+
function formatBytes(bytes) {
|
|
209
|
+
if (bytes < 1024)
|
|
210
|
+
return `${bytes}B`;
|
|
211
|
+
if (bytes < 1024 * 1024)
|
|
212
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
213
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stopCommand = stopCommand;
|
|
4
|
+
const daemon_1 = require("../services/daemon");
|
|
5
|
+
const i18n_1 = require("../services/i18n");
|
|
6
|
+
function stopCommand(dependencies = {}) {
|
|
7
|
+
const daemonService = dependencies.daemonService ?? new daemon_1.DaemonService();
|
|
8
|
+
const exit = dependencies.exit ?? ((code) => process.exit(code));
|
|
9
|
+
const killProcess = dependencies.killProcess ?? ((pid) => process.kill(pid, 'SIGTERM'));
|
|
10
|
+
const pid = daemonService.readPid();
|
|
11
|
+
if (pid === null) {
|
|
12
|
+
console.log(`ā¹ļø ${(0, i18n_1.t)('stop.not_running_no_pid')}`);
|
|
13
|
+
exit(0);
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
if (!daemonService.isRunning(pid)) {
|
|
17
|
+
console.log(`ā¹ļø ${(0, i18n_1.t)('stop.not_running_stale')}`);
|
|
18
|
+
daemonService.removePid();
|
|
19
|
+
exit(0);
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
killProcess(pid);
|
|
24
|
+
console.log(`ā
${(0, i18n_1.t)('stop.stopped', { pid })}`);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
console.error(`ā ${(0, i18n_1.t)('stop.failed', { pid, message: err.message })}`);
|
|
28
|
+
exit(1);
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
// Give the process a moment to clean up its own PID file
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
daemonService.removePid();
|
|
34
|
+
exit(0);
|
|
35
|
+
}, 500);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=stop.js.map
|