agentbridge-cli 0.1.16__tar.gz → 0.1.17__tar.gz
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.
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/PKG-INFO +1 -1
- agentbridge_cli-0.1.17/agentbridge/_build_info.py +1 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/AgentBridgeMenuBarApp.swift +0 -1
- agentbridge_cli-0.1.17/macos/Sources/AgentBridgeMenuBar/MenuBarStatusPresenter.swift +78 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Tests/AgentBridgeMenuBarTests/StatusModelsTests.swift +26 -6
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/pyproject.toml +2 -1
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/uv.lock +5 -4
- agentbridge_cli-0.1.16/agentbridge/_build_info.py +0 -1
- agentbridge_cli-0.1.16/macos/Sources/AgentBridgeMenuBar/MenuBarStatusPresenter.swift +0 -120
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.codex/config.toml +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.codex/skills/build-release/SKILL.md +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.codex/skills/build-release/agents/openai.yaml +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.codex/skills/build-release/scripts/release_build.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.env.example +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.github/dependabot.yml +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.github/workflows/ci.yml +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.github/workflows/dependency-review.yml +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.github/workflows/release.yml +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.gitignore +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/AGENTS.md +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/CLAUDE.md +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/LICENSE +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/Makefile +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/README.md +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/TODO.txt +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/__init__.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/config.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/dashboard.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/models.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/pool.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/server.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/android-chrome-192.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/android-chrome-512.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/apple-touch-icon.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/favicon-16.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/favicon-32.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/favicon-48.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/favicon.ico +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/favicon.svg +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/site.webmanifest +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/templates/dashboard/base.html +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/templates/dashboard/chat.html +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/templates/dashboard/detail.html +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/templates/dashboard/page.html +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/templates/dashboard/pool.html +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/templates/dashboard/requests.html +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/architecture.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/agentbridge-popover-final.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/agentbridge-popover-normalized.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/agentbridge-popover-pass-1.jpeg +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/implementation-header-activity.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-header-activity.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-inactive-menu-icons.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-inactive-telegram-badge-normalized.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-inactive-telegram-badge.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-low-contrast-arrows-normalized.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-low-contrast-arrows.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-panel.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-telegram-badge-normalized.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-telegram-badge.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/status-item-active-workers.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/status-item-arrow-contrast-comparison.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/status-item-badge-comparison.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/status-item-inactive-comparison.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/status-item-no-workers.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa.md +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/docs/plans/2026-02-14-dashboard-design.md +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/docs/plans/2026-02-14-dashboard-implementation.md +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/hatch_build.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/apple-store/app-store-icon-1024.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/icon/icon-1024.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/logo/logo-1024.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/manifest.json +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/icon-source-keyed.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/icon-source.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/logo-source-keyed.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/logo-source.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/social-background-source.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/social-source.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/android-chrome-192.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/android-chrome-512.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/apple-touch-icon.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/favicon/favicon-16.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/favicon/favicon-32.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/favicon/favicon-48.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/favicon/favicon.ico +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/favicon/favicon.svg +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/og-image-1200x630.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/site.webmanifest +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/logo.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Package.swift +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/README.md +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/BrandMark.swift +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/HealthClient.swift +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/ServerController.swift +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/ServerLauncher.swift +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/SettingsView.swift +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/StatusModels.swift +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/StatusPopover.swift +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/scripts/build_macos_app.sh +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/scripts/dashboard_load_test.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/scripts/verify_macos_app.sh +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/fixtures/ocr_test_document.png +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_config.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_dashboard.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_dependency_security.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_image_utils.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_model_mapping.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_models.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_pool.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_server.py +0 -0
- {agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/tests/test_session_logger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agentbridge-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.17
|
|
4
4
|
Summary: Bridge OpenAI tools to Claude Code SDK, Codex CLI, and OpenRouter
|
|
5
5
|
Project-URL: Homepage, https://github.com/tsilva/agentbridge
|
|
6
6
|
Project-URL: Repository, https://github.com/tsilva/agentbridge
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
GIT_HASH = "6883ee1"
|
|
@@ -40,7 +40,6 @@ final class AgentBridgeAppDelegate: NSObject, NSApplicationDelegate {
|
|
|
40
40
|
if let button = item.button {
|
|
41
41
|
button.target = self
|
|
42
42
|
button.action = #selector(togglePopover(_:))
|
|
43
|
-
statusPresenter.install(on: button)
|
|
44
43
|
statusPresenter.update(
|
|
45
44
|
button: button,
|
|
46
45
|
phase: controller.phase,
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import AppKit
|
|
2
|
+
|
|
3
|
+
@MainActor
|
|
4
|
+
final class MenuBarStatusPresenter {
|
|
5
|
+
private weak var presentedButton: NSStatusBarButton?
|
|
6
|
+
private var displayedPhase: ServerPhase?
|
|
7
|
+
private(set) var displayedCount: Int?
|
|
8
|
+
|
|
9
|
+
func update(
|
|
10
|
+
button: NSStatusBarButton,
|
|
11
|
+
phase: ServerPhase,
|
|
12
|
+
activeWorkers: Int
|
|
13
|
+
) {
|
|
14
|
+
let count = max(activeWorkers, 0)
|
|
15
|
+
let badgeCount = count > 0 ? count : nil
|
|
16
|
+
guard presentedButton !== button || displayedPhase != phase || displayedCount != badgeCount
|
|
17
|
+
else { return }
|
|
18
|
+
|
|
19
|
+
let label = Self.accessibilityLabel(for: phase, activeWorkers: count)
|
|
20
|
+
let symbol = NSImage(
|
|
21
|
+
systemSymbolName: phase.menuBarSymbol,
|
|
22
|
+
accessibilityDescription: label
|
|
23
|
+
)
|
|
24
|
+
let image = badgeCount.map { Self.badgedImage(symbol: symbol, count: $0) } ?? symbol
|
|
25
|
+
image?.isTemplate = true
|
|
26
|
+
button.image = image
|
|
27
|
+
button.toolTip = label
|
|
28
|
+
button.setAccessibilityLabel(label)
|
|
29
|
+
presentedButton = button
|
|
30
|
+
displayedPhase = phase
|
|
31
|
+
displayedCount = badgeCount
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static func accessibilityLabel(for phase: ServerPhase, activeWorkers: Int) -> String {
|
|
35
|
+
guard activeWorkers > 0 else { return "AgentBridge: \(phase.label)" }
|
|
36
|
+
let noun = activeWorkers == 1 ? "worker" : "workers"
|
|
37
|
+
return "AgentBridge: \(phase.label), \(activeWorkers) active \(noun)"
|
|
38
|
+
}
|
|
39
|
+
private static func badgedImage(symbol: NSImage?, count: Int) -> NSImage {
|
|
40
|
+
let text = NSAttributedString(
|
|
41
|
+
string: String(count),
|
|
42
|
+
attributes: [
|
|
43
|
+
.font: NSFont.systemFont(ofSize: 7.5, weight: .semibold),
|
|
44
|
+
.foregroundColor: NSColor.black,
|
|
45
|
+
]
|
|
46
|
+
)
|
|
47
|
+
let textSize = text.size()
|
|
48
|
+
let badgeWidth = max(11, ceil(textSize.width) + 1.5)
|
|
49
|
+
let size = NSSize(width: max(22, badgeWidth), height: 22)
|
|
50
|
+
|
|
51
|
+
// AppKit snapshots status items under different appearances. A layer-backed
|
|
52
|
+
// badge/text-field subview mutates during those callbacks and can schedule
|
|
53
|
+
// another snapshot indefinitely, even while hidden. Keep the entire icon
|
|
54
|
+
// in one template image so snapshots never update a custom view hierarchy.
|
|
55
|
+
return NSImage(size: size, flipped: false) { rect in
|
|
56
|
+
symbol?.draw(in: NSRect(x: (rect.width - 18) / 2, y: 3, width: 18, height: 18))
|
|
57
|
+
let badge = NSBezierPath(roundedRect: NSRect(
|
|
58
|
+
x: rect.width - badgeWidth, y: 0, width: badgeWidth, height: 11
|
|
59
|
+
), xRadius: 5.5, yRadius: 5.5)
|
|
60
|
+
guard let context = NSGraphicsContext.current?.cgContext else { return false }
|
|
61
|
+
context.saveGState()
|
|
62
|
+
context.setBlendMode(.clear)
|
|
63
|
+
badge.fill()
|
|
64
|
+
context.setBlendMode(.normal)
|
|
65
|
+
NSColor.black.withAlphaComponent(0.48).setFill()
|
|
66
|
+
badge.fill()
|
|
67
|
+
// Cut the number out of the alpha mask; macOS supplies the contrasting
|
|
68
|
+
// foreground color for both light and dark menu bars.
|
|
69
|
+
context.setBlendMode(.destinationOut)
|
|
70
|
+
text.draw(at: NSPoint(
|
|
71
|
+
x: rect.width - badgeWidth + (badgeWidth - textSize.width) / 2,
|
|
72
|
+
y: (11 - textSize.height) / 2
|
|
73
|
+
))
|
|
74
|
+
context.restoreGState()
|
|
75
|
+
return true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -77,8 +77,8 @@ final class StatusModelsTests: XCTestCase {
|
|
|
77
77
|
func testMenuBarBadgeIsHiddenWithoutActiveWorkers() throws {
|
|
78
78
|
let (canvas, button, presenter) = makeMenuBarFixture(activeWorkers: 0)
|
|
79
79
|
|
|
80
|
-
XCTAssertTrue(
|
|
81
|
-
XCTAssertNil(presenter.
|
|
80
|
+
XCTAssertTrue(button.subviews.isEmpty)
|
|
81
|
+
XCTAssertNil(presenter.displayedCount)
|
|
82
82
|
XCTAssertEqual(button.toolTip, "AgentBridge: Running")
|
|
83
83
|
|
|
84
84
|
try writeSnapshot(
|
|
@@ -103,15 +103,15 @@ final class StatusModelsTests: XCTestCase {
|
|
|
103
103
|
activeWorkers: 48
|
|
104
104
|
)
|
|
105
105
|
XCTAssertEqual(button.image?.isTemplate, true)
|
|
106
|
-
|
|
106
|
+
XCTAssertEqual(presenter.displayedCount, 48)
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
@MainActor
|
|
110
110
|
func testMenuBarBadgeShowsActiveWorkerCount() throws {
|
|
111
111
|
let (canvas, button, presenter) = makeMenuBarFixture(activeWorkers: 48)
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
XCTAssertEqual(presenter.
|
|
113
|
+
XCTAssertTrue(button.subviews.isEmpty)
|
|
114
|
+
XCTAssertEqual(presenter.displayedCount, 48)
|
|
115
115
|
XCTAssertEqual(button.toolTip, "AgentBridge: Running, 48 active workers")
|
|
116
116
|
XCTAssertEqual(button.image?.isTemplate, true)
|
|
117
117
|
|
|
@@ -121,6 +121,27 @@ final class StatusModelsTests: XCTestCase {
|
|
|
121
121
|
)
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
@MainActor
|
|
125
|
+
func testUnchangedHealthDoesNotReplaceStatusImage() {
|
|
126
|
+
let (_, button, presenter) = makeMenuBarFixture(activeWorkers: 2)
|
|
127
|
+
let image = button.image
|
|
128
|
+
|
|
129
|
+
for _ in 0..<10 {
|
|
130
|
+
presenter.update(button: button, phase: .runningManaged, activeWorkers: 2)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
XCTAssertTrue(button.image === image)
|
|
134
|
+
XCTAssertTrue(button.subviews.isEmpty)
|
|
135
|
+
|
|
136
|
+
presenter.update(button: button, phase: .runningManaged, activeWorkers: 0)
|
|
137
|
+
XCTAssertFalse(button.image === image)
|
|
138
|
+
XCTAssertNil(presenter.displayedCount)
|
|
139
|
+
XCTAssertEqual(button.toolTip, "AgentBridge: Running")
|
|
140
|
+
|
|
141
|
+
presenter.update(button: button, phase: .failed, activeWorkers: 0)
|
|
142
|
+
XCTAssertEqual(button.toolTip, "AgentBridge: Needs attention")
|
|
143
|
+
}
|
|
144
|
+
|
|
124
145
|
@MainActor
|
|
125
146
|
private func makeMenuBarFixture(
|
|
126
147
|
activeWorkers: Int
|
|
@@ -139,7 +160,6 @@ final class StatusModelsTests: XCTestCase {
|
|
|
139
160
|
button.isBordered = false
|
|
140
161
|
canvas.addSubview(button)
|
|
141
162
|
let presenter = MenuBarStatusPresenter()
|
|
142
|
-
presenter.install(on: button)
|
|
143
163
|
presenter.update(
|
|
144
164
|
button: button,
|
|
145
165
|
phase: .runningManaged,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agentbridge-cli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.17"
|
|
4
4
|
description = "Bridge OpenAI tools to Claude Code SDK, Codex CLI, and OpenRouter"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = {text = "MIT"}
|
|
@@ -71,6 +71,7 @@ select = ["E", "F", "I"]
|
|
|
71
71
|
required-version = "==0.11.13"
|
|
72
72
|
exclude-newer = "7 days"
|
|
73
73
|
constraint-dependencies = [
|
|
74
|
+
"anyio>=4.14.2",
|
|
74
75
|
"click>=8.3.3",
|
|
75
76
|
"cryptography>=50.0.0",
|
|
76
77
|
"idna>=3.15",
|
|
@@ -22,6 +22,7 @@ gradlab = false
|
|
|
22
22
|
|
|
23
23
|
[manifest]
|
|
24
24
|
constraints = [
|
|
25
|
+
{ name = "anyio", specifier = ">=4.14.2" },
|
|
25
26
|
{ name = "click", specifier = ">=8.3.3" },
|
|
26
27
|
{ name = "cryptography", specifier = ">=50.0.0" },
|
|
27
28
|
{ name = "guardrails-ai", specifier = "!=0.10.1" },
|
|
@@ -37,7 +38,7 @@ constraints = [
|
|
|
37
38
|
|
|
38
39
|
[[package]]
|
|
39
40
|
name = "agentbridge-cli"
|
|
40
|
-
version = "0.1.
|
|
41
|
+
version = "0.1.17"
|
|
41
42
|
source = { editable = "." }
|
|
42
43
|
dependencies = [
|
|
43
44
|
{ name = "claude-agent-sdk" },
|
|
@@ -91,15 +92,15 @@ wheels = [
|
|
|
91
92
|
|
|
92
93
|
[[package]]
|
|
93
94
|
name = "anyio"
|
|
94
|
-
version = "4.
|
|
95
|
+
version = "4.14.2"
|
|
95
96
|
source = { registry = "https://pypi.org/simple" }
|
|
96
97
|
dependencies = [
|
|
97
98
|
{ name = "idna" },
|
|
98
99
|
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
|
99
100
|
]
|
|
100
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
101
|
+
sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" }
|
|
101
102
|
wheels = [
|
|
102
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
103
|
+
{ url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" },
|
|
103
104
|
]
|
|
104
105
|
|
|
105
106
|
[[package]]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
GIT_HASH = "4d5ec6b"
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import AppKit
|
|
2
|
-
|
|
3
|
-
@MainActor
|
|
4
|
-
final class MenuBarStatusPresenter {
|
|
5
|
-
let badgeView = MenuBarActivityBadgeView()
|
|
6
|
-
|
|
7
|
-
func install(on button: NSStatusBarButton) {
|
|
8
|
-
guard badgeView.superview !== button else { return }
|
|
9
|
-
|
|
10
|
-
badgeView.translatesAutoresizingMaskIntoConstraints = false
|
|
11
|
-
button.addSubview(badgeView)
|
|
12
|
-
NSLayoutConstraint.activate([
|
|
13
|
-
badgeView.trailingAnchor.constraint(equalTo: button.trailingAnchor),
|
|
14
|
-
badgeView.bottomAnchor.constraint(equalTo: button.bottomAnchor, constant: 2),
|
|
15
|
-
badgeView.heightAnchor.constraint(equalToConstant: 11),
|
|
16
|
-
])
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
func update(
|
|
20
|
-
button: NSStatusBarButton,
|
|
21
|
-
phase: ServerPhase,
|
|
22
|
-
activeWorkers: Int
|
|
23
|
-
) {
|
|
24
|
-
let count = max(activeWorkers, 0)
|
|
25
|
-
let label = Self.accessibilityLabel(for: phase, activeWorkers: count)
|
|
26
|
-
let image = NSImage(
|
|
27
|
-
systemSymbolName: phase.menuBarSymbol,
|
|
28
|
-
accessibilityDescription: label
|
|
29
|
-
)
|
|
30
|
-
image?.isTemplate = true
|
|
31
|
-
button.image = image
|
|
32
|
-
button.toolTip = label
|
|
33
|
-
button.setAccessibilityLabel(label)
|
|
34
|
-
badgeView.update(count: count)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static func accessibilityLabel(for phase: ServerPhase, activeWorkers: Int) -> String {
|
|
38
|
-
guard activeWorkers > 0 else { return "AgentBridge: \(phase.label)" }
|
|
39
|
-
let noun = activeWorkers == 1 ? "worker" : "workers"
|
|
40
|
-
return "AgentBridge: \(phase.label), \(activeWorkers) active \(noun)"
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@MainActor
|
|
45
|
-
final class MenuBarActivityBadgeView: NSView {
|
|
46
|
-
private let countLabel = NSTextField(labelWithString: "")
|
|
47
|
-
|
|
48
|
-
private(set) var displayedCount: Int?
|
|
49
|
-
|
|
50
|
-
override init(frame frameRect: NSRect) {
|
|
51
|
-
super.init(frame: frameRect)
|
|
52
|
-
configureView()
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
required init?(coder: NSCoder) {
|
|
56
|
-
super.init(coder: coder)
|
|
57
|
-
configureView()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
override var intrinsicContentSize: NSSize {
|
|
61
|
-
let labelWidth = ceil(countLabel.intrinsicContentSize.width)
|
|
62
|
-
return NSSize(width: max(11, labelWidth + 1.5), height: 11)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
override func hitTest(_ point: NSPoint) -> NSView? {
|
|
66
|
-
nil
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
override func viewDidChangeEffectiveAppearance() {
|
|
70
|
-
super.viewDidChangeEffectiveAppearance()
|
|
71
|
-
updateColors()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
func update(count: Int) {
|
|
75
|
-
guard count > 0 else {
|
|
76
|
-
displayedCount = nil
|
|
77
|
-
countLabel.stringValue = ""
|
|
78
|
-
isHidden = true
|
|
79
|
-
invalidateIntrinsicContentSize()
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
displayedCount = count
|
|
84
|
-
countLabel.stringValue = String(count)
|
|
85
|
-
isHidden = false
|
|
86
|
-
invalidateIntrinsicContentSize()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private func configureView() {
|
|
90
|
-
wantsLayer = true
|
|
91
|
-
layer?.cornerRadius = 5.5
|
|
92
|
-
layer?.cornerCurve = .continuous
|
|
93
|
-
|
|
94
|
-
countLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
95
|
-
countLabel.font = .systemFont(ofSize: 7.5, weight: .semibold)
|
|
96
|
-
countLabel.alignment = .center
|
|
97
|
-
countLabel.lineBreakMode = .byClipping
|
|
98
|
-
countLabel.maximumNumberOfLines = 1
|
|
99
|
-
addSubview(countLabel)
|
|
100
|
-
|
|
101
|
-
NSLayoutConstraint.activate([
|
|
102
|
-
countLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0.75),
|
|
103
|
-
countLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -0.75),
|
|
104
|
-
countLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
105
|
-
])
|
|
106
|
-
|
|
107
|
-
setAccessibilityElement(false)
|
|
108
|
-
isHidden = true
|
|
109
|
-
updateColors()
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private func updateColors() {
|
|
113
|
-
let match = effectiveAppearance.bestMatch(from: [.darkAqua, .aqua])
|
|
114
|
-
let usesDarkMenuBar = match == .darkAqua
|
|
115
|
-
layer?.backgroundColor = NSColor.labelColor.withAlphaComponent(0.48).cgColor
|
|
116
|
-
countLabel.textColor = usesDarkMenuBar
|
|
117
|
-
? NSColor.black.withAlphaComponent(0.78)
|
|
118
|
-
: NSColor.white.withAlphaComponent(0.94)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/.codex/skills/build-release/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/android-chrome-192.png
RENAMED
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/android-chrome-512.png
RENAMED
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/static/brand/apple-touch-icon.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/templates/dashboard/detail.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/agentbridge/templates/dashboard/requests.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/agentbridge-popover-normalized.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/implementation-header-activity.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-inactive-menu-icons.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-inactive-telegram-badge.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-low-contrast-arrows.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/reference-telegram-badge-normalized.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/status-item-badge-comparison.png
RENAMED
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/design-qa/status-item-inactive-comparison.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/docs/plans/2026-02-14-dashboard-implementation.md
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/apple-store/app-store-icon-1024.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/icon-source-keyed.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/logo-source-keyed.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/sources/social-background-source.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/android-chrome-192.png
RENAMED
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/android-chrome-512.png
RENAMED
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/favicon/favicon-16.png
RENAMED
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/favicon/favicon-32.png
RENAMED
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/favicon/favicon-48.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/image-assets/web-seo/og-image-1200x630.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbridge_cli-0.1.16 → agentbridge_cli-0.1.17}/macos/Sources/AgentBridgeMenuBar/BrandMark.swift
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|