agentbridge-cli 0.1.11__tar.gz → 0.1.13__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.
Files changed (129) hide show
  1. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.codex/skills/build-release/SKILL.md +28 -11
  2. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.codex/skills/build-release/scripts/release_build.py +41 -1
  3. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.github/dependabot.yml +19 -0
  4. agentbridge_cli-0.1.13/.github/workflows/ci.yml +52 -0
  5. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.github/workflows/release.yml +127 -16
  6. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.gitignore +2 -0
  7. agentbridge_cli-0.1.11/README.md → agentbridge_cli-0.1.13/PKG-INFO +77 -5
  8. agentbridge_cli-0.1.11/PKG-INFO → agentbridge_cli-0.1.13/README.md +45 -35
  9. agentbridge_cli-0.1.13/agentbridge/_build_info.py +1 -0
  10. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/dashboard.py +46 -0
  11. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/pool.py +1 -0
  12. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/server.py +55 -16
  13. agentbridge_cli-0.1.13/agentbridge/static/brand/android-chrome-192.png +0 -0
  14. agentbridge_cli-0.1.13/agentbridge/static/brand/android-chrome-512.png +0 -0
  15. agentbridge_cli-0.1.13/agentbridge/static/brand/apple-touch-icon.png +0 -0
  16. agentbridge_cli-0.1.13/agentbridge/static/brand/favicon-16.png +0 -0
  17. agentbridge_cli-0.1.13/agentbridge/static/brand/favicon-32.png +0 -0
  18. agentbridge_cli-0.1.13/agentbridge/static/brand/favicon-48.png +0 -0
  19. agentbridge_cli-0.1.13/agentbridge/static/brand/favicon.ico +0 -0
  20. agentbridge_cli-0.1.13/agentbridge/static/brand/favicon.svg +11 -0
  21. {agentbridge_cli-0.1.11/image-assets/web-seo → agentbridge_cli-0.1.13/agentbridge/static/brand}/site.webmanifest +4 -4
  22. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/templates/dashboard/base.html +28 -21
  23. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/templates/dashboard/chat.html +1 -1
  24. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/templates/dashboard/page.html +1 -1
  25. agentbridge_cli-0.1.13/design-qa/agentbridge-popover-final.png +0 -0
  26. agentbridge_cli-0.1.13/design-qa/agentbridge-popover-normalized.png +0 -0
  27. agentbridge_cli-0.1.13/design-qa/agentbridge-popover-pass-1.jpeg +0 -0
  28. agentbridge_cli-0.1.13/design-qa/implementation-header-activity.png +0 -0
  29. agentbridge_cli-0.1.13/design-qa/reference-header-activity.png +0 -0
  30. agentbridge_cli-0.1.13/design-qa/reference-inactive-menu-icons.png +0 -0
  31. agentbridge_cli-0.1.13/design-qa/reference-inactive-telegram-badge-normalized.png +0 -0
  32. agentbridge_cli-0.1.13/design-qa/reference-inactive-telegram-badge.png +0 -0
  33. agentbridge_cli-0.1.13/design-qa/reference-low-contrast-arrows-normalized.png +0 -0
  34. agentbridge_cli-0.1.13/design-qa/reference-low-contrast-arrows.png +0 -0
  35. agentbridge_cli-0.1.13/design-qa/reference-panel.png +0 -0
  36. agentbridge_cli-0.1.13/design-qa/reference-telegram-badge-normalized.png +0 -0
  37. agentbridge_cli-0.1.13/design-qa/reference-telegram-badge.png +0 -0
  38. agentbridge_cli-0.1.13/design-qa/status-item-active-workers.png +0 -0
  39. agentbridge_cli-0.1.13/design-qa/status-item-arrow-contrast-comparison.png +0 -0
  40. agentbridge_cli-0.1.13/design-qa/status-item-badge-comparison.png +0 -0
  41. agentbridge_cli-0.1.13/design-qa/status-item-inactive-comparison.png +0 -0
  42. agentbridge_cli-0.1.13/design-qa/status-item-no-workers.png +0 -0
  43. agentbridge_cli-0.1.13/design-qa.md +58 -0
  44. agentbridge_cli-0.1.13/image-assets/apple-store/app-store-icon-1024.png +0 -0
  45. agentbridge_cli-0.1.13/image-assets/icon/icon-1024.png +0 -0
  46. agentbridge_cli-0.1.13/image-assets/logo/logo-1024.png +0 -0
  47. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/image-assets/manifest.json +14 -2
  48. agentbridge_cli-0.1.13/image-assets/sources/icon-source-keyed.png +0 -0
  49. agentbridge_cli-0.1.13/image-assets/sources/icon-source.png +0 -0
  50. agentbridge_cli-0.1.13/image-assets/sources/logo-source-keyed.png +0 -0
  51. agentbridge_cli-0.1.13/image-assets/sources/logo-source.png +0 -0
  52. agentbridge_cli-0.1.13/image-assets/sources/social-background-source.png +0 -0
  53. agentbridge_cli-0.1.13/image-assets/sources/social-source.png +0 -0
  54. agentbridge_cli-0.1.13/image-assets/web-seo/android-chrome-192.png +0 -0
  55. agentbridge_cli-0.1.13/image-assets/web-seo/android-chrome-512.png +0 -0
  56. agentbridge_cli-0.1.13/image-assets/web-seo/apple-touch-icon.png +0 -0
  57. agentbridge_cli-0.1.13/image-assets/web-seo/favicon/favicon-16.png +0 -0
  58. agentbridge_cli-0.1.13/image-assets/web-seo/favicon/favicon-32.png +0 -0
  59. agentbridge_cli-0.1.13/image-assets/web-seo/favicon/favicon-48.png +0 -0
  60. agentbridge_cli-0.1.13/image-assets/web-seo/favicon/favicon.ico +0 -0
  61. agentbridge_cli-0.1.13/image-assets/web-seo/favicon/favicon.svg +11 -0
  62. agentbridge_cli-0.1.13/image-assets/web-seo/og-image-1200x630.png +0 -0
  63. agentbridge_cli-0.1.13/image-assets/web-seo/site.webmanifest +21 -0
  64. agentbridge_cli-0.1.13/logo.png +0 -0
  65. agentbridge_cli-0.1.13/macos/Package.swift +21 -0
  66. agentbridge_cli-0.1.13/macos/README.md +50 -0
  67. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/AgentBridgeMenuBarApp.swift +177 -0
  68. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/BrandMark.swift +40 -0
  69. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/HealthClient.swift +67 -0
  70. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/MenuBarStatusPresenter.swift +135 -0
  71. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/ServerController.swift +266 -0
  72. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/ServerLauncher.swift +116 -0
  73. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/SettingsView.swift +225 -0
  74. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/StatusModels.swift +131 -0
  75. agentbridge_cli-0.1.13/macos/Sources/AgentBridgeMenuBar/StatusPopover.swift +284 -0
  76. agentbridge_cli-0.1.13/macos/Tests/AgentBridgeMenuBarTests/StatusModelsTests.swift +148 -0
  77. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/pyproject.toml +26 -7
  78. agentbridge_cli-0.1.13/scripts/build_macos_app.sh +159 -0
  79. agentbridge_cli-0.1.13/scripts/verify_macos_app.sh +25 -0
  80. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/test_dashboard.py +50 -2
  81. agentbridge_cli-0.1.13/tests/test_dependency_security.py +74 -0
  82. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/test_pool.py +5 -0
  83. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/test_server.py +28 -0
  84. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/uv.lock +553 -99
  85. agentbridge_cli-0.1.11/.github/workflows/ci.yml +0 -36
  86. agentbridge_cli-0.1.11/agentbridge/_build_info.py +0 -1
  87. agentbridge_cli-0.1.11/image-assets/icon/icon-1024.png +0 -0
  88. agentbridge_cli-0.1.11/image-assets/logo/logo-1024.png +0 -0
  89. agentbridge_cli-0.1.11/image-assets/sources/icon-source-keyed.png +0 -0
  90. agentbridge_cli-0.1.11/image-assets/sources/icon-source.png +0 -0
  91. agentbridge_cli-0.1.11/image-assets/sources/logo-source-keyed.png +0 -0
  92. agentbridge_cli-0.1.11/image-assets/sources/logo-source.png +0 -0
  93. agentbridge_cli-0.1.11/image-assets/sources/social-background-source.png +0 -0
  94. agentbridge_cli-0.1.11/image-assets/sources/social-source.png +0 -0
  95. agentbridge_cli-0.1.11/image-assets/web-seo/android-chrome-192.png +0 -0
  96. agentbridge_cli-0.1.11/image-assets/web-seo/android-chrome-512.png +0 -0
  97. agentbridge_cli-0.1.11/image-assets/web-seo/apple-touch-icon.png +0 -0
  98. agentbridge_cli-0.1.11/image-assets/web-seo/favicon/favicon-16.png +0 -0
  99. agentbridge_cli-0.1.11/image-assets/web-seo/favicon/favicon-32.png +0 -0
  100. agentbridge_cli-0.1.11/image-assets/web-seo/favicon/favicon-48.png +0 -0
  101. agentbridge_cli-0.1.11/image-assets/web-seo/favicon/favicon.ico +0 -0
  102. agentbridge_cli-0.1.11/image-assets/web-seo/og-image-1200x630.png +0 -0
  103. agentbridge_cli-0.1.11/logo.png +0 -0
  104. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.codex/config.toml +0 -0
  105. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.codex/skills/build-release/agents/openai.yaml +0 -0
  106. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.env.example +0 -0
  107. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/.github/workflows/dependency-review.yml +0 -0
  108. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/AGENTS.md +0 -0
  109. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/CLAUDE.md +0 -0
  110. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/LICENSE +0 -0
  111. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/Makefile +0 -0
  112. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/TODO.txt +0 -0
  113. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/__init__.py +0 -0
  114. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/config.py +0 -0
  115. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/models.py +0 -0
  116. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/templates/dashboard/detail.html +0 -0
  117. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/templates/dashboard/pool.html +0 -0
  118. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/agentbridge/templates/dashboard/requests.html +0 -0
  119. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/architecture.png +0 -0
  120. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/docs/plans/2026-02-14-dashboard-design.md +0 -0
  121. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/docs/plans/2026-02-14-dashboard-implementation.md +0 -0
  122. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/hatch_build.py +0 -0
  123. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/scripts/dashboard_load_test.py +0 -0
  124. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/fixtures/ocr_test_document.png +0 -0
  125. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/test_config.py +0 -0
  126. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/test_image_utils.py +0 -0
  127. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/test_model_mapping.py +0 -0
  128. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/test_models.py +0 -0
  129. {agentbridge_cli-0.1.11 → agentbridge_cli-0.1.13}/tests/test_session_logger.py +0 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: build-release
3
- description: Build, publish, and verify AgentBridge releases. Use when the user invokes /build-release or asks to cut, launch, tag, publish, monitor, or verify an agentbridge-cli PyPI or GitHub release.
3
+ description: Build, publish, and verify AgentBridge releases. Use when the user invokes /build-release or asks to cut, launch, tag, publish, monitor, or verify the agentbridge-cli PyPI package or macOS app.
4
4
  ---
5
5
 
6
6
  # Build Release
@@ -9,7 +9,7 @@ Use the repository-owned GitHub Actions workflow and PyPI Trusted Publishing.
9
9
  Do not create a local tag or upload with local credentials: pushing a new
10
10
  `pyproject.toml` version to `main` triggers `.github/workflows/release.yml`,
11
11
  which tests, scans, builds, creates `v<version>`, creates the GitHub Release,
12
- and publishes `agentbridge-cli`.
12
+ publishes `agentbridge-cli`, and attaches ad-hoc-signed arm64 and x86_64 DMGs.
13
13
 
14
14
  Use the next unused patch version unless the user requests another valid,
15
15
  unused semantic version. Treat an untagged version absent from PyPI as pending.
@@ -28,6 +28,9 @@ git log --oneline HEAD..origin/main
28
28
  Stop on unrelated changes, unpublished commits, divergence, or another branch.
29
29
  Do not clean, pull, commit unrelated files, or switch branches.
30
30
 
31
+ The macOS artifacts use an ad-hoc signature and are not notarized. They do not
32
+ require Apple Developer credentials or repository secrets.
33
+
31
34
  2. Select the release version from the repository root:
32
35
 
33
36
  ```bash
@@ -47,10 +50,12 @@ uv lock
47
50
  python3 .codex/skills/build-release/scripts/release_build.py preflight --version <version>
48
51
  ```
49
52
 
50
- The preflight requires consistent project and lock metadata, an unused PyPI
51
- version and tag, clean patch formatting, a frozen lock, passing tests on Python
52
- 3.12 and 3.13, Ruff, a successful wheel and sdist build, artifact audits, and a
53
- wheel installation smoke test. Stop at the exact failed gate.
53
+ The preflight requires macOS. It checks consistent project and lock metadata, an
54
+ unused PyPI version and tag, clean patch formatting, a frozen lock, Python 3.12
55
+ and 3.13 tests, Ruff, Swift tests, a self-contained app/DMG build for the current
56
+ Mac architecture, app signature and embedded-runtime smoke tests, wheel and
57
+ sdist audits, and a wheel installation smoke test. CI builds both macOS
58
+ architectures with ad-hoc signatures. Stop at the exact failed gate.
54
59
 
55
60
  4. Review and publish the release commit:
56
61
 
@@ -87,12 +92,24 @@ python3 .codex/skills/build-release/scripts/release_build.py wait-pypi --version
87
92
  gh release view v<version> --json url,tagName,assets
88
93
  ```
89
94
 
90
- Do not report success until PyPI returns files for the exact version. If the
91
- workflow fails, inspect `gh run view <run-id> --log-failed` and report the
92
- failed gate before considering recovery.
95
+ Require both
96
+ `AgentBridge-<version>-macos-arm64.dmg` and
97
+ `AgentBridge-<version>-macos-x86_64.dmg` plus their `.sha256` files in the
98
+ release assets. Do not report success until PyPI returns exact-version files and
99
+ all required GitHub assets exist. If the workflow fails, inspect
100
+ `gh run view <run-id> --log-failed` and report the failed gate before considering
101
+ recovery.
102
+
103
+ If an existing release is missing only its macOS assets, attach them without
104
+ republishing Python distributions:
105
+
106
+ ```bash
107
+ gh workflow run release.yml --ref main -f attach_macos=true
108
+ ```
93
109
 
94
110
  ## Final Response
95
111
 
96
112
  Lead with the exact PyPI version URL. Report the tag, release workflow URL and
97
- conclusion, GitHub Release URL, pushed commit, and every distribution filename.
98
- On failure, report the exact command or job and the next safe recovery action.
113
+ conclusion, GitHub Release URL, pushed commit, every Python distribution, and
114
+ every macOS DMG/checksum filename. On failure, report the exact command or job
115
+ and the next safe recovery action.
@@ -7,6 +7,7 @@ import argparse
7
7
  import email.parser
8
8
  import hashlib
9
9
  import json
10
+ import platform
10
11
  import re
11
12
  import subprocess
12
13
  import sys
@@ -307,6 +308,40 @@ def smoke_wheel(wheel: Path, version: str) -> None:
307
308
  run([str(installed_python), "-c", code])
308
309
 
309
310
 
311
+ def preflight_macos_app(version: str) -> dict[str, object]:
312
+ if sys.platform != "darwin":
313
+ raise SystemExit("the AgentBridge release preflight requires macOS for app validation")
314
+
315
+ architecture = platform.machine()
316
+ if architecture not in {"arm64", "x86_64"}:
317
+ raise SystemExit(f"unsupported macOS release architecture: {architecture}")
318
+
319
+ run(["swift", "test", "--package-path", "macos"])
320
+ run(["scripts/build_macos_app.sh"])
321
+
322
+ output = REPO_ROOT / "build" / "macos" / architecture
323
+ app = output / "AgentBridge.app"
324
+ dmg = output / f"AgentBridge-{version}-macos-{architecture}.dmg"
325
+ checksum = Path(f"{dmg}.sha256")
326
+ run(["scripts/verify_macos_app.sh", str(app)])
327
+
328
+ if not dmg.is_file() or not checksum.is_file():
329
+ raise SystemExit(f"macOS release artifacts are missing under {output}")
330
+ recorded_hash = checksum.read_text(encoding="utf-8").split(maxsplit=1)[0]
331
+ actual_hash = sha256(dmg)
332
+ if recorded_hash != actual_hash:
333
+ raise SystemExit(f"macOS DMG checksum mismatch: {dmg.name}")
334
+
335
+ result = {
336
+ "file": dmg.name,
337
+ "sha256": actual_hash,
338
+ "architecture": architecture,
339
+ "signing": "local preflight signature",
340
+ }
341
+ print(json.dumps({"macos_app": result}, indent=2))
342
+ return result
343
+
344
+
310
345
  def preflight(args: argparse.Namespace) -> None:
311
346
  version = args.version
312
347
  check_version(version)
@@ -342,6 +377,7 @@ def preflight(args: argparse.Namespace) -> None:
342
377
  ".codex/skills/build-release/scripts/release_build.py",
343
378
  ]
344
379
  )
380
+ macos_result = preflight_macos_app(version)
345
381
  with tempfile.TemporaryDirectory(prefix="agentbridge-release-") as directory:
346
382
  output = Path(directory) / "dist"
347
383
  run(["uv", "build", "--out-dir", str(output)])
@@ -356,7 +392,11 @@ def preflight(args: argparse.Namespace) -> None:
356
392
  smoke_wheel(wheels[0], version)
357
393
  print(
358
394
  json.dumps(
359
- {"package": PACKAGE_NAME, "version": version, "artifacts": results},
395
+ {
396
+ "package": PACKAGE_NAME,
397
+ "version": version,
398
+ "artifacts": results + [macos_result],
399
+ },
360
400
  indent=2,
361
401
  )
362
402
  )
@@ -10,6 +10,18 @@ updates:
10
10
  cooldown:
11
11
  default-days: 7
12
12
  open-pull-requests-limit: 5
13
+ groups:
14
+ security-updates:
15
+ applies-to: security-updates
16
+ patterns:
17
+ - "*"
18
+ minor-and-patch:
19
+ applies-to: version-updates
20
+ update-types:
21
+ - minor
22
+ - patch
23
+ patterns:
24
+ - "*"
13
25
 
14
26
  - package-ecosystem: github-actions
15
27
  directory: /
@@ -21,3 +33,10 @@ updates:
21
33
  cooldown:
22
34
  default-days: 7
23
35
  open-pull-requests-limit: 5
36
+ groups:
37
+ minor-and-patch:
38
+ update-types:
39
+ - minor
40
+ - patch
41
+ patterns:
42
+ - "*"
@@ -0,0 +1,52 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ merge_group:
9
+ types:
10
+ - checks_requested
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ test:
17
+ runs-on: ubuntu-latest
18
+ strategy:
19
+ matrix:
20
+ python-version: ["3.12", "3.13"]
21
+ steps:
22
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23
+ with:
24
+ persist-credentials: false
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
28
+ with:
29
+ enable-cache: true
30
+ cache-dependency-glob: "uv.lock"
31
+
32
+ - name: Set up Python ${{ matrix.python-version }}
33
+ run: uv python install ${{ matrix.python-version }}
34
+
35
+ - name: Install dependencies
36
+ run: uv sync --frozen --extra test --python ${{ matrix.python-version }}
37
+
38
+ - name: Audit dependencies
39
+ run: uv run --frozen --extra test --python ${{ matrix.python-version }} pip-audit
40
+
41
+ - name: Lint
42
+ run: uv run --frozen --extra test --python ${{ matrix.python-version }} ruff check agentbridge tests
43
+
44
+ - name: Run tests
45
+ run: uv run --frozen --extra test --python ${{ matrix.python-version }} pytest -q
46
+
47
+ - name: Smoke test CLI
48
+ run: uv run --frozen --python ${{ matrix.python-version }} agentbridge --help
49
+
50
+ - name: Build package
51
+ if: matrix.python-version == '3.12'
52
+ run: uv build
@@ -8,6 +8,11 @@ on:
8
8
  required: false
9
9
  default: false
10
10
  type: boolean
11
+ attach_macos:
12
+ description: Build and attach macOS DMGs to the current version's existing release
13
+ required: false
14
+ default: false
15
+ type: boolean
11
16
  push:
12
17
  branches: [main]
13
18
  paths:
@@ -28,7 +33,7 @@ jobs:
28
33
  outputs:
29
34
  should-publish: ${{ steps.publish.outputs.should-publish }}
30
35
  steps:
31
- - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
36
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
32
37
  with:
33
38
  fetch-depth: 0
34
39
  persist-credentials: false
@@ -52,36 +57,51 @@ jobs:
52
57
  matrix:
53
58
  python-version: ["3.12", "3.13"]
54
59
  steps:
55
- - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
60
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
56
61
  with:
57
62
  persist-credentials: false
58
63
  - name: Install uv
59
- uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
64
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
60
65
  with:
61
66
  enable-cache: true
62
67
  cache-dependency-glob: "uv.lock"
63
68
  - name: Set up Python ${{ matrix.python-version }}
64
69
  run: uv python install ${{ matrix.python-version }}
65
70
  - name: Install dependencies
66
- run: uv sync --all-extras --python ${{ matrix.python-version }}
71
+ run: uv sync --frozen --extra test --python ${{ matrix.python-version }}
72
+ - name: Audit dependencies
73
+ run: uv run --frozen --extra test --python ${{ matrix.python-version }} pip-audit
74
+ - name: Lint
75
+ run: uv run --frozen --extra test --python ${{ matrix.python-version }} ruff check agentbridge tests
67
76
  - name: Run tests
68
- run: uv run --python ${{ matrix.python-version }} pytest tests/ -v --tb=short
77
+ run: uv run --frozen --extra test --python ${{ matrix.python-version }} pytest -q
69
78
 
70
79
  pii-scan:
71
80
  runs-on: ubuntu-latest
72
81
  permissions:
73
82
  contents: read
74
83
  steps:
75
- - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
84
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
76
85
  with:
77
86
  persist-credentials: false
78
87
  - name: Run gitleaks
79
- uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2
88
+ uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0
80
89
  env:
81
90
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
82
91
 
92
+ macos-test:
93
+ runs-on: macos-15
94
+ permissions:
95
+ contents: read
96
+ steps:
97
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
98
+ with:
99
+ persist-credentials: false
100
+ - name: Test menu-bar app
101
+ run: swift test --package-path macos
102
+
83
103
  build:
84
- needs: [changes, test, pii-scan]
104
+ needs: [changes, test, pii-scan, macos-test]
85
105
  if: needs.changes.outputs.should-publish == 'true'
86
106
  runs-on: ubuntu-latest
87
107
  timeout-minutes: 15
@@ -91,7 +111,7 @@ jobs:
91
111
  publish: ${{ steps.check-version.outputs.tag_exists == 'false' }}
92
112
  tag: ${{ steps.check-version.outputs.tag }}
93
113
  steps:
94
- - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
114
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
95
115
  with:
96
116
  fetch-depth: 0
97
117
  persist-credentials: false
@@ -122,7 +142,7 @@ jobs:
122
142
  echo "Version ${version} maps to ${tag}; tag_exists=${tag_exists}"
123
143
  - name: Setup uv
124
144
  if: steps.check-version.outputs.tag_exists == 'false'
125
- uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
145
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
126
146
  with:
127
147
  enable-cache: true
128
148
  cache-dependency-glob: "uv.lock"
@@ -175,26 +195,79 @@ jobs:
175
195
  PY
176
196
  - name: Store package artifacts
177
197
  if: steps.check-version.outputs.tag_exists == 'false'
178
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
198
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
179
199
  with:
180
200
  name: python-package-${{ github.sha }}
181
201
  path: dist/
182
202
  if-no-files-found: error
183
203
  retention-days: 1
184
204
 
205
+ macos-app:
206
+ needs: [build]
207
+ if: >-
208
+ always() &&
209
+ (needs.build.outputs.publish == 'true' ||
210
+ (github.event_name == 'workflow_dispatch' && inputs.attach_macos == true))
211
+ strategy:
212
+ fail-fast: false
213
+ matrix:
214
+ include:
215
+ - runner: macos-15
216
+ architecture: arm64
217
+ - runner: macos-15-intel
218
+ architecture: x86_64
219
+ runs-on: ${{ matrix.runner }}
220
+ timeout-minutes: 30
221
+ permissions:
222
+ contents: read
223
+ steps:
224
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
225
+ with:
226
+ persist-credentials: false
227
+ - name: Install uv
228
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
229
+ with:
230
+ enable-cache: true
231
+ cache-dependency-glob: "uv.lock"
232
+ - name: Install Python 3.12
233
+ run: uv python install 3.12
234
+ - name: Build ad-hoc-signed application
235
+ run: scripts/build_macos_app.sh
236
+ - name: Verify embedded application
237
+ run: scripts/verify_macos_app.sh "build/macos/${{ matrix.architecture }}/AgentBridge.app"
238
+ - name: Store macOS artifacts
239
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
240
+ with:
241
+ name: macos-app-${{ matrix.architecture }}-${{ github.sha }}
242
+ path: |
243
+ build/macos/${{ matrix.architecture }}/*.dmg
244
+ build/macos/${{ matrix.architecture }}/*.dmg.sha256
245
+ if-no-files-found: error
246
+ retention-days: 1
247
+
185
248
  release:
186
- needs: [build, publish]
187
- if: needs.build.outputs.publish == 'true'
249
+ needs: [build, publish, macos-app]
250
+ if: >-
251
+ always() &&
252
+ needs.build.outputs.publish == 'true' &&
253
+ needs.publish.result == 'success' &&
254
+ needs.macos-app.result == 'success'
188
255
  runs-on: ubuntu-latest
189
256
  timeout-minutes: 10
190
257
  permissions:
191
258
  contents: write
192
259
  steps:
193
260
  - name: Download package artifacts
194
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
261
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
195
262
  with:
196
263
  name: python-package-${{ github.sha }}
197
264
  path: dist/
265
+ - name: Download macOS artifacts
266
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
267
+ with:
268
+ pattern: macos-app-*-${{ github.sha }}
269
+ path: dist/
270
+ merge-multiple: true
198
271
  - name: Create GitHub release
199
272
  run: gh release create "$TAG" --title "$TAG" --generate-notes dist/*
200
273
  env:
@@ -202,6 +275,44 @@ jobs:
202
275
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
203
276
  TAG: ${{ needs.build.outputs.tag }}
204
277
 
278
+ attach-macos:
279
+ needs: [macos-app]
280
+ if: >-
281
+ always() &&
282
+ github.event_name == 'workflow_dispatch' &&
283
+ inputs.attach_macos == true &&
284
+ needs.macos-app.result == 'success'
285
+ runs-on: ubuntu-latest
286
+ timeout-minutes: 10
287
+ permissions:
288
+ contents: write
289
+ steps:
290
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
291
+ with:
292
+ persist-credentials: false
293
+ - name: Download macOS artifacts
294
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
295
+ with:
296
+ pattern: macos-app-*-${{ github.sha }}
297
+ path: dist/
298
+ merge-multiple: true
299
+ - name: Attach DMGs to the existing release
300
+ shell: bash
301
+ run: |
302
+ version="$(python - <<'PY'
303
+ import tomllib
304
+
305
+ with open("pyproject.toml", "rb") as pyproject_file:
306
+ print(tomllib.load(pyproject_file)["project"]["version"])
307
+ PY
308
+ )"
309
+ tag="v${version}"
310
+ gh release view "$tag" >/dev/null
311
+ gh release upload "$tag" dist/* --clobber
312
+ env:
313
+ GH_REPO: ${{ github.repository }}
314
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
315
+
205
316
  publish:
206
317
  needs: [build]
207
318
  if: needs.build.outputs.publish == 'true'
@@ -215,9 +326,9 @@ jobs:
215
326
  id-token: write
216
327
  steps:
217
328
  - name: Setup uv
218
- uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
329
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
219
330
  - name: Download package artifacts
220
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
331
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
221
332
  with:
222
333
  name: python-package-${{ github.sha }}
223
334
  path: dist/
@@ -54,4 +54,6 @@ logs/
54
54
  *$py.class
55
55
  .claude/settings.local.json
56
56
  .eggs/
57
+ .build/
58
+ .swiftpm/
57
59
  _build_info.py
@@ -1,10 +1,42 @@
1
+ Metadata-Version: 2.5
2
+ Name: agentbridge-cli
3
+ Version: 0.1.13
4
+ Summary: Bridge OpenAI tools to Claude Code SDK, Codex CLI, and OpenRouter
5
+ Project-URL: Homepage, https://github.com/tsilva/agentbridge
6
+ Project-URL: Repository, https://github.com/tsilva/agentbridge
7
+ Project-URL: Issues, https://github.com/tsilva/agentbridge/issues
8
+ Author: tsilva
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: anthropic,api,bridge,claude,claude-code,codex,fastapi,llm,openai,streaming
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Framework :: FastAPI
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: claude-agent-sdk>=0.2.132
21
+ Requires-Dist: fastapi>=0.141.1
22
+ Requires-Dist: jinja2>=3.1.0
23
+ Requires-Dist: openrouter==1.1.31
24
+ Requires-Dist: pillow>=12.3.0
25
+ Requires-Dist: uvicorn[standard]>=0.32.0
26
+ Provides-Extra: test
27
+ Requires-Dist: pip-audit>=2.9.0; extra == 'test'
28
+ Requires-Dist: pytest-asyncio>=1.4.0; extra == 'test'
29
+ Requires-Dist: pytest>=9.1.1; extra == 'test'
30
+ Requires-Dist: ruff>=0.15.0; extra == 'test'
31
+ Description-Content-Type: text/markdown
32
+
1
33
  <div align="center">
2
- <img src="./logo.png" alt="agentbridge" width="512" />
34
+ <img src="./logo.png" alt="AgentBridge" width="512" />
3
35
 
4
- **🌉 Bridge OpenAI tools to Claude Code SDK, Codex CLI, or OpenRouter — use your subscriptions anywhere 🔌**
36
+ **OpenAI-compatible routing for Claude Code, Codex, and OpenRouter — use your subscriptions anywhere.**
5
37
  </div>
6
38
 
7
- agentbridge is a local API bridge for developers who want to connect OpenAI-compatible apps to Claude Code, Codex, or OpenRouter. Run one server, choose a backend with a namespaced model ID, and point existing Chat Completions clients at `http://localhost:8082/api/v1`.
39
+ AgentBridge is a local API bridge for developers who want to connect OpenAI-compatible apps to Claude Code, Codex, or OpenRouter. Run one server, choose a backend with a namespaced model ID, and point existing Chat Completions clients at `http://localhost:8082/api/v1`.
8
40
 
9
41
  It supports streaming and non-streaming responses, image and PDF inputs where the backend accepts them, native Codex image editing, strict JSON Schema output, OpenAI-style tool calls, a live dashboard, and local JSON session logs.
10
42
 
@@ -12,6 +44,36 @@ It supports streaming and non-streaming responses, image and PDF inputs where th
12
44
 
13
45
  ## Install
14
46
 
47
+ ### macOS menu-bar app
48
+
49
+ Download the DMG for your Mac architecture from the GitHub Release, drag
50
+ `AgentBridge.app` to Applications, and open it. The app is ad-hoc signed rather
51
+ than Apple-notarized, so on first launch macOS may require you to Control-click
52
+ the app, choose **Open**, and confirm.
53
+
54
+ You can also build the app locally on macOS 13 or later. This requires
55
+ [uv](https://docs.astral.sh/uv/) and the Xcode Command Line Tools, but not an
56
+ Apple Developer account:
57
+
58
+ ```bash
59
+ git clone https://github.com/tsilva/agentbridge.git
60
+ cd agentbridge
61
+ scripts/build_macos_app.sh
62
+ open "build/macos/$(uname -m)/AgentBridge-"*.dmg
63
+ ```
64
+
65
+ The menu-bar window shows live server health and activity, starts and stops the
66
+ local server, opens the dashboard, and provides settings for the port, worker
67
+ count, and launch at login. See [`macos/README.md`](macos/README.md) for
68
+ development instructions.
69
+
70
+ The app contains its own Python 3.12 runtime and AgentBridge dependencies. It
71
+ does not bundle the Claude Code or Codex executables: installed provider tools
72
+ and their existing authentication state remain in the user account. Mutable
73
+ configuration and logs continue to live under `~/.config/agentbridge/`.
74
+
75
+ ### Command line
76
+
15
77
  ```bash
16
78
  uv tool install agentbridge-cli
17
79
  agentbridge
@@ -97,14 +159,17 @@ agentbridge --workers 3 # set Claude pool and Code
97
159
  agentbridge --version # print package and git version
98
160
  uv run --frozen --extra test pytest -q # run tests
99
161
  uv run --frozen --extra test ruff check agentbridge tests # lint Python
162
+ swift test --package-path macos # test the macOS app
163
+ scripts/build_macos_app.sh # build a local signed app and DMG
100
164
  uv lock --check # verify the lockfile
101
165
  uv build # build wheel and source distribution
102
166
  ```
103
167
 
104
168
  ## Notes
105
169
 
106
- - Python 3.12+ and at least one authenticated backend are required.
170
+ - The CLI requires Python 3.12+; the macOS app bundles Python. At least one authenticated backend is required for provider requests.
107
171
  - Public routes include `POST /api/v1/chat/completions`, `POST /api/v1/images`, `GET /api/v1/models`, `GET /api/v1/capabilities`, `GET /health`, `/dashboard`, and `/dashboard/chat`.
172
+ - `GET /health` includes safe operator status used by the menu-bar app: version, start time, uptime, configured workers, active requests, and pool state when initialized.
108
173
  - `PORT`, `POOL_SIZE`, `CLAUDE_TIMEOUT`, `CODEX_TIMEOUT`, `CODEX_IMAGE_TIMEOUT`, and `OPENROUTER_TIMEOUT` control the server port, pool size, and provider timeouts. `--workers` overrides `POOL_SIZE`; Codex chat and native image generation default to 600-second timeouts, while Claude and OpenRouter default to 120 seconds.
109
174
  - `MAX_IMAGE_INPUT_BYTES`, `MAX_IMAGE_OUTPUT_BYTES`, and `MAX_IMAGE_PIXELS` bound native image requests. Defaults are 64 MiB input, 32 MiB output, and 40 million pixels.
110
175
  - `AGENTBRIDGE_CONFIG_DIR` moves the user configuration directory. `LOG_DIR` moves session logs, and `MAX_LOG_FILES` limits retained JSON logs.
@@ -116,7 +181,14 @@ uv build # build wheel and source d
116
181
 
117
182
  ## Publishing
118
183
 
119
- Releases use the `Release` GitHub Actions workflow and PyPI Trusted Publishing for the `agentbridge-cli` project. The publisher is scoped to owner `tsilva`, repository `agentbridge`, workflow `release.yml`, and environment `pypi`; no PyPI API token is required. Releases through `0.1.10` remain available under the previous `agentbridge-py` distribution name.
184
+ Releases use the `Release` GitHub Actions workflow and PyPI Trusted Publishing
185
+ for the `agentbridge-cli` project. The publisher is scoped to owner `tsilva`,
186
+ repository `agentbridge`, workflow `release.yml`, and environment `pypi`; no
187
+ PyPI API token is required. GitHub Releases contain the Python distributions
188
+ plus ad-hoc-signed arm64 and x86_64 macOS DMGs and SHA-256 checksums. These DMGs
189
+ are not Apple-notarized and require no Apple Developer credentials. Releases
190
+ through `0.1.10` remain available under the previous `agentbridge-py`
191
+ distribution name.
120
192
 
121
193
  ## Architecture
122
194