@pixelbyte-software/pixcode 1.52.4 → 1.53.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/README.md +9 -10
- package/README.tr.md +1 -1
- package/dist/api-automation.html +1 -1
- package/dist/assets/index-BO0lz8ZD.js +816 -0
- package/dist/assets/index-DnjqWG8B.css +32 -0
- package/dist/docs.html +10 -10
- package/dist/features.html +3 -3
- package/dist/index.html +2 -2
- package/dist/landing.html +16 -16
- package/dist/llms-full.txt +4 -4
- package/dist/llms.txt +3 -3
- package/dist/openapi.yaml +6 -6
- package/dist-server/server/index.js +8 -125
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.js +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/agent-card.js +4 -4
- package/dist-server/server/modules/orchestration/a2a/agent-card.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/routes.js +2 -5
- package/dist-server/server/modules/orchestration/a2a/routes.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/task-dispatcher.js +295 -0
- package/dist-server/server/modules/orchestration/a2a/task-dispatcher.js.map +1 -0
- package/dist-server/server/modules/orchestration/index.js +0 -2
- package/dist-server/server/modules/orchestration/index.js.map +1 -1
- package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js +2 -2
- package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js.map +1 -1
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js +12 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js.map +1 -1
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js +19 -26
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js.map +1 -1
- package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +47 -58
- package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -1
- package/dist-server/server/modules/orchestration/workflows/workflow-trace.js +2 -2
- package/dist-server/server/modules/orchestration/workflows/workflow-trace.js.map +1 -1
- package/dist-server/server/routes/git.js +79 -21
- package/dist-server/server/routes/git.js.map +1 -1
- package/dist-server/server/services/public-api-manifest.js +0 -9
- package/dist-server/server/services/public-api-manifest.js.map +1 -1
- package/package.json +1 -1
- package/server/index.js +7 -134
- package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +1 -1
- package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +1 -1
- package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +1 -1
- package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +1 -1
- package/server/modules/orchestration/a2a/adapters/json-event.adapter.ts +1 -1
- package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +1 -1
- package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +1 -1
- package/server/modules/orchestration/a2a/agent-card.ts +4 -4
- package/server/modules/orchestration/a2a/routes.ts +2 -6
- package/server/modules/orchestration/a2a/task-dispatcher.ts +345 -0
- package/server/modules/orchestration/index.ts +0 -2
- package/server/modules/orchestration/tasks/orchestration-task-store.ts +2 -2
- package/server/modules/orchestration/tasks/orchestration-task.routes.ts +17 -0
- package/server/modules/orchestration/tasks/orchestration-task.service.ts +19 -27
- package/server/modules/orchestration/tasks/orchestration-task.types.ts +2 -2
- package/server/modules/orchestration/tasks/task-run-graph.ts +1 -1
- package/server/modules/orchestration/workflows/workflow-runner.ts +52 -60
- package/server/modules/orchestration/workflows/workflow-trace.ts +2 -2
- package/server/modules/orchestration/workflows/workflow.types.ts +1 -1
- package/server/routes/git.js +89 -28
- package/server/services/public-api-manifest.js +0 -9
- package/dist/assets/index-CapxXSc7.js +0 -816
- package/dist/assets/index-DkT6-Pja.css +0 -32
- package/dist/hermes-agent.png +0 -0
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js +0 -577
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js.map +0 -1
- package/dist-server/server/services/hermes-gateway.js +0 -1467
- package/dist-server/server/services/hermes-gateway.js.map +0 -1
- package/dist-server/server/services/hermes-install-jobs.js +0 -676
- package/dist-server/server/services/hermes-install-jobs.js.map +0 -1
- package/scripts/hermes/configure-pixcode-mcp.mjs +0 -165
- package/scripts/hermes/pixcode-mcp-server.mjs +0 -1009
- package/scripts/smoke/hermes-api-install.mjs +0 -56
- package/scripts/smoke/hermes-gateway-persistence.mjs +0 -104
- package/scripts/smoke/hermes-mcp-pixcode-roundtrip.mjs +0 -426
- package/scripts/smoke/hermes-rest-chat-api.mjs +0 -162
- package/scripts/smoke/hermes-rest-chat-live.mjs +0 -45
- package/scripts/smoke/hermes-rest-codex-launch.mjs +0 -209
- package/scripts/smoke/hermes-rest-gateway.mjs +0 -79
- package/scripts/smoke/hermes-rest-live.mjs +0 -42
- package/scripts/smoke/hermes-roundtrip.mjs +0 -167
- package/scripts/smoke/hermes-settings-commands.mjs +0 -349
- package/scripts/smoke/hermes-smoke-launcher-guard.mjs +0 -34
- package/server/modules/orchestration/hermes/hermes.routes.ts +0 -642
- package/server/services/hermes-gateway.js +0 -1562
- package/server/services/hermes-install-jobs.js +0 -729
package/server/index.js
CHANGED
|
@@ -104,7 +104,6 @@ import platformizationRoutes from './routes/platformization.js';
|
|
|
104
104
|
import liveViewRoutes, { createLiveViewPublicRouter } from './routes/live-view.js';
|
|
105
105
|
import providerRoutes from './modules/providers/provider.routes.js';
|
|
106
106
|
import {
|
|
107
|
-
createHermesTaskRouter,
|
|
108
107
|
adapterRegistry,
|
|
109
108
|
ClaudeCodeA2AAdapter,
|
|
110
109
|
CodexA2AAdapter,
|
|
@@ -115,7 +114,6 @@ import {
|
|
|
115
114
|
JsonEventA2AAdapter,
|
|
116
115
|
createPreviewProxyRouter,
|
|
117
116
|
createOrchestrationTaskRouter,
|
|
118
|
-
createHermesRouter,
|
|
119
117
|
createWorkflowRouter,
|
|
120
118
|
} from './modules/orchestration/index.js';
|
|
121
119
|
import networkRoutes from './routes/network.js';
|
|
@@ -127,9 +125,8 @@ import {
|
|
|
127
125
|
applyAllStoredCredentialsToEnv,
|
|
128
126
|
} from './services/provider-credentials.js';
|
|
129
127
|
import { primeCliBinPath } from './services/install-jobs.js';
|
|
130
|
-
import { buildHermesPathEnv, primeHermesPath } from './services/hermes-install-jobs.js';
|
|
131
128
|
import { startEnabledPluginServers, stopAllPlugins, getPluginPort } from './utils/plugin-process-manager.js';
|
|
132
|
-
import { initializeDatabase, sessionNamesDb, applyCustomSessionNames,
|
|
129
|
+
import { initializeDatabase, sessionNamesDb, applyCustomSessionNames, appConfigDb } from './database/db.js';
|
|
133
130
|
import { setNotificationWebSocketServer } from './services/notification-orchestrator.js';
|
|
134
131
|
import { configureWebPush } from './services/vapid-keys.js';
|
|
135
132
|
import { validateApiKey, authenticateToken, authenticateWebSocket, requireAdmin, requireApiScope } from './middleware/auth.js';
|
|
@@ -1143,13 +1140,6 @@ function resolvePublicBaseUrl(request) {
|
|
|
1143
1140
|
return `${proto}://${String(host).split(',')[0].trim()}`;
|
|
1144
1141
|
}
|
|
1145
1142
|
|
|
1146
|
-
function resolveHermesMcpBaseUrl() {
|
|
1147
|
-
const configured = process.env.PIXCODE_INTERNAL_BASE_URL || process.env.PIXCODE_HERMES_BASE_URL;
|
|
1148
|
-
if (configured) return configured.replace(/\/$/, '');
|
|
1149
|
-
|
|
1150
|
-
return `http://127.0.0.1:${process.env.SERVER_PORT || process.env.PORT || '3001'}`;
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
1143
|
function quoteBashArg(value) {
|
|
1154
1144
|
return `'${String(value).replace(/'/g, "'\\''")}'`;
|
|
1155
1145
|
}
|
|
@@ -1162,74 +1152,6 @@ function quoteShellArgForPlatform(value) {
|
|
|
1162
1152
|
return os.platform() === 'win32' ? quotePowerShellArg(value) : quoteBashArg(value);
|
|
1163
1153
|
}
|
|
1164
1154
|
|
|
1165
|
-
const HERMES_CLI_COMMAND_PATTERN = /^hermes(?:\s+[A-Za-z0-9._:/=@+-]+)*\s*$/;
|
|
1166
|
-
const HERMES_AGENT_API_SCOPES = [
|
|
1167
|
-
'auth:read',
|
|
1168
|
-
'auth:write',
|
|
1169
|
-
'diagnostics:read',
|
|
1170
|
-
'files:read',
|
|
1171
|
-
'files:write',
|
|
1172
|
-
'git:read',
|
|
1173
|
-
'git:write',
|
|
1174
|
-
'hermes:mcp',
|
|
1175
|
-
'hermes:gateway',
|
|
1176
|
-
'notifications:read',
|
|
1177
|
-
'notifications:write',
|
|
1178
|
-
'orchestration:read',
|
|
1179
|
-
'orchestration:write',
|
|
1180
|
-
'plugins:read',
|
|
1181
|
-
'plugins:write',
|
|
1182
|
-
'projects:read',
|
|
1183
|
-
'projects:write',
|
|
1184
|
-
'providers:read',
|
|
1185
|
-
'providers:write',
|
|
1186
|
-
'remote:read',
|
|
1187
|
-
'remote:write',
|
|
1188
|
-
'sessions:read',
|
|
1189
|
-
'sessions:write',
|
|
1190
|
-
'settings:read',
|
|
1191
|
-
'settings:write',
|
|
1192
|
-
'telegram:read',
|
|
1193
|
-
'telegram:write',
|
|
1194
|
-
'terminal:launch',
|
|
1195
|
-
'updates:read',
|
|
1196
|
-
'updates:write',
|
|
1197
|
-
'webhooks:read',
|
|
1198
|
-
'webhooks:write',
|
|
1199
|
-
];
|
|
1200
|
-
|
|
1201
|
-
function isHermesCliCommand(command) {
|
|
1202
|
-
return typeof command === 'string' && HERMES_CLI_COMMAND_PATTERN.test(command.trim());
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
function buildHermesCliCommand(command) {
|
|
1206
|
-
const hermesCommand = typeof command === 'string' && command.trim() ? command.trim() : 'hermes';
|
|
1207
|
-
const configureScript = path.join(APP_ROOT, 'scripts', 'hermes', 'configure-pixcode-mcp.mjs');
|
|
1208
|
-
if (os.platform() === 'win32') {
|
|
1209
|
-
return `& ${quotePowerShellArg(process.execPath)} ${quotePowerShellArg(configureScript)} *> $null; ${hermesCommand}`;
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
return `${quoteBashArg(process.execPath)} ${quoteBashArg(configureScript)} >/dev/null 2>&1; exec ${hermesCommand}`;
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
function getOrCreateHermesApiKey(userId) {
|
|
1216
|
-
if (!userId) return null;
|
|
1217
|
-
|
|
1218
|
-
const existing = apiKeysDb
|
|
1219
|
-
.getApiKeys(userId)
|
|
1220
|
-
.find((key) => key.key_name === 'Hermes Agent MCP' && key.is_active);
|
|
1221
|
-
if (existing?.api_key) {
|
|
1222
|
-
const existingScopes = Array.isArray(existing.scopes) ? existing.scopes : [];
|
|
1223
|
-
const missingScopes = HERMES_AGENT_API_SCOPES.filter((scope) => !existingScopes.includes(scope));
|
|
1224
|
-
if (missingScopes.length > 0 && existing.id) {
|
|
1225
|
-
apiKeysDb.updateApiKeyScopes(userId, existing.id, [...existingScopes, ...missingScopes]);
|
|
1226
|
-
}
|
|
1227
|
-
return existing.api_key;
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
return apiKeysDb.createApiKey(userId, 'Hermes Agent MCP', HERMES_AGENT_API_SCOPES).apiKey;
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
1155
|
// Single WebSocket server that handles both paths
|
|
1234
1156
|
const wss = new WebSocketServer({
|
|
1235
1157
|
server,
|
|
@@ -1321,8 +1243,6 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, requireProject
|
|
|
1321
1243
|
const projectPath = typeof req.query.projectPath === 'string' && req.query.projectPath.trim()
|
|
1322
1244
|
? req.query.projectPath.trim()
|
|
1323
1245
|
: null;
|
|
1324
|
-
const launchId = Number.parseInt(String(req.query.launchId || ''), 10);
|
|
1325
|
-
const requestedLaunchId = Number.isFinite(launchId) && launchId > 0 ? launchId : null;
|
|
1326
1246
|
const maxChars = Math.min(
|
|
1327
1247
|
20000,
|
|
1328
1248
|
Math.max(1000, Number.parseInt(String(req.query.maxChars || '12000'), 10) || 12000)
|
|
@@ -1341,8 +1261,7 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, requireProject
|
|
|
1341
1261
|
session?.provider === provider &&
|
|
1342
1262
|
!session?.isPlainShell &&
|
|
1343
1263
|
(canReadAnyShellSession || session?.userId === requestUserId) &&
|
|
1344
|
-
(!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath)
|
|
1345
|
-
(!requestedLaunchId || session.hermesLaunchId === requestedLaunchId)
|
|
1264
|
+
(!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath)
|
|
1346
1265
|
) {
|
|
1347
1266
|
if (!matchedSession || (session.updatedAt || 0) > (matchedSession.updatedAt || 0)) {
|
|
1348
1267
|
matchedSession = session;
|
|
@@ -1355,7 +1274,6 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, requireProject
|
|
|
1355
1274
|
active: false,
|
|
1356
1275
|
provider,
|
|
1357
1276
|
projectPath: requestedProjectPath,
|
|
1358
|
-
launchId: requestedLaunchId,
|
|
1359
1277
|
output: '',
|
|
1360
1278
|
message: 'No active provider terminal session found for this project.',
|
|
1361
1279
|
});
|
|
@@ -1369,7 +1287,6 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, requireProject
|
|
|
1369
1287
|
provider,
|
|
1370
1288
|
projectPath: path.resolve(matchedSession.projectPath || os.homedir()),
|
|
1371
1289
|
sessionId: matchedSession.sessionId || null,
|
|
1372
|
-
launchId: matchedSession.hermesLaunchId || null,
|
|
1373
1290
|
updatedAt: matchedSession.updatedAt || null,
|
|
1374
1291
|
...terminalState,
|
|
1375
1292
|
output,
|
|
@@ -1381,8 +1298,6 @@ app.post('/api/shell/sessions/provider-input', authenticateToken, requireProject
|
|
|
1381
1298
|
const projectPath = typeof req.body?.projectPath === 'string' && req.body.projectPath.trim()
|
|
1382
1299
|
? req.body.projectPath.trim()
|
|
1383
1300
|
: null;
|
|
1384
|
-
const launchId = Number.parseInt(String(req.body?.launchId || ''), 10);
|
|
1385
|
-
const requestedLaunchId = Number.isFinite(launchId) && launchId > 0 ? launchId : null;
|
|
1386
1301
|
const input = typeof req.body?.input === 'string' ? req.body.input : '';
|
|
1387
1302
|
const submit = req.body?.submit !== false;
|
|
1388
1303
|
|
|
@@ -1401,8 +1316,7 @@ app.post('/api/shell/sessions/provider-input', authenticateToken, requireProject
|
|
|
1401
1316
|
session?.pty &&
|
|
1402
1317
|
session.lifecycleState === 'running' &&
|
|
1403
1318
|
(canWriteAnyShellSession || session?.userId === requestUserId) &&
|
|
1404
|
-
(!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath)
|
|
1405
|
-
(!requestedLaunchId || session.hermesLaunchId === requestedLaunchId)
|
|
1319
|
+
(!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath)
|
|
1406
1320
|
) {
|
|
1407
1321
|
if (!matchedSession || (session.updatedAt || 0) > (matchedSession.updatedAt || 0)) {
|
|
1408
1322
|
matchedSession = session;
|
|
@@ -1415,7 +1329,6 @@ app.post('/api/shell/sessions/provider-input', authenticateToken, requireProject
|
|
|
1415
1329
|
ok: false,
|
|
1416
1330
|
provider,
|
|
1417
1331
|
projectPath: requestedProjectPath,
|
|
1418
|
-
launchId: requestedLaunchId,
|
|
1419
1332
|
wrote: false,
|
|
1420
1333
|
message: 'No running provider terminal session found for this project.',
|
|
1421
1334
|
});
|
|
@@ -1430,7 +1343,6 @@ app.post('/api/shell/sessions/provider-input', authenticateToken, requireProject
|
|
|
1430
1343
|
provider,
|
|
1431
1344
|
projectPath: path.resolve(matchedSession.projectPath || os.homedir()),
|
|
1432
1345
|
sessionId: matchedSession.sessionId || null,
|
|
1433
|
-
launchId: matchedSession.hermesLaunchId || null,
|
|
1434
1346
|
wrote: true,
|
|
1435
1347
|
submitted: submit,
|
|
1436
1348
|
bytes: Buffer.byteLength(data),
|
|
@@ -1508,7 +1420,6 @@ app.use('/api/live-view', authenticateToken, liveViewRoutes);
|
|
|
1508
1420
|
// Unified provider MCP routes (protected)
|
|
1509
1421
|
app.use('/api/providers', authenticateToken, providerRoutes);
|
|
1510
1422
|
|
|
1511
|
-
// Hermes internal task router has its own localhost/auth middleware; do not wrap with authenticateToken.
|
|
1512
1423
|
adapterRegistry.register(new ClaudeCodeA2AAdapter());
|
|
1513
1424
|
adapterRegistry.register(new CodexA2AAdapter());
|
|
1514
1425
|
adapterRegistry.register(new CursorA2AAdapter());
|
|
@@ -1516,14 +1427,8 @@ adapterRegistry.register(new GeminiA2AAdapter());
|
|
|
1516
1427
|
adapterRegistry.register(new QwenA2AAdapter());
|
|
1517
1428
|
adapterRegistry.register(new OpenCodeA2AAdapter());
|
|
1518
1429
|
adapterRegistry.register(new JsonEventA2AAdapter());
|
|
1519
|
-
app.use('/hermes', createHermesTaskRouter());
|
|
1520
1430
|
app.use('/preview', authenticateToken, requireAdmin, createPreviewProxyRouter());
|
|
1521
1431
|
app.use('/api/orchestration', authenticateToken, requireAdmin, createOrchestrationTaskRouter());
|
|
1522
|
-
app.use('/api/orchestration/hermes', authenticateToken, requireAdmin, createHermesRouter({
|
|
1523
|
-
appRoot: APP_ROOT,
|
|
1524
|
-
createHermesApiKey: getOrCreateHermesApiKey,
|
|
1525
|
-
resolvePublicBaseUrl,
|
|
1526
|
-
}));
|
|
1527
1432
|
app.use('/api/orchestration', authenticateToken, requireAdmin, createWorkflowRouter());
|
|
1528
1433
|
app.use('/live', createLiveViewPublicRouter());
|
|
1529
1434
|
|
|
@@ -3394,18 +3299,11 @@ function handleShellConnection(ws, request) {
|
|
|
3394
3299
|
const startupInputDelivery = data.startupInputDelivery === 'terminal' ? 'terminal' : 'command';
|
|
3395
3300
|
const commandStartupInput = startupInputDelivery === 'command' ? startupInput : null;
|
|
3396
3301
|
const terminalStartupInput = startupInputDelivery === 'terminal' ? startupInput : null;
|
|
3397
|
-
const hermesLaunchId = Number.isFinite(Number(data.hermesLaunchId)) && Number(data.hermesLaunchId) > 0
|
|
3398
|
-
? Number(data.hermesLaunchId)
|
|
3399
|
-
: null;
|
|
3400
3302
|
const isPlainShell = data.isPlainShell || (!!initialCommand && !hasSession) || provider === 'plain-shell';
|
|
3401
|
-
const isHermesCliLaunch = isPlainShell && isHermesCliCommand(initialCommand);
|
|
3402
3303
|
const forceNewSession = Boolean(data.forceNewSession);
|
|
3403
3304
|
const shellPermissionMode = normalizeShellPermissionMode(data.permissionMode);
|
|
3404
3305
|
const shellSkipPermissions = Boolean(data.skipPermissions);
|
|
3405
3306
|
const shellPermissionFlags = buildProviderShellPermissionFlags(provider, shellPermissionMode, shellSkipPermissions);
|
|
3406
|
-
const hermesApiKey = isHermesCliLaunch
|
|
3407
|
-
? getOrCreateHermesApiKey(request.user?.id ?? request.user?.userId ?? null)
|
|
3408
|
-
: null;
|
|
3409
3307
|
urlDetectionBuffer = '';
|
|
3410
3308
|
announcedAuthUrls.clear();
|
|
3411
3309
|
|
|
@@ -3477,7 +3375,6 @@ function handleShellConnection(ws, request) {
|
|
|
3477
3375
|
}
|
|
3478
3376
|
|
|
3479
3377
|
existingSession.ws = ws;
|
|
3480
|
-
existingSession.hermesLaunchId = hermesLaunchId || existingSession.hermesLaunchId;
|
|
3481
3378
|
existingSession.updatedAt = Date.now();
|
|
3482
3379
|
if (terminalStartupInput && !isPlainShell) {
|
|
3483
3380
|
writeTerminalStartupInput(existingSession, terminalStartupInput, 'reused provider session', 350);
|
|
@@ -3539,9 +3436,7 @@ function handleShellConnection(ws, request) {
|
|
|
3539
3436
|
let shellCommand;
|
|
3540
3437
|
if (isPlainShell) {
|
|
3541
3438
|
// Plain shell mode without an initial command must stay interactive.
|
|
3542
|
-
shellCommand =
|
|
3543
|
-
? buildHermesCliCommand(initialCommand)
|
|
3544
|
-
: initialCommand || null;
|
|
3439
|
+
shellCommand = initialCommand || null;
|
|
3545
3440
|
} else if (provider === 'cursor') {
|
|
3546
3441
|
const command = buildProviderShellCommand('cursor-agent', shellPermissionFlags);
|
|
3547
3442
|
if (hasSession && sessionId) {
|
|
@@ -3654,16 +3549,12 @@ function handleShellConnection(ws, request) {
|
|
|
3654
3549
|
const termCols = data.cols || 80;
|
|
3655
3550
|
const termRows = data.rows || 24;
|
|
3656
3551
|
console.log('📐 Using terminal dimensions:', termCols, 'x', termRows);
|
|
3657
|
-
const shellEnv =
|
|
3552
|
+
const shellEnv = {
|
|
3553
|
+
...process.env,
|
|
3658
3554
|
TERM: 'xterm-256color',
|
|
3659
3555
|
COLORTERM: 'truecolor',
|
|
3660
3556
|
FORCE_COLOR: '3',
|
|
3661
|
-
|
|
3662
|
-
PIXCODE_BASE_URL: resolveHermesMcpBaseUrl(),
|
|
3663
|
-
PIXCODE_API_KEY: hermesApiKey || '',
|
|
3664
|
-
PIXCODE_APP_ROOT: APP_ROOT,
|
|
3665
|
-
} : {}),
|
|
3666
|
-
});
|
|
3557
|
+
};
|
|
3667
3558
|
|
|
3668
3559
|
shellProcess = pty.spawn(shell, shellArgs, {
|
|
3669
3560
|
name: 'xterm-256color',
|
|
@@ -3684,7 +3575,6 @@ function handleShellConnection(ws, request) {
|
|
|
3684
3575
|
projectPath,
|
|
3685
3576
|
sessionId,
|
|
3686
3577
|
tabId,
|
|
3687
|
-
hermesLaunchId,
|
|
3688
3578
|
provider,
|
|
3689
3579
|
isPlainShell,
|
|
3690
3580
|
lifecycleState: 'running',
|
|
@@ -3825,14 +3715,6 @@ function handleShellConnection(ws, request) {
|
|
|
3825
3715
|
return;
|
|
3826
3716
|
}
|
|
3827
3717
|
|
|
3828
|
-
// Plain shells are cheap to recreate, so terminate them immediately
|
|
3829
|
-
// instead of keeping a 30-minute zombie PTY around.
|
|
3830
|
-
if (session.isPlainShell) {
|
|
3831
|
-
console.log('🧹 Terminating plain shell PTY on disconnect:', ptySessionKey);
|
|
3832
|
-
terminatePtySession(ptySessionKey, session, 'plain shell disconnect');
|
|
3833
|
-
return;
|
|
3834
|
-
}
|
|
3835
|
-
|
|
3836
3718
|
console.log('⏳ PTY session kept alive, will timeout in 30 minutes:', ptySessionKey);
|
|
3837
3719
|
session.ws = null;
|
|
3838
3720
|
|
|
@@ -4526,15 +4408,6 @@ async function startServer() {
|
|
|
4526
4408
|
console.warn('[install-jobs] Failed to prime CLI bin path:', err?.message || err);
|
|
4527
4409
|
}
|
|
4528
4410
|
|
|
4529
|
-
// Prime Hermes' known install locations separately so the project
|
|
4530
|
-
// terminal can resolve `hermes` even when Windows has not refreshed the
|
|
4531
|
-
// user's PATH for the current Pixcode process.
|
|
4532
|
-
try {
|
|
4533
|
-
primeHermesPath();
|
|
4534
|
-
} catch (err) {
|
|
4535
|
-
console.warn('[install-jobs] Failed to prime Hermes bin path:', err?.message || err);
|
|
4536
|
-
}
|
|
4537
|
-
|
|
4538
4411
|
// Restore any previously-configured Telegram bot. This is best-effort:
|
|
4539
4412
|
// a bad token or network blip should warn, not crash the server.
|
|
4540
4413
|
restoreBotFromConfig().catch((err) => {
|
|
@@ -49,7 +49,7 @@ export class ClaudeCodeA2AAdapter extends AbstractA2AAdapter {
|
|
|
49
49
|
readonly agentCard: AgentCard = {
|
|
50
50
|
name: 'pixcode-claude-code',
|
|
51
51
|
description: 'Anthropic Claude Code, accessed via Pixcode',
|
|
52
|
-
url: '/
|
|
52
|
+
url: '/api/orchestration/agents/claude-code',
|
|
53
53
|
version: '1.0.0',
|
|
54
54
|
capabilities: ['streaming', 'fileEdit', 'commandExec', 'mcp'],
|
|
55
55
|
skills: [
|
|
@@ -40,7 +40,7 @@ export class CodexA2AAdapter extends AbstractA2AAdapter {
|
|
|
40
40
|
readonly agentCard: AgentCard = {
|
|
41
41
|
name: 'pixcode-codex',
|
|
42
42
|
description: 'OpenAI Codex, accessed via Pixcode',
|
|
43
|
-
url: '/
|
|
43
|
+
url: '/api/orchestration/agents/codex',
|
|
44
44
|
version: '1.0.0',
|
|
45
45
|
capabilities: ['streaming', 'fileEdit', 'commandExec', 'webSearch', 'mcp'],
|
|
46
46
|
skills: [
|
|
@@ -40,7 +40,7 @@ export class CursorA2AAdapter extends AbstractA2AAdapter {
|
|
|
40
40
|
readonly agentCard: AgentCard = {
|
|
41
41
|
name: 'pixcode-cursor',
|
|
42
42
|
description: 'Cursor CLI, accessed via Pixcode',
|
|
43
|
-
url: '/
|
|
43
|
+
url: '/api/orchestration/agents/cursor',
|
|
44
44
|
version: '1.0.0',
|
|
45
45
|
capabilities: ['streaming', 'fileEdit', 'commandExec'],
|
|
46
46
|
skills: [
|
|
@@ -40,7 +40,7 @@ export class GeminiA2AAdapter extends AbstractA2AAdapter {
|
|
|
40
40
|
readonly agentCard: AgentCard = {
|
|
41
41
|
name: 'pixcode-gemini',
|
|
42
42
|
description: 'Google Gemini CLI, accessed via Pixcode',
|
|
43
|
-
url: '/
|
|
43
|
+
url: '/api/orchestration/agents/gemini',
|
|
44
44
|
version: '1.0.0',
|
|
45
45
|
capabilities: ['streaming', 'fileEdit', 'commandExec', 'mcp'],
|
|
46
46
|
skills: [
|
|
@@ -21,7 +21,7 @@ export class JsonEventA2AAdapter extends AbstractA2AAdapter {
|
|
|
21
21
|
readonly agentCard: AgentCard = {
|
|
22
22
|
name: 'pixcode-json-event',
|
|
23
23
|
description: 'JSON Event Stream Adapter for Pixcode Orchestration',
|
|
24
|
-
url: '/
|
|
24
|
+
url: '/api/orchestration/agents/json-event',
|
|
25
25
|
version: '1.0.0',
|
|
26
26
|
capabilities: ['streaming', 'event-driven'],
|
|
27
27
|
skills: [
|
|
@@ -40,7 +40,7 @@ export class OpenCodeA2AAdapter extends AbstractA2AAdapter {
|
|
|
40
40
|
readonly agentCard: AgentCard = {
|
|
41
41
|
name: 'pixcode-opencode',
|
|
42
42
|
description: 'OpenCode CLI, accessed via Pixcode',
|
|
43
|
-
url: '/
|
|
43
|
+
url: '/api/orchestration/agents/opencode',
|
|
44
44
|
version: '1.0.0',
|
|
45
45
|
capabilities: ['streaming', 'fileEdit', 'commandExec', 'multiProvider'],
|
|
46
46
|
skills: [
|
|
@@ -40,7 +40,7 @@ export class QwenA2AAdapter extends AbstractA2AAdapter {
|
|
|
40
40
|
readonly agentCard: AgentCard = {
|
|
41
41
|
name: 'pixcode-qwen',
|
|
42
42
|
description: 'Qwen Code CLI, accessed via Pixcode',
|
|
43
|
-
url: '/
|
|
43
|
+
url: '/api/orchestration/agents/qwen',
|
|
44
44
|
version: '1.0.0',
|
|
45
45
|
capabilities: ['streaming', 'fileEdit', 'commandExec', 'mcp'],
|
|
46
46
|
skills: [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// server/modules/orchestration/a2a/agent-card.ts
|
|
2
|
-
// Pixcode advertises
|
|
3
|
-
// Per-CLI adapters publish their own cards
|
|
2
|
+
// Pixcode advertises one local orchestration control agent.
|
|
3
|
+
// Per-CLI adapters publish their own cards through orchestration metadata.
|
|
4
4
|
|
|
5
5
|
import { readFileSync } from 'node:fs';
|
|
6
6
|
import { dirname, resolve } from 'node:path';
|
|
@@ -44,9 +44,9 @@ export function buildPixcodeAgentCard(baseUrl: string): AgentCard {
|
|
|
44
44
|
return {
|
|
45
45
|
name: 'pixcode',
|
|
46
46
|
description:
|
|
47
|
-
'Pixcode
|
|
47
|
+
'Pixcode multi-CLI orchestration platform. Routes tasks to ' +
|
|
48
48
|
'Claude Code, Codex, Cursor, Gemini, Qwen, or OpenCode adapters.',
|
|
49
|
-
url: `${baseUrl.replace(/\/$/, '')}/
|
|
49
|
+
url: `${baseUrl.replace(/\/$/, '')}/api/orchestration`,
|
|
50
50
|
version: VERSION,
|
|
51
51
|
capabilities: ['streaming', 'taskRouting'],
|
|
52
52
|
skills,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// server/modules/orchestration/a2a/routes.ts
|
|
2
|
-
// Internal
|
|
3
|
-
//
|
|
2
|
+
// Internal A2A task router. The adapter primitives stay in this folder while
|
|
3
|
+
// orchestration uses the in-process dispatcher by default.
|
|
4
4
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
|
|
@@ -584,7 +584,3 @@ function createA2ARouter(): Router {
|
|
|
584
584
|
|
|
585
585
|
return router;
|
|
586
586
|
}
|
|
587
|
-
|
|
588
|
-
export function createHermesTaskRouter(): Router {
|
|
589
|
-
return createA2ARouter();
|
|
590
|
-
}
|