opencara 0.23.1 → 0.23.3
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 +99 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3754,7 +3754,7 @@ async function executeIssueReviewTask(client, agentId, task, deps, timeoutSecond
|
|
|
3754
3754
|
}
|
|
3755
3755
|
|
|
3756
3756
|
// src/implement.ts
|
|
3757
|
-
import { execFileSync as execFileSync6 } from "child_process";
|
|
3757
|
+
import { execFileSync as execFileSync6, spawn as spawn2 } from "child_process";
|
|
3758
3758
|
import * as fs8 from "fs";
|
|
3759
3759
|
import * as path8 from "path";
|
|
3760
3760
|
var TIMEOUT_SAFETY_MARGIN_MS6 = 3e4;
|
|
@@ -3869,7 +3869,7 @@ function checkoutForImplement(owner, repo, issueNumber, branchName, baseDir) {
|
|
|
3869
3869
|
}
|
|
3870
3870
|
}
|
|
3871
3871
|
const credArgs = ghAvailable ? ["-c", `credential.helper=${GH_CREDENTIAL_HELPER2}`] : [];
|
|
3872
|
-
gitExec2([...credArgs, "fetch", "--force", "origin"], bareRepoPath);
|
|
3872
|
+
gitExec2([...credArgs, "fetch", "--force", "origin", "+refs/heads/*:refs/heads/*"], bareRepoPath);
|
|
3873
3873
|
let defaultBranch;
|
|
3874
3874
|
try {
|
|
3875
3875
|
defaultBranch = gitExec2(
|
|
@@ -3953,6 +3953,57 @@ function createPR(worktreePath, issueNumber, issueTitle, summary, branchName) {
|
|
|
3953
3953
|
const prNumber = parseInt(prNumberMatch[1], 10);
|
|
3954
3954
|
return { prNumber, prUrl };
|
|
3955
3955
|
}
|
|
3956
|
+
function isAgenticCommand(commandTemplate) {
|
|
3957
|
+
return commandTemplate.includes("${PROMPT}") && !commandTemplate.includes("--print");
|
|
3958
|
+
}
|
|
3959
|
+
function executeAgentic(commandTemplate, prompt2, timeoutMs, cwd, signal) {
|
|
3960
|
+
const allVars = { PROMPT: prompt2, CODEBASE_DIR: cwd };
|
|
3961
|
+
const { command, args } = parseCommandTemplate(commandTemplate, allVars);
|
|
3962
|
+
return new Promise((resolve2, reject) => {
|
|
3963
|
+
if (signal?.aborted) {
|
|
3964
|
+
reject(new ToolTimeoutError("Tool execution aborted"));
|
|
3965
|
+
return;
|
|
3966
|
+
}
|
|
3967
|
+
const child = spawn2(command, args, {
|
|
3968
|
+
stdio: "inherit",
|
|
3969
|
+
cwd
|
|
3970
|
+
});
|
|
3971
|
+
let settled = false;
|
|
3972
|
+
const timer = setTimeout(() => {
|
|
3973
|
+
if (!settled) {
|
|
3974
|
+
child.kill("SIGTERM");
|
|
3975
|
+
setTimeout(() => {
|
|
3976
|
+
if (!settled) child.kill("SIGKILL");
|
|
3977
|
+
}, 5e3);
|
|
3978
|
+
}
|
|
3979
|
+
}, timeoutMs);
|
|
3980
|
+
let onAbort;
|
|
3981
|
+
if (signal) {
|
|
3982
|
+
onAbort = () => {
|
|
3983
|
+
if (!settled) child.kill("SIGTERM");
|
|
3984
|
+
};
|
|
3985
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
3986
|
+
}
|
|
3987
|
+
child.on("error", (err) => {
|
|
3988
|
+
clearTimeout(timer);
|
|
3989
|
+
if (onAbort && signal) signal.removeEventListener("abort", onAbort);
|
|
3990
|
+
if (settled) return;
|
|
3991
|
+
settled = true;
|
|
3992
|
+
reject(err);
|
|
3993
|
+
});
|
|
3994
|
+
child.on("close", (code, sig) => {
|
|
3995
|
+
clearTimeout(timer);
|
|
3996
|
+
if (onAbort && signal) signal.removeEventListener("abort", onAbort);
|
|
3997
|
+
if (settled) return;
|
|
3998
|
+
settled = true;
|
|
3999
|
+
if (sig === "SIGTERM" || sig === "SIGKILL") {
|
|
4000
|
+
reject(new ToolTimeoutError(`Tool timed out after ${Math.round(timeoutMs / 1e3)}s`));
|
|
4001
|
+
return;
|
|
4002
|
+
}
|
|
4003
|
+
resolve2({ exitCode: code ?? 1 });
|
|
4004
|
+
});
|
|
4005
|
+
});
|
|
4006
|
+
}
|
|
3956
4007
|
async function executeImplement(task, worktreePath, deps, timeoutSeconds, signal, runTool = executeTool) {
|
|
3957
4008
|
const timeoutMs = timeoutSeconds * 1e3;
|
|
3958
4009
|
if (timeoutMs <= TIMEOUT_SAFETY_MARGIN_MS6) {
|
|
@@ -3960,6 +4011,25 @@ async function executeImplement(task, worktreePath, deps, timeoutSeconds, signal
|
|
|
3960
4011
|
}
|
|
3961
4012
|
const effectiveTimeout = timeoutMs - TIMEOUT_SAFETY_MARGIN_MS6;
|
|
3962
4013
|
const prompt2 = buildImplementPrompt(task);
|
|
4014
|
+
if (isAgenticCommand(deps.commandTemplate)) {
|
|
4015
|
+
const result2 = await executeAgentic(
|
|
4016
|
+
deps.commandTemplate,
|
|
4017
|
+
prompt2,
|
|
4018
|
+
effectiveTimeout,
|
|
4019
|
+
worktreePath,
|
|
4020
|
+
signal
|
|
4021
|
+
);
|
|
4022
|
+
return {
|
|
4023
|
+
output: {
|
|
4024
|
+
summary: result2.exitCode === 0 ? "Implementation completed" : "Implementation failed",
|
|
4025
|
+
filesChanged: []
|
|
4026
|
+
},
|
|
4027
|
+
tokensUsed: 0,
|
|
4028
|
+
tokensEstimated: true,
|
|
4029
|
+
tokenDetail: { input: 0, output: 0, total: 0, parsed: false },
|
|
4030
|
+
agentic: true
|
|
4031
|
+
};
|
|
4032
|
+
}
|
|
3963
4033
|
const result = await runTool(
|
|
3964
4034
|
deps.commandTemplate,
|
|
3965
4035
|
prompt2,
|
|
@@ -3980,7 +4050,8 @@ async function executeImplement(task, worktreePath, deps, timeoutSeconds, signal
|
|
|
3980
4050
|
output,
|
|
3981
4051
|
tokensUsed: result.tokensUsed + inputTokens,
|
|
3982
4052
|
tokensEstimated: !result.tokensParsed,
|
|
3983
|
-
tokenDetail
|
|
4053
|
+
tokenDetail,
|
|
4054
|
+
agentic: false
|
|
3984
4055
|
};
|
|
3985
4056
|
}
|
|
3986
4057
|
async function executeImplementTask(client, agentId, task, deps, timeoutSeconds, logger, signal, runTool, role = "implement", gitOps = { checkoutForImplement, commitAndPush, createPR, cleanupImplementWorktree }) {
|
|
@@ -4011,6 +4082,27 @@ async function executeImplementTask(client, agentId, task, deps, timeoutSeconds,
|
|
|
4011
4082
|
runTool
|
|
4012
4083
|
);
|
|
4013
4084
|
logger.log(` AI completed (${aiResult.tokensUsed.toLocaleString()} tokens)`);
|
|
4085
|
+
if (aiResult.agentic) {
|
|
4086
|
+
logger.log(" Agentic mode \u2014 AI handled commit/push/PR/review/merge");
|
|
4087
|
+
try {
|
|
4088
|
+
await client.post(`/api/tasks/${task.task_id}/result`, {
|
|
4089
|
+
agent_id: agentId,
|
|
4090
|
+
type: role,
|
|
4091
|
+
review_text: sanitizeTokens(aiResult.output.summary),
|
|
4092
|
+
tokens_used: aiResult.tokensUsed
|
|
4093
|
+
});
|
|
4094
|
+
logger.log(" Result submitted");
|
|
4095
|
+
} catch {
|
|
4096
|
+
logger.log(
|
|
4097
|
+
" Result submission skipped (claim may have expired \u2014 normal for agentic mode)"
|
|
4098
|
+
);
|
|
4099
|
+
}
|
|
4100
|
+
return {
|
|
4101
|
+
tokensUsed: aiResult.tokensUsed,
|
|
4102
|
+
tokensEstimated: aiResult.tokensEstimated,
|
|
4103
|
+
tokenDetail: aiResult.tokenDetail
|
|
4104
|
+
};
|
|
4105
|
+
}
|
|
4014
4106
|
let filesChanged = 0;
|
|
4015
4107
|
let uncommitted = 0;
|
|
4016
4108
|
try {
|
|
@@ -5571,7 +5663,7 @@ function sleep2(ms, signal) {
|
|
|
5571
5663
|
async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
|
|
5572
5664
|
const client = new ApiClient(platformUrl, {
|
|
5573
5665
|
authToken: options?.authToken,
|
|
5574
|
-
cliVersion: "0.23.
|
|
5666
|
+
cliVersion: "0.23.3",
|
|
5575
5667
|
versionOverride: options?.versionOverride,
|
|
5576
5668
|
onTokenRefresh: options?.onTokenRefresh
|
|
5577
5669
|
});
|
|
@@ -5857,7 +5949,7 @@ async function startBatchAgents(config, agents, pollIntervalMs, oauthToken, opti
|
|
|
5857
5949
|
const { versionOverride, verbose, instancesOverride, agentOwner, userOrgs } = options;
|
|
5858
5950
|
const client = new ApiClient(config.platformUrl, {
|
|
5859
5951
|
authToken: oauthToken,
|
|
5860
|
-
cliVersion: "0.23.
|
|
5952
|
+
cliVersion: "0.23.3",
|
|
5861
5953
|
versionOverride,
|
|
5862
5954
|
onTokenRefresh: () => getValidToken(config.platformUrl, { configPath: config.authFile })
|
|
5863
5955
|
});
|
|
@@ -6200,7 +6292,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
|
|
|
6200
6292
|
}
|
|
6201
6293
|
config = loadConfig();
|
|
6202
6294
|
}
|
|
6203
|
-
console.log(formatVersionBanner("0.23.
|
|
6295
|
+
console.log(formatVersionBanner("0.23.3", "fb13aac"));
|
|
6204
6296
|
if (config.agents && config.agents.length > 0) {
|
|
6205
6297
|
const toolEntries = config.agents.map((a) => ({
|
|
6206
6298
|
tool: a.tool,
|
|
@@ -7023,7 +7115,7 @@ var statusCommand = new Command4("status").description("Show agent config, conne
|
|
|
7023
7115
|
});
|
|
7024
7116
|
|
|
7025
7117
|
// src/index.ts
|
|
7026
|
-
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.23.
|
|
7118
|
+
var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.23.3"} (${"fb13aac"})`);
|
|
7027
7119
|
program.addCommand(agentCommand);
|
|
7028
7120
|
program.addCommand(authCommand());
|
|
7029
7121
|
program.addCommand(dedupCommand());
|