AHP Swift Package v0.4.0
[0.4.0] — 2026-06-19
Implements AHP 0.4.0.
Added
MessageOriginstruct andMessageKindenum now typeMessage.origin
(previously an untypedAnyCodable);MessageKindcoversuser,agent,
tool, andsystemNotification, adding faithful agent- and tool-initiated
origins.ConfigPropertySchema.additionalProperties— optional field describing the
schema for object-typed config properties beyond those inproperties.ChangesetContentChangedActionfor full-replacement changeset file
snapshots with optional operations and error details.ChangesetOperationStatus.disabled— new case for changeset operations
that are currently unavailable and cannot be invoked.ChangesetOperation.group— optional identifier for grouping related
changeset operations together in the UI._meta(meta) field on the per-turn chat actions (chat/turnStarted,
chat/delta,chat/responsePart,chat/reasoning,chat/usage,
chat/turnComplete,chat/turnCancelled,chat/error) — optional
provider-specific metadata so hosts can carry portable per-event context,
such as attributing an event to a specific agent (e.g. a sub-agent acting
within the turn).
Changed
ToolResultSubagentContent.resourceis now specified as the spawned worker
chat URI (ahp-chat:/<cid>), not a session URI — a tool-spawned
sub-agent is a chat. Its doc now describes the correspondence with the worker
chat'sChatOrigin.toolrecord (matchingtoolCallId), which remains the
canonical representation of the spawn relationship.- BREAKING:
SessionStatusis now anOptionSetwith aUInt32rawValue
(wasInt), an unsigned 32-bit bitset that preserves combined and unknown
forward-compat bits. Combine flags with set-union (∪/union) and test
membership withcontains(_:). - BREAKING:
ChangesetOperationTarget's range target now carries a nested
TextRange({start: {line, character}, end: {line, character}}) instead of
a flat{start, end}integer pair.
Added
SnapshotState.resourceWatchcase and matching
MultiHostStateMirror.resourceWatchesslot, soapplySnapshot(host:snapshot:)
can seed anahp-resource-watch:channel's descriptor (root URI, recursive
flag, optional includes/excludes) alongside the existing root / session /
terminal / changeset / annotations slots.reset(host:)/reset()clear
the new slot.
Fixed
AnyCodable.encodeno longer corruptsNSNumber-backedInt/Doublevalues toBool/Int.NSNumberis now special-cased before the generic Swift type arms, usingCFBooleanGetTypeID()to distinguish boolean from numericNSNumberinstances.AnyCodable.encode(to:)now preserves unsigned integers aboveInt64.max(encodingNSNumbervalues whoseobjCTypeis unsigned viauint64Valueinstead of the signedint64Valuefallback), and theAnyCodable.swifttemplate inscripts/generate-swift.tsreproduces the full encode/equality logic so regenerating the scaffold no longer reintroduces the bug.MultiHostClient/host runtime now advertises the generatedSUPPORTED_PROTOCOL_VERSIONSoninitializeinstead of a stale hard-coded"0.2.0".- Session reducers now apply
_meta(meta) updates from every
tool-call-scoped action, not onlysession/toolCallStart.
Added
-
annotationsReducerimplemented; annotations conformance fixtures (210–219) now pass. -
AnnotationsUpdatedAction(annotations/updated) — partially updates an
existing annotation'sturnId/resource/range/resolvedwithout
resending its entries. Handled by the annotations reducer (no-op on unknown
id). -
ahp-chat:channel for per-chat conversation state;SessionState.chats[]catalog;SessionState.defaultChat?input-routing hint;ChatOriginprovenance union;createChat/disposeChatcommands. -
SessionChatAddedAction,SessionChatRemovedAction, andSessionChatUpdatedActionhandling for incremental chat catalog updates. -
ChatSummary.workingDirectory— optional per-chat working directory. Falls back to the session'sworkingDirectorywhen absent. -
SessionDefaultChatChangedAction(session/defaultChatChanged) — updatesSessionState.defaultChatto steer new input to the designated chat; absent value clears the hint. -
ErrorInfo.meta: [String: AnyCodable]?— optional provider-specific metadata bag on error payloads (serialized as_meta), mirroring the existingmetafield onUsageInfoand other protocol types. Clients MAY inspect well-known keys here for richer, localised error UI. -
RootStatenow exposes an optional_metaproperty bag (meta: [String: AnyCodable]?) for implementation-defined agent-host metadata, such as a
well-knownhostBuildkey carrying the host's build version/commit/date. -
changesetReducerandresourceWatchReducer— the two state reducers
that were missing from the Swift client are now implemented, mirroring the
canonical TypeScript reducers (and the Kotlin/.NET clients).changesetReducer
foldschangeset/*actions intoChangesetState;resourceWatchReducer
treatsresourceWatch/changedas a documented event pass-through. The
fixture-driven reducer test no longer silently skips the terminal, changeset,
and resourceWatch fixture families — they now decode and assert, with the
remaining gaps (unknown-discriminant response part; the not-yet-implemented
annotations channel) pinned by an explicit drift tripwire.
Changed
ChatStateis now flat — the previous embeddedsummaryhas been replaced with inlinedresource/title/status/activity/modifiedAt/model/agent/origin/workingDirectoryproperties.ChatSummaryremains as the standalone catalog entry onSessionState.chats.ChatSummary.modifiedAtandChatState.modifiedAtare now ISO 8601Stringvalues instead ofInt64/UInt64milliseconds.
Added
ChatSummary.interactivity/ChatState.interactivity("full" | "read-only" | "hidden") indicating how the user can interact with a chat. Absent defaults to"full".
Removed
SessionChatsChangedAction(replaced by the three discrete chat-catalog actions above).
Fixed
- Encode-fidelity: an unknown
StateActionvariant no longer re-encodes to
{}(dropping itstypediscriminant and extra fields); the raw payload is
preserved on decode and re-emitted verbatim. - Forward-compatibility: unknown discriminants on wire-decoded discriminated
unions (ResponsePart,ToolCallState,TerminalClaim,
TerminalContentPart,Customization, and other evolvable unions) now decode
to a raw passthrough and re-encode verbatim instead of throwing
DecodingError, so a snapshot carrying an unknown variant still decodes and
subsequent actions fold correctly. ChangesetOperationResourceTarget/…RangeTargetnow encode theirkind
discriminant (previously a computed property excluded fromCodingKeys, so it
was dropped on encode).