opencara 0.12.1 → 0.14.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/dist/index.js +140 -49
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -137,20 +137,20 @@ var KNOWN_TOOL_NAMES = new Set(DEFAULT_REGISTRY.tools.map((t) => t.name));
|
|
|
137
137
|
var TOOL_ALIASES = {
|
|
138
138
|
"claude-code": "claude"
|
|
139
139
|
};
|
|
140
|
-
function parseRepoConfig(obj, index) {
|
|
141
|
-
const raw = obj
|
|
140
|
+
function parseRepoConfig(obj, index, field = "repos") {
|
|
141
|
+
const raw = obj[field];
|
|
142
142
|
if (raw === void 0 || raw === null) return void 0;
|
|
143
143
|
if (typeof raw !== "object") {
|
|
144
|
-
throw new RepoConfigError(`agents[${index}]
|
|
144
|
+
throw new RepoConfigError(`agents[${index}].${field} must be an object`);
|
|
145
145
|
}
|
|
146
146
|
const reposObj = raw;
|
|
147
147
|
const mode = reposObj.mode;
|
|
148
148
|
if (mode === void 0) {
|
|
149
|
-
throw new RepoConfigError(`agents[${index}].
|
|
149
|
+
throw new RepoConfigError(`agents[${index}].${field}.mode is required`);
|
|
150
150
|
}
|
|
151
151
|
if (typeof mode !== "string" || !VALID_REPO_MODES.includes(mode)) {
|
|
152
152
|
throw new RepoConfigError(
|
|
153
|
-
`agents[${index}].
|
|
153
|
+
`agents[${index}].${field}.mode must be one of: ${VALID_REPO_MODES.join(", ")}`
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
const config = { mode };
|
|
@@ -158,7 +158,7 @@ function parseRepoConfig(obj, index) {
|
|
|
158
158
|
if (mode === "whitelist" || mode === "blacklist") {
|
|
159
159
|
if (!Array.isArray(list) || list.length === 0) {
|
|
160
160
|
throw new RepoConfigError(
|
|
161
|
-
`agents[${index}].
|
|
161
|
+
`agents[${index}].${field}.list is required and must be non-empty for mode '${mode}'`
|
|
162
162
|
);
|
|
163
163
|
}
|
|
164
164
|
}
|
|
@@ -166,7 +166,7 @@ function parseRepoConfig(obj, index) {
|
|
|
166
166
|
for (let j = 0; j < list.length; j++) {
|
|
167
167
|
if (typeof list[j] !== "string" || !REPO_PATTERN.test(list[j])) {
|
|
168
168
|
throw new RepoConfigError(
|
|
169
|
-
`agents[${index}].
|
|
169
|
+
`agents[${index}].${field}.list[${j}] must match 'owner/repo' format`
|
|
170
170
|
);
|
|
171
171
|
}
|
|
172
172
|
}
|
|
@@ -213,10 +213,18 @@ function parseAgents(data) {
|
|
|
213
213
|
if (typeof obj.command === "string") agent.command = obj.command;
|
|
214
214
|
if (obj.router === true) agent.router = true;
|
|
215
215
|
if (obj.review_only === true) agent.review_only = true;
|
|
216
|
+
if (obj.synthesizer_only === true) agent.synthesizer_only = true;
|
|
217
|
+
if (agent.review_only && agent.synthesizer_only) {
|
|
218
|
+
throw new ConfigValidationError(
|
|
219
|
+
`agents[${i}]: review_only and synthesizer_only cannot both be true`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
216
222
|
if (typeof obj.github_token === "string") agent.github_token = obj.github_token;
|
|
217
223
|
if (typeof obj.codebase_dir === "string") agent.codebase_dir = obj.codebase_dir;
|
|
218
224
|
const repoConfig = parseRepoConfig(obj, i);
|
|
219
225
|
if (repoConfig) agent.repos = repoConfig;
|
|
226
|
+
const synthesizeRepoConfig = parseRepoConfig(obj, i, "synthesize_repos");
|
|
227
|
+
if (synthesizeRepoConfig) agent.synthesize_repos = synthesizeRepoConfig;
|
|
220
228
|
agents.push(agent);
|
|
221
229
|
}
|
|
222
230
|
return agents;
|
|
@@ -254,9 +262,11 @@ function loadConfig() {
|
|
|
254
262
|
const envPlatformUrl = process.env.OPENCARA_PLATFORM_URL?.trim() || null;
|
|
255
263
|
const defaults = {
|
|
256
264
|
platformUrl: envPlatformUrl || DEFAULT_PLATFORM_URL,
|
|
265
|
+
apiKey: null,
|
|
257
266
|
maxDiffSizeKb: DEFAULT_MAX_DIFF_SIZE_KB,
|
|
258
267
|
maxConsecutiveErrors: DEFAULT_MAX_CONSECUTIVE_ERRORS,
|
|
259
268
|
githubToken: null,
|
|
269
|
+
githubUsername: null,
|
|
260
270
|
codebaseDir: null,
|
|
261
271
|
agentCommand: null,
|
|
262
272
|
agents: null
|
|
@@ -272,9 +282,11 @@ function loadConfig() {
|
|
|
272
282
|
const overrides = validateConfigData(data, envPlatformUrl);
|
|
273
283
|
return {
|
|
274
284
|
platformUrl: envPlatformUrl || (typeof data.platform_url === "string" ? data.platform_url : DEFAULT_PLATFORM_URL),
|
|
285
|
+
apiKey: typeof data.api_key === "string" ? data.api_key.trim() || null : null,
|
|
275
286
|
maxDiffSizeKb: overrides.maxDiffSizeKb ?? (typeof data.max_diff_size_kb === "number" ? data.max_diff_size_kb : DEFAULT_MAX_DIFF_SIZE_KB),
|
|
276
287
|
maxConsecutiveErrors: overrides.maxConsecutiveErrors ?? (typeof data.max_consecutive_errors === "number" ? data.max_consecutive_errors : DEFAULT_MAX_CONSECUTIVE_ERRORS),
|
|
277
288
|
githubToken: typeof data.github_token === "string" ? data.github_token : null,
|
|
289
|
+
githubUsername: typeof data.github_username === "string" ? data.github_username : null,
|
|
278
290
|
codebaseDir: typeof data.codebase_dir === "string" ? data.codebase_dir : null,
|
|
279
291
|
agentCommand: typeof data.agent_command === "string" ? data.agent_command : null,
|
|
280
292
|
agents: parseAgents(data)
|
|
@@ -291,6 +303,22 @@ function resolveCodebaseDir(agentDir, globalDir) {
|
|
|
291
303
|
}
|
|
292
304
|
return path.resolve(raw);
|
|
293
305
|
}
|
|
306
|
+
async function resolveGithubUsername(githubToken, fetchFn = fetch) {
|
|
307
|
+
if (!githubToken) return null;
|
|
308
|
+
try {
|
|
309
|
+
const response = await fetchFn("https://api.github.com/user", {
|
|
310
|
+
headers: {
|
|
311
|
+
Authorization: `Bearer ${githubToken}`,
|
|
312
|
+
Accept: "application/vnd.github+json"
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
if (!response.ok) return null;
|
|
316
|
+
const data = await response.json();
|
|
317
|
+
return typeof data.login === "string" ? data.login : null;
|
|
318
|
+
} catch {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
294
322
|
|
|
295
323
|
// src/codebase.ts
|
|
296
324
|
import { execFileSync } from "child_process";
|
|
@@ -413,18 +441,29 @@ var HttpError = class extends Error {
|
|
|
413
441
|
}
|
|
414
442
|
};
|
|
415
443
|
var ApiClient = class {
|
|
416
|
-
constructor(baseUrl,
|
|
444
|
+
constructor(baseUrl, debugOrOptions) {
|
|
417
445
|
this.baseUrl = baseUrl;
|
|
418
|
-
|
|
446
|
+
if (typeof debugOrOptions === "object" && debugOrOptions !== null) {
|
|
447
|
+
this.debug = debugOrOptions.debug ?? process.env.OPENCARA_DEBUG === "1";
|
|
448
|
+
this.apiKey = debugOrOptions.apiKey ?? null;
|
|
449
|
+
} else {
|
|
450
|
+
this.debug = debugOrOptions ?? process.env.OPENCARA_DEBUG === "1";
|
|
451
|
+
this.apiKey = null;
|
|
452
|
+
}
|
|
419
453
|
}
|
|
420
454
|
debug;
|
|
455
|
+
apiKey;
|
|
421
456
|
log(msg) {
|
|
422
457
|
if (this.debug) console.debug(`[ApiClient] ${msg}`);
|
|
423
458
|
}
|
|
424
459
|
headers() {
|
|
425
|
-
|
|
460
|
+
const h = {
|
|
426
461
|
"Content-Type": "application/json"
|
|
427
462
|
};
|
|
463
|
+
if (this.apiKey) {
|
|
464
|
+
h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
465
|
+
}
|
|
466
|
+
return h;
|
|
428
467
|
}
|
|
429
468
|
async get(path5) {
|
|
430
469
|
this.log(`GET ${path5}`);
|
|
@@ -500,15 +539,15 @@ function sleep(ms, signal) {
|
|
|
500
539
|
resolve2();
|
|
501
540
|
return;
|
|
502
541
|
}
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
);
|
|
542
|
+
const onAbort = () => {
|
|
543
|
+
clearTimeout(timer);
|
|
544
|
+
resolve2();
|
|
545
|
+
};
|
|
546
|
+
const timer = setTimeout(() => {
|
|
547
|
+
signal?.removeEventListener("abort", onAbort);
|
|
548
|
+
resolve2();
|
|
549
|
+
}, ms);
|
|
550
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
512
551
|
});
|
|
513
552
|
}
|
|
514
553
|
|
|
@@ -522,6 +561,7 @@ var ToolTimeoutError = class extends Error {
|
|
|
522
561
|
this.name = "ToolTimeoutError";
|
|
523
562
|
}
|
|
524
563
|
};
|
|
564
|
+
var SIGKILL_GRACE_MS = 5e3;
|
|
525
565
|
var MIN_PARTIAL_RESULT_LENGTH = 50;
|
|
526
566
|
var MAX_STDERR_LENGTH = 1e3;
|
|
527
567
|
function validateCommandBinary(commandTemplate) {
|
|
@@ -621,9 +661,17 @@ function executeTool(commandTemplate, prompt, timeoutMs, signal, vars, cwd) {
|
|
|
621
661
|
let stdout = "";
|
|
622
662
|
let stderr = "";
|
|
623
663
|
let settled = false;
|
|
624
|
-
|
|
664
|
+
let sigkillTimer;
|
|
665
|
+
function scheduleKillEscalation() {
|
|
625
666
|
child.kill("SIGTERM");
|
|
626
|
-
|
|
667
|
+
if (sigkillTimer) clearTimeout(sigkillTimer);
|
|
668
|
+
sigkillTimer = setTimeout(() => {
|
|
669
|
+
if (!settled) {
|
|
670
|
+
child.kill("SIGKILL");
|
|
671
|
+
}
|
|
672
|
+
}, SIGKILL_GRACE_MS);
|
|
673
|
+
}
|
|
674
|
+
const timer = setTimeout(scheduleKillEscalation, timeoutMs);
|
|
627
675
|
child.stdout?.on("data", (chunk) => {
|
|
628
676
|
stdout += chunk.toString();
|
|
629
677
|
});
|
|
@@ -636,13 +684,12 @@ function executeTool(commandTemplate, prompt, timeoutMs, signal, vars, cwd) {
|
|
|
636
684
|
child.stdin?.end();
|
|
637
685
|
let onAbort;
|
|
638
686
|
if (signal) {
|
|
639
|
-
onAbort =
|
|
640
|
-
child.kill();
|
|
641
|
-
};
|
|
687
|
+
onAbort = scheduleKillEscalation;
|
|
642
688
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
643
689
|
}
|
|
644
690
|
function cleanup() {
|
|
645
691
|
clearTimeout(timer);
|
|
692
|
+
if (sigkillTimer) clearTimeout(sigkillTimer);
|
|
646
693
|
if (onAbort && signal) {
|
|
647
694
|
signal.removeEventListener("abort", onAbort);
|
|
648
695
|
}
|
|
@@ -1313,6 +1360,11 @@ function toApiDiffUrl(webUrl) {
|
|
|
1313
1360
|
const [, owner, repo, prNumber] = match;
|
|
1314
1361
|
return `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}`;
|
|
1315
1362
|
}
|
|
1363
|
+
function computeRoles(agent) {
|
|
1364
|
+
if (agent.review_only) return ["review"];
|
|
1365
|
+
if (agent.synthesizer_only) return ["summary"];
|
|
1366
|
+
return ["review", "summary"];
|
|
1367
|
+
}
|
|
1316
1368
|
async function fetchDiff(diffUrl, githubToken, signal) {
|
|
1317
1369
|
return withRetry(
|
|
1318
1370
|
async () => {
|
|
@@ -1346,7 +1398,17 @@ async function fetchDiff(diffUrl, githubToken, signal) {
|
|
|
1346
1398
|
}
|
|
1347
1399
|
var MAX_DIFF_FETCH_ATTEMPTS = 3;
|
|
1348
1400
|
async function pollLoop(client, agentId, reviewDeps, consumptionDeps, agentInfo, logger, agentSession, options) {
|
|
1349
|
-
const {
|
|
1401
|
+
const {
|
|
1402
|
+
pollIntervalMs,
|
|
1403
|
+
maxConsecutiveErrors,
|
|
1404
|
+
routerRelay,
|
|
1405
|
+
reviewOnly,
|
|
1406
|
+
repoConfig,
|
|
1407
|
+
roles,
|
|
1408
|
+
synthesizeRepos,
|
|
1409
|
+
githubUsername,
|
|
1410
|
+
signal
|
|
1411
|
+
} = options;
|
|
1350
1412
|
const { log, logError, logWarn } = logger;
|
|
1351
1413
|
log(`${icons.polling} Polling every ${pollIntervalMs / 1e3}s...`);
|
|
1352
1414
|
let consecutiveAuthErrors = 0;
|
|
@@ -1355,10 +1417,15 @@ async function pollLoop(client, agentId, reviewDeps, consumptionDeps, agentInfo,
|
|
|
1355
1417
|
while (!signal?.aborted) {
|
|
1356
1418
|
try {
|
|
1357
1419
|
const pollBody = { agent_id: agentId };
|
|
1420
|
+
if (githubUsername) pollBody.github_username = githubUsername;
|
|
1421
|
+
if (roles) pollBody.roles = roles;
|
|
1358
1422
|
if (reviewOnly) pollBody.review_only = true;
|
|
1359
1423
|
if (repoConfig?.list?.length) {
|
|
1360
1424
|
pollBody.repos = repoConfig.list;
|
|
1361
1425
|
}
|
|
1426
|
+
if (synthesizeRepos) pollBody.synthesize_repos = synthesizeRepos;
|
|
1427
|
+
if (agentInfo.model) pollBody.model = agentInfo.model;
|
|
1428
|
+
if (agentInfo.tool) pollBody.tool = agentInfo.tool;
|
|
1362
1429
|
const pollResponse = await client.post("/api/tasks/poll", pollBody);
|
|
1363
1430
|
consecutiveAuthErrors = 0;
|
|
1364
1431
|
consecutiveErrors = 0;
|
|
@@ -1377,7 +1444,8 @@ async function pollLoop(client, agentId, reviewDeps, consumptionDeps, agentInfo,
|
|
|
1377
1444
|
logger,
|
|
1378
1445
|
agentSession,
|
|
1379
1446
|
routerRelay,
|
|
1380
|
-
signal
|
|
1447
|
+
signal,
|
|
1448
|
+
githubUsername
|
|
1381
1449
|
);
|
|
1382
1450
|
if (result.diffFetchFailed) {
|
|
1383
1451
|
agentSession.errorsEncountered++;
|
|
@@ -1430,20 +1498,22 @@ async function pollLoop(client, agentId, reviewDeps, consumptionDeps, agentInfo,
|
|
|
1430
1498
|
await sleep2(pollIntervalMs, signal);
|
|
1431
1499
|
}
|
|
1432
1500
|
}
|
|
1433
|
-
async function handleTask(client, agentId, task, reviewDeps, consumptionDeps, agentInfo, logger, agentSession, routerRelay, signal) {
|
|
1501
|
+
async function handleTask(client, agentId, task, reviewDeps, consumptionDeps, agentInfo, logger, agentSession, routerRelay, signal, githubUsername) {
|
|
1434
1502
|
const { task_id, owner, repo, pr_number, diff_url, timeout_seconds, prompt, role } = task;
|
|
1435
1503
|
const { log, logError, logWarn } = logger;
|
|
1436
1504
|
log(`${icons.success} Claimed task ${task_id} (${role}) \u2014 ${owner}/${repo}#${pr_number}`);
|
|
1437
1505
|
log(` https://github.com/${owner}/${repo}/pull/${pr_number}`);
|
|
1438
1506
|
let claimResponse;
|
|
1439
1507
|
try {
|
|
1508
|
+
const claimBody = {
|
|
1509
|
+
agent_id: agentId,
|
|
1510
|
+
role,
|
|
1511
|
+
model: agentInfo.model,
|
|
1512
|
+
tool: agentInfo.tool
|
|
1513
|
+
};
|
|
1514
|
+
if (githubUsername) claimBody.github_username = githubUsername;
|
|
1440
1515
|
claimResponse = await withRetry(
|
|
1441
|
-
() => client.post(`/api/tasks/${task_id}/claim`,
|
|
1442
|
-
agent_id: agentId,
|
|
1443
|
-
role,
|
|
1444
|
-
model: agentInfo.model,
|
|
1445
|
-
tool: agentInfo.tool
|
|
1446
|
-
}),
|
|
1516
|
+
() => client.post(`/api/tasks/${task_id}/claim`, claimBody),
|
|
1447
1517
|
{ maxAttempts: 2 },
|
|
1448
1518
|
signal
|
|
1449
1519
|
);
|
|
@@ -1800,19 +1870,19 @@ function sleep2(ms, signal) {
|
|
|
1800
1870
|
resolve2();
|
|
1801
1871
|
return;
|
|
1802
1872
|
}
|
|
1803
|
-
const
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
);
|
|
1873
|
+
const onAbort = () => {
|
|
1874
|
+
clearTimeout(timer);
|
|
1875
|
+
resolve2();
|
|
1876
|
+
};
|
|
1877
|
+
const timer = setTimeout(() => {
|
|
1878
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1879
|
+
resolve2();
|
|
1880
|
+
}, ms);
|
|
1881
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1812
1882
|
});
|
|
1813
1883
|
}
|
|
1814
1884
|
async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
|
|
1815
|
-
const client = new ApiClient(platformUrl);
|
|
1885
|
+
const client = new ApiClient(platformUrl, { apiKey: options?.apiKey });
|
|
1816
1886
|
const session = consumptionDeps?.session ?? createSessionTracker();
|
|
1817
1887
|
const deps = consumptionDeps ?? { agentId, session };
|
|
1818
1888
|
const logger = createLogger(options?.label);
|
|
@@ -1846,6 +1916,9 @@ async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumpti
|
|
|
1846
1916
|
routerRelay: options?.routerRelay,
|
|
1847
1917
|
reviewOnly: options?.reviewOnly,
|
|
1848
1918
|
repoConfig: options?.repoConfig,
|
|
1919
|
+
roles: options?.roles,
|
|
1920
|
+
synthesizeRepos: options?.synthesizeRepos,
|
|
1921
|
+
githubUsername: options?.githubUsername,
|
|
1849
1922
|
signal: abortController.signal
|
|
1850
1923
|
});
|
|
1851
1924
|
log(formatExitSummary(agentSession));
|
|
@@ -1867,6 +1940,10 @@ async function startAgentRouter() {
|
|
|
1867
1940
|
const auth = resolveGithubToken2(configToken);
|
|
1868
1941
|
const logger = createLogger(agentConfig?.name ?? "agent[0]");
|
|
1869
1942
|
logAuthMethod(auth.method, logger.log);
|
|
1943
|
+
const githubUsername = config.githubUsername ?? await resolveGithubUsername(auth.token) ?? void 0;
|
|
1944
|
+
if (githubUsername) {
|
|
1945
|
+
logger.log(`GitHub identity: ${githubUsername}`);
|
|
1946
|
+
}
|
|
1870
1947
|
const codebaseDir = resolveCodebaseDir(agentConfig?.codebase_dir, config.codebaseDir);
|
|
1871
1948
|
const reviewDeps = {
|
|
1872
1949
|
commandTemplate: commandTemplate ?? "",
|
|
@@ -1878,6 +1955,7 @@ async function startAgentRouter() {
|
|
|
1878
1955
|
const model = agentConfig?.model ?? "unknown";
|
|
1879
1956
|
const tool = agentConfig?.tool ?? "unknown";
|
|
1880
1957
|
const label = agentConfig?.name ?? "agent[0]";
|
|
1958
|
+
const roles = agentConfig ? computeRoles(agentConfig) : void 0;
|
|
1881
1959
|
await startAgent(
|
|
1882
1960
|
agentId,
|
|
1883
1961
|
config.platformUrl,
|
|
@@ -1892,12 +1970,16 @@ async function startAgentRouter() {
|
|
|
1892
1970
|
routerRelay: router,
|
|
1893
1971
|
reviewOnly: agentConfig?.review_only,
|
|
1894
1972
|
repoConfig: agentConfig?.repos,
|
|
1895
|
-
|
|
1973
|
+
roles,
|
|
1974
|
+
synthesizeRepos: agentConfig?.synthesize_repos,
|
|
1975
|
+
githubUsername,
|
|
1976
|
+
label,
|
|
1977
|
+
apiKey: config.apiKey
|
|
1896
1978
|
}
|
|
1897
1979
|
);
|
|
1898
1980
|
router.stop();
|
|
1899
1981
|
}
|
|
1900
|
-
function startAgentByIndex(config, agentIndex, pollIntervalMs, auth) {
|
|
1982
|
+
function startAgentByIndex(config, agentIndex, pollIntervalMs, auth, githubUsername) {
|
|
1901
1983
|
const agentId = crypto.randomUUID();
|
|
1902
1984
|
let commandTemplate;
|
|
1903
1985
|
let agentConfig;
|
|
@@ -1941,6 +2023,7 @@ function startAgentByIndex(config, agentIndex, pollIntervalMs, auth) {
|
|
|
1941
2023
|
const session = createSessionTracker();
|
|
1942
2024
|
const model = agentConfig?.model ?? "unknown";
|
|
1943
2025
|
const tool = agentConfig?.tool ?? "unknown";
|
|
2026
|
+
const roles = agentConfig ? computeRoles(agentConfig) : void 0;
|
|
1944
2027
|
const agentPromise = startAgent(
|
|
1945
2028
|
agentId,
|
|
1946
2029
|
config.platformUrl,
|
|
@@ -1953,7 +2036,11 @@ function startAgentByIndex(config, agentIndex, pollIntervalMs, auth) {
|
|
|
1953
2036
|
routerRelay,
|
|
1954
2037
|
reviewOnly: agentConfig?.review_only,
|
|
1955
2038
|
repoConfig: agentConfig?.repos,
|
|
1956
|
-
|
|
2039
|
+
roles,
|
|
2040
|
+
synthesizeRepos: agentConfig?.synthesize_repos,
|
|
2041
|
+
githubUsername,
|
|
2042
|
+
label,
|
|
2043
|
+
apiKey: config.apiKey
|
|
1957
2044
|
}
|
|
1958
2045
|
).finally(() => {
|
|
1959
2046
|
routerRelay?.stop();
|
|
@@ -1967,6 +2054,10 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
1967
2054
|
const configToken = resolveGithubToken(void 0, config.githubToken);
|
|
1968
2055
|
const auth = resolveGithubToken2(configToken);
|
|
1969
2056
|
logAuthMethod(auth.method, console.log.bind(console));
|
|
2057
|
+
const githubUsername = config.githubUsername ?? await resolveGithubUsername(auth.token) ?? void 0;
|
|
2058
|
+
if (githubUsername) {
|
|
2059
|
+
console.log(`GitHub identity: ${githubUsername}`);
|
|
2060
|
+
}
|
|
1970
2061
|
if (opts.all) {
|
|
1971
2062
|
if (!config.agents || config.agents.length === 0) {
|
|
1972
2063
|
console.error("No agents configured in ~/.opencara/config.yml");
|
|
@@ -1977,7 +2068,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
1977
2068
|
const promises = [];
|
|
1978
2069
|
let startFailed = false;
|
|
1979
2070
|
for (let i = 0; i < config.agents.length; i++) {
|
|
1980
|
-
const p = startAgentByIndex(config, i, pollIntervalMs, auth);
|
|
2071
|
+
const p = startAgentByIndex(config, i, pollIntervalMs, auth, githubUsername);
|
|
1981
2072
|
if (p) {
|
|
1982
2073
|
promises.push(p);
|
|
1983
2074
|
} else {
|
|
@@ -2014,7 +2105,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
2014
2105
|
process.exit(1);
|
|
2015
2106
|
return;
|
|
2016
2107
|
}
|
|
2017
|
-
const p = startAgentByIndex(config, agentIndex, pollIntervalMs, auth);
|
|
2108
|
+
const p = startAgentByIndex(config, agentIndex, pollIntervalMs, auth, githubUsername);
|
|
2018
2109
|
if (!p) {
|
|
2019
2110
|
process.exit(1);
|
|
2020
2111
|
return;
|
|
@@ -2024,7 +2115,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
2024
2115
|
});
|
|
2025
2116
|
|
|
2026
2117
|
// src/index.ts
|
|
2027
|
-
var program = new Command2().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.
|
|
2118
|
+
var program = new Command2().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.14.0");
|
|
2028
2119
|
program.addCommand(agentCommand);
|
|
2029
2120
|
program.action(() => {
|
|
2030
2121
|
startAgentRouter();
|