opencara 0.19.6 → 0.19.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.
- package/dist/index.js +113 -119
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5260,7 +5260,7 @@ function sleep2(ms, signal) {
|
|
|
5260
5260
|
async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
|
|
5261
5261
|
const client = new ApiClient(platformUrl, {
|
|
5262
5262
|
authToken: options?.authToken,
|
|
5263
|
-
cliVersion: "0.19.
|
|
5263
|
+
cliVersion: "0.19.7",
|
|
5264
5264
|
versionOverride: options?.versionOverride,
|
|
5265
5265
|
onTokenRefresh: options?.onTokenRefresh
|
|
5266
5266
|
});
|
|
@@ -5547,7 +5547,7 @@ async function startBatchAgents(config, agents, pollIntervalMs, oauthToken, opti
|
|
|
5547
5547
|
const { versionOverride, verbose, instancesOverride, agentOwner, userOrgs } = options;
|
|
5548
5548
|
const client = new ApiClient(config.platformUrl, {
|
|
5549
5549
|
authToken: oauthToken,
|
|
5550
|
-
cliVersion: "0.19.
|
|
5550
|
+
cliVersion: "0.19.7",
|
|
5551
5551
|
versionOverride,
|
|
5552
5552
|
onTokenRefresh: () => getValidToken(config.platformUrl, { configPath: config.authFile })
|
|
5553
5553
|
});
|
|
@@ -6143,104 +6143,114 @@ function authCommand() {
|
|
|
6143
6143
|
}
|
|
6144
6144
|
|
|
6145
6145
|
// src/commands/dedup.ts
|
|
6146
|
+
import { execFileSync as execFileSync8 } from "child_process";
|
|
6146
6147
|
import { Command as Command3 } from "commander";
|
|
6147
6148
|
import pc3 from "picocolors";
|
|
6148
6149
|
var DEFAULT_RECENT_DAYS = 30;
|
|
6149
|
-
var PER_PAGE = 100;
|
|
6150
6150
|
var OPEN_MARKER = "<!-- opencara-dedup-index:open -->";
|
|
6151
6151
|
var RECENT_MARKER = "<!-- opencara-dedup-index:recent -->";
|
|
6152
6152
|
var ARCHIVED_MARKER = "<!-- opencara-dedup-index:archived -->";
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
}
|
|
6153
|
+
function defaultExecGh(args) {
|
|
6154
|
+
return execFileSync8("gh", args, {
|
|
6155
|
+
encoding: "utf-8",
|
|
6156
|
+
timeout: 3e4,
|
|
6157
|
+
maxBuffer: 50 * 1024 * 1024,
|
|
6158
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
6160
6159
|
});
|
|
6161
|
-
if (res.status === 404) return null;
|
|
6162
|
-
if (!res.ok) throw new Error(`GitHub API error: ${res.status} fetching ${path10}`);
|
|
6163
|
-
return res.text();
|
|
6164
6160
|
}
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6161
|
+
function fetchRepoFile(owner, repo, path10, execGh = defaultExecGh) {
|
|
6162
|
+
try {
|
|
6163
|
+
return execGh([
|
|
6164
|
+
"api",
|
|
6165
|
+
`repos/${owner}/${repo}/contents/${path10}`,
|
|
6166
|
+
"-H",
|
|
6167
|
+
"Accept: application/vnd.github.raw+json"
|
|
6168
|
+
]);
|
|
6169
|
+
} catch (err) {
|
|
6170
|
+
const message = String(err.stderr ?? err);
|
|
6171
|
+
if (message.includes("404") || message.includes("Not Found")) return null;
|
|
6172
|
+
throw new Error(`gh API error fetching ${path10}: ${message}`);
|
|
6173
|
+
}
|
|
6174
|
+
}
|
|
6175
|
+
function fetchAllPRs(owner, repo, execGh = defaultExecGh, log) {
|
|
6176
|
+
const output = execGh([
|
|
6177
|
+
"pr",
|
|
6178
|
+
"list",
|
|
6179
|
+
"--repo",
|
|
6180
|
+
`${owner}/${repo}`,
|
|
6181
|
+
"--state",
|
|
6182
|
+
"all",
|
|
6183
|
+
"--limit",
|
|
6184
|
+
"9999",
|
|
6185
|
+
"--json",
|
|
6186
|
+
"number,title,state,labels,closedAt,mergedAt"
|
|
6187
|
+
]);
|
|
6188
|
+
const raw = JSON.parse(output);
|
|
6189
|
+
const items = raw.map((pr) => ({
|
|
6190
|
+
number: pr.number,
|
|
6191
|
+
title: pr.title,
|
|
6192
|
+
state: pr.state === "MERGED" ? "closed" : pr.state.toLowerCase(),
|
|
6193
|
+
labels: pr.labels,
|
|
6194
|
+
closed_at: pr.closedAt || null,
|
|
6195
|
+
merged_at: pr.mergedAt || null
|
|
6196
|
+
}));
|
|
6197
|
+
if (log) log(` Fetched ${items.length} PRs...`);
|
|
6183
6198
|
return items;
|
|
6184
6199
|
}
|
|
6185
|
-
|
|
6186
|
-
const
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6200
|
+
function fetchAllIssues(owner, repo, execGh = defaultExecGh, log) {
|
|
6201
|
+
const output = execGh([
|
|
6202
|
+
"issue",
|
|
6203
|
+
"list",
|
|
6204
|
+
"--repo",
|
|
6205
|
+
`${owner}/${repo}`,
|
|
6206
|
+
"--state",
|
|
6207
|
+
"all",
|
|
6208
|
+
"--limit",
|
|
6209
|
+
"9999",
|
|
6210
|
+
"--json",
|
|
6211
|
+
"number,title,state,labels,closedAt"
|
|
6212
|
+
]);
|
|
6213
|
+
const raw = JSON.parse(output);
|
|
6214
|
+
const items = raw.map((issue) => ({
|
|
6215
|
+
number: issue.number,
|
|
6216
|
+
title: issue.title,
|
|
6217
|
+
state: issue.state.toLowerCase(),
|
|
6218
|
+
labels: issue.labels,
|
|
6219
|
+
closed_at: issue.closedAt || null
|
|
6220
|
+
}));
|
|
6221
|
+
if (log) log(` Fetched ${items.length} issues...`);
|
|
6204
6222
|
return items;
|
|
6205
6223
|
}
|
|
6206
|
-
|
|
6207
|
-
const
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
headers: {
|
|
6237
|
-
Authorization: `Bearer ${token}`,
|
|
6238
|
-
Accept: "application/vnd.github+json",
|
|
6239
|
-
"Content-Type": "application/json"
|
|
6240
|
-
},
|
|
6241
|
-
body: JSON.stringify({ body })
|
|
6242
|
-
});
|
|
6243
|
-
if (!res.ok) throw new Error(`GitHub API error: ${res.status} updating comment`);
|
|
6224
|
+
function fetchIssueComments2(owner, repo, issueNumber, execGh = defaultExecGh) {
|
|
6225
|
+
const output = execGh([
|
|
6226
|
+
"api",
|
|
6227
|
+
"--paginate",
|
|
6228
|
+
`repos/${owner}/${repo}/issues/${issueNumber}/comments`
|
|
6229
|
+
]);
|
|
6230
|
+
return JSON.parse(output);
|
|
6231
|
+
}
|
|
6232
|
+
function createIssueComment(owner, repo, issueNumber, body, execGh = defaultExecGh) {
|
|
6233
|
+
const output = execGh([
|
|
6234
|
+
"api",
|
|
6235
|
+
`repos/${owner}/${repo}/issues/${issueNumber}/comments`,
|
|
6236
|
+
"-X",
|
|
6237
|
+
"POST",
|
|
6238
|
+
"-f",
|
|
6239
|
+
`body=${body}`,
|
|
6240
|
+
"--jq",
|
|
6241
|
+
".id"
|
|
6242
|
+
]);
|
|
6243
|
+
return parseInt(output.trim(), 10);
|
|
6244
|
+
}
|
|
6245
|
+
function updateIssueComment(owner, repo, commentId, body, execGh = defaultExecGh) {
|
|
6246
|
+
execGh([
|
|
6247
|
+
"api",
|
|
6248
|
+
`repos/${owner}/${repo}/issues/comments/${commentId}`,
|
|
6249
|
+
"-X",
|
|
6250
|
+
"PATCH",
|
|
6251
|
+
"-f",
|
|
6252
|
+
`body=${body}`
|
|
6253
|
+
]);
|
|
6244
6254
|
}
|
|
6245
6255
|
function formatEntry(item, compact = false) {
|
|
6246
6256
|
if (compact) {
|
|
@@ -6350,19 +6360,19 @@ function findIndexComments(comments) {
|
|
|
6350
6360
|
return { open, recent, archived };
|
|
6351
6361
|
}
|
|
6352
6362
|
async function initIndex(opts) {
|
|
6353
|
-
const { owner, repo, indexIssue, kind, recentDays, dryRun
|
|
6354
|
-
const
|
|
6363
|
+
const { owner, repo, indexIssue, kind, recentDays, dryRun } = opts;
|
|
6364
|
+
const execGh = opts.execGh ?? defaultExecGh;
|
|
6355
6365
|
const log = opts.log ?? (() => {
|
|
6356
6366
|
});
|
|
6357
6367
|
const runTool = opts.runTool ?? executeTool;
|
|
6358
6368
|
log(`Scanning ${kind}...`);
|
|
6359
|
-
const items = kind === "prs" ?
|
|
6369
|
+
const items = kind === "prs" ? fetchAllPRs(owner, repo, execGh, log) : fetchAllIssues(owner, repo, execGh, log);
|
|
6360
6370
|
log(`${icons.info} Found ${items.length} ${kind}.`);
|
|
6361
6371
|
const { open, recentlyClosed, archived } = categorizeItems(items, recentDays);
|
|
6362
6372
|
log(
|
|
6363
6373
|
` ${open.length} open, ${recentlyClosed.length} recently closed, ${archived.length} archived`
|
|
6364
6374
|
);
|
|
6365
|
-
const comments =
|
|
6375
|
+
const comments = fetchIssueComments2(owner, repo, indexIssue, execGh);
|
|
6366
6376
|
const found = findIndexComments(comments);
|
|
6367
6377
|
const existingOpen = found.open ? parseExistingNumbers(found.open.body) : /* @__PURE__ */ new Set();
|
|
6368
6378
|
const existingRecent = found.recent ? parseExistingNumbers(found.recent.body) : /* @__PURE__ */ new Set();
|
|
@@ -6431,19 +6441,19 @@ ${icons.info} Dry run \u2014 would update index issue #${indexIssue}:`);
|
|
|
6431
6441
|
}
|
|
6432
6442
|
log(`Populating index issue #${indexIssue}...`);
|
|
6433
6443
|
if (found.open) {
|
|
6434
|
-
|
|
6444
|
+
updateIssueComment(owner, repo, found.open.id, openBody, execGh);
|
|
6435
6445
|
} else {
|
|
6436
|
-
|
|
6446
|
+
createIssueComment(owner, repo, indexIssue, openBody, execGh);
|
|
6437
6447
|
}
|
|
6438
6448
|
if (found.recent) {
|
|
6439
|
-
|
|
6449
|
+
updateIssueComment(owner, repo, found.recent.id, recentBody, execGh);
|
|
6440
6450
|
} else {
|
|
6441
|
-
|
|
6451
|
+
createIssueComment(owner, repo, indexIssue, recentBody, execGh);
|
|
6442
6452
|
}
|
|
6443
6453
|
if (found.archived) {
|
|
6444
|
-
|
|
6454
|
+
updateIssueComment(owner, repo, found.archived.id, archivedBody, execGh);
|
|
6445
6455
|
} else {
|
|
6446
|
-
|
|
6456
|
+
createIssueComment(owner, repo, indexIssue, archivedBody, execGh);
|
|
6447
6457
|
}
|
|
6448
6458
|
log(
|
|
6449
6459
|
`${icons.success} Index populated: ${open.length} open, ${recentlyClosed.length} recent, ${archived.length} archived (${newEntries} new entries)`
|
|
@@ -6456,22 +6466,10 @@ ${icons.info} Dry run \u2014 would update index issue #${indexIssue}:`);
|
|
|
6456
6466
|
};
|
|
6457
6467
|
}
|
|
6458
6468
|
async function runDedupInit(options, deps = {}) {
|
|
6459
|
-
const
|
|
6469
|
+
const execGh = deps.execGh ?? defaultExecGh;
|
|
6460
6470
|
const log = deps.log ?? console.log;
|
|
6461
6471
|
const logError = deps.logError ?? console.error;
|
|
6462
6472
|
const resolveCmd = deps.resolveAgentCommandFn ?? resolveAgentCommand;
|
|
6463
|
-
const ensureAuthFn = deps.ensureAuthFn ?? (() => ensureAuth("https://opencara.workers.dev"));
|
|
6464
|
-
let token;
|
|
6465
|
-
try {
|
|
6466
|
-
token = await ensureAuthFn();
|
|
6467
|
-
} catch (err) {
|
|
6468
|
-
if (err instanceof AuthError) {
|
|
6469
|
-
logError(`${icons.error} ${err.message}`);
|
|
6470
|
-
process.exitCode = 1;
|
|
6471
|
-
return;
|
|
6472
|
-
}
|
|
6473
|
-
throw err;
|
|
6474
|
-
}
|
|
6475
6473
|
if (!options.repo) {
|
|
6476
6474
|
logError(`${icons.error} --repo is required. Usage: opencara dedup init --repo owner/repo`);
|
|
6477
6475
|
process.exitCode = 1;
|
|
@@ -6490,7 +6488,7 @@ async function runDedupInit(options, deps = {}) {
|
|
|
6490
6488
|
return;
|
|
6491
6489
|
}
|
|
6492
6490
|
log(`Fetching .opencara.toml from ${options.repo}...`);
|
|
6493
|
-
const tomlContent =
|
|
6491
|
+
const tomlContent = fetchRepoFile(owner, repo, ".opencara.toml", execGh);
|
|
6494
6492
|
if (!tomlContent) {
|
|
6495
6493
|
logError(`${icons.error} No .opencara.toml found in ${options.repo}`);
|
|
6496
6494
|
process.exitCode = 1;
|
|
@@ -6552,9 +6550,8 @@ ${pc3.bold(`Initializing ${target.kind} dedup index (issue #${target.indexIssue}
|
|
|
6552
6550
|
kind: target.kind,
|
|
6553
6551
|
recentDays,
|
|
6554
6552
|
dryRun: options.dryRun ?? false,
|
|
6555
|
-
token,
|
|
6556
6553
|
agentCommandTemplate,
|
|
6557
|
-
|
|
6554
|
+
execGh,
|
|
6558
6555
|
log,
|
|
6559
6556
|
runTool: deps.runTool
|
|
6560
6557
|
});
|
|
@@ -6567,10 +6564,7 @@ function dedupCommand() {
|
|
|
6567
6564
|
"Use AI agent to generate enriched descriptions (e.g., claude, codex, gemini, qwen)"
|
|
6568
6565
|
).action(
|
|
6569
6566
|
async (options) => {
|
|
6570
|
-
|
|
6571
|
-
await runDedupInit(options, {
|
|
6572
|
-
ensureAuthFn: () => ensureAuth(config.platformUrl, { configPath: config.authFile })
|
|
6573
|
-
});
|
|
6567
|
+
await runDedupInit(options);
|
|
6574
6568
|
}
|
|
6575
6569
|
);
|
|
6576
6570
|
return dedup;
|
|
@@ -6704,7 +6698,7 @@ var statusCommand = new Command4("status").description("Show agent config, conne
|
|
|
6704
6698
|
});
|
|
6705
6699
|
|
|
6706
6700
|
// src/index.ts
|
|
6707
|
-
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.19.
|
|
6701
|
+
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.19.7");
|
|
6708
6702
|
program.addCommand(agentCommand);
|
|
6709
6703
|
program.addCommand(authCommand());
|
|
6710
6704
|
program.addCommand(dedupCommand());
|