@usepipr/cli 0.4.3 → 0.6.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 pipr contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -6,6 +6,10 @@ delegates runtime behavior to `@usepipr/runtime`.
6
6
  Use this package when installing Pipr through npm. The release installer and
7
7
  GitHub Releases publish compiled CLI binaries for supported platforms.
8
8
 
9
+ The npm package executes with Bun and requires Bun 1.3.14 or newer. Compiled
10
+ GitHub Release binaries are self-contained and do not require a system Bun
11
+ installation.
12
+
9
13
  ## Commands
10
14
 
11
15
  The binary exposes these command groups:
package/dist/main.d.mts CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export {}
package/dist/main.mjs CHANGED
@@ -1,15 +1,16 @@
1
1
  #!/usr/bin/env bun
2
2
  import * as core from "@actions/core";
3
3
  import { PublicationError, runDryRunCommand, runHostRunCommand, runInitCommand, runInspectCommand, runLocalReviewCommand, runValidateCommand, supportedOfficialInitAdapters, supportedOfficialInitRecipes } from "@usepipr/runtime";
4
+ import { presentGitHubActionError, presentGitHubActionPublicationError, presentGitHubActionResult } from "@usepipr/runtime/internal/action-result";
4
5
  import { inspect } from "node:util";
5
- import { presentGitHubActionResult } from "@usepipr/runtime/internal/action-result";
6
+ import { stripPiprMainCommentMarkers, toPiprResult } from "@usepipr/runtime/internal/pipr-result";
6
7
  import { Command, CommanderError } from "commander";
7
8
  import { chmod, lstat, mkdir, mkdtemp, open, readdir, rename, rm } from "node:fs/promises";
8
9
  import os from "node:os";
9
10
  import path from "node:path";
10
11
  import { createHash } from "node:crypto";
11
12
  //#region package.json
12
- var version = "0.4.3";
13
+ var version = "0.6.0";
13
14
  //#endregion
14
15
  //#region src/skill-catalog.ts
15
16
  const bundledSkillName = "pipr-setup";
@@ -431,7 +432,9 @@ function createProgram(options = {}) {
431
432
  program.addHelpText("after", agentHelpText);
432
433
  program.command("init").description("Create editable TypeScript config").option("--config-dir <dir>", "Config directory", ".pipr").option("--adapters <adapters>", `Adapters to initialize (${supportedOfficialInitAdapters.join(", ")}; use 'none' to skip adapter files)`).option("--recipe <recipe>", `Starter recipe (${supportedOfficialInitRecipes.join(", ")})`).option("--minimal", "Scaffold a single-file .pipr/config.ts without package.json").option("--force", "Overwrite existing pipr files").action(runInit);
433
434
  program.command("host-run").description("Run a change request event through a Code Host Adapter").option("--host <host>", "Code host adapter").option("--event <path>", "Native event payload path").option("--config-dir <dir>", "Config directory", ".pipr").action(runHostRun);
434
- program.command("webhook").description("Run trusted webhook ingress").command("serve").description("Serve one repository with a durable webhook queue").requiredOption("--host <host>", "Code host adapter").requiredOption("--workspace <path>", "Trusted repository workspace").requiredOption("--repository <repository>", "Expected provider repository ID or path").option("--database <path>", "SQLite delivery database", ".pipr/webhooks.sqlite").option("--hostname <hostname>", "Listen hostname", "127.0.0.1").option("--port <port>", "Listen port", "8787").option("--config-dir <dir>", "Config directory", ".pipr").action(runWebhookServe);
435
+ const webhook = program.command("webhook").description("Run trusted webhook ingress");
436
+ webhook.command("serve").description("Serve one repository with a durable webhook queue").requiredOption("--host <host>", "Code host adapter").requiredOption("--workspace <path>", "Trusted repository workspace").requiredOption("--repository <repository>", "Expected provider repository ID or path").option("--database <path>", "SQLite delivery database", ".pipr/webhooks.sqlite").option("--hostname <hostname>", "Listen hostname", "127.0.0.1").option("--port <port>", "Listen port", "8787").option("--config-dir <dir>", "Config directory", ".pipr").action(runWebhookServe);
437
+ webhook.command("status").description("Show recent webhook delivery outcomes").option("--database <path>", "SQLite delivery database", ".pipr/webhooks.sqlite").option("--limit <count>", "Maximum deliveries to show", "20").option("--json", "Print versioned JSON").action(runWebhookStatus);
435
438
  program.command("check").description("Type-load config and validate the runtime plan").option("--config-dir <dir>", "Config directory", ".pipr").option("--require-env", "Require configured provider env vars").action(runCheck);
436
439
  program.command("dry-run").description("Load config and event without publishing").requiredOption("--event <path>", "Native event payload path").option("--host <host>", "Code host adapter").option("--config-dir <dir>", "Config directory", ".pipr").action(runDryRun);
437
440
  program.command("inspect").description("Print models, agents, tasks, commands, and tools").option("--config-dir <dir>", "Config directory", ".pipr").action(runInspect);
@@ -501,6 +504,43 @@ async function runWebhookServe(options) {
501
504
  env: process.env
502
505
  });
503
506
  }
507
+ async function runWebhookStatus(options) {
508
+ const { readWebhookDeliveryStatus } = await import("@usepipr/runtime");
509
+ const limit = Number(options.limit);
510
+ const deliveries = readWebhookDeliveryStatus(options.database ?? ".pipr/webhooks.sqlite", limit);
511
+ if (options.json) {
512
+ console.log(JSON.stringify({
513
+ formatVersion: 1,
514
+ deliveries
515
+ }, null, 2));
516
+ return;
517
+ }
518
+ if (deliveries.length === 0) {
519
+ console.log("No webhook deliveries found.");
520
+ return;
521
+ }
522
+ const rows = deliveries.map((delivery) => [
523
+ shorten(delivery.id, 24),
524
+ delivery.host,
525
+ delivery.status,
526
+ String(delivery.attempts),
527
+ delivery.resultKind ?? "-",
528
+ delivery.runId ? shorten(delivery.runId, 12) : "-",
529
+ delivery.updatedAt
530
+ ]);
531
+ console.log([[
532
+ "DELIVERY",
533
+ "HOST",
534
+ "STATUS",
535
+ "ATTEMPTS",
536
+ "RESULT",
537
+ "RUN",
538
+ "UPDATED"
539
+ ], ...rows].map((row) => row.join(" ")).join("\n"));
540
+ }
541
+ function shorten(value, length) {
542
+ return value.length <= length ? value : `${value.slice(0, length - 1)}…`;
543
+ }
504
544
  function webhookHost(value) {
505
545
  if (value === "gitlab" || value === "azure-devops" || value === "bitbucket") return value;
506
546
  throw new Error("webhook serve supports --host gitlab, azure-devops, or bitbucket");
@@ -684,7 +724,10 @@ function formatLocalLogValue(value) {
684
724
  }
685
725
  function writeLocalReviewResult(result, json) {
686
726
  if (json) {
687
- console.log(JSON.stringify(localReviewJson(result), null, 2));
727
+ console.log(JSON.stringify(toPiprResult({
728
+ source: "local",
729
+ result
730
+ }), null, 2));
688
731
  return;
689
732
  }
690
733
  if (result.kind === "skipped") {
@@ -694,7 +737,7 @@ function writeLocalReviewResult(result, json) {
694
737
  console.log(formatLocalReview(result));
695
738
  }
696
739
  function formatLocalReview(result) {
697
- const mainComment = result.mainComment.split("\n").filter((line) => !line.startsWith("<!-- pipr:main-comment ")).join("\n").trimStart();
740
+ const mainComment = stripPiprMainCommentMarkers(result.mainComment);
698
741
  const inlineFindings = result.inlineCommentDrafts.map((draft, index) => {
699
742
  const range = draft.startLine === draft.endLine ? `${draft.path}:${draft.startLine}` : `${draft.path}:${draft.startLine}-${draft.endLine}`;
700
743
  return [
@@ -711,19 +754,6 @@ function formatLocalReview(result) {
711
754
  inlineFindings.join("\n\n")
712
755
  ].join("\n");
713
756
  }
714
- function localReviewJson(result) {
715
- return {
716
- kind: result.kind,
717
- ...result.kind === "skipped" ? { skipReason: result.skipReason } : {},
718
- mainComment: result.mainComment,
719
- inlineFindings: result.inlineCommentDrafts,
720
- droppedFindings: result.validated.droppedFindings,
721
- taskChecks: result.taskChecks,
722
- provider: result.provider,
723
- providerModels: result.publicationPlan.metadata.providerModels ?? [result.provider.model],
724
- repairAttempted: result.repairAttempted
725
- };
726
- }
727
757
  async function runDryRun(options) {
728
758
  if (!options.event) throw new Error("dry-run requires --event <path>");
729
759
  const result = await runDryRunCommand({
@@ -835,20 +865,23 @@ function isUnsafeTerminalControl(code) {
835
865
  //#region src/main.ts
836
866
  const env = process.env;
837
867
  runMain({ env }).catch((error) => handleFatalError(error, env));
838
- function handleFatalError(error, env) {
868
+ async function handleFatalError(error, env) {
839
869
  const sanitizedMessage = sanitizeTerminalMessage(error instanceof Error ? error.message : String(error));
840
870
  if (env.GITHUB_ACTIONS !== "true") {
841
871
  console.error(`error: ${sanitizedMessage}`);
842
872
  process.exit(1);
843
873
  }
844
- writeGitHubActionsFailure(error, sanitizedMessage);
874
+ await writeGitHubActionsFailure(error, sanitizedMessage);
845
875
  process.exitCode = 1;
846
876
  }
847
- function writeGitHubActionsFailure(error, message) {
848
- if (error instanceof PublicationError && error.result) {
849
- core.setOutput("publication", JSON.stringify(error.result));
850
- core.error(`pipr publication metadata: ${JSON.stringify(error.result)}`);
851
- }
877
+ async function writeGitHubActionsFailure(error, message) {
878
+ const presenter = {
879
+ info: core.info,
880
+ warning: core.warning,
881
+ setOutput: core.setOutput
882
+ };
883
+ if (error instanceof PublicationError) await presentGitHubActionPublicationError(error, presenter);
884
+ else await presentGitHubActionError(presenter);
852
885
  core.setFailed(message);
853
886
  }
854
887
  //#endregion
package/dist/main.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.mjs","names":["cliPackage.version","cliPackage.version"],"sources":["../package.json","../src/skill-catalog.ts","../src/skills.ts","../src/release/targets.ts","../src/update.ts","../src/runner.ts","../src/terminal-output.ts","../src/main.ts"],"sourcesContent":["","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport const bundledSkillName = \"pipr-setup\";\nconst bundledSkillFilePaths = new Set([\n \"SKILL.md\",\n \"references/config-patterns.md\",\n \"references/recipes.md\",\n]);\n\nexport type BundledSkillFile = {\n path: string;\n contents: string;\n};\n\nexport type BundledSkill = {\n name: string;\n description: string;\n files: BundledSkillFile[];\n};\n\nexport type BundledSkillCatalog = {\n skills: BundledSkill[];\n};\n\nexport function singleBundledSkill(catalog: BundledSkillCatalog): BundledSkill {\n const [skill] = catalog.skills;\n if (catalog.skills.length !== 1 || skill?.name !== bundledSkillName) {\n throw new Error(\n `Expected exactly one bundled skill named '${bundledSkillName}', found: ${catalog.skills\n .map((item) => item.name)\n .join(\", \")}`,\n );\n }\n return skill;\n}\n\nexport function containedSkillFilePath(root: string, relativePath: string): string {\n if (path.isAbsolute(relativePath)) {\n throw new Error(`Bundled skill file path must be relative: ${relativePath}`);\n }\n const resolvedRoot = path.resolve(root);\n const target = path.resolve(resolvedRoot, relativePath);\n if (target !== resolvedRoot && !target.startsWith(`${resolvedRoot}${path.sep}`)) {\n throw new Error(`Bundled skill file path escapes the skill directory: ${relativePath}`);\n }\n return target;\n}\n\nexport async function readBundledSkillCatalog(skillsRoot: string): Promise<BundledSkillCatalog> {\n const entries = await readdir(skillsRoot, { withFileTypes: true });\n const skills = await Promise.all(\n entries\n .filter((entry) => entry.isDirectory())\n .map(async (entry) => {\n const skillDir = path.join(skillsRoot, entry.name);\n const files = await readSkillFiles(skillDir);\n validateBundledSkillFiles(entry.name, files);\n const skillMd = files.find((file) => file.path === \"SKILL.md\");\n if (!skillMd) {\n throw new Error(`${skillDir}: missing SKILL.md`);\n }\n return {\n name: entry.name,\n description: frontmatterDescription(skillMd.contents),\n files,\n };\n }),\n );\n const catalog = { skills: skills.sort((left, right) => left.name.localeCompare(right.name)) };\n singleBundledSkill(catalog);\n return catalog;\n}\n\nasync function readSkillFiles(skillDir: string, prefix = \"\"): Promise<BundledSkillFile[]> {\n const entries = await readdir(path.join(skillDir, prefix), { withFileTypes: true });\n const files = await Promise.all(\n entries\n .filter((entry) => !entry.name.startsWith(\".\"))\n .sort((left, right) => left.name.localeCompare(right.name))\n .map(async (entry) => {\n const relativePath = prefix ? path.join(prefix, entry.name) : entry.name;\n if (entry.isDirectory()) {\n return await readSkillFiles(skillDir, relativePath);\n }\n if (!entry.isFile()) {\n return [];\n }\n const contents = await Bun.file(path.join(skillDir, relativePath)).text();\n return [{ path: relativePath.split(path.sep).join(\"/\"), contents }];\n }),\n );\n return files.flat();\n}\n\nfunction frontmatterDescription(contents: string): string {\n const frontmatter = contents.match(/^---\\n(?<body>[\\s\\S]*?)\\n---/u)?.groups?.body;\n const description = frontmatter\n ?.split(\"\\n\")\n .find((line) => line.startsWith(\"description:\"))\n ?.replace(/^description:\\s*/u, \"\")\n .trim()\n .replace(/^[\"']|[\"']$/gu, \"\");\n if (!description) {\n throw new Error(\"Bundled skill SKILL.md is missing a description\");\n }\n return description;\n}\n\nfunction validateBundledSkillFiles(skillName: string, files: BundledSkillFile[]): void {\n if (skillName !== bundledSkillName) {\n return;\n }\n const found = new Set(files.map((file) => file.path));\n const unexpected = [...found].filter((filePath) => !bundledSkillFilePaths.has(filePath));\n const missing = [...bundledSkillFilePaths].filter((filePath) => !found.has(filePath));\n if (unexpected.length > 0 || missing.length > 0) {\n throw new Error(\n `${bundledSkillName} bundled files must match the release allowlist; ` +\n `unexpected: ${unexpected.join(\", \") || \"-\"}; missing: ${missing.join(\", \") || \"-\"}`,\n );\n }\n}\n","import { lstat, mkdir, mkdtemp, readdir, rename, rm } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport cliPackage from \"../package.json\" with { type: \"json\" };\nimport {\n type BundledSkill,\n type BundledSkillCatalog,\n type BundledSkillFile,\n bundledSkillName,\n containedSkillFilePath,\n readBundledSkillCatalog,\n singleBundledSkill,\n} from \"./skill-catalog.js\";\n\ndeclare const PIPR_EMBEDDED_SKILLS: string | undefined;\n\nlet skillPromise: Promise<BundledSkill> | undefined;\n\ntype SkillCatalogAttempt =\n | { catalog: BundledSkillCatalog; skillsRoot: string }\n | { error: string; skillsRoot: string };\n\nexport async function resolveBundledSkill(): Promise<BundledSkill> {\n skillPromise ??= loadBundledSkill();\n return await skillPromise;\n}\n\nexport function formatBundledSkill(skill: BundledSkill): string {\n const files = [...skill.files].sort(compareSkillFiles);\n return [\n `# ${skill.name}`,\n \"\",\n skill.description,\n \"\",\n ...files.flatMap((file) => [\n `----- BEGIN SKILL FILE: ${file.path} -----`,\n file.contents.trimEnd(),\n `----- END SKILL FILE: ${file.path} -----`,\n \"\",\n ]),\n ].join(\"\\n\");\n}\n\nfunction compareSkillFiles(left: BundledSkillFile, right: BundledSkillFile): number {\n if (left.path === \"SKILL.md\") {\n return -1;\n }\n if (right.path === \"SKILL.md\") {\n return 1;\n }\n return left.path.localeCompare(right.path);\n}\n\nexport async function materializeBundledSkill(): Promise<string> {\n const skill = await resolveBundledSkill();\n const versionDir = path.join(skillCacheRoot(), cliPackage.version);\n const skillDir = path.join(versionDir, skill.name);\n await mkdir(versionDir, { recursive: true });\n const stagingDir = await mkdtemp(path.join(versionDir, `${bundledSkillName}-`));\n try {\n for (const file of skill.files) {\n await writeSkillFile(stagingDir, file);\n }\n if (await skillDirectoryMatches(skillDir, skill.files)) {\n await rm(stagingDir, { recursive: true, force: true });\n return skillDir;\n }\n await rm(skillDir, { recursive: true, force: true });\n await renameSkillDirectory(stagingDir, skillDir, skill.files);\n } catch (error) {\n await rm(stagingDir, { recursive: true, force: true });\n throw error;\n }\n return skillDir;\n}\n\nasync function loadBundledSkill(): Promise<BundledSkill> {\n const embedded = embeddedSkillCatalog();\n return singleBundledSkill(embedded ?? (await loadFilesystemSkillCatalog()));\n}\n\nasync function loadFilesystemSkillCatalog(): Promise<BundledSkillCatalog> {\n const attempts = await Promise.all(skillRootCandidates().map(readSkillCatalogAttempt));\n const loaded = attempts.find(\n (attempt): attempt is Extract<SkillCatalogAttempt, { catalog: BundledSkillCatalog }> =>\n \"catalog\" in attempt,\n );\n if (loaded) {\n return loaded.catalog;\n }\n throw new Error(\n `Unable to load bundled Pipr skills.\\n${attempts\n .map((attempt) => `${attempt.skillsRoot}: ${\"error\" in attempt ? attempt.error : \"loaded\"}`)\n .join(\"\\n\")}`,\n );\n}\n\nasync function readSkillCatalogAttempt(skillsRoot: string): Promise<SkillCatalogAttempt> {\n try {\n return { skillsRoot, catalog: await readBundledSkillCatalog(skillsRoot) };\n } catch (error) {\n return { skillsRoot, error: error instanceof Error ? error.message : String(error) };\n }\n}\n\nfunction embeddedSkillCatalog(): BundledSkillCatalog | undefined {\n if (typeof PIPR_EMBEDDED_SKILLS !== \"string\" || PIPR_EMBEDDED_SKILLS.length === 0) {\n return undefined;\n }\n return JSON.parse(PIPR_EMBEDDED_SKILLS) as BundledSkillCatalog;\n}\n\nfunction skillRootCandidates(): string[] {\n const here = import.meta.dirname;\n return [path.join(here, \"skills\"), path.resolve(here, \"../../../skills\")];\n}\n\nasync function writeSkillFile(skillDir: string, file: BundledSkillFile): Promise<void> {\n const target = containedSkillFilePath(skillDir, file.path);\n await mkdir(path.dirname(target), { recursive: true });\n await Bun.write(target, file.contents);\n}\n\nasync function renameSkillDirectory(\n stagingDir: string,\n skillDir: string,\n files: BundledSkillFile[],\n): Promise<void> {\n try {\n await rename(stagingDir, skillDir);\n } catch (error) {\n if (isExistingDirectoryError(error) && (await skillDirectoryMatches(skillDir, files))) {\n await rm(stagingDir, { recursive: true, force: true });\n return;\n }\n throw error;\n }\n}\n\nasync function skillDirectoryMatches(\n skillDir: string,\n files: BundledSkillFile[],\n): Promise<boolean> {\n try {\n return (\n (await skillDirectoryPathsMatch(skillDir, files)) &&\n (await skillDirectoryContentsMatch(skillDir, files))\n );\n } catch {\n return false;\n }\n}\n\nasync function skillDirectoryPathsMatch(\n skillDir: string,\n files: BundledSkillFile[],\n): Promise<boolean> {\n const actualPaths = await listSkillDirectoryEntries(skillDir);\n const expectedPaths = files.map((file) => file.path).sort();\n return (\n actualPaths.length === expectedPaths.length &&\n actualPaths.every((value, index) => value === expectedPaths[index])\n );\n}\n\nasync function skillDirectoryContentsMatch(\n skillDir: string,\n files: BundledSkillFile[],\n): Promise<boolean> {\n for (const file of files) {\n if (!(await skillFileMatches(skillDir, file))) {\n return false;\n }\n }\n return true;\n}\n\nasync function skillFileMatches(skillDir: string, file: BundledSkillFile): Promise<boolean> {\n const target = containedSkillFilePath(skillDir, file.path);\n return (await lstat(target)).isFile() && (await Bun.file(target).text()) === file.contents;\n}\n\nasync function listSkillDirectoryEntries(skillDir: string, prefix = \"\"): Promise<string[]> {\n const entries = await readdir(path.join(skillDir, prefix), { withFileTypes: true });\n const paths = await Promise.all(\n entries\n .filter((entry) => !entry.name.startsWith(\".\"))\n .map(async (entry) => {\n const relativePath = prefix ? path.join(prefix, entry.name) : entry.name;\n if (entry.isDirectory()) {\n return await listSkillDirectoryEntries(skillDir, relativePath);\n }\n return [relativePath.split(path.sep).join(\"/\")];\n }),\n );\n return paths.flat().sort();\n}\n\nconst existingDirectoryErrorCodes = new Set([\"EEXIST\", \"ENOTEMPTY\"]);\n\nfunction isExistingDirectoryError(error: unknown): boolean {\n return existingDirectoryErrorCodes.has((error as { code?: string } | undefined)?.code ?? \"\");\n}\n\nfunction skillCacheRoot(): string {\n const override = process.env.PIPR_SKILL_CACHE_DIR;\n if (override && override.trim().length > 0) {\n return path.resolve(override);\n }\n const cacheHome = process.env.XDG_CACHE_HOME || path.join(os.homedir(), \".cache\");\n return path.join(cacheHome, \"pipr\", \"skills\");\n}\n","export type ReleasePlatform = {\n platform: NodeJS.Platform;\n arch: NodeJS.Architecture;\n};\n\nexport type ReleaseTarget = ReleasePlatform & {\n target: string;\n outfile: string;\n};\n\nexport const releaseTargets: ReleaseTarget[] = [\n { platform: \"linux\", arch: \"x64\", target: \"bun-linux-x64-baseline\", outfile: \"pipr-linux-x64\" },\n { platform: \"linux\", arch: \"arm64\", target: \"bun-linux-arm64\", outfile: \"pipr-linux-arm64\" },\n { platform: \"darwin\", arch: \"x64\", target: \"bun-darwin-x64\", outfile: \"pipr-darwin-x64\" },\n {\n platform: \"darwin\",\n arch: \"arm64\",\n target: \"bun-darwin-arm64\",\n outfile: \"pipr-darwin-arm64\",\n },\n];\n\nexport function releaseTargetForPlatform(platform: ReleasePlatform): ReleaseTarget | undefined {\n return releaseTargets.find(\n (target) => target.platform === platform.platform && target.arch === platform.arch,\n );\n}\n\nexport function releaseAssetForPlatform(platform: ReleasePlatform): string {\n const target = releaseTargetForPlatform(platform);\n if (target) {\n return target.outfile;\n }\n if (!releaseTargets.some((item) => item.platform === platform.platform)) {\n throw new Error(`pipr update unsupported OS: ${platform.platform}`);\n }\n throw new Error(`pipr update unsupported architecture: ${platform.arch}`);\n}\n","import { createHash } from \"node:crypto\";\nimport { chmod, mkdtemp, open, rename, rm } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { ReleasePlatform } from \"./release/targets.js\";\nimport { releaseAssetForPlatform } from \"./release/targets.js\";\n\nexport { releaseAssetForPlatform } from \"./release/targets.js\";\n\nexport type UpdateResult =\n | { kind: \"up-to-date\"; version: string }\n | { kind: \"updated\"; previousVersion: string; version: string };\n\nexport type UpdateNotice = {\n currentVersion: string;\n latestVersion: string;\n};\n\ntype ReleaseFetch = (url: string, init?: RequestInit) => Promise<Response>;\n\ntype UpdateOptions = {\n currentVersion: string;\n executablePath: string;\n fetch?: ReleaseFetch;\n platform?: ReleasePlatform;\n};\n\ntype UpdateNoticeOptions = {\n currentVersion: string;\n fetch?: ReleaseFetch;\n timeoutMs?: number;\n};\n\ntype LatestRelease = {\n tag_name?: unknown;\n};\n\nconst officialRepo = \"somus/pipr\";\nconst packageManagerUpdateHelp = [\n \"pipr update only supports compiled GitHub Release binaries.\",\n \"If you installed with npm, run: npm install -g @usepipr/cli@latest\",\n \"If you installed with Bun, run: bun install -g @usepipr/cli@latest\",\n \"If you installed from source, pull the repository and rebuild the CLI.\",\n].join(\"\\n\");\n\nexport function resolveCurrentExecutablePath(\n options: { argv?: string[]; execPath?: string } = {},\n): string {\n const execPath = options.execPath ?? process.execPath;\n const argv = options.argv ?? process.argv;\n const execName = path.basename(execPath).toLowerCase();\n const scriptPath = argv[1];\n if (\n execName === \"bun\" ||\n execName.startsWith(\"bun-\") ||\n execName === \"node\" ||\n execName.startsWith(\"node-\") ||\n scriptPath?.endsWith(\".ts\") ||\n scriptPath?.endsWith(\".mjs\")\n ) {\n throw new Error(packageManagerUpdateHelp);\n }\n return execPath;\n}\n\nexport async function runPiprUpdate(options: UpdateOptions): Promise<UpdateResult> {\n if (!isStableSemver(options.currentVersion)) {\n throw new Error(\n `current pipr version is not a stable semver version: ${options.currentVersion}`,\n );\n }\n const fetchRelease = options.fetch ?? globalThis.fetch.bind(globalThis);\n const platform = options.platform ?? { platform: process.platform, arch: process.arch };\n const asset = releaseAssetForPlatform(platform);\n const release = await latestRelease(fetchRelease);\n const version = release.version;\n if (compareSemver(version, options.currentVersion) <= 0) {\n return { kind: \"up-to-date\", version: options.currentVersion };\n }\n const releaseDownloadBaseUrl = `https://github.com/${officialRepo}/releases/download/${release.tag}`;\n const [binary, checksums] = await Promise.all([\n downloadBytes(fetchRelease, `${releaseDownloadBaseUrl}/${asset}`),\n downloadText(fetchRelease, `${releaseDownloadBaseUrl}/SHA256SUMS`),\n ]);\n verifyChecksum(binary, expectedChecksum(checksums, asset), asset);\n\n const tempPath = path.join(\n path.dirname(options.executablePath),\n `.pipr-update-${process.pid}-${Date.now()}`,\n );\n let createdTemp = false;\n let replaced = false;\n try {\n const tempFile = await open(tempPath, \"wx\", 0o700);\n createdTemp = true;\n try {\n await tempFile.writeFile(binary);\n } finally {\n await tempFile.close();\n }\n await chmod(tempPath, 0o755);\n const binaryVersion = await downloadedVersion(tempPath);\n if (!isStableSemver(binaryVersion)) {\n throw new Error(`downloaded pipr binary reported invalid version: ${binaryVersion}`);\n }\n if (binaryVersion !== version) {\n throw new Error(\n `downloaded pipr binary reported ${binaryVersion}, expected latest ${version}`,\n );\n }\n await rename(tempPath, options.executablePath);\n replaced = true;\n return { kind: \"updated\", previousVersion: options.currentVersion, version };\n } finally {\n if (createdTemp && !replaced) {\n await rm(tempPath, { force: true });\n }\n }\n}\n\nexport async function availablePiprUpdateNotice(\n options: UpdateNoticeOptions,\n): Promise<UpdateNotice | undefined> {\n if (!isStableSemver(options.currentVersion)) {\n return undefined;\n }\n const fetchRelease = withFetchTimeout(\n options.fetch ?? globalThis.fetch.bind(globalThis),\n options.timeoutMs,\n );\n const release = await latestRelease(fetchRelease);\n if (compareSemver(release.version, options.currentVersion) <= 0) {\n return undefined;\n }\n return { currentVersion: options.currentVersion, latestVersion: release.version };\n}\n\nfunction withFetchTimeout(fetchRelease: ReleaseFetch, timeoutMs: number | undefined): ReleaseFetch {\n if (timeoutMs === undefined) {\n return fetchRelease;\n }\n return async (url, init) => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetchRelease(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timeout);\n }\n };\n}\n\nasync function latestRelease(fetchRelease: ReleaseFetch): Promise<{\n tag: string;\n version: string;\n}> {\n const response = await fetchRelease(\n `https://api.github.com/repos/${officialRepo}/releases/latest`,\n );\n if (!response.ok) {\n throw new Error(`failed to fetch latest release metadata: HTTP ${response.status}`);\n }\n const release = (await response.json()) as LatestRelease;\n if (typeof release.tag_name !== \"string\") {\n throw new Error(\"latest release metadata is missing tag_name\");\n }\n const version = release.tag_name.replace(/^v/, \"\");\n if (!isStableSemver(version)) {\n throw new Error(`latest release tag is not a stable semver version: ${release.tag_name}`);\n }\n return { tag: release.tag_name, version };\n}\n\nasync function downloadBytes(\n fetchRelease: (url: string) => Promise<Response>,\n url: string,\n): Promise<Buffer> {\n const response = await fetchRelease(url);\n if (!response.ok) {\n throw new Error(`failed to download ${url}: HTTP ${response.status}`);\n }\n return Buffer.from(await response.arrayBuffer());\n}\n\nasync function downloadText(\n fetchRelease: (url: string) => Promise<Response>,\n url: string,\n): Promise<string> {\n const response = await fetchRelease(url);\n if (!response.ok) {\n throw new Error(`failed to download ${url}: HTTP ${response.status}`);\n }\n return await response.text();\n}\n\nfunction expectedChecksum(checksums: string, asset: string): string {\n for (const line of checksums.split(/\\r?\\n/)) {\n const [checksum, name] = line.trim().split(/\\s+/);\n if (name === asset && checksum) {\n return checksum;\n }\n }\n throw new Error(`checksum for ${asset} not found`);\n}\n\nfunction verifyChecksum(binary: Buffer, expected: string, asset: string): void {\n const actual = createHash(\"sha256\").update(binary).digest(\"hex\");\n if (actual !== expected) {\n throw new Error(`checksum mismatch for ${asset}`);\n }\n}\n\nasync function downloadedVersion(executablePath: string): Promise<string> {\n const validationCwd = await mkdtemp(path.join(os.tmpdir(), \"pipr-update-version-\"));\n try {\n const process = Bun.spawn([executablePath, \"--version\"], {\n cwd: validationCwd,\n env: {\n HOME: validationCwd,\n PATH: \"/usr/bin:/bin\",\n TMPDIR: validationCwd,\n },\n stderr: \"pipe\",\n stdout: \"pipe\",\n });\n const [exitCode, stdout, stderr] = await Promise.all([\n process.exited,\n process.stdout ? new Response(process.stdout).text() : \"\",\n process.stderr ? new Response(process.stderr).text() : \"\",\n ]);\n if (exitCode !== 0) {\n throw new Error(\n `downloaded pipr binary failed --version: ${stderr.trim() || stdout.trim() || exitCode}`,\n );\n }\n return stdout.trim();\n } finally {\n await rm(validationCwd, { force: true, recursive: true });\n }\n}\n\nfunction isStableSemver(version: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+$/.test(version);\n}\n\nfunction compareSemver(left: string, right: string): number {\n const leftParts = left.split(\".\").map(Number);\n const rightParts = right.split(\".\").map(Number);\n for (let index = 0; index < 3; index += 1) {\n const difference = leftParts[index] - rightParts[index];\n if (difference !== 0) {\n return difference;\n }\n }\n return 0;\n}\n","import { inspect } from \"node:util\";\nimport * as core from \"@actions/core\";\nimport {\n type RuntimeLogRecord,\n type RuntimeLogSink,\n runDryRunCommand,\n runHostRunCommand,\n runInitCommand,\n runInspectCommand,\n runLocalReviewCommand,\n runValidateCommand,\n supportedOfficialInitAdapters,\n supportedOfficialInitRecipes,\n} from \"@usepipr/runtime\";\nimport { presentGitHubActionResult } from \"@usepipr/runtime/internal/action-result\";\nimport { Command, CommanderError } from \"commander\";\nimport cliPackage from \"../package.json\" with { type: \"json\" };\nimport { formatBundledSkill, materializeBundledSkill, resolveBundledSkill } from \"./skills.js\";\nimport {\n availablePiprUpdateNotice,\n resolveCurrentExecutablePath,\n runPiprUpdate,\n} from \"./update.js\";\n\ntype CliOptions = {\n configDir: string;\n database?: string;\n host?: string;\n hostname?: string;\n port?: string;\n repository?: string;\n workspace?: string;\n event?: string;\n force?: boolean;\n adapters?: string;\n recipe?: string;\n minimal?: boolean;\n requireEnv?: boolean;\n base?: string;\n head?: string;\n piExecutable?: string;\n json?: boolean;\n};\n\ntype MainOptions = {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n updateNoticeFetch?: typeof fetch;\n writeUpdateNotice?: (message: string) => void;\n};\n\nexport async function runMain(options: MainOptions = {}): Promise<void> {\n const argv = options.argv ?? process.argv;\n const env = options.env ?? process.env;\n if (!isUpdateCommand(argv)) {\n await writeAvailableUpdateNotice(options);\n }\n const program = createProgram({ exitOverride: env.GITHUB_ACTIONS === \"true\" });\n try {\n if (argv.length <= 2) {\n program.outputHelp();\n return;\n }\n await program.parseAsync(argv);\n } catch (error) {\n if (error instanceof CommanderError && error.exitCode === 0) {\n return;\n }\n throw error;\n }\n}\n\nfunction createProgram(options: { exitOverride?: boolean } = {}): Command {\n const program = new Command();\n program.name(\"pipr\").version(cliPackage.version).showHelpAfterError();\n if (options.exitOverride) {\n program.exitOverride();\n }\n program.addHelpText(\"after\", agentHelpText);\n\n program\n .command(\"init\")\n .description(\"Create editable TypeScript config\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .option(\n \"--adapters <adapters>\",\n `Adapters to initialize (${supportedOfficialInitAdapters.join(\", \")}; use 'none' to skip adapter files)`,\n )\n .option(\"--recipe <recipe>\", `Starter recipe (${supportedOfficialInitRecipes.join(\", \")})`)\n .option(\"--minimal\", \"Scaffold a single-file .pipr/config.ts without package.json\")\n .option(\"--force\", \"Overwrite existing pipr files\")\n .action(runInit);\n\n program\n .command(\"host-run\")\n .description(\"Run a change request event through a Code Host Adapter\")\n .option(\"--host <host>\", \"Code host adapter\")\n .option(\"--event <path>\", \"Native event payload path\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .action(runHostRun);\n\n const webhook = program.command(\"webhook\").description(\"Run trusted webhook ingress\");\n webhook\n .command(\"serve\")\n .description(\"Serve one repository with a durable webhook queue\")\n .requiredOption(\"--host <host>\", \"Code host adapter\")\n .requiredOption(\"--workspace <path>\", \"Trusted repository workspace\")\n .requiredOption(\"--repository <repository>\", \"Expected provider repository ID or path\")\n .option(\"--database <path>\", \"SQLite delivery database\", \".pipr/webhooks.sqlite\")\n .option(\"--hostname <hostname>\", \"Listen hostname\", \"127.0.0.1\")\n .option(\"--port <port>\", \"Listen port\", \"8787\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .action(runWebhookServe);\n\n program\n .command(\"check\")\n .description(\"Type-load config and validate the runtime plan\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .option(\"--require-env\", \"Require configured provider env vars\")\n .action(runCheck);\n\n program\n .command(\"dry-run\")\n .description(\"Load config and event without publishing\")\n .requiredOption(\"--event <path>\", \"Native event payload path\")\n .option(\"--host <host>\", \"Code host adapter\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .action(runDryRun);\n\n program\n .command(\"inspect\")\n .description(\"Print models, agents, tasks, commands, and tools\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .action(runInspect);\n\n program\n .command(\"review\")\n .description(\"Run configured change-request review tasks locally without publishing\")\n .requiredOption(\"--base <sha>\", \"Base commit SHA\")\n .option(\"--head <sha>\", \"Head commit SHA or ref; omitted reviews the working tree\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .option(\"--pi-executable <path>\", \"Pi executable path\")\n .option(\"--json\", \"Print structured JSON output\")\n .action(runLocalReview);\n\n program.command(\"version\").description(\"Print the CLI version\").action(runVersion);\n\n program.command(\"update\").description(\"Update a GitHub Release binary install\").action(runUpdate);\n\n const skill = program\n .command(\"skill\")\n .description(\"Print the bundled Pipr setup skill\")\n .action(runSkillGet);\n skill\n .command(\"path\")\n .description(\"Materialize the bundled Pipr setup skill and print its directory path\")\n .action(runSkillPath);\n\n return program;\n}\n\nconst agentHelpText = `\n\nStart here (for AI agents):\n pipr skill\n\nThe Pipr setup skill ships with the CLI and is version-matched to this release.\nPrefer it over guessing commands or config shape from memory.\n\n skill Print the bundled setup skill and references\n skill path Materialize the setup skill and print its directory path\n`;\n\nasync function runHostRun(options: CliOptions): Promise<void> {\n const env = process.env;\n const isGitHubAction = env.GITHUB_ACTIONS === \"true\";\n const result = await runHostRunCommand({\n rootDir: hostRunRootDir(env),\n configDir: options.configDir,\n host: options.host,\n eventPath: options.event ?? env.PIPR_EVENT_PATH ?? env.GITHUB_EVENT_PATH,\n env,\n dryRun: env.PIPR_DRY_RUN === \"1\",\n logSink: isGitHubAction ? githubActionsLogSink : localConsoleLogSink,\n });\n if (isGitHubAction) {\n await presentGitHubActionResult(result, {\n info: core.info,\n warning: core.warning,\n setOutput(name, value) {\n core.setOutput(name, value);\n },\n });\n return;\n }\n if (result.kind === \"ignored\") {\n console.log(`ignored: ${result.reason}`);\n return;\n }\n console.log(`pipr ${result.kind} completed for change #${result.event.change.number}`);\n}\n\nfunction hostRunRootDir(env: NodeJS.ProcessEnv): string {\n return (\n env.GITHUB_WORKSPACE ??\n env.CI_PROJECT_DIR ??\n env.BITBUCKET_CLONE_DIR ??\n env.BUILD_SOURCESDIRECTORY ??\n process.cwd()\n );\n}\n\nasync function runWebhookServe(options: CliOptions): Promise<void> {\n const { runWebhookServer } = await import(\"@usepipr/runtime\");\n const secret = process.env.PIPR_WEBHOOK_SECRET;\n if (!secret) throw new Error(\"PIPR_WEBHOOK_SECRET is required\");\n const host = webhookHost(options.host);\n const port = webhookPort(options.port);\n await runWebhookServer({\n host,\n workspace: options.workspace ?? process.cwd(),\n configDir: options.configDir,\n databasePath: options.database ?? \".pipr/webhooks.sqlite\",\n expectedRepository: options.repository ?? \"\",\n secret,\n hostname: options.hostname,\n port,\n env: process.env,\n });\n}\n\nfunction webhookHost(value: string | undefined): \"gitlab\" | \"azure-devops\" | \"bitbucket\" {\n if (value === \"gitlab\" || value === \"azure-devops\" || value === \"bitbucket\") return value;\n throw new Error(\"webhook serve supports --host gitlab, azure-devops, or bitbucket\");\n}\n\nfunction webhookPort(value: string | undefined): number {\n const port = Number(value);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(\"--port must be an integer from 1 to 65535\");\n }\n return port;\n}\n\nconst githubActionsLogSink: RuntimeLogSink = {\n log(record) {\n const line = JSON.stringify({\n level: record.level,\n event: record.event,\n ...record.fields,\n });\n githubActionLogWriters[record.level](\n record.text === undefined ? line : `${line}\\n${record.text}`,\n );\n },\n async group(name, run) {\n return await core.group(name, run);\n },\n};\n\nconst githubActionLogWriters = {\n info: core.info,\n notice: core.notice,\n warning: core.warning,\n error: core.error,\n debug: core.debug,\n} satisfies Record<RuntimeLogRecord[\"level\"], (message: string) => void>;\n\nasync function runInit(options: CliOptions): Promise<void> {\n const result = await runInitCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n force: options.force === true,\n adapters: options.adapters?.split(\",\").map((adapter) => adapter.trim()),\n recipe: options.recipe,\n minimal: options.minimal === true,\n });\n console.log(\n `created ${result.created.length} file(s)` +\n (result.overwritten.length > 0 ? `; overwrote ${result.overwritten.length}` : \"\"),\n );\n if (options.minimal === true) {\n console.log(\n \"For editor types, install @usepipr/sdk at the repo root: npm install -D @usepipr/sdk\",\n );\n }\n}\n\nasync function runCheck(options: CliOptions): Promise<void> {\n const settings = await runValidateCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n env: process.env,\n requireProviderEnv: options.requireEnv === true,\n });\n console.log(`valid: ${settings.source}`);\n writeConfigWarnings(settings.warnings);\n}\n\nasync function runInspect(options: CliOptions): Promise<void> {\n const result = await runInspectCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n env: process.env,\n });\n const { warnings, ...plan } = result;\n writeConfigWarnings(warnings);\n console.log(inspect(plan, { depth: 8, colors: false }));\n}\n\nfunction writeConfigWarnings(warnings: readonly string[]): void {\n for (const warning of warnings) {\n console.log(`warning: ${warning}`);\n }\n}\n\nasync function runSkillGet(): Promise<void> {\n console.log(formatBundledSkill(await resolveBundledSkill()));\n}\n\nasync function runSkillPath(): Promise<void> {\n console.log(await materializeBundledSkill());\n}\n\nfunction runVersion(): void {\n console.log(cliPackage.version);\n}\n\nasync function runUpdate(): Promise<void> {\n const result = await runPiprUpdate({\n currentVersion: cliPackage.version,\n executablePath: resolveCurrentExecutablePath(),\n });\n if (result.kind === \"up-to-date\") {\n console.log(`pipr ${result.version} is already up to date`);\n return;\n }\n console.log(`updated pipr from ${result.previousVersion} to ${result.version}`);\n}\n\nasync function writeAvailableUpdateNotice(options: MainOptions): Promise<void> {\n const env = options.env ?? process.env;\n if (shouldSkipUpdateNotice(env)) {\n return;\n }\n try {\n const notice = await availablePiprUpdateNotice({\n currentVersion: cliPackage.version,\n fetch: options.updateNoticeFetch,\n timeoutMs: 750,\n });\n if (notice) {\n (options.writeUpdateNotice ?? console.error)(\n `pipr ${notice.latestVersion} is available (current ${notice.currentVersion}). ` +\n \"Run `pipr update` for release binaries, or reinstall @usepipr/cli with npm/Bun.\",\n );\n }\n } catch {\n return;\n }\n}\n\nfunction shouldSkipUpdateNotice(env: NodeJS.ProcessEnv): boolean {\n if (env.PIPR_UPDATE_NOTICE === \"0\") {\n return true;\n }\n if (env.PIPR_UPDATE_NOTICE === \"1\") {\n return false;\n }\n\n const ci = env.CI?.trim().toLowerCase();\n return (\n (ci !== undefined && ci !== \"\" && ci !== \"0\" && ci !== \"false\") ||\n env.GITHUB_ACTIONS !== undefined\n );\n}\n\nfunction isUpdateCommand(argv: string[]): boolean {\n const args = argv.slice(2);\n if (args[0] === \"--\") {\n return args[1] === \"update\";\n }\n return (\n args[0] === \"update\" ||\n (args.length >= 2 && args[0] === \"help\" && args[1] === \"update\") ||\n (args.length >= 2 && args[0] === \"--help\" && args[1] === \"update\")\n );\n}\n\nasync function runLocalReview(options: CliOptions & { base: string }): Promise<void> {\n const result = await runLocalReviewCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n env: process.env,\n baseSha: options.base,\n headSha: options.head,\n piExecutable: options.piExecutable,\n logSink: localConsoleLogSink,\n taskLog: stderrTaskLog,\n });\n writeLocalReviewResult(result, options.json === true);\n}\n\ntype LocalReviewResult = Awaited<ReturnType<typeof runLocalReviewCommand>>;\n\nconst stderrTaskLog = {\n info(message: string) {\n console.error(`[info] ${message}`);\n },\n warn(message: string) {\n console.error(`[warn] ${message}`);\n },\n error(message: string) {\n console.error(`[error] ${message}`);\n },\n};\n\nconst localConsoleLogSink: RuntimeLogSink = {\n log(record) {\n console.error(formatLocalLogRecord(record));\n },\n async group(_name, run) {\n return await run();\n },\n};\n\nfunction formatLocalLogRecord(record: RuntimeLogRecord): string {\n const fields = Object.entries(record.fields)\n .map(([key, value]) => formatLocalLogField(key, value))\n .filter((field): field is string => field !== undefined);\n const prefix = formatLocalLogPrefix(record);\n const formatted = [...prefix, ...fields].join(\" \");\n return record.text === undefined ? formatted : `${formatted}\\n${record.text}`;\n}\n\nfunction formatLocalLogPrefix(record: RuntimeLogRecord): string[] {\n return [\"pipr\", localLogPlainLevels.has(record.level) ? \"\" : record.level, record.event].filter(\n Boolean,\n );\n}\n\nconst localLogNumberFields: Record<string, (value: number) => string> = {\n additions: (value) => `+${value}`,\n deletions: (value) => `-${value}`,\n durationMs: (value) =>\n `duration=${value < 1000 ? `${value}ms` : `${(value / 1000).toFixed(1)}s`}`,\n promptBytes: (value) => `prompt=${value}B`,\n stderrBytes: (value) => `stderr=${value}B`,\n stdoutBytes: (value) => `stdout=${value}B`,\n};\n\nconst localLogPlainLevels = new Set([\"info\", \"notice\"]);\n\nfunction formatLocalLogField(key: string, value: unknown): string | undefined {\n if (value == null) {\n return undefined;\n }\n\n return formatLocalLogFieldValue(key, value);\n}\n\nfunction formatLocalLogFieldValue(key: string, value: unknown): string {\n const formattedNumber =\n typeof value === \"number\" ? localLogNumberFields[key]?.(value) : undefined;\n return formattedNumber ?? `${key}=${formatLocalLogValue(value)}`;\n}\n\nconst localLogValueFormatters: Record<string, (value: unknown) => string> = {\n boolean: String,\n number: String,\n object: (value) =>\n Array.isArray(value)\n ? value.length === 0\n ? \"-\"\n : value.map(formatLocalLogValue).join(\",\")\n : JSON.stringify(value),\n string: (value) => {\n const text = String(value);\n return /\\s/.test(text) ? JSON.stringify(text) : text;\n },\n};\n\nfunction formatLocalLogValue(value: unknown): string {\n return (localLogValueFormatters[typeof value] ?? JSON.stringify)(value);\n}\n\nfunction writeLocalReviewResult(result: LocalReviewResult, json: boolean): void {\n if (json) {\n console.log(JSON.stringify(localReviewJson(result), null, 2));\n return;\n }\n if (result.kind === \"skipped\") {\n console.log(`skipped: ${result.skipReason ?? \"no task matched\"}`);\n return;\n }\n console.log(formatLocalReview(result));\n}\n\nfunction formatLocalReview(result: Extract<LocalReviewResult, { kind: \"review\" }>): string {\n const mainComment = result.mainComment\n .split(\"\\n\")\n .filter((line) => !line.startsWith(\"<!-- pipr:main-comment \"))\n .join(\"\\n\")\n .trimStart();\n const inlineFindings = result.inlineCommentDrafts.map((draft, index) => {\n const range =\n draft.startLine === draft.endLine\n ? `${draft.path}:${draft.startLine}`\n : `${draft.path}:${draft.startLine}-${draft.endLine}`;\n return [\n `${index + 1}. ${range}`,\n `Range: ${draft.finding.rangeId ?? \"-\"}`,\n draft.finding.body,\n ].join(\"\\n\");\n });\n return inlineFindings.length === 0\n ? mainComment\n : [mainComment.trimEnd(), \"\", \"## Inline Findings\", \"\", inlineFindings.join(\"\\n\\n\")].join(\"\\n\");\n}\n\nfunction localReviewJson(result: LocalReviewResult) {\n return {\n kind: result.kind,\n ...(result.kind === \"skipped\" ? { skipReason: result.skipReason } : {}),\n mainComment: result.mainComment,\n inlineFindings: result.inlineCommentDrafts,\n droppedFindings: result.validated.droppedFindings,\n taskChecks: result.taskChecks,\n provider: result.provider,\n providerModels: result.publicationPlan.metadata.providerModels ?? [result.provider.model],\n repairAttempted: result.repairAttempted,\n };\n}\n\nasync function runDryRun(options: CliOptions): Promise<void> {\n if (!options.event) {\n throw new Error(\"dry-run requires --event <path>\");\n }\n const result = await runDryRunCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n host: options.host,\n env: process.env,\n eventPath: options.event,\n });\n writeConfigWarnings(result.warnings);\n console.log(\n inspect(\n {\n configSource: result.configSource,\n event: result.event,\n },\n { depth: 6, colors: false },\n ),\n );\n}\n","export function sanitizeTerminalMessage(message: string): string {\n let sanitized = \"\";\n for (let index = 0; index < message.length; index += 1) {\n const code = message.charCodeAt(index);\n if (code === 0x1b) {\n index = skipTerminalControlSequence(message, index);\n continue;\n }\n if (code === c1OscIntroducer) {\n index = skipUntilTerminator(message, index + 1, bellTerminator);\n continue;\n }\n if (c1StringControlIntroducers.has(code)) {\n index = skipUntilTerminator(message, index + 1);\n continue;\n }\n if (code === c1CsiIntroducer) {\n index = skipCsiSequence(message, index + 1);\n continue;\n }\n if (isUnsafeTerminalControl(code)) {\n continue;\n }\n sanitized += message[index];\n }\n return sanitized;\n}\n\nconst oscIntroducer = 0x5d;\nconst csiIntroducer = 0x5b;\nconst c1OscIntroducer = 0x9d;\nconst c1CsiIntroducer = 0x9b;\nconst bellTerminator = 0x07;\nconst stringTerminator = 0x9c;\nconst stringControlIntroducers = new Set([0x50, 0x58, 0x5e, 0x5f]);\nconst c1StringControlIntroducers = new Set([0x90, 0x98, 0x9e, 0x9f]);\n\nfunction skipTerminalControlSequence(message: string, index: number): number {\n const next = message.charCodeAt(index + 1);\n if (Number.isNaN(next)) {\n return index;\n }\n if (next === oscIntroducer) {\n return skipUntilTerminator(message, index + 2, bellTerminator);\n }\n if (stringControlIntroducers.has(next)) {\n return skipUntilTerminator(message, index + 2);\n }\n if (next === csiIntroducer) {\n return skipCsiSequence(message, index + 2);\n }\n if (isEscapeIntermediate(next)) {\n return skipEscapeSequenceWithIntermediates(message, index + 1);\n }\n if (isSingleEscapeSequenceFinal(next)) {\n return index + 1;\n }\n return index;\n}\n\nfunction skipCsiSequence(message: string, index: number): number {\n for (let cursor = index; cursor < message.length; cursor += 1) {\n const code = message.charCodeAt(cursor);\n if (code >= 0x40 && code <= 0x7e) {\n return cursor;\n }\n }\n return message.length - 1;\n}\n\nfunction skipUntilTerminator(message: string, index: number, terminator?: number): number {\n for (let cursor = index; cursor < message.length; cursor += 1) {\n const code = message.charCodeAt(cursor);\n if (code === stringTerminator) {\n return cursor;\n }\n if (terminator !== undefined && code === terminator) {\n return cursor;\n }\n if (code === 0x1b && cursor + 1 < message.length && message.charCodeAt(cursor + 1) === 0x5c) {\n return cursor + 1;\n }\n }\n return message.length - 1;\n}\n\nfunction skipEscapeSequenceWithIntermediates(message: string, index: number): number {\n for (let cursor = index; cursor < message.length; cursor += 1) {\n const code = message.charCodeAt(cursor);\n if (isEscapeIntermediate(code)) {\n continue;\n }\n if (isSingleEscapeSequenceFinal(code)) {\n return cursor;\n }\n return Math.max(cursor - 1, index);\n }\n return message.length - 1;\n}\n\nfunction isEscapeIntermediate(code: number): boolean {\n return code >= 0x20 && code <= 0x2f;\n}\n\nfunction isSingleEscapeSequenceFinal(code: number): boolean {\n return code >= 0x30 && code <= 0x7e;\n}\n\nfunction isUnsafeTerminalControl(code: number): boolean {\n return (code < 0x20 && code !== 0x09 && code !== 0x0a) || (code >= 0x7f && code <= 0x9f);\n}\n","#!/usr/bin/env bun\nimport * as core from \"@actions/core\";\nimport { PublicationError } from \"@usepipr/runtime\";\nimport { runMain } from \"./runner.js\";\nimport { sanitizeTerminalMessage } from \"./terminal-output.js\";\n\nconst env = process.env;\n\nrunMain({ env }).catch((error) => handleFatalError(error, env));\n\nfunction handleFatalError(error: unknown, env: NodeJS.ProcessEnv): void {\n const message = error instanceof Error ? error.message : String(error);\n const sanitizedMessage = sanitizeTerminalMessage(message);\n if (env.GITHUB_ACTIONS !== \"true\") {\n console.error(`error: ${sanitizedMessage}`);\n process.exit(1);\n }\n writeGitHubActionsFailure(error, sanitizedMessage);\n process.exitCode = 1;\n}\n\nfunction writeGitHubActionsFailure(error: unknown, message: string): void {\n if (error instanceof PublicationError && error.result) {\n core.setOutput(\"publication\", JSON.stringify(error.result));\n core.error(`pipr publication metadata: ${JSON.stringify(error.result)}`);\n }\n core.setFailed(message);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"main.mjs","names":["cliPackage.version","cliPackage.version"],"sources":["../package.json","../src/skill-catalog.ts","../src/skills.ts","../src/release/targets.ts","../src/update.ts","../src/runner.ts","../src/terminal-output.ts","../src/main.ts"],"sourcesContent":["","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport const bundledSkillName = \"pipr-setup\";\nconst bundledSkillFilePaths = new Set([\n \"SKILL.md\",\n \"references/config-patterns.md\",\n \"references/recipes.md\",\n]);\n\nexport type BundledSkillFile = {\n path: string;\n contents: string;\n};\n\nexport type BundledSkill = {\n name: string;\n description: string;\n files: BundledSkillFile[];\n};\n\nexport type BundledSkillCatalog = {\n skills: BundledSkill[];\n};\n\nexport function singleBundledSkill(catalog: BundledSkillCatalog): BundledSkill {\n const [skill] = catalog.skills;\n if (catalog.skills.length !== 1 || skill?.name !== bundledSkillName) {\n throw new Error(\n `Expected exactly one bundled skill named '${bundledSkillName}', found: ${catalog.skills\n .map((item) => item.name)\n .join(\", \")}`,\n );\n }\n return skill;\n}\n\nexport function containedSkillFilePath(root: string, relativePath: string): string {\n if (path.isAbsolute(relativePath)) {\n throw new Error(`Bundled skill file path must be relative: ${relativePath}`);\n }\n const resolvedRoot = path.resolve(root);\n const target = path.resolve(resolvedRoot, relativePath);\n if (target !== resolvedRoot && !target.startsWith(`${resolvedRoot}${path.sep}`)) {\n throw new Error(`Bundled skill file path escapes the skill directory: ${relativePath}`);\n }\n return target;\n}\n\nexport async function readBundledSkillCatalog(skillsRoot: string): Promise<BundledSkillCatalog> {\n const entries = await readdir(skillsRoot, { withFileTypes: true });\n const skills = await Promise.all(\n entries\n .filter((entry) => entry.isDirectory())\n .map(async (entry) => {\n const skillDir = path.join(skillsRoot, entry.name);\n const files = await readSkillFiles(skillDir);\n validateBundledSkillFiles(entry.name, files);\n const skillMd = files.find((file) => file.path === \"SKILL.md\");\n if (!skillMd) {\n throw new Error(`${skillDir}: missing SKILL.md`);\n }\n return {\n name: entry.name,\n description: frontmatterDescription(skillMd.contents),\n files,\n };\n }),\n );\n const catalog = { skills: skills.sort((left, right) => left.name.localeCompare(right.name)) };\n singleBundledSkill(catalog);\n return catalog;\n}\n\nasync function readSkillFiles(skillDir: string, prefix = \"\"): Promise<BundledSkillFile[]> {\n const entries = await readdir(path.join(skillDir, prefix), { withFileTypes: true });\n const files = await Promise.all(\n entries\n .filter((entry) => !entry.name.startsWith(\".\"))\n .sort((left, right) => left.name.localeCompare(right.name))\n .map(async (entry) => {\n const relativePath = prefix ? path.join(prefix, entry.name) : entry.name;\n if (entry.isDirectory()) {\n return await readSkillFiles(skillDir, relativePath);\n }\n if (!entry.isFile()) {\n return [];\n }\n const contents = await Bun.file(path.join(skillDir, relativePath)).text();\n return [{ path: relativePath.split(path.sep).join(\"/\"), contents }];\n }),\n );\n return files.flat();\n}\n\nfunction frontmatterDescription(contents: string): string {\n const frontmatter = contents.match(/^---\\n(?<body>[\\s\\S]*?)\\n---/u)?.groups?.body;\n const description = frontmatter\n ?.split(\"\\n\")\n .find((line) => line.startsWith(\"description:\"))\n ?.replace(/^description:\\s*/u, \"\")\n .trim()\n .replace(/^[\"']|[\"']$/gu, \"\");\n if (!description) {\n throw new Error(\"Bundled skill SKILL.md is missing a description\");\n }\n return description;\n}\n\nfunction validateBundledSkillFiles(skillName: string, files: BundledSkillFile[]): void {\n if (skillName !== bundledSkillName) {\n return;\n }\n const found = new Set(files.map((file) => file.path));\n const unexpected = [...found].filter((filePath) => !bundledSkillFilePaths.has(filePath));\n const missing = [...bundledSkillFilePaths].filter((filePath) => !found.has(filePath));\n if (unexpected.length > 0 || missing.length > 0) {\n throw new Error(\n `${bundledSkillName} bundled files must match the release allowlist; ` +\n `unexpected: ${unexpected.join(\", \") || \"-\"}; missing: ${missing.join(\", \") || \"-\"}`,\n );\n }\n}\n","import { lstat, mkdir, mkdtemp, readdir, rename, rm } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport cliPackage from \"../package.json\" with { type: \"json\" };\nimport {\n type BundledSkill,\n type BundledSkillCatalog,\n type BundledSkillFile,\n bundledSkillName,\n containedSkillFilePath,\n readBundledSkillCatalog,\n singleBundledSkill,\n} from \"./skill-catalog.js\";\n\ndeclare const PIPR_EMBEDDED_SKILLS: string | undefined;\n\nlet skillPromise: Promise<BundledSkill> | undefined;\n\ntype SkillCatalogAttempt =\n | { catalog: BundledSkillCatalog; skillsRoot: string }\n | { error: string; skillsRoot: string };\n\nexport async function resolveBundledSkill(): Promise<BundledSkill> {\n skillPromise ??= loadBundledSkill();\n return await skillPromise;\n}\n\nexport function formatBundledSkill(skill: BundledSkill): string {\n const files = [...skill.files].sort(compareSkillFiles);\n return [\n `# ${skill.name}`,\n \"\",\n skill.description,\n \"\",\n ...files.flatMap((file) => [\n `----- BEGIN SKILL FILE: ${file.path} -----`,\n file.contents.trimEnd(),\n `----- END SKILL FILE: ${file.path} -----`,\n \"\",\n ]),\n ].join(\"\\n\");\n}\n\nfunction compareSkillFiles(left: BundledSkillFile, right: BundledSkillFile): number {\n if (left.path === \"SKILL.md\") {\n return -1;\n }\n if (right.path === \"SKILL.md\") {\n return 1;\n }\n return left.path.localeCompare(right.path);\n}\n\nexport async function materializeBundledSkill(): Promise<string> {\n const skill = await resolveBundledSkill();\n const versionDir = path.join(skillCacheRoot(), cliPackage.version);\n const skillDir = path.join(versionDir, skill.name);\n await mkdir(versionDir, { recursive: true });\n const stagingDir = await mkdtemp(path.join(versionDir, `${bundledSkillName}-`));\n try {\n for (const file of skill.files) {\n await writeSkillFile(stagingDir, file);\n }\n if (await skillDirectoryMatches(skillDir, skill.files)) {\n await rm(stagingDir, { recursive: true, force: true });\n return skillDir;\n }\n await rm(skillDir, { recursive: true, force: true });\n await renameSkillDirectory(stagingDir, skillDir, skill.files);\n } catch (error) {\n await rm(stagingDir, { recursive: true, force: true });\n throw error;\n }\n return skillDir;\n}\n\nasync function loadBundledSkill(): Promise<BundledSkill> {\n const embedded = embeddedSkillCatalog();\n return singleBundledSkill(embedded ?? (await loadFilesystemSkillCatalog()));\n}\n\nasync function loadFilesystemSkillCatalog(): Promise<BundledSkillCatalog> {\n const attempts = await Promise.all(skillRootCandidates().map(readSkillCatalogAttempt));\n const loaded = attempts.find(\n (attempt): attempt is Extract<SkillCatalogAttempt, { catalog: BundledSkillCatalog }> =>\n \"catalog\" in attempt,\n );\n if (loaded) {\n return loaded.catalog;\n }\n throw new Error(\n `Unable to load bundled Pipr skills.\\n${attempts\n .map((attempt) => `${attempt.skillsRoot}: ${\"error\" in attempt ? attempt.error : \"loaded\"}`)\n .join(\"\\n\")}`,\n );\n}\n\nasync function readSkillCatalogAttempt(skillsRoot: string): Promise<SkillCatalogAttempt> {\n try {\n return { skillsRoot, catalog: await readBundledSkillCatalog(skillsRoot) };\n } catch (error) {\n return { skillsRoot, error: error instanceof Error ? error.message : String(error) };\n }\n}\n\nfunction embeddedSkillCatalog(): BundledSkillCatalog | undefined {\n if (typeof PIPR_EMBEDDED_SKILLS !== \"string\" || PIPR_EMBEDDED_SKILLS.length === 0) {\n return undefined;\n }\n return JSON.parse(PIPR_EMBEDDED_SKILLS) as BundledSkillCatalog;\n}\n\nfunction skillRootCandidates(): string[] {\n const here = import.meta.dirname;\n return [path.join(here, \"skills\"), path.resolve(here, \"../../../skills\")];\n}\n\nasync function writeSkillFile(skillDir: string, file: BundledSkillFile): Promise<void> {\n const target = containedSkillFilePath(skillDir, file.path);\n await mkdir(path.dirname(target), { recursive: true });\n await Bun.write(target, file.contents);\n}\n\nasync function renameSkillDirectory(\n stagingDir: string,\n skillDir: string,\n files: BundledSkillFile[],\n): Promise<void> {\n try {\n await rename(stagingDir, skillDir);\n } catch (error) {\n if (isExistingDirectoryError(error) && (await skillDirectoryMatches(skillDir, files))) {\n await rm(stagingDir, { recursive: true, force: true });\n return;\n }\n throw error;\n }\n}\n\nasync function skillDirectoryMatches(\n skillDir: string,\n files: BundledSkillFile[],\n): Promise<boolean> {\n try {\n return (\n (await skillDirectoryPathsMatch(skillDir, files)) &&\n (await skillDirectoryContentsMatch(skillDir, files))\n );\n } catch {\n return false;\n }\n}\n\nasync function skillDirectoryPathsMatch(\n skillDir: string,\n files: BundledSkillFile[],\n): Promise<boolean> {\n const actualPaths = await listSkillDirectoryEntries(skillDir);\n const expectedPaths = files.map((file) => file.path).sort();\n return (\n actualPaths.length === expectedPaths.length &&\n actualPaths.every((value, index) => value === expectedPaths[index])\n );\n}\n\nasync function skillDirectoryContentsMatch(\n skillDir: string,\n files: BundledSkillFile[],\n): Promise<boolean> {\n for (const file of files) {\n if (!(await skillFileMatches(skillDir, file))) {\n return false;\n }\n }\n return true;\n}\n\nasync function skillFileMatches(skillDir: string, file: BundledSkillFile): Promise<boolean> {\n const target = containedSkillFilePath(skillDir, file.path);\n return (await lstat(target)).isFile() && (await Bun.file(target).text()) === file.contents;\n}\n\nasync function listSkillDirectoryEntries(skillDir: string, prefix = \"\"): Promise<string[]> {\n const entries = await readdir(path.join(skillDir, prefix), { withFileTypes: true });\n const paths = await Promise.all(\n entries\n .filter((entry) => !entry.name.startsWith(\".\"))\n .map(async (entry) => {\n const relativePath = prefix ? path.join(prefix, entry.name) : entry.name;\n if (entry.isDirectory()) {\n return await listSkillDirectoryEntries(skillDir, relativePath);\n }\n return [relativePath.split(path.sep).join(\"/\")];\n }),\n );\n return paths.flat().sort();\n}\n\nconst existingDirectoryErrorCodes = new Set([\"EEXIST\", \"ENOTEMPTY\"]);\n\nfunction isExistingDirectoryError(error: unknown): boolean {\n return existingDirectoryErrorCodes.has((error as { code?: string } | undefined)?.code ?? \"\");\n}\n\nfunction skillCacheRoot(): string {\n const override = process.env.PIPR_SKILL_CACHE_DIR;\n if (override && override.trim().length > 0) {\n return path.resolve(override);\n }\n const cacheHome = process.env.XDG_CACHE_HOME || path.join(os.homedir(), \".cache\");\n return path.join(cacheHome, \"pipr\", \"skills\");\n}\n","export type ReleasePlatform = {\n platform: NodeJS.Platform;\n arch: NodeJS.Architecture;\n};\n\nexport type ReleaseTarget = ReleasePlatform & {\n target: string;\n outfile: string;\n};\n\nexport const releaseTargets: ReleaseTarget[] = [\n { platform: \"linux\", arch: \"x64\", target: \"bun-linux-x64-baseline\", outfile: \"pipr-linux-x64\" },\n { platform: \"linux\", arch: \"arm64\", target: \"bun-linux-arm64\", outfile: \"pipr-linux-arm64\" },\n { platform: \"darwin\", arch: \"x64\", target: \"bun-darwin-x64\", outfile: \"pipr-darwin-x64\" },\n {\n platform: \"darwin\",\n arch: \"arm64\",\n target: \"bun-darwin-arm64\",\n outfile: \"pipr-darwin-arm64\",\n },\n];\n\nexport function releaseTargetForPlatform(platform: ReleasePlatform): ReleaseTarget | undefined {\n return releaseTargets.find(\n (target) => target.platform === platform.platform && target.arch === platform.arch,\n );\n}\n\nexport function releaseAssetForPlatform(platform: ReleasePlatform): string {\n const target = releaseTargetForPlatform(platform);\n if (target) {\n return target.outfile;\n }\n if (!releaseTargets.some((item) => item.platform === platform.platform)) {\n throw new Error(`pipr update unsupported OS: ${platform.platform}`);\n }\n throw new Error(`pipr update unsupported architecture: ${platform.arch}`);\n}\n","import { createHash } from \"node:crypto\";\nimport { chmod, mkdtemp, open, rename, rm } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { ReleasePlatform } from \"./release/targets.js\";\nimport { releaseAssetForPlatform } from \"./release/targets.js\";\n\nexport { releaseAssetForPlatform } from \"./release/targets.js\";\n\nexport type UpdateResult =\n | { kind: \"up-to-date\"; version: string }\n | { kind: \"updated\"; previousVersion: string; version: string };\n\nexport type UpdateNotice = {\n currentVersion: string;\n latestVersion: string;\n};\n\ntype ReleaseFetch = (url: string, init?: RequestInit) => Promise<Response>;\n\ntype UpdateOptions = {\n currentVersion: string;\n executablePath: string;\n fetch?: ReleaseFetch;\n platform?: ReleasePlatform;\n};\n\ntype UpdateNoticeOptions = {\n currentVersion: string;\n fetch?: ReleaseFetch;\n timeoutMs?: number;\n};\n\ntype LatestRelease = {\n tag_name?: unknown;\n};\n\nconst officialRepo = \"somus/pipr\";\nconst packageManagerUpdateHelp = [\n \"pipr update only supports compiled GitHub Release binaries.\",\n \"If you installed with npm, run: npm install -g @usepipr/cli@latest\",\n \"If you installed with Bun, run: bun install -g @usepipr/cli@latest\",\n \"If you installed from source, pull the repository and rebuild the CLI.\",\n].join(\"\\n\");\n\nexport function resolveCurrentExecutablePath(\n options: { argv?: string[]; execPath?: string } = {},\n): string {\n const execPath = options.execPath ?? process.execPath;\n const argv = options.argv ?? process.argv;\n const execName = path.basename(execPath).toLowerCase();\n const scriptPath = argv[1];\n if (\n execName === \"bun\" ||\n execName.startsWith(\"bun-\") ||\n execName === \"node\" ||\n execName.startsWith(\"node-\") ||\n scriptPath?.endsWith(\".ts\") ||\n scriptPath?.endsWith(\".mjs\")\n ) {\n throw new Error(packageManagerUpdateHelp);\n }\n return execPath;\n}\n\nexport async function runPiprUpdate(options: UpdateOptions): Promise<UpdateResult> {\n if (!isStableSemver(options.currentVersion)) {\n throw new Error(\n `current pipr version is not a stable semver version: ${options.currentVersion}`,\n );\n }\n const fetchRelease = options.fetch ?? globalThis.fetch.bind(globalThis);\n const platform = options.platform ?? { platform: process.platform, arch: process.arch };\n const asset = releaseAssetForPlatform(platform);\n const release = await latestRelease(fetchRelease);\n const version = release.version;\n if (compareSemver(version, options.currentVersion) <= 0) {\n return { kind: \"up-to-date\", version: options.currentVersion };\n }\n const releaseDownloadBaseUrl = `https://github.com/${officialRepo}/releases/download/${release.tag}`;\n const [binary, checksums] = await Promise.all([\n downloadBytes(fetchRelease, `${releaseDownloadBaseUrl}/${asset}`),\n downloadText(fetchRelease, `${releaseDownloadBaseUrl}/SHA256SUMS`),\n ]);\n verifyChecksum(binary, expectedChecksum(checksums, asset), asset);\n\n const tempPath = path.join(\n path.dirname(options.executablePath),\n `.pipr-update-${process.pid}-${Date.now()}`,\n );\n let createdTemp = false;\n let replaced = false;\n try {\n const tempFile = await open(tempPath, \"wx\", 0o700);\n createdTemp = true;\n try {\n await tempFile.writeFile(binary);\n } finally {\n await tempFile.close();\n }\n await chmod(tempPath, 0o755);\n const binaryVersion = await downloadedVersion(tempPath);\n if (!isStableSemver(binaryVersion)) {\n throw new Error(`downloaded pipr binary reported invalid version: ${binaryVersion}`);\n }\n if (binaryVersion !== version) {\n throw new Error(\n `downloaded pipr binary reported ${binaryVersion}, expected latest ${version}`,\n );\n }\n await rename(tempPath, options.executablePath);\n replaced = true;\n return { kind: \"updated\", previousVersion: options.currentVersion, version };\n } finally {\n if (createdTemp && !replaced) {\n await rm(tempPath, { force: true });\n }\n }\n}\n\nexport async function availablePiprUpdateNotice(\n options: UpdateNoticeOptions,\n): Promise<UpdateNotice | undefined> {\n if (!isStableSemver(options.currentVersion)) {\n return undefined;\n }\n const fetchRelease = withFetchTimeout(\n options.fetch ?? globalThis.fetch.bind(globalThis),\n options.timeoutMs,\n );\n const release = await latestRelease(fetchRelease);\n if (compareSemver(release.version, options.currentVersion) <= 0) {\n return undefined;\n }\n return { currentVersion: options.currentVersion, latestVersion: release.version };\n}\n\nfunction withFetchTimeout(fetchRelease: ReleaseFetch, timeoutMs: number | undefined): ReleaseFetch {\n if (timeoutMs === undefined) {\n return fetchRelease;\n }\n return async (url, init) => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetchRelease(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timeout);\n }\n };\n}\n\nasync function latestRelease(fetchRelease: ReleaseFetch): Promise<{\n tag: string;\n version: string;\n}> {\n const response = await fetchRelease(\n `https://api.github.com/repos/${officialRepo}/releases/latest`,\n );\n if (!response.ok) {\n throw new Error(`failed to fetch latest release metadata: HTTP ${response.status}`);\n }\n const release = (await response.json()) as LatestRelease;\n if (typeof release.tag_name !== \"string\") {\n throw new Error(\"latest release metadata is missing tag_name\");\n }\n const version = release.tag_name.replace(/^v/, \"\");\n if (!isStableSemver(version)) {\n throw new Error(`latest release tag is not a stable semver version: ${release.tag_name}`);\n }\n return { tag: release.tag_name, version };\n}\n\nasync function downloadBytes(\n fetchRelease: (url: string) => Promise<Response>,\n url: string,\n): Promise<Buffer> {\n const response = await fetchRelease(url);\n if (!response.ok) {\n throw new Error(`failed to download ${url}: HTTP ${response.status}`);\n }\n return Buffer.from(await response.arrayBuffer());\n}\n\nasync function downloadText(\n fetchRelease: (url: string) => Promise<Response>,\n url: string,\n): Promise<string> {\n const response = await fetchRelease(url);\n if (!response.ok) {\n throw new Error(`failed to download ${url}: HTTP ${response.status}`);\n }\n return await response.text();\n}\n\nfunction expectedChecksum(checksums: string, asset: string): string {\n for (const line of checksums.split(/\\r?\\n/)) {\n const [checksum, name] = line.trim().split(/\\s+/);\n if (name === asset && checksum) {\n return checksum;\n }\n }\n throw new Error(`checksum for ${asset} not found`);\n}\n\nfunction verifyChecksum(binary: Buffer, expected: string, asset: string): void {\n const actual = createHash(\"sha256\").update(binary).digest(\"hex\");\n if (actual !== expected) {\n throw new Error(`checksum mismatch for ${asset}`);\n }\n}\n\nasync function downloadedVersion(executablePath: string): Promise<string> {\n const validationCwd = await mkdtemp(path.join(os.tmpdir(), \"pipr-update-version-\"));\n try {\n const process = Bun.spawn([executablePath, \"--version\"], {\n cwd: validationCwd,\n env: {\n HOME: validationCwd,\n PATH: \"/usr/bin:/bin\",\n TMPDIR: validationCwd,\n },\n stderr: \"pipe\",\n stdout: \"pipe\",\n });\n const [exitCode, stdout, stderr] = await Promise.all([\n process.exited,\n process.stdout ? new Response(process.stdout).text() : \"\",\n process.stderr ? new Response(process.stderr).text() : \"\",\n ]);\n if (exitCode !== 0) {\n throw new Error(\n `downloaded pipr binary failed --version: ${stderr.trim() || stdout.trim() || exitCode}`,\n );\n }\n return stdout.trim();\n } finally {\n await rm(validationCwd, { force: true, recursive: true });\n }\n}\n\nfunction isStableSemver(version: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+$/.test(version);\n}\n\nfunction compareSemver(left: string, right: string): number {\n const leftParts = left.split(\".\").map(Number);\n const rightParts = right.split(\".\").map(Number);\n for (let index = 0; index < 3; index += 1) {\n const difference = leftParts[index] - rightParts[index];\n if (difference !== 0) {\n return difference;\n }\n }\n return 0;\n}\n","import { inspect } from \"node:util\";\nimport * as core from \"@actions/core\";\nimport {\n type RuntimeLogRecord,\n type RuntimeLogSink,\n runDryRunCommand,\n runHostRunCommand,\n runInitCommand,\n runInspectCommand,\n runLocalReviewCommand,\n runValidateCommand,\n supportedOfficialInitAdapters,\n supportedOfficialInitRecipes,\n} from \"@usepipr/runtime\";\nimport { presentGitHubActionResult } from \"@usepipr/runtime/internal/action-result\";\nimport { stripPiprMainCommentMarkers, toPiprResult } from \"@usepipr/runtime/internal/pipr-result\";\nimport { Command, CommanderError } from \"commander\";\nimport cliPackage from \"../package.json\" with { type: \"json\" };\nimport { formatBundledSkill, materializeBundledSkill, resolveBundledSkill } from \"./skills.js\";\nimport {\n availablePiprUpdateNotice,\n resolveCurrentExecutablePath,\n runPiprUpdate,\n} from \"./update.js\";\n\ntype CliOptions = {\n configDir: string;\n database?: string;\n host?: string;\n hostname?: string;\n port?: string;\n repository?: string;\n workspace?: string;\n event?: string;\n force?: boolean;\n adapters?: string;\n recipe?: string;\n minimal?: boolean;\n requireEnv?: boolean;\n base?: string;\n head?: string;\n piExecutable?: string;\n json?: boolean;\n limit?: string;\n};\n\ntype MainOptions = {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n updateNoticeFetch?: typeof fetch;\n writeUpdateNotice?: (message: string) => void;\n};\n\nexport async function runMain(options: MainOptions = {}): Promise<void> {\n const argv = options.argv ?? process.argv;\n const env = options.env ?? process.env;\n if (!isUpdateCommand(argv)) {\n await writeAvailableUpdateNotice(options);\n }\n const program = createProgram({ exitOverride: env.GITHUB_ACTIONS === \"true\" });\n try {\n if (argv.length <= 2) {\n program.outputHelp();\n return;\n }\n await program.parseAsync(argv);\n } catch (error) {\n if (error instanceof CommanderError && error.exitCode === 0) {\n return;\n }\n throw error;\n }\n}\n\nfunction createProgram(options: { exitOverride?: boolean } = {}): Command {\n const program = new Command();\n program.name(\"pipr\").version(cliPackage.version).showHelpAfterError();\n if (options.exitOverride) {\n program.exitOverride();\n }\n program.addHelpText(\"after\", agentHelpText);\n\n program\n .command(\"init\")\n .description(\"Create editable TypeScript config\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .option(\n \"--adapters <adapters>\",\n `Adapters to initialize (${supportedOfficialInitAdapters.join(\", \")}; use 'none' to skip adapter files)`,\n )\n .option(\"--recipe <recipe>\", `Starter recipe (${supportedOfficialInitRecipes.join(\", \")})`)\n .option(\"--minimal\", \"Scaffold a single-file .pipr/config.ts without package.json\")\n .option(\"--force\", \"Overwrite existing pipr files\")\n .action(runInit);\n\n program\n .command(\"host-run\")\n .description(\"Run a change request event through a Code Host Adapter\")\n .option(\"--host <host>\", \"Code host adapter\")\n .option(\"--event <path>\", \"Native event payload path\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .action(runHostRun);\n\n const webhook = program.command(\"webhook\").description(\"Run trusted webhook ingress\");\n webhook\n .command(\"serve\")\n .description(\"Serve one repository with a durable webhook queue\")\n .requiredOption(\"--host <host>\", \"Code host adapter\")\n .requiredOption(\"--workspace <path>\", \"Trusted repository workspace\")\n .requiredOption(\"--repository <repository>\", \"Expected provider repository ID or path\")\n .option(\"--database <path>\", \"SQLite delivery database\", \".pipr/webhooks.sqlite\")\n .option(\"--hostname <hostname>\", \"Listen hostname\", \"127.0.0.1\")\n .option(\"--port <port>\", \"Listen port\", \"8787\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .action(runWebhookServe);\n webhook\n .command(\"status\")\n .description(\"Show recent webhook delivery outcomes\")\n .option(\"--database <path>\", \"SQLite delivery database\", \".pipr/webhooks.sqlite\")\n .option(\"--limit <count>\", \"Maximum deliveries to show\", \"20\")\n .option(\"--json\", \"Print versioned JSON\")\n .action(runWebhookStatus);\n\n program\n .command(\"check\")\n .description(\"Type-load config and validate the runtime plan\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .option(\"--require-env\", \"Require configured provider env vars\")\n .action(runCheck);\n\n program\n .command(\"dry-run\")\n .description(\"Load config and event without publishing\")\n .requiredOption(\"--event <path>\", \"Native event payload path\")\n .option(\"--host <host>\", \"Code host adapter\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .action(runDryRun);\n\n program\n .command(\"inspect\")\n .description(\"Print models, agents, tasks, commands, and tools\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .action(runInspect);\n\n program\n .command(\"review\")\n .description(\"Run configured change-request review tasks locally without publishing\")\n .requiredOption(\"--base <sha>\", \"Base commit SHA\")\n .option(\"--head <sha>\", \"Head commit SHA or ref; omitted reviews the working tree\")\n .option(\"--config-dir <dir>\", \"Config directory\", \".pipr\")\n .option(\"--pi-executable <path>\", \"Pi executable path\")\n .option(\"--json\", \"Print structured JSON output\")\n .action(runLocalReview);\n\n program.command(\"version\").description(\"Print the CLI version\").action(runVersion);\n\n program.command(\"update\").description(\"Update a GitHub Release binary install\").action(runUpdate);\n\n const skill = program\n .command(\"skill\")\n .description(\"Print the bundled Pipr setup skill\")\n .action(runSkillGet);\n skill\n .command(\"path\")\n .description(\"Materialize the bundled Pipr setup skill and print its directory path\")\n .action(runSkillPath);\n\n return program;\n}\n\nconst agentHelpText = `\n\nStart here (for AI agents):\n pipr skill\n\nThe Pipr setup skill ships with the CLI and is version-matched to this release.\nPrefer it over guessing commands or config shape from memory.\n\n skill Print the bundled setup skill and references\n skill path Materialize the setup skill and print its directory path\n`;\n\nasync function runHostRun(options: CliOptions): Promise<void> {\n const env = process.env;\n const isGitHubAction = env.GITHUB_ACTIONS === \"true\";\n const result = await runHostRunCommand({\n rootDir: hostRunRootDir(env),\n configDir: options.configDir,\n host: options.host,\n eventPath: options.event ?? env.PIPR_EVENT_PATH ?? env.GITHUB_EVENT_PATH,\n env,\n dryRun: env.PIPR_DRY_RUN === \"1\",\n logSink: isGitHubAction ? githubActionsLogSink : localConsoleLogSink,\n });\n if (isGitHubAction) {\n await presentGitHubActionResult(result, {\n info: core.info,\n warning: core.warning,\n setOutput(name, value) {\n core.setOutput(name, value);\n },\n });\n return;\n }\n if (result.kind === \"ignored\") {\n console.log(`ignored: ${result.reason}`);\n return;\n }\n console.log(`pipr ${result.kind} completed for change #${result.event.change.number}`);\n}\n\nfunction hostRunRootDir(env: NodeJS.ProcessEnv): string {\n return (\n env.GITHUB_WORKSPACE ??\n env.CI_PROJECT_DIR ??\n env.BITBUCKET_CLONE_DIR ??\n env.BUILD_SOURCESDIRECTORY ??\n process.cwd()\n );\n}\n\nasync function runWebhookServe(options: CliOptions): Promise<void> {\n const { runWebhookServer } = await import(\"@usepipr/runtime\");\n const secret = process.env.PIPR_WEBHOOK_SECRET;\n if (!secret) throw new Error(\"PIPR_WEBHOOK_SECRET is required\");\n const host = webhookHost(options.host);\n const port = webhookPort(options.port);\n await runWebhookServer({\n host,\n workspace: options.workspace ?? process.cwd(),\n configDir: options.configDir,\n databasePath: options.database ?? \".pipr/webhooks.sqlite\",\n expectedRepository: options.repository ?? \"\",\n secret,\n hostname: options.hostname,\n port,\n env: process.env,\n });\n}\n\nasync function runWebhookStatus(options: CliOptions): Promise<void> {\n const { readWebhookDeliveryStatus } = await import(\"@usepipr/runtime\");\n const limit = Number(options.limit);\n const deliveries = readWebhookDeliveryStatus(options.database ?? \".pipr/webhooks.sqlite\", limit);\n if (options.json) {\n console.log(JSON.stringify({ formatVersion: 1, deliveries }, null, 2));\n return;\n }\n if (deliveries.length === 0) {\n console.log(\"No webhook deliveries found.\");\n return;\n }\n const rows = deliveries.map((delivery) => [\n shorten(delivery.id, 24),\n delivery.host,\n delivery.status,\n String(delivery.attempts),\n delivery.resultKind ?? \"-\",\n delivery.runId ? shorten(delivery.runId, 12) : \"-\",\n delivery.updatedAt,\n ]);\n console.log(\n [[\"DELIVERY\", \"HOST\", \"STATUS\", \"ATTEMPTS\", \"RESULT\", \"RUN\", \"UPDATED\"], ...rows]\n .map((row) => row.join(\"\\t\"))\n .join(\"\\n\"),\n );\n}\n\nfunction shorten(value: string, length: number): string {\n return value.length <= length ? value : `${value.slice(0, length - 1)}…`;\n}\n\nfunction webhookHost(value: string | undefined): \"gitlab\" | \"azure-devops\" | \"bitbucket\" {\n if (value === \"gitlab\" || value === \"azure-devops\" || value === \"bitbucket\") return value;\n throw new Error(\"webhook serve supports --host gitlab, azure-devops, or bitbucket\");\n}\n\nfunction webhookPort(value: string | undefined): number {\n const port = Number(value);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(\"--port must be an integer from 1 to 65535\");\n }\n return port;\n}\n\nconst githubActionsLogSink: RuntimeLogSink = {\n log(record) {\n const line = JSON.stringify({\n level: record.level,\n event: record.event,\n ...record.fields,\n });\n githubActionLogWriters[record.level](\n record.text === undefined ? line : `${line}\\n${record.text}`,\n );\n },\n async group(name, run) {\n return await core.group(name, run);\n },\n};\n\nconst githubActionLogWriters = {\n info: core.info,\n notice: core.notice,\n warning: core.warning,\n error: core.error,\n debug: core.debug,\n} satisfies Record<RuntimeLogRecord[\"level\"], (message: string) => void>;\n\nasync function runInit(options: CliOptions): Promise<void> {\n const result = await runInitCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n force: options.force === true,\n adapters: options.adapters?.split(\",\").map((adapter) => adapter.trim()),\n recipe: options.recipe,\n minimal: options.minimal === true,\n });\n console.log(\n `created ${result.created.length} file(s)` +\n (result.overwritten.length > 0 ? `; overwrote ${result.overwritten.length}` : \"\"),\n );\n if (options.minimal === true) {\n console.log(\n \"For editor types, install @usepipr/sdk at the repo root: npm install -D @usepipr/sdk\",\n );\n }\n}\n\nasync function runCheck(options: CliOptions): Promise<void> {\n const settings = await runValidateCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n env: process.env,\n requireProviderEnv: options.requireEnv === true,\n });\n console.log(`valid: ${settings.source}`);\n writeConfigWarnings(settings.warnings);\n}\n\nasync function runInspect(options: CliOptions): Promise<void> {\n const result = await runInspectCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n env: process.env,\n });\n const { warnings, ...plan } = result;\n writeConfigWarnings(warnings);\n console.log(inspect(plan, { depth: 8, colors: false }));\n}\n\nfunction writeConfigWarnings(warnings: readonly string[]): void {\n for (const warning of warnings) {\n console.log(`warning: ${warning}`);\n }\n}\n\nasync function runSkillGet(): Promise<void> {\n console.log(formatBundledSkill(await resolveBundledSkill()));\n}\n\nasync function runSkillPath(): Promise<void> {\n console.log(await materializeBundledSkill());\n}\n\nfunction runVersion(): void {\n console.log(cliPackage.version);\n}\n\nasync function runUpdate(): Promise<void> {\n const result = await runPiprUpdate({\n currentVersion: cliPackage.version,\n executablePath: resolveCurrentExecutablePath(),\n });\n if (result.kind === \"up-to-date\") {\n console.log(`pipr ${result.version} is already up to date`);\n return;\n }\n console.log(`updated pipr from ${result.previousVersion} to ${result.version}`);\n}\n\nasync function writeAvailableUpdateNotice(options: MainOptions): Promise<void> {\n const env = options.env ?? process.env;\n if (shouldSkipUpdateNotice(env)) {\n return;\n }\n try {\n const notice = await availablePiprUpdateNotice({\n currentVersion: cliPackage.version,\n fetch: options.updateNoticeFetch,\n timeoutMs: 750,\n });\n if (notice) {\n (options.writeUpdateNotice ?? console.error)(\n `pipr ${notice.latestVersion} is available (current ${notice.currentVersion}). ` +\n \"Run `pipr update` for release binaries, or reinstall @usepipr/cli with npm/Bun.\",\n );\n }\n } catch {\n return;\n }\n}\n\nfunction shouldSkipUpdateNotice(env: NodeJS.ProcessEnv): boolean {\n if (env.PIPR_UPDATE_NOTICE === \"0\") {\n return true;\n }\n if (env.PIPR_UPDATE_NOTICE === \"1\") {\n return false;\n }\n\n const ci = env.CI?.trim().toLowerCase();\n return (\n (ci !== undefined && ci !== \"\" && ci !== \"0\" && ci !== \"false\") ||\n env.GITHUB_ACTIONS !== undefined\n );\n}\n\nfunction isUpdateCommand(argv: string[]): boolean {\n const args = argv.slice(2);\n if (args[0] === \"--\") {\n return args[1] === \"update\";\n }\n return (\n args[0] === \"update\" ||\n (args.length >= 2 && args[0] === \"help\" && args[1] === \"update\") ||\n (args.length >= 2 && args[0] === \"--help\" && args[1] === \"update\")\n );\n}\n\nasync function runLocalReview(options: CliOptions & { base: string }): Promise<void> {\n const result = await runLocalReviewCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n env: process.env,\n baseSha: options.base,\n headSha: options.head,\n piExecutable: options.piExecutable,\n logSink: localConsoleLogSink,\n taskLog: stderrTaskLog,\n });\n writeLocalReviewResult(result, options.json === true);\n}\n\ntype LocalReviewResult = Awaited<ReturnType<typeof runLocalReviewCommand>>;\n\nconst stderrTaskLog = {\n info(message: string) {\n console.error(`[info] ${message}`);\n },\n warn(message: string) {\n console.error(`[warn] ${message}`);\n },\n error(message: string) {\n console.error(`[error] ${message}`);\n },\n};\n\nconst localConsoleLogSink: RuntimeLogSink = {\n log(record) {\n console.error(formatLocalLogRecord(record));\n },\n async group(_name, run) {\n return await run();\n },\n};\n\nfunction formatLocalLogRecord(record: RuntimeLogRecord): string {\n const fields = Object.entries(record.fields)\n .map(([key, value]) => formatLocalLogField(key, value))\n .filter((field): field is string => field !== undefined);\n const prefix = formatLocalLogPrefix(record);\n const formatted = [...prefix, ...fields].join(\" \");\n return record.text === undefined ? formatted : `${formatted}\\n${record.text}`;\n}\n\nfunction formatLocalLogPrefix(record: RuntimeLogRecord): string[] {\n return [\"pipr\", localLogPlainLevels.has(record.level) ? \"\" : record.level, record.event].filter(\n Boolean,\n );\n}\n\nconst localLogNumberFields: Record<string, (value: number) => string> = {\n additions: (value) => `+${value}`,\n deletions: (value) => `-${value}`,\n durationMs: (value) =>\n `duration=${value < 1000 ? `${value}ms` : `${(value / 1000).toFixed(1)}s`}`,\n promptBytes: (value) => `prompt=${value}B`,\n stderrBytes: (value) => `stderr=${value}B`,\n stdoutBytes: (value) => `stdout=${value}B`,\n};\n\nconst localLogPlainLevels = new Set([\"info\", \"notice\"]);\n\nfunction formatLocalLogField(key: string, value: unknown): string | undefined {\n if (value == null) {\n return undefined;\n }\n\n return formatLocalLogFieldValue(key, value);\n}\n\nfunction formatLocalLogFieldValue(key: string, value: unknown): string {\n const formattedNumber =\n typeof value === \"number\" ? localLogNumberFields[key]?.(value) : undefined;\n return formattedNumber ?? `${key}=${formatLocalLogValue(value)}`;\n}\n\nconst localLogValueFormatters: Record<string, (value: unknown) => string> = {\n boolean: String,\n number: String,\n object: (value) =>\n Array.isArray(value)\n ? value.length === 0\n ? \"-\"\n : value.map(formatLocalLogValue).join(\",\")\n : JSON.stringify(value),\n string: (value) => {\n const text = String(value);\n return /\\s/.test(text) ? JSON.stringify(text) : text;\n },\n};\n\nfunction formatLocalLogValue(value: unknown): string {\n return (localLogValueFormatters[typeof value] ?? JSON.stringify)(value);\n}\n\nfunction writeLocalReviewResult(result: LocalReviewResult, json: boolean): void {\n if (json) {\n console.log(JSON.stringify(toPiprResult({ source: \"local\", result }), null, 2));\n return;\n }\n if (result.kind === \"skipped\") {\n console.log(`skipped: ${result.skipReason ?? \"no task matched\"}`);\n return;\n }\n console.log(formatLocalReview(result));\n}\n\nfunction formatLocalReview(result: Extract<LocalReviewResult, { kind: \"review\" }>): string {\n const mainComment = stripPiprMainCommentMarkers(result.mainComment);\n const inlineFindings = result.inlineCommentDrafts.map((draft, index) => {\n const range =\n draft.startLine === draft.endLine\n ? `${draft.path}:${draft.startLine}`\n : `${draft.path}:${draft.startLine}-${draft.endLine}`;\n return [\n `${index + 1}. ${range}`,\n `Range: ${draft.finding.rangeId ?? \"-\"}`,\n draft.finding.body,\n ].join(\"\\n\");\n });\n return inlineFindings.length === 0\n ? mainComment\n : [mainComment.trimEnd(), \"\", \"## Inline Findings\", \"\", inlineFindings.join(\"\\n\\n\")].join(\"\\n\");\n}\n\nasync function runDryRun(options: CliOptions): Promise<void> {\n if (!options.event) {\n throw new Error(\"dry-run requires --event <path>\");\n }\n const result = await runDryRunCommand({\n rootDir: process.cwd(),\n configDir: options.configDir,\n host: options.host,\n env: process.env,\n eventPath: options.event,\n });\n writeConfigWarnings(result.warnings);\n console.log(\n inspect(\n {\n configSource: result.configSource,\n event: result.event,\n },\n { depth: 6, colors: false },\n ),\n );\n}\n","export function sanitizeTerminalMessage(message: string): string {\n let sanitized = \"\";\n for (let index = 0; index < message.length; index += 1) {\n const code = message.charCodeAt(index);\n if (code === 0x1b) {\n index = skipTerminalControlSequence(message, index);\n continue;\n }\n if (code === c1OscIntroducer) {\n index = skipUntilTerminator(message, index + 1, bellTerminator);\n continue;\n }\n if (c1StringControlIntroducers.has(code)) {\n index = skipUntilTerminator(message, index + 1);\n continue;\n }\n if (code === c1CsiIntroducer) {\n index = skipCsiSequence(message, index + 1);\n continue;\n }\n if (isUnsafeTerminalControl(code)) {\n continue;\n }\n sanitized += message[index];\n }\n return sanitized;\n}\n\nconst oscIntroducer = 0x5d;\nconst csiIntroducer = 0x5b;\nconst c1OscIntroducer = 0x9d;\nconst c1CsiIntroducer = 0x9b;\nconst bellTerminator = 0x07;\nconst stringTerminator = 0x9c;\nconst stringControlIntroducers = new Set([0x50, 0x58, 0x5e, 0x5f]);\nconst c1StringControlIntroducers = new Set([0x90, 0x98, 0x9e, 0x9f]);\n\nfunction skipTerminalControlSequence(message: string, index: number): number {\n const next = message.charCodeAt(index + 1);\n if (Number.isNaN(next)) {\n return index;\n }\n if (next === oscIntroducer) {\n return skipUntilTerminator(message, index + 2, bellTerminator);\n }\n if (stringControlIntroducers.has(next)) {\n return skipUntilTerminator(message, index + 2);\n }\n if (next === csiIntroducer) {\n return skipCsiSequence(message, index + 2);\n }\n if (isEscapeIntermediate(next)) {\n return skipEscapeSequenceWithIntermediates(message, index + 1);\n }\n if (isSingleEscapeSequenceFinal(next)) {\n return index + 1;\n }\n return index;\n}\n\nfunction skipCsiSequence(message: string, index: number): number {\n for (let cursor = index; cursor < message.length; cursor += 1) {\n const code = message.charCodeAt(cursor);\n if (code >= 0x40 && code <= 0x7e) {\n return cursor;\n }\n }\n return message.length - 1;\n}\n\nfunction skipUntilTerminator(message: string, index: number, terminator?: number): number {\n for (let cursor = index; cursor < message.length; cursor += 1) {\n const code = message.charCodeAt(cursor);\n if (code === stringTerminator) {\n return cursor;\n }\n if (terminator !== undefined && code === terminator) {\n return cursor;\n }\n if (code === 0x1b && cursor + 1 < message.length && message.charCodeAt(cursor + 1) === 0x5c) {\n return cursor + 1;\n }\n }\n return message.length - 1;\n}\n\nfunction skipEscapeSequenceWithIntermediates(message: string, index: number): number {\n for (let cursor = index; cursor < message.length; cursor += 1) {\n const code = message.charCodeAt(cursor);\n if (isEscapeIntermediate(code)) {\n continue;\n }\n if (isSingleEscapeSequenceFinal(code)) {\n return cursor;\n }\n return Math.max(cursor - 1, index);\n }\n return message.length - 1;\n}\n\nfunction isEscapeIntermediate(code: number): boolean {\n return code >= 0x20 && code <= 0x2f;\n}\n\nfunction isSingleEscapeSequenceFinal(code: number): boolean {\n return code >= 0x30 && code <= 0x7e;\n}\n\nfunction isUnsafeTerminalControl(code: number): boolean {\n return (code < 0x20 && code !== 0x09 && code !== 0x0a) || (code >= 0x7f && code <= 0x9f);\n}\n","#!/usr/bin/env bun\nimport * as core from \"@actions/core\";\nimport { PublicationError } from \"@usepipr/runtime\";\nimport {\n presentGitHubActionError,\n presentGitHubActionPublicationError,\n} from \"@usepipr/runtime/internal/action-result\";\nimport { runMain } from \"./runner.js\";\nimport { sanitizeTerminalMessage } from \"./terminal-output.js\";\n\nconst env = process.env;\n\nrunMain({ env }).catch((error) => handleFatalError(error, env));\n\nasync function handleFatalError(error: unknown, env: NodeJS.ProcessEnv): Promise<void> {\n const message = error instanceof Error ? error.message : String(error);\n const sanitizedMessage = sanitizeTerminalMessage(message);\n if (env.GITHUB_ACTIONS !== \"true\") {\n console.error(`error: ${sanitizedMessage}`);\n process.exit(1);\n }\n await writeGitHubActionsFailure(error, sanitizedMessage);\n process.exitCode = 1;\n}\n\nasync function writeGitHubActionsFailure(error: unknown, message: string): Promise<void> {\n const presenter = {\n info: core.info,\n warning: core.warning,\n setOutput: core.setOutput,\n };\n if (error instanceof PublicationError) {\n await presentGitHubActionPublicationError(error, presenter);\n } else {\n await presentGitHubActionError(presenter);\n }\n core.setFailed(message);\n}\n"],"mappings":";;;;;;;;;;;;;;;ACGA,MAAa,mBAAmB;AAChC,MAAM,wCAAwB,IAAI,IAAI;CACpC;CACA;CACA;AACF,CAAC;AAiBD,SAAgB,mBAAmB,SAA4C;CAC7E,MAAM,CAAC,SAAS,QAAQ;CACxB,IAAI,QAAQ,OAAO,WAAW,KAAK,OAAO,SAAA,cACxC,MAAM,IAAI,MACR,6CAA6C,iBAAiB,YAAY,QAAQ,OAC/E,KAAK,SAAS,KAAK,IAAI,CAAC,CACxB,KAAK,IAAI,GACd;CAEF,OAAO;AACT;AAEA,SAAgB,uBAAuB,MAAc,cAA8B;CACjF,IAAI,KAAK,WAAW,YAAY,GAC9B,MAAM,IAAI,MAAM,6CAA6C,cAAc;CAE7E,MAAM,eAAe,KAAK,QAAQ,IAAI;CACtC,MAAM,SAAS,KAAK,QAAQ,cAAc,YAAY;CACtD,IAAI,WAAW,gBAAgB,CAAC,OAAO,WAAW,GAAG,eAAe,KAAK,KAAK,GAC5E,MAAM,IAAI,MAAM,wDAAwD,cAAc;CAExF,OAAO;AACT;AAEA,eAAsB,wBAAwB,YAAkD;CAC9F,MAAM,UAAU,MAAM,QAAQ,YAAY,EAAE,eAAe,KAAK,CAAC;CAmBjE,MAAM,UAAU,EAAE,SAAQ,MAlBL,QAAQ,IAC3B,QACG,QAAQ,UAAU,MAAM,YAAY,CAAC,CAAC,CACtC,IAAI,OAAO,UAAU;EACpB,MAAM,WAAW,KAAK,KAAK,YAAY,MAAM,IAAI;EACjD,MAAM,QAAQ,MAAM,eAAe,QAAQ;EAC3C,0BAA0B,MAAM,MAAM,KAAK;EAC3C,MAAM,UAAU,MAAM,MAAM,SAAS,KAAK,SAAS,UAAU;EAC7D,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,GAAG,SAAS,mBAAmB;EAEjD,OAAO;GACL,MAAM,MAAM;GACZ,aAAa,uBAAuB,QAAQ,QAAQ;GACpD;EACF;CACF,CAAC,CACL,EAAA,CACiC,MAAM,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC,EAAE;CAC5F,mBAAmB,OAAO;CAC1B,OAAO;AACT;AAEA,eAAe,eAAe,UAAkB,SAAS,IAAiC;CACxF,MAAM,UAAU,MAAM,QAAQ,KAAK,KAAK,UAAU,MAAM,GAAG,EAAE,eAAe,KAAK,CAAC;CAiBlF,QAAO,MAhBa,QAAQ,IAC1B,QACG,QAAQ,UAAU,CAAC,MAAM,KAAK,WAAW,GAAG,CAAC,CAAC,CAC9C,MAAM,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC,CAAC,CAC1D,IAAI,OAAO,UAAU;EACpB,MAAM,eAAe,SAAS,KAAK,KAAK,QAAQ,MAAM,IAAI,IAAI,MAAM;EACpE,IAAI,MAAM,YAAY,GACpB,OAAO,MAAM,eAAe,UAAU,YAAY;EAEpD,IAAI,CAAC,MAAM,OAAO,GAChB,OAAO,CAAC;EAEV,MAAM,WAAW,MAAM,IAAI,KAAK,KAAK,KAAK,UAAU,YAAY,CAAC,CAAC,CAAC,KAAK;EACxE,OAAO,CAAC;GAAE,MAAM,aAAa,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG;GAAG;EAAS,CAAC;CACpE,CAAC,CACL,EAAA,CACa,KAAK;AACpB;AAEA,SAAS,uBAAuB,UAA0B;CAExD,MAAM,eADc,SAAS,MAAM,+BAA+B,CAAC,EAAE,QAAQ,KAAA,EAEzE,MAAM,IAAI,CAAC,CACZ,MAAM,SAAS,KAAK,WAAW,cAAc,CAAC,CAAC,EAC9C,QAAQ,qBAAqB,EAAE,CAAC,CACjC,KAAK,CAAC,CACN,QAAQ,iBAAiB,EAAE;CAC9B,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,iDAAiD;CAEnE,OAAO;AACT;AAEA,SAAS,0BAA0B,WAAmB,OAAiC;CACrF,IAAI,cAAA,cACF;CAEF,MAAM,QAAQ,IAAI,IAAI,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC;CACpD,MAAM,aAAa,CAAC,GAAG,KAAK,CAAC,CAAC,QAAQ,aAAa,CAAC,sBAAsB,IAAI,QAAQ,CAAC;CACvF,MAAM,UAAU,CAAC,GAAG,qBAAqB,CAAC,CAAC,QAAQ,aAAa,CAAC,MAAM,IAAI,QAAQ,CAAC;CACpF,IAAI,WAAW,SAAS,KAAK,QAAQ,SAAS,GAC5C,MAAM,IAAI,MACR,GAAG,iBAAiB,+DACH,WAAW,KAAK,IAAI,KAAK,IAAI,aAAa,QAAQ,KAAK,IAAI,KAAK,KACnF;AAEJ;;;AC1GA,IAAI;AAMJ,eAAsB,sBAA6C;CACjE,iBAAiB,iBAAiB;CAClC,OAAO,MAAM;AACf;AAEA,SAAgB,mBAAmB,OAA6B;CAC9D,MAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,KAAK,iBAAiB;CACrD,OAAO;EACL,KAAK,MAAM;EACX;EACA,MAAM;EACN;EACA,GAAG,MAAM,SAAS,SAAS;GACzB,2BAA2B,KAAK,KAAK;GACrC,KAAK,SAAS,QAAQ;GACtB,yBAAyB,KAAK,KAAK;GACnC;EACF,CAAC;CACH,CAAC,CAAC,KAAK,IAAI;AACb;AAEA,SAAS,kBAAkB,MAAwB,OAAiC;CAClF,IAAI,KAAK,SAAS,YAChB,OAAO;CAET,IAAI,MAAM,SAAS,YACjB,OAAO;CAET,OAAO,KAAK,KAAK,cAAc,MAAM,IAAI;AAC3C;AAEA,eAAsB,0BAA2C;CAC/D,MAAM,QAAQ,MAAM,oBAAoB;CACxC,MAAM,aAAa,KAAK,KAAK,eAAe,GAAGA,OAAkB;CACjE,MAAM,WAAW,KAAK,KAAK,YAAY,MAAM,IAAI;CACjD,MAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;CAC3C,MAAM,aAAa,MAAM,QAAQ,KAAK,KAAK,YAAY,GAAG,iBAAiB,EAAE,CAAC;CAC9E,IAAI;EACF,KAAK,MAAM,QAAQ,MAAM,OACvB,MAAM,eAAe,YAAY,IAAI;EAEvC,IAAI,MAAM,sBAAsB,UAAU,MAAM,KAAK,GAAG;GACtD,MAAM,GAAG,YAAY;IAAE,WAAW;IAAM,OAAO;GAAK,CAAC;GACrD,OAAO;EACT;EACA,MAAM,GAAG,UAAU;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;EACnD,MAAM,qBAAqB,YAAY,UAAU,MAAM,KAAK;CAC9D,SAAS,OAAO;EACd,MAAM,GAAG,YAAY;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;EACrD,MAAM;CACR;CACA,OAAO;AACT;AAEA,eAAe,mBAA0C;CAEvD,OAAO,mBADU,qBACgB,KAAM,MAAM,2BAA2B,CAAE;AAC5E;AAEA,eAAe,6BAA2D;CACxE,MAAM,WAAW,MAAM,QAAQ,IAAI,oBAAoB,CAAC,CAAC,IAAI,uBAAuB,CAAC;CACrF,MAAM,SAAS,SAAS,MACrB,YACC,aAAa,OACjB;CACA,IAAI,QACF,OAAO,OAAO;CAEhB,MAAM,IAAI,MACR,wCAAwC,SACrC,KAAK,YAAY,GAAG,QAAQ,WAAW,IAAI,WAAW,UAAU,QAAQ,QAAQ,UAAU,CAAC,CAC3F,KAAK,IAAI,GACd;AACF;AAEA,eAAe,wBAAwB,YAAkD;CACvF,IAAI;EACF,OAAO;GAAE;GAAY,SAAS,MAAM,wBAAwB,UAAU;EAAE;CAC1E,SAAS,OAAO;EACd,OAAO;GAAE;GAAY,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAAE;CACrF;AACF;AAEA,SAAS,uBAAwD;CAC/D,IAAI,OAAO,yBAAyB,YAAY,qBAAqB,WAAW,GAC9E;CAEF,OAAO,KAAK,MAAM,oBAAoB;AACxC;AAEA,SAAS,sBAAgC;CACvC,MAAM,OAAO,OAAO,KAAK;CACzB,OAAO,CAAC,KAAK,KAAK,MAAM,QAAQ,GAAG,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC1E;AAEA,eAAe,eAAe,UAAkB,MAAuC;CACrF,MAAM,SAAS,uBAAuB,UAAU,KAAK,IAAI;CACzD,MAAM,MAAM,KAAK,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;CACrD,MAAM,IAAI,MAAM,QAAQ,KAAK,QAAQ;AACvC;AAEA,eAAe,qBACb,YACA,UACA,OACe;CACf,IAAI;EACF,MAAM,OAAO,YAAY,QAAQ;CACnC,SAAS,OAAO;EACd,IAAI,yBAAyB,KAAK,KAAM,MAAM,sBAAsB,UAAU,KAAK,GAAI;GACrF,MAAM,GAAG,YAAY;IAAE,WAAW;IAAM,OAAO;GAAK,CAAC;GACrD;EACF;EACA,MAAM;CACR;AACF;AAEA,eAAe,sBACb,UACA,OACkB;CAClB,IAAI;EACF,OACG,MAAM,yBAAyB,UAAU,KAAK,KAC9C,MAAM,4BAA4B,UAAU,KAAK;CAEtD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAe,yBACb,UACA,OACkB;CAClB,MAAM,cAAc,MAAM,0BAA0B,QAAQ;CAC5D,MAAM,gBAAgB,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK;CAC1D,OACE,YAAY,WAAW,cAAc,UACrC,YAAY,OAAO,OAAO,UAAU,UAAU,cAAc,MAAM;AAEtE;AAEA,eAAe,4BACb,UACA,OACkB;CAClB,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAE,MAAM,iBAAiB,UAAU,IAAI,GACzC,OAAO;CAGX,OAAO;AACT;AAEA,eAAe,iBAAiB,UAAkB,MAA0C;CAC1F,MAAM,SAAS,uBAAuB,UAAU,KAAK,IAAI;CACzD,QAAQ,MAAM,MAAM,MAAM,EAAA,CAAG,OAAO,KAAM,MAAM,IAAI,KAAK,MAAM,CAAC,CAAC,KAAK,MAAO,KAAK;AACpF;AAEA,eAAe,0BAA0B,UAAkB,SAAS,IAAuB;CACzF,MAAM,UAAU,MAAM,QAAQ,KAAK,KAAK,UAAU,MAAM,GAAG,EAAE,eAAe,KAAK,CAAC;CAYlF,QAAO,MAXa,QAAQ,IAC1B,QACG,QAAQ,UAAU,CAAC,MAAM,KAAK,WAAW,GAAG,CAAC,CAAC,CAC9C,IAAI,OAAO,UAAU;EACpB,MAAM,eAAe,SAAS,KAAK,KAAK,QAAQ,MAAM,IAAI,IAAI,MAAM;EACpE,IAAI,MAAM,YAAY,GACpB,OAAO,MAAM,0BAA0B,UAAU,YAAY;EAE/D,OAAO,CAAC,aAAa,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC;CAChD,CAAC,CACL,EAAA,CACa,KAAK,CAAC,CAAC,KAAK;AAC3B;AAEA,MAAM,8CAA8B,IAAI,IAAI,CAAC,UAAU,WAAW,CAAC;AAEnE,SAAS,yBAAyB,OAAyB;CACzD,OAAO,4BAA4B,IAAK,OAAyC,QAAQ,EAAE;AAC7F;AAEA,SAAS,iBAAyB;CAChC,MAAM,WAAW,QAAQ,IAAI;CAC7B,IAAI,YAAY,SAAS,KAAK,CAAC,CAAC,SAAS,GACvC,OAAO,KAAK,QAAQ,QAAQ;CAE9B,MAAM,YAAY,QAAQ,IAAI,kBAAkB,KAAK,KAAK,GAAG,QAAQ,GAAG,QAAQ;CAChF,OAAO,KAAK,KAAK,WAAW,QAAQ,QAAQ;AAC9C;;;ACzMA,MAAa,iBAAkC;CAC7C;EAAE,UAAU;EAAS,MAAM;EAAO,QAAQ;EAA0B,SAAS;CAAiB;CAC9F;EAAE,UAAU;EAAS,MAAM;EAAS,QAAQ;EAAmB,SAAS;CAAmB;CAC3F;EAAE,UAAU;EAAU,MAAM;EAAO,QAAQ;EAAkB,SAAS;CAAkB;CACxF;EACE,UAAU;EACV,MAAM;EACN,QAAQ;EACR,SAAS;CACX;AACF;AAEA,SAAgB,yBAAyB,UAAsD;CAC7F,OAAO,eAAe,MACnB,WAAW,OAAO,aAAa,SAAS,YAAY,OAAO,SAAS,SAAS,IAChF;AACF;AAEA,SAAgB,wBAAwB,UAAmC;CACzE,MAAM,SAAS,yBAAyB,QAAQ;CAChD,IAAI,QACF,OAAO,OAAO;CAEhB,IAAI,CAAC,eAAe,MAAM,SAAS,KAAK,aAAa,SAAS,QAAQ,GACpE,MAAM,IAAI,MAAM,+BAA+B,SAAS,UAAU;CAEpE,MAAM,IAAI,MAAM,yCAAyC,SAAS,MAAM;AAC1E;;;ACAA,MAAM,eAAe;AACrB,MAAM,2BAA2B;CAC/B;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,IAAI;AAEX,SAAgB,6BACd,UAAkD,CAAC,GAC3C;CACR,MAAM,WAAW,QAAQ,YAAY,QAAQ;CAC7C,MAAM,OAAO,QAAQ,QAAQ,QAAQ;CACrC,MAAM,WAAW,KAAK,SAAS,QAAQ,CAAC,CAAC,YAAY;CACrD,MAAM,aAAa,KAAK;CACxB,IACE,aAAa,SACb,SAAS,WAAW,MAAM,KAC1B,aAAa,UACb,SAAS,WAAW,OAAO,KAC3B,YAAY,SAAS,KAAK,KAC1B,YAAY,SAAS,MAAM,GAE3B,MAAM,IAAI,MAAM,wBAAwB;CAE1C,OAAO;AACT;AAEA,eAAsB,cAAc,SAA+C;CACjF,IAAI,CAAC,eAAe,QAAQ,cAAc,GACxC,MAAM,IAAI,MACR,wDAAwD,QAAQ,gBAClE;CAEF,MAAM,eAAe,QAAQ,SAAS,WAAW,MAAM,KAAK,UAAU;CAEtE,MAAM,QAAQ,wBADG,QAAQ,YAAY;EAAE,UAAU,QAAQ;EAAU,MAAM,QAAQ;CAAK,CACxC;CAC9C,MAAM,UAAU,MAAM,cAAc,YAAY;CAChD,MAAM,UAAU,QAAQ;CACxB,IAAI,cAAc,SAAS,QAAQ,cAAc,KAAK,GACpD,OAAO;EAAE,MAAM;EAAc,SAAS,QAAQ;CAAe;CAE/D,MAAM,yBAAyB,sBAAsB,aAAa,qBAAqB,QAAQ;CAC/F,MAAM,CAAC,QAAQ,aAAa,MAAM,QAAQ,IAAI,CAC5C,cAAc,cAAc,GAAG,uBAAuB,GAAG,OAAO,GAChE,aAAa,cAAc,GAAG,uBAAuB,YAAY,CACnE,CAAC;CACD,eAAe,QAAQ,iBAAiB,WAAW,KAAK,GAAG,KAAK;CAEhE,MAAM,WAAW,KAAK,KACpB,KAAK,QAAQ,QAAQ,cAAc,GACnC,gBAAgB,QAAQ,IAAI,GAAG,KAAK,IAAI,GAC1C;CACA,IAAI,cAAc;CAClB,IAAI,WAAW;CACf,IAAI;EACF,MAAM,WAAW,MAAM,KAAK,UAAU,MAAM,GAAK;EACjD,cAAc;EACd,IAAI;GACF,MAAM,SAAS,UAAU,MAAM;EACjC,UAAU;GACR,MAAM,SAAS,MAAM;EACvB;EACA,MAAM,MAAM,UAAU,GAAK;EAC3B,MAAM,gBAAgB,MAAM,kBAAkB,QAAQ;EACtD,IAAI,CAAC,eAAe,aAAa,GAC/B,MAAM,IAAI,MAAM,oDAAoD,eAAe;EAErF,IAAI,kBAAkB,SACpB,MAAM,IAAI,MACR,mCAAmC,cAAc,oBAAoB,SACvE;EAEF,MAAM,OAAO,UAAU,QAAQ,cAAc;EAC7C,WAAW;EACX,OAAO;GAAE,MAAM;GAAW,iBAAiB,QAAQ;GAAgB;EAAQ;CAC7E,UAAU;EACR,IAAI,eAAe,CAAC,UAClB,MAAM,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC;CAEtC;AACF;AAEA,eAAsB,0BACpB,SACmC;CACnC,IAAI,CAAC,eAAe,QAAQ,cAAc,GACxC;CAMF,MAAM,UAAU,MAAM,cAJD,iBACnB,QAAQ,SAAS,WAAW,MAAM,KAAK,UAAU,GACjD,QAAQ,SAEqC,CAAC;CAChD,IAAI,cAAc,QAAQ,SAAS,QAAQ,cAAc,KAAK,GAC5D;CAEF,OAAO;EAAE,gBAAgB,QAAQ;EAAgB,eAAe,QAAQ;CAAQ;AAClF;AAEA,SAAS,iBAAiB,cAA4B,WAA6C;CACjG,IAAI,cAAc,KAAA,GAChB,OAAO;CAET,OAAO,OAAO,KAAK,SAAS;EAC1B,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,UAAU,iBAAiB,WAAW,MAAM,GAAG,SAAS;EAC9D,IAAI;GACF,OAAO,MAAM,aAAa,KAAK;IAAE,GAAG;IAAM,QAAQ,WAAW;GAAO,CAAC;EACvE,UAAU;GACR,aAAa,OAAO;EACtB;CACF;AACF;AAEA,eAAe,cAAc,cAG1B;CACD,MAAM,WAAW,MAAM,aACrB,gCAAgC,aAAa,iBAC/C;CACA,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,iDAAiD,SAAS,QAAQ;CAEpF,MAAM,UAAW,MAAM,SAAS,KAAK;CACrC,IAAI,OAAO,QAAQ,aAAa,UAC9B,MAAM,IAAI,MAAM,6CAA6C;CAE/D,MAAM,UAAU,QAAQ,SAAS,QAAQ,MAAM,EAAE;CACjD,IAAI,CAAC,eAAe,OAAO,GACzB,MAAM,IAAI,MAAM,sDAAsD,QAAQ,UAAU;CAE1F,OAAO;EAAE,KAAK,QAAQ;EAAU;CAAQ;AAC1C;AAEA,eAAe,cACb,cACA,KACiB;CACjB,MAAM,WAAW,MAAM,aAAa,GAAG;CACvC,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,sBAAsB,IAAI,SAAS,SAAS,QAAQ;CAEtE,OAAO,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AACjD;AAEA,eAAe,aACb,cACA,KACiB;CACjB,MAAM,WAAW,MAAM,aAAa,GAAG;CACvC,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,sBAAsB,IAAI,SAAS,SAAS,QAAQ;CAEtE,OAAO,MAAM,SAAS,KAAK;AAC7B;AAEA,SAAS,iBAAiB,WAAmB,OAAuB;CAClE,KAAK,MAAM,QAAQ,UAAU,MAAM,OAAO,GAAG;EAC3C,MAAM,CAAC,UAAU,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM,KAAK;EAChD,IAAI,SAAS,SAAS,UACpB,OAAO;CAEX;CACA,MAAM,IAAI,MAAM,gBAAgB,MAAM,WAAW;AACnD;AAEA,SAAS,eAAe,QAAgB,UAAkB,OAAqB;CAE7E,IADe,WAAW,QAAQ,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,OAAO,KACjD,MAAM,UACb,MAAM,IAAI,MAAM,yBAAyB,OAAO;AAEpD;AAEA,eAAe,kBAAkB,gBAAyC;CACxE,MAAM,gBAAgB,MAAM,QAAQ,KAAK,KAAK,GAAG,OAAO,GAAG,sBAAsB,CAAC;CAClF,IAAI;EACF,MAAM,UAAU,IAAI,MAAM,CAAC,gBAAgB,WAAW,GAAG;GACvD,KAAK;GACL,KAAK;IACH,MAAM;IACN,MAAM;IACN,QAAQ;GACV;GACA,QAAQ;GACR,QAAQ;EACV,CAAC;EACD,MAAM,CAAC,UAAU,QAAQ,UAAU,MAAM,QAAQ,IAAI;GACnD,QAAQ;GACR,QAAQ,SAAS,IAAI,SAAS,QAAQ,MAAM,CAAC,CAAC,KAAK,IAAI;GACvD,QAAQ,SAAS,IAAI,SAAS,QAAQ,MAAM,CAAC,CAAC,KAAK,IAAI;EACzD,CAAC;EACD,IAAI,aAAa,GACf,MAAM,IAAI,MACR,4CAA4C,OAAO,KAAK,KAAK,OAAO,KAAK,KAAK,UAChF;EAEF,OAAO,OAAO,KAAK;CACrB,UAAU;EACR,MAAM,GAAG,eAAe;GAAE,OAAO;GAAM,WAAW;EAAK,CAAC;CAC1D;AACF;AAEA,SAAS,eAAe,SAA0B;CAChD,OAAO,kBAAkB,KAAK,OAAO;AACvC;AAEA,SAAS,cAAc,MAAc,OAAuB;CAC1D,MAAM,YAAY,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CAC5C,MAAM,aAAa,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CAC9C,KAAK,IAAI,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG;EACzC,MAAM,aAAa,UAAU,SAAS,WAAW;EACjD,IAAI,eAAe,GACjB,OAAO;CAEX;CACA,OAAO;AACT;;;AC1MA,eAAsB,QAAQ,UAAuB,CAAC,GAAkB;CACtE,MAAM,OAAO,QAAQ,QAAQ,QAAQ;CACrC,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,IAAI,CAAC,gBAAgB,IAAI,GACvB,MAAM,2BAA2B,OAAO;CAE1C,MAAM,UAAU,cAAc,EAAE,cAAc,IAAI,mBAAmB,OAAO,CAAC;CAC7E,IAAI;EACF,IAAI,KAAK,UAAU,GAAG;GACpB,QAAQ,WAAW;GACnB;EACF;EACA,MAAM,QAAQ,WAAW,IAAI;CAC/B,SAAS,OAAO;EACd,IAAI,iBAAiB,kBAAkB,MAAM,aAAa,GACxD;EAEF,MAAM;CACR;AACF;AAEA,SAAS,cAAc,UAAsC,CAAC,GAAY;CACxE,MAAM,UAAU,IAAI,QAAQ;CAC5B,QAAQ,KAAK,MAAM,CAAC,CAAC,QAAQC,OAAkB,CAAC,CAAC,mBAAmB;CACpE,IAAI,QAAQ,cACV,QAAQ,aAAa;CAEvB,QAAQ,YAAY,SAAS,aAAa;CAE1C,QACG,QAAQ,MAAM,CAAC,CACf,YAAY,mCAAmC,CAAC,CAChD,OAAO,sBAAsB,oBAAoB,OAAO,CAAC,CACzD,OACC,yBACA,2BAA2B,8BAA8B,KAAK,IAAI,EAAE,oCACtE,CAAC,CACA,OAAO,qBAAqB,mBAAmB,6BAA6B,KAAK,IAAI,EAAE,EAAE,CAAC,CAC1F,OAAO,aAAa,6DAA6D,CAAC,CAClF,OAAO,WAAW,+BAA+B,CAAC,CAClD,OAAO,OAAO;CAEjB,QACG,QAAQ,UAAU,CAAC,CACnB,YAAY,wDAAwD,CAAC,CACrE,OAAO,iBAAiB,mBAAmB,CAAC,CAC5C,OAAO,kBAAkB,2BAA2B,CAAC,CACrD,OAAO,sBAAsB,oBAAoB,OAAO,CAAC,CACzD,OAAO,UAAU;CAEpB,MAAM,UAAU,QAAQ,QAAQ,SAAS,CAAC,CAAC,YAAY,6BAA6B;CACpF,QACG,QAAQ,OAAO,CAAC,CAChB,YAAY,mDAAmD,CAAC,CAChE,eAAe,iBAAiB,mBAAmB,CAAC,CACpD,eAAe,sBAAsB,8BAA8B,CAAC,CACpE,eAAe,6BAA6B,yCAAyC,CAAC,CACtF,OAAO,qBAAqB,4BAA4B,uBAAuB,CAAC,CAChF,OAAO,yBAAyB,mBAAmB,WAAW,CAAC,CAC/D,OAAO,iBAAiB,eAAe,MAAM,CAAC,CAC9C,OAAO,sBAAsB,oBAAoB,OAAO,CAAC,CACzD,OAAO,eAAe;CACzB,QACG,QAAQ,QAAQ,CAAC,CACjB,YAAY,uCAAuC,CAAC,CACpD,OAAO,qBAAqB,4BAA4B,uBAAuB,CAAC,CAChF,OAAO,mBAAmB,8BAA8B,IAAI,CAAC,CAC7D,OAAO,UAAU,sBAAsB,CAAC,CACxC,OAAO,gBAAgB;CAE1B,QACG,QAAQ,OAAO,CAAC,CAChB,YAAY,gDAAgD,CAAC,CAC7D,OAAO,sBAAsB,oBAAoB,OAAO,CAAC,CACzD,OAAO,iBAAiB,sCAAsC,CAAC,CAC/D,OAAO,QAAQ;CAElB,QACG,QAAQ,SAAS,CAAC,CAClB,YAAY,0CAA0C,CAAC,CACvD,eAAe,kBAAkB,2BAA2B,CAAC,CAC7D,OAAO,iBAAiB,mBAAmB,CAAC,CAC5C,OAAO,sBAAsB,oBAAoB,OAAO,CAAC,CACzD,OAAO,SAAS;CAEnB,QACG,QAAQ,SAAS,CAAC,CAClB,YAAY,kDAAkD,CAAC,CAC/D,OAAO,sBAAsB,oBAAoB,OAAO,CAAC,CACzD,OAAO,UAAU;CAEpB,QACG,QAAQ,QAAQ,CAAC,CACjB,YAAY,uEAAuE,CAAC,CACpF,eAAe,gBAAgB,iBAAiB,CAAC,CACjD,OAAO,gBAAgB,0DAA0D,CAAC,CAClF,OAAO,sBAAsB,oBAAoB,OAAO,CAAC,CACzD,OAAO,0BAA0B,oBAAoB,CAAC,CACtD,OAAO,UAAU,8BAA8B,CAAC,CAChD,OAAO,cAAc;CAExB,QAAQ,QAAQ,SAAS,CAAC,CAAC,YAAY,uBAAuB,CAAC,CAAC,OAAO,UAAU;CAEjF,QAAQ,QAAQ,QAAQ,CAAC,CAAC,YAAY,wCAAwC,CAAC,CAAC,OAAO,SAAS;CAMhG,QAHG,QAAQ,OAAO,CAAC,CAChB,YAAY,oCAAoC,CAAC,CACjD,OAAO,WACN,CAAC,CACF,QAAQ,MAAM,CAAC,CACf,YAAY,uEAAuE,CAAC,CACpF,OAAO,YAAY;CAEtB,OAAO;AACT;AAEA,MAAM,gBAAgB;;;;;;;;;;;AAYtB,eAAe,WAAW,SAAoC;CAC5D,MAAM,MAAM,QAAQ;CACpB,MAAM,iBAAiB,IAAI,mBAAmB;CAC9C,MAAM,SAAS,MAAM,kBAAkB;EACrC,SAAS,eAAe,GAAG;EAC3B,WAAW,QAAQ;EACnB,MAAM,QAAQ;EACd,WAAW,QAAQ,SAAS,IAAI,mBAAmB,IAAI;EACvD;EACA,QAAQ,IAAI,iBAAiB;EAC7B,SAAS,iBAAiB,uBAAuB;CACnD,CAAC;CACD,IAAI,gBAAgB;EAClB,MAAM,0BAA0B,QAAQ;GACtC,MAAM,KAAK;GACX,SAAS,KAAK;GACd,UAAU,MAAM,OAAO;IACrB,KAAK,UAAU,MAAM,KAAK;GAC5B;EACF,CAAC;EACD;CACF;CACA,IAAI,OAAO,SAAS,WAAW;EAC7B,QAAQ,IAAI,YAAY,OAAO,QAAQ;EACvC;CACF;CACA,QAAQ,IAAI,QAAQ,OAAO,KAAK,yBAAyB,OAAO,MAAM,OAAO,QAAQ;AACvF;AAEA,SAAS,eAAe,KAAgC;CACtD,OACE,IAAI,oBACJ,IAAI,kBACJ,IAAI,uBACJ,IAAI,0BACJ,QAAQ,IAAI;AAEhB;AAEA,eAAe,gBAAgB,SAAoC;CACjE,MAAM,EAAE,qBAAqB,MAAM,OAAO;CAC1C,MAAM,SAAS,QAAQ,IAAI;CAC3B,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,iCAAiC;CAC9D,MAAM,OAAO,YAAY,QAAQ,IAAI;CACrC,MAAM,OAAO,YAAY,QAAQ,IAAI;CACrC,MAAM,iBAAiB;EACrB;EACA,WAAW,QAAQ,aAAa,QAAQ,IAAI;EAC5C,WAAW,QAAQ;EACnB,cAAc,QAAQ,YAAY;EAClC,oBAAoB,QAAQ,cAAc;EAC1C;EACA,UAAU,QAAQ;EAClB;EACA,KAAK,QAAQ;CACf,CAAC;AACH;AAEA,eAAe,iBAAiB,SAAoC;CAClE,MAAM,EAAE,8BAA8B,MAAM,OAAO;CACnD,MAAM,QAAQ,OAAO,QAAQ,KAAK;CAClC,MAAM,aAAa,0BAA0B,QAAQ,YAAY,yBAAyB,KAAK;CAC/F,IAAI,QAAQ,MAAM;EAChB,QAAQ,IAAI,KAAK,UAAU;GAAE,eAAe;GAAG;EAAW,GAAG,MAAM,CAAC,CAAC;EACrE;CACF;CACA,IAAI,WAAW,WAAW,GAAG;EAC3B,QAAQ,IAAI,8BAA8B;EAC1C;CACF;CACA,MAAM,OAAO,WAAW,KAAK,aAAa;EACxC,QAAQ,SAAS,IAAI,EAAE;EACvB,SAAS;EACT,SAAS;EACT,OAAO,SAAS,QAAQ;EACxB,SAAS,cAAc;EACvB,SAAS,QAAQ,QAAQ,SAAS,OAAO,EAAE,IAAI;EAC/C,SAAS;CACX,CAAC;CACD,QAAQ,IACN,CAAC;EAAC;EAAY;EAAQ;EAAU;EAAY;EAAU;EAAO;CAAS,GAAG,GAAG,IAAI,CAAC,CAC9E,KAAK,QAAQ,IAAI,KAAK,GAAI,CAAC,CAAC,CAC5B,KAAK,IAAI,CACd;AACF;AAEA,SAAS,QAAQ,OAAe,QAAwB;CACtD,OAAO,MAAM,UAAU,SAAS,QAAQ,GAAG,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE;AACxE;AAEA,SAAS,YAAY,OAAoE;CACvF,IAAI,UAAU,YAAY,UAAU,kBAAkB,UAAU,aAAa,OAAO;CACpF,MAAM,IAAI,MAAM,kEAAkE;AACpF;AAEA,SAAS,YAAY,OAAmC;CACtD,MAAM,OAAO,OAAO,KAAK;CACzB,IAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAChD,MAAM,IAAI,MAAM,2CAA2C;CAE7D,OAAO;AACT;AAEA,MAAM,uBAAuC;CAC3C,IAAI,QAAQ;EACV,MAAM,OAAO,KAAK,UAAU;GAC1B,OAAO,OAAO;GACd,OAAO,OAAO;GACd,GAAG,OAAO;EACZ,CAAC;EACD,uBAAuB,OAAO,MAAM,CAClC,OAAO,SAAS,KAAA,IAAY,OAAO,GAAG,KAAK,IAAI,OAAO,MACxD;CACF;CACA,MAAM,MAAM,MAAM,KAAK;EACrB,OAAO,MAAM,KAAK,MAAM,MAAM,GAAG;CACnC;AACF;AAEA,MAAM,yBAAyB;CAC7B,MAAM,KAAK;CACX,QAAQ,KAAK;CACb,SAAS,KAAK;CACd,OAAO,KAAK;CACZ,OAAO,KAAK;AACd;AAEA,eAAe,QAAQ,SAAoC;CACzD,MAAM,SAAS,MAAM,eAAe;EAClC,SAAS,QAAQ,IAAI;EACrB,WAAW,QAAQ;EACnB,OAAO,QAAQ,UAAU;EACzB,UAAU,QAAQ,UAAU,MAAM,GAAG,CAAC,CAAC,KAAK,YAAY,QAAQ,KAAK,CAAC;EACtE,QAAQ,QAAQ;EAChB,SAAS,QAAQ,YAAY;CAC/B,CAAC;CACD,QAAQ,IACN,WAAW,OAAO,QAAQ,OAAO,aAC9B,OAAO,YAAY,SAAS,IAAI,eAAe,OAAO,YAAY,WAAW,GAClF;CACA,IAAI,QAAQ,YAAY,MACtB,QAAQ,IACN,sFACF;AAEJ;AAEA,eAAe,SAAS,SAAoC;CAC1D,MAAM,WAAW,MAAM,mBAAmB;EACxC,SAAS,QAAQ,IAAI;EACrB,WAAW,QAAQ;EACnB,KAAK,QAAQ;EACb,oBAAoB,QAAQ,eAAe;CAC7C,CAAC;CACD,QAAQ,IAAI,UAAU,SAAS,QAAQ;CACvC,oBAAoB,SAAS,QAAQ;AACvC;AAEA,eAAe,WAAW,SAAoC;CAM5D,MAAM,EAAE,UAAU,GAAG,SAAS,MALT,kBAAkB;EACrC,SAAS,QAAQ,IAAI;EACrB,WAAW,QAAQ;EACnB,KAAK,QAAQ;CACf,CAAC;CAED,oBAAoB,QAAQ;CAC5B,QAAQ,IAAI,QAAQ,MAAM;EAAE,OAAO;EAAG,QAAQ;CAAM,CAAC,CAAC;AACxD;AAEA,SAAS,oBAAoB,UAAmC;CAC9D,KAAK,MAAM,WAAW,UACpB,QAAQ,IAAI,YAAY,SAAS;AAErC;AAEA,eAAe,cAA6B;CAC1C,QAAQ,IAAI,mBAAmB,MAAM,oBAAoB,CAAC,CAAC;AAC7D;AAEA,eAAe,eAA8B;CAC3C,QAAQ,IAAI,MAAM,wBAAwB,CAAC;AAC7C;AAEA,SAAS,aAAmB;CAC1B,QAAQ,IAAIA,OAAkB;AAChC;AAEA,eAAe,YAA2B;CACxC,MAAM,SAAS,MAAM,cAAc;EACjC,gBAAgBA;EAChB,gBAAgB,6BAA6B;CAC/C,CAAC;CACD,IAAI,OAAO,SAAS,cAAc;EAChC,QAAQ,IAAI,QAAQ,OAAO,QAAQ,uBAAuB;EAC1D;CACF;CACA,QAAQ,IAAI,qBAAqB,OAAO,gBAAgB,MAAM,OAAO,SAAS;AAChF;AAEA,eAAe,2BAA2B,SAAqC;CAE7E,IAAI,uBADQ,QAAQ,OAAO,QAAQ,GACL,GAC5B;CAEF,IAAI;EACF,MAAM,SAAS,MAAM,0BAA0B;GAC7C,gBAAgBA;GAChB,OAAO,QAAQ;GACf,WAAW;EACb,CAAC;EACD,IAAI,QACF,CAAC,QAAQ,qBAAqB,QAAQ,MAAA,CACpC,QAAQ,OAAO,cAAc,yBAAyB,OAAO,eAAe,qFAE9E;CAEJ,QAAQ;EACN;CACF;AACF;AAEA,SAAS,uBAAuB,KAAiC;CAC/D,IAAI,IAAI,uBAAuB,KAC7B,OAAO;CAET,IAAI,IAAI,uBAAuB,KAC7B,OAAO;CAGT,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,YAAY;CACtC,OACG,OAAO,KAAA,KAAa,OAAO,MAAM,OAAO,OAAO,OAAO,WACvD,IAAI,mBAAmB,KAAA;AAE3B;AAEA,SAAS,gBAAgB,MAAyB;CAChD,MAAM,OAAO,KAAK,MAAM,CAAC;CACzB,IAAI,KAAK,OAAO,MACd,OAAO,KAAK,OAAO;CAErB,OACE,KAAK,OAAO,YACX,KAAK,UAAU,KAAK,KAAK,OAAO,UAAU,KAAK,OAAO,YACtD,KAAK,UAAU,KAAK,KAAK,OAAO,YAAY,KAAK,OAAO;AAE7D;AAEA,eAAe,eAAe,SAAuD;CAWnF,uBAAuB,MAVF,sBAAsB;EACzC,SAAS,QAAQ,IAAI;EACrB,WAAW,QAAQ;EACnB,KAAK,QAAQ;EACb,SAAS,QAAQ;EACjB,SAAS,QAAQ;EACjB,cAAc,QAAQ;EACtB,SAAS;EACT,SAAS;CACX,CAAC,GAC8B,QAAQ,SAAS,IAAI;AACtD;AAIA,MAAM,gBAAgB;CACpB,KAAK,SAAiB;EACpB,QAAQ,MAAM,UAAU,SAAS;CACnC;CACA,KAAK,SAAiB;EACpB,QAAQ,MAAM,UAAU,SAAS;CACnC;CACA,MAAM,SAAiB;EACrB,QAAQ,MAAM,WAAW,SAAS;CACpC;AACF;AAEA,MAAM,sBAAsC;CAC1C,IAAI,QAAQ;EACV,QAAQ,MAAM,qBAAqB,MAAM,CAAC;CAC5C;CACA,MAAM,MAAM,OAAO,KAAK;EACtB,OAAO,MAAM,IAAI;CACnB;AACF;AAEA,SAAS,qBAAqB,QAAkC;CAC9D,MAAM,SAAS,OAAO,QAAQ,OAAO,MAAM,CAAC,CACzC,KAAK,CAAC,KAAK,WAAW,oBAAoB,KAAK,KAAK,CAAC,CAAC,CACtD,QAAQ,UAA2B,UAAU,KAAA,CAAS;CAEzD,MAAM,YAAY,CAAC,GADJ,qBAAqB,MACT,GAAG,GAAG,MAAM,CAAC,CAAC,KAAK,GAAG;CACjD,OAAO,OAAO,SAAS,KAAA,IAAY,YAAY,GAAG,UAAU,IAAI,OAAO;AACzE;AAEA,SAAS,qBAAqB,QAAoC;CAChE,OAAO;EAAC;EAAQ,oBAAoB,IAAI,OAAO,KAAK,IAAI,KAAK,OAAO;EAAO,OAAO;CAAK,CAAC,CAAC,OACvF,OACF;AACF;AAEA,MAAM,uBAAkE;CACtE,YAAY,UAAU,IAAI;CAC1B,YAAY,UAAU,IAAI;CAC1B,aAAa,UACX,YAAY,QAAQ,MAAO,GAAG,MAAM,MAAM,IAAI,QAAQ,IAAA,CAAM,QAAQ,CAAC,EAAE;CACzE,cAAc,UAAU,UAAU,MAAM;CACxC,cAAc,UAAU,UAAU,MAAM;CACxC,cAAc,UAAU,UAAU,MAAM;AAC1C;AAEA,MAAM,sCAAsB,IAAI,IAAI,CAAC,QAAQ,QAAQ,CAAC;AAEtD,SAAS,oBAAoB,KAAa,OAAoC;CAC5E,IAAI,SAAS,MACX;CAGF,OAAO,yBAAyB,KAAK,KAAK;AAC5C;AAEA,SAAS,yBAAyB,KAAa,OAAwB;CAGrE,QADE,OAAO,UAAU,WAAW,qBAAqB,IAAI,GAAG,KAAK,IAAI,KAAA,MACzC,GAAG,IAAI,GAAG,oBAAoB,KAAK;AAC/D;AAEA,MAAM,0BAAsE;CAC1E,SAAS;CACT,QAAQ;CACR,SAAS,UACP,MAAM,QAAQ,KAAK,IACf,MAAM,WAAW,IACf,MACA,MAAM,IAAI,mBAAmB,CAAC,CAAC,KAAK,GAAG,IACzC,KAAK,UAAU,KAAK;CAC1B,SAAS,UAAU;EACjB,MAAM,OAAO,OAAO,KAAK;EACzB,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI;CAClD;AACF;AAEA,SAAS,oBAAoB,OAAwB;CACnD,QAAQ,wBAAwB,OAAO,UAAU,KAAK,UAAA,CAAW,KAAK;AACxE;AAEA,SAAS,uBAAuB,QAA2B,MAAqB;CAC9E,IAAI,MAAM;EACR,QAAQ,IAAI,KAAK,UAAU,aAAa;GAAE,QAAQ;GAAS;EAAO,CAAC,GAAG,MAAM,CAAC,CAAC;EAC9E;CACF;CACA,IAAI,OAAO,SAAS,WAAW;EAC7B,QAAQ,IAAI,YAAY,OAAO,cAAc,mBAAmB;EAChE;CACF;CACA,QAAQ,IAAI,kBAAkB,MAAM,CAAC;AACvC;AAEA,SAAS,kBAAkB,QAAgE;CACzF,MAAM,cAAc,4BAA4B,OAAO,WAAW;CAClE,MAAM,iBAAiB,OAAO,oBAAoB,KAAK,OAAO,UAAU;EACtE,MAAM,QACJ,MAAM,cAAc,MAAM,UACtB,GAAG,MAAM,KAAK,GAAG,MAAM,cACvB,GAAG,MAAM,KAAK,GAAG,MAAM,UAAU,GAAG,MAAM;EAChD,OAAO;GACL,GAAG,QAAQ,EAAE,IAAI;GACjB,UAAU,MAAM,QAAQ,WAAW;GACnC,MAAM,QAAQ;EAChB,CAAC,CAAC,KAAK,IAAI;CACb,CAAC;CACD,OAAO,eAAe,WAAW,IAC7B,cACA;EAAC,YAAY,QAAQ;EAAG;EAAI;EAAsB;EAAI,eAAe,KAAK,MAAM;CAAC,CAAC,CAAC,KAAK,IAAI;AAClG;AAEA,eAAe,UAAU,SAAoC;CAC3D,IAAI,CAAC,QAAQ,OACX,MAAM,IAAI,MAAM,iCAAiC;CAEnD,MAAM,SAAS,MAAM,iBAAiB;EACpC,SAAS,QAAQ,IAAI;EACrB,WAAW,QAAQ;EACnB,MAAM,QAAQ;EACd,KAAK,QAAQ;EACb,WAAW,QAAQ;CACrB,CAAC;CACD,oBAAoB,OAAO,QAAQ;CACnC,QAAQ,IACN,QACE;EACE,cAAc,OAAO;EACrB,OAAO,OAAO;CAChB,GACA;EAAE,OAAO;EAAG,QAAQ;CAAM,CAC5B,CACF;AACF;;;AClkBA,SAAgB,wBAAwB,SAAyB;CAC/D,IAAI,YAAY;CAChB,KAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,GAAG;EACtD,MAAM,OAAO,QAAQ,WAAW,KAAK;EACrC,IAAI,SAAS,IAAM;GACjB,QAAQ,4BAA4B,SAAS,KAAK;GAClD;EACF;EACA,IAAI,SAAS,iBAAiB;GAC5B,QAAQ,oBAAoB,SAAS,QAAQ,GAAG,cAAc;GAC9D;EACF;EACA,IAAI,2BAA2B,IAAI,IAAI,GAAG;GACxC,QAAQ,oBAAoB,SAAS,QAAQ,CAAC;GAC9C;EACF;EACA,IAAI,SAAS,iBAAiB;GAC5B,QAAQ,gBAAgB,SAAS,QAAQ,CAAC;GAC1C;EACF;EACA,IAAI,wBAAwB,IAAI,GAC9B;EAEF,aAAa,QAAQ;CACvB;CACA,OAAO;AACT;AAEA,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AACtB,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,2CAA2B,IAAI,IAAI;CAAC;CAAM;CAAM;CAAM;AAAI,CAAC;AACjE,MAAM,6CAA6B,IAAI,IAAI;CAAC;CAAM;CAAM;CAAM;AAAI,CAAC;AAEnE,SAAS,4BAA4B,SAAiB,OAAuB;CAC3E,MAAM,OAAO,QAAQ,WAAW,QAAQ,CAAC;CACzC,IAAI,OAAO,MAAM,IAAI,GACnB,OAAO;CAET,IAAI,SAAS,eACX,OAAO,oBAAoB,SAAS,QAAQ,GAAG,cAAc;CAE/D,IAAI,yBAAyB,IAAI,IAAI,GACnC,OAAO,oBAAoB,SAAS,QAAQ,CAAC;CAE/C,IAAI,SAAS,eACX,OAAO,gBAAgB,SAAS,QAAQ,CAAC;CAE3C,IAAI,qBAAqB,IAAI,GAC3B,OAAO,oCAAoC,SAAS,QAAQ,CAAC;CAE/D,IAAI,4BAA4B,IAAI,GAClC,OAAO,QAAQ;CAEjB,OAAO;AACT;AAEA,SAAS,gBAAgB,SAAiB,OAAuB;CAC/D,KAAK,IAAI,SAAS,OAAO,SAAS,QAAQ,QAAQ,UAAU,GAAG;EAC7D,MAAM,OAAO,QAAQ,WAAW,MAAM;EACtC,IAAI,QAAQ,MAAQ,QAAQ,KAC1B,OAAO;CAEX;CACA,OAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,oBAAoB,SAAiB,OAAe,YAA6B;CACxF,KAAK,IAAI,SAAS,OAAO,SAAS,QAAQ,QAAQ,UAAU,GAAG;EAC7D,MAAM,OAAO,QAAQ,WAAW,MAAM;EACtC,IAAI,SAAS,kBACX,OAAO;EAET,IAAI,eAAe,KAAA,KAAa,SAAS,YACvC,OAAO;EAET,IAAI,SAAS,MAAQ,SAAS,IAAI,QAAQ,UAAU,QAAQ,WAAW,SAAS,CAAC,MAAM,IACrF,OAAO,SAAS;CAEpB;CACA,OAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,oCAAoC,SAAiB,OAAuB;CACnF,KAAK,IAAI,SAAS,OAAO,SAAS,QAAQ,QAAQ,UAAU,GAAG;EAC7D,MAAM,OAAO,QAAQ,WAAW,MAAM;EACtC,IAAI,qBAAqB,IAAI,GAC3B;EAEF,IAAI,4BAA4B,IAAI,GAClC,OAAO;EAET,OAAO,KAAK,IAAI,SAAS,GAAG,KAAK;CACnC;CACA,OAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,qBAAqB,MAAuB;CACnD,OAAO,QAAQ,MAAQ,QAAQ;AACjC;AAEA,SAAS,4BAA4B,MAAuB;CAC1D,OAAO,QAAQ,MAAQ,QAAQ;AACjC;AAEA,SAAS,wBAAwB,MAAuB;CACtD,OAAQ,OAAO,MAAQ,SAAS,KAAQ,SAAS,MAAU,QAAQ,OAAQ,QAAQ;AACrF;;;ACpGA,MAAM,MAAM,QAAQ;AAEpB,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,UAAU,iBAAiB,OAAO,GAAG,CAAC;AAE9D,eAAe,iBAAiB,OAAgB,KAAuC;CAErF,MAAM,mBAAmB,wBADT,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACb;CACxD,IAAI,IAAI,mBAAmB,QAAQ;EACjC,QAAQ,MAAM,UAAU,kBAAkB;EAC1C,QAAQ,KAAK,CAAC;CAChB;CACA,MAAM,0BAA0B,OAAO,gBAAgB;CACvD,QAAQ,WAAW;AACrB;AAEA,eAAe,0BAA0B,OAAgB,SAAgC;CACvF,MAAM,YAAY;EAChB,MAAM,KAAK;EACX,SAAS,KAAK;EACd,WAAW,KAAK;CAClB;CACA,IAAI,iBAAiB,kBACnB,MAAM,oCAAoC,OAAO,SAAS;MAE1D,MAAM,yBAAyB,SAAS;CAE1C,KAAK,UAAU,OAAO;AACxB"}
@@ -87,7 +87,7 @@ While customizing:
87
87
 
88
88
  - Keep config load synchronous. Runtime work belongs inside `pipr.task(...)`.
89
89
  - Use `pipr.secret({ name })`; never write raw secret values.
90
- - Prefer `pipr.review(...)` until the interview requires multiple Pi calls, command input, custom schemas, plugin tools, explicit checks, or main-comment-only output.
90
+ - Prefer `pipr.review(...)` for the built-in findings-plus-summary flow. Use custom agents and tasks for custom prompts, additional Pi calls, command input, custom schemas, plugin tools, explicit checks, or main-comment-only output.
91
91
  - For custom tasks, pass `{ manifest }` to `ctx.pi.run(...)`; do not interpolate the Diff Manifest into prompts yourself.
92
92
  - Core already adds bounded change request metadata and schema-aware `suggestedFix` rules to agent prompts. Do not duplicate them in `instructions` or prompt input.
93
93
  - Emit exactly one final output from each selected task: `ctx.comment(...)` or `ctx.command.reply(...)`.
@@ -4,17 +4,17 @@ Use these patterns when customizing `.pipr/config.ts`.
4
4
 
5
5
  ## CLI commands
6
6
 
7
- | Command | Use |
8
- | --- | --- |
9
- | `pipr init` | Create `.pipr/config.ts`, `.pipr/package.json`, `.pipr/bun.lock`, `.pipr/tsconfig.json`, `.pipr/.gitignore`, and the default GitHub workflow. |
10
- | `pipr init --adapters <list>` | Generate selected adapter artifacts for `github`, `gitlab`, `azure-devops`, or `bitbucket`; use `none` to skip adapter files. |
11
- | `pipr init --minimal` | Create only `.pipr/config.ts`; editor types come from a repo-root `@usepipr/sdk` install. |
12
- | `pipr inspect` | Print models, agents, tasks, commands, tools, publication settings, checks, and limits. |
13
- | `pipr check` | Type-load config and validate the runtime plan. |
14
- | `pipr check --require-env` | Also require configured provider env vars. |
15
- | `pipr review --base <ref>` | Run change-request tasks locally without publishing comments. |
16
- | `pipr dry-run --host <host> --event <path>` | Load a native provider event and config without model calls or publication. |
17
- | `pipr webhook serve --host <host> --workspace <path> --repository <id>` | Run trusted webhook ingress for GitLab, Azure DevOps, or Bitbucket. |
7
+ | Command | Use |
8
+ | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
9
+ | `pipr init` | Create `.pipr/config.ts`, `.pipr/package.json`, `.pipr/bun.lock`, `.pipr/tsconfig.json`, `.pipr/.gitignore`, and the default GitHub workflow. |
10
+ | `pipr init --adapters <list>` | Generate selected adapter artifacts for `github`, `gitlab`, `azure-devops`, or `bitbucket`; use `none` to skip adapter files. |
11
+ | `pipr init --minimal` | Create only `.pipr/config.ts`; editor types come from a repo-root `@usepipr/sdk` install. |
12
+ | `pipr inspect` | Print models, agents, tasks, commands, tools, publication settings, checks, and limits. |
13
+ | `pipr check` | Type-load config and validate the runtime plan. |
14
+ | `pipr check --require-env` | Also require configured provider env vars. |
15
+ | `pipr review --base <ref>` | Run change-request tasks locally without publishing comments. |
16
+ | `pipr dry-run --host <host> --event <path>` | Load a native provider event and config without model calls or publication. |
17
+ | `pipr webhook serve --host <host> --workspace <path> --repository <id>` | Run trusted webhook ingress for GitLab, Azure DevOps, or Bitbucket. |
18
18
 
19
19
  ## Model and review basics
20
20
 
@@ -26,7 +26,7 @@ export default definePipr((pipr) => {
26
26
  provider: "deepseek",
27
27
  model: "deepseek-v4-pro",
28
28
  apiKey: pipr.secret({ name: "DEEPSEEK_API_KEY" }),
29
- options: { thinking: "high" },
29
+ thinking: "high",
30
30
  });
31
31
 
32
32
  pipr.config({ publication: { maxInlineComments: 5 } });
@@ -34,17 +34,20 @@ export default definePipr((pipr) => {
34
34
  pipr.review({
35
35
  id: "review",
36
36
  model,
37
- instructions: `
38
- Review the change request diff for correctness, security,
39
- maintainability, and test coverage.
40
- Return only actionable findings that target valid diff ranges.
41
- `,
37
+ instructions: {
38
+ findings: `
39
+ Review the change request diff for correctness, security,
40
+ maintainability, and test coverage. Return only actionable findings
41
+ that target valid diff ranges.
42
+ `,
43
+ summary: "Summarize changed behavior, risk, and reviewer focus.",
44
+ },
42
45
  timeout: "10m",
43
46
  });
44
47
  });
45
48
  ```
46
49
 
47
- Use `id` on a model only when two model profiles share the same provider and model with different options.
50
+ Use `id` on a model only when two profiles share the same provider and model with different API keys or thinking levels.
48
51
 
49
52
  ## Entrypoints
50
53
 
@@ -52,7 +55,10 @@ Use `id` on a model only when two model profiles share the same provider and mod
52
55
  pipr.review({
53
56
  id: "review",
54
57
  model,
55
- instructions: "Review only actionable defects.",
58
+ instructions: {
59
+ findings: "Review only actionable defects.",
60
+ summary: "Summarize changed behavior and risk.",
61
+ },
56
62
  entrypoints: {
57
63
  changeRequest: ["opened", "updated", "reopened", "ready"],
58
64
  command: { pattern: "@pipr review", permission: "write" },
@@ -86,7 +92,10 @@ Use `paths` to filter the Diff Manifest and publishable Inline Review Comments:
86
92
  pipr.review({
87
93
  id: "runtime-review",
88
94
  model,
89
- instructions: "Review runtime changes only.",
95
+ instructions: {
96
+ findings: "Review runtime changes only.",
97
+ summary: "Summarize runtime changes and risk.",
98
+ },
90
99
  paths: {
91
100
  include: ["packages/runtime/**"],
92
101
  exclude: ["**/*.test.ts"],
@@ -118,7 +127,10 @@ const task = pipr.task({
118
127
  async run(ctx) {
119
128
  const manifest = await ctx.change.diffManifest({ compressed: true });
120
129
  const result = await ctx.pi.run(security, { manifest });
121
- await ctx.comment({ main: result.summary.body, inlineFindings: result.inlineFindings });
130
+ await ctx.comment({
131
+ main: result.summary.body,
132
+ inlineFindings: result.inlineFindings,
133
+ });
122
134
  },
123
135
  });
124
136
 
@@ -145,7 +157,8 @@ pipr.config({
145
157
  autoResolve: {
146
158
  enabled: true,
147
159
  model,
148
- instructions: "Resolve only when the changed code addresses the finding directly.",
160
+ instructions:
161
+ "Resolve only when the changed code addresses the finding directly.",
149
162
  synchronize: true,
150
163
  userReplies: { enabled: true, allowedActors: "write" },
151
164
  },
@@ -163,7 +176,7 @@ Use required checks only when the user wants merge-gate behavior. Use comments f
163
176
  Use only secret names in config:
164
177
 
165
178
  ```ts
166
- apiKey: pipr.secret({ name: "DEEPSEEK_API_KEY" })
179
+ apiKey: pipr.secret({ name: "DEEPSEEK_API_KEY" });
167
180
  ```
168
181
 
169
182
  Add secret mappings in the selected code host integration. GitHub uses `.github/workflows/pipr.yml`; GitLab uses masked CI/CD variables; Azure DevOps and Bitbucket webhook runners use their trusted secret stores. Never commit raw provider keys, local `.env` values, or personal credentials.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usepipr/cli",
3
- "version": "0.4.3",
3
+ "version": "0.6.0",
4
4
  "description": "Command-line interface for Pipr code host review automation",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -17,13 +17,17 @@
17
17
  "access": "public"
18
18
  },
19
19
  "files": [
20
- "dist"
20
+ "dist",
21
+ "LICENSE"
21
22
  ],
23
+ "engines": {
24
+ "bun": ">=1.3.14"
25
+ },
22
26
  "bin": {
23
27
  "pipr": "./dist/main.mjs"
24
28
  },
25
29
  "scripts": {
26
- "build": "tsdown src/main.ts --dts --format esm --out-dir dist && bun src/release/copy-skills.ts",
30
+ "build": "tsdown src/main.ts --dts --format esm --out-dir dist --tsconfig tsconfig.build.json && bun src/release/copy-skills.ts",
27
31
  "typecheck": "tsc --noEmit",
28
32
  "test": "bun test --timeout 30000",
29
33
  "lint": "biome lint src",
@@ -33,8 +37,8 @@
33
37
  },
34
38
  "dependencies": {
35
39
  "@actions/core": "3.0.1",
36
- "@usepipr/runtime": "0.4.3",
37
- "@usepipr/sdk": "0.4.3",
40
+ "@usepipr/runtime": "0.6.0",
41
+ "@usepipr/sdk": "0.6.0",
38
42
  "commander": "15.0.0"
39
43
  }
40
44
  }