@skippr/live-agent-sdk 0.45.0 → 0.46.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.
@@ -8,14 +8,35 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/components/LiveAgent.tsx
10
10
  import { LiveKitRoom, RoomAudioRenderer } from "@livekit/components-react";
11
- import { useCallback as useCallback10, useMemo as useMemo5, useRef as useRef13, useState as useState15 } from "react";
11
+ import { useCallback as useCallback10, useMemo as useMemo6, useRef as useRef13, useState as useState15 } from "react";
12
12
 
13
13
  // src/context/LiveAgentContext.tsx
14
14
  import { createContext } from "react";
15
15
  var LiveAgentContext = createContext(null);
16
16
 
17
17
  // src/hooks/useAdoptionGoals.ts
18
- import { useCallback, useEffect, useState } from "react";
18
+ import { useCallback, useEffect, useMemo, useState } from "react";
19
+
20
+ // src/lib/hashMatch.ts
21
+ function globToRegExp(pattern) {
22
+ const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\*\\\*/g, ".*").replace(/\\\*/g, "[^/]*");
23
+ return new RegExp(`^${escaped}$`);
24
+ }
25
+ function normalizeHash(rawHash) {
26
+ return rawHash.replace(/^#/, "").toLowerCase();
27
+ }
28
+ function matchesHash(rawHash, matchType, hashPattern) {
29
+ const hash = normalizeHash(rawHash);
30
+ const pattern = hashPattern.toLowerCase();
31
+ switch (matchType) {
32
+ case "exact" /* Exact */:
33
+ return hash === pattern;
34
+ case "prefix" /* Prefix */:
35
+ return hash.startsWith(pattern);
36
+ case "glob" /* Glob */:
37
+ return globToRegExp(pattern).test(hash);
38
+ }
39
+ }
19
40
 
20
41
  // src/lib/navigation.ts
21
42
  var listeners = new Set;
@@ -62,7 +83,8 @@ function useAdoptionGoals({
62
83
  bearerToken,
63
84
  authedFetch
64
85
  }) {
65
- const [goals, setGoals] = useState([]);
86
+ const [candidates, setCandidates] = useState([]);
87
+ const [hash, setHash] = useState(window.location.hash);
66
88
  const match = useCallback(async () => {
67
89
  try {
68
90
  const resp = await authedFetch(`${API_URL}/v1/adoption/goals/match`, {
@@ -71,28 +93,30 @@ function useAdoptionGoals({
71
93
  body: JSON.stringify({ url: window.location.origin + window.location.pathname })
72
94
  });
73
95
  if (!resp.ok) {
74
- setGoals([]);
96
+ setCandidates([]);
75
97
  return;
76
98
  }
77
99
  const data = await resp.json();
78
- setGoals(Array.isArray(data?.goals) ? data.goals : []);
100
+ setCandidates(Array.isArray(data?.goals) ? data.goals : []);
79
101
  } catch (e) {
80
102
  console.warn("[Skippr] adoption match failed", e);
81
- setGoals([]);
103
+ setCandidates([]);
82
104
  }
83
105
  }, [authedFetch]);
84
106
  useEffect(() => {
85
107
  if (!enabled || !bearerToken) {
86
- setGoals([]);
108
+ setCandidates([]);
87
109
  return;
88
110
  }
89
111
  match();
90
112
  let lastPath = window.location.pathname;
91
113
  let timer;
92
114
  const unsubscribe = subscribeToLocationChange(() => {
115
+ setHash(window.location.hash);
93
116
  if (window.location.pathname === lastPath)
94
117
  return;
95
118
  lastPath = window.location.pathname;
119
+ setCandidates([]);
96
120
  if (timer)
97
121
  clearTimeout(timer);
98
122
  timer = setTimeout(() => {
@@ -105,6 +129,12 @@ function useAdoptionGoals({
105
129
  unsubscribe();
106
130
  };
107
131
  }, [enabled, bearerToken, match]);
132
+ const goals = useMemo(() => {
133
+ const hashSpecific = candidates.filter((goal) => goal.hashPattern !== null && matchesHash(hash, goal.matchType, goal.hashPattern));
134
+ if (hashSpecific.length > 0)
135
+ return hashSpecific;
136
+ return candidates.filter((goal) => goal.hashPattern === null);
137
+ }, [candidates, hash]);
108
138
  const postStatus = useCallback((goalId, status) => {
109
139
  authedFetch(`${API_URL}/v1/adoption/goals/${goalId}/status`, {
110
140
  method: "POST",
@@ -113,7 +143,7 @@ function useAdoptionGoals({
113
143
  }).catch((e) => console.warn("[Skippr] adoption status update failed", e));
114
144
  }, [authedFetch]);
115
145
  const dismissGoal = useCallback((goalId) => {
116
- setGoals((prev) => prev.filter((goal) => goal.goalId !== goalId));
146
+ setCandidates((prev) => prev.filter((goal) => goal.goalId !== goalId));
117
147
  postStatus(goalId, "dismissed" /* Dismissed */);
118
148
  }, [postStatus]);
119
149
  const attendGoal = useCallback((goalId) => {
@@ -649,13 +679,6 @@ function useSession({
649
679
  };
650
680
  }
651
681
 
652
- // src/lib/agentMode.ts
653
- var AGENT_MODE = {
654
- Standard: "standard",
655
- AlwaysOn: "always_on"
656
- };
657
- var AGENT_MODES = Object.values(AGENT_MODE);
658
-
659
682
  // src/lib/constants.ts
660
683
  var SIDEBAR_WIDTH = 360;
661
684
  var WIDGET_ROOT_ID = "skippr-sdk-root";
@@ -667,6 +690,13 @@ var HIGHLIGHT_TOPIC = "skippr.highlight";
667
690
  var PAGE_ACTIONS_TOPIC = "skippr.page-actions";
668
691
  var NAME_MAX_CHARS = 80;
669
692
 
693
+ // src/lib/agentMode.ts
694
+ var AGENT_MODE = {
695
+ Standard: "standard",
696
+ AlwaysOn: "always_on"
697
+ };
698
+ var AGENT_MODES = Object.values(AGENT_MODE);
699
+
670
700
  // src/lib/sessionStatus.ts
671
701
  var SESSION_STATUS = {
672
702
  pending: "pending",
@@ -1673,7 +1703,7 @@ var hasA11yProp = (props) => {
1673
1703
  };
1674
1704
 
1675
1705
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/context.js
1676
- import { createContext as createContext2, useContext, useMemo, createElement } from "react";
1706
+ import { createContext as createContext2, useContext, useMemo as useMemo2, createElement } from "react";
1677
1707
  var LucideContext = createContext2({});
1678
1708
  var useLucideContext = () => useContext(LucideContext);
1679
1709
 
@@ -3054,11 +3084,11 @@ function ShadowHost({ children }) {
3054
3084
  import { useContext as useContext6, useEffect as useEffect19 } from "react";
3055
3085
 
3056
3086
  // src/hooks/useCombinedMessages.ts
3057
- import { useContext as useContext4, useMemo as useMemo4 } from "react";
3087
+ import { useContext as useContext4, useMemo as useMemo5 } from "react";
3058
3088
 
3059
3089
  // src/hooks/useChatMessages.ts
3060
3090
  import { useChat, useLocalParticipant as useLocalParticipant4 } from "@livekit/components-react/hooks";
3061
- import { useMemo as useMemo2 } from "react";
3091
+ import { useMemo as useMemo3 } from "react";
3062
3092
 
3063
3093
  // src/lib/filterSystemMessages.ts
3064
3094
  var SYSTEM_MESSAGE_PATTERN = /^\[\w+\]$/;
@@ -3071,7 +3101,7 @@ function useChatMessages() {
3071
3101
  const { chatMessages: rawMessages, send, isSending } = useChat();
3072
3102
  const { localParticipant } = useLocalParticipant4();
3073
3103
  const localIdentity = localParticipant.identity;
3074
- const chatMessages = useMemo2(() => {
3104
+ const chatMessages = useMemo3(() => {
3075
3105
  const sortedMessages = rawMessages.map((msg) => ({
3076
3106
  id: msg.id,
3077
3107
  role: msg.from?.identity === localIdentity ? "user" : "assistant",
@@ -3086,12 +3116,12 @@ function useChatMessages() {
3086
3116
 
3087
3117
  // src/hooks/useStreamingTranscript.ts
3088
3118
  import { useLocalParticipant as useLocalParticipant5, useTranscriptions } from "@livekit/components-react/hooks";
3089
- import { useMemo as useMemo3 } from "react";
3119
+ import { useMemo as useMemo4 } from "react";
3090
3120
  function useStreamingTranscript() {
3091
3121
  const transcriptions = useTranscriptions();
3092
3122
  const { localParticipant } = useLocalParticipant5();
3093
3123
  const localIdentity = localParticipant.identity;
3094
- const transcriptMessages = useMemo3(() => filterSystemMessages(transcriptions.filter((stream) => stream.text.trim().length > 0).map((stream) => ({
3124
+ const transcriptMessages = useMemo4(() => filterSystemMessages(transcriptions.filter((stream) => stream.text.trim().length > 0).map((stream) => ({
3095
3125
  id: stream.streamInfo.id,
3096
3126
  role: stream.participantInfo.identity === localIdentity ? "user" : "assistant",
3097
3127
  content: stream.text,
@@ -3123,14 +3153,14 @@ function useCombinedMessages() {
3123
3153
  const { chatMessages, sendChatMessage, isSendingChat } = useChatMessages();
3124
3154
  const { state: agentState } = useAgentVoiceState();
3125
3155
  const historyMessages = useContext4(LiveAgentContext)?.historyMessages ?? [];
3126
- const liveMessages = useMemo4(() => {
3156
+ const liveMessages = useMemo5(() => {
3127
3157
  if (chatMessages.length === 0)
3128
3158
  return transcriptMessages;
3129
3159
  if (transcriptMessages.length === 0)
3130
3160
  return chatMessages;
3131
3161
  return mergeChatsIntoTranscripts(transcriptMessages, chatMessages);
3132
3162
  }, [transcriptMessages, chatMessages]);
3133
- const allMessages = useMemo4(() => {
3163
+ const allMessages = useMemo5(() => {
3134
3164
  if (historyMessages.length === 0)
3135
3165
  return liveMessages;
3136
3166
  const seenIds = new Set(liveMessages.map((message) => message.id));
@@ -4581,17 +4611,16 @@ function LiveAgent(props) {
4581
4611
  bearerToken,
4582
4612
  authedFetch
4583
4613
  });
4584
- const hasAlwaysOnModule = availableModules.some((m) => m.mode === AGENT_MODE.AlwaysOn);
4585
4614
  const {
4586
4615
  goals: adoptionGoals,
4587
4616
  dismissGoal: dismissAdoptionGoal,
4588
4617
  attendGoal
4589
4618
  } = useAdoptionGoals({
4590
- enabled: !inSession && hasAlwaysOnModule,
4619
+ enabled: !inSession,
4591
4620
  bearerToken,
4592
4621
  authedFetch
4593
4622
  });
4594
- const activeModuleForAgent = useMemo5(() => {
4623
+ const activeModuleForAgent = useMemo6(() => {
4595
4624
  if (activeModule)
4596
4625
  return activeModule;
4597
4626
  if (!hostAgentId)
@@ -4599,7 +4628,7 @@ function LiveAgent(props) {
4599
4628
  return availableModules.find((m) => m.id === hostAgentId) ?? null;
4600
4629
  }, [activeModule, hostAgentId, availableModules]);
4601
4630
  const agentMode = activeModuleForAgent?.mode ?? null;
4602
- const resumableSession = useMemo5(() => getResumableSession(activeModuleForAgent), [activeModuleForAgent]);
4631
+ const resumableSession = useMemo6(() => getResumableSession(activeModuleForAgent), [activeModuleForAgent]);
4603
4632
  const resumeSession = useCallback10(async () => {
4604
4633
  if (!resumableSession)
4605
4634
  return;
@@ -4662,7 +4691,7 @@ function LiveAgent(props) {
4662
4691
  }, [minimizable]);
4663
4692
  const isConnected = connection !== null;
4664
4693
  const isAuthenticated = bearerToken !== null || auth.isAuthenticated;
4665
- const ctx = useMemo5(() => ({
4694
+ const ctx = useMemo6(() => ({
4666
4695
  connection,
4667
4696
  shouldConnect,
4668
4697
  isConnected,