tide-commander 0.52.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 +364 -0
- package/dist/assets/characters/Textures/colormap.png +0 -0
- package/dist/assets/characters/character-female-a.glb +0 -0
- package/dist/assets/characters/character-female-b.glb +0 -0
- package/dist/assets/characters/character-female-c.glb +0 -0
- package/dist/assets/characters/character-female-d.glb +0 -0
- package/dist/assets/characters/character-female-e.glb +0 -0
- package/dist/assets/characters/character-female-f.glb +0 -0
- package/dist/assets/characters/character-male-a-processed.gltf +11862 -0
- package/dist/assets/characters/character-male-a.glb +0 -0
- package/dist/assets/characters/character-male-b.glb +0 -0
- package/dist/assets/characters/character-male-c.glb +0 -0
- package/dist/assets/characters/character-male-d.glb +0 -0
- package/dist/assets/characters/character-male-e.glb +0 -0
- package/dist/assets/characters/character-male-f.glb +0 -0
- package/dist/assets/icons/icon-192.png +0 -0
- package/dist/assets/icons/icon-512.png +0 -0
- package/dist/assets/landing-Cc0MDBAK.css +1 -0
- package/dist/assets/main-BIpLsrUu.css +1 -0
- package/dist/assets/main-DMTRw3br.js +276 -0
- package/dist/assets/textures/concrete_floor_worn_001_diff_1k.jpg +0 -0
- package/dist/assets/textures/logo-blanco.png +0 -0
- package/dist/assets/vendor-react-uS-d4TUT.js +17 -0
- package/dist/assets/vendor-three-4iQNXcoo.js +3828 -0
- package/dist/assets/web-BZdi2lG9.js +1 -0
- package/dist/assets/web-yHsOO1Qb.js +1 -0
- package/dist/index.html +38 -0
- package/dist/manifest.json +39 -0
- package/dist/src/packages/landing/index.html +463 -0
- package/dist/src/packages/server/app.js +87 -0
- package/dist/src/packages/server/auth/index.js +121 -0
- package/dist/src/packages/server/claude/backend.js +578 -0
- package/dist/src/packages/server/claude/index.js +8 -0
- package/dist/src/packages/server/claude/runner/internal-events.js +22 -0
- package/dist/src/packages/server/claude/runner/process-lifecycle.js +208 -0
- package/dist/src/packages/server/claude/runner/recovery-store.js +72 -0
- package/dist/src/packages/server/claude/runner/resource-monitor.js +51 -0
- package/dist/src/packages/server/claude/runner/restart-policy.js +69 -0
- package/dist/src/packages/server/claude/runner/stdout-pipeline.js +153 -0
- package/dist/src/packages/server/claude/runner/watchdog.js +114 -0
- package/dist/src/packages/server/claude/runner.js +310 -0
- package/dist/src/packages/server/claude/session-loader.js +898 -0
- package/dist/src/packages/server/claude/types.js +5 -0
- package/dist/src/packages/server/cli.js +113 -0
- package/dist/src/packages/server/codex/backend.js +119 -0
- package/dist/src/packages/server/codex/index.js +2 -0
- package/dist/src/packages/server/codex/json-event-parser.js +612 -0
- package/dist/src/packages/server/data/builtin-skills/bitbucket-pr.js +298 -0
- package/dist/src/packages/server/data/builtin-skills/full-notifications.js +49 -0
- package/dist/src/packages/server/data/builtin-skills/git-captain.js +304 -0
- package/dist/src/packages/server/data/builtin-skills/index.js +61 -0
- package/dist/src/packages/server/data/builtin-skills/pm2-logs.js +354 -0
- package/dist/src/packages/server/data/builtin-skills/send-message-to-agent.js +51 -0
- package/dist/src/packages/server/data/builtin-skills/server-logs.js +124 -0
- package/dist/src/packages/server/data/builtin-skills/streaming-exec.js +94 -0
- package/dist/src/packages/server/data/builtin-skills/types.js +4 -0
- package/dist/src/packages/server/data/builtin-skills.js +6 -0
- package/dist/src/packages/server/data/index.js +890 -0
- package/dist/src/packages/server/data/snapshots.js +371 -0
- package/dist/src/packages/server/index.js +96 -0
- package/dist/src/packages/server/prompts/tide-commander.js +13 -0
- package/dist/src/packages/server/routes/agents.js +406 -0
- package/dist/src/packages/server/routes/config.js +347 -0
- package/dist/src/packages/server/routes/custom-models.js +170 -0
- package/dist/src/packages/server/routes/exec.js +269 -0
- package/dist/src/packages/server/routes/files.js +995 -0
- package/dist/src/packages/server/routes/index.js +38 -0
- package/dist/src/packages/server/routes/notifications.js +81 -0
- package/dist/src/packages/server/routes/permissions.js +115 -0
- package/dist/src/packages/server/routes/snapshots.js +224 -0
- package/dist/src/packages/server/routes/stt.js +99 -0
- package/dist/src/packages/server/routes/tts.js +166 -0
- package/dist/src/packages/server/routes/voice-assistant.js +310 -0
- package/dist/src/packages/server/runtime/claude-runtime-provider.js +10 -0
- package/dist/src/packages/server/runtime/codex-runtime-provider.js +11 -0
- package/dist/src/packages/server/runtime/index.js +2 -0
- package/dist/src/packages/server/runtime/types.js +6 -0
- package/dist/src/packages/server/services/agent-lifecycle-service.js +82 -0
- package/dist/src/packages/server/services/agent-service.js +410 -0
- package/dist/src/packages/server/services/boss-message-service.js +430 -0
- package/dist/src/packages/server/services/boss-service.js +553 -0
- package/dist/src/packages/server/services/building-service.js +867 -0
- package/dist/src/packages/server/services/claude-service.js +5 -0
- package/dist/src/packages/server/services/custom-class-service.js +323 -0
- package/dist/src/packages/server/services/database-service.js +914 -0
- package/dist/src/packages/server/services/docker-service.js +865 -0
- package/dist/src/packages/server/services/fileTracker.js +242 -0
- package/dist/src/packages/server/services/index.js +21 -0
- package/dist/src/packages/server/services/permission-service.js +258 -0
- package/dist/src/packages/server/services/pm2-service.js +435 -0
- package/dist/src/packages/server/services/runtime-command-execution.js +168 -0
- package/dist/src/packages/server/services/runtime-events.js +357 -0
- package/dist/src/packages/server/services/runtime-service.js +308 -0
- package/dist/src/packages/server/services/runtime-status-sync.js +104 -0
- package/dist/src/packages/server/services/runtime-subagents.js +50 -0
- package/dist/src/packages/server/services/runtime-watchdog.js +74 -0
- package/dist/src/packages/server/services/secrets-service.js +206 -0
- package/dist/src/packages/server/services/skill-service.js +508 -0
- package/dist/src/packages/server/services/subordinate-context-service.js +223 -0
- package/dist/src/packages/server/services/supervisor-claude.js +132 -0
- package/dist/src/packages/server/services/supervisor-prompts.js +80 -0
- package/dist/src/packages/server/services/supervisor-service.js +659 -0
- package/dist/src/packages/server/services/work-plan-service.js +476 -0
- package/dist/src/packages/server/setup.js +86 -0
- package/dist/src/packages/server/utils/index.js +4 -0
- package/dist/src/packages/server/utils/logger.js +302 -0
- package/dist/src/packages/server/utils/string.js +39 -0
- package/dist/src/packages/server/utils/tool-formatting.js +139 -0
- package/dist/src/packages/server/utils/unicode.js +46 -0
- package/dist/src/packages/server/websocket/handler.js +290 -0
- package/dist/src/packages/server/websocket/handlers/agent-handler.js +515 -0
- package/dist/src/packages/server/websocket/handlers/boss-handler.js +116 -0
- package/dist/src/packages/server/websocket/handlers/boss-response-handler.js +250 -0
- package/dist/src/packages/server/websocket/handlers/building-handler.js +298 -0
- package/dist/src/packages/server/websocket/handlers/command-handler.js +217 -0
- package/dist/src/packages/server/websocket/handlers/custom-class-handler.js +68 -0
- package/dist/src/packages/server/websocket/handlers/database-handler.js +223 -0
- package/dist/src/packages/server/websocket/handlers/notification-handler.js +25 -0
- package/dist/src/packages/server/websocket/handlers/permission-handler.js +21 -0
- package/dist/src/packages/server/websocket/handlers/secrets-handler.js +61 -0
- package/dist/src/packages/server/websocket/handlers/skill-handler.js +148 -0
- package/dist/src/packages/server/websocket/handlers/supervisor-handler.js +44 -0
- package/dist/src/packages/server/websocket/handlers/sync-handler.js +19 -0
- package/dist/src/packages/server/websocket/handlers/types.js +4 -0
- package/dist/src/packages/server/websocket/listeners/boss-listeners.js +21 -0
- package/dist/src/packages/server/websocket/listeners/index.js +32 -0
- package/dist/src/packages/server/websocket/listeners/permission-listeners.js +19 -0
- package/dist/src/packages/server/websocket/listeners/runtime-listeners.js +196 -0
- package/dist/src/packages/server/websocket/listeners/skill-listeners.js +51 -0
- package/dist/src/packages/server/websocket/listeners/supervisor-listeners.js +37 -0
- package/dist/src/packages/shared/agent-types.js +54 -0
- package/dist/src/packages/shared/building-types.js +43 -0
- package/dist/src/packages/shared/common-types.js +1 -0
- package/dist/src/packages/shared/database-types.js +8 -0
- package/dist/src/packages/shared/types/snapshot.js +7 -0
- package/dist/src/packages/shared/types.js +12 -0
- package/dist/src/packages/shared/websocket-messages.js +1 -0
- package/dist/sw.js +37 -0
- package/package.json +90 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exec Routes
|
|
3
|
+
* REST API endpoints for executing commands with streaming output
|
|
4
|
+
*
|
|
5
|
+
* Agents can execute long-running commands via HTTP POST requests.
|
|
6
|
+
* Output is streamed to clients via WebSocket in real-time.
|
|
7
|
+
*/
|
|
8
|
+
import { Router } from 'express';
|
|
9
|
+
import { spawn } from 'child_process';
|
|
10
|
+
import { agentService, secretsService } from '../services/index.js';
|
|
11
|
+
import { createLogger, generateId } from '../utils/index.js';
|
|
12
|
+
const log = createLogger('Exec');
|
|
13
|
+
const router = Router();
|
|
14
|
+
// Store for broadcasting via WebSocket
|
|
15
|
+
let broadcastFn = null;
|
|
16
|
+
const runningTasks = new Map();
|
|
17
|
+
/**
|
|
18
|
+
* Set the broadcast function for sending output to all clients
|
|
19
|
+
*/
|
|
20
|
+
export function setBroadcast(fn) {
|
|
21
|
+
broadcastFn = fn;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get all running tasks for an agent
|
|
25
|
+
*/
|
|
26
|
+
export function getRunningTasks(agentId) {
|
|
27
|
+
return Array.from(runningTasks.values()).filter(t => t.agentId === agentId);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Kill a running task by ID
|
|
31
|
+
*/
|
|
32
|
+
export function killTask(taskId) {
|
|
33
|
+
const task = runningTasks.get(taskId);
|
|
34
|
+
if (task) {
|
|
35
|
+
try {
|
|
36
|
+
task.process.kill('SIGTERM');
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
log.error(`Failed to kill task ${taskId}:`, err);
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* POST /api/exec - Execute a command with streaming output
|
|
48
|
+
*
|
|
49
|
+
* Body:
|
|
50
|
+
* - agentId: string (required) - The ID of the agent executing the command
|
|
51
|
+
* - command: string (required) - The command to execute
|
|
52
|
+
* - cwd: string (optional) - Working directory (defaults to agent's cwd)
|
|
53
|
+
*
|
|
54
|
+
* This endpoint executes the command and streams output via WebSocket.
|
|
55
|
+
* Returns the final output and exit code when the command completes.
|
|
56
|
+
*/
|
|
57
|
+
router.post('/', async (req, res) => {
|
|
58
|
+
try {
|
|
59
|
+
const { agentId, command, cwd } = req.body;
|
|
60
|
+
// Validate required fields
|
|
61
|
+
if (!agentId || !command) {
|
|
62
|
+
log.error(`[Exec] Missing required fields. Body: ${JSON.stringify(req.body)}`);
|
|
63
|
+
res.status(400).json({
|
|
64
|
+
error: 'Missing required fields: agentId, command',
|
|
65
|
+
received: req.body
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
log.log(`[Exec] Received exec request for agent ${agentId}`);
|
|
70
|
+
log.log(`[Exec] Command: ${command.slice(0, 100)}${command.length > 100 ? '...' : ''}`);
|
|
71
|
+
if (cwd) {
|
|
72
|
+
log.log(`[Exec] CWD: ${cwd}`);
|
|
73
|
+
}
|
|
74
|
+
// Get agent info
|
|
75
|
+
const agent = agentService.getAgent(agentId);
|
|
76
|
+
if (!agent) {
|
|
77
|
+
res.status(404).json({ error: `Agent not found: ${agentId}` });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Use provided cwd or agent's cwd
|
|
81
|
+
const workingDir = cwd || agent.cwd;
|
|
82
|
+
// Replace secret placeholders in command (e.g., {{API_KEY}} -> actual value)
|
|
83
|
+
const processedCommand = secretsService.replaceSecrets(command);
|
|
84
|
+
// Generate task ID
|
|
85
|
+
const taskId = generateId();
|
|
86
|
+
// Log original command (not processed, to avoid leaking secrets in logs)
|
|
87
|
+
log.log(`[${agent.name}] Executing: ${command} (task: ${taskId})`);
|
|
88
|
+
// Broadcast task started
|
|
89
|
+
if (broadcastFn) {
|
|
90
|
+
broadcastFn({
|
|
91
|
+
type: 'exec_task_started',
|
|
92
|
+
payload: {
|
|
93
|
+
taskId,
|
|
94
|
+
agentId,
|
|
95
|
+
agentName: agent.name,
|
|
96
|
+
command,
|
|
97
|
+
cwd: workingDir,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
// Spawn the process with secrets replaced
|
|
102
|
+
const childProcess = spawn('bash', ['-c', processedCommand], {
|
|
103
|
+
cwd: workingDir,
|
|
104
|
+
env: { ...process.env },
|
|
105
|
+
shell: false,
|
|
106
|
+
});
|
|
107
|
+
// Track the task
|
|
108
|
+
const task = {
|
|
109
|
+
id: taskId,
|
|
110
|
+
agentId,
|
|
111
|
+
command,
|
|
112
|
+
process: childProcess,
|
|
113
|
+
output: [],
|
|
114
|
+
startedAt: Date.now(),
|
|
115
|
+
};
|
|
116
|
+
runningTasks.set(taskId, task);
|
|
117
|
+
// Collect output
|
|
118
|
+
let fullOutput = '';
|
|
119
|
+
let exitCode = null;
|
|
120
|
+
// Stream stdout
|
|
121
|
+
childProcess.stdout?.on('data', (data) => {
|
|
122
|
+
const text = data.toString();
|
|
123
|
+
fullOutput += text;
|
|
124
|
+
task.output.push(text);
|
|
125
|
+
// Broadcast output chunk
|
|
126
|
+
if (broadcastFn) {
|
|
127
|
+
broadcastFn({
|
|
128
|
+
type: 'exec_task_output',
|
|
129
|
+
payload: {
|
|
130
|
+
taskId,
|
|
131
|
+
agentId,
|
|
132
|
+
output: text,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
// Stream stderr
|
|
138
|
+
childProcess.stderr?.on('data', (data) => {
|
|
139
|
+
const text = data.toString();
|
|
140
|
+
fullOutput += text;
|
|
141
|
+
task.output.push(text);
|
|
142
|
+
// Broadcast output chunk (stderr too)
|
|
143
|
+
if (broadcastFn) {
|
|
144
|
+
broadcastFn({
|
|
145
|
+
type: 'exec_task_output',
|
|
146
|
+
payload: {
|
|
147
|
+
taskId,
|
|
148
|
+
agentId,
|
|
149
|
+
output: text,
|
|
150
|
+
isError: true,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
// Wait for process to complete
|
|
156
|
+
await new Promise((resolve) => {
|
|
157
|
+
childProcess.on('close', (code) => {
|
|
158
|
+
exitCode = code;
|
|
159
|
+
resolve();
|
|
160
|
+
});
|
|
161
|
+
childProcess.on('error', (err) => {
|
|
162
|
+
log.error(`[${agent.name}] Process error:`, err);
|
|
163
|
+
fullOutput += `\nError: ${err.message}`;
|
|
164
|
+
resolve();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
// Clean up task tracking
|
|
168
|
+
runningTasks.delete(taskId);
|
|
169
|
+
// Broadcast task completed
|
|
170
|
+
if (broadcastFn) {
|
|
171
|
+
broadcastFn({
|
|
172
|
+
type: 'exec_task_completed',
|
|
173
|
+
payload: {
|
|
174
|
+
taskId,
|
|
175
|
+
agentId,
|
|
176
|
+
exitCode,
|
|
177
|
+
success: exitCode === 0,
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
log.log(`[${agent.name}] Command completed with exit code ${exitCode}`);
|
|
182
|
+
// Return final result to the caller (curl)
|
|
183
|
+
res.status(200).json({
|
|
184
|
+
success: exitCode === 0,
|
|
185
|
+
taskId,
|
|
186
|
+
exitCode,
|
|
187
|
+
output: fullOutput,
|
|
188
|
+
duration: Date.now() - task.startedAt,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
log.error('Failed to execute command:', err);
|
|
193
|
+
log.error('Error details:', {
|
|
194
|
+
message: err.message,
|
|
195
|
+
code: err.code,
|
|
196
|
+
errno: err.errno,
|
|
197
|
+
syscall: err.syscall,
|
|
198
|
+
});
|
|
199
|
+
res.status(500).json({
|
|
200
|
+
error: err.message,
|
|
201
|
+
details: {
|
|
202
|
+
code: err.code,
|
|
203
|
+
syscall: err.syscall,
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
/**
|
|
209
|
+
* GET /api/exec/tasks/:agentId - List running tasks for an agent
|
|
210
|
+
*/
|
|
211
|
+
router.get('/tasks/:agentId', (req, res) => {
|
|
212
|
+
const agentId = req.params.agentId;
|
|
213
|
+
const tasks = getRunningTasks(agentId).map(t => ({
|
|
214
|
+
id: t.id,
|
|
215
|
+
command: t.command,
|
|
216
|
+
startedAt: t.startedAt,
|
|
217
|
+
outputLines: t.output.length,
|
|
218
|
+
}));
|
|
219
|
+
res.json({ tasks });
|
|
220
|
+
});
|
|
221
|
+
/**
|
|
222
|
+
* DELETE /api/exec/tasks/:taskId - Kill a running task
|
|
223
|
+
*/
|
|
224
|
+
router.delete('/tasks/:taskId', (req, res) => {
|
|
225
|
+
const taskId = req.params.taskId;
|
|
226
|
+
const killed = killTask(taskId);
|
|
227
|
+
if (killed) {
|
|
228
|
+
res.json({ success: true, message: `Task ${taskId} killed` });
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
res.status(404).json({ error: `Task not found: ${taskId}` });
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
/**
|
|
235
|
+
* POST /api/exec/generate-curl - Generate properly escaped curl command for shell execution
|
|
236
|
+
*
|
|
237
|
+
* This endpoint generates a curl command with proper escaping for Codex agents
|
|
238
|
+
* that need to execute it through shell (zsh, bash, etc.)
|
|
239
|
+
*/
|
|
240
|
+
router.post('/generate-curl', (req, res) => {
|
|
241
|
+
const { agentId, command, cwd } = req.body;
|
|
242
|
+
if (!agentId || !command) {
|
|
243
|
+
res.status(400).json({
|
|
244
|
+
error: 'Missing required fields: agentId, command'
|
|
245
|
+
});
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
// Build the JSON payload
|
|
249
|
+
const payload = {
|
|
250
|
+
agentId,
|
|
251
|
+
command,
|
|
252
|
+
};
|
|
253
|
+
if (cwd) {
|
|
254
|
+
payload.cwd = cwd;
|
|
255
|
+
}
|
|
256
|
+
// Escape the JSON payload properly for shell execution
|
|
257
|
+
// Use single quotes around JSON and escape any single quotes inside
|
|
258
|
+
const jsonStr = JSON.stringify(payload);
|
|
259
|
+
const escapedJson = jsonStr.replace(/'/g, "'\\''");
|
|
260
|
+
// Generate curl command using $'...' syntax (ANSI-C quoting)
|
|
261
|
+
// This is more reliable across different shells
|
|
262
|
+
const curlCommand = `curl -s -X POST http://localhost:5174/api/exec -H "Content-Type: application/json" -d '${escapedJson}'`;
|
|
263
|
+
res.json({
|
|
264
|
+
success: true,
|
|
265
|
+
command: curlCommand,
|
|
266
|
+
payload,
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
export default router;
|