@usepipr/runtime 0.3.6 → 0.3.7
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/{commands-C6wfO-y7.d.mts → commands-Bcta0T4L.d.mts} +27 -1
- package/dist/commands-Bcta0T4L.d.mts.map +1 -0
- package/dist/{commands-Btw_Ummi.mjs → commands-DM63Wmy0.mjs} +293 -31
- package/dist/commands-DM63Wmy0.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/internal/testing.d.mts +1 -1
- package/dist/internal/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/commands-Btw_Ummi.mjs.map +0 -1
- package/dist/commands-C6wfO-y7.d.mts.map +0 -1
|
@@ -304,6 +304,19 @@ declare const publicationMetadataSchema: z.ZodObject<{
|
|
|
304
304
|
validFindings: z.ZodNumber;
|
|
305
305
|
droppedFindings: z.ZodNumber;
|
|
306
306
|
cappedInlineFindings: z.ZodNumber;
|
|
307
|
+
stats: z.ZodOptional<z.ZodObject<{
|
|
308
|
+
models: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
309
|
+
agentRuns: z.ZodNumber;
|
|
310
|
+
durationMs: z.ZodNumber;
|
|
311
|
+
inputTokens: z.ZodNumber;
|
|
312
|
+
outputTokens: z.ZodNumber;
|
|
313
|
+
costUsd: z.ZodNumber;
|
|
314
|
+
usageStatus: z.ZodEnum<{
|
|
315
|
+
complete: "complete";
|
|
316
|
+
partial: "partial";
|
|
317
|
+
unavailable: "unavailable";
|
|
318
|
+
}>;
|
|
319
|
+
}, z.core.$strict>>;
|
|
307
320
|
}, z.core.$strict>;
|
|
308
321
|
type PublicationMetadata = z.infer<typeof publicationMetadataSchema>;
|
|
309
322
|
declare const publicationPlanSchema: z.ZodObject<{
|
|
@@ -334,6 +347,19 @@ declare const publicationPlanSchema: z.ZodObject<{
|
|
|
334
347
|
validFindings: z.ZodNumber;
|
|
335
348
|
droppedFindings: z.ZodNumber;
|
|
336
349
|
cappedInlineFindings: z.ZodNumber;
|
|
350
|
+
stats: z.ZodOptional<z.ZodObject<{
|
|
351
|
+
models: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
352
|
+
agentRuns: z.ZodNumber;
|
|
353
|
+
durationMs: z.ZodNumber;
|
|
354
|
+
inputTokens: z.ZodNumber;
|
|
355
|
+
outputTokens: z.ZodNumber;
|
|
356
|
+
costUsd: z.ZodNumber;
|
|
357
|
+
usageStatus: z.ZodEnum<{
|
|
358
|
+
complete: "complete";
|
|
359
|
+
partial: "partial";
|
|
360
|
+
unavailable: "unavailable";
|
|
361
|
+
}>;
|
|
362
|
+
}, z.core.$strict>>;
|
|
337
363
|
}, z.core.$strict>;
|
|
338
364
|
reviewState: z.ZodObject<{
|
|
339
365
|
version: z.ZodLiteral<1>;
|
|
@@ -872,4 +898,4 @@ declare function runActionCommand(options: ActionCommandOptions): Promise<Action
|
|
|
872
898
|
declare function runActionCommandWithDependencies(options: ActionCommandDependencyOptions): Promise<ActionCommandResult>;
|
|
873
899
|
//#endregion
|
|
874
900
|
export { PlatformInfo as A, GitHubPublicationClient as C, ChangeRequestRef as D, ChangeRequestEventContext as E, supportedOfficialInitAdapters as F, RepositoryRef as M, RuntimeSettings as N, DiffManifest as O, OfficialInitAdapter as P, ActionLogSink as S, PublicationResult as T, piBuiltinToolNames as _, runInspectCommand as a, piThinkingLevels as b, ActionCommandOptions as c, DryRunCommandResult as d, InitCommandOptions as f, RuntimeCommandOptions as g, LocalReviewCommandResult as h, runInitCommand as i, ProviderConfig as j, PiprConfig as k, ActionCommandResult as l, LocalReviewCommandOptions as m, runActionCommandWithDependencies as n, runLocalReviewCommand as o, InspectCommandResult as p, runDryRunCommand as r, runValidateCommand as s, runActionCommand as t, DryRunCommandOptions as u, piReadOnlyToolNames as v, PublicationError as w, ActionLogRecord as x, piRequiredCliFlags as y };
|
|
875
|
-
//# sourceMappingURL=commands-
|
|
901
|
+
//# sourceMappingURL=commands-Bcta0T4L.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands-Bcta0T4L.d.mts","names":[],"sources":["../src/config/init.ts","../src/types.ts","../src/config/project.ts","../src/review/prior-state.ts","../src/review/comment.ts","../src/review/publication-result.ts","../src/hosts/types.ts","../src/hosts/github/command.ts","../src/hosts/github/publication-client.ts","../src/shared/logging.ts","../src/pi/contract.ts","../src/review/task/task-output.ts","../src/review/task/task-runtime.ts","../src/action/types.ts","../src/action/commands.ts"],"mappings":";;;;KAsBY;EACV;EACA;EACA;;cAGW;KAED,8BAA8B;;;cCCpC,sBAAoB,EAAA;;;;;;;;;;;;;;cAyBpB,kBAAgB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAehB,uBAAqB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAMrB,oBAAkB,EAAA;;;;cAKlB,qBAAmB,EAAA;;;;cAanB,wBAAsB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAWtB,iCAA+B,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqE/B,uBAAqB,EAAA;;;;;;;;cAMrB,8BAA4B,EAAA;;;;;;;KAEtB,iBAAiB,EAAE,aAAa;KAGhC,aAAa,EAAE,aAAa;KAC5B,kBAAkB,EAAE,aAAa;KACjC,eAAe,EAAE,aAAa;KAC9B,gBAAgB,EAAE,aAAa;KAC/B,mBAAmB,EAAE,aAAa;KAClC,4BAA4B,EAAE,aAAa;KAE3C,kBAAkB,EAAE,aAAa;KACjC,yBAAyB,EAAE,aAAa;;;KC1KxC;EACV;EACA;EACA;EACA;EACA,QAAQ;IAAQ;IAAc;;EAC9B,UAAU;IAAQ;IAAiB;IAAc;;EACjD;EACA;;;;cCAW,wBAAsB,EAAA;;;;;;;;;;;;;;;;;;;;KAQvB,mBAAmB,EAAE,aAAa;;;cCDxC,6BAA2B,EAAA;;;;;;;;;;;;KAsCrB,wBAAwB,EAAE,aAAa;KACvC,qBAAqB;cAM3B,oBAAkB,EAAA;;;;;;;;;;;;KAYZ,eAAe,EAAE,aAAa;cAEpC,2BAAyB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;KAenB,sBAAsB,EAAE,aAAa;cAE3C,uBAAqB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAUf,kBAAkB,EAAE,aAAa;;;KC3HjC;EACV;IACE;IACA;;EAEF;IACE;IACA;IACA;;EAEF,UAAU;IACR;IACA;;;;cAKS,yBAAyB;WAGzB,QAAQ,KAAK;cADtB,iBACS,QAAQ,KAAK;;;;KCZd;EACV;EACA,KAAK,OAAO;EACZ;;KAGU;EACV;EACA;EACA;EACA,YAAY;EACZ;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;IACR;IACA;IACA;;;KAIQ;EACV;EACA;EACA;EACA,YAAY;EACZ;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV,YAAY;EACZ,QAAQ;EACR;EACA;EACA;EACA;;KAGU,uBAAuB;KAEvB;KAEA;EACV;EACA;;KAGU;EACV,WAAW,SAAS,wBAAwB,QAAQ;EACpD,kBAAkB;IAChB,YAAY;IACZ;IACA;IACA;IACA;IACA;MACE,QAAQ;EACZ,sBAAsB,SAAS,wBAAwB,QAAQ;EAC/D,2BAA2B,SAAS,wBAAwB,QAAQ;;KAG1D;EACV,wBAAwB;IACtB,YAAY;IACZ;MACE,QAAQ;;KAGF;EACV,mBAAmB;IAAW;IAAiB,QAAQ;;EACvD,8BAA8B;IAAW;IAAiB,MAAM,OAAO;;;KAG7D;EACV,QAAQ;IACN,MAAM;IACN,QAAQ;MACN,QAAQ;EACZ,wBAAwB;IACtB,QAAQ;IACR;IACA;IACA;MACE,QAAQ;EACZ,sBAAsB;IACpB,QAAQ;IACR,SAAS;IACT;MACE;IAAU;;;KAGJ;EACV,sBAAsB;IACpB,QAAQ;MACN,QAAQ;EACZ,sBAAsB;IACpB,QAAQ;MACN;EACJ,0BAA0B;IACxB,QAAQ;MACN,QAAQ;;KAGF;EACV,gBAAgB;IACd,QAAQ;IACR;IACA;MACE,QAAQ;EACZ,gBAAgB;IACd,QAAQ;IACR,UAAU;IACV,YAAY;IACZ;MACE;;KAGM;EACV;EACA,QAAQ;EACR,WAAW;EACX,aAAa;EACb,cAAc;EACd,WAAW;EACX,SAAS;;;;KC5GC;EACV,YAAY;EACZ,QAAQ;;KAGE;EACV,eAAe;IACb,YAAY;IACZ;MACE,QAAQ;EACZ,wBAAwB;IACtB,YAAY;IACZ;MACE,QAAQ;;;;cC/CR,0BAAwB,EAAA,QAAA,EAAA;;;;;;;;;;;;;;;;;;;cAMxB,2BAAyB,EAAA,QAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA2BzB,0BAAwB,EAAA;;;;;cAwExB,sBAAoB,EAAA;;;;KAKd,qBAAqB,EAAE,aAAa;KACpC,sBAAsB,EAAE,aAAa;KACrC,qBAAqB,EAAE,aAAa;KACpC,iBAAiB,EAAE,aAAa;KAEhC;EACV,6BAA6B;EAC7B,sBAAsB;IAAW;IAAc;MAA8B;EAC7E,kBAAkB;IAAW;IAAc;MAAwB,QAAQ;EAC3E,mBAAmB;IACjB;IACA;IACA;MACE;IAAU;;EACd,mBAAmB;IACjB;IACA;IACA;MACE;IAAU;;EACd,mBAAmB;IACjB;IACA;MACE,QAAQ;EACZ,kBAAkB;IAChB;IACA;MACE,QAAQ;EACZ,oBAAoB;IAClB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;MACE;IAAU;;EACd,yBAAyB;IACvB;IACA;IACA;IACA;MACE;IAAU;;EACd,oBAAoB;IAAW;MAAqB;EACpD,eAAe;IACb;IACA;IACA;IACA;MACE,QAAQ;EACZ,eAAe;IACb;IACA;IACA;IACA;IACA;MACE;;;;KCnLM;EACV,IAAI,QAAQ;EACZ,MAAM,GAAG,cAAc,WAAW,QAAQ,KAAK,QAAQ;;KAG7C;EACV,OAAO;EACP;EACA,QAAQ;EACR;;KAQU,wBAAwB;KAsBxB;;;cCvCC;cACA;cACA;cAEA;;;KCkBD;KAEA;EACV;EACA,YAAY;EACZ;;;;KCqDG;EACH,UAAU;EACV,cAAc;EACd,YAAY;EACZ;;KAGU,uBACP;EACC;EACA,QAAQ;EACR,WAAW;EACX,iBAAiB;EACjB;EACA,qBAAqB;EACrB;MAED;EACC;EACA;EACA,QAAQ;EACR,WAAW;EACX,iBAAiB;EACjB;EACA,qBAAqB;EACrB;MAED;EACC;EACA;IACE;IACA;IACA,WAAW;IACX;;EAEF;EACA;EACA;EACA;EACA;;;;KChHM;EACV;EACA;EACA,MAAM,OAAO;EACb;;KAGU,qBAAqB;EAC/B;EACA;EACA;EACA;;KAGU,uBAAuB;EACjC;;KAGU,uBAAuB;EACjC;EACA;EACA,UAAU;;KAGA,iCAAiC;EAC3C;EACA,cAAc;EACd,eAAe;EACf,0BAA0B;;KAGhB;EACV,KAAK;EACL,KAAK;EACL,MAAM;;KAGI,4BAA4B;EACtC;EACA;EACA;EACA,UAAU;EACV,UAAU;;KAGA;EACV;EACA,OAAO;EACP;;KAGU,uBAAuB;EACjC;;KAGU,2BAA2B;EACrC;EACA;;KAGU,+BAA+B,QAAQ;EAAuB;;KAE9D;EAEN;EACA;;EAGA;EACA,OAAO;EACP;;EAGA;EACA,OAAO;EACP;EACA;EACA;;EAGA;EACA,OAAO;EACP;EACA;EACA,QAAQ;EACR,aAAa;;EAGb;EACA,OAAO;EACP;EACA;EACA;IACE;;EAEF,aAAa;;EAGb;EACA,OAAO;EACP;EACA;;KAuBM,wBAAwB;;;;iBCxFd,eACpB,SAAS,qBACR,QAAQ;;iBAYW,mBACpB,SAAS,wBACR,QAAQ;;iBAUW,kBACpB,SAAS,wBACR,QAAQ;;iBASW,iBACpB,SAAS,uBACR,QAAQ;;iBAoBW,sBACpB,SAAS,4BACR,QAAQ;;iBA2EW,iBACpB,SAAS,uBACR,QAAQ;iBAIW,iCACpB,SAAS,iCACR,QAAQ"}
|
|
@@ -526,7 +526,7 @@ function compareStableSemver(left, right) {
|
|
|
526
526
|
}
|
|
527
527
|
//#endregion
|
|
528
528
|
//#region src/shared/version.ts
|
|
529
|
-
const runtimeVersion = "0.3.
|
|
529
|
+
const runtimeVersion = "0.3.7";
|
|
530
530
|
//#endregion
|
|
531
531
|
//#region src/config/version-compat.ts
|
|
532
532
|
async function resolveConfigVersionCompatibility(options) {
|
|
@@ -3544,8 +3544,8 @@ function isOfficialInitRecipeId(recipe) {
|
|
|
3544
3544
|
//#endregion
|
|
3545
3545
|
//#region src/config/init.ts
|
|
3546
3546
|
const supportedOfficialInitAdapters = ["github"];
|
|
3547
|
-
const defaultWorkflowActionRef = "somus/pipr@v0.3.
|
|
3548
|
-
const defaultSdkVersion = "0.3.
|
|
3547
|
+
const defaultWorkflowActionRef = "somus/pipr@v0.3.7";
|
|
3548
|
+
const defaultSdkVersion = "0.3.7";
|
|
3549
3549
|
function resolveOfficialInitAdapters(adapters) {
|
|
3550
3550
|
if (adapters === void 0) return [...supportedOfficialInitAdapters];
|
|
3551
3551
|
if (adapters.length === 0) return [];
|
|
@@ -4746,6 +4746,24 @@ const ignoredWorkspacePaths = /* @__PURE__ */ new Set([
|
|
|
4746
4746
|
".fallow",
|
|
4747
4747
|
"coverage"
|
|
4748
4748
|
]);
|
|
4749
|
+
const eventRecordSchema = z.record(z.string(), z.unknown());
|
|
4750
|
+
const tokenCountSchema = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
|
4751
|
+
const assistantMessageEventSchema = z.looseObject({
|
|
4752
|
+
type: z.literal("message_end"),
|
|
4753
|
+
message: z.looseObject({
|
|
4754
|
+
role: z.literal("assistant"),
|
|
4755
|
+
model: z.string().min(1).optional(),
|
|
4756
|
+
responseModel: z.string().min(1).optional()
|
|
4757
|
+
})
|
|
4758
|
+
});
|
|
4759
|
+
const assistantUsageMessageSchema = z.looseObject({
|
|
4760
|
+
role: z.literal("assistant"),
|
|
4761
|
+
usage: z.looseObject({
|
|
4762
|
+
input: tokenCountSchema,
|
|
4763
|
+
output: tokenCountSchema,
|
|
4764
|
+
cost: z.looseObject({ total: z.number().nonnegative() })
|
|
4765
|
+
})
|
|
4766
|
+
});
|
|
4749
4767
|
async function runPi(options) {
|
|
4750
4768
|
const started = Date.now();
|
|
4751
4769
|
const sandbox = await createPiRunSandbox(options.workspace);
|
|
@@ -4768,10 +4786,13 @@ async function runPi(options) {
|
|
|
4768
4786
|
started,
|
|
4769
4787
|
timeoutSeconds: options.timeoutSeconds
|
|
4770
4788
|
});
|
|
4771
|
-
|
|
4789
|
+
const events = parsePiJsonEvents(result.stdout);
|
|
4790
|
+
return {
|
|
4772
4791
|
...result,
|
|
4773
|
-
|
|
4774
|
-
|
|
4792
|
+
...events?.models.length ? { models: events.models } : {},
|
|
4793
|
+
...events?.usage ? { usage: events.usage } : {},
|
|
4794
|
+
stdout: result.exitCode === 0 ? events?.assistantText ?? result.stdout : result.stdout
|
|
4795
|
+
};
|
|
4775
4796
|
} finally {
|
|
4776
4797
|
await preparedTools?.custom?.close();
|
|
4777
4798
|
await chmodRecursive(sandbox.root, 493);
|
|
@@ -4893,19 +4914,69 @@ async function chmodRecursive(target, mode) {
|
|
|
4893
4914
|
const entries = await readdir(target, { withFileTypes: true });
|
|
4894
4915
|
for (const entry of entries) await chmodRecursive(path.join(target, entry.name), mode);
|
|
4895
4916
|
}
|
|
4896
|
-
function
|
|
4917
|
+
function parsePiJsonEvents(stdout) {
|
|
4897
4918
|
const events = [];
|
|
4898
4919
|
for (const line of stdout.split(/\r?\n/).map((item) => item.trim()).filter(Boolean)) try {
|
|
4899
4920
|
const value = JSON.parse(line);
|
|
4900
|
-
|
|
4901
|
-
|
|
4921
|
+
const parsed = eventRecordSchema.safeParse(value);
|
|
4922
|
+
if (!parsed.success) return;
|
|
4923
|
+
events.push(parsed.data);
|
|
4902
4924
|
} catch {
|
|
4903
4925
|
return;
|
|
4904
4926
|
}
|
|
4905
4927
|
if (!events.some((event) => typeof event.type === "string")) return;
|
|
4906
|
-
let
|
|
4907
|
-
for (const event of events)
|
|
4908
|
-
|
|
4928
|
+
let assistantText;
|
|
4929
|
+
for (const event of events) assistantText = assistantTextFromEvent(event) ?? assistantText;
|
|
4930
|
+
const assistantMessages = assistantMessagesFromEvents(events);
|
|
4931
|
+
const models = assistantModels(assistantMessages);
|
|
4932
|
+
const usage = assistantUsage(assistantMessages);
|
|
4933
|
+
return {
|
|
4934
|
+
...assistantText !== void 0 ? { assistantText } : {},
|
|
4935
|
+
models,
|
|
4936
|
+
...usage ? { usage } : {}
|
|
4937
|
+
};
|
|
4938
|
+
}
|
|
4939
|
+
function assistantMessagesFromEvents(events) {
|
|
4940
|
+
return events.flatMap((event) => {
|
|
4941
|
+
const parsed = assistantMessageEventSchema.safeParse(event);
|
|
4942
|
+
return parsed.success ? [parsed.data.message] : [];
|
|
4943
|
+
});
|
|
4944
|
+
}
|
|
4945
|
+
function assistantModels(messages) {
|
|
4946
|
+
const models = [];
|
|
4947
|
+
for (const message of messages) {
|
|
4948
|
+
const model = message.responseModel ?? message.model;
|
|
4949
|
+
if (model && !models.includes(model)) models.push(model);
|
|
4950
|
+
}
|
|
4951
|
+
return models;
|
|
4952
|
+
}
|
|
4953
|
+
function assistantUsage(messages) {
|
|
4954
|
+
const usageMessages = messages.flatMap((message) => {
|
|
4955
|
+
const parsed = assistantUsageMessageSchema.safeParse(message);
|
|
4956
|
+
return parsed.success ? [parsed.data] : [];
|
|
4957
|
+
});
|
|
4958
|
+
if (usageMessages.length === 0) return;
|
|
4959
|
+
let inputTokens = 0;
|
|
4960
|
+
let outputTokens = 0;
|
|
4961
|
+
let costUsd = 0;
|
|
4962
|
+
let partial = usageMessages.length !== messages.length;
|
|
4963
|
+
for (const message of usageMessages) {
|
|
4964
|
+
const nextInputTokens = inputTokens + message.usage.input;
|
|
4965
|
+
if (Number.isSafeInteger(nextInputTokens)) inputTokens = nextInputTokens;
|
|
4966
|
+
else partial = true;
|
|
4967
|
+
const nextOutputTokens = outputTokens + message.usage.output;
|
|
4968
|
+
if (Number.isSafeInteger(nextOutputTokens)) outputTokens = nextOutputTokens;
|
|
4969
|
+
else partial = true;
|
|
4970
|
+
const nextCostUsd = costUsd + message.usage.cost.total;
|
|
4971
|
+
if (Number.isFinite(nextCostUsd)) costUsd = nextCostUsd;
|
|
4972
|
+
else partial = true;
|
|
4973
|
+
}
|
|
4974
|
+
return {
|
|
4975
|
+
status: partial ? "partial" : "complete",
|
|
4976
|
+
inputTokens,
|
|
4977
|
+
outputTokens,
|
|
4978
|
+
costUsd
|
|
4979
|
+
};
|
|
4909
4980
|
}
|
|
4910
4981
|
function assistantTextFromEvent(event) {
|
|
4911
4982
|
if (event.type === "message_end" || event.type === "turn_end") return assistantMessageText(event.message);
|
|
@@ -5521,16 +5592,27 @@ async function runPiForPrompt(options, provider, prompt) {
|
|
|
5521
5592
|
const customTools = customToolsForRun(options);
|
|
5522
5593
|
const timeoutSeconds = promptTimeoutSeconds(options);
|
|
5523
5594
|
logPiStart(options, provider, prompt, builtinTools, runtimeTools, customTools);
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5595
|
+
let result;
|
|
5596
|
+
try {
|
|
5597
|
+
result = await (options.runtime.piRunner ?? runPi)({
|
|
5598
|
+
workspace: options.runtime.workspace,
|
|
5599
|
+
provider,
|
|
5600
|
+
prompt,
|
|
5601
|
+
env: options.runtime.env,
|
|
5602
|
+
piExecutable: options.runtime.piExecutable,
|
|
5603
|
+
builtinTools,
|
|
5604
|
+
runtimeTools,
|
|
5605
|
+
customTools,
|
|
5606
|
+
timeoutSeconds
|
|
5607
|
+
});
|
|
5608
|
+
} catch (error) {
|
|
5609
|
+
options.runtime.piRunSink?.({ models: [provider.model] });
|
|
5610
|
+
throw error;
|
|
5611
|
+
}
|
|
5612
|
+
const reportedModels = result.models?.map((model) => model.trim()).filter(Boolean);
|
|
5613
|
+
options.runtime.piRunSink?.({
|
|
5614
|
+
models: reportedModels?.length ? reportedModels : [provider.model],
|
|
5615
|
+
...result.usage ? { usage: result.usage } : {}
|
|
5534
5616
|
});
|
|
5535
5617
|
logPiResult(options, provider, result, timeoutSeconds);
|
|
5536
5618
|
assertSuccessfulPiResult(result, options.runtime.log);
|
|
@@ -5674,6 +5756,8 @@ const mainCommentTitles = /* @__PURE__ */ new Set([
|
|
|
5674
5756
|
"# Pipr Review",
|
|
5675
5757
|
mainCommentTitle
|
|
5676
5758
|
]);
|
|
5759
|
+
const reviewStatsStartMarker = "<!-- pipr:stats:start -->";
|
|
5760
|
+
const reviewStatsEndMarker = "<!-- pipr:stats:end -->";
|
|
5677
5761
|
const escapedRepositoryUrl = piprRepositoryUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5678
5762
|
const mainCommentAttributionPattern = new RegExp(`^<sub>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+\\))\\.)?</sub>$`);
|
|
5679
5763
|
//#endregion
|
|
@@ -5933,6 +6017,29 @@ function parseAttrs(input) {
|
|
|
5933
6017
|
function hashParts(parts) {
|
|
5934
6018
|
return new Bun.CryptoHasher("sha256").update(parts.join("\n")).digest("hex").slice(0, 16);
|
|
5935
6019
|
}
|
|
6020
|
+
const maxReviewStatsModelLength = 200;
|
|
6021
|
+
const credentialLikeModelPattern = /(?:(?:AKIA|ASIA)[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35}|(?:sk|rk)_live_[A-Za-z0-9]{16,}|sk-(?:proj-)?[A-Za-z0-9_-]{16,}|gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{16,}|glpat-[A-Za-z0-9_-]{16,}|npm_[A-Za-z0-9]{16,}|xox[baprs]-[A-Za-z0-9-]{16,})/i;
|
|
6022
|
+
const highEntropyModelSegmentPattern = /[A-Za-z0-9]{24,}/;
|
|
6023
|
+
const reviewStatsModelSchema = z.string().min(1).max(maxReviewStatsModelLength).transform((model) => sanitizeReviewStatsModel(model) ?? "[invalid model]");
|
|
6024
|
+
const reviewStatsSchema = z.strictObject({
|
|
6025
|
+
models: z.array(reviewStatsModelSchema).min(1).max(20),
|
|
6026
|
+
agentRuns: z.number().int().positive(),
|
|
6027
|
+
durationMs: z.number().int().nonnegative(),
|
|
6028
|
+
inputTokens: z.number().int().nonnegative(),
|
|
6029
|
+
outputTokens: z.number().int().nonnegative(),
|
|
6030
|
+
costUsd: z.number().nonnegative(),
|
|
6031
|
+
usageStatus: z.enum([
|
|
6032
|
+
"complete",
|
|
6033
|
+
"partial",
|
|
6034
|
+
"unavailable"
|
|
6035
|
+
])
|
|
6036
|
+
});
|
|
6037
|
+
function sanitizeReviewStatsModel(model) {
|
|
6038
|
+
const normalized = model.replace(/\s+/g, " ").trim();
|
|
6039
|
+
if (credentialLikeModelPattern.test(normalized) || highEntropyModelSegmentPattern.test(normalized)) return "[redacted credential]";
|
|
6040
|
+
const sanitized = redactPotentialSecrets(normalized);
|
|
6041
|
+
return sanitized ? sanitized.slice(0, maxReviewStatsModelLength) : void 0;
|
|
6042
|
+
}
|
|
5936
6043
|
//#endregion
|
|
5937
6044
|
//#region src/review/comment.ts
|
|
5938
6045
|
const inlinePublicationItemSchema = z.strictObject({
|
|
@@ -5990,7 +6097,8 @@ const publicationMetadataSchema = z.strictObject({
|
|
|
5990
6097
|
failedTasks: z.array(z.string().min(1)),
|
|
5991
6098
|
validFindings: z.number().int().min(0),
|
|
5992
6099
|
droppedFindings: z.number().int().min(0),
|
|
5993
|
-
cappedInlineFindings: z.number().int().min(0)
|
|
6100
|
+
cappedInlineFindings: z.number().int().min(0),
|
|
6101
|
+
stats: reviewStatsSchema.optional()
|
|
5994
6102
|
});
|
|
5995
6103
|
const publicationPlanSchema = z.strictObject({
|
|
5996
6104
|
mainComment: z.string().min(1),
|
|
@@ -6106,10 +6214,54 @@ function renderMainComment(options) {
|
|
|
6106
6214
|
...options.metadata.validFindings > 0 ? [`**Findings:** ${options.metadata.validFindings}`, ""] : [],
|
|
6107
6215
|
redactPotentialSecrets(options.main),
|
|
6108
6216
|
"",
|
|
6217
|
+
...options.metadata.stats ? [renderReviewStats(options.metadata.stats), ""] : [],
|
|
6109
6218
|
renderMainCommentAttribution(options.metadata),
|
|
6110
6219
|
""
|
|
6111
6220
|
].join("\n");
|
|
6112
6221
|
}
|
|
6222
|
+
function renderReviewStats(stats) {
|
|
6223
|
+
const usageSuffix = stats.usageStatus === "partial" ? " (reported)" : "";
|
|
6224
|
+
const usageUnavailable = stats.usageStatus === "unavailable";
|
|
6225
|
+
return [
|
|
6226
|
+
reviewStatsStartMarker,
|
|
6227
|
+
"<details>",
|
|
6228
|
+
"<summary>Review stats</summary>",
|
|
6229
|
+
"",
|
|
6230
|
+
"| Metric | Total |",
|
|
6231
|
+
"| --- | ---: |",
|
|
6232
|
+
`| Models | ${stats.models.map(formatModel).join(", ")} |`,
|
|
6233
|
+
`| Agent runs | ${stats.agentRuns} |`,
|
|
6234
|
+
`| Elapsed | ${formatDuration(stats.durationMs)} |`,
|
|
6235
|
+
`| Input tokens | ${usageUnavailable ? "Unavailable" : `${formatInteger(stats.inputTokens)}${usageSuffix}`} |`,
|
|
6236
|
+
`| Output tokens | ${usageUnavailable ? "Unavailable" : `${formatInteger(stats.outputTokens)}${usageSuffix}`} |`,
|
|
6237
|
+
`| Cost (USD) | ${usageUnavailable ? "Unavailable" : `${formatCost(stats.costUsd)}${usageSuffix}`} |`,
|
|
6238
|
+
"",
|
|
6239
|
+
"</details>",
|
|
6240
|
+
reviewStatsEndMarker
|
|
6241
|
+
].join("\n");
|
|
6242
|
+
}
|
|
6243
|
+
function formatModel(model) {
|
|
6244
|
+
return `<code>${model.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\|/g, "|")}</code>`;
|
|
6245
|
+
}
|
|
6246
|
+
function formatInteger(value) {
|
|
6247
|
+
return value.toLocaleString("en-US");
|
|
6248
|
+
}
|
|
6249
|
+
function formatDuration(durationMs) {
|
|
6250
|
+
if (durationMs < 1e3) return `${durationMs}ms`;
|
|
6251
|
+
const totalSeconds = durationMs / 1e3;
|
|
6252
|
+
if (totalSeconds < 60) return `${formatTenths(totalSeconds)}s`;
|
|
6253
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
6254
|
+
return `${minutes}m ${formatTenths(totalSeconds - minutes * 60)}s`;
|
|
6255
|
+
}
|
|
6256
|
+
function formatTenths(value) {
|
|
6257
|
+
return value.toFixed(1).replace(/\.0$/, "");
|
|
6258
|
+
}
|
|
6259
|
+
function formatCost(costUsd) {
|
|
6260
|
+
if (costUsd === 0) return "$0.00";
|
|
6261
|
+
if (costUsd < 1e-4) return `$${costUsd.toFixed(6)}`;
|
|
6262
|
+
if (costUsd < .01) return `$${costUsd.toFixed(4)}`;
|
|
6263
|
+
return `$${costUsd.toFixed(2)}`;
|
|
6264
|
+
}
|
|
6113
6265
|
function renderMainCommentAttribution(metadata) {
|
|
6114
6266
|
const configNotice = configVersionNotice(metadata);
|
|
6115
6267
|
return `<sub>Review generated by [Pipr](${piprRepositoryUrl}) for commit \`${metadata.reviewedHeadSha.slice(0, 7)}\`.${configNotice}</sub>`;
|
|
@@ -6266,7 +6418,8 @@ async function runInternalVerifier(options) {
|
|
|
6266
6418
|
piExecutable: options.piExecutable,
|
|
6267
6419
|
piRunner: options.piRunner,
|
|
6268
6420
|
runId: options.runId,
|
|
6269
|
-
log: options.log
|
|
6421
|
+
log: options.log,
|
|
6422
|
+
...options.piRunSink ? { piRunSink: options.piRunSink } : {}
|
|
6270
6423
|
}
|
|
6271
6424
|
});
|
|
6272
6425
|
return applyVerifierOutput(options, candidates, verifierOutputSchema.parse(result.value), result.providerModels);
|
|
@@ -6438,6 +6591,20 @@ function boundedVerifierText(value) {
|
|
|
6438
6591
|
//#endregion
|
|
6439
6592
|
//#region src/review/task/task-output.ts
|
|
6440
6593
|
const agentInlineFindingsOutputSchema = z.custom((value) => z.looseObject({ inlineFindings: z.array(reviewFindingSchema) }).safeParse(value).success);
|
|
6594
|
+
const generatedReviewStatsShape = [
|
|
6595
|
+
/^$/,
|
|
6596
|
+
/^\| Metric \| Total \|$/,
|
|
6597
|
+
/^\| --- \| ---: \|$/,
|
|
6598
|
+
/^\| Models \| .+ \|$/,
|
|
6599
|
+
/^\| Agent runs \| \d+ \|$/,
|
|
6600
|
+
/^\| Elapsed \| .+ \|$/,
|
|
6601
|
+
/^\| Input tokens \| (?:Unavailable|[\d,]+(?: \(reported\))?) \|$/,
|
|
6602
|
+
/^\| Output tokens \| (?:Unavailable|[\d,]+(?: \(reported\))?) \|$/,
|
|
6603
|
+
/^\| Cost \(USD\) \| (?:Unavailable|\$\d+(?:\.\d+)?(?:e[+-]?\d+)?(?: \(reported\))?) \|$/,
|
|
6604
|
+
/^$/,
|
|
6605
|
+
/^<\/details>$/,
|
|
6606
|
+
/^<!-- pipr:stats:end -->$/
|
|
6607
|
+
];
|
|
6441
6608
|
function createOutputState() {
|
|
6442
6609
|
return {
|
|
6443
6610
|
findings: [],
|
|
@@ -6457,6 +6624,66 @@ function mergeTaskOutputs(results) {
|
|
|
6457
6624
|
}
|
|
6458
6625
|
return merged;
|
|
6459
6626
|
}
|
|
6627
|
+
function reviewStatsForRuns(runs, durationMs) {
|
|
6628
|
+
if (runs.length === 0) return;
|
|
6629
|
+
const usage = aggregateReviewUsage(runs);
|
|
6630
|
+
return {
|
|
6631
|
+
models: collectReviewModels(runs),
|
|
6632
|
+
agentRuns: runs.length,
|
|
6633
|
+
durationMs,
|
|
6634
|
+
inputTokens: usage.inputTokens,
|
|
6635
|
+
outputTokens: usage.outputTokens,
|
|
6636
|
+
costUsd: usage.costUsd,
|
|
6637
|
+
usageStatus: usage.status
|
|
6638
|
+
};
|
|
6639
|
+
}
|
|
6640
|
+
function collectReviewModels(runs) {
|
|
6641
|
+
const models = [];
|
|
6642
|
+
for (const model of runs.flatMap((run) => run.models)) {
|
|
6643
|
+
const sanitized = sanitizeReviewStatsModel(model);
|
|
6644
|
+
if (sanitized && models.length < 20 && !models.includes(sanitized)) models.push(sanitized);
|
|
6645
|
+
}
|
|
6646
|
+
return models.length > 0 ? models : ["[invalid model]"];
|
|
6647
|
+
}
|
|
6648
|
+
function aggregateReviewUsage(runs) {
|
|
6649
|
+
let inputTokens = 0;
|
|
6650
|
+
let outputTokens = 0;
|
|
6651
|
+
let costUsd = 0;
|
|
6652
|
+
let reportedRuns = 0;
|
|
6653
|
+
let partialUsage = false;
|
|
6654
|
+
for (const run of runs) {
|
|
6655
|
+
if (!run.usage) continue;
|
|
6656
|
+
reportedRuns += 1;
|
|
6657
|
+
const input = addReportedUsage(inputTokens, run.usage.inputTokens, Number.isSafeInteger);
|
|
6658
|
+
const output = addReportedUsage(outputTokens, run.usage.outputTokens, Number.isSafeInteger);
|
|
6659
|
+
const cost = addReportedUsage(costUsd, run.usage.costUsd, Number.isFinite);
|
|
6660
|
+
inputTokens = input.total;
|
|
6661
|
+
outputTokens = output.total;
|
|
6662
|
+
costUsd = cost.total;
|
|
6663
|
+
const sumsComplete = [
|
|
6664
|
+
input,
|
|
6665
|
+
output,
|
|
6666
|
+
cost
|
|
6667
|
+
].every((sum) => sum.complete);
|
|
6668
|
+
partialUsage ||= run.usage.status === "partial" || !sumsComplete;
|
|
6669
|
+
}
|
|
6670
|
+
return {
|
|
6671
|
+
inputTokens,
|
|
6672
|
+
outputTokens,
|
|
6673
|
+
costUsd,
|
|
6674
|
+
status: reportedRuns === 0 ? "unavailable" : reportedRuns < runs.length || partialUsage ? "partial" : "complete"
|
|
6675
|
+
};
|
|
6676
|
+
}
|
|
6677
|
+
function addReportedUsage(current, reported, isValid) {
|
|
6678
|
+
const next = current + reported;
|
|
6679
|
+
return isValid(next) ? {
|
|
6680
|
+
total: next,
|
|
6681
|
+
complete: true
|
|
6682
|
+
} : {
|
|
6683
|
+
total: current,
|
|
6684
|
+
complete: false
|
|
6685
|
+
};
|
|
6686
|
+
}
|
|
6460
6687
|
function mergeCommentContribution(merged, comment) {
|
|
6461
6688
|
if (!comment) return;
|
|
6462
6689
|
assertOutputContributionAllowed(merged, "comment", comment.taskName, (existing, next) => `ctx.comment(...) may be called once per selected run; received comments from '${existing}' and '${next}'`);
|
|
@@ -6534,12 +6761,37 @@ function priorReviewForTask(priorMainComment, priorReviewState) {
|
|
|
6534
6761
|
};
|
|
6535
6762
|
}
|
|
6536
6763
|
function visibleMainComment(body) {
|
|
6537
|
-
const
|
|
6764
|
+
const sourceLines = body.split("\n");
|
|
6765
|
+
const statsRange = generatedReviewStatsRange(sourceLines);
|
|
6766
|
+
const lines = sourceLines.filter((line, index) => {
|
|
6767
|
+
return !(statsRange && index >= statsRange.start && index <= statsRange.end) && !line.startsWith("<!-- pipr:main-comment ") && !mainCommentAttributionPattern.test(line);
|
|
6768
|
+
});
|
|
6538
6769
|
while (lines[0] === "") lines.shift();
|
|
6539
6770
|
if (lines[0] && mainCommentTitles.has(lines[0])) lines.shift();
|
|
6540
6771
|
while (lines[0] === "") lines.shift();
|
|
6541
6772
|
return lines.join("\n").trim();
|
|
6542
6773
|
}
|
|
6774
|
+
function generatedReviewStatsRange(lines) {
|
|
6775
|
+
const attributionIndex = lines.findLastIndex((line) => mainCommentAttributionPattern.test(line));
|
|
6776
|
+
if (attributionIndex < 0) return;
|
|
6777
|
+
const end = lines.slice(0, attributionIndex).findLastIndex((line) => line !== "");
|
|
6778
|
+
if (end < 0) return;
|
|
6779
|
+
if (lines[end] !== "<!-- pipr:stats:end -->") return;
|
|
6780
|
+
if (lines[end - 1] !== "</details>") return;
|
|
6781
|
+
const start = lines.lastIndexOf(reviewStatsStartMarker, end - 2);
|
|
6782
|
+
if (start < 0) return;
|
|
6783
|
+
if (lines[start + 1] !== "<details>") return;
|
|
6784
|
+
if (lines[start + 2] !== "<summary>Review stats</summary>") return;
|
|
6785
|
+
if (!matchesGeneratedReviewStatsShape(lines, start, end)) return;
|
|
6786
|
+
return {
|
|
6787
|
+
start,
|
|
6788
|
+
end
|
|
6789
|
+
};
|
|
6790
|
+
}
|
|
6791
|
+
function matchesGeneratedReviewStatsShape(lines, start, end) {
|
|
6792
|
+
const generatedShape = lines.slice(start + 3, end + 1);
|
|
6793
|
+
return generatedShape.length === generatedReviewStatsShape.length && generatedReviewStatsShape.every((pattern, index) => pattern.test(generatedShape[index] ?? ""));
|
|
6794
|
+
}
|
|
6543
6795
|
function collectInlineFindings(state, findings) {
|
|
6544
6796
|
if (!findings) return;
|
|
6545
6797
|
const arrayScope = state.findingScopes.get(findings);
|
|
@@ -6563,6 +6815,7 @@ function collectedReview(output, summaryBody) {
|
|
|
6563
6815
|
//#region src/review/task/task-runtime.ts
|
|
6564
6816
|
const genericTaskFailureSummary = "Task failed; see logs for details.";
|
|
6565
6817
|
async function runTaskRuntime(options) {
|
|
6818
|
+
const runtimeStarted = Date.now();
|
|
6566
6819
|
const config = parsePiprConfig(options.config);
|
|
6567
6820
|
const provider = options.providerOverride ? parseProviderConfig(options.providerOverride) : resolveProvider(config, config.defaultProvider);
|
|
6568
6821
|
const diffManifest = parseDiffManifest((options.diffManifestBuilder ?? buildDiffManifest)({
|
|
@@ -6615,11 +6868,15 @@ async function runTaskRuntime(options) {
|
|
|
6615
6868
|
const loadedPriorReviewState = options.priorReviewState ?? await options.loadPriorReviewState?.();
|
|
6616
6869
|
const priorMainComment = options.priorMainComment ?? await options.loadPriorMainComment?.();
|
|
6617
6870
|
const priorReviewState = priorReviewStateForSelectedTasks(loadedPriorReviewState, selectedTasks);
|
|
6871
|
+
const piRuns = [];
|
|
6618
6872
|
const runtimeOptions = {
|
|
6619
6873
|
...options,
|
|
6620
6874
|
priorReviewState,
|
|
6621
6875
|
priorMainComment,
|
|
6622
|
-
runId
|
|
6876
|
+
runId,
|
|
6877
|
+
piRunSink(run) {
|
|
6878
|
+
piRuns.push(run);
|
|
6879
|
+
}
|
|
6623
6880
|
};
|
|
6624
6881
|
const manifestCache = /* @__PURE__ */ new Map();
|
|
6625
6882
|
const taskResults = await Promise.all(tasks.map(async (task, taskOrder) => {
|
|
@@ -6703,8 +6960,10 @@ async function runTaskRuntime(options) {
|
|
|
6703
6960
|
provider,
|
|
6704
6961
|
diffManifest,
|
|
6705
6962
|
priorReviewState,
|
|
6706
|
-
runId
|
|
6963
|
+
runId,
|
|
6964
|
+
piRunSink: runtimeOptions.piRunSink
|
|
6707
6965
|
});
|
|
6966
|
+
const stats = reviewStatsForRuns(piRuns, Date.now() - runtimeStarted);
|
|
6708
6967
|
const publishing = buildCommentPublishingPlan({
|
|
6709
6968
|
event: options.event,
|
|
6710
6969
|
main,
|
|
@@ -6723,7 +6982,8 @@ async function runTaskRuntime(options) {
|
|
|
6723
6982
|
selectedTasks,
|
|
6724
6983
|
failedTasks: [],
|
|
6725
6984
|
validFindings: validated.validFindings.length,
|
|
6726
|
-
droppedFindings: validated.droppedFindings.length
|
|
6985
|
+
droppedFindings: validated.droppedFindings.length,
|
|
6986
|
+
...stats ? { stats } : {}
|
|
6727
6987
|
}
|
|
6728
6988
|
});
|
|
6729
6989
|
const publicationPlan = publishing.publicationPlan;
|
|
@@ -6782,7 +7042,8 @@ async function runSynchronizeVerifier(options) {
|
|
|
6782
7042
|
priorReviewState: options.priorReviewState,
|
|
6783
7043
|
threadContexts: await options.options.loadInlineThreadContexts?.() ?? [],
|
|
6784
7044
|
mode: { kind: "synchronize" },
|
|
6785
|
-
runId: options.runId
|
|
7045
|
+
runId: options.runId,
|
|
7046
|
+
piRunSink: options.piRunSink
|
|
6786
7047
|
});
|
|
6787
7048
|
}
|
|
6788
7049
|
function createTaskContext(options) {
|
|
@@ -6843,7 +7104,8 @@ function createTaskContext(options) {
|
|
|
6843
7104
|
runtime: {
|
|
6844
7105
|
...options,
|
|
6845
7106
|
taskContext,
|
|
6846
|
-
runId: options.runId
|
|
7107
|
+
runId: options.runId,
|
|
7108
|
+
piRunSink: options.piRunSink
|
|
6847
7109
|
}
|
|
6848
7110
|
});
|
|
6849
7111
|
options.output.providerModels.push(...result.providerModels);
|
|
@@ -9167,4 +9429,4 @@ async function runActionCommandWithDependencies(options) {
|
|
|
9167
9429
|
//#endregion
|
|
9168
9430
|
export { runInspectCommand as a, PublicationError as c, supportedOfficialInitRecipes as d, piBuiltinToolNames as f, piThinkingLevels as h, runInitCommand as i, supportedOfficialInitAdapters as l, piRequiredCliFlags as m, runActionCommandWithDependencies as n, runLocalReviewCommand as o, piReadOnlyToolNames as p, runDryRunCommand as r, runValidateCommand as s, runActionCommand as t, listOfficialInitRecipes as u };
|
|
9169
9431
|
|
|
9170
|
-
//# sourceMappingURL=commands-
|
|
9432
|
+
//# sourceMappingURL=commands-DM63Wmy0.mjs.map
|