@zixt/host 0.0.47 → 0.0.48
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/index.js +250 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import { homedir } from "node:os";
|
|
|
31
31
|
// package.json
|
|
32
32
|
var package_default = {
|
|
33
33
|
name: "@zixt/host",
|
|
34
|
-
version: "0.0.
|
|
34
|
+
version: "0.0.48",
|
|
35
35
|
type: "module",
|
|
36
36
|
exports: {
|
|
37
37
|
".": "./src/client.ts",
|
|
@@ -14660,7 +14660,17 @@ var ID_PREFIXES = {
|
|
|
14660
14660
|
/** One Manager inference call's token-metering row (MG-8). */
|
|
14661
14661
|
managerUsage: "mgu",
|
|
14662
14662
|
/** One ordered Manager reply awaiting Slack delivery. */
|
|
14663
|
-
managerSlackOutbox: "mso"
|
|
14663
|
+
managerSlackOutbox: "mso",
|
|
14664
|
+
/** One organization phone line that reaches its Manager. */
|
|
14665
|
+
voiceLine: "vln",
|
|
14666
|
+
/** One member-owned phone number admitted to Manager calls. */
|
|
14667
|
+
voiceCaller: "vcr",
|
|
14668
|
+
/** One live or historical phone call with the Manager. */
|
|
14669
|
+
voiceCall: "vca",
|
|
14670
|
+
/** One durable caller-transcript or Manager-speech delivery. */
|
|
14671
|
+
voiceTurn: "vtr",
|
|
14672
|
+
/** One signed voice-provider webhook receipt. */
|
|
14673
|
+
voiceWebhookEvent: "vwe"
|
|
14664
14674
|
};
|
|
14665
14675
|
var idPattern = (prefix) => new RegExp(`^${prefix}_[0-9a-f]{32}$`);
|
|
14666
14676
|
function newId(prefix) {
|
|
@@ -14687,6 +14697,14 @@ var ManagerId = idSchema(ID_PREFIXES.manager, "manager id");
|
|
|
14687
14697
|
var ManagerMemoryId = idSchema(ID_PREFIXES.managerMemory, "manager memory id");
|
|
14688
14698
|
var ConversationId = idSchema(ID_PREFIXES.conversation, "conversation id");
|
|
14689
14699
|
var ConversationEventId = idSchema(ID_PREFIXES.conversationEvent, "conversation event id");
|
|
14700
|
+
var VoiceLineId = idSchema(ID_PREFIXES.voiceLine, "voice line id");
|
|
14701
|
+
var VoiceCallerId = idSchema(ID_PREFIXES.voiceCaller, "voice caller id");
|
|
14702
|
+
var VoiceCallId = idSchema(ID_PREFIXES.voiceCall, "voice call id");
|
|
14703
|
+
var VoiceTurnId = idSchema(ID_PREFIXES.voiceTurn, "voice turn id");
|
|
14704
|
+
var VoiceWebhookEventId = idSchema(
|
|
14705
|
+
ID_PREFIXES.voiceWebhookEvent,
|
|
14706
|
+
"voice webhook event id"
|
|
14707
|
+
);
|
|
14690
14708
|
|
|
14691
14709
|
// ../../packages/contracts/src/browser.ts
|
|
14692
14710
|
var BrowserViewport = external_exports.object({
|
|
@@ -18752,7 +18770,7 @@ var ListManagerMemoriesResponse = external_exports.object({
|
|
|
18752
18770
|
memories: external_exports.array(ManagerMemoryProjection).max(MANAGER_MEMORY_MAX_ITEMS),
|
|
18753
18771
|
limit: external_exports.number().int().min(1)
|
|
18754
18772
|
}).strict();
|
|
18755
|
-
var ConversationChannel = external_exports.enum(["web", "slack", "whatsapp"]);
|
|
18773
|
+
var ConversationChannel = external_exports.enum(["web", "slack", "whatsapp", "phone"]);
|
|
18756
18774
|
var ConversationStatus = external_exports.enum(["idle", "thinking"]);
|
|
18757
18775
|
var ConversationProjection = external_exports.object({
|
|
18758
18776
|
id: ConversationId,
|
|
@@ -18790,6 +18808,10 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
|
|
|
18790
18808
|
text: external_exports.string(),
|
|
18791
18809
|
/** Display attribution only; authentication subjects remain internal. */
|
|
18792
18810
|
author: external_exports.object({ displayName: external_exports.string().nullable() }).strict(),
|
|
18811
|
+
/** Transport that supplied this turn; legacy events omit it. */
|
|
18812
|
+
sourceChannel: ConversationChannel.optional(),
|
|
18813
|
+
/** Input affordance within the trusted transport; legacy/typed turns omit it. */
|
|
18814
|
+
inputModality: external_exports.literal("voice").optional(),
|
|
18793
18815
|
attachments: external_exports.array(TaskAttachmentRef).max(TASK_MESSAGE_MAX_ATTACHMENTS).optional()
|
|
18794
18816
|
}).strict(),
|
|
18795
18817
|
/** The Manager's prose reply. */
|
|
@@ -18931,6 +18953,231 @@ var ManagerStreamFrame = external_exports.discriminatedUnion("type", [
|
|
|
18931
18953
|
external_exports.object({ type: external_exports.literal("conversation"), conversation: ConversationProjection }).strict()
|
|
18932
18954
|
]);
|
|
18933
18955
|
|
|
18956
|
+
// ../../packages/contracts/src/voice.ts
|
|
18957
|
+
var VOICE_MAX_CALL_MINUTES = 30;
|
|
18958
|
+
var VoiceE164Number = external_exports.string().regex(/^\+[1-9]\d{7,14}$/, "must be an international phone number");
|
|
18959
|
+
var VoicePhoneNumberInput = external_exports.string().trim().min(7).max(32).refine(
|
|
18960
|
+
(value) => /^\+[1-9]\d{7,14}$/.test(value.replace(/[\s()\-.]/g, "")),
|
|
18961
|
+
"must include a country code"
|
|
18962
|
+
);
|
|
18963
|
+
var VoiceAvailability = external_exports.enum(["unavailable", "setup_required", "setting_up", "ready", "needs_attention"]).describe(
|
|
18964
|
+
"Local Zixt deployment and line configuration state; ready does not prove remote webhook delivery"
|
|
18965
|
+
);
|
|
18966
|
+
var VoiceLineProjection = external_exports.object({
|
|
18967
|
+
id: VoiceLineId,
|
|
18968
|
+
/** Full public number: a member needs this value in order to call it. */
|
|
18969
|
+
dialInNumber: VoiceE164Number,
|
|
18970
|
+
enabled: external_exports.boolean(),
|
|
18971
|
+
readiness: external_exports.enum(["setting_up", "ready", "needs_attention"]).describe("Local line-resource state; ready does not prove remote webhook delivery")
|
|
18972
|
+
}).strict();
|
|
18973
|
+
var VoiceCallerProjection = external_exports.object({
|
|
18974
|
+
id: VoiceCallerId,
|
|
18975
|
+
memberId: MemberId,
|
|
18976
|
+
memberDisplayName: external_exports.string().min(1).max(120),
|
|
18977
|
+
/** Masked E.164 (for example +1 ••• ••• 7767), never the lookup key. */
|
|
18978
|
+
phoneNumber: external_exports.string().regex(/^\+(?:1|••) ••• ••• \d{4}$/, "must be a masked phone number"),
|
|
18979
|
+
status: external_exports.enum(["sending", "pending", "verified", "failed"]),
|
|
18980
|
+
verifiedAt: external_exports.string().nullable(),
|
|
18981
|
+
verificationExpiresAt: external_exports.string().nullable(),
|
|
18982
|
+
/** Member can manage their own rows; Admin/Owner can manage every row. */
|
|
18983
|
+
canManage: external_exports.boolean(),
|
|
18984
|
+
isCurrentMember: external_exports.boolean()
|
|
18985
|
+
}).strict();
|
|
18986
|
+
var VoiceSettingsResponse = external_exports.object({
|
|
18987
|
+
availability: VoiceAvailability,
|
|
18988
|
+
enabled: external_exports.boolean(),
|
|
18989
|
+
dialInNumber: VoiceE164Number.nullable(),
|
|
18990
|
+
line: VoiceLineProjection.nullable(),
|
|
18991
|
+
callers: external_exports.array(VoiceCallerProjection).max(500),
|
|
18992
|
+
/** Admin/Owner can set up or enable the organization line. */
|
|
18993
|
+
canManageLine: external_exports.boolean(),
|
|
18994
|
+
/** Admin/Owner can start verification for another member. */
|
|
18995
|
+
canManageCallers: external_exports.boolean(),
|
|
18996
|
+
currentMemberId: MemberId,
|
|
18997
|
+
maxCallMinutes: external_exports.literal(VOICE_MAX_CALL_MINUTES),
|
|
18998
|
+
revision: external_exports.number().int().min(0)
|
|
18999
|
+
}).strict().superRefine((settings, context) => {
|
|
19000
|
+
if (!settings.line && settings.dialInNumber !== null) {
|
|
19001
|
+
context.addIssue({
|
|
19002
|
+
code: "custom",
|
|
19003
|
+
path: ["dialInNumber"],
|
|
19004
|
+
message: "requires a line"
|
|
19005
|
+
});
|
|
19006
|
+
return;
|
|
19007
|
+
}
|
|
19008
|
+
if (settings.line && (settings.line.dialInNumber !== settings.dialInNumber || settings.line.enabled !== settings.enabled)) {
|
|
19009
|
+
context.addIssue({
|
|
19010
|
+
code: "custom",
|
|
19011
|
+
path: ["line"],
|
|
19012
|
+
message: "must match the top-level line state"
|
|
19013
|
+
});
|
|
19014
|
+
}
|
|
19015
|
+
});
|
|
19016
|
+
var SetupVoiceCallsRequest = external_exports.object({ requestId: external_exports.uuid() }).strict();
|
|
19017
|
+
var SetVoiceCallsEnabledRequest = external_exports.object({ enabled: external_exports.boolean(), expectedRevision: external_exports.number().int().min(0) }).strict();
|
|
19018
|
+
var StartVoiceCallerVerificationRequest = external_exports.object({
|
|
19019
|
+
requestId: external_exports.uuid(),
|
|
19020
|
+
phoneNumber: VoicePhoneNumberInput,
|
|
19021
|
+
/** Omit to verify a number for the authenticated member. */
|
|
19022
|
+
memberId: MemberId.optional()
|
|
19023
|
+
}).strict();
|
|
19024
|
+
var StartVoiceCallerVerificationResponse = external_exports.object({ verificationId: VoiceCallerId, caller: VoiceCallerProjection }).strict();
|
|
19025
|
+
var CheckVoiceCallerVerificationRequest = external_exports.object({
|
|
19026
|
+
verificationId: VoiceCallerId,
|
|
19027
|
+
/** Verification codes are transported to Twilio and are never persisted. */
|
|
19028
|
+
code: external_exports.string().trim().regex(/^\d{4,10}$/, "enter the code from the text message")
|
|
19029
|
+
}).strict();
|
|
19030
|
+
var ResendVoiceCallerVerificationRequest = external_exports.object({ requestId: external_exports.uuid(), verificationId: VoiceCallerId }).strict();
|
|
19031
|
+
var RemoveVoiceCallerResponse = external_exports.object({ removed: external_exports.literal(true) }).strict();
|
|
19032
|
+
var StartVoiceCallRequest = external_exports.object({
|
|
19033
|
+
requestId: external_exports.uuid(),
|
|
19034
|
+
/** Must be a verified number owned by the authenticated member. */
|
|
19035
|
+
callerId: VoiceCallerId,
|
|
19036
|
+
/** Present when the call continues the exact open Manager Task/chat. */
|
|
19037
|
+
conversationId: ConversationId.optional()
|
|
19038
|
+
}).strict();
|
|
19039
|
+
var VoiceCallStatus = external_exports.enum(["calling", "connected", "ending", "ended", "failed"]);
|
|
19040
|
+
var VoiceCallProjection = external_exports.object({
|
|
19041
|
+
id: VoiceCallId,
|
|
19042
|
+
status: VoiceCallStatus,
|
|
19043
|
+
callerId: VoiceCallerId,
|
|
19044
|
+
/** Bound as soon as a new-task call is admitted; never waits for first speech. */
|
|
19045
|
+
conversationId: ConversationId.nullable(),
|
|
19046
|
+
startedAt: IsoDate2,
|
|
19047
|
+
/**
|
|
19048
|
+
* Earliest time this member may start another call under the one-minute
|
|
19049
|
+
* admission cooldown. Null means this attempt did not consume cooldown
|
|
19050
|
+
* (for example, the carrier definitively rejected it before ringing).
|
|
19051
|
+
* Optional only for rolling compatibility with an older cloud response.
|
|
19052
|
+
*/
|
|
19053
|
+
outboundCooldownUntil: IsoDate2.nullable().optional(),
|
|
19054
|
+
maxCallMinutes: external_exports.literal(VOICE_MAX_CALL_MINUTES),
|
|
19055
|
+
/** Server-derived; only the mapped caller may end this call. */
|
|
19056
|
+
canEnd: external_exports.boolean()
|
|
19057
|
+
}).strict();
|
|
19058
|
+
var VoiceCurrentCallQuery = external_exports.object({
|
|
19059
|
+
conversationId: ConversationId.optional(),
|
|
19060
|
+
/** Exact idempotency fence used only to recover this member's uncertain start. */
|
|
19061
|
+
requestId: external_exports.uuid().optional()
|
|
19062
|
+
}).strict().refine((query) => !(query.conversationId && query.requestId), {
|
|
19063
|
+
message: "choose a Task or an exact call request, not both"
|
|
19064
|
+
});
|
|
19065
|
+
var VoiceCurrentCallResponse = external_exports.object({ call: VoiceCallProjection.nullable() }).strict();
|
|
19066
|
+
var EndVoiceCallResponse = external_exports.object({ ended: external_exports.literal(true) }).strict();
|
|
19067
|
+
var BrowserVoiceReadinessResponse = external_exports.object({
|
|
19068
|
+
ready: external_exports.boolean(),
|
|
19069
|
+
reason: external_exports.enum(["manager_unavailable", "voice_unavailable", "voice_in_use"]).nullable()
|
|
19070
|
+
}).strict().superRefine((value, context) => {
|
|
19071
|
+
if (value.ready !== (value.reason === null)) {
|
|
19072
|
+
context.addIssue({
|
|
19073
|
+
code: "custom",
|
|
19074
|
+
path: ["reason"],
|
|
19075
|
+
message: "must be null exactly when browser Voice mode is ready"
|
|
19076
|
+
});
|
|
19077
|
+
}
|
|
19078
|
+
});
|
|
19079
|
+
var BROWSER_VOICE_MAX_SDP_BYTES = 131072;
|
|
19080
|
+
function isAudioOnlyWebRtcSessionDescription(value) {
|
|
19081
|
+
if (!/^v=0(?:\r?\n)/.test(value) || value.includes("\0") || /\r(?!\n)/.test(value)) {
|
|
19082
|
+
return false;
|
|
19083
|
+
}
|
|
19084
|
+
const media = value.split(/\r?\n/).filter((line) => line.startsWith("m="));
|
|
19085
|
+
if (media.length !== 1 || !/^m=audio [1-9]\d* UDP\/TLS\/RTP\/SAVPF(?: \d+)+$/.test(media[0])) {
|
|
19086
|
+
return false;
|
|
19087
|
+
}
|
|
19088
|
+
const forbiddenAttribute = /^(?:a=inactive|a=(?:sctp-port|sctpmap|dcmap|dcsa|max-message-size):)/i;
|
|
19089
|
+
return !value.split(/\r?\n/).some((line) => forbiddenAttribute.test(line) || /webrtc-datachannel/i.test(line));
|
|
19090
|
+
}
|
|
19091
|
+
var BrowserVoiceSessionDescription = external_exports.string().min(4).max(BROWSER_VOICE_MAX_SDP_BYTES).refine((value) => new TextEncoder().encode(value).byteLength <= BROWSER_VOICE_MAX_SDP_BYTES, {
|
|
19092
|
+
message: "must fit within the WebRTC session description limit"
|
|
19093
|
+
}).refine(isAudioOnlyWebRtcSessionDescription, {
|
|
19094
|
+
message: "must be an audio-only WebRTC session description"
|
|
19095
|
+
});
|
|
19096
|
+
var BrowserVoiceInitialRunner = TaskRunnerSelection.refine(
|
|
19097
|
+
(selection) => selection.type !== void 0 || selection.model !== void 0 || selection.effort !== void 0,
|
|
19098
|
+
"choose at least one runtime preference"
|
|
19099
|
+
);
|
|
19100
|
+
var StartBrowserVoiceSessionRequest = external_exports.object({
|
|
19101
|
+
/** Stable client fence. A provider-create ambiguity is never resubmitted under this id. */
|
|
19102
|
+
requestId: external_exports.uuid(),
|
|
19103
|
+
offerSdp: BrowserVoiceSessionDescription,
|
|
19104
|
+
conversationId: ConversationId.optional(),
|
|
19105
|
+
/** Manager Browser teammate selected for spoken Browser-directed turns. */
|
|
19106
|
+
browserAgentId: AgentId.optional(),
|
|
19107
|
+
/** New-Task-only one-use runtime for its first successful delegation. */
|
|
19108
|
+
initialDelegation: external_exports.object({ runner: BrowserVoiceInitialRunner }).strict().optional()
|
|
19109
|
+
}).strict().superRefine((value, context) => {
|
|
19110
|
+
if (value.conversationId && value.initialDelegation) {
|
|
19111
|
+
context.addIssue({
|
|
19112
|
+
code: "custom",
|
|
19113
|
+
path: ["initialDelegation"],
|
|
19114
|
+
message: "is available only when voice mode opens a new Task"
|
|
19115
|
+
});
|
|
19116
|
+
}
|
|
19117
|
+
});
|
|
19118
|
+
var BrowserVoiceSessionStatus = external_exports.enum([
|
|
19119
|
+
"connecting",
|
|
19120
|
+
"connected",
|
|
19121
|
+
"ending",
|
|
19122
|
+
"ended",
|
|
19123
|
+
"failed"
|
|
19124
|
+
]);
|
|
19125
|
+
var BrowserVoiceSessionProjection = external_exports.object({
|
|
19126
|
+
id: VoiceCallId,
|
|
19127
|
+
status: BrowserVoiceSessionStatus,
|
|
19128
|
+
conversationId: ConversationId.nullable(),
|
|
19129
|
+
startedAt: IsoDate2,
|
|
19130
|
+
expiresAt: IsoDate2,
|
|
19131
|
+
/** Server-derived from the authenticated member binding and terminal state. */
|
|
19132
|
+
canEnd: external_exports.boolean()
|
|
19133
|
+
}).strict();
|
|
19134
|
+
var StartBrowserVoiceSessionResponse = external_exports.object({
|
|
19135
|
+
session: BrowserVoiceSessionProjection,
|
|
19136
|
+
/** Applied directly to the browser peer connection and never persisted by Zixt. */
|
|
19137
|
+
answerSdp: BrowserVoiceSessionDescription
|
|
19138
|
+
}).strict();
|
|
19139
|
+
var AckBrowserVoiceSessionRequest = external_exports.object({ requestId: external_exports.uuid() }).strict();
|
|
19140
|
+
var AckBrowserVoiceSessionResponse = external_exports.object({ session: BrowserVoiceSessionProjection }).strict();
|
|
19141
|
+
var BrowserVoiceCurrentSessionQuery = external_exports.object({
|
|
19142
|
+
conversationId: ConversationId.optional(),
|
|
19143
|
+
/** Recover the exact uncertain start instead of whichever session is current. */
|
|
19144
|
+
requestId: external_exports.uuid().optional()
|
|
19145
|
+
}).strict().refine((query) => !(query.conversationId && query.requestId), {
|
|
19146
|
+
message: "choose a Task or an exact session request, not both"
|
|
19147
|
+
});
|
|
19148
|
+
var BrowserVoiceCurrentSessionResponse = external_exports.object({ session: BrowserVoiceSessionProjection.nullable() }).strict();
|
|
19149
|
+
var EndBrowserVoiceSessionResponse = external_exports.object({ ended: external_exports.literal(true) }).strict();
|
|
19150
|
+
var BrowserVoiceCaption = external_exports.string().max(4e3);
|
|
19151
|
+
var BrowserVoiceCallerIdentity = {
|
|
19152
|
+
// Zixt-scoped presentation identity only. Provider item ids stay inside the
|
|
19153
|
+
// voice service, and both fields remain optional across rolling deploys.
|
|
19154
|
+
utteranceId: external_exports.string().min(1).max(128).regex(/^[A-Za-z0-9_-]+$/).optional(),
|
|
19155
|
+
utteranceOrdinal: external_exports.number().int().min(1).optional()
|
|
19156
|
+
};
|
|
19157
|
+
var BrowserVoicePresentationFrame = external_exports.discriminatedUnion("type", [
|
|
19158
|
+
external_exports.object({ type: external_exports.literal("caller_speech_started"), ...BrowserVoiceCallerIdentity }).strict(),
|
|
19159
|
+
external_exports.object({ type: external_exports.literal("caller_speech_stopped"), ...BrowserVoiceCallerIdentity }).strict(),
|
|
19160
|
+
external_exports.object({
|
|
19161
|
+
type: external_exports.literal("user_caption"),
|
|
19162
|
+
text: BrowserVoiceCaption,
|
|
19163
|
+
final: external_exports.boolean(),
|
|
19164
|
+
...BrowserVoiceCallerIdentity
|
|
19165
|
+
}).strict(),
|
|
19166
|
+
external_exports.object({
|
|
19167
|
+
type: external_exports.literal("manager_speech_started"),
|
|
19168
|
+
speechId: VoiceTurnId,
|
|
19169
|
+
text: BrowserVoiceCaption
|
|
19170
|
+
}).strict(),
|
|
19171
|
+
external_exports.object({ type: external_exports.literal("manager_speech_stopped"), speechId: VoiceTurnId }).strict(),
|
|
19172
|
+
external_exports.object({ type: external_exports.literal("manager_speech_failed"), speechId: VoiceTurnId }).strict(),
|
|
19173
|
+
external_exports.object({ type: external_exports.literal("manager_speech_idle") }).strict(),
|
|
19174
|
+
external_exports.object({ type: external_exports.literal("transcription_failed"), ...BrowserVoiceCallerIdentity }).strict(),
|
|
19175
|
+
external_exports.object({ type: external_exports.literal("session_ended") }).strict(),
|
|
19176
|
+
external_exports.object({ type: external_exports.literal("session_failed") }).strict()
|
|
19177
|
+
]);
|
|
19178
|
+
var InterruptBrowserVoiceSessionRequest = external_exports.object({ speechId: VoiceTurnId }).strict();
|
|
19179
|
+
var InterruptBrowserVoiceSessionResponse = external_exports.object({ interrupted: external_exports.boolean() }).strict();
|
|
19180
|
+
|
|
18934
19181
|
// ../../packages/contracts/src/slack.ts
|
|
18935
19182
|
var SlackInstallationProjection = external_exports.object({
|
|
18936
19183
|
id: external_exports.string(),
|