dsh-realtime 0.2.4 → 0.2.5

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/lib/journal.d.ts CHANGED
@@ -107,6 +107,7 @@ export declare class Journal {
107
107
  private readonly capacity;
108
108
  private readonly secrets;
109
109
  private readonly entries;
110
+ private readonly sinks;
110
111
  private nextSeq;
111
112
  /**
112
113
  * @param options - capacity and the values that must never be retained.
@@ -125,6 +126,21 @@ export declare class Journal {
125
126
  * @param values - secrets to add; empty and duplicate values are ignored.
126
127
  */
127
128
  addSecrets(values: readonly string[]): void;
129
+ /**
130
+ * Send every entry, as it is recorded, to somewhere else as well.
131
+ *
132
+ * The journal itself stays I/O-free on purpose — it is a plain object a test can construct and a route can
133
+ * serve — so persistence is a *sink* the caller supplies rather than something this class does. Additive,
134
+ * for the same reason `addSecrets` is: sinks arrive with the plugins that want them, and plugins load in no
135
+ * guaranteed order.
136
+ *
137
+ * **A sink cannot break the record.** It is called inside a guard, so a sink that throws — a full disk, a
138
+ * path that does not exist, a bug in the caller's own writer — costs the copy and never the entry. A
139
+ * diagnostic mechanism that can lose the diagnostic is worse than none, because it fails exactly when it is
140
+ * needed.
141
+ * @param sink - called with each entry, oldest to newest, in the order they were recorded.
142
+ */
143
+ onEntry(sink: (entry: JournalEntry) => void): void;
128
144
  /**
129
145
  * Redact and retain one entry, evicting the oldest when the buffer is full.
130
146
  * @param kind - what happened.
@@ -1 +1 @@
1
- {"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,6DAA6D;AAC7D,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAE3C;;;;;GAKG;AACH,MAAM,MAAM,WAAW;AACrB,6DAA6D;AAC3D,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB;AACxD;;;;;;GAMG;GACD,iBAAiB,GAAG,iBAAiB,GAAG,eAAe;AACzD,0EAA0E;GACxE,iBAAiB;AACnB,6FAA6F;GAC3F,iBAAiB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,gBAAgB;AAC7E,iCAAiC;GAC/B,iBAAiB;AACnB,qFAAqF;GACnF,qBAAqB;AACvB,kGAAkG;GAChG,kBAAkB;AACpB,+EAA+E;GAC7E,aAAa;AACf,6FAA6F;GAC3F,iBAAiB;AACnB;;;;;;;GAOG;GACD,gBAAgB,CAAA;AAEpB,0BAA0B;AAC1B,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,qBAAqB;IACrB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,uFAAuF;IACvF,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAClD;AAED,oCAAoC;AACpC,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC5B;AAED;;;;;;GAMG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,OAAO,CAAI;IAEnB;;;;OAIG;IACH,YAAY,OAAO,GAAE,cAAmB,EAOvC;IAED;;;;;;;;;OASG;IACH,UAAU,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAK1C;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EAAE,EAAE,GAAE,MAAmB,GAAG,YAAY,CAgB9G;IAED;;;;;;OAMG;IACH,QAAQ,IAAI,YAAY,EAAE,CAEzB;IAED,kCAAkC;IAClC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,+EAA+E;IAC/E,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAElC;CACF"}
1
+ {"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,6DAA6D;AAC7D,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAE3C;;;;;GAKG;AACH,MAAM,MAAM,WAAW;AACrB,6DAA6D;AAC3D,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB;AACxD;;;;;;GAMG;GACD,iBAAiB,GAAG,iBAAiB,GAAG,eAAe;AACzD,0EAA0E;GACxE,iBAAiB;AACnB,6FAA6F;GAC3F,iBAAiB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,gBAAgB;AAC7E,iCAAiC;GAC/B,iBAAiB;AACnB,qFAAqF;GACnF,qBAAqB;AACvB,kGAAkG;GAChG,kBAAkB;AACpB,+EAA+E;GAC7E,aAAa;AACf,6FAA6F;GAC3F,iBAAiB;AACnB;;;;;;;GAOG;GACD,gBAAgB,CAAA;AAEpB,0BAA0B;AAC1B,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,qBAAqB;IACrB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,uFAAuF;IACvF,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAClD;AAED,oCAAoC;AACpC,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC5B;AAED;;;;;;GAMG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwC;IAC9D,OAAO,CAAC,OAAO,CAAI;IAEnB;;;;OAIG;IACH,YAAY,OAAO,GAAE,cAAmB,EAOvC;IAED;;;;;;;;;OASG;IACH,UAAU,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAK1C;IAED;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI,CAGjD;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EAAE,EAAE,GAAE,MAAmB,GAAG,YAAY,CA0B9G;IAED;;;;;;OAMG;IACH,QAAQ,IAAI,YAAY,EAAE,CAEzB;IAED,kCAAkC;IAClC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,+EAA+E;IAC/E,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAElC;CACF"}
package/lib/journal.js CHANGED
@@ -38,6 +38,7 @@ export class Journal {
38
38
  capacity;
39
39
  secrets;
40
40
  entries = [];
41
+ sinks = [];
41
42
  nextSeq = 1;
42
43
  /**
43
44
  * @param options - capacity and the values that must never be retained.
@@ -70,6 +71,25 @@ export class Journal {
70
71
  this.secrets.push(value);
71
72
  }
72
73
  }
74
+ /**
75
+ * Send every entry, as it is recorded, to somewhere else as well.
76
+ *
77
+ * The journal itself stays I/O-free on purpose — it is a plain object a test can construct and a route can
78
+ * serve — so persistence is a *sink* the caller supplies rather than something this class does. Additive,
79
+ * for the same reason `addSecrets` is: sinks arrive with the plugins that want them, and plugins load in no
80
+ * guaranteed order.
81
+ *
82
+ * **A sink cannot break the record.** It is called inside a guard, so a sink that throws — a full disk, a
83
+ * path that does not exist, a bug in the caller's own writer — costs the copy and never the entry. A
84
+ * diagnostic mechanism that can lose the diagnostic is worse than none, because it fails exactly when it is
85
+ * needed.
86
+ * @param sink - called with each entry, oldest to newest, in the order they were recorded.
87
+ */
88
+ onEntry(sink) {
89
+ if (typeof sink !== 'function')
90
+ return;
91
+ this.sinks.push(sink);
92
+ }
73
93
  /**
74
94
  * Redact and retain one entry, evicting the oldest when the buffer is full.
75
95
  * @param kind - what happened.
@@ -93,6 +113,17 @@ export class Journal {
93
113
  // the memory ceiling is a property of the type rather than of the caller's discipline.
94
114
  while (this.entries.length > this.capacity)
95
115
  this.entries.shift();
116
+ for (const sink of this.sinks) {
117
+ try {
118
+ sink(entry);
119
+ }
120
+ catch {
121
+ // Deliberately swallowed: see `onEntry`. The entry is already retained, so a broken sink costs the
122
+ // copy and not the record — and re-throwing here would let a diagnostics sink take down the path it
123
+ // was added to illuminate. This guard is proven able to fail: remove it and `journal-sink.spec.ts`
124
+ // reports a lost entry.
125
+ }
126
+ }
96
127
  return entry;
97
128
  }
98
129
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"journal.js","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,6DAA6D;AAC7D,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AA2E3C;;;;;;GAMG;AACH,MAAM,OAAO,OAAO;IACD,QAAQ,CAAQ;IAChB,OAAO,CAAU;IACjB,OAAO,GAAmB,EAAE,CAAA;IACrC,OAAO,GAAG,CAAC,CAAA;IAEnB;;;;OAIG;IACH,YAAY,OAAO,GAAmB,EAAE;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,wBAAwB,CAAA;QAC7D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,UAAU,CAAC,yDAAyD,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QACnG,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC;IAED;;;;;;;;;OASG;IACH,UAAU,CAAC,MAAyB;QAClC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAQ;YAC7D,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAiB,EAAE,MAAM,GAAqC,EAAE,EAAE,EAAE,GAAW,IAAI,CAAC,GAAG,EAAE;QAC9F,MAAM,IAAI,GAA2B,EAAE,CAAA;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACzC,CAAC;QACD,MAAM,KAAK,GAAiB,MAAM,CAAC,MAAM,CAAC;YACxC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE;YACnB,EAAE;YACF,IAAI;YACJ,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;SAC5B,CAAC,CAAA;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACxB,6FAA6F;QAC7F,uFAAuF;QACvF,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QAChE,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;;OAMG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAA;IAC/E,CAAC;IAED,kCAAkC;IAClC,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAA;IAC5B,CAAC;IAED,+EAA+E;IAC/E,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAA;IAC7B,CAAC;CACF"}
1
+ {"version":3,"file":"journal.js","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-realtime",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Realtime voice capability seam for DeepSeek Harness: a provider registry plus the session adapter base.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
package/src/journal.ts CHANGED
@@ -114,6 +114,7 @@ export class Journal {
114
114
  private readonly capacity: number
115
115
  private readonly secrets: string[]
116
116
  private readonly entries: JournalEntry[] = []
117
+ private readonly sinks: ((entry: JournalEntry) => void)[] = []
117
118
  private nextSeq = 1
118
119
 
119
120
  /**
@@ -147,6 +148,25 @@ export class Journal {
147
148
  }
148
149
  }
149
150
 
151
+ /**
152
+ * Send every entry, as it is recorded, to somewhere else as well.
153
+ *
154
+ * The journal itself stays I/O-free on purpose — it is a plain object a test can construct and a route can
155
+ * serve — so persistence is a *sink* the caller supplies rather than something this class does. Additive,
156
+ * for the same reason `addSecrets` is: sinks arrive with the plugins that want them, and plugins load in no
157
+ * guaranteed order.
158
+ *
159
+ * **A sink cannot break the record.** It is called inside a guard, so a sink that throws — a full disk, a
160
+ * path that does not exist, a bug in the caller's own writer — costs the copy and never the entry. A
161
+ * diagnostic mechanism that can lose the diagnostic is worse than none, because it fails exactly when it is
162
+ * needed.
163
+ * @param sink - called with each entry, oldest to newest, in the order they were recorded.
164
+ */
165
+ onEntry(sink: (entry: JournalEntry) => void): void {
166
+ if (typeof sink !== 'function') return
167
+ this.sinks.push(sink)
168
+ }
169
+
150
170
  /**
151
171
  * Redact and retain one entry, evicting the oldest when the buffer is full.
152
172
  * @param kind - what happened.
@@ -169,6 +189,16 @@ export class Journal {
169
189
  // `shift()` on a bounded array: the buffer is capped, so this stays O(capacity) at worst and
170
190
  // the memory ceiling is a property of the type rather than of the caller's discipline.
171
191
  while (this.entries.length > this.capacity) this.entries.shift()
192
+ for (const sink of this.sinks) {
193
+ try {
194
+ sink(entry)
195
+ } catch {
196
+ // Deliberately swallowed: see `onEntry`. The entry is already retained, so a broken sink costs the
197
+ // copy and not the record — and re-throwing here would let a diagnostics sink take down the path it
198
+ // was added to illuminate. This guard is proven able to fail: remove it and `journal-sink.spec.ts`
199
+ // reports a lost entry.
200
+ }
201
+ }
172
202
  return entry
173
203
  }
174
204