open-azdo 0.2.4 → 0.2.6

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/README.md CHANGED
@@ -77,7 +77,7 @@ pool:
77
77
  vmImage: ubuntu-latest
78
78
 
79
79
  variables:
80
- OpenCodeModel: openai/gpt-5.4
80
+ OpenCodeModel: openai/gpt-5.4-mini
81
81
  OpenCodeThinking: high
82
82
 
83
83
  steps:
package/dist/open-azdo.js CHANGED
@@ -46932,17 +46932,17 @@ var runGit = (workspace, operation, args2, allowNonZeroExit = false) => exports_
46932
46932
  allowNonZeroExit
46933
46933
  });
46934
46934
  });
46935
+ var resolveHeadReviewedSourceCommitCandidate = (workspace) => runGit(workspace, "Git.resolveReviewedSourceCommit.revList", ["rev-list", "--parents", "-n", "1", "HEAD"]).pipe(exports_Effect.map((result4) => {
46936
+ const hashes = result4.stdout.trim().split(/\s+/);
46937
+ return hashes.length === 3 ? "HEAD^2" : "HEAD";
46938
+ }));
46935
46939
  var resolveReviewedSourceCommit = ({ workspace, sourceCommitId }) => exports_Effect.gen(function* () {
46936
- const candidate = sourceCommitId ?? (yield* runGit(workspace, "Git.resolveReviewedSourceCommit.revList", [
46937
- "rev-list",
46938
- "--parents",
46939
- "-n",
46940
- "1",
46941
- "HEAD"
46942
- ]).pipe(exports_Effect.map((result4) => {
46943
- const hashes = result4.stdout.trim().split(/\s+/);
46944
- return hashes.length === 3 ? "HEAD^2" : "HEAD";
46945
- })));
46940
+ const fallbackCandidate = yield* resolveHeadReviewedSourceCommitCandidate(workspace);
46941
+ let candidate = fallbackCandidate;
46942
+ if (sourceCommitId !== undefined) {
46943
+ const explicitCandidate = yield* runGit(workspace, "Git.resolveReviewedSourceCommit.verifyExplicit", ["rev-parse", "--verify", `${sourceCommitId}^{commit}`], true);
46944
+ candidate = explicitCandidate.exitCode === 0 ? sourceCommitId : fallbackCandidate;
46945
+ }
46946
46946
  const resolved = yield* runGit(workspace, "Git.resolveReviewedSourceCommit.revParse", [
46947
46947
  "rev-parse",
46948
46948
  "--verify",
@@ -47044,6 +47044,26 @@ var resolvePullRequestDiff = (input) => exports_Effect.gen(function* () {
47044
47044
  // ../../packages/core/src/platform/Services/ProcessRunner.ts
47045
47045
  class ProcessRunner extends exports_ServiceMap.Service()("open-azdo/platform/ProcessRunner") {
47046
47046
  }
47047
+ // ../../packages/core/src/format-unknown.ts
47048
+ var formatUnknownDetail = (value3) => {
47049
+ if (typeof value3 === "string") {
47050
+ return value3;
47051
+ }
47052
+ if (value3 instanceof Error) {
47053
+ return value3.message;
47054
+ }
47055
+ if (typeof value3 === "number" || typeof value3 === "boolean" || typeof value3 === "bigint") {
47056
+ return String(value3);
47057
+ }
47058
+ if (value3 === undefined) {
47059
+ return "undefined";
47060
+ }
47061
+ if (value3 === null) {
47062
+ return "null";
47063
+ }
47064
+ return stringifyJson2(value3);
47065
+ };
47066
+
47047
47067
  // ../../packages/core/src/platform/Layers/ProcessRunner.ts
47048
47068
  var DEFAULT_TIMEOUT = seconds(30);
47049
47069
  var DEFAULT_MAX_OUTPUT_BYTES = 1e6;
@@ -47113,7 +47133,7 @@ var makeProcessRunner = exports_Effect.gen(function* () {
47113
47133
  stderr: "pipe"
47114
47134
  });
47115
47135
  return yield* exports_Effect.gen(function* () {
47116
- const handle = yield* spawner.spawn(command).pipe(exports_Effect.mapError((error2) => toCommandExecutionError(input, `Failed to start ${commandLabel(input)}: ${String(error2)}`)));
47136
+ const handle = yield* spawner.spawn(command).pipe(exports_Effect.mapError((error2) => toCommandExecutionError(input, `Failed to start ${commandLabel(input)}: ${formatUnknownDetail(error2)}`)));
47117
47137
  const [stdout, stderr, exitCode] = yield* exports_Effect.all([
47118
47138
  collectOutput(input, handle.stdout, "stdout", maxOutputBytes),
47119
47139
  collectOutput(input, handle.stderr, "stderr", maxOutputBytes),
@@ -47181,6 +47201,7 @@ var GitExecLive = exports_Layer.effect(GitExec, makeGitExec);
47181
47201
  class OpenCodeRunner extends exports_ServiceMap.Service()("open-azdo/opencode/OpenCodeRunner") {
47182
47202
  }
47183
47203
  // ../../packages/core/src/opencode/Layers/OpenCodeRunner.ts
47204
+ var OPENCODE_MAX_OUTPUT_BYTES = 1e7;
47184
47205
  var buildOpenCodeConfig = (agentName) => ({
47185
47206
  $schema: "https://opencode.ai/config.json",
47186
47207
  permission: {
@@ -47233,10 +47254,68 @@ var buildOpenCodeArgs = (request3) => [
47233
47254
  ...request3.variant ? ["--variant", request3.variant] : [],
47234
47255
  REVIEW_TRIGGER_MESSAGE
47235
47256
  ];
47236
- var extractFinalResponse = (output) => {
47257
+ var isRecord = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
47258
+ var toNumberOrUndefined = (value3) => typeof value3 === "number" && Number.isFinite(value3) ? value3 : undefined;
47259
+ var parseTokenUsage = (value3) => {
47260
+ if (!isRecord(value3)) {
47261
+ return;
47262
+ }
47263
+ const input = toNumberOrUndefined(value3.input);
47264
+ const output = toNumberOrUndefined(value3.output);
47265
+ if (input === undefined || output === undefined) {
47266
+ return;
47267
+ }
47268
+ return {
47269
+ input,
47270
+ output,
47271
+ reasoning: toNumberOrUndefined(value3.reasoning) ?? 0,
47272
+ cacheRead: toNumberOrUndefined(value3.cacheRead) ?? 0,
47273
+ cacheWrite: toNumberOrUndefined(value3.cacheWrite) ?? 0
47274
+ };
47275
+ };
47276
+ var buildUsage = ({
47277
+ costUsd,
47278
+ tokens
47279
+ }) => {
47280
+ if (costUsd === undefined && tokens === undefined) {
47281
+ return;
47282
+ }
47283
+ return {
47284
+ ...costUsd !== undefined ? { costUsd } : {},
47285
+ ...tokens ? { tokens } : {}
47286
+ };
47287
+ };
47288
+ var parsePartUsage = (value3) => {
47289
+ if (!isRecord(value3) || value3.type !== "step-finish") {
47290
+ return;
47291
+ }
47292
+ return buildUsage({
47293
+ costUsd: toNumberOrUndefined(value3.cost),
47294
+ tokens: parseTokenUsage(value3.tokens)
47295
+ });
47296
+ };
47297
+ var parseAssistantUsage = (value3) => {
47298
+ if (!isRecord(value3)) {
47299
+ return;
47300
+ }
47301
+ const candidate = isRecord(value3.info) ? value3.info : value3;
47302
+ return buildUsage({
47303
+ costUsd: toNumberOrUndefined(candidate.cost),
47304
+ tokens: parseTokenUsage(candidate.tokens)
47305
+ });
47306
+ };
47307
+ var extractOpenCodeRunResult = (output) => {
47237
47308
  const texts = [];
47238
47309
  const structuredCandidates = [];
47239
47310
  const reportedErrors = [];
47311
+ let sessionId;
47312
+ let stepFinishUsage;
47313
+ let assistantUsage;
47314
+ const buildRunResult = (response2) => ({
47315
+ response: response2,
47316
+ ...sessionId ? { sessionId } : {},
47317
+ ...stepFinishUsage || assistantUsage ? { usage: stepFinishUsage ?? assistantUsage } : {}
47318
+ });
47240
47319
  const describeError = (value3) => {
47241
47320
  if (value3 === null || value3 === undefined) {
47242
47321
  return;
@@ -47245,19 +47324,21 @@ var extractFinalResponse = (output) => {
47245
47324
  const trimmed = value3.trim();
47246
47325
  return trimmed.length > 0 ? trimmed : undefined;
47247
47326
  }
47248
- if (typeof value3 !== "object" || Array.isArray(value3)) {
47327
+ if (typeof value3 === "number" || typeof value3 === "boolean" || typeof value3 === "bigint") {
47249
47328
  return String(value3);
47250
47329
  }
47251
- const record3 = value3;
47252
- const message = describeError(record3.message) ?? describeError(record3.detail) ?? describeError(record3.data) ?? describeError(record3.error) ?? describeError(record3.cause);
47330
+ if (!isRecord(value3)) {
47331
+ return;
47332
+ }
47333
+ const message = describeError(value3.message) ?? describeError(value3.detail) ?? describeError(value3.data) ?? describeError(value3.error) ?? describeError(value3.cause);
47253
47334
  if (!message) {
47254
- return stringifyJson2(record3);
47335
+ return stringifyJson2(value3);
47255
47336
  }
47256
- const name = typeof record3.name === "string" ? record3.name.trim() : "";
47337
+ const name = typeof value3.name === "string" ? value3.name.trim() : "";
47257
47338
  return name.length > 0 && !message.startsWith(`${name}:`) ? `${name}: ${message}` : message;
47258
47339
  };
47259
47340
  const maybeCollectStructuredCandidate = (value3) => {
47260
- if (!value3 || typeof value3 !== "object" || Array.isArray(value3)) {
47341
+ if (!isRecord(value3)) {
47261
47342
  return;
47262
47343
  }
47263
47344
  if ("summary" in value3 && "verdict" in value3 && "findings" in value3) {
@@ -47285,10 +47366,21 @@ var extractFinalResponse = (output) => {
47285
47366
  }
47286
47367
  return;
47287
47368
  }
47288
- if (typeof value3 !== "object") {
47369
+ if (!isRecord(value3)) {
47289
47370
  return;
47290
47371
  }
47291
47372
  maybeCollectStructuredCandidate(value3);
47373
+ const usageFromPart = parsePartUsage(value3);
47374
+ if (usageFromPart) {
47375
+ stepFinishUsage = usageFromPart;
47376
+ }
47377
+ const usageFromAssistant = parseAssistantUsage(value3);
47378
+ if (usageFromAssistant) {
47379
+ assistantUsage = usageFromAssistant;
47380
+ }
47381
+ if (typeof value3.sessionID === "string") {
47382
+ sessionId = value3.sessionID;
47383
+ }
47292
47384
  if ("type" in value3 && value3.type === "text" && "text" in value3 && typeof value3.text === "string") {
47293
47385
  texts.push(value3.text.trim());
47294
47386
  }
@@ -47323,7 +47415,7 @@ var extractFinalResponse = (output) => {
47323
47415
  }
47324
47416
  const structuredResponse = structuredCandidates.at(-1)?.trim();
47325
47417
  if (structuredResponse) {
47326
- return structuredResponse;
47418
+ return buildRunResult(structuredResponse);
47327
47419
  }
47328
47420
  const response = texts.join(`
47329
47421
  `).trim();
@@ -47333,7 +47425,7 @@ var extractFinalResponse = (output) => {
47333
47425
  output
47334
47426
  });
47335
47427
  }
47336
- return response;
47428
+ return buildRunResult(response);
47337
47429
  };
47338
47430
  var makeOpenCodeRunner = exports_Effect.gen(function* () {
47339
47431
  const runner = yield* ProcessRunner;
@@ -47349,7 +47441,7 @@ var makeOpenCodeRunner = exports_Effect.gen(function* () {
47349
47441
  });
47350
47442
  const tempDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "open-azdo-opencode-" }).pipe(exports_Effect.mapError((error2) => new OpenCodeOutputError({
47351
47443
  message: "Failed to create OpenCode temp directory.",
47352
- output: String(error2)
47444
+ output: formatUnknownDetail(error2)
47353
47445
  })));
47354
47446
  const configPath = path3.join(tempDir, "opencode.json");
47355
47447
  const promptPath = path3.join(tempDir, "agent-prompt.md");
@@ -47358,7 +47450,7 @@ var makeOpenCodeRunner = exports_Effect.gen(function* () {
47358
47450
  fileSystem.writeFileString(configPath, stringifyJson2(buildOpenCodeConfig(request3.agent)))
47359
47451
  ], { concurrency: "unbounded" }).pipe(exports_Effect.mapError((error2) => new OpenCodeOutputError({
47360
47452
  message: "Failed to write temporary OpenCode configuration.",
47361
- output: String(error2)
47453
+ output: formatUnknownDetail(error2)
47362
47454
  })));
47363
47455
  yield* logInfo2("Prepared temporary OpenCode files.", {
47364
47456
  tempDir,
@@ -47371,6 +47463,7 @@ var makeOpenCodeRunner = exports_Effect.gen(function* () {
47371
47463
  args: buildOpenCodeArgs(request3),
47372
47464
  cwd: request3.workspace,
47373
47465
  timeout: request3.timeout,
47466
+ maxOutputBytes: OPENCODE_MAX_OUTPUT_BYTES,
47374
47467
  env: {
47375
47468
  ...request3.inheritedEnv,
47376
47469
  OPENCODE_CONFIG: configPath,
@@ -47398,11 +47491,11 @@ var makeOpenCodeRunner = exports_Effect.gen(function* () {
47398
47491
  exitCode: result4.exitCode
47399
47492
  });
47400
47493
  }
47401
- const response = yield* exports_Effect.try({
47402
- try: () => extractFinalResponse(result4.stdout),
47494
+ const runResult = yield* exports_Effect.try({
47495
+ try: () => extractOpenCodeRunResult(result4.stdout),
47403
47496
  catch: (error2) => error2 instanceof OpenCodeOutputError ? error2 : new OpenCodeOutputError({
47404
47497
  message: "OpenCode did not return a valid final response.",
47405
- output: String(error2)
47498
+ output: formatUnknownDetail(error2)
47406
47499
  })
47407
47500
  }).pipe(exports_Effect.tapError((error2) => logError2("Failed to extract final OpenCode response.", {
47408
47501
  stdoutPreview: truncateForLog(result4.stdout),
@@ -47410,10 +47503,14 @@ var makeOpenCodeRunner = exports_Effect.gen(function* () {
47410
47503
  detail: error2.message
47411
47504
  })));
47412
47505
  yield* logInfo2("Extracted final OpenCode response.", {
47413
- responseChars: response.length,
47414
- responsePreview: truncateForLog(response)
47506
+ responseChars: runResult.response.length,
47507
+ responsePreview: truncateForLog(runResult.response),
47508
+ sessionId: runResult.sessionId,
47509
+ costUsd: runResult.usage?.costUsd,
47510
+ inputTokens: runResult.usage?.tokens?.input,
47511
+ outputTokens: runResult.usage?.tokens?.output
47415
47512
  });
47416
- return response;
47513
+ return runResult;
47417
47514
  }).pipe(exports_Effect.scoped);
47418
47515
  });
47419
47516
  return {
@@ -47512,6 +47609,24 @@ var SeverityCountsSchema = exports_Schema.Struct({
47512
47609
  high: exports_Schema.Int,
47513
47610
  critical: exports_Schema.Int
47514
47611
  });
47612
+ var ReviewHistoryTokensSchema = exports_Schema.Struct({
47613
+ input: exports_Schema.Int,
47614
+ output: exports_Schema.Int,
47615
+ reasoning: exports_Schema.Int,
47616
+ cacheRead: exports_Schema.Int,
47617
+ cacheWrite: exports_Schema.Int
47618
+ });
47619
+ var ReviewHistoryEntrySchema = exports_Schema.Struct({
47620
+ reviewedCommit: exports_Schema.String,
47621
+ reviewMode: exports_Schema.Literals(["full", "follow-up"]),
47622
+ model: exports_Schema.String,
47623
+ variant: exports_Schema.optionalKey(exports_Schema.String),
47624
+ buildNumber: exports_Schema.optionalKey(exports_Schema.String),
47625
+ buildId: exports_Schema.optionalKey(exports_Schema.String),
47626
+ buildLink: exports_Schema.optionalKey(exports_Schema.String),
47627
+ costUsd: exports_Schema.optionalKey(exports_Schema.Number),
47628
+ tokens: exports_Schema.optionalKey(ReviewHistoryTokensSchema)
47629
+ });
47515
47630
  var ManagedReviewStateSchema = exports_Schema.Struct({
47516
47631
  schemaVersion: exports_Schema.Int,
47517
47632
  reviewedCommit: exports_Schema.String,
@@ -47520,10 +47635,11 @@ var ManagedReviewStateSchema = exports_Schema.Struct({
47520
47635
  severityCounts: SeverityCountsSchema,
47521
47636
  findingsCount: exports_Schema.Int,
47522
47637
  inlineFindingsCount: exports_Schema.Int,
47523
- unmappedNotesCount: exports_Schema.Int
47638
+ unmappedNotesCount: exports_Schema.Int,
47639
+ reviewHistory: exports_Schema.optionalKey(exports_Schema.Array(ReviewHistoryEntrySchema))
47524
47640
  });
47525
47641
  var isActiveThreadStatus = (status) => status === 1 || status === "active" || status === "pending";
47526
- var STATE_SCHEMA_VERSION = 1;
47642
+ var STATE_SCHEMA_VERSION = 2;
47527
47643
  var FINDING_MARKER_PREFIX = "<!-- open-azdo:";
47528
47644
  var SUMMARY_STATE_PREFIX = "<!-- open-azdo-review:";
47529
47645
  var COMMENT_SUFFIX = " -->";
@@ -47568,7 +47684,8 @@ var fingerprintFinding = (finding) => {
47568
47684
  var buildManagedReviewState = ({
47569
47685
  reviewedCommit,
47570
47686
  pullRequestBaseRef,
47571
- reviewResult
47687
+ reviewResult,
47688
+ reviewHistory
47572
47689
  }) => ({
47573
47690
  schemaVersion: STATE_SCHEMA_VERSION,
47574
47691
  reviewedCommit,
@@ -47577,8 +47694,56 @@ var buildManagedReviewState = ({
47577
47694
  severityCounts: countBySeverity(reviewResult.findings),
47578
47695
  findingsCount: reviewResult.findings.length,
47579
47696
  inlineFindingsCount: reviewResult.inlineFindings?.length ?? 0,
47580
- unmappedNotesCount: reviewResult.unmappedNotes.length
47581
- });
47697
+ unmappedNotesCount: reviewResult.unmappedNotes.length,
47698
+ ...reviewHistory && reviewHistory.length > 0 ? { reviewHistory: [...reviewHistory] } : {}
47699
+ });
47700
+ var shortCommit = (value3) => value3.slice(0, 12);
47701
+ var formatInteger = (value3) => new Intl.NumberFormat("en-US").format(value3);
47702
+ var formatCostUsd = (value3) => new Intl.NumberFormat("en-US", {
47703
+ style: "currency",
47704
+ currency: "USD",
47705
+ minimumFractionDigits: 4,
47706
+ maximumFractionDigits: 4
47707
+ }).format(value3);
47708
+ var escapeTableCell = (value3) => value3.replaceAll("|", "\\|").replaceAll(`
47709
+ `, "<br>");
47710
+ var formatReviewLabel = (entry) => {
47711
+ const buildLabel = entry.buildNumber ? `Build ${entry.buildNumber}` : entry.buildId ? `Build ${entry.buildId}` : undefined;
47712
+ const commitLabel = shortCommit(entry.reviewedCommit);
47713
+ if (buildLabel && entry.buildLink) {
47714
+ return `[${buildLabel}](${entry.buildLink}) \xB7 ${commitLabel}`;
47715
+ }
47716
+ if (buildLabel) {
47717
+ return `${buildLabel} \xB7 ${commitLabel}`;
47718
+ }
47719
+ return commitLabel;
47720
+ };
47721
+ var formatTokenBreakdown = (tokens) => {
47722
+ if (!tokens) {
47723
+ return "-";
47724
+ }
47725
+ const segments = [`input ${formatInteger(tokens.input)}`, `output ${formatInteger(tokens.output)}`];
47726
+ if (tokens.reasoning > 0) {
47727
+ segments.push(`reasoning ${formatInteger(tokens.reasoning)}`);
47728
+ }
47729
+ if (tokens.cacheRead > 0) {
47730
+ segments.push(`cache read ${formatInteger(tokens.cacheRead)}`);
47731
+ }
47732
+ if (tokens.cacheWrite > 0) {
47733
+ segments.push(`cache write ${formatInteger(tokens.cacheWrite)}`);
47734
+ }
47735
+ return segments.join(", ");
47736
+ };
47737
+ var formatModelLabel = (entry) => entry.variant ? `${entry.model} (${entry.variant})` : entry.model;
47738
+ var appendReviewHistorySection = (lines, reviewHistory) => {
47739
+ if (reviewHistory.length === 0) {
47740
+ return;
47741
+ }
47742
+ lines.push("", "Review cost history:", "", "| Review | Mode | Model | Tokens | Cost |", "| --- | --- | --- | --- | --- |");
47743
+ for (const entry of reviewHistory) {
47744
+ lines.push(`| ${escapeTableCell(formatReviewLabel(entry))} | ${escapeTableCell(entry.reviewMode)} | ${escapeTableCell(formatModelLabel(entry))} | ${escapeTableCell(formatTokenBreakdown(entry.tokens))} | ${escapeTableCell(entry.costUsd !== undefined ? formatCostUsd(entry.costUsd) : "-")} |`);
47745
+ }
47746
+ };
47582
47747
  var buildSummaryComment = (snapshot) => {
47583
47748
  const lines = [
47584
47749
  `Verdict: **${snapshot.verdict}**`,
@@ -47596,6 +47761,7 @@ var buildSummaryComment = (snapshot) => {
47596
47761
  if (snapshot.buildLink) {
47597
47762
  lines.push("", `Build: ${snapshot.buildLink}`);
47598
47763
  }
47764
+ appendReviewHistorySection(lines, snapshot.persistedState?.reviewHistory ?? []);
47599
47765
  if (snapshot.persistedState) {
47600
47766
  lines.push("", encodeManagedReviewState(snapshot.persistedState));
47601
47767
  }
@@ -48017,6 +48183,50 @@ var decodeOpenCodeResult = (rawResult) => parseJsonUnknown(rawResult).pipe(expor
48017
48183
  }),
48018
48184
  onSuccess: (decodedJson) => decodedJson
48019
48185
  }));
48186
+ var mapUsageTokens = (usage) => usage?.tokens ? {
48187
+ input: usage.tokens.input,
48188
+ output: usage.tokens.output,
48189
+ reasoning: usage.tokens.reasoning,
48190
+ cacheRead: usage.tokens.cacheRead,
48191
+ cacheWrite: usage.tokens.cacheWrite
48192
+ } : undefined;
48193
+ var buildReviewHistoryEntry = ({
48194
+ reviewedCommit,
48195
+ reviewMode,
48196
+ config,
48197
+ buildLink,
48198
+ usage
48199
+ }) => {
48200
+ const tokens = mapUsageTokens(usage);
48201
+ return {
48202
+ reviewedCommit,
48203
+ reviewMode,
48204
+ model: config.model,
48205
+ ...config.opencodeVariant ? { variant: config.opencodeVariant } : {},
48206
+ ...config.buildNumber ? { buildNumber: config.buildNumber } : {},
48207
+ ...config.buildId ? { buildId: config.buildId } : {},
48208
+ ...buildLink ? { buildLink } : {},
48209
+ ...usage?.costUsd !== undefined ? { costUsd: usage.costUsd } : {},
48210
+ ...tokens ? { tokens } : {}
48211
+ };
48212
+ };
48213
+ var appendReviewHistoryEntry = ({
48214
+ previousSummaryState,
48215
+ reviewedCommit,
48216
+ reviewMode,
48217
+ config,
48218
+ buildLink,
48219
+ usage
48220
+ }) => [
48221
+ ...previousSummaryState?.reviewHistory ?? [],
48222
+ buildReviewHistoryEntry({
48223
+ reviewedCommit,
48224
+ reviewMode,
48225
+ config,
48226
+ buildLink,
48227
+ usage
48228
+ })
48229
+ ];
48020
48230
  var writeReviewWorkflowOutput = (config, output) => {
48021
48231
  if (config.json) {
48022
48232
  return writeStdout(`${stringifyJson2({
@@ -48133,7 +48343,7 @@ var runReviewWithResolvedConfig = (config, azureContext, buildLink) => exports_E
48133
48343
  yield* logInfo2("Built review prompt.", {
48134
48344
  promptChars: prompt.length
48135
48345
  });
48136
- const rawResult = yield* openCodeRunner.run({
48346
+ const openCodeResult = yield* openCodeRunner.run({
48137
48347
  workspace: config.workspace,
48138
48348
  model: config.model,
48139
48349
  agent: config.agent,
@@ -48143,9 +48353,13 @@ var runReviewWithResolvedConfig = (config, azureContext, buildLink) => exports_E
48143
48353
  inheritedEnv: config.inheritedEnv
48144
48354
  });
48145
48355
  yield* logInfo2("Received OpenCode response.", {
48146
- responseChars: rawResult.length
48356
+ responseChars: openCodeResult.response.length,
48357
+ sessionId: openCodeResult.sessionId,
48358
+ costUsd: openCodeResult.usage?.costUsd,
48359
+ inputTokens: openCodeResult.usage?.tokens?.input,
48360
+ outputTokens: openCodeResult.usage?.tokens?.output
48147
48361
  });
48148
- const reviewResult = yield* decodeOpenCodeResult(rawResult).pipe(exports_Effect.flatMap((decodedJson) => decodeReviewResult(decodedJson, scopedDiff.changedLinesByFile)));
48362
+ const reviewResult = yield* decodeOpenCodeResult(openCodeResult.response).pipe(exports_Effect.flatMap((decodedJson) => decodeReviewResult(decodedJson, scopedDiff.changedLinesByFile)));
48149
48363
  yield* logInfo2("Decoded review result.", {
48150
48364
  reviewMode,
48151
48365
  verdict: reviewResult.verdict,
@@ -48160,10 +48374,19 @@ var runReviewWithResolvedConfig = (config, azureContext, buildLink) => exports_E
48160
48374
  scopedDeletedLinesByFile: scopedDiff.deletedLinesByFile,
48161
48375
  reviewResult
48162
48376
  }) : reviewResult;
48377
+ const reviewHistory = appendReviewHistoryEntry({
48378
+ previousSummaryState,
48379
+ reviewedCommit: reviewedSourceCommit,
48380
+ reviewMode,
48381
+ config,
48382
+ buildLink,
48383
+ usage: openCodeResult.usage
48384
+ });
48163
48385
  const summaryState = buildManagedReviewState({
48164
48386
  reviewedCommit: reviewedSourceCommit,
48165
48387
  pullRequestBaseRef: fullPullRequestDiff.baseRef,
48166
- reviewResult: outstandingReviewResult
48388
+ reviewResult: outstandingReviewResult,
48389
+ reviewHistory
48167
48390
  });
48168
48391
  const summaryContent = buildSummaryComment({
48169
48392
  verdict: summaryState.verdict,
@@ -48471,7 +48694,7 @@ var reviewCommandConfig = {
48471
48694
  var reviewCommand = make33("review", reviewCommandConfig).pipe(withDescription3("Review an Azure DevOps pull request with OpenCode."), withHandler((input) => runReviewCommand(input)));
48472
48695
  var openAzdoCli = make33("open-azdo").pipe(withDescription3("Secure Azure DevOps pull-request review CLI powered by OpenCode."), withSubcommands([reviewCommand]));
48473
48696
  // package.json
48474
- var version2 = "0.2.4";
48697
+ var version2 = "0.2.6";
48475
48698
 
48476
48699
  // src/Main.ts
48477
48700
  var cliProgram = run3(openAzdoCli, { version: version2 }).pipe(exports_Effect.scoped, exports_Effect.provide(BaseRuntimeLayer));
@@ -48480,4 +48703,4 @@ var main = () => runMain2(cliProgram, { disableErrorReporting: true });
48480
48703
  // bin/open-azdo.ts
48481
48704
  main();
48482
48705
 
48483
- //# debugId=7528100F803103A764756E2164756E21
48706
+ //# debugId=151A25C3CC4015FB64756E2164756E21