getpatter 0.6.1 → 0.6.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/dist/chunk-CL2U3YET.mjs +1429 -0
- package/dist/{chunk-TEW3NAZJ.mjs → chunk-LE63CSOB.mjs} +371 -1486
- package/dist/{chunk-RV7APPYE.mjs → chunk-R2T4JABZ.mjs} +13 -0
- package/dist/cli.js +48 -23
- package/dist/dashboard/ui.html +8 -8
- package/dist/index.d.mts +452 -186
- package/dist/index.d.ts +452 -186
- package/dist/index.js +1485 -979
- package/dist/index.mjs +973 -790
- package/dist/openai-realtime-2-CNFARP25.mjs +8 -0
- package/dist/{silero-vad-NSEXI4XS.mjs → silero-vad-LNDFGIY7.mjs} +1 -1
- package/dist/{test-mode-WEKKNBLD.mjs → test-mode-RS57BDM6.mjs} +2 -1
- package/package.json +1 -1
- package/src/dashboard/ui.html +8 -8
|
@@ -262,6 +262,19 @@ var SileroVAD = class _SileroVAD {
|
|
|
262
262
|
static forPhoneCall(options = {}) {
|
|
263
263
|
return _SileroVAD.load({
|
|
264
264
|
sampleRate: 16e3,
|
|
265
|
+
// Telephony bumps the activation threshold from the upstream
|
|
266
|
+
// 0.5 → 0.8 (with deactivation 0.65) so background voices and
|
|
267
|
+
// low-volume audio in the caller's room don't trip barge-in.
|
|
268
|
+
// Near-mic speech typically scores 0.85-0.98 on Silero — above
|
|
269
|
+
// 0.8 — while a distant second speaker through a phone's noise-
|
|
270
|
+
// suppression pipeline lands around 0.4-0.6 and is now correctly
|
|
271
|
+
// ignored. Bumped twice during 2026-05-20 acceptance: first 0.5
|
|
272
|
+
// → 0.7 (still triggered on quiet voices), then 0.7 → 0.8.
|
|
273
|
+
// Trade-off: a whispered legitimate input may not trigger;
|
|
274
|
+
// typical phone-call speakers are unaffected. Pass an explicit
|
|
275
|
+
// ``activationThreshold`` to override per call site.
|
|
276
|
+
activationThreshold: 0.8,
|
|
277
|
+
deactivationThreshold: 0.65,
|
|
265
278
|
...options
|
|
266
279
|
});
|
|
267
280
|
}
|
package/dist/cli.js
CHANGED
|
@@ -29,8 +29,8 @@ var import_express = __toESM(require("express"));
|
|
|
29
29
|
|
|
30
30
|
// src/dashboard/store.ts
|
|
31
31
|
var import_events = require("events");
|
|
32
|
-
var
|
|
33
|
-
var
|
|
32
|
+
var fs2 = __toESM(require("fs"));
|
|
33
|
+
var path2 = __toESM(require("path"));
|
|
34
34
|
|
|
35
35
|
// src/logger.ts
|
|
36
36
|
var defaultLogger = {
|
|
@@ -45,7 +45,24 @@ function getLogger() {
|
|
|
45
45
|
return currentLogger;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
// src/version.ts
|
|
49
|
+
var fs = __toESM(require("fs"));
|
|
50
|
+
var path = __toESM(require("path"));
|
|
51
|
+
function readVersion() {
|
|
52
|
+
try {
|
|
53
|
+
const pkgPath = path.resolve(__dirname, "..", "package.json");
|
|
54
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
55
|
+
return typeof pkg.version === "string" && pkg.version.length > 0 ? pkg.version : "";
|
|
56
|
+
} catch {
|
|
57
|
+
return "";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
var VERSION = readVersion();
|
|
61
|
+
|
|
48
62
|
// src/dashboard/store.ts
|
|
63
|
+
function sdkVersion() {
|
|
64
|
+
return VERSION;
|
|
65
|
+
}
|
|
49
66
|
var MetricsStore = class extends import_events.EventEmitter {
|
|
50
67
|
maxCalls;
|
|
51
68
|
calls = [];
|
|
@@ -328,15 +345,15 @@ var MetricsStore = class extends import_events.EventEmitter {
|
|
|
328
345
|
persistDeletedIds() {
|
|
329
346
|
if (this.deletedIdsPath === null) return;
|
|
330
347
|
try {
|
|
331
|
-
const dir =
|
|
332
|
-
|
|
348
|
+
const dir = path2.dirname(this.deletedIdsPath);
|
|
349
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
333
350
|
const tmp = this.deletedIdsPath + ".tmp";
|
|
334
351
|
const payload = {
|
|
335
352
|
version: 1,
|
|
336
353
|
deleted_call_ids: Array.from(this.deletedCallIds).sort()
|
|
337
354
|
};
|
|
338
|
-
|
|
339
|
-
|
|
355
|
+
fs2.writeFileSync(tmp, JSON.stringify(payload, null, 2), "utf8");
|
|
356
|
+
fs2.renameSync(tmp, this.deletedIdsPath);
|
|
340
357
|
} catch (err) {
|
|
341
358
|
getLogger().debug(
|
|
342
359
|
`MetricsStore.persistDeletedIds: ${String(err)}`
|
|
@@ -369,7 +386,8 @@ var MetricsStore = class extends import_events.EventEmitter {
|
|
|
369
386
|
avg_duration: 0,
|
|
370
387
|
avg_latency_ms: 0,
|
|
371
388
|
cost_breakdown: { stt: 0, tts: 0, llm: 0, telephony: 0 },
|
|
372
|
-
active_calls: this.activeCalls.size
|
|
389
|
+
active_calls: this.activeCalls.size,
|
|
390
|
+
sdk_version: sdkVersion()
|
|
373
391
|
};
|
|
374
392
|
}
|
|
375
393
|
let totalCost = 0;
|
|
@@ -408,7 +426,8 @@ var MetricsStore = class extends import_events.EventEmitter {
|
|
|
408
426
|
llm: Math.round(costLlm * 1e6) / 1e6,
|
|
409
427
|
telephony: Math.round(costTel * 1e6) / 1e6
|
|
410
428
|
},
|
|
411
|
-
active_calls: this.activeCalls.size
|
|
429
|
+
active_calls: this.activeCalls.size,
|
|
430
|
+
sdk_version: sdkVersion()
|
|
412
431
|
};
|
|
413
432
|
}
|
|
414
433
|
/**
|
|
@@ -444,11 +463,11 @@ var MetricsStore = class extends import_events.EventEmitter {
|
|
|
444
463
|
*/
|
|
445
464
|
hydrate(logRoot) {
|
|
446
465
|
if (!logRoot) return 0;
|
|
447
|
-
const deletedIdsPath =
|
|
466
|
+
const deletedIdsPath = path2.join(logRoot, ".deleted_call_ids.json");
|
|
448
467
|
this.deletedIdsPath = deletedIdsPath;
|
|
449
|
-
if (
|
|
468
|
+
if (fs2.existsSync(deletedIdsPath)) {
|
|
450
469
|
try {
|
|
451
|
-
const raw =
|
|
470
|
+
const raw = fs2.readFileSync(deletedIdsPath, "utf8");
|
|
452
471
|
const payload = JSON.parse(raw);
|
|
453
472
|
const arr = Array.isArray(payload.deleted_call_ids) ? payload.deleted_call_ids : [];
|
|
454
473
|
for (const cid of arr) {
|
|
@@ -462,19 +481,19 @@ var MetricsStore = class extends import_events.EventEmitter {
|
|
|
462
481
|
);
|
|
463
482
|
}
|
|
464
483
|
}
|
|
465
|
-
const callsRoot =
|
|
466
|
-
if (!
|
|
484
|
+
const callsRoot = path2.join(logRoot, "calls");
|
|
485
|
+
if (!fs2.existsSync(callsRoot)) return 0;
|
|
467
486
|
const collected = [];
|
|
468
487
|
const seen = new Set(this.calls.map((c) => c.call_id));
|
|
469
488
|
const walk = (dir, depth) => {
|
|
470
489
|
let entries;
|
|
471
490
|
try {
|
|
472
|
-
entries =
|
|
491
|
+
entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
473
492
|
} catch {
|
|
474
493
|
return;
|
|
475
494
|
}
|
|
476
495
|
for (const entry of entries) {
|
|
477
|
-
const childPath =
|
|
496
|
+
const childPath = path2.join(dir, entry.name);
|
|
478
497
|
if (depth < 3) {
|
|
479
498
|
if (entry.isDirectory() && /^\d+$/.test(entry.name)) {
|
|
480
499
|
walk(childPath, depth + 1);
|
|
@@ -482,10 +501,10 @@ var MetricsStore = class extends import_events.EventEmitter {
|
|
|
482
501
|
continue;
|
|
483
502
|
}
|
|
484
503
|
if (!entry.isDirectory()) continue;
|
|
485
|
-
const metadataPath =
|
|
486
|
-
if (!
|
|
504
|
+
const metadataPath = path2.join(childPath, "metadata.json");
|
|
505
|
+
if (!fs2.existsSync(metadataPath)) continue;
|
|
487
506
|
try {
|
|
488
|
-
const raw =
|
|
507
|
+
const raw = fs2.readFileSync(metadataPath, "utf8");
|
|
489
508
|
const meta = JSON.parse(raw);
|
|
490
509
|
const callId = meta.call_id || entry.name;
|
|
491
510
|
if (!callId || seen.has(callId)) continue;
|
|
@@ -498,7 +517,7 @@ var MetricsStore = class extends import_events.EventEmitter {
|
|
|
498
517
|
}
|
|
499
518
|
if (!record.transcript || record.transcript.length === 0) {
|
|
500
519
|
const fromJsonl = loadTranscriptJsonl(
|
|
501
|
-
|
|
520
|
+
path2.join(childPath, "transcript.jsonl")
|
|
502
521
|
);
|
|
503
522
|
if (fromJsonl.length > 0) record.transcript = fromJsonl;
|
|
504
523
|
}
|
|
@@ -577,8 +596,8 @@ function metadataToCallRecord(callId, meta) {
|
|
|
577
596
|
}
|
|
578
597
|
function loadTranscriptJsonl(filePath) {
|
|
579
598
|
try {
|
|
580
|
-
if (!
|
|
581
|
-
const raw =
|
|
599
|
+
if (!fs2.existsSync(filePath)) return [];
|
|
600
|
+
const raw = fs2.readFileSync(filePath, "utf8");
|
|
582
601
|
const lines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
583
602
|
const out = [];
|
|
584
603
|
for (const line of lines) {
|
|
@@ -723,9 +742,9 @@ function loadDashboardHtml() {
|
|
|
723
742
|
(0, import_node_path.join)(here, "dashboard", "ui.html"),
|
|
724
743
|
(0, import_node_path.join)(here, "..", "dashboard", "ui.html")
|
|
725
744
|
];
|
|
726
|
-
for (const
|
|
745
|
+
for (const path3 of candidates) {
|
|
727
746
|
try {
|
|
728
|
-
return (0, import_node_fs.readFileSync)(
|
|
747
|
+
return (0, import_node_fs.readFileSync)(path3, "utf8");
|
|
729
748
|
} catch {
|
|
730
749
|
}
|
|
731
750
|
}
|
|
@@ -978,6 +997,12 @@ async function main() {
|
|
|
978
997
|
res.json({ ok: false, error: "missing call_id" });
|
|
979
998
|
return;
|
|
980
999
|
}
|
|
1000
|
+
const status = data.status;
|
|
1001
|
+
if (status === "initiated") {
|
|
1002
|
+
store.recordCallInitiated(data);
|
|
1003
|
+
res.json({ ok: true, call_id: callId, event: "initiated" });
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
981
1006
|
store.recordCallStart(data);
|
|
982
1007
|
if (data.ended_at) {
|
|
983
1008
|
store.recordCallEnd(data, data.metrics ?? null);
|