All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Cluster-grade runtime: everything needed for a host platform (e.g. 书安OS)
to run long-lived agent sessions across many nodes — graceful shutdown,
multi-tenant identity, cost governance, deterministic replay, crash-tolerant
runs, and bounded in-memory state — plus an adversarial-review hardening
pass. All additions are backward compatible (new methods, new optional
fields, new SessionStore trait methods with default no-op impls).
- Session / Agent lifecycle control.
AgentSession::close()is now a full graceful stop: flipsis_closed(furthersend/streamfast-fail withCodeError::SessionClosed), cancels the active run, all in-flight delegated subagent tasks, and pending HITL confirmations.AgentSession::is_closed()accessor.- Agent-side session registry:
Agent::list_sessions(),close_session(id),close()(also disconnects global MCP), andis_closed(). Sessions are tracked byWeakref and pruned lazily. - Session-level
CancellationTokenparent: every run derives its token viachild_token(), soclose()cascades to all in-flight work.AgentSession::session_cancel_token()exposes it for embedders.
- Host-provided identity labels —
tenant_id,principal,agent_template_id,correlation_idonSessionOptions(builder methods + accessors), persisted inSessionData, restored on resume. Framework treats them as opaque; the host drives multi-tenant aggregation / billing / tracing. Exposed on both SDKs. BudgetGuardcost/quota contract (budgetmodule) — host-suppliedcheck_before_llm/record_after_llm/check_before_tool, consulted at the LLM call site.Denyaborts withCodeError::BudgetExhausted;SoftLimitemits an event and proceeds. SDK bridges: a Python class (opts.budget_guard) and Nodesession.setBudgetGuard({...}). The Node bridge fails closed (timeout / unreadable return → deny).HostEnv(IdGenerator + Clock) injection (host_envmodule) — replace the default UUID + wall-clock pair for deterministic replay of a run on another node.SequentialIdGenerator/FixedClockhelpers.- Loop checkpoints + run resumption (
loop_checkpointmodule) — the agent loop persists aLoopCheckpointafter each completed tool round (when aSessionStoreis configured);AgentSession::resume_run(run_id)replays from the last boundary on any node sharing the store, continuing cumulative token/tool-call accounting.SessionStoregainssave/load/delete_loop_checkpoint; file writes are crash-atomic. SessionRetentionLimits(retentionmodule) — optional FIFO caps on the in-memory run store (runs + per-run events), trace sink, and terminal subagent task snapshots, so long-running sessions don't grow unbounded. Exposed on both SDKs. Default is unbounded (no behavior change).- MCP idle disconnect —
McpManager::disconnect_idle(threshold_ms)andAgent::disconnect_idle_mcp(...)(both SDKs) reap quiet MCP servers (releasing FDs / background workers) while keeping their config for on-demand reconnect. - Cluster
AgentEventvariants —BudgetThresholdHit,PassivationRequested,PeerInvocation: platform-level events a host emits viaHookExecutorso in-session code can react uniformly. SessionStorenow persists the subagent task tracker across save/resume (save/load_subagent_tasks), so a migrated session keeps a queryable history of its delegated child runs.- New errors:
CodeError::SessionClosed,CodeError::BudgetExhausted.
resume_runcontinues cumulative metrics (total_usage,tool_calls_count) from the checkpoint instead of restarting at zero.- Run-store and subagent-tracker FIFO eviction now hold their parallel maps under a single canonical lock order, so eviction is atomic with respect to concurrent record/cancel (no transient map inconsistency).
- Loop checkpoint leak: checkpoints were written after every tool round but never deleted — unbounded disk/memory growth on every completed run. They are now removed when a run reaches a terminal state in-process; only a true crash leaves one for resume.
event_countcorruption: restoring a session whose per-run event buffer had been trimmed reset the cumulativeevent_countto the trimmed length. The persisted cumulative count is now preserved.- Node
BudgetGuardfail-open: a hung or slow guard silently allowed the LLM call (disabling enforcement). It now fails closed (deny) on timeout and on an unreadable return. - MCP timestamp leak:
touch()-without-connect orphan timestamps are now purged bydisconnect_idle. - Session registry dangling
Weakentries are pruned onAgent::close().
- Node
BudgetGuardcallbacks must not throw — due to a napi-rs constraint a thrown exception aborts the host process at return-value conversion. Wrap guard logic in try/catch and return a decision. Hangs are handled safely (fail-closed timeout). The PythonBudgetGuardcatches exceptions and is unaffected.
- Python SDK: small pure-Python bootstrap shim published to PyPI as
a3s-code. On firstimport a3s_codeit downloads the matching native wheel for the current interpreter/platform from this repo's GitHub Releases, verifies the wheel's sha256 against the release manifest, extracts the compiled_nativeextension into~/.cache/a3s-code/<version>/, and registers it assys.modules["a3s_code._native"]. Subsequent imports use the cache. Source undersdk/python-bootstrap/.- Environment knobs:
A3S_CODE_CACHE_DIR,A3S_CODE_RELEASES_BASE_URL,A3S_CODE_SKIP_HASH_CHECK. - 15 unit tests + 1 live download test gated on
A3S_CODE_BOOTSTRAP_LIVE=1. - New workflow
publish-python-bootstrap.yml, wired afterpublish-pythoninrelease.yml.
- Environment knobs:
scripts/check_release_versions.shnow also validates the bootstrap package version and the runtime__version__literal.release.shnow bumps the bootstrap version in lockstep with the core release.
pip install a3s-codeworks again from v3.2.1, restored after v3.2.0 could only push a single wheel to PyPI under the quota cap.
- Added a queryable subagent task tracker so callers can observe delegated
child runs by
task_idinstead of scanningrun_events(). The tracker is a materialized view over the existingSubagentStart/SubagentProgress/SubagentEndevent stream — the stream remains the authoritative record. - Added three new APIs on
AgentSession(and mirrored bindings on the Node and Python SDKs):subagent_task(task_id)— look up a task snapshot by id.subagent_tasks()— list every delegated subagent task observed in this session, oldest first.pending_subagent_tasks()— list only tasks still inrunningstate.
- Added emission of
SubagentProgressevents from the child loop forwarder. Two milestones are surfaced today:status = "tool_completed"after each child tool ends (metadata: tool, exit_code, output_bytes, optional error_kind) andstatus = "turn_completed"after each child LLM turn (metadata: turn, prompt/completion/total tokens). Noisy events (TextDelta, ToolStart, ToolOutputDelta, nested subagent events) are intentionally not translated; consumers needing token-level streaming should subscribe to the raw event stream directly. - Added
SubagentStatus::CancelledandAgentSession::cancel_subagent_task(id)for interrupting in-flight delegated child runs without cancelling the parent run. Bindings on both SDKs (session.cancelSubagentTask(taskId)/session.cancel_subagent_task(task_id)). A lateSubagentEndfrom a cancelled child does not downgrade the terminal status — it staysCancelled. - Added
SubagentTaskSnapshotcarryingtask_id,parent_session_id,child_session_id,agent,description,status,started_ms,updated_ms, optionalfinished_ms/output/success, and aprogresslog. The Cancellation path also propagates a real cancellation token into the child loop viaAgentLoop::execute_with_session, so the signal honors existing LLM-streaming yield points. - Added
InMemorySubagentTaskTrackerandSubagentProgressEntryto the public crate-root re-exports ofa3s-code-corealongside the existingSubagentStatus/SubagentTaskSnapshottypes.
- Marked
SubagentStatus#[non_exhaustive]so future variants can be added without a major version bump. - Reshaped the Node SDK type layout to survive
napi-rsregeneration. The build now writes generated declarations togenerated.d.ts; hand-authored types that mirror JSON wire shapes (ToolErrorKind,VerificationStatus,VerificationCheck,VerificationReport,ToolArtifact) now live inextra-types.d.ts; the publishedindex.d.tsis a small hand-authored aggregator that re-exports both. Thetypesfield inpackage.jsonstill points atindex.d.ts, so consumer imports are unchanged. A newnpm run test:typesscript type-checks the aggregator to guard against future regressions.
- Fixed
TaskExecutor::executeandexecute_backgroundso the emittedSubagentStartcarries the real parent session id (previouslyString::new()), andexecute_backgroundreturns the sametask_idthat appears in lifecycle events (previously a throwaway id). The background path also pre-emitsSubagentStartsynchronously so callers that query the tracker immediately after scheduling do not race the spawned task.
- The Python SDK no longer ships native wheels to PyPI. The project grew past PyPI's default 10 GB per-project quota, and binary wheels for the full Rust × CPython × platform matrix consume that budget fast. From v3.2.0 onwards the canonical wheel host is GitHub Releases — see README for the install command. Versions up to 3.1.0 remain installable from PyPI for backward compatibility.
TaskExecutor::execute,execute_parallel, andexecute_backgroundnow take an additionalparent_session_id: Option<&str>(orOption<String>for the background variant) so the emitted lifecycle events can be correctly associated with the parent session. Direct callers ofTaskExecutorneed to passNone(or the parent session id) to keep current behavior.register_task_with_mcpgained a trailingsubagent_tracker: Option<Arc<InMemorySubagentTaskTracker>>parameter so the session bootstrap path can share a single tracker Arc with the executor and the liveAgentSession. PassNoneto opt out.
- Added Claude Code-style automatic subagent delegation. When a request matches
multiple independent specialists, the runtime can pre-run those child agents
through one bounded
parallel_taskcall and feed the gathered context back into the main turn. - Added
auto_delegationconfiguration and session overrides, including the globalauto_parallelkill switch. Settingauto_parallel = falsedisables automatic parallel child-agent fan-out while keeping manualparallel_taskavailable. - Added
max_parallel_tasksas the shared sibling fan-out limit forparallel_task, delegated plan waves, and safe parallel write batches. - Added a reusable ordered parallel executor so concurrent child results remain deterministic and individual task failures are isolated.
- Added native
.a3s/agentsand~/.a3s/agentssubagent discovery with recursive loading..claude/agentsremains a compatibility source, but.a3s/agentswins when the same agent name appears in both locations. - Added Claude-style markdown agent compatibility for
tools,allowedTools, anddisallowedToolsfrontmatter.toolsbehaves as an allowlist anddisallowedToolsis a denylist that takes precedence. - Added direct worker/subagent APIs across Rust, Node.js, and Python:
WorkerAgentSpec,AgentDefinition,session_for_worker, live worker registration, andtask/parallel_taskhelpers. - Added real-provider smoke coverage for automatic parallel delegation and
built-in subagent execution using
.a3s/config.acl.
- Aligned built-in subagent names and aliases with Claude Code conventions:
general-purposealiases togeneral;verify/verifieralias toverification;code-review/revieweralias toreview. - Tightened built-in subagent permission boundaries. Read-only and review-style
agents now default-deny undeclared tools, and all built-ins deny recursive
task/parallel_taskdelegation to prevent unbounded nesting. - Collapsed independent delegated plan waves into a single
parallel_taskoperation where possible, rather than launching serial siblingtaskcalls. - Updated Node and Python SDK documentation to prefer the single delegation
surface backed by the core
taskandparallel_tasktools.
- Fixed release helper version checks so they no longer reference the removed
cli/package. - Fixed explicit subagent trigger parsing so normal phrases such as "use the
plan" are not mistaken for a
plansubagent request.
- New public
ToolErrorKindenum (#[non_exhaustive], JSON-tagged on thetypediscriminator) carries structured tool failure reasons from the Rust core all the way to SDK callers without losing the type. Six variants:version_conflict,remote_git_conflict,not_found,invalid_argument,unsupported,timeout. - New optional
error_kindfield onToolOutput,ToolResult, andToolCallResult, plus a matching field onAgentEvent::ToolEndfor streaming consumers. - Built-in
editandpatchtools populateerror_kindviaToolErrorKind::from_workspace_errorwhenever aWorkspaceErrorvariant maps to a typed kind. The human-readableoutput/contentmessage is unchanged so the model still gets the retry hint; SDK callers now have a programmatic discriminator next to it. - Node SDK: new
errorKindJsonfield onToolResultandAgentEvent(JSON-encodedToolErrorKind) plus a newToolErrorKindTypeScript discriminated-union type inindex.d.ts. - Python SDK: new
error_kind_json(raw) anderror_kind(parsed dict) properties onToolResultandAgentEvent.
This closes the v3.0 typed-error gap: until this commit the typed
WorkspaceError enum on the Rust trait surface was effectively
re-stringified at the SDK boundary, forcing JS/Python callers to
regex-match the output to detect e.g. concurrent-modification
conflicts. They now switch / match on error_kind.type instead.
WorkspaceFileSystemandWorkspaceFileSystemExttrait methods now returnWorkspaceResult<T>instead ofanyhow::Result<T>. The new result type wraps the typedWorkspaceErrorenum (#[non_exhaustive]) with structured variants forNotFound,VersionConflict,RemoteGitConflict,InvalidArgument,Timeout,Unsupported, and aBackend(anyhow::Error)catch-all. Callers that used?to lift errors intoanyhow::Resultkeep working unchanged thanks to the blanketFrom<WorkspaceError> for anyhow::Errorimpl; callers that previously diderr.downcast_ref::<WorkspaceVersionConflict>()nowmatchon the typed variant directly:// before: if e.downcast_ref::<WorkspaceVersionConflict>().is_some() { ... } // after: if matches!(e, WorkspaceError::VersionConflict(_)) { ... }
WorkspaceServices::read_for_edit,write_for_edit, and the genericrun_with_timeout(now polymorphic in the error type) follow the same shape. The other 5 traits (WorkspaceCommandRunner,WorkspaceSearch,WorkspaceGit,WorkspaceGitStashProvider,WorkspaceGitWorktreeProvider) still returnanyhow::Result— their migration toWorkspaceResultwill be additive (non-breaking) in a future v3.x release.
- Added
S3WorkspaceBackend— an S3-compatible workspace backend that lets built-in file tools (read,write,edit,patch,ls) operate directly against any S3-compatible endpoint (AWS S3, MinIO, RustFS, R2, Backblaze B2, ...). Gated behind the news3Cargo feature. - Added
S3BackendConfigbuilder for configuring endpoint, region, static or session-token credentials, force-path-style, request timeout, and bucket prefix. - Added
WorkspaceServices::s3()factory andWorkspaceServices::from_s3_backend()helper. The factory installs a 60s default per-operation timeout and declinesbash,git,grep, andglobcapabilities — capability gating automatically hides those tools from the model so it cannot call operations the backend cannot service. - Exposed
S3WorkspaceBackendin the Node and Python SDKs alongsideLocalWorkspaceBackend. Configuration uses the same option surface (workspaceBackend/workspace_backend). S3WorkspaceBackend::read_textnow enforces a configurable size ceiling (S3BackendConfig::max_read_bytes, default 10 MiB) by inspectingContent-Lengthon theGetObjectresponse before consuming the body. Oversized objects are rejected with a clear error and never buffered into memory. Responses without aContent-Lengthheader are refused rather than risking OOM.- Added optional
WorkspaceFileSystemExttrait for backends that expose compare-and-swap writes, plus aWorkspaceVersionConflicterror type.S3WorkspaceBackendimplements it via ETag +If-MatchonPutObject. Theeditandpatchtools now capture the ETag during the read and reject the write on version mismatch (HTTP 412), surfacing a typed "Concurrent modification detected" error so the model can re-read and retry instead of silently clobbering a concurrent writer.WorkspaceServices::read_for_editandwrite_for_editare the new helpers tools should use for any read-modify-write cycle; backends without versioning (e.g. local) transparently fall through to plainread_text/write_text. S3WorkspaceBackendnow implementsWorkspaceSearch(degradedgrep/globviaLIST+GET+ regex). Off by default; opt in viaS3BackendConfig::enable_search(true). Hard ceilings on objects scanned per call (max_objects_scanned, default 500) and per-object body size forgrep(max_grep_bytes_per_object, default 1 MiB) bound the API cost. Hitting either ceiling setsWorkspaceGrepResult::truncated = true. Glob patterns follow the local backend's recursion convention:*.rsmatches the immediate level,**/*.rsrecurses.S3WorkspaceBackend::grepnow downloads candidate objects in parallel viafutures::stream::buffer_unordered. Concurrency defaults to 8 and is configurable viaS3BackendConfig::search_concurrency(also exposed on both SDKs). Output ordering remains deterministic — results are sorted by workspace path before assembly — so callers see the same layout regardless of S3 response timing.
- Internal
workspace::conformancemodule (test-only) codifies the behavioural invariants every backend implementingWorkspaceFileSystem(and optionallyWorkspaceFileSystemExt) must satisfy. Two public entry points,assert_filesystem_conformanceandassert_filesystem_ext_conformance, are run againstLocalWorkspaceBackendand a newInMemoryFileSystemreference backend so the contract is exercised both over real I/O and an ideal HashMap-backed implementation. Future backends (GCS, container, browser) gain a regression suite for free — when the conformance set grows after a production incident, every backend running it picks up the new test automatically.
WorkspaceServices::with_remote_gitpreviously rebuilt the services throughWorkspaceServicesBuilder, which silently droppedlocal_root(and would silently drop any future field). The decorator now goes through a new internalwith_git_providerhelper that uses an explicit struct literal — adding a new field toWorkspaceServicesnow triggers a compile error in every decorator, forcing a deliberate decision.RemoteGitBackend::diffpreviously deserialised the entire response body before applyingmax_diff_bytes, so a misbehaving gitserver returning a multi-gigabyte JSON could exhaust client memory. The diff path now streams the body with a hard cap (max_diff_bytes * 4, floor 64 KiB), rejecting requests upfront whenContent-Lengthadvertises an oversized body and aborting the stream mid-flight when chunked encoding hides the size. The softmax_diff_bytesdisplay truncation is unchanged.
S3WorkspaceBackend::list_dirnow errors with "S3 path not found" when the LIST returns zero entries on a non-root path, matching the local backend's behaviour. Previously a missing prefix silently returnedOk(vec![]), masking typos. Paths that exist only as S3 zero-byte directory markers still returnOk(vec![]).- Every S3 API call (
GET,PUT,LIST) onS3WorkspaceBackendnow emits a structuredtracing::debug!event with fieldsop,bucket,target,bytes,outcome,duration_ms. Hosts can meter S3 cost by subscribing to these events without the backend taking a dependency on any metrics framework. - Node and Python SDKs now expose the workspace hardening options added
in this release. The Node
JsS3BackendConfigand PythonS3WorkspaceBackendconstructor acceptmaxReadBytes/max_read_bytes,searchEnabled/search_enabled,maxObjectsScanned/max_objects_scanned, andmaxGrepBytesPerObject/max_grep_bytes_per_object. A newRemoteGitBackendConfigclass (Python) /JsRemoteGitBackendConfigshape (Node) and a top-levelremoteGit/remote_gitsession option let SDK callers attachRemoteGitBackendon top of any workspace backend. PassingremoteGitwithoutworkspaceBackendraises a clear error. - Added
RemoteGitBackend— an HTTP/JSONWorkspaceGitclient that brings thegittool to non-local workspaces (S3 today; future container / DFS). ImplementsWorkspaceGitin full andWorkspaceGitStashProvider; deliberately omitsWorkspaceGitWorktreeProviderbecause worktrees do not map to a remote service. The protocol is specified inapps/docs/content/docs/en/code/rfcs/workspace-remote-git.mdx.- New types:
RemoteGitBackend,RemoteGitBackendConfig,RemoteGitConflict(anyhow-downcastable for recoverable 409 / 422 responses such asWORKING_TREE_DIRTYandBRANCH_EXISTS). - New factory:
WorkspaceServices::with_remote_git(config)on any existingArc<WorkspaceServices>to attach remote git on top of an S3 (or local) filesystem backend. - Client-side ceilings:
request_timeout(default 30 s),max_log_entries(default 200),max_diff_bytes(default 1 MiB). - Per-call
tracing::debug!event with fieldsop,repo_id,status,bytes,outcome,duration_ms, mirroring the S3 metering shape so a single subscriber meters both. - Authentication: bearer token (header
Authorization: Bearer <token>) or mTLS viaclient_cert_pem+client_key_pem(PKCS#8 PEM key for therustls-tlsbackend). Setting only one of the mTLS pair fails at construction.
- New types:
- Restructured
core/src/workspace.rsinto aworkspace/module withworkspace/mod.rs(abstract traits +WorkspaceServices),workspace/local.rs(LocalWorkspaceBackend), andworkspace/s3.rs(S3WorkspaceBackend). No behavioural change for existing callers.
- Added
WorkspaceServicescapability abstraction (core/src/workspace.rs) that lets the host supply file system, command runner, search, and Git providers behind the stable built-in tool contract. The defaultLocalWorkspaceBackendpreserves existing local-filesystem behavior, while DFS, browser, container, and remote backends can be assembled viaWorkspaceServicesBuilder. - Added
SessionOptions::with_workspace_backend()(aliaswith_workspace_services) so callers can opt-in to non-local workspaces without changing tool schemas. - Added capability-driven tool gating:
bash,grep,glob, andgitare only registered when the workspace backend declares the matching capability, preventing models from invoking tools the backend cannot service. - Added
Session::write_file,Session::ls,Session::edit_file, andSession::patch_filedirect-tool APIs in core, Node, and Python SDKs, alongside the existingread_file/bash/glob/grep. - Added
LocalWorkspaceBackendclass to the Node and Python SDKs as the explicit typed form of the default backend and the option surface for future remote/browser/DFS workspaces. - Added
workspace_servicestoChildRunContextso child runs inherit the parent's workspace backend. - Added 17 unit + integration tests covering virtual path resolution, capability downgrade, contract-level tool routing for files / search / bash / git through pluggable backends, and session-level direct-tool dispatch.
- Refactored built-in tools
read,write,edit,patch,ls,bash,grep,glob, andgitto route operations throughWorkspaceServicesinstead of hard-coded local filesystem calls. Local behavior is unchanged. - Centralized workspace-boundary path checks in
ToolContext::resolve_workspace_path, removing duplicated canonicalization logic fromToolExecutor::execute.
- Removed two
clippy::useless_conversionwarnings incore/tests/test_ahp_idle_with_llm.rssocargo clippy --all-targetsis clean.
- Updated
README.md, Node SDK README, and Python SDK README with workspace backend usage and the new direct-tool API surface.
- Added
ConfirmationInheritanceenum for controlling how child runs resolve Ask decisions:AutoApprove(default),DenyOnAsk, andInheritParent. - Added
confirmation_inheritancefield toWorkerAgentSpecin Node and Python SDKs, allowing fine-grained control over child run confirmation behavior. - Added
ChildRunContextfor explicit parent capability inheritance, ensuring child runs properly inherit permission checkers and confirmation policies. - Added comprehensive integration tests for task delegation with real LLM calls and mock LLM contract tests for permission and confirmation inheritance.
- Added SDK integration tests for
confirmation_inheritancein both Node and Python SDKs with.a3s/config.aclconfiguration support.
- Fixed task delegation to properly inherit permission checker from agent definition in child runs (Issue #28).
- Fixed child runs to respect parent's confirmation policy when using
InheritParentmode.
- Unified
AgentDefinition→AgentConfigconversion viaapply_to()method for consistent configuration application. - Refactored
ToolExecutorto remove redundantguard_policyfield, relying onPermissionCheckerfor all permission decisions.
- Updated Node and Python SDK READMEs with
confirmation_inheritanceexamples and usage guidance. - Updated English and Chinese documentation for teams and tasks with worker agent confirmation inheritance patterns.
- Added
generate_objectbuilt-in tool for structured JSON output with schema validation, automatic repair, and streaming partial objects. Works across all providers via tool-calling mode. - Added
llm::structuredmodule with four output modes (tool, prompt, strict, json), robust JSON extraction from dirty LLM output, partial JSON parser for streaming, and a built-in JSON Schema validator supportinganyOf/oneOf, nullable types,additionalProperties,pattern, and numeric ranges. - Added streaming partial object support:
generate_objectemitstool_output_deltaevents with progressively complete JSON snapshots. - Added comprehensive documentation: structured output example (EN/CN), contract review tutorial (EN/CN), and 7 additional core mechanism tutorials (PTC, streaming, session persistence, skills, MCP, security/HITL, hooks, memory).
- Fixed Shiki build error in docs site caused by unsupported
acllanguage identifier in code blocks (replaced withtext).
- Added compact, object-shaped SDK APIs for long-lived integrations:
send(...),run(...),stream(...),task(...),tasks(...),git(...),addMcp(...)/add_mcp(...),removeMcp(...)/remove_mcp(...), andmcps(). - Added live run/tool observability through active tool snapshots and richer run replay APIs across Rust, Node.js, and Python SDKs.
- Added a durable SDK API design contract under
manual/SDK_API_DESIGN.md. - Added Python SDK parity for worker agents, HITL confirmation policy/control, session-for-worker, live worker registration, and session close.
- Split the large agent and session API implementation files into focused runtime modules for maintainability.
- Made AHP the single harness/advisory/control plane with richer event context, heartbeat state, runtime state snapshots, and decision mapping.
- Updated docs and examples to prefer short SDK method names while retaining long compatibility aliases.
- Re-exported
ActiveToolSnapshotfrom the Rust core crate root.
- Removed the obsolete sidecar/copilot/BTW/strategize/BTE mechanism and related prompts, docs, configs, and examples. Background advice, context supplements, and PTC proposals now belong to the caller or AHP harness.
- Promoted A3S Code package metadata to
2.0.0across Rust core, Node.js SDK, and Python SDK. - Standardized runtime configuration on ACL (
.acl) and explicitenv(...)credential injection. - Reworked the public API surface around
Agent,AgentSession, and 2.0-compatible session/control-plane primitives.
- Release-blocking real-provider integration test for
.a3s/config.aclenvironment-variable injection. - No-network integration coverage, script dry-run support, and literal-config extraction for MiniMax ACL
env(...)resolution. - Release validation scripts for local core tests, AHP feature tests, version consistency, patch hygiene, and real-provider ACL smoke tests.
- Legacy HCL config artifacts and stale prompt tests that no longer match the 2.0 ACL runtime.
- Issue #25 Fix: The
web_searchtool now returns an error when unknown parameters are passed (e.g.,engineinstead ofengines). Previously, unknown parameters were silently ignored, causing confusion when users specified the wrong field name.
enginesparameter type changed fromstringtoarrayin schema to match actual API- Updated a3s-search integration to v1.0.0
-
Built-in Git Client: New
gittool with auto-install support for Windows, macOS, and Linux. Downloads official pre-built git binaries to~/.local/git/bin/when git is not available - no package manager required.Full git operations:
status,log,branch,checkout,diff,stash,remote,worktree -
Git Convenience Methods: Python SDK (
session.git(...)) and Node SDK (session.git(...)) convenience methods for git operations.
- Updated all system prompts to reference "A3S Code" instead of "Claude Code"
- Updated skill references to use
a3s-lab/code-skills
-
Document Parser: Removed
composite_document_parseranddocumentmodules and all related code. This feature was not fully implemented and has been removed to simplify the codebase. -
Agentic Search/Parse Tools: Removed
agentic_searchandagentic_parsebuilt-in tools. -
Git Worktree Tool: Replaced by the new unified
gittool withworktreesubcommand.
- Tool Count: Updated built-in tool count from 15 to 16 to reflect new git and box tools.
- Documentation: Updated all documentation to reflect new tool names and capabilities.
-
XLSB (Excel Binary) Support: Added calamine-based BIFF12 parsing for XLSB files with proper cell value extraction, supporting Float, Int, Bool, DateTime, DateTimeIso, and DurationIso types. Significantly improves table fidelity for .xlsb files.
-
HWPX Table Extraction: Added structured table extraction from Korean HWPX documents. Parses
tbl/tr/tcXML hierarchy and includesstructured_payloadfortables[]output. -
Vision OCR Provider: New OCR backend supporting OpenAI-compatible vision APIs for document OCR fallback.
document_parser { ocr { enabled = true model = "openai/gpt-4.1-mini" api_key = "sk-..." base_url = "https://api.openai.com/v1" # optional prompt = "Extract all text from this document..." max_images = 8 dpi = 144 } }
Provider priority: External provider > Vision API (if model+api_key configured) > Builtin tesseract
-
Tabular Query Intent Detection: Automatically detects when queries relate to tables (keywords: table, column, row, spreadsheet, excel, csv, cell, data, record, etc.) and boosts table line matches by +10 keyword hits plus 1.3x relevance multiplier.
-
Heading Inheritance Boost: When search matches appear under headings that also match the query, those matches receive a relevance boost (up to 1.3x). Looks backwards to find the closest preceding heading.
DocumentOcrConfigextended with new fields:provider: Option<String>- Backend selection ("vision" or "builtin")base_url: Option<String>- Custom API endpointapi_key: Option<String>- API authentication
- Added
calamine = "0.26"for XLSB parsing - Added
reqwest/blockingfeature for Vision API HTTP calls
- Test assertion:
paged_text_blocks_reflow_two_column_preserves_paragraph_breaks- Corrected expected string "Parser metadata now tracks OCR" vs "Parser metadata now tracks OCR backend"
-
Phase 1 structured result surfaces:
structured_payloadexposed inagentic_parseoutput and metadata- Table payloads in stable machine-readable form
- Page-level data in
agentic_parseoutput and metadata - Stable
tables[],pages[],elements[]outputs
-
Phase 2 PDF extraction improvements:
- lopdf position-aware text extraction
- Reduced dependence on weak text fallbacks
- Position-aware table detection
-
agentic_searchenhancements:- Chunk context consumption
- Tabular content consumption
- Page numbers and locators support
ParsedDocumentextended withtables: Vec<StructuredTable>andpages: Vec<PageInfo>
- Windows shell compatibility improvements
- Runtime session header support for OpenAI configs
- Cross-platform environment variable expansion in tests
- Enhanced agent config, document parser, LLM, tools, and SDKs
- Host shell environment propagation to tool commands
- Zhipu AI client (
ZhipuClientformerlyGlmClient) - Duplicate tool call circuit breaker
- Streaming fallback support
agentic_parseskill
- Session-local skill registries
- Tool schema hardening
- Slash command output restoration