claude-code-rust 0.13.0 → 0.13.2

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.
@@ -1,132 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from "node:fs";
3
-
4
- const reportPath = process.argv[2] ?? "jscpd-report/jscpd-report.json";
5
- const warningThreshold = Number.parseFloat(process.env.JSCPD_WARNING_THRESHOLD ?? "3.0");
6
-
7
- function escapeWorkflowCommand(value) {
8
- return String(value).replaceAll("%", "%25").replaceAll("\r", "%0D").replaceAll("\n", "%0A");
9
- }
10
-
11
- function markdownCell(value) {
12
- return String(value).replaceAll("|", "\\|").replaceAll("\n", " ");
13
- }
14
-
15
- function asNumber(value, fallback = 0) {
16
- const number = Number(value);
17
- return Number.isFinite(number) ? number : fallback;
18
- }
19
-
20
- function formatPercent(value) {
21
- return `${asNumber(value).toFixed(2)}%`;
22
- }
23
-
24
- function formatLocation(location) {
25
- if (!location?.name) {
26
- return "unknown";
27
- }
28
- const name = String(location.name).replaceAll("\\", "/");
29
- const start = asNumber(location.start, asNumber(location.startLoc?.line, 1));
30
- const end = asNumber(location.end, asNumber(location.endLoc?.line, start));
31
- return `${name}:${start}-${end}`;
32
- }
33
-
34
- function appendSummary(markdown) {
35
- const summaryPath = process.env.GITHUB_STEP_SUMMARY;
36
- if (summaryPath) {
37
- fs.appendFileSync(summaryPath, `${markdown}\n`);
38
- }
39
- }
40
-
41
- function emitWarning(message) {
42
- console.log(`::warning title=Duplicate code soft threshold::${escapeWorkflowCommand(message)}`);
43
- }
44
-
45
- if (!fs.existsSync(reportPath)) {
46
- const message = `jscpd report not found at ${reportPath}; duplicate-code summary was skipped.`;
47
- emitWarning(message);
48
- appendSummary(`### Duplicate Code Scan\n\n${message}\n`);
49
- process.exit(0);
50
- }
51
-
52
- const report = JSON.parse(fs.readFileSync(reportPath, "utf8"));
53
- const total = report.statistics?.total ?? {};
54
- const formats = report.statistics?.formats ?? {};
55
- const duplicates = Array.isArray(report.duplicates) ? report.duplicates : [];
56
-
57
- const percentage = asNumber(total.percentage);
58
- const clones = asNumber(total.clones, duplicates.length);
59
- const duplicatedLines = asNumber(total.duplicatedLines);
60
- const totalLines = asNumber(total.lines);
61
- const duplicatedTokens = asNumber(total.duplicatedTokens);
62
- const totalTokens = asNumber(total.tokens);
63
-
64
- const status =
65
- percentage >= warningThreshold
66
- ? `Warning: duplicated lines are ${formatPercent(percentage)}, above the ${formatPercent(warningThreshold)} soft threshold.`
67
- : `OK: duplicated lines are ${formatPercent(percentage)}, below the ${formatPercent(warningThreshold)} soft threshold.`;
68
-
69
- console.log(status);
70
- console.log(
71
- `jscpd found ${clones} clones across ${totalLines} lines and ${totalTokens} tokens ` +
72
- `(${duplicatedLines} duplicated lines, ${duplicatedTokens} duplicated tokens).`,
73
- );
74
-
75
- if (percentage >= warningThreshold) {
76
- emitWarning(
77
- `jscpd found ${formatPercent(percentage)} duplicated lines (${clones} clones), ` +
78
- `above the ${formatPercent(warningThreshold)} advisory threshold. ` +
79
- "This workflow is warning-only and does not block the PR.",
80
- );
81
- }
82
-
83
- const formatRows = Object.entries(formats)
84
- .sort(([, left], [, right]) => asNumber(right.percentage) - asNumber(left.percentage))
85
- .map(([format, stats]) =>
86
- [
87
- markdownCell(format),
88
- asNumber(stats.sources),
89
- asNumber(stats.clones),
90
- asNumber(stats.duplicatedLines),
91
- formatPercent(stats.percentage),
92
- ].join(" | "),
93
- );
94
-
95
- const topDuplicates = [...duplicates]
96
- .sort((left, right) => asNumber(right.lines) - asNumber(left.lines))
97
- .slice(0, 10)
98
- .map((duplicate) =>
99
- [
100
- asNumber(duplicate.lines),
101
- asNumber(duplicate.tokens),
102
- markdownCell(duplicate.format ?? "unknown"),
103
- markdownCell(formatLocation(duplicate.firstFile)),
104
- markdownCell(formatLocation(duplicate.secondFile)),
105
- ].join(" | "),
106
- );
107
-
108
- const summary = [
109
- "### Duplicate Code Scan",
110
- "",
111
- status,
112
- "",
113
- "| Metric | Value |",
114
- "| --- | ---: |",
115
- `| Clones | ${clones} |`,
116
- `| Duplicated lines | ${duplicatedLines} / ${totalLines} (${formatPercent(percentage)}) |`,
117
- `| Duplicated tokens | ${duplicatedTokens} / ${totalTokens} (${formatPercent(total.percentageTokens)}) |`,
118
- `| Soft threshold | ${formatPercent(warningThreshold)} |`,
119
- "",
120
- "| Format | Files | Clones | Duplicated lines | Duplicated lines % |",
121
- "| --- | ---: | ---: | ---: | ---: |",
122
- ...formatRows,
123
- "",
124
- "| Lines | Tokens | Format | First location | Second location |",
125
- "| ---: | ---: | --- | --- | --- |",
126
- ...(topDuplicates.length > 0 ? topDuplicates : ["| 0 | 0 | none | n/a | n/a |"]),
127
- "",
128
- "The complete JSON and HTML reports are attached as the `jscpd-report` workflow artifact.",
129
- "",
130
- ].join("\n");
131
-
132
- appendSummary(summary);
@@ -1,140 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
-
4
- const fs = require("node:fs");
5
- const path = require("node:path");
6
- const https = require("node:https");
7
- const { spawnSync } = require("node:child_process");
8
- const { pipeline } = require("node:stream/promises");
9
-
10
- const TARGETS = {
11
- "darwin:arm64": { target: "aarch64-apple-darwin", exe: "claude-rs" },
12
- "darwin:x64": { target: "x86_64-apple-darwin", exe: "claude-rs" },
13
- "linux:x64": { target: "x86_64-unknown-linux-gnu", exe: "claude-rs" },
14
- "win32:x64": { target: "x86_64-pc-windows-msvc", exe: "claude-rs.exe" }
15
- };
16
-
17
- const MAX_REDIRECTS = 5;
18
- const BRIDGE_RUNTIME_EXE =
19
- process.platform === "win32" ? "claude-rs-bridge-node.exe" : "claude-rs-bridge-node";
20
-
21
- function getTargetInfo() {
22
- return TARGETS[`${process.platform}:${process.arch}`];
23
- }
24
-
25
- async function downloadFile(url, outPath, redirects = 0) {
26
- if (redirects > MAX_REDIRECTS) {
27
- throw new Error(`Too many redirects while downloading ${url}`);
28
- }
29
-
30
- await new Promise((resolve, reject) => {
31
- const req = https.get(
32
- url,
33
- { headers: { "User-Agent": "claude-code-rust-installer" } },
34
- (res) => {
35
- const status = res.statusCode ?? 0;
36
-
37
- if (status >= 300 && status < 400 && res.headers.location) {
38
- const nextUrl = new URL(res.headers.location, url).toString();
39
- res.resume();
40
- downloadFile(nextUrl, outPath, redirects + 1).then(resolve).catch(reject);
41
- return;
42
- }
43
-
44
- if (status !== 200) {
45
- const chunks = [];
46
- res.on("data", (chunk) => chunks.push(chunk));
47
- res.on("end", () => {
48
- const body = Buffer.concat(chunks).toString("utf8").trim();
49
- reject(new Error(`Download failed (${status}) for ${url}${body ? `: ${body}` : ""}`));
50
- });
51
- return;
52
- }
53
-
54
- pipeline(res, fs.createWriteStream(outPath)).then(resolve).catch(reject);
55
- }
56
- );
57
-
58
- req.on("error", reject);
59
- });
60
- }
61
-
62
- function installRenamedBridgeRuntime(installDir) {
63
- const sourcePath = process.execPath;
64
- const runtimePath = path.join(installDir, BRIDGE_RUNTIME_EXE);
65
-
66
- try {
67
- if (!sourcePath || !fs.existsSync(sourcePath)) {
68
- throw new Error("current Node.js executable could not be resolved");
69
- }
70
-
71
- if (path.resolve(sourcePath) !== path.resolve(runtimePath)) {
72
- fs.copyFileSync(sourcePath, runtimePath);
73
- }
74
-
75
- if (process.platform !== "win32") {
76
- fs.chmodSync(runtimePath, 0o755);
77
- }
78
-
79
- const result = spawnSync(runtimePath, ["--version"], {
80
- encoding: "utf8",
81
- windowsHide: true
82
- });
83
- const version = String(result.stdout || "").trim();
84
-
85
- if (result.status !== 0 || !/^v\d+\./.test(version)) {
86
- throw new Error(
87
- `copied runtime failed validation${result.stderr ? `: ${result.stderr.trim()}` : ""}`
88
- );
89
- }
90
-
91
- console.log(`Installed renamed Agent SDK bridge runtime ${BRIDGE_RUNTIME_EXE} (${version})`);
92
- } catch (error) {
93
- try {
94
- fs.rmSync(runtimePath, { force: true });
95
- } catch {
96
- // Best-effort cleanup only; the Rust binary can still fall back to `node`.
97
- }
98
- console.warn(
99
- `Skipping renamed Agent SDK bridge runtime: ${error.message}. ` +
100
- "claude-rs will fall back to the `node` executable on PATH."
101
- );
102
- }
103
- }
104
-
105
- async function main() {
106
- const info = getTargetInfo();
107
- if (!info) {
108
- const key = `${process.platform}:${process.arch}`;
109
- throw new Error(`Unsupported platform/arch for claude-code-rust package install: ${key}`);
110
- }
111
-
112
- const pkgJsonPath = path.join(__dirname, "..", "package.json");
113
- const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
114
- const version = process.env.npm_package_version || pkg.version;
115
- const tag = `v${version}`;
116
- const repo = "srothgan/claude-code-rust";
117
- const assetName = `claude-code-rust-${info.target}${info.exe.endsWith(".exe") ? ".exe" : ""}`;
118
- const url = `https://github.com/${repo}/releases/download/${tag}/${assetName}`;
119
-
120
- const installDir = path.join(__dirname, "..", "vendor", info.target);
121
- const binaryPath = path.join(installDir, info.exe);
122
- const tempPath = `${binaryPath}.tmp`;
123
-
124
- fs.mkdirSync(installDir, { recursive: true });
125
- await downloadFile(url, tempPath);
126
- fs.renameSync(tempPath, binaryPath);
127
-
128
- if (process.platform !== "win32") {
129
- fs.chmodSync(binaryPath, 0o755);
130
- }
131
-
132
- installRenamedBridgeRuntime(installDir);
133
-
134
- console.log(`Installed claude-code-rust ${version} (${info.target})`);
135
- }
136
-
137
- main().catch((error) => {
138
- console.error(`claude-code-rust postinstall failed: ${error.message}`);
139
- process.exit(1);
140
- });