@framers/agentos-ext-google-cloud-stt 0.2.1 → 0.3.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/SKILL.md CHANGED
@@ -14,12 +14,14 @@ Provide credentials via the `GOOGLE_CLOUD_STT_CREDENTIALS` secret. Accepts eithe
14
14
  - An absolute path to a service-account JSON key file (contains `/` or `\`)
15
15
  - A raw JSON string with the service-account credentials
16
16
 
17
+ Leave the secret unset to use Google's Application Default Credentials (`GOOGLE_APPLICATION_CREDENTIALS`, `gcloud auth application-default login`, or the metadata server on Google Cloud).
18
+
17
19
  ## Features
18
20
 
19
- - LINEAR16 PCM audio transcription
21
+ - WAV and FLAC files (Google reads the encoding and sample rate from the header) and raw LINEAR16 PCM
20
22
  - Configurable language code (BCP-47)
21
- - Confidence scores and word-level alternatives
22
- - Maps to standard `SpeechTranscriptionResult` shape
23
+ - Returns the AgentOS `SpeechTranscriptionResult`: `text` (each stretch's most likely transcript, in order), mean `confidence`, `isFinal`, and `segments` with timing when Google reports end times
24
+ - Batch only (`supportsStreaming: false`)
23
25
 
24
26
  ## Configuration
25
27
 
@@ -10,18 +10,39 @@
10
10
  * @module google-cloud-stt
11
11
  */
12
12
  /**
13
- * A single recognised audio segment returned by the provider.
14
- *
15
- * Mirrors the generic `SpeechTranscriptionResult` shape used across the
16
- * AgentOS voice pipeline.
13
+ * One stretch of recognised speech: Google returns a result per consecutive
14
+ * portion of the audio.
15
+ */
16
+ export interface SpeechTranscriptionSegment {
17
+ /** The most likely transcript of this stretch. */
18
+ text: string;
19
+ /** Start in seconds from the beginning of the audio. */
20
+ startTime: number;
21
+ /** End in seconds from the beginning of the audio. */
22
+ endTime: number;
23
+ /** Confidence score in [0, 1], when Google reports one. */
24
+ confidence?: number;
25
+ }
26
+ /**
27
+ * The transcription result of the AgentOS `SpeechToTextProvider` contract
28
+ * (`SpeechTranscriptionResult` in `@framers/agentos`), mirrored here so the
29
+ * pack carries no type import from agentos.
17
30
  */
18
31
  export interface SpeechTranscriptionResult {
19
- /** The recognised text. */
20
- transcript: string;
21
- /** Confidence score in [0, 1]. */
22
- confidence: number;
23
- /** Whether this is a final (non-speculative) result. Always `true` for batch. */
32
+ /** The recognised text: every stretch's most likely transcript, in order. */
33
+ text: string;
34
+ /** BCP-47 language of the transcript. */
35
+ language?: string;
36
+ /** Mean confidence of the stretches, in [0, 1], when Google reports any. */
37
+ confidence?: number;
38
+ /** Always `true`: batch recognition returns final results only. */
24
39
  isFinal: boolean;
40
+ /** Always 0; cost is tracked above the provider, as for AgentOS's core batch providers. */
41
+ cost: number;
42
+ /** Per-stretch transcripts with their timing, when Google reports end times. */
43
+ segments?: SpeechTranscriptionSegment[];
44
+ /** The raw `RecognizeResponse`. */
45
+ providerResponse?: unknown;
25
46
  }
26
47
  /**
27
48
  * Per-call transcription options forwarded to the Google Cloud API.
@@ -31,13 +52,18 @@ export interface GoogleCloudSTTOptions {
31
52
  language?: string;
32
53
  }
33
54
  /**
34
- * Audio frame passed to {@link GoogleCloudSTTProvider.transcribe}.
55
+ * Audio passed to {@link GoogleCloudSTTProvider.transcribe}: the fields of the
56
+ * AgentOS `SpeechAudioInput` this provider reads.
35
57
  */
36
58
  export interface AudioData {
37
- /** Raw PCM bytes (LINEAR16). */
59
+ /** The audio bytes: a WAV or FLAC file, or raw LINEAR16 PCM. */
38
60
  data: Buffer;
39
- /** Sample rate in Hz. @defaultValue `16000` */
61
+ /** Sample rate in Hz. Raw PCM defaults to 16000; a WAV or FLAC header supplies its own. */
40
62
  sampleRate?: number;
63
+ /** MIME type, such as `'audio/wav'` or `'audio/flac'`. */
64
+ mimeType?: string;
65
+ /** Container format, such as `'wav'` or `'flac'`. */
66
+ format?: string;
41
67
  }
42
68
  /**
43
69
  * Google Cloud Speech-to-Text batch provider.
@@ -49,6 +75,10 @@ export interface AudioData {
49
75
  export declare class GoogleCloudSTTProvider {
50
76
  /** Stable provider identifier used by the AgentOS extension registry. */
51
77
  readonly id = "google-cloud-stt";
78
+ /** Human-readable provider name. */
79
+ readonly displayName = "Google Cloud Speech-to-Text";
80
+ /** Batch recognition only: this provider does not stream. */
81
+ readonly supportsStreaming = false;
52
82
  /** Lazily initialised Speech client. */
53
83
  private _client;
54
84
  /** Resolved client constructor options (set in constructor, used in {@link _getClient}). */
@@ -70,16 +100,22 @@ export declare class GoogleCloudSTTProvider {
70
100
  */
71
101
  private _getClient;
72
102
  /**
73
- * Transcribe a batch audio buffer using Google Cloud Speech-to-Text.
103
+ * The provider's display name, as the AgentOS speech contract requires.
104
+ *
105
+ * @returns `'Google Cloud Speech-to-Text'`.
106
+ */
107
+ getProviderName(): string;
108
+ /**
109
+ * Transcribe an audio file or raw PCM buffer using Google Cloud Speech-to-Text.
74
110
  *
75
- * The audio must be encoded as LINEAR16 (raw PCM, 16-bit little-endian).
76
- * The method returns all recognised alternatives from the first result, each
77
- * mapped to a {@link SpeechTranscriptionResult}.
111
+ * Google returns one result per consecutive stretch of the audio, each with
112
+ * its alternatives ordered by likelihood. The transcript is every stretch's
113
+ * first alternative, in order.
78
114
  *
79
- * @param audio - Audio frame containing the raw PCM bytes and sample rate.
115
+ * @param audio - WAV or FLAC file bytes, or raw LINEAR16 PCM with its sample rate.
80
116
  * @param options - Optional per-call parameters (language code).
81
- * @returns Array of transcription results ordered by confidence (descending).
117
+ * @returns The transcription in the AgentOS `SpeechTranscriptionResult` shape.
82
118
  */
83
- transcribe(audio: AudioData, options?: GoogleCloudSTTOptions): Promise<SpeechTranscriptionResult[]>;
119
+ transcribe(audio: AudioData, options?: GoogleCloudSTTOptions): Promise<SpeechTranscriptionResult>;
84
120
  }
85
121
  //# sourceMappingURL=GoogleCloudSTTProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleCloudSTTProvider.d.ts","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAOH;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACxC,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,qBAAa,sBAAsB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,sBAAsB;IAEjC,wCAAwC;IACxC,OAAO,CAAC,OAAO,CAA6B;IAE5C,4FAA4F;IAC5F,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IAEzD;;;;;;;OAOG;gBACS,WAAW,EAAE,MAAM;IAmB/B;;;;;OAKG;YACW,UAAU;IAaxB;;;;;;;;;;OAUG;IACG,UAAU,CACd,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,yBAAyB,EAAE,CAAC;CA2BxC"}
1
+ {"version":3,"file":"GoogleCloudSTTProvider.d.ts","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAOH;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,QAAQ,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACxC,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA0BD;;;;;;GAMG;AACH,qBAAa,sBAAsB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,sBAAsB;IAEjC,oCAAoC;IACpC,QAAQ,CAAC,WAAW,iCAAiC;IAErD,6DAA6D;IAC7D,QAAQ,CAAC,iBAAiB,SAAS;IAEnC,wCAAwC;IACxC,OAAO,CAAC,OAAO,CAA6B;IAE5C,4FAA4F;IAC5F,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IAEzD;;;;;;;OAOG;gBACS,WAAW,EAAE,MAAM;IAmB/B;;;;;OAKG;YACW,UAAU;IAaxB;;;;OAIG;IACH,eAAe,IAAI,MAAM;IAIzB;;;;;;;;;;OAUG;IACG,UAAU,CACd,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,yBAAyB,CAAC;CA0CtC"}
@@ -10,6 +10,29 @@
10
10
  *
11
11
  * @module google-cloud-stt
12
12
  */
13
+ /**
14
+ * The encoding fields of the recognition config for this audio.
15
+ *
16
+ * WAV and FLAC files carry a header that states the encoding and sample rate.
17
+ * Google reads both from it and rejects a request whose stated values disagree
18
+ * (google.cloud.speech.v1 `RecognitionConfig`), so for those formats the
19
+ * encoding is left out and the sample rate is sent only when the caller gives
20
+ * one. Anything else is sent as raw LINEAR16 PCM.
21
+ */
22
+ function encodingFor(audio) {
23
+ const declared = `${audio.mimeType ?? ''} ${audio.format ?? ''}`.toLowerCase();
24
+ if (declared.includes('wav') || declared.includes('flac')) {
25
+ return audio.sampleRate ? { sampleRateHertz: audio.sampleRate } : {};
26
+ }
27
+ return { encoding: 'LINEAR16', sampleRateHertz: audio.sampleRate ?? 16000 };
28
+ }
29
+ /** Seconds in a protobuf `Duration` (`{ seconds, nanos }`, seconds possibly a string). */
30
+ function durationSeconds(duration) {
31
+ if (!duration)
32
+ return undefined;
33
+ const seconds = Number(duration.seconds ?? 0) + Number(duration.nanos ?? 0) / 1e9;
34
+ return Number.isFinite(seconds) ? seconds : undefined;
35
+ }
13
36
  /**
14
37
  * Google Cloud Speech-to-Text batch provider.
15
38
  *
@@ -20,6 +43,10 @@
20
43
  export class GoogleCloudSTTProvider {
21
44
  /** Stable provider identifier used by the AgentOS extension registry. */
22
45
  id = 'google-cloud-stt';
46
+ /** Human-readable provider name. */
47
+ displayName = 'Google Cloud Speech-to-Text';
48
+ /** Batch recognition only: this provider does not stream. */
49
+ supportsStreaming = false;
23
50
  /** Lazily initialised Speech client. */
24
51
  _client = null;
25
52
  /** Resolved client constructor options (set in constructor, used in {@link _getClient}). */
@@ -69,38 +96,62 @@ export class GoogleCloudSTTProvider {
69
96
  // Public API
70
97
  // ---------------------------------------------------------------------------
71
98
  /**
72
- * Transcribe a batch audio buffer using Google Cloud Speech-to-Text.
99
+ * The provider's display name, as the AgentOS speech contract requires.
100
+ *
101
+ * @returns `'Google Cloud Speech-to-Text'`.
102
+ */
103
+ getProviderName() {
104
+ return this.displayName;
105
+ }
106
+ /**
107
+ * Transcribe an audio file or raw PCM buffer using Google Cloud Speech-to-Text.
73
108
  *
74
- * The audio must be encoded as LINEAR16 (raw PCM, 16-bit little-endian).
75
- * The method returns all recognised alternatives from the first result, each
76
- * mapped to a {@link SpeechTranscriptionResult}.
109
+ * Google returns one result per consecutive stretch of the audio, each with
110
+ * its alternatives ordered by likelihood. The transcript is every stretch's
111
+ * first alternative, in order.
77
112
  *
78
- * @param audio - Audio frame containing the raw PCM bytes and sample rate.
113
+ * @param audio - WAV or FLAC file bytes, or raw LINEAR16 PCM with its sample rate.
79
114
  * @param options - Optional per-call parameters (language code).
80
- * @returns Array of transcription results ordered by confidence (descending).
115
+ * @returns The transcription in the AgentOS `SpeechTranscriptionResult` shape.
81
116
  */
82
117
  async transcribe(audio, options) {
83
118
  const client = await this._getClient();
119
+ const languageCode = options?.language ?? 'en-US';
84
120
  const response = await client.recognize({
85
121
  audio: { content: audio.data.toString('base64') },
86
- config: {
87
- encoding: 'LINEAR16',
88
- sampleRateHertz: audio.sampleRate ?? 16000,
89
- languageCode: options?.language ?? 'en-US',
90
- },
122
+ config: { ...encodingFor(audio), languageCode },
91
123
  });
92
- const results = [];
93
- for (const result of response[0]?.results ?? []) {
124
+ const recognized = response[0];
125
+ const stretches = [];
126
+ for (const result of recognized?.results ?? []) {
94
127
  const alt = result?.alternatives?.[0];
95
- if (alt) {
96
- results.push({
97
- transcript: alt.transcript ?? '',
98
- confidence: alt.confidence ?? 0,
99
- isFinal: true,
100
- });
101
- }
128
+ if (!alt)
129
+ continue;
130
+ stretches.push({
131
+ text: (alt.transcript ?? '').trim(),
132
+ confidence: typeof alt.confidence === 'number' ? alt.confidence : undefined,
133
+ endTime: durationSeconds(result.resultEndTime),
134
+ });
102
135
  }
103
- return results;
136
+ const confidences = stretches.map((s) => s.confidence).filter((c) => c !== undefined);
137
+ // Timing is reported only when Google gives every stretch an end time.
138
+ let start = 0;
139
+ const segments = stretches.length > 0 && stretches.every((s) => s.endTime !== undefined)
140
+ ? stretches.map((s) => {
141
+ const segment = { text: s.text, startTime: start, endTime: s.endTime, confidence: s.confidence };
142
+ start = s.endTime;
143
+ return segment;
144
+ })
145
+ : undefined;
146
+ return {
147
+ text: stretches.map((s) => s.text).filter((t) => t.length > 0).join(' '),
148
+ language: recognized?.results?.[0]?.languageCode || languageCode,
149
+ confidence: confidences.length > 0 ? confidences.reduce((sum, c) => sum + c, 0) / confidences.length : undefined,
150
+ isFinal: true,
151
+ cost: 0,
152
+ segments,
153
+ providerResponse: recognized,
154
+ };
104
155
  }
105
156
  }
106
157
  //# sourceMappingURL=GoogleCloudSTTProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleCloudSTTProvider.js","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"AAAA,cAAc;AACd;;;;;;;;;;GAUG;AAwCH;;;;;;GAMG;AACH,MAAM,OAAO,sBAAsB;IACjC,yEAAyE;IAChE,EAAE,GAAG,kBAAkB,CAAC;IAEjC,wCAAwC;IAChC,OAAO,GAAwB,IAAI,CAAC;IAE5C,4FAA4F;IAC3E,cAAc,CAA0B;IAEzD;;;;;;;OAOG;IACH,YAAY,WAAmB;QAC7B,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;YACxB,wEAAwE;YACxE,wEAAwE;YACxE,yEAAyE;YACzE,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QAC3B,CAAC;aAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnE,wBAAwB;YACxB,IAAI,CAAC,cAAc,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,8CAA8C;YAC9C,IAAI,CAAC,cAAc,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAA4B,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E;;;;;OAKG;IACK,KAAK,CAAC,UAAU;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,wEAAwE;YACxE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;YAC9D,IAAI,CAAC,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,8EAA8E;IAC9E,aAAa;IACb,8EAA8E;IAE9E;;;;;;;;;;OAUG;IACH,KAAK,CAAC,UAAU,CACd,KAAgB,EAChB,OAA+B;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAEvC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC;YACtC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YACjD,MAAM,EAAE;gBACN,QAAQ,EAAE,UAAU;gBACpB,eAAe,EAAE,KAAK,CAAC,UAAU,IAAI,KAAK;gBAC1C,YAAY,EAAE,OAAO,EAAE,QAAQ,IAAI,OAAO;aAC3C;SACF,CAAC,CAAC;QAEH,MAAM,OAAO,GAAgC,EAAE,CAAC;QAEhD,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;YACtC,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,CAAC,IAAI,CAAC;oBACX,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE;oBAChC,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC;oBAC/B,OAAO,EAAE,IAAI;iBACd,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"GoogleCloudSTTProvider.js","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -62,5 +62,5 @@ export declare function createGoogleCloudSTT(credentials: string): GoogleCloudST
62
62
  */
63
63
  export declare function createExtensionPack(context: ExtensionPackContext): ExtensionPack;
64
64
  export { GoogleCloudSTTProvider } from './GoogleCloudSTTProvider.js';
65
- export type { SpeechTranscriptionResult, GoogleCloudSTTOptions, AudioData, } from './GoogleCloudSTTProvider.js';
65
+ export type { SpeechTranscriptionResult, SpeechTranscriptionSegment, GoogleCloudSTTOptions, AudioData, } from './GoogleCloudSTTProvider.js';
66
66
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAMrE,2DAA2D;AAC3D,UAAU,mBAAmB;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,qDAAqD;AACrD,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,mBAAmB,EAAE,CAAC;CACpC;AAED,4DAA4D;AAC5D,UAAU,oBAAoB;IAC5B,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AASD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,sBAAsB,CAEhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAgBhF;AAMD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EACV,yBAAyB,EACzB,qBAAqB,EACrB,SAAS,GACV,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAMrE,2DAA2D;AAC3D,UAAU,mBAAmB;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,qDAAqD;AACrD,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,mBAAmB,EAAE,CAAC;CACpC;AAED,4DAA4D;AAC5D,UAAU,oBAAoB;IAC5B,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AASD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,sBAAsB,CAEhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAgBhF;AAMD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,qBAAqB,EACrB,SAAS,GACV,MAAM,6BAA6B,CAAC"}
package/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@framers/agentos-ext-google-cloud-stt",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Batch speech-to-text via Google Cloud Speech-to-Text API",
5
5
  "kind": "stt-provider",
6
6
  "extensionId": "google-cloud-stt",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@framers/agentos-ext-google-cloud-stt",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Batch speech-to-text via Google Cloud Speech-to-Text API for AgentOS voice pipeline",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "@google-cloud/speech": "^6.0.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@framers/agentos": "^0.10.40",
25
+ "@framers/agentos": "^0.12.5",
26
26
  "@google-cloud/speech": "^6.0.0",
27
27
  "typescript": "^5.5.0",
28
28
  "vitest": "^3.2.7"
@@ -17,18 +17,40 @@
17
17
  type SpeechClient = any;
18
18
 
19
19
  /**
20
- * A single recognised audio segment returned by the provider.
21
- *
22
- * Mirrors the generic `SpeechTranscriptionResult` shape used across the
23
- * AgentOS voice pipeline.
20
+ * One stretch of recognised speech: Google returns a result per consecutive
21
+ * portion of the audio.
22
+ */
23
+ export interface SpeechTranscriptionSegment {
24
+ /** The most likely transcript of this stretch. */
25
+ text: string;
26
+ /** Start in seconds from the beginning of the audio. */
27
+ startTime: number;
28
+ /** End in seconds from the beginning of the audio. */
29
+ endTime: number;
30
+ /** Confidence score in [0, 1], when Google reports one. */
31
+ confidence?: number;
32
+ }
33
+
34
+ /**
35
+ * The transcription result of the AgentOS `SpeechToTextProvider` contract
36
+ * (`SpeechTranscriptionResult` in `@framers/agentos`), mirrored here so the
37
+ * pack carries no type import from agentos.
24
38
  */
25
39
  export interface SpeechTranscriptionResult {
26
- /** The recognised text. */
27
- transcript: string;
28
- /** Confidence score in [0, 1]. */
29
- confidence: number;
30
- /** Whether this is a final (non-speculative) result. Always `true` for batch. */
40
+ /** The recognised text: every stretch's most likely transcript, in order. */
41
+ text: string;
42
+ /** BCP-47 language of the transcript. */
43
+ language?: string;
44
+ /** Mean confidence of the stretches, in [0, 1], when Google reports any. */
45
+ confidence?: number;
46
+ /** Always `true`: batch recognition returns final results only. */
31
47
  isFinal: boolean;
48
+ /** Always 0; cost is tracked above the provider, as for AgentOS's core batch providers. */
49
+ cost: number;
50
+ /** Per-stretch transcripts with their timing, when Google reports end times. */
51
+ segments?: SpeechTranscriptionSegment[];
52
+ /** The raw `RecognizeResponse`. */
53
+ providerResponse?: unknown;
32
54
  }
33
55
 
34
56
  /**
@@ -40,13 +62,42 @@ export interface GoogleCloudSTTOptions {
40
62
  }
41
63
 
42
64
  /**
43
- * Audio frame passed to {@link GoogleCloudSTTProvider.transcribe}.
65
+ * Audio passed to {@link GoogleCloudSTTProvider.transcribe}: the fields of the
66
+ * AgentOS `SpeechAudioInput` this provider reads.
44
67
  */
45
68
  export interface AudioData {
46
- /** Raw PCM bytes (LINEAR16). */
69
+ /** The audio bytes: a WAV or FLAC file, or raw LINEAR16 PCM. */
47
70
  data: Buffer;
48
- /** Sample rate in Hz. @defaultValue `16000` */
71
+ /** Sample rate in Hz. Raw PCM defaults to 16000; a WAV or FLAC header supplies its own. */
49
72
  sampleRate?: number;
73
+ /** MIME type, such as `'audio/wav'` or `'audio/flac'`. */
74
+ mimeType?: string;
75
+ /** Container format, such as `'wav'` or `'flac'`. */
76
+ format?: string;
77
+ }
78
+
79
+ /**
80
+ * The encoding fields of the recognition config for this audio.
81
+ *
82
+ * WAV and FLAC files carry a header that states the encoding and sample rate.
83
+ * Google reads both from it and rejects a request whose stated values disagree
84
+ * (google.cloud.speech.v1 `RecognitionConfig`), so for those formats the
85
+ * encoding is left out and the sample rate is sent only when the caller gives
86
+ * one. Anything else is sent as raw LINEAR16 PCM.
87
+ */
88
+ function encodingFor(audio: AudioData): { encoding?: string; sampleRateHertz?: number } {
89
+ const declared = `${audio.mimeType ?? ''} ${audio.format ?? ''}`.toLowerCase();
90
+ if (declared.includes('wav') || declared.includes('flac')) {
91
+ return audio.sampleRate ? { sampleRateHertz: audio.sampleRate } : {};
92
+ }
93
+ return { encoding: 'LINEAR16', sampleRateHertz: audio.sampleRate ?? 16000 };
94
+ }
95
+
96
+ /** Seconds in a protobuf `Duration` (`{ seconds, nanos }`, seconds possibly a string). */
97
+ function durationSeconds(duration: { seconds?: unknown; nanos?: unknown } | null | undefined): number | undefined {
98
+ if (!duration) return undefined;
99
+ const seconds = Number(duration.seconds ?? 0) + Number(duration.nanos ?? 0) / 1e9;
100
+ return Number.isFinite(seconds) ? seconds : undefined;
50
101
  }
51
102
 
52
103
  /**
@@ -60,6 +111,12 @@ export class GoogleCloudSTTProvider {
60
111
  /** Stable provider identifier used by the AgentOS extension registry. */
61
112
  readonly id = 'google-cloud-stt';
62
113
 
114
+ /** Human-readable provider name. */
115
+ readonly displayName = 'Google Cloud Speech-to-Text';
116
+
117
+ /** Batch recognition only: this provider does not stream. */
118
+ readonly supportsStreaming = false;
119
+
63
120
  /** Lazily initialised Speech client. */
64
121
  private _client: SpeechClient | null = null;
65
122
 
@@ -113,44 +170,68 @@ export class GoogleCloudSTTProvider {
113
170
  // ---------------------------------------------------------------------------
114
171
 
115
172
  /**
116
- * Transcribe a batch audio buffer using Google Cloud Speech-to-Text.
173
+ * The provider's display name, as the AgentOS speech contract requires.
117
174
  *
118
- * The audio must be encoded as LINEAR16 (raw PCM, 16-bit little-endian).
119
- * The method returns all recognised alternatives from the first result, each
120
- * mapped to a {@link SpeechTranscriptionResult}.
175
+ * @returns `'Google Cloud Speech-to-Text'`.
176
+ */
177
+ getProviderName(): string {
178
+ return this.displayName;
179
+ }
180
+
181
+ /**
182
+ * Transcribe an audio file or raw PCM buffer using Google Cloud Speech-to-Text.
121
183
  *
122
- * @param audio - Audio frame containing the raw PCM bytes and sample rate.
184
+ * Google returns one result per consecutive stretch of the audio, each with
185
+ * its alternatives ordered by likelihood. The transcript is every stretch's
186
+ * first alternative, in order.
187
+ *
188
+ * @param audio - WAV or FLAC file bytes, or raw LINEAR16 PCM with its sample rate.
123
189
  * @param options - Optional per-call parameters (language code).
124
- * @returns Array of transcription results ordered by confidence (descending).
190
+ * @returns The transcription in the AgentOS `SpeechTranscriptionResult` shape.
125
191
  */
126
192
  async transcribe(
127
193
  audio: AudioData,
128
194
  options?: GoogleCloudSTTOptions,
129
- ): Promise<SpeechTranscriptionResult[]> {
195
+ ): Promise<SpeechTranscriptionResult> {
130
196
  const client = await this._getClient();
197
+ const languageCode = options?.language ?? 'en-US';
131
198
 
132
199
  const response = await client.recognize({
133
200
  audio: { content: audio.data.toString('base64') },
134
- config: {
135
- encoding: 'LINEAR16',
136
- sampleRateHertz: audio.sampleRate ?? 16000,
137
- languageCode: options?.language ?? 'en-US',
138
- },
201
+ config: { ...encodingFor(audio), languageCode },
139
202
  });
203
+ const recognized = response[0];
140
204
 
141
- const results: SpeechTranscriptionResult[] = [];
142
-
143
- for (const result of response[0]?.results ?? []) {
205
+ const stretches: Array<{ text: string; confidence?: number; endTime?: number }> = [];
206
+ for (const result of recognized?.results ?? []) {
144
207
  const alt = result?.alternatives?.[0];
145
- if (alt) {
146
- results.push({
147
- transcript: alt.transcript ?? '',
148
- confidence: alt.confidence ?? 0,
149
- isFinal: true,
150
- });
151
- }
208
+ if (!alt) continue;
209
+ stretches.push({
210
+ text: (alt.transcript ?? '').trim(),
211
+ confidence: typeof alt.confidence === 'number' ? alt.confidence : undefined,
212
+ endTime: durationSeconds(result.resultEndTime),
213
+ });
152
214
  }
153
215
 
154
- return results;
216
+ const confidences = stretches.map((s) => s.confidence).filter((c): c is number => c !== undefined);
217
+ // Timing is reported only when Google gives every stretch an end time.
218
+ let start = 0;
219
+ const segments = stretches.length > 0 && stretches.every((s) => s.endTime !== undefined)
220
+ ? stretches.map((s) => {
221
+ const segment = { text: s.text, startTime: start, endTime: s.endTime as number, confidence: s.confidence };
222
+ start = s.endTime as number;
223
+ return segment;
224
+ })
225
+ : undefined;
226
+
227
+ return {
228
+ text: stretches.map((s) => s.text).filter((t) => t.length > 0).join(' '),
229
+ language: recognized?.results?.[0]?.languageCode || languageCode,
230
+ confidence: confidences.length > 0 ? confidences.reduce((sum, c) => sum + c, 0) / confidences.length : undefined,
231
+ isFinal: true,
232
+ cost: 0,
233
+ segments,
234
+ providerResponse: recognized,
235
+ };
155
236
  }
156
237
  }
package/src/index.ts CHANGED
@@ -105,6 +105,7 @@ export function createExtensionPack(context: ExtensionPackContext): ExtensionPac
105
105
  export { GoogleCloudSTTProvider } from './GoogleCloudSTTProvider.js';
106
106
  export type {
107
107
  SpeechTranscriptionResult,
108
+ SpeechTranscriptionSegment,
108
109
  GoogleCloudSTTOptions,
109
110
  AudioData,
110
111
  } from './GoogleCloudSTTProvider.js';