@fonoster/callrecord 0.30.0 → 0.31.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/dist/CallRecordWriter.d.ts +2 -2
- package/dist/CallRecordWriter.js +2 -2
- package/dist/indexEntry.d.ts +15 -1
- package/dist/indexEntry.js +8 -24
- package/dist/parts.d.ts +1 -1
- package/dist/recording.d.ts +1 -1
- package/dist/recording.js +2 -2
- package/dist/sign.d.ts +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/vcon.d.ts +2 -2
- package/dist/vcon.js +36 -12
- package/package.json +4 -5
|
@@ -46,7 +46,7 @@ export type CallRecordWriterOptions = {
|
|
|
46
46
|
};
|
|
47
47
|
/**
|
|
48
48
|
* Builds call records live and seals them at hangup (call-record "The record is built during the
|
|
49
|
-
* call and sealed at hangup"). It implements
|
|
49
|
+
* call and sealed at hangup"). It implements AppBridge's CallRecordSink interface.
|
|
50
50
|
*/
|
|
51
51
|
export declare class CallRecordWriter {
|
|
52
52
|
private readonly options;
|
|
@@ -92,7 +92,7 @@ export declare class CallRecordWriter {
|
|
|
92
92
|
private sealed;
|
|
93
93
|
/**
|
|
94
94
|
* Seals records whose calls stopped appending more than `deadlineMs` ago without a hangup (a
|
|
95
|
-
*
|
|
95
|
+
* appbridge that crashed). Returns the callRefs sealed.
|
|
96
96
|
*/
|
|
97
97
|
sweep(now?: number, deadlineMs?: number): Promise<string[]>;
|
|
98
98
|
/** Adds a version derived from the current one (it references its predecessor). */
|
package/dist/CallRecordWriter.js
CHANGED
|
@@ -108,7 +108,7 @@ function assertSameWorkspace(callRef, stored, expected) {
|
|
|
108
108
|
const OTHER_SEAL_WAIT_MS = 120000;
|
|
109
109
|
/**
|
|
110
110
|
* Builds call records live and seals them at hangup (call-record "The record is built during the
|
|
111
|
-
* call and sealed at hangup"). It implements
|
|
111
|
+
* call and sealed at hangup"). It implements AppBridge's CallRecordSink interface.
|
|
112
112
|
*/
|
|
113
113
|
class CallRecordWriter {
|
|
114
114
|
constructor(options) {
|
|
@@ -304,7 +304,7 @@ class CallRecordWriter {
|
|
|
304
304
|
}
|
|
305
305
|
/**
|
|
306
306
|
* Seals records whose calls stopped appending more than `deadlineMs` ago without a hangup (a
|
|
307
|
-
*
|
|
307
|
+
* appbridge that crashed). Returns the callRefs sealed.
|
|
308
308
|
*/
|
|
309
309
|
sweep() {
|
|
310
310
|
return __awaiter(this, arguments, void 0, function* (now = Date.now(), deadlineMs = exports.SEAL_DEADLINE_MS) {
|
package/dist/indexEntry.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export type RecordIndexEntry = {
|
|
|
14
14
|
endReason: string | null;
|
|
15
15
|
failureReason: string | null;
|
|
16
16
|
sipStatus: number | null;
|
|
17
|
+
/** Who answered, by AMD: human, voicemail, ivr, machine or unknown; null when AMD didn't run. */
|
|
18
|
+
amdStatus: string | null;
|
|
17
19
|
startedAt: string;
|
|
18
20
|
endedAt: string | null;
|
|
19
21
|
durationSeconds: number;
|
|
@@ -25,8 +27,20 @@ export type RecordIndexEntry = {
|
|
|
25
27
|
size: number;
|
|
26
28
|
/** Parts present in this version: recording, messages, transcript. */
|
|
27
29
|
parts: string[];
|
|
30
|
+
/** How the call started: call or browser_test (add-usage-metering). */
|
|
31
|
+
origin?: string;
|
|
32
|
+
/** The call's usage lines, signed with the record (add-usage-metering). */
|
|
33
|
+
usage?: IndexUsageLine[];
|
|
28
34
|
};
|
|
29
|
-
/**
|
|
35
|
+
/** One usage line as the index carries it; the control plane validates it against its meters. */
|
|
36
|
+
export type IndexUsageLine = {
|
|
37
|
+
meter: string;
|
|
38
|
+
quantity: number;
|
|
39
|
+
provider?: string;
|
|
40
|
+
model?: string;
|
|
41
|
+
keySource?: "platform" | "workspace";
|
|
42
|
+
};
|
|
43
|
+
/** NATS subject AppBridge publishes index entries on; the control plane consumes it. */
|
|
30
44
|
export declare const RECORD_SEALED_SUBJECT = "callrecord.sealed";
|
|
31
45
|
export declare function indexEntry(callRef: string, sealed: SealedVersion | SealingVersion, vcon: Vcon, where: {
|
|
32
46
|
region: string;
|
package/dist/indexEntry.js
CHANGED
|
@@ -21,10 +21,10 @@ exports.indexEntry = indexEntry;
|
|
|
21
21
|
* limitations under the License.
|
|
22
22
|
*/
|
|
23
23
|
const parts_1 = require("./parts");
|
|
24
|
-
/** NATS subject
|
|
24
|
+
/** NATS subject AppBridge publishes index entries on; the control plane consumes it. */
|
|
25
25
|
exports.RECORD_SEALED_SUBJECT = "callrecord.sealed";
|
|
26
26
|
function indexEntry(callRef, sealed, vcon, where) {
|
|
27
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
27
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
28
28
|
const f = ((_a = vcon.fonoster) !== null && _a !== void 0 ? _a : {});
|
|
29
29
|
const tel = (role) => {
|
|
30
30
|
const p = vcon.parties.find((x) => x.role === role);
|
|
@@ -39,30 +39,14 @@ function indexEntry(callRef, sealed, vcon, where) {
|
|
|
39
39
|
const size = sealed.parts.reduce((n, p) => n + (0, parts_1.partSize)(p), 0) +
|
|
40
40
|
sealed.signed.payload.length +
|
|
41
41
|
sealed.redacted.payload.length;
|
|
42
|
-
return {
|
|
43
|
-
|
|
44
|
-
workspaceRef: (_d = f.workspaceRef) !== null && _d !== void 0 ? _d : null,
|
|
45
|
-
appRef: (_f = ((_e = f.appRefs) !== null && _e !== void 0 ? _e : [])[0]) !== null && _f !== void 0 ? _f : null,
|
|
46
|
-
from: tel("caller"),
|
|
47
|
-
to: tel("callee"),
|
|
48
|
-
direction: (_g = f.direction) !== null && _g !== void 0 ? _g : null,
|
|
49
|
-
status: String((_h = f.status) !== null && _h !== void 0 ? _h : "completed"),
|
|
50
|
-
endReason: (_j = f.endReason) !== null && _j !== void 0 ? _j : null,
|
|
51
|
-
failureReason: (_k = failure === null || failure === void 0 ? void 0 : failure.reason) !== null && _k !== void 0 ? _k : null,
|
|
52
|
-
sipStatus: (_l = failure === null || failure === void 0 ? void 0 : failure.sipStatus) !== null && _l !== void 0 ? _l : null,
|
|
53
|
-
startedAt,
|
|
54
|
-
endedAt,
|
|
55
|
-
durationSeconds: endedAt
|
|
42
|
+
return Object.assign(Object.assign(Object.assign({ callRef, workspaceRef: (_d = f.workspaceRef) !== null && _d !== void 0 ? _d : null, appRef: (_f = ((_e = f.appRefs) !== null && _e !== void 0 ? _e : [])[0]) !== null && _f !== void 0 ? _f : null, from: tel("caller"), to: tel("callee"), direction: (_g = f.direction) !== null && _g !== void 0 ? _g : null, status: String((_h = f.status) !== null && _h !== void 0 ? _h : "completed"), endReason: (_j = f.endReason) !== null && _j !== void 0 ? _j : null, failureReason: (_k = failure === null || failure === void 0 ? void 0 : failure.reason) !== null && _k !== void 0 ? _k : null, sipStatus: (_l = failure === null || failure === void 0 ? void 0 : failure.sipStatus) !== null && _l !== void 0 ? _l : null, amdStatus: (_o = (_m = f.amd) === null || _m === void 0 ? void 0 : _m.status) !== null && _o !== void 0 ? _o : null, startedAt,
|
|
43
|
+
endedAt, durationSeconds: endedAt
|
|
56
44
|
? Math.max(0, Math.round((Date.parse(endedAt) - Date.parse(startedAt)) / 1000))
|
|
57
|
-
: 0,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
version: sealed.version,
|
|
61
|
-
size,
|
|
62
|
-
parts: [
|
|
45
|
+
: 0, region: where.region, location: where.location }, (f.origin ? { origin: String(f.origin) } : {})), (Array.isArray(f.usage) && f.usage.length
|
|
46
|
+
? { usage: f.usage }
|
|
47
|
+
: {})), { version: sealed.version, size, parts: [
|
|
63
48
|
...(hasRecording ? ["recording"] : []),
|
|
64
49
|
...(hasTranscript ? ["transcript"] : []),
|
|
65
50
|
...(hasMessages ? ["messages"] : [])
|
|
66
|
-
]
|
|
67
|
-
};
|
|
51
|
+
] });
|
|
68
52
|
}
|
package/dist/parts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FilePart, Part, SealingPart, StoredPart } from "./types";
|
|
1
|
+
import type { FilePart, Part, SealingPart, StoredPart } from "./types";
|
|
2
2
|
export declare const isFilePart: (p: SealingPart) => p is FilePart;
|
|
3
3
|
export declare const isStoredPart: (p: SealingPart) => p is StoredPart;
|
|
4
4
|
export declare const isDataPart: (p: SealingPart) => p is Part;
|
package/dist/recording.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export declare class Recorder {
|
|
|
34
34
|
export declare function wavHeader(dataBytes: number, channels: number, rate?: number): Buffer<ArrayBuffer>;
|
|
35
35
|
/**
|
|
36
36
|
* Builds the stereo WAV (left: caller, right: agent) from a recorder's directory, or undefined
|
|
37
|
-
* when nothing was recorded. Works on what a crashed
|
|
37
|
+
* when nothing was recorded. Works on what a crashed AppBridge left behind as well.
|
|
38
38
|
*/
|
|
39
39
|
export declare function assembleRecording(dir: string): {
|
|
40
40
|
wav: Buffer;
|
package/dist/recording.js
CHANGED
|
@@ -72,7 +72,7 @@ const fs = __importStar(require("fs"));
|
|
|
72
72
|
const path = __importStar(require("path"));
|
|
73
73
|
// Full-call recording (call-record "Recording is applied by policy", design V8): an internal
|
|
74
74
|
// listener attached with media-control `listener.attach`, one unmixed RTP stream per side. The
|
|
75
|
-
// recorder writes each side as raw 16 kHz PCM next to the working record, so
|
|
75
|
+
// recorder writes each side as raw 16 kHz PCM next to the working record, so an AppBridge crash
|
|
76
76
|
// keeps what was recorded; sealing turns the two sides into one stereo WAV (left: caller,
|
|
77
77
|
// right: agent) and references it, with its hash, from the vCon dialog.
|
|
78
78
|
exports.RECORDING_RATE = 16000;
|
|
@@ -205,7 +205,7 @@ function wavHeader(dataBytes, channels, rate = exports.RECORDING_RATE) {
|
|
|
205
205
|
}
|
|
206
206
|
/**
|
|
207
207
|
* Builds the stereo WAV (left: caller, right: agent) from a recorder's directory, or undefined
|
|
208
|
-
* when nothing was recorded. Works on what a crashed
|
|
208
|
+
* when nothing was recorded. Works on what a crashed AppBridge left behind as well.
|
|
209
209
|
*/
|
|
210
210
|
function assembleRecording(dir) {
|
|
211
211
|
const metaFile = path.join(dir, "meta.json");
|
package/dist/sign.d.ts
CHANGED
package/dist/storage.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ObjectStore } from "./objectStore";
|
|
2
2
|
import { Part, RecordEntry, SealedVersion, SealingVersion, SignedVcon } from "./types";
|
|
3
3
|
/**
|
|
4
|
-
* Working records live on
|
|
4
|
+
* Working records live on AppBridge's local disk while the call runs: one fsynced JSON line
|
|
5
5
|
* per entry, plus the raw recording tracks. Sealed records go to object storage (RecordStore).
|
|
6
6
|
*/
|
|
7
7
|
export declare class FsWorkingStore {
|
|
@@ -23,7 +23,7 @@ export declare class FsWorkingStore {
|
|
|
23
23
|
/**
|
|
24
24
|
* The owner's heartbeat on a live call's working record (ST-5): moves its time of last append
|
|
25
25
|
* to now without writing, so a quiet call (hold, long silence) is not taken for an abandoned
|
|
26
|
-
* one by another
|
|
26
|
+
* one by another AppBridge sweeping the same directory.
|
|
27
27
|
*/
|
|
28
28
|
touch(callRef: string): void;
|
|
29
29
|
private sealLock;
|
package/dist/storage.js
CHANGED
|
@@ -68,7 +68,7 @@ const path = __importStar(require("path"));
|
|
|
68
68
|
const objectStore_1 = require("./objectStore");
|
|
69
69
|
const parts_1 = require("./parts");
|
|
70
70
|
/**
|
|
71
|
-
* Working records live on
|
|
71
|
+
* Working records live on AppBridge's local disk while the call runs: one fsynced JSON line
|
|
72
72
|
* per entry, plus the raw recording tracks. Sealed records go to object storage (RecordStore).
|
|
73
73
|
*/
|
|
74
74
|
class FsWorkingStore {
|
|
@@ -132,7 +132,7 @@ class FsWorkingStore {
|
|
|
132
132
|
/**
|
|
133
133
|
* The owner's heartbeat on a live call's working record (ST-5): moves its time of last append
|
|
134
134
|
* to now without writing, so a quiet call (hold, long silence) is not taken for an abandoned
|
|
135
|
-
* one by another
|
|
135
|
+
* one by another AppBridge sweeping the same directory.
|
|
136
136
|
*/
|
|
137
137
|
touch(callRef) {
|
|
138
138
|
const now = new Date();
|
package/dist/types.d.ts
CHANGED
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
* See the License for the specific language governing permissions and
|
|
17
17
|
* limitations under the License.
|
|
18
18
|
*/
|
|
19
|
-
/** One working-record entry, as
|
|
19
|
+
/** One working-record entry, as AppBridge appends it (voice-session, "Every message is part of the call record"). */
|
|
20
20
|
export type RecordEntry = {
|
|
21
21
|
at: number;
|
|
22
|
-
source: "app" | "
|
|
22
|
+
source: "app" | "appbridge" | "event";
|
|
23
23
|
message: Record<string, unknown>;
|
|
24
24
|
};
|
|
25
25
|
/** A part stored next to the vCon (vCon external references with content hashes). */
|
package/dist/vcon.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BeepSpan } from "./recording";
|
|
2
|
-
import { RecordEntry, SealingPart, Vcon } from "./types";
|
|
1
|
+
import type { BeepSpan } from "./recording";
|
|
2
|
+
import type { RecordEntry, SealingPart, Vcon } from "./types";
|
|
3
3
|
/**
|
|
4
4
|
* Pinned to draft-ietf-vcon-vcon-core-04 (September 2026), which requires "0.4.0" (call-record
|
|
5
5
|
* open question O4).
|
package/dist/vcon.js
CHANGED
|
@@ -48,7 +48,7 @@ const iso = (ms) => new Date(ms).toISOString();
|
|
|
48
48
|
* attached part with a content hash. Lists what is missing (recording, SIP trace, hangup).
|
|
49
49
|
*/
|
|
50
50
|
function buildVcon(callRef, entries, options) {
|
|
51
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
51
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
52
52
|
const parties = [];
|
|
53
53
|
const dialog = [];
|
|
54
54
|
const decisions = [];
|
|
@@ -60,8 +60,14 @@ function buildVcon(callRef, entries, options) {
|
|
|
60
60
|
let endedAt;
|
|
61
61
|
let endReason;
|
|
62
62
|
const failures = [];
|
|
63
|
+
// Audio filters that failed, at start or mid-call, with the reason (for the "Unfiltered" badge).
|
|
64
|
+
const filterFailures = [];
|
|
65
|
+
// The call's usage: each snapshot holds all of it, so the last one wins (add-usage-metering).
|
|
66
|
+
let usage;
|
|
63
67
|
let started;
|
|
64
68
|
let failure;
|
|
69
|
+
// Who answered (AMD), as AppBridge reported it: the first verdict is the call's.
|
|
70
|
+
let amd;
|
|
65
71
|
let recordingPolicy;
|
|
66
72
|
let recordingFailed;
|
|
67
73
|
let consentRequested = false;
|
|
@@ -71,7 +77,7 @@ function buildVcon(callRef, entries, options) {
|
|
|
71
77
|
for (const e of entries) {
|
|
72
78
|
const m = e.message;
|
|
73
79
|
const type = m.type;
|
|
74
|
-
if (e.source === "
|
|
80
|
+
if (e.source === "appbridge" && type === "session.start") {
|
|
75
81
|
if (!parties.length) {
|
|
76
82
|
startedAt = e.at;
|
|
77
83
|
parties.push({ tel: m.from, role: "caller" }, { tel: m.to, role: "callee" });
|
|
@@ -81,7 +87,7 @@ function buildVcon(callRef, entries, options) {
|
|
|
81
87
|
appParty.set(appRef, parties.push({ name: appRef, role: "agent", meta: { appRef } }) - 1);
|
|
82
88
|
currentApp = appParty.get(appRef);
|
|
83
89
|
}
|
|
84
|
-
else if (e.source === "
|
|
90
|
+
else if (e.source === "appbridge" && type === "turn.ended") {
|
|
85
91
|
const turn = {
|
|
86
92
|
type: "text",
|
|
87
93
|
start: iso(e.at),
|
|
@@ -104,11 +110,11 @@ function buildVcon(callRef, entries, options) {
|
|
|
104
110
|
userStartedAt = undefined;
|
|
105
111
|
decisions.push(Object.assign({ at: iso(e.at) }, m));
|
|
106
112
|
}
|
|
107
|
-
else if (e.source === "
|
|
113
|
+
else if (e.source === "appbridge" && type === "turn.user_started") {
|
|
108
114
|
userStartedAt !== null && userStartedAt !== void 0 ? userStartedAt : (userStartedAt = e.at);
|
|
109
115
|
decisions.push(Object.assign({ at: iso(e.at) }, m));
|
|
110
116
|
}
|
|
111
|
-
else if (e.source === "
|
|
117
|
+
else if (e.source === "appbridge" &&
|
|
112
118
|
(type === null || type === void 0 ? void 0 : type.startsWith("turn.")) &&
|
|
113
119
|
type !== "turn.estimate") {
|
|
114
120
|
decisions.push(Object.assign({ at: iso(e.at) }, m));
|
|
@@ -119,12 +125,12 @@ function buildVcon(callRef, entries, options) {
|
|
|
119
125
|
s.text += String((_e = m.text) !== null && _e !== void 0 ? _e : "");
|
|
120
126
|
speech.set(id, s);
|
|
121
127
|
}
|
|
122
|
-
else if (e.source === "
|
|
128
|
+
else if (e.source === "appbridge" && type === "output.started") {
|
|
123
129
|
const s = speech.get(String(m.id));
|
|
124
130
|
if (s)
|
|
125
131
|
s.startedAt = e.at;
|
|
126
132
|
}
|
|
127
|
-
else if (e.source === "
|
|
133
|
+
else if (e.source === "appbridge" &&
|
|
128
134
|
(type === "output.done" || type === "output.interrupted")) {
|
|
129
135
|
const s = speech.get(String(m.id));
|
|
130
136
|
if (s && s.text) {
|
|
@@ -152,15 +158,24 @@ function buildVcon(callRef, entries, options) {
|
|
|
152
158
|
else if (e.source === "event" && type === "call.failed") {
|
|
153
159
|
failure !== null && failure !== void 0 ? failure : (failure = Object.assign({ reason: String(m.reason) }, (typeof m.sipStatus === "number" ? { sipStatus: m.sipStatus } : {})));
|
|
154
160
|
}
|
|
161
|
+
else if (e.source === "event" && type === "amd.result") {
|
|
162
|
+
amd !== null && amd !== void 0 ? amd : (amd = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ status: String((_j = m.status) !== null && _j !== void 0 ? _j : "unknown") }, (typeof m.confidence === "number"
|
|
163
|
+
? { confidence: m.confidence }
|
|
164
|
+
: {})), (typeof m.detector === "string" ? { detector: m.detector } : {})), (typeof m.audioMs === "number" ? { audioMs: m.audioMs } : {})), (typeof m.reason === "string" ? { reason: m.reason } : {})), { at: iso(e.at) }));
|
|
165
|
+
}
|
|
155
166
|
else if (e.source === "event" && type === "recording.started") {
|
|
156
|
-
recordingPolicy = String((
|
|
167
|
+
recordingPolicy = String((_k = m.policy) !== null && _k !== void 0 ? _k : "on");
|
|
157
168
|
}
|
|
158
169
|
else if (e.source === "event" && type === "recording.failed") {
|
|
159
|
-
recordingFailed = String((
|
|
170
|
+
recordingFailed = String((_l = m.reason) !== null && _l !== void 0 ? _l : "error");
|
|
160
171
|
}
|
|
161
172
|
else if (e.source === "event" && type === "recording.consent_requested") {
|
|
162
173
|
consentRequested = true;
|
|
163
174
|
}
|
|
175
|
+
else if (e.source === "event" && type === "usage.snapshot") {
|
|
176
|
+
if (Array.isArray(m.lines))
|
|
177
|
+
usage = m.lines;
|
|
178
|
+
}
|
|
164
179
|
else if (e.source === "event" && type === "call.ended") {
|
|
165
180
|
endedAt = e.at;
|
|
166
181
|
endReason = String(m.reason);
|
|
@@ -170,8 +185,17 @@ function buildVcon(callRef, entries, options) {
|
|
|
170
185
|
type === "filter.failed" ||
|
|
171
186
|
type === "app.dropped")) {
|
|
172
187
|
failures.push(type);
|
|
188
|
+
if (type === "filter.failed") {
|
|
189
|
+
filterFailures.push(Object.assign(Object.assign({}, (m.name ? { name: String(m.name) } : {})), { reason: String((_m = m.reason) !== null && _m !== void 0 ? _m : "error") }));
|
|
190
|
+
}
|
|
173
191
|
}
|
|
174
192
|
}
|
|
193
|
+
// Each spoken turn starts when that side began speaking and lasts until it stopped (vCon
|
|
194
|
+
// dialog `duration`, seconds): the transcript's timings per turn and per side.
|
|
195
|
+
for (const [turn, span] of heard) {
|
|
196
|
+
turn.start = iso(span.from);
|
|
197
|
+
turn.duration = Math.max(0, span.to - span.from) / 1000;
|
|
198
|
+
}
|
|
175
199
|
// A call that never reached an app has no session.start: its parties come from call.started
|
|
176
200
|
// (minimal record, call-record "Calls that never reach an app get a minimal record").
|
|
177
201
|
if (!parties.length && started) {
|
|
@@ -261,11 +285,11 @@ function buildVcon(callRef, entries, options) {
|
|
|
261
285
|
url: `parts/${p.name}`,
|
|
262
286
|
content_hash: (0, parts_1.partHash)(p)
|
|
263
287
|
})),
|
|
264
|
-
fonoster: Object.assign(Object.assign(Object.assign({ callRef, region: options.region, startedAt: iso(startedAt), endedAt: endedAt ? iso(endedAt) : null, endReason: endReason !== null && endReason !== void 0 ? endReason : null, status, direction: (
|
|
288
|
+
fonoster: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ callRef, region: options.region, startedAt: iso(startedAt), endedAt: endedAt ? iso(endedAt) : null, endReason: endReason !== null && endReason !== void 0 ? endReason : null, status, direction: (_o = started === null || started === void 0 ? void 0 : started.direction) !== null && _o !== void 0 ? _o : null, workspaceRef: (_p = started === null || started === void 0 ? void 0 : started.workspaceRef) !== null && _p !== void 0 ? _p : null, appRefs }, (failure ? { failure } : {})), (amd ? { amd } : {})), (recordingPolicy || recordingFailed || consentRequested
|
|
265
289
|
? {
|
|
266
290
|
recording: Object.assign({ policy: recordingPolicy !== null && recordingPolicy !== void 0 ? recordingPolicy : null, consentRequested }, (recordingFailed ? { failed: recordingFailed } : {}))
|
|
267
291
|
}
|
|
268
|
-
: {})), { complete: !missing.includes("hangup"), missing,
|
|
292
|
+
: {})), (filterFailures.length ? { filters: { failed: filterFailures } } : {})), ((started === null || started === void 0 ? void 0 : started.origin) ? { origin: started.origin } : {})), ((usage === null || usage === void 0 ? void 0 : usage.length) ? { usage } : {})), { complete: !missing.includes("hangup"), missing,
|
|
269
293
|
failures })
|
|
270
294
|
};
|
|
271
295
|
const vcon = Object.assign(Object.assign({}, base), { uuid: (0, crypto_1.randomUUID)(), dialog });
|
|
@@ -299,7 +323,7 @@ function buildVcon(callRef, entries, options) {
|
|
|
299
323
|
// turn that carried them, since there are no word timings yet (O3). Without a beeped copy the
|
|
300
324
|
// redacted copy does not reference the recording at all.
|
|
301
325
|
const beeped = redactions && recording && spans.length && !unlocatable
|
|
302
|
-
? (
|
|
326
|
+
? (_q = recording.beep) === null || _q === void 0 ? void 0 : _q.call(recording, spans)
|
|
303
327
|
: undefined;
|
|
304
328
|
if (beeped)
|
|
305
329
|
parts.push(beeped);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fonoster/callrecord",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "Call records: working records during calls, sealed and signed vCon files after hangup",
|
|
5
5
|
"author": "Pedro Sanders <psanders@fonoster.com>",
|
|
6
6
|
"homepage": "https://github.com/fonoster/fonoster#readme",
|
|
@@ -13,12 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"prebuild": "rimraf ./dist tsconfig.tsbuildinfo",
|
|
16
|
-
"build": "tsc -b tsconfig.json"
|
|
17
|
-
"clean": "rimraf ./dist node_modules tsconfig.tsbuildinfo"
|
|
16
|
+
"build": "tsc -b tsconfig.json"
|
|
18
17
|
},
|
|
19
18
|
"dependencies": {
|
|
20
19
|
"@aws-sdk/client-s3": "^3.958.0",
|
|
21
|
-
"@fonoster/logger": "^0.
|
|
20
|
+
"@fonoster/logger": "^0.31.0"
|
|
22
21
|
},
|
|
23
22
|
"files": [
|
|
24
23
|
"dist",
|
|
@@ -40,5 +39,5 @@
|
|
|
40
39
|
"devDependencies": {
|
|
41
40
|
"ajv": "^8.18.0"
|
|
42
41
|
},
|
|
43
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "f0a5102dddeea0f70f659234108805bc10690f2e"
|
|
44
43
|
}
|