@inferencesh/app 0.1.14 → 0.1.15

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.ts CHANGED
@@ -2,7 +2,7 @@ export { File } from "./file.js";
2
2
  export type { FileOptions, FileData } from "./file.js";
3
3
  export { createFileSchema, isFileSchema, FILE_SCHEMA_MARKER } from "./schema.js";
4
4
  export type { Socket, Frame } from "./socket.js";
5
- export { createStreamSchema, media, pcm16, Live, liveFields, binaryField, STREAM_SCHEMA_MARKER, BINARY_SCHEMA_MARKER, } from "./stream.js";
5
+ export { createStreamSchema, media, pcm16, Live, liveFields, binaryField, STREAM_SCHEMA_MARKER, CLEAR_KEY, BINARY_SCHEMA_MARKER, } from "./stream.js";
6
6
  export type { Update } from "./stream.js";
7
7
  export { StorageDir, ensureDir } from "./storage.js";
8
8
  export type { StorageDirValue } from "./storage.js";
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  export { File } from "./file.js";
3
3
  // Zod schema utilities
4
4
  export { createFileSchema, isFileSchema, FILE_SCHEMA_MARKER } from "./schema.js";
5
- export { createStreamSchema, media, pcm16, Live, liveFields, binaryField, STREAM_SCHEMA_MARKER, BINARY_SCHEMA_MARKER, } from "./stream.js";
5
+ export { createStreamSchema, media, pcm16, Live, liveFields, binaryField, STREAM_SCHEMA_MARKER, CLEAR_KEY, BINARY_SCHEMA_MARKER, } from "./stream.js";
6
6
  // Storage directories
7
7
  export { StorageDir, ensureDir } from "./storage.js";
8
8
  // Download utility
package/dist/stream.d.ts CHANGED
@@ -51,6 +51,11 @@ import type { Socket } from "./socket.js";
51
51
  * The kernel's zodToJsonSchema reads this and emits `format: "stream"`.
52
52
  */
53
53
  export declare const STREAM_SCHEMA_MARKER: unique symbol;
54
+ /**
55
+ * A control frame, `{"$clear": "audio"}`: drop what has been buffered of a
56
+ * live output field. Reserved keys start with `$`, which no field name can.
57
+ */
58
+ export declare const CLEAR_KEY = "$clear";
54
59
  /**
55
60
  * Marks a binary item schema. The value on `_def` is the content type.
56
61
  * The kernel's zodToJsonSchema reads this and emits
@@ -127,6 +132,8 @@ export declare class Live {
127
132
  private readonly inBinary;
128
133
  private readonly outShape;
129
134
  private readonly outBinary;
135
+ private readonly outLive;
136
+ private refusedBinary;
130
137
  constructor(socket: Socket, inputData: Record<string, unknown>, inputSchema: any, outputSchema: any);
131
138
  [Symbol.asyncIterator](): AsyncGenerator<Update, void, undefined>;
132
139
  private frames;
@@ -140,5 +147,10 @@ export declare class Live {
140
147
  * `await live.send({ effect: "echo" })` are JSON frames. Keys in one call
141
148
  * other than the binary field go out together as one JSON frame.
142
149
  */
150
+ /**
151
+ * Tell the caller to drop what it has buffered of a live output field:
152
+ * the queued audio of an answer the user just talked over.
153
+ */
154
+ clear(field: string): Promise<void>;
143
155
  send(fields: Record<string, unknown>): Promise<void>;
144
156
  }
package/dist/stream.js CHANGED
@@ -50,6 +50,11 @@
50
50
  * The kernel's zodToJsonSchema reads this and emits `format: "stream"`.
51
51
  */
52
52
  export const STREAM_SCHEMA_MARKER = Symbol.for("inferencesh.streamSchema");
53
+ /**
54
+ * A control frame, `{"$clear": "audio"}`: drop what has been buffered of a
55
+ * live output field. Reserved keys start with `$`, which no field name can.
56
+ */
57
+ export const CLEAR_KEY = "$clear";
53
58
  /**
54
59
  * Marks a binary item schema. The value on `_def` is the content type.
55
60
  * The kernel's zodToJsonSchema reads this and emits
@@ -213,6 +218,8 @@ export class Live {
213
218
  inBinary;
214
219
  outShape;
215
220
  outBinary;
221
+ outLive;
222
+ refusedBinary = false;
216
223
  constructor(socket, inputData, inputSchema, outputSchema) {
217
224
  this.socket = socket;
218
225
  this.input = inputData;
@@ -221,6 +228,7 @@ export class Live {
221
228
  this.inBinary = binaryField(inputSchema);
222
229
  this.outShape = shapeOf(outputSchema);
223
230
  this.outBinary = binaryField(outputSchema);
231
+ this.outLive = liveFields(outputSchema);
224
232
  }
225
233
  async *[Symbol.asyncIterator]() {
226
234
  for await (const frame of this.frames()) {
@@ -245,7 +253,12 @@ export class Live {
245
253
  async read(frame) {
246
254
  if (isBinaryFrame(frame)) {
247
255
  if (this.inBinary === null) {
248
- await this.refuse(null, "this function takes no binary frames");
256
+ // Once: a caller streaming audio to the wrong function would
257
+ // otherwise get an error frame for every frame it sends.
258
+ if (!this.refusedBinary) {
259
+ this.refusedBinary = true;
260
+ await this.refuse(null, "this function takes no binary frames");
261
+ }
249
262
  return [];
250
263
  }
251
264
  return [{ field: this.inBinary, value: toBuffer(frame) }];
@@ -263,30 +276,25 @@ export class Live {
263
276
  }
264
277
  const updates = [];
265
278
  for (const [key, raw] of Object.entries(patch)) {
266
- if (Object.prototype.hasOwnProperty.call(this.inLive, key)) {
267
- if (key === this.inBinary) {
268
- await this.refuse(key, "send this field's items as binary frames");
269
- continue;
270
- }
271
- const result = this.inLive[key].safeParse(raw);
272
- if (!result.success) {
273
- await this.refuse(key, firstIssue(result));
274
- continue;
275
- }
276
- updates.push({ field: key, value: result.data });
279
+ const live = Object.prototype.hasOwnProperty.call(this.inLive, key);
280
+ if (!live && !Object.prototype.hasOwnProperty.call(this.inShape, key)) {
281
+ await this.refuse(key, "no such field");
282
+ continue;
277
283
  }
278
- else if (Object.prototype.hasOwnProperty.call(this.inShape, key)) {
279
- const result = this.inShape[key].safeParse(raw);
280
- if (!result.success) {
281
- await this.refuse(key, firstIssue(result));
282
- continue;
283
- }
284
- this.input[key] = result.data;
285
- updates.push({ field: key, value: result.data });
284
+ if (key === this.inBinary) {
285
+ await this.refuse(key, "send this field's items as binary frames");
286
+ continue;
286
287
  }
287
- else {
288
- await this.refuse(key, "no such field");
288
+ // A live field's items are validated against the item schema, an
289
+ // ordinary field against its own and then applied to the input.
290
+ const result = (live ? this.inLive[key] : this.inShape[key]).safeParse(raw);
291
+ if (!result.success) {
292
+ await this.refuse(key, firstIssue(result));
293
+ continue;
289
294
  }
295
+ if (!live)
296
+ this.input[key] = result.data;
297
+ updates.push({ field: key, value: result.data });
290
298
  }
291
299
  return updates;
292
300
  }
@@ -301,6 +309,16 @@ export class Live {
301
309
  * `await live.send({ effect: "echo" })` are JSON frames. Keys in one call
302
310
  * other than the binary field go out together as one JSON frame.
303
311
  */
312
+ /**
313
+ * Tell the caller to drop what it has buffered of a live output field:
314
+ * the queued audio of an answer the user just talked over.
315
+ */
316
+ async clear(field) {
317
+ if (!Object.prototype.hasOwnProperty.call(this.outLive, field)) {
318
+ throw new Error(`the output schema has no live field "${field}"`);
319
+ }
320
+ await this.socket.send({ [CLEAR_KEY]: field });
321
+ }
304
322
  async send(fields) {
305
323
  const patch = {};
306
324
  for (const [key, value] of Object.entries(fields)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inferencesh/app",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "App framework for building inference.sh apps — File handling, output metadata, storage utilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",