Skip to content

agenttalk 0.98.0

Choose a tag to compare

@zoolok17 zoolok17 released this 07 Oct 01:36
· 632 commits to master since this release
a925106

In short: this release is mostly about the dashboards, and about seats that meet an
overloaded AI provider. The new dashboard (/v2) now works on a phone-sized screen, as one
column with tabs for what needs you, the team and the lead. Both dashboards stop treating
slightly old data as an error: the server now sends the data together with its age, and the
classic page keeps showing the last good data under an "Updating" banner instead of a red
"Degraded" box, asks for new data every 10 seconds instead of every 2, and gains a Refresh
live data button. An optional, read-only budget feed (--enable-budget, off by default) makes
this machine's gateway money figures available to the dashboard; there is no budget screen
yet. A Claude seat whose AI provider is overloaded, or whose usage limit cannot be confirmed,
now waits and tries again after 15 minutes, then 30, then every 60, instead of retrying every
few seconds for hours; this is on by default and can be switched off. The README now opens
with a plain-language front page, and several of its statements were corrected. The gateway
and its ledger are unchanged in this release, so upgrading needs no extra step.

Added

  • The new dashboard (/v2) now works on a phone-sized screen. Until now the page had a fixed
    minimum width of 1024 pixels, so on a phone it was cut off and had to be scrolled sideways.

    What you will notice: before this, /v2 on a narrow screen showed the desktop page, wider than
    the screen. Now, under 1024 pixels, it is one column with a bar at the bottom to switch between
    three parts: Needs you (the cards that wait for you, shown first), Team (usage windows
    and the team list) and Lead (the lead's latest message, the chat and the message box). Every
    button is at least 48 pixels tall, and nothing scrolls sideways down to 360 pixels wide. At 1024
    pixels and wider the page looks and works exactly as before. Themes, the keyboard shortcuts and
    the quiet, offline and needs-you states work at every width. The keyboard keys j, k,
    Enter and l only act on the cards of the Needs you part, so on a phone they do nothing while
    Team or Lead is showing. A warning that the server cannot be reached, with its Retry button,
    shows above every part, and the Needs you tab shows how many cards are open. There is no money (budget) part yet; it comes with its own feed later.

    What you need to do: nothing. This only changes how the page looks on a narrow screen; reaching
    the dashboard from a phone is not part of this change (it still listens on this computer only).

    Technical details: one @media (max-width: 1023px) block at the end of
    src/agenttalk/web_static/console2.css; a static <nav id="c2-tabs"> in render_console2
    (src/agenttalk/web.py); buildTabs / setTab in console2.js set data-c2-tab and
    data-c2-mode on #app. Tests: tests/console2_render.test.mjs and the phone tests in
    tests/test_console2_web.py.

  • An optional budget data feed for the dashboard. Before, the dashboard
    server did not read this machine's gateway ledger. Starting dashboard or
    serve with --enable-budget now makes those recorded money figures and
    limits available at GET /api/budget, including the opening balance after
    a reset and its month. The answer explains that it is not the provider's
    bill and excludes other machines. The feed is off by default, reads without
    changing the ledger, and reuses answers for ten seconds to limit short read
    locks. There is no budget screen yet; existing dashboard answers are unchanged.
    An incomplete ledger installation is reported as unavailable, rather than
    mistaken for a machine that has never been set up.

Changed

  • The README now opens with a plain-language front page. Someone who has never
    programmed can now learn from the first screen what agenttalk does, who it is for and
    what they need first: an AI tool with working access to its model, Python, the
    operating systems, and whether setup needs technical help. The front page then tells a
    normal day with a small team and its honest limits, and ends with a short way in,
    including how one lead sets up a supervised team. What agenttalk does well and under
    which conditions, what stays on your machine and what agenttalk is not are now in the
    first section of the guide. The detailed guide and reference follow further down, with
    every fact kept; the list of optional features and the file locations moved into the
    technical reference. A few points were corrected or added:

    • The bundled supervisor runs on Windows only (#356 tracks a monitor for Linux and
      macOS). The project's tests run on Windows, Linux and macOS; the managed gateway's
      background service uses Windows Task Scheduler or a systemd user service, so it
      cannot be installed on macOS; and a wrapped Codex seat whose shell is bash or zsh
      needs "reply_shell": "bash" in .agenttalk/supervisor.json.
    • You can start just one assistant, the lead, and have it set up a supervised team;
      on Windows you then start the supervisor yourself (#355 would let the lead do that
      too), and it starts the teammates in its settings in the background.
    • The pre-action check stops on a withdrawn (rescinded) request and, with --gates,
      on a gate at HOLD; the bundled lead instructions show it without --gates today
      (#362). Sending a newer request in place of an old one does not stop the old one.
    • A bus command run without an agent name stops with "no agent identity"; only the
      bundled skills fall back to a default name. The README used to say every command
      fell back silently.
    • The wrapper's reply instructions leave out the seat's name and the wrapper does not
      pass it on, so a supervised seat's reply can fail. An ordinary seat can carry its
      name (AGENTTALK_SELF) in its supervisor.json entry; a gateway-backed seat
      refuses that entry and must reply with --from <seat> (#354, with the wider
      problem in #178).
    • A restart tries to resume the assistant's session and starts a fresh one when it
      cannot; accepted lessons reach a wrapped seat's turns (up to five) or a seat run by
      hand through agenttalk sync, as reminders; a work order closes on a done or
      declined reply, on a verdict when the reply has no status field, by hand
      (ack --to-request) or by withdrawal, so closed does not always mean completed.
    • No agenttalk command merges. The optional lanes can create a branch and a
      worktree and, under their own checks, remove them; janitor --apply can save a
      worktree's uncommitted changes as a commit on its branch.
    • Lanes need the bus folder inside the code repository (#245).
    • janitor --apply can follow a folder link in a rare case and delete files outside
      the folder; use its report until that is fixed (#342).
    • Temp files are not yet routed into a seat's scratch folder (#336).
    • The dashboard's views can still be slow on a large store with a cold cache (#251).
  • A Claude seat whose AI provider is overloaded, or answers with an error that looks like a usage
    limit but cannot be confirmed, now waits and tries again later, instead of retrying every few
    seconds for hours.
    Until now such a failure was retried every 0.3 to 2 seconds until the
    "100 attempts / 4 hours" rule gave up and dead-lettered the message. This is on by default,
    and the same switch as the usage-limit park controls it.

    What changes: an overloaded provider (HTTP 529) gets two quick ordinary retries and then a
    cool-down; a throttled one (a 429 without limit details, a status or window word the wrapper
    does not know, or a rejection that no error result confirms) cools down at once. The seat then
    tries again after 15 minutes, then after 30, then every 60. The message is kept, the seat stays
    alive, and the wait and the tries made under it never count towards "100 attempts / 4 hours". A
    restart does not make it try sooner: the saved time wins. Only structured proof from the seat's
    own output counts, a later successful result cancels it, and message text never decides anything.
    A proven usage limit is unchanged.

    What you will notice: agenttalk status flags the seat provider_wait_parked(kind=...,retry=<time>);
    attention, doctor, supervisor and both web consoles show it as parked in its own words
    ("waiting for an overloaded AI provider; tries again at ...", or "waiting on a possible usage
    limit; ..."), never as a usage limit for an overload; the liaison gets one notice when it starts
    and one when its kind changes. The seat's health says provider_wait_parked.

    A usage limit whose retry at the reset time was never used keeps that retry while a cool-down
    interrupts it (a new record field, quota_wake_epoch, written only then): when the same limit
    returns, the retry comes back if it is still ahead and is exactly the reset's own retry (a saved
    time that does not match its reset is dropped, never used). The cool-down notice has the subject
    "provider-wait park notice" and names only the saved next try.

    What to do: wait, or skip the message with agenttalk ack --for <agent> --id <message id> (no
    dead-letter record). Starting the seat again does not try sooner. To get the old behaviour for all
    three kinds of park, set AGENTTALK_STOP_RETRIES_AT_LIMIT=0 (or false, off, no); a message
    that already carries a cool-down is then driven as before, and its attempts and time stay out of
    its disposal counts.

    Known limits: Claude only; the first two overload retries are real attempts, so a message that
    already has 19 eligible attempts reaches the 20-attempt escalation with the first, and one with 98
    attempts and four eligible hours reaches the disposal with the second (the promise of no disposal
    starts with the cool-down); the 529 and plain-429 cases in the tests are made up, because no real
    sample exists.

    Technical detail: new fields in the message's attempt record (added only: park_kind,
    cooldown_step, soft_run, park_rev, park_detail), the health reason provider_wait_parked
    with an optional closed reason_detail, and the additive keys kind, next_try_epoch and
    park_rev in the park view and in status --json, and kind and next_try_epoch (not park_rev)
    in the supervisor row and the doctor data (older records have none and read as a usage limit). The version-1 marker file is unchanged and a
    cool-down writes none. The next try is the record's wake_epoch, written by one function that
    validates the final time.

Fixed

  • Slow budget-reader startup no longer looks like a busy ledger. Before,
    starting Python used up the same short deadline as reading the figures,
    which could hide valid figures or mislabel a damaged ledger on a loaded
    machine. The helper now gets ten seconds to start, then a separate 150 ms
    read deadline. A failed startup reports unavailable, with no figures.
    Nothing needs configuring. Technical details: budget.py and
    docs/BUDGET-FEED.md; tests cover deliberately delayed startup and cleanup.

  • The dashboard server no longer calls slightly old data an error (#361). The server keeps a
    background picture of the team's messages. When that picture was more than 15 seconds old, it
    answered /api/state with the error "snapshot stale" instead of the data, even though nothing had
    failed and a rebuild was simply still running. A script reading /api/state could not tell
    "rebuilding" from "broken", and the new console (/v2) showed "Can't read this team".

    What you will notice: before this, old data during a rebuild came back as an error and no data.
    Now it comes back as data, with a new freshness entry on each team: snapshot_age_s (how old
    the data is), stale (older than 15 seconds), rebuilding (a rebuild is running) and
    scan_error (only for a real failure - one with no message text still reports its type, such as
    "MemoryError" - not for a routine retry after a concurrent write or a
    requested rebuild). The classic page shows a banner from freshness (its words follow the facts:
    "Updating…" only when the server says a refresh is running, an out-of-date warning from the age,
    failure words from scan_error; when the server could not say whether a refresh runs, it shows
    "Showing last known data" with the age and the failure), and the new console (/v2) greys the team under an "old messages" or "last
    scan failed" banner; neither shows a green verdict while it shows. The data and its age always
    come from the same snapshot. Real failures are still errors: a config change, no picture yet,
    and a failed scan once the data is also more than 15 seconds old (named by its real cause, no
    longer "snapshot stale"). The board's coverage keeps its 15-second rule.

    What you need to do: nothing. A script that detected old data through the "snapshot stale"
    error should read freshness.stale instead.

    Technical details: SnapshotService.freshness() in src/agenttalk/envelope_snapshot.py;
    active() no longer raises "snapshot stale"; _root_state in src/agenttalk/web.py adds the
    freshness entry to each root (from one snapshot, one lock: active_with_freshness); the
    classic console.js reads it in keepLastGoodRoots and keptRootNote; console2-model.js
    reads it in freshness() (state old).

  • The classic dashboard no longer replaces the whole page with a red "Degraded" message
    while it is only refreshing, and it asks for new data less often.
    The dashboard keeps a
    picture of the team's messages and rebuilds it every few seconds. On a large message store a
    rebuild can take about as long as the picture is allowed to be old, so now and then the server
    answered "snapshot stale" and the page threw away everything on screen to show that message.
    It looked like a fault when nothing was wrong, and it hid the data you were reading.

    What you will notice: before this, a red "Degraded: snapshot stale" box replaced the page every
    few seconds on a big store. Now, when an answer comes back with an error and the page already
    has good data for that team, the page keeps showing that data. A banner on top says "Updating...
    showing data from UTC" and gives the server's message in brackets. If that goes on for
    more than a minute, the banner turns into a warning ("The data is out of date and not
    refreshing"); the data still stays on screen. The top bar never says "Healthy" while data is
    being kept this way. If there is no earlier good data (for example right after you open the
    page), you still see the "Degraded" message as before. The page now asks for new data every 10
    seconds instead of every 2, and the top bar has a Refresh live data button that fetches the latest
    team data on demand, including the lists of the view you are looking at (it only reads; it
    changes nothing). It does not refresh the Archived list in Sessions.

    What you need to do: nothing.

    Technical details: client only, in src/agenttalk/web_static/console.js and console.css.
    keepLastGoodRoots remembers each root's last answer without errors and, when the next answer
    for that root has errors, substitutes it (marked _keptErrors and _keptAt); every error keeps
    the data, and the banner text never depends on the error's wording. POLL_MS is now 10000, so
    ATTENTION_STALE_MS and STATE_STALE_MS (4 x POLL_MS) are 40 s. The server still answers
    "snapshot stale" after 15 s; reporting freshness as data is a separate follow-up. Issue #359.