@zixt/host 0.0.47 → 0.0.49

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.
Files changed (2) hide show
  1. package/dist/index.js +293 -4
  2. 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.47",
34
+ version: "0.0.49",
35
35
  type: "module",
36
36
  exports: {
37
37
  ".": "./src/client.ts",
@@ -14657,10 +14657,22 @@ var ID_PREFIXES = {
14657
14657
  conversation: "cnv",
14658
14658
  /** One immutable Conversation timeline entry. */
14659
14659
  conversationEvent: "cve",
14660
+ /** One human-confirmed integration action prepared by the Manager. */
14661
+ managerIntegrationAction: "mia",
14660
14662
  /** One Manager inference call's token-metering row (MG-8). */
14661
14663
  managerUsage: "mgu",
14662
14664
  /** One ordered Manager reply awaiting Slack delivery. */
14663
- managerSlackOutbox: "mso"
14665
+ managerSlackOutbox: "mso",
14666
+ /** One organization phone line that reaches its Manager. */
14667
+ voiceLine: "vln",
14668
+ /** One member-owned phone number admitted to Manager calls. */
14669
+ voiceCaller: "vcr",
14670
+ /** One live or historical phone call with the Manager. */
14671
+ voiceCall: "vca",
14672
+ /** One durable caller-transcript or Manager-speech delivery. */
14673
+ voiceTurn: "vtr",
14674
+ /** One signed voice-provider webhook receipt. */
14675
+ voiceWebhookEvent: "vwe"
14664
14676
  };
14665
14677
  var idPattern = (prefix) => new RegExp(`^${prefix}_[0-9a-f]{32}$`);
14666
14678
  function newId(prefix) {
@@ -14687,6 +14699,18 @@ var ManagerId = idSchema(ID_PREFIXES.manager, "manager id");
14687
14699
  var ManagerMemoryId = idSchema(ID_PREFIXES.managerMemory, "manager memory id");
14688
14700
  var ConversationId = idSchema(ID_PREFIXES.conversation, "conversation id");
14689
14701
  var ConversationEventId = idSchema(ID_PREFIXES.conversationEvent, "conversation event id");
14702
+ var ManagerIntegrationActionId = idSchema(
14703
+ ID_PREFIXES.managerIntegrationAction,
14704
+ "Manager integration action id"
14705
+ );
14706
+ var VoiceLineId = idSchema(ID_PREFIXES.voiceLine, "voice line id");
14707
+ var VoiceCallerId = idSchema(ID_PREFIXES.voiceCaller, "voice caller id");
14708
+ var VoiceCallId = idSchema(ID_PREFIXES.voiceCall, "voice call id");
14709
+ var VoiceTurnId = idSchema(ID_PREFIXES.voiceTurn, "voice turn id");
14710
+ var VoiceWebhookEventId = idSchema(
14711
+ ID_PREFIXES.voiceWebhookEvent,
14712
+ "voice webhook event id"
14713
+ );
14690
14714
 
14691
14715
  // ../../packages/contracts/src/browser.ts
14692
14716
  var BrowserViewport = external_exports.object({
@@ -18752,7 +18776,7 @@ var ListManagerMemoriesResponse = external_exports.object({
18752
18776
  memories: external_exports.array(ManagerMemoryProjection).max(MANAGER_MEMORY_MAX_ITEMS),
18753
18777
  limit: external_exports.number().int().min(1)
18754
18778
  }).strict();
18755
- var ConversationChannel = external_exports.enum(["web", "slack", "whatsapp"]);
18779
+ var ConversationChannel = external_exports.enum(["web", "slack", "whatsapp", "phone"]);
18756
18780
  var ConversationStatus = external_exports.enum(["idle", "thinking"]);
18757
18781
  var ConversationProjection = external_exports.object({
18758
18782
  id: ConversationId,
@@ -18790,6 +18814,10 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
18790
18814
  text: external_exports.string(),
18791
18815
  /** Display attribution only; authentication subjects remain internal. */
18792
18816
  author: external_exports.object({ displayName: external_exports.string().nullable() }).strict(),
18817
+ /** Transport that supplied this turn; legacy events omit it. */
18818
+ sourceChannel: ConversationChannel.optional(),
18819
+ /** Input affordance within the trusted transport; legacy/typed turns omit it. */
18820
+ inputModality: external_exports.literal("voice").optional(),
18793
18821
  attachments: external_exports.array(TaskAttachmentRef).max(TASK_MESSAGE_MAX_ATTACHMENTS).optional()
18794
18822
  }).strict(),
18795
18823
  /** The Manager's prose reply. */
@@ -18801,7 +18829,9 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
18801
18829
  tool: external_exports.string(),
18802
18830
  summary: external_exports.string(),
18803
18831
  taskId: TaskId.nullable(),
18804
- agentId: AgentId.nullable()
18832
+ agentId: AgentId.nullable(),
18833
+ /** Present only for a confirmation card; OAuth authority never appears here. */
18834
+ integrationActionId: ManagerIntegrationActionId.nullable().optional()
18805
18835
  }).strict(),
18806
18836
  /** A mirrored child-Task event: what the teammate wrote or became. */
18807
18837
  external_exports.object({
@@ -18823,6 +18853,40 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
18823
18853
  /** A Manager loop failure a person should see (provider outage, refusal). */
18824
18854
  external_exports.object({ ...conversationEventBase, kind: external_exports.literal("error"), message: external_exports.string() }).strict()
18825
18855
  ]);
18856
+ var ManagerIntegrationProvider = external_exports.enum(["slack"]);
18857
+ var ManagerIntegrationOperation = external_exports.enum(["connect", "reconnect", "check", "remove"]);
18858
+ var ManagerIntegrationActionStatus = external_exports.enum([
18859
+ "awaiting_confirmation",
18860
+ "working",
18861
+ "authorizing",
18862
+ "completed",
18863
+ "cancelled",
18864
+ "failed",
18865
+ "expired"
18866
+ ]);
18867
+ var ManagerIntegrationActionProjection = external_exports.object({
18868
+ id: ManagerIntegrationActionId,
18869
+ conversationId: ConversationId,
18870
+ provider: ManagerIntegrationProvider,
18871
+ providerName: external_exports.string().min(1).max(80),
18872
+ operation: ManagerIntegrationOperation,
18873
+ status: ManagerIntegrationActionStatus,
18874
+ title: external_exports.string().min(1).max(200),
18875
+ description: external_exports.string().min(1).max(1e3),
18876
+ confirmLabel: external_exports.string().min(1).max(100),
18877
+ outcome: external_exports.string().max(1e3).nullable(),
18878
+ createdAt: external_exports.string(),
18879
+ expiresAt: external_exports.string()
18880
+ }).strict();
18881
+ var ManagerIntegrationOAuthStart = external_exports.object({
18882
+ authorizeUrl: external_exports.url().max(4e3),
18883
+ callbackOrigin: external_exports.url().max(2e3)
18884
+ }).strict();
18885
+ var ConfirmManagerIntegrationActionRequest = external_exports.object({ requestId: external_exports.string().uuid() }).strict();
18886
+ var ManagerIntegrationActionResponse = external_exports.object({
18887
+ action: ManagerIntegrationActionProjection,
18888
+ oauth: ManagerIntegrationOAuthStart.nullable()
18889
+ }).strict();
18826
18890
  var NonEmptyTaskRunnerSelection = TaskRunnerSelection.refine(
18827
18891
  (selection) => selection.type !== void 0 || selection.model !== void 0 || selection.effort !== void 0,
18828
18892
  "choose at least one runtime preference"
@@ -18931,6 +18995,231 @@ var ManagerStreamFrame = external_exports.discriminatedUnion("type", [
18931
18995
  external_exports.object({ type: external_exports.literal("conversation"), conversation: ConversationProjection }).strict()
18932
18996
  ]);
18933
18997
 
18998
+ // ../../packages/contracts/src/voice.ts
18999
+ var VOICE_MAX_CALL_MINUTES = 30;
19000
+ var VoiceE164Number = external_exports.string().regex(/^\+[1-9]\d{7,14}$/, "must be an international phone number");
19001
+ var VoicePhoneNumberInput = external_exports.string().trim().min(7).max(32).refine(
19002
+ (value) => /^\+[1-9]\d{7,14}$/.test(value.replace(/[\s()\-.]/g, "")),
19003
+ "must include a country code"
19004
+ );
19005
+ var VoiceAvailability = external_exports.enum(["unavailable", "setup_required", "setting_up", "ready", "needs_attention"]).describe(
19006
+ "Local Zixt deployment and line configuration state; ready does not prove remote webhook delivery"
19007
+ );
19008
+ var VoiceLineProjection = external_exports.object({
19009
+ id: VoiceLineId,
19010
+ /** Full public number: a member needs this value in order to call it. */
19011
+ dialInNumber: VoiceE164Number,
19012
+ enabled: external_exports.boolean(),
19013
+ readiness: external_exports.enum(["setting_up", "ready", "needs_attention"]).describe("Local line-resource state; ready does not prove remote webhook delivery")
19014
+ }).strict();
19015
+ var VoiceCallerProjection = external_exports.object({
19016
+ id: VoiceCallerId,
19017
+ memberId: MemberId,
19018
+ memberDisplayName: external_exports.string().min(1).max(120),
19019
+ /** Masked E.164 (for example +1 ••• ••• 7767), never the lookup key. */
19020
+ phoneNumber: external_exports.string().regex(/^\+(?:1|••) ••• ••• \d{4}$/, "must be a masked phone number"),
19021
+ status: external_exports.enum(["sending", "pending", "verified", "failed"]),
19022
+ verifiedAt: external_exports.string().nullable(),
19023
+ verificationExpiresAt: external_exports.string().nullable(),
19024
+ /** Member can manage their own rows; Admin/Owner can manage every row. */
19025
+ canManage: external_exports.boolean(),
19026
+ isCurrentMember: external_exports.boolean()
19027
+ }).strict();
19028
+ var VoiceSettingsResponse = external_exports.object({
19029
+ availability: VoiceAvailability,
19030
+ enabled: external_exports.boolean(),
19031
+ dialInNumber: VoiceE164Number.nullable(),
19032
+ line: VoiceLineProjection.nullable(),
19033
+ callers: external_exports.array(VoiceCallerProjection).max(500),
19034
+ /** Admin/Owner can set up or enable the organization line. */
19035
+ canManageLine: external_exports.boolean(),
19036
+ /** Admin/Owner can start verification for another member. */
19037
+ canManageCallers: external_exports.boolean(),
19038
+ currentMemberId: MemberId,
19039
+ maxCallMinutes: external_exports.literal(VOICE_MAX_CALL_MINUTES),
19040
+ revision: external_exports.number().int().min(0)
19041
+ }).strict().superRefine((settings, context) => {
19042
+ if (!settings.line && settings.dialInNumber !== null) {
19043
+ context.addIssue({
19044
+ code: "custom",
19045
+ path: ["dialInNumber"],
19046
+ message: "requires a line"
19047
+ });
19048
+ return;
19049
+ }
19050
+ if (settings.line && (settings.line.dialInNumber !== settings.dialInNumber || settings.line.enabled !== settings.enabled)) {
19051
+ context.addIssue({
19052
+ code: "custom",
19053
+ path: ["line"],
19054
+ message: "must match the top-level line state"
19055
+ });
19056
+ }
19057
+ });
19058
+ var SetupVoiceCallsRequest = external_exports.object({ requestId: external_exports.uuid() }).strict();
19059
+ var SetVoiceCallsEnabledRequest = external_exports.object({ enabled: external_exports.boolean(), expectedRevision: external_exports.number().int().min(0) }).strict();
19060
+ var StartVoiceCallerVerificationRequest = external_exports.object({
19061
+ requestId: external_exports.uuid(),
19062
+ phoneNumber: VoicePhoneNumberInput,
19063
+ /** Omit to verify a number for the authenticated member. */
19064
+ memberId: MemberId.optional()
19065
+ }).strict();
19066
+ var StartVoiceCallerVerificationResponse = external_exports.object({ verificationId: VoiceCallerId, caller: VoiceCallerProjection }).strict();
19067
+ var CheckVoiceCallerVerificationRequest = external_exports.object({
19068
+ verificationId: VoiceCallerId,
19069
+ /** Verification codes are transported to Twilio and are never persisted. */
19070
+ code: external_exports.string().trim().regex(/^\d{4,10}$/, "enter the code from the text message")
19071
+ }).strict();
19072
+ var ResendVoiceCallerVerificationRequest = external_exports.object({ requestId: external_exports.uuid(), verificationId: VoiceCallerId }).strict();
19073
+ var RemoveVoiceCallerResponse = external_exports.object({ removed: external_exports.literal(true) }).strict();
19074
+ var StartVoiceCallRequest = external_exports.object({
19075
+ requestId: external_exports.uuid(),
19076
+ /** Must be a verified number owned by the authenticated member. */
19077
+ callerId: VoiceCallerId,
19078
+ /** Present when the call continues the exact open Manager Task/chat. */
19079
+ conversationId: ConversationId.optional()
19080
+ }).strict();
19081
+ var VoiceCallStatus = external_exports.enum(["calling", "connected", "ending", "ended", "failed"]);
19082
+ var VoiceCallProjection = external_exports.object({
19083
+ id: VoiceCallId,
19084
+ status: VoiceCallStatus,
19085
+ callerId: VoiceCallerId,
19086
+ /** Bound as soon as a new-task call is admitted; never waits for first speech. */
19087
+ conversationId: ConversationId.nullable(),
19088
+ startedAt: IsoDate2,
19089
+ /**
19090
+ * Earliest time this member may start another call under the one-minute
19091
+ * admission cooldown. Null means this attempt did not consume cooldown
19092
+ * (for example, the carrier definitively rejected it before ringing).
19093
+ * Optional only for rolling compatibility with an older cloud response.
19094
+ */
19095
+ outboundCooldownUntil: IsoDate2.nullable().optional(),
19096
+ maxCallMinutes: external_exports.literal(VOICE_MAX_CALL_MINUTES),
19097
+ /** Server-derived; only the mapped caller may end this call. */
19098
+ canEnd: external_exports.boolean()
19099
+ }).strict();
19100
+ var VoiceCurrentCallQuery = external_exports.object({
19101
+ conversationId: ConversationId.optional(),
19102
+ /** Exact idempotency fence used only to recover this member's uncertain start. */
19103
+ requestId: external_exports.uuid().optional()
19104
+ }).strict().refine((query) => !(query.conversationId && query.requestId), {
19105
+ message: "choose a Task or an exact call request, not both"
19106
+ });
19107
+ var VoiceCurrentCallResponse = external_exports.object({ call: VoiceCallProjection.nullable() }).strict();
19108
+ var EndVoiceCallResponse = external_exports.object({ ended: external_exports.literal(true) }).strict();
19109
+ var BrowserVoiceReadinessResponse = external_exports.object({
19110
+ ready: external_exports.boolean(),
19111
+ reason: external_exports.enum(["manager_unavailable", "voice_unavailable", "voice_in_use"]).nullable()
19112
+ }).strict().superRefine((value, context) => {
19113
+ if (value.ready !== (value.reason === null)) {
19114
+ context.addIssue({
19115
+ code: "custom",
19116
+ path: ["reason"],
19117
+ message: "must be null exactly when browser Voice mode is ready"
19118
+ });
19119
+ }
19120
+ });
19121
+ var BROWSER_VOICE_MAX_SDP_BYTES = 131072;
19122
+ function isAudioOnlyWebRtcSessionDescription(value) {
19123
+ if (!/^v=0(?:\r?\n)/.test(value) || value.includes("\0") || /\r(?!\n)/.test(value)) {
19124
+ return false;
19125
+ }
19126
+ const media = value.split(/\r?\n/).filter((line) => line.startsWith("m="));
19127
+ if (media.length !== 1 || !/^m=audio [1-9]\d* UDP\/TLS\/RTP\/SAVPF(?: \d+)+$/.test(media[0])) {
19128
+ return false;
19129
+ }
19130
+ const forbiddenAttribute = /^(?:a=inactive|a=(?:sctp-port|sctpmap|dcmap|dcsa|max-message-size):)/i;
19131
+ return !value.split(/\r?\n/).some((line) => forbiddenAttribute.test(line) || /webrtc-datachannel/i.test(line));
19132
+ }
19133
+ 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, {
19134
+ message: "must fit within the WebRTC session description limit"
19135
+ }).refine(isAudioOnlyWebRtcSessionDescription, {
19136
+ message: "must be an audio-only WebRTC session description"
19137
+ });
19138
+ var BrowserVoiceInitialRunner = TaskRunnerSelection.refine(
19139
+ (selection) => selection.type !== void 0 || selection.model !== void 0 || selection.effort !== void 0,
19140
+ "choose at least one runtime preference"
19141
+ );
19142
+ var StartBrowserVoiceSessionRequest = external_exports.object({
19143
+ /** Stable client fence. A provider-create ambiguity is never resubmitted under this id. */
19144
+ requestId: external_exports.uuid(),
19145
+ offerSdp: BrowserVoiceSessionDescription,
19146
+ conversationId: ConversationId.optional(),
19147
+ /** Manager Browser teammate selected for spoken Browser-directed turns. */
19148
+ browserAgentId: AgentId.optional(),
19149
+ /** New-Task-only one-use runtime for its first successful delegation. */
19150
+ initialDelegation: external_exports.object({ runner: BrowserVoiceInitialRunner }).strict().optional()
19151
+ }).strict().superRefine((value, context) => {
19152
+ if (value.conversationId && value.initialDelegation) {
19153
+ context.addIssue({
19154
+ code: "custom",
19155
+ path: ["initialDelegation"],
19156
+ message: "is available only when voice mode opens a new Task"
19157
+ });
19158
+ }
19159
+ });
19160
+ var BrowserVoiceSessionStatus = external_exports.enum([
19161
+ "connecting",
19162
+ "connected",
19163
+ "ending",
19164
+ "ended",
19165
+ "failed"
19166
+ ]);
19167
+ var BrowserVoiceSessionProjection = external_exports.object({
19168
+ id: VoiceCallId,
19169
+ status: BrowserVoiceSessionStatus,
19170
+ conversationId: ConversationId.nullable(),
19171
+ startedAt: IsoDate2,
19172
+ expiresAt: IsoDate2,
19173
+ /** Server-derived from the authenticated member binding and terminal state. */
19174
+ canEnd: external_exports.boolean()
19175
+ }).strict();
19176
+ var StartBrowserVoiceSessionResponse = external_exports.object({
19177
+ session: BrowserVoiceSessionProjection,
19178
+ /** Applied directly to the browser peer connection and never persisted by Zixt. */
19179
+ answerSdp: BrowserVoiceSessionDescription
19180
+ }).strict();
19181
+ var AckBrowserVoiceSessionRequest = external_exports.object({ requestId: external_exports.uuid() }).strict();
19182
+ var AckBrowserVoiceSessionResponse = external_exports.object({ session: BrowserVoiceSessionProjection }).strict();
19183
+ var BrowserVoiceCurrentSessionQuery = external_exports.object({
19184
+ conversationId: ConversationId.optional(),
19185
+ /** Recover the exact uncertain start instead of whichever session is current. */
19186
+ requestId: external_exports.uuid().optional()
19187
+ }).strict().refine((query) => !(query.conversationId && query.requestId), {
19188
+ message: "choose a Task or an exact session request, not both"
19189
+ });
19190
+ var BrowserVoiceCurrentSessionResponse = external_exports.object({ session: BrowserVoiceSessionProjection.nullable() }).strict();
19191
+ var EndBrowserVoiceSessionResponse = external_exports.object({ ended: external_exports.literal(true) }).strict();
19192
+ var BrowserVoiceCaption = external_exports.string().max(4e3);
19193
+ var BrowserVoiceCallerIdentity = {
19194
+ // Zixt-scoped presentation identity only. Provider item ids stay inside the
19195
+ // voice service, and both fields remain optional across rolling deploys.
19196
+ utteranceId: external_exports.string().min(1).max(128).regex(/^[A-Za-z0-9_-]+$/).optional(),
19197
+ utteranceOrdinal: external_exports.number().int().min(1).optional()
19198
+ };
19199
+ var BrowserVoicePresentationFrame = external_exports.discriminatedUnion("type", [
19200
+ external_exports.object({ type: external_exports.literal("caller_speech_started"), ...BrowserVoiceCallerIdentity }).strict(),
19201
+ external_exports.object({ type: external_exports.literal("caller_speech_stopped"), ...BrowserVoiceCallerIdentity }).strict(),
19202
+ external_exports.object({
19203
+ type: external_exports.literal("user_caption"),
19204
+ text: BrowserVoiceCaption,
19205
+ final: external_exports.boolean(),
19206
+ ...BrowserVoiceCallerIdentity
19207
+ }).strict(),
19208
+ external_exports.object({
19209
+ type: external_exports.literal("manager_speech_started"),
19210
+ speechId: VoiceTurnId,
19211
+ text: BrowserVoiceCaption
19212
+ }).strict(),
19213
+ external_exports.object({ type: external_exports.literal("manager_speech_stopped"), speechId: VoiceTurnId }).strict(),
19214
+ external_exports.object({ type: external_exports.literal("manager_speech_failed"), speechId: VoiceTurnId }).strict(),
19215
+ external_exports.object({ type: external_exports.literal("manager_speech_idle") }).strict(),
19216
+ external_exports.object({ type: external_exports.literal("transcription_failed"), ...BrowserVoiceCallerIdentity }).strict(),
19217
+ external_exports.object({ type: external_exports.literal("session_ended") }).strict(),
19218
+ external_exports.object({ type: external_exports.literal("session_failed") }).strict()
19219
+ ]);
19220
+ var InterruptBrowserVoiceSessionRequest = external_exports.object({ speechId: VoiceTurnId }).strict();
19221
+ var InterruptBrowserVoiceSessionResponse = external_exports.object({ interrupted: external_exports.boolean() }).strict();
19222
+
18934
19223
  // ../../packages/contracts/src/slack.ts
18935
19224
  var SlackInstallationProjection = external_exports.object({
18936
19225
  id: external_exports.string(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.47",
3
+ "version": "0.0.49",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",