@plasius/ai-speech 0.1.1 → 0.1.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/CHANGELOG.md +15 -0
- package/README.md +77 -3
- package/dist/index.cjs +374 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +140 -2
- package/dist/index.d.ts +140 -2
- package/dist/index.js +350 -2
- package/dist/index.js.map +1 -1
- package/docs/adrs/adr-0002-tts-cache-and-address-policy-contracts.md +34 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -5,8 +5,146 @@ interface AiPackageDescriptor {
|
|
|
5
5
|
readonly summary: string;
|
|
6
6
|
}
|
|
7
7
|
declare const AI_SPEECH_PACKAGE = "@plasius/ai-speech";
|
|
8
|
-
declare const AI_SPEECH_FEATURE_FLAG_ID = "ai.speech.enabled";
|
|
9
8
|
declare const AI_SPEECH_ENV_PREFIX = "AI_SPEECH";
|
|
9
|
+
declare const AI_SPEECH_FEATURE_FLAGS: {
|
|
10
|
+
readonly ttsCache: "ai.tts.cache.enabled";
|
|
11
|
+
readonly ttsNearReuse: "ai.tts.near-reuse.enabled";
|
|
12
|
+
readonly premiumCharacters: "ai.tts.premium-characters.enabled";
|
|
13
|
+
};
|
|
14
|
+
type AiSpeechFeatureFlagKey = (typeof AI_SPEECH_FEATURE_FLAGS)[keyof typeof AI_SPEECH_FEATURE_FLAGS];
|
|
15
|
+
type AiSpeechFeatureFlagSnapshot = Readonly<Record<string, boolean | undefined>>;
|
|
16
|
+
declare const AI_SPEECH_FEATURE_FLAG_ID: "ai.tts.cache.enabled";
|
|
17
|
+
declare const AI_SPEECH_ROLLOUT_EVALUATORS: readonly ["remote-flag-service", "host-application", "break-glass-env"];
|
|
18
|
+
type AiSpeechRolloutEvaluator = (typeof AI_SPEECH_ROLLOUT_EVALUATORS)[number];
|
|
19
|
+
declare const AI_SPEECH_ROLLOUT_FALLBACK_MODES: readonly ["fail-closed", "fail-open"];
|
|
20
|
+
type AiSpeechRolloutFallbackMode = (typeof AI_SPEECH_ROLLOUT_FALLBACK_MODES)[number];
|
|
21
|
+
interface AiSpeechRolloutControl {
|
|
22
|
+
readonly featureFlag: AiSpeechFeatureFlagKey;
|
|
23
|
+
readonly evaluator: AiSpeechRolloutEvaluator;
|
|
24
|
+
readonly defaultEnabled: boolean;
|
|
25
|
+
readonly fallbackMode: AiSpeechRolloutFallbackMode;
|
|
26
|
+
}
|
|
27
|
+
interface AiSpeechRolloutDecision extends AiSpeechRolloutControl {
|
|
28
|
+
readonly enabled: boolean;
|
|
29
|
+
readonly source: "snapshot" | "default";
|
|
30
|
+
}
|
|
31
|
+
declare const AI_SPEECH_ROLLOUTS: Readonly<{
|
|
32
|
+
ttsCache: Readonly<AiSpeechRolloutControl>;
|
|
33
|
+
ttsNearReuse: Readonly<AiSpeechRolloutControl>;
|
|
34
|
+
premiumCharacters: Readonly<AiSpeechRolloutControl>;
|
|
35
|
+
}>;
|
|
36
|
+
declare function resolveAiSpeechRolloutDecision(control: AiSpeechRolloutControl, snapshot?: AiSpeechFeatureFlagSnapshot): AiSpeechRolloutDecision;
|
|
37
|
+
declare function isAiSpeechFeatureEnabled(featureFlag: AiSpeechFeatureFlagKey, snapshot?: AiSpeechFeatureFlagSnapshot): boolean;
|
|
38
|
+
declare const AI_SPEECH_VOICE_TIERS: readonly ["development", "standard", "premium-character"];
|
|
39
|
+
type AiSpeechVoiceTier = (typeof AI_SPEECH_VOICE_TIERS)[number];
|
|
40
|
+
declare const AI_SPEECH_ENVIRONMENTS: readonly ["development", "preview", "production"];
|
|
41
|
+
type AiSpeechEnvironment = (typeof AI_SPEECH_ENVIRONMENTS)[number];
|
|
42
|
+
interface AiSpeechVoiceTierDecision {
|
|
43
|
+
readonly requestedTier: AiSpeechVoiceTier;
|
|
44
|
+
readonly resolvedTier: AiSpeechVoiceTier;
|
|
45
|
+
readonly fallbackTier?: AiSpeechVoiceTier;
|
|
46
|
+
readonly reasonCodes: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
interface ResolveAiSpeechVoiceTierInput {
|
|
49
|
+
readonly environment: AiSpeechEnvironment;
|
|
50
|
+
readonly requestedTier?: AiSpeechVoiceTier;
|
|
51
|
+
readonly featureFlags?: AiSpeechFeatureFlagSnapshot;
|
|
52
|
+
}
|
|
53
|
+
declare function resolveAiSpeechVoiceTier(input: ResolveAiSpeechVoiceTierInput): AiSpeechVoiceTierDecision;
|
|
54
|
+
declare const AI_SPEECH_PLAYER_ADDRESS_SOURCES: readonly ["generic-player", "class-title", "faction-title", "authored-character", "user-name", "account-handle", "user-renamed-character"];
|
|
55
|
+
type AiSpeechPlayerAddressSource = (typeof AI_SPEECH_PLAYER_ADDRESS_SOURCES)[number];
|
|
56
|
+
declare const AI_SPEECH_DEFAULT_PLAYER_LABEL = "Player";
|
|
57
|
+
interface AiSpeechPlayerAddressInput {
|
|
58
|
+
readonly source: AiSpeechPlayerAddressSource;
|
|
59
|
+
readonly rawValue?: string;
|
|
60
|
+
readonly fallbackLabel?: string;
|
|
61
|
+
}
|
|
62
|
+
interface AiSpeechPlayerAddressDecision {
|
|
63
|
+
readonly source: AiSpeechPlayerAddressSource;
|
|
64
|
+
readonly renderText: string;
|
|
65
|
+
readonly exactReuseAllowed: boolean;
|
|
66
|
+
readonly nearReuseAllowed: boolean;
|
|
67
|
+
readonly redacted: boolean;
|
|
68
|
+
readonly reasonCodes: readonly string[];
|
|
69
|
+
}
|
|
70
|
+
declare function resolveAiSpeechPlayerAddress(input: AiSpeechPlayerAddressInput): AiSpeechPlayerAddressDecision;
|
|
71
|
+
interface AiSpeechRenderTextInput {
|
|
72
|
+
readonly textTemplate: string;
|
|
73
|
+
readonly playerAddress?: AiSpeechPlayerAddressInput;
|
|
74
|
+
}
|
|
75
|
+
interface AiSpeechRenderTextResult {
|
|
76
|
+
readonly renderText: string;
|
|
77
|
+
readonly normalizedRenderText: string;
|
|
78
|
+
readonly playerAddress?: AiSpeechPlayerAddressDecision;
|
|
79
|
+
}
|
|
80
|
+
declare function renderAiSpeechText(input: AiSpeechRenderTextInput): AiSpeechRenderTextResult;
|
|
81
|
+
declare function normalizeAiSpeechText(value: string): string;
|
|
82
|
+
declare const AI_SPEECH_PROVIDER_CACHE_PERMISSIONS: readonly ["forbidden", "exact-only", "exact-and-near"];
|
|
83
|
+
type AiSpeechProviderCachePermission = (typeof AI_SPEECH_PROVIDER_CACHE_PERMISSIONS)[number];
|
|
84
|
+
declare const AI_SPEECH_CACHE_MODES: readonly ["disabled", "no-cache", "exact", "near"];
|
|
85
|
+
type AiSpeechCacheMode = (typeof AI_SPEECH_CACHE_MODES)[number];
|
|
86
|
+
declare const AI_SPEECH_CACHE_SCOPES: readonly ["none", "actor", "global"];
|
|
87
|
+
type AiSpeechCacheScope = (typeof AI_SPEECH_CACHE_SCOPES)[number];
|
|
88
|
+
declare const AI_SPEECH_UTTERANCE_CLASSES: readonly ["system-generic", "game-npc-dialogue", "game-bark", "player-address", "moderation-notice", "private-response"];
|
|
89
|
+
type AiSpeechUtteranceClass = (typeof AI_SPEECH_UTTERANCE_CLASSES)[number];
|
|
90
|
+
declare const AI_SPEECH_NEAR_REUSE_SAFE_CLASSES: readonly ["system-generic", "game-npc-dialogue", "game-bark", "player-address"];
|
|
91
|
+
interface AiSpeechCacheKeyInput {
|
|
92
|
+
readonly providerId: string;
|
|
93
|
+
readonly modelId: string;
|
|
94
|
+
readonly voiceId: string;
|
|
95
|
+
readonly locale: string;
|
|
96
|
+
readonly format: string;
|
|
97
|
+
readonly pronunciationVersion: string;
|
|
98
|
+
readonly normalizedRenderText: string;
|
|
99
|
+
readonly styleId?: string;
|
|
100
|
+
readonly scopeDiscriminator?: string;
|
|
101
|
+
}
|
|
102
|
+
interface AiSpeechVoiceProfileRef {
|
|
103
|
+
readonly providerId: string;
|
|
104
|
+
readonly modelId: string;
|
|
105
|
+
readonly voiceId: string;
|
|
106
|
+
readonly locale: string;
|
|
107
|
+
readonly format: string;
|
|
108
|
+
readonly pronunciationVersion: string;
|
|
109
|
+
readonly styleId?: string;
|
|
110
|
+
readonly cachePermission: AiSpeechProviderCachePermission;
|
|
111
|
+
readonly tier?: AiSpeechVoiceTier;
|
|
112
|
+
readonly profileId?: string;
|
|
113
|
+
}
|
|
114
|
+
interface AiSpeechCacheTelemetry {
|
|
115
|
+
readonly cacheHits: number;
|
|
116
|
+
readonly nearCacheHits: number;
|
|
117
|
+
readonly cacheMisses: number;
|
|
118
|
+
readonly charactersSaved: number;
|
|
119
|
+
readonly estimatedCostSavedUsd?: number;
|
|
120
|
+
readonly voiceProfileIds?: readonly string[];
|
|
121
|
+
}
|
|
122
|
+
interface PlanAiSpeechCacheInput {
|
|
123
|
+
readonly utteranceClass: AiSpeechUtteranceClass;
|
|
124
|
+
readonly textTemplate: string;
|
|
125
|
+
readonly playerAddress?: AiSpeechPlayerAddressInput;
|
|
126
|
+
readonly voice: AiSpeechVoiceProfileRef;
|
|
127
|
+
readonly featureFlags?: AiSpeechFeatureFlagSnapshot;
|
|
128
|
+
readonly actorScopeKey?: string;
|
|
129
|
+
readonly containsPersonalData?: boolean;
|
|
130
|
+
readonly containsPrivateContext?: boolean;
|
|
131
|
+
readonly containsModerationNotice?: boolean;
|
|
132
|
+
}
|
|
133
|
+
interface AiSpeechCachePlan {
|
|
134
|
+
readonly mode: AiSpeechCacheMode;
|
|
135
|
+
readonly sharingScope: AiSpeechCacheScope;
|
|
136
|
+
readonly renderText: string;
|
|
137
|
+
readonly normalizedRenderText: string;
|
|
138
|
+
readonly exactKey?: string;
|
|
139
|
+
readonly nearKey?: string;
|
|
140
|
+
readonly enabledFeatureFlags: readonly AiSpeechFeatureFlagKey[];
|
|
141
|
+
readonly playerAddress?: AiSpeechPlayerAddressDecision;
|
|
142
|
+
readonly reasonCodes: readonly string[];
|
|
143
|
+
}
|
|
144
|
+
declare function createAiSpeechCacheKey(input: AiSpeechCacheKeyInput): string;
|
|
145
|
+
declare function createAiSpeechNearReuseFingerprint(value: string): string;
|
|
146
|
+
declare function isAiSpeechNearReuseSafeClass(utteranceClass: AiSpeechUtteranceClass): boolean;
|
|
147
|
+
declare function planAiSpeechCache(input: PlanAiSpeechCacheInput): AiSpeechCachePlan;
|
|
10
148
|
declare const packageDescriptor: AiPackageDescriptor;
|
|
11
149
|
|
|
12
|
-
export { AI_SPEECH_ENV_PREFIX, AI_SPEECH_FEATURE_FLAG_ID, AI_SPEECH_PACKAGE, type AiPackageDescriptor, packageDescriptor };
|
|
150
|
+
export { AI_SPEECH_CACHE_MODES, AI_SPEECH_CACHE_SCOPES, AI_SPEECH_DEFAULT_PLAYER_LABEL, AI_SPEECH_ENVIRONMENTS, AI_SPEECH_ENV_PREFIX, AI_SPEECH_FEATURE_FLAGS, AI_SPEECH_FEATURE_FLAG_ID, AI_SPEECH_NEAR_REUSE_SAFE_CLASSES, AI_SPEECH_PACKAGE, AI_SPEECH_PLAYER_ADDRESS_SOURCES, AI_SPEECH_PROVIDER_CACHE_PERMISSIONS, AI_SPEECH_ROLLOUTS, AI_SPEECH_ROLLOUT_EVALUATORS, AI_SPEECH_ROLLOUT_FALLBACK_MODES, AI_SPEECH_UTTERANCE_CLASSES, AI_SPEECH_VOICE_TIERS, type AiPackageDescriptor, type AiSpeechCacheKeyInput, type AiSpeechCacheMode, type AiSpeechCachePlan, type AiSpeechCacheScope, type AiSpeechCacheTelemetry, type AiSpeechEnvironment, type AiSpeechFeatureFlagKey, type AiSpeechFeatureFlagSnapshot, type AiSpeechPlayerAddressDecision, type AiSpeechPlayerAddressInput, type AiSpeechPlayerAddressSource, type AiSpeechProviderCachePermission, type AiSpeechRenderTextInput, type AiSpeechRenderTextResult, type AiSpeechRolloutControl, type AiSpeechRolloutDecision, type AiSpeechRolloutEvaluator, type AiSpeechRolloutFallbackMode, type AiSpeechUtteranceClass, type AiSpeechVoiceProfileRef, type AiSpeechVoiceTier, type AiSpeechVoiceTierDecision, type PlanAiSpeechCacheInput, type ResolveAiSpeechVoiceTierInput, createAiSpeechCacheKey, createAiSpeechNearReuseFingerprint, isAiSpeechFeatureEnabled, isAiSpeechNearReuseSafeClass, normalizeAiSpeechText, packageDescriptor, planAiSpeechCache, renderAiSpeechText, resolveAiSpeechPlayerAddress, resolveAiSpeechRolloutDecision, resolveAiSpeechVoiceTier };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,146 @@ interface AiPackageDescriptor {
|
|
|
5
5
|
readonly summary: string;
|
|
6
6
|
}
|
|
7
7
|
declare const AI_SPEECH_PACKAGE = "@plasius/ai-speech";
|
|
8
|
-
declare const AI_SPEECH_FEATURE_FLAG_ID = "ai.speech.enabled";
|
|
9
8
|
declare const AI_SPEECH_ENV_PREFIX = "AI_SPEECH";
|
|
9
|
+
declare const AI_SPEECH_FEATURE_FLAGS: {
|
|
10
|
+
readonly ttsCache: "ai.tts.cache.enabled";
|
|
11
|
+
readonly ttsNearReuse: "ai.tts.near-reuse.enabled";
|
|
12
|
+
readonly premiumCharacters: "ai.tts.premium-characters.enabled";
|
|
13
|
+
};
|
|
14
|
+
type AiSpeechFeatureFlagKey = (typeof AI_SPEECH_FEATURE_FLAGS)[keyof typeof AI_SPEECH_FEATURE_FLAGS];
|
|
15
|
+
type AiSpeechFeatureFlagSnapshot = Readonly<Record<string, boolean | undefined>>;
|
|
16
|
+
declare const AI_SPEECH_FEATURE_FLAG_ID: "ai.tts.cache.enabled";
|
|
17
|
+
declare const AI_SPEECH_ROLLOUT_EVALUATORS: readonly ["remote-flag-service", "host-application", "break-glass-env"];
|
|
18
|
+
type AiSpeechRolloutEvaluator = (typeof AI_SPEECH_ROLLOUT_EVALUATORS)[number];
|
|
19
|
+
declare const AI_SPEECH_ROLLOUT_FALLBACK_MODES: readonly ["fail-closed", "fail-open"];
|
|
20
|
+
type AiSpeechRolloutFallbackMode = (typeof AI_SPEECH_ROLLOUT_FALLBACK_MODES)[number];
|
|
21
|
+
interface AiSpeechRolloutControl {
|
|
22
|
+
readonly featureFlag: AiSpeechFeatureFlagKey;
|
|
23
|
+
readonly evaluator: AiSpeechRolloutEvaluator;
|
|
24
|
+
readonly defaultEnabled: boolean;
|
|
25
|
+
readonly fallbackMode: AiSpeechRolloutFallbackMode;
|
|
26
|
+
}
|
|
27
|
+
interface AiSpeechRolloutDecision extends AiSpeechRolloutControl {
|
|
28
|
+
readonly enabled: boolean;
|
|
29
|
+
readonly source: "snapshot" | "default";
|
|
30
|
+
}
|
|
31
|
+
declare const AI_SPEECH_ROLLOUTS: Readonly<{
|
|
32
|
+
ttsCache: Readonly<AiSpeechRolloutControl>;
|
|
33
|
+
ttsNearReuse: Readonly<AiSpeechRolloutControl>;
|
|
34
|
+
premiumCharacters: Readonly<AiSpeechRolloutControl>;
|
|
35
|
+
}>;
|
|
36
|
+
declare function resolveAiSpeechRolloutDecision(control: AiSpeechRolloutControl, snapshot?: AiSpeechFeatureFlagSnapshot): AiSpeechRolloutDecision;
|
|
37
|
+
declare function isAiSpeechFeatureEnabled(featureFlag: AiSpeechFeatureFlagKey, snapshot?: AiSpeechFeatureFlagSnapshot): boolean;
|
|
38
|
+
declare const AI_SPEECH_VOICE_TIERS: readonly ["development", "standard", "premium-character"];
|
|
39
|
+
type AiSpeechVoiceTier = (typeof AI_SPEECH_VOICE_TIERS)[number];
|
|
40
|
+
declare const AI_SPEECH_ENVIRONMENTS: readonly ["development", "preview", "production"];
|
|
41
|
+
type AiSpeechEnvironment = (typeof AI_SPEECH_ENVIRONMENTS)[number];
|
|
42
|
+
interface AiSpeechVoiceTierDecision {
|
|
43
|
+
readonly requestedTier: AiSpeechVoiceTier;
|
|
44
|
+
readonly resolvedTier: AiSpeechVoiceTier;
|
|
45
|
+
readonly fallbackTier?: AiSpeechVoiceTier;
|
|
46
|
+
readonly reasonCodes: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
interface ResolveAiSpeechVoiceTierInput {
|
|
49
|
+
readonly environment: AiSpeechEnvironment;
|
|
50
|
+
readonly requestedTier?: AiSpeechVoiceTier;
|
|
51
|
+
readonly featureFlags?: AiSpeechFeatureFlagSnapshot;
|
|
52
|
+
}
|
|
53
|
+
declare function resolveAiSpeechVoiceTier(input: ResolveAiSpeechVoiceTierInput): AiSpeechVoiceTierDecision;
|
|
54
|
+
declare const AI_SPEECH_PLAYER_ADDRESS_SOURCES: readonly ["generic-player", "class-title", "faction-title", "authored-character", "user-name", "account-handle", "user-renamed-character"];
|
|
55
|
+
type AiSpeechPlayerAddressSource = (typeof AI_SPEECH_PLAYER_ADDRESS_SOURCES)[number];
|
|
56
|
+
declare const AI_SPEECH_DEFAULT_PLAYER_LABEL = "Player";
|
|
57
|
+
interface AiSpeechPlayerAddressInput {
|
|
58
|
+
readonly source: AiSpeechPlayerAddressSource;
|
|
59
|
+
readonly rawValue?: string;
|
|
60
|
+
readonly fallbackLabel?: string;
|
|
61
|
+
}
|
|
62
|
+
interface AiSpeechPlayerAddressDecision {
|
|
63
|
+
readonly source: AiSpeechPlayerAddressSource;
|
|
64
|
+
readonly renderText: string;
|
|
65
|
+
readonly exactReuseAllowed: boolean;
|
|
66
|
+
readonly nearReuseAllowed: boolean;
|
|
67
|
+
readonly redacted: boolean;
|
|
68
|
+
readonly reasonCodes: readonly string[];
|
|
69
|
+
}
|
|
70
|
+
declare function resolveAiSpeechPlayerAddress(input: AiSpeechPlayerAddressInput): AiSpeechPlayerAddressDecision;
|
|
71
|
+
interface AiSpeechRenderTextInput {
|
|
72
|
+
readonly textTemplate: string;
|
|
73
|
+
readonly playerAddress?: AiSpeechPlayerAddressInput;
|
|
74
|
+
}
|
|
75
|
+
interface AiSpeechRenderTextResult {
|
|
76
|
+
readonly renderText: string;
|
|
77
|
+
readonly normalizedRenderText: string;
|
|
78
|
+
readonly playerAddress?: AiSpeechPlayerAddressDecision;
|
|
79
|
+
}
|
|
80
|
+
declare function renderAiSpeechText(input: AiSpeechRenderTextInput): AiSpeechRenderTextResult;
|
|
81
|
+
declare function normalizeAiSpeechText(value: string): string;
|
|
82
|
+
declare const AI_SPEECH_PROVIDER_CACHE_PERMISSIONS: readonly ["forbidden", "exact-only", "exact-and-near"];
|
|
83
|
+
type AiSpeechProviderCachePermission = (typeof AI_SPEECH_PROVIDER_CACHE_PERMISSIONS)[number];
|
|
84
|
+
declare const AI_SPEECH_CACHE_MODES: readonly ["disabled", "no-cache", "exact", "near"];
|
|
85
|
+
type AiSpeechCacheMode = (typeof AI_SPEECH_CACHE_MODES)[number];
|
|
86
|
+
declare const AI_SPEECH_CACHE_SCOPES: readonly ["none", "actor", "global"];
|
|
87
|
+
type AiSpeechCacheScope = (typeof AI_SPEECH_CACHE_SCOPES)[number];
|
|
88
|
+
declare const AI_SPEECH_UTTERANCE_CLASSES: readonly ["system-generic", "game-npc-dialogue", "game-bark", "player-address", "moderation-notice", "private-response"];
|
|
89
|
+
type AiSpeechUtteranceClass = (typeof AI_SPEECH_UTTERANCE_CLASSES)[number];
|
|
90
|
+
declare const AI_SPEECH_NEAR_REUSE_SAFE_CLASSES: readonly ["system-generic", "game-npc-dialogue", "game-bark", "player-address"];
|
|
91
|
+
interface AiSpeechCacheKeyInput {
|
|
92
|
+
readonly providerId: string;
|
|
93
|
+
readonly modelId: string;
|
|
94
|
+
readonly voiceId: string;
|
|
95
|
+
readonly locale: string;
|
|
96
|
+
readonly format: string;
|
|
97
|
+
readonly pronunciationVersion: string;
|
|
98
|
+
readonly normalizedRenderText: string;
|
|
99
|
+
readonly styleId?: string;
|
|
100
|
+
readonly scopeDiscriminator?: string;
|
|
101
|
+
}
|
|
102
|
+
interface AiSpeechVoiceProfileRef {
|
|
103
|
+
readonly providerId: string;
|
|
104
|
+
readonly modelId: string;
|
|
105
|
+
readonly voiceId: string;
|
|
106
|
+
readonly locale: string;
|
|
107
|
+
readonly format: string;
|
|
108
|
+
readonly pronunciationVersion: string;
|
|
109
|
+
readonly styleId?: string;
|
|
110
|
+
readonly cachePermission: AiSpeechProviderCachePermission;
|
|
111
|
+
readonly tier?: AiSpeechVoiceTier;
|
|
112
|
+
readonly profileId?: string;
|
|
113
|
+
}
|
|
114
|
+
interface AiSpeechCacheTelemetry {
|
|
115
|
+
readonly cacheHits: number;
|
|
116
|
+
readonly nearCacheHits: number;
|
|
117
|
+
readonly cacheMisses: number;
|
|
118
|
+
readonly charactersSaved: number;
|
|
119
|
+
readonly estimatedCostSavedUsd?: number;
|
|
120
|
+
readonly voiceProfileIds?: readonly string[];
|
|
121
|
+
}
|
|
122
|
+
interface PlanAiSpeechCacheInput {
|
|
123
|
+
readonly utteranceClass: AiSpeechUtteranceClass;
|
|
124
|
+
readonly textTemplate: string;
|
|
125
|
+
readonly playerAddress?: AiSpeechPlayerAddressInput;
|
|
126
|
+
readonly voice: AiSpeechVoiceProfileRef;
|
|
127
|
+
readonly featureFlags?: AiSpeechFeatureFlagSnapshot;
|
|
128
|
+
readonly actorScopeKey?: string;
|
|
129
|
+
readonly containsPersonalData?: boolean;
|
|
130
|
+
readonly containsPrivateContext?: boolean;
|
|
131
|
+
readonly containsModerationNotice?: boolean;
|
|
132
|
+
}
|
|
133
|
+
interface AiSpeechCachePlan {
|
|
134
|
+
readonly mode: AiSpeechCacheMode;
|
|
135
|
+
readonly sharingScope: AiSpeechCacheScope;
|
|
136
|
+
readonly renderText: string;
|
|
137
|
+
readonly normalizedRenderText: string;
|
|
138
|
+
readonly exactKey?: string;
|
|
139
|
+
readonly nearKey?: string;
|
|
140
|
+
readonly enabledFeatureFlags: readonly AiSpeechFeatureFlagKey[];
|
|
141
|
+
readonly playerAddress?: AiSpeechPlayerAddressDecision;
|
|
142
|
+
readonly reasonCodes: readonly string[];
|
|
143
|
+
}
|
|
144
|
+
declare function createAiSpeechCacheKey(input: AiSpeechCacheKeyInput): string;
|
|
145
|
+
declare function createAiSpeechNearReuseFingerprint(value: string): string;
|
|
146
|
+
declare function isAiSpeechNearReuseSafeClass(utteranceClass: AiSpeechUtteranceClass): boolean;
|
|
147
|
+
declare function planAiSpeechCache(input: PlanAiSpeechCacheInput): AiSpeechCachePlan;
|
|
10
148
|
declare const packageDescriptor: AiPackageDescriptor;
|
|
11
149
|
|
|
12
|
-
export { AI_SPEECH_ENV_PREFIX, AI_SPEECH_FEATURE_FLAG_ID, AI_SPEECH_PACKAGE, type AiPackageDescriptor, packageDescriptor };
|
|
150
|
+
export { AI_SPEECH_CACHE_MODES, AI_SPEECH_CACHE_SCOPES, AI_SPEECH_DEFAULT_PLAYER_LABEL, AI_SPEECH_ENVIRONMENTS, AI_SPEECH_ENV_PREFIX, AI_SPEECH_FEATURE_FLAGS, AI_SPEECH_FEATURE_FLAG_ID, AI_SPEECH_NEAR_REUSE_SAFE_CLASSES, AI_SPEECH_PACKAGE, AI_SPEECH_PLAYER_ADDRESS_SOURCES, AI_SPEECH_PROVIDER_CACHE_PERMISSIONS, AI_SPEECH_ROLLOUTS, AI_SPEECH_ROLLOUT_EVALUATORS, AI_SPEECH_ROLLOUT_FALLBACK_MODES, AI_SPEECH_UTTERANCE_CLASSES, AI_SPEECH_VOICE_TIERS, type AiPackageDescriptor, type AiSpeechCacheKeyInput, type AiSpeechCacheMode, type AiSpeechCachePlan, type AiSpeechCacheScope, type AiSpeechCacheTelemetry, type AiSpeechEnvironment, type AiSpeechFeatureFlagKey, type AiSpeechFeatureFlagSnapshot, type AiSpeechPlayerAddressDecision, type AiSpeechPlayerAddressInput, type AiSpeechPlayerAddressSource, type AiSpeechProviderCachePermission, type AiSpeechRenderTextInput, type AiSpeechRenderTextResult, type AiSpeechRolloutControl, type AiSpeechRolloutDecision, type AiSpeechRolloutEvaluator, type AiSpeechRolloutFallbackMode, type AiSpeechUtteranceClass, type AiSpeechVoiceProfileRef, type AiSpeechVoiceTier, type AiSpeechVoiceTierDecision, type PlanAiSpeechCacheInput, type ResolveAiSpeechVoiceTierInput, createAiSpeechCacheKey, createAiSpeechNearReuseFingerprint, isAiSpeechFeatureEnabled, isAiSpeechNearReuseSafeClass, normalizeAiSpeechText, packageDescriptor, planAiSpeechCache, renderAiSpeechText, resolveAiSpeechPlayerAddress, resolveAiSpeechRolloutDecision, resolveAiSpeechVoiceTier };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,332 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
+
function requireNonEmptyString(value, label) {
|
|
3
|
+
const trimmed = value.trim();
|
|
4
|
+
if (trimmed.length === 0) {
|
|
5
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
6
|
+
}
|
|
7
|
+
return trimmed;
|
|
8
|
+
}
|
|
9
|
+
function normalizeWhitespace(value) {
|
|
10
|
+
return value.replace(/\s+/gu, " ").trim();
|
|
11
|
+
}
|
|
2
12
|
var AI_SPEECH_PACKAGE = "@plasius/ai-speech";
|
|
3
|
-
var AI_SPEECH_FEATURE_FLAG_ID = "ai.speech.enabled";
|
|
4
13
|
var AI_SPEECH_ENV_PREFIX = "AI_SPEECH";
|
|
14
|
+
var AI_SPEECH_FEATURE_FLAGS = {
|
|
15
|
+
ttsCache: "ai.tts.cache.enabled",
|
|
16
|
+
ttsNearReuse: "ai.tts.near-reuse.enabled",
|
|
17
|
+
premiumCharacters: "ai.tts.premium-characters.enabled"
|
|
18
|
+
};
|
|
19
|
+
var AI_SPEECH_FEATURE_FLAG_ID = AI_SPEECH_FEATURE_FLAGS.ttsCache;
|
|
20
|
+
var AI_SPEECH_ROLLOUT_EVALUATORS = [
|
|
21
|
+
"remote-flag-service",
|
|
22
|
+
"host-application",
|
|
23
|
+
"break-glass-env"
|
|
24
|
+
];
|
|
25
|
+
var AI_SPEECH_ROLLOUT_FALLBACK_MODES = [
|
|
26
|
+
"fail-closed",
|
|
27
|
+
"fail-open"
|
|
28
|
+
];
|
|
29
|
+
var AI_SPEECH_ROLLOUTS = Object.freeze({
|
|
30
|
+
ttsCache: Object.freeze({
|
|
31
|
+
featureFlag: AI_SPEECH_FEATURE_FLAGS.ttsCache,
|
|
32
|
+
evaluator: "remote-flag-service",
|
|
33
|
+
defaultEnabled: false,
|
|
34
|
+
fallbackMode: "fail-closed"
|
|
35
|
+
}),
|
|
36
|
+
ttsNearReuse: Object.freeze({
|
|
37
|
+
featureFlag: AI_SPEECH_FEATURE_FLAGS.ttsNearReuse,
|
|
38
|
+
evaluator: "remote-flag-service",
|
|
39
|
+
defaultEnabled: false,
|
|
40
|
+
fallbackMode: "fail-closed"
|
|
41
|
+
}),
|
|
42
|
+
premiumCharacters: Object.freeze({
|
|
43
|
+
featureFlag: AI_SPEECH_FEATURE_FLAGS.premiumCharacters,
|
|
44
|
+
evaluator: "remote-flag-service",
|
|
45
|
+
defaultEnabled: false,
|
|
46
|
+
fallbackMode: "fail-closed"
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
function resolveAiSpeechRolloutDecision(control, snapshot = {}) {
|
|
50
|
+
const resolved = snapshot[control.featureFlag];
|
|
51
|
+
if (typeof resolved === "boolean") {
|
|
52
|
+
return {
|
|
53
|
+
...control,
|
|
54
|
+
enabled: resolved,
|
|
55
|
+
source: "snapshot"
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
...control,
|
|
60
|
+
enabled: control.defaultEnabled,
|
|
61
|
+
source: "default"
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function isAiSpeechFeatureEnabled(featureFlag, snapshot = {}) {
|
|
65
|
+
const control = Object.values(AI_SPEECH_ROLLOUTS).find(
|
|
66
|
+
(candidate) => candidate.featureFlag === featureFlag
|
|
67
|
+
);
|
|
68
|
+
if (!control) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return resolveAiSpeechRolloutDecision(control, snapshot).enabled;
|
|
72
|
+
}
|
|
73
|
+
var AI_SPEECH_VOICE_TIERS = [
|
|
74
|
+
"development",
|
|
75
|
+
"standard",
|
|
76
|
+
"premium-character"
|
|
77
|
+
];
|
|
78
|
+
var AI_SPEECH_ENVIRONMENTS = [
|
|
79
|
+
"development",
|
|
80
|
+
"preview",
|
|
81
|
+
"production"
|
|
82
|
+
];
|
|
83
|
+
function resolveAiSpeechVoiceTier(input) {
|
|
84
|
+
const requestedTier = input.requestedTier ?? (input.environment === "development" ? "development" : "standard");
|
|
85
|
+
if (requestedTier === "premium-character" && !isAiSpeechFeatureEnabled(
|
|
86
|
+
AI_SPEECH_FEATURE_FLAGS.premiumCharacters,
|
|
87
|
+
input.featureFlags
|
|
88
|
+
)) {
|
|
89
|
+
return {
|
|
90
|
+
requestedTier,
|
|
91
|
+
resolvedTier: "standard",
|
|
92
|
+
fallbackTier: "standard",
|
|
93
|
+
reasonCodes: ["premium-character-rollout-disabled"]
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (requestedTier === "development" && input.environment !== "development") {
|
|
97
|
+
return {
|
|
98
|
+
requestedTier,
|
|
99
|
+
resolvedTier: "standard",
|
|
100
|
+
fallbackTier: "standard",
|
|
101
|
+
reasonCodes: ["development-voices-limited-to-development-environments"]
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
requestedTier,
|
|
106
|
+
resolvedTier: requestedTier,
|
|
107
|
+
reasonCodes: []
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
var AI_SPEECH_PLAYER_ADDRESS_SOURCES = [
|
|
111
|
+
"generic-player",
|
|
112
|
+
"class-title",
|
|
113
|
+
"faction-title",
|
|
114
|
+
"authored-character",
|
|
115
|
+
"user-name",
|
|
116
|
+
"account-handle",
|
|
117
|
+
"user-renamed-character"
|
|
118
|
+
];
|
|
119
|
+
var AI_SPEECH_DEFAULT_PLAYER_LABEL = "Player";
|
|
120
|
+
function resolveAiSpeechPlayerAddress(input) {
|
|
121
|
+
const fallbackLabel = normalizeWhitespace(input.fallbackLabel ?? "") || AI_SPEECH_DEFAULT_PLAYER_LABEL;
|
|
122
|
+
const rawValue = normalizeWhitespace(input.rawValue ?? "");
|
|
123
|
+
switch (input.source) {
|
|
124
|
+
case "generic-player":
|
|
125
|
+
return {
|
|
126
|
+
source: input.source,
|
|
127
|
+
renderText: fallbackLabel,
|
|
128
|
+
exactReuseAllowed: true,
|
|
129
|
+
nearReuseAllowed: true,
|
|
130
|
+
redacted: false,
|
|
131
|
+
reasonCodes: ["generic-player-address"]
|
|
132
|
+
};
|
|
133
|
+
case "class-title":
|
|
134
|
+
case "faction-title":
|
|
135
|
+
return {
|
|
136
|
+
source: input.source,
|
|
137
|
+
renderText: rawValue || fallbackLabel,
|
|
138
|
+
exactReuseAllowed: true,
|
|
139
|
+
nearReuseAllowed: true,
|
|
140
|
+
redacted: false,
|
|
141
|
+
reasonCodes: rawValue ? [] : ["player-address-fell-back-to-generic-label"]
|
|
142
|
+
};
|
|
143
|
+
case "authored-character":
|
|
144
|
+
return {
|
|
145
|
+
source: input.source,
|
|
146
|
+
renderText: rawValue || fallbackLabel,
|
|
147
|
+
exactReuseAllowed: true,
|
|
148
|
+
nearReuseAllowed: true,
|
|
149
|
+
redacted: false,
|
|
150
|
+
reasonCodes: rawValue ? [] : ["player-address-fell-back-to-generic-label"]
|
|
151
|
+
};
|
|
152
|
+
case "user-name":
|
|
153
|
+
case "account-handle":
|
|
154
|
+
case "user-renamed-character":
|
|
155
|
+
return {
|
|
156
|
+
source: input.source,
|
|
157
|
+
renderText: fallbackLabel,
|
|
158
|
+
exactReuseAllowed: true,
|
|
159
|
+
nearReuseAllowed: false,
|
|
160
|
+
redacted: true,
|
|
161
|
+
reasonCodes: ["player-identifier-redacted-from-render-text"]
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function renderAiSpeechText(input) {
|
|
166
|
+
const textTemplate = requireNonEmptyString(
|
|
167
|
+
input.textTemplate,
|
|
168
|
+
"Speech text template"
|
|
169
|
+
);
|
|
170
|
+
const hasPlayerPlaceholder = textTemplate.includes("{playerAddress}");
|
|
171
|
+
if (hasPlayerPlaceholder && !input.playerAddress) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
"Speech text template requires playerAddress when using the {playerAddress} placeholder."
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
const playerAddress = input.playerAddress ? resolveAiSpeechPlayerAddress(input.playerAddress) : void 0;
|
|
177
|
+
const renderText = normalizeWhitespace(
|
|
178
|
+
hasPlayerPlaceholder && playerAddress ? textTemplate.replace(/\{playerAddress\}/gu, playerAddress.renderText) : textTemplate
|
|
179
|
+
);
|
|
180
|
+
return {
|
|
181
|
+
renderText,
|
|
182
|
+
normalizedRenderText: normalizeAiSpeechText(renderText),
|
|
183
|
+
playerAddress
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function normalizeAiSpeechText(value) {
|
|
187
|
+
return requireNonEmptyString(
|
|
188
|
+
normalizeWhitespace(value).toLocaleLowerCase("en-GB"),
|
|
189
|
+
"Speech text"
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
var AI_SPEECH_PROVIDER_CACHE_PERMISSIONS = [
|
|
193
|
+
"forbidden",
|
|
194
|
+
"exact-only",
|
|
195
|
+
"exact-and-near"
|
|
196
|
+
];
|
|
197
|
+
var AI_SPEECH_CACHE_MODES = [
|
|
198
|
+
"disabled",
|
|
199
|
+
"no-cache",
|
|
200
|
+
"exact",
|
|
201
|
+
"near"
|
|
202
|
+
];
|
|
203
|
+
var AI_SPEECH_CACHE_SCOPES = ["none", "actor", "global"];
|
|
204
|
+
var AI_SPEECH_UTTERANCE_CLASSES = [
|
|
205
|
+
"system-generic",
|
|
206
|
+
"game-npc-dialogue",
|
|
207
|
+
"game-bark",
|
|
208
|
+
"player-address",
|
|
209
|
+
"moderation-notice",
|
|
210
|
+
"private-response"
|
|
211
|
+
];
|
|
212
|
+
var AI_SPEECH_NEAR_REUSE_SAFE_CLASSES = [
|
|
213
|
+
"system-generic",
|
|
214
|
+
"game-npc-dialogue",
|
|
215
|
+
"game-bark",
|
|
216
|
+
"player-address"
|
|
217
|
+
];
|
|
218
|
+
var AI_SPEECH_NEAR_REUSE_SAFE_CLASS_SET = new Set(AI_SPEECH_NEAR_REUSE_SAFE_CLASSES);
|
|
219
|
+
function createAiSpeechCacheKey(input) {
|
|
220
|
+
const scopeDiscriminator = normalizeWhitespace(input.scopeDiscriminator ?? "");
|
|
221
|
+
return [
|
|
222
|
+
requireNonEmptyString(input.providerId, "Provider id"),
|
|
223
|
+
requireNonEmptyString(input.modelId, "Model id"),
|
|
224
|
+
requireNonEmptyString(input.voiceId, "Voice id"),
|
|
225
|
+
requireNonEmptyString(input.locale, "Locale"),
|
|
226
|
+
normalizeWhitespace(input.styleId ?? "") || "_",
|
|
227
|
+
requireNonEmptyString(input.format, "Format"),
|
|
228
|
+
requireNonEmptyString(
|
|
229
|
+
input.pronunciationVersion,
|
|
230
|
+
"Pronunciation version"
|
|
231
|
+
),
|
|
232
|
+
scopeDiscriminator || "global",
|
|
233
|
+
normalizeAiSpeechText(input.normalizedRenderText)
|
|
234
|
+
].map((segment) => encodeURIComponent(segment)).join("::");
|
|
235
|
+
}
|
|
236
|
+
function createAiSpeechNearReuseFingerprint(value) {
|
|
237
|
+
const normalized = normalizeAiSpeechText(value).replace(/[^a-z0-9\s]/gu, " ").replace(/\s+/gu, " ").trim();
|
|
238
|
+
return requireNonEmptyString(normalized, "Near-reuse fingerprint");
|
|
239
|
+
}
|
|
240
|
+
function isAiSpeechNearReuseSafeClass(utteranceClass) {
|
|
241
|
+
return AI_SPEECH_NEAR_REUSE_SAFE_CLASS_SET.has(utteranceClass);
|
|
242
|
+
}
|
|
243
|
+
function planAiSpeechCache(input) {
|
|
244
|
+
const rendered = renderAiSpeechText({
|
|
245
|
+
textTemplate: input.textTemplate,
|
|
246
|
+
playerAddress: input.playerAddress
|
|
247
|
+
});
|
|
248
|
+
const enabledFeatureFlags = [];
|
|
249
|
+
const cacheEnabled = isAiSpeechFeatureEnabled(
|
|
250
|
+
AI_SPEECH_FEATURE_FLAGS.ttsCache,
|
|
251
|
+
input.featureFlags
|
|
252
|
+
);
|
|
253
|
+
if (!cacheEnabled) {
|
|
254
|
+
return {
|
|
255
|
+
mode: "disabled",
|
|
256
|
+
sharingScope: "none",
|
|
257
|
+
renderText: rendered.renderText,
|
|
258
|
+
normalizedRenderText: rendered.normalizedRenderText,
|
|
259
|
+
enabledFeatureFlags,
|
|
260
|
+
playerAddress: rendered.playerAddress,
|
|
261
|
+
reasonCodes: ["tts-cache-rollout-disabled"]
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
enabledFeatureFlags.push(AI_SPEECH_FEATURE_FLAGS.ttsCache);
|
|
265
|
+
if (input.voice.cachePermission === "forbidden") {
|
|
266
|
+
return {
|
|
267
|
+
mode: "no-cache",
|
|
268
|
+
sharingScope: "none",
|
|
269
|
+
renderText: rendered.renderText,
|
|
270
|
+
normalizedRenderText: rendered.normalizedRenderText,
|
|
271
|
+
enabledFeatureFlags,
|
|
272
|
+
playerAddress: rendered.playerAddress,
|
|
273
|
+
reasonCodes: ["provider-forbids-tts-caching"]
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
const containsSensitiveContent = Boolean(input.containsPersonalData) || Boolean(input.containsPrivateContext) || Boolean(input.containsModerationNotice) || Boolean(rendered.playerAddress?.redacted);
|
|
277
|
+
const actorScopeKey = normalizeWhitespace(input.actorScopeKey ?? "");
|
|
278
|
+
const actorScopeRequired = containsSensitiveContent || input.utteranceClass === "private-response";
|
|
279
|
+
if (actorScopeRequired && !actorScopeKey) {
|
|
280
|
+
return {
|
|
281
|
+
mode: "no-cache",
|
|
282
|
+
sharingScope: "none",
|
|
283
|
+
renderText: rendered.renderText,
|
|
284
|
+
normalizedRenderText: rendered.normalizedRenderText,
|
|
285
|
+
enabledFeatureFlags,
|
|
286
|
+
playerAddress: rendered.playerAddress,
|
|
287
|
+
reasonCodes: ["actor-scope-key-required-for-sensitive-cache-entry"]
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
const exactKey = createAiSpeechCacheKey({
|
|
291
|
+
...input.voice,
|
|
292
|
+
normalizedRenderText: rendered.normalizedRenderText,
|
|
293
|
+
scopeDiscriminator: actorScopeRequired ? actorScopeKey : void 0
|
|
294
|
+
});
|
|
295
|
+
const nearReuseEnabled = input.voice.cachePermission === "exact-and-near" && isAiSpeechFeatureEnabled(
|
|
296
|
+
AI_SPEECH_FEATURE_FLAGS.ttsNearReuse,
|
|
297
|
+
input.featureFlags
|
|
298
|
+
) && isAiSpeechNearReuseSafeClass(input.utteranceClass) && !containsSensitiveContent && (rendered.playerAddress?.nearReuseAllowed ?? true);
|
|
299
|
+
if (!nearReuseEnabled) {
|
|
300
|
+
return {
|
|
301
|
+
mode: "exact",
|
|
302
|
+
sharingScope: actorScopeRequired ? "actor" : "global",
|
|
303
|
+
renderText: rendered.renderText,
|
|
304
|
+
normalizedRenderText: rendered.normalizedRenderText,
|
|
305
|
+
exactKey,
|
|
306
|
+
enabledFeatureFlags,
|
|
307
|
+
playerAddress: rendered.playerAddress,
|
|
308
|
+
reasonCodes: containsSensitiveContent ? ["exact-cache-only-for-sensitive-or-redacted-content"] : ["near-reuse-disabled-or-ineligible"]
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
enabledFeatureFlags.push(AI_SPEECH_FEATURE_FLAGS.ttsNearReuse);
|
|
312
|
+
const nearKey = createAiSpeechCacheKey({
|
|
313
|
+
...input.voice,
|
|
314
|
+
normalizedRenderText: createAiSpeechNearReuseFingerprint(
|
|
315
|
+
rendered.normalizedRenderText
|
|
316
|
+
)
|
|
317
|
+
});
|
|
318
|
+
return {
|
|
319
|
+
mode: "near",
|
|
320
|
+
sharingScope: "global",
|
|
321
|
+
renderText: rendered.renderText,
|
|
322
|
+
normalizedRenderText: rendered.normalizedRenderText,
|
|
323
|
+
exactKey,
|
|
324
|
+
nearKey,
|
|
325
|
+
enabledFeatureFlags,
|
|
326
|
+
playerAddress: rendered.playerAddress,
|
|
327
|
+
reasonCodes: ["near-reuse-eligible"]
|
|
328
|
+
};
|
|
329
|
+
}
|
|
5
330
|
var packageDescriptor = Object.freeze({
|
|
6
331
|
packageName: AI_SPEECH_PACKAGE,
|
|
7
332
|
featureFlagId: AI_SPEECH_FEATURE_FLAG_ID,
|
|
@@ -9,9 +334,32 @@ var packageDescriptor = Object.freeze({
|
|
|
9
334
|
summary: "Speech orchestration, TTS cache contracts, STT/TTS routing, and voice tier policy for Plasius AI."
|
|
10
335
|
});
|
|
11
336
|
export {
|
|
337
|
+
AI_SPEECH_CACHE_MODES,
|
|
338
|
+
AI_SPEECH_CACHE_SCOPES,
|
|
339
|
+
AI_SPEECH_DEFAULT_PLAYER_LABEL,
|
|
340
|
+
AI_SPEECH_ENVIRONMENTS,
|
|
12
341
|
AI_SPEECH_ENV_PREFIX,
|
|
342
|
+
AI_SPEECH_FEATURE_FLAGS,
|
|
13
343
|
AI_SPEECH_FEATURE_FLAG_ID,
|
|
344
|
+
AI_SPEECH_NEAR_REUSE_SAFE_CLASSES,
|
|
14
345
|
AI_SPEECH_PACKAGE,
|
|
15
|
-
|
|
346
|
+
AI_SPEECH_PLAYER_ADDRESS_SOURCES,
|
|
347
|
+
AI_SPEECH_PROVIDER_CACHE_PERMISSIONS,
|
|
348
|
+
AI_SPEECH_ROLLOUTS,
|
|
349
|
+
AI_SPEECH_ROLLOUT_EVALUATORS,
|
|
350
|
+
AI_SPEECH_ROLLOUT_FALLBACK_MODES,
|
|
351
|
+
AI_SPEECH_UTTERANCE_CLASSES,
|
|
352
|
+
AI_SPEECH_VOICE_TIERS,
|
|
353
|
+
createAiSpeechCacheKey,
|
|
354
|
+
createAiSpeechNearReuseFingerprint,
|
|
355
|
+
isAiSpeechFeatureEnabled,
|
|
356
|
+
isAiSpeechNearReuseSafeClass,
|
|
357
|
+
normalizeAiSpeechText,
|
|
358
|
+
packageDescriptor,
|
|
359
|
+
planAiSpeechCache,
|
|
360
|
+
renderAiSpeechText,
|
|
361
|
+
resolveAiSpeechPlayerAddress,
|
|
362
|
+
resolveAiSpeechRolloutDecision,
|
|
363
|
+
resolveAiSpeechVoiceTier
|
|
16
364
|
};
|
|
17
365
|
//# sourceMappingURL=index.js.map
|