@framers/agentos 0.13.79 → 0.13.81
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/dist/agents/agency/AgencyMemoryManager.js +1 -1
- package/dist/agents/agency/AgencyMemoryManager.js.map +1 -1
- package/dist/agents/definitions/AgentCore.d.ts.map +1 -1
- package/dist/agents/definitions/AgentCore.js +7 -3
- package/dist/agents/definitions/AgentCore.js.map +1 -1
- package/dist/agents/definitions/AgentPoolAgent.d.ts +1 -0
- package/dist/agents/definitions/AgentPoolAgent.d.ts.map +1 -1
- package/dist/agents/definitions/AgentPoolAgent.js +24 -6
- package/dist/agents/definitions/AgentPoolAgent.js.map +1 -1
- package/dist/api/AgentOS.js +1 -1
- package/dist/api/AgentOS.js.map +1 -1
- package/dist/api/runtime/GMIChunkTransformer.d.ts.map +1 -1
- package/dist/api/runtime/GMIChunkTransformer.js +1 -1
- package/dist/api/runtime/GMIChunkTransformer.js.map +1 -1
- package/dist/api/runtime/strategies/shared.d.ts +7 -4
- package/dist/api/runtime/strategies/shared.d.ts.map +1 -1
- package/dist/api/runtime/strategies/shared.js +12 -4
- package/dist/api/runtime/strategies/shared.js.map +1 -1
- package/dist/api/structured/output/StructuredOutputManager.js +1 -1
- package/dist/api/structured/output/StructuredOutputManager.js.map +1 -1
- package/dist/api/types.d.ts +5 -4
- package/dist/api/types.d.ts.map +1 -1
- package/dist/api/types.js.map +1 -1
- package/dist/cognition/nlp/ai_utilities/LLMUtilityAI.js +7 -7
- package/dist/cognition/nlp/ai_utilities/LLMUtilityAI.js.map +1 -1
- package/dist/cognition/rag/VectorStoreManager.d.ts.map +1 -1
- package/dist/cognition/rag/VectorStoreManager.js +5 -2
- package/dist/cognition/rag/VectorStoreManager.js.map +1 -1
- package/dist/cognition/substrate/GMIManager.d.ts.map +1 -1
- package/dist/cognition/substrate/GMIManager.js +4 -1
- package/dist/cognition/substrate/GMIManager.js.map +1 -1
- package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/AnthropicProvider.js +8 -2
- package/dist/core/llm/providers/implementations/AnthropicProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/GeminiProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/GeminiProvider.js +4 -1
- package/dist/core/llm/providers/implementations/GeminiProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/OllamaProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/OllamaProvider.js +81 -60
- package/dist/core/llm/providers/implementations/OllamaProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/OpenAIProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/OpenAIProvider.js +14 -5
- package/dist/core/llm/providers/implementations/OpenAIProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/OpenRouterProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/OpenRouterProvider.js +19 -6
- package/dist/core/llm/providers/implementations/OpenRouterProvider.js.map +1 -1
- package/dist/io/channels/ChannelRouter.d.ts.map +1 -1
- package/dist/io/channels/ChannelRouter.js +4 -1
- package/dist/io/channels/ChannelRouter.js.map +1 -1
- package/dist/io/channels/meetings/signing.d.ts +19 -18
- package/dist/io/channels/meetings/signing.d.ts.map +1 -1
- package/dist/io/channels/meetings/signing.js +32 -20
- package/dist/io/channels/meetings/signing.js.map +1 -1
- package/dist/io/channels/meetings/stores/sql.d.ts +160 -0
- package/dist/io/channels/meetings/stores/sql.d.ts.map +1 -0
- package/dist/io/channels/meetings/stores/sql.js +497 -0
- package/dist/io/channels/meetings/stores/sql.js.map +1 -0
- package/dist/io/voice-pipeline/LiveKitStreamTransport.d.ts +8 -0
- package/dist/io/voice-pipeline/LiveKitStreamTransport.d.ts.map +1 -1
- package/dist/io/voice-pipeline/LiveKitStreamTransport.js +32 -1
- package/dist/io/voice-pipeline/LiveKitStreamTransport.js.map +1 -1
- package/dist/orchestration/planner/PlanningEngine.js +5 -5
- package/dist/orchestration/planner/PlanningEngine.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
import { CONTENT_EVENT_TYPES } from '../types.js';
|
|
2
|
+
import { DuplicateIdempotencyKeyError, FencedError, nextAttemptAt, OUTBOX_GIVE_UP_MS } from './types.js';
|
|
3
|
+
/** Default prefix for all meeting tables and indexes. */
|
|
4
|
+
export const DEFAULT_TABLE_PREFIX = 'agentos_meeting';
|
|
5
|
+
/** A lower-case letter then at most 37 lower-case letters, digits or underscores: `idx_<prefix>_events_id` stays within 63 bytes. */
|
|
6
|
+
const TABLE_PREFIX = /^[a-z][a-z0-9_]{0,37}$/;
|
|
7
|
+
/** Builds the table names, rejecting a prefix outside the identifier length and character bounds. */
|
|
8
|
+
export function meetingStoreTables(tablePrefix = DEFAULT_TABLE_PREFIX) {
|
|
9
|
+
if (!TABLE_PREFIX.test(tablePrefix))
|
|
10
|
+
throw new Error(`A meeting store's tablePrefix is a lower-case letter and at most 37 more lower-case letters, digits or underscores; got ${JSON.stringify(tablePrefix)}.`);
|
|
11
|
+
return { runs: `${tablePrefix}_runs`, jobs: `${tablePrefix}_jobs`, turns: `${tablePrefix}_turns`, events: `${tablePrefix}_events`, outbox: `${tablePrefix}_outbox`, locks: `${tablePrefix}_run_locks` };
|
|
12
|
+
}
|
|
13
|
+
/** The six tables and their indexes under one prefix. A product copies this text into its migration. */
|
|
14
|
+
export function meetingStoresDdl(tablePrefix = DEFAULT_TABLE_PREFIX) {
|
|
15
|
+
const t = meetingStoreTables(tablePrefix);
|
|
16
|
+
const p = tablePrefix;
|
|
17
|
+
return `
|
|
18
|
+
CREATE TABLE IF NOT EXISTS ${t.runs} (
|
|
19
|
+
run_id TEXT PRIMARY KEY,
|
|
20
|
+
owner_ref TEXT NOT NULL,
|
|
21
|
+
provider_name TEXT NOT NULL,
|
|
22
|
+
platform TEXT NOT NULL,
|
|
23
|
+
state TEXT NOT NULL,
|
|
24
|
+
keep TEXT NOT NULL,
|
|
25
|
+
meeting_url TEXT NOT NULL,
|
|
26
|
+
bot_name TEXT NOT NULL,
|
|
27
|
+
notice_text TEXT NOT NULL,
|
|
28
|
+
notice_version TEXT NOT NULL,
|
|
29
|
+
notice_late_text TEXT NOT NULL,
|
|
30
|
+
stop_phrase TEXT NOT NULL,
|
|
31
|
+
limits_json TEXT NOT NULL,
|
|
32
|
+
idempotency_key TEXT,
|
|
33
|
+
transcriber TEXT,
|
|
34
|
+
requested_at BIGINT NOT NULL,
|
|
35
|
+
join_at BIGINT NOT NULL,
|
|
36
|
+
dispatched_at BIGINT,
|
|
37
|
+
joined_at BIGINT,
|
|
38
|
+
notice_posted_at BIGINT,
|
|
39
|
+
capture_started_at BIGINT,
|
|
40
|
+
left_at BIGINT,
|
|
41
|
+
done_at BIGINT,
|
|
42
|
+
reason TEXT,
|
|
43
|
+
billed_seconds INTEGER NOT NULL DEFAULT 0,
|
|
44
|
+
reservation_id TEXT,
|
|
45
|
+
consent_record_id TEXT,
|
|
46
|
+
dispatch_json TEXT,
|
|
47
|
+
page_seen_at BIGINT,
|
|
48
|
+
last_usage_at BIGINT,
|
|
49
|
+
monitor_seen_at BIGINT,
|
|
50
|
+
participant_count INTEGER,
|
|
51
|
+
leave_commanded_at BIGINT,
|
|
52
|
+
capture_suspended_at BIGINT,
|
|
53
|
+
alone_since BIGINT,
|
|
54
|
+
reported_seconds INTEGER,
|
|
55
|
+
cleanup_pending BOOLEAN NOT NULL DEFAULT FALSE,
|
|
56
|
+
purged_at BIGINT
|
|
57
|
+
);
|
|
58
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_${p}_runs_idem ON ${t.runs} (owner_ref, idempotency_key) WHERE idempotency_key IS NOT NULL;
|
|
59
|
+
CREATE INDEX IF NOT EXISTS idx_${p}_runs_owner ON ${t.runs} (owner_ref, requested_at DESC);
|
|
60
|
+
CREATE INDEX IF NOT EXISTS idx_${p}_runs_state ON ${t.runs} (state);
|
|
61
|
+
CREATE TABLE IF NOT EXISTS ${t.jobs} (
|
|
62
|
+
run_id TEXT PRIMARY KEY,
|
|
63
|
+
dispatch_at BIGINT NOT NULL,
|
|
64
|
+
lease_holder TEXT,
|
|
65
|
+
lease_expires_at BIGINT,
|
|
66
|
+
worker_id TEXT,
|
|
67
|
+
dispatched BOOLEAN NOT NULL DEFAULT FALSE,
|
|
68
|
+
cancelled BOOLEAN NOT NULL DEFAULT FALSE
|
|
69
|
+
);
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_${p}_jobs_due ON ${t.jobs} (dispatch_at) WHERE NOT dispatched AND NOT cancelled;
|
|
71
|
+
CREATE TABLE IF NOT EXISTS ${t.locks} (
|
|
72
|
+
run_id TEXT PRIMARY KEY,
|
|
73
|
+
event_seq INTEGER NOT NULL DEFAULT 0,
|
|
74
|
+
turn_seq INTEGER NOT NULL DEFAULT 0,
|
|
75
|
+
fenced_at BIGINT
|
|
76
|
+
);
|
|
77
|
+
CREATE TABLE IF NOT EXISTS ${t.turns} (
|
|
78
|
+
run_id TEXT NOT NULL,
|
|
79
|
+
seq INTEGER NOT NULL,
|
|
80
|
+
turn_id TEXT NOT NULL,
|
|
81
|
+
at BIGINT NOT NULL,
|
|
82
|
+
text TEXT NOT NULL,
|
|
83
|
+
speaker TEXT,
|
|
84
|
+
start_ms INTEGER,
|
|
85
|
+
end_ms INTEGER,
|
|
86
|
+
PRIMARY KEY (run_id, seq)
|
|
87
|
+
);
|
|
88
|
+
CREATE TABLE IF NOT EXISTS ${t.events} (
|
|
89
|
+
run_id TEXT NOT NULL,
|
|
90
|
+
seq INTEGER NOT NULL,
|
|
91
|
+
event_id TEXT NOT NULL,
|
|
92
|
+
type TEXT NOT NULL,
|
|
93
|
+
at BIGINT NOT NULL,
|
|
94
|
+
data_json TEXT,
|
|
95
|
+
purged BOOLEAN NOT NULL DEFAULT FALSE,
|
|
96
|
+
PRIMARY KEY (run_id, seq)
|
|
97
|
+
);
|
|
98
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_${p}_events_id ON ${t.events} (event_id);
|
|
99
|
+
CREATE TABLE IF NOT EXISTS ${t.outbox} (
|
|
100
|
+
id TEXT PRIMARY KEY,
|
|
101
|
+
run_id TEXT NOT NULL,
|
|
102
|
+
destination_ref TEXT NOT NULL,
|
|
103
|
+
event_id TEXT NOT NULL,
|
|
104
|
+
type TEXT NOT NULL,
|
|
105
|
+
payload TEXT NOT NULL,
|
|
106
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
107
|
+
first_attempt_at BIGINT,
|
|
108
|
+
next_at BIGINT NOT NULL,
|
|
109
|
+
state TEXT NOT NULL,
|
|
110
|
+
purged BOOLEAN NOT NULL DEFAULT FALSE
|
|
111
|
+
);
|
|
112
|
+
CREATE INDEX IF NOT EXISTS idx_${p}_outbox_due ON ${t.outbox} (next_at) WHERE state = 'pending';
|
|
113
|
+
CREATE INDEX IF NOT EXISTS idx_${p}_outbox_run ON ${t.outbox} (run_id);
|
|
114
|
+
`;
|
|
115
|
+
}
|
|
116
|
+
/** Schema under {@link DEFAULT_TABLE_PREFIX}; apply it before constructing the stores. */
|
|
117
|
+
export const MEETING_STORES_DDL = meetingStoresDdl();
|
|
118
|
+
/** These stores are Postgres stores: `FOR UPDATE SKIP LOCKED`, `ON CONFLICT ... RETURNING` and the row lock an upsert takes are what they rest on. */
|
|
119
|
+
function checkPostgres(db, what) {
|
|
120
|
+
if (!/postgres/i.test(db.kind))
|
|
121
|
+
throw new Error(`${what} is a Postgres store; "${db.kind}" is not Postgres.`);
|
|
122
|
+
const caps = db.capabilities;
|
|
123
|
+
if (!(caps.has('transactions') && caps.has('persistence') && caps.has('concurrent'))) {
|
|
124
|
+
throw new Error(`${what} needs a store several processes share (transactions, persistence and concurrent access); "${db.kind}" lacks one.`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const num = (v) => (v === null || v === undefined ? undefined : typeof v === 'number' ? v : Number(v));
|
|
128
|
+
const bool = (v) => v === true || v === 1 || v === '1' || v === 't' || v === 'true';
|
|
129
|
+
/**
|
|
130
|
+
* Takes the run's anchor row for the rest of the transaction (an upsert locks the row it touches, so every content write
|
|
131
|
+
* of one run runs after the one before it) and answers the fence. The row is made on first use.
|
|
132
|
+
*/
|
|
133
|
+
async function lockRun(trx, locks, runId) {
|
|
134
|
+
const row = await trx.get(`INSERT INTO ${locks} (run_id) VALUES (?) ON CONFLICT (run_id) DO UPDATE SET run_id = EXCLUDED.run_id RETURNING fenced_at, event_seq`, [runId]);
|
|
135
|
+
return { fencedAt: num(row?.fenced_at), eventSeq: num(row?.event_seq) ?? 0 };
|
|
136
|
+
}
|
|
137
|
+
async function fenceRun(db, locks, runId, now) {
|
|
138
|
+
await db.run(`INSERT INTO ${locks} (run_id, fenced_at) VALUES (?, ?) ON CONFLICT (run_id) DO UPDATE SET fenced_at = COALESCE(${locks}.fenced_at, EXCLUDED.fenced_at)`, [runId, now]);
|
|
139
|
+
}
|
|
140
|
+
/** Durable run records with sealed URLs and expected-state updates under the run anchor. */
|
|
141
|
+
export class SqlRunStore {
|
|
142
|
+
/** Checks the adapter capabilities and prefix; the caller applies the exported DDL. */
|
|
143
|
+
constructor(opts) {
|
|
144
|
+
this.opts = opts;
|
|
145
|
+
checkPostgres(opts.db, 'SqlRunStore');
|
|
146
|
+
this.t = meetingStoreTables(opts.tablePrefix);
|
|
147
|
+
}
|
|
148
|
+
/** Serialises no options, database or box; persistence uses only the explicit row fields. */
|
|
149
|
+
toJSON() {
|
|
150
|
+
return '[SqlRunStore redacted]';
|
|
151
|
+
}
|
|
152
|
+
row(run) {
|
|
153
|
+
return [run.runId, run.ownerRef, run.providerName, run.platform, run.state, run.keep, run.meetingUrl === '' ? '' : this.opts.box.seal(run.meetingUrl, run.runId), run.botName, run.notice.text, run.notice.version, run.notice.lateArrivalText, run.stopPhrase, JSON.stringify(run.limits), run.idempotencyKey ?? null, run.transcriber ?? null, run.requestedAt, run.joinAt, run.dispatchedAt ?? null, run.joinedAt ?? null, run.noticePostedAt ?? null, run.captureStartedAt ?? null, run.leftAt ?? null, run.doneAt ?? null, run.reason ?? null, run.billedSeconds, run.reservationId ?? null, run.consentRecordId ?? null, run.dispatch ? JSON.stringify(run.dispatch) : null, run.pageSeenAt ?? null, run.lastUsageAt ?? null, run.monitorSeenAt ?? null, run.participantCount ?? null, run.leaveCommandedAt ?? null, run.captureSuspendedAt ?? null, run.aloneSince ?? null, run.reportedSeconds ?? null, run.cleanupPending ?? false, run.purgedAt ?? null];
|
|
154
|
+
}
|
|
155
|
+
fromRow(r) {
|
|
156
|
+
const sealed = String(r.meeting_url ?? '');
|
|
157
|
+
const run = {
|
|
158
|
+
runId: String(r.run_id), ownerRef: String(r.owner_ref), providerName: String(r.provider_name), platform: r.platform, state: r.state, keep: r.keep,
|
|
159
|
+
meetingUrl: sealed === '' ? '' : this.opts.box.open(sealed, String(r.run_id)), botName: String(r.bot_name), notice: { text: String(r.notice_text), version: String(r.notice_version), lateArrivalText: String(r.notice_late_text) }, stopPhrase: String(r.stop_phrase),
|
|
160
|
+
limits: JSON.parse(String(r.limits_json)), requestedAt: num(r.requested_at), joinAt: num(r.join_at), billedSeconds: num(r.billed_seconds) ?? 0,
|
|
161
|
+
};
|
|
162
|
+
const opt = (key, value) => { if (value !== undefined && value !== null)
|
|
163
|
+
run[key] = value; };
|
|
164
|
+
opt('idempotencyKey', r.idempotency_key);
|
|
165
|
+
opt('transcriber', r.transcriber);
|
|
166
|
+
opt('dispatchedAt', num(r.dispatched_at));
|
|
167
|
+
opt('joinedAt', num(r.joined_at));
|
|
168
|
+
opt('noticePostedAt', num(r.notice_posted_at));
|
|
169
|
+
opt('captureStartedAt', num(r.capture_started_at));
|
|
170
|
+
opt('leftAt', num(r.left_at));
|
|
171
|
+
opt('doneAt', num(r.done_at));
|
|
172
|
+
opt('reason', r.reason);
|
|
173
|
+
opt('reservationId', r.reservation_id);
|
|
174
|
+
opt('consentRecordId', r.consent_record_id);
|
|
175
|
+
opt('dispatch', r.dispatch_json ? JSON.parse(String(r.dispatch_json)) : undefined);
|
|
176
|
+
opt('pageSeenAt', num(r.page_seen_at));
|
|
177
|
+
opt('lastUsageAt', num(r.last_usage_at));
|
|
178
|
+
opt('monitorSeenAt', num(r.monitor_seen_at));
|
|
179
|
+
opt('participantCount', num(r.participant_count));
|
|
180
|
+
opt('leaveCommandedAt', num(r.leave_commanded_at));
|
|
181
|
+
opt('captureSuspendedAt', num(r.capture_suspended_at));
|
|
182
|
+
opt('aloneSince', num(r.alone_since));
|
|
183
|
+
opt('reportedSeconds', num(r.reported_seconds));
|
|
184
|
+
opt('purgedAt', num(r.purged_at));
|
|
185
|
+
if (bool(r.cleanup_pending))
|
|
186
|
+
run.cleanupPending = true;
|
|
187
|
+
return run;
|
|
188
|
+
}
|
|
189
|
+
/** Inserts a run, mapping an owner's repeated idempotency key to the public conflict error. */
|
|
190
|
+
async insert(run) {
|
|
191
|
+
const marks = SqlRunStore.COLUMNS.split(', ').map(() => '?').join(', ');
|
|
192
|
+
try {
|
|
193
|
+
await this.opts.db.transaction(async (trx) => {
|
|
194
|
+
await lockRun(trx, this.t.locks, run.runId);
|
|
195
|
+
await trx.run(`INSERT INTO ${this.t.runs} (${SqlRunStore.COLUMNS}) VALUES (${marks})`, this.row(run));
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
const conflict = err;
|
|
200
|
+
const index = `idx_${this.opts.tablePrefix ?? DEFAULT_TABLE_PREFIX}_runs_idem`;
|
|
201
|
+
if (conflict.code === '23505' && conflict.constraint === index && run.idempotencyKey !== undefined) {
|
|
202
|
+
throw new DuplicateIdempotencyKeyError(run.ownerRef, run.idempotencyKey);
|
|
203
|
+
}
|
|
204
|
+
throw err;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/** Reads a run, opening its URL with its run id as authenticated context. */
|
|
208
|
+
async get(runId) {
|
|
209
|
+
const r = await this.opts.db.get(`SELECT * FROM ${this.t.runs} WHERE run_id = ?`, [runId]);
|
|
210
|
+
return r ? this.fromRow(r) : undefined;
|
|
211
|
+
}
|
|
212
|
+
/** Re-reads and patches under the anchor, setting the content fence atomically on entry to purging. */
|
|
213
|
+
async update(runId, patch, expectState) {
|
|
214
|
+
return this.opts.db.transaction(async (trx) => {
|
|
215
|
+
await lockRun(trx, this.t.locks, runId);
|
|
216
|
+
const r = await trx.get(`SELECT * FROM ${this.t.runs} WHERE run_id = ? FOR UPDATE`, [runId]);
|
|
217
|
+
if (!r)
|
|
218
|
+
return undefined;
|
|
219
|
+
const current = this.fromRow(r);
|
|
220
|
+
if (expectState !== undefined) {
|
|
221
|
+
const allowed = Array.isArray(expectState) ? expectState : [expectState];
|
|
222
|
+
if (!allowed.includes(current.state))
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
if (patch.state === 'purging') {
|
|
226
|
+
await trx.run(`UPDATE ${this.t.locks} SET fenced_at = COALESCE(fenced_at, ?) WHERE run_id = ?`, [Date.now(), runId]);
|
|
227
|
+
}
|
|
228
|
+
const next = { ...current, ...patch };
|
|
229
|
+
const row = this.row(next);
|
|
230
|
+
const sets = SqlRunStore.COLUMNS.split(', ').map((c) => `${c} = ?`).join(', ');
|
|
231
|
+
await trx.run(`UPDATE ${this.t.runs} SET ${sets} WHERE run_id = ?`, [...row, runId]);
|
|
232
|
+
return next;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/** Rewrites an existing row under the anchor, including its content-free form after a purge. */
|
|
236
|
+
async replace(run) {
|
|
237
|
+
const sets = SqlRunStore.COLUMNS.split(', ').map((c) => `${c} = ?`).join(', ');
|
|
238
|
+
await this.opts.db.transaction(async (trx) => {
|
|
239
|
+
await lockRun(trx, this.t.locks, run.runId);
|
|
240
|
+
await trx.run(`UPDATE ${this.t.runs} SET ${sets} WHERE run_id = ?`, [...this.row(run), run.runId]);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
/** Lists matching runs by requested time descending, then run id ascending. */
|
|
244
|
+
async list(filter) {
|
|
245
|
+
const where = [];
|
|
246
|
+
const params = [];
|
|
247
|
+
if (filter.ownerRef !== undefined) {
|
|
248
|
+
where.push('owner_ref = ?');
|
|
249
|
+
params.push(filter.ownerRef);
|
|
250
|
+
}
|
|
251
|
+
if (filter.states?.length) {
|
|
252
|
+
where.push(`state IN (${filter.states.map(() => '?').join(', ')})`);
|
|
253
|
+
params.push(...filter.states);
|
|
254
|
+
}
|
|
255
|
+
if (filter.since !== undefined) {
|
|
256
|
+
where.push('requested_at >= ?');
|
|
257
|
+
params.push(filter.since);
|
|
258
|
+
}
|
|
259
|
+
const rows = await this.opts.db.all(`SELECT * FROM ${this.t.runs}${where.length ? ` WHERE ${where.join(' AND ')}` : ''} ORDER BY requested_at DESC, run_id ASC LIMIT ?`, [...params, filter.limit ?? 500]);
|
|
260
|
+
return rows.map((r) => this.fromRow(r));
|
|
261
|
+
}
|
|
262
|
+
/** Finds the owner's run for a previously used idempotency key. */
|
|
263
|
+
async findByIdempotencyKey(ownerRef, key) {
|
|
264
|
+
const r = await this.opts.db.get(`SELECT * FROM ${this.t.runs} WHERE owner_ref = ? AND idempotency_key = ?`, [ownerRef, key]);
|
|
265
|
+
return r ? this.fromRow(r) : undefined;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
SqlRunStore.COLUMNS = 'run_id, owner_ref, provider_name, platform, state, keep, meeting_url, bot_name, notice_text, notice_version, notice_late_text, stop_phrase, limits_json, idempotency_key, transcriber, requested_at, join_at, dispatched_at, joined_at, notice_posted_at, capture_started_at, left_at, done_at, reason, billed_seconds, reservation_id, consent_record_id, dispatch_json, page_seen_at, last_usage_at, monitor_seen_at, participant_count, leave_commanded_at, capture_suspended_at, alone_since, reported_seconds, cleanup_pending, purged_at';
|
|
269
|
+
/** Postgres dispatch jobs with atomic leases and holder-checked writes. */
|
|
270
|
+
export class SqlJobStore {
|
|
271
|
+
/** Checks the adapter capabilities and prefix without creating tables. */
|
|
272
|
+
constructor(opts) {
|
|
273
|
+
this.opts = opts;
|
|
274
|
+
checkPostgres(opts.db, 'SqlJobStore');
|
|
275
|
+
this.t = meetingStoreTables(opts.tablePrefix);
|
|
276
|
+
}
|
|
277
|
+
fromRow(r) {
|
|
278
|
+
return { runId: String(r.run_id), dispatchAt: num(r.dispatch_at), leaseHolder: r.lease_holder ?? undefined, leaseExpiresAt: num(r.lease_expires_at), workerId: r.worker_id ?? undefined, dispatched: bool(r.dispatched), cancelled: bool(r.cancelled) };
|
|
279
|
+
}
|
|
280
|
+
/** Schedules a job; an existing job keeps its lease, dispatch and cancellation fields. */
|
|
281
|
+
async schedule(job) {
|
|
282
|
+
await this.opts.db.run(`INSERT INTO ${this.t.jobs} (run_id, dispatch_at) VALUES (?, ?) ON CONFLICT (run_id) DO UPDATE SET dispatch_at = EXCLUDED.dispatch_at`, [job.runId, job.dispatchAt]);
|
|
283
|
+
}
|
|
284
|
+
/** One statement: the row is locked, skipped by any other taker, and leased in the same UPDATE. */
|
|
285
|
+
async lease(holder, now, ttlMs) {
|
|
286
|
+
const r = await this.opts.db.get(`UPDATE ${this.t.jobs} SET lease_holder = ?, lease_expires_at = ?
|
|
287
|
+
WHERE run_id = (
|
|
288
|
+
SELECT run_id FROM ${this.t.jobs}
|
|
289
|
+
WHERE NOT dispatched AND NOT cancelled AND dispatch_at <= ? AND (lease_expires_at IS NULL OR lease_expires_at <= ?)
|
|
290
|
+
ORDER BY dispatch_at LIMIT 1 FOR UPDATE SKIP LOCKED
|
|
291
|
+
) RETURNING *`, [holder, now + ttlMs, now, now]);
|
|
292
|
+
return r ? this.fromRow(r) : undefined;
|
|
293
|
+
}
|
|
294
|
+
/** Extends an unexpired lease only for its current holder. */
|
|
295
|
+
async renew(runId, holder, now, ttlMs) {
|
|
296
|
+
const res = await this.opts.db.run(`UPDATE ${this.t.jobs} SET lease_expires_at = ? WHERE run_id = ? AND lease_holder = ? AND lease_expires_at > ?`, [now + ttlMs, runId, holder, now]);
|
|
297
|
+
return res.changes > 0;
|
|
298
|
+
}
|
|
299
|
+
/** Records the holder's dispatch and reports a cancellation that arrived during it. */
|
|
300
|
+
async markDispatched(runId, holder, workerId) {
|
|
301
|
+
return this.opts.db.transaction(async (trx) => {
|
|
302
|
+
const job = await trx.get(`SELECT lease_holder, cancelled FROM ${this.t.jobs} WHERE run_id = ? FOR UPDATE`, [runId]);
|
|
303
|
+
if (!job)
|
|
304
|
+
return { recorded: false, cancelled: false };
|
|
305
|
+
if (job.lease_holder !== holder)
|
|
306
|
+
return { recorded: false, cancelled: bool(job.cancelled) };
|
|
307
|
+
await trx.run(`UPDATE ${this.t.jobs} SET dispatched = TRUE, worker_id = ? WHERE run_id = ? AND lease_holder = ?`, [workerId ?? null, runId, holder]);
|
|
308
|
+
return { recorded: true, cancelled: bool(job.cancelled) };
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
/** Releases the holder's lease and moves the job's due time to its retry. */
|
|
312
|
+
async release(runId, holder, retryAt) {
|
|
313
|
+
const result = await this.opts.db.run(`UPDATE ${this.t.jobs} SET lease_holder = NULL, lease_expires_at = NULL, dispatch_at = ? WHERE run_id = ? AND lease_holder = ?`, [retryAt, runId, holder]);
|
|
314
|
+
return result.changes > 0;
|
|
315
|
+
}
|
|
316
|
+
/** Cancels a pending job or reports that the caller must leave an already dispatched bot. */
|
|
317
|
+
async cancel(runId) {
|
|
318
|
+
return this.opts.db.transaction(async (trx) => {
|
|
319
|
+
const r = await trx.get(`SELECT dispatched FROM ${this.t.jobs} WHERE run_id = ? FOR UPDATE`, [runId]);
|
|
320
|
+
if (!r)
|
|
321
|
+
return 'missing';
|
|
322
|
+
if (bool(r.dispatched))
|
|
323
|
+
return 'already_dispatched';
|
|
324
|
+
await trx.run(`UPDATE ${this.t.jobs} SET cancelled = TRUE WHERE run_id = ?`, [runId]);
|
|
325
|
+
return 'cancelled';
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
/** Reads one dispatch job. */
|
|
329
|
+
async get(runId) {
|
|
330
|
+
const r = await this.opts.db.get(`SELECT * FROM ${this.t.jobs} WHERE run_id = ?`, [runId]);
|
|
331
|
+
return r ? this.fromRow(r) : undefined;
|
|
332
|
+
}
|
|
333
|
+
/** Lists the dispatched jobs reconciliation compares with provider usage. */
|
|
334
|
+
async listDispatched() {
|
|
335
|
+
return (await this.opts.db.all(`SELECT * FROM ${this.t.jobs} WHERE dispatched`)).map((r) => this.fromRow(r));
|
|
336
|
+
}
|
|
337
|
+
/** Removes a run's job. */
|
|
338
|
+
async remove(runId) {
|
|
339
|
+
await this.opts.db.run(`DELETE FROM ${this.t.jobs} WHERE run_id = ?`, [runId]);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/** Durable transcript turns, allocated and written under the same anchor as the content fence. */
|
|
343
|
+
export class SqlTranscriptStore {
|
|
344
|
+
/** Checks the adapter capabilities and prefix without creating tables. */
|
|
345
|
+
constructor(opts) {
|
|
346
|
+
this.opts = opts;
|
|
347
|
+
checkPostgres(opts.db, 'SqlTranscriptStore');
|
|
348
|
+
this.t = meetingStoreTables(opts.tablePrefix);
|
|
349
|
+
}
|
|
350
|
+
/** The anchor row is locked first, so an append and a fence of one run never interleave: a fence that commits first is seen, a fence that waits sees the turn and purges it. */
|
|
351
|
+
async append(turn) {
|
|
352
|
+
await this.opts.db.transaction(async (trx) => {
|
|
353
|
+
const { fencedAt } = await lockRun(trx, this.t.locks, turn.runId);
|
|
354
|
+
if (fencedAt !== undefined)
|
|
355
|
+
throw new FencedError(turn.runId);
|
|
356
|
+
await trx.run(`INSERT INTO ${this.t.turns} (run_id, seq, turn_id, at, text, speaker, start_ms, end_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT (run_id, seq) DO NOTHING`, [turn.runId, turn.seq, turn.turnId, turn.at, turn.text, turn.speaker ?? null, turn.startMs ?? null, turn.endMs ?? null]);
|
|
357
|
+
await trx.run(`UPDATE ${this.t.locks} SET turn_seq = GREATEST(turn_seq, ?) WHERE run_id = ?`, [turn.seq, turn.runId]);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
/** Allocates the next run sequence and stores the turn atomically, rejecting fenced runs. */
|
|
361
|
+
async appendNext(input) {
|
|
362
|
+
return this.opts.db.transaction(async (trx) => {
|
|
363
|
+
const { fencedAt } = await lockRun(trx, this.t.locks, input.runId);
|
|
364
|
+
if (fencedAt !== undefined)
|
|
365
|
+
throw new FencedError(input.runId);
|
|
366
|
+
const row = await trx.get(`UPDATE ${this.t.locks} SET turn_seq = GREATEST(turn_seq, COALESCE((SELECT MAX(seq) FROM ${this.t.turns} WHERE run_id = ?), 0)) + 1 WHERE run_id = ? RETURNING turn_seq`, [input.runId, input.runId]);
|
|
367
|
+
const seq = num(row?.turn_seq);
|
|
368
|
+
const turn = { ...input, seq, turnId: `${input.runId}:${seq}` };
|
|
369
|
+
await trx.run(`INSERT INTO ${this.t.turns} (run_id, seq, turn_id, at, text, speaker, start_ms, end_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [turn.runId, seq, turn.turnId, turn.at, turn.text, turn.speaker ?? null, turn.startMs ?? null, turn.endMs ?? null]);
|
|
370
|
+
return turn;
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
/** Reads turns after the cursor in sequence order. */
|
|
374
|
+
async read(runId, fromSeq, limit = 500) {
|
|
375
|
+
const rows = await this.opts.db.all(`SELECT * FROM ${this.t.turns} WHERE run_id = ? AND seq > ? ORDER BY seq LIMIT ?`, [runId, fromSeq, limit]);
|
|
376
|
+
return rows.map((r) => ({ runId: String(r.run_id), seq: num(r.seq), turnId: String(r.turn_id), at: num(r.at), text: String(r.text), speaker: r.speaker ?? undefined, startMs: num(r.start_ms), endMs: num(r.end_ms) }));
|
|
377
|
+
}
|
|
378
|
+
/** Fences the run against further transcript and content writes. */
|
|
379
|
+
async fence(runId) {
|
|
380
|
+
await fenceRun(this.opts.db, this.t.locks, runId, Date.now());
|
|
381
|
+
}
|
|
382
|
+
/** Reports whether the run's durable fence is set. */
|
|
383
|
+
async isFenced(runId) {
|
|
384
|
+
const r = await this.opts.db.get(`SELECT fenced_at FROM ${this.t.locks} WHERE run_id = ?`, [runId]);
|
|
385
|
+
return num(r?.fenced_at) !== undefined;
|
|
386
|
+
}
|
|
387
|
+
/** Removes turns under the anchor, retaining its fence and sequence counters. */
|
|
388
|
+
async purge(runId) {
|
|
389
|
+
await this.opts.db.transaction(async (trx) => {
|
|
390
|
+
await lockRun(trx, this.t.locks, runId);
|
|
391
|
+
await trx.run(`DELETE FROM ${this.t.turns} WHERE run_id = ?`, [runId]);
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
/** Durable per-run event sequences with idempotent event ids and payload fencing. */
|
|
396
|
+
export class SqlEventStore {
|
|
397
|
+
/** Checks the adapter capabilities and prefix without creating tables. */
|
|
398
|
+
constructor(opts) {
|
|
399
|
+
this.opts = opts;
|
|
400
|
+
checkPostgres(opts.db, 'SqlEventStore');
|
|
401
|
+
this.t = meetingStoreTables(opts.tablePrefix);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* One transaction: the run's anchor row is locked (so sequence numbers of one run are handed out one at a time and the
|
|
405
|
+
* fence is read under the same lock), a repeated event id answers its existing sequence, the counter advances, the row
|
|
406
|
+
* is written; behind the fence a content event is written without its payload.
|
|
407
|
+
*/
|
|
408
|
+
async append(event) {
|
|
409
|
+
return this.opts.db.transaction(async (trx) => {
|
|
410
|
+
const { fencedAt } = await lockRun(trx, this.t.locks, event.runId);
|
|
411
|
+
const existing = await trx.get(`SELECT seq FROM ${this.t.events} WHERE event_id = ?`, [event.eventId]);
|
|
412
|
+
if (existing)
|
|
413
|
+
return { inserted: false, seq: num(existing.seq) };
|
|
414
|
+
const next = await trx.get(`UPDATE ${this.t.locks} SET event_seq = event_seq + 1 WHERE run_id = ? RETURNING event_seq`, [event.runId]);
|
|
415
|
+
const seq = num(next?.event_seq);
|
|
416
|
+
const behindFence = fencedAt !== undefined && CONTENT_EVENT_TYPES.has(event.type);
|
|
417
|
+
await trx.run(`INSERT INTO ${this.t.events} (run_id, seq, event_id, type, at, data_json, purged) VALUES (?, ?, ?, ?, ?, ?, ?)`, [event.runId, seq, event.eventId, event.type, event.at, behindFence || event.data === undefined ? null : JSON.stringify(event.data), behindFence]);
|
|
418
|
+
return { inserted: true, seq };
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
/** Reads events after the cursor in sequence order. */
|
|
422
|
+
async read(runId, fromSeq, limit = 500) {
|
|
423
|
+
const rows = await this.opts.db.all(`SELECT * FROM ${this.t.events} WHERE run_id = ? AND seq > ? ORDER BY seq LIMIT ?`, [runId, fromSeq, limit]);
|
|
424
|
+
return rows.map((r) => ({ runId: String(r.run_id), seq: num(r.seq), eventId: String(r.event_id), type: r.type, at: num(r.at), ...(r.data_json ? { data: JSON.parse(String(r.data_json)) } : {}), ...(bool(r.purged) ? { purged: true } : {}) }));
|
|
425
|
+
}
|
|
426
|
+
/** Prevents further content payloads from being stored for the run. */
|
|
427
|
+
async fence(runId) {
|
|
428
|
+
await fenceRun(this.opts.db, this.t.locks, runId, Date.now());
|
|
429
|
+
}
|
|
430
|
+
/** Scrubs content payloads under the anchor, preserving event ids, types, times and sequences. */
|
|
431
|
+
async purgePayloads(runId) {
|
|
432
|
+
const types = [...CONTENT_EVENT_TYPES];
|
|
433
|
+
await this.opts.db.transaction(async (trx) => {
|
|
434
|
+
await lockRun(trx, this.t.locks, runId);
|
|
435
|
+
await trx.run(`UPDATE ${this.t.events} SET data_json = NULL, purged = TRUE WHERE run_id = ? AND type IN (${types.map(() => '?').join(', ')})`, [runId, ...types]);
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/** Durable outbound deliveries with retry backoff, manual replay and content scrubbing. */
|
|
440
|
+
export class SqlOutbox {
|
|
441
|
+
/** Checks the adapter capabilities and prefix without creating tables. */
|
|
442
|
+
constructor(opts) {
|
|
443
|
+
this.opts = opts;
|
|
444
|
+
checkPostgres(opts.db, 'SqlOutbox');
|
|
445
|
+
this.t = meetingStoreTables(opts.tablePrefix);
|
|
446
|
+
}
|
|
447
|
+
fromRow(r) {
|
|
448
|
+
return { id: String(r.id), runId: String(r.run_id), destinationRef: String(r.destination_ref), eventId: String(r.event_id), type: r.type, payload: String(r.payload), attempts: num(r.attempts) ?? 0, firstAttemptAt: num(r.first_attempt_at), nextAt: num(r.next_at), state: r.state, purged: bool(r.purged) };
|
|
449
|
+
}
|
|
450
|
+
/** Enqueues once per delivery id, refusing new content behind the run's fence. */
|
|
451
|
+
async enqueue(d, now) {
|
|
452
|
+
await this.opts.db.transaction(async (trx) => {
|
|
453
|
+
const { fencedAt } = await lockRun(trx, this.t.locks, d.runId);
|
|
454
|
+
if (fencedAt !== undefined && CONTENT_EVENT_TYPES.has(d.type))
|
|
455
|
+
return;
|
|
456
|
+
await trx.run(`INSERT INTO ${this.t.outbox} (id, run_id, destination_ref, event_id, type, payload, next_at, state) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending') ON CONFLICT (id) DO NOTHING`, [d.id, d.runId, d.destinationRef, d.eventId, d.type, d.payload, now]);
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
/** Lists pending deliveries due at now, ordered by due time and id. */
|
|
460
|
+
async due(now, limit = 100) {
|
|
461
|
+
return (await this.opts.db.all(`SELECT * FROM ${this.t.outbox} WHERE state = 'pending' AND next_at <= ? ORDER BY next_at, id LIMIT ?`, [now, limit])).map((r) => this.fromRow(r));
|
|
462
|
+
}
|
|
463
|
+
/** Marks a delivery accepted by its destination. */
|
|
464
|
+
async markDelivered(id) {
|
|
465
|
+
await this.opts.db.run(`UPDATE ${this.t.outbox} SET state = 'delivered' WHERE id = ?`, [id]);
|
|
466
|
+
}
|
|
467
|
+
/** Advances retry backoff, giving up a day after the first failed attempt. */
|
|
468
|
+
async markFailed(id, now) {
|
|
469
|
+
await this.opts.db.transaction(async (trx) => {
|
|
470
|
+
const r = await trx.get(`SELECT attempts, first_attempt_at FROM ${this.t.outbox} WHERE id = ? FOR UPDATE`, [id]);
|
|
471
|
+
if (!r)
|
|
472
|
+
return;
|
|
473
|
+
const attempts = (num(r.attempts) ?? 0) + 1;
|
|
474
|
+
const first = num(r.first_attempt_at) ?? now;
|
|
475
|
+
const dead = now - first >= OUTBOX_GIVE_UP_MS;
|
|
476
|
+
await trx.run(`UPDATE ${this.t.outbox} SET attempts = ?, first_attempt_at = ?, next_at = ?, state = ? WHERE id = ?`, [attempts, first, dead ? now : nextAttemptAt(attempts, now), dead ? 'dead' : 'pending', id]);
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
/** Resets attempts and makes a delivery due now without restoring any purged payload. */
|
|
480
|
+
async replay(id, now) {
|
|
481
|
+
await this.opts.db.run(`UPDATE ${this.t.outbox} SET state = 'pending', attempts = 0, first_attempt_at = NULL, next_at = ? WHERE id = ?`, [now, id]);
|
|
482
|
+
}
|
|
483
|
+
/** Fences new content and scrubs content deliveries, including delivered rows; content-free deliveries keep their type and payload. */
|
|
484
|
+
async purgeContent(runId) {
|
|
485
|
+
await this.opts.db.transaction(async (trx) => {
|
|
486
|
+
await lockRun(trx, this.t.locks, runId);
|
|
487
|
+
await trx.run(`UPDATE ${this.t.locks} SET fenced_at = COALESCE(fenced_at, ?) WHERE run_id = ?`, [Date.now(), runId]);
|
|
488
|
+
const types = [...CONTENT_EVENT_TYPES];
|
|
489
|
+
await trx.run(`UPDATE ${this.t.outbox} SET payload = '', type = 'bot:purged', purged = TRUE WHERE run_id = ? AND type IN (${types.map(() => '?').join(', ')})`, [runId, ...types]);
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
/** Lists all deliveries of a run, including delivered and dead ones. */
|
|
493
|
+
async listByRun(runId) {
|
|
494
|
+
return (await this.opts.db.all(`SELECT * FROM ${this.t.outbox} WHERE run_id = ? ORDER BY next_at, id`, [runId])).map((r) => this.fromRow(r));
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
//# sourceMappingURL=sql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.js","sourceRoot":"","sources":["../../../../../src/io/channels/meetings/stores/sql.ts"],"names":[],"mappings":"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"}
|
|
@@ -55,6 +55,8 @@ export interface LiveKitStreamTransportOptions {
|
|
|
55
55
|
* least one sample at `sampleRate`; rtc-node's default when omitted.
|
|
56
56
|
*/
|
|
57
57
|
frameSizeMs?: number;
|
|
58
|
+
/** While the consumer has asked for a pause, frames are held up to this much audio; beyond it the oldest are dropped and a `gap` is emitted on resume. Default 2000. */
|
|
59
|
+
bufferMs?: number;
|
|
58
60
|
/** The `@livekit/rtc-node` module the host imports; imported on first use when omitted. */
|
|
59
61
|
rtc?: LiveKitRtcModule;
|
|
60
62
|
}
|
|
@@ -67,6 +69,7 @@ export interface LiveKitStreamTransportOptions {
|
|
|
67
69
|
* | Event | Payload | Description |
|
|
68
70
|
* |-------------|---------------------------|-----------------------------------------------|
|
|
69
71
|
* | `'audio'` | `AudioFrame` | The participant's audio, mono Float32. |
|
|
72
|
+
* | `'gap'` | `{ droppedMs: number, reason: 'paused' }` | Audio dropped beyond the paused buffer, reported on resume before held frames. |
|
|
70
73
|
* | `'message'` | {@link ClientTextMessage} | A JSON message from the participant on the topic. |
|
|
71
74
|
* | `'close'` | *(none)* | The transport closed (or the room disconnected). |
|
|
72
75
|
* | `'error'` | `Error` | A message that is not JSON, a text stream of the participant's that fails while it is read, or a failure to read audio (the peer missing among them). |
|
|
@@ -91,6 +94,11 @@ export declare class LiveKitStreamTransport extends EventEmitter implements IStr
|
|
|
91
94
|
private _state;
|
|
92
95
|
private readonly topic;
|
|
93
96
|
private readonly source;
|
|
97
|
+
private paused;
|
|
98
|
+
private readonly held;
|
|
99
|
+
private heldMs;
|
|
100
|
+
private droppedMs;
|
|
101
|
+
private readonly bufferMs;
|
|
94
102
|
/** The participant's text streams being read; {@link close} closes them. */
|
|
95
103
|
private readonly readers;
|
|
96
104
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveKitStreamTransport.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/LiveKitStreamTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"LiveKitStreamTransport.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/LiveKitStreamTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAEV,gBAAgB,EAChB,iBAAiB,EAEjB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAEtB,MAAM,sCAAsC,CAAC;AAE9C,6EAA6E;AAC7E,eAAO,MAAM,+BAA+B,kBAAkB,CAAC;AAE/D,iDAAiD;AACjD,MAAM,WAAW,6BAA6B;IAC5C,2DAA2D;IAC3D,IAAI,EAAE,eAAe,CAAC;IACtB,+DAA+D;IAC/D,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wKAAwK;IACxK,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,sBAAuB,SAAQ,YAAa,YAAW,gBAAgB;IAmBtE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAlBpC,QAAQ,CAAC,EAAE,sDAAgB;IAC3B,OAAO,CAAC,MAAM,CAAwD;IACtE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoB;IACzC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;IAElE;;;;;OAKG;gBAC0B,OAAO,EAAE,6BAA6B;IA6BnE,IAAI,KAAK,IAAI,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAExD;IAED;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnD;;;;OAIG;IACG,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5D;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAW7C,yEAAyE;YAC3D,IAAI;IAwBlB,OAAO,CAAC,QAAQ,CAAC,MAAM,CA2BrB;IAEF;;;OAGG;IACH,OAAO,CAAC,aAAa;CAOtB"}
|
|
@@ -56,6 +56,7 @@ function closeTextReader(reader) {
|
|
|
56
56
|
* | Event | Payload | Description |
|
|
57
57
|
* |-------------|---------------------------|-----------------------------------------------|
|
|
58
58
|
* | `'audio'` | `AudioFrame` | The participant's audio, mono Float32. |
|
|
59
|
+
* | `'gap'` | `{ droppedMs: number, reason: 'paused' }` | Audio dropped beyond the paused buffer, reported on resume before held frames. |
|
|
59
60
|
* | `'message'` | {@link ClientTextMessage} | A JSON message from the participant on the topic. |
|
|
60
61
|
* | `'close'` | *(none)* | The transport closed (or the room disconnected). |
|
|
61
62
|
* | `'error'` | `Error` | A message that is not JSON, a text stream of the participant's that fails while it is read, or a failure to read audio (the peer missing among them). |
|
|
@@ -86,6 +87,10 @@ export class LiveKitStreamTransport extends EventEmitter {
|
|
|
86
87
|
this.options = options;
|
|
87
88
|
this.id = randomUUID();
|
|
88
89
|
this._state = 'open';
|
|
90
|
+
this.paused = false;
|
|
91
|
+
this.held = [];
|
|
92
|
+
this.heldMs = 0;
|
|
93
|
+
this.droppedMs = 0;
|
|
89
94
|
/** The participant's text streams being read; {@link close} closes them. */
|
|
90
95
|
this.readers = new Set();
|
|
91
96
|
this.onText = (reader, participant) => {
|
|
@@ -118,6 +123,20 @@ export class LiveKitStreamTransport extends EventEmitter {
|
|
|
118
123
|
});
|
|
119
124
|
};
|
|
120
125
|
this.topic = options.topic ?? LIVEKIT_TRANSPORT_DEFAULT_TOPIC;
|
|
126
|
+
this.bufferMs = options.bufferMs ?? 2000;
|
|
127
|
+
this.on('pause', () => {
|
|
128
|
+
this.paused = true;
|
|
129
|
+
});
|
|
130
|
+
this.on('resume', () => {
|
|
131
|
+
this.paused = false;
|
|
132
|
+
if (this.droppedMs > 0) {
|
|
133
|
+
this.emit('gap', { droppedMs: this.droppedMs, reason: 'paused' });
|
|
134
|
+
this.droppedMs = 0;
|
|
135
|
+
}
|
|
136
|
+
for (const f of this.held.splice(0))
|
|
137
|
+
this.emit('audio', f);
|
|
138
|
+
this.heldMs = 0;
|
|
139
|
+
});
|
|
121
140
|
// The source checks the options before the topic is taken, so a refused
|
|
122
141
|
// option leaves the topic free; until it is read, the source holds nothing.
|
|
123
142
|
this.source = new LiveKitRoomAudioSource({
|
|
@@ -184,7 +203,19 @@ export class LiveKitStreamTransport extends EventEmitter {
|
|
|
184
203
|
async pump() {
|
|
185
204
|
try {
|
|
186
205
|
for await (const frame of this.source) {
|
|
187
|
-
this.
|
|
206
|
+
if (!this.paused) {
|
|
207
|
+
this.emit('audio', frame);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const ms = (frame.samples.length / frame.sampleRate) * 1000;
|
|
211
|
+
this.held.push(frame);
|
|
212
|
+
this.heldMs += ms;
|
|
213
|
+
while (this.heldMs > this.bufferMs && this.held.length) {
|
|
214
|
+
const old = this.held.shift();
|
|
215
|
+
const oldMs = (old.samples.length / old.sampleRate) * 1000;
|
|
216
|
+
this.heldMs -= oldMs;
|
|
217
|
+
this.droppedMs += oldMs;
|
|
218
|
+
}
|
|
188
219
|
}
|
|
189
220
|
}
|
|
190
221
|
catch (err) {
|