getaimeter 0.6.3 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getaimeter",
3
- "version": "0.6.3",
3
+ "version": "0.7.0",
4
4
  "description": "Track AI coding costs across Claude, Cursor, Codex, and Gemini. Optimization recommendations that cut costs by 30%.",
5
5
  "bin": {
6
6
  "aimeter": "cli.js"
package/tray-launcher.vbs CHANGED
@@ -1,2 +1,4 @@
1
1
  Set objShell = CreateObject("WScript.Shell")
2
- 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), 0, False
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()