Skip to content

feat: agent-context — runtime hints, AGENTS.md, Windows render fixes#5

Merged
igor-ctrl merged 3 commits into
mainfrom
feat/agent-context
May 4, 2026
Merged

feat: agent-context — runtime hints, AGENTS.md, Windows render fixes#5
igor-ctrl merged 3 commits into
mainfrom
feat/agent-context

Conversation

@igor-ctrl

Copy link
Copy Markdown
Owner

Why

Closes friction reported by users running bcli through AI coding agents (Claude Code, Cursor, etc.). A typical session burned 5+ tool calls on guessed endpoint names, guessed field names, and redundant -e Production flags. Three independent improvements bring the average down to 1–2.

What

1. Runtime hints at the moment of failure (eb1a78a)

  • RegistryError (raised when disable_standard_api = true and the entity isn't curated) now includes a fuzzy "Did you mean: …?" suggestion using the same registry search the OTHER RegistryError raise site already uses, plus pointers to the cheaper recipes (endpoint search, endpoint list -f json).
  • HTTP 400 with BC's Could not find a property named 'X' on type 'Microsoft.NAV.Y' now auto-suggests bcli endpoint fields <entity> — with the entity name extracted from the URL via regex. Cheap, no extra network calls, doesn't fire on unrelated 400s.
  • Top-level bcli --help gets a "Discovery for AI agents" line under examples so agents that run --help first see the recipe without an extra tool call.

2. AGENTS.md at repo root (c85fcd8)

Convention now (Cursor, Claude Code, Codex) is AGENTS.md at the root rather than buried in docs/. Content covers profile/env resolution (don't pass -e if it's in the profile), endpoint discovery recipe (search → info → fields), field discovery (bcli endpoint fields <name> is canonical, don't guess), format selection, the three error patterns agents hit most, and a one-shot decision flow. Examples are domain-neutral throughout.

3. Windows table render fix (cd4d6a9)

Two compounding bugs surface together on classic PowerShell (conhost.exe, no Windows Terminal):

  • sys.stdout.isatty() returns True even when output is being captured by a parent process (an AI agent's tool runner), so the existing non-TTY → markdown auto-fallback doesn't fire.
  • Rich emits UTF-8 box-drawing characters into a CP1252 console, producing mojibake (e.g. preservationSt�).

Detect classic Windows console via sys.platform == "win32" AND WT_SESSION unset; default to markdown there. Reconfigure stdout/stderr to UTF-8 on win32 so the table path, when used deliberately, lands as proper UTF-8 bytes. Separately, mark the first column no_wrap=True so bcli endpoint list doesn't clip the entity name on narrow terminals.

Test plan

  • uv run pytest tests/ — 432 pass, 5 skipped (was 418 + 5; 14 new tests for hints + Windows detection)
  • uv run ruff check src/ — clean
  • Manual end-to-end: bcli --profile sandbox endpoint search llpendpoint info llpUtilizations -f jsonendpoint fields llpUtilizations succeeds; the agent doesn't need to --help between steps
  • grep -iE 'beautech|engine-tech|technical' AGENTS.md returns 0 matches (domain-neutral)
  • Verify on a real classic-PowerShell laptop that bcli endpoint list no longer renders

igor-ctrl added 3 commits May 4, 2026 15:01
Two of bcli's failure modes leak common AI-agent (and human) confusion:

1. RegistryError on disable_standard_api: the message told the user
   to run `bcli endpoint list` but didn't suggest the cheaper recipes
   (`endpoint search` for fuzzy match, `endpoint list -f json` for
   machine-parseable enumeration), and didn't compute the
   "did-you-mean" suggestion that the *other* RegistryError raise
   site (registry/_registry.py) already does. Result: agents would
   guess `preservationStatus` (singular) → error → run
   `endpoint list` (truncated table) → guess again. Add fuzzy
   suggestions inline, plus pointers to the cheaper commands.

2. HTTP 400 "Could not find a property named 'X'" from BC: the raw
   message gave no hint that `bcli endpoint fields <name>` was the
   right next move. Add a transport-layer hint that detects this
   specific BC pattern, extracts the entity set from the URL, and
   suggests the exact follow-up command. Cheap regex match, no extra
   network calls, and it doesn't fire on unrelated 400s.

Also wire a "Discovery for AI agents" line into the top-level
`bcli --help` text so agents that run --help first see the recipe
without an extra round trip.

Tests cover the happy path, the URL-unparseable fallback, and the
no-hint-on-other-errors negative cases.
…runcate the first column

Two compounding bugs surface together on legacy Windows PowerShell
(conhost.exe, no Windows Terminal):

1. sys.stdout.isatty() returns True even when output is being captured
   by a parent process (an AI agent's tool runner, in the case that
   prompted this), so the existing non-TTY → markdown auto-fallback
   doesn't fire.

2. Rich emits UTF-8 box-drawing characters into a CP1252 console,
   producing `�` mojibake (e.g. `preservationSt�` instead of the real
   entity name).

Detect classic Windows console as `sys.platform == "win32"` AND
`WT_SESSION` unset (Windows Terminal sets it). Default to markdown
there. Also reconfigure stdout/stderr to UTF-8 on win32 so the table
path, when used deliberately via `BCLI_FORMAT=table` or `--format
table`, at least lands as proper UTF-8 bytes.

Separately: in the table renderer, mark the first column `no_wrap=True`
so `bcli endpoint list` doesn't clip the entity name (the one column a
caller actually needs to read) on narrow terminals. Subsequent columns
keep the 40-char ellipsis cap.

Tests cover all matrix combinations: explicit env override, agent env
vars, non-TTY, POSIX TTY, Windows + classic console, Windows + WT,
and the explicit-table-format escape hatch.
Most users running Claude Code / Cursor / Codex against bcli aren't
in bcli's source tree, so docs/* never loads into their session.
AGENTS.md at the repo root is the convention agent tooling looks for
first.

Content is the doc-first counterpart to the runtime hints landed in
the previous commit: profile/env resolution (don't pass -e if it's
in the profile), endpoint discovery recipe (search → info → fields),
field discovery (don't guess — `bcli endpoint fields <name>`), format
selection trade-offs, and the three error patterns agents hit most.
Plus a one-shot decision flow.

All examples use generic placeholders (`my-profile`, `vendors`) so the
doc stays domain-neutral. Cross-linked from README.md.
@igor-ctrl igor-ctrl merged commit 9129f15 into main May 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant