@usepipr/runtime 0.4.3 → 0.5.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/LICENSE +21 -0
- package/README.md +8 -5
- package/dist/{commands-DA0Ij4Di.d.mts → commands-CF59DZXx.d.mts} +2 -2
- package/dist/{commands-DA0Ij4Di.d.mts.map → commands-CF59DZXx.d.mts.map} +1 -1
- package/dist/{commands-B9qNW4pk.mjs → commands-DgZU7tf7.mjs} +474 -334
- package/dist/commands-DgZU7tf7.mjs.map +1 -0
- package/dist/index.d.mts +16 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +117 -15
- package/dist/index.mjs.map +1 -1
- package/dist/internal/action-result.d.mts +4 -2
- package/dist/internal/action-result.d.mts.map +1 -1
- package/dist/internal/action-result.mjs +28 -12
- package/dist/internal/action-result.mjs.map +1 -1
- package/dist/internal/docs.mjs +1 -1
- package/dist/internal/pipr-result.d.mts +24 -0
- package/dist/internal/pipr-result.d.mts.map +1 -0
- package/dist/internal/pipr-result.mjs +126 -0
- package/dist/internal/pipr-result.mjs.map +1 -0
- package/dist/internal/testing.d.mts +11 -11
- package/dist/internal/testing.d.mts.map +1 -1
- package/dist/internal/testing.mjs +1 -1
- package/dist/main-comment-envelope-DFirHYhW.mjs +69 -0
- package/dist/main-comment-envelope-DFirHYhW.mjs.map +1 -0
- package/dist/{official-github-workflow-Bjlu-FL3.mjs → official-github-workflow-DNzV5Z70.mjs} +183 -33
- package/dist/official-github-workflow-DNzV5Z70.mjs.map +1 -0
- package/dist/{types-BAis_Lwm.d.mts → types-Dn1U3MDG.d.mts} +30 -18
- package/dist/types-Dn1U3MDG.d.mts.map +1 -0
- package/package.json +16 -8
- package/dist/commands-B9qNW4pk.mjs.map +0 -1
- package/dist/official-github-workflow-Bjlu-FL3.mjs.map +0 -1
- package/dist/types-BAis_Lwm.d.mts.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { c as resolveReadAtRefRequest, d as isRecord, l as unavailableReadAtRefResult, n as boundedLineSlice, r as parseManifestPath, u as createDiffRangeIndex } from "./runtime-tools-core-D8_WsbL_.mjs";
|
|
2
|
-
import { a as officialInitRecipeWorkflowEnvSecrets, i as officialInitRecipeFiles, r as officialInitRecipeConfigTs, t as renderOfficialGithubWorkflow } from "./official-github-workflow-
|
|
2
|
+
import { a as officialInitRecipeWorkflowEnvSecrets, i as officialInitRecipeFiles, r as officialInitRecipeConfigTs, t as renderOfficialGithubWorkflow } from "./official-github-workflow-DNzV5Z70.mjs";
|
|
3
3
|
import { t as isPublishableSuggestedFixSelection } from "./suggested-fix-publication-policy-B5Wwuudp.mjs";
|
|
4
|
+
import { a as mainCommentTitle, c as reviewStatsEndMarker, i as mainCommentHeaderHiddenMarker, l as reviewStatsHiddenMarker, n as mainCommentAttributionTextPattern, o as mainCommentTitles, r as mainCommentFooterHiddenMarker, s as piprRepositoryUrl, t as parseGeneratedMainCommentEnvelope, u as reviewStatsStartMarker } from "./main-comment-envelope-DFirHYhW.mjs";
|
|
4
5
|
import { createRequire } from "node:module";
|
|
5
6
|
import { chmod, chown, cp, lstat, mkdir, mkdtemp, readdir, rm } from "node:fs/promises";
|
|
6
7
|
import path from "node:path";
|
|
@@ -597,7 +598,7 @@ function compareStableSemver(left, right) {
|
|
|
597
598
|
}
|
|
598
599
|
//#endregion
|
|
599
600
|
//#region src/shared/version.ts
|
|
600
|
-
const runtimeVersion = "0.
|
|
601
|
+
const runtimeVersion = "0.5.0";
|
|
601
602
|
//#endregion
|
|
602
603
|
//#region src/config/version-compat.ts
|
|
603
604
|
async function resolveConfigVersionCompatibility(options) {
|
|
@@ -746,7 +747,7 @@ async function loadTypescriptForConfig(configDir) {
|
|
|
746
747
|
packageRoot: localPackageRoot
|
|
747
748
|
};
|
|
748
749
|
return {
|
|
749
|
-
ts: typescriptApi(await import("
|
|
750
|
+
ts: typescriptApi(await import("typescript6")),
|
|
750
751
|
packageRoot: await runtimeTypescriptPackageRoot()
|
|
751
752
|
};
|
|
752
753
|
}
|
|
@@ -759,7 +760,7 @@ function typescriptApi(module) {
|
|
|
759
760
|
async function runtimeTypescriptPackageRoot() {
|
|
760
761
|
try {
|
|
761
762
|
const require = createRequire(import.meta.url);
|
|
762
|
-
const packageRoot = path.dirname(require.resolve("
|
|
763
|
+
const packageRoot = path.dirname(require.resolve("typescript6/package.json"));
|
|
763
764
|
return await fileExists(path.join(packageRoot, "lib", "typescript.js")) ? packageRoot : void 0;
|
|
764
765
|
} catch {
|
|
765
766
|
return;
|
|
@@ -935,8 +936,8 @@ const supportedOfficialInitAdapters = [
|
|
|
935
936
|
"azure-devops",
|
|
936
937
|
"bitbucket"
|
|
937
938
|
];
|
|
938
|
-
const defaultGitLabImageRef = "ghcr.io/somus/pipr:v0.
|
|
939
|
-
const defaultSdkVersion = "0.
|
|
939
|
+
const defaultGitLabImageRef = "ghcr.io/somus/pipr:v0.5.0";
|
|
940
|
+
const defaultSdkVersion = "0.5.0";
|
|
940
941
|
function resolveOfficialInitAdapters(adapters) {
|
|
941
942
|
if (adapters === void 0) return ["github"];
|
|
942
943
|
if (adapters.length === 0) return [];
|
|
@@ -1155,6 +1156,14 @@ async function maybeLstat(filePath) {
|
|
|
1155
1156
|
}
|
|
1156
1157
|
//#endregion
|
|
1157
1158
|
//#region src/diff/git.ts
|
|
1159
|
+
var GitOutputLimitError = class extends Error {
|
|
1160
|
+
limitBytes;
|
|
1161
|
+
constructor(limitBytes) {
|
|
1162
|
+
super(`git output exceeded ${limitBytes} byte limit`);
|
|
1163
|
+
this.limitBytes = limitBytes;
|
|
1164
|
+
this.name = "GitOutputLimitError";
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1158
1167
|
function runGit$1(args, cwd, maxBuffer) {
|
|
1159
1168
|
const result = Bun.spawnSync(["git", ...args], {
|
|
1160
1169
|
cwd,
|
|
@@ -1163,6 +1172,7 @@ function runGit$1(args, cwd, maxBuffer) {
|
|
|
1163
1172
|
stderr: "pipe",
|
|
1164
1173
|
stdout: "pipe"
|
|
1165
1174
|
});
|
|
1175
|
+
if (result.exitedDueToMaxBuffer && maxBuffer !== void 0) throw new GitOutputLimitError(maxBuffer);
|
|
1166
1176
|
if (result.exitCode !== 0) {
|
|
1167
1177
|
const failure = result.stderr?.toString().trim() || "unknown error";
|
|
1168
1178
|
throw new Error(`git ${args.join(" ")} failed: ${failure}`);
|
|
@@ -1175,6 +1185,7 @@ const lockFilePattern = /(^|\/)(bun\.lock|package-lock\.json|pnpm-lock\.yaml|yar
|
|
|
1175
1185
|
const generatedPattern = /(^|\/)(dist|build|coverage|vendor)\//;
|
|
1176
1186
|
const maxInlineChangedLines = 1e3;
|
|
1177
1187
|
const maxCommentableRangeLines = 5e3;
|
|
1188
|
+
const maxAggregatePatchBytes = 16 * 1024 * 1024;
|
|
1178
1189
|
function buildDiffManifest(options) {
|
|
1179
1190
|
const mergeBaseSha = runGit$1([
|
|
1180
1191
|
"merge-base",
|
|
@@ -1188,7 +1199,7 @@ function buildDiffManifest(options) {
|
|
|
1188
1199
|
"--find-renames"
|
|
1189
1200
|
], mergeBaseSha, diffHead), options.cwd));
|
|
1190
1201
|
const diffStats = getDiffStats(options.cwd, mergeBaseSha, diffHead);
|
|
1191
|
-
const rawPatch =
|
|
1202
|
+
const rawPatch = loadRawPatch(buildUnifiedDiffArgs(mergeBaseSha, diffHead, getPreExcludedFiles(files, diffStats)), options.cwd);
|
|
1192
1203
|
const parsedDiff = parseUnifiedDiff(rawPatch.patch, rawPatch.filePaths);
|
|
1193
1204
|
for (const file of files) {
|
|
1194
1205
|
const stats = diffStats.get(file.path);
|
|
@@ -1212,6 +1223,14 @@ function buildDiffManifest(options) {
|
|
|
1212
1223
|
files
|
|
1213
1224
|
});
|
|
1214
1225
|
}
|
|
1226
|
+
function loadRawPatch(args, cwd) {
|
|
1227
|
+
try {
|
|
1228
|
+
return parseRawPatch(runGit$1(args, cwd, maxAggregatePatchBytes));
|
|
1229
|
+
} catch (error) {
|
|
1230
|
+
if (error instanceof GitOutputLimitError) throw new Error(`Diff Manifest construction exceeded aggregate patch limit before parsing; limit=${error.limitBytes} bytes`);
|
|
1231
|
+
throw error;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1215
1234
|
function parseNameStatus(output) {
|
|
1216
1235
|
const fields = output.split("\0");
|
|
1217
1236
|
const files = [];
|
|
@@ -3409,8 +3428,7 @@ function resolveProvider(config, providerId) {
|
|
|
3409
3428
|
return provider;
|
|
3410
3429
|
}
|
|
3411
3430
|
function createAgentRunContext(runtime) {
|
|
3412
|
-
const
|
|
3413
|
-
if (!runId) throw new Error("runId is required for stable review run identity");
|
|
3431
|
+
const run = runtime.run;
|
|
3414
3432
|
const repositorySlugParts = runtime.event.repository.slug.split("/");
|
|
3415
3433
|
const repository = {
|
|
3416
3434
|
root: runtime.workspace,
|
|
@@ -3427,13 +3445,13 @@ function createAgentRunContext(runtime) {
|
|
|
3427
3445
|
const platform = { id: runtime.event.platform.id };
|
|
3428
3446
|
return {
|
|
3429
3447
|
prompt: {
|
|
3430
|
-
|
|
3448
|
+
run,
|
|
3431
3449
|
repository,
|
|
3432
3450
|
change,
|
|
3433
3451
|
platform
|
|
3434
3452
|
},
|
|
3435
3453
|
tools: {
|
|
3436
|
-
run
|
|
3454
|
+
run,
|
|
3437
3455
|
repository,
|
|
3438
3456
|
change,
|
|
3439
3457
|
platform
|
|
@@ -3696,25 +3714,6 @@ function buildRepairPrompt(options) {
|
|
|
3696
3714
|
options.prompt
|
|
3697
3715
|
].join("\n\n");
|
|
3698
3716
|
}
|
|
3699
|
-
//#endregion
|
|
3700
|
-
//#region src/review/comment-branding.ts
|
|
3701
|
-
const piprLogoUrl = "https://pipr.run/images/pipr/pipr-mark.svg";
|
|
3702
|
-
const piprRepositoryUrl = "https://github.com/somus/pipr";
|
|
3703
|
-
const mainCommentTitle = `# <img src="${piprLogoUrl}" width="22" height="22" alt=""> Pipr Review`;
|
|
3704
|
-
const mainCommentTitles = /* @__PURE__ */ new Set([
|
|
3705
|
-
"# pipr Review",
|
|
3706
|
-
"# Pipr Review",
|
|
3707
|
-
mainCommentTitle
|
|
3708
|
-
]);
|
|
3709
|
-
const mainCommentHeaderHiddenMarker = "<!-- pipr:header:hidden -->";
|
|
3710
|
-
const mainCommentFooterHiddenMarker = "<!-- pipr:footer:hidden -->";
|
|
3711
|
-
const reviewStatsStartMarker = "<!-- pipr:stats:start -->";
|
|
3712
|
-
const reviewStatsEndMarker = "<!-- pipr:stats:end -->";
|
|
3713
|
-
const reviewStatsHiddenMarker = "<!-- pipr:stats:hidden -->";
|
|
3714
|
-
const escapedRepositoryUrl = piprRepositoryUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3715
|
-
const mainCommentAttributionSource = `Review generated by \\[Pipr\\]\\(${escapedRepositoryUrl}\\) for commit \`[^\`]+\`\\.(?: Config SDK \\d+\\.\\d+\\.\\d+ is behind (?:Pipr \\d+\\.\\d+\\.\\d+|\\[Pipr \\d+\\.\\d+\\.\\d+\\]\\(${escapedRepositoryUrl}/releases/tag/v\\d+\\.\\d+\\.\\d+\\))\\.)?`;
|
|
3716
|
-
const mainCommentAttributionTextPattern = new RegExp(`^${mainCommentAttributionSource}$`);
|
|
3717
|
-
const mainCommentAttributionPattern = new RegExp(`^<sub>${mainCommentAttributionSource}</sub>$`);
|
|
3718
3717
|
const maxReviewStatsModelLength = 200;
|
|
3719
3718
|
const reviewStatsModelSchema = z.string().min(1).max(maxReviewStatsModelLength).transform((model) => sanitizeReviewStatsModel(model) ?? "[invalid model]");
|
|
3720
3719
|
const reviewStatsSchema = z.strictObject({
|
|
@@ -4601,7 +4600,7 @@ async function runInternalVerifier(options) {
|
|
|
4601
4600
|
env: options.env,
|
|
4602
4601
|
piExecutable: options.piExecutable,
|
|
4603
4602
|
piRunner: options.piRunner,
|
|
4604
|
-
|
|
4603
|
+
run: options.run,
|
|
4605
4604
|
log: options.log,
|
|
4606
4605
|
...options.piRunSink ? { piRunSink: options.piRunSink } : {}
|
|
4607
4606
|
}
|
|
@@ -4619,7 +4618,7 @@ async function runInternalVerifier(options) {
|
|
|
4619
4618
|
function verifierInput(options, prior, candidates) {
|
|
4620
4619
|
return {
|
|
4621
4620
|
manifest: options.diffManifest,
|
|
4622
|
-
runId: options.
|
|
4621
|
+
runId: options.run.id,
|
|
4623
4622
|
mode: options.mode.kind,
|
|
4624
4623
|
reviewedHeadSha: prior.reviewedHeadSha,
|
|
4625
4624
|
currentHeadSha: options.event.change.head.sha,
|
|
@@ -4720,7 +4719,6 @@ function verifierResponseBody(response) {
|
|
|
4720
4719
|
}
|
|
4721
4720
|
function internalVerifierAgent(provider, config) {
|
|
4722
4721
|
return {
|
|
4723
|
-
kind: "pipr.agent",
|
|
4724
4722
|
name: "pipr-internal-verifier",
|
|
4725
4723
|
definition: {
|
|
4726
4724
|
model: modelProfile(provider),
|
|
@@ -4739,8 +4737,8 @@ function internalVerifierAgent(provider, config) {
|
|
|
4739
4737
|
"Do not repeat user-supplied text unless needed to explain the verdict.",
|
|
4740
4738
|
config.publication.autoResolve.instructions
|
|
4741
4739
|
].filter(Boolean).join("\n"),
|
|
4742
|
-
prompt: (
|
|
4743
|
-
const { manifest: _manifest, ...verifierPromptInput } =
|
|
4740
|
+
prompt: (value) => {
|
|
4741
|
+
const { manifest: _manifest, ...verifierPromptInput } = value;
|
|
4744
4742
|
return JSON.stringify(verifierPromptInput, null, 2);
|
|
4745
4743
|
},
|
|
4746
4744
|
tools: [],
|
|
@@ -4749,15 +4747,6 @@ function internalVerifierAgent(provider, config) {
|
|
|
4749
4747
|
invalidOutput: 1,
|
|
4750
4748
|
transientFailure: 0
|
|
4751
4749
|
}
|
|
4752
|
-
},
|
|
4753
|
-
extend(patch) {
|
|
4754
|
-
return {
|
|
4755
|
-
...this,
|
|
4756
|
-
definition: {
|
|
4757
|
-
...this.definition,
|
|
4758
|
-
...patch
|
|
4759
|
-
}
|
|
4760
|
-
};
|
|
4761
4750
|
}
|
|
4762
4751
|
};
|
|
4763
4752
|
}
|
|
@@ -4779,20 +4768,6 @@ function boundedVerifierText(value) {
|
|
|
4779
4768
|
//#endregion
|
|
4780
4769
|
//#region src/review/task/task-output.ts
|
|
4781
4770
|
const agentInlineFindingsOutputSchema = z.custom((value) => z.looseObject({ inlineFindings: z.array(reviewFindingSchema) }).safeParse(value).success);
|
|
4782
|
-
const generatedReviewStatsShape = [
|
|
4783
|
-
/^$/,
|
|
4784
|
-
/^\| Metric \| Total \|$/,
|
|
4785
|
-
/^\| --- \| ---: \|$/,
|
|
4786
|
-
/^\| Models \| .+ \|$/,
|
|
4787
|
-
/^\| Agent runs \| \d+ \|$/,
|
|
4788
|
-
/^\| Elapsed \| .+ \|$/,
|
|
4789
|
-
/^\| Input tokens \| (?:Unavailable|[\d,]+(?: \(reported\))?) \|$/,
|
|
4790
|
-
/^\| Output tokens \| (?:Unavailable|[\d,]+(?: \(reported\))?) \|$/,
|
|
4791
|
-
/^\| Cost \(USD\) \| (?:Unavailable|\$\d+(?:\.\d+)?(?:e[+-]?\d+)?(?: \(reported\))?) \|$/,
|
|
4792
|
-
/^$/,
|
|
4793
|
-
/^<\/details>$/,
|
|
4794
|
-
/^<!-- pipr:stats:end -->$/
|
|
4795
|
-
];
|
|
4796
4771
|
function createOutputState() {
|
|
4797
4772
|
return {
|
|
4798
4773
|
findings: [],
|
|
@@ -4959,42 +4934,6 @@ function visibleMainComment(body) {
|
|
|
4959
4934
|
while (lines[0] === "") lines.shift();
|
|
4960
4935
|
return lines.join("\n").trim();
|
|
4961
4936
|
}
|
|
4962
|
-
function parseGeneratedMainCommentEnvelope(lines) {
|
|
4963
|
-
const mainMarkerIndex = lines.findIndex((line) => line.startsWith("<!-- pipr:main-comment "));
|
|
4964
|
-
const headerCandidateOffset = lines.slice(mainMarkerIndex + 1).findIndex((line) => line !== "");
|
|
4965
|
-
const headerCandidateIndex = mainMarkerIndex + 1 + headerCandidateOffset;
|
|
4966
|
-
const headerMarkerIndex = mainMarkerIndex >= 0 && headerCandidateOffset >= 0 && lines[headerCandidateIndex] === "<!-- pipr:header:hidden -->" ? headerCandidateIndex : -1;
|
|
4967
|
-
const lastLineIndex = lines.findLastIndex((line) => line !== "");
|
|
4968
|
-
const lastLine = lines[lastLineIndex] ?? "";
|
|
4969
|
-
const footerIndex = lastLine === "<!-- pipr:footer:hidden -->" || mainCommentAttributionPattern.test(lastLine) ? lastLineIndex : -1;
|
|
4970
|
-
const lastContentIndex = lines.slice(0, footerIndex < 0 ? lines.length : footerIndex).findLastIndex((line) => line !== "");
|
|
4971
|
-
return {
|
|
4972
|
-
mainMarkerIndex,
|
|
4973
|
-
headerMarkerIndex,
|
|
4974
|
-
statsMarkerIndex: lines[lastContentIndex] === "<!-- pipr:stats:hidden -->" ? lastContentIndex : -1,
|
|
4975
|
-
statsRange: generatedReviewStatsRange(lines, footerIndex),
|
|
4976
|
-
footerIndex
|
|
4977
|
-
};
|
|
4978
|
-
}
|
|
4979
|
-
function generatedReviewStatsRange(lines, generatedFooterIndex) {
|
|
4980
|
-
const end = lines.slice(0, generatedFooterIndex < 0 ? lines.length : generatedFooterIndex).findLastIndex((line) => line !== "");
|
|
4981
|
-
if (end < 0) return;
|
|
4982
|
-
if (lines[end] !== "<!-- pipr:stats:end -->") return;
|
|
4983
|
-
if (lines[end - 1] !== "</details>") return;
|
|
4984
|
-
const start = lines.lastIndexOf(reviewStatsStartMarker, end - 2);
|
|
4985
|
-
if (start < 0) return;
|
|
4986
|
-
if (lines[start + 1] !== "<details>") return;
|
|
4987
|
-
if (lines[start + 2] !== "<summary>Review stats</summary>") return;
|
|
4988
|
-
if (!matchesGeneratedReviewStatsShape(lines, start, end)) return;
|
|
4989
|
-
return {
|
|
4990
|
-
start,
|
|
4991
|
-
end
|
|
4992
|
-
};
|
|
4993
|
-
}
|
|
4994
|
-
function matchesGeneratedReviewStatsShape(lines, start, end) {
|
|
4995
|
-
const generatedShape = lines.slice(start + 3, end + 1);
|
|
4996
|
-
return generatedShape.length === generatedReviewStatsShape.length && generatedReviewStatsShape.every((pattern, index) => pattern.test(generatedShape[index] ?? ""));
|
|
4997
|
-
}
|
|
4998
4937
|
function collectInlineFindings(state, findings) {
|
|
4999
4938
|
if (!findings) return;
|
|
5000
4939
|
const arrayScope = state.findingScopes.get(findings);
|
|
@@ -5020,7 +4959,7 @@ const genericTaskFailureSummary = "Task failed; see logs for details.";
|
|
|
5020
4959
|
async function runTaskRuntime(options) {
|
|
5021
4960
|
const runtimeStarted = Date.now();
|
|
5022
4961
|
const config = parsePiprConfig(options.config);
|
|
5023
|
-
const provider =
|
|
4962
|
+
const provider = taskRuntimeProvider(options, config);
|
|
5024
4963
|
const diffManifest = parseDiffManifest((options.diffManifestBuilder ?? buildDiffManifest)({
|
|
5025
4964
|
cwd: options.workspace,
|
|
5026
4965
|
baseSha: options.event.change.base.sha,
|
|
@@ -5068,6 +5007,10 @@ async function runTaskRuntime(options) {
|
|
|
5068
5007
|
trustedConfigHash: options.trustedConfigHash,
|
|
5069
5008
|
commandInvocation: options.commandInvocation
|
|
5070
5009
|
});
|
|
5010
|
+
const run = Object.freeze({
|
|
5011
|
+
id: runId,
|
|
5012
|
+
trigger: taskRunTrigger(options)
|
|
5013
|
+
});
|
|
5071
5014
|
const loadedPriorReviewState = options.priorReviewState ?? await options.loadPriorReviewState?.();
|
|
5072
5015
|
const priorMainComment = options.priorMainComment ?? await options.loadPriorMainComment?.();
|
|
5073
5016
|
const priorReviewState = priorReviewStateForSelectedTasks(loadedPriorReviewState, selectedTasks);
|
|
@@ -5076,62 +5019,23 @@ async function runTaskRuntime(options) {
|
|
|
5076
5019
|
...options,
|
|
5077
5020
|
priorReviewState,
|
|
5078
5021
|
priorMainComment,
|
|
5079
|
-
|
|
5022
|
+
run,
|
|
5080
5023
|
piRunSink(run) {
|
|
5081
5024
|
piRuns.push(run);
|
|
5082
5025
|
}
|
|
5083
5026
|
};
|
|
5084
5027
|
const manifestCache = /* @__PURE__ */ new Map();
|
|
5085
|
-
const taskResults = await
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
...runtimeOptions,
|
|
5095
|
-
config,
|
|
5096
|
-
provider,
|
|
5097
|
-
diffManifest,
|
|
5098
|
-
manifestCache,
|
|
5099
|
-
output,
|
|
5100
|
-
taskName: task.name,
|
|
5101
|
-
taskOrder
|
|
5102
|
-
}), task.name === options.taskName ? options.taskInput : void 0);
|
|
5103
|
-
options.log?.info("task ok", {
|
|
5104
|
-
task: task.name,
|
|
5105
|
-
durationMs: Date.now() - started,
|
|
5106
|
-
findings: output.findings.length,
|
|
5107
|
-
providerModels: output.providerModels,
|
|
5108
|
-
repairAttempted: output.repairAttempted
|
|
5109
|
-
});
|
|
5110
|
-
return {
|
|
5111
|
-
taskName: task.name,
|
|
5112
|
-
output
|
|
5113
|
-
};
|
|
5114
|
-
} catch (error) {
|
|
5115
|
-
const check = {
|
|
5116
|
-
conclusion: "failure",
|
|
5117
|
-
summary: genericTaskFailureSummary
|
|
5118
|
-
};
|
|
5119
|
-
options.log?.error("task failed", {
|
|
5120
|
-
task: task.name,
|
|
5121
|
-
durationMs: Date.now() - started,
|
|
5122
|
-
error: error instanceof Error ? error.message : String(error)
|
|
5123
|
-
});
|
|
5124
|
-
if (options.log?.debugEnabled && error instanceof Error && error.stack) options.log.text("debug", "error stack", error.stack);
|
|
5125
|
-
return {
|
|
5126
|
-
taskName: task.name,
|
|
5127
|
-
output: {
|
|
5128
|
-
...output,
|
|
5129
|
-
check
|
|
5130
|
-
},
|
|
5131
|
-
error
|
|
5132
|
-
};
|
|
5028
|
+
const taskResults = await executeSelectedTasks({
|
|
5029
|
+
tasks,
|
|
5030
|
+
runtimeOptions: options,
|
|
5031
|
+
context: {
|
|
5032
|
+
...runtimeOptions,
|
|
5033
|
+
config,
|
|
5034
|
+
provider,
|
|
5035
|
+
diffManifest,
|
|
5036
|
+
manifestCache
|
|
5133
5037
|
}
|
|
5134
|
-
})
|
|
5038
|
+
});
|
|
5135
5039
|
const taskChecks = taskResults.map((result) => runtimeTaskCheckResult(result.taskName, result.output.check ?? { conclusion: "success" }));
|
|
5136
5040
|
const failedTask = taskResults.find((result) => result.error !== void 0);
|
|
5137
5041
|
if (failedTask) {
|
|
@@ -5144,11 +5048,20 @@ async function runTaskRuntime(options) {
|
|
|
5144
5048
|
providerModels: output.providerModels,
|
|
5145
5049
|
repairAttempted: output.repairAttempted
|
|
5146
5050
|
});
|
|
5051
|
+
const commandDurationMs = Date.now() - runtimeStarted;
|
|
5147
5052
|
const commandResponse = commandResponseResultFromOutput({
|
|
5148
5053
|
provider,
|
|
5149
5054
|
diffManifest,
|
|
5150
5055
|
output,
|
|
5151
5056
|
taskChecks,
|
|
5057
|
+
run: runSummary({
|
|
5058
|
+
options,
|
|
5059
|
+
run,
|
|
5060
|
+
selectedTasks,
|
|
5061
|
+
durationMs: commandDurationMs,
|
|
5062
|
+
models: output.providerModels.length > 0 ? uniq(output.providerModels) : [provider.model],
|
|
5063
|
+
stats: reviewStatsForRuns(piRuns, commandDurationMs)
|
|
5064
|
+
}),
|
|
5152
5065
|
commandInvocation: options.commandInvocation,
|
|
5153
5066
|
secretRedactor: options.secretRedactor
|
|
5154
5067
|
});
|
|
@@ -5157,7 +5070,7 @@ async function runTaskRuntime(options) {
|
|
|
5157
5070
|
return commandResponse;
|
|
5158
5071
|
}
|
|
5159
5072
|
assertReviewCommentOutput(output, options.commandInvocation !== void 0);
|
|
5160
|
-
const main =
|
|
5073
|
+
const main = reviewMainComment(output);
|
|
5161
5074
|
const validated = validateReviewResult(collectedReview(output, main), diffManifest, {
|
|
5162
5075
|
expectedHeadSha: options.event.change.head.sha,
|
|
5163
5076
|
pathScopeForFinding: (_finding, index) => output.findings[index]?.paths
|
|
@@ -5168,10 +5081,12 @@ async function runTaskRuntime(options) {
|
|
|
5168
5081
|
provider,
|
|
5169
5082
|
diffManifest,
|
|
5170
5083
|
priorReviewState,
|
|
5171
|
-
|
|
5084
|
+
run,
|
|
5172
5085
|
piRunSink: runtimeOptions.piRunSink
|
|
5173
5086
|
});
|
|
5174
|
-
const
|
|
5087
|
+
const durationMs = Date.now() - runtimeStarted;
|
|
5088
|
+
const stats = reviewStatsForRuns(piRuns, durationMs);
|
|
5089
|
+
const models = reviewProviderModels(output, verifier.providerModels, provider.model);
|
|
5175
5090
|
const redactedPublication = redactReviewPublication({
|
|
5176
5091
|
main,
|
|
5177
5092
|
validated,
|
|
@@ -5197,7 +5112,7 @@ async function runTaskRuntime(options) {
|
|
|
5197
5112
|
trustedConfigSha: options.trustedConfigSha,
|
|
5198
5113
|
trustedConfigHash: options.trustedConfigHash,
|
|
5199
5114
|
reviewedHeadSha: options.event.change.head.sha,
|
|
5200
|
-
providerModels:
|
|
5115
|
+
providerModels: models,
|
|
5201
5116
|
selectedTasks,
|
|
5202
5117
|
failedTasks: [],
|
|
5203
5118
|
validFindings: validated.validFindings.length,
|
|
@@ -5215,6 +5130,14 @@ async function runTaskRuntime(options) {
|
|
|
5215
5130
|
});
|
|
5216
5131
|
return {
|
|
5217
5132
|
kind: "review",
|
|
5133
|
+
run: runSummary({
|
|
5134
|
+
options,
|
|
5135
|
+
run,
|
|
5136
|
+
selectedTasks,
|
|
5137
|
+
durationMs,
|
|
5138
|
+
models,
|
|
5139
|
+
stats
|
|
5140
|
+
}),
|
|
5218
5141
|
provider,
|
|
5219
5142
|
diffManifest,
|
|
5220
5143
|
review: redactedPublication.validated.review,
|
|
@@ -5226,6 +5149,67 @@ async function runTaskRuntime(options) {
|
|
|
5226
5149
|
repairAttempted: output.repairAttempted
|
|
5227
5150
|
};
|
|
5228
5151
|
}
|
|
5152
|
+
function taskRuntimeProvider(options, config) {
|
|
5153
|
+
return options.providerOverride ? parseProviderConfig(options.providerOverride) : resolveProvider(config, config.defaultProvider);
|
|
5154
|
+
}
|
|
5155
|
+
function taskRunTrigger(options) {
|
|
5156
|
+
if (options.runTrigger) return options.runTrigger;
|
|
5157
|
+
return options.commandInvocation ? "command" : "change-request";
|
|
5158
|
+
}
|
|
5159
|
+
function reviewMainComment(output) {
|
|
5160
|
+
return typeof output.comment.value === "string" ? output.comment.value : output.comment.value.main ?? "Review completed.";
|
|
5161
|
+
}
|
|
5162
|
+
function reviewProviderModels(output, verifierModels, fallbackModel) {
|
|
5163
|
+
return output.providerModels.length + verifierModels.length > 0 ? uniq([...output.providerModels, ...verifierModels]) : [fallbackModel];
|
|
5164
|
+
}
|
|
5165
|
+
async function executeSelectedTasks(options) {
|
|
5166
|
+
return Promise.all(options.tasks.map(async (task, taskOrder) => {
|
|
5167
|
+
const output = createOutputState();
|
|
5168
|
+
const started = Date.now();
|
|
5169
|
+
options.runtimeOptions.log?.info("task start", {
|
|
5170
|
+
task: task.name,
|
|
5171
|
+
order: taskOrder
|
|
5172
|
+
});
|
|
5173
|
+
try {
|
|
5174
|
+
await task.handler(createTaskContext({
|
|
5175
|
+
...options.context,
|
|
5176
|
+
output,
|
|
5177
|
+
taskName: task.name,
|
|
5178
|
+
taskOrder
|
|
5179
|
+
}), task.name === options.runtimeOptions.taskName ? options.runtimeOptions.taskInput : void 0);
|
|
5180
|
+
options.runtimeOptions.log?.info("task ok", {
|
|
5181
|
+
task: task.name,
|
|
5182
|
+
durationMs: Date.now() - started,
|
|
5183
|
+
findings: output.findings.length,
|
|
5184
|
+
providerModels: output.providerModels,
|
|
5185
|
+
repairAttempted: output.repairAttempted
|
|
5186
|
+
});
|
|
5187
|
+
return {
|
|
5188
|
+
taskName: task.name,
|
|
5189
|
+
output
|
|
5190
|
+
};
|
|
5191
|
+
} catch (error) {
|
|
5192
|
+
const check = {
|
|
5193
|
+
conclusion: "failure",
|
|
5194
|
+
summary: genericTaskFailureSummary
|
|
5195
|
+
};
|
|
5196
|
+
options.runtimeOptions.log?.error("task failed", {
|
|
5197
|
+
task: task.name,
|
|
5198
|
+
durationMs: Date.now() - started,
|
|
5199
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5200
|
+
});
|
|
5201
|
+
if (options.runtimeOptions.log?.debugEnabled && error instanceof Error && error.stack) options.runtimeOptions.log.text("debug", "error stack", error.stack);
|
|
5202
|
+
return {
|
|
5203
|
+
taskName: task.name,
|
|
5204
|
+
output: {
|
|
5205
|
+
...output,
|
|
5206
|
+
check
|
|
5207
|
+
},
|
|
5208
|
+
error
|
|
5209
|
+
};
|
|
5210
|
+
}
|
|
5211
|
+
}));
|
|
5212
|
+
}
|
|
5229
5213
|
function publishFailedRunTaskChecks(options, taskChecks) {
|
|
5230
5214
|
const redacted = redactCommandPublication({
|
|
5231
5215
|
body: "",
|
|
@@ -5234,6 +5218,22 @@ function publishFailedRunTaskChecks(options, taskChecks) {
|
|
|
5234
5218
|
});
|
|
5235
5219
|
publishTaskChecks(options.checkSink, redacted.taskChecks);
|
|
5236
5220
|
}
|
|
5221
|
+
function runSummary(options) {
|
|
5222
|
+
const { agentRuns = 0, inputTokens = 0, outputTokens = 0, costUsd = 0, usageStatus = "unavailable" } = options.stats ?? {};
|
|
5223
|
+
return {
|
|
5224
|
+
...options.run,
|
|
5225
|
+
baseSha: options.options.event.change.base.sha,
|
|
5226
|
+
headSha: options.options.event.change.head.sha,
|
|
5227
|
+
tasks: options.selectedTasks,
|
|
5228
|
+
durationMs: options.durationMs,
|
|
5229
|
+
models: options.models,
|
|
5230
|
+
agentRuns,
|
|
5231
|
+
inputTokens,
|
|
5232
|
+
outputTokens,
|
|
5233
|
+
costUsd,
|
|
5234
|
+
usageStatus
|
|
5235
|
+
};
|
|
5236
|
+
}
|
|
5237
5237
|
function commandResponseResultFromOutput(options) {
|
|
5238
5238
|
const commandResponse = options.output.commandResponse;
|
|
5239
5239
|
if (!commandResponse) return;
|
|
@@ -5270,7 +5270,7 @@ async function runSynchronizeVerifier(options) {
|
|
|
5270
5270
|
priorReviewState: options.priorReviewState,
|
|
5271
5271
|
threadContexts: await options.options.loadInlineThreadContexts?.() ?? [],
|
|
5272
5272
|
mode: { kind: "synchronize" },
|
|
5273
|
-
|
|
5273
|
+
run: options.run,
|
|
5274
5274
|
piRunSink: options.piRunSink
|
|
5275
5275
|
});
|
|
5276
5276
|
}
|
|
@@ -5278,7 +5278,7 @@ function createTaskContext(options) {
|
|
|
5278
5278
|
const repositorySlugParts = options.event.repository.slug.split("/");
|
|
5279
5279
|
let taskContext;
|
|
5280
5280
|
taskContext = {
|
|
5281
|
-
run:
|
|
5281
|
+
run: options.run,
|
|
5282
5282
|
repository: {
|
|
5283
5283
|
root: options.workspace,
|
|
5284
5284
|
owner: repositorySlugParts.length > 1 ? repositorySlugParts[0] : void 0,
|
|
@@ -5307,9 +5307,6 @@ function createTaskContext(options) {
|
|
|
5307
5307
|
previousPath: file.previousPath,
|
|
5308
5308
|
status: file.status
|
|
5309
5309
|
}));
|
|
5310
|
-
},
|
|
5311
|
-
async currentHeadSha() {
|
|
5312
|
-
return options.event.change.head.sha;
|
|
5313
5310
|
}
|
|
5314
5311
|
},
|
|
5315
5312
|
platform: { id: options.event.platform.id },
|
|
@@ -5326,13 +5323,13 @@ function createTaskContext(options) {
|
|
|
5326
5323
|
},
|
|
5327
5324
|
pi: { async run(agent, input, runOptions) {
|
|
5328
5325
|
const result = await runReviewAgent({
|
|
5329
|
-
agent,
|
|
5326
|
+
agent: options.plan.resolveAgent(agent),
|
|
5330
5327
|
input,
|
|
5331
5328
|
runOptions,
|
|
5332
5329
|
runtime: {
|
|
5333
5330
|
...options,
|
|
5334
5331
|
taskContext,
|
|
5335
|
-
|
|
5332
|
+
run: options.run,
|
|
5336
5333
|
piRunSink: options.piRunSink
|
|
5337
5334
|
}
|
|
5338
5335
|
});
|
|
@@ -5371,6 +5368,7 @@ function commandResponseRuntimeResult(options) {
|
|
|
5371
5368
|
});
|
|
5372
5369
|
return {
|
|
5373
5370
|
kind: "command-response",
|
|
5371
|
+
run: options.run,
|
|
5374
5372
|
provider: options.provider,
|
|
5375
5373
|
diffManifest: options.diffManifest,
|
|
5376
5374
|
taskChecks: redacted.taskChecks,
|
|
@@ -5461,6 +5459,134 @@ function createKnownSecretRedactor(options) {
|
|
|
5461
5459
|
return createSecretRedactor(sensitiveEnvironmentValues(options?.env ?? process.env));
|
|
5462
5460
|
}
|
|
5463
5461
|
//#endregion
|
|
5462
|
+
//#region src/review/inline-publication-policy.ts
|
|
5463
|
+
function inlinePublicationDecision(options) {
|
|
5464
|
+
if (options.existing.markers.has(options.marker) || hasExistingInlinePublicationLocation(options.existing.locations, options.location)) return "skip";
|
|
5465
|
+
return "post";
|
|
5466
|
+
}
|
|
5467
|
+
function hasExistingInlinePublicationLocation(existing, location) {
|
|
5468
|
+
return existing.some((comment) => {
|
|
5469
|
+
if (comment.path !== location.path || comment.commitId !== location.commitId || comment.side !== location.side) return false;
|
|
5470
|
+
return comment.startLine <= location.endLine && location.startLine <= comment.endLine;
|
|
5471
|
+
});
|
|
5472
|
+
}
|
|
5473
|
+
//#endregion
|
|
5474
|
+
//#region src/review/publication-result.ts
|
|
5475
|
+
/** Error thrown when publication fails after producing partial result metadata. */
|
|
5476
|
+
var PublicationError = class extends Error {
|
|
5477
|
+
result;
|
|
5478
|
+
constructor(message, result) {
|
|
5479
|
+
super(message);
|
|
5480
|
+
this.result = result;
|
|
5481
|
+
}
|
|
5482
|
+
};
|
|
5483
|
+
//#endregion
|
|
5484
|
+
//#region src/hosts/publication.ts
|
|
5485
|
+
async function publishUnseenInlineItems(options) {
|
|
5486
|
+
const existing = new Set(extractInlineFindingMarkerRecords(options.existingBodies).map((record) => `${record.id}:${record.head}`));
|
|
5487
|
+
const errors = [];
|
|
5488
|
+
let posted = 0;
|
|
5489
|
+
let skipped = 0;
|
|
5490
|
+
for (const item of options.items) {
|
|
5491
|
+
const marker = `${item.findingId}:${item.reviewedHeadSha}`;
|
|
5492
|
+
const location = options.location?.(item);
|
|
5493
|
+
if (existing.has(marker) || location !== void 0 && inlinePublicationDecision({
|
|
5494
|
+
marker,
|
|
5495
|
+
location,
|
|
5496
|
+
existing: {
|
|
5497
|
+
markers: existing,
|
|
5498
|
+
locations: options.existingLocations ?? []
|
|
5499
|
+
}
|
|
5500
|
+
}) === "skip") {
|
|
5501
|
+
skipped += 1;
|
|
5502
|
+
continue;
|
|
5503
|
+
}
|
|
5504
|
+
try {
|
|
5505
|
+
await options.publish(item);
|
|
5506
|
+
posted += 1;
|
|
5507
|
+
existing.add(marker);
|
|
5508
|
+
if (location) options.existingLocations?.push(location);
|
|
5509
|
+
} catch (error) {
|
|
5510
|
+
errors.push(error instanceof Error ? error.message : String(error));
|
|
5511
|
+
}
|
|
5512
|
+
}
|
|
5513
|
+
return {
|
|
5514
|
+
posted,
|
|
5515
|
+
skipped,
|
|
5516
|
+
errors
|
|
5517
|
+
};
|
|
5518
|
+
}
|
|
5519
|
+
function nativeInlineLocation(options) {
|
|
5520
|
+
const rightSide = options.rightEnd !== void 0;
|
|
5521
|
+
const endLine = rightSide ? options.rightEnd : options.leftEnd;
|
|
5522
|
+
if (endLine === void 0) return void 0;
|
|
5523
|
+
return {
|
|
5524
|
+
path: rightSide ? options.rightPath : options.leftPath,
|
|
5525
|
+
commitId: options.commitId,
|
|
5526
|
+
side: rightSide ? "RIGHT" : "LEFT",
|
|
5527
|
+
startLine: (rightSide ? options.rightStart : options.leftStart) ?? endLine,
|
|
5528
|
+
endLine
|
|
5529
|
+
};
|
|
5530
|
+
}
|
|
5531
|
+
function commandResponseBody(options) {
|
|
5532
|
+
const marker = `<!-- pipr:command-response change=${options.changeNumber} source=${options.sourceCommentId} command=${options.commandName} -->`;
|
|
5533
|
+
return {
|
|
5534
|
+
marker,
|
|
5535
|
+
body: [
|
|
5536
|
+
marker,
|
|
5537
|
+
"",
|
|
5538
|
+
options.body,
|
|
5539
|
+
""
|
|
5540
|
+
].join("\n")
|
|
5541
|
+
};
|
|
5542
|
+
}
|
|
5543
|
+
function commandStatusText(options) {
|
|
5544
|
+
return [
|
|
5545
|
+
`<!-- pipr:command-state state=${options.state} head=${options.reviewedHeadSha} -->`,
|
|
5546
|
+
"",
|
|
5547
|
+
{
|
|
5548
|
+
accepted: "Pipr accepted this command.",
|
|
5549
|
+
running: "Pipr is running this command.",
|
|
5550
|
+
completed: "Pipr completed this command.",
|
|
5551
|
+
failed: "Pipr could not complete this command; see the run log for details.",
|
|
5552
|
+
superseded: "Pipr stopped because the change request head was updated."
|
|
5553
|
+
}[options.state]
|
|
5554
|
+
].join("\n");
|
|
5555
|
+
}
|
|
5556
|
+
function threadActionReply(action) {
|
|
5557
|
+
const marker = action.kind === "resolve" ? renderResolvedFindingMarker(action.findingId, action.findingHeadSha) : renderVerifierResponseMarker(action.findingId, action.responseKey);
|
|
5558
|
+
return {
|
|
5559
|
+
marker,
|
|
5560
|
+
body: [
|
|
5561
|
+
marker,
|
|
5562
|
+
"",
|
|
5563
|
+
action.body.replaceAll("<!--", "<!--")
|
|
5564
|
+
].join("\n")
|
|
5565
|
+
};
|
|
5566
|
+
}
|
|
5567
|
+
function completeHostPublication(options) {
|
|
5568
|
+
const partial = {
|
|
5569
|
+
inlineComments: {
|
|
5570
|
+
posted: options.inline.posted,
|
|
5571
|
+
skipped: options.inline.skipped,
|
|
5572
|
+
failed: options.inline.errors.length
|
|
5573
|
+
},
|
|
5574
|
+
metadata: {
|
|
5575
|
+
...options.metadata,
|
|
5576
|
+
inlinePublicationErrors: options.inline.errors,
|
|
5577
|
+
inlineResolutionErrors: options.resolutionErrors
|
|
5578
|
+
}
|
|
5579
|
+
};
|
|
5580
|
+
if (options.inline.errors.length > 0) throw new PublicationError(`${options.provider} inline comment publication failed`, partial);
|
|
5581
|
+
return {
|
|
5582
|
+
mainComment: {
|
|
5583
|
+
action: options.mainAction,
|
|
5584
|
+
id: options.mainId
|
|
5585
|
+
},
|
|
5586
|
+
...partial
|
|
5587
|
+
};
|
|
5588
|
+
}
|
|
5589
|
+
//#endregion
|
|
5464
5590
|
//#region src/hosts/http.ts
|
|
5465
5591
|
var CodeHostHttpError = class extends Error {
|
|
5466
5592
|
status;
|
|
@@ -6032,121 +6158,6 @@ function azureRepositoryUrl(organization, project, repository) {
|
|
|
6032
6158
|
return `https://dev.azure.com/${encodeURIComponent(organization)}/${encodeURIComponent(project)}/_git/${encodeURIComponent(repository)}`;
|
|
6033
6159
|
}
|
|
6034
6160
|
//#endregion
|
|
6035
|
-
//#region src/review/inline-publication-policy.ts
|
|
6036
|
-
function inlinePublicationDecision(options) {
|
|
6037
|
-
if (options.existing.markers.has(options.marker) || hasExistingInlinePublicationLocation(options.existing.locations, options.location)) return "skip";
|
|
6038
|
-
return "post";
|
|
6039
|
-
}
|
|
6040
|
-
function hasExistingInlinePublicationLocation(existing, location) {
|
|
6041
|
-
return existing.some((comment) => {
|
|
6042
|
-
if (comment.path !== location.path || comment.commitId !== location.commitId || comment.side !== location.side) return false;
|
|
6043
|
-
return comment.startLine <= location.endLine && location.startLine <= comment.endLine;
|
|
6044
|
-
});
|
|
6045
|
-
}
|
|
6046
|
-
//#endregion
|
|
6047
|
-
//#region src/review/publication-result.ts
|
|
6048
|
-
/** Error thrown when publication fails after producing partial result metadata. */
|
|
6049
|
-
var PublicationError = class extends Error {
|
|
6050
|
-
result;
|
|
6051
|
-
constructor(message, result) {
|
|
6052
|
-
super(message);
|
|
6053
|
-
this.result = result;
|
|
6054
|
-
}
|
|
6055
|
-
};
|
|
6056
|
-
//#endregion
|
|
6057
|
-
//#region src/hosts/publication.ts
|
|
6058
|
-
async function publishUnseenInlineItems(options) {
|
|
6059
|
-
const existing = new Set(extractInlineFindingMarkerRecords(options.existingBodies).map((record) => `${record.id}:${record.head}`));
|
|
6060
|
-
const errors = [];
|
|
6061
|
-
let posted = 0;
|
|
6062
|
-
let skipped = 0;
|
|
6063
|
-
for (const item of options.items) {
|
|
6064
|
-
const marker = `${item.findingId}:${item.reviewedHeadSha}`;
|
|
6065
|
-
const location = options.location?.(item);
|
|
6066
|
-
if (existing.has(marker) || location !== void 0 && inlinePublicationDecision({
|
|
6067
|
-
marker,
|
|
6068
|
-
location,
|
|
6069
|
-
existing: {
|
|
6070
|
-
markers: existing,
|
|
6071
|
-
locations: options.existingLocations ?? []
|
|
6072
|
-
}
|
|
6073
|
-
}) === "skip") {
|
|
6074
|
-
skipped += 1;
|
|
6075
|
-
continue;
|
|
6076
|
-
}
|
|
6077
|
-
try {
|
|
6078
|
-
await options.publish(item);
|
|
6079
|
-
posted += 1;
|
|
6080
|
-
existing.add(marker);
|
|
6081
|
-
if (location) options.existingLocations?.push(location);
|
|
6082
|
-
} catch (error) {
|
|
6083
|
-
errors.push(error instanceof Error ? error.message : String(error));
|
|
6084
|
-
}
|
|
6085
|
-
}
|
|
6086
|
-
return {
|
|
6087
|
-
posted,
|
|
6088
|
-
skipped,
|
|
6089
|
-
errors
|
|
6090
|
-
};
|
|
6091
|
-
}
|
|
6092
|
-
function nativeInlineLocation(options) {
|
|
6093
|
-
const rightSide = options.rightEnd !== void 0;
|
|
6094
|
-
const endLine = rightSide ? options.rightEnd : options.leftEnd;
|
|
6095
|
-
if (endLine === void 0) return void 0;
|
|
6096
|
-
return {
|
|
6097
|
-
path: rightSide ? options.rightPath : options.leftPath,
|
|
6098
|
-
commitId: options.commitId,
|
|
6099
|
-
side: rightSide ? "RIGHT" : "LEFT",
|
|
6100
|
-
startLine: (rightSide ? options.rightStart : options.leftStart) ?? endLine,
|
|
6101
|
-
endLine
|
|
6102
|
-
};
|
|
6103
|
-
}
|
|
6104
|
-
function commandResponseBody(options) {
|
|
6105
|
-
const marker = `<!-- pipr:command-response change=${options.changeNumber} source=${options.sourceCommentId} command=${options.commandName} -->`;
|
|
6106
|
-
return {
|
|
6107
|
-
marker,
|
|
6108
|
-
body: [
|
|
6109
|
-
marker,
|
|
6110
|
-
"",
|
|
6111
|
-
options.body,
|
|
6112
|
-
""
|
|
6113
|
-
].join("\n")
|
|
6114
|
-
};
|
|
6115
|
-
}
|
|
6116
|
-
function threadActionReply(action) {
|
|
6117
|
-
const marker = action.kind === "resolve" ? renderResolvedFindingMarker(action.findingId, action.findingHeadSha) : renderVerifierResponseMarker(action.findingId, action.responseKey);
|
|
6118
|
-
return {
|
|
6119
|
-
marker,
|
|
6120
|
-
body: [
|
|
6121
|
-
marker,
|
|
6122
|
-
"",
|
|
6123
|
-
action.body.replaceAll("<!--", "<!--")
|
|
6124
|
-
].join("\n")
|
|
6125
|
-
};
|
|
6126
|
-
}
|
|
6127
|
-
function completeHostPublication(options) {
|
|
6128
|
-
const partial = {
|
|
6129
|
-
inlineComments: {
|
|
6130
|
-
posted: options.inline.posted,
|
|
6131
|
-
skipped: options.inline.skipped,
|
|
6132
|
-
failed: options.inline.errors.length
|
|
6133
|
-
},
|
|
6134
|
-
metadata: {
|
|
6135
|
-
...options.metadata,
|
|
6136
|
-
inlinePublicationErrors: options.inline.errors,
|
|
6137
|
-
inlineResolutionErrors: options.resolutionErrors
|
|
6138
|
-
}
|
|
6139
|
-
};
|
|
6140
|
-
if (options.inline.errors.length > 0) throw new PublicationError(`${options.provider} inline comment publication failed`, partial);
|
|
6141
|
-
return {
|
|
6142
|
-
mainComment: {
|
|
6143
|
-
action: options.mainAction,
|
|
6144
|
-
id: options.mainId
|
|
6145
|
-
},
|
|
6146
|
-
...partial
|
|
6147
|
-
};
|
|
6148
|
-
}
|
|
6149
|
-
//#endregion
|
|
6150
6161
|
//#region src/hosts/azure-devops/publication.ts
|
|
6151
6162
|
async function publishAzureDevOpsPlan(options) {
|
|
6152
6163
|
const coordinates = azureCoordinates$1(options.change);
|
|
@@ -6226,8 +6237,11 @@ async function publishAzureDevOpsCommandResponse(options) {
|
|
|
6226
6237
|
commandName: options.commandName,
|
|
6227
6238
|
body: options.body
|
|
6228
6239
|
});
|
|
6229
|
-
await currentPullRequest(options.client, options.change);
|
|
6230
|
-
const { owner, threads } =
|
|
6240
|
+
if (!options.allowHeadDrift) await currentPullRequest(options.client, options.change);
|
|
6241
|
+
const { owner, threads } = options.allowHeadDrift ? {
|
|
6242
|
+
owner: await authenticatedAzureOwner(options.client),
|
|
6243
|
+
threads: await options.client.listThreads(coordinates.repositoryId, options.change.change.number)
|
|
6244
|
+
} : await loadAzureWriteState(options.client, options.change);
|
|
6231
6245
|
const existing = ownedRootThread(threads, owner.uniqueName, response.marker);
|
|
6232
6246
|
const comment = existing ? await options.client.updateComment(coordinates.repositoryId, options.change.change.number, existing.id, existing.comments[0]?.id ?? "", response.body) : (await options.client.createThread(coordinates.repositoryId, options.change.change.number, unpositionedThread(response.body))).comments[0];
|
|
6233
6247
|
if (!comment) throw new Error("Azure DevOps did not return the command response comment");
|
|
@@ -6564,6 +6578,12 @@ function createAzureDevOpsHostAdapter(options = {}) {
|
|
|
6564
6578
|
client,
|
|
6565
6579
|
...args
|
|
6566
6580
|
}),
|
|
6581
|
+
publishCommandStatus: (args) => publishAzureDevOpsCommandResponse({
|
|
6582
|
+
client,
|
|
6583
|
+
...args,
|
|
6584
|
+
body: commandStatusText(args),
|
|
6585
|
+
allowHeadDrift: true
|
|
6586
|
+
}),
|
|
6567
6587
|
publishThreadActions: (args) => publishAzureDevOpsThreadActions({
|
|
6568
6588
|
client,
|
|
6569
6589
|
...args
|
|
@@ -7054,8 +7074,11 @@ async function publishBitbucketCommandResponse(options) {
|
|
|
7054
7074
|
commandName: options.commandName,
|
|
7055
7075
|
body: options.body
|
|
7056
7076
|
});
|
|
7057
|
-
await assertCurrentEndpoints(options.client, options.change);
|
|
7058
|
-
const { owner, comments } =
|
|
7077
|
+
if (!options.allowHeadDrift) await assertCurrentEndpoints(options.client, options.change);
|
|
7078
|
+
const { owner, comments } = options.allowHeadDrift ? {
|
|
7079
|
+
owner: await authenticatedBitbucketOwner(options.client),
|
|
7080
|
+
comments: await options.client.listComments(options.change.change.number)
|
|
7081
|
+
} : await loadBitbucketWriteState(options.client, options.change);
|
|
7059
7082
|
const existing = comments.find((comment) => comment.user?.uuid === owner.uuid && normalizeBitbucketMarkdown(comment.content.raw).includes(response.marker));
|
|
7060
7083
|
const responseBody = renderBitbucketMarkdown(response.body);
|
|
7061
7084
|
const comment = existing ? await options.client.updateComment(options.change.change.number, existing.id, responseBody) : await options.client.createComment(options.change.change.number, { content: { raw: responseBody } });
|
|
@@ -7241,6 +7264,12 @@ function createBitbucketHostAdapter(options = {}) {
|
|
|
7241
7264
|
client,
|
|
7242
7265
|
...args
|
|
7243
7266
|
}),
|
|
7267
|
+
publishCommandStatus: (args) => publishBitbucketCommandResponse({
|
|
7268
|
+
client,
|
|
7269
|
+
...args,
|
|
7270
|
+
body: commandStatusText(args),
|
|
7271
|
+
allowHeadDrift: true
|
|
7272
|
+
}),
|
|
7244
7273
|
publishThreadActions: (args) => publishBitbucketThreadActions({
|
|
7245
7274
|
client,
|
|
7246
7275
|
...args
|
|
@@ -7895,32 +7924,26 @@ function findMainComment(comments, marker, changeNumber, ownerLogin) {
|
|
|
7895
7924
|
}
|
|
7896
7925
|
//#endregion
|
|
7897
7926
|
//#region src/hosts/github/publication-command-response.ts
|
|
7898
|
-
const commandResponseMarker = "pipr:command-response";
|
|
7899
7927
|
async function publishGitHubCommandResponse(options) {
|
|
7900
|
-
await assertCurrentHeadSha(options.client, options.change, options.change.change.head.sha);
|
|
7928
|
+
if (!options.allowHeadDrift) await assertCurrentHeadSha(options.client, options.change, options.change.change.head.sha);
|
|
7901
7929
|
const ownerLogin = await options.client.getAuthenticatedUserLogin();
|
|
7902
|
-
const
|
|
7930
|
+
const response = commandResponseBody({
|
|
7903
7931
|
changeNumber: options.change.change.number,
|
|
7904
|
-
sourceCommentId: options.sourceCommentId,
|
|
7905
|
-
commandName: options.commandName
|
|
7932
|
+
sourceCommentId: String(options.sourceCommentId),
|
|
7933
|
+
commandName: options.commandName,
|
|
7934
|
+
body: options.body
|
|
7906
7935
|
});
|
|
7907
|
-
const body = [
|
|
7908
|
-
marker,
|
|
7909
|
-
"",
|
|
7910
|
-
options.body,
|
|
7911
|
-
""
|
|
7912
|
-
].join("\n");
|
|
7913
7936
|
const comments = await options.client.listIssueComments({
|
|
7914
7937
|
repo: options.change.repository.slug,
|
|
7915
7938
|
issueNumber: options.change.change.number
|
|
7916
7939
|
});
|
|
7917
|
-
await assertCurrentHeadSha(options.client, options.change, options.change.change.head.sha);
|
|
7918
|
-
const existing = findCommandResponseComment(comments, marker, ownerLogin);
|
|
7940
|
+
if (!options.allowHeadDrift) await assertCurrentHeadSha(options.client, options.change, options.change.change.head.sha);
|
|
7941
|
+
const existing = findCommandResponseComment(comments, response.marker, ownerLogin);
|
|
7919
7942
|
if (existing) {
|
|
7920
7943
|
const updated = await options.client.updateIssueComment({
|
|
7921
7944
|
repo: options.change.repository.slug,
|
|
7922
7945
|
commentId: existing.id,
|
|
7923
|
-
body
|
|
7946
|
+
body: response.body
|
|
7924
7947
|
});
|
|
7925
7948
|
return {
|
|
7926
7949
|
action: "updated",
|
|
@@ -7930,7 +7953,7 @@ async function publishGitHubCommandResponse(options) {
|
|
|
7930
7953
|
const created = await options.client.createIssueComment({
|
|
7931
7954
|
repo: options.change.repository.slug,
|
|
7932
7955
|
issueNumber: options.change.change.number,
|
|
7933
|
-
body
|
|
7956
|
+
body: response.body
|
|
7934
7957
|
});
|
|
7935
7958
|
return {
|
|
7936
7959
|
action: "created",
|
|
@@ -7940,9 +7963,6 @@ async function publishGitHubCommandResponse(options) {
|
|
|
7940
7963
|
function findCommandResponseComment(comments, marker, ownerLogin) {
|
|
7941
7964
|
return findOwnedIssueComment(comments, ownerLogin, (firstLine) => firstLine === marker);
|
|
7942
7965
|
}
|
|
7943
|
-
function renderCommandResponseMarker(options) {
|
|
7944
|
-
return `<!-- ${commandResponseMarker} change=${options.changeNumber} source=${options.sourceCommentId} command=${options.commandName} -->`;
|
|
7945
|
-
}
|
|
7946
7966
|
//#endregion
|
|
7947
7967
|
//#region src/hosts/github/publication-prior-state.ts
|
|
7948
7968
|
async function loadGitHubPriorReviewState(options) {
|
|
@@ -8486,6 +8506,16 @@ function createGitHubHostAdapter(options = {}) {
|
|
|
8486
8506
|
body: options.body
|
|
8487
8507
|
});
|
|
8488
8508
|
},
|
|
8509
|
+
publishCommandStatus(options) {
|
|
8510
|
+
return publishGitHubCommandResponse({
|
|
8511
|
+
client: publicationClient,
|
|
8512
|
+
change: options.change,
|
|
8513
|
+
sourceCommentId: Number(options.sourceCommentId),
|
|
8514
|
+
commandName: options.commandName,
|
|
8515
|
+
body: commandStatusText(options),
|
|
8516
|
+
allowHeadDrift: true
|
|
8517
|
+
});
|
|
8518
|
+
},
|
|
8489
8519
|
publishThreadActions(options) {
|
|
8490
8520
|
return publishGitHubThreadActions({
|
|
8491
8521
|
client: publicationClient,
|
|
@@ -8988,7 +9018,7 @@ async function publishGitLabCommandResponse(options) {
|
|
|
8988
9018
|
body: options.body
|
|
8989
9019
|
});
|
|
8990
9020
|
const existing = ownedNote(await options.client.listNotes(projectId, options.change.change.number), owner.username, response.marker);
|
|
8991
|
-
await assertCurrentHead(options.client, projectId, options.change);
|
|
9021
|
+
if (!options.allowHeadDrift) await assertCurrentHead(options.client, projectId, options.change);
|
|
8992
9022
|
const note = existing ? await options.client.updateNote(projectId, options.change.change.number, existing.id, response.body) : await options.client.createNote(projectId, options.change.change.number, response.body);
|
|
8993
9023
|
return {
|
|
8994
9024
|
action: existing ? "updated" : "created",
|
|
@@ -9178,6 +9208,12 @@ function createGitLabHostAdapter(options = {}) {
|
|
|
9178
9208
|
client,
|
|
9179
9209
|
...args
|
|
9180
9210
|
}),
|
|
9211
|
+
publishCommandStatus: (args) => publishGitLabCommandResponse({
|
|
9212
|
+
client,
|
|
9213
|
+
...args,
|
|
9214
|
+
body: commandStatusText(args),
|
|
9215
|
+
allowHeadDrift: true
|
|
9216
|
+
}),
|
|
9181
9217
|
publishThreadActions: (args) => publishGitLabThreadActions({
|
|
9182
9218
|
client,
|
|
9183
9219
|
...args
|
|
@@ -9541,6 +9577,7 @@ async function runTrustedReviewAndPublish(options) {
|
|
|
9541
9577
|
await finalizeRuntimeChecks(checks, {});
|
|
9542
9578
|
return {
|
|
9543
9579
|
kind: "command-response",
|
|
9580
|
+
run: review.run,
|
|
9544
9581
|
response: {
|
|
9545
9582
|
commandName: review.commandResponse.commandName,
|
|
9546
9583
|
body: review.commandResponse.body
|
|
@@ -9814,6 +9851,11 @@ function runnableIssueCommentCommand(comment, dryRun) {
|
|
|
9814
9851
|
};
|
|
9815
9852
|
}
|
|
9816
9853
|
async function dispatchIssueCommentCommand(options, adapter, prepared, log) {
|
|
9854
|
+
const runnable = await resolveRunnableCommand(adapter, prepared, log);
|
|
9855
|
+
if (runnable.kind !== "matched") return runnable;
|
|
9856
|
+
return await runCommandLifecycle(options, adapter, prepared, runnable.invocation, log);
|
|
9857
|
+
}
|
|
9858
|
+
async function resolveRunnableCommand(adapter, prepared, log) {
|
|
9817
9859
|
const requiredPermission = prepared.resolution.kind === "matched" ? prepared.resolution.invocation.requiredPermission : prepared.resolution.requiredPermission;
|
|
9818
9860
|
const permission = await logPhase(log, "check command permission", async () => adapter.permissions.getRepositoryPermission({
|
|
9819
9861
|
change: prepared.event,
|
|
@@ -9850,36 +9892,93 @@ async function dispatchIssueCommentCommand(options, adapter, prepared, log) {
|
|
|
9850
9892
|
kind: "ignored",
|
|
9851
9893
|
reason: "command dispatch did not resolve to a runnable task"
|
|
9852
9894
|
};
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
|
|
9895
|
+
return parsedResolution;
|
|
9896
|
+
}
|
|
9897
|
+
async function runCommandLifecycle(options, adapter, prepared, invocation, log) {
|
|
9898
|
+
const status = adapter.publication?.publishCommandStatus;
|
|
9899
|
+
if (!status) throw new Error("command status publication is not available for this code host");
|
|
9900
|
+
const statusOptions = {
|
|
9901
|
+
change: prepared.event,
|
|
9902
|
+
sourceCommentId: prepared.comment.commentId,
|
|
9903
|
+
commandName: invocation.commandName,
|
|
9904
|
+
reviewedHeadSha: prepared.event.change.head.sha
|
|
9905
|
+
};
|
|
9906
|
+
await status({
|
|
9907
|
+
...statusOptions,
|
|
9908
|
+
state: "accepted"
|
|
9859
9909
|
});
|
|
9860
|
-
|
|
9861
|
-
adapter,
|
|
9862
|
-
|
|
9863
|
-
|
|
9910
|
+
try {
|
|
9911
|
+
await prepareTrustedHeadCheckout(options, adapter, prepared.trustedRuntime.settings.config, prepared.event, log);
|
|
9912
|
+
const dispatch = dispatchRuntimeEntry({
|
|
9913
|
+
kind: "change-request",
|
|
9914
|
+
plan: prepared.trustedRuntime.plan,
|
|
9915
|
+
event: prepared.event,
|
|
9916
|
+
taskName: invocation.taskName
|
|
9917
|
+
});
|
|
9918
|
+
await status({
|
|
9919
|
+
...statusOptions,
|
|
9920
|
+
state: "running"
|
|
9921
|
+
});
|
|
9922
|
+
const result = await issueCommentCommandResult({
|
|
9864
9923
|
adapter,
|
|
9865
|
-
|
|
9924
|
+
completed: await runTrustedReviewAndPublish({
|
|
9925
|
+
options,
|
|
9926
|
+
adapter,
|
|
9927
|
+
trustedRuntime: prepared.trustedRuntime,
|
|
9928
|
+
event: prepared.event,
|
|
9929
|
+
taskName: invocation.taskName,
|
|
9930
|
+
taskInput: invocation.inputs,
|
|
9931
|
+
selectedTasks: dispatch.kind === "change-request" ? dispatch.tasks : [],
|
|
9932
|
+
commandInvocation: {
|
|
9933
|
+
name: invocation.commandName,
|
|
9934
|
+
line: invocation.line,
|
|
9935
|
+
arguments: invocation.arguments,
|
|
9936
|
+
sourceCommentId: prepared.comment.commentId
|
|
9937
|
+
},
|
|
9938
|
+
log
|
|
9939
|
+
}),
|
|
9866
9940
|
event: prepared.event,
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9941
|
+
commandName: invocation.commandName,
|
|
9942
|
+
sourceCommentId: prepared.comment.commentId,
|
|
9943
|
+
configSource: prepared.trustedRuntime.settings.source
|
|
9944
|
+
});
|
|
9945
|
+
if (result.kind === "review") await status({
|
|
9946
|
+
...statusOptions,
|
|
9947
|
+
state: "completed"
|
|
9948
|
+
});
|
|
9949
|
+
return result;
|
|
9950
|
+
} catch (error) {
|
|
9951
|
+
await publishCommandFailureStatus({
|
|
9952
|
+
adapter,
|
|
9953
|
+
prepared,
|
|
9954
|
+
status,
|
|
9955
|
+
statusOptions,
|
|
9956
|
+
error,
|
|
9876
9957
|
log
|
|
9877
|
-
})
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9958
|
+
});
|
|
9959
|
+
throw error;
|
|
9960
|
+
}
|
|
9961
|
+
}
|
|
9962
|
+
async function publishCommandFailureStatus(options) {
|
|
9963
|
+
try {
|
|
9964
|
+
const state = (await options.adapter.events.loadChangeRequest({
|
|
9965
|
+
repository: options.prepared.comment.repository,
|
|
9966
|
+
changeNumber: options.prepared.comment.changeNumber,
|
|
9967
|
+
workspace: options.prepared.comment.workspace,
|
|
9968
|
+
eventName: options.prepared.comment.eventName,
|
|
9969
|
+
action: options.prepared.comment.action,
|
|
9970
|
+
rawAction: options.prepared.comment.rawAction
|
|
9971
|
+
})).change.head.sha === options.prepared.event.change.head.sha ? "failed" : "superseded";
|
|
9972
|
+
await options.status({
|
|
9973
|
+
...options.statusOptions,
|
|
9974
|
+
state
|
|
9975
|
+
});
|
|
9976
|
+
} catch (statusError) {
|
|
9977
|
+
options.log.warning("command terminal status publication failed", {
|
|
9978
|
+
error: statusError instanceof Error ? statusError.message : String(statusError),
|
|
9979
|
+
originalError: options.error instanceof Error ? options.error.message : String(options.error)
|
|
9980
|
+
});
|
|
9981
|
+
}
|
|
9883
9982
|
}
|
|
9884
9983
|
async function issueCommentCommandResult(options) {
|
|
9885
9984
|
if (options.completed.kind === "skipped") return {
|
|
@@ -9913,6 +10012,7 @@ async function publishCommandResponseHostRunResult(options) {
|
|
|
9913
10012
|
});
|
|
9914
10013
|
return {
|
|
9915
10014
|
kind: "command-response",
|
|
10015
|
+
run: options.completed.run,
|
|
9916
10016
|
event: options.event,
|
|
9917
10017
|
command: options.completed.response.commandName,
|
|
9918
10018
|
configSource: options.configSource,
|
|
@@ -9950,6 +10050,7 @@ async function runReviewCommentReplyHostRunCommand(options, adapter, log, reply)
|
|
|
9950
10050
|
});
|
|
9951
10051
|
return {
|
|
9952
10052
|
kind: "verifier",
|
|
10053
|
+
run: result.run,
|
|
9953
10054
|
event: prepared.event,
|
|
9954
10055
|
configSource: prepared.trustedRuntime.settings.source,
|
|
9955
10056
|
errors: publication?.errors ?? []
|
|
@@ -10027,6 +10128,23 @@ async function runReviewCommentVerifier(options, adapter, prepared, log) {
|
|
|
10027
10128
|
const config = trustedRuntime.settings.config;
|
|
10028
10129
|
const provider = resolveProvider(config, config.defaultProvider);
|
|
10029
10130
|
const verifierProvider = resolveProvider(config, config.publication.autoResolve.model ?? config.defaultProvider);
|
|
10131
|
+
const started = Date.now();
|
|
10132
|
+
const piRuns = [];
|
|
10133
|
+
const runId = stableReviewRunId({
|
|
10134
|
+
event,
|
|
10135
|
+
selectedTasks: ["pipr-internal-verifier"],
|
|
10136
|
+
trustedConfigSha: trustedRuntime.trustedConfigSha,
|
|
10137
|
+
trustedConfigHash: trustedRuntime.trustedConfigHash,
|
|
10138
|
+
verifierInvocation: {
|
|
10139
|
+
mode: "user-reply",
|
|
10140
|
+
commentId: reply.commentId,
|
|
10141
|
+
parentCommentId: reply.parentCommentId
|
|
10142
|
+
}
|
|
10143
|
+
});
|
|
10144
|
+
const runContext = Object.freeze({
|
|
10145
|
+
id: runId,
|
|
10146
|
+
trigger: "verifier"
|
|
10147
|
+
});
|
|
10030
10148
|
const threadContexts = await adapter.comments?.loadInlineThreadContexts?.({ change: event }) ?? [];
|
|
10031
10149
|
log.notice("verifier start", {
|
|
10032
10150
|
mode: "user-reply",
|
|
@@ -10061,26 +10179,47 @@ async function runReviewCommentVerifier(options, adapter, prepared, log) {
|
|
|
10061
10179
|
},
|
|
10062
10180
|
respondWhenStillValid: config.publication.autoResolve.userReplies.respondWhenStillValid
|
|
10063
10181
|
},
|
|
10064
|
-
|
|
10065
|
-
|
|
10066
|
-
|
|
10067
|
-
|
|
10068
|
-
|
|
10069
|
-
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10182
|
+
run: runContext,
|
|
10183
|
+
piRunSink(run) {
|
|
10184
|
+
piRuns.push(run);
|
|
10185
|
+
}
|
|
10186
|
+
});
|
|
10187
|
+
const durationMs = Date.now() - started;
|
|
10188
|
+
const stats = reviewStatsForRuns(piRuns, durationMs);
|
|
10189
|
+
const run = verifierRunSummary({
|
|
10190
|
+
event,
|
|
10191
|
+
run: runContext,
|
|
10192
|
+
durationMs,
|
|
10193
|
+
providerModels: result.providerModels,
|
|
10194
|
+
fallbackModel: verifierProvider.model,
|
|
10195
|
+
stats
|
|
10075
10196
|
});
|
|
10076
10197
|
return {
|
|
10077
10198
|
...result,
|
|
10199
|
+
run,
|
|
10078
10200
|
threadActions: redactThreadActions({
|
|
10079
10201
|
threadActions: result.threadActions,
|
|
10080
10202
|
redactor: options.secretRedactor
|
|
10081
10203
|
})
|
|
10082
10204
|
};
|
|
10083
10205
|
}
|
|
10206
|
+
function verifierRunSummary(options) {
|
|
10207
|
+
const { agentRuns = 0, inputTokens = 0, outputTokens = 0, costUsd = 0, usageStatus = "unavailable" } = options.stats ?? {};
|
|
10208
|
+
const models = options.providerModels.length ? options.providerModels : [options.fallbackModel];
|
|
10209
|
+
return {
|
|
10210
|
+
...options.run,
|
|
10211
|
+
baseSha: options.event.change.base.sha,
|
|
10212
|
+
headSha: options.event.change.head.sha,
|
|
10213
|
+
tasks: ["pipr-internal-verifier"],
|
|
10214
|
+
durationMs: options.durationMs,
|
|
10215
|
+
models,
|
|
10216
|
+
agentRuns,
|
|
10217
|
+
inputTokens,
|
|
10218
|
+
outputTokens,
|
|
10219
|
+
costUsd,
|
|
10220
|
+
usageStatus
|
|
10221
|
+
};
|
|
10222
|
+
}
|
|
10084
10223
|
function runnableReviewCommentReply(reply) {
|
|
10085
10224
|
if (reply.action !== "created") return {
|
|
10086
10225
|
kind: "ignored",
|
|
@@ -10213,7 +10352,8 @@ async function runLocalReviewCommand(options) {
|
|
|
10213
10352
|
includeWorkingTree: true
|
|
10214
10353
|
}) : void 0,
|
|
10215
10354
|
log,
|
|
10216
|
-
taskLog: options.taskLog
|
|
10355
|
+
taskLog: options.taskLog,
|
|
10356
|
+
runTrigger: "local"
|
|
10217
10357
|
});
|
|
10218
10358
|
if (result.kind === "command-response") throw new Error("command response result is only supported for issue_comment commands");
|
|
10219
10359
|
log?.notice("local review complete", {
|
|
@@ -10265,6 +10405,6 @@ async function runHostRunCommandWithDependencies(options) {
|
|
|
10265
10405
|
});
|
|
10266
10406
|
}
|
|
10267
10407
|
//#endregion
|
|
10268
|
-
export { piReadOnlyToolNames as _, runInspectCommand as a, createGitLabClient as c,
|
|
10408
|
+
export { piReadOnlyToolNames as _, runInspectCommand as a, createGitLabClient as c, createAzureDevOpsClient as d, azureOrganizationFromUrl as f, piBuiltinToolNames as g, supportedOfficialInitAdapters as h, runInitCommand as i, createGitHubHostAdapter as l, createKnownSecretRedactor as m, runHostRunCommand as n, runLocalReviewCommand as o, PublicationError as p, runHostRunCommandWithDependencies as r, runValidateCommand as s, runDryRunCommand as t, createBitbucketClient as u, piRequiredCliFlags as v, piThinkingLevels as y };
|
|
10269
10409
|
|
|
10270
|
-
//# sourceMappingURL=commands-
|
|
10410
|
+
//# sourceMappingURL=commands-DgZU7tf7.mjs.map
|