opencara 0.15.1 → 0.15.2

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 +58 -24
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -869,6 +869,23 @@ function buildSystemPrompt(owner, repo, mode = "full") {
869
869
  const template = mode === "compact" ? COMPACT_SYSTEM_PROMPT_TEMPLATE : FULL_SYSTEM_PROMPT_TEMPLATE;
870
870
  return template.replace("{owner}", owner).replace("{repo}", repo);
871
871
  }
872
+ var VERDICT_EMOJI = {
873
+ approve: "\u2705",
874
+ request_changes: "\u274C",
875
+ comment: "\u{1F4AC}"
876
+ };
877
+ function buildMetadataHeader(verdict, meta) {
878
+ if (!meta) return "";
879
+ const emoji = VERDICT_EMOJI[verdict] ?? "";
880
+ const lines = [`**Reviewer**: \`${meta.model}/${meta.tool}\``];
881
+ if (meta.githubUsername) {
882
+ lines.push(
883
+ `**Contributors**: [@${meta.githubUsername}](https://github.com/${meta.githubUsername})`
884
+ );
885
+ }
886
+ lines.push(`**Verdict**: ${emoji} ${verdict}`);
887
+ return lines.join("\n") + "\n\n";
888
+ }
872
889
  function buildUserMessage(prompt, diffContent, contextBlock) {
873
890
  const parts = [prompt];
874
891
  if (contextBlock) {
@@ -928,6 +945,7 @@ ${userMessage}`;
928
945
  deps.codebaseDir ?? void 0
929
946
  );
930
947
  const { verdict, review } = extractVerdict(result.stdout);
948
+ const header = buildMetadataHeader(verdict, req.meta);
931
949
  const inputTokens = result.tokensParsed ? 0 : estimateTokens(fullPrompt);
932
950
  const detail = result.tokenDetail;
933
951
  const tokenDetail = result.tokensParsed ? detail : {
@@ -937,7 +955,7 @@ ${userMessage}`;
937
955
  parsed: false
938
956
  };
939
957
  return {
940
- review,
958
+ review: header + review,
941
959
  verdict,
942
960
  tokensUsed: result.tokensUsed + inputTokens,
943
961
  tokensEstimated: !result.tokensParsed,
@@ -963,6 +981,22 @@ var InputTooLargeError = class extends Error {
963
981
  this.name = "InputTooLargeError";
964
982
  }
965
983
  };
984
+ function buildSummaryMetadataHeader(verdict, meta) {
985
+ if (!meta) return "";
986
+ const emoji = VERDICT_EMOJI[verdict] ?? "";
987
+ const reviewersList = meta.reviewerModels.map((r) => `\`${r}\``).join(", ");
988
+ const lines = [
989
+ `**Reviewers**: ${reviewersList}`,
990
+ `**Synthesizer**: \`${meta.model}/${meta.tool}\``
991
+ ];
992
+ if (meta.githubUsername) {
993
+ lines.push(
994
+ `**Contributors**: [@${meta.githubUsername}](https://github.com/${meta.githubUsername})`
995
+ );
996
+ }
997
+ lines.push(`**Verdict**: ${emoji} ${verdict}`);
998
+ return lines.join("\n") + "\n\n";
999
+ }
966
1000
  function buildSummarySystemPrompt(owner, repo, reviewCount) {
967
1001
  return `You are a senior code reviewer and lead synthesizer for the ${owner}/${repo} repository.
968
1002
 
@@ -1042,6 +1076,10 @@ async function executeSummary(req, deps, runTool = executeTool) {
1042
1076
  abortController.abort();
1043
1077
  }, effectiveTimeout);
1044
1078
  try {
1079
+ const summaryMeta = req.meta ? {
1080
+ ...req.meta,
1081
+ reviewerModels: req.reviews.map((r) => `${r.model}/${r.tool}`)
1082
+ } : void 0;
1045
1083
  const systemPrompt = buildSummarySystemPrompt(req.owner, req.repo, req.reviews.length);
1046
1084
  const userMessage = buildSummaryUserMessage(
1047
1085
  req.prompt,
@@ -1060,6 +1098,8 @@ ${userMessage}`;
1060
1098
  void 0,
1061
1099
  deps.codebaseDir ?? void 0
1062
1100
  );
1101
+ const { verdict, review } = extractVerdict(result.stdout);
1102
+ const header = buildSummaryMetadataHeader(verdict, summaryMeta);
1063
1103
  const inputTokens = result.tokensParsed ? 0 : estimateTokens(fullPrompt);
1064
1104
  const detail = result.tokenDetail;
1065
1105
  const tokenDetail = result.tokensParsed ? detail : {
@@ -1069,7 +1109,7 @@ ${userMessage}`;
1069
1109
  parsed: false
1070
1110
  };
1071
1111
  return {
1072
- summary: result.stdout,
1112
+ summary: header + review,
1073
1113
  tokensUsed: result.tokensUsed + inputTokens,
1074
1114
  tokensEstimated: !result.tokensParsed,
1075
1115
  tokenDetail
@@ -1692,13 +1732,6 @@ function concatUint8Arrays(chunks, totalLength) {
1692
1732
  return result;
1693
1733
  }
1694
1734
  var MAX_DIFF_FETCH_ATTEMPTS = 3;
1695
- function appendContributorAttribution(text, githubUsername) {
1696
- if (!githubUsername) return text;
1697
- return `${text}
1698
-
1699
- ---
1700
- Contributed by [@${githubUsername}](https://github.com/${githubUsername})`;
1701
- }
1702
1735
  async function pollLoop(client, agentId, reviewDeps, consumptionDeps, agentInfo, logger, agentSession, options) {
1703
1736
  const {
1704
1737
  pollIntervalMs,
@@ -1926,6 +1959,7 @@ async function handleTask(client, agentId, task, reviewDeps, consumptionDeps, ag
1926
1959
  taskReviewDeps,
1927
1960
  consumptionDeps,
1928
1961
  logger,
1962
+ agentInfo,
1929
1963
  routerRelay,
1930
1964
  signal,
1931
1965
  contextBlock,
@@ -1945,6 +1979,7 @@ async function handleTask(client, agentId, task, reviewDeps, consumptionDeps, ag
1945
1979
  taskReviewDeps,
1946
1980
  consumptionDeps,
1947
1981
  logger,
1982
+ agentInfo,
1948
1983
  routerRelay,
1949
1984
  signal,
1950
1985
  contextBlock,
@@ -1998,7 +2033,7 @@ async function safeError(client, taskId, agentId, error, logger) {
1998
2033
  );
1999
2034
  }
2000
2035
  }
2001
- async function executeReviewTask(client, agentId, taskId, owner, repo, prNumber, diffContent, prompt, timeoutSeconds, reviewDeps, consumptionDeps, logger, routerRelay, signal, contextBlock, githubUsername) {
2036
+ async function executeReviewTask(client, agentId, taskId, owner, repo, prNumber, diffContent, prompt, timeoutSeconds, reviewDeps, consumptionDeps, logger, agentInfo, routerRelay, signal, contextBlock, githubUsername) {
2002
2037
  if (consumptionDeps.usageLimits?.maxTokensPerReview != null && consumptionDeps.usageTracker) {
2003
2038
  const estimatedInput = estimateTokens(diffContent + prompt + (contextBlock ?? ""));
2004
2039
  const perReviewCheck = consumptionDeps.usageTracker.checkPerReviewLimit(
@@ -2041,6 +2076,7 @@ async function executeReviewTask(client, agentId, taskId, owner, repo, prNumber,
2041
2076
  };
2042
2077
  } else {
2043
2078
  logger.log(` ${icons.running} Executing review: ${reviewDeps.commandTemplate}`);
2079
+ const meta = { model: agentInfo.model, tool: agentInfo.tool, githubUsername };
2044
2080
  const result = await executeReview(
2045
2081
  {
2046
2082
  taskId,
@@ -2051,7 +2087,8 @@ async function executeReviewTask(client, agentId, taskId, owner, repo, prNumber,
2051
2087
  prNumber,
2052
2088
  timeout: timeoutSeconds,
2053
2089
  reviewMode: "full",
2054
- contextBlock
2090
+ contextBlock,
2091
+ meta
2055
2092
  },
2056
2093
  reviewDeps
2057
2094
  );
@@ -2065,7 +2102,7 @@ async function executeReviewTask(client, agentId, taskId, owner, repo, prNumber,
2065
2102
  estimated: result.tokensEstimated
2066
2103
  };
2067
2104
  }
2068
- const sanitizedReview = appendContributorAttribution(sanitizeTokens(reviewText), githubUsername);
2105
+ const sanitizedReview = sanitizeTokens(reviewText);
2069
2106
  await withRetry(
2070
2107
  () => client.post(`/api/tasks/${taskId}/result`, {
2071
2108
  agent_id: agentId,
@@ -2088,7 +2125,8 @@ async function executeReviewTask(client, agentId, taskId, owner, repo, prNumber,
2088
2125
  logger.log(` ${icons.success} Review submitted (${tokensUsed.toLocaleString()} tokens)`);
2089
2126
  logger.log(formatPostReviewStats(consumptionDeps.session));
2090
2127
  }
2091
- async function executeSummaryTask(client, agentId, taskId, owner, repo, prNumber, diffContent, prompt, timeoutSeconds, reviews, reviewDeps, consumptionDeps, logger, routerRelay, signal, contextBlock, githubUsername) {
2128
+ async function executeSummaryTask(client, agentId, taskId, owner, repo, prNumber, diffContent, prompt, timeoutSeconds, reviews, reviewDeps, consumptionDeps, logger, agentInfo, routerRelay, signal, contextBlock, githubUsername) {
2129
+ const meta = { model: agentInfo.model, tool: agentInfo.tool, githubUsername };
2092
2130
  if (reviews.length === 0) {
2093
2131
  let reviewText;
2094
2132
  let verdict;
@@ -2132,7 +2170,8 @@ async function executeSummaryTask(client, agentId, taskId, owner, repo, prNumber
2132
2170
  prNumber,
2133
2171
  timeout: timeoutSeconds,
2134
2172
  reviewMode: "full",
2135
- contextBlock
2173
+ contextBlock,
2174
+ meta
2136
2175
  },
2137
2176
  reviewDeps
2138
2177
  );
@@ -2146,10 +2185,7 @@ async function executeSummaryTask(client, agentId, taskId, owner, repo, prNumber
2146
2185
  estimated: result.tokensEstimated
2147
2186
  };
2148
2187
  }
2149
- const sanitizedReview = appendContributorAttribution(
2150
- sanitizeTokens(reviewText),
2151
- githubUsername
2152
- );
2188
+ const sanitizedReview = sanitizeTokens(reviewText);
2153
2189
  await withRetry(
2154
2190
  () => client.post(`/api/tasks/${taskId}/result`, {
2155
2191
  agent_id: agentId,
@@ -2221,7 +2257,8 @@ async function executeSummaryTask(client, agentId, taskId, owner, repo, prNumber
2221
2257
  prNumber,
2222
2258
  timeout: timeoutSeconds,
2223
2259
  diffContent,
2224
- contextBlock
2260
+ contextBlock,
2261
+ meta
2225
2262
  },
2226
2263
  reviewDeps
2227
2264
  );
@@ -2234,10 +2271,7 @@ async function executeSummaryTask(client, agentId, taskId, owner, repo, prNumber
2234
2271
  estimated: result.tokensEstimated
2235
2272
  };
2236
2273
  }
2237
- const sanitizedSummary = appendContributorAttribution(
2238
- sanitizeTokens(summaryText),
2239
- githubUsername
2240
- );
2274
+ const sanitizedSummary = sanitizeTokens(summaryText);
2241
2275
  await withRetry(
2242
2276
  () => client.post(`/api/tasks/${taskId}/result`, {
2243
2277
  agent_id: agentId,
@@ -2529,7 +2563,7 @@ agentCommand.command("start").description("Start agents in polling mode").option
2529
2563
  });
2530
2564
 
2531
2565
  // src/index.ts
2532
- var program = new Command2().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.15.1");
2566
+ var program = new Command2().name("opencara").description("OpenCara \u2014 distributed AI code review agent").version("0.15.2");
2533
2567
  program.addCommand(agentCommand);
2534
2568
  program.action(() => {
2535
2569
  startAgentRouter();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencara",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
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",