@framers/agentos-ext-amazon-polly 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/LICENSE +23 -0
- package/SKILL.md +51 -0
- package/dist/AmazonPollyTTSProvider.d.ts +114 -0
- package/dist/AmazonPollyTTSProvider.d.ts.map +1 -0
- package/dist/AmazonPollyTTSProvider.js +142 -0
- package/dist/AmazonPollyTTSProvider.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/manifest.json +8 -0
- package/package.json +44 -0
- package/src/AmazonPollyTTSProvider.ts +220 -0
- package/src/index.ts +116 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Framers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: amazon-polly
|
|
3
|
+
description: Neural text-to-speech via Amazon Polly
|
|
4
|
+
category: voice
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Amazon Polly TTS
|
|
8
|
+
|
|
9
|
+
Text-to-speech synthesis using Amazon Polly's Neural engine with MP3 output.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Set the following secrets in your environment or agent secrets store:
|
|
14
|
+
|
|
15
|
+
| Secret | Description |
|
|
16
|
+
|---------------------|--------------------------|
|
|
17
|
+
| `AWS_ACCESS_KEY_ID` | IAM access key ID |
|
|
18
|
+
| `AWS_SECRET_ACCESS_KEY` | IAM secret access key |
|
|
19
|
+
| `AWS_REGION` | AWS region (default `us-east-1`) |
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- Neural engine (high-quality, natural-sounding voices)
|
|
24
|
+
- MP3 audio output
|
|
25
|
+
- `listAvailableVoices()` to enumerate all Polly voices
|
|
26
|
+
- Default voice: `Joanna` (en-US, Neural)
|
|
27
|
+
|
|
28
|
+
## Configuration
|
|
29
|
+
|
|
30
|
+
In `agent.config.json`:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"voice": {
|
|
35
|
+
"tts": "amazon-polly"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Provider-specific options:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"voice": {
|
|
45
|
+
"tts": "amazon-polly",
|
|
46
|
+
"providerOptions": {
|
|
47
|
+
"voice": "Matthew"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file AmazonPollyTTSProvider.ts
|
|
3
|
+
* @description Text-to-speech provider backed by Amazon Polly Neural engine.
|
|
4
|
+
*
|
|
5
|
+
* The provider uses the AWS SDK v3 `@aws-sdk/client-polly` package, which is
|
|
6
|
+
* declared as a peer dependency so it is only loaded at runtime.
|
|
7
|
+
*
|
|
8
|
+
* Audio is synthesised in MP3 format using the Neural engine. The response
|
|
9
|
+
* `AudioStream` (a `ReadableStream` in Node 18+) is fully collected into a
|
|
10
|
+
* `Buffer` before being returned to the caller.
|
|
11
|
+
*
|
|
12
|
+
* @module amazon-polly
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Constructor options for {@link AmazonPollyTTSProvider}.
|
|
16
|
+
*/
|
|
17
|
+
export interface AmazonPollyCredentials {
|
|
18
|
+
/** AWS IAM access key ID. */
|
|
19
|
+
accessKeyId: string;
|
|
20
|
+
/** AWS IAM secret access key. */
|
|
21
|
+
secretAccessKey: string;
|
|
22
|
+
/**
|
|
23
|
+
* AWS region where the Polly endpoint lives.
|
|
24
|
+
* @defaultValue `'us-east-1'`
|
|
25
|
+
*/
|
|
26
|
+
region?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A voice available on Amazon Polly.
|
|
30
|
+
*
|
|
31
|
+
* Mirrors the generic `SpeechVoice` shape used across the AgentOS voice pipeline.
|
|
32
|
+
*/
|
|
33
|
+
export interface SpeechVoice {
|
|
34
|
+
/** Provider-specific voice identifier (e.g. `'Joanna'`). */
|
|
35
|
+
id: string;
|
|
36
|
+
/** Human-readable display name. */
|
|
37
|
+
name: string;
|
|
38
|
+
/** Primary BCP-47 language code supported by this voice. */
|
|
39
|
+
languageCode: string;
|
|
40
|
+
/** Biological gender label from the API (`'Male'`, `'Female'`). */
|
|
41
|
+
gender?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Synthesised audio returned by {@link AmazonPollyTTSProvider.synthesize}.
|
|
45
|
+
*/
|
|
46
|
+
export interface SynthesisResult {
|
|
47
|
+
/** Raw MP3 audio bytes. */
|
|
48
|
+
audioBuffer: Buffer;
|
|
49
|
+
/** MIME type of the audio data. Always `'audio/mpeg'` for this provider. */
|
|
50
|
+
mimeType: 'audio/mpeg';
|
|
51
|
+
/** Billable cost of the request (placeholder — always 0). */
|
|
52
|
+
cost: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Per-call synthesis options forwarded to the Amazon Polly API.
|
|
56
|
+
*/
|
|
57
|
+
export interface AmazonPollyTTSOptions {
|
|
58
|
+
/**
|
|
59
|
+
* Polly VoiceId (e.g. `'Joanna'`, `'Matthew'`).
|
|
60
|
+
* @defaultValue `'Joanna'`
|
|
61
|
+
* @see {@link https://docs.aws.amazon.com/polly/latest/dg/voicelist.html}
|
|
62
|
+
*/
|
|
63
|
+
voice?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Amazon Polly text-to-speech provider.
|
|
67
|
+
*
|
|
68
|
+
* Implements the `TextToSpeechProvider` contract expected by the AgentOS voice
|
|
69
|
+
* pipeline without taking a hard runtime dependency on the interface types.
|
|
70
|
+
*/
|
|
71
|
+
export declare class AmazonPollyTTSProvider {
|
|
72
|
+
/** Stable provider identifier used by the AgentOS extension registry. */
|
|
73
|
+
readonly id = "amazon-polly";
|
|
74
|
+
/** Lazily initialised Polly client. */
|
|
75
|
+
private _client;
|
|
76
|
+
/** Client configuration stored for lazy initialisation. */
|
|
77
|
+
private readonly _config;
|
|
78
|
+
/**
|
|
79
|
+
* Create a new {@link AmazonPollyTTSProvider}.
|
|
80
|
+
*
|
|
81
|
+
* @param credentials - AWS credentials and optional region.
|
|
82
|
+
*/
|
|
83
|
+
constructor(credentials: AmazonPollyCredentials);
|
|
84
|
+
/**
|
|
85
|
+
* Lazily create and return the `PollyClient` instance.
|
|
86
|
+
*/
|
|
87
|
+
private _getClient;
|
|
88
|
+
/**
|
|
89
|
+
* Drain a Node.js `Readable` or a WHATWG `ReadableStream` into a `Buffer`.
|
|
90
|
+
*
|
|
91
|
+
* Amazon Polly v3 returns the audio stream as a `Readable` in Node
|
|
92
|
+
* environments. This helper handles both the Node stream API and the
|
|
93
|
+
* WHATWG `ReadableStream` API (for edge runtimes).
|
|
94
|
+
*
|
|
95
|
+
* @param stream - The audio stream from the Polly response.
|
|
96
|
+
* @returns A `Buffer` containing the full audio payload.
|
|
97
|
+
*/
|
|
98
|
+
private _collectStream;
|
|
99
|
+
/**
|
|
100
|
+
* Synthesise text to MP3 audio using Amazon Polly Neural engine.
|
|
101
|
+
*
|
|
102
|
+
* @param text - Plain text to synthesise.
|
|
103
|
+
* @param options - Optional per-call parameters (voice ID).
|
|
104
|
+
* @returns {@link SynthesisResult} containing the raw MP3 buffer.
|
|
105
|
+
*/
|
|
106
|
+
synthesize(text: string, options?: AmazonPollyTTSOptions): Promise<SynthesisResult>;
|
|
107
|
+
/**
|
|
108
|
+
* List all voices available on Amazon Polly.
|
|
109
|
+
*
|
|
110
|
+
* @returns Array of {@link SpeechVoice} objects.
|
|
111
|
+
*/
|
|
112
|
+
listAvailableVoices(): Promise<SpeechVoice[]>;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=AmazonPollyTTSProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AmazonPollyTTSProvider.d.ts","sourceRoot":"","sources":["../src/AmazonPollyTTSProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAC;IACX,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,EAAE,YAAY,CAAC;IACvB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,qBAAa,sBAAsB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,kBAAkB;IAE7B,uCAAuC;IACvC,OAAO,CAAC,OAAO,CAA4B;IAE3C,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAE3D;;;;OAIG;gBACS,WAAW,EAAE,sBAAsB;IAY/C;;OAEG;YACW,UAAU;IAcxB;;;;;;;;;OASG;YACW,cAAc;IAuC5B;;;;;;OAMG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;IAsBzF;;;;OAIG;IACG,mBAAmB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAcpD"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file AmazonPollyTTSProvider.ts
|
|
3
|
+
* @description Text-to-speech provider backed by Amazon Polly Neural engine.
|
|
4
|
+
*
|
|
5
|
+
* The provider uses the AWS SDK v3 `@aws-sdk/client-polly` package, which is
|
|
6
|
+
* declared as a peer dependency so it is only loaded at runtime.
|
|
7
|
+
*
|
|
8
|
+
* Audio is synthesised in MP3 format using the Neural engine. The response
|
|
9
|
+
* `AudioStream` (a `ReadableStream` in Node 18+) is fully collected into a
|
|
10
|
+
* `Buffer` before being returned to the caller.
|
|
11
|
+
*
|
|
12
|
+
* @module amazon-polly
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Amazon Polly text-to-speech provider.
|
|
16
|
+
*
|
|
17
|
+
* Implements the `TextToSpeechProvider` contract expected by the AgentOS voice
|
|
18
|
+
* pipeline without taking a hard runtime dependency on the interface types.
|
|
19
|
+
*/
|
|
20
|
+
export class AmazonPollyTTSProvider {
|
|
21
|
+
/** Stable provider identifier used by the AgentOS extension registry. */
|
|
22
|
+
id = 'amazon-polly';
|
|
23
|
+
/** Lazily initialised Polly client. */
|
|
24
|
+
_client = null;
|
|
25
|
+
/** Client configuration stored for lazy initialisation. */
|
|
26
|
+
_config;
|
|
27
|
+
/**
|
|
28
|
+
* Create a new {@link AmazonPollyTTSProvider}.
|
|
29
|
+
*
|
|
30
|
+
* @param credentials - AWS credentials and optional region.
|
|
31
|
+
*/
|
|
32
|
+
constructor(credentials) {
|
|
33
|
+
this._config = {
|
|
34
|
+
accessKeyId: credentials.accessKeyId,
|
|
35
|
+
secretAccessKey: credentials.secretAccessKey,
|
|
36
|
+
region: credentials.region ?? 'us-east-1',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Private helpers
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
/**
|
|
43
|
+
* Lazily create and return the `PollyClient` instance.
|
|
44
|
+
*/
|
|
45
|
+
async _getClient() {
|
|
46
|
+
if (!this._client) {
|
|
47
|
+
const { PollyClient } = await import('@aws-sdk/client-polly');
|
|
48
|
+
this._client = new PollyClient({
|
|
49
|
+
region: this._config.region,
|
|
50
|
+
credentials: {
|
|
51
|
+
accessKeyId: this._config.accessKeyId,
|
|
52
|
+
secretAccessKey: this._config.secretAccessKey,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return this._client;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Drain a Node.js `Readable` or a WHATWG `ReadableStream` into a `Buffer`.
|
|
60
|
+
*
|
|
61
|
+
* Amazon Polly v3 returns the audio stream as a `Readable` in Node
|
|
62
|
+
* environments. This helper handles both the Node stream API and the
|
|
63
|
+
* WHATWG `ReadableStream` API (for edge runtimes).
|
|
64
|
+
*
|
|
65
|
+
* @param stream - The audio stream from the Polly response.
|
|
66
|
+
* @returns A `Buffer` containing the full audio payload.
|
|
67
|
+
*/
|
|
68
|
+
async _collectStream(stream) {
|
|
69
|
+
// Node.js Readable (most common in server environments)
|
|
70
|
+
if (stream !== null &&
|
|
71
|
+
typeof stream === 'object' &&
|
|
72
|
+
typeof stream.on === 'function') {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
const chunks = [];
|
|
75
|
+
const readable = stream;
|
|
76
|
+
readable.on('data', (chunk) => chunks.push(chunk));
|
|
77
|
+
readable.on('end', () => resolve(Buffer.concat(chunks)));
|
|
78
|
+
readable.on('error', reject);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// WHATWG ReadableStream (edge runtimes)
|
|
82
|
+
if (stream !== null &&
|
|
83
|
+
typeof stream === 'object' &&
|
|
84
|
+
typeof stream.getReader === 'function') {
|
|
85
|
+
const reader = stream.getReader();
|
|
86
|
+
const chunks = [];
|
|
87
|
+
for (;;) {
|
|
88
|
+
const { done, value } = await reader.read();
|
|
89
|
+
if (done)
|
|
90
|
+
break;
|
|
91
|
+
if (value)
|
|
92
|
+
chunks.push(value);
|
|
93
|
+
}
|
|
94
|
+
return Buffer.concat(chunks);
|
|
95
|
+
}
|
|
96
|
+
throw new TypeError('Unsupported AudioStream type returned by Polly');
|
|
97
|
+
}
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Public API
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
/**
|
|
102
|
+
* Synthesise text to MP3 audio using Amazon Polly Neural engine.
|
|
103
|
+
*
|
|
104
|
+
* @param text - Plain text to synthesise.
|
|
105
|
+
* @param options - Optional per-call parameters (voice ID).
|
|
106
|
+
* @returns {@link SynthesisResult} containing the raw MP3 buffer.
|
|
107
|
+
*/
|
|
108
|
+
async synthesize(text, options) {
|
|
109
|
+
const client = await this._getClient();
|
|
110
|
+
const { SynthesizeSpeechCommand } = await import('@aws-sdk/client-polly');
|
|
111
|
+
const response = await client.send(new SynthesizeSpeechCommand({
|
|
112
|
+
Engine: 'neural',
|
|
113
|
+
OutputFormat: 'mp3',
|
|
114
|
+
Text: text,
|
|
115
|
+
VoiceId: options?.voice ?? 'Joanna',
|
|
116
|
+
}));
|
|
117
|
+
const audioBuffer = await this._collectStream(response.AudioStream);
|
|
118
|
+
return {
|
|
119
|
+
audioBuffer,
|
|
120
|
+
mimeType: 'audio/mpeg',
|
|
121
|
+
cost: 0,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* List all voices available on Amazon Polly.
|
|
126
|
+
*
|
|
127
|
+
* @returns Array of {@link SpeechVoice} objects.
|
|
128
|
+
*/
|
|
129
|
+
async listAvailableVoices() {
|
|
130
|
+
const client = await this._getClient();
|
|
131
|
+
const { DescribeVoicesCommand } = await import('@aws-sdk/client-polly');
|
|
132
|
+
const response = await client.send(new DescribeVoicesCommand({}));
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
134
|
+
return (response.Voices ?? []).map((v) => ({
|
|
135
|
+
id: v.Id ?? '',
|
|
136
|
+
name: v.Name ?? '',
|
|
137
|
+
languageCode: v.LanguageCode ?? '',
|
|
138
|
+
gender: v.Gender ?? undefined,
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=AmazonPollyTTSProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AmazonPollyTTSProvider.js","sourceRoot":"","sources":["../src/AmazonPollyTTSProvider.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @description Pack factory for the Amazon Polly TTS extension pack.
|
|
4
|
+
*
|
|
5
|
+
* Exports the main {@link createAmazonPollyTTS} factory function and the
|
|
6
|
+
* {@link createExtensionPack} bridge function conforming to the AgentOS
|
|
7
|
+
* manifest factory convention.
|
|
8
|
+
*
|
|
9
|
+
* ### Usage (direct)
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { createAmazonPollyTTS } from '@framers/agentos-ext-amazon-polly';
|
|
12
|
+
*
|
|
13
|
+
* const tts = createAmazonPollyTTS({
|
|
14
|
+
* accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
15
|
+
* secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
16
|
+
* region: 'us-east-1',
|
|
17
|
+
* });
|
|
18
|
+
* const result = await tts.synthesize('Hello, world!');
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* ### Usage (manifest-driven)
|
|
22
|
+
* ```json
|
|
23
|
+
* { "packs": [{ "module": "@framers/agentos-ext-amazon-polly" }] }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @module amazon-polly
|
|
27
|
+
*/
|
|
28
|
+
import { AmazonPollyTTSProvider } from './AmazonPollyTTSProvider.js';
|
|
29
|
+
import type { AmazonPollyCredentials } from './AmazonPollyTTSProvider.js';
|
|
30
|
+
/** Subset of ExtensionDescriptor required by this pack. */
|
|
31
|
+
interface ExtensionDescriptor {
|
|
32
|
+
id: string;
|
|
33
|
+
kind: string;
|
|
34
|
+
payload: unknown;
|
|
35
|
+
enableByDefault?: boolean;
|
|
36
|
+
metadata?: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
/** Subset of ExtensionPack required by this pack. */
|
|
39
|
+
interface ExtensionPack {
|
|
40
|
+
id: string;
|
|
41
|
+
descriptors: ExtensionDescriptor[];
|
|
42
|
+
}
|
|
43
|
+
/** Subset of ExtensionPackContext required by this pack. */
|
|
44
|
+
interface ExtensionPackContext {
|
|
45
|
+
getSecret?: (id: string) => string | undefined;
|
|
46
|
+
options?: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create a standalone {@link AmazonPollyTTSProvider} instance.
|
|
50
|
+
*
|
|
51
|
+
* @param credentials - AWS credentials and optional region.
|
|
52
|
+
* @returns Configured {@link AmazonPollyTTSProvider}.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createAmazonPollyTTS(credentials: AmazonPollyCredentials): AmazonPollyTTSProvider;
|
|
55
|
+
/**
|
|
56
|
+
* AgentOS manifest factory function.
|
|
57
|
+
*
|
|
58
|
+
* Reads `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and optionally
|
|
59
|
+
* `AWS_REGION` from the pack context secrets, then returns an
|
|
60
|
+
* {@link ExtensionPack} containing a single `tts-provider` descriptor backed
|
|
61
|
+
* by {@link AmazonPollyTTSProvider}.
|
|
62
|
+
*
|
|
63
|
+
* @param context - Pack context supplied by the extension manager.
|
|
64
|
+
* @returns A fully configured {@link ExtensionPack}.
|
|
65
|
+
*/
|
|
66
|
+
export declare function createExtensionPack(context: ExtensionPackContext): ExtensionPack;
|
|
67
|
+
export { AmazonPollyTTSProvider } from './AmazonPollyTTSProvider.js';
|
|
68
|
+
export type { AmazonPollyCredentials, AmazonPollyTTSOptions, SpeechVoice, SynthesisResult, } from './AmazonPollyTTSProvider.js';
|
|
69
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAM1E,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;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,sBAAsB,GAAG,sBAAsB,CAEhG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAmBhF;AAMD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,WAAW,EACX,eAAe,GAChB,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @description Pack factory for the Amazon Polly TTS extension pack.
|
|
4
|
+
*
|
|
5
|
+
* Exports the main {@link createAmazonPollyTTS} factory function and the
|
|
6
|
+
* {@link createExtensionPack} bridge function conforming to the AgentOS
|
|
7
|
+
* manifest factory convention.
|
|
8
|
+
*
|
|
9
|
+
* ### Usage (direct)
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { createAmazonPollyTTS } from '@framers/agentos-ext-amazon-polly';
|
|
12
|
+
*
|
|
13
|
+
* const tts = createAmazonPollyTTS({
|
|
14
|
+
* accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
15
|
+
* secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
16
|
+
* region: 'us-east-1',
|
|
17
|
+
* });
|
|
18
|
+
* const result = await tts.synthesize('Hello, world!');
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* ### Usage (manifest-driven)
|
|
22
|
+
* ```json
|
|
23
|
+
* { "packs": [{ "module": "@framers/agentos-ext-amazon-polly" }] }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @module amazon-polly
|
|
27
|
+
*/
|
|
28
|
+
import { AmazonPollyTTSProvider } from './AmazonPollyTTSProvider.js';
|
|
29
|
+
/** Kind constant matching packages/agentos/src/extensions/types.ts. */
|
|
30
|
+
const EXTENSION_KIND_TTS = 'tts-provider';
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Factories
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
/**
|
|
35
|
+
* Create a standalone {@link AmazonPollyTTSProvider} instance.
|
|
36
|
+
*
|
|
37
|
+
* @param credentials - AWS credentials and optional region.
|
|
38
|
+
* @returns Configured {@link AmazonPollyTTSProvider}.
|
|
39
|
+
*/
|
|
40
|
+
export function createAmazonPollyTTS(credentials) {
|
|
41
|
+
return new AmazonPollyTTSProvider(credentials);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* AgentOS manifest factory function.
|
|
45
|
+
*
|
|
46
|
+
* Reads `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and optionally
|
|
47
|
+
* `AWS_REGION` from the pack context secrets, then returns an
|
|
48
|
+
* {@link ExtensionPack} containing a single `tts-provider` descriptor backed
|
|
49
|
+
* by {@link AmazonPollyTTSProvider}.
|
|
50
|
+
*
|
|
51
|
+
* @param context - Pack context supplied by the extension manager.
|
|
52
|
+
* @returns A fully configured {@link ExtensionPack}.
|
|
53
|
+
*/
|
|
54
|
+
export function createExtensionPack(context) {
|
|
55
|
+
const provider = new AmazonPollyTTSProvider({
|
|
56
|
+
accessKeyId: context.getSecret?.('AWS_ACCESS_KEY_ID') ?? '',
|
|
57
|
+
secretAccessKey: context.getSecret?.('AWS_SECRET_ACCESS_KEY') ?? '',
|
|
58
|
+
region: context.getSecret?.('AWS_REGION'),
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
id: 'amazon-polly',
|
|
62
|
+
descriptors: [
|
|
63
|
+
{
|
|
64
|
+
id: 'amazon-polly',
|
|
65
|
+
kind: EXTENSION_KIND_TTS,
|
|
66
|
+
payload: provider,
|
|
67
|
+
enableByDefault: true,
|
|
68
|
+
metadata: { providerId: 'amazon-polly' },
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Re-exports
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
export { AmazonPollyTTSProvider } from './AmazonPollyTTSProvider.js';
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AA4BrE,uEAAuE;AACvE,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAE1C,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmC;IACtE,OAAO,IAAI,sBAAsB,CAAC,WAAW,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAA6B;IAC/D,MAAM,QAAQ,GAAG,IAAI,sBAAsB,CAAC;QAC1C,WAAW,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE;QAC3D,eAAe,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,uBAAuB,CAAC,IAAI,EAAE;QACnE,MAAM,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,YAAY,CAAC;KAC1C,CAAC,CAAC;IAEH,OAAO;QACL,EAAE,EAAE,cAAc;QAClB,WAAW,EAAE;YACX;gBACE,EAAE,EAAE,cAAc;gBAClB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,QAAQ;gBACjB,eAAe,EAAE,IAAI;gBACrB,QAAQ,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE;aACzC;SACF;KACF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC"}
|
package/manifest.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@framers/agentos-ext-amazon-polly",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Text-to-speech via Amazon Polly for AgentOS voice pipeline",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src",
|
|
17
|
+
"SKILL.md",
|
|
18
|
+
"manifest.json"
|
|
19
|
+
],
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@framers/agentos": "^0.1.0",
|
|
22
|
+
"@aws-sdk/client-polly": "^3.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@aws-sdk/client-polly": "^3.0.0",
|
|
26
|
+
"typescript": "^5.5.0",
|
|
27
|
+
"vitest": "^1.6.0",
|
|
28
|
+
"@framers/agentos": "0.1.94"
|
|
29
|
+
},
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"author": "Frame.dev",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/framersai/agentos-extensions.git",
|
|
35
|
+
"directory": "registry/curated/voice/amazon-polly"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.json",
|
|
42
|
+
"test": "vitest run"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file AmazonPollyTTSProvider.ts
|
|
3
|
+
* @description Text-to-speech provider backed by Amazon Polly Neural engine.
|
|
4
|
+
*
|
|
5
|
+
* The provider uses the AWS SDK v3 `@aws-sdk/client-polly` package, which is
|
|
6
|
+
* declared as a peer dependency so it is only loaded at runtime.
|
|
7
|
+
*
|
|
8
|
+
* Audio is synthesised in MP3 format using the Neural engine. The response
|
|
9
|
+
* `AudioStream` (a `ReadableStream` in Node 18+) is fully collected into a
|
|
10
|
+
* `Buffer` before being returned to the caller.
|
|
11
|
+
*
|
|
12
|
+
* @module amazon-polly
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
type PollyClient = any;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Constructor options for {@link AmazonPollyTTSProvider}.
|
|
20
|
+
*/
|
|
21
|
+
export interface AmazonPollyCredentials {
|
|
22
|
+
/** AWS IAM access key ID. */
|
|
23
|
+
accessKeyId: string;
|
|
24
|
+
/** AWS IAM secret access key. */
|
|
25
|
+
secretAccessKey: string;
|
|
26
|
+
/**
|
|
27
|
+
* AWS region where the Polly endpoint lives.
|
|
28
|
+
* @defaultValue `'us-east-1'`
|
|
29
|
+
*/
|
|
30
|
+
region?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A voice available on Amazon Polly.
|
|
35
|
+
*
|
|
36
|
+
* Mirrors the generic `SpeechVoice` shape used across the AgentOS voice pipeline.
|
|
37
|
+
*/
|
|
38
|
+
export interface SpeechVoice {
|
|
39
|
+
/** Provider-specific voice identifier (e.g. `'Joanna'`). */
|
|
40
|
+
id: string;
|
|
41
|
+
/** Human-readable display name. */
|
|
42
|
+
name: string;
|
|
43
|
+
/** Primary BCP-47 language code supported by this voice. */
|
|
44
|
+
languageCode: string;
|
|
45
|
+
/** Biological gender label from the API (`'Male'`, `'Female'`). */
|
|
46
|
+
gender?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Synthesised audio returned by {@link AmazonPollyTTSProvider.synthesize}.
|
|
51
|
+
*/
|
|
52
|
+
export interface SynthesisResult {
|
|
53
|
+
/** Raw MP3 audio bytes. */
|
|
54
|
+
audioBuffer: Buffer;
|
|
55
|
+
/** MIME type of the audio data. Always `'audio/mpeg'` for this provider. */
|
|
56
|
+
mimeType: 'audio/mpeg';
|
|
57
|
+
/** Billable cost of the request (placeholder — always 0). */
|
|
58
|
+
cost: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Per-call synthesis options forwarded to the Amazon Polly API.
|
|
63
|
+
*/
|
|
64
|
+
export interface AmazonPollyTTSOptions {
|
|
65
|
+
/**
|
|
66
|
+
* Polly VoiceId (e.g. `'Joanna'`, `'Matthew'`).
|
|
67
|
+
* @defaultValue `'Joanna'`
|
|
68
|
+
* @see {@link https://docs.aws.amazon.com/polly/latest/dg/voicelist.html}
|
|
69
|
+
*/
|
|
70
|
+
voice?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Amazon Polly text-to-speech provider.
|
|
75
|
+
*
|
|
76
|
+
* Implements the `TextToSpeechProvider` contract expected by the AgentOS voice
|
|
77
|
+
* pipeline without taking a hard runtime dependency on the interface types.
|
|
78
|
+
*/
|
|
79
|
+
export class AmazonPollyTTSProvider {
|
|
80
|
+
/** Stable provider identifier used by the AgentOS extension registry. */
|
|
81
|
+
readonly id = 'amazon-polly';
|
|
82
|
+
|
|
83
|
+
/** Lazily initialised Polly client. */
|
|
84
|
+
private _client: PollyClient | null = null;
|
|
85
|
+
|
|
86
|
+
/** Client configuration stored for lazy initialisation. */
|
|
87
|
+
private readonly _config: Required<AmazonPollyCredentials>;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Create a new {@link AmazonPollyTTSProvider}.
|
|
91
|
+
*
|
|
92
|
+
* @param credentials - AWS credentials and optional region.
|
|
93
|
+
*/
|
|
94
|
+
constructor(credentials: AmazonPollyCredentials) {
|
|
95
|
+
this._config = {
|
|
96
|
+
accessKeyId: credentials.accessKeyId,
|
|
97
|
+
secretAccessKey: credentials.secretAccessKey,
|
|
98
|
+
region: credentials.region ?? 'us-east-1',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
// Private helpers
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Lazily create and return the `PollyClient` instance.
|
|
108
|
+
*/
|
|
109
|
+
private async _getClient(): Promise<PollyClient> {
|
|
110
|
+
if (!this._client) {
|
|
111
|
+
const { PollyClient } = await import('@aws-sdk/client-polly');
|
|
112
|
+
this._client = new PollyClient({
|
|
113
|
+
region: this._config.region,
|
|
114
|
+
credentials: {
|
|
115
|
+
accessKeyId: this._config.accessKeyId,
|
|
116
|
+
secretAccessKey: this._config.secretAccessKey,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return this._client;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Drain a Node.js `Readable` or a WHATWG `ReadableStream` into a `Buffer`.
|
|
125
|
+
*
|
|
126
|
+
* Amazon Polly v3 returns the audio stream as a `Readable` in Node
|
|
127
|
+
* environments. This helper handles both the Node stream API and the
|
|
128
|
+
* WHATWG `ReadableStream` API (for edge runtimes).
|
|
129
|
+
*
|
|
130
|
+
* @param stream - The audio stream from the Polly response.
|
|
131
|
+
* @returns A `Buffer` containing the full audio payload.
|
|
132
|
+
*/
|
|
133
|
+
private async _collectStream(stream: unknown): Promise<Buffer> {
|
|
134
|
+
// Node.js Readable (most common in server environments)
|
|
135
|
+
if (
|
|
136
|
+
stream !== null &&
|
|
137
|
+
typeof stream === 'object' &&
|
|
138
|
+
typeof (stream as { on?: unknown }).on === 'function'
|
|
139
|
+
) {
|
|
140
|
+
return new Promise<Buffer>((resolve, reject) => {
|
|
141
|
+
const chunks: Buffer[] = [];
|
|
142
|
+
const readable = stream as NodeJS.ReadableStream;
|
|
143
|
+
readable.on('data', (chunk: Buffer) => chunks.push(chunk));
|
|
144
|
+
readable.on('end', () => resolve(Buffer.concat(chunks)));
|
|
145
|
+
readable.on('error', reject);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// WHATWG ReadableStream (edge runtimes)
|
|
150
|
+
if (
|
|
151
|
+
stream !== null &&
|
|
152
|
+
typeof stream === 'object' &&
|
|
153
|
+
typeof (stream as { getReader?: unknown }).getReader === 'function'
|
|
154
|
+
) {
|
|
155
|
+
const reader = (stream as ReadableStream<Uint8Array>).getReader();
|
|
156
|
+
const chunks: Uint8Array[] = [];
|
|
157
|
+
for (;;) {
|
|
158
|
+
const { done, value } = await reader.read();
|
|
159
|
+
if (done) break;
|
|
160
|
+
if (value) chunks.push(value);
|
|
161
|
+
}
|
|
162
|
+
return Buffer.concat(chunks);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
throw new TypeError('Unsupported AudioStream type returned by Polly');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Public API
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Synthesise text to MP3 audio using Amazon Polly Neural engine.
|
|
174
|
+
*
|
|
175
|
+
* @param text - Plain text to synthesise.
|
|
176
|
+
* @param options - Optional per-call parameters (voice ID).
|
|
177
|
+
* @returns {@link SynthesisResult} containing the raw MP3 buffer.
|
|
178
|
+
*/
|
|
179
|
+
async synthesize(text: string, options?: AmazonPollyTTSOptions): Promise<SynthesisResult> {
|
|
180
|
+
const client = await this._getClient();
|
|
181
|
+
|
|
182
|
+
const { SynthesizeSpeechCommand } = await import('@aws-sdk/client-polly');
|
|
183
|
+
const response = await client.send(
|
|
184
|
+
new SynthesizeSpeechCommand({
|
|
185
|
+
Engine: 'neural',
|
|
186
|
+
OutputFormat: 'mp3',
|
|
187
|
+
Text: text,
|
|
188
|
+
VoiceId: options?.voice ?? 'Joanna',
|
|
189
|
+
}),
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const audioBuffer = await this._collectStream(response.AudioStream);
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
audioBuffer,
|
|
196
|
+
mimeType: 'audio/mpeg',
|
|
197
|
+
cost: 0,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* List all voices available on Amazon Polly.
|
|
203
|
+
*
|
|
204
|
+
* @returns Array of {@link SpeechVoice} objects.
|
|
205
|
+
*/
|
|
206
|
+
async listAvailableVoices(): Promise<SpeechVoice[]> {
|
|
207
|
+
const client = await this._getClient();
|
|
208
|
+
|
|
209
|
+
const { DescribeVoicesCommand } = await import('@aws-sdk/client-polly');
|
|
210
|
+
const response = await client.send(new DescribeVoicesCommand({}));
|
|
211
|
+
|
|
212
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
213
|
+
return (response.Voices ?? []).map((v: any) => ({
|
|
214
|
+
id: v.Id ?? '',
|
|
215
|
+
name: v.Name ?? '',
|
|
216
|
+
languageCode: v.LanguageCode ?? '',
|
|
217
|
+
gender: v.Gender ?? undefined,
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @description Pack factory for the Amazon Polly TTS extension pack.
|
|
4
|
+
*
|
|
5
|
+
* Exports the main {@link createAmazonPollyTTS} factory function and the
|
|
6
|
+
* {@link createExtensionPack} bridge function conforming to the AgentOS
|
|
7
|
+
* manifest factory convention.
|
|
8
|
+
*
|
|
9
|
+
* ### Usage (direct)
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { createAmazonPollyTTS } from '@framers/agentos-ext-amazon-polly';
|
|
12
|
+
*
|
|
13
|
+
* const tts = createAmazonPollyTTS({
|
|
14
|
+
* accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
15
|
+
* secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
16
|
+
* region: 'us-east-1',
|
|
17
|
+
* });
|
|
18
|
+
* const result = await tts.synthesize('Hello, world!');
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* ### Usage (manifest-driven)
|
|
22
|
+
* ```json
|
|
23
|
+
* { "packs": [{ "module": "@framers/agentos-ext-amazon-polly" }] }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @module amazon-polly
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { AmazonPollyTTSProvider } from './AmazonPollyTTSProvider.js';
|
|
30
|
+
import type { AmazonPollyCredentials } from './AmazonPollyTTSProvider.js';
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Local interface mirrors — avoids a hard runtime dep on @framers/agentos
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
/** Subset of ExtensionDescriptor required by this pack. */
|
|
37
|
+
interface ExtensionDescriptor {
|
|
38
|
+
id: string;
|
|
39
|
+
kind: string;
|
|
40
|
+
payload: unknown;
|
|
41
|
+
enableByDefault?: boolean;
|
|
42
|
+
metadata?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Subset of ExtensionPack required by this pack. */
|
|
46
|
+
interface ExtensionPack {
|
|
47
|
+
id: string;
|
|
48
|
+
descriptors: ExtensionDescriptor[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Subset of ExtensionPackContext required by this pack. */
|
|
52
|
+
interface ExtensionPackContext {
|
|
53
|
+
getSecret?: (id: string) => string | undefined;
|
|
54
|
+
options?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Kind constant matching packages/agentos/src/extensions/types.ts. */
|
|
58
|
+
const EXTENSION_KIND_TTS = 'tts-provider';
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Factories
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create a standalone {@link AmazonPollyTTSProvider} instance.
|
|
66
|
+
*
|
|
67
|
+
* @param credentials - AWS credentials and optional region.
|
|
68
|
+
* @returns Configured {@link AmazonPollyTTSProvider}.
|
|
69
|
+
*/
|
|
70
|
+
export function createAmazonPollyTTS(credentials: AmazonPollyCredentials): AmazonPollyTTSProvider {
|
|
71
|
+
return new AmazonPollyTTSProvider(credentials);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* AgentOS manifest factory function.
|
|
76
|
+
*
|
|
77
|
+
* Reads `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and optionally
|
|
78
|
+
* `AWS_REGION` from the pack context secrets, then returns an
|
|
79
|
+
* {@link ExtensionPack} containing a single `tts-provider` descriptor backed
|
|
80
|
+
* by {@link AmazonPollyTTSProvider}.
|
|
81
|
+
*
|
|
82
|
+
* @param context - Pack context supplied by the extension manager.
|
|
83
|
+
* @returns A fully configured {@link ExtensionPack}.
|
|
84
|
+
*/
|
|
85
|
+
export function createExtensionPack(context: ExtensionPackContext): ExtensionPack {
|
|
86
|
+
const provider = new AmazonPollyTTSProvider({
|
|
87
|
+
accessKeyId: context.getSecret?.('AWS_ACCESS_KEY_ID') ?? '',
|
|
88
|
+
secretAccessKey: context.getSecret?.('AWS_SECRET_ACCESS_KEY') ?? '',
|
|
89
|
+
region: context.getSecret?.('AWS_REGION'),
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
id: 'amazon-polly',
|
|
94
|
+
descriptors: [
|
|
95
|
+
{
|
|
96
|
+
id: 'amazon-polly',
|
|
97
|
+
kind: EXTENSION_KIND_TTS,
|
|
98
|
+
payload: provider,
|
|
99
|
+
enableByDefault: true,
|
|
100
|
+
metadata: { providerId: 'amazon-polly' },
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Re-exports
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
export { AmazonPollyTTSProvider } from './AmazonPollyTTSProvider.js';
|
|
111
|
+
export type {
|
|
112
|
+
AmazonPollyCredentials,
|
|
113
|
+
AmazonPollyTTSOptions,
|
|
114
|
+
SpeechVoice,
|
|
115
|
+
SynthesisResult,
|
|
116
|
+
} from './AmazonPollyTTSProvider.js';
|