relay-codex 0.6.0 → 0.6.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.
- package/docs/commands.md +4 -0
- package/docs/publishing.md +2 -2
- package/package.json +1 -1
- package/python/Menu.swift +31 -3
- package/python/router.py +1 -1
package/docs/commands.md
CHANGED
|
@@ -109,6 +109,10 @@ allowance and does not fetch account allowance. `refresh` explicitly checks it.
|
|
|
109
109
|
The menu uses one local status stream, a template icon, and native session actions.
|
|
110
110
|
Opening it reads a fresh local snapshot, and visible rows update in place.
|
|
111
111
|
Short-window and weekly allowance are labeled separately.
|
|
112
|
+
Accounts assigned to live Relay sessions have a checkmark and an “In use” label;
|
|
113
|
+
shared accounts also show their session count. To switch, open the Relay icon,
|
|
114
|
+
then your session, then **Switch account**, and choose the account email. The
|
|
115
|
+
current choice is marked **Current**. The menu tracks tasks started through Relay.
|
|
112
116
|
Each session menu can switch to another enabled account after work and approvals
|
|
113
117
|
finish. The worker checks allowance and session capacity before switching, then
|
|
114
118
|
checks again that the session is idle before changing its login. Rejected actions
|
package/docs/publishing.md
CHANGED
|
@@ -8,8 +8,8 @@ Friends can run `npx relay-codex` or install it with `npm install -g relay-codex
|
|
|
8
8
|
The GitHub repository is enough for friends to install or try Relay:
|
|
9
9
|
|
|
10
10
|
```sh
|
|
11
|
-
npm install -g github:blackspider-ops/relay#v0.6.
|
|
12
|
-
npx --yes github:blackspider-ops/relay#v0.6.
|
|
11
|
+
npm install -g github:blackspider-ops/relay#v0.6.1
|
|
12
|
+
npx --yes github:blackspider-ops/relay#v0.6.1 --version
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
`npx` runs packages; it is not a separate publishing service. Publishing
|
package/package.json
CHANGED
package/python/Menu.swift
CHANGED
|
@@ -186,6 +186,7 @@ final class MenuController: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
|
|
186
186
|
func makeMenu() -> NSMenu {
|
|
187
187
|
let sessions = current["sessions"] as? [[String: Any]] ?? []
|
|
188
188
|
let accounts = current["accounts"] as? [[String: Any]] ?? []
|
|
189
|
+
let liveSessions = sessions.filter { $0["running"] as? Bool ?? true }
|
|
189
190
|
let menu = NSMenu(); menu.delegate = self
|
|
190
191
|
menu.autoenablesItems = false
|
|
191
192
|
text("Relay · \(sessions.count) sessions", into: menu)
|
|
@@ -195,8 +196,12 @@ final class MenuController: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
|
|
195
196
|
if !actionRunning { action("Dismiss message", args: ["dismiss"], into: menu) }
|
|
196
197
|
}
|
|
197
198
|
if accounts.isEmpty { text("Add an account with relay setup in Terminal.", into: menu) }
|
|
199
|
+
if liveSessions.isEmpty && !accounts.isEmpty { text("No Relay sessions running. Start with relay run.", into: menu) }
|
|
198
200
|
for account in accounts {
|
|
199
201
|
let name = account["name"] as? String ?? "Account"
|
|
202
|
+
let accountID = account["id"] as? String ?? ""
|
|
203
|
+
let assigned = liveSessions.filter { $0["account"] as? String == accountID }
|
|
204
|
+
let inUse = assigned.isEmpty ? "" : assigned.count == 1 ? " · In use" : " · In use by \(assigned.count) sessions"
|
|
200
205
|
let primary = account["primary"] as? [String: Any]
|
|
201
206
|
let short = account["short_remaining"] as? String ?? (primary?["usedPercent"] as? NSNumber).map { "\(max(0, 100 - $0.intValue))%" } ?? "?"
|
|
202
207
|
let remaining = short == "?" ? "allowance unknown" : short + " left"
|
|
@@ -206,6 +211,13 @@ final class MenuController: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
|
|
206
211
|
let submenu = NSMenu()
|
|
207
212
|
submenu.autoenablesItems = false
|
|
208
213
|
if let email = account["email"] as? String { text(email, into: submenu) }
|
|
214
|
+
if !assigned.isEmpty {
|
|
215
|
+
for session in assigned {
|
|
216
|
+
let sessionName = session["name"] as? String ?? String((session["id"] as? String ?? "").prefix(10))
|
|
217
|
+
text("In use by: \(sessionName)", into: submenu)
|
|
218
|
+
}
|
|
219
|
+
text("To switch: open that session → Switch account.", into: submenu)
|
|
220
|
+
}
|
|
209
221
|
text("Short window: \(remaining)", into: submenu)
|
|
210
222
|
if weekly != "?" { text("Weekly window: \(weekly) left", into: submenu) }
|
|
211
223
|
for row in MenuController.accountTimingRows(account) {
|
|
@@ -220,7 +232,8 @@ final class MenuController: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
|
|
220
232
|
action(enabled ? "Disable for future routing" : "Enable for routing", args: ["account", enabled ? "disable" : "enable", id], into: submenu)
|
|
221
233
|
text("Current tasks keep running.", into: submenu)
|
|
222
234
|
}
|
|
223
|
-
let entry = NSMenuItem(title: "\(name) · \(label)", action: nil, keyEquivalent: "")
|
|
235
|
+
let entry = NSMenuItem(title: "\(name)\(inUse) · \(label)", action: nil, keyEquivalent: "")
|
|
236
|
+
entry.state = assigned.isEmpty ? .off : .on
|
|
224
237
|
entry.identifier = NSUserInterfaceItemIdentifier("account:" + (account["id"] as? String ?? name))
|
|
225
238
|
entry.submenu = submenu; menu.addItem(entry)
|
|
226
239
|
}
|
|
@@ -248,7 +261,7 @@ final class MenuController: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
|
|
248
261
|
let modelAllowed = models.isEmpty || model == nil || models.contains(model!)
|
|
249
262
|
let available = (account["enabled"] as? Bool ?? true) && !(account["maintenance"] as? Bool ?? false) && modelAllowed
|
|
250
263
|
let name = account["name"] as? String ?? accountID
|
|
251
|
-
let choice = action(name + (available ? "" : " · unavailable"), args: ["switch", id, "--account", accountID, "--wait"], into: choices)
|
|
264
|
+
let choice = action(name + (selected ? " · Current" : available ? "" : " · unavailable"), args: ["switch", id, "--account", accountID, "--wait"], into: choices)
|
|
252
265
|
choice.state = selected ? .on : .off
|
|
253
266
|
choice.isEnabled = !selected && available && !actionRunning
|
|
254
267
|
}
|
|
@@ -363,6 +376,20 @@ if CommandLine.arguments.contains("--self-check") {
|
|
|
363
376
|
let switchArgs = ["switch", "live", "--account", "two", "--wait"]
|
|
364
377
|
let correctChoices = findAction(switchArgs, in: controls)?.isEnabled == true && findAction(["switch", "live", "--account", "one", "--wait"], in: controls)?.state == .on && findAction(["switch", "live", "--account", "off", "--wait"], in: controls)?.isEnabled == false
|
|
365
378
|
let stoppedControls = findAction(["restart", "stopped", "--if-stopped"], in: controls) != nil && findAction(["pause", "stopped", "--wait"], in: controls) == nil
|
|
379
|
+
let activeMarker = controls.items.first { $0.identifier?.rawValue == "account:one" }
|
|
380
|
+
let currentChoice = findAction(["switch", "live", "--account", "one", "--wait"], in: controls)
|
|
381
|
+
let correctMarker = activeMarker?.state == .on && activeMarker?.title.contains("In use") == true && currentChoice?.title.contains("Current") == true
|
|
382
|
+
let originalSessions = controller.current["sessions"]
|
|
383
|
+
controller.current["sessions"] = [["id": "a", "account": "one", "running": true], ["id": "b", "account": "one", "running": true], ["id": "c", "account": "two", "running": true], ["id": "d", "account": "off", "running": false]]
|
|
384
|
+
let multiple = controller.makeMenu()
|
|
385
|
+
let one = multiple.items.first { $0.identifier?.rawValue == "account:one" }
|
|
386
|
+
let two = multiple.items.first { $0.identifier?.rawValue == "account:two" }
|
|
387
|
+
let off = multiple.items.first { $0.identifier?.rawValue == "account:off" }
|
|
388
|
+
let correctMultiple = one?.title.contains("In use by 2 sessions") == true && two?.state == .on && off?.state == .off
|
|
389
|
+
controller.current["sessions"] = [["id": "stopped", "account": "one", "running": false]]
|
|
390
|
+
let empty = controller.makeMenu()
|
|
391
|
+
let correctEmpty = empty.items.contains { $0.title.contains("No Relay sessions running") } && empty.items.first { $0.identifier?.rawValue == "account:one" }?.state == .off
|
|
392
|
+
controller.current["sessions"] = originalSessions
|
|
366
393
|
controller.actionRunning = true; controller.actionNotice = "Applying change…"
|
|
367
394
|
let pending = controller.makeMenu()
|
|
368
395
|
let correctPending = findAction(switchArgs, in: pending)?.isEnabled == false && findAction(["refresh"], in: pending)?.isEnabled == false && findAction(["copy", "relay attach live"], in: pending)?.isEnabled == true
|
|
@@ -371,7 +398,8 @@ if CommandLine.arguments.contains("--self-check") {
|
|
|
371
398
|
let retainedResult = controller.makeMenu().items.contains { $0.title == "Task is busy." }
|
|
372
399
|
print("Account choices and stopped controls correct: \(correctChoices && stoppedControls)")
|
|
373
400
|
print("Pending action protected and result retained: \(correctPending && retainedResult)")
|
|
374
|
-
|
|
401
|
+
print("In-use accounts and current choice marked: \(correctMarker && correctMultiple && correctEmpty)")
|
|
402
|
+
exit(normal != nil && attention != nil && liveUpdate && safeIdentity && correctTiming && correctChoices && stoppedControls && correctPending && retainedResult && correctMarker && correctMultiple && correctEmpty ? 0 : 1)
|
|
375
403
|
} else {
|
|
376
404
|
let app = NSApplication.shared
|
|
377
405
|
let delegate = MenuController(); app.delegate = delegate; app.run()
|
package/python/router.py
CHANGED
|
@@ -24,7 +24,7 @@ from pool import Pool, blocked, reset_time, failure_kind, file_lock
|
|
|
24
24
|
from launch import translate, RESUME_FIELDS
|
|
25
25
|
import settings
|
|
26
26
|
|
|
27
|
-
VERSION = "0.6.
|
|
27
|
+
VERSION = "0.6.1"
|
|
28
28
|
_support = Path.home() / "Library/Application Support"
|
|
29
29
|
_legacy = _support / "Codex Accounts"
|
|
30
30
|
_default_state = _legacy if (_legacy / "accounts").exists() else _support / "Relay"
|