Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,81 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.2.0] - 2026-05-24

### Added

- Added a queryable subagent task tracker so callers can observe delegated
child runs by `task_id` instead of scanning `run_events()`. The tracker is
a materialized view over the existing `SubagentStart` / `SubagentProgress`
/ `SubagentEnd` event 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 in `running` state.
- Added emission of `SubagentProgress` events 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) and `status = "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::Cancelled` and `AgentSession::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 late `SubagentEnd` from a
cancelled child does not downgrade the terminal status — it stays
`Cancelled`.
- Added `SubagentTaskSnapshot` carrying `task_id`, `parent_session_id`,
`child_session_id`, `agent`, `description`, `status`, `started_ms`,
`updated_ms`, optional `finished_ms` / `output` / `success`, and a
`progress` log. The Cancellation path also propagates a real cancellation
token into the child loop via `AgentLoop::execute_with_session`, so the
signal honors existing LLM-streaming yield points.
- Added `InMemorySubagentTaskTracker` and `SubagentProgressEntry` to the
public crate-root re-exports of `a3s-code-core` alongside the existing
`SubagentStatus` / `SubagentTaskSnapshot` types.

### Changed

- Marked `SubagentStatus` `#[non_exhaustive]` so future variants can be added
without a major version bump.
- Reshaped the Node SDK type layout to survive `napi-rs` regeneration. The
build now writes generated declarations to `generated.d.ts`; hand-authored
types that mirror JSON wire shapes (`ToolErrorKind`, `VerificationStatus`,
`VerificationCheck`, `VerificationReport`, `ToolArtifact`) now live in
`extra-types.d.ts`; the published `index.d.ts` is a small hand-authored
aggregator that re-exports both. The `types` field in `package.json` still
points at `index.d.ts`, so consumer imports are unchanged. A new
`npm run test:types` script type-checks the aggregator to guard against
future regressions.

### Fixed

- Fixed `TaskExecutor::execute` and `execute_background` so the emitted
`SubagentStart` carries the real parent session id (previously
`String::new()`), and `execute_background` returns the same `task_id`
that appears in lifecycle events (previously a throwaway id). The
background path also pre-emits `SubagentStart` synchronously so callers
that query the tracker immediately after scheduling do not race the
spawned task.

### Breaking

- `TaskExecutor::execute`, `execute_parallel`, and `execute_background` now
take an additional `parent_session_id: Option<&str>` (or
`Option<String>` for the background variant) so the emitted lifecycle
events can be correctly associated with the parent session. Direct
callers of `TaskExecutor` need to pass `None` (or the parent session id)
to keep current behavior.
- `register_task_with_mcp` gained a trailing
`subagent_tracker: Option<Arc<InMemorySubagentTaskTracker>>` parameter so
the session bootstrap path can share a single tracker Arc with the
executor and the live `AgentSession`. Pass `None` to opt out.

## [3.1.0] - 2026-05-23

### Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,29 @@ Intent -> Context -> Action -> Observation -> Verification -> Compaction

Everything else is an extension of that loop.

### What's new in 3.2

- **Subagent task tracker** — every delegated child run is now observable
through a queryable view fed by the existing `subagent_start` /
`subagent_progress` / `subagent_end` event stream. The new
`AgentSession::subagent_task(id)`, `subagent_tasks()`, and
`pending_subagent_tasks()` APIs (mirrored on Node and Python) let
dashboards introspect child runs without scanning `run_events()`.
- **Mid-task progress milestones** — the child loop forwarder now
synthesizes `SubagentProgress` events for `tool_completed` and
`turn_completed`, so callers see intermediate state instead of just
Start → End.
- **Cancel by task id** — `AgentSession::cancel_subagent_task(id)`
(and `session.cancelSubagentTask` / `session.cancel_subagent_task`
on the SDKs) interrupts an in-flight delegated run without
cancelling the parent. A late `SubagentEnd` from a cancelled child
does not downgrade the terminal status — it stays `Cancelled`.

Full migration notes are in [CHANGELOG.md](./CHANGELOG.md). The
`TaskExecutor` signature additions and the `SubagentStatus` variant
addition are the only breaking changes; `SubagentStatus` is now
`#[non_exhaustive]` so future variants are non-breaking.

### What's new in 3.0

- **Cloud-native workspace** — `S3WorkspaceBackend` with ETag
Expand Down Expand Up @@ -1115,6 +1138,20 @@ Core delegation primitives:
- `task` — run one focused delegated child run
- `parallel_task` — run independent delegated child runs concurrently

Once a child run is in flight, the parent session can observe and steer
it through the subagent task tracker:

| Operation | Rust | Node | Python |
|---|---|---|---|
| Look up a task by id | `session.subagent_task(id)` | `session.subagentTask(id)` | `session.subagent_task(id)` |
| List subagent tasks (this session) | `session.subagent_tasks()` | `session.subagentTasks()` | `session.subagent_tasks()` |
| List only in-flight subagent tasks | `session.pending_subagent_tasks()` | `session.pendingSubagentTasks()` | `session.pending_subagent_tasks()` |
| Observe mid-task milestones | `subagent_progress` in `run_events()` | same | same |
| Cancel an in-flight task | `session.cancel_subagent_task(id)` | `session.cancelSubagentTask(id)` | `session.cancel_subagent_task(id)` |

The tracker is a materialized view over the existing event stream; the
stream remains the authoritative record.

Built-in subagents are available through these primitives and through automatic
delegation:

Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "a3s-code-core"
version = "3.1.0"
version = "3.2.0"
edition = "2021"
authors = ["A3S Lab Team"]
license = "MIT"
Expand Down
1 change: 1 addition & 0 deletions core/src/subagent_task_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use tokio_util::sync::CancellationToken;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum SubagentStatus {
Running,
Completed,
Expand Down
4 changes: 2 additions & 2 deletions sdk/node/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "a3s-code-node"
version = "3.1.0"
version = "3.2.0"
edition = "2021"
authors = ["A3S Lab Team"]
license = "MIT"
Expand All @@ -11,7 +11,7 @@ description = "A3S Code Node.js bindings - Native addon via napi-rs"
crate-type = ["cdylib"]

[dependencies]
a3s-code-core = { version = "3.1.0", path = "../../core", features = ["ahp", "s3"] }
a3s-code-core = { version = "3.2.0", path = "../../core", features = ["ahp", "s3"] }
napi = { version = "2", features = ["async", "napi6", "serde-json"] }
napi-derive = "2"
tokio = { version = "1.35", features = ["full"] }
Expand Down
14 changes: 7 additions & 7 deletions sdk/node/examples/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions sdk/node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions sdk/node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@a3s-lab/code",
"version": "3.1.0",
"version": "3.2.0",
"description": "A3S Code - Native Node.js bindings for the coding-agent runtime",
"main": "index.js",
"types": "index.d.ts",
Expand Down Expand Up @@ -43,11 +43,11 @@
"test:helpers": "node test-helpers.mjs"
},
"optionalDependencies": {
"@a3s-lab/code-darwin-arm64": "3.1.0",
"@a3s-lab/code-linux-x64-gnu": "3.1.0",
"@a3s-lab/code-linux-x64-musl": "3.1.0",
"@a3s-lab/code-linux-arm64-gnu": "3.1.0",
"@a3s-lab/code-linux-arm64-musl": "3.1.0",
"@a3s-lab/code-win32-x64-msvc": "3.1.0"
"@a3s-lab/code-darwin-arm64": "3.2.0",
"@a3s-lab/code-linux-x64-gnu": "3.2.0",
"@a3s-lab/code-linux-x64-musl": "3.2.0",
"@a3s-lab/code-linux-arm64-gnu": "3.2.0",
"@a3s-lab/code-linux-arm64-musl": "3.2.0",
"@a3s-lab/code-win32-x64-msvc": "3.2.0"
}
}
4 changes: 2 additions & 2 deletions sdk/python/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "a3s-code-py"
version = "3.1.0"
version = "3.2.0"
edition = "2021"
authors = ["A3S Lab Team"]
license = "MIT"
Expand All @@ -12,7 +12,7 @@ name = "a3s_code"
crate-type = ["cdylib"]

[dependencies]
a3s-code-core = { version = "3.1.0", path = "../../core", features = ["ahp", "s3"] }
a3s-code-core = { version = "3.2.0", path = "../../core", features = ["ahp", "s3"] }
pyo3 = "0.23"
tokio = { version = "1.35", features = ["full"] }
serde_json = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion sdk/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "maturin"

[project]
name = "a3s-code"
version = "3.1.0"
version = "3.2.0"
description = "A3S Code - Native Python bindings for the coding-agent runtime"
readme = "README.md"
license = {text = "MIT"}
Expand Down
Loading