opencara 0.18.5 → 0.18.6
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 +66 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16,15 +16,24 @@ function isDedupRole(role) {
|
|
|
16
16
|
function isTriageRole(role) {
|
|
17
17
|
return role === "pr_triage" || role === "issue_triage";
|
|
18
18
|
}
|
|
19
|
-
function isRepoAllowed(repoConfig, targetOwner, targetRepo, agentOwner) {
|
|
19
|
+
function isRepoAllowed(repoConfig, targetOwner, targetRepo, agentOwner, userOrgs) {
|
|
20
20
|
if (!repoConfig)
|
|
21
21
|
return true;
|
|
22
22
|
const fullRepo = `${targetOwner}/${targetRepo}`;
|
|
23
23
|
switch (repoConfig.mode) {
|
|
24
24
|
case "public":
|
|
25
25
|
return true;
|
|
26
|
-
case "private":
|
|
27
|
-
|
|
26
|
+
case "private": {
|
|
27
|
+
const normalizedTarget = targetOwner.toLowerCase();
|
|
28
|
+
const normalizedOwner = agentOwner?.toLowerCase();
|
|
29
|
+
const hasAccess = normalizedOwner === normalizedTarget || userOrgs != null && userOrgs.has(normalizedTarget);
|
|
30
|
+
if (!hasAccess)
|
|
31
|
+
return false;
|
|
32
|
+
if (repoConfig.list && repoConfig.list.length > 0) {
|
|
33
|
+
return repoConfig.list.includes(fullRepo);
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
28
37
|
case "whitelist":
|
|
29
38
|
return (repoConfig.list ?? []).includes(fullRepo);
|
|
30
39
|
case "blacklist":
|
|
@@ -1189,6 +1198,30 @@ async function resolveUser(token, fetchFn = fetch) {
|
|
|
1189
1198
|
}
|
|
1190
1199
|
return { login: data.login, id: data.id };
|
|
1191
1200
|
}
|
|
1201
|
+
async function fetchUserOrgs(token, fetchFn = fetch) {
|
|
1202
|
+
try {
|
|
1203
|
+
const res = await fetchFn("https://api.github.com/user/orgs?per_page=100", {
|
|
1204
|
+
headers: {
|
|
1205
|
+
Authorization: `Bearer ${token}`,
|
|
1206
|
+
Accept: "application/vnd.github+json",
|
|
1207
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
if (!res.ok) {
|
|
1211
|
+
return /* @__PURE__ */ new Set();
|
|
1212
|
+
}
|
|
1213
|
+
const data = await res.json();
|
|
1214
|
+
const orgs = /* @__PURE__ */ new Set();
|
|
1215
|
+
for (const org of data) {
|
|
1216
|
+
if (typeof org.login === "string") {
|
|
1217
|
+
orgs.add(org.login.toLowerCase());
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
return orgs;
|
|
1221
|
+
} catch {
|
|
1222
|
+
return /* @__PURE__ */ new Set();
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1192
1225
|
|
|
1193
1226
|
// src/http.ts
|
|
1194
1227
|
var HttpError = class extends Error {
|
|
@@ -3207,7 +3240,9 @@ async function pollLoop(client, agentId, reviewDeps, consumptionDeps, agentInfo,
|
|
|
3207
3240
|
synthesizeRepos,
|
|
3208
3241
|
signal,
|
|
3209
3242
|
cleanupTracker,
|
|
3210
|
-
verbose
|
|
3243
|
+
verbose,
|
|
3244
|
+
agentOwner,
|
|
3245
|
+
userOrgs
|
|
3211
3246
|
} = options;
|
|
3212
3247
|
const { log, logError, logWarn } = logger;
|
|
3213
3248
|
log(`${icons.polling} Polling every ${pollIntervalMs / 1e3}s...`);
|
|
@@ -3239,7 +3274,9 @@ async function pollLoop(client, agentId, reviewDeps, consumptionDeps, agentInfo,
|
|
|
3239
3274
|
const pollResponse = await client.post("/api/tasks/poll", pollBody);
|
|
3240
3275
|
consecutiveAuthErrors = 0;
|
|
3241
3276
|
consecutiveErrors = 0;
|
|
3242
|
-
const eligibleTasks = repoConfig ? pollResponse.tasks.filter(
|
|
3277
|
+
const eligibleTasks = repoConfig ? pollResponse.tasks.filter(
|
|
3278
|
+
(t) => isRepoAllowed(repoConfig, t.owner, t.repo, agentOwner, userOrgs)
|
|
3279
|
+
) : pollResponse.tasks;
|
|
3243
3280
|
const task = eligibleTasks.find(
|
|
3244
3281
|
(t) => (diffFailCounts.get(t.task_id) ?? 0) < MAX_DIFF_FETCH_ATTEMPTS
|
|
3245
3282
|
);
|
|
@@ -3904,7 +3941,7 @@ function sleep2(ms, signal) {
|
|
|
3904
3941
|
async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
|
|
3905
3942
|
const client = new ApiClient(platformUrl, {
|
|
3906
3943
|
authToken: options?.authToken,
|
|
3907
|
-
cliVersion: "0.18.
|
|
3944
|
+
cliVersion: "0.18.6",
|
|
3908
3945
|
versionOverride: options?.versionOverride,
|
|
3909
3946
|
onTokenRefresh: options?.onTokenRefresh
|
|
3910
3947
|
});
|
|
@@ -3972,7 +4009,9 @@ async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumpti
|
|
|
3972
4009
|
synthesizeRepos: options?.synthesizeRepos,
|
|
3973
4010
|
signal: abortController.signal,
|
|
3974
4011
|
cleanupTracker,
|
|
3975
|
-
verbose: options?.verbose
|
|
4012
|
+
verbose: options?.verbose,
|
|
4013
|
+
agentOwner: options?.agentOwner,
|
|
4014
|
+
userOrgs: options?.userOrgs
|
|
3976
4015
|
});
|
|
3977
4016
|
if (cleanupTracker && cleanupTracker.size > 0) {
|
|
3978
4017
|
const finalSwept = await cleanupTracker.sweep(cleanupWorktree);
|
|
@@ -4014,9 +4053,12 @@ async function startAgentRouter() {
|
|
|
4014
4053
|
throw err;
|
|
4015
4054
|
}
|
|
4016
4055
|
const storedAuth = loadAuth();
|
|
4056
|
+
const agentOwner = storedAuth?.github_username;
|
|
4017
4057
|
if (storedAuth) {
|
|
4018
4058
|
logger.log(`Authenticated as ${storedAuth.github_username}`);
|
|
4019
4059
|
}
|
|
4060
|
+
const repoConfig = agentConfig?.repos;
|
|
4061
|
+
const userOrgs = repoConfig?.mode === "private" ? await fetchUserOrgs(oauthToken) : /* @__PURE__ */ new Set();
|
|
4020
4062
|
const codebaseDir = resolveCodebaseDir(agentConfig?.codebase_dir, config.codebaseDir);
|
|
4021
4063
|
const reviewDeps = {
|
|
4022
4064
|
commandTemplate: commandTemplate ?? "",
|
|
@@ -4046,12 +4088,14 @@ async function startAgentRouter() {
|
|
|
4046
4088
|
maxConsecutiveErrors: config.maxConsecutiveErrors,
|
|
4047
4089
|
routerRelay: router,
|
|
4048
4090
|
reviewOnly: agentConfig?.review_only,
|
|
4049
|
-
repoConfig
|
|
4091
|
+
repoConfig,
|
|
4050
4092
|
roles,
|
|
4051
4093
|
synthesizeRepos: agentConfig?.synthesize_repos,
|
|
4052
4094
|
label,
|
|
4053
4095
|
authToken: oauthToken,
|
|
4054
4096
|
onTokenRefresh: () => getValidToken(config.platformUrl),
|
|
4097
|
+
agentOwner,
|
|
4098
|
+
userOrgs,
|
|
4055
4099
|
usageLimits: config.usageLimits,
|
|
4056
4100
|
versionOverride,
|
|
4057
4101
|
codebaseTtl: config.codebaseTtl
|
|
@@ -4059,7 +4103,7 @@ async function startAgentRouter() {
|
|
|
4059
4103
|
);
|
|
4060
4104
|
router.stop();
|
|
4061
4105
|
}
|
|
4062
|
-
function startAgentByIndex(config, agentIndex, pollIntervalMs, oauthToken, versionOverride, verbose, instancesOverride) {
|
|
4106
|
+
function startAgentByIndex(config, agentIndex, pollIntervalMs, oauthToken, versionOverride, verbose, instancesOverride, agentOwner, userOrgs) {
|
|
4063
4107
|
let commandTemplate;
|
|
4064
4108
|
let agentConfig;
|
|
4065
4109
|
if (config.agents && config.agents.length > agentIndex) {
|
|
@@ -4122,7 +4166,9 @@ function startAgentByIndex(config, agentIndex, pollIntervalMs, oauthToken, versi
|
|
|
4122
4166
|
usageLimits: config.usageLimits,
|
|
4123
4167
|
versionOverride,
|
|
4124
4168
|
codebaseTtl: config.codebaseTtl,
|
|
4125
|
-
verbose
|
|
4169
|
+
verbose,
|
|
4170
|
+
agentOwner,
|
|
4171
|
+
userOrgs
|
|
4126
4172
|
}
|
|
4127
4173
|
).finally(() => {
|
|
4128
4174
|
routerRelay?.stop();
|
|
@@ -4161,9 +4207,12 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
4161
4207
|
throw err;
|
|
4162
4208
|
}
|
|
4163
4209
|
const storedAuth = loadAuth();
|
|
4210
|
+
const agentOwner = storedAuth?.github_username;
|
|
4164
4211
|
if (storedAuth) {
|
|
4165
4212
|
console.log(`Authenticated as ${storedAuth.github_username}`);
|
|
4166
4213
|
}
|
|
4214
|
+
const needsOrgs = config.agents?.some((a) => a.repos?.mode === "private") ?? false;
|
|
4215
|
+
const userOrgs = needsOrgs ? await fetchUserOrgs(oauthToken) : /* @__PURE__ */ new Set();
|
|
4167
4216
|
if (opts.all) {
|
|
4168
4217
|
if (!config.agents || config.agents.length === 0) {
|
|
4169
4218
|
console.error("No agents configured in ~/.opencara/config.toml");
|
|
@@ -4181,7 +4230,9 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
4181
4230
|
oauthToken,
|
|
4182
4231
|
versionOverride,
|
|
4183
4232
|
opts.verbose,
|
|
4184
|
-
instancesOverride
|
|
4233
|
+
instancesOverride,
|
|
4234
|
+
agentOwner,
|
|
4235
|
+
userOrgs
|
|
4185
4236
|
);
|
|
4186
4237
|
if (agentPromises) {
|
|
4187
4238
|
promises.push(...agentPromises);
|
|
@@ -4226,7 +4277,9 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
4226
4277
|
oauthToken,
|
|
4227
4278
|
versionOverride,
|
|
4228
4279
|
opts.verbose,
|
|
4229
|
-
instancesOverride
|
|
4280
|
+
instancesOverride,
|
|
4281
|
+
agentOwner,
|
|
4282
|
+
userOrgs
|
|
4230
4283
|
);
|
|
4231
4284
|
if (!agentPromises) {
|
|
4232
4285
|
process.exit(1);
|
|
@@ -4942,7 +4995,7 @@ var statusCommand = new Command4("status").description("Show agent config, conne
|
|
|
4942
4995
|
});
|
|
4943
4996
|
|
|
4944
4997
|
// src/index.ts
|
|
4945
|
-
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.18.
|
|
4998
|
+
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.18.6");
|
|
4946
4999
|
program.addCommand(agentCommand);
|
|
4947
5000
|
program.addCommand(authCommand());
|
|
4948
5001
|
program.addCommand(dedupCommand());
|