Skip to content
Open
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
36 changes: 0 additions & 36 deletions .changeset/claude-rate-limit-handling.md

This file was deleted.

40 changes: 0 additions & 40 deletions .changeset/hold-task-for-background-work.md

This file was deleted.

7 changes: 0 additions & 7 deletions .changeset/prompt-timeout-disable.md

This file was deleted.

32 changes: 0 additions & 32 deletions .changeset/rate-limit-fail-task.md

This file was deleted.

33 changes: 0 additions & 33 deletions .changeset/session-ttl-disabled-by-default.md

This file was deleted.

8 changes: 8 additions & 0 deletions a2a-antigravity/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# a2a-antigravity

## 0.2.1

### Patch Changes

- Updated dependencies [f3c7062]
- Updated dependencies [41e2d82]
- @a2a-wrapper/core@2.1.0

## 0.2.0

### Minor Changes
Expand Down
4 changes: 2 additions & 2 deletions a2a-antigravity/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "a2a-antigravity",
"version": "0.2.0",
"version": "0.2.1",
"description": "A2A (Agent-to-Agent) protocol wrapper for Google Antigravity SDK. Exposes Antigravity through the shared HTTP/JSON-RPC/REST/SSE A2A surface using a private Python SDK bridge.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -59,7 +59,7 @@
},
"dependencies": {
"@a2a-js/sdk": "^1.0.0",
"@a2a-wrapper/core": "2.0.0",
"@a2a-wrapper/core": "2.1.0",
"express": "^4.18.2",
"uuid": "^9.0.0"
},
Expand Down
141 changes: 141 additions & 0 deletions a2a-claude/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,146 @@
# a2a-claude

## 0.4.0

### Minor Changes

- f3c7062: Handle Claude rate limit events instead of failing the turn generically.

Rate-limit signals were previously unrecognised: `rate_limit_event`,
`system/api_retry`, and assistant `rate_limit` errors all fell through to a
debug log, and the turn surfaced as `failed` with `"Error during execution."`

A rejection now ends the turn immediately with an `input-required` status naming
the limit type and reset time, plus structured metadata (`reason`,
`rateLimitType`, `resetsAt`, `resetsAtIso`, `utilization`, and `errorCode` /
`canPurchaseCredits` when the SDK reports them). The task stays non-terminal, so
the client continues the same conversation on the same task once the limit
resets. Configurable via `rateLimit.taskState` for clients that require a
terminal state.

This does not shorten the SDK's own retry behaviour: a `system/api_retry` is
deliberately treated as a warning that does not end the turn, so the SDK's
internal retries still run to exhaustion inside the same `timeouts.prompt`
window. The turn ends only once the SDK gives up and emits an assistant
`rate_limit` error. Those retries are at least visible now, as `rate_limit`
sideband events with `action: "retrying"` carrying the SDK's `attempt`,
`maxRetries`, and `delayMs`.

A rejection whose overage window is still open is treated as a warning rather
than a rejection, since the request may proceed on overage credits; if it does
not, the assistant `rate_limit` error still ends the turn. Limit details are
never fabricated — a limit type or reset time is inherited by a later signal
only from a snapshot that reported pressure, utilization is never inherited, and
a reset time that is not in the future is dropped.

Adds a `rate_limit` sideband event type to `@a2a-wrapper/core`, gated by
`features.emitRateLimitEvents`.

- 41e2d82: Hold the A2A Task open while Claude has background work in flight.

A Task used to reach a terminal state as soon as Claude's first turn ended —
even when that turn had just started a background process and said it was
waiting on the result. A2A gives an agent no way to open a new turn against a
terminal Task, so the follow-up report had nowhere to land.

The Task now stays in `working` for as long as Claude reports background work
running, and completes only once a turn ends with nothing left. Each turn
publishes its own `response` artifact and a non-final `working` status update
whose `metadata.backgroundTasks` lists what is still in flight. Chains of any
length work this way, as rounds of one Task rather than several Tasks.

Controlled by `features.holdTaskForBackgroundWork` (default `true`; set
`false` for the old complete-at-first-result behavior) and
`features.emitBackgroundTaskEvents` (default `true`), which publishes a new
`background_tasks` sideband event — added to `@a2a-wrapper/core` — each time
the live set changes.

Bumps `@anthropic-ai/claude-agent-sdk` from `0.3.202` to `0.3.245`. The
feature needs at least `0.3.235`, the first version to emit
`background_tasks_changed`.

Three changes apply even with `holdTaskForBackgroundWork` off:

- Queries now use streaming input rather than a string prompt. A string prompt
makes the SDK close the CLI subprocess's stdin on the first result, which
ends the process before a second round is possible. This is not switchable.
- `agent_started` / `agent_finished` are emitted once per A2A Task rather than
once per SDK turn.
- A success result with empty text no longer publishes an empty `response`
artifact.

See the a2a-claude README for caveats, including how `claude.maxTurns` and
`timeouts.prompt` now span a held-open Task's rounds.

- ddc0861: Allow `timeouts.prompt` to be disabled by setting it to `0` (or any value `<= 0`). Previously every turn was bounded at ten minutes by default with no way to opt out, which cut off legitimately long-running turns.

Negative values were also a footgun: `setTimeout` coerces a negative delay to the next tick, so `prompt: -1` — the intuitive spelling for "no timeout" — aborted the turn immediately instead of disabling the bound. The timer is now armed only for positive values, matching the "set to `0` to disable" convention already used for `healthCheck`.

- a9101a1: **Breaking:** a rate limit now always fails the task. The `rateLimit.taskState`
config option is removed.

It previously defaulted to `input-required`, on the reasoning that leaving the
task open let the client continue the same conversation. That reasoning does not
hold:

- **The interrupted turn cannot resume.** `ctx.task` only suppresses the initial
`Task` record; the prompt sent is always the new user message, and there is no
replay or continue-previous-turn logic. A follow-up on the open task is just a
new prompt appended to the conversation — exactly what a new task would send.
- **Continuity never depended on the task state.** It comes from the
`contextId` → Claude session mapping in `SessionManager`, which is indifferent
to how a task ended. A new task on the same `contextId` resumes the identical
Claude session.
- **`input-required` means the agent lacks information.** A rate limit lacks
quota; nothing the client sends unblocks it, only elapsed time. Clients with
generic `input-required` handling would prompt a human for input nobody wants.
- Publishing a non-terminal state alongside `final: true` was also internally
inconsistent.

The status message now always points at the `contextId` rather than the closed
task, and still carries the structured metadata (`reason`, `rateLimitType`,
`resetsAt`, `resetsAtIso`, `utilization`) that an orchestrator needs to schedule
its own retry. `features.emitRateLimitEvents` is unchanged.

Migration: remove any `rateLimit` block from your config. If your orchestrator
alerts on failed tasks, key the suppression on `metadata.reason === "rate_limit"`.

- 3ec9e49: **Breaking:** session expiry is now disabled by default (`session.ttl` defaults
to `0`), and the background cleanup sweep with it (`session.cleanupInterval`
also defaults to `0`). Set `"session.ttl": 3600000` and
`"session.cleanupInterval": 300000` to restore the previous behaviour.

Previously sessions expired one hour after their **first** message regardless of
activity, which silently dropped the `contextId` → Claude session mapping and
made a conversation lose all of its context with no error and only an
`info`-level log line. Evicting the record reclaimed no disk either — the wrapper
never deletes SDK session files, so eviction orphaned the transcript rather than
removing it.

`session.ttl <= 0` now disables expiry in both eviction paths. A positive `ttl`
behaves as before.

`cleanupInterval` is only ever consulted when `ttl > 0` — with expiry off there
is nothing to sweep — so leaving it at `300000` alongside `ttl: 0` was dead
configuration that read as if it did something. It now defaults to `0` to match,
and both example configs drop it entirely. If you set `ttl` on its own you get
expiry via the lazy check in `getOrCreate`, but a context that is never used
again holds its record until the process exits; set `cleanupInterval` too if you
want that reclaimed. Both disabled states are now logged at startup, so neither
can be lost silently.

Known consequence: if a Claude session's on-disk transcript is removed while the
server is running, the stored `contextId` → `sessionId` mapping is now pinned for
the life of the process instead of being evicted within the hour, so turns on
that context keep failing to resume until the server restarts. Previously the
one-hour expiry masked this by self-healing.

### Patch Changes

- Updated dependencies [f3c7062]
- Updated dependencies [41e2d82]
- @a2a-wrapper/core@2.1.0

## 0.3.0

### Minor Changes
Expand Down
4 changes: 2 additions & 2 deletions a2a-claude/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "a2a-claude",
"version": "0.3.0",
"version": "0.4.0",
"description": "A2A (Agent-to-Agent) protocol wrapper for Claude Code via the Claude Agent SDK. Drop a JSON config file in, get a fully-spec-compliant A2A server out. Supports permission modes, MCP tools, streaming sideband events, and multi-agent delegation.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -54,7 +54,7 @@
},
"dependencies": {
"@a2a-js/sdk": "^1.0.0",
"@a2a-wrapper/core": "2.0.0",
"@a2a-wrapper/core": "2.1.0",
"@anthropic-ai/claude-agent-sdk": "0.3.245",
"express": "^4.18.2",
"uuid": "^9.0.0"
Expand Down
8 changes: 8 additions & 0 deletions a2a-codex/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# a2a-codex

## 1.7.1

### Patch Changes

- Updated dependencies [f3c7062]
- Updated dependencies [41e2d82]
- @a2a-wrapper/core@2.1.0

## 1.7.0

### Minor Changes
Expand Down
4 changes: 2 additions & 2 deletions a2a-codex/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "a2a-codex",
"version": "1.7.0",
"version": "1.7.1",
"description": "A2A (Agent-to-Agent) protocol wrapper for OpenAI Codex SDK. Drop a JSON config file in, get a fully-spec-compliant A2A server out. Supports repository sandboxing, MCP tools, streaming sideband events, and multi-agent delegation.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -54,7 +54,7 @@
},
"dependencies": {
"@a2a-js/sdk": "^1.0.0",
"@a2a-wrapper/core": "2.0.0",
"@a2a-wrapper/core": "2.1.0",
"@openai/codex-sdk": "^0.137.0",
"express": "^4.18.2",
"uuid": "^9.0.0"
Expand Down
8 changes: 8 additions & 0 deletions a2a-copilot/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 1.8.1

### Patch Changes

- Updated dependencies [f3c7062]
- Updated dependencies [41e2d82]
- @a2a-wrapper/core@2.1.0

## 1.8.0

### Minor Changes
Expand Down
Loading