@juliantanx/aiusage-widget 1.3.2 → 1.3.4
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 +1 -1
- package/README_zh.md +1 -1
- package/bin/install-native.js +121 -0
- package/bin/launcher.js +1 -1
- package/bin/prepare-native.js +43 -0
- package/dist/main.js +27 -24
- package/dist/native/better_sqlite3.node +0 -0
- package/dist/renderer/assets/index-CArY3S1D.js +2 -0
- package/dist/renderer/assets/index-D6oVYB8t.css +1 -0
- package/dist/renderer/index.html +2 -2
- package/dist/ui.js +43 -18
- package/package.json +10 -7
- package/dist/renderer/assets/index-2X4hbwJe.css +0 -1
- package/dist/renderer/assets/index-Bb9mog0W.js +0 -1
package/README.md
CHANGED
package/README_zh.md
CHANGED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* postinstall: produce a better-sqlite3 native binding that matches BOTH the
|
|
4
|
+
* end user's platform/arch AND Electron's ABI, and place it at
|
|
5
|
+
* dist/native/better_sqlite3.node (where main.ts loads it via `nativeBinding`).
|
|
6
|
+
*
|
|
7
|
+
* Why this exists:
|
|
8
|
+
* - Electron embeds its own Node, so a binding compiled for the system Node
|
|
9
|
+
* ABI fails to load inside Electron, and vice versa.
|
|
10
|
+
* - The published package cannot ship a single prebuilt binary, because that
|
|
11
|
+
* binary is locked to the platform/arch of the machine that built it
|
|
12
|
+
* (the CI runner). On any other OS/arch it is unloadable.
|
|
13
|
+
*
|
|
14
|
+
* Strategy: download the prebuilt better-sqlite3 binary for `electron` runtime
|
|
15
|
+
* matching the locally installed Electron version, this platform, and this
|
|
16
|
+
* arch. We run prebuild-install inside a throwaway copy of better-sqlite3's
|
|
17
|
+
* package.json so we never clobber the shared better-sqlite3 build/Release
|
|
18
|
+
* (the CLI package relies on its Node-ABI binding in a pnpm workspace).
|
|
19
|
+
*
|
|
20
|
+
* Best-effort: a failure here (e.g. offline install, or no prebuilt for an
|
|
21
|
+
* exotic platform) prints a warning but does not fail `npm install`; any
|
|
22
|
+
* binary shipped in dist/native remains as a last-resort fallback.
|
|
23
|
+
*/
|
|
24
|
+
const { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, rmSync } = require('node:fs')
|
|
25
|
+
const { dirname, join } = require('node:path')
|
|
26
|
+
const { execFileSync } = require('node:child_process')
|
|
27
|
+
const { tmpdir } = require('node:os')
|
|
28
|
+
|
|
29
|
+
const widgetRoot = join(__dirname, '..')
|
|
30
|
+
|
|
31
|
+
function warn(message) {
|
|
32
|
+
console.warn(`[aiusage-widget] ${message}`)
|
|
33
|
+
console.warn('[aiusage-widget] the tray widget may fail to open the usage database until this is resolved.')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveElectronVersion() {
|
|
37
|
+
try {
|
|
38
|
+
return require('electron/package.json').version
|
|
39
|
+
} catch {
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function main() {
|
|
45
|
+
const electronVersion = resolveElectronVersion()
|
|
46
|
+
if (!electronVersion) {
|
|
47
|
+
warn('could not resolve the installed electron version; skipping native binding setup.')
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let betterSqlite3Pkg
|
|
52
|
+
try {
|
|
53
|
+
betterSqlite3Pkg = require.resolve('better-sqlite3/package.json')
|
|
54
|
+
} catch {
|
|
55
|
+
warn('could not locate better-sqlite3; skipping native binding setup.')
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
const betterSqlite3Dir = dirname(betterSqlite3Pkg)
|
|
59
|
+
|
|
60
|
+
let prebuildInstallBin
|
|
61
|
+
try {
|
|
62
|
+
prebuildInstallBin = require.resolve('prebuild-install/bin.js', { paths: [betterSqlite3Dir] })
|
|
63
|
+
} catch {
|
|
64
|
+
warn('could not locate prebuild-install; skipping native binding setup.')
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Run prebuild-install against a disposable copy of better-sqlite3's
|
|
69
|
+
// package.json so the shared install (used by the Node-side CLI) is untouched.
|
|
70
|
+
const stageDir = join(tmpdir(), `aiusage-widget-native-${process.pid}`)
|
|
71
|
+
try {
|
|
72
|
+
mkdirSync(stageDir, { recursive: true })
|
|
73
|
+
writeFileSync(join(stageDir, 'package.json'), readFileSync(betterSqlite3Pkg))
|
|
74
|
+
|
|
75
|
+
execFileSync(
|
|
76
|
+
process.execPath,
|
|
77
|
+
[
|
|
78
|
+
prebuildInstallBin,
|
|
79
|
+
'--runtime=electron',
|
|
80
|
+
`--target=${electronVersion}`,
|
|
81
|
+
`--arch=${process.arch}`,
|
|
82
|
+
`--platform=${process.platform}`,
|
|
83
|
+
],
|
|
84
|
+
{ cwd: stageDir, stdio: 'inherit' },
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
const built = join(stageDir, 'build', 'Release', 'better_sqlite3.node')
|
|
88
|
+
if (!existsSync(built)) {
|
|
89
|
+
warn('prebuild-install completed but produced no binary; skipping native binding setup.')
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const nativeDir = join(widgetRoot, 'dist', 'native')
|
|
94
|
+
mkdirSync(nativeDir, { recursive: true })
|
|
95
|
+
const target = join(nativeDir, 'better_sqlite3.node')
|
|
96
|
+
copyFileSync(built, target)
|
|
97
|
+
|
|
98
|
+
if (process.platform === 'darwin') {
|
|
99
|
+
// Ad-hoc sign so Gatekeeper / hardened runtime will load the binding.
|
|
100
|
+
try {
|
|
101
|
+
execFileSync('codesign', ['--force', '--sign', '-', target], { stdio: 'inherit' })
|
|
102
|
+
} catch {
|
|
103
|
+
// Non-fatal: unsigned binaries still load in most local setups.
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.log(
|
|
108
|
+
`[aiusage-widget] installed better-sqlite3 binding for electron ${electronVersion} (${process.platform}-${process.arch}).`,
|
|
109
|
+
)
|
|
110
|
+
} catch (error) {
|
|
111
|
+
warn(`failed to set up the native binding: ${error && error.message ? error.message : error}`)
|
|
112
|
+
} finally {
|
|
113
|
+
try {
|
|
114
|
+
rmSync(stageDir, { recursive: true, force: true })
|
|
115
|
+
} catch {
|
|
116
|
+
// ignore cleanup failures
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
main()
|
package/bin/launcher.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const { spawn } = require('child_process')
|
|
3
|
-
const { writeFileSync, mkdirSync }
|
|
3
|
+
const { writeFileSync, mkdirSync } = require('fs')
|
|
4
4
|
const { homedir } = require('os')
|
|
5
5
|
const electron = require('electron')
|
|
6
6
|
const path = require('path')
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { copyFileSync, mkdirSync } = require('node:fs')
|
|
3
|
+
const { dirname, join } = require('node:path')
|
|
4
|
+
const { execFileSync } = require('node:child_process')
|
|
5
|
+
const { rebuild } = require('@electron/rebuild')
|
|
6
|
+
|
|
7
|
+
const widgetRoot = join(__dirname, '..')
|
|
8
|
+
const nativeSource = join(
|
|
9
|
+
dirname(require.resolve('better-sqlite3/package.json')),
|
|
10
|
+
'build',
|
|
11
|
+
'Release',
|
|
12
|
+
'better_sqlite3.node'
|
|
13
|
+
)
|
|
14
|
+
const nativeDir = join(widgetRoot, 'dist', 'native')
|
|
15
|
+
const nativeTarget = join(nativeDir, 'better_sqlite3.node')
|
|
16
|
+
|
|
17
|
+
async function main() {
|
|
18
|
+
const electronVersion = require('electron/package.json').version
|
|
19
|
+
|
|
20
|
+
await rebuild({
|
|
21
|
+
buildPath: widgetRoot,
|
|
22
|
+
electronVersion,
|
|
23
|
+
onlyModules: ['better-sqlite3'],
|
|
24
|
+
force: true,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
mkdirSync(nativeDir, { recursive: true })
|
|
28
|
+
copyFileSync(nativeSource, nativeTarget)
|
|
29
|
+
|
|
30
|
+
if (process.platform === 'darwin') {
|
|
31
|
+
execFileSync('codesign', ['--force', '--sign', '-', nativeTarget], { stdio: 'inherit' })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
execFileSync('npm', ['run', 'install'], {
|
|
35
|
+
cwd: dirname(require.resolve('better-sqlite3/package.json')),
|
|
36
|
+
stdio: 'inherit',
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
main().catch((error) => {
|
|
41
|
+
console.error(error)
|
|
42
|
+
process.exit(1)
|
|
43
|
+
})
|
package/dist/main.js
CHANGED
|
@@ -23,7 +23,10 @@ if (process.platform === 'darwin' && electron_1.app.dock) {
|
|
|
23
23
|
}
|
|
24
24
|
electron_1.app.whenReady().then(() => {
|
|
25
25
|
if ((0, node_fs_1.existsSync)(DB_PATH)) {
|
|
26
|
-
db = new Database(DB_PATH, {
|
|
26
|
+
db = new Database(DB_PATH, {
|
|
27
|
+
readonly: true,
|
|
28
|
+
nativeBinding: (0, ui_1.getWidgetNativeBindingPath)(__dirname),
|
|
29
|
+
});
|
|
27
30
|
}
|
|
28
31
|
createTray();
|
|
29
32
|
createWindow();
|
|
@@ -39,13 +42,10 @@ electron_1.app.on('before-quit', () => {
|
|
|
39
42
|
db?.close();
|
|
40
43
|
});
|
|
41
44
|
function createTray() {
|
|
42
|
-
const
|
|
45
|
+
const { buffer, scaleFactor } = (0, ui_1.getTrayIconNativeImage)();
|
|
46
|
+
const icon = electron_1.nativeImage.createFromBuffer(buffer, scaleFactor ? { scaleFactor } : undefined);
|
|
43
47
|
tray = new electron_1.Tray(icon);
|
|
44
48
|
tray.setToolTip('aiusage Widget');
|
|
45
|
-
// On macOS, SVG icons silently fail — use a text label as the visible entry
|
|
46
|
-
if (process.platform === 'darwin') {
|
|
47
|
-
tray.setTitle('⚡');
|
|
48
|
-
}
|
|
49
49
|
tray.on('click', () => toggleWindow());
|
|
50
50
|
tray.on('right-click', () => {
|
|
51
51
|
const menu = electron_1.Menu.buildFromTemplate([
|
|
@@ -85,10 +85,13 @@ function showWindow() {
|
|
|
85
85
|
// Position near tray icon
|
|
86
86
|
const trayBounds = tray.getBounds();
|
|
87
87
|
const winBounds = win.getBounds();
|
|
88
|
-
const
|
|
89
|
-
const y =
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
const displayBounds = electron_1.screen.getDisplayNearestPoint({ x: trayBounds.x, y: trayBounds.y }).workArea;
|
|
89
|
+
const { x, y } = (0, ui_1.getWindowPosition)({
|
|
90
|
+
platform: process.platform,
|
|
91
|
+
trayBounds,
|
|
92
|
+
windowBounds: winBounds,
|
|
93
|
+
displayBounds,
|
|
94
|
+
});
|
|
92
95
|
win.setPosition(x, y, false);
|
|
93
96
|
win.show();
|
|
94
97
|
win.focus();
|
|
@@ -156,7 +159,8 @@ async function isDashboardReachable(port) {
|
|
|
156
159
|
resolve(res.statusCode !== undefined && res.statusCode < 500);
|
|
157
160
|
});
|
|
158
161
|
req.on('error', () => resolve(false));
|
|
159
|
-
|
|
162
|
+
// 200ms is plenty for localhost; 1000ms caused each poll to block for 1s
|
|
163
|
+
req.setTimeout(200, () => { req.destroy(); resolve(false); });
|
|
160
164
|
});
|
|
161
165
|
}
|
|
162
166
|
async function launchDashboard() {
|
|
@@ -167,21 +171,20 @@ async function launchDashboard() {
|
|
|
167
171
|
stdio: 'ignore',
|
|
168
172
|
shell: true,
|
|
169
173
|
});
|
|
170
|
-
let
|
|
171
|
-
child.on('error', (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
174
|
+
let failed = false;
|
|
175
|
+
child.on('error', () => { failed = true; });
|
|
176
|
+
// shell:true suppresses ENOENT on the error event — the shell itself spawns fine
|
|
177
|
+
// but exits immediately (code 127) when the command isn't found. Detect that here.
|
|
178
|
+
child.on('close', (code) => {
|
|
179
|
+
if (code !== 0)
|
|
180
|
+
failed = true;
|
|
178
181
|
});
|
|
179
182
|
child.unref();
|
|
180
|
-
//
|
|
183
|
+
// Poll up to 5s (25 × 200ms) for the server to become reachable
|
|
181
184
|
let attempts = 0;
|
|
182
185
|
const check = async () => {
|
|
183
|
-
if (
|
|
184
|
-
resolve({ success: false, error:
|
|
186
|
+
if (failed) {
|
|
187
|
+
resolve({ success: false, error: 'aiusage command not found' });
|
|
185
188
|
return;
|
|
186
189
|
}
|
|
187
190
|
if (await isDashboardReachable(getDashboardPort())) {
|
|
@@ -189,11 +192,11 @@ async function launchDashboard() {
|
|
|
189
192
|
return;
|
|
190
193
|
}
|
|
191
194
|
attempts++;
|
|
192
|
-
if (attempts >=
|
|
195
|
+
if (attempts >= 25) {
|
|
193
196
|
resolve({ success: false, error: 'Server failed to start within 5 seconds' });
|
|
194
197
|
return;
|
|
195
198
|
}
|
|
196
|
-
setTimeout(check,
|
|
199
|
+
setTimeout(check, 200);
|
|
197
200
|
};
|
|
198
201
|
check();
|
|
199
202
|
});
|
|
Binary file
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var se=Object.defineProperty;var ie=(e,t,n)=>t in e?se(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var z=(e,t,n)=>ie(e,typeof t!="symbol"?t+"":t,n);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))o(r);new MutationObserver(r=>{for(const s of r)if(s.type==="childList")for(const f of s.addedNodes)f.tagName==="LINK"&&f.rel==="modulepreload"&&o(f)}).observe(document,{childList:!0,subtree:!0});function n(r){const s={};return r.integrity&&(s.integrity=r.integrity),r.referrerPolicy&&(s.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?s.credentials="include":r.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function o(r){if(r.ep)return;r.ep=!0;const s=n(r);fetch(r.href,s)}})();function w(){}function re(e){return e()}function X(){return Object.create(null)}function T(e){e.forEach(re)}function R(e){return typeof e=="function"}function Y(e,t){return e!=e?t==t:e!==t||e&&typeof e=="object"||typeof e=="function"}function le(e){return Object.keys(e).length===0}function d(e,t){e.appendChild(t)}function I(e,t,n){e.insertBefore(t,n||null)}function M(e){e.parentNode&&e.parentNode.removeChild(e)}function g(e){return document.createElement(e)}function F(e){return document.createTextNode(e)}function _(){return F(" ")}function K(e,t,n,o){return e.addEventListener(t,n,o),()=>e.removeEventListener(t,n,o)}function p(e,t,n){n==null?e.removeAttribute(t):e.getAttribute(t)!==n&&e.setAttribute(t,n)}function fe(e){return Array.from(e.childNodes)}function U(e,t){t=""+t,e.data!==t&&(e.data=t)}function Z(e,t,n){e.classList.toggle(t,!!n)}let L;function x(e){L=e}function ce(){if(!L)throw new Error("Function called outside component initialization");return L}function ue(e){ce().$$.on_mount.push(e)}const $=[],ee=[];let k=[];const te=[],ae=Promise.resolve();let V=!1;function de(){V||(V=!0,ae.then(oe))}function W(e){k.push(e)}const B=new Set;let v=0;function oe(){if(v!==0)return;const e=L;do{try{for(;v<$.length;){const t=$[v];v++,x(t),he(t.$$)}}catch(t){throw $.length=0,v=0,t}for(x(null),$.length=0,v=0;ee.length;)ee.pop()();for(let t=0;t<k.length;t+=1){const n=k[t];B.has(n)||(B.add(n),n())}k.length=0}while($.length);for(;te.length;)te.pop()();V=!1,B.clear(),x(e)}function he(e){if(e.fragment!==null){e.update(),T(e.before_update);const t=e.dirty;e.dirty=[-1],e.fragment&&e.fragment.p(e.ctx,t),e.after_update.forEach(W)}}function pe(e){const t=[],n=[];k.forEach(o=>e.indexOf(o)===-1?t.push(o):n.push(o)),n.forEach(o=>o()),k=t}const P=new Set;let ge;function O(e,t){e&&e.i&&(P.delete(e),e.i(t))}function N(e,t,n,o){if(e&&e.o){if(P.has(e))return;P.add(e),ge.c.push(()=>{P.delete(e)}),e.o(t)}}function A(e){e&&e.c()}function E(e,t,n){const{fragment:o,after_update:r}=e.$$;o&&o.m(t,n),W(()=>{const s=e.$$.on_mount.map(re).filter(R);e.$$.on_destroy?e.$$.on_destroy.push(...s):T(s),e.$$.on_mount=[]}),r.forEach(W)}function C(e,t){const n=e.$$;n.fragment!==null&&(pe(n.after_update),T(n.on_destroy),n.fragment&&n.fragment.d(t),n.on_destroy=n.fragment=null,n.ctx=[])}function me(e,t){e.$$.dirty[0]===-1&&($.push(e),de(),e.$$.dirty.fill(0)),e.$$.dirty[t/31|0]|=1<<t%31}function G(e,t,n,o,r,s,f=null,h=[-1]){const l=L;x(e);const i=e.$$={fragment:null,ctx:[],props:s,update:w,not_equal:r,bound:X(),on_mount:[],on_destroy:[],on_disconnect:[],before_update:[],after_update:[],context:new Map(t.context||(l?l.$$.context:[])),callbacks:X(),dirty:h,skip_bound:!1,root:t.target||l.$$.root};f&&f(i.root);let u=!1;if(i.ctx=n?n(e,t.props||{},(c,m,...b)=>{const S=b.length?b[0]:m;return i.ctx&&r(i.ctx[c],i.ctx[c]=S)&&(!i.skip_bound&&i.bound[c]&&i.bound[c](S),u&&me(e,c)),m}):[],i.update(),u=!0,T(i.before_update),i.fragment=o?o(i.ctx):!1,t.target){if(t.hydrate){const c=fe(t.target);i.fragment&&i.fragment.l(c),c.forEach(M)}else i.fragment&&i.fragment.c();t.intro&&O(e.$$.fragment),E(e,t.target,t.anchor),oe()}x(l)}class J{constructor(){z(this,"$$");z(this,"$$set")}$destroy(){C(this,1),this.$destroy=w}$on(t,n){if(!R(n))return w;const o=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return o.push(n),()=>{const r=o.indexOf(n);r!==-1&&o.splice(r,1)}}$set(t){this.$$set&&!le(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}}const ye="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(ye);function _e(e){let t,n,o,r,s,f,h,l,i;return{c(){t=g("div"),n=g("span"),n.innerHTML=`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 64 64" style="display:block;border-radius:4px"><rect width="64" height="64" rx="14" fill="#0d9488"></rect><rect x="10" y="38" width="12" height="16" rx="3" fill="white"></rect><rect x="26" y="26" width="12" height="28" rx="3" fill="white"></rect><rect x="42" y="14" width="12" height="40" rx="3" fill="white"></rect></svg>
|
|
2
|
+
aiusage`,o=_(),r=g("div"),s=g("button"),s.textContent="↻",f=_(),h=g("button"),h.textContent="✕",p(n,"class","logo svelte-soepgf"),p(s,"class","icon-btn svelte-soepgf"),p(s,"title","Refresh"),p(h,"class","icon-btn svelte-soepgf"),p(h,"title","Close"),p(r,"class","actions svelte-soepgf"),p(t,"class","header svelte-soepgf")},m(u,c){I(u,t,c),d(t,n),d(t,o),d(t,r),d(r,s),d(r,f),d(r,h),l||(i=[K(s,"click",function(){R(e[0])&&e[0].apply(this,arguments)}),K(h,"click",function(){R(e[1])&&e[1].apply(this,arguments)})],l=!0)},p(u,[c]){e=u},i:w,o:w,d(u){u&&M(t),l=!1,T(i)}}}function we(e,t,n){let{onRefresh:o}=t,{onClose:r}=t;return e.$$set=s=>{"onRefresh"in s&&n(0,o=s.onRefresh),"onClose"in s&&n(1,r=s.onClose)},[o,r]}class be extends J{constructor(t){super(),G(this,t,we,_e,Y,{onRefresh:0,onClose:1})}}function ne(e){let t,n;return{c(){t=g("span"),n=F(e[2]),p(t,"class","secondary svelte-savwyt")},m(o,r){I(o,t,r),d(t,n)},p(o,r){r&4&&U(n,o[2])},d(o){o&&M(t)}}}function ve(e){let t,n,o,r,s,f,h,l,i=e[2]&&ne(e);return{c(){t=g("div"),n=g("div"),o=F(e[0]),r=_(),s=g("div"),f=g("span"),h=F(e[1]),l=_(),i&&i.c(),p(n,"class","section-label svelte-savwyt"),p(f,"class","primary svelte-savwyt"),p(s,"class","values svelte-savwyt"),p(t,"class","section svelte-savwyt")},m(u,c){I(u,t,c),d(t,n),d(n,o),d(t,r),d(t,s),d(s,f),d(f,h),d(s,l),i&&i.m(s,null)},p(u,[c]){c&1&&U(o,u[0]),c&2&&U(h,u[1]),u[2]?i?i.p(u,c):(i=ne(u),i.c(),i.m(s,null)):i&&(i.d(1),i=null)},i:w,o:w,d(u){u&&M(t),i&&i.d()}}}function $e(e,t,n){let{label:o}=t,{primary:r}=t,{secondary:s=""}=t;return e.$$set=f=>{"label"in f&&n(0,o=f.label),"primary"in f&&n(1,r=f.primary),"secondary"in f&&n(2,s=f.secondary)},[o,r,s]}class H extends J{constructor(t){super(),G(this,t,$e,ve,Y,{label:0,primary:1,secondary:2})}}function ke(e){let t,n,o,r,s,f,h,l,i,u,c,m,b,S;return n=new be({props:{onRefresh:e[6],onClose:Se}}),r=new H({props:{label:"TODAY",primary:e[5],secondary:e[4]}}),f=new H({props:{label:"THIS MONTH",primary:e[3]}}),l=new H({props:{label:"TOP MODEL",primary:e[2],secondary:e[1]}}),{c(){t=g("div"),A(n.$$.fragment),o=_(),A(r.$$.fragment),s=_(),A(f.$$.fragment),h=_(),A(l.$$.fragment),i=_(),u=g("div"),c=g("button"),c.textContent="Open Full Dashboard →",p(c,"class","open-btn svelte-z2p4qk"),p(u,"class","footer svelte-z2p4qk"),p(t,"class","panel svelte-z2p4qk"),Z(t,"loading",e[0])},m(a,y){I(a,t,y),E(n,t,null),d(t,o),E(r,t,null),d(t,s),E(f,t,null),d(t,h),E(l,t,null),d(t,i),d(t,u),d(u,c),m=!0,b||(S=K(c,"click",Oe),b=!0)},p(a,[y]){const j={};y&32&&(j.primary=a[5]),y&16&&(j.secondary=a[4]),r.$set(j);const Q={};y&8&&(Q.primary=a[3]),f.$set(Q);const q={};y&4&&(q.primary=a[2]),y&2&&(q.secondary=a[1]),l.$set(q),(!m||y&1)&&Z(t,"loading",a[0])},i(a){m||(O(n.$$.fragment,a),O(r.$$.fragment,a),O(f.$$.fragment,a),O(l.$$.fragment,a),m=!0)},o(a){N(n.$$.fragment,a),N(r.$$.fragment,a),N(f.$$.fragment,a),N(l.$$.fragment,a),m=!1},d(a){a&&M(t),C(n),C(r),C(f),C(l),b=!1,S()}}}function D(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:String(e)}function Se(){window.widget.hideWindow()}async function Oe(){await window.widget.openDashboard()}function Ee(e,t,n){let o,r,s,f,h,l=null,i=!0;async function u(){n(0,i=!0),n(7,l=await window.widget.getData()),n(0,i=!1)}return ue(()=>{u(),window.widget.onDataUpdate(c=>{n(7,l=c),n(0,i=!1)})}),e.$$.update=()=>{var c;e.$$.dirty&128&&n(5,o=l?D(l.todayTokens.total):"—"),e.$$.dirty&128&&n(4,r=l?`↑${D(l.todayTokens.input)} ↓${D(l.todayTokens.output)}`:""),e.$$.dirty&128&&n(3,s=l?D(l.monthTokens.total):"—"),e.$$.dirty&128&&n(2,f=((c=l==null?void 0:l.topModel)==null?void 0:c.name)??"—"),e.$$.dirty&128&&n(1,h=l!=null&&l.topModel?`${l.topModel.share}%`:"")},[i,h,f,s,r,o,u,l]}class Ce extends J{constructor(t){super(),G(this,t,Ee,ke,Y,{})}}new Ce({target:document.getElementById("app")});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.header.svelte-soepgf{display:flex;align-items:center;justify-content:space-between;padding:12px 14px 10px;border-bottom:1px solid var(--border);-webkit-app-region:drag}.logo.svelte-soepgf{display:flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--text-primary);letter-spacing:.01em}.actions.svelte-soepgf{display:flex;gap:4px;-webkit-app-region:no-drag}.icon-btn.svelte-soepgf{width:24px;height:24px;border:none;border-radius:4px;background:transparent;color:var(--text-muted);cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;transition:background .1s,color .1s;padding:0}.icon-btn.svelte-soepgf:hover{background:var(--bg-hover);color:var(--text-primary)}.section.svelte-savwyt{padding:12px 14px;border-bottom:1px solid var(--border)}.section-label.svelte-savwyt{font-size:10px;font-weight:700;letter-spacing:.08em;color:var(--text-muted);text-transform:uppercase;margin-bottom:5px}.values.svelte-savwyt{display:flex;align-items:baseline;gap:8px}.primary.svelte-savwyt{font-size:16px;font-weight:600;color:var(--text-primary);font-variant-numeric:tabular-nums}.secondary.svelte-savwyt{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums}*{box-sizing:border-box;margin:0;padding:0}body{background:transparent;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;-webkit-font-smoothing:antialiased}:root{--bg:#1a1a1f;--bg-hover:rgba(255, 255, 255, .06);--border:rgba(255, 255, 255, .08);--text-primary:#f0f0f2;--text-muted:rgba(240, 240, 242, .45);--accent:#6c8eff}@media (prefers-color-scheme: light){:root{--bg:#ffffff;--bg-hover:rgba(0, 0, 0, .05);--border:rgba(0, 0, 0, .08);--text-primary:#0f0f12;--text-muted:rgba(15, 15, 18, .45);--accent:#3b5bdb}}.panel.svelte-z2p4qk{background:var(--bg);border-radius:12px;border:1px solid var(--border);overflow:hidden;width:320px;box-shadow:0 8px 32px #0000004d,0 2px 8px #0003;transition:opacity .15s}.panel.loading.svelte-z2p4qk{opacity:.7}.footer.svelte-z2p4qk{padding:10px 14px 14px}.open-btn.svelte-z2p4qk{width:100%;padding:9px 14px;border:1px solid var(--accent);border-radius:7px;background:transparent;color:var(--accent);font-size:12px;font-weight:600;cursor:pointer;transition:background .15s;letter-spacing:.01em}.open-btn.svelte-z2p4qk:hover{background:#6c8eff1a}
|
package/dist/renderer/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" />
|
|
7
7
|
<title>aiusage Widget</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-CArY3S1D.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-D6oVYB8t.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="app"></div>
|
package/dist/ui.js
CHANGED
|
@@ -3,19 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.shouldShowWindowOnLaunch = shouldShowWindowOnLaunch;
|
|
4
4
|
exports.shouldHideWindowOnBlur = shouldHideWindowOnBlur;
|
|
5
5
|
exports.shouldHideWindowOnClose = shouldHideWindowOnClose;
|
|
6
|
-
exports.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
'
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
'
|
|
6
|
+
exports.getWindowPosition = getWindowPosition;
|
|
7
|
+
exports.getWidgetNativeBindingPath = getWidgetNativeBindingPath;
|
|
8
|
+
exports.getTrayIconNativeImage = getTrayIconNativeImage;
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
// macOS: 32x32 PNG rendered at @2x — displayed as 16x16 logical on Retina via scaleFactor:2
|
|
11
|
+
const TRAY_ICON_PNG_MAC_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAsklEQVR4nO2XQQ7EIAhFuQBX8HQe' +
|
|
12
|
+
'hu7Z9U6z8TZu2jSxjekwYxpUuoCEjRr+EzEBgMqQKSDTgkwJmTIybZ08l5hH7ACSIVPsLPoPJkri' +
|
|
13
|
+
'o4XvHuu0z7i5lIkA5V1mi5++QCkOK4AERum/ngFGBF7TZ7vbsSadHQLwyxzAAboBtKp8OEBLwAEc' +
|
|
14
|
+
'QA2grXI1gFbAARzgKcBXSzYRIItNaesbavcrT69oy20HE/PR7BXDqeV4vgPnux87hsqGswAAAABJ' +
|
|
15
|
+
'RU5ErkJggg==';
|
|
16
|
+
// Windows: 16x16 PNG
|
|
17
|
+
const TRAY_ICON_PNG_WIN_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAaElEQVR4nGNgYGBg4J3Skco7peMa' +
|
|
18
|
+
'75SO/0RikNpUBiTNxGpEx6kMJNqM4RIGYhVbr5j/v+3UETAGsWHiRBsA0ggDIDbtDUB3MskGoGug' +
|
|
19
|
+
'vQGEnEzQAEIaBrcB17CFASE+clKmLDNRmp0B5XqLc//RXPMAAAAASUVORK5CYII=';
|
|
20
|
+
// Linux: 22x22 PNG
|
|
21
|
+
const TRAY_ICON_PNG_LINUX_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAt0lEQVR4nGNggALeKR3ZvFM6zvJO' +
|
|
22
|
+
'6fjDO6XjP4n4D1RvNgMy4J3SsYAMw3DhBcgupZahMJzNAPUCtQ0+y0BmmIKx1Yp5cIwe5gzkGtp+' +
|
|
23
|
+
'6sh/ZADiI8uTbfDUC6dRDAbxB5fBMrP7wZiqBt//+B5uAIhNFYNBrkQHILFhbnDuvu3/P/z4AccQ' +
|
|
24
|
+
'PlUMxqZ4ZBn8hwYG/0EpNk2WzgYrgGEQHyRefXQfXAzExqcWis/SrqCnWdVEq8oUAE+RyDWaecD7' +
|
|
25
|
+
'AAAAAElFTkSuQmCC';
|
|
19
26
|
function shouldShowWindowOnLaunch(isPackaged) {
|
|
20
27
|
return !isPackaged;
|
|
21
28
|
}
|
|
@@ -25,10 +32,28 @@ function shouldHideWindowOnBlur(isPackaged) {
|
|
|
25
32
|
function shouldHideWindowOnClose(_) {
|
|
26
33
|
return true;
|
|
27
34
|
}
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
function getWindowPosition({ platform, trayBounds, windowBounds, displayBounds, }) {
|
|
36
|
+
const preferredX = Math.round(trayBounds.x + trayBounds.width / 2 - windowBounds.width / 2);
|
|
37
|
+
const preferredY = platform === 'darwin'
|
|
38
|
+
? trayBounds.y + trayBounds.height + 4
|
|
39
|
+
: trayBounds.y - windowBounds.height - 4;
|
|
40
|
+
const maxX = Math.max(displayBounds.x, displayBounds.x + displayBounds.width - windowBounds.width);
|
|
41
|
+
const maxY = Math.max(displayBounds.y, displayBounds.y + displayBounds.height - windowBounds.height);
|
|
42
|
+
return {
|
|
43
|
+
x: Math.min(Math.max(preferredX, displayBounds.x), maxX),
|
|
44
|
+
y: Math.min(Math.max(preferredY, displayBounds.y), maxY),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function getWidgetNativeBindingPath(baseDir) {
|
|
48
|
+
return (0, node_path_1.join)(baseDir, 'native', 'better_sqlite3.node');
|
|
49
|
+
}
|
|
50
|
+
function getTrayIconNativeImage() {
|
|
51
|
+
if (process.platform === 'darwin') {
|
|
52
|
+
// 32x32 PNG at scaleFactor 2 = renders as 16x16 logical, sharp on Retina
|
|
53
|
+
return { buffer: Buffer.from(TRAY_ICON_PNG_MAC_BASE64, 'base64'), scaleFactor: 2 };
|
|
54
|
+
}
|
|
55
|
+
if (process.platform === 'linux') {
|
|
56
|
+
return { buffer: Buffer.from(TRAY_ICON_PNG_LINUX_BASE64, 'base64') };
|
|
32
57
|
}
|
|
33
|
-
return
|
|
58
|
+
return { buffer: Buffer.from(TRAY_ICON_PNG_WIN_BASE64, 'base64') };
|
|
34
59
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juliantanx/aiusage-widget",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "System tray widget for aiusage — view AI token usage from your system tray",
|
|
6
6
|
"keywords": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"engines": {
|
|
25
|
-
"node": ">=
|
|
25
|
+
"node": ">=20"
|
|
26
26
|
},
|
|
27
27
|
"main": "dist/main.js",
|
|
28
28
|
"files": [
|
|
@@ -35,10 +35,11 @@
|
|
|
35
35
|
"aiusage-widget": "bin/launcher.js"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"better-sqlite3": "^
|
|
38
|
+
"better-sqlite3": "^12.0.0",
|
|
39
|
+
"electron": "^33.0.0"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"electron": "^
|
|
42
|
+
"@electron/rebuild": "^3.6.1",
|
|
42
43
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
|
43
44
|
"@types/better-sqlite3": "*",
|
|
44
45
|
"@types/node": "*",
|
|
@@ -51,11 +52,13 @@
|
|
|
51
52
|
"wait-on": "^7.0.0"
|
|
52
53
|
},
|
|
53
54
|
"scripts": {
|
|
55
|
+
"postinstall": "node bin/install-native.js",
|
|
54
56
|
"rebuild": "pnpm run rebuild:electron",
|
|
55
|
-
"rebuild:electron": "node -e \"const {
|
|
57
|
+
"rebuild:electron": "node -e \"const {rebuild}=require('@electron/rebuild');const v=require('electron/package.json').version;rebuild({buildPath:process.cwd(),electronVersion:v,onlyModules:['better-sqlite3'],force:true}).then(()=>process.exit(0)).catch(e=>{console.error(e);process.exit(1)})\"",
|
|
58
|
+
"prepare:native": "node bin/prepare-native.js",
|
|
56
59
|
"rebuild:node": "npm rebuild better-sqlite3",
|
|
57
|
-
"dev": "pnpm run
|
|
58
|
-
"build": "rm -rf dist/renderer && vite build && tsc -p tsconfig.json",
|
|
60
|
+
"dev": "pnpm run prepare:native && concurrently --names \"vite,tsc,electron\" --kill-others --success command-electron \"vite build --watch\" \"tsc -p tsconfig.json --watch\" \"node -e \\\"require('wait-on')({resources:['dist/main.js']},()=>{const c=require('child_process').spawn(require('electron'),['.'],{stdio:'inherit'});c.on('exit',(code,signal)=>process.exit(code ?? (signal ? 1 : 0)))})\\\"\"",
|
|
61
|
+
"build": "rm -rf dist/renderer && vite build && tsc -p tsconfig.json && pnpm run prepare:native",
|
|
59
62
|
"pack": "pnpm build && electron-builder",
|
|
60
63
|
"test": "pnpm run rebuild:node && vitest run"
|
|
61
64
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.header.svelte-14gtt2i{display:flex;align-items:center;justify-content:space-between;padding:12px 14px 10px;border-bottom:1px solid var(--border);-webkit-app-region:drag}.logo.svelte-14gtt2i{font-size:13px;font-weight:600;color:var(--text-primary);letter-spacing:.01em}.actions.svelte-14gtt2i{display:flex;gap:4px;-webkit-app-region:no-drag}.icon-btn.svelte-14gtt2i{width:24px;height:24px;border:none;border-radius:4px;background:transparent;color:var(--text-muted);cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;transition:background .1s,color .1s;padding:0}.icon-btn.svelte-14gtt2i:hover{background:var(--bg-hover);color:var(--text-primary)}.section.svelte-savwyt{padding:12px 14px;border-bottom:1px solid var(--border)}.section-label.svelte-savwyt{font-size:10px;font-weight:700;letter-spacing:.08em;color:var(--text-muted);text-transform:uppercase;margin-bottom:5px}.values.svelte-savwyt{display:flex;align-items:baseline;gap:8px}.primary.svelte-savwyt{font-size:16px;font-weight:600;color:var(--text-primary);font-variant-numeric:tabular-nums}.secondary.svelte-savwyt{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums}*{box-sizing:border-box;margin:0;padding:0}body{background:transparent;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;-webkit-font-smoothing:antialiased}:root{--bg:#1a1a1f;--bg-hover:rgba(255, 255, 255, .06);--border:rgba(255, 255, 255, .08);--text-primary:#f0f0f2;--text-muted:rgba(240, 240, 242, .45);--accent:#6c8eff}@media (prefers-color-scheme: light){:root{--bg:#ffffff;--bg-hover:rgba(0, 0, 0, .05);--border:rgba(0, 0, 0, .08);--text-primary:#0f0f12;--text-muted:rgba(15, 15, 18, .45);--accent:#3b5bdb}}.panel.svelte-z2p4qk{background:var(--bg);border-radius:12px;border:1px solid var(--border);overflow:hidden;width:320px;box-shadow:0 8px 32px #0000004d,0 2px 8px #0003;transition:opacity .15s}.panel.loading.svelte-z2p4qk{opacity:.7}.footer.svelte-z2p4qk{padding:10px 14px 14px}.open-btn.svelte-z2p4qk{width:100%;padding:9px 14px;border:1px solid var(--accent);border-radius:7px;background:transparent;color:var(--accent);font-size:12px;font-weight:600;cursor:pointer;transition:background .15s;letter-spacing:.01em}.open-btn.svelte-z2p4qk:hover{background:#6c8eff1a}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var se=Object.defineProperty;var ie=(e,t,n)=>t in e?se(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var x=(e,t,n)=>ie(e,typeof t!="symbol"?t+"":t,n);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))o(r);new MutationObserver(r=>{for(const s of r)if(s.type==="childList")for(const u of s.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&o(u)}).observe(document,{childList:!0,subtree:!0});function n(r){const s={};return r.integrity&&(s.integrity=r.integrity),r.referrerPolicy&&(s.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?s.credentials="include":r.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function o(r){if(r.ep)return;r.ep=!0;const s=n(r);fetch(r.href,s)}})();function w(){}function re(e){return e()}function X(){return Object.create(null)}function M(e){e.forEach(re)}function F(e){return typeof e=="function"}function Y(e,t){return e!=e?t==t:e!==t||e&&typeof e=="object"||typeof e=="function"}function le(e){return Object.keys(e).length===0}function d(e,t){e.appendChild(t)}function j(e,t,n){e.insertBefore(t,n||null)}function N(e){e.parentNode&&e.parentNode.removeChild(e)}function h(e){return document.createElement(e)}function I(e){return document.createTextNode(e)}function _(){return I(" ")}function K(e,t,n,o){return e.addEventListener(t,n,o),()=>e.removeEventListener(t,n,o)}function p(e,t,n){n==null?e.removeAttribute(t):e.getAttribute(t)!==n&&e.setAttribute(t,n)}function ue(e){return Array.from(e.childNodes)}function U(e,t){t=""+t,e.data!==t&&(e.data=t)}function Z(e,t,n){e.classList.toggle(t,!!n)}let T;function L(e){T=e}function ae(){if(!T)throw new Error("Function called outside component initialization");return T}function fe(e){ae().$$.on_mount.push(e)}const v=[],ee=[];let S=[];const te=[],ce=Promise.resolve();let V=!1;function de(){V||(V=!0,ce.then(oe))}function W(e){S.push(e)}const B=new Set;let $=0;function oe(){if($!==0)return;const e=T;do{try{for(;$<v.length;){const t=v[$];$++,L(t),me(t.$$)}}catch(t){throw v.length=0,$=0,t}for(L(null),v.length=0,$=0;ee.length;)ee.pop()();for(let t=0;t<S.length;t+=1){const n=S[t];B.has(n)||(B.add(n),n())}S.length=0}while(v.length);for(;te.length;)te.pop()();V=!1,B.clear(),L(e)}function me(e){if(e.fragment!==null){e.update(),M(e.before_update);const t=e.dirty;e.dirty=[-1],e.fragment&&e.fragment.p(e.ctx,t),e.after_update.forEach(W)}}function pe(e){const t=[],n=[];S.forEach(o=>e.indexOf(o)===-1?t.push(o):n.push(o)),n.forEach(o=>o()),S=t}const R=new Set;let he;function O(e,t){e&&e.i&&(R.delete(e),e.i(t))}function A(e,t,n,o){if(e&&e.o){if(R.has(e))return;R.add(e),he.c.push(()=>{R.delete(e)}),e.o(t)}}function D(e){e&&e.c()}function C(e,t,n){const{fragment:o,after_update:r}=e.$$;o&&o.m(t,n),W(()=>{const s=e.$$.on_mount.map(re).filter(F);e.$$.on_destroy?e.$$.on_destroy.push(...s):M(s),e.$$.on_mount=[]}),r.forEach(W)}function E(e,t){const n=e.$$;n.fragment!==null&&(pe(n.after_update),M(n.on_destroy),n.fragment&&n.fragment.d(t),n.on_destroy=n.fragment=null,n.ctx=[])}function ge(e,t){e.$$.dirty[0]===-1&&(v.push(e),de(),e.$$.dirty.fill(0)),e.$$.dirty[t/31|0]|=1<<t%31}function G(e,t,n,o,r,s,u=null,m=[-1]){const l=T;L(e);const i=e.$$={fragment:null,ctx:[],props:s,update:w,not_equal:r,bound:X(),on_mount:[],on_destroy:[],on_disconnect:[],before_update:[],after_update:[],context:new Map(t.context||(l?l.$$.context:[])),callbacks:X(),dirty:m,skip_bound:!1,root:t.target||l.$$.root};u&&u(i.root);let f=!1;if(i.ctx=n?n(e,t.props||{},(a,g,...b)=>{const k=b.length?b[0]:g;return i.ctx&&r(i.ctx[a],i.ctx[a]=k)&&(!i.skip_bound&&i.bound[a]&&i.bound[a](k),f&&ge(e,a)),g}):[],i.update(),f=!0,M(i.before_update),i.fragment=o?o(i.ctx):!1,t.target){if(t.hydrate){const a=ue(t.target);i.fragment&&i.fragment.l(a),a.forEach(N)}else i.fragment&&i.fragment.c();t.intro&&O(e.$$.fragment),C(e,t.target,t.anchor),oe()}L(l)}class J{constructor(){x(this,"$$");x(this,"$$set")}$destroy(){E(this,1),this.$destroy=w}$on(t,n){if(!F(n))return w;const o=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return o.push(n),()=>{const r=o.indexOf(n);r!==-1&&o.splice(r,1)}}$set(t){this.$$set&&!le(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}}const ye="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(ye);function _e(e){let t,n,o,r,s,u,m,l,i;return{c(){t=h("div"),n=h("span"),n.textContent="⚡ aiusage",o=_(),r=h("div"),s=h("button"),s.textContent="↻",u=_(),m=h("button"),m.textContent="✕",p(n,"class","logo svelte-14gtt2i"),p(s,"class","icon-btn svelte-14gtt2i"),p(s,"title","Refresh"),p(m,"class","icon-btn svelte-14gtt2i"),p(m,"title","Close"),p(r,"class","actions svelte-14gtt2i"),p(t,"class","header svelte-14gtt2i")},m(f,a){j(f,t,a),d(t,n),d(t,o),d(t,r),d(r,s),d(r,u),d(r,m),l||(i=[K(s,"click",function(){F(e[0])&&e[0].apply(this,arguments)}),K(m,"click",function(){F(e[1])&&e[1].apply(this,arguments)})],l=!0)},p(f,[a]){e=f},i:w,o:w,d(f){f&&N(t),l=!1,M(i)}}}function we(e,t,n){let{onRefresh:o}=t,{onClose:r}=t;return e.$$set=s=>{"onRefresh"in s&&n(0,o=s.onRefresh),"onClose"in s&&n(1,r=s.onClose)},[o,r]}class be extends J{constructor(t){super(),G(this,t,we,_e,Y,{onRefresh:0,onClose:1})}}function ne(e){let t,n;return{c(){t=h("span"),n=I(e[2]),p(t,"class","secondary svelte-savwyt")},m(o,r){j(o,t,r),d(t,n)},p(o,r){r&4&&U(n,o[2])},d(o){o&&N(t)}}}function $e(e){let t,n,o,r,s,u,m,l,i=e[2]&&ne(e);return{c(){t=h("div"),n=h("div"),o=I(e[0]),r=_(),s=h("div"),u=h("span"),m=I(e[1]),l=_(),i&&i.c(),p(n,"class","section-label svelte-savwyt"),p(u,"class","primary svelte-savwyt"),p(s,"class","values svelte-savwyt"),p(t,"class","section svelte-savwyt")},m(f,a){j(f,t,a),d(t,n),d(n,o),d(t,r),d(t,s),d(s,u),d(u,m),d(s,l),i&&i.m(s,null)},p(f,[a]){a&1&&U(o,f[0]),a&2&&U(m,f[1]),f[2]?i?i.p(f,a):(i=ne(f),i.c(),i.m(s,null)):i&&(i.d(1),i=null)},i:w,o:w,d(f){f&&N(t),i&&i.d()}}}function ve(e,t,n){let{label:o}=t,{primary:r}=t,{secondary:s=""}=t;return e.$$set=u=>{"label"in u&&n(0,o=u.label),"primary"in u&&n(1,r=u.primary),"secondary"in u&&n(2,s=u.secondary)},[o,r,s]}class H extends J{constructor(t){super(),G(this,t,ve,$e,Y,{label:0,primary:1,secondary:2})}}function Se(e){let t,n,o,r,s,u,m,l,i,f,a,g,b,k;return n=new be({props:{onRefresh:e[6],onClose:ke}}),r=new H({props:{label:"TODAY",primary:e[5],secondary:e[4]}}),u=new H({props:{label:"THIS MONTH",primary:e[3]}}),l=new H({props:{label:"TOP MODEL",primary:e[2],secondary:e[1]}}),{c(){t=h("div"),D(n.$$.fragment),o=_(),D(r.$$.fragment),s=_(),D(u.$$.fragment),m=_(),D(l.$$.fragment),i=_(),f=h("div"),a=h("button"),a.textContent="Open Full Dashboard →",p(a,"class","open-btn svelte-z2p4qk"),p(f,"class","footer svelte-z2p4qk"),p(t,"class","panel svelte-z2p4qk"),Z(t,"loading",e[0])},m(c,y){j(c,t,y),C(n,t,null),d(t,o),C(r,t,null),d(t,s),C(u,t,null),d(t,m),C(l,t,null),d(t,i),d(t,f),d(f,a),g=!0,b||(k=K(a,"click",Oe),b=!0)},p(c,[y]){const q={};y&32&&(q.primary=c[5]),y&16&&(q.secondary=c[4]),r.$set(q);const Q={};y&8&&(Q.primary=c[3]),u.$set(Q);const z={};y&4&&(z.primary=c[2]),y&2&&(z.secondary=c[1]),l.$set(z),(!g||y&1)&&Z(t,"loading",c[0])},i(c){g||(O(n.$$.fragment,c),O(r.$$.fragment,c),O(u.$$.fragment,c),O(l.$$.fragment,c),g=!0)},o(c){A(n.$$.fragment,c),A(r.$$.fragment,c),A(u.$$.fragment,c),A(l.$$.fragment,c),g=!1},d(c){c&&N(t),E(n),E(r),E(u),E(l),b=!1,k()}}}function P(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:String(e)}function ke(){window.widget.hideWindow()}async function Oe(){await window.widget.openDashboard()}function Ce(e,t,n){let o,r,s,u,m,l=null,i=!0;async function f(){n(0,i=!0),n(7,l=await window.widget.getData()),n(0,i=!1)}return fe(()=>{f(),window.widget.onDataUpdate(a=>{n(7,l=a),n(0,i=!1)})}),e.$$.update=()=>{var a;e.$$.dirty&128&&n(5,o=l?P(l.todayTokens.total):"—"),e.$$.dirty&128&&n(4,r=l?`↑${P(l.todayTokens.input)} ↓${P(l.todayTokens.output)}`:""),e.$$.dirty&128&&n(3,s=l?P(l.monthTokens.total):"—"),e.$$.dirty&128&&n(2,u=((a=l==null?void 0:l.topModel)==null?void 0:a.name)??"—"),e.$$.dirty&128&&n(1,m=l!=null&&l.topModel?`${l.topModel.share}%`:"")},[i,m,u,s,r,o,f,l]}class Ee extends J{constructor(t){super(),G(this,t,Ce,Se,Y,{})}}new Ee({target:document.getElementById("app")});
|