@haikit/client 0.20.2 → 0.20.3

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +12 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haikit/client",
3
- "version": "0.20.2",
3
+ "version": "0.20.3",
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
@@ -401,7 +401,9 @@ export function createChat({
401
401
  surface.revising = false;
402
402
  const { instance, element } = surface;
403
403
  if (instance && typeof instance.update === "function") attempt(() => instance.update(event.props));
404
- else if (instance && element) mount(surface.handle, element);
404
+ // mounted with no instance to update, a component's `mount` may return
405
+ // nothing: it's mounted again all the same, or it would show old props
406
+ else if (element) mount(surface.handle, element);
405
407
  }
406
408
  break;
407
409
  }
@@ -412,7 +414,8 @@ export function createChat({
412
414
  surface.state = event.state;
413
415
  // kept, so a surface mounted again once frozen still knows the answer
414
416
  surface.selection = event.selection;
415
- surface.instance?.freeze?.(event.selection);
417
+ // isolated, like every other hook: one that throws mustn't stop the event
418
+ attempt(() => surface.instance?.freeze?.(event.selection));
416
419
  }
417
420
  break;
418
421
  }
@@ -494,8 +497,9 @@ export function createChat({
494
497
  headers: last ? { "last-event-id": String(last) } : {},
495
498
  signal: attempt.signal,
496
499
  });
497
- // the server has no such conversation, or sends no notices: stop
498
- if (res.status === 404) return;
500
+ // the server has no such conversation, or sends no notices: stop,
501
+ // and stop waiting for a wake turn this stream was following
502
+ if (res.status === 404) return finishRemote();
499
503
  if (res.ok) {
500
504
  const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
501
505
  let buffer = "";
@@ -546,6 +550,8 @@ export function createChat({
546
550
  // what the turn has shown so far, or that none is running.
547
551
  if (polling && ended && gen === generation && !signal.aborted) {
548
552
  firstPoll = false;
553
+ // a poll that ended as polls do was healthy: the next failure backs off from the start
554
+ wait = 1_000;
549
555
  await pause(Math.max(0, POLL_GAP_MS - (Date.now() - opened)), signal);
550
556
  continue;
551
557
  }
@@ -698,7 +704,8 @@ export function createChat({
698
704
  if (!surface.element) return;
699
705
  surface.element.inert = true;
700
706
  surface.element.dataset.expired = "";
701
- surface.instance?.expire?.();
707
+ // after sealing, and isolated: one that throws mustn't leave the next unsealed
708
+ attempt(() => surface.instance?.expire?.());
702
709
  }
703
710
 
704
711
  /**