Move to g.fc.run/ai/byre and tag v0.1.0

This commit is contained in:
Ian Gulliver
2026-10-18 15:32:07 -07:00
parent 923d0a2c00
commit c0c514e28e
73 changed files with 160 additions and 162 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ When asked to deploy, do exactly this, from the worktree root:
1. `go install ./cmd/byre && codesign --force --sign "Apple Development" --identifier run.fc.byre ~/bin/byre && swift build --package-path hands --configuration release && install hands/.build/release/byre-hands ~/bin/ && launchctl kickstart -k gui/$(id -u)/run.fc.byre`, always as that one command, never `go install` on its own, and always the last action of the turn. The signature gives byre a stable identity, so the macOS privacy grants it holds (Screen Recording, Accessibility, Automation) survive the rebuild; `go install`'s own ad-hoc signature changes with every build and loses them. `install` replaces `byre-hands` with a new file rather than writing over the one running agents have open.
2. When you resume, confirm it came up: read the tail of `~/Library/Logs/byre.log`, and `GET /api/admin/status` through the `tailscale serve` URL (`tailscale serve status` shows it). Report what you deployed and what you checked.
3. Once the service is confirmed healthy, rebuild and relaunch the macOS app: run `mac/bundle.sh`, then update every Mac whose app is running: on iso, `pkill -x Byre` and `open mac/.build/byre.app`, only when an app was running there (never start one that wasn't); on each client Mac, replace and relaunch the installed app through the client tools without asking first. The app reads its server address from its iCloud-synced SwiftData store, shared by every build, so the new build reconnects to prod with no setup. Report each Mac's app commit.
3. Once the service is confirmed healthy, rebuild and relaunch the macOS app: run `mac/bundle.sh`, then update every Mac whose app is running: on iso, `pkill -x Byre` and `open mac/.build/Byre.app`, only when an app was running there (never start one that wasn't); on each client Mac, replace and relaunch the installed app through the client tools without asking first. The app reads its server address from its iCloud-synced SwiftData store, shared by every build, so the new build reconnects to prod with no setup. Report each Mac's app commit.
What to expect:
+2 -2
View File
@@ -24,11 +24,11 @@ macOS, [Tailscale](https://tailscale.com) on every Mac, and on the Mac that runs
## Installing
1. Download the latest `byre-<version>.dmg` from [the releases page](https://g.fc.run/misc/byre/releases) and drag `byre.app` to Applications, on every Mac you'll use byre from.
1. Download the latest `byre-<version>.dmg` from [the releases page](https://g.fc.run/ai/byre/releases) and drag `Byre.app` to Applications, on every Mac you'll use byre from.
2. On the Mac that runs the server, from a terminal whose `PATH` finds `claude`, `codex`, `git` and `npx`:
```
/Applications/byre.app/Contents/Helpers/byre install
/Applications/Byre.app/Contents/Helpers/byre install
```
It installs the server as a launchd service and serves it through `tailscale serve`, printing the URL.
-2
View File
@@ -26,7 +26,5 @@
- Phone app
A native client for the phone over the same API, sharing the macOS client's SwiftUI code where it can. Every surveyed tool has one (Claude, Codex, Cursor and Conductor apps, GitHub Mobile, Superset for iPhone); it needs its own layout, since two half-width panes don't fit a phone.
- Move to g.fc.run/ai/byre
Before tagging v0.1.0, since the update feed URL is baked into every installed app. The owner creates the `ai` org on g.fc.run and transfers the repo (Settings → Danger Zone → Transfer ownership). Then rename all the way down: `go.mod`'s module and every import, `SUFeedURL` in `mac/Info.plist`, `repo=` in `mac/release.sh`, README and docs links, and the service checkout's `origin` (`git@g.fc.run:ai/byre.git`).
- Server setup in the app
Setting up the server's Mac from the app instead of a terminal: on the connection screen, a choice to run the server on this Mac, which does what `Contents/Helpers/byre install` does (the launch agent, `tailscale serve`), checks that `claude`, `codex`, `git` and Tailscale are there, and connects to the URL it set up.
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"path/filepath"
"strings"
"g.fc.run/misc/byre/internal/tailscale"
"g.fc.run/ai/byre/internal/tailscale"
)
const serviceLabel = "run.fc.byre"
+1 -1
View File
@@ -12,7 +12,7 @@ import (
"os/signal"
"strings"
"g.fc.run/misc/byre/internal/claude"
"g.fc.run/ai/byre/internal/claude"
)
func runCmd(args []string) {
+2 -2
View File
@@ -13,8 +13,8 @@ import (
"syscall"
"time"
"g.fc.run/misc/byre/internal/server"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/server"
"g.fc.run/ai/byre/internal/store"
)
const defaultListen = "127.0.0.1:8270"
+1 -1
View File
@@ -16,7 +16,7 @@ The app connects to byre's `tailscale serve` HTTPS URL, so its requests get the
- `UserNotifications` for notifications.
- Third-party code: Apple's `swift-openapi-generator` (with `swift-openapi-runtime` and `swift-openapi-urlsession`) for the API types and client, SwiftTerm for the terminal, and Sparkle for updates (its framework is a binary target, loaded from `Contents/Frameworks` through the `@executable_path/../Frameworks` rpath set in `mac/Package.swift`).
The project is a Swift package under `mac/`, built with `swift build`, not an Xcode project. It builds with Xcode's toolchain: `xcode-select --print-path` must print `/Applications/Xcode.app/Contents/Developer`. With the Command Line Tools selected while Xcode is installed, Swift Build finds two toolchains for the Command Line Tools path and picks one at random on each run; the pick is part of the build request, so every change of pick rebuilds every target. `mac/bundle.sh` builds the release configuration in one directory shared by every worktree, `~/Library/Caches/byre/build`: SwiftPM keys a build on the package's absolute path, so a build in a fresh worktree, or one sharing a `--scratch-path`, recompiles every dependency. Under a `lockf` lock on `~/Library/Caches/byre/build.lock`, so builds from different worktrees take turns, it copies the worktree's `mac/`, `api/` and `hands/` there with `rsync --checksum`, which rewrites only files whose contents differ and leaves the rest's modification times alone, builds both packages, and copies the executables and Sparkle's framework out to `mac/.build/Byre`, `mac/.build/byre-hands` and `mac/.build/Sparkle.framework`. The server is built outside the lock with `go build -o mac/.build/server/byre`, since Go's own cache is shared and safe to use concurrently. It passes `--no-color-diagnostics` because `COLOR_DIAGNOSTICS` otherwise follows whether output is a terminal and is part of the build request, so agents whose shells differ would each rebuild every target in turn; `build-request.json` under `.build/out/Intermediates.noindex/XCBuildData/` shows what a build was keyed on. It then assembles `mac/.build/byre.app` (`Byre` in `Contents/MacOS`, the server and `byre-hands` in `Contents/Helpers`, Sparkle in `Contents/Frameworks`, `mac/Info.plist` with the fixed bundle identifier `run.fc.byre.mac` and a `ByreCommit` key added holding the worktree's `git rev-parse HEAD`, which `API` sends as the `Byre-Commit` header on every request beside `Byre-Host`, the Mac's name, `CFBundleShortVersionString` from `git describe --tags --always` and `CFBundleVersion` from `git rev-list --count HEAD`, the `mac/fonts/` files and an `.icns` rendered from `mac/icon.svg`, cached as `mac/.build/byre.icns` until the SVG changes) and signs it; notification permission needs the bundle identifier. `docs/operations.md`, "macOS app", lists the signing order.
The project is a Swift package under `mac/`, built with `swift build`, not an Xcode project. It builds with Xcode's toolchain: `xcode-select --print-path` must print `/Applications/Xcode.app/Contents/Developer`. With the Command Line Tools selected while Xcode is installed, Swift Build finds two toolchains for the Command Line Tools path and picks one at random on each run; the pick is part of the build request, so every change of pick rebuilds every target. `mac/bundle.sh` builds the release configuration in one directory shared by every worktree, `~/Library/Caches/byre/build`: SwiftPM keys a build on the package's absolute path, so a build in a fresh worktree, or one sharing a `--scratch-path`, recompiles every dependency. Under a `lockf` lock on `~/Library/Caches/byre/build.lock`, so builds from different worktrees take turns, it copies the worktree's `mac/`, `api/` and `hands/` there with `rsync --checksum`, which rewrites only files whose contents differ and leaves the rest's modification times alone, builds both packages, and copies the executables and Sparkle's framework out to `mac/.build/Byre`, `mac/.build/byre-hands` and `mac/.build/Sparkle.framework`. The server is built outside the lock with `go build -o mac/.build/server/byre`, since Go's own cache is shared and safe to use concurrently. It passes `--no-color-diagnostics` because `COLOR_DIAGNOSTICS` otherwise follows whether output is a terminal and is part of the build request, so agents whose shells differ would each rebuild every target in turn; `build-request.json` under `.build/out/Intermediates.noindex/XCBuildData/` shows what a build was keyed on. It then assembles `mac/.build/Byre.app` (`Byre` in `Contents/MacOS`, the server and `byre-hands` in `Contents/Helpers`, Sparkle in `Contents/Frameworks`, `mac/Info.plist` with the fixed bundle identifier `run.fc.byre.mac` and a `ByreCommit` key added holding the worktree's `git rev-parse HEAD`, which `API` sends as the `Byre-Commit` header on every request beside `Byre-Host`, the Mac's name, `CFBundleShortVersionString` from `git describe --tags --always` and `CFBundleVersion` from `git rev-list --count HEAD`, the `mac/fonts/` files and an `.icns` rendered from `mac/icon.svg`, cached as `mac/.build/byre.icns` until the SVG changes) and signs it; notification permission needs the bundle identifier. `docs/operations.md`, "macOS app", lists the signing order.
## Signing
+7 -7
View File
@@ -112,7 +112,7 @@ A team task has several agents working at once in its one worktree, branch and p
The listen address is `byre serve --listen`, whose default is `defaultListen` in `cmd/byre/serve.go` (`go run ./cmd/byre serve --help` prints it); keep it on loopback, since identity relies on requests arriving from `tailscale serve`.
`byre install` (`cmd/byre/install.go`) sets the service up for the binary it is run as, with `byre-hands` beside it: it writes `~/Library/LaunchAgents/run.fc.byre.plist` running `<that binary> serve`, with a `PATH` of that binary's directory (so `byre-hands` beside it is found) followed by the `PATH` of the shell it was run from (which must find `claude`, `codex`, `git` and `npx`, the last for the Playwright MCP server, which also needs Google Chrome) and logs to `~/Library/Logs/byre.log`; boots out the service if it is loaded, so the new plist is read; bootstraps it; and runs `tailscale serve --bg --https=443 http://<default listen address>` through the Tailscale app's CLI (`tailscale.ServeRoot`, see "Previews"), printing `byre is at https://<machine>.<tailnet>.ts.net`. Running it again after an update restarts the service on the new binary. From a release, that is `/Applications/byre.app/Contents/Helpers/byre install`. From a checkout:
`byre install` (`cmd/byre/install.go`) sets the service up for the binary it is run as, with `byre-hands` beside it: it writes `~/Library/LaunchAgents/run.fc.byre.plist` running `<that binary> serve`, with a `PATH` of that binary's directory (so `byre-hands` beside it is found) followed by the `PATH` of the shell it was run from (which must find `claude`, `codex`, `git` and `npx`, the last for the Playwright MCP server, which also needs Google Chrome) and logs to `~/Library/Logs/byre.log`; boots out the service if it is loaded, so the new plist is read; bootstraps it; and runs `tailscale serve --bg --https=443 http://<default listen address>` through the Tailscale app's CLI (`tailscale.ServeRoot`, see "Previews"), printing `byre is at https://<machine>.<tailnet>.ts.net`. Running it again after an update restarts the service on the new binary. From a release, that is `/Applications/Byre.app/Contents/Helpers/byre install`. From a checkout:
```
go install ./cmd/byre
@@ -128,9 +128,9 @@ After rebuilding from a checkout: step 1 of "Deploying" in `AGENTS.md`, which re
## Releases
A release is one notarized disk image, `byre-<version>.dmg`, holding `byre.app`: the macOS app, with the server (`Contents/Helpers/byre`) and `byre-hands` (`Contents/Helpers/byre-hands`) inside it. Every Mac installs the same app; the server's Mac also runs `byre install` from it (see "Running as a service"). Releases are on the repo's releases page on g.fc.run, `https://g.fc.run/misc/byre/releases`.
A release is one notarized disk image, `byre-<version>.dmg`, holding `Byre.app`: the macOS app, with the server (`Contents/Helpers/byre`) and `byre-hands` (`Contents/Helpers/byre-hands`) inside it. Every Mac installs the same app; the server's Mac also runs `byre install` from it (see "Running as a service"). Releases are on the repo's releases page on g.fc.run, `https://g.fc.run/ai/byre/releases`.
`mac/release.sh` makes one, run on byre's host from a checkout whose `HEAD` carries a `v<version>` tag already pushed to `origin`, with a clean tree; it fetches the tag from `origin` and stops unless it names `HEAD`. It builds with `mac/bundle.sh` (signed with Developer ID, see `docs/macos.md`), zips the app and notarizes it with `xcrun notarytool submit --keychain-profile byre-notary --wait`, staples the ticket, builds the disk image with `hdiutil` (the app and an `/Applications` link), signs, notarizes and staples that too, and writes its SHA-256 beside it. It then signs the image for Sparkle with `sign_update --account byre` and writes `appcast.xml`, a feed with that one release. Last, it creates the release as a draft through the Gitea API (`POST /api/v1/repos/misc/byre/releases`, notes the commit subjects since the previous tag), uploads the image, its `.sha256` and `appcast.xml` as assets, and only then publishes it (`PATCH` with `draft: false`), so the `latest` release always has its appcast. A run that fails part way leaves the draft on the releases page; delete it there before running again. Everything lands in `mac/.build/release/<version>/`, and the script prints the release page.
`mac/release.sh` makes one, run on byre's host from a checkout whose `HEAD` carries a `v<version>` tag already pushed to `origin`, with a clean tree; it fetches the tag from `origin` and stops unless it names `HEAD`. It builds with `mac/bundle.sh` (signed with Developer ID, see `docs/macos.md`), zips the app and notarizes it with `xcrun notarytool submit --keychain-profile byre-notary --wait`, staples the ticket, builds the disk image with `hdiutil` (the app and an `/Applications` link), signs, notarizes and staples that too, and writes its SHA-256 beside it. It then signs the image for Sparkle with `sign_update --account byre` and writes `appcast.xml`, a feed with that one release. Last, it creates the release as a draft through the Gitea API (`POST /api/v1/repos/ai/byre/releases`, notes the commit subjects since the previous tag), uploads the image, its `.sha256` and `appcast.xml` as assets, and only then publishes it (`PATCH` with `draft: false`), so the `latest` release always has its appcast. A run that fails part way leaves the draft on the releases page; delete it there before running again. Everything lands in `mac/.build/release/<version>/`, and the script prints the release page.
It needs, on that Mac:
@@ -139,15 +139,15 @@ It needs, on that Mac:
- the Sparkle signing key in the login keychain under account `byre` (`~/Library/Caches/byre/sparkle-<version>/bin/generate_keys --account byre -p` prints its public key, which must match `SUPublicEDKey` in `mac/Info.plist`; `-x <file>` exports it for safekeeping). The script downloads Sparkle's tools to that cache directory when they are missing;
- a g.fc.run token that can write the repo's releases, as the generic password with service `byre-release` (`security add-generic-password -s byre-release -a g.fc.run -w <token>`).
The app checks `https://g.fc.run/misc/byre/releases/download/latest/appcast.xml` for updates (see "Updates" in `docs/macos.md`); Gitea serves the `latest` name from the newest release, so each release's appcast replaces the last.
The app checks `https://g.fc.run/ai/byre/releases/download/latest/appcast.xml` for updates (see "Updates" in `docs/macos.md`); Gitea serves the `latest` name from the newest release, so each release's appcast replaces the last.
Clients reach `tailscale serve` over HTTP/2; it proxies to byre over HTTP/1.1 and passes SSE through unbuffered.
## macOS app
**Building.** `mac/bundle.sh`, from any directory, builds the release configuration with `swift build` in `~/Library/Caches/byre/build`, one build directory every worktree shares and takes turns in (`docs/macos.md`, "Stack", says why), and assembles `mac/.build/byre.app`: the `Byre` executable in `Contents/MacOS`; the server, built with `go build ./cmd/byre`, and `byre-hands`, built from `hands/`, in `Contents/Helpers` (not beside `Byre`: the default APFS volume ignores case, so `byre` and `Byre` would be one file); Sparkle's framework in `Contents/Frameworks`; `mac/Info.plist` with a `ByreCommit` key added holding the worktree's `git rev-parse HEAD`, `CFBundleShortVersionString` its `git describe --tags --always` without the leading `v` (`0.1.0` on a release tag, `0.1.0-12-gabc1234` after it) and `CFBundleVersion` its `git rev-list --count HEAD` (the About panel shows them as "Version <version> (<count>)", and Sparkle compares the count); the `mac/fonts/` woff2 files, an icon rendered from `mac/icon.svg` with `rsvg-convert` and `iconutil` (cached as `mac/.build/byre.icns` until the SVG changes) and `mac/byre.provisionprofile`. It signs each piece with the Developer ID Application certificate, a secure timestamp and the hardened runtime, innermost first: `byre-hands` as `run.fc.byre.hands` and the server as `run.fc.byre`, both with `mac/automation.entitlements` (Apple Events, which the hardened runtime otherwise refuses), Sparkle's `Autoupdate`, `Updater.app` and framework (its XPC services, only needed by sandboxed apps, are removed), then the bundle with `mac/byre.entitlements`. It prints the bundle's path. It needs Xcode selected (`xcode-select --print-path` prints `/Applications/Xcode.app/Contents/Developer`), Go, `rsvg-convert` (Homebrew's `librsvg`), the team's Developer ID Application certificate and network access for the timestamp, and it stops first unless `mac/byre.provisionprofile` has `ProvisionsAllDevices` (a Developer ID profile; a development profile can't authorize the Developer ID signature); `docs/macos.md`, "Signing", covers the certificate and profile. Debug builds are refused by an `#error` in `ByreApp.swift`. The first build on a Mac fetches the Swift packages pinned in `mac/Package.resolved` and compiles them and the generated API client; later builds, from any worktree, recompile only the targets whose sources differ from the last build's, usually just `Byre`. The API client is generated from `api/openapi.yaml` at build time. The palette is `mac/Sources/Byre/Palette.swift`, one light and one dark value per colour.
**Building.** `mac/bundle.sh`, from any directory, builds the release configuration with `swift build` in `~/Library/Caches/byre/build`, one build directory every worktree shares and takes turns in (`docs/macos.md`, "Stack", says why), and assembles `mac/.build/Byre.app`: the `Byre` executable in `Contents/MacOS`; the server, built with `go build ./cmd/byre`, and `byre-hands`, built from `hands/`, in `Contents/Helpers` (not beside `Byre`: the default APFS volume ignores case, so `byre` and `Byre` would be one file); Sparkle's framework in `Contents/Frameworks`; `mac/Info.plist` with a `ByreCommit` key added holding the worktree's `git rev-parse HEAD`, `CFBundleShortVersionString` its `git describe --tags --always` without the leading `v` (`0.1.0` on a release tag, `0.1.0-12-gabc1234` after it) and `CFBundleVersion` its `git rev-list --count HEAD` (the About panel shows them as "Version <version> (<count>)", and Sparkle compares the count); the `mac/fonts/` woff2 files, an icon rendered from `mac/icon.svg` with `rsvg-convert` and `iconutil` (cached as `mac/.build/byre.icns` until the SVG changes) and `mac/byre.provisionprofile`. It signs each piece with the Developer ID Application certificate, a secure timestamp and the hardened runtime, innermost first: `byre-hands` as `run.fc.byre.hands` and the server as `run.fc.byre`, both with `mac/automation.entitlements` (Apple Events, which the hardened runtime otherwise refuses), Sparkle's `Autoupdate`, `Updater.app` and framework (its XPC services, only needed by sandboxed apps, are removed), then the bundle with `mac/byre.entitlements`. It prints the bundle's path. It needs Xcode selected (`xcode-select --print-path` prints `/Applications/Xcode.app/Contents/Developer`), Go, `rsvg-convert` (Homebrew's `librsvg`), the team's Developer ID Application certificate and network access for the timestamp, and it stops first unless `mac/byre.provisionprofile` has `ProvisionsAllDevices` (a Developer ID profile; a development profile can't authorize the Developer ID signature); `docs/macos.md`, "Signing", covers the certificate and profile. Debug builds are refused by an `#error` in `ByreApp.swift`. The first build on a Mac fetches the Swift packages pinned in `mac/Package.resolved` and compiles them and the generated API client; later builds, from any worktree, recompile only the targets whose sources differ from the last build's, usually just `Byre`. The API client is generated from `api/openapi.yaml` at build time. The palette is `mac/Sources/Byre/Palette.swift`, one light and one dark value per colour.
**Installing.** A release is installed from its disk image into `/Applications` (see "Releases") and updates itself (`docs/macos.md`, "Updates"). A build from a checkout runs from where it was built: `open mac/.build/byre.app` in the worktree that built it. A new build replaces the bundle, so quit the running app first (`pkill -x Byre` quits every running copy, whichever worktree built it) and open the new one; step 4 of "Deploying" in `AGENTS.md` does this after a deploy. Every build shares the bundle identifier `run.fc.byre.mac` and the same store, so any build reconnects to the server the last one used. Closing the window leaves the app running for notifications; ⌘Q quits it.
**Installing.** A release is installed from its disk image into `/Applications` (see "Releases") and updates itself (`docs/macos.md`, "Updates"). A build from a checkout runs from where it was built: `open mac/.build/Byre.app` in the worktree that built it. A new build replaces the bundle, so quit the running app first (`pkill -x Byre` quits every running copy, whichever worktree built it) and open the new one; step 4 of "Deploying" in `AGENTS.md` does this after a deploy. Every build shares the bundle identifier `run.fc.byre.mac` and the same store, so any build reconnects to the server the last one used. Closing the window leaves the app running for notifications; ⌘Q quits it.
**Storage.** The app keeps three kinds of record in SwiftData (`mac/Sources/Byre/Persistence.swift`): the server origin, when each task was last selected, and composer and answer drafts as JSON, one record per server and login (`docs/macos.md`, "Persistence" and "Drafts"). The store is `~/Library/Application Support/run.fc.byre.mac/byre.store`, with its `-shm` and `-wal` files and CloudKit's working files beside it in that directory; the app isn't sandboxed, so it names its own file rather than SwiftData's default `default.store`, which every unsandboxed app shares. The store syncs through the iCloud private database of container `iCloud.run.fc.byre.mac`, in CloudKit's Production environment (`com.apple.developer.icloud-container-environment` in `mac/byre.entitlements`), whose schema is deployed from Development in the CloudKit console before a release that changes the SwiftData models; the CloudKit console (icloud.developer.apple.com, the container, Production, Private Database, zone `com.apple.coredata.cloudkit.zone`) shows the records. Deleting the local files while the app isn't running makes the next launch download the records again from iCloud; deleting the records in the console as well starts from the connection screen. Pasted images stay in memory and are dropped on Change Server… and quit. The app logs through `os.Logger`: `log show --last 10m --predicate 'subsystem == "run.fc.byre.mac"'` prints it.
@@ -351,7 +351,7 @@ Implementer sessions get eight MCP tools for it (`internal/agents/clients.go`).
`client_read`, `client_write` and `client_edit` wait at most 2 minutes for each reply, and their paths, like `client_download`'s `path`, are absolute or start with `~/`, which the app expands.
- `client_hands`: `op: hands`, with `tool` and `arguments` as the `hands` tools take them (see "Screen and app control"). The app runs one `byre-hands`, bundled at `Contents/Helpers/byre-hands`, started on first use and again after it exits, writes each call to its stdin as a `tools/call` line and replies with the line's `result`, which byre returns to the agent as the tool's result, images included (`mcp.Tool.Rich`; Codex gets them as `inputImage` data URLs). The macOS privacy grants it needs (Screen Recording, Accessibility, Automation of Orion) belong to byre's app on that Mac, since the app is the responsible process; `NSAppleEventsUsageDescription` in `mac/Info.plist` is what lets macOS ask for the Automation grant. Each `byre-hands` process has its own pending calls, so one that exits fails only the calls sent to it.
A byre restart drops every connection; each app reconnects 2s later, and calls in flight at the restart fail as disconnected. Updating a client's app goes through the tools themselves: `client_upload` the new `byre.app`, then `client_bash` a command that quits the old app and opens the new one, which outlives the app and reconnects. An app that doesn't know the `upload` op can't be updated this way, so its update is by hand.
A byre restart drops every connection; each app reconnects 2s later, and calls in flight at the restart fail as disconnected. Updating a client's app goes through the tools themselves: `client_upload` the new `Byre.app`, then `client_bash` a command that quits the old app and opens the new one, which outlives the app and reconnects. An app that doesn't know the `upload` op can't be updated this way, so its update is by hand.
`log show --info --last 10m --predicate 'subsystem == "run.fc.byre.mac"'` on a client shows `client request <id>: <op>` lines and `byre-hands` starts and exits, which are info level and kept only in memory, so they cover the last few minutes at most; connection drops (`client connection closed`, `client connection got no pong`) are notices, which macOS keeps on disk, so `log show --start` reaches much further back for them; byre's log shows `client connected` and `client disconnected`.
+1 -1
View File
@@ -1,4 +1,4 @@
module g.fc.run/misc/byre
module g.fc.run/ai/byre
go 1.26.0
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"fmt"
"log/slog"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/store"
)
func (m *Manager) MergeAfterReview(ctx context.Context, task api.Task, user api.User, target api.MergeTaskJSONBodyTarget, title string) (api.Task, error) {
+4 -4
View File
@@ -15,9 +15,9 @@ import (
"time"
"unicode/utf8"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/clients"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/clients"
"g.fc.run/ai/byre/internal/mcp"
)
const (
@@ -69,7 +69,7 @@ func (m *Manager) clientTools(l *live) []mcp.Tool {
"properties": {
"client": {"type": "string", "description": "The client's name from list_clients, or its id when several are connected from that Mac."},
"path": {"type": "string", "description": "The file or directory, relative to your worktree."},
"dest": {"type": "string", "description": "Its new path on the client, absolute or starting with ~/, e.g. ~/Applications/byre.app."}
"dest": {"type": "string", "description": "Its new path on the client, absolute or starting with ~/, e.g. ~/Applications/Byre.app."}
},
"required": ["client", "path", "dest"]
}`),
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/codex"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/codex"
)
var codexToolItems = map[string]bool{
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"log/slog"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/store"
)
const handoffPrompt = `Write a handoff for a fresh agent that will continue this task with none of your context. ` +
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"context"
"log/slog"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
)
type mergeTurn struct {
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"fmt"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/store"
)
func (m *Manager) Fork(ctx context.Context, src api.Task, project api.Project, n int, creator api.User) (api.Task, error) {
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"strings"
"unicode/utf8"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/claude"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/todo"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/claude"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/todo"
)
const guidance = `You are running inside byre. The human reads your work in byre's app, not a terminal.
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"os/exec"
"path/filepath"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/ai/byre/internal/mcp"
)
const screenshotGuidance = "\n- When a turn changes something you can see, you can show it in your final message: save screenshots with the Playwright tools (pages you serve on this task's ports) or hands' capture with save (apps on this Mac), and embed each as a Markdown image, ![what it shows](<path>), with the path the tool returned. They go to the task's media folder, outside the worktree, so they are never committed, and are deleted when the task closes. Leave out a screenshot that adds nothing to the text."
+1 -1
View File
@@ -18,7 +18,7 @@ import (
"syscall"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const (
+3 -3
View File
@@ -10,9 +10,9 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
)
var attachmentKinds = []api.AttachmentKind{
+3 -3
View File
@@ -9,9 +9,9 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/workflow"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/workflow"
)
const leadGuidance = `You are the human's lead agent in byre, shown in the left pane of byre's app. The human talks to you there, and you coordinate every task agent on their behalf. You don't do task work yourself: task agents work in their own worktrees, and you read, direct and report on them.
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"fmt"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
)
func (m *Manager) noteTools(tool func(name, description, schema string, run func(ctx context.Context, user api.User, raw json.RawMessage) (string, error)) mcp.Tool) []mcp.Tool {
+5 -5
View File
@@ -10,11 +10,11 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/todo"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/todo"
)
func (m *Manager) leadTools(l *live) []mcp.Tool {
+8 -8
View File
@@ -14,14 +14,14 @@ import (
"sync"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/claude"
"g.fc.run/misc/byre/internal/clients"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/terminal"
"g.fc.run/misc/byre/internal/workflow"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/claude"
"g.fc.run/ai/byre/internal/clients"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/terminal"
"g.fc.run/ai/byre/internal/workflow"
)
var (
+4 -4
View File
@@ -12,10 +12,10 @@ import (
"sync"
"unicode/utf8"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
)
const maxMergeTitle = 72
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/store"
)
func (m *Manager) mergeNote(ctx context.Context, task api.Task, login string) (string, error) {
+4 -4
View File
@@ -12,10 +12,10 @@ import (
"time"
"unicode/utf8"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/tailscale"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/tailscale"
)
const maxPreviewName = 40
+5 -5
View File
@@ -7,11 +7,11 @@ import (
"os"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/claude"
"g.fc.run/misc/byre/internal/codex"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/workflow"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/claude"
"g.fc.run/ai/byre/internal/codex"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/workflow"
)
type image struct {
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"strings"
"sync"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/store"
)
type sessionLock struct {
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/store"
)
func (m *Manager) Respond(ctx context.Context, user string, creates []api.InboxResponseCreate) ([]api.InboxItem, error) {
+4 -4
View File
@@ -12,10 +12,10 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
)
const maxReviewFiles = 200
+5 -5
View File
@@ -9,11 +9,11 @@ import (
"sync"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/claude"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/claude"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
)
type snapRequest struct {
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"log/slog"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
)
func (m *Manager) subtaskTools(l *live) []mcp.Tool {
+3 -3
View File
@@ -9,9 +9,9 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
)
const summaryRequest = "Call set_task_summary with a summary of the whole task, not just this turn, for whoever searches closed tasks later: what it set out to do, what was built or tried, the key decisions and why, and what was deliberately left out."
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"path/filepath"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/todo"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/todo"
)
func (m *Manager) CreateTask(ctx context.Context, project api.Project, title, createdBy, base, actor string) (api.Task, error) {
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"log/slog"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/workflow"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/workflow"
)
const boardActor = "board"
+3 -3
View File
@@ -8,9 +8,9 @@ import (
"sync/atomic"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/terminal"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/terminal"
)
const (
+5 -5
View File
@@ -8,11 +8,11 @@ import (
"log/slog"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/workflow"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/workflow"
)
func (m *Manager) SaveWorkflow(ctx context.Context, name string, file []byte, actor string) (api.WorkflowSummary, error) {
+1 -1
View File
@@ -18,7 +18,7 @@ import (
"sync/atomic"
"time"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/ai/byre/internal/mcp"
)
type HookFunc func(ctx context.Context, input json.RawMessage) (map[string]any, error)
+1 -1
View File
@@ -15,7 +15,7 @@ import (
"github.com/coder/websocket"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const (
+1 -1
View File
@@ -18,7 +18,7 @@ import (
"sync/atomic"
"time"
"g.fc.run/misc/byre/internal/mcp"
"g.fc.run/ai/byre/internal/mcp"
)
type Options struct {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"strconv"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
var statuses = map[byte]api.FileChangeStatus{
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"net/http"
"os"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/store"
)
func (s *Server) UploadBlob(w http.ResponseWriter, r *http.Request) {
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"net/http"
"regexp"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
)
var objectID = regexp.MustCompile(`^[0-9a-f]{40}([0-9a-f]{24})?$`)
+2 -2
View File
@@ -14,8 +14,8 @@ import (
"strings"
"unicode/utf8"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/git"
)
const (
+1 -1
View File
@@ -3,7 +3,7 @@ package server
import (
"sync"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
type hub struct {
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"path/filepath"
"strings"
"g.fc.run/misc/byre/internal/agents"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/agents"
"g.fc.run/ai/byre/internal/api"
)
var worktreeImageTypes = map[string]string{
+2 -2
View File
@@ -3,8 +3,8 @@ package server
import (
"net/http"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/store"
)
func (s *Server) ListInbox(w http.ResponseWriter, r *http.Request, params api.ListInboxParams) {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"net/http"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
func (s *Server) ListLeadSessions(w http.ResponseWriter, r *http.Request) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"net/http"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
func (s *Server) UpdateNotificationPrefs(w http.ResponseWriter, r *http.Request) {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"errors"
"net/http"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
func (s *Server) ListReviews(w http.ResponseWriter, r *http.Request, taskID string) {
+8 -8
View File
@@ -14,14 +14,14 @@ import (
"sync"
"time"
"g.fc.run/misc/byre/internal/agents"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/clients"
"g.fc.run/misc/byre/internal/git"
"g.fc.run/misc/byre/internal/store"
"g.fc.run/misc/byre/internal/terminal"
"g.fc.run/misc/byre/internal/todo"
"g.fc.run/misc/byre/internal/workflow"
"g.fc.run/ai/byre/internal/agents"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/clients"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/terminal"
"g.fc.run/ai/byre/internal/todo"
"g.fc.run/ai/byre/internal/workflow"
)
type Server struct {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"net/http"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const backfillPage = 500
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"github.com/coder/websocket"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/misc/byre/internal/terminal"
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/terminal"
)
const (
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"net/http"
"net/url"
"g.fc.run/misc/byre/internal/workflow"
"g.fc.run/ai/byre/internal/workflow"
)
const maxWorkflowFileBytes = 1 << 20
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"path/filepath"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const MaxBlobBytes = 5 << 20
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
type DiscardState string
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"strings"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
func (s *Store) CreateInboxItem(ctx context.Context, item api.InboxItem) error {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"errors"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
type LeadInputKind string
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"fmt"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
func (s *Store) LeadNotes(ctx context.Context, owner string) ([]api.LeadNote, error) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"database/sql"
"encoding/json"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
func (s *Store) UpdateNotificationPrefs(ctx context.Context, login string, prefs api.NotificationPrefs) (api.User, error) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"database/sql"
"errors"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const previewColumns = `task_id, name, port, created_at`
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"errors"
"time"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const reviewColumns = `id, task_id, snapshot_n, coalesce(agent_session_id, ''), vendor, model, state, result, error, created_at, finished_at, finding_states`
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"database/sql"
"errors"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const snapshotColumns = `id, task_id, agent_session_id, n, commit_sha, tree_sha, event_seq, trigger, created_at`
+1 -1
View File
@@ -14,7 +14,7 @@ import (
_ "modernc.org/sqlite"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
var ErrNotFound = errors.New("not found")
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
func (s *Store) SummaryReads(ctx context.Context, login string) (map[string]int64, error) {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"errors"
"fmt"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
type FrozenWorkflow struct {
+1 -1
View File
@@ -12,7 +12,7 @@ import (
"github.com/creack/pty"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const (
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"regexp"
"strings"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
const File = "TODO.md"
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"go.yaml.in/yaml/v3"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
var keyOrder = []string{"description", "stages", "name", "after", "base", "model", "prompt"}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"unicode"
"unicode/utf8"
"g.fc.run/misc/byre/internal/api"
"g.fc.run/ai/byre/internal/api"
)
var ErrInvalid = errors.New("invalid workflow")
+2 -2
View File
@@ -5,7 +5,7 @@
<key>CFBundleIdentifier</key>
<string>run.fc.byre.mac</string>
<key>CFBundleName</key>
<string>byre</string>
<string>Byre</string>
<key>CFBundleExecutable</key>
<string>Byre</string>
<key>CFBundlePackageType</key>
@@ -17,7 +17,7 @@
<key>NSHighResolutionCapable</key>
<true/>
<key>SUFeedURL</key>
<string>https://g.fc.run/misc/byre/releases/download/latest/appcast.xml</string>
<string>https://g.fc.run/ai/byre/releases/download/latest/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>350+qbxFCpm+LhbRlCxtBHST+FTz6o19jhGOSs8D0XU=</string>
<key>SUEnableAutomaticChecks</key>
+1 -1
View File
@@ -4,7 +4,7 @@ mac=$(cd "$(dirname "$0")" && pwd)
root=$(dirname "$mac")
shared=$HOME/Library/Caches/byre/build
build=$mac/.build
app=$build/byre.app
app=$build/Byre.app
svg=$mac/icon.svg
icns=$build/byre.icns
identity="Developer ID Application"
+3 -3
View File
@@ -2,7 +2,7 @@
set -eu
mac=$(cd "$(dirname "$0")" && pwd)
root=$(dirname "$mac")
repo=misc/byre
repo=ai/byre
api=https://g.fc.run/api/v1/repos/$repo
sparkle_version=2.10.0
sparkle=$HOME/Library/Caches/byre/sparkle-$sparkle_version
@@ -27,7 +27,7 @@ if [ ! -x "$sparkle/bin/sign_update" ]; then
fi
"$mac/bundle.sh"
app=$mac/.build/byre.app
app=$mac/.build/Byre.app
out=$mac/.build/release/$version
rm -rf "$out"
mkdir -p "$out"
@@ -40,7 +40,7 @@ rm "$out/byre.zip"
dmg=byre-$version.dmg
stage=$out/stage
mkdir "$stage"
ditto "$app" "$stage/byre.app"
ditto "$app" "$stage/Byre.app"
ln -s /Applications "$stage/Applications"
hdiutil create -volname byre -srcfolder "$stage" -format UDZO "$out/$dmg"
rm -rf "$stage"