Skip to content

Tags: evalstate/fast-agent

Tags

v0.10.49

Toggle v0.10.49's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Dev/0.10.49 (#1047)

* Release 0.10.49: fix provider failure accounting and record PTC dispatches

* Prepare 0.10.49 dependencies, Trackio and HF GLM-5.3 support

Refresh compatible provider SDKs and restore optional Trackio with CPU telemetry disabled by default. Add HF GLM-5.3 routes, preserve reasoning verbatim, isolate request kwargs, and refresh capability references.

Validated in a clean staged snapshot: 10055 unit tests passed, 6 skipped; format, lint, typecheck and all package builds passed.

* Tighten HF GLM routes, request isolation, and Trackio packaging

- Make raw reasoning replay an explicit HF route-profile flag (GLM-5.3 routes
  and GLM-5.2's preserved-thinking route) instead of a class/model check.
- Deep-copy request metadata before merging so provider request shaping never
  mutates caller state (native Z.ai previously leaked tool_stream/thinking).
- Normalize unsupported `medium` effort to `high` (was falling back to `max`).
- Point `zaiglm` at native GLM-5.3; add `zaiglm52` for GLM-5.2.
- Move the billable GLM-5.3 smoke to scripts/ and drop tests of the script.
- gepa extra depends on fast-agent-mcp[trackio] rather than duplicating it;
  Trackio install test no longer inspects SDK internals and has a timeout.
- Trim HF GLM-5.3 docs to user-facing behaviour.

* Default native Z.ai provider to GLM-5.3

* Promote PTC batching guidance into agent instructions

v0.10.48

Toggle v0.10.48's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(ptc): programmatic tool calling with /tools tool-surface view (#…

…1034)

* fix: make logger name/context keyword-only and fix printf-style logger call sites

* feat: programmatic tool calling (--ptc) proof of concept using pydantic-monty

Expose agent tools as typed async Python functions behind a single
execute_python tool. Model-written code runs in a persistent Monty REPL,
is type-checked against generated stubs before execution, and dispatches
nested calls through the normal McpAgent call_tool path.

Includes ptc settings, go --ptc flag, examples/ptc demo, tests and a
research/roadmap plan in plan/programmatic-tool-calling.md.

* fix(ptc): bound print capture, safe stub docstrings, preserve explicit nulls, reset sandbox on conversation clear

* fix(ptc): keep typo detection, exact optional parameter types, flattened unions

- Only add **kwargs for explicitly open schemas (additionalProperties true or a
  schema); an absent key is treated as closed so misspelled arguments fail the
  type check before any tool runs.
- Optional parameters keep their exact schema type with a '= ...' default, so
  explicit None is only accepted for nullable fields.
- Flatten nested union members, fixing duplicated '| None' in rendered stubs.
- Document that the print capture cap protects host memory, not model context.
- Plan: defer readable model-facing docstrings (repr rendering) as a follow-up.

* feat(ptc): show the PTC tool surface in /tools; harness tools, media and nested-call linking

/tools under programmatic tool calling
- Add ToolSurface (fast_agent/tools/tool_surface.py): every reachable tool with a
  ToolExposure (MODEL = definition sent to the model, PROGRAMMATIC = stub inside
  execute_python), rough ~token context estimates, and why a tool stays direct
  (declared by tool or matching ptc.direct_tools pattern). Extensible for search.
- McpAgent.tool_surface() reports exactly what the sandbox exposes; other agents
  fall back to all-MODEL via resolve_tool_surface().
- /tools groups "Sent to the model" vs "Callable from execute_python" (collapsed
  per source), warns about large stubs (>= ~500 tokens); /tools --all lists
  signatures; /tools <name> resolves tool or Python names and shows the stub.
- TUI, ACP and harness slash_command render from one ToolsListing; completion
  includes nested tools and --all.

Also includes in-progress PTC work: harness tool behaviour under PTC
(slash_command stays direct), attach_media/get_resource handling, nested call
linking and metadata, elicitation/callback fixes, evals and media example server.

* feat(ptc): freeform execute_python input for GPT-6

- ptc.tool_format: auto | json | freeform. auto uses the model database
  ptc_tool_format (freeform for GPT-6 Astra/Sol/Luna and 6.1 Sol; GPT-5.6 can opt in).
- Freeform sends execute_python as a Responses custom tool with a permissive Lark
  grammar, so the model writes raw Python with no JSON escaping. The source arrives as
  {"input": ...}; providers without custom tools fall back to the same JSON schema.
- execute() accepts `code` or `input`, so history from before a model switch still runs.
- Tool metadata marks the input as raw (code_format: raw), so the streaming preview
  renders freeform input as highlighted Python.
- /tools shows "freeform input" in the PTC settings line.

Tested live with codexresponses.gpt-6-astra: examples/ptc/evals.py 7/7 freeform and
7/7 JSON.

* fix(ptc): structured shell/process values, direct shell access, clearer syntax errors

- Shell calls from execute_python return {stdout, stderr, exit_code, status,
  process_id, truncated}; a non-zero exit is a value, not an exception, unless
  check=True. Model-facing text and display are unchanged.
- The process tool returns structured values to code: status/wait give the
  shell dict with stdout/stderr since the last read (managed and durable
  processes), stop gives {process_id, status}, list gives a list.
- Tools can declare a sandbox-facing input schema and description; the
  freeform shell is a keyword-argument function in code (timeout= works).
- A tool's program value now takes precedence over is_error; failed subagent
  runs no longer attach one, so they still raise.
- New expose="both": shell and process tools stay directly callable alongside
  execute_python for one-off commands and text with heredocs or source code.
- Syntax errors (including those surfaced by the type checker) are described
  with CPython's parser plus a nested triple-quote hint; code is never run.
- execute_python description matches pydantic-monty 1.2.0: modules, file
  access, rejected constructs; a test checks the module lists against Monty.
- Suggest running full CPython through a shell tool when one is available.

* feat(ptc): ptc.nested_tools to force code-only tools

shell and process declare expose="both", so under PTC they stay directly callable and
GPT-6 Luna mostly bypassed execute_python (tb21-luna-medium-ptc-flex-004: ~9% of calls
via code). There was no configuration way back to code-only.

- ptc.nested_tools: fnmatch patterns made callable only from code, overriding a tool's
  declared direct/both exposure. ["*"] gives a code-only run
  (env: PTC__NESTED_TOOLS='["*"]').
- Precedence: ptc.direct_tools > ptc.nested_tools > tool declaration.

* fix(ptc): shell and process are code-only under PTC again

a9994bc declared the shell and process tools expose="both", which kept them directly
callable next to execute_python and made PTC optional: in
tb21-luna-medium-ptc-flex-004, GPT-6 Luna made ~91% of calls directly.

- Shell and process tools declare expose="nested" again, so --ptc means tools are
  reached through code. Structured shell/process values (D1-D4 fixes) are unchanged.
- Direct access remains opt-in via ptc.direct_tools; ptc.nested_tools still forces
  code-only for other tools that declare direct access.
- The shell contract test now asserts the model sees only execute_python.

Verified live with codexresponses.gpt-6-luna and --shell: one top-level
execute_python call, with shell running inside it.

* fix(ptc): short, specific exception messages for failed nested calls

Benchmark run -005 had 0.7% of scripts abort with RuntimeErrors whose message was the
model-facing display text. Reproduced each category:

- check=True shell failures raised the display text ("[stderr] ... process_id:
  process-N ... exit code was 3"). They now raise "<fn>: command failed with exit code
  3" (or "command timed out" / "command terminated") plus stderr/stdout tails, like
  CalledProcessError.
- edit_file failures (and MCP tools with JSON error bodies) raised a raw JSON object.
  They now raise its message with the error code, e.g. "edit_file: old_string was not
  found ... [no_match]".
- Every nested-call exception is prefixed with the sandbox function name, and the
  redundant "Error:" prefix is dropped.

Tools can set a short sandbox-facing message with the new FAST_AGENT_PTC_ERROR result
meta key, parallel to FAST_AGENT_PTC_VALUE.

Already correct, so unchanged: a command killed by its own timeout= returns
{"status": "timed_out", "exit_code": None, ...}; invalid arguments, unknown process IDs
and missing files raise by design.

* feat(ptc): leaner code tool description, settle/asyncio prelude, /tools ptc

Token efficiency (gpt-6-astra, 9 simple jobs x 3 runs): PTC overhead vs off
drops from +58% to +29% overall; per-request fixed cost ~1.4k -> ~0.8k tokens.

- Shorten execute_python instructions (~795 -> ~500 tokens).
- Render output schemas as compact TypedDict-like shapes
  (`Returns: {id: str, tags?: list[str]}`, top-level field descriptions as
  comments) instead of JSON schema text (~440 -> ~100 tokens).
- Stub docstrings are escaped triple-quoted literals rather than repr().
- Sandbox prelude pre-imports asyncio and defines settle(aw) for
  allSettled-style gather.
- Structured results with non-text blocks use a
  {structured_content, content} envelope.
- `/tools ptc` (TUI and ACP) shows the code tool description verbatim,
  including full stubs; offered in completion when PTC is on.
- Update the PTC plan to match the code.

* fix(copilot): stream Responses SSE without the SDK accumulator

openai>=3.34 raises 'Lifecycle response identity changed.' when lifecycle
events carry differing response ids, which Copilot's SSE stream does.
Copilot SSE now iterates raw events from responses.create(stream=True),
sharing the wrapper previously private to OpenResponses. Bump openai to
3.37.0 (still enforces the check).

* Bump pydantic-monty to 1.3.0 and huggingface_hub to 2.3.0

* feat(ptc): sandbox file I/O via agent tools; call sandbox callables "functions"

Haiku 5.5 (low) on TB2.1 fell from 79% to 11% with PTC: it wrote plain
os/pathlib/open() code, hit PermissionError, then called sandbox-only
functions as direct tools and gave up.

- files.py: open(), pathlib and the os file functions are served by nested
  read_text_file / write_text_file / shell calls, with the same permissions,
  hooks and execution environment; writes are buffered per script.
- Wording: the sandbox callables are always "functions"; "tool" is kept for
  things the model can call directly. The description says the word once, in a
  sentence mapping "use the `x` tool" in other instructions to `await x(...)`.
  The shell notes name the real shell function (was hard-coded `shell`), and
  CPython guidance runs the script from code. The result header counts
  "calls", failures list "Calls that completed".
- Recovery hints: unsupported I/O errors name concrete awaited calls,
  un-awaited calls are flagged, and a direct call to a code-only function is
  answered with how to call it from execute_python.
- Plan updated and reconciled with the code.

* feat: integrate GPT-6.1 Terra across OpenAI, Codex and Copilot

* feat(ptc): fresh sandbox per run with a session-persisted store; fixes from TB2.1 runs

Benchmark analysis (Haiku 5.5 / Luna, TB2.1) found sandbox defects that cost
steps and trials; this addresses the ones in fast-agent.

State between runs
- Every execute_python run now gets a fresh Monty sandbox. Monty's REPL type
  checker pins each variable to the type of its first value and forgets names
  set by failed or unchecked runs (4.4% of Haiku's scripts were rejected for
  reassignment alone); a fresh sandbox per run removes that class of error.
- New store()/load()/stored() functions (ptc/store.py) carry plain data
  between runs as tagged JSON (bytes, tuples, sets, non-str keys, big ints,
  NaN), capped at 64 MB, cleared with the conversation.
- The store is saved beside the agent's history (ptc_store_<agent>.json,
  snapshot schema v6 with SessionAgentSnapshot.ptc_store_file), copied on fork
  and restored on resume after the transcript; a resume into an agent without
  PTC warns instead of dropping it.

Shell commands that outlive the foreground limit
- The script result lists commands still running at the end, with the wait
  call to use; check=True now waits for completion like subprocess.run and
  stops the command if the call is cancelled.

Sandbox file access
- Reads check the file size first (512 KB binary, 4 MB text) and fail with a
  clear "too large; use a shell command" error instead of base64-ing the whole
  file until the 30 s yield; internal file commands that still yield are
  stopped by process id rather than left running.
- The instructions say open() loads whole files (even read(n)/seek()) and that
  struct/int.from_bytes are unavailable.
- Buffered writes are committed early past 8 MB, bounding host memory.
- Renames follow rename(2) (no-op for the same file, replace a symlinked
  target, EISDIR/ENOTDIR/ENOTEMPTY) instead of pre-deleting the target and
  relying on mv.
- Paths are normalised with path_from_arg(); without a shell, relative paths
  resolve against the ACP session or agent directory instead of /.
- Internal file operations display as one line instead of their shell script
  and base64 output.

Smaller fixes
- map() passes type checking (missing from Monty's stubs).
- The "not awaited" note matches Monty's coroutine repr, not any printed
  "<coroutine " text.

* fix(ptc): save the store through HistoryAgent; keep symlinks renamed onto themselves

- Turn-end saves and checkpoints pass a HistoryAgent wrapper from
  save_session_history(), which did not expose ptc_store, so stored values were
  never written on the normal save path and were lost on resume. HistoryAgent now
  delegates ptc_store; the end-to-end store test saves through the hook.
- os.rename("link", "link") on a symlink removed the link: the same-file check
  skipped symlinks, so the target (also the source) was deleted before mv. The
  rename script now exits early when source and target are the same directory
  entry (same name in the same parent directory).

* build(ptc): pydantic-monty 1.4.0; document decimal and method decorators

- Bump pydantic-monty to 1.4.0 (lock changes only the three monty packages).
- decimal is now importable in the sandbox: listed in the instructions and
  reserved so a tool named `decimal` gets the `_tool` suffix.
- Instructions: plain function decorators and dataclass methods work in Monty;
  only method decorators (@staticmethod, @classmethod, @Property) do not.

1.4.0 drops each worker's type checker on session reset, so with a fresh
session per run every type-checked run rebuilds it (~12 ms vs ~2 ms on 1.3.0).
Monty's type-stub gaps (map, os.walk/scandir, open, OSError subclasses) and
REPL checker behaviour are unchanged, so the workarounds stay.

* fix(ptc): keep rename targets on failure, resolve relative shell cwd, fresh reads, spool truncation

- Rename: a target rename(2) would replace (symlink, empty directory) is moved
  aside and restored if moving the source fails, instead of being deleted first.
- Shell working directory: a relative cwd was joined onto the local executor's
  already-resolved directory (work/work), so every shell command failed for an
  agent with a relative cwd. Local shells now resolve it against the process
  directory, as the executor does. ShellRuntime.command_working_directory()
  gives the directory commands run in; the PTC sandbox uses it.
- Sandbox reads: writes, deletes, rmdir and renames drop what open() cached
  for the affected paths, so later reads see the new contents.
- Durable processes: output dropped past durable_output_max_bytes now marks
  the sandbox read as truncated.

* fix(deps): upgrade Pillow and suspend Trackio extra

* fix(ptc): require the shell value contract for file access; release finished dispatches; unique media handles

- Sandbox file access chose its shell by name, so ACP terminal `execute` or an
  MCP `remote__execute` could be picked although they return display text, not
  a ShellProgramValue: every file operation failed, including the size check
  before text reads. programmatic_shell_tool now declares a value contract in
  the tool's PTC options and only such shells serve file operations; without
  one, text goes through read_text_file/write_text_file.
- Nested dispatch tasks are tracked only while outstanding, so finished
  results are not held in host memory until the script ends.
- Media handles carry a per-store random prefix: a handle restored through
  store() and session resume can no longer resolve to media fetched later
  under the same number.

* test(acp): compare session schema version with SESSION_SNAPSHOT_SCHEMA_VERSION

The PTC store bumped the session snapshot schema to v6; the ACP session integration test pinned 5.

* fix(ptc): raise for stopped checked commands; bound the open() read-ahead cache

- check=True: a command stopped by another process call while the check waits
  returns terminated/cancelled without an error flag, so sandbox code got
  display text instead of the RuntimeError check promises. Unsuccessful checked
  statuses now mark the result as an error.
- open() read-ahead: Monty keeps no live handles, so close() never reaches the
  host and every opened-but-unread file stayed cached until the script ended,
  outside Monty's memory limit. The cache is capped at 16 MB, evicting the
  oldest entries; a read after eviction fetches the file again.

* fix(ptc): stat dangling symlinks as missing; NUL-delimit directory listings

- os.stat() on a dangling symlink raised IndexError: the existence check
  accepted the link and the size fallback printed an incomplete record. stat
  now follows the link as os.stat does (FileNotFoundError) and the fallback
  fails instead of printing a partial result.
- listdir/iterdir and walk/glob split find output on newlines, so a name like
  "one\ntwo" became separate (and unrelated) paths. Entries are now
  NUL-delimited (find -print0, NUL-terminated scan records).

* refactor(ptc): native local filesystem pass-through; reject non-local environments

Sandbox open()/pathlib/os now run directly against the local filesystem
instead of being routed through agent file/shell tools. Removes the tool
transport (SandboxFileTools, buffered writes, read-ahead cache, the
sandbox_file_operation display line and the shell value contract option).

- SandboxFilesystem is a Monty AbstractOS: read/write gated separately,
  serialized operations, regular files only (O_NONBLOCK), bounded reads
  and directory listings, no environment access.
- McpAgent validates the environment: PTC is local POSIX only; Docker,
  remote, ACP-owned and custom environments raise AgentConfigError until
  filesystem adapters exist.
- Docs/help/config describe PTC file access as experimental pass-through,
  not a filesystem sandbox.

v0.10.47

Toggle v0.10.47's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Release 0.10.47: dependency refresh (huggingface_hub 2, anthropic nat…

…ive OTel, fastmcp 4.1, duckdb 2, ty 0.0.90) (#1032)

* Update dependencies and adopt upstream improvements

- huggingface_hub 2.2 (httpx2 stack), trackio 0.43, tokenizers 0.23.3
- anthropic 1.17: drop OpenLLMetry AnthropicInstrumentor in favour of the
  SDK's native OpenTelemetry spans; fix base_url /v1 suffix stripping
- openai 3.35.1: public type_to_response_format_param import; typed
  Responses stream failure handling
- fastmcp-slim 4.1.3: release connection-scoped harness sessions when their
  MCP session ends (DELETE, idle timeout, crash)
- a2a-sdk 1.2.3: report unresolvable agent cards as AgentConfigError
- google-genai 2.32, pydantic 2.14.1, pydantic-settings 2.16.1,
  starlette 1.9, aiohttp 3.14.5, filelock 4.2.4, typer 0.27.3,
  opentelemetry exporter 1.45.1, textual-image 0.14.2
- duckdb 2.0: fix parquet row count; validate user SQL before execution
- privacy-gpu: onnxruntime-gpu>=1.27 targets CUDA 13
- drop beartype pin (now required by fastmcp-slim on 3.15)
- dev: ruff 0.17.1, ty 0.0.90, zensical 0.0.71, pre-commit 4.7.0

* Fix ty 0.0.90 override and contextmanager diagnostics

ty 0.0.87+ enables invalid-mutable-override and checks receiver attribute
overrides. Make AgentProtocol.context/instruction read-only properties, drop
the writable kind declaration from CommandBase, move service_tier onto
OpenAISettings, and annotate context managers with Generator/AsyncGenerator.

* Docs: use zensical exclude_docs, redirects and draft_docs

- exclude _generated snippet fragments and asset READMEs from the built site
  (replaces the meta plugin/.meta.yml search exclusion)
- replace moved-page stubs with redirect_maps entries
- keep the ledger prototype as a draft

* Release 0.10.47

* Lock patched pyjwt 2.15.1 and multidict 6.9.1 (Dependabot advisories)

v0.10.46

Toggle v0.10.46's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Release 0.10.46: Responses websocket close diagnostics (#1014)

* Responses websocket: diagnose streams that end without a completion event

When the server ends a websocket stream before `response.completed`, the error
only said `events_seen=N; last_frame=<240-char prefix>`. Against GitHub Copilot
the first frame is an untyped `{"headers": {...}}` frame whose experiment
assignment header alone exceeds 240 characters, so the preview never reached the
useful part, and a drop without a close frame reported no close details at all.
Observed in Deep-SWE runs: two frames, then the connection closed ~16 s after
the request, every attempt, with nothing to distinguish a provider close, an
intermediary reset or a policy cut.

Error message (console; not persisted by the failure event):
- names the closing condition, including `received_close=none` when the peer
  dropped the connection without a close frame, and `close_code=none`, plus
  `ws_exception=<type>`;
- `seconds_since_request` and `seconds_since_last_frame`;
- `frames=[...]`: the last five frames as event types, with Copilot header frames
  shown as header names plus `*request-id*` values that match a strict identifier
  pattern (for provider support requests); other header values are never shown.

Exception: `close_snapshot` (the persisted fields) and `last_frame`, the raw last
frame bounded to 16 KiB, for programmatic inspection only; never logged.

Persisted `Responses websocket attempt failed` event, schema bumped to v2:
`close_kind` (fixed vocabulary), `close_code` (int), `events_seen`,
`last_event_types` (allowlisted Responses event names; `headers`, `other`,
`untyped` otherwise), `seconds_since_request`, `seconds_since_last_frame`.
All null for failures that are not stream closes. No provider-controlled strings
are persisted; tests assert header values, request ids and unknown event names
stay out of the log.

No change to retry, reconnect or timeout behaviour.

* Release 0.10.46: Responses websocket close diagnostics

v0.10.45

Toggle v0.10.45's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Release 0.10.45: provider-native compaction (#1011)

* Release 0.10.45: provider-native compaction

Compaction now uses each provider's native mechanism where it is verified,
with fast-agent still owning policy (when to compact, what to keep, archiving).

- OpenAI provider-native checkpoints (on by default) for GPT models on
  responses, codexresponses and Copilot: a request ending in a
  compaction_trigger item replaces the compacted region with an opaque,
  encrypted checkpoint. Opt out per model with ?compaction=client or per
  route with native_compaction: false; compaction.strategy: client still
  forces fast-agent's summary everywhere.
- Copilot Claude models use Anthropic server-side threshold compaction
  in-request; harness auto-compaction stands aside for them.
- New model-string option compaction=native|client, validated per route.
- Astra effort is re-sent as a configuration_update after a checkpoint, on
  every route that replays checkpoints (including Copilot).
- Checkpoints record their producing route: Copilot checkpoints are only
  readable on Copilot and fail clearly elsewhere.
- Process-poll folding keeps messages that carry an in-band checkpoint.
- ATIF records the compaction strategy, embeds the compaction call and
  counts provider checkpoints; validate_atif accounts for embedded calls.
- Anthropic usage folds compaction iterations into billed totals and
  takes context size from the last sampling iteration.
- Codex Responses defaults Astra, GPT-6.1 Sol and Luna to high effort and
  serves GPT-6.1 Sol with a 500k window; Responses requests now send the
  model's default effort (as /model already displayed).
- Display: COMPACTING progress for the native call and streamed compaction
  events; provider checkpoints show their encrypted size and archive.
- Live smoke script scripts/openai_native_compaction_smoke.py and
  sanitized Codex compaction trace fixtures.

* Refresh CPD baseline for the compaction model-string field

ModelConfig and ModelQueryOverrides intentionally mirror each other's typed
fields (existing approved finding); adding compaction to both grows the same
duplication from 122 to 129 tokens.

* fix: preserve failed-run ATIF exports after compaction

* feat: show effective compaction mode in model status

* fix: extend stream idle defaults for high reasoning

* chore: keep concurrent compaction threshold work separate

* test: give ACP /model LLM stubs the compaction surface

The /model Compaction line reads compaction support and the effective
trigger; the integration stubs predated it (Integration (acp) failure).

* feat: xAI native compaction and per-model compaction triggers

xAI provider-native compaction (on by default for xai.*):
- Grok compacts through POST /responses/compact (xAI rejects
  compaction_trigger items) and replays the returned compaction item via the
  shared OpenAI-format replay channel; no instructions are sent, since later
  requests carry the system prompt.
- Checkpoints are route-bound both ways: xAI reads only xAI checkpoints and
  OpenAI routes reject xAI's, with a clear switch-back/restore message.
- xAI's compaction usage reports reasoning outside output_tokens (observed
  live); it is folded back in so usage validation and accounting hold.
- xai.native_compaction setting; ?compaction=native accepted for xai.
- Compaction calls are captured under FAST_AGENT_LLM_TRACE.
- xAI's compaction drops tool outputs by design; documented.

Per-model compaction triggers:
- New model-string option compact_at=<tokens|fraction> (190k, 1m, 0.7, 70%)
  for any provider. Precedence: compact_at, compaction.threshold, the
  model's default, then 0.85.
- ModelParameters/overlay metadata compaction_trigger_tokens; Grok 4.7
  defaults to 190,000 tokens to stay below its 200k long-context rate.
- compaction.threshold now defaults to unset; the setup template leaves it
  commented so model defaults apply.
- Triggers are compared in tokens (auto-compaction, post-compaction budget,
  in-request provider trigger); /model and /compact preview show both forms.

Tests use a local /responses/compact HTTP simulator over a sanitized live
capture; the native compaction smoke script gains --route xai.

* Refresh CPD baseline for the compact_at model-string field

* update docs

v0.10.44

Toggle v0.10.44's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Release 0.10.44 (#1009)

* feat: support Python 3.15

- Allow Python 3.15 (requires-python <3.16) for fast-agent-mcp,
  fast-agent-acp and hf-inference-acp.
- Require beartype>=0.23.0 (transitive via fastmcp -> py-key-value-aio);
  earlier releases import typing.no_type_check_decorator, removed in 3.15.
- Bump pydantic 2.13.5 -> 2.14.0 so pydantic-core ships cp315 wheels
  (2.46.5 has none, so 3.15 installs needed a Rust toolchain).
- Narrow the Anthropic message_stop replay adapter: pydantic 2.14 types
  TypeAdapter.validate_python, exposing an unchecked `.message` access.
- Keep the config encoding test simulating a non-UTF-8 locale under 3.15's
  default UTF-8 mode (PEP 686) by patching io.text_encoding.
- Run unit tests on Python 3.14 and 3.15 in CI.

* perf(cli): defer CLI startup imports with PEP 810 __lazy_modules__

On Python 3.15+, defer modules only used inside functions on the CLI
startup path (update check, display, importlib.metadata, connect_targets).
Earlier Python versions ignore __lazy_modules__.

`fast-agent --help`: ~149ms -> ~124ms; `fast-agent go --help`: ~173ms ->
~147ms (median of 25 runs, 3.15.0). A 3.15-only test guards that help
output does not load the deferred modules.

* refactor(cli): drop always-true Python 3.7 version check

* chore: prepare 0.10.44

* test(skills): run CLI subprocess with sys.executable instead of uv run

`uv run` from the repo root re-synced .venv to the lockfile mid-suite,
silently undoing any locally installed package overrides, and ran the
CLI on .venv's interpreter rather than the one under test.

v0.10.43

Toggle v0.10.43's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Release 0.10.43 (#999)

* chore(deps): bump MCP, Anthropic and OpenAI SDKs; prepare 0.10.43
* feat(sessions): skip sessions owned by another process
* feat(go): add --isolated one-shot runs
* feat(usage): record client-observed request timing on usage turns
* feat(plugins): pass the completed turn to post-user-turn plugins
* docs(benchmarks): add DeepSeek V4.1 Flash max 6h run and refresh ledger
* feat(ui): live context fill and smoothed tok/s in streaming header
* feat(models): add Claude Haiku 5.5
* feat(copilot): add Claude Haiku 5.5 route
* feat(plugins): plugin bundles and plugin update notices
* chore(models): list Haiku 5.5 with current Anthropic models in the picker
* docs(benchmarks): refresh benchmark data, ledger and pages
* Print keyring access notice before model picker draws

v0.10.42

Toggle v0.10.42's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: preserve observed ATIF accounting and prepare 0.10.42 (#995)

* fix: preserve observed ATIF accounting and prepare 0.10.42

* docs: clarify observed usage contributes to campaign totals

* docs: explain interrupted-stream accounting in plain language

v0.10.41

Toggle v0.10.41's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: support inline Copilot documents and prepare 0.10.41 (#993)

v0.10.40

Toggle v0.10.40's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fast-agent 0.10.40: GPT-6.1 Sol (responses, codexresponses, copilot),…

… openai 3.21.0 (#992)

* feat: add GPT-6.1 Sol on responses, codexresponses and copilot

- gpt-6.1-sol reuses the GPT-6 Sol layout (freeform shell, writer/editor pair,
  SSE+websocket, fast/flex tiers, Lite opt-in, route-specific long context)
  but, like Astra, only accepts low..max reasoning (none/minimal rejected)
- sol now targets codexresponses.gpt-6.1-sol; GPT-6 Sol stays available as sol6
- add gpt-6.1-sol / gpt61sol Responses aliases and the Copilot model
- live structured-output smoke on Copilot and Codex OAuth
- docs + regenerated reference tables

* chore: bump openai SDK 3.19.2 -> 3.21.0

- 3.21.0 adds the gpt-6.1-sol model identifier to the SDK types
- 3.20.0 retries raw TLS transport errors (ssl.SSLError / anyio.EndOfStream)
  as connection errors instead of surfacing them unretried

* fast-agent 0.10.40