@bitkyc08/opencodex 2.7.35 → 2.7.36

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 (80) hide show
  1. package/README.ja.md +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +4 -2
  4. package/README.ru.md +1 -1
  5. package/README.zh-CN.md +1 -1
  6. package/bin/ocx.mjs +52 -0
  7. package/gui/dist/assets/index-BpX-hoSd.css +1 -0
  8. package/gui/dist/assets/index-ZmFopEYw.js +52 -0
  9. package/gui/dist/index.html +2 -2
  10. package/package.json +1 -1
  11. package/src/adapters/cursor/cursor-errors.ts +38 -1
  12. package/src/adapters/cursor/discovery.ts +1 -0
  13. package/src/adapters/cursor/effort-map.ts +1 -0
  14. package/src/adapters/cursor/live-models.ts +22 -5
  15. package/src/adapters/cursor/live-transport.ts +82 -7
  16. package/src/adapters/cursor/transport.ts +2 -0
  17. package/src/adapters/cursor.ts +5 -2
  18. package/src/adapters/openai-responses.ts +64 -1
  19. package/src/cli/doctor.ts +10 -0
  20. package/src/cli/help.ts +10 -0
  21. package/src/cli/index.ts +88 -9
  22. package/src/cli/internal-dispatch.ts +20 -0
  23. package/src/cli/status.ts +15 -4
  24. package/src/cli/tray-proxy.ts +52 -0
  25. package/src/codex/auth-api.ts +46 -5
  26. package/src/codex/autostart-health.ts +149 -0
  27. package/src/codex/catalog/aggregation.ts +268 -0
  28. package/src/codex/catalog/bundled.ts +188 -0
  29. package/src/codex/catalog/effort.ts +263 -0
  30. package/src/codex/catalog/metadata.ts +176 -0
  31. package/src/codex/catalog/parsing.ts +399 -0
  32. package/src/codex/catalog/provider-fetch.ts +609 -0
  33. package/src/codex/catalog/sync.ts +540 -0
  34. package/src/codex/catalog.ts +11 -2426
  35. package/src/codex/inject.ts +165 -3
  36. package/src/codex/shim.ts +141 -8
  37. package/src/codex/sync.ts +17 -2
  38. package/src/config.ts +23 -0
  39. package/src/lib/errors.ts +11 -0
  40. package/src/providers/antigravity-models.ts +33 -0
  41. package/src/providers/kiro-models.ts +2 -0
  42. package/src/providers/registry.ts +2 -2
  43. package/src/responses/state.ts +69 -6
  44. package/src/server/auth-cors.ts +3 -0
  45. package/src/server/management/agent-settings-routes.ts +536 -0
  46. package/src/server/management/combo-routes.ts +210 -0
  47. package/src/server/management/config-routes.ts +302 -0
  48. package/src/server/management/context.ts +21 -0
  49. package/src/server/management/logs-usage-routes.ts +176 -0
  50. package/src/server/management/model-routes.ts +253 -0
  51. package/src/server/management/oauth-account-routes.ts +301 -0
  52. package/src/server/management/provider-routes.ts +408 -0
  53. package/src/server/management/shared.ts +186 -0
  54. package/src/server/management-api.ts +23 -1806
  55. package/src/server/responses/collaboration.ts +300 -0
  56. package/src/server/responses/compact.ts +342 -0
  57. package/src/server/responses/core.ts +1498 -0
  58. package/src/server/responses/encrypted-payload.ts +231 -0
  59. package/src/server/responses/fetch-helpers.ts +157 -0
  60. package/src/server/responses.ts +9 -2172
  61. package/src/server/startup-action-control.ts +41 -0
  62. package/src/server/startup-health-cache.ts +100 -0
  63. package/src/server/windows-tray-control.ts +41 -0
  64. package/src/service.ts +171 -19
  65. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  66. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  67. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  68. package/src/tray/assets/opencodex-tray.png +0 -0
  69. package/src/tray/windows-tray.ps1 +290 -0
  70. package/src/tray/windows.ts +628 -0
  71. package/src/types.ts +5 -0
  72. package/src/update/index.ts +43 -0
  73. package/src/update/job.ts +46 -0
  74. package/src/update/tray-update-plan.d.mts +18 -0
  75. package/src/update/tray-update-plan.mjs +38 -0
  76. package/src/usage/cost.ts +0 -0
  77. package/src/usage/expected-prices.ts +9 -2
  78. package/src/usage/summary.ts +42 -7
  79. package/gui/dist/assets/index-BunUANVE.js +0 -52
  80. package/gui/dist/assets/index-Sg-7L_oZ.css +0 -1
@@ -0,0 +1,290 @@
1
+ param(
2
+ [Parameter(Mandatory = $true)][string]$BunPath,
3
+ [Parameter(Mandatory = $true)][string]$CliPath,
4
+ [Parameter(Mandatory = $true)][string]$CodexHome,
5
+ [Parameter(Mandatory = $true)][string]$OpenCodexHome,
6
+ [ValidateSet("Run", "Stop")][string]$Mode = "Run",
7
+ [int]$HostPid = 0
8
+ )
9
+
10
+ $ErrorActionPreference = "Stop"
11
+ Add-Type -AssemblyName System.Windows.Forms
12
+ Add-Type -AssemblyName System.Drawing
13
+
14
+ # Normalize aliases before deriving singleton/event names. Without this,
15
+ # C:\path and C:\path\. create separate tray instances for the same home.
16
+ function Normalize-HomePath([string]$Value) {
17
+ $full = [System.IO.Path]::GetFullPath($Value)
18
+ $root = [System.IO.Path]::GetPathRoot($full)
19
+ if ($full -eq $root) { return $full }
20
+ return $full.TrimEnd([System.IO.Path]::DirectorySeparatorChar, [System.IO.Path]::AltDirectorySeparatorChar)
21
+ }
22
+ $OpenCodexHome = Normalize-HomePath $OpenCodexHome
23
+ $CodexHome = Normalize-HomePath $CodexHome
24
+
25
+ $script:ownedIcons = New-Object System.Collections.Generic.List[System.Drawing.Icon]
26
+ function Load-TrayIcon([string]$Name, [System.Drawing.Icon]$Fallback) {
27
+ $path = Join-Path $OpenCodexHome $Name
28
+ if (-not [System.IO.File]::Exists($path)) { return $Fallback }
29
+ try {
30
+ $icon = New-Object System.Drawing.Icon($path)
31
+ [void]$script:ownedIcons.Add($icon)
32
+ return $icon
33
+ } catch {
34
+ return $Fallback
35
+ }
36
+ }
37
+ $onlineIcon = Load-TrayIcon "opencodex-tray-online.ico" ([System.Drawing.SystemIcons]::Information)
38
+ $warningIcon = Load-TrayIcon "opencodex-tray-warning.ico" ([System.Drawing.SystemIcons]::Warning)
39
+ $offlineIcon = Load-TrayIcon "opencodex-tray-offline.ico" ([System.Drawing.SystemIcons]::Error)
40
+
41
+ function Get-StableHash([string]$Value) {
42
+ $sha = [System.Security.Cryptography.SHA256]::Create()
43
+ try {
44
+ $bytes = [System.Text.Encoding]::UTF8.GetBytes($Value.ToLowerInvariant())
45
+ $hash = [System.BitConverter]::ToString($sha.ComputeHash($bytes)).Replace("-", "").Substring(0, 20)
46
+ return $hash
47
+ } finally {
48
+ $sha.Dispose()
49
+ }
50
+ }
51
+
52
+ $stableHash = Get-StableHash $OpenCodexHome
53
+ $stopEventCreated = $false
54
+ $stopEvent = New-Object System.Threading.EventWaitHandle($false, [System.Threading.EventResetMode]::AutoReset, "Local\OpenCodexTrayStop-$stableHash", [ref]$stopEventCreated)
55
+ if ($Mode -eq "Stop") {
56
+ [void]$stopEvent.Set()
57
+ $stopEvent.Dispose()
58
+ exit 0
59
+ }
60
+
61
+ $createdNew = $false
62
+ $mutex = New-Object System.Threading.Mutex($true, "Local\OpenCodexTray-$stableHash", [ref]$createdNew)
63
+ if (-not $createdNew) {
64
+ $stopEvent.Dispose()
65
+ $mutex.Dispose()
66
+ exit 0
67
+ }
68
+
69
+ $heartbeatPath = Join-Path $OpenCodexHome "tray-heartbeat.json"
70
+ $actionLogPath = Join-Path $OpenCodexHome "tray-actions.log"
71
+
72
+ function Write-ActionLog([string]$Message) {
73
+ $line = "[$([DateTimeOffset]::Now.ToString('o'))] $Message"
74
+ [System.IO.File]::AppendAllText($actionLogPath, $line + [Environment]::NewLine, (New-Object System.Text.UTF8Encoding($false)))
75
+ }
76
+
77
+ function ConvertTo-NativeArgument([string]$Value) {
78
+ if ($Value.Contains('"') -or $Value.Contains("`r") -or $Value.Contains("`n")) {
79
+ throw "Invalid native command argument"
80
+ }
81
+ return '"' + $Value + '"'
82
+ }
83
+
84
+ function Start-OcxCommand([string[]]$CommandArgs) {
85
+ try {
86
+ $allArgs = @($CliPath) + $CommandArgs
87
+ $psi = New-Object System.Diagnostics.ProcessStartInfo
88
+ $psi.FileName = $BunPath
89
+ $psi.Arguments = (($allArgs | ForEach-Object { ConvertTo-NativeArgument $_ }) -join " ")
90
+ $psi.UseShellExecute = $false
91
+ $psi.CreateNoWindow = $true
92
+ $psi.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
93
+ $psi.EnvironmentVariables["CODEX_HOME"] = $CodexHome
94
+ $psi.EnvironmentVariables["OPENCODEX_HOME"] = $OpenCodexHome
95
+ $process = [System.Diagnostics.Process]::Start($psi)
96
+ if ($null -ne $process) { $process.Dispose() }
97
+ Write-ActionLog "dispatched $($CommandArgs -join ' ')"
98
+ return $true
99
+ } catch {
100
+ Write-ActionLog "launch failed: $($_.Exception.GetType().Name)"
101
+ $notify.ShowBalloonTip(5000, "opencodex action failed", "The action could not start. Open the logs folder or run ocx doctor.", [System.Windows.Forms.ToolTipIcon]::Error)
102
+ return $false
103
+ }
104
+ }
105
+
106
+ function Read-ListenTarget {
107
+ foreach ($path in @((Join-Path $OpenCodexHome "runtime-port.json"), (Join-Path $OpenCodexHome "config.json"))) {
108
+ try {
109
+ $value = Get-Content -LiteralPath $path -Raw | ConvertFrom-Json
110
+ $candidate = [int]$value.port
111
+ if ($candidate -gt 0 -and $candidate -le 65535) {
112
+ $candidateHost = [string]$value.hostname
113
+ $ip = $null
114
+ $hostName = if ([string]::IsNullOrWhiteSpace($candidateHost) -or $candidateHost -in @("localhost", "0.0.0.0", "::", "[::]")) {
115
+ "127.0.0.1"
116
+ } elseif ([System.Net.IPAddress]::TryParse($candidateHost.Trim("[", "]"), [ref]$ip)) {
117
+ if ($ip.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetworkV6) { "[$($ip.ToString())]" } else { $ip.ToString() }
118
+ } else {
119
+ "127.0.0.1"
120
+ }
121
+ return @{ port = $candidate; host = $hostName; pid = $value.pid }
122
+ }
123
+ } catch { }
124
+ }
125
+ return @{ port = 10100; host = "127.0.0.1"; pid = $null }
126
+ }
127
+
128
+ function Read-JsonUrl([string]$Url) {
129
+ $request = [System.Net.HttpWebRequest]::Create($Url)
130
+ $request.Method = "GET"
131
+ $request.Timeout = 700
132
+ $request.ReadWriteTimeout = 700
133
+ $response = $request.GetResponse()
134
+ try {
135
+ $reader = New-Object System.IO.StreamReader($response.GetResponseStream())
136
+ try { return ($reader.ReadToEnd() | ConvertFrom-Json) } finally { $reader.Dispose() }
137
+ } finally {
138
+ $response.Dispose()
139
+ }
140
+ }
141
+
142
+ $notify = New-Object System.Windows.Forms.NotifyIcon
143
+ $menu = New-Object System.Windows.Forms.ContextMenuStrip
144
+ $statusItem = New-Object System.Windows.Forms.ToolStripMenuItem
145
+ $statusItem.Enabled = $false
146
+ $safetyItem = New-Object System.Windows.Forms.ToolStripMenuItem
147
+ $safetyItem.Enabled = $false
148
+ $openItem = $menu.Items.Add("Open Dashboard")
149
+ $startItem = $menu.Items.Add("Start Proxy")
150
+ $stopItem = $menu.Items.Add("Stop Proxy and Restore Native Routing")
151
+ $restartItem = $menu.Items.Add("Restart Proxy")
152
+ [void]$menu.Items.Add((New-Object System.Windows.Forms.ToolStripSeparator))
153
+ [void]$menu.Items.Add($statusItem)
154
+ [void]$menu.Items.Add($safetyItem)
155
+ $logsItem = $menu.Items.Add("Open Logs Folder")
156
+ [void]$menu.Items.Add((New-Object System.Windows.Forms.ToolStripSeparator))
157
+ $exitItem = $menu.Items.Add("Exit Tray")
158
+
159
+ $script:online = $false
160
+ $script:port = 10100
161
+ $script:proxyPid = $null
162
+ $script:pendingAction = $null
163
+ $script:pendingStarted = 0L
164
+ $script:pendingDeadline = 0L
165
+ $script:pendingOldProxyPid = $null
166
+
167
+ function Set-PendingAction([string]$Action, [int]$TimeoutSeconds) {
168
+ $script:pendingAction = $Action
169
+ $script:pendingStarted = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
170
+ $script:pendingDeadline = $script:pendingStarted + ($TimeoutSeconds * 1000)
171
+ $script:pendingOldProxyPid = $script:proxyPid
172
+ }
173
+
174
+ function Complete-PendingAction([bool]$Success) {
175
+ if ($null -eq $script:pendingAction) { return }
176
+ $action = $script:pendingAction
177
+ $script:pendingAction = $null
178
+ if ($Success) {
179
+ Write-ActionLog "$action completed (port=$($script:port), pid=$($script:proxyPid))"
180
+ $notify.ShowBalloonTip(2500, "opencodex", "$action completed.", [System.Windows.Forms.ToolTipIcon]::Info)
181
+ } else {
182
+ Write-ActionLog "$action failed to reach the expected state"
183
+ $notify.ShowBalloonTip(5000, "opencodex action failed", "$action did not reach the expected state. Open the logs folder or run ocx doctor.", [System.Windows.Forms.ToolTipIcon]::Error)
184
+ }
185
+ }
186
+
187
+ function Update-TrayState {
188
+ $target = Read-ListenTarget
189
+ $script:port = [int]$target.port
190
+ $health = $null
191
+ $origin = "http://$($target.host):$($script:port)"
192
+ try { $health = Read-JsonUrl "$origin/healthz" } catch { }
193
+ $pidMatches = $null -eq $target.pid -or [int]$target.pid -eq [int]$health.pid
194
+ $script:online = $null -ne $health -and $health.status -eq "ok" -and $health.service -eq "opencodex" -and [int]$health.port -eq $script:port -and $pidMatches
195
+ $script:proxyPid = if ($script:online) { [int]$health.pid } else { $null }
196
+ if ($script:online) {
197
+ $statusItem.Text = "Proxy: Online (port $($script:port))"
198
+ $notify.Text = "opencodex: Online"
199
+ $startItem.Enabled = $false
200
+ $stopItem.Enabled = $true
201
+ $restartItem.Enabled = $true
202
+ try {
203
+ $startup = Read-JsonUrl "$origin/api/startup-health"
204
+ $label = if ($startup.status -eq "at-risk") { "At risk" } elseif ($startup.status -eq "protected") { "Protected" } else { "Native routing" }
205
+ $safetyItem.Text = "Restart safety: $label"
206
+ $notify.Icon = if ($startup.status -eq "at-risk") { $warningIcon } else { $onlineIcon }
207
+ } catch {
208
+ $safetyItem.Text = "Restart safety: unavailable"
209
+ $notify.Icon = $warningIcon
210
+ }
211
+ } else {
212
+ $statusItem.Text = "Proxy: Offline"
213
+ $safetyItem.Text = "Restart safety: start the proxy to inspect"
214
+ $notify.Text = "opencodex: Offline"
215
+ $notify.Icon = $offlineIcon
216
+ $startItem.Enabled = $true
217
+ $stopItem.Enabled = $false
218
+ $restartItem.Enabled = $false
219
+ }
220
+ $heartbeat = @{ pid = $PID; timestamp = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() }
221
+ if ($HostPid -gt 0) { $heartbeat.hostPid = $HostPid }
222
+ $heartbeatJson = $heartbeat | ConvertTo-Json -Compress
223
+ [System.IO.File]::WriteAllText($heartbeatPath, $heartbeatJson, (New-Object System.Text.UTF8Encoding($false)))
224
+
225
+ if ($null -ne $script:pendingAction) {
226
+ $now = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
227
+ $elapsed = $now - $script:pendingStarted
228
+ $reached = ($script:pendingAction -eq "Start Proxy" -and $script:online) -or
229
+ ($script:pendingAction -eq "Stop Proxy" -and -not $script:online) -or
230
+ ($script:pendingAction -eq "Restart Proxy" -and $elapsed -gt 3000 -and $script:online -and $script:proxyPid -ne $script:pendingOldProxyPid)
231
+ if ($reached) { Complete-PendingAction $true }
232
+ elseif ($now -gt $script:pendingDeadline) { Complete-PendingAction $false }
233
+ }
234
+ }
235
+
236
+ $openItem.add_Click({ Start-OcxCommand @("gui") })
237
+ $startItem.add_Click({
238
+ $statusItem.Text = "Proxy: Starting..."
239
+ Set-PendingAction "Start Proxy" 15
240
+ if (-not (Start-OcxCommand @("__tray-start"))) { $script:pendingAction = $null }
241
+ })
242
+ $stopItem.add_Click({
243
+ $statusItem.Text = "Proxy: Stopping..."
244
+ Set-PendingAction "Stop Proxy" 15
245
+ if (-not (Start-OcxCommand @("stop"))) { $script:pendingAction = $null }
246
+ })
247
+ $restartItem.add_Click({
248
+ $statusItem.Text = "Proxy: Restarting..."
249
+ Set-PendingAction "Restart Proxy" 20
250
+ if (-not (Start-OcxCommand @("__tray-restart"))) { $script:pendingAction = $null }
251
+ })
252
+ $logsItem.add_Click({
253
+ $psi = New-Object System.Diagnostics.ProcessStartInfo
254
+ $psi.FileName = $OpenCodexHome
255
+ $psi.UseShellExecute = $true
256
+ [void][System.Diagnostics.Process]::Start($psi)
257
+ })
258
+ $exitItem.add_Click({ [System.Windows.Forms.Application]::Exit() })
259
+ $notify.add_DoubleClick({ Start-OcxCommand @("gui") })
260
+
261
+ $timer = New-Object System.Windows.Forms.Timer
262
+ $timer.Interval = 3000
263
+ $timer.add_Tick({
264
+ if ($stopEvent.WaitOne(0)) {
265
+ [System.Windows.Forms.Application]::Exit()
266
+ return
267
+ }
268
+ Update-TrayState
269
+ })
270
+ $notify.ContextMenuStrip = $menu
271
+ $notify.Icon = $offlineIcon
272
+ $notify.Visible = $true
273
+ $notify.Text = "opencodex: Checking..."
274
+
275
+ try {
276
+ Update-TrayState
277
+ $timer.Start()
278
+ [System.Windows.Forms.Application]::Run()
279
+ } finally {
280
+ $timer.Stop()
281
+ $timer.Dispose()
282
+ $notify.Visible = $false
283
+ $notify.Dispose()
284
+ foreach ($icon in $script:ownedIcons) { $icon.Dispose() }
285
+ $menu.Dispose()
286
+ try { Remove-Item -LiteralPath $heartbeatPath -Force -ErrorAction SilentlyContinue } catch { }
287
+ try { $mutex.ReleaseMutex() } catch { }
288
+ $mutex.Dispose()
289
+ $stopEvent.Dispose()
290
+ }