@fabric-harness/sdk 1.13.0 → 2.0.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.
Files changed (169) hide show
  1. package/dist/action.d.ts +69 -0
  2. package/dist/action.d.ts.map +1 -0
  3. package/dist/action.js +119 -0
  4. package/dist/action.js.map +1 -0
  5. package/dist/agent-definition.d.ts +6 -0
  6. package/dist/agent-definition.d.ts.map +1 -1
  7. package/dist/agent-definition.js.map +1 -1
  8. package/dist/agent.d.ts +2 -0
  9. package/dist/agent.d.ts.map +1 -1
  10. package/dist/agent.js +35 -1
  11. package/dist/agent.js.map +1 -1
  12. package/dist/attachment-store-contract.d.ts +34 -0
  13. package/dist/attachment-store-contract.d.ts.map +1 -0
  14. package/dist/attachment-store-contract.js +0 -0
  15. package/dist/attachment-store-contract.js.map +1 -0
  16. package/dist/attachment-store.d.ts +107 -0
  17. package/dist/attachment-store.d.ts.map +1 -0
  18. package/dist/attachment-store.js +164 -0
  19. package/dist/attachment-store.js.map +1 -0
  20. package/dist/channel.d.ts +84 -0
  21. package/dist/channel.d.ts.map +1 -0
  22. package/dist/channel.js +115 -0
  23. package/dist/channel.js.map +1 -0
  24. package/dist/context-budget.d.ts +16 -0
  25. package/dist/context-budget.d.ts.map +1 -1
  26. package/dist/context-budget.js +38 -3
  27. package/dist/context-budget.js.map +1 -1
  28. package/dist/conversation-projection.d.ts +52 -0
  29. package/dist/conversation-projection.d.ts.map +1 -0
  30. package/dist/conversation-projection.js +207 -0
  31. package/dist/conversation-projection.js.map +1 -0
  32. package/dist/conversation-stream-contract.d.ts +37 -0
  33. package/dist/conversation-stream-contract.d.ts.map +1 -0
  34. package/dist/conversation-stream-contract.js +453 -0
  35. package/dist/conversation-stream-contract.js.map +1 -0
  36. package/dist/conversation-stream.d.ts +141 -0
  37. package/dist/conversation-stream.d.ts.map +1 -0
  38. package/dist/conversation-stream.js +159 -0
  39. package/dist/conversation-stream.js.map +1 -0
  40. package/dist/cost-budget.d.ts +106 -1
  41. package/dist/cost-budget.d.ts.map +1 -1
  42. package/dist/cost-budget.js +48 -2
  43. package/dist/cost-budget.js.map +1 -1
  44. package/dist/delivered-message.d.ts +90 -0
  45. package/dist/delivered-message.d.ts.map +1 -0
  46. package/dist/delivered-message.js +154 -0
  47. package/dist/delivered-message.js.map +1 -0
  48. package/dist/dispatch.d.ts +108 -0
  49. package/dist/dispatch.d.ts.map +1 -0
  50. package/dist/dispatch.js +179 -0
  51. package/dist/dispatch.js.map +1 -0
  52. package/dist/error.d.ts +1 -1
  53. package/dist/error.d.ts.map +1 -1
  54. package/dist/error.js.map +1 -1
  55. package/dist/history.d.ts +49 -2
  56. package/dist/history.d.ts.map +1 -1
  57. package/dist/history.js +163 -0
  58. package/dist/history.js.map +1 -1
  59. package/dist/in-memory-submission-store.d.ts +53 -0
  60. package/dist/in-memory-submission-store.d.ts.map +1 -0
  61. package/dist/in-memory-submission-store.js +340 -0
  62. package/dist/in-memory-submission-store.js.map +1 -0
  63. package/dist/index.d.ts +51 -13
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +28 -7
  66. package/dist/index.js.map +1 -1
  67. package/dist/loop.d.ts +29 -3
  68. package/dist/loop.d.ts.map +1 -1
  69. package/dist/loop.js +167 -24
  70. package/dist/loop.js.map +1 -1
  71. package/dist/model.d.ts +37 -0
  72. package/dist/model.d.ts.map +1 -1
  73. package/dist/model.js +250 -79
  74. package/dist/model.js.map +1 -1
  75. package/dist/otel-observer.d.ts +44 -0
  76. package/dist/otel-observer.d.ts.map +1 -0
  77. package/dist/otel-observer.js +165 -0
  78. package/dist/otel-observer.js.map +1 -0
  79. package/dist/persistence.d.ts +70 -0
  80. package/dist/persistence.d.ts.map +1 -0
  81. package/dist/persistence.js +17 -0
  82. package/dist/persistence.js.map +1 -0
  83. package/dist/persistent-agent.d.ts +86 -0
  84. package/dist/persistent-agent.d.ts.map +1 -0
  85. package/dist/persistent-agent.js +75 -0
  86. package/dist/persistent-agent.js.map +1 -0
  87. package/dist/pi-loop-runtime.d.ts.map +1 -1
  88. package/dist/pi-loop-runtime.js +7 -1
  89. package/dist/pi-loop-runtime.js.map +1 -1
  90. package/dist/profile.d.ts +33 -0
  91. package/dist/profile.d.ts.map +1 -0
  92. package/dist/profile.js +10 -0
  93. package/dist/profile.js.map +1 -0
  94. package/dist/providers.d.ts +14 -0
  95. package/dist/providers.d.ts.map +1 -1
  96. package/dist/providers.js +18 -1
  97. package/dist/providers.js.map +1 -1
  98. package/dist/result.d.ts +12 -0
  99. package/dist/result.d.ts.map +1 -1
  100. package/dist/result.js +26 -0
  101. package/dist/result.js.map +1 -1
  102. package/dist/retrieval.d.ts +61 -0
  103. package/dist/retrieval.d.ts.map +1 -0
  104. package/dist/retrieval.js +26 -0
  105. package/dist/retrieval.js.map +1 -0
  106. package/dist/runtime-mode.d.ts +1 -1
  107. package/dist/runtime-mode.d.ts.map +1 -1
  108. package/dist/runtime-mode.js +2 -1
  109. package/dist/runtime-mode.js.map +1 -1
  110. package/dist/scope-key.d.ts +25 -0
  111. package/dist/scope-key.d.ts.map +1 -0
  112. package/dist/scope-key.js +34 -0
  113. package/dist/scope-key.js.map +1 -0
  114. package/dist/session.d.ts +47 -1
  115. package/dist/session.d.ts.map +1 -1
  116. package/dist/session.js +364 -35
  117. package/dist/session.js.map +1 -1
  118. package/dist/skills.d.ts +33 -0
  119. package/dist/skills.d.ts.map +1 -0
  120. package/dist/skills.js +65 -0
  121. package/dist/skills.js.map +1 -0
  122. package/dist/store.d.ts +36 -1
  123. package/dist/store.d.ts.map +1 -1
  124. package/dist/store.js +83 -0
  125. package/dist/store.js.map +1 -1
  126. package/dist/stream-chunks.d.ts +42 -0
  127. package/dist/stream-chunks.d.ts.map +1 -0
  128. package/dist/stream-chunks.js +138 -0
  129. package/dist/stream-chunks.js.map +1 -0
  130. package/dist/strict.d.ts +40 -11
  131. package/dist/strict.d.ts.map +1 -1
  132. package/dist/strict.js +22 -7
  133. package/dist/strict.js.map +1 -1
  134. package/dist/submission-context.d.ts +26 -0
  135. package/dist/submission-context.d.ts.map +1 -0
  136. package/dist/submission-context.js +20 -0
  137. package/dist/submission-context.js.map +1 -0
  138. package/dist/submission-runner.d.ts +150 -0
  139. package/dist/submission-runner.d.ts.map +1 -0
  140. package/dist/submission-runner.js +767 -0
  141. package/dist/submission-runner.js.map +1 -0
  142. package/dist/submission-state.d.ts +50 -0
  143. package/dist/submission-state.d.ts.map +1 -0
  144. package/dist/submission-state.js +82 -0
  145. package/dist/submission-state.js.map +1 -0
  146. package/dist/submission-store-contract.d.ts +31 -0
  147. package/dist/submission-store-contract.d.ts.map +1 -0
  148. package/dist/submission-store-contract.js +730 -0
  149. package/dist/submission-store-contract.js.map +1 -0
  150. package/dist/submission-store.d.ts +365 -0
  151. package/dist/submission-store.d.ts.map +1 -0
  152. package/dist/submission-store.js +191 -0
  153. package/dist/submission-store.js.map +1 -0
  154. package/dist/submission-telemetry.d.ts +56 -0
  155. package/dist/submission-telemetry.d.ts.map +1 -0
  156. package/dist/submission-telemetry.js +36 -0
  157. package/dist/submission-telemetry.js.map +1 -0
  158. package/dist/testing-contracts.d.ts +17 -0
  159. package/dist/testing-contracts.d.ts.map +1 -0
  160. package/dist/testing-contracts.js +14 -0
  161. package/dist/testing-contracts.js.map +1 -0
  162. package/dist/tools.d.ts +32 -4
  163. package/dist/tools.d.ts.map +1 -1
  164. package/dist/tools.js +132 -6
  165. package/dist/tools.js.map +1 -1
  166. package/dist/types.d.ts +132 -3
  167. package/dist/types.d.ts.map +1 -1
  168. package/dist/types.js.map +1 -1
  169. package/package.json +16 -8
@@ -0,0 +1,207 @@
1
+ import { ConversationStreamStoreError, conversationStreamPath, } from './conversation-stream.js';
2
+ /**
3
+ * Wrap a {@link SessionStore} so active-path appends are mirrored into an
4
+ * append-only {@link ConversationStreamStore} projection (v2 A4).
5
+ *
6
+ * The SessionEntry DAG stays the single source of truth; the stream gives
7
+ * clients offset-based catch-up + live tail. Two rules keep them coherent:
8
+ *
9
+ * 1. **Idempotent by entryId** — a crash between the DAG write and the
10
+ * stream write is repaired on the next append: the projector diffs the
11
+ * stream tail against the active path and re-emits anything missing.
12
+ * 2. **Truncation is explicit** — the DAG can branch (fork/replay/
13
+ * checkpoint-restore rewrite `leafId`); the stream cannot. When `save()`
14
+ * rewinds the active path, the projector appends a `truncated` record
15
+ * and re-acquires the producer (epoch bump), so tailing clients see the
16
+ * branch switch instead of silently reading a stale path.
17
+ *
18
+ * Projection failures are logged and swallowed — the conversation stream is
19
+ * an observability surface and must never fail the session write itself;
20
+ * the diff-repair on the next append restores consistency.
21
+ */
22
+ export function withConversationProjection(store, streams, options = {}) {
23
+ const projector = new ConversationProjector(streams, options);
24
+ const wrapped = {
25
+ ...store,
26
+ load: (id) => store.load(id),
27
+ save: async (data) => {
28
+ await store.save(data);
29
+ await projector.projectSave(data);
30
+ },
31
+ };
32
+ if (store.appendEntry) {
33
+ wrapped.appendEntry = async (sessionId, entry) => {
34
+ await store.appendEntry?.(sessionId, entry);
35
+ await projector.projectAppend(store, sessionId, entry);
36
+ };
37
+ }
38
+ if (store.delete) {
39
+ wrapped.delete = async (sessionId) => {
40
+ await store.delete?.(sessionId);
41
+ await projector.deleteStream(sessionId);
42
+ };
43
+ }
44
+ return wrapped;
45
+ }
46
+ export class ConversationProjector {
47
+ streams;
48
+ producerId;
49
+ onError;
50
+ producers = new Map();
51
+ constructor(streams, options = {}) {
52
+ this.streams = streams;
53
+ this.producerId = options.producerId ?? `projector-${Math.random().toString(16).slice(2)}`;
54
+ this.onError = options.onError ?? ((error) => {
55
+ console.error('[fabric-harness:conversation-projection] projection failed:', error);
56
+ });
57
+ }
58
+ /** Mirror one appended entry, repairing any missed backlog first. */
59
+ async projectAppend(store, sessionId, entry) {
60
+ try {
61
+ const producer = await this.ensureProducer(sessionId);
62
+ // Fast path: this entry directly extends the projected tail.
63
+ const last = producer.projectedEntryIds[producer.projectedEntryIds.length - 1];
64
+ if (entry.parentId && entry.parentId === last) {
65
+ await this.appendRecords(sessionId, producer, [{ kind: 'entry', entry }], [entry.id]);
66
+ return;
67
+ }
68
+ // Slow path: reproject from the session's current active path (covers
69
+ // missed appends, first projection of an existing session, and forks).
70
+ const data = await store.load(sessionId);
71
+ if (!data)
72
+ return;
73
+ await this.reproject(sessionId, producer, data);
74
+ }
75
+ catch (error) {
76
+ this.onError(error);
77
+ }
78
+ }
79
+ /** Handle whole-document saves (fork/replay/truncation rewrite the path). */
80
+ async projectSave(data) {
81
+ try {
82
+ const producer = await this.ensureProducer(data.id);
83
+ await this.reproject(data.id, producer, data);
84
+ }
85
+ catch (error) {
86
+ this.onError(error);
87
+ }
88
+ }
89
+ async deleteStream(sessionId) {
90
+ try {
91
+ await this.streams.delete(conversationStreamPath(sessionId));
92
+ this.producers.delete(sessionId);
93
+ }
94
+ catch (error) {
95
+ this.onError(error);
96
+ }
97
+ }
98
+ async ensureProducer(sessionId) {
99
+ const existing = this.producers.get(sessionId);
100
+ if (existing)
101
+ return existing;
102
+ const path = conversationStreamPath(sessionId);
103
+ await this.streams.createStream(path, { storeSessionId: sessionId });
104
+ const claim = await this.streams.acquireProducer(path, this.producerId);
105
+ const state = {
106
+ producerId: claim.producerId,
107
+ producerEpoch: claim.producerEpoch,
108
+ nextProducerSequence: claim.nextProducerSequence,
109
+ // Durable stream stores outlive this process: rebuild what has already
110
+ // been projected from the stream itself, otherwise the first
111
+ // post-restart diff would re-emit the entire path as duplicates.
112
+ projectedEntryIds: await this.readProjectedEntryIds(path),
113
+ };
114
+ this.producers.set(sessionId, state);
115
+ return state;
116
+ }
117
+ /** Fold the stream into the currently-projected entry ids (truncations rewind). */
118
+ async readProjectedEntryIds(path) {
119
+ const projected = [];
120
+ let offset;
121
+ for (;;) {
122
+ const result = await this.streams.read(path, { ...(offset !== undefined ? { offset } : {}), limit: 1000 });
123
+ for (const batch of result.batches) {
124
+ for (const record of batch.records) {
125
+ if (record.kind === 'entry') {
126
+ projected.push(record.entry.id);
127
+ }
128
+ else {
129
+ const keep = record.rewoundTo ? projected.indexOf(record.rewoundTo) + 1 : 0;
130
+ projected.length = keep;
131
+ }
132
+ }
133
+ }
134
+ if (result.upToDate)
135
+ return projected;
136
+ offset = result.nextOffset;
137
+ }
138
+ }
139
+ /**
140
+ * Diff the projected tail against the current active path. A pure
141
+ * extension appends the missing suffix; a divergence appends a
142
+ * `truncated` record (with a fresh producer epoch) then the new suffix.
143
+ */
144
+ async reproject(sessionId, producer, data) {
145
+ const path = activePath(data);
146
+ const pathIds = path.map((entry) => entry.id);
147
+ const projected = producer.projectedEntryIds;
148
+ let common = 0;
149
+ while (common < projected.length && common < pathIds.length && projected[common] === pathIds[common]) {
150
+ common += 1;
151
+ }
152
+ const records = [];
153
+ if (common < projected.length) {
154
+ // The active path diverged from what we already emitted — branch switch.
155
+ const newLeaf = pathIds[pathIds.length - 1] ?? '';
156
+ const rewoundTo = common > 0 ? projected[common - 1] ?? '' : '';
157
+ records.push({ kind: 'truncated', rewoundTo, newLeafId: newLeaf, reason: 'active-path-rewound' });
158
+ const claim = await this.streams.acquireProducer(conversationStreamPath(sessionId), this.producerId);
159
+ producer.producerEpoch = claim.producerEpoch;
160
+ producer.nextProducerSequence = claim.nextProducerSequence;
161
+ }
162
+ for (const entry of path.slice(common)) {
163
+ records.push({ kind: 'entry', entry });
164
+ }
165
+ if (records.length === 0)
166
+ return;
167
+ await this.appendRecords(sessionId, producer, records, pathIds);
168
+ }
169
+ async appendRecords(sessionId, producer, records, projectedIds) {
170
+ try {
171
+ await this.streams.append({
172
+ path: conversationStreamPath(sessionId),
173
+ producerId: producer.producerId,
174
+ producerEpoch: producer.producerEpoch,
175
+ producerSequence: producer.nextProducerSequence,
176
+ records,
177
+ });
178
+ producer.nextProducerSequence += 1;
179
+ producer.projectedEntryIds =
180
+ records.length === 1 && records[0]?.kind === 'entry'
181
+ ? [...producer.projectedEntryIds, ...projectedIds.slice(-1)]
182
+ : projectedIds;
183
+ }
184
+ catch (error) {
185
+ if (error instanceof ConversationStreamStoreError && error.code === 'PRODUCER_FENCED') {
186
+ // Another projector took over (multi-writer window). Drop local
187
+ // state; the next append re-acquires and diff-repairs.
188
+ this.producers.delete(sessionId);
189
+ return;
190
+ }
191
+ throw error;
192
+ }
193
+ }
194
+ }
195
+ /** Compute the active (leaf-rooted) path of a SessionData snapshot. */
196
+ function activePath(data) {
197
+ const entries = data.entries ?? [];
198
+ const byId = new Map(entries.map((entry) => [entry.id, entry]));
199
+ const path = [];
200
+ let current = data.leafId ? byId.get(data.leafId) : entries[entries.length - 1];
201
+ while (current) {
202
+ path.push(current);
203
+ current = current.parentId ? byId.get(current.parentId) : undefined;
204
+ }
205
+ return path.reverse();
206
+ }
207
+ //# sourceMappingURL=conversation-projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-projection.js","sourceRoot":"","sources":["../src/conversation-projection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAOlC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,0BAA0B,CACxC,KAAmB,EACnB,OAAgC,EAChC,UAAuE,EAAE;IAEzE,MAAM,SAAS,GAAG,IAAI,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE9D,MAAM,OAAO,GAAiB;QAC5B,GAAG,KAAK;QACR,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACnB,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;IAEF,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,OAAO,CAAC,WAAW,GAAG,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE;YAC/C,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC5C,MAAM,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QACzD,CAAC,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,GAAG,KAAK,EAAE,SAAS,EAAE,EAAE;YACnC,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,SAAS,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC1C,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAUD,MAAM,OAAO,qBAAqB;IAMb;IALF,UAAU,CAAS;IACnB,OAAO,CAA2B;IAClC,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;IAE9D,YACmB,OAAgC,EACjD,UAAuE,EAAE;QADxD,YAAO,GAAP,OAAO,CAAyB;QAGjD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,aAAa,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YAC3C,OAAO,CAAC,KAAK,CAAC,6DAA6D,EAAE,KAAK,CAAC,CAAC;QACtF,CAAC,CAAC,CAAC;IACL,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,aAAa,CAAC,KAAmB,EAAE,SAAiB,EAAE,KAAmB;QAC7E,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YACtD,6DAA6D;YAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,iBAAiB,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/E,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAC9C,MAAM,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;gBACtF,OAAO;YACT,CAAC;YACD,sEAAsE;YACtE,uEAAuE;YACvE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzC,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,WAAW,CAAC,IAAiB;QACjC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpD,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,SAAiB;QAClC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,CAAC;YAC7D,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,SAAiB;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,IAAI,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACxE,MAAM,KAAK,GAAkB;YAC3B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;YAChD,uEAAuE;YACvE,6DAA6D;YAC7D,iEAAiE;YACjE,iBAAiB,EAAE,MAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC;SAC1D,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACrC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mFAAmF;IAC3E,KAAK,CAAC,qBAAqB,CAAC,IAAY;QAC9C,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,IAAI,MAA0B,CAAC;QAC/B,SAAS,CAAC;YACR,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3G,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBACnC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;wBAC5B,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAClC,CAAC;yBAAM,CAAC;wBACN,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC5E,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC;oBAC1B,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,MAAM,CAAC,QAAQ;gBAAE,OAAO,SAAS,CAAC;YACtC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;QAC7B,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,SAAS,CAAC,SAAiB,EAAE,QAAuB,EAAE,IAAiB;QACnF,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,QAAQ,CAAC,iBAAiB,CAAC;QAE7C,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACrG,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAA+B,EAAE,CAAC;QAC/C,IAAI,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;YAC9B,yEAAyE;YACzE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAClD,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;YAClG,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YACrG,QAAQ,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;YAC7C,QAAQ,CAAC,oBAAoB,GAAG,KAAK,CAAC,oBAAoB,CAAC;QAC7D,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACjC,MAAM,IAAI,CAAC,aAAa,CACtB,SAAS,EACT,QAAQ,EACR,OAAO,EACP,OAAO,CACR,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,SAAiB,EACjB,QAAuB,EACvB,OAAmC,EACnC,YAAsB;QAEtB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;gBACxB,IAAI,EAAE,sBAAsB,CAAC,SAAS,CAAC;gBACvC,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,gBAAgB,EAAE,QAAQ,CAAC,oBAAoB;gBAC/C,OAAO;aACR,CAAC,CAAC;YACH,QAAQ,CAAC,oBAAoB,IAAI,CAAC,CAAC;YACnC,QAAQ,CAAC,iBAAiB;gBACxB,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO;oBAClD,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,iBAAiB,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC5D,CAAC,CAAC,YAAY,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,4BAA4B,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBACtF,gEAAgE;gBAChE,uDAAuD;gBACvD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBACjC,OAAO;YACT,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAED,uEAAuE;AACvE,SAAS,UAAU,CAAC,IAAiB;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,IAAI,GAAmB,EAAE,CAAC;IAChC,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAChF,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnB,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtE,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;AACxB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared contract tests for {@link ConversationStreamStore} implementations.
3
+ *
4
+ * Store packages call {@link defineConversationStreamStoreContractTests} with
5
+ * a factory that creates their backend. The tests exercise every method on
6
+ * `ConversationStreamStore` with identical behavioral assertions regardless of
7
+ * the underlying storage engine — batch atomicity, producer fencing via
8
+ * epochs, idempotent redelivery, and offset catch-up reads.
9
+ *
10
+ * `subscribe` is a process-local notification seam: the suite only asserts
11
+ * that appends made through the same store instance notify local listeners
12
+ * and that unsubscribing stops further notifications. Cross-process fan-out
13
+ * is deliberately out of contract — backends may no-op it.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { defineConversationStreamStoreContractTests } from '@fabric-harness/sdk/testing/contracts';
18
+ *
19
+ * defineConversationStreamStoreContractTests('My backend', async () => ({
20
+ * store: await createMyStreamStore(),
21
+ * close: async () => myBackend.close(),
22
+ * }));
23
+ * ```
24
+ */
25
+ import type { ConversationStreamStore } from './conversation-stream.js';
26
+ export interface ConversationStreamStoreContractHandle {
27
+ /** The fresh store under test. */
28
+ store: ConversationStreamStore;
29
+ /** Optional cleanup after the test (close connections, delete temp files). */
30
+ close?: () => Promise<void>;
31
+ }
32
+ /**
33
+ * Register the standard {@link ConversationStreamStore} contract tests under
34
+ * the given describe label. Each test gets a fresh store from `factory()`.
35
+ */
36
+ export declare function defineConversationStreamStoreContractTests(name: string, factory: () => Promise<ConversationStreamStoreContractHandle>): void;
37
+ //# sourceMappingURL=conversation-stream-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-stream-contract.d.ts","sourceRoot":"","sources":["../src/conversation-stream-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAEV,uBAAuB,EAExB,MAAM,0BAA0B,CAAC;AAoClC,MAAM,WAAW,qCAAqC;IACpD,kCAAkC;IAClC,KAAK,EAAE,uBAAuB,CAAC;IAC/B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,0CAA0C,CACxD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,OAAO,CAAC,qCAAqC,CAAC,GAC5D,IAAI,CAmdN"}