Skip to content

Feat/agon everywhere#236

Merged
cukas merged 6 commits into
mainfrom
feat/agon-everywhere
Jun 25, 2026
Merged

Feat/agon everywhere#236
cukas merged 6 commits into
mainfrom
feat/agon-everywhere

Conversation

@cukas

@cukas cukas commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

No description provided.

…annel

Browser-agent brain (agentic-brain-client). Two threads on the ReAct loop:

FLAIL/DISPATCH FIXES
- normalizeToolSchema: coerce the lent SHORTHAND inputSchema ({url:'string'}) into a real
  JSON Schema. Wire-proven root cause of kimi 'produced no answer (exit 1)' — kimi's endpoint
  400s an invalid tools.function.parameters; minimax tolerated it but flailed. Detect a real
  schema by type==='object' only (no type/properties-named-field false-positive); keep object-
  valued per-property schemas; reject arrays; skip __proto__/constructor/prototype.
- unwrapToolInputEnvelope: strip the redundant {input:{…}} the marker engines double-wrap
  (navigate({input:{url}}) → navigate({url})), schema-aware so a tool that really takes 'input'
  is never stripped. This is what fixes the live navigate/click 'invalid url' / 'needs a string
  selector' loop on minimax/kimi.
- stuck-guards: consecutive-failure cap (MAX_CONSECUTIVE_TOOL_FAILURES) + unknown-tool calls now
  count toward it; bounded read fingerprints + a size cap on the re-view map; MAX_AGENT_STEPS 30→60.

MID-TURN ASK-USER CHANNEL (implements the BrainClient contract's question-request/provideAnswer)
- A deferral now PAUSES the turn: yield question-request, register-before-yield, waitForUserAnswer,
  inject the answer, CONTINUE. questionArbitration flips to 'host-only'; provideAnswer resolves by
  requestId with FAIL-SAFE clientId arbitration (the empty-owner short-circuit dropped here AND in
  provideApproval/provideCapabilityResult). Bounded (MAX_USER_QUESTIONS=6); on timeout it falls back
  to the autonomous nudge (no dead-end). Narration still nudges.

96→ tests across the loop, schema, unwrap, ask-user, and host-only arbitration.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
AgonServe gains POST /answer {requestId, answer} → BrainClient.provideAnswer (host-only
arbitration enforced in the brain), and flushes the question-request event over SSE like an
approval so the panel sees it immediately. +2 wire tests (/answer ack + missing-requestId 400).

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
…all)

The terminal driver (agon drive) and the REPL /chrome handler both SUBMIT turns to the
agentic brain but have no mid-turn free-text answer UI. So when the engine defers and the brain
asks, they immediately reply over /answer with the autonomous-proceed guidance (the same push the
old nudge gave) instead of leaving the turn paused for QUESTION_TIMEOUT_MS. The browser panel still
answers interactively; these headless clients proceed on their own — preserving pre-feature behavior.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
…imax/zai)

The coding-plan engines were sent BOTH the native tools[] array AND the strict __AGON_TOOL__ text-marker system prompt, so they obeyed the louder text instruction — typed a marker as prose and narrated-and-stopped. Native function-calling was wired but dormant; the browser agent only drove reliably on the CLI engines (claude/codex), defeating Agon's multi-AI premise.

buildAgentSystemPrompt is now transport-aware: an engine that actually dispatches via the adapter's API path is told to CALL its native function-calling tools instead of typing the marker. runTurn derives that with the adapter's EXACT predicate — no usable binary (engine.binary ? registry.findBinary(engine) : null is null) AND an api block with its key present — so a declared-but-uninstalled binary that falls back to API also gets the native prompt (codex 0.92), and the empty-api-object case resolves correctly (kimi 0.85). The mid-turn nudge/deferral reminders are phrased per transport too. Marker-parse fallback + tool_choice:auto stay, so zero regression for claude/codex/agy and a native engine that still emits a marker is still caught.

Also hardens normalizeToolSchema with a bounded recursive sanitizeSchemaNode that strips __proto__/constructor/prototype at every depth from object-valued per-property schemas (kimi 0.85). +5 tests (transport-aware prompt + missing-binary API fallback + native nudge phrasing + deep proto-strip); 93 brain tests green, full tsc -b build, 3547 unit tests pass (2 pre-existing env failures: *.bin gitignore + claude-auth-down live probe).

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
Anthropic no longer meters `claude -p` under the subscription, so the billing reason the PTY subscription brain was the default is gone — and -p is far more reliable than scraping the interactive TUI (the scrape was 40-60% flaky for short tool-answers). Flip the default for the brain/dispatch path (chat, forge, orchestration, interactive Cesar) from PTY → --print.

All three gates (adapter shouldUseClaudePty, persistent-session factory, cesar/session DeliverAnswer wiring) now read ONE core helper, claudeBrainUsesPty(cwd?), so the policy lives in a single place. Precedence: AGON_CLAUDE_PTY env (1/true→pty, 0/false→print) overrides the persisted `claudeBackend` setting ('pty'|'print', default 'print'); pass cwd to honor a project-local .agon.json override. Switch back to the PTY brain with `agon config claudeBackend pty` or AGON_CLAUDE_PTY=1, or flip the one default in claudeBrainUsesPty.

SCOPE GUARD: the /model live model probe (cli-models-registry __pty:/model) is untouched — it always uses the TUI to read the live model list, independent of this switch. The browser extension needs no change; it inherits -p through the served brain's adapter.dispatch.

Review-hardened (two 6-engine passes): codegen duplicate-JSDoc removed (raw handler); shouldUseClaudePty now identifies claude by id OR binary (agrees with the other gates, kimi 0.85); claudeBrainUsesPty(cwd) honors project-local config (codex 0.90); only claude consults the switch so a non-claude stream-json companion is never coupled to claude's setting (minimax 0.85). +new claudeBackend setting + tests (env/config/precedence + shouldUseClaudePty id-or-binary). 3550 unit tests pass (2 pre-existing env failures only).

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
…ailure

A 401 under workspace-pure isolation (claude's clean config dir is stale or
never logged in, or an API engine's key is missing) used to surface as a bare
"produced no answer" / raw `API Error: 401`, with no clue that `agon login
<engine>` is the fix — a silent, undiscoverable hang. This adds one generic,
metadata-driven checker and wires it into every dispatch surface so the exact
recovery command is always shown.

- `authLoginHint(engine)` + `authFailureHint(engine, signal)` in engine-health
  (next to classifyDispatchFailure). Derived from the engine's OWN metadata, no
  per-engine special-casing: a CLI engine with an isolated config dir + loginArgs
  (claude/codex) → `agon login <id> --force` (--force because a 401 after a
  present authMarker means the marker is STALE, which plain login would skip);
  an API-only engine → set its apiKeyEnv / `agon provider`; else → `agon doctor`.
  Null-safe (optional-chained) so an undefined engine degrades, never throws.
- Wired into all three surfaces: the browser/serve panel notice
  (agentic-brain-client), the panel seat detail for review/forge/brainstorm/
  tribunal (seat-dispatch), and the REPL Cesar quarantine warning (cesar/brain,
  reusing the already-resolved engine to avoid a throwing registry.get).
- seat-dispatch no longer burns a doomed retry on an auth failure — a 401 can't
  recover by retrying, so the credential fix surfaces on the first attempt.

Tests: auth-failure-hint (8) covers CLI/API/fallback/precedence + non-auth →
null; seat-dispatch gains a no-retry-on-401 case. Full unit suite green (only
the pre-existing *.bin gitignore env test fails, untouched here).

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
@cukas cukas merged commit bbef6dc into main Jun 25, 2026
2 checks passed
@cukas cukas deleted the feat/agon-everywhere branch June 25, 2026 16:56
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.

2 participants