kt-wrapped 0.0.0-stage → 0.1.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/README.md +151 -2
- package/assets/images/demo-wrapped.png +0 -0
- package/bin/kt-wrapped.mjs +84 -0
- package/package.json +40 -3
- package/postinstall.mjs +244 -0
package/README.md
CHANGED
|
@@ -1,3 +1,152 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# kt-wrapped
|
|
4
|
+
|
|
5
|
+
**Your year in code, beautifully visualized.**
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
<strong>Credit:</strong> Modified from
|
|
9
|
+
<a href="https://github.com/numman-ali/codex-wrapped">numman-ali/codex-wrapped</a>,
|
|
10
|
+
which was built on top of
|
|
11
|
+
<a href="https://github.com/moddi3/opencode-wrapped">opencode-wrapped</a>.
|
|
12
|
+
</p>
|
|
13
|
+
<p>
|
|
14
|
+
Built for
|
|
15
|
+
<a href="https://github.com/Kohaku-Lab/KohakuTerrarium">Kohaku-Lab/KohakuTerrarium</a>.
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
Generate a personalized "Spotify Wrapped"-style summary of your
|
|
19
|
+
[KohakuTerrarium](https://github.com/Kohaku-Lab/KohakuTerrarium) usage.
|
|
20
|
+
|
|
21
|
+
[](LICENSE)
|
|
22
|
+
[](https://bun.sh)
|
|
23
|
+
|
|
24
|
+
<img src="./assets/images/demo-wrapped.png" alt="KT Wrapped Example" width="600" />
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
### Quick Start
|
|
33
|
+
|
|
34
|
+
Run directly without installing:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx kt-wrapped # or bunx, or yarn/pnpm dlx
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Global Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install -g kt-wrapped # or bun/yarn/pnpm
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Then run anywhere:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
kt-wrapped
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Usage Options
|
|
53
|
+
|
|
54
|
+
| Option | Description |
|
|
55
|
+
| --------------- | ------------------------------------ |
|
|
56
|
+
| `--year, -y` | Generate wrapped for a specific year |
|
|
57
|
+
| `--help, -h` | Show help message |
|
|
58
|
+
| `--version, -v` | Show version number |
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
- Sessions, turns, tokens, projects, and streaks
|
|
63
|
+
- GitHub-style activity heatmap
|
|
64
|
+
- Top models and providers breakdown
|
|
65
|
+
- Usage cost (when available)
|
|
66
|
+
- Shareable PNG image
|
|
67
|
+
- Inline image display (Ghostty, Kitty, iTerm2, WezTerm, Konsole)
|
|
68
|
+
- Auto-copy to clipboard
|
|
69
|
+
|
|
70
|
+
## Terminal Support
|
|
71
|
+
|
|
72
|
+
The wrapped image displays natively in terminals that support inline images:
|
|
73
|
+
|
|
74
|
+
| Terminal | Protocol | Status |
|
|
75
|
+
| ------------------------------------------ | -------------- | --------------------------- |
|
|
76
|
+
| [Ghostty](https://ghostty.org) | Kitty Graphics | Full support |
|
|
77
|
+
| [Kitty](https://sw.kovidgoyal.net/kitty/) | Kitty Graphics | Full support |
|
|
78
|
+
| [WezTerm](https://wezfurlong.org/wezterm/) | Kitty + iTerm2 | Full support |
|
|
79
|
+
| [iTerm2](https://iterm2.com) | iTerm2 Inline | Full support |
|
|
80
|
+
| [Konsole](https://konsole.kde.org) | Kitty Graphics | Full support |
|
|
81
|
+
| Other terminals | — | Image saved to file only |
|
|
82
|
+
|
|
83
|
+
## Output
|
|
84
|
+
|
|
85
|
+
The tool generates:
|
|
86
|
+
|
|
87
|
+
1. **Terminal Summary** — Quick stats overview in your terminal
|
|
88
|
+
2. **PNG Image** — A beautiful, shareable wrapped card saved to your home directory
|
|
89
|
+
3. **Clipboard** — Automatically copies the image to your clipboard
|
|
90
|
+
|
|
91
|
+
## Data Source
|
|
92
|
+
|
|
93
|
+
`kt-wrapped` reads data from your local KohakuTerrarium session store:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
~/.kohakuterrarium/sessions
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
No data is sent anywhere. Everything is processed locally.
|
|
100
|
+
|
|
101
|
+
Token pricing for cost estimates is also local and versioned in:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
src/pricing-data.ts
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
If a model is missing from that table, cost is treated as unavailable for that model until it is added in a new release.
|
|
108
|
+
|
|
109
|
+
## Building
|
|
110
|
+
|
|
111
|
+
### Development
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Run in development mode with hot reload
|
|
115
|
+
bun run dev
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Production Build
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Build for all platforms
|
|
122
|
+
bun run build
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Releasing
|
|
126
|
+
|
|
127
|
+
Releases are automated via [semantic-release](https://semantic-release.gitbook.io). Merging PRs with [conventional commits](https://www.conventionalcommits.org) to `main` triggers a release.
|
|
128
|
+
|
|
129
|
+
## Tech Stack
|
|
130
|
+
|
|
131
|
+
- **Runtime**: [Bun](https://bun.sh)
|
|
132
|
+
- **Image Generation**: [Satori](https://github.com/vercel/satori) + [Resvg](https://github.com/nicolo-ribaudo/resvg-js)
|
|
133
|
+
- **CLI UI**: [@clack/prompts](https://github.com/natemoo-re/clack)
|
|
134
|
+
- **Font**: IBM Plex Mono
|
|
135
|
+
|
|
136
|
+
## Contributing
|
|
137
|
+
|
|
138
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
<div align="center">
|
|
147
|
+
|
|
148
|
+
Built for the KohakuTerrarium community
|
|
149
|
+
|
|
150
|
+
Credit: <a href="https://github.com/ryoppippi/ccusage">ccusage</a>
|
|
151
|
+
|
|
152
|
+
</div>
|
|
Binary file
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const projectRoot = path.resolve(__dirname, "..");
|
|
12
|
+
|
|
13
|
+
function run(command, args) {
|
|
14
|
+
const result = spawnSync(command, args, {
|
|
15
|
+
stdio: "inherit",
|
|
16
|
+
});
|
|
17
|
+
if (result.error) {
|
|
18
|
+
console.error(result.error.message);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const code = typeof result.status === "number" ? result.status : 0;
|
|
22
|
+
process.exit(code);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const localEntry = path.join(projectRoot, "src", "index.ts");
|
|
26
|
+
if (fs.existsSync(localEntry)) {
|
|
27
|
+
run("bun", [localEntry, ...process.argv.slice(2)]);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const platformMap = {
|
|
31
|
+
darwin: "darwin",
|
|
32
|
+
linux: "linux",
|
|
33
|
+
win32: "windows",
|
|
34
|
+
};
|
|
35
|
+
const archMap = {
|
|
36
|
+
x64: "x64",
|
|
37
|
+
arm64: "arm64",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
let platform = platformMap[os.platform()];
|
|
41
|
+
if (!platform) {
|
|
42
|
+
platform = os.platform();
|
|
43
|
+
}
|
|
44
|
+
let arch = archMap[os.arch()];
|
|
45
|
+
if (!arch) {
|
|
46
|
+
arch = os.arch();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const base = "kt-wrapped-" + platform + "-" + arch;
|
|
50
|
+
const binary = platform === "windows" ? "kt-wrapped.exe" : "kt-wrapped";
|
|
51
|
+
|
|
52
|
+
function findBinary(startDir) {
|
|
53
|
+
let current = startDir;
|
|
54
|
+
for (;;) {
|
|
55
|
+
const modules = path.join(current, "node_modules");
|
|
56
|
+
if (fs.existsSync(modules)) {
|
|
57
|
+
const entries = fs.readdirSync(modules);
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
if (!entry.startsWith(base)) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const candidate = path.join(modules, entry, "bin", binary);
|
|
63
|
+
if (fs.existsSync(candidate)) {
|
|
64
|
+
return candidate;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const parent = path.dirname(current);
|
|
69
|
+
if (parent === current) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
current = parent;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const resolved = findBinary(__dirname);
|
|
77
|
+
if (!resolved) {
|
|
78
|
+
console.error(
|
|
79
|
+
'Unable to find a runnable kt-wrapped binary. For local development, run "bun src/index.ts".'
|
|
80
|
+
);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
run(resolved, process.argv.slice(2));
|
package/package.json
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kt-wrapped",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Generate a personalized Spotify Wrapped-style summary of your KohakuTerrarium usage",
|
|
5
|
+
"bin": {
|
|
6
|
+
"kt-wrapped": "bin/kt-wrapped.mjs"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node ./postinstall.mjs"
|
|
10
|
+
},
|
|
11
|
+
"optionalDependencies": {
|
|
12
|
+
"kt-wrapped-linux-arm64": "0.1.0",
|
|
13
|
+
"kt-wrapped-linux-x64": "0.1.0",
|
|
14
|
+
"kt-wrapped-linux-x64-baseline": "0.1.0",
|
|
15
|
+
"kt-wrapped-linux-arm64-musl": "0.1.0",
|
|
16
|
+
"kt-wrapped-linux-x64-musl": "0.1.0",
|
|
17
|
+
"kt-wrapped-linux-x64-baseline-musl": "0.1.0",
|
|
18
|
+
"kt-wrapped-darwin-arm64": "0.1.0",
|
|
19
|
+
"kt-wrapped-darwin-x64": "0.1.0",
|
|
20
|
+
"kt-wrapped-darwin-x64-baseline": "0.1.0",
|
|
21
|
+
"kt-wrapped-windows-x64": "0.1.0",
|
|
22
|
+
"kt-wrapped-windows-x64-baseline": "0.1.0"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/Kohaku-Lab/KohakuTerrarium.git"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/Kohaku-Lab/KohakuTerrarium",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/Kohaku-Lab/KohakuTerrarium/issues"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"kohakuterrarium",
|
|
34
|
+
"kt",
|
|
35
|
+
"wrapped",
|
|
36
|
+
"kt-wrapped"
|
|
37
|
+
],
|
|
38
|
+
"author": {
|
|
39
|
+
"name": "Numman Ali",
|
|
40
|
+
"email": "numman.ali@gmail.com"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT"
|
|
6
43
|
}
|
package/postinstall.mjs
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Postinstall script for codex-wrapped-noyrlimit
|
|
5
|
+
*
|
|
6
|
+
* This script runs after npm install and symlinks the correct platform-specific
|
|
7
|
+
* binary to the bin directory. It auto-detects:
|
|
8
|
+
* - Platform (darwin, linux, windows)
|
|
9
|
+
* - Architecture (arm64, x64)
|
|
10
|
+
* - Libc (glibc, musl) for Linux
|
|
11
|
+
* - AVX2 support (baseline vs optimized) for x64
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import fs from "fs";
|
|
15
|
+
import path from "path";
|
|
16
|
+
import os from "os";
|
|
17
|
+
import { execSync } from "child_process";
|
|
18
|
+
import { fileURLToPath } from "url";
|
|
19
|
+
import { createRequire } from "module";
|
|
20
|
+
|
|
21
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
const require = createRequire(import.meta.url);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Detect if the system uses musl libc (Alpine Linux, etc.)
|
|
26
|
+
*/
|
|
27
|
+
function detectMusl() {
|
|
28
|
+
if (os.platform() !== "linux") return false;
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// Method 1: Check ldd output
|
|
32
|
+
const lddOutput = execSync("ldd --version 2>&1 || true", { encoding: "utf8" });
|
|
33
|
+
if (lddOutput.toLowerCase().includes("musl")) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Method 2: Check for musl loader
|
|
38
|
+
const files = fs.readdirSync("/lib").filter((f) => f.startsWith("ld-musl-"));
|
|
39
|
+
if (files.length > 0) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
// Ignore errors
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Detect if the CPU supports AVX2 instructions
|
|
51
|
+
*/
|
|
52
|
+
function detectAVX2() {
|
|
53
|
+
if (os.arch() !== "x64") return true; // Only relevant for x64
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
if (os.platform() === "linux") {
|
|
57
|
+
const cpuinfo = fs.readFileSync("/proc/cpuinfo", "utf8");
|
|
58
|
+
return cpuinfo.toLowerCase().includes("avx2");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (os.platform() === "darwin") {
|
|
62
|
+
const output = execSync("sysctl -n machdep.cpu.features 2>/dev/null || true", {
|
|
63
|
+
encoding: "utf8",
|
|
64
|
+
});
|
|
65
|
+
return output.toLowerCase().includes("avx2");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (os.platform() === "win32") {
|
|
69
|
+
// Windows: Assume AVX2 support on modern systems
|
|
70
|
+
// A more robust check would require native code
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
74
|
+
// If we can't detect, assume AVX2 is supported
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get the platform-specific package name
|
|
82
|
+
*/
|
|
83
|
+
function getPackageName() {
|
|
84
|
+
let platform;
|
|
85
|
+
switch (os.platform()) {
|
|
86
|
+
case "darwin":
|
|
87
|
+
platform = "darwin";
|
|
88
|
+
break;
|
|
89
|
+
case "linux":
|
|
90
|
+
platform = "linux";
|
|
91
|
+
break;
|
|
92
|
+
case "win32":
|
|
93
|
+
platform = "windows";
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let arch;
|
|
100
|
+
switch (os.arch()) {
|
|
101
|
+
case "x64":
|
|
102
|
+
arch = "x64";
|
|
103
|
+
break;
|
|
104
|
+
case "arm64":
|
|
105
|
+
arch = "arm64";
|
|
106
|
+
break;
|
|
107
|
+
default:
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Build package name parts
|
|
112
|
+
const parts = ["codex-wrapped-noyrlimit", platform, arch];
|
|
113
|
+
|
|
114
|
+
// Add baseline suffix for x64 without AVX2
|
|
115
|
+
if (arch === "x64" && !detectAVX2()) {
|
|
116
|
+
parts.push("baseline");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Add musl suffix for Linux with musl libc
|
|
120
|
+
if (platform === "linux" && detectMusl()) {
|
|
121
|
+
parts.push("musl");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return parts.join("-");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Find the binary from the platform package
|
|
129
|
+
*/
|
|
130
|
+
function findBinary(packageName) {
|
|
131
|
+
const binaryName =
|
|
132
|
+
os.platform() === "win32" ? "codex-wrapped-noyrlimit.exe" : "codex-wrapped-noyrlimit";
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`);
|
|
136
|
+
const packageDir = path.dirname(packageJsonPath);
|
|
137
|
+
const binaryPath = path.join(packageDir, "bin", binaryName);
|
|
138
|
+
|
|
139
|
+
if (fs.existsSync(binaryPath)) {
|
|
140
|
+
return { binaryPath, binaryName };
|
|
141
|
+
}
|
|
142
|
+
} catch {
|
|
143
|
+
// Package not found via require.resolve
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Fallback: try common paths
|
|
147
|
+
const fallbackPaths = [
|
|
148
|
+
path.join(__dirname, "..", packageName, "bin", binaryName),
|
|
149
|
+
path.join(__dirname, "node_modules", packageName, "bin", binaryName),
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
for (const p of fallbackPaths) {
|
|
153
|
+
if (fs.existsSync(p)) {
|
|
154
|
+
return { binaryPath: p, binaryName };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Prepare the bin directory
|
|
163
|
+
*/
|
|
164
|
+
function prepareBinDirectory(binaryName) {
|
|
165
|
+
const binDir = path.join(__dirname, "bin");
|
|
166
|
+
const targetPath = path.join(binDir, binaryName);
|
|
167
|
+
|
|
168
|
+
// Ensure bin directory exists
|
|
169
|
+
if (!fs.existsSync(binDir)) {
|
|
170
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Remove existing binary/symlink if it exists
|
|
174
|
+
if (fs.existsSync(targetPath)) {
|
|
175
|
+
fs.unlinkSync(targetPath);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return { binDir, targetPath };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Create symlink (or copy on Windows)
|
|
183
|
+
*/
|
|
184
|
+
function linkBinary(sourcePath, binaryName) {
|
|
185
|
+
const { targetPath } = prepareBinDirectory(binaryName);
|
|
186
|
+
|
|
187
|
+
if (os.platform() === "win32") {
|
|
188
|
+
// Windows: copy instead of symlink (symlinks require admin)
|
|
189
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
190
|
+
} else {
|
|
191
|
+
fs.symlinkSync(sourcePath, targetPath);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Verify the file exists
|
|
195
|
+
if (!fs.existsSync(targetPath)) {
|
|
196
|
+
throw new Error(`Failed to create binary at ${targetPath}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function main() {
|
|
201
|
+
try {
|
|
202
|
+
const packageName = getPackageName();
|
|
203
|
+
|
|
204
|
+
if (!packageName) {
|
|
205
|
+
console.error(`codex-wrapped-noyrlimit: Unsupported platform: ${os.platform()}-${os.arch()}`);
|
|
206
|
+
console.error("Please download the binary manually from:");
|
|
207
|
+
console.error("https://github.com/numman-ali/codex-wrapped/releases");
|
|
208
|
+
process.exit(0); // Exit gracefully
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
console.log(`codex-wrapped-noyrlimit: Detected platform package: ${packageName}`);
|
|
212
|
+
|
|
213
|
+
const result = findBinary(packageName);
|
|
214
|
+
|
|
215
|
+
if (!result) {
|
|
216
|
+
// Try fallback without baseline/musl
|
|
217
|
+
const baseParts = packageName.split("-").slice(0, 3);
|
|
218
|
+
const basePackage = baseParts.join("-");
|
|
219
|
+
|
|
220
|
+
if (basePackage !== packageName) {
|
|
221
|
+
console.log(`codex-wrapped-noyrlimit: Trying fallback package: ${basePackage}`);
|
|
222
|
+
const fallbackResult = findBinary(basePackage);
|
|
223
|
+
|
|
224
|
+
if (fallbackResult) {
|
|
225
|
+
linkBinary(fallbackResult.binaryPath, fallbackResult.binaryName);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
console.error(`codex-wrapped-noyrlimit: Could not find binary for ${packageName}`);
|
|
231
|
+
console.error("The optional dependency may have failed to install.");
|
|
232
|
+
console.error("Please download the binary manually from:");
|
|
233
|
+
console.error("https://github.com/numman-ali/codex-wrapped/releases");
|
|
234
|
+
process.exit(0);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
linkBinary(result.binaryPath, result.binaryName);
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.error("codex-wrapped-noyrlimit: Postinstall error:", error.message);
|
|
240
|
+
process.exit(0); // Exit gracefully to not break npm install
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
main();
|