opencara 0.24.3 → 0.25.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 +84 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1880,18 +1880,71 @@ function gitExec(command, args, cwd, opts) {
|
|
|
1880
1880
|
throw new Error(sanitizeTokens(message));
|
|
1881
1881
|
}
|
|
1882
1882
|
}
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1883
|
+
var DEFAULT_BRANCH_FALLBACKS = ["main", "master"];
|
|
1884
|
+
function isValidBranchName(name) {
|
|
1885
|
+
if (!name) return false;
|
|
1886
|
+
if (name.startsWith("-")) return false;
|
|
1887
|
+
if (name.includes("..")) return false;
|
|
1888
|
+
return /^[A-Za-z0-9_./-]+$/.test(name);
|
|
1889
|
+
}
|
|
1890
|
+
function fetchBranch(bareRepoPath, branch, ghAvailable) {
|
|
1887
1891
|
const credArgs = ghAvailable ? ["-c", `credential.helper=${GH_CREDENTIAL_HELPER}`] : [];
|
|
1888
1892
|
gitExec(
|
|
1889
1893
|
"git",
|
|
1890
|
-
[...credArgs, "fetch", "--force", "origin", `${
|
|
1894
|
+
[...credArgs, "fetch", "--force", "origin", `${branch}:refs/remotes/origin/${branch}`],
|
|
1891
1895
|
bareRepoPath
|
|
1892
1896
|
);
|
|
1897
|
+
}
|
|
1898
|
+
function isRemoteRefMissingError(err) {
|
|
1899
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1900
|
+
return /couldn't find remote ref/i.test(msg) || /couldnt find remote ref/i.test(msg) || /no such ref/i.test(msg) || /remote ref.*not found/i.test(msg) || /unknown revision or path not in the working tree/i.test(msg);
|
|
1901
|
+
}
|
|
1902
|
+
function deriveDefaultBranch(bareRepoPath, ghAvailable) {
|
|
1903
|
+
try {
|
|
1904
|
+
const out = gitExec("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], bareRepoPath).trim();
|
|
1905
|
+
const prefix = "refs/remotes/origin/";
|
|
1906
|
+
if (out.startsWith(prefix)) {
|
|
1907
|
+
const branch = out.slice(prefix.length);
|
|
1908
|
+
if (isValidBranchName(branch)) {
|
|
1909
|
+
try {
|
|
1910
|
+
fetchBranch(bareRepoPath, branch, ghAvailable);
|
|
1911
|
+
return branch;
|
|
1912
|
+
} catch {
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
} catch {
|
|
1917
|
+
}
|
|
1918
|
+
for (const candidate of DEFAULT_BRANCH_FALLBACKS) {
|
|
1919
|
+
try {
|
|
1920
|
+
fetchBranch(bareRepoPath, candidate, ghAvailable);
|
|
1921
|
+
return candidate;
|
|
1922
|
+
} catch {
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
throw new Error("Cannot derive default branch: origin/HEAD, main, and master all failed");
|
|
1926
|
+
}
|
|
1927
|
+
function diffFromWorktree(bareRepoPath, worktreePath, baseRef, ghAvailable, maxDiffBytes = 128 * 1024 * 1024) {
|
|
1928
|
+
let resolvedBaseRef;
|
|
1929
|
+
if (baseRef) {
|
|
1930
|
+
if (!isValidBranchName(baseRef)) {
|
|
1931
|
+
throw new Error(`Invalid base ref: ${baseRef}`);
|
|
1932
|
+
}
|
|
1933
|
+
try {
|
|
1934
|
+
fetchBranch(bareRepoPath, baseRef, ghAvailable);
|
|
1935
|
+
resolvedBaseRef = baseRef;
|
|
1936
|
+
} catch (err) {
|
|
1937
|
+
if (!isRemoteRefMissingError(err)) {
|
|
1938
|
+
throw err;
|
|
1939
|
+
}
|
|
1940
|
+
resolvedBaseRef = void 0;
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
if (!resolvedBaseRef) {
|
|
1944
|
+
resolvedBaseRef = deriveDefaultBranch(bareRepoPath, ghAvailable);
|
|
1945
|
+
}
|
|
1893
1946
|
try {
|
|
1894
|
-
return gitExec("git", ["diff", `origin/${
|
|
1947
|
+
return gitExec("git", ["diff", `origin/${resolvedBaseRef}...HEAD`], worktreePath, {
|
|
1895
1948
|
maxBuffer: maxDiffBytes
|
|
1896
1949
|
});
|
|
1897
1950
|
} catch (err) {
|
|
@@ -4687,6 +4740,12 @@ function registerShutdownHandlers(controller, log, graceMs = SHUTDOWN_GRACE_MS)
|
|
|
4687
4740
|
};
|
|
4688
4741
|
}
|
|
4689
4742
|
var NON_RETRYABLE_STATUSES = /* @__PURE__ */ new Set([401, 403, 404]);
|
|
4743
|
+
function build404Hint(isGhAuthenticated) {
|
|
4744
|
+
if (isGhAuthenticated) {
|
|
4745
|
+
return ". Diff fetch returned 404. Possible causes: (a) PR not found, (b) the installation can't access this repo, or (c) a transient GitHub outage. See any `[fetchDiffViaGh]` warning above for the underlying `gh api` error.";
|
|
4746
|
+
}
|
|
4747
|
+
return ". If this is a private repo, ensure gh CLI is installed and authenticated: gh auth login";
|
|
4748
|
+
}
|
|
4690
4749
|
function toApiDiffUrl(webUrl) {
|
|
4691
4750
|
const match = webUrl.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)(?:\.diff)?$/);
|
|
4692
4751
|
if (!match) return null;
|
|
@@ -4748,7 +4807,7 @@ function computeRoles(agent) {
|
|
|
4748
4807
|
return ["review", "summary", "implement", "fix"];
|
|
4749
4808
|
}
|
|
4750
4809
|
var DIFF_FETCH_TIMEOUT_MS = 6e4;
|
|
4751
|
-
async function fetchDiffHttp(url, headers, signal, maxDiffSizeKb) {
|
|
4810
|
+
async function fetchDiffHttp(url, headers, signal, maxDiffSizeKb, isGhAuthenticatedFn = isGhAvailable) {
|
|
4752
4811
|
const maxBytes = maxDiffSizeKb ? maxDiffSizeKb * 1024 : Infinity;
|
|
4753
4812
|
const controller = new AbortController();
|
|
4754
4813
|
const timer = setTimeout(() => controller.abort(), DIFF_FETCH_TIMEOUT_MS);
|
|
@@ -4769,7 +4828,7 @@ async function fetchDiffHttp(url, headers, signal, maxDiffSizeKb) {
|
|
|
4769
4828
|
clearTimeout(timer);
|
|
4770
4829
|
signal?.removeEventListener("abort", onParentAbort);
|
|
4771
4830
|
if (!response.ok) {
|
|
4772
|
-
const hint = response.status === 404 ?
|
|
4831
|
+
const hint = response.status === 404 ? build404Hint(isGhAuthenticatedFn()) : "";
|
|
4773
4832
|
const msg = `Failed to fetch diff: ${response.status} ${response.statusText}${hint}`;
|
|
4774
4833
|
if (NON_RETRYABLE_STATUSES.has(response.status)) {
|
|
4775
4834
|
throw new NonRetryableError(msg);
|
|
@@ -5054,7 +5113,12 @@ async function handleTask(client, agentId, task, reviewDeps, consumptionDeps, ag
|
|
|
5054
5113
|
);
|
|
5055
5114
|
taskReviewDeps = { ...reviewDeps, codebaseDir: null };
|
|
5056
5115
|
}
|
|
5057
|
-
if (taskCheckoutPath && taskBareRepoPath
|
|
5116
|
+
if (taskCheckoutPath && taskBareRepoPath) {
|
|
5117
|
+
if (!base_ref) {
|
|
5118
|
+
logWarn(
|
|
5119
|
+
` Warning: task ${task_id} has no base_ref \u2014 deriving default branch from worktree`
|
|
5120
|
+
);
|
|
5121
|
+
}
|
|
5058
5122
|
try {
|
|
5059
5123
|
const ghAvailable = isGhAvailable();
|
|
5060
5124
|
const maxDiffBytes = reviewDeps.maxDiffSizeKb ? reviewDeps.maxDiffSizeKb * 1024 : void 0;
|
|
@@ -5077,23 +5141,16 @@ async function handleTask(client, agentId, task, reviewDeps, consumptionDeps, ag
|
|
|
5077
5141
|
diffContent = gitDiff;
|
|
5078
5142
|
log(` Diff generated via git (${Math.round(diffContent.length / 1024)}KB)`);
|
|
5079
5143
|
} catch (err) {
|
|
5144
|
+
const message = err.message;
|
|
5080
5145
|
if (err instanceof DiffTooLargeError) {
|
|
5081
|
-
logError(` ${
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
task_id,
|
|
5085
|
-
agentId,
|
|
5086
|
-
`Cannot access diff: ${err.message}`,
|
|
5087
|
-
logger
|
|
5088
|
-
);
|
|
5089
|
-
return { diffFetchFailed: true };
|
|
5146
|
+
logError(` ${message}`);
|
|
5147
|
+
} else {
|
|
5148
|
+
logError(` git diff failed for task ${task_id}: ${message}`);
|
|
5090
5149
|
}
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
);
|
|
5150
|
+
await safeReject(client, task_id, agentId, `Cannot access diff: ${message}`, logger);
|
|
5151
|
+
return { diffFetchFailed: true };
|
|
5094
5152
|
}
|
|
5095
|
-
}
|
|
5096
|
-
if (!diffContent) {
|
|
5153
|
+
} else {
|
|
5097
5154
|
try {
|
|
5098
5155
|
const result = await fetchDiff(diff_url, owner, repo, pr_number, {
|
|
5099
5156
|
githubToken: client.currentToken,
|
|
@@ -5736,7 +5793,7 @@ function sleep2(ms, signal) {
|
|
|
5736
5793
|
async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
|
|
5737
5794
|
const client = new ApiClient(platformUrl, {
|
|
5738
5795
|
authToken: options?.authToken,
|
|
5739
|
-
cliVersion: "0.
|
|
5796
|
+
cliVersion: "0.25.0",
|
|
5740
5797
|
versionOverride: options?.versionOverride,
|
|
5741
5798
|
onTokenRefresh: options?.onTokenRefresh
|
|
5742
5799
|
});
|
|
@@ -6101,7 +6158,7 @@ async function startBatchAgents(config, agents, pollIntervalMs, oauthToken, opti
|
|
|
6101
6158
|
const { versionOverride, verbose, instancesOverride, agentOwner, userOrgs } = options;
|
|
6102
6159
|
const client = new ApiClient(config.platformUrl, {
|
|
6103
6160
|
authToken: oauthToken,
|
|
6104
|
-
cliVersion: "0.
|
|
6161
|
+
cliVersion: "0.25.0",
|
|
6105
6162
|
versionOverride,
|
|
6106
6163
|
onTokenRefresh: () => getValidToken(config.platformUrl, { configPath: config.authFile })
|
|
6107
6164
|
});
|
|
@@ -6450,7 +6507,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
6450
6507
|
}
|
|
6451
6508
|
config = loadConfig();
|
|
6452
6509
|
}
|
|
6453
|
-
console.log(formatVersionBanner("0.
|
|
6510
|
+
console.log(formatVersionBanner("0.25.0", "a984ae2"));
|
|
6454
6511
|
if (config.agents && config.agents.length > 0) {
|
|
6455
6512
|
const toolEntries = config.agents.map((a) => ({
|
|
6456
6513
|
tool: a.tool,
|
|
@@ -7272,7 +7329,7 @@ var statusCommand = new Command4("status").description("Show agent config, conne
|
|
|
7272
7329
|
});
|
|
7273
7330
|
|
|
7274
7331
|
// src/index.ts
|
|
7275
|
-
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.
|
|
7332
|
+
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.25.0"} (${"a984ae2"})`);
|
|
7276
7333
|
program.addCommand(agentCommand);
|
|
7277
7334
|
program.addCommand(authCommand());
|
|
7278
7335
|
program.addCommand(dedupCommand());
|