Skip to content

Releases: lyc-aon/successor-agent

v0.1.39 — z.ai vision wiring + browser verification loop fix

Choose a tag to compare

@lyc-aon lyc-aon released this 18 Apr 00:52

v0.1.39 — 2026-04-17

GLM / z.ai subscription vision wiring, browser verification loop fix,
and Anthropic tool_result wire format correction. Driven by a real
GLM 5.1 repro where the model got stuck reopening the same page 4-5
times in a row during a verification run.

What changed

  • z.ai vision auto-wiring. The z.ai preset now carries a
    tool_defaults.vision block pointing at glm-4.6v on the same
    Anthropic-compatible endpoint that covers the GLM Coding Plan
    subscription. Picking that preset in successor setup and enabling
    the vision tool wires it end-to-end with zero manual config. Model
    choice is deliberate: glm-5v-turbo + /paas/v4 is pay-as-you-go
    and not covered by the subscription; glm-4.6v + /api/anthropic
    is.

  • New VISION_PROVIDER_OPTIONS value: anthropic. The vision
    tool now supports an Anthropic-compatible dispatch path that posts
    to {base_url}/v1/messages with Anthropic-style image content
    blocks (source.{type:"base64", media_type, data}) and x-api-key
    auth. Alongside the existing llamacpp and openai_compat paths.

  • Primary-client API key fallback for vision. If the vision
    block's api_key is empty, the harness now reuses the active chat
    provider's key. Users drop their z.ai key in the provider block
    once; the vision tool picks it up automatically.

  • New bundled profile: zai.json. Ships with GLM 5.1 as the
    text brain on the Anthropic endpoint and vision routed to
    glm-4.6v on the same endpoint. Zero-config starting point for
    z.ai users.

  • ProviderPreset.tool_defaults field. New optional
    dict[str, dict] mirroring Profile.tool_config. Lets any preset
    carry paired tool defaults that flow into new wizard-created
    profiles automatically for whichever tools the user enables.
    Extensible to browser/holonet/etc. in one-line preset edits.

  • Browser verification loop fix. The browser_runtime guidance
    is now one-shot per user turn instead of re-injected every agent
    tick — free-code's memoized-per-session approach, applied to the
    turn scope. Repeated re-injection of the verification recipe was
    actively keeping capable models (GLM 5.1, Claude) from
    self-terminating when their contract was already satisfied.

  • Hard refusal on 5th identical browser open. Previously the
    tracker appended the same polite "you reopened the same page"
    progress note on every repeat, which the model could ignore
    indefinitely. Now the 5th consecutive open of the same target
    with unchanged state returns exit_code=1 with a clear "Refused:
    Nth consecutive open, reply with plain text" stderr. Different
    target or state-changed open resets the streak.

  • Contract-settled one-shot nudge. When the verification ledger
    transitions from has-open-items → all-passed within a user turn,
    the harness queues a single "You're done. Reply with plain text
    now. Do not run additional browser, screenshot, or vision calls
    unless the user asks." Consumed on emit. Gives capable models a
    clear stop signal that never existed before.

  • Removed "consider more edge cases" and "launch verifier
    subagent" nudges.
    Three lines in verification_contract.py and
    web/verification.py kept re-appearing every turn even after the
    contract was all-passed, training the model to always do more.
    Free-code has no equivalent; the contract's existence is
    sufficient signal.

  • Anthropic tool_result wire format fix. Previously each
    role="tool" log message became its own {"role": "user"} with a
    single tool_result block, producing a malformed sequence when
    one assistant turn emitted multiple tool_use blocks. Now
    consecutive tool results coalesce into one user message with N
    tool_result blocks per Anthropic spec, matching free-code. Also
    added a native-tool discriminator in LogMessage.to_api_dict():
    non-bash cards with a tool_call_id emit role="tool" for
    proper structured wire format; bash keeps its text-fence flatten
    for llama.cpp chat-template compatibility.

  • Version-aware _api_root regex. Both providers/openai_compat.py
    and web/vision.py now recognize any /vN path segment (not just
    /v1) when normalizing a base URL. Latent bug that produced
    …/paas/v4/v1/models 404s for non-v1 versioned endpoints like
    z.ai's /paas/v4.

Verification

  • pytest -q — 1377 passed
  • End-to-end probe against z.ai with a real subscription key confirms
    the Anthropic vision dispatch returns 200 on the first call
    (billing passthrough, no 429s).
  • New tests cover: preset tool_defaults propagation via the wizard,
    settled-nudge emission, 5th-identical-open refusal, anthropic
    tool_result batching, and the native-tool vs bash-text
    discriminator in to_api_dict.

v0.1.38 — Agent Loop Hardening + Compaction Overhaul

Choose a tag to compare

@lyc-aon lyc-aon released this 17 Apr 07:52

What changed

Driven by real small-model testing with Qwen 3.6-35B-A3B on local compute.

Interrupt handling

  • Ctrl+C double-press — first press interrupts the running stream/tools/compaction, second press within 800ms exits cleanly. No more instant-kill.

Browser tool

  • js_eval actionpage.evaluate() for running arbitrary JavaScript against the live page. Read DOM state, call functions, inspect variables directly.
  • Screenshot loop prevention — read-only actions no longer reset the stagnant-state counter. Screenshot streak detector nudges after 3+ consecutive screenshots. Action-repeat tracker nudges after 3+ identical calls.

File tools

  • edit_file works after partial reads — no longer requires a full read_file first. Partial reads accepted; old_string match against disk content is the safety check.

Compaction overhaul

Four changes that collectively double the usable context runway between compaction cycles:

  • Tool outputs in kept rounds cleared during compaction (keeps 4 most recent, replaces older ones with placeholders)
  • Microcompact keeps 4 most recent tool results (was 8)
  • System prompt measurement uses the full assembled prompt instead of the short profile prompt
  • Default keep_recent_rounds lowered from 6 to 2 for tool-heavy profiles

Vision

  • Thinking-model fix — falls back to reasoning_content when content is empty (fixes Qwen 3.x analysis). Default max_tokens raised to 16384.

Testing infrastructure

  • New scripts/sandbox_runner.py + scripts/sandbox_scenarios.py — 4-tier E2E testing framework for small-model behavior observation.

Verification

  • ruff check src tests — all clean
  • pytest -q — 1362 passed

v0.1.36 - KV-friendly prompt assembly hotfix

Choose a tag to compare

@lyc-aon lyc-aon released this 11 Apr 04:33

This hotfix fixes a real performance regression in long local-model sessions: Successor now preserves a KV-cache-friendly request shape instead of quietly rewriting earlier prompt bytes as the conversation grows.

What changed

  • made prompt assembly append-only in the places that matter for local cache reuse
    • runtime-tail context is now always appended as its own synthetic turn instead of being merged into the latest real user message
    • adjacent same-role API messages now preserve their original boundaries instead of being merged together later
  • stabilized native tool-call serialization
    • assistant tool_calls[].function.arguments now use canonical JSON ordering so identical tool payloads serialize to identical bytes
  • added better cache-shape diagnostics
    • turn traces and /perf now record request prefix hash, full request hash, and tail kind alongside the existing stable-system hash and llama timing data
    • this makes it possible to distinguish harness-side request-shape churn from provider-side cache dropout

Verification

  • ruff check src tests
  • PYTHONPATH=src pytest -q
    • 1277 passed in 25.56s
  • live llama.cpp KV verification
    • before fix: repeated late-turn cache_n=0, median first-token latency ~34s, suspected KV misses across many turns
    • after fix: cache_n grows turn-to-turn, hit ratio stays roughly 0.8–0.94, and first-token latency stays sub-second in the extended local-model session

v0.1.35 - semantic tool cards and compaction floor fix

Choose a tag to compare

@lyc-aon lyc-aon released this 11 Apr 03:12

This release tightens the tool-card surface so long iterative runs are
easier to read while they are happening and easier to trust after the
fact.

What changed

  • semantic streamed tool previews are now first-class instead of
    bash-biased placeholders
    • in-flight native tool calls keep stable glyphs and labels while
      their arguments stream in
    • unknown streamed tools now render as explicit unsupported/pending
      states instead of temporarily pretending to be bash
    • the live ↳ tool preview now attaches directly below the assistant
      text without the old stray spacer/cursor line
  • task and verification cards now use richer card-native rendering
    • full task/proof lists are always shown instead of being clipped by
      the generic tool-output cap
    • task and verification rows now have status-specific treatment for
      completed, active/running, pending, and failed states
    • card headers now carry summary badges like 4 tasks, 1 active,
      3 checks, and 1 failed
  • verification can now annotate the earlier step it actually judged
    • after a verify update, the most recent substantive prior tool
      card gets a retroactive proof badge such as verified or
      proof failed
  • manual compaction now uses the real structural minimum instead of the
    old fake 4-round gate
    • 2-round sessions can compact when there is one older round to
      summarize and one newer round to keep
    • the stale Run /burn first to inflate the context refusal path is
      gone

Verification

  • ruff check src tests
  • PYTHONPATH=src pytest -q
    • 1275 passed in 25.33s
  • render-level visual verification:
    • semantic streaming preview matrix
    • paper/steel task + verify card inspection
    • retroactive proof badge inspection on prior tool cards
  • chat-level visual artifacts:
    • /tmp/successor-proof-renders/verified-paper-light-final.png
    • /tmp/successor-proof-renders/failed-steel-dark-final.png

v0.1.34 — history browser + live stream scroll

Choose a tag to compare

@lyc-aon lyc-aon released this 10 Apr 23:57

This release tightens one of the last rough edges in the terminal UX: prompt recall, wheel scrolling, and live stream rendering now stop fighting each other.

What changed

  • replaced shell-style empty-prompt history recall with a dedicated prompt-history browser
    • Ctrl+R and /history [query] now open a centered overlay with filter-as-you-type recall, preview, and draft restoration on Esc
    • bare / are now pure scroll keys again
  • restored alternate-scroll behavior when mouse off is active
    • Successor now enables DECSET ?1007 when it is not capturing the mouse, and turns it back off when mouse on reclaims wheel events
  • made live stream rows part of the scrollable viewport
    • while the model is thinking or responding, the visible stream rows now contribute to scroll headroom instead of temporarily pinning the viewport harder than the committed transcript
  • added first-class prompt/KV diagnostics on top of the cache-friendly llama.cpp loop
    • completed stream trace events now record first-token latency, total stream latency, raw provider timings, prompt cache hit ratio, and a conservative suspected-KV-miss flag
    • /perf with /kv alias reports the last few completed turns with slot id, stable hash, cache_n, prompt_n, and prompt-eval timing

Verification

  • ruff check src tests
  • PYTHONPATH=src pytest -q
    • 1254 passed in 25.23s
  • focused interaction coverage:
    • prompt-history browser open/filter/accept/restore paths
    • terminal alternate-scroll toggle behavior in mouse off
    • live-stream scroll headroom while the model is still talking

v0.1.33 - cache-friendly llama.cpp agent-loop release

Choose a tag to compare

@lyc-aon lyc-aon released this 10 Apr 20:44

v0.1.33, cache-friendly llama.cpp agent-loop release (2026-04-10)

This release turns Successor's local-model loop into something that is
KV-cache-friendly by design instead of by luck.

The core change is architectural: the request builder now keeps the
cache-critical system prefix stable across ordinary turns, moves
volatile ledger/reminder state to a tail context message, and makes the
llama.cpp cache/slot path explicit instead of relying on server
defaults. The budget UI, fill bar, and autocompact gate also now read
from the same canonical outbound request envelope, so context reporting
tracks what the harness actually sends.

What landed

  • src/successor/chat_agent_loop.py
    • splits prompt assembly into a stable system bundle and volatile
      tail-only runtime sections
    • caches the stable rendered prompt on the chat instance
    • records stable/volatile hashes and cache metadata in trace events
    • keeps one-turn reminders, ledger/runtime nudges, and other
      per-turn state out of the cache-critical front of the prompt
  • src/successor/context_usage.py
    • new canonical request-envelope layer used for both prompt assembly
      accounting and runtime budget reporting
    • tracks stable-system hash, volatile-tail hash, cache-break reasons,
      slot id, and prompt-cache preference per turn
  • src/successor/providers/llama.py
    • explicitly sends cache_prompt=true
    • supports preferred id_slot when llama.cpp exposes slot support
    • adds exact /tokenize support for llama-backed token accounting
  • src/successor/chat.py
    • applies provider cache preferences on live client/profile changes
    • reserves a foreground slot for the parent chat when slot-aware
      background scheduling is available
    • aligns post-compact cache-warmer behavior with the deferred-turn
      resume path
  • src/successor/subagents/manager.py
    • routes child chats onto non-foreground slots when available
    • claims and releases child slot affinity explicitly
  • src/successor/tasks.py
    • splits stable task primer guidance from volatile execution state
  • src/successor/verification_contract.py
    • splits stable verification primer guidance from volatile runtime
      verification state
  • src/successor/runbook.py
    • splits stable experiment/runbook primer guidance from volatile
      attempt/runtime state
  • src/successor/providers/openai_compat.py
    • preserves tool-call fields and tools= handling so the generic
      OpenAI-compatible path stays coherent with the new request envelope
  • docs
    • adds:
      • docs/chat-agent-loop-refactor-plan.md
      • docs/chat-display-runtime-refactor-plan.md
    • updates:
      • docs/chat-runtime-refactor-plan.md
      • README.md
      • CHANGELOG.md

Release verification

  • lint:
    • ruff check src tests
  • full suite:
    • PYTHONPATH=src pytest -q
    • 1256 passed in 25.00s
  • live supervised E2E:
    • workspace:
      • /home/lycaon/Desktop/successor-kv-cache-e2e-20260410
    • trace:
      • /home/lycaon/.config/successor/logs/20260410-142431-p898945.jsonl
    • app:
      • /home/lycaon/Desktop/successor-kv-cache-e2e-20260410/command-cascade.html
    • screenshots:
      • /tmp/command-cascade-initial.png
      • /tmp/command-cascade-autoplay.png
    • observed cache behavior:
      • stable system hash remained e13605d528a0
      • volatile tail hash changed independently across turns
      • llama requests carried cache_prompt=true
      • foreground chat stayed on slot 0
    • observed runtime behavior:
      • the model adopted task and verify
      • the model authored the app with native file tools
      • the model found and fixed a real runtime logger bug on its own
      • independent Playwright verification passed for:
        • start screen load
        • start-game transition
        • correct-command scoring
        • autoplay/debug flow
    • remaining limitation surfaced by the run:
      • browser type still failed on a custom input control and the
        supervised loop spent too long retrying selector variants instead
        of pivoting immediately to a deterministic fallback

v0.1.32 - llama.cpp continuation-prefill hotfix

Choose a tag to compare

@lyc-aon lyc-aon released this 10 Apr 19:09

v0.1.32, llama.cpp continuation-prefill hotfix (2026-04-10)

This hotfix fixes a concrete local-model failure in the agent loop:
when Successor auto-continued after an assistant turn that contained no
visible content or after a normal assistant reply while a task or
verification item was still in_progress, the next request could be
sent to llama.cpp with the prompt ending on assistant.

That shape is rejected by llama.cpp thinking mode with:
HTTP 400: Assistant response prefill is incompatible with enable_thinking.

What landed

  • src/successor/chat_agent_loop.py
    • adds a transient internal user continuation prefill on outbound
      internal re-entry turns when the API-visible history would otherwise
      end on assistant
    • keeps the chat transcript unchanged while making the provider-facing
      prompt valid for llama.cpp thinking mode
    • marks the visible (no answer — model produced only reasoning)
      placeholder as synthetic so it no longer leaks back into model
      history
  • tests
    • adds regression coverage for task-ledger continuation,
      verification-ledger continuation, and the exact reasoning-only
      placeholder path that previously triggered the 400

Release verification

  • lint:
    • ruff check src/successor/chat_agent_loop.py tests/test_chat_tasks.py tests/test_chat_verification.py
  • targeted tests:
    • PYTHONPATH=src pytest -q tests/test_chat_tasks.py tests/test_chat_verification.py
    • 9 passed in 0.22s
    • PYTHONPATH=src pytest -q tests/test_chat_subagents.py tests/test_file_tools.py tests/test_chat_bash.py
    • 71 passed in 1.60s
  • live llama.cpp verification:
    • confirmed a raw assistant-ended prompt still returns HTTP 400
    • confirmed the same prompt succeeds once the internal continuation
      user prefill is appended

v0.1.31: task adoption nudges and reserved port guards

Choose a tag to compare

@lyc-aon lyc-aon released this 10 Apr 18:27

Highlights

This release hardens the agent loop around two practical local-model failure modes:

  • broad, stateful requests that should start with a task ledger but instead jump straight into file writes
  • preview-app serving loops that accidentally kill the live local model endpoint while trying to reclaim a familiar port like 8080

The goal is not fewer turns. The goal is a more reliable default path: plan before mutating, verify before stopping, and choose another free port before reclaiming a live runtime.

What Landed

  • new long-horizon task-adoption nudges for broad, multi-step, stateful, browser-heavy, and supervised requests
  • bounded planning reminders in the agent loop so the model adopts the session task ledger before substantive mutation, process-management, or browser loops
  • reserved-port guardrails that refuse obvious kill/reclaim commands targeting the active local provider endpoint
  • stronger bash guidance: prefer native file tools for source work, pick another free port instead of blindly reclaiming 8080, and only stop a process when it is clearly yours or the user asked
  • stronger task and browser-verification guidance so process management and runtime proof paths are explicit earlier
  • updated README, file-tools docs, changelog, and version metadata

Verification

  • ruff check passed on the shipped slice
  • targeted pytest verification passed: 66 passed
  • supervised live E2E run completed successfully against the local model
    • model adopted task before the first file mutation
    • model used native write_file for all authored files
    • model served the preview app on 8083 instead of touching the provider on 8080
    • verification contract finished 4/4 passed

Artifact References

  • live supervised trace: ~/.config/successor/logs/20260410-121402-p668167.jsonl
  • verified workspace: ~/.local/share/successor/e2e/supervised-ledger-port-guard-run/

v0.1.30

Choose a tag to compare

@lyc-aon lyc-aon released this 10 Apr 17:31

Highlights

  • Added repo-aware final-mile verification hints and stricter verifier-worker support.
  • Added stateful/runtime verification nudges so games and other realtime tasks are pushed toward a deterministic driver or autoplay harness plus an observable debug surface.
  • Continued the chat.py cleanup by extracting the display, agent-loop, and tool-runtime seams while keeping the existing SuccessorChat surface intact.
  • Updated README and local docs to reflect the stronger runtime verification workflow.

Verification

  • ruff check src tests
  • PYTHONPATH=src pytest -q
    • 1243 passed in 12.71s
  • Live supervised E2E bundle:
    • ~/.local/share/successor/e2e/stateful_verify_snake_adoption/

Note

The new stateful verifier-adoption layer improves behavior, but it is not yet a hard guarantee that the model will synthesize the best deterministic driver on its own. The release includes that improvement and keeps the remaining gap explicit in trace and playback artifacts.

Successor v0.1.29

Choose a tag to compare

@lyc-aon lyc-aon released this 10 Apr 13:06

v0.1.29, chat render seam extraction + visual verification harness (2026-04-09)

This pass reduces the risk surface inside src/successor/chat.py
without changing the underlying renderer methodology. The render
primitives, diff layer, and terminal ownership model stay intact; the
chat scene composition gets extracted into dedicated render modules with
new seam tests and explicit visual verification.

What landed

  • src/successor/render/chat_frame.py
    • layout dataclasses and frame partition helpers
  • src/successor/render/chat_header.py
    • header composition and widget placement
  • src/successor/render/chat_viewport.py
    • viewport math, body-width policy, and scroll decisions
  • src/successor/render/chat_intro.py
    • intro hero + info rail painting
  • src/successor/render/chat_overlays.py
    • help overlay and slash-command dropdown painters
  • src/successor/render/chat_input.py
    • input/search/footer painters
  • src/successor/render/chat_rows.py
    • extracted row rendering and card flattening helpers
  • src/successor/chat.py
    • now delegates scene composition into render modules while remaining
      the controller/runtime owner
  • tests/test_chat_render_layout.py
    • seam coverage for layout and paint routing
  • tests/test_chat_render_viewport.py
    • seam coverage for viewport math and streaming row placement
  • docs
    • updated README.md
    • updated docs/chat-render-refactor-plan.md
    • updated docs/changelog.md

Verification

  • lint:
    • ruff check src/successor/chat.py src/successor/render/chat_*.py tests/test_chat_render_layout.py tests/test_chat_render_viewport.py
  • bytecode:
    • PYTHONPATH=src python3 -m compileall src/successor
  • focused render slice:
    • PYTHONPATH=src pytest -q tests/test_snapshot_themes.py tests/test_intro_art.py tests/test_intro_sequence.py tests/test_chat_perf.py tests/test_chat_mouse.py tests/test_chat_paste.py tests/test_compaction_animation.py tests/test_playback.py tests/test_terminal.py tests/test_chat_render_layout.py tests/test_chat_render_viewport.py
    • 129 passed in 5.10s
  • full suite:
    • PYTHONPATH=src pytest -q
    • 1227 passed in 12.34s
  • headless human-emulated runtime verification:
    • drove ?, /theme paper, /mode light, /density spacious,
      /budget, /bash printf 'render-check\n', and two live model turns
      through SuccessorChat.on_key() + on_tick() with RecordingBundle
    • generated intro/help/autocomplete/runtime playback screenshots and
      visually confirmed bounded artboard layout, centered help modal,
      input-edge slash palette, and paper/light runtime composition