@framers/agentos-ext-diarization 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 +71 -0
- package/dist/ClusteringStrategy.d.ts +56 -0
- package/dist/ClusteringStrategy.d.ts.map +1 -0
- package/dist/ClusteringStrategy.js +123 -0
- package/dist/ClusteringStrategy.js.map +1 -0
- package/dist/DiarizationEngine.d.ts +45 -0
- package/dist/DiarizationEngine.d.ts.map +1 -0
- package/dist/DiarizationEngine.js +84 -0
- package/dist/DiarizationEngine.js.map +1 -0
- package/dist/DiarizationSession.d.ts +90 -0
- package/dist/DiarizationSession.d.ts.map +1 -0
- package/dist/DiarizationSession.js +139 -0
- package/dist/DiarizationSession.js.map +1 -0
- package/dist/LocalDiarizationBackend.d.ts +90 -0
- package/dist/LocalDiarizationBackend.d.ts.map +1 -0
- package/dist/LocalDiarizationBackend.js +177 -0
- package/dist/LocalDiarizationBackend.js.map +1 -0
- package/dist/ProviderDiarizationBackend.d.ts +54 -0
- package/dist/ProviderDiarizationBackend.d.ts.map +1 -0
- package/dist/ProviderDiarizationBackend.js +101 -0
- package/dist/ProviderDiarizationBackend.js.map +1 -0
- package/dist/SlidingWindowExtractor.d.ts +85 -0
- package/dist/SlidingWindowExtractor.d.ts.map +1 -0
- package/dist/SlidingWindowExtractor.js +140 -0
- package/dist/SlidingWindowExtractor.js.map +1 -0
- package/dist/SpeakerEmbeddingCache.d.ts +117 -0
- package/dist/SpeakerEmbeddingCache.d.ts.map +1 -0
- package/dist/SpeakerEmbeddingCache.js +193 -0
- package/dist/SpeakerEmbeddingCache.js.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +177 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/manifest.json +8 -0
- package/package.json +48 -0
- package/src/ClusteringStrategy.ts +139 -0
- package/src/DiarizationEngine.ts +94 -0
- package/src/DiarizationSession.ts +178 -0
- package/src/LocalDiarizationBackend.ts +201 -0
- package/src/ProviderDiarizationBackend.ts +119 -0
- package/src/SlidingWindowExtractor.ts +174 -0
- package/src/SpeakerEmbeddingCache.ts +228 -0
- package/src/index.ts +105 -0
- package/src/types.ts +221 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlidingWindowExtractor.js","sourceRoot":"","sources":["../src/SlidingWindowExtractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file SpeakerEmbeddingCache.ts
|
|
3
|
+
* @description Stores and matches speaker voiceprints using cosine similarity.
|
|
4
|
+
*
|
|
5
|
+
* Each speaker is represented as a running centroid — the mean of all
|
|
6
|
+
* embeddings observed so far. New audio embeddings are matched against
|
|
7
|
+
* existing centroids; if the best match exceeds the similarity threshold the
|
|
8
|
+
* frame is attributed to that speaker and the centroid is updated. Otherwise
|
|
9
|
+
* a new `Speaker_N` identity is created.
|
|
10
|
+
*
|
|
11
|
+
* @module diarization/SpeakerEmbeddingCache
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Compute the cosine similarity between two embedding vectors.
|
|
15
|
+
*
|
|
16
|
+
* Returns a value in the range `[-1, 1]`. A small epsilon is added to the
|
|
17
|
+
* denominator to prevent division-by-zero on silent/zero frames.
|
|
18
|
+
*
|
|
19
|
+
* @param a - First embedding vector.
|
|
20
|
+
* @param b - Second embedding vector.
|
|
21
|
+
* @returns Cosine similarity.
|
|
22
|
+
*/
|
|
23
|
+
export declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
|
|
24
|
+
/**
|
|
25
|
+
* In-memory cache of speaker voiceprint centroids.
|
|
26
|
+
*
|
|
27
|
+
* Centroids are updated with an online running-average as new embeddings
|
|
28
|
+
* arrive, so memory usage is O(speakers × embedding dimensions) regardless of
|
|
29
|
+
* the number of frames observed.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const cache = new SpeakerEmbeddingCache(0.7);
|
|
34
|
+
* const { speakerId, isNew } = cache.getOrCreateSpeaker(embedding);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare class SpeakerEmbeddingCache {
|
|
38
|
+
private readonly threshold;
|
|
39
|
+
/**
|
|
40
|
+
* Centroid map: `speakerId → { embedding, count }`.
|
|
41
|
+
*
|
|
42
|
+
* Access via {@link centroids} for testing/introspection.
|
|
43
|
+
*/
|
|
44
|
+
private readonly _centroids;
|
|
45
|
+
/**
|
|
46
|
+
* @param threshold - Minimum cosine similarity required to attribute a new
|
|
47
|
+
* embedding to an existing speaker. Embeddings below this threshold
|
|
48
|
+
* create a new speaker identity.
|
|
49
|
+
* @defaultValue 0.7
|
|
50
|
+
*/
|
|
51
|
+
constructor(threshold?: number);
|
|
52
|
+
/**
|
|
53
|
+
* Update the running centroid for `speakerId` with a new embedding.
|
|
54
|
+
*
|
|
55
|
+
* The centroid is recalculated as an online running average:
|
|
56
|
+
* `new_mean = old_mean + (x - old_mean) / (count + 1)`.
|
|
57
|
+
*
|
|
58
|
+
* @param speakerId - Speaker identity to update.
|
|
59
|
+
* @param embedding - New embedding vector to incorporate.
|
|
60
|
+
*/
|
|
61
|
+
addEmbedding(speakerId: string, embedding: Float32Array): void;
|
|
62
|
+
/**
|
|
63
|
+
* Find the existing speaker whose centroid is most similar to `embedding`.
|
|
64
|
+
*
|
|
65
|
+
* Returns `null` if no speaker exceeds the similarity threshold or the cache
|
|
66
|
+
* is empty.
|
|
67
|
+
*
|
|
68
|
+
* @param embedding - Query embedding vector.
|
|
69
|
+
* @returns Best match above threshold, or `null`.
|
|
70
|
+
*/
|
|
71
|
+
findClosestSpeaker(embedding: Float32Array): {
|
|
72
|
+
speakerId: string;
|
|
73
|
+
similarity: number;
|
|
74
|
+
} | null;
|
|
75
|
+
/**
|
|
76
|
+
* Look up or create a speaker identity for `embedding`.
|
|
77
|
+
*
|
|
78
|
+
* If a match above the threshold is found, the centroid is updated and the
|
|
79
|
+
* existing ID is returned. Otherwise a new `Speaker_N` identity is
|
|
80
|
+
* registered.
|
|
81
|
+
*
|
|
82
|
+
* @param embedding - Audio embedding to resolve.
|
|
83
|
+
* @returns Speaker ID and whether a new identity was created.
|
|
84
|
+
*/
|
|
85
|
+
getOrCreateSpeaker(embedding: Float32Array): {
|
|
86
|
+
speakerId: string;
|
|
87
|
+
isNew: boolean;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Pre-register a known speaker voiceprint, overwriting any existing centroid
|
|
91
|
+
* for this ID.
|
|
92
|
+
*
|
|
93
|
+
* Use this to seed the cache with enrolment recordings before a session
|
|
94
|
+
* begins so that known participants are matched by name rather than the
|
|
95
|
+
* auto-generated `Speaker_N` label.
|
|
96
|
+
*
|
|
97
|
+
* @param id - Human-readable speaker identifier.
|
|
98
|
+
* @param voiceprint - Reference embedding for this speaker.
|
|
99
|
+
*/
|
|
100
|
+
enrollSpeaker(id: string, voiceprint: Float32Array): void;
|
|
101
|
+
/**
|
|
102
|
+
* Read-only view of the internal centroid map.
|
|
103
|
+
*
|
|
104
|
+
* Returns a snapshot — modifications to the returned map do not affect the
|
|
105
|
+
* cache.
|
|
106
|
+
*/
|
|
107
|
+
get centroids(): Map<string, Float32Array>;
|
|
108
|
+
/** Number of distinct speaker identities currently tracked. */
|
|
109
|
+
get size(): number;
|
|
110
|
+
/**
|
|
111
|
+
* Remove all centroids from the cache.
|
|
112
|
+
*
|
|
113
|
+
* Useful for resetting state between test cases.
|
|
114
|
+
*/
|
|
115
|
+
clear(): void;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=SpeakerEmbeddingCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpeakerEmbeddingCache.d.ts","sourceRoot":"","sources":["../src/SpeakerEmbeddingCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkBH;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAYzE;AAMD;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAqB;IAsBpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAjBtC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAM/D;;;;;OAKG;gBAC0B,SAAS,GAAE,MAAY;IAMpD;;;;;;;;OAQG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI;IAuB9D;;;;;;;;OAQG;IACH,kBAAkB,CAAC,SAAS,EAAE,YAAY,GAAG;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAmB7F;;;;;;;;;OASG;IACH,kBAAkB,CAAC,SAAS,EAAE,YAAY,GAAG;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;IAalF;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,GAAG,IAAI;IAQzD;;;;;OAKG;IACH,IAAI,SAAS,IAAI,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAMzC;IAED,+DAA+D;IAC/D,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file SpeakerEmbeddingCache.ts
|
|
3
|
+
* @description Stores and matches speaker voiceprints using cosine similarity.
|
|
4
|
+
*
|
|
5
|
+
* Each speaker is represented as a running centroid — the mean of all
|
|
6
|
+
* embeddings observed so far. New audio embeddings are matched against
|
|
7
|
+
* existing centroids; if the best match exceeds the similarity threshold the
|
|
8
|
+
* frame is attributed to that speaker and the centroid is updated. Otherwise
|
|
9
|
+
* a new `Speaker_N` identity is created.
|
|
10
|
+
*
|
|
11
|
+
* @module diarization/SpeakerEmbeddingCache
|
|
12
|
+
*/
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Helpers
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
/**
|
|
17
|
+
* Compute the cosine similarity between two embedding vectors.
|
|
18
|
+
*
|
|
19
|
+
* Returns a value in the range `[-1, 1]`. A small epsilon is added to the
|
|
20
|
+
* denominator to prevent division-by-zero on silent/zero frames.
|
|
21
|
+
*
|
|
22
|
+
* @param a - First embedding vector.
|
|
23
|
+
* @param b - Second embedding vector.
|
|
24
|
+
* @returns Cosine similarity.
|
|
25
|
+
*/
|
|
26
|
+
export function cosineSimilarity(a, b) {
|
|
27
|
+
let dot = 0;
|
|
28
|
+
let magA = 0;
|
|
29
|
+
let magB = 0;
|
|
30
|
+
for (let i = 0; i < a.length; i++) {
|
|
31
|
+
dot += a[i] * b[i];
|
|
32
|
+
magA += (a[i]) ** 2;
|
|
33
|
+
magB += (b[i]) ** 2;
|
|
34
|
+
}
|
|
35
|
+
return dot / (Math.sqrt(magA) * Math.sqrt(magB) + 1e-8);
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Main class
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
/**
|
|
41
|
+
* In-memory cache of speaker voiceprint centroids.
|
|
42
|
+
*
|
|
43
|
+
* Centroids are updated with an online running-average as new embeddings
|
|
44
|
+
* arrive, so memory usage is O(speakers × embedding dimensions) regardless of
|
|
45
|
+
* the number of frames observed.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const cache = new SpeakerEmbeddingCache(0.7);
|
|
50
|
+
* const { speakerId, isNew } = cache.getOrCreateSpeaker(embedding);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export class SpeakerEmbeddingCache {
|
|
54
|
+
threshold;
|
|
55
|
+
// -------------------------------------------------------------------------
|
|
56
|
+
// Private state
|
|
57
|
+
// -------------------------------------------------------------------------
|
|
58
|
+
/**
|
|
59
|
+
* Centroid map: `speakerId → { embedding, count }`.
|
|
60
|
+
*
|
|
61
|
+
* Access via {@link centroids} for testing/introspection.
|
|
62
|
+
*/
|
|
63
|
+
_centroids = new Map();
|
|
64
|
+
// -------------------------------------------------------------------------
|
|
65
|
+
// Constructor
|
|
66
|
+
// -------------------------------------------------------------------------
|
|
67
|
+
/**
|
|
68
|
+
* @param threshold - Minimum cosine similarity required to attribute a new
|
|
69
|
+
* embedding to an existing speaker. Embeddings below this threshold
|
|
70
|
+
* create a new speaker identity.
|
|
71
|
+
* @defaultValue 0.7
|
|
72
|
+
*/
|
|
73
|
+
constructor(threshold = 0.7) {
|
|
74
|
+
this.threshold = threshold;
|
|
75
|
+
}
|
|
76
|
+
// -------------------------------------------------------------------------
|
|
77
|
+
// Public API
|
|
78
|
+
// -------------------------------------------------------------------------
|
|
79
|
+
/**
|
|
80
|
+
* Update the running centroid for `speakerId` with a new embedding.
|
|
81
|
+
*
|
|
82
|
+
* The centroid is recalculated as an online running average:
|
|
83
|
+
* `new_mean = old_mean + (x - old_mean) / (count + 1)`.
|
|
84
|
+
*
|
|
85
|
+
* @param speakerId - Speaker identity to update.
|
|
86
|
+
* @param embedding - New embedding vector to incorporate.
|
|
87
|
+
*/
|
|
88
|
+
addEmbedding(speakerId, embedding) {
|
|
89
|
+
const existing = this._centroids.get(speakerId);
|
|
90
|
+
if (!existing) {
|
|
91
|
+
// First frame — store a copy of the embedding directly.
|
|
92
|
+
this._centroids.set(speakerId, {
|
|
93
|
+
embedding: embedding.slice(),
|
|
94
|
+
count: 1,
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Online running average: mean_n = mean_{n-1} + (x - mean_{n-1}) / n
|
|
99
|
+
const newCount = existing.count + 1;
|
|
100
|
+
const newEmbedding = new Float32Array(existing.embedding.length);
|
|
101
|
+
for (let i = 0; i < existing.embedding.length; i++) {
|
|
102
|
+
newEmbedding[i] = existing.embedding[i] + (embedding[i] - existing.embedding[i]) / newCount;
|
|
103
|
+
}
|
|
104
|
+
this._centroids.set(speakerId, { embedding: newEmbedding, count: newCount });
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Find the existing speaker whose centroid is most similar to `embedding`.
|
|
108
|
+
*
|
|
109
|
+
* Returns `null` if no speaker exceeds the similarity threshold or the cache
|
|
110
|
+
* is empty.
|
|
111
|
+
*
|
|
112
|
+
* @param embedding - Query embedding vector.
|
|
113
|
+
* @returns Best match above threshold, or `null`.
|
|
114
|
+
*/
|
|
115
|
+
findClosestSpeaker(embedding) {
|
|
116
|
+
let bestId = null;
|
|
117
|
+
let bestSim = -Infinity;
|
|
118
|
+
for (const [id, entry] of this._centroids) {
|
|
119
|
+
const sim = cosineSimilarity(embedding, entry.embedding);
|
|
120
|
+
if (sim > bestSim) {
|
|
121
|
+
bestSim = sim;
|
|
122
|
+
bestId = id;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (bestId === null || bestSim < this.threshold) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
return { speakerId: bestId, similarity: bestSim };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Look up or create a speaker identity for `embedding`.
|
|
132
|
+
*
|
|
133
|
+
* If a match above the threshold is found, the centroid is updated and the
|
|
134
|
+
* existing ID is returned. Otherwise a new `Speaker_N` identity is
|
|
135
|
+
* registered.
|
|
136
|
+
*
|
|
137
|
+
* @param embedding - Audio embedding to resolve.
|
|
138
|
+
* @returns Speaker ID and whether a new identity was created.
|
|
139
|
+
*/
|
|
140
|
+
getOrCreateSpeaker(embedding) {
|
|
141
|
+
const match = this.findClosestSpeaker(embedding);
|
|
142
|
+
if (match) {
|
|
143
|
+
this.addEmbedding(match.speakerId, embedding);
|
|
144
|
+
return { speakerId: match.speakerId, isNew: false };
|
|
145
|
+
}
|
|
146
|
+
const newId = `Speaker_${this._centroids.size}`;
|
|
147
|
+
this.addEmbedding(newId, embedding);
|
|
148
|
+
return { speakerId: newId, isNew: true };
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Pre-register a known speaker voiceprint, overwriting any existing centroid
|
|
152
|
+
* for this ID.
|
|
153
|
+
*
|
|
154
|
+
* Use this to seed the cache with enrolment recordings before a session
|
|
155
|
+
* begins so that known participants are matched by name rather than the
|
|
156
|
+
* auto-generated `Speaker_N` label.
|
|
157
|
+
*
|
|
158
|
+
* @param id - Human-readable speaker identifier.
|
|
159
|
+
* @param voiceprint - Reference embedding for this speaker.
|
|
160
|
+
*/
|
|
161
|
+
enrollSpeaker(id, voiceprint) {
|
|
162
|
+
this._centroids.set(id, { embedding: voiceprint.slice(), count: 1 });
|
|
163
|
+
}
|
|
164
|
+
// -------------------------------------------------------------------------
|
|
165
|
+
// Accessors (useful for testing and ClusteringStrategy)
|
|
166
|
+
// -------------------------------------------------------------------------
|
|
167
|
+
/**
|
|
168
|
+
* Read-only view of the internal centroid map.
|
|
169
|
+
*
|
|
170
|
+
* Returns a snapshot — modifications to the returned map do not affect the
|
|
171
|
+
* cache.
|
|
172
|
+
*/
|
|
173
|
+
get centroids() {
|
|
174
|
+
const result = new Map();
|
|
175
|
+
for (const [id, entry] of this._centroids) {
|
|
176
|
+
result.set(id, entry.embedding.slice());
|
|
177
|
+
}
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
/** Number of distinct speaker identities currently tracked. */
|
|
181
|
+
get size() {
|
|
182
|
+
return this._centroids.size;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Remove all centroids from the cache.
|
|
186
|
+
*
|
|
187
|
+
* Useful for resetting state between test cases.
|
|
188
|
+
*/
|
|
189
|
+
clear() {
|
|
190
|
+
this._centroids.clear();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=SpeakerEmbeddingCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpeakerEmbeddingCache.js","sourceRoot":"","sources":["../src/SpeakerEmbeddingCache.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @description Pack factory for the Diarization extension pack.
|
|
4
|
+
*
|
|
5
|
+
* ### Usage (direct)
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { createDiarizationEngine } from '@framers/agentos-ext-diarization';
|
|
8
|
+
*
|
|
9
|
+
* const engine = createDiarizationEngine();
|
|
10
|
+
* const session = engine.startSession({ backend: 'local' });
|
|
11
|
+
* session.on('speaker_identified', ({ speakerId }) => console.log(speakerId));
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* ### Usage (manifest-driven)
|
|
15
|
+
* ```json
|
|
16
|
+
* { "packs": [{ "module": "@framers/agentos-ext-diarization" }] }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @module diarization
|
|
20
|
+
*/
|
|
21
|
+
import { DiarizationEngine } from './DiarizationEngine.js';
|
|
22
|
+
/** Subset of ExtensionDescriptor required by this pack. */
|
|
23
|
+
interface ExtensionDescriptor {
|
|
24
|
+
id: string;
|
|
25
|
+
kind: string;
|
|
26
|
+
payload: unknown;
|
|
27
|
+
enableByDefault?: boolean;
|
|
28
|
+
metadata?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
/** Subset of ExtensionPack required by this pack. */
|
|
31
|
+
interface ExtensionPack {
|
|
32
|
+
id: string;
|
|
33
|
+
descriptors: ExtensionDescriptor[];
|
|
34
|
+
}
|
|
35
|
+
/** Subset of ExtensionPackContext required by this pack. */
|
|
36
|
+
interface ExtensionPackContext {
|
|
37
|
+
getSecret?: (id: string) => string | undefined;
|
|
38
|
+
options?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a standalone {@link DiarizationEngine} instance.
|
|
42
|
+
*
|
|
43
|
+
* Use this when composing the engine programmatically outside of the
|
|
44
|
+
* AgentOS extension system.
|
|
45
|
+
*
|
|
46
|
+
* @returns A configured {@link DiarizationEngine}.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createDiarizationEngine(): DiarizationEngine;
|
|
49
|
+
/**
|
|
50
|
+
* AgentOS manifest factory function.
|
|
51
|
+
*
|
|
52
|
+
* Returns an {@link ExtensionPack} containing a single `diarization-provider`
|
|
53
|
+
* descriptor backed by {@link DiarizationEngine}.
|
|
54
|
+
*
|
|
55
|
+
* @param _context - Pack context supplied by the extension manager.
|
|
56
|
+
* @returns A fully configured {@link ExtensionPack}.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createExtensionPack(_context: ExtensionPackContext): ExtensionPack;
|
|
59
|
+
export * from './types.js';
|
|
60
|
+
export { DiarizationEngine } from './DiarizationEngine.js';
|
|
61
|
+
export { DiarizationSession } from './DiarizationSession.js';
|
|
62
|
+
export { SpeakerEmbeddingCache, cosineSimilarity } from './SpeakerEmbeddingCache.js';
|
|
63
|
+
export { ClusteringStrategy } from './ClusteringStrategy.js';
|
|
64
|
+
export { SlidingWindowExtractor } from './SlidingWindowExtractor.js';
|
|
65
|
+
export { ProviderDiarizationBackend } from './ProviderDiarizationBackend.js';
|
|
66
|
+
export { LocalDiarizationBackend } from './LocalDiarizationBackend.js';
|
|
67
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAM3D,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;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,CAE3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,aAAa,CAejF;AAMD,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @description Pack factory for the Diarization extension pack.
|
|
4
|
+
*
|
|
5
|
+
* ### Usage (direct)
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { createDiarizationEngine } from '@framers/agentos-ext-diarization';
|
|
8
|
+
*
|
|
9
|
+
* const engine = createDiarizationEngine();
|
|
10
|
+
* const session = engine.startSession({ backend: 'local' });
|
|
11
|
+
* session.on('speaker_identified', ({ speakerId }) => console.log(speakerId));
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* ### Usage (manifest-driven)
|
|
15
|
+
* ```json
|
|
16
|
+
* { "packs": [{ "module": "@framers/agentos-ext-diarization" }] }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @module diarization
|
|
20
|
+
*/
|
|
21
|
+
import { DiarizationEngine } from './DiarizationEngine.js';
|
|
22
|
+
/** Kind constant matching packages/agentos/src/extensions/types.ts. */
|
|
23
|
+
const EXTENSION_KIND_DIARIZATION = 'diarization-provider';
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Factory
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/**
|
|
28
|
+
* Create a standalone {@link DiarizationEngine} instance.
|
|
29
|
+
*
|
|
30
|
+
* Use this when composing the engine programmatically outside of the
|
|
31
|
+
* AgentOS extension system.
|
|
32
|
+
*
|
|
33
|
+
* @returns A configured {@link DiarizationEngine}.
|
|
34
|
+
*/
|
|
35
|
+
export function createDiarizationEngine() {
|
|
36
|
+
return new DiarizationEngine();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* AgentOS manifest factory function.
|
|
40
|
+
*
|
|
41
|
+
* Returns an {@link ExtensionPack} containing a single `diarization-provider`
|
|
42
|
+
* descriptor backed by {@link DiarizationEngine}.
|
|
43
|
+
*
|
|
44
|
+
* @param _context - Pack context supplied by the extension manager.
|
|
45
|
+
* @returns A fully configured {@link ExtensionPack}.
|
|
46
|
+
*/
|
|
47
|
+
export function createExtensionPack(_context) {
|
|
48
|
+
const engine = new DiarizationEngine();
|
|
49
|
+
return {
|
|
50
|
+
id: 'diarization',
|
|
51
|
+
descriptors: [
|
|
52
|
+
{
|
|
53
|
+
id: 'diarization-engine',
|
|
54
|
+
kind: EXTENSION_KIND_DIARIZATION,
|
|
55
|
+
payload: engine,
|
|
56
|
+
enableByDefault: true,
|
|
57
|
+
metadata: { providerId: 'diarization-local' },
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// Re-exports
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
export * from './types.js';
|
|
66
|
+
export { DiarizationEngine } from './DiarizationEngine.js';
|
|
67
|
+
export { DiarizationSession } from './DiarizationSession.js';
|
|
68
|
+
export { SpeakerEmbeddingCache, cosineSimilarity } from './SpeakerEmbeddingCache.js';
|
|
69
|
+
export { ClusteringStrategy } from './ClusteringStrategy.js';
|
|
70
|
+
export { SlidingWindowExtractor } from './SlidingWindowExtractor.js';
|
|
71
|
+
export { ProviderDiarizationBackend } from './ProviderDiarizationBackend.js';
|
|
72
|
+
export { LocalDiarizationBackend } from './LocalDiarizationBackend.js';
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AA2B3D,uEAAuE;AACvE,MAAM,0BAA0B,GAAG,sBAAsB,CAAC;AAE1D,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,iBAAiB,EAAE,CAAC;AACjC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAA8B;IAChE,MAAM,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAEvC,OAAO;QACL,EAAE,EAAE,aAAa;QACjB,WAAW,EAAE;YACX;gBACE,EAAE,EAAE,oBAAoB;gBACxB,IAAI,EAAE,0BAA0B;gBAChC,OAAO,EAAE,MAAM;gBACf,eAAe,EAAE,IAAI;gBACrB,QAAQ,EAAE,EAAE,UAAU,EAAE,mBAAmB,EAAE;aAC9C;SACF;KACF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file types.ts
|
|
3
|
+
* @description Core types for the diarization extension pack.
|
|
4
|
+
*
|
|
5
|
+
* These types define the public contract shared between the engine, session
|
|
6
|
+
* implementations, and calling code. They intentionally avoid importing from
|
|
7
|
+
* `@framers/agentos` so the pack can boot in environments where the core
|
|
8
|
+
* package is not yet available.
|
|
9
|
+
*
|
|
10
|
+
* @module diarization/types
|
|
11
|
+
*/
|
|
12
|
+
import type { EventEmitter } from 'node:events';
|
|
13
|
+
/**
|
|
14
|
+
* Minimal audio frame type used by the diarization pipeline.
|
|
15
|
+
*
|
|
16
|
+
* Matches the `AudioFrame` shape from `@framers/agentos` voice types so that
|
|
17
|
+
* frames can be forwarded without conversion.
|
|
18
|
+
*/
|
|
19
|
+
export interface AudioFrame {
|
|
20
|
+
/** Raw 32-bit float PCM samples, normalised to the range `[-1, 1]`. */
|
|
21
|
+
samples: Float32Array;
|
|
22
|
+
/** Sample rate in Hz (e.g. 16000). */
|
|
23
|
+
sampleRate: number;
|
|
24
|
+
/** Wall-clock timestamp in milliseconds when the frame was captured. */
|
|
25
|
+
timestamp: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A single word or token produced by an STT provider, optionally annotated
|
|
29
|
+
* with a speaker label.
|
|
30
|
+
*/
|
|
31
|
+
export interface TranscriptWord {
|
|
32
|
+
/** The recognised word text. */
|
|
33
|
+
word: string;
|
|
34
|
+
/** Start time of the word in seconds (relative to session start). */
|
|
35
|
+
start: number;
|
|
36
|
+
/** End time of the word in seconds (relative to session start). */
|
|
37
|
+
end: number;
|
|
38
|
+
/** Provider-assigned speaker label, e.g. `'0'` or `'Speaker_1'`. */
|
|
39
|
+
speaker?: string;
|
|
40
|
+
/** Per-word confidence in the range `[0, 1]`. */
|
|
41
|
+
confidence?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A transcript event as emitted by an STT provider session.
|
|
45
|
+
*
|
|
46
|
+
* Diarization operates on these events when running in provider-delegated
|
|
47
|
+
* mode; the `words` array carries word-level speaker annotations.
|
|
48
|
+
*/
|
|
49
|
+
export interface TranscriptEvent {
|
|
50
|
+
/** Full transcript text for this event. */
|
|
51
|
+
text: string;
|
|
52
|
+
/** Whether this is a finalised (stable) transcript hypothesis. */
|
|
53
|
+
isFinal: boolean;
|
|
54
|
+
/** Word-level tokens with optional speaker labels. */
|
|
55
|
+
words?: TranscriptWord[];
|
|
56
|
+
/** Session-relative timestamp in milliseconds. */
|
|
57
|
+
timestamp: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A contiguous audio or text segment attributed to a single speaker.
|
|
61
|
+
*/
|
|
62
|
+
export interface DiarizedSegment {
|
|
63
|
+
/** Resolved speaker identifier (e.g. `'Alice'` or `'Speaker_0'`). */
|
|
64
|
+
speakerId: string;
|
|
65
|
+
/** Transcript text for this segment, if available. */
|
|
66
|
+
text?: string;
|
|
67
|
+
/** Segment start time in milliseconds (wall clock). */
|
|
68
|
+
startMs: number;
|
|
69
|
+
/** Segment end time in milliseconds (wall clock). */
|
|
70
|
+
endMs: number;
|
|
71
|
+
/** Confidence score for the speaker attribution in the range `[0, 1]`. */
|
|
72
|
+
confidence: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Payload for the `speaker_identified` event emitted by a
|
|
76
|
+
* {@link IDiarizationSession}.
|
|
77
|
+
*/
|
|
78
|
+
export interface SpeakerIdentified {
|
|
79
|
+
/** Resolved speaker identifier. */
|
|
80
|
+
speakerId: string;
|
|
81
|
+
/** Confidence in the range `[0, 1]`. */
|
|
82
|
+
confidence: number;
|
|
83
|
+
/** Wall-clock timestamp in milliseconds when this identification was made. */
|
|
84
|
+
timestamp: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Configuration object for {@link IDiarizationEngine.startSession}.
|
|
88
|
+
*/
|
|
89
|
+
export interface DiarizationConfig {
|
|
90
|
+
/**
|
|
91
|
+
* Backend to use.
|
|
92
|
+
* - `'provider'` — extract speaker labels from STT provider word results.
|
|
93
|
+
* - `'local'` — use the built-in spectral-centroid sliding-window backend.
|
|
94
|
+
* @defaultValue 'local'
|
|
95
|
+
*/
|
|
96
|
+
backend?: 'provider' | 'local';
|
|
97
|
+
/**
|
|
98
|
+
* Cosine similarity threshold for speaker matching.
|
|
99
|
+
* Embeddings with similarity above this value are attributed to the same
|
|
100
|
+
* speaker.
|
|
101
|
+
* @defaultValue 0.7
|
|
102
|
+
*/
|
|
103
|
+
similarityThreshold?: number;
|
|
104
|
+
/**
|
|
105
|
+
* Hint for the clustering strategy — how many distinct speakers are expected
|
|
106
|
+
* in this session. When set, the engine will try to merge centroids until
|
|
107
|
+
* this count is reached.
|
|
108
|
+
*/
|
|
109
|
+
expectedSpeakers?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Chunk duration in milliseconds for the sliding-window extractor.
|
|
112
|
+
* @defaultValue 1500
|
|
113
|
+
*/
|
|
114
|
+
chunkSizeMs?: number;
|
|
115
|
+
/**
|
|
116
|
+
* Overlap between consecutive chunks in milliseconds.
|
|
117
|
+
* @defaultValue 500
|
|
118
|
+
*/
|
|
119
|
+
overlapMs?: number;
|
|
120
|
+
/**
|
|
121
|
+
* Audio sample rate in Hz.
|
|
122
|
+
* @defaultValue 16000
|
|
123
|
+
*/
|
|
124
|
+
sampleRate?: number;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* A live diarization session.
|
|
128
|
+
*
|
|
129
|
+
* Extends `EventEmitter` so callers can subscribe to `speaker_identified`,
|
|
130
|
+
* `segment_ready`, `error`, and `close` events.
|
|
131
|
+
*/
|
|
132
|
+
export interface IDiarizationSession extends EventEmitter {
|
|
133
|
+
/**
|
|
134
|
+
* Push a raw audio frame into the diarization pipeline.
|
|
135
|
+
*
|
|
136
|
+
* In local mode, frames are accumulated in a sliding window and processed
|
|
137
|
+
* when a full chunk is ready. In provider mode, this is a no-op (speaker
|
|
138
|
+
* labels come from {@link labelTranscript}).
|
|
139
|
+
*/
|
|
140
|
+
pushAudio(frame: AudioFrame): void;
|
|
141
|
+
/**
|
|
142
|
+
* Attach provider-supplied speaker labels to a transcript event and return
|
|
143
|
+
* the resulting {@link DiarizedSegment} (if enough information is present).
|
|
144
|
+
*
|
|
145
|
+
* In provider mode this is the primary data path. In local mode, the engine
|
|
146
|
+
* merges the text with the most recent speaker identification.
|
|
147
|
+
*/
|
|
148
|
+
labelTranscript(event: TranscriptEvent): DiarizedSegment | null;
|
|
149
|
+
/**
|
|
150
|
+
* Pre-register a known speaker voiceprint so the engine can label them by
|
|
151
|
+
* name rather than an auto-generated `Speaker_N` identifier.
|
|
152
|
+
*
|
|
153
|
+
* @param id - Human-readable speaker name or identifier.
|
|
154
|
+
* @param voiceprint - 32-bit float embedding vector representing the
|
|
155
|
+
* speaker's vocal characteristics.
|
|
156
|
+
*/
|
|
157
|
+
enrollSpeaker(id: string, voiceprint: Float32Array): void;
|
|
158
|
+
/**
|
|
159
|
+
* Terminate the session and release all resources.
|
|
160
|
+
*
|
|
161
|
+
* After `close()` is called, no further events will be emitted.
|
|
162
|
+
*/
|
|
163
|
+
close(): void;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Factory interface for creating diarization sessions.
|
|
167
|
+
*/
|
|
168
|
+
export interface IDiarizationEngine {
|
|
169
|
+
/**
|
|
170
|
+
* Create and start a new {@link IDiarizationSession}.
|
|
171
|
+
*
|
|
172
|
+
* @param config - Optional session configuration.
|
|
173
|
+
* @returns A ready-to-use diarization session.
|
|
174
|
+
*/
|
|
175
|
+
startSession(config?: DiarizationConfig): IDiarizationSession;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,uEAAuE;IACvE,OAAO,EAAE,YAAY,CAAC;IACtB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,sDAAsD;IACtD,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IAE/B;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD;;;;;GAKG;AACH,MAAM,WAAW,mBAAoB,SAAQ,YAAY;IACvD;;;;;;OAMG;IACH,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAEnC;;;;;;OAMG;IACH,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,GAAG,IAAI,CAAC;IAEhE;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,GAAG,IAAI,CAAC;IAE1D;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAMD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,YAAY,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,mBAAmB,CAAC;CAC/D"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file types.ts
|
|
3
|
+
* @description Core types for the diarization extension pack.
|
|
4
|
+
*
|
|
5
|
+
* These types define the public contract shared between the engine, session
|
|
6
|
+
* implementations, and calling code. They intentionally avoid importing from
|
|
7
|
+
* `@framers/agentos` so the pack can boot in environments where the core
|
|
8
|
+
* package is not yet available.
|
|
9
|
+
*
|
|
10
|
+
* @module diarization/types
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=types.js.map
|