Add usage commands, a vendor-neutral usage format and a knowledge base

This commit is contained in:
Ian Gulliver
2026-10-19 15:08:57 -07:00
parent 912225cbd1
commit 8a395d4d6e
17 changed files with 1010 additions and 403 deletions
+5 -19
View File
@@ -153,7 +153,6 @@ func (m *Manager) agyTurnEnded(ctx context.Context, l *live, p antigravityProces
m.mu.Lock()
final := l.lastText
m.mu.Unlock()
go m.readAgyRateLimit()
success := res.Status == "SUCCESS"
bounce := false
@@ -207,30 +206,17 @@ func (m *Manager) readAgyRateLimit() {
slog.Error("read antigravity rate limits", "err", err)
return
}
m.mu.Lock()
m.rateLimits[api.Antigravity] = agyRateLimit(groups)
m.mu.Unlock()
m.store.Broadcast(api.Event{Kind: "admin.health", Actor: "byre", Payload: map[string]any{}})
m.setVendorUsage(api.Antigravity, agyUsage(groups))
}
func agyRateLimit(groups []antigravity.UsageGroup) map[string]any {
info := map[string]any{"status": "allowed"}
windows := map[string]any{}
func agyUsage(groups []antigravity.UsageGroup) api.Usage {
u := api.Usage{UpdatedAt: time.Now(), Windows: []api.UsageWindow{}}
for _, g := range groups {
for _, b := range g.Buckets {
window := map[string]any{"utilization": 1 - b.RemainingFraction, "resetsAt": b.ResetTime.Unix()}
if mins := agyWindowMins[b.Window]; mins != 0 {
window["windowMins"] = mins
}
windows[b.ID] = window
if b.RemainingFraction <= 0 {
info["status"] = "rejected"
info["rateLimitType"] = b.ID
}
u.Windows = append(u.Windows, percentWindow(b.ID, 1-b.RemainingFraction, b.ResetTime.Unix(), int64(agyWindowMins[b.Window])*60))
}
}
info["unifiedWindows"] = windows
return info
return u
}
func (m *Manager) agyBeforeModel(l *live) antigravity.HookFunc {
+11 -23
View File
@@ -225,36 +225,24 @@ func (m *Manager) readCodexRateLimit() {
}
func (m *Manager) setCodexRateLimit(r codex.RateLimitSnapshot) {
m.mu.Lock()
m.rateLimits[api.Codex] = codexRateLimit(r)
m.mu.Unlock()
m.store.Broadcast(api.Event{Kind: "admin.health", Actor: "byre", Payload: map[string]any{}})
m.setVendorUsage(api.Codex, codexUsage(r))
}
func codexRateLimit(r codex.RateLimitSnapshot) map[string]any {
status := "allowed"
func codexUsage(r codex.RateLimitSnapshot) api.Usage {
u := api.Usage{UpdatedAt: time.Now(), Windows: []api.UsageWindow{}}
if r.RateLimitReachedType != "" {
status = "rejected"
u.Rejected = new(string(r.RateLimitReachedType))
}
windows := map[string]any{}
for name, w := range map[string]*codex.RateLimitWindow{"primary": r.Primary, "secondary": r.Secondary} {
if w == nil {
for _, w := range []struct {
name string
w *codex.RateLimitWindow
}{{"primary", r.Primary}, {"secondary", r.Secondary}} {
if w.w == nil {
continue
}
window := map[string]any{"utilization": float64(w.UsedPercent) / 100}
if w.ResetsAt != 0 {
window["resetsAt"] = w.ResetsAt
}
if w.WindowDurationMins != 0 {
window["windowMins"] = w.WindowDurationMins
}
windows[name] = window
u.Windows = append(u.Windows, percentWindow(w.name, float64(w.w.UsedPercent)/100, w.w.ResetsAt, w.w.WindowDurationMins*60))
}
info := map[string]any{"status": status, "unifiedWindows": windows, "planType": r.PlanType}
if r.RateLimitReachedType != "" {
info["rateLimitType"] = r.RateLimitReachedType
}
return info
return u
}
func (m *Manager) codexTurnCompleted(ctx context.Context, l *live, s *codex.Session, turn codex.Turn) error {
-1
View File
@@ -21,7 +21,6 @@ const guidance = `You are running inside byre. The human reads your work in byre
- In that final message and in ask_human context, put long supporting detail (logs, full lists, data) in collapsed sections the human expands on demand: a line <details><summary>Title</summary>, the Markdown content, then a line </details>.
- Don't commit. byre commits everything in the worktree at the end of each turn, using the turn's final message.
- Don't push, don't switch or touch other branches, and don't run git maintenance (gc, prune, worktree prune). byre handles merging and pushing.
- byre signs merge commits on the merging user's Mac. To turn it on for a project, run ` + "`byre signing <checkout>`" + ` on this machine.
- TODO.md at the repo root is the project's list of work for byre. Each item is a top-level ` + "`- `" + ` line holding only a short title, which byre uses as the task's title and the item's identity, with its description in lines indented two spaces under it. ` + "`#`" + ` headings group items into sections, and a checked ` + "`- [x]`" + ` item is skipped.`
const proseQuestionNudge = "Your final message asks the human something in prose. Ask it with byre's ask_human tool " +
+66
View File
@@ -0,0 +1,66 @@
package agents
import (
"context"
"embed"
"encoding/json"
"fmt"
"io/fs"
"strings"
"g.fc.run/ai/byre/internal/mcp"
)
//go:embed kb/*.md
var kbFiles embed.FS
var kb, kbIndex = loadKB()
func loadKB() (map[string]string, string) {
entries, err := fs.ReadDir(kbFiles, "kb")
if err != nil {
panic(err)
}
articles := map[string]string{}
index := ""
for _, e := range entries {
b, err := kbFiles.ReadFile("kb/" + e.Name())
if err != nil {
panic(err)
}
summary, body, _ := strings.Cut(string(b), "\n")
topic := strings.TrimSuffix(e.Name(), ".md")
articles[topic] = strings.TrimSpace(body)
index += fmt.Sprintf("\n- %s: %s", topic, summary)
}
return articles, index
}
func (m *Manager) readKnowledgeTool() mcp.Tool {
return mcp.Tool{
Name: "read_knowledge",
Description: "Read an article from byre's knowledge base: how byre features work that agents need only now and then. " +
"Read the matching article before working on or answering about one of these topics:" + kbIndex,
InputSchema: json.RawMessage(`{
"type": "object",
"properties": {
"topic": {"type": "string", "description": "The article's topic, as listed."}
},
"required": ["topic"]
}`),
Handler: func(ctx context.Context, raw json.RawMessage) (string, error) {
args := struct {
Topic string `json:"topic"`
}{}
err := json.Unmarshal(raw, &args)
if err != nil {
return "", fmt.Errorf("malformed read_knowledge call: %w", err)
}
body, ok := kb[args.Topic]
if !ok {
return "", fmt.Errorf("no article %q; the topics are:%s", args.Topic, kbIndex)
}
return body, nil
},
}
}
+29
View File
@@ -0,0 +1,29 @@
How byre signs merge commits on the merging user's Mac, and how to turn it on for a project.
# Signing merge commits
byre never signs with a key on the machine it runs on. When a project checkout has `commit.gpgsign` true, the squash commit of a Merge or `merge_to_main` is signed on the merging user's most recently active connected Mac, so a key that never leaves that Mac (a Secure Enclave key behind Touch ID, say) works. The merge fails when that user has no app connected.
## Turning it on
Run, on the machine byre runs on:
```
byre signing <checkout>
```
`<checkout>` is the project's main checkout, not a task worktree. It sets `commit.gpgsign` true for the checkout and false for its task worktrees (which would otherwise try to sign on the server and fail), prints both values, and fails unless the checkout's reads true. It refuses a checkout that is itself a linked worktree. No restart is needed; the next merge reads the config.
## What the Mac needs
The Mac's own git signing config, the same that signs the user's local commits:
- `gpg.format`: `openpgp` (default) or `x509`. `ssh` is not supported.
- The program, when it isn't `gpg` or `gpgsm`: `gpg.openpgp.program` or `gpg.program`, or `gpg.x509.program`.
- `user.signingkey`, when the program can't find the key from the user's git identity in byre.
The program must print `[GNUPG:] SIG_CREATED ` on its status fd. A Touch ID prompt left unanswered for 2 minutes fails the merge.
## Checking
`git -C <checkout> cat-file commit HEAD` shows a `gpgsig` header on a signed merge commit. The notes commit under `refs/notes/byre` is not signed.
+53
View File
@@ -0,0 +1,53 @@
The JSON format a usage command prints so byre's Status tab shows a vendor's usage and limits, and how to set one.
# Usage commands
byre shows each vendor's (claude, codex, antigravity) usage and limits in the Status tab. By default it uses what the vendor itself reports. A usage command replaces that for one vendor: a shell command that prints the numbers in a vendor-neutral format, so byre needn't know where they come from.
## Contract
- byre runs it with `$SHELL -l -c '<command>'` in byre's own environment (no task's worktree or `$PORT`), at startup, after every turn of that vendor's agents ends, and when the command is saved. One run at a time per vendor.
- It must finish within 10 seconds, print one JSON object to stdout and exit 0. On a non-zero exit, a timeout or output that doesn't parse, byre shows nothing for that vendor.
- Every field is optional. Unknown fields are ignored. No field names a vendor.
```json
{
"updated_at": "2026-10-19T21:24:56Z",
"rejected": "daily budget spent",
"windows": [
{
"label": "Today",
"used": 150.94,
"limit": 200,
"unit": "usd",
"resets_at": "2026-10-20T12:00:00Z",
"window_seconds": 86400
},
{
"label": "Rate",
"used": 36,
"limit": 40,
"unit": "requests",
"resets_in_seconds": 240
}
]
}
```
| Field | Meaning |
|---|---|
| `updated_at` | RFC 3339 time the numbers were current; now when absent. |
| `rejected` | Why the vendor is refusing work; absent while it isn't. A window whose `used` reaches its `limit` also shows the vendor as rejected. |
| `windows[]` | Independent meters, shown in order. |
| `label` | Short name for the meter. |
| `used`, `limit` | Numbers in `unit`. A window without `limit` shows as a bare count. |
| `unit` | `usd`, `tokens`, `requests` or `percent`; selects formatting. |
| `resets_at` | RFC 3339 time the meter resets. |
| `resets_in_seconds` | Alternative to `resets_at`, relative to `updated_at`. |
| `window_seconds` | The window's length; with `resets_at`, it draws the pace bar of time elapsed against amount used. |
Status shows the example as `Today $150.94 / $200.00 · 75% … in 14h 35m` and `Rate 36 / 40 requests · 90% … in 4m`.
## Setting one
The human sets it in the app: Server tab, Usage commands, one field per vendor; empty uses the vendor's own reports. The same is `PUT /api/admin/usage-commands` with `{"claude": "...", "codex": "...", "antigravity": "..."}` (all three; `GET` reads them). Test a command by running it by hand and checking its output parses as above.
+1 -1
View File
@@ -95,7 +95,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
}),
tool("read_status",
"Read byre's health as JSON, the same as the Status tab: rate_limits (the latest each vendor reported: how much of its window is used, when it resets, and whether it is allowed or allowed_warning), "+
"Read byre's health as JSON, the same as the Status tab: rate_limits (each vendor's latest usage: per window, how much is used of its limit and in what unit, and when it resets),"+
"agent_processes with each one's health, zombies, protocol_errors and running_turns. "+
"Check it before starting a batch of work or when agents misbehave: warn the human when a vendor nears its limit, and put new work on the vendor with headroom.",
`{"type": "object", "properties": {}}`,
+29 -42
View File
@@ -46,22 +46,23 @@ type Manager struct {
clients *clients.Registry
terminals *terminal.Terminals
mu sync.Mutex
live map[string]*live
starting map[string]*start
closing bool
rateLimits map[api.AgentSessionVendor]map[string]any
leadAnswered map[string]bool
paneFocus map[string]api.PaneFocus
paneReported map[string]time.Time
paneMoved map[string]time.Time
humanMoved map[string]time.Time
moveRefused map[string]bool
startedTodo map[string]time.Time
startRefused map[string]bool
finishing map[string]bool
handoffModel map[string]string
mergeTurns map[string]mergeTurn
mu sync.Mutex
live map[string]*live
starting map[string]*start
closing bool
rateLimits map[api.AgentSessionVendor]api.Usage
usageCommands map[api.AgentSessionVendor]string
leadAnswered map[string]bool
paneFocus map[string]api.PaneFocus
paneReported map[string]time.Time
paneMoved map[string]time.Time
humanMoved map[string]time.Time
moveRefused map[string]bool
startedTodo map[string]time.Time
startRefused map[string]bool
finishing map[string]bool
handoffModel map[string]string
mergeTurns map[string]mergeTurn
deliverMu sync.Mutex
deliverLocks map[string]*sessionLock
@@ -76,6 +77,8 @@ type Manager struct {
reviewMu sync.Mutex
usageMu map[api.AgentSessionVendor]*sync.Mutex
workflowMu sync.Mutex
bad *badLines
@@ -141,7 +144,9 @@ func New(st *store.Store, worktreeRoot, leadRoot, handsRoot, codexHome, antigrav
live: map[string]*live{},
starting: map[string]*start{},
deliverLocks: map[string]*sessionLock{},
rateLimits: map[api.AgentSessionVendor]map[string]any{},
rateLimits: map[api.AgentSessionVendor]api.Usage{},
usageCommands: map[api.AgentSessionVendor]string{},
usageMu: map[api.AgentSessionVendor]*sync.Mutex{api.Claude: {}, api.Codex: {}, api.Antigravity: {}},
leadAnswered: map[string]bool{},
paneFocus: map[string]api.PaneFocus{},
paneReported: map[string]time.Time{},
@@ -160,8 +165,7 @@ func New(st *store.Store, worktreeRoot, leadRoot, handsRoot, codexHome, antigrav
watchStop: make(chan struct{}),
}
go m.signalLoop()
go m.readCodexRateLimit()
go m.readAgyRateLimit()
go m.loadUsage()
return m
}
@@ -504,13 +508,13 @@ func (m *Manager) LiveCount() int {
type Usage struct {
Running []api.TurnRef
RateLimits map[string]map[string]any
RateLimits map[string]api.Usage
}
func (m *Manager) Usage(ctx context.Context) (Usage, error) {
u := Usage{
Running: []api.TurnRef{},
RateLimits: map[string]map[string]any{},
RateLimits: map[string]api.Usage{},
}
running, err := m.store.SessionsInState(ctx, api.AgentSessionStateRunning)
@@ -738,7 +742,7 @@ func (m *Manager) startLive(ctx context.Context, sess api.AgentSession, task api
if err != nil {
return nil, err
}
tools := append([]mcp.Tool{m.askTool(l), m.cancelQuestionTool(l), m.setMergeTitleTool(l), m.stopMergeTool(l), m.mergeToMainTool(l), m.setTaskSummaryTool(l), m.searchClosedTool(l), m.exposePortTool(l), m.takeSnapshotTool(l), m.terminalReadTool(l), m.terminalTypeTool(l), m.bashTool(l)}, append(m.subtaskTools(l), m.clientTools(l)...)...)
tools := append([]mcp.Tool{m.askTool(l), m.cancelQuestionTool(l), m.setMergeTitleTool(l), m.stopMergeTool(l), m.mergeToMainTool(l), m.setTaskSummaryTool(l), m.searchClosedTool(l), m.exposePortTool(l), m.takeSnapshotTool(l), m.terminalReadTool(l), m.terminalTypeTool(l), m.bashTool(l), m.readKnowledgeTool()}, append(m.subtaskTools(l), m.clientTools(l)...)...)
lead := true
if sess.Role == api.Implementer {
g += longTitleGuidance(task)
@@ -806,7 +810,7 @@ func (m *Manager) startLive(ctx context.Context, sess api.AgentSession, task api
return nil, err
}
l.notes = "\n\n" + notes
tools = m.leadTools(l)
tools = append(m.leadTools(l), m.readKnowledgeTool())
env = nil
}
servers := []*mcp.Server{{Name: "byre", Version: "0.0.0", Tools: tools}}
@@ -1001,14 +1005,12 @@ func (m *Manager) handle(ctx context.Context, l *live, ev claude.Event) error {
return err
}
addClaudeWindowMins(info.RateLimitInfo)
m.mu.Lock()
m.rateLimits[l.vendor] = info.RateLimitInfo
if info.RateLimitInfo["status"] == "rejected" {
l.rateLimited = info.RateLimitInfo
}
m.mu.Unlock()
m.setVendorUsage(l.vendor, claudeUsage(info.RateLimitInfo))
case "system":
if ev.Subtype == "init" {
@@ -1057,6 +1059,7 @@ type endResult struct {
}
func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error {
go m.readUsage(l.vendor)
if l.owner != "" {
return m.leadTurnEnded(ctx, l, res)
}
@@ -1339,22 +1342,6 @@ func (m *Manager) event(l *live, actor, kind string, payload map[string]any) api
return ev
}
func addClaudeWindowMins(info map[string]any) {
windows, _ := info["unifiedWindows"].(map[string]any)
for name, w := range windows {
window, ok := w.(map[string]any)
if !ok {
continue
}
switch {
case strings.HasPrefix(name, "five_hour"):
window["windowMins"] = 5 * 60
case strings.HasPrefix(name, "seven_day"):
window["windowMins"] = 7 * 24 * 60
}
}
}
func decode(raw json.RawMessage) (any, error) {
if len(raw) == 0 {
return nil, nil
+205
View File
@@ -0,0 +1,205 @@
package agents
import (
"context"
"encoding/json"
"errors"
"fmt"
"log/slog"
"maps"
"os"
"os/exec"
"slices"
"strings"
"syscall"
"time"
"g.fc.run/ai/byre/internal/api"
)
const usageTimeout = 10 * time.Second
func (m *Manager) loadUsage() {
cmds, err := m.store.UsageCommands(context.Background())
if err != nil {
slog.Error("load usage commands", "err", err)
return
}
m.mu.Lock()
m.usageCommands = cmds
m.mu.Unlock()
go m.readCodexRateLimit()
for _, v := range []api.AgentSessionVendor{api.Claude, api.Codex, api.Antigravity} {
go m.readUsage(v)
}
}
func (m *Manager) UsageCommands() api.UsageCommands {
m.mu.Lock()
defer m.mu.Unlock()
return api.UsageCommands{
Claude: m.usageCommands[api.Claude],
Codex: m.usageCommands[api.Codex],
Antigravity: m.usageCommands[api.Antigravity],
}
}
func (m *Manager) SetUsageCommands(ctx context.Context, actor string, c api.UsageCommands) error {
cmds := map[api.AgentSessionVendor]string{
api.Claude: strings.TrimSpace(c.Claude),
api.Codex: strings.TrimSpace(c.Codex),
api.Antigravity: strings.TrimSpace(c.Antigravity),
}
err := m.store.SetUsageCommands(ctx, actor, cmds)
if err != nil {
return err
}
changed := []api.AgentSessionVendor{}
m.mu.Lock()
for v, cmd := range cmds {
if m.usageCommands[v] != cmd {
changed = append(changed, v)
delete(m.rateLimits, v)
}
}
m.usageCommands = cmds
m.mu.Unlock()
m.store.Broadcast(api.Event{Kind: "admin.health", Actor: "byre", Payload: map[string]any{}})
for _, v := range changed {
if v == api.Codex && cmds[v] == "" {
go m.readCodexRateLimit()
}
go m.readUsage(v)
}
return nil
}
func (m *Manager) readUsage(vendor api.AgentSessionVendor) {
mu := m.usageMu[vendor]
mu.Lock()
defer mu.Unlock()
m.mu.Lock()
cmdline := m.usageCommands[vendor]
m.mu.Unlock()
if cmdline == "" {
if vendor == api.Antigravity {
m.readAgyRateLimit()
}
return
}
u, err := runUsageCommand(cmdline)
m.mu.Lock()
if m.usageCommands[vendor] != cmdline {
m.mu.Unlock()
return
}
if err != nil {
delete(m.rateLimits, vendor)
} else {
m.rateLimits[vendor] = u
}
m.mu.Unlock()
if err != nil {
slog.Error("usage command", "vendor", vendor, "err", err)
}
m.store.Broadcast(api.Event{Kind: "admin.health", Actor: "byre", Payload: map[string]any{}})
}
func (m *Manager) setVendorUsage(vendor api.AgentSessionVendor, u api.Usage) {
m.mu.Lock()
if m.usageCommands[vendor] != "" {
m.mu.Unlock()
return
}
m.rateLimits[vendor] = u
m.mu.Unlock()
m.store.Broadcast(api.Event{Kind: "admin.health", Actor: "byre", Payload: map[string]any{}})
}
func runUsageCommand(cmdline string) (api.Usage, error) {
shell := os.Getenv("SHELL")
if shell == "" {
return api.Usage{}, errors.New("SHELL is not set in byre's environment")
}
ctx, cancel := context.WithTimeout(context.Background(), usageTimeout)
defer cancel()
cmd := exec.CommandContext(ctx, shell, "-l", "-c", cmdline)
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Cancel = func() error {
return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
}
cmd.WaitDelay = time.Second
out, err := cmd.Output()
if err != nil {
return api.Usage{}, fmt.Errorf("%s: %w", cmdline, err)
}
return parseUsage(out)
}
func parseUsage(out []byte) (api.Usage, error) {
in := struct {
UpdatedAt *time.Time `json:"updated_at"`
Rejected *string `json:"rejected"`
Windows []struct {
api.UsageWindow
ResetsInSeconds *float64 `json:"resets_in_seconds"`
} `json:"windows"`
}{}
err := json.Unmarshal(out, &in)
if err != nil {
return api.Usage{}, fmt.Errorf("usage output: %w", err)
}
u := api.Usage{UpdatedAt: time.Now(), Rejected: in.Rejected, Windows: []api.UsageWindow{}}
if in.UpdatedAt != nil {
u.UpdatedAt = *in.UpdatedAt
}
for _, w := range in.Windows {
if w.ResetsAt == nil && w.ResetsInSeconds != nil {
w.ResetsAt = new(u.UpdatedAt.Add(time.Duration(*w.ResetsInSeconds * float64(time.Second))))
}
u.Windows = append(u.Windows, w.UsageWindow)
}
return u, nil
}
func percentWindow(label string, fraction float64, resetsAt int64, windowSeconds int64) api.UsageWindow {
w := api.UsageWindow{Label: label, Used: fraction * 100, Limit: new(100.0), Unit: "percent"}
if resetsAt != 0 {
w.ResetsAt = new(time.Unix(resetsAt, 0))
}
if windowSeconds != 0 {
w.WindowSeconds = &windowSeconds
}
return w
}
func claudeUsage(info map[string]any) api.Usage {
u := api.Usage{UpdatedAt: time.Now(), Windows: []api.UsageWindow{}}
if info["status"] == "rejected" {
reason, _ := info["rateLimitType"].(string)
u.Rejected = new(reason)
}
windows, _ := info["unifiedWindows"].(map[string]any)
for _, name := range slices.Sorted(maps.Keys(windows)) {
w, ok := windows[name].(map[string]any)
if !ok {
continue
}
used, _ := w["utilization"].(float64)
resets, _ := w["resetsAt"].(float64)
seconds := int64(0)
switch {
case strings.HasPrefix(name, "five_hour"):
seconds = 5 * 60 * 60
case strings.HasPrefix(name, "seven_day"):
seconds = 7 * 24 * 60 * 60
}
u.Windows = append(u.Windows, percentWindow(name, used, int64(resets), seconds))
}
return u
}
+349 -262
View File
@@ -1231,8 +1231,8 @@ type Status struct {
Projects int `json:"projects"`
ProtocolErrors ProtocolErrors `json:"protocol_errors"`
// RateLimits The latest rate-limit status each vendor reported, keyed by vendor.
RateLimits map[string]map[string]interface{} `json:"rate_limits"`
// RateLimits Each vendor's latest usage, keyed by vendor, from its usage command or, without one, what the vendor itself reported.
RateLimits map[string]Usage `json:"rate_limits"`
// RunningTurns Turns running now, oldest session first.
RunningTurns []TurnRef `json:"running_turns"`
@@ -1429,6 +1429,46 @@ type Unmerged struct {
Uncommitted int `json:"uncommitted"`
}
// Usage defines model for Usage.
type Usage struct {
// Rejected Why the vendor is refusing work, such as a usage cap or depleted credits; absent while it isn't. A window at its limit also counts as rejected.
Rejected *string `json:"rejected,omitempty"`
// UpdatedAt When the numbers were current.
UpdatedAt time.Time `json:"updated_at"`
// Windows Independent meters, in the order to show them.
Windows []UsageWindow `json:"windows"`
}
// UsageCommands The shell command that reports each vendor's usage, keyed by vendor; empty uses what the vendor itself reports.
type UsageCommands struct {
Antigravity string `json:"antigravity"`
Claude string `json:"claude"`
Codex string `json:"codex"`
}
// UsageWindow defines model for UsageWindow.
type UsageWindow struct {
// Label Short name for the meter.
Label string `json:"label"`
// Limit The window's limit
Limit *float64 `json:"limit,omitempty"`
// ResetsAt When the meter resets.
ResetsAt *time.Time `json:"resets_at,omitempty"`
// Unit usd, tokens, requests or percent; selects formatting.
Unit string `json:"unit"`
// Used Amount used
Used float64 `json:"used"`
// WindowSeconds The window's length
WindowSeconds *int64 `json:"window_seconds,omitempty"`
}
// User defines model for User.
type User struct {
// DefaultModel The model the app starts new tasks on.
@@ -1599,6 +1639,9 @@ type GetTaskTerminalParams struct {
Rows int `form:"rows" json:"rows"`
}
// UpdateUsageCommandsJSONRequestBody defines body for UpdateUsageCommands for application/json ContentType.
type UpdateUsageCommandsJSONRequestBody = UsageCommands
// RespondInboxJSONRequestBody defines body for RespondInbox for application/json ContentType.
type RespondInboxJSONRequestBody = InboxRespond
@@ -1662,6 +1705,12 @@ type ServerInterface interface {
// (GET /api/admin/status)
GetStatus(w http.ResponseWriter, r *http.Request)
// (GET /api/admin/usage-commands)
GetUsageCommands(w http.ResponseWriter, r *http.Request)
// (PUT /api/admin/usage-commands)
UpdateUsageCommands(w http.ResponseWriter, r *http.Request)
// (POST /api/blobs)
UploadBlob(w http.ResponseWriter, r *http.Request)
@@ -1892,6 +1941,34 @@ func (siw *ServerInterfaceWrapper) GetStatus(w http.ResponseWriter, r *http.Requ
handler.ServeHTTP(w, r)
}
// GetUsageCommands operation middleware
func (siw *ServerInterfaceWrapper) GetUsageCommands(w http.ResponseWriter, r *http.Request) {
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.GetUsageCommands(w, r)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// UpdateUsageCommands operation middleware
func (siw *ServerInterfaceWrapper) UpdateUsageCommands(w http.ResponseWriter, r *http.Request) {
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.UpdateUsageCommands(w, r)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// UploadBlob operation middleware
func (siw *ServerInterfaceWrapper) UploadBlob(w http.ResponseWriter, r *http.Request) {
@@ -3858,6 +3935,8 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/inbox/responses", wrapper.RespondInbox)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/events", wrapper.StreamEvents)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/admin/status", wrapper.GetStatus)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/admin/usage-commands", wrapper.GetUsageCommands)
m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/admin/usage-commands", wrapper.UpdateUsageCommands)
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/admin/permissions", wrapper.CheckPermissions)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/workflows", wrapper.ListWorkflows)
m.HandleFunc(http.MethodDelete+" "+options.BaseURL+"/api/workflows/{name}", wrapper.DeleteWorkflow)
@@ -3872,266 +3951,274 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
// const string: with thousands of chunks the chained `+` fold is several
// times slower for the Go compiler than parsing a slice literal.
var swaggerSpec = []string{
"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",
"TustmrGzVPPgPr9XtZ737//PAA==",
"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",
}
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,
+18
View File
@@ -632,6 +632,24 @@ func (s *Server) CheckPermissions(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, perms)
}
func (s *Server) GetUsageCommands(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, s.agents.UsageCommands())
}
func (s *Server) UpdateUsageCommands(w http.ResponseWriter, r *http.Request) {
req := api.UsageCommands{}
if !readJSON(w, r, &req) {
return
}
err := s.agents.SetUsageCommands(r.Context(), actor(r), req)
if err != nil {
writeStoreError(w, err)
return
}
writeJSON(w, http.StatusOK, s.agents.UsageCommands())
}
func (s *Server) status(ctx context.Context) (api.Status, error) {
c, err := s.store.Counts(ctx)
if err != nil {
@@ -0,0 +1,4 @@
CREATE TABLE usage_commands (
vendor TEXT PRIMARY KEY,
command TEXT NOT NULL
);
+43
View File
@@ -0,0 +1,43 @@
package store
import (
"context"
"database/sql"
"g.fc.run/ai/byre/internal/api"
)
func (s *Store) UsageCommands(ctx context.Context) (map[api.AgentSessionVendor]string, error) {
rows, err := s.db.QueryContext(ctx, `SELECT vendor, command FROM usage_commands`)
if err != nil {
return nil, err
}
defer rows.Close()
cmds := map[api.AgentSessionVendor]string{}
for rows.Next() {
vendor := ""
cmd := ""
err = rows.Scan(&vendor, &cmd)
if err != nil {
return nil, err
}
cmds[api.AgentSessionVendor(vendor)] = cmd
}
return cmds, rows.Err()
}
func (s *Store) SetUsageCommands(ctx context.Context, actor string, cmds map[api.AgentSessionVendor]string) error {
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
for vendor, cmd := range cmds {
_, err := tx.ExecContext(ctx, `
INSERT INTO usage_commands (vendor, command) VALUES (?, ?)
ON CONFLICT (vendor) DO UPDATE SET command = excluded.command
`, string(vendor), cmd)
if err != nil {
return err
}
}
return emit(api.Event{Kind: "admin.usage_commands", Actor: actor, Payload: map[string]any{}})
})
}