Skip to content

Releases

v0.12.0

Choose a tag to compare

@saadahmed95 saadahmed95 released this 27 Oct 09:27
b9a60a0

See CHANGELOG.md, section 0.12.0.

v0.11.0

Choose a tag to compare

@saadahmed95 saadahmed95 released this 23 Oct 10:08
a306fae

See CHANGELOG.md, section 0.11.0.

v0.10.0

Choose a tag to compare

@saadahmed95 saadahmed95 released this 21 Oct 12:19
430933b

What's Changed

  • fix(build): ship no test fixtures, and fail the build on one only tests reach by @saadahmed95 in #202
  • chore(build): remove four unused layer index files, and ship nothing the root doesn't reach by @saadahmed95 in #203
  • feat(transport)!: forward no caller header to tools when auth.forwardHeaders is unset by @saadahmed95 in #204
  • build(build): release 0.10.0 by @saadahmed95 in #205

Full Changelog: v0.9.0...v0.10.0

v0.9.0

Choose a tag to compare

@saadahmed95 saadahmed95 released this 21 Oct 08:51
7955b21

What's Changed

  • feat(transport): record which persona wrote an assistant entry by @saadahmed95 in #181
  • feat(testing): export the recorded protocol frames as a consumer fixture by @saadahmed95 in #182
  • feat(providers): fail over to a second provider when one is unavailable by @saadahmed95 in #183
  • feat(transport): let a consumer set the text of the connect frame by @saadahmed95 in #184
  • feat(providers): add a reversible prompt mask at the provider boundary by @saadahmed95 in #185
  • lore: onboard re-cinq/halengine by @lore-agent[bot] in #196
  • docs(spec): describe the shipped tool-response contract by @saadahmed95 in #190
  • feat(types): give session state a creation time to measure age from by @saadahmed95 in #186
  • feat(providers): make the mock provider scriptable by @saadahmed95 in #187
  • feat(providers): report token usage from the Bedrock provider by @saadahmed95 in #188
  • fix(transport): refuse an authenticated id the engine cannot use as an identity by @saadahmed95 in #189
  • feat(orchestration): read the tool list every turn, not at construction by @saadahmed95 in #191
  • feat(transport): carry the authenticated user into the tool context by @saadahmed95 in #192
  • feat(transport): let a consumer choose which caller headers reach a tool by @saadahmed95 in #193
  • ci(lore): bring the ingest workflow to v7, keeping local hardening by @gedaiu in #199
  • build: Bump eslint from 10.12.0 to 10.13.0 in the development group across 1 directory by @dependabot[bot] in #180
  • feat(session): support mongodb driver 7 by @vvondruska in #169
  • feat(tools): mark a failed tool result as an error on the provider wire by @saadahmed95 in #195
  • fix(orchestration): give each tool call its own copy of the caller's headers by @saadahmed95 in #200
  • build(build): release 0.9.0 by @saadahmed95 in #201

Full Changelog: v0.8.0...v0.9.0

v0.8.0

Choose a tag to compare

@saadahmed95 saadahmed95 released this 19 Oct 20:54
e951e35

What's Changed

Full Changelog: v0.7.0...v0.8.0

v0.7.0

Choose a tag to compare

@saadahmed95 saadahmed95 released this 19 Oct 19:32
99ac2a0

What's Changed

  • stop save from resurrecting erased conversations by @lore-agent[bot] in #168
  • build: Bump the development group across 1 directory with 6 updates by @dependabot[bot] in #167
  • build: Bump the production group across 1 directory with 4 updates by @dependabot[bot] in #166
  • build: Bump mongodb-memory-server from 10.4.3 to 11.3.0 by @dependabot[bot] in #138
  • build: Bump actions/setup-node from 7.0.0 to 7.1.0 by @dependabot[bot] in #159
  • fix(transport): answer unhandled HTTP errors with a safe JSON response by @saadahmed95 in #170
  • fix(tools): refuse a duplicate tool name in ToolRegistry by @saadahmed95 in #171
  • fix(transport): close an upgraded WebSocket with 1011 instead of writing HTTP 500 into it by @saadahmed95 in #172
  • fix(session): break a tie on session activity by one rule in both stores by @saadahmed95 in #173
  • feat(transport): map every AIError to a client error through one table by @saadahmed95 in #174
  • fix(transport): blank every model-authored entry when a tool suppresses the response by @saadahmed95 in #175
  • fix(transport): bind the credential the engine authenticates to the one it forwards by @saadahmed95 in #176
  • build(build): release 0.7.0 by @saadahmed95 in #177

Full Changelog: v0.6.1...v0.7.0

v0.6.1

Choose a tag to compare

@saadahmed95 saadahmed95 released this 16 Oct 12:17
edf5f0c

What's Changed

Full Changelog: v0.6.0...v0.6.1

v0.6.0

Choose a tag to compare

@vvondruska vvondruska released this 08 Oct 06:29
11cda9f

What's Changed

Full Changelog: v0.5.0...v0.6.0

v0.5.0

Choose a tag to compare

@saadahmed95 saadahmed95 released this 04 Oct 21:44
b97e7b1

Session resume, a cancellation chain from the socket through the provider to every tool call, tools that run on Vertex, and failing tool calls answered to the model. One thing is removed and several behaviours an existing consumer observes change: see Upgrading from 0.4.x below. Every release up to and including 0.4.0 has two defects that end the process (see Security and Fixed), so upgrade even if you use none of the new features.

Upgrading from 0.4.x

  • Every client must offer hal.v1 beside its token, new WebSocket(url, ['hal.v1', token]). A bare-token offer, accepted with a deprecation warning since 0.3.0, now fails to connect, and credentialFromSubprotocol returns undefined for it.
  • Closing a socket abandons its turn. The run stops reading from the model and abandons its tool calls, no stream_end follows the close, and afterModelResponse and onError do not fire for it, while afterSession still does. A missed heartbeat and stop() close sockets too, so drain connections before a deploy.
  • Every tool call now has 30 seconds to settle, a beforeToolCall policy included. A tool that legitimately runs longer needs a larger toolTimeoutMs, or 0 for the old unbounded wait.
  • ToolRegistry.execute no longer throws for a tool name the model invented, or rejects when an executor throws: the model is answered instead. It throws a TypeError for an input that is not an object, whatever the tool's schema.
  • Messages in one session are answered one at a time, so a message sent while another is streaming starts after that one's stream_end.
  • Tools now run on Vertex, where a function-calling turn ends tool_use instead of end_turn. If you read stopReason yourself, expect the new value.
  • Two new error log lines: authenticator failed for a WsAuthenticator that throws or rejects, and tool executor threw for a tool executor that does.
  • Resume is opt-in and changes nothing until you enable it. With it on, do not erase a conversation in onDisconnect: the socket a resume replaced can report onDisconnect after the resume.

Added

  • Session resume, opt-in via transport: {resume: {enabled: true}}. A client that reconnects with ?sessionId=<id> gets its conversation back, but only the session's own user; any other id gets a fresh session, indistinguishable from one that never existed.
  • Continue the latest session with resume: {enabled: true, latest: true}: a refresh or a new tab rejoins the user's most recently active conversation, and ?new=1 starts a new one. Stores supply it through the optional SessionStore.latestFor.
  • An expired session told apart from a missing one, through the optional SessionStore.lookup and resumeFailure on the connected frame, which reads expired only for the session's owner.
  • Cancel a model call with SendMessageParams.signal. Bedrock closes the request; @google-cloud/vertexai cannot cancel, so on Vertex the engine stops reading while the vendor request runs on.
  • A deadline on every tool call, toolTimeoutMs (default 30000, 0 waits forever), and a ToolContext.signal aborted at the deadline with a TimeoutError, so a tool that passes it to fetch stops its own request too.
  • Stored entries a tool suppressed carry suppressed: true, so a resumed session never shows text a tool hid.

Removed

  • The bare-token subprotocol offer. It put the access token in the 101 response headers; clients have offered ['hal.v1', token] since 0.3.0.

Changed

  • Closing a socket abandons its turn, as above. The session keeps the answer as it stood, committed and flagged truncated, so a resumed session shows it cut off. processMessageStream takes an optional {signal} that does the same for a caller of its own.
  • credentialFromSubprotocol returns undefined unless the offer includes hal.v1.
  • A failing WsAuthenticator is logged at error, with its error type only, never its message.

Fixed

  • Messages in one session are answered one at a time, in the order they arrived, instead of interleaving two runs.
  • A Vertex stream that failed mid-way ended the process, through an unobserved promise inside @google-cloud/vertexai. Every release up to and including 0.4.0 is affected.
  • No tool ever ran on Vertex: the provider reported a function-calling turn as end_turn, so the call was dropped. Every release up to and including 0.4.0 is affected.
  • A failing tool call no longer fails the turn. An invented tool name or a throwing executor is answered to the model, and the round's other results survive. The thrown message is logged, cut to 500 characters, and never shown to the model; a throw after the user left is logged at info as tool call abandoned.
  • An answer still streaming when a tool suppresses the response is committed and retracted like one already sent.

Security

  • One malformed WebSocket upgrade could end the process. An empty or missing Host header, or a request-target such as //, threw where nothing catches it, so a single request with no credentials ended the process and every conversation on it. It is now answered 400 Bad Request. Every release up to and including 0.4.0 is affected.

Full detail is in CHANGELOG.md.

v0.4.0

Choose a tag to compare

@gedaiu gedaiu released this 29 Sep 16:31
b219ecd

Durable sessions, provider retries, and three hook-reliability fixes. Nothing is removed and no existing signature changes, but three behaviours an existing consumer observes do change — see Upgrading from 0.3.x below.

Upgrading from 0.3.x

  • A closed socket no longer erases the conversation. The WebSocket close handler used to call sessionStore.delete(sessionId) unconditionally, so behind a durable store every conversation was written and then destroyed the moment the customer closed their tab. delete now has no engine-internal caller and is purely your erasure primitive. To restore the old behaviour, pass onDisconnect: sessionId => store.delete(sessionId) — but do not point that at MongoSessionStore, where delete destroys the document.
  • afterModelResponse now reports the whole turn's usage. It receives totalUsage, the sum across every provider call in the turn, rather than the last round alone. Billing and audit consumers will see totals rise on tool-heavy turns; that is the corrected figure.
  • onError now fires for rejections that are not Error instances. A non-Error value is wrapped in an Error whose cause is the original, so a hook typed against Error keeps compiling and a hook that wants the raw value can reach it.
  • SessionStore members are now Awaitable<T>. A synchronous store needs no change.
  • New optional peer dependency: mongodb, loaded only if MongoSessionStore actually connects.

Added

  • MongoSessionStore — a durable session store, exported as MongoSessionStore and createMongoSessionStore. Takes a collection, a client with a database name, or a connection URL; nothing reads the environment for you. No credential is ever written: authHeaders, authorization, cookie and host are stripped at any depth, and the same stripCredentialKeys is exported for stores you write yourself.
  • SessionStore.save(session) — the write signal a durable store needs, called once per processed user message from the same path that runs afterSession, so it fires for a turn that ended in a provider error as well as one that succeeded. What it throws is logged and the turn continues: a database outage is not a reason for the agent to stop answering.
  • SessionStore.evict(sessionId) and a bounded InMemorySessionStore, which now takes {maxAgeMs} (eight hours by default). There is no timer — a library-owned interval would keep your process alive.
  • withRetry(provider, policy) — wraps any AIProvider with per-attempt retry and two separate deadlines. Retries stop once the first chunk has been handed off, because streamed output cannot be un-sent; a stalled stream surfaces as an AIError with code TIMEOUT. Defaults: maxAttempts: 3, baseDelayMs: 500, maxDelayMs: 5000, firstChunkTimeoutMs: 30000, idleChunkTimeoutMs: 30000, exponential backoff with full jitter.
  • HalEngineConfig.resilience?: RetryPolicy — when present, createHalEngine wraps the configured provider; when absent, behaviour is unchanged.

Fixed

  • onError and afterSession now run when beforeSession throws. The call sat above the try, so a failure during session setup skipped both hooks — and leaked whatever beforeSession had allocated on exactly the path where the allocation failed.

Full detail, including the entries not repeated here, is in CHANGELOG.md.