@haikit/client 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -129,7 +129,15 @@ The server closes a conversation once any surface passes its freshness window.
129
129
  The client knows each window too, so a tab left open closes on time instead of
130
130
  looking live until a click is refused: `state.expired` holds the notice,
131
131
  `send` and `interact` stop sending, and each surface's element is made `inert`
132
- with `data-expired` set. `chat.reset()` starts a new conversation; the default
132
+ with `data-expired` set.
133
+
134
+ The browser counts each window from when it sent the request that rendered
135
+ the surface, which is never later than the server's own stamp, so its
136
+ deadline is never later than the server's. Each surface also comes with
137
+ `ageMs`, how long ago the server stored it: the time its digest took, plus,
138
+ for one replayed to a stream that joined a wake turn part way, how long it
139
+ waited. The window is counted from whichever is earlier. That's a duration,
140
+ not a time, so the two clocks are never compared. `chat.reset()` starts a new conversation; the default
133
141
  transcript renders the notice with a button that calls it.
134
142
 
135
143
  ## Serving it
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haikit/client",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "The haikit browser runtime: streams tool payloads into interactive UI surfaces. Plain ESM, no build step, no dependencies.",
5
5
  "keywords": [
6
6
  "haikit",
package/src/index.js CHANGED
@@ -293,7 +293,11 @@ export function createChat({ endpoint = "/hai", registry, notices = {} }) {
293
293
  state.blocks.push(early);
294
294
  }
295
295
  if (typeof event.staleAfterMs === "number") {
296
- const at = sentAt + event.staleAfterMs;
296
+ // From when the request that rendered it was sent, or, for a surface
297
+ // replayed to a stream that joined a wake turn part way, from when
298
+ // it was stored, by its age: whichever is earlier.
299
+ const from = typeof event.ageMs === "number" ? Math.min(sentAt, Date.now() - event.ageMs) : sentAt;
300
+ const at = from + event.staleAfterMs;
297
301
  if (state.expiresAt === null || at < state.expiresAt) {
298
302
  state.expiresAt = at;
299
303
  closingWindow = event.staleAfterMs;