@simonpeacocks/peacockery-voice-client 0.1.3 → 0.2.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.
package/README.md CHANGED
@@ -19,9 +19,31 @@ const voice = createPeacockeryVoiceClient({
19
19
  const { data, error } = await voice.GET("/v1/models");
20
20
  ```
21
21
 
22
- For a device-bound child, pass `authorizationScheme: "DPoP"` and a platform proof provider. The callback receives the access token, HTTP method, canonical resource URI, and current server nonce; it returns one ES256 `dpop+jwt`. The wrapper automatically retries the first `use_dpop_nonce` challenge with a new proof. A trusted parent can also remain `Bearer` while supplying `dpopProof` to bind a newly minted child.
22
+ For a device-bound child, pass `authorizationScheme: "DPoP"` and a platform proof provider. The callback receives the access token, HTTP method, canonical resource URI, and current server nonce; it returns one ES256 `dpop+jwt`. The wrapper automatically retries the first `use_dpop_nonce` challenge with a new proof. A trusted parent can remain `Bearer` while supplying an `ath`-free `dpopBindingProof` to bind a newly minted child, keeping the parent token inside the trusted backend.
23
23
 
24
- Private-key creation and signing stay in platform code. On Apple hardware the intended provider uses a non-exportable Secure Enclave P-256 key; the generated client never serializes or persists that key.
24
+ Private-key creation and signing stay in platform code. Apple clients use Secure Enclave P-256 keys; Android clients should use a non-exportable Android Keystore P-256 key. The generated client handles public proofs while private-key state stays exclusively platform-managed.
25
+
26
+ For realtime PCM, build the authenticated upgrade request and parse every provider-neutral event through the package:
27
+
28
+ ```ts
29
+ const request = await createPeacockeryVoiceRealtimeRequest({
30
+ apiKey: childToken,
31
+ authorizationScheme: "DPoP",
32
+ dpopProof: signWithAndroidKeystore,
33
+ encoding: "linear16",
34
+ interimResults: true,
35
+ model: "deepgram-nova-3",
36
+ sampleRate: 16_000,
37
+ });
38
+
39
+ const socket = createNativeWebSocket(request.url, request.headers);
40
+ socket.addEventListener("message", ({ data }) => {
41
+ const event = parsePeacockeryVoiceRealtimeEvent(String(data));
42
+ if (event.type.startsWith("transcript.")) updateVisibleTranscript(event.text);
43
+ });
44
+ ```
45
+
46
+ Send raw PCM chunks as binary WebSocket messages. Send `{ "type": "close" }` after the final chunk and retain the terminal `session.completed` result. The React Native adapter owns the native WebSocket constructor and Android Keystore signer because those APIs live outside the generated HTTP package.
25
47
 
26
48
  Run `pnpm run generate:sdk` from the repository root whenever the OpenAPI contract changes. Compiled JavaScript and declarations are checked in, and private Git installations consume them directly. Realtime WebSockets still use the protocol documented by `/v1/realtime`; `openapi-fetch` covers the HTTP surface.
27
49
 
package/dist/auth.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ export declare const peacockeryVoiceBaseUrls: {
2
+ readonly lab: "https://voice-lab.peacockery.studio";
3
+ readonly production: "https://voice.peacockery.studio";
4
+ };
5
+ export type PeacockeryVoiceEnvironment = keyof typeof peacockeryVoiceBaseUrls;
6
+ export interface PeacockeryVoiceDpopProofInput {
7
+ readonly accessToken: string;
8
+ readonly htm: string;
9
+ readonly htu: string;
10
+ readonly nonce?: string;
11
+ }
12
+ export type PeacockeryVoiceDpopProofProvider = (input: PeacockeryVoiceDpopProofInput) => Promise<string>;
13
+ export type PeacockeryVoiceDpopBindingProofInput = Omit<PeacockeryVoiceDpopProofInput, "accessToken">;
14
+ export type PeacockeryVoiceDpopBindingProofProvider = (input: PeacockeryVoiceDpopBindingProofInput) => Promise<string>;
15
+ export interface PeacockeryVoiceClientOptions {
16
+ apiKey: string;
17
+ authorizationScheme?: "Bearer" | "DPoP";
18
+ baseUrl?: string;
19
+ dpopBindingProof?: PeacockeryVoiceDpopBindingProofProvider;
20
+ dpopProof?: PeacockeryVoiceDpopProofProvider;
21
+ environment?: PeacockeryVoiceEnvironment;
22
+ fetch?: typeof globalThis.fetch;
23
+ }
24
+ export declare const dpopHtu: (requestUrl: string) => string;
25
+ export declare const authenticatedFetch: (options: PeacockeryVoiceClientOptions) => typeof globalThis.fetch;
package/dist/auth.js ADDED
@@ -0,0 +1,51 @@
1
+ export const peacockeryVoiceBaseUrls = {
2
+ lab: "https://voice-lab.peacockery.studio",
3
+ production: "https://voice.peacockery.studio",
4
+ };
5
+ export const dpopHtu = (requestUrl) => {
6
+ const url = new URL(requestUrl);
7
+ return `${url.origin}${url.pathname}`;
8
+ };
9
+ export const authenticatedFetch = (options) => {
10
+ const scheme = options.authorizationScheme ?? "Bearer";
11
+ const fetchImplementation = options.fetch ?? globalThis.fetch;
12
+ const bindingProofProvider = options.dpopBindingProof;
13
+ const workloadProofProvider = options.dpopProof;
14
+ if (scheme === "DPoP" && !workloadProofProvider) {
15
+ throw new Error("DPoP authorization requires a proof provider");
16
+ }
17
+ const hasProofProvider = scheme === "DPoP"
18
+ ? Boolean(workloadProofProvider)
19
+ : Boolean(bindingProofProvider);
20
+ let nonce;
21
+ return async (input, init) => {
22
+ const request = new Request(input, init);
23
+ const send = async () => {
24
+ const headers = new Headers(request.headers);
25
+ headers.set("Authorization", `${scheme} ${options.apiKey}`);
26
+ const proofInput = {
27
+ htm: request.method,
28
+ htu: dpopHtu(request.url),
29
+ ...(nonce ? { nonce } : {}),
30
+ };
31
+ if (scheme === "DPoP" && workloadProofProvider) {
32
+ headers.set("DPoP", await workloadProofProvider({
33
+ accessToken: options.apiKey,
34
+ ...proofInput,
35
+ }));
36
+ }
37
+ else if (bindingProofProvider) {
38
+ headers.set("DPoP", await bindingProofProvider(proofInput));
39
+ }
40
+ return fetchImplementation(new Request(request.clone(), { headers }));
41
+ };
42
+ const response = await send();
43
+ const challengedNonce = response.headers.get("DPoP-Nonce")?.trim();
44
+ if (response.status !== 401 || !challengedNonce || !hasProofProvider) {
45
+ return response;
46
+ }
47
+ nonce = challengedNonce;
48
+ await response.body?.cancel();
49
+ return send();
50
+ };
51
+ };
package/dist/index.d.ts CHANGED
@@ -1,24 +1,7 @@
1
+ import { type PeacockeryVoiceClientOptions } from "./auth.js";
1
2
  import type { paths } from "./schema.js";
3
+ export { type PeacockeryVoiceClientOptions, type PeacockeryVoiceDpopBindingProofInput, type PeacockeryVoiceDpopBindingProofProvider, type PeacockeryVoiceDpopProofInput, type PeacockeryVoiceDpopProofProvider, type PeacockeryVoiceEnvironment, peacockeryVoiceBaseUrls, } from "./auth.js";
4
+ export { createPeacockeryVoiceRealtimeRequest, type PeacockeryVoiceRealtimeAudioReceivedEvent, type PeacockeryVoiceRealtimeEvent, type PeacockeryVoiceRealtimeOptions, type PeacockeryVoiceRealtimePongEvent, type PeacockeryVoiceRealtimeRequest, type PeacockeryVoiceRealtimeSessionStartedEvent, type PeacockeryVoiceRealtimeTranscriptEvent, type PeacockeryVoiceRealtimeTurnEvent, parsePeacockeryVoiceRealtimeEvent, } from "./realtime.js";
2
5
  export type { components, operations, paths } from "./schema.js";
3
- export declare const peacockeryVoiceBaseUrls: {
4
- readonly lab: "https://voice-lab.peacockery.studio";
5
- readonly production: "https://voice.peacockery.studio";
6
- };
7
- export type PeacockeryVoiceEnvironment = keyof typeof peacockeryVoiceBaseUrls;
8
- export interface PeacockeryVoiceDpopProofInput {
9
- readonly accessToken: string;
10
- readonly htm: string;
11
- readonly htu: string;
12
- readonly nonce?: string;
13
- }
14
- export type PeacockeryVoiceDpopProofProvider = (input: PeacockeryVoiceDpopProofInput) => Promise<string>;
15
- export interface PeacockeryVoiceClientOptions {
16
- apiKey: string;
17
- authorizationScheme?: "Bearer" | "DPoP";
18
- baseUrl?: string;
19
- dpopProof?: PeacockeryVoiceDpopProofProvider;
20
- environment?: PeacockeryVoiceEnvironment;
21
- fetch?: typeof globalThis.fetch;
22
- }
23
6
  export declare const createPeacockeryVoiceClient: (options: PeacockeryVoiceClientOptions) => import("openapi-fetch").Client<paths, `${string}/${string}`>;
24
7
  export type PeacockeryVoiceClient = ReturnType<typeof createPeacockeryVoiceClient>;
package/dist/index.js CHANGED
@@ -1,44 +1,8 @@
1
1
  import createClient from "openapi-fetch";
2
- export const peacockeryVoiceBaseUrls = {
3
- lab: "https://voice-lab.peacockery.studio",
4
- production: "https://voice.peacockery.studio",
5
- };
6
- const dpopHtu = (requestUrl) => {
7
- const url = new URL(requestUrl);
8
- return `${url.origin}${url.pathname}`;
9
- };
10
- const authenticatedFetch = (options) => {
11
- const scheme = options.authorizationScheme ?? "Bearer";
12
- const fetchImplementation = options.fetch ?? globalThis.fetch;
13
- if (scheme === "DPoP" && !options.dpopProof) {
14
- throw new Error("DPoP authorization requires a proof provider");
15
- }
16
- let nonce;
17
- return async (input, init) => {
18
- const request = new Request(input, init);
19
- const send = async () => {
20
- const headers = new Headers(request.headers);
21
- headers.set("Authorization", `${scheme} ${options.apiKey}`);
22
- if (options.dpopProof) {
23
- headers.set("DPoP", await options.dpopProof({
24
- accessToken: options.apiKey,
25
- htm: request.method,
26
- htu: dpopHtu(request.url),
27
- ...(nonce ? { nonce } : {}),
28
- }));
29
- }
30
- return fetchImplementation(new Request(request.clone(), { headers }));
31
- };
32
- const response = await send();
33
- const challengedNonce = response.headers.get("DPoP-Nonce")?.trim();
34
- if (response.status !== 401 || !challengedNonce || !options.dpopProof) {
35
- return response;
36
- }
37
- nonce = challengedNonce;
38
- await response.body?.cancel();
39
- return send();
40
- };
41
- };
2
+ import { authenticatedFetch, peacockeryVoiceBaseUrls, } from "./auth.js";
3
+ // biome-ignore lint/performance/noBarrelFile: The public package entrypoint intentionally exposes the supported auth surface.
4
+ export { peacockeryVoiceBaseUrls, } from "./auth.js";
5
+ export { createPeacockeryVoiceRealtimeRequest, parsePeacockeryVoiceRealtimeEvent, } from "./realtime.js";
42
6
  export const createPeacockeryVoiceClient = (options) => {
43
7
  const environment = options.environment ?? "production";
44
8
  return createClient({
@@ -0,0 +1,86 @@
1
+ import { type PeacockeryVoiceClientOptions } from "./auth.js";
2
+ import type { components } from "./schema.js";
3
+ type RealtimeTerminalEvent = components["schemas"]["RealtimeSessionResult"];
4
+ interface TranscriptSegment {
5
+ endSeconds: number | null;
6
+ scores?: {
7
+ confidence?: number;
8
+ logProbability?: number;
9
+ probability?: number;
10
+ score?: number;
11
+ speakerConfidence?: number;
12
+ };
13
+ speaker?: string | number;
14
+ startSeconds: number | null;
15
+ text: string;
16
+ }
17
+ type TranscriptSpeakerTurn = Omit<TranscriptSegment, "scores">;
18
+ type TranscriptWord = TranscriptSegment & {
19
+ startSeconds: number;
20
+ endSeconds: number;
21
+ };
22
+ export interface PeacockeryVoiceRealtimeOptions extends PeacockeryVoiceClientOptions {
23
+ channels?: number;
24
+ contextBias?: string[];
25
+ diarize?: boolean;
26
+ encoding?: string;
27
+ endpointing?: string;
28
+ interimResults?: boolean;
29
+ language?: string;
30
+ model: string;
31
+ sampleRate?: number;
32
+ speakerReferences?: Record<string, string>;
33
+ targetStreamingDelayMs?: number;
34
+ turnDetection?: {
35
+ start_threshold?: number;
36
+ eager_end_threshold?: number;
37
+ end_threshold?: number;
38
+ min_silence_ms?: number;
39
+ end_timeout_ms?: number;
40
+ };
41
+ utteranceEndMs?: number;
42
+ vadEvents?: boolean;
43
+ }
44
+ export interface PeacockeryVoiceRealtimeRequest {
45
+ headers: Readonly<Record<string, string>>;
46
+ url: string;
47
+ }
48
+ interface RealtimeEventBase {
49
+ protocol_version: 1;
50
+ sequence: number;
51
+ session_id: string;
52
+ }
53
+ export interface PeacockeryVoiceRealtimeSessionStartedEvent extends RealtimeEventBase {
54
+ language: string | null;
55
+ model: string;
56
+ type: "session.started";
57
+ }
58
+ export interface PeacockeryVoiceRealtimeTranscriptEvent extends RealtimeEventBase {
59
+ segments: TranscriptSegment[];
60
+ speaker_turns: TranscriptSpeakerTurn[];
61
+ speech_final?: boolean;
62
+ text: string;
63
+ type: "transcript.committed" | "transcript.delta" | "transcript.interim";
64
+ words: TranscriptWord[];
65
+ }
66
+ export interface PeacockeryVoiceRealtimeAudioReceivedEvent {
67
+ audio_bytes: number;
68
+ chunk_bytes: number;
69
+ message_count: number;
70
+ session_id: string;
71
+ type: "audio.received";
72
+ }
73
+ export interface PeacockeryVoiceRealtimePongEvent {
74
+ message_count: number;
75
+ session_id: string;
76
+ type: "pong";
77
+ }
78
+ export interface PeacockeryVoiceRealtimeTurnEvent extends RealtimeEventBase {
79
+ end_reason?: "threshold" | "timeout";
80
+ time_seconds: number;
81
+ type: "turn.start" | "turn.eager_end" | "turn.resume" | "turn.end";
82
+ }
83
+ export type PeacockeryVoiceRealtimeEvent = PeacockeryVoiceRealtimeTurnEvent | PeacockeryVoiceRealtimeAudioReceivedEvent | PeacockeryVoiceRealtimePongEvent | PeacockeryVoiceRealtimeSessionStartedEvent | PeacockeryVoiceRealtimeTranscriptEvent | RealtimeTerminalEvent;
84
+ export declare const createPeacockeryVoiceRealtimeRequest: (options: PeacockeryVoiceRealtimeOptions) => Promise<PeacockeryVoiceRealtimeRequest>;
85
+ export declare const parsePeacockeryVoiceRealtimeEvent: (value: string | unknown) => PeacockeryVoiceRealtimeEvent;
86
+ export {};
@@ -0,0 +1,149 @@
1
+ import { dpopHtu, peacockeryVoiceBaseUrls, } from "./auth.js";
2
+ const realtimeHttpUrl = (options) => {
3
+ const environment = options.environment ?? "production";
4
+ const url = new URL("/v1/realtime", options.baseUrl ?? peacockeryVoiceBaseUrls[environment]);
5
+ const query = {
6
+ channels: options.channels,
7
+ diarize: options.diarize,
8
+ encoding: options.encoding,
9
+ endpointing: options.endpointing,
10
+ interim_results: options.interimResults,
11
+ language: options.language,
12
+ model: options.model,
13
+ sample_rate: options.sampleRate,
14
+ speaker_references: options.speakerReferences
15
+ ? JSON.stringify(options.speakerReferences)
16
+ : undefined,
17
+ target_streaming_delay_ms: options.targetStreamingDelayMs,
18
+ turn_detection: options.turnDetection
19
+ ? JSON.stringify(options.turnDetection)
20
+ : undefined,
21
+ utterance_end_ms: options.utteranceEndMs,
22
+ vad_events: options.vadEvents,
23
+ };
24
+ for (const [name, value] of Object.entries(query)) {
25
+ if (value !== undefined) {
26
+ url.searchParams.set(name, String(value));
27
+ }
28
+ }
29
+ for (const term of options.contextBias ?? []) {
30
+ url.searchParams.append("context_bias", term);
31
+ }
32
+ return url;
33
+ };
34
+ const headersRecord = (headers) => {
35
+ const record = {};
36
+ for (const [name, value] of headers) {
37
+ record[name] = value;
38
+ }
39
+ return record;
40
+ };
41
+ export const createPeacockeryVoiceRealtimeRequest = async (options) => {
42
+ const scheme = options.authorizationScheme ?? "Bearer";
43
+ const url = realtimeHttpUrl(options);
44
+ const headers = new Headers({
45
+ Authorization: `${scheme} ${options.apiKey}`,
46
+ });
47
+ if (scheme === "DPoP") {
48
+ const proofProvider = options.dpopProof;
49
+ if (!proofProvider) {
50
+ throw new Error("DPoP authorization requires a proof provider");
51
+ }
52
+ let nonce;
53
+ const fetchImplementation = options.fetch ?? globalThis.fetch;
54
+ const nonceUrl = new URL("/v1/auth/dpop-nonce", url);
55
+ const prime = async () => {
56
+ const primeHeaders = new Headers({
57
+ Authorization: `DPoP ${options.apiKey}`,
58
+ DPoP: await proofProvider({
59
+ accessToken: options.apiKey,
60
+ htm: "POST",
61
+ htu: dpopHtu(nonceUrl.href),
62
+ ...(nonce ? { nonce } : {}),
63
+ }),
64
+ });
65
+ return fetchImplementation(nonceUrl, {
66
+ headers: primeHeaders,
67
+ method: "POST",
68
+ });
69
+ };
70
+ let response = await prime();
71
+ const challengedNonce = response.headers.get("DPoP-Nonce")?.trim();
72
+ if (response.status === 401 && challengedNonce) {
73
+ nonce = challengedNonce;
74
+ await response.body?.cancel();
75
+ response = await prime();
76
+ }
77
+ if (response.status !== 204 || !nonce) {
78
+ throw new Error(`Peacockery Voice DPoP nonce bootstrap returned ${response.status}`);
79
+ }
80
+ await response.body?.cancel();
81
+ headers.set("DPoP", await proofProvider({
82
+ accessToken: options.apiKey,
83
+ htm: "GET",
84
+ htu: dpopHtu(url.href),
85
+ nonce,
86
+ }));
87
+ }
88
+ url.protocol = url.protocol === "http:" ? "ws:" : "wss:";
89
+ return { headers: headersRecord(headers), url: url.href };
90
+ };
91
+ const isRecord = (value) => typeof value === "object" && value !== null;
92
+ const isTurnEvent = (value) => typeof value.time_seconds === "number" &&
93
+ Number.isFinite(value.time_seconds) &&
94
+ value.time_seconds >= 0 &&
95
+ (value.end_reason === undefined ||
96
+ value.end_reason === "threshold" ||
97
+ value.end_reason === "timeout");
98
+ const isRealtimeEvent = (value) => {
99
+ if (!isRecord(value) || typeof value.type !== "string") {
100
+ return false;
101
+ }
102
+ if (value.type === "audio.received") {
103
+ return (typeof value.audio_bytes === "number" &&
104
+ typeof value.chunk_bytes === "number" &&
105
+ typeof value.message_count === "number" &&
106
+ typeof value.session_id === "string");
107
+ }
108
+ if (value.type === "pong") {
109
+ return (typeof value.message_count === "number" &&
110
+ typeof value.session_id === "string");
111
+ }
112
+ const hasProtocolBase = value.protocol_version === 1 &&
113
+ typeof value.sequence === "number" &&
114
+ typeof value.session_id === "string";
115
+ if (!hasProtocolBase) {
116
+ return false;
117
+ }
118
+ if (["turn.start", "turn.eager_end", "turn.resume", "turn.end"].includes(value.type)) {
119
+ return isTurnEvent(value);
120
+ }
121
+ if (value.type === "session.started") {
122
+ return ((typeof value.language === "string" || value.language === null) &&
123
+ typeof value.model === "string");
124
+ }
125
+ if (value.type === "transcript.committed" ||
126
+ value.type === "transcript.delta" ||
127
+ value.type === "transcript.interim") {
128
+ return (Array.isArray(value.segments) &&
129
+ Array.isArray(value.speaker_turns) &&
130
+ typeof value.text === "string" &&
131
+ Array.isArray(value.words));
132
+ }
133
+ if (value.type === "session.completed") {
134
+ return value.status === "succeeded" && isRecord(value.result);
135
+ }
136
+ if (value.type === "session.failed") {
137
+ return (value.status === "failed" &&
138
+ isRecord(value.error) &&
139
+ isRecord(value.result));
140
+ }
141
+ return false;
142
+ };
143
+ export const parsePeacockeryVoiceRealtimeEvent = (value) => {
144
+ const parsed = typeof value === "string" ? JSON.parse(value) : value;
145
+ if (!isRealtimeEvent(parsed)) {
146
+ throw new Error("Peacockery Voice returned an invalid realtime event");
147
+ }
148
+ return parsed;
149
+ };
package/dist/schema.d.ts CHANGED
@@ -1245,6 +1245,49 @@ export interface paths {
1245
1245
  patch?: never;
1246
1246
  trace?: never;
1247
1247
  };
1248
+ "/v1/auth/dpop-nonce": {
1249
+ parameters: {
1250
+ query?: never;
1251
+ header?: never;
1252
+ path?: never;
1253
+ cookie?: never;
1254
+ };
1255
+ get?: never;
1256
+ put?: never;
1257
+ /** Prime a DPoP nonce before a WebSocket upgrade */
1258
+ post: {
1259
+ parameters: {
1260
+ query?: never;
1261
+ header?: never;
1262
+ path?: never;
1263
+ cookie?: never;
1264
+ };
1265
+ requestBody?: never;
1266
+ responses: {
1267
+ /** @description DPoP nonce is current for this credential. */
1268
+ 204: {
1269
+ headers: {
1270
+ [name: string]: unknown;
1271
+ };
1272
+ content?: never;
1273
+ };
1274
+ /** @description Unauthorized. */
1275
+ 401: {
1276
+ headers: {
1277
+ [name: string]: unknown;
1278
+ };
1279
+ content: {
1280
+ "application/json": components["schemas"]["ErrorResponse"];
1281
+ };
1282
+ };
1283
+ };
1284
+ };
1285
+ delete?: never;
1286
+ options?: never;
1287
+ head?: never;
1288
+ patch?: never;
1289
+ trace?: never;
1290
+ };
1248
1291
  "/v1/jobs/{job_id}": {
1249
1292
  parameters: {
1250
1293
  query?: never;
@@ -1359,6 +1402,7 @@ export interface paths {
1359
1402
  query?: {
1360
1403
  audio_format?: string;
1361
1404
  channels?: number;
1405
+ context_bias?: string;
1362
1406
  detect_entities?: "true" | "false";
1363
1407
  diarize?: "true" | "false";
1364
1408
  diarize_model?: "latest" | "v1";
@@ -1382,8 +1426,12 @@ export interface paths {
1382
1426
  sample_rate?: number;
1383
1427
  search?: string;
1384
1428
  smart_format?: "true" | "false";
1429
+ /** @description JSON object mapping speaker names to completed upload input_key values */
1430
+ speaker_references?: string;
1385
1431
  tag?: string;
1386
1432
  target_streaming_delay_ms?: number;
1433
+ /** @description JSON turn-detection configuration; {} uses provider defaults */
1434
+ turn_detection?: string;
1387
1435
  utterance_end_ms?: number;
1388
1436
  vad_events?: "true" | "false";
1389
1437
  version?: string;
@@ -2071,7 +2119,7 @@ export interface components {
2071
2119
  /** @enum {string|null} */
2072
2120
  source: "derived" | "provider" | null;
2073
2121
  items: {
2074
- end_seconds: number;
2122
+ end_seconds: number | null;
2075
2123
  scores: {
2076
2124
  confidence: number | null;
2077
2125
  log_probability: number | null;
@@ -2080,7 +2128,7 @@ export interface components {
2080
2128
  speaker_confidence: number | null;
2081
2129
  } | null;
2082
2130
  speaker: string | number | null;
2083
- start_seconds: number;
2131
+ start_seconds: number | null;
2084
2132
  text: string;
2085
2133
  }[];
2086
2134
  };
@@ -2090,9 +2138,9 @@ export interface components {
2090
2138
  /** @enum {string|null} */
2091
2139
  source: "derived" | "provider" | null;
2092
2140
  items: {
2093
- end_seconds: number;
2141
+ end_seconds: number | null;
2094
2142
  speaker: string | number | null;
2095
- start_seconds: number;
2143
+ start_seconds: number | null;
2096
2144
  text: string;
2097
2145
  scores: null;
2098
2146
  }[];
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@simonpeacocks/peacockery-voice-client",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Generated TypeScript client for the Peacockery Voice API",
5
- "type": "module",
6
- "license": "MIT",
7
5
  "repository": {
8
6
  "type": "git",
9
7
  "url": "git+https://github.com/chikingsley/peacockery-voice.git",
10
8
  "directory": "clients/typescript"
11
9
  },
10
+ "license": "MIT",
11
+ "type": "module",
12
12
  "exports": {
13
13
  ".": {
14
14
  "types": "./dist/index.d.ts",
@@ -18,10 +18,6 @@
18
18
  "files": [
19
19
  "dist"
20
20
  ],
21
- "publishConfig": {
22
- "access": "public",
23
- "provenance": false
24
- },
25
21
  "scripts": {
26
22
  "build": "tsc",
27
23
  "check": "tsc --noEmit",
@@ -32,5 +28,9 @@
32
28
  },
33
29
  "devDependencies": {
34
30
  "typescript": "^7.0.2"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "provenance": false
35
35
  }
36
36
  }