agent-window 1.4.0 → 1.4.1
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 +1 -1
- package/src/bot.js +92 -38
- package/src/core/config.js +1 -0
package/package.json
CHANGED
package/src/bot.js
CHANGED
|
@@ -49,6 +49,7 @@ const ALLOWED_CHANNELS = config.discord.allowedChannels;
|
|
|
49
49
|
const CHANNEL_SESSIONS_FILE = config.paths.sessions;
|
|
50
50
|
const PENDING_DIR = config.paths.pending;
|
|
51
51
|
const HOOK_DIR = config.paths.hooks;
|
|
52
|
+
const USE_DOCKER = config.workspace.useDocker; // Whether to use Docker or run locally
|
|
52
53
|
const CONTAINER_NAME = config.workspace.containerName;
|
|
53
54
|
const DOCKER_IMAGE = config.workspace.dockerImage;
|
|
54
55
|
|
|
@@ -118,20 +119,37 @@ function updateHealthStatus(component, status) {
|
|
|
118
119
|
|
|
119
120
|
// Get overall health status
|
|
120
121
|
function getOverallHealth() {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
122
|
+
// Build health check string
|
|
123
|
+
const checks = [healthStatus.pm2 ? '✓' : '✗', healthStatus.discord ? '✓' : '✗'];
|
|
124
|
+
|
|
125
|
+
// Only check Docker if enabled
|
|
126
|
+
if (USE_DOCKER) {
|
|
127
|
+
checks.push(healthStatus.docker ? '✓' : '✗');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const healthString = checks.join(' ');
|
|
131
|
+
|
|
132
|
+
// Determine overall status
|
|
133
|
+
if (USE_DOCKER) {
|
|
134
|
+
// Docker mode: all components must be healthy
|
|
135
|
+
if (healthStatus.pm2 && healthStatus.discord && healthStatus.docker) {
|
|
136
|
+
return 'healthy';
|
|
137
|
+
} else if (healthStatus.pm2 && healthStatus.discord) {
|
|
138
|
+
return 'degraded'; // Running but Docker failed
|
|
139
|
+
} else if (healthStatus.pm2) {
|
|
140
|
+
return 'unhealthy'; // PM2 running but Discord disconnected
|
|
141
|
+
} else {
|
|
142
|
+
return 'failed';
|
|
143
|
+
}
|
|
133
144
|
} else {
|
|
134
|
-
|
|
145
|
+
// Non-Docker mode: only PM2 and Discord required
|
|
146
|
+
if (healthStatus.pm2 && healthStatus.discord) {
|
|
147
|
+
return 'healthy';
|
|
148
|
+
} else if (healthStatus.pm2) {
|
|
149
|
+
return 'unhealthy'; // PM2 running but Discord disconnected
|
|
150
|
+
} else {
|
|
151
|
+
return 'failed';
|
|
152
|
+
}
|
|
135
153
|
}
|
|
136
154
|
}
|
|
137
155
|
|
|
@@ -346,6 +364,13 @@ function isContainerRunning() {
|
|
|
346
364
|
|
|
347
365
|
// Start or ensure persistent container is running
|
|
348
366
|
function ensureContainer() {
|
|
367
|
+
// Skip Docker operations if not using Docker
|
|
368
|
+
if (!USE_DOCKER) {
|
|
369
|
+
console.log('[Docker] Docker is disabled (useDocker: false). Running in local mode.');
|
|
370
|
+
updateHealthStatus('docker', true); // Mark as "healthy" since we don't need Docker
|
|
371
|
+
return true;
|
|
372
|
+
}
|
|
373
|
+
|
|
349
374
|
// Log the paths being used
|
|
350
375
|
console.log('[Docker] PENDING_DIR (host):', PENDING_DIR);
|
|
351
376
|
console.log('[Docker] HOOK_DIR (host):', HOOK_DIR);
|
|
@@ -437,6 +462,11 @@ function ensureContainer() {
|
|
|
437
462
|
|
|
438
463
|
// Stop persistent container (call on bot shutdown)
|
|
439
464
|
function stopContainer() {
|
|
465
|
+
if (!USE_DOCKER) {
|
|
466
|
+
console.log('[Docker] Docker is disabled. No container to stop.');
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
|
|
440
470
|
try {
|
|
441
471
|
execSync(`docker stop ${CONTAINER_NAME} 2>/dev/null`);
|
|
442
472
|
execSync(`docker rm ${CONTAINER_NAME} 2>/dev/null`);
|
|
@@ -1445,21 +1475,42 @@ const commands = {
|
|
|
1445
1475
|
let lastStatusUpdate = 0;
|
|
1446
1476
|
const task = activeTasks.get(channelId);
|
|
1447
1477
|
|
|
1448
|
-
//
|
|
1449
|
-
|
|
1450
|
-
'exec', '-i',
|
|
1451
|
-
CONTAINER_NAME,
|
|
1452
|
-
CLI_COMMAND,
|
|
1453
|
-
...cliArgs
|
|
1454
|
-
];
|
|
1478
|
+
// Execute CLI command (either in Docker or locally based on configuration)
|
|
1479
|
+
let child;
|
|
1455
1480
|
|
|
1456
|
-
|
|
1481
|
+
if (USE_DOCKER) {
|
|
1482
|
+
// Use docker exec to run CLI in the persistent container
|
|
1483
|
+
const dockerArgs = [
|
|
1484
|
+
'exec', '-i',
|
|
1485
|
+
CONTAINER_NAME,
|
|
1486
|
+
CLI_COMMAND,
|
|
1487
|
+
...cliArgs
|
|
1488
|
+
];
|
|
1457
1489
|
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1490
|
+
console.log('[Docker] Executing in container:', CONTAINER_NAME);
|
|
1491
|
+
|
|
1492
|
+
child = spawn('docker', dockerArgs, {
|
|
1493
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1494
|
+
});
|
|
1461
1495
|
|
|
1462
|
-
|
|
1496
|
+
child.stdin.end();
|
|
1497
|
+
} else {
|
|
1498
|
+
// Run CLI directly on local host
|
|
1499
|
+
console.log('[Local] Executing locally:', CLI_COMMAND, ...cliArgs);
|
|
1500
|
+
|
|
1501
|
+
child = spawn(CLI_COMMAND, cliArgs, {
|
|
1502
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1503
|
+
cwd: PROJECT_DIR,
|
|
1504
|
+
env: {
|
|
1505
|
+
...process.env,
|
|
1506
|
+
CLAUDE_CODE_OAUTH_TOKEN: OAUTH_TOKEN || '',
|
|
1507
|
+
HOME: process.env.HOME,
|
|
1508
|
+
PATH: process.env.PATH
|
|
1509
|
+
}
|
|
1510
|
+
});
|
|
1511
|
+
|
|
1512
|
+
child.stdin.end();
|
|
1513
|
+
}
|
|
1463
1514
|
|
|
1464
1515
|
// Update status periodically (with stop button)
|
|
1465
1516
|
// forceUpdate=true bypasses throttle for important state changes
|
|
@@ -1762,18 +1813,9 @@ client.on(Events.MessageCreate, async (message) => {
|
|
|
1762
1813
|
return;
|
|
1763
1814
|
}
|
|
1764
1815
|
|
|
1765
|
-
|
|
1766
|
-
// - If ALLOWED_CHANNELS is set, only allow those channels
|
|
1767
|
-
// - If ALLOWED_CHANNELS is missing (should not happen due to config validation), reject ALL non-DM messages
|
|
1768
|
-
if (!isDM) {
|
|
1769
|
-
if (!ALLOWED_CHANNELS || ALLOWED_CHANNELS.length === 0) {
|
|
1770
|
-
// Defensive: If no channels are configured, reject all non-DM messages
|
|
1771
|
-
console.error('[MSG] SECURITY: No ALLOWED_CHANNELS configured. Rejecting message for safety.');
|
|
1772
|
-
console.error('[MSG] Please configure ALLOWED_CHANNELS in your config.json');
|
|
1773
|
-
return;
|
|
1774
|
-
}
|
|
1816
|
+
if (ALLOWED_CHANNELS && !isDM) {
|
|
1775
1817
|
if (!ALLOWED_CHANNELS.includes(message.channel.id)) {
|
|
1776
|
-
console.log(
|
|
1818
|
+
console.log('[MSG] Ignored: channel not allowed');
|
|
1777
1819
|
return;
|
|
1778
1820
|
}
|
|
1779
1821
|
}
|
|
@@ -1853,9 +1895,14 @@ client.on(Events.ClientReady, async () => {
|
|
|
1853
1895
|
// Send startup notification to Discord channels
|
|
1854
1896
|
try {
|
|
1855
1897
|
const uptime = Math.floor((Date.now() - healthStatus.startTime) / 1000);
|
|
1856
|
-
const dockerStatus = healthStatus.docker ? '✓ Connected' : '✗ Not Available';
|
|
1857
1898
|
const overallStatus = overallHealth.toUpperCase();
|
|
1858
1899
|
|
|
1900
|
+
// Build execution mode info
|
|
1901
|
+
const execMode = USE_DOCKER ? 'Docker Container' : 'Local Host';
|
|
1902
|
+
const dockerStatus = USE_DOCKER
|
|
1903
|
+
? (healthStatus.docker ? '✓ Connected' : '✗ Not Available')
|
|
1904
|
+
: '⊘ Disabled (Local Mode)';
|
|
1905
|
+
|
|
1859
1906
|
// Build startup message
|
|
1860
1907
|
const startupMessage = {
|
|
1861
1908
|
embeds: [{
|
|
@@ -1867,6 +1914,11 @@ client.on(Events.ClientReady, async () => {
|
|
|
1867
1914
|
value: overallStatus,
|
|
1868
1915
|
inline: true
|
|
1869
1916
|
},
|
|
1917
|
+
{
|
|
1918
|
+
name: 'Execution Mode',
|
|
1919
|
+
value: execMode,
|
|
1920
|
+
inline: true
|
|
1921
|
+
},
|
|
1870
1922
|
{
|
|
1871
1923
|
name: 'Docker',
|
|
1872
1924
|
value: dockerStatus,
|
|
@@ -1879,7 +1931,9 @@ client.on(Events.ClientReady, async () => {
|
|
|
1879
1931
|
},
|
|
1880
1932
|
{
|
|
1881
1933
|
name: 'Components',
|
|
1882
|
-
value:
|
|
1934
|
+
value: USE_DOCKER
|
|
1935
|
+
? `PM2: ✓\nDiscord: ✓\nDocker: ${healthStatus.docker ? '✓' : '✗'}`
|
|
1936
|
+
: `PM2: ✓\nDiscord: ✓\nDocker: ⊘ (Local Mode)`,
|
|
1883
1937
|
inline: false
|
|
1884
1938
|
}
|
|
1885
1939
|
],
|
package/src/core/config.js
CHANGED
|
@@ -81,6 +81,7 @@ function loadConfig() {
|
|
|
81
81
|
// === Workspace Configuration ===
|
|
82
82
|
workspace: {
|
|
83
83
|
projectDir: expandPath(fileConfig.PROJECT_DIR) || process.cwd(),
|
|
84
|
+
useDocker: fileConfig.workspace?.useDocker !== false, // Default to true for backward compatibility
|
|
84
85
|
containerName: fileConfig.workspace?.containerName || 'claude-discord-bot',
|
|
85
86
|
dockerImage: fileConfig.workspace?.dockerImage || 'claude-sandbox',
|
|
86
87
|
portMappings: fileConfig.workspace?.portMappings || [],
|