@framers/agentos-ext-google-cloud-stt 0.3.0 → 0.3.2

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
@@ -11,14 +11,14 @@ Batch speech-to-text recognition using Google Cloud Speech-to-Text V1 API.
11
11
  ## Setup
12
12
 
13
13
  Provide credentials via the `GOOGLE_CLOUD_STT_CREDENTIALS` secret. Accepts either:
14
- - An absolute path to a service-account JSON key file (contains `/` or `\`)
15
- - A raw JSON string with the service-account credentials
14
+ - The service-account key itself, as JSON (any value that starts with `{`)
15
+ - A path to a service-account JSON key file (any other value)
16
16
 
17
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
18
 
19
19
  ## Features
20
20
 
21
- - WAV and FLAC files (Google reads the encoding and sample rate from the header) and raw LINEAR16 PCM
21
+ - WAV and FLAC files (detected from the bytes; Google reads the encoding and sample rate from the header) and raw LINEAR16 PCM, whatever MIME type the caller declares
22
22
  - Configurable language code (BCP-47)
23
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
24
  - Batch only (`supportsStreaming: false`)
@@ -2,10 +2,10 @@
2
2
  * @file GoogleCloudSTTProvider.ts
3
3
  * @description Batch speech-to-text provider backed by Google Cloud Speech-to-Text V1 API.
4
4
  *
5
- * Credentials are resolved from the constructor argument:
6
- * - If the string contains `/` or `\`, it is treated as a path to a service-account JSON key file
7
- * and passed to the client as `keyFilename`.
8
- * - Otherwise the string is parsed as a JSON object and passed as `credentials`.
5
+ * Credentials are resolved from the constructor argument (see `clientOptionsFor`):
6
+ * - An empty string leaves the client on Application Default Credentials.
7
+ * - A string that starts with `{` is an inline service-account key, passed as `credentials`.
8
+ * - Any other string is a path to a service-account key file, passed as `keyFilename`.
9
9
  *
10
10
  * @module google-cloud-stt
11
11
  */
@@ -60,9 +60,9 @@ export interface AudioData {
60
60
  data: Buffer;
61
61
  /** Sample rate in Hz. Raw PCM defaults to 16000; a WAV or FLAC header supplies its own. */
62
62
  sampleRate?: number;
63
- /** MIME type, such as `'audio/wav'` or `'audio/flac'`. */
63
+ /** MIME type, such as `'audio/wav'`. Informational: the bytes decide the encoding. */
64
64
  mimeType?: string;
65
- /** Container format, such as `'wav'` or `'flac'`. */
65
+ /** Container format, such as `'wav'`. Informational: the bytes decide the encoding. */
66
66
  format?: string;
67
67
  }
68
68
  /**
@@ -86,10 +86,10 @@ export declare class GoogleCloudSTTProvider {
86
86
  /**
87
87
  * Create a new {@link GoogleCloudSTTProvider}.
88
88
  *
89
- * @param credentials - Either an absolute path to a service-account JSON key
90
- * file (any string that contains `/` or `\`), a JSON string containing
91
- * the service-account credentials object, or an empty string, which
92
- * leaves the client on Google's Application Default Credentials.
89
+ * @param credentials - The service-account key as JSON (a string that starts
90
+ * with `{`), a path to its key file, or an empty string, which leaves the
91
+ * client on Google's Application Default Credentials.
92
+ * @throws When `credentials` starts with `{` but is not valid JSON.
93
93
  */
94
94
  constructor(credentials: string);
95
95
  /**
@@ -1 +1 @@
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"}
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,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgED;;;;;;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;IAY/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"}
@@ -3,25 +3,35 @@
3
3
  * @file GoogleCloudSTTProvider.ts
4
4
  * @description Batch speech-to-text provider backed by Google Cloud Speech-to-Text V1 API.
5
5
  *
6
- * Credentials are resolved from the constructor argument:
7
- * - If the string contains `/` or `\`, it is treated as a path to a service-account JSON key file
8
- * and passed to the client as `keyFilename`.
9
- * - Otherwise the string is parsed as a JSON object and passed as `credentials`.
6
+ * Credentials are resolved from the constructor argument (see `clientOptionsFor`):
7
+ * - An empty string leaves the client on Application Default Credentials.
8
+ * - A string that starts with `{` is an inline service-account key, passed as `credentials`.
9
+ * - Any other string is a path to a service-account key file, passed as `keyFilename`.
10
10
  *
11
11
  * @module google-cloud-stt
12
12
  */
13
+ /** True when the bytes start with a RIFF/WAVE header. */
14
+ function hasWavHeader(data) {
15
+ return data.length >= 12 && data.toString('latin1', 0, 4) === 'RIFF' && data.toString('latin1', 8, 12) === 'WAVE';
16
+ }
17
+ /** True when the bytes start with the FLAC stream marker. */
18
+ function hasFlacHeader(data) {
19
+ return data.length >= 4 && data.toString('latin1', 0, 4) === 'fLaC';
20
+ }
13
21
  /**
14
22
  * The encoding fields of the recognition config for this audio.
15
23
  *
16
24
  * WAV and FLAC files carry a header that states the encoding and sample rate.
17
25
  * Google reads both from it and rejects a request whose stated values disagree
18
- * (google.cloud.speech.v1 `RecognitionConfig`), so for those formats the
26
+ * (google.cloud.speech.v1 `RecognitionConfig`), so for those files the
19
27
  * encoding is left out and the sample rate is sent only when the caller gives
20
28
  * one. Anything else is sent as raw LINEAR16 PCM.
29
+ *
30
+ * The bytes decide, not the declared type: AgentOS's speech adapter labels
31
+ * every buffer `audio/wav`, headerless PCM included.
21
32
  */
22
33
  function encodingFor(audio) {
23
- const declared = `${audio.mimeType ?? ''} ${audio.format ?? ''}`.toLowerCase();
24
- if (declared.includes('wav') || declared.includes('flac')) {
34
+ if (hasWavHeader(audio.data) || hasFlacHeader(audio.data)) {
25
35
  return audio.sampleRate ? { sampleRateHertz: audio.sampleRate } : {};
26
36
  }
27
37
  return { encoding: 'LINEAR16', sampleRateHertz: audio.sampleRate ?? 16000 };
@@ -33,6 +43,32 @@ function durationSeconds(duration) {
33
43
  const seconds = Number(duration.seconds ?? 0) + Number(duration.nanos ?? 0) / 1e9;
34
44
  return Number.isFinite(seconds) ? seconds : undefined;
35
45
  }
46
+ /**
47
+ * Client options for a credentials string, decided by its content:
48
+ * - empty or blank: none, so the client finds Application Default Credentials;
49
+ * - starting with `{`: an inline service-account key, passed as `credentials`;
50
+ * - anything else: a path to a key file, passed as `keyFilename`.
51
+ *
52
+ * Every real key holds `/` (its https URLs) and `\` (the `\n` escapes in
53
+ * `private_key`), so those characters cannot tell a key from a path.
54
+ *
55
+ * @throws When the string starts with `{` but is not valid JSON. The message
56
+ * names GOOGLE_CLOUD_STT_CREDENTIALS and quotes none of the value.
57
+ */
58
+ function clientOptionsFor(credentials) {
59
+ const text = credentials.trim();
60
+ if (!text)
61
+ return {};
62
+ if (!text.startsWith('{'))
63
+ return { keyFilename: text };
64
+ try {
65
+ return { credentials: JSON.parse(text) };
66
+ }
67
+ catch {
68
+ // JSON.parse's message quotes the text near the error, and here that text is key material.
69
+ throw new Error('GOOGLE_CLOUD_STT_CREDENTIALS starts with "{" but is not valid JSON: give the whole service-account key, or a path to its file.');
70
+ }
71
+ }
36
72
  /**
37
73
  * Google Cloud Speech-to-Text batch provider.
38
74
  *
@@ -54,26 +90,17 @@ export class GoogleCloudSTTProvider {
54
90
  /**
55
91
  * Create a new {@link GoogleCloudSTTProvider}.
56
92
  *
57
- * @param credentials - Either an absolute path to a service-account JSON key
58
- * file (any string that contains `/` or `\`), a JSON string containing
59
- * the service-account credentials object, or an empty string, which
60
- * leaves the client on Google's Application Default Credentials.
93
+ * @param credentials - The service-account key as JSON (a string that starts
94
+ * with `{`), a path to its key file, or an empty string, which leaves the
95
+ * client on Google's Application Default Credentials.
96
+ * @throws When `credentials` starts with `{` but is not valid JSON.
61
97
  */
62
98
  constructor(credentials) {
63
- if (!credentials.trim()) {
64
- // No key given: the Google client finds Application Default Credentials
65
- // (GOOGLE_APPLICATION_CREDENTIALS, gcloud, or the metadata server) when
66
- // it is first used, so the pack still loads without a configured secret.
67
- this._clientOptions = {};
68
- }
69
- else if (credentials.includes('/') || credentials.includes('\\')) {
70
- // Treat as a file path.
71
- this._clientOptions = { keyFilename: credentials };
72
- }
73
- else {
74
- // Treat as an inline JSON credentials object.
75
- this._clientOptions = { credentials: JSON.parse(credentials) };
76
- }
99
+ // An empty string gives no options: the Google client finds Application
100
+ // Default Credentials (GOOGLE_APPLICATION_CREDENTIALS, gcloud, or the
101
+ // metadata server) when it is first used, so the pack still loads without
102
+ // a configured secret.
103
+ this._clientOptions = clientOptionsFor(credentials);
77
104
  }
78
105
  // ---------------------------------------------------------------------------
79
106
  // Private helpers
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleCloudSTTProvider.js","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"AAAA,cAAc;AACd;;;;;;;;;;GAUG;AAmEH;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,KAAgB;IACnC,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/E,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1D,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,CAAC,UAAU,IAAI,KAAK,EAAE,CAAC;AAC9E,CAAC;AAED,0FAA0F;AAC1F,SAAS,eAAe,CAAC,QAAmE;IAC1F,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;IAClF,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,sBAAsB;IACjC,yEAAyE;IAChE,EAAE,GAAG,kBAAkB,CAAC;IAEjC,oCAAoC;IAC3B,WAAW,GAAG,6BAA6B,CAAC;IAErD,6DAA6D;IACpD,iBAAiB,GAAG,KAAK,CAAC;IAEnC,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;;;;OAIG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,UAAU,CACd,KAAgB,EAChB,OAA+B;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACvC,MAAM,YAAY,GAAG,OAAO,EAAE,QAAQ,IAAI,OAAO,CAAC;QAElD,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,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,YAAY,EAAE;SAChD,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE/B,MAAM,SAAS,GAAmE,EAAE,CAAC;QACrF,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;YAC/C,MAAM,GAAG,GAAG,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;YACtC,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,SAAS,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBACnC,UAAU,EAAE,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;gBAC3E,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,aAAa,CAAC;aAC/C,CAAC,CAAC;QACL,CAAC;QAED,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;QACnG,uEAAuE;QACvE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC;YACtF,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAClB,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,OAAiB,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;gBAC3G,KAAK,GAAG,CAAC,CAAC,OAAiB,CAAC;gBAC5B,OAAO,OAAO,CAAC;YACjB,CAAC,CAAC;YACJ,CAAC,CAAC,SAAS,CAAC;QAEd,OAAO;YACL,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YACxE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,IAAI,YAAY;YAChE,UAAU,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;YAChH,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,CAAC;YACP,QAAQ;YACR,gBAAgB,EAAE,UAAU;SAC7B,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"GoogleCloudSTTProvider.js","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"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"}
package/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@framers/agentos-ext-google-cloud-stt",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
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.3.0",
3
+ "version": "0.3.2",
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.12.5",
25
+ "@framers/agentos": "^0.12.8",
26
26
  "@google-cloud/speech": "^6.0.0",
27
27
  "typescript": "^5.5.0",
28
28
  "vitest": "^3.2.7"
@@ -3,10 +3,10 @@
3
3
  * @file GoogleCloudSTTProvider.ts
4
4
  * @description Batch speech-to-text provider backed by Google Cloud Speech-to-Text V1 API.
5
5
  *
6
- * Credentials are resolved from the constructor argument:
7
- * - If the string contains `/` or `\`, it is treated as a path to a service-account JSON key file
8
- * and passed to the client as `keyFilename`.
9
- * - Otherwise the string is parsed as a JSON object and passed as `credentials`.
6
+ * Credentials are resolved from the constructor argument (see `clientOptionsFor`):
7
+ * - An empty string leaves the client on Application Default Credentials.
8
+ * - A string that starts with `{` is an inline service-account key, passed as `credentials`.
9
+ * - Any other string is a path to a service-account key file, passed as `keyFilename`.
10
10
  *
11
11
  * @module google-cloud-stt
12
12
  */
@@ -70,24 +70,36 @@ export interface AudioData {
70
70
  data: Buffer;
71
71
  /** Sample rate in Hz. Raw PCM defaults to 16000; a WAV or FLAC header supplies its own. */
72
72
  sampleRate?: number;
73
- /** MIME type, such as `'audio/wav'` or `'audio/flac'`. */
73
+ /** MIME type, such as `'audio/wav'`. Informational: the bytes decide the encoding. */
74
74
  mimeType?: string;
75
- /** Container format, such as `'wav'` or `'flac'`. */
75
+ /** Container format, such as `'wav'`. Informational: the bytes decide the encoding. */
76
76
  format?: string;
77
77
  }
78
78
 
79
+ /** True when the bytes start with a RIFF/WAVE header. */
80
+ function hasWavHeader(data: Buffer): boolean {
81
+ return data.length >= 12 && data.toString('latin1', 0, 4) === 'RIFF' && data.toString('latin1', 8, 12) === 'WAVE';
82
+ }
83
+
84
+ /** True when the bytes start with the FLAC stream marker. */
85
+ function hasFlacHeader(data: Buffer): boolean {
86
+ return data.length >= 4 && data.toString('latin1', 0, 4) === 'fLaC';
87
+ }
88
+
79
89
  /**
80
90
  * The encoding fields of the recognition config for this audio.
81
91
  *
82
92
  * WAV and FLAC files carry a header that states the encoding and sample rate.
83
93
  * Google reads both from it and rejects a request whose stated values disagree
84
- * (google.cloud.speech.v1 `RecognitionConfig`), so for those formats the
94
+ * (google.cloud.speech.v1 `RecognitionConfig`), so for those files the
85
95
  * encoding is left out and the sample rate is sent only when the caller gives
86
96
  * one. Anything else is sent as raw LINEAR16 PCM.
97
+ *
98
+ * The bytes decide, not the declared type: AgentOS's speech adapter labels
99
+ * every buffer `audio/wav`, headerless PCM included.
87
100
  */
88
101
  function encodingFor(audio: AudioData): { encoding?: string; sampleRateHertz?: number } {
89
- const declared = `${audio.mimeType ?? ''} ${audio.format ?? ''}`.toLowerCase();
90
- if (declared.includes('wav') || declared.includes('flac')) {
102
+ if (hasWavHeader(audio.data) || hasFlacHeader(audio.data)) {
91
103
  return audio.sampleRate ? { sampleRateHertz: audio.sampleRate } : {};
92
104
  }
93
105
  return { encoding: 'LINEAR16', sampleRateHertz: audio.sampleRate ?? 16000 };
@@ -100,6 +112,32 @@ function durationSeconds(duration: { seconds?: unknown; nanos?: unknown } | null
100
112
  return Number.isFinite(seconds) ? seconds : undefined;
101
113
  }
102
114
 
115
+ /**
116
+ * Client options for a credentials string, decided by its content:
117
+ * - empty or blank: none, so the client finds Application Default Credentials;
118
+ * - starting with `{`: an inline service-account key, passed as `credentials`;
119
+ * - anything else: a path to a key file, passed as `keyFilename`.
120
+ *
121
+ * Every real key holds `/` (its https URLs) and `\` (the `\n` escapes in
122
+ * `private_key`), so those characters cannot tell a key from a path.
123
+ *
124
+ * @throws When the string starts with `{` but is not valid JSON. The message
125
+ * names GOOGLE_CLOUD_STT_CREDENTIALS and quotes none of the value.
126
+ */
127
+ function clientOptionsFor(credentials: string): Record<string, unknown> {
128
+ const text = credentials.trim();
129
+ if (!text) return {};
130
+ if (!text.startsWith('{')) return { keyFilename: text };
131
+ try {
132
+ return { credentials: JSON.parse(text) as Record<string, unknown> };
133
+ } catch {
134
+ // JSON.parse's message quotes the text near the error, and here that text is key material.
135
+ throw new Error(
136
+ 'GOOGLE_CLOUD_STT_CREDENTIALS starts with "{" but is not valid JSON: give the whole service-account key, or a path to its file.',
137
+ );
138
+ }
139
+ }
140
+
103
141
  /**
104
142
  * Google Cloud Speech-to-Text batch provider.
105
143
  *
@@ -126,24 +164,17 @@ export class GoogleCloudSTTProvider {
126
164
  /**
127
165
  * Create a new {@link GoogleCloudSTTProvider}.
128
166
  *
129
- * @param credentials - Either an absolute path to a service-account JSON key
130
- * file (any string that contains `/` or `\`), a JSON string containing
131
- * the service-account credentials object, or an empty string, which
132
- * leaves the client on Google's Application Default Credentials.
167
+ * @param credentials - The service-account key as JSON (a string that starts
168
+ * with `{`), a path to its key file, or an empty string, which leaves the
169
+ * client on Google's Application Default Credentials.
170
+ * @throws When `credentials` starts with `{` but is not valid JSON.
133
171
  */
134
172
  constructor(credentials: string) {
135
- if (!credentials.trim()) {
136
- // No key given: the Google client finds Application Default Credentials
137
- // (GOOGLE_APPLICATION_CREDENTIALS, gcloud, or the metadata server) when
138
- // it is first used, so the pack still loads without a configured secret.
139
- this._clientOptions = {};
140
- } else if (credentials.includes('/') || credentials.includes('\\')) {
141
- // Treat as a file path.
142
- this._clientOptions = { keyFilename: credentials };
143
- } else {
144
- // Treat as an inline JSON credentials object.
145
- this._clientOptions = { credentials: JSON.parse(credentials) as Record<string, unknown> };
146
- }
173
+ // An empty string gives no options: the Google client finds Application
174
+ // Default Credentials (GOOGLE_APPLICATION_CREDENTIALS, gcloud, or the
175
+ // metadata server) when it is first used, so the pack still loads without
176
+ // a configured secret.
177
+ this._clientOptions = clientOptionsFor(credentials);
147
178
  }
148
179
 
149
180
  // ---------------------------------------------------------------------------