@eventmodelers/cli 0.0.18 → 0.0.19
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/cli.js +20 -1
- package/package.json +1 -1
- package/shared/build-kit/lib/ralph.js +26 -1
package/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import { execSync, spawn } from 'child_process';
|
|
18
18
|
import { createInterface, emitKeypressEvents, moveCursor, clearScreenDown } from 'readline';
|
|
19
19
|
import { homedir } from 'os';
|
|
20
|
+
import { randomUUID } from 'crypto';
|
|
20
21
|
|
|
21
22
|
const __filename = fileURLToPath(import.meta.url);
|
|
22
23
|
const __dirname = dirname(__filename);
|
|
@@ -437,6 +438,23 @@ function readJsonSafe(path) {
|
|
|
437
438
|
}
|
|
438
439
|
}
|
|
439
440
|
|
|
441
|
+
// Distinguishes this agent process from any other agent pinging the same
|
|
442
|
+
// token/board — e.g. a build-kit and a modeling-kit install in the same project
|
|
443
|
+
// share one root config.json, and without a per-agent id both would upsert the
|
|
444
|
+
// same alive row and race each other. Written to the kit's OWN config.json
|
|
445
|
+
// (inside kitDir, not the shared root one credentials live in) so a build agent
|
|
446
|
+
// and a modeling agent never end up with the same id, and persisted so restarts
|
|
447
|
+
// of this same kit keep reporting under the same identity.
|
|
448
|
+
function ensureAgentId(kitDir) {
|
|
449
|
+
const kitConfigPath = join(kitDir, '.eventmodelers', 'config.json');
|
|
450
|
+
const existing = readJsonSafe(kitConfigPath);
|
|
451
|
+
if (existing.agentId) return existing.agentId;
|
|
452
|
+
const agentId = randomUUID();
|
|
453
|
+
mkdirSync(dirname(kitConfigPath), { recursive: true });
|
|
454
|
+
writeFileSync(kitConfigPath, JSON.stringify({ ...existing, agentId }, null, 2));
|
|
455
|
+
return agentId;
|
|
456
|
+
}
|
|
457
|
+
|
|
440
458
|
// Hierarchical resolution: a shared config higher up the directory tree (e.g. the
|
|
441
459
|
// project root's own .eventmodelers/config.json, or ~/.eventmodelers/config.json for
|
|
442
460
|
// defaults shared across every project) provides the base values — this is where
|
|
@@ -828,6 +846,7 @@ async function runModeling(kitDir, projectDir) {
|
|
|
828
846
|
const { createClient } = await import('@supabase/supabase-js');
|
|
829
847
|
|
|
830
848
|
const local = loadLocalConfig(kitDir);
|
|
849
|
+
local.agentId = local.agentId ?? ensureAgentId(kitDir);
|
|
831
850
|
if (!local.token || !local.organizationId) {
|
|
832
851
|
console.error('❌ --modeling needs platform credentials in .eventmodelers/config.json (token + organizationId) — run `/connect` once or paste your config first.');
|
|
833
852
|
process.exit(1);
|
|
@@ -1020,7 +1039,7 @@ async function runModeling(kitDir, projectDir) {
|
|
|
1020
1039
|
const res = await fetch(`${cfg.baseUrl}/api/agent-alive`, {
|
|
1021
1040
|
method: 'POST',
|
|
1022
1041
|
headers: { Authorization: `Bearer ${realtimeToken}`, 'Content-Type': 'application/json' },
|
|
1023
|
-
body: JSON.stringify({ token: cfg.token, board_id: cfg.boardId, agent_type: 'MODELING' }),
|
|
1042
|
+
body: JSON.stringify({ token: cfg.token, board_id: cfg.boardId, agent_type: 'MODELING', agent_id: cfg.agentId }),
|
|
1024
1043
|
signal: AbortSignal.timeout(10_000),
|
|
1025
1044
|
});
|
|
1026
1045
|
if (!res.ok) log(`ping failed: ${res.status}`);
|
package/package.json
CHANGED
|
@@ -108,6 +108,30 @@ function hasCredentials(cfg) {
|
|
|
108
108
|
return !!(cfg.token && cfg.organizationId && cfg.boardId && cfg.baseUrl);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
// Distinguishes this agent process from any other agent pinging the same
|
|
112
|
+
// token/board — e.g. a build-kit and a modeling-kit install in the same project
|
|
113
|
+
// share one root config.json, and without a per-agent id both would upsert the
|
|
114
|
+
// same alive row and race each other. Written to the kit's OWN config.json
|
|
115
|
+
// (inside kitDir, not the shared root one credentials live in) so a build agent
|
|
116
|
+
// and a modeling agent never end up with the same id, and persisted so restarts
|
|
117
|
+
// of this same kit keep reporting under the same identity.
|
|
118
|
+
function ensureAgentId(kitDir) {
|
|
119
|
+
const kitConfigPath = join(kitDir, '.eventmodelers', 'config.json');
|
|
120
|
+
let existing = {};
|
|
121
|
+
if (existsSync(kitConfigPath)) {
|
|
122
|
+
try {
|
|
123
|
+
existing = JSON.parse(readFileSync(kitConfigPath, 'utf-8'));
|
|
124
|
+
} catch {
|
|
125
|
+
console.warn(`[ralph] Skipping invalid config at ${kitConfigPath}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (existing.agentId) return existing.agentId;
|
|
129
|
+
const agentId = randomUUID();
|
|
130
|
+
mkdirSync(dirname(kitConfigPath), { recursive: true });
|
|
131
|
+
writeFileSync(kitConfigPath, JSON.stringify({ ...existing, agentId }, null, 2));
|
|
132
|
+
return agentId;
|
|
133
|
+
}
|
|
134
|
+
|
|
111
135
|
async function fetchPlatformConfig(local) {
|
|
112
136
|
const remote = await fetchJSON(`${local.baseUrl}/api/config`, {
|
|
113
137
|
headers: { 'x-token': local.token },
|
|
@@ -252,7 +276,7 @@ async function startRealtimeAgent(cfg, kitDir) {
|
|
|
252
276
|
const res = await fetch(`${cfg.baseUrl}/api/agent-alive`, {
|
|
253
277
|
method: 'POST',
|
|
254
278
|
headers: { Authorization: `Bearer ${realtimeToken}`, 'Content-Type': 'application/json' },
|
|
255
|
-
body: JSON.stringify({ token: cfg.token, board_id: cfg.boardId, agent_type: 'BUILD' }),
|
|
279
|
+
body: JSON.stringify({ token: cfg.token, board_id: cfg.boardId, agent_type: 'BUILD', agent_id: cfg.agentId }),
|
|
256
280
|
signal: AbortSignal.timeout(10_000),
|
|
257
281
|
});
|
|
258
282
|
if (!res.ok) console.error(`[agent] Ping failed: ${res.status}`);
|
|
@@ -357,6 +381,7 @@ export { loadLocalConfig, fetchPlatformConfig, retryOn401, startRealtimeAgent };
|
|
|
357
381
|
|
|
358
382
|
export async function startRalph({ kitDir, projectDir, onTask, onPlannedSlice }) {
|
|
359
383
|
const local = loadLocalConfig(kitDir);
|
|
384
|
+
local.agentId = local.agentId ?? ensureAgentId(kitDir);
|
|
360
385
|
|
|
361
386
|
console.log(`Ralph — kit: ${kitDir}`);
|
|
362
387
|
console.log(` project: ${projectDir}`);
|