dsh-realtime 0.2.3 → 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 +18 -0
- package/lib/journal.d.ts.map +1 -1
- package/lib/journal.js +31 -0
- package/lib/journal.js.map +1 -1
- package/lib/types.d.ts +24 -0
- package/lib/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/journal.ts +32 -0
- package/src/types.ts +25 -0
package/lib/journal.d.ts
CHANGED
|
@@ -51,6 +51,8 @@ export type JournalKind =
|
|
|
51
51
|
| 'answer.received'
|
|
52
52
|
/** A context append was acknowledged on the wire. Not delivery — see invariant 6. */
|
|
53
53
|
| 'append.acknowledged'
|
|
54
|
+
/** A narrated step the provider did not take. Not an answer failure — a step nobody will hear. */
|
|
55
|
+
| 'progress.dropped'
|
|
54
56
|
/** Audio was handed to the transport. **Not** a claim that anyone heard it. */
|
|
55
57
|
| 'speech.sent'
|
|
56
58
|
/** The configuration as resolved, so a journal can be read without the profile beside it. */
|
|
@@ -105,6 +107,7 @@ export declare class Journal {
|
|
|
105
107
|
private readonly capacity;
|
|
106
108
|
private readonly secrets;
|
|
107
109
|
private readonly entries;
|
|
110
|
+
private readonly sinks;
|
|
108
111
|
private nextSeq;
|
|
109
112
|
/**
|
|
110
113
|
* @param options - capacity and the values that must never be retained.
|
|
@@ -123,6 +126,21 @@ export declare class Journal {
|
|
|
123
126
|
* @param values - secrets to add; empty and duplicate values are ignored.
|
|
124
127
|
*/
|
|
125
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;
|
|
126
144
|
/**
|
|
127
145
|
* Redact and retain one entry, evicting the oldest when the buffer is full.
|
|
128
146
|
* @param kind - what happened.
|
package/lib/journal.d.ts.map
CHANGED
|
@@ -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,+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,
|
|
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
|
/**
|
package/lib/journal.js.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"journal.js","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"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"}
|
package/lib/types.d.ts
CHANGED
|
@@ -213,4 +213,28 @@ export interface RealtimeDelegationSettlement {
|
|
|
213
213
|
/** The controller's own reason, redacted, when the outcome is `refused`. */
|
|
214
214
|
readonly reason?: string;
|
|
215
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* One progress step of a delegated turn, on its way to an ear or to the model's own context.
|
|
218
|
+
*
|
|
219
|
+
* The vocabulary of a **narration**, not of the protocol: the provider's append is the transport, and this
|
|
220
|
+
* is what a plugin says through it. `channel` reuses the distinction the seam already carries on an answer
|
|
221
|
+
* — `commentary` is spoken aloud, `thinking` is context the model may use without saying it — because
|
|
222
|
+
* "spoken for milestones, silent for chatter" is a choice about that one field.
|
|
223
|
+
*
|
|
224
|
+
* Deliberately carries **no tool arguments, ever**. A step is derived from the tool's own *name* against a
|
|
225
|
+
* configured phrase table; a tool's raw arguments are model-authored text, and the only model-authored text
|
|
226
|
+
* that may reach a user's ear is the answer, which is redacted on the way out.
|
|
227
|
+
*
|
|
228
|
+
* How long the window lasts, and why a step is placed at all, is measured in
|
|
229
|
+
* [`usable-window.md`](https://github.com/Travizm/dsh-openai-live/blob/main/docs/usable-window.md): a step
|
|
230
|
+
* is placed while the session's timeline advances, which is while the client's microphone is streaming.
|
|
231
|
+
*/
|
|
232
|
+
export interface RealtimeDelegationProgress {
|
|
233
|
+
/** The delegation this step belongs to. A step for an id nobody is waiting on is dropped. */
|
|
234
|
+
readonly id: string;
|
|
235
|
+
/** `commentary` is spoken; `thinking` is context the model may keep to itself. */
|
|
236
|
+
readonly channel: 'commentary' | 'thinking';
|
|
237
|
+
/** The words — authored by configuration, never by the model. */
|
|
238
|
+
readonly text: string;
|
|
239
|
+
}
|
|
216
240
|
//# sourceMappingURL=types.d.ts.map
|
package/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/journal.ts
CHANGED
|
@@ -55,6 +55,8 @@ export type JournalKind =
|
|
|
55
55
|
| 'answer.received'
|
|
56
56
|
/** A context append was acknowledged on the wire. Not delivery — see invariant 6. */
|
|
57
57
|
| 'append.acknowledged'
|
|
58
|
+
/** A narrated step the provider did not take. Not an answer failure — a step nobody will hear. */
|
|
59
|
+
| 'progress.dropped'
|
|
58
60
|
/** Audio was handed to the transport. **Not** a claim that anyone heard it. */
|
|
59
61
|
| 'speech.sent'
|
|
60
62
|
/** The configuration as resolved, so a journal can be read without the profile beside it. */
|
|
@@ -112,6 +114,7 @@ export class Journal {
|
|
|
112
114
|
private readonly capacity: number
|
|
113
115
|
private readonly secrets: string[]
|
|
114
116
|
private readonly entries: JournalEntry[] = []
|
|
117
|
+
private readonly sinks: ((entry: JournalEntry) => void)[] = []
|
|
115
118
|
private nextSeq = 1
|
|
116
119
|
|
|
117
120
|
/**
|
|
@@ -145,6 +148,25 @@ export class Journal {
|
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
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
|
+
|
|
148
170
|
/**
|
|
149
171
|
* Redact and retain one entry, evicting the oldest when the buffer is full.
|
|
150
172
|
* @param kind - what happened.
|
|
@@ -167,6 +189,16 @@ export class Journal {
|
|
|
167
189
|
// `shift()` on a bounded array: the buffer is capped, so this stays O(capacity) at worst and
|
|
168
190
|
// the memory ceiling is a property of the type rather than of the caller's discipline.
|
|
169
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
|
+
}
|
|
170
202
|
return entry
|
|
171
203
|
}
|
|
172
204
|
|
package/src/types.ts
CHANGED
|
@@ -234,3 +234,28 @@ export interface RealtimeDelegationSettlement {
|
|
|
234
234
|
/** The controller's own reason, redacted, when the outcome is `refused`. */
|
|
235
235
|
readonly reason?: string
|
|
236
236
|
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* One progress step of a delegated turn, on its way to an ear or to the model's own context.
|
|
240
|
+
*
|
|
241
|
+
* The vocabulary of a **narration**, not of the protocol: the provider's append is the transport, and this
|
|
242
|
+
* is what a plugin says through it. `channel` reuses the distinction the seam already carries on an answer
|
|
243
|
+
* — `commentary` is spoken aloud, `thinking` is context the model may use without saying it — because
|
|
244
|
+
* "spoken for milestones, silent for chatter" is a choice about that one field.
|
|
245
|
+
*
|
|
246
|
+
* Deliberately carries **no tool arguments, ever**. A step is derived from the tool's own *name* against a
|
|
247
|
+
* configured phrase table; a tool's raw arguments are model-authored text, and the only model-authored text
|
|
248
|
+
* that may reach a user's ear is the answer, which is redacted on the way out.
|
|
249
|
+
*
|
|
250
|
+
* How long the window lasts, and why a step is placed at all, is measured in
|
|
251
|
+
* [`usable-window.md`](https://github.com/Travizm/dsh-openai-live/blob/main/docs/usable-window.md): a step
|
|
252
|
+
* is placed while the session's timeline advances, which is while the client's microphone is streaming.
|
|
253
|
+
*/
|
|
254
|
+
export interface RealtimeDelegationProgress {
|
|
255
|
+
/** The delegation this step belongs to. A step for an id nobody is waiting on is dropped. */
|
|
256
|
+
readonly id: string
|
|
257
|
+
/** `commentary` is spoken; `thinking` is context the model may keep to itself. */
|
|
258
|
+
readonly channel: 'commentary' | 'thinking'
|
|
259
|
+
/** The words — authored by configuration, never by the model. */
|
|
260
|
+
readonly text: string
|
|
261
|
+
}
|