opencara 0.23.10 → 0.23.11
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 +76 -152
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34,15 +34,12 @@ function isRepoAllowed(repoConfig, targetOwner, targetRepo, agentOwner, userOrgs
|
|
|
34
34
|
case "public":
|
|
35
35
|
return true;
|
|
36
36
|
case "private": {
|
|
37
|
+
if (repoConfig.list && repoConfig.list.length > 0 && repoConfig.list.includes(fullRepo)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
37
40
|
const normalizedTarget = targetOwner.toLowerCase();
|
|
38
41
|
const normalizedOwner = agentOwner?.toLowerCase();
|
|
39
|
-
|
|
40
|
-
if (!hasAccess)
|
|
41
|
-
return false;
|
|
42
|
-
if (repoConfig.list && repoConfig.list.length > 0) {
|
|
43
|
-
return repoConfig.list.includes(fullRepo);
|
|
44
|
-
}
|
|
45
|
-
return true;
|
|
42
|
+
return normalizedOwner === normalizedTarget || userOrgs != null && userOrgs.has(normalizedTarget);
|
|
46
43
|
}
|
|
47
44
|
case "whitelist":
|
|
48
45
|
return (repoConfig.list ?? []).includes(fullRepo);
|
|
@@ -53,84 +50,6 @@ function isRepoAllowed(repoConfig, targetOwner, targetRepo, agentOwner, userOrgs
|
|
|
53
50
|
}
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
// ../shared/dist/api.js
|
|
57
|
-
var DEFAULT_REGISTRY = {
|
|
58
|
-
tools: [
|
|
59
|
-
{
|
|
60
|
-
name: "claude",
|
|
61
|
-
displayName: "Claude",
|
|
62
|
-
binary: "claude",
|
|
63
|
-
commandTemplate: "claude --model ${MODEL} --allowedTools '*' --print",
|
|
64
|
-
tokenParser: "claude"
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
name: "codex",
|
|
68
|
-
displayName: "Codex",
|
|
69
|
-
binary: "codex",
|
|
70
|
-
commandTemplate: "codex --model ${MODEL} exec",
|
|
71
|
-
tokenParser: "codex"
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
name: "gemini",
|
|
75
|
-
displayName: "Gemini",
|
|
76
|
-
binary: "gemini",
|
|
77
|
-
commandTemplate: "gemini -m ${MODEL}",
|
|
78
|
-
tokenParser: "gemini"
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: "qwen",
|
|
82
|
-
displayName: "Qwen",
|
|
83
|
-
binary: "qwen",
|
|
84
|
-
commandTemplate: "qwen --model ${MODEL} -y",
|
|
85
|
-
tokenParser: "qwen"
|
|
86
|
-
}
|
|
87
|
-
],
|
|
88
|
-
models: [
|
|
89
|
-
{
|
|
90
|
-
name: "claude-opus-4-6",
|
|
91
|
-
displayName: "Claude Opus 4.6",
|
|
92
|
-
tools: ["claude"]
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: "claude-opus-4-6[1m]",
|
|
96
|
-
displayName: "Claude Opus 4.6 (1M context)",
|
|
97
|
-
tools: ["claude"]
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
name: "claude-sonnet-4-6",
|
|
101
|
-
displayName: "Claude Sonnet 4.6",
|
|
102
|
-
tools: ["claude"]
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
name: "claude-sonnet-4-6[1m]",
|
|
106
|
-
displayName: "Claude Sonnet 4.6 (1M context)",
|
|
107
|
-
tools: ["claude"]
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
name: "gpt-5-codex",
|
|
111
|
-
displayName: "GPT-5 Codex",
|
|
112
|
-
tools: ["codex"]
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
name: "gemini-2.5-pro",
|
|
116
|
-
displayName: "Gemini 2.5 Pro",
|
|
117
|
-
tools: ["gemini"]
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
name: "qwen3.5-plus",
|
|
121
|
-
displayName: "Qwen 3.5 Plus",
|
|
122
|
-
tools: ["qwen"]
|
|
123
|
-
},
|
|
124
|
-
{ name: "glm-5", displayName: "GLM-5", tools: ["qwen"] },
|
|
125
|
-
{ name: "kimi-k2.5", displayName: "Kimi K2.5", tools: ["qwen"] },
|
|
126
|
-
{
|
|
127
|
-
name: "minimax-m2.5",
|
|
128
|
-
displayName: "Minimax M2.5",
|
|
129
|
-
tools: ["qwen"]
|
|
130
|
-
}
|
|
131
|
-
]
|
|
132
|
-
};
|
|
133
|
-
|
|
134
53
|
// ../shared/dist/review-config.js
|
|
135
54
|
import { parse as parseToml } from "smol-toml";
|
|
136
55
|
function isObject(value) {
|
|
@@ -552,6 +471,26 @@ import * as fs from "fs";
|
|
|
552
471
|
import * as path from "path";
|
|
553
472
|
import * as os from "os";
|
|
554
473
|
import { parse as parseToml2, stringify as stringifyToml } from "smol-toml";
|
|
474
|
+
|
|
475
|
+
// src/tool-defs.ts
|
|
476
|
+
var _cache = null;
|
|
477
|
+
function loadToolDefs() {
|
|
478
|
+
if (!_cache) {
|
|
479
|
+
_cache = JSON.parse('[{"name":"claude","binary":"claude","models":["claude-sonnet-4-6","claude-opus-4-6"],"command":"claude --model ${MODEL} --allowedTools \'*\' --print","scannable":true,"installLink":"https://docs.anthropic.com/en/docs/claude-code"},{"name":"codex","binary":"codex","models":["gpt-5-codex"],"command":"codex --model ${MODEL} exec","scannable":true,"installLink":"https://github.com/openai/codex"},{"name":"gemini","binary":"gemini","models":["gemini-2.5-pro"],"command":"gemini -m ${MODEL}","scannable":true,"installLink":"https://github.com/google-gemini/gemini-cli"},{"name":"qwen","binary":"qwen","models":["qwen3.5-plus","glm-5","kimi-k2.5","minimax-m2.5"],"command":"qwen --model ${MODEL} -y","scannable":false}]');
|
|
480
|
+
}
|
|
481
|
+
return _cache;
|
|
482
|
+
}
|
|
483
|
+
function getToolDef(name) {
|
|
484
|
+
return loadToolDefs().find((t) => t.name === name);
|
|
485
|
+
}
|
|
486
|
+
function getScannableTools() {
|
|
487
|
+
return loadToolDefs().filter((t) => t.scannable);
|
|
488
|
+
}
|
|
489
|
+
function getKnownToolNames() {
|
|
490
|
+
return new Set(loadToolDefs().map((t) => t.name));
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// src/config.ts
|
|
555
494
|
var DEFAULT_PLATFORM_URL = "https://api.opencara.com";
|
|
556
495
|
var CONFIG_DIR = path.join(os.homedir(), ".opencara");
|
|
557
496
|
var CONFIG_FILE = process.env.OPENCARA_CONFIG && process.env.OPENCARA_CONFIG.trim() ? path.resolve(process.env.OPENCARA_CONFIG) : path.join(CONFIG_DIR, "config.toml");
|
|
@@ -589,7 +528,7 @@ var ConfigValidationError = class extends Error {
|
|
|
589
528
|
this.name = "ConfigValidationError";
|
|
590
529
|
}
|
|
591
530
|
};
|
|
592
|
-
var KNOWN_TOOL_NAMES =
|
|
531
|
+
var KNOWN_TOOL_NAMES = getKnownToolNames();
|
|
593
532
|
var TOOL_ALIASES = {
|
|
594
533
|
"claude-code": "claude"
|
|
595
534
|
};
|
|
@@ -4416,17 +4355,6 @@ function countReviewComments(commentsText) {
|
|
|
4416
4355
|
import { execFileSync as execFileSync8 } from "child_process";
|
|
4417
4356
|
import * as fs9 from "fs";
|
|
4418
4357
|
import * as readline2 from "readline";
|
|
4419
|
-
var SCANNABLE_TOOLS = ["claude", "codex", "gemini"];
|
|
4420
|
-
var DEFAULT_MODELS = {
|
|
4421
|
-
claude: "claude-sonnet-4-6",
|
|
4422
|
-
codex: "gpt-5-codex",
|
|
4423
|
-
gemini: "gemini-2.5-pro"
|
|
4424
|
-
};
|
|
4425
|
-
var INSTALL_LINKS = {
|
|
4426
|
-
claude: "https://docs.anthropic.com/en/docs/claude-code",
|
|
4427
|
-
codex: "https://github.com/openai/codex",
|
|
4428
|
-
gemini: "https://github.com/google-gemini/gemini-cli"
|
|
4429
|
-
};
|
|
4430
4358
|
function checkPrerequisites() {
|
|
4431
4359
|
const gitInstalled = validateCommandBinary("git");
|
|
4432
4360
|
const ghInstalled = validateCommandBinary("gh");
|
|
@@ -4450,21 +4378,13 @@ function checkPrerequisites() {
|
|
|
4450
4378
|
}
|
|
4451
4379
|
function discoverTools() {
|
|
4452
4380
|
const results = [];
|
|
4453
|
-
for (const
|
|
4454
|
-
if (validateCommandBinary(
|
|
4455
|
-
|
|
4456
|
-
results.push({ toolName, defaultModel });
|
|
4381
|
+
for (const tool of getScannableTools()) {
|
|
4382
|
+
if (validateCommandBinary(tool.binary)) {
|
|
4383
|
+
results.push({ toolName: tool.name, defaultModel: tool.models[0] });
|
|
4457
4384
|
}
|
|
4458
4385
|
}
|
|
4459
4386
|
return results;
|
|
4460
4387
|
}
|
|
4461
|
-
function resolveDefaultModel(toolName) {
|
|
4462
|
-
if (DEFAULT_MODELS[toolName]) {
|
|
4463
|
-
return DEFAULT_MODELS[toolName];
|
|
4464
|
-
}
|
|
4465
|
-
const registryModel = DEFAULT_REGISTRY.models.find((m) => m.tools.includes(toolName));
|
|
4466
|
-
return registryModel?.name ?? toolName;
|
|
4467
|
-
}
|
|
4468
4388
|
function generateConfig(tools) {
|
|
4469
4389
|
const lines = [
|
|
4470
4390
|
"# Auto-generated by opencara \u2014 edit to customize",
|
|
@@ -4541,22 +4461,29 @@ No config found at ${CONFIG_FILE}
|
|
|
4541
4461
|
process.stdout.write("Continuing without gh \u2014 some features may be limited.\n");
|
|
4542
4462
|
}
|
|
4543
4463
|
process.stdout.write("\nScanning for AI tools...\n");
|
|
4464
|
+
const scannableTools = getScannableTools();
|
|
4544
4465
|
const found = discoverTools();
|
|
4545
|
-
for (const tool of
|
|
4546
|
-
const disc = found.find((t) => t.toolName === tool);
|
|
4466
|
+
for (const tool of scannableTools) {
|
|
4467
|
+
const disc = found.find((t) => t.toolName === tool.name);
|
|
4547
4468
|
if (disc) {
|
|
4548
|
-
process.stdout.write(` \u2713 ${tool} (${disc.defaultModel})
|
|
4469
|
+
process.stdout.write(` \u2713 ${tool.name} (${disc.defaultModel})
|
|
4549
4470
|
`);
|
|
4550
4471
|
} else {
|
|
4551
|
-
process.stdout.write(` \u2717 ${tool} (not found)
|
|
4472
|
+
process.stdout.write(` \u2717 ${tool.name} (not found)
|
|
4552
4473
|
`);
|
|
4553
4474
|
}
|
|
4554
4475
|
}
|
|
4555
4476
|
if (found.length === 0) {
|
|
4556
|
-
process.stdout.write(
|
|
4557
|
-
|
|
4558
|
-
|
|
4477
|
+
process.stdout.write(
|
|
4478
|
+
`
|
|
4479
|
+
No AI tools found. Install one of: ${scannableTools.map((t) => t.name).join(", ")}
|
|
4480
|
+
`
|
|
4481
|
+
);
|
|
4482
|
+
for (const tool of scannableTools) {
|
|
4483
|
+
if (tool.installLink) {
|
|
4484
|
+
process.stdout.write(` ${tool.name}: ${tool.installLink}
|
|
4559
4485
|
`);
|
|
4486
|
+
}
|
|
4560
4487
|
}
|
|
4561
4488
|
return false;
|
|
4562
4489
|
}
|
|
@@ -4690,9 +4617,9 @@ function resolveCommandTemplate(agentConfig, globalCommand) {
|
|
|
4690
4617
|
if (agentConfig?.command) return agentConfig.command;
|
|
4691
4618
|
if (globalCommand) return globalCommand;
|
|
4692
4619
|
if (agentConfig?.tool) {
|
|
4693
|
-
const
|
|
4694
|
-
if (
|
|
4695
|
-
return
|
|
4620
|
+
const toolDef = getToolDef(agentConfig.tool);
|
|
4621
|
+
if (toolDef) {
|
|
4622
|
+
return toolDef.command.replaceAll("${MODEL}", agentConfig.model ?? "");
|
|
4696
4623
|
}
|
|
4697
4624
|
}
|
|
4698
4625
|
return void 0;
|
|
@@ -5750,7 +5677,7 @@ function sleep2(ms, signal) {
|
|
|
5750
5677
|
async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
|
|
5751
5678
|
const client = new ApiClient(platformUrl, {
|
|
5752
5679
|
authToken: options?.authToken,
|
|
5753
|
-
cliVersion: "0.23.
|
|
5680
|
+
cliVersion: "0.23.11",
|
|
5754
5681
|
versionOverride: options?.versionOverride,
|
|
5755
5682
|
onTokenRefresh: options?.onTokenRefresh
|
|
5756
5683
|
});
|
|
@@ -6046,7 +5973,7 @@ async function startBatchAgents(config, agents, pollIntervalMs, oauthToken, opti
|
|
|
6046
5973
|
const { versionOverride, verbose, instancesOverride, agentOwner, userOrgs } = options;
|
|
6047
5974
|
const client = new ApiClient(config.platformUrl, {
|
|
6048
5975
|
authToken: oauthToken,
|
|
6049
|
-
cliVersion: "0.23.
|
|
5976
|
+
cliVersion: "0.23.11",
|
|
6050
5977
|
versionOverride,
|
|
6051
5978
|
onTokenRefresh: () => getValidToken(config.platformUrl, { configPath: config.authFile })
|
|
6052
5979
|
});
|
|
@@ -6217,12 +6144,11 @@ async function startBatchAgents(config, agents, pollIntervalMs, oauthToken, opti
|
|
|
6217
6144
|
async function startAgentRouter() {
|
|
6218
6145
|
const config = loadConfig();
|
|
6219
6146
|
const agentId = crypto2.randomUUID();
|
|
6220
|
-
let commandTemplate;
|
|
6221
6147
|
let agentConfig;
|
|
6222
6148
|
if (config.agents && config.agents.length > 0) {
|
|
6223
6149
|
agentConfig = config.agents.find((a) => a.router) ?? config.agents[0];
|
|
6224
6150
|
}
|
|
6225
|
-
commandTemplate = resolveCommandTemplate(agentConfig, config.agentCommand);
|
|
6151
|
+
const commandTemplate = resolveCommandTemplate(agentConfig, config.agentCommand);
|
|
6226
6152
|
const router = new RouterRelay();
|
|
6227
6153
|
router.start();
|
|
6228
6154
|
const logger = createLogger(agentConfig?.name ?? "agent[0]");
|
|
@@ -6294,12 +6220,11 @@ async function startAgentRouter() {
|
|
|
6294
6220
|
router.stop();
|
|
6295
6221
|
}
|
|
6296
6222
|
function startAgentByIndex(config, agentIndex, pollIntervalMs, oauthToken, versionOverride, verbose, instancesOverride, agentOwner, userOrgs) {
|
|
6297
|
-
let commandTemplate;
|
|
6298
6223
|
let agentConfig;
|
|
6299
6224
|
if (config.agents && config.agents.length > agentIndex) {
|
|
6300
6225
|
agentConfig = config.agents[agentIndex];
|
|
6301
6226
|
}
|
|
6302
|
-
commandTemplate = resolveCommandTemplate(agentConfig, config.agentCommand);
|
|
6227
|
+
const commandTemplate = resolveCommandTemplate(agentConfig, config.agentCommand);
|
|
6303
6228
|
const label = agentConfig?.name ?? `agent[${agentIndex}]`;
|
|
6304
6229
|
if (!commandTemplate) {
|
|
6305
6230
|
console.error(`[${label}] No command configured. Skipping.`);
|
|
@@ -6375,7 +6300,7 @@ function startAgentByIndex(config, agentIndex, pollIntervalMs, oauthToken, versi
|
|
|
6375
6300
|
return promises;
|
|
6376
6301
|
}
|
|
6377
6302
|
var agentCommand = new Command("agent").description("Manage review agents");
|
|
6378
|
-
agentCommand.command("start").description("Start agents in polling mode").option("--poll-interval <seconds>", "Poll interval in seconds", "10").option("--agent <index>", "
|
|
6303
|
+
agentCommand.command("start").description("Start agents in polling mode").option("--poll-interval <seconds>", "Poll interval in seconds", "10").option("--agent <index>", "Start a single agent by index from config.toml (0-based)").option("--all", "Start all configured agents concurrently (default when --agent is not set)").option(
|
|
6379
6304
|
"--version-override <value>",
|
|
6380
6305
|
"Cloudflare Workers version override (e.g. opencara-server=abc123)"
|
|
6381
6306
|
).option("-v, --verbose", "Log tool stdout/stderr after each review/summary for debugging").option("--instances <count>", "Number of concurrent instances per agent (overrides config)").action(
|
|
@@ -6393,7 +6318,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
6393
6318
|
}
|
|
6394
6319
|
config = loadConfig();
|
|
6395
6320
|
}
|
|
6396
|
-
console.log(formatVersionBanner("0.23.
|
|
6321
|
+
console.log(formatVersionBanner("0.23.11", "1ab6f70"));
|
|
6397
6322
|
if (config.agents && config.agents.length > 0) {
|
|
6398
6323
|
const toolEntries = config.agents.map((a) => ({
|
|
6399
6324
|
tool: a.tool,
|
|
@@ -6462,21 +6387,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
6462
6387
|
} else if (needsOrgs && userOrgs.size > 0) {
|
|
6463
6388
|
console.log(`Org memberships: ${[...userOrgs].join(", ")}`);
|
|
6464
6389
|
}
|
|
6465
|
-
if (opts.
|
|
6466
|
-
if (!config.agents || config.agents.length === 0) {
|
|
6467
|
-
console.error("No agents configured in ~/.opencara/config.toml");
|
|
6468
|
-
process.exit(1);
|
|
6469
|
-
return;
|
|
6470
|
-
}
|
|
6471
|
-
console.log(`Starting ${config.agents.length} agent config(s) in batch mode...`);
|
|
6472
|
-
await startBatchAgents(config, config.agents, pollIntervalMs, oauthToken, {
|
|
6473
|
-
versionOverride,
|
|
6474
|
-
verbose: opts.verbose,
|
|
6475
|
-
instancesOverride,
|
|
6476
|
-
agentOwner,
|
|
6477
|
-
userOrgs
|
|
6478
|
-
});
|
|
6479
|
-
} else {
|
|
6390
|
+
if (opts.agent != null) {
|
|
6480
6391
|
const maxIndex = (config.agents?.length ?? 0) - 1;
|
|
6481
6392
|
const agentIndex = Number(opts.agent);
|
|
6482
6393
|
if (!Number.isInteger(agentIndex) || agentIndex < 0 || agentIndex > maxIndex) {
|
|
@@ -6509,6 +6420,20 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
6509
6420
|
}
|
|
6510
6421
|
process.exit(1);
|
|
6511
6422
|
}
|
|
6423
|
+
} else {
|
|
6424
|
+
if (!config.agents || config.agents.length === 0) {
|
|
6425
|
+
console.error("No agents configured in ~/.opencara/config.toml");
|
|
6426
|
+
process.exit(1);
|
|
6427
|
+
return;
|
|
6428
|
+
}
|
|
6429
|
+
console.log(`Starting ${config.agents.length} agent config(s) in batch mode...`);
|
|
6430
|
+
await startBatchAgents(config, config.agents, pollIntervalMs, oauthToken, {
|
|
6431
|
+
versionOverride,
|
|
6432
|
+
verbose: opts.verbose,
|
|
6433
|
+
instancesOverride,
|
|
6434
|
+
agentOwner,
|
|
6435
|
+
userOrgs
|
|
6436
|
+
});
|
|
6512
6437
|
}
|
|
6513
6438
|
}
|
|
6514
6439
|
);
|
|
@@ -6799,11 +6724,10 @@ function resolveAgentCommand(toolName) {
|
|
|
6799
6724
|
if (cmd) return cmd;
|
|
6800
6725
|
}
|
|
6801
6726
|
}
|
|
6802
|
-
const
|
|
6803
|
-
if (
|
|
6804
|
-
const
|
|
6805
|
-
|
|
6806
|
-
return registryTool.commandTemplate.replaceAll("${MODEL}", modelName);
|
|
6727
|
+
const toolDef = getToolDef(toolName);
|
|
6728
|
+
if (toolDef) {
|
|
6729
|
+
const modelName = toolDef.models[0] ?? "";
|
|
6730
|
+
return toolDef.command.replaceAll("${MODEL}", modelName);
|
|
6807
6731
|
}
|
|
6808
6732
|
return null;
|
|
6809
6733
|
}
|
|
@@ -7050,7 +6974,7 @@ async function runDedupInit(options, deps = {}) {
|
|
|
7050
6974
|
const cmd = resolveCmd(options.agent);
|
|
7051
6975
|
if (!cmd) {
|
|
7052
6976
|
logError(
|
|
7053
|
-
`${icons.error} Unknown agent tool "${options.agent}". Available: ${
|
|
6977
|
+
`${icons.error} Unknown agent tool "${options.agent}". Available: ${loadToolDefs().map((t) => t.name).join(", ")}`
|
|
7054
6978
|
);
|
|
7055
6979
|
process.exitCode = 1;
|
|
7056
6980
|
return;
|
|
@@ -7105,13 +7029,13 @@ function agentRoleLabel(agent) {
|
|
|
7105
7029
|
return "reviewer+synthesizer";
|
|
7106
7030
|
}
|
|
7107
7031
|
function resolveToolBinary(toolName) {
|
|
7108
|
-
const
|
|
7109
|
-
return
|
|
7032
|
+
const def = getToolDef(toolName);
|
|
7033
|
+
return def?.binary ?? toolName;
|
|
7110
7034
|
}
|
|
7111
7035
|
function resolveCommand(agent) {
|
|
7112
7036
|
if (agent.command) return agent.command;
|
|
7113
|
-
const
|
|
7114
|
-
return
|
|
7037
|
+
const def = getToolDef(agent.tool);
|
|
7038
|
+
return def?.command ?? null;
|
|
7115
7039
|
}
|
|
7116
7040
|
async function checkConnectivity(platformUrl, fetchFn = fetch) {
|
|
7117
7041
|
const start = Date.now();
|
|
@@ -7216,7 +7140,7 @@ var statusCommand = new Command4("status").description("Show agent config, conne
|
|
|
7216
7140
|
});
|
|
7217
7141
|
|
|
7218
7142
|
// src/index.ts
|
|
7219
|
-
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.23.
|
|
7143
|
+
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.23.11"} (${"1ab6f70"})`);
|
|
7220
7144
|
program.addCommand(agentCommand);
|
|
7221
7145
|
program.addCommand(authCommand());
|
|
7222
7146
|
program.addCommand(dedupCommand());
|