ai-wrapped 1.2.0 → 1.3.1

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.
Files changed (41) hide show
  1. package/bin/cli.ts +238 -0
  2. package/dist/assets/index-BL7674T7.js +43 -0
  3. package/dist/assets/index-CFTgb0TD.css +1 -0
  4. package/{src/mainview → dist}/index.html +2 -1
  5. package/dist/tray-icon.png +0 -0
  6. package/dist/tray-icon@2x.png +0 -0
  7. package/package.json +24 -4
  8. package/tsconfig.json +1 -1
  9. package/.0spec/config.toml +0 -50
  10. package/.0spec/flows/ai-stats-build.toml +0 -291
  11. package/.0spec/flows/ai-stats-fix.toml +0 -285
  12. package/.0spec/flows/ai-stats.toml +0 -400
  13. package/.github/workflows/pages.yml +0 -31
  14. package/.github/workflows/publish.yml +0 -34
  15. package/.releaserc.json +0 -9
  16. package/AGENTS.md +0 -120
  17. package/bun.lock +0 -635
  18. package/docs/CNAME +0 -1
  19. package/docs/icon.png +0 -0
  20. package/docs/index.html +0 -581
  21. package/src/mainview/App.tsx +0 -40
  22. package/src/mainview/components/AgentBadge.tsx +0 -17
  23. package/src/mainview/components/Dashboard.tsx +0 -343
  24. package/src/mainview/components/DashboardCharts.tsx +0 -663
  25. package/src/mainview/components/EmptyState.tsx +0 -17
  26. package/src/mainview/components/Sidebar.tsx +0 -128
  27. package/src/mainview/components/StatsCards.tsx +0 -118
  28. package/src/mainview/hooks/modelKeys.test.ts +0 -35
  29. package/src/mainview/hooks/modelKeys.ts +0 -15
  30. package/src/mainview/hooks/useDashboardData.ts +0 -436
  31. package/src/mainview/hooks/useRPC.ts +0 -29
  32. package/src/mainview/index.css +0 -203
  33. package/src/mainview/index.ts +0 -12
  34. package/src/mainview/lib/constants.ts +0 -32
  35. package/src/mainview/lib/formatters.test.ts +0 -14
  36. package/src/mainview/lib/formatters.ts +0 -82
  37. package/src/types/electrobun-bun.d.ts +0 -117
  38. package/src/types/electrobun-root.d.ts +0 -3
  39. package/src/types/electrobun-view.d.ts +0 -38
  40. package/tsconfig.typecheck.json +0 -11
  41. package/vite.config.ts +0 -23
package/bin/cli.ts ADDED
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { dirname, join } from "node:path";
4
+
5
+ const PKG_ROOT = join(dirname(Bun.main), "..");
6
+ const HOME = Bun.env.HOME || Bun.env.USERPROFILE || "";
7
+ const CACHE_DIR = `${HOME}/.ai-wrapped/app`;
8
+ const VERSION_FILE = `${CACHE_DIR}/version.json`;
9
+
10
+ interface CachedBuild {
11
+ version: string;
12
+ platform: string;
13
+ arch: string;
14
+ builtAt: string;
15
+ }
16
+
17
+ async function readCachedBuild(): Promise<CachedBuild | null> {
18
+ const file = Bun.file(VERSION_FILE);
19
+ if (!(await file.exists())) return null;
20
+ try {
21
+ return (await file.json()) as CachedBuild;
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+
27
+ async function getPackageVersion(): Promise<string> {
28
+ const pkg = await Bun.file(join(PKG_ROOT, "package.json")).json();
29
+ return pkg.version;
30
+ }
31
+
32
+ async function ensureRuntimeBuildDependencies(): Promise<void> {
33
+ const electrobunPkg = Bun.file(
34
+ join(PKG_ROOT, "node_modules", "electrobun", "package.json"),
35
+ );
36
+ if (await electrobunPkg.exists()) return;
37
+
38
+ // bunx extracts ai-wrapped without node_modules, but electrobun expects
39
+ // ./node_modules/electrobun relative to the app root when building.
40
+ console.log(" Installing build dependencies...\n");
41
+ const proc = Bun.spawn([process.execPath, "install", "--production"], {
42
+ cwd: PKG_ROOT,
43
+ stdout: "inherit",
44
+ stderr: "inherit",
45
+ env: { ...process.env },
46
+ });
47
+
48
+ const exitCode = await proc.exited;
49
+ if (exitCode !== 0) {
50
+ throw new Error(`Dependency install failed with exit code ${exitCode}`);
51
+ }
52
+ }
53
+
54
+ async function buildApp(): Promise<string> {
55
+ const platform = process.platform;
56
+ const arch = process.arch;
57
+
58
+ // Electrobun build needs to run from the package root
59
+ console.log(" Building app (first run only)...\n");
60
+ await ensureRuntimeBuildDependencies();
61
+
62
+ // Run electrobun build from the package directory
63
+ const proc = Bun.spawn(["bunx", "electrobun", "build"], {
64
+ cwd: PKG_ROOT,
65
+ stdout: "inherit",
66
+ stderr: "inherit",
67
+ env: { ...process.env },
68
+ });
69
+
70
+ const exitCode = await proc.exited;
71
+ if (exitCode !== 0) {
72
+ throw new Error(`Build failed with exit code ${exitCode}`);
73
+ }
74
+
75
+ // Find the built .app
76
+ // Electrobun outputs to build/dev-{platform}-{arch}/ by default
77
+ const platformLabel =
78
+ platform === "darwin" ? "macos" : platform === "win32" ? "win" : "linux";
79
+ const buildDir = join(PKG_ROOT, "build", `dev-${platformLabel}-${arch}`);
80
+
81
+ if (platform === "darwin") {
82
+ const appPath = join(buildDir, "AI Wrapped-dev.app");
83
+ const exists = await Bun.file(join(appPath, "Contents", "Info.plist")).exists();
84
+ if (!exists) {
85
+ throw new Error(
86
+ `Build completed but app not found at ${appPath}. Check build output.`,
87
+ );
88
+ }
89
+ return appPath;
90
+ }
91
+
92
+ // Linux/Windows: return the build directory
93
+ return buildDir;
94
+ }
95
+
96
+ async function installToCache(builtPath: string): Promise<void> {
97
+ const platform = process.platform;
98
+
99
+ await Bun.$`mkdir -p ${CACHE_DIR}`.quiet();
100
+
101
+ if (platform === "darwin") {
102
+ // Copy .app bundle to cache
103
+ await Bun.$`rm -rf ${CACHE_DIR}/"AI Wrapped.app"`.quiet();
104
+ await Bun.$`cp -R ${builtPath} ${CACHE_DIR}/"AI Wrapped.app"`.quiet();
105
+ } else {
106
+ // Copy all files for linux/windows
107
+ await Bun.$`rm -rf ${CACHE_DIR}/app-files`.quiet();
108
+ await Bun.$`cp -R ${builtPath} ${CACHE_DIR}/app-files`.quiet();
109
+ }
110
+ }
111
+
112
+ async function launch(): Promise<void> {
113
+ const platform = process.platform;
114
+
115
+ if (platform === "darwin") {
116
+ const appPath = `${CACHE_DIR}/AI Wrapped.app`;
117
+ const plist = Bun.file(`${appPath}/Contents/Info.plist`);
118
+ if (!(await plist.exists())) {
119
+ throw new Error(
120
+ `App not found at ${appPath}. Try running with --rebuild.`,
121
+ );
122
+ }
123
+ console.log(" Launching AI Wrapped...");
124
+ await Bun.$`open ${appPath}`.quiet();
125
+ } else if (platform === "linux") {
126
+ console.log(" Launching AI Wrapped...");
127
+ Bun.spawn(["sh", "-c", `"${CACHE_DIR}/app-files/launcher" &`], {
128
+ stdout: "ignore",
129
+ stderr: "ignore",
130
+ });
131
+ } else if (platform === "win32") {
132
+ console.log(" Launching AI Wrapped...");
133
+ Bun.spawn(
134
+ ["cmd", "/c", "start", "", `${CACHE_DIR}\\app-files\\AI Wrapped.exe`],
135
+ { stdout: "ignore", stderr: "ignore" },
136
+ );
137
+ }
138
+ }
139
+
140
+ async function main() {
141
+ const platform = process.platform;
142
+ const arch = process.arch;
143
+
144
+ console.log("");
145
+ console.log(" \x1b[1mAI Wrapped\x1b[0m");
146
+ console.log(" Your year in AI\n");
147
+
148
+ // --help
149
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
150
+ console.log(" Usage: ai-wrapped [options]\n");
151
+ console.log(" Options:");
152
+ console.log(" --version, -v Show installed version");
153
+ console.log(" --rebuild Force rebuild the app");
154
+ console.log(" --uninstall Remove cached app");
155
+ console.log(" --help, -h Show this help");
156
+ return;
157
+ }
158
+
159
+ // --version
160
+ if (process.argv.includes("--version") || process.argv.includes("-v")) {
161
+ const cached = await readCachedBuild();
162
+ const pkgVersion = await getPackageVersion();
163
+ console.log(` Package: v${pkgVersion}`);
164
+ console.log(
165
+ cached
166
+ ? ` Installed: v${cached.version} (${cached.platform}/${cached.arch})`
167
+ : " Not built yet",
168
+ );
169
+ return;
170
+ }
171
+
172
+ // --uninstall
173
+ if (process.argv.includes("--uninstall")) {
174
+ console.log(" Removing ~/.ai-wrapped...");
175
+ if (platform === "win32") {
176
+ await Bun.$`powershell -Command "Remove-Item -Recurse -Force '${HOME}/.ai-wrapped' -ErrorAction SilentlyContinue"`.quiet();
177
+ } else {
178
+ await Bun.$`rm -rf ${HOME}/.ai-wrapped`.quiet();
179
+ }
180
+ console.log(" Done.");
181
+ return;
182
+ }
183
+
184
+ const forceRebuild = process.argv.includes("--rebuild");
185
+
186
+ // Check if we need to build
187
+ const pkgVersion = await getPackageVersion();
188
+ const cached = await readCachedBuild();
189
+ const platformLabel =
190
+ platform === "darwin" ? "macos" : platform === "win32" ? "win" : "linux";
191
+ const needsBuild =
192
+ forceRebuild ||
193
+ !cached ||
194
+ cached.version !== pkgVersion ||
195
+ cached.platform !== platformLabel ||
196
+ cached.arch !== arch;
197
+
198
+ if (needsBuild) {
199
+ if (cached && !forceRebuild) {
200
+ console.log(
201
+ ` Upgrading v${cached.version} \u2192 v${pkgVersion}`,
202
+ );
203
+ } else if (!forceRebuild) {
204
+ console.log(` First run — building v${pkgVersion}...`);
205
+ } else {
206
+ console.log(` Rebuilding v${pkgVersion}...`);
207
+ }
208
+
209
+ const builtPath = await buildApp();
210
+ await installToCache(builtPath);
211
+
212
+ // Write version cache
213
+ await Bun.write(
214
+ VERSION_FILE,
215
+ JSON.stringify(
216
+ {
217
+ version: pkgVersion,
218
+ platform: platformLabel,
219
+ arch,
220
+ builtAt: new Date().toISOString(),
221
+ },
222
+ null,
223
+ 2,
224
+ ),
225
+ );
226
+
227
+ console.log(`\n Built and cached v${pkgVersion}\n`);
228
+ } else {
229
+ console.log(` v${pkgVersion} ready\n`);
230
+ }
231
+
232
+ await launch();
233
+ }
234
+
235
+ main().catch((err) => {
236
+ console.error(`\n Error: ${(err as Error).message}`);
237
+ process.exit(1);
238
+ });