replicas-engine 0.1.17 → 0.1.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/dist/src/index.js +195 -12
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -384,7 +384,7 @@ function convertCodexEvent(event, linearSessionId) {
|
|
|
384
384
|
|
|
385
385
|
// src/utils/git.ts
|
|
386
386
|
import { execSync } from "child_process";
|
|
387
|
-
var
|
|
387
|
+
var cachedPr = null;
|
|
388
388
|
function runGitCommand(command, cwd) {
|
|
389
389
|
return execSync(command, {
|
|
390
390
|
cwd,
|
|
@@ -443,16 +443,17 @@ function getGitDiff(cwd) {
|
|
|
443
443
|
}
|
|
444
444
|
}
|
|
445
445
|
function getPullRequestUrl(cwd) {
|
|
446
|
-
if (cachedPrUrl) {
|
|
447
|
-
return cachedPrUrl;
|
|
448
|
-
}
|
|
449
446
|
try {
|
|
450
|
-
const
|
|
451
|
-
if (!
|
|
447
|
+
const currentBranch = getCurrentBranch(cwd);
|
|
448
|
+
if (!currentBranch) {
|
|
452
449
|
return null;
|
|
453
450
|
}
|
|
451
|
+
if (cachedPr && cachedPr.branch === currentBranch) {
|
|
452
|
+
return cachedPr.prUrl;
|
|
453
|
+
}
|
|
454
|
+
cachedPr = null;
|
|
454
455
|
try {
|
|
455
|
-
const remoteRef = execSync(`git ls-remote --heads origin ${
|
|
456
|
+
const remoteRef = execSync(`git ls-remote --heads origin ${currentBranch}`, {
|
|
456
457
|
cwd,
|
|
457
458
|
encoding: "utf-8",
|
|
458
459
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -470,8 +471,11 @@ function getPullRequestUrl(cwd) {
|
|
|
470
471
|
stdio: ["pipe", "pipe", "pipe"]
|
|
471
472
|
}).trim();
|
|
472
473
|
if (prInfo) {
|
|
473
|
-
|
|
474
|
-
|
|
474
|
+
cachedPr = {
|
|
475
|
+
prUrl: prInfo,
|
|
476
|
+
branch: currentBranch
|
|
477
|
+
};
|
|
478
|
+
return cachedPr.prUrl;
|
|
475
479
|
}
|
|
476
480
|
} catch {
|
|
477
481
|
return null;
|
|
@@ -1300,9 +1304,186 @@ var GitHubTokenManager = class {
|
|
|
1300
1304
|
};
|
|
1301
1305
|
var githubTokenManager = new GitHubTokenManager();
|
|
1302
1306
|
|
|
1307
|
+
// src/services/claude-token-manager.ts
|
|
1308
|
+
import { promises as fs2 } from "fs";
|
|
1309
|
+
import path2 from "path";
|
|
1310
|
+
var ClaudeTokenManager = class {
|
|
1311
|
+
refreshInterval = null;
|
|
1312
|
+
REFRESH_INTERVAL_MS = 45 * 60 * 1e3;
|
|
1313
|
+
// 45 minutes
|
|
1314
|
+
async start() {
|
|
1315
|
+
const monolithUrl = process.env.MONOLITH_URL;
|
|
1316
|
+
const workspaceId = process.env.WORKSPACE_ID;
|
|
1317
|
+
const engineSecret = process.env.REPLICAS_ENGINE_SECRET;
|
|
1318
|
+
if (!monolithUrl || !workspaceId || !engineSecret) {
|
|
1319
|
+
console.log("[ClaudeTokenManager] Skipping: missing MONOLITH_URL, WORKSPACE_ID, or REPLICAS_ENGINE_SECRET");
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
console.log("[ClaudeTokenManager] Starting token refresh service");
|
|
1323
|
+
await this.refreshCredentials();
|
|
1324
|
+
this.refreshInterval = setInterval(() => {
|
|
1325
|
+
this.refreshCredentials().catch((error) => {
|
|
1326
|
+
console.error("[ClaudeTokenManager] Scheduled refresh failed:", error);
|
|
1327
|
+
});
|
|
1328
|
+
}, this.REFRESH_INTERVAL_MS);
|
|
1329
|
+
console.log("[ClaudeTokenManager] Token refresh scheduled every 45 minutes");
|
|
1330
|
+
}
|
|
1331
|
+
stop() {
|
|
1332
|
+
if (this.refreshInterval) {
|
|
1333
|
+
clearInterval(this.refreshInterval);
|
|
1334
|
+
this.refreshInterval = null;
|
|
1335
|
+
console.log("[ClaudeTokenManager] Stopped");
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
async refreshCredentials() {
|
|
1339
|
+
const monolithUrl = process.env.MONOLITH_URL;
|
|
1340
|
+
const workspaceId = process.env.WORKSPACE_ID;
|
|
1341
|
+
const engineSecret = process.env.REPLICAS_ENGINE_SECRET;
|
|
1342
|
+
if (!monolithUrl || !workspaceId || !engineSecret) {
|
|
1343
|
+
console.log("[ClaudeTokenManager] Refresh skipped: missing configuration");
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
console.log("[ClaudeTokenManager] Refreshing Claude credentials...");
|
|
1347
|
+
try {
|
|
1348
|
+
const response = await fetch(`${monolithUrl}/v1/engine/claude/refresh-credentials`, {
|
|
1349
|
+
method: "POST",
|
|
1350
|
+
headers: {
|
|
1351
|
+
"Authorization": `Bearer ${engineSecret}`,
|
|
1352
|
+
"X-Workspace-Id": workspaceId,
|
|
1353
|
+
"Content-Type": "application/json"
|
|
1354
|
+
}
|
|
1355
|
+
});
|
|
1356
|
+
if (!response.ok) {
|
|
1357
|
+
const errorText = await response.text();
|
|
1358
|
+
throw new Error(`Credentials refresh failed: ${response.status} ${errorText}`);
|
|
1359
|
+
}
|
|
1360
|
+
const data = await response.json();
|
|
1361
|
+
await this.updateClaudeCredentials(data);
|
|
1362
|
+
console.log(`[ClaudeTokenManager] Credentials refreshed successfully, expires at ${data.expiresAt}`);
|
|
1363
|
+
} catch (error) {
|
|
1364
|
+
console.error("[ClaudeTokenManager] Failed to refresh credentials:", error);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
async updateClaudeCredentials(credentials) {
|
|
1368
|
+
const workspaceHome = process.env.WORKSPACE_HOME || process.env.HOME;
|
|
1369
|
+
if (!workspaceHome) {
|
|
1370
|
+
console.warn("[ClaudeTokenManager] No WORKSPACE_HOME or HOME set, skipping credentials update");
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
const claudeDir = path2.join(workspaceHome, ".claude");
|
|
1374
|
+
const credentialsPath = path2.join(claudeDir, ".credentials.json");
|
|
1375
|
+
const claudeCliConfig = {
|
|
1376
|
+
claudeAiOauth: {
|
|
1377
|
+
accessToken: credentials.accessToken,
|
|
1378
|
+
refreshToken: credentials.refreshToken,
|
|
1379
|
+
expiresAt: new Date(credentials.expiresAt).getTime(),
|
|
1380
|
+
scopes: credentials.scopes,
|
|
1381
|
+
subscriptionType: credentials.subscriptionType
|
|
1382
|
+
}
|
|
1383
|
+
};
|
|
1384
|
+
try {
|
|
1385
|
+
await fs2.mkdir(claudeDir, { recursive: true, mode: 448 });
|
|
1386
|
+
await fs2.writeFile(credentialsPath, JSON.stringify(claudeCliConfig, null, 2), { mode: 384 });
|
|
1387
|
+
console.log(`[ClaudeTokenManager] Updated ${credentialsPath}`);
|
|
1388
|
+
} catch (error) {
|
|
1389
|
+
console.error("[ClaudeTokenManager] Failed to update credentials file:", error);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
var claudeTokenManager = new ClaudeTokenManager();
|
|
1394
|
+
|
|
1395
|
+
// src/services/codex-token-manager.ts
|
|
1396
|
+
import { promises as fs3 } from "fs";
|
|
1397
|
+
import path3 from "path";
|
|
1398
|
+
var CodexTokenManager = class {
|
|
1399
|
+
refreshInterval = null;
|
|
1400
|
+
REFRESH_INTERVAL_MS = 45 * 60 * 1e3;
|
|
1401
|
+
// 45 minutes
|
|
1402
|
+
async start() {
|
|
1403
|
+
const monolithUrl = process.env.MONOLITH_URL;
|
|
1404
|
+
const workspaceId = process.env.WORKSPACE_ID;
|
|
1405
|
+
const engineSecret = process.env.REPLICAS_ENGINE_SECRET;
|
|
1406
|
+
if (!monolithUrl || !workspaceId || !engineSecret) {
|
|
1407
|
+
console.log("[CodexTokenManager] Skipping: missing MONOLITH_URL, WORKSPACE_ID, or REPLICAS_ENGINE_SECRET");
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
console.log("[CodexTokenManager] Starting token refresh service");
|
|
1411
|
+
await this.refreshCredentials();
|
|
1412
|
+
this.refreshInterval = setInterval(() => {
|
|
1413
|
+
this.refreshCredentials().catch((error) => {
|
|
1414
|
+
console.error("[CodexTokenManager] Scheduled refresh failed:", error);
|
|
1415
|
+
});
|
|
1416
|
+
}, this.REFRESH_INTERVAL_MS);
|
|
1417
|
+
console.log("[CodexTokenManager] Token refresh scheduled every 45 minutes");
|
|
1418
|
+
}
|
|
1419
|
+
stop() {
|
|
1420
|
+
if (this.refreshInterval) {
|
|
1421
|
+
clearInterval(this.refreshInterval);
|
|
1422
|
+
this.refreshInterval = null;
|
|
1423
|
+
console.log("[CodexTokenManager] Stopped");
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
async refreshCredentials() {
|
|
1427
|
+
const monolithUrl = process.env.MONOLITH_URL;
|
|
1428
|
+
const workspaceId = process.env.WORKSPACE_ID;
|
|
1429
|
+
const engineSecret = process.env.REPLICAS_ENGINE_SECRET;
|
|
1430
|
+
if (!monolithUrl || !workspaceId || !engineSecret) {
|
|
1431
|
+
console.log("[CodexTokenManager] Refresh skipped: missing configuration");
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
console.log("[CodexTokenManager] Refreshing Codex credentials...");
|
|
1435
|
+
try {
|
|
1436
|
+
const response = await fetch(`${monolithUrl}/v1/engine/codex/refresh-credentials`, {
|
|
1437
|
+
method: "POST",
|
|
1438
|
+
headers: {
|
|
1439
|
+
"Authorization": `Bearer ${engineSecret}`,
|
|
1440
|
+
"X-Workspace-Id": workspaceId,
|
|
1441
|
+
"Content-Type": "application/json"
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
if (!response.ok) {
|
|
1445
|
+
const errorText = await response.text();
|
|
1446
|
+
throw new Error(`Credentials refresh failed: ${response.status} ${errorText}`);
|
|
1447
|
+
}
|
|
1448
|
+
const data = await response.json();
|
|
1449
|
+
await this.updateCodexCredentials(data);
|
|
1450
|
+
console.log(`[CodexTokenManager] Credentials refreshed successfully, expires at ${data.expiresAt}`);
|
|
1451
|
+
} catch (error) {
|
|
1452
|
+
console.error("[CodexTokenManager] Failed to refresh credentials:", error);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
async updateCodexCredentials(credentials) {
|
|
1456
|
+
const workspaceHome = process.env.WORKSPACE_HOME || process.env.HOME;
|
|
1457
|
+
if (!workspaceHome) {
|
|
1458
|
+
console.warn("[CodexTokenManager] No WORKSPACE_HOME or HOME set, skipping credentials update");
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
const codexDir = path3.join(workspaceHome, ".codex");
|
|
1462
|
+
const authPath = path3.join(codexDir, "auth.json");
|
|
1463
|
+
const codexAuthConfig = {
|
|
1464
|
+
OPENAI_API_KEY: null,
|
|
1465
|
+
tokens: {
|
|
1466
|
+
id_token: credentials.idToken,
|
|
1467
|
+
access_token: credentials.accessToken,
|
|
1468
|
+
refresh_token: credentials.refreshToken,
|
|
1469
|
+
account_id: credentials.accountId
|
|
1470
|
+
},
|
|
1471
|
+
last_refresh: (/* @__PURE__ */ new Date()).toISOString()
|
|
1472
|
+
};
|
|
1473
|
+
try {
|
|
1474
|
+
await fs3.mkdir(codexDir, { recursive: true, mode: 448 });
|
|
1475
|
+
await fs3.writeFile(authPath, JSON.stringify(codexAuthConfig, null, 2), { mode: 384 });
|
|
1476
|
+
console.log(`[CodexTokenManager] Updated ${authPath}`);
|
|
1477
|
+
} catch (error) {
|
|
1478
|
+
console.error("[CodexTokenManager] Failed to update credentials file:", error);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
};
|
|
1482
|
+
var codexTokenManager = new CodexTokenManager();
|
|
1483
|
+
|
|
1303
1484
|
// src/services/git-init.ts
|
|
1304
1485
|
import { existsSync } from "fs";
|
|
1305
|
-
import
|
|
1486
|
+
import path4 from "path";
|
|
1306
1487
|
var initializedBranch = null;
|
|
1307
1488
|
function findAvailableBranchName(baseName, cwd) {
|
|
1308
1489
|
if (!branchExists(baseName, cwd)) {
|
|
@@ -1336,7 +1517,7 @@ async function initializeGitRepository() {
|
|
|
1336
1517
|
error: "No WORKSPACE_NAME environment variable set"
|
|
1337
1518
|
};
|
|
1338
1519
|
}
|
|
1339
|
-
const repoPath =
|
|
1520
|
+
const repoPath = path4.join(workspaceHome, "workspaces", repoName);
|
|
1340
1521
|
if (!existsSync(repoPath)) {
|
|
1341
1522
|
console.log(`[GitInit] Repository directory does not exist: ${repoPath}`);
|
|
1342
1523
|
console.log("[GitInit] Waiting for initializer to clone the repository...");
|
|
@@ -1345,7 +1526,7 @@ async function initializeGitRepository() {
|
|
|
1345
1526
|
branch: null
|
|
1346
1527
|
};
|
|
1347
1528
|
}
|
|
1348
|
-
if (!existsSync(
|
|
1529
|
+
if (!existsSync(path4.join(repoPath, ".git"))) {
|
|
1349
1530
|
return {
|
|
1350
1531
|
success: false,
|
|
1351
1532
|
branch: null,
|
|
@@ -1468,6 +1649,8 @@ serve(
|
|
|
1468
1649
|
console.warn(`Git initialization warning: ${gitResult.error}`);
|
|
1469
1650
|
}
|
|
1470
1651
|
await githubTokenManager.start();
|
|
1652
|
+
await claudeTokenManager.start();
|
|
1653
|
+
await codexTokenManager.start();
|
|
1471
1654
|
const monolithService2 = new MonolithService();
|
|
1472
1655
|
await monolithService2.sendEvent({ type: "workspace_ready", payload: {} });
|
|
1473
1656
|
}
|