opencara 0.23.2 → 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.
Files changed (2) hide show
  1. package/dist/index.js +99 -10
  2. 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,10 +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(
3873
- [...credArgs, "fetch", "--force", "origin", "+refs/heads/*:refs/heads/*"],
3874
- bareRepoPath
3875
- );
3872
+ gitExec2([...credArgs, "fetch", "--force", "origin", "+refs/heads/*:refs/heads/*"], bareRepoPath);
3876
3873
  let defaultBranch;
3877
3874
  try {
3878
3875
  defaultBranch = gitExec2(
@@ -3956,6 +3953,57 @@ function createPR(worktreePath, issueNumber, issueTitle, summary, branchName) {
3956
3953
  const prNumber = parseInt(prNumberMatch[1], 10);
3957
3954
  return { prNumber, prUrl };
3958
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
+ }
3959
4007
  async function executeImplement(task, worktreePath, deps, timeoutSeconds, signal, runTool = executeTool) {
3960
4008
  const timeoutMs = timeoutSeconds * 1e3;
3961
4009
  if (timeoutMs <= TIMEOUT_SAFETY_MARGIN_MS6) {
@@ -3963,6 +4011,25 @@ async function executeImplement(task, worktreePath, deps, timeoutSeconds, signal
3963
4011
  }
3964
4012
  const effectiveTimeout = timeoutMs - TIMEOUT_SAFETY_MARGIN_MS6;
3965
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
+ }
3966
4033
  const result = await runTool(
3967
4034
  deps.commandTemplate,
3968
4035
  prompt2,
@@ -3983,7 +4050,8 @@ async function executeImplement(task, worktreePath, deps, timeoutSeconds, signal
3983
4050
  output,
3984
4051
  tokensUsed: result.tokensUsed + inputTokens,
3985
4052
  tokensEstimated: !result.tokensParsed,
3986
- tokenDetail
4053
+ tokenDetail,
4054
+ agentic: false
3987
4055
  };
3988
4056
  }
3989
4057
  async function executeImplementTask(client, agentId, task, deps, timeoutSeconds, logger, signal, runTool, role = "implement", gitOps = { checkoutForImplement, commitAndPush, createPR, cleanupImplementWorktree }) {
@@ -4014,6 +4082,27 @@ async function executeImplementTask(client, agentId, task, deps, timeoutSeconds,
4014
4082
  runTool
4015
4083
  );
4016
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
+ }
4017
4106
  let filesChanged = 0;
4018
4107
  let uncommitted = 0;
4019
4108
  try {
@@ -5574,7 +5663,7 @@ function sleep2(ms, signal) {
5574
5663
  async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
5575
5664
  const client = new ApiClient(platformUrl, {
5576
5665
  authToken: options?.authToken,
5577
- cliVersion: "0.23.2",
5666
+ cliVersion: "0.23.3",
5578
5667
  versionOverride: options?.versionOverride,
5579
5668
  onTokenRefresh: options?.onTokenRefresh
5580
5669
  });
@@ -5860,7 +5949,7 @@ async function startBatchAgents(config, agents, pollIntervalMs, oauthToken, opti
5860
5949
  const { versionOverride, verbose, instancesOverride, agentOwner, userOrgs } = options;
5861
5950
  const client = new ApiClient(config.platformUrl, {
5862
5951
  authToken: oauthToken,
5863
- cliVersion: "0.23.2",
5952
+ cliVersion: "0.23.3",
5864
5953
  versionOverride,
5865
5954
  onTokenRefresh: () => getValidToken(config.platformUrl, { configPath: config.authFile })
5866
5955
  });
@@ -6203,7 +6292,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
6203
6292
  }
6204
6293
  config = loadConfig();
6205
6294
  }
6206
- console.log(formatVersionBanner("0.23.2", "0987fd4"));
6295
+ console.log(formatVersionBanner("0.23.3", "fb13aac"));
6207
6296
  if (config.agents && config.agents.length > 0) {
6208
6297
  const toolEntries = config.agents.map((a) => ({
6209
6298
  tool: a.tool,
@@ -7026,7 +7115,7 @@ var statusCommand = new Command4("status").description("Show agent config, conne
7026
7115
  });
7027
7116
 
7028
7117
  // src/index.ts
7029
- var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.23.2"} (${"0987fd4"})`);
7118
+ var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.23.3"} (${"fb13aac"})`);
7030
7119
  program.addCommand(agentCommand);
7031
7120
  program.addCommand(authCommand());
7032
7121
  program.addCommand(dedupCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencara",
3
- "version": "0.23.2",
3
+ "version": "0.23.3",
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",