From fe10dbd5d83fe34b5bd005263002409c34953024 Mon Sep 17 00:00:00 2001 From: Corvid Agent <0xopenbytes@gmail.com> Date: Thu, 21 May 2026 16:43:32 -0700 Subject: [PATCH] fix(v0.6.2): repo view takes positional OWNER/NAME, repo file handles dirs Two real failures we just saw the corvidagent hit on a corvid-verify PR #5 lookup: 1. `github repo view CorvidLabs/corvid-verify` failed with `unknown argument 'CorvidLabs/corvid-verify'`. `gh repo view` takes the repo as a positional natively, and the agent reasonably tried the same shape. Accept it when the token looks like `owner/name` (contains a `/`); -R still works for explicit form. 2. `github repo file Sources -R CorvidLabs/corvid-verify` died with `jq: expected an object but got: array`. The contents API returns an array for directories; we were piping that into a jq filter that assumed an object with a .content field. Probe the response type once, then render: file -> decoded contents (unchanged), directory -> nametypesize listing. Same command for both, agent can now browse a remote repo with one tool instead of getting stuck. --- CHANGELOG.md | 7 ++++++ bin/fledge-github-repo | 56 +++++++++++++++++++++++++++++++++++------- plugin.toml | 2 +- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c71f0f4..96ec111 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [v0.6.2] - 2026-05-21 + +### Fixes + +- `repo view` now also accepts `OWNER/NAME` as a positional argument, matching `gh repo view`'s native syntax. Previously the agent's natural-looking `repo view CorvidLabs/corvid-verify` failed with `unknown argument` and forced an awkward retry with `-R`. +- `repo file` now detects whether the path resolves to a file or a directory and renders accordingly: file → decoded contents (as before), directory → `nametypesize` listing. Previously a directory path hit `jq: expected an object but got: array` and the agent had no way to browse remote repos. + ## [v0.6.1] - 2026-05-21 ### Fixes diff --git a/bin/fledge-github-repo b/bin/fledge-github-repo index c4f2223..5d261a5 100755 --- a/bin/fledge-github-repo +++ b/bin/fledge-github-repo @@ -20,6 +20,15 @@ if [ $# -gt 0 ] && [ "${1:0:1}" != "-" ]; then view) ACTION="view" shift + # gh's native `gh repo view ` takes the repo as a + # positional. Mirror that so the agent can call either + # `repo view CorvidLabs/x` or `repo view -R CorvidLabs/x` and + # land in the same place. Only accept it when it looks like + # owner/name (i.e. contains a /) — bare words are typos. + if [ $# -gt 0 ] && [ "${1:0:1}" != "-" ] && [[ "$1" == */* ]]; then + REPO="$1" + shift + fi ;; file) ACTION="file" @@ -42,18 +51,25 @@ while [ $# -gt 0 ]; do fledge github repo — read repo metadata and file contents via the gh CLI USAGE: - fledge github repo [view] View repo metadata (default) - fledge github repo file Read a file from the repo + fledge github repo [view] [OWNER/NAME] View repo metadata (default) + fledge github repo file Read a file OR list a directory OPTIONS: - -R, --repo Target repo (default: current working repo) + -R, --repo Target repo (default: current working repo). + view also accepts OWNER/NAME as a positional. -r, --ref Branch / tag / SHA (file only; default: repo default) --json Output JSON +The `file` action returns the file's decoded contents when PATH is a +file, or a tab-separated listing (nametypesize) when PATH +is a directory — same command, agent can browse and read with one tool. + EXAMPLES: fledge github repo - fledge github repo view -R CorvidLabs/merlin + fledge github repo view CorvidLabs/merlin + fledge github repo view -R CorvidLabs/merlin --json fledge github repo file CHANGELOG.md + fledge github repo file Sources -R CorvidLabs/corvid-verify fledge github repo file README.md -R CorvidLabs/fledge-plugin-github fledge github repo file Cargo.toml -r v0.3.0 EOF @@ -114,15 +130,37 @@ if [ "$ACTION" = "file" ]; then ENDPOINT="${ENDPOINT}?ref=${REF}" fi + # The contents API returns: + # - an object with .content (base64-encoded) when PATH is a file, + # - an array of entries when PATH is a directory. + # Previously we blindly piped .content into base64(1), which croaked + # on dirs with `expected an object but got: array`. Probe the type + # once, then render appropriately so the agent can use the SAME + # command for both file and dir lookups. if [ "$JSON" = "true" ]; then # Pass through the raw API response — caller decodes content # themselves if they want the base64. gh api "$ENDPOINT" - else - # Default: emit just the decoded file contents. The contents API - # returns base64-encoded content for files; the .content field - # holds it with embedded newlines that base64(1) tolerates. - gh api "$ENDPOINT" --jq '.content' | base64 -d + exit 0 fi + + RAW="$(gh api "$ENDPOINT")" + KIND="$(printf '%s' "$RAW" | jq -r 'if type == "array" then "dir" elif type == "object" and .type == "file" then "file" else "other" end')" + case "$KIND" in + file) + printf '%s' "$RAW" | jq -r '.content' | base64 -d + ;; + dir) + # Directory: print a brief listing. One line per entry, sorted + # like `ls -F` (trailing / for dirs). The agent can then call + # `repo file ` on whichever entry it wants. + printf '%s' "$RAW" | jq -r 'sort_by(.type, .name) | .[] | "\(if .type == "dir" then .name + "/" else .name end)\t\(.type)\t\(.size // "")"' + ;; + *) + # Symlink, submodule, or something else we don't render. Dump the + # JSON so the caller can see what it is. + printf '%s\n' "$RAW" + ;; + esac exit 0 fi diff --git a/plugin.toml b/plugin.toml index e22da9d..773e359 100644 --- a/plugin.toml +++ b/plugin.toml @@ -1,6 +1,6 @@ [plugin] name = "fledge-plugin-github" -version = "0.6.1" +version = "0.6.2" description = "GitHub commands for fledge — list/view/create/comment/review/merge PRs, list/view/create/comment/close issues, read repo files, view CI checks, and poll for daemon events via the gh CLI" author = "0xLeif" license = "MIT"