@methiu/raigal 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/astro.js +1 -1
- package/dist/adapters/expo.js +1 -1
- package/dist/adapters/nuxt.js +1 -1
- package/dist/adapters/sveltekit.js +1 -1
- package/dist/adapters/vite.js +1 -1
- package/dist/cli.js +574 -368
- package/dist/{core-o3KNKhg2.js → core-kJtASBYe.js} +12 -2
- package/dist/index.js +39 -10
- package/dist/{json-Be-AUuDb.js → json-BpPaIvrn.js} +1 -1
- package/dist/{json-DBN8fnd3.js → json-C9fBWj3V.js} +1 -1
- package/dist/mcp.js +24 -7
- package/dist/report-pr-closed-CDdQjRWj.js +44 -0
- package/dist/{sarif-B-l1Fhzd.js → sarif--DI_2p2r.js} +1 -1
- package/dist/{sarif-C9k9QYGi.js → sarif-CuuawcSp.js} +1 -1
- package/dist/{version-om7oAIVO.js → version-gBpAhuDc.js} +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -108,7 +108,28 @@ const getProviderStatuses = () => PROVIDERS.map((provider) => {
|
|
|
108
108
|
};
|
|
109
109
|
});
|
|
110
110
|
const resolveProvider = (selection, statuses = getProviderStatuses()) => {
|
|
111
|
-
if (selection !== "auto")
|
|
111
|
+
if (selection !== "auto") {
|
|
112
|
+
const found = statuses.find((status) => status.provider.id === selection);
|
|
113
|
+
if (found) return found;
|
|
114
|
+
if (commandExists(selection)) return {
|
|
115
|
+
provider: {
|
|
116
|
+
id: selection,
|
|
117
|
+
label: selection,
|
|
118
|
+
bin: selection,
|
|
119
|
+
loginCommand: {
|
|
120
|
+
command: selection,
|
|
121
|
+
args: ["login"]
|
|
122
|
+
},
|
|
123
|
+
loginHint: `Run \`${selection} login\`.`,
|
|
124
|
+
buildArgs: (prompt) => [prompt]
|
|
125
|
+
},
|
|
126
|
+
installed: true,
|
|
127
|
+
authenticated: true,
|
|
128
|
+
version: readVersion(selection),
|
|
129
|
+
authHint: null
|
|
130
|
+
};
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
112
133
|
return statuses.find((status) => status.installed && status.authenticated !== false) ?? statuses.find((status) => status.installed) ?? null;
|
|
113
134
|
};
|
|
114
135
|
//#endregion
|
|
@@ -863,7 +884,7 @@ const createLogger = (deps = {}) => {
|
|
|
863
884
|
const log = createLogger();
|
|
864
885
|
//#endregion
|
|
865
886
|
//#region src/version.ts
|
|
866
|
-
const APP_VERSION = "1.0.
|
|
887
|
+
const APP_VERSION = "1.0.3";
|
|
867
888
|
//#endregion
|
|
868
889
|
//#region src/commands/agent-connect.ts
|
|
869
890
|
const commandText = (status) => [status.provider.loginCommand.command, ...status.provider.loginCommand.args].join(" ");
|
|
@@ -1058,7 +1079,8 @@ const Finding = z.object({
|
|
|
1058
1079
|
severity: Severity,
|
|
1059
1080
|
path: z.string().max(500),
|
|
1060
1081
|
line: z.number().int().nonnegative(),
|
|
1061
|
-
fingerprint: z.string().length(32)
|
|
1082
|
+
fingerprint: z.string().length(32),
|
|
1083
|
+
message: z.string().max(500).optional()
|
|
1062
1084
|
});
|
|
1063
1085
|
const RepoRef = z.object({
|
|
1064
1086
|
provider: z.literal("github"),
|
|
@@ -1073,12 +1095,21 @@ const Step = z.object({
|
|
|
1073
1095
|
ms: z.number().int().nonnegative(),
|
|
1074
1096
|
counts: z.record(z.string(), z.number()).optional()
|
|
1075
1097
|
});
|
|
1098
|
+
const AgentTelemetry = z.object({
|
|
1099
|
+
provider: z.string().max(80),
|
|
1100
|
+
before_score: z.number().min(0).max(100).nullable(),
|
|
1101
|
+
after_score: z.number().min(0).max(100).nullable(),
|
|
1102
|
+
pr_url: z.string().url().max(500).optional(),
|
|
1103
|
+
patch_diff: z.string().max(2e4).optional(),
|
|
1104
|
+
duration_ms: z.number().int().nonnegative().optional()
|
|
1105
|
+
});
|
|
1076
1106
|
const Report = z.object({
|
|
1077
1107
|
score: z.number().min(0).max(100).nullable(),
|
|
1078
1108
|
scoreable: z.boolean(),
|
|
1079
1109
|
engine_scores: z.record(z.string(), z.number()).optional(),
|
|
1080
1110
|
files_scanned: z.number().int().nonnegative(),
|
|
1081
|
-
findings: z.array(Finding).max(5e3)
|
|
1111
|
+
findings: z.array(Finding).max(5e3),
|
|
1112
|
+
agent_telemetry: AgentTelemetry.optional()
|
|
1082
1113
|
});
|
|
1083
1114
|
const Run = z.object({
|
|
1084
1115
|
run_id: z.uuid(),
|
|
@@ -1095,7 +1126,13 @@ const Run = z.object({
|
|
|
1095
1126
|
branch: z.string().max(200).optional(),
|
|
1096
1127
|
head_sha: z.string().max(64).optional(),
|
|
1097
1128
|
base_ref: z.string().max(200).optional(),
|
|
1098
|
-
pr_number: z.number().int().optional()
|
|
1129
|
+
pr_number: z.number().int().optional(),
|
|
1130
|
+
diff_summary: z.object({
|
|
1131
|
+
files_changed: z.number().int().nonnegative(),
|
|
1132
|
+
additions: z.number().int().nonnegative(),
|
|
1133
|
+
deletions: z.number().int().nonnegative()
|
|
1134
|
+
}).optional(),
|
|
1135
|
+
diff_preview: z.string().max(1e4).optional()
|
|
1099
1136
|
}),
|
|
1100
1137
|
ci: z.object({
|
|
1101
1138
|
provider: z.string().max(40),
|
|
@@ -1111,7 +1148,8 @@ const Run = z.object({
|
|
|
1111
1148
|
ended_at: z.iso.datetime(),
|
|
1112
1149
|
exit_code: z.number().int(),
|
|
1113
1150
|
steps: z.array(Step).max(200),
|
|
1114
|
-
report: Report.optional()
|
|
1151
|
+
report: Report.optional(),
|
|
1152
|
+
agent_telemetry: AgentTelemetry.optional()
|
|
1115
1153
|
});
|
|
1116
1154
|
const Policy = z.object({
|
|
1117
1155
|
version: z.number().int(),
|
|
@@ -1345,7 +1383,7 @@ const verifyEntitlementJwt = (jwt, options = {}) => {
|
|
|
1345
1383
|
const claims = parsed.data;
|
|
1346
1384
|
const expectedIssuer = process.env.RAIGAL_ISSUER?.trim() || "https://app.raigal.dev";
|
|
1347
1385
|
if (claims.iss !== expectedIssuer) throw new JwtVerificationError(`Untrusted issuer: ${claims.iss}`, "invalid_issuer");
|
|
1348
|
-
if (!isVersionAtLeast("1.0.
|
|
1386
|
+
if (!isVersionAtLeast("1.0.3", claims.min_cli_version)) throw new JwtVerificationError(`CLI version ${APP_VERSION} is below required minimum ${claims.min_cli_version}. Run "raigal update" or "npm install -g @methiu/raigal@latest".`, "cli_version_unsupported");
|
|
1349
1387
|
const now = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
1350
1388
|
const grace = options.allowGraceSeconds ?? 0;
|
|
1351
1389
|
if (now > claims.exp + grace) {
|
|
@@ -1512,7 +1550,7 @@ const getEntitlement = async () => {
|
|
|
1512
1550
|
};
|
|
1513
1551
|
//#endregion
|
|
1514
1552
|
//#region src/cloud/owner.ts
|
|
1515
|
-
const GITHUB_REMOTE_RE$1 = /^(?:git@github\.com
|
|
1553
|
+
const GITHUB_REMOTE_RE$1 = /^(?:(?:git@|ssh:\/\/(?:git@)?)github\.com(?::(?:\d+\/)?|[:/])|https:\/\/(?:[^@]+@)?github\.com\/)([^/]+)\/([^/.\s]+?)(?:\.git)?\s*$/;
|
|
1516
1554
|
const parseGitRemote = (rawUrl) => {
|
|
1517
1555
|
if (!rawUrl) return {
|
|
1518
1556
|
owner: null,
|
|
@@ -2575,6 +2613,392 @@ var AgentTui = class {
|
|
|
2575
2613
|
}
|
|
2576
2614
|
};
|
|
2577
2615
|
//#endregion
|
|
2616
|
+
//#region src/cloud/context.ts
|
|
2617
|
+
const execGit = (args, cwd) => {
|
|
2618
|
+
try {
|
|
2619
|
+
const res = spawnSync("git", args, {
|
|
2620
|
+
cwd: path.resolve(cwd),
|
|
2621
|
+
encoding: "utf-8",
|
|
2622
|
+
stdio: [
|
|
2623
|
+
"ignore",
|
|
2624
|
+
"pipe",
|
|
2625
|
+
"ignore"
|
|
2626
|
+
]
|
|
2627
|
+
});
|
|
2628
|
+
if (res.error || res.status !== 0) return void 0;
|
|
2629
|
+
return res.stdout.trim() || void 0;
|
|
2630
|
+
} catch {
|
|
2631
|
+
return;
|
|
2632
|
+
}
|
|
2633
|
+
};
|
|
2634
|
+
const detectDefaultBranch = (directory) => {
|
|
2635
|
+
try {
|
|
2636
|
+
const out = execGit(["symbolic-ref", "refs/remotes/origin/HEAD"], directory);
|
|
2637
|
+
if (out && out.startsWith("refs/remotes/origin/")) return out.replace("refs/remotes/origin/", "").trim();
|
|
2638
|
+
} catch {}
|
|
2639
|
+
return "main";
|
|
2640
|
+
};
|
|
2641
|
+
const detectGitDiff = (directory, baseRef) => {
|
|
2642
|
+
const targetBase = baseRef || detectDefaultBranch(directory);
|
|
2643
|
+
try {
|
|
2644
|
+
let shortstat = execGit([
|
|
2645
|
+
"diff",
|
|
2646
|
+
"--shortstat",
|
|
2647
|
+
`${targetBase}...HEAD`
|
|
2648
|
+
], directory);
|
|
2649
|
+
if (!shortstat) shortstat = execGit([
|
|
2650
|
+
"diff",
|
|
2651
|
+
"--shortstat",
|
|
2652
|
+
`origin/${targetBase}...HEAD`
|
|
2653
|
+
], directory);
|
|
2654
|
+
if (!shortstat) shortstat = execGit([
|
|
2655
|
+
"diff",
|
|
2656
|
+
"--shortstat",
|
|
2657
|
+
"HEAD~1"
|
|
2658
|
+
], directory);
|
|
2659
|
+
let diffSummary;
|
|
2660
|
+
if (shortstat) {
|
|
2661
|
+
const filesMatch = shortstat.match(/(\d+)\s+files?\s+changed/);
|
|
2662
|
+
const addMatch = shortstat.match(/(\d+)\s+insertions?\s*\(\+\)/);
|
|
2663
|
+
const delMatch = shortstat.match(/(\d+)\s+deletions?\s*\(-\)/);
|
|
2664
|
+
diffSummary = {
|
|
2665
|
+
files_changed: filesMatch ? Number.parseInt(filesMatch[1], 10) : 1,
|
|
2666
|
+
additions: addMatch ? Number.parseInt(addMatch[1], 10) : 0,
|
|
2667
|
+
deletions: delMatch ? Number.parseInt(delMatch[1], 10) : 0
|
|
2668
|
+
};
|
|
2669
|
+
}
|
|
2670
|
+
let preview = execGit([
|
|
2671
|
+
"diff",
|
|
2672
|
+
"-U2",
|
|
2673
|
+
"--no-color",
|
|
2674
|
+
`${targetBase}...HEAD`
|
|
2675
|
+
], directory);
|
|
2676
|
+
if (!preview) preview = execGit([
|
|
2677
|
+
"diff",
|
|
2678
|
+
"-U2",
|
|
2679
|
+
"--no-color",
|
|
2680
|
+
`origin/${targetBase}...HEAD`
|
|
2681
|
+
], directory);
|
|
2682
|
+
if (!preview) preview = execGit([
|
|
2683
|
+
"diff",
|
|
2684
|
+
"-U2",
|
|
2685
|
+
"--no-color",
|
|
2686
|
+
"HEAD~1"
|
|
2687
|
+
], directory);
|
|
2688
|
+
let diffPreview;
|
|
2689
|
+
if (preview) diffPreview = preview.split("\n").slice(0, 40).join("\n").slice(0, 1e4);
|
|
2690
|
+
return {
|
|
2691
|
+
diffSummary,
|
|
2692
|
+
diffPreview
|
|
2693
|
+
};
|
|
2694
|
+
} catch {
|
|
2695
|
+
return {};
|
|
2696
|
+
}
|
|
2697
|
+
};
|
|
2698
|
+
const getRootCommitHash = (directory) => {
|
|
2699
|
+
const hash = execGit([
|
|
2700
|
+
"rev-list",
|
|
2701
|
+
"--max-parents=0",
|
|
2702
|
+
"HEAD"
|
|
2703
|
+
], directory);
|
|
2704
|
+
if (!hash) return void 0;
|
|
2705
|
+
const firstLine = hash.split("\n")[0]?.trim();
|
|
2706
|
+
return firstLine && /^[0-9a-f]{40,64}$/i.test(firstLine) ? firstLine : void 0;
|
|
2707
|
+
};
|
|
2708
|
+
const detectRepoRef = (directory, ownerId) => {
|
|
2709
|
+
const detected = detectLocalRepoOwner(directory);
|
|
2710
|
+
if (!detected.owner || !detected.repo) return null;
|
|
2711
|
+
return {
|
|
2712
|
+
provider: "github",
|
|
2713
|
+
slug: `${detected.owner}/${detected.repo}`.toLowerCase(),
|
|
2714
|
+
owner_id: ownerId,
|
|
2715
|
+
root_commit_hash: getRootCommitHash(directory)
|
|
2716
|
+
};
|
|
2717
|
+
};
|
|
2718
|
+
const readGitHubEventPayload = () => {
|
|
2719
|
+
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
2720
|
+
if (!eventPath || !fs.existsSync(eventPath)) return null;
|
|
2721
|
+
try {
|
|
2722
|
+
const content = fs.readFileSync(eventPath, "utf-8");
|
|
2723
|
+
return JSON.parse(content);
|
|
2724
|
+
} catch {
|
|
2725
|
+
return null;
|
|
2726
|
+
}
|
|
2727
|
+
};
|
|
2728
|
+
const detectGitContext = (directory) => {
|
|
2729
|
+
const eventPayload = readGitHubEventPayload();
|
|
2730
|
+
const pr = eventPayload?.pull_request;
|
|
2731
|
+
let headSha = pr?.head?.sha;
|
|
2732
|
+
if (!headSha) headSha = process.env.GITHUB_SHA || execGit(["rev-parse", "HEAD"], directory);
|
|
2733
|
+
let branch = process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME;
|
|
2734
|
+
if (!branch) {
|
|
2735
|
+
branch = execGit([
|
|
2736
|
+
"rev-parse",
|
|
2737
|
+
"--abbrev-ref",
|
|
2738
|
+
"HEAD"
|
|
2739
|
+
], directory);
|
|
2740
|
+
if (branch === "HEAD") branch = void 0;
|
|
2741
|
+
}
|
|
2742
|
+
let baseRef = pr?.base?.ref || process.env.GITHUB_BASE_REF;
|
|
2743
|
+
if (!baseRef) baseRef = void 0;
|
|
2744
|
+
let prNumber;
|
|
2745
|
+
if (typeof pr?.number === "number") prNumber = pr.number;
|
|
2746
|
+
else if (typeof eventPayload?.number === "number") prNumber = eventPayload.number;
|
|
2747
|
+
else if (process.env.RAIGAL_PR_NUMBER || process.env.PR_NUMBER) {
|
|
2748
|
+
const parsed = Number.parseInt(process.env.RAIGAL_PR_NUMBER || process.env.PR_NUMBER || "", 10);
|
|
2749
|
+
if (!Number.isNaN(parsed) && parsed > 0) prNumber = parsed;
|
|
2750
|
+
} else if (process.env.GITHUB_REF) {
|
|
2751
|
+
const match = process.env.GITHUB_REF.match(/refs\/pull\/(\d+)(?:\/|$)/);
|
|
2752
|
+
if (match && match[1]) prNumber = Number.parseInt(match[1], 10);
|
|
2753
|
+
}
|
|
2754
|
+
if (!prNumber && branch) {
|
|
2755
|
+
const match = branch.match(/pull\/(\d+)/i) || branch.match(/^pr-(\d+)/i);
|
|
2756
|
+
if (match && match[1]) prNumber = Number.parseInt(match[1], 10);
|
|
2757
|
+
}
|
|
2758
|
+
const result = {};
|
|
2759
|
+
if (branch) result.branch = branch;
|
|
2760
|
+
if (headSha) result.head_sha = headSha;
|
|
2761
|
+
if (baseRef) result.base_ref = baseRef;
|
|
2762
|
+
if (prNumber !== void 0 && !Number.isNaN(prNumber)) result.pr_number = prNumber;
|
|
2763
|
+
const { diffSummary, diffPreview } = detectGitDiff(directory, baseRef);
|
|
2764
|
+
if (diffSummary) result.diff_summary = diffSummary;
|
|
2765
|
+
if (diffPreview) result.diff_preview = diffPreview;
|
|
2766
|
+
return result;
|
|
2767
|
+
};
|
|
2768
|
+
const detectCiContext = () => {
|
|
2769
|
+
if (process.env.GITHUB_ACTIONS === "true" || process.env.GITHUB_ACTIONS === "1") {
|
|
2770
|
+
const serverUrl = process.env.GITHUB_SERVER_URL || "https://github.com";
|
|
2771
|
+
const repo = process.env.GITHUB_REPOSITORY;
|
|
2772
|
+
const runId = process.env.GITHUB_RUN_ID;
|
|
2773
|
+
let runUrl;
|
|
2774
|
+
if (repo && runId) {
|
|
2775
|
+
const attempt = process.env.GITHUB_RUN_ATTEMPT;
|
|
2776
|
+
runUrl = `${serverUrl}/${repo}/actions/runs/${runId}${attempt ? `/attempts/${attempt}` : ""}`;
|
|
2777
|
+
}
|
|
2778
|
+
return {
|
|
2779
|
+
provider: "github-actions",
|
|
2780
|
+
...runUrl ? { run_url: runUrl } : {}
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
if (process.env.CI === "true" || process.env.CI === "1") return { provider: process.env.GITLAB_CI && "gitlab-ci" || process.env.BITBUCKET_BUILD_NUMBER && "bitbucket-pipelines" || process.env.CIRCLECI && "circleci" || process.env.BUILDKITE && "buildkite" || process.env.TRAVIS && "travis-ci" || "generic-ci" };
|
|
2784
|
+
};
|
|
2785
|
+
//#endregion
|
|
2786
|
+
//#region src/cloud/outbox.ts
|
|
2787
|
+
const MAX_OUTBOX_BYTES = 5 * 1024 * 1024;
|
|
2788
|
+
const getMaxOutboxBytes = () => {
|
|
2789
|
+
const override = process.env.RAIGAL_MAX_OUTBOX_BYTES;
|
|
2790
|
+
if (override) {
|
|
2791
|
+
const parsed = Number.parseInt(override, 10);
|
|
2792
|
+
if (!Number.isNaN(parsed) && parsed > 0) return parsed;
|
|
2793
|
+
}
|
|
2794
|
+
return MAX_OUTBOX_BYTES;
|
|
2795
|
+
};
|
|
2796
|
+
const loadOutboxRuns = () => {
|
|
2797
|
+
const outboxPath = getOutboxPath();
|
|
2798
|
+
if (!fs.existsSync(outboxPath)) return [];
|
|
2799
|
+
try {
|
|
2800
|
+
const lines = fs.readFileSync(outboxPath, "utf-8").split("\n").filter((l) => l.trim().length > 0);
|
|
2801
|
+
const runs = [];
|
|
2802
|
+
for (const line of lines) try {
|
|
2803
|
+
const parsed = JSON.parse(line);
|
|
2804
|
+
const valid = Run.safeParse(parsed);
|
|
2805
|
+
if (valid.success) runs.push(valid.data);
|
|
2806
|
+
} catch {}
|
|
2807
|
+
return runs;
|
|
2808
|
+
} catch {
|
|
2809
|
+
return [];
|
|
2810
|
+
}
|
|
2811
|
+
};
|
|
2812
|
+
const writeRunsToOutbox = (runs) => {
|
|
2813
|
+
const outboxPath = getOutboxPath();
|
|
2814
|
+
const dir = path.dirname(outboxPath);
|
|
2815
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, {
|
|
2816
|
+
recursive: true,
|
|
2817
|
+
mode: 448
|
|
2818
|
+
});
|
|
2819
|
+
let lines = runs.map((r) => JSON.stringify(r));
|
|
2820
|
+
let text = lines.length > 0 ? `${lines.join("\n")}\n` : "";
|
|
2821
|
+
const maxBytes = getMaxOutboxBytes();
|
|
2822
|
+
while (Buffer.byteLength(text, "utf-8") > maxBytes && lines.length > 1) {
|
|
2823
|
+
lines.shift();
|
|
2824
|
+
text = `${lines.join("\n")}\n`;
|
|
2825
|
+
}
|
|
2826
|
+
const temp = `${outboxPath}.${Date.now()}.tmp`;
|
|
2827
|
+
fs.writeFileSync(temp, text, { mode: 384 });
|
|
2828
|
+
try {
|
|
2829
|
+
fs.renameSync(temp, outboxPath);
|
|
2830
|
+
} catch {
|
|
2831
|
+
fs.rmSync(temp, { force: true });
|
|
2832
|
+
fs.writeFileSync(outboxPath, text, { mode: 384 });
|
|
2833
|
+
}
|
|
2834
|
+
};
|
|
2835
|
+
const enqueueRun = (run) => {
|
|
2836
|
+
const existing = loadOutboxRuns();
|
|
2837
|
+
existing.push(run);
|
|
2838
|
+
writeRunsToOutbox(existing);
|
|
2839
|
+
};
|
|
2840
|
+
const getLastRecordedRun = () => {
|
|
2841
|
+
const runs = loadOutboxRuns();
|
|
2842
|
+
return runs.length > 0 ? runs[runs.length - 1] ?? null : null;
|
|
2843
|
+
};
|
|
2844
|
+
const flushOutbox = async (token) => {
|
|
2845
|
+
const runs = loadOutboxRuns();
|
|
2846
|
+
if (runs.length === 0) return {
|
|
2847
|
+
sent: 0,
|
|
2848
|
+
failed: 0,
|
|
2849
|
+
remaining: 0
|
|
2850
|
+
};
|
|
2851
|
+
let sentCount = 0;
|
|
2852
|
+
let failCount = 0;
|
|
2853
|
+
const remainingRuns = [];
|
|
2854
|
+
for (let i = 0; i < runs.length; i++) {
|
|
2855
|
+
const run = runs[i];
|
|
2856
|
+
try {
|
|
2857
|
+
await requestApi("/v1/runs", {
|
|
2858
|
+
method: "POST",
|
|
2859
|
+
token,
|
|
2860
|
+
body: run,
|
|
2861
|
+
timeoutMs: 4e3
|
|
2862
|
+
});
|
|
2863
|
+
sentCount++;
|
|
2864
|
+
} catch (err) {
|
|
2865
|
+
if (err instanceof ApiError) {
|
|
2866
|
+
if ([
|
|
2867
|
+
400,
|
|
2868
|
+
401,
|
|
2869
|
+
403,
|
|
2870
|
+
413,
|
|
2871
|
+
422
|
|
2872
|
+
].includes(err.status)) {
|
|
2873
|
+
failCount++;
|
|
2874
|
+
continue;
|
|
2875
|
+
}
|
|
2876
|
+
if (err.status === 409) {
|
|
2877
|
+
sentCount++;
|
|
2878
|
+
continue;
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
failCount++;
|
|
2882
|
+
remainingRuns.push(...runs.slice(i));
|
|
2883
|
+
break;
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
writeRunsToOutbox(remainingRuns);
|
|
2887
|
+
return {
|
|
2888
|
+
sent: sentCount,
|
|
2889
|
+
failed: failCount,
|
|
2890
|
+
remaining: remainingRuns.length
|
|
2891
|
+
};
|
|
2892
|
+
};
|
|
2893
|
+
//#endregion
|
|
2894
|
+
//#region src/cloud/recorder.ts
|
|
2895
|
+
var CloudRunRecorder = class {
|
|
2896
|
+
runId;
|
|
2897
|
+
command;
|
|
2898
|
+
directory;
|
|
2899
|
+
flags;
|
|
2900
|
+
startedAt;
|
|
2901
|
+
steps = [];
|
|
2902
|
+
report;
|
|
2903
|
+
policyMeta;
|
|
2904
|
+
gitContextOverride;
|
|
2905
|
+
agentTelemetry;
|
|
2906
|
+
seq = 0;
|
|
2907
|
+
finished = false;
|
|
2908
|
+
constructor(command, directory, flags = []) {
|
|
2909
|
+
this.runId = randomUUID();
|
|
2910
|
+
this.command = command;
|
|
2911
|
+
this.directory = directory;
|
|
2912
|
+
this.flags = flags.map((f) => f.replace(/^--?/, "")).filter((f) => f.length > 0).slice(0, 40);
|
|
2913
|
+
this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2914
|
+
}
|
|
2915
|
+
recordStep(name, durationMs, ok = true, counts) {
|
|
2916
|
+
if (this.steps.length >= 200) return;
|
|
2917
|
+
this.steps.push({
|
|
2918
|
+
seq: this.seq++,
|
|
2919
|
+
name: name.slice(0, 80),
|
|
2920
|
+
ok,
|
|
2921
|
+
ms: Math.max(0, Math.round(durationMs)),
|
|
2922
|
+
counts
|
|
2923
|
+
});
|
|
2924
|
+
}
|
|
2925
|
+
setReport(report) {
|
|
2926
|
+
this.report = report;
|
|
2927
|
+
}
|
|
2928
|
+
setPolicyMeta(version, hash) {
|
|
2929
|
+
this.policyMeta = {
|
|
2930
|
+
version,
|
|
2931
|
+
hash: hash.slice(0, 64)
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
setAgentTelemetry(telemetry) {
|
|
2935
|
+
this.agentTelemetry = telemetry;
|
|
2936
|
+
}
|
|
2937
|
+
setGitContext(git) {
|
|
2938
|
+
this.gitContextOverride = {
|
|
2939
|
+
...this.gitContextOverride,
|
|
2940
|
+
...git
|
|
2941
|
+
};
|
|
2942
|
+
}
|
|
2943
|
+
buildRunPayload(exitCode) {
|
|
2944
|
+
const repo = detectRepoRef(this.directory) || {
|
|
2945
|
+
provider: "github",
|
|
2946
|
+
slug: "unknown/unknown"
|
|
2947
|
+
};
|
|
2948
|
+
const git = {
|
|
2949
|
+
...detectGitContext(this.directory),
|
|
2950
|
+
...this.gitContextOverride
|
|
2951
|
+
};
|
|
2952
|
+
const ci = detectCiContext();
|
|
2953
|
+
const ownerVerified = Boolean(process.env.ACTIONS_ID_TOKEN_REQUEST_URL);
|
|
2954
|
+
return {
|
|
2955
|
+
run_id: this.runId,
|
|
2956
|
+
command: this.command,
|
|
2957
|
+
repo,
|
|
2958
|
+
owner_verified: ownerVerified,
|
|
2959
|
+
git,
|
|
2960
|
+
ci,
|
|
2961
|
+
flags: this.flags,
|
|
2962
|
+
cli_version: APP_VERSION,
|
|
2963
|
+
policy: this.policyMeta,
|
|
2964
|
+
started_at: this.startedAt,
|
|
2965
|
+
ended_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2966
|
+
exit_code: exitCode,
|
|
2967
|
+
steps: this.steps.slice(0, 200),
|
|
2968
|
+
report: this.report ? {
|
|
2969
|
+
...this.report,
|
|
2970
|
+
agent_telemetry: this.agentTelemetry || this.report.agent_telemetry
|
|
2971
|
+
} : void 0,
|
|
2972
|
+
agent_telemetry: this.agentTelemetry
|
|
2973
|
+
};
|
|
2974
|
+
}
|
|
2975
|
+
async finish(exitCode) {
|
|
2976
|
+
if (this.finished) return;
|
|
2977
|
+
this.finished = true;
|
|
2978
|
+
try {
|
|
2979
|
+
enqueueRun(this.buildRunPayload(exitCode));
|
|
2980
|
+
const activeToken = getActiveToken();
|
|
2981
|
+
if (activeToken) await flushOutbox(activeToken.token);
|
|
2982
|
+
} catch {}
|
|
2983
|
+
}
|
|
2984
|
+
};
|
|
2985
|
+
let activeRecorder = null;
|
|
2986
|
+
const getActiveRecorder = () => activeRecorder;
|
|
2987
|
+
const startRunRecorder = (command, directory, flags = []) => {
|
|
2988
|
+
const recorder = new CloudRunRecorder(command, directory, flags);
|
|
2989
|
+
activeRecorder = recorder;
|
|
2990
|
+
const activeToken = getActiveToken();
|
|
2991
|
+
if (activeToken) flushOutbox(activeToken.token).catch(() => {});
|
|
2992
|
+
return recorder;
|
|
2993
|
+
};
|
|
2994
|
+
const finishActiveRecorder = async (exitCode = 0) => {
|
|
2995
|
+
if (activeRecorder) {
|
|
2996
|
+
const rec = activeRecorder;
|
|
2997
|
+
activeRecorder = null;
|
|
2998
|
+
await rec.finish(exitCode);
|
|
2999
|
+
}
|
|
3000
|
+
};
|
|
3001
|
+
//#endregion
|
|
2578
3002
|
//#region src/commands/agent-local-cli.ts
|
|
2579
3003
|
const cliPath$1 = () => {
|
|
2580
3004
|
const arg = process.argv[1];
|
|
@@ -3466,6 +3890,47 @@ const runAgentSession = async (selected, resolvedDir, options, started) => {
|
|
|
3466
3890
|
published: Boolean(published)
|
|
3467
3891
|
});
|
|
3468
3892
|
await tui.finish({ footer: `Done · ${selected.provider.id} · ${Math.round(performance.now() - started)}ms` });
|
|
3893
|
+
const recorder = getActiveRecorder();
|
|
3894
|
+
if (recorder) {
|
|
3895
|
+
let patchDiff;
|
|
3896
|
+
if (created?.worktree?.path) try {
|
|
3897
|
+
patchDiff = (spawnSync("git", [
|
|
3898
|
+
"diff",
|
|
3899
|
+
"-U2",
|
|
3900
|
+
"--no-color",
|
|
3901
|
+
"HEAD"
|
|
3902
|
+
], {
|
|
3903
|
+
cwd: created.worktree.path,
|
|
3904
|
+
encoding: "utf-8"
|
|
3905
|
+
}).stdout || "").slice(0, 2e4) || void 0;
|
|
3906
|
+
} catch {}
|
|
3907
|
+
if (published) {
|
|
3908
|
+
const prMatch = published.prUrl?.match(/\/pull\/(\d+)/);
|
|
3909
|
+
const prNumber = prMatch ? Number.parseInt(prMatch[1], 10) : void 0;
|
|
3910
|
+
recorder.setGitContext({
|
|
3911
|
+
branch: published.branch,
|
|
3912
|
+
pr_number: prNumber
|
|
3913
|
+
});
|
|
3914
|
+
} else if (options.branch) recorder.setGitContext({ branch: options.branch });
|
|
3915
|
+
const agentTelemetry = {
|
|
3916
|
+
provider: selected.provider.id,
|
|
3917
|
+
before_score: before.score,
|
|
3918
|
+
after_score: verified.after.score,
|
|
3919
|
+
pr_url: published?.prUrl || void 0,
|
|
3920
|
+
patch_diff: patchDiff,
|
|
3921
|
+
duration_ms: Math.round(performance.now() - started)
|
|
3922
|
+
};
|
|
3923
|
+
recorder.setAgentTelemetry(agentTelemetry);
|
|
3924
|
+
recorder.recordStep("agent:baseline", 50, true);
|
|
3925
|
+
recorder.recordStep("agent:verify", Math.round(performance.now() - started), verified.after.score !== null && verified.after.score >= options.targetScore);
|
|
3926
|
+
recorder.setReport({
|
|
3927
|
+
score: verified.after.score,
|
|
3928
|
+
scoreable: true,
|
|
3929
|
+
files_scanned: changedFiles.length,
|
|
3930
|
+
findings: [],
|
|
3931
|
+
agent_telemetry: agentTelemetry
|
|
3932
|
+
});
|
|
3933
|
+
}
|
|
3469
3934
|
printAgentSessionSummary({
|
|
3470
3935
|
before,
|
|
3471
3936
|
after: verified.after,
|
|
@@ -7181,172 +7646,64 @@ const pollDeviceAuthorization = async (grant) => {
|
|
|
7181
7646
|
}
|
|
7182
7647
|
if (pollResult.status === "denied") {
|
|
7183
7648
|
log.error(`Login authorization denied: ${pollResult.error ?? "User rejected request."}`);
|
|
7184
|
-
process.exitCode = 1;
|
|
7185
|
-
return;
|
|
7186
|
-
}
|
|
7187
|
-
if (pollResult.status === "expired") {
|
|
7188
|
-
log.error("Login authorization code expired. Please try running `raigal login` again.");
|
|
7189
|
-
process.exitCode = 1;
|
|
7190
|
-
return;
|
|
7191
|
-
}
|
|
7192
|
-
if (pollResult.status === "ok" && pollResult.data) {
|
|
7193
|
-
const { access_token, org, user, expires_at } = pollResult.data;
|
|
7194
|
-
saveStoredCredentials({
|
|
7195
|
-
token: access_token,
|
|
7196
|
-
org,
|
|
7197
|
-
user,
|
|
7198
|
-
expires_at
|
|
7199
|
-
});
|
|
7200
|
-
process.stdout.write("\n");
|
|
7201
|
-
log.success(`Signed in as ${user.email} · ${org.name}`);
|
|
7202
|
-
return;
|
|
7203
|
-
}
|
|
7204
|
-
} catch (err) {
|
|
7205
|
-
log.error(`Polling error: ${err instanceof Error ? err.message : String(err)}`);
|
|
7206
|
-
process.exitCode = 1;
|
|
7207
|
-
return;
|
|
7208
|
-
}
|
|
7209
|
-
}
|
|
7210
|
-
log.error("Login timed out. Please run `raigal login` again.");
|
|
7211
|
-
process.exitCode = 1;
|
|
7212
|
-
};
|
|
7213
|
-
const loginCommand = async (options = {}) => {
|
|
7214
|
-
if (options.withToken) {
|
|
7215
|
-
await loginWithToken();
|
|
7216
|
-
return;
|
|
7217
|
-
}
|
|
7218
|
-
log.info("Starting browser login...");
|
|
7219
|
-
let grant;
|
|
7220
|
-
try {
|
|
7221
|
-
grant = await startDeviceLogin();
|
|
7222
|
-
} catch (err) {
|
|
7223
|
-
log.error(`Failed to start login: ${err instanceof Error ? err.message : String(err)}`);
|
|
7224
|
-
process.exitCode = 1;
|
|
7225
|
-
return;
|
|
7226
|
-
}
|
|
7227
|
-
process.stdout.write("\n");
|
|
7228
|
-
process.stdout.write(` Confirmation code: ${grant.user_code}\n`);
|
|
7229
|
-
process.stdout.write(` Verification URL: ${grant.verification_uri_complete}\n\n`);
|
|
7230
|
-
log.muted("Opening browser to confirm authorization...");
|
|
7231
|
-
openBrowser(grant.verification_uri_complete);
|
|
7232
|
-
await pollDeviceAuthorization(grant);
|
|
7233
|
-
};
|
|
7234
|
-
//#endregion
|
|
7235
|
-
//#region src/commands/logout.ts
|
|
7236
|
-
const logoutCommand = async () => {
|
|
7237
|
-
const active = getActiveToken();
|
|
7238
|
-
if (active && active.kind === "session") await revokeSessionApi(active.token);
|
|
7239
|
-
clearStoredCredentials();
|
|
7240
|
-
clearCachedEntitlement();
|
|
7241
|
-
log.success("Signed out and cleared cached credentials.");
|
|
7242
|
-
};
|
|
7243
|
-
//#endregion
|
|
7244
|
-
//#region src/cloud/outbox.ts
|
|
7245
|
-
const MAX_OUTBOX_BYTES = 5 * 1024 * 1024;
|
|
7246
|
-
const getMaxOutboxBytes = () => {
|
|
7247
|
-
const override = process.env.RAIGAL_MAX_OUTBOX_BYTES;
|
|
7248
|
-
if (override) {
|
|
7249
|
-
const parsed = Number.parseInt(override, 10);
|
|
7250
|
-
if (!Number.isNaN(parsed) && parsed > 0) return parsed;
|
|
7251
|
-
}
|
|
7252
|
-
return MAX_OUTBOX_BYTES;
|
|
7253
|
-
};
|
|
7254
|
-
const loadOutboxRuns = () => {
|
|
7255
|
-
const outboxPath = getOutboxPath();
|
|
7256
|
-
if (!fs.existsSync(outboxPath)) return [];
|
|
7257
|
-
try {
|
|
7258
|
-
const lines = fs.readFileSync(outboxPath, "utf-8").split("\n").filter((l) => l.trim().length > 0);
|
|
7259
|
-
const runs = [];
|
|
7260
|
-
for (const line of lines) try {
|
|
7261
|
-
const parsed = JSON.parse(line);
|
|
7262
|
-
const valid = Run.safeParse(parsed);
|
|
7263
|
-
if (valid.success) runs.push(valid.data);
|
|
7264
|
-
} catch {}
|
|
7265
|
-
return runs;
|
|
7266
|
-
} catch {
|
|
7267
|
-
return [];
|
|
7268
|
-
}
|
|
7269
|
-
};
|
|
7270
|
-
const writeRunsToOutbox = (runs) => {
|
|
7271
|
-
const outboxPath = getOutboxPath();
|
|
7272
|
-
const dir = path.dirname(outboxPath);
|
|
7273
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, {
|
|
7274
|
-
recursive: true,
|
|
7275
|
-
mode: 448
|
|
7276
|
-
});
|
|
7277
|
-
let lines = runs.map((r) => JSON.stringify(r));
|
|
7278
|
-
let text = lines.length > 0 ? `${lines.join("\n")}\n` : "";
|
|
7279
|
-
const maxBytes = getMaxOutboxBytes();
|
|
7280
|
-
while (Buffer.byteLength(text, "utf-8") > maxBytes && lines.length > 1) {
|
|
7281
|
-
lines.shift();
|
|
7282
|
-
text = `${lines.join("\n")}\n`;
|
|
7283
|
-
}
|
|
7284
|
-
const temp = `${outboxPath}.${Date.now()}.tmp`;
|
|
7285
|
-
fs.writeFileSync(temp, text, { mode: 384 });
|
|
7286
|
-
try {
|
|
7287
|
-
fs.renameSync(temp, outboxPath);
|
|
7288
|
-
} catch {
|
|
7289
|
-
fs.rmSync(temp, { force: true });
|
|
7290
|
-
fs.writeFileSync(outboxPath, text, { mode: 384 });
|
|
7291
|
-
}
|
|
7292
|
-
};
|
|
7293
|
-
const enqueueRun = (run) => {
|
|
7294
|
-
const existing = loadOutboxRuns();
|
|
7295
|
-
existing.push(run);
|
|
7296
|
-
writeRunsToOutbox(existing);
|
|
7297
|
-
};
|
|
7298
|
-
const getLastRecordedRun = () => {
|
|
7299
|
-
const runs = loadOutboxRuns();
|
|
7300
|
-
return runs.length > 0 ? runs[runs.length - 1] ?? null : null;
|
|
7301
|
-
};
|
|
7302
|
-
const flushOutbox = async (token) => {
|
|
7303
|
-
const runs = loadOutboxRuns();
|
|
7304
|
-
if (runs.length === 0) return {
|
|
7305
|
-
sent: 0,
|
|
7306
|
-
failed: 0,
|
|
7307
|
-
remaining: 0
|
|
7308
|
-
};
|
|
7309
|
-
let sentCount = 0;
|
|
7310
|
-
let failCount = 0;
|
|
7311
|
-
const remainingRuns = [];
|
|
7312
|
-
for (let i = 0; i < runs.length; i++) {
|
|
7313
|
-
const run = runs[i];
|
|
7314
|
-
try {
|
|
7315
|
-
await requestApi("/v1/runs", {
|
|
7316
|
-
method: "POST",
|
|
7317
|
-
token,
|
|
7318
|
-
body: run,
|
|
7319
|
-
timeoutMs: 4e3
|
|
7320
|
-
});
|
|
7321
|
-
sentCount++;
|
|
7322
|
-
} catch (err) {
|
|
7323
|
-
if (err instanceof ApiError) {
|
|
7324
|
-
if ([
|
|
7325
|
-
400,
|
|
7326
|
-
401,
|
|
7327
|
-
403,
|
|
7328
|
-
413,
|
|
7329
|
-
422
|
|
7330
|
-
].includes(err.status)) {
|
|
7331
|
-
failCount++;
|
|
7332
|
-
continue;
|
|
7333
|
-
}
|
|
7334
|
-
if (err.status === 409) {
|
|
7335
|
-
sentCount++;
|
|
7336
|
-
continue;
|
|
7337
|
-
}
|
|
7649
|
+
process.exitCode = 1;
|
|
7650
|
+
return;
|
|
7338
7651
|
}
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7652
|
+
if (pollResult.status === "expired") {
|
|
7653
|
+
log.error("Login authorization code expired. Please try running `raigal login` again.");
|
|
7654
|
+
process.exitCode = 1;
|
|
7655
|
+
return;
|
|
7656
|
+
}
|
|
7657
|
+
if (pollResult.status === "ok" && pollResult.data) {
|
|
7658
|
+
const { access_token, org, user, expires_at } = pollResult.data;
|
|
7659
|
+
saveStoredCredentials({
|
|
7660
|
+
token: access_token,
|
|
7661
|
+
org,
|
|
7662
|
+
user,
|
|
7663
|
+
expires_at
|
|
7664
|
+
});
|
|
7665
|
+
process.stdout.write("\n");
|
|
7666
|
+
log.success(`Signed in as ${user.email} · ${org.name}`);
|
|
7667
|
+
return;
|
|
7668
|
+
}
|
|
7669
|
+
} catch (err) {
|
|
7670
|
+
log.error(`Polling error: ${err instanceof Error ? err.message : String(err)}`);
|
|
7671
|
+
process.exitCode = 1;
|
|
7672
|
+
return;
|
|
7342
7673
|
}
|
|
7343
7674
|
}
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7675
|
+
log.error("Login timed out. Please run `raigal login` again.");
|
|
7676
|
+
process.exitCode = 1;
|
|
7677
|
+
};
|
|
7678
|
+
const loginCommand = async (options = {}) => {
|
|
7679
|
+
if (options.withToken) {
|
|
7680
|
+
await loginWithToken();
|
|
7681
|
+
return;
|
|
7682
|
+
}
|
|
7683
|
+
log.info("Starting browser login...");
|
|
7684
|
+
let grant;
|
|
7685
|
+
try {
|
|
7686
|
+
grant = await startDeviceLogin();
|
|
7687
|
+
} catch (err) {
|
|
7688
|
+
log.error(`Failed to start login: ${err instanceof Error ? err.message : String(err)}`);
|
|
7689
|
+
process.exitCode = 1;
|
|
7690
|
+
return;
|
|
7691
|
+
}
|
|
7692
|
+
process.stdout.write("\n");
|
|
7693
|
+
process.stdout.write(` Confirmation code: ${grant.user_code}\n`);
|
|
7694
|
+
process.stdout.write(` Verification URL: ${grant.verification_uri_complete}\n\n`);
|
|
7695
|
+
log.muted("Opening browser to confirm authorization...");
|
|
7696
|
+
openBrowser(grant.verification_uri_complete);
|
|
7697
|
+
await pollDeviceAuthorization(grant);
|
|
7698
|
+
};
|
|
7699
|
+
//#endregion
|
|
7700
|
+
//#region src/commands/logout.ts
|
|
7701
|
+
const logoutCommand = async () => {
|
|
7702
|
+
const active = getActiveToken();
|
|
7703
|
+
if (active && active.kind === "session") await revokeSessionApi(active.token);
|
|
7704
|
+
clearStoredCredentials();
|
|
7705
|
+
clearCachedEntitlement();
|
|
7706
|
+
log.success("Signed out and cleared cached credentials.");
|
|
7350
7707
|
};
|
|
7351
7708
|
//#endregion
|
|
7352
7709
|
//#region src/commands/telemetry-show.ts
|
|
@@ -7450,6 +7807,14 @@ const registerCloudCommands = (program) => {
|
|
|
7450
7807
|
if (flags.show || isJson) await telemetryShowCommand({ json: isJson });
|
|
7451
7808
|
else process.stdout.write("Run `raigal telemetry --show` to inspect recorded telemetry payloads.\n");
|
|
7452
7809
|
});
|
|
7810
|
+
program.command("report-pr-closed").description("Report a pull request closed/merged event to Raigal Cloud").option("--pr <number>", "PR number (default: read from GITHUB_EVENT_PATH)").option("--merged", "Flag indicating whether PR was merged").action(async (flags) => {
|
|
7811
|
+
const prNumber = flags.pr ? Number.parseInt(flags.pr, 10) : void 0;
|
|
7812
|
+
const { reportPrClosedCommand } = await import("./report-pr-closed-CDdQjRWj.js");
|
|
7813
|
+
await reportPrClosedCommand({
|
|
7814
|
+
prNumber,
|
|
7815
|
+
merged: Boolean(flags.merged)
|
|
7816
|
+
});
|
|
7817
|
+
});
|
|
7453
7818
|
};
|
|
7454
7819
|
//#endregion
|
|
7455
7820
|
//#region src/hooks/feedback.ts
|
|
@@ -21146,7 +21511,17 @@ const atomicWrite = (targetPath, content) => {
|
|
|
21146
21511
|
const rand = Math.random().toString(36).slice(2, 10);
|
|
21147
21512
|
const tmp = path.join(dir, `.aislop-tmp-${process.pid}-${rand}`);
|
|
21148
21513
|
fs.writeFileSync(tmp, content, "utf-8");
|
|
21149
|
-
|
|
21514
|
+
try {
|
|
21515
|
+
fs.renameSync(tmp, targetPath);
|
|
21516
|
+
} catch (err) {
|
|
21517
|
+
const code = err?.code;
|
|
21518
|
+
if (code === "EPERM" || code === "EBUSY") {
|
|
21519
|
+
fs.copyFileSync(tmp, targetPath);
|
|
21520
|
+
try {
|
|
21521
|
+
fs.unlinkSync(tmp);
|
|
21522
|
+
} catch {}
|
|
21523
|
+
} else throw err;
|
|
21524
|
+
}
|
|
21150
21525
|
};
|
|
21151
21526
|
const readIfExists = (targetPath) => {
|
|
21152
21527
|
try {
|
|
@@ -23984,7 +24359,7 @@ const maybeNotifyUpdate = async (now = Date.now()) => {
|
|
|
23984
24359
|
if (!process.stderr.isTTY) return;
|
|
23985
24360
|
const cachePath = resolveUpdateCachePath();
|
|
23986
24361
|
const cache = readCache(cachePath);
|
|
23987
|
-
if (cache && isOutdated("1.0.
|
|
24362
|
+
if (cache && isOutdated("1.0.3", cache.latest)) process.stderr.write(formatUpdateNotice(APP_VERSION, cache.latest));
|
|
23988
24363
|
if (!cache || now - cache.checkedAt > CHECK_INTERVAL_MS) {
|
|
23989
24364
|
const latest = await fetchLatestVersion$1();
|
|
23990
24365
|
if (latest) writeCache(cachePath, {
|
|
@@ -24504,7 +24879,7 @@ const renderCommandGroup = (group, commandWidth) => {
|
|
|
24504
24879
|
return lines;
|
|
24505
24880
|
};
|
|
24506
24881
|
const renderCommandReference = (input = {}) => {
|
|
24507
|
-
const version = input.version ?? "1.0.
|
|
24882
|
+
const version = input.version ?? "1.0.3";
|
|
24508
24883
|
const commandWidth = Math.max(...COMMAND_REFERENCE.map((item) => item.command.length));
|
|
24509
24884
|
const lines = [renderHeader({
|
|
24510
24885
|
version,
|
|
@@ -24727,7 +25102,7 @@ const renderHelpDetails = () => [
|
|
|
24727
25102
|
].map((line) => highlightRaigal(line, theme)).join("\n");
|
|
24728
25103
|
const renderHome = (input = {}) => {
|
|
24729
25104
|
let out = renderHeader({
|
|
24730
|
-
version: input.version ?? "1.0.
|
|
25105
|
+
version: input.version ?? "1.0.3",
|
|
24731
25106
|
command: "--bare",
|
|
24732
25107
|
context: []
|
|
24733
25108
|
});
|
|
@@ -24885,100 +25260,15 @@ const matchFixAgent = (flags) => {
|
|
|
24885
25260
|
return FIX_AGENT_FLAGS.find((a) => flags[a.name])?.flag;
|
|
24886
25261
|
};
|
|
24887
25262
|
//#endregion
|
|
24888
|
-
//#region src/
|
|
24889
|
-
|
|
24890
|
-
|
|
24891
|
-
|
|
24892
|
-
|
|
24893
|
-
|
|
24894
|
-
|
|
24895
|
-
|
|
24896
|
-
|
|
24897
|
-
"ignore"
|
|
24898
|
-
]
|
|
24899
|
-
});
|
|
24900
|
-
if (res.error || res.status !== 0) return void 0;
|
|
24901
|
-
return res.stdout.trim() || void 0;
|
|
24902
|
-
} catch {
|
|
24903
|
-
return;
|
|
24904
|
-
}
|
|
24905
|
-
};
|
|
24906
|
-
const getRootCommitHash = (directory) => {
|
|
24907
|
-
const hash = execGit([
|
|
24908
|
-
"rev-list",
|
|
24909
|
-
"--max-parents=0",
|
|
24910
|
-
"HEAD"
|
|
24911
|
-
], directory);
|
|
24912
|
-
if (!hash) return void 0;
|
|
24913
|
-
const firstLine = hash.split("\n")[0]?.trim();
|
|
24914
|
-
return firstLine && /^[0-9a-f]{40,64}$/i.test(firstLine) ? firstLine : void 0;
|
|
24915
|
-
};
|
|
24916
|
-
const detectRepoRef = (directory, ownerId) => {
|
|
24917
|
-
const detected = detectLocalRepoOwner(directory);
|
|
24918
|
-
if (!detected.owner || !detected.repo) return null;
|
|
24919
|
-
return {
|
|
24920
|
-
provider: "github",
|
|
24921
|
-
slug: `${detected.owner}/${detected.repo}`.toLowerCase(),
|
|
24922
|
-
owner_id: ownerId,
|
|
24923
|
-
root_commit_hash: getRootCommitHash(directory)
|
|
24924
|
-
};
|
|
24925
|
-
};
|
|
24926
|
-
const readGitHubEventPayload = () => {
|
|
24927
|
-
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
24928
|
-
if (!eventPath || !fs.existsSync(eventPath)) return null;
|
|
24929
|
-
try {
|
|
24930
|
-
const content = fs.readFileSync(eventPath, "utf-8");
|
|
24931
|
-
return JSON.parse(content);
|
|
24932
|
-
} catch {
|
|
24933
|
-
return null;
|
|
24934
|
-
}
|
|
24935
|
-
};
|
|
24936
|
-
const detectGitContext = (directory) => {
|
|
24937
|
-
const eventPayload = readGitHubEventPayload();
|
|
24938
|
-
const pr = eventPayload?.pull_request;
|
|
24939
|
-
let headSha = pr?.head?.sha;
|
|
24940
|
-
if (!headSha) headSha = process.env.GITHUB_SHA || execGit(["rev-parse", "HEAD"], directory);
|
|
24941
|
-
let branch = process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME;
|
|
24942
|
-
if (!branch) {
|
|
24943
|
-
branch = execGit([
|
|
24944
|
-
"rev-parse",
|
|
24945
|
-
"--abbrev-ref",
|
|
24946
|
-
"HEAD"
|
|
24947
|
-
], directory);
|
|
24948
|
-
if (branch === "HEAD") branch = void 0;
|
|
24949
|
-
}
|
|
24950
|
-
let baseRef = pr?.base?.ref || process.env.GITHUB_BASE_REF;
|
|
24951
|
-
if (!baseRef) baseRef = void 0;
|
|
24952
|
-
let prNumber;
|
|
24953
|
-
if (typeof pr?.number === "number") prNumber = pr.number;
|
|
24954
|
-
else if (typeof eventPayload?.number === "number") prNumber = eventPayload.number;
|
|
24955
|
-
else if (process.env.GITHUB_REF) {
|
|
24956
|
-
const match = process.env.GITHUB_REF.match(/^refs\/pull\/(\d+)\//);
|
|
24957
|
-
if (match && match[1]) prNumber = Number.parseInt(match[1], 10);
|
|
24958
|
-
}
|
|
24959
|
-
const result = {};
|
|
24960
|
-
if (branch) result.branch = branch;
|
|
24961
|
-
if (headSha) result.head_sha = headSha;
|
|
24962
|
-
if (baseRef) result.base_ref = baseRef;
|
|
24963
|
-
if (prNumber !== void 0 && !Number.isNaN(prNumber)) result.pr_number = prNumber;
|
|
24964
|
-
return result;
|
|
24965
|
-
};
|
|
24966
|
-
const detectCiContext = () => {
|
|
24967
|
-
if (process.env.GITHUB_ACTIONS === "true" || process.env.GITHUB_ACTIONS === "1") {
|
|
24968
|
-
const serverUrl = process.env.GITHUB_SERVER_URL || "https://github.com";
|
|
24969
|
-
const repo = process.env.GITHUB_REPOSITORY;
|
|
24970
|
-
const runId = process.env.GITHUB_RUN_ID;
|
|
24971
|
-
let runUrl;
|
|
24972
|
-
if (repo && runId) {
|
|
24973
|
-
const attempt = process.env.GITHUB_RUN_ATTEMPT;
|
|
24974
|
-
runUrl = `${serverUrl}/${repo}/actions/runs/${runId}${attempt ? `/attempts/${attempt}` : ""}`;
|
|
24975
|
-
}
|
|
24976
|
-
return {
|
|
24977
|
-
provider: "github-actions",
|
|
24978
|
-
...runUrl ? { run_url: runUrl } : {}
|
|
24979
|
-
};
|
|
24980
|
-
}
|
|
24981
|
-
if (process.env.CI === "true" || process.env.CI === "1") return { provider: process.env.GITLAB_CI && "gitlab-ci" || process.env.BITBUCKET_BUILD_NUMBER && "bitbucket-pipelines" || process.env.CIRCLECI && "circleci" || process.env.BUILDKITE && "buildkite" || process.env.TRAVIS && "travis-ci" || "generic-ci" };
|
|
25263
|
+
//#region src/output/rule-message.ts
|
|
25264
|
+
/**
|
|
25265
|
+
* Pure deterministic formatter for diagnostic messages.
|
|
25266
|
+
* Secret-class rules (or redactSource: true) unconditionally return FIXED_SECRET_DIAGNOSTIC_MESSAGE.
|
|
25267
|
+
* Non-secret rules return diagnostic.message (clamped to max 500 chars).
|
|
25268
|
+
*/
|
|
25269
|
+
const formatFindingMessage = (diagnostic) => {
|
|
25270
|
+
if (diagnostic.redactSource || isSecretClassRule(diagnostic.rule)) return FIXED_SECRET_DIAGNOSTIC_MESSAGE;
|
|
25271
|
+
return diagnostic.message.slice(0, 500);
|
|
24982
25272
|
};
|
|
24983
25273
|
//#endregion
|
|
24984
25274
|
//#region src/cloud/fingerprint.ts
|
|
@@ -25020,7 +25310,8 @@ const toContractFinding = (diagnostic, rootDirectory, lineTextOverride) => {
|
|
|
25020
25310
|
severity,
|
|
25021
25311
|
path: relativePath,
|
|
25022
25312
|
line: Math.max(0, diagnostic.line),
|
|
25023
|
-
fingerprint
|
|
25313
|
+
fingerprint,
|
|
25314
|
+
message: formatFindingMessage(diagnostic)
|
|
25024
25315
|
};
|
|
25025
25316
|
};
|
|
25026
25317
|
//#endregion
|
|
@@ -25111,96 +25402,6 @@ const applyPolicyToConfig = (localConfig, policy) => {
|
|
|
25111
25402
|
};
|
|
25112
25403
|
};
|
|
25113
25404
|
//#endregion
|
|
25114
|
-
//#region src/cloud/recorder.ts
|
|
25115
|
-
var CloudRunRecorder = class {
|
|
25116
|
-
runId;
|
|
25117
|
-
command;
|
|
25118
|
-
directory;
|
|
25119
|
-
flags;
|
|
25120
|
-
startedAt;
|
|
25121
|
-
steps = [];
|
|
25122
|
-
report;
|
|
25123
|
-
policyMeta;
|
|
25124
|
-
seq = 0;
|
|
25125
|
-
finished = false;
|
|
25126
|
-
constructor(command, directory, flags = []) {
|
|
25127
|
-
this.runId = randomUUID();
|
|
25128
|
-
this.command = command;
|
|
25129
|
-
this.directory = directory;
|
|
25130
|
-
this.flags = flags.map((f) => f.replace(/^--?/, "")).filter((f) => f.length > 0).slice(0, 40);
|
|
25131
|
-
this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25132
|
-
}
|
|
25133
|
-
recordStep(name, durationMs, ok = true, counts) {
|
|
25134
|
-
if (this.steps.length >= 200) return;
|
|
25135
|
-
this.steps.push({
|
|
25136
|
-
seq: this.seq++,
|
|
25137
|
-
name: name.slice(0, 80),
|
|
25138
|
-
ok,
|
|
25139
|
-
ms: Math.max(0, Math.round(durationMs)),
|
|
25140
|
-
counts
|
|
25141
|
-
});
|
|
25142
|
-
}
|
|
25143
|
-
setReport(report) {
|
|
25144
|
-
this.report = report;
|
|
25145
|
-
}
|
|
25146
|
-
setPolicyMeta(version, hash) {
|
|
25147
|
-
this.policyMeta = {
|
|
25148
|
-
version,
|
|
25149
|
-
hash: hash.slice(0, 64)
|
|
25150
|
-
};
|
|
25151
|
-
}
|
|
25152
|
-
buildRunPayload(exitCode) {
|
|
25153
|
-
const repo = detectRepoRef(this.directory) || {
|
|
25154
|
-
provider: "github",
|
|
25155
|
-
slug: "unknown/unknown"
|
|
25156
|
-
};
|
|
25157
|
-
const git = detectGitContext(this.directory);
|
|
25158
|
-
const ci = detectCiContext();
|
|
25159
|
-
const ownerVerified = Boolean(process.env.ACTIONS_ID_TOKEN_REQUEST_URL);
|
|
25160
|
-
return {
|
|
25161
|
-
run_id: this.runId,
|
|
25162
|
-
command: this.command,
|
|
25163
|
-
repo,
|
|
25164
|
-
owner_verified: ownerVerified,
|
|
25165
|
-
git,
|
|
25166
|
-
ci,
|
|
25167
|
-
flags: this.flags,
|
|
25168
|
-
cli_version: APP_VERSION,
|
|
25169
|
-
policy: this.policyMeta,
|
|
25170
|
-
started_at: this.startedAt,
|
|
25171
|
-
ended_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25172
|
-
exit_code: exitCode,
|
|
25173
|
-
steps: this.steps.slice(0, 200),
|
|
25174
|
-
report: this.report
|
|
25175
|
-
};
|
|
25176
|
-
}
|
|
25177
|
-
async finish(exitCode) {
|
|
25178
|
-
if (this.finished) return;
|
|
25179
|
-
this.finished = true;
|
|
25180
|
-
try {
|
|
25181
|
-
enqueueRun(this.buildRunPayload(exitCode));
|
|
25182
|
-
const activeToken = getActiveToken();
|
|
25183
|
-
if (activeToken) await flushOutbox(activeToken.token);
|
|
25184
|
-
} catch {}
|
|
25185
|
-
}
|
|
25186
|
-
};
|
|
25187
|
-
let activeRecorder = null;
|
|
25188
|
-
const getActiveRecorder = () => activeRecorder;
|
|
25189
|
-
const startRunRecorder = (command, directory, flags = []) => {
|
|
25190
|
-
const recorder = new CloudRunRecorder(command, directory, flags);
|
|
25191
|
-
activeRecorder = recorder;
|
|
25192
|
-
const activeToken = getActiveToken();
|
|
25193
|
-
if (activeToken) flushOutbox(activeToken.token).catch(() => {});
|
|
25194
|
-
return recorder;
|
|
25195
|
-
};
|
|
25196
|
-
const finishActiveRecorder = async (exitCode = 0) => {
|
|
25197
|
-
if (activeRecorder) {
|
|
25198
|
-
const rec = activeRecorder;
|
|
25199
|
-
activeRecorder = null;
|
|
25200
|
-
await rec.finish(exitCode);
|
|
25201
|
-
}
|
|
25202
|
-
};
|
|
25203
|
-
//#endregion
|
|
25204
25405
|
//#region src/engagement/pilot-invitation.ts
|
|
25205
25406
|
const STATE_BASENAME = "pilot_invitation.scans";
|
|
25206
25407
|
const INVITATION_SCAN_THRESHOLD = 3;
|
|
@@ -26435,12 +26636,12 @@ const runScanBody = async (resolvedDir, config, options, projectInfo, scanScope,
|
|
|
26435
26636
|
scoreFileCount
|
|
26436
26637
|
});
|
|
26437
26638
|
if (options.sarif) {
|
|
26438
|
-
const { buildSarifLog } = await import("./sarif
|
|
26639
|
+
const { buildSarifLog } = await import("./sarif--DI_2p2r.js");
|
|
26439
26640
|
console.log(JSON.stringify(buildSarifLog(results), null, 2));
|
|
26440
26641
|
return completion;
|
|
26441
26642
|
}
|
|
26442
26643
|
if (options.json) {
|
|
26443
|
-
const { buildJsonOutput } = await import("./json-
|
|
26644
|
+
const { buildJsonOutput } = await import("./json-C9fBWj3V.js");
|
|
26444
26645
|
const jsonOut = buildJsonOutput(results, scoreResult, scoreFileCount, elapsedMs, scanCoverage);
|
|
26445
26646
|
console.log(JSON.stringify(jsonOut, null, 2));
|
|
26446
26647
|
return completion;
|
|
@@ -29358,13 +29559,18 @@ const safeTelemetryConfig = (dir) => {
|
|
|
29358
29559
|
return;
|
|
29359
29560
|
}
|
|
29360
29561
|
};
|
|
29361
|
-
const handleTerminationSignal = async () => {
|
|
29562
|
+
const handleTerminationSignal = async (signal) => {
|
|
29362
29563
|
killActiveChildren();
|
|
29363
|
-
|
|
29364
|
-
|
|
29564
|
+
const exitCode = signal === "SIGINT" ? 130 : 143;
|
|
29565
|
+
await finishActiveRecorder(exitCode);
|
|
29566
|
+
process.exit(exitCode);
|
|
29365
29567
|
};
|
|
29366
|
-
process.on("SIGINT",
|
|
29367
|
-
|
|
29568
|
+
process.on("SIGINT", () => {
|
|
29569
|
+
handleTerminationSignal("SIGINT");
|
|
29570
|
+
});
|
|
29571
|
+
process.on("SIGTERM", () => {
|
|
29572
|
+
handleTerminationSignal("SIGTERM");
|
|
29573
|
+
});
|
|
29368
29574
|
const fireInstalledOnce = () => {
|
|
29369
29575
|
if (isTelemetryDisabled(safeTelemetryConfig(process.cwd()))) return;
|
|
29370
29576
|
if (ensureInstallId(resolveInstallIdPath()).created) track({
|
|
@@ -29551,4 +29757,4 @@ const main = async () => {
|
|
|
29551
29757
|
};
|
|
29552
29758
|
main();
|
|
29553
29759
|
//#endregion
|
|
29554
|
-
export {
|
|
29760
|
+
export { requestApi as a, log as c, detectRepoRef as i, FIXED_SECRET_DIAGNOSTIC_MESSAGE as l, withFindingAssessments as n, getActiveToken as o, ENGINE_INFO as r, APP_VERSION as s, summarizeFindingAssessments as t, isSecretClassRule as u };
|