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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,26 @@ Spec version: `0.4.0`
Resolving or re-anchoring an annotation no longer requires replacing the
whole annotation via `annotations/set`. Omitted fields are left unchanged;
the annotation's `entries`, `id`, and `_meta` are never touched.
- `ahp-chat:` channel for per-chat conversation state; `SessionState.chats[]` catalog; `SessionState.defaultChat?` input-routing hint; `ChatOrigin` provenance union; `createChat` command.
- `ChatSummary.workingDirectory?` — optional per-chat working directory. When absent, chats inherit the session's `workingDirectory`. Enables agent-swarm patterns where multiple chats in one session operate on independent worktrees.
- Three discrete chat-catalog actions on the session channel — `session/chatAdded` (upsert by `summary.resource`), `session/chatRemoved`, and `session/chatUpdated` (partial-update with `Partial<ChatSummary>`) — mirroring the root-channel `root/sessionAdded` / `root/sessionRemoved` / `root/sessionSummaryChanged` pattern.
- `RootState` now carries an optional `_meta` property bag for
implementation-defined metadata about the agent host itself, mirroring the
MCP `_meta` convention. A well-known `hostBuild` key may carry build
information (version, commit, date) about the program hosting the agent host.

### Changed

- `fetchTurns` and `completions` now target an `ahp-chat:` channel; `PROTOCOL_VERSION` bumped to `0.4.0`.
- `ChatState` is now **flat** — the previous `summary: ChatSummary` sub-object has been replaced by inlined `resource` / `title` / `status` / `activity` / `modifiedAt` / `model` / `agent` / `origin` / `workingDirectory` fields. `ChatSummary` remains as the standalone catalog entry on `SessionState.chats`.
- `ChatSummary.modifiedAt` and `ChatState.modifiedAt` are now ISO 8601 strings instead of numeric milliseconds.
- `SessionSummary` now documents how its aggregate fields (`status`, `activity`, `modifiedAt`) are derived from the session's chats, including `InputNeeded` / `Error` promotion when any chat raises the flag.

### Removed

- `SessionState.turns`, `SessionState.activeTurn`, `SessionState.steeringMessage`, `SessionState.queuedMessages`, `SessionState.inputRequests` (moved to `ChatState`).
- `session/chatsChanged` full-replacement action (replaced by `session/chatAdded` / `session/chatRemoved` / `session/chatUpdated`).

## [0.3.0] — 2026-06-05

Spec version: `0.3.0`
Expand Down
17 changes: 15 additions & 2 deletions clients/go/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,23 @@ tag whose matching `## [X.Y.Z]` heading is missing from this file.
resending its entries. Handled by the annotations reducer (no-op on unknown
id).

### Added

- `ahp-chat:` channel for per-chat conversation state; `SessionState.chats[]` catalog; `SessionState.defaultChat?` input-routing hint; `ChatOrigin` provenance union; `createChat` / `disposeChat` commands.
- `ChatSummary.WorkingDirectory` — optional per-chat working directory. Falls back to the session's `WorkingDirectory` when absent.
- Three discrete chat-catalog actions on the session channel — `SessionChatAddedAction` (upsert by `Summary.Resource`), `SessionChatRemovedAction`, and `SessionChatUpdatedAction` (partial-update payload).
- `RootState` now exposes an optional `_meta` property bag (`Meta
map[string]json.RawMessage`) for implementation-defined agent-host metadata,
such as a well-known `hostBuild` key carrying the host's build
version/commit/date.

### Changed

- `ChatState` is now flat — the previous embedded `Summary` has been replaced with inlined `Resource` / `Title` / `Status` / `Activity` / `ModifiedAt` / `Model` / `Agent` / `Origin` / `WorkingDirectory` fields. `ChatSummary` remains as the standalone catalog entry on `SessionState.Chats`.
- `ChatSummary.ModifiedAt` and `ChatState.ModifiedAt` are now ISO 8601 `string` values instead of integer milliseconds.

### Removed

- `SessionChatsChangedAction` (replaced by the three discrete chat-catalog actions above).

## [0.3.0] — 2026-06-05

Implements AHP 0.3.0.
Expand Down Expand Up @@ -96,11 +106,14 @@ Implements AHP 0.3.0.

### Changed

- Reducers split into per-chat and session-aggregate handlers to match the multi-chat protocol shape.
- `fetchTurns` and `completions` now target an `ahp-chat:` channel; `PROTOCOL_VERSION` bumped to `0.4.0`.
- Renamed the `ChangesetSummary` type to `Changeset`. The on-the-wire shape is unchanged.
- Moved the `changesets` catalogue from `SessionSummary` to `SessionState`. The `session/changesetsChanged` action now updates `state.changesets` directly instead of `state.summary.changesets`.

### Removed

- `SessionState.turns`, `SessionState.activeTurn`, `SessionState.steeringMessage`, `SessionState.queuedMessages`, `SessionState.inputRequests` (moved to `ChatState`).
- Removed the `additions`, `deletions`, and `files` fields from `ChangesetSummary`. Aggregate counts now live on `SessionSummary.changes`; per-changeset views derive their own totals from `ChangesetState.files`.

### Changed
Expand Down
28 changes: 26 additions & 2 deletions clients/go/ahp/multi_host_state_mirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ type HostedResourceKey struct {
// The mirror has no opinion about how snapshots are kept in sync with
// the server — that's the consumer's job, typically by feeding action
// envelopes from a [HostSubscriptionEvent] stream through the matching
// [ApplyActionToRoot] / [ApplyActionToSession] / [ApplyActionToTerminal]
// reducer and re-storing the result.
// [ApplyActionToRoot] / [ApplyActionToSession] / [ApplyActionToChat] /
// [ApplyActionToTerminal] reducer and re-storing the result.
type MultiHostStateMirror struct {
mu sync.RWMutex
roots map[string]ahptypes.RootState
session map[HostedResourceKey]ahptypes.SessionState
chat map[HostedResourceKey]ahptypes.ChatState
term map[HostedResourceKey]ahptypes.TerminalState
changes map[HostedResourceKey]ahptypes.ChangesetState
}
Expand All @@ -37,6 +38,7 @@ func NewMultiHostStateMirror() *MultiHostStateMirror {
return &MultiHostStateMirror{
roots: make(map[string]ahptypes.RootState),
session: make(map[HostedResourceKey]ahptypes.SessionState),
chat: make(map[HostedResourceKey]ahptypes.ChatState),
term: make(map[HostedResourceKey]ahptypes.TerminalState),
changes: make(map[HostedResourceKey]ahptypes.ChangesetState),
}
Expand Down Expand Up @@ -74,6 +76,22 @@ func (m *MultiHostStateMirror) Session(hostID string, uri ahptypes.URI) (ahptype
return v, ok
}

// PutChat stores a chat snapshot under (hostID, uri).
func (m *MultiHostStateMirror) PutChat(hostID string, uri ahptypes.URI, c ahptypes.ChatState) {
m.mu.Lock()
defer m.mu.Unlock()
m.chat[HostedResourceKey{hostID, uri}] = c
}

// Chat returns the chat snapshot at (hostID, uri), or
// (zero, false) if none is recorded.
func (m *MultiHostStateMirror) Chat(hostID string, uri ahptypes.URI) (ahptypes.ChatState, bool) {
m.mu.RLock()
defer m.mu.RUnlock()
v, ok := m.chat[HostedResourceKey{hostID, uri}]
return v, ok
}

// PutTerminal stores a terminal snapshot under (hostID, uri).
func (m *MultiHostStateMirror) PutTerminal(hostID string, uri ahptypes.URI, t ahptypes.TerminalState) {
m.mu.Lock()
Expand Down Expand Up @@ -117,6 +135,11 @@ func (m *MultiHostStateMirror) DropHost(hostID string) {
delete(m.session, k)
}
}
for k := range m.chat {
if k.HostID == hostID {
delete(m.chat, k)
}
}
for k := range m.term {
if k.HostID == hostID {
delete(m.term, k)
Expand All @@ -136,6 +159,7 @@ func (m *MultiHostStateMirror) DropResource(hostID string, uri ahptypes.URI) {
defer m.mu.Unlock()
k := HostedResourceKey{hostID, uri}
delete(m.session, k)
delete(m.chat, k)
delete(m.term, k)
delete(m.changes, k)
}
Loading
Loading