getaimeter 0.6.4 → 0.7.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/package.json +1 -1
- package/tray-launcher.vbs +3 -1
- package/tray.js +2 -0
- package/tray.ps1 +87 -5
package/package.json
CHANGED
package/tray-launcher.vbs
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
Set objShell = CreateObject("WScript.Shell")
|
|
2
|
-
|
|
2
|
+
Dim sVersion
|
|
3
|
+
If WScript.Arguments.Count > 3 Then sVersion = WScript.Arguments(3) Else sVersion = "unknown"
|
|
4
|
+
objShell.Run "powershell -NoProfile -ExecutionPolicy Bypass -STA -File """ & Replace(WScript.ScriptFullName, "tray-launcher.vbs", "tray.ps1") & """ -IconPath """ & Replace(WScript.ScriptFullName, "tray-launcher.vbs", "icon.ico") & """ -MaskedKey """ & WScript.Arguments(0) & """ -LogPath """ & WScript.Arguments(1) & """ -ParentPid " & WScript.Arguments(2) & " -Version """ & sVersion & """", 0, False
|
package/tray.js
CHANGED
|
@@ -13,6 +13,7 @@ async function startTray(onStop) {
|
|
|
13
13
|
const apiKey = getApiKey();
|
|
14
14
|
const maskedKey = apiKey ? `${apiKey.slice(0, 8)}...${apiKey.slice(-4)}` : 'not set';
|
|
15
15
|
const logPath = path.join(AIMETER_DIR, 'watcher.log');
|
|
16
|
+
const version = require('./package.json').version;
|
|
16
17
|
|
|
17
18
|
return new Promise((resolve) => {
|
|
18
19
|
// Use cscript to launch VBS which launches PowerShell hidden with -STA
|
|
@@ -22,6 +23,7 @@ async function startTray(onStop) {
|
|
|
22
23
|
maskedKey,
|
|
23
24
|
logPath,
|
|
24
25
|
String(process.pid),
|
|
26
|
+
version,
|
|
25
27
|
], { windowsHide: true }, (err) => {
|
|
26
28
|
if (err) resolve(null);
|
|
27
29
|
});
|
package/tray.ps1
CHANGED
|
@@ -2,12 +2,23 @@ param(
|
|
|
2
2
|
[string]$IconPath,
|
|
3
3
|
[string]$MaskedKey,
|
|
4
4
|
[string]$LogPath,
|
|
5
|
-
[int]$ParentPid
|
|
5
|
+
[int]$ParentPid,
|
|
6
|
+
[string]$Version = "unknown"
|
|
6
7
|
)
|
|
7
8
|
|
|
8
9
|
Add-Type -AssemblyName System.Windows.Forms
|
|
9
10
|
Add-Type -AssemblyName System.Drawing
|
|
10
11
|
|
|
12
|
+
# ── Prevent duplicate tray instances ──────────────────────────────────────────
|
|
13
|
+
$mutexName = "Global\AIMeterTray"
|
|
14
|
+
$createdNew = $false
|
|
15
|
+
$mutex = New-Object System.Threading.Mutex($true, $mutexName, [ref]$createdNew)
|
|
16
|
+
if (-not $createdNew) {
|
|
17
|
+
# Another tray is already running — exit silently
|
|
18
|
+
$mutex.Dispose()
|
|
19
|
+
exit 0
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
# Create tray icon
|
|
12
23
|
$tray = New-Object System.Windows.Forms.NotifyIcon
|
|
13
24
|
|
|
@@ -21,13 +32,13 @@ if ($IconPath -and (Test-Path $IconPath)) {
|
|
|
21
32
|
$tray.Icon = [System.Drawing.SystemIcons]::Application
|
|
22
33
|
}
|
|
23
34
|
|
|
24
|
-
$tray.Text = "AIMeter - Tracking AI usage"
|
|
35
|
+
$tray.Text = "AIMeter v$Version - Tracking AI usage"
|
|
25
36
|
$tray.Visible = $true
|
|
26
37
|
|
|
27
38
|
# Context menu
|
|
28
39
|
$menu = New-Object System.Windows.Forms.ContextMenuStrip
|
|
29
40
|
|
|
30
|
-
$header = $menu.Items.Add("AIMeter Watcher")
|
|
41
|
+
$header = $menu.Items.Add("AIMeter Watcher v$Version")
|
|
31
42
|
$header.Enabled = $false
|
|
32
43
|
$header.Font = New-Object System.Drawing.Font($header.Font, [System.Drawing.FontStyle]::Bold)
|
|
33
44
|
|
|
@@ -44,8 +55,6 @@ $dashboard.Add_Click({ Start-Process "https://getaimeter.com/dashboard" })
|
|
|
44
55
|
$logs = $menu.Items.Add("View Logs")
|
|
45
56
|
$viewerScript = Join-Path (Split-Path $MyInvocation.MyCommand.Path) 'log-viewer.ps1'
|
|
46
57
|
$logs.Add_Click({
|
|
47
|
-
# Launch log viewer as a separate process so it doesn't block the tray
|
|
48
|
-
# Launch via wscript to avoid any console window flash
|
|
49
58
|
$vbsCmd = "CreateObject(""WScript.Shell"").Run ""powershell -NoProfile -ExecutionPolicy Bypass -STA -WindowStyle Hidden -File """"$viewerScript"""" -LogPath """"$LogPath"""""", 0, False"
|
|
50
59
|
$tempVbs = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'aimeter-logviewer.vbs')
|
|
51
60
|
[System.IO.File]::WriteAllText($tempVbs, $vbsCmd)
|
|
@@ -54,10 +63,78 @@ $logs.Add_Click({
|
|
|
54
63
|
|
|
55
64
|
$menu.Items.Add("-")
|
|
56
65
|
|
|
66
|
+
# ── Help submenu ──────────────────────────────────────────────────────────────
|
|
67
|
+
$helpMenu = New-Object System.Windows.Forms.ToolStripMenuItem("Help")
|
|
68
|
+
|
|
69
|
+
$aboutItem = New-Object System.Windows.Forms.ToolStripMenuItem("About AIMeter")
|
|
70
|
+
$aboutItem.Add_Click({
|
|
71
|
+
[System.Windows.Forms.MessageBox]::Show(
|
|
72
|
+
"AIMeter v$Version`n`nAI coding cost optimizer.`nTrack Claude, Cursor, Codex, and Gemini.`n`nhttps://getaimeter.com",
|
|
73
|
+
"About AIMeter",
|
|
74
|
+
[System.Windows.Forms.MessageBoxButtons]::OK,
|
|
75
|
+
[System.Windows.Forms.MessageBoxIcon]::Information
|
|
76
|
+
)
|
|
77
|
+
})
|
|
78
|
+
$helpMenu.DropDownItems.Add($aboutItem) | Out-Null
|
|
79
|
+
|
|
80
|
+
$checkUpdateItem = New-Object System.Windows.Forms.ToolStripMenuItem("Check for Updates")
|
|
81
|
+
$checkUpdateItem.Add_Click({
|
|
82
|
+
$checkUpdateItem.Text = "Checking..."
|
|
83
|
+
$checkUpdateItem.Enabled = $false
|
|
84
|
+
try {
|
|
85
|
+
$response = Invoke-RestMethod -Uri "https://registry.npmjs.org/getaimeter/latest" -TimeoutSec 5
|
|
86
|
+
$latest = $response.version
|
|
87
|
+
if ($latest -and $latest -ne $Version) {
|
|
88
|
+
$result = [System.Windows.Forms.MessageBox]::Show(
|
|
89
|
+
"Update available: v$Version -> v$latest`n`nRun this command to update:`nnpm install -g getaimeter@latest`n`nThen restart the watcher.`n`nOpen terminal to update now?",
|
|
90
|
+
"Update Available",
|
|
91
|
+
[System.Windows.Forms.MessageBoxButtons]::YesNo,
|
|
92
|
+
[System.Windows.Forms.MessageBoxIcon]::Information
|
|
93
|
+
)
|
|
94
|
+
if ($result -eq [System.Windows.Forms.DialogResult]::Yes) {
|
|
95
|
+
Start-Process "cmd.exe" -ArgumentList "/k npm install -g getaimeter@latest && echo. && echo Update complete. Restart the watcher with: aimeter stop && aimeter start"
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
[System.Windows.Forms.MessageBox]::Show(
|
|
99
|
+
"You are running the latest version (v$Version).",
|
|
100
|
+
"No Updates",
|
|
101
|
+
[System.Windows.Forms.MessageBoxButtons]::OK,
|
|
102
|
+
[System.Windows.Forms.MessageBoxIcon]::Information
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
} catch {
|
|
106
|
+
[System.Windows.Forms.MessageBox]::Show(
|
|
107
|
+
"Could not check for updates. Please check your internet connection.",
|
|
108
|
+
"Update Check Failed",
|
|
109
|
+
[System.Windows.Forms.MessageBoxButtons]::OK,
|
|
110
|
+
[System.Windows.Forms.MessageBoxIcon]::Warning
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
$checkUpdateItem.Text = "Check for Updates"
|
|
114
|
+
$checkUpdateItem.Enabled = $true
|
|
115
|
+
})
|
|
116
|
+
$helpMenu.DropDownItems.Add($checkUpdateItem) | Out-Null
|
|
117
|
+
|
|
118
|
+
$helpMenu.DropDownItems.Add("-") | Out-Null
|
|
119
|
+
|
|
120
|
+
$docsItem = New-Object System.Windows.Forms.ToolStripMenuItem("Documentation")
|
|
121
|
+
$docsItem.Add_Click({ Start-Process "https://www.npmjs.com/package/getaimeter" })
|
|
122
|
+
$helpMenu.DropDownItems.Add($docsItem) | Out-Null
|
|
123
|
+
|
|
124
|
+
$websiteItem = New-Object System.Windows.Forms.ToolStripMenuItem("Website")
|
|
125
|
+
$websiteItem.Add_Click({ Start-Process "https://getaimeter.com" })
|
|
126
|
+
$helpMenu.DropDownItems.Add($websiteItem) | Out-Null
|
|
127
|
+
|
|
128
|
+
$menu.Items.Add($helpMenu)
|
|
129
|
+
|
|
130
|
+
$menu.Items.Add("-")
|
|
131
|
+
|
|
57
132
|
$stop = $menu.Items.Add("Stop Watcher")
|
|
58
133
|
$stop.Add_Click({
|
|
59
134
|
$tray.Visible = $false
|
|
60
135
|
$tray.Dispose()
|
|
136
|
+
$mutex.ReleaseMutex()
|
|
137
|
+
$mutex.Dispose()
|
|
61
138
|
if ($ParentPid -gt 0) {
|
|
62
139
|
try { Stop-Process -Id $ParentPid -Force -ErrorAction SilentlyContinue } catch {}
|
|
63
140
|
}
|
|
@@ -77,11 +154,16 @@ $timer.Add_Tick({
|
|
|
77
154
|
# Parent died, clean up
|
|
78
155
|
$tray.Visible = $false
|
|
79
156
|
$tray.Dispose()
|
|
157
|
+
$mutex.ReleaseMutex()
|
|
158
|
+
$mutex.Dispose()
|
|
80
159
|
[System.Windows.Forms.Application]::Exit()
|
|
81
160
|
}
|
|
82
161
|
}
|
|
83
162
|
})
|
|
84
163
|
$timer.Start()
|
|
85
164
|
|
|
165
|
+
# Double-click tray icon opens dashboard
|
|
166
|
+
$tray.Add_DoubleClick({ Start-Process "https://getaimeter.com/dashboard" })
|
|
167
|
+
|
|
86
168
|
# Run message loop
|
|
87
169
|
[System.Windows.Forms.Application]::Run()
|