@lunora/client 1.0.0-alpha.65 → 1.0.0-alpha.67

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/dist/index.d.mts CHANGED
@@ -16,7 +16,7 @@ declare const anyApi: Record<string, Record<string, unknown>>;
16
16
  /**
17
17
  * The durable-message shape the reconcile reads: a structural subset of each
18
18
  * adapter's `AgentChatMessage` (itself a client-safe mirror of `@lunora/agent`'s
19
- * `AgentMessageRow`). Only `content`, `role`, and the globally-monotonic `seq` are
19
+ * `AgentMessageRow`). Only `content`, `role`, and the per-thread-monotonic `seq` are
20
20
  * consulted; adapters pass their fuller row type, which is assignable to this.
21
21
  */
22
22
  interface ReconcileDurableMessage {
@@ -36,8 +36,15 @@ interface OptimisticMessage {
36
36
  * The highest durable `seq` present when this row was sent. The reconcile
37
37
  * retires the row when a durable `user` row with matching `content` lands at a
38
38
  * STRICTLY GREATER `seq` (i.e. after the send) — window-independent because
39
- * `seq` is globally monotonic, not a positional count. Also the age baseline for
40
- * the {@link RETIRE_AFTER_DURABLE_SEQ_ADVANCE} fallback.
39
+ * `seq` is monotonic, not a positional count. Also the age baseline for the
40
+ * {@link RETIRE_AFTER_DURABLE_SEQ_ADVANCE} fallback.
41
+ *
42
+ * `seq` is monotonic PER THREAD, not globally (`@lunora/agent` assigns it from
43
+ * the thread's own message count), so a baseline captured in one thread is
44
+ * meaningless in another: an optimistic row carried across a thread switch can
45
+ * never be retired by the new thread's history until its `seq` happens to pass
46
+ * the old thread's. Adapters therefore drop their optimistic rows whenever the
47
+ * resolved thread key changes.
41
48
  */
42
49
  maxDurableSeqAtSend: number;
43
50
  }
@@ -58,8 +65,8 @@ declare const maxSeq: (messages: ReadonlyArray<{
58
65
  * This covers the pathological "identical content already present at send time"
59
66
  * case, where no user row with a STRICTLY GREATER `seq` than the send-time max will
60
67
  * ever appear for the primary content match to consume (e.g. the acknowledging row
61
- * was evicted by a bounded `limit` before reconcile could see it). `seq` is globally
62
- * monotonic, so it keeps climbing even when the visible user-row COUNT does not.
68
+ * was evicted by a bounded `limit` before reconcile could see it). `seq` is monotonic
69
+ * within the thread, so it keeps climbing even when the visible user-row COUNT does not.
63
70
  *
64
71
  * The `2` is a heuristic threshold, NOT an invariant about turn shape. It is
65
72
  * tempting to read it as "one turn == a user row and an assistant row (+2)", but
package/dist/index.d.ts CHANGED
@@ -16,7 +16,7 @@ declare const anyApi: Record<string, Record<string, unknown>>;
16
16
  /**
17
17
  * The durable-message shape the reconcile reads: a structural subset of each
18
18
  * adapter's `AgentChatMessage` (itself a client-safe mirror of `@lunora/agent`'s
19
- * `AgentMessageRow`). Only `content`, `role`, and the globally-monotonic `seq` are
19
+ * `AgentMessageRow`). Only `content`, `role`, and the per-thread-monotonic `seq` are
20
20
  * consulted; adapters pass their fuller row type, which is assignable to this.
21
21
  */
22
22
  interface ReconcileDurableMessage {
@@ -36,8 +36,15 @@ interface OptimisticMessage {
36
36
  * The highest durable `seq` present when this row was sent. The reconcile
37
37
  * retires the row when a durable `user` row with matching `content` lands at a
38
38
  * STRICTLY GREATER `seq` (i.e. after the send) — window-independent because
39
- * `seq` is globally monotonic, not a positional count. Also the age baseline for
40
- * the {@link RETIRE_AFTER_DURABLE_SEQ_ADVANCE} fallback.
39
+ * `seq` is monotonic, not a positional count. Also the age baseline for the
40
+ * {@link RETIRE_AFTER_DURABLE_SEQ_ADVANCE} fallback.
41
+ *
42
+ * `seq` is monotonic PER THREAD, not globally (`@lunora/agent` assigns it from
43
+ * the thread's own message count), so a baseline captured in one thread is
44
+ * meaningless in another: an optimistic row carried across a thread switch can
45
+ * never be retired by the new thread's history until its `seq` happens to pass
46
+ * the old thread's. Adapters therefore drop their optimistic rows whenever the
47
+ * resolved thread key changes.
41
48
  */
42
49
  maxDurableSeqAtSend: number;
43
50
  }
@@ -58,8 +65,8 @@ declare const maxSeq: (messages: ReadonlyArray<{
58
65
  * This covers the pathological "identical content already present at send time"
59
66
  * case, where no user row with a STRICTLY GREATER `seq` than the send-time max will
60
67
  * ever appear for the primary content match to consume (e.g. the acknowledging row
61
- * was evicted by a bounded `limit` before reconcile could see it). `seq` is globally
62
- * monotonic, so it keeps climbing even when the visible user-row COUNT does not.
68
+ * was evicted by a bounded `limit` before reconcile could see it). `seq` is monotonic
69
+ * within the thread, so it keeps climbing even when the visible user-row COUNT does not.
63
70
  *
64
71
  * The `2` is a heuristic threshold, NOT an invariant about turn shape. It is
65
72
  * tempting to read it as "one turn == a user row and an assistant row (+2)", but
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/client",
3
- "version": "1.0.0-alpha.65",
3
+ "version": "1.0.0-alpha.67",
4
4
  "description": "Lunora browser SDK: WebSocket transport, optimistic updates, and an offline mutation queue",
5
5
  "keywords": [
6
6
  "cloudflare",