@voctiv/agent-sdk 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/README.md +527 -188
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/types/media-providers.d.ts +87 -0
- package/dist/types/media-providers.d.ts.map +1 -0
- package/dist/types/media-providers.js +23 -0
- package/dist/types/media-providers.js.map +1 -0
- package/examples/README.md +2 -0
- package/examples/custom-media-providers-script.ts +47 -0
- package/examples/custom-media-providers.ts +112 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
*/
|
|
31
31
|
export { defineScript } from './define-script';
|
|
32
32
|
export type { ScriptContext, ScriptFn } from './define-script';
|
|
33
|
+
export { defineMediaProviders } from './types/media-providers';
|
|
34
|
+
export type { MediaProvidersDefinition, MediaConnectorContext, MediaProviderShared, AsrProviderFactory, TtsProviderFactory, ScriptAsrConnector, ScriptAsrConnectorError, ScriptTtsConnector, TtsSynthesisContext as ScriptTtsSynthesisContext, } from './types/media-providers';
|
|
33
35
|
export type { ScriptDialogContext, ScriptPhase, ScriptRunTime, ScriptResult, PersistedScriptResult, ScriptError, AgentContext, AgentEnvSetOptions, StorageContextApi, } from './types/script-context';
|
|
34
36
|
export { getScriptPhase } from './types/script-context';
|
|
35
37
|
export type { NluScriptApi, PlatformApi, DialogApi, ScheduleCallOptions, SendMessageOptions, InboundMessage, MessagingApi, } from './types/platform';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE/D,YAAY,EACV,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,YAAY,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACjG,YAAY,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3H,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EACV,SAAS,EACT,OAAO,EACP,SAAS,EACT,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,YAAY,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACjG,YAAY,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3H,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EACV,SAAS,EACT,OAAO,EACP,SAAS,EACT,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -30,9 +30,11 @@
|
|
|
30
30
|
* and live SIP INFO ({@link import('./types/events').SipInfo} on `sipInfo$`). See **`README.md`** → SIP Signalling Metadata.
|
|
31
31
|
*/
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
-
exports.parseRecallDelaySeconds = exports.parseRecallCount = exports.isLegacyPhraseRecord = exports.LEGACY_PHRASE_RECORD_BRAND = exports.TranscriptionRole = exports.getScriptPhase = exports.defineScript = void 0;
|
|
33
|
+
exports.parseRecallDelaySeconds = exports.parseRecallCount = exports.isLegacyPhraseRecord = exports.LEGACY_PHRASE_RECORD_BRAND = exports.TranscriptionRole = exports.getScriptPhase = exports.defineMediaProviders = exports.defineScript = void 0;
|
|
34
34
|
var define_script_1 = require("./define-script");
|
|
35
35
|
Object.defineProperty(exports, "defineScript", { enumerable: true, get: function () { return define_script_1.defineScript; } });
|
|
36
|
+
var media_providers_1 = require("./types/media-providers");
|
|
37
|
+
Object.defineProperty(exports, "defineMediaProviders", { enumerable: true, get: function () { return media_providers_1.defineMediaProviders; } });
|
|
36
38
|
var script_context_1 = require("./types/script-context");
|
|
37
39
|
Object.defineProperty(exports, "getScriptPhase", { enumerable: true, get: function () { return script_context_1.getScriptPhase; } });
|
|
38
40
|
var logger_1 = require("./types/logger");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;;;AAEH,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;;;AAEH,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAGrB,2DAA+D;AAAtD,uHAAA,oBAAoB,OAAA;AAyB7B,yDAAwD;AAA/C,gHAAA,cAAc,OAAA;AAavB,yCAAmD;AAA1C,2GAAA,iBAAiB,OAAA;AAwC1B,uDAG+B;AAF7B,2HAAA,0BAA0B,OAAA;AAC1B,qHAAA,oBAAoB,OAAA;AAUtB,+CAA2E;AAAlE,gHAAA,gBAAgB,OAAA;AAAE,uHAAA,uBAAuB,OAAA"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Observable, Subject } from 'rxjs';
|
|
2
|
+
import type { Readable } from 'stream';
|
|
3
|
+
/**
|
|
4
|
+
* Context passed to custom ASR/TTS factories from {@link defineMediaProviders}.
|
|
5
|
+
* Populated by the host outside the script sandbox.
|
|
6
|
+
*/
|
|
7
|
+
export interface MediaConnectorContext {
|
|
8
|
+
id: string;
|
|
9
|
+
config: Record<string, string>;
|
|
10
|
+
dialogUuid: string;
|
|
11
|
+
role?: string;
|
|
12
|
+
debug$: Subject<string>;
|
|
13
|
+
}
|
|
14
|
+
export interface ScriptAsrConnectorError {
|
|
15
|
+
message: string;
|
|
16
|
+
code?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Host ASR connector contract for custom providers (same surface as runtime AsrConnector).
|
|
20
|
+
*/
|
|
21
|
+
export interface ScriptAsrConnector {
|
|
22
|
+
transcription$: Subject<{
|
|
23
|
+
text: string;
|
|
24
|
+
isFinal: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
result$: Subject<string>;
|
|
27
|
+
error$: Subject<ScriptAsrConnectorError>;
|
|
28
|
+
isOpen(): boolean;
|
|
29
|
+
send(audio: ArrayBufferLike): void;
|
|
30
|
+
speech(active: boolean): void;
|
|
31
|
+
finalize(): void;
|
|
32
|
+
close(): void;
|
|
33
|
+
}
|
|
34
|
+
export type TtsSynthesisContext = {
|
|
35
|
+
previousText?: string;
|
|
36
|
+
nextText?: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Unified TTS connector: batch HTTP + optional streaming WebSocket methods.
|
|
40
|
+
*/
|
|
41
|
+
export interface ScriptTtsConnector {
|
|
42
|
+
supportsStreaming(): boolean;
|
|
43
|
+
textToSpeechStream(rawtext: string, ctx?: TtsSynthesisContext): Promise<Readable>;
|
|
44
|
+
readonly audio$: Subject<Buffer>;
|
|
45
|
+
readonly done$: Subject<void>;
|
|
46
|
+
open(): Promise<void>;
|
|
47
|
+
startGeneration(): Promise<void>;
|
|
48
|
+
sendText(chunk: string): void;
|
|
49
|
+
flush(): void;
|
|
50
|
+
sendSeparatorFlush?(): void;
|
|
51
|
+
close(): void;
|
|
52
|
+
}
|
|
53
|
+
/** Optional session object shared by ASR and TTS factories for one dialog. */
|
|
54
|
+
export type MediaProviderShared = {
|
|
55
|
+
dispose?: () => void;
|
|
56
|
+
close?: () => void;
|
|
57
|
+
} & Record<string, unknown>;
|
|
58
|
+
export type AsrProviderFactory = (ctx: MediaConnectorContext, shared: MediaProviderShared | undefined) => ScriptAsrConnector;
|
|
59
|
+
export type TtsProviderFactory = (ctx: MediaConnectorContext, shared: MediaProviderShared | undefined) => ScriptTtsConnector;
|
|
60
|
+
export interface MediaProvidersDefinition {
|
|
61
|
+
createShared?: (ctx: {
|
|
62
|
+
dialogUuid: string;
|
|
63
|
+
debug$: Subject<string>;
|
|
64
|
+
}) => MediaProviderShared;
|
|
65
|
+
asr?: Record<string, AsrProviderFactory>;
|
|
66
|
+
tts?: Record<string, TtsProviderFactory>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Mark a named export as custom media providers (identity helper).
|
|
70
|
+
*
|
|
71
|
+
* Export from a sibling module (`media-providers/index.ts`), not from the
|
|
72
|
+
* sandboxed script entry. The host loads this outside the VM.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* // media-providers/index.ts (host-only)
|
|
77
|
+
* export const mediaProviders = defineMediaProviders({
|
|
78
|
+
* createShared: (ctx) => new MySession(ctx),
|
|
79
|
+
* asr: { 'my-asr': (ctx, shared) => new MyAsr(ctx, shared) },
|
|
80
|
+
* tts: { 'my-tts': (ctx, shared) => new MyTts(ctx, shared) },
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function defineMediaProviders(def: MediaProvidersDefinition): MediaProvidersDefinition;
|
|
85
|
+
/** @internal helper type for hosts that mirror connector subjects */
|
|
86
|
+
export type SubjectLike<T> = Subject<T> | Observable<T>;
|
|
87
|
+
//# sourceMappingURL=media-providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-providers.d.ts","sourceRoot":"","sources":["../../src/types/media-providers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineMediaProviders = defineMediaProviders;
|
|
4
|
+
/**
|
|
5
|
+
* Mark a named export as custom media providers (identity helper).
|
|
6
|
+
*
|
|
7
|
+
* Export from a sibling module (`media-providers/index.ts`), not from the
|
|
8
|
+
* sandboxed script entry. The host loads this outside the VM.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* // media-providers/index.ts (host-only)
|
|
13
|
+
* export const mediaProviders = defineMediaProviders({
|
|
14
|
+
* createShared: (ctx) => new MySession(ctx),
|
|
15
|
+
* asr: { 'my-asr': (ctx, shared) => new MyAsr(ctx, shared) },
|
|
16
|
+
* tts: { 'my-tts': (ctx, shared) => new MyTts(ctx, shared) },
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function defineMediaProviders(def) {
|
|
21
|
+
return def;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=media-providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-providers.js","sourceRoot":"","sources":["../../src/types/media-providers.ts"],"names":[],"mappings":";;AAuGA,oDAIC;AApBD;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,oBAAoB,CAClC,GAA6B;IAE7B,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/examples/README.md
CHANGED
|
@@ -11,6 +11,8 @@ Each file exports one `defineScript` handler. The host **always** invokes that s
|
|
|
11
11
|
| [schedule-call-with-defaults.ts](./schedule-call-with-defaults.ts) | `platform.call()` using CMS defaults from `context` |
|
|
12
12
|
| [after-call-continuation.ts](./after-call-continuation.ts) | `onSuccessCall` / `onFailedCall` + `getScriptPhase()` |
|
|
13
13
|
| [read-recall-from-params.ts](./read-recall-from-params.ts) | `parseRecallDelaySeconds()` / `parseRecallCount()` |
|
|
14
|
+
| [custom-media-providers.ts](./custom-media-providers.ts) | Host-only `mediaProviders` (`implements ScriptAsrConnector` / `ScriptTtsConnector`) |
|
|
15
|
+
| [custom-media-providers-script.ts](./custom-media-providers-script.ts) | Sandboxed `defineScript` using custom vendors (no `ws` / no `process.env`) |
|
|
14
16
|
|
|
15
17
|
## Recall flow
|
|
16
18
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandboxed script entry that uses custom mediaProviders vendors.
|
|
3
|
+
*
|
|
4
|
+
* Pair with `custom-media-providers.ts` deployed as `dist/media-providers/index.js`.
|
|
5
|
+
* This file must stay free of `ws` / connector imports — the script VM has no `process`.
|
|
6
|
+
*/
|
|
7
|
+
import { defineScript } from '@voctiv/agent-sdk';
|
|
8
|
+
|
|
9
|
+
export default defineScript(async ({ channel, logger }) => {
|
|
10
|
+
channel.sip.answer();
|
|
11
|
+
|
|
12
|
+
// Pass credentials via `data` (or channel/platform params). Do not use process.env
|
|
13
|
+
// in the sandboxed entry — `process` is not defined in the script VM.
|
|
14
|
+
// Host-side factories in media-providers/ may still read process.env.
|
|
15
|
+
const apiKey = String(
|
|
16
|
+
(channel.params as Record<string, unknown>).api_key ?? '',
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const asr = await channel.createAsr({
|
|
20
|
+
vendor: 'my-asr',
|
|
21
|
+
language: 'ru-RU',
|
|
22
|
+
data: { api_key: apiKey },
|
|
23
|
+
});
|
|
24
|
+
const tts = await channel.createTts({
|
|
25
|
+
vendor: 'my-tts',
|
|
26
|
+
data: {
|
|
27
|
+
api_key: apiKey,
|
|
28
|
+
voice_id: '…',
|
|
29
|
+
output_format: 'pcm_16000',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await tts.say('Hello from a custom TTS connector.', { alias: 'greet' });
|
|
34
|
+
|
|
35
|
+
tts.say$('One. Two.', { alias: 'reply', ttsStrategy: 'streaming' }).subscribe({
|
|
36
|
+
next: (ev) => {
|
|
37
|
+
logger.log('tts utterance', { state: ev.state, alias: ev.itemAlias });
|
|
38
|
+
},
|
|
39
|
+
error: (err) => logger.error('tts failed', err),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await channel.audio.say('Reuse handle', { tts });
|
|
43
|
+
|
|
44
|
+
asr.destroy();
|
|
45
|
+
tts.destroy();
|
|
46
|
+
channel.sip.hangup();
|
|
47
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-only custom ASR / TTS module.
|
|
3
|
+
*
|
|
4
|
+
* Ship as `dist/media-providers/index.js` next to the sandboxed script entry.
|
|
5
|
+
* The host `require`s this file outside the script VM (full Node: `ws`, `process`, …).
|
|
6
|
+
*
|
|
7
|
+
* Do **not** re-export `mediaProviders` from `dist/index.js` — the sandbox has no
|
|
8
|
+
* `process`, so loading `ws` there fails. Keep `defineScript` in a separate file
|
|
9
|
+
* (see `custom-media-providers-script.ts`).
|
|
10
|
+
*
|
|
11
|
+
* Batch and streaming TTS share one class (`supportsStreaming()` + streaming
|
|
12
|
+
* lifecycle). Do not register a separate streaming map.
|
|
13
|
+
*/
|
|
14
|
+
import { Readable } from 'stream';
|
|
15
|
+
import { Subject } from 'rxjs';
|
|
16
|
+
import {
|
|
17
|
+
defineMediaProviders,
|
|
18
|
+
type MediaConnectorContext,
|
|
19
|
+
type MediaProviderShared,
|
|
20
|
+
type ScriptAsrConnector,
|
|
21
|
+
type ScriptTtsConnector,
|
|
22
|
+
type ScriptTtsSynthesisContext,
|
|
23
|
+
} from '@voctiv/agent-sdk';
|
|
24
|
+
|
|
25
|
+
type SharedSession = MediaProviderShared & {
|
|
26
|
+
turns: number;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
class EchoAsr implements ScriptAsrConnector {
|
|
30
|
+
readonly transcription$ = new Subject<{ text: string; isFinal: boolean }>();
|
|
31
|
+
readonly result$ = new Subject<string>();
|
|
32
|
+
readonly error$ = new Subject<{ message: string; code?: number }>();
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
private readonly ctx: MediaConnectorContext,
|
|
36
|
+
private readonly shared: SharedSession | undefined,
|
|
37
|
+
) {}
|
|
38
|
+
|
|
39
|
+
isOpen(): boolean {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
send(_audio: ArrayBufferLike): void {
|
|
44
|
+
// Forward PCM (S16LE mono 16 kHz) to your vendor here.
|
|
45
|
+
void this.ctx;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
speech(_active: boolean): void {}
|
|
49
|
+
|
|
50
|
+
finalize(): void {
|
|
51
|
+
const text = 'heard';
|
|
52
|
+
this.transcription$.next({ text, isFinal: true });
|
|
53
|
+
this.result$.next(text);
|
|
54
|
+
if (this.shared) this.shared.turns += 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
close(): void {
|
|
58
|
+
this.transcription$.complete();
|
|
59
|
+
this.result$.complete();
|
|
60
|
+
this.error$.complete();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class BatchOrStreamTts implements ScriptTtsConnector {
|
|
65
|
+
readonly audio$ = new Subject<Buffer>();
|
|
66
|
+
readonly done$ = new Subject<void>();
|
|
67
|
+
|
|
68
|
+
constructor(
|
|
69
|
+
private readonly ctx: MediaConnectorContext,
|
|
70
|
+
private readonly shared: SharedSession | undefined,
|
|
71
|
+
) {}
|
|
72
|
+
|
|
73
|
+
/** Return true when this connector also owns a long-lived streaming socket. */
|
|
74
|
+
supportsStreaming(): boolean {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async textToSpeechStream(
|
|
79
|
+
rawtext: string,
|
|
80
|
+
_ctx?: ScriptTtsSynthesisContext,
|
|
81
|
+
): Promise<Readable> {
|
|
82
|
+
void this.ctx;
|
|
83
|
+
void this.shared;
|
|
84
|
+
// Replace with HTTP keep-alive synthesis that returns a PCM stream.
|
|
85
|
+
return Readable.from([Buffer.from(rawtext, 'utf8')]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async open(): Promise<void> {}
|
|
89
|
+
async startGeneration(): Promise<void> {}
|
|
90
|
+
sendText(_chunk: string): void {}
|
|
91
|
+
flush(): void {}
|
|
92
|
+
close(): void {
|
|
93
|
+
// Soft-close streaming sockets for reuse; do not complete Subjects if the
|
|
94
|
+
// host may call open() again on the same fingerprint.
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const mediaProviders = defineMediaProviders({
|
|
99
|
+
createShared: (): SharedSession => ({
|
|
100
|
+
turns: 0,
|
|
101
|
+
dispose() {
|
|
102
|
+
/* release vendor app state for this dialog */
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
105
|
+
asr: {
|
|
106
|
+
'my-asr': (ctx, shared) => new EchoAsr(ctx, shared as SharedSession),
|
|
107
|
+
},
|
|
108
|
+
tts: {
|
|
109
|
+
'my-tts': (ctx, shared) =>
|
|
110
|
+
new BatchOrStreamTts(ctx, shared as SharedSession),
|
|
111
|
+
},
|
|
112
|
+
});
|
package/package.json
CHANGED