opencara 0.23.12 → 0.23.14

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 +55 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -132,7 +132,7 @@ function parseTriggerSection(raw, defaults) {
132
132
  }
133
133
  return result;
134
134
  }
135
- var DEFAULT_MODEL_DIVERSITY_GRACE_MS = 3e4;
135
+ var DEFAULT_MODEL_DIVERSITY_GRACE_MS = 3e5;
136
136
  function parseDurationSeconds(value, defaultMs) {
137
137
  if (typeof value === "number")
138
138
  return value === 0 ? 0 : clamp(value, 0, 300) * 1e3;
@@ -4825,6 +4825,10 @@ function concatUint8Arrays(chunks, totalLength) {
4825
4825
  return result;
4826
4826
  }
4827
4827
  var MAX_DIFF_FETCH_ATTEMPTS = 3;
4828
+ var MAX_TASK_ERROR_ATTEMPTS = 3;
4829
+ var WEIGHT_PENALTY_FACTOR = 0.5;
4830
+ var MIN_DISPATCH_WEIGHT = 0.1;
4831
+ var WEIGHT_RECOVERY = 0.25;
4828
4832
  async function pollLoop(client, agentId, reviewDeps, consumptionDeps, agentInfo, logger, agentSession, options) {
4829
4833
  const {
4830
4834
  pollIntervalMs,
@@ -5314,6 +5318,7 @@ async function handleTask(client, agentId, task, reviewDeps, consumptionDeps, ag
5314
5318
  logError(` ${icons.error} Error on task ${task_id}: ${err.message}`);
5315
5319
  await safeError(client, task_id, agentId, err.message, logger);
5316
5320
  }
5321
+ return { toolFailed: true };
5317
5322
  } finally {
5318
5323
  if (taskCheckoutPath && taskBareRepoPath) {
5319
5324
  if (cleanupTracker) {
@@ -5695,7 +5700,7 @@ function sleep2(ms, signal) {
5695
5700
  async function startAgent(agentId, platformUrl, agentInfo, reviewDeps, consumptionDeps, options) {
5696
5701
  const client = new ApiClient(platformUrl, {
5697
5702
  authToken: options?.authToken,
5698
- cliVersion: "0.23.12",
5703
+ cliVersion: "0.23.14",
5699
5704
  versionOverride: options?.versionOverride,
5700
5705
  onTokenRefresh: options?.onTokenRefresh
5701
5706
  });
@@ -5870,7 +5875,16 @@ async function batchPollLoop(client, agentStates, options) {
5870
5875
  const response = await client.post("/api/tasks/poll/batch", request);
5871
5876
  consecutiveAuthErrors = 0;
5872
5877
  consecutiveErrors = 0;
5873
- for (const state of availableStates) {
5878
+ const eligibleStates = availableStates.filter((s) => s.weight >= MIN_DISPATCH_WEIGHT);
5879
+ const dispatchOrder = eligibleStates.map((s) => ({ state: s, score: s.weight * Math.random() })).sort((a, b) => b.score - a.score).map((e) => e.state);
5880
+ for (const s of availableStates) {
5881
+ if (s.weight < MIN_DISPATCH_WEIGHT) {
5882
+ s.logger.logWarn(
5883
+ `${icons.warn} Agent paused (weight ${s.weight.toFixed(2)} < ${MIN_DISPATCH_WEIGHT})`
5884
+ );
5885
+ }
5886
+ }
5887
+ for (const state of dispatchOrder) {
5874
5888
  const agentName = state.descriptor.name;
5875
5889
  const pollResponse = response.assignments[agentName];
5876
5890
  if (!pollResponse || pollResponse.tasks.length === 0) continue;
@@ -5883,7 +5897,9 @@ async function batchPollLoop(client, agentStates, options) {
5883
5897
  accessibleRepos,
5884
5898
  (msg) => state.logger.logWarn(`${icons.warn} ${msg}`)
5885
5899
  );
5886
- const task = eligible[0];
5900
+ const task = eligible.find(
5901
+ (t) => (state.taskErrorCounts.get(t.task_id) ?? 0) < MAX_TASK_ERROR_ATTEMPTS
5902
+ );
5887
5903
  if (!task) continue;
5888
5904
  busyAgents.add(state);
5889
5905
  const p = (async () => {
@@ -5915,10 +5931,39 @@ async function batchPollLoop(client, agentStates, options) {
5915
5931
  ` Skipping task ${task.task_id} after ${count} diff fetch failures`
5916
5932
  );
5917
5933
  }
5934
+ state.weight = Math.max(0, state.weight * WEIGHT_PENALTY_FACTOR);
5935
+ state.logger.logWarn(
5936
+ `${icons.warn} Weight reduced to ${state.weight.toFixed(2)} after diff fetch failure`
5937
+ );
5938
+ } else if (result.toolFailed) {
5939
+ const errCount = (state.taskErrorCounts.get(task.task_id) ?? 0) + 1;
5940
+ state.taskErrorCounts.set(task.task_id, errCount);
5941
+ if (errCount >= MAX_TASK_ERROR_ATTEMPTS) {
5942
+ state.logger.logWarn(
5943
+ `${icons.warn} Giving up on task ${task.task_id.slice(0, 8)}\u2026 after ${errCount} tool failures`
5944
+ );
5945
+ }
5946
+ state.weight = Math.max(0, state.weight * WEIGHT_PENALTY_FACTOR);
5947
+ state.logger.logWarn(
5948
+ `${icons.warn} Weight reduced to ${state.weight.toFixed(2)} after tool error`
5949
+ );
5950
+ } else {
5951
+ state.weight = Math.min(1, state.weight + WEIGHT_RECOVERY);
5918
5952
  }
5919
5953
  } catch (err) {
5920
5954
  logError(`${icons.error} Task handler failed: ${err.message}`);
5921
5955
  consecutiveErrors++;
5956
+ const errCount = (state.taskErrorCounts.get(task.task_id) ?? 0) + 1;
5957
+ state.taskErrorCounts.set(task.task_id, errCount);
5958
+ if (errCount >= MAX_TASK_ERROR_ATTEMPTS) {
5959
+ state.logger.logWarn(
5960
+ `${icons.warn} Giving up on task ${task.task_id.slice(0, 8)}\u2026 after ${errCount} failures`
5961
+ );
5962
+ }
5963
+ state.weight = Math.max(0, state.weight * WEIGHT_PENALTY_FACTOR);
5964
+ state.logger.logWarn(
5965
+ `${icons.warn} Weight reduced to ${state.weight.toFixed(2)} after task error`
5966
+ );
5922
5967
  } finally {
5923
5968
  busyAgents.delete(state);
5924
5969
  if (state.cleanupTracker) {
@@ -5992,7 +6037,7 @@ async function startBatchAgents(config, agents, pollIntervalMs, oauthToken, opti
5992
6037
  const { versionOverride, verbose, instancesOverride, agentOwner, userOrgs } = options;
5993
6038
  const client = new ApiClient(config.platformUrl, {
5994
6039
  authToken: oauthToken,
5995
- cliVersion: "0.23.12",
6040
+ cliVersion: "0.23.14",
5996
6041
  versionOverride,
5997
6042
  onTokenRefresh: () => getValidToken(config.platformUrl, { configPath: config.authFile })
5998
6043
  });
@@ -6071,7 +6116,9 @@ async function startBatchAgents(config, agents, pollIntervalMs, oauthToken, opti
6071
6116
  routerRelay,
6072
6117
  cleanupTracker,
6073
6118
  verbose,
6074
- diffFailCounts: /* @__PURE__ */ new Map()
6119
+ diffFailCounts: /* @__PURE__ */ new Map(),
6120
+ taskErrorCounts: /* @__PURE__ */ new Map(),
6121
+ weight: 1
6075
6122
  });
6076
6123
  }
6077
6124
  }
@@ -6337,7 +6384,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
6337
6384
  }
6338
6385
  config = loadConfig();
6339
6386
  }
6340
- console.log(formatVersionBanner("0.23.12", "d2879c9"));
6387
+ console.log(formatVersionBanner("0.23.14", "7dead21"));
6341
6388
  if (config.agents && config.agents.length > 0) {
6342
6389
  const toolEntries = config.agents.map((a) => ({
6343
6390
  tool: a.tool,
@@ -7159,7 +7206,7 @@ var statusCommand = new Command4("status").description("Show agent config, conne
7159
7206
  });
7160
7207
 
7161
7208
  // src/index.ts
7162
- var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.23.12"} (${"d2879c9"})`);
7209
+ var program = new Command5().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version(`${"0.23.14"} (${"7dead21"})`);
7163
7210
  program.addCommand(agentCommand);
7164
7211
  program.addCommand(authCommand());
7165
7212
  program.addCommand(dedupCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencara",
3
- "version": "0.23.12",
3
+ "version": "0.23.14",
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",