opencara 0.18.6 → 0.18.7

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.
Files changed (2) hide show
  1. package/dist/index.js +65 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -987,6 +987,7 @@ import * as fs5 from "fs";
987
987
  import * as path5 from "path";
988
988
  import * as os2 from "os";
989
989
  import * as crypto from "crypto";
990
+ import { execFileSync as execFileSync3 } from "child_process";
990
991
  var AUTH_DIR = path5.join(os2.homedir(), ".opencara");
991
992
  function getAuthFilePath() {
992
993
  const envPath = process.env.OPENCARA_AUTH_FILE?.trim();
@@ -1198,7 +1199,9 @@ async function resolveUser(token, fetchFn = fetch) {
1198
1199
  }
1199
1200
  return { login: data.login, id: data.id };
1200
1201
  }
1201
- async function fetchUserOrgs(token, fetchFn = fetch) {
1202
+ async function fetchUserOrgs(token, fetchFn = fetch, expectedLogin) {
1203
+ const ghOrgs = fetchUserOrgsViaGh(expectedLogin);
1204
+ if (ghOrgs.size > 0) return ghOrgs;
1202
1205
  try {
1203
1206
  const res = await fetchFn("https://api.github.com/user/orgs?per_page=100", {
1204
1207
  headers: {
@@ -1222,6 +1225,33 @@ async function fetchUserOrgs(token, fetchFn = fetch) {
1222
1225
  return /* @__PURE__ */ new Set();
1223
1226
  }
1224
1227
  }
1228
+ function fetchUserOrgsViaGh(expectedLogin) {
1229
+ try {
1230
+ if (expectedLogin) {
1231
+ const ghUser = execFileSync3("gh", ["api", "/user", "--jq", ".login"], {
1232
+ encoding: "utf-8",
1233
+ timeout: 1e4,
1234
+ stdio: ["ignore", "pipe", "pipe"]
1235
+ }).trim();
1236
+ if (ghUser.toLowerCase() !== expectedLogin.toLowerCase()) {
1237
+ return /* @__PURE__ */ new Set();
1238
+ }
1239
+ }
1240
+ const output = execFileSync3("gh", ["api", "/user/orgs", "--paginate", "--jq", ".[].login"], {
1241
+ encoding: "utf-8",
1242
+ timeout: 15e3,
1243
+ stdio: ["ignore", "pipe", "pipe"]
1244
+ });
1245
+ const orgs = /* @__PURE__ */ new Set();
1246
+ for (const line of output.trim().split("\n")) {
1247
+ const name = line.trim();
1248
+ if (name) orgs.add(name.toLowerCase());
1249
+ }
1250
+ return orgs;
1251
+ } catch {
1252
+ return /* @__PURE__ */ new Set();
1253
+ }
1254
+ }
1225
1255
 
1226
1256
  // src/http.ts
1227
1257
  var HttpError = class extends Error {
@@ -1429,7 +1459,7 @@ function sleep(ms, signal) {
1429
1459
  }
1430
1460
 
1431
1461
  // src/tool-executor.ts
1432
- import { spawn, execFileSync as execFileSync3 } from "child_process";
1462
+ import { spawn, execFileSync as execFileSync4 } from "child_process";
1433
1463
  import * as fs6 from "fs";
1434
1464
  import * as path6 from "path";
1435
1465
  var ToolTimeoutError = class extends Error {
@@ -1454,9 +1484,9 @@ function validateCommandBinary(commandTemplate) {
1454
1484
  try {
1455
1485
  const isWindows = process.platform === "win32";
1456
1486
  if (isWindows) {
1457
- execFileSync3("where", [command], { stdio: "pipe" });
1487
+ execFileSync4("where", [command], { stdio: "pipe" });
1458
1488
  } else {
1459
- execFileSync3("sh", ["-c", 'command -v -- "$1"', "_", command], { stdio: "pipe" });
1489
+ execFileSync4("sh", ["-c", 'command -v -- "$1"', "_", command], { stdio: "pipe" });
1460
1490
  }
1461
1491
  return true;
1462
1492
  } catch {
@@ -3941,7 +3971,7 @@ function sleep2(ms, signal) {
3941
3971
  async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
3942
3972
  const client = new ApiClient(platformUrl, {
3943
3973
  authToken: options?.authToken,
3944
- cliVersion: "0.18.6",
3974
+ cliVersion: "0.18.7",
3945
3975
  versionOverride: options?.versionOverride,
3946
3976
  onTokenRefresh: options?.onTokenRefresh
3947
3977
  });
@@ -4212,7 +4242,35 @@ agentCommand.command("start").description("Start agents in polling mode").option
4212
4242
  console.log(`Authenticated as ${storedAuth.github_username}`);
4213
4243
  }
4214
4244
  const needsOrgs = config.agents?.some((a) => a.repos?.mode === "private") ?? false;
4215
- const userOrgs = needsOrgs ? await fetchUserOrgs(oauthToken) : /* @__PURE__ */ new Set();
4245
+ let userOrgs = needsOrgs ? await fetchUserOrgs(oauthToken, fetch, agentOwner) : /* @__PURE__ */ new Set();
4246
+ if (needsOrgs && userOrgs.size === 0 && config.agents) {
4247
+ const currentLogin = agentOwner?.toLowerCase();
4248
+ const fallbackOrgs = /* @__PURE__ */ new Set();
4249
+ for (const a of config.agents) {
4250
+ if (a.repos?.list) {
4251
+ for (const repo of a.repos.list) {
4252
+ const owner = repo.split("/")[0]?.toLowerCase();
4253
+ if (owner && owner !== currentLogin) fallbackOrgs.add(owner);
4254
+ }
4255
+ }
4256
+ if (a.synthesize_repos?.list) {
4257
+ for (const repo of a.synthesize_repos.list) {
4258
+ const owner = repo.split("/")[0]?.toLowerCase();
4259
+ if (owner && owner !== currentLogin) fallbackOrgs.add(owner);
4260
+ }
4261
+ }
4262
+ }
4263
+ if (fallbackOrgs.size > 0) {
4264
+ userOrgs = fallbackOrgs;
4265
+ console.log(`Org memberships (from config): ${[...userOrgs].join(", ")}`);
4266
+ } else {
4267
+ console.warn(
4268
+ "\u26A0 Failed to fetch org memberships \u2014 private mode agents may not see org repos"
4269
+ );
4270
+ }
4271
+ } else if (needsOrgs && userOrgs.size > 0) {
4272
+ console.log(`Org memberships: ${[...userOrgs].join(", ")}`);
4273
+ }
4216
4274
  if (opts.all) {
4217
4275
  if (!config.agents || config.agents.length === 0) {
4218
4276
  console.error("No agents configured in ~/.opencara/config.toml");
@@ -4995,7 +5053,7 @@ var statusCommand = new Command4("status").description("Show agent config, conne
4995
5053
  });
4996
5054
 
4997
5055
  // src/index.ts
4998
- var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.18.6");
5056
+ var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.18.7");
4999
5057
  program.addCommand(agentCommand);
5000
5058
  program.addCommand(authCommand());
5001
5059
  program.addCommand(dedupCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencara",
3
- "version": "0.18.6",
3
+ "version": "0.18.7",
4
4
  "description": "Distributed AI code review agent — poll, review, and submit PR reviews using your own AI tools",
5
5
  "type": "module",
6
6
  "license": "MIT",