@weareikko/code-review 0.8.6 → 0.9.0
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/{cli-BbR1oftT.js → cli-DK0kteLL.js} +255 -173
- package/dist/cli-DK0kteLL.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/diagnostics.d.ts +11 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/gitlab-review.d.ts +9 -0
- package/dist/gitlab-review.d.ts.map +1 -1
- package/dist/otel.d.ts +4 -4
- package/dist/otel.d.ts.map +1 -1
- package/dist/review.js +1 -1
- package/package.json +1 -1
- package/dist/cli-BbR1oftT.js.map +0 -1
|
@@ -560,7 +560,7 @@ function buildSummaryBody(summary, costFooter, options = {}) {
|
|
|
560
560
|
return `${withFooter}\n\n${buildSummaryHistoryBlock(historyEntries)}`;
|
|
561
561
|
}
|
|
562
562
|
function buildReviewedCommitFooter(commitSha) {
|
|
563
|
-
return `Reviewed by ${PRODUCT_LINK} v0.
|
|
563
|
+
return `Reviewed by ${PRODUCT_LINK} v0.9.0 for commit ${commitSha}.`;
|
|
564
564
|
}
|
|
565
565
|
function extractReviewedCommitSha(body) {
|
|
566
566
|
return REVIEWED_COMMIT_FOOTER_PATTERN.exec(body)?.[1] ?? null;
|
|
@@ -1359,6 +1359,7 @@ function createDiagnosticContext(phase, config, runId, overrides = {}) {
|
|
|
1359
1359
|
project: config.project,
|
|
1360
1360
|
mr: config.mr,
|
|
1361
1361
|
gitlabUrl: config.gitlabUrl,
|
|
1362
|
+
platform: config.platform,
|
|
1362
1363
|
cwd: config.cwd,
|
|
1363
1364
|
model: config.model,
|
|
1364
1365
|
minSeverity: config.minSeverity,
|
|
@@ -4354,54 +4355,59 @@ async function runReview(config, options) {
|
|
|
4354
4355
|
attachTelemetry: options.attachTelemetry,
|
|
4355
4356
|
verifyStaged: diskMode ? retrievableSkipped : void 0
|
|
4356
4357
|
};
|
|
4358
|
+
const buildUsage = () => ({
|
|
4359
|
+
model: config.model,
|
|
4360
|
+
thinkingLevel: config.thinkingLevel,
|
|
4361
|
+
tokens: aggregated.tokens,
|
|
4362
|
+
cost: aggregated.cost,
|
|
4363
|
+
byModel: buildByModelUsage(aggregated),
|
|
4364
|
+
skills: context.skills.map((s) => s.name),
|
|
4365
|
+
sizeNotice
|
|
4366
|
+
});
|
|
4357
4367
|
let outputText;
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
const detachTelemetry = options.attachTelemetry?.(findAgent);
|
|
4370
|
-
let turnCount = 0;
|
|
4371
|
-
let toolCallCount = 0;
|
|
4372
|
-
let finalText;
|
|
4373
|
-
try {
|
|
4374
|
-
finalText = await runAgentToCompletion(findAgent, userPrompt, {
|
|
4375
|
-
timeoutMs,
|
|
4376
|
-
onAssistantMessage: (message) => accumulateUsage(aggregated, message, primary.id),
|
|
4377
|
-
onTurnStart: (turn) => {
|
|
4378
|
-
turnCount = turn;
|
|
4379
|
-
logger.debug(`Turn ${turn} started`);
|
|
4380
|
-
},
|
|
4381
|
-
onToolStart: (toolName, args) => {
|
|
4382
|
-
toolCallCount += 1;
|
|
4383
|
-
logger.debug(` → ${toolName}${formatToolArgs(toolName, args)}`);
|
|
4384
|
-
}
|
|
4368
|
+
try {
|
|
4369
|
+
if (config.reviewDepth === "full") {
|
|
4370
|
+
const { findings, summary } = await runMultiAngleFind(context, minSeverity, userPrompt, deps);
|
|
4371
|
+
outputText = await verifyAndSynthesize(findings, summary, diff, options.commitLog, deps);
|
|
4372
|
+
} else {
|
|
4373
|
+
const findAgent = createAgent({
|
|
4374
|
+
systemPrompt,
|
|
4375
|
+
model: primary.model,
|
|
4376
|
+
tools,
|
|
4377
|
+
thinkingLevel: config.thinkingLevel,
|
|
4378
|
+
getApiKey: primary.getApiKey
|
|
4385
4379
|
});
|
|
4386
|
-
|
|
4387
|
-
|
|
4380
|
+
const detachTelemetry = options.attachTelemetry?.(findAgent);
|
|
4381
|
+
let turnCount = 0;
|
|
4382
|
+
let toolCallCount = 0;
|
|
4383
|
+
let finalText;
|
|
4384
|
+
try {
|
|
4385
|
+
finalText = await runAgentToCompletion(findAgent, userPrompt, {
|
|
4386
|
+
timeoutMs,
|
|
4387
|
+
onAssistantMessage: (message) => accumulateUsage(aggregated, message, primary.id),
|
|
4388
|
+
onTurnStart: (turn) => {
|
|
4389
|
+
turnCount = turn;
|
|
4390
|
+
logger.debug(`Turn ${turn} started`);
|
|
4391
|
+
},
|
|
4392
|
+
onToolStart: (toolName, args) => {
|
|
4393
|
+
toolCallCount += 1;
|
|
4394
|
+
logger.debug(` → ${toolName}${formatToolArgs(toolName, args)}`);
|
|
4395
|
+
}
|
|
4396
|
+
});
|
|
4397
|
+
} finally {
|
|
4398
|
+
detachTelemetry?.();
|
|
4399
|
+
}
|
|
4400
|
+
logger.debug(`Agent finished: ${turnCount} turn(s), ${toolCallCount} tool call(s)`);
|
|
4401
|
+
outputText = config.reviewDepth === "verify" ? await runVerifyStage(finalText, diff, options.commitLog, deps) : finalText;
|
|
4388
4402
|
}
|
|
4389
|
-
|
|
4390
|
-
|
|
4403
|
+
} finally {
|
|
4404
|
+
options.onUsage?.(buildUsage());
|
|
4391
4405
|
}
|
|
4392
4406
|
const reviewPath = resolve(cwd, config.reviewFile);
|
|
4393
4407
|
await mkdir(dirname(reviewPath), { recursive: true });
|
|
4394
4408
|
await writeFile(reviewPath, outputText, "utf8");
|
|
4395
4409
|
if (retrievableSkipped.length > 0) await cleanupSkippedDiffs(cwd);
|
|
4396
|
-
return
|
|
4397
|
-
model: config.model,
|
|
4398
|
-
thinkingLevel: config.thinkingLevel,
|
|
4399
|
-
tokens: aggregated.tokens,
|
|
4400
|
-
cost: aggregated.cost,
|
|
4401
|
-
byModel: buildByModelUsage(aggregated),
|
|
4402
|
-
skills: context.skills.map((s) => s.name),
|
|
4403
|
-
sizeNotice
|
|
4404
|
-
};
|
|
4410
|
+
return buildUsage();
|
|
4405
4411
|
}
|
|
4406
4412
|
/**
|
|
4407
4413
|
* Convert the per-model usage buckets into the public {@link ModelUsage} array,
|
|
@@ -4758,13 +4764,13 @@ async function startOtelBridge(options = {}) {
|
|
|
4758
4764
|
unit: "{token}",
|
|
4759
4765
|
advice: { explicitBucketBoundaries: TOKEN_BUCKETS }
|
|
4760
4766
|
});
|
|
4761
|
-
const operationCost = meter.createHistogram("
|
|
4762
|
-
description: "
|
|
4767
|
+
const operationCost = meter.createHistogram("code_review_llm_cost_usd", {
|
|
4768
|
+
description: "LLM cost in USD per turn, by token type (non-standard extension)",
|
|
4763
4769
|
unit: "{usd}",
|
|
4764
4770
|
advice: { explicitBucketBoundaries: COST_BUCKETS_USD }
|
|
4765
4771
|
});
|
|
4766
|
-
const timeToFirstToken = meter.createHistogram("gen_ai.client.
|
|
4767
|
-
description: "Time to first
|
|
4772
|
+
const timeToFirstToken = meter.createHistogram("gen_ai.client.operation.time_to_first_chunk", {
|
|
4773
|
+
description: "Time to first chunk from the LLM",
|
|
4768
4774
|
unit: "s",
|
|
4769
4775
|
advice: { explicitBucketBoundaries: TTFT_BUCKETS_S }
|
|
4770
4776
|
});
|
|
@@ -4804,6 +4810,9 @@ async function startOtelBridge(options = {}) {
|
|
|
4804
4810
|
ciAttrs,
|
|
4805
4811
|
ciSpanAttrs,
|
|
4806
4812
|
model: ctx.model,
|
|
4813
|
+
dryRun: ctx.dryRun,
|
|
4814
|
+
platform: ctx.platform,
|
|
4815
|
+
serverAddress: hostOf(ctx.gitlabUrl),
|
|
4807
4816
|
rootSpanCtx
|
|
4808
4817
|
});
|
|
4809
4818
|
emitReviewStartedLog(logger, ctx, ciAttrs, ciSpanAttrs, rootSpanCtx);
|
|
@@ -4835,50 +4844,55 @@ async function startOtelBridge(options = {}) {
|
|
|
4835
4844
|
entry.span.end();
|
|
4836
4845
|
entry.closed = true;
|
|
4837
4846
|
const status = resolveRunStatus(ctx, isError);
|
|
4838
|
-
const projectPath = ciAttrs["
|
|
4847
|
+
const projectPath = ciAttrs["vcs.repository.name"] ?? "";
|
|
4848
|
+
const vcs = vcsAttrs(ctx.platform, ctx.gitlabUrl);
|
|
4839
4849
|
if (typeof ctx.durationMs === "number") reviewPhaseDuration.record(ctx.durationMs / 1e3, {
|
|
4840
4850
|
...REVIEW_SERVICE_ATTRS,
|
|
4841
|
-
|
|
4842
|
-
"
|
|
4843
|
-
"
|
|
4851
|
+
...vcs,
|
|
4852
|
+
"vcs.repository.name": projectPath,
|
|
4853
|
+
"code_review.phase": ctx.phase,
|
|
4854
|
+
"code_review.status": status
|
|
4844
4855
|
});
|
|
4845
4856
|
if (ctx.phase === ROOT_PHASE) {
|
|
4846
4857
|
const meta = runMeta.get(ctx.runId);
|
|
4847
|
-
const pipelineSource = ciAttrs["
|
|
4858
|
+
const pipelineSource = ciAttrs["cicd.pipeline.source"] ?? "";
|
|
4848
4859
|
const runMetricBase = {
|
|
4849
4860
|
...REVIEW_SERVICE_ATTRS,
|
|
4850
|
-
|
|
4851
|
-
"
|
|
4861
|
+
...vcs,
|
|
4862
|
+
"vcs.repository.name": projectPath,
|
|
4863
|
+
"code_review.dry_run": ctx.dryRun,
|
|
4864
|
+
...ctx.firstReview !== void 0 ? { "code_review.first_review": ctx.firstReview } : {}
|
|
4852
4865
|
};
|
|
4853
4866
|
const usage = meta?.usage ?? ctx.usage;
|
|
4854
4867
|
const runModelAttrs = genAiModelAttrs(void 0, splitModel(usage?.model ?? "").modelId);
|
|
4855
4868
|
reviewRunsTotal.add(1, {
|
|
4856
4869
|
...runMetricBase,
|
|
4857
|
-
"
|
|
4858
|
-
"
|
|
4870
|
+
"cicd.pipeline.source": pipelineSource,
|
|
4871
|
+
"code_review.status": status
|
|
4859
4872
|
});
|
|
4860
4873
|
if (isError) reviewErrorsTotal.add(1, {
|
|
4861
4874
|
...runMetricBase,
|
|
4862
|
-
"
|
|
4875
|
+
"code_review.status": status,
|
|
4863
4876
|
"error.type": errorTypeOf(ctx)
|
|
4864
4877
|
});
|
|
4865
4878
|
if (typeof ctx.durationMs === "number") reviewRunDuration.record(ctx.durationMs / 1e3, {
|
|
4866
4879
|
...runMetricBase,
|
|
4867
4880
|
...runModelAttrs,
|
|
4868
|
-
"
|
|
4869
|
-
"
|
|
4881
|
+
"cicd.pipeline.source": pipelineSource,
|
|
4882
|
+
"code_review.status": status
|
|
4870
4883
|
});
|
|
4871
4884
|
const totalCostUsd = usage?.cost.total;
|
|
4872
4885
|
if (totalCostUsd !== void 0) reviewTotalCost.record(totalCostUsd, {
|
|
4873
4886
|
...runMetricBase,
|
|
4874
4887
|
...runModelAttrs,
|
|
4875
|
-
"
|
|
4888
|
+
"code_review.status": status
|
|
4876
4889
|
});
|
|
4877
4890
|
if (usage) {
|
|
4878
4891
|
const tokenAttrs = {
|
|
4879
4892
|
...REVIEW_SERVICE_ATTRS,
|
|
4880
4893
|
...runModelAttrs,
|
|
4881
|
-
|
|
4894
|
+
...vcs,
|
|
4895
|
+
"vcs.repository.name": projectPath
|
|
4882
4896
|
};
|
|
4883
4897
|
for (const [field, type] of [
|
|
4884
4898
|
["input", "input"],
|
|
@@ -4894,7 +4908,7 @@ async function startOtelBridge(options = {}) {
|
|
|
4894
4908
|
if (bySeverity) {
|
|
4895
4909
|
for (const [severity, count] of Object.entries(bySeverity)) if (count && count > 0) reviewCommentsTotal.add(count, {
|
|
4896
4910
|
...runMetricBase,
|
|
4897
|
-
"
|
|
4911
|
+
"code_review.comment.severity": severity
|
|
4898
4912
|
});
|
|
4899
4913
|
} else {
|
|
4900
4914
|
const posted = ctx.posted ?? 0;
|
|
@@ -4940,16 +4954,17 @@ async function startOtelBridge(options = {}) {
|
|
|
4940
4954
|
context: meta?.rootSpanCtx,
|
|
4941
4955
|
attributes: {
|
|
4942
4956
|
"service.name": SERVICE_NAME,
|
|
4943
|
-
"event.name": "
|
|
4944
|
-
"
|
|
4945
|
-
"
|
|
4946
|
-
"
|
|
4947
|
-
"
|
|
4948
|
-
"
|
|
4957
|
+
"event.name": "code_review.comment",
|
|
4958
|
+
"code_review.run_id": runId,
|
|
4959
|
+
"code_review.comment.file": comment.file,
|
|
4960
|
+
"code_review.comment.line": comment.line,
|
|
4961
|
+
"code_review.comment.severity": comment.severity,
|
|
4962
|
+
"code_review.comment.is_duplicate": duplicate,
|
|
4949
4963
|
...meta && {
|
|
4950
|
-
"
|
|
4951
|
-
"
|
|
4952
|
-
"
|
|
4964
|
+
"vcs.repository.id": meta.project,
|
|
4965
|
+
"vcs.change.id": meta.mr,
|
|
4966
|
+
...meta.platform ? { "vcs.provider.name": meta.platform } : {},
|
|
4967
|
+
...meta.serverAddress ? { "server.address": meta.serverAddress } : {},
|
|
4953
4968
|
...meta.ciAttrs,
|
|
4954
4969
|
...meta.ciSpanAttrs
|
|
4955
4970
|
}
|
|
@@ -4964,20 +4979,30 @@ async function startOtelBridge(options = {}) {
|
|
|
4964
4979
|
ciAttrs,
|
|
4965
4980
|
runId,
|
|
4966
4981
|
configuredModel: runMeta.get(runId)?.model,
|
|
4982
|
+
dryRun: runMeta.get(runId)?.dryRun,
|
|
4983
|
+
platform: runMeta.get(runId)?.platform,
|
|
4984
|
+
serverAddress: runMeta.get(runId)?.serverAddress,
|
|
4967
4985
|
captureContent
|
|
4968
4986
|
});
|
|
4969
4987
|
}
|
|
4970
4988
|
};
|
|
4971
4989
|
}
|
|
4972
4990
|
/**
|
|
4973
|
-
* Builds the dynamic `gen_ai.
|
|
4974
|
-
* shared by the per-turn and per-phase GenAI metric emitters. Owning
|
|
4975
|
-
* one place keeps the two emission sites from drifting into separate
|
|
4976
|
-
* series (the double-count `recordGenAiMetrics` documents).
|
|
4991
|
+
* Builds the dynamic `gen_ai.provider.name` / `gen_ai.request.model` metric
|
|
4992
|
+
* labels shared by the per-turn and per-phase GenAI metric emitters. Owning
|
|
4993
|
+
* these in one place keeps the two emission sites from drifting into separate
|
|
4994
|
+
* Prometheus series (the double-count `recordGenAiMetrics` documents).
|
|
4995
|
+
*
|
|
4996
|
+
* `gen_ai.provider.name` is the current GenAI-semconv discriminator; the
|
|
4997
|
+
* deprecated `gen_ai.system` is emitted alongside it during the transition so
|
|
4998
|
+
* backends still keyed on the old attribute keep working.
|
|
4977
4999
|
*/
|
|
4978
5000
|
function genAiModelAttrs(provider, modelId) {
|
|
4979
5001
|
return {
|
|
4980
|
-
...provider ? {
|
|
5002
|
+
...provider ? {
|
|
5003
|
+
"gen_ai.provider.name": provider,
|
|
5004
|
+
"gen_ai.system": provider
|
|
5005
|
+
} : {},
|
|
4981
5006
|
...modelId ? { "gen_ai.request.model": modelId } : {}
|
|
4982
5007
|
};
|
|
4983
5008
|
}
|
|
@@ -5033,9 +5058,9 @@ function recordTurnUsage(span, u, metricAttrs, tokenUsage, operationCost) {
|
|
|
5033
5058
|
...metricAttrs,
|
|
5034
5059
|
"gen_ai.token.type": "cache_creation"
|
|
5035
5060
|
});
|
|
5036
|
-
span.setAttribute("
|
|
5037
|
-
span.setAttribute("
|
|
5038
|
-
span.setAttribute("
|
|
5061
|
+
span.setAttribute("code_review.cost.input_usd", u.cost.input);
|
|
5062
|
+
span.setAttribute("code_review.cost.output_usd", u.cost.output);
|
|
5063
|
+
span.setAttribute("code_review.cost.total_usd", u.cost.total);
|
|
5039
5064
|
}
|
|
5040
5065
|
}
|
|
5041
5066
|
/**
|
|
@@ -5099,12 +5124,15 @@ function extractOutputMessages(msg) {
|
|
|
5099
5124
|
}]);
|
|
5100
5125
|
}
|
|
5101
5126
|
function buildAgentSubscriber(tracer, tokenUsage, operationCost, timeToFirstToken, reviewerSpanCtx, options = {}) {
|
|
5102
|
-
const { ciAttrs = {}, runId, configuredModel, captureContent = false } = options;
|
|
5127
|
+
const { ciAttrs = {}, runId, configuredModel, dryRun, platform, serverAddress, captureContent = false } = options;
|
|
5103
5128
|
const configuredProvider = configuredModel ? splitModel(configuredModel).provider : void 0;
|
|
5104
5129
|
const baseMetricAttrs = {
|
|
5105
5130
|
"gen_ai.operation.name": "invoke_agent",
|
|
5106
5131
|
...REVIEW_SERVICE_ATTRS,
|
|
5107
|
-
...ciAttrs
|
|
5132
|
+
...ciAttrs,
|
|
5133
|
+
...dryRun !== void 0 ? { "code_review.dry_run": dryRun } : {},
|
|
5134
|
+
...platform ? { "vcs.provider.name": platform } : {},
|
|
5135
|
+
...serverAddress ? { "server.address": serverAddress } : {}
|
|
5108
5136
|
};
|
|
5109
5137
|
return (agent) => {
|
|
5110
5138
|
let currentTurn;
|
|
@@ -5138,13 +5166,16 @@ function buildAgentSubscriber(tracer, tokenUsage, operationCost, timeToFirstToke
|
|
|
5138
5166
|
...baseMetricAttrs,
|
|
5139
5167
|
...genAiModelAttrs(provider, modelId)
|
|
5140
5168
|
};
|
|
5141
|
-
if (provider)
|
|
5169
|
+
if (provider) {
|
|
5170
|
+
span.setAttribute("gen_ai.provider.name", provider);
|
|
5171
|
+
span.setAttribute("gen_ai.system", provider);
|
|
5172
|
+
}
|
|
5142
5173
|
if (modelId) span.setAttribute("gen_ai.response.model", modelId);
|
|
5143
5174
|
if (msg.stopReason) span.setAttribute("gen_ai.response.stop_reason", msg.stopReason);
|
|
5144
5175
|
if (firstTokenMs !== void 0) {
|
|
5145
5176
|
const ttftS = (firstTokenMs - startMs) / 1e3;
|
|
5146
5177
|
timeToFirstToken.record(ttftS, metricAttrs);
|
|
5147
|
-
span.setAttribute("gen_ai.client.
|
|
5178
|
+
span.setAttribute("gen_ai.client.operation.time_to_first_chunk_s", ttftS);
|
|
5148
5179
|
}
|
|
5149
5180
|
if (msg.usage) recordTurnUsage(span, msg.usage, metricAttrs, tokenUsage, operationCost);
|
|
5150
5181
|
if (captureContent) {
|
|
@@ -5215,7 +5246,7 @@ async function loadDefaultRuntime() {
|
|
|
5215
5246
|
const [sdkNode, resources, semconv] = modules;
|
|
5216
5247
|
const serviceResource = resources.resourceFromAttributes({
|
|
5217
5248
|
[semconv.ATTR_SERVICE_NAME ?? "service.name"]: SERVICE_NAME,
|
|
5218
|
-
[semconv.ATTR_SERVICE_VERSION ?? "service.version"]: "0.
|
|
5249
|
+
[semconv.ATTR_SERVICE_VERSION ?? "service.version"]: "0.9.0"
|
|
5219
5250
|
});
|
|
5220
5251
|
process.env.OTEL_METRICS_EXPORTER = process.env.OTEL_METRICS_EXPORTER ?? "otlp";
|
|
5221
5252
|
process.env.OTEL_LOGS_EXPORTER = process.env.OTEL_LOGS_EXPORTER ?? "otlp";
|
|
@@ -5237,14 +5268,14 @@ function emitReviewStartedLog(logger, ctx, ciAttrs, ciSpanAttrs, rootSpanCtx) {
|
|
|
5237
5268
|
context: rootSpanCtx,
|
|
5238
5269
|
attributes: {
|
|
5239
5270
|
"service.name": SERVICE_NAME,
|
|
5240
|
-
"event.name": "
|
|
5241
|
-
"
|
|
5242
|
-
"
|
|
5243
|
-
|
|
5271
|
+
"event.name": "code_review.started",
|
|
5272
|
+
"vcs.repository.id": ctx.project,
|
|
5273
|
+
"vcs.change.id": ctx.mr,
|
|
5274
|
+
...vcsAttrs(ctx.platform, ctx.gitlabUrl),
|
|
5244
5275
|
...ciAttrs,
|
|
5245
5276
|
...ciSpanAttrs,
|
|
5246
|
-
"
|
|
5247
|
-
"
|
|
5277
|
+
"code_review.run_id": ctx.runId,
|
|
5278
|
+
"code_review.dry_run": ctx.dryRun,
|
|
5248
5279
|
...modelId !== void 0 && { "gen_ai.request.model": modelId }
|
|
5249
5280
|
}
|
|
5250
5281
|
});
|
|
@@ -5264,10 +5295,10 @@ function emitReviewCompletedLog(logger, ctx, meta, isError) {
|
|
|
5264
5295
|
context: meta?.rootSpanCtx,
|
|
5265
5296
|
attributes: {
|
|
5266
5297
|
"service.name": SERVICE_NAME,
|
|
5267
|
-
"event.name": isError ? "
|
|
5268
|
-
"
|
|
5269
|
-
"
|
|
5270
|
-
|
|
5298
|
+
"event.name": isError ? "code_review.failed" : "code_review.completed",
|
|
5299
|
+
"vcs.repository.id": ctx.project,
|
|
5300
|
+
"vcs.change.id": ctx.mr,
|
|
5301
|
+
...vcsAttrs(ctx.platform, ctx.gitlabUrl),
|
|
5271
5302
|
...meta?.ciAttrs,
|
|
5272
5303
|
...meta?.ciSpanAttrs,
|
|
5273
5304
|
...isError && {
|
|
@@ -5275,15 +5306,15 @@ function emitReviewCompletedLog(logger, ctx, meta, isError) {
|
|
|
5275
5306
|
...ctx.errorInfo && { "error.message": ctx.errorInfo.message },
|
|
5276
5307
|
...typeof ctx.errorInfo?.status === "number" && { "http.response.status_code": ctx.errorInfo.status }
|
|
5277
5308
|
},
|
|
5278
|
-
"
|
|
5279
|
-
"
|
|
5280
|
-
"
|
|
5281
|
-
"
|
|
5282
|
-
"
|
|
5283
|
-
"
|
|
5284
|
-
"
|
|
5309
|
+
"code_review.run_id": ctx.runId,
|
|
5310
|
+
"code_review.duration_ms": ctx.durationMs ?? 0,
|
|
5311
|
+
"code_review.dry_run": ctx.dryRun,
|
|
5312
|
+
"code_review.comments.generated": ctx.generated ?? 0,
|
|
5313
|
+
"code_review.comments.new": ctx.newComments ?? 0,
|
|
5314
|
+
"code_review.comments.duplicate": ctx.duplicateComments ?? 0,
|
|
5315
|
+
"code_review.comments.posted": ctx.posted ?? 0,
|
|
5285
5316
|
...modelId !== void 0 && { "gen_ai.request.model": modelId },
|
|
5286
|
-
...cost !== void 0 && { "
|
|
5317
|
+
...cost !== void 0 && { "code_review.cost.total_usd": cost },
|
|
5287
5318
|
...usage?.tokens.input !== void 0 && { "gen_ai.usage.input_tokens": usage.tokens.input + (usage.tokens.cacheRead ?? 0) },
|
|
5288
5319
|
...usage?.tokens.cacheRead && {
|
|
5289
5320
|
"gen_ai.usage.input_tokens.cached": usage.tokens.cacheRead,
|
|
@@ -5302,39 +5333,39 @@ function spanNameFor(phase) {
|
|
|
5302
5333
|
/** Creates the review-level OTel metric instruments on the given meter. */
|
|
5303
5334
|
function createReviewInstruments(meter) {
|
|
5304
5335
|
return {
|
|
5305
|
-
reviewRunsTotal: meter.createCounter("
|
|
5306
|
-
reviewErrorsTotal: meter.createCounter("
|
|
5336
|
+
reviewRunsTotal: meter.createCounter("code_review_runs_total", { description: "Total number of code-review runs, labelled by terminal status" }),
|
|
5337
|
+
reviewErrorsTotal: meter.createCounter("code_review_errors_total", { description: "Total number of failed code-review runs, labelled by error type" }),
|
|
5307
5338
|
reviewLlmTokens: {
|
|
5308
|
-
input: meter.createCounter("
|
|
5339
|
+
input: meter.createCounter("code_review_llm_input_tokens_total", {
|
|
5309
5340
|
description: "Total non-cached LLM input tokens consumed across code-review runs",
|
|
5310
5341
|
unit: "{token}"
|
|
5311
5342
|
}),
|
|
5312
|
-
output: meter.createCounter("
|
|
5343
|
+
output: meter.createCounter("code_review_llm_output_tokens_total", {
|
|
5313
5344
|
description: "Total LLM output tokens generated across code-review runs",
|
|
5314
5345
|
unit: "{token}"
|
|
5315
5346
|
}),
|
|
5316
|
-
cache_read: meter.createCounter("
|
|
5347
|
+
cache_read: meter.createCounter("code_review_llm_cache_read_tokens_total", {
|
|
5317
5348
|
description: "Total LLM cache-read input tokens across code-review runs",
|
|
5318
5349
|
unit: "{token}"
|
|
5319
5350
|
}),
|
|
5320
|
-
cache_creation: meter.createCounter("
|
|
5351
|
+
cache_creation: meter.createCounter("code_review_llm_cache_creation_tokens_total", {
|
|
5321
5352
|
description: "Total LLM cache-creation input tokens across code-review runs",
|
|
5322
5353
|
unit: "{token}"
|
|
5323
5354
|
})
|
|
5324
5355
|
},
|
|
5325
|
-
reviewRunDuration: meter.createHistogram("
|
|
5356
|
+
reviewRunDuration: meter.createHistogram("code_review_run_duration_seconds", {
|
|
5326
5357
|
description: "Duration of a complete code-review run",
|
|
5327
5358
|
unit: "s",
|
|
5328
5359
|
advice: { explicitBucketBoundaries: REVIEW_RUN_DURATION_BUCKETS_S }
|
|
5329
5360
|
}),
|
|
5330
|
-
reviewTotalCost: meter.createHistogram("
|
|
5361
|
+
reviewTotalCost: meter.createHistogram("code_review_total_cost_usd", {
|
|
5331
5362
|
description: "Total LLM cost in USD for a complete code-review run",
|
|
5332
5363
|
unit: "{usd}",
|
|
5333
5364
|
advice: { explicitBucketBoundaries: REVIEW_TOTAL_COST_BUCKETS_USD }
|
|
5334
5365
|
}),
|
|
5335
|
-
reviewCommentsTotal: meter.createCounter("
|
|
5336
|
-
reviewDraftsPublishedTotal: meter.createCounter("
|
|
5337
|
-
reviewPhaseDuration: meter.createHistogram("
|
|
5366
|
+
reviewCommentsTotal: meter.createCounter("code_review_comments_total", { description: "Total number of MR comments posted by code-review" }),
|
|
5367
|
+
reviewDraftsPublishedTotal: meter.createCounter("code_review_drafts_published_total", { description: "Total number of draft notes published by code-review" }),
|
|
5368
|
+
reviewPhaseDuration: meter.createHistogram("code_review_phase_duration_seconds", {
|
|
5338
5369
|
description: "Duration of individual code-review workflow phases",
|
|
5339
5370
|
unit: "s",
|
|
5340
5371
|
advice: { explicitBucketBoundaries: REVIEW_PHASE_DURATION_BUCKETS_S }
|
|
@@ -5358,7 +5389,7 @@ function errorTypeOf(ctx) {
|
|
|
5358
5389
|
return base;
|
|
5359
5390
|
}
|
|
5360
5391
|
/**
|
|
5361
|
-
* Derives the `
|
|
5392
|
+
* Derives the `code_review.status` label used by review-level OTel metrics.
|
|
5362
5393
|
* Distinguishes timeouts (AbortError / ETIMEDOUT) from generic errors so
|
|
5363
5394
|
* Grafana alerts can treat deadline-exceeded runs separately.
|
|
5364
5395
|
*/
|
|
@@ -5369,55 +5400,91 @@ function resolveRunStatus(ctx, isError) {
|
|
|
5369
5400
|
return "error";
|
|
5370
5401
|
}
|
|
5371
5402
|
/**
|
|
5372
|
-
* Extracts
|
|
5373
|
-
*
|
|
5374
|
-
*
|
|
5403
|
+
* Extracts low-cardinality CI project/pipeline context (repository, owner, base
|
|
5404
|
+
* branch, pipeline trigger) as platform-neutral `vcs.*` / `cicd.*` attributes
|
|
5405
|
+
* added to every metric, span, and log record. Sourced from GitLab CI or GitHub
|
|
5406
|
+
* Actions variables — a run is one or the other, so `??` picks whichever is set;
|
|
5407
|
+
* callers spread the result so missing vars add nothing.
|
|
5375
5408
|
*/
|
|
5376
5409
|
function buildCiAttrs(env) {
|
|
5377
5410
|
const attrs = {};
|
|
5378
|
-
|
|
5379
|
-
if (
|
|
5380
|
-
|
|
5381
|
-
if (
|
|
5411
|
+
const repository = env.CI_PROJECT_PATH ?? env.GITHUB_REPOSITORY;
|
|
5412
|
+
if (repository) attrs["vcs.repository.name"] = repository;
|
|
5413
|
+
const owner = env.CI_PROJECT_NAMESPACE ?? env.GITHUB_REPOSITORY_OWNER;
|
|
5414
|
+
if (owner) attrs["vcs.owner.name"] = owner;
|
|
5415
|
+
const baseRef = env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME ?? env.GITHUB_BASE_REF;
|
|
5416
|
+
if (baseRef) attrs["vcs.ref.base.name"] = baseRef;
|
|
5417
|
+
const pipelineSource = env.CI_PIPELINE_SOURCE ?? env.GITHUB_EVENT_NAME;
|
|
5418
|
+
if (pipelineSource) attrs["cicd.pipeline.source"] = pipelineSource;
|
|
5382
5419
|
return attrs;
|
|
5383
5420
|
}
|
|
5384
5421
|
/**
|
|
5385
|
-
* Extracts high-cardinality
|
|
5386
|
-
*
|
|
5387
|
-
* Prometheus/Mimir).
|
|
5422
|
+
* Extracts high-cardinality CI identifiers that should appear on spans and log
|
|
5423
|
+
* records but NOT on metric data points (to avoid label explosion in
|
|
5424
|
+
* Prometheus/Mimir). Sourced from GitLab CI or GitHub Actions. GitHub exposes no
|
|
5425
|
+
* per-job run id in the environment, so the job's config-key (`GITHUB_JOB`) is
|
|
5426
|
+
* used for the task identifier. Spread via `ciSpanAttrs` stored in RunMeta.
|
|
5388
5427
|
*/
|
|
5389
5428
|
function buildCiSpanAttrs(env) {
|
|
5390
5429
|
const attrs = {};
|
|
5391
|
-
|
|
5392
|
-
if (
|
|
5430
|
+
const taskRunId = env.CI_JOB_ID ?? env.GITHUB_JOB;
|
|
5431
|
+
if (taskRunId) attrs["cicd.pipeline.task.run.id"] = taskRunId;
|
|
5432
|
+
const pipelineRunId = env.CI_PIPELINE_ID ?? env.GITHUB_RUN_ID;
|
|
5433
|
+
if (pipelineRunId) attrs["cicd.pipeline.run.id"] = pipelineRunId;
|
|
5434
|
+
const repositoryUrl = env.CI_PROJECT_URL ?? (env.GITHUB_SERVER_URL && env.GITHUB_REPOSITORY ? `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}` : void 0);
|
|
5435
|
+
if (repositoryUrl) attrs["vcs.repository.url.full"] = repositoryUrl;
|
|
5393
5436
|
return attrs;
|
|
5394
5437
|
}
|
|
5438
|
+
/** Host of a server URL, for the low-cardinality `server.address` instance label. */
|
|
5439
|
+
function hostOf(url) {
|
|
5440
|
+
if (!url) return void 0;
|
|
5441
|
+
try {
|
|
5442
|
+
return new URL(url).host;
|
|
5443
|
+
} catch {
|
|
5444
|
+
return;
|
|
5445
|
+
}
|
|
5446
|
+
}
|
|
5447
|
+
/**
|
|
5448
|
+
* Low-cardinality VCS discriminators added to every metric, span, and log:
|
|
5449
|
+
* `vcs.provider.name` (gitlab | github) to filter by platform, and
|
|
5450
|
+
* `server.address` (the instance host) to distinguish multiple GitLab/GitHub
|
|
5451
|
+
* instances (e.g. gitlab.com vs a self-hosted gitlab.example.com).
|
|
5452
|
+
*/
|
|
5453
|
+
function vcsAttrs(platform, serverUrl) {
|
|
5454
|
+
const host = hostOf(serverUrl);
|
|
5455
|
+
return {
|
|
5456
|
+
...platform ? { "vcs.provider.name": platform } : {},
|
|
5457
|
+
...host ? { "server.address": host } : {}
|
|
5458
|
+
};
|
|
5459
|
+
}
|
|
5395
5460
|
function baseAttributes(ctx) {
|
|
5461
|
+
const host = hostOf(ctx.gitlabUrl);
|
|
5396
5462
|
return {
|
|
5397
|
-
"
|
|
5463
|
+
"code_review.run_id": ctx.runId,
|
|
5398
5464
|
"gen_ai.conversation.id": ctx.runId,
|
|
5399
|
-
"
|
|
5400
|
-
"
|
|
5401
|
-
"
|
|
5402
|
-
"
|
|
5403
|
-
"
|
|
5404
|
-
"
|
|
5405
|
-
"
|
|
5465
|
+
"code_review.phase": ctx.phase,
|
|
5466
|
+
"vcs.repository.id": ctx.project,
|
|
5467
|
+
"vcs.change.id": ctx.mr,
|
|
5468
|
+
...ctx.platform ? { "vcs.provider.name": ctx.platform } : {},
|
|
5469
|
+
...host ? { "server.address": host } : {},
|
|
5470
|
+
"code_review.dry_run": ctx.dryRun,
|
|
5471
|
+
"code_review.no_post": ctx.noPost,
|
|
5472
|
+
"code_review.min_severity": ctx.minSeverity
|
|
5406
5473
|
};
|
|
5407
5474
|
}
|
|
5408
5475
|
var NUMERIC_RESULT_ATTRIBUTES = [
|
|
5409
|
-
["durationMs", "
|
|
5410
|
-
["generated", "
|
|
5411
|
-
["newComments", "
|
|
5412
|
-
["duplicateComments", "
|
|
5413
|
-
["posted", "
|
|
5414
|
-
["draftsPublished", "
|
|
5415
|
-
["draftsCreated", "
|
|
5416
|
-
["summaryNoteId", "
|
|
5417
|
-
["warnings", "
|
|
5418
|
-
["draftsAbandoned", "
|
|
5419
|
-
["draftsDeletedPrePublish", "
|
|
5420
|
-
["draftsPublishFailed", "
|
|
5476
|
+
["durationMs", "code_review.duration_ms"],
|
|
5477
|
+
["generated", "code_review.comments.generated"],
|
|
5478
|
+
["newComments", "code_review.comments.new"],
|
|
5479
|
+
["duplicateComments", "code_review.comments.duplicate"],
|
|
5480
|
+
["posted", "code_review.comments.posted"],
|
|
5481
|
+
["draftsPublished", "code_review.drafts.published"],
|
|
5482
|
+
["draftsCreated", "code_review.drafts.created"],
|
|
5483
|
+
["summaryNoteId", "code_review.summary.note_id"],
|
|
5484
|
+
["warnings", "code_review.warnings"],
|
|
5485
|
+
["draftsAbandoned", "code_review.drafts.abandoned"],
|
|
5486
|
+
["draftsDeletedPrePublish", "code_review.drafts.deleted_pre_publish"],
|
|
5487
|
+
["draftsPublishFailed", "code_review.drafts.publish_failed"],
|
|
5421
5488
|
["diffFilesChanged", "diff.files_changed"],
|
|
5422
5489
|
["diffLinesAdded", "diff.lines_added"],
|
|
5423
5490
|
["diffLinesRemoved", "diff.lines_removed"],
|
|
@@ -5425,7 +5492,7 @@ var NUMERIC_RESULT_ATTRIBUTES = [
|
|
|
5425
5492
|
["httpResponseBodySize", "http.response.body.size"]
|
|
5426
5493
|
];
|
|
5427
5494
|
var STRING_RESULT_ATTRIBUTES = [
|
|
5428
|
-
["summaryAction", "
|
|
5495
|
+
["summaryAction", "code_review.summary.action"],
|
|
5429
5496
|
["httpRequestMethod", "http.request.method"],
|
|
5430
5497
|
["httpUrl", "url.full"],
|
|
5431
5498
|
["serverAddress", "server.address"]
|
|
@@ -5442,7 +5509,10 @@ function applyResultAttributes(span, ctx) {
|
|
|
5442
5509
|
}
|
|
5443
5510
|
function applyGenAiAttributes(span, ctx) {
|
|
5444
5511
|
const { provider, modelId } = splitModel(ctx.model ?? "");
|
|
5445
|
-
if (provider)
|
|
5512
|
+
if (provider) {
|
|
5513
|
+
span.setAttribute("gen_ai.provider.name", provider);
|
|
5514
|
+
span.setAttribute("gen_ai.system", provider);
|
|
5515
|
+
}
|
|
5446
5516
|
if (modelId) {
|
|
5447
5517
|
span.setAttribute("gen_ai.request.model", modelId);
|
|
5448
5518
|
span.setAttribute("gen_ai.response.model", modelId);
|
|
@@ -5452,16 +5522,16 @@ function applyGenAiAttributes(span, ctx) {
|
|
|
5452
5522
|
const usage = ctx.usage;
|
|
5453
5523
|
if (!usage) return;
|
|
5454
5524
|
setTokenUsageSpanAttributes(span, usage.tokens);
|
|
5455
|
-
span.setAttribute("
|
|
5456
|
-
span.setAttribute("
|
|
5457
|
-
span.setAttribute("
|
|
5458
|
-
span.setAttribute("
|
|
5459
|
-
span.setAttribute("
|
|
5525
|
+
span.setAttribute("code_review.cost.input_usd", usage.cost.input);
|
|
5526
|
+
span.setAttribute("code_review.cost.output_usd", usage.cost.output);
|
|
5527
|
+
span.setAttribute("code_review.cost.cache_read_usd", usage.cost.cacheRead);
|
|
5528
|
+
span.setAttribute("code_review.cost.cache_creation_usd", usage.cost.cacheWrite);
|
|
5529
|
+
span.setAttribute("code_review.cost.total_usd", usage.cost.total);
|
|
5460
5530
|
}
|
|
5461
5531
|
/**
|
|
5462
5532
|
* Records `gen_ai.client.operation.duration` for the `reviewer.run` phase.
|
|
5463
5533
|
*
|
|
5464
|
-
* Token usage (`gen_ai.client.token.usage`) and cost (`
|
|
5534
|
+
* Token usage (`gen_ai.client.token.usage`) and cost (`code_review_llm_cost_usd`) are
|
|
5465
5535
|
* intentionally NOT recorded here. They are emitted per-turn by
|
|
5466
5536
|
* `buildAgentSubscriber` from the live agent event stream. Keeping a single
|
|
5467
5537
|
* emission point for each metric prevents the double-count that previously
|
|
@@ -5474,7 +5544,9 @@ function recordGenAiMetrics(durationHist, ctx, isError, ciAttrs = {}) {
|
|
|
5474
5544
|
"gen_ai.operation.name": "invoke_agent",
|
|
5475
5545
|
...REVIEW_SERVICE_ATTRS,
|
|
5476
5546
|
...ciAttrs,
|
|
5477
|
-
...
|
|
5547
|
+
...vcsAttrs(ctx.platform, ctx.gitlabUrl),
|
|
5548
|
+
...genAiModelAttrs(provider, modelId),
|
|
5549
|
+
"code_review.dry_run": ctx.dryRun
|
|
5478
5550
|
};
|
|
5479
5551
|
if (isError) attrs["error.type"] = errorTypeOf(ctx);
|
|
5480
5552
|
if (typeof ctx.durationMs === "number") durationHist.record(ctx.durationMs / 1e3, attrs);
|
|
@@ -5647,7 +5719,7 @@ function boldCommentTitle(body) {
|
|
|
5647
5719
|
*/
|
|
5648
5720
|
function buildCommentBody(body, commitSha, confidence) {
|
|
5649
5721
|
const confidenceLine = `_Confidence: ${confidence}._`;
|
|
5650
|
-
const footer = `<sub>Reviewed by ${PRODUCT_LINK} v0.
|
|
5722
|
+
const footer = `<sub>Reviewed by ${PRODUCT_LINK} v0.9.0 for commit ${commitSha}.</sub>`;
|
|
5651
5723
|
return `${boldCommentTitle(body.trim())}\n\n${confidenceLine}\n\n---\n\n${footer}`;
|
|
5652
5724
|
}
|
|
5653
5725
|
function buildPayload(comment, body, refs, resolved) {
|
|
@@ -6442,6 +6514,7 @@ async function run(config, bridges) {
|
|
|
6442
6514
|
const refs = await tracedRead("scm.get_latest_version", () => platform.getRefs());
|
|
6443
6515
|
const initialDiscussions = await tracedRead("scm.get_discussions", () => platform.getDiscussions());
|
|
6444
6516
|
const reviewedCommitSha = findExistingReviewedCommitSha(initialDiscussions);
|
|
6517
|
+
runContext.firstReview = findExistingSummaryNote(initialDiscussions) === null;
|
|
6445
6518
|
if (!config.forceReview && !config.dryRun && !config.noPost && reviewedCommitSha === refs.head_sha) {
|
|
6446
6519
|
const usage = zeroReviewUsage(config.model, config.thinkingLevel);
|
|
6447
6520
|
runContext.usage = usage;
|
|
@@ -6484,27 +6557,36 @@ async function run(config, bridges) {
|
|
|
6484
6557
|
if (priorThreads.length > 0) logger.info(`Found ${priorThreads.length} prior thread(s) with developer replies — including as context.`);
|
|
6485
6558
|
logger.info("Running review...");
|
|
6486
6559
|
let usage;
|
|
6560
|
+
let partialUsage;
|
|
6487
6561
|
try {
|
|
6488
6562
|
usage = await traceDiagnosticPhase("reviewer.run", config, runId, async (context) => {
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6563
|
+
try {
|
|
6564
|
+
const result = await runReview(config, {
|
|
6565
|
+
cwd: config.cwd,
|
|
6566
|
+
diff,
|
|
6567
|
+
commitLog,
|
|
6568
|
+
priorThreads,
|
|
6569
|
+
intent: {
|
|
6570
|
+
title: mr.title,
|
|
6571
|
+
description: mr.description
|
|
6572
|
+
},
|
|
6573
|
+
logger,
|
|
6574
|
+
attachTelemetry: bridges?.otel?.createAgentTelemetry(runId),
|
|
6575
|
+
onUsage: (u) => {
|
|
6576
|
+
partialUsage = u;
|
|
6577
|
+
},
|
|
6578
|
+
sinceRef: config.inputMode === "commits" && reviewedCommitSha && reviewedCommitSha !== refs.head_sha ? reviewedCommitSha : void 0
|
|
6579
|
+
});
|
|
6580
|
+
context.usage = result;
|
|
6581
|
+
return result;
|
|
6582
|
+
} catch (error) {
|
|
6583
|
+
if (partialUsage) context.usage = partialUsage;
|
|
6584
|
+
throw error;
|
|
6585
|
+
}
|
|
6504
6586
|
});
|
|
6505
6587
|
} catch (error) {
|
|
6506
6588
|
if (!isQuotaExceededError(error)) throw error;
|
|
6507
|
-
const skipUsage = zeroReviewUsage(config.model, config.thinkingLevel);
|
|
6589
|
+
const skipUsage = partialUsage ?? zeroReviewUsage(config.model, config.thinkingLevel);
|
|
6508
6590
|
runContext.usage = skipUsage;
|
|
6509
6591
|
runContext.generated = 0;
|
|
6510
6592
|
runContext.newComments = 0;
|
|
@@ -6744,10 +6826,10 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
6744
6826
|
return;
|
|
6745
6827
|
}
|
|
6746
6828
|
if (argv.includes("--version") || argv.includes("-v")) {
|
|
6747
|
-
console.log("0.
|
|
6829
|
+
console.log("0.9.0");
|
|
6748
6830
|
return;
|
|
6749
6831
|
}
|
|
6750
|
-
process.stderr.write(`[code-review] @weareikko/code-review v0.
|
|
6832
|
+
process.stderr.write(`[code-review] @weareikko/code-review v0.9.0\n`);
|
|
6751
6833
|
assertNodeVersion();
|
|
6752
6834
|
applyCodeReviewEnvPrefix();
|
|
6753
6835
|
applyDefaultCacheRetention();
|
|
@@ -6770,4 +6852,4 @@ if (isDirectRun()) main().catch((error) => {
|
|
|
6770
6852
|
//#endregion
|
|
6771
6853
|
export { normalizeBody as $, SUMMARY_HISTORY_END as A, buildSummaryHistoryEntries as B, createDiagnosticContext as C, traceDiagnosticPhase as D, traceDiagnostic as E, SUMMARY_MARKER as F, findExistingSummaryNoteId as G, extractSummaryHistoryEntries as H, buildArchivedSummaryEntry as I, upsertSummaryNote as J, stripSummaryHistory as K, buildReviewedCommitFooter as L, SUMMARY_HISTORY_ENTRY_START as M, SUMMARY_HISTORY_LIMIT as N, normalizeSeverity as O, SUMMARY_HISTORY_START as P, fingerprints as Q, buildSizeNoticeBlock as R, DIAGNOSTIC_CHANNEL_PREFIX as S, diagnosticChannels as T, findExistingReviewedCommitSha as U, extractReviewedCommitSha as V, findExistingSummaryNote as W, extractDiffHunkContext as X, appendFingerprintMarkers as Y, extractExistingFingerprints as Z, resolveNpmSkillDir as _, main as a, parseReviewMarkdownWithWarnings as b, buildGeneratedComments as c, startOtelBridge as d, sha256 as et, filterDiff as f, parseSkillSpec as g, loadNamedSkill as h, formatUsageLine as i, SUMMARY_HISTORY_ENTRY_END as j, toGitLabReviewSeverity as k, buildPayload as l, gitSkillCacheKey as m, formatPerModelUsage as n, run as o, runReview as p, stripSummaryMarker as q, formatSkillsFooter as r, withHttpStamping as s, countPostedBySeverity as t, isOtelEnabled as u, resolveSkillCacheDir as v, createDiagnosticRunId as w, DIAGNOSTIC_CHANNEL_NAMES as x, parseReviewMarkdown as y, buildSummaryBody as z };
|
|
6772
6854
|
|
|
6773
|
-
//# sourceMappingURL=cli-
|
|
6855
|
+
//# sourceMappingURL=cli-DK0kteLL.js.map
|